Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 3559 → Rev 3555

/kernel/branches/net/applications/downloader/downloader.asm
0,0 → 1,1201
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2009-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; downloader.asm - HTTP client for KolibriOS ;;
;; ;;
;; Based on HTTPC.asm for menuetos by ville turjanmaa ;;
;; ;;
;; Programmers: Barsuk, Clevermouse, Marat Zakiyanov, ;;
;; Kirill Lipatov, dunkaist, HidnPlayr ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
URLMAXLEN = 1024
primary_buffer_size = 4096
 
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
format binary as ""
 
use32
org 0x0
 
db 'MENUET01' ; header
dd 0x01 ; header version
dd START ; entry point
dd IM_END ; image size
dd I_END ; required memory
dd I_END ; esp
dd params ; I_PARAM
dd 0x0 ; I_Path
 
include '../macros.inc'
include '../proc32.inc'
include '../network.inc'
include '../../../../../programs/develop/libraries/box_lib/trunk/box_lib.mac'
include '../dll.inc'
include '../debug-fdo.inc'
 
START:
 
mcall 68, 11 ; init heap so we can allocate memory dynamically
 
mcall 40, EV_STACK
 
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
 
; prepare webAddr area
 
mov al, ' '
mov edi, webAddr
mov ecx, URLMAXLEN
rep stosb
xor eax, eax
stosb
 
; prepare document area
mov al, '/'
mov edi, document
stosb
mov al, ' '
mov ecx, URLMAXLEN-1
rep stosb
 
call load_settings
cmp byte[params], 0
je prepare_event ;red
 
; we have an url
mov edi, document_user
mov al, ' '
mov ecx, URLMAXLEN
rep stosb
mov esi, params
mov edi, document_user
 
; copy untill space or 0
.copy_param:
mov al, [esi]
test al, al
jz .done
 
cmp al, ' '
jz .done_inc
 
mov [edi], al
inc esi
inc edi
jmp .copy_param
 
.done_inc:
 
; url is followed by shared memory name.
inc esi
.done:
mov [shared_name], esi
 
mov ah, 22 ; strange way to tell that socket should be opened...
call socket_commands
 
jmp still
 
prepare_event:
; Report events
; Stack 8 + defaults
mcall 40, 10100111b
 
red: ; redraw
call draw_window
 
still:
mcall 23, 1 ; wait here for event
cmp eax, 1 ; redraw request ?
je red
 
cmp eax, 2 ; key in buffer ?
je key
 
cmp eax, 3 ; button in buffer ?
je button
cmp eax, 6 ; mouse in buffer ?
je mouse
 
; Get the web page data from the remote server
cmp eax, 8
jne still
 
call read_incoming_data
 
cmp [status], 4
je .no_send
 
mov [onoff], 1
call send_request
 
.no_send:
call print_status
 
cmp [prev_status], 4
jne no_close
cmp [status], 4 ; connection closed by server
jbe no_close ; respond to connection close command
; draw page
call read_incoming_data
mcall close, [socketnum]
mov [onoff], 0
 
no_close:
jmp still
 
key:
mcall 2 ; read key
 
stdcall [edit_box_key], dword edit1
 
shr eax, 8
cmp eax, 13
je retkey
jmp still
 
button:
 
mcall 17 ; get id
cmp ah, 26
je save
cmp ah, 1 ; button id=1 ?
jne noclose
; DEBUGF 1, "Closing socket before exit...\n"
 
close_end_exit:
 
exit:
or eax, -1 ; close this program
mcall
mouse:
stdcall [edit_box_mouse], edit1
jmp still
 
save:
DEBUGF 1, "file saved\n"
mcall 70, fileinfo
 
mov ecx, [sc.work_text]
or ecx, 0x80000000
mcall 4, <10, 93>, , download_complete
 
jmp still
 
noclose:
cmp ah, 31
jne noup
sub [display_from], 20
jmp still
 
noup:
cmp ah, 32
jne nourl
add [display_from], 20
jmp still
 
 
retkey:
mov ah, 22 ; start load
 
nourl:
call socket_commands ; opens or closes the connection
jmp still
 
 
;****************************************************************************
; Function
; send_request
;
; Description
; Transmits the GET request to the server.
; This is done as GET then URL then HTTP/1.1', 13, 10, 13, 10 in 3 packets
;
;****************************************************************************
send_request:
pusha
mov esi, string0
mov edi, request
movsd
; If proxy is used, make absolute URI - prepend http://<host>
cmp byte[proxyAddr], 0
jz .noproxy
mov dword[edi], 'http'
mov byte[edi+4], ':'
mov word[edi+5], '//'
add edi, 7
mov esi, webAddr
 
.copy_host_loop:
lodsb
cmp al, ' '
jz .noproxy
stosb
jmp .copy_host_loop
 
.noproxy:
xor edx, edx ; 0
 
.next_edx:
; Determine the length of the url to send in the GET request
mov al, [edx+document]
cmp al, ' '
je .document_done
mov [edi], al
inc edi
inc edx
jmp .next_edx
 
.document_done:
mov esi, stringh
mov ecx, stringh_end-stringh
rep movsb
xor edx, edx ; 0
 
.webaddr_next:
mov al, [webAddr + edx]
cmp al, ' '
je .webaddr_done
mov [edi], al
inc edi
inc edx
jmp .webaddr_next
 
.webaddr_done:
cmp byte[proxyUser], 0
jz @f
call append_proxy_auth_header
@@:
mov esi, connclose
mov ecx, connclose_end-connclose
rep movsb
 
pusha
mov eax, 63
mov ebx, 1
mov edx, request
@@:
mov cl, [edx]
cmp edx, edi
jz @f
mcall
inc edx
jmp @b
@@:
popa
 
mov esi, edi
sub esi, request ; length
xor edi, edi ; flags
;;;;now write \r\nConnection: Close \r\n\r\n
mcall send, [socketnum], request ;' HTTP/1.1 .. '
popa
ret
 
;****************************************************************************
; Function
; print_status
;
; Description
; displays the socket/data received status information
;
;****************************************************************************
print_status:
pusha
mcall 26, 9
cmp eax, [nextupdate]
jb status_return
 
add eax, 25
mov [nextupdate], eax
 
mov ecx, [winys]
shl ecx, 16
add ecx, -18 shl 16 + 10
mcall 13, <5, 100>, , 0xffffff
 
mov edx, 12 shl 16 - 18
add edx, [winys]
xor esi, esi
mcall 47, <3, 0>, [status], ,
 
mov edx, 40 shl 16 - 18
add edx, [winys]
mcall , <6, 0>, [pos]
 
status_return:
popa
ret
 
;****************************************************************************
; Function
; read_incoming_data
;
; Description
; receive the web page from the server, storing it without processing
;
;****************************************************************************
read_incoming_data:
cmp [onoff], 1
je .rid
ret
 
.rid:
push esi
push edi
DEBUGF 1, "rid\n"
 
.read:
mcall recv, [socketnum], primary_buf, primary_buffer_size, 0
inc eax ; -1 = error (socket closed?)
jz .no_more_data
dec eax ; 0 bytes...
jz .read
mov edi, [pos]
add [pos], eax
push eax
mcall 68, 20, [pos], [buf_ptr]
mov [buf_ptr], eax
add edi, eax
mov esi, primary_buf
pop ecx ; number of recently read bytes
lea edx, [ecx - 3]
rep movsb
.no_more_data:
 
; mov [status], 4 ; connection closed by server
 
call parse_result
mov ecx, [shared_name]
test ecx, ecx
jz @f
cmp [ecx], byte 0
jnz save_in_shared
@@:
 
mcall 70, fileinfo
mov ecx, [sc.work_text]
or ecx, 0x80000000
mcall 4, <10, 93>, , download_complete
DEBUGF 1, "file saved\n"
 
pop edi
pop esi
 
; if called from command line, then exit
cmp byte[params], 0
jne exit
 
ret
save_in_shared:
 
mov esi, 1 ; SHM_OPEN+SHM_WRITE
mcall 68, 22
test eax, eax
jz save_in_shared_done
 
sub edx, 4
jbe save_in_shared_done
 
mov ecx, [final_size]
cmp ecx, edx
jb @f
 
mov ecx, edx
@@:
mov [eax], ecx
lea edi, [eax+4]
mov esi, [final_buffer]
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
 
save_in_shared_done:
pop edi
pop esi
jmp exit
; this function cuts header, and removes chunk sizes if doc is chunked
; in: buf_ptr, pos; out: buf_ptr, pos.
parse_result:
; close socket
mcall close, [socketnum]
DEBUGF 1, "close socketnum: 0x%x\n", eax
mov edi, [buf_ptr]
mov edx, [pos]
mov [buf_size], edx
; mcall 70, fileinfo_tmp
DEBUGF 1, "pos = 0x%x\n", edx
 
; first, find end of headers
.next_byte:
cmp dword[edi], 0x0d0a0d0a ; ìíå ëåíü ÷èòàòü ñòàíäàðò, ïóñòü áóäóò îáà âàðèàíòà
je .end_of_headers
cmp dword[edi], 0x0a0d0a0d
je .end_of_headers
inc edi
dec edx
jne .next_byte
; no end of headers. it's an error. let client see all those headers.
ret
 
.end_of_headers:
; here we look at headers and search content-length or transfer-encoding headers
; DEBUGF 1, "eoh\n"
 
sub edi, [buf_ptr]
add edi, 4
mov [body_pos], edi ; store position where document body starts
mov [is_chunked], 0
; find content-length in headers
; not good method, but should work for 'Content-Length:'
mov esi, [buf_ptr]
mov edi, s_contentlength
mov ebx, [body_pos]
xor edx, edx ; 0
.cl_next:
mov al, [esi]
cmp al, [edi + edx]
jne .cl_fail
inc edx
cmp edx, len_contentlength
je .cl_found
jmp .cl_incr
.cl_fail:
xor edx, edx ; 0
.cl_incr:
inc esi
dec ebx
je .cl_error
jmp .cl_next
.cl_error:
; DEBUGF 1, "content-length not found\n"
 
; find 'chunked'
; äà, ÿ êîïèðóþ êîä, ýòî óæàñíî, íî ìíå õî÷åòñÿ, ÷òîáû ïîñêîðåå çàðàáîòàëî
; à òàì óæ îòðåôàêòîðþ
mov esi, [buf_ptr]
mov edi, s_chunked
mov ebx, [body_pos]
xor edx, edx ; 0
 
.ch_next:
mov al, [esi]
cmp al, [edi + edx]
jne .ch_fail
inc edx
cmp edx, len_chunked
je .ch_found
jmp .ch_incr
 
.ch_fail:
xor edx, edx ; 0
 
.ch_incr:
inc esi
dec ebx
je .ch_error
jmp .ch_next
 
.ch_error:
; if neither of the 2 headers is found, it's an error
; DEBUGF 1, "transfer-encoding: chunked not found\n"
mov eax, [pos]
sub eax, [body_pos]
jmp .write_final_size
 
.ch_found:
mov [is_chunked], 1
mov eax, [body_pos]
add eax, [buf_ptr]
sub eax, 2
mov [prev_chunk_end], eax
jmp parse_chunks
.cl_found:
call read_number ; eax = number from *esi
 
.write_final_size:
mov [final_size], eax ; if this works, i will b very happy...
mov ebx, [pos] ; we well check if it is right
sub ebx, [body_pos]
 
; everything is ok, so we return
mov eax, [body_pos]
mov ebx, [buf_ptr]
add ebx, eax
mov [final_buffer], ebx
; mov ebx, [pos]
; sub ebx, eax
; mov [final_size], ebx
ret
parse_chunks:
; DEBUGF 1, "parse chunks\n"
; we have to look through the data and remove sizes of chunks we see
; 1. read size of next chunk
; 2. if 0, it's end. if not, continue.
; 3. make a good buffer and copy a chunk there
xor eax, eax
mov [final_buffer], eax ; 0
mov [final_size], eax ; 0
.read_size:
mov eax, [prev_chunk_end]
mov ebx, eax
sub ebx, [buf_ptr]
mov edx, eax
; DEBUGF 1, "rs "
cmp ebx, [pos]
jae chunks_end ; not good
call read_hex ; in: eax=pointer to text. out:eax=hex number, ebx=end of text.
cmp eax, 0
jz chunks_end
 
add ebx, 1
mov edx, ebx ; edx = size of size of chunk
add ebx, eax
mov [prev_chunk_end], ebx
; DEBUGF 1, "sz "
 
; do copying: from buf_ptr+edx to final_buffer+prev_final_size count eax
; realloc final buffer
push eax
push edx
push dword [final_size]
add [final_size], eax
mcall 68, 20, [final_size], [final_buffer]
mov [final_buffer], eax
; DEBUGF 1, "re "
pop edi
pop esi
pop ecx
; add [pos], ecx
add edi, [final_buffer]
; DEBUGF 1, "cp "
 
rep movsb
jmp .read_size
chunks_end:
; free old buffer
DEBUGF 1, "chunks end\n"
 
mcall 68, 13, [buf_ptr]
; done!
ret
 
; reads content-length from [edi+ecx], result in eax
read_number:
push ebx
xor eax, eax
xor ebx, ebx
 
.next:
mov bl, [esi]
 
cmp bl, '0'
jb .not_number
cmp bl, '9'
ja .not_number
sub bl, '0'
shl eax, 1
lea eax, [eax + eax * 4] ; eax *= 10
add eax, ebx
 
.not_number:
cmp bl, 13
je .done
inc esi
jmp .next
 
.done:
pop ebx
ret
; reads hex from eax, result in eax, end of text in ebx
read_hex:
add eax, 2
mov ebx, eax
mov eax, [ebx]
mov [deba], eax
 
xor eax, eax
xor ecx, ecx
.next:
mov cl, [ebx]
inc ebx
cmp cl, 0x0d
jz .done
 
or cl, 0x20
sub cl, '0'
jb .bad
 
cmp cl, 0x9
jbe .adding
 
sub cl, 'a'-'0'-10
cmp cl, 0x0a
jb .bad
 
cmp cl, 0x0f
ja .bad
 
.adding:
shl eax, 4
or eax, ecx
; jmp .not_number
;.bad:
.bad:
jmp .next
.done:
 
ret
 
;****************************************************************************
; Function
; socket_commands
;
; Description
; opens or closes the socket
;
;****************************************************************************
socket_commands:
cmp ah, 22 ; open socket
jne tst3
 
DEBUGF 1, "opening socket\n"
 
; Clear all page memory
xor eax, eax
mov [prev_chunk_end], eax ; 0
cmp [buf_ptr], eax ; 0
jz no_free
 
mcall 68, 13, [buf_ptr] ; free buffer
 
no_free:
xor eax, eax
mov [buf_size], eax ; 0
; Parse the entered url
call parse_url
 
mov edx, 80
cmp byte [proxyAddr], 0
jz @f
mov eax, [proxyPort]
xchg al, ah
mov [server_port], ax
@@:
 
mcall socket, AF_INET4, SOCK_STREAM, 0
mov [socketnum], eax
mcall connect, [socketnum], sockaddr1, 18
mov [pagexs], 80
push eax
xor eax, eax ; 0
mov [pos], eax
mov [pagex], eax
mov [pagey], eax
mov [command_on_off], eax
mov [is_body], eax
pop eax
ret
 
tst3:
cmp ah, 24 ; close socket
jne no_24
 
mcall close, [socketnum]
no_24:
ret
 
;****************************************************************************
; Function
; parse_url
;
; Description
; parses the full url typed in by the user into a web address ( that
; can be turned into an IP address by DNS ) and the page to display
; DNS will be used to translate the web address into an IP address, if
; needed.
; url is at document_user and will be space terminated.
; web address goes to webAddr and is space terminated.
; ip address goes to server_ip
; page goes to document and is space terminated.
;
; Supported formats:
; <protocol://>address<page>
; <protocol> is optional, removed and ignored - only http supported
; <address> is required. It can be an ip address or web address
; <page> is optional and must start with a leading / character
;
;****************************************************************************
parse_url:
; First, reset destination variables
mov al, ' '
mov edi, document
mov ecx, URLMAXLEN
rep stosb
mov edi, webAddr
mov ecx, URLMAXLEN
rep stosb
 
mov al, '/'
mov [document], al
 
mov esi, document_user
; remove any leading protocol text
mov ecx, URLMAXLEN
mov ax, '//'
 
pu_000:
cmp [esi], byte ' ' ; end of text?
je pu_002 ; yep, so not found
cmp [esi], ax
je pu_001 ; Found it, so esi+2 is start
inc esi
loop pu_000
 
pu_002:
; not found, so reset esi to start
mov esi, document_user-2
 
pu_001:
add esi, 2
mov ebx, esi ; save address of start of web address
mov edi, document_user + URLMAXLEN ; end of string
; look for page delimiter - it's a '/' character
pu_003:
cmp [esi], byte ' ' ; end of text?
je pu_004 ; yep, so none found
cmp esi, edi ; end of string?
je pu_004 ; yep, so none found
cmp [esi], byte '/' ; delimiter?
je pu_005 ; yep - process it
inc esi
jmp pu_003
 
pu_005:
; copy page to document address
; esi = delimiter
push esi
mov ecx, edi ; end of document_user
mov edi, document
 
pu_006:
movsb
cmp esi, ecx
je pu_007 ; end of string?
cmp [esi], byte ' ' ; end of text
; je pu_007 ; äçåí-àññåìáëåð
; jmp pu_006 ; íå íàäî ïëîäèòü ñóùíîñòè ïî íàïðàñíó
jne pu_006
 
pu_007:
pop esi ; point esi to '/' delimiter
 
pu_004:
; copy web address to webAddr
; start in ebx, end in esi-1
mov ecx, esi
mov esi, ebx
mov edi, webAddr
 
pu_008:
movsb
cmp esi, ecx
; je pu_009 ; äçåí-àññåìáëåð
; jmp pu_008 ; íå íàäî ïëîäèòü ñóùíîñòè ïî íàïðàñíó
jne pu_008
 
pu_009:
; For debugging, display resulting strings
DEBUGF 1, "%s", document_user
DEBUGF 1, "%s", webAddr
DEBUGF 1, "%s", document
 
; Look up the ip address, or was it specified?
mov al, [proxyAddr]
cmp al, 0
jnz pu_015
mov al, [webAddr]
pu_015:
cmp al, '0'
jb pu_010 ; Resolve address
cmp al, '9'
ja pu_010 ; Resolve address
 
DEBUGF 1, "GotIP\n"
 
; Convert address
; If proxy is given, get proxy address instead of server
mov esi, proxyAddr-1
cmp byte[esi+1], 0
jne pu_020
mov esi, webAddr-1
 
pu_020:
mov edi, server_ip
xor eax, eax
 
ip1:
inc esi
cmp [esi], byte '0'
jb ip2
cmp [esi], byte '9'
ja ip2
imul eax, 10
movzx ebx, byte [esi]
sub ebx, 48
add eax, ebx
jmp ip1
 
ip2:
mov [edi], al
xor eax, eax
inc edi
cmp edi, server_ip+3
jbe ip1
jmp pu_011
 
pu_010:
DEBUGF 1, "Resolving...\n"
 
; resolve name
push esp ; reserve stack place
push esp ; fourth parameter
push 0 ; third parameter
push 0 ; second parameter
push webAddr
call [getaddrinfo]
pop esi
; test for error
test eax, eax
; jnz .fail_dns
 
; fill in ip in sockstruct
mov eax, [esi + addrinfo.ai_addr]
mov eax, [eax + sockaddr_in.sin_addr]
mov [server_ip], eax
 
 
DEBUGF 1, "Resolved\n"
 
pu_011:
 
ret
 
;***************************************************************************
; Function
; load_settings
;
; Description
; Load settings from configuration file network.ini
;
;***************************************************************************
load_settings:
 
invoke ini.get_str, inifile, sec_proxy, key_proxy, proxyAddr, 256, proxyAddr
invoke ini.get_int, inifile, sec_proxy, key_proxyport, 80
mov [proxyPort], eax
invoke ini.get_str, inifile, sec_proxy, key_user, proxyUser, 256, proxyUser
invoke ini.get_str, inifile, sec_proxy, key_password, proxyPassword, 256, proxyPassword
 
ret
 
;***************************************************************************
; Function
; append_proxy_auth_header
;
; Description
; Append header to HTTP request for proxy authentification
;
;***************************************************************************
append_proxy_auth_header:
mov esi, proxy_auth_basic
mov ecx, proxy_auth_basic_end - proxy_auth_basic
rep movsb
; base64-encode string <user>:<password>
mov esi, proxyUser
 
apah000:
lodsb
test al, al
jz apah001
call encode_base64_byte
jmp apah000
 
apah001:
mov al, ':'
call encode_base64_byte
mov esi, proxyPassword
 
apah002:
lodsb
test al, al
jz apah003
call encode_base64_byte
jmp apah002
 
apah003:
call encode_base64_final
ret
 
encode_base64_byte:
inc ecx
shl edx, 8
mov dl, al
cmp ecx, 3
je ebb001
ret
 
ebb001:
shl edx, 8
inc ecx
 
ebb002:
rol edx, 6
xor eax, eax
xchg al, dl
mov al, [base64_table+eax]
stosb
loop ebb002
ret
 
encode_base64_final:
mov al, 0
test ecx, ecx
jz ebf000
call encode_base64_byte
test ecx, ecx
jz ebf001
call encode_base64_byte
mov byte [edi-2], '='
 
ebf001:
mov byte [edi-1], '='
 
ebf000:
ret
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
draw_window:
 
mcall 12, 1
 
mcall 48, 3, sc, 40 ;get system colors
 
mov edx, [sc.work]
or edx, 0x34000000
mcall 0, <50, 370>, <350, 140>, , 0, title ;draw window
mov ecx, [sc.work_text]
or ecx, 80000000h
mcall 4, <14, 14>, , type_pls ;"URL:"
 
edit_boxes_set_sys_color edit1, editboxes_end, sc
stdcall [edit_box_draw], edit1
 
; RELOAD
mcall 8, <90, 68>, <54, 16>, 22, [sc.work_button]
; STOP
mcall , <166, 50>, <54, 16>, 24
; SAVE
mcall , <224, 54>, , 26
; BUTTON TEXT
mov ecx, [sc.work_button_text]
or ecx, 80000000h
mcall 4, <102, 59>, , button_text
 
mcall 12, 2 ; end window redraw
ret
;-----------------------------------------------------------------------------
; Data area
;-----------------------------------------------------------------------------
align 4
@IMPORT:
 
library libini, 'libini.obj', \
box_lib, 'box_lib.obj', \
network, 'network.obj'
 
import libini, \
ini.get_str, 'ini_get_str', \
ini.get_int, 'ini_get_int'
 
import box_lib, \
edit_box_draw, 'edit_box', \
edit_box_key, 'edit_box_key', \
edit_box_mouse, 'edit_box_mouse'
 
import network,\
getaddrinfo, 'getaddrinfo',\
freeaddrinfo, 'freeaddrinfo',\
inet_ntoa, 'inet_ntoa'
 
;---------------------------------------------------------------------
fileinfo dd 2, 0, 0
final_size dd 0
final_buffer dd 0
db '/rd/1/.download', 0
body_pos dd 0
 
buf_size dd 0
buf_ptr dd 0
 
deba dd 0
db 0
 
;---------------------------------------------------------------------
 
mouse_dd dd 0
edit1 edit_box 295, 48, 10, 0xffffff, 0xff, 0x80ff, 0, 0x8000, URLMAXLEN, document_user, mouse_dd, ed_focus+ed_always_focus, 7, 7
editboxes_end:
 
;---------------------------------------------------------------------
 
include_debug_strings
 
;---------------------------------------------------------------------
 
type_pls db 'URL:', 0
button_text db 'DOWNLOAD STOP RESAVE', 0
download_complete db 'File saved as /rd/1/.download', 0
display_from dd 20
pos dd 0
pagex dd 0
pagey dd 0
pagexs dd 80
command_on_off dd 0
text_type db 1
com2 dd 0
script dd 0
socketnum dd 0
 
addr dd 0
ya dd 0
len dd 0
 
title db 'HTTP Downloader', 0
 
;---------------------------------------------------------------------
s_contentlength db 'Content-Length:'
len_contentlength = 15
 
s_chunked db 'Transfer-Encoding: chunked'
len_chunked = $ - s_chunked
 
is_body dd 0 ; 0 if headers, 1 if content
is_chunked dd 0
prev_chunk_end dd 0
cur_chunk_size dd 0
 
string0: db 'GET '
 
stringh db ' HTTP/1.1', 13, 10, 'Host: '
stringh_end:
proxy_auth_basic db 13, 10, 'Proxy-Authorization: Basic '
proxy_auth_basic_end:
connclose db 13, 10, 'User-Agent: Kolibrios Downloader', 13, 10, 'Connection: Close', 13, 10, 13, 10
connclose_end:
 
base64_table db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
db '0123456789+/'
 
inifile db '/sys/network.ini', 0
 
sec_proxy:
key_proxy db 'proxy', 0
key_proxyport db 'port', 0
key_user db 'user', 0
key_password db 'password', 0
 
sockaddr1:
dw AF_INET4
server_port dw 0x5000 ; 80
server_ip dd 0
rb 10
 
proxyPort dd 80
 
shared_name dd 0
 
status dd 0x0
prev_status dd 0x0
 
onoff dd 0x0
 
nextupdate dd 0
winys dd 400
 
;---------------------------------------------------------------------
document_user db 'http://', 0
;---------------------------------------------------------------------
IM_END:
;---------------------------------------------------------------------
rb URLMAXLEN-(IM_END - document_user)
;---------------------------------------------------------------------
sc system_colors
;---------------------------------------------------------------------
align 4
document rb URLMAXLEN
;---------------------------------------------------------------------
align 4
webAddr rb URLMAXLEN+1
;---------------------------------------------------------------------
 
align 4
primary_buf rb primary_buffer_size
 
params rb 1024
 
request rb 256
 
proxyAddr rb 256
proxyUser rb 256
proxyPassword rb 256
 
rb 4096 ; stack
 
I_END:
 
 
 
/kernel/branches/net/applications/ftpc/ftpc.asm
0,0 → 1,390
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ftpc.asm - FTP client for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format binary as ""
 
__DEBUG__ = 0
__DEBUG_LEVEL__ = 1
BUFFERSIZE = 1024
 
STATUS_CONNECTING = 0
STATUS_CONNECTED = 1
STATUS_NEEDPASSWORD = 1
STATUS_LOGGED_IN = 3
 
use32
; standard header
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem+0x1000 ; required memory
dd mem+0x1000 ; stack pointer
dd s ; parameters
dd 0 ; path
 
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
include '../debug-fdo.inc'
include '../network.inc'
 
include 'usercommands.inc'
include 'servercommands.inc'
 
; entry point
start:
 
DEBUGF 1, "hello"
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
; initialize console
push 1
call [con_start]
push title
push 25
push 80
push 25
push 80
call [con_init]
 
; Check for parameters
cmp byte [s], 0
jne resolve
 
main:
call [con_cls]
; Welcome user
push str1
call [con_write_asciiz]
 
; write prompt
push str2
call [con_write_asciiz]
; read string
mov esi, s
push 256
push esi
call [con_gets]
; check for exit
test eax, eax
jz done
cmp byte [esi], 10
jz done
 
resolve:
 
; delete terminating '\n'
mov esi, s
@@:
lodsb
cmp al, 0x20
ja @r
mov byte [esi-1], 0
 
; call [con_cls]
push str3
call [con_write_asciiz]
push s
call [con_write_asciiz]
 
; resolve name
push esp ; reserve stack place
push esp ; fourth parameter
push 0 ; third parameter
push 0 ; second parameter
push s ; first parameter
call [getaddrinfo]
pop esi
; test for error
test eax, eax
jnz fail
 
; write results
push str8
call [con_write_asciiz]
; mov edi, esi
 
; convert IP address to decimal notation
mov eax, [esi+addrinfo.ai_addr]
mov eax, [eax+sockaddr_in.sin_addr]
mov [sockaddr1.ip], eax
push eax
call [inet_ntoa]
; write result
push eax
call [con_write_asciiz]
; free allocated memory
push esi
call [freeaddrinfo]
 
push str9
call [con_write_asciiz]
 
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
jz fail2
mov [socketnum], eax
 
mcall connect, [socketnum], sockaddr1, 18
 
mcall 40, 1 shl 7
 
mov [status], STATUS_CONNECTING
mov [offset], buffer_ptr
 
wait_for_serverdata:
mcall 10
 
call [con_get_flags]
test eax, 0x200 ; con window closed?
jnz exit
 
; receive socket data
mcall recv, [socketnum], [offset], BUFFERSIZE, 0
inc eax
jz wait_for_serverdata
dec eax
jz wait_for_serverdata
 
; extract commands, copy them to "s" buffer
add eax, buffer_ptr ; eax = end pointer
mov esi, buffer_ptr ; esi = current pointer
.nextcommand:
mov edi, s
.byteloop:
cmp esi, eax
jae wait_for_serverdata
lodsb
cmp al, 10 ; excellent, we might have a command
je .got_command
cmp al, 13 ; just ignore this crap
je .byteloop
stosb
jmp .byteloop
 
; we have a newline check if its a command
.got_command:
xor al, al
stosb
; push esi eax
 
; print it to the screen
pushd s
call [con_write_asciiz]
pushd str4 ; newline
call [con_write_asciiz]
 
; cmp byte[s+2], " "
; jne .not_command
 
lea ecx, [edi - s]
call server_parser
 
; .not_command:
; pop eax esi
; jmp .nextcommand
 
 
 
 
wait_for_usercommand:
 
cmp [status], STATUS_CONNECTED
je .connected
 
cmp [status], STATUS_NEEDPASSWORD
je .needpass
 
 
; write prompt
push str2
call [con_write_asciiz]
; read string
mov esi, s
push 256
push esi
call [con_gets]
 
call [con_get_flags]
test eax, 0x200 ; con window closed?
jnz exit
 
cmp dword[s], "list"
je cmd_list
 
cmp dword[s], "help"
je cmd_help
 
push str_unkown
call [con_write_asciiz]
 
jmp wait_for_usercommand
 
 
.connected:
 
push str_user
call [con_write_asciiz]
 
mov dword[s], "USER"
mov byte[s+4], " "
 
jmp .send
 
 
.needpass:
push str_pass
call [con_write_asciiz]
 
mov dword[s], "PASS"
mov byte[s+4], " "
 
.send:
; read string
mov esi, s+5
push 256
push esi
call [con_gets]
 
mov edi, s+5
mov ecx, 256
xor al, al
repne scasb
lea esi, [edi-s-1]
mcall send, [socketnum], s
 
jmp wait_for_usercommand
 
 
 
 
 
 
open_dataconnection:
cmp [status], STATUS_LOGGED_IN
jne .fail
 
mov dword[s], "PASV"
mov byte[s+4], 10
mcall send, [socketnum], s, 5
 
ret
 
.fail:
push str6
call [con_write_asciiz]
 
ret
 
 
fail2:
push str6
call [con_write_asciiz]
 
jmp fail.wait
 
fail:
push str5
call [con_write_asciiz]
.wait:
push str10
call [con_write_asciiz]
call [con_getch2]
jmp main
 
done:
push 1
call [con_exit]
exit:
 
mcall close, [socketnum]
mcall -1
 
 
 
; data
title db 'FTP client',0
str1 db 'FTP client for KolibriOS v0.01',10,10,'Please enter ftp server address.',10,0
str2 db '> ',0
str3 db 'Connecting to ',0
str4 db 10,0
str5 db 10,'Name resolution failed.',10,0
str6 db 10,'Socket error.',10,0
str8 db ' (',0
str9 db ')',10,0
str10 db 'Push any key to continue.',0
str_user db "username: ",0
str_pass db "password: ",0
str_unkown db "unkown command",10,0
str_help db "available commands:",10,10
db "help list",10,0
 
str_open db "opening data socket",10,0
 
sockaddr1:
dw AF_INET4
.port dw 0x1500 ; 21
.ip dd 0
rb 10
 
sockaddr2:
dw AF_INET4
.port dw 0
.ip dd 0
rb 10
 
include_debug_strings ; ALWAYS present in data section
 
 
 
; import
align 4
@IMPORT:
 
library network, 'network.obj', console, 'console.obj'
 
import network, \
getaddrinfo, 'getaddrinfo', \
freeaddrinfo, 'freeaddrinfo', \
inet_ntoa, 'inet_ntoa'
 
import console, \
con_start, 'START', \
con_init, 'con_init', \
con_write_asciiz,'con_write_asciiz', \
con_exit, 'con_exit', \
con_gets, 'con_gets',\
con_cls, 'con_cls',\
con_getch2, 'con_getch2',\
con_set_cursor_pos, 'con_set_cursor_pos',\
con_write_string, 'con_write_string',\
con_get_flags, 'con_get_flags'
 
 
i_end:
 
active_passive db ?
socketnum dd ?
datasocket dd ?
buffer_ptr rb 2*BUFFERSIZE
status db ?
offset dd ?
 
s rb 1024
 
mem:
/kernel/branches/net/applications/ftpc/servercommands.inc
0,0 → 1,114
server_parser:
 
; Commands are always 3 numbers and followed by a space
; If a server decides it needs multiline output,
; first lines will have a dash instead of space after numbers,
; thus they are simply ignored.
 
cmp dword[s], "150 "
je data_ok
 
cmp dword[s], "220 "
je welcome
 
cmp dword[s], "227 "
je pasv_ok
 
cmp dword[s], "230 "
je login_ok
 
cmp dword[s], "331 "
je pass
 
ret
 
 
welcome:
 
mov [status], STATUS_CONNECTED
ret
 
 
pass:
 
mov [status], STATUS_NEEDPASSWORD
ret
 
 
login_ok:
 
mov [status], STATUS_LOGGED_IN
ret
 
 
pasv_ok:
 
sub ecx, 5
jb .fail
mov al, "("
mov edi, s + 5
repne scasb
 
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
je fail
mov [datasocket], eax
 
mov esi, edi
call ascii_dec
mov byte[sockaddr2.ip+0], bl
call ascii_dec
mov byte[sockaddr2.ip+1], bl
call ascii_dec
mov byte[sockaddr2.ip+2], bl
call ascii_dec
mov byte[sockaddr2.ip+3], bl
 
call ascii_dec
mov byte[sockaddr2.port+1], bl
call ascii_dec
mov byte[sockaddr2.port+0], bl
 
push str_open
call [con_write_asciiz]
 
mcall connect, [datasocket], sockaddr2, 18
 
.fail:
ret
 
 
data_ok:
 
mcall recv, [datasocket], buffer_ptr, BUFFERSIZE, 0 ; fixme: use other buffer
inc eax
jz .fail
dec eax
jz .fail
 
mov byte[buffer_ptr + eax], 0
pushd buffer_ptr
call [con_write_asciiz]
 
.fail:
ret
 
 
ascii_dec:
 
xor ebx, ebx
mov cl, 3
.loop:
lodsb
sub al, '0'
jb .done
cmp al, 9
ja .done
lea ebx, [ebx*4+ebx]
shl ebx, 1
add bl, al
dec cl
jnz .loop
 
.done:
ret
/kernel/branches/net/applications/ftpc/usercommands.inc
0,0 → 1,17
cmd_list:
 
call open_dataconnection
 
mov dword[s], "LIST"
mov word[s+4], 0x0d0a
mcall send, [socketnum], s, 6
 
jmp wait_for_serverdata
 
 
cmd_help:
 
push str_help
call [con_write_asciiz]
 
jmp wait_for_usercommand
/kernel/branches/net/applications/ircc/window.inc
0,0 → 1,167
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
window_create:
 
; allocate the window data block
mcall 68, 12, sizeof.window_data
test eax, eax
jz .fail
 
; fill it with all zeros
push eax
mov edi, eax
mov ecx, (sizeof.window_data+3)/4
xor eax, eax
rep stosd
pop eax
 
.fail:
ret
 
 
window_set_name: ; esi = ptr to name, ebx = window ptr
 
pusha
 
; Skip heading spaces
.spaceloop:
cmp byte[esi], ' '
jne .done
inc esi
jmp .spaceloop
.done:
 
; Now copy it
lea edi, [ebx + window.name]
mov ecx, MAX_WINDOWNAME_LEN
.loop:
lodsb
cmp al, 0x21
jbe .addzero
stosb
dec ecx
jnz .loop
.addzero:
xor al, al
stosb
 
call draw_windownames ; redraw it
 
popa
 
ret
 
 
 
window_refresh:
 
; set the correct buffer pointers ; FIXME: what is it good for?
mov eax, [textbox_width] ;
imul eax, 11 ;
mov [pos], eax ;
 
mov eax, [window_print]
mov eax, [eax + window.data_ptr]
add eax, window_data.text
mov [text_start], eax
 
ret
 
 
window_updated:
 
mov edi, [window_print]
test [edi + window.flags], FLAG_UPDATED
jnz .skip
 
or [edi + window.flags], FLAG_UPDATED
 
; now play a sound :)
 
.skip:
 
ret
 
 
print_text: ; eax = start ptr
; dl = end char
pusha
ptr2:
mov bl, [eax]
 
cmp bl, dl
je ptr_ret
cmp bl, 0
je ptr_ret
call print_character
 
inc eax
jmp ptr2
 
ptr_ret:
popa
ret
 
 
print_text2: ; esi = ptr to ASCIIZ string
 
pusha
.loop:
lodsb
test al, al
jz .done
mov bl, al
call print_character
jmp .loop
 
.done:
popa
ret
 
 
if TIMESTAMP
print_timestamp:
 
pusha
mcall 3 ; get system time
 
mov bl, '['
call print_character
mov ecx, TIMESTAMP
.loop:
mov bl, al
shr bl, 4
add bl, '0'
call print_character
 
mov bl, al
and bl, 0x0f
add bl, '0'
call print_character
 
dec ecx
jz .done
 
mov bl, ':'
call print_character
shr eax, 8
jmp .loop
.done:
mov bl, ']'
call print_character
mov bl, ' '
call print_character
 
popa
ret
end if
/kernel/branches/net/applications/ircc/gui.inc
0,0 → 1,316
draw_window:
 
pusha
 
mcall 9, thread_info, -1 ; get current window size
mov eax, dword[thread_info+42] ; window xsize
mov ebx, dword[thread_info+46] ; ysize
mov edx, dword[thread_info+62] ; work area xsize
mov esi, dword[thread_info+66] ; ysize
sub eax, edx
sub ebx, esi
 
cmp edx, WIN_MIN_X
jae .x_ok
mov edx, WIN_MIN_X
.x_ok:
mov [xsize], edx
add edx, eax
 
cmp esi, WIN_MIN_Y
jae .y_ok
mov esi, WIN_MIN_Y
.y_ok:
mov [ysize], esi
add esi, ebx
mcall 67, -1, -1 ; set the new sizes
 
mcall 12, 1
xor eax, eax ; draw window
mov ebx, WIN_MIN_X
mov ecx, WIN_MIN_Y
mov edx, [colors.work]
add edx, 0x33000000
mov edi, str_programname
mcall
mcall 12, 2 ;; when do we actually need this??
 
mov ebx, [xsize]
mov ecx, [ysize]
sub cx, 15 ;;;;
push cx
shl ecx, 16
pop cx
mov edx, [colors.work_graph]
mcall 38 ; draw line
 
mov ecx, TOP_Y SHL 16 + TOP_Y
mcall
 
mov edi, [window_open]
cmp [edi + window.type], WINDOWTYPE_CHANNEL
jne .not_channel
 
; draw a vertical separator line
mov ebx, [xsize]
sub ebx, USERLIST_X + SCROLLBAR_WIDTH + 3
push bx
shl ebx, 16
pop bx
mov ecx, [ysize]
add ecx, TOP_Y SHL 16 -(15) ;;;;
mcall
 
call redraw_channel_list
 
.not_channel:
mov edx, [edi + window.data_ptr]
add edx, window_data.text
call draw_channel_text
 
; editbox
 
mov eax, [ysize]
sub eax, 12 ;;;;;;
mov [edit1.top], eax
 
mov eax, [xsize]
mov [edit1.width], eax
 
push dword edit1
call [edit_box_draw]
 
; tabs
 
call draw_windownames
 
popa
ret
 
 
 
redraw_channel_list:
 
; First, calculate scrollbar
 
mov ebx, [window_open]
mov eax, [ebx + window.users] ; number of users in the open window
mov [scroll1.max_area], eax
 
mov eax, [ysize]
sub eax, TOP_Y + 15 ;;;;
push eax
mov [scroll1.y_size], ax
 
mov eax, [xsize]
sub eax, SCROLLBAR_WIDTH
mov [scroll1.x_pos], ax
 
pop eax ; scrollbar height
xor edx, edx
mov ecx, 10
div ecx
mov [scroll1.cur_area], eax
 
; Do we need a scrollbar?
cmp eax, [scroll1.max_area]
jae .noscroll
 
; Is the current position greater then the max position?
cmp eax, [scroll1.position]
ja @f
mov [scroll1.position], eax
@@:
 
; OK, draw the scrollbar
mov [scroll1.all_redraw], 1
 
push dword scroll1
call [scrollbar_v_draw]
 
jmp print_channel_list
 
.noscroll:
mov [scroll1.position], 0
 
 
 
print_channel_list:
 
pusha
; Now, draw the usernames themselves
 
; first, draw an invisible button
mov ebx, [xsize]
sub ebx, USERLIST_X + SCROLLBAR_WIDTH
shl ebx, 16
push ebx
mov bx, USERLIST_X
mov ecx, [ysize]
add ecx, TEXT_Y shl 16 - (TEXT_Y + 15) ;;;;; + 10???
push ecx ebx
mov edx, 50 + 1 shl 29 + 1 shl 30
mcall 8
 
; now draw rectangle to clear the names
pop ebx ecx
mov edx, [colors.work]
mcall 13
 
; now draw the names according with scrollbar position and window size
mov eax, [scroll1.position]
xor edx, edx
mov ecx, MAX_NICK_LEN
mul ecx
mov edx, eax
mov eax, [window_open]
mov ebp, [eax + window.selected]
add edx, [eax + window.data_ptr]
sub ebp, [scroll1.position]
add edx, window_data.names
 
pop ebx
mov bx, TEXT_Y
mov ecx, [colors.work_text]
or ecx, 0x80000000 ; ASCIIZ string
mov eax, 4 ; draw text
 
mov edi, [ysize] ; Calculate how many names will fit on screen
sub edi, TEXT_Y + 15 ;+ 10 ;;;;;
.loop:
cmp byte[edx], 0 ; end of list?
je .done
 
dec ebp ; is this name selected?
jnz .nothighlight
; yes, highlight it
pusha
mov cx, bx
mov bx, USERLIST_X
shl ecx, 16
mov cx, 10 - 1
mov edx, 0x00000055 ; blue!
mcall 13
popa
 
mov ecx, 0x8000ffff ; cyan!
mcall
 
mov ecx, [colors.work_text]
or ecx, 0x80000000 ; ASCIIZ string
jmp .next
 
.nothighlight:
mcall
 
.next:
add edx, MAX_NICK_LEN ; next name
add ebx, 10 ; height distance between lines
sub edi, 10
ja .loop
 
.done:
popa
 
ret
 
 
 
 
draw_channel_text:
 
pusha
 
mov eax, 4 ; draw text
mov ebx, TEXT_X shl 16 + TEXT_Y
mov ecx, 12 ; 12 lines max ?
mov esi, [textbox_width]
 
.dct:
pusha
mov cx, bx
shl ecx, 16
mov cx, 9 ; character height
mov eax, 13 ; draw rectangle
mov ebx, TEXT_X shl 16
mov bx, word[textbox_width]
imul bx, 6 ; character width
mov edx, [colors.work]
mcall
popa
 
push ecx
mov ecx, [colors.work_text]
cmp word[edx], '* '
jne .no_red
mov ecx, 0x00aa0000
jmp .draw
.no_red:
 
cmp word[edx], '**'
jne .no_light_blue
cmp byte[edx+2], '*'
jne .no_light_blue
mov ecx, 0x000000aa
jmp .draw
.no_light_blue:
 
cmp byte[edx], '#'
jne .no_blue
mov ecx, 0x0000aa00
; jmp .draw
.no_blue:
 
.draw:
mcall
add edx, [textbox_width]
add ebx, 10 ; height distance between lines
 
pop ecx
loop .dct
 
popa
ret
 
 
 
draw_windownames:
 
mov eax, 8
mov ebx, 5 shl 16 + 120
mov ecx, 12 shl 16 + 12
mov edx, WINDOW_BTN_START
mov edi, windows
.more_btn:
mov esi, [colors.work_button]
cmp [window_open], edi
jne @f
not esi
and esi, 0x00ffffff
@@:
mcall
inc edx
add ebx, 125 shl 16
add edi, sizeof.window
cmp [edi + window.data_ptr], 0
jne .more_btn
 
mov eax, 4
mov ebx, 10 shl 16 + 15
mov ecx, [colors.work_button_text]
or ecx, 0x80000000 ; ASCIIZ string
lea edx, [windows + window.name]
mov esi, MAX_WINDOWS
.more:
mcall
add edx, sizeof.window
cmp byte[edx], 0
je .enough
add ebx, 125 shl 16
dec esi
jnz .more
.enough:
 
ret
 
 
/kernel/branches/net/applications/ircc/ircc.asm
0,0 → 1,476
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; IRC client for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org, ;;
;; text encoder/decoder by Clevermouse. ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
version equ '0.1'
 
; connection status
STATUS_DISCONNECTED = 0
STATUS_RESOLVING = 1
STATUS_CONNECTING = 2
STATUS_CONNECTED = 3
 
; window flags
FLAG_UPDATED = 1 shl 0
FLAG_CLOSE = 1 shl 1
FLAG_RECEIVING_NAMES = 1 shl 2
 
; window types
WINDOWTYPE_SERVER = 0
WINDOWTYPE_CHANNEL = 1
WINDOWTYPE_CHAT = 2
WINDOWTYPE_LIST = 3
WINDOWTYPE_DCC = 4
 
; supported encodings
CP866 = 0
CP1251 = 1
UTF8 = 2
 
; settings
USERCMD_MAX_SIZE = 400
 
WIN_MIN_X = 600
WIN_MIN_Y = 165
 
TEXT_X = 5
TEXT_Y = 30
 
TOP_Y = 25
 
MAX_WINDOWS = 20
MAX_USERS = 4096
 
MAX_NICK_LEN = 32
MAX_REAL_LEN = 32 ; realname
MAX_SERVER_NAME = 256
 
MAX_CHANNEL_LEN = 40
MAX_CHANNELS = 37
 
MAX_COMMAND_LEN = 512
 
TIMESTAMP = 3 ; 3 = hh:mm:ss, 2 = hh:mm, 0 = no timestamp
 
MAX_WINDOWNAME_LEN = 256
 
WINDOW_BTN_START = 100
 
SCROLLBAR_WIDTH = 12
 
USERLIST_X = 98
 
 
format binary as ""
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 1 ; header version
dd START ; program start
dd I_END ; program image size
dd IM_END+2048 ; required amount of memory
dd IM_END+2048
dd param
dd path
 
include "../macros.inc"
include "../proc32.inc"
include "../dll.inc"
include "../network.inc"
include "../struct.inc"
include '../../../../../programs/develop/libraries/box_lib/trunk/box_lib.mac'
 
struct window
data_ptr dd ? ; zero if not used
flags db ?
type db ?
name rb MAX_WINDOWNAME_LEN
users dd ?
users_scroll dd ?
selected dd ? ; selected user, 0 if none selected
ends
 
struct window_data
text rb 120*60
title rb 256
names rb MAX_NICK_LEN * MAX_USERS
usertext rb 256
usertextlen dd ?
ends
 
include "encodings.inc"
include "window.inc" ; also contains text print routines
include "serverparser.inc"
include "userparser.inc"
include "socket.inc"
include "gui.inc"
include "users.inc"
 
 
START:
 
mcall 68, 11 ; init heap so we can allocate memory dynamically
 
; wanted events
mcall 40, EVM_REDRAW + EVM_KEY + EVM_BUTTON + EVM_STACK + EVM_MOUSE
 
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
 
; find path to main settings file (ircc.ini)
mov edi, path ; Calculate the length of zero-terminated string
xor al, al
mov ecx, 1024
repne scasb
dec edi
mov eax, '.ini'
stosd
xor al, al
stosb
 
; Fill the window buffer with zeros
mov edi, windows
mov ecx, (sizeof.window*MAX_WINDOWS+3)/4
xor eax, eax
rep stosd
 
; clear command area too
mov edi, servercommand
mov ecx, 600/4
rep stosd
 
; allocate window data block
call window_create
mov ebx, windows
mov [ebx + window.data_ptr], eax
mov [ebx + window.flags], 0
mov [ebx + window.type], WINDOWTYPE_SERVER
add eax, window_data.text
mov [text_start], eax
 
call window_refresh
 
; get system colors
mcall 48, 3, colors, 40
 
; set edit box and scrollbar colors
mov eax, [colors.work]
mov [scroll1.bg_color], eax
 
mov eax, [colors.work_button]
mov [scroll1.front_color], eax
 
mov eax, [colors.work_text]
mov [scroll1.line_color], eax
 
; get settings from ini
invoke ini.get_str, path, str_user, str_nick, user_nick, MAX_NICK_LEN, default_nick
invoke ini.get_str, path, str_user, str_real, user_real_name, MAX_REAL_LEN, default_real
 
; Welcome user
mov esi, str_welcome
call print_text2
 
call draw_window ;;; FIXME (gui is not correctly drawn first time)
 
redraw:
call draw_window
 
still:
 
; wait here for event
mcall 10
 
dec eax
jz redraw
 
dec eax
jz main_window_key
 
dec eax
jz button
 
cmp al, 3
je mouse
 
call process_network_event
 
mov edx, [window_open]
test [edx + window.flags], FLAG_UPDATED
jz .no_update
and [edx + window.flags], not FLAG_UPDATED
mov edx, [edx + window.data_ptr]
add edx, window_data.text
call draw_channel_text
.no_update:
call print_channel_list
 
jmp still
 
button:
 
mcall 17 ; get id
shr eax, 8
 
cmp ax, 1 ; close program
je exit
 
cmp ax, 50
jne @f
 
mcall 37, 1 ; Get mouse position
sub ax, TEXT_Y
mov bl, 10
div bl
and eax, 0x000000ff
inc eax
add eax, [scroll1.position]
mov ebx, [window_open]
mov [ebx + window.selected], eax
 
call print_channel_list
 
jmp still
 
@@:
sub ax, WINDOW_BTN_START
jb exit
 
cmp ax, MAX_WINDOWS
ja exit
 
mov dx, sizeof.window
mul dx
shl edx, 16
mov dx, ax
add edx, windows
cmp [edx + window.data_ptr], 0
je exit
mov [window_open], edx
call window_refresh
call draw_window
 
jmp still
exit:
mcall -1
 
 
 
main_window_key:
 
mcall 2
 
push dword edit1
call [edit_box_key]
 
cmp ah, 13 ; enter
jne no_send2
 
call user_parser
 
mov [edit1.size], 0
mov [edit1.pos], 0
 
push dword edit1
call [edit_box_draw]
 
mov edx, [window_open]
mov edx, [edx + window.data_ptr]
add edx, window_data.text
call draw_channel_text
 
jmp still
no_send2:
 
jmp still
 
mouse:
push dword edit1
call [edit_box_mouse]
 
; TODO: check if scrollbar is active
push [scroll1.position]
push dword scroll1
call [scrollbar_v_mouse]
pop eax
cmp eax, [scroll1.position] ; did the scrollbar move?
je @f
call print_channel_list
@@:
 
jmp still
 
 
; DATA AREA
 
encoding_text:
db 'CP866 '
db 'CP1251'
db 'UTF-8 '
encoding_text_len = 6
 
action_header db '*** ', 0
action_header_short db '* ', 0
ctcp_header db '-> [',0
ctcp_version db '] VERSION',10,0
ctcp_ping db '] PING',10,0
ctcp_time db '] TIME',10,0
has_left_channel db ' has left ', 0
joins_channel db ' has joined ', 0
is_now_known_as db ' is now known as ', 0
has_quit_irc db ' has quit IRC', 10, 0
sets_mode db ' sets mode ', 0
kicked db ' is kicked from ', 0
str_talking db 'Now talking in ',0
str_topic db 'Topic is ',0
str_setby db 'Set by ',0
 
str_version db 'VERSION '
str_programname db 'KolibriOS IRC client ', version, 0
 
str_user db 'user', 0
str_nick db 'nick', 0
str_real db 'realname', 0
str_email db 'email', 0
 
default_nick db 'kolibri_user', 0
default_real db 'Kolibri User', 0
 
str_welcome db 10
db ' ______________________ __ __ __',10
db '| \______ \_ ___ \ ____ | | |__| ____ _____/ |_',10
db '| || _/ \ \/ _/ ___\| | | |/ __ \ / \ __\',10
db '| || | \ \____ \ \___| |_| \ ___/| | \ |',10
db '|___||____|_ /\______ / \___ >____/__|\___ >___| /__|',10
db ' \/ \/ \/ \/ \/',10
db 10
db 'Welcome to IRC client ',version,' for KolibriOS',10
db 10
db 'Type /help for help',10,0
 
str_nickchange db 'Nickname is now ',0
str_realchange db 'Real name is now ',0
str_dotnewline db '.',10, 0
str_newline db 10, 0
str_connecting db 10,'* Connecting to ',0
str_help db 10,'following commands are available:',10
db 10
db '/nick <nick> : change nickname to <nick>',10
db '/real <real name> : change real name to <real name>',10
db '/server <address> : connect to server <address>',10
db '/code <code> : change codepage to cp866, cp1251, or utf8',10,0
 
str_1 db ' -',0
str_2 db '- ',0
 
str_sockerr db 'Socket Error',10,0
str_dnserr db 'Unable to resolve hostname.',10,0
str_refused db 'Connection refused',10,0
 
sockaddr1:
dw AF_INET4
.port dw 0x0b1a ; 6667
.ip dd 0
rb 10
 
 
status dd STATUS_DISCONNECTED
 
text_start dd ? ; pointer to current textbox data
irc_data dd 0x0 ; encoder
textbox_width dd 80 ; in characters, not pixels ;)
pos dd 66 * 11 ; encoder
 
window_open dd windows
window_print dd windows
 
scroll dd 1
dd 12
 
align 4
@IMPORT:
 
library network, 'network.obj',\
libini, 'libini.obj',\
boxlib, 'box_lib.obj'
 
import network,\
getaddrinfo, 'getaddrinfo',\
freeaddrinfo, 'freeaddrinfo',\
inet_ntoa, 'inet_ntoa'
 
import libini,\
ini.get_str, 'ini_get_str',\
ini.get_int, 'ini_get_int'
 
import boxlib,\
edit_box_draw ,'edit_box' ,\
edit_box_key ,'edit_box_key' ,\
edit_box_mouse ,'edit_box_mouse' ,\
scrollbar_v_draw ,'scrollbar_v_draw' ,\
scrollbar_v_mouse,'scrollbar_v_mouse'
 
 
usercommand db '/server chat.freenode.net', 0
rb MAX_COMMAND_LEN
 
I_END:
 
; width, left, top
edit1 edit_box 0, 0, 0, 0xffffff, 0x6f9480, 0, 0, 0, USERCMD_MAX_SIZE, usercommand, mouse_dd, ed_focus, 25, 25
; xsize, xpos, ysize, ypos, max, cur, pos, bgcol, frcol, linecol
scroll1 scrollbar SCROLLBAR_WIDTH, 300, 150, TOP_Y, 10, 100, 0, 0, 0, 0, 0, 1
scroll2 scrollbar SCROLLBAR_WIDTH, 300, 150, TOP_Y, 10, 100, 0, 0, 0, 0, 0, 1
 
main_PID dd ? ; identifier of main thread
utf8_bytes_rest dd ? ; bytes rest in current UTF8 sequence
utf8_char dd ? ; first bits of current UTF8 character
gai_reqdata rb 32 ; buffer for getaddrinfo_start/process
ip_list dd ? ; will be filled as pointer to addrinfo list
packetbuf rb 1024 ; buffer for packets to server
path rb 1024
param rb 1024
 
socketnum dd ?
 
servercommand rb 600
 
thread_info rb 1024
xsize dd ?
ysize dd ?
 
colors system_colors
 
irc_server_name rb MAX_SERVER_NAME
 
user_nick rb MAX_NICK_LEN
user_real_name rb MAX_REAL_LEN
 
windows rb MAX_WINDOWS*sizeof.window
 
mouse_dd dd ?
 
IM_END:
 
 
 
 
 
 
 
/kernel/branches/net/applications/ircc/serverparser.inc
0,0 → 1,928
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
server_parser:
 
mov esi, servercommand
 
cmp byte [esi], ':'
jne .parse
 
.spaceloop:
lodsb
test al, al
jz .fail
cmp al, ' '
jne .spaceloop
 
.parse:
mov eax, [esi]
or eax, 0x20202020
mov edi, server_commands
mov ecx, server_commands.number
 
.loop:
scasd
je .got_cmd
add edi, 4
dec ecx
jnz .loop
 
.fail:
ret
 
.got_cmd:
jmp dword[edi]
 
 
server_commands:
 
dd '322 ', cmd_322 ; RPL_LIST
dd '323 ', cmd_323 ; RPL_LISTEND
dd '328 ', cmd_328
dd '332 ', cmd_topic
dd '333 ', cmd_333 ; nickname and time of topic
dd '353 ', cmd_353 ; name reply
dd '366 ', cmd_366 ; end of names list
dd '372 ', cmd_372 ; motd
dd '375 ', cmd_375 ; start of motd
dd '376 ', cmd_376 ; end of motd
dd '421 ', cmd_421 ; unknown command
dd 'join', cmd_join
dd 'kick', cmd_kick
dd 'mode', cmd_mode
dd 'nick', cmd_nick
dd 'part', cmd_part
dd 'ping', cmd_ping
dd 'priv', cmd_privmsg
dd 'quit', cmd_quit
dd 'noti', cmd_notice
 
.number = ($ - server_commands) / 8
 
 
align 4
compare_to_nick:
 
push esi
mov ecx, MAX_NICK_LEN
mov esi, user_nick
.loop:
lodsb
cmp al, ' '
jbe .done
cmp al, 'a'
jb .ok
cmp al, 'z'
ja .ok
sub al, 0x20
.ok:
 
mov bl, byte[edi]
cmp bl, 'a'
jb .ok2
cmp bl, 'z'
ja .ok2
sub bl, 0x20
.ok2:
cmp bl, al
jne .not_equal
inc edi
dec ecx
jnz .loop
 
.done:
xor eax, eax
pop esi
ret
 
.not_equal:
or eax, -1
pop esi
ret
 
align 4
skip_nick:
 
; First: skip the NICK (maybe we should verify it?)
.nick:
lodsb
cmp al, ' '
je .skip
cmp al, ':'
je .skip
jmp .nick
 
; skip all leading spaces and semicolons
.skip:
lodsb
cmp al, ' '
je .skip
cmp al, ':'
je .skip
dec esi
 
ret
 
 
align 4
find_window: ; esi is ptr to windowname
 
push esi
 
mov edi, esi
call compare_to_nick
jne .nochat
 
mov esi, servercommand+1
.nochat:
 
; now search for window in list
mov ebx, windows
mov [window_print], ebx ; set first window (server window) as default output window
.scanloop:
cmp [ebx + window.data_ptr], 0
je .create_it
push esi
lea edi, [ebx + window.name]
mov ecx, MAX_WINDOWNAME_LEN
repe cmpsb
pop esi
cmp byte[edi-1], 0
je .got_it
add ebx, sizeof.window
; TODO: check buffer limits ?
jmp .scanloop
 
; create channel window - search for empty slot
.create_it:
mov ebx, windows
mov ecx, MAX_WINDOWS
.scanloop2:
cmp [ebx + window.data_ptr], 0
je .free_found
add ebx, sizeof.window
dec ecx
jnz .scanloop2
; Error: no more available windows!
jmp .just_skip
 
.free_found:
push ebx
call window_create
pop ebx
test eax, eax
jz .just_skip
mov [ebx + window.data_ptr], eax
mov [ebx + window.type], WINDOWTYPE_CHAT
mov [ebx + window.flags], 0
 
call window_set_name
 
mov [window_open], ebx
mov [window_print], ebx
call window_refresh
 
call draw_windownames
jmp .just_skip
 
; found it!
.got_it:
mov [window_print], ebx
call window_refresh
 
.just_skip:
pop esi
.skip1:
; skip text
lodsb
test al, al
jz .quit
cmp al, ' '
jne .skip1
dec esi
; now skip trailing spaces and semicolons
.skip2:
lodsb
test al, al
jz .quit
cmp al, ' '
je .skip2
cmp al, ':'
je .skip2
dec esi
 
.quit:
ret
 
 
 
 
 
 
cmd_328:
cmd_421:
cmd_372:
cmd_375:
cmd_376:
add esi, 4
jmp cmd_notice.loop
 
cmd_notice:
 
cmp byte[servercommand], ':'
jne .gogogo
 
mov byte [esi-1], 0
push esi
mov esi, str_1
call print_text2
mov esi, servercommand+1
call print_text2
mov esi, str_2
call print_text2
pop esi
 
.gogogo:
add esi, 6
 
.loop:
inc esi
cmp byte [esi], 0
je .fail
cmp byte [esi], ' '
jne .loop
 
.loop2:
inc esi
cmp byte [esi], 0
je .fail
cmp byte [esi], ' '
je .loop2
cmp byte [esi], ':'
je .loop2
 
call print_text2
mov esi, str_newline
call print_text2
 
.fail:
 
ret
 
 
 
cmd_ping:
 
; Just change PING to PONG
mov dword[esi], 'PONG'
 
; Find the end of the command
lea edi, [esi + 5]
xor al, al
repne scasb
 
; Now send it back
mov edx, esi
mov esi, edi
mov word [esi], 0x0d0a
inc esi
inc esi
sub esi, edx
mcall send, [socketnum], , , 0
 
ret
 
 
 
cmd_privmsg:
 
add esi, 8 ; skip 'PRIVMSG '
call find_window ; esi now points to end of destination name
 
cmp byte[esi], 1
je cmd_ctcp
 
cmp dword[esi], 'ACTI' ; Action?
je .action
 
; nope, just plain old privmsg
if TIMESTAMP
call print_timestamp
end if
 
push esi
mov bl, '<'
call print_character
 
mov eax, servercommand+1
mov dl, '!'
call print_text
 
mov bl, '>'
call print_character
 
mov bl, ' '
call print_character
 
pop esi
call print_text2
 
mov bl, 10
call print_character
 
.fail:
ret
 
.action:
add esi, 8
push esi
if TIMESTAMP
call print_timestamp
end if
 
mov esi, action_header_short
call print_text2
 
mov eax, servercommand+1
mov dl, ' '
call print_text
 
mov bl, ' '
call print_character
 
pop esi
call print_text2
 
mov bl, 10
call print_character
 
ret
 
cmd_ctcp:
inc esi
 
cmp dword[esi], 'VERS'
je .version
 
cmp dword[esi], 'TIME'
je .time
 
cmp dword[esi], 'PING'
je .ping
 
ret
 
.time:
mov byte [esi+4], ' '
lea edi, [esi+5]
 
; TODO: add system date (fn 29) in human readable format
 
mcall 3 ; get system time
 
mov ecx, 3
.timeloop:
mov bl, al
shr al, 4
add al, '0'
stosb
 
mov al, bl
and al, 0x0f
add al, '0'
stosb
 
dec ecx
jz .timedone
 
mov al, ':'
stosb
shr eax, 8
jmp .timeloop
 
.timedone:
xor al, al
stosb
call ctcp_reply
 
if TIMESTAMP
call print_timestamp
end if
 
mov esi, ctcp_header
call print_text2
 
mov esi, servercommand+1
call print_text2
 
mov esi, ctcp_time
call print_text2
 
ret
 
.version:
mov esi, str_version
call ctcp_reply
 
if TIMESTAMP
call print_timestamp
end if
 
mov esi, ctcp_header
call print_text2
 
mov esi, servercommand+1
call print_text2
 
mov esi, ctcp_version
call print_text2
 
ret
 
.ping:
call ctcp_reply
 
if TIMESTAMP
call print_timestamp
end if
 
mov esi, ctcp_header
call print_text2
 
mov esi, servercommand+1
call print_text2
 
mov esi, ctcp_ping
call print_text2
 
ret
 
 
 
ctcp_reply:
 
push esi
 
mov dword [usercommand], 'NOTI'
mov dword [usercommand+4], 'CE '
 
mov esi, servercommand+1
mov edi, usercommand+7
.nickloop:
lodsb
cmp al, '!'
je .done
cmp al, ' '
je .done
test al, al
je .fail
stosb
jmp .nickloop
.done:
mov byte [esi-1], 0
mov ax, ' :'
stosw
mov al, 1
stosb
 
pop esi
.replyloop:
lodsb
cmp al, 1
jbe .done2
stosb
jmp .replyloop
.done2:
 
mov al, 1
stosb
mov ax, 0x0a0d
stosw
 
lea esi, [edi - usercommand]
mcall send, [socketnum], usercommand, , 0
.fail:
ret
 
 
 
cmd_part:
add esi, 5 ; skip 'PART '
push esi
call skip_nick
call find_window
pop esi
 
; Is it me who parted?
mov edi, servercommand+1
call compare_to_nick
jne .dont_close
 
; yes, close the window
mov edi, [window_print]
mov [edi + window.flags], FLAG_UPDATED + FLAG_CLOSE
 
ret
 
; somebody else parted, just print message
.dont_close:
push esi
mov esi, action_header
call print_text2
 
mov eax, servercommand+1
mov dl, '!'
mov cl, ' '
call print_text
 
mov esi, has_left_channel
call print_text2
 
pop esi
call print_text2
 
mov esi, str_newline
call print_text2
 
mov ebx, [window_print]
mov esi, servercommand+1
call user_remove
 
ret
 
 
 
cmd_join:
add esi, 5 ; skip 'JOIN '
 
; compare nick: did we join a channel?
mov edi, servercommand+1
call compare_to_nick
jne .no_new_window
 
; create channel window - search for empty slot
mov ebx, windows
mov ecx, MAX_WINDOWS
.loop:
cmp [ebx + window.data_ptr], 0
je .free_found
add ebx, sizeof.window
dec ecx
jnz .loop
; Error: no more available windows!! ;;;;; TODO
.fail:
ret
 
.free_found:
push ebx
call window_create
pop ebx
test eax, eax
jz .fail
mov [ebx + window.data_ptr], eax
mov [ebx + window.type], WINDOWTYPE_CHANNEL
mov [ebx + window.flags], 0
 
call window_set_name
 
mov [window_open], ebx
mov [window_print], ebx
call window_refresh
 
push esi
mov esi, action_header
call print_text2
 
mov esi, str_talking
call print_text2
 
pop eax
mov dl, ' '
call print_text
 
mov esi, str_dotnewline
call print_text2
 
call draw_window
 
ret
 
.no_new_window:
push esi
call find_window
 
mov esi, action_header
call print_text2
 
mov eax, servercommand+1
mov dl, '!'
call print_text
 
mov esi, joins_channel
call print_text2
 
pop esi
call print_text2
 
mov esi, str_newline
call print_text2
 
mov ebx, [window_print]
mov esi, servercommand+1
call user_add
 
ret
 
 
 
 
cmd_nick:
; NOTE: This command applies to a user, and thus has no specific channel
add esi, 5 ; skip 'NICK '
 
cmp byte[esi], ':' ; TODO: skip all spaces and semicolons?
jne @f
inc esi
@@:
 
; Change the nick in the current userlist. TODO: check other channels too!
push esi
mov ebx, [window_print]
 
mov esi, servercommand+1
call user_remove
 
mov esi, [esp]
call user_add
 
call redraw_channel_list
 
; Is it me who changed nick?
mov edi, servercommand+1
call compare_to_nick
pop esi
jne .not_me
 
mov ecx, MAX_NICK_LEN-1
push esi
.copyloop:
lodsb
test al, al
jz .copydone
cmp al, ' '
je .copydone
stosb
dec ecx
jnz .copyloop
.copydone:
xor al, al
stosb
pop esi
.not_me:
 
; Now print a message on the current channel
push esi
mov esi, action_header_short
call print_text2
 
mov eax, servercommand+1
mov dl, '!'
call print_text
 
mov esi, is_now_known_as
call print_text2
 
pop esi
call print_text2
 
mov esi, str_newline
call print_text2
 
ret
 
 
 
 
cmd_kick:
add esi, 5 ; skip 'KICK '
; Is it me who got kicked?
mov edi, servercommand+1
call compare_to_nick
jne .not_me
 
; TODO: mark channel as disconnected
 
.not_me:
; find the channel user has been kicked from
push esi
call skip_nick
call find_window
 
mov esi, action_header_short
call print_text2
 
mov eax, servercommand+1
mov dl, '!'
call print_text
 
mov esi, kicked
call print_text2
 
pop esi
call print_text2
 
mov esi, str_newline
call print_text2
 
mov ebx, [window_print]
mov esi, servercommand+1
call user_remove
 
ret
 
 
 
cmd_quit:
; NOTE: This command applies to a user, and thus has no specific channel
 
mov esi, action_header
call print_text2
 
mov eax, servercommand+1
mov dl, '!'
call print_text
 
mov esi, has_quit_irc
call print_text2
 
; TODO: check other channels on same server too!
mov ebx, [window_print]
mov esi, servercommand+1
call user_remove
 
ret
 
 
 
cmd_mode:
 
add esi, 5 ; skip 'MODE '
 
push esi
mov esi, action_header_short
call print_text2
 
mov eax, servercommand+1
mov dl, ' '
call print_text
 
mov esi, sets_mode
call print_text2
 
pop esi
call print_text2
 
mov esi, str_newline
call print_text2
 
;;; TODO: change username if needed
 
ret
 
 
cmd_353: ; channel usernames reply
 
add esi, 4 ; skip '353 '
call skip_nick
inc esi ; channel type '*', '=' or '@'
inc esi ; ' '
call find_window
 
; now find window ptr and check if this is the first 353 message
mov ebx, [window_print]
test [ebx + window.flags], FLAG_RECEIVING_NAMES
jnz .add
 
or [ebx + window.flags], FLAG_RECEIVING_NAMES
; mov [ebx + window.users], 0
; TODO: remove all users?
 
.add:
push esi
call user_add
pop esi
 
.namesloop:
lodsb
test al, al
jz .done
cmp al, ' ' ; names list is separated with spaces
jne .namesloop
jmp .add
 
.done:
call redraw_channel_list
 
ret
 
 
 
 
 
cmd_366: ; channel usernames end
 
add esi, 4 ; skip '366 '
call skip_nick
call find_window
 
mov ebx, [window_print]
and [ebx + window.flags], not FLAG_RECEIVING_NAMES
 
ret
 
 
 
 
cmd_topic:
 
add esi, 4 ; skip '332 '
call skip_nick
call find_window
 
push esi
mov esi, action_header
call print_text2
 
mov esi, str_topic
call print_text2
 
pop esi
call print_text2
 
mov esi, str_newline
call print_text2
 
ret
 
 
cmd_333:
 
add esi, 4 ; skip '333 '
call skip_nick ;;;;
call find_window
 
; mov ecx, 2 ; number of spaces to find ;;; CHECKME
; .loop:
; lodsb
; test al, al
; je .fail
; cmp al, ' '
; jne .loop
; dec ecx
; jnz .loop ; find some more spaces
 
push esi
mov esi, action_header
call print_text2
 
mov esi, str_setby
call print_text2
 
; pop esi
; call print_text2
 
pop eax
mov dl, '!'
call print_text
 
mov esi, str_newline
call print_text2
 
.fail:
ret
 
cmd_322:
add esi, 4
 
call skip_nick
 
call print_text2
 
mov esi, str_newline
call print_text2
 
ret
 
cmd_323:
 
ret
/kernel/branches/net/applications/ircc/userparser.inc
0,0 → 1,318
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
user_parser:
 
mov eax, [edit1.size]
mov word [usercommand + eax], 0x0a0d ; terminate the line
 
cmp byte[usercommand], '/' ; is it a server command ?
je server_command
 
; Ignore data commands when not connected.
cmp [status], STATUS_CONNECTED
jne sdts_ret
 
; Ok, we said something, print it to our textbox
 
; TODO: dont send if it's a server window?
 
push [window_open] ; print to the current window
pop [window_print]
call window_refresh
 
if TIMESTAMP
call print_timestamp
end if
 
mov bl, '<'
call print_character
 
mov esi, user_nick
call print_text2
 
mov bl,'>'
call print_character
mov bl,' '
call print_character
 
mov eax, [edit1.size]
mov byte[usercommand + eax],0
 
mov esi, usercommand
call print_text2
 
mov bl, 10
call print_character
 
; and now send it to the server
 
mov dword[packetbuf], 'priv'
mov dword[packetbuf+4], 'msg '
 
mov esi, [window_open]
add esi, window.name
mov edi, packetbuf+8
mov ecx, MAX_WINDOWNAME_LEN
.loop:
lodsb
test al, al
jz .done
stosb
dec ecx
jnz .loop
.done:
 
mov ax, ' :'
stosw
 
mov esi, usercommand
mov ecx, [edit1.size]
inc ecx
call recode
 
mov al, 10
stosb
 
lea esi, [edi - packetbuf]
mcall send, [socketnum], packetbuf, , 0
 
sdts_ret:
 
ret
 
 
 
user_commands:
dd 'nick', cmd_usr_nick
dd 'real', cmd_usr_real
dd 'serv', cmd_usr_server
dd 'help', cmd_usr_help
dd 'code', cmd_usr_code
; TODO: All other commands require a connection to the server.
dd 'quer', cmd_usr_quer
dd 'quit', cmd_usr_quit
 
.number = ($ - user_commands) / 8
 
 
 
server_command:
 
mov eax, dword[usercommand+1]
or eax, 0x20202020
 
mov edi, user_commands
mov ecx, user_commands.number
.loop:
scasd
je .got_cmd
add edi, 4
dec ecx
jnz .loop
jmp cmd_usr_send ; If none of the previous commands, just send to server
 
.got_cmd:
jmp dword[edi]
 
 
 
 
 
cmd_usr_quit:
 
cmp [edit1.size], 5
je .ok
jb cmd_usr_send
cmp byte[usercommand+5], ' '
jne cmd_usr_send
 
.ok:
call cmd_usr_send
 
mcall close, [socketnum]
 
mov ecx, MAX_WINDOWS
mov edi, windows
.loop:
mov [edi + window.flags], FLAG_CLOSE
add edi, sizeof.window
dec ecx
jnz .loop
 
ret
 
 
 
 
cmd_usr_nick:
 
cmp [edit1.size], 5
je .justprint
cmp byte[usercommand+5], ' '
jne cmd_usr_send
 
mov ecx, MAX_NICK_LEN
mov esi, usercommand+6
mov edi, user_nick
.loop:
lodsb
cmp al, 13
je .done
stosb
dec ecx
jnz .loop
.done:
xor al, al
stosb
 
cmp [socketnum], 0
je .justprint
 
lea esi, [edi - usercommand]
mcall send, [socketnum], usercommand+1, , 0
 
.justprint:
mov esi, str_nickchange
call print_text2
mov esi, user_nick
call print_text2
mov esi, str_dotnewline
call print_text2
 
ret
 
 
 
cmd_usr_real:
 
cmp byte[usercommand+5], ' '
jne cmd_usr_send
 
mov ecx, MAX_REAL_LEN
mov esi, usercommand+6
mov edi, user_real_name
.loop:
lodsb
cmp al, 13
je .done
stosb
dec ecx
jnz .loop
.done:
xor al, al
stosb
 
mov esi, str_realchange
call print_text2
mov esi, user_real_name
call print_text2
mov esi, str_dotnewline
call print_text2
 
ret
 
 
 
cmd_usr_server:
 
mov eax, dword[usercommand+5] ; check for 'er ', we only checked 'serv'
or eax, 0x00002020
and eax, 0x00ffffff
cmp eax, 'er '
jne cmd_usr_send
 
mov ecx, [edit1.size] ; ok now set the address
sub ecx, 8
 
mov esi, usercommand+8
push esi
mov edi, irc_server_name
rep movsb
xor al, al
stosb
pop esi
 
; set it also in window name
mov ebx, [window_print]
call window_set_name
 
; now connect
call socket_connect
 
ret
 
 
cmd_usr_quer:
 
mov ecx, MAX_WINDOWS
mov ebx, windows
.loop:
cmp [ebx + window.data_ptr], 0
je .found
add ebx, sizeof.window
dec ecx
jnz .loop
 
; error: no available channels ! FIXME
 
ret
 
 
.found:
call window_create
test eax, eax
jz .error
mov [ebx + window.data_ptr], eax
 
mov esi, usercommand+7
call window_set_name
 
mov [ebx + window.type], WINDOWTYPE_CHAT
mov [ebx + window.flags], 0
 
.error:
 
ret
 
 
 
cmd_usr_help:
 
mov esi, str_help
call print_text2
 
ret
 
 
 
cmd_usr_code:
 
; TODO
 
ret
 
 
 
cmd_usr_send:
 
mov esi, usercommand+1
mov ecx, [edit1.size]
inc ecx
mov edi, packetbuf
call recode
 
lea esi, [edi - packetbuf]
mcall send, [socketnum], packetbuf, , 0
 
ret
 
/kernel/branches/net/applications/ircc/users.inc
0,0 → 1,164
 
 
; esi is ptr to nick
; ebx is ptr to window
align 4
user_add:
 
cmp [ebx + window.users], MAX_USERS
jae fail
 
mov edi, [ebx + window.data_ptr]
add edi, window_data.names
mov ebp, [ebx + window.users]
inc ebp ; CHECKME
 
push esi edi
.restart:
mov ecx, MAX_NICK_LEN
.loop1:
lodsb
cmp al, '@'
jne @f
mov al, ' ' ; give @ highest priority
@@:
cmp al, 'A'
jb @f
cmp al, 'Z'
ja @f
add al, 'a' - 'A' ; convert to lowercase
@@:
dec ecx
jz .got_it
 
.loop2:
mov dl, [edi]
cmp dl, 0
je .got_it
cmp dl, '@'
jne @f
mov dl, ' ' ; give @ highest priority
@@:
cmp dl, 'A'
jb @f
cmp dl, 'Z'
ja @f
add dl, 'a' - 'A' ; convert to lowercase
@@:
cmp al, dl
jb .got_it
je .check_next
 
pop edi esi
add edi, MAX_NICK_LEN
push esi edi
 
dec ebp
jnz .restart
 
.check_next:
inc edi
jmp .loop1
 
.got_it:
pop edi esi
 
; OK, insert it here..
 
; mov all trailing usernames by MAX_NICK_LEN bytes
push esi edi
mov esi, [ebx + window.data_ptr]
add esi, window_data.names + MAX_NICK_LEN * (MAX_USERS - 1)
 
mov ecx, esi
sub ecx, edi
add ecx, MAX_NICK_LEN
shr ecx, 2
lea edi, [esi + MAX_NICK_LEN]
std
rep movsd
cld
pop edi esi
 
; Now insert our new username
mov ecx, MAX_NICK_LEN-1
.fill:
lodsb
cmp al, ' '
je .done
cmp al, '!'
je .done
stosb
loop .fill
.done:
xor al, al
stosb
 
inc [ebx + window.users]
 
ret
 
 
 
 
 
; esi is ptr to nick
; ebx is ptr to window
align 4
user_remove:
 
call user_find
jz fail
 
lea esi, [edi + MAX_NICK_LEN]
mov ecx, [ebx + window.data_ptr]
add ecx, window_data.names + MAX_NICK_LEN * MAX_USERS
sub ecx, esi
shr ecx, 2
rep movsd
 
dec [ebx + window.users]
xor eax, eax
 
ret
 
 
 
; IN:
; esi is ptr to nick
; ebx is ptr to window
; OUT:
; edi is ptr to nick in userlist
align 4
user_find:
 
mov eax, [ebx + window.users]
test eax, eax
jz fail
mov edi, [ebx + window.data_ptr]
add edi, window_data.names
 
.loop:
push esi edi
mov ecx, MAX_NICK_LEN
repe cmpsb
cmp byte[edi-1], 0
je .got_it
; TODO: check byte[esi] too!
pop edi esi
add edi, MAX_NICK_LEN
dec eax
jnz .loop
jmp fail
 
.got_it:
pop edi esi
test edi, edi ; to clear zero flag
 
ret
 
 
fail:
 
xor edi, edi
ret
/kernel/branches/net/applications/ircc/socket.inc
0,0 → 1,242
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
socket_connect:
 
; cmp [status], STATUS_CONNECTED ; TODO
; je disconnect
 
; ignore if status is not "disconnected"
cmp [status], STATUS_DISCONNECTED
jne .nothing
 
mov esi, str_connecting
call print_text2
mov esi, irc_server_name
call print_text2
mov esi, str_dotnewline
call print_text2
 
; update status
inc [status] ; was STATUS_DISCONNECTED, now STATUS_RESOLVING
 
; resolve name
push esp ; reserve stack place
push esp ; fourth parameter
push 0 ; third parameter
push 0 ; second parameter
push irc_server_name
call [getaddrinfo]
pop esi
; test for error
test eax, eax
jnz .fail_dns
 
; fill in ip in sockstruct
mov eax, [esi + addrinfo.ai_addr]
mov eax, [eax + sockaddr_in.sin_addr]
mov [sockaddr1.ip], eax
 
; free allocated memory
push esi
call [freeaddrinfo]
 
; update status
inc [status]
 
; connect
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
jz .fail
mov [socketnum], eax
 
mcall connect, [socketnum], sockaddr1, 18
cmp eax, -1
jz .fail_refused
 
.nothing:
ret
 
.fail:
mov [status], STATUS_DISCONNECTED
 
mov esi, str_sockerr
call print_text2
 
ret
 
.fail_dns:
mov [status], STATUS_DISCONNECTED
 
mov esi, str_dnserr
call print_text2
 
ret
 
.fail_refused:
mov [status], STATUS_DISCONNECTED
 
mov esi, str_refused
call print_text2
 
ret
 
 
 
socket_write_userinfo:
 
; create packet in packetbuf
mov edi, packetbuf
 
mov eax, 'NICK'
stosd
mov al, ' '
stosb
mov esi, user_nick
mov ecx, MAX_NICK_LEN
.loop:
lodsb
test al, al
jz .done
stosb
dec ecx
jnz .loop
.done:
mov ax, 0x0d0a
stosw
 
mov eax, 'USER'
stosd
mov al, ' '
stosb
mov esi, user_nick
mov ecx, MAX_NICK_LEN
.loop2:
lodsb
test al, al
jz .done2
stosb
dec ecx
jnz .loop2
.done2:
mov eax, ' 8 *'
stosd
mov ax, ' :'
stosw
mov al, ' '
stosb
mov esi, user_real_name
mov ecx, MAX_REAL_LEN
.loop3:
lodsb
test al, al
jz .done3
stosb
dec ecx
jnz .loop3
.done3:
mov ax, 0x0d0a
stosw
 
lea esi, [edi - packetbuf]
mcall send, [socketnum], packetbuf, , 0
 
ret
 
 
 
 
process_network_event:
; values for status: 0, 1, 2, 3
mov eax, [status]
dec eax
; 0 = STATUS_DISCONNECTED - do nothing
; (ignore network events if we are disconnected from network)
js .nothing
; 1 = STATUS_RESOLVING
jz .nothing
; 2 = STATUS_CONNECTING
dec eax
jz .connecting
; 3 = STATUS_CONNECTED
jmp .connected
 
.nothing:
ret
 
.connecting:
call socket_write_userinfo
 
; The connection has been established, change status from "connecting" to "connected".
inc [status]
 
.connected:
call read_incoming_data
ret
 
 
disconnect:
 
cmp [status], STATUS_DISCONNECTED
je .nothing
 
mcall close, [socketnum]
 
mov [status], STATUS_DISCONNECTED
 
.nothing:
ret
 
 
 
read_incoming_data:
 
pusha
 
; TODO: read more data if we receive one full packet
 
.nextpacket:
mcall recv, [socketnum], packetbuf, 1024 ; read a packet
inc eax ; check if we got one
jz .done
dec eax
jz .done
 
; ok we have data, now feed it to the recoder
 
lea edx, [packetbuf + eax] ; edx = end pointer
mov esi, packetbuf ; esi = start pointer
.nextcommand:
mov edi, servercommand
.byteloop:
call get_next_byte ; reads byte from [esi] to al
jnc .nextpacket ; if CF is set, we need more data
cmp al, 10
je .got_command
cmp al, 13
je .got_command
stosb
jmp .byteloop
 
; we have a command, call the serverparser
 
.got_command:
mov byte[edi], 0 ; mark the end of the command
push esi edx
call server_parser
pop edx esi
jmp .nextcommand
 
.done:
popa
 
ret
/kernel/branches/net/applications/ircc/encodings.inc
0,0 → 1,317
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
get_next_byte:
; Load next byte from the packet, translating to cp866 if necessary
; At input esi = pointer to data, edx = limit of data
; Output is either (translated) byte in al with CF set or CF cleared.
mov eax, [encoding]
jmp [get_byte_table+eax*4]
 
get_byte_cp866:
cmp esi, edx
jae .nothing
lodsb
.nothing:
ret
 
get_byte_cp1251:
cmp esi, edx
jae .nothing
lodsb
cmp al, 0x80
jb @f
and eax, 0x7F
mov al, [cp1251_table+eax]
@@:
stc
.nothing:
ret
 
get_byte_utf8:
; UTF8 decoding is slightly complicated.
; One character can occupy one or more bytes.
; The boundary in packets theoretically can be anywhere in data,
; so this procedure keeps internal state between calls and handles
; one byte at a time, looping until character is read or packet is over.
; Globally, there are two distinct tasks: decode byte sequence to unicode char
; and convert this unicode char to our base encoding (that is cp866).
; 1. Check that there are data.
cmp esi, edx
jae .nothing
; 2. Load byte.
lodsb
movzx ecx, al
; 3. Bytes in an UTF8 sequence can be of any of three types.
; If most significant bit is cleared, sequence is one byte and usual ASCII char.
; First byte of a sequence must be 11xxxxxx, other bytes are 10yyyyyy.
and al, 0xC0
jns .single_byte
jp .first_byte
; 4. This byte is not first in UTF8 sequence.
; 4a. Check that the sequence was started. If no, it is invalid byte
; and we simply ignore it.
cmp [utf8_bytes_rest], 0
jz get_byte_utf8
; 4b. Otherwise, it is really next byte and it gives some more bits of char.
mov eax, [utf8_char]
shl eax, 6
lea eax, [eax+ecx-0x80]
; 4c. Decrement number of bytes rest in the sequence.
; If it goes to zero, character is read, so return it.
dec [utf8_bytes_rest]
jz .got_char
mov [utf8_char], eax
jmp get_byte_utf8
; 5. If the byte is first in UTF8 sequence, calculate the number of leading 1s
; - it equals total number of bytes in the sequence; some other bits rest for
; leading bits in the character.
.first_byte:
mov eax, -1
@@:
inc eax
add cl, cl
js @b
mov [utf8_bytes_rest], eax
xchg eax, ecx
inc ecx
shr al, cl
mov [utf8_char], eax
jmp get_byte_utf8
; 6. If the byte is ASCII char, it is the character.
.single_byte:
xchg eax, ecx
.got_char:
; We got the character, now abandon a possible sequence in progress.
and [utf8_bytes_rest], 0
; Now second task. The unicode character is in eax, and now we shall convert it
; to cp866.
cmp eax, 0x80
jb .done
; 0x410-0x43F -> 0x80-0xAF, 0x440-0x44F -> 0xE0-0xEF, 0x401 -> 0xF0, 0x451 -> 0xF1
cmp eax, 0x401
jz .YO
cmp eax, 0x451
jz .yo
cmp eax, 0x410
jb .unrecognized
cmp eax, 0x440
jb .part1
cmp eax, 0x450
jae .unrecognized
sub al, (0x40-0xE0) and 0xFF
ret
.part1:
sub al, 0x10-0x80
.nothing:
.done:
ret
.unrecognized:
mov al, '?'
stc
ret
.YO:
mov al, 0xF0
stc
ret
.yo:
mov al, 0xF1
stc
ret
 
 
 
print_character:
 
pusha
 
cmp bl, 13 ; line beginning
jne nobol
 
mov ecx, [pos]
inc ecx
boll1:
dec ecx
mov eax, ecx
xor edx, edx
mov ebx, [textbox_width]
div ebx
test edx, edx
jnz boll1
mov [pos], ecx
jmp newdata
nobol:
 
cmp bl, 10 ; line down
jne nolf
 
addx1:
inc [pos]
mov eax, [pos]
xor edx, edx
mov ecx, [textbox_width]
div ecx
test edx, edx
jnz addx1
mov eax, [pos]
jmp cm1
nolf:
no_lf_ret:
 
 
cmp bl, 15 ; character
jbe newdata
 
mov eax, [irc_data]
shl eax, 8
mov al, bl
mov [irc_data], eax
 
mov eax, [pos]
;---- draw data
pusha
 
and ebx, 0xff
add eax, [text_start]
mov [eax], bl
 
popa
;---- draw data
 
mov eax, [pos]
inc eax
cm1:
mov ebx, [scroll+4]
imul ebx, [textbox_width]
cmp eax, ebx
jb noeaxz
 
mov esi, [text_start]
add esi, [textbox_width]
 
mov edi, [text_start]
mov ecx, ebx
rep movsb
 
mov esi, [text_start]
mov ecx, [textbox_width]
imul ecx, 61
add esi, ecx
 
mov edi, [text_start]
mov ecx, [textbox_width]
imul ecx, 60
add edi, ecx
mov ecx, ebx
rep movsb
 
mov eax, ebx
sub eax, [textbox_width]
noeaxz:
mov [pos], eax
 
newdata:
mov eax, [window_print]
or [eax + window.flags], FLAG_UPDATED
 
popa
ret
 
 
 
recode_to_cp866:
rep movsb
ret
 
recode_to_cp1251:
xor eax, eax
jecxz .nothing
.loop:
lodsb
cmp al,0x80
jb @f
mov al, [cp866_table-0x80+eax]
@@: stosb
loop .loop
.nothing:
ret
 
recode_to_utf8:
jecxz .nothing
.loop:
lodsb
cmp al, 0x80
jb .single_byte
and eax, 0x7F
mov ax, [utf8_table+eax*2]
stosw
loop .loop
ret
.single_byte:
stosb
loop .loop
.nothing:
ret
 
recode:
mov eax, [encoding]
jmp [recode_proc+eax*4]
 
 
 
encoding dd UTF8
recode_proc dd recode_to_cp866, recode_to_cp1251, recode_to_utf8
get_byte_table dd get_byte_cp866, get_byte_cp1251, get_byte_utf8
 
 
cp1251_table:
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; 8
db '?','?','?','?','?',$F9,'?','?' , '?','?','?','?','?','?','?','?' ; 9
db '?',$F6,$F7,'?',$FD,'?','?','?' , $F0,'?',$F2,'?','?','?','?',$F4 ; A
db $F8,'?','?','?','?','?','?',$FA , $F1,$FC,$F3,'?','?','?','?',$F5 ; B
db $80,$81,$82,$83,$84,$85,$86,$87 , $88,$89,$8A,$8B,$8C,$8D,$8E,$8F ; C
db $90,$91,$92,$93,$94,$95,$96,$97 , $98,$99,$9A,$9B,$9C,$9D,$9E,$9F ; D
db $A0,$A1,$A2,$A3,$A4,$A5,$A6,$A7 , $A8,$A9,$AA,$AB,$AC,$AD,$AE,$AF ; E
db $E0,$E1,$E2,$E3,$E4,$E5,$E6,$E7 , $E8,$E9,$EA,$EB,$EC,$ED,$EE,$EF ; F
 
; 0 1 2 3 4 5 6 7 8 9 A B C D E F
 
utf8_table:
times 80h dw 0x98C3 ; default placeholder
 
; 0x80-0xAF -> 0x90D0-0xBFD0
repeat 0x30
store byte 0xD0 at utf8_table+2*(%-1)
store byte 0x90+%-1 at utf8_table+2*%-1
end repeat
 
; 0xE0-0xEF -> 0x80D1-0x8FD1
repeat 0x10
store byte 0xD1 at utf8_table+2*(0xE0-0x80+%-1)
store byte 0x80+%-1 at utf8_table+2*(0xE0-0x80+%)-1
end repeat
 
; 0xF0 -> 0x81D0, 0xF1 -> 0x91D1
store dword 0x91D181D0 at utf8_table+2*(0xF0-0x80)
 
cp866_table:
db $C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7 , $C8,$C9,$CA,$CB,$CC,$CD,$CE,$CF ; 8
db $D0,$D1,$D2,$D3,$D4,$D5,$D6,$D7 , $D8,$D9,$DA,$DB,$DC,$DD,$DE,$DF ; 9
db $E0,$E1,$E2,$E3,$E4,$E5,$E6,$E7 , $E8,$E9,$EA,$EB,$EC,$ED,$EE,$EF ; A
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; B
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; C
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; D
db $F0,$F1,$F2,$F3,$F4,$F5,$F6,$F7 , $F8,$F9,$FA,$FB,$FC,$FD,$FE,$FF ; E
db $A8,$B8,$AA,$BA,$AF,$BF,$A1,$A2 , $B0,$95,$B7,'?',$B9,$A4,'?','?' ; F
 
; 0 1 2 3 4 5 6 7 8 9 A B C D E F
 
/kernel/branches/net/applications/ircc/ircc.ini
0,0 → 1,8
[user]
nick = kolibri_user
realname = tetten
 
[colors]
action1 = 0x000000aa
action2 = 0x0000aa00
action3 = 0x00aa0000
/kernel/branches/net/applications/libio.inc
0,0 → 1,113
;;================================================================================================;;
;;//// libio.inc //// (c) mike.dld, 2007-2008 ////////////////////////////////////////////////////;;
;;================================================================================================;;
;; ;;
;; This file is part of Common development libraries (Libs-Dev). ;;
;; ;;
;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
;; of the License, or (at your option) any later version. ;;
;; ;;
;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
;; Lesser General Public License for more details. ;;
;; ;;
;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
;; If not, see <http://www.gnu.org/licenses/>. ;;
;; ;;
;;================================================================================================;;
 
 
O_BINARY = 00000000b
O_READ = 00000001b
O_WRITE = 00000010b
O_CREATE = 00000100b
O_SHARE = 00001000b
O_TEXT = 00010000b
 
SEEK_SET = 0
SEEK_CUR = 1
SEEK_END = 2
 
struct FileDateTime
union
time dd ?
struct
sec db ?
min db ?
hour db ?
ends
ends
union
date dd ?
struct
day db ?
month db ?
year dw ?
ends
ends
ends
 
struct FileInfoBlock
Function dd ?
Position dd ?
Flags dd ?
Count dd ?
Buffer dd ?
db ?
FileName dd ?
ends
 
struct FileInfoHeader
Version dd ?
FilesRead dd ?
FilesCount dd ?
rd 5
ends
 
struct FileInfoA
Attributes dd ?
Flags dd ?
DateCreate FileDateTime
DateAccess FileDateTime
DateModify FileDateTime
union
FileSize dq ?
struct
FileSizeLow dd ?
FileSizeHigh dd ?
ends
ends
FileName rb 264
ends
 
struct FileInfoW
Attributes dd ?
Flags dd ?
DateCreate FileDateTime
DateAccess FileDateTime
DateModify FileDateTime
union
FileSize dq ?
struct
FileSizeLow dd ?
FileSizeHigh dd ?
ends
ends
FileName rw 264
ends
 
virtual at 0
FileInfo FileInfoA
FileInfo fix FileInfoA
sizeof.FileInfo fix sizeof.FileInfoA
end virtual
 
FA_READONLY = 00000001b
FA_HIDDEN = 00000010b
FA_SYSTEM = 00000100b
FA_LABEL = 00001000b
FA_FOLDER = 00010000b
FA_ARCHIVED = 00100000b
FA_NORMAL = 01000000b
FA_ANY = 01111111b
/kernel/branches/net/applications/macros.inc
0,0 → 1,588
@^ fix macro comment {
^@ fix }
 
; -------------------------
macro library [lname,fname]
{
forward
dd __#lname#_library_table__,__#lname#_library_name__
common
dd 0
forward
align 4
__#lname#_library_name__ db fname,0
}
 
macro import lname,[name,sname]
{
common
align 4
__#lname#_library_table__:
forward
if used name
name dd __#name#_import_name__
end if
common
dd 0
forward
if used name
align 4
__#name#_import_name__ db sname,0
end if
}
 
macro export [name,sname]
{
forward
dd __#name#_export_name__,name
common
dd 0
forward
align 4
__#name#_export_name__ db sname,0
}
; -------------------------
 
macro m2m dest,src {
push src
pop dest
}
 
 
macro iglobal {
IGlobals equ IGlobals,
macro __IGlobalBlock { }
macro uglobal {
UGlobals equ UGlobals,
macro __UGlobalBlock { }
 
endg fix } ; Use endg for ending iglobal and uglobal blocks.
 
 
macro IncludeIGlobals{
macro IGlobals dummy,[n] \{ __IGlobalBlock
purge __IGlobalBlock \}
match I, IGlobals \{ I \} }
 
macro IncludeUGlobals{
macro UGlobals dummy,[n] \{
\common
\local begin, size
begin = $
virtual at $
\forward
__UGlobalBlock
purge __UGlobalBlock
\common
size = $ - begin
end virtual
rb size
\}
match U, UGlobals \{ U \} }
 
uglobal
endg
iglobal
endg
 
 
; new application structure
macro meos_app_start
{
use32
org 0x0
 
db 'MENUET01'
dd 0x01
dd __start
dd __end
dd __memory
dd __stack
 
if used __params & ~defined __params
dd __params
else
dd 0x0
end if
 
dd 0x0
}
MEOS_APP_START fix meos_app_start
 
macro code
{
__start:
}
CODE fix code
 
macro data
{
__data:
IncludeIGlobals
}
DATA fix data
 
macro udata
{
if used __params & ~defined __params
__params:
db 0
__end:
rb 255
else
__end:
end if
__udata:
IncludeUGlobals
}
UDATA fix udata
 
macro meos_app_end
{
align 32
rb 2048
__stack:
__memory:
}
MEOS_APP_END fix meos_app_end
 
 
; macro for defining multiline text data
struc mstr [sstring]
{
forward
local ssize
virtual at 0
db sstring
ssize = $
end virtual
dd ssize
db sstring
common
dd -1
}
 
; macro for defining multiline text data
struc mls [sstring]
{
forward
local ssize
virtual at 0
db sstring ; mod
ssize = $
end virtual
db ssize
db sstring
common
db -1 ; mod
}
 
 
 
; strings
macro sz name,[data] { ; from MFAR [mike.dld]
common
if used name
name db data
.size = $-name
end if
}
 
macro lsz name,[lng,data] { ; from MFAR [mike.dld]
common
if used name
label name
forward
if lang eq lng
db data
end if
common
.size = $-name
end if
}
 
macro szc name,elsz,[data] { ; from MFAR [mike.dld]
common
local s,m
m = 0
if used name
label name
forward
virtual at 0
db data
s = $
end virtual
d#elsz s
if m < s
m = s
end if
db data
common
.size = $-name
.maxl = m
end if
}
 
macro lszc name,elsz,[lng,data] { ; from MFAR [mike.dld]
common
local s,m,c
m = 0
c = 0
if used name
label name
forward
if lang eq lng
virtual at 0
db data
s = $
end virtual
d#elsz s
if m < s
m = s
end if
db data
c = c+1
end if
common
.size = $-name
.maxl = m
.count = c
end if
}
 
 
; easy system call macro
macro mpack dest, hsrc, lsrc
{
if (hsrc eqtype 0) & (lsrc eqtype 0)
mov dest, (hsrc) shl 16 + lsrc
else
if (hsrc eqtype 0) & (~lsrc eqtype 0)
mov dest, (hsrc) shl 16
add dest, lsrc
else
mov dest, hsrc
shl dest, 16
add dest, lsrc
end if
end if
}
 
macro __mov reg,a,b { ; mike.dld
if (~a eq)&(~b eq)
mpack reg,a,b
else if (~a eq)&(b eq)
mov reg,a
end if
}
 
 
include 'config.inc'
;__CPU_type equ p5
SYSENTER_VAR equ 0
 
macro mcall a,b,c,d,e,f { ; mike.dld, updated by Ghost for Fast System Calls
local ..ret_point
__mov eax,a
__mov ebx,b
__mov ecx,c
__mov edx,d
__mov esi,e
__mov edi,f
 
if __CPU_type eq p5
int 0x40
else
if __CPU_type eq p6
push ebp
mov ebp, esp
push ..ret_point ; it may be 2 or 5 byte
sysenter
..ret_point:
pop edx
pop ecx
 
else
if __CPU_type eq k6
push ecx
syscall
pop ecx
else
display 'ERROR : unknown CPU type (set to p5)', 10, 13
__CPU_type equ p5
int 0x40
end if
end if
end if
}
 
 
; -------------------------
macro header a,[b] {
common
use32
org 0
db 'MENUET',a
forward
if b eq
dd 0
else
dd b
end if }
macro section name { align 16
label name }
macro func name {
if ~used name
display 'FUNC NOT USED: ',`name,13,10
else
align 4
name:
;diff16 `name,0,name
;pushad
;pushfd
;dps `name
;newline
;mcall 5,1
;popfd
;popad
}
macro endf { end if }
 
macro diff16 title,l1,l2
{
local s,d
s = l2-l1
display title,': 0x'
repeat 8
d = '0' + s shr ((8-%) shl 2) and $0F
if d > '9'
d = d + 'A'-'9'-1
end if
display d
end repeat
display 13,10
}
 
macro diff10 title,l1,l2
{
local s,d,z,m
s = l2-l1
z = 0
m = 1000000000
display title,': '
repeat 10
d = '0' + s / m
s = s - (s/m)*m
m = m / 10
if d <> '0'
z = 1
end if
if z <> 0
display d
end if
end repeat
display 13,10
}
 
; optimize the code for size
__regs fix <eax,ebx,ecx,edx,esi,edi,ebp,esp>
 
macro add arg1,arg2
{
if (arg2 eqtype 0)
if (arg2) = 1
inc arg1
else
add arg1,arg2
end if
else
add arg1,arg2
end if
}
 
macro sub arg1,arg2
{
if (arg2 eqtype 0)
if (arg2) = 1
dec arg1
else
sub arg1,arg2
end if
else
sub arg1,arg2
end if
}
 
macro mov arg1,arg2
{
if (arg1 in __regs) & ((arg2 eqtype 0) | (arg2 eqtype '0'))
if (arg2) = 0
xor arg1,arg1
else if (arg2) = 1
xor arg1,arg1
inc arg1
else if (arg2) = -1
or arg1,-1
else if (arg2) > -128 & (arg2) < 128
push arg2
pop arg1
else
mov arg1,arg2
end if
else
mov arg1,arg2
end if
}
 
 
macro RGB [a] {
common
match (r=,g=,b),a \{
\dd ((r) shl 16) or ((g) shl 8) or (b)
\}
}
 
 
struc POINT _t,_dx,_dy {
.x _t _dx
.y _t _dy
}
 
; structure definition helper
include 'struct.inc'
 
struct RECT
left dd ?
top dd ?
right dd ?
bottom dd ?
ends
 
struct BOX
left dd ?
top dd ?
width dd ?
height dd ?
ends
 
; structures used in MeOS
struct process_information
cpu_usage dd ? ; +0
window_stack_position dw ? ; +4
window_stack_value dw ? ; +6
dw ? ; +8
process_name rb 12 ; +10
memory_start dd ? ; +22
used_memory dd ? ; +26
PID dd ? ; +30
box BOX ; +34
slot_state dw ? ; +50
dw ? ; +52
client_box BOX ; +54
wnd_state db ? ; +70
rb (1024-71)
ends
 
struct system_colors
frame dd ?
grab dd ?
grab_button dd ?
grab_button_text dd ?
grab_text dd ?
work dd ?
work_button dd ?
work_button_text dd ?
work_text dd ?
work_graph dd ?
ends
 
struct FILEDATE
Second db ?
Minute db ?
Hour db ?
db ?
Day db ?
Month db ?
Year dw ?
ends
 
struct FILEINFO
Attributes dd ?
IsUnicode db ?
db 3 dup(?)
DateCreate FILEDATE
DateAccess FILEDATE
DateModify FILEDATE
Size dq ?
ends
 
 
if __CPU_type eq p5 ; CMOVcc isnt supported on the P5
 
cmove fix cmovz
macro cmovz reg1, reg2 {
 
local .jumpaddr
 
jnz .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
cmovne fix cmovnz
macro cmovnz reg1, reg2 {
 
local .jumpaddr
 
jz .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
macro cmovg reg1, reg2 {
 
local .jumpaddr
 
jle .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
macro cmovl reg1, reg2 {
 
local .jumpaddr
 
jge .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
end if
 
; constants
 
; events
EV_IDLE = 0
EV_TIMER = 0
EV_REDRAW = 1
EV_KEY = 2
EV_BUTTON = 3
EV_EXIT = 4
EV_BACKGROUND = 5
EV_MOUSE = 6
EV_IPC = 7
EV_STACK = 8
 
; event mask bits for function 40
EVM_REDRAW = 1b
EVM_KEY = 10b
EVM_BUTTON = 100b
EVM_EXIT = 1000b
EVM_BACKGROUND = 10000b
EVM_MOUSE = 100000b
EVM_IPC = 1000000b
EVM_STACK = 10000000b
EVM_DEBUG = 100000000b
EVM_STACK2 = 1000000000b
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/applications/zeroconf/network.ini
0,0 → 1,9
[ipconfig]
; type should be static or zeroconf
; zeroconf means the service first tries to contact a DHCP server
; If dhcp is not available, it switches to link-local
type = zeroconf
ip = 192.168.1.150
gateway = 192.168.1.1
dns = 192.168.1.1
subnet = 255.255.255.0
/kernel/branches/net/applications/zeroconf/zeroconf.asm
0,0 → 1,620
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; zeroconfig.asm - Zeroconfig service for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; Some code contributed by Derpenguin ;;
;; ;;
;; DHCP code is based on that by Mike Hibbet ;;
; (DHCP client for menuetos) ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format binary as ""
 
use32
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd IM_END ; size of image
dd (I_END+0x100) ; memory for app
dd (I_END+0x100) ; esp
dd 0, 0 ; I_Param, I_Path
 
; CONFIGURATION
 
TIMEOUT = 60 ; in seconds
BUFFER = 1024 ; in bytes
__DEBUG__ = 1 ; enable/disable
__DEBUG_LEVEL__ = 1 ; 1 = all, 2 = errors
 
; CONFIGURATION FOR LINK-LOCAL
 
PROBE_WAIT = 1 ; second (initial random delay)
PROBE_MIN = 1 ; second (minimum delay till repeated probe)
PROBE_MAX = 2 ; seconds (maximum delay till repeated probe)
PROBE_NUM = 3 ; (number of probe packets)
 
ANNOUNCE_NUM = 2 ; (number of announcement packets)
ANNOUNCE_INTERVAL = 2 ; seconds (time between announcement packets)
ANNOUNCE_WAIT = 2 ; seconds (delay before announcing)
 
MAX_CONFLICTS = 10 ; (max conflicts before rate limiting)
 
RATE_LIMIT_INTERVAL = 60 ; seconds (delay between successive attempts)
 
DEFEND_INTERVAL = 10 ; seconds (min. wait between defensive ARPs)
 
 
include '../proc32.inc'
include '../macros.inc'
include '../debug-fdo.inc'
include '../network.inc'
include 'dhcp.inc'
include '../dll.inc'
 
 
Ip2dword:
push edx
 
; This code validates if the query is an IP containing 4 numbers and 3 dots
 
xor al, al ; make al (dot count) zero
 
@@:
cmp byte[edx],'0' ; check if this byte is a number, if not jump to no_IP
jl no_IP ;
cmp byte[edx],'9' ;
jg no_IP ;
 
inc edx ; the byte was a number, so lets check the next byte
 
cmp byte[edx],0 ; is this byte zero? (have we reached end of query?)
jz @f ; jump to next @@ then
cmp byte[edx],':'
jz @f
 
cmp byte[edx],'.' ; is this byte a dot?
jne @r ; if not, jump to previous @@
 
inc al ; the byte was a dot so increment al(dot count)
inc edx ; next byte
jmp @r ; lets check for numbers again (jump to previous @@)
 
@@: ; we reach this when end of query reached
cmp al,3 ; check if there where 3 dots
jnz no_IP ; if not, jump to no_IP
 
; The following code will convert this IP into a dword and output it in eax
; If there is also a port number specified, this will be returned in ebx, otherwise ebx is -1
 
pop esi ; edx (query address) was pushed onto stack and is now popped in esi
 
xor edx, edx ; result
xor eax, eax ; current character
xor ebx, ebx ; current byte
 
.outer_loop:
shl edx, 8
add edx, ebx
xor ebx, ebx
.inner_loop:
lodsb
test eax, eax
jz .finish
cmp al, '.'
jz .outer_loop
sub eax, '0'
imul ebx, 10
add ebx, eax
jmp .inner_loop
.finish:
shl edx, 8
add edx, ebx
 
bswap edx ; we want little endian order
 
ret
 
no_IP:
pop edx
xor edx, edx
 
ret
 
 
 
 
 
 
START:
mcall 40, EVM_STACK2
 
DEBUGF 1,">Zero-config service loaded\n"
 
.wait:
mcall 76, API_ETH + 4 ; get MAC of ethernet interface 0
cmp eax, -1
jne .start
 
mcall 10
jmp .wait
 
.start:
mov word[MAC], bx
mov dword[MAC+2], eax
DEBUGF 1,"->MAC: %x-%x-%x-%x-%x-%x\n", [MAC+0]:2, [MAC+1]:2, [MAC+2]:2, [MAC+3]:2, [MAC+4]:2, [MAC+5]:2
 
mcall 40, EVM_STACK
 
mcall 68, 11
 
stdcall dll.Load,@IMPORT
or eax, eax
jnz try_dhcp
 
invoke ini.get_str, path, str_ipconfig, str_type, inibuf, 16, 0
 
cmp dword[inibuf], 'stat'
jne try_dhcp
 
invoke ini.get_str, path, str_ipconfig, str_ip, inibuf, 16, 0
mov edx, inibuf
call Ip2dword
mcall 76, API_IPv4 + 3, edx
 
invoke ini.get_str, path, str_ipconfig, str_gateway, inibuf, 16, 0
mov edx, inibuf
call Ip2dword
mcall 76, API_IPv4 + 9, edx
 
invoke ini.get_str, path, str_ipconfig, str_dns, inibuf, 16, 0
mov edx, inibuf
call Ip2dword
mcall 76, API_IPv4 + 5, edx
 
invoke ini.get_str, path, str_ipconfig, str_subnet, inibuf, 16, 0
mov edx, inibuf
call Ip2dword
mcall 76, API_IPv4 + 7, edx
 
 
mcall -1
 
 
try_dhcp:
 
DEBUGF 1,"->Trying DHCP\n"
 
mcall 75, 0, AF_INET4, SOCK_DGRAM, 0 ; open socket (parameters: domain, type, reserved)
cmp eax, -1
je error
mov [socketNum], eax
 
DEBUGF 1,"->Socket %x opened\n", eax
 
mcall 75, 2, [socketNum], sockaddr1, 18 ; bind socket to local port 68
cmp eax, -1
je error
 
DEBUGF 1,"->Socket Bound to local port 68\n"
 
mcall 75, 4, [socketNum], sockaddr2, 18 ; connect to 255.255.255.255 on port 67
cmp eax, -1
je error
 
DEBUGF 1,"->Connected to 255.255.255.255 on port 67\n"
 
mov [dhcpMsgType], 0x01 ; DHCP discover
mov [dhcpLease], esi ; esi is still -1 (-1 = forever)
 
mcall 26, 9 ; Get system time
imul eax, 100
mov [currTime], eax
 
build_request: ; Creates a DHCP request packet.
 
DEBUGF 1,"->Building request\n"
 
stdcall mem.Alloc, BUFFER
mov [dhcpMsg], eax
test eax, eax
jz dhcp_error
 
;;; todo: skip this bullcrap
 
mov edi, eax
mov ecx, BUFFER
xor eax, eax
rep stosb
 
;; todo: put this in a buffer instead of writing bytes and words!
 
mov edx, [dhcpMsg]
 
; Boot protocol legacy
mov [edx], byte 0x01 ; Boot request
mov [edx+1], byte 0x01 ; Ethernet
mov [edx+2], byte 0x06 ; Ethernet h/w len
mov [edx+4], dword 0x11223344 ; xid ;;;;;;;
mov eax, [currTime]
mov [edx+8], eax ; secs, our uptime
mov [edx+10], byte 0x80 ; broadcast flag set
mov eax, dword [MAC] ; first 4 bytes of MAC
mov [edx+28],dword eax
mov ax, word [MAC+4] ; last 2 bytes of MAC
mov [edx+32],word ax
 
; DHCP extension
mov [edx+236], dword 0x63538263 ; magic cookie
mov [edx+240], word 0x0135 ; option DHCP msg type
mov al, [dhcpMsgType]
mov [edx+240+2], al
mov [edx+240+3], word 0x0433 ; option Lease time = infinity
mov eax, [dhcpLease]
mov [edx+240+5], eax
mov [edx+240+9], word 0x0432 ; option requested IP address
mov eax, [dhcp.ip]
mov [edx+240+11], eax
mov [edx+240+15], word 0x0437 ; option request list
mov [edx+240+17], dword 0x0f060301
 
cmp [dhcpMsgType], byte 0x01 ; Check which msg we are sending
jne request_options
 
mov [edx+240+21], byte 0xff ; "Discover" options
 
mov [dhcpMsgLen], dword 262 ; end of options marker
jmp send_dhcpmsg
 
request_options:
mov [edx+240+21], word 0x0436 ; server IP
mov eax, [dhcpServerIP]
mov [edx+240+23], eax
 
mov [edx+240+27], byte 0xff ; end of options marker
 
mov [dhcpMsgLen], dword 268
 
send_dhcpmsg:
mcall 75, 6, [socketNum], [dhcpMsg], [dhcpMsgLen] ; write to socket ( send broadcast request )
 
mov eax, [dhcpMsg] ; Setup the DHCP buffer to receive response
mov [dhcpMsgLen], eax ; Used as a pointer to the data
 
mcall 23, TIMEOUT*10 ; wait for data
 
read_data: ; we have data - this will be the response
mcall 75, 7, [socketNum], [dhcpMsg], BUFFER ; read data from socket
 
DEBUGF 1,"->%d bytes received\n", eax
 
cmp eax, -1
je dhcp_error
 
mov [dhcpMsgLen], eax
 
; depending on which msg we sent, handle the response
; accordingly.
; If the response is to a dhcp discover, then:
; 1) If response is DHCP OFFER then
; 1.1) record server IP, lease time & IP address.
; 1.2) send a request packet
; If the response is to a dhcp request, then:
; 1) If the response is DHCP ACK then
; 1.1) extract the DNS & subnet fields. Set them in the stack
 
cmp [dhcpMsgType], 0x01 ; did we send a discover?
je discover
 
cmp [dhcpMsgType], 0x03 ; did we send a request?
je request
 
call dhcp_end ; we should never reach here ;)
jmp exit
 
discover:
call parse_response
 
cmp [dhcpMsgType], 0x02 ; Was the response an offer?
je send_request
 
call dhcp_end
jmp link_local
 
send_request:
mov [dhcpMsgType], 0x03 ; make it a request
jmp build_request
 
request:
call parse_response
 
cmp [dhcpMsgType], 0x05 ; Was the response an ACK? It should be
jne read_data ; NO - read next packets
 
call dhcp_end
 
mcall 76, API_IPv4 + 3, [dhcp.ip] ; ip
mcall 76, API_IPv4 + 5, [dhcp.dns] ; dns
mcall 76, API_IPv4 + 7, [dhcp.subnet] ; subnet
mcall 76, API_IPv4 + 9, [dhcp.gateway] ; gateway
 
jmp exit
 
dhcp_end:
mcall close, [socketNum]
stdcall mem.Free, [dhcpMsg]
 
ret
 
;***************************************************************************
; Function
; parseResponse
;
; Description
; extracts the fields ( client IP address and options ) from
; a DHCP response
; The values go into
; dhcpMsgType,dhcpLease,dhcpClientIP,dhcpServerIP,
; dhcpDNSIP, dhcpSubnet
; The message is stored in dhcpMsg
;
;***************************************************************************
parse_response:
 
DEBUGF 1,"Data received, parsing response\n"
mov edx, [dhcpMsg]
 
push dword [edx+16]
pop [dhcp.ip]
DEBUGF 1,"Client: %u.%u.%u.%u\n", [edx+16]:1, [edx+17]:1, [edx+18]:1, [edx+19]:1
 
; TODO: check if there really are options
 
mov al, 240 ; Point to first option
movzx ecx, al
 
.next_option:
add edx, ecx
 
mov al, [edx] ; get message identifier
 
cmp al, 0xff ; End of options?
je .done
 
cmp al, 0
je .pad
 
; TODO: check if we still are inside the buffer
 
inc edx
movzx ecx, byte [edx] ; get data length
inc edx ; point to data
 
cmp al, dhcp_msg_type ; Msg type is a single byte option
je .msgtype
 
cmp al, dhcp_dhcp_server_id
je .server
 
cmp al, dhcp_address_time
je .lease
 
cmp al, dhcp_subnet_mask
je .subnet
 
cmp al, dhcp_router
je .router
 
cmp al, dhcp_domain_server
je .dns
 
DEBUGF 1,"Unsupported DHCP option: %u\n", al
 
jmp .next_option
 
.pad:
xor ecx, ecx
inc ecx
jmp .next_option
 
.msgtype:
mov al, [edx]
mov [dhcpMsgType], al
 
DEBUGF 1,"DHCP Msg type: %u\n", al
jmp .next_option ; Get next option
 
.server:
mov eax, [edx]
mov [dhcpServerIP], eax
DEBUGF 1,"Server: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
jmp .next_option
 
.lease:
pusha
mov eax,[edx]
bswap eax
mov [dhcpLease],eax
DEBUGF 1,"lease: %d\n",eax
popa
jmp .next_option
 
.subnet:
push dword [edx]
pop [dhcp.subnet]
DEBUGF 1,"Subnet: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
jmp .next_option
 
.router:
push dword [edx]
pop [dhcp.gateway]
DEBUGF 1,"Gateway: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
jmp .next_option
 
.dns:
push dword [edx]
pop [dhcp.dns]
DEBUGF 1,"DNS: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
jmp .next_option
 
.done:
ret
 
 
 
dhcp_error:
call dhcp_end
 
link_local:
call random
mov cx, ax
shl ecx, 16
mov cx, 0xfea9 ; IP 169.254.0.0 link local net, see RFC3927
mcall 76, API_IPv4 + 3, ecx ; mask is 255.255.0.0
DEBUGF 1,"Link Local IP assinged: 169.254.%u.%u\n", [generator+0]:1, [generator+1]:1
mcall 76, API_IPv4 + 7, 0xffff
mcall 76, API_IPv4 + 9, 0x0
mcall 76, API_IPv4 + 5, 0x0
 
mcall 5, PROBE_WAIT*100
 
xor esi, esi
probe_loop:
call random ; create a pseudo random number in eax (seeded by MAC)
 
cmp al, PROBE_MIN*100 ; check if al is bigger then PROBE_MIN
jae @f ; all ok
add al, (PROBE_MAX-PROBE_MIN)*100 ; al is too small
@@:
 
cmp al, PROBE_MAX*100
jbe @f
sub al, (PROBE_MAX-PROBE_MIN)*100
@@:
 
movzx ebx,al
DEBUGF 1,"Waiting %u0ms\n",ebx
mcall 5
 
DEBUGF 1,"Sending Probe\n"
mcall 76, API_ARP + 6
inc esi
 
cmp esi, PROBE_NUM
jb probe_loop
 
; now we wait further ANNOUNCE_WAIT seconds and send ANNOUNCE_NUM ARP announces. If any other host has assingned
; IP within this time, we should create another adress, that have to be done later
 
DEBUGF 1,"Waiting %us\n", ANNOUNCE_WAIT
mcall 5, ANNOUNCE_WAIT*100
xor esi, esi
announce_loop:
 
DEBUGF 1,"Sending Announce\n"
mcall 76, API_ARP + 6
 
inc esi
cmp esi,ANNOUNCE_NUM
je @f
 
DEBUGF 1,"Waiting %us\n", ANNOUNCE_INTERVAL
mcall 5, ANNOUNCE_INTERVAL*100
jmp announce_loop
@@:
 
 
error:
DEBUGF 1,"Socket error\n"
exit: ; we should, instead of closing, detect ARP conflicts and detect if cable keeps connected ;)
mcall -1
 
 
random: ; Pseudo random actually
 
mov eax, [generator]
add eax, -43ab45b5h
ror eax, 1
bswap eax
xor eax, dword[MAC]
ror eax, 1
xor eax, dword[MAC+2]
mov [generator], eax
 
ret
 
; DATA AREA
 
align 16
@IMPORT:
 
library \
libini,'libini.obj'
 
import libini, \
ini.get_str,'ini_get_str'
 
include_debug_strings
 
str_ip db 'ip', 0
str_subnet db 'subnet', 0
str_gateway db 'gateway', 0
str_dns db 'dns', 0
str_ipconfig db 'ipconfig', 0
str_type db 'type', 0
 
 
sockaddr1:
 
dw AF_INET4
dw 68 shl 8 ; local port
dd 0 ; local IP
 
rb 10
 
 
sockaddr2:
 
dw AF_INET4
dw 67 shl 8 ; destination port
dd -1 ; destination IP
 
rb 10
 
path db '/sys/network.ini'
 
IM_END:
 
inibuf rb 16
 
dhcpMsgType db ?
dhcpLease dd ?
dhcpServerIP dd ?
 
dhcp:
.ip dd ?
.subnet dd ?
.dns dd ?
.gateway dd ?
 
 
dhcpMsgLen dd ?
socketNum dd ?
 
MAC dp ?
 
currTime dd ?
generator dd ?
 
dhcpMsg dd ?
 
I_END:
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/applications/zeroconf/dhcp.inc
0,0 → 1,263
;Name Number Length Meaning
 
dhcp_pad_option equ 0 ; 0 None
dhcp_end_option equ 255 ; 0 None
dhcp_subnet_mask equ 1 ; 4 Subnet Mask Value
dhcp_time_offset equ 2 ; 4 Time Offset in Seconds from UTC
dhcp_router equ 3 ; N×4 Router addresses
dhcp_time_server equ 4 ; N×4 Timeserver addresses
dhcp_name_server equ 5 ; N×4 IEN-116 Server addresses
dhcp_domain_server equ 6 ; N×4 DNS Server addresses
dhcp_log_server equ 7 ; N×4 Logging Server addresses
dhcp_quotes_server equ 8 ; N×4 Quotes Server addresses
dhcp_lpr_server equ 9 ; N×4 Printer Server addresses
dhcp_impress_server equ 10 ; N×4 Impress Server addresses
dhcp_rlp_server equ 11 ; N×4 N RLP Server addresses
dhcp_hostname equ 12 ; N Hostname string
dhcp_boot_file_size equ 13 ; 2 Size of boot file in 512-octet blocks
dhcp_merit_dump_file equ 14 ; N Client to dump and name the file to dump it to
dhcp_domain_name equ 15 ; N The DNS domain name of the client
dhcp_swap_server equ 16 ; 4 Swap Server address
dhcp_root_path equ 17 ; N Path name for root disk
dhcp_extension_file equ 18 ; N Path name for more BOOTP info
 
;IP Layer Parameters per Host
 
dhcp_forward equ 19 ; 1 Enable/Disable IP Forwarding
dhcp_srcrte equ 20 ; 1 Enable/Disable Non-Local Source Routing
dhcp_policy equ 21 ; N×8 Non-Local Source Routing Policy Filters
dhcp_mag_dg_assembly equ 22 ; 2 Max Datagram Reassembly Size
dhcp_default_ip_tll equ 23 ; 1 Default IP Time to Live
dhcp_mtu_timeout equ 24 ; 4 Path MTU Aging Timeout
dhcp_mtu_plateau equ 25 ; N×2 Path MTU Plateau Table
 
;IP Layer Parameters per Interface
 
dhcp_mtu_interface equ 26 ; 2 Interface MTU Size
dhcp_mtu_subnet equ 27 ; 1 All Subnets are Local
dhcp_broadcast_address equ 28 ; 4 Broadcast Address
dhcp_mask_discovery equ 29 ; 1 Perform Mask Discovery
dhcp_mask_supplier equ 30 ; 1 Provide Mask to Others
dhcp_router_discovery equ 31 ; 1 Perform Router Discovery
dhcp_router_request equ 32 ; 4 Router Solicitation Address
dhcp_static_route equ 33 ; N×8 Static Routing Table
 
;Link Layer Parameters per Interface
 
dhcp_trailers equ 34 ; 1 Trailer Encapsulation
dhcp_arp_timeout equ 35 ; 4 ARP Cache Timeout
dhcp_ethernet equ 36 ; 1 Ethernet Encapsulation
 
;TCP Parameters
 
dhcp_default_tcp_tll equ 37 ; 1 Default TCP Time to Live
dhcp_keepalive_time equ 38 ; 4 TCP Keepalive Interval
dhcp_keepalive_data equ 39 ; 1 TCP Keepalive Garbage
 
;Application and Service Parameters
 
dhcp_nis_domain equ 40 ; N NIS Domain Name
dhcp_nis_servers equ 41 ; N×4 NIS Server Addresses
dhcp_ntp_servers equ 42 ; N×4 NTP Server Addresses
dhcp_vendor_specific equ 43 ; N Vendor Specific Information
dhcp_netbios_name_srv equ 44 ; N×4 NETBIOS Name Servers
dhcp_netbios_dist_srv equ 45 ; N×4 NETBIOS Datagram Distribution
dhcp_netbios_node_type equ 46 ; 1 NETBIOS Node Type
dhcp_netbios_scope equ 47 ; N NETBIOS Scope
dhcp_x_window_font equ 48 ; N×4 X Window Font Server
dhcp_x_window_manager equ 49 ; N×4 X Window Display Manager
dhcp_nis_domain_name equ 64 ; N NIS+ v3 Client Domain Name
dhcp_nis_server_addr equ 65 ; N×4 NIS+ v3 Server Addresses
dhcp_home_agent_addrs equ 68 ; N×4 Mobile IP Home Agent Addresses
dhcp_smtp_server equ 69 ; N×4 Simple Mail Server Addresses
dhcp_pop3_server equ 70 ; N×4 Post Office Server Addresses
dhcp_nntp_server equ 71 ; N×4 Network News Server Addresses
dhcp_www_server equ 72 ; N×4 WWW Server Addresses
dhcp_finger_server equ 73 ; N×4 Finger Server Addresses
dhcp_irc_server equ 74 ; N×4 Chat Server Addresses
dhcp_streettalk_server equ 75 ; N×4 StreetTalk Server Addresses
dhcp_stda_server equ 76 ; N×4 ST Directory Assist. Addresses
 
;DHCP Extensions
 
dhcp_address_request equ 50 ; 4 Requested IP Address
dhcp_address_time equ 51 ; 4 IP Address Lease Time
dhcp_option_overload equ 52 ; 1 Overload "sname" or "file"
dhcp_msg_type equ 53 ; 1 DHCP Message Type
dhcp_dhcp_server_id equ 54 ; 4 DHCP Server Identification
dhcp_parameter_list equ 55 ; N Parameter Request List
dhcp_dhcp_message equ 56 ; N DHCP Error Message
dhcp_dhcp_max_msg_size equ 57 ; 2 DHCP Maximum Message Size
dhcp_renewal_time equ 58 ; 4 DHCP Renewal (T1) Time
dhcp_rebinding_time equ 59 ; 4 DHCP Rebinding (T2) Time
dhcp_class_id equ 60 ; N Vendor Class Identifier
dhcp_client_id equ 61 ; N Client Identifier
dhcp_server_name equ 66 ; N TFTP Server Name
dhcp_bootfile_name equ 67 ; N Boot File Name
 
;Newer extensions
 
dhcp_netware_ip_domain equ 62 ; N Netware/IP Domain Name
dhcp_netware_ip_option equ 63 ; N Netware/IP sub Options
dhcp_user_class equ 77 ; N User Class Information
dhcp_directory_agent equ 78 ; N directory agent information
dhcp_service_scope equ 79 ; N service location agent scope
dhcp_rapid_commit equ 80 ; 0 Rapid Commit
dhcp_client_fqdn equ 81 ; N Fully Qualified Domain Name
dhcp_relay_agent_info equ 82 ; N Relay Agent Information, RFC 3046
dhcp_isns equ 83 ; N Internet Storage Name Service
; 84 REMOVED/Unassigned
dhcp_nds_servers equ 85 ; N Novell Directory Services
dhcp_nds_tree_name equ 86 ; N Novell Directory Services
dhcp_nds_conext equ 87 ; N Novell Directory Services
dhcp_bcmcs equ 88 ; Controller Domain Name list
dhcp_bcmcs equ 89 ; Controller IPv4 address option
dhcp_authentication equ 90 ; N Authentication
; 91 REMOVED/Unassigned
; 92 REMOVED/Unassigned
dhcp_client_system equ 93 ; N Client System Architecture
dhcp_client_ndi equ 94 ; N Client Network Device Interface
dhcp_ldap equ 95 ; N Lightweight Directory Access Protocol
; 96 REMOVED/Unassigned
dhcp_uuid_guid equ 97 ; N UUID/GUID-based Client Identifier
dchp_user_auth equ 98 ; N Open Group's User Authentication
; 99 REMOVED/Unassigned
; 100 REMOVED/Unassigned
; 101 REMOVED/Unassigned
; 102 REMOVED/Unassigned
; 103 REMOVED/Unassigned
; 104 REMOVED/Unassigned
; 105 REMOVED/Unassigned
; 106 REMOVED/Unassigned
; 107 REMOVED/Unassigned
; 108 REMOVED/Unassigned
; 109 REMOVED/Unassigned
; 110 REMOVED/Unassigned
; 111 REMOVED/Unassigned
dhcp_netinfo_address equ 112 ; N NetInfo Parent Server Address
dhcp_netinfo_tag equ 113 ; N NetInfo Parent Server Tag
dhcp_url equ 114 ; N URL
; 115 REMOVED/Unassigned
dhcp_auto_config equ 116 ; N DHCP Auto-Configuration
dhcp_ns_search equ 117 ; N Name Service Search
dhcp_subnet_selection equ 118 ; 4 Subnet Selection Option
dhcp_domain_search equ 119 ; N DNS domain search list
dhcp_sip_servers equ 120 ; N SIP Servers DHCP Option
dhcp_cl_static_route equ 121 ; N Classless Static Route Option
dhcp_ccc equ 122 ; N CableLabs Client Configuration
dhcp_geoconf equ 123 ; 16 GeoConf Option
dhcp_v_i_vendor_class equ 124 ; Vendor-Identifying Vendor Class
dhcp_v_i_vendor_spec equ 125 ; Vendor-Identifying Vendor-Specific
; 126 REMOVED/Unassigned
; 127 REMOVED/Unassigned
dhcp_pxe equ 128 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_etherboot_sign equ 128 ; Etherboot signature. 6 bytes: E4:45:74:68:00:00
dhcp_docsis equ 128 ; DOCSIS "full security" server IP address
dhcp_tftp_server_ip equ 128 ; TFTP Server IP address (for IP Phone software load)
dhcp_pxe equ 129 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_kernel_options equ 129 ; Kernel options. Variable length string
dhcp_call_server_ip equ 129 ; Call Server IP address
dhcp_pxe equ 130 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_ethernet_interface equ 130 ; Ethernet interface. Variable length string.
dhcp_siscrimination equ 130 ; Discrimination string (to identify vendor)
dhcp_pxe equ 131 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_remote_stat_server equ 131 ; Remote statistics server IP address
dhcp_pxe equ 132 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_802.1p equ 132 ; 802.1P VLAN ID
dhcp_pxe equ 133 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_802.1q equ 133 ; 802.1Q L2 Priority
dhcp_pxe equ 134 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_diffserv equ 134 ; Diffserv Code Point
dhcp_pxe equ 135 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_http_proxy_psa equ 135 ; HTTP Proxy for phone-specific applications
; 136 REMOVED/Unassigned
; 137 REMOVED/Unassigned
; 138 REMOVED/Unassigned
; 139 REMOVED/Unassigned
; 140 REMOVED/Unassigned
; 141 REMOVED/Unassigned
; 142 REMOVED/Unassigned
; 143 REMOVED/Unassigned
; 144 REMOVED/Unassigned
; 145 REMOVED/Unassigned
; 146 REMOVED/Unassigned
; 147 REMOVED/Unassigned
; 148 REMOVED/Unassigned
; 149 REMOVED/Unassigned
dhcp_tftp_server_addr equ 150 ; TFTP server address (Tentatively Assigned - 23 June 2005)
dhcp_etherboot equ 150 ; Etherboot
dhcp_grub_conf_path equ 150 ; GRUB configuration path name
; 151 REMOVED/Unassigned
; 152 REMOVED/Unassigned
; 153 REMOVED/Unassigned
; 154 REMOVED/Unassigned
; 155 REMOVED/Unassigned
; 156 REMOVED/Unassigned
; 157 REMOVED/Unassigned
; 158 REMOVED/Unassigned
; 159 REMOVED/Unassigned
; 160 REMOVED/Unassigned
; 161 REMOVED/Unassigned
; 162 REMOVED/Unassigned
; 163 REMOVED/Unassigned
; 164 REMOVED/Unassigned
; 165 REMOVED/Unassigned
; 166 REMOVED/Unassigned
; 167 REMOVED/Unassigned
; 168 REMOVED/Unassigned
; 169 REMOVED/Unassigned
; 170 REMOVED/Unassigned
; 171 REMOVED/Unassigned
; 172 REMOVED/Unassigned
; 173 REMOVED/Unassigned
; 174 REMOVED/Unassigned
dhcp_etherboot equ 175 ; Etherboot (Tentatively Assigned - 23 June 2005)
dhcp_ip_telephone equ 176 ; IP Telephone (Tentatively Assigned - 23 June 2005)
dhcp_etherboot equ 177 ; Etherboot (Tentatively Assigned - 23 June 2005)
dhcp_packetcable equ 177 ; PacketCable and CableHome (replaced by 122)
; 178 REMOVED/Unassigned
; 179 REMOVED/Unassigned
; 180 REMOVED/Unassigned
; 181 REMOVED/Unassigned
; 182 REMOVED/Unassigned
; 183 REMOVED/Unassigned
; 184 REMOVED/Unassigned
; 185 REMOVED/Unassigned
; 186 REMOVED/Unassigned
; 187 REMOVED/Unassigned
; 188 REMOVED/Unassigned
; 189 REMOVED/Unassigned
; 190 REMOVED/Unassigned
; 191 REMOVED/Unassigned
; 192 REMOVED/Unassigned
; 193 REMOVED/Unassigned
; 194 REMOVED/Unassigned
; 195 REMOVED/Unassigned
; 196 REMOVED/Unassigned
; 197 REMOVED/Unassigned
; 198 REMOVED/Unassigned
; 199 REMOVED/Unassigned
; 200 REMOVED/Unassigned
; 201 REMOVED/Unassigned
; 202 REMOVED/Unassigned
; 203 REMOVED/Unassigned
; 204 REMOVED/Unassigned
; 205 REMOVED/Unassigned
; 206 REMOVED/Unassigned
; 207 REMOVED/Unassigned
dhcp_pxelinux.magic equ 208 ; pxelinux.magic (string) = F1:00:74:7E (241.0.116.126) (Tentatively Assigned - 23 June 2005)
dhcp_pxelinux.conffile equ 209 ; pxelinux.configfile (text) (Tentatively Assigned - 23 June 2005)
dhcp_pxelinux.path equ 210 ; pxelinux.pathprefix (text) (Tentatively Assigned - 23 June 2005)
dhcp_pxelinux.reboot equ 211 ; pxelinux.reboottime (unsigned integer 32 bits) (Tentatively Assigned - 23 June 2005)
; 212 REMOVED/Unassigned
; 213 REMOVED/Unassigned
; 214 REMOVED/Unassigned
; 215 REMOVED/Unassigned
; 216 REMOVED/Unassigned
; 217 REMOVED/Unassigned
; 218 REMOVED/Unassigned
; 219 REMOVED/Unassigned
dhcp_subnet_aloc equ 220 ; Subnet Allocation Option (Tentatively Assigned - 23 June 2005)
dhcp_virtual_subnet equ 221 ; Virtual Subnet Selection Option (Tentatively Assigned - 23 June 2005)
; 222 REMOVED/Unassigned
; 223 REMOVED/Unassigned
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/applications/netcfg/vendors.inc
0,0 → 1,1072
; AUTHOR: Victor Alberto Gil Hancco Laquita <vhanla@gmail.com>
; This list might content mistakes, plz report it
; There are 865 Lists of Vendors' Names
; Date: 8/14/2005
;
; maybe this list is outdated...
; (the source was from 2004 list)
 
; changed 11/05/2006: + 3 vendors and no more label 'PREVIOUSVERSIONLIST'
; so the total quantity of vendors is 875 now (changes by Sergey Kuzmin)
 
; changed 16/08/2006: + 122 vendors
; so the total quantity of vendors is 987 now (changes by Sergey Kuzmin)
 
; changed ??/04/2007:
; size optimezed
; total quantity of vendors is 997 now (changes by Mihailov Ilia)
 
 
macro VendorID a,b { ; by mike.dld
dw a
dd _vtmp#a
\iglobal
_vtmp#a db b
db 0
\};endg
}
 
macro ClassID a,b,c,d {
db a
db b
local tt
 
if c eq
db 0
db 1
tt = 'x'
else
db c
db 0
tt = c
end if
dd _ctmp#a#b#tt
\iglobal
_ctmp#a#b#tt db d
db 0
\};endg
}
 
;--------------------------------------
VendorsTab:
VendorID 0x0033, 'PARADYNE CORP.'
VendorID 0x003D, 'Lockheed Martin Corp'
VendorID 0x0100, 'NCIPHER CORP. LTD'
VendorID 0x0675, 'DYNALINK'
VendorID 0x0571, 'BERKOM'
VendorID 0x0A89, 'BREA TECHNOLOGIES INC'
VendorID 0x0E11, 'COMPAQ COMPUTER CORP.'
VendorID 0x1000, 'SYMBIOS LOGIC INC/LSI Logic'
VendorID 0x1001, 'KOLTER ELECTRONIC'
VendorID 0x1002, 'ATI TECHNOLOGIES INC'
VendorID 0x1003, 'ULSI'
VendorID 0x1004, 'VLSI TECHNOLOGY INC'
VendorID 0x1005, 'ADL'
VendorID 0x100B, 'NATIONAL SEMICONDUCTOR CORPORATION'
VendorID 0x100C, 'Tseng Labs'
VendorID 0x100E, 'Weitek'
VendorID 0x1010, 'VIDEO LOGIC LTD'
VendorID 0x1011, 'Digital Equipment Corporation'
VendorID 0x1013, 'Cirrus Logic'
VendorID 0x1014, 'IBM'
VendorID 0x1017, 'Spea Software AG'
VendorID 0x1018, 'UNISYS CORPORATION'
VendorID 0x1019, 'ELITEGROUP COMPUTER SYS'
VendorID 0x101A, 'NCR Corporation'
VendorID 0x101E, 'AMERICAN MEGATRENDS'
VendorID 0x1020, 'HITACHI COMPUTER PRODUCTS'
VendorID 0x1021, 'OKI ELECTRIC INDUSTRY CO. LTD.'
VendorID 0x1022, 'Advanced Micro Devices'
VendorID 0x1023, 'TRIDENT MICROSYSTEMS'
VendorID 0x1025, 'Acer Incorporated'
VendorID 0x1028, 'DELL COMPUTER CORPORATION'
VendorID 0x102A, 'LSI LOGIC CORPORATION'
VendorID 0x102B, 'MATROX GRAPHICS'
VendorID 0x102C, 'Asiliant (Chips And Technologies)'
VendorID 0x102D, 'Wyse Technologies'
VendorID 0x102F, 'TOSHIBA AMERICA'
VendorID 0x1031, 'miro Computer Products AG'
VendorID 0x1033, 'NEC CORPORATION'
VendorID 0x1036, 'Future Domain'
VendorID 0x1038, 'AMP'
VendorID 0x1039, 'SILICON INTEGRATED SYSTEMS'
VendorID 0x103C, 'Hewlett-Packard Company'
VendorID 0x103F, 'SYNOPSYS/LOGIC MODELING GROUP'
VendorID 0x1042, 'Micron Electronics'
VendorID 0x1043, 'ASUSTEK COMPUTER'
VendorID 0x1044, 'DISTRIBUTED PROCESSING TECHNOLOGY'
VendorID 0x1045, 'OPTI INC.'
VendorID 0x1048, 'ELSA AG'
VendorID 0x1049, 'FOUNTAIN TECHNOLOGIES'
VendorID 0x104A, 'STMicroelectronics'
VendorID 0x104B, 'BusLogic'
VendorID 0x104C, 'TEXAS INSTRUMENTS'
VendorID 0x104D, 'SONY CORPORATION'
VendorID 0x104E, 'Oak Technology'
VendorID 0x104F, 'Co-Time Computer Ltd.'
VendorID 0x1050, 'WINBOND ELECTRONICS CORP'
VendorID 0x1051, 'Anigma Corp.'
VendorID 0x1054, 'HITACHI'
VendorID 0x1055, 'Standard Microsystems Corp.'
VendorID 0x1057, 'Motorola'
VendorID 0x1058, 'ETRI'
VendorID 0x1059, 'TEKNOR INDUSTRIAL COMPUTERS INC'
VendorID 0x105A, 'PROMISE TECHNOLOGY'
VendorID 0x105B, 'FOXCONN INTERNATIONAL INC'
VendorID 0x105D, 'NUMBER 9 VISUAL TECHNOLOGY'
VendorID 0x105F, 'INFOTRONIC AMERICA INC'
VendorID 0x1060, 'United Microelectronics'
VendorID 0x1061, '8x8 Inc.'
VendorID 0x1063, 'OCEAN MANUFACTURING LTD'
VendorID 0x1064, 'ALCATEL'
VendorID 0x1065, 'Texas Microsystems'
VendorID 0x1066, 'Picopower Technology'
VendorID 0x1067, 'MITSUBISHI ELECTRIC AMERICA'
VendorID 0x1068, 'DIVERSIFIED TECHNOLOGY'
VendorID 0x1069, 'MYLEX CORPORATION'
VendorID 0x106B, 'APPLE COMPUTER INC.'
VendorID 0x106C, 'Hyundai Electronics America'
VendorID 0x106D, 'SEQUENT COMPUTER SYSTEMS'
VendorID 0x1070, 'DAEWOO TELECOM LTD'
VendorID 0x1071, 'MITAC'
VendorID 0x1073, 'YAMAHA CORPORATION'
VendorID 0x1074, 'Nexgen Microsystems'
VendorID 0x1076, 'Chaintech Comp.'
VendorID 0x1077, 'QLOGIC Corporation'
VendorID 0x1078, 'Cyrix Corporation'
VendorID 0x1079, 'I-BUS'
VendorID 0x107B, 'GATEWAY 2000'
VendorID 0x107D, 'Leadtek Research'
VendorID 0x107E, 'INTERPHASE CORPORATION'
VendorID 0x107F, 'Data Technology Corporation'
VendorID 0x1080, 'Cypress Semiconductor'
VendorID 0x1081, 'Radius Inc.'
VendorID 0x1083, 'Forex Computer Corporation'
VendorID 0x1085, 'Tulip Computers International BV'
VendorID 0x1087, 'Cache Computer'
VendorID 0x108A, 'SBS Operations'
VendorID 0x108D, 'OLICOM'
VendorID 0x108E, 'Sun Microsystems'
VendorID 0x1091, 'Intergraph Corporation'
VendorID 0x1092, 'Diamond Computer Systems'
VendorID 0x1093, 'National Instruments'
VendorID 0x1095, 'SILICON IMAGE (WAS CMD TECHNOLOGY INC)'
VendorID 0x1096, 'ALACRON'
VendorID 0x1097, 'APPIAN Graphics/ETMA'
VendorID 0x1098, 'Quantum Designs Ltd.'
VendorID 0x109A, 'PACKARD BELL NEC'
VendorID 0x109E, 'BROOKTREE CORPORATION'
VendorID 0x109F, 'TRIGEM COMPUTER INC.'
VendorID 0x10A0, 'MEIDENSHA CORPORATION'
VendorID 0x10A2, 'QUANTUM EFFECT DESIGN'
VendorID 0x10A4, 'Globe Manufacturing Sales'
VendorID 0x10A8, 'Sierra Semiconductor'
VendorID 0x10A9, 'SILICON GRAPHICS'
VendorID 0x10AC, 'HONEYWELL IAC'
VendorID 0x10AD, 'Winbond Systems Labs'
VendorID 0x10AF, 'MICRO COMPUTER SYSTEMS INC'
VendorID 0x10B5, 'PLX TECHNOLOGY.'
VendorID 0x10B6, 'MADGE NETWORKS'
VendorID 0x10B7, '3COM Corp, Networking Division'
VendorID 0x10B8, 'Standard Microsystems Corporation'
VendorID 0x10B9, 'ACER LABS Incorp.'
VendorID 0x10BA, 'MITSUBISHI ELECTRIC CORP.'
VendorID 0x10BD, 'Surecom Technology'
VendorID 0x10C2, 'AUSPEX SYSTEMS INC.'
VendorID 0x10C3, 'Samsung Semiconductors'
VendorID 0x10C4, 'Award Software International Inc.'
VendorID 0x10C8, 'NEOMAGIC CORPORATION'
VendorID 0x10CA, 'FUJITSU MICROELECTRONIC'
VendorID 0x10CB, 'OMRON CORPORATION'
VendorID 0x10CD, 'ADVANCED SYSTEM PRODUCTS'
VendorID 0x10CF, 'FUJITSU LIMITED'
VendorID 0x10D1, 'FUTUREPLUS SYSTEMS CORP.'
VendorID 0x10D2, 'MOLEX INCORPORATED'
VendorID 0x10D9, 'Macronix International Co. Ltd.'
VendorID 0x10DB, 'ROHM LSI SYSTEMS'
VendorID 0x10DC, 'CERN-European Lab. for Particle Physics'
VendorID 0x10DD, 'EVANS & SUTHERLAND'
VendorID 0x10DE, 'NVIDIA CORPORATION'
VendorID 0x10DF, 'EMULEX CORPORATION'
VendorID 0x10E1, 'TEKRAM TECHNOLOGY CO.LTD.'
VendorID 0x10E3, 'TUNDRA SEMICONDUCTOR CORP'
VendorID 0x10E5, 'MICRO INDUSTRIES CORPORATION'
VendorID 0x10E8, 'Applied Micro Circuits Corp.'
VendorID 0x10EA, 'Tvia, Inc.'
VendorID 0x10EB, 'Artist Graphics'
VendorID 0x10EC, 'REALTEK SEMICONDUCTOR CORP.'
VendorID 0x10ED, 'Ascii Corporation'
VendorID 0x10EE, 'XILINX'
VendorID 0x10EF, 'Racore Computer Products'
VendorID 0x10F0, 'Curtiss-Wright Controls Embedded Computing'
VendorID 0x10F1, 'TYAN COMPUTER'
VendorID 0x10F4, 'S-Mos Systems'
VendorID 0x10F5, 'NKK CORPORATION'
VendorID 0x10F6, 'Creative Electronic Systems SA'
VendorID 0x10FA, 'Truevision'
VendorID 0x10FB, 'Thesys Microelectronics'
VendorID 0x10FC, 'I-O DATA DEVICE'
VendorID 0x10FE, 'FAST MULTIMEDIA AG'
VendorID 0x1101, 'INITIO CORPORATION'
VendorID 0x1102, 'Creative Labs'
VendorID 0x1105, 'SIGMA DESIGNS'
VendorID 0x1106, 'VIA TECHNOLOGIES'
VendorID 0x1107, 'ASCEND COMMUNICATIONS/Stratus Computer'
VendorID 0x1108, 'Proteon Inc.'
VendorID 0x1109, 'Adaptec/Cogent Data Technologies Inc'
VendorID 0x110A, 'SIEMENS PC SYSTEME GMBH'
VendorID 0x110B, 'Chromatic Research Inc'
VendorID 0x1111, 'SANTA CRUZ OPERATION'
VendorID 0x1112, 'Osicom Technologies Inc.'
VendorID 0x1113, 'ACCTON TECHNOLOGY'
VendorID 0x1114, 'Atmel Corp.'
VendorID 0x1116, 'Media 100, Inc.'
VendorID 0x1117, 'Datacube Inc.'
VendorID 0x1118, 'FCI ELECTRONICS'
VendorID 0x1119, 'ICP-VORTEX COMPUTERSYSTEM GMBH'
VendorID 0x111A, 'EFFICIENT NETWORKS'
VendorID 0x111C, 'Tricord Systems Inc.'
VendorID 0x111D, 'INTEGRATED DEVICE TECH'
VendorID 0x111F, 'Precision Digital Images'
VendorID 0x1120, 'EMC CORPORATION'
VendorID 0x1127, 'FORE SYSTEMS INC'
VendorID 0x112A, 'HERMES ELECTRONICS COMPANY'
VendorID 0x112E, 'Infomedia'
VendorID 0x112F, 'IMAGING TECHNOLOGY'
VendorID 0x1131, 'PHILIPS SEMICONDUCTORS'
VendorID 0x1132, 'MITEL CORP'
VendorID 0x1133, 'Eicon Networks Corporation'
VendorID 0x1134, 'MERCURY COMPUTER SYSTEMS'
VendorID 0x1135, 'FUJI XEROX CO LTD'
VendorID 0x1136, 'MOMENTUM DATA SYSTEMS'
VendorID 0x1137, 'CISCO SYSTEMS INC'
VendorID 0x1138, 'ZIATECH CORPORATION'
VendorID 0x113C, 'CYCLONE MICROSYSTEMS.'
VendorID 0x113E, 'SANYO ELECTRIC CO-Information Systems Division'
VendorID 0x113F, 'Equinox Systems'
VendorID 0x1141, 'CREST MICROSYSTEM INC.'
VendorID 0x1142, 'Alliance Semiconductor CA - USA'
VendorID 0x1144, 'Cincinnati Milacron'
VendorID 0x1145, 'WORKBIT CORPORATION'
VendorID 0x1146, 'FORCE COMPUTERS GMBH'
VendorID 0x1147, 'Interface Corp'
VendorID 0x1148, 'SYSKONNECT/Marvell'
VendorID 0x114A, 'VMIC'
VendorID 0x114C, 'ANNABOOKS'
VendorID 0x114F, 'DIGI INTERNATIONAL'
VendorID 0x1154, 'MELCO INC'
VendorID 0x1155, 'Pine Technology Ltd'
VendorID 0x1158, 'Voarx R&D Inc'
VendorID 0x1159, 'Mutech'
VendorID 0x115C, 'PHOTRON LTD.'
VendorID 0x115D, 'XIRCOM'
VendorID 0x1161, 'PFU LIMITED'
VendorID 0x1163, 'RENDITION'
VendorID 0x1165, 'Imagraph Corporation'
VendorID 0x1166, 'Reliance Computer Corp./ServerWorks'
VendorID 0x1169, 'Centre f/Dev. of Adv. Computing'
VendorID 0x116A, 'Polaris Communications'
VendorID 0x116E, 'ELECTRONICS FOR IMAGING'
VendorID 0x1170, 'INVENTEC CORPORATION'
VendorID 0x1171, 'BLUE WAVE SYSTEMS'
VendorID 0x1172, 'ALTERA CORPORATION'
VendorID 0x1176, 'SBE'
VendorID 0x1178, 'Alfa Inc'
VendorID 0x1179, 'TOSHIBA AMERICA INFO SYSTEMS'
VendorID 0x117B, 'GCE-8320B'
VendorID 0x117E, 'T/R Systems'
VendorID 0x1180, 'RICOH CO LTD'
VendorID 0x1185, 'Dataworld'
VendorID 0x1186, 'D-LINK SYSTEM INC'
VendorID 0x1187, 'ADVANCED TECHNOLOGY LABORATORIES'
VendorID 0x1189, 'MATSUSHITA ELECTIC INDUSTRIAL CO LTD'
VendorID 0x118B, 'PLATYPUS TECHNOLOGY PTY LTD'
VendorID 0x118C, 'Corollary Inc'
VendorID 0x118D, 'BitFlow Inc'
VendorID 0x118E, 'Hermstedt AG'
VendorID 0x1190, 'Tripace'
VendorID 0x1191, 'ACARD TECHNOLOGY'
VendorID 0x1193, 'ZeitNet'
VendorID 0x1195, 'RATOC SYSTEMS INC'
VendorID 0x1197, 'Gage Applied Technologies'
VendorID 0x1199, 'Attachmate Corp.'
VendorID 0x119A, 'MINDSHARE.'
VendorID 0x119B, 'Omega Micro Inc.'
VendorID 0x119D, 'BUG.'
VendorID 0x119E, 'FUJITSU MICROELECTRONICS LTD.'
VendorID 0x119F, 'BULL HN INFORMATION SYSTEMS'
VendorID 0x11A1, 'HAMAMATSU PHOTONICS K.K.'
VendorID 0x11A8, 'Systech Corp.'
VendorID 0x11A9, 'InnoSys Inc.'
VendorID 0x11AA, 'ACTEL'
VendorID 0x11AB, 'GALILEO TECHNOLOGY LTD/Marvell Semiconductor, Inc.'
VendorID 0x11AD, 'LITE-ON COMMUNICATIONS INC'
VendorID 0x11AE, 'SCITEX CORPORATION'
VendorID 0x11AF, 'AVID TECHNOLOGY INC'
VendorID 0x11B0, 'V3 SEMICONDUCTOR INC./Quicklogic Corp'
VendorID 0x11B2, 'EASTMAN KODAK'
VendorID 0x11B3, 'BARR SYSTEMS INC.'
VendorID 0x11B5, 'Radstone Technology Ltd.'
VendorID 0x11B8, 'Xpoint Technologies Inc'
VendorID 0x11B9, 'Pathlight Technology Inc.'
VendorID 0x11BC, 'Network Peripherals Inc'
VendorID 0x11BD, 'Pinnacle Systems Inc.'
VendorID 0x11BF, 'ASTRODESIGN'
VendorID 0x11C1, 'AGERE/LUCENT'
VendorID 0x11C6, 'DAINIPPON SCREEN MFG. CO. LTD'
VendorID 0x11C8, 'DOLPHIN INTERCONNECT SOLUTIONS AS'
VendorID 0x11C9, 'MAGMA'
VendorID 0x11CA, 'LSI SYSTEMS'
VendorID 0x11CB, 'SPECIALIX INTERNATIONAL LTD'
VendorID 0x11CE, 'NETACCESS/Primary Rate Inc'
VendorID 0x11D0, 'LOCKHEED MARTIN-Electronics & Communications'
VendorID 0x11D1, 'AuraVision Corporation'
VendorID 0x11D2, 'INTERCOM INC.'
VendorID 0x11D4, 'Analog Devices, Inc.'
VendorID 0x11D5, 'IKON CORPORATION/Tahoma Technology'
VendorID 0x11D9, 'TOSHIBA TEC CORPORATION'
VendorID 0x11DA, 'NOVELL'
VendorID 0x11DB, 'Sega Enterprises Ltd'
VendorID 0x11DE, 'Zoran Corporation'
VendorID 0x11DF, 'NEW WAVE PDG'
VendorID 0x11E3, 'QUICKLOGIC CORPORATION'
VendorID 0x11EC, 'CORECO INC'
VendorID 0x11EE, 'DOME IMAGING SYSTEMS INC'
VendorID 0x11F0, 'Compu-Shack GmbH'
VendorID 0x11F4, 'Kinetic Systems Corporation'
VendorID 0x11F6, 'Powermatic Data Systems Ltd'
VendorID 0x11F8, 'PMC-SIERRA INC'
VendorID 0x11FE, 'Comtrol Corp'
VendorID 0x1202, 'Network General Corp'
VendorID 0x1203, 'AGFA CORPORATION'
VendorID 0x1206, 'AMDAHL CORPORATION'
VendorID 0x1208, 'Parsytec GmbH'
VendorID 0x1209, 'Sci Systems Inc'
VendorID 0x120E, 'Cyclades Corporation'
VendorID 0x120F, 'ESSENTIAL COMMUNICATIONS'
VendorID 0x1214, 'PERFORMANCE TECHNOLOGIES.'
VendorID 0x1216, 'PURUP-EskoFot A/S'
VendorID 0x1217, 'O2MICRO.'
VendorID 0x121A, '3DFX INTERACTIVE'
VendorID 0x121B, 'VIRATA LTD'
VendorID 0x1220, 'Ariel Corporation'
VendorID 0x1221, 'CONTEC CO. LTD'
VendorID 0x1223, 'ARTESYN COMMUNICATIONS PRODUCTS INC'
VendorID 0x1224, 'Interactive Images'
VendorID 0x1227, 'TECH-SOURCE'
VendorID 0x122C, 'SICAN GMBH'
VendorID 0x122D, 'Aztech System Ltd'
VendorID 0x1232, 'MARCONI COMMUNICATIONS LTD'
VendorID 0x1236, 'Sigma Designs, Inc'
VendorID 0x124C, 'Solitron Technologies Inc.'
VendorID 0x124D, 'Stallion Technologies'
VendorID 0x124F, 'Infortrend Technology Inc'
VendorID 0x1256, 'Perceptive Solutions Inc.'
VendorID 0x1258, 'Gilbarco Inc.'
VendorID 0x125B, 'Asix Electronics Corp.'
VendorID 0x1266, 'Microdyne Corp.'
VendorID 0x1267, 'S.A. Telecommunications'
VendorID 0x1361, 'SOLITON SYSTEMS K.K.'
VendorID 0x123C, 'CENTURY SYSTEMS.'
VendorID 0x123D, 'Engineering Design Team Inc.'
VendorID 0x123F, 'C-CUBE MICROSYSTEMS'
VendorID 0x1242, 'JAYCOR NETWORKS INC./JNI Corporation'
VendorID 0x1244, 'AVM AUDIOVISUELLES MKTG & COMPUTER SYSTEM GMBH'
VendorID 0x124B, 'SBS TECHNOLOGIES'
VendorID 0x1250, 'Hitachi Microcomputer System Ltd.'
VendorID 0x1253, 'GUZIK TECHNICAL ENTERPRISES'
VendorID 0x1255, 'OPTIBASE LTD'
VendorID 0x1259, 'ALLIED TELESYN INTERNATIONAL'
VendorID 0x125C, 'AURORA TECHNOLOGIES.'
VendorID 0x125D, 'ESS TECHNOLOGY, INC.'
VendorID 0x125F, 'CONCURRENT TECHNOLOGIES'
VendorID 0x1260, 'INTERSIL CORP'
VendorID 0x1261, 'MATSUSHITA-KOTOBUKI ELECTRONICS'
VendorID 0x1264, 'AVAL NAGASAKI CORPORATION'
VendorID 0x1268, 'TEKTRONIX'
VendorID 0x126C, 'Nortel Networks Corp.'
VendorID 0x126D, 'SPLASH TECHNOLOGY.'
VendorID 0x126E, 'SUMITOMO METAL INDUSTRIES'
VendorID 0x126F, 'SILICON MOTION.'
VendorID 0x1270, 'OLYMPUS OPTICAL CO. LTD.'
VendorID 0x1274, 'Creative Labs (was Ensoniq, Malvern)'
VendorID 0x1275, 'NETWORK APPLIANCE CORPORATION'
VendorID 0x1278, 'Transtech Parallel Systems'
VendorID 0x1279, 'TRANSMETA CORPORATION'
VendorID 0x127A, 'CONEXANT, ROCKWELL'
VendorID 0x127D, 'VELA RESEARCH LP'
VendorID 0x127F, 'FUJIFILM'
VendorID 0x1281, 'YOKOGAWA ELECTRIC CORPORATION'
VendorID 0x1283, 'Integrated Technology Express Inc.'
VendorID 0x1286, 'MAZET GMBH'
VendorID 0x128B, 'TRANSWITCH CORPORATION'
VendorID 0x128D, 'G2 Networks Inc.'
VendorID 0x128F, 'TATENO DENNOU.'
VendorID 0x1290, 'TOSHIBA PERSONAL COMPUTER SYSTEM CORP.'
VendorID 0x1291, 'NCS COMPUTER ITALIA SRL'
VendorID 0x1292, 'TRITECH MICROELECTRONICS INC'
VendorID 0x1297, 'SHUTTLE COMPUTER'
VendorID 0x1299, 'KNOWLEDGE TECHNOLOGY LAB.'
VendorID 0x129A, 'VMETRO Inc.'
VendorID 0x129E, 'VICTOR COMPANY OF JAPAN'
VendorID 0x12A0, 'ALLEN- BRADLEY COMPANY'
VendorID 0x12A3, 'Lucent Technologies AMR'
VendorID 0x12A7, 'AMO GMBH'
VendorID 0x12A9, 'XIOTECH CORPORATION'
VendorID 0x12AB, 'YUAN YUAN ENTERPRISE CO. LTD.'
VendorID 0x12AE, 'Alteon Networks Inc.'
VendorID 0x12B6, 'NATURAL MICROSYSTEMS'
VendorID 0x12B7, 'COGNEX MODULAR VISION SYSTEMS DIV.-ACUMEN INC.'
VendorID 0x12B9, '3Com Corp, Modem Division'
VendorID 0x12BC, 'ARRAY MICROSYSTEMS'
VendorID 0x12BE, 'ANCHOR CHIPS INC.'
VendorID 0x12BF, 'Fujifilm Microdevices'
VendorID 0x12C0, 'INFIMED'
VendorID 0x12C3, 'Holtek Microelectronics Inc.'
VendorID 0x12C4, 'Connect Tech Inc'
VendorID 0x12C6, 'Mitan Corporation'
VendorID 0x12C7, 'Dialogic Corp'
VendorID 0x12CA, 'Integrated Computing Engines'
VendorID 0x12CD, 'Aims Lab'
VendorID 0x12D2, 'NVIDIA (WAS: STB,SGS THOMPSON)'
VendorID 0x12D3, 'GE VINGMED ULTRASOUND AS'
VendorID 0x12D4, 'COMVERSE NETWORKS SYSTEM & Ulticom, Inc.'
VendorID 0x12D5, 'Equator Technologies'
VendorID 0x12D6, 'Analogic Corp'
VendorID 0x12D8, 'PERICOM SEMICONDUCTOR'
VendorID 0x12D9, 'Aculab PLC'
VendorID 0x12DA, 'True Time Inc.'
VendorID 0x12DE, 'Rainbow Technologies'
VendorID 0x12DF, 'SBS Technologies Inc'
VendorID 0x12E0, 'Chase Research PLC'
VendorID 0x12E2, 'Datum Inc. Bancomm-Timing Division'
VendorID 0x12E4, 'Brooktrout Technology Inc'
VendorID 0x12E7, 'Sebring Systems'
VendorID 0x12EA, 'Real Vision'
VendorID 0x12EB, 'Aureal Semiconductor'
VendorID 0x12EC, '3A'
VendorID 0x12F0, 'PENTEK'
VendorID 0x12F7, 'COGNEX INC.'
VendorID 0x12FB, 'Spectrum Signal Processing'
VendorID 0x12FC, 'CAPITAL EQUIPMENT CORP'
VendorID 0x12FE, 'ESD Electronic System Design GmbH'
VendorID 0x1304, 'Juniper Networks Inc.'
VendorID 0x1307, 'Computer Boards'
VendorID 0x1308, 'LEVEL ONE COMMUNICATIONS/Jato Technologies Inc.'
VendorID 0x130A, 'Mitsubishi Electric MicroComputer'
VendorID 0x130B, 'Colorgraphic Communications Corp'
VendorID 0x130F, 'Advanet Inc'
VendorID 0x1310, 'GESPAC'
VendorID 0x1313, 'YASKAWA ELECTRIC CO.'
VendorID 0x1316, 'TERADYNE INC.'
VendorID 0x1317, 'ADMTEK INC'
VendorID 0x1318, 'Packet Engines Inc.'
VendorID 0x1319, 'ForteMedia'
VendorID 0x131F, 'SIIG Inc'
VendorID 0x1325, 'SALIX TECHNOLOGIES INC'
VendorID 0x1326, 'SeaChange International'
VendorID 0x1331, 'RadiSys Corp.'
VendorID 0x133D, 'PRISA NETWORKS'
VendorID 0x133F, 'SCM MICROSYSTEMS'
VendorID 0x1342, 'PROMAX SYSTEMS INC'
VendorID 0x1344, 'MICRON TECHNOLOGY INC'
VendorID 0x134A, 'Domex'
VendorID 0x134B, 'ARK RESEARCH CORP.'
VendorID 0x134C, 'CHORI JOHO SYSTEM CO. LTD'
VendorID 0x134D, 'PC-TEL INC'
VendorID 0x135A, 'BRAIN BOXES LIMITED'
VendorID 0x135C, 'QUATECH INC'
VendorID 0x135E, 'SEALEVEL SYSTEMS INC'
VendorID 0x135F, 'I-DATA INTERNATIONAL A-S'
VendorID 0x1360, 'MEINBERG FUNKUHREN'
VendorID 0x1363, 'PHOENIX TECHNOLOGIES LTD'
VendorID 0x1365, 'HYPERCOPE'
VendorID 0x1367, 'HITACHI ZOSEN CORPORATION'
VendorID 0x1368, 'SKYWARE CORPORATION'
VendorID 0x1369, 'DIGIGRAM'
VendorID 0x136B, 'KAWASAKI STEEL CORPORATION'
VendorID 0x136C, 'ADTEK SYSTEM SCIENCE CO LTD'
VendorID 0x1375, 'BOEING-SUNNYVALE'
VendorID 0x1376, 'LAN Media Corporation'
VendorID 0x1377, 'ELECTRONIC EQUIPMENT PRODUCTION & DISTRIBUTION'
VendorID 0x137A, 'MARK OF THE UNICORN INC'
VendorID 0x137B, 'PPT VISION'
VendorID 0x137C, 'IWATSU ELECTRIC CO LTD'
VendorID 0x137D, 'DYNACHIP CORPORATION'
VendorID 0x1380, 'SANRITZ AUTOMATION CO LTC'
VendorID 0x1381, 'BRAINS CO. LTD'
VendorID 0x1383, 'CONTROLNET INC'
VendorID 0x1384, 'STELLAR SEMICONDUCTOR INC'
VendorID 0x1385, 'NETGEAR'
VendorID 0x1387, 'SYSTRAN CORP'
VendorID 0x1388, 'HITACHI INFORMATION TECHNOLOGY CO LTD'
VendorID 0x1389, 'APPLICOM INTERNATIONAL'
VendorID 0x138A, 'SITERA'
VendorID 0x138B, 'TOKIMEC INC'
VendorID 0x138E, 'BASLER GMBH'
VendorID 0x138F, 'PATAPSCO DESIGNS INC'
VendorID 0x1393, 'MOXA TECHNOLOGIES CO LTD'
VendorID 0x1394, 'LEVEL ONE COMMUNICATIONS'
VendorID 0x1395, 'AMBICOM INC'
VendorID 0x1396, 'CIPHER SYSTEMS INC'
VendorID 0x1397, 'COLOGNE CHIP DESIGNS GMBH'
VendorID 0x1398, 'CLARION CO. LTD'
VendorID 0x1399, 'RIOS SYSTEMS CO LTD'
VendorID 0x139A, 'ALACRITECH INC'
VendorID 0x139C, 'QUANTUM 3D INC'
VendorID 0x139D, 'XSTREAMS PLC/ EPL LIMITED'
VendorID 0x139E, 'ECHOSTAR DATA NETWORKS'
VendorID 0x139F, 'AETHRA S.R.L.'
VendorID 0x13A0, 'CRYSTAL GROUP INC'
VendorID 0x13A1, 'KAWASAKI HEAVY INDUSTRIES LTD'
VendorID 0x13A2, 'OSITECH COMMUNICATIONS INC'
VendorID 0x13A4, 'RASCOM INC'
VendorID 0x13A7, 'TELES AG'
VendorID 0x13A8, 'EXAR CORP.'
VendorID 0x13A9, 'SIEMENS MEDICAL SYSTEMS'
VendorID 0x13AA, 'NORTEL NETWORKS-BWA DIVISION'
VendorID 0x13AF, 'T.SQWARE'
VendorID 0x13B1, 'TAMURA CORPORATION'
VendorID 0x13B4, 'WELLBEAN CO INC'
VendorID 0x13B5, 'ARM Ltd'
VendorID 0x13B6, 'DLoG GMBH'
VendorID 0x13B8, 'NOKIA TELECOMMUNICATIONS OY'
VendorID 0x13BD, 'SHARP CORPORATION'
VendorID 0x13BF, 'SHAREWAVE INC'
VendorID 0x13C0, 'Microgate Corp.'
VendorID 0x13C1, '3ware Inc.'
VendorID 0x13C2, 'TECHNOTREND SYSTEMTECHNIK GMBH'
VendorID 0x13C3, 'JANZ COMPUTER AG'
VendorID 0x13C6, 'CONDOR ENGINEERING INC'
VendorID 0x13C7, 'BLUE CHIP TECHNOLOGY LTD'
VendorID 0x13CA, 'IOMEGA CORPORATION'
VendorID 0x13CC, 'METHEUS CORPORATION'
VendorID 0x13CF, 'STUDIO AUDIO & VIDEO LTD'
VendorID 0x13D0, 'B2C2'
VendorID 0x13D1, 'ABOCOM SYSTEMS'
VendorID 0x13D2, 'SHARK MULTIMEDIA INC'
VendorID 0x13D3, 'IMC NETWORKS'
VendorID 0x13D4, 'GRAPHICS MICROSYSTEMS INC'
VendorID 0x13D6, 'K.I. TECHNOLOGY CO LTD'
VendorID 0x13D7, 'TOSHIBA ENGINEERING CORPORATION'
VendorID 0x13D8, 'PHOBOS CORPORATION'
VendorID 0x13D9, 'APEX INC'
VendorID 0x13DC, 'NETBOOST CORPORATION'
VendorID 0x13DE, 'ABB ROBOTICS PRODUCTS'
VendorID 0x13DF, 'E-TECH INC'
VendorID 0x13E0, 'GVC CORPORATION'
VendorID 0x13E3, 'NEST INC'
VendorID 0x13E4, 'CALCULEX INC'
VendorID 0x13E5, 'TELESOFT DESIGN LTD'
VendorID 0x13E9, 'INTRASERVER TECHNOLOGY INC'
VendorID 0x13EA, 'DALLAS SEMICONDUCTOR'
VendorID 0x13F0, 'SUNDANCE TECHNOLOGY INC'
VendorID 0x13F1, 'OCE-TECHNOLOGIES B.V.'
VendorID 0x13F2, 'FORD MICROELECTRONICS INC'
VendorID 0x13F4, 'TROIKA NETWORKS INC'
VendorID 0x13F6, 'C-MEDIA ELECTRONICS INC'
VendorID 0x13F9, 'NTT ADVANCED TECHNOLOGY CORP.'
VendorID 0x13FB, 'AYDIN CORP'
VendorID 0x13FD, 'MICRO SCIENCE INC'
VendorID 0x1400, 'ARTX INC'
VendorID 0x1402, 'Meilhaus Electronic GmbH Germany'
VendorID 0x1404, 'FUNDAMENTAL SOFTWARE INC'
VendorID 0x1406, 'OCE PRINTING SYSTEMS GmbH'
VendorID 0x1407, 'LAVA COMPUTER MFG INC'
VendorID 0x1408, 'ALOKA CO. LTD'
VendorID 0x140A, 'DSP RESEARCH INC'
VendorID 0x140B, 'RAMIX INC'
VendorID 0x140D, 'MATSUSHITA ELECTRIC WORKS LTD'
VendorID 0x1412, 'ICEnsemble'
VendorID 0x1413, 'ADDONICS'
VendorID 0x1415, 'OXFORD SEMICONDUCTOR LTD'
VendorID 0x1418, 'KYUSHU ELECTRONICS SYSTEMS INC'
VendorID 0x1419, 'EXCEL SWITCHING CORP'
VendorID 0x141B, 'ZOOM TELEPHONICS INC'
VendorID 0x141E, 'FANUC LTD'
VendorID 0x1420, 'PSION DACOM PLC'
VendorID 0x1428, 'EDEC CO LTD'
VendorID 0x1429, 'UNEX TECHNOLOGY CORP'
VendorID 0x142A, 'KINGMAX TECHNOLOGY INC'
VendorID 0x142B, 'RADIOLAN'
VendorID 0x142C, 'MINTON OPTIC INDUSTRY CO LTD'
VendorID 0x142D, 'PIXSTREAM INC'
VendorID 0x1430, 'ITT AEROSPACE/COMMUNICATIONS DIVISION'
VendorID 0x1433, 'ELTEC ELEKTRONIK GMBH'
VendorID 0x1436, 'CIS TECHNOLOGY INC'
VendorID 0x1437, 'NISSIN INC CO'
VendorID 0x1438, 'ATMEL-DREAM'
VendorID 0x143F, 'LIGHTWELL CO LTD-ZAX DIVISION'
VendorID 0x1441, 'AGIE SA'
VendorID 0x1445, 'LOGICAL CO LTD'
VendorID 0x1446, 'GRAPHIN CO. LTD'
VendorID 0x1447, 'AIM GMBH'
VendorID 0x144A, 'ADLINK Technology Inc'
VendorID 0x144B, 'LORONIX INFORMATION SYSTEMS INC'
VendorID 0x144D, 'SAMSUNG ELECTRONICS CO LTD'
VendorID 0x1450, 'OCTAVE COMMUNICATIONS IND.'
VendorID 0x1451, 'SP3D CHIP DESIGN GMBH'
VendorID 0x1453, 'MYCOM INC'
VendorID 0x1455, 'LOGIC PLUS PLUS INC'
VendorID 0x1458, 'GIGA-BYTE TECHNOLOGY'
VendorID 0x145C, 'CRYPTEK'
VendorID 0x145F, 'BALDOR ELECTRIC COMPANY'
VendorID 0x1460, 'DYNARC INC'
VendorID 0x1461, 'AVERMEDIA Tech.'
VendorID 0x1462, 'MICRO-STAR INTERNATIONAL CO LTD'
VendorID 0x1463, 'FAST CORPORATION'
VendorID 0x1464, 'INTERACTIVE CIRCUITS & SYSTEMS LTD'
VendorID 0x1465, 'GN NETTEST TELECOM DIV.'
VendorID 0x1468, 'AMBIT MICROSYSTEMS CORP.'
VendorID 0x1469, 'CLEVELAND MOTION CONTROLS'
VendorID 0x146C, 'RUBY TECH CORP.'
VendorID 0x146D, 'TACHYON'
VendorID 0x146E, 'WILLIAMS ELECTRONICS GAMES.'
VendorID 0x1471, 'INTEGRATED TELECOM EXPRESS INC'
VendorID 0x1473, 'ZAPEX TECHNOLOGIES INC'
VendorID 0x1474, 'DOUG CARSON & ASSOCIATES'
VendorID 0x1477, 'NET INSIGHT'
VendorID 0x1478, 'DIATREND CORPORATION'
VendorID 0x147B, 'ABIT Computer'
VendorID 0x147F, 'NIHON UNISYS'
VendorID 0x1482, 'ISYTEC-Integrierte Systemtechnik Gmbh'
VendorID 0x1483, 'LABWAY COPORATION'
VendorID 0x1485, 'ERMA-ELECTRONIC GMBH'
VendorID 0x1489, 'KYE SYSTEMS CORPORATION'
VendorID 0x148A, 'OPTO 22'
VendorID 0x148B, 'INNOMEDIALOGIC INC.'
VendorID 0x148E, 'OSI PLUS CORPORATION'
VendorID 0x148F, 'PLANT EQUIPMENT.'
VendorID 0x1490, 'TC LABS PTY LTD.'
VendorID 0x1493, 'MAKER COMMUNICATIONS'
VendorID 0x1495, 'TOKAI COMMUNICATIONS INDUSTRY CO. LTD'
VendorID 0x1496, 'JOYTECH COMPUTER CO. LTD.'
VendorID 0x1497, 'SMA REGELSYSTEME GMBH'
VendorID 0x1499, 'EMTEC CO. LTD'
VendorID 0x149A, 'ANDOR TECHNOLOGY LTD'
VendorID 0x149B, 'SEIKO INSTRUMENTS INC'
VendorID 0x149C, 'OVISLINK CORP.'
VendorID 0x149D, 'NEWTEK INC'
VendorID 0x149E, 'MAPLETREE NETWORKS INC.'
VendorID 0x149F, 'LECTRON CO LTD'
VendorID 0x14A0, 'SOFTING GMBH'
VendorID 0x14A1, 'SYSTEMBASE CO LTD'
VendorID 0x14A2, 'MILLENNIUM ENGINEERING INC'
VendorID 0x14A3, 'MAVERICK NETWORKS'
VendorID 0x14A4, 'GVC/BCM ADVANCED RESEARCH'
VendorID 0x14A5, 'XIONICS DOCUMENT TECHNOLOGIES INC.'
VendorID 0x14A6, 'INOVA COMPUTERS GMBH & CO KG'
VendorID 0x14A8, 'FEATRON TECHNOLOGIES CORPORATION'
VendorID 0x14A9, 'HIVERTEC INC.'
VendorID 0x14AB, 'MENTOR GRAPHICS CORP.'
VendorID 0x14AC, 'NOVAWEB TECHNOLOGIES INC'
VendorID 0x14AD, 'TIME SPACE RADIO AB'
VendorID 0x14AE, 'CTI PET Systems'
VendorID 0x14AF, 'GUILLEMOT CORPORATION'
VendorID 0x14B0, 'BST COMMUNICATION TECHNOLOGY LTD'
VendorID 0x14B1, 'NEXTCOM K.K.'
VendorID 0x14B2, 'ENNOVATE NETWORKS INC'
VendorID 0x14B3, 'XPEED INC.'
VendorID 0x14B4, 'PHILIPS BUSINESS ELECTRONICS B.V.'
VendorID 0x14B5, 'CREAMWARE GMBH'
VendorID 0x14B6, 'QUANTUM DATA CORP.'
VendorID 0x14B7, 'PROXIM INC'
VendorID 0x14B8, 'TECHSOFT TECHNOLOGY CO LTD'
VendorID 0x14B9, 'AIRONET WIRELESS COMMUNICATIONS'
VendorID 0x14BA, 'INTERNIX INC.'
VendorID 0x14BB, 'SEMTECH CORPORATION'
VendorID 0x14BC, 'GLOBESPAN SEMICONDUCTOR INC.'
VendorID 0x14BD, 'CARDIO CONTROL N.V.'
VendorID 0x14BE, 'L3 COMMUNICATIONS'
VendorID 0x14BF, 'SPIDER COMMUNICATIONS INC.'
VendorID 0x14C0, 'COMPAL ELECTRONICS INC'
VendorID 0x14C1, 'MYRICOM INC.'
VendorID 0x14C2, 'DTK COMPUTER'
VendorID 0x14C3, 'MEDIATEK CORP.'
VendorID 0x14C4, 'IWASAKI INFORMATION SYSTEMS CO LTD'
VendorID 0x14C5, 'ABB AUTOMATION PRODUCTS'
VendorID 0x14C6, 'DATA RACE INC'
VendorID 0x14C7, 'MODULAR TECHNOLOY HOLDINGS LTD'
VendorID 0x14C8, 'TURBOCOMM TECH. INC.'
VendorID 0x14C9, 'ODIN TELESYSTEMS INC'
VendorID 0x14CA, 'PE LOGIC CORP.'
VendorID 0x14CB, 'Billionton Systems Inc./Cadmus Micro Inc.'
VendorID 0x14CC, 'NAKAYO TELECOMMUNICATIONS INC'
VendorID 0x14CD, 'UNIVERSAL SCIENTIFIC IND'
VendorID 0x14CE, 'WHISTLE COMMUNICATIONS'
VendorID 0x14CF, 'TEK MICROSYSTEMS INC.'
VendorID 0x14D0, 'ERICSSON AXE R & D'
VendorID 0x14D1, 'COMPUTER HI-TECH CO LTD'
VendorID 0x14D2, 'TITAN ELECTRONICS INC'
VendorID 0x14D3, 'CIRTECH (UK) LTD'
VendorID 0x14D4, 'PANACOM TECHNOLOGY CORP'
VendorID 0x14D5, 'NITSUKO CORPORATION'
VendorID 0x14D6, 'ACCUSYS'
VendorID 0x14D7, 'HIRAKAWA HEWTECH CORP'
VendorID 0x14D8, 'HOPF ELEKTRONIK GMBH'
VendorID 0x14D9, 'ALPHA PROCESSOR INC'
VendorID 0x14DA, 'NATIONAL AEROSPACE LABORATORIES'
VendorID 0x14DB, 'AVLAB TECHNOLOGY INC'
VendorID 0x14DC, 'AMPLICON LIVELINE LTD'
VendorID 0x14DD, 'IMODL INC.'
VendorID 0x14DE, 'APPLIED INTEGRATION CORPORATION'
VendorID 0x14DF, 'BASIS COMMUNICATIONS CORP'
VendorID 0x14E1, 'INVERTEX'
VendorID 0x14E2, 'INFOLIBRIA'
VendorID 0x14E3, 'AMTELCO'
VendorID 0x14E4, 'BROADCOM CORPORATION'
VendorID 0x14E5, 'PIXELFUSION LTD'
VendorID 0x14E6, 'SHINING TECHNOLOGY INC'
VendorID 0x14E7, '3CX'
VendorID 0x14E8, 'RAYCER INC'
VendorID 0x14E9, 'GARNETS SYSTEM CO LTD'
VendorID 0x14EA, 'PLANEX COMMUNICATIONS INC'
VendorID 0x14EB, 'SEIKO EPSON CORPORATION'
VendorID 0x14EC, 'ACQIRIS'
VendorID 0x14ED, 'DATAKINETICS LTD'
VendorID 0x14EE, 'MASPRO KENKOH CORP'
VendorID 0x14EF, 'CARRY COMPUTER ENG. CO LTD'
VendorID 0x14F0, 'CANON RESEACH CENTRE FRANCE'
VendorID 0x14F1, 'Conexant Systems, Inc'
VendorID 0x14F2, 'Mobility Electronics, Inc.'
VendorID 0x14F3, 'BROADLOGIC'
VendorID 0x14F4, 'TOKYO ELECTRONIC INDUSTRY CO LTD'
VendorID 0x14F5, 'SOPAC LTD'
VendorID 0x14F6, 'COYOTE TECHNOLOGIES LLC'
VendorID 0x14F7, 'WOLF TECHNOLOGY INC'
VendorID 0x14F8, 'AUDIOCODES INC'
VendorID 0x14F9, 'AG COMMUNICATIONS'
VendorID 0x14FA, 'WAVETEK WANDEL & GOLTERMANN'
VendorID 0x14FB, 'TRANSAS MARINE (UK) LTD'
VendorID 0x14FC, 'QUADRICS SUPERCOMPUTERS WORLD'
VendorID 0x14FD, 'JAPAN COMPUTER INDUSTRY INC.'
VendorID 0x14FE, 'ARCHTEK TELECOM CORP.'
VendorID 0x14FF, 'TWINHEAD INTERNATIONAL CORP'
VendorID 0x1500, 'LANTECH COMPUTER COMPANY'
VendorID 0x1501, 'BANKSOFT CANADA LTD'
VendorID 0x1502, 'MITSUBISHI ELECTRIC LOGISTICS SUPPORT CO'
VendorID 0x1503, 'KAWASAKI LSI USA INC'
VendorID 0x1504, 'KAISER ELECTRONICS'
VendorID 0x1505, 'ITA INGENIEURBURO FUR TESTAUFGABEN GMBH'
VendorID 0x1506, 'CHAMELEON SYSTEMS INC'
VendorID 0x1507, 'HTEC LTD'
VendorID 0x1508, 'HONDA CONNECTORS/MHOTRONICS INC'
VendorID 0x1509, 'FIRST INTERNATIONAL COMPUTER INC'
VendorID 0x150A, 'FORVUS RESEARCH INC'
VendorID 0x150B, 'YAMASHITA SYSTEMS CORP'
VendorID 0x150C, 'KYOPAL CO LTD'
VendorID 0x150D, 'WARPSPPED INC'
VendorID 0x150E, 'C-PORT CORPORATION'
VendorID 0x150F, 'INTEC GMBH'
VendorID 0x1510, 'BEHAVIOR TECH COMPUTER CORP'
VendorID 0x1511, 'CENTILLIUM TECHNOLOGY CORP'
VendorID 0x1512, 'ROSUN TECHNOLOGIES INC'
VendorID 0x1513, 'RAYCHEM'
VendorID 0x1514, 'TFL LAN INC'
VendorID 0x1515, 'ICS ADVENT'
VendorID 0x1516, 'MYSON TECHNOLOGY INC'
VendorID 0x1517, 'ECHOTEK CORPORATION'
VendorID 0x1518, 'PEP MODULAR COMPUTERS GMBH'
VendorID 0x1519, 'TELEFON AKTIEBOLAGET LM Ericsson'
VendorID 0x151A, 'GLOBETEK INC'
VendorID 0x151B, 'COMBOX LTD'
VendorID 0x151C, 'DIGITAL AUDIO LABS INC'
VendorID 0x151D, 'FUJITSU COMPUTER PRODUCTS OF AMERICA'
VendorID 0x151E, 'MATRIX CORP.'
VendorID 0x151F, 'TOPIC SEMICONDUCTOR CORP'
VendorID 0x1520, 'CHAPLET SYSTEM INC'
VendorID 0x1521, 'BELL CORPORATION'
VendorID 0x1522, 'MAINPINE LIMITED'
VendorID 0x1523, 'MUSIC SEMICONDUCTORS'
VendorID 0x1524, 'ENE TECHNOLOGY INC'
VendorID 0x1525, 'IMPACT TECHNOLOGIES'
VendorID 0x1526, 'ISS'
VendorID 0x1527, 'SOLECTRON'
VendorID 0x1528, 'ACKSYS'
VendorID 0x1529, 'AMERICAN MICROSYSTEMS INC'
VendorID 0x152A, 'QUICKTURN DESIGN SYSTEMS'
VendorID 0x152B, 'FLYTECH TECHNOLOGY CO LTD'
VendorID 0x152C, 'MACRAIGOR SYSTEMS LLC'
VendorID 0x152D, 'QUANTA COMPUTER INC'
VendorID 0x152E, 'MELEC INC'
VendorID 0x152F, 'PHILIPS-CRYPTO'
VendorID 0x1530, 'ACQIS TECHNOLOGY'
VendorID 0x1531, 'CHRYON CORP.'
VendorID 0x1532, 'ECHELON CORPORATION'
VendorID 0x1533, 'BALTIMORE'
VendorID 0x1534, 'ROAD CORPORATION'
VendorID 0x1535, 'EVERGREEN TECHNOLOGIES INC'
VendorID 0x1537, 'DATALEX COMMUNCATIONS'
VendorID 0x1538, 'ARALION INC.'
VendorID 0x1539, 'ATELIER INFORMATIQUES et ELECTRONIQUE ETUDES S.A.'
VendorID 0x153A, 'ONO SOKKI'
VendorID 0x153B, 'TERRATEC ELECTRONIC GMBH'
VendorID 0x153C, 'ANTAL ELECTRONIC'
VendorID 0x153D, 'FILANET CORPORATION'
VendorID 0x153E, 'TECHWELL INC'
VendorID 0x153F, 'MIPS DENMARK'
VendorID 0x1540, 'PROVIDEO MULTIMEDIA CO LTD'
VendorID 0x1541, 'TELOSITY INC.'
VendorID 0x1542, 'VIVID TECHNOLOGY INC'
VendorID 0x1543, 'SILICON LABORATORIES'
VendorID 0x1544, 'DCM DATA SYSTEMS'
VendorID 0x1545, 'VISIONTEK'
VendorID 0x1546, 'IOI TECHNOLOGY CORP.'
VendorID 0x1547, 'MITUTOYO CORPORATION'
VendorID 0x1548, 'JET PROPULSION LABORATORY'
VendorID 0x1549, 'INTERCONNECT SYSTEMS SOLUTIONS'
VendorID 0x154A, 'MAX TECHNOLOGIES INC.'
VendorID 0x154B, 'COMPUTEX CO LTD'
VendorID 0x154C, 'VISUAL TECHNOLOGY INC.'
VendorID 0x154D, 'PAN INTERNATIONAL INDUSTRIAL CORP'
VendorID 0x154E, 'SERVOTEST LTD'
VendorID 0x154F, 'STRATABEAM TECHNOLOGY'
VendorID 0x1550, 'OPEN NETWORK CO LTD'
VendorID 0x1551, 'SMART ELECTRONIC DEVELOPMENT GMBH'
VendorID 0x1552, 'RACAL AIRTECH LTD'
VendorID 0x1553, 'CHICONY ELECTRONICS CO LTD'
VendorID 0x1554, 'PROLINK MICROSYSTEMS CORP.'
VendorID 0x1555, 'GESYTEC GMBH'
VendorID 0x1556, 'PLD APPLICATIONS'
VendorID 0x1557, 'MEDIASTAR CO. LTD'
VendorID 0x1558, 'CLEVO/KAPOK COMPUTER'
VendorID 0x1559, 'SI LOGIC LTD'
VendorID 0x155A, 'INNOMEDIA INC'
VendorID 0x155B, 'PROTAC INTERNATIONAL CORP'
VendorID 0x155C, 'CEMAX-ICON INC'
VendorID 0x155D, 'MAC SYSTEM CO LTD'
VendorID 0x155E, 'LP ELEKTRONIK GMBH/KUKA Controls GmbH'
VendorID 0x155F, 'PERLE SYSTEMS LIMITED'
VendorID 0x1560, 'TERAYON COMMUNICATIONS SYSTEMS'
VendorID 0x1561, 'VIEWGRAPHICS INC'
VendorID 0x1562, 'Symbol Technologies, Inc.'
VendorID 0x1563, 'A-TREND'
VendorID 0x1564, 'YAMAKATSU ELECTRONICS INDUSTRY CO LTD'
VendorID 0x1565, 'BIOSTAR MICROTECH INT CORP'
VendorID 0x1566, 'ARDENT TECHNOLOGIES INC'
VendorID 0x1567, 'JUNGSOFT'
VendorID 0x1568, 'DDK ELECTRONICS INC'
VendorID 0x1569, 'PALIT MICROSYSTEMS INC'
VendorID 0x156A, 'AVTEC SYSTEMS'
VendorID 0x156B, '2WIRE'
VendorID 0x156C, 'VIDAC ELECTRONICS GMBH'
VendorID 0x156D, 'ALPHA-TOP CORP'
VendorID 0x156E, 'ALFA INC'
VendorID 0x156F, 'M-SYSTEMS FLASH DISK PIONEERS LTD'
VendorID 0x1570, 'LECROY CORPORATION'
VendorID 0x1571, 'CONTEMPORARY CONTROLS'
VendorID 0x1572, 'OTIS ELEVATOR COMPANY'
VendorID 0x1573, 'LATTICE-VANTIS'
VendorID 0x1574, 'FAIRCHILD SEMICONDUCTOR'
VendorID 0x1575, 'VOLTAIRE ADVANCED DATA SECURITY LTD'
VendorID 0x1576, 'VIEWCAST COM'
VendorID 0x1578, 'HITT'
VendorID 0x1579, 'DUAL TECHNOLOGY CORPORATION'
VendorID 0x157A, 'JAPAN ELECRONICS IND. INC'
VendorID 0x157B, 'STAR MULTIMEDIA CORP.'
VendorID 0x157C, 'EUROSOFT (UK) LTD'
VendorID 0x157D, 'GEMFLEX NETWORKS'
VendorID 0x157E, 'TRANSITION NETWORKS'
VendorID 0x157F, 'PX INSTRUMENTS TECHNOLOGY LTD'
VendorID 0x1580, 'PRIMEX AEROSPACE CO.'
VendorID 0x1581, 'SEH COMPUTERTECHNIK GMBH'
VendorID 0x1582, 'CYTEC CORPORATION'
VendorID 0x1583, 'INET TECHNOLOGIES INC'
VendorID 0x1584, 'UNIWILL COMPUTER CORP'
VendorID 0x1585, 'LOGITRON'
VendorID 0x1586, 'LANCAST INC'
VendorID 0x1587, 'KONICA CORPORATION'
VendorID 0x1588, 'SOLIDUM SYSTEMS CORP'
VendorID 0x1589, 'ATLANTEK MICROSYSTEMS PTY LTD'
VendorID 0x158A, 'DIGALOG SYSTEMS INC'
VendorID 0x158B, 'ALLIED DATA TECHNOLOGIES'
VendorID 0x158C, 'HITACHI SEMICONDUCTOR & DEVICES SALES CO LTD'
VendorID 0x158D, 'POINT MULTIMEDIA SYSTEMS'
VendorID 0x158E, 'LARA TECHNOLOGY INC'
VendorID 0x158F, 'DITECT COOP'
VendorID 0x1590, '3PARDATA'
VendorID 0x1591, 'ARN'
VendorID 0x1592, 'SYBA TECH LIMITED'
VendorID 0x1593, 'BOPS INC'
VendorID 0x1594, 'NETGAME LTD'
VendorID 0x1595, 'DIVA SYSTEMS CORP.'
VendorID 0x1596, 'FOLSOM RESEARCH INC'
VendorID 0x1597, 'MEMEC DESIGN SERVICES'
VendorID 0x1598, 'GRANITE MICROSYSTEMS'
VendorID 0x1599, 'DELTA ELECTRONICS INC'
VendorID 0x159A, 'GENERAL INSTRUMENT'
VendorID 0x159B, 'FARADAY TECHNOLOGY CORP'
VendorID 0x159C, 'STRATUS COMPUTER SYSTEMS'
VendorID 0x159D, 'NINGBO HARRISON ELECTRONICS CO LTD'
VendorID 0x159E, 'A-MAX TECHNOLOGY'
VendorID 0x159F, 'GALEA NETWORK SECURITY'
VendorID 0x15A0, 'COMPUMASTER SRL'
VendorID 0x15A1, 'GEOCAST NETWORK SYSTEMS INC'
VendorID 0x15A2, 'CATALYST ENTERPRISES INC'
VendorID 0x15A3, 'ITALTEL'
VendorID 0x15A4, 'X-NET OY'
VendorID 0x15A5, 'TOYOTA MACS INC'
VendorID 0x15A6, 'SUNLIGHT ULTRASOUND TECHNOLOGIES LTD'
VendorID 0x15A7, 'SSE TELECOM INC'
VendorID 0x15A8, 'SHANGHAI COMMUNICATIONS TECHNOLOGIES CENTER'
VendorID 0x15AA, 'MORETON BAY'
VendorID 0x15AB, 'BLUESTEEL NETWORKS INC'
VendorID 0x15AC, 'NORTH ATLANTIC INSTRUMENTS'
VendorID 0x15AD, 'VMware Inc.'
VendorID 0x15AE, 'AMERSHAM PHARMACIA BIOTECH'
VendorID 0x15B0, 'ZOLTRIX INTERNATIONAL LIMITED'
VendorID 0x15B1, 'SOURCE TECHNOLOGY INC'
VendorID 0x15B2, 'MOSAID TECHNOLOGIES INC.'
VendorID 0x15B3, 'MELLANOX TECHNOLOGY'
VendorID 0x15B4, 'CCI/TRIAD'
VendorID 0x15B5, 'CIMETRICS INC'
VendorID 0x15B6, 'TEXAS MEMORY SYSTEMS INC'
VendorID 0x15B7, 'SANDISK CORP.'
VendorID 0x15B8, 'ADDI-DATA GMBH'
VendorID 0x15B9, 'MAESTRO DIGITAL COMMUNICATIONS'
VendorID 0x15BA, 'IMPACCT TECHNOLOGY CORP'
VendorID 0x15BB, 'PORTWELL INC'
VendorID 0x15BC, 'AGILENT TECHNOLOGIES'
VendorID 0x15BD, 'DFI INC.'
VendorID 0x15BE, 'SOLA ELECTRONICS'
VendorID 0x15BF, 'HIGH TECH COMPUTER CORP (HTC)'
VendorID 0x15C0, 'BVM LIMITED'
VendorID 0x15C1, 'QUANTEL'
VendorID 0x15C2, 'NEWER TECHNOLOGY INC'
VendorID 0x15C3, 'TAIWAN MYCOMP CO LTD'
VendorID 0x15C4, 'EVSX'
VendorID 0x15C5, 'PROCOMP INFORMATICS LTD'
VendorID 0x15C6, 'TECHNICAL UNIVERSITY OF BUDAPEST'
VendorID 0x15C7, 'TATEYAMA SYSTEM LABORATORY CO LTD'
VendorID 0x15C8, 'PENTA MEDIA CO. LTD'
VendorID 0x15C9, 'SEROME TECHNOLOGY INC'
VendorID 0x15CA, 'BITBOYS OY'
VendorID 0x15CB, 'AG ELECTRONICS LTD'
VendorID 0x15CC, 'HOTRAIL INC.'
VendorID 0x15CD, 'DREAMTECH CO LTD'
VendorID 0x15CE, 'GENRAD INC.'
VendorID 0x15CF, 'HILSCHER GMBH'
VendorID 0x15D1, 'INFINEON TECHNOLOGIES AG'
VendorID 0x15D2, 'FIC (FIRST INTERNATIONAL COMPUTER INC)'
VendorID 0x15D3, 'NDS TECHNOLOGIES ISRAEL LTD'
VendorID 0x15D4, 'IWILL CORPORATION'
VendorID 0x15D5, 'TATUNG CO.'
VendorID 0x15D6, 'ENTRIDIA CORPORATION'
VendorID 0x15D7, 'Rockwell-Collins Inc'
VendorID 0x15D8, 'CYBERNETICS TECHNOLOGY CO LTD'
VendorID 0x15D9, 'SUPER MICRO COMPUTER INC'
VendorID 0x15DA, 'CYBERFIRM INC.'
VendorID 0x15DB, 'APPLIED COMPUTING SYSTEMS INC.'
VendorID 0x15DC, 'LITRONIC INC'
VendorID 0x15DD, 'SIGMATEL INC.'
VendorID 0x15DE, 'MALLEABLE TECHNOLOGIES INC'
VendorID 0x15DF, 'INFINILINK CORP.'
VendorID 0x15E0, 'CACHEFLOW INC'
VendorID 0x15E1, 'VOICE TECHNOLOGIES GROUP INC'
VendorID 0x15E2, 'QUICKNET TECHNOLOGIES INC'
VendorID 0x15E3, 'NETWORTH TECHNOLOGIES INC'
VendorID 0x15E4, 'VSN SYSTEMEN BV'
VendorID 0x15E5, 'VALLEY TECHNOLOGIES INC'
VendorID 0x15E6, 'AGERE INC.'
VendorID 0x15E7, 'GET ENGINEERING CORP.'
VendorID 0x15E8, 'NATIONAL DATACOMM CORP.'
VendorID 0x15E9, 'PACIFIC DIGITAL CORP.'
VendorID 0x15EA, 'TOKYO DENSHI SEKEI K.K.'
VendorID 0x15EB, 'DRSEARCH GMBH'
VendorID 0x15EC, 'BECKHOFF GMBH'
VendorID 0x15ED, 'MACROLINK INC'
VendorID 0x15EE, 'IN WIN DEVELOPMENT INC.'
VendorID 0x15EF, 'INTELLIGENT PARADIGM INC'
VendorID 0x15F0, 'B-TREE SYSTEMS INC'
VendorID 0x15F1, 'TIMES N SYSTEMS INC'
VendorID 0x15F2, 'DIAGNOSTIC INSTRUMENTS INC'
VendorID 0x15F3, 'DIGITMEDIA CORP.'
VendorID 0x15F4, 'VALUESOFT'
VendorID 0x15F5, 'POWER MICRO RESEARCH'
VendorID 0x15F6, 'EXTREME PACKET DEVICE INC'
VendorID 0x15F7, 'BANCTEC'
VendorID 0x15F8, 'KOGA ELECTRONICS CO'
VendorID 0x15F9, 'ZENITH ELECTRONICS CORPORATION'
VendorID 0x15FA, 'J P AXZAM CORPORATION'
VendorID 0x15FB, 'ZILOG INC.'
VendorID 0x15FC, 'TECHSAN ELECTRONICS CO LTD'
VendorID 0x15FD, 'N-CUBED.NET'
VendorID 0x15FE, 'KINPO ELECTRONICS INC'
VendorID 0x15FF, 'FASTPOINT TECHNOLOGIES INC.'
VendorID 0x1600, 'NORTHROP GRUMMAN-CANADA LTD'
VendorID 0x1601, 'TENTA TECHNOLOGY'
VendorID 0x1602, 'PROSYS-TEC INC.'
VendorID 0x1603, 'NOKIA WIRELESS BUSINESS COMMUNICATIONS'
VendorID 0x1604, 'CENTRAL SYSTEM RESEARCH CO LTD'
VendorID 0x1605, 'PAIRGAIN TECHNOLOGIES'
VendorID 0x1606, 'EUROPOP AG'
VendorID 0x1607, 'LAVA SEMICONDUCTOR MANUFACTURING INC.'
VendorID 0x1608, 'AUTOMATED WAGERING INTERNATIONAL'
VendorID 0x1609, 'SCIEMETRIC INSTRUMENTS INC'
VendorID 0x166D, 'Broadcom -SiByte'
VendorID 0x168C, 'Atheros Communications Inc.'
VendorID 0x1695, 'EPOX Computer Co'
VendorID 0x17F2, 'ALBATRON Corp.'
VendorID 0x1813, 'AMBIENT TECHNOLOGIES INC'
VendorID 0x1849, 'ASROCK Inc'
VendorID 0x1B13, 'Jaton Corp'
VendorID 0x2001, 'TEMPORAL RESEARCH LTD'
VendorID 0x270F, 'CHAINTECH COMPUTER CO. LTD'
VendorID 0x3388, 'HINT CORP'
VendorID 0x3411, 'QUANTUM DESIGNS (H.K.) INC.'
VendorID 0x4005, 'AVANCE LOGIC INC'
VendorID 0x4033, 'DELTA NETWORKS INC'
VendorID 0x416C, 'ALADDIN KNOWLEDGE SYSTEMS'
VendorID 0x4444, 'CONEXANT (WAS ICOMPRESION INC.)'
VendorID 0x4943, 'GROWTH NETWORKS'
VendorID 0x4CA1, 'SEANIX TECHNOLOGY INC'
VendorID 0x4D51, 'MEDIAQ INC.'
VendorID 0x4D54, 'MICROTECHNICA CO LTD'
VendorID 0x5136, 'S S TECHNOLOGIES'
VendorID 0x5333, 'S3 Graphics Co., Ltd.'
VendorID 0x544C, 'TERALOGIC INC'
VendorID 0x5555, 'GENROCO INC'
VendorID 0x6409, 'LOGITEC CORP.'
VendorID 0x6666, 'DECISION COMPUTER INTERNATIONAL CO.'
VendorID 0x8086, 'Intel Corp.'
VendorID 0x8888, 'SILICON MAGIC CORP.'
VendorID 0x8E0E, 'COMPUTONE CORPORATION'
VendorID 0x9004, 'Adaptec Inc'
VendorID 0x919A, 'GIGAPIXEL CORP'
VendorID 0x9412, 'HOLTEK'
VendorID 0x9699, 'OMNI MEDIA TECHNOLOGY INC.'
VendorID 0x9710, 'NetMos'
VendorID 0xA0A0, 'AOPEN INC.'
VendorID 0xA259, 'HEWLETT PACKARD'
VendorID 0xAC1E, 'DIGITAL RECEIVER TECHNOLOGY INC'
VendorID 0xC0DE, 'MOTOROLA'
VendorID 0xC0FE, 'MOTION ENGINEERING.'
VendorID 0xCA50, 'VARIAN AUSTRIALIA PTY LTD'
VendorID 0xCAFE, 'CHRYSALIS-ITS'
VendorID 0xCCCC, 'CATAPULT COMMUNICATIONS'
VendorID 0xD4D4, 'DY4 Systems Inc/Curtiss-Wright Controls Embed. Com'
VendorID 0xE159, 'TigerJet'
VendorID 0xE4BF, 'EKF ELEKTRONIK GMBH'
VendorID 0xEA01, 'EAGLE TECHNOLOGY'
VendorID 0xFA57, 'FAST SEARCH & TRANSFER ASA'
VendorID 0xFEDA, 'EPIGRAM INC'
VendorID 0, 'Unknown' ; <- terminator
 
;--------------------------------------
Classes:
; Class, Subclass, [Interface], Name
ClassID 2, 0, , 'Ethernet'
ClassID 2, 1, , 'Token Ring'
ClassID 2, 2, , 'FDDI'
ClassID 2, 3, , 'ATM'
ClassID 2, 4, , 'ISDN'
ClassID 2, 5, , 'WorldFip'
ClassID 2, 6, , 'PICMG 2.14'
ClassID 2, 0x80, , 'misc'
 
ClassID 0x0d, 0x20, , 'Wlan (802.11a)'
ClassID 0x0d, 0x21, , 'Wlan (802.11b)'
 
 
ClassID 0xff, 0xff, , 'Unknown' ; <- terminator
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/applications/netcfg/drivers.inc
0,0 → 1,198
driverlist:
db 'RTL8139',0
dd 0x813910ec
dd 0x813810ec
dd 0x12111113
dd 0x13601500
dd 0x13604033
dd 0x13001186
dd 0x13401186
dd 0xab0613d1
dd 0xa1171259
dd 0xa11e1259
dd 0xab0614ea
dd 0xab0714ea
dd 0x123411db
dd 0x91301432
dd 0x101202ac
dd 0x0106018a
dd 0x1211126c
dd 0x81391743
dd 0x8139021b
dd 0x0 ; end
 
db 'RTL8029',0
dd 0x802910ec
dd 0x0
 
db 'I8255X',0
dd 0x12098086
dd 0x10298086
dd 0x12298086
dd 0x10308086
dd 0x24498086
dd 0x0
 
db 'RTL8169',0
dd 0x816810ec
dd 0x816910ec
dd 0x011616ec
dd 0x43001186
dd 0x813610ec
dd 0x0
 
db '3C59X',0
dd 0x590010b7
dd 0x592010b7
dd 0x597010b7
dd 0x595010b7
dd 0x595110b7
dd 0x595210b7
dd 0x900010b7
dd 0x900110b7
dd 0x900410b7
dd 0x900510b7
dd 0x900610b7
dd 0x900A10b7
dd 0x905010b7
dd 0x905110b7
dd 0x905510b7
dd 0x905810b7
dd 0x905A10b7
dd 0x920010b7
dd 0x980010b7
dd 0x980510b7
dd 0x764610b7
dd 0x505510b7
dd 0x605510b7
dd 0x605610b7
dd 0x5b5710b7
dd 0x505710b7
dd 0x515710b7
dd 0x525710b7
dd 0x656010b7
dd 0x656210b7
dd 0x656410b7
dd 0x450010b7
dd 0x0
 
db 'SIS900',0
dd 0x09001039
dd 0x70161039
dd 0x0
 
db 'PCNET32',0
dd 0x20001022
dd 0x26251022
dd 0x20011022
dd 0x0
 
db 'FORCEDETH',0
dd 0x006610de
dd 0x01c310de
dd 0x00D610de
dd 0x008610de
dd 0x008c10de
dd 0x00e610de
dd 0x00df10de
dd 0x005610de
dd 0x005710de
dd 0x003710de
dd 0x003810de
dd 0x026810de
dd 0x026910de
dd 0x037210de
dd 0x037310de
dd 0x03e510de
dd 0x03e610de
dd 0x03ee10de
dd 0x03ef10de
dd 0x045010de
dd 0x045110de
dd 0x045210de
dd 0x045310de
dd 0x054c10de
dd 0x054d10de
dd 0x054e10de
dd 0x054f10de
dd 0x07dc10de
dd 0x07dd10de
dd 0x07de10de
dd 0x07df10de
dd 0x076010de
dd 0x076110de
dd 0x076210de
dd 0x076310de
dd 0x0ab010de
dd 0x0ab110de
dd 0x0ab210de
dd 0x0ab310de
dd 0x0d7d10de
dd 0x0
 
db 'MTD80X',0
dd 0x08031516
dd 0x08001516
dd 0x08911516
dd 0x0
 
db 'dec21x4x',0
dd 0x00091011
dd 0x00191011
dd 0x09851317
dd 0x0
 
db 'R6040',0
dd 0x604017F3
dd 0x0
 
db 'i8254x',0
dd 0x10008086 ; 82542 (Fiber)
dd 0x10018086 ; 82543GC (Fiber)
dd 0x10048086 ; 82543GC (Copper)
dd 0x10088086 ; 82544EI (Copper)
dd 0x10098086 ; 82544EI (Fiber)
dd 0x100A8086 ; 82540EM
dd 0x100C8086 ; 82544GC (Copper)
dd 0x100D8086 ; 82544GC (LOM)
dd 0x100E8086 ; 82540EM
dd 0x100F8086 ; 82545EM (Copper)
dd 0x10108086 ; 82546EB (Copper)
dd 0x10118086 ; 82545EM (Fiber)
dd 0x10128086 ; 82546EB (Fiber)
dd 0x10138086 ; 82541EI
dd 0x10148086 ; 82541ER
dd 0x10158086 ; 82540EM (LOM)
dd 0x10168086 ; 82540EP (Mobile)
dd 0x10178086 ; 82540EP
dd 0x10188086 ; 82541EI
dd 0x10198086 ; 82547EI
dd 0x101a8086 ; 82547EI (Mobile)
dd 0x101d8086 ; 82546EB
dd 0x101e8086 ; 82540EP (Mobile)
dd 0x10268086 ; 82545GM
dd 0x10278086 ; 82545GM
dd 0x10288086 ; 82545GM
dd 0x105b8086 ; 82546GB (Copper)
dd 0x10758086 ; 82547GI
dd 0x10768086 ; 82541GI
dd 0x10778086 ; 82541GI
dd 0x10788086 ; 82541ER
dd 0x10798086 ; 82546GB
dd 0x107a8086 ; 82546GB
dd 0x107b8086 ; 82546GB
dd 0x107c8086 ; 82541PI
dd 0x10b58086 ; 82546GB (Copper)
dd 0x11078086 ; 82544EI
dd 0x11128086 ; 82544GC
dd 0x0
 
db 'RHINE', 0 ; VIA Rhine
dd 0x30431106
dd 0x61001106
dd 0x30651106
dd 0x31061106
dd 0x30531106
dd 0x0
 
dd 0x0 ; driverlist end
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/applications/netcfg/netcfg.asm
0,0 → 1,548
;
; Netcfg v1.02
;
; Application to load network drivers in KolibriOS
;
; By hidnplayr
;
 
format binary as ""
 
use32
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd IM_END ; size of image
dd (I_END+0x100) ; memory for app
dd (I_END+0x100) ; esp
dd param, 0x0 ; I_Param , I_Icon
 
type_ethernet equ 1
 
include '../macros.inc'
 
START:
; first, check boot parameters
 
cmp byte[param], 0
je .noparams
 
mcall 40, 0
 
push .exit
cmp byte[param], 'A' ; A for All
je Get_PCI_Info
 
cmp byte[param], 'F' ; F for First
je Get_PCI_Info
 
ret
 
.exit:
mcall -1
 
.noparams:
call draw_window
 
still:
mcall 10 ; wait here for event
dec eax ; redraw request ?
jz red
dec eax ; key in buffer ?
jz key
dec eax ; button in buffer ?
jz button
jmp still
 
red: ; redraw
mcall 9, Proc_Info, -1 ; window redraw requested so get new window coordinates and size
mov eax, [Proc_Info.box.left]; store the window coordinates into the Form Structure
mov [Form + 2], ax ; x start position
mov eax, [Proc_Info.box.top];
mov [Form + 6], ax ; ystart position
mov eax, [Proc_Info.box.width] ;
mov [Form], ax ; window width
mov eax, [Proc_Info.box.height] ;
mov [Form + 4] ,ax ; window height
call draw_window ; go redraw window now
jmp still
 
key: ; key
mcall 2 ; just read it and ignore
jmp still
button: ; button
mcall 17 ; get id
 
cmp ah, 1 ; button id = 1 ?
jne @f
exit: mcall -1 ; close this program
@@:
cmp eax,0x0000ff00
jg load_drv
 
cmp ah, 4
je hook
 
cmp ah, 5
je reset
 
cmp ah, 6
je unload
 
jmp still
 
 
load_drv:
shr eax, 16
mov word [selected], ax
 
mov bl , 6 ; get a dword
mov bh , ah ; bus
mov ch , al ; dev
mov cl , 0 ; offset to device/vendor id
mcall 62 ; get ID's
 
mov word [PCI_Vendor], ax
shr eax, 16
mov word [PCI_Device], ax
call get_drv_ptr
 
mov ecx, eax
mcall 68, 16
 
mov [IOCTL.handle], eax
 
call draw_window
 
cmp [IOCTL.handle], 0
jne still
 
mcall 4, 20 shl 16 + 30, 1 shl 31 + 0x00ff0000 , load_error
 
jmp still
 
 
hook:
mov ax , [selected]
test ax , ax
jz still
 
mov [hardwareinfo.pci_dev], al
mov [hardwareinfo.pci_bus], ah
 
mov [IOCTL.io_code], 1 ; SRV_HOOK
mov [IOCTL.inp_size], 3
mov [IOCTL.input], hardwareinfo
mov [IOCTL.out_size], 0
mov [IOCTL.output], 0
 
mcall 68, 17, IOCTL
 
mov byte[drivernumber], al
 
jmp still
 
reset:
movzx ebx, byte[drivernumber]
mcall 74,,2
 
jmp still
 
unload:
movzx ebx, byte[drivernumber]
mcall 74,,3
 
jmp still
 
draw_window:
mcall 12, 1 ; start of draw
mcall 0, dword [Form], dword [Form + 4], 0x13ffffff, 0x805080d0, title
 
call Get_PCI_Info ; get pci version and last bus, scan for and draw each pci device
 
cmp edx, 20 shl 16 + 110
je .nonefound
 
mcall 4, 20 shl 16 + 100, 1 shl 31 + 0x00000000 , caption
 
cmp [selected], 0
jz .done
cmp [IOCTL.handle] ,0
jz .done
 
mcall 8, 18 shl 16 + 100, 35 shl 16 + 18, 4, 0x00007f00
mcall ,, 55 shl 16 + 18, 5, 0x0000007f
mcall ,, 75 shl 16 + 18, 6, 0x007f0000
 
mcall 4, 33 shl 16 + 42, 1 shl 31 + 0x00ffffff , btn_start
mcall , 33 shl 16 + 62, , btn_reset
mcall , 36 shl 16 + 82, , btn_stop
 
jmp .done
 
.nonefound:
mcall 4, 20 shl 16 + 30, 1 shl 31 + 0x00ff0000 , nonefound
.done:
mcall 12, 2 ; end of draw
ret
 
 
 
 
 
;------------------------------------------------------------------
;* Gets the PCI Version and Last Bus
Get_PCI_Info:
mcall 62, 0
mov word [PCI_Version], ax
mcall 62, 1
mov byte [PCI_LastBus], al
;----------------------------------------------------------
;* Get all devices on PCI Bus
mov edx, 20 shl 16 + 110 ; set start write position
cmp al , 0xff ; 0xFF means no pci bus found
jne Pci_Exists ;
ret ; if no bus then leave
Pci_Exists:
mov byte [V_Bus], 0 ; reset varibles
mov byte [V_Dev], 0 ;
Start_Enum:
mov bl , 6 ; get a dword
mov bh , byte [V_Bus] ; bus of pci device
mov ch , byte [V_Dev] ; device number/function
mov cl , 0 ; offset to device/vendor id
mcall 62 ; get ID's
 
cmp ax, 0 ; Vendor ID should not be 0 or 0xFFFF
je nextDev ; check next device if nothing exists here
cmp ax, 0xffff ;
je nextDev ;
 
mov word [PCI_Vendor], ax ; There is a device here, save the ID's
shr eax, 16 ;
mov word [PCI_Device], ax ;
mov bl , 4 ; Read config byte
mov bh , byte [V_Bus] ; Bus #
mov ch , byte [V_Dev] ; Device # on bus
mov cl , 0x08 ; Register to read (Get Revision)
mcall 62 ; Read it
mov byte [PCI_Rev], al ; Save it
mov cl , 0x0b ; Register to read (Get class)
mcall 62 ; Read it
mov byte [PCI_Class], al ; Save it
mov cl , 0x0a ; Register to read (Get Subclass)
mcall 62 ; Read it
mov byte [PCI_SubClass], al ; Save it
mov cl , 0x09 ; Register to read (Get Interface)
mcall 62 ; Read it
mov [PCI_Interface], al ; Save it
mov cl , 0x3c ; Register to read (Get IRQ)
@@: mcall 62 ; Read it
mov [PCI_IRQ], al ; Save it
 
; cmp byte [PCI_Class], 0 ; device from before class codes
; je @f
 
cmp byte [PCI_Class], 2 ; network controller
jne nextDev
; @@:
 
cmp byte[param], 0
jne load_and_start
 
mov cl, 0x0e
mcall 62
push eax
call Print_New_Device ; print device info to screen
pop eax
test al, al
js nextDev
 
nextdev2:
test byte [V_Dev], 7
jnz nextDev
or byte [V_Dev], 7
 
nextDev:
inc [V_Dev] ; lower 3 bits are the function number
 
jnz Start_Enum ; jump until we reach zero
mov byte [V_Dev], 0 ; reset device number
inc byte [V_Bus] ; next bus
mov al , byte [PCI_LastBus] ; get last bus
cmp byte [V_Bus], al ; was it last bus
jbe Start_Enum ; if not jump to keep searching
ret
 
 
 
load_and_start:
 
call get_drv_ptr
cmp eax, lbl_none
je .next
 
mov ecx, eax
mcall 68, 16
test eax, eax
jz .next
mov [IOCTL.handle], eax
 
mov al, [V_Dev]
mov [hardwareinfo.pci_dev], al
mov al, [V_Bus]
mov [hardwareinfo.pci_bus], al
 
mov [IOCTL.io_code], 1 ; SRV_HOOK
mov [IOCTL.inp_size], 3
mov [IOCTL.input], hardwareinfo
mov [IOCTL.out_size], 0
mov [IOCTL.output], 0
 
mcall 68, 17, IOCTL
 
.next:
cmp byte[param], 'A'
je nextdev2
jmp exit
 
 
 
;------------------------------------------------------------------
;* Print device info to screen
Print_New_Device:
 
push edx ; Magic ! (to print a button...)
 
mov ebx, 18 shl 16
mov bx , [Form]
sub bx , 36
 
mov cx , dx
dec cx
shl ecx, 16
add ecx, 9
 
movzx edx, byte [V_Bus]
shl dx , 8
mov dl , byte [V_Dev]
 
mov esi, 0x0000c0ff ; color: yellow if selected, blue otherwise
cmp word [selected], dx
jne @f
mov esi, 0x00c0c000
@@:
 
shl edx, 8
or dl , 0xff
 
mcall 8
pop edx
 
xor esi, esi ; Color of text
movzx ecx, word [PCI_Vendor] ; number to be written
mcall 47, 0x00040100 ; Write Vendor ID
 
add edx, (4*6+18) shl 16
movzx ecx, word [PCI_Device] ; get Vendor ID
mcall ; Draw Vendor ID to Window
 
add edx, (4*6+18) shl 16
movzx ecx, byte [V_Bus] ; get bus number
mcall ,0x00020100 ; draw bus number to screen
 
add edx, (2*6+18) shl 16
movzx ecx, byte [V_Dev] ; get device number
shr ecx, 3 ; device number is bits 3-7
mcall ; Draw device Number To Window
 
add edx, (2*6+18) shl 16
movzx ecx, byte [PCI_Rev] ; get revision number
mcall ; Draw Revision to screen
 
add edx, (2*6+18) shl 16
movzx ecx, [PCI_IRQ]
cmp cl , 0x0f ; IRQ must be between 0 and 15
ja @f
mcall
@@:
;
;Write Names
movzx ebx, dx ; Set y position
or ebx, 230 shl 16 ; set Xposition
 
;------------------------------------------------------------------
; Prints the Vendor's Name based on Vendor ID
;------------------------------------------------------------------
mov edx, VendorsTab
mov cx , word[PCI_Vendor]
.fn: mov ax , [edx]
add edx, 6
test ax , ax
jz .find
cmp ax , cx
jne .fn
.find: mov edx, [edx - 4]
mcall 4,, 0x80000000 ; lets print the vendor Name
 
;------------------------------------------------------------------
; Get description based on Class/Subclass
;------------------------------------------------------------------
mov eax, dword [PCI_Class]
and eax, 0xffffff
xor edx, edx
xor esi, esi
.fnc: inc esi
mov ecx, [Classes + esi * 8 - 8]
cmp cx , 0xffff
je .endfc
cmp cx , ax
jne .fnc
test ecx, 0xff000000
jz @f
mov edx, [Classes + esi * 8 - 4]
jmp .fnc
@@: cmp eax, ecx
jne .fnc
xor edx, edx
.endfc: test edx, edx
jnz @f
mov edx, [Classes + esi * 8 - 4]
@@:
add ebx, 288 shl 16
mcall 4,, 0x80000000,, 32 ; draw the text
movzx edx, bx ; get y coordinate
add edx, 0x0014000A ; add 10 to y coordinate and set x coordinate to 20
 
;------------------------------------------------------------------
; Print Driver Name
;------------------------------------------------------------------
push edx
add ebx, 120 shl 16
push ebx
 
call get_drv_ptr
mov edx, eax
pop ebx
mcall 4,,0x80000000 ; lets print the vendor Name
pop edx
ret
 
get_drv_ptr:
mov eax, driverlist ; eax will be the pointer to latest driver title
mov ebx, driverlist ; ebx is the current pointer
mov ecx, dword[PCI_Vendor] ; the device/vendor id of we want to find
 
driverloop:
inc ebx
 
cmp byte[ebx],0
jne driverloop
 
inc ebx ; the device/vendor id list for the driver eax is pointing to starts here.
 
deviceloop:
cmp dword[ebx],0
je nextdriver
 
cmp dword[ebx],ecx
je driverfound
 
add ebx,4
jmp deviceloop
 
nextdriver:
add ebx,4
 
cmp dword[ebx],0
je nodriver
 
mov eax,ebx
jmp driverloop
 
nodriver:
mov eax, lbl_none ; lets print the vendor Name
ret
 
driverfound:
ret
 
include 'vendors.inc'
include 'drivers.inc'
 
 
;------------------------------------------------------------------
; DATA AREA
 
 
DATA
 
 
Form: dw 800 ; window width (no more, special for 800x600)
dw 100 ; window x start
dw 220 ; window height
dw 100 ; window y start
 
title db 'Network Driver Control Center', 0
 
caption db 'Vendor Device Bus Dev Rev IRQ Company Description DRIVER',0
nonefound db 'No compatible devices were found!',0
btn_start db 'Start device',0
btn_reset db 'Reset device',0
btn_stop db 'Stop device',0
lbl_none db 'none',0
load_error db 'Could not load driver!',0
 
hardwareinfo:
.type db 1 ; pci
.pci_bus db ?
.pci_dev db ?
 
 
IM_END:
 
;------------------------------------------------------------------
; UNINITIALIZED DATA AREA
 
 
IOCTL:
.handle dd ?
.io_code dd ?
.input dd ?
.inp_size dd ?
.output dd ?
.out_size dd ?
 
drivernumber db ?
MAC dp ?
 
 
type db ?
selected dw ?
V_Bus db ?
V_Dev db ?
PCI_Version dw ?
PCI_LastBus db ?
PCI_Vendor dw ?
PCI_Device dw ?
PCI_Bus db ?
PCI_Dev db ?
PCI_Rev db ?
; don`t change order!!!
PCI_Class db ?
PCI_SubClass db ?
PCI_Interface db ?
PCI_IRQ db ?
 
Proc_Info process_information
 
param rb 1024
 
 
I_END:
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/applications/netstat/netstat.asm
0,0 → 1,614
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; netstat.asm - Network Status Tool for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format binary as ""
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image
dd (I_END+0x100) ; memory for app
dd (I_END+0x100) ; esp
dd I_PARAM , 0x0 ; I_Param , I_Icon
 
include '..\macros.inc'
include '..\network.inc'
 
START:
mcall 40, EVM_REDRAW + EVM_BUTTON + EVM_STACK2
 
redraw:
mcall 12, 1
mcall 0, 100 shl 16 + 600, 100 shl 16 + 240, 0x34bcbcbc, , name ; draw window
 
call draw_interfaces
 
mov edx, 101
mov esi, 0x00aaaaff
mov edi, 0x00aaffff
 
cmp dl, [mode]
cmove esi, edi
mcall 8, 25 shl 16 + 65, 25 shl 16 + 20
 
.morebuttons:
inc edx
add ebx, 75 shl 16
mov esi, 0x00aaaaff
 
cmp dl, [mode]
cmove esi, edi
mcall
 
cmp edx, 105
jle .morebuttons
 
mcall 4, 28 shl 16 + 31, 0x80000000, modes
 
cmp [mode], 101
jne .no_eth
 
mcall 4, 20 shl 16 + 75, 0x80000000, str_packets_tx
add ebx, 18
mov edx, str_packets_rx
mcall
add ebx, 18
mov edx, str_bytes_tx
mcall
add ebx, 18
mov edx, str_bytes_rx
mcall
add ebx, 18
mov edx, str_MAC
mcall
add ebx, 18
mov edx, str_link
mcall
 
mov ebx, API_ETH + 4
mov bh, [device]
mcall 76
push eax
push bx
 
mov edx, 135 shl 16 + 75 + 4*18
call draw_mac
jmp end_of_draw
 
.no_eth:
 
cmp [mode], 102
jne .no_ip
 
mcall 4, 20 shl 16 + 75, 0x80000000, str_packets_tx
add ebx, 18
mov edx, str_packets_rx
mcall
add ebx, 18
mov edx, str_ip
mcall
add ebx, 18
mov edx, str_dns
mcall
add ebx, 18
mov edx, str_subnet
mcall
add ebx, 18
mov edx, str_gateway
mcall
 
 
mov ebx, API_IPv4 + 8
mov bh, [device]
mcall 76
push eax
 
dec bl
dec bl
mcall 76
push eax
 
dec bl
dec bl
mcall 76
push eax
 
dec bl
dec bl
mcall 76
push eax
 
mov edx, 135 shl 16 + 75 + 2*18
call draw_ip
 
add edx, 18
call draw_ip
 
add edx, 18
call draw_ip
 
add edx, 18
call draw_ip
 
jmp end_of_draw
 
.no_ip:
 
cmp [mode], 103
jne .no_arp
 
mcall 4, 20 shl 16 + 75, 0x80000000, str_packets_tx
add ebx, 18
mov edx, str_packets_rx
mcall
add ebx, 18
mov edx, str_arp
mcall
add ebx, 18
mov edx, str_conflicts
mcall
 
jmp end_of_draw
 
.no_arp:
 
mcall 4, 20 shl 16 + 75, 0x80000000, str_packets_tx
 
add ebx, 18
mov edx, str_packets_rx
mcall
 
cmp [mode], 106
jne end_of_draw
 
add ebx, 18
mov edx, str_missed
mcall
 
add ebx, 18
mov edx, str_dumped
mcall
 
 
 
end_of_draw:
mcall 12, 2
 
draw_stats:
 
cmp [mode], 101
jne not_101
 
mov ebx, API_ETH
mov bh, [device]
@@:
push ebx
mcall 76
pop ebx
push eax
inc bl
cmp bl, 3
jbe @r
inc bl
mcall 76
push eax
 
mov ebx, 0x000a0000
pop ecx
mov edx, 135 shl 16 + 75 + 5*18
mov esi, 0x40000000
mov edi, 0x00bcbcbc
mcall 47
 
sub edx, 18*2
pop ecx
mcall
 
sub edx, 18
pop ecx
mcall
 
sub edx, 18
pop ecx
mcall
 
sub edx, 18
pop ecx
mcall
 
jmp mainloop
 
 
not_101:
 
cmp [mode], 102
jne not_102
 
mov ebx, API_IPv4
mov bh, [device]
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
 
mov ebx, 0x000a0000
pop ecx
mov edx, 135 shl 16 + 75 + 18
mov esi, 0x40000000
mov edi, 0x00bcbcbc
mcall 47
 
sub edx, 18
pop ecx
mcall
 
jmp mainloop
 
 
not_102:
 
cmp [mode], 103
jne not_103
 
mov ebx, API_ARP
mov bh, [device]
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
mov bl, 7
push ebx
mcall 76
pop ebx
push eax
 
mov ebx, 0x000a0000
pop ecx
mov edx, 135 shl 16 + 75 + 3*18
mov esi, 0x40000000
mov edi, 0x00bcbcbc
mcall 47
 
sub edx, 18
pop ecx
mcall
 
sub edx, 18
pop ecx
mcall
 
sub edx, 18
pop ecx
mcall
 
jmp mainloop
 
not_103:
 
cmp [mode], 104
jne not_104
 
mov ebx, API_ICMP
mov bh, [device]
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
mov ebx, 0x000a0000
pop ecx
mov edx, 135 shl 16 + 75 + 18
mov esi, 0x40000000
mov edi, 0x00bcbcbc
mcall 47
 
sub edx, 18
pop ecx
mcall
 
jmp mainloop
 
not_104:
 
cmp [mode], 105
jne not_105
 
mov ebx, API_UDP
mov bh, [device]
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
mov ebx, 0x000a0000
pop ecx
mov edx, 135 shl 16 + 75 + 18
mov esi, 0x40000000
mov edi, 0x00bcbcbc
mcall 47
 
sub edx, 18
pop ecx
mcall
 
jmp mainloop
 
not_105:
 
cmp [mode], 106
jne not_106
 
mov ebx, API_TCP
mov bh, [device]
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
mov ebx, 0x000a0000
pop ecx
mov edx, 135 shl 16 + 75 + 18*3
mov esi, 0x40000000
mov edi, 0x00bcbcbc
mcall 47
 
sub edx, 18
pop ecx
mcall
 
sub edx, 18
pop ecx
mcall
 
sub edx, 18
pop ecx
mcall
 
jmp mainloop
 
not_106:
 
mainloop:
 
mcall 23, 50 ; wait for event with timeout (0,5 s)
 
cmp eax, 1
je redraw
cmp eax, 3
je button
cmp eax, 11
je redraw
 
jmp draw_stats
 
button: ; button
mcall 17 ; get id
cmp ah, 1
je exit
cmp ah, 0
je .interface
mov [mode], ah
jmp redraw
 
.interface:
shr eax, 16
mov [device], al
jmp redraw
 
exit:
mcall -1
 
 
 
draw_mac:
 
mov eax, 47
mov ebx, 0x00020100
mov esi, 0x40000000
mov edi, 0x00bcbcbc
 
mov cl, [esp+4]
mcall
 
mov cl, [esp+4+1]
add edx, 15 shl 16
mcall
 
mov cl, [esp+4+2]
add edx, 15 shl 16
mcall
 
mov cl, [esp+4+3]
add edx, 15 shl 16
mcall
 
mov cl, [esp+4+4]
add edx, 15 shl 16
mcall
 
mov cl, [esp+4+5]
add edx, 15 shl 16
mcall
 
sub edx, 5*15 shl 16
 
ret 6
 
 
draw_ip:
 
mov eax, 47
mov ebx, 0x00030000
mov esi, 0x40000000
mov edi, 0x00bcbcbc
 
xor ecx, ecx
 
mov cl, [esp+4]
mcall
 
mov cl, [esp+4+1]
add edx, 30 shl 16
mcall
 
mov cl, [esp+4+2]
add edx, 30 shl 16
mcall
 
mov cl, [esp+4+3]
add edx, 30 shl 16
mcall
 
sub edx, 3*30 shl 16
ret 4
 
 
draw_interfaces:
 
mov [.btnpos], 8 shl 16 + 20
mov [.txtpos], 490 shl 16 + 15
 
mcall 74, -1 ; get number of active network devices
mov ecx, eax
 
xor ebx, ebx ; get device type
.loop:
mcall 74
cmp eax, 1 ; ethernet?
je .hit
inc bh
jb .loop ; tried all 256?
ret
 
 
.hit:
push ecx ebx
movzx edx, bh
shl edx, 8
mov esi, 0x00aaaaff
cmp bh, [device]
cmove esi, 0x00aaffff
mcall 8, 485 shl 16 + 100, [.btnpos]
mov ebx, [esp]
inc bl
mov ecx, namebuf
mov edx, namebuf
mcall 74 ; get device name
cmp eax, -1
jne @f
mov edx, str_unknown
@@:
mcall 4, [.txtpos], 0x80000000 ; print the name
pop ebx ecx
 
inc bh
 
add [.btnpos], 25 shl 16
add [.txtpos], 25
 
dec ecx
jnz .loop
 
ret
 
.btnpos dd ?
.txtpos dd ?
 
 
 
 
; DATA AREA
 
name db 'Netstat', 0
mode db 101
device db 0
modes db 'Ethernet IPv4 ARP ICMP UDP TCP', 0
 
str_packets_tx db 'Packets sent:', 0
str_packets_rx db 'Packets received:', 0
str_bytes_tx db 'Bytes sent:', 0
str_bytes_rx db 'Bytes received:', 0
str_MAC db 'MAC address:', 0
str_ip db 'IP address:', 0
str_dns db 'DNS address:', 0
str_subnet db 'Subnet mask:', 0
str_gateway db 'Standard gateway:', 0
str_arp db 'ARP entrys:', 0
str_conflicts db 'ARP conflicts:', 0
str_unknown db 'unknown', 0
str_missed db 'Packets missed:',0
str_dumped db 'Packets dumped:',0
str_link db 'Link state:',0
 
namebuf rb 64
 
I_PARAM rb 1024
 
I_END:
 
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/applications/network.inc
0,0 → 1,94
; Socket types
SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3
 
; Socket options
SO_NONBLOCK = 1 shl 31
 
; IP protocols
IPPROTO_IP = 0
IPPROTO_ICMP = 1
IPPROTO_TCP = 6
IPPROTO_UDP = 17
 
; Address families
AF_UNSPEC = 0
AF_LOCAL = 1
AF_INET4 = 2 ; IPv4
AF_INET6 = 28 ; IPv6 (not supported yet)
 
PF_UNSPEC = AF_UNSPEC
PF_LOCAL = AF_LOCAL
PF_INET4 = AF_INET4
PF_INET6 = AF_INET6
 
; Flags for addrinfo
AI_PASSIVE = 1
AI_CANONNAME = 2
AI_NUMERICHOST = 4
AI_NUMERICSERV = 8
AI_ADDRCONFIG = 0x400
 
; internal definition
AI_SUPPORTED = 0x40F
 
; for system function 76
API_ETH = 0 shl 16
API_IPv4 = 1 shl 16
API_ICMP = 2 shl 16
API_UDP = 3 shl 16
API_TCP = 4 shl 16
API_ARP = 5 shl 16
API_PPPOE = 6 shl 16
 
struct sockaddr_in
sin_family dw ? ; sa_family_t
sin_port dw ? ; in_port_t
sin_addr dd ? ; struct in_addr
sin_zero rb 8 ; zero
ends
 
struct addrinfo
ai_flags dd ? ; bitmask of AI_*
ai_family dd ? ; PF_*
ai_socktype dd ? ; SOCK_*
ai_protocol dd ? ; 0 or IPPROTO_*
ai_addrlen dd ? ; length of ai_addr
ai_canonname dd ? ; char*
ai_addr dd ? ; struct sockaddr*
ai_next dd ? ; struct addrinfo*
ends
 
EAI_ADDRFAMILY = 1
EAI_AGAIN = 2
EAI_BADFLAGS = 3
EAI_FAIL = 4
EAI_FAMILY = 5
EAI_MEMORY = 6
EAI_NONAME = 8
EAI_SERVICE = 9
EAI_SOCKTYPE = 10
EAI_BADHINTS = 12
EAI_PROTOCOL = 13
EAI_OVERFLOW = 14
 
socket fix 75, 0
close fix 75, 1
bind fix 75, 2
listen fix 75, 3
connect fix 75, 4
accept fix 75, 5
send fix 75, 6
recv fix 75, 7
setsockopt fix 75, 8
getsockopt fix 75, 9
socketpair fix 75, 10
 
 
struct ARP_entry
IP dd ?
MAC dp ?
status dw ?
TTL dw ?
ends
/kernel/branches/net/applications/tftpc/tftpc.asm
0,0 → 1,566
format binary as ""
 
use32
org 0x0
 
db 'MENUET01'
dd 0x1
dd START
dd I_END
dd IM_END
dd IM_END
dd 0, 0
 
include '../proc32.inc'
include '../macros.inc'
include '../libio.inc'
include '../dll.inc'
include '../../../../../programs/develop/libraries/box_lib/trunk/box_lib.mac'
 
include '../network.inc'
 
 
filebuffer_size equ 4*4096 ; 16kb (dont try to change it yet..)
TIMEOUT equ 100
buffer_len equ 1500
 
AF_INET4 equ 2
IP_PROTO_UDP equ 17
 
opcode_rrq equ 1
opcode_wrq equ 2
opcode_data equ 3
opcode_ack equ 4
opcode_error equ 5
 
; read/write request packet
;
; 2 bytes string 1 byte string 1 byte
; ------------------------------------------------
; | Opcode | Filename | 0 | Mode | 0 |
; ------------------------------------------------
 
; data packet
;
; 2 bytes 2 bytes n bytes
; ----------------------------------
; | Opcode | Block # | Data |
; ----------------------------------
 
; acknowledgement packet
;
; 2 bytes 2 bytes
; ---------------------
; | Opcode | Block # |
; ---------------------
 
; error packet
;
; 2 bytes 2 bytes string 1 byte
; ----------------------------------------
; | Opcode | ErrorCode | ErrMsg | 0 |
; ----------------------------------------
 
 
START:
 
mcall 68, 11
 
stdcall dll.Load, @IMPORT
or eax, eax
jnz exit
 
stop_transfer:
mcall 40, 00100111b
 
red_win:
call draw_window
 
align 4
still:
mcall 10
 
dec eax
jz red_win
 
dec eax
jz key
 
dec eax
jz button
 
push dword edit1
call [edit_box_mouse]
 
push dword edit2
call [edit_box_mouse]
 
push dword edit3
call [edit_box_mouse]
 
push dword edit4
call [edit_box_mouse]
 
push dword Option_boxs1
call [option_box_mouse]
 
push dword Option_boxs2
call [option_box_mouse]
 
jmp still
 
button:
mcall 17
 
cmp ah,0x10
je start_transfer
 
 
test ah , ah
jz still
 
exit: mcall -1
key:
mcall 2
 
push dword edit1
call [edit_box_key]
 
push dword edit2
call [edit_box_key]
 
push dword edit3
call [edit_box_key]
 
push dword edit4
call [edit_box_key]
 
jmp still
 
 
align 4
draw_window:
mcall 12,1
mcall 0, (50*65536+400), (30*65536+180), 0x34AABBCC, 0x085080DD, str_title
 
mcall 4, 35*65536+10, 0x80000000, str_server
 
mov ebx, 5*65536+30
mov edx, str_source
mcall
 
mov ebx, 11*65536+50
mov edx, str_destination
mcall
 
mov ebx, 47*65536+72
mov edx, str_mode
mcall
 
mov ebx, 160*65536+72
mov edx, str_method
mcall
 
mov ebx, 270*65536+72
mov edx, str_blocksize
mcall
 
push dword edit1
call [edit_box_draw]
 
push dword edit2
call [edit_box_draw]
 
push dword edit3
call [edit_box_draw]
 
push dword edit4
call [edit_box_draw]
 
push dword Option_boxs1
call [option_box_draw]
 
push dword Option_boxs2
call [option_box_draw]
 
mcall 8,210*65536+170, 105*65536+16,0x00000010,0x085080DD
 
mcall 4,260*65536+110, 0x80000000, str_transfer
 
mcall 38,10*65536+380, 130*65536+130,0x00000000
 
mcall 4,350*65536+137, 0x80000000, str_kb_s
 
mcall 47,1 shl 31 + 7 shl 16 + 1,kbps,305*65536+137,0x00000000
 
mcall 4,50*65536+137, 0x80000000, str_complete
 
mcall 47,1 shl 31 + 3 shl 16 + 1,done,25*65536+137,0x00000000
 
mcall 12,2
 
ret
 
 
 
 
 
start_transfer:
 
; first, resolve the hostname
 
push esp ; reserve stack place
 
push esp ; fourth parameter
push 0 ; third parameter
push 0 ; second parameter
push dword SRV ; first parameter
call [getaddrinfo]
 
pop esi
 
; test for error
test eax, eax
jnz still
 
mov esi, [esi]
mov esi, [esi + sockaddr_in.sin_addr]
mov dword [IP], esi
 
mcall socket, AF_INET4, SOCK_DGRAM, 0 ; socket_open
cmp eax, -1
je still
 
mov [socketnum], eax
 
mcall connect, [socketnum], sockaddr, sockaddr_len ; socket_connect
cmp eax, -1
je still
 
mov word [I_END], opcode_rrq
cmp [option_group2],op3
je @f
mov word [I_END], opcode_wrq
@@:
 
xor al , al
mov edi, remote_addr
mov ecx, 250
repnz scasb
sub edi, remote_addr-1
mov ecx, edi
mov edi, I_END+2
mov esi, remote_addr
rep movsb
 
cmp [option_group1], op1
je .ascii
 
mov esi, octet
movsd
movsb
 
jmp .send_request
 
.ascii:
 
mov esi, netascii
movsd
movsd
 
.send_request:
 
xor al, al
stosb
 
sub edi, I_END
mov esi, edi
mcall send, [socketnum], I_END
 
mcall 40, 10000101b
 
mov [last_ack], 0
 
 
 
 
 
 
receive_data_loop:
 
mcall 23, TIMEOUT
 
dec eax
jz .red
 
dec eax
jz .key
 
 
mcall recv, [socketnum], buffer, buffer_len, 0 ; receive data
 
cmp word[buffer], opcode_data
jne .error
 
mov bx, [last_ack]
cmp word [buffer + 2], bx
jne .packet_got_lost
inc [last_ack]
 
cmp eax, 4+512
je .continue
 
; last packet, or something else
.error:
 
.packet_got_lost:
 
 
 
.continue:
 
mov word[buffer], opcode_ack ; send ack
mcall send, [socketnum], buffer, 4, 0
 
jmp receive_data_loop
 
.red:
 
call draw_window
 
jmp receive_data_loop
 
 
.key:
mcall 2
cmp ah, 2
jz exit
 
; close socket ?
 
jmp receive_data_loop
 
 
 
 
 
 
;--------------------------------
 
 
send_:
 
invoke file_open, local_addr, O_READ
or eax, eax
jz .exit
mov [fh], eax
 
stdcall mem.Alloc, filebuffer_size
or eax, eax
jz .exit
mov [fb], eax
 
mov [last_ack], 0
mov [fo], 0
 
.read_chunk:
 
invoke file_seek, [fh], [fo], SEEK_END
cmp eax, -1
je .exit
invoke file_read, [fh], [fb], filebuffer_size
cmp eax, -1
je .exit
add [fo], filebuffer_size
cmp eax, filebuffer_size
je .packet
 
; ijhidfhfdsndsfqk
 
.packet:
 
movzx esi, [last_ack]
and esi, 0x000000001f ; last five bits BUFFER SIZE MUST BE 16 kb for this to work !!!
shl esi, 9 ; = * 512
add esi, [fb]
mov edi, buffer
mov ax, opcode_data
stosw
mov ax, [last_ack]
stosw
mov ecx, 512/4
rep movsd
 
mcall send, [socketnum], buffer, 4+512, 0 ; send data
 
 
.loop:
 
mcall 23, TIMEOUT
 
dec eax
jz .red
 
dec eax
jz .key
 
mcall recv, [socketnum], buffer, buffer_len, 0 ; receive ack
 
cmp word[buffer], opcode_ack
jne .exit
 
mov ax, [last_ack]
cmp word[buffer+2], ax
jne .packet
inc [last_ack]
test [last_ack],0x001f
jz .read_chunk
jmp .packet
 
 
.red:
 
call draw_window
 
jmp .loop
 
 
.key:
mcall 2
cmp ah, 2
jz exit
 
; close socket ?
 
jmp .loop
 
.exit:
invoke file_close, [fh]
jmp still
 
 
 
 
 
;-------------------------
; DATA
 
socketnum dd 0
kbps dd 0
done dd 0
 
sockaddr:
dw AF_INET4
dw 0x4500 ; 69
IP db 192,168,1,115
sockaddr_len = $ - sockaddr
 
align 16
@IMPORT:
 
library box_lib , 'box_lib.obj', \
io_lib , 'libio.obj', \
network , 'network.obj'
 
import box_lib ,\
edit_box_draw ,'edit_box' ,\
edit_box_key ,'edit_box_key' ,\
edit_box_mouse ,'edit_box_mouse' ,\
version_ed ,'version_ed' ,\
init_checkbox ,'init_checkbox2' ,\
check_box_draw ,'check_box_draw2' ,\
check_box_mouse ,'check_box_mouse2' ,\
version_ch ,'version_ch2' ,\
option_box_draw ,'option_box_draw' ,\
option_box_mouse ,'option_box_mouse' ,\
version_op ,'version_op'
 
import io_lib ,\
file_find_first , 'file_find_first' ,\
file_find_next , 'file_find_next' ,\
file_find_close , 'file_find_close' ,\
file_size , 'file_size' ,\
file_open , 'file_open' ,\
file_read , 'file_read' ,\
file_write , 'file_write' ,\
file_seek , 'file_seek' ,\
file_tell , 'file_tell' ,\
file_eof? , 'file_iseof' ,\
file_seteof , 'file_seteof' ,\
file_truncate , 'file_truncate' ,\
file_close , 'file_close'
 
import network ,\
inet_ntoa , 'inet_ntoa' ,\
getaddrinfo , 'getaddrinfo' ,\
freeaddrinfo , 'freeaddrinfo'
 
 
edit1 edit_box 300,80,5 ,0xffffff,0x6f9480,0,0,0,99 ,SRV,mouse_dd,ed_focus, 11,11
edit2 edit_box 300,80,25,0xffffff,0x6a9480,0,0,0,99 ,remote_addr,mouse_dd,ed_figure_only, 5,5
edit3 edit_box 300,80,45,0xffffff,0x6a9480,0,0,0,99 ,local_addr,mouse_dd,ed_figure_only, 27,27
edit4 edit_box 40,340,68,0xffffff,0x6a9480,0,0,0,5 ,BLK,mouse_dd,ed_figure_only, 3,3
 
op1 option_box option_group1,80,68,6,12,0xffffff,0,0,netascii,octet-netascii
op2 option_box option_group1,80,85,6,12,0xFFFFFF,0,0,octet,get-octet
 
op3 option_box option_group2,210,68,6,12,0xffffff,0,0,get,put-get
op4 option_box option_group2,210,85,6,12,0xFFFFFF,0,0,put,BLK-put
 
option_group1 dd op1
option_group2 dd op3
Option_boxs1 dd op1,op2,0
Option_boxs2 dd op3,op4,0
 
str_title db 'TFTP client for KolibriOS',0
str_server db 'Server:',0
str_source db 'Remote file:',0
str_destination db 'Local file:',0
str_mode db 'Mode:',0
str_method db 'Method:',0
str_blocksize db 'Blocksize:',0
str_kb_s db 'kb/s',0
str_complete db '% complete',0
str_transfer db 'Transfer',0
 
str_error:
._0 db 'Not defined, see error message (if any).',0
._1 db 'File not found.',0
._2 db 'Access violation.',0
._3 db 'Disk full or allocation exceeded.',0
._4 db 'Illegal TFTP operation.',0
._5 db 'Unknown transfer ID.',0
._6 db 'File already exists.',0
._7 db 'No such user.',0
 
 
netascii db 'NetASCII'
octet db 'Octet'
get db 'GET'
put db 'PUT'
 
BLK db "512",0,0,0
 
last_ack dw ?
 
fh dd ? ; file handle
fo dd ? ; file offset
fb dd ? ; file buffer
 
SRV db "192.168.1.115",0
rb (SRV + 256 - $)
 
remote_addr db "IMG00",0
rb (remote_addr + 256 - $)
 
local_addr db "/hd0/1/KolibriOS/kernel.mnt",0
rb (local_addr + 256 - $)
 
I_END:
mouse_dd dd ?
buffer:
rb buffer_len
 
rb 0x1000 ; stack
 
IM_END:
/kernel/branches/net/applications/socketdbg/socket.inc
0,0 → 1,164
struct LHEAD
next dd ? ;next object in list
prev dd ? ;prev object in list
ends
 
struct MUTEX
lhead LHEAD
count dd ?
ends
 
 
struct SOCKET
 
NextPtr dd ? ; pointer to next socket in list
PrevPtr dd ? ; pointer to previous socket in list
Number dd ? ; socket number
 
mutex MUTEX
 
PID dd ? ; application process id
Domain dd ? ; INET/UNIX/..
Type dd ? ; RAW/STREAM/DGRAP
Protocol dd ? ; ICMP/IPv4/ARP/TCP/UDP
errorcode dd ?
device dd ?
 
options dd ?
state dd ?
backlog dw ? ; how many incomming connections that can be queued
 
snd_proc dd ?
rcv_proc dd ?
 
ends
 
struct IP_SOCKET SOCKET
 
LocalIP rd 4 ; network byte order
RemoteIP rd 4 ; network byte order
 
ends
 
struct TCP_SOCKET IP_SOCKET
 
LocalPort dw ? ; network byte order
RemotePort dw ? ; network byte order
 
t_state dd ? ; TCB state
t_rxtshift db ?
rb 3 ; align
t_rxtcur dd ?
t_dupacks dd ?
t_maxseg dd ?
t_force dd ?
t_flags dd ?
 
;---------------
; RFC783 page 21
 
; send sequence
SND_UNA dd ? ; sequence number of unack'ed sent Packets
SND_NXT dd ? ; next send sequence number to use
SND_UP dd ? ; urgent pointer
SND_WL1 dd ? ; window minus one
SND_WL2 dd ? ;
ISS dd ? ; initial send sequence number
SND_WND dd ? ; send window
 
; receive sequence
RCV_WND dd ? ; receive window
RCV_NXT dd ? ; next receive sequence number to use
RCV_UP dd ? ; urgent pointer
IRS dd ? ; initial receive sequence number
 
;---------------------
; Additional variables
 
; receive variables
RCV_ADV dd ?
 
; retransmit variables
SND_MAX dd ?
 
; congestion control
SND_CWND dd ?
SND_SSTHRESH dd ?
 
;----------------------
; Transmit timing stuff
t_idle dd ?
t_rtt dd ?
t_rtseq dd ?
t_srtt dd ?
t_rttvar dd ?
t_rttmin dd ?
max_sndwnd dd ?
 
;-----------------
; Out-of-band data
t_oobflags dd ?
t_iobc dd ?
t_softerror dd ?
 
 
;---------
; RFC 1323 ; the order of next 4 elements may not change
 
SND_SCALE db ?
RCV_SCALE db ?
requested_s_scale db ?
request_r_scale db ?
 
ts_recent dd ? ; a copy of the most-recent valid timestamp from the other end
ts_recent_age dd ?
last_ack_sent dd ?
 
 
;-------
; Timers
timer_retransmission dd ? ; rexmt
timer_persist dd ?
timer_keepalive dd ? ; keepalive/syn timeout
timer_timed_wait dd ? ; also used as 2msl timer
 
; extra
 
ts_ecr dd ? ; timestamp echo reply
ts_val dd ?
temp_bits db ?
 
ends
 
struct UDP_SOCKET IP_SOCKET
 
LocalPort dw ? ; network byte order
RemotePort dw ? ; network byte order
firstpacket db ?
 
ends
 
 
struct ICMP_SOCKET IP_SOCKET
 
Identifier dw ?
 
ends
 
 
struct RING_BUFFER
 
start_ptr dd ? ; Pointer to start of buffer
end_ptr dd ? ; pointer to end of buffer
read_ptr dd ? ; Read pointer
write_ptr dd ? ; Write pointer
size dd ? ; Number of bytes buffered
 
ends
 
struct STREAM_SOCKET TCP_SOCKET
 
rcv RING_BUFFER
snd RING_BUFFER
 
ends
/kernel/branches/net/applications/socketdbg/socketdbg.asm
0,0 → 1,100
format binary as ""
 
use32
; standard header
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem ; required memory
dd mem ; stack pointer
dd 0 ; parameters
dd 0 ; path
 
; useful includes
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
 
include '../struct.inc'
 
include 'socket.inc'
 
; entry point
start:
mcall 40, 0 ; we dont want any events
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
; initialize console
push 1
call [con_start]
push title
push -1
push -1
push -1
push -1
call [con_init]
; main loop
main:
mcall 75, 255, 0, socket_list ; get current socket list
 
call [con_cls]
 
mov esi, socket_list
.loop:
lodsd
test eax, eax
jz .done
 
mov ecx, eax
mcall 75, 255, , socket_buf
 
pushd [socket_buf + SOCKET.state]
pushd [socket_buf + SOCKET.PID]
pushd [socket_buf + SOCKET.Number]
push str_sock
call [con_printf]
add esp, 4
 
jmp .loop
 
.done:
 
mcall 23, 50
 
jmp main
 
 
push 0
call [con_exit]
exit:
mcall -1
 
; data
title db 'Socket debugger', 0
 
str_sock db 'Socket=%d PID=%d state=%d', 10, 0
 
; import
align 4
@IMPORT:
 
library console, 'console.obj'
 
import console, \
con_start, 'START', \
con_init, 'con_init', \
con_cls, 'con_cls', \
con_exit, 'con_exit', \
con_printf, 'con_printf'
i_end:
 
socket_list rd 4096
socket_buf rd 4096
 
align 4
rb 4096 ; stack
mem:
/kernel/branches/net/applications/ftpd/commands.inc
0,0 → 1,1135
 
 
struct thread_data
rb 1024
stack rb 0
 
home_dir rb 1024 ; home directory in wich the user is locked, asciiz
work_dir rb 1024 ; working directory, must at all times begin and end with a '/', asciiz
fpath rb 1024*3 ; file path, combination of home_dir, work_dir and filename
; Will also be used to temporarily store username
 
type db ? ; ASCII/EBDIC/IMAGE/..
mode db ? ; active/passive
socketnum dd ? ; Commands socket
state dd ? ; disconnected/logging in/logged in/..
passivesocknum dd ? ; when in passive mode, this is the listening socket
datasocketnum dd ? ; socket used for data transfers
permissions dd ? ; read/write/execute/....
buffer_ptr dd ?
pid dd ? ; Process id of the current thread
 
datasock sockaddr_in
 
buffer rb BUFFERSIZE
ends
 
;------------------------------------------------
; parse_cmd
;
; Internal function wich uses the 'commands'
; table to call an appropriate cmd_xx function.
;
; input: esi = ptr to ascii commands
; ecx = number of bytes input
; ebp = pointer to thread_data structure
;
; output: none
;
;------------------------------------------------
align 4
parse_cmd: ; esi must point to command
 
cmp byte [esi], 0x20 ; skip all leading characters
ja .ok
inc esi
dec ecx
cmp ecx, 3
jb .error
jmp parse_cmd
.ok:
cmp byte [esi+3], 0x20
ja @f
mov byte [esi+3], 0
@@:
 
mov eax, [esi]
and eax, not 0x20202020 ; convert to upper case
mov edi, commands ; list of commands to scan
.scanloop:
cmp eax, [edi]
je .got_it
 
add edi, 5*4
cmp byte [edi], 0
jne .scanloop
 
.error:
cmp [ebp + thread_data.state], STATE_ACTIVE
jb login_first
sendFTP "500 Unsupported command"
ret
 
.got_it:
mov eax, [ebp + thread_data.state]
jmp dword [edi + 4 + eax]
 
 
align 4
iglobal
commands: ; all commands must be in uppercase
 
dd 'ABOR', login_first, login_first, login_first, cmdABOR
; dd 'ACCT', login_first, login_first, login_first, cmd_ACCT
; dd 'APPE', login_first, login_first, login_first, cmd_APPE
dd 'CDUP', login_first, login_first, login_first, cmdCDUP
dd 'CWD', login_first, login_first, login_first, cmdCWD
dd 'DELE', login_first, login_first, login_first, cmdDELE
; dd 'HELP', login_first, login_first, login_first, cmd_HELP
dd 'LIST', login_first, login_first, login_first, cmdLIST
; dd 'MDTM', login_first, login_first, login_first, cmd_MDTM
; dd 'MKD', login_first, login_first, login_first, cmd_MKD
; dd 'MODE', login_first, login_first, login_first, cmd_MODE
dd 'NLST', login_first, login_first, login_first, cmdNLST
dd 'NOOP', login_first, login_first, login_first, cmdNOOP
dd 'PASS', cmdPASS.0, cmdPASS , cmdPASS.2, cmdPASS.3
dd 'PASV', login_first, login_first, login_first, cmdPASV
dd 'PORT', login_first, login_first, login_first, cmdPORT
dd 'PWD', login_first, login_first, login_first, cmdPWD
dd 'QUIT', cmdQUIT, cmdQUIT, cmdQUIT, cmdQUIT
; dd 'REIN', login_first, login_first, login_first, cmd_REIN
; dd 'REST', login_first, login_first, login_first, cmd_REST
dd 'RETR', login_first, login_first, login_first, cmdRETR
; dd 'RMD', login_first, login_first, login_first, cmd_RMD
; dd 'RNFR', login_first, login_first, login_first, cmd_RNFR
; dd 'RNTO', login_first, login_first, login_first, cmd_RNTO
; dd 'SITE', login_first, login_first, login_first, cmd_SITE
; dd 'SIZE', login_first, login_first, login_first, cmd_SIZE
; dd 'STAT', login_first, login_first, login_first, cmd_STAT
dd 'STOR', login_first, login_first, login_first, cmdSTOR
; dd 'STOU', login_first, login_first, login_first, cmd_STOU
; dd 'STRU', login_first, login_first, login_first, cmd_STRU
dd 'SYST', login_first, login_first, login_first, cmdSYST
dd 'TYPE', login_first, login_first, login_first, cmdTYPE
dd 'USER', cmdUSER, cmdUSER, cmdUSER, cmdUSER.2
db 0 ; end marker
endg
 
align 4
login_first:
sendFTP "530 Please login with USER and PASS"
ret
 
align 4
permission_denied:
sendFTP "550 Permission denied"
ret
 
align 4
socketerror:
invoke con_set_flags, 0x0c
invoke con_write_asciiz, str_sockerr
invoke con_set_flags, 0x07
 
sendFTP "425 Can't open data connection"
ret
 
align 4
abort_transfer:
and [ebp + thread_data.permissions], not ABORT
mov [ebp + thread_data.mode], MODE_NOTREADY
invoke file.close, ebx
mcall close, [ebp + thread_data.datasocketnum]
 
sendFTP "530 Transfer aborted"
ret
 
align 4
ip_to_dword: ; esi = ptr to str, cl = separator ('.', ',')
 
call ascii_to_byte
mov bl, al
cmp byte [esi], cl
jne .err
inc esi
 
call ascii_to_byte
mov bh, al
cmp byte [esi], cl
jne .err
inc esi
 
shl ebx, 16
 
call ascii_to_byte
mov bl, al
cmp byte [esi], cl
jne .err
inc esi
 
call ascii_to_byte
mov bh, al
 
ror ebx, 16
ret
 
.err:
xor ebx, ebx
ret
 
align 4 ; esi = ptr to str, output in eax
ascii_to_byte:
 
xor eax, eax
push ebx
 
.loop:
movzx ebx, byte[esi]
sub bl, '0'
jb .done
cmp bl, 9
ja .done
lea eax, [eax*4 + eax] ;
shl eax, 1 ; eax = eax * 10
add eax, ebx
inc esi
 
jmp .loop
 
.done:
pop ebx
ret
 
align 4
dword_to_ascii: ; edi = ptr where to write, eax is number
 
push edx ebx ecx
mov ebx, 10
xor ecx, ecx
 
@@:
xor edx, edx
div ebx
add edx, '0'
pushw dx
inc ecx
test eax, eax
jnz @r
 
@@:
popw ax
stosb
dec ecx
jnz @r
 
pop ecx ebx edx
ret
 
align 4
create_path: ; combine home_dir and work_dir strings into fpath
 
lea edi, [ebp + thread_data.fpath]
lea esi, [ebp + thread_data.home_dir]
mov ecx, 1024
.loop1:
lodsb
cmp al, 0x20
jb .next
stosb
loop .loop1
.next:
 
cmp byte[edi-1], '/'
jne @f
dec edi
@@:
 
lea esi, [ebp + thread_data.work_dir]
mov ecx, 1024
.loop2:
lodsb
cmp al, 0x20
jb .done
stosb
loop .loop2
 
.done:
xor al, al
stosb
ret
 
 
align 4
nextpasvport:
 
inc [pasv_port]
 
mov ax, [pasv_port]
cmp ax, [pasv_start]
jb .restart
cmp ax, [pasv_end]
ja .restart
 
ret
 
.restart:
pushw [pasv_start]
popw [pasv_port]
 
ret
 
 
align 4
open_datasock:
 
cmp [ebp + thread_data.mode], MODE_PASSIVE_OK
je .start
 
; If we are in active mode, it's time to open a data socket..
cmp [ebp + thread_data.mode], MODE_ACTIVE
jne .not_active
mov ecx, [ebp + thread_data.datasocketnum]
lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock
mcall connect
cmp eax, -1
jne .start
 
.socketerror:
add esp, 4
jmp socketerror
 
; If we are still in passive_wait, it's time we accept an incomming call..
.not_active:
cmp [ebp + thread_data.mode], MODE_PASSIVE_WAIT
jne .socketerror
 
.try_now:
mov ecx, [ebp + thread_data.passivesocknum]
lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock
mcall accept
cmp eax, -1
jne .pasv_ok
mov [ebp + thread_data.mode], MODE_PASSIVE_FAILED ; assume that we will fail
mcall 23, 200
mcall accept
cmp eax, -1
je .socketerror
.pasv_ok:
mov [ebp + thread_data.datasocketnum], eax
mov [ebp + thread_data.mode], MODE_PASSIVE_OK
mcall close ; [ebp + thread_data.passivesocknum]
mov [ebp + thread_data.passivesocknum], -1
invoke con_write_asciiz, str_datasock
 
.start:
ret
 
 
;------------------------------------------------
; "ABOR"
;
; This command aborts the current filetransfer.
;
;------------------------------------------------
align 4
cmdABOR:
 
or [ebp + thread_data.permissions], ABORT
sendFTP "250 Command succesul"
ret
 
;------------------------------------------------
; "CDUP"
;
; Change the directory to move up one level.
;
;------------------------------------------------
align 4
cmdCDUP:
 
test [ebp + thread_data.permissions], PERMISSION_CD
jz permission_denied
 
cmp byte [ebp + thread_data.work_dir+1], 0 ; are we in "/" ?
je .done ; if so, we cant go up..
 
; find the end of asciiz string work_dir
mov ecx, 1024
xor al, al
lea edi, [ebp + thread_data.work_dir]
repne scasb
; return 2 characters (right before last /)
sub edi, 3
; and now search backwards, for a '/'
mov al,'/'
neg ecx
add ecx, 1024
std
repne scasb
cld
; terminate the string here
mov byte[edi+2], 0
 
.done:
; Print the new working dir on the console
lea eax, [ebp + thread_data.work_dir]
invoke con_write_asciiz, eax
invoke con_write_asciiz, str_newline
 
sendFTP "250 Command succesul"
ret
 
;------------------------------------------------
; "CWD"
;
; Change Working Directory.
;
;------------------------------------------------
align 4
cmdCWD:
 
test [ebp + thread_data.permissions], PERMISSION_CD
jz permission_denied
 
; do we have enough parameters?
sub ecx, 4
jbe .err
 
; get ready to copy the path
add esi, 4
mov ecx, 1024
lea edi, [ebp + thread_data.work_dir]
 
; if received dir starts with '/', we will simply copy it
; If not, we will append the current path with the received path.
cmp byte [esi], '/'
je .copyloop
 
; Find the end of work_dir string.
xor al, al
.find_zero:
repne scasb
dec edi
 
; and now append work_dir with received string
mov ecx, 1024
 
; scan for end byte, or '.'
.copyloop:
lodsb
cmp al, 0x20
jb .done
;;; cmp al, '.' ; '..' means we must go up one dir TODO
;;; je .up
stosb
loop .copyloop
 
; now, now make sure it ends with '/', 0
.done:
cmp byte [edi-1], '/'
je @f
mov byte [edi], '/'
inc edi
@@:
mov byte [edi], 0
 
; Print the new working dir on the console
lea eax, [ebp + thread_data.work_dir]
invoke con_write_asciiz, eax
invoke con_write_asciiz, str_newline
 
sendFTP "250 Command succesful"
ret
 
.err:
sendFTP "550 Directory does not exist"
ret
 
;------------------------------------------------
; "DELE"
;
; Delete a file from the server.
;
;------------------------------------------------
align 4
cmdDELE:
 
test [ebp + thread_data.permissions], PERMISSION_DELETE
jz permission_denied
 
ret
 
;------------------------------------------------
; "LIST"
;
; List the files in the current working directory.
;
;------------------------------------------------
align 4
cmdLIST:
 
test [ebp + thread_data.permissions], PERMISSION_EXEC
jz permission_denied
 
call open_datasock
 
; Create fpath from home_dir and work_dir
call create_path
 
lea ebx, [ebp + thread_data.fpath]
invoke con_write_asciiz, ebx
invoke con_write_asciiz, str_newline
 
; Start the search
invoke file.find.first, ebx, str_mask, FA_READONLY+FA_FOLDER+FA_ARCHIVED;+FA_NORMAL
test eax, eax
jz .nosuchdir
 
lea edi, [ebp + thread_data.buffer]
.parse_file:
test eax, eax ; did we find a file?
jz .done
mov ebx, eax ; yes, save the descripter in ebx
 
; first, convert the attributes
test [ebx + FileInfoA.Attributes], FA_FOLDER
jnz .folder
 
test [ebx + FileInfoA.Attributes], FA_READONLY
jnz .readonly
 
mov eax, '-rw-'
stosd
jmp .attr
 
.folder:
mov eax, 'drwx'
stosd
jmp .attr
 
.readonly:
mov eax, '-r--'
stosd
 
.attr:
mov eax, 'rw-r'
stosd
mov ax, 'w-'
stosw
mov al, ' '
stosb
 
; now..
mov ax, '1 '
stosw
 
; now write owner, everything is owned by FTP, woohoo!
mov eax, 'FTP '
stosd
stosd
 
; now the filesize in ascii
mov eax, [ebx + FileInfoA.FileSizeLow]
call dword_to_ascii
mov al, ' '
stosb
 
; then date (month/day/year)
movzx eax, [ebx + FileInfoA.DateModify + FileDateTime.month]
cmp eax, 12
ja @f
mov eax, [months - 4 + 4*eax]
stosd
@@:
 
movzx eax, [ebx + FileInfoA.DateModify + FileDateTime.day]
call dword_to_ascii
mov al, ' '
stosb
 
movzx eax, [ebx + FileInfoA.DateModify + FileDateTime.year]
call dword_to_ascii
mov al, ' '
stosb
 
; and last but not least, filename
lea esi, [ebx + FileInfoA.FileName]
mov ecx, 264
.nameloop:
lodsb
test al, al
jz .namedone
stosb
loop .nameloop
 
; insert a cr lf
.namedone:
mov ax, 0x0a0d
stosw
 
test [ebp + thread_data.permissions], ABORT ; Did we receive ABOR command from client?
jnz abort_transfer
 
; check next file
invoke file.find.next, ebx
jmp .parse_file
 
; close file desc
.done:
invoke file.find.close, ebx ; ebx is descriptor of last file, eax will be -1 !!
 
; append the string with a 0
xor al, al
stosb
 
; Warn the client we're about to send the data
push edi
sendFTP "150 Here it comes.."
pop esi
 
; and send it to the client
mov ecx, [ebp + thread_data.datasocketnum] ; socket num
lea edx, [ebp + thread_data.buffer] ; buffer ptr
sub esi, edx ; length
xor edi, edi ; flags
mcall send
 
; close the data socket..
mov [ebp + thread_data.mode], MODE_NOTREADY
mcall close, [ebp + thread_data.datasocketnum]
 
sendFTP "226 Transfer OK"
ret
 
.nosuchdir:
sendFTP "550 Directory does not exist"
ret
 
;------------------------------------------------
; "NLST"
;
; List the filenames of the files in the current working directory.
;
;------------------------------------------------
align 4
cmdNLST:
 
test [ebp + thread_data.permissions], PERMISSION_EXEC
jz permission_denied
 
; TODO: same as list but simpler output format
 
ret
 
;------------------------------------------------
; "NOOP"
;
; No operation, just keep the connection alive.
;
;------------------------------------------------
align 4
cmdNOOP:
 
sendFTP "200 Command OK"
ret
 
;------------------------------------------------
; "PASS"
;
; Second phase of login process, client provides password.
;
;------------------------------------------------
align 4
cmdPASS:
 
; read the password from users.ini
lea edi, [ebp + thread_data.buffer + 512] ; temp pass
lea ebx, [ebp + thread_data.fpath] ; temp username
invoke ini.get_str, path2, ebx, str_pass, edi, 512, str_infinity
test eax, eax ; unable to read password? fail!
jnz .incorrect
cmp dword [edi], -1 ; no key, section or file found.. fail!
je .incorrect
cmp byte [edi], 0 ; zero password? ok!
je .ok
 
add esi, 5
sub ecx, 5
jbe .incorrect ; no password given? but hey, we need one! fail..
 
; compare with received password
repe cmpsb
cmp byte [esi-1], 0x20 ; printeable characters left?
jae .incorrect
cmp byte [edi-1], 0
jne .incorrect
 
.ok:
invoke ini.get_int, path2, ebx, str_mode, 0
mov [ebp + thread_data.permissions], eax
 
invoke con_write_asciiz, str_pass_ok
mov [ebp + thread_data.state], STATE_ACTIVE
sendFTP "230 You are now logged in"
ret
 
.2:
.incorrect:
invoke con_write_asciiz, str_pass_err
mov [ebp + thread_data.state], STATE_CONNECTED ; reset state
sendFTP "530 Login incorrect"
ret
 
.0:
sendFTP "503 Login with USER first"
ret
 
.3:
sendFTP "230 Already logged in"
ret
 
;------------------------------------------------
; "PASV"
;
; Initiate a passive dataconnection.
;
;------------------------------------------------
align 4
cmdPASV:
 
; cmp [ebp + thread_data.passivesocknum], -1
; je @f
; mcall close, [ebp + thread_data.passivesocknum] ; if there is still a socket open, close it
; @@:
 
; Open a new TCP socket
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
je socketerror
mov [ebp + thread_data.passivesocknum], eax
 
; Bind it to a known local port
mov [ebp + thread_data.datasock.sin_family], AF_INET4
mov [ebp + thread_data.datasock.sin_addr], 0
 
mov ecx, eax ; passivesocketnum
lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock
 
.next_port: ; TODO: break the endless loop
call nextpasvport
mov ax, [pasv_port]
xchg al, ah
mov [ebp + thread_data.datasock.sin_port], ax
 
mcall bind
cmp eax, -1
je .next_port
 
; And set it to listen!
mcall listen, , 1
cmp eax, -1
je socketerror
 
; Tell our thread we are ready to accept incoming calls
mov [ebp + thread_data.mode], MODE_PASSIVE_WAIT
 
; Now tell the client where to connect to in this format:
; 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
; where a1.a2.a3.a4 is the IP address and p1*256+p2 is the port number.
 
; '227 ('
lea edi, [ebp + thread_data.buffer]
mov eax, '227 '
stosd
mov al, '('
stosb
; ip
movzx eax, byte [serverip]
call dword_to_ascii
mov al, ','
stosb
movzx eax, byte [serverip+1]
call dword_to_ascii
mov al, ','
stosb
movzx eax, byte [serverip+2]
call dword_to_ascii
mov al, ','
stosb
movzx eax, byte [serverip+3]
call dword_to_ascii
mov al, ','
stosb
; port
movzx eax, byte [ebp + thread_data.datasock.sin_port]
call dword_to_ascii
mov al, ','
stosb
movzx eax, byte [ebp + thread_data.datasock.sin_port+1]
call dword_to_ascii
; ')', 13, 10, 0
mov eax, ')' + 0x000a0d00
stosd
 
lea esi, [edi - thread_data.buffer]
sub esi, ebp
mov ecx, [ebp + thread_data.socketnum]
lea edx, [ebp + thread_data.buffer]
xor edi, edi
mcall send
 
ret
 
;------------------------------------------------
; "PWD"
;
; Print the current working directory.
;
;------------------------------------------------
align 4
cmdPWD:
 
mov dword [ebp + thread_data.buffer], '257 '
mov byte [ebp + thread_data.buffer+4], '"'
 
lea edi, [ebp + thread_data.buffer+5]
lea esi, [ebp + thread_data.work_dir]
mov ecx, 1024
.loop:
lodsb
or al, al
jz .ok
stosb
dec ecx
jnz .loop
 
.ok:
mov dword [edi], '"' + 0x000a0d00 ; '"',13,10,0
lea esi, [edi - thread_data.buffer + 4]
sub esi, ebp
mov ecx, [ebp + thread_data.socketnum]
lea edx, [ebp + thread_data.buffer]
xor edi, edi
mcall send
 
; Print the new working dir on the console
lea eax, [ebp + thread_data.work_dir]
invoke con_write_asciiz, eax
invoke con_write_asciiz, str_newline
 
ret
 
;------------------------------------------------
; "PORT"
;
; Initiate an active dataconnection.
;
;------------------------------------------------
align 4
cmdPORT:
 
; PORT a1,a2,a3,a4,p1,p2
; IP address a1.a2.a3.a4, port p1*256+p2
 
; Convert the IP
lea esi, [esi+5]
mov cl, ','
call ip_to_dword
; And put it in datasock
mov [ebp + thread_data.datasock.sin_addr], ebx
 
; Now the same with portnumber
inc esi
call ascii_to_byte
mov byte[ebp + thread_data.datasock.sin_port], al
inc esi
call ascii_to_byte
mov byte[ebp + thread_data.datasock.sin_port+1], al
 
; We will open the socket, but do not connect yet!
mov [ebp + thread_data.datasock.sin_family], AF_INET4
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
je socketerror
 
mov [ebp + thread_data.datasocketnum], eax
mov [ebp + thread_data.mode], MODE_ACTIVE
 
sendFTP "225 Data connection open"
ret
 
;------------------------------------------------
; "QUIT"
;
; Close the connection with client.
;
;------------------------------------------------
align 4
cmdQUIT:
 
sendFTP "221 Bye!"
mcall close, [ebp + thread_data.datasocketnum]
mcall close, [ebp + thread_data.socketnum]
 
add esp, 4 ; get rid of call return address
jmp thread_exit ; now close this thread
 
 
;------------------------------------------------
; "RETR"
;
; Retrieve a file from the ftp server.
;
;------------------------------------------------
align 4
cmdRETR:
 
test [ebp + thread_data.permissions], PERMISSION_READ
jz permission_denied
 
cmp ecx, 1024 + 5
jae .cannot_open
 
sub ecx, 5
jb .cannot_open
 
call open_datasock
 
call create_path
dec edi
lea esi, [ebp + thread_data.buffer + 5]
mov ecx, 1024
cmp byte [esi], '/'
jne .loop
inc esi
.loop:
lodsb
cmp al, 0x20
jl .done
stosb
loop .loop
.done:
xor al, al
stosb
 
lea ebx, [ebp + thread_data.fpath]
invoke con_write_asciiz, ebx
invoke con_write_asciiz, str_newline
 
invoke file.open, ebx, O_READ
test eax, eax
jz .cannot_open
 
push eax
sendFTP "150 Here it comes.."
pop ebx
 
.read_more:
test [ebp + thread_data.permissions], ABORT
jnz abort_transfer
 
lea eax, [ebp + thread_data.buffer] ; FIXME: use another buffer!! if we receive something on control connection now, we screw up!
invoke file.read, ebx, eax, BUFFERSIZE
cmp eax, -1
je .cannot_open ; FIXME: this is not the correct error
 
invoke con_write_asciiz, str2
 
push eax ebx
mov esi, eax
mov ecx, [ebp + thread_data.datasocketnum]
lea edx, [ebp + thread_data.buffer]
xor edi, edi
mcall send
pop ebx ecx
cmp eax, -1
je socketerror ; FIXME: not the correct error
 
; cmp eax, ecx
; jne not_all_byes_sent ; TODO
 
cmp ecx, BUFFERSIZE
je .read_more
 
invoke file.close, ebx
 
invoke con_write_asciiz, str2b
 
mov [ebp + thread_data.mode], MODE_NOTREADY
mcall close, [ebp + thread_data.datasocketnum]
 
sendFTP "226 Transfer OK, closing connection"
ret
 
.cannot_open:
invoke con_set_flags, 0x0c
invoke con_write_asciiz, str_notfound
invoke con_set_flags, 0x07
 
sendFTP "550 No such file"
ret
 
 
 
;------------------------------------------------
; "STOR"
;
; Store a file on the server.
;
;------------------------------------------------
align 4
cmdSTOR:
 
test [ebp + thread_data.permissions], PERMISSION_WRITE
jz permission_denied
 
 
;;;;
test [ebp + thread_data.permissions], ABORT
jnz abort_transfer
 
;;;;
 
ret
 
;------------------------------------------------
; "SYST"
;
; Send information about the system.
;
;------------------------------------------------
align 4
cmdSYST:
 
sendFTP "215 UNIX type: L8"
ret
 
;------------------------------------------------
; "TYPE"
;
; Choose the file transfer type.
;
;------------------------------------------------
align 4
cmdTYPE:
 
cmp ecx, 6
jb parse_cmd.error
 
mov al, byte[esi+5]
and al, not 0x20
 
cmp al, 'A'
je .ascii
cmp al, 'E'
je .ebdic
cmp al, 'I'
je .image
cmp al, 'L'
je .local
 
jmp parse_cmd.error
 
.ascii:
mov [ebp + thread_data.type], TYPE_ASCII
jmp .subtype
 
.ebdic:
mov [ebp + thread_data.type], TYPE_EBDIC
 
.subtype:
cmp ecx, 8
jb .non_print
 
mov al, byte[esi+7]
and al, not 0x20
 
cmp al, 'N'
je .non_print
cmp al, 'T'
je .telnet
cmp al, 'C'
je .asacc
cmp al, 0x20
jb .non_print
 
jmp parse_cmd.error
 
.non_print:
or [ebp + thread_data.type], TYPE_NP
jmp .ok
 
.telnet:
or [ebp + thread_data.type], TYPE_TELNET
jmp .ok
 
.asacc:
or [ebp + thread_data.type], TYPE_ASA
jmp .ok
 
.image:
mov [ebp + thread_data.type], TYPE_IMAGE
jmp .ok
 
.local:
cmp ecx, 8
jb parse_cmd.error
 
mov al, byte[esi+7]
sub al, '0'
jb parse_cmd.error ; FIXME: this is not the correct errormessage
cmp al, 9
ja parse_cmd.error ; FIXME
or al, TYPE_LOCAL
mov [ebp + thread_data.type], al
 
.ok:
sendFTP "200 Command ok"
ret
 
;------------------------------------------------
; "USER"
;
; Login to the server, step one of two. ;;; TODO: prevent buffer overflow!
;
;------------------------------------------------
align 4
cmdUSER:
 
lea esi, [esi + 5]
lea edi, [ebp + thread_data.fpath] ; temp buffer for username
.loop:
lodsb
stosb
cmp al, 0x20
jae .loop
mov byte [edi-1], 0
 
lea esi, [ebp + thread_data.fpath]
lea eax, [ebp + thread_data.home_dir]
invoke ini.get_str, path2, esi, str_home, eax, 1024, str_infinity
cmp eax, -1
je .login_fail
cmp dword [esi], -1
je .login_fail
 
mov word [ebp + thread_data.work_dir], "/" ; "/", 0
 
invoke con_write_asciiz, str_logged_in
mov [ebp + thread_data.state], STATE_LOGIN
.sendstr:
sendFTP "331 Please specify the password"
ret
 
.login_fail:
invoke con_write_asciiz, str_pass_err
mov [ebp + thread_data.state], STATE_LOGIN_FAIL
jmp .sendstr
 
align 4
.2:
sendFTP "530 Can't change to another user"
ret
/kernel/branches/net/applications/ftpd/ftpd.asm
0,0 → 1,455
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ftpd.asm - FTP Daemon for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
DEBUG = 0 ; if set to one, program will run in a single thread
 
BUFFERSIZE = 8192
 
; using multiple's of 4
STATE_CONNECTED = 0*4
STATE_LOGIN = 1*4
STATE_LOGIN_FAIL = 2*4 ; When an invalid username was given
STATE_ACTIVE = 3*4
 
TYPE_UNDEF = 0
 
TYPE_ASCII = 00000100b
TYPE_EBDIC = 00001000b
; subtypes for ascii & ebdic (np = default)
TYPE_NP = 00000001b ; non printable
TYPE_TELNET = 00000010b
TYPE_ASA = 00000011b
 
TYPE_IMAGE = 01000000b ; binary data
TYPE_LOCAL = 10000000b ; bits per byte must be specified
; lower 4 bits will hold this value
MODE_NOTREADY = 0
MODE_ACTIVE = 1
MODE_PASSIVE_WAIT = 2
MODE_PASSIVE_OK = 3
MODE_PASSIVE_FAILED = 4
 
PERMISSION_EXEC = 1b ; LIST
PERMISSION_READ = 10b
PERMISSION_WRITE = 100b
PERMISSION_DELETE = 1000b
PERMISSION_CD = 10000b ; Change Directory
 
ABORT = 1 shl 31
 
format binary as ""
 
use32
 
org 0x0
 
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem+0x1000 ; required memory
dd mem+0x1000 ; stack pointer
dd params ; parameters
dd path ; path
 
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
include '../struct.inc'
include '../libio.inc'
 
include '../network.inc'
 
macro sendFTP str {
local string, length
xor edi, edi
mcall send, [ebp + thread_data.socketnum], string, length
 
iglobal
string db str, 13, 10
length = $ - string
\}
}
 
include 'commands.inc'
 
start:
mcall 68, 11 ; init heap
mcall 40, 1 shl 7 ; we only want network events
 
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
 
; find path to main settings file (ftpd.ini)
mov edi, path ; Calculate the length of zero-terminated string
xor al, al
mov ecx, 1024
repne scasb
dec edi
mov esi, str_ini ; append it with '.ini', 0
movsd
movsb
 
; now create the second path (users.ini)
std
mov al, '/'
repne scasb
lea ecx, [edi - path + 2]
cld
mov esi, path
mov edi, path2
rep movsb
mov esi, str_users
movsd
movsd
movsw
 
; initialize console
invoke con_start, 1
invoke con_init, -1, -1, -1, -1, title
 
; get settings from ini
invoke ini.get_str, path, str_ftpd, str_ip, ini_buf, 16, 0
mov esi, ini_buf
mov cl, '.'
call ip_to_dword
mov [serverip], ebx
 
invoke ini.get_int, path, str_ftpd, str_port, 21
xchg al, ah
mov [sockaddr1.port], ax
 
xchg al, ah
invoke con_printf, str1, eax
add esp, 8
 
; open listening socket
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
je sock_err
mov [socketnum], eax
 
invoke con_write_asciiz, str2
 
; mcall setsockopt, [socketnum], SOL_SOCKET, SO_REUSEADDR, &yes,
; cmp eax, -1
; je opt_err
 
mcall bind, [socketnum], sockaddr1, sockaddr1.length
cmp eax, -1
je bind_err
 
invoke con_write_asciiz, str2
 
invoke ini.get_int, path, str_ftpd, str_conn, 1 ; Backlog (max connections)
mov edx, eax
 
invoke con_write_asciiz, str2
 
mcall listen, [socketnum]
cmp eax, -1
je listen_err
 
invoke con_write_asciiz, str2b
 
invoke ini.get_int, path, str_pasv, str_start, 2000
mov [pasv_start], ax
invoke ini.get_int, path, str_pasv, str_end, 5000
mov [pasv_end], ax
 
mov [alive], 1
 
mainloop:
mcall 23, 100 ; Wait here for incoming connections on the base socket (socketnum)
; One second timeout, we will use this to check if console is still working
 
test eax, eax ; network event?
jz .checkconsole
 
if DEBUG
jmp threadstart
else
mcall 51, 1, threadstart, 0 ; Start a new thread for every incoming connection
; NOTE: upon initialisation of the thread, stack will not be available!
end if
jmp mainloop
 
.checkconsole:
 
invoke con_get_flags ; Is console still running?
test eax, 0x0200
jz mainloop
mcall close, [socketnum] ; kill the listening socket
mov [alive], 0
mcall -1 ; and exit
 
diff16 "threadstart", 0, $
 
threadstart:
;;; mcall 68, 11 ; init heap
mcall 68, 12, sizeof.thread_data ; allocate the thread data struct
test eax, eax
je exit
 
lea esp, [eax + thread_data.stack] ; init stack
mov ebp, eax
 
mcall 40, 1 shl 7 ; we only want network events for this thread
 
lea ebx, [ebp + thread_data.buffer] ; get information about the current process
or ecx, -1
mcall 9
mov eax, dword [ebp + thread_data.buffer + 30] ; PID is at offset 30
mov [ebp + thread_data.pid], eax
 
invoke con_set_flags, 0x03
invoke con_printf, str8, [ebp + thread_data.pid] ; print on the console that we have created the new thread successfully
add esp, 8 ; balance stack
invoke con_set_flags, 0x07
 
mcall accept, [socketnum], sockaddr1, sockaddr1.length ; time to accept the awaiting connection..
cmp eax, -1
je thread_exit
mov [ebp + thread_data.socketnum], eax
 
if DEBUG
mcall close, [socketnum] ; close the listening socket
end if
 
mov [ebp + thread_data.state], STATE_CONNECTED
mov [ebp + thread_data.permissions], 0
mov [ebp + thread_data.mode], MODE_NOTREADY
lea eax, [ebp + thread_data.buffer]
mov [ebp + thread_data.buffer_ptr], eax
mov [ebp + thread_data.passivesocknum], -1
 
sendFTP "220 Welcome to KolibriOS FTP daemon"
 
diff16 "threadloop", 0, $
threadloop:
; Check if our socket is still connected
mcall send, [ebp + thread_data.socketnum], 0, 0 ; Try to send zero bytes, if socket is closed, this will return -1
cmp eax, -1
je thread_exit
 
cmp [alive], 0 ; Did main thread take a run for it?
je thread_exit
 
mcall 10 ; Wait for network event
 
cmp [ebp + thread_data.mode], MODE_PASSIVE_WAIT
jne .not_passive
mov ecx, [ebp + thread_data.passivesocknum]
lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock
mcall accept
cmp eax, -1
je .not_passive
mov [ebp + thread_data.datasocketnum], eax
mov [ebp + thread_data.mode], MODE_PASSIVE_OK
mcall close ; [ebp + thread_data.passivesocknum]
mov [ebp + thread_data.passivesocknum], -1
 
invoke con_write_asciiz, str_datasock
.not_passive:
 
mov ecx, [ebp + thread_data.socketnum]
mov edx, [ebp + thread_data.buffer_ptr]
mov esi, sizeof.thread_data.buffer ;;; FIXME
mcall recv
inc eax ; error? (-1)
jz threadloop
dec eax ; 0 bytes read?
jz threadloop
 
mov edi, [ebp + thread_data.buffer_ptr]
add [ebp + thread_data.buffer_ptr], eax
 
; Check if we received a newline character, if not, wait for more data
mov ecx, eax
mov al, 13
repne scasb
jne threadloop
 
; We got a command!
mov byte [edi + 1], 0 ; append string with zero byte
lea esi, [ebp + thread_data.buffer]
mov ecx, [ebp + thread_data.buffer_ptr]
sub ecx, esi
mov [ebp + thread_data.buffer_ptr], esi ; reset buffer ptr
 
invoke con_set_flags, 0x02 ; print received data to console (in green color)
invoke con_write_asciiz, str_newline
invoke con_write_asciiz, esi
invoke con_set_flags, 0x07
 
push threadloop
jmp parse_cmd
 
listen_err:
invoke con_set_flags, 0x0c ; print errors in red
invoke con_write_asciiz, str3
jmp done
 
bind_err:
invoke con_set_flags, 0x0c ; print errors in red
invoke con_write_asciiz, str4
jmp done
 
sock_err:
invoke con_set_flags, 0x0c ; print errors in red
invoke con_write_asciiz, str6
jmp done
 
done:
invoke con_exit, 0
exit:
mcall -1
 
 
thread_exit:
invoke con_set_flags, 0x03 ; print thread info in blue
invoke con_printf, str_bye, [ebp + thread_data.pid] ; print on the console that we are about to kill the thread
add esp, 8 ; balance stack
mcall 68, 13, ebp ; free the memory
mcall -1 ; and kill the thread
 
 
; initialized data
 
title db 'KolibriOS FTP daemon 0.1', 0
str1 db 'Starting FTP daemon on port %u.', 0
str2 db '.', 0
str2b db ' OK!',10,0
str3 db 'Listen error',10,0
str4 db 10,'ERROR: local port is already in use.',10,0
;str5 db 'Setsockopt error.',10,10,0
str6 db 'ERROR: Could not open socket.',10,0
str7 db 'Got data!',10,10,0
str8 db 10,'Thread %d created',10,0
str_bye db 10,'Thread %d killed',10,0
 
str_logged_in db 'Login ok',10,0
str_pass_ok db 'Password ok',10,0
str_pass_err db 'Password/Username incorrect',10,0
str_pwd db 'Current directory is "%s"\n',0
str_err2 db 'ERROR: cannot open the directory.',10,0
str_datasock db 'Passive data socket connected.',10,0
str_notfound db 'ERROR: file not found.',10,0
str_sockerr db 'ERROR: socket error.',10,0
 
str_newline db 10, 0
str_mask db '*', 0
str_infinity db 0xff, 0xff, 0xff, 0xff, 0
 
months dd 'Jan '
dd 'Feb '
dd 'Mar '
dd 'Apr '
dd 'May '
dd 'Jun '
dd 'Jul '
dd 'Aug '
dd 'Sep '
dd 'Oct '
dd 'Nov '
dd 'Dec '
 
str_users db 'users'
str_ini db '.ini', 0
str_port db 'port', 0
str_ftpd db 'ftpd', 0
str_conn db 'conn', 0
str_ip db 'ip', 0
str_pass db 'pass', 0
str_home db 'home', 0
str_mode db 'mode', 0
str_pasv db 'pasv', 0
str_start db 'start', 0
str_end db 'end', 0
 
 
sockaddr1:
dw AF_INET4
.port dw 0
.ip dd 0
rb 10
.length = $ - sockaddr1
 
; import
 
align 4
@IMPORT:
 
diff16 "import", 0, $
 
library console, 'console.obj',\
libini, 'libini.obj', \
libio, 'libio.obj'
 
import console,\
con_start, 'START',\
con_init, 'con_init',\
con_write_asciiz, 'con_write_asciiz',\
con_exit, 'con_exit',\
con_gets, 'con_gets',\
con_cls, 'con_cls',\
con_printf, 'con_printf',\
con_getch2, 'con_getch2',\
con_set_cursor_pos, 'con_set_cursor_pos',\
con_set_flags, 'con_set_flags',\
con_get_flags, 'con_get_flags'
 
import libini,\
ini.get_str, 'ini_get_str',\
ini.get_int, 'ini_get_int'
 
import libio,\
file.size, 'file_size',\
file.open, 'file_open',\
file.read, 'file_read',\
file.close, 'file_close',\
file.find.first, 'file_find_first',\
file.find.next, 'file_find_next',\
file.find.close, 'file_find_close'
 
 
IncludeIGlobals
 
 
i_end:
 
diff16 "i_end", 0, $
 
; uninitialised data
 
socketnum dd ?
path rb 1024
path2 rb 1024
params rb 1024
serverip dd ?
pasv_start dw ?
pasv_end dw ?
pasv_port dw ?
 
ini_buf rb 3*4+3+1
 
alive db ?
 
mem:
 
 
/kernel/branches/net/applications/ftpd/users.ini
0,0 → 1,20
; Access modes
;
; List = 1
; Read = 2
; Write = 4
; Delete = 8
; Change directory = 16
 
 
[anonymous]
; leavy pass empty to disable it
pass=
home=/rd/1/
mode=3
 
[test]
pass=1234
home=/rd/1/
mode=31
 
/kernel/branches/net/applications/ftpd/ftpd.ini
0,0 → 1,8
[ftpd]
port=21
conn=10
ip=127.0.0.1
 
[pasv]
start=2000
end=5000
/kernel/branches/net/applications/libraries/network/network.asm
0,0 → 1,1295
format MS COFF
 
public @EXPORT as 'EXPORTS'
 
include '../../struct.inc'
include '../../proc32.inc'
include '../../macros.inc'
purge section,mov,add,sub
 
include '../../network.inc'
 
section '.flat' code readable align 16
 
;;===========================================================================;;
lib_init: ;//////////////////////////////////////////////////////////////////;;
;;---------------------------------------------------------------------------;;
;? Library entry point (called after library load) ;;
;;---------------------------------------------------------------------------;;
;> eax = pointer to memory allocation routine ;;
;> ebx = pointer to memory freeing routine ;;
;> ecx = pointer to memory reallocation routine ;;
;> edx = pointer to library loading routine ;;
;;---------------------------------------------------------------------------;;
;< eax = 1 (fail) / 0 (ok) (library initialization result) ;;
;;===========================================================================;;
mov [mem.alloc], eax
mov [mem.free], ebx
mov [mem.realloc], ecx
mov [dll.load], edx
mov [DNSrequestID], 1
xor eax, eax
ret
 
;;===========================================================================;;
;; in_addr_t __stdcall inet_addr(__in const char* hostname); ;;
inet_addr: ;;
;;---------------------------------------------------------------------------;;
;? Convert the string from standard IPv4 dotted notation to integer IP addr. ;;
;;---------------------------------------------------------------------------;;
;> first parameter = host name ;;
;;---------------------------------------------------------------------------;;
;< eax = IP address on success / -1 on error ;;
;;===========================================================================;;
; 0. Save used registers for __stdcall.
push ebx esi edi
mov esi, [esp+16] ; esi = hostname
; 1. Check that only allowed symbols are present.
; (hex digits, possibly letters 'x'/'X' and up to 3 dots)
push esi
xor ecx, ecx
.calcdots_loop:
; loop for all characters in string
lodsb
; check for end of string
cmp al, 0
jz .calcdots_loop_done
; check for dot
cmp al, '.'
jz .dot
; check for digit
sub al, '0'
cmp al, 9
jbe .calcdots_loop
; check for hex letter
sub al, 'A' - '0' ; 'A'-'F' -> 0-5, 'a'-'f' -> 20h-25h
and al, not 20h
cmp al, 'F' - 'A'
jbe .calcdots_loop
; check for 'x'/'X'
cmp al, 'X' - 'A'
jz .calcdots_loop
jmp .fail.pop
.dot:
inc ecx
jmp .calcdots_loop
.calcdots_loop_done:
cmp ecx, 4
jae .fail.pop
; 2. The name can be valid dotted name; try to convert, checking limit
pop esi
xor edi, edi ; edi = address
push 0xFFFFFFFF
pop edx ; edx = mask for rest of address
; 2a. Convert name except for last group.
jecxz .ip_convert_2b
.ip_convert_2a:
push ecx
mov ecx, 0xFF ; limit for all groups except for last
call .get_number
pop ecx
jc .fail
cmp byte [esi-1], '.'
jnz .fail
shl edi, 8
shr edx, 8
add edi, eax
loop .ip_convert_2a
; 2b. Convert last group.
.ip_convert_2b:
mov ecx, edx
call .get_number
jc .fail
cmp byte [esi-1], 0
jnz .fail
@@:
shl edi, 8
shr edx, 8
jnz @b
add edi, eax
; 2c. Convert to network byte order.
bswap edi
; 3. Set return value, restore used registers and return.
xchg eax, edi
.ret:
pop edi esi ebx
ret 4
; 4. On error, return -1.
.fail.pop:
pop esi
.fail:
push -1
pop eax
jmp .ret
 
;;===========================================================================;;
;; Internal auxiliary function for IP parsing. ;;
.get_number: ;;
;;---------------------------------------------------------------------------;;
;? Converts string to number. ;;
;;---------------------------------------------------------------------------;;
;> esi -> string ;;
;> ecx = limit for number ;;
;;---------------------------------------------------------------------------;;
;< eax = number ;;
;< CF set on error (too big number) / cleared on success ;;
;< esi -> end of number representation ;;
;;===========================================================================;;
; 0. Save edx, which is used in caller.
push edx
; 1. Initialize number, zero eax so that lodsb gets full dword.
xor eax, eax
xor edx, edx
; 2. Get used numeral system: 0x = hex, otherwise 0 = octal, otherwise decimal
push 10
pop ebx
lodsb
cmp al, '0'
jnz .convert
push 8
pop ebx
lodsb
cmp al, 'x'
jnz .convert
add ebx, ebx
; 3. Loop while digits are encountered.
.convert:
; 4. Convert digit from text representation to binary value.
or al, 20h ; '0'-'9' -> '0'-'9', 'A'-'F' -> 'a'-'f'
sub al, '0'
cmp al, 9
jbe .digit
sub al, 'a' - '0'
cmp al, 'f' - 'a'
ja .convert_done
add al, 10
.digit:
; 5. Digit must be less than base of numeral system.
cmp eax, ebx
jae .convert_done
; 6. Advance the number.
imul edx, ebx
add edx, eax
cmp edx, ecx
ja .gn_error
; 3b. Continue loop.
lodsb
jmp .convert
.convert_done:
; 7. Invalid character, number converted, return success.
xchg eax, edx
pop edx
clc
ret
.gn_error:
; 8. Too big number, return error.
pop edx
stc
ret
 
;;===========================================================================;;
;; char* __stdcall inet_ntoa(struct in_addr in); ;;
inet_ntoa: ;;
;;---------------------------------------------------------------------------;;
;? Convert the Internet host address to standard IPv4 dotted notation. ;;
;;---------------------------------------------------------------------------;;
;> first parameter = host address ;;
;;---------------------------------------------------------------------------;;
;< eax = pointer to resulting string (in static buffer) ;;
;;===========================================================================;;
; 0. Save used registers for __stdcall.
push ebx esi edi
mov bl, 0xCD ; constant for div 10
; 1. Write octet 4 times.
mov edi, .buffer
mov edx, [esp+16] ; eax = in
mov al, dl
call .write
mov al, dh
shr edx, 16
call .write
mov al, dl
call .write
mov al, dh
call .write
; 2. Replace final dot with terminating zero.
mov byte [edi-1], 0
; 3. Restore used registers, set result value and return.
pop edi esi ebx
mov eax, .buffer
ret 4
 
.write:
movzx esi, al
mul bl
add esi, ('.' shl 8) + '0'
shr ah, 3 ; ah = al / 10
movzx ecx, ah
add ecx, ecx
lea ecx, [ecx*5]
sub esi, ecx ; lobyte(esi) = al % 10, hibyte(esi) = '.'
test ah, ah
jz .1digit
cmp ah, 10
jb .2digit
cmp ah, 20
sbb cl, cl
add cl, '2'
mov byte [edi], cl
movzx ecx, cl
lea ecx, [ecx*5]
sub ah, cl
sub ah, cl
add ah, ('0'*11) and 255
mov byte [edi+1], ah
mov word [edi+2], si
add edi, 4
ret
.2digit:
add ah, '0'
mov byte [edi], ah
mov word [edi+1], si
add edi, 3
ret
.1digit:
mov word [edi], si
add edi, 2
ret
 
struct __gai_reqdata
socketnum dd ?
; external code should not look on rest of this structure,
; it is internal for getaddrinfo_start/process/abort
reqid dw ? ; DNS request ID
socktype db ? ; SOCK_* or 0 for any
db ?
service dd ?
flags dd ?
reserved rb 16
ends
 
;;===========================================================================;;
;; int __stdcall getaddrinfo(__in const char* hostname, ;;
;; __in const char* servname, ;;
;; __in const struct addrinfo* hints, ;;
;; __out struct addrinfo **res); ;;
getaddrinfo: ;;
;;---------------------------------------------------------------------------;;
;? Get a list of IP addresses and port numbers for given host and service ;;
;;---------------------------------------------------------------------------;;
;> first parameter (optional) = host name ;;
;> second parameter (optional) = service name (decimal number for now) ;;
;> third parameter (optional) = hints for socketnum type ;;
;> fourth parameter = pointer to result (head of L1-list) ;;
;;---------------------------------------------------------------------------;;
;< eax = 0 on success / one of EAI_ codes on error ;;
;;===========================================================================;;
; 0. Save used registers for __stdcall.
push ebx esi edi
mov edi, [esp+28] ; edi = res
; 1. Create and send DNS packet.
sub esp, sizeof.__gai_reqdata ; reserve stack place (1)
push esp ; fifth parameter = pointer to (1)
push edi ; fourth parameter = res
push dword [esp+32+sizeof.__gai_reqdata] ; third parameter = hints
push dword [esp+32+sizeof.__gai_reqdata] ; second parameter = servname
push dword [esp+32+sizeof.__gai_reqdata] ; first parameter = hostname
call getaddrinfo_start
test eax, eax
jns .ret ; if name resolved without network activity, return
; 2. Wait for DNS reply.
; 2a. Ignore all events except network stack.
mcall 40, EVM_STACK
push eax ; save previous event mask (2)
; 2b. Get upper limit for wait time. Use timeout = 5 seconds.
mcall 26, 9 ; get time stamp
xchg esi, eax ; save time stamp to esi
mov ebx, 500 ; start value for timeout
add esi, ebx
.wait:
; 2c. Wait for event with timeout.
mcall 23 ; wait for event - must be stack event
; 2d. Check for timeout.
test eax, eax
lea eax, [esp+4] ; pointer to (1)
jz .timeout
; 3. Got packet. Call processing function.
push edi ; second parameter: pointer to result
push eax ; first parameter: pointer to reqdata
call getaddrinfo_process
; 4. Test whether wait loop must be continued.
test eax, eax
jns .ret.restore
; 2e. Recalculate timeout value.
mcall 26, 9
mov ebx, esi
sub ebx, eax
; 2f. Check that time is not over; if not, continue wait loop
cmp ebx, 500
jbe .wait
.timeout:
; 5. Timeout: abort and return error
push eax
call getaddrinfo_abort
and dword [edi], 0
push EAI_AGAIN
pop eax
.ret.restore:
; 6. Restore event mask.
pop ebx ; get event mask (2)
push eax ; save return code (3)
mcall 40
pop eax ; restore return code (3)
.ret:
; 7. Restore stack pointer, used registers and return.
add esp, sizeof.__gai_reqdata ; undo (1)
pop edi esi ebx
ret 16
 
;;===========================================================================;;
;; int __stdcall getaddrinfo_start(__in const char* hostname, ;;
;; __in const char* servname, ;;
;; __in const struct addrinfo* hints, ;;
;; __out struct addrinfo **res, ;;
;; __out struct __gai_reqdata* reqdata); ;;
getaddrinfo_start: ;;
;;---------------------------------------------------------------------------;;
;? Initiator for getaddrinfo, sends DNS request ;;
;;---------------------------------------------------------------------------;;
;> first 4 parameters same as for getaddrinfo ;;
;> last parameter = pointer to buffer for __gai_reqdata, must be passed to ;;
;> getaddrinfo_process as is ;;
;;---------------------------------------------------------------------------;;
;< eax = <0 if wait loop must be entered / 0 on success / EAI_* on error ;;
;;===========================================================================;;
;; Known limitations: ;;
;; 1. No support for TCP connections => ;;
;; 1a. Long replies will be truncated, and not all IP addresses will be got. ;;
;; 2. No support for iterative resolving => ;;
;; 2a. In theory may fail with some servers. ;;
;; 3. Assumes that domain for relative names is always root, ".". ;;
;; 4. Does not support lookup of services by name, ;;
;; only decimal representation is supported. ;;
;; 5. Assumes that IPv4 is always configured, so AI_ADDRCONFIG has no effect.;;
;;===========================================================================;;
; 0. Create stack frame and save used registers for __stdcall.
push ebx esi edi
push ebp
mov ebp, esp
virtual at ebp-8
.recent_restsize dd ? ; this is for memory alloc in ._.generate_data
.recent_page dd ? ; this is for memory alloc in ._.generate_data
rd 5 ; saved regs and return address
.hostname dd ?
.servname dd ?
.hints dd ?
.res dd ?
.reqdata dd ?
end virtual
xor edi, edi
push edi ; init .recent_page
push edi ; init .recent_restsize
; 1. Check that parameters are correct and can be handled by this implementation.
; 1a. If 'res' pointer is given, set result to zero.
mov eax, [.res]
test eax, eax
jz @f
mov [eax], edi
@@:
; 1b. Only AI_SUPPORTED flags are supported for hints->ai_flags.
mov ecx, [.hints]
xor edx, edx
jecxz .nohints
mov edx, [ecx+addrinfo.ai_flags]
.nohints:
mov ebx, [.reqdata]
mov [ebx+__gai_reqdata.flags], edx
push EAI_BADFLAGS
pop eax
test edx, not AI_SUPPORTED
jnz .ret
; 1c. Either hostname or servname must be given. If AI_CANONNAME is set,
; hostname must also be set.
cmp [.hostname], edi
jnz @f
test dl, AI_CANONNAME
jnz .ret
push EAI_NONAME
pop eax
cmp [.servname], edi
jz .ret
@@:
; 1d. Only IPv4 is supported, so hints->ai_family must be either PF_UNSPEC or PF_INET.
push EAI_FAMILY
pop eax
jecxz @f
cmp [ecx+addrinfo.ai_family], edi
jz @f
cmp [ecx+addrinfo.ai_family], AF_INET4
jnz .ret
@@:
; 1e. Valid combinations for ai_socktype/ai_protocol: 0/0 for any or
; SOCK_STREAM/IPPROTO_TCP, SOCK_DGRAM/IPPROTO_UDP
; (raw socketnums are not yet supported by the kernel)
xor edx, edx ; assume 0=any if no hints
jecxz .socketnum_type_ok
mov edx, [ecx+addrinfo.ai_socktype]
mov esi, [ecx+addrinfo.ai_protocol]
; 1f. Test for ai_socktype=0 and ai_protocol=0.
test edx, edx
jnz .check_socktype
test esi, esi
jz .socketnum_type_ok
; 1g. ai_socktype=0, ai_protocol is nonzero.
push EAI_SERVICE
pop eax
inc edx ; edx = SOCK_STREAM
cmp esi, IPPROTO_TCP
jz .socketnum_type_ok
inc edx ; edx = SOCK_DGRAM
cmp esi, IPPROTO_UDP
jz .socketnum_type_ok
.ret:
; Restore saved registers, destroy stack frame and return.
mov esp, ebp
pop ebp
pop edi esi ebx
ret 20
; 1h. ai_socktype is nonzero.
.check_socktype:
push EAI_SOCKTYPE
pop eax
cmp edx, SOCK_STREAM
jz .check_tcp
cmp edx, SOCK_DGRAM
jnz .ret
test esi, esi
jz .socketnum_type_ok
cmp esi, IPPROTO_UDP
jz .socketnum_type_ok
jmp .ret
.check_tcp:
test esi, esi
jz .socketnum_type_ok
cmp esi, IPPROTO_TCP
jnz .ret
.socketnum_type_ok:
mov [ebx+__gai_reqdata.socktype], dl
; 2. Resolve service.
; 2a. If no name is given, remember value -1.
push -1
pop edx
mov esi, [.servname]
test esi, esi
jz .service_resolved
; 2b. Loop for characters of string while digits are encountered.
xor edx, edx
xor eax, eax
.serv_to_number:
lodsb
sub al, '0'
cmp al, 9
ja .serv_to_number_done
; for each digit, set edx = edx*10 + <digit>
lea edx, [edx*5]
lea edx, [edx*2+eax]
; check for correctness: service port must fit in word
cmp edx, 0x10000
jae .service_not_number
jmp .serv_to_number
.serv_to_number_done:
and edx, 0xFFFF ; make sure that port fits
; 2c. If zero character reached, name is resolved;
; otherwise, return error (no support for symbolic names yet)
cmp al, -'0'
jz .service_resolved
.service_not_number:
push EAI_NONAME
pop eax
jmp .ret
.service_resolved:
; 2d. Save result to reqdata.
mov [ebx+__gai_reqdata.service], edx
; 3. Process host name.
mov esi, [.hostname]
; 3a. If hostname is not given,
; use localhost for active socketnums and INADDR_ANY for passive socketnums.
mov eax, 0x0100007F ; 127.0.0.1 in network byte order
test byte [ebx+__gai_reqdata.flags], AI_PASSIVE
jz @f
xor eax, eax
@@:
test esi, esi
jz .hostname_is_ip
; 3b. Check for dotted IPv4 name.
push esi
call inet_addr
cmp eax, -1
jz .resolve_hostname
.hostname_is_ip:
; 3c. hostname is valid representation of IP address, and we have resolved it.
; Generate result, if .res pointer is not NULL.
mov ebx, [.reqdata]
mov esi, [.res]
test esi, esi
jz .no_result
call getaddrinfo._.generate_data
; 3d. Check for memory allocation error.
.3d:
push EAI_MEMORY
pop eax
test esi, esi
jz .ret
; 3e. If AI_CANONNAME is set, copy input name.
test byte [ebx+__gai_reqdata.flags], AI_CANONNAME
jz .no_result
; 3f. Calculate length of name.
push -1
pop ecx
mov edi, [.hostname]
xor eax, eax
repnz scasb
not ecx
; 3g. Check whether it fits on one page with main data.
cmp ecx, [.recent_restsize]
jbe .name_fits
; 3h. If not, allocate new page.
push ecx
add ecx, 4 ; first dword contains number of objects on the page
mcall 68, 12
pop ecx
; 3i. If allocation has failed, free addrinfo and return error.
test eax, eax
jnz .name_allocated
push [.res]
call freeaddrinfo
push EAI_MEMORY
pop eax
jmp .ret
.name_allocated:
; 3j. Otherwise, set edi to allocated memory and continue to 3l.
xchg edi, eax ; put result to edi
push 1
pop eax
stosd ; number of objects on the page = 1
jmp .copy_name
.name_fits:
; 3k. Get pointer to free memory in allocated page.
mov edi, [.recent_page]
mov eax, edi
and eax, not 0xFFF
inc dword [eax] ; increase number of objects
.copy_name:
; 3l. Put pointer to struct addrinfo.
mov eax, [.res]
mov eax, [eax]
mov [eax+addrinfo.ai_canonname], edi
; 3m. Copy name.
rep movsb
.no_result:
; 3n. Return success.
xor eax, eax
jmp .ret
; 4. Host address is not dotted IP. Test whether we are allowed to contact DNS.
; Return error if no.
.resolve_hostname:
push EAI_NONAME
pop eax
mov ebx, [.reqdata]
test byte [ebx+__gai_reqdata.flags], AI_NUMERICHOST
jnz .ret
; Host address is domain name. Contact DNS server.
mov esi, [.hostname]
; 5. Reserve stack place for UDP packet.
; According to RFC1035, maximum UDP packet size in DNS is 512 bytes.
sub esp, 512
; 6. Create DNS request packet.
; 6a. Set pointer to start of buffer.
mov edi, esp
; 6b. Get request ID, write it to buffer.
push 1
pop eax
lock xadd [DNSrequestID], eax ; atomically increment ID, get old value
stosw
mov [ebx+__gai_reqdata.reqid], ax
; 6c. Packed field: QR=0 (query), Opcode=0000 (standard query),
; AA=0 (ignored in requests), TC=0 (no truncation),
; RD=1 (recursion desired)
mov al, 00000001b
stosb
; 6d. Packed field: ignored in requests
mov al, 0
stosb
; 6e. Write questions count = 1 and answers count = 0
; Note that network byte order is big-endian.
mov eax, 0x00000100
stosd
; 6f. Write nameservers count = 0 and additional records count = 0
xor eax, eax
stosd
; 6g. Write request data: name
; According to RFC1035, maximum length of name is 255 bytes.
; For correct names, buffer cannot overflow.
lea ebx, [esi+256] ; ebx = limit for name (including terminating zero)
; translate string "www.yandex.ru" {00} to byte data {03} "www" {06} "yandex" {02} "ru" {00}
.nameloop: ; here we go in the start of each label: before "www", before "yandex", before "ru"
xor ecx, ecx ; ecx = length of current label
inc edi ; skip length, it will be filled later
.labelloop: ; here we go for each symbol of name
lodsb ; get next character
test al, al ; terminating zero?
jz .endname
cmp esi, ebx ; limit exceeded?
jae .wrongname
cmp al, '.' ; end of label?
jz .labelend
stosb ; put next character
inc ecx ; increment label length
jmp .labelloop
.wrongname:
push EAI_NONAME
pop eax
jmp .ret
.labelend:
test ecx, ecx ; null label can be only in the end of name
jz .wrongname
.endname:
cmp ecx, 63
ja .wrongname
; write length to byte [edi-ecx-1]
mov eax, ecx
neg eax
mov byte [edi+eax-1], cl
cmp byte [esi-1], 0 ; that was last label in the name?
jnz .nameloop
; write terminating zero if not yet
mov al, 0
cmp byte [edi-1], al
jz @f
stosb
@@:
; 6h. Write request data:
; query type = A (host address) = 1,
; query class = IN (internet IPv4 address) = 1
; Note that network byte order is big-endian.
mov eax, 0x01000100
stosd
; 7. Get DNS server address.
mcall 76, API_IPv4 + 4 ; protocol IP=0, device number=0, function=get DNS address
cmp eax, -1
je .ret.dnserr
mov esi, eax ; put server address to esi
; 8. Open UDP socketnum to DNS server, port 53.
; 8a. Create new socketnum.
mcall 75, 0, AF_INET4, SOCK_DGRAM
cmp eax, -1 ; error?
jz .ret.dnserr
mov ecx, eax ; put socketnum handle to ecx
; 8b. Create sockaddr structure on the stack.
push 0
push 0 ; sin_zero
push esi ; sin_addr
push AF_INET4 + (53 shl 24)
; sin_family and sin_port in network byte order
; 8c. Connect.
mcall 75, 4, , esp, sizeof.sockaddr_in
; 8d. Restore the stack, undo 8b.
add esp, esi
; 8e. Check result.
cmp eax, -1
jz .ret.close
; 9. Send DNS request packet.
sub edi, esp ; get packet length
mov esi, edi
xor edi, edi
mcall 75, 6, , esp
cmp eax, -1
jz .ret.close
mov eax, [.reqdata]
mov [eax+__gai_reqdata.socketnum], ecx
push -1
pop eax ; return status: more processing required
jmp .ret.dns
.ret.close:
mcall 75, 1
.ret.dnserr:
push EAI_AGAIN
pop eax
.ret.dns:
; 6. Restore stack pointer and return.
jmp .ret
 
;;===========================================================================;;
;; int __stdcall getaddrinfo_process(__in struct __gai_reqdata* reqdata, ;;
;; __out struct addrinfo** res); ;;
getaddrinfo_process: ;;
;;---------------------------------------------------------------------------;;
;? Processes network events from DNS reply ;;
;;---------------------------------------------------------------------------;;
;> first parameter = pointer to struct __gai_reqdata filled by ..._start ;;
;> second parameter = same as for getaddrinfo ;;
;;---------------------------------------------------------------------------;;
;< eax = -1 if more processing required / 0 on success / >0 = error code ;;
;;===========================================================================;;
; 0. Create stack frame.
push ebp
mov ebp, esp
virtual at ebp-.locals_size
.locals_start:
.datagram rb 512
.addrname dd ?
.name dd ?
.res_list_tail dd ?
.cname dd ?
.recent_restsize dd ? ; this is for memory alloc in ._.generate_data
.recent_page dd ? ; this is for memory alloc in ._.generate_data
.locals_size = $ - .locals_start
rd 2
.reqdata dd ?
.res dd ?
end virtual
xor eax, eax
push eax ; initialize .recent_page
push eax ; initialize .recent_restsize
push eax ; initialize .cname
push [.res] ; initialize .res_list_tail
sub esp, .locals_size-16 ; reserve place for other vars
mov edx, esp ; edx -> buffer for datagram
; 1. Save used registers for __stdcall.
push ebx esi edi
mov edi, [.reqdata]
; 2. Read UDP datagram.
mov ecx, [edi+__gai_reqdata.socketnum]
push edi
mcall 75, 7, , , 512, 0
pop edi
; 3. Ignore events for other socketnums (return if no data read)
test eax, eax
jz .ret.more_processing_required
; 4. Sanity check: discard too short packets.
xchg ecx, eax ; save packet length in ecx
cmp ecx, 12
jb .ret.more_processing_required
; 5. Discard packets with ID != request ID.
mov eax, dword [edi+__gai_reqdata.reqid]
cmp ax, [edx]
jnz .ret.more_processing_required
; 6. Sanity check: discard query packets.
test byte [edx+2], 80h
jz .ret.more_processing_required
; 7. Sanity check: must be exactly one query (our).
cmp word [edx+4], 0x0100 ; note network byte order
jnz .ret.more_processing_required
; 8. Check for errors. Return EAI_NONAME for error code 3 and EAI_FAIL for other.
mov al, [edx+3]
and al, 0xF
jz @f
cmp al, 3
jnz .ret.no_recovery
jmp .ret.no_name
@@:
; 9. Locate answers section. Exactly 1 query is present in this packet.
add ecx, edx ; ecx = limit
lea esi, [edx+12]
call .skip_name
lodsd ; skip QTYPE and QCLASS field
cmp esi, ecx
ja .ret.no_recovery
; 10. Loop through all answers.
movzx ebx, word [edx+6] ; get answers count
xchg bl, bh ; network -> Intel byte order
.answers_loop:
dec ebx
js .answers_done
; 10a. Process each record.
mov [.name], esi
; 10b. Skip name field.
call .skip_name
; 10c. Get record information, handle two types for class IN (internet).
lodsd ; get type and class
cmp esi, ecx
ja .ret.no_recovery
cmp eax, 0x01000500 ; type=5, class=1?
jz .got_cname
cmp eax, 0x01000100 ; type=1, class=1?
jnz .answers_loop.next
.got_addr:
; 10d. Process record A, host address.
add esi, 10
cmp esi, ecx
ja .ret.no_recovery
cmp word [esi-6], 0x0400 ; RDATA for A records must be 4 bytes long
jnz .ret.no_recovery
mov eax, [.name]
mov [.addrname], eax
; 10e. Create corresponding record in the answer.
push ebx ecx esi
mov eax, [esi-4] ; IP address
mov esi, [.res_list_tail] ; pointer to result
test esi, esi
jz .no_result ; do not save if .res is NULL
mov ebx, [.reqdata] ; request data
call getaddrinfo._.generate_data
mov [.res_list_tail], esi
pop esi ecx ebx
cmp [.res_list_tail], 0
jnz .answers_loop
; 10f. If generate_data failed (this means memory allocation failure), abort
jmp .ret.no_memory
.no_result:
pop esi ecx ebx
jmp .answers_loop
.got_cname:
; 10g. Process record CNAME, main host name.
lea eax, [esi+6]
mov [.cname], eax
.answers_loop.next:
; 10h. Skip other record fields, advance to next record.
lodsd ; skip TTL
xor eax, eax
lodsw ; get length of RDATA field
xchg al, ah ; network -> Intel byte order
add esi, eax
cmp esi, ecx
ja .ret.no_recovery
jmp .answers_loop
.answers_done:
; 11. Check that there is at least 1 answer.
mov eax, [.res_list_tail]
cmp [.res], eax
jz .ret.no_data
; 12. If canonical name was required, add it now.
mov eax, [.reqdata]
test byte [eax+__gai_reqdata.flags], AI_CANONNAME
jz .no_canon_name
; 12a. If at least one CNAME record is present, use name from last such record.
; Otherwise, use name from one of A records.
mov esi, [.cname]
test esi, esi
jnz .has_cname
mov esi, [.addrname]
.has_cname:
; 12b. Calculate name length.
call .get_name_length
jc .ret.no_recovery
; 12c. Check that the caller really want to get data.
cmp [.res], 0
jz .no_canon_name
; 12d. Allocate memory for name.
call getaddrinfo._.memalloc
test edi, edi
jz .ret.no_memory
; 12e. Make first entry in .res list point to canonical name.
mov eax, [.res]
mov eax, [eax]
mov [eax+addrinfo.ai_canonname], edi
; 12f. Decode name.
call .decode_name
.no_canon_name:
; 13. Set status to success.
xor eax, eax
jmp .ret.close
; Handle errors.
.ret.more_processing_required:
push -1
pop eax
jmp .ret
.ret.no_recovery:
push EAI_FAIL
pop eax
jmp .ret.destroy
.ret.no_memory:
push EAI_MEMORY
pop eax
jmp .ret.destroy
.ret.no_name:
.ret.no_data:
push EAI_NONAME
pop eax
.ret.destroy:
; 14. If an error occured, free memory acquired so far.
push eax
mov esi, [.res]
test esi, esi
jz @f
pushd [esi]
call freeaddrinfo
and dword [esi], 0
@@:
pop eax
.ret.close:
; 15. Close socketnum.
push eax
mov ecx, [.reqdata]
mov ecx, [ecx+__gai_reqdata.socketnum]
mcall 75, 1
pop eax
; 16. Restore used registers, destroy stack frame and return.
.ret:
pop edi esi ebx
mov esp, ebp
pop ebp
ret 8
 
;;===========================================================================;;
;; Internal auxiliary function for skipping names in DNS packet. ;;
.skip_name: ;;
;;---------------------------------------------------------------------------;;
;? Skips name in DNS packet. ;;
;;---------------------------------------------------------------------------;;
;> esi -> name ;;
;> ecx = end of packet ;;
;;---------------------------------------------------------------------------;;
;< esi -> end of name ;;
;;===========================================================================;;
xor eax, eax
cmp esi, ecx
jae .skip_name.done
lodsb
test al, al
jz .skip_name.done
test al, 0xC0
jnz .skip_name.pointer
add esi, eax
jmp .skip_name
.skip_name.pointer:
inc esi
.skip_name.done:
ret
 
;;===========================================================================;;
;; Internal auxiliary function for calculating length of name in DNS packet. ;;
.get_name_length: ;;
;;---------------------------------------------------------------------------;;
;? Calculate length of name (including terminating zero) in DNS packet. ;;
;;---------------------------------------------------------------------------;;
;> edx = start of packet ;;
;> esi -> name ;;
;> ecx = end of packet ;;
;;---------------------------------------------------------------------------;;
;< eax = length of name ;;
;< CF set on error / cleared on success ;;
;;===========================================================================;;
xor ebx, ebx ; ebx will hold data length
.get_name_length.zero:
xor eax, eax
.get_name_length.loop:
cmp esi, ecx
jae .get_name_length.fail
lodsb
test al, al
jz .get_name_length.done
test al, 0xC0
jnz .get_name_length.pointer
add esi, eax
inc ebx
add ebx, eax
cmp ebx, 256
jbe .get_name_length.loop
.get_name_length.fail:
stc
ret
.get_name_length.pointer:
and al, 0x3F
mov ah, al
lodsb
lea esi, [edx+eax]
jmp .get_name_length.zero
.get_name_length.done:
test ebx, ebx
jz .get_name_length.fail
xchg eax, ebx
clc
ret
 
;;===========================================================================;;
;; Internal auxiliary function for decoding DNS name. ;;
.decode_name: ;;
;;---------------------------------------------------------------------------;;
;? Decode name in DNS packet. ;;
;;---------------------------------------------------------------------------;;
;> edx = start of packet ;;
;> esi -> name in packet ;;
;> edi -> buffer for decoded name ;;
;;===========================================================================;;
xor eax, eax
lodsb
test al, al
jz .decode_name.done
test al, 0xC0
jnz .decode_name.pointer
mov ecx, eax
rep movsb
mov al, '.'
stosb
jmp .decode_name
.decode_name.pointer:
and al, 0x3F
mov ah, al
lodsb
lea esi, [edx+eax]
jmp .decode_name
.decode_name.done:
mov byte [edi-1], 0
ret
 
;;===========================================================================;;
;; Internal auxiliary function for allocating memory for getaddrinfo. ;;
getaddrinfo._.memalloc: ;;
;;---------------------------------------------------------------------------;;
;? Memory allocation. ;;
;;---------------------------------------------------------------------------;;
;> eax = size in bytes, must be less than page size. ;;
;> [ebp-4] = .recent_page = last allocated page ;;
;> [ebp-8] = .recent_restsize = bytes rest in last allocated page ;;
;;---------------------------------------------------------------------------;;
;< edi -> allocated memory / NULL on error ;;
;;===========================================================================;;
; 1. Set edi to result of function.
mov edi, [ebp-4]
; 2. Check whether we need to allocate a new page.
cmp eax, [ebp-8]
jbe .no_new_page
; 2. Allocate new page if need. Reset edi to new result.
push eax ebx
mcall 68, 12, 0x1000
xchg edi, eax ; put result to edi
pop ebx eax
; 3. Check returned value of allocator. Fail if it failed.
test edi, edi
jz .ret
; 4. Update .recent_page and .recent_restsize.
add edi, 4
sub ecx, 4
mov [ebp-4], edi
mov [ebp-8], ecx
.no_new_page:
; 5. Increase number of objects on this page.
push eax
mov eax, edi
and eax, not 0xFFF
inc dword [eax]
pop eax
; 6. Advance last allocated pointer, decrease memory size.
add [ebp-4], eax
sub [ebp-8], eax
; 7. Return.
.ret:
ret
 
;;===========================================================================;;
;; Internal auxiliary function for freeing memory for freeaddrinfo. ;;
getaddrinfo._.memfree: ;;
;;---------------------------------------------------------------------------;;
;? Free memory. ;;
;;---------------------------------------------------------------------------;;
;> eax = pointer ;;
;;===========================================================================;;
; 1. Get start of page.
mov ecx, eax
and ecx, not 0xFFF
; 2. Decrease number of objects.
dec dword [ecx]
; 3. If it goes to zero, free the page.
jnz @f
push ebx
mcall 68, 13
pop ebx
@@:
; 4. Done.
ret
 
;;===========================================================================;;
getaddrinfo._.generate_data: ;;
;;---------------------------------------------------------------------------;;
;? Generate item(s) of getaddrinfo result list by one IP address. ;;
;;---------------------------------------------------------------------------;;
;> eax = IP address ;;
;> ebx = request data ;;
;> esi = pointer to result ;;
;> [ebp-4] = .recent_page = last allocated page ;;
;> [ebp-8] = .recent_restsize = bytes rest in last allocated page ;;
;;---------------------------------------------------------------------------;;
;< esi = pointer to next list item for result / NULL on error ;;
;;===========================================================================;;
; 1. If no service is given, append one item with zero port.
; append one item with zero socktype/protocol/port.
cmp [ebx+__gai_reqdata.service], -1
jnz .has_service
call .append_item
; 1a. If neither protocol nor socktype were specified,
; leave zeroes in socktype and protocol.
mov cl, [ebx+__gai_reqdata.socktype]
test cl, cl
jz .no_socktype
; 1b. Otherwise, set socktype and protocol to desired.
call .set_socktype
.no_socktype:
ret
.has_service:
; 2. If TCP is allowed, append item for TCP.
cmp [ebx+__gai_reqdata.socktype], 0
jz .tcp_ok
cmp [ebx+__gai_reqdata.socktype], SOCK_STREAM
jnz .tcp_disallowed
.tcp_ok:
call .append_item
mov cl, SOCK_STREAM
call .set_socktype
call .set_port
.tcp_disallowed:
; 3. If UDP is allowed, append item for UDP.
cmp [ebx+__gai_reqdata.socktype], 0
jz .udp_ok
cmp [ebx+__gai_reqdata.socktype], SOCK_DGRAM
jnz .udp_disallowed
.udp_ok:
call .append_item
mov cl, SOCK_DGRAM
call .set_socktype
call .set_port
.udp_disallowed:
ret
 
.append_item:
; 1. Allocate memory for struct sockaddr_in and struct addrinfo.
push eax
push sizeof.addrinfo + sizeof.sockaddr_in
pop eax
call getaddrinfo._.memalloc
; 2. Check for memory allocation fail.
test edi, edi
jz .no_memory
; 3. Zero allocated memory.
push (sizeof.addrinfo + sizeof.sockaddr_in) / 4
pop ecx
xor eax, eax
push edi
rep stosd
pop edi
; 4. Fill struct addrinfo.
mov eax, [ebx+__gai_reqdata.flags]
mov [edi+addrinfo.ai_flags], eax
mov byte [edi+addrinfo.ai_family], AF_INET4
mov byte [edi+addrinfo.ai_addrlen], sizeof.sockaddr_in
lea ecx, [edi+sizeof.addrinfo]
mov [edi+addrinfo.ai_addr], ecx
; 5. Fill struct sockaddr_in.
mov byte [ecx+sockaddr_in.sin_family], AF_INET4
pop eax
mov [ecx+sockaddr_in.sin_addr], eax
; 6. Append new item to the list.
mov [esi], edi
lea esi, [edi+addrinfo.ai_next]
; 7. Return.
ret
.no_memory:
pop eax
xor esi, esi
ret
 
.set_socktype:
; Set ai_socktype and ai_protocol fields by given socketnum type.
mov byte [edi+addrinfo.ai_socktype], cl
dec cl
jnz .set_udp
.set_tcp:
mov byte [edi+addrinfo.ai_protocol], IPPROTO_TCP
ret
.set_udp:
mov byte [edi+addrinfo.ai_protocol], IPPROTO_UDP
ret
 
.set_port:
; Just copy port from input __gai_reqdata to output addrinfo.
push edx
mov edx, [ebx+__gai_reqdata.service]
xchg dl, dh ; convert to network byte order ;;;;; CHECKME
mov [edi+sizeof.addrinfo+sockaddr_in.sin_port], dx
pop edx
ret
 
;;===========================================================================;;
;; void __stdcall getaddrinfo_abort(__in struct __gai_reqdata* reqdata); ;;
getaddrinfo_abort: ;;
;;---------------------------------------------------------------------------;;
;? Abort process started by getaddrinfo_start, free all resources. ;;
;;---------------------------------------------------------------------------;;
;> first parameter = pointer to struct __gai_reqdata filled by ..._start ;;
;;===========================================================================;;
; 0. Save used registers for __stdcall.
push ebx
; 1. Allocated resources: only socketnum, so close it and return.
mov eax, [esp+8]
mov ecx, [eax+__gai_reqdata.socketnum]
mcall 75, 1
; 2. Restore used registers and return.
pop ebx
ret 4
 
;;===========================================================================;;
;; void __stdcall freeaddrinfo(__in struct addrinfo* ai); ;;
freeaddrinfo: ;;
;;---------------------------------------------------------------------------;;
;? Free one or more addrinfo structures returned by getaddrinfo. ;;
;;---------------------------------------------------------------------------;;
;> first parameter = head of list of structures ;;
; (may be arbitrary sublist of original) ;;
;;===========================================================================;;
; 1. Loop for all items in the list.
mov edx, [esp+4] ; eax = ai
.loop:
test edx, edx
jz .done
; 2. Free each item.
; 2a. Free ai_canonname, if allocated.
mov eax, [edx+addrinfo.ai_canonname]
test eax, eax
jz .no_canon_name
call getaddrinfo._.memfree
.no_canon_name:
; 2b. Remember next item
; (after freeing the field ai_next can became unavailable).
pushd [edx+addrinfo.ai_next]
; 2c. Free item itself.
xchg eax, edx
call getaddrinfo._.memfree
; 2d. Restore pointer to next item and continue loop.
pop edx
jmp .loop
.done:
; 3. Done.
ret 4
 
;;===========================================================================;;
;;///////////////////////////////////////////////////////////////////////////;;
;;===========================================================================;;
;! Exported functions section ;;
;;===========================================================================;;
;;///////////////////////////////////////////////////////////////////////////;;
;;===========================================================================;;
 
 
align 4
@EXPORT:
export \
lib_init , 'lib_init' , \
0x00010001 , 'version' , \
inet_addr , 'inet_addr' , \
inet_ntoa , 'inet_ntoa' , \
getaddrinfo , 'getaddrinfo' , \
getaddrinfo_start , 'getaddrinfo_start' , \
getaddrinfo_process , 'getaddrinfo_process' , \
getaddrinfo_abort , 'getaddrinfo_abort' , \
freeaddrinfo , 'freeaddrinfo'
 
section '.data' data readable writable align 16
; uninitialized data
mem.alloc dd ?
mem.free dd ?
mem.realloc dd ?
dll.load dd ?
 
DNSrequestID dd ?
 
inet_ntoa.buffer rb 16 ; static buffer for inet_ntoa
/kernel/branches/net/applications/synergyc/synergyc.asm
0,0 → 1,384
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Synergyc.asm - Synergy client for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format binary as ""
 
use32
org 0x0
 
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem+0x1000 ; required memory
dd mem+0x1000 ; stack pointer
dd 0 ; parameters
dd path ; path
 
__DEBUG__ equ 1 ; enable/disable
__DEBUG_LEVEL__ equ 1 ; 1 = all, 2 = errors
 
 
BUFFERSIZE equ 1024
DEFAULTPORT equ 24800
 
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
 
include '../network.inc'
 
start:
 
cld
mov edi, path ; Calculate the length of zero-terminated string
xor al, al
mov ecx, 1024
repne scasb
dec edi
mov esi, filename ; append the path with '.ini'
movsd
movsb
 
mcall 68, 11
 
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
 
push 1
call [con_start]
 
push title
push 25
push 80
push 25
push 80
call [con_init]
 
push path
call [con_write_asciiz]
 
push newline
call [con_write_asciiz]
 
push newline
call [con_write_asciiz]
 
invoke ini.get_str, path, str_remote, str_ip, buffer_ptr, 16, 0
test eax, eax
jnz error
 
invoke ini.get_int, path, str_remote, str_port, DEFAULTPORT
xchg al, ah
mov [sockaddr1.port], ax
 
push str1
call [con_write_asciiz]
 
push buffer_ptr
call [con_write_asciiz]
 
push newline
call [con_write_asciiz]
 
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
je error
 
mov [socketnum], eax
 
push buffer_ptr ; hostname
call [inet_addr]
cmp eax, -1
je error
mov [sockaddr1.ip], eax
 
mcall connect, [socketnum], sockaddr1, 18
 
push str7
call [con_write_asciiz]
 
mcall 40, 1 shl 7; + 7
 
login:
call wait_for_data
 
push buffer_ptr + 4
call [con_write_asciiz]
 
cmp dword [buffer_ptr], 11 shl 24
jne login
cmp dword [buffer_ptr + 4], 'Syne'
jne login
cmp word [buffer_ptr + 8], 'rg'
jne login
cmp byte [buffer_ptr + 10], 'y'
jne login
 
push str2
call [con_write_asciiz]
 
lea edi, [buffer_ptr + 11 + 4 + 4]
invoke ini.get_str, path, str_local, str_name, edi, 255, 0
xor al , al
mov ecx, 256
repne scasb
sub edi, buffer_ptr + 1 + 4
mov esi, edi
bswap edi
mov dword [buffer_ptr], edi
mov edi, esi
sub edi, 11 + 4
bswap edi
mov dword [buffer_ptr + 11 + 4], edi
add esi, 4
 
mcall send, [socketnum], buffer_ptr, , 0
 
mainloop:
call wait_for_data
mov edi, buffer_ptr
 
.command:
push eax edi
 
cmp dword [edi + 4], 'QINF' ; query screen info
je .qinf
 
cmp dword [edi + 4], 'CALV' ; alive ?
je .calv
 
cmp dword [edi + 4], 'CINN' ; mouse moved into screen
je .cinn
 
cmp dword [edi + 4], 'DCLP' ; Clipboard event
je .dclp
 
cmp dword [edi + 4], 'DMMV' ; Mouse moved
je .dmmv
 
cmp dword [edi + 4], 'COUT' ; leave screen
je .cout
 
cmp dword [edi + 4], 'DMDN' ; mouse button down
je .dmdn
 
cmp dword [edi + 4], 'DMUP' ; mouse button released
je .dmup
 
cmp dword [edi + 4], 'CNOP' ; no operation
je .next
 
cmp dword [edi + 4], 'CIAK' ; resolution changed?
je .ciak
 
push str3
call [con_write_asciiz]
 
mov byte[edi+8],0
add edi, 4
push edi
call [con_write_asciiz]
 
push newline
call [con_write_asciiz]
 
.next:
pop edi eax
 
mov ecx, dword [edi]
bswap ecx
add ecx, 4
sub eax, ecx
jle mainloop
add edi, ecx
jmp .command
 
 
.qinf:
mcall 14 ; get screen info
add eax, 0x00010001
bswap eax
mov dword [screeninfo.size], eax
mcall send, [socketnum], screeninfo, screeninfo.length, 0 ; send client name
jmp .next
 
 
.calv:
mcall send, [socketnum], calv, calv.length, 0 ; looks like ping-pong event
jmp .next
 
 
.cinn:
mov edx, [edi + 8]
bswap edx
mcall 18, 19, 4
; ignore sequence number and modify key mask for now
push str6
call [con_write_asciiz]
jmp .next
 
.dclp:
 
jmp .next
 
.dmmv:
mov edx, [edi + 8]
bswap edx
mcall 18, 19, 4
mcall send, [socketnum], cnop, cnop.length, 0 ; reply with NOP
push str4
call [con_write_asciiz]
jmp .next
 
.cout:
jmp .next
 
.dmdn:
movzx eax, byte [edi + 8]
or [mousestate], eax
mcall 18, 19, 5, [mousestate]
mcall send, [socketnum], cnop, cnop.length, 0 ; reply with NOP
push str5
call [con_write_asciiz]
jmp .next
 
.dmup:
movzx eax, byte [edi + 8]
not eax
and [mousestate], eax
mcall 18, 19, 5, [mousestate]
mcall send, [socketnum], cnop, cnop.length, 0 ; reply with NOP
push str5
call [con_write_asciiz]
jmp .next
 
.ciak:
jmp .next
 
error:
push str_err
call [con_write_asciiz]
 
call [con_gets]
 
push 1
call [con_exit]
 
mcall close, [socketnum]
exit:
 
mcall -1
 
 
wait_for_data:
mcall 10 ; wait for data
 
mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, 0
cmp eax, -1
je wait_for_data
 
cmp eax, 8
jl wait_for_data
 
ret
 
 
 
; data
title db 'Synergy client',0
str1 db 'Connecting to: ',0
str7 db 'Connected!',13,10,0
str2 db 13,10,'Handshake received',13,10,0
str3 db 'Unsupported command: ',0
newline db 13,10,0
str4 db 'mouse moved',13,10,0
str5 db 'mouse buttons changed',13,10,0
str6 db 'Enter screen',13,10,0
str_err db 'Error occured !',13,10,'Press any key to quit',0
 
screeninfo:
dd (screeninfo.length - 4) shl 24
db 'DINF'
dw 0 ; coordinate of leftmost pixel
dw 0 ; coordiante of topmost pixel
.size:
dw 0 ; width
dw 0 ; height
 
dw 0 ; size of warp zone
 
dw 0xb88b ; x position of the mouse on the secondary screen (no idea what it means)
dw 0xbcfb ; y position of the mouse on the secondary screen
.length = $ - screeninfo
 
calv:
dd (4) shl 24
db 'CALV'
.length = $ - calv + 8 ; also send cnop
 
cnop:
dd (4) shl 24
db 'CNOP'
.length = $ - cnop
 
mousestate dd 0
 
 
sockaddr1:
dw AF_INET4
.port dw 0
.ip dd 192 + 168 shl 8 + 1 shl 16 + 115 shl 24
rb 10
 
filename db '.ini', 0
str_local db 'local', 0
str_name db 'name', 0
str_remote db 'remote', 0
str_port db 'port', 0
str_ip db 'ip', 0
 
; import
align 16
@IMPORT:
 
library console, 'console.obj',\
network, 'network.obj',\
libini, 'libini.obj'
 
import network,\
inet_addr, 'inet_addr'
 
import console, \
con_start, 'START',\
con_init, 'con_init',\
con_write_asciiz, 'con_write_asciiz',\
con_exit, 'con_exit',\
con_gets, 'con_gets',\
con_cls, 'con_cls',\
con_getch2, 'con_getch2',\
con_set_cursor_pos, 'con_set_cursor_pos'
 
import libini,\
ini.get_str, 'ini_get_str',\
ini.get_int, 'ini_get_int'
 
align 4
i_end:
socketnum dd ?
buffer_ptr rb BUFFERSIZE
path rb 4096 ; stack
mem:
/kernel/branches/net/applications/synergyc/synergyc.ini
0,0 → 1,6
[local]
name = karaboeia
 
[remote]
ip = 192.168.1.115
port = 24800
/kernel/branches/net/applications/tcpserv/tcpserv.asm
0,0 → 1,168
format binary as ""
 
use32
; standard header
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem ; required memory
dd mem ; stack pointer
dd 0 ; parameters
dd 0 ; path
 
 
BUFFERSIZE equ 1500
; useful includes
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
 
include '../network.inc'
 
; entry point
start:
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
 
; initialize console
push 1
call [con_start]
push title
push 25
push 80
push 25
push 80
call [con_init]
 
mcall 40, 1 shl 7 ; we only want network events
 
push str1
call [con_write_asciiz]
 
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
je sock_err
 
mov [socketnum], eax
 
;; mcall setsockopt, [socketnum], SOL_SOCKET, SO_REUSEADDR, &yes,
;; cmp eax, -1
;; je opt_err
 
mcall bind, [socketnum], sockaddr1, sockaddr1.length
cmp eax, -1
je bind_err
 
mcall listen, [socketnum], 10 ; Backlog = 10
cmp eax, -1
je listen_err
 
push str2
call [con_write_asciiz]
 
mcall 10
 
mcall accept, [socketnum], sockaddr1, sockaddr1.length
cmp eax, -1
je acpt_err
 
mov [socketnum2], eax
 
;; mcall close, [socketnum]
 
mcall send, [socketnum2], hello, hello.length
 
.loop:
mcall 10
 
mcall recv, [socketnum2], buffer, buffer.length
cmp eax, -1
je .loop
 
mov byte [buffer + eax], 0
 
push buffer
call [con_write_asciiz]
 
jmp .loop
 
acpt_err:
push str8
call [con_write_asciiz]
jmp done
 
listen_err:
push str3
call [con_write_asciiz]
jmp done
 
bind_err:
push str4
call [con_write_asciiz]
jmp done
 
sock_err:
push str6
call [con_write_asciiz]
jmp done
 
done:
call [con_getch2]
push 1
call [con_exit]
exit:
mcall -1
 
 
 
; data
title db 'TCP stream server - test',0
str1 db 'Opening socket',10, 0
str2 db 'Listening for incoming connections...',10,0
str3 db 'Listen error',10,10,0
str4 db 'Bind error',10,10,0
str5 db 'Setsockopt error.',10,10,0
str6 db 'Could not open socket',10,10,0
str7 db 'Got data!',10,10,0
str8 db 'Error accepting connection',10,10,0
 
hello db 'Hello world!',0
.length = $ - hello
 
sockaddr1:
dw AF_INET4
.port dw 0x1700 ; 23
.ip dd 0
rb 10
.length = $ - sockaddr1
 
; import
align 4
@IMPORT:
 
library console, 'console.obj'
 
import console, \
con_start, 'START', \
con_init, 'con_init', \
con_write_asciiz, 'con_write_asciiz', \
con_exit, 'con_exit', \
con_gets, 'con_gets',\
con_cls, 'con_cls',\
con_printf, 'con_printf',\
con_getch2, 'con_getch2',\
con_set_cursor_pos, 'con_set_cursor_pos'
i_end:
 
socketnum dd ?
socketnum2 dd ?
buffer rb BUFFERSIZE
.length = BUFFERSIZE
 
align 4
rb 4096 ; stack
mem:
/kernel/branches/net/applications/telnet/telnet.asm
0,0 → 1,305
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; telnet.asm - Telnet client for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format binary as ""
 
__DEBUG__ equ 0
__DEBUG_LEVEL__ equ 1
BUFFERSIZE equ 4096
 
use32
; standard header
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem ; required memory
dd mem ; stack pointer
dd s ; parameters
dd 0 ; path
 
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
include '../debug-fdo.inc'
include '../network.inc'
 
; entry point
start:
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
; initialize console
push 1
call [con_start]
push title
push 25
push 80
push 25
push 80
call [con_init]
 
; Check for parameters
cmp byte [s], 0
jne resolve
 
main:
call [con_cls]
; Welcome user
push str1
call [con_write_asciiz]
 
; write prompt
push str2
call [con_write_asciiz]
; read string
mov esi, s
push 256
push esi
call [con_gets]
; check for exit
test eax, eax
jz done
cmp byte [esi], 10
jz done
 
resolve:
 
; delete terminating '\n'
mov esi, s
@@:
lodsb
cmp al, 0x20
ja @r
mov byte [esi-1], 0
 
call [con_cls]
push str3
call [con_write_asciiz]
push s
call [con_write_asciiz]
 
; resolve name
push esp ; reserve stack place
push esp ; fourth parameter
push 0 ; third parameter
push 0 ; second parameter
push s ; first parameter
call [getaddrinfo]
pop esi
; test for error
test eax, eax
jnz fail
 
; write results
push str8
call [con_write_asciiz]
; mov edi, esi
 
; convert IP address to decimal notation
mov eax, [esi+addrinfo.ai_addr]
mov eax, [eax+sockaddr_in.sin_addr]
mov [sockaddr1.ip], eax
push eax
call [inet_ntoa]
; write result
push eax
call [con_write_asciiz]
; free allocated memory
push esi
call [freeaddrinfo]
 
push str9
call [con_write_asciiz]
 
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
jz fail2
mov [socketnum], eax
 
mcall connect, [socketnum], sockaddr1, 18
 
mcall 40, 1 shl 7 ; + 7
call [con_cls]
 
mcall 18, 7
push eax
mcall 51, 1, thread, mem - 2048
pop ecx
mcall 18, 3
 
mainloop:
DEBUGF 1, 'TELNET: Waiting for events\n'
mcall 10
DEBUGF 1, 'TELNET: EVENT %x !\n', eax
 
call [con_get_flags]
test eax, 0x200 ; con window closed?
jnz exit
 
mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, 0
cmp eax, -1
je mainloop
 
DEBUGF 1, 'TELNET: got %u bytes of data !\n', eax
 
mov esi, buffer_ptr
lea edi, [esi + eax]
mov byte [edi], 0
 
.scan_cmd:
cmp byte [esi], 0xff ; Interpret As Command
jne .no_cmd
; TODO: parse options, for now, we will reply with 'WONT' to everything
mov byte [esi + 1], 252 ; WONT
add esi, 3 ; a command is always 3 bytes
jmp .scan_cmd
.no_cmd:
 
cmp esi, buffer_ptr
je .print_loop
 
DEBUGF 1, 'TELNET: sending data\n'
 
push esi edi
sub esi, buffer_ptr
mcall send, [socketnum], buffer_ptr, , 0
pop edi esi
 
.print_loop:
DEBUGF 1, 'TELNET: printloop\n'
cmp esi, edi
jae mainloop
 
cmp byte [esi], 0x1b ; escape character
jne .print_byte
inc esi
 
cmp word [esi], 0x485b ; move cursor to beginning
jne @f
inc esi
inc esi
 
DEBUGF 1, 'TELNET: resetting cursor \n'
 
push 0
push 0
call [con_set_cursor_pos]
jmp .print_loop
 
@@:
inc esi
inc esi
jmp .print_loop
 
.print_byte:
push dword 1
push esi ; next string to print
inc esi
call [con_write_string]
jmp .print_loop
 
 
fail2:
push str6
call [con_write_asciiz]
 
jmp fail.wait
 
fail:
push str5
call [con_write_asciiz]
.wait:
push str10
call [con_write_asciiz]
call [con_getch2]
jmp main
 
done:
push 1
call [con_exit]
exit:
 
mcall close, [socketnum]
mcall -1
 
 
 
thread:
mcall 40, 0
.loop:
call [con_getch2]
mov byte [send_data], al
mcall send, [socketnum], send_data, 1
 
call [con_get_flags]
test eax, 0x200 ; con window closed?
jz .loop
mcall -1
 
; data
title db 'Telnet',0
str1 db 'Telnet for KolibriOS v0.11',10,10,'Please enter URL of telnet server (for example: towel.blinkenlights.nl)',10,10,0
str2 db '> ',0
str3 db 'Connecting to: ',0
str4 db 10,0
str5 db 10,'Name resolution failed.',10,0
str6 db 10,'Could not open socket.',10,0
str8 db ' (',0
str9 db ')',10,0
str10 db 'Push any key to continue.',0
 
sockaddr1:
dw AF_INET4
.port dw 0x1700 ; 23
.ip dd 0
rb 10
 
include_debug_strings ; ALWAYS present in data section
 
 
 
; import
align 4
@IMPORT:
 
library network, 'network.obj', console, 'console.obj'
import network, \
getaddrinfo, 'getaddrinfo', \
freeaddrinfo, 'freeaddrinfo', \
inet_ntoa, 'inet_ntoa'
import console, \
con_start, 'START', \
con_init, 'con_init', \
con_write_asciiz, 'con_write_asciiz', \
con_exit, 'con_exit', \
con_gets, 'con_gets',\
con_cls, 'con_cls',\
con_getch2, 'con_getch2',\
con_set_cursor_pos, 'con_set_cursor_pos',\
con_write_string, 'con_write_string',\
con_get_flags, 'con_get_flags'
 
 
i_end:
 
socketnum dd ?
buffer_ptr rb BUFFERSIZE+1
send_data rb 100
 
s rb 1024
rb 4096 ; stack
mem:
/kernel/branches/net/applications/vncc/vncc.asm
0,0 → 1,283
;
;
; VNC Client for kolibrios by hidnplayr
;
; hidnplayr@gmail.com
;
 
format binary as ""
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image
dd IM_END ; memory for app
dd IM_END ; esp
dd 0x0 , 0x0 ; I_Param , I_Path
 
__DEBUG__ equ 1
__DEBUG_LEVEL__ equ 1
 
STRLEN = 64 ; password and server max length
xpos = 4 ; coordinates of image
ypos = 22 ;
 
TIMEOUT = 5 ; timeout in seconds
 
include '../macros.inc'
include '../debug-fdo.inc'
include '../proc32.inc'
include '../dll.inc'
include '../struct.inc'
include '../network.inc'
 
include 'structs.inc'
include 'logon.inc'
include 'raw.inc'
include 'thread.inc'
 
START:
 
mcall 68, 11 ; init heap
 
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
 
call red_logon
 
mcall 40, 0 ; no events
mcall 67, 0, 0, 0, 0 ; resize the window (hide it)
mcall 51, 1, thread_start, thread_stack
 
DEBUGF 1,'Thread created: %u\n', eax
 
@@:
mcall 5, 10
cmp byte [thread_ready], 0
je @r
 
mcall 40, 100111b ; mouse, button, key, redraw
 
 
mov edx, dword [screen]
movzx esi, dx
shr edx, 16
add edx, 2*xpos
add esi, ypos+xpos
mcall 67, 10, 10 ; resize the window
 
mainloop:
mcall 23, 50 ; wait for event, 0,5s timeout
 
dec eax
jz redraw
 
dec eax
jz key
 
dec eax
jz button
 
sub eax, 3
jz mouse
 
jmp mainloop
 
key:
 
DEBUGF 1,'Sending key event\n'
 
mcall 2
mov byte [keyevent.key+3], ah
 
mcall send, [socketnum], keyevent, 8, 0
jmp mainloop
 
mouse:
 
DEBUGF 1,'Sending mouse event\n'
 
mcall 37, 1 ; get mouse pos
sub eax, xpos shl 16 + ypos
bswap eax
mov [pointerevent.x], ax
shr eax, 16
mov [pointerevent.y], ax
 
mcall 37, 2 ; get mouse buttons
test al, 00000010b ; test if right button was pressed (bit 1 in kolibri)
jz @f
add al, 00000010b ; in RFB protocol it is bit 2, so if we add bit 2 again, we'll get bit 3 and bit 1 will remain the same
@@:
mov [pointerevent.mask],al
 
mcall send, [socketnum], pointerevent, 6, 0
jmp mainloop
 
redraw:
 
DEBUGF 1,'Drawing window\n'
 
mcall 12, 1
 
mov ebx, dword[screen]
movzx ecx, bx
shr ebx, 16
mov edx, 0x74ffffff
mov edi, name
mcall 0 ; draw window
 
call drawbuffer
 
mcall 12, 2
 
jmp mainloop
 
drawbuffer:
 
mcall 7, framebuffer_data, dword[screen], 0
ret
 
 
button:
mcall 17 ; get id
 
exit:
DEBUGF 1, 'Closing time!\n'
mcall close, [socketnum]
mcall -1
 
no_rfb:
DEBUGF 1, 'This is no vnc server!\n'
jmp exit
 
invalid_security:
DEBUGF 1, 'Security error: %s\n', receive_buffer+5
jmp exit
 
 
; DATA AREA
 
include_debug_strings ; ALWAYS present in data section
 
handshake db 'RFB 003.003', 10
shared db 0
beep db 0x85,0x25,0x85,0x40,0
 
pixel_format32 db 0 ; setPixelformat
rb 3 ; padding
.bpp db 32 ; bits per pixel
.depth db 32 ; depth
.big_endian db 0 ; big-endian flag
.true_color db 1 ; true-colour flag
.red_max db 0,255 ; red-max
.green_max db 0,255 ; green-max
.blue_max db 0,255 ; blue-max
.red_shif db 0 ; red-shift
.green_shift db 8 ; green-shift
.blue_shift db 16 ; blue-shift
rb 3 ; padding
 
pixel_format16 db 0 ; setPixelformat
rb 3 ; padding
.bpp db 16 ; bits per pixel
.depth db 15 ; depth
.big_endian db 0 ; big-endian flag
.true_color db 1 ; true-colour flag
.red_max db 0,31 ; red-max
.green_max db 0,31 ; green-max
.blue_max db 0,31 ; blue-max
.red_shif db 0 ; red-shift
.green_shift db 5 ; green-shift
.blue_shift db 10 ; blue-shift
rb 3 ; padding
 
pixel_format8 db 0 ; setPixelformat
rb 3 ; padding
.bpp db 8 ; bits per pixel
.depth db 6 ; depth
.big_endian db 0 ; big-endian flag
.true_color db 1 ; true-colour flag
.red_max db 0,3 ; red-max
.green_max db 0,3 ; green-max
.blue_max db 0,3 ; blue-max
.red_shif db 0 ; red-shift
.green_shift db 2 ; green-shift
.blue_shift db 4 ; blue-shift
rb 3 ; padding
 
encodings db 2 ; setEncodings
rb 1 ; padding
db 1,0 ; number of encodings
db 0,0,0,0 ; raw encoding (DWORD, Big endian order)
db 1,0,0,0 ; Copyrect encoding
 
fbur db 3 ; frame buffer update request
.inc db 0 ; incremental
.x dw 0
.y dw 0
.width dw 0
.height dw 0
 
keyevent db 4 ; keyevent
.down db 0 ; down-flag
dw 0 ; padding
.key dd 0 ; key
 
pointerevent db 5 ; pointerevent
.mask db 0 ; button-mask
.x dw 0 ; x-position
.y dw 0 ; y-position
 
 
sockaddr1:
dw AF_INET4
.port dw 0x0c17 ; 5900
.ip dd 0
rb 10
 
thread_ready db 0
; import
align 4
@IMPORT:
 
library network, 'network.obj'
import network, \
getaddrinfo, 'getaddrinfo', \
freeaddrinfo, 'freeaddrinfo', \
inet_ntoa, 'inet_ntoa'
 
name db 'VNC client', 0
 
I_END:
 
socketnum dd ?
datapointer dd ?
 
frame:
.width dw ?
.height dw ?
.x dw ?
.y dw ?
 
screen:
.height dw ?
.width dw ?
 
receive_buffer rb 5*1024*1024 ; 5 mb buffer for received data (incoming frbupdate etc)
framebuffer_data rb 1024*768*3 ; framebuffer
 
 
rb 0x1000
thread_stack:
 
rb 0x1000
IM_END:
 
 
/kernel/branches/net/applications/vncc/logon.inc
0,0 → 1,257
red_logon:
call draw_window_logon ; at first, draw the window
 
still_logon: ; main cycle of application begins here
mov eax,10 ; wait here for event
mcall
 
checkevent_logon: ; Check what event was called _logon: this will be used to return from textbox focus
 
dec eax ; redraw request ?
jz red_logon
dec eax ; key in buffer ?
jz key_logon
dec eax ; button in buffer ?
jz button_logon
 
jmp still_logon
 
key_logon: ; key event handler
mov al,2 ; eax was zero so will now be 2
mcall ; just read it and ignore
 
cmp ah,13
jne still_logon ; return to main loop
 
ret ; enter key was pressed => return to logon
 
button_logon: ; eax was zero so will now be 17
mov al,17 ; get id
mcall
 
cmp ah,1 ; close ?
jz close_logon
cmp ah,2 ; logon ?
je connect_logon
cmp ah,5 ; first ?
jz dstbtn_logon
 
srcbtn_logon:
mov dword[addr],first
jmp rk_logon
 
dstbtn_logon:
mov dword[addr],second
 
rk_logon:
mov edi,[addr] ; load the address of the string
xor al,al ; mov al,0 ; the symbol we will search for
mov ecx,STRLEN+1 ; length of the string (+1)
cld ; search forward
repne scasb ; do search now
inc ecx ; we've found a zero or ecx became 0
mov eax,STRLEN+1
sub eax,ecx ; eax = address of <0> character
mov [temp],eax ; position
 
cmp dword[addr],dword second
jne @f
mov dword [passlen],eax
@@:
 
call print_text_logon
 
mov edi,[addr] ; address of string
add edi,[temp] ; cursor position
 
.waitev_logon:
mov eax,10 ; wait for event
mcall
cmp eax,2 ; button presed ?
jne checkevent_logon ; a key is pressed or redraw is nessesary, goto checkevent
mcall ; eax = 2, read button
shr eax,8
cmp eax,8
jnz .nobs_logon ; BACKSPACE
cmp edi,[addr]
jz .waitev_logon
dec edi
mov byte[edi],0
 
cmp dword[addr],second
jne @f
dec [passlen]
@@:
 
call print_text_logon
jmp .waitev_logon
.nobs_logon:
cmp eax,13 ; ENTER
je still_logon
cmp eax,192
jne .noclear_logon
xor al,al
mov edi,[addr]
mov ecx,STRLEN
rep stosb
mov edi,[addr]
call print_text_logon
jmp .waitev_logon
 
.noclear_logon:
mov [edi],al
 
cmp dword[addr],second
jne @f
inc [passlen]
@@:
 
call print_text_logon
 
inc edi
mov esi,[addr]
add esi,STRLEN
cmp esi,edi
jnz .waitev_logon
 
jmp still_logon
 
 
; print strings (source & destination)
print_text_logon:
pusha
 
mov eax, 8
mov ebx, 105*65536+200
mov ecx, 31*65536+13
mov edx, 4
mov esi, 0xEBEBEB
mcall
 
cmp byte[mode],0
je @f
 
mov ecx, 49*65536+12
inc edx
mcall
 
@@:
mov eax, 4 ; function 4 _logon: write text to window
mov ebx, 107*65536+34 ; [x start] *65536 + [y start]
xor ecx, ecx ; color of text RRGGBB
mov edx, first ; pointer to text beginning
mov esi, STRLEN ; text length
mcall
 
cmp byte[mode],0
je dont_draw_pass
 
add ebx,16
mov edi,[passlen]
 
@@:
cmp edi,0
jle dont_draw_pass
 
dec edi
mov edx, passchar
mov esi, 1
mcall
add ebx,6*65536
jmp @r
 
dont_draw_pass:
 
popa
ret
 
close_logon:
or eax,-1
mcall
 
connect_logon:
ret
 
draw_window_logon:
 
mcall 12, 1 ; start window draw
pusha
; DRAW WINDOW
xor eax, eax ; function 0 _logon: define and draw window
mov ebx, 160*65536+330 ; [x start] *65536 + [x size]
mov ecx, 160*65536+100 ; [y start] *65536 + [y size]
mov edx, 0x13DDDDDD ; color of work area RRGGBB
mov edi, title ; WINDOW LABEL
mcall
 
mov eax, 8 ; LOGON BUTTON
mov ebx, 220*65536+85
mov ecx, 63*65536+16
mov edx, 2
mov esi, 0xCCCCCC
mcall
 
call print_text_logon
cmp byte[mode], 0
je servermode_
 
mov eax, 4 ; function 4 write text to window
mov ebx, 25*65536+33 ; [x start] *65536 + [y start]
xor ecx, ecx
mov edx, userstr ; pointer to text beginning
mov esi, passstr-userstr ; text length
mcall
 
add bl,19
mov edx, passstr ; pointer to text beginning
mov esi, connectstr-passstr ; text length
mcall
 
jmp drawtherest_
 
servermode_:
 
mov eax, 4 ; function 4 write text to window
mov ebx, 25*65536+33 ; [x start] *65536 + [y start]
xor ecx, ecx
mov edx, serverstr ; pointer to text beginning
mov esi, userstr-serverstr ; text length
mcall
 
drawtherest_:
 
mov ebx, 240*65536+67 ; [x start] *65536 + [y start]
mov edx, connectstr ; pointer to text beginning
mov esi, connect_e-connectstr ; text length
mcall
 
popa
inc ebx
mcall
 
ret
 
 
; DATA AREA
title db 'Kolibrios VNC client by HIDNPLAYR',0
 
first: db '192.168.1.5'
rb STRLEN
second: rb STRLEN
 
passchar db '*'
passlen dd 0
 
addr dd 0
temp dd 0
mode db 0 ; 0 = connection details, 1 = authentication
 
serverstr: db 'server:'
userstr: db 'username:'
passstr: db 'password:'
connectstr: db 'connect !'
connect_e:
 
I_END_logon:
/kernel/branches/net/applications/vncc/raw.inc
0,0 → 1,153
encoding_raw:
DEBUGF 1,'RAW\n'
 
mov ax,[frame.y] ;
mov bx,[screen.width] ;
mul bx ;
shl edx,16 ;
mov dx,ax ; [screen.width]*[frame.y]
movzx eax,[frame.x]
add edx,eax ; [screen.width]*[frame.y]+[frame.x]
 
mov eax,3 ;
mul edx ; ([screen.width]*[frame.y]+[frame.x])*3
 
add eax,framebuffer_data ;
push eax ; framebuffer_data+([screen.width]*[frame.y]+[frame.x])*3
 
mov ax,[frame.width] ;
mov bx,3 ;
mul bx ;
shl edx,16 ;
mov dx,ax ; [frame.width]*3
 
pop eax ;
add edx,eax ; framebuffer_data+([screen.width]*[frame.y]+[frame.x])*3+[frame.width]*3
push eax ;
push edx ;
 
mov ax,[frame.height] ;
dec ax ;
mov bx,3 ;
mul bx ;
mov bx,[screen.width] ;
mul bx ;
shl edx,16 ;
mov dx,ax ;
mov ecx,edx ;
pop edx ;
add ecx,edx ; mov ecx,edx+([frame.height]-1)*[screen.width]*3
pop ebx
 
.pixelloop32:
cmp ebx,ecx
jge next_rectangle
 
; add esi,2 ; 32 bit code RAW - OK
; mov al,[esi] ;
; mov [ebx],al ;
; inc ebx ;
; dec esi ;
; ;
; mov al,[esi] ;
; mov [ebx],al ;
; inc ebx ;
; dec esi ;
; ;
; mov al,[esi] ;
; mov [ebx],al ;
; inc ebx ;
; add esi,4 ;
 
; push ecx ; 16 bit code RAW
; mov cl,51
;
; mov ax,[esi] ;
; xchg al,ah
; and al,00011111b ;
; xchg al,ah
; mul cl
; mov [ebx],al ;
; inc ebx ;
;
; mov ax,[esi] ;
; xchg al,ah
; shr ax,5 ;
; xchg al,ah
; and al,00011111b ;
; mul cl
; mov [ebx],al ;
; inc ebx ;
;
; mov ax,[esi] ;
; xchg al,ah
; shr ax,10 ;
; and al,00011111b ;
; mul cl
; mov [ebx],al ;
; inc ebx ;
;
; inc esi ;
; inc esi ;
; pop ecx
 
push ecx ; 8 bit code RAW - OK
mov cl,85 ;
;
mov al,[esi] ;
shr al,4 ;
and al,3 ;
mul cl ;
mov [ebx],al ;
inc ebx ;
;
mov al,[esi] ;
shr al,2 ;
and al,3 ;
mul cl ;
mov [ebx],al ;
inc ebx ;
;
mov al,[esi] ;
and al,3 ;
mul cl ;
mov byte[ebx],al ;
inc ebx ;
inc esi ;
pop ecx ;
 
 
cmp ebx,edx
jl .pixelloop32
 
push edx
push ebx
mov ax,[screen.width]
mov bx,3
mul bx
shl edx,16
mov dx,ax
mov eax,edx
pop ebx
pop edx
 
add ebx,eax ; eax = [screen.width]*3
add edx,eax
 
push edx
push ebx
mov ax,[frame.width]
mov bx,3
mul bx
shl edx,16
mov dx,ax
mov eax,edx
pop ebx
pop edx
 
sub ebx,eax ; eax = [frame.width]*3
 
jmp .pixelloop32
 
 
 
/kernel/branches/net/applications/vncc/structs.inc
0,0 → 1,22
 
struct pixel_format
bpp db ?
depth db ?
big_endian db ?
true_color db ?
red_max dw ?
green_max dw ?
blue_max dw ?
red_shift db ?
green_shift db ?
blue_shift db ?
padding rb 3
ends
 
struct framebuffer
width dw ?
height dw ?
pixelformat pixel_format
name_length dd ?
name rb 256
ends
/kernel/branches/net/applications/vncc/thread.inc
0,0 → 1,239
 
thread_start:
 
DEBUGF 1, 'I am the thread!\n'
 
mcall 40, 1 shl 7
 
; resolve name
push esp ; reserve stack place
invoke getaddrinfo, first, 0, 0, esp
pop esi
; test for error
test eax, eax
jnz exit
 
mov eax, [esi+addrinfo.ai_addr]
mov eax, [eax+sockaddr_in.sin_addr]
mov [sockaddr1.ip], eax
 
; DEBUGF 1, 'Connecting to %u.%u.%u.%u:%u\n', \
; [server_ip]:1, [server_ip+1]:1, \
; [server_ip+2]:1, [server_ip+3]:1, \
; [server_port]:2
 
mcall socket, AF_INET4, SOCK_STREAM, 0
mov [socketnum], eax
mcall connect, [socketnum], sockaddr1, 18
 
call wait_for_data
 
cmp dword [receive_buffer], 'RFB '
jne no_rfb
DEBUGF 1, 'received: %s\n', receive_buffer
mcall send, [socketnum], handshake, 12, 0
DEBUGF 1, 'Sending handshake: protocol version\n'
 
call wait_for_data
 
cmp dword [receive_buffer], 0x00000000
je invalid_security
 
cmp dword [receive_buffer], 0x01000000
je no_security
 
cmp dword [receive_buffer], 0x02000000
je vnc_security
 
jmp exit
 
vnc_security:
mov byte[mode], 1
call red_logon
 
no_security:
mcall send, [socketnum], shared, 1, 0
DEBUGF 1, 'Sending handshake: shared session?\n'
 
mcall 23, 100*TIMEOUT
 
call wait_for_data ; now the server should send init message
 
DEBUGF 1, 'Serverinit: bpp: %u depth: %u bigendian: %u truecolor: %u\n', \
[receive_buffer+framebuffer.pixelformat.bpp]:1, \
[receive_buffer+framebuffer.pixelformat.depth]:1, \
[receive_buffer+framebuffer.pixelformat.big_endian]:1, \
[receive_buffer+framebuffer.pixelformat.true_color]:1
 
mov eax, dword [receive_buffer]
mov dword [fbur.width], eax
bswap eax
mov dword [screen], eax
 
mcall send, [socketnum], pixel_format8, 20, 0
DEBUGF 1, 'Sending pixel format\n'
call read_data
 
; eth.write_tcp [socket],8,encodings
; DEBUGF 1,'Sending encoding info\n'
; call read_data
 
mov byte [thread_ready], 1
 
request_rfb:
mov [fbur.inc], 2
mcall send, [socketnum], fbur, 10, 0
 
thread_loop:
mcall 23, 100
 
call read_data ; Read the data into the buffer
 
; cmp eax, 2
; jb mainloop
 
DEBUGF 1,'Data received, %u bytes\n', eax
 
cmp byte [receive_buffer],0
je framebufferupdate
 
cmp byte [receive_buffer],1
je setcolourmapentries
 
cmp byte [receive_buffer],2
je bell
 
cmp byte [receive_buffer],3
je servercuttext
 
jmp thread_loop
 
align 4
framebufferupdate:
 
mov ax, word [receive_buffer+2]
xchg al, ah
mov di, ax
DEBUGF 1, 'Framebufferupdate: %u frames\n', di
mov esi, receive_buffer+4
jmp rectangle_loop
 
 
next_rectangle:
call drawbuffer
 
dec di
test di, di
jz request_rfb
 
rectangle_loop:
 
mov edx, [esi]
bswap edx
mov ebx, edx
shr edx, 16
mov [frame.x], dx
mov [frame.y], bx
add esi, 4
mov ecx, [esi]
bswap ecx
mov eax, ecx
shr ecx, 16
mov [frame.width], cx
mov [frame.height], ax
add esi, 4
mov eax, [esi]
add esi, 4
 
mov ebx, esi
sub ebx, receive_buffer+12
DEBUGF 1, 'frame: width=%u height=%u x=%u y=%u offset:%u encoding:',\
[frame.width]:2, [frame.height]:2, [frame.x]:2, [frame.y]:2, ebx
 
cmp eax, 0
je encoding_raw
; cmp eax, 1
; je encoding_copyrect
cmp eax, 2
je encoding_RRE
cmp eax, 5
je encoding_hextile
cmp eax, 16
je encoding_ZRLE
 
mov ebx, esi
sub ebx, receive_buffer+8
DEBUGF 1, '\nunknown encoding: %u (offset %u)\n', eax, ebx
jmp bell
jmp thread_loop
 
encoding_RRE:
 
DEBUGF 1, 'RRE\n'
 
jmp next_rectangle
 
encoding_hextile:
 
DEBUGF 1, 'hextile\n'
 
jmp next_rectangle
 
encoding_ZRLE:
 
DEBUGF 1, 'ZRLE\n'
 
jmp next_rectangle
 
setcolourmapentries:
 
DEBUGF 1, 'Server sent SetColourMapEntries message\n'
 
jmp thread_loop
 
 
bell:
mcall 55, 55, , , beep
 
jmp thread_loop
 
 
servercuttext:
 
DEBUGF 1, 'Server cut text\n'
 
jmp thread_loop
 
 
read_data:
 
mov [datapointer], receive_buffer
.loop:
mcall 23, 100*TIMEOUT
mcall recv, [socketnum], [datapointer], 4096, 0
cmp eax, -1
je .done
 
add [datapointer], eax
 
cmp eax, 4096
je .loop
 
.done:
mov eax, [datapointer]
sub eax, receive_buffer
ret
 
 
 
wait_for_data:
 
mcall 23, 500
mcall recv, [socketnum], receive_buffer, 4096, 0
cmp eax, -1
je wait_for_data
test eax, eax
jz wait_for_data
 
ret
 
/kernel/branches/net/applications/pppoe/pppoe.asm
0,0 → 1,362
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; pppoe.asm - PPPoE dialer for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format binary as ""
 
use32
 
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem ; required memory
dd mem ; stack pointer
dd 0 ; parameters
dd 0 ; path
 
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
include '../network.inc'
include '../struct.inc'
 
; Ethernet protocol numbers
ETHER_PPP_DISCOVERY = 0x6388
ETHER_PPP_SESSION = 0x6488
 
; PPP protocol numbers
PPP_LCP = 0x21c0 ; Link Configure Protocol
PPP_CBCP = 0x29c0 ; CallBack Control Protocol
PPP_PAP = 0x23c0 ; Password Authenication Protocol packet
PPP_CHAP = 0x23c2 ; Challenge Handshake Authentication Protocol
PPP_IPCP = 0x2180 ; Internet Protocol Configure Protocol (maybe this should be in kernel?)
PPP_CCP = 0xfd80 ; Compression Configure Protocol
 
; PPP Active Discovery...
PPPoE_PADI = 0x09 ; .. Initiation
PPPoE_PADO = 0x07 ; .. Offer
PPPoE_PADR = 0x19 ; .. Request
PPPoE_PADS = 0x65 ; .. Session-confirmation
PPPoE_PADT = 0xa7 ; .. Terminate
 
TAG_EOL = 0x0000
TAG_SERVICE_NAME= 0x0101
TAG_AC_NAME = 0x0201
TAG_HOST_UNIQ = 0x0301
TAG_AC_COOKIE = 0x0401
 
LCP_config_request = 1
LCP_config_ack = 2
LCP_config_nak = 3
LCP_config_reject = 4
LCP_terminate_request = 5
LCP_terminate_ack = 6
LCP_code_reject = 7
LCP_protocol_reject = 8
LCP_echo_request = 9
LCP_echo_reply = 10
LCP_discard_request = 11
 
struct ETH_frame
DestMac dp ?
SrcMac dp ?
Type dw ?
ends
 
struct PPPoE_frame ETH_frame
VersionAndType db ?
Code db ?
SessionID dw ?
Length dw ? ; Length of payload, does NOT include the length PPPoE header.
Payload rb 0
ends
 
struct PPP_frame PPPoE_frame
Protocol dw ?
ends
 
struct LCP_frame PPP_frame
LCP_Code db ?
LCP_Identifier db ?
LCP_Length dw ?
LCP_Data rb 0
ends
 
; entry point
start:
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
; initialize console
push 1
call [con_start]
push title
push 25
push 80
push 25
push 80
call [con_init]
 
main:
mcall 40, 1 shl 7
 
call [con_cls]
; Welcome user
push str1
call [con_write_asciiz]
 
mcall socket, 777, 3, 666
mov [socketnum], eax
mcall send, [socketnum], PADI, PADI.length, 0
 
mainloop:
mcall 10
 
call [con_get_flags]
test eax, 0x200 ; con window closed?
jnz close_conn
 
mcall recv, [socketnum], buffer, 4096
cmp eax, sizeof.PPPoE_frame
jb mainloop
 
cmp word [buffer + ETH_frame.Type], ETHER_PPP_SESSION
je SESSION_input
 
cmp word [buffer + ETH_frame.Type], ETHER_PPP_DISCOVERY
jne mainloop
 
cmp [buffer + PPPoE_frame.Code], PPPoE_PADO
je pado
 
cmp [buffer + PPPoE_frame.Code], PPPoE_PADS
je pads
 
cmp [buffer + PPPoE_frame.Code], PPPoE_PADT
je padt
 
jmp mainloop
 
pado:
 
push str2
call [con_write_asciiz]
 
lea esi, [buffer + ETH_frame.SrcMac] ; source mac -> dest mac
lea edi, [buffer + ETH_frame.DestMac]
movsw
movsd
 
mov byte [buffer + PPPoE_frame.Code], PPPoE_PADR ; change packet type to PADR
 
mov al, byte [buffer + PPPoE_frame.Length + 1] ; get packet size
mov ah, byte [buffer + PPPoE_frame.Length + 0]
movzx esi, ax
add esi, sizeof.PPPoE_frame
mcall send, [socketnum], buffer, , 0 ; now send it!
 
jmp mainloop
 
 
pads:
 
push str3
call [con_write_asciiz]
 
mov edx, dword [buffer + ETH_frame.SrcMac] ; source mac -> dest mac
mov si, word [buffer + ETH_frame.SrcMac + 4]
mov dword [PADT.mac], edx
mov word [PADT.mac + 4], si
 
mov cx, word [buffer + PPPoE_frame.SessionID] ; and Session ID
mov [PADT.sid], cx
 
mcall 76, API_PPPOE + 0 ; Start PPPoE session
 
jmp mainloop
 
padt:
 
push str4
call [con_write_asciiz]
 
mcall 76, API_PPPOE + 1 ; Stop PPPoE session
 
exit:
mcall close, [socketnum]
mcall -1
 
 
close_conn:
 
mcall send, [socketnum], PADT, PADT.length, 0
jmp exit
 
 
SESSION_input:
 
mov ax, word[buffer + PPP_frame.Protocol]
 
cmp ax, PPP_LCP
je LCP_input
 
cmp ax, PPP_CBCP
je CBCP_input
 
cmp ax, PPP_PAP
je PAP_input
 
cmp ax, PPP_CHAP
je CHAP_input
 
cmp ax, PPP_IPCP
je IPCP_input
 
cmp ax, PPP_CCP
je CCP_input
 
jmp mainloop
 
 
 
LCP_input:
 
stdcall con_write_asciiz, str_lcp
 
cmp [buffer + LCP_frame.LCP_Code], LCP_echo_request
je .echo
 
.dump:
jmp mainloop
 
.echo:
mov [buffer + LCP_frame.LCP_Code], LCP_echo_reply
 
lea esi, [buffer + ETH_frame.SrcMac] ; source mac -> dest mac
lea edi, [buffer + ETH_frame.DestMac]
movsw
movsd
 
mov esi, eax
mcall send, [socketnum], buffer, , 0 ; now send it back!
 
jmp mainloop
 
CBCP_input:
 
stdcall con_write_asciiz, str_cbcp
 
jmp mainloop
 
PAP_input:
 
stdcall con_write_asciiz, str_pap
 
jmp mainloop
 
CHAP_input:
 
stdcall con_write_asciiz, str_chap
 
jmp mainloop
 
IPCP_input:
 
stdcall con_write_asciiz, str_ipcp
 
jmp mainloop
 
CCP_input:
 
stdcall con_write_asciiz, str_ccp
 
jmp mainloop
 
; data
title db 'PPPoE',0
str1 db 'Sending PADI',13,10,0
str2 db 'Got PADO',13,10,'Sending PADR',13,10,0
str3 db 'Got PADS',13,10,'starting PPPoE session',13,10,0
str4 db 'Got PADT - connection terminated by Access Concentrator',13,10,0
str_lcp db 'Got LCP packet',13,10,0
str_cbcp db 'got CBCP packet',13,10,0
str_pap db 'got PAP packet',13,10,0
str_chap db 'got CHAP packet',13,10,0
str_ipcp db 'got IPCP packet',13,10,0
str_ccp db 'got CCP packet',13,10,0
 
 
PADI:
dp 0xffffffffffff ; dest mac: broadcast
dp 0 ; source mac (overwritten by kernel)
dw ETHER_PPP_DISCOVERY ; type
 
db 0x11 ; Version and Type
db PPPoE_PADI ; Code
dw 0 ; session ID
dw 20 shl 8 ; Payload Length
 
dw TAG_SERVICE_NAME ; tag
dw 0x0000 ; length
 
dw TAG_HOST_UNIQ ; tag
dw 0x0c00 ; length = 12 bytes
 
dd 0xdead ; some random id
dd 0xbeef
dd 0x1337
 
.length = $ - PADI
 
PADT:
 
.mac dp 0 ; Dest mac, to be filled in
dp 0 ; source mac (overwritten by kernel)
dw ETHER_PPP_DISCOVERY ; Type
 
db 0x11 ; Version and Type
db PPPoE_PADT ; Code: terminate connection
.sid dw 0 ; session id, to be filled in
dw 0 ; PAyload length = 0
 
.length = $ - PADT
 
 
; import
align 4
@IMPORT:
 
library console, 'console.obj'
import console, \
con_start, 'START', \
con_init, 'con_init', \
con_write_asciiz, 'con_write_asciiz', \
con_exit, 'con_exit', \
con_gets, 'con_gets',\
con_cls, 'con_cls',\
con_getch2, 'con_getch2',\
con_set_cursor_pos, 'con_set_cursor_pos',\
con_write_string, 'con_write_string',\
con_get_flags, 'con_get_flags'
 
 
i_end:
 
socketnum dd ?
 
buffer rb 4096
rb 4096 ; stack
mem:
/kernel/branches/net/applications/icmp/icmp.inc
0,0 → 1,77
; ICMP types & codes
 
ICMP_ECHOREPLY equ 0 ; echo reply message
 
ICMP_UNREACH equ 3
ICMP_UNREACH_NET equ 0 ; bad net
ICMP_UNREACH_HOST equ 1 ; bad host
ICMP_UNREACH_PROTOCOL equ 2 ; bad protocol
ICMP_UNREACH_PORT equ 3 ; bad port
ICMP_UNREACH_NEEDFRAG equ 4 ; IP_DF caused drop
ICMP_UNREACH_SRCFAIL equ 5 ; src route failed
ICMP_UNREACH_NET_UNKNOWN equ 6 ; unknown net
ICMP_UNREACH_HOST_UNKNOWN equ 7 ; unknown host
ICMP_UNREACH_ISOLATED equ 8 ; src host isolated
ICMP_UNREACH_NET_PROHIB equ 9 ; prohibited access
ICMP_UNREACH_HOST_PROHIB equ 10 ; ditto
ICMP_UNREACH_TOSNET equ 11 ; bad tos for net
ICMP_UNREACH_TOSHOST equ 12 ; bad tos for host
ICMP_UNREACH_FILTER_PROHIB equ 13 ; admin prohib
ICMP_UNREACH_HOST_PRECEDENCE equ 14 ; host prec vio.
ICMP_UNREACH_PRECEDENCE_CUTOFF equ 15 ; prec cutoff
 
ICMP_SOURCEQUENCH equ 4 ; Packet lost, slow down
 
ICMP_REDIRECT equ 5 ; shorter route, codes:
ICMP_REDIRECT_NET equ 0 ; for network
ICMP_REDIRECT_HOST equ 1 ; for host
ICMP_REDIRECT_TOSNET equ 2 ; for tos and net
ICMP_REDIRECT_TOSHOST equ 3 ; for tos and host
 
ICMP_ALTHOSTADDR equ 6 ; alternate host address
ICMP_ECHO equ 8 ; echo service
ICMP_ROUTERADVERT equ 9 ; router advertisement
ICMP_ROUTERADVERT_NORMAL equ 0 ; normal advertisement
ICMP_ROUTERADVERT_NOROUTE_COMMON equ 16 ; selective routing
 
ICMP_ROUTERSOLICIT equ 10 ; router solicitation
ICMP_TIMXCEED equ 11 ; time exceeded, code:
ICMP_TIMXCEED_INTRANS equ 0 ; ttl==0 in transit
ICMP_TIMXCEED_REASS equ 1 ; ttl==0 in reass
 
ICMP_PARAMPROB equ 12 ; ip header bad
ICMP_PARAMPROB_ERRATPTR equ 0 ; error at param ptr
ICMP_PARAMPROB_OPTABSENT equ 1 ; req. opt. absent
ICMP_PARAMPROB_LENGTH equ 2 ; bad length
 
ICMP_TSTAMP equ 13 ; timestamp request
ICMP_TSTAMPREPLY equ 14 ; timestamp reply
ICMP_IREQ equ 15 ; information request
ICMP_IREQREPLY equ 16 ; information reply
ICMP_MASKREQ equ 17 ; address mask request
ICMP_MASKREPLY equ 18 ; address mask reply
ICMP_TRACEROUTE equ 30 ; traceroute
ICMP_DATACONVERR equ 31 ; data conversion error
ICMP_MOBILE_REDIRECT equ 32 ; mobile host redirect
ICMP_IPV6_WHEREAREYOU equ 33 ; IPv6 where-are-you
ICMP_IPV6_IAMHERE equ 34 ; IPv6 i-am-here
ICMP_MOBILE_REGREQUEST equ 35 ; mobile registration req
ICMP_MOBILE_REGREPLY equ 36 ; mobile registreation reply
ICMP_SKIP equ 39 ; SKIP
 
ICMP_PHOTURIS equ 40 ; Photuris
ICMP_PHOTURIS_UNKNOWN_INDEX equ 1 ; unknown sec index
ICMP_PHOTURIS_AUTH_FAILED equ 2 ; auth failed
ICMP_PHOTURIS_DECRYPT_FAILED equ 3 ; decrypt failed
 
 
 
virtual at 0
ICMP_Packet:
.Type db ?
.Code db ?
.Checksum dw ?
.Identifier dw ?
.SequenceNumber dw ?
.Data:
end virtual
/kernel/branches/net/applications/icmp/ping.asm
0,0 → 1,256
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ping.asm - ICMP echo client for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
format binary as ""
 
use32
org 0x0
 
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd I_END ; initialized size
dd mem ; required memory
dd mem ; stack pointer
dd s ; parameters
dd 0 ; path
 
 
BUFFERSIZE equ 1500
; useful includes
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
include '../network.inc'
 
include 'icmp.inc'
 
 
start:
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
; initialize console
push 1
call [con_start]
push title
push 25
push 80
push 25
push 80
call [con_init]
; main loop
cmp byte[s], 0
jne resolve
main:
; write prompt
push str2
call [con_write_asciiz]
; read string
mov esi, s
push 256
push esi
call [con_gets]
; check for exit
test eax, eax
jz done
cmp byte [esi], 10
jz done
; delete terminating '\n'
push esi
@@:
lodsb
test al, al
jnz @b
mov byte [esi-2], al
pop esi
 
resolve:
; resolve name
push esp ; reserve stack place
push esp ; fourth parameter
push 0 ; third parameter
push 0 ; second parameter
push s ; first parameter
call [getaddrinfo]
pop esi
; test for error
test eax, eax
jnz fail
 
; convert IP address to decimal notation
mov eax, [esi+addrinfo.ai_addr]
mov eax, [eax+sockaddr_in.sin_addr]
mov [sockaddr1.ip], eax
push eax
call [inet_ntoa]
; write result
mov [ip_ptr], eax
 
push eax
 
; free allocated memory
push esi
call [freeaddrinfo]
 
push str4
call [con_write_asciiz]
 
mcall socket, AF_INET4, SOCK_RAW, IPPROTO_ICMP
cmp eax, -1
jz fail2
mov [socketnum], eax
 
mcall connect, [socketnum], sockaddr1, 18
 
mcall 40, 1 shl 7 ; + 7
; call [con_cls]
 
mov [count], 4
 
mainloop:
push str3
call [con_write_asciiz]
push [ip_ptr]
call [con_write_asciiz]
 
mcall 26,9
mov [time_reference], eax
mcall send, [socketnum], icmp_packet, icmp_packet.length, 0
 
mcall 23, 300 ; 3 seconds time-out
mcall 26,9
neg [time_reference]
add [time_reference], eax
 
mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, 0
cmp eax, -1
je .no_response
 
; validate the packet
lea esi, [buffer_ptr + ICMP_Packet.Data]
mov edi, icmp_packet.data
mov ecx, 32/4
repe cmpsd
jne .miscomp
 
push [time_reference]
push str7
call [con_printf]
 
jmp continue
 
.miscomp:
sub edi, icmp_packet.data
push edi
push str9
call [con_printf]
jmp continue
 
.no_response:
push str8
call [con_write_asciiz]
 
continue:
dec [count]
jz done
mcall 5, 100 ; wait a second
inc [icmp_packet.id]
jmp mainloop
 
 
 
done:
push str10
call [con_write_asciiz]
call [con_getch2]
push 1
call [con_exit]
exit:
mcall -1
 
fail:
push str5
call [con_write_asciiz]
jmp done
fail2:
push str6
call [con_write_asciiz]
jmp done
 
 
; data
title db 'ICMP - echo client',0
str2 db '> ',0
str3 db 'Ping to ',0
str4 db 10,0
str5 db 'Name resolution failed.',10,0
str6 db 'Could not open socket',10,0
str7 db ' time= %u0ms',10,0
str8 db ' timeout!',10,0
str9 db ' miscompare at offset %u',10,0
str10 db 10,'Press any key to exit',0
 
sockaddr1:
dw AF_INET4
.port dw 0
.ip dd 0
rb 10
 
time_reference dd ?
ip_ptr dd ?
count dd ?
 
 
; import
align 4
@IMPORT:
 
library network, 'network.obj', console, 'console.obj'
import network, \
getaddrinfo, 'getaddrinfo', \
freeaddrinfo, 'freeaddrinfo', \
inet_ntoa, 'inet_ntoa'
 
import console, \
con_start, 'START', \
con_init, 'con_init', \
con_write_asciiz, 'con_write_asciiz', \
con_printf, 'con_printf', \
con_exit, 'con_exit', \
con_gets, 'con_gets',\
con_cls, 'con_cls',\
con_getch2, 'con_getch2',\
con_set_cursor_pos, 'con_set_cursor_pos'
 
socketnum dd ?
 
icmp_packet: db 8 ; type
db 0 ; code
dw 0 ;
.id dw 0x0000 ; identifier
.seq dw 0x0001 ; sequence number
.data db 'abcdefghijklmnopqrstuvwxyz012345678'
.length = $ - icmp_packet
 
I_END:
 
buffer_ptr rb BUFFERSIZE
 
s rb 1024
rb 4096 ; stack
mem:
/kernel/branches/net/applications/arpcfg/arpcfg.asm
0,0 → 1,156
;
; ARPmanager for KolibriOS
;
; hidnplayr@gmail.com
;
 
format binary as ""
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd IM_END ; size of image
dd (I_END+0x100) ; memory for app
dd (I_END+0x100) ; esp
dd 0x0 , 0x0 ; I_Param , I_Icon
 
include '../macros.inc'
purge mov, add, sub
include '../struct.inc'
include '../network.inc'
 
START:
 
redraw:
 
mcall 12, 1
mcall 0, 100 shl 16 + 520, 100 shl 16 + 240, 0x34bcbcbc, , str_name
mcall 4, 25 shl 16 + 31, 0x80000000, str_legend
mcall 12, 2
 
draw_stats:
 
mov edx, 50 shl 16 + 50
mov [last], 0
 
.loop:
mcall 76, API_ARP + 3, [last],,, arp_buf
cmp eax, -1
je mainloop
 
mcall 4, edx, 0x80000000, str_entry
mov edx, ebx
 
mov eax, 47
mov ebx, 0x00030000
mov esi, 0x40000000
mov edi, 0x00bcbcbc
xor ecx, ecx
 
mov cl, byte[arp_buf.IP+0]
mcall
 
mov cl, byte[arp_buf.IP+1]
add edx, 24 shl 16
mcall
 
mov cl, byte[arp_buf.IP+2]
add edx, 24 shl 16
mcall
 
mov cl, byte[arp_buf.IP+3]
add edx, 24 shl 16
mcall
 
 
mov ebx, 0x00020100
mov cl, byte[arp_buf.MAC+0]
add edx, 36 shl 16
mcall
 
mov cl, byte[arp_buf.MAC+1]
add edx, 18 shl 16
mcall
 
mov cl, byte[arp_buf.MAC+2]
add edx, 18 shl 16
mcall
 
mov cl, byte[arp_buf.MAC+3]
add edx, 18 shl 16
mcall
 
mov cl, byte[arp_buf.MAC+4]
add edx, 18 shl 16
mcall
 
mov cl, byte[arp_buf.MAC+5]
add edx, 18 shl 16
mcall
 
mov ebx, 0x00040000
mov cx, [arp_buf.status]
add edx, 30 shl 16
mcall
 
mov cx, [arp_buf.TTL]
add edx, 60 shl 16
mcall
 
add dx, 20
rol edx, 16
mov dx, 50
rol edx, 16
inc [last]
 
jmp .loop
 
 
mainloop:
 
mcall 23,50 ; wait for event with timeout (0,5 s)
 
cmp eax, 1
je redraw
cmp eax, 2
je key
cmp eax, 3
je button
 
jmp draw_stats
 
 
key:
mcall 2
jmp mainloop
 
 
button: ; button
mcall 17 ; get id
cmp ah, 1
je exit
jmp redraw
 
exit:
mcall -1
 
 
 
; DATA AREA
 
str_name db 'ARP manager', 0
str_legend db '# IP-address MAC-address Status TTL', 0
str_entry db ' . . . - - - - - s', 0
 
IM_END:
 
last dd ?
arp_buf ARP_entry
 
I_END:
 
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/applications/nslookup/nslookup.asm
0,0 → 1,136
format binary as ""
 
use32
; standard header
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem ; required memory
dd mem ; stack pointer
dd 0 ; parameters
dd 0 ; path
 
; useful includes
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
 
include '../network.inc'
 
; entry point
start:
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
; initialize console
push 1
call [con_start]
push title
push -1
push -1
push -1
push -1
call [con_init]
; main loop
main:
; write prompt
push str1
call [con_write_asciiz]
; read string
mov esi, s
push 256
push esi
call [con_gets]
; check for exit
test eax, eax
jz done
cmp byte [esi], 10
jz done
; delete terminating '\n'
push esi
@@:
lodsb
test al, al
jnz @b
mov byte [esi-2], al
pop esi
; resolve name
push esp ; reserve stack place
push esp ; fourth parameter
push 0 ; third parameter
push 0 ; second parameter
push esi ; first parameter
call [getaddrinfo]
pop esi
; test for error
test eax, eax
jnz fail
; write results
push str2
call [con_write_asciiz]
mov edi, esi
addrloop:
; before all subsequent addresses print comma
cmp edi, esi
jz @f
push str3
call [con_write_asciiz]
@@:
; convert IP address to decimal notation
mov eax, [edi+addrinfo.ai_addr]
pushd [eax+sockaddr_in.sin_addr]
call [inet_ntoa]
; write result
push eax
call [con_write_asciiz]
; advance to next item
mov edi, [edi+addrinfo.ai_next]
test edi, edi
jnz addrloop
; free allocated memory
push esi
call [freeaddrinfo]
; write newline and continue main loop
push str4
@@:
call [con_write_asciiz]
jmp main
fail:
push str5
jmp @b
done:
push 1
call [con_exit]
exit:
mcall -1
 
; data
title db 'Names resolver',0
str1 db 'Host name to resolve: ',0
str2 db 'IP address(es): ',0
str3 db ', ',0
str4 db 10,0
str5 db 'Name resolution failed.',10,0
; import
align 4
@IMPORT:
 
library network, 'network.obj', console, 'console.obj'
import network, \
getaddrinfo, 'getaddrinfo', \
freeaddrinfo, 'freeaddrinfo', \
inet_ntoa, 'inet_ntoa'
import console, \
con_start, 'START', \
con_init, 'con_init', \
con_write_asciiz, 'con_write_asciiz', \
con_exit, 'con_exit', \
con_gets, 'con_gets'
i_end:
s rb 256
align 4
rb 4096 ; stack
mem:
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/applications/dll.inc
0,0 → 1,160
;-----------------------------------------------------------------------------
proc mem.Alloc size ;/////////////////////////////////////////////////////////
;-----------------------------------------------------------------------------
push ebx ecx
mov eax,[size]
lea ecx,[eax+4+4095]
and ecx, not 4095
mcall 68,12
test eax, eax
jz @f
add ecx,-4
mov [eax],ecx
add eax,4
@@:
pop ecx ebx
ret
endp
 
;-----------------------------------------------------------------------------
proc mem.ReAlloc mptr,size;///////////////////////////////////////////////////
;-----------------------------------------------------------------------------
push ebx ecx esi edi eax
mov eax,[mptr]
mov ebx,[size]
or eax,eax
jz @f
lea ecx,[ebx+4+4095]
and ecx,not 4095
add ecx,-4
cmp ecx,[eax-4]
je .exit
@@: mov eax,ebx
call mem.Alloc
xchg eax,[esp]
or eax,eax
jz .exit
mov esi,eax
xchg eax,[esp]
mov edi,eax
mov ecx,[esi-4]
cmp ecx,[edi-4]
jbe @f
mov ecx,[edi-4]
@@: add ecx,3
shr ecx,2
cld
rep movsd
xchg eax,[esp]
call mem.Free
.exit:
pop eax edi esi ecx ebx
ret
endp
 
;-----------------------------------------------------------------------------
proc mem.Free mptr ;//////////////////////////////////////////////////////////
;-----------------------------------------------------------------------------
mov eax,[mptr]
or eax,eax
jz @f
push ebx ecx
lea ecx,[eax-4]
mcall 68,13
pop ecx ebx
@@: ret
endp
 
 
proc dll.Load, import_table:dword
mov esi,[import_table]
.next_lib: mov edx,[esi]
or edx,edx
jz .exit
push esi
mov esi,[esi+4]
mov edi,s_libdir.fname
@@: lodsb
stosb
or al,al
jnz @b
mcall 68,19,s_libdir
or eax,eax
jz .fail
stdcall dll.Link,eax,edx
stdcall dll.Init,[eax+4]
pop esi
add esi,8
jmp .next_lib
.exit: xor eax,eax
ret
.fail: add esp,4
xor eax,eax
inc eax
ret
endp
 
proc dll.Link, exp:dword,imp:dword
push eax
mov esi,[imp]
test esi,esi
jz .done
.next: lodsd
test eax,eax
jz .done
stdcall dll.GetProcAddress,[exp],eax
or eax,eax
jz @f
mov [esi-4],eax
jmp .next
@@: mov dword[esp],0
.done: pop eax
ret
endp
 
proc dll.Init, dllentry:dword
pushad
mov eax,mem.Alloc
mov ebx,mem.Free
mov ecx,mem.ReAlloc
mov edx,dll.Load
stdcall [dllentry]
popad
ret
endp
 
proc dll.GetProcAddress, exp:dword,sz_name:dword
mov edx,[exp]
xor eax,eax
.next: or edx,edx
jz .end
cmp dword[edx],0
jz .end
stdcall strcmp,[edx],[sz_name]
test eax,eax
jz .ok
add edx,8
jmp .next
.ok: mov eax,[edx+4]
.end: ret
endp
 
proc strcmp, str1:dword,str2:dword
push esi edi
mov esi,[str1]
mov edi,[str2]
xor eax,eax
@@: lodsb
scasb
jne .fail
or al,al
jnz @b
jmp .ok
.fail: or eax,-1
.ok: pop edi esi
ret
endp
 
s_libdir:
db '/sys/lib/'
.fname rb 32
/kernel/branches/net/applications/struct.inc
0,0 → 1,240
 
; Macroinstructions for defining data structures
 
macro struct name
{ virtual at 0
fields@struct equ name
match child parent, name \{ fields@struct equ child,fields@\#parent \}
sub@struct equ
struc db [val] \{ \common define field@struct .,db,<val>
fields@struct equ fields@struct,field@struct \}
struc dw [val] \{ \common define field@struct .,dw,<val>
fields@struct equ fields@struct,field@struct \}
struc du [val] \{ \common define field@struct .,du,<val>
fields@struct equ fields@struct,field@struct \}
struc dd [val] \{ \common define field@struct .,dd,<val>
fields@struct equ fields@struct,field@struct \}
struc dp [val] \{ \common define field@struct .,dp,<val>
fields@struct equ fields@struct,field@struct \}
struc dq [val] \{ \common define field@struct .,dq,<val>
fields@struct equ fields@struct,field@struct \}
struc dt [val] \{ \common define field@struct .,dt,<val>
fields@struct equ fields@struct,field@struct \}
struc rb count \{ define field@struct .,db,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rw count \{ define field@struct .,dw,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rd count \{ define field@struct .,dd,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rp count \{ define field@struct .,dp,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rq count \{ define field@struct .,dq,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rt count \{ define field@struct .,dt,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro db [val] \{ \common \local anonymous
define field@struct anonymous,db,<val>
fields@struct equ fields@struct,field@struct \}
macro dw [val] \{ \common \local anonymous
define field@struct anonymous,dw,<val>
fields@struct equ fields@struct,field@struct \}
macro du [val] \{ \common \local anonymous
define field@struct anonymous,du,<val>
fields@struct equ fields@struct,field@struct \}
macro dd [val] \{ \common \local anonymous
define field@struct anonymous,dd,<val>
fields@struct equ fields@struct,field@struct \}
macro dp [val] \{ \common \local anonymous
define field@struct anonymous,dp,<val>
fields@struct equ fields@struct,field@struct \}
macro dq [val] \{ \common \local anonymous
define field@struct anonymous,dq,<val>
fields@struct equ fields@struct,field@struct \}
macro dt [val] \{ \common \local anonymous
define field@struct anonymous,dt,<val>
fields@struct equ fields@struct,field@struct \}
macro rb count \{ \local anonymous
define field@struct anonymous,db,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rw count \{ \local anonymous
define field@struct anonymous,dw,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rd count \{ \local anonymous
define field@struct anonymous,dd,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rp count \{ \local anonymous
define field@struct anonymous,dp,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rq count \{ \local anonymous
define field@struct anonymous,dq,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rt count \{ \local anonymous
define field@struct anonymous,dt,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro union \{ fields@struct equ fields@struct,,union,<
sub@struct equ union \}
macro struct \{ fields@struct equ fields@struct,,substruct,<
sub@struct equ substruct \} }
 
macro ends
{ match , sub@struct \{ restruc db,dw,du,dd,dp,dq,dt
restruc rb,rw,rd,rp,rq,rt
purge db,dw,du,dd,dp,dq,dt
purge rb,rw,rd,rp,rq,rt
purge union,struct
match name tail,fields@struct, \\{ if $
display 'Error: definition of ',\\`name,' contains illegal instructions.',0Dh,0Ah
err
end if \\}
match name=,fields,fields@struct \\{ fields@struct equ
make@struct name,fields
define fields@\\#name fields \\}
end virtual \}
match any, sub@struct \{ fields@struct equ fields@struct> \}
restore sub@struct }
 
macro make@struct name,[field,type,def]
{ common
local define
define equ name
forward
local sub
match , field \{ make@substruct type,name,sub def
define equ define,.,sub, \}
match any, field \{ define equ define,.#field,type,<def> \}
common
match fields, define \{ define@struct fields \} }
 
macro define@struct name,[field,type,def]
{ common
virtual
db `name
load initial@struct byte from 0
if initial@struct = '.'
display 'Error: name of structure should not begin with a dot.',0Dh,0Ah
err
end if
end virtual
local list
list equ
forward
if ~ field eq .
name#field type def
sizeof.#name#field = $ - name#field
else
label name#.#type
rb sizeof.#type
end if
local value
match any, list \{ list equ list, \}
list equ list <value>
common
sizeof.#name = $
restruc name
match values, list \{
struc name value \\{ \\local \\..base
match any, fields@struct \\\{ fields@struct equ fields@struct,.,name,<values> \\\}
match , fields@struct \\\{ label \\..base
forward
match , value \\\\{ field type def \\\\}
match any, value \\\\{ field type value
if ~ field eq .
rb sizeof.#name#field - ($-field)
end if \\\\}
common label . at \\..base \\\}
\\}
macro name value \\{
match any, fields@struct \\\{ \\\local anonymous
fields@struct equ fields@struct,anonymous,name,<values> \\\}
match , fields@struct \\\{
forward
match , value \\\\{ type def \\\\}
match any, value \\\\{ \\\\local ..field
..field = $
type value
if ~ field eq .
rb sizeof.#name#field - ($-..field)
end if \\\\}
common \\\} \\} \} }
 
macro enable@substruct
{ macro make@substruct substruct,parent,name,[field,type,def]
\{ \common
\local define
define equ parent,name
\forward
\local sub
match , field \\{ match any, type \\\{ enable@substruct
make@substruct type,parent,sub def
purge make@substruct
define equ define,.,sub, \\\} \\}
match any, field \\{ define equ define,.\#field,type,<def> \\}
\common
match fields, define \\{ define@\#substruct fields \\} \} }
 
enable@substruct
 
macro define@union parent,name,[field,type,def]
{ common
virtual at parent#.#name
forward
if ~ field eq .
virtual at parent#.#name
parent#field type def
sizeof.#parent#field = $ - parent#field
end virtual
if sizeof.#parent#field > $ - parent#.#name
rb sizeof.#parent#field - ($ - parent#.#name)
end if
else
virtual at parent#.#name
label parent#.#type
type def
end virtual
label name#.#type at parent#.#name
if sizeof.#type > $ - parent#.#name
rb sizeof.#type - ($ - parent#.#name)
end if
end if
common
sizeof.#name = $ - parent#.#name
end virtual
struc name [value] \{ \common
label .\#name
last@union equ
forward
match any, last@union \\{ virtual at .\#name
field type def
end virtual \\}
match , last@union \\{ match , value \\\{ field type def \\\}
match any, value \\\{ field type value \\\} \\}
last@union equ field
common rb sizeof.#name - ($ - .\#name) \}
macro name [value] \{ \common \local ..anonymous
..anonymous name value \} }
 
macro define@substruct parent,name,[field,type,def]
{ common
virtual at parent#.#name
forward
if ~ field eq .
parent#field type def
sizeof.#parent#field = $ - parent#field
else
label parent#.#type
rb sizeof.#type
end if
common
sizeof.#name = $ - parent#.#name
end virtual
struc name value \{
label .\#name
forward
match , value \\{ field type def \\}
match any, value \\{ field type value
if ~ field eq .
rb sizeof.#parent#field - ($-field)
end if \\}
common \}
macro name value \{ \local ..anonymous
..anonymous name \} }
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/applications/config.inc
0,0 → 1,0
__CPU_type fix p5
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/applications/debug-fdo.inc
0,0 → 1,422
;
; Formatted Debug Output (FDO)
; Copyright (c) 2005-2006, mike.dld
; Created: 2005-01-29, Changed: 2006-11-10
;
; For questions and bug reports, mail to mike.dld@gmail.com
;
; Available format specifiers are: %s, %d, %u, %x (with partial width support)
;
 
; to be defined:
; __DEBUG__ equ 1
; __DEBUG_LEVEL__ equ 5
 
macro debug_func name {
if used name
name@of@func equ name
}
 
macro debug_beginf {
align 4
name@of@func:
}
 
debug_endf fix end if
 
macro DEBUGS _sign,[_str] {
common
local tp
tp equ 0
match _arg:_num,_str \{
DEBUGS_N _sign,_num,_arg
tp equ 1
\}
match =0 _arg,tp _str \{
DEBUGS_N _sign,,_arg
\}
}
 
macro DEBUGS_N _sign,_num,[_str] {
common
pushf
pushad
local ..str,..label,is_str
is_str = 0
forward
if _str eqtype ''
is_str = 1
end if
common
if is_str = 1
jmp ..label
..str db _str,0
..label:
add esp,4*8+4
mov edx,..str
sub esp,4*8+4
else
mov edx,_str
end if
if ~_num eq
if _num eqtype eax
if _num in <eax,ebx,ecx,edx,edi,ebp,esp>
mov esi,_num
else if ~_num eq esi
movzx esi,_num
end if
else if _num eqtype 0
mov esi,_num
else
local tp
tp equ 0
match [_arg],_num \{
mov esi,dword[_arg]
tp equ 1
\}
match =0 =dword[_arg],tp _num \{
mov esi,dword[_arg]
tp equ 1
\}
match =0 =word[_arg],tp _num \{
movzx esi,word[_arg]
tp equ 1
\}
match =0 =byte[_arg],tp _num \{
movzx esi,byte[_arg]
tp equ 1
\}
match =0,tp \{
'Error: specified string width is incorrect'
\}
end if
else
mov esi,0x7FFFFFFF
end if
call fdo_debug_outstr
popad
popf
}
 
macro DEBUGD _sign,_dec {
local tp
tp equ 0
match _arg:_num,_dec \{
DEBUGD_N _sign,_num,_arg
tp equ 1
\}
match =0 _arg,tp _dec \{
DEBUGD_N _sign,,_arg
\}
}
 
macro DEBUGD_N _sign,_num,_dec {
pushf
pushad
if (~_num eq)
if (_dec eqtype eax | _dec eqtype 0)
'Error: precision allowed only for in-memory variables'
end if
if (~_num in <1,2,4>)
if _sign
'Error: 1, 2 and 4 are only allowed for precision in %d'
else
'Error: 1, 2 and 4 are only allowed for precision in %u'
end if
end if
end if
if _dec eqtype eax
if _dec in <ebx,ecx,edx,esi,edi,ebp,esp>
mov eax,_dec
else if ~_dec eq eax
if _sign = 1
movsx eax,_dec
else
movzx eax,_dec
end if
end if
else if _dec eqtype 0
mov eax,_dec
else
add esp,4*8+4
if _num eq
mov eax,dword _dec
else if _num = 1
if _sign = 1
movsx eax,byte _dec
else
movzx eax,byte _dec
end if
else if _num = 2
if _sign = 1
movsx eax,word _dec
else
movzx eax,word _dec
end if
else
mov eax,dword _dec
end if
sub esp,4*8+4
end if
mov cl,_sign
call fdo_debug_outdec
popad
popf
}
 
macro DEBUGH _sign,_hex {
local tp
tp equ 0
match _arg:_num,_hex \{
DEBUGH_N _sign,_num,_arg
tp equ 1
\}
match =0 _arg,tp _hex \{
DEBUGH_N _sign,,_arg
\}
}
 
macro DEBUGH_N _sign,_num,_hex {
pushf
pushad
if (~_num eq) & (~_num in <1,2,3,4,5,6,7,8>)
'Error: 1..8 are only allowed for precision in %x'
end if
if _hex eqtype eax
if _hex in <eax,ebx,ecx,edx,esi,edi,ebp,esp>
if ~_hex eq eax
mov eax,_hex
end if
else if _hex in <ax,bx,cx,dx,si,di,bp,sp>
if ~_hex eq ax
movzx eax,_hex
end if
shl eax,16
if (_num eq)
mov edx,4
end if
else if _hex in <al,ah,bl,bh,cl,ch,dl,dh>
if ~_hex eq al
movzx eax,_hex
end if
shl eax,24
if (_num eq)
mov edx,2
end if
end if
else if _hex eqtype 0
mov eax,_hex
else
add esp,4*8+4
mov eax,dword _hex
sub esp,4*8+4
end if
if ~_num eq
mov edx,_num
else
mov edx,8
end if
call fdo_debug_outhex
popad
popf
}
 
;-----------------------------------------------------------------------------
 
debug_func fdo_debug_outchar
debug_beginf
pushad
mov cl,al
mov ebx,1
mov eax,63
mcall
popad
ret
debug_endf
 
debug_func fdo_debug_outstr
debug_beginf
mov eax,63
mov ebx,1
.l1: dec esi
js .l2
mov cl,[edx]
or cl,cl
jz .l2
mcall
inc edx
jmp .l1
.l2: ret
debug_endf
 
debug_func fdo_debug_outdec
debug_beginf
or cl,cl
jz @f
or eax,eax
jns @f
neg eax
push eax
mov al,'-'
call fdo_debug_outchar
pop eax
@@: push 10
pop ecx
push -'0'
.l1: xor edx,edx
div ecx
push edx
test eax,eax
jnz .l1
.l2: pop eax
add al,'0'
jz .l3
call fdo_debug_outchar
jmp .l2
.l3: ret
debug_endf
 
debug_func fdo_debug_outhex
__fdo_hexdigits db '0123456789ABCDEF'
debug_beginf
mov cl,dl
neg cl
add cl,8
shl cl,2
rol eax,cl
.l1: rol eax,4
push eax
and eax,0x0000000F
mov al,[__fdo_hexdigits+eax]
call fdo_debug_outchar
pop eax
dec edx
jnz .l1
ret
debug_endf
 
;-----------------------------------------------------------------------------
 
macro DEBUGF _level,_format,[_arg] {
common
if __DEBUG__ = 1 & _level >= __DEBUG_LEVEL__
local ..f1,f2,a1,a2,c1,c2,c3,..lbl
_debug_str_ equ __debug_str_ # a1
a1 = 0
c2 = 0
c3 = 0
f2 = 0
repeat ..lbl-..f1
virtual at 0
db _format,0,0
load c1 word from %-1
end virtual
if c1 = '%s'
virtual at 0
db _format,0,0
store word 0 at %-1
load c1 from f2-c2
end virtual
if c1 <> 0
DEBUGS 0,_debug_str_+f2-c2
end if
c2 = c2 + 1
f2 = %+1
DEBUGF_HELPER S,a1,0,_arg
else if c1 = '%x'
virtual at 0
db _format,0,0
store word 0 at %-1
load c1 from f2-c2
end virtual
if c1 <> 0
DEBUGS 0,_debug_str_+f2-c2
end if
c2 = c2 + 1
f2 = %+1
DEBUGF_HELPER H,a1,0,_arg
else if c1 = '%d' | c1 = '%u'
local c4
if c1 = '%d'
c4 = 1
else
c4 = 0
end if
virtual at 0
db _format,0,0
store word 0 at %-1
load c1 from f2-c2
end virtual
if c1 <> 0
DEBUGS 0,_debug_str_+f2-c2
end if
c2 = c2 + 1
f2 = %+1
DEBUGF_HELPER D,a1,c4,_arg
else if c1 = '\n'
c3 = c3 + 1
end if
end repeat
virtual at 0
db _format,0,0
load c1 from f2-c2
end virtual
if (c1<>0)&(f2<>..lbl-..f1-1)
DEBUGS 0,_debug_str_+f2-c2
end if
virtual at 0
..f1 db _format,0
..lbl:
__debug_strings equ __debug_strings,_debug_str_,<_format>,..lbl-..f1-1-c2-c3
end virtual
end if
}
 
macro __include_debug_strings dummy,[_id,_fmt,_len] {
common
local c1,a1,a2
forward
if defined _len & ~_len eq
_id:
a1 = 0
a2 = 0
repeat _len
virtual at 0
db _fmt,0,0
load c1 word from %+a2-1
end virtual
if (c1='%s')|(c1='%x')|(c1='%d')|(c1='%u')
db 0
a2 = a2 + 1
else if (c1='\n')
dw $0A0D
a1 = a1 + 1
a2 = a2 + 1
else
db c1 and 0x0FF
end if
end repeat
db 0
end if
}
 
macro DEBUGF_HELPER _letter,_num,_sign,[_arg] {
common
local num
num = 0
forward
if num = _num
DEBUG#_letter _sign,_arg
end if
num = num+1
common
_num = _num+1
}
 
macro include_debug_strings {
if __DEBUG__ = 1
match dbg_str,__debug_strings \{
__include_debug_strings dbg_str
\}
end if
}
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/applications/proc32.inc
0,0 → 1,270
 
; Macroinstructions for defining and calling procedures
 
macro stdcall proc,[arg] ; directly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call proc }
 
macro invoke proc,[arg] ; indirectly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call [proc] }
 
macro ccall proc,[arg] ; directly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call proc
if size@ccall
add esp,size@ccall
end if }
 
macro cinvoke proc,[arg] ; indirectly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call [proc]
if size@ccall
add esp,size@ccall
end if }
 
macro proc [args] ; define procedure
{ common
match name params, args>
\{ define@proc name,<params \} }
 
prologue@proc equ prologuedef
 
macro prologuedef procname,flag,parmbytes,localbytes,reglist
{ if parmbytes | localbytes
push ebp
mov ebp,esp
if localbytes
sub esp,localbytes
end if
end if
irps reg, reglist \{ push reg \} }
 
epilogue@proc equ epiloguedef
 
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
{ irps reg, reglist \{ reverse pop reg \}
if parmbytes | localbytes
leave
end if
if flag and 10000b
retn
else
retn parmbytes
end if }
 
macro define@proc name,statement
{ local params,flag,regs,parmbytes,localbytes,current
if used name
name:
match =stdcall args, statement \{ params equ args
flag = 11b \}
match =stdcall, statement \{ params equ
flag = 11b \}
match =c args, statement \{ params equ args
flag = 10001b \}
match =c, statement \{ params equ
flag = 10001b \}
match =params, params \{ params equ statement
flag = 0 \}
virtual at ebp+8
match =uses reglist=,args, params \{ regs equ reglist
params equ args \}
match =regs =uses reglist, regs params \{ regs equ reglist
params equ \}
match =regs, regs \{ regs equ \}
match =,args, params \{ defargs@proc args \}
match =args@proc args, args@proc params \{ defargs@proc args \}
parmbytes = $ - (ebp+8)
end virtual
name # % = parmbytes/4
all@vars equ
current = 0
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
macro locals
\{ virtual at ebp-localbytes+current
macro label def \\{ match . type,def> \\\{ deflocal@proc .,label,<type \\\} \\}
struc db [val] \\{ \common deflocal@proc .,db,val \\}
struc du [val] \\{ \common deflocal@proc .,du,val \\}
struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
macro endl
\{ purge label
restruc db,du,dw,dp,dd,dt,dq
restruc rb,rw,rp,rd,rt,rq
current = $-(ebp-localbytes)
end virtual \}
macro ret operand
\{ match any, operand \\{ retn operand \\}
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs>
\\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2
end if \} }
 
macro defargs@proc [arg]
{ common
if ~ arg eq
forward
local ..arg,current@arg
match argname:type, arg
\{ current@arg equ argname
label ..arg type
argname equ ..arg
if dqword eq type
dd ?,?,?,?
else if tbyte eq type
dd ?,?,?
else if qword eq type | pword eq type
dd ?,?
else
dd ?
end if \}
match =current@arg,current@arg
\{ current@arg equ arg
arg equ ..arg
..arg dd ? \}
common
args@proc equ current@arg
forward
restore current@arg
common
end if }
 
macro deflocal@proc name,def,[val]
{ common
match vars, all@vars \{ all@vars equ all@vars, \}
all@vars equ all@vars name
forward
local ..var,..tmp
match =label,def \{ ..tmp equ \}
match tmp,..tmp \{ ..var def val \}
match ,..tmp \{ label ..var val \}
match =?, val \{ ..tmp equ \}
match any =dup (=?), val \{ ..tmp equ \}
match tmp : value, ..tmp : val
\{ tmp: end virtual
initlocal@proc ..var,def value
virtual at tmp\}
common
match first rest, ..var, \{ name equ first \} }
 
macro initlocal@proc name,def
{ virtual at name
def
size@initlocal = $ - name
end virtual
position@initlocal = 0
while size@initlocal > position@initlocal
virtual at name
def
if size@initlocal - position@initlocal < 2
current@initlocal = 1
load byte@initlocal byte from name+position@initlocal
else if size@initlocal - position@initlocal < 4
current@initlocal = 2
load word@initlocal word from name+position@initlocal
else
current@initlocal = 4
load dword@initlocal dword from name+position@initlocal
end if
end virtual
if current@initlocal = 1
mov byte [name+position@initlocal],byte@initlocal
else if current@initlocal = 2
mov word [name+position@initlocal],word@initlocal
else
mov dword [name+position@initlocal],dword@initlocal
end if
position@initlocal = position@initlocal + current@initlocal
end while }
 
macro endp
{ purge ret,locals,endl
finish@proc
purge finish@proc
restore regs@proc
match all,args@proc \{ restore all \}
restore args@proc
match all,all@vars \{ restore all \} }
 
macro local [var]
{ common
locals
forward done@local equ
match varname[count]:vartype, var
\{ match =BYTE, vartype \\{ varname rb count
restore done@local \\}
match =WORD, vartype \\{ varname rw count
restore done@local \\}
match =DWORD, vartype \\{ varname rd count
restore done@local \\}
match =PWORD, vartype \\{ varname rp count
restore done@local \\}
match =QWORD, vartype \\{ varname rq count
restore done@local \\}
match =TBYTE, vartype \\{ varname rt count
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
rq count+count
restore done@local \\}
match , done@local \\{ virtual
varname vartype
end virtual
rb count*sizeof.\#vartype
restore done@local \\} \}
match :varname:vartype, done@local:var
\{ match =BYTE, vartype \\{ varname db ?
restore done@local \\}
match =WORD, vartype \\{ varname dw ?
restore done@local \\}
match =DWORD, vartype \\{ varname dd ?
restore done@local \\}
match =PWORD, vartype \\{ varname dp ?
restore done@local \\}
match =QWORD, vartype \\{ varname dq ?
restore done@local \\}
match =TBYTE, vartype \\{ varname dt ?
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
dq ?,?
restore done@local \\}
match , done@local \\{ varname vartype
restore done@local \\} \}
match ,done@local
\{ var
restore done@local \}
common
endl }
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/data32.inc
0,0 → 1,504
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
keymap:
 
db '6',27
db '1234567890-=',8,9
db 'qwertyuiop[]',13
db '~asdfghjkl;',39,96,0,'\zxcvbnm,./',0,'45 '
db '@234567890123',180,178,184,'6',176,'7'
db 179,'8',181,177,183,185,182
db 'AB<D',255,'FGHIJKLMNOPQRSTUVWXYZ'
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
 
keymap_shift:
db '6',27
db '!@#$%^&*()_+',8,9
db 'QWERTYUIOP{}',13
db '~ASDFGHJKL:"~',0,'|ZXCVBNM<>?',0,'45 '
db '@234567890123',180,178,184,'6',176,'7'
db 179,'8',181,177,183,185,182
db 'AB>D',255,'FGHIJKLMNOPQRSTUVWXYZ'
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
 
 
keymap_alt:
db ' ',27
db ' @ $ {[]}\ ',8,9
db ' ',13
db ' ',0,' ',0,'4',0,' '
db ' ',180,178,184,'6',176,'7'
db 179,'8',181,177,183,185,182
db 'ABCD',255,'FGHIJKLMNOPQRSTUVWXYZ'
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
 
 
 
if lang eq ru
boot_initirq db 'ˆ­¨æ¨ «¨§ æ¨ï IRQ',0
boot_picinit db 'ˆ­¨æ¨ «¨§ æ¨ï PIC',0
boot_v86machine db 'ˆ­¨æ¨ «¨§ æ¨ï á¨á⥬ë V86 ¬ è¨­ë',0
boot_inittimer db 'ˆ­¨æ¨ «¨§ æ¨ï á¨á⥬­®£® â ©¬¥à  (IRQ0)',0
boot_initapic db '®¯ë⪠ ¨­¨æ¨ «¨§ æ¨¨ APIC',0
boot_enableirq db '‚ª«îç¨âì ¯à¥à뢠­¨ï 2, 6, 13, 14, 15',0
boot_enablint_ide db ' §à¥è¥­¨¥ ¯à¥à뢠­¨© ¢ ª®­â஫«¥à¥ IDE',0
boot_detectfloppy db '®¨áª floppy ¤¨áª®¢®¤®¢',0
boot_detecthdcd db '®¨áª ¦¥áâª¨å ¤¨áª®¢ ¨ ATAPI ¯à¨¢®¤®¢',0
boot_getcache db '®«ã祭¨¥ ¯ ¬ï⨠¤«ï ªíè ',0
boot_detectpart db '®¨áª à §¤¥«®¢ ­  ¤¨áª®¢ëå ãáâனá⢠å',0
boot_init_sys db 'ˆ­¨æ¨ «¨§ æ¨ï á¨á⥬­®£® ª â «®£  /sys',0
boot_loadlibs db '‡ £à㧪  ¡¨¡«¨®â¥ª (.obj)',0
boot_memdetect db 'Š®«¨ç¥á⢮ ®¯¥à â¨¢­®© ¯ ¬ïâ¨',' ',' Œ¡',0
boot_tss db '“áâ ­®¢ª  TSSs',0
boot_cpuid db '—⥭¨¥ CPUIDs',0
; boot_devices db '®¨áª ãáâனáâ¢',0
boot_timer db '“áâ ­®¢ª  â ©¬¥à ',0
boot_irqs db '¥à¥®¯à¥¤¥«¥­¨¥ IRQ',0
boot_setmouse db '“áâ ­®¢ª  ¬ëè¨',0
boot_windefs db '“áâ ­®¢ª  ­ áâ஥ª ®ª®­ ¯® 㬮«ç ­¨î',0
boot_bgr db '“áâ ­®¢ª  ä®­ ',0
boot_resirqports db '¥§¥à¢¨à®¢ ­¨¥ IRQ ¨ ¯®à⮢',0
boot_setrports db '“áâ ­®¢ª   ¤à¥á®¢ IRQ',0
boot_setostask db '‘®§¤ ­¨¥ ¯à®æ¥áá  ï¤à ',0
boot_allirqs db 'Žâªàë⨥ ¢á¥å IRQ',0
boot_tsc db '—⥭¨¥ TSC',0
boot_cpufreq db '— áâ®â  ¯à®æ¥áá®à  ',' ',' Œƒæ',0
boot_pal_ega db '“áâ ­®¢ª  EGA/CGA 320x200 ¯ «¨âàë',0
boot_pal_vga db '“áâ ­®¢ª  VGA 640x480 ¯ «¨âàë',0
boot_failed db '‡ £à㧪  ¯¥à¢®£® ¯à¨«®¦¥­¨ï ­¥ 㤠« áì',0
boot_mtrr db '“áâ ­®¢ª  MTRR',0
boot_APIC_found db 'APIC ¢ª«î祭', 0
boot_APIC_nfound db 'APIC ­¥ ­ ©¤¥­', 0
if preboot_blogesc
boot_tasking db '‚ᥠ£®â®¢® ¤«ï § ¯ã᪠, ­ ¦¬¨âॠESC ¤«ï áâ àâ ',0
end if
else if lang eq sp
include 'data32sp.inc'
else
boot_initirq db 'Initialize IRQ',0
boot_picinit db 'Initialize PIC',0
boot_v86machine db 'Initialize system V86 machine',0
boot_inittimer db 'Initialize system timer (IRQ0)',0
boot_initapic db 'Try to initialize APIC',0
boot_enableirq db 'Enable interrupts 2, 6, 13, 14, 15',0
boot_enablint_ide db 'Enable interrupts in IDE controller',0
boot_detectfloppy db 'Search floppy drives',0
boot_detecthdcd db 'Search hard drives and ATAPI drives',0
boot_getcache db 'Get memory for cache',0
boot_detectpart db 'Search partitions on disk devices',0
boot_init_sys db 'Initialize system directory /sys',0
boot_loadlibs db 'Loading librares (.obj)',0
boot_memdetect db 'Determining amount of memory',0
boot_tss db 'Setting TSSs',0
boot_cpuid db 'Reading CPUIDs',0
; boot_devices db 'Detecting devices',0
boot_setmouse db 'Setting mouse',0
boot_windefs db 'Setting window defaults',0
boot_bgr db 'Calculating background',0
boot_resirqports db 'Reserving IRQs & ports',0
boot_setostask db 'Setting OS task',0
boot_allirqs db 'Unmasking IRQs',0
boot_tsc db 'Reading TSC',0
boot_cpufreq db 'CPU frequency is ',' ',' MHz',0
boot_pal_ega db 'Setting EGA/CGA 320x200 palette',0
boot_pal_vga db 'Setting VGA 640x480 palette',0
boot_failed db 'Failed to start first app',0
boot_mtrr db 'Setting MTRR',0
boot_APIC_found db 'APIC enabled', 0
boot_APIC_nfound db 'APIC not found', 0
if preboot_blogesc
boot_tasking db 'All set - press ESC to start',0
end if
end if
 
;new_process_loading db 'K : New Process - loading',13,10,0
;new_process_running db 'K : New Process - done',13,10,0
start_not_enough_memory db 'K : New Process - not enough memory',13,10,0
 
msg_unresolved db 'unresolved ',0
msg_module db 'in module ',0
if ~ lang eq sp
msg_version db 'incompatible driver version',13,10,0
msg_www db 'please visit www.kolibrios.org',13,10,0
end if
msg_CR db 13,10,0
 
intel_str db "GenuineIntel",0
AMD_str db "AuthenticAMD",0
 
szHwMouse db 'ATI2D',0
szPS2MDriver db 'PS2MOUSE',0
;szCOM_MDriver db 'COM_MOUSE',0
szUSB db 'USB',0
szAtiHW db '/rd/1/drivers/ati2d.drv',0
 
szSTART db 'START',0
szEXPORTS db 'EXPORTS',0
sz_EXPORTS db '_EXPORTS',0
 
szIMPORTS db 'IMPORTS',0
 
read_firstapp db '/sys/'
firstapp db 'LAUNCHER',0
notifyapp db '@notify',0
if lang eq ru
ud_user_message db 'Žè¨¡ª : ­¥¯®¤¤¥à¦¨¢ ¥¬ ï ¨­áâàãªæ¨ï ¯à®æ¥áá®à ',0
else if ~ lang eq sp
ud_user_message db 'Error: unsupported processor instruction',0
end if
 
bootpath db '/KOLIBRI '
bootpath2 db 0
vmode db '/sys/drivers/VMODE.MDR',0
;vrr_m db 'VRR_M',0
kernel_file db 'KERNEL MNT'
 
dev_data_path db '/RD/1/DRIVERS/DEVICES.DAT',0
 
align 4
 
shmem_list:
.bk dd shmem_list
.fd dd shmem_list
 
dll_list:
.bk dd dll_list
.fd dd dll_list
 
pcidev_list:
.bk dd pcidev_list
.fd dd pcidev_list
 
MAX_DEFAULT_DLL_ADDR = 0x80000000
MIN_DEFAULT_DLL_ADDR = 0x70000000
dll_cur_addr dd MIN_DEFAULT_DLL_ADDR
 
; supported videomodes
 
 
; mike.dld {
;db 0
;dd servetable-0x10000
;align 4
;draw_line dd __sys_draw_line
;draw_pointer dd __sys_draw_pointer
;//mike.dld, 2006-08-02 [
;;drawbar dd __sys_drawbar
;;drawbar dd __sys_drawbar.forced
;drawbar dd vesa20_drawbar
;//mike.dld, 2006-08-02 ]
;putpixel dd __sys_putpixel
; } mike.dld
 
 
align 4
keyboard dd 1
syslang dd 1
 
boot_y dd 10
 
pci_bios_entry dd 0
dw pci_code_sel
 
if __DEBUG__ eq 1
include_debug_strings
end if
 
IncludeIGlobals
 
align 16
gdts:
 
dw gdte-$-1
dd gdts
dw 0
 
; Attention! Do not change the order of the first four selectors. They are used in Fast System Call
; must be : os_code, os_data, app_code, app_data, ....
 
int_code_l:
os_code_l:
dw 0xffff
dw 0x0000
db 0x00
dw 11011111b *256 +10011010b
db 0x00
 
int_data_l:
os_data_l:
dw 0xffff
dw 0x0000
db 0x00
dw 11011111b *256 +10010010b
db 0x00
 
app_code_l:
dw 0xFFFF
dw 0
db 0
db cpl3
dw G32+D32+0xF;
 
app_data_l:
dw 0xFFFF
dw 0
db 0
db drw3
dw G32+D32+0xF;
 
; ------------- PCI BIOS ------------------
 
pci_code_32:
dw 0 ;lim 0-15
dw 0 ;base 0-15
db 0 ;base 16-23
db cpl0 ;type
db D32 ;lim 16-19+props
db 0 ;base 24-31
 
pci_data_32:
dw 0 ;lim 0-15
dw 0 ;base 0-15
db 0 ;base 16-23
db dpl0 ;type
db D32 ;lim 16-19+props
db 0 ;base 24-31
 
; --------------- APM ---------------------
apm_code_32:
dw 0x0f ; limit 64kb
db 0, 0, 0
dw 11010000b *256 +10011010b
db 0x00
apm_code_16:
dw 0x0f
db 0, 0, 0
dw 10010000b *256 +10011010b
db 0x00
apm_data_16:
dw 0x0f
db 0, 0, 0
dw 10010000b *256 +10010010b
db 0x00
; -----------------------------------------
 
graph_data_l:
 
dw 0x7ff
dw 0x0000
db 0x00
dw 11010000b *256 +11110010b
db 0x00
tss0_l:
dw sizeof.TSS-1
dw tss and 0xFFFF
db (tss shr 16) and 0xFF
db 10001001b
dw (tss shr 16) and 0xFF00
 
tls_data_l:
dw 0x0FFF
dw 0
db 0
db drw3
dw D32
 
endofcode:
gdte:
 
align 16
cur_saved_data:
rb 4096
fpu_data:
rb 512
 
mem_block_list rd 64*2
mem_used_list rd 64*2
mem_hash_cnt rd 64
 
heap_mutex MUTEX
heap_size rd 1
heap_free rd 1
heap_blocks rd 1
free_blocks rd 1
 
mem_block_mask rd 2
next_memblock rd 1
 
 
mst MEM_STATE
 
page_start rd 1
page_end rd 1
sys_page_map rd 1
os_stack_seg rd 1
 
 
srv.fd rd 1
srv.bk rd 1
 
 
align 16
 
_display display_t
 
_WinMapAddress rd 1
_WinMapSize rd 1
 
def_cursor rd 1
def_cursor_clock rd 1
current_cursor rd 1
hw_cursor rd 1
cur_saved_base rd 1
 
cur.lock rd 1 ;1 - lock update, 2- hide
cur.left rd 1 ;cursor clip box
cur.top rd 1
cur.right rd 1
cur.bottom rd 1
cur.w rd 1
cur.h rd 1
 
ipc_tmp rd 1
ipc_pdir rd 1
ipc_ptab rd 1
 
proc_mem_map rd 1
proc_mem_pdir rd 1
proc_mem_tab rd 1
 
tmp_task_pdir rd 1
tmp_task_ptab rd 1
 
default_io_map rd 1
 
LFBSize rd 1
 
stall_mcs rd 1
current_slot rd 1
 
; status
hd1_status rd 1 ; 0 - free : other - pid
application_table_status rd 1 ; 0 - free : other - pid
 
; device addresses
mididp rd 1
midisp rd 1
 
cdbase rd 1
cdid rd 1
 
hdbase rd 1 ; for boot 0x1f0
hdid rd 1
hdpos rd 1 ; for boot 0x1
label known_part dword
fat32part rd 1 ; for boot 0x1
cdpos rd 1
 
;CPUID information
cpu_vendor rd 3
cpu_sign rd 1
cpu_info rd 1
cpu_caps rd 4
 
 
pg_data PG_DATA
heap_test rd 1
 
buttontype rd 1
windowtypechanged rd 1
 
hd_entries rd 1 ;unused ? 0xfe10
 
mouse_active rd 1
mouse_pause rd 1
 
redrawmouse_unconditional rd 1
 
img_background rd 1
mem_BACKGROUND rd 1
static_background_data rd 1
 
cache_ide0:
cache_ide0_pointer rd 1
cache_ide0_size rd 1 ; not use
cache_ide0_data_pointer rd 1
cache_ide0_system_data_size rd 1 ; not use
cache_ide0_appl_data_size rd 1 ; not use
cache_ide0_system_data rd 1
cache_ide0_appl_data rd 1
cache_ide0_system_sad_size rd 1
cache_ide0_appl_sad_size rd 1
cache_ide0_search_start rd 1
cache_ide0_appl_search_start rd 1
 
cache_ide1:
cache_ide1_pointer rd 1
cache_ide1_size rd 1 ; not use
cache_ide1_data_pointer rd 1
cache_ide1_system_data_size rd 1 ; not use
cache_ide1_appl_data_size rd 1 ; not use
cache_ide1_system_data rd 1
cache_ide1_appl_data rd 1
cache_ide1_system_sad_size rd 1
cache_ide1_appl_sad_size rd 1
cache_ide1_search_start rd 1
cache_ide1_appl_search_start rd 1
 
cache_ide2:
cache_ide2_pointer rd 1
cache_ide2_size rd 1 ; not use
cache_ide2_data_pointer rd 1
cache_ide2_system_data_size rd 1 ; not use
cache_ide2_appl_data_size rd 1 ; not use
cache_ide2_system_data rd 1
cache_ide2_appl_data rd 1
cache_ide2_system_sad_size rd 1
cache_ide2_appl_sad_size rd 1
cache_ide2_search_start rd 1
cache_ide2_appl_search_start rd 1
 
cache_ide3:
cache_ide3_pointer rd 1
cache_ide3_size rd 1 ; not use
cache_ide3_data_pointer rd 1
cache_ide3_system_data_size rd 1 ; not use
cache_ide3_appl_data_size rd 1 ; not use
cache_ide3_system_data rd 1
cache_ide3_appl_data rd 1
cache_ide3_system_sad_size rd 1
cache_ide3_appl_sad_size rd 1
cache_ide3_search_start rd 1
cache_ide3_appl_search_start rd 1
 
debug_step_pointer rd 1
hdd_appl_data rb 1 ; 0 = system cache, 1 - application cache
cd_appl_data rb 1 ; 0 = system cache, 1 - application cache
 
lba_read_enabled rd 1 ; 0 = disabled , 1 = enabled
pci_access_enabled rd 1 ; 0 = disabled , 1 = enabled
timer_ticks_enable rb 1 ; for cd driver
 
NumBiosDisks rd 1
BiosDisksData rb 200h
BiosDiskCaches rb 80h*(cache_ide1-cache_ide0)
BiosDiskPartitions rd 80h
 
tetten:
IncludeUGlobals
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/gui/event.inc
0,0 → 1,615
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
WINDOW_MOVE_AND_RESIZE_FLAGS = \
mouse.WINDOW_RESIZE_N_FLAG + \
mouse.WINDOW_RESIZE_W_FLAG + \
mouse.WINDOW_RESIZE_S_FLAG + \
mouse.WINDOW_RESIZE_E_FLAG + \
mouse.WINDOW_MOVE_FLAG
 
uglobal
align 4
event_start dd ?
event_end dd ?
event_uid dd 0
endg
EV_SPACE = 512
FreeEvents = event_start-EVENT.fd ; "âèðòóàëüíûé" event, èñïîëüçóþòñÿ òîëüêî ïîëÿ:
; FreeEvents.fd=event_start è FreeEvents.bk=event_end
;-----------------------------------------------------------------------------
align 4
init_events: ;; used from kernel.asm
stdcall kernel_alloc, EV_SPACE*sizeof.EVENT
or eax, eax
jz .fail
; eax - current event, ebx - previos event below
mov ecx, EV_SPACE ; current - in allocated space
mov ebx, FreeEvents ; previos - íà÷àëî ñïèñêà
push ebx ; îíî æå è êîíåö ïîòîì áóäåò
;--------------------------------------
align 4
@@:
mov [ebx+EVENT.fd], eax
mov [eax+EVENT.bk], ebx
mov ebx, eax ; previos <- current
add eax, sizeof.EVENT ; new current
loop @b
pop eax ; âîò îíî êîíöîì è ñòàëî
mov [ebx+EVENT.fd], eax
mov [eax+EVENT.bk], ebx
;--------------------------------------
align 4
.fail:
ret
;-----------------------------------------------------------------------------
EVENT_WATCHED equ 0x10000000 ;áèò 28
EVENT_SIGNALED equ 0x20000000 ;áèò 29
MANUAL_RESET equ 0x40000000 ;áèò 30
MANUAL_DESTROY equ 0x80000000 ;áèò 31
;-----------------------------------------------------------------------------
align 4
create_event: ;; EXPORT use
;info:
; Ïåðåíîñèì EVENT èç ñïèñêà FreeEvents â ñïèñîê ObjList òåêóùåãî ñëîòà
; EVENT.state óñòàíàâëèâàåì èç ecx, EVENT.code êîñâåííî èç esi (åñëè esi<>0)
;param:
; esi - event data
; ecx - flags
;retval:
; eax - event (=0 => fail)
; edx - uid
;scratched: ebx,ecx,esi,edi
mov ebx, [current_slot]
add ebx, APP_OBJ_OFFSET
mov edx, [TASK_BASE]
mov edx, [edx+TASKDATA.pid]
pushfd
cli
;--------------------------------------
align 4
set_event: ;; INTERNAL use !!! don't use for Call
;info:
; Áåðåì íîâûé event èç FreeEvents, çàïîëíÿåì åãî ïîëÿ, êàê óêàçàíî â ecx,edx,esi
; è óñòàíàâëèâàåì â ñïèñîê, óêàçàííûé â ebx.
; Âîçâðàùàåì ñàì event (â eax), è åãî uid (â edx)
;param:
; ebx - start-chain "virtual" event for entry new event Right of him
; ecx - flags (copied to EVENT.state)
; edx - pid (copied to EVENT.pid)
; esi - event data (copied to EVENT.code indirect, =0 => skip)
;retval:
; eax - event (=0 => fail)
; edx - uid
;scratched: ebx,ecx,esi,edi
mov eax, FreeEvents
cmp eax, [eax+EVENT.fd]
jne @f ; not empty ???
pushad
call init_events
popad
jz RemoveEventTo.break ; POPF+RET
;--------------------------------------
align 4
@@:
mov eax, [eax+EVENT.fd]
mov [eax+EVENT.magic], 'EVNT'
mov [eax+EVENT.destroy], destroy_event.internal
mov [eax+EVENT.state], ecx
mov [eax+EVENT.pid], edx
inc [event_uid]
Mov [eax+EVENT.id],edx,[event_uid]
or esi, esi
jz RemoveEventTo
lea edi, [eax+EVENT.code]
mov ecx, (sizeof.EVENT -EVENT.code)/4
cld
rep movsd
;--------------------------------------
align 4
RemoveEventTo: ;; INTERNAL use !!! don't use for Call
;param:
; eax - óêàçàòåëü íà event, ÊÎÒÎÐÛÉ âñòàâëÿåì
; ebx - óêàçàòåëü íà event, ÏÎÑËÅ êîòîðîãî âñòàâëÿåì
;scratched: ebx,ecx
mov ecx, eax ; ecx=eax=Self, ebx=NewLeft
xchg ecx, [ebx+EVENT.fd] ; NewLeft.fd=Self, ecx=NewRight
cmp eax, ecx ; ñòîï, ñåáå äóìàþ...
je .break ; - à íå äóðàê ëè ÿ?
mov [ecx+EVENT.bk], eax ; NewRight.bk=Self
xchg ebx, [eax+EVENT.bk] ; Self.bk=NewLeft, ebx=OldLeft
xchg ecx, [eax+EVENT.fd] ; Self.fd=NewRight, ecx=OldRight
mov [ebx+EVENT.fd], ecx ; OldLeft.fd=OldRight
mov [ecx+EVENT.bk], ebx ; OldRight.bk=OldLeft
;--------------------------------------
align 4
.break:
popfd
ret
;-----------------------------------------------------------------------------
align 4
NotDummyTest: ;; INTERNAL use (not returned for fail !!!)
pop edi
call DummyTest ; not returned for fail !!!
mov ebx, eax
mov eax, [ebx+EVENT.pid]
push edi
;--------------------------------------
align 4
.small: ; êðèâî êàê-òî...
pop edi
pushfd
cli
call pid_to_slot ; saved all registers (eax - retval)
shl eax, 8
jz RemoveEventTo.break ; POPF+RET
jmp edi ; øòàòíûé âîçâðàò
;-----------------------------------------------------------------------------
align 4
raise_event: ;; EXPORT use
;info:
; Óñòàíàâëèâàåì äàííûå EVENT.code
; Åñëè òàì ôëàã EVENT_SIGNALED óæå àêòèâåí - áîëüøå íè÷åãî
; Èíà÷å: ýòîò ôëàã âçâîäèòñÿ, çà èñêëþ÷åíèåì ñëó÷àÿ íàëè÷èÿ ôëàãà EVENT_WATCHED â edx
;  ýòîì ñëó÷àå EVENT_SIGNALED âçâîäèòñÿ ëèøü ïðè íàëè÷èå EVENT_WATCHED â ñàìîì ñîáûòèè
;param:
; eax - event
; ebx - uid (for Dummy testing)
; edx - flags
; esi - event data (=0 => skip)
;scratched: ebx,ecx,esi,edi
call NotDummyTest ; not returned for fail !!!
or esi, esi
jz @f
lea edi, [ebx+EVENT.code]
mov ecx, (sizeof.EVENT -EVENT.code)/4
cld
rep movsd
;--------------------------------------
align 4
@@:
test byte[ebx+EVENT.state+3], EVENT_SIGNALED shr 24
jnz RemoveEventTo.break ; POPF+RET
bt edx, 28 ;EVENT_WATCHED
jnc @f
test byte[ebx+EVENT.state+3], EVENT_WATCHED shr 24
jz RemoveEventTo.break ; POPF+RET
;--------------------------------------
align 4
@@:
or byte[ebx+EVENT.state+3], EVENT_SIGNALED shr 24
add eax, SLOT_BASE+APP_EV_OFFSET
xchg eax, ebx
jmp RemoveEventTo
;-----------------------------------------------------------------------------
align 4
clear_event: ;; EXPORT use
;info:
;
;param:
; eax - event
; ebx - uid (for Dummy testing)
;scratched: ebx,ecx
call NotDummyTest ; not returned for fail !!!
add eax, SLOT_BASE+APP_OBJ_OFFSET
and byte[ebx+EVENT.state+3], not((EVENT_SIGNALED+EVENT_WATCHED)shr 24)
xchg eax, ebx
jmp RemoveEventTo
;-----------------------------------------------------------------------------
align 4
send_event: ;; EXPORT use
;info:
; Ñîçäàåò íîâûé EVENT (âûòàñêèâàåò èç ñïèñêà FreeEvents) â ñïèñêå EventList
; öåëåâîãî ñëîòà (eax=pid), ñ äàííûìè èç esi êîñâåííî, è state=EVENT_SIGNALED
;param:
; eax - slots pid, to sending new event
; esi - pointer to sending data (in code field of new event)
;retval:
; eax - event (=0 => fail)
; edx - uid
;warning:
; may be used as CDECL with such prefix...
; mov esi,[esp+8]
; mov eax,[esp+4]
; but not as STDCALL :(
;scratched: ebx,ecx,esi,edi
mov edx, eax
call NotDummyTest.small ; not returned for fail !!!
lea ebx, [eax+SLOT_BASE+APP_EV_OFFSET]
mov ecx, EVENT_SIGNALED
jmp set_event
;-----------------------------------------------------------------------------
align 4
DummyTest: ;; INTERNAL use (not returned for fail !!!)
;param:
; eax - event
; ebx - uid (for Dummy testing)
cmp [eax+EVENT.magic], 'EVNT'
jne @f
cmp [eax+EVENT.id], ebx
je .ret
;--------------------------------------
align 4
@@:
pop eax
xor eax, eax
;--------------------------------------
align 4
.ret:
ret
;-----------------------------------------------------------------------------
align 4
Wait_events:
or ebx, -1; infinite timeout
;--------------------------------------
align 4
Wait_events_ex:
;info:
; Îæèäàíèå "àáñòðàêòíîãî" ñîáûòèÿ ÷åðåç ïåðåâîä ñëîòà â 5-þ ïîçèöèþ.
; Àáñòðàêòíîñòü çàêëþ÷åíà â òîì, ÷òî ôàêò ñîáûòèÿ îïðåäåëÿåòñÿ ôóíêöèåé APPDATA.wait_test,
; êîòîðàÿ çàäàåòñÿ êëèåíòîì è ìîæåò áûòü ôàêòè÷åñêè ëþáîé.
; Ýòî ïîçâîëÿåò shed-ó íàäåæíî îïðåäåëèòü ôàêò ñîáûòèÿ, è íå ñîâåðøàòü "õîëîñòûõ" ïåðåêëþ÷åíèé,
; ïðåäíàçíà÷åííûõ äëÿ ðàçáîðîê òèïà "ñâîé/÷óæîé" âíóòðè çàäà÷è.
;param:
; edx - wait_test, êëèåíòñêàÿ ô-ÿ òåñòèðîâàíèÿ (àäðåñ êîäà)
; ecx - wait_param, äîïîëíèòåëüíûé ïàðàìåòð, âîçìîæíî íåîáõîäèìûé äëÿ [wait_test]
; ebx - wait_timeout
;retval:
; eax - ðåçóëüòàò âûçîâà [wait_test] (=0 => timeout)
;scratched: esi
mov esi, [current_slot]
mov [esi+APPDATA.wait_param], ecx
pushad
mov ebx, esi;ïîêà ýòî âîïðîñ, ÷åãî êóäû ñóâàòü..........
pushfd ; ýòî ñëåäñòâèå îáùåé êîíöåïöèè: ïóñòü ô-ÿ òåñòèðîâàíèÿ èìååò
cli ; ïðàâî ðàññ÷èòûâàòü íà çàêðûòûå ïðåðûâàíèÿ, êàê ïðè âûçîâå èç shed
call edx
popfd
mov [esp+28], eax
popad
or eax, eax
jnz @f ;RET
mov [esi+APPDATA.wait_test], edx
mov [esi+APPDATA.wait_timeout], ebx
Mov [esi+APPDATA.wait_begin],eax,[timer_ticks]
mov eax, [TASK_BASE]
mov [eax+TASKDATA.state], 5
call change_task
mov eax, [esi+APPDATA.wait_param]
;--------------------------------------
align 4
@@:
ret
;-----------------------------------------------------------------------------
align 4
wait_event: ;; EXPORT use
;info:
; Îæèäàíèå ôëàãà EVENT_SIGNALED â ñîâåðøåííî êîíêðåòíîì Event
; (óñòàíàâëèâàåìîãî, íàäî ïîëàãàòü, ÷åðåç raise_event)
; Ïðè àêòèâíîì ôëàãå MANUAL_RESET - áîëüøå íè÷åãî
; Èíà÷å: ôëàãè EVENT_SIGNALED è EVENT_WATCHED ó ïîëó÷åííîãî ñîáûòèÿ ñáðàñûâàþòñÿ,
; è, ïðè àêòèâíîì MANUAL_DESTROY - ïåðåìåùàåòñÿ â ñïèñîê ObjList òåêóùåãî ñëîòà,
; à ïðè íå àêòèâíîì - óíè÷òîæàåòñÿ øòàòíî (destroy_event.internal)
;param:
; eax - event
; ebx - uid (for Dummy testing)
;scratched: ecx,edx,esi
call DummyTest
mov ecx, eax ; wait_param
mov edx, get_event_alone ; wait_test
call Wait_events ; timeout ignored
jmp wait_finish
;-----------------------------------------------------------------------------
align 4
wait_event_timeout:
;param:
; eax - event
; ebx - uid (for Dummy testing)
; ecx - timeout in timer ticks
;retval:
; eax - EVENT handle or 0 if timeout
call DummyTest
mov ebx, ecx
mov ecx, eax ; wait_param
mov edx, get_event_alone ; wait_test
call Wait_events_ex
test eax, eax
jnz wait_finish
ret
;-----------------------------------------------------------------------------
align 4
get_event_ex: ;; f68:14
;info:
; Îæèäàíèå ëþáîãî ñîáûòèÿ â î÷åðåäè EventList òåêóùåãî ñëîòà
; Äàííûå ñîáûòèÿ code - êîïèðóþòñÿ â ïàìÿòü ïðèëîæåíèÿ (êîñâåííî ïî edi)
; Ïðè àêòèâíîì ôëàãå MANUAL_RESET - áîëüøå íè÷åãî
; Èíà÷å: ôëàãè EVENT_SIGNALED è EVENT_WATCHED ó ïîëó÷åííîãî ñîáûòèÿ ñáðàñûâàþòñÿ,
; è, ïðè àêòèâíîì MANUAL_DESTROY - ïåðåìåùàåòñÿ â ñïèñîê ObjList òåêóùåãî ñëîòà,
; à ïðè íå àêòèâíîì - óíè÷òîæàåòñÿ øòàòíî (destroy_event.internal)
;param:
; edi - àäðåñ â êîäå ïðèëîæåíèÿ äëÿ êîïèðîâàíèÿ äàííûõ èç EVENT.code
;retval:
; eax - ñîáñòâåííî EVENT (áóäåì íàçûâàòü ýòî åãî õýíäëîì)
;scratched: ebx,ecx,edx,esi,edi
mov edx, get_event_queue ; wait_test
call Wait_events ; timeout ignored
lea esi, [eax+EVENT.code]
mov ecx, (sizeof.EVENT-EVENT.code)/4
cld
rep movsd
mov byte[edi-(sizeof.EVENT-EVENT.code)+2], cl;clear priority field
;--------------------------------------
align 4
wait_finish:
test byte[eax+EVENT.state+3], MANUAL_RESET shr 24
jnz get_event_queue.ret ; RET
and byte[eax+EVENT.state+3], not((EVENT_SIGNALED+EVENT_WATCHED)shr 24)
test byte[eax+EVENT.state+3], MANUAL_DESTROY shr 24
jz destroy_event.internal
mov ebx, [current_slot]
add ebx, APP_OBJ_OFFSET
pushfd
cli
jmp RemoveEventTo
;-----------------------------------------------------------------------------
align 4
destroy_event: ;; EXPORT use
;info:
; Ïåðåíîñèì EVENT â ñïèñîê FreeEvents, ÷èñòèì ïîëÿ magic,destroy,pid,id
;param:
; eax - event
; ebx - uid (for Dummy testing)
;retval:
; eax - àäðåñ îáúåêòà EVENT (=0 => fail)
;scratched: ebx,ecx
call DummyTest ; not returned for fail !!!
;--------------------------------------
align 4
.internal:
xor ecx, ecx ; clear common header
pushfd
cli
mov [eax+EVENT.magic], ecx
mov [eax+EVENT.destroy], ecx
mov [eax+EVENT.pid], ecx
mov [eax+EVENT.id], ecx
mov ebx, FreeEvents
jmp RemoveEventTo
;-----------------------------------------------------------------------------
align 4
get_event_queue:
;info:
; êëèåíòñêàÿ ô-ÿ òåñòèðîâàíèÿ äëÿ get_event_ex
;warning:
; -don't use [TASK_BASE],[current_slot],[CURRENT_TASK] - it is not for your slot
; -may be assumed, that interrupt are disabled
; -it is not restriction for scratched registers
;param:
; ebx - àäðåñ APPDATA ñëîòà òåñòèðîâàíèÿ
;retval:
; eax - àäðåñ îáúåêòà EVENT (=0 => fail)
add ebx, APP_EV_OFFSET
mov eax, [ebx+APPOBJ.bk] ; âûáèðàåì ñ êîíöà, ïî ïðèíöèïó FIFO
cmp eax, ebx ; empty ???
je get_event_alone.ret0
;--------------------------------------
align 4
.ret:
ret
;-----------------------------------------------------------------------------
align 4
get_event_alone:
;info:
; êëèåíòñêàÿ ô-ÿ òåñòèðîâàíèÿ äëÿ wait_event
;warning:
; -don't use [TASK_BASE],[current_slot],[CURRENT_TASK] - it is not for your slot
; -may be assumed, that interrupt are disabled
; -it is not restriction for scratched registers
;param:
; ebx - àäðåñ APPDATA ñëîòà òåñòèðîâàíèÿ
;retval:
; eax - àäðåñ îáúåêòà EVENT (=0 => fail)
mov eax, [ebx+APPDATA.wait_param]
test byte[eax+EVENT.state+3], EVENT_SIGNALED shr 24
jnz .ret
or byte[eax+EVENT.state+3], EVENT_WATCHED shr 24
;--------------------------------------
align 4
.ret0:
xor eax, eax; NO event!!!
;--------------------------------------
align 4
.ret:
ret
;-----------------------------------------------------------------------------
align 4
sys_sendwindowmsg: ;; f72
dec ebx
jnz .ret ;subfunction==1 ?
pushfd
cli
sub ecx, 2
je .sendkey
dec ecx
jnz .retf
;--------------------------------------
align 4
.sendbtn:
cmp byte[BTN_COUNT], 1
jae .result ;overflow
inc byte[BTN_COUNT]
shl edx, 8
mov [BTN_BUFF], edx
jmp .result
;--------------------------------------
align 4
.sendkey:
movzx eax, byte[KEY_COUNT]
cmp al, 120
jae .result ;overflow
inc byte[KEY_COUNT]
mov [KEY_COUNT+1+eax], dl
;--------------------------------------
align 4
.result:
setae byte[esp+32] ;ñ÷èòàåì, ÷òî èñõîäíî: dword[esp+32]==72
;--------------------------------------
align 4
.retf:
popfd
;--------------------------------------
align 4
.ret:
ret
;-----------------------------------------------------------------------------
align 4
sys_getevent: ;; f11
mov ebx, [current_slot];ïîêà ýòî âîïðîñ, ÷åãî êóäû ñóâàòü..........
pushfd ; ýòî ñëåäñòâèå îáùåé êîíöåïöèè: ïóñòü ô-ÿ òåñòèðîâàíèÿ èìååò
cli ; ïðàâî ðàññ÷èòûâàòü íà çàêðûòûå ïðåðûâàíèÿ, êàê ïðè âûçîâå èç shed
call get_event_for_app
popfd
mov [esp+32], eax
ret
;-----------------------------------------------------------------------------
align 4
sys_waitforevent: ;; f10
or ebx, -1; infinite timeout
;--------------------------------------
align 4
sys_wait_event_timeout: ;; f23
call unprotect_from_terminate
mov edx, get_event_for_app; wait_test
call Wait_events_ex ; ebx - timeout
mov [esp+32], eax
call protect_from_terminate
ret
;-----------------------------------------------------------------------------
align 4
get_event_for_app: ;; used from f10,f11,f23
;info:
; êëèåíòñêàÿ ô-ÿ òåñòèðîâàíèÿ äëÿ ïðèëîæåíèé (f10,f23)
;warning:
; -don't use [TASK_BASE],[current_slot],[CURRENT_TASK] - it is not for your slot
; -may be assumed, that interrupt are disabled
; -it is not restriction for scratched registers
;param:
; ebx - àäðåñ APPDATA ñëîòà òåñòèðîâàíèÿ
;retval:
; eax - íîìåð ñîáûòèÿ (=0 => no events)
movzx edi, bh ; bh is assumed as [CURRENT_TASK]
shl edi, 5
add edi, CURRENT_TASK ; edi is assumed as [TASK_BASE]
mov ecx, [edi+TASKDATA.event_mask]
and ecx, 0x7FFFFFFF
;--------------------------------------
align 4
.loop: ; ïîêà íå èñ÷åðïàåì âñå áèòû ìàñêè
bsr eax, ecx ; íàõîäèì íåíóëåâîé áèò ìàñêè (31 -> 0)
jz .no_events ; èñ÷åðïàëè âñå áèòû ìàñêè, íî íè÷åãî íå íàøëè ???
btr ecx, eax ; ñáðàñûâàåì ïðîâåðÿåìûé áèò ìàñêè
; ïåðåõîäèì íà îáðàáîò÷èê ýòîãî (eax) áèòà
cmp eax, 10
jae .loop ; eax=[10..31], ignored (event 11...32)
 
cmp eax, 3
je .loop ; eax=3, ignored (event 4)
 
cmp eax, 4
je .FlagAutoReset ; eax=4, retvals=eax+1 (event 5)
 
cmp eax, 5
je .mouse_check ; eax=5, retvals=eax+1 (event 6)
 
ja .FlagAutoReset ; eax=[6..9], retvals=eax+1 (event 7...10)
 
cmp eax, 1
jae .BtKy ; eax=[1,2], retvals=eax+1 (event 2,3)
;--------------------------------------
align 4
.WndRedraw: ; eax=0, retval WndRedraw=1
cmp [edi-twdw+WDATA.fl_redraw], al;al==0
jne .result
jmp .loop
;--------------------------------------
align 4
.no_events:
xor eax, eax
ret
;--------------------------------------
align 4
.mouse_check: ; Mouse 5+1=6
push eax
mov eax, [TASK_BASE]
mov eax, [eax + TASKDATA.event_mask]
test eax, 0x80000000 ; bit 31: active/inactive filter f.40
jz @f
pop eax
jmp .FlagAutoReset
;--------------------------------------
align 4
@@:
; If the window is captured and moved by the user, then no mouse events!!!
mov al, [mouse.active_sys_window.action]
and al, WINDOW_MOVE_AND_RESIZE_FLAGS
test al, al
pop eax
jnz .loop
;--------------------------------------
align 4
.FlagAutoReset: ; retvals: BgrRedraw=5, IPC=7, Stack=8, Debug=9
btr [ebx+APPDATA.event_mask], eax
jnc .loop
;--------------------------------------
align 4
.result: ; retval = eax+1
inc eax
ret
;--------------------------------------
align 4
.BtKy:
movzx edx, bh
movzx edx, word[WIN_STACK+edx*2]
je .Keys ; eax=1, retval Keys=2
;--------------------------------------
align 4
.Buttons: ; eax=2, retval Buttons=3
cmp byte[BTN_COUNT], 0
je .loop ; empty ???
cmp edx, [TASK_COUNT]
jne .loop ; not Top ???
mov edx, [BTN_BUFF]
shr edx, 8
cmp edx, 0xFFFF ;-ID for Minimize-Button of Form
jne .result
mov [window_minimize], 1
dec byte[BTN_COUNT]
jmp .loop
;--------------------------------------
align 4
.Keys: ; eax==1
cmp edx, [TASK_COUNT]
jne @f ; not Top ???
cmp [KEY_COUNT], al; al==1
jae .result ; not empty ???
;--------------------------------------
align 4
@@:
mov edx, hotkey_buffer
;--------------------------------------
align 4
@@:
cmp [edx], bh ; bh - slot for testing
je .result
add edx, 8
cmp edx, hotkey_buffer+120*8
jb @b
jmp .loop
;end.
;-----------------------------------------------------------------------------
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/gui/font.inc
0,0 → 1,239
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
;------------------------------------------------------------------------------
align 4
dtext_asciiz_esi: ; for skins title out
push eax
xor eax, eax
inc eax
jmp dtext.1
;------------------------------------------------------------------------------
align 4
dtext:
; ebx x & y
; ecx style ( 0xX0000000 ) & color ( 0x00RRGGBB )
; X = ABnnb:
; nn = font
; A = 0 <=> output esi characters; otherwise output ASCIIZ string
; B = 1 <=> fill background with color eax
; edx start of text
; edi 1 force or user area for redirect
push eax
xor eax, eax
;--------------------------------------
align 4
.1:
pushad
movsx eax, bx ; eax=y
sar ebx, 16 ; ebx=x
xchg eax, ebx ; eax=x, ebx=y
cmp esi, 255
jb .loop
 
mov esi, 255
;--------------------------------------
align 4
.loop:
test ecx, ecx
js .test_asciiz
 
dec esi
js .end
 
jmp @f
;--------------------------------------
align 4
.test_asciiz:
cmp byte [edx], 0
jz .end
 
cmp byte [esp+28], 1
jne @f
 
dec esi
js .end
;--------------------------------------
align 4
@@:
inc edx
pushad
movzx edx, byte [edx-1]
test ecx, 0x10000000
jnz .font2
 
mov esi, 9
lea ebp, [FONT_I+8*edx+edx]
;--------------------------------------
align 4
.symloop1:
mov dl, byte [ebp]
or dl, 1 shl 6
;--------------------------------------
align 4
.pixloop1:
shr dl, 1
jz .pixloop1end
 
jnc .nopix
 
test ecx, 0x08000000 ; redirect the output to the user area
jz @f
 
call draw_text_to_user_area
jmp .pixloop1cont
;--------------------------------------
align 4
@@:
and ecx, 0xFBFFFFFF ;negate 0x04000000 save to mouseunder area
; call [putpixel]
call __sys_putpixel
jmp .pixloop1cont
;--------------------------------------
align 4
.nopix:
test ecx, 0x40000000
jz .pixloop1cont
 
push ecx
mov ecx, [esp+4+20h+20h]
 
test ecx, 0x08000000 ; redirect the output to the user area
jz @f
 
call draw_text_to_user_area
pop ecx
jmp .pixloop1cont
;--------------------------------------
align 4
@@:
and ecx, 0xFBFFFFFF ;negate 0x04000000 save to mouseunder area
; call [putpixel]
call __sys_putpixel
pop ecx
;--------------------------------------
align 4
.pixloop1cont:
inc eax
jmp .pixloop1
;--------------------------------------
align 4
.pixloop1end:
sub eax, 6
inc ebx
inc ebp
dec esi
jnz .symloop1
 
popad
add eax, 6
jmp .loop
;--------------------------------------
align 4
.font2:
add edx, edx
lea ebp, [FONT_II+4*edx+edx+1]
push 9
movzx esi, byte [ebp-1]
;--------------------------------------
align 4
.symloop2:
mov dl, byte [ebp]
push esi
;--------------------------------------
align 4
.pixloop2:
shr dl, 1
jnc .nopix2
 
test ecx, 0x08000000 ; redirect the output to the user area
jz @f
 
call draw_text_to_user_area
jmp .pixloop2cont
;--------------------------------------
align 4
@@:
and ecx, 0xFBFFFFFF ;negate 0x04000000 save to mouseunder area
; call [putpixel]
call __sys_putpixel
jmp .pixloop2cont
;--------------------------------------
align 4
.nopix2:
test ecx, 0x40000000
jz .pixloop2cont
 
push ecx
mov ecx, [esp+12+20h+20h]
 
test ecx, 0x08000000 ; redirect the output to the user area
jz @f
 
call draw_text_to_user_area
pop ecx
jmp .pixloop2cont
;--------------------------------------
align 4
@@:
and ecx, 0xFBFFFFFF ;negate 0x04000000 save to mouseunder area
; call [putpixel]
call __sys_putpixel
pop ecx
;--------------------------------------
align 4
.pixloop2cont:
inc eax
dec esi
jnz .pixloop2
 
pop esi
sub eax, esi
inc ebx
inc ebp
dec dword [esp]
jnz .symloop2
 
pop eax
add dword [esp+28], esi
popad
jmp .loop
;--------------------------------------
align 4
.end:
popad
pop eax
ret
;------------------------------------------------------------------------------
; eax = x coordinate
; ebx = y coordinate
; ecx = ?? RR GG BB
; edi = user area
align 4
draw_text_to_user_area:
pushad
imul ebx, [edi+0]
add eax, ebx
shl eax, 2
add eax, edi
add eax, 8
and ecx, 0xffffff
or ecx, 0xff000000 ; not transparent
mov [eax], ecx ; store pixel
popad
ret
;------------------------------------------------------------------------------
align 4
FONT_I:
file 'char.mt'
;------------------------------------------------------------------------------
align 4
FONT_II:
file 'char2.mt'
;------------------------------------------------------------------------------
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/gui/mouse.inc
0,0 → 1,718
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
include 'mousepointer.inc'
 
;==============================================================================
;///// public functions ///////////////////////////////////////////////////////
;==============================================================================
 
mouse.LEFT_BUTTON_FLAG = 0001b
mouse.RIGHT_BUTTON_FLAG = 0010b
mouse.MIDDLE_BUTTON_FLAG = 0100b
 
mouse.BUTTONS_MASK = \
mouse.LEFT_BUTTON_FLAG or \
mouse.RIGHT_BUTTON_FLAG or \
mouse.MIDDLE_BUTTON_FLAG
 
mouse.WINDOW_RESIZE_N_FLAG = 000001b
mouse.WINDOW_RESIZE_W_FLAG = 000010b
mouse.WINDOW_RESIZE_S_FLAG = 000100b
mouse.WINDOW_RESIZE_E_FLAG = 001000b
mouse.WINDOW_MOVE_FLAG = 010000b
 
mouse.WINDOW_RESIZE_SW_FLAG = \
mouse.WINDOW_RESIZE_S_FLAG or \
mouse.WINDOW_RESIZE_W_FLAG
mouse.WINDOW_RESIZE_SE_FLAG = \
mouse.WINDOW_RESIZE_S_FLAG or \
mouse.WINDOW_RESIZE_E_FLAG
 
align 4
;------------------------------------------------------------------------------
mouse_check_events: ;//////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? Check if mouse buttons state or cursor position has changed and call
;? appropriate handlers
;------------------------------------------------------------------------------
push eax ebx
 
mov al, [BTN_DOWN]
mov bl, [mouse.state.buttons]
and al, mouse.BUTTONS_MASK
mov cl, al
xchg cl, [mouse.state.buttons]
xor bl, al
push eax ebx
 
; did any mouse button changed its state?
or bl, bl
jz .check_position
 
; yes it did, is that the first button of all pressed down?
or cl, cl
jnz .check_buttons_released
 
; yes it is, activate window user is pointing at, if needed
call mouse._.activate_sys_window_under_cursor
 
; NOTE: this code wouldn't be necessary if we knew window did
; already redraw itself after call above
or eax, eax
jz @f
 
and [mouse.state.buttons], 0
jmp .exit
 
; is there any system button under cursor?
@@:
call mouse._.find_sys_button_under_cursor
or eax, eax
jz .check_buttons_released
 
; yes there is, activate it and exit
mov [mouse.active_sys_button.pbid], eax
mov [mouse.active_sys_button.coord], ebx
mov cl, [mouse.state.buttons]
mov [mouse.active_sys_button.buttons], cl
call sys_button_activate_handler
jmp .exit
 
.check_buttons_released:
cmp [mouse.state.buttons], 0
jnz .buttons_changed
 
; did we press some button earlier?
cmp [mouse.active_sys_button.pbid], 0
je .buttons_changed
 
; yes we did, deactivate it
xor eax, eax
xchg eax, [mouse.active_sys_button.pbid]
mov ebx, [mouse.active_sys_button.coord]
mov cl, [mouse.active_sys_button.buttons]
push eax ebx
call sys_button_deactivate_handler
pop edx ecx
 
; is the button under cursor the one we deactivated?
call mouse._.find_sys_button_under_cursor
cmp eax, ecx
jne .exit
cmp ebx, edx
jne .exit
 
; yes it is, perform associated action
mov cl, [mouse.active_sys_button.buttons]
call sys_button_perform_handler
jmp .exit
 
.buttons_changed:
test byte[esp], mouse.LEFT_BUTTON_FLAG
jz @f
mov eax, [esp + 4]
call .call_left_button_handler
 
@@:
test byte[esp], mouse.RIGHT_BUTTON_FLAG
jz @f
mov eax, [esp + 4]
call .call_right_button_handler
 
@@:
test byte[esp], mouse.MIDDLE_BUTTON_FLAG
jz .check_position
mov eax, [esp + 4]
call .call_middle_button_handler
 
.check_position:
movzx eax, word[MOUSE_X]
movzx ebx, word[MOUSE_Y]
cmp eax, [mouse.state.pos.x]
jne .position_changed
cmp ebx, [mouse.state.pos.y]
je .exit
 
.position_changed:
xchg eax, [mouse.state.pos.x]
xchg ebx, [mouse.state.pos.y]
 
call mouse._.move_handler
 
.exit:
add esp, 8
pop ebx eax
ret
 
.call_left_button_handler:
test eax, mouse.LEFT_BUTTON_FLAG
jnz mouse._.left_button_press_handler
jmp mouse._.left_button_release_handler
 
.call_right_button_handler:
test eax, mouse.RIGHT_BUTTON_FLAG
jnz mouse._.right_button_press_handler
jmp mouse._.right_button_release_handler
 
.call_middle_button_handler:
test eax, mouse.MIDDLE_BUTTON_FLAG
jnz mouse._.middle_button_press_handler
jmp mouse._.middle_button_release_handler
 
;==============================================================================
;///// private functions //////////////////////////////////////////////////////
;==============================================================================
 
uglobal
mouse.state:
.pos POINT
.buttons db ?
 
; NOTE: since there's no unique and lifetime-constant button identifiers,
; we're using two dwords to identify each of them:
; * pbid - process slot (high 8 bits) and button id (low 24 bits) pack
; * coord - left (high 16 bits) and top (low 16 bits) coordinates pack
align 4
mouse.active_sys_button:
.pbid dd ?
.coord dd ?
.buttons db ?
 
align 4
mouse.active_sys_window:
.pslot dd ?
.old_box BOX
.new_box BOX
.delta POINT
.last_ticks dd ?
.action db ?
endg
 
align 4
;------------------------------------------------------------------------------
mouse._.left_button_press_handler: ;///////////////////////////////////////////
;------------------------------------------------------------------------------
;? Called when left mouse button has been pressed down
;------------------------------------------------------------------------------
test [mouse.state.buttons], not mouse.LEFT_BUTTON_FLAG
jnz .exit
 
call mouse._.find_sys_window_under_cursor
call mouse._.check_sys_window_actions
mov [mouse.active_sys_window.action], al
or eax, eax
jz .exit
 
xchg eax, edx
test dl, mouse.WINDOW_MOVE_FLAG
jz @f
 
mov eax, [timer_ticks]
mov ebx, eax
xchg ebx, [mouse.active_sys_window.last_ticks]
sub eax, ebx
cmp eax, 50
jg @f
 
mov [mouse.active_sys_window.last_ticks], 0
call sys_window_maximize_handler
jmp .exit
 
@@:
test [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED
jnz .exit
mov [mouse.active_sys_window.pslot], esi
lea eax, [edi + WDATA.box]
mov ebx, mouse.active_sys_window.old_box
mov ecx, sizeof.BOX
call memmove
mov ebx, mouse.active_sys_window.new_box
call memmove
test edx, mouse.WINDOW_MOVE_FLAG
jz @f
 
call .calculate_n_delta
call .calculate_w_delta
jmp .call_window_handler
 
@@:
test dl, mouse.WINDOW_RESIZE_W_FLAG
jz @f
call .calculate_w_delta
 
@@:
test dl, mouse.WINDOW_RESIZE_S_FLAG
jz @f
call .calculate_s_delta
 
@@:
test dl, mouse.WINDOW_RESIZE_E_FLAG
jz .call_window_handler
call .calculate_e_delta
 
.call_window_handler:
; mov eax, mouse.active_sys_window.old_box
; call sys_window_start_moving_handler
 
.exit:
ret
 
.calculate_n_delta:
mov eax, [mouse.state.pos.y]
sub eax, [mouse.active_sys_window.old_box.top]
mov [mouse.active_sys_window.delta.y], eax
ret
 
.calculate_w_delta:
mov eax, [mouse.state.pos.x]
sub eax, [mouse.active_sys_window.old_box.left]
mov [mouse.active_sys_window.delta.x], eax
ret
 
.calculate_s_delta:
mov eax, [mouse.active_sys_window.old_box.top]
add eax, [mouse.active_sys_window.old_box.height]
sub eax, [mouse.state.pos.y]
mov [mouse.active_sys_window.delta.y], eax
ret
 
.calculate_e_delta:
mov eax, [mouse.active_sys_window.old_box.left]
add eax, [mouse.active_sys_window.old_box.width]
sub eax, [mouse.state.pos.x]
mov [mouse.active_sys_window.delta.x], eax
ret
 
align 4
;------------------------------------------------------------------------------
mouse._.left_button_release_handler: ;/////////////////////////////////////////
;------------------------------------------------------------------------------
;? Called when left mouse button has been released
;------------------------------------------------------------------------------
xor esi, esi
xchg esi, [mouse.active_sys_window.pslot]
or esi, esi
jz .exit
 
mov eax, esi
shl eax, 5
add eax, window_data + WDATA.box
mov ebx, mouse.active_sys_window.old_box
mov ecx, sizeof.BOX
call memmove
 
mov eax, mouse.active_sys_window.old_box
mov ebx, mouse.active_sys_window.new_box
call sys_window_end_moving_handler
 
.exit:
and [mouse.active_sys_window.action], 0
ret
 
align 4
;------------------------------------------------------------------------------
mouse._.right_button_press_handler: ;//////////////////////////////////////////
;------------------------------------------------------------------------------
;? Called when right mouse button has been pressed down
;------------------------------------------------------------------------------
test [mouse.state.buttons], not mouse.RIGHT_BUTTON_FLAG
jnz .exit
 
call mouse._.find_sys_window_under_cursor
call mouse._.check_sys_window_actions
test al, mouse.WINDOW_MOVE_FLAG
jz .exit
 
call sys_window_rollup_handler
 
.exit:
ret
 
align 4
;------------------------------------------------------------------------------
mouse._.right_button_release_handler: ;////////////////////////////////////////
;------------------------------------------------------------------------------
;? Called when right mouse button has been released
;------------------------------------------------------------------------------
ret
 
align 4
;------------------------------------------------------------------------------
mouse._.middle_button_press_handler: ;/////////////////////////////////////////
;------------------------------------------------------------------------------
;? Called when middle mouse button has been pressed down
;------------------------------------------------------------------------------
ret
 
align 4
;------------------------------------------------------------------------------
mouse._.middle_button_release_handler: ;///////////////////////////////////////
;------------------------------------------------------------------------------
;? Called when middle mouse button has been released
;------------------------------------------------------------------------------
ret
 
align 4
;------------------------------------------------------------------------------
mouse._.move_handler: ;////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? Called when cursor has been moved
;------------------------------------------------------------------------------
;> eax = old x coord
;> ebx = old y coord
;------------------------------------------------------------------------------
cmp [mouse.active_sys_button.pbid], 0
jnz .exit
 
mov esi, [mouse.active_sys_window.pslot]
or esi, esi
jz .exit
 
mov eax, mouse.active_sys_window.new_box
mov ebx, mouse.active_sys_window.old_box
mov ecx, sizeof.BOX
call memmove
 
mov dl, [mouse.active_sys_window.action]
test dl, mouse.WINDOW_MOVE_FLAG
jz .check_resize_w
 
mov eax, [mouse.state.pos.x]
sub eax, [mouse.active_sys_window.delta.x]
mov [mouse.active_sys_window.new_box.left], eax
mov eax, [mouse.state.pos.y]
sub eax, [mouse.active_sys_window.delta.y]
mov [mouse.active_sys_window.new_box.top], eax
 
mov eax, [mouse.active_sys_window.new_box.left]
or eax, eax
jge @f
xor eax, eax
mov [mouse.active_sys_window.new_box.left], eax
@@:
add eax, [mouse.active_sys_window.new_box.width]
cmp eax, [Screen_Max_X]
jl @f
sub eax, [Screen_Max_X]
sub [mouse.active_sys_window.new_box.left], eax
@@:
mov eax, [mouse.active_sys_window.new_box.top]
or eax, eax
jge @f
xor eax, eax
mov [mouse.active_sys_window.new_box.top], eax
@@:
add eax, [mouse.active_sys_window.new_box.height]
cmp eax, [Screen_Max_Y]
jle .call_window_handler
sub eax, [Screen_Max_Y]
sub [mouse.active_sys_window.new_box.top], eax
jmp .call_window_handler
 
.check_resize_w:
test dl, mouse.WINDOW_RESIZE_W_FLAG
jz .check_resize_s
 
mov eax, [mouse.state.pos.x]
sub eax, [mouse.active_sys_window.delta.x]
mov [mouse.active_sys_window.new_box.left], eax
sub eax, [mouse.active_sys_window.old_box.left]
sub [mouse.active_sys_window.new_box.width], eax
 
mov eax, [mouse.active_sys_window.new_box.width]
sub eax, 127
jge @f
add [mouse.active_sys_window.new_box.left], eax
mov [mouse.active_sys_window.new_box.width], 127
@@:
mov eax, [mouse.active_sys_window.new_box.left]
or eax, eax
jge .check_resize_s
add [mouse.active_sys_window.new_box.width], eax
xor eax, eax
mov [mouse.active_sys_window.new_box.left], eax
 
.check_resize_s:
test dl, mouse.WINDOW_RESIZE_S_FLAG
jz .check_resize_e
 
mov eax, [mouse.state.pos.y]
add eax, [mouse.active_sys_window.delta.y]
sub eax, [mouse.active_sys_window.old_box.top]
mov [mouse.active_sys_window.new_box.height], eax
 
push eax
mov edi, esi
shl edi, 5
add edi, window_data
call window._.get_rolledup_height
mov ecx, eax
pop eax
mov eax, [mouse.active_sys_window.new_box.height]
cmp eax, ecx
jge @f
mov eax, ecx
mov [mouse.active_sys_window.new_box.height], eax
@@:
add eax, [mouse.active_sys_window.new_box.top]
cmp eax, [Screen_Max_Y]
jle .check_resize_e
sub eax, [Screen_Max_Y]
neg eax
add [mouse.active_sys_window.new_box.height], eax
mov ecx, [Screen_Max_Y]
cmp ecx, eax
jge .check_resize_e
mov [mouse.active_sys_window.new_box.height], ecx
 
.check_resize_e:
test dl, mouse.WINDOW_RESIZE_E_FLAG
jz .call_window_handler
 
mov eax, [mouse.state.pos.x]
add eax, [mouse.active_sys_window.delta.x]
sub eax, [mouse.active_sys_window.old_box.left]
mov [mouse.active_sys_window.new_box.width], eax
 
mov eax, [mouse.active_sys_window.new_box.width]
cmp eax, 127
jge @f
mov eax, 127
mov [mouse.active_sys_window.new_box.width], eax
@@:
add eax, [mouse.active_sys_window.new_box.left]
cmp eax, [Screen_Max_X]
jle .call_window_handler
sub eax, [Screen_Max_X]
neg eax
add [mouse.active_sys_window.new_box.width], eax
mov ecx, [Screen_Max_X]
cmp ecx, eax
jge .call_window_handler
mov [mouse.active_sys_window.new_box.width], ecx
 
.call_window_handler:
mov eax, mouse.active_sys_window.old_box
mov ebx, mouse.active_sys_window.new_box
 
push esi
mov esi, mouse.active_sys_window.old_box
mov edi, mouse.active_sys_window.new_box
mov ecx, sizeof.BOX / 4
repe
cmpsd
pop esi
je .exit
 
mov [mouse.active_sys_window.last_ticks], 0
call sys_window_moving_handler
 
.exit:
ret
 
align 4
;------------------------------------------------------------------------------
mouse._.find_sys_window_under_cursor: ;////////////////////////////////////////
;------------------------------------------------------------------------------
;? Find system window object which is currently visible on screen and has
;? mouse cursor within its bounds
;------------------------------------------------------------------------------
;< esi = process slot
;< edi = pointer to WDATA struct
;------------------------------------------------------------------------------
; mov esi, [Screen_Max_X]
; inc esi
; imul esi, [mouse.state.pos.y]
mov esi, [mouse.state.pos.y]
mov esi, [d_width_calc_area + esi*4]
 
add esi, [_WinMapAddress]
add esi, [mouse.state.pos.x]
movzx esi, byte[esi]
mov edi, esi
shl edi, 5
add edi, window_data
ret
 
align 4
;------------------------------------------------------------------------------
mouse._.activate_sys_window_under_cursor: ;////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
; activate and redraw window under cursor (if necessary)
call mouse._.find_sys_window_under_cursor
movzx esi, word[WIN_STACK + esi * 2]
lea esi, [WIN_POS + esi * 2]
jmp waredraw
 
align 4
;------------------------------------------------------------------------------
mouse._.find_sys_button_under_cursor: ;////////////////////////////////////////
;------------------------------------------------------------------------------
;? Find system button object which is currently visible on screen and has
;? mouse cursor within its bounds
;------------------------------------------------------------------------------
;< eax = pack[8(process slot), 24(button id)] or 0
;< ebx = pack[16(button x coord), 16(button y coord)]
;------------------------------------------------------------------------------
push ecx edx esi edi
 
call mouse._.find_sys_window_under_cursor
mov edx, esi
 
; check if any process button contains cursor
mov eax, [BTN_ADDR]
mov ecx, [eax]
imul esi, ecx, sizeof.SYS_BUTTON
add esi, eax
inc ecx
add esi, sizeof.SYS_BUTTON
 
.next_button:
dec ecx
jz .not_found
 
add esi, -sizeof.SYS_BUTTON
 
; does it belong to our process?
cmp dx, [esi + SYS_BUTTON.pslot]
jne .next_button
 
; does it contain cursor coordinates?
mov eax, [mouse.state.pos.x]
sub eax, [edi + WDATA.box.left]
sub ax, [esi + SYS_BUTTON.left]
jl .next_button
sub ax, [esi + SYS_BUTTON.width]
jge .next_button
mov eax, [mouse.state.pos.y]
sub eax, [edi + WDATA.box.top]
sub ax, [esi + SYS_BUTTON.top]
jl .next_button
sub ax, [esi + SYS_BUTTON.height]
jge .next_button
 
; okay, return it
shl edx, 24
mov eax, dword[esi + SYS_BUTTON.id_hi - 2]
mov ax, [esi + SYS_BUTTON.id_lo]
and eax, 0x0ffffff
or eax, edx
mov ebx, dword[esi + SYS_BUTTON.left - 2]
mov bx, [esi + SYS_BUTTON.top]
jmp .exit
 
.not_found:
xor eax, eax
xor ebx, ebx
 
.exit:
pop edi esi edx ecx
ret
 
align 4
;------------------------------------------------------------------------------
mouse._.check_sys_window_actions: ;////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
;< eax = action flags or 0
;------------------------------------------------------------------------------
; is window movable?
test byte[edi + WDATA.cl_titlebar + 3], 0x01
jnz .no_action
 
mov eax, [mouse.state.pos.x]
mov ebx, [mouse.state.pos.y]
sub eax, [edi + WDATA.box.left]
sub ebx, [edi + WDATA.box.top]
 
; is there a window titlebar under cursor?
push eax
call window._.get_titlebar_height
cmp ebx, eax
pop eax
jl .move_action
 
; no there isn't, can it be resized then?
mov dl, [edi + WDATA.fl_wstyle]
and dl, 0x0f
; NOTE: dangerous optimization, revise if window types changed;
; this currently implies only types 2 and 3 could be resized
test dl, 2
jz .no_action
 
mov ecx, [edi + WDATA.box.width]
add ecx, -window.BORDER_SIZE
mov edx, [edi + WDATA.box.height]
add edx, -window.BORDER_SIZE
 
; is it rolled up?
test [edi + WDATA.fl_wstate], WSTATE_ROLLEDUP
jnz .resize_w_or_e_action
 
cmp eax, window.BORDER_SIZE
jl .resize_w_action
cmp eax, ecx
jg .resize_e_action
cmp ebx, edx
jle .no_action
 
.resize_s_action:
cmp eax, window.BORDER_SIZE + 10
jl .resize_sw_action
add ecx, -10
cmp eax, ecx
jge .resize_se_action
mov eax, mouse.WINDOW_RESIZE_S_FLAG
jmp .exit
 
.resize_w_or_e_action:
cmp eax, window.BORDER_SIZE + 10
jl .resize_w_action.direct
add ecx, -10
cmp eax, ecx
jg .resize_e_action.direct
jmp .no_action
 
.resize_w_action:
add edx, -10
cmp ebx, edx
jge .resize_sw_action
.resize_w_action.direct:
mov eax, mouse.WINDOW_RESIZE_W_FLAG
jmp .exit
 
.resize_e_action:
add edx, -10
cmp ebx, edx
jge .resize_se_action
.resize_e_action.direct:
mov eax, mouse.WINDOW_RESIZE_E_FLAG
jmp .exit
 
.resize_sw_action:
mov eax, mouse.WINDOW_RESIZE_SW_FLAG
jmp .exit
 
.resize_se_action:
mov eax, mouse.WINDOW_RESIZE_SE_FLAG
jmp .exit
 
.move_action:
mov eax, mouse.WINDOW_MOVE_FLAG
jmp .exit
 
.no_action:
xor eax, eax
 
.exit:
ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/gui/mousepointer.inc
0,0 → 1,250
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 2288 $
 
 
iglobal
 
align 4
mousepointer:
db 0x00,0x00,0x00,0x74,0x74,0x74,0x6e,0x6e,0x6e,0x6f
db 0x6f,0x6f,0x71,0x71,0x71,0x75,0x75,0x75,0x79,0x79
db 0x79,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80,0x80
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
db 0x80,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63
db 0x66,0x66,0x66,0x6c,0x6c,0x6c,0x72,0x72,0x72,0x78
db 0x78,0x78,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xc0
db 0xc0,0xc0,0x00,0x00,0x00,0x54,0x54,0x54,0x57,0x57
db 0x57,0x5f,0x5f,0x5f,0x68,0x68,0x68,0x71,0x71,0x71
db 0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xc0,0xc0,0xc0
db 0xc0,0xc0,0xc0,0x00,0x00,0x00,0x47,0x47,0x47,0x50
db 0x50,0x50,0x5b,0x5b,0x5b,0x67,0x67,0x67,0x70,0x70
db 0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
db 0x80,0x80,0x80,0x80,0x80,0xff,0xff,0xff,0xc0,0xc0
db 0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x3f,0x3f,0x3f
db 0x4b,0x4b,0x4b,0x59,0x59,0x59,0x66,0x66,0x66,0x70
db 0x70,0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e
db 0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
db 0x80,0x80,0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0
db 0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x3a,0x3a
db 0x3a,0x49,0x49,0x49,0x59,0x59,0x59,0x66,0x66,0x66
db 0x70,0x70,0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e
db 0x7e,0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
db 0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0
db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x39
db 0x39,0x39,0x49,0x49,0x49,0x59,0x59,0x59,0x66,0x66
db 0x66,0x71,0x71,0x71,0x78,0x78,0x78,0x7c,0x7c,0x7c
db 0x7e,0x7e,0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0xff
db 0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0
db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00
db 0x39,0x39,0x39,0x4a,0x4a,0x4a,0x5a,0x5a,0x5a,0x68
db 0x68,0x68,0x72,0x72,0x72,0x79,0x79,0x79,0x7d,0x7d
db 0x7d,0x7f,0x7f,0x7f,0x80,0x80,0x80,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0
db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00
db 0x00,0x3c,0x3c,0x3c,0x4e,0x4e,0x4e,0x5e,0x5e,0x5e
db 0x6b,0x6b,0x6b,0x75,0x75,0x75,0x7a,0x7a,0x7a,0x7e
db 0x7e,0x7e,0x80,0x80,0x80,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0
db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00
db 0x00,0x00,0x43,0x43,0x43,0x55,0x55,0x55,0x64,0x64
db 0x64,0x70,0x70,0x70,0x78,0x78,0x78,0x7d,0x7d,0x7d
db 0x80,0x80,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xc0
db 0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x4e,0x4e,0x4e,0x5f,0x5f,0x5f,0x6d
db 0x6d,0x6d,0x76,0x76,0x76,0x7c,0x7c,0x7c,0x80,0x80
db 0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00
db 0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x14
db 0x14,0x14,0x1b,0x1b,0x1b,0x29,0x29,0x29,0x3a,0x3a
db 0x3a,0x4c,0x4c,0x4c,0x5d,0x5d,0x5d,0x6c,0x6c,0x6c
db 0x75,0x75,0x75,0x7b,0x7b,0x7b,0x80,0x80,0x80,0xc0
db 0xc0,0xc0,0x00,0x00,0x00,0x2f,0x2f,0x2f,0x80,0x80
db 0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00
db 0x21,0x21,0x21,0x2e,0x2e,0x2e,0x40,0x40,0x40,0x52
db 0x52,0x52,0x62,0x62,0x62,0x6f,0x6f,0x6f,0x77,0x77
db 0x77,0x7c,0x7c,0x7c,0x80,0x80,0x80,0x00,0x00,0x00
db 0x47,0x47,0x47,0x3b,0x3b,0x3b,0x80,0x80,0x80,0xff
db 0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x25,0x25
db 0x25,0x30,0x30,0x30,0x42,0x42,0x42,0x54,0x54,0x54
db 0x64,0x64,0x64,0x70,0x70,0x70,0x78,0x78,0x78,0x7d
db 0x7d,0x7d,0x00,0x00,0x00,0x62,0x62,0x62,0x52,0x52
db 0x52,0x4a,0x4a,0x4a,0x43,0x43,0x43,0x80,0x80,0x80
db 0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x33
db 0x33,0x33,0x42,0x42,0x42,0x54,0x54,0x54,0x64,0x64
db 0x64,0x71,0x71,0x71,0x79,0x79,0x79,0x7d,0x7d,0x7d
db 0x72,0x72,0x72,0x6b,0x6b,0x6b,0x5f,0x5f,0x5f,0x5a
db 0x5a,0x5a,0x54,0x54,0x54,0x80,0x80,0x80,0xff,0xff
db 0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x35,0x35,0x35
db 0x41,0x41,0x41,0x53,0x53,0x53,0x63,0x63,0x63,0x70
db 0x70,0x70,0x78,0x78,0x78,0x7d,0x7d,0x7d,0x77,0x77
db 0x77,0x73,0x73,0x73,0x6c,0x6c,0x6c,0x68,0x68,0x68
db 0x62,0x62,0x62,0x5a,0x5a,0x5a,0x80,0x80,0x80,0xff
db 0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x41,0x41
db 0x41,0x52,0x52,0x52,0x62,0x62,0x62,0x6f,0x6f,0x6f
db 0x78,0x78,0x78,0x7d,0x7d,0x7d,0x7b,0x7b,0x7b,0x79
db 0x79,0x79,0x74,0x74,0x74,0x72,0x72,0x72,0x6e,0x6e
db 0x6e,0x66,0x66,0x66,0x80,0x80,0x80,0xc0,0xc0,0xc0
db 0xc0,0xc0,0xc0,0x00,0x00,0x00,0x44,0x44,0x44,0x52
db 0x52,0x52,0x62,0x62,0x62,0x6e,0x6e,0x6e,0x77,0x77
db 0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x7c,0x7c,0x7c
db 0x7a,0x7a,0x7a,0x79,0x79,0x79,0x75,0x75,0x75,0x6f
db 0x6f,0x6f,0x65,0x65,0x65,0x00,0x00,0x00,0x00,0x00
db 0x00,0x48,0x48,0x48,0x4b,0x4b,0x4b,0x56,0x56,0x56
db 0x65,0x65,0x65,0x70,0x70,0x70,0x78,0x78,0x78,0x7d
db 0x7d,0x7d,0x80,0x80,0x80,0x7f,0x7f,0x7f,0x7e,0x7e
db 0x7e,0x7d,0x7d,0x7d,0x7a,0x7a,0x7a,0x76,0x76,0x76
db 0x6f,0x6f,0x6f,0x65,0x65,0x65,0x5c,0x5c,0x5c,0x56
db 0x56,0x56,0x58,0x58,0x58,0x60,0x60,0x60,0x6b,0x6b
db 0x6b,0x73,0x73,0x73,0x7a,0x7a,0x7a,0x7d,0x7d,0x7d
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x7f
db 0x7f,0x7f,0x7d,0x7d,0x7d,0x7a,0x7a,0x7a,0x76,0x76
db 0x76,0x70,0x70,0x70,0x6a,0x6a,0x6a,0x66,0x66,0x66
db 0x66,0x66,0x66,0x6c,0x6c,0x6c,0x72,0x72,0x72,0x78
db 0x78,0x78,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
db 0x7f,0x7f,0x7f,0x7d,0x7d,0x7d,0x7b,0x7b,0x7b,0x77
db 0x77,0x77,0x73,0x73,0x73,0x71,0x71,0x71,0x71,0x71
db 0x71,0x74,0x74,0x74,0x78,0x78,0x78,0x7b,0x7b,0x7b
db 0x7d,0x7d,0x7d,0x7f,0x7f,0x7f,0x80,0x80,0x80,0x80
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
db 0x80,0x7f,0x7f,0x7f,0x7d,0x7d,0x7d,0x7c,0x7c,0x7c
db 0x7a,0x7a,0x7a,0x78,0x78,0x78,0x78,0x78,0x78,0x7a
db 0x7a,0x7a,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x7f,0x7f
db 0x7f,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
db 0x80,0x80,0x7f,0x7f,0x7f,0x7e,0x7e,0x7e,0x7e,0x7e
db 0x7e,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e
db 0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x80,0x80,0x80,0x80
db 0x80,0x80
 
mousepointer1:
db 0xff,0xff,0xff,0x06,0x06,0x06,0x0a,0x0a
db 0x0a,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x19,0x16
db 0x16,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2e,0x2e,0x2e
db 0x23,0x23,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x3f
db 0x3f,0x29,0x29,0x29,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x47
db 0x47,0x47,0x2c,0x2c,0x2c,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0x48,0x48,0x48,0x2c,0x2c,0x2c,0x16,0x16,0x16,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x16,0x16,0x16
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0x47,0x47,0x47,0x29,0x29,0x29
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0x40,0x40,0x40,0x23,0x23
db 0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xaa,0xaa,0xaa,0x9f,0x9f,0x9f,0x8c,0x8c,0x8c
db 0x70,0x70,0x70,0x4f,0x4f,0x4f,0x30,0x30,0x30,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8f,0x8f,0x8f
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0xff,0x9c,0x9c,0x9c,0x87,0x87,0x87,0x6c,0x6c
db 0x6c,0x4f,0x4f,0x4f,0x32,0x32,0x32,0x19,0x19,0x19
db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff
db 0xff,0xff,0x69,0x69,0x69,0x84,0x84,0x84,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0x92,0x92,0x92,0x79,0x79,0x79,0x59,0x59,0x59,0x3c
db 0x3c,0x3c,0x24,0x24,0x24,0x11,0x11,0x11,0x00,0x00
db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x37,0x37,0x37
db 0x5d,0x5d,0x5d,0x70,0x70,0x70,0x76,0x76,0x76,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0xff,0x75,0x75,0x75,0x51,0x51,0x51,0x31,0x31,0x31
db 0x19,0x19,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x16,0x16,0x16,0x2d,0x2d,0x2d,0x49,0x49
db 0x49,0x53,0x53,0x53,0x54,0x54,0x54,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x78
db 0x78,0x78,0x54,0x54,0x54,0x30,0x30,0x30,0x16,0x16
db 0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x0f,0x0f,0x0f,0x1f,0x1f,0x1f,0x30,0x30,0x30,0x33
db 0x33,0x33,0x33,0x33,0x33,0x3b,0x3b,0x3b,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
db 0x62,0x62,0x62,0x3b,0x3b,0x3b,0x1c,0x1c,0x1c,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08
db 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x24,0x24,0x24,0xff,0xff,0xff,0xff
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x6e,0x6e
db 0x6e,0x48,0x48,0x48,0x25,0x25,0x25,0x0e,0x0e,0x0e
db 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x00
db 0x00,0x00,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x00,0x00
db 0x00,0x00,0x00,0x00,0x29,0x29,0x29,0xff,0xff,0xff
db 0xff,0xff,0xff,0x7c,0x7c,0x7c,0x71,0x71,0x71,0x50
db 0x50,0x50,0x2b,0x2b,0x2b,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x02,0x02,0x02,0x04,0x04,0x04,0x00
db 0x00,0x00,0x00,0x00,0x00,0x36,0x36,0x36,0x56,0x56
db 0x56,0x69,0x69,0x69,0x64,0x64,0x64,0x4a,0x4a,0x4a
db 0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x05,0x05,0x05
db 0x00,0x00,0x00,0x21,0x21,0x21,0x39,0x39,0x39,0x49
db 0x49,0x49,0x48,0x48,0x48,0x35,0x35,0x35,0x1d,0x1d
db 0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00
db 0x00,0x00,0x00,0x00,0x1d,0x1d,0x1d,0x27,0x27,0x27
db 0x27,0x27,0x27,0x1d,0x1d,0x1d,0x0f,0x0f,0x0f,0x06
db 0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 0x00,0x00,0x00,0x00
 
endg
/kernel/branches/net/gui/window.inc
0,0 → 1,2421
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
;==============================================================================
;///// public functions ///////////////////////////////////////////////////////
;==============================================================================
 
window.BORDER_SIZE = 5
 
macro FuncTable name, table_name, [label]
{
common
align 4
\label name#.#table_name dword
forward
dd name#.#label
common
name#.sizeof.#table_name = $ - name#.#table_name
}
 
uglobal
common_colours rd 32
draw_limits RECT
endg
 
align 4
;------------------------------------------------------------------------------
syscall_draw_window: ;///// system function 0 /////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
mov eax, edx
shr eax, 24
and al, 0x0f
cmp al, 5
jae .exit
 
push eax
call window._.sys_set_window
pop eax
 
or al, al
jnz @f
 
; type I - original style
call drawwindow_I
jmp window._.draw_window_caption.2
;--------------------------------------
align 4
@@:
dec al
jnz @f
 
; type II - only reserve area, no draw
; call sys_window_mouse
; call [draw_pointer]
call __sys_draw_pointer
jmp .exit
;--------------------------------------
align 4
@@:
dec al
jnz @f
 
; type III - new style
call drawwindow_III
jmp window._.draw_window_caption.2
 
; type IV & V - skinned window (resizable & not)
;--------------------------------------
align 4
@@:
mov eax, [TASK_COUNT]
movzx eax, word[WIN_POS + eax * 2]
cmp eax, [CURRENT_TASK]
setz al
movzx eax, al
push eax
call drawwindow_IV
jmp window._.draw_window_caption.2
;--------------------------------------
align 4
.exit:
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
syscall_display_settings: ;///// system function 48 ///////////////////////////
;------------------------------------------------------------------------------
;; Redraw screen:
;< ebx = 0
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;; Set button style:
;< ebx = 1
;< ecx = 0 (flat) or 1 (with gradient)
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;; Set system color palette:
;< ebx = 2
;< ecx = pointer to color table
;< edx = size of color table
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;; Get system color palette:
;< ebx = 3
;< ecx = pointer to color table buffer
;< edx = size of color table buffer
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;; Get skinned caption height:
;< ebx = 4
;> eax = height in pixels
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;; Get screen working area:
;< ebx = 5
;> eax = pack[16(left), 16(right)]
;> ebx = pack[16(top), 16(bottom)]
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;; Set screen working area:
;< ebx = 6
;< ecx = pack[16(left), 16(right)]
;< edx = pack[16(top), 16(bottom)]
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;; Get skin margins:
;< ebx = 7
;> eax = pack[16(left), 16(right)]
;> ebx = pack[16(top), 16(bottom)]
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;; Set skin:
;< ebx = 8
;< ecx = pointer to FileInfoBlock struct
;> eax = FS error code
;------------------------------------------------------------------------------
cmp ebx, .sizeof.ftable / 4
ja @f
jmp [.ftable + ebx * 4]
;--------------------------------------
align 4
@@:
ret
;------------------------------------------------------------------------------
align 4
syscall_display_settings.00:
xor eax, eax
inc ebx
cmp [windowtypechanged], ebx
jne .exit
mov [windowtypechanged], eax
 
jmp syscall_display_settings._.redraw_whole_screen
;--------------------------------------
align 4
.exit:
ret
;------------------------------------------------------------------------------
align 4
syscall_display_settings.01:
and ecx, 1
cmp ecx, [buttontype]
je .exit
mov [buttontype], ecx
mov [windowtypechanged], ebx
;--------------------------------------
align 4
.exit:
ret
;------------------------------------------------------------------------------
align 4
syscall_display_settings.02:
dec ebx
mov esi, ecx
and edx, 127
mov edi, common_colours
mov ecx, edx
rep movsb
mov [windowtypechanged], ebx
ret
;------------------------------------------------------------------------------
align 4
syscall_display_settings.03:
mov edi, ecx
and edx, 127
mov esi, common_colours
mov ecx, edx
rep movsb
ret
;------------------------------------------------------------------------------
align 4
syscall_display_settings.04:
mov eax, [_skinh]
mov [esp + 32], eax
ret
;------------------------------------------------------------------------------
align 4
syscall_display_settings.05:
mov eax, [screen_workarea.left - 2]
mov ax, word[screen_workarea.right]
mov [esp + 32], eax
mov eax, [screen_workarea.top - 2]
mov ax, word[screen_workarea.bottom]
mov [esp + 20], eax
ret
;------------------------------------------------------------------------------
align 4
syscall_display_settings.06:
xor esi, esi
 
mov edi, [Screen_Max_X]
mov eax, ecx
movsx ebx, ax
sar eax, 16
cmp eax, ebx
jge .check_horizontal
inc esi
or eax, eax
jge @f
xor eax, eax
;--------------------------------------
align 4
@@:
mov [screen_workarea.left], eax
cmp ebx, edi
jle @f
mov ebx, edi
;--------------------------------------
align 4
@@:
mov [screen_workarea.right], ebx
;--------------------------------------
align 4
.check_horizontal:
mov edi, [Screen_Max_Y]
mov eax, edx
movsx ebx, ax
sar eax, 16
cmp eax, ebx
jge .check_if_redraw_needed
inc esi
or eax, eax
jge @f
xor eax, eax
;--------------------------------------
align 4
@@:
mov [screen_workarea.top], eax
cmp ebx, edi
jle @f
mov ebx, edi
;--------------------------------------
align 4
@@:
mov [screen_workarea.bottom], ebx
;--------------------------------------
align 4
.check_if_redraw_needed:
or esi, esi
jz .exit
 
call repos_windows
jmp syscall_display_settings._.calculate_whole_screen
;--------------------------------------
align 4
.exit:
ret
;------------------------------------------------------------------------------
align 4
syscall_display_settings.07:
mov eax, [_skinmargins + 0]
mov [esp + 32], eax
mov eax, [_skinmargins + 4]
mov [esp + 20], eax
ret
;------------------------------------------------------------------------------
align 4
syscall_display_settings.08:
mov ebx, ecx
call read_skin_file
mov [esp + 32], eax
test eax, eax
jnz .exit
 
call syscall_display_settings._.calculate_whole_screen
jmp syscall_display_settings._.redraw_whole_screen
;--------------------------------------
align 4
.exit:
ret
;------------------------------------------------------------------------------
align 4
syscall_display_settings._.calculate_whole_screen:
xor eax, eax
xor ebx, ebx
mov ecx, [Screen_Max_X]
mov edx, [Screen_Max_Y]
jmp calculatescreen
;------------------------------------------------------------------------------
align 4
syscall_display_settings._.redraw_whole_screen:
xor eax, eax
mov [draw_limits.left], eax
mov [draw_limits.top], eax
mov eax, [Screen_Max_X]
mov [draw_limits.right], eax
mov eax, [Screen_Max_Y]
mov [draw_limits.bottom], eax
mov eax, window_data
jmp redrawscreen
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
syscall_set_window_shape: ;///// system function 50 ///////////////////////////
;------------------------------------------------------------------------------
;; Set window shape address:
;> ebx = 0
;> ecx = shape data address
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;; Set window shape scale:
;> ebx = 1
;> ecx = scale power (resulting scale is 2^ebx)
;------------------------------------------------------------------------------
mov edi, [current_slot]
 
test ebx, ebx
jne .shape_scale
mov [edi + APPDATA.wnd_shape], ecx
;--------------------------------------
align 4
.shape_scale:
dec ebx
jnz .exit
mov [edi + APPDATA.wnd_shape_scale], ecx
;--------------------------------------
align 4
.exit:
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
syscall_move_window: ;///// system function 67 ////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
mov edi, [CURRENT_TASK]
shl edi, 5
add edi, window_data
 
test [edi + WDATA.fl_wdrawn], 1
jz .exit
 
test [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED
jnz .exit
 
cmp ebx, -1
jne @f
mov ebx, [edi + WDATA.box.left]
;--------------------------------------
align 4
@@:
cmp ecx, -1
jne @f
mov ecx, [edi + WDATA.box.top]
;--------------------------------------
align 4
@@:
cmp edx, -1
jne @f
mov edx, [edi + WDATA.box.width]
;--------------------------------------
align 4
@@:
cmp esi, -1
jne @f
mov esi, [edi + WDATA.box.height]
;--------------------------------------
align 4
@@:
push esi edx ecx ebx
mov eax, esp
mov bl, [edi + WDATA.fl_wstate]
call window._.set_window_box
add esp, sizeof.BOX
 
; NOTE: do we really need this? to be reworked
; mov byte[DONT_DRAW_MOUSE], 0 ; mouse pointer
; mov byte[MOUSE_BACKGROUND], 0 ; no mouse under
; mov byte[MOUSE_DOWN], 0 ; react to mouse up/down
 
; NOTE: do we really need this? to be reworked
; call [draw_pointer]
;--------------------------------------
align 4
.exit:
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
syscall_window_settings: ;///// system function 71 /////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
dec ebx ; subfunction #1 - set window caption
jnz .exit_fail
 
; 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 * 8 + SLOT_BASE + APPDATA.wnd_caption], ecx
or [edi + window_data + WDATA.fl_wstyle], WSTYLE_HASCAPTION
 
call window._.draw_window_caption
 
xor eax, eax ; eax = 0 (success)
ret
 
; .get_window_caption:
; dec eax ; subfunction #2 - get window caption
; jnz .exit_fail
 
; not implemented yet
;--------------------------------------
align 4
.exit_fail:
xor eax, eax
inc eax ; eax = 1 (fail)
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
set_window_defaults: ;/////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
mov byte [window_data + 0x20 + WDATA.cl_titlebar + 3], 1 ; desktop is not movable
push eax ecx
xor eax, eax
mov ecx, WIN_STACK
;--------------------------------------
align 4
@@:
inc eax
add ecx, 2
; process no
mov [ecx + 0x000], ax
; positions in stack
mov [ecx + 0x400], ax
cmp ecx, WIN_POS - 2
jne @b
pop ecx eax
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
calculatescreen: ;/////////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? Scan all windows from bottom to top, calling `setscreen` for each one
;? intersecting given screen area
;------------------------------------------------------------------------------
;> eax = left
;> ebx = top
;> ecx = right
;> edx = bottom
;------------------------------------------------------------------------------
push esi
pushfd
cli
 
mov esi, 1
call window._.set_screen
 
push ebp
 
mov ebp, [TASK_COUNT]
cmp ebp, 1
jbe .exit
 
push edx ecx ebx eax
;--------------------------------------
align 4
.next_window:
movzx edi, word[WIN_POS + esi * 2]
shl edi, 5
 
cmp [CURRENT_TASK + edi + TASKDATA.state], TSTATE_FREE
je .skip_window
 
add edi, window_data
test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED
jnz .skip_window
 
mov eax, [edi + WDATA.box.left]
cmp eax, [esp + RECT.right]
jg .skip_window
mov ebx, [edi + WDATA.box.top]
cmp ebx, [esp + RECT.bottom]
jg .skip_window
mov ecx, [edi + WDATA.box.width]
add ecx, eax
cmp ecx, [esp + RECT.left]
jl .skip_window
mov edx, [edi + WDATA.box.height]
add edx, ebx
cmp edx, [esp + RECT.top]
jl .skip_window
 
cmp eax, [esp + RECT.left]
jae @f
mov eax, [esp + RECT.left]
;--------------------------------------
align 4
@@:
cmp ebx, [esp + RECT.top]
jae @f
mov ebx, [esp + RECT.top]
;--------------------------------------
align 4
@@:
cmp ecx, [esp + RECT.right]
jbe @f
mov ecx, [esp + RECT.right]
;--------------------------------------
align 4
@@:
cmp edx, [esp + RECT.bottom]
jbe @f
mov edx, [esp + RECT.bottom]
;--------------------------------------
align 4
@@:
push esi
movzx esi, word[WIN_POS + esi * 2]
call window._.set_screen
pop esi
;--------------------------------------
align 4
.skip_window:
inc esi
dec ebp
jnz .next_window
 
pop eax ebx ecx edx
;--------------------------------------
align 4
.exit:
pop ebp
inc [_display.mask_seqno]
popfd
pop esi
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
repos_windows: ;///////////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
mov ecx, [TASK_COUNT]
mov edi, window_data + sizeof.WDATA * 2
call force_redraw_background
dec ecx
jle .exit
;--------------------------------------
align 4
.next_window:
mov [edi + WDATA.fl_redraw], 1
test [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED
jnz .fix_maximized
 
mov eax, [edi + WDATA.box.left]
add eax, [edi + WDATA.box.width]
mov ebx, [Screen_Max_X]
cmp eax, ebx
jle .fix_vertical
mov eax, [edi + WDATA.box.width]
sub eax, ebx
jle @f
mov [edi + WDATA.box.width], ebx
;--------------------------------------
align 4
@@:
sub ebx, [edi + WDATA.box.width]
mov [edi + WDATA.box.left], ebx
;--------------------------------------
align 4
.fix_vertical:
mov eax, [edi + WDATA.box.top]
add eax, [edi + WDATA.box.height]
mov ebx, [Screen_Max_Y]
cmp eax, ebx
jle .fix_client_box
mov eax, [edi + WDATA.box.height]
sub eax, ebx
jle @f
mov [edi + WDATA.box.height], ebx
;--------------------------------------
align 4
@@:
sub ebx, [edi + WDATA.box.height]
mov [edi + WDATA.box.top], ebx
;--------------------------------------
align 4
.fix_client_box:
call window._.set_window_clientbox
add edi, sizeof.WDATA
loop .next_window
;--------------------------------------
align 4
.exit:
ret
;--------------------------------------
align 4
.fix_maximized:
mov eax, [screen_workarea.left]
mov [edi + WDATA.box.left], eax
sub eax, [screen_workarea.right]
neg eax
mov [edi + WDATA.box.width], eax
mov eax, [screen_workarea.top]
mov [edi + WDATA.box.top], eax
test [edi + WDATA.fl_wstate], WSTATE_ROLLEDUP
jnz .fix_client_box
sub eax, [screen_workarea.bottom]
neg eax
mov [edi + WDATA.box.height], eax
jmp .fix_client_box
;------------------------------------------------------------------------------
;align 4
;------------------------------------------------------------------------------
;sys_window_mouse: ;////////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
; NOTE: commented out since doesn't provide necessary functionality
; anyway, to be reworked
; push eax
;
; mov eax, [timer_ticks]
; cmp [new_window_starting], eax
; jb .exit
;
; mov byte[MOUSE_BACKGROUND], 0
; mov byte[DONT_DRAW_MOUSE], 0
;
; mov [new_window_starting], eax
;
; .exit:
; pop eax
; ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
draw_rectangle: ;//////////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;> eax = pack[16(left), 16(right)]
;> ebx = pack[16(top), 16(bottom)]
;> esi = color
; ?? RR GG BB ; 0x01000000 negation
; ; 0x02000000 used for draw_rectangle without top line
; ; for example drawwindow_III and drawwindow_IV
;------------------------------------------------------------------------------
push eax ebx ecx edi
 
xor edi, edi
;--------------------------------------
align 4
.flags_set:
push ebx
 
; set line color
mov ecx, esi
; draw top border
rol ebx, 16
push ebx
rol ebx, 16
pop bx
test ecx, 1 shl 25
jnz @f
sub ecx, 1 shl 25
; call [draw_line]
call __sys_draw_line
;--------------------------------------
align 4
@@:
; draw bottom border
mov ebx, [esp - 2]
pop bx
; call [draw_line]
call __sys_draw_line
 
pop ebx
add ebx, 1 * 65536 - 1
 
; draw left border
rol eax, 16
push eax
rol eax, 16
pop ax
; call [draw_line]
call __sys_draw_line
 
; draw right border
mov eax, [esp - 2]
pop ax
; call [draw_line]
call __sys_draw_line
 
pop edi ecx ebx eax
ret
;--------------------------------------
align 4
.forced:
push eax ebx ecx edi
xor edi, edi
inc edi
jmp .flags_set
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
drawwindow_I_caption: ;////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
push [edx + WDATA.cl_titlebar]
mov esi, edx
 
mov edx, [esi + WDATA.box.top]
mov eax, edx
lea ebx, [edx + 21]
inc edx
add eax, [esi + WDATA.box.height]
 
cmp ebx, eax
jbe @f
mov ebx, eax
;--------------------------------------
align 4
@@:
push ebx
 
xor edi, edi
;--------------------------------------
align 4
.next_line:
mov ebx, edx
shl ebx, 16
add ebx, edx
mov eax, [esi + WDATA.box.left]
inc eax
shl eax, 16
add eax, [esi + WDATA.box.left]
add eax, [esi + WDATA.box.width]
dec eax
mov ecx, [esi + WDATA.cl_titlebar]
test ecx, 0x80000000
jz @f
sub ecx, 0x00040404
mov [esi + WDATA.cl_titlebar], ecx
;--------------------------------------
align 4
@@:
and ecx, 0x00ffffff
; call [draw_line]
call __sys_draw_line
inc edx
cmp edx, [esp]
jb .next_line
 
add esp, 4
pop [esi + WDATA.cl_titlebar]
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
drawwindow_I: ;////////////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
pushad
 
; window border
 
mov eax, [edx + WDATA.box.left - 2]
mov ax, word[edx + WDATA.box.left]
add ax, word[edx + WDATA.box.width]
mov ebx, [edx + WDATA.box.top - 2]
mov bx, word[edx + WDATA.box.top]
add bx, word[edx + WDATA.box.height]
 
mov esi, [edx + WDATA.cl_frames]
call draw_rectangle
 
; window caption
 
call drawwindow_I_caption
 
; window client area
 
; do we need to draw it?
mov edi, [esi + WDATA.cl_workarea]
test edi, 0x40000000
jnz .exit
 
; does client area have a positive size on screen?
mov edx, [esi + WDATA.box.top]
add edx, 21 + 5
mov ebx, [esi + WDATA.box.top]
add ebx, [esi + WDATA.box.height]
cmp edx, ebx
jg .exit
 
; okay, let's draw it
mov eax, 1
mov ebx, 21
mov ecx, [esi + WDATA.box.width]
mov edx, [esi + WDATA.box.height]
; call [drawbar]
call vesa20_drawbar
;--------------------------------------
align 4
.exit:
popad
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
drawwindow_III_caption: ;/////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
mov ecx, [edx + WDATA.cl_titlebar]
push ecx
mov esi, edx
mov edx, [esi + WDATA.box.top]
add edx, 4
mov ebx, [esi + WDATA.box.top]
add ebx, 20
mov eax, [esi + WDATA.box.top]
add eax, [esi + WDATA.box.height]
 
cmp ebx, eax
jb @f
mov ebx, eax
;--------------------------------------
align 4
@@:
push ebx
 
xor edi, edi
;--------------------------------------
align 4
.next_line:
mov ebx, edx
shl ebx, 16
add ebx, edx
mov eax, [esi + WDATA.box.left]
shl eax, 16
add eax, [esi + WDATA.box.left]
add eax, [esi + WDATA.box.width]
add eax, 4 * 65536 - 4
mov ecx, [esi + WDATA.cl_titlebar]
test ecx, 0x40000000
jz @f
add ecx, 0x00040404
;--------------------------------------
align 4
@@:
test ecx, 0x80000000
jz @f
sub ecx, 0x00040404
;--------------------------------------
align 4
@@:
mov [esi + WDATA.cl_titlebar], ecx
and ecx, 0x00ffffff
; call [draw_line]
call __sys_draw_line
inc edx
cmp edx, [esp]
jb .next_line
 
add esp, 4
pop [esi + WDATA.cl_titlebar]
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
drawwindow_III: ;//////////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
pushad
 
; window border
 
mov eax, [edx + WDATA.box.left - 2]
mov ax, word[edx + WDATA.box.left]
add ax, word[edx + WDATA.box.width]
mov ebx, [edx + WDATA.box.top - 2]
mov bx, word[edx + WDATA.box.top]
add bx, word[edx + WDATA.box.height]
 
mov esi, [edx + WDATA.cl_frames]
shr esi, 1
and esi, 0x007f7f7f
call draw_rectangle
 
push esi
mov ecx, 3
mov esi, [edx + WDATA.cl_frames]
;--------------------------------------
align 4
.next_frame:
add eax, 1 * 65536 - 1
add ebx, 1 * 65536 - 1
call draw_rectangle
dec ecx
jnz .next_frame
 
pop esi
add eax, 1 * 65536 - 1
add ebx, 1 * 65536 - 1
call draw_rectangle
 
; window caption
 
call drawwindow_III_caption
 
; window client area
 
; do we need to draw it?
mov edi, [esi + WDATA.cl_workarea]
test edi, 0x40000000
jnz .exit
 
; does client area have a positive size on screen?
mov edx, [esi + WDATA.box.top]
add edx, 21 + 5
mov ebx, [esi + WDATA.box.top]
add ebx, [esi + WDATA.box.height]
cmp edx, ebx
jg .exit
 
; okay, let's draw it
mov eax, 5
mov ebx, 20
mov ecx, [esi + WDATA.box.width]
mov edx, [esi + WDATA.box.height]
sub ecx, 4
sub edx, 4
; call [drawbar]
call vesa20_drawbar
;--------------------------------------
align 4
.exit:
popad
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
waredraw: ;////////////////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? Activate window, redrawing if necessary
;------------------------------------------------------------------------------
push -1
mov eax, [TASK_COUNT]
lea eax, [WIN_POS + eax * 2]
cmp eax, esi
pop eax
je .exit
 
; is it overlapped by another window now?
push ecx
call window._.check_window_draw
test ecx, ecx
pop ecx
jz .do_not_draw
 
; yes it is, activate and update screen buffer
mov byte[MOUSE_DOWN], 1
call window._.window_activate
 
pushad
mov edi, [TASK_COUNT]
movzx esi, word[WIN_POS + edi * 2]
shl esi, 5
add esi, window_data
 
mov eax, [esi + WDATA.box.left]
mov ebx, [esi + WDATA.box.top]
mov ecx, [esi + WDATA.box.width]
mov edx, [esi + WDATA.box.height]
 
add ecx, eax
add edx, ebx
 
mov edi, [TASK_COUNT]
movzx esi, word[WIN_POS + edi * 2]
call window._.set_screen
inc [_display.mask_seqno]
popad
 
; tell application to redraw itself
mov [edi + WDATA.fl_redraw], 1
xor eax, eax
jmp .exit
;--------------------------------------
align 4
.do_not_draw:
; no it's not, just activate the window
call window._.window_activate
xor eax, eax
mov byte[MOUSE_BACKGROUND], al
mov byte[DONT_DRAW_MOUSE], al
;--------------------------------------
align 4
.exit:
mov byte[MOUSE_DOWN], 0
inc eax
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
minimize_all_window:
push ebx ecx edx esi edi
pushfd
cli
xor edx, edx
mov eax, 2 ; we do not minimize the kernel thread N1
mov ebx, [TASK_COUNT]
;--------------------------------------
align 4
.loop:
movzx edi, word[WIN_POS + eax * 2]
shl edi, 5
; it is a unused slot?
cmp dword [edi+CURRENT_TASK+TASKDATA.state], 9
je @f
; it is a hidden thread?
lea esi, [edi*8+SLOT_BASE+APPDATA.app_name]
cmp [esi], byte '@'
je @f
; is it already minimized?
test [edi + window_data+WDATA.fl_wstate], WSTATE_MINIMIZED
jnz @f
; no it's not, let's do that
or [edi + window_data+WDATA.fl_wstate], WSTATE_MINIMIZED
inc edx
;--------------------------------------
align 4
@@:
inc eax
cmp eax, ebx
jbe .loop
; If nothing has changed
test edx, edx
jz @f
 
push edx
call syscall_display_settings._.calculate_whole_screen
call syscall_display_settings._.redraw_whole_screen
pop edx
;--------------------------------------
align 4
@@:
mov eax, edx
popfd
pop edi esi edx ecx ebx
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
minimize_window: ;/////////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;> eax = window number on screen
;------------------------------------------------------------------------------
;# corrupts [dl*]
;------------------------------------------------------------------------------
push edi
pushfd
cli
 
; is it already minimized?
movzx edi, word[WIN_POS + eax * 2]
shl edi, 5
add edi, window_data
test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED
jnz .exit
 
push eax ebx ecx edx esi
 
; no it's not, let's do that
or [edi + WDATA.fl_wstate], WSTATE_MINIMIZED
; If the window width is 0, then the action is not needed.
cmp [edi + WDATA.box.width], dword 0
je @f
; If the window height is 0, then the action is not needed.
cmp [edi + WDATA.box.height], dword 0
je @f
 
mov eax, [edi + WDATA.box.left]
mov [draw_limits.left], eax
mov ecx, eax
add ecx, [edi + WDATA.box.width]
mov [draw_limits.right], ecx
mov ebx, [edi + WDATA.box.top]
mov [draw_limits.top], ebx
mov edx, ebx
add edx, [edi + WDATA.box.height]
mov [draw_limits.bottom], edx
 
; DEBUGF 1, "K : minimize_window\n"
; DEBUGF 1, "K : dl_left %x\n",[draw_limits.left]
; DEBUGF 1, "K : dl_right %x\n",[draw_limits.right]
; DEBUGF 1, "K : dl_top %x\n",[draw_limits.top]
; DEBUGF 1, "K : dl_bottom %x\n",[draw_limits.bottom]
call calculatescreen
; xor esi, esi
; xor eax, eax
mov eax, edi
call redrawscreen
;--------------------------------------
align 4
@@:
pop esi edx ecx ebx eax
;--------------------------------------
align 4
.exit:
popfd
pop edi
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
restore_minimized_window: ;////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;> eax = window number on screen
;------------------------------------------------------------------------------
;# corrupts [dl*]
;------------------------------------------------------------------------------
pushad
pushfd
cli
 
; is it already restored?
movzx esi, word[WIN_POS + eax * 2]
mov edi, esi
shl edi, 5
add edi, window_data
test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED
jz .exit
 
; no it's not, let's do that
mov [edi + WDATA.fl_redraw], 1
and [edi + WDATA.fl_wstate], not WSTATE_MINIMIZED
mov ebp, window._.set_screen
cmp eax, [TASK_COUNT]
jz @f
mov ebp, calculatescreen
;--------------------------------------
align 4
@@:
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 ebp
inc [_display.mask_seqno]
mov byte[MOUSE_BACKGROUND], 0
;--------------------------------------
align 4
.exit:
popfd
popad
ret
;------------------------------------------------------------------------------
align 4
; TODO: remove this proc
;------------------------------------------------------------------------------
window_check_events: ;/////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
; do we have window minimize/restore request?
cmp [window_minimize], 0
je .exit
 
; okay, minimize or restore top-most window and exit
mov eax, [TASK_COUNT]
mov bl, 0
xchg [window_minimize], bl
dec bl
jnz @f
call minimize_window
jmp .exit
;--------------------------------------
align 4
@@:
call restore_minimized_window
;--------------------------------------
align 4
.exit:
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
sys_window_maximize_handler: ;/////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
;> esi = process slot
;------------------------------------------------------------------------------
mov edi, esi
shl edi, 5
add edi, window_data
 
; can window change its height?
; only types 2 and 3 can be resized
mov dl, [edi + WDATA.fl_wstyle]
test dl, 2
jz .exit
 
; toggle normal/maximized window state
mov bl, [edi + WDATA.fl_wstate]
xor bl, WSTATE_MAXIMIZED
 
; calculate and set appropriate window bounds
test bl, WSTATE_MAXIMIZED
jz .restore_size
 
mov eax, [screen_workarea.left]
mov ecx, [screen_workarea.top]
push [screen_workarea.bottom] \
[screen_workarea.right] \
ecx \
eax
sub [esp + BOX.width], eax
sub [esp + BOX.height], ecx
mov eax, esp
jmp .set_box
;--------------------------------------
align 4
.restore_size:
mov eax, esi
shl eax, 8
add eax, SLOT_BASE + APPDATA.saved_box
push [eax + BOX.height] \
[eax + BOX.width] \
[eax + BOX.top] \
[eax + BOX.left]
mov eax, esp
;--------------------------------------
align 4
.set_box:
test bl, WSTATE_ROLLEDUP
jz @f
 
xchg eax, ecx
call window._.get_rolledup_height
mov [ecx + BOX.height], eax
xchg eax, ecx
;--------------------------------------
align 4
@@:
call window._.set_window_box
add esp, sizeof.BOX
;--------------------------------------
align 4
.exit:
inc [_display.mask_seqno]
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
sys_window_rollup_handler: ;///////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
;> esi = process slot
;------------------------------------------------------------------------------
mov edx, esi
shl edx, 8
add edx, SLOT_BASE
 
; toggle normal/rolled up window state
mov bl, [edi + WDATA.fl_wstate]
xor bl, WSTATE_ROLLEDUP
 
; calculate and set appropriate window bounds
test bl, WSTATE_ROLLEDUP
jz .restore_size
 
call window._.get_rolledup_height
push eax \
[edi + WDATA.box.width] \
[edi + WDATA.box.top] \
[edi + WDATA.box.left]
mov eax, esp
jmp .set_box
;--------------------------------------
align 4
.restore_size:
test bl, WSTATE_MAXIMIZED
jnz @f
add esp, -sizeof.BOX
lea eax, [edx + APPDATA.saved_box]
jmp .set_box
;--------------------------------------
align 4
@@:
mov eax, [screen_workarea.top]
push [screen_workarea.bottom] \
[edi + WDATA.box.width] \
eax \
[edi + WDATA.box.left]
sub [esp + BOX.height], eax
mov eax, esp
;--------------------------------------
align 4
.set_box:
call window._.set_window_box
add esp, sizeof.BOX
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
;sys_window_start_moving_handler: ;/////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
;> eax = old (original) window box
;> esi = process slot
;------------------------------------------------------------------------------
; mov edi, eax
; call window._.draw_negative_box
; ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
sys_window_end_moving_handler: ;///////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
;> eax = old (original) window box
;> ebx = new (final) window box
;> esi = process slot
;------------------------------------------------------------------------------
; mov edi, ebx
; call window._.end_moving__box
 
mov edi, esi
shl edi, 5
add edi, window_data
 
mov eax, ebx
mov bl, [edi + WDATA.fl_wstate]
call window._.set_window_box
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
sys_window_moving_handler: ;///////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
;> eax = old (from previous call) window box
;> ebx = new (current) window box
;> esi = process_slot
;------------------------------------------------------------------------------
mov edi, eax
call window._.draw_negative_box
mov edi, ebx
call window._.draw_negative_box
ret
;==============================================================================
;///// private functions //////////////////////////////////////////////////////
;==============================================================================
 
iglobal
FuncTable syscall_display_settings, ftable, \
00, 01, 02, 03, 04, 05, 06, 07, 08
 
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}
endg
 
;uglobal
; NOTE: commented out since doesn't provide necessary functionality anyway,
; to be reworked
; new_window_starting dd ?
;endg
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
window._.invalidate_screen: ;//////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
;> eax = old (original) window box
;> ebx = new (final) window box
;> edi = pointer to WDATA struct
;------------------------------------------------------------------------------
push eax ebx
 
; TODO: do we really need `draw_limits`?
; Yes, they are used by background drawing code.
 
; we need only to restore the background windows at the old place!
mov ecx, [ebx + BOX.left]
mov [draw_limits.left], ecx
add ecx, [ebx + BOX.width]
mov [draw_limits.right], ecx
mov ecx, [ebx + BOX.top]
mov [draw_limits.top], ecx
add ecx, [ebx + BOX.height]
mov [draw_limits.bottom], ecx
; recalculate screen buffer at old position
push ebx
mov edx, [eax + BOX.height]
mov ecx, [eax + BOX.width]
mov ebx, [eax + BOX.top]
mov eax, [eax + BOX.left]
add ecx, eax
add edx, ebx
call calculatescreen
pop eax
; recalculate screen buffer at new position
mov edx, [eax + BOX.height]
mov ecx, [eax + BOX.width]
mov ebx, [eax + BOX.top]
mov eax, [eax + BOX.left]
add ecx, eax
add edx, ebx
call calculatescreen
 
mov eax, edi
call redrawscreen
 
; tell window to redraw itself
mov [edi + WDATA.fl_redraw], 1
 
pop ebx eax
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
window._.set_window_box: ;/////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
;> eax = pointer to BOX struct
;> bl = new window state flags
;> edi = pointer to WDATA struct
;------------------------------------------------------------------------------
push eax ebx esi
 
; don't do anything if the new box is identical to the old
cmp bl, [edi + WDATA.fl_wstate]
jnz @f
mov esi, eax
push edi
if WDATA.box
add edi, WDATA.box
end if
mov ecx, 4
repz cmpsd
pop edi
jz .exit
;--------------------------------------
align 4
@@:
add esp, -sizeof.BOX
mov ebx, esp
if WDATA.box
lea esi, [edi + WDATA.box]
else
mov esi, edi ; optimization for WDATA.box = 0
end if
xchg eax, esi
mov ecx, sizeof.BOX
call memmove
xchg eax, esi
xchg ebx, esi
call memmove
mov eax, ebx
mov ebx, esi
 
call window._.check_window_position
call window._.set_window_clientbox
call window._.invalidate_screen
 
add esp, sizeof.BOX
 
mov cl, [esp + 4]
mov ch, cl
xchg cl, [edi + WDATA.fl_wstate]
 
or cl, ch
test cl, WSTATE_MAXIMIZED
jnz .exit
 
mov eax, edi
sub eax, window_data
shl eax, 3
add eax, SLOT_BASE
 
lea ebx, [edi + WDATA.box]
xchg esp, ebx
 
pop [eax + APPDATA.saved_box.left] \
[eax + APPDATA.saved_box.top] \
[eax + APPDATA.saved_box.width] \
edx
 
xchg esp, ebx
 
test ch, WSTATE_ROLLEDUP
jnz .exit
 
mov [eax + APPDATA.saved_box.height], edx
;--------------------------------------
align 4
.exit:
pop esi ebx eax
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
window._.set_window_clientbox: ;///////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
;> edi = pointer to WDATA struct
;------------------------------------------------------------------------------
push eax ecx edi
 
mov eax, [_skinh]
mov [window_topleft + 8 * 3 + 4], eax
mov [window_topleft + 8 * 4 + 4], eax
 
mov ecx, edi
sub edi, window_data
shl edi, 3
test [ecx + WDATA.fl_wstyle], WSTYLE_CLIENTRELATIVE
jz .whole_window
 
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
jmp .exit
;--------------------------------------
align 4
.whole_window:
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
;--------------------------------------
align 4
.exit:
pop edi ecx eax
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
window._.sys_set_window: ;/////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
;< edx = pointer to WDATA struct
;------------------------------------------------------------------------------
mov eax, [CURRENT_TASK]
shl eax, 5
add eax, window_data
 
; save window colors
mov [eax + WDATA.cl_workarea], edx
mov [eax + WDATA.cl_titlebar], esi
mov [eax + WDATA.cl_frames], edi
 
mov edi, eax
 
; was it already defined before?
test [edi + WDATA.fl_wdrawn], 1
jnz .set_client_box
or [edi + WDATA.fl_wdrawn], 1
; After first draw_window we need redraw mouse necessarily!
; Otherwise the user can see cursor specified by f.37.5 from another window.
; He will be really unhappy! He is terrible in rage - usually he throws stones!
mov [redrawmouse_unconditional], 1
; NOTE: commented out since doesn't provide necessary functionality
; anyway, to be reworked
; mov eax, [timer_ticks] ; [0xfdf0]
; add eax, 100
; mov [new_window_starting], eax
 
; no it wasn't, performing initial window definition
movzx eax, bx
mov [edi + WDATA.box.width], eax
movzx eax, cx
mov [edi + WDATA.box.height], eax
sar ebx, 16
sar ecx, 16
mov [edi + WDATA.box.left], ebx
mov [edi + WDATA.box.top], ecx
 
call window._.check_window_position
 
push ecx edi
 
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
cmp cl, 3
je @f
cmp cl, 4
je @f
 
xor eax, eax
;--------------------------------------
align 4
@@:
mov [edi + APPDATA.wnd_caption], eax
 
mov esi, [esp]
add edi, APPDATA.saved_box
movsd
movsd
movsd
movsd
 
pop edi ecx
 
mov esi, [CURRENT_TASK]
movzx esi, word[WIN_STACK + esi * 2]
lea esi, [WIN_POS + esi * 2]
call waredraw
 
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
 
mov byte[KEY_COUNT], 0 ; empty keyboard buffer
mov byte[BTN_COUNT], 0 ; empty button buffer
;--------------------------------------
align 4
.set_client_box:
; update window client box coordinates
call window._.set_window_clientbox
 
; reset window redraw flag and exit
mov [edi + WDATA.fl_redraw], 0
mov edx, edi
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
window._.check_window_position: ;//////////////////////////////////////////////
;------------------------------------------------------------------------------
;? Check if window is inside screen area
;------------------------------------------------------------------------------
;> edi = pointer to WDATA
;------------------------------------------------------------------------------
push eax ebx ecx edx esi
 
mov eax, [edi + WDATA.box.left]
mov ebx, [edi + WDATA.box.top]
mov ecx, [edi + WDATA.box.width]
mov edx, [edi + WDATA.box.height]
 
mov esi, [Screen_Max_X]
cmp ecx, esi
ja .fix_width_high
;--------------------------------------
align 4
.check_left:
or eax, eax
jl .fix_left_low
add eax, ecx
cmp eax, esi
jg .fix_left_high
;--------------------------------------
align 4
.check_height:
mov esi, [Screen_Max_Y]
cmp edx, esi
ja .fix_height_high
;--------------------------------------
align 4
.check_top:
or ebx, ebx
jl .fix_top_low
add ebx, edx
cmp ebx, esi
jg .fix_top_high
;--------------------------------------
align 4
.exit:
pop esi edx ecx ebx eax
ret
;--------------------------------------
align 4
.fix_width_high:
mov ecx, esi
mov [edi + WDATA.box.width], esi
jmp .check_left
;--------------------------------------
align 4
.fix_left_low:
xor eax, eax
mov [edi + WDATA.box.left], eax
jmp .check_height
;--------------------------------------
align 4
.fix_left_high:
mov eax, esi
sub eax, ecx
mov [edi + WDATA.box.left], eax
jmp .check_height
;--------------------------------------
align 4
.fix_height_high:
mov edx, esi
mov [edi + WDATA.box.height], esi
jmp .check_top
;--------------------------------------
align 4
.fix_top_low:
xor ebx, ebx
mov [edi + WDATA.box.top], ebx
jmp .exit
;--------------------------------------
align 4
.fix_top_high:
mov ebx, esi
sub ebx, edx
mov [edi + WDATA.box.top], ebx
jmp .exit
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
window._.get_titlebar_height: ;////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
;> edi = pointer to WDATA
;------------------------------------------------------------------------------
mov al, [edi + WDATA.fl_wstyle]
and al, 0x0f
cmp al, 0x03
jne @f
mov eax, [_skinh]
ret
;--------------------------------------
align 4
@@:
mov eax, 21
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
window._.get_rolledup_height: ;////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
;> edi = pointer to WDATA
;------------------------------------------------------------------------------
mov al, [edi + WDATA.fl_wstyle]
and al, 0x0f
cmp al, 0x03
jb @f
mov eax, [_skinh]
add eax, 3
ret
;--------------------------------------
align 4
@@:
or al, al
jnz @f
mov eax, 21
ret
;--------------------------------------
align 4
@@:
mov eax, 21 + 2
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
window._.set_screen: ;/////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? Reserve window area in screen buffer
;------------------------------------------------------------------------------
;> eax = left
;> ebx = top
;> ecx = right
;> edx = bottom
;> esi = process number
;------------------------------------------------------------------------------
virtual at esp
ff_x dd ?
ff_y dd ?
ff_width dd ?
ff_xsz dd ?
ff_ysz dd ?
ff_scale dd ?
end virtual
 
pushad
 
cmp esi, 1
jz .check_for_shaped_window
mov edi, esi
shl edi, 5
cmp [window_data + edi + WDATA.box.width], 0
jnz .check_for_shaped_window
cmp [window_data + edi + WDATA.box.height], 0
jz .exit
;--------------------------------------
align 4
.check_for_shaped_window:
mov edi, esi
shl edi, 8
add edi, SLOT_BASE
cmp [edi + APPDATA.wnd_shape], 0
jne .shaped_window
 
; get x&y size
sub ecx, eax
sub edx, ebx
inc ecx
inc edx
 
; get WinMap start
push esi
; mov edi, [Screen_Max_X]
; inc edi
; mov esi, edi
mov esi, [Screen_Max_X]
inc esi
; imul edi, ebx
mov edi, [d_width_calc_area + ebx*4]
 
add edi, eax
add edi, [_WinMapAddress]
pop eax
mov ah, al
push ax
shl eax, 16
pop ax
;--------------------------------------
align 4
.next_line:
push ecx
shr ecx, 2
rep stosd
mov ecx, [esp]
and ecx, 3
rep stosb
pop ecx
add edi, esi
sub edi, ecx
dec edx
jnz .next_line
 
jmp .exit
;--------------------------------------
align 4
.shaped_window:
; for (y=0; y <= x_size; y++)
; for (x=0; x <= x_size; x++)
; if (shape[coord(x,y,scale)]==1)
; set_pixel(x, y, process_number);
 
sub ecx, eax
sub edx, ebx
inc ecx
inc edx
 
push [edi + APPDATA.wnd_shape_scale] ; push scale first -> for loop
 
; get WinMap start -> ebp
push eax
; mov eax, [Screen_Max_X] ; screen_sx
; inc eax
; imul eax, ebx
mov eax, [d_width_calc_area + ebx*4]
 
add eax, [esp]
add eax, [_WinMapAddress]
mov ebp, eax
 
mov edi, [edi + APPDATA.wnd_shape]
pop eax
 
; eax = x_start
; ebx = y_start
; ecx = x_size
; edx = y_size
; esi = process_number
; edi = &shape
; [scale]
push edx ecx ; for loop - x,y size
 
mov ecx, esi
shl ecx, 5
mov edx, [window_data + ecx + WDATA.box.top]
push [window_data + ecx + WDATA.box.width] ; for loop - width
mov ecx, [window_data + ecx + WDATA.box.left]
sub ebx, edx
sub eax, ecx
push ebx eax ; for loop - x,y
 
add [ff_xsz], eax
add [ff_ysz], ebx
 
mov ebx, [ff_y]
;--------------------------------------
align 4
.ff_new_y:
mov edx, [ff_x]
;--------------------------------------
align 4
.ff_new_x:
; -- body --
mov ecx, [ff_scale]
mov eax, [ff_width]
inc eax
shr eax, cl
push ebx edx
shr ebx, cl
shr edx, cl
imul eax, ebx
add eax, edx
pop edx ebx
add eax, edi
call .read_byte
test al, al
jz @f
mov eax, esi
mov [ebp], al
; -- end body --
;--------------------------------------
align 4
@@:
inc ebp
inc edx
cmp edx, [ff_xsz]
jb .ff_new_x
 
sub ebp, [ff_xsz]
add ebp, [ff_x]
add ebp, [Screen_Max_X] ; screen.x
inc ebp
inc ebx
cmp ebx, [ff_ysz]
jb .ff_new_y
 
add esp, 24
;--------------------------------------
align 4
.exit:
popad
inc [_display.mask_seqno]
ret
;--------------------------------------
align 4
.read_byte:
; eax - address
; esi - slot
push eax ecx edx esi
xchg eax, esi
lea ecx, [esp + 12]
mov edx, 1
call read_process_memory
pop esi edx ecx eax
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
window._.window_activate: ;////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? Activate window
;------------------------------------------------------------------------------
;> esi = pointer to WIN_POS+ window data
;------------------------------------------------------------------------------
push eax ebx
 
; if type of current active window is 3 or 4, it must be redrawn
mov ebx, [TASK_COUNT]
; DEBUGF 1, "K : TASK_COUNT (0x%x)\n", ebx
movzx ebx, word[WIN_POS + ebx * 2]
shl ebx, 5
add eax, window_data
mov al, [window_data + ebx + WDATA.fl_wstyle]
and al, 0x0f
cmp al, 0x03
je .set_window_redraw_flag
cmp al, 0x04
jne .move_others_down
;--------------------------------------
align 4
.set_window_redraw_flag:
mov [window_data + ebx + WDATA.fl_redraw], 1
;--------------------------------------
align 4
.move_others_down:
; ax <- process no
movzx ebx, word[esi]
; ax <- position in window stack
movzx ebx, word[WIN_STACK + ebx * 2]
 
; drop others
xor eax, eax
;--------------------------------------
align 4
.next_stack_window:
cmp eax, [TASK_COUNT]
jae .move_self_up
inc eax
; push ebx
; xor ebx,ebx
; mov bx,[WIN_STACK + eax * 2]
; DEBUGF 1, "K : DEC WIN_STACK (0x%x)\n",ebx
; pop ebx
cmp [WIN_STACK + eax * 2], bx
jbe .next_stack_window
dec word[WIN_STACK + eax * 2]
jmp .next_stack_window
;--------------------------------------
align 4
.move_self_up:
movzx ebx, word[esi]
; number of processes
mov ax, [TASK_COUNT]
; this is the last (and the upper)
mov [WIN_STACK + ebx * 2], ax
 
; update on screen - window stack
xor eax, eax
;--------------------------------------
align 4
.next_window_pos:
cmp eax, [TASK_COUNT]
jae .reset_vars
inc eax
movzx ebx, word[WIN_STACK + eax * 2]
mov [WIN_POS + ebx * 2], ax
jmp .next_window_pos
;--------------------------------------
align 4
.reset_vars:
mov byte[KEY_COUNT], 0
mov byte[BTN_COUNT], 0
mov word[MOUSE_SCROLL_H], 0
mov word[MOUSE_SCROLL_V], 0
 
pop ebx eax
ret
;------------------------------------------------------------------------------
window._.window_deactivate: ;////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? Deactivate window
;------------------------------------------------------------------------------
;> esi = pointer to WIN_POS+ window data
;------------------------------------------------------------------------------
push eax ebx
;--------------------------------------
align 4
.move_others_up:
; ax <- process no
movzx ebx, word[esi]
; ax <- position in window stack
movzx ebx, word[WIN_STACK + ebx * 2]
; up others
xor eax, eax
;--------------------------------------
align 4
.next_stack_window:
cmp eax, [TASK_COUNT]
jae .move_self_down
inc eax
cmp [WIN_STACK + eax * 2], bx
jae .next_stack_window
inc word[WIN_STACK + eax * 2]
jmp .next_stack_window
;--------------------------------------
align 4
.move_self_down:
movzx ebx, word[esi]
; this is the last (and the low)
mov [WIN_STACK + ebx * 2], word 1
; update on screen - window stack
xor eax, eax
;--------------------------------------
align 4
.next_window_pos:
cmp eax, [TASK_COUNT]
jae .reset_vars
inc eax
movzx ebx, word[WIN_STACK + eax * 2]
mov [WIN_POS + ebx * 2], ax
jmp .next_window_pos
;--------------------------------------
align 4
.reset_vars:
mov byte[KEY_COUNT], 0
mov byte[BTN_COUNT], 0
mov word[MOUSE_SCROLL_H], 0
mov word[MOUSE_SCROLL_V], 0
pop ebx eax
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
window._.check_window_draw: ;//////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? Check if window is necessary to draw
;------------------------------------------------------------------------------
;> edi = pointer to WDATA
;------------------------------------------------------------------------------
mov cl, [edi + WDATA.fl_wstyle]
and cl, 0x0f
cmp cl, 3
je .exit.redraw ; window type 3
cmp cl, 4
je .exit.redraw ; window type 4
 
push eax ebx edx esi
 
mov eax, edi
sub eax, window_data
shr eax, 5
 
movzx eax, word[WIN_STACK + eax * 2] ; get value of the curr process
lea esi, [WIN_POS + eax * 2] ; get address of this process at 0xC400
;--------------------------------------
align 4
.next_window:
add esi, 2
 
mov eax, [TASK_COUNT]
lea eax, word[WIN_POS + eax * 2] ; number of the upper window
 
cmp esi, eax
ja .exit.no_redraw
 
movzx edx, word[esi]
shl edx, 5
cmp [CURRENT_TASK + edx + TASKDATA.state], TSTATE_FREE
je .next_window
 
mov eax, [edi + WDATA.box.top]
mov ebx, [edi + WDATA.box.height]
add ebx, eax
 
mov ecx, [window_data + edx + WDATA.box.top]
cmp ecx, ebx
jge .next_window
add ecx, [window_data + edx + WDATA.box.height]
cmp eax, ecx
jge .next_window
 
mov eax, [edi + WDATA.box.left]
mov ebx, [edi + WDATA.box.width]
add ebx, eax
 
mov ecx, [window_data + edx + WDATA.box.left]
cmp ecx, ebx
jge .next_window
add ecx, [window_data + edx + WDATA.box.width]
cmp eax, ecx
jge .next_window
 
pop esi edx ebx eax
;--------------------------------------
align 4
.exit.redraw:
xor ecx, ecx
inc ecx
ret
;--------------------------------------
align 4
.exit.no_redraw:
pop esi edx ebx eax
xor ecx, ecx
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
window._.draw_window_caption: ;////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
xor eax, eax
mov edx, [TASK_COUNT]
movzx edx, word[WIN_POS + edx * 2]
cmp edx, [CURRENT_TASK]
jne @f
inc eax
;--------------------------------------
align 4
@@:
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
cmp bl, 4
je .draw_caption_style_3
 
jmp .not_style_3
;--------------------------------------
align 4
.draw_caption_style_3:
push edx
call drawwindow_IV_caption
add esp, 4
jmp .2
;--------------------------------------
align 4
.not_style_3:
cmp bl, 2
jne .not_style_2
 
call drawwindow_III_caption
jmp .2
;--------------------------------------
align 4
.not_style_2:
cmp bl, 0
jne .2
 
call drawwindow_I_caption
;--------------------------------------
align 4
.2:
mov edi, [CURRENT_TASK]
shl edi, 5
test [edi + window_data + WDATA.fl_wstyle], WSTYLE_HASCAPTION
jz .exit
mov edx, [edi * 8 + SLOT_BASE + APPDATA.wnd_caption]
or edx, edx
jz .exit
 
movzx eax, [edi + window_data + WDATA.fl_wstyle]
and al, 0x0F
cmp al, 3
je .skinned
cmp al, 4
je .skinned
 
jmp .not_skinned
;--------------------------------------
align 4
.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 .exit
 
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
;--------------------------------------
align 4
.not_skinned:
cmp al, 1
je .exit
 
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 .exit
 
mov esi, eax
mov ebx, 0x00080007
add ebx, ebp
;--------------------------------------
align 4
.dodraw:
mov ecx, [common_colours + 16]
or ecx, 0x80000000
xor edi, edi
call dtext_asciiz_esi
;--------------------------------------
align 4
.exit:
; call [draw_pointer]
call __sys_draw_pointer
ret
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
window._.draw_negative_box: ;//////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? Draw negative box
;------------------------------------------------------------------------------
;> edi = pointer to BOX struct
;------------------------------------------------------------------------------
push eax ebx esi
mov esi, 0x01000000
;--------------------------------------
align 4
.1:
mov eax, [edi + BOX.left - 2]
mov ax, word[edi + BOX.left]
add ax, word[edi + BOX.width]
mov ebx, [edi + BOX.top - 2]
mov bx, word[edi + BOX.top]
add bx, word[edi + BOX.height]
call draw_rectangle.forced
pop esi ebx eax
ret
;------------------------------------------------------------------------------
;align 4
;------------------------------------------------------------------------------
;window._.end_moving__box: ;//////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? Draw positive box
;------------------------------------------------------------------------------
;> edi = pointer to BOX struct
;------------------------------------------------------------------------------
; push eax ebx esi
; xor esi, esi
; jmp window._.draw_negative_box.1
;------------------------------------------------------------------------------
align 4
;------------------------------------------------------------------------------
window._.get_rect: ;/////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description> void __fastcall get_window_rect(struct RECT* rc);
;------------------------------------------------------------------------------
;> ecx = pointer to RECT
;------------------------------------------------------------------------------
mov eax, [TASK_BASE]
 
mov edx, [eax-twdw + WDATA.box.left]
mov [ecx+RECT.left], edx
 
add edx, [eax-twdw + WDATA.box.width]
mov [ecx+RECT.right], edx
 
mov edx, [eax-twdw + WDATA.box.top]
mov [ecx+RECT.top], edx
 
add edx, [eax-twdw + WDATA.box.height]
mov [ecx+RECT.bottom], edx
ret
;------------------------------------------------------------------------------
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/gui/char.mt
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/kernel/branches/net/gui/char2.mt
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/kernel/branches/net/gui/button.inc
0,0 → 1,508
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
;==============================================================================
;///// public functions ///////////////////////////////////////////////////////
;==============================================================================
 
button.MAX_BUTTONS = 4095
 
struct SYS_BUTTON
pslot dw ?
id_lo dw ?
left dw ?
width dw ?
top dw ?
height dw ?
id_hi dw ?
dw ?
ends
 
align 4
;------------------------------------------------------------------------------
syscall_button: ;///// system function 8 //////////////////////////////////////
;------------------------------------------------------------------------------
;? Define/undefine GUI button object
;------------------------------------------------------------------------------
;; Define button:
;> ebx = pack[16(x), 16(width)]
;> ecx = pack[16(y), 16(height)]
;> edx = pack[8(flags), 24(button identifier)]
;> flags bits:
;> 7 (31) = 0
;> 6 (30) = don't draw button
;> 5 (29) = don't draw button frame when pressed
;> esi = button color
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;; Undefine button:
;> edx = pack[8(flags), 24(button identifier)]
;> flags bits:
;> 7 (31) = 1
;------------------------------------------------------------------------------
; do we actually need to undefine the button?
test edx, 0x80000000
jnz .remove_button
 
; do we have free button slots available?
mov edi, [BTN_ADDR]
mov eax, [edi]
cmp eax, button.MAX_BUTTONS
jge .exit
 
; does it have positive size? (otherwise it doesn't have sense)
or bx, bx
jle .exit
or cx, cx
jle .exit
 
; make coordinates clientbox-relative
push eax
mov eax, [current_slot]
rol ebx, 16
add bx, word[eax + APPDATA.wnd_clientbox.left]
rol ebx, 16
rol ecx, 16
add cx, word[eax + APPDATA.wnd_clientbox.top]
rol ecx, 16
pop eax
 
; basic checks passed, define the button
push ebx ecx edx
inc eax
mov [edi], ax
shl eax, 4
add edi, eax
; NOTE: this code doesn't rely on SYS_BUTTON struct, please revise it
; if you change something
mov ax, [CURRENT_TASK]
stosw
mov ax, dx
stosw ; button id number: bits 0-15
mov eax, ebx
rol eax, 16
stosd ; x start | x size
mov eax, ecx
rol eax, 16
stosd ; y start | y size
mov eax, edx
shr eax, 16
stosw ; button id number: bits 16-31
pop edx ecx ebx
 
; do we also need to draw the button?
test edx, 0x40000000
jnz .exit
 
; draw button body
 
pushad
 
; calculate window-relative coordinates
movzx edi, cx
shr ebx, 16
shr ecx, 16
mov eax, [TASK_BASE]
add ebx, [eax - twdw + WDATA.box.left]
add ecx, [eax - twdw + WDATA.box.top]
mov eax, ebx
shl eax, 16
mov ax, bx
add ax, word[esp + 16]
mov ebx, ecx
shl ebx, 16
mov bx, cx
 
; calculate initial color
mov ecx, esi
cmp [buttontype], 0
je @f
call button._.incecx2
 
; set button height counter
@@:
mov edx, edi
 
.next_line:
call button._.button_dececx
push edi
xor edi, edi
; call [draw_line]
call __sys_draw_line
pop edi
add ebx, 0x00010001
dec edx
jnz .next_line
 
popad
 
; draw button frame
 
push ebx ecx
 
; calculate window-relative coordinates
shr ebx, 16
shr ecx, 16
mov eax, [TASK_BASE]
add ebx, [eax - twdw + WDATA.box.left]
add ecx, [eax - twdw + WDATA.box.top]
 
; top border
mov eax, ebx
shl eax, 16
mov ax, bx
add ax, [esp + 4]
mov ebx, ecx
shl ebx, 16
mov bx, cx
push ebx
xor edi, edi
mov ecx, esi
call button._.incecx
; call [draw_line]
call __sys_draw_line
 
; bottom border
movzx edx, word[esp + 4 + 0]
add ebx, edx
shl edx, 16
add ebx, edx
mov ecx, esi
call button._.dececx
; call [draw_line]
call __sys_draw_line
 
; left border
pop ebx
push edx
mov edx, eax
shr edx, 16
mov ax, dx
mov edx, ebx
shr edx, 16
mov bx, dx
add bx, [esp + 4 + 0]
pop edx
mov ecx, esi
call button._.incecx
; call [draw_line]
call __sys_draw_line
 
; right border
mov dx, [esp + 4]
add ax, dx
shl edx, 16
add eax, edx
add ebx, 0x00010000
mov ecx, esi
call button._.dececx
; call [draw_line]
call __sys_draw_line
 
pop ecx ebx
 
.exit:
ret
 
; FIXME: mutex needed
syscall_button.remove_button:
and edx, 0x00ffffff
mov edi, [BTN_ADDR]
mov ebx, [edi]
inc ebx
imul esi, ebx, sizeof.SYS_BUTTON
add esi, edi
xor ecx, ecx
add ecx, -sizeof.SYS_BUTTON
add esi, sizeof.SYS_BUTTON
 
.next_button:
dec ebx
jz .exit
 
add ecx, sizeof.SYS_BUTTON
add esi, -sizeof.SYS_BUTTON
 
; does it belong to our process?
mov ax, [CURRENT_TASK]
cmp ax, [esi + SYS_BUTTON.pslot]
jne .next_button
 
; does the identifier match?
mov eax, dword[esi + SYS_BUTTON.id_hi - 2]
mov ax, [esi + SYS_BUTTON.id_lo]
and eax, 0x00ffffff
cmp edx, eax
jne .next_button
 
; okay, undefine it
push ebx
mov ebx, esi
lea eax, [esi + sizeof.SYS_BUTTON]
call memmove
dec dword[edi]
add ecx, -sizeof.SYS_BUTTON
pop ebx
jmp .next_button
 
.exit:
ret
 
align 4
;------------------------------------------------------------------------------
sys_button_activate_handler: ;/////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
;> eax = pack[8(process slot), 24(button id)]
;> ebx = pack[16(button x coord), 16(button y coord)]
;> cl = mouse button mask this system button was pressed with
;------------------------------------------------------------------------------
call button._.find_button
or eax, eax
jz .exit
 
mov ebx, dword[eax + SYS_BUTTON.id_hi - 2]
call button._.negative_button
 
.exit:
ret
 
align 4
;------------------------------------------------------------------------------
sys_button_deactivate_handler: ;///////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
;> eax = pack[8(process slot), 24(button id)]
;> ebx = pack[16(button x coord), 16(button y coord)]
;> cl = mouse button mask this system button was pressed with
;------------------------------------------------------------------------------
call button._.find_button
or eax, eax
jz .exit
 
mov ebx, dword[eax + SYS_BUTTON.id_hi - 2]
call button._.negative_button
 
.exit:
ret
 
align 4
;------------------------------------------------------------------------------
sys_button_perform_handler: ;//////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
;> eax = pack[8(process slot), 24(button id)]
;> ebx = pack[16(button x coord), 16(button y coord)]
;> cl = mouse button mask this system button was pressed with
;------------------------------------------------------------------------------
shl eax, 8
mov al, cl
movzx ebx, byte[BTN_COUNT]
mov [BTN_BUFF + ebx * 4], eax
inc bl
mov [BTN_COUNT], bl
ret
 
;==============================================================================
;///// private functions //////////////////////////////////////////////////////
;==============================================================================
 
;------------------------------------------------------------------------------
button._.find_button: ;////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? Find system button by specified process slot, id and coordinates
;------------------------------------------------------------------------------
;> eax = pack[8(process slot), 24(button id)] or 0
;> ebx = pack[16(button x coord), 16(button y coord)]
;------------------------------------------------------------------------------
;< eax = pointer to SYS_BUTTON struct or 0
;------------------------------------------------------------------------------
push ecx edx esi edi
 
mov edx, eax
shr edx, 24
and eax, 0x0ffffff
 
mov edi, [BTN_ADDR]
mov ecx, [edi]
imul esi, ecx, sizeof.SYS_BUTTON
add esi, edi
inc ecx
add esi, sizeof.SYS_BUTTON
 
.next_button:
dec ecx
jz .not_found
 
add esi, -sizeof.SYS_BUTTON
 
; does it belong to our process?
cmp dx, [esi + SYS_BUTTON.pslot]
jne .next_button
 
; does id match?
mov edi, dword[esi + SYS_BUTTON.id_hi - 2]
mov di, [esi + SYS_BUTTON.id_lo]
and edi, 0x0ffffff
cmp eax, edi
jne .next_button
 
; does coordinates match?
mov edi, dword[esi + SYS_BUTTON.left - 2]
mov di, [esi + SYS_BUTTON.top]
cmp ebx, edi
jne .next_button
 
; okay, return it
mov eax, esi
jmp .exit
 
.not_found:
xor eax, eax
 
.exit:
pop edi esi edx ecx
ret
 
;------------------------------------------------------------------------------
button._.dececx: ;/////////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
sub cl, 0x20
jnc @f
xor cl, cl
@@:
sub ch, 0x20
jnc @f
xor ch, ch
@@:
rol ecx, 16
sub cl, 0x20
jnc @f
xor cl, cl
@@:
rol ecx, 16
ret
 
;------------------------------------------------------------------------------
button._.incecx: ;/////////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
add cl, 0x20
jnc @f
or cl, -1
@@:
add ch, 0x20
jnc @f
or ch, -1
@@:
rol ecx, 16
add cl, 0x20
jnc @f
or cl, -1
@@:
rol ecx, 16
ret
 
;------------------------------------------------------------------------------
button._.incecx2: ;////////////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
add cl, 0x14
jnc @f
or cl, -1
@@:
add ch, 0x14
jnc @f
or ch, -1
@@:
rol ecx, 16
add cl, 0x14
jnc @f
or cl, -1
@@:
rol ecx, 16
ret
 
;------------------------------------------------------------------------------
button._.button_dececx: ;//////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? <description>
;------------------------------------------------------------------------------
cmp [buttontype], 1
jne .finish
 
push eax
mov al, 1
cmp edi, 20
jg @f
mov al, 2
 
@@:
sub cl, al
jnc @f
xor cl, cl
@@:
sub ch, al
jnc @f
xor ch, ch
@@:
rol ecx, 16
sub cl, al
jnc @f
xor cl, cl
@@:
rol ecx, 16
 
pop eax
 
.finish:
ret
 
;------------------------------------------------------------------------------
button._.negative_button: ;////////////////////////////////////////////////////
;------------------------------------------------------------------------------
;? Invert system button border
;------------------------------------------------------------------------------
; if requested, do not display button border on press.
test ebx, 0x20000000
jnz .exit
 
pushad
 
xchg esi, eax
 
movzx ecx, [esi + SYS_BUTTON.pslot]
shl ecx, 5
add ecx, window_data
 
mov eax, dword[esi + SYS_BUTTON.left]
mov ebx, dword[esi + SYS_BUTTON.top]
add eax, [ecx + WDATA.box.left]
add ebx, [ecx + WDATA.box.top]
push eax ebx
pop edx ecx
rol eax, 16
rol ebx, 16
add ax, cx
add bx, dx
 
mov esi, 0x01000000
call draw_rectangle.forced
 
popad
 
.exit:
ret
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/gui/skincode.inc
0,0 → 1,529
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
include "skindata.inc"
 
;skin_data = 0x00778000
;------------------------------------------------------------------------------
align 4
read_skin_file:
stdcall load_file, ebx
test eax, eax
jz .notfound
cmp dword [eax], 'SKIN'
jnz .noskin
cmp ebx, 32*1024
jb @f
mov ebx, 32*1024
;--------------------------------------
align 4
@@:
lea ecx, [ebx+3]
shr ecx, 2
mov esi, eax
mov edi, skin_data
rep movsd
stdcall kernel_free, eax
 
call parse_skin_data
xor eax, eax
ret
;--------------------------------------
align 4
.notfound:
xor eax, eax
inc eax
ret
;--------------------------------------
align 4
.noskin:
stdcall kernel_free, eax
push 2
pop eax
ret
;------------------------------------------------------------------------------
struct SKIN_HEADER
ident dd ?
version dd ?
params dd ?
buttons dd ?
bitmaps dd ?
ends
 
struct SKIN_PARAMS
skin_height dd ?
margin.right dw ?
margin.left dw ?
margin.bottom dw ?
margin.top dw ?
colors.inner dd ?
colors.outer dd ?
colors.frame dd ?
colors_1.inner dd ?
colors_1.outer dd ?
colors_1.frame dd ?
dtp.size dd ?
dtp.data rb 40
ends
 
struct SKIN_BUTTONS
type dd ?
; position
left dw ?
top dw ?
; size
width dw ?
height dw ?
ends
 
struct SKIN_BITMAPS
kind dw ?
type dw ?
data dd ?
ends
;------------------------------------------------------------------------------
align 4
load_default_skin:
mov [_skinh], 22
mov ebx, _skin_file_default
call read_skin_file
ret
;------------------------------------------------------------------------------
align 4
parse_skin_data:
mov ebp, skin_data
cmp [ebp+SKIN_HEADER.ident], 'SKIN'
jne .exit
 
mov edi, skin_udata
mov ecx, (skin_udata.end-skin_udata)/4
xor eax, eax
cld
rep stosd
 
mov ebx, [ebp+SKIN_HEADER.params]
add ebx, skin_data
mov eax, [ebx+SKIN_PARAMS.skin_height]
mov [_skinh], eax
mov eax, [ebx+SKIN_PARAMS.colors.inner]
mov [skin_active.colors.inner], eax
mov eax, [ebx+SKIN_PARAMS.colors.outer]
mov [skin_active.colors.outer], eax
mov eax, [ebx+SKIN_PARAMS.colors.frame]
mov [skin_active.colors.frame], eax
mov eax, [ebx+SKIN_PARAMS.colors_1.inner]
mov [skin_inactive.colors.inner], eax
mov eax, [ebx+SKIN_PARAMS.colors_1.outer]
mov [skin_inactive.colors.outer], eax
mov eax, [ebx+SKIN_PARAMS.colors_1.frame]
mov [skin_inactive.colors.frame], eax
lea esi, [ebx+SKIN_PARAMS.dtp.data]
mov edi, common_colours
mov ecx, [ebx+SKIN_PARAMS.dtp.size]
and ecx, 127
rep movsb
mov eax, dword[ebx+SKIN_PARAMS.margin.right]
mov dword[_skinmargins+0], eax
mov eax, dword[ebx+SKIN_PARAMS.margin.bottom]
mov dword[_skinmargins+4], eax
 
mov ebx, [ebp+SKIN_HEADER.bitmaps]
add ebx, skin_data
;--------------------------------------
align 4
.lp1:
cmp dword[ebx], 0
je .end_bitmaps
movzx eax, [ebx+SKIN_BITMAPS.kind]
movzx ecx, [ebx+SKIN_BITMAPS.type]
dec eax
jnz .not_left
xor eax, eax
mov edx, skin_active.left.data
or ecx, ecx
jnz @f
mov edx, skin_inactive.left.data
;--------------------------------------
align 4
@@:
jmp .next_bitmap
;--------------------------------------
align 4
.not_left:
dec eax
jnz .not_oper
mov esi, [ebx+SKIN_BITMAPS.data]
add esi, skin_data
mov eax, [esi+0]
neg eax
mov edx, skin_active.oper.data
or ecx, ecx
jnz @f
mov edx, skin_inactive.oper.data
;--------------------------------------
align 4
@@:
jmp .next_bitmap
;--------------------------------------
align 4
.not_oper:
dec eax
jnz .not_base
mov eax, [skin_active.left.width]
mov edx, skin_active.base.data
or ecx, ecx
jnz @f
mov eax, [skin_inactive.left.width]
mov edx, skin_inactive.base.data
;--------------------------------------
align 4
@@:
jmp .next_bitmap
;--------------------------------------
align 4
.not_base:
add ebx, 8
jmp .lp1
;--------------------------------------
align 4
.next_bitmap:
mov ecx, [ebx+SKIN_BITMAPS.data]
add ecx, skin_data
mov [edx+4], eax
mov eax, [ecx+0]
mov [edx+8], eax
add ecx, 8
mov [edx+0], ecx
add ebx, 8
jmp .lp1
;--------------------------------------
align 4
.end_bitmaps:
mov ebx, [ebp+SKIN_HEADER.buttons]
add ebx, skin_data
;--------------------------------------
align 4
.lp2:
cmp dword[ebx], 0
je .end_buttons
mov eax, [ebx+SKIN_BUTTONS.type]
dec eax
jnz .not_close
mov edx, skin_btn_close
jmp .next_button
;--------------------------------------
align 4
.not_close:
dec eax
jnz .not_minimize
mov edx, skin_btn_minimize
jmp .next_button
;--------------------------------------
align 4
.not_minimize:
add ebx, 12
jmp .lp2
;--------------------------------------
align 4
.next_button:
movsx eax, [ebx+SKIN_BUTTONS.left]
mov [edx+SKIN_BUTTON.left], eax
movsx eax, [ebx+SKIN_BUTTONS.top]
mov [edx+SKIN_BUTTON.top], eax
movsx eax, [ebx+SKIN_BUTTONS.width]
mov [edx+SKIN_BUTTON.width], eax
movsx eax, [ebx+SKIN_BUTTONS.height]
mov [edx+SKIN_BUTTON.height], eax
add ebx, 12
jmp .lp2
;--------------------------------------
align 4
.end_buttons:
.exit:
ret
;------------------------------------------------------------------------------
align 4
drawwindow_IV_caption:
 
mov ebp, skin_active
or al, al
jnz @f
mov ebp, skin_inactive
;--------------------------------------
align 4
@@:
mov esi, [esp+4]
mov eax, [esi+WDATA.box.width] ; window width
mov edx, [ebp+SKIN_DATA.left.left]
shl edx, 16
mov ecx, [ebp+SKIN_DATA.left.width]
shl ecx, 16
add ecx, [_skinh]
 
mov ebx, [ebp+SKIN_DATA.left.data]
or ebx, ebx
jz @f
call sys_putimage.forced
;--------------------------------------
align 4
@@:
mov esi, [esp+4]
mov eax, [esi+WDATA.box.width]
sub eax, [ebp+SKIN_DATA.left.width]
sub eax, [ebp+SKIN_DATA.oper.width]
cmp eax, [ebp+SKIN_DATA.base.left]
jng .non_base
xor edx, edx
mov ecx, [ebp+SKIN_DATA.base.width]
jecxz .non_base
div ecx
 
inc eax
 
mov ebx, [ebp+SKIN_DATA.base.data]
mov ecx, [ebp+SKIN_DATA.base.width]
shl ecx, 16
add ecx, [_skinh]
mov edx, [ebp+SKIN_DATA.base.left]
sub edx, [ebp+SKIN_DATA.base.width]
shl edx, 16
;--------------------------------------
align 4
.baseskinloop:
shr edx, 16
add edx, [ebp+SKIN_DATA.base.width]
shl edx, 16
 
push eax ebx ecx edx
 
or ebx, ebx
jz @f
call sys_putimage.forced
;--------------------------------------
align 4
@@:
pop edx ecx ebx eax
 
dec eax
jnz .baseskinloop
;--------------------------------------
align 4
.non_base:
 
mov esi, [esp+4]
mov edx, [esi+WDATA.box.width]
sub edx, [ebp+SKIN_DATA.oper.width]
inc edx
shl edx, 16
mov ebx, [ebp+SKIN_DATA.oper.data]
 
mov ecx, [ebp+SKIN_DATA.oper.width]
shl ecx, 16
add ecx, [_skinh]
 
or ebx, ebx
jz @f
call sys_putimage.forced
;--------------------------------------
align 4
@@:
ret
;------------------------------------------------------------------------------
align 4
drawwindow_IV:
;param1 - aw_yes
pusha
 
push edx
 
mov edi, edx
 
mov ebp, skin_active
cmp byte [esp+32+4+4], 0
jne @f
mov ebp, skin_inactive
;--------------------------------------
align 4
@@:
mov eax, [edi+WDATA.box.left]
shl eax, 16
mov ax, word [edi+WDATA.box.left]
add ax, word [edi+WDATA.box.width]
mov ebx, [edi+WDATA.box.top]
shl ebx, 16
mov bx, word [edi+WDATA.box.top]
add bx, word [edi+WDATA.box.height]
mov esi, [ebp+SKIN_DATA.colors.outer]
or esi, 1 shl 25 ; 0x02000000 used for draw_rectangle without top line
ror ebx, 16
add ebx, [_skinh]
sub bx, 1
rol ebx, 16
call draw_rectangle
mov ecx, 3
;--------------------------------------
align 4
_dw3l:
add eax, 1*65536-1
add ebx, 0*65536-1
test ax, ax
js no_skin_add_button
test bx, bx
js no_skin_add_button
mov esi, [ebp+SKIN_DATA.colors.frame];[edi+24]
or esi, 1 shl 25; 0x02000000 used for draw_rectangle without top line
call draw_rectangle
dec ecx
jnz _dw3l
mov esi, [ebp+SKIN_DATA.colors.inner]
or esi, 1 shl 25; 0x02000000 used for draw_rectangle without top line
add eax, 1*65536-1
add ebx, 0*65536-1
test ax, ax
js no_skin_add_button
test bx, bx
js no_skin_add_button
test [edi + WDATA.fl_wstate], WSTATE_ROLLEDUP
jnz @f
call draw_rectangle
;--------------------------------------
align 4
@@:
cmp dword[skin_data], 'SKIN'
je @f
xor eax, eax
xor ebx, ebx
mov esi, [esp]
mov ecx, [esi+WDATA.box.width]
inc ecx
mov edx, [_skinh]
mov edi, [common_colours+4]; standard grab color
; call [drawbar]
call vesa20_drawbar
jmp draw_clientbar
;--------------------------------------
align 4
@@:
mov al, [esp+32+4+4]
call drawwindow_IV_caption
;--------------------------------------
align 4
draw_clientbar:
mov esi, [esp]
 
mov edx, [esi+WDATA.box.top] ; WORK AREA
add edx, 21+5
mov ebx, [esi+WDATA.box.top]
add ebx, [esi+WDATA.box.height]
cmp edx, ebx
jg _noinside2
mov eax, 5
mov ebx, [_skinh]
mov ecx, [esi+WDATA.box.width]
mov edx, [esi+WDATA.box.height]
sub ecx, 4
sub edx, 4
mov edi, [esi+WDATA.cl_workarea]
test edi, 0x40000000
jnz _noinside2
; call [drawbar]
call vesa20_drawbar
;--------------------------------------
align 4
_noinside2:
cmp dword[skin_data], 'SKIN'
jne no_skin_add_button
;* close button
mov edi, [BTN_ADDR]
movzx eax, word [edi]
cmp eax, 1000
jge no_skin_add_button
inc eax
mov [edi], ax
 
shl eax, 4
add eax, edi
 
mov bx, [CURRENT_TASK]
mov [eax], bx
 
add eax, 2 ; save button id number
mov bx, 1
mov [eax], bx
add eax, 2 ; x start
xor ebx, ebx
cmp [skin_btn_close.left], 0
jge _bCx_at_right
mov ebx, [esp]
mov ebx, [ebx+WDATA.box.width]
inc ebx
;--------------------------------------
align 4
_bCx_at_right:
add ebx, [skin_btn_close.left]
mov [eax], bx
add eax, 2 ; x size
mov ebx, [skin_btn_close.width]
dec ebx
mov [eax], bx
add eax, 2 ; y start
mov ebx, [skin_btn_close.top]
mov [eax], bx
add eax, 2 ; y size
mov ebx, [skin_btn_close.height]
dec ebx
mov [eax], bx
;* minimize button
mov edi, [BTN_ADDR]
movzx eax, word [edi]
cmp eax, 1000
jge no_skin_add_button
inc eax
mov [edi], ax
 
shl eax, 4
add eax, edi
 
mov bx, [CURRENT_TASK]
mov [eax], bx
 
add eax, 2 ; save button id number
mov bx, 65535;999
mov [eax], bx
add eax, 2 ; x start
xor ebx, ebx
cmp [skin_btn_minimize.left], 0
jge _bMx_at_right
mov ebx, [esp]
mov ebx, [ebx+WDATA.box.width]
inc ebx
;--------------------------------------
align 4
_bMx_at_right:
add ebx, [skin_btn_minimize.left]
mov [eax], bx
add eax, 2 ; x size
mov ebx, [skin_btn_minimize.width]
dec ebx
mov [eax], bx
add eax, 2 ; y start
mov ebx, [skin_btn_minimize.top]
mov [eax], bx
add eax, 2 ; y size
mov ebx, [skin_btn_minimize.height]
dec ebx
mov [eax], bx
;--------------------------------------
align 4
no_skin_add_button:
pop edi
popa
ret 4
;------------------------------------------------------------------------------
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/gui/skindata.inc
0,0 → 1,64
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
;
; WINDOW SKIN DATA
;
 
iglobal
_skin_file_default db '/sys/DEFAULT.SKN',0
endg
 
struct SKIN_DATA
colors.inner dd ?
colors.outer dd ?
colors.frame dd ?
left.data dd ?
left.left dd ?
left.width dd ?
oper.data dd ?
oper.left dd ?
oper.width dd ?
base.data dd ?
base.left dd ?
base.width dd ?
ends
 
struct SKIN_BUTTON
left dd ?
top dd ?
width dd ?
height dd ?
ends
 
uglobal
 
align 4
 
skin_udata:
_skinh dd ?
 
_skinmargins: ; rw 4
.right dw ?
.left dw ?
.bottom dw ?
.top dw ?
 
skin_btn_close SKIN_BUTTON
skin_btn_minimize SKIN_BUTTON
 
skin_active SKIN_DATA
skin_inactive SKIN_DATA
 
align 4
 
skin_udata.end:
 
endg
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/gui
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/kernel.asm
0,0 → 1,5662
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved.
;; PROGRAMMING:
;; Ivan Poddubny
;; Marat Zakiyanov (Mario79)
;; VaStaNi
;; Trans
;; Mihail Semenyako (mike.dld)
;; Sergey Kuzmin (Wildwest)
;; Andrey Halyavin (halyavin)
;; Mihail Lisovin (Mihasik)
;; Andrey Ignatiev (andrew_programmer)
;; NoName
;; Evgeny Grechnikov (Diamond)
;; Iliya Mihailov (Ghost)
;; Sergey Semyonov (Serge)
;; Johnny_B
;; SPraid (simba)
;; Hidnplayr
;; Alexey Teplov (<Lrz>)
;; Rus
;; Nable
;; shurf
;; Alver
;; Maxis
;; Galkov
;; CleverMouse
;; tsdima
;; turbanoff
;; Asper
;; art_zh
;;
;; Data in this file was originally part of MenuetOS project which is
;; distributed under the terms of GNU GPL. It is modified and redistributed as
;; part of KolibriOS project under the terms of GNU GPL.
;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa
;; PROGRAMMING:
;;
;; Ville Mikael Turjanmaa, villemt@itu.jyu.fi
;; - main os coding/design
;; Jan-Michael Brummer, BUZZ2@gmx.de
;; Felix Kaiser, info@felix-kaiser.de
;; Paolo Minazzi, paolo.minazzi@inwind.it
;; quickcode@mail.ru
;; Alexey, kgaz@crosswinds.net
;; Juan M. Caravaca, bitrider@wanadoo.es
;; kristol@nic.fi
;; Mike Hibbett, mikeh@oceanfree.net
;; Lasse Kuusijarvi, kuusijar@lut.fi
;; Jarek Pelczar, jarekp3@wp.pl
;;
;; KolibriOS is distributed in the hope that it will be useful, but WITHOUT ANY
;; WARRANTY. No author or distributor accepts responsibility to anyone for the
;; consequences of using it or for whether it serves any particular purpose or
;; works at all, unless he says so in writing. Refer to the GNU General Public
;; License (the "GPL") for full details.
;
;; Everyone is granted permission to copy, modify and redistribute KolibriOS,
;; but only under the conditions described in the GPL. A copy of this license
;; is supposed to have been given to you along with KolibriOS so you can know
;; your rights and responsibilities. It should be in a file named COPYING.
;; Among other things, the copyright notice and this notice must be preserved
;; on all copies.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format binary as "mnt"
 
include 'macros.inc'
include 'struct.inc'
 
$Revision $
 
 
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
 
include "proc32.inc"
include "kglobals.inc"
;include "lang.inc"
lang fix en
 
include "const.inc"
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_code equ (os_code_l-gdts)
graph_data equ (3+graph_data_l-gdts)
tss0 equ (tss0_l-gdts)
app_code equ (3+app_code_l-gdts)
app_data equ (3+app_data_l-gdts)
app_tls equ (3+tls_data_l-gdts)
pci_code_sel equ (pci_code_32-gdts)
pci_data_sel equ (pci_data_32-gdts)
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Included files:
;;
;; Kernel16.inc
;; - Booteng.inc English text for bootup
;; - Bootcode.inc Hardware setup
;; - Pci16.inc PCI functions
;;
;; Kernel32.inc
;; - Sys32.inc Process management
;; - Shutdown.inc Shutdown and restart
;; - Fat32.inc Read / write hd
;; - Vesa12.inc Vesa 1.2 driver
;; - Vesa20.inc Vesa 2.0 driver
;; - Vga.inc VGA driver
;; - Stack.inc Network interface
;; - Mouse.inc Mouse pointer
;; - Scincode.inc Window skinning
;; - Pci32.inc PCI functions
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 16 BIT ENTRY FROM BOOTSECTOR ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
use16
org 0x0
jmp start_of_code
 
if lang eq sp
include "kernelsp.inc" ; spanish kernel messages
else
version db 'Kolibri OS network development ',13,10,13,10,0
end if
 
include "boot/bootstr.inc" ; language-independent boot messages
include "boot/preboot.inc"
 
if lang eq ge
include "boot/bootge.inc" ; german system boot messages
else if lang eq sp
include "boot/bootsp.inc" ; spanish system boot messages
else if lang eq ru
include "boot/bootru.inc" ; russian system boot messages
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
else
include "boot/booten.inc" ; english system boot messages
end if
 
include "boot/bootcode.inc" ; 16 bit system boot code
include "bus/pci/pci16.inc"
include "detect/biosdisk.inc"
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SWITCH TO 32 BIT PROTECTED MODE ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
; CR0 Flags - Protected mode and Paging
 
mov ecx, CR0_PE
 
; Enabling 32 bit protected mode
 
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
 
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 0xffff
dw 0x0000
db 0x00
dw 11011111b *256 +10011010b
db 0x00
 
dw 0xffff
dw 0x0000
db 0x00
dw 11011111b *256 +10010010b
db 0x00
 
include "data16.inc"
 
use32
org $+0x10000
 
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, 0x006CC00 ; Set stack
 
; CLEAR 0x280000 - HEAP_BASE
 
xor eax, eax
mov edi, CLEAN_ZONE
mov ecx, (HEAP_BASE-OS_BASE-CLEAN_ZONE) / 4
cld
rep stosd
 
; CLEAR KERNEL UNDEFINED GLOBALS
mov edi, endofcode-OS_BASE
mov ecx, 0x90000
sub ecx, edi
shr ecx, 2
rep stosd
 
; SAVE & CLEAR 0-0xffff
 
xor esi, esi
mov edi, (BOOT_VAR-OS_BASE)
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 check_acpi
call init_BIOS32
; MEMORY MODEL
call mem_test
call init_mem
call init_page_map
 
; ENABLE PAGING
 
mov eax, sys_pgdir-OS_BASE
mov cr3, eax
 
mov eax, cr0
or eax, CR0_PG+CR0_WP
mov cr0, eax
 
lgdt [gdts]
jmp pword os_code:high_code
 
align 4
bios32_entry dd ?
tmp_page_tabs dd ?
 
use16
org $-0x10000
include "boot/shutdown.inc" ; shutdown or restart
org $+0x10000
use32
 
__DEBUG__ fix 1
__DEBUG_LEVEL__ fix 1
include 'init.inc'
 
org OS_BASE+$
 
include 'fdo.inc'
 
align 4
high_code:
mov ax, os_stack
mov bx, app_data
mov cx, app_tls
mov ss, ax
add esp, OS_BASE
 
mov ds, bx
mov es, bx
mov fs, cx
mov gs, bx
 
bt [cpu_caps], CAPS_PGE
jnc @F
 
or dword [sys_pgdir+(OS_BASE shr 20)], PG_GLOBAL
 
mov ebx, cr4
or ebx, CR4_PGE
mov cr4, ebx
@@:
xor eax, eax
mov dword [sys_pgdir], eax
mov dword [sys_pgdir+4], eax
 
mov eax, cr3
mov cr3, eax ; flush TLB
 
mov ecx, pg_data.mutex
call mutex_init
 
mov ecx, disk_list_mutex
call mutex_init
 
mov ecx, keyboard_list_mutex
call mutex_init
 
mov ecx, unpack_mutex
call mutex_init
 
; SAVE REAL MODE VARIABLES
mov ax, [BOOT_VAR + BOOT_IDE_BASE_ADDR]
mov [IDEContrRegsBaseAddr], ax
; --------------- APM ---------------------
 
; init selectors
mov ebx, [BOOT_VAR+BOOT_APM_ENTRY] ; offset of APM entry point
movzx eax, word [BOOT_VAR+BOOT_APM_CODE_32] ; real-mode segment base address of
; protected-mode 32-bit code segment
movzx ecx, word [BOOT_VAR+BOOT_APM_CODE_16]; real-mode segment base address of
; protected-mode 16-bit code segment
movzx edx, word [BOOT_VAR+BOOT_APM_DATA_16]; real-mode segment base address of
; protected-mode 16-bit data segment
 
shl eax, 4
mov [dword apm_code_32 + 2], ax
shr eax, 16
mov [dword apm_code_32 + 4], al
 
shl ecx, 4
mov [dword apm_code_16 + 2], cx
shr ecx, 16
mov [dword apm_code_16 + 4], cl
 
shl edx, 4
mov [dword apm_data_16 + 2], dx
shr edx, 16
mov [dword apm_data_16 + 4], dl
 
mov dword[apm_entry], ebx
mov word [apm_entry + 4], apm_code_32 - gdts
 
mov eax, [BOOT_VAR + BOOT_APM_VERSION] ; version & flags
mov [apm_vf], eax
; -----------------------------------------
mov al, [BOOT_VAR+BOOT_DMA] ; DMA access
mov [allow_dma_access], al
movzx eax, byte [BOOT_VAR+BOOT_BPP] ; bpp
mov [ScreenBPP], al
 
mov [_display.bpp], eax
mov [_display.vrefresh], 60
 
movzx eax, word [BOOT_VAR+BOOT_X_RES]; X max
mov [_display.width], eax
mov [display_width_standard], eax
dec eax
mov [Screen_Max_X], eax
mov [screen_workarea.right], eax
movzx eax, word [BOOT_VAR+BOOT_Y_RES]; Y max
mov [_display.height], eax
mov [display_height_standard], eax
dec eax
mov [Screen_Max_Y], eax
mov [screen_workarea.bottom], eax
movzx eax, word [BOOT_VAR+BOOT_VESA_MODE]; 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
movzx eax, word[BOOT_VAR+BOOT_PITCH] ; for other modes
mov [BytesPerScanLine], ax
mov [_display.pitch], eax
@@:
mov eax, [_display.width]
mul [_display.height]
mov [_WinMapSize], eax
 
call calculate_fast_getting_offset_for_WinMapAddress
; for Qemu or non standart video cards
; Unfortunately [BytesPerScanLine] does not always
; equal to [_display.width] * [ScreenBPP] / 8
call calculate_fast_getting_offset_for_LFB
 
mov esi, BOOT_VAR+0x9080
movzx ecx, byte [esi-1]
mov [NumBiosDisks], ecx
mov edi, BiosDisksData
rep movsd
 
; GRAPHICS ADDRESSES
 
mov eax, [BOOT_VAR+BOOT_LFB]
mov [LFBAddress], eax
 
cmp [SCR_MODE], word 0100000000000000b
jge setvesa20
cmp [SCR_MODE], word 0x13 ; EGA 320*200 256 colors
je v20ga32
jmp v20ga24
 
setvesa20:
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
jmp no_mode_0x12
v20ga24:
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:
 
mov [MOUSE_PICTURE], dword mousepointer
mov [_display.check_mouse], check_mouse_area_for_putpixel
mov [_display.check_m_pixel], check_mouse_area_for_getpixel
 
; -------- 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
; mov eax, sysenter_stack ; Check it
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
 
; !!!! 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 eax, syscall_entry
mov ecx, MSR_AMD_STAR
wrmsr
.noSYSCALL:
; -----------------------------------------
stdcall alloc_page
stdcall map_page, tss-0xF80, eax, PG_SW
stdcall alloc_page
inc eax
mov [SLOT_BASE+256+APPDATA.io_map], eax
stdcall map_page, tss+0x80, eax, PG_SW
stdcall alloc_page
inc eax
mov dword [SLOT_BASE+256+APPDATA.io_map+4], eax
stdcall map_page, tss+0x1080, eax, PG_SW
 
; LOAD IDT
 
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
 
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
;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 ax, tss0
ltr ax
 
mov [LFBSize], 0xC00000
call init_LFB
call init_fpu
call init_malloc
 
stdcall alloc_kernel_space, 0x51000
mov [default_io_map], eax
 
add eax, 0x2000
mov [ipc_tmp], eax
mov ebx, 0x1000
 
add eax, 0x40000
mov [proc_mem_map], eax
 
add eax, 0x8000
mov [proc_mem_pdir], eax
 
add eax, ebx
mov [proc_mem_tab], eax
 
add eax, ebx
mov [tmp_task_pdir], eax
 
add eax, ebx
mov [tmp_task_ptab], eax
 
add eax, ebx
mov [ipc_pdir], 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
 
mov [unpack.p], eax
 
call init_events
mov eax, srv.fd-SRV.fd
mov [srv.fd], eax
mov [srv.bk], eax
 
;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
 
stdcall kernel_alloc, [_WinMapSize]
mov [_WinMapAddress], eax
 
xor eax, eax
inc eax
mov [CURRENT_TASK], eax ;dword 1
mov [TASK_COUNT], eax ;dword 1
mov [TASK_BASE], dword TASK_DATA
mov [current_slot], SLOT_BASE+256
 
; set background
 
mov [BgrDrawMode], eax
mov [BgrDataWidth], eax
mov [BgrDataHeight], eax
mov [mem_BACKGROUND], 4
mov [img_background], static_background_data
 
; SET UP OS TASK
 
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
 
; 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.terminate_protection], 80000001h
 
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 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.tls_base], eax
 
; task list
mov dword [TASK_DATA+TASKDATA.mem_start], eax; process base address
inc eax
mov dword [CURRENT_TASK], eax
mov dword [TASK_COUNT], eax
mov [current_slot], SLOT_BASE+256
mov [TASK_BASE], dword TASK_DATA
mov byte[TASK_DATA+TASKDATA.wnd_number], al ; on screen number
mov dword [TASK_DATA+TASKDATA.pid], eax ; process id number
 
mov [SLOT_BASE + 256 + APPDATA.dir_table], sys_pgdir - OS_BASE
 
; REDIRECT ALL IRQ'S TO INT'S 0x20-0x2f
mov esi, boot_initirq
call boot_log
call init_irqs
 
mov esi, boot_picinit
call boot_log
call PIC_init
 
mov esi, boot_v86machine
call boot_log
; Initialize system V86 machine
call init_sys_v86
 
mov esi, boot_inittimer
call boot_log
; Initialize system timer (IRQ0)
call PIT_init
 
mov esi, boot_initapic
call boot_log
; Try to Initialize APIC
call APIC_init
 
mov esi, boot_enableirq
call boot_log
; Enable timer IRQ (IRQ0) and hard drives IRQs (IRQ14, IRQ15)
; they are used: when partitions are scanned, hd_read relies on timer
call unmask_timer
stdcall enable_irq, 2 ; @#$%! PIC
stdcall enable_irq, 6 ; FDD
stdcall enable_irq, 13 ; co-processor
stdcall enable_irq, 14
stdcall enable_irq, 15
 
mov esi, boot_enablint_ide
call boot_log
; Enable interrupts in IDE controller
mov al, 0
mov dx, 0x3F6
out dx, al
mov dl, 0x76
out dx, al
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!
; mov esi, boot_detectdisks
; call boot_log
;include 'detect/disks.inc'
mov esi, boot_detectfloppy
call boot_log
include 'detect/dev_fd.inc'
mov esi, boot_detecthdcd
call boot_log
include 'detect/dev_hdcd.inc'
mov esi, boot_getcache
call boot_log
include 'detect/getcache.inc'
mov esi, boot_detectpart
call boot_log
include 'detect/sear_par.inc'
;!!!!!!!!!!!!!!!!!!!!!!!!!!
 
mov esi, boot_init_sys
call boot_log
call Parser_params
 
if ~ defined extended_primary_loader
; ramdisk image should be loaded by extended primary loader if it exists
; READ RAMDISK IMAGE FROM HD
 
;!!!!!!!!!!!!!!!!!!!!!!!
include 'boot/rdload.inc'
;!!!!!!!!!!!!!!!!!!!!!!!
end if
; mov [dma_hdd],1
; CALCULATE FAT CHAIN FOR RAMDISK
 
call calculatefatchain
 
if 0
mov ax, [OS_BASE+0x10000+bx_from_load]
cmp ax, 'r1'; if using not ram disk, then load librares and parameters {SPraid.simba}
je no_lib_load
 
mov esi, boot_loadlibs
call boot_log
; 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
no_lib_load:
end if
 
; Display APIC status
mov esi, boot_APIC_found
cmp [irq_mode], IRQ_APIC
je @f
mov esi, boot_APIC_nfound
@@:
call boot_log
 
; PRINT AMOUNT OF MEMORY
mov esi, boot_memdetect
call boot_log
 
movzx ecx, word [boot_y]
if lang eq ru
or ecx, (10+30*6) shl 16
else if lang eq sp
or ecx, (10+33*6) shl 16
else
or ecx, (10+29*6) shl 16
end if
sub ecx, 10
mov edx, 0xFFFFFF
mov ebx, [MEM_AMOUNT]
shr ebx, 20
xor edi, edi
mov eax, 0x00040000
inc edi
call display_number_force
 
; BUILD SCHEDULER
 
; call build_scheduler; sys32.inc
 
; mov esi, boot_devices
; call boot_log
 
mov [pci_access_enabled], 1
call pci_enum
 
; SET PRELIMINARY WINDOW STACK AND POSITIONS
 
mov esi, boot_windefs
call boot_log
call set_window_defaults
 
; SET BACKGROUND DEFAULTS
 
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
 
call init_display
mov eax, [def_cursor]
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 ebx, 1000000
; div ebx
; ¢®®¡é¥-â® ¯à®¨§¢®¤¨â¥«ì­®áâì ¢ ¤ ­­®¬ ª®­ªà¥â­®¬ ¬¥áâ¥
; ᮢ¥à襭­® ­¥ªà¨â¨ç­ , ­® çâ®¡ë § âª­ãâì «î¡¨â¥«¥©
; ®¯â¨¬¨§¨àãîé¨å ª®¬¯¨«ïâ®à®¢ Ÿ‚“...
mov edx, 2251799814
mul edx
shr edx, 19
mov [stall_mcs], edx
; PRINT CPU FREQUENCY
mov esi, boot_cpufreq
call boot_log
 
mov ebx, edx
movzx ecx, word [boot_y]
if lang eq ru
add ecx, (10+19*6) shl 16 - 10 ; 'Determining amount of memory'
else if lang eq sp
add ecx, (10+25*6) shl 16 - 10 ; 'Determining amount of memory'
else
add ecx, (10+17*6) shl 16 - 10 ; 'Determining amount of memory'
end if
mov edx, 0xFFFFFF
xor edi, edi
mov eax, 0x00040000
inc edi
call display_number_force
 
; SET VARIABLES
 
call set_variables
 
; STACK AND FDC
 
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
no_pal_vga:
 
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
 
;protect io permission map
 
mov esi, [default_io_map]
stdcall map_page, esi, [SLOT_BASE+256+APPDATA.io_map], PG_MAP
add esi, 0x1000
stdcall map_page, esi, [SLOT_BASE+256+APPDATA.io_map+4], PG_MAP
 
stdcall map_page, tss._io_map_0, \
[SLOT_BASE+256+APPDATA.io_map], PG_MAP
stdcall map_page, tss._io_map_1, \
[SLOT_BASE+256+APPDATA.io_map+4], PG_MAP
 
mov ax, [OS_BASE+0x10000+bx_from_load]
 
; LOAD FIRST APPLICATION
cli
 
; cmp byte [BOOT_VAR+0x9030],1
; jne no_load_vrr_m
 
; mov ebp, vrr_m
; call fs_execute_from_sysdir
;
;; cmp eax,2 ; if vrr_m app found (PID=2)
; sub eax,2
; jz first_app_found
;
;no_load_vrr_m:
 
mov ebp, firstapp
call fs_execute_from_sysdir
 
; cmp eax,2 ; continue if a process has been loaded
test eax, eax
jns first_app_found
 
mov esi, boot_failed
call boot_log
 
mov eax, 0xDEADBEEF ; otherwise halt
hlt
 
first_app_found:
 
cli
 
;mov [TASK_COUNT],dword 2
push 1
pop dword [CURRENT_TASK] ; set OS task fisrt
 
; SET KEYBOARD PARAMETERS
mov al, 0xf6 ; reset keyboard, scan enabled
call kb_write
test ah, ah
jnz .no_keyboard
 
; wait until 8042 is ready
xor ecx, ecx
@@:
in al, 64h
and al, 00000010b
loopnz @b
 
iglobal
align 4
ps2_keyboard_functions:
dd .end - $
dd 0 ; no close
dd ps2_set_lights
.end:
endg
stdcall register_keyboard, ps2_keyboard_functions, 0
; mov al, 0xED ; Keyboard LEDs - only for testing!
; call kb_write
; call kb_read
; mov al, 111b
; call kb_write
; call kb_read
 
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
; call kb_read
;// mike.dld [
call set_lights
;// mike.dld ]
stdcall attach_int_handler, 1, irq1, 0
.no_keyboard:
 
; SET MOUSE
 
stdcall load_driver, szPS2MDriver
; stdcall load_driver, szCOM_MDriver
 
mov esi, boot_setmouse
call boot_log
call setmouse
 
; Setup serial output console (if enabled)
 
if defined debug_com_base
 
; enable Divisor latch
 
mov dx, debug_com_base+3
mov al, 1 shl 7
out dx, al
 
; Set speed to 115200 baud (max speed)
 
mov dx, debug_com_base
mov al, 0x01
out dx, al
 
mov dx, debug_com_base+1
mov al, 0x00
out dx, al
 
; No parity, 8bits words, one stop bit, dlab bit back to 0
 
mov dx, debug_com_base+3
mov al, 3
out dx, al
 
; disable interrupts
 
mov dx, debug_com_base+1
mov al, 0
out dx, al
 
; clear + enable fifo (64 bits)
 
mov dx, debug_com_base+2
mov al, 0x7 + 1 shl 5
out dx, al
 
 
end if
 
mov eax, [cpu_count]
test eax, eax
jnz @F
mov al, 1 ; at least one CPU
@@:
DEBUGF 1, "K : %d CPU detected\n", eax
 
; START MULTITASKING
 
; A 'All set - press ESC to start' messages if need
if preboot_blogesc
mov esi, boot_tasking
call boot_log
.bll1:
in al, 0x60 ; wait for ESC key press
cmp al, 129
jne .bll1
end if
 
cmp [IDEContrRegsBaseAddr], 0
setnz [dma_hdd]
mov [timer_ticks_enable], 1 ; for cd driver
 
sti
call change_task
 
jmp osloop
 
 
; Fly :)
 
include 'unpacker.inc'
 
align 4
boot_log:
pushad
 
mov ebx, 10*65536
mov bx, word [boot_y]
add [boot_y], dword 10
mov ecx, 0x80ffffff; ASCIIZ string with white color
xor edi, edi
mov edx, esi
inc edi
call dtext
 
mov [novesachecksum], 1000
call checkVga_N13
 
popad
 
ret
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; MAIN OS LOOP START ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 32
osloop:
; call [draw_pointer]
call __sys_draw_pointer
call window_check_events
call mouse_check_events
call checkmisc
call checkVga_N13
call stack_handler
call checkidle
call check_fdd_motor_status
call check_ATAPI_device_event
call check_lights_state
call check_timers
jmp osloop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; MAIN OS LOOP END ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
checkidle:
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
idle_loop_entry:
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
 
uglobal
idlemem dd 0x0
idleuse dd 0x0
idleusesec dd 0x0
check_idle_semaphore dd 0x0
endg
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; INCLUDED SYSTEM FILES ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
include "kernel32.inc"
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; KERNEL FUNCTIONS ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
reserve_irqs_ports:
 
 
; RESERVE PORTS
mov eax, RESERVED_PORTS
mov ecx, 1
 
mov [eax], dword 4
 
mov [eax+16], ecx
mov [eax+16+4], dword 0
mov [eax+16+4], dword 0x2D
 
mov [eax+32], ecx
mov [eax+32+4], dword 0x30
mov [eax+32+8], dword 0x4D
 
mov [eax+48], ecx
mov [eax+48+4], dword 0x50
mov [eax+28+8], dword 0xDF
 
mov [eax+64], ecx
mov [eax+64+4], dword 0xE5
mov [eax+64+8], dword 0xFF
 
ret
 
 
iglobal
process_number dd 0x1
endg
 
set_variables:
 
mov ecx, 0x16 ; flush port 0x60
.fl60:
in al, 0x60
loop .fl60
push eax
 
mov ax, [BOOT_VAR+BOOT_Y_RES]
shr ax, 1
shl eax, 16
mov ax, [BOOT_VAR+BOOT_X_RES]
shr ax, 1
mov [MOUSE_X], eax
 
xor eax, eax
mov [BTN_ADDR], dword BUTTON_INFO ; address of button list
 
mov byte [MOUSE_BUFF_COUNT], al ; mouse buffer
mov byte [KEY_COUNT], al ; keyboard buffer
mov byte [BTN_COUNT], al ; button buffer
; mov [MOUSE_X],dword 100*65536+100 ; mouse x/y
 
;!! IP 04.02.2005:
mov byte [DONT_SWITCH], al; change task if possible
pop eax
ret
 
align 4
;input eax=43,bl-byte of output, ecx - number of port
sys_outport:
 
mov edi, ecx ; separate flag for read / write
and ecx, 65535
 
mov eax, [RESERVED_PORTS]
test eax, eax
jnz .sopl8
inc eax
mov [esp+32], eax
ret
 
.sopl8:
mov edx, [TASK_BASE]
mov edx, [edx+0x4]
;and ecx,65535
;cld - set on interrupt 0x40
.sopl1:
 
mov esi, eax
shl esi, 4
add esi, RESERVED_PORTS
cmp edx, [esi+0]
jne .sopl2
cmp ecx, [esi+4]
jb .sopl2
cmp ecx, [esi+8]
jg .sopl2
.sopl3:
 
test edi, 0x80000000; read ?
jnz .sopl4
 
mov eax, ebx
mov dx, cx ; write
out dx, al
and [esp+32], dword 0
ret
 
.sopl2:
 
dec eax
jnz .sopl1
inc eax
mov [esp+32], eax
ret
 
 
.sopl4:
 
mov dx, cx ; read
in al, dx
and eax, 0xff
and [esp+32], dword 0
mov [esp+20], eax
ret
 
display_number:
;It is not optimization
mov eax, ebx
mov ebx, ecx
mov ecx, edx
mov edx, esi
mov esi, edi
; eax = print type, al=0 -> ebx is number
; al=1 -> ebx is pointer
; ah=0 -> display decimal
; ah=1 -> display hexadecimal
; ah=2 -> display binary
; eax bits 16-21 = number of digits to display (0-32)
; eax bits 22-31 = reserved
;
; ebx = number or pointer
; ecx = x shl 16 + y
; edx = color
xor edi, edi
display_number_force:
push eax
and eax, 0x3fffffff
cmp eax, 0xffff ; length > 0 ?
pop eax
jge cont_displ
ret
cont_displ:
push eax
and eax, 0x3fffffff
cmp eax, 61*0x10000 ; length <= 60 ?
pop eax
jb cont_displ2
ret
cont_displ2:
 
pushad
 
cmp al, 1 ; ecx is a pointer ?
jne displnl1
mov ebp, ebx
add ebp, 4
mov ebp, [ebp+std_application_base_address]
mov ebx, [ebx+std_application_base_address]
displnl1:
sub esp, 64
 
test ah, ah ; DECIMAL
jnz no_display_desnum
shr eax, 16
and eax, 0xC03f
; and eax,0x3f
push eax
and eax, 0x3f
mov edi, esp
add edi, 4+64-1
mov ecx, eax
mov eax, ebx
mov ebx, 10
d_desnum:
xor edx, edx
call division_64_bits
div ebx
add dl, 48
mov [edi], dl
dec edi
loop d_desnum
pop eax
call normalize_number
call draw_num_text
add esp, 64
popad
ret
no_display_desnum:
 
cmp ah, 0x01 ; HEXADECIMAL
jne no_display_hexnum
shr eax, 16
and eax, 0xC03f
; and eax,0x3f
push eax
and eax, 0x3f
mov edi, esp
add edi, 4+64-1
mov ecx, eax
mov eax, ebx
mov ebx, 16
d_hexnum:
xor edx, edx
call division_64_bits
div ebx
hexletters = __fdo_hexdigits
add edx, hexletters
mov dl, [edx]
mov [edi], dl
dec edi
loop d_hexnum
pop eax
call normalize_number
call draw_num_text
add esp, 64
popad
ret
no_display_hexnum:
 
cmp ah, 0x02 ; BINARY
jne no_display_binnum
shr eax, 16
and eax, 0xC03f
; and eax,0x3f
push eax
and eax, 0x3f
mov edi, esp
add edi, 4+64-1
mov ecx, eax
mov eax, ebx
mov ebx, 2
d_binnum:
xor edx, edx
call division_64_bits
div ebx
add dl, 48
mov [edi], dl
dec edi
loop d_binnum
pop eax
call normalize_number
call draw_num_text
add esp, 64
popad
ret
no_display_binnum:
 
add esp, 64
popad
ret
 
normalize_number:
test ah, 0x80
jz .continue
mov ecx, 48
and eax, 0x3f
@@:
inc edi
cmp [edi], cl
jne .continue
dec eax
cmp eax, 1
ja @r
mov al, 1
.continue:
and eax, 0x3f
ret
 
division_64_bits:
test [esp+1+4], byte 0x40
jz .continue
push eax
mov eax, ebp
div ebx
mov ebp, eax
pop eax
.continue:
ret
 
draw_num_text:
mov esi, eax
mov edx, 64+4
sub edx, eax
add edx, esp
mov ebx, [esp+64+32-8+4]
; add window start x & y
mov ecx, [TASK_BASE]
 
mov edi, [CURRENT_TASK]
shl edi, 8
 
mov eax, [ecx-twdw+WDATA.box.left]
add eax, [edi+SLOT_BASE+APPDATA.wnd_clientbox.left]
shl eax, 16
add eax, [ecx-twdw+WDATA.box.top]
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]
jmp dtext
 
align 4
 
sys_setup:
 
; 1=roland mpu midi base , base io address
; 2=keyboard 1, base kaybap 2, shift keymap, 9 country 1eng 2fi 3ger 4rus
; 3=cd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave
; 5=system language, 1eng 2fi 3ger 4rus
; 7=hd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave
; 8=fat32 partition in hd
; 9
; 10 = sound dma channel
; 11 = enable lba read
; 12 = enable pci access
 
 
and [esp+32], dword 0
dec ebx ; MIDI
jnz nsyse1
cmp ecx, 0x100
 
jb nsyse1
mov esi, 65535
cmp esi, ecx
 
jb nsyse1
mov [midi_base], cx ;bx
mov word [mididp], cx;bx
inc cx ;bx
mov word [midisp], cx;bx
ret
 
iglobal
midi_base dw 0
endg
 
nsyse1:
dec ebx ; KEYBOARD
jnz nsyse2
mov edi, [TASK_BASE]
mov eax, [edi+TASKDATA.mem_start]
add eax, edx
 
dec ecx
jnz kbnobase
mov ebx, keymap
mov ecx, 128
call memmove
ret
kbnobase:
dec ecx
jnz kbnoshift
 
mov ebx, keymap_shift
mov ecx, 128
call memmove
ret
kbnoshift:
dec ecx
jnz kbnoalt
mov ebx, keymap_alt
mov ecx, 128
call memmove
ret
kbnoalt:
sub ecx, 6
jnz kbnocountry
mov word [keyboard], dx
ret
kbnocountry:
mov [esp+32], dword 1
ret
nsyse2:
dec ebx ; CD
jnz nsyse4
 
test ecx, ecx
jz nosesl
 
cmp ecx, 4
ja nosesl
mov [cd_base], cl
 
dec ecx
jnz noprma
mov [cdbase], 0x1f0
mov [cdid], 0xa0
noprma:
 
dec ecx
jnz noprsl
mov [cdbase], 0x1f0
mov [cdid], 0xb0
noprsl:
dec ecx
jnz nosema
mov [cdbase], 0x170
mov [cdid], 0xa0
nosema:
dec ecx
jnz nosesl
mov [cdbase], 0x170
mov [cdid], 0xb0
nosesl:
ret
 
iglobal
cd_base db 0
 
endg
nsyse4:
 
sub ebx, 2 ; SYSTEM LANGUAGE
jnz nsyse5
mov [syslang], ecx
ret
nsyse5:
 
sub ebx, 2 ; HD BASE
jnz nsyse7
 
test ecx, ecx
jz nosethd
 
cmp ecx, 4
ja nosethd
mov [hd_base], cl
 
cmp ecx, 1
jnz noprmahd
mov [hdbase], 0x1f0
and dword [hdid], 0x0
mov dword [hdpos], ecx
; call set_FAT32_variables
noprmahd:
 
cmp ecx, 2
jnz noprslhd
mov [hdbase], 0x1f0
mov [hdid], 0x10
mov dword [hdpos], ecx
; call set_FAT32_variables
noprslhd:
 
cmp ecx, 3
jnz nosemahd
mov [hdbase], 0x170
and dword [hdid], 0x0
mov dword [hdpos], ecx
; call set_FAT32_variables
nosemahd:
 
cmp ecx, 4
jnz noseslhd
mov [hdbase], 0x170
mov [hdid], 0x10
mov dword [hdpos], ecx
; call set_FAT32_variables
noseslhd:
call reserve_hd1
call reserve_hd_channel
call free_hd_channel
and dword [hd1_status], 0 ; free
nosethd:
ret
 
iglobal
hd_base db 0
endg
 
nsyse7:
 
; cmp eax,8 ; HD PARTITION
dec ebx
jnz nsyse8
mov [fat32part], ecx
; call set_FAT32_variables
call reserve_hd1
call reserve_hd_channel
call free_hd_channel
; pusha
call choice_necessity_partition_1
; popa
and dword [hd1_status], 0 ; free
ret
 
nsyse8:
; cmp eax,11 ; ENABLE LBA READ
and ecx, 1
sub ebx, 3
jnz no_set_lba_read
mov [lba_read_enabled], ecx
ret
 
no_set_lba_read:
; cmp eax,12 ; ENABLE PCI ACCESS
dec ebx
jnz sys_setup_err
mov [pci_access_enabled], ecx
ret
 
sys_setup_err:
or [esp+32], dword -1
ret
 
align 4
 
sys_getsetup:
 
; 1=roland mpu midi base , base io address
; 2=keyboard 1, base kaybap 2, shift keymap, 9 country 1eng 2fi 3ger 4rus
; 3=cd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave
; 5=system language, 1eng 2fi 3ger 4rus
; 7=hd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave
; 8=fat32 partition in hd
; 9=get hs timer tic
 
; cmp eax,1
dec ebx
jnz ngsyse1
movzx eax, [midi_base]
mov [esp+32], eax
ret
ngsyse1:
; cmp eax,2
dec ebx
jnz ngsyse2
 
mov edi, [TASK_BASE]
mov ebx, [edi+TASKDATA.mem_start]
add ebx, edx
 
; cmp ebx,1
dec ecx
jnz kbnobaseret
mov eax, keymap
mov ecx, 128
call memmove
ret
kbnobaseret:
; cmp ebx,2
dec ecx
jnz kbnoshiftret
 
mov eax, keymap_shift
mov ecx, 128
call memmove
ret
kbnoshiftret:
; cmp ebx,3
dec ecx
jne kbnoaltret
 
mov eax, keymap_alt
mov ecx, 128
call memmove
ret
kbnoaltret:
; cmp ebx,9
sub ecx, 6
jnz ngsyse2
movzx eax, word [keyboard]
mov [esp+32], eax
ret
 
 
ngsyse2:
; cmp eax,3
dec ebx
jnz ngsyse3
movzx eax, [cd_base]
mov [esp+32], eax
ret
ngsyse3:
; cmp eax,5
sub ebx, 2
jnz ngsyse5
mov eax, [syslang]
mov [esp+32], eax
ret
ngsyse5:
; cmp eax,7
sub ebx, 2
jnz ngsyse7
movzx eax, [hd_base]
mov [esp+32], eax
ret
ngsyse7:
; cmp eax,8
dec ebx
jnz ngsyse8
mov eax, [fat32part]
mov [esp+32], eax
ret
ngsyse8:
; cmp eax,9
dec ebx
jnz ngsyse9
mov eax, [timer_ticks];[0xfdf0]
mov [esp+32], eax
ret
ngsyse9:
; cmp eax,11
sub ebx, 2
jnz ngsyse11
mov eax, [lba_read_enabled]
mov [esp+32], eax
ret
ngsyse11:
; cmp eax,12
dec ebx
jnz ngsyse12
mov eax, [pci_access_enabled]
mov [esp+32], eax
ret
ngsyse12:
mov [esp+32], dword 1
ret
 
 
get_timer_ticks:
mov eax, [timer_ticks]
ret
 
iglobal
align 4
mousefn dd msscreen, mswin, msbutton, msset
dd app_load_cursor
dd app_set_cursor
dd app_delete_cursor
dd msz
endg
 
readmousepos:
 
; eax=0 screen relative
; eax=1 window relative
; eax=2 buttons pressed
; eax=3 set mouse pos ; reserved
; eax=4 load cursor
; eax=5 set cursor
; eax=6 delete cursor ; reserved
; eax=7 get mouse_z
 
cmp ebx, 7
ja msset
jmp [mousefn+ebx*4]
msscreen:
mov eax, [MOUSE_X]
shl eax, 16
mov ax, [MOUSE_Y]
mov [esp+36-4], 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 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-4], eax
ret
msbutton:
movzx eax, byte [BTN_DOWN]
mov [esp+36-4], 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-4], eax
and [MOUSE_SCROLL_H], word 0
and [MOUSE_SCROLL_V], word 0
ret
@@:
and [esp+36-4], dword 0
; ret
msset:
ret
 
app_load_cursor:
cmp ecx, OS_BASE
jae msset
stdcall load_cursor, ecx, edx
mov [esp+36-4], eax
ret
 
app_set_cursor:
stdcall set_cursor, ecx
mov [esp+36-4], eax
ret
 
app_delete_cursor:
stdcall delete_cursor, ecx
mov [esp+36-4], eax
ret
 
is_input:
 
push 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
ret
 
 
get_mpu_in:
 
push edx
mov dx, word [mididp]
in al, dx
pop edx
ret
 
 
put_mpu_out:
 
push edx
mov dx, word [mididp]
out dx, al
pop edx
ret
 
 
 
align 4
 
sys_midi:
cmp [mididp], 0
jnz sm0
mov [esp+36], dword 1
ret
sm0:
and [esp+36], dword 0
dec ebx
jnz smn1
; call setuart
su1:
call is_output
test al, al
jnz su1
mov dx, word [midisp]
mov al, 0xff
out dx, al
su2:
mov dx, word [midisp]
mov al, 0xff
out dx, al
call is_input
test al, al
jnz su2
call get_mpu_in
cmp al, 0xfe
jnz su2
su3:
call is_output
test al, al
jnz su3
mov dx, word [midisp]
mov al, 0x3f
out dx, al
ret
smn1:
dec ebx
jnz smn2
sm10:
call get_mpu_in
call is_output
test al, al
jnz sm10
mov al, bl
call put_mpu_out
smn2:
ret
 
detect_devices:
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;include 'detect/commouse.inc'
;include 'detect/ps2mouse.inc'
;include 'detect/dev_fd.inc'
;include 'detect/dev_hdcd.inc'
;include 'detect/sear_par.inc'
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ret
 
sys_end:
;--------------------------------------
cmp [_display.select_cursor], 0
je @f
; restore default cursor before killing
pusha
mov ecx, [current_slot]
call restore_default_cursor_before_killing
popa
@@:
;--------------------------------------
; kill all sockets this process owns
pusha
mov edx, [TASK_BASE]
mov edx, [edx+TASKDATA.pid]
call SOCKET_process_end
popa
;--------------------------------------
mov ecx, [current_slot]
mov eax, [ecx+APPDATA.tls_base]
test eax, eax
jz @F
 
stdcall user_free, eax
@@:
 
mov eax, [TASK_BASE]
mov [eax+TASKDATA.state], 3; terminate this program
 
waitterm: ; wait here for termination
mov ebx, 100
call delay_hs
jmp waitterm
;------------------------------------------------------------------------------
align 4
restore_default_cursor_before_killing:
pushfd
cli
mov eax, [def_cursor]
mov [ecx+APPDATA.cursor], eax
 
movzx eax, word [MOUSE_Y]
movzx ebx, word [MOUSE_X]
; mov ecx, [Screen_Max_X]
; inc ecx
; mul ecx
mov eax, [d_width_calc_area + eax*4]
 
add eax, [_WinMapAddress]
movzx edx, byte [ebx+eax]
shl edx, 8
mov esi, [edx+SLOT_BASE+APPDATA.cursor]
 
cmp esi, [current_cursor]
je @f
 
push esi
call [_display.select_cursor]
mov [current_cursor], esi
@@:
mov [redrawmouse_unconditional], 1
popfd
; call [draw_pointer]
call __sys_draw_pointer
ret
;------------------------------------------------------------------------------
iglobal
align 4
sys_system_table:
dd sysfn_deactivate ; 1 = deactivate window
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 sysfn_min_windows ; 23 = minimize all windows
dd sysfn_set_screen_sizes ; 24 = set screen sizes for Vesa
sysfn_num = ($ - sys_system_table)/4
endg
;------------------------------------------------------------------------------
sys_system:
dec ebx
cmp ebx, sysfn_num
jae @f
jmp dword [sys_system_table + ebx*4]
@@:
ret
;------------------------------------------------------------------------------
sysfn_shutdown: ; 18.9 = system shutdown
cmp ecx, 1
jl exit_for_anyone
cmp ecx, 4
jg exit_for_anyone
mov [BOOT_VAR+0x9030], cl
 
mov eax, [TASK_COUNT]
mov [SYS_SHUTDOWN], al
mov [shutdown_processes], eax
and dword [esp+32], 0
exit_for_anyone:
ret
uglobal
shutdown_processes:
dd 0x0
endg
;------------------------------------------------------------------------------
sysfn_terminate: ; 18.2 = TERMINATE
push ecx
cmp ecx, 2
jb noprocessterminate
mov edx, [TASK_COUNT]
cmp ecx, edx
ja noprocessterminate
mov eax, [TASK_COUNT]
shl ecx, 5
mov edx, [ecx+CURRENT_TASK+TASKDATA.pid]
add ecx, CURRENT_TASK+TASKDATA.state
cmp byte [ecx], 9
jz noprocessterminate
push ecx edx
lea edx, [(ecx-(CURRENT_TASK and 1FFFFFFFh)-TASKDATA.state)*8+SLOT_BASE]
call request_terminate
pop edx ecx
test eax, eax
jz noprocessterminate
;--------------------------------------
; terminate all network sockets it used
pusha
call SOCKET_process_end
popa
;--------------------------------------
cmp [_display.select_cursor], 0
je .restore_end
; restore default cursor before killing
pusha
mov ecx, [esp+32]
shl ecx, 8
add ecx, SLOT_BASE
mov eax, [def_cursor]
cmp [ecx+APPDATA.cursor], eax
je @f
call restore_default_cursor_before_killing
@@:
popa
.restore_end:
;--------------------------------------
;call MEM_Heap_Lock ;guarantee that process isn't working with heap
mov [ecx], byte 3; clear possible i40's
;call MEM_Heap_UnLock
 
cmp edx, [application_table_status]; clear app table stat
jne noatsc
and [application_table_status], 0
noatsc:
noprocessterminate:
add esp, 4
ret
;------------------------------------------------------------------------------
sysfn_terminate2:
;lock application_table_status mutex
.table_status:
cli
cmp [application_table_status], 0
je .stf
sti
call change_task
jmp .table_status
.stf:
call set_application_table_status
mov eax, ecx
call pid_to_slot
test eax, eax
jz .not_found
mov ecx, eax
cli
call sysfn_terminate
and [application_table_status], 0
sti
and dword [esp+32], 0
ret
.not_found:
mov [application_table_status], 0
or dword [esp+32], -1
ret
;------------------------------------------------------------------------------
sysfn_deactivate: ; 18.1 = DEACTIVATE WINDOW
cmp ecx, 2
jb .nowindowdeactivate
cmp ecx, [TASK_COUNT]
ja .nowindowdeactivate
 
movzx esi, word [WIN_STACK + ecx*2]
cmp esi, 1
je .nowindowdeactivate ; already deactive
 
mov edi, ecx
shl edi, 5
add edi, window_data
movzx esi, word [WIN_STACK + ecx * 2]
lea esi, [WIN_POS + esi * 2]
call window._.window_deactivate
 
xor eax, eax
mov byte[MOUSE_BACKGROUND], al
mov byte[DONT_DRAW_MOUSE], al
mov byte[MOUSE_DOWN], 0
 
call syscall_display_settings._.calculate_whole_screen
call syscall_display_settings._.redraw_whole_screen
.nowindowdeactivate:
ret
;------------------------------------------------------------------------------
sysfn_activate: ; 18.3 = ACTIVATE WINDOW
cmp ecx, 2
jb .nowindowactivate
cmp ecx, [TASK_COUNT]
ja .nowindowactivate
 
mov [window_minimize], 2; restore window if minimized
 
movzx esi, word [WIN_STACK + ecx*2]
cmp esi, [TASK_COUNT]
je .nowindowactivate; already active
 
mov edi, ecx
shl edi, 5
add edi, window_data
movzx esi, word [WIN_STACK + ecx * 2]
lea esi, [WIN_POS + esi * 2]
call waredraw
.nowindowactivate:
ret
;------------------------------------------------------------------------------
sysfn_getidletime: ; 18.4 = GET IDLETIME
mov eax, [idleusesec]
mov [esp+32], eax
ret
;------------------------------------------------------------------------------
sysfn_getcpuclock: ; 18.5 = GET TSC/SEC
mov eax, [CPU_FREQ]
mov [esp+32], eax
ret
;------------------------------------------------------------------------------
; SAVE ramdisk to /hd/1/menuet.img
;!!!!!!!!!!!!!!!!!!!!!!!!
include 'blkdev/rdsave.inc'
;!!!!!!!!!!!!!!!!!!!!!!!!
;------------------------------------------------------------------------------
align 4
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
; cmp ecx,1
dec ecx
jnz nogetsoundflag
movzx eax, byte [sound_flag]; get sound_flag
mov [esp+32], eax
ret
nogetsoundflag:
; cmp ecx,2
dec ecx
jnz nosoundflag
xor byte [sound_flag], 1
nosoundflag:
ret
;------------------------------------------------------------------------------
sysfn_minimize: ; 18.10 = minimize window
mov [window_minimize], 1
ret
;------------------------------------------------------------------------------
align 4
sysfn_getdiskinfo: ; 18.11 = get disk info table
; cmp ecx,1
dec ecx
jnz full_table
small_table:
call for_all_tables
mov ecx, 10
cld
rep movsb
ret
for_all_tables:
mov edi, edx
mov esi, DRIVE_DATA
ret
full_table:
; cmp ecx,2
dec ecx
jnz exit_for_anyone
call for_all_tables
mov ecx, 16384
cld
rep movsd
ret
;------------------------------------------------------------------------------
sysfn_lastkey: ; 18.12 = return 0 (backward compatibility)
and dword [esp+32], 0
ret
;------------------------------------------------------------------------------
sysfn_getversion: ; 18.13 = get kernel ID and version
mov edi, ecx
mov esi, version_inf
mov ecx, version_end-version_inf
rep movsb
ret
;------------------------------------------------------------------------------
sysfn_waitretrace: ; 18.14 = sys wait retrace
;wait retrace functions
sys_wait_retrace:
mov edx, 0x3da
WaitRetrace_loop:
in al, dx
test al, 1000b
jz WaitRetrace_loop
and [esp+32], dword 0
ret
;------------------------------------------------------------------------------
align 4
sysfn_centermouse: ; 18.15 = mouse centered
; removed here by <Lrz>
; call mouse_centered
;* 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
; ret
;* mouse centered - end code- Mario79
xor eax, eax
and [esp+32], eax
; pop eax
ret
;------------------------------------------------------------------------------
align 4
sysfn_mouse_acceleration: ; 18.19 = set/get mouse features
test ecx, ecx; get mouse speed factor
jnz .set_mouse_acceleration
xor eax, eax
mov ax, [mouse_speed_factor]
mov [esp+32], eax
ret
.set_mouse_acceleration:
; cmp ecx,1 ; set mouse speed factor
dec ecx
jnz .get_mouse_delay
mov [mouse_speed_factor], dx
ret
.get_mouse_delay:
; cmp ecx,2 ; get mouse delay
dec ecx
jnz .set_mouse_delay
mov eax, [mouse_delay]
mov [esp+32], eax
ret
.set_mouse_delay:
; cmp ecx,3 ; set mouse delay
dec ecx
jnz .set_pointer_position
mov [mouse_delay], edx
ret
.set_pointer_position:
; cmp ecx,4 ; set mouse pointer position
dec ecx
jnz .set_mouse_button
cmp dx, word[Screen_Max_Y]
ja .end
rol edx, 16
cmp dx, word[Screen_Max_X]
ja .end
mov [MOUSE_X], edx
ret
.set_mouse_button:
; cmp ecx,5 ; set mouse button features
dec ecx
jnz .end
mov [BTN_DOWN], dl
mov [mouse_active], 1
.end:
ret
;------------------------------------------------------------------------------
sysfn_getfreemem:
mov eax, [pg_data.pages_free]
shl eax, 2
mov [esp+32], eax
ret
;------------------------------------------------------------------------------
sysfn_getallmem:
mov eax, [MEM_AMOUNT]
shr eax, 10
mov [esp+32], eax
ret
;------------------------------------------------------------------------------
sysfn_pid_to_slot:
mov eax, ecx
call pid_to_slot
mov [esp+32], eax
ret
;------------------------------------------------------------------------------
sysfn_min_rest_window:
pushad
mov eax, edx ; ebx - operating
shr ecx, 1
jnc @f
call pid_to_slot
@@:
or eax, eax ; eax - number of slot
jz .error
cmp eax, 255 ; varify maximal slot number
ja .error
movzx eax, word [WIN_STACK + eax*2]
shr ecx, 1
jc .restore
; .minimize:
call minimize_window
jmp .exit
.restore:
call restore_minimized_window
.exit:
popad
xor eax, eax
mov [esp+32], eax
ret
.error:
popad
xor eax, eax
dec eax
mov [esp+32], eax
ret
;------------------------------------------------------------------------------
sysfn_min_windows:
call minimize_all_window
mov [esp+32], eax
call change_task
ret
;------------------------------------------------------------------------------
sysfn_set_screen_sizes:
cmp [SCR_MODE], word 0x13
jbe .exit
 
cmp [_display.select_cursor], select_cursor
jne .exit
 
cmp ecx, [display_width_standard]
ja .exit
 
cmp edx, [display_height_standard]
ja .exit
 
pushfd
cli
mov eax, ecx
mov ecx, [BytesPerScanLine]
mov [_display.width], eax
dec eax
mov [_display.height], edx
dec edx
; eax - new Screen_Max_X
; edx - new Screen_Max_Y
mov [do_not_touch_winmap], 1
call set_screen
mov [do_not_touch_winmap], 0
popfd
call change_task
.exit:
ret
;------------------------------------------------------------------------------
uglobal
screen_workarea RECT
display_width_standard dd 0
display_height_standard dd 0
do_not_touch_winmap db 0
window_minimize db 0
sound_flag db 0
 
endg
 
UID_NONE=0
UID_MENUETOS=1 ;official
UID_KOLIBRI=2 ;russian
 
iglobal
version_inf:
db 0,7,7,0 ; version 0.7.7.0
db 0
dd __REV__
version_end:
endg
;------------------------------------------------------------------------------
align 4
sys_cachetodiskette:
cmp ebx, 1
jne .no_floppy_a_save
mov [flp_number], 1
jmp .save_image_on_floppy
;--------------------------------------
align 4
.no_floppy_a_save:
cmp ebx, 2
jne .no_floppy_b_save
mov [flp_number], 2
;--------------------------------------
align 4
.save_image_on_floppy:
call save_image
mov [esp + 32], dword 0
cmp [FDC_Status], 0
je .yes_floppy_save
;--------------------------------------
align 4
.no_floppy_b_save:
mov [esp + 32], dword 1
;--------------------------------------
align 4
.yes_floppy_save:
ret
;------------------------------------------------------------------------------
uglobal
; bgrchanged dd 0x0
align 4
bgrlockpid dd 0
bgrlock db 0
endg
;------------------------------------------------------------------------------
align 4
sys_background:
cmp ebx, 1 ; BACKGROUND SIZE
jnz nosb1
test ecx, ecx
jz sbgrr
 
test edx, edx
jz sbgrr
;--------------------------------------
align 4
@@:
;;Maxis use atomic bts for mutexes 4.4.2009
bts dword [bgrlock], 0
jnc @f
call change_task
jmp @b
;--------------------------------------
align 4
@@:
mov [BgrDataWidth], ecx
mov [BgrDataHeight], edx
; mov [bgrchanged],1
 
pushad
; return memory for old background
mov eax, [img_background]
cmp eax, static_background_data
jz @f
stdcall kernel_free, eax
;--------------------------------------
align 4
@@:
; calculate RAW size
xor eax, eax
inc eax
cmp [BgrDataWidth], eax
jae @f
mov [BgrDataWidth], eax
;--------------------------------------
align 4
@@:
cmp [BgrDataHeight], eax
jae @f
mov [BgrDataHeight], eax
;--------------------------------------
align 4
@@:
mov eax, [BgrDataWidth]
imul eax, [BgrDataHeight]
lea eax, [eax*3]
; it is reserved with aligned to the boundary of 4 KB pages,
; otherwise there may be exceptions a page fault for vesa20_drawbackground_tiled
; because the 32 bit read is used for high performance: "mov eax,[esi]"
shr eax, 12
inc eax
shl eax, 12
mov [mem_BACKGROUND], eax
; get memory for new background
stdcall kernel_alloc, eax
test eax, eax
jz .memfailed
mov [img_background], eax
jmp .exit
;--------------------------------------
align 4
.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
;--------------------------------------
align 4
.exit:
popad
mov [bgrlock], 0
;--------------------------------------
align 4
sbgrr:
ret
;------------------------------------------------------------------------------
align 4
nosb1:
cmp ebx, 2 ; SET PIXEL
jnz nosb2
 
mov eax, [img_background]
test ecx, ecx
jz @f
cmp eax, static_background_data
jz .ret
;--------------------------------------
align 4
@@:
mov ebx, [mem_BACKGROUND]
add ebx, 4095
and ebx, -4096
sub ebx, 4
cmp ecx, ebx
ja .ret
 
mov ebx, [eax+ecx]
and ebx, 0xFF000000;255*256*256*256
and edx, 0x00FFFFFF;255*256*256+255*256+255
add edx, ebx
mov [eax+ecx], edx
;--------------------------------------
align 4
.ret:
ret
;------------------------------------------------------------------------------
align 4
nosb2:
cmp ebx, 3 ; DRAW BACKGROUND
jnz nosb3
;--------------------------------------
align 4
draw_background_temp:
mov [background_defined], 1
call force_redraw_background
;--------------------------------------
align 4
nosb31:
ret
;------------------------------------------------------------------------------
align 4
nosb3:
cmp ebx, 4 ; TILED / STRETCHED
jnz nosb4
cmp ecx, [BgrDrawMode]
je nosb41
mov [BgrDrawMode], ecx
;--------------------------------------
align 4
nosb41:
ret
;------------------------------------------------------------------------------
align 4
nosb4:
cmp ebx, 5 ; BLOCK MOVE TO BGR
jnz nosb5
cmp [img_background], static_background_data
jnz @f
test edx, edx
jnz .fin
cmp esi, 4
ja .fin
;--------------------------------------
align 4
@@:
; bughere
mov eax, ecx
mov ebx, edx
add ebx, [img_background];IMG_BACKGROUND
mov ecx, esi
call memmove
;--------------------------------------
align 4
.fin:
ret
;------------------------------------------------------------------------------
align 4
nosb5:
cmp ebx, 6
jnz nosb6
;--------------------------------------
align 4
;;Maxis use atomic bts for mutex 4.4.2009
@@:
bts dword [bgrlock], 0
jnc @f
call change_task
jmp @b
;--------------------------------------
align 4
@@:
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
;--------------------------------------
align 4
.z:
mov eax, [page_tabs+ebx*4]
test al, 1
jz @f
call free_page
;--------------------------------------
align 4
@@:
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
;--------------------------------------
align 4
.nomem:
and [bgrlockpid], 0
mov [bgrlock], 0
;------------------------------------------------------------------------------
align 4
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
dec ecx
;--------------------------------------
align 4
@@:
and dword [page_tabs+eax*4], 0
mov edx, eax
shl edx, 12
push eax
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
;--------------------------------------
align 4
.err:
and dword [esp+32], 0
ret
;------------------------------------------------------------------------------
align 4
nosb7:
cmp ebx, 8
jnz nosb8
 
mov eax, [BG_Rect_X_left_right]
mov [esp + 32], eax ; eax = [left]*65536 + [right]
mov eax, [BG_Rect_Y_top_bottom]
mov [esp + 20], eax ; ebx = [top]*65536 + [bottom]
ret
;------------------------------------------------------------------------------
align 4
nosb8:
cmp ebx, 9
jnz nosb9
; ecx = [left]*65536 + [right]
; edx = [top]*65536 + [bottom]
mov eax, [Screen_Max_X]
mov ebx, [Screen_Max_Y]
; check [right]
cmp cx, ax
ja .exit
; check [left]
ror ecx, 16
cmp cx, ax
ja .exit
; check [bottom]
cmp dx, bx
ja .exit
; check [top]
ror edx, 16
cmp dx, bx
ja .exit
 
movzx eax, cx ; [left]
movzx ebx, dx ; [top]
 
shr ecx, 16 ; [right]
shr edx, 16 ; [bottom]
 
mov [background_defined], 1
 
mov [draw_data+32 + RECT.left], eax
mov [draw_data+32 + RECT.top], ebx
 
mov [draw_data+32 + RECT.right], ecx
mov [draw_data+32 + RECT.bottom], edx
 
inc byte[REDRAW_BACKGROUND]
;--------------------------------------
align 4
.exit:
ret
;------------------------------------------------------------------------------
align 4
nosb9:
ret
;------------------------------------------------------------------------------
align 4
uglobal
BG_Rect_X_left_right dd 0x0
BG_Rect_Y_top_bottom dd 0x0
endg
;------------------------------------------------------------------------------
align 4
force_redraw_background:
and [draw_data+32 + RECT.left], 0
and [draw_data+32 + RECT.top], 0
push eax ebx
mov eax, [Screen_Max_X]
mov ebx, [Screen_Max_Y]
mov [draw_data+32 + RECT.right], eax
mov [draw_data+32 + RECT.bottom], ebx
pop ebx eax
inc byte[REDRAW_BACKGROUND]
ret
;------------------------------------------------------------------------------
align 4
sys_getbackground:
; cmp eax,1 ; SIZE
dec ebx
jnz nogb1
mov eax, [BgrDataWidth]
shl eax, 16
mov ax, [BgrDataHeight]
mov [esp+32], eax
ret
;------------------------------------------------------------------------------
align 4
nogb1:
; cmp eax,2 ; PIXEL
dec ebx
jnz nogb2
 
mov eax, [img_background]
test ecx, ecx
jz @f
cmp eax, static_background_data
jz .ret
;--------------------------------------
align 4
@@:
mov ebx, [mem_BACKGROUND]
add ebx, 4095
and ebx, -4096
sub ebx, 4
cmp ecx, ebx
ja .ret
 
mov eax, [ecx+eax]
 
and eax, 0xFFFFFF
mov [esp+32], eax
;--------------------------------------
align 4
.ret:
ret
;------------------------------------------------------------------------------
align 4
nogb2:
 
; cmp eax,4 ; TILED / STRETCHED
dec ebx
dec ebx
jnz nogb4
mov eax, [BgrDrawMode]
;--------------------------------------
align 4
nogb4:
mov [esp+32], eax
ret
;------------------------------------------------------------------------------
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
;--------------------------------------
align 4
.ret_eax:
mov [esp + 32], eax
ret
;--------------------------------------
align 4
.finish:
; test hotkeys buffer
mov ecx, hotkey_buffer
;--------------------------------------
align 4
@@:
cmp [ecx], ebx
jz .found
add ecx, 8
cmp ecx, hotkey_buffer + 120 * 8
jb @b
ret
;--------------------------------------
align 4
.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
;------------------------------------------------------------------------------
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]
and al, 0xFE ; delete left button bit
mov [BTN_COUNT], byte 0
mov [esp + 32], eax
;--------------------------------------
align 4
.exit:
ret
;------------------------------------------------------------------------------
align 4
sys_cpuusage:
 
; RETURN:
;
; +00 dword process cpu usage
; +04 word position in windowing stack
; +06 word windowing stack value at current position (cpu nro)
; +10 12 bytes name
; +22 dword start in mem
; +26 dword used mem
; +30 dword PID , process idenfification number
;
 
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
 
; +4: word: position of the window of thread in the window stack
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
 
shl ecx, 5
 
; +0: dword: memory usage
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
 
; +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
.os_mem:
stosd
lea eax, [edx-1]
stosd
 
; +30: PID/TID
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
 
; Process state (+50)
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
 
; Window state
mov al, [ecx+window_data+WDATA.fl_wstate]
stosb
 
; Event mask (+71)
mov EAX, dword [ECX+CURRENT_TASK+TASKDATA.event_mask]
stosd
 
pop esi
pop edi
 
.nofillbuf:
; return number of processes
 
mov eax, [TASK_COUNT]
mov [esp+32], eax
ret
 
align 4
sys_clock:
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
@@:
; 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
 
 
align 4
 
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
@@:
 
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]
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
sys_newba:
dec ebx
jz end_of_buttons_away
 
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
 
jmp sys_newba2
 
end_of_buttons_away:
 
ret
 
no_widgets_away:
 
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
 
srl1:
ret
 
;ok - 100% work
;nt - not tested
;---------------------------------------------------------------------------------------------
;eax
;0 - task switch counter. Ret switch counter in eax. Block. ok.
;1 - change task. Ret nothing. Block. ok.
;2 - performance control
; ebx
; 0 - enable or disable (inversion) PCE flag on CR4 for rdmpc in user mode.
; returned new cr4 in eax. Ret cr4 in eax. Block. ok.
; 1 - is cache enabled. Ret cr0 in eax if enabled else zero in eax. Block. ok.
; 2 - enable cache. Ret 1 in eax. Ret nothing. Block. ok.
; 3 - disable cache. Ret 0 in eax. Ret nothing. Block. ok.
;eax
;3 - rdmsr. Counter in edx. (edx:eax) [esi:edi, edx] => [edx:esi, ecx]. Ret in ebx:eax. Block. ok.
;4 - wrmsr. Counter in edx. (edx:eax) [esi:edi, edx] => [edx:esi, ecx]. Ret in ebx:eax. Block. ok.
;---------------------------------------------------------------------------------------------
iglobal
align 4
sheduler:
dd sys_sheduler.00
dd change_task
dd sys_sheduler.02
dd sys_sheduler.03
dd sys_sheduler.04
endg
sys_sheduler:
;rewritten by <Lrz> 29.12.2009
jmp dword [sheduler+ebx*4]
;.shed_counter:
.00:
mov eax, [context_counter]
mov [esp+32], eax
ret
 
.02:
;.perf_control:
inc ebx ;before ebx=2, ebx=3
cmp ebx, ecx ;if ecx=3, ebx=3
jz cache_disable
 
dec ebx ;ebx=2
cmp ebx, ecx ;
jz cache_enable ;if ecx=2 and ebx=2
 
dec ebx ;ebx=1
cmp ebx, ecx
jz is_cache_enabled ;if ecx=1 and ebx=1
 
dec ebx
test ebx, ecx ;ebx=0 and ecx=0
jz modify_pce ;if ecx=0
 
ret
 
.03:
;.rdmsr_instr:
;now counter in ecx
;(edx:eax) esi:edi => edx:esi
mov eax, esi
mov ecx, edx
rdmsr
mov [esp+32], eax
mov [esp+20], edx ;ret in ebx?
ret
 
.04:
;.wrmsr_instr:
;now counter in ecx
;(edx:eax) esi:edi => edx:esi
; Fast Call MSR can't be destroy
; ® MSR_AMD_EFER ¬®¦­® ¨§¬¥­ïâì, â.ª. ¢ í⮬ ॣ¨áâॠ«¨è
; ¢ª«îç îâáï/¢ëª«îç îâáï à áè¨à¥­­ë¥ ¢®§¬®¦­®áâ¨
cmp edx, MSR_SYSENTER_CS
je @f
cmp edx, MSR_SYSENTER_ESP
je @f
cmp edx, MSR_SYSENTER_EIP
je @f
cmp edx, MSR_AMD_STAR
je @f
 
mov eax, esi
mov ecx, edx
wrmsr
; mov [esp + 32], eax
; mov [esp + 20], edx ;ret in ebx?
@@:
ret
 
cache_disable:
mov eax, cr0
or eax, 01100000000000000000000000000000b
mov cr0, eax
wbinvd ;set MESI
ret
 
cache_enable:
mov eax, cr0
and eax, 10011111111111111111111111111111b
mov cr0, eax
ret
 
is_cache_enabled:
mov eax, cr0
mov ebx, eax
and eax, 01100000000000000000000000000000b
jz cache_disabled
mov [esp+32], ebx
cache_disabled:
mov dword [esp+32], eax;0
ret
 
modify_pce:
mov eax, cr4
; mov ebx,0
; or bx,100000000b ;pce
; xor eax,ebx ;invert pce
bts eax, 8;pce=cr4[8]
mov cr4, eax
mov [esp+32], eax
ret
;---------------------------------------------------------------------------------------------
 
 
; check if pixel is allowed to be drawn
 
;checkpixel:
; push eax edx
 
;; mov edx, [Screen_Max_X] ; screen x size
;; inc edx
;; imul edx, ebx
; mov edx, [d_width_calc_area + ebx*4]
; add eax, [_WinMapAddress]
; mov dl, [eax+edx]; lea eax, [...]
 
; xor ecx, ecx
; mov eax, [CURRENT_TASK]
; cmp al, dl
; setne cl
 
; pop edx eax
; ret
 
iglobal
cpustring db 'CPU',0
endg
 
uglobal
background_defined db 0 ; diamond, 11.04.2006
endg
;-----------------------------------------------------------------------------
align 4
checkmisc:
cmp [ctrl_alt_del], 1
jne nocpustart
 
mov ebp, cpustring
call fs_execute_from_sysdir
 
mov [ctrl_alt_del], 0
;--------------------------------------
align 4
nocpustart:
cmp [mouse_active], 1
jne mouse_not_active
mov [mouse_active], 0
 
xor edi, edi
mov ebx, CURRENT_TASK
 
mov ecx, [TASK_COUNT]
movzx eax, word [WIN_POS + ecx*2] ; active window
shl eax, 8
push eax
 
movzx eax, word [MOUSE_X]
movzx edx, word [MOUSE_Y]
;--------------------------------------
align 4
.set_mouse_event:
add edi, 256
add ebx, 32
test [ebx+TASKDATA.event_mask], 0x80000000
jz .pos_filter
 
cmp edi, [esp] ; skip if filtration active
jne .skip
;--------------------------------------
align 4
.pos_filter:
test [ebx+TASKDATA.event_mask], 0x40000000
jz .set
 
mov esi, [ebx-twdw+WDATA.box.left]
cmp eax, esi
jb .skip
add esi, [ebx-twdw+WDATA.box.width]
cmp eax, esi
ja .skip
 
mov esi, [ebx-twdw+WDATA.box.top]
cmp edx, esi
jb .skip
add esi, [ebx-twdw+WDATA.box.height]
cmp edx, esi
ja .skip
;--------------------------------------
align 4
.set:
or [edi+SLOT_BASE+APPDATA.event_mask], 100000b ; set event 6
;--------------------------------------
align 4
.skip:
loop .set_mouse_event
 
pop eax
;--------------------------------------
align 4
mouse_not_active:
cmp byte[REDRAW_BACKGROUND], 0 ; background update ?
jz nobackgr
 
cmp [background_defined], 0
jz nobackgr
;--------------------------------------
align 4
@@:
push eax
mov eax, [draw_data+32 + RECT.left]
shl eax, 16
add eax, [draw_data+32 + RECT.right]
mov [BG_Rect_X_left_right], eax ; [left]*65536 + [right]
 
mov eax, [draw_data+32 + RECT.top]
shl eax, 16
add eax, [draw_data+32 + RECT.bottom]
mov [BG_Rect_Y_top_bottom], eax ; [top]*65536 + [bottom]
pop eax
 
call drawbackground
; DEBUGF 1, "K : drawbackground\n"
; DEBUGF 1, "K : backg x %x\n",[BG_Rect_X_left_right]
; DEBUGF 1, "K : backg y %x\n",[BG_Rect_Y_top_bottom]
;--------- set event 5 start ----------
push ecx edi
xor edi, edi
mov ecx, [TASK_COUNT]
;--------------------------------------
align 4
set_bgr_event:
add edi, 256
or [edi+SLOT_BASE+APPDATA.event_mask], 10000b ; set event 5
loop set_bgr_event
pop edi ecx
; call change_task - because the application must have time to call f.15.8
call change_task
;--------- set event 5 stop -----------
dec byte[REDRAW_BACKGROUND] ; got new update request?
jnz @b
 
mov [draw_data+32 + RECT.left], eax
mov [draw_data+32 + RECT.top], eax
mov [draw_data+32 + RECT.right], eax
mov [draw_data+32 + RECT.bottom], eax
mov [MOUSE_BACKGROUND], byte 0
;--------------------------------------
align 4
nobackgr:
; system shutdown request
cmp [SYS_SHUTDOWN], byte 0
je noshutdown
 
mov edx, [shutdown_processes]
 
cmp [SYS_SHUTDOWN], dl
jne noshutdown
 
lea ecx, [edx-1]
mov edx, OS_BASE+0x3040
jecxz no_mark_system_shutdown
;--------------------------------------
align 4
markz:
push ecx edx
cmp [edx+TASKDATA.state], 9
jz .nokill
lea edx, [(edx-(CURRENT_TASK and 1FFFFFFFh))*8+SLOT_BASE]
cmp [edx+APPDATA.dir_table], sys_pgdir - OS_BASE
jz .nokill
call request_terminate
jmp .common
.nokill:
dec byte [SYS_SHUTDOWN]
xor eax, eax
.common:
pop edx ecx
test eax, eax
jz @f
mov [edx+TASKDATA.state], byte 3
@@:
add edx, 0x20
loop markz
;--------------------------------------
align 4
@@:
no_mark_system_shutdown:
dec byte [SYS_SHUTDOWN]
je system_shutdown
;--------------------------------------
align 4
noshutdown:
mov eax, [TASK_COUNT] ; termination
mov ebx, TASK_DATA+TASKDATA.state
mov esi, 1
;--------------------------------------
align 4
newct:
mov cl, [ebx]
cmp cl, byte 3
jz .terminate
 
cmp cl, byte 4
jnz .noterminate
.terminate:
pushad
call terminate
popad
cmp byte [SYS_SHUTDOWN], 0
jz .noterminate
dec byte [SYS_SHUTDOWN]
je system_shutdown
 
.noterminate:
add ebx, 0x20
inc esi
dec eax
jnz newct
ret
;-----------------------------------------------------------------------------
align 4
redrawscreen:
; eax , if process window_data base is eax, do not set flag/limits
 
pushad
push eax
 
;;; mov ebx,2
;;; call delay_hs
 
;mov ecx,0 ; redraw flags for apps
xor ecx, ecx
;--------------------------------------
align 4
newdw2:
inc ecx
push ecx
 
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 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 ecx, [draw_limits.bottom] ; ecx = area y end ebx = window y start
cmp ecx, ebx
jb ricino
 
mov ecx, [draw_limits.right] ; 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, [draw_limits.top] ; eax = area y start edx = window y end
cmp edx, eax
jb ricino
 
mov eax, [draw_limits.left] ; eax = area x start ecx = window x end
cmp ecx, eax
jb ricino
;--------------------------------------
align 4
bgli:
cmp dword[esp], 1
jnz .az
 
cmp byte[REDRAW_BACKGROUND], 0
jz .az
 
mov dl, 0
lea eax, [edi+draw_data-window_data]
mov ebx, [draw_limits.left]
cmp ebx, [eax+RECT.left]
jae @f
 
mov [eax+RECT.left], ebx
mov dl, 1
;--------------------------------------
align 4
@@:
mov ebx, [draw_limits.top]
cmp ebx, [eax+RECT.top]
jae @f
 
mov [eax+RECT.top], ebx
mov dl, 1
;--------------------------------------
align 4
@@:
mov ebx, [draw_limits.right]
cmp ebx, [eax+RECT.right]
jbe @f
 
mov [eax+RECT.right], ebx
mov dl, 1
;--------------------------------------
align 4
@@:
mov ebx, [draw_limits.bottom]
cmp ebx, [eax+RECT.bottom]
jbe @f
 
mov [eax+RECT.bottom], ebx
mov dl, 1
;--------------------------------------
align 4
@@:
add byte[REDRAW_BACKGROUND], dl
jmp newdw8
;--------------------------------------
align 4
.az:
mov eax, edi
add eax, draw_data-window_data
 
mov ebx, [draw_limits.left] ; set limits
mov [eax + RECT.left], ebx
mov ebx, [draw_limits.top]
mov [eax + RECT.top], ebx
mov ebx, [draw_limits.right]
mov [eax + RECT.right], ebx
mov ebx, [draw_limits.bottom]
mov [eax + RECT.bottom], ebx
 
sub eax, draw_data-window_data
 
cmp dword [esp], 1
jne nobgrd
inc byte[REDRAW_BACKGROUND]
;--------------------------------------
align 4
newdw8:
nobgrd:
 
mov [eax + WDATA.fl_redraw], byte 1 ; mark as redraw
;--------------------------------------
align 4
ricino:
not_this_task:
pop ecx
 
cmp ecx, [TASK_COUNT]
jle newdw2
 
pop eax
popad
ret
;-----------------------------------------------------------------------------
align 4
calculatebackground: ; background
mov edi, [_WinMapAddress] ; set os to use all pixels
mov eax, 0x01010101
mov ecx, [_WinMapSize]
shr ecx, 2
rep stosd
 
mov byte[REDRAW_BACKGROUND], 0 ; do not draw background!
ret
;-----------------------------------------------------------------------------
uglobal
imax dd 0x0
endg
;-----------------------------------------------------------------------------
align 4
delay_ms: ; delay in 1/1000 sec
push eax
push ecx
 
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
;--------------------------------------
align 4
cnt1:
in al, 0x61
and al, 0x10
cmp al, ah
jz cnt1
 
mov ah, al
loop cnt1
 
pop ecx
pop eax
ret
;-----------------------------------------------------------------------------
align 4
set_app_param:
mov edi, [TASK_BASE]
mov eax, ebx
btr eax, 3 ; move MOUSE_FILTRATION
mov ebx, [current_slot] ; bit into event_filter
setc byte [ebx+APPDATA.event_filter]
xchg eax, [edi + TASKDATA.event_mask] ; set new event mask
mov [esp+32], eax ; return old mask value
ret
;-----------------------------------------------------------------------------
 
; this is for syscall
proc delay_hs_unprotected
call unprotect_from_terminate
call delay_hs
call protect_from_terminate
ret
endp
 
align 4
delay_hs: ; delay in 1/100 secs
; ebx = delay time
push ecx
push edx
 
mov edx, [timer_ticks]
;--------------------------------------
align 4
newtic:
mov ecx, [timer_ticks]
sub ecx, edx
cmp ecx, ebx
jae zerodelay
 
call change_task
 
jmp newtic
;--------------------------------------
align 4
zerodelay:
pop edx
pop ecx
ret
;-----------------------------------------------------------------------------
align 16 ;very often call this subrutine
memmove: ; memory move in bytes
; eax = from
; ebx = to
; ecx = no of bytes
test ecx, ecx
jle .ret
 
push esi edi ecx
 
mov edi, ebx
mov esi, eax
 
test ecx, not 11b
jz @f
 
push ecx
shr ecx, 2
rep movsd
pop ecx
and ecx, 11b
jz .finish
;--------------------------------------
align 4
@@:
rep movsb
;--------------------------------------
align 4
.finish:
pop ecx edi esi
;--------------------------------------
align 4
.ret:
ret
;-----------------------------------------------------------------------------
; <diamond> Sysfunction 34, read_floppy_file, is obsolete. Use 58 or 70 function instead.
;align 4
;
;read_floppy_file:
;
;; as input
;;
;; eax pointer to file
;; ebx file lenght
;; ecx start 512 byte block number
;; edx number of blocks to read
;; esi pointer to return/work area (atleast 20 000 bytes)
;;
;;
;; on return
;;
;; eax = 0 command succesful
;; 1 no fd base and/or partition defined
;; 2 yet unsupported FS
;; 3 unknown FS
;; 4 partition not defined at hd
;; 5 file not found
;; ebx = size of file
;
; mov edi,[TASK_BASE]
; add edi,0x10
; add esi,[edi]
; add eax,[edi]
;
; pushad
; mov edi,esi
; add edi,1024
; mov esi,0x100000+19*512
; sub ecx,1
; shl ecx,9
; add esi,ecx
; shl edx,9
; mov ecx,edx
; cld
; rep movsb
; popad
;
; mov [esp+36],eax
; mov [esp+24],ebx
; ret
 
 
 
align 4
set_io_access_rights:
push edi eax
mov edi, tss._io_map_0
; mov ecx,eax
; and ecx,7 ; offset in byte
; shr eax,3 ; number of byte
; add edi,eax
; mov ebx,1
; shl ebx,cl
test ebp, ebp
; cmp ebp,0 ; enable access - ebp = 0
jnz .siar1
; not ebx
; and [edi],byte bl
btr [edi], eax
pop eax edi
ret
.siar1:
bts [edi], eax
; or [edi],byte bl ; disable access - ebp = 1
pop eax edi
ret
;reserve/free group of ports
; * eax = 46 - number function
; * ebx = 0 - reserve, 1 - free
; * ecx = number start arrea of ports
; * edx = number end arrea of ports (include last number of port)
;Return value:
; * eax = 0 - succesful
; * eax = 1 - error
; * The system has reserve this ports:
; 0..0x2d, 0x30..0x4d, 0x50..0xdf, 0xe5..0xff (include last number of port).
;destroys eax,ebx, ebp
r_f_port_area:
 
test ebx, ebx
jnz free_port_area
; je r_port_area
; jmp free_port_area
 
; r_port_area:
 
; pushad
 
cmp ecx, edx ; beginning > end ?
ja rpal1
cmp edx, 65536
jae rpal1
mov eax, [RESERVED_PORTS]
test eax, eax ; no reserved areas ?
je rpal2
cmp eax, 255 ; max reserved
jae rpal1
rpal3:
mov ebx, eax
shl ebx, 4
add ebx, RESERVED_PORTS
cmp ecx, [ebx+8]
ja rpal4
cmp edx, [ebx+4]
jae rpal1
; jb rpal4
; jmp rpal1
rpal4:
dec eax
jnz rpal3
jmp rpal2
rpal1:
; popad
; mov eax,1
xor eax, eax
inc eax
ret
rpal2:
; popad
; enable port access at port IO map
cli
pushad ; start enable io map
 
cmp edx, 65536;16384
jae no_unmask_io; jge
mov eax, ecx
; push ebp
xor ebp, ebp ; enable - eax = port
new_port_access:
; pushad
call set_io_access_rights
; popad
inc eax
cmp eax, edx
jbe new_port_access
; pop ebp
no_unmask_io:
popad ; end enable io map
sti
 
mov eax, [RESERVED_PORTS]
add eax, 1
mov [RESERVED_PORTS], eax
shl eax, 4
add eax, RESERVED_PORTS
mov ebx, [TASK_BASE]
mov ebx, [ebx+TASKDATA.pid]
mov [eax], ebx
mov [eax+4], ecx
mov [eax+8], edx
 
xor eax, eax
ret
 
free_port_area:
 
; pushad
mov eax, [RESERVED_PORTS]; no reserved areas ?
test eax, eax
jz frpal2
mov ebx, [TASK_BASE]
mov ebx, [ebx+TASKDATA.pid]
frpal3:
mov edi, eax
shl edi, 4
add edi, RESERVED_PORTS
cmp ebx, [edi]
jne frpal4
cmp ecx, [edi+4]
jne frpal4
cmp edx, [edi+8]
jne frpal4
jmp frpal1
frpal4:
dec eax
jnz frpal3
frpal2:
; popad
inc eax
ret
frpal1:
push ecx
mov ecx, 256
sub ecx, eax
shl ecx, 4
mov esi, edi
add esi, 16
cld
rep movsb
 
dec dword [RESERVED_PORTS]
;popad
;disable port access at port IO map
 
; pushad ; start disable io map
pop eax ;start port
cmp edx, 65536;16384
jge no_mask_io
 
; mov eax,ecx
xor ebp, ebp
inc ebp
new_port_access_disable:
; pushad
; mov ebp,1 ; disable - eax = port
call set_io_access_rights
; popad
inc eax
cmp eax, edx
jbe new_port_access_disable
no_mask_io:
; popad ; end disable io map
xor eax, eax
ret
;-----------------------------------------------------------------------------
align 4
drawbackground:
dbrv20:
cmp [BgrDrawMode], dword 1
jne bgrstr
call vesa20_drawbackground_tiled
; call [draw_pointer]
call __sys_draw_pointer
ret
;--------------------------------------
align 4
bgrstr:
call vesa20_drawbackground_stretch
; call [draw_pointer]
call __sys_draw_pointer
ret
;-----------------------------------------------------------------------------
align 4
syscall_putimage: ; PutImage
sys_putimage:
test ecx, 0x80008000
jnz .exit
test ecx, 0x0000FFFF
jz .exit
test ecx, 0xFFFF0000
jnz @f
;--------------------------------------
align 4
.exit:
ret
;--------------------------------------
align 4
@@:
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
;--------------------------------------
align 4
.forced:
push ebp esi 0
mov ebp, putimage_get24bpp
mov esi, putimage_init24bpp
;--------------------------------------
align 4
sys_putimage_bpp:
call vesa20_putimage
pop ebp esi ebp
ret
; jmp [draw_pointer]
;-----------------------------------------------------------------------------
align 4
sys_putimage_palette:
; ebx = pointer to image
; ecx = [xsize]*65536 + [ysize]
; edx = [xstart]*65536 + [ystart]
; 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
;--------------------------------------
align 4
.forced:
cmp esi, 1
jnz @f
push edi
mov eax, [edi+4]
sub eax, [edi]
push eax
push dword [edi]
push 0ffffff80h
mov edi, esp
call put_mono_image
add esp, 12
pop edi
ret
;--------------------------------------
align 4
@@:
cmp esi, 2
jnz @f
push edi
push 0ffffff80h
mov edi, esp
call put_2bit_image
pop eax
pop edi
ret
;--------------------------------------
align 4
@@:
cmp esi, 4
jnz @f
push edi
push 0ffffff80h
mov edi, esp
call put_4bit_image
pop eax
pop edi
ret
;--------------------------------------
align 4
@@:
push ebp esi ebp
cmp esi, 8
jnz @f
mov ebp, putimage_get8bpp
mov esi, putimage_init8bpp
jmp sys_putimage_bpp
;--------------------------------------
align 4
@@:
cmp esi, 9
jnz @f
mov ebp, putimage_get9bpp
mov esi, putimage_init9bpp
jmp sys_putimage_bpp
;--------------------------------------
align 4
@@:
cmp esi, 15
jnz @f
mov ebp, putimage_get15bpp
mov esi, putimage_init15bpp
jmp sys_putimage_bpp
;--------------------------------------
align 4
@@:
cmp esi, 16
jnz @f
mov ebp, putimage_get16bpp
mov esi, putimage_init16bpp
jmp sys_putimage_bpp
;--------------------------------------
align 4
@@:
cmp esi, 24
jnz @f
mov ebp, putimage_get24bpp
mov esi, putimage_init24bpp
jmp sys_putimage_bpp
;--------------------------------------
align 4
@@:
cmp esi, 32
jnz @f
mov ebp, putimage_get32bpp
mov esi, putimage_init32bpp
jmp sys_putimage_bpp
;--------------------------------------
align 4
@@:
pop ebp esi ebp
ret
;-----------------------------------------------------------------------------
align 4
put_mono_image:
push ebp esi ebp
mov ebp, putimage_get1bpp
mov esi, putimage_init1bpp
jmp sys_putimage_bpp
;-----------------------------------------------------------------------------
align 4
put_2bit_image:
push ebp esi ebp
mov ebp, putimage_get2bpp
mov esi, putimage_init2bpp
jmp sys_putimage_bpp
;-----------------------------------------------------------------------------
align 4
put_4bit_image:
push ebp esi ebp
mov ebp, putimage_get4bpp
mov esi, putimage_init4bpp
jmp sys_putimage_bpp
;-----------------------------------------------------------------------------
align 4
putimage_init24bpp:
lea eax, [eax*3]
putimage_init8bpp:
putimage_init9bpp:
ret
;-----------------------------------------------------------------------------
align 16
putimage_get24bpp:
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
;-----------------------------------------------------------------------------
align 16
putimage_get9bpp:
lodsb
mov ah, al
shl eax, 8
mov al, ah
ret 4
;-----------------------------------------------------------------------------
align 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
;-----------------------------------------------------------------------------
align 16
putimage_get1bpp:
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
;-----------------------------------------------------------------------------
align 4
putimage_init2bpp:
add eax, ecx
push ecx
add ecx, 3
add eax, 3
shr ecx, 2
shr eax, 2
sub eax, ecx
pop ecx
ret
;-----------------------------------------------------------------------------
align 16
putimage_get2bpp:
push edx
mov edx, [esp+8]
mov al, [edx]
mov ah, al
shr al, 6
shl ah, 2
jnz .nonewbyte
lodsb
mov ah, al
shr al, 6
shl ah, 2
add ah, 1
.nonewbyte:
mov [edx], ah
mov edx, [edx+4]
movzx eax, al
mov eax, [edx+eax*4]
pop edx
ret 4
;-----------------------------------------------------------------------------
align 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
;-----------------------------------------------------------------------------
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
@@:
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
;-----------------------------------------------------------------------------
align 4
putimage_init32bpp:
shl eax, 2
ret
;-----------------------------------------------------------------------------
align 16
putimage_get32bpp:
lodsd
ret 4
;-----------------------------------------------------------------------------
align 4
putimage_init15bpp:
putimage_init16bpp:
add eax, eax
ret
;-----------------------------------------------------------------------------
align 16
putimage_get15bpp:
; 0RRRRRGGGGGBBBBB -> 00000000RRRRR000GGGGG000BBBBB000
push ecx edx
movzx eax, word [esi]
add esi, 2
mov ecx, eax
mov edx, eax
and eax, 0x1F
and ecx, 0x1F shl 5
and edx, 0x1F shl 10
shl eax, 3
shl ecx, 6
shl edx, 9
or eax, ecx
or eax, edx
pop edx ecx
ret 4
;-----------------------------------------------------------------------------
align 16
putimage_get16bpp:
; RRRRRGGGGGGBBBBB -> 00000000RRRRR000GGGGGG00BBBBB000
push ecx edx
movzx eax, word [esi]
add esi, 2
mov ecx, eax
mov edx, eax
and eax, 0x1F
and ecx, 0x3F shl 5
and edx, 0x1F shl 11
shl eax, 3
shl ecx, 5
shl edx, 8
or eax, ecx
or eax, edx
pop edx ecx
ret 4
;-----------------------------------------------------------------------------
;align 4
; eax x beginning
; ebx y beginning
; ecx x 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]
;--------------------------------------
;align 4
;.forced:
; call vesa20_drawbar
; call [draw_pointer]
; ret
;-----------------------------------------------------------------------------
align 4
kb_read:
 
push ecx edx
 
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
kr_ready:
push ecx
mov ecx, 32
kr_delay:
loop kr_delay
pop ecx
in al, 0x60
xor ah, ah
kr_exit:
 
pop edx ecx
 
ret
;-----------------------------------------------------------------------------
align 4
kb_write:
 
push ecx edx
 
mov dl, al
; mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's
; kw_loop1:
; in al,0x64
; test al,0x20
; jz kw_ok1
; loop kw_loop1
; mov ah,1
; jmp kw_exit
; kw_ok1:
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
kw_ok:
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
kw_ok3:
mov ah, 8
kw_loop4:
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
kw_ok4:
xor ah, ah
kw_exit:
 
pop edx ecx
 
ret
;-----------------------------------------------------------------------------
align 4
kb_cmd:
 
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
c_send:
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
c_error:
mov ah, 1
jmp c_exit
c_ok:
xor ah, ah
c_exit:
ret
 
 
setmouse: ; set mousepicture -pointer
; ps2 mouse enable
 
; mov [MOUSE_PICTURE], dword mousepointer
 
cli
 
ret
 
if used _rdtsc
_rdtsc:
bt [cpu_caps], CAPS_TSC
jnc ret_rdtsc
rdtsc
ret
ret_rdtsc:
mov edx, 0xffffffff
mov eax, 0xffffffff
ret
end if
 
sys_msg_board_str:
 
pushad
@@:
cmp [esi], byte 0
je @f
mov eax, 1
movzx ebx, byte [esi]
call sys_msg_board
inc esi
jmp @b
@@:
popad
ret
 
sys_msg_board_byte:
; in: al = byte to display
; out: nothing
; destroys: nothing
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
 
sys_msg_board_dword:
; in: eax = dword to display
; out: nothing
; destroys: nothing
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
 
msg_board_data_size = 65536 ; Must be power of two
 
uglobal
msg_board_data rb msg_board_data_size
msg_board_count dd 0x0
endg
 
sys_msg_board:
 
; 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
 
if defined debug_com_base
 
push dx ax
 
@@: ; Wait for empty transmit register (yes, this slows down system..)
mov dx, debug_com_base+5
in al, dx
test al, 1 shl 5
jz @r
 
mov dx, debug_com_base ; Output the byte
mov al, bl
out dx, al
 
pop ax dx
 
end if
 
mov [msg_board_data+ecx], bl
inc ecx
and ecx, msg_board_data_size - 1
mov [msg_board_count], ecx
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
.smbl21:
mov [esp+36], ecx
mov [esp+24], ecx
.smbl2:
ret
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 66 sys function. ;;
;; in eax=66,ebx in [0..5],ecx,edx ;;
;; out eax ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
iglobal
align 4
f66call:
dd sys_process_def.1 ; 1 = set keyboard mode
dd sys_process_def.2 ; 2 = get keyboard mode
dd sys_process_def.3 ; 3 = get keyboard ctrl, alt, shift
dd sys_process_def.4 ; 4 = set system-wide hotkey
dd sys_process_def.5 ; 5 = delete installed hotkey
dd sys_process_def.6 ; 6 = disable input, work only hotkeys
dd sys_process_def.7 ; 7 = enable input, opposition to f.66.6
endg
;-----------------------------------------------------------------------------
align 4
sys_process_def:
dec ebx
cmp ebx, 7
jae .not_support ;if >=8 then or eax,-1
 
mov edi, [CURRENT_TASK]
jmp dword [f66call+ebx*4]
 
.not_support:
or eax, -1
ret
;-----------------------------------------------------------------------------
align 4
.1:
shl edi, 8
mov [edi+SLOT_BASE + APPDATA.keyboard_mode], cl
 
ret
;-----------------------------------------------------------------------------
align 4
.2: ; 2 = get keyboard mode
shl edi, 8
movzx eax, byte [SLOT_BASE+edi + APPDATA.keyboard_mode]
mov [esp+32], eax
ret
;-----------------------------------------------------------------------------
align 4
.3: ;3 = get keyboard ctrl, alt, shift
mov eax, [kb_state]
mov [esp+32], eax
ret
;-----------------------------------------------------------------------------
align 4
.4:
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+32], 1
ret
.found_free:
mov [eax+8], edi
mov [eax+4], edx
movzx ecx, cl
lea ecx, [hotkey_scancodes+ecx*4]
mov edx, [ecx]
mov [eax], edx
mov [ecx], eax
mov [eax+12], ecx
test edx, edx
jz @f
mov [edx+12], eax
@@:
and dword [esp+32], 0
ret
;-----------------------------------------------------------------------------
align 4
.5:
movzx ebx, cl
lea ebx, [hotkey_scancodes+ebx*4]
mov eax, [ebx]
.scan:
test eax, eax
jz .notfound
cmp [eax+8], edi
jnz .next
cmp [eax+4], edx
jz .found
.next:
mov eax, [eax]
jmp .scan
.notfound:
mov dword [esp+32], 1
ret
.found:
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+32], edx
ret
;-----------------------------------------------------------------------------
align 4
.6:
pushfd
cli
mov eax, [PID_lock_input]
test eax, eax
jnz @f
; get current PID
mov eax, [CURRENT_TASK]
shl eax, 5
mov eax, [eax+CURRENT_TASK+TASKDATA.pid]
; set current PID for lock input
mov [PID_lock_input], eax
@@:
popfd
ret
;-----------------------------------------------------------------------------
align 4
.7:
mov eax, [PID_lock_input]
test eax, eax
jz @f
; get current PID
mov ebx, [CURRENT_TASK]
shl ebx, 5
mov ebx, [ebx+CURRENT_TASK+TASKDATA.pid]
; compare current lock input with current PID
cmp ebx, eax
jne @f
 
xor eax, eax
mov [PID_lock_input], eax
@@:
ret
;-----------------------------------------------------------------------------
uglobal
PID_lock_input dd 0x0
endg
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 61 sys function. ;;
;; in eax=61,ebx in [1..3] ;;
;; out eax ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
iglobal
align 4
f61call:
dd sys_gs.1 ; resolution
dd sys_gs.2 ; bits per pixel
dd sys_gs.3 ; bytes per scanline
endg
 
 
align 4
 
sys_gs: ; direct screen access
dec ebx
cmp ebx, 2
ja .not_support
jmp dword [f61call+ebx*4]
.not_support:
or [esp+32], dword -1
ret
 
 
.1: ; resolution
mov eax, [Screen_Max_X]
shl eax, 16
mov ax, [Screen_Max_Y]
add eax, 0x00010001
mov [esp+32], eax
ret
.2: ; bits per pixel
movzx eax, byte [ScreenBPP]
mov [esp+32], eax
ret
.3: ; bytes per scanline
mov eax, [BytesPerScanLine]
mov [esp+32], eax
ret
 
align 4 ; system functions
 
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
and ecx, 0xFBFFFFFF ;negate 0x04000000 save to mouseunder area
; jmp [putpixel]
jmp __sys_putpixel
 
align 4
 
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
test ecx, 0x08000000 ; redirect the output to the user area
jnz dtext
xor edi, edi
jmp dtext
 
align 4
 
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
 
align 4
 
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 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]
 
add eax, [esi + APPDATA.wnd_clientbox.left]
add ebx, [esi + APPDATA.wnd_clientbox.top]
add ecx, eax
add edx, ebx
; jmp [drawbar]
jmp vesa20_drawbar
.drectr:
ret
 
align 4
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
 
cmp ebx, 4
jb .audio
jz .eject
cmp ebx, 5
jnz .ret
.load:
call .reserve
call LoadMedium
;call .free
jmp .free
; ret
.eject:
call .reserve
call clear_CD_cache
call allow_medium_removal
call EjectMedium
; call .free
jmp .free
; ret
.audio:
call sys_cd_audio
mov [esp+36-4], eax
.ret:
ret
 
.reserve:
call reserve_cd
mov eax, ecx
shr eax, 1
and eax, 1
inc eax
mov [ChannelNumber], ax
mov eax, ecx
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 .free;.err
ret
.free:
call free_cd_channel
and [cd_status], 0
ret
.err:
call .free
; pop eax
ret
;-----------------------------------------------------------------------------
align 4
syscall_getpixel_WinMap: ; GetPixel WinMap
cmp ebx, [Screen_Max_X]
jbe @f
cmp ecx, [Screen_Max_Y]
jbe @f
xor eax, eax
jmp .store
;--------------------------------------
align 4
@@:
mov eax, [d_width_calc_area + ecx*4]
add eax, [_WinMapAddress]
movzx eax, byte[eax+ebx] ; get value for current point
;--------------------------------------
align 4
.store:
mov [esp + 32], eax
ret
;-----------------------------------------------------------------------------
align 4
syscall_getpixel: ; GetPixel
mov ecx, [Screen_Max_X]
inc ecx
xor edx, edx
mov eax, ebx
div ecx
mov ebx, edx
xchg eax, ebx
and ecx, 0xFBFFFFFF ;negate 0x04000000 use mouseunder area
call dword [GETPIXEL]; eax - x, ebx - y
mov [esp + 32], ecx
ret
;-----------------------------------------------------------------------------
align 4
syscall_getarea:
;eax = 36
;ebx = pointer to bufer for img BBGGRRBBGGRR...
;ecx = [size x]*65536 + [size y]
;edx = [start x]*65536 + [start y]
pushad
mov edi, ebx
mov eax, edx
shr eax, 16
mov ebx, edx
and ebx, 0xffff
dec eax
dec ebx
; eax - x, ebx - y
mov edx, ecx
 
shr ecx, 16
and edx, 0xffff
mov esi, ecx
; ecx - size x, edx - size y
 
mov ebp, edx
dec ebp
lea ebp, [ebp*3]
 
imul ebp, esi
 
mov esi, ecx
dec esi
lea esi, [esi*3]
 
add ebp, esi
add ebp, edi
 
add ebx, edx
;--------------------------------------
align 4
.start_y:
push ecx edx
;--------------------------------------
align 4
.start_x:
push eax ebx ecx
add eax, ecx
 
and ecx, 0xFBFFFFFF ;negate 0x04000000 use mouseunder area
call dword [GETPIXEL]; eax - x, ebx - y
 
mov [ebp], cx
shr ecx, 16
mov [ebp+2], cl
 
pop ecx ebx eax
sub ebp, 3
dec ecx
jnz .start_x
pop edx ecx
dec ebx
dec edx
jnz .start_y
popad
ret
;-----------------------------------------------------------------------------
align 4
syscall_putarea_backgr:
;eax = 25
;ebx = pointer to bufer for img BBGGRRBBGGRR...
;ecx = [size x]*65536 + [size y]
;edx = [start x]*65536 + [start y]
pushad
mov edi, ebx
mov eax, edx
shr eax, 16
mov ebx, edx
and ebx, 0xffff
dec eax
dec ebx
; eax - x, ebx - y
mov edx, ecx
shr ecx, 16
and edx, 0xffff
mov esi, ecx
; ecx - size x, edx - size y
mov ebp, edx
dec ebp
shl ebp, 2
 
imul ebp, esi
 
mov esi, ecx
dec esi
shl esi, 2
 
add ebp, esi
add ebp, edi
 
add ebx, edx
;--------------------------------------
align 4
.start_y:
push ecx edx
;--------------------------------------
align 4
.start_x:
push eax ecx
add eax, ecx
 
mov ecx, [ebp]
rol ecx, 8
test cl, cl ; transparensy = 0
jz .no_put
 
xor cl, cl
ror ecx, 8
 
pushad
mov edx, [d_width_calc_area + ebx*4]
add edx, [_WinMapAddress]
movzx edx, byte [eax+edx]
cmp dl, byte 1
jne @f
 
call dword [PUTPIXEL]; eax - x, ebx - y
;--------------------------------------
align 4
@@:
popad
;--------------------------------------
align 4
.no_put:
pop ecx eax
 
sub ebp, 4
dec ecx
jnz .start_x
 
pop edx ecx
dec ebx
dec edx
jnz .start_y
 
popad
ret
;-----------------------------------------------------------------------------
align 4
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]
jmp __sys_draw_line
 
 
align 4
syscall_reserveportarea: ; ReservePortArea and FreePortArea
 
call r_f_port_area
mov [esp+32], eax
ret
 
align 4
syscall_threads: ; CreateThreads
; eax=1 create thread
;
; ebx=thread start
; ecx=thread stack value
;
; on return : eax = pid
 
call new_sys_threads
 
mov [esp+32], eax
ret
 
paleholder:
ret
;------------------------------------------------------------------------------
align 4
calculate_fast_getting_offset_for_WinMapAddress:
; calculate data area for fast getting offset to _WinMapAddress
xor eax, eax
mov ecx, [_display.height]
inc ecx
mov edi, d_width_calc_area
cld
@@:
stosd
add eax, [_display.width]
dec ecx
jnz @r
ret
;------------------------------------------------------------------------------
align 4
calculate_fast_getting_offset_for_LFB:
; calculate data area for fast getting offset to LFB
xor eax, eax
mov ecx, [_display.height]
inc ecx
mov edi, BPSLine_calc_area
cld
@@:
stosd
add eax, [BytesPerScanLine]
dec ecx
jnz @r
ret
;------------------------------------------------------------------------------
align 4
set_screen:
; in:
; eax - new Screen_Max_X
; ecx - new BytesPerScanLine
; edx - new Screen_Max_Y
cmp eax, [Screen_Max_X]
jne .set
 
cmp edx, [Screen_Max_Y]
jne .set
ret
.set:
pushfd
cli
 
mov [Screen_Max_X], eax
mov [Screen_Max_Y], edx
mov [BytesPerScanLine], ecx
 
mov [screen_workarea.right], eax
mov [screen_workarea.bottom], edx
 
push ebx
push esi
push edi
 
pushad
 
cmp [do_not_touch_winmap], 1
je @f
 
stdcall kernel_free, [_WinMapAddress]
 
mov eax, [_display.width]
mul [_display.height]
mov [_WinMapSize], eax
 
stdcall kernel_alloc, eax
mov [_WinMapAddress], eax
test eax, eax
jz .epic_fail
; store for f.18.24
mov eax, [_display.width]
mov [display_width_standard], eax
 
mov eax, [_display.height]
mov [display_height_standard], eax
@@:
call calculate_fast_getting_offset_for_WinMapAddress
; for Qemu or non standart video cards
; Unfortunately [BytesPerScanLine] does not always
; equal to [_display.width] * [ScreenBPP] / 8
call calculate_fast_getting_offset_for_LFB
popad
 
call repos_windows
xor eax, eax
xor ebx, ebx
mov ecx, [Screen_Max_X]
mov edx, [Screen_Max_Y]
call calculatescreen
pop edi
pop esi
pop ebx
 
popfd
ret
 
.epic_fail:
hlt ; Houston, we've had a problem
 
; --------------- APM ---------------------
uglobal
apm_entry dp 0
apm_vf dd 0
endg
 
align 4
sys_apm:
xor eax, eax
cmp word [apm_vf], ax ; Check APM BIOS enable
jne @f
inc eax
or dword [esp + 44], eax ; error
add eax, 7
mov dword [esp + 32], eax ; 32-bit protected-mode interface not supported
ret
 
@@:
; xchg eax, ecx
; xchg ebx, ecx
 
cmp dx, 3
ja @f
and [esp + 44], byte 0xfe ; emulate func 0..3 as func 0
mov eax, [apm_vf]
mov [esp + 32], eax
shr eax, 16
mov [esp + 28], eax
ret
 
@@:
 
mov esi, [master_tab+(OS_BASE shr 20)]
xchg [master_tab], esi
push esi
mov edi, cr3
mov cr3, edi ;flush TLB
 
call pword [apm_entry] ;call APM BIOS
 
xchg eax, [esp]
mov [master_tab], eax
mov eax, cr3
mov cr3, eax
pop eax
 
mov [esp + 4 ], edi
mov [esp + 8], esi
mov [esp + 20], ebx
mov [esp + 24], edx
mov [esp + 28], ecx
mov [esp + 32], eax
setc al
and [esp + 44], byte 0xfe
or [esp + 44], al
ret
; -----------------------------------------
 
align 4
 
undefined_syscall: ; Undefined system call
mov [esp + 32], dword -1
ret
 
align 4
system_shutdown: ; shut down the system
 
cmp byte [BOOT_VAR+0x9030], 1
jne @F
ret
@@:
call stop_all_services
push 3 ; stop playing cd
pop eax
call sys_cd_audio
 
yes_shutdown_param:
cli
 
if ~ defined extended_primary_loader
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
end if
 
mov esi, BOOT_VAR ; restore 0x0 - 0xffff
mov edi, OS_BASE
mov ecx, 0x10000/4
cld
rep movsd
 
call restorefatchain
 
call IRQ_mask_all
 
if 0
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, 0xFE
out 0x64, al
 
hlt
jmp $-1
 
else
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
@@:
; 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
.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
.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
.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
.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]
@@:
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
.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
@@:
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]
@@:
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
@@:
jmp $
 
 
no_acpi_power_off:
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, 0xFE
out 0x64, al
 
hlt
jmp $-1
 
scan_rsdp:
add eax, OS_BASE
.s:
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
.n:
add eax, 10h
loop .s
stc
.ok:
ret
end if
 
include "data32.inc"
 
__REV__ = __REV
 
uglobals_size = $ - endofcode
if ~ lang eq sp
diff16 "end of kernel code",0,$
end if
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/network/stack.inc
0,0 → 1,781
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; STACK.INC ;;
;; ;;
;; TCP/IP stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Some parts of code are based on the work of: ;;
;; Mike Hibbett (menuetos network stack) ;;
;; Eugen Brasoveanu (solar os network stack and drivers) ;;
;; mike.dld (kolibrios socket code) ;;
;; ;;
;; TCP part is based on 4.4BSD ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
uglobal
net_10ms dd ?
net_tmr_count dw ?
endg
 
MAX_NET_DEVICES = 16
ARP_BLOCK = 1 ; true or false
 
MIN_EPHEMERAL_PORT = 49152
MIN_EPHEMERAL_PORT_N = 0x00C0 ; same in Network byte order (FIXME)
MAX_EPHEMERAL_PORT = 61000
MAX_EPHEMERAL_PORT_N = 0x48EE ; same in Network byte order (FIXME)
 
; Ethernet protocol numbers
ETHER_ARP = 0x0608
ETHER_IPv4 = 0x0008
ETHER_IPv6 = 0xDD86
ETHER_PPP_DISCOVERY = 0x6388
ETHER_PPP_SESSION = 0x6488
 
; PPP protocol numbers
PPP_IPv4 = 0x2100
PPP_IPV6 = 0x5780
 
;Protocol family
AF_UNSPEC = 0
AF_LOCAL = 1
AF_INET4 = 2
AF_INET6 = 10
AF_PPP = 777
 
; Internet protocol numbers
IP_PROTO_IP = 0
IP_PROTO_ICMP = 1
IP_PROTO_TCP = 6
IP_PROTO_UDP = 17
 
; PPP protocol number
PPP_PROTO_ETHERNET = 666
 
; Socket types
SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3
 
; Socket options
SO_ACCEPTCON = 1 shl 0
SO_BROADCAST = 1 shl 1
SO_DEBUG = 1 shl 2
SO_DONTROUTE = 1 shl 3
SO_KEEPALIVE = 1 shl 4
SO_OOBINLINE = 1 shl 5
SO_REUSEADDR = 1 shl 6
SO_REUSEPORT = 1 shl 7
SO_USELOOPBACK = 1 shl 8
SO_BINDTODEVICE = 1 shl 9
 
SO_BLOCK = 1 shl 10 ; TO BE REMOVED
SO_NONBLOCK = 1 shl 31
 
; Socket flags for user calls
MSG_PEEK = 0x02
MSG_DONTWAIT = 0x40
 
; Socket level
SOL_SOCKET = 0
 
 
; Socket States
SS_NOFDREF = 0x0001 ; no file table ref any more
SS_ISCONNECTED = 0x0002 ; socket connected to a peer
SS_ISCONNECTING = 0x0004 ; in process of connecting to peer
SS_ISDISCONNECTING = 0x0008 ; in process of disconnecting
SS_CANTSENDMORE = 0x0010 ; can't send more data to peer
SS_CANTRCVMORE = 0x0020 ; can't receive more data from peer
SS_RCVATMARK = 0x0040 ; at mark on input
SS_ISABORTING = 0x0080 ; aborting fd references - close()
SS_RESTARTSYS = 0x0100 ; restart blocked system calls
SS_ISDISCONNECTED = 0x0800 ; socket disconnected from peer
 
SS_ASYNC = 0x0100 ; async i/o notify
SS_ISCONFIRMING = 0x0200 ; deciding to accept connection req
SS_MORETOCOME = 0x0400
 
SS_BLOCKED = 0x8000
 
 
SOCKET_MAXDATA = 4096*32 ; must be 4096*(power of 2) where 'power of 2' is at least 8
 
; Network driver types
NET_TYPE_LOOPBACK = 0
NET_TYPE_ETH = 1
NET_TYPE_SLIP = 2
 
MAX_backlog = 20 ; maximum backlog for stream sockets
 
; Error Codes
ENOBUFS = 55
ECONNREFUSED = 61
ECONNRESET = 52
ETIMEDOUT = 60
ECONNABORTED = 53
 
; Api protocol numbers
API_ETH = 0
API_IPv4 = 1
API_ICMP = 2
API_UDP = 3
API_TCP = 4
API_ARP = 5
API_PPPOE = 6
API_IPv6 = 7
 
HWACC_TCP_IPv4 = 1 shl 0
 
struct NET_DEVICE
 
type dd ? ; Type field
mtu dd ? ; Maximal Transmission Unit
name dd ? ; Ptr to 0 terminated string
 
unload dd ? ; Ptrs to driver functions
reset dd ? ;
transmit dd ? ;
 
bytes_tx dq ? ; Statistics, updated by the driver
bytes_rx dq ? ;
packets_tx dd ? ;
packets_rx dd ? ;
 
state dd ? ; link state (0 = no link)
hwacc dd ? ; bitmask stating enabled HW accelerations (offload engines)
 
ends
 
 
; Exactly as it says..
macro pseudo_random reg {
add reg, [esp]
rol reg, 5
xor reg, [timer_ticks]
add reg, [CPU_FREQ]
imul reg, 214013
xor reg, 0xdeadbeef
rol reg, 9
}
 
; Network to Hardware byte order (dword)
macro ntohd reg {
 
rol word reg, 8
rol dword reg, 16
rol word reg , 8
 
}
 
; Network to Hardware byte order (word)
macro ntohw reg {
 
rol word reg, 8
 
}
 
 
include "queue.inc"
 
include "loopback.inc"
include "ethernet.inc"
 
include "PPPoE.inc"
 
include "ARP.inc"
include "IPv4.inc"
include "IPv6.inc"
 
include "icmp.inc"
include "udp.inc"
include "tcp.inc"
 
include "socket.inc"
 
 
 
align 4
uglobal
 
NET_RUNNING dd ?
NET_DEFAULT dd ?
NET_DRV_LIST rd MAX_NET_DEVICES
 
endg
 
 
;-----------------------------------------------------------------
;
; stack_init
;
; This function calls all network init procedures
;
; IN: /
; OUT: /
;
;-----------------------------------------------------------------
align 4
stack_init:
 
; Init the network drivers list
xor eax, eax
mov edi, NET_RUNNING
mov ecx, (MAX_NET_DEVICES + 2)
rep stosd
 
PPPoE_init
 
IPv4_init
; IPv6_init
ICMP_init
 
ARP_init
UDP_init
TCP_init
 
SOCKET_init
 
mov [net_tmr_count], 0
 
ret
 
 
;-----------------------------------------------------------------
;
; stack_handler
;
; This function is called in kernel loop
;
; IN: /
; OUT: /
;
;-----------------------------------------------------------------
align 4
stack_handler:
 
cmp [NET_RUNNING], 0
je .exit
 
 
; Test for 10ms tick
mov eax, [timer_ticks]
cmp eax, [net_10ms]
je .exit
mov [net_10ms], eax
 
test [net_10ms], 0x0f ; 160ms
jnz .exit
 
TCP_timer_160ms
 
test [net_10ms], 0x3f ; 640ms
jnz .exit
 
TCP_timer_640ms
ARP_decrease_entry_ttls
IPv4_decrease_fragment_ttls
 
.exit:
ret
 
 
 
align 4
NET_link_changed:
 
DEBUGF 1,"NET_link_changed device=0x%x status=0x%x\n", ebx, [ebx + NET_DEVICE.state]
 
align 4
NET_send_event:
 
DEBUGF 1,"NET_send_event\n"
 
; Send event to all applications
push edi ecx
mov edi, SLOT_BASE
mov ecx, [TASK_COUNT]
.loop:
add edi, 256
or [edi + APPDATA.event_mask], EVENT_NETWORK2
loop .loop
pop ecx edi
 
call change_task
 
ret
 
 
 
;-----------------------------------------------------------------
;
; NET_add_device:
;
; This function is called by the network drivers,
; to register each running NIC to the kernel
;
; IN: Pointer to device structure in ebx
; OUT: Device num in eax, -1 on error
;
;-----------------------------------------------------------------
align 4
NET_add_device:
 
DEBUGF 1,"NET_Add_Device: %x\n", ebx ;;; TODO: use mutex to lock net device list
 
cmp [NET_RUNNING], MAX_NET_DEVICES
jae .error
 
;----------------------------------
; Check if device is already listed
mov eax, ebx
mov ecx, MAX_NET_DEVICES ; We need to check whole list because a device may be removed without re-organizing list
mov edi, NET_DRV_LIST
 
repne scasd ; See if device is already in the list
jz .error
 
;----------------------------
; Find empty slot in the list
xor eax, eax
mov ecx, MAX_NET_DEVICES
mov edi, NET_DRV_LIST
 
repne scasd
jnz .error
 
sub edi, 4
 
;-----------------------------
; Add device to the found slot
mov [edi], ebx ; add device to list
 
mov eax, edi ; Calculate device number in eax
sub eax, NET_DRV_LIST
shr eax, 2
 
inc [NET_RUNNING] ; Indicate that one more network device is up and running
 
cmp eax, 1 ; If it's the first network device, try to set it as default
jne @f
push eax
call NET_set_default
pop eax
@@:
 
call NET_send_event
 
DEBUGF 1,"Device number: %u\n", eax
ret
 
.error:
or eax, -1
DEBUGF 2,"Adding network device failed\n"
ret
 
 
 
;-----------------------------------------------------------------
;
; NET_set_default
;
; API to set the default interface
;
; IN: Device num in eax
; OUT: Device num in eax, -1 on error
;
;-----------------------------------------------------------------
align 4
NET_set_default:
 
DEBUGF 1,"NET_set_default: device=%x\n", eax
 
cmp eax, MAX_NET_DEVICES
jae .error
 
cmp [NET_DRV_LIST+eax*4], 0
je .error
 
mov [NET_DEFAULT], eax
 
DEBUGF 1,"NET_set_default: succes\n"
ret
 
.error:
or eax, -1
DEBUGF 1,"NET_set_default: failed\n"
ret
 
 
;-----------------------------------------------------------------
;
; NET_Remove_Device:
;
; This function is called by etwork drivers,
; to unregister network devices from the kernel
;
; IN: Pointer to device structure in ebx
; OUT: eax: -1 on error
;
;-----------------------------------------------------------------
align 4
NET_remove_device:
 
cmp [NET_RUNNING], 0
je .error
 
cmp [NET_DRV_LIST], ebx
jne @f
mov [NET_DRV_LIST], 0
cmp [NET_RUNNING], 1
je @f
; there are still active devices, find one and make it default
xor eax, eax
mov ecx, MAX_NET_DEVICES
mov edi, NET_DRV_LIST
repe scasd
je @f
shr edi, 2
dec edi
mov [NET_DEFAULT], edi
@@:
 
;----------------------------
; Find the driver in the list
 
mov eax, ebx
mov ecx, MAX_NET_DEVICES
mov edi, NET_DRV_LIST+4
 
repne scasd
jnz .error
 
;------------------------
; Remove it from the list
 
xor eax, eax
mov dword [edi-4], eax
 
call NET_send_event
 
dec [NET_RUNNING]
ret
 
.error:
or eax, -1
ret
 
 
 
;-----------------------------------------------------------------
;
; NET_ptr_to_num
;
; IN: ebx = ptr to device struct
; OUT: edi = -1 on error, device number otherwise
;
;-----------------------------------------------------------------
align 4
NET_ptr_to_num:
push ecx
 
mov ecx, MAX_NET_DEVICES
mov edi, NET_DRV_LIST
 
.loop:
cmp ebx, [edi]
jz .found
add edi, 4
dec ecx
jnz .loop
 
; repnz scasd could work too if eax is used instead of ebx!
 
or edi, -1
 
pop ecx
ret
 
.found:
sub edi, NET_DRV_LIST
shr edi, 2
 
pop ecx
ret
 
;-----------------------------------------------------------------
;
; checksum_1
;
; This is the first of two functions needed to calculate a checksum.
;
; IN: edx = start offset for semi-checksum
; esi = pointer to data
; ecx = data size
; OUT: edx = semi-checksum
;
;
; Code was optimized by diamond
;
;-----------------------------------------------------------------
align 4
checksum_1:
 
shr ecx, 1
pushf
jz .no_2
 
shr ecx, 1
pushf
jz .no_4
 
shr ecx, 1
pushf
jz .no_8
 
.loop:
add dl, [esi+1]
adc dh, [esi+0]
 
adc dl, [esi+3]
adc dh, [esi+2]
 
adc dl, [esi+5]
adc dh, [esi+4]
 
adc dl, [esi+7]
adc dh, [esi+6]
 
adc edx, 0
add esi, 8
 
dec ecx
jnz .loop
 
adc edx, 0
 
.no_8:
popf
jnc .no_4
 
add dl, [esi+1]
adc dh, [esi+0]
 
adc dl, [esi+3]
adc dh, [esi+2]
 
adc edx, 0
add esi, 4
 
.no_4:
popf
jnc .no_2
 
add dl, [esi+1]
adc dh, [esi+0]
 
adc edx, 0
inc esi
inc esi
 
.no_2:
popf
jnc .end
 
add dh, [esi+0]
adc edx, 0
.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 ecx, edx
shr ecx, 16
add dx, cx
test dx, dx ; it seems that ZF is not set when CF is set :(
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 (75)
;
;----------------------------------------------------------------
align 4
sys_network: ; FIXME: make default device easily accessible
 
cmp ebx, -1
jne @f
 
mov eax, [NET_RUNNING]
jmp .return
 
@@:
cmp bh, MAX_NET_DEVICES ; Check if device number exists
jae .doesnt_exist
 
mov esi, ebx
and esi, 0x0000ff00
shr esi, 6
 
cmp dword [esi + NET_DRV_LIST], 0 ; check if driver is running
je .doesnt_exist
 
mov eax, [esi + NET_DRV_LIST]
 
and ebx, 0x000000ff
cmp ebx, .number
ja .doesnt_exist
jmp dword [.table + 4*ebx]
 
.table:
dd .get_type ; 0
dd .get_dev_name ; 1
dd .reset ; 2
dd .stop ; 3
dd .get_ptr ; 4
dd .get_drv_name ; 5
dd .set_default ; 6
.number = ($ - .table) / 4 - 1
 
.get_type: ; 0 = Get device type (ethernet/token ring/...)
 
mov eax, [eax + NET_DEVICE.type]
jmp .return
 
 
.get_dev_name: ; 1 = Get device name
 
mov esi, [eax + NET_DEVICE.name]
mov edi, ecx
 
mov ecx, 64/4 ; max length
rep movsd
 
xor eax, eax
jmp .return
 
.reset: ; 2 = Reset the device
 
call [eax + NET_DEVICE.reset]
jmp .return
 
.stop: ; 3 = Stop driver for this device
 
call [eax + NET_DEVICE.unload]
jmp .return
 
 
.get_ptr: ; 4 = Get driver pointer
 
jmp .return
 
 
.get_drv_name: ; 5 = Get driver name
 
xor eax, eax
jmp .return
 
 
.set_default: ; 6 = Set default device
 
call NET_set_default
jmp .return
 
.doesnt_exist:
mov eax, -1
 
.return:
mov [esp+32], eax
ret
 
 
;----------------------------------------------------------------
;
; System function to work with protocols (76)
;
;----------------------------------------------------------------
align 4
sys_protocols:
cmp bh, MAX_NET_DEVICES ; Check if device number exists
jae .doesnt_exist
 
mov esi, ebx
and esi, 0x0000ff00
shr esi, 6 ; now we have the device num * 4 in esi
cmp [esi + NET_DRV_LIST], 0 ; check if driver is running
je .doesnt_exist
 
push .return ; return address (we will be using jumps instead of calls)
 
mov eax, ebx ; set ax to protocol number
shr eax, 16 ;
 
cmp ax, API_ETH
je ETH_api
 
cmp ax, API_IPv4
je IPv4_api
 
cmp ax, API_ICMP
je ICMP_api
 
cmp ax, API_UDP
je UDP_api
 
cmp ax, API_TCP
je TCP_api
 
cmp ax, API_ARP
je ARP_api
 
cmp ax, API_PPPOE
je PPPoE_api
 
cmp ax, API_IPv6
je IPv6_api
 
add esp, 4 ; if we reached here, no function was called, so we need to balance stack
 
.doesnt_exist:
mov eax, -1
 
.return:
mov [esp+28+4], eax ; return eax value to the program
ret
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/network/IPv4.inc
0,0 → 1,1019
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; IPv4.INC ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
;; ;;
;; Based on the work of [Johnny_B] and [smb] ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
MAX_FRAGMENTS = 64
 
struct IPv4_header
 
VersionAndIHL db ? ; Version[0-3 bits] and IHL(header length)[4-7 bits]
TypeOfService db ? ; precedence [7-5] minimize delay [4], maximize throughput [3], maximize riliability [2] minimize momentary cost [1] and zero [0]
TotalLength dw ?
Identification dw ?
FlagsAndFragmentOffset dw ? ; Flags[0-2] and FragmentOffset[3-15]
TimeToLive db ? ;
Protocol db ?
HeaderChecksum dw ?
SourceAddress dd ?
DestinationAddress dd ?
 
ends
 
struct FRAGMENT_slot
 
ttl dw ? ; Time to live for this entry, 0 for empty slot's
id dw ? ; Identification field from IP header
SrcIP dd ? ; .. from IP header
DstIP dd ? ; .. from IP header
ptr dd ? ; Pointer to first packet
 
ends
 
struct FRAGMENT_entry ; This structure will replace the ethernet header in fragmented ip packets
 
PrevPtr dd ? ; Pointer to previous fragment entry (-1 for first packet)
NextPtr dd ? ; Pointer to next fragment entry (-1 for last packet)
Owner dd ? ; Pointer to structure of driver
rb 2 ; to match ethernet header size ;;; FIXME
; Ip header begins here (we will need the IP header to re-construct the complete packet)
ends
 
 
align 4
uglobal
 
IP_LIST rd MAX_NET_DEVICES
SUBNET_LIST rd MAX_NET_DEVICES
DNS_LIST rd MAX_NET_DEVICES
GATEWAY_LIST rd MAX_NET_DEVICES
BROADCAST_LIST rd MAX_NET_DEVICES
 
IP_packets_tx rd MAX_NET_DEVICES
IP_packets_rx rd MAX_NET_DEVICES
IP_packets_dumped rd MAX_NET_DEVICES
 
FRAGMENT_LIST rb MAX_FRAGMENTS * sizeof.FRAGMENT_slot
endg
 
 
;-----------------------------------------------------------------
;
; IPv4_init
;
; This function resets all IP variables
;
;-----------------------------------------------------------------
macro IPv4_init {
 
xor eax, eax
mov edi, IP_LIST
mov ecx, 7*MAX_NET_DEVICES + (sizeof.FRAGMENT_slot*MAX_FRAGMENTS)/4
rep stosd
 
}
 
 
;-----------------------------------------------------------------
;
; Decrease TimeToLive of all fragment slots
;
;-----------------------------------------------------------------
macro IPv4_decrease_fragment_ttls {
 
local .loop, .next
 
mov esi, FRAGMENT_LIST
mov ecx, MAX_FRAGMENTS
.loop:
cmp [esi + FRAGMENT_slot.ttl], 0
je .next
dec [esi + FRAGMENT_slot.ttl]
jz .died
.next:
add esi, sizeof.FRAGMENT_slot
dec ecx
jnz .loop
jmp .done
 
.died:
DEBUGF 2,"IPv4 Fragment slot timed-out!\n"
;;; TODO: clear all entry's of timed-out slot
jmp .next
 
.done:
}
 
 
 
macro IPv4_checksum ptr {
 
; This is the fast procedure to create or check an IP header without options
; To create a new checksum, the checksum field must be set to 0 before computation
; To check an existing checksum, leave the checksum as is, and it will be 0 after this procedure, if it was correct
 
push ebx
xor ebx, ebx
add bl, [ptr+1]
adc bh, [ptr+0]
 
adc bl, [ptr+3]
adc bh, [ptr+2]
 
adc bl, [ptr+5]
adc bh, [ptr+4]
 
adc bl, [ptr+7]
adc bh, [ptr+6]
 
adc bl, [ptr+9]
adc bh, [ptr+8]
 
; we skip 11th and 12th byte, they are the checksum bytes and should be 0 for re-calculation
 
adc bl, [ptr+13]
adc bh, [ptr+12]
 
adc bl, [ptr+15]
adc bh, [ptr+14]
 
adc bl, [ptr+17]
adc bh, [ptr+16]
 
adc bl, [ptr+19]
adc bh, [ptr+18]
 
adc ebx, 0
 
push ecx
mov ecx, ebx
shr ecx, 16
and ebx, 0xffff
add ebx, ecx
 
mov ecx, ebx
shr ecx, 16
add ebx, ecx
 
not bx
jnz .not_zero
dec bx
.not_zero:
xchg bl, bh
pop ecx
 
neg word [ptr+10] ; zero will stay zero so we just get the checksum
add word [ptr+10], bx ; , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
pop ebx
 
}
 
 
 
;-----------------------------------------------------------------
;
; IPv4_input:
;
; Will check if IPv4 Packet isnt damaged
; and call appropriate handler. (TCP/UDP/ICMP/..)
;
; It will also re-construct fragmented packets
;
; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
; pointer to device struct in ebx
; pointer to IPv4 header in edx
; size of IPv4 packet in ecx
; OUT: /
;
;-----------------------------------------------------------------
align 4
IPv4_input: ; TODO: add IPv4 raw sockets support
 
DEBUGF 2,"IPv4_input, packet from: %u.%u.%u.%u ",\
[edx + IPv4_header.SourceAddress + 0]:1,[edx + IPv4_header.SourceAddress + 1]:1,\
[edx + IPv4_header.SourceAddress + 2]:1,[edx + IPv4_header.SourceAddress + 3]:1
DEBUGF 2,"to: %u.%u.%u.%u\n",\
[edx + IPv4_header.DestinationAddress + 0]:1,[edx + IPv4_header.DestinationAddress + 1]:1,\
[edx + IPv4_header.DestinationAddress + 2]:1,[edx + IPv4_header.DestinationAddress + 3]:1
 
;-------------------------------
; re-calculate the checksum
 
IPv4_checksum edx
jnz .dump ; if checksum isn't valid then dump packet
 
DEBUGF 1,"IPv4_input: Checksum ok\n"
 
;-----------------------------------
; Check if destination IP is correct
 
call NET_ptr_to_num
shl edi, 2
 
; check if it matches local ip (Using RFC1122 strong end system model)
 
mov eax, [edx + IPv4_header.DestinationAddress]
cmp eax, [IP_LIST + edi]
je .ip_ok
 
; check for broadcast (IP or (not SUBNET))
 
cmp eax, [BROADCAST_LIST + edi]
je .ip_ok
 
; or a special broadcast (255.255.255.255)
 
cmp eax, 0xffffffff
je .ip_ok
 
; maybe it's a multicast (224.0.0.0/4)
 
and eax, 0x0fffffff
cmp eax, 224
je .ip_ok
 
; or a loopback address (127.0.0.0/8)
 
and eax, 0x00ffffff
cmp eax, 127
je .ip_ok
 
; or it's just not meant for us.. :(
 
DEBUGF 2,"IPv4_input: Destination address does not match!\n"
jmp .dump
 
;------------------------
; Now we can update stats
 
.ip_ok:
inc [IP_packets_rx + edi]
 
;----------------------------------
; Check if the packet is fragmented
 
test [edx + IPv4_header.FlagsAndFragmentOffset], 1 shl 5 ; Is 'more fragments' flag set ?
jnz .has_fragments ; If so, we definately have a fragmented packet
 
test [edx + IPv4_header.FlagsAndFragmentOffset], 0xff1f ; If flag is not set, but there is a fragment offset, the packet is last in series of fragmented packets
jnz .is_last_fragment
 
;-------------------------------------------------------------------
; No, it's just a regular IP packet, pass it to the higher protocols
 
.handle_it: ; We reach here if packet hasnt been fragmented, or when it already has been re-constructed
 
movzx esi, [edx + IPv4_header.VersionAndIHL] ; Calculate Header length by using IHL field
and esi, 0x0000000f ;
shl esi, 2 ;
 
movzx ecx, [edx + IPv4_header.TotalLength] ; Calculate length of encapsulated Packet
xchg cl, ch ;
sub ecx, esi ;
 
lea edi, [edx + IPv4_header.SourceAddress] ; make edi ptr to source and dest IPv4 address
mov al, [edx + IPv4_header.Protocol]
add esi, edx ; make esi ptr to data
 
cmp al, IP_PROTO_TCP
je TCP_input
 
cmp al, IP_PROTO_UDP
je UDP_input
 
cmp al, IP_PROTO_ICMP
je ICMP_input
 
DEBUGF 2,"IPv4_input: unknown protocol %u\n", al
 
.dump:
DEBUGF 1,"IPv4_input: dumping\n"
inc [IP_packets_dumped] ; FIXME: use correct interface
call kernel_free
add esp, 4 ; pop (balance stack)
ret
 
 
;---------------------------
; Fragmented packet handler
 
 
.has_fragments:
movzx eax, [edx + IPv4_header.FlagsAndFragmentOffset]
xchg al, ah
shl ax, 3
 
DEBUGF 1,"IPv4_input: fragmented packet offset=%u id=%x\n", ax, [edx + IPv4_header.Identification]:4
 
test ax, ax ; Is this the first packet of the fragment?
jz .is_first_fragment
 
 
;-------------------------------------------------------
; We have a fragmented IP packet, but it's not the first
 
DEBUGF 1,"IPv4_input: Middle fragment packet received!\n"
 
call IPv4_find_fragment_slot
cmp esi, -1
je .dump
 
mov [esi + FRAGMENT_slot.ttl], 15 ; Reset the ttl
mov esi, [esi + FRAGMENT_slot.ptr]
or edi, -1
.find_last_entry: ; The following routine will try to find the last entry
cmp edi, [esi + FRAGMENT_entry.PrevPtr]
jne .destroy_slot ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
mov edi, esi
mov esi, [esi + FRAGMENT_entry.NextPtr]
cmp esi, -1
jne .find_last_entry
; We found the last entry (pointer is now in edi)
; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure
 
pop eax ; pointer to packet
mov [edi + FRAGMENT_entry.NextPtr], eax ; update pointer of previous entry to the new entry
mov [eax + FRAGMENT_entry.NextPtr], -1
mov [eax + FRAGMENT_entry.PrevPtr], edi
mov [eax + FRAGMENT_entry.Owner], ebx
 
add esp, 4
ret
 
 
;------------------------------------
; We have received the first fragment
 
.is_first_fragment:
DEBUGF 1,"IPv4_input: First fragment packet received!\n"
; try to locate a free slot..
mov ecx, MAX_FRAGMENTS
mov esi, FRAGMENT_LIST
.find_free_slot:
cmp word [esi + FRAGMENT_slot.ttl], 0
je .found_free_slot
add esi, sizeof.FRAGMENT_slot
loop .find_free_slot
jmp .dump ; If no free slot was found, dump the packet
 
.found_free_slot: ; We found a free slot, let's fill in the FRAGMENT_slot structure
mov [esi + FRAGMENT_slot.ttl], 15 ; RFC recommends 15 secs as ttl
mov ax, [edx + IPv4_header.Identification]
mov [esi + FRAGMENT_slot.id], ax
mov eax, [edx + IPv4_header.SourceAddress]
mov [esi + FRAGMENT_slot.SrcIP], eax
mov eax, [edx + IPv4_header.DestinationAddress]
mov [esi + FRAGMENT_slot.DstIP], eax
pop eax
mov [esi + FRAGMENT_slot.ptr], eax
; Now, replace ethernet header in original buffer with a FRAGMENT_entry structure
mov [eax + FRAGMENT_entry.NextPtr], -1
mov [eax + FRAGMENT_entry.PrevPtr], -1
mov [eax + FRAGMENT_entry.Owner], ebx
 
add esp, 4 ; balance stack and exit
ret
 
 
;-----------------------------------
; We have received the last fragment
 
.is_last_fragment:
DEBUGF 1,"IPv4_input: Last fragment packet received!\n"
 
call IPv4_find_fragment_slot
cmp esi, -1
je .dump
 
mov esi, [esi + FRAGMENT_slot.ptr] ; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer
push esi
xor eax, eax
or edi, -1
 
.count_bytes:
cmp [esi + FRAGMENT_entry.PrevPtr], edi
jne .destroy_slot_pop ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
mov cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.TotalLength] ; Add total length
xchg cl, ch
DEBUGF 1,"IPv4_input: Packet size=%u\n", cx
add ax, cx
movzx cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL] ; Sub Header length
and cx, 0x000F
shl cx, 2
DEBUGF 1,"IPv4_input: Header size=%u\n", cx
sub ax, cx
mov edi, esi
mov esi, [esi + FRAGMENT_entry.NextPtr]
cmp esi, -1
jne .count_bytes
 
mov esi, [esp+4]
mov [edi + FRAGMENT_entry.NextPtr], esi ; Add this packet to the chain, this simplifies the following code
mov [esi + FRAGMENT_entry.NextPtr], -1
mov [esi + FRAGMENT_entry.PrevPtr], edi
mov [esi + FRAGMENT_entry.Owner], ebx
 
mov cx, [edx + IPv4_header.TotalLength] ; Note: This time we dont substract Header length
xchg cl, ch
DEBUGF 1,"IPv4_input: Packet size=%u\n", cx
add ax, cx
DEBUGF 1,"IPv4_input: Total Received data size=%u\n", eax
 
push eax
mov ax, [edx + IPv4_header.FlagsAndFragmentOffset]
xchg al, ah
shl ax, 3
add cx, ax
pop eax
DEBUGF 1,"IPv4_input: Total Fragment size=%u\n", ecx
 
cmp ax, cx
jne .destroy_slot_pop
 
push eax
push eax
call kernel_alloc
test eax, eax
je .destroy_slot_pop ; If we dont have enough space to allocate the buffer, discard all packets in slot
mov edx, [esp+4] ; Get pointer to first fragment entry back in edx
 
.rebuild_packet_loop:
movzx ecx, [edx + sizeof.FRAGMENT_entry + IPv4_header.FlagsAndFragmentOffset] ; Calculate the fragment offset
xchg cl, ch ; intel byte order
shl cx, 3 ; multiply by 8 and clear first 3 bits
DEBUGF 1,"IPv4_input: Fragment offset=%u\n", cx
 
lea edi, [eax + ecx] ; Notice that edi will be equal to eax for first fragment
movzx ebx, [edx + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL] ; Find header size (in ebx) of fragment
and bx, 0x000F ;
shl bx, 2 ;
 
lea esi, [edx + sizeof.FRAGMENT_entry] ; Set esi to the correct begin of fragment
movzx ecx, [edx + sizeof.FRAGMENT_entry + IPv4_header.TotalLength] ; Calculate total length of fragment
xchg cl, ch ; intel byte order
 
cmp edi, eax ; Is this packet the first fragment ?
je .first_fragment
sub cx, bx ; If not, dont copy the header
add esi, ebx ;
.first_fragment:
 
push cx ; First copy dword-wise, then byte-wise
shr cx, 2 ;
rep movsd ;
pop cx ;
and cx, 3 ;
rep movsb ;
 
push eax
push edx ; Push pointer to fragment onto stack
mov ebx, [edx + FRAGMENT_entry.Owner] ; we need to remeber the owner, in case this is the last packet
mov edx, [edx + FRAGMENT_entry.NextPtr] ; Set edx to the next pointer
call kernel_free ; free the previous fragment buffer (this uses the value from stack)
pop eax
cmp edx, -1 ; Check if it is last fragment in chain
jne .rebuild_packet_loop
 
pop ecx
xchg cl, ch
mov edx, eax
mov [edx + IPv4_header.TotalLength], cx
add esp, 8
xchg cl, ch
push ecx
 
push eax
jmp .handle_it ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr
 
.destroy_slot_pop:
add esp, 4
.destroy_slot:
DEBUGF 1,"IPv4_input: Destroy fragment slot!\n"
; TODO!
jmp .dump
 
 
 
 
 
;-----------------------------------------------------------------
;
; find fragment slot
;
; IN: pointer to fragmented packet in edx
; OUT: pointer to slot in esi, -1 on error
;
;-----------------------------------------------------------------
align 4
IPv4_find_fragment_slot:
 
;;; TODO: the RFC says we should check protocol number too
 
push eax ebx ecx edx
mov ax, [edx + IPv4_header.Identification]
mov ecx, MAX_FRAGMENTS
mov esi, FRAGMENT_LIST
mov ebx, [edx + IPv4_header.SourceAddress]
mov edx, [edx + IPv4_header.DestinationAddress]
.find_slot:
cmp [esi + FRAGMENT_slot.id], ax
jne .try_next
cmp [esi + FRAGMENT_slot.SrcIP], ebx
jne .try_next
cmp [esi + FRAGMENT_slot.DstIP], edx
je .found_slot
.try_next:
add esi, sizeof.FRAGMENT_slot
loop .find_slot
 
or esi, -1
.found_slot:
pop edx ecx ebx eax
ret
 
 
;------------------------------------------------------------------
;
; IPv4_output
;
; IN: eax = dest ip
; ebx = output device ptr/0 for automatic choice
; ecx = data length
; edx = source ip
; di = TTL shl 8 + protocol
;
; OUT: eax = pointer to buffer start
; ebx = pointer to device struct (needed for sending procedure)
; ecx = unchanged (packet size of embedded data)
; edx = size of complete buffer
; edi = pointer to start of data (0 on error)
;
;------------------------------------------------------------------
align 4
IPv4_output:
 
DEBUGF 1,"IPv4_output: size=%u\n", ecx
 
cmp ecx, 65500 ; Max IPv4 packet size
ja .too_large
 
push ecx eax edx di
 
cmp eax, 1 shl 24 + 127
je .loopback
 
call IPv4_route ; outputs device number in edi, dest ip in eax
call ARP_IP_to_MAC
test eax, 0xffff0000 ; error bits
jnz .arp_error
push ebx ; push the mac onto the stack
push ax
 
inc [IP_packets_tx + edi] ; update stats
 
mov ebx, [NET_DRV_LIST + edi]
lea eax, [ebx + ETH_DEVICE.mac]
mov edx, esp
mov ecx, [esp + 10 + 6]
add ecx, sizeof.IPv4_header
mov di, ETHER_IPv4
call ETH_output
jz .eth_error
add esp, 6 ; pop the mac out of the stack
 
.continue:
xchg cl, ch ; internet byte order
mov [edi + IPv4_header.VersionAndIHL], 0x45 ; IPv4, normal length (no Optional header)
mov [edi + IPv4_header.TypeOfService], 0 ; nothing special, just plain ip packet
mov [edi + IPv4_header.TotalLength], cx
mov [edi + IPv4_header.Identification], 0 ; fragment id: FIXME
mov [edi + IPv4_header.FlagsAndFragmentOffset], 0
pop word [edi + IPv4_header.TimeToLive] ; ttl shl 8 + protocol
; [edi + IPv4_header.Protocol]
mov [edi + IPv4_header.HeaderChecksum], 0
popd [edi + IPv4_header.SourceAddress]
popd [edi + IPv4_header.DestinationAddress]
 
pop ecx
 
IPv4_checksum edi
add edi, sizeof.IPv4_header
DEBUGF 2,"IPv4_output: success!\n"
ret
 
.eth_error:
DEBUGF 2,"IPv4_output: ethernet error\n"
add esp, 3*4+2+6
xor edi, edi
ret
 
.arp_error:
DEBUGF 2,"IPv4_output: ARP error=%x\n", eax
add esp, 3*4+2
xor edi, edi
ret
 
.too_large:
DEBUGF 2,"IPv4_output: Packet too large!\n"
xor edi, edi
ret
 
.loopback:
mov dword [esp + 2], eax
add ecx, sizeof.IPv4_header
mov di, ETHER_IPv4
call LOOP_output
jmp .continue
 
 
 
 
;------------------------------------------------------------------
;
; IPv4_output_raw
;
; IN: eax = socket ptr
; ecx = data length
; esi = data ptr
;
; OUT: /
;
;------------------------------------------------------------------
align 4
IPv4_output_raw:
 
DEBUGF 1,"IPv4_output_raw: size=%u ptr=%x socket=%x\n", ecx, esi, eax
 
cmp ecx, 1480 ;;;;; FIXME
ja .too_large
 
sub esp, 8
push esi eax
 
call IPv4_route
call ARP_IP_to_MAC
 
test eax, 0xffff0000 ; error bits
jnz .arp_error
 
push ebx ; push the mac
push ax
 
inc [IP_packets_tx + edi]
mov ebx, [NET_DRV_LIST + edi]
lea eax, [ebx + ETH_DEVICE.mac]
mov edx, esp
mov ecx, [esp + 6 + 4]
add ecx, sizeof.IPv4_header
mov di, ETHER_IPv4
call ETH_output
jz .error
 
add esp, 6 ; pop the mac
 
mov dword[esp+4+4], edx
mov dword[esp+4+4+4], eax
 
pop eax esi
;; todo: check socket options if we should add header, or just compute checksum
 
push edi ecx
rep movsb
pop ecx edi
 
; [edi + IPv4_header.VersionAndIHL] ; IPv4, normal length (no Optional header)
; [edi + IPv4_header.TypeOfService] ; nothing special, just plain ip packet
; [edi + IPv4_header.TotalLength]
; [edi + IPv4_header.TotalLength] ; internet byte order
; [edi + IPv4_header.FlagsAndFragmentOffset]
 
mov [edi + IPv4_header.HeaderChecksum], 0
 
; [edi + IPv4_header.TimeToLive] ; ttl shl 8 + protocol
; [edi + IPv4_header.Protocol]
; [edi + IPv4_header.Identification] ; fragment id
; [edi + IPv4_header.SourceAddress]
; [edi + IPv4_header.DestinationAddress]
 
IPv4_checksum edi ;;;; todo: checksum for IP packet with options!
add edi, sizeof.IPv4_header
DEBUGF 2,"IPv4_output_raw: device=%x\n", ebx
call [ebx + NET_DEVICE.transmit]
ret
 
.error:
add esp, 6
.arp_error:
add esp, 8+4+4
.too_large:
DEBUGF 2,"IPv4_output_raw: Failed\n"
sub edi, edi
ret
 
 
;--------------------------------------------------------
;
;
; IN: dword [esp] = pointer to buffer containing ipv4 packet to be fragmented
; dword [esp+4] = buffer size
; esi = pointer to ip header in that buffer
; ecx = max size of fragments
;
; OUT: /
;
;--------------------------------------------------------
 
align 4
IPv4_fragment:
 
DEBUGF 1,"IPv4_fragment\n"
 
and ecx, not 111b ; align 4
 
cmp ecx, sizeof.IPv4_header + 8 ; must be able to put at least 8 bytes
jb .err2
 
push esi ecx
mov eax, [esi + IPv4_header.DestinationAddress]
call ARP_IP_to_MAC
pop ecx esi
cmp eax, -1
jz .err2
 
push ebx
push ax
 
mov ebx, [NET_DRV_LIST]
lea eax, [ebx + ETH_DEVICE.mac]
push eax
 
 
push esi ; ptr to ip header
sub ecx, sizeof.IPv4_header ; substract header size
push ecx ; max data size
push dword 0 ; offset
 
.new_fragment:
DEBUGF 1,"Ipv4_fragment: new fragment"
 
 
mov eax, [esp + 3*4]
lea ebx, [esp + 4*4]
mov di , ETHER_IPv4
call ETH_output
 
cmp edi, -1
jz .err
 
; copy header
mov esi, [esp + 2*4]
mov ecx, 5 ; 5 dwords: TODO: use IHL field of the header!
rep movsd
 
; copy data
mov esi, [esp + 2*4]
add esi, sizeof.IPv4_header
add esi, [esp] ; offset
 
mov ecx, [esp + 1*4]
DEBUGF 1,"IPv4_fragment: copying %u bytes\n", ecx
rep movsb
 
; now, correct header
mov ecx, [esp + 1*4]
add ecx, sizeof.IPv4_header
xchg cl, ch
mov [edi + IPv4_header.TotalLength], cx
 
mov ecx, [esp] ; offset
xchg cl, ch
 
; cmp dword[esp + 4*4], 0 ; last fragment?;<<<<<<
; je .last_fragment
or cx, 1 shl 2 ; more fragments
; .last_fragment:
mov [edi + IPv4_header.FlagsAndFragmentOffset], cx
 
mov [edi + IPv4_header.HeaderChecksum], 0
 
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<< send the packet
mov ecx, [esp + 1*4]
 
push edx eax
IPv4_checksum edi
 
call [ebx + NET_DEVICE.transmit]
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 
mov ecx, [esp+4]
add [esp], ecx
 
mov ecx, [esp+3*4+6+4] ; ptr to begin of buff
add ecx, [esp+3*4+6+4+4] ; buff size
sub ecx, [esp+2*4] ; ptr to ip header
add ecx, [esp] ; offset
 
DEBUGF 1,"Ipv4_fragment: %u bytes remaining\n", ecx
 
cmp ecx, [esp+1*4]
jae .new_fragment
 
mov [esp+4], ecx ; set fragment size to remaining packet size
jmp .new_fragment
 
.err:
DEBUGF 1,"Ipv4_fragment: failed\n"
.done:
add esp, 12 + 4 + 6
.err2:
DEBUGF 1,"Ipv4_fragment: dumping\n"
call kernel_free
add esp, 4
 
ret
 
 
 
;---------------------------------------------------------------------------
;
; IPv4_route
;
; IN: eax = Destination IP
; OUT: edi = device id * 4
; eax = ip of gateway if nescessary, unchanged otherwise
;
;---------------------------------------------------------------------------
align 4
IPv4_route:
 
cmp eax, 0xffffffff
je .broadcast
 
xor edi, edi
mov ecx, MAX_NET_DEVICES
.loop:
mov ebx, [IP_LIST+edi]
and ebx, [SUBNET_LIST+edi]
jz .next
mov edx, eax
and edx, [SUBNET_LIST+edi]
 
cmp ebx, edx
je .found_it
.next:
add edi, 4
dec ecx
jnz .loop
 
.invalid:
xor edi, edi ; if none found, use device 0 as default
mov eax, [GATEWAY_LIST]
 
.found_it:
DEBUGF 1,"IPv4_dest_to_dev: %u\n", edi
ret
 
.broadcast:
xor edi, edi
ret
 
 
 
;---------------------------------------------------------------------------
;
; IPv4_get_frgmnt_num
;
; IN: /
; OUT: fragment number in ax
;
;---------------------------------------------------------------------------
align 4
IPv4_get_frgmnt_num:
xor ax, ax ;;; TODO: replace this with real code
 
ret
 
 
;---------------------------------------------------------------------------
;
; IPv4_API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;---------------------------------------------------------------------------
align 4
IPv4_api:
 
movzx eax, bh
shl eax, 2
 
and ebx, 0x000000ff
cmp ebx, .number
ja .error
jmp dword [.table + 4*ebx]
 
.table:
dd .packets_tx ; 0
dd .packets_rx ; 1
dd .read_ip ; 2
dd .write_ip ; 3
dd .read_dns ; 4
dd .write_dns ; 5
dd .read_subnet ; 6
dd .write_subnet ; 7
dd .read_gateway ; 8
dd .write_gateway ; 9
.number = ($ - .table) / 4 - 1
 
.error:
mov eax, -1
ret
 
.packets_tx:
mov eax, [IP_packets_tx + eax]
ret
 
.packets_rx:
mov eax, [IP_packets_rx + eax]
ret
 
.read_ip:
mov eax, [IP_LIST + eax]
ret
 
.write_ip:
mov [IP_LIST + eax], ecx
mov edi, eax ; device number, we'll need it for ARP
 
; pre-calculate the local broadcast address
mov ebx, [SUBNET_LIST + eax]
not ebx
or ebx, ecx
mov [BROADCAST_LIST + eax], ebx
 
mov eax, ecx
call ARP_output_request ; now send a gratuitous ARP
 
call NET_send_event
xor eax, eax
ret
 
.read_dns:
mov eax, [DNS_LIST + eax]
ret
 
.write_dns:
mov [DNS_LIST + eax], ecx
call NET_send_event
xor eax, eax
ret
 
.read_subnet:
mov eax, [SUBNET_LIST + eax]
ret
 
.write_subnet:
mov [SUBNET_LIST + eax], ecx
 
; pre-calculate the local broadcast address
mov ebx, [IP_LIST + eax]
not ecx
or ecx, ebx
mov [BROADCAST_LIST + eax], ecx
 
call NET_send_event
xor eax, eax
ret
 
.read_gateway:
mov eax, [GATEWAY_LIST + eax]
ret
 
.write_gateway:
mov [GATEWAY_LIST + eax], ecx
 
call NET_send_event
xor eax, eax
ret
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/network/socket.inc
0,0 → 1,2285
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org, ;;
;; and Clevermouse. ;;
;; ;;
;; Based on code by mike.dld ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
struct SOCKET
 
NextPtr dd ? ; pointer to next socket in list
PrevPtr dd ? ; pointer to previous socket in list
Number dd ? ; socket number
 
mutex MUTEX
 
PID dd ? ; process ID
TID dd ? ; thread ID
Domain dd ? ; INET/LOCAL/..
Type dd ? ; RAW/STREAM/DGRAP
Protocol dd ? ; ICMP/IPv4/ARP/TCP/UDP
errorcode dd ?
device dd ? ; driver pointer, socket pointer if it's an LOCAL socket
 
options dd ?
state dd ?
backlog dw ? ; how many incoming connections that can be queued
 
snd_proc dd ?
rcv_proc dd ?
 
ends
 
struct IP_SOCKET SOCKET
 
LocalIP rd 4 ; network byte order
RemoteIP rd 4 ; network byte order
 
ends
 
struct TCP_SOCKET IP_SOCKET
 
LocalPort dw ? ; network byte order
RemotePort dw ? ; network byte order
 
t_state dd ? ; TCB state
t_rxtshift db ?
rb 3 ; align
t_rxtcur dd ?
t_dupacks dd ?
t_maxseg dd ?
t_force dd ?
t_flags dd ?
 
;---------------
; RFC783 page 21
 
; send sequence
SND_UNA dd ? ; sequence number of unack'ed sent Packets
SND_NXT dd ? ; next send sequence number to use
SND_UP dd ? ; urgent pointer
SND_WL1 dd ? ; window minus one
SND_WL2 dd ? ;
ISS dd ? ; initial send sequence number
SND_WND dd ? ; send window
 
; receive sequence
RCV_WND dd ? ; receive window
RCV_NXT dd ? ; next receive sequence number to use
RCV_UP dd ? ; urgent pointer
IRS dd ? ; initial receive sequence number
 
;---------------------
; Additional variables
 
; receive variables
RCV_ADV dd ?
 
; retransmit variables
SND_MAX dd ?
 
; congestion control
SND_CWND dd ?
SND_SSTHRESH dd ?
 
;----------------------
; Transmit timing stuff
t_idle dd ?
t_rtt dd ?
t_rtseq dd ?
t_srtt dd ?
t_rttvar dd ?
t_rttmin dd ?
max_sndwnd dd ?
 
;-----------------
; Out-of-band data
t_oobflags dd ?
t_iobc dd ?
t_softerror dd ?
 
 
;---------
; RFC 1323 ; the order of next 4 elements may not change
 
SND_SCALE db ?
RCV_SCALE db ?
requested_s_scale db ?
request_r_scale db ?
 
ts_recent dd ? ; a copy of the most-recent valid timestamp from the other end
ts_recent_age dd ?
last_ack_sent dd ?
 
 
;-------
; Timers
timer_retransmission dd ? ; rexmt
timer_persist dd ?
timer_keepalive dd ? ; keepalive/syn timeout
timer_timed_wait dd ? ; also used as 2msl timer
 
; extra
 
ts_ecr dd ? ; timestamp echo reply
ts_val dd ?
 
seg_next dd ? ; re-assembly queue
 
temp_bits db ?
rb 3 ; align
 
ends
 
struct UDP_SOCKET IP_SOCKET
 
LocalPort dw ? ; network byte order
RemotePort dw ? ; network byte order
firstpacket db ?
 
ends
 
 
struct ICMP_SOCKET IP_SOCKET
 
Identifier dw ?
 
ends
 
 
struct RING_BUFFER
 
mutex MUTEX
start_ptr dd ? ; Pointer to start of buffer
end_ptr dd ? ; pointer to end of buffer
read_ptr dd ? ; Read pointer
write_ptr dd ? ; Write pointer
size dd ? ; Number of bytes buffered
 
ends
 
struct STREAM_SOCKET TCP_SOCKET
 
rcv RING_BUFFER
snd RING_BUFFER
 
ends
 
struct socket_queue_entry
 
data_ptr dd ?
buf_ptr dd ?
data_size dd ?
 
ends
 
 
SOCKETBUFFSIZE = 4096 ; in bytes
 
SOCKET_QUEUE_SIZE = 10 ; maximum number of incoming packets queued for 1 socket
; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
SOCKET_QUEUE_LOCATION = (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*sizeof.socket_queue_entry - sizeof.queue)
 
uglobal
net_sockets rd 4
last_socket_num dd ?
last_UDP_port dw ? ; These values give the number of the last used ephemeral port
last_TCP_port dw ? ;
endg
 
 
;-----------------------------------------------------------------
;
; SOCKET_init
;
;-----------------------------------------------------------------
macro SOCKET_init {
 
xor eax, eax
mov edi, net_sockets
mov ecx, 5
rep stosd
 
@@:
pseudo_random eax
cmp ax, MIN_EPHEMERAL_PORT
jb @r
cmp ax, MAX_EPHEMERAL_PORT
ja @r
xchg al, ah
mov [last_UDP_port], ax
 
@@:
pseudo_random eax
cmp ax, MIN_EPHEMERAL_PORT
jb @r
cmp ax, MAX_EPHEMERAL_PORT
ja @r
xchg al, ah
mov [last_TCP_port], ax
 
}
 
;-----------------------------------------------------------------
;
; Socket API (function 74)
;
;-----------------------------------------------------------------
align 4
sys_socket:
 
cmp ebx, 255
jz SOCKET_debug
 
cmp ebx, .number
ja s_error
jmp dword [.table + 4*ebx]
 
.table:
dd SOCKET_open ; 0
dd SOCKET_close ; 1
dd SOCKET_bind ; 2
dd SOCKET_listen ; 3
dd SOCKET_connect ; 4
dd SOCKET_accept ; 5
dd SOCKET_send ; 6
dd SOCKET_receive ; 7
dd SOCKET_set_opt ; 8
dd SOCKET_get_opt ; 9
dd SOCKET_pair ; 10
.number = ($ - .table) / 4 - 1
 
s_error:
DEBUGF 2,"SOCKET: error\n"
mov dword [esp+32], -1
 
ret
 
;-----------------------------------------------------------------
;
; SOCKET_open
;
; IN: domain in ecx
; type in edx
; protocol in esi
; OUT: eax is socket num, -1 on error
;
;-----------------------------------------------------------------
align 4
SOCKET_open:
 
DEBUGF 2,"SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi
 
push ecx edx esi
call SOCKET_alloc
pop esi edx ecx
jz s_error
 
mov [esp+32], edi ; return socketnumber
DEBUGF 2,"socknum=%u\n", edi
 
; push edx
; and edx, SO_NONBLOCK
or [eax + SOCKET.options], SO_NONBLOCK ;edx
; pop edx
; and edx, not SO_NONBLOCK
 
mov [eax + SOCKET.Domain], ecx
mov [eax + SOCKET.Type], edx
mov [eax + SOCKET.Protocol], esi
 
cmp ecx, AF_INET4
jne .no_inet4
 
cmp edx, SOCK_DGRAM
je .udp
 
cmp edx, SOCK_STREAM
je .tcp
 
cmp edx, SOCK_RAW
je .raw
 
.no_inet4:
cmp ecx, AF_PPP
jne .no_ppp
 
cmp esi, PPP_PROTO_ETHERNET
je .pppoe
 
.no_ppp:
DEBUGF 2,"Unknown socket family/protocol\n"
ret
 
align 4
.raw:
test esi, esi ; IP_PROTO_IP
jz .ip
 
cmp esi, IP_PROTO_ICMP
je .icmp
 
cmp esi, IP_PROTO_UDP
je .udp
 
cmp esi, IP_PROTO_TCP
je .tcp
 
ret
 
align 4
.udp:
mov [eax + SOCKET.Protocol], IP_PROTO_UDP
mov [eax + SOCKET.snd_proc], SOCKET_send_udp
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
ret
 
align 4
.tcp:
mov [eax + SOCKET.Protocol], IP_PROTO_TCP
mov [eax + SOCKET.snd_proc], SOCKET_send_tcp
mov [eax + SOCKET.rcv_proc], SOCKET_receive_stream
 
TCP_init_socket eax
ret
 
 
align 4
.ip:
mov [eax + SOCKET.snd_proc], SOCKET_send_ip
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
ret
 
 
align 4
.icmp:
mov [eax + SOCKET.snd_proc], SOCKET_send_icmp
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
ret
 
align 4
.pppoe:
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue
pop eax
 
mov [eax + SOCKET.snd_proc], SOCKET_send_pppoe
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
ret
 
 
;-----------------------------------------------------------------
;
; SOCKET_bind
;
; IN: socket number in ecx
; pointer to sockaddr struct in edx
; length of that struct in esi
; OUT: 0 on success
;
;-----------------------------------------------------------------
align 4
SOCKET_bind:
 
DEBUGF 2,"SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
 
call SOCKET_num_to_ptr
jz s_error
 
cmp esi, 2
jb s_error
 
cmp word [edx], AF_INET4
je .af_inet4
 
cmp word [edx], AF_LOCAL
je .af_local
 
jmp s_error
 
.af_local:
; TODO: write code here
 
mov dword [esp+32], 0
ret
 
.af_inet4:
 
cmp esi, 6
jb s_error
 
cmp [eax + SOCKET.Protocol], IP_PROTO_UDP
je .udp
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
je .tcp
 
jmp s_error
 
.tcp:
.udp:
 
mov ebx, [edx + 4] ; First, fill in the IP
test ebx, ebx ; If IP is 0, use default
jnz @f
mov ebx, [NET_DEFAULT]
mov ebx, [IP_LIST + 4*ebx]
@@:
mov [eax + IP_SOCKET.LocalIP], ebx
 
mov bx, [edx + 2] ; Now fill in the local port if it's still available
call SOCKET_check_port
jz s_error ; ZF is set by socket_check_port, on error
 
DEBUGF 1,"SOCKET_bind: local ip=%u.%u.%u.%u\n",\
[eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
[eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
 
mov dword [esp+32], 0
ret
 
 
 
 
;-----------------------------------------------------------------
;
; SOCKET_connect
;
; IN: socket number in ecx
; pointer to sockaddr struct in edx
; length of that struct in esi
; OUT: 0 on success
;
;-----------------------------------------------------------------
align 4
SOCKET_connect:
 
DEBUGF 2,"SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
 
call SOCKET_num_to_ptr
jz s_error
 
cmp esi, 8
jb s_error
 
cmp word [edx], AF_INET4
je .af_inet4
 
jmp s_error
 
.af_inet4:
cmp [eax + IP_SOCKET.LocalIP], 0
jne @f
push [IP_LIST] ; FIXME
pop [eax + IP_SOCKET.LocalIP]
@@:
 
cmp [eax + SOCKET.Protocol], IP_PROTO_UDP
je .udp
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
je .tcp
 
cmp [eax + SOCKET.Protocol], IP_PROTO_IP
je .ip
 
cmp [eax + SOCKET.Protocol], IP_PROTO_ICMP
je .ip
 
jmp s_error
 
align 4
.udp:
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
 
pushw [edx + 2]
pop [eax + UDP_SOCKET.RemotePort]
 
pushd [edx + 4]
pop [eax + IP_SOCKET.RemoteIP]
 
cmp [eax + UDP_SOCKET.LocalPort], 0
jne @f
call SOCKET_find_port
@@:
 
mov [eax + UDP_SOCKET.firstpacket], 0
 
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue
pop eax
 
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
 
mov dword [esp+32], 0
ret
 
align 4
.tcp:
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
 
pushw [edx + 2]
pop [eax + TCP_SOCKET.RemotePort]
 
pushd [edx + 4]
pop [eax + IP_SOCKET.RemoteIP]
 
cmp [eax + TCP_SOCKET.LocalPort], 0
jne @f
call SOCKET_find_port
@@:
 
mov [eax + TCP_SOCKET.timer_persist], 0
mov [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT
 
push [TCP_sequence_num]
add [TCP_sequence_num], 6400
pop [eax + TCP_SOCKET.ISS]
mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init
 
 
TCP_sendseqinit eax
 
; mov [ebx + TCP_SOCKET.timer_retransmission], ;; todo: create macro to set retransmission timer
 
mov ebx, eax
 
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_create
 
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_create
 
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
popa
 
mov eax, ebx
call TCP_output
 
;;; TODO: wait for successfull connection if blocking socket
 
mov dword [esp+32], 0
ret
 
align 4
.ip:
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
 
pushd [edx + 4]
pop [eax + IP_SOCKET.RemoteIP]
 
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue
pop eax
 
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
 
mov dword [esp+32], 0
ret
 
 
;-----------------------------------------------------------------
;
; SOCKET_listen
;
; IN: socket number in ecx
; backlog in edx
; OUT: eax is socket num, -1 on error
;
;-----------------------------------------------------------------
align 4
SOCKET_listen:
 
DEBUGF 2,"SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
 
call SOCKET_num_to_ptr
jz s_error
 
cmp [eax + SOCKET.Domain], AF_INET4
jne s_error
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
jne s_error
 
cmp [eax + TCP_SOCKET.LocalPort], 0
je s_error
 
cmp [eax + IP_SOCKET.LocalIP], 0
jne @f
push [IP_LIST]
pop [eax + IP_SOCKET.LocalIP]
@@:
 
cmp edx, MAX_backlog
jbe @f
mov edx, MAX_backlog
@@:
 
mov [eax + SOCKET.backlog], dx
or [eax + SOCKET.options], SO_ACCEPTCON
mov [eax + TCP_SOCKET.t_state], TCPS_LISTEN
mov [eax + TCP_SOCKET.timer_keepalive], 0 ; disable keepalive timer
 
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up sockets queue
pop eax
 
mov dword [esp+32], 0
 
ret
 
 
;-----------------------------------------------------------------
;
; SOCKET_accept
;
; IN: socket number in ecx
; addr in edx
; addrlen in esi
; OUT: eax is socket num, -1 on error
;
;-----------------------------------------------------------------
align 4
SOCKET_accept:
 
DEBUGF 2,"SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
 
call SOCKET_num_to_ptr
jz s_error
 
test [eax + SOCKET.options], SO_ACCEPTCON
jz s_error
 
cmp [eax + SOCKET.Domain], AF_INET4
jne s_error
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
jne s_error
 
.loop:
get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .block
 
; Ok, we got a socket ptr
mov eax, [esi]
 
; Change thread ID to that of the current thread
mov ebx, [TASK_BASE]
mov ebx, [ebx + TASKDATA.pid]
mov [eax + SOCKET.TID], ebx
 
; Convert it to a socket number
call SOCKET_ptr_to_num
jz s_error
; and return it to caller
mov [esp+32], eax
ret
 
.block:
test [eax + SOCKET.options], SO_NONBLOCK
jnz s_error
 
call SOCKET_block
jmp .loop
 
;-----------------------------------------------------------------
;
; SOCKET_close
;
; IN: socket number in ecx
; OUT: eax is socket num, -1 on error
;
;-----------------------------------------------------------------
align 4
SOCKET_close:
 
DEBUGF 2,"SOCKET_close: socknum=%u\n", ecx
 
call SOCKET_num_to_ptr
jz s_error
 
mov dword [esp+32], 0 ; The socket exists, so we will succeed in closing it.
 
.socket:
or [eax + SOCKET.options], SO_NONBLOCK ; Mark the socket as non blocking, we dont want it to block any longer!
 
test [eax + SOCKET.state], SS_BLOCKED ; Is the socket still in blocked state?
jz @f
call SOCKET_notify.unblock ; Unblock it.
@@:
 
cmp [eax + SOCKET.Domain], AF_INET4
jne .free
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
je .tcp
 
.free:
call SOCKET_free
ret
 
.tcp:
cmp [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED ; state must be LISTEN, SYN_SENT or CLOSED
jb .free
 
call TCP_usrclosed
call TCP_output ;;;; Fixme: is this nescessary??
 
ret
 
 
;-----------------------------------------------------------------
;
; SOCKET_receive
;
; IN: socket number in ecx
; addr to buffer in edx
; length of buffer in esi
; flags in edi
; OUT: eax is number of bytes copied, -1 on error
;
;-----------------------------------------------------------------
align 4
SOCKET_receive:
 
DEBUGF 2,"SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
 
call SOCKET_num_to_ptr
jz s_error
 
jmp [eax + SOCKET.rcv_proc]
 
 
align 4
SOCKET_receive_dgram:
 
DEBUGF 1,"SOCKET_receive: DGRAM\n"
 
mov ebx, esi
mov edi, edx ; addr to buffer
 
.loop:
get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .block ; destroys esi and ecx
 
mov ecx, [esi + socket_queue_entry.data_size]
DEBUGF 1,"SOCKET_receive: %u bytes data\n", ecx
 
cmp ecx, ebx
ja .too_small
 
push [esi + socket_queue_entry.buf_ptr] ; save the buffer addr so we can clear it later
mov esi, [esi + socket_queue_entry.data_ptr]
DEBUGF 1,"SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
mov [esp+32+4], ecx ; return number of bytes copied
 
; copy the data
shr ecx, 1
jnc .nb
movsb
.nb:
shr ecx, 1
jnc .nw
movsw
.nw:
test ecx, ecx
jz .nd
rep movsd
.nd:
 
call kernel_free ; remove the packet
ret
 
.too_small:
 
DEBUGF 2,"SOCKET_receive: Buffer too small\n"
jmp s_error
 
.block:
test [eax + SOCKET.options], SO_NONBLOCK
jnz s_error
 
call SOCKET_block
jmp .loop
 
 
align 4
SOCKET_receive_local:
 
; does this socket have a PID yet?
cmp [eax + SOCKET.PID], 0
jne @f
 
; Change PID to that of current process
mov ebx, [TASK_BASE]
mov ebx, [ebx + TASKDATA.pid]
mov [eax + SOCKET.PID], ebx
mov [eax + SOCKET.TID], ebx ; currently TID = PID in kolibrios :(
@@:
 
mov [eax + SOCKET.rcv_proc], SOCKET_receive_stream
 
align 4
SOCKET_receive_stream:
 
DEBUGF 1,"SOCKET_receive: STREAM\n"
 
mov ebx, edi
mov ecx, esi
mov edi, edx
xor edx, edx
 
test ebx, MSG_DONTWAIT
jnz .dontwait
.loop:
cmp [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
je .block
.dontwait:
test ebx, MSG_PEEK
jnz .peek
 
add eax, STREAM_SOCKET.rcv
call SOCKET_ring_read
call SOCKET_ring_free
 
mov [esp+32], ecx ; return number of bytes copied
ret
 
.peek:
mov ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
mov [esp+32], ecx ; return number of bytes available
ret
 
.block:
test [eax + SOCKET.options], SO_NONBLOCK
jnz .return0
 
call SOCKET_block
jmp .loop
 
.return0:
xor ecx, ecx
mov [esp+32], ecx
ret
 
 
;-----------------------------------------------------------------
;
; SOCKET_send
;
;
; IN: socket number in ecx
; pointer to data in edx
; datalength in esi
; flags in edi
; OUT: -1 on error
;
;-----------------------------------------------------------------
align 4
SOCKET_send:
 
DEBUGF 2,"SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
 
call SOCKET_num_to_ptr
jz s_error
 
mov ecx, esi
mov esi, edx
 
jmp [eax + SOCKET.snd_proc]
 
 
align 4
SOCKET_send_udp:
 
DEBUGF 1,"SOCKET_send: UDP\n"
 
mov [esp+32], ecx
call UDP_output
cmp eax, -1
je s_error
ret
 
 
align 4
SOCKET_send_tcp:
 
DEBUGF 1,"SOCKET_send: TCP\n"
 
push eax
add eax, STREAM_SOCKET.snd
call SOCKET_ring_write
pop eax
 
mov [esp+32], ecx
 
call TCP_output
ret
 
 
align 4
SOCKET_send_ip:
 
DEBUGF 1,"SOCKET_send: IPv4\n"
 
mov [esp+32], ecx
call IPv4_output_raw
cmp eax, -1
je s_error
ret
 
 
align 4
SOCKET_send_icmp:
 
DEBUGF 1,"SOCKET_send: ICMP\n"
 
mov [esp+32], ecx
call ICMP_output_raw
cmp eax, -1
je s_error
ret
 
 
align 4
SOCKET_send_pppoe:
 
DEBUGF 1,"SOCKET_send: PPPoE\n"
 
mov [esp+32], ecx
mov ebx, [eax + SOCKET.device]
 
call PPPoE_discovery_output
cmp eax, -1
je s_error
ret
 
 
 
align 4
SOCKET_send_local:
 
; does this socket have a PID yet?
cmp [eax + SOCKET.PID], 0
jne @f
 
; Change PID to that of current process
mov ebx, [TASK_BASE]
mov ebx, [ebx + TASKDATA.pid]
mov [eax + SOCKET.PID], ebx
mov [eax + SOCKET.TID], ebx ; currently TID = PID in kolibrios :(
@@:
mov [eax + SOCKET.snd_proc], SOCKET_send_local_
 
align 4
SOCKET_send_local_:
 
DEBUGF 1,"SOCKET_send: LOCAL\n"
 
; get the other side's socket and check if it still exists
mov eax, [eax + SOCKET.device]
call SOCKET_check
jz s_error
 
; allright, shove in the data!
push eax
add eax, STREAM_SOCKET.rcv
call SOCKET_ring_write
pop eax
 
; return the number of written bytes (or errorcode) to application
mov [esp+32], ecx
 
; and notify the other end
call SOCKET_notify
 
ret
 
 
;-----------------------------------------------------------------
;
; SOCKET_get_options
;
; IN: ecx = socket number
; edx = pointer to the options:
; dd level, optname, optval, optlen
; OUT: -1 on error
;
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
; TODO: find best way to notify that send()'ed data were acknowledged
; Also pseudo-optname -3 is valid and returns socket state, one of TCPS_*.
;
;-----------------------------------------------------------------
align 4
SOCKET_get_opt:
 
DEBUGF 2,"SOCKET_get_opt\n"
 
call SOCKET_num_to_ptr
jz s_error
 
cmp dword [edx], IP_PROTO_TCP
jne s_error
cmp dword [edx+4], -2
je @f
cmp dword [edx+4], -3
jne s_error
@@:
; mov eax, [edx+12]
; test eax, eax
; jz .fail
; cmp dword [eax], 4
; mov dword [eax], 4
; jb .fail
; stdcall net_socket_num_to_addr, ecx
; test eax, eax
; jz .fail
; ; todo: check that eax is really TCP socket
; mov ecx, [eax + TCP_SOCKET.last_ack_number]
; cmp dword [edx+4], -2
; jz @f
; mov ecx, [eax + TCP_SOCKET.state]
@@:
mov eax, [edx+8]
test eax, eax
jz @f
mov [eax], ecx
@@:
mov dword [esp+32], 0
ret
 
 
 
;-----------------------------------------------------------------
;
; SOCKET_set_options
;
; IN: ecx = socket number
; edx = pointer to the options:
; dd level, optname, optlen, optval
; OUT: -1 on error
;
;-----------------------------------------------------------------
align 4
SOCKET_set_opt:
 
DEBUGF 2,"SOCKET_set_opt\n"
 
call SOCKET_num_to_ptr
jz s_error
 
cmp dword [edx], SOL_SOCKET
jne s_error
 
cmp dword [edx+4], SO_BINDTODEVICE
je .bind
 
cmp dword [edx+4], SO_BLOCK
je .block
 
jmp s_error
 
.bind:
cmp dword [edx+8], 0
je .unbind
 
movzx edx, byte [edx + 9]
cmp edx, MAX_NET_DEVICES
ja s_error
 
mov edx, [NET_DRV_LIST + 4*edx]
test edx, edx
jz s_error
mov [eax + SOCKET.device], edx
 
DEBUGF 1,"SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
 
mov dword [esp+32], 0 ; success!
ret
 
.unbind:
mov [eax + SOCKET.device], 0
 
mov dword [esp+32], 0 ; success!
ret
 
.block:
cmp dword [edx+8], 0
je .unblock
 
and [eax + SOCKET.options], not SO_NONBLOCK
 
mov dword [esp+32], 0 ; success!
ret
 
.unblock:
or [eax + SOCKET.options], SO_NONBLOCK
 
mov dword [esp+32], 0 ; success!
ret
 
 
 
;-----------------------------------------------------------------
;
; SOCKET_pair
;
; Allocates a pair of linked LOCAL domain sockets
;
; IN: /
; OUT: eax is socket1 num, -1 on error
; ebx is socket2 num
;
;-----------------------------------------------------------------
align 4
SOCKET_pair:
 
DEBUGF 2,"SOCKET_pair\n"
 
call SOCKET_alloc
jz s_error
mov [esp+32], edi ; application's eax
 
mov [eax + SOCKET.Domain], AF_LOCAL
mov [eax + SOCKET.Type], SOCK_STREAM
mov [eax + SOCKET.Protocol], 0 ;;; CHECKME
mov [eax + SOCKET.snd_proc], SOCKET_send_local
mov [eax + SOCKET.rcv_proc], SOCKET_receive_local
mov [eax + SOCKET.PID], 0
mov ebx, eax
 
call SOCKET_alloc
jz .error
mov [esp+24], edi ; application's ebx
 
mov [eax + SOCKET.Domain], AF_LOCAL
mov [eax + SOCKET.Type], SOCK_STREAM
mov [eax + SOCKET.Protocol], 0 ;;; CHECKME
mov [eax + SOCKET.snd_proc], SOCKET_send_local
mov [eax + SOCKET.rcv_proc], SOCKET_receive_local
mov [eax + SOCKET.PID], 0
 
; Link the two sockets to eachother
mov [eax + SOCKET.device], ebx
mov [ebx + SOCKET.device], eax
 
lea eax, [eax + STREAM_SOCKET.rcv]
call SOCKET_ring_create
 
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_create
pop eax
 
ret
 
.error:
mov eax, ebx
call SOCKET_free
jmp s_error
 
 
 
;-----------------------------------------------------------------
;
; SOCKET_debug
;
; Copies socket variables to application buffer
;
; IN: ecx = socket number
; edx = pointer to buffer
;
; OUT: -1 on error
;-----------------------------------------------------------------
align 4
SOCKET_debug:
 
DEBUGF 1,"SOCKET_debug\n"
 
mov edi, edx
 
test ecx, ecx
jz .returnall
 
call SOCKET_num_to_ptr
jz s_error
 
mov esi, eax
mov ecx, SOCKETBUFFSIZE/4
rep movsd
 
mov dword [esp+32], 0
ret
 
.returnall:
mov ebx, net_sockets
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
test ebx, ebx
jz .done
mov eax, [ebx + SOCKET.Number]
stosd
jmp .next_socket
.done:
xor eax, eax
stosd
 
mov dword [esp+32], 0
ret
 
 
;-----------------------------------------------------------------
;
; SOCKET_find_port
;
; Fills in the local port number for TCP and UDP sockets
; This procedure always works because the number of sockets is
; limited to a smaller number then the number of possible ports
;
; IN: eax = socket pointer
; OUT: /
;
;-----------------------------------------------------------------
align 4
SOCKET_find_port:
 
DEBUGF 2,"SOCKET_find_port\n"
 
push ebx esi ecx
 
cmp [eax + SOCKET.Protocol], IP_PROTO_UDP
je .udp
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
je .tcp
 
pop ecx esi ebx
ret
 
.udp:
mov bx, [last_UDP_port]
call .findit
mov [last_UDP_port], bx
 
pop ecx esi ebx
ret
 
.tcp:
mov bx, [last_TCP_port]
call .findit
mov [last_TCP_port], bx
 
pop ecx esi ebx
ret
 
 
.restart:
mov bx, MIN_EPHEMERAL_PORT_N
.findit:
cmp bx, MAX_EPHEMERAL_PORT_N
je .restart
 
add bh, 1
adc bl, 0
 
call SOCKET_check_port
jz .findit
ret
 
 
 
;-----------------------------------------------------------------
;
; SOCKET_check_port (to be used with AF_INET only!)
;
; Checks if a local port number is unused
; If the proposed port number is unused, it is filled in in the socket structure
;
; IN: eax = socket ptr (to find out if its a TCP/UDP socket)
; bx = proposed socket number (network byte order)
;
; OUT: ZF = set on error
;
;-----------------------------------------------------------------
align 4
SOCKET_check_port:
 
DEBUGF 2,"SOCKET_check_port: "
 
mov ecx, [eax + SOCKET.Protocol]
mov edx, [eax + IP_SOCKET.LocalIP]
mov esi, net_sockets
 
.next_socket:
mov esi, [esi + SOCKET.NextPtr]
or esi, esi
jz .port_ok
 
cmp [esi + SOCKET.Protocol], ecx
jne .next_socket
 
cmp [esi + IP_SOCKET.LocalIP], edx
jne .next_socket
 
cmp [esi + UDP_SOCKET.LocalPort], bx
jne .next_socket
 
DEBUGF 2,"local port %x already in use\n", bx ; FIXME: find a way to print big endian values with debugf
ret
 
.port_ok:
DEBUGF 2,"local port %x is free\n", bx ; FIXME: find a way to print big endian values with debugf
mov [eax + UDP_SOCKET.LocalPort], bx
or bx, bx ; clear the zero-flag
ret
 
 
 
;-----------------------------------------------------------------
;
; SOCKET_input
;
; Updates a (stateless) socket with received data
;
; Note: the mutex should already be set !
;
; IN: eax = socket ptr
; ecx = data size
; esi = ptr to data
; [esp] = ptr to buf
; [esp + 4] = buf size
;
; OUT: /
;
;-----------------------------------------------------------------
align 4
SOCKET_input:
 
DEBUGF 2,"SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
 
mov [esp+4], ecx
push esi
mov esi, esp
 
add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
 
DEBUGF 1,"SOCKET_input: success\n"
add esp, sizeof.socket_queue_entry
 
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
popa
 
jmp SOCKET_notify
 
.full:
DEBUGF 2,"SOCKET_input: socket %x is full!\n", eax
 
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
popa
 
call kernel_free
add esp, 8
 
ret
 
 
;--------------------------
;
; eax = ptr to ring struct (just a buffer of the right size)
;
align 4
SOCKET_ring_create:
 
push esi
mov esi, eax
 
push edx
stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
pop edx
 
DEBUGF 1,"SOCKET_ring_created: %x\n", eax
 
pusha
lea ecx, [esi + RING_BUFFER.mutex]
call mutex_init
popa
 
mov [esi + RING_BUFFER.start_ptr], eax
mov [esi + RING_BUFFER.write_ptr], eax
mov [esi + RING_BUFFER.read_ptr], eax
mov [esi + RING_BUFFER.size], 0
add eax, SOCKET_MAXDATA
mov [esi + RING_BUFFER.end_ptr], eax
mov eax, esi
pop esi
 
ret
 
;-----------------------------------------------------------------
;
; SOCKET_ring_write
;
; Adds data to a stream socket, and updates write pointer and size
;
; IN: eax = ptr to ring struct
; ecx = data size
; esi = ptr to data
;
; OUT: ecx = number of bytes stored
;
;-----------------------------------------------------------------
align 4
SOCKET_ring_write:
 
DEBUGF 1,"SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
 
; lock mutex
pusha
lea ecx, [eax + RING_BUFFER.mutex]
call mutex_lock ; TODO: check what registers this function actually destroys
popa
 
; calculate available size
mov edi, SOCKET_MAXDATA
sub edi, [eax + RING_BUFFER.size] ; available buffer size in edi
cmp ecx, edi
jbe .copy
mov ecx, edi
.copy:
mov edi, [eax + RING_BUFFER.write_ptr]
DEBUGF 2,"SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
 
; update write ptr
push edi
add edi, ecx
cmp edi, [eax + RING_BUFFER.end_ptr]
jb @f
sub edi, SOCKET_MAXDATA ; WRAP
@@:
mov [eax + RING_BUFFER.write_ptr], edi
pop edi
 
; update size
add [eax + RING_BUFFER.size], ecx
 
; copy the data
push ecx
shr ecx, 1
jnc .nb
movsb
.nb:
shr ecx, 1
jnc .nw
movsw
.nw:
test ecx, ecx
jz .nd
rep movsd
.nd:
pop ecx
 
; unlock mutex
push eax ecx
lea ecx, [eax + RING_BUFFER.mutex]
call mutex_unlock ; TODO: check what registers this function actually destroys
pop ecx eax
 
ret
 
;-----------------------------------------------------------------
;
; SOCKET_ring_read
;
; IN: eax = ring struct ptr
; ecx = bytes to read
; edx = offset
; edi = ptr to buffer start
;
; OUT: eax = unchanged
; ecx = number of bytes read (0 on error)
; edx = destroyed
; esi = destroyed
; edi = ptr to buffer end
;
;-----------------------------------------------------------------
align 4
SOCKET_ring_read:
 
DEBUGF 1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
 
pusha
lea ecx, [eax + RING_BUFFER.mutex]
call mutex_lock ; TODO: check what registers this function actually destroys
popa
 
mov esi, [eax + RING_BUFFER.read_ptr]
add esi, edx ; esi = start_ptr + offset
 
neg edx
add edx, [eax + RING_BUFFER.size] ; edx = snd.size - offset
jle .no_data_at_all
 
pusha
lea ecx, [eax + RING_BUFFER.mutex]
call mutex_unlock ; TODO: check what registers this function actually destroys
popa
 
cmp ecx, edx
ja .less_data
 
.copy:
DEBUGF 2,"SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
push ecx
shr ecx, 1
jnc .nb
movsb
.nb:
shr ecx, 1
jnc .nw
movsw
.nw:
test ecx, ecx
jz .nd
rep movsd
.nd:
pop ecx
ret
 
.no_data_at_all:
pusha
lea ecx, [eax + RING_BUFFER.mutex]
call mutex_unlock ; TODO: check what registers this function actually destroys
popa
 
DEBUGF 1,"SOCKET_ring_read: no data at all!\n"
xor ecx, ecx
ret
 
.less_data:
mov ecx, edx
jmp .copy
 
 
;-----------------------------------------------------------------
;
; SOCKET_ring_free
;
; Free's some bytes from the ringbuffer
;
; IN: eax = ptr to ring struct
; ecx = data size
;
; OUT: ecx = number of bytes free-ed
;
;-----------------------------------------------------------------
align 4
SOCKET_ring_free:
 
DEBUGF 1,"SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
 
push eax ecx
lea ecx, [eax + RING_BUFFER.mutex]
call mutex_lock ; TODO: check what registers this function actually destroys
pop ecx eax
 
sub [eax + RING_BUFFER.size], ecx
jb .error
add [eax + RING_BUFFER.read_ptr], ecx
 
mov edx, [eax + RING_BUFFER.end_ptr]
cmp [eax + RING_BUFFER.read_ptr], edx
jb @f
sub [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA
@@:
 
push eax ecx
lea ecx, [eax + RING_BUFFER.mutex] ; TODO: check what registers this function actually destroys
call mutex_unlock
pop ecx eax
 
ret
 
.error: ; we could free all available bytes, but that would be stupid, i guess..
DEBUGF 1,"SOCKET_ring_free: buffer=%x error!\n", eax
add [eax + RING_BUFFER.size], ecx
 
push eax
lea ecx, [eax + RING_BUFFER.mutex]
call mutex_unlock ; TODO: check what registers this function actually destroys
pop eax
 
xor ecx, ecx
ret
 
 
;-----------------------------------------------------------------
;
; SOCKET_block
;
; Suspends the thread attached to a socket
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
align 4
SOCKET_block:
 
DEBUGF 1,"SOCKET_block: %x\n", eax
 
pushf
cli
 
; Set the 'socket is blocked' flag
or [eax + SOCKET.state], SS_BLOCKED
 
; Suspend the thread
push edx
mov edx, [TASK_BASE]
mov [edx + TASKDATA.state], 1 ; Suspended
 
; Remember the thread ID so we can wake it up again
mov edx, [edx + TASKDATA.pid]
DEBUGF 1,"SOCKET_block: suspending thread: %u\n", edx
mov [eax + SOCKET.TID], edx
pop edx
 
call change_task
popf
 
DEBUGF 1,"SOCKET_block: continueing\n"
 
ret
 
 
;-----------------------------------------------------------------
;
; SOCKET_notify
;
; notify's the owner of a socket that something happened
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
align 4
SOCKET_notify:
 
DEBUGF 1,"SOCKET_notify: %x\n", eax
 
call SOCKET_check
jz .error
 
test [eax + SOCKET.state], SS_BLOCKED
jnz .unblock
 
test [eax + SOCKET.options], SO_NONBLOCK
jz .error
 
push eax ecx esi
 
; socket exists and is of non blocking type.
; We'll try to flag an event to the thread
 
mov eax, [eax + SOCKET.TID]
test eax, eax
jz .done
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
; PID not found, TODO: close socket!
jmp .done
 
.found_pid:
shl ecx, 8
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
mov [check_idle_semaphore], 200 ; What does this mean??
 
DEBUGF 1,"SOCKET_notify: Raised a network event!\n"
 
jmp .done
 
.unblock:
push eax ecx esi
; Clear the 'socket is blocked' flag
and [eax + SOCKET.state], not SS_BLOCKED
 
; Find the thread's TASK_DATA
mov eax, [eax + SOCKET.TID]
test eax, eax
jz .error
xor ecx, ecx
inc ecx
mov esi, TASK_DATA
.next:
cmp [esi + TASKDATA.pid], eax
je .found
inc ecx
add esi, 0x20
cmp ecx, [TASK_COUNT]
jbe .next
jmp .error
.found:
 
; Run the thread
mov [esi + TASKDATA.state], 0 ; Running
DEBUGF 1,"SOCKET_notify: Unblocked socket!\n"
 
.done:
pop esi ecx eax
 
.error:
ret
 
 
;--------------------------------------------------------------------
;
; SOCKET_alloc
;
; 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).
;
; IN: /
; OUT: eax = 0 on error, socket ptr otherwise
; edi = socket number
; ZF = cleared on error
;
;--------------------------------------------------------------------
align 4
SOCKET_alloc:
 
push ebx
 
stdcall kernel_alloc, SOCKETBUFFSIZE
DEBUGF 1, "SOCKET_alloc: ptr=%x\n", eax
or eax, eax
jz .exit
 
; zero-initialize allocated memory
push eax
mov edi, eax
mov ecx, SOCKETBUFFSIZE / 4
xor eax, eax
rep stosd
pop eax
 
; set send-and receive procedures to return -1
mov [eax + SOCKET.snd_proc], s_error
mov [eax + SOCKET.rcv_proc], s_error
 
; find first free socket number and use it
mov edi, [last_socket_num]
.next_socket_number:
inc edi
jz .next_socket_number ; avoid socket nr 0
cmp edi, -1
je .next_socket_number ; avoid socket nr -1
mov ebx, net_sockets
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
test ebx, ebx
jz .last_socket
 
cmp [ebx + SOCKET.Number], edi
jne .next_socket
jmp .next_socket_number
 
.last_socket:
mov [last_socket_num], edi
mov [eax + SOCKET.Number], edi
DEBUGF 1, "SOCKET_alloc: number=%u\n", edi
 
; Fill in PID
mov ebx, [TASK_BASE]
mov ebx, [ebx + TASKDATA.pid]
mov [eax + SOCKET.PID], ebx
mov [eax + SOCKET.TID], ebx ; currently TID = PID in kolibrios :(
 
; init mutex
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_init
popa
 
; add socket to the list by re-arranging some pointers
mov ebx, [net_sockets + SOCKET.NextPtr]
 
mov [eax + SOCKET.PrevPtr], net_sockets
mov [eax + SOCKET.NextPtr], ebx
 
test ebx, ebx
jz @f
 
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_lock
popa
 
mov [ebx + SOCKET.PrevPtr], eax
 
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
popa
@@:
 
mov [net_sockets + SOCKET.NextPtr], eax
or eax, eax ; used to clear zero flag
.exit:
pop ebx
 
ret
 
 
;----------------------------------------------------
;
; SOCKET_free
;
; Free socket data memory and remove socket from the list
;
; IN: eax = socket ptr
; OUT: /
;
;----------------------------------------------------
align 4
SOCKET_free:
 
DEBUGF 1, "SOCKET_free: %x\n", eax
 
call SOCKET_check
jz .error
 
push ebx
 
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
 
cmp [eax + SOCKET.Domain], AF_INET4
jnz .no_tcp
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
jnz .no_tcp
 
mov ebx, eax
stdcall kernel_free, [ebx + STREAM_SOCKET.rcv.start_ptr]
stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
mov eax, ebx
.no_tcp:
 
push eax ; this will be passed to kernel_free
mov ebx, [eax + SOCKET.NextPtr]
mov eax, [eax + SOCKET.PrevPtr]
 
DEBUGF 1, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
 
test eax, eax
jz @f
mov [eax + SOCKET.NextPtr], ebx
@@:
 
test ebx, ebx
jz @f
mov [ebx + SOCKET.PrevPtr], eax
@@:
 
call kernel_free
pop ebx
 
DEBUGF 1, "SOCKET_free: success!\n"
 
.error:
ret
 
;------------------------------------
;
; SOCKET_fork
;
; Create a child socket
;
; IN: socket nr in ebx
; OUT: child socket nr in eax
;
;-----------------------------------
align 4
SOCKET_fork:
 
DEBUGF 1,"SOCKET_fork: %x\n", ebx
 
; Exit if backlog queue is full
mov eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
cmp ax, [ebx + SOCKET.backlog]
jae .fail
 
; Allocate new socket
push ebx
call SOCKET_alloc
pop ebx
jz .fail
 
push eax
mov esi, esp
add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
pop eax
 
; Copy structure from current socket to new
; We start at PID to preserve the socket num, and the 2 pointers at beginning of socket
lea esi, [ebx + SOCKET.PID]
lea edi, [eax + SOCKET.PID]
mov ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
rep movsd
 
and [eax + SOCKET.options], not SO_ACCEPTCON
 
ret
 
.fail2:
add esp, 4+4+4
.fail:
DEBUGF 1,"SOCKET_fork: failed\n"
xor eax, eax
ret
 
 
;---------------------------------------------------
;
; SOCKET_num_to_ptr
;
; Get socket structure address by its number
;
; IN: ecx = socket number
; OUT: eax = 0 on error, socket ptr otherwise
; ZF = set on error
;
;---------------------------------------------------
align 4
SOCKET_num_to_ptr:
 
DEBUGF 1,"SOCKET_num_to_ptr: num=%u ", ecx
 
mov eax, net_sockets
 
.next_socket:
mov eax, [eax + SOCKET.NextPtr]
or eax, eax
jz .error
cmp [eax + SOCKET.Number], ecx
jne .next_socket
 
test eax, eax
 
DEBUGF 1,"ptr=%x\n", eax
ret
 
.error:
DEBUGF 1,"not found\n", eax
ret
 
 
;---------------------------------------------------
;
; SOCKET_ptr_to_num
;
; Get socket number by its address
;
; IN: eax = socket ptr
; OUT: eax = 0 on error, socket num otherwise
; ZF = set on error
;
;---------------------------------------------------
align 4
SOCKET_ptr_to_num:
 
DEBUGF 1,"SOCKET_ptr_to_num: ptr=%x ", eax
 
call SOCKET_check
jz .error
 
mov eax, [eax + SOCKET.Number]
 
DEBUGF 1,"num=%u\n", eax
ret
 
.error:
DEBUGF 1,"not found\n", eax
ret
 
 
;---------------------------------------------------
;
; SOCKET_check
;
; checks if the given value is really a socket ptr
;
; IN: eax = socket ptr
; OUT: eax = 0 on error, unchanged otherwise
; ZF = set on error
;
;---------------------------------------------------
align 4
SOCKET_check:
 
DEBUGF 1,"SOCKET_check: %x\n", eax
 
push ebx
mov ebx, net_sockets
 
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .done
cmp ebx, eax
jnz .next_socket
 
.done:
mov eax, ebx
test eax, eax
pop ebx
 
ret
 
 
 
;---------------------------------------------------
;
; SOCKET_check_owner
;
; checks if the caller application owns the socket
;
; IN: eax = socket ptr
; OUT: ZF = true/false
;
;---------------------------------------------------
align 4
SOCKET_check_owner:
 
DEBUGF 1,"SOCKET_check_owner: %x\n", eax
 
push ebx
mov ebx, [TASK_BASE]
mov ebx, [ebx + TASKDATA.pid]
cmp [eax + SOCKET.PID], ebx
pop ebx
 
ret
 
 
 
 
;------------------------------------------------------
;
; SOCKET_process_end
;
; Kernel calls this function when a certain process ends
; This function will check if the process had any open sockets
; And update them accordingly
;
; IN: edx = pid
; OUT: /
;
;------------------------------------------------------
align 4
SOCKET_process_end:
 
DEBUGF 1, "SOCKET_process_end: %x\n", edx
 
push ebx
mov ebx, net_sockets
 
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
.next_socket_test:
test ebx, ebx
jz .done
 
cmp [ebx + SOCKET.PID], edx
jne .next_socket
 
DEBUGF 1, "SOCKET_process_end: killing socket %x\n", ebx
 
mov [ebx + SOCKET.PID], 0
mov eax, ebx
mov ebx, [ebx + SOCKET.NextPtr]
pusha
call SOCKET_close.socket
popa
jmp .next_socket_test
 
.done:
pop ebx
 
ret
 
 
 
 
;-----------------------------------------------------------------
;
; SOCKET_is_connecting
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
 
align 4
SOCKET_is_connecting:
 
DEBUGF 1,"SOCKET_is_connecting: %x\n", eax
 
and [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
or [eax + SOCKET.options], SS_ISCONNECTING
 
jmp SOCKET_notify
 
 
 
;-----------------------------------------------------------------
;
; SOCKET_is_connected
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
 
align 4
SOCKET_is_connected:
 
DEBUGF 1,"SOCKET_is_connected: %x\n", eax
 
and [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
or [eax + SOCKET.options], SS_ISCONNECTED
 
jmp SOCKET_notify
 
 
 
 
;-----------------------------------------------------------------
;
; SOCKET_is_disconnecting
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
 
align 4
SOCKET_is_disconnecting:
 
DEBUGF 1,"SOCKET_is_disconnecting: %x\n", eax
 
and [eax + SOCKET.options], not (SS_ISCONNECTING)
or [eax + SOCKET.options], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
 
jmp SOCKET_notify
 
 
 
;-----------------------------------------------------------------
;
; SOCKET_is_disconnected
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
 
align 4
SOCKET_is_disconnected:
 
DEBUGF 1,"SOCKET_is_disconnected: %x\n", eax
 
and [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
or [eax + SOCKET.options], SS_CANTRCVMORE + SS_CANTSENDMORE
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
je .tcp
 
cmp [eax + SOCKET.Protocol], IP_PROTO_UDP
je .udp
 
jmp SOCKET_notify
 
.tcp:
.udp:
mov [eax + UDP_SOCKET.LocalPort], 0 ; UDP and TCP structs store localport at the same offset
mov [eax + UDP_SOCKET.RemotePort], 0
 
jmp SOCKET_notify
 
 
;-----------------------------------------------------------------
;
; SOCKET_cant_recv_more
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
 
align 4
SOCKET_cant_recv_more:
 
DEBUGF 1,"SOCKET_cant_recv_more: %x\n", eax
 
or [eax + SOCKET.options], SS_CANTRCVMORE
 
ret
 
 
 
;-----------------------------------------------------------------
;
; SOCKET_cant_send_more
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
 
align 4
SOCKET_cant_send_more:
 
DEBUGF 1,"SOCKET_cant_send_more: %x\n", eax
 
or [eax + SOCKET.options], SS_CANTSENDMORE
 
ret
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/network/tcp_subr.inc
0,0 → 1,546
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Based on the code of 4.4BSD ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
align 4
iglobal
TCP_backoff db 0,1,2,3,4,5,6,6,6,6,6,6,6
endg
 
macro TCP_checksum IP1, IP2 {
 
;-------------
; Pseudoheader
 
; protocol type
mov edx, IP_PROTO_TCP
 
; source address
add dl, byte [IP1+1]
adc dh, byte [IP1+0]
adc dl, byte [IP1+3]
adc dh, byte [IP1+2]
 
; destination address
adc dl, byte [IP2+1]
adc dh, byte [IP2+0]
adc dl, byte [IP2+3]
adc dh, byte [IP2+2]
 
; size
adc dl, cl
adc dh, ch
 
adc edx, 0
 
;---------------------
; Real header and data
 
push esi
call checksum_1
call checksum_2
pop esi
 
} ; returns in dx only
 
 
 
 
macro TCP_sendseqinit ptr {
 
push edi ;;;; i dont like this static use of edi
mov edi, [ptr + TCP_SOCKET.ISS]
mov [ptr + TCP_SOCKET.SND_UP], edi
mov [ptr + TCP_SOCKET.SND_MAX], edi
mov [ptr + TCP_SOCKET.SND_NXT], edi
mov [ptr + TCP_SOCKET.SND_UNA], edi
pop edi
 
}
 
 
 
macro TCP_rcvseqinit ptr {
 
push edi
mov edi, [ptr + TCP_SOCKET.IRS]
inc edi
mov [ptr + TCP_SOCKET.RCV_NXT], edi
mov [ptr + TCP_SOCKET.RCV_ADV], edi
pop edi
 
}
 
 
 
macro TCP_init_socket socket {
 
mov [socket + TCP_SOCKET.t_maxseg], TCP_mss_default
mov [socket + TCP_SOCKET.t_flags], TF_REQ_SCALE or TF_REQ_TSTMP
 
mov [socket + TCP_SOCKET.t_srtt], TCP_time_srtt_default
mov [socket + TCP_SOCKET.t_rttvar], TCP_time_rtt_default * 4
mov [socket + TCP_SOCKET.t_rttmin], TCP_time_re_min
;;; TODO: TCP_time_rangeset
 
mov [socket + TCP_SOCKET.SND_CWND], TCP_max_win shl TCP_max_winshift
mov [socket + TCP_SOCKET.SND_SSTHRESH], TCP_max_win shl TCP_max_winshift
 
 
}
 
 
;---------------------------
;
; TCP_pull_out_of_band
;
; IN: eax =
; ebx = socket ptr
; edx = tcp packet ptr
;
; OUT: /
;
;---------------------------
 
align 4
TCP_pull_out_of_band:
 
DEBUGF 1,"TCP_pull_out_of_band\n"
 
;;;; 1282-1305
 
ret
 
 
 
 
 
 
 
 
;-------------------------
;
; TCP_drop
;
; IN: eax = socket ptr
; ebx = error number
;
; OUT: eax = socket ptr
;
;-------------------------
align 4
TCP_drop:
 
DEBUGF 1,"TCP_drop: %x\n", eax
 
cmp [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
jb .no_syn_received
 
mov [eax + TCP_SOCKET.t_state], TCPS_CLOSED
 
call TCP_output
 
;;; TODO: update stats
 
jmp TCP_close
 
.no_syn_received:
 
;;; TODO: update stats
 
;;; TODO: check if error code is "Connection timed out' and handle accordingly
 
mov [eax + SOCKET.errorcode], ebx
 
 
 
 
 
 
 
 
;-------------------------
;
; TCP_close
;
; IN: eax = socket ptr
; OUT: eax = socket ptr
;
;-------------------------
align 4
TCP_close:
 
DEBUGF 1,"TCP_close: %x\n", eax
 
;;; TODO: update RTT and mean deviation
;;; TODO: update slow start threshold
 
call SOCKET_is_disconnected
call SOCKET_free
 
ret
 
 
 
 
;-------------------------
;
; TCP_outflags
;
; IN: eax = socket ptr
;
; OUT: edx = flags
;
;-------------------------
align 4
TCP_outflags:
 
mov edx, [eax + TCP_SOCKET.t_state]
movzx edx, byte [edx + .flaglist]
 
DEBUGF 1,"TCP_outflags: socket=%x flags=%x\n", eax, dl
 
ret
 
.flaglist:
 
db TH_RST + TH_ACK ; TCPS_CLOSED
db 0 ; TCPS_LISTEN
db TH_SYN ; TCPS_SYN_SENT
db TH_SYN + TH_ACK ; TCPS_SYN_RECEIVED
db TH_ACK ; TCPS_ESTABLISHED
db TH_ACK ; TCPS_CLOSE_WAIT
db TH_FIN + TH_ACK ; TCPS_FIN_WAIT_1
db TH_FIN + TH_ACK ; TCPS_CLOSING
db TH_FIN + TH_ACK ; TCPS_LAST_ACK
db TH_ACK ; TCPS_FIN_WAIT_2
db TH_ACK ; TCPS_TIMED_WAIT
 
 
 
 
 
 
;---------------------------------------
;
; The fast way to send an ACK/RST/keepalive segment
;
; TCP_respond
;
; IN: ebx = socket ptr
; cl = flags
;
;--------------------------------------
align 4
TCP_respond:
 
DEBUGF 1,"TCP_respond_socket: socket=%x flags=%x\n", ebx, cl
 
;---------------------
; Create the IP packet
 
push cx ebx
mov eax, [ebx + IP_SOCKET.RemoteIP]
mov edx, [ebx + IP_SOCKET.LocalIP]
mov ecx, sizeof.TCP_header
mov di, IP_PROTO_TCP shl 8 + 128
call IPv4_output
test edi, edi
jz .error
pop esi cx
push edx eax
 
;-----------------------------------------------
; Fill in the TCP header by using the socket ptr
 
mov ax, [esi + TCP_SOCKET.LocalPort]
stosw
mov ax, [esi + TCP_SOCKET.RemotePort]
stosw
mov eax, [esi + TCP_SOCKET.SND_NXT]
bswap eax
stosd
mov eax, [esi + TCP_SOCKET.RCV_NXT]
bswap eax
stosd
mov al, 0x50 ; Dataoffset: 20 bytes (TCP_header.DataOffset)
stosb
mov al, cl
stosb
; mov ax, [esi + TCP_SOCKET.RCV_WND]
; rol ax, 8
mov ax, 0x00a0 ;;;;;;; FIXME
stosw ; window
xor eax, eax
stosd ; checksum + urgentpointer
 
;---------------------
; Fill in the checksum
 
.checksum:
sub edi, sizeof.TCP_header
mov ecx, sizeof.TCP_header
xchg esi, edi
TCP_checksum (edi + IP_SOCKET.LocalIP), (edi + IP_SOCKET.RemoteIP)
mov [esi+TCP_header.Checksum], dx
 
;--------------------
; And send the segment
 
call [ebx + NET_DEVICE.transmit]
ret
 
.error:
DEBUGF 1,"TCP_respond_socket: failed\n"
add esp, 2 + 4
 
ret
 
 
 
 
 
 
 
 
;-------------------------
; TCP_respond_segment:
;
; IN: edx = segment ptr (a previously received segment)
; edi = ptr to dest and src IPv4 addresses
; cl = flags
 
align 4
TCP_respond_segment:
 
DEBUGF 1,"TCP_respond_segment: frame=%x flags=%x\n", edx, cl
 
;---------------------
; Create the IP packet
 
push cx edx
mov ebx, [edi + 4]
mov eax, [edi]
mov ecx, sizeof.TCP_header
mov di, IP_PROTO_TCP shl 8 + 128
call IPv4_output
jz .error
pop esi cx
 
push edx eax
 
;---------------------------------------------------
; Fill in the TCP header by using a received segment
 
mov ax, [esi + TCP_header.DestinationPort]
stosw
mov ax, [esi + TCP_header.SourcePort]
stosw
mov eax, [esi + TCP_header.AckNumber]
bswap eax
stosd
xor eax, eax
stosd
mov al, 0x50 ; Dataoffset: 20 bytes (sizeof.TCP_header/4 shl 4)
stosb
mov al, cl
stosb
mov ax, 1280
rol ax, 8
stosw ; window
xor eax, eax
stosd ; checksum + urgentpointer
 
;---------------------
; Fill in the checksum
 
lea esi, [edi - sizeof.TCP_header]
mov ecx, sizeof.TCP_header
TCP_checksum (esi - sizeof.IPv4_header + IPv4_header.DestinationAddress),\ ; FIXME
(esi - sizeof.IPv4_header + IPv4_header.SourceAddress)
mov [esi + TCP_header.Checksum], dx
 
;--------------------
; And send the segment
 
call [ebx + NET_DEVICE.transmit]
ret
 
.error:
DEBUGF 1,"TCP_respond_segment: failed\n"
add esp, 2+4
 
ret
 
 
macro TCPT_RANGESET timer, value, min, max {
 
local .min
local .max
local .done
 
cmp value, min
jb .min
cmp value, max
ja .max
 
mov timer, value
jmp .done
 
.min:
mov timer, value
jmp .done
 
.max:
mov timer, value
jmp .done
 
.done:
}
 
 
align 4
TCP_set_persist:
 
DEBUGF 1,"TCP_set_persist\n"
 
; First, check if retransmit timer is not set, retransmit and persist are mutually exclusive
 
cmp [eax + TCP_SOCKET.timer_retransmission], 0
ja @f
 
; calculate RTO
push ebx
mov ebx, [eax + TCP_SOCKET.t_srtt]
shr ebx, 2
add ebx, [eax + TCP_SOCKET.t_rttvar]
shr ebx, 1
 
mov cl, [eax + TCP_SOCKET.t_rxtshift]
shl ebx, cl
 
; Start/restart persistance timer.
 
TCPT_RANGESET [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max
 
pop ebx
 
cmp [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift
jae @f
inc [eax + TCP_SOCKET.t_rxtshift]
@@:
 
ret
 
 
 
; eax = rtt
; ebx = socket ptr
 
align 4
TCP_xmit_timer:
 
DEBUGF 1,"TCP_xmit_timer: socket=%x rtt=%d0ms\n", ebx, eax
 
;TODO: update stats
 
cmp [ebx + TCP_SOCKET.t_rtt], 0
je .no_rtt_yet
 
; srtt is stored as a fixed point with 3 bits after the binary point.
; The following magic is equivalent of the smoothing algorithm in rfc793 with an alpha of .875
; (srtt = rtt/8 + srtt*7/8 in fixed point)
; Adjust rtt to origin 0.
 
push ecx
mov ecx, [ebx + TCP_SOCKET.t_srtt]
shr ecx, TCP_RTT_SHIFT
sub eax, ecx
dec eax
pop ecx
 
add [ebx + TCP_SOCKET.t_srtt], eax
ja @f
mov [ebx + TCP_SOCKET.t_srtt], 1
@@:
 
; We accumulate a smoothed rtt variance (actually, a smoothed mean difference),
; then set the retransmit timer to smoothed rtt + 4 times the smoothed variance.
; rttvar is stored as fixed point with 2 bits after the binary point.
; The following is equivalent to rfc793 smoothing with an alpha of .75
; (rttvar = rttvar*3/4 + delta/4) (delta = eax)
 
; get abs(eax)
push edx
cdq
xor eax, edx
sub eax, edx
 
mov edx, [ebx + TCP_SOCKET.t_rttvar]
shr edx, TCP_RTTVAR_SHIFT
sub eax, edx
pop edx
 
add [ebx + TCP_SOCKET.t_rttvar], eax
ja @f
mov [ebx + TCP_SOCKET.t_rttvar], 1
@@:
ret
 
 
.no_rtt_yet:
 
push ecx
mov ecx, eax
shl ecx, TCP_RTT_SHIFT
mov [ebx + TCP_SOCKET.t_srtt], ecx
 
shl eax, TCP_RTTVAR_SHIFT - 1
mov [ebx + TCP_SOCKET.t_rttvar], eax
pop ecx
 
ret
 
 
 
 
; eax = max segment size
; ebx = socket ptr
align 4
TCP_mss:
 
cmp eax, 1420 ; FIXME
jbe @f
mov eax, 1420
@@:
mov [ebx + TCP_SOCKET.t_maxseg], eax
 
 
ret
 
 
 
 
; ebx = socket ptr
; edx = segment ptr
align 4
TCP_reassemble:
 
 
 
ret
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/network/tcp_input.inc
0,0 → 1,1664
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Based on the code of 4.4BSD ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
;-----------------------------------------------------------------
;
; TCP_input:
;
; Add a segment to the incoming TCP queue
;
; IN: [esp] = ptr to buffer
; [esp+4] = buffer size (dont care)
; ebx = ptr to device struct
; ecx = segment size
; esi = ptr to TCP segment
; edi = ptr to ipv4 source address, followed by ipv4 dest address
;
; OUT: /
;
;-----------------------------------------------------------------
 
align 4
TCP_input:
 
; record the current time
mov eax, [timer_ticks] ; in 1/100 seconds
mov [esp + 4], eax
 
push ebx ecx esi edi ; mind the order
mov esi, esp
 
pushf
cli
add_to_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .fail
popf
 
add esp, sizeof.TCP_queue_entry
 
mov [check_idle_semaphore], 5
xor edx, edx
mov eax, [TCP_input_event]
mov ebx, [eax + EVENT.id]
xor esi, esi
call raise_event
 
ret
 
.fail:
popf
DEBUGF 2, "TCP incoming queue is full, discarding packet!\n"
 
inc [TCP_segments_missed] ; FIXME: use correct interface
 
add esp, sizeof.TCP_queue_entry - 8
call kernel_free
add esp, 4
 
ret
 
 
 
 
align 4
TCP_process_input:
 
xor esi, esi
mov ecx, MANUAL_DESTROY
call create_event
mov [TCP_input_event], eax
 
.wait:
mov eax, [TCP_input_event]
mov ebx, [eax + EVENT.id]
call wait_event
 
.loop:
get_from_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .wait
 
push [esi + TCP_queue_entry.timestamp]
push [esi + TCP_queue_entry.buffer_ptr]
 
mov ebx, [esi + TCP_queue_entry.device_ptr]
mov ecx, [esi + TCP_queue_entry.segment_size]
mov edi, [esi + TCP_queue_entry.ip_ptr] ; ptr to ipv4 source address, followed by ipv4 destination address
mov esi, [esi + TCP_queue_entry.segment_ptr] ; change esi last
 
DEBUGF 1,"TCP_input: size=%u time=%d\n", ecx, [timer_ticks]
 
mov edx, esi
 
cmp ebx, LOOPBACK_DEVICE
je .checksum_ok
 
; re-calculate the checksum (if not already done by hw)
; test [ebx + NET_DEVICE.hwacc], HWACC_TCP_IPv4_IN
; jnz .checksum_ok
 
push ecx esi
pushw [esi + TCP_header.Checksum]
mov [esi + TCP_header.Checksum], 0
TCP_checksum (edi), (edi+4)
pop cx ; previous checksum
cmp cx, dx
pop edx ecx
jne .drop_no_socket
.checksum_ok:
 
; Verify the data offset
and [edx + TCP_header.DataOffset], 0xf0 ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
shr [edx + TCP_header.DataOffset], 2
cmp [edx + TCP_header.DataOffset], sizeof.TCP_header ; Now see if it's at least the size of a standard TCP header
jb .drop_no_socket ; If not, drop the packet
 
movzx eax, [edx + TCP_header.DataOffset]
sub ecx, eax ; substract TCP header size from total segment size
jb .drop_no_socket ; If total segment size is less then the advertised header size, drop packet
DEBUGF 1,"TCP_input: %u bytes of data\n", ecx
 
;-------------------------------------------
; Convert Big-endian values to little endian
 
ntohd [edx + TCP_header.SequenceNumber]
ntohd [edx + TCP_header.AckNumber]
 
ntohw [edx + TCP_header.Window]
ntohw [edx + TCP_header.UrgentPointer]
 
;------------------------
; Find the socket pointer
 
; IP Packet TCP Destination Port = local Port
; (IP Packet SenderAddress = Remote IP) OR (Remote IP = 0)
; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0)
 
.findpcb:
mov ebx, net_sockets
mov si, [edx + TCP_header.DestinationPort]
 
.socket_loop:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .respond_seg_reset
 
cmp [ebx + SOCKET.Domain], AF_INET4
jne .socket_loop
 
cmp [ebx + SOCKET.Protocol], IP_PROTO_TCP
jne .socket_loop
 
cmp [ebx + TCP_SOCKET.LocalPort], si
jne .socket_loop
 
mov eax, [ebx + IP_SOCKET.RemoteIP]
cmp eax, [edi] ; Ipv4 source address
je @f
test eax, eax
jnz .socket_loop
@@:
 
mov ax, [ebx + TCP_SOCKET.RemotePort]
cmp [edx + TCP_header.SourcePort], ax
je .found_socket
test ax, ax
jnz .socket_loop
.found_socket: ; ebx now contains the socketpointer
DEBUGF 1,"TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2
 
;-------------
; update stats
 
inc [TCP_segments_rx] ; FIXME: correct interface?
 
;----------------------------
; Check if socket isnt closed
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
je .drop_no_socket
 
;----------------
; Lock the socket
 
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_lock
popa
 
DEBUGF 1,"TCP_input: socket locked\n"
 
;---------------------------
; disable all temporary bits
 
mov [ebx + TCP_SOCKET.temp_bits], 0
 
;---------------------------------------
; unscale the window into a 32 bit value
 
movzx eax, [edx + TCP_header.Window]
push ecx
mov cl, [ebx + TCP_SOCKET.SND_SCALE]
shl eax, cl
mov dword [edx + TCP_header.Window], eax ; word after window is checksum, we dont need checksum anymore
pop ecx
 
;---------------------------------------
; Are we accepting incoming connections?
 
test [ebx + SOCKET.options], SO_ACCEPTCON
jz .no_accept
 
DEBUGF 1,"TCP_input: Accepting new connection\n"
 
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
popa
 
push ecx edx esi edi ;;;
call SOCKET_fork
pop edi esi edx ecx
 
test eax, eax
jz .drop_no_socket
 
mov ebx, eax
 
mov [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET ;;; FIXME: should we take over bits from previous socket?
 
push dword [edi + 4] ; Ipv4 destination addres
pop [ebx + IP_SOCKET.LocalIP]
 
push [edx + TCP_header.DestinationPort]
pop [ebx + TCP_SOCKET.LocalPort]
 
mov [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
.no_accept:
 
 
;-------------------------------------
; Reset idle timer and keepalive timer
 
mov [ebx + TCP_SOCKET.t_idle], 0
mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_idle
 
;--------------------
; Process TCP options
 
push ecx
 
movzx ecx, [edx + TCP_header.DataOffset]
cmp ecx, sizeof.TCP_header ; Does header contain any options?
je .no_options
 
DEBUGF 1,"TCP_input: Segment has options\n"
 
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
;;; cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
;;; jz .not_uni_xfer ; also no header prediction
 
add ecx, edx
lea esi, [edx + sizeof.TCP_header]
 
.opt_loop:
cmp esi, ecx ; are we scanning outside of header?
jae .no_options
lodsb
cmp al, TCP_OPT_EOL ; end of option list?
je .no_options
cmp al, TCP_OPT_NOP
je .opt_loop
cmp al, TCP_OPT_MAXSEG
je .opt_maxseg
cmp al, TCP_OPT_WINDOW
je .opt_window
cmp al, TCP_OPT_SACK_PERMIT
je .opt_sack_permit
; cmp al, TCP_OPT_SACK
; je .opt_sack
cmp al, TCP_OPT_TIMESTAMP
je .opt_timestamp
DEBUGF 1,"TCP_input: unknown option:%u\n", al
jmp .no_options ; If we reach here, some unknown options were received, skip them all!
 
.opt_maxseg:
lodsb
cmp al, 4
jne .no_options ; error occured, ignore all options!
 
test [edx + TCP_header.Flags], TH_SYN
jz @f
 
lodsw
rol ax, 8
DEBUGF 1,"TCP_input: Maxseg=%u\n", ax
call TCP_mss
@@:
jmp .opt_loop
 
 
.opt_window:
lodsb
cmp al, 3
jne .no_options
 
test [edx + TCP_header.Flags], TH_SYN
jz @f
 
DEBUGF 1,"TCP_input: Got window scale option\n"
or [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
 
lodsb
mov [ebx + TCP_SOCKET.SND_SCALE], al
;;;;; TODO
 
@@:
jmp .opt_loop
 
 
.opt_sack_permit:
lodsb
cmp al, 2
jne .no_options
 
test [edx + TCP_header.Flags], TH_SYN
jz @f
 
DEBUGF 1,"TCP_input: Selective Acknowledgement permitted\n"
or [ebx + TCP_SOCKET.t_flags], TF_SACK_PERMIT
 
@@:
jmp .opt_loop
 
 
.opt_timestamp:
lodsb
cmp al, 10 ; length must be 10
jne .no_options
 
DEBUGF 1,"TCP_input: Got timestamp option\n"
 
test [edx + TCP_header.Flags], TH_SYN
jz @f
or [ebx + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
@@:
 
lodsd
mov [ebx + TCP_SOCKET.ts_val], eax
lodsd ; timestamp echo reply
mov [ebx + TCP_SOCKET.ts_ecr], eax
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
 
; Since we have a timestamp, lets do the paws test right away!
 
test [edx + TCP_header.Flags], TH_RST
jnz .no_paws
 
mov eax, [ebx + TCP_SOCKET.ts_recent]
test eax, eax
jz .no_paws
cmp eax, [ebx + TCP_SOCKET.ts_val]
jge .no_paws
 
DEBUGF 1,"TCP_input: PAWS: detected an old segment\n"
 
mov eax, [esp+4+4] ; tcp_now
sub eax, [ebx + TCP_SOCKET.ts_recent_age]
 
pop ecx
cmp eax, TCP_PAWS_IDLE
jle .drop_after_ack ; TODO: update stats
push ecx
 
mov [ebx + TCP_SOCKET.ts_recent], 0 ; timestamp was invalid, fix it.
.no_paws:
jmp .opt_loop
 
.no_options:
 
pop ecx
 
;-----------------------------------------------------------------------
; Time to do some header prediction (Original Principle by Van Jacobson)
 
; There are two common cases for an uni-directional data transfer.
;
; General rule: the packets has no control flags, is in-sequence,
; window width didnt change and we're not retransmitting.
;
; Second rules:
; - If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
; In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
;
; - If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
; If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
jnz .not_uni_xfer
 
test [edx + TCP_header.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
jnz .not_uni_xfer
 
test [edx + TCP_header.Flags], TH_ACK
jz .not_uni_xfer
 
mov eax, [edx + TCP_header.SequenceNumber]
cmp eax, [ebx + TCP_SOCKET.RCV_NXT]
jne .not_uni_xfer
 
mov eax, dword [edx + TCP_header.Window]
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jne .not_uni_xfer
 
mov eax, [ebx + TCP_SOCKET.SND_NXT]
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
jne .not_uni_xfer
 
;---------------------------------------
; check if we are sender in the uni-xfer
 
; If the following 4 conditions are all true, this segment is a pure ACK.
;
; - The segment contains no data.
test ecx, ecx
jnz .not_sender
 
; - The congestion window is greater than or equal to the current send window.
; This test is true only if the window is fully open, that is, the connection is not in the middle of slow start or congestion avoidance.
mov eax, [ebx + TCP_SOCKET.SND_CWND]
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jb .not_uni_xfer
 
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
ja .not_uni_xfer
 
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
sub eax, [ebx + TCP_SOCKET.SND_UNA]
jbe .not_uni_xfer
 
DEBUGF 1,"TCP_input: Header prediction: we are sender\n"
 
;---------------------------------
; Packet is a pure ACK, process it
 
; Delete acknowledged bytes from send buffer
pusha
mov ecx, eax
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_free
popa
 
; Update RTT estimators
 
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
jz .no_timestamp_rtt
mov eax, [esp + 4] ; timestamp when this segment was received
sub eax, [ebx + TCP_SOCKET.ts_ecr]
inc eax
call TCP_xmit_timer
jmp .rtt_done
 
.no_timestamp_rtt:
cmp [ebx + TCP_SOCKET.t_rtt], 0
je .rtt_done
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.t_rtseq]
jbe .rtt_done
mov eax, [ebx + TCP_SOCKET.t_rtt]
call TCP_xmit_timer
 
.rtt_done:
 
; update window pointers
mov eax, [edx + TCP_header.AckNumber]
mov [ebx + TCP_SOCKET.SND_UNA], eax
 
; Stop retransmit timer
mov [ebx + TCP_SOCKET.timer_retransmission], 0
 
; Unlock the socket
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
popa
 
; Awaken waiting processes
mov eax, ebx
call SOCKET_notify
 
; Generate more output
call TCP_output
 
jmp .drop_no_socket
 
;-------------------------------------------------
; maybe we are the receiver in the uni-xfer then..
 
.not_sender:
; - The amount of data in the segment is greater than 0 (data count is in ecx)
 
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_UNA]
jne .not_uni_xfer
 
; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
 
;;; TODO
 
; jnz .not_uni_xfer
 
; Complete processing of received data
 
DEBUGF 1,"TCP_input: Header prediction: we are receiving %u bytes\n", ecx
 
add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied
 
movzx esi, [edx + TCP_header.DataOffset]
add esi, edx
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_write ; Add the data to the socket buffer
 
mov eax, ebx
call SOCKET_notify
 
or [ebx + TCP_SOCKET.t_flags], TF_DELACK ; Set delayed ack flag
 
jmp .drop
 
;--------------------------------------------------
; Header prediction failed, do it the slow way
 
.not_uni_xfer:
 
DEBUGF 1,"TCP_input: Header prediction failed\n"
 
; Calculate receive window size
 
push edx
mov eax, SOCKETBUFFSIZE
sub eax, [ebx + STREAM_SOCKET.rcv.size]
mov edx, [ebx + TCP_SOCKET.RCV_ADV]
sub edx, [ebx + TCP_SOCKET.RCV_NXT]
cmp eax, edx
jg @f
mov eax, edx
@@:
DEBUGF 1,"Receive window size=%d\n", eax
mov [ebx + TCP_SOCKET.RCV_WND], eax
pop edx
 
; If we are in listen or syn_sent state, go to that specific code right away
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
je .LISTEN
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT
je .SYN_SENT
 
;----------------------------
; trim any data not in window
 
; check for duplicate data at beginning of segment (635)
 
mov eax, [ebx + TCP_SOCKET.RCV_NXT]
sub eax, [edx + TCP_header.SequenceNumber]
jle .no_duplicate
 
DEBUGF 1,"TCP_input: %u bytes duplicate data!\n", eax
 
test [edx + TCP_header.Flags], TH_SYN
jz .no_dup_syn
 
DEBUGF 1,"TCP_input: got duplicate syn\n"
 
and [edx + TCP_header.Flags], not (TH_SYN)
inc [edx + TCP_header.SequenceNumber]
 
cmp [edx + TCP_header.UrgentPointer], 1
jbe @f
dec [edx + TCP_header.UrgentPointer]
jmp .dup_syn
@@:
and [edx + TCP_header.Flags], not (TH_URG)
.dup_syn:
dec eax
.no_dup_syn:
 
; Check for entire duplicate segment (646)
cmp eax, ecx ; eax holds number of bytes to drop, ecx is data size
jb .duplicate
jnz @f
test [edx + TCP_header.Flags], TH_FIN
jnz .duplicate
@@:
 
; Any valid FIN must be to the left of the window.
; At this point the FIN must be out of sequence or a duplicate, drop it
and [edx + TCP_header.Flags], not TH_FIN
 
; send an ACK and resynchronize and drop any data.
; But keep on processing for RST or ACK
DEBUGF 1, "616\n"
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
mov eax, ecx
;TODO: update stats
 
;-----------------------------------------------
; Remove duplicate data and update urgent offset
 
.duplicate:
;;; TODO: 677
add [edx + TCP_header.SequenceNumber], eax
sub ecx, eax
 
sub [edx + TCP_header.UrgentPointer], ax
jg @f
and [edx + TCP_header.Flags], not (TH_URG)
mov [edx + TCP_header.UrgentPointer], 0
@@:
 
;--------------------------------------------------
; Handle data that arrives after process terminates (687)
 
.no_duplicate:
cmp [ebx + SOCKET.PID], 0
jne .not_terminated
cmp [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
jbe .not_terminated
test ecx, ecx
jz .not_terminated
 
mov eax, ebx
call TCP_close
;;;TODO: update stats
jmp .respond_seg_reset
 
;----------------------------------------
; Remove data beyond right edge of window (700-736)
 
.not_terminated:
mov eax, [edx + TCP_header.SequenceNumber]
add eax, ecx
sub eax, [ebx + TCP_SOCKET.RCV_NXT]
sub eax, [ebx + TCP_SOCKET.RCV_WND] ; eax now holds the number of bytes to drop
jle .no_excess_data
 
DEBUGF 1,"%d bytes beyond right edge of window\n", eax
 
;;; TODO: update stats
cmp eax, ecx
jl .dont_drop_all
; If a new connection request is received while in TIME_WAIT, drop the old connection and start over,
; if the sequence numbers are above the previous ones
 
test [edx + TCP_header.Flags], TH_SYN
jz .no_new_request
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
jne .no_new_request
; mov edx, [ebx + TCP_SOCKET.RCV_NXT]
; cmp edx, [edx + TCP_header.SequenceNumber]
; add edx, 64000 ; TCP_ISSINCR FIXME
mov eax, ebx
call TCP_close
jmp .findpcb ; FIXME: skip code for unscaling window, ...
.no_new_request:
 
; If window is closed can only take segments at window edge, and have to drop data and PUSH from
; incoming segments. Continue processing, but remember to ACK. Otherwise drop segment and ACK
 
cmp [ebx + TCP_SOCKET.RCV_WND], 0
jne .drop_after_ack
mov eax, [edx + TCP_header.SequenceNumber]
cmp eax, [ebx + TCP_SOCKET.RCV_NXT]
jne .drop_after_ack
 
DEBUGF 1, "690\n"
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
;;; TODO: update stats
jmp .no_excess_data
.dont_drop_all:
;;; TODO: update stats
;;; TODO: 733
 
sub ecx, eax
and [ebx + TCP_SOCKET.t_flags], not (TH_PUSH or TH_FIN)
.no_excess_data:
 
;-----------------
; Record timestamp (737-746)
 
; If last ACK falls within this segments sequence numbers, record its timestamp
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
jz .no_timestamp
mov eax, [ebx + TCP_SOCKET.last_ack_sent]
sub eax, [edx + TCP_header.SequenceNumber]
jb .no_timestamp
test [ebx + TCP_header.Flags], TH_SYN or TH_FIN ; syn and fin occupy one byte
jz @f
dec eax
@@:
sub eax, ecx
jae .no_timestamp
 
DEBUGF 1,"Recording timestamp\n"
 
mov eax, [esp + 4] ; tcp_now
mov [ebx + TCP_SOCKET.ts_recent_age], eax
mov eax, [ebx + TCP_SOCKET.ts_val]
mov [ebx + TCP_SOCKET.ts_recent], eax
.no_timestamp:
 
;------------------
; Process RST flags
 
test [edx + TCP_header.Flags], TH_RST
jz .no_rst
 
DEBUGF 1,"TCP_input: Got an RST flag\n"
 
mov eax, [ebx + TCP_SOCKET.t_state]
shl eax, 2
jmp dword [eax + .rst_sw_list]
 
.rst_sw_list:
dd .no_rst ; TCPS_CLOSED
dd .no_rst ; TCPS_LISTEN
dd .no_rst ; TCPS_SYN_SENT
dd .econnrefused ; TCPS_SYN_RECEIVED
dd .econnreset ; TCPS_ESTABLISHED
dd .econnreset ; TCPS_CLOSE_WAIT
dd .econnreset ; TCPS_FIN_WAIT_1
dd .rst_close ; TCPS_CLOSING
dd .rst_close ; TCPS_LAST_ACK
dd .econnreset ; TCPS_FIN_WAIT_2
dd .rst_close ; TCPS_TIMED_WAIT
 
.econnrefused:
DEBUGF 1,"TCP_input: Connection refused\n"
 
mov [ebx + SOCKET.errorcode], ECONNREFUSED
jmp .close
 
.econnreset:
DEBUGF 1,"TCP_input: Connection reset\n"
 
mov [ebx + SOCKET.errorcode], ECONNRESET
 
.close:
DEBUGF 1,"TCP_input: Closing connection\n"
 
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
;;; TODO: update stats (tcp drops)
mov eax, ebx
call TCP_close
jmp .drop_no_socket
 
.rst_close:
DEBUGF 1,"TCP_input: Closing with reset\n"
 
mov eax, ebx
call TCP_close
jmp .drop_no_socket
 
.no_rst:
 
;--------------------------------------
; handle SYN-full and ACK-less segments
 
test [edx + TCP_header.Flags], TH_SYN
jz .not_syn_full
 
mov eax, ebx
mov ebx, ECONNRESET
call TCP_drop
jmp .drop_with_reset
.not_syn_full:
 
;---------------
; ACK processing
 
test [edx + TCP_header.Flags], TH_ACK
jz .drop
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
jb .ack_processed ; states: closed, listen, syn_sent
ja .no_syn_rcv ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait
 
DEBUGF 1,"TCP_input: state=syn_received\n"
 
mov eax, [edx + TCP_header.AckNumber]
cmp [ebx + TCP_SOCKET.SND_UNA], eax
ja .drop_with_reset
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
ja .drop_with_reset
 
;;; TODO: update stats
 
mov eax, ebx
call SOCKET_is_connected
mov [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
 
; Do window scaling?
 
test [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
jz @f
test [ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
jz @f
 
push word [ebx + TCP_SOCKET.requested_s_scale] ; Set send and receive scale factors to the received values
pop word [ebx + TCP_SOCKET.SND_SCALE]
@@:
 
;;; TODO: call TCP_reassemble
 
mov eax, [edx + TCP_header.SequenceNumber]
dec eax
mov [ebx + TCP_SOCKET.SND_WL1], eax
 
.no_syn_rcv:
 
;-------------------------
; check for duplicate ACKs
 
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_UNA]
ja .not_dup_ack
 
test ecx, ecx
jnz .reset_dupacks
 
mov eax, dword [edx + TCP_header.Window]
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jne .reset_dupacks
 
DEBUGF 1,"TCP_input: Processing duplicate ACK\n"
 
; If we have outstanding data, other than a window probe, this is a completely duplicate ACK
; (window info didnt change) The ACK is the biggest we've seen and we've seen exactly our rexmt threshold of them,
; assume a packet has been dropped and retransmit it. Kludge snd_nxt & the congestion window so we send only this one packet.
 
cmp [ebx + TCP_SOCKET.timer_retransmission], 0 ;;;; FIXME
jg @f
 
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_UNA]
je .dup_ack
 
@@:
mov [ebx + TCP_SOCKET.t_dupacks], 0
jmp .not_dup_ack
 
.dup_ack:
inc [ebx + TCP_SOCKET.t_dupacks]
cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
jne .no_re_xmit
 
push [ebx + TCP_SOCKET.SND_NXT] ; >>>>
 
mov eax, [ebx + TCP_SOCKET.SND_WND]
cmp eax, [ebx + TCP_SOCKET.SND_CWND]
cmova eax, [ebx + TCP_SOCKET.SND_CWND]
shr eax, 1
push edx
xor edx, edx
div [ebx + TCP_SOCKET.t_maxseg]
cmp eax, 2
ja @f
xor eax, eax
mov al, 2
@@:
mul [ebx + TCP_SOCKET.t_maxseg]
pop edx
mov [ebx + TCP_SOCKET.SND_SSTHRESH], eax
 
mov [ebx + TCP_SOCKET.timer_retransmission], 0 ; turn off retransmission timer
mov [ebx + TCP_SOCKET.t_rtt], 0
mov eax, [edx + TCP_header.AckNumber]
mov [ebx + TCP_SOCKET.SND_NXT], eax
mov eax, [ebx + TCP_SOCKET.t_maxseg]
mov [ebx + TCP_SOCKET.SND_CWND], eax
 
; Unlock the socket
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
 
; retransmit missing segment
mov eax, [esp]
call TCP_output
 
; Lock the socket again
mov ecx, [esp]
add ecx, SOCKET.mutex
call mutex_lock
pop ebx
 
; Continue processing
xor edx, edx
mov eax, [ebx + TCP_SOCKET.t_maxseg]
mul [ebx + TCP_SOCKET.t_dupacks]
add eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
mov [ebx + TCP_SOCKET.SND_CWND], eax
 
pop eax ; <<<<
cmp eax, [ebx + TCP_SOCKET.SND_NXT]
jb @f
mov [ebx + TCP_SOCKET.SND_NXT], eax
@@:
 
jmp .drop
 
 
.no_re_xmit:
jbe .not_dup_ack
 
DEBUGF 1,"TCP_input: Increasing congestion window\n"
 
mov eax, [ebx + TCP_SOCKET.t_maxseg]
add [ebx + TCP_SOCKET.SND_CWND], eax
 
; Unlock the socket
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
 
; retransmit missing segment
mov eax, [esp]
call TCP_output
 
; Lock the socket again
mov ecx, [esp]
add ecx, SOCKET.mutex
call mutex_lock
pop ebx
 
jmp .drop
 
 
.not_dup_ack:
 
;-------------------------------------------------
; If the congestion window was inflated to account
; for the other side's cached packets, retract it
 
mov eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
cmp eax, [ebx + TCP_SOCKET.SND_CWND]
ja @f
cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
jbe @f
mov [ebx + TCP_SOCKET.SND_CWND], eax
@@:
 
mov [ebx + TCP_SOCKET.t_dupacks], 0
 
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
jbe @f
 
;;; TODO: update stats
jmp .drop_after_ack
 
@@:
 
mov edi, [edx + TCP_header.AckNumber]
sub edi, [ebx + TCP_SOCKET.SND_UNA] ; now we got the number of acked bytes in edi
 
;;; TODO: update stats
 
DEBUGF 1,"TCP_input: acceptable ACK for %u bytes\n", edi
 
;------------------------------------------
; RTT measurements and retransmission timer (912-926)
 
; If we have a timestamp, update smoothed RTT
 
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
jz .timestamp_not_present
mov eax, [esp+4]
sub eax, [ebx + TCP_SOCKET.ts_ecr]
inc eax
call TCP_xmit_timer
jmp .rtt_done_
 
; If no timestamp but transmit timer is running and timed sequence number was acked,
; update smoothed RTT. Since we now have an RTT measurement, cancel the timer backoff
; (Phil Karn's retransmit algo)
; Recompute the initial retransmit timer
 
.timestamp_not_present:
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.t_rtseq]
jbe .rtt_done_
mov eax, [ebx + TCP_SOCKET.t_rtt]
test eax, eax
jz .rtt_done_
call TCP_xmit_timer
 
.rtt_done_:
 
; If all outstanding data is acked, stop retransmit timer and remember to restart (more output or persist)
; If there is more data to be acked, restart retransmit timer, using current (possible backed-off) value.
 
mov eax, [ebx + TCP_SOCKET.SND_MAX]
cmp eax, [edx + TCP_header.AckNumber]
jne .more_data
mov [ebx + TCP_SOCKET.timer_retransmission], 0
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
jmp .no_restart
.more_data:
cmp [ebx + TCP_SOCKET.timer_persist], 0
jne .no_restart
 
mov eax, [ebx + TCP_SOCKET.t_rxtcur]
mov [ebx + TCP_SOCKET.timer_retransmission], eax
 
.no_restart:
 
 
;-------------------------------------------
; Open congestion window in response to ACKs
 
mov esi, [ebx + TCP_SOCKET.SND_CWND]
mov eax, [ebx + TCP_SOCKET.t_maxseg]
 
cmp esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
jbe @f
push edx
push eax
mul eax
div esi
pop edx
shr edx, 3
add eax, edx
pop edx
@@:
 
add esi, eax
 
push ecx
mov cl, [ebx + TCP_SOCKET.SND_SCALE]
mov eax, TCP_max_win
shl eax, cl
pop ecx
 
cmp esi, eax
cmova esi, eax
mov [ebx + TCP_SOCKET.SND_CWND], esi
 
;------------------------------------------
; Remove acknowledged data from send buffer
 
cmp edi, [ebx + STREAM_SOCKET.snd.size]
jbe .finiacked
 
push ecx edx ebx
mov ecx, [ebx + STREAM_SOCKET.snd.size]
lea eax, [ebx + STREAM_SOCKET.snd]
sub [ebx + TCP_SOCKET.SND_WND], ecx
call SOCKET_ring_free
pop ebx edx ecx
 
DEBUGF 1,"TCP_input: our FIN is acked\n"
stc
 
jmp .wakeup
 
.finiacked:
 
push ecx edx ebx
mov ecx, edi
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_free
pop ebx
sub [ebx + TCP_SOCKET.SND_WND], ecx
pop edx ecx
 
DEBUGF 1,"TCP_input: our FIN is not acked\n"
clc
 
;----------------------------------------
; Wake up process waiting on send buffer
 
.wakeup:
 
pushf ; Keep the flags (Carry flag)
mov eax, ebx
call SOCKET_notify
 
; Update TCPS
 
mov eax, [edx + TCP_header.AckNumber]
mov [ebx + TCP_SOCKET.SND_UNA], eax
cmp eax, [ebx + TCP_SOCKET.SND_NXT]
jb @f
mov [ebx + TCP_SOCKET.SND_NXT], eax
@@:
 
popf
 
; General ACK handling complete
; Now do the state-specific ones
; Carry flag is set when our FIN is acked
 
mov eax, [ebx + TCP_SOCKET.t_state]
jmp dword [eax*4 + .ACK_sw_list]
 
.ACK_sw_list:
dd .ack_processed ; TCPS_CLOSED
dd .ack_processed ; TCPS_LISTEN
dd .ack_processed ; TCPS_SYN_SENT
dd .ack_processed ; TCPS_SYN_RECEIVED
dd .ack_processed ; TCPS_ESTABLISHED
dd .ack_processed ; TCPS_CLOSE_WAIT
dd .ack_fw1 ; TCPS_FIN_WAIT_1
dd .ack_c ; TCPS_CLOSING
dd .ack_la ; TCPS_LAST_ACK
dd .ack_processed ; TCPS_FIN_WAIT_2
dd .ack_tw ; TCPS_TIMED_WAIT
 
 
.ack_fw1:
jnc .ack_processed
 
test [ebx + SOCKET.state], SS_CANTRCVMORE
jnz @f
mov eax, ebx
call SOCKET_is_disconnected
mov [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle
@@:
mov [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
jmp .ack_processed
 
.ack_c:
jnc .ack_processed
 
mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
mov eax, ebx
call TCP_cancel_timers
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
mov eax, ebx
call SOCKET_is_disconnected
jmp .ack_processed
 
.ack_la:
jnc .ack_processed
 
mov eax, ebx
call TCP_disconnect
jmp .drop
 
.ack_tw:
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
jmp .drop_after_ack
 
.reset_dupacks: ; We got a new ACK, reset duplicate ACK counter
mov [ebx + TCP_SOCKET.t_dupacks], 0
jmp .ack_processed
 
;-------
; LISTEN
 
align 4
.LISTEN:
 
DEBUGF 1,"TCP_input: state=listen\n"
 
test [edx + TCP_header.Flags], TH_RST
jnz .drop
 
test [edx + TCP_header.Flags], TH_ACK
jnz .drop_with_reset
 
test [edx + TCP_header.Flags], TH_SYN
jz .drop
 
;;; TODO: check if it's a broadcast or multicast, and drop if so
 
push dword [edi] ; Ipv4 source addres
pop [ebx + IP_SOCKET.RemoteIP]
 
push [edx + TCP_header.SourcePort]
pop [ebx + TCP_SOCKET.RemotePort]
 
push [edx + TCP_header.SequenceNumber]
pop [ebx + TCP_SOCKET.IRS]
 
mov eax, [TCP_sequence_num]
add [TCP_sequence_num], 64000 / 2
mov [ebx + TCP_SOCKET.ISS], eax
mov [ebx + TCP_SOCKET.SND_NXT], eax
 
TCP_sendseqinit ebx
TCP_rcvseqinit ebx
 
mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
mov [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval ;;;; macro
 
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_create
 
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_create
 
and [ebx + TCP_SOCKET.temp_bits], not TCP_BIT_DROPSOCKET
 
;;; call SOCKET_notify_owner
 
jmp .trim_then_step6
 
;------------
; Active Open
 
align 4
.SYN_SENT:
 
DEBUGF 1,"TCP_input: state=syn_sent\n"
 
test [edx + TCP_header.Flags], TH_ACK
jz @f
 
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.ISS]
jbe .drop_with_reset
 
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
ja .drop_with_reset
@@:
 
test [edx + TCP_header.Flags], TH_RST
jz @f
 
test [edx + TCP_header.Flags], TH_ACK
jz .drop
 
mov eax, ebx
mov ebx, ECONNREFUSED
call TCP_drop
 
jmp .drop
@@:
 
test [edx + TCP_header.Flags], TH_SYN
jz .drop
 
; at this point, segment seems to be valid
 
test [edx + TCP_header.Flags], TH_ACK
jz .no_syn_ack
 
; now, process received SYN in response to an active open
 
mov eax, [edx + TCP_header.AckNumber]
mov [ebx + TCP_SOCKET.SND_UNA], eax
cmp eax, [ebx + TCP_SOCKET.SND_NXT]
jbe @f
mov [ebx + TCP_SOCKET.SND_NXT], eax
@@:
 
.no_syn_ack:
mov [ebx + TCP_SOCKET.timer_retransmission], 0 ; disable retransmission
 
push [edx + TCP_header.SequenceNumber]
pop [ebx + TCP_SOCKET.IRS]
 
TCP_rcvseqinit ebx
 
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
 
mov eax, [ebx + TCP_SOCKET.SND_UNA]
cmp eax, [ebx + TCP_SOCKET.ISS]
jbe .simultaneous_open
 
test [edx + TCP_header.Flags], TH_ACK
jz .simultaneous_open
 
DEBUGF 1,"TCP_input: active open\n"
 
;;; TODO: update stats
 
; set socket state to connected
mov [ebx + SOCKET.state], SS_ISCONNECTED
mov [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
 
; Do window scaling on this connection ?
mov eax, [ebx + TCP_SOCKET.t_flags]
and eax, TF_REQ_SCALE or TF_RCVD_SCALE
cmp eax, TF_REQ_SCALE or TF_RCVD_SCALE
jne .no_scaling
 
mov ax, word [ebx + TCP_SOCKET.requested_s_scale]
mov word [ebx + TCP_SOCKET.SND_SCALE], ax
.no_scaling:
 
;;; TODO: reassemble packets queue
 
mov eax, [ebx + TCP_SOCKET.t_rtt]
test eax, eax
je .trim_then_step6
call TCP_xmit_timer
jmp .trim_then_step6
 
.simultaneous_open:
 
DEBUGF 1,"TCP_input: simultaneous open\n"
; We have received a syn but no ACK, so we are having a simultaneous open..
mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
 
;-------------------------------------
; Common processing for receipt of SYN
 
.trim_then_step6:
 
inc [edx + TCP_header.SequenceNumber]
 
;;; TODO: Drop any received data that follows receive window (590)
 
mov eax, [edx + TCP_header.SequenceNumber]
mov [ebx + TCP_SOCKET.RCV_UP], eax
dec eax
mov [ebx + TCP_SOCKET.SND_WL1], eax
 
;-------
; step 6
 
.ack_processed:
 
DEBUGF 1,"TCP_input: ACK processed\n"
 
;----------------------------------------------
; check if we need to update window information
 
test [edx + TCP_header.Flags], TH_ACK
jz .no_window_update
 
mov eax, [ebx + TCP_SOCKET.SND_WL1]
cmp eax, [edx + TCP_header.SequenceNumber]
jb .update_window
ja @f
 
mov eax, [ebx + TCP_SOCKET.SND_WL2]
cmp eax, [edx + TCP_header.AckNumber]
jb .update_window
ja .no_window_update
@@:
 
mov eax, dword [edx + TCP_header.Window]
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jbe .no_window_update
 
.update_window:
 
;;; TODO: update stats (Keep track of pure window updates)
 
mov eax, dword [edx + TCP_header.Window]
cmp eax, [ebx + TCP_SOCKET.max_sndwnd]
jbe @f
mov [ebx + TCP_SOCKET.max_sndwnd], eax
@@:
mov [ebx + TCP_SOCKET.SND_WND], eax
 
DEBUGF 1,"TCP_input: Updating window to %u\n", eax
 
push [edx + TCP_header.SequenceNumber]
pop [ebx + TCP_SOCKET.SND_WL1]
 
push [edx + TCP_header.AckNumber]
pop [ebx + TCP_SOCKET.SND_WL2]
 
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
 
.no_window_update:
 
;-----------------
; process URG flag
 
test [edx + TCP_header.Flags], TH_URG
jz .not_urgent
 
cmp [edx + TCP_header.UrgentPointer], 0
jz .not_urgent
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
je .not_urgent
 
; Ignore bogus urgent offsets
 
movzx eax, [edx + TCP_header.UrgentPointer]
add eax, [ebx + STREAM_SOCKET.rcv.size]
cmp eax, SOCKET_MAXDATA
jbe .not_urgent
 
mov [edx + TCP_header.UrgentPointer], 0
and [edx + TCP_header.Flags], not (TH_URG)
jmp .do_data
 
.not_urgent:
 
; processing of received urgent pointer
 
;;; TODO (1051-1093)
 
 
;---------------------------------------
; process the data in the segment (1094)
 
.do_data:
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
jae .final_processing
 
test [edx + TCP_header.Flags], TH_FIN
jnz @f
 
test ecx, ecx
jnz .final_processing
@@:
 
 
; The segment is in order?
mov eax, [edx + TCP_header.SequenceNumber]
cmp eax, [ebx + TCP_SOCKET.RCV_NXT]
jne .out_of_order
 
; The reassembly queue is empty?
cmp [ebx + TCP_SOCKET.seg_next], 0
jne .out_of_order
 
; The connection is established?
cmp [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
jne .out_of_order
 
; Ok, lets do this.. Set delayed ACK flag and copy data into socket buffer
or [ebx + TCP_SOCKET.t_flags], TF_DELACK
 
pusha
movzx esi, [edx + TCP_header.DataOffset]
add esi, edx
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_write ; Add the data to the socket buffer
add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied
popa
 
; Wake up the sleeping process
mov eax, ebx
call SOCKET_notify
 
jmp .data_done
 
.out_of_order:
 
; Uh-oh, some data is out of order, lets call TCP reassemble for help
 
call TCP_reassemble
 
DEBUGF 1, "1470\n"
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
 
.data_done:
 
;---------------
; FIN processing
 
test [edx + TCP_header.Flags], TH_FIN
jz .final_processing
 
DEBUGF 1,"TCP_input: Processing FIN\n"
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
jae .not_first_fin
 
DEBUGF 1,"TCP_input: First FIN for this connection\n"
 
mov eax, ebx
call SOCKET_cant_recv_more
 
mov [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
inc [ebx + TCP_SOCKET.RCV_NXT]
 
.not_first_fin:
mov eax, [ebx + TCP_SOCKET.t_state]
shl eax, 2
jmp dword [eax + .FIN_sw_list]
 
.FIN_sw_list:
dd .final_processing ; TCPS_CLOSED
dd .final_processing ; TCPS_LISTEN
dd .final_processing ; TCPS_SYN_SENT
dd .fin_syn_est ; TCPS_SYN_RECEIVED
dd .fin_syn_est ; TCPS_ESTABLISHED
dd .final_processing ; TCPS_CLOSE_WAIT
dd .fin_wait1 ; TCPS_FIN_WAIT_1
dd .final_processing ; TCPS_CLOSING
dd .final_processing ; TCPS_LAST_ACK
dd .fin_wait2 ; TCPS_FIN_WAIT_2
dd .fin_timed ; TCPS_TIMED_WAIT
 
.fin_syn_est:
 
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
jmp .final_processing
 
.fin_wait1:
 
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
jmp .final_processing
 
.fin_wait2:
 
mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
mov eax, ebx
call TCP_cancel_timers
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
call SOCKET_is_disconnected
jmp .final_processing
 
.fin_timed:
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
jmp .final_processing
 
 
.drop_after_ack:
DEBUGF 1,"TCP_input: Drop after ACK\n"
 
push edx ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
pop eax edx
 
test [edx + TCP_header.Flags], TH_RST
jnz .dumpit
 
or [eax + TCP_SOCKET.t_flags], TF_ACKNOW
jmp .need_output
 
.drop_with_reset:
DEBUGF 1,"TCP_input: Drop with reset\n"
 
push ebx edx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
pop edx ebx
 
test [edx + TCP_header.Flags], TH_RST
jnz .dumpit
 
;;; if its a multicast/broadcast, also drop
 
test [edx + TCP_header.Flags], TH_ACK
jnz .respond_ack
 
test [edx + TCP_header.Flags], TH_SYN
jnz .respond_syn
jmp .dumpit
 
;-----------------
; Final processing
 
.final_processing:
DEBUGF 1,"TCP_input: Final processing\n"
 
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
pop eax
 
test [eax + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
jnz .need_output
 
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW
jz .dumpit
DEBUGF 1,"TCP_input: ACK now!\n"
 
.need_output:
DEBUGF 1,"TCP_input: need output\n"
call TCP_output
 
.dumpit:
DEBUGF 1,"TCP_input: dumping\n"
 
call kernel_free
add esp, 4
jmp .loop
 
;---------
; Respond
 
.respond_ack:
push ebx
mov cl, TH_RST
call TCP_respond
pop ebx
jmp .destroy_new_socket
 
.respond_syn:
push ebx
mov cl, TH_RST + TH_ACK
call TCP_respond
pop ebx
jmp .destroy_new_socket
 
.respond_seg_reset:
test [edx + TCP_header.Flags], TH_RST
jnz .drop_no_socket
 
;;; TODO: if its a multicast/broadcast, also drop
 
test [edx + TCP_header.Flags], TH_ACK
jnz .respond_seg_ack
 
test [edx + TCP_header.Flags], TH_SYN
jnz .respond_seg_syn
 
jmp .drop_no_socket
 
.respond_seg_ack:
mov cl, TH_RST
call TCP_respond_segment
jmp .drop_no_socket
 
.respond_seg_syn:
mov cl, TH_RST + TH_ACK
call TCP_respond_segment
jmp .drop_no_socket
 
;-----
; Drop
 
.drop:
DEBUGF 1,"TCP_input: Dropping segment\n"
 
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
popa
 
.destroy_new_socket:
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET
jz .drop_no_socket
 
mov eax, ebx
call SOCKET_free
 
.drop_no_socket:
DEBUGF 1,"TCP_input: Drop (no socket)\n"
 
call kernel_free
add esp, 4
jmp .loop
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/network/tcp.inc
0,0 → 1,224
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Based on the code of 4.4BSD ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
; Socket states
TCPS_CLOSED = 0
TCPS_LISTEN = 1
TCPS_SYN_SENT = 2
TCPS_SYN_RECEIVED = 3
TCPS_ESTABLISHED = 4
TCPS_CLOSE_WAIT = 5
TCPS_FIN_WAIT_1 = 6
TCPS_CLOSING = 7
TCPS_LAST_ACK = 8
TCPS_FIN_WAIT_2 = 9
TCPS_TIMED_WAIT = 10
 
; Socket Flags
TF_ACKNOW = 1 shl 0 ; ack peer immediately
TF_DELACK = 1 shl 1 ; ack, but try to delay it
TF_NODELAY = 1 shl 2 ; don't delay packets to coalesce
TF_NOOPT = 1 shl 3 ; don't use tcp options
TF_SENTFIN = 1 shl 4 ; have sent FIN
TF_REQ_SCALE = 1 shl 5 ; have/will request window scaling
TF_RCVD_SCALE = 1 shl 6 ; other side has requested scaling
TF_REQ_TSTMP = 1 shl 7 ; have/will request timestamps
TF_RCVD_TSTMP = 1 shl 8 ; a timestamp was received in SYN
TF_SACK_PERMIT = 1 shl 9 ; other side said I could SACK
 
; Segment flags
TH_FIN = 1 shl 0
TH_SYN = 1 shl 1
TH_RST = 1 shl 2
TH_PUSH = 1 shl 3
TH_ACK = 1 shl 4
TH_URG = 1 shl 5
 
; Segment header options
TCP_OPT_EOL = 0 ; End of option list.
TCP_OPT_NOP = 1 ; No-Operation.
TCP_OPT_MAXSEG = 2 ; Maximum Segment Size.
TCP_OPT_WINDOW = 3 ; window scale
TCP_OPT_SACK_PERMIT = 4 ; Selective Acknowledgement
TCP_OPT_SACK = 5
TCP_OPT_TIMESTAMP = 8
 
; Fundamental timer values
TCP_time_MSL = 47 ; max segment lifetime (30s)
TCP_time_re_min = 2 ; min retransmission (1,28s)
TCP_time_re_max = 100 ; max retransmission (64s)
TCP_time_pers_min = 8 ; min persist (5,12s)
TCP_time_pers_max = 94 ; max persist (60,16s)
TCP_time_keep_init = 118 ; connection establishment (75,52s)
TCP_time_keep_idle = 4608 ; idle time before 1st probe (2h)
TCP_time_keep_interval = 118 ; between probes when no response (75,52s)
TCP_time_rtt_default = 5 ; default Round Trip Time (3,2s)
TCP_time_srtt_default = 0 ;
TCP_time_max_idle = 8*TCP_time_keep_interval ; FIXME
 
; timer constants
TCP_max_rxtshift = 12 ; max retransmissions waiting for ACK
TCP_max_keepcnt = 8 ; max keepalive probes
 
;
TCP_max_winshift = 14
TCP_max_win = 65535
 
TCP_re_xmit_thresh = 3
 
TCP_mss_default = 1480 ; default max segment size
 
; smoothed round trip time and estimated variance are stored as fixed point numbers,
; shifted by the value below.
; With these scales, srtt has 3 bits to the right of the binary point, and thus an "alpha"
; of .875. rttvar has 2 bits to the right and thus "alpha" of 0.75
TCP_RTT_SHIFT = 3
TCP_RTTVAR_SHIFT = 2
 
; bits used by tcp_input and tcp_output
TCP_BIT_NEEDOUTPUT = 1 shl 0
TCP_BIT_TIMESTAMP = 1 shl 1
TCP_BIT_DROPSOCKET = 1 shl 2
 
TCP_BIT_SENDALOT = 1 shl 0
 
TCP_PAWS_IDLE = 24*24*60*60*100 ; 24 days, in 1/100 seconds
 
TCP_QUEUE_SIZE = 50
 
struct TCP_header
 
SourcePort dw ?
DestinationPort dw ?
SequenceNumber dd ?
AckNumber dd ?
DataOffset db ? ; DataOffset[0-3 bits] and Reserved[4-7]
Flags db ? ; Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
Window dw ?
Checksum dw ?
UrgentPointer dw ?
 
ends
 
struct TCP_queue_entry
 
ip_ptr dd ?
segment_ptr dd ?
segment_size dd ?
device_ptr dd ?
 
buffer_ptr dd ?
timestamp dd ?
 
ends
 
align 4
uglobal
TCP_segments_tx rd MAX_NET_DEVICES
TCP_segments_rx rd MAX_NET_DEVICES
TCP_segments_missed rd MAX_NET_DEVICES
TCP_segments_dumped rd MAX_NET_DEVICES
; TCP_bytes_rx rq MAX_NET_DEVICES
; TCP_bytes_tx rq MAX_NET_DEVICES
TCP_sequence_num dd ?
TCP_queue rd TCP_QUEUE_SIZE*sizeof.TCP_queue_entry/4
TCP_input_event dd ?
endg
 
 
;-----------------------------------------------------------------
;
; TCP_init
;
; This function resets all TCP variables
;
;-----------------------------------------------------------------
macro TCP_init {
 
xor eax, eax
mov edi, TCP_segments_tx
mov ecx, (6*MAX_NET_DEVICES)
rep stosd
 
pseudo_random eax
mov [TCP_sequence_num], eax
 
init_queue TCP_queue
 
push 1
pop ebx
mov ecx, TCP_process_input
call new_sys_threads
 
}
 
 
include 'tcp_timer.inc'
include 'tcp_subr.inc'
include 'tcp_usreq.inc'
include 'tcp_input.inc'
include 'tcp_output.inc'
 
 
;---------------------------------------------------------------------------
;
; TCP_API
;
; This function is called by system function 76
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;---------------------------------------------------------------------------
align 4
TCP_api:
 
movzx eax, bh
shl eax, 2
 
test bl, bl
jz .packets_tx ; 0
dec bl
jz .packets_rx ; 1
dec bl
jz .packets_missed ; 2
dec bl
jz .packets_dumped ; 3
 
.error:
mov eax, -1
ret
 
.packets_tx:
mov eax, [TCP_segments_tx + eax]
ret
 
.packets_rx:
mov eax, [TCP_segments_rx + eax]
ret
 
.packets_missed:
mov eax, [TCP_segments_missed + eax]
ret
 
.packets_dumped:
mov eax, [TCP_segments_dumped + eax]
ret
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/network/ARP.inc
0,0 → 1,645
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ARP.INC ;;
;; ;;
;; Part of the tcp/ip network stack for KolibriOS ;;
;; ;;
;; Based on the work of [Johnny_B] and [smb] ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June- 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
ARP_NO_ENTRY = 0
ARP_VALID_MAPPING = 1
ARP_AWAITING_RESPONSE = 2
ARP_RESPONSE_TIMEOUT = 3
 
ARP_REQUEST_TTL = 31 ; 20 s
ARP_ENTRY_TTL = 937 ; 600 s
ARP_STATIC_ENTRY = -1
 
ARP_REQ_OPCODE = 0x0100 ; request
ARP_REP_OPCODE = 0x0200 ; reply
 
ARP_TABLE_SIZE = 20 ; Size of table
 
struct ARP_entry
 
IP dd ?
MAC dp ?
Status dw ?
TTL dw ?
 
ends
 
struct ARP_header
 
HardwareType dw ?
ProtocolType dw ?
HardwareSize db ?
ProtocolSize db ?
Opcode dw ?
SenderMAC dp ?
SenderIP dd ?
TargetMAC dp ?
TargetIP dd ?
 
ends
 
align 4
uglobal
 
NumARP dd ?
 
ARP_table rb ARP_TABLE_SIZE * sizeof.ARP_entry ; TODO: separate ARP table and stats per interface
 
ARP_PACKETS_TX rd MAX_NET_DEVICES
ARP_PACKETS_RX rd MAX_NET_DEVICES
ARP_CONFLICTS rd MAX_NET_DEVICES
 
 
endg
 
 
 
;-----------------------------------------------------------------
;
; ARP_init
;
; This function resets all ARP variables
;
;-----------------------------------------------------------------
macro ARP_init {
 
xor eax, eax
mov [NumARP], eax
 
mov edi, ARP_PACKETS_TX
mov ecx, 3*MAX_NET_DEVICES
rep stosd
 
}
 
;---------------------------------------------------------------------------
;
; ARP_decrease_entry_ttls
;
;---------------------------------------------------------------------------
 
macro ARP_decrease_entry_ttls {
 
local .loop
local .exit
 
; The TTL field is decremented every second, and is deleted when it reaches 0.
; It is refreshed every time a packet is received.
; If the TTL field is 0xFFFF it is a static entry and is never deleted.
; The status field can be the following values:
; 0x0000 entry not used
; 0x0001 entry holds a valid mapping
; 0x0002 entry contains an IP address, awaiting ARP response
; 0x0003 No response received to ARP request.
; The last status value is provided to allow the network layer to delete
; a packet that is queued awaiting an ARP response
 
mov ecx, [NumARP]
test ecx, ecx
jz .exit
 
mov esi, ARP_table
.loop:
cmp [esi + ARP_entry.TTL], ARP_STATIC_ENTRY
je .next
 
dec [esi + ARP_entry.TTL]
jz .time_out
 
.next:
add esi, sizeof.ARP_entry
dec ecx
jnz .loop
jmp .exit
 
.time_out:
cmp [esi + ARP_entry.Status], ARP_AWAITING_RESPONSE
je .response_timeout
 
push esi ecx
call ARP_del_entry
pop ecx esi
 
jmp .next
 
.response_timeout:
mov [esi + ARP_entry.Status], ARP_RESPONSE_TIMEOUT
mov [esi + ARP_entry.TTL], 10
 
jmp .next
 
.exit:
 
}
 
 
;-----------------------------------------------------------------
;
; ARP_input
;
; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
; packet size (without ethernet header) in ecx
; packet ptr in edx
; device ptr in ebx
; OUT: /
;
;-----------------------------------------------------------------
align 4
ARP_input:
 
;-----------------------------------------
; Check validity and print some debug info
 
cmp ecx, sizeof.ARP_header
jb .exit
 
call NET_ptr_to_num
cmp edi, -1
jz .exit
 
inc [ARP_PACKETS_RX + 4*edi] ; update stats
 
DEBUGF 1,"ARP_input: got packet from %u.%u.%u.%u through device %u\n",\
[edx + ARP_header.SenderIP]:1, [edx + ARP_header.SenderIP + 1]:1,\
[edx + ARP_header.SenderIP + 2]:1, [edx + ARP_header.SenderIP + 3]:1, edi
 
;------------------------------
; First, check for IP collision
 
mov eax, [edx + ARP_header.SenderIP]
cmp eax, [IP_LIST + 4*edi]
je .collision
 
;---------------------
; Handle reply packets
 
cmp [edx + ARP_header.Opcode], ARP_REP_OPCODE
jne .maybe_request
 
DEBUGF 1,"ARP_input: It's a reply\n"
 
mov ecx, [NumARP]
test ecx, ecx
jz .exit
 
mov esi, ARP_table
.loop:
cmp [esi + ARP_entry.IP], eax
je .gotit
add esi, sizeof.ARP_entry
dec ecx
jnz .loop
 
DEBUGF 1,"ARP_input: no matching entry found\n"
jmp .exit
 
.gotit:
DEBUGF 1,"ARP_input: found matching entry\n"
 
cmp [esi + ARP_entry.TTL], ARP_STATIC_ENTRY ; if it is a static entry, dont touch it
je .exit
 
DEBUGF 1,"ARP_input: updating entry\n"
 
mov [esi + ARP_entry.Status], ARP_VALID_MAPPING
mov [esi + ARP_entry.TTL], ARP_ENTRY_TTL
 
mov eax, dword [edx + ARP_header.SenderMAC]
mov dword [esi + ARP_entry.MAC], eax
mov cx, word [edx + ARP_header.SenderMAC + 4]
mov word [esi + ARP_entry.MAC + 4], cx
 
jmp .exit
 
;-----------------------
; Handle request packets
 
.maybe_request:
cmp [edx + ARP_header.Opcode], ARP_REQ_OPCODE
jne .exit
 
DEBUGF 1,"ARP_input: its a request\n"
 
mov eax, [IP_LIST + 4*edi]
cmp eax, [edx + ARP_header.TargetIP] ; Is it looking for my IP address?
jne .exit
 
push eax
push edi
 
; OK, it is a request for one of our MAC addresses.
; Build the frame and send it. We can reuse the buffer. (faster then using ARP_create_packet)
 
lea esi, [edx + ARP_header.SenderMAC]
lea edi, [edx + ARP_header.TargetMAC]
movsd ; Move Sender Mac to Dest MAC
movsw ;
movsd ; Move sender IP to Dest IP
 
pop esi
mov esi, [NET_DRV_LIST + 4*esi]
lea esi, [esi + ETH_DEVICE.mac]
lea edi, [edx + ARP_header.SenderMAC]
movsd ; Copy MAC address from in MAC_LIST
movsw ;
pop eax
stosd ; Write our IP
 
mov [edx + ARP_header.Opcode], ARP_REP_OPCODE
 
; Now, Fill in ETHERNET header
 
mov edi, [esp]
lea esi, [edx + ARP_header.TargetMAC]
movsd
movsw
lea esi, [edx + ARP_header.SenderMAC]
movsd
movsw
; mov ax , ETHER_ARP ; It's already there, I'm sure of it!
; stosw
 
DEBUGF 1,"ARP_input: Sending reply\n"
 
call [ebx + NET_DEVICE.transmit]
ret
 
.collision:
inc [ARP_CONFLICTS + 4*edi]
DEBUGF 1,"ARP_input: IP address conflict detected!\n"
 
.exit:
call kernel_free
add esp, 4 ; pop (balance stack)
 
DEBUGF 1,"ARP_input: exiting\n"
ret
 
 
;---------------------------------------------------------------------------
;
; ARP_output_request
;
; IN: ip in eax
; device in edi
; OUT: /
;
;---------------------------------------------------------------------------
align 4
ARP_output_request:
 
push eax ; DestIP
pushd [IP_LIST + edi] ; SenderIP
inc [ARP_PACKETS_TX + edi] ; assume we will succeed
 
DEBUGF 1,"ARP_output_request: ip=%u.%u.%u.%u\n",\
[esp + 4]:1, [esp + 5]:1, [esp + 6]:1, [esp + 7]:1
 
mov ebx, [NET_DRV_LIST + edi] ; device ptr
 
lea eax, [ebx + ETH_DEVICE.mac] ; local device mac
mov edx, ETH_BROADCAST ; broadcast mac
mov ecx, sizeof.ARP_header
mov di, ETHER_ARP
call ETH_output
jz .exit
 
mov ecx, eax
 
mov [edi + ARP_header.HardwareType], 0x0100 ; Ethernet
mov [edi + ARP_header.ProtocolType], 0x0008 ; IP
mov [edi + ARP_header.HardwareSize], 6 ; MAC-addr length
mov [edi + ARP_header.ProtocolSize], 4 ; IP-addr length
mov [edi + ARP_header.Opcode], ARP_REQ_OPCODE ; Request
 
add edi, ARP_header.SenderMAC
 
lea esi, [ebx + ETH_DEVICE.mac] ; SenderMac
movsw ;
movsd ;
pop eax ; SenderIP
stosd ;
 
mov eax, -1 ; DestMac
stosd ;
stosw ;
pop eax ; DestIP
stosd ;
 
DEBUGF 1,"ARP_output_request: device=%x\n", ebx
 
push edx ecx
call [ebx + NET_DEVICE.transmit]
ret
 
.exit:
add esp, 4 + 4
DEBUGF 1,"ARP_output_request: failed\n"
sub eax, eax
ret
 
 
;-----------------------------------------------------------------
;
; ARP_add_entry (or update)
;
; IN: esi = ptr to entry (can easily be made on the stack)
; OUT: eax = entry #, -1 on error
; edi = ptr to newly created entry
;
;----------------------------------------------------------------- ; TODO: use a mutex
align 4
ARP_add_entry:
 
DEBUGF 1,"ARP_add_entry: "
 
mov ecx, [NumARP]
cmp ecx, ARP_TABLE_SIZE ; list full ?
jae .error
 
xor eax, eax
mov edi, ARP_table
mov ecx, [esi + ARP_entry.IP]
.loop:
cmp [edi + ARP_entry.Status], ARP_NO_ENTRY ; is this slot empty?
je .add
 
cmp [edi + ARP_entry.IP], ecx ; if not, check if it doesnt collide
jne .maybe_next
 
cmp [edi + ARP_entry.TTL], ARP_STATIC_ENTRY ; ok, its the same IP, update it if not static
jne .add
 
.maybe_next: ; try the next slot
add edi, sizeof.ARP_entry
inc eax
cmp eax, ARP_TABLE_SIZE
jae .error
jmp .loop
 
.add:
mov ecx, sizeof.ARP_entry/2
rep movsw
inc [NumARP]
sub edi, sizeof.ARP_entry
DEBUGF 1,"entry=%u\n", eax
 
ret
 
.error:
DEBUGF 1,"failed\n"
mov eax, -1
ret
 
 
;-----------------------------------------------------------------
;
; ARP_del_entry
;
; IN: esi = ptr to arp entry
; OUT: /
;
;-----------------------------------------------------------------
align 4
ARP_del_entry:
 
DEBUGF 1,"ARP_del_entry: entry=%x entrys=%u\n", esi, [NumARP]
DEBUGF 1,"ARP_del_entry: IP=%u.%u.%u.%u\n", \
[esi + ARP_entry.IP]:1, [esi + ARP_entry.IP + 1]:1, [esi + ARP_entry.IP + 2]:1, [esi + ARP_entry.IP + 3]:1
 
mov ecx, ARP_table + (ARP_TABLE_SIZE - 1) * sizeof.ARP_entry
sub ecx, esi
shr ecx, 1
 
mov edi, esi
add esi, sizeof.ARP_entry
rep movsw
 
xor eax, eax
mov ecx, sizeof.ARP_entry/2
rep stosw
 
dec [NumARP]
DEBUGF 1,"ARP_del_entry: success\n"
 
ret
 
 
 
 
 
;-----------------------------------------------------------------
;
; ARP_IP_to_MAC
;
; This function translates an IP address to a MAC address
;
; IN: eax = IPv4 address
; edi = device number
; OUT: eax = -1 on error, -2 means request send
; else, ax = first two bytes of mac (high 16 bits of eax will be 0)
; ebx = last four bytes of mac
; edi = unchanged
;
;-----------------------------------------------------------------
align 4
ARP_IP_to_MAC:
 
DEBUGF 1,"ARP_IP_to_MAC: %u.%u", al, ah
rol eax, 16
DEBUGF 1,".%u.%u\n", al, ah
rol eax, 16
 
cmp eax, 0xffffffff
je .broadcast
 
;--------------------------------
; Try to find the IP in ARP_table
 
mov ecx, [NumARP]
test ecx, ecx
jz .not_in_list
mov esi, ARP_table + ARP_entry.IP
.scan_loop:
cmp [esi], eax
je .found_it
add esi, sizeof.ARP_entry
loop .scan_loop
 
.not_in_list:
DEBUGF 1,"ARP_IP_to_MAC: preparing for ARP request\n"
 
;--------------------
; Send an ARP request
 
push eax edi ; save IP for ARP_output_request
 
; Now create the ARP entry
pushw ARP_REQUEST_TTL ; TTL
pushw ARP_AWAITING_RESPONSE ; status
pushd 0 ; mac
pushw 0
pushd eax ; ip
mov esi, esp
call ARP_add_entry
add esp, sizeof.ARP_entry ; clear the entry from stack
 
cmp eax, -1 ; did ARP_add_entry fail?
je .full
 
mov esi, edi
pop edi eax ; IP in eax, device number in edi, for ARP_output_request
 
push esi edi
call ARP_output_request ; And send a request
pop edi esi
 
;-----------------------------------------------
; At this point, we got an ARP entry in the list
.found_it:
cmp [esi + ARP_entry.Status], ARP_VALID_MAPPING ; Does it have a MAC assigned?
je .valid
 
if ARP_BLOCK
 
cmp [esi + ARP_entry.Status], ARP_AWAITING_RESPONSE ; Are we waiting for reply from remote end?
jne .give_up
push esi
mov esi, 10 ; wait 10 ms
call delay_ms
pop esi
jmp .found_it ; now check again
 
else
 
jmp .give_up
 
end if
 
.valid:
DEBUGF 1,"ARP_IP_to_MAC: found MAC\n"
movzx eax, word[esi + ARP_entry.MAC]
mov ebx, dword[esi + ARP_entry.MAC + 2]
ret
 
.full:
DEBUGF 1,"ARP_IP_to_MAC: table is full!\n"
add esp, 8
.give_up:
DEBUGF 1,"ARP_IP_to_MAC: entry has no valid mapping!\n"
mov eax, -1
ret
 
.broadcast:
mov eax, 0x0000ffff
mov ebx, 0xffffffff
ret
 
 
;-----------------------------------------------------------------
;
; ARP_API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT: ?
;
;-----------------------------------------------------------------
align 4
ARP_api:
 
movzx eax, bh
shl eax, 2
 
and ebx, 0xff
cmp ebx, .number
ja .error
jmp dword [.table + 4*ebx]
 
.table:
dd .packets_tx ; 0
dd .packets_rx ; 1
dd .entries ; 2
dd .read ; 3
dd .write ; 4
dd .remove ; 5
dd .send_announce ; 6
dd .conflicts ; 7
.number = ($ - .table) / 4 - 1
 
.error:
mov eax, -1
ret
 
.packets_tx:
mov eax, [ARP_PACKETS_TX + eax]
ret
 
.packets_rx:
mov eax, [ARP_PACKETS_RX + eax]
ret
 
.conflicts:
mov eax, [ARP_CONFLICTS + eax]
ret
 
.entries:
mov eax, [NumARP]
ret
 
.read:
cmp ecx, [NumARP]
jae .error
; edi = pointer to buffer
; ecx = # entry
imul ecx, sizeof.ARP_entry
add ecx, ARP_table
mov esi, ecx
mov ecx, sizeof.ARP_entry/2
rep movsw
 
xor eax, eax
ret
 
.write:
; esi = pointer to buffer
call ARP_add_entry ; out: eax = entry number, -1 on error
ret
 
.remove:
; ecx = # entry
cmp ecx, [NumARP]
jae .error
imul ecx, sizeof.ARP_entry
lea esi, [ARP_table + ecx]
call ARP_del_entry
ret
 
.send_announce:
mov edi, eax
mov eax, [IP_LIST + eax]
call ARP_output_request ; now send a gratuitous ARP
ret
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/network/ethernet.inc
0,0 → 1,233
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ETHERNET.INC ;;
;; ;;
;; Ethernet network layer for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
ETH_FRAME_MINIMUM = 60
 
struct ETH_header
 
DstMAC dp ? ; destination MAC-address
SrcMAC dp ? ; source MAC-address
Type dw ? ; type of the upper-layer protocol
 
ends
 
struct ETH_DEVICE NET_DEVICE
 
mac dp ?
 
ends
 
align 4
iglobal
 
ETH_BROADCAST dp 0xffffffffffff
endg
 
;-----------------------------------------------------------------
;
; ETH_input
;
; This function is called by ethernet drivers,
; It pushes the received ethernet packets onto the eth_in_queue
;
; IN: [esp] = Pointer to buffer
; [esp+4] = size of buffer
; ebx = pointer to eth_device
; OUT: /
;
;-----------------------------------------------------------------
align 4
ETH_input:
mov eax, [esp]
mov ecx, [esp+4]
 
DEBUGF 1,"ETH_input: size=%u\n", ecx
cmp ecx, ETH_FRAME_MINIMUM
jb .dump
sub ecx, sizeof.ETH_header
 
lea edx, [eax + sizeof.ETH_header]
mov ax, [eax + ETH_header.Type]
 
cmp ax, ETHER_IPv4
je IPv4_input
 
cmp ax, ETHER_ARP
je ARP_input
 
cmp ax, ETHER_IPv6
je IPv6_input
 
cmp ax, ETHER_PPP_DISCOVERY
je PPPoE_discovery_input
 
cmp ax, ETHER_PPP_SESSION
je PPPoE_session_input
 
DEBUGF 2,"ETH_input: Unknown packet type=%x\n", ax
 
.dump:
DEBUGF 2,"ETH_input: dumping\n"
call kernel_free
add esp, 4
ret
 
;-----------------------------------------------------------------
;
; ETH_output
;
; IN: eax = pointer to source mac
; ebx = device ptr
; ecx = packet size
; edx = pointer to destination mac
; di = protocol
;
; OUT: edi = 0 on error, pointer to buffer otherwise
; eax = buffer start
; ebx = to device structure
; ecx = unchanged (packet size of embedded data)
; edx = size of complete buffer
;
;-----------------------------------------------------------------
align 4
ETH_output:
 
DEBUGF 1,"ETH_output: size=%u device=%x\n", ecx, ebx
 
cmp ecx, [ebx + NET_DEVICE.mtu]
ja .exit
 
push ecx
push di eax edx
 
add ecx, sizeof.ETH_header
stdcall kernel_alloc, ecx
test eax, eax
jz .out_of_ram
mov edi, eax
 
pop esi
movsd
movsw
pop esi
movsd
movsw
pop ax
stosw
 
lea eax, [edi - sizeof.ETH_header] ; Set eax to buffer start
pop ecx
lea edx, [ecx + sizeof.ETH_header] ; Set edx to complete buffer size
 
cmp edx, ETH_FRAME_MINIMUM
jbe .adjust_size
.done:
DEBUGF 1,"ETH_output: ptr=%x size=%u\n", eax, edx
ret
 
.adjust_size:
mov edx, ETH_FRAME_MINIMUM
test edx, edx ; clear zero flag
jmp .done
 
.out_of_ram:
DEBUGF 2,"ETH_output: Out of ram!\n"
add esp, 4+4+2+4
sub edi, edi
ret
 
.exit:
DEBUGF 2,"ETH_output: Packet too large!\n"
sub edi, edi
ret
 
 
 
;-----------------------------------------------------------------
;
; ETH_API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;-----------------------------------------------------------------
align 4
ETH_api:
 
cmp bh, MAX_NET_DEVICES
ja .error
movzx eax, bh
mov eax, dword [NET_DRV_LIST + 4*eax]
cmp [eax + NET_DEVICE.type], NET_TYPE_ETH
jne .error
 
and ebx, 0xff
cmp ebx, .number
ja .error
jmp dword [.table + 4*ebx]
 
.table:
dd .packets_tx ; 0
dd .packets_rx ; 1
dd .bytes_tx ; 2
dd .bytes_rx ; 3
dd .read_mac ; 4
dd .state ; 5
.number = ($ - .table) / 4 - 1
 
.error:
or eax, -1
ret
 
.packets_tx:
mov eax, [eax + NET_DEVICE.packets_tx]
 
ret
 
.packets_rx:
mov eax, [eax + NET_DEVICE.packets_rx]
ret
 
.bytes_tx:
mov ebx, dword [eax + NET_DEVICE.bytes_tx + 4]
mov eax, dword [eax + NET_DEVICE.bytes_tx]
mov [esp+20+4], ebx ; TODO: fix this ugly code
ret
 
.bytes_rx:
mov ebx, dword [eax + NET_DEVICE.bytes_rx + 4]
mov eax, dword [eax + NET_DEVICE.bytes_rx]
mov [esp+20+4], ebx ; TODO: fix this ugly code
ret
 
 
.read_mac:
movzx ebx, word [eax + ETH_DEVICE.mac]
mov eax, dword [eax + ETH_DEVICE.mac + 2]
mov [esp+20+4], ebx ; TODO: fix this ugly code
ret
 
.state:
mov eax, [eax + NET_DEVICE.state]
ret
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/network/tcp_output.inc
0,0 → 1,621
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Based on the code of 4.4BSD ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
;-----------------------------------------------------------------
;
; TCP_output
;
; IN: eax = socket pointer
;
; OUT: /
;
;-----------------------------------------------------------------
align 4
TCP_output:
 
DEBUGF 1,"TCP_output: socket=%x\n", eax
 
push eax
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
pop eax
 
; We'll detect the length of the data to be transmitted, and flags to be used
; If there is some data, or any critical controls to send (SYN / RST), then transmit
; Otherwise, investigate further
 
mov ebx, [eax + TCP_SOCKET.SND_MAX]
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
jbe .not_idle
 
mov ebx, [eax + TCP_SOCKET.t_idle]
cmp ebx, [eax + TCP_SOCKET.t_rxtcur]
jbe .not_idle
 
; We have been idle for a while and no ACKS are expected to clock out any data we send..
; Slow start to get ack "clock" running again.
 
mov ebx, [eax + TCP_SOCKET.t_maxseg]
mov [eax + TCP_SOCKET.SND_CWND], ebx
 
.not_idle:
.again:
mov [eax + TCP_SOCKET.temp_bits], 0
 
mov ebx, [eax + TCP_SOCKET.SND_NXT] ; calculate offset (71)
sub ebx, [eax + TCP_SOCKET.SND_UNA] ;
 
mov ecx, [eax + TCP_SOCKET.SND_WND] ; determine window
cmp ecx, [eax + TCP_SOCKET.SND_CWND] ;
jb @f ;
mov ecx, [eax + TCP_SOCKET.SND_CWND] ;
@@: ;
 
call TCP_outflags ; flags in dl
 
;------------------------
; data being forced out ?
 
; If in persist timeout with window of 0, send 1 byte.
; Otherwise, if window is small but nonzero, and timer expired,
; we will send what we can and go to transmit state
 
cmp [eax + TCP_SOCKET.t_force], 0
je .no_force
 
DEBUGF 1,"TCP_output: forcing data out\n"
 
test ecx, ecx
jnz .no_zero_window
 
cmp ebx, [eax + STREAM_SOCKET.snd.size]
jae @f
 
and dl, not (TH_FIN)
 
@@:
inc ecx
jmp .no_force
 
.no_zero_window:
mov [eax + TCP_SOCKET.timer_persist], 0
mov [eax + TCP_SOCKET.t_rxtshift], 0
 
.no_force:
 
;--------------------------------
; Calculate how much data to send (106)
 
mov esi, [eax + STREAM_SOCKET.snd.size]
cmp esi, ecx
jb @f
mov esi, ecx
@@:
sub esi, ebx
 
 
;------------------------
; check for window shrink (107)
 
; If FIN has been set, but not ACKed, but we havent been called to retransmit, esi will be -1
; Otherwise, window shrank after we sent into it.
 
jae .not_persist
 
; enter persist state
xor esi, esi
 
; If window shrank to 0
test ecx, ecx
jnz @f
 
; cancel pending retransmit
mov [eax + TCP_SOCKET.timer_retransmission], 0
 
; pull SND_NXT back to (closed) window, We will enter persist state below.
push [eax + TCP_SOCKET.SND_UNA]
pop [eax + TCP_SOCKET.SND_NXT]
@@:
 
; If window didn't close completely, just wait for an ACK
 
.not_persist:
 
;---------------------------
; Send one segment at a time (124)
 
cmp esi, [eax + TCP_SOCKET.t_maxseg]
jbe @f
 
mov esi, [eax + TCP_SOCKET.t_maxseg]
or [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT
@@:
 
;--------------------------------------------
; Turn of FIN flag if send buffer not emptied (128)
 
mov edi, [eax + TCP_SOCKET.SND_NXT]
add edi, esi
sub edi, [eax + TCP_SOCKET.SND_UNA]
cmp edi, [eax + STREAM_SOCKET.snd.size]
jae @f
and dl, not (TH_FIN)
 
@@:
 
;-------------------------------
; calculate window advertisement (130)
 
mov ecx, SOCKET_MAXDATA
sub ecx, [eax + STREAM_SOCKET.rcv.size]
 
;------------------------------
; Sender silly window avoidance (131)
 
test esi, esi
jz .len_zero
 
cmp esi, [eax + TCP_SOCKET.t_maxseg]
je TCP_send
 
add ebx, esi ; offset + length
cmp ebx, [eax + STREAM_SOCKET.snd.size]
jb @f
 
test [eax + TCP_SOCKET.t_flags], TF_NODELAY
jnz TCP_send
 
mov ebx, [eax + TCP_SOCKET.SND_MAX]
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
je TCP_send
@@:
 
test [eax + TCP_SOCKET.t_force], -1 ;;;
jnz TCP_send
 
mov ebx, [eax + TCP_SOCKET.max_sndwnd]
shr ebx, 1
cmp esi, ebx
jae TCP_send
 
mov ebx, [eax + TCP_SOCKET.SND_NXT]
cmp ebx, [eax + TCP_SOCKET.SND_MAX]
jb TCP_send
 
.len_zero:
 
;----------------------------------------
; Check if a window update should be sent (154)
 
DEBUGF 1,"TCP_output: window=%d\n", ecx
 
; Compare available window to amount of window known to peer (as advertised window less next expected input)
; If the difference is at least two max size segments, or at least 50% of the maximum possible window,
; Then we want to send a window update to the peer.
 
test ecx, ecx
jz .no_window
 
push ecx
mov cl, [eax + TCP_SOCKET.RCV_SCALE]
mov ebx, TCP_max_win
shl ebx, cl
pop ecx
cmp ebx, ecx
jb @f
mov ebx, ecx
@@:
sub ebx, [eax + TCP_SOCKET.RCV_ADV]
add ebx, [eax + TCP_SOCKET.RCV_NXT]
 
mov edi, [eax + TCP_SOCKET.t_maxseg]
shl edi, 1
 
; cmp ebx, edi
; jae TCP_send
 
; cmp ebx, [eax + TCP_SOCKET.] ;;; TODO: check with receive buffer high water mark
; jae TCP_send
 
.no_window:
 
;--------------------------
; Should a segment be sent? (174)
 
DEBUGF 1,"TCP_output: 174\n"
 
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW ; we need to ACK
jnz TCP_send
 
test dl, TH_SYN + TH_RST ; we need to send a SYN or RST
jnz TCP_send
 
mov ebx, [eax + TCP_SOCKET.SND_UP] ; when urgent pointer is beyond start of send bufer
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
ja TCP_send
 
test dl, TH_FIN
jz .enter_persist ; no reason to send, enter persist state
 
; FIN was set, only send if not already sent, or on retransmit
 
test [eax + TCP_SOCKET.t_flags], TF_SENTFIN
jz TCP_send
 
mov ebx, [eax + TCP_SOCKET.SND_NXT]
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
je TCP_send
 
;--------------------
; Enter persist state (191)
 
.enter_persist:
 
cmp [eax + STREAM_SOCKET.snd.size], 0 ; Data ready to send?
jne @f
cmp [eax + TCP_SOCKET.timer_retransmission], 0
jne @f
cmp [eax + TCP_SOCKET.timer_persist], 0 ; Persist timer already expired?
jne @f
 
DEBUGF 1,"TCP_output: Entering persist state\n"
 
mov [eax + TCP_SOCKET.t_rxtshift], 0
call TCP_set_persist
@@:
 
;----------------------------
; No reason to send a segment (219)
 
DEBUGF 1,"TCP_output: No reason to send a segment\n"
 
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
popa
 
; Fixme: returnvalue?
 
ret
 
 
 
 
 
 
 
 
 
;-----------------------------------------------
;
; Send a segment (222)
;
; eax = socket pointer
; esi = data len
; dl = flags
;
;-----------------------------------------------
align 4
TCP_send:
 
DEBUGF 1,"TCP_send: socket=%x length=%u flags=%x\n", eax, esi, dl
 
push eax ; save socket ptr
push esi ; and data length too
mov edi, sizeof.TCP_header ; edi will contain headersize
 
;------------------------------------
; Send options with first SYN segment
 
test dl, TH_SYN
jz .options_done
 
push [eax + TCP_SOCKET.ISS]
pop [eax + TCP_SOCKET.SND_NXT]
 
test [eax + TCP_SOCKET.t_flags], TF_NOOPT
jnz .options_done
 
mov ecx, 1460 ;;;; FIXME: use routing blablabla to determine MSS
or ecx, TCP_OPT_MAXSEG shl 24 + 4 shl 16
bswap ecx
push ecx
add di, 4
 
DEBUGF 1,"TCP_send: added maxseg option\n"
 
test [eax + TCP_SOCKET.t_flags], TF_REQ_SCALE
jz .no_scale
 
test dl, TH_ACK
jz .scale_opt
 
test [eax + TCP_SOCKET.t_flags], TF_RCVD_SCALE
jz .no_scale
 
.scale_opt:
mov cl, [eax + TCP_SOCKET.request_r_scale]
mov ch, TCP_OPT_NOP
pushw cx
pushw TCP_OPT_WINDOW + 3 shl 8
add di, 4
 
DEBUGF 1,"TCP_send: added scale option\n"
 
.no_scale:
.no_syn:
 
;------------------------------------
; Make the timestamp option if needed
 
test [eax + TCP_SOCKET.t_flags], TF_REQ_TSTMP
jz .no_timestamp
 
test dl, TH_RST
jnz .no_timestamp
 
test dl, TH_ACK
jz .timestamp
 
test [eax + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
jz .no_timestamp
 
.timestamp:
pushd 0
pushd [timer_ticks]
pushd TCP_OPT_NOP + TCP_OPT_NOP shl 8 + TCP_OPT_TIMESTAMP shl 16 + 10 shl 24
add di, 12
 
DEBUGF 1,"TCP_send: added timestamp\n"
 
.no_timestamp:
 
; <Add additional options here>
 
.options_done:
 
; eax = socket ptr
; edx = flags
; edi = header size
; esi = data len
 
;---------------------------------------------
; check if we dont exceed the max segment size (270)
 
add esi, edi ; total TCP segment size
cmp esi, [eax + TCP_SOCKET.t_maxseg]
jbe .no_overflow
 
mov esi, [eax + TCP_SOCKET.t_maxseg]
or [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT
.no_overflow:
 
;-----------------------------------------------------------------
; Start by pushing all TCP header values in reverse order on stack
; (essentially, creating the tcp header on the stack!)
 
pushw 0 ; .UrgentPointer dw ?
pushw 0 ; .Checksum dw ?
pushw 0x00a0 ; .Window dw ? ;;;;;;; FIXME (370)
shl edi, 2 ; .DataOffset db ? only 4 left-most bits
shl dx, 8
or dx, di ; .Flags db ?
pushw dx
shr edi, 2 ; .DataOffset db ?
 
push [eax + TCP_SOCKET.RCV_NXT] ; .AckNumber dd ?
ntohd [esp]
 
push [eax + TCP_SOCKET.SND_NXT] ; .SequenceNumber dd ?
ntohd [esp]
 
push [eax + TCP_SOCKET.RemotePort] ; .DestinationPort dw ?
push [eax + TCP_SOCKET.LocalPort] ; .SourcePort dw ?
 
push edi ; header size
 
;---------------------
; Create the IP packet
 
mov ecx, esi
 
mov ebx, [eax + SOCKET.device]
mov edx, [eax + IP_SOCKET.LocalIP] ; source ip
mov eax, [eax + IP_SOCKET.RemoteIP] ; dest ip
mov di, IP_PROTO_TCP shl 8 + 128
call IPv4_output
jz .ip_error
 
;-----------------------------------------
; Move TCP header from stack to TCP packet
 
push ecx
mov ecx, [esp + 4]
lea esi, [esp + 8]
shr ecx, 2 ; count is in bytes, we will work with dwords
rep movsd
pop ecx ; full TCP packet size
 
pop esi ; headersize
add esp, esi ; remove it from stack
 
push edx ; packet size for send proc
push eax ; packet ptr for send proc
 
mov edx, edi ; begin of data
sub edx, esi ; begin of packet (edi = begin of data)
push ecx
sub ecx, esi ; data size
 
;--------------
; Copy the data
 
; eax = ptr to ring struct
; ecx = buffer size
; edi = ptr to buffer
 
mov eax, [esp + 16] ; get socket ptr
 
push edx
push [eax + TCP_SOCKET.SND_NXT] ; we'll need this for timing the transmission
test ecx, ecx
jz .nodata
mov edx, [eax + TCP_SOCKET.SND_NXT]
add [eax + TCP_SOCKET.SND_NXT], ecx ; update sequence number <<< CHECKME
sub edx, [eax + TCP_SOCKET.SND_UNA] ; offset
add eax, STREAM_SOCKET.snd
call SOCKET_ring_read
.nodata:
pop edi
pop esi ; begin of data
pop ecx ; full packet size
mov eax, [esp + 12] ; socket ptr
 
;----------------------------------
; initialize retransmit timer (400)
 
;TODO: check t_force and persist
 
test [esi + TCP_header.Flags], TH_SYN + TH_FIN ; syn and fin take a sequence number
jz @f
inc [eax + TCP_SOCKET.SND_NXT]
test [esi + TCP_header.Flags], TH_FIN
jz @f
or [eax + TCP_SOCKET.t_flags], TF_SENTFIN ; if we sent a fin, set the sentfin flag
@@:
 
mov edx, [eax + TCP_SOCKET.SND_NXT]
cmp edx, [eax + TCP_SOCKET.SND_MAX] ; is this a retransmission?
jbe @f
mov [eax + TCP_SOCKET.SND_MAX], edx ; [eax + TCP_SOCKET.SND_NXT] from before we updated it
 
cmp [eax + TCP_SOCKET.t_rtt], 0 ; are we currently timing anything?
je @f
mov [eax + TCP_SOCKET.t_rtt], 1 ; nope, start transmission timer
mov [eax + TCP_SOCKET.t_rtseq], edi
;TODO: update stats
@@:
 
; set retransmission timer if not already set, and not doing an ACK or keepalive probe
 
cmp [eax + TCP_SOCKET.timer_retransmission], 0 ;;;; FIXME
ja .retransmit_set
 
cmp edx, [eax + TCP_SOCKET.SND_UNA] ; edx is still [eax + TCP_SOCKET.SND_NXT]
je .retransmit_set
 
mov edx, [eax + TCP_SOCKET.t_rxtcur]
mov [eax + TCP_SOCKET.timer_retransmission], edx
 
cmp [eax + TCP_SOCKET.timer_persist], 0
jne .retransmit_set
mov [eax + TCP_SOCKET.timer_persist], 0
mov [eax + TCP_SOCKET.t_rxtshift], 0
 
.retransmit_set:
 
;--------------------
; Create the checksum
 
TCP_checksum (eax + IP_SOCKET.LocalIP), (eax + IP_SOCKET.RemoteIP)
mov [esi + TCP_header.Checksum], dx
 
;----------------
; Send the packet
 
DEBUGF 1,"TCP_send: Sending with device %x\n", ebx
call [ebx + NET_DEVICE.transmit]
jnz .send_error
 
;---------------
; Ok, data sent!
 
pop ecx
pop eax
 
inc [TCP_segments_tx] ; FIXME: correct interface?
 
; update advertised receive window
test ecx, ecx
jz @f
add ecx, [eax + TCP_SOCKET.RCV_NXT]
cmp ecx, [eax + TCP_SOCKET.RCV_ADV]
jbe @f
mov [eax + TCP_SOCKET.RCV_ADV], ecx
@@:
 
; update last ack sent
push [eax + TCP_SOCKET.RCV_NXT]
pop [eax + TCP_SOCKET.last_ack_sent]
 
; and flags
and [eax + TCP_SOCKET.t_flags], not (TF_ACKNOW + TF_DELACK)
 
;--------------
; unlock socket
 
push eax
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
pop eax
 
;-----------------------------
; Check if we need more output
 
test [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT
jnz TCP_output.again
 
DEBUGF 1,"TCP_send: success!\n"
 
xor eax, eax
ret
 
 
.ip_error:
pop ecx
add esp, ecx
add esp, 4
pop eax
 
mov [eax + TCP_SOCKET.timer_retransmission], TCP_time_re_min
 
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
 
DEBUGF 1,"TCP_send: IP error\n"
 
or eax, -1
ret
 
 
.send_error:
add esp, 8
 
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
 
DEBUGF 1,"TCP_send: sending failed\n"
 
or eax, -2
ret
 
 
 
 
 
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/network/tcp_usreq.inc
0,0 → 1,102
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Based on the code of 4.4BSD ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
;-------------------------
;
; TCP_usrclose
;
; Move connection to next state, based on process close.
;
; IN: eax = socket ptr
;
;-------------------------
align 4
TCP_usrclosed:
 
DEBUGF 1,"TCP_usrclosed: %x\n", eax
 
push ebx
mov ebx, [eax + TCP_SOCKET.t_state]
mov ebx, dword [.switch + ebx*4]
jmp ebx
 
.switch:
 
dd .close ; TCPS_CLOSED
dd .close ; TCPS_LISTEN
dd .close ; TCPS_SYN_SENT
dd .wait1 ; TCPS_SYN_RECEIVED
dd .wait1 ; TCPS_ESTABLISHED
dd .last_ack ; TCPS_CLOSE_WAIT
dd .ret ; TCPS_FIN_WAIT_1
dd .ret ; TCPS_CLOSING
dd .ret ; TCPS_LAST_ACK
dd .disc ; TCPS_FIN_WAIT_2
dd .disc ; TCPS_TIMED_WAIT
 
 
.close:
mov [eax + TCP_SOCKET.t_state], TCPS_CLOSED
call TCP_close
pop ebx
ret
 
.wait1:
mov [eax + TCP_SOCKET.t_state], TCPS_FIN_WAIT_1
; TODO: set timer?
pop ebx
ret
 
.last_ack:
mov [eax + TCP_SOCKET.t_state], TCPS_LAST_ACK
pop ebx
ret
 
.disc:
call SOCKET_is_disconnected
; TODO: set timer?
.ret:
pop ebx
ret
 
 
 
 
;-------------------------
;
; TCP_disconnect
;
; IN: eax = socket ptr
; OUT: eax = socket ptr
;
;-------------------------
align 4
TCP_disconnect:
 
DEBUGF 1,"TCP_disconnect: %x\n", eax
 
cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
jb TCP_close
 
 
; TODO: implement LINGER ?
 
call SOCKET_is_disconnecting
call TCP_usrclosed
call TCP_output
 
ret
/kernel/branches/net/network/IPv6.inc
0,0 → 1,298
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2012-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; IPv6.INC ;;
;; ;;
;; Part of the tcp/ip network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
struct IPv6_header
 
VersionTrafficFlow dd ? ; Version[0-3], Traffic class[4-11], Flow Label [12-31]
PayloadLength dw ? ; 16 bits, unsigned length of payload (extension headers are part of this)
NextHeader db ? ; Values are same as in IPv4 'Protocol' field
HopLimit db ? ; Decremented by every node, packet is discarded when it reaches 0
SourceAddress rd 4 ; 128-bit addresses
DestinationAddress rd 4 ;
Payload rb 0
 
ends
 
 
align 4
uglobal
 
IPv6:
.addresses rd 4*MAX_NET_DEVICES
.subnet rd 4*MAX_NET_DEVICES
.dns rd 4*MAX_NET_DEVICES
.gateway rd 4*MAX_NET_DEVICES
 
.packets_tx rd MAX_NET_DEVICES
.packets_rx rd MAX_NET_DEVICES
 
endg
 
 
;-----------------------------------------------------------------
;
; IPv6_init
;
; This function resets all IP variables
;
;-----------------------------------------------------------------
macro IPv6_init {
 
xor eax, eax
mov edi, IPv6
mov ecx, (4*4*4+2*4)MAX_IP
rep stosd
 
}
 
 
 
;-----------------------------------------------------------------
;
; IPv6_input:
;
; Will check if IPv6 Packet isnt damaged
; and call appropriate handler. (TCP/UDP/ICMP/..)
;
; It will also re-construct fragmented packets
;
; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
; pointer to device struct in ebx
; pointer to IPv6 header in edx
; size of IPv6 packet in ecx
; OUT: /
;
;-----------------------------------------------------------------
align 4
IPv6_input:
 
DEBUGF 2,"IPv6_input from: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\
[edx + IPv6_header.SourceAddress + 0]:2,[edx + IPv6_header.SourceAddress + 1]:2,\
[edx + IPv6_header.SourceAddress + 2]:2,[edx + IPv6_header.SourceAddress + 3]:2,\
[edx + IPv6_header.SourceAddress + 4]:2,[edx + IPv6_header.SourceAddress + 5]:2,\
[edx + IPv6_header.SourceAddress + 6]:2,[edx + IPv6_header.SourceAddress + 7]:2,\
[edx + IPv6_header.SourceAddress + 8]:2,[edx + IPv6_header.SourceAddress + 9]:2,\
[edx + IPv6_header.SourceAddress + 10]:2,[edx + IPv6_header.SourceAddress + 11]:2,\
[edx + IPv6_header.SourceAddress + 12]:2,[edx + IPv6_header.SourceAddress + 13]:2,\
[edx + IPv6_header.SourceAddress + 14]:2,[edx + IPv6_header.SourceAddress + 15]:2
 
DEBUGF 1,"IPv6_input to: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\
[edx + IPv6_header.DestinationAddress + 0]:2,[edx + IPv6_header.DestinationAddress + 1]:2,\
[edx + IPv6_header.DestinationAddress + 2]:2,[edx + IPv6_header.DestinationAddress + 3]:2,\
[edx + IPv6_header.DestinationAddress + 4]:2,[edx + IPv6_header.DestinationAddress + 5]:2,\
[edx + IPv6_header.DestinationAddress + 6]:2,[edx + IPv6_header.DestinationAddress + 7]:2,\
[edx + IPv6_header.DestinationAddress + 8]:2,[edx + IPv6_header.DestinationAddress + 9]:2,\
[edx + IPv6_header.DestinationAddress + 10]:2,[edx + IPv6_header.DestinationAddress + 11]:2,\
[edx + IPv6_header.DestinationAddress + 12]:2,[edx + IPv6_header.DestinationAddress + 13]:2,\
[edx + IPv6_header.DestinationAddress + 14]:2,[edx + IPv6_header.DestinationAddress + 15]:2
 
sub ecx, sizeof.IPv6_header
jb .dump
 
cmp cx, [edx + IPv6_header.PayloadLength]
jb .dump
 
;-------------------------------------------------------------------
; No, it's just a regular IP packet, pass it to the higher protocols
 
.handle_it:
movzx ecx, [edx + IPv6_header.PayloadLength]
lea edi, [edx + IPv6_header.SourceAddress] ; make edi ptr to source and dest IPv6 address
lea esi, [edx + IPv6_header.Payload] ; make esi ptr to data
mov al, [edx + IPv6_header.NextHeader]
 
.scan:
cmp al, 59 ; no next
je .dump
 
cmp al, 0
je .hop_by_hop
 
cmp al, 43
je .routing
 
cmp al, 44
je .fragment
 
cmp al, 60
je .dest_opts
 
; cmp al, IP_PROTO_TCP
; je TCP_input
 
; cmp al, IP_PROTO_UDP
; je UDP_input
 
; cmp al, 58
; je ICMP6_input
 
DEBUGF 2,"IPv6_input - unknown protocol: %u\n", al
 
.dump:
DEBUGF 1,"IPv6_input - dumping\n"
call kernel_free
add esp, 4
 
ret
 
.dump_options:
add esp, 2+4+4
jmp .dump
 
.nextheader:
pop esi
pop ecx
pop ax
jmp .scan
 
;-------------------------
; Hop-by-Hop
 
.hop_by_hop:
DEBUGF 1,"IPv6_input - hop by hop\n"
pushw [esi] ; 8 bit identifier for option type
movzx eax, byte[esi + 1] ; Hdr Ext Len
inc eax ; first 8 octets not counted
shl eax, 3 ; * 8
sub ecx, eax
push ecx
add eax, esi
push eax
inc esi
inc esi
 
mov al, [esi]
 
cmp al, 0
je .pad_1
 
cmp al, 1
je .pad_n
 
; TODO: check with other known options
 
; unknown option.. discard packet or not?
; check highest two bits
test al, 0xc0 ; discard packet
jnz .dump_options
 
.pad_n:
movzx eax, byte[esi + 1]
DEBUGF 1,"IPv6_input - pad %u\n", eax
inc esi
inc esi
add esi, eax
sub ecx, eax
jmp .hop_by_hop
 
.pad_1:
DEBUGF 1,"IPv6_input - pad 1\n"
inc esi
dec ecx
jmp .hop_by_hop
 
 
 
.dest_opts:
DEBUGF 1,"IPv6_input - dest opts\n"
jmp .nextheader
 
.routing:
DEBUGF 1,"IPv6_input - routing\n"
pushw [esi] ; 8 bit identifier for option type
movzx eax, byte[esi + 1] ; Hdr Ext Len
inc eax ; first 8 octets not counted
shl eax, 3 ; * 8
sub ecx, eax
push ecx
add eax, esi
push eax
inc esi
inc esi
 
cmp al, 0
je .pad_1
 
cmp al, 1
je .pad_n
 
mov al, [esi] ; routing type
 
jmp .nextheader
 
.fragment:
DEBUGF 1,"IPv6_input - fragment\n"
 
jmp .nextheader
 
 
 
 
 
 
;---------------------------------------------------------------------------
;
; IPv6_API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;---------------------------------------------------------------------------
align 4
IPv6_api:
 
movzx eax, bh
shl eax, 2
 
and ebx, 0x000000ff
cmp ebx, .number
ja .error
jmp dword [.table + 4*ebx]
 
.table:
dd .packets_tx ; 0
dd .packets_rx ; 1
; dd .read_ip ; 2
; dd .write_ip ; 3
; dd .read_dns ; 4
; dd .write_dns ; 5
; dd .read_subnet ; 6
; dd .write_subnet ; 7
; dd .read_gateway ; 8
; dd .write_gateway ; 9
.number = ($ - .table) / 4 - 1
 
.error:
mov eax, -1
ret
 
.packets_tx:
mov eax, [IPv6.packets_tx + eax]
ret
 
.packets_rx:
mov eax, [IPv6.packets_rx + eax]
ret
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/network/loopback.inc
0,0 → 1,126
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; loopback.inc ;;
;; ;;
;; LoopBack device for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 2891 $
 
iglobal
 
LOOPBACK_DEVICE:
.type dd NET_TYPE_LOOPBACK
.mtu dd 4096
.name dd .namestr
 
.unload dd .dummy_fn
.reset dd .dummy_fn
.transmit dd LOOP_input
 
.bytes_tx dq 0
.bytes_rx dq 0
.packets_tx dd 0
.packets_rx dd 0
 
.namestr db 'loopback', 0
 
.dummy_fn:
ret
 
endg
 
;-----------------------------------------------------------------
;
; LOOP_input
;
; IN: [esp+4] = Pointer to buffer
; [esp+8] = size of buffer
;
; OUT: /
;
;-----------------------------------------------------------------
align 4
LOOP_input:
pop ebx
pop eax
pop ecx
 
push ebx
push ecx
push eax
 
DEBUGF 1,"LOOP_input: size=%u\n", ecx
lea edx, [eax + 2]
mov ax, word[eax]
mov ebx, LOOPBACK_DEVICE
 
cmp ax, ETHER_IPv4
je IPv4_input
 
DEBUGF 2,"LOOP_input: Unknown packet type=%x\n", ax
 
.dump:
DEBUGF 2,"LOOP_input: dumping\n"
call kernel_free
add esp, 4
ret
 
;-----------------------------------------------------------------
;
; LOOP_output
;
; IN:
; ecx = packet size
; di = protocol
;
; OUT: edi = 0 on error, pointer to buffer otherwise
; eax = buffer start
; ebx = to device structure
; ecx = unchanged (packet size of embedded data)
; edx = size of complete buffer
;
;-----------------------------------------------------------------
align 4
LOOP_output:
 
DEBUGF 1,"LOOP_output\n"
 
push ecx
push di
 
add ecx, 2
cmp ecx, [LOOPBACK_DEVICE.mtu]
ja .out_of_ram
stdcall kernel_alloc, ecx
test eax, eax
jz .out_of_ram
mov edi, eax
pop ax
stosw
 
lea eax, [edi - 2] ; Set eax to buffer start
pop ecx
lea edx, [ecx + 2] ; Set edx to complete buffer size
mov ebx, LOOPBACK_DEVICE
 
.done:
DEBUGF 2,"LOOP_output: ptr=%x size=%u\n", eax, edx
ret
 
.out_of_ram:
DEBUGF 2,"LOOP_output: failed\n"
add esp, 2+4
sub edi, edi
ret
 
 
/kernel/branches/net/network/tcp_timer.inc
0,0 → 1,168
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Based on the code of 4.4BSD ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
;----------------------
; 160 ms timer
;----------------------
macro TCP_timer_160ms {
 
local .loop
local .exit
 
mov ebx, net_sockets
.loop:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .exit
 
cmp [ebx + SOCKET.Domain], AF_INET4
jne .loop
 
cmp [ebx + SOCKET.Protocol], IP_PROTO_TCP
jne .loop
 
test [ebx + TCP_SOCKET.t_flags], TF_DELACK
jz .loop
and [ebx + TCP_SOCKET.t_flags], not (TF_DELACK)
 
push ebx
mov cl, TH_ACK
call TCP_respond
; and [ebx + TCP_SOCKET.t_flags], TF_ACKNOW ;;
; mov eax, ebx ;;
; call TCP_output ;;
pop ebx
 
jmp .loop
 
.exit:
 
}
 
 
;----------------------
; 640 ms timer
;----------------------
macro TCP_timer_640ms {
 
local .loop
local .exit
 
; Update TCP sequence number
 
add [TCP_sequence_num], 64000
 
; scan through all the active TCP sockets, decrementing ALL timers
; timers do not have the chance to wrap because the keepalive timer will kill the socket when it expires
 
mov eax, net_sockets
.loop:
mov eax, [eax + SOCKET.NextPtr]
.check_only:
or eax, eax
jz .exit
 
cmp [eax + SOCKET.Domain], AF_INET4
jne .loop
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
jne .loop
 
inc [eax + TCP_SOCKET.t_idle]
dec [eax + TCP_SOCKET.timer_retransmission]
jnz .check_more2
 
DEBUGF 1,"socket %x: Retransmission timer expired\n", eax
 
push eax
call TCP_output
pop eax
 
.check_more2:
dec [eax + TCP_SOCKET.timer_keepalive]
jnz .check_more3
 
DEBUGF 1,"socket %x: Keepalive expired\n", eax
 
cmp [eax + TCP_SOCKET.state], TCPS_ESTABLISHED
ja .dont_kill
 
push eax
call TCP_disconnect
pop eax
jmp .loop
 
.dont_kill:
test [eax + SOCKET.options], SO_KEEPALIVE
jz .reset_keepalive
 
push eax
mov ebx, eax
xor cl, cl
call TCP_respond ; send keepalive
pop eax
mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
jmp .check_more3
 
.reset_keepalive:
mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_idle
 
.check_more3:
dec [eax + TCP_SOCKET.timer_timed_wait]
jnz .check_more5
 
DEBUGF 1,"socket %x: 2MSL timer expired\n", eax
 
.check_more5:
dec [eax + TCP_SOCKET.timer_persist]
jnz .loop
 
DEBUGF 1,"socket %x: persist timer expired\n", eax
 
call TCP_set_persist
mov [eax + TCP_SOCKET.t_force], 1
push eax
call TCP_output
pop eax
mov [eax + TCP_SOCKET.t_force], 0
 
jmp .loop
.exit:
 
}
 
 
 
; eax = socket
 
TCP_cancel_timers:
 
push eax edi
 
lea edi, [eax + TCP_SOCKET.timer_retransmission]
xor eax, eax
stosd
stosd
stosd
stosd
stosd
 
pop edi eax
 
 
ret
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/network/udp.inc
0,0 → 1,325
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; UDP.INC ;;
;; ;;
;; Part of the tcp/ip network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
struct UDP_header
 
SourcePort dw ?
DestinationPort dw ?
Length dw ? ; Length of (UDP Header + Data)
Checksum dw ?
 
ends
 
 
align 4
uglobal
UDP_PACKETS_TX rd MAX_NET_DEVICES
UDP_PACKETS_RX rd MAX_NET_DEVICES
endg
 
 
;-----------------------------------------------------------------
;
; UDP_init
;
; This function resets all UDP variables
;
;-----------------------------------------------------------------
macro UDP_init {
 
xor eax, eax
mov edi, UDP_PACKETS_TX
mov ecx, 2*MAX_NET_DEVICES
rep stosd
}
 
 
macro UDP_checksum IP1, IP2 { ; esi = ptr to udp packet, ecx = packet size, destroys: ecx, edx
 
; Pseudoheader
mov edx, IP_PROTO_UDP
 
add dl, [IP1+1]
adc dh, [IP1+0]
adc dl, [IP1+3]
adc dh, [IP1+2]
 
adc dl, [IP2+1]
adc dh, [IP2+0]
adc dl, [IP2+3]
adc dh, [IP2+2]
 
adc dl, cl ; byte[esi+UDP_header.Length+1]
adc dh, ch ; byte[esi+UDP_header.Length+0]
 
; Done with pseudoheader, now do real header
adc dl, byte[esi+UDP_header.SourcePort+1]
adc dh, byte[esi+UDP_header.SourcePort+0]
 
adc dl, byte[esi+UDP_header.DestinationPort+1]
adc dh, byte[esi+UDP_header.DestinationPort+0]
 
adc dl, byte[esi+UDP_header.Length+1]
adc dh, byte[esi+UDP_header.Length+0]
 
adc edx, 0
 
; Done with header, now do data
push esi
movzx ecx, [esi+UDP_header.Length]
rol cx , 8
sub cx , sizeof.UDP_header
add esi, sizeof.UDP_header
 
call checksum_1
call checksum_2
pop esi
 
add [esi+UDP_header.Checksum], dx ; this final instruction will set or clear ZF :)
 
}
 
 
;-----------------------------------------------------------------
;
; UDP_input:
;
; Called by IPv4_input,
; this procedure will inject the udp data diagrams in the application sockets.
;
; IN: [esp] = Pointer to buffer
; [esp+4] = size of buffer
; ebx = ptr to device struct
; ecx = UDP Packet size
; esi = ptr to UDP header
; edi = ptr to ipv4 source and dest address
;
; OUT: /
;
;-----------------------------------------------------------------
align 4
UDP_input:
 
DEBUGF 1,"UDP_input: size=%u\n", ecx
 
; First validate, checksum
 
neg [esi + UDP_header.Checksum] ; substract checksum from 0
jz .no_checksum ; if checksum is zero, it is considered valid
 
; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct
 
UDP_checksum (edi), (edi+4)
jnz .checksum_mismatch
 
.no_checksum:
DEBUGF 1,"UDP_input: checksum ok\n"
 
; Convert length to little endian
 
rol [esi + UDP_header.Length], 8
 
; Look for a socket where
; IP Packet UDP Destination Port = local Port
; IP Packet SA = Remote IP
 
mov cx, [esi + UDP_header.SourcePort]
mov dx, [esi + UDP_header.DestinationPort]
mov edi, [edi + 4] ; ipv4 source address
mov eax, net_sockets
 
.next_socket:
mov eax, [eax + SOCKET.NextPtr]
or eax, eax
jz .dump
 
cmp [eax + SOCKET.Domain], AF_INET4
jne .next_socket
 
cmp [eax + SOCKET.Protocol], IP_PROTO_UDP
jne .next_socket
 
cmp [eax + UDP_SOCKET.LocalPort], dx
jne .next_socket
 
DEBUGF 1,"UDP_input: socket=%x\n", eax
 
;;; TODO: when packet is processed, check more sockets!
 
; cmp [eax + IP_SOCKET.RemoteIP], 0xffffffff
; je @f
; cmp [eax + IP_SOCKET.RemoteIP], edi
; jne .next_socket
; @@:
;
; FIXME: UDP should check remote IP, but not under all circumstances!
 
cmp [eax + UDP_SOCKET.firstpacket], 0
je .updateport
 
cmp [eax + UDP_SOCKET.RemotePort], cx
jne .dump
 
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
 
.updatesock:
inc [UDP_PACKETS_RX] ; Fixme: correct interface?
 
movzx ecx, [esi + UDP_header.Length]
sub ecx, sizeof.UDP_header
add esi, sizeof.UDP_header
 
jmp SOCKET_input
 
.updateport:
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
 
DEBUGF 1,"UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf
mov [eax + UDP_SOCKET.RemotePort], cx
inc [eax + UDP_SOCKET.firstpacket]
 
jmp .updatesock
 
 
.checksum_mismatch:
DEBUGF 2,"UDP_input: checksum mismatch\n"
 
.dump:
call kernel_free
add esp, 4 ; pop (balance stack)
DEBUGF 2,"UDP_input: dumping\n"
 
ret
 
 
 
 
;-----------------------------------------------------------------
;
; UDP_output
;
; IN: eax = socket pointer
; ecx = number of bytes to send
; esi = pointer to data
;
;-----------------------------------------------------------------
 
align 4
UDP_output:
 
DEBUGF 1,"UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi
 
mov dx, [eax + UDP_SOCKET.RemotePort]
DEBUGF 1,"UDP_output: remote port=%x, ", dx ; FIXME: find a way to print big endian values with debugf
rol edx, 16
mov dx, [eax + UDP_SOCKET.LocalPort]
DEBUGF 1,"local port=%x\n", dx
 
sub esp, 8 ; Data ptr and data size will be placed here
push edx esi
mov ebx, [eax + SOCKET.device]
mov edx, [eax + IP_SOCKET.LocalIP]
mov eax, [eax + IP_SOCKET.RemoteIP]
mov di, IP_PROTO_UDP shl 8 + 128
add ecx, sizeof.UDP_header
call IPv4_output
jz .fail
mov [esp + 8], eax ; pointer to buffer start
mov [esp + 8 + 4], edx ; buffer size
 
mov [edi + UDP_header.Length], cx
rol [edi + UDP_header.Length], 8
 
pop esi
push edi ecx
sub ecx, sizeof.UDP_header
add edi, sizeof.UDP_header
shr ecx, 2
rep movsd
mov ecx, [esp]
and ecx, 3
rep movsb
pop ecx edi
 
pop dword [edi + UDP_header.SourcePort]
 
; Checksum
mov esi, edi
mov [edi + UDP_header.Checksum], 0
UDP_checksum (edi-4), (edi-8) ; FIXME: IPv4 packet could have options..
 
DEBUGF 1,"UDP_output: sending with device %x\n", ebx
call [ebx + NET_DEVICE.transmit]
test eax, eax
jnz @f
inc [UDP_PACKETS_TX] ; FIXME: correct device?
@@:
 
ret
 
.fail:
DEBUGF 1,"UDP_output: failed\n"
add esp, 4+4+8
or eax, -1
ret
 
 
 
;---------------------------------------------------------------------------
;
; UDP_API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;---------------------------------------------------------------------------
 
align 4
UDP_api:
 
movzx eax, bh
shl eax, 2
 
test bl, bl
jz .packets_tx ; 0
dec bl
jz .packets_rx ; 1
 
.error:
mov eax, -1
ret
 
.packets_tx:
mov eax, [UDP_PACKETS_TX + eax]
ret
 
.packets_rx:
mov eax, [UDP_PACKETS_RX + eax]
ret
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/network/PPPoE.inc
0,0 → 1,340
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; PPPoE.INC ;;
;; ;;
;; Part of the tcp/ip network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
struct PPPoE_frame
VersionAndType db ?
Code db ?
SessionID dw ?
Length dw ? ; Length of payload, does NOT include the length PPPoE header.
Payload rb 0
ends
 
uglobal
PPPoE_SID dw ?
PPPoE_MAC dp ?
endg
 
;-----------------------------------------------------------------
;
; PPPoE_init
;
; This function resets all IP variables
;
;-----------------------------------------------------------------
macro PPPoE_init {
 
call PPPoE_stop_connection
 
}
 
 
;-----------------------------------------------------------------
;
; PPPoE discovery input
;
; Handler of received Ethernet packet with type = Discovery
;
;
; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
; pointer to device struct in ebx
; pointer to PPP header in edx
; size of PPP packet in ecx
; OUT: /
;
;-----------------------------------------------------------------
align 4
PPPoE_discovery_input:
 
DEBUGF 2,"PPPoE_discovery_input\n"
 
; First, find open PPPoE socket
 
mov eax, net_sockets
 
.next_socket:
mov eax, [eax + SOCKET.NextPtr]
or eax, eax
jz .dump
 
cmp [eax + SOCKET.Domain], AF_PPP
jne .next_socket
 
cmp [eax + SOCKET.Protocol], PPP_PROTO_ETHERNET
jne .next_socket
 
; Now, send it to the this socket
 
mov ecx, [esp + 4]
mov esi, [esp]
 
jmp SOCKET_input
 
.dump:
DEBUGF 1,'PPPoE_discovery_input: dumping\n'
call kernel_free
add esp, 4
ret
 
 
;--------------------------------------
;
; Send discovery packet
;
; IN: eax = socket pointer
; ecx = number of bytes to send
; esi = pointer to data
;
;--------------------------------------
 
align 4
PPPoE_discovery_output:
 
DEBUGF 2,"PPPoE_discovery_output: socket=%x buffer=%x size=%d\n", eax, esi, ecx
 
; RFC2516: An entire PADI packet (including the PPPoE header) MUST NOT
; exceed 1484 octets.
cmp ecx, 1484 + 14
ja .bad
 
; Check that device exists and is ethernet device
mov ebx, [eax + SOCKET.device]
 
cmp ebx, MAX_NET_DEVICES
ja .bad
 
mov ebx, [NET_DRV_LIST + 4*ebx]
test ebx, ebx
jz .bad
 
cmp [ebx + NET_DEVICE.type], NET_TYPE_ETH
jne .bad
 
DEBUGF 2,"PPPoE_discovery_output: device=%x\n", ebx
 
; Create packet.
push ecx esi
stdcall kernel_alloc, 1500
pop esi ecx
test eax, eax
jz .bad
 
mov edx, ecx
mov edi, eax
rep movsb
 
cmp edx, 60 ; Min ETH size
ja @f
mov edx, 60
@@:
 
push edx eax ; size and packet ptr for driver send proc
 
; Overwrite source MAC and protocol type
lea edi, [eax + ETH_header.SrcMAC]
lea esi, [ebx + ETH_DEVICE.mac]
movsd
movsw
cmp word[edi], ETHER_PPP_SESSION ; Allow only PPP_discovery, or LCP
je @f
mov ax, ETHER_PPP_DISCOVERY
stosw
@@:
 
; And send the packet
call [ebx + NET_DEVICE.transmit]
 
xor eax, eax
ret
 
.bad:
or eax, -1
ret
 
 
;-----------------------------------------------------------------
;
; PPPoE session input
;
; Handler of received Ethernet packet with type = Session
;
;
; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
; pointer to device struct in ebx
; pointer to PPP header in edx
; size of PPP packet in ecx
; OUT: /
;
;-----------------------------------------------------------------
align 4
PPPoE_session_input:
 
cmp [edx + PPPoE_frame.VersionAndType], 0x11
jne .dump
 
cmp [edx + PPPoE_frame.Code], 0x00
jne .dump
 
movzx ecx, [edx + PPPoE_frame.Length]
xchg cl, ch
 
mov ax, [edx + PPPoE_frame.SessionID]
DEBUGF 2,"PPPoE_input: session ID=%x, length=%u\n", ax, cx
cmp ax, [PPPoE_SID]
jne .dump
 
mov ax, word [edx + PPPoE_frame.Payload]
add edx, PPPoE_frame.Payload + 2
 
cmp ax, PPP_IPv4
je IPv4_input
 
; cmp ax, PPP_IPv6
; je IPv6_input
 
jmp PPPoE_discovery_input ; Send LCP,CHAP,CBCP,... packets to the PPP dialer
DEBUGF 2,"PPPoE_input: Unknown protocol=%x\n", ax
 
.dump:
DEBUGF 2,"PPPoE_input: dumping\n"
call kernel_free
add esp, 4
ret
 
 
 
 
;-----------------------------------------------------------------
;
; PPPoE_output
;
; IN:
; ebx = device ptr
; ecx = packet size
;
; di = protocol
;
; OUT: edi = 0 on error, pointer to buffer otherwise
; eax = buffer start
; ebx = to device structure
; ecx = unchanged (packet size of embedded data)
; edx = size of complete buffer
;
;-----------------------------------------------------------------
align 4
PPPoE_output:
 
DEBUGF 1,"PPPoE_output: size=%u device=%x\n", ecx, ebx
 
pushw di
pushw [PPPoE_SID]
 
lea eax, [ebx + ETH_DEVICE.mac]
lea edx, [PPPoE_MAC]
add ecx, PPPoE_frame.Payload + 2
mov di, ETHER_PPP_SESSION
call ETH_output
jz .eth_error
 
sub ecx, PPPoE_frame.Payload
mov [edi + PPPoE_frame.VersionAndType], 0x11
mov [edi + PPPoE_frame.Code], 0
popw [edi + PPPoE_frame.SessionID]
xchg cl, ch
mov [edi + PPPoE_frame.Length], cx
xchg cl, ch
 
pop word [edi + PPPoE_frame.Payload]
 
sub ecx, 2
add edi, PPPoE_frame.Payload + 2
 
DEBUGF 1,"PPPoE_output: success!\n"
ret
 
 
.eth_error:
add esp, 4
xor edi, edi
 
ret
 
 
PPPoE_start_connection:
 
DEBUGF 2,"PPPoE_start_connection: %x\n", cx
 
cmp [PPPoE_SID], 0
jne .fail
 
mov [PPPoE_SID], cx
mov dword [PPPoE_MAC], edx
mov word [PPPoE_MAC + 4], si
 
xor eax, eax
ret
 
.fail:
or eax, -1
ret
 
 
align 4
PPPoE_stop_connection:
 
DEBUGF 2,"PPPoE_stop_connection\n"
 
xor eax, eax
mov [PPPoE_SID], ax
mov dword [PPPoE_MAC], eax
mov word [PPPoE_MAC + 4], ax
 
ret
 
 
;---------------------------------------------------------------------------
;
; PPPoE API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;---------------------------------------------------------------------------
align 4
PPPoE_api:
 
movzx eax, bh
shl eax, 2
 
and ebx, 0xff
cmp ebx, .number
ja .error
jmp dword [.table + 4*ebx]
 
.table:
dd PPPoE_start_connection ; 0
dd PPPoE_stop_connection ; 1
.number = ($ - .table) / 4 - 1
 
.error:
mov eax, -1
ret
/kernel/branches/net/network/icmp.inc
0,0 → 1,431
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ICMP.INC ;;
;; ;;
;; Part of the tcp/ip network stack for KolibriOS ;;
;; ;;
;; Based on the work of [Johnny_B] and [smb] ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
$Revision$
 
; ICMP types & codes
 
ICMP_ECHOREPLY = 0 ; echo reply message
 
ICMP_UNREACH = 3
ICMP_UNREACH_NET = 0 ; bad net
ICMP_UNREACH_HOST = 1 ; bad host
ICMP_UNREACH_PROTOCOL = 2 ; bad protocol
ICMP_UNREACH_PORT = 3 ; bad port
ICMP_UNREACH_NEEDFRAG = 4 ; IP_DF caused drop
ICMP_UNREACH_SRCFAIL = 5 ; src route failed
ICMP_UNREACH_NET_UNKNOWN = 6 ; unknown net
ICMP_UNREACH_HOST_UNKNOWN = 7 ; unknown host
ICMP_UNREACH_ISOLATED = 8 ; src host isolated
ICMP_UNREACH_NET_PROHIB = 9 ; prohibited access
ICMP_UNREACH_HOST_PROHIB = 10 ; ditto
ICMP_UNREACH_TOSNET = 11 ; bad tos for net
ICMP_UNREACH_TOSHOST = 12 ; bad tos for host
ICMP_UNREACH_FILTER_PROHIB = 13 ; admin prohib
ICMP_UNREACH_HOST_PRECEDENCE = 14 ; host prec vio.
ICMP_UNREACH_PRECEDENCE_CUTOFF = 15 ; prec cutoff
 
ICMP_SOURCEQUENCH = 4 ; Packet lost, slow down
 
ICMP_REDIRECT = 5 ; shorter route, codes:
ICMP_REDIRECT_NET = 0 ; for network
ICMP_REDIRECT_HOST = 1 ; for host
ICMP_REDIRECT_TOSNET = 2 ; for tos and net
ICMP_REDIRECT_TOSHOST = 3 ; for tos and host
 
ICMP_ALTHOSTADDR = 6 ; alternate host address
ICMP_ECHO = 8 ; echo service
ICMP_ROUTERADVERT = 9 ; router advertisement
ICMP_ROUTERADVERT_NORMAL = 0 ; normal advertisement
ICMP_ROUTERADVERT_NOROUTE_COMMON= 16 ; selective routing
 
ICMP_ROUTERSOLICIT = 10 ; router solicitation
ICMP_TIMXCEED = 11 ; time exceeded, code:
ICMP_TIMXCEED_INTRANS = 0 ; ttl==0 in transit
ICMP_TIMXCEED_REASS = 1 ; ttl==0 in reass
 
ICMP_PARAMPROB = 12 ; ip header bad
ICMP_PARAMPROB_ERRATPTR = 0 ; error at param ptr
ICMP_PARAMPROB_OPTABSENT = 1 ; req. opt. absent
ICMP_PARAMPROB_LENGTH = 2 ; bad length
 
ICMP_TSTAMP = 13 ; timestamp request
ICMP_TSTAMPREPLY = 14 ; timestamp reply
ICMP_IREQ = 15 ; information request
ICMP_IREQREPLY = 16 ; information reply
ICMP_MASKREQ = 17 ; address mask request
ICMP_MASKREPLY = 18 ; address mask reply
ICMP_TRACEROUTE = 30 ; traceroute
ICMP_DATACONVERR = 31 ; data conversion error
ICMP_MOBILE_REDIRECT = 32 ; mobile host redirect
ICMP_IPV6_WHEREAREYOU = 33 ; IPv6 where-are-you
ICMP_IPV6_IAMHERE = 34 ; IPv6 i-am-here
ICMP_MOBILE_REGREQUEST = 35 ; mobile registration req
ICMP_MOBILE_REGREPLY = 36 ; mobile registreation reply
ICMP_SKIP = 39 ; SKIP
 
ICMP_PHOTURIS = 40 ; Photuris
ICMP_PHOTURIS_UNKNOWN_INDEX = 1 ; unknown sec index
ICMP_PHOTURIS_AUTH_FAILED = 2 ; auth failed
ICMP_PHOTURIS_DECRYPT_FAILED = 3 ; decrypt failed
 
 
 
struct ICMP_header
 
Type db ?
Code db ?
Checksum dw ?
Identifier dw ?
SequenceNumber dw ?
 
ends
 
 
align 4
uglobal
ICMP_PACKETS_TX rd MAX_NET_DEVICES
ICMP_PACKETS_RX rd MAX_NET_DEVICES
endg
 
 
 
;-----------------------------------------------------------------
;
; ICMP_init
;
;-----------------------------------------------------------------
 
macro ICMP_init {
 
xor eax, eax
mov edi, ICMP_PACKETS_TX
mov ecx, 2*MAX_NET_DEVICES
rep stosd
 
}
 
 
;-----------------------------------------------------------------
;
; ICMP_input:
;
; This procedure will send reply's to ICMP echo's
; and insert packets into sockets when needed
;
; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
; ebx = pointer to device struct
; ecx = ICMP Packet size
; esi = ptr to ICMP Packet data
; edi = ptr to ipv4 source and dest address
;
; OUT: /
;
;-----------------------------------------------------------------
align 4
ICMP_input:
 
DEBUGF 1,"ICMP_input:\n"
 
; First, check the checksum (altough some implementations ignore it)
 
push esi ecx
push [esi + ICMP_header.Checksum]
mov [esi + ICMP_header.Checksum], 0
xor edx, edx
call checksum_1
call checksum_2
pop si
cmp dx, si
pop ecx edx
jne .checksum_mismatch
 
cmp [edx + ICMP_header.Type], ICMP_ECHO ; Is this an echo request?
jne .check_sockets
 
; We well re-use the packet so we can create the response as fast as possible
; Notice: this only works on pure ethernet
 
DEBUGF 1,"got echo request\n"
mov [edx + ICMP_header.Type], ICMP_ECHOREPLY ; Change Packet type to reply
 
mov esi, [esp] ; Start of buffer
 
cmp dword[edi + 4], 1 shl 24 + 127
je .loopback
 
; Update stats (and validate device ptr)
call NET_ptr_to_num
cmp edi,-1
je .dump
inc [ICMP_PACKETS_RX + 4*edi]
inc [ICMP_PACKETS_TX + 4*edi]
 
; exchange dest and source address in IP header
; exchange dest and source MAC in ETH header
push dword [esi + ETH_header.DstMAC]
push dword [esi + ETH_header.SrcMAC]
pop dword [esi + ETH_header.DstMAC]
pop dword [esi + ETH_header.SrcMAC]
push word [esi + ETH_header.DstMAC + 4]
push word [esi + ETH_header.SrcMAC + 4]
pop word [esi + ETH_header.DstMAC + 4]
pop word [esi + ETH_header.SrcMAC + 4]
add esi, sizeof.ETH_header-2
 
.loopback:
add esi, 2
push [esi + IPv4_header.SourceAddress]
push [esi + IPv4_header.DestinationAddress]
pop [esi + IPv4_header.SourceAddress]
pop [esi + IPv4_header.DestinationAddress]
 
; Recalculate ip header checksum
movzx ecx, [esi + IPv4_header.VersionAndIHL] ; Calculate IP Header length by using IHL field
and ecx, 0x0f
shl cx, 2
mov edi, ecx ; IP header length
mov eax, edx ; ICMP packet start addr
 
push esi ; Calculate the IP checksum
xor edx, edx ;
call checksum_1 ;
call checksum_2 ;
pop esi ;
mov [esi + IPv4_header.HeaderChecksum], dx ;
 
; Recalculate ICMP CheckSum
movzx ecx, [esi + IPv4_header.TotalLength] ; Find length of IP Packet
xchg ch, cl ;
sub ecx, edi ; IP packet length - IP header length = ICMP packet length
 
mov esi, eax ; Calculate ICMP checksum
xor edx, edx ;
call checksum_1 ;
call checksum_2 ;
mov [eax + ICMP_header.Checksum], dx ;
 
; Transmit the packet (notice that packet ptr and packet size have been on stack since start of the procedure!)
call [ebx + NET_DEVICE.transmit]
ret
 
 
 
 
.check_sockets:
; Look for an open ICMP socket
 
mov esi, [edi] ; ipv4 source address
mov eax, net_sockets
.try_more:
; mov , [edx + ICMP_header.Identifier]
.next_socket:
mov eax, [eax + SOCKET.NextPtr]
or eax, eax
jz .dump
 
cmp [eax + SOCKET.Domain], AF_INET4
jne .next_socket
 
cmp [eax + SOCKET.Protocol], IP_PROTO_ICMP
jne .next_socket
 
cmp [eax + IP_SOCKET.RemoteIP], esi
jne .next_socket
 
; cmp [eax + ICMP_SOCKET.Identifier],
; jne .next_socket
 
; call IPv4_dest_to_dev
; cmp edi,-1
; je .dump
; inc [ICMP_PACKETS_RX+edi]
 
DEBUGF 1,"socket=%x\n", eax
 
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
 
mov esi, edx
jmp SOCKET_input
 
 
.checksum_mismatch:
DEBUGF 1,"checksum mismatch\n"
 
.dump:
DEBUGF 1,"ICMP_input: dumping\n"
 
call kernel_free
add esp, 4 ; pop (balance stack)
 
ret
 
 
;-----------------------------------------------------------------
;
; ICMP_output
;
; IN: eax = dest ip
; ebx = source ip
; ecx = data length
; dh = type
; dl = code
; esi = data offset
; edi = identifier shl 16 + sequence number
;
;-----------------------------------------------------------------
align 4
ICMP_output:
 
DEBUGF 1,"Creating ICMP Packet\n"
 
push esi edi dx
 
mov edx, [eax + IP_SOCKET.LocalIP]
mov eax, [eax + IP_SOCKET.RemoteIP]
add ecx, sizeof.ICMP_header
mov di, IP_PROTO_ICMP SHL 8 + 128 ; TTL
call IPv4_output
jz .exit
 
DEBUGF 1,"full icmp packet size: %u\n", edx
 
pop word [edi + ICMP_header.Type] ; Write both type and code bytes at once
pop dword [edi + ICMP_header.Identifier] ; identifier and sequence number
mov [edi + ICMP_header.Checksum], 0
 
push ebx ecx edx
mov esi, edi
xor edx, edx
call checksum_1
call checksum_2
mov [edi + ICMP_header.Checksum], dx
pop edx ecx ebx esi
 
sub ecx, sizeof.ICMP_header
add edi, sizeof.ICMP_header
push cx
shr cx, 2
rep movsd
pop cx
and cx, 3
rep movsb
 
sub edi, edx ;;; TODO: find a better way to remember start of packet
push edx edi
DEBUGF 1,"Sending ICMP Packet\n"
call [ebx + NET_DEVICE.transmit]
ret
.exit:
DEBUGF 1,"Creating ICMP Packet failed\n"
add esp, 2*4 + 2
ret
 
 
 
 
;-----------------------------------------------------------------
;
; ICMP_output
;
; IN: eax = socket ptr
; ecx = data length
; esi = data offset
;
;-----------------------------------------------------------------
align 4
ICMP_output_raw:
 
DEBUGF 1,"Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
 
push edx
 
mov di, IP_PROTO_ICMP SHL 8 + 128 ; TTL
mov edx, [eax + IP_SOCKET.LocalIP]
mov eax, [eax + IP_SOCKET.RemoteIP]
call IPv4_output
jz .exit
 
pop esi
push edx
push eax
 
push edi ecx
DEBUGF 1,"copying %u bytes from %x to %x\n", ecx, esi, edi
rep movsb
pop ecx edi
 
mov [edi + ICMP_header.Checksum], 0
 
mov esi, edi
xor edx, edx
call checksum_1
call checksum_2
mov [edi + ICMP_header.Checksum], dx
 
DEBUGF 1,"Sending ICMP Packet\n"
call [ebx + NET_DEVICE.transmit]
ret
.exit:
DEBUGF 1,"Creating ICMP Packet failed\n"
add esp, 4
ret
 
 
 
 
;-----------------------------------------------------------------
;
; ICMP_API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;-----------------------------------------------------------------
align 4
ICMP_api:
 
movzx eax, bh
shl eax, 2
 
test bl, bl
jz .packets_tx ; 0
dec bl
jz .packets_rx ; 1
 
.error:
mov eax, -1
ret
 
.packets_tx:
mov eax, [ICMP_PACKETS_TX + eax]
ret
 
.packets_rx:
mov eax, [ICMP_PACKETS_RX + eax]
ret
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/network/queue.inc
0,0 → 1,100
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; queue.inc ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
; The Queues implemented by these macros form a ring-buffer.
; The data to these queue's always looks like this:
;
; At top, you have the queue struct, wich has the size (number of currently queued packets, read and write pointers.
; This struct is followed by a number of slots wich you can read and write to using the macros.
; How these slots look like is up to you to chose, normally they should have at least a pointer to where the real data is.
; (you can see some examples below)
 
 
struct queue
 
size dd ? ; number of queued packets in this queue
w_ptr dd ? ; current writing pointer in queue
r_ptr dd ? ; current reading pointer
 
ends
 
; The following macros share these inputs:
 
; ptr = pointer to where the queue data is located
; size = number of slots/entrys in the queue
; entry_size = size of one slot, in bytes
; failaddr = the address where macro will jump to when there is no data in the queue
 
; additionally, add_to_queue requires you to set esi to the data wich you want to queue
; get_from_queue on the other hand will return a pointer in esi, to the entry you're interessed in
; PS: macros WILL destroy ecx and edi
 
macro add_to_queue ptr, size, entry_size, failaddr {
 
cmp [ptr + queue.size], size ; Check if queue isnt full
jae failaddr
 
inc [ptr + queue.size] ; if not full, queue one more
 
mov edi, [ptr + queue.w_ptr] ; Current write pointer (FIFO!)
mov ecx, entry_size/4 ; Write the queue entry
rep movsd ;
 
lea ecx, [size*entry_size+ptr+sizeof.queue]
cmp edi, ecx ; entry size
jb .no_wrap
 
sub edi, size*entry_size
 
.no_wrap:
mov [ptr + queue.w_ptr], edi
 
}
 
 
 
macro get_from_queue ptr, size, entry_size, failaddr {
 
cmp [ptr + queue.size], 0 ; any packets queued?
je failaddr
 
dec [ptr + queue.size] ; if so, dequeue one
 
mov esi, [ptr + queue.r_ptr]
push esi
 
add esi, entry_size
 
lea ecx, [size*entry_size+ptr+sizeof.queue]
cmp esi, ecx ; entry size
jb .no_wrap
 
sub esi, size*entry_size
 
.no_wrap:
mov dword [ptr + queue.r_ptr], esi
 
pop esi
 
}
 
macro init_queue ptr {
 
mov [ptr + queue.size] , 0
lea edi, [ptr + sizeof.queue]
mov [ptr + queue.w_ptr], edi
mov [ptr + queue.r_ptr], edi
}
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/network
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/const.inc
0,0 → 1,693
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
dpl0 equ 10010000b ; data read dpl0
drw0 equ 10010010b ; data read/write dpl0
drw3 equ 11110010b ; data read/write dpl3
cpl0 equ 10011010b ; code read dpl0
cpl3 equ 11111010b ; code read dpl3
 
D32 equ 01000000b ; 32bit segment
G32 equ 10000000b ; page gran
 
 
;;;;;;;;;;;;cpu_caps flags;;;;;;;;;;;;;;;;
 
CPU_386 equ 3
CPU_486 equ 4
CPU_PENTIUM equ 5
CPU_P6 equ 6
CPU_PENTIUM4 equ 0x0F
 
CAPS_FPU equ 00 ;on-chip x87 floating point unit
CAPS_VME equ 01 ;virtual-mode enhancements
CAPS_DE equ 02 ;debugging extensions
CAPS_PSE equ 03 ;page-size extensions
CAPS_TSC equ 04 ;time stamp counter
CAPS_MSR equ 05 ;model-specific registers
CAPS_PAE equ 06 ;physical-address extensions
CAPS_MCE equ 07 ;machine check exception
CAPS_CX8 equ 08 ;CMPXCHG8B instruction
CAPS_APIC equ 09 ;on-chip advanced programmable
; interrupt controller
; 10 ;unused
CAPS_SEP equ 11 ;SYSENTER and SYSEXIT instructions
CAPS_MTRR equ 12 ;memory-type range registers
CAPS_PGE equ 13 ;page global extension
CAPS_MCA equ 14 ;machine check architecture
CAPS_CMOV equ 15 ;conditional move instructions
CAPS_PAT equ 16 ;page attribute table
 
CAPS_PSE36 equ 17 ;page-size extensions
CAPS_PSN equ 18 ;processor serial number
CAPS_CLFLUSH equ 19 ;CLFUSH instruction
 
CAPS_DS equ 21 ;debug store
CAPS_ACPI equ 22 ;thermal monitor and software
;controlled clock supported
CAPS_MMX equ 23 ;MMX instructions
CAPS_FXSR equ 24 ;FXSAVE and FXRSTOR instructions
CAPS_SSE equ 25 ;SSE instructions
CAPS_SSE2 equ 26 ;SSE2 instructions
CAPS_SS equ 27 ;self-snoop
CAPS_HTT equ 28 ;hyper-threading technology
CAPS_TM equ 29 ;thermal monitor supported
CAPS_IA64 equ 30 ;IA64 capabilities
CAPS_PBE equ 31 ;pending break enable
 
;ecx
CAPS_SSE3 equ 32 ;SSE3 instructions
; 33
; 34
CAPS_MONITOR equ 35 ;MONITOR/MWAIT instructions
CAPS_DS_CPL equ 36 ;
CAPS_VMX equ 37 ;virtual mode extensions
; 38 ;
CAPS_EST equ 39 ;enhansed speed step
CAPS_TM2 equ 40 ;thermal monitor2 supported
; 41
CAPS_CID equ 42 ;
; 43
; 44
CAPS_CX16 equ 45 ;CMPXCHG16B instruction
CAPS_xTPR equ 46 ;
;
;reserved
;
;ext edx /ecx
CAPS_SYSCAL equ 64 ;
CAPS_XD equ 65 ;execution disable
CAPS_FFXSR equ 66 ;
CAPS_RDTSCP equ 67 ;
CAPS_X64 equ 68 ;
CAPS_3DNOW equ 69 ;
CAPS_3DNOWEXT equ 70 ;
CAPS_LAHF equ 71 ;
CAPS_CMP_LEG equ 72 ;
CAPS_SVM equ 73 ;secure virual machine
CAPS_ALTMOVCR8 equ 74 ;
 
; CPU MSR names
MSR_SYSENTER_CS equ 0x174
MSR_SYSENTER_ESP equ 0x175
MSR_SYSENTER_EIP equ 0x176
MSR_AMD_EFER equ 0xC0000080 ; Extended Feature Enable Register
MSR_AMD_STAR equ 0xC0000081 ; SYSCALL/SYSRET Target Address Register
 
CR0_PE equ 0x00000001 ;protected mode
CR0_MP equ 0x00000002 ;monitor fpu
CR0_EM equ 0x00000004 ;fpu emulation
CR0_TS equ 0x00000008 ;task switch
CR0_ET equ 0x00000010 ;extension type hardcoded to 1
CR0_NE equ 0x00000020 ;numeric error
CR0_WP equ 0x00010000 ;write protect
CR0_AM equ 0x00040000 ;alignment check
CR0_NW equ 0x20000000 ;not write-through
CR0_CD equ 0x40000000 ;cache disable
CR0_PG equ 0x80000000 ;paging
 
 
CR4_VME equ 0x0001
CR4_PVI equ 0x0002
CR4_TSD equ 0x0004
CR4_DE equ 0x0008
CR4_PSE equ 0x0010
CR4_PAE equ 0x0020
CR4_MCE equ 0x0040
CR4_PGE equ 0x0080
CR4_PCE equ 0x0100
CR4_OSFXSR equ 0x0200
CR4_OSXMMEXPT equ 0x0400
 
SSE_IE equ 0x0001
SSE_DE equ 0x0002
SSE_ZE equ 0x0004
SSE_OE equ 0x0008
SSE_UE equ 0x0010
SSE_PE equ 0x0020
SSE_DAZ equ 0x0040
SSE_IM equ 0x0080
SSE_DM equ 0x0100
SSE_ZM equ 0x0200
SSE_OM equ 0x0400
SSE_UM equ 0x0800
SSE_PM equ 0x1000
SSE_FZ equ 0x8000
 
SSE_INIT equ (SSE_IM+SSE_DM+SSE_ZM+SSE_OM+SSE_UM+SSE_PM)
 
IRQ_PIC equ 0
IRQ_APIC equ 1
 
struct TSS
_back rw 2
_esp0 rd 1
_ss0 rw 2
_esp1 rd 1
_ss1 rw 2
_esp2 rd 1
_ss2 rw 2
_cr3 rd 1
_eip rd 1
_eflags rd 1
_eax rd 1
_ecx rd 1
_edx rd 1
_ebx rd 1
_esp rd 1
_ebp rd 1
_esi rd 1
_edi rd 1
_es rw 2
_cs rw 2
_ss rw 2
_ds rw 2
_fs rw 2
_gs rw 2
_ldt rw 2
_trap rw 1
_io rw 1
rb 24
_io_map_0 rb 4096
_io_map_1 rb 4096
ends
 
OS_BASE equ 0x80000000
 
window_data equ (OS_BASE+0x0001000)
 
CURRENT_TASK equ (OS_BASE+0x0003000)
TASK_COUNT equ (OS_BASE+0x0003004)
TASK_BASE equ (OS_BASE+0x0003010)
TASK_DATA equ (OS_BASE+0x0003020)
TASK_EVENT equ (OS_BASE+0x0003020)
 
mouseunder equ (OS_BASE+0x0006900)
CDDataBuf equ (OS_BASE+0x0007000)
FLOPPY_BUFF equ (OS_BASE+0x0008000)
ACTIVE_PROC_STACK equ (OS_BASE+0x000A400) ;unused
idts equ (OS_BASE+0x000B100)
WIN_STACK equ (OS_BASE+0x000C000)
WIN_POS equ (OS_BASE+0x000C400)
FDD_BUFF equ (OS_BASE+0x000D000)
 
;unused ? only one reference
ENABLE_TASKSWITCH equ (OS_BASE+0x000E000)
 
PUTPIXEL equ (OS_BASE+0x000E020)
GETPIXEL equ (OS_BASE+0x000E024)
 
;unused ? only one reference
BANK_SWITCH equ (OS_BASE+0x000E030)
 
;unused ? store mousepointer
MOUSE_PICTURE equ (OS_BASE+0x000F200)
 
;MOUSE_VISIBLE equ (OS_BASE+0x000F204)
WIN_TEMP_XY equ (OS_BASE+0x000F300)
KEY_COUNT equ (OS_BASE+0x000F400)
KEY_BUFF equ (OS_BASE+0x000F401)
 
BTN_COUNT equ (OS_BASE+0x000F500)
BTN_BUFF equ (OS_BASE+0x000F501)
 
CPU_FREQ equ (OS_BASE+0x000F600)
 
;unused ? no active references
MOUSE_PORT equ (OS_BASE+0x000F604)
 
;unused
PS2_CHUNK equ (OS_BASE+0x000FB00)
 
MOUSE_SCROLL_H equ (OS_BASE+0x000FB08)
MOUSE_X equ (OS_BASE+0x000FB0A)
MOUSE_Y equ (OS_BASE+0x000FB0C)
MOUSE_SCROLL_V equ (OS_BASE+0x000FB0E)
 
MOUSE_COLOR_MEM equ (OS_BASE+0x000FB10)
COLOR_TEMP equ (OS_BASE+0x000FB30)
BTN_DOWN equ (OS_BASE+0x000FB40)
MOUSE_DOWN equ (OS_BASE+0x000FB44)
X_UNDER equ (OS_BASE+0x000FB4A)
Y_UNDER equ (OS_BASE+0x000FB4C)
ScreenBPP equ (OS_BASE+0x000FBF1)
 
;unused ? only one reference
MOUSE_BUFF_COUNT equ (OS_BASE+0x000FCFF)
 
Screen_Max_X equ (OS_BASE+0x000FE00)
Screen_Max_Y equ (OS_BASE+0x000FE04)
BytesPerScanLine equ (OS_BASE+0x000FE08)
SCR_MODE equ (OS_BASE+0x000FE0C)
 
LFBAddress equ (OS_BASE+0x000FE80)
BTN_ADDR equ (OS_BASE+0x000FE88)
MEM_AMOUNT equ (OS_BASE+0x000FE8C)
 
SYS_SHUTDOWN equ (OS_BASE+0x000FF00)
TASK_ACTIVATE equ (OS_BASE+0x000FF01)
 
REDRAW_BACKGROUND equ (OS_BASE+0x000FFF0)
 
BANK_RW equ (OS_BASE+0x000FFF2)
MOUSE_BACKGROUND equ (OS_BASE+0x000FFF4)
DONT_DRAW_MOUSE equ (OS_BASE+0x000FFF5)
DONT_SWITCH equ (OS_BASE+0x000FFFF)
 
TMP_STACK_TOP equ 0x006CC00
 
sys_pgdir equ (OS_BASE+0x006F000)
 
DRIVE_DATA equ (OS_BASE+0x0070000)
 
SLOT_BASE equ (OS_BASE+0x0080000)
 
;unused
TMP_BUFF equ (OS_BASE+0x0090000)
 
VGABasePtr equ (OS_BASE+0x00A0000)
 
RAMDISK equ (OS_BASE+0x0100000)
RAMDISK_FAT equ (OS_BASE+0x0280000)
FLOPPY_FAT equ (OS_BASE+0x0282000)
 
CLEAN_ZONE equ 0x284000
IDE_DMA equ 0x284000
 
BgrAuxTable equ (OS_BASE+0x0298000)
; unused?
SB16Buffer equ (OS_BASE+0x02A0000)
SB16_Status equ (OS_BASE+0x02B0000)
 
BUTTON_INFO equ (OS_BASE+0x02B3FEE)
 
BPSLine_calc_area equ (OS_BASE+0x02C4000)
d_width_calc_area equ (OS_BASE+0x02CA000)
 
RESERVED_PORTS equ (OS_BASE+0x02D0000)
BOOT_VAR equ (OS_BASE+0x02E0000)
 
stack_data_start equ (OS_BASE+0x02F0000)
eth_data_start equ (OS_BASE+0x02F0000)
stack_data equ (OS_BASE+0x02F4000)
stack_data_end equ (OS_BASE+0x030ffff)
resendQ equ (OS_BASE+0x0310000)
 
skin_data equ (OS_BASE+0x0318000)
draw_data equ (OS_BASE+0x0320000)
 
BgrDrawMode equ (OS_BASE+0x0323FF4)
BgrDataWidth equ (OS_BASE+0x0323FF8)
BgrDataHeight equ (OS_BASE+0x0323FFC)
 
sys_pgmap equ (OS_BASE+0x0324000)
 
UPPER_KERNEL_PAGES equ (OS_BASE+0x0400000)
 
virtual at (OS_BASE+0x05FFF80)
tss TSS
end virtual
 
HEAP_BASE equ (OS_BASE+0x0800000)
HEAP_MIN_SIZE equ 0x01000000
 
page_tabs equ 0xFDC00000
app_page_tabs equ 0xFDC00000
kernel_tabs equ (page_tabs+ (OS_BASE shr 10)) ;0xFDE00000
master_tab equ (page_tabs+ (page_tabs shr 10)) ;0xFDFF70000
 
LFB_BASE equ 0xFE000000
 
 
new_app_base equ 0;
 
twdw equ 0x2000 ;(CURRENT_TASK-window_data)
 
std_application_base_address equ new_app_base
RING0_STACK_SIZE equ (0x2000 - 512) ;512 áàéò äëÿ êîíòåêñòà FPU
 
REG_SS equ (RING0_STACK_SIZE-4)
REG_APP_ESP equ (RING0_STACK_SIZE-8)
REG_EFLAGS equ (RING0_STACK_SIZE-12)
REG_CS equ (RING0_STACK_SIZE-16)
REG_EIP equ (RING0_STACK_SIZE-20)
REG_EAX equ (RING0_STACK_SIZE-24)
REG_ECX equ (RING0_STACK_SIZE-28)
REG_EDX equ (RING0_STACK_SIZE-32)
REG_EBX equ (RING0_STACK_SIZE-36)
REG_ESP equ (RING0_STACK_SIZE-40) ;RING0_STACK_SIZE-20
REG_EBP equ (RING0_STACK_SIZE-44)
REG_ESI equ (RING0_STACK_SIZE-48)
REG_EDI equ (RING0_STACK_SIZE-52)
REG_RET equ (RING0_STACK_SIZE-56) ;irq0.return
 
 
PG_UNMAP equ 0x000
PG_MAP equ 0x001
PG_WRITE equ 0x002
PG_SW equ 0x003
PG_USER equ 0x005
PG_UW equ 0x007
PG_NOCACHE equ 0x018
PG_LARGE equ 0x080
PG_GLOBAL equ 0x100
 
PG_SHARED equ 0x200
 
;;;;;;;;;;;boot time variables
 
BOOT_BPP equ 0x9000 ;byte bits per pixel
BOOT_PITCH equ 0x9001 ;word scanline length
BOOT_VESA_MODE equ 0x9008 ;word vesa video mode
BOOT_X_RES equ 0x900A ;word X res
BOOT_Y_RES equ 0x900C ;word Y res
;;BOOT_MOUSE_PORT equ 0x9010 ;byte mouse port - not used
BOOT_BANK_SW equ 0x9014 ;dword Vesa 1.2 pm bank switch
BOOT_LFB equ 0x9018 ;dword Vesa 2.0 LFB address
BOOT_MTRR equ 0x901C ;byte 0 or 1 : enable MTRR graphics acceleration
BOOT_LOG equ 0x901D ;byte not used anymore (0 or 1 : enable system log display)
;BOOT_DIRECT_LFB equ 0x901E ;byte 0 or 1 : enable direct lfb write, paging disabled
BOOT_DMA equ 0x901F ;
BOOT_PCI_DATA equ 0x9020 ;8bytes pci data
BOOT_VRR equ 0x9030 ;byte VRR start enabled 1, 2-no
BOOT_IDE_BASE_ADDR equ 0x9031 ;word IDEContrRegsBaseAddr
BOOT_MEM_AMOUNT equ 0x9034 ;dword memory amount
 
BOOT_APM_ENTRY equ 0x9040
BOOT_APM_VERSION equ 0x9044
BOOT_APM_FLAGS equ 0x9046 ;unused
BOOT_APM_CODE_32 equ 0x9050
BOOT_APM_CODE_16 equ 0x9052
BOOT_APM_DATA_16 equ 0x9054
 
TMP_FILE_NAME equ 0
TMP_CMD_LINE equ 1024
TMP_ICON_OFFS equ 1280
 
 
EVENT_REDRAW equ 0x00000001
EVENT_KEY equ 0x00000002
EVENT_BUTTON equ 0x00000004
EVENT_BACKGROUND equ 0x00000010
EVENT_MOUSE equ 0x00000020
EVENT_IPC equ 0x00000040
EVENT_NETWORK equ 0x00000080
EVENT_DEBUG equ 0x00000100
EVENT_NETWORK2 equ 0x00000200
EVENT_EXTENDED equ 0x00000400
 
 
EV_INTR equ 1
 
struct THR_DATA
rb (8192-512)
; pl0_stack
fpu_state rb 512
tls_page rb 4096
pdbr rb 4096
ends
 
virtual at (OS_BASE-sizeof.THR_DATA)
thr_data THR_DATA
end virtual
 
struct SYS_VARS
bpp dd ?
scanline dd ?
vesa_mode dd ?
x_res dd ?
y_res dd ?
ends
 
struct APPOBJ ; common object header
magic dd ? ;
destroy dd ? ; internal destructor
fd dd ? ; next object in list
bk dd ? ; prev object in list
pid dd ? ; owner id
ends
 
APP_OBJ_OFFSET equ 48
APP_EV_OFFSET equ 40
 
struct CURSOR APPOBJ
base dd ? ;allocated memory
hot_x dd ? ;hotspot coords
hot_y dd ?
 
list_next dd ? ;next cursor in cursor list
list_prev dd ? ;prev cursor in cursor list
dev_obj dd ? ;device depended data
ends
 
 
struct EVENT APPOBJ
id dd ? ;event uid
state dd ? ;internal flags
code dd ?
rd 5
ends
 
 
struct SMEM
bk dd ?
fd dd ? ;+4
base dd ? ;+8
size dd ? ;+12
access dd ? ;+16
refcount dd ? ;+20
name rb 32 ;+24
ends
 
struct SMAP APPOBJ
base dd ? ;mapped base
parent dd ? ;SMEM
ends
 
struct DLLDESCR
bk dd ?
fd dd ? ;+4
data dd ? ;+8
size dd ? ;+12
timestamp dq ?
refcount dd ?
defaultbase dd ?
coff_hdr dd ?
symbols_ptr dd ?
symbols_num dd ?
symbols_lim dd ?
exports dd ? ;export table
name rb 260
ends
 
struct HDLL
fd dd ? ;next object in list
bk dd ? ;prev object in list
pid dd ? ;owner id
 
base dd ? ;mapped base
size dd ? ;mapped size
refcount dd ? ;reference counter for this process and this lib
parent dd ? ;DLLDESCR
ends
 
struct display_t
x dd ?
y dd ?
width dd ?
height dd ?
bpp dd ?
vrefresh dd ?
pitch dd ?
lfb dd ?
 
modes dd ?
ddev dd ?
connector dd ?
crtc dd ?
 
cr_list.next dd ?
cr_list.prev dd ?
 
cursor dd ?
 
init_cursor dd ?
select_cursor dd ?
show_cursor dd ?
move_cursor dd ?
restore_cursor dd ?
disable_mouse dd ?
mask_seqno dd ?
check_mouse dd ?
check_m_pixel dd ?
ends
 
struct BOOT_DATA
bpp dd ?
scanline dd ?
vesa_mode dd ?
x_res dd ?
y_res dd ?
mouse_port dd ?
bank_switch dd ?
lfb dd ?
vesa_mem dd ?
log dd ?
direct_lfb dd ?
pci_data dd ?
dd ?
vrr dd ?
ide_base dd ?
mem_amount dd ?
pages_count dd ?
pagemap_size dd ?
kernel_max dd ?
kernel_pages dd ?
kernel_tables dd ?
 
cpu_vendor dd ?
dd ?
dd ?
cpu_sign dd ?
cpu_info dd ?
cpu_caps dd ?
dd ?
dd ?
ends
 
struct LHEAD
next dd ? ;next object in list
prev dd ? ;prev object in list
ends
 
struct MUTEX
lhead LHEAD
count dd ?
ends
 
struct PCIDEV
bk dd ?
fd dd ?
vendor_device_id dd ?
class dd ?
devfn db ?
bus db ?
ends
 
; The following macro assume that we are on uniprocessor machine.
; Serious work is needed for multiprocessor machines.
macro spin_lock_irqsave spinlock
{
pushf
cli
}
macro spin_unlock_irqrestore spinlock
{
popf
}
macro spin_lock_irq spinlock
{
cli
}
macro spin_unlock_irq spinlock
{
sti
}
 
struct MEM_STATE
mutex MUTEX
smallmap dd ?
treemap dd ?
topsize dd ?
top dd ?
smallbins rd 4*32
treebins rd 32
ends
 
struct PG_DATA
mem_amount dd ?
vesa_mem dd ?
pages_count dd ?
pages_free dd ?
pages_faults dd ?
pagemap_size dd ?
kernel_pages dd ?
kernel_tables dd ?
sys_page_dir dd ?
mutex MUTEX
ends
 
struct SRV
srv_name rb 16 ;ASCIIZ string
magic dd ? ;+0x10 ;'SRV '
size dd ? ;+0x14 ;size of structure SRV
fd dd ? ;+0x18 ;next SRV descriptor
bk dd ? ;+0x1C ;prev SRV descriptor
base dd ? ;+0x20 ;service base address
entry dd ? ;+0x24 ;service START function
srv_proc dd ? ;+0x28 ;user mode service handler
srv_proc_ex dd ? ;+0x2C ;kernel mode service handler
ends
 
DRV_ENTRY equ 1
DRV_EXIT equ -1
 
struct COFF_HEADER
machine dw ?
nSections dw ?
DataTime dd ?
pSymTable dd ?
nSymbols dd ?
optHeader dw ?
flags dw ?
ends
 
struct COFF_SECTION
Name rb 8
VirtualSize dd ?
VirtualAddress dd ?
SizeOfRawData dd ?
PtrRawData dd ?
PtrReloc dd ?
PtrLinenumbers dd ?
NumReloc dw ?
NumLinenum dw ?
Characteristics dd ?
ends
 
struct COFF_RELOC
VirtualAddress dd ?
SymIndex dd ?
Type dw ?
ends
 
struct COFF_SYM
Name rb 8
Value dd ?
SectionNumber dw ?
Type dw ?
StorageClass db ?
NumAuxSymbols db ?
ends
 
struct IOCTL
handle dd ?
io_code dd ?
input dd ?
inp_size dd ?
output dd ?
out_size dd ?
ends
 
struct IRQH
list LHEAD
handler dd ? ;handler roututine
data dd ? ;user-specific data
ends
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/bus/pci/pci32.inc
0,0 → 1,724
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; PCI32.INC ;;
;; ;;
;; 32 bit PCI driver code ;;
;; ;;
;; Version 0.3 April 9, 2007 ;;
;; Version 0.2 December 21st, 2002 ;;
;; ;;
;; Author: Victor Prodan, victorprodan@yahoo.com ;;
;; Mihailov Ilia, ghost.nsk@gmail.com ;;
;; Credits: ;;
;; Ralf Brown ;;
;; Mike Hibbett, mikeh@oceanfree.net ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
;***************************************************************************
; Function
; pci_api:
;
; Description
; entry point for system PCI calls
;***************************************************************************
;mmio_pci_addr equ 0x400 ; set actual PCI address here to activate user-MMIO
 
iglobal
align 4
f62call:
dd pci_fn_0
dd pci_fn_1
dd pci_fn_2
dd pci_service_not_supported ;3
dd pci_read_reg ;4 byte
dd pci_read_reg ;5 word
dd pci_read_reg ;6 dword
dd pci_service_not_supported ;7
dd pci_write_reg ;8 byte
dd pci_write_reg ;9 word
dd pci_write_reg ;10 dword
if defined mmio_pci_addr
dd pci_mmio_init ;11
dd pci_mmio_map ;12
dd pci_mmio_unmap ;13
end if
 
endg
 
align 4
 
pci_api:
 
;cross
mov eax, ebx
mov ebx, ecx
mov ecx, edx
 
cmp [pci_access_enabled], 1
jne pci_service_not_supported
 
movzx edx, al
 
if defined mmio_pci_addr
cmp al, 13
ja pci_service_not_supported
else
cmp al, 10
ja pci_service_not_supported
end if
 
call dword [f62call+edx*4]
mov dword [esp+32], eax
ret
 
 
align 4
pci_api_drv:
 
cmp [pci_access_enabled], 1
jne .fail
 
cmp eax, 2
ja .fail
 
jmp dword [f62call+eax*4]
 
.fail:
or eax, -1
ret
 
 
;; ============================================
 
pci_fn_0:
; PCI function 0: get pci version (AH.AL)
movzx eax, word [BOOT_VAR+0x9022]
ret
 
pci_fn_1:
; PCI function 1: get last bus in AL
mov al, [BOOT_VAR+0x9021]
ret
 
pci_fn_2:
; PCI function 2: get pci access mechanism
mov al, [BOOT_VAR+0x9020]
ret
 
pci_service_not_supported:
or eax, -1
mov dword [esp+32], eax
ret
 
;***************************************************************************
; Function
; pci_make_config_cmd
;
; Description
; creates a command dword for use with the PCI bus
; bus # in ah
; device+func in bh (dddddfff)
; register in bl
;
; command dword returned in eax ( 10000000 bbbbbbbb dddddfff rrrrrr00 )
;***************************************************************************
 
align 4
 
pci_make_config_cmd:
shl eax, 8 ; move bus to bits 16-23
mov ax, bx ; combine all
and eax, 0xffffff
or eax, 0x80000000
ret
 
;***************************************************************************
; Function
; pci_read_reg:
;
; Description
; read a register from the PCI config space into EAX/AX/AL
; IN: ah=bus,device+func=bh,register address=bl
; number of bytes to read (1,2,4) coded into AL, bits 0-1
; (0 - byte, 1 - word, 2 - dword)
;***************************************************************************
 
align 4
 
pci_read_reg:
push ebx esi
cmp byte [BOOT_VAR+0x9020], 2;what mechanism will we use?
je pci_read_reg_2
 
; mechanism 1
mov esi, eax ; save register size into ESI
and esi, 3
 
call pci_make_config_cmd
mov ebx, eax
; get current state
mov dx, 0xcf8
in eax, dx
push eax
; set up addressing to config data
mov eax, ebx
and al, 0xfc; make address dword-aligned
out dx, eax
; get requested DWORD of config data
mov dl, 0xfc
and bl, 3
or dl, bl ; add to port address first 2 bits of register address
 
or esi, esi
jz pci_read_byte1
cmp esi, 1
jz pci_read_word1
cmp esi, 2
jz pci_read_dword1
jmp pci_fin_read1
 
pci_read_byte1:
in al, dx
jmp pci_fin_read1
pci_read_word1:
in ax, dx
jmp pci_fin_read1
pci_read_dword1:
in eax, dx
jmp pci_fin_read1
pci_fin_read1:
; restore configuration control
xchg eax, [esp]
mov dx, 0xcf8
out dx, eax
 
pop eax
pop esi ebx
ret
pci_read_reg_2:
 
test bh, 128 ;mech#2 only supports 16 devices per bus
jnz pci_read_reg_err
 
mov esi, eax ; save register size into ESI
and esi, 3
 
push eax
;store current state of config space
mov dx, 0xcf8
in al, dx
mov ah, al
mov dl, 0xfa
in al, dx
 
xchg eax, [esp]
; out 0xcfa,bus
mov al, ah
out dx, al
; out 0xcf8,0x80
mov dl, 0xf8
mov al, 0x80
out dx, al
; compute addr
shr bh, 3; func is ignored in mechanism 2
or bh, 0xc0
mov dx, bx
 
or esi, esi
jz pci_read_byte2
cmp esi, 1
jz pci_read_word2
cmp esi, 2
jz pci_read_dword2
jmp pci_fin_read2
 
pci_read_byte2:
in al, dx
jmp pci_fin_read2
pci_read_word2:
in ax, dx
jmp pci_fin_read2
pci_read_dword2:
in eax, dx
; jmp pci_fin_read2
pci_fin_read2:
 
; restore configuration space
xchg eax, [esp]
mov dx, 0xcfa
out dx, al
mov dl, 0xf8
mov al, ah
out dx, al
 
pop eax
pop esi ebx
ret
 
pci_read_reg_err:
xor eax, eax
dec eax
pop esi ebx
ret
 
 
;***************************************************************************
; Function
; pci_write_reg:
;
; Description
; write a register from ECX/CX/CL into the PCI config space
; IN: ah=bus,device+func=bh,register address (dword aligned)=bl,
; value to write in ecx
; number of bytes to write (1,2,4) coded into AL, bits 0-1
; (0 - byte, 1 - word, 2 - dword)
;***************************************************************************
 
align 4
 
pci_write_reg:
push esi ebx
cmp byte [BOOT_VAR+0x9020], 2;what mechanism will we use?
je pci_write_reg_2
 
; mechanism 1
mov esi, eax ; save register size into ESI
and esi, 3
 
call pci_make_config_cmd
mov ebx, eax
; get current state into ecx
mov dx, 0xcf8
in eax, dx
push eax
; set up addressing to config data
mov eax, ebx
and al, 0xfc; make address dword-aligned
out dx, eax
; write DWORD of config data
mov dl, 0xfc
and bl, 3
or dl, bl
mov eax, ecx
 
or esi, esi
jz pci_write_byte1
cmp esi, 1
jz pci_write_word1
cmp esi, 2
jz pci_write_dword1
jmp pci_fin_write1
 
pci_write_byte1:
out dx, al
jmp pci_fin_write1
pci_write_word1:
out dx, ax
jmp pci_fin_write1
pci_write_dword1:
out dx, eax
jmp pci_fin_write1
pci_fin_write1:
 
; restore configuration control
pop eax
mov dl, 0xf8
out dx, eax
 
xor eax, eax
pop ebx esi
 
ret
pci_write_reg_2:
 
test bh, 128 ;mech#2 only supports 16 devices per bus
jnz pci_write_reg_err
 
 
mov esi, eax ; save register size into ESI
and esi, 3
 
push eax
;store current state of config space
mov dx, 0xcf8
in al, dx
mov ah, al
mov dl, 0xfa
in al, dx
xchg eax, [esp]
; out 0xcfa,bus
mov al, ah
out dx, al
; out 0xcf8,0x80
mov dl, 0xf8
mov al, 0x80
out dx, al
; compute addr
shr bh, 3; func is ignored in mechanism 2
or bh, 0xc0
mov dx, bx
; write register
mov eax, ecx
 
or esi, esi
jz pci_write_byte2
cmp esi, 1
jz pci_write_word2
cmp esi, 2
jz pci_write_dword2
jmp pci_fin_write2
 
pci_write_byte2:
out dx, al
jmp pci_fin_write2
pci_write_word2:
out dx, ax
jmp pci_fin_write2
pci_write_dword2:
out dx, eax
jmp pci_fin_write2
pci_fin_write2:
; restore configuration space
pop eax
mov dx, 0xcfa
out dx, al
mov dl, 0xf8
mov al, ah
out dx, al
 
xor eax, eax
pop ebx esi
ret
 
pci_write_reg_err:
xor eax, eax
dec eax
pop ebx esi
ret
 
if defined mmio_pci_addr ; must be set above
;***************************************************************************
; Function
; pci_mmio_init
;
; Description
; IN: bx = device's PCI bus address (bbbbbbbbdddddfff)
; Returns eax = user heap space available (bytes)
; Error codes
; eax = -1 : PCI user access blocked,
; eax = -2 : device not registered for uMMIO service
; eax = -3 : user heap initialization failure
;***************************************************************************
pci_mmio_init:
cmp bx, mmio_pci_addr
jz @f
mov eax, -2
ret
@@:
call init_heap ; (if not initialized yet)
or eax, eax
jz @f
ret
@@:
mov eax, -3
ret
 
 
;***************************************************************************
; Function
; pci_mmio_map
;
; Description
; maps a block of PCI memory to user-accessible linear address
;
; WARNING! This VERY EXPERIMENTAL service is for one chosen PCI device only!
; The target device address should be set in kernel var mmio_pci_addr
;
; IN: ah = BAR#;
; IN: ebx = block size (bytes);
; IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages);
;
; Returns eax = MMIO block's linear address in the userspace (if no error)
;
;
; Error codes
; eax = -1 : user access to PCI blocked,
; eax = -2 : an invalid BAR register referred
; eax = -3 : no i/o space on that BAR
; eax = -4 : a port i/o BAR register referred
; eax = -5 : dynamic userspace allocation problem
;***************************************************************************
 
pci_mmio_map:
and edx, 0x0ffff
cmp ah, 6
jc .bar_0_5
jz .bar_rom
mov eax, -2
ret
.bar_rom:
mov ah, 8 ; bar6 = Expansion ROM base address
.bar_0_5:
push ecx
add ebx, 4095
and ebx, -4096
push ebx
mov bl, ah ; bl = BAR# (0..5), however bl=8 for BAR6
shl bl, 1
shl bl, 1
add bl, 0x10; now bl = BAR offset in PCI config. space
mov ax, mmio_pci_addr
mov bh, al ; bh = dddddfff
mov al, 2 ; al : DW to read
call pci_read_reg
or eax, eax
jnz @f
mov eax, -3 ; empty I/O space
jmp mmio_ret_fail
@@:
test eax, 1
jz @f
mov eax, -4 ; damned ports (not MMIO space)
jmp mmio_ret_fail
@@:
pop ecx ; ecx = block size, bytes (expanded to whole page)
mov ebx, ecx; user_alloc destroys eax, ecx, edx, but saves ebx
and eax, 0xFFFFFFF0
push eax ; store MMIO physical address + keep 2DWords in the stack
stdcall user_alloc, ecx
or eax, eax
jnz mmio_map_over
mov eax, -5 ; problem with page allocation
 
mmio_ret_fail:
pop ecx
pop edx
ret
 
mmio_map_over:
mov ecx, ebx; ecx = size (bytes, expanded to whole page)
shr ecx, 12 ; ecx = number of pages
mov ebx, eax; ebx = linear address
pop eax ; eax = MMIO start
pop edx ; edx = MMIO shift (pages)
shl edx, 12 ; edx = MMIO shift (bytes)
add eax, edx; eax = uMMIO physical address
or eax, PG_SHARED
or eax, PG_UW
or eax, PG_NOCACHE
mov edi, ebx
call commit_pages
mov eax, edi
ret
 
;***************************************************************************
; Function
; pci_mmio_unmap_page
;
; Description
; unmaps the linear space previously tied to a PCI memory block
;
; IN: ebx = linear address of space previously allocated by pci_mmio_map
; returns eax = 1 if successfully unmapped
;
; Error codes
; eax = -1 if no user PCI access allowed,
; eax = 0 if unmapping failed
;***************************************************************************
 
pci_mmio_unmap:
stdcall user_free, ebx
ret
 
end if
 
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
uglobal
align 4
; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1)
pci_emu_dat:
times 30*10 db 0
endg
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
align 4
sys_pcibios:
cmp [pci_access_enabled], 1
jne .unsupported_func
cmp [pci_bios_entry], 0
jz .emulate_bios
 
push ds
mov ax, pci_data_sel
mov ds, ax
mov eax, ebp
mov ah, 0B1h
call pword [cs:pci_bios_entry]
pop ds
 
jmp .return
;-=-=-=-=-=-=-=-=
.emulate_bios:
cmp ebp, 1 ; PCI_FUNCTION_ID
jnz .not_PCI_BIOS_PRESENT
mov edx, 'PCI '
mov al, [BOOT_VAR + 0x9020]
mov bx, [BOOT_VAR + 0x9022]
mov cl, [BOOT_VAR + 0x9021]
xor ah, ah
jmp .return_abcd
 
.not_PCI_BIOS_PRESENT:
cmp ebp, 2 ; FIND_PCI_DEVICE
jne .not_FIND_PCI_DEVICE
mov ebx, pci_emu_dat
..nxt:
cmp [ebx], dx
jne ..no
cmp [ebx + 2], cx
jne ..no
dec si
jns ..no
mov bx, [ebx + 4]
xor ah, ah
jmp .return_ab
..no:
cmp word[ebx], 0
je ..dev_not_found
add ebx, 10
jmp ..nxt
..dev_not_found:
mov ah, 0x86 ; DEVICE_NOT_FOUND
jmp .return_a
 
.not_FIND_PCI_DEVICE:
cmp ebp, 3 ; FIND_PCI_CLASS_CODE
jne .not_FIND_PCI_CLASS_CODE
mov esi, pci_emu_dat
shl ecx, 8
..nxt2:
cmp [esi], ecx
jne ..no2
mov bx, [esi]
xor ah, ah
jmp .return_ab
..no2:
cmp dword[esi], 0
je ..dev_not_found
add esi, 10
jmp ..nxt2
 
.not_FIND_PCI_CLASS_CODE:
cmp ebp, 8 ; READ_CONFIG_*
jb .not_READ_CONFIG
cmp ebp, 0x0A
ja .not_READ_CONFIG
mov eax, ebp
mov ah, bh
mov edx, edi
mov bh, bl
mov bl, dl
call pci_read_reg
mov ecx, eax
xor ah, ah ; SUCCESSFUL
jmp .return_abc
.not_READ_CONFIG:
cmp ebp, 0x0B ; WRITE_CONFIG_*
jb .not_WRITE_CONFIG
cmp ebp, 0x0D
ja .not_WRITE_CONFIG
lea eax, [ebp+1]
mov ah, bh
mov edx, edi
mov bh, bl
mov bl, dl
call pci_write_reg
xor ah, ah ; SUCCESSFUL
jmp .return_abc
.not_WRITE_CONFIG:
.unsupported_func:
mov ah, 0x81 ; FUNC_NOT_SUPPORTED
.return:
mov dword[esp + 4 ], edi
mov dword[esp + 8], esi
.return_abcd:
mov dword[esp + 24], edx
.return_abc:
mov dword[esp + 28], ecx
.return_ab:
mov dword[esp + 20], ebx
.return_a:
mov dword[esp + 32], eax
ret
 
proc pci_enum
push ebp
mov ebp, esp
push 0
virtual at ebp-4
.devfn db ?
.bus db ?
end virtual
.loop:
mov ah, [.bus]
mov al, 2
mov bh, [.devfn]
mov bl, 0
call pci_read_reg
cmp eax, 0xFFFFFFFF
jnz .has_device
test byte [.devfn], 7
jnz .next_func
jmp .no_device
.has_device:
push eax
push sizeof.PCIDEV
pop eax
call malloc
pop ecx
test eax, eax
jz .nomemory
mov edi, eax
mov [edi+PCIDEV.vendor_device_id], ecx
mov eax, pcidev_list
mov ecx, [eax+PCIDEV.bk]
mov [edi+PCIDEV.bk], ecx
mov [edi+PCIDEV.fd], eax
mov [ecx+PCIDEV.fd], edi
mov [eax+PCIDEV.bk], edi
mov eax, dword [.devfn]
mov word [edi+PCIDEV.devfn], ax
mov bh, al
mov al, 2
mov bl, 8
call pci_read_reg
shr eax, 8
mov [edi+PCIDEV.class], eax
test byte [.devfn], 7
jnz .next_func
mov ah, [.bus]
mov al, 0
mov bh, [.devfn]
mov bl, 0Eh
call pci_read_reg
test al, al
js .next_func
.no_device:
or byte [.devfn], 7
.next_func:
inc dword [.devfn]
mov ah, [.bus]
cmp ah, [BOOT_VAR+0x9021]
jbe .loop
.nomemory:
leave
ret
endp
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/bus/pci/PCIe.inc
0,0 → 1,119
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; PCIe.INC ;;
;; ;;
;; Extended PCI express services ;;
;; ;;
;; art_zh <artem@jerdev.co.uk> ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 1463 $
 
;***************************************************************************
; Function
; pci_ext_config:
;
; Description
; PCIe extended (memory-mapped) config space detection
;
; WARNINGs:
; 1) Very Experimental!
; 2) direct HT-detection (no ACPI or BIOS service used)
; 3) Only AMD/HT processors currently supported
;
;***************************************************************************
 
PCIe_CONFIG_SPACE equ 0xF0000000 ; to be moved to const.inc
mmio_pcie_cfg_addr dd 0x0 ; intel pcie space may be defined here
mmio_pcie_cfg_lim dd 0x0 ; upper pcie space address
 
 
align 4
 
pci_ext_config:
 
mov ebx, [mmio_pcie_cfg_addr]
or ebx, ebx
jz @f
or ebx, 0x7FFFFFFF ; required by PCI-SIG standards
jnz .pcie_failed
add ebx, 0x0FFFFC
cmp ebx, [mmio_pcie_cfg_lim]; is the space limit correct?
ja .pcie_failed
jmp .pcie_cfg_mapped
@@:
mov ebx, [cpu_vendor]
cmp ebx, dword [AMD_str]
jne .pcie_failed
mov bx, 0xC184 ; dev = 24, fn = 01, reg = 84h
 
.check_HT_mmio:
mov cx, bx
mov ax, 0x0002 ; bus = 0, 1dword to read
call pci_read_reg
mov bx, cx
sub bl, 4
and al, 0x80 ; check the NP bit
jz .no_pcie_cfg
shl eax, 8 ; bus:[27..20], dev:[19:15]
or eax, 0x00007FFC ; fun:[14..12], reg:[11:2]
mov [mmio_pcie_cfg_lim], eax
mov cl, bl
mov ax, 0x0002 ; bus = 0, 1dword to read
call pci_read_reg
mov bx, cx
test al, 0x03 ; MMIO Base RW enabled?
jz .no_pcie_cfg
test al, 0x0C ; MMIO Base locked?
jnz .no_pcie_cfg
xor al, al
shl eax, 8
test eax, 0x000F0000 ; MMIO Base must be bus0-aligned
jnz .no_pcie_cfg
mov [mmio_pcie_cfg_addr], eax
add eax, 0x000FFFFC
sub eax, [mmio_pcie_cfg_lim]; MMIO must cover at least one bus
ja .no_pcie_cfg
 
; -- it looks like a true PCIe config space;
mov eax, [mmio_pcie_cfg_addr] ; physical address
or eax, (PG_SHARED + PG_LARGE + PG_USER)
mov ebx, PCIe_CONFIG_SPACE ; linear address
mov ecx, ebx
shr ebx, 20
add ebx, sys_pgdir ; PgDir entry @
@@:
mov dword[ebx], eax ; map 4 buses
invlpg [ecx]
cmp bl, 4
jz .pcie_cfg_mapped ; fix it later
add bl, 4 ; next PgDir entry
add eax, 0x400000 ; eax += 4M
add ecx, 0x400000
jmp @b
 
.pcie_cfg_mapped:
; -- glad to have the extended PCIe config field found
; mov esi, boot_pcie_ok
; call boot_log
ret ; <<<<<<<<<<< OK >>>>>>>>>>>
.no_pcie_cfg:
 
xor eax, eax
mov [mmio_pcie_cfg_addr], eax
mov [mmio_pcie_cfg_lim], eax
add bl, 12
cmp bl, 0xC0 ; MMIO regs lay below this offset
jb .check_HT_mmio
.pcie_failed:
; mov esi, boot_pcie_fail
; call boot_log
ret ; <<<<<<<<< FAILURE >>>>>>>>>
 
/kernel/branches/net/bus/pci/pci16.inc
0,0 → 1,51
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; PCI16.INC ;;
;; ;;
;; 16 bit PCI driver code ;;
;; ;;
;; Version 0.2 December 21st, 2002 ;;
;; ;;
;; Author: Victor Prodan, victorprodan@yahoo.com ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
init_pci_16:
 
pushad
 
xor ax, ax
mov es, ax
mov byte [es:0x9020], 1;default mechanism:1
mov ax, 0xb101
int 0x1a
or ah, ah
jnz pci16skip
 
mov [es:0x9021], cl;last PCI bus in system
mov [es:0x9022], bx
mov [es:0x9024], edi
 
; we have a PCI BIOS, so check which configuration mechanism(s)
; it supports
; AL = PCI hardware characteristics (bit0 => mechanism1, bit1 => mechanism2)
test al, 1
jnz pci16skip
test al, 2
jz pci16skip
mov byte [es:0x9020], 2; if (al&3)==2 => mechanism 2
 
pci16skip:
 
mov ax, 0x1000
mov es, ax
 
popad
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/bus
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/core/heap.inc
0,0 → 1,1537
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
struct MEM_BLOCK
list LHEAD
next_block dd ? ;+8
prev_block dd ? ;+4
base dd ? ;+16
size dd ? ;+20
flags dd ? ;+24
handle dd ? ;+28
ends
 
FREE_BLOCK equ 4
USED_BLOCK equ 8
DONT_FREE_BLOCK equ 10h
 
 
block_next equ MEM_BLOCK.next_block
block_prev equ MEM_BLOCK.prev_block
list_fd equ MEM_BLOCK.list.next
list_bk equ MEM_BLOCK.list.prev
block_base equ MEM_BLOCK.base
block_size equ MEM_BLOCK.size
block_flags equ MEM_BLOCK.flags
 
macro calc_index op
{ shr op, 12
dec op
cmp op, 63
jna @f
mov op, 63
@@:
}
 
align 4
md:
.add_to_used:
mov eax, [esi+block_base]
mov ebx, [esi+block_base]
shr ebx, 6
add eax, ebx
shr ebx, 6
add eax, ebx
shr eax, 12
and eax, 63
inc [mem_hash_cnt+eax*4]
 
lea ecx, [mem_used_list+eax*8]
list_add esi, ecx
mov [esi+block_flags], USED_BLOCK
mov eax, [esi+block_size]
sub [heap_free], eax
ret
align 4
.find_used:
mov ecx, eax
mov ebx, eax
shr ebx, 6
add ecx, ebx
shr ebx, 6
add ecx, ebx
shr ecx, 12
and ecx, 63
 
lea ebx, [mem_used_list+ecx*8]
mov esi, ebx
.next:
mov esi, [esi+list_fd]
cmp esi, ebx
je .fail
 
cmp eax, [esi+block_base]
jne .next
 
ret
.fail:
xor esi, esi
ret
 
align 4
.del_from_used:
call .find_used
test esi, esi
jz .done
 
cmp [esi+block_flags], USED_BLOCK
jne .fatal
 
dec [mem_hash_cnt+ecx*4]
list_del esi
.done:
ret
.fatal: ;FIXME panic here
xor esi, esi
ret
 
;Initial heap state
;
;+heap_size terminator USED_BLOCK
;+4096*MEM_BLOCK.sizeof free space FREE_BLOCK
;HEAP_BASE heap_descriptors USED_BLOCK
;
 
align 4
proc init_kernel_heap
 
mov ecx, 64
mov edi, mem_block_list
@@:
mov eax, edi
stosd
stosd
loop @B
 
mov ecx, 64
mov edi, mem_used_list
@@:
mov eax, edi
stosd
stosd
loop @B
 
stdcall alloc_pages, dword 32
mov ecx, 32
mov edx, eax
mov edi, HEAP_BASE
.l1:
stdcall map_page, edi, edx, PG_SW
add edi, 0x1000
add edx, 0x1000
dec ecx
jnz .l1
 
mov edi, HEAP_BASE ;descriptors
mov ebx, HEAP_BASE+sizeof.MEM_BLOCK ;free space
mov ecx, HEAP_BASE+sizeof.MEM_BLOCK*2 ;terminator
 
xor eax, eax
mov [edi+block_next], ebx
mov [edi+block_prev], eax
mov [edi+list_fd], eax
mov [edi+list_bk], eax
mov [edi+block_base], HEAP_BASE
mov [edi+block_size], 4096*sizeof.MEM_BLOCK
mov [edi+block_flags], USED_BLOCK
 
mov [ecx+block_next], eax
mov [ecx+block_prev], ebx
mov [ecx+list_fd], eax
mov [ecx+list_bk], eax
mov [ecx+block_base], eax
mov [ecx+block_size], eax
mov [ecx+block_flags], USED_BLOCK
 
mov [ebx+block_next], ecx
mov [ebx+block_prev], edi
mov [ebx+block_base], HEAP_BASE+4096*sizeof.MEM_BLOCK
 
mov ecx, [pg_data.kernel_pages]
shl ecx, 12
sub ecx, HEAP_BASE-OS_BASE+4096*sizeof.MEM_BLOCK
mov [heap_size], ecx
mov [heap_free], ecx
mov [ebx+block_size], ecx
mov [ebx+block_flags], FREE_BLOCK
 
mov [mem_block_mask], eax
mov [mem_block_mask+4], 0x80000000
 
mov ecx, mem_block_list+63*8
list_add ebx, ecx
 
mov ecx, 4096-3-1
mov eax, HEAP_BASE+sizeof.MEM_BLOCK*4
 
mov [next_memblock], HEAP_BASE+sizeof.MEM_BLOCK *3
@@:
mov [eax-sizeof.MEM_BLOCK], eax
add eax, sizeof.MEM_BLOCK
loop @B
 
mov [eax-sizeof.MEM_BLOCK], dword 0
 
mov ecx, heap_mutex
call mutex_init
mov [heap_blocks], 4094
mov [free_blocks], 4093
ret
endp
 
; param
; eax= required size
;
; retval
; edi= memory block descriptor
; ebx= descriptor index
 
align 4
get_small_block:
mov ecx, eax
shr ecx, 12
dec ecx
cmp ecx, 63
jle .get_index
mov ecx, 63
.get_index:
lea esi, [mem_block_mask]
xor ebx, ebx
or edx, -1
 
cmp ecx, 32
jb .bit_test
 
sub ecx, 32
add ebx, 32
add esi, 4
.bit_test:
shl edx, cl
and edx, [esi]
.find:
bsf edi, edx
jz .high_mask
add ebx, edi
lea ecx, [mem_block_list+ebx*8]
mov edi, ecx
.next:
mov edi, [edi+list_fd]
cmp edi, ecx
je .err
cmp eax, [edi+block_size]
ja .next
ret
.err:
xor edi, edi
ret
 
.high_mask:
add esi, 4
cmp esi, mem_block_mask+8
jae .err
add ebx, 32
mov edx, [esi]
jmp .find
 
 
align 4
free_mem_block:
mov ebx, [next_memblock]
mov [eax], ebx
mov [next_memblock], eax
xor ebx, ebx
 
mov dword [eax+4], ebx
mov dword [eax+8], ebx
mov dword [eax+12], ebx
mov dword [eax+16], ebx
; mov dword [eax+20], 0 ;don't clear block size
mov dword [eax+24], ebx
mov dword [eax+28], ebx
inc [free_blocks]
ret
 
align 4
proc alloc_kernel_space stdcall, size:dword
local block_ind:DWORD
 
push ebx
push esi
push edi
 
mov eax, [size]
add eax, 4095
and eax, not 4095
mov [size], eax
 
cmp eax, [heap_free]
ja .error
 
mov ecx, heap_mutex
call mutex_lock
 
mov eax, [size]
 
call get_small_block ; eax
test edi, edi
jz .error_unlock
 
cmp [edi+block_flags], FREE_BLOCK
jne .error_unlock
 
mov [block_ind], ebx ;index of allocated block
 
mov eax, [edi+block_size]
cmp eax, [size]
je .m_eq_size
 
mov esi, [next_memblock] ;new memory block
test esi, esi
jz .error_unlock
 
dec [free_blocks]
mov eax, [esi]
mov [next_memblock], eax
 
mov [esi+block_next], edi
mov eax, [edi+block_prev]
mov [esi+block_prev], eax
mov [edi+block_prev], esi
mov [esi+list_fd], 0
mov [esi+list_bk], 0
mov [eax+block_next], esi
 
mov ebx, [edi+block_base]
mov [esi+block_base], ebx
mov edx, [size]
mov [esi+block_size], edx
add [edi+block_base], edx
sub [edi+block_size], edx
 
mov eax, [edi+block_size]
calc_index eax
cmp eax, [block_ind]
je .add_used
 
list_del edi
 
mov ecx, [block_ind]
lea edx, [mem_block_list+ecx*8]
cmp edx, [edx]
jnz @f
btr [mem_block_mask], ecx
@@:
bts [mem_block_mask], eax
lea edx, [mem_block_list+eax*8] ;edx= list head
list_add edi, edx
.add_used:
 
call md.add_to_used
 
mov ecx, heap_mutex
call mutex_unlock
mov eax, [esi+block_base]
pop edi
pop esi
pop ebx
ret
 
.m_eq_size:
list_del edi
lea edx, [mem_block_list+ebx*8]
cmp edx, [edx]
jnz @f
btr [mem_block_mask], ebx
@@:
mov esi, edi
jmp .add_used
 
.error_unlock:
mov ecx, heap_mutex
call mutex_unlock
.error:
xor eax, eax
pop edi
pop esi
pop ebx
ret
endp
 
align 4
proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword
 
mov ecx, heap_mutex
call mutex_lock
 
mov eax, [base]
 
call md.del_from_used
test esi, esi
jz .fail
 
mov eax, [esi+block_size]
add [heap_free], eax
 
mov edi, [esi+block_next]
cmp [edi+block_flags], FREE_BLOCK
jne .prev
 
list_del edi
 
mov edx, [edi+block_next]
mov [esi+block_next], edx
mov [edx+block_prev], esi
mov ecx, [edi+block_size]
add [esi+block_size], ecx
 
calc_index ecx
 
lea edx, [mem_block_list+ecx*8]
cmp edx, [edx]
jne @F
btr [mem_block_mask], ecx
@@:
mov eax, edi
call free_mem_block
.prev:
mov edi, [esi+block_prev]
cmp [edi+block_flags], FREE_BLOCK
jne .insert
 
mov edx, [esi+block_next]
mov [edi+block_next], edx
mov [edx+block_prev], edi
 
mov eax, esi
call free_mem_block
 
mov ecx, [edi+block_size]
mov eax, [esi+block_size]
add eax, ecx
mov [edi+block_size], eax
 
calc_index eax ;new index
calc_index ecx ;old index
cmp eax, ecx
je .m_eq
 
push ecx
list_del edi
pop ecx
 
lea edx, [mem_block_list+ecx*8]
cmp edx, [edx]
jne .add_block
btr [mem_block_mask], ecx
 
.add_block:
bts [mem_block_mask], eax
lea edx, [mem_block_list+eax*8]
list_add edi, edx
.m_eq:
mov ecx, heap_mutex
call mutex_unlock
xor eax, eax
not eax
ret
.insert:
mov [esi+block_flags], FREE_BLOCK
mov eax, [esi+block_size]
calc_index eax
mov edi, esi
jmp .add_block
 
.fail:
mov ecx, heap_mutex
call mutex_unlock
xor eax, eax
ret
endp
 
align 4
proc kernel_alloc stdcall, size:dword
locals
lin_addr dd ?
pages_count dd ?
endl
 
push ebx
push edi
 
mov eax, [size]
add eax, 4095
and eax, not 4095;
mov [size], eax
and eax, eax
jz .err
mov ebx, eax
shr ebx, 12
mov [pages_count], ebx
 
stdcall alloc_kernel_space, eax
test eax, eax
jz .err
mov [lin_addr], eax
 
mov ecx, [pages_count]
mov edx, eax
mov ebx, ecx
 
shr ecx, 3
jz .next
 
and ebx, not 7
push ebx
stdcall alloc_pages, ebx
pop ecx ; yes ecx!!!
and eax, eax
jz .err
 
mov edi, eax
mov edx, [lin_addr]
@@:
stdcall map_page, edx, edi, dword PG_SW
add edx, 0x1000
add edi, 0x1000
dec ecx
jnz @B
.next:
mov ecx, [pages_count]
and ecx, 7
jz .end
@@:
push ecx
call alloc_page
pop ecx
test eax, eax
jz .err
 
stdcall map_page, edx, eax, dword PG_SW
add edx, 0x1000
dec ecx
jnz @B
.end:
mov eax, [lin_addr]
pop edi
pop ebx
ret
.err:
xor eax, eax
pop edi
pop ebx
ret
endp
 
align 4
proc kernel_free stdcall, base:dword
 
push ebx esi
 
mov ecx, heap_mutex
call mutex_lock
 
mov eax, [base]
call md.find_used
 
mov ecx, heap_mutex
cmp [esi+block_flags], USED_BLOCK
jne .fail
 
call mutex_unlock
 
mov eax, [esi+block_base]
mov ecx, [esi+block_size]
shr ecx, 12
call release_pages ;eax, ecx
stdcall free_kernel_space, [base]
pop esi ebx
ret
.fail:
call mutex_unlock
xor eax, eax
pop esi ebx
ret
endp
 
restore block_next
restore block_prev
restore block_list
restore block_base
restore block_size
restore block_flags
 
;;;;;;;;;;;;;; USER ;;;;;;;;;;;;;;;;;
 
HEAP_TOP equ 0x80000000
 
align 4
proc init_heap
 
mov ebx, [current_slot]
mov eax, [ebx+APPDATA.heap_top]
test eax, eax
jz @F
sub eax, [ebx+APPDATA.heap_base]
sub eax, 4096
ret
@@:
mov esi, [ebx+APPDATA.mem_size]
add esi, 4095
and esi, not 4095
mov [ebx+APPDATA.mem_size], esi
mov eax, HEAP_TOP
mov [ebx+APPDATA.heap_base], esi
mov [ebx+APPDATA.heap_top], eax
 
sub eax, esi
shr esi, 10
mov ecx, eax
sub eax, 4096
or ecx, FREE_BLOCK
mov [page_tabs+esi], ecx
ret
endp
 
align 4
proc user_alloc stdcall, alloc_size:dword
 
push ebx
push esi
push edi
 
mov ecx, [alloc_size]
add ecx, (4095+4096)
and ecx, not 4095
 
mov ebx, [current_slot]
mov esi, dword [ebx+APPDATA.heap_base] ; heap_base
mov edi, dword [ebx+APPDATA.heap_top] ; heap_top
l_0:
cmp esi, edi
jae m_exit
 
mov ebx, esi
shr ebx, 12
mov eax, [page_tabs+ebx*4]
test al, FREE_BLOCK
jz test_used
and eax, 0xFFFFF000
cmp eax, ecx ;alloc_size
jb m_next
jz @f
 
lea edx, [esi+ecx]
sub eax, ecx
or al, FREE_BLOCK
shr edx, 12
mov [page_tabs+edx*4], eax
@@:
or ecx, USED_BLOCK
mov [page_tabs+ebx*4], ecx
shr ecx, 12
inc ebx
dec ecx
jz .no
@@:
mov dword [page_tabs+ebx*4], 2
inc ebx
dec ecx
jnz @B
.no:
 
mov edx, [current_slot]
mov ebx, [alloc_size]
add ebx, 0xFFF
and ebx, not 0xFFF
add ebx, [edx+APPDATA.mem_size]
call update_mem_size
 
lea eax, [esi+4096]
 
pop edi
pop esi
pop ebx
ret
test_used:
test al, USED_BLOCK
jz m_exit
 
and eax, 0xFFFFF000
m_next:
add esi, eax
jmp l_0
m_exit:
xor eax, eax
pop edi
pop esi
pop ebx
ret
endp
 
align 4
proc user_alloc_at stdcall, address:dword, alloc_size:dword
 
push ebx
push esi
push edi
 
mov ebx, [current_slot]
mov edx, [address]
and edx, not 0xFFF
mov [address], edx
sub edx, 0x1000
jb .error
mov esi, [ebx+APPDATA.heap_base]
mov edi, [ebx+APPDATA.heap_top]
cmp edx, esi
jb .error
.scan:
cmp esi, edi
jae .error
mov ebx, esi
shr ebx, 12
mov eax, [page_tabs+ebx*4]
mov ecx, eax
and ecx, 0xFFFFF000
add ecx, esi
cmp edx, ecx
jb .found
mov esi, ecx
jmp .scan
.error:
xor eax, eax
pop edi
pop esi
pop ebx
ret
.found:
test al, FREE_BLOCK
jz .error
mov eax, ecx
sub eax, edx
sub eax, 0x1000
cmp eax, [alloc_size]
jb .error
 
; Here we have 1 big free block which includes requested area.
; In general, 3 other blocks must be created instead:
; free at [esi, edx);
; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000));
; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx)
; First or third block (or both) may be absent.
mov eax, edx
sub eax, esi
jz .nofirst
or al, FREE_BLOCK
mov [page_tabs+ebx*4], eax
.nofirst:
mov eax, [alloc_size]
add eax, 0x1FFF
and eax, not 0xFFF
mov ebx, edx
add edx, eax
shr ebx, 12
or al, USED_BLOCK
mov [page_tabs+ebx*4], eax
shr eax, 12
dec eax
jz .second_nofill
inc ebx
.fill:
mov dword [page_tabs+ebx*4], 2
inc ebx
dec eax
jnz .fill
 
.second_nofill:
sub ecx, edx
jz .nothird
or cl, FREE_BLOCK
mov [page_tabs+ebx*4], ecx
 
.nothird:
 
mov edx, [current_slot]
mov ebx, [alloc_size]
add ebx, 0xFFF
and ebx, not 0xFFF
add ebx, [edx+APPDATA.mem_size]
call update_mem_size
 
mov eax, [address]
 
pop edi
pop esi
pop ebx
ret
endp
 
align 4
proc user_free stdcall, base:dword
 
push esi
 
mov esi, [base]
test esi, esi
jz .exit
 
push ebx
 
xor ebx, ebx
shr esi, 12
mov eax, [page_tabs+(esi-1)*4]
test al, USED_BLOCK
jz .cantfree
test al, DONT_FREE_BLOCK
jnz .cantfree
 
and eax, not 4095
mov ecx, eax
or al, FREE_BLOCK
mov [page_tabs+(esi-1)*4], eax
sub ecx, 4096
mov ebx, ecx
shr ecx, 12
jz .released
.release:
xor eax, eax
xchg eax, [page_tabs+esi*4]
test al, 1
jz @F
test eax, PG_SHARED
jnz @F
call free_page
mov eax, esi
shl eax, 12
invlpg [eax]
@@:
inc esi
dec ecx
jnz .release
 
.released:
push edi
 
mov edx, [current_slot]
mov esi, dword [edx+APPDATA.heap_base]
mov edi, dword [edx+APPDATA.heap_top]
sub ebx, [edx+APPDATA.mem_size]
neg ebx
call update_mem_size
call user_normalize
pop edi
pop ebx
pop esi
ret
.exit:
xor eax, eax
inc eax
pop esi
ret
.cantfree:
xor eax, eax
pop ebx
pop esi
ret
endp
 
 
align 4
proc user_unmap stdcall, base:dword, offset:dword, size:dword
 
push ebx
 
mov ebx, [base] ; must be valid pointer
test ebx, ebx
jz .error
 
mov edx, [offset] ; check offset
add edx, ebx ; must be below 2Gb app limit
js .error
 
shr ebx, 12 ; chek block attributes
lea ebx, [page_tabs+ebx*4]
mov eax, [ebx-4] ; block attributes
test al, USED_BLOCK
jz .error
test al, DONT_FREE_BLOCK
jnz .error
 
shr edx, 12
lea edx, [page_tabs+edx*4] ; unmap offset
 
mov ecx, [size]
add ecx, 4095
shr ecx, 12 ; unmap size in pages
 
shr eax, 12 ; block size + 1 page
lea ebx, [ebx+eax*4-4] ; block end ptr
lea eax, [edx+ecx*4] ; unmap end ptr
 
cmp eax, ebx ; check for overflow
ja .error
 
mov ebx, [offset]
and ebx, not 4095 ; is it required ?
 
.unmap:
mov eax, [edx] ; get page addres
test al, 1 ; page mapped ?
jz @F
test eax, PG_SHARED ; page shared ?
jnz @F
mov [page_tabs+edx*4], dword 2
; mark page as reserved
invlpg [ebx] ; when we start using
call free_page ; empty c-o-w page instead this ?
@@:
add ebx, 4096
add edx, 4
dec ecx
jnz .unmap
 
pop ebx
or al, 1 ; return non zero on success
ret
.error:
pop ebx
xor eax, eax ; something wrong
ret
endp
 
align 4
user_normalize:
; in: esi=heap_base, edi=heap_top
; out: eax=0 <=> OK
; destroys: ebx,edx,esi,edi
shr esi, 12
shr edi, 12
@@:
mov eax, [page_tabs+esi*4]
test al, USED_BLOCK
jz .test_free
shr eax, 12
add esi, eax
jmp @B
.test_free:
test al, FREE_BLOCK
jz .err
mov edx, eax
shr edx, 12
add edx, esi
cmp edx, edi
jae .exit
 
mov ebx, [page_tabs+edx*4]
test bl, USED_BLOCK
jz .next_free
 
shr ebx, 12
add edx, ebx
mov esi, edx
jmp @B
.next_free:
test bl, FREE_BLOCK
jz .err
and dword [page_tabs+edx*4], 0
add eax, ebx
and eax, not 4095
or eax, FREE_BLOCK
mov [page_tabs+esi*4], eax
jmp @B
.exit:
xor eax, eax
inc eax
ret
.err:
xor eax, eax
ret
 
user_realloc:
; in: eax = pointer, ebx = new size
; out: eax = new pointer or NULL
test eax, eax
jnz @f
; realloc(NULL,sz) - same as malloc(sz)
push ebx
call user_alloc
ret
@@:
push ecx edx
lea ecx, [eax - 0x1000]
shr ecx, 12
mov edx, [page_tabs+ecx*4]
test dl, USED_BLOCK
jnz @f
; attempt to realloc invalid pointer
.ret0:
pop edx ecx
xor eax, eax
ret
@@:
test dl, DONT_FREE_BLOCK
jnz .ret0
add ebx, 0x1FFF
shr edx, 12
shr ebx, 12
; edx = allocated size, ebx = new size
add edx, ecx
add ebx, ecx
cmp edx, ebx
jb .realloc_add
; release part of allocated memory
.loop:
cmp edx, ebx
jz .release_done
dec edx
xor eax, eax
xchg eax, [page_tabs+edx*4]
test al, 1
jz .loop
call free_page
mov eax, edx
shl eax, 12
invlpg [eax]
jmp .loop
.release_done:
sub ebx, ecx
cmp ebx, 1
jnz .nofreeall
mov eax, [page_tabs+ecx*4]
and eax, not 0xFFF
mov edx, [current_slot]
mov ebx, [APPDATA.mem_size+edx]
sub ebx, eax
add ebx, 0x1000
or al, FREE_BLOCK
mov [page_tabs+ecx*4], eax
push esi edi
mov esi, [APPDATA.heap_base+edx]
mov edi, [APPDATA.heap_top+edx]
call update_mem_size
call user_normalize
pop edi esi
jmp .ret0 ; all freed
.nofreeall:
sub edx, ecx
shl ebx, 12
or ebx, USED_BLOCK
xchg [page_tabs+ecx*4], ebx
shr ebx, 12
sub ebx, edx
push ebx ecx edx
mov edx, [current_slot]
shl ebx, 12
sub ebx, [APPDATA.mem_size+edx]
neg ebx
call update_mem_size
pop edx ecx ebx
lea eax, [ecx+1]
shl eax, 12
push eax
add ecx, edx
lea edx, [ecx+ebx]
shl ebx, 12
jz .ret
push esi
mov esi, [current_slot]
mov esi, [APPDATA.heap_top+esi]
shr esi, 12
@@:
cmp edx, esi
jae .merge_done
mov eax, [page_tabs+edx*4]
test al, USED_BLOCK
jnz .merge_done
and dword [page_tabs+edx*4], 0
shr eax, 12
add edx, eax
shl eax, 12
add ebx, eax
jmp @b
.merge_done:
pop esi
or ebx, FREE_BLOCK
mov [page_tabs+ecx*4], ebx
.ret:
pop eax edx ecx
ret
.realloc_add:
; get some additional memory
mov eax, [current_slot]
mov eax, [APPDATA.heap_top+eax]
shr eax, 12
cmp edx, eax
jae .cant_inplace
mov eax, [page_tabs+edx*4]
test al, FREE_BLOCK
jz .cant_inplace
shr eax, 12
add eax, edx
sub eax, ebx
jb .cant_inplace
jz @f
shl eax, 12
or al, FREE_BLOCK
mov [page_tabs+ebx*4], eax
@@:
mov eax, ebx
sub eax, ecx
shl eax, 12
or al, USED_BLOCK
mov [page_tabs+ecx*4], eax
lea eax, [ecx+1]
shl eax, 12
push eax
push edi
lea edi, [page_tabs+edx*4]
mov eax, 2
sub ebx, edx
mov ecx, ebx
cld
rep stosd
pop edi
mov edx, [current_slot]
shl ebx, 12
add ebx, [APPDATA.mem_size+edx]
call update_mem_size
pop eax edx ecx
ret
.cant_inplace:
push esi edi
mov eax, [current_slot]
mov esi, [APPDATA.heap_base+eax]
mov edi, [APPDATA.heap_top+eax]
shr esi, 12
shr edi, 12
sub ebx, ecx
.find_place:
cmp esi, edi
jae .place_not_found
mov eax, [page_tabs+esi*4]
test al, FREE_BLOCK
jz .next_place
shr eax, 12
cmp eax, ebx
jae .place_found
add esi, eax
jmp .find_place
.next_place:
shr eax, 12
add esi, eax
jmp .find_place
.place_not_found:
pop edi esi
jmp .ret0
.place_found:
sub eax, ebx
jz @f
push esi
add esi, ebx
shl eax, 12
or al, FREE_BLOCK
mov [page_tabs+esi*4], eax
pop esi
@@:
mov eax, ebx
shl eax, 12
or al, USED_BLOCK
mov [page_tabs+esi*4], eax
inc esi
mov eax, esi
shl eax, 12
push eax
mov eax, [page_tabs+ecx*4]
and eax, not 0xFFF
or al, FREE_BLOCK
sub edx, ecx
mov [page_tabs+ecx*4], eax
inc ecx
dec ebx
dec edx
jz .no
@@:
xor eax, eax
xchg eax, [page_tabs+ecx*4]
mov [page_tabs+esi*4], eax
mov eax, ecx
shl eax, 12
invlpg [eax]
inc esi
inc ecx
dec ebx
dec edx
jnz @b
.no:
push ebx
mov edx, [current_slot]
shl ebx, 12
add ebx, [APPDATA.mem_size+edx]
call update_mem_size
pop ebx
@@:
mov dword [page_tabs+esi*4], 2
inc esi
dec ebx
jnz @b
pop eax edi esi edx ecx
ret
 
if 0
align 4
proc alloc_dll
pushf
cli
bsf eax, [dll_map]
jnz .find
popf
xor eax, eax
ret
.find:
btr [dll_map], eax
popf
shl eax, 5
add eax, dll_tab
ret
endp
 
align 4
proc alloc_service
pushf
cli
bsf eax, [srv_map]
jnz .find
popf
xor eax, eax
ret
.find:
btr [srv_map], eax
popf
shl eax, 0x02
lea eax, [srv_tab+eax+eax*8] ;srv_tab+eax*36
ret
endp
 
end if
 
 
;;;;;;;;;;;;;; SHARED ;;;;;;;;;;;;;;;;;
 
 
; param
; eax= shm_map object
 
align 4
destroy_smap:
 
pushfd
cli
 
push esi
push edi
 
mov edi, eax
mov esi, [eax+SMAP.parent]
test esi, esi
jz .done
 
lock dec [esi+SMEM.refcount]
jnz .done
 
mov ecx, [esi+SMEM.bk]
mov edx, [esi+SMEM.fd]
 
mov [ecx+SMEM.fd], edx
mov [edx+SMEM.bk], ecx
 
stdcall kernel_free, [esi+SMEM.base]
mov eax, esi
call free
.done:
mov eax, edi
call destroy_kernel_object
 
pop edi
pop esi
popfd
 
ret
 
E_NOTFOUND equ 5
E_ACCESS equ 10
E_NOMEM equ 30
E_PARAM equ 33
 
SHM_READ equ 0
SHM_WRITE equ 1
 
SHM_ACCESS_MASK equ 3
 
SHM_OPEN equ (0 shl 2)
SHM_OPEN_ALWAYS equ (1 shl 2)
SHM_CREATE equ (2 shl 2)
 
SHM_OPEN_MASK equ (3 shl 2)
 
align 4
proc shmem_open stdcall name:dword, size:dword, access:dword
locals
action dd ?
owner_access dd ?
mapped dd ?
endl
 
push ebx
push esi
push edi
 
mov [mapped], 0
mov [owner_access], 0
 
pushfd ;mutex required
cli
 
mov eax, [access]
and eax, SHM_OPEN_MASK
mov [action], eax
 
mov ebx, [name]
test ebx, ebx
mov edx, E_PARAM
jz .fail
 
mov esi, [shmem_list.fd]
align 4
@@:
cmp esi, shmem_list
je .not_found
 
lea edx, [esi+SMEM.name]; link , base, size
stdcall strncmp, edx, ebx, 32
test eax, eax
je .found
 
mov esi, [esi+SMEM.fd]
jmp @B
 
.not_found:
mov eax, [action]
 
cmp eax, SHM_OPEN
mov edx, E_NOTFOUND
je .fail
 
cmp eax, SHM_CREATE
mov edx, E_PARAM
je .create_shm
 
cmp eax, SHM_OPEN_ALWAYS
jne .fail
 
.create_shm:
 
mov ecx, [size]
test ecx, ecx
jz .fail
 
add ecx, 4095
and ecx, -4096
mov [size], ecx
 
mov eax, sizeof.SMEM
call malloc
test eax, eax
mov esi, eax
mov edx, E_NOMEM
jz .fail
 
stdcall kernel_alloc, [size]
test eax, eax
mov [mapped], eax
mov edx, E_NOMEM
jz .cleanup
 
mov ecx, [size]
mov edx, [access]
and edx, SHM_ACCESS_MASK
 
mov [esi+SMEM.base], eax
mov [esi+SMEM.size], ecx
mov [esi+SMEM.access], edx
mov [esi+SMEM.refcount], 0
mov [esi+SMEM.name+28], 0
 
lea eax, [esi+SMEM.name]
stdcall strncpy, eax, [name], 31
 
mov eax, [shmem_list.fd]
mov [esi+SMEM.bk], shmem_list
mov [esi+SMEM.fd], eax
 
mov [eax+SMEM.bk], esi
mov [shmem_list.fd], esi
 
mov [action], SHM_OPEN
mov [owner_access], SHM_WRITE
 
.found:
mov eax, [action]
 
cmp eax, SHM_CREATE
mov edx, E_ACCESS
je .exit
 
cmp eax, SHM_OPEN
mov edx, E_PARAM
je .create_map
 
cmp eax, SHM_OPEN_ALWAYS
jne .fail
 
.create_map:
 
mov eax, [access]
and eax, SHM_ACCESS_MASK
cmp eax, [esi+SMEM.access]
mov [access], eax
mov edx, E_ACCESS
ja .fail
 
mov ebx, [CURRENT_TASK]
shl ebx, 5
mov ebx, [CURRENT_TASK+ebx+4]
mov eax, sizeof.SMAP
 
call create_kernel_object
test eax, eax
mov edi, eax
mov edx, E_NOMEM
jz .fail
 
inc [esi+SMEM.refcount]
 
mov [edi+SMAP.magic], 'SMAP'
mov [edi+SMAP.destroy], destroy_smap
mov [edi+SMAP.parent], esi
mov [edi+SMAP.base], 0
 
stdcall user_alloc, [esi+SMEM.size]
test eax, eax
mov [mapped], eax
mov edx, E_NOMEM
jz .cleanup2
 
mov [edi+SMAP.base], eax
 
mov ecx, [esi+SMEM.size]
mov [size], ecx
 
shr ecx, 12
shr eax, 10
 
mov esi, [esi+SMEM.base]
shr esi, 10
lea edi, [page_tabs+eax]
add esi, page_tabs
 
mov edx, [access]
or edx, [owner_access]
shl edx, 1
or edx, PG_USER+PG_SHARED
@@:
lodsd
and eax, 0xFFFFF000
or eax, edx
stosd
loop @B
 
xor edx, edx
 
cmp [owner_access], 0
jne .fail
.exit:
mov edx, [size]
.fail:
mov eax, [mapped]
 
popfd
pop edi
pop esi
pop ebx
ret
.cleanup:
mov [size], edx
mov eax, esi
call free
jmp .exit
 
.cleanup2:
mov [size], edx
mov eax, edi
call destroy_smap
jmp .exit
endp
 
align 4
proc shmem_close stdcall, name:dword
 
mov eax, [name]
test eax, eax
jz .fail
 
push esi
push edi
pushfd
cli
 
mov esi, [current_slot]
add esi, APP_OBJ_OFFSET
.next:
mov eax, [esi+APPOBJ.fd]
test eax, eax
jz @F
 
cmp eax, esi
mov esi, eax
je @F
 
cmp [eax+SMAP.magic], 'SMAP'
jne .next
 
mov edi, [eax+SMAP.parent]
test edi, edi
jz .next
 
lea edi, [edi+SMEM.name]
stdcall strncmp, [name], edi, 32
test eax, eax
jne .next
 
stdcall user_free, [esi+SMAP.base]
 
mov eax, esi
call [esi+APPOBJ.destroy]
@@:
popfd
pop edi
pop esi
.fail:
ret
endp
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/peload.inc
0,0 → 1,341
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
include 'export.inc'
 
align 4
 
proc load_PE stdcall, file_name:dword
locals
image dd ?
entry dd ?
base dd ?
endl
 
stdcall load_file, [file_name]
test eax, eax
jz .fail
 
mov [image], eax
 
mov edx, [eax+60]
 
stdcall kernel_alloc, [eax+80+edx]
test eax, eax
jz .cleanup
 
mov [base], eax
 
stdcall map_PE, eax, [image]
 
mov [entry], eax
test eax, eax
jnz .cleanup
 
stdcall kernel_free, [base]
.cleanup:
stdcall kernel_free, [image]
mov eax, [entry]
ret
.fail:
xor eax, eax
ret
endp
 
DWORD equ dword
PTR equ
 
align 4
map_PE: ;stdcall base:dword, image:dword
cld
push ebp
push edi
push esi
push ebx
sub esp, 60
mov ebx, DWORD PTR [esp+84]
mov ebp, DWORD PTR [esp+80]
mov edx, ebx
mov esi, ebx
add edx, DWORD PTR [ebx+60]
mov edi, ebp
mov DWORD PTR [esp+32], edx
mov ecx, DWORD PTR [edx+84]
 
shr ecx, 2
rep movsd
 
movzx eax, WORD PTR [edx+6]
mov DWORD PTR [esp+36], 0
mov DWORD PTR [esp+16], eax
jmp L2
L3:
mov eax, DWORD PTR [edx+264]
test eax, eax
je L4
mov esi, ebx
mov edi, ebp
add esi, DWORD PTR [edx+268]
mov ecx, eax
add edi, DWORD PTR [edx+260]
 
shr ecx, 2
rep movsd
 
L4:
mov ecx, DWORD PTR [edx+256]
add ecx, 4095
and ecx, -4096
cmp ecx, eax
jbe L6
sub ecx, eax
add eax, DWORD PTR [edx+260]
lea edi, [eax+ebp]
 
xor eax, eax
rep stosb
 
L6:
inc DWORD PTR [esp+36]
add edx, 40
L2:
mov esi, DWORD PTR [esp+16]
cmp DWORD PTR [esp+36], esi
jne L3
mov edi, DWORD PTR [esp+32]
cmp DWORD PTR [edi+164], 0
je L9
mov esi, ebp
mov ecx, ebp
sub esi, DWORD PTR [edi+52]
add ecx, DWORD PTR [edi+160]
mov eax, esi
shr eax, 16
mov DWORD PTR [esp+12], eax
jmp L11
L12:
lea ebx, [eax-8]
xor edi, edi
shr ebx, 1
jmp L13
L14:
movzx eax, WORD PTR [ecx+8+edi*2]
mov edx, eax
shr eax, 12
and edx, 4095
add edx, DWORD PTR [ecx]
cmp ax, 2
je L17
cmp ax, 3
je L18
dec ax
jne L15
mov eax, DWORD PTR [esp+12]
add WORD PTR [edx+ebp], ax
L17:
add WORD PTR [edx+ebp], si
L18:
add DWORD PTR [edx+ebp], esi
L15:
inc edi
L13:
cmp edi, ebx
jne L14
add ecx, DWORD PTR [ecx+4]
L11:
mov eax, DWORD PTR [ecx+4]
test eax, eax
jne L12
L9:
mov edx, DWORD PTR [esp+32]
cmp DWORD PTR [edx+132], 0
je L20
mov eax, ebp
add eax, DWORD PTR [edx+128]
mov DWORD PTR [esp+40], 0
add eax, 20
mov DWORD PTR [esp+56], eax
L22:
mov ecx, DWORD PTR [esp+56]
cmp DWORD PTR [ecx-16], 0
jne L23
cmp DWORD PTR [ecx-8], 0
je L25
L23:
mov edi, DWORD PTR [__exports+32]
mov esi, DWORD PTR [__exports+28]
mov eax, DWORD PTR [esp+56]
mov DWORD PTR [esp+20], edi
add edi, OS_BASE
add esi, OS_BASE
mov DWORD PTR [esp+44], esi
mov ecx, DWORD PTR [eax-4]
mov DWORD PTR [esp+48], edi
mov edx, DWORD PTR [eax-20]
mov DWORD PTR [esp+52], 0
add ecx, ebp
add edx, ebp
mov DWORD PTR [esp+24], edx
mov DWORD PTR [esp+28], ecx
L26:
mov esi, DWORD PTR [esp+52]
mov edi, DWORD PTR [esp+24]
mov eax, DWORD PTR [edi+esi*4]
test eax, eax
je L27
test eax, eax
js L27
lea edi, [ebp+eax]
mov eax, DWORD PTR [esp+28]
mov DWORD PTR [eax+esi*4], 0
lea esi, [edi+2]
push eax
push 32
movzx eax, WORD PTR [edi]
mov edx, DWORD PTR [esp+56]
mov eax, DWORD PTR [edx+eax*4]
add eax, OS_BASE
push eax
push esi
call strncmp
pop ebx
xor ebx, ebx
test eax, eax
jne L32
jmp L30
L33:
push ecx
push 32
mov ecx, DWORD PTR [esp+28]
mov eax, DWORD PTR [ecx+OS_BASE+ebx*4]
add eax, OS_BASE
push eax
push esi
call strncmp
pop edx
test eax, eax
jne L34
mov esi, DWORD PTR [esp+44]
mov edx, DWORD PTR [esp+52]
mov ecx, DWORD PTR [esp+28]
mov eax, DWORD PTR [esi+ebx*4]
add eax, OS_BASE
mov DWORD PTR [ecx+edx*4], eax
jmp L36
L34:
inc ebx
L32:
cmp ebx, DWORD PTR [__exports+24]
jb L33
L36:
cmp ebx, DWORD PTR [__exports+24]
jne L37
 
mov esi, msg_unresolved
call sys_msg_board_str
lea esi, [edi+2]
call sys_msg_board_str
mov esi, msg_CR
call sys_msg_board_str
 
mov DWORD PTR [esp+40], 1
jmp L37
L30:
movzx eax, WORD PTR [edi]
mov esi, DWORD PTR [esp+44]
mov edi, DWORD PTR [esp+52]
mov edx, DWORD PTR [esp+28]
mov eax, DWORD PTR [esi+eax*4]
add eax, OS_BASE
mov DWORD PTR [edx+edi*4], eax
L37:
inc DWORD PTR [esp+52]
jmp L26
L27:
add DWORD PTR [esp+56], 20
jmp L22
L25:
xor eax, eax
cmp DWORD PTR [esp+40], 0
jne L40
L20:
mov ecx, DWORD PTR [esp+32]
mov eax, ebp
add eax, DWORD PTR [ecx+40]
L40:
add esp, 60
pop ebx
pop esi
pop edi
pop ebp
ret 8
 
align 16
__exports:
export 'KERNEL', \
alloc_kernel_space, 'AllocKernelSpace', \ ; stdcall
alloc_page, 'AllocPage', \ ; gcc ABI
alloc_pages, 'AllocPages', \ ; stdcall
commit_pages, 'CommitPages', \ ; eax, ebx, ecx
\
disk_add, 'DiskAdd', \ ;stdcall
disk_media_changed, 'DiskMediaChanged', \ ;stdcall
\
create_event, 'CreateEvent', \ ; ecx, esi
destroy_event, 'DestroyEvent', \ ;
raise_event, 'RaiseEvent', \ ; eax, ebx, edx, esi
wait_event, 'WaitEvent', \ ; eax, ebx
wait_event_timeout, 'WaitEventTimeout', \ ; eax, ebx, ecx
get_event_ex, 'GetEvent', \ ; edi
\
create_kernel_object, 'CreateObject', \
create_ring_buffer, 'CreateRingBuffer', \ ; stdcall
destroy_kernel_object, 'DestroyObject', \
free_kernel_space, 'FreeKernelSpace', \ ; stdcall
free_page, 'FreePage', \ ; eax
kernel_alloc, 'KernelAlloc', \ ; stdcall
kernel_free, 'KernelFree', \ ; stdcall
malloc, 'Kmalloc', \
free, 'Kfree', \
map_io_mem, 'MapIoMem', \ ; stdcall
map_page, 'MapPage', \ ; stdcall
get_pg_addr, 'GetPgAddr', \ ; eax
\
mutex_init, 'MutexInit', \ ; gcc fastcall
mutex_lock, 'MutexLock', \ ; gcc fastcall
mutex_unlock, 'MutexUnlock', \ ; gcc fastcall
\
get_display, 'GetDisplay', \
set_screen, 'SetScreen', \
window._.get_rect, 'GetWindowRect', \ ; gcc fastcall
pci_api_drv, 'PciApi', \
pci_read8, 'PciRead8', \ ; stdcall
pci_read16, 'PciRead16', \ ; stdcall
pci_read32, 'PciRead32', \ ; stdcall
pci_write8, 'PciWrite8', \ ; stdcall
pci_write16, 'PciWrite16', \ ; stdcall
pci_write32, 'PciWrite32', \ ; stdcall
\
get_pid, 'GetPid', \
get_service, 'GetService', \ ;
reg_service, 'RegService', \ ; stdcall
attach_int_handler, 'AttachIntHandler', \ ; stdcall
user_alloc, 'UserAlloc', \ ; stdcall
user_free, 'UserFree', \ ; stdcall
unmap_pages, 'UnmapPages', \ ; eax, ecx
sys_msg_board_str, 'SysMsgBoardStr', \
get_timer_ticks, 'GetTimerTicks', \
get_stack_base, 'GetStackBase', \
delay_hs, 'Delay', \ ; ebx
set_mouse_data, 'SetMouseData', \ ;
set_keyboard_data, 'SetKeyboardData', \ ; gcc fastcall
timer_hs, 'TimerHs' ; stdcall
 
 
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/v86.inc
0,0 → 1,923
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2007-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
; Virtual-8086 mode manager
; diamond, 2007, 2008
 
DEBUG_SHOW_IO = 0
 
struct V86_machine
; page directory
pagedir dd ?
; translation table: V86 address -> flat linear address
pages dd ?
; mutex to protect all data from writing by multiple threads at one time
mutex dd ?
; i/o permission map
iopm dd ?
ends
 
; Create V86 machine
; in: nothing
; out: eax = handle (pointer to struc V86_machine)
; eax = NULL => failure
; destroys: ebx, ecx, edx (due to malloc)
v86_create:
; allocate V86_machine structure
mov eax, sizeof.V86_machine
call malloc
test eax, eax
jz .fail
; initialize mutex
and dword [eax+V86_machine.mutex], 0
; allocate tables
mov ebx, eax
; We allocate 4 pages.
; First is main page directory for V86 mode.
; Second page:
; first half (0x800 bytes) is page table for addresses 0 - 0x100000,
; second half is for V86-to-linear translation.
; Third and fourth are for I/O permission map.
push 8000h ; blocks less than 8 pages are discontinuous
call kernel_alloc
test eax, eax
jz .fail2
mov [ebx+V86_machine.pagedir], eax
push edi eax
mov edi, eax
add eax, 1800h
mov [ebx+V86_machine.pages], eax
; initialize tables
mov ecx, 2000h/4
xor eax, eax
rep stosd
mov [ebx+V86_machine.iopm], edi
dec eax
mov ecx, 2000h/4
rep stosd
pop eax
; page directory: first entry is page table...
mov edi, eax
add eax, 1000h
push eax
call get_pg_addr
or al, PG_UW
stosd
; ...and also copy system page tables
; thx to Serge, system is located at high addresses
add edi, (OS_BASE shr 20) - 4
push esi
mov esi, (OS_BASE shr 20) + sys_pgdir
mov ecx, 0x80000000 shr 22
rep movsd
 
mov eax, [ebx+V86_machine.pagedir] ;root dir also is
call get_pg_addr ;used as page table
or al, PG_SW
mov [edi-4096+(page_tabs shr 20)], eax
 
pop esi
; now V86 specific: initialize known addresses in first Mb
pop eax
; first page - BIOS data (shared between all machines!)
; physical address = 0
; linear address = OS_BASE
mov dword [eax], 111b
mov dword [eax+800h], OS_BASE
; page before 0xA0000 - Extended BIOS Data Area (shared between all machines!)
; physical address = 0x9C000
; linear address = 0x8009C000
; (I have seen one computer with EBDA segment = 0x9D80,
; all other computers use less memory)
mov ecx, 4
mov edx, 0x9C000
push eax
lea edi, [eax+0x9C*4]
@@:
lea eax, [edx + OS_BASE]
mov [edi+800h], eax
lea eax, [edx + 111b]
stosd
add edx, 0x1000
loop @b
pop eax
pop edi
; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!)
; physical address = 0xC0000
; linear address = 0x800C0000
mov ecx, 0xC0
@@:
mov edx, ecx
shl edx, 12
push edx
or edx, 111b
mov [eax+ecx*4], edx
pop edx
add edx, OS_BASE
mov [eax+ecx*4+0x800], edx
inc cl
jnz @b
mov eax, ebx
ret
.fail2:
mov eax, ebx
call free
.fail:
xor eax, eax
ret
 
; Destroy V86 machine
; in: eax = handle
; out: nothing
; destroys: eax, ebx, ecx, edx (due to free)
v86_destroy:
push eax
stdcall kernel_free, [eax+V86_machine.pagedir]
pop eax
jmp free
 
; Translate V86-address to linear address
; in: eax=V86 address
; esi=handle
; out: eax=linear address
; destroys: nothing
v86_get_lin_addr:
push ecx edx
mov ecx, eax
mov edx, [esi+V86_machine.pages]
shr ecx, 12
and eax, 0xFFF
add eax, [edx+ecx*4] ; atomic operation, no mutex needed
pop edx ecx
ret
 
; Sets linear address for V86-page
; in: eax=linear address (must be page-aligned)
; ecx=V86 page (NOT address!)
; esi=handle
; out: nothing
; destroys: nothing
v86_set_page:
push eax ebx
mov ebx, [esi+V86_machine.pagedir]
mov [ebx+ecx*4+0x1800], eax
call get_pg_addr
or al, 111b
mov [ebx+ecx*4+0x1000], eax
pop ebx eax
ret
 
; Allocate memory in V86 machine
; in: eax=size (in bytes)
; esi=handle
; out: eax=V86 address, para-aligned (0x10 multiple)
; destroys: nothing
; ­¥¤®¯¨á ­ !!!
;v86_alloc:
; push ebx ecx edx edi
; lea ebx, [esi+V86_machine.mutex]
; call wait_mutex
; add eax, 0x1F
; shr eax, 4
; mov ebx, 0x1000 ; start with address 0x1000 (second page)
; mov edi, [esi+V86_machine.tables]
;.l:
; mov ecx, ebx
; shr ecx, 12
; mov edx, [edi+0x1000+ecx*4] ; get linear address
; test edx, edx ; page allocated?
; jz .unalloc
; mov ecx, ebx
; and ecx, 0xFFF
; add edx, ecx
; cmp dword [edx], 0 ; free block?
; jnz .n
; cmp dword [edx+4],
; and [esi+V86_machine.mutex], 0
; pop edi edx ecx ebx
; ret
 
uglobal
sys_v86_machine dd ?
endg
 
; Called from kernel.asm at first stages of loading
; Initialize system V86 machine (used to simulate BIOS int 13h)
init_sys_v86:
call v86_create
mov [sys_v86_machine], eax
test eax, eax
jz .ret
mov byte [OS_BASE + 0x500], 0xCD
mov byte [OS_BASE + 0x501], 0x13
mov byte [OS_BASE + 0x502], 0xF4
mov byte [OS_BASE + 0x503], 0xCD
mov byte [OS_BASE + 0x504], 0x10
mov byte [OS_BASE + 0x505], 0xF4
mov esi, eax
mov ebx, [eax+V86_machine.pagedir]
; one page for stack, two pages for results (0x2000 bytes = 16 sectors)
mov dword [ebx+0x99*4+0x1000], 0x99000 or 111b
mov dword [ebx+0x99*4+0x1800], OS_BASE + 0x99000
mov dword [ebx+0x9A*4+0x1000], 0x9A000 or 111b
mov dword [ebx+0x9A*4+0x1800], OS_BASE + 0x9A000
mov dword [ebx+0x9B*4+0x1000], 0x9B000 or 111b
mov dword [ebx+0x9B*4+0x1800], OS_BASE + 0x9B000
if ~DEBUG_SHOW_IO
; allow access to all ports
mov ecx, [esi+V86_machine.iopm]
xor eax, eax
mov edi, ecx
mov ecx, 10000h/8/4
rep stosd
end if
.ret:
ret
 
struct v86_regs
; don't change the order, it is important
edi dd ?
esi dd ?
ebp dd ?
dd ? ; ignored
ebx dd ?
edx dd ?
ecx dd ?
eax dd ?
eip dd ?
cs dd ?
eflags dd ? ; VM flag must be set!
esp dd ?
ss dd ?
es dd ?
ds dd ?
fs dd ?
gs dd ?
ends
 
; Run V86 machine
; in: ebx -> registers for V86 (two structures: in and out)
; esi = handle
; ecx = expected end address (CS:IP)
; edx = IRQ to hook or -1 if not required
; out: structure pointed to by ebx is filled with new values
; eax = 1 - exception has occured, cl contains code
; eax = 2 - access to disabled i/o port, ecx contains port address
; eax = 3 - IRQ is already hooked by another VM
; destroys: nothing
v86_start:
pushad
 
cli
 
mov ecx, [CURRENT_TASK]
shl ecx, 8
add ecx, SLOT_BASE
 
mov eax, [esi+V86_machine.iopm]
call get_pg_addr
inc eax
push dword [ecx+APPDATA.io_map]
push dword [ecx+APPDATA.io_map+4]
mov dword [ecx+APPDATA.io_map], eax
mov dword [page_tabs + (tss._io_map_0 shr 10)], eax
add eax, 0x1000
mov dword [ecx+APPDATA.io_map+4], eax
mov dword [page_tabs + (tss._io_map_1 shr 10)], eax
 
push [ecx+APPDATA.dir_table]
push [ecx+APPDATA.saved_esp0]
mov [ecx+APPDATA.saved_esp0], esp
mov [tss._esp0], esp
 
mov eax, [esi+V86_machine.pagedir]
call get_pg_addr
mov [ecx+APPDATA.dir_table], eax
mov cr3, eax
 
; mov [irq_tab+5*4], my05
 
; We do not enable interrupts, because V86 IRQ redirector assumes that
; machine is running
; They will be enabled by IRET.
; sti
 
mov eax, esi
sub esp, sizeof.v86_regs
mov esi, ebx
mov edi, esp
mov ecx, sizeof.v86_regs/4
rep movsd
 
cmp edx, -1
jz .noirqhook
uglobal
v86_irqhooks rd IRQ_RESERVED * 2
endg
cmp [v86_irqhooks+edx*8], 0
jz @f
cmp [v86_irqhooks+edx*8], eax
jz @f
mov esi, v86_irqerr
call sys_msg_board_str
inc [v86_irqhooks+edx*8+4]
mov eax, 3
jmp v86_exc_c.exit
@@:
mov [v86_irqhooks+edx*8], eax
inc [v86_irqhooks+edx*8+4]
.noirqhook:
 
popad
iretd
 
; It is only possible to leave virtual-8086 mode by faulting to
; a protected-mode interrupt handler (typically the general-protection
; exception handler, which in turn calls the virtual 8086-mode monitor).
 
iglobal
v86_exc_str1 db 'V86 : unexpected exception ',0
v86_exc_str2 db ' at ',0
v86_exc_str3 db ':',0
v86_exc_str4 db 13,10,'V86 : faulted code:',0
v86_exc_str5 db ' (unavailable)',0
v86_newline db 13,10,0
v86_io_str1 db 'V86 : access to disabled i/o port ',0
v86_io_byte db ' (byte)',13,10,0
v86_io_word db ' (word)',13,10,0
v86_io_dword db ' (dword)',13,10,0
v86_irqerr db 'V86 : IRQ already hooked',13,10,0
endg
 
v86_exc_c:
; Did we all that we have wanted to do?
cmp bl, 1
jne @f
xor eax, eax
mov dr6, eax
@@:
mov eax, [esp+sizeof.v86_regs+10h+18h]
cmp word [esp+v86_regs.eip], ax
jnz @f
shr eax, 16
cmp word [esp+v86_regs.cs], ax
jz .done
@@:
; Various system events, which must be handled, result in #GP
cmp bl, 13
jnz .nogp
; If faulted EIP exceeds 0xFFFF, we have #GP and it is an error
cmp word [esp+v86_regs.eip+2], 0
jnz .nogp
; Otherwise we can safely access byte at CS:IP
; (because it is #GP, not #PF handler)
; …᫨ ¡ë ¬ë ¬®£«¨ áå«®¯®â âì ¨áª«î祭¨¥ ⮫쪮 ¨§-§  ç⥭¨ï ¡ ©â®¢ ª®¤ ,
; ¬ë ¡ë ¥£® 㦥 áå«®¯®â «¨ ¨ íâ® ¡ë«® ¡ë ­¥ #GP
movzx esi, word [esp+v86_regs.cs]
shl esi, 4
add esi, [esp+v86_regs.eip]
lodsb
cmp al, 0xCD ; int xx command = CD xx
jz .handle_int
cmp al, 0xCF
jz .handle_iret
cmp al, 0xF3
jz .handle_rep
cmp al, 0xEC
jz .handle_in
cmp al, 0xED
jz .handle_in_word
cmp al, 0xEE
jz .handle_out
cmp al, 0xEF
jz .handle_out_word
cmp al, 0xE4
jz .handle_in_imm
cmp al, 0xE6
jz .handle_out_imm
cmp al, 0x9C
jz .handle_pushf
cmp al, 0x9D
jz .handle_popf
cmp al, 0xFA
jz .handle_cli
cmp al, 0xFB
jz .handle_sti
cmp al, 0x66
jz .handle_66
jmp .nogp
.handle_int:
cmp word [esp+v86_regs.eip], 0xFFFF
jae .nogp
xor eax, eax
lodsb
; call sys_msg_board_byte
; simulate INT command
; N.B. It is possible that some checks need to be corrected,
; but at least in case of normal execution the code works.
.simulate_int:
cmp word [esp+v86_regs.esp], 6
jae @f
mov bl, 12 ; #SS exception
jmp .nogp
@@:
movzx edx, word [esp+v86_regs.ss]
shl edx, 4
push eax
movzx eax, word [esp+4+v86_regs.esp]
sub eax, 6
add edx, eax
mov eax, edx
mov esi, [esp+4+sizeof.v86_regs+10h+4]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14 ; #PF exception
jmp .nogp
@@:
lea eax, [edx+5]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14 ; #PF exception
jmp .nogp
@@:
sub word [esp+4+v86_regs.esp], 6
mov eax, [esp+4+v86_regs.eip]
cmp byte [esp+1], 0
jnz @f
inc eax
inc eax
@@:
mov word [edx], ax
mov eax, [esp+4+v86_regs.cs]
mov word [edx+2], ax
mov eax, [esp+4+v86_regs.eflags]
mov word [edx+4], ax
pop eax
mov ah, 0
mov cx, [eax*4]
mov word [esp+v86_regs.eip], cx
mov cx, [eax*4+2]
mov word [esp+v86_regs.cs], cx
; note that interrupts will be disabled globally at IRET
and byte [esp+v86_regs.eflags+1], not 3 ; clear IF and TF flags
; continue V86 execution
popad
iretd
.handle_iret:
cmp word [esp+v86_regs.esp], 0x10000 - 6
jbe @f
mov bl, 12
jmp .nogp
@@:
movzx edx, word [esp+v86_regs.ss]
shl edx, 4
movzx eax, word [esp+v86_regs.esp]
add edx, eax
mov eax, edx
mov esi, [esp+sizeof.v86_regs+10h+4]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14
jmp .nogp
@@:
lea eax, [edx+5]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14
jmp .nogp
@@:
mov ax, [edx]
mov word [esp+v86_regs.eip], ax
mov ax, [edx+2]
mov word [esp+v86_regs.cs], ax
mov ax, [edx+4]
mov word [esp+v86_regs.eflags], ax
add word [esp+v86_regs.esp], 6
popad
iretd
.handle_pushf:
cmp word [esp+v86_regs.esp], 1
jnz @f
mov bl, 12
jmp .nogp
@@:
movzx edx, word [esp+v86_regs.ss]
shl edx, 4
mov eax, [esp+v86_regs.esp]
sub eax, 2
movzx eax, ax
add edx, eax
mov eax, edx
mov esi, [esp+sizeof.v86_regs+10h+4]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14 ; #PF exception
jmp .nogp
@@:
lea eax, [edx+1]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14
jmp .nogp
@@:
sub word [esp+v86_regs.esp], 2
mov eax, [esp+v86_regs.eflags]
mov [edx], ax
inc word [esp+v86_regs.eip]
popad
iretd
.handle_pushfd:
cmp word [esp+v86_regs.esp], 4
jae @f
mov bl, 12 ; #SS exception
jmp .nogp
@@:
movzx edx, word [esp+v86_regs.ss]
shl edx, 4
movzx eax, word [esp+v86_regs.esp]
sub eax, 4
add edx, eax
mov eax, edx
mov esi, [esp+sizeof.v86_regs+10h+4]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14 ; #PF exception
jmp .nogp
@@:
lea eax, [edx+3]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14 ; #PF exception
jmp .nogp
@@:
sub word [esp+v86_regs.esp], 4
movzx eax, word [esp+v86_regs.eflags]
mov [edx], eax
add word [esp+v86_regs.eip], 2
popad
iretd
.handle_popf:
cmp word [esp+v86_regs.esp], 0xFFFF
jnz @f
mov bl, 12
jmp .nogp
@@:
movzx edx, word [esp+v86_regs.ss]
shl edx, 4
movzx eax, word [esp+v86_regs.esp]
add edx, eax
mov eax, edx
mov esi, [esp+sizeof.v86_regs+10h+4]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14 ; #PF exception
jmp .nogp
@@:
lea eax, [edx+1]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14
jmp .nogp
@@:
mov ax, [edx]
mov word [esp+v86_regs.eflags], ax
add word [esp+v86_regs.esp], 2
inc word [esp+v86_regs.eip]
popad
iretd
.handle_popfd:
cmp word [esp+v86_regs.esp], 0x10000 - 4
jbe @f
mov bl, 12
jmp .nogp
@@:
movzx edx, word [esp+v86_regs.ss]
shl edx, 4
movzx eax, word [esp+v86_regs.esp]
add edx, eax
mov eax, edx
mov esi, [esp+sizeof.v86_regs+10h+4]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14
jmp .nogp
@@:
lea eax, [edx+3]
call v86_get_lin_addr
cmp eax, 0x1000
jae @f
mov bl, 14
jmp .nogp
@@:
mov eax, [edx]
mov word [esp+v86_regs.eflags], ax
add word [esp+v86_regs.esp], 4
add word [esp+v86_regs.eip], 2
popad
iretd
.handle_cli:
and byte [esp+v86_regs.eflags+1], not 2
inc word [esp+v86_regs.eip]
popad
iretd
.handle_sti:
or byte [esp+v86_regs.eflags+1], 2
inc word [esp+v86_regs.eip]
popad
iretd
.handle_rep:
cmp word [esp+v86_regs.eip], 0xFFFF
jae .nogp
lodsb
cmp al, 6Eh
jz .handle_rep_outsb
jmp .nogp
.handle_rep_outsb:
.handle_in:
.handle_out:
.invalid_io_byte:
movzx ebx, word [esp+v86_regs.edx]
mov ecx, 1
jmp .invalid_io
.handle_in_imm:
.handle_out_imm:
cmp word [esp+v86_regs.eip], 0xFFFF
jae .nogp
lodsb
movzx ebx, al
mov ecx, 1
jmp .invalid_io
.handle_66:
cmp word [esp+v86_regs.eip], 0xFFFF
jae .nogp
lodsb
cmp al, 0x9C
jz .handle_pushfd
cmp al, 0x9D
jz .handle_popfd
cmp al, 0xEF
jz .handle_out_dword
cmp al, 0xED
jz .handle_in_dword
jmp .nogp
.handle_in_word:
.handle_out_word:
movzx ebx, word [esp+v86_regs.edx]
mov ecx, 2
jmp .invalid_io
.handle_in_dword:
.handle_out_dword:
.invalid_io_dword:
movzx ebx, word [esp+v86_regs.edx]
mov ecx, 4
.invalid_io:
mov esi, v86_io_str1
call sys_msg_board_str
mov eax, ebx
call sys_msg_board_dword
mov esi, v86_io_byte
cmp ecx, 1
jz @f
mov esi, v86_io_word
cmp ecx, 2
jz @f
mov esi, v86_io_dword
@@:
call sys_msg_board_str
if DEBUG_SHOW_IO
mov edx, ebx
mov ebx, 200
call delay_hs
mov esi, [esp+v86_regs.size+10h+4]
mov eax, [esi+V86_machine.iopm]
@@:
btr [eax], edx
inc edx
loop @b
popad
iretd
else
mov eax, 2
jmp .exit
end if
.nogp:
 
mov esi, v86_exc_str1
call sys_msg_board_str
mov al, bl
call sys_msg_board_byte
mov esi, v86_exc_str2
call sys_msg_board_str
mov ax, [esp+32+4]
call sys_msg_board_word
mov esi, v86_exc_str3
call sys_msg_board_str
mov ax, [esp+32]
call sys_msg_board_word
mov esi, v86_exc_str4
call sys_msg_board_str
mov ecx, 8
movzx edx, word [esp+32+4]
shl edx, 4
add edx, [esp+32]
@@:
mov esi, [esp+sizeof.v86_regs+10h+4]
mov eax, edx
call v86_get_lin_addr
cmp eax, 0x1000
jb .nopage
mov esi, v86_exc_str3-2
call sys_msg_board_str
mov al, [edx]
call sys_msg_board_byte
inc edx
loop @b
jmp @f
.nopage:
mov esi, v86_exc_str5
call sys_msg_board_str
@@:
mov esi, v86_newline
call sys_msg_board_str
mov eax, 1
jmp .exit
 
.done:
xor eax, eax
 
.exit:
mov [esp+sizeof.v86_regs+10h+1Ch], eax
mov [esp+sizeof.v86_regs+10h+18h], ebx
 
mov edx, [esp+sizeof.v86_regs+10h+14h]
cmp edx, -1
jz @f
dec [v86_irqhooks+edx*8+4]
jnz @f
and [v86_irqhooks+edx*8], 0
@@:
 
mov esi, esp
mov edi, [esi+sizeof.v86_regs+10h+10h]
add edi, sizeof.v86_regs
mov ecx, sizeof.v86_regs/4
rep movsd
mov esp, esi
 
cli
mov ecx, [CURRENT_TASK]
shl ecx, 8
pop eax
mov [SLOT_BASE+ecx+APPDATA.saved_esp0], eax
mov [tss._esp0], eax
pop eax
mov [SLOT_BASE+ecx+APPDATA.dir_table], eax
pop ebx
mov dword [SLOT_BASE+ecx+APPDATA.io_map+4], ebx
mov dword [page_tabs + (tss._io_map_1 shr 10)], ebx
pop ebx
mov dword [SLOT_BASE+ecx+APPDATA.io_map], ebx
mov dword [page_tabs + (tss._io_map_0 shr 10)], ebx
mov cr3, eax
sti
 
popad
ret
 
;my05:
; mov dx, 30C2h
; mov cx, 4
;.0:
; in al, dx
; cmp al, 0FFh
; jz @f
; test al, 4
; jnz .1
;@@:
; add dx, 8
; in al, dx
; cmp al, 0FFh
; jz @f
; test al, 4
; jnz .1
;@@:
; loop .0
; ret
;.1:
; or al, 84h
; out dx, al
;.2:
; mov dx, 30F7h
; in al, dx
; mov byte [BOOT_VAR + 48Eh], 0FFh
; ret
 
align 4
v86_irq:
; push irq/pushad/jmp v86_irq
; ebp = irq
lea esi, [esp+1Ch]
lea edi, [esi+4]
mov ecx, 8
std
rep movsd
cld
mov edi, ebp
pop eax
v86_irq2:
mov esi, [v86_irqhooks+edi*8] ; get VM handle
mov eax, [esi+V86_machine.pagedir]
call get_pg_addr
mov ecx, [CURRENT_TASK]
shl ecx, 8
cmp [SLOT_BASE+ecx+APPDATA.dir_table], eax
jnz .notcurrent
lea eax, [edi+8]
cmp al, 10h
mov ah, 1
jb @f
add al, 60h
@@:
jmp v86_exc_c.simulate_int
.notcurrent:
mov ebx, SLOT_BASE + 0x100
mov ecx, [TASK_COUNT]
.scan:
cmp [ebx+APPDATA.dir_table], eax
jnz .cont
push ecx
mov ecx, [ebx+APPDATA.saved_esp0]
cmp word [ecx-sizeof.v86_regs+v86_regs.esp], 6
jb .cont2
movzx edx, word [ecx-sizeof.v86_regs+v86_regs.ss]
shl edx, 4
push eax
movzx eax, word [ecx-sizeof.v86_regs+v86_regs.esp]
sub eax, 6
add edx, eax
mov eax, edx
call v86_get_lin_addr
cmp eax, 0x1000
jb .cont3
lea eax, [edx+5]
call v86_get_lin_addr
cmp eax, 0x1000
jb .cont3
pop eax
pop ecx
jmp .found
.cont3:
pop eax
.cont2:
pop ecx
.cont:
add ebx, 0x100
loop .scan
mov ecx, edi
call irq_eoi
popad
iretd
.found:
mov cr3, eax
sub word [esi-sizeof.v86_regs+v86_regs.esp], 6
mov ecx, [esi-sizeof.v86_regs+v86_regs.eip]
mov word [edx], cx
mov ecx, [esi-sizeof.v86_regs+v86_regs.cs]
mov word [edx+2], cx
mov ecx, [esi-sizeof.v86_regs+v86_regs.eflags]
mov word [edx+4], cx
lea eax, [edi+8]
cmp al, 10h
jb @f
add al, 60h
@@:
mov cx, [eax*4]
mov word [esi-sizeof.v86_regs+v86_regs.eip], cx
mov cx, [eax*4+2]
mov word [esi-sizeof.v86_regs+v86_regs.cs], cx
and byte [esi-sizeof.v86_regs+v86_regs.eflags+1], not 3
call update_counters
lea edi, [ebx + 0x100000000 - SLOT_BASE]
shr edi, 3
add edi, TASK_DATA
call find_next_task.found
call do_change_task
popad
iretd
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/apic.inc
0,0 → 1,443
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
iglobal
IRQ_COUNT dd 24
endg
 
uglobal
irq_mode rd 1
IOAPIC_base rd 1
LAPIC_BASE rd 1
endg
 
APIC_ID equ 0x20
APIC_TPR equ 0x80
APIC_EOI equ 0xb0
APIC_LDR equ 0xd0
APIC_DFR equ 0xe0
APIC_SVR equ 0xf0
APIC_ISR equ 0x100
APIC_ESR equ 0x280
APIC_ICRL equ 0x300
APIC_ICRH equ 0x310
APIC_LVT_LINT0 equ 0x350
APIC_LVT_LINT1 equ 0x360
APIC_LVT_err equ 0x370
 
; APIC timer
APIC_LVT_timer equ 0x320
APIC_timer_div equ 0x3e0
APIC_timer_init equ 0x380
APIC_timer_cur equ 0x390
; IOAPIC
IOAPIC_ID equ 0x0
IOAPIC_VER equ 0x1
IOAPIC_ARB equ 0x2
IOAPIC_REDTBL equ 0x10
 
align 4
APIC_init:
mov [irq_mode], IRQ_PIC
 
cmp [acpi_ioapic_base], 0
jz .no_apic
 
cmp [acpi_lapic_base], 0
jz .no_apic
 
stdcall load_file, dev_data_path
test eax, eax
jz .no_apic
 
mov [acpi_dev_data], eax
mov [acpi_dev_size], ebx
 
call IRQ_mask_all
 
; IOAPIC init
stdcall map_io_mem, [acpi_ioapic_base], 0x20, PG_SW+PG_NOCACHE
mov [IOAPIC_base], eax
 
mov eax, IOAPIC_VER
call IOAPIC_read
shr eax, 16
inc al
movzx eax, al
cmp al, IRQ_RESERVED
jbe @f
 
mov al, IRQ_RESERVED
@@:
mov [IRQ_COUNT], eax
 
; Reroute IOAPIC & mask all interrupts
xor ecx, ecx
mov eax, IOAPIC_REDTBL
@@:
mov ebx, eax
call IOAPIC_read
mov ah, 0x09; Delivery Mode: Lowest Priority, Destination Mode: Logical
mov al, cl
add al, 0x20; vector
or eax, 0x10000; Mask Interrupt
cmp ecx, 16
jb .set
 
or eax, 0xa000;<<< level-triggered active-low for IRQ16+
.set:
xchg eax, ebx
call IOAPIC_write
inc eax
mov ebx, eax
call IOAPIC_read
or eax, 0xff000000; Destination Field
xchg eax, ebx
call IOAPIC_write
inc eax
inc ecx
cmp ecx, [IRQ_COUNT]
jb @b
 
call LAPIC_init
 
mov [irq_mode], IRQ_APIC
 
mov al, 0x70
out 0x22, al
mov al, 1
out 0x23, al
 
call pci_irq_fixup
.no_apic:
 
ret
 
;===========================================================
align 4
LAPIC_init:
 
cmp [LAPIC_BASE], 0
jne .done
 
stdcall map_io_mem, [acpi_lapic_base], 0x1000, PG_SW+PG_NOCACHE
mov [LAPIC_BASE], eax
mov esi, eax
 
; Program Destination Format Register for Flat mode.
mov eax, [esi + APIC_DFR]
or eax, 0xf0000000
mov [esi + APIC_DFR], eax
 
; Program Logical Destination Register.
mov eax, [esi + APIC_LDR]
;and eax, 0xff000000
and eax, 0x00ffffff
or eax, 0x01000000;!!!!!!!!!!!!
mov [esi + APIC_LDR], eax
 
; Task Priority Register initialization.
mov eax, [esi + APIC_TPR]
and eax, 0xffffff00
mov [esi + APIC_TPR], eax
 
; Flush the queue
mov edx, 0
.nxt2:
mov ecx, 32
mov eax, [esi + APIC_ISR + edx]
.nxt:
shr eax, 1
jnc @f
mov dword [esi + APIC_EOI], 0; EOI
@@:
loop .nxt
 
add edx, 0x10
cmp edx, 0x170
jbe .nxt2
 
; Spurious-Interrupt Vector Register initialization.
mov eax, [esi + APIC_SVR]
or eax, 0x1ff
and eax, 0xfffffdff
mov [esi + APIC_SVR], eax
 
; Initialize LVT LINT0 register. (INTR)
mov eax, 0x00700
; mov eax, 0x10700
mov [esi + APIC_LVT_LINT0], eax
 
; Initialize LVT LINT1 register. (NMI)
mov eax, 0x00400
mov [esi + APIC_LVT_LINT1], eax
 
; Initialize LVT Error register.
mov eax, [esi + APIC_LVT_err]
or eax, 0x10000; bit 16
mov [esi + APIC_LVT_err], eax
 
; LAPIC timer
; pre init
mov dword[esi + APIC_timer_div], 1011b; 1
mov dword[esi + APIC_timer_init], 0xffffffff; max val
push esi
mov esi, 640 ; wait 0.64 sec
call delay_ms
pop esi
mov eax, [esi + APIC_timer_cur]; read current tick couner
xor eax, 0xffffffff ; eax = 0xffffffff - eax
shr eax, 6 ; eax /= 64; APIC ticks per 0.01 sec
 
; Start (every 0.01 sec)
mov dword[esi + APIC_LVT_timer], 0x30020; periodic int 0x20
mov dword[esi + APIC_timer_init], eax
 
.done:
ret
 
;===========================================================
; IOAPIC implementation
align 4
IOAPIC_read:
; in : EAX - IOAPIC register
; out: EAX - readed value
push esi
mov esi, [IOAPIC_base]
mov [esi], eax
mov eax, [esi + 0x10]
pop esi
ret
 
align 4
IOAPIC_write:
; in : EAX - IOAPIC register
; EBX - value
; out: none
push esi
mov esi, [IOAPIC_base]
mov [esi], eax
mov [esi + 0x10], ebx
pop esi
ret
;===========================================================
; Remap all IRQ to 0x20+ Vectors
; IRQ0 to vector 0x20, IRQ1 to vector 0x21....
align 4
PIC_init:
cli
mov al, 0x11 ; icw4, edge triggered
out 0x20, al
out 0xA0, al
 
mov al, 0x20 ; generate 0x20 +
out 0x21, al
mov al, 0x28 ; generate 0x28 +
out 0xA1, al
 
mov al, 0x04 ; slave at irq2
out 0x21, al
mov al, 0x02 ; at irq9
out 0xA1, al
 
mov al, 0x01 ; 8086 mode
out 0x21, al
out 0xA1, al
 
call IRQ_mask_all
; mov dword[irq_type_to_set], IRQ_TYPE_PIC
ret
 
; -----------------------------------------
; TIMER SET TO 1/100 S
align 4
PIT_init:
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
ret
 
; -----------------------------------------
align 4
unmask_timer:
cmp [irq_mode], IRQ_APIC
je @f
 
stdcall enable_irq, 0
ret
@@:
; use PIT
; in some systems PIT no connected to IOAPIC
; mov eax, 0x14
; call IOAPIC_read
; mov ah, 0x09 ; Delivery Mode: Lowest Priority, Destination Mode: Logical
; mov al, 0x20
; or eax, 0x10000 ; Mask Interrupt
; mov ebx, eax
; mov eax, 0x14
; call IOAPIC_write
; stdcall enable_irq, 2
; ret
 
; use LAPIC timer
mov esi, [LAPIC_BASE]
mov eax, [esi + APIC_LVT_timer]
and eax, 0xfffeffff
mov [esi + APIC_LVT_timer], eax
ret
 
; -----------------------------------------
; Disable all IRQ
align 4
IRQ_mask_all:
cmp [irq_mode], IRQ_APIC
je .APIC
 
mov al, 0xFF
out 0x21, al
out 0xA1, al
mov ecx, 0x1000
ret
.APIC:
mov ecx, [IRQ_COUNT]
mov eax, 0x10
@@:
mov ebx, eax
call IOAPIC_read
or eax, 0x10000; bit 16
xchg eax, ebx
call IOAPIC_write
inc eax
inc eax
loop @b
ret
 
; -----------------------------------------
; End Of Interrupt
; cl - IRQ number
align 4
irq_eoi: ; __fastcall
cmp [irq_mode], IRQ_APIC
je .APIC
 
cmp cl, 8
mov al, 0x20
jb @f
out 0xa0, al
@@:
out 0x20, al
ret
 
.APIC:
mov eax, [LAPIC_BASE]
mov dword [eax + APIC_EOI], 0; EOI
ret
 
; -----------------------------------------
; from dll.inc
align 4
proc enable_irq stdcall, irq_line:dword
mov ebx, [irq_line]
cmp [irq_mode], IRQ_APIC
je .APIC
 
mov edx, 0x21
cmp ebx, 8
jb @F
 
mov edx, 0xA1
sub ebx, 8
@@:
in al, dx
btr eax, ebx
out dx, al
ret
.APIC:
shl ebx, 1
add ebx, 0x10
mov eax, ebx
call IOAPIC_read
and eax, 0xfffeffff; bit 16
xchg eax, ebx
call IOAPIC_write
ret
endp
 
proc disable_irq stdcall, irq_line:dword
mov ebx, [irq_line]
cmp [irq_mode], IRQ_APIC
je .APIC
 
mov edx, 0x21
cmp ebx, 8
jb @F
 
mov edx, 0xA1
sub ebx, 8
@@:
in al, dx
bts eax, ebx
out dx, al
ret
.APIC:
shl ebx, 1
add ebx, 0x10
mov eax, ebx
call IOAPIC_read
or eax, 0x10000; bit 16
xchg eax, ebx
call IOAPIC_write
ret
endp
 
align 4
pci_irq_fixup:
 
push ebp
 
mov esi, [acpi_dev_data]
mov ebx, [acpi_dev_size]
 
lea edi, [esi+ebx]
 
.iterate:
 
cmp esi, edi
jae .done
 
mov eax, [esi]
 
cmp eax, -1
je .done
 
movzx ebx, al
movzx ebp, ah
 
stdcall pci_read32, ebp, ebx, 0
 
cmp eax, [esi+4]
jne .skip
 
mov eax, [esi+8]
stdcall pci_write8, ebp, ebx, 0x3C, eax
.skip:
add esi, 16
jmp .iterate
 
.done:
.fail:
pop ebp
ret
 
 
 
 
 
/kernel/branches/net/core/conf_lib-sp.inc
0,0 → 1,11
; ste archivo debe ser editado con codificaci¢n CP866
 
ugui_mouse_speed db 'velocidad del rat¢n',0
ugui_mouse_delay db 'demora del rat¢n',0
 
udev db 'disp',0
unet db 'red',0
unet_active db 'activa',0
unet_addr db 'direc',0
unet_mask db 'm sc',0
unet_gate db 'puer',0
/kernel/branches/net/core/conf_lib.inc
0,0 → 1,221
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;-------------------------------------------------------------------------
;Loading configuration from ini file
; {SPraid.simba}
;-------------------------------------------------------------------------
 
$Revision $
 
iglobal
conf_path_sect:
db 'path',0
 
conf_fname db '/sys/sys.conf',0
endg
; set soke kernel configuration
proc set_kernel_conf
locals
par db 30 dup(?)
endl
 
pushad
;[gui]
;mouse_speed
 
lea eax, [par]
push eax
invoke ini.get_str, conf_fname, ugui, ugui_mouse_speed, \
eax,30, ugui_mouse_speed_def
pop eax
stdcall strtoint, eax
mov [mouse_speed_factor], ax
 
;mouse_delay
lea eax, [par]
push eax
invoke ini.get_str, conf_fname, ugui, ugui_mouse_delay, \
eax,30, ugui_mouse_delay_def
pop eax
stdcall strtoint, eax
mov [mouse_delay], eax
 
 
;midibase
lea eax, [par]
push eax
invoke ini.get_str, conf_fname, udev, udev_midibase, eax, 30, udev_midibase_def
pop eax
stdcall strtoint, eax
 
cmp eax, 0x100
jb @f
cmp eax, 0x10000
jae @f
mov [midi_base], ax
mov [mididp], eax
inc eax
mov [midisp], eax
@@:
popad
ret
endp
iglobal
ugui db 'gui',0
ugui_mouse_speed_def db '2',0
ugui_mouse_delay_def db '0x00A',0
udev_midibase db 'midibase',0
udev_midibase_def db '0x320',0
endg
 
iglobal
if lang eq sp
include 'core/conf_lib-sp.inc'
else
ugui_mouse_speed db 'mouse_speed',0
ugui_mouse_delay db 'mouse_delay',0
udev db 'dev',0
unet db 'net',0
unet_active db 'active',0
unet_addr db 'addr',0
unet_mask db 'mask',0
unet_gate db 'gate',0
end if
unet_def db 0
endg
; convert string to DWord
proc strtoint stdcall,strs
pushad
 
mov eax, [strs]
inc eax
mov bl, [eax]
cmp bl, 'x'
je .hex
cmp bl, 'X'
je .hex
jmp .dec
.hex:
inc eax
stdcall strtoint_hex, eax
jmp .exit
.dec:
dec eax
stdcall strtoint_dec, eax
.exit:
mov [esp+28], eax
popad
ret
endp
 
; convert string to DWord for decimal value
proc strtoint_dec stdcall,strs
pushad
xor edx, edx
; ¯®¨áª ª®­æ 
mov esi, [strs]
@@:
lodsb
or al, al
jnz @b
mov ebx, esi
mov esi, [strs]
dec ebx
sub ebx, esi
mov ecx, 1
 
@@:
dec ebx
or ebx, ebx
jz @f
imul ecx, ecx, 10; ¯®à冷ª
jmp @b
@@:
 
xchg ebx, ecx
 
 
xor ecx, ecx
 
 
@@:
xor eax, eax
lodsb
cmp al, 0
je .eend
 
sub al, 30h
imul ebx
add ecx, eax
push ecx
xchg eax, ebx
mov ecx, 10
div ecx
xchg eax, ebx
pop ecx
jmp @b
 
.eend:
mov [esp+28], ecx
popad
ret
endp
 
;convert string to DWord for hex value
proc strtoint_hex stdcall,strs
pushad
xor edx, edx
 
mov esi, [strs]
mov ebx, 1
add esi, 1
 
@@:
lodsb
or al, al
jz @f
shl ebx, 4
jmp @b
@@:
xor ecx, ecx
mov esi, [strs]
 
@@:
xor eax, eax
lodsb
cmp al, 0
je .eend
 
cmp al, 'a'
jae .bm
cmp al, 'A'
jae .bb
jmp .cc
.bm: ; 57h
sub al, 57h
jmp .do
 
.bb: ; 37h
sub al, 37h
jmp .do
 
.cc: ; 30h
sub al, 30h
 
.do:
imul ebx
add ecx, eax
shr ebx, 4
 
jmp @b
 
.eend:
mov [esp+28], ecx
popad
ret
endp
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/dll.inc
0,0 → 1,1453
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
DRV_COMPAT equ 5 ;minimal required drivers version
DRV_CURRENT equ 6 ;current drivers model version
 
DRV_VERSION equ (DRV_COMPAT shl 16) or DRV_CURRENT
PID_KERNEL equ 1 ;os_idle thread
 
 
 
align 4
proc get_notify stdcall, p_ev:dword
 
.wait:
mov ebx, [current_slot]
test dword [ebx+APPDATA.event_mask], EVENT_NOTIFY
jz @f
and dword [ebx+APPDATA.event_mask], not EVENT_NOTIFY
mov edi, [p_ev]
mov dword [edi], EV_INTR
mov eax, [ebx+APPDATA.event]
mov dword [edi+4], eax
ret
@@:
call change_task
jmp .wait
endp
 
align 4
proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 6
mov bh, byte [devfn]
mov bl, byte [reg]
call pci_read_reg
pop ebx
ret
endp
 
align 4
proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 5
mov bh, byte [devfn]
mov bl, byte [reg]
call pci_read_reg
pop ebx
ret
endp
 
align 4
proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 4
mov bh, byte [devfn]
mov bl, byte [reg]
call pci_read_reg
pop ebx
ret
endp
 
align 4
proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 8
mov bh, byte [devfn]
mov bl, byte [reg]
mov ecx, [val]
call pci_write_reg
pop ebx
ret
endp
 
align 4
proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 9
mov bh, byte [devfn]
mov bl, byte [reg]
mov ecx, [val]
call pci_write_reg
pop ebx
ret
endp
 
align 4
proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 10
mov bh, byte [devfn]
mov bl, byte [reg]
mov ecx, [val]
call pci_write_reg
pop ebx
ret
endp
 
handle equ IOCTL.handle
io_code equ IOCTL.io_code
input equ IOCTL.input
inp_size equ IOCTL.inp_size
output equ IOCTL.output
out_size equ IOCTL.out_size
 
 
align 4
proc srv_handler stdcall, ioctl:dword
mov esi, [ioctl]
test esi, esi
jz .err
 
mov edi, [esi+handle]
cmp [edi+SRV.magic], ' SRV'
jne .fail
 
cmp [edi+SRV.size], sizeof.SRV
jne .fail
 
stdcall [edi+SRV.srv_proc], esi
ret
.fail:
xor eax, eax
not eax
mov [esi+output], eax
mov [esi+out_size], 4
ret
.err:
xor eax, eax
not eax
ret
endp
 
; param
; ecx= io_control
;
; retval
; eax= error code
 
align 4
srv_handlerEx:
cmp ecx, OS_BASE
jae .fail
 
mov eax, [ecx+handle]
cmp [eax+SRV.magic], ' SRV'
jne .fail
 
cmp [eax+SRV.size], sizeof.SRV
jne .fail
 
stdcall [eax+SRV.srv_proc], ecx
ret
.fail:
or eax, -1
ret
 
restore handle
restore io_code
restore input
restore inp_size
restore output
restore out_size
 
align 4
proc get_service stdcall, sz_name:dword
mov eax, [sz_name]
test eax, eax
jnz @F
ret
@@:
mov edx, [srv.fd]
@@:
cmp edx, srv.fd-SRV.fd
je .not_load
 
stdcall strncmp, edx, [sz_name], 16
test eax, eax
je .ok
 
mov edx, [edx+SRV.fd]
jmp @B
.not_load:
pop ebp
jmp load_driver
.ok:
mov eax, edx
ret
endp
 
align 4
proc reg_service stdcall, name:dword, handler:dword
 
push ebx
 
xor eax, eax
 
cmp [name], eax
je .fail
 
cmp [handler], eax
je .fail
 
mov eax, sizeof.SRV
call malloc
test eax, eax
jz .fail
 
push esi
push edi
mov edi, eax
mov esi, [name]
movsd
movsd
movsd
movsd
pop edi
pop esi
 
mov [eax+SRV.magic], ' SRV'
mov [eax+SRV.size], sizeof.SRV
 
mov ebx, srv.fd-SRV.fd
mov edx, [ebx+SRV.fd]
mov [eax+SRV.fd], edx
mov [eax+SRV.bk], ebx
mov [ebx+SRV.fd], eax
mov [edx+SRV.bk], eax
 
mov ecx, [handler]
mov [eax+SRV.srv_proc], ecx
pop ebx
ret
.fail:
xor eax, eax
pop ebx
ret
endp
 
align 4
proc get_proc stdcall, exp:dword, sz_name:dword
 
mov edx, [exp]
.next:
mov eax, [edx]
test eax, eax
jz .end
 
push edx
stdcall strncmp, eax, [sz_name], 16
pop edx
test eax, eax
jz .ok
 
add edx, 8
jmp .next
.ok:
mov eax, [edx+4]
.end:
ret
endp
 
align 4
proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword
 
@@:
stdcall strncmp, [pSym], [sz_sym], 8
test eax, eax
jz .ok
add [pSym], 18
dec [count]
jnz @b
xor eax, eax
ret
.ok:
mov eax, [pSym]
mov eax, [eax+8]
ret
endp
 
align 4
proc get_curr_task
mov eax, [CURRENT_TASK]
shl eax, 8
ret
endp
 
align 4
proc get_fileinfo stdcall, file_name:dword, info:dword
locals
cmd dd ?
offset dd ?
dd ?
count dd ?
buff dd ?
db ?
name dd ?
endl
 
xor eax, eax
mov ebx, [file_name]
mov ecx, [info]
 
mov [cmd], 5
mov [offset], eax
mov [offset+4], eax
mov [count], eax
mov [buff], ecx
mov byte [buff+4], al
mov [name], ebx
 
mov eax, 70
lea ebx, [cmd]
int 0x40
ret
endp
 
align 4
proc read_file stdcall,file_name:dword, buffer:dword, off:dword,\
bytes:dword
locals
cmd dd ?
offset dd ?
dd ?
count dd ?
buff dd ?
db ?
name dd ?
endl
 
xor eax, eax
mov ebx, [file_name]
mov ecx, [off]
mov edx, [bytes]
mov esi, [buffer]
 
mov [cmd], eax
mov [offset], ecx
mov [offset+4], eax
mov [count], edx
mov [buff], esi
mov byte [buff+4], al
mov [name], ebx
 
pushad
lea ebx, [cmd]
call file_system_lfn_protected
popad
ret
endp
 
; description
; allocate kernel memory and loads the specified file
;
; param
; file_name= full path to file
;
; retval
; eax= file image in kernel memory
; ebx= size of file
;
; warging
; You mast call kernel_free() to delete each file
; loaded by the load_file() function
 
align 4
proc load_file stdcall, file_name:dword
locals
attr dd ?
flags dd ?
cr_time dd ?
cr_date dd ?
acc_time dd ?
acc_date dd ?
mod_time dd ?
mod_date dd ?
file_size dd ?
 
file dd ?
file2 dd ?
endl
 
push esi
push edi
 
lea eax, [attr]
stdcall get_fileinfo, [file_name], eax
test eax, eax
jnz .fail
 
mov eax, [file_size]
cmp eax, 1024*1024*16
ja .fail
 
stdcall kernel_alloc, [file_size]
mov [file], eax
test eax, eax
jz .fail
 
stdcall read_file, [file_name], eax, dword 0, [file_size]
cmp ebx, [file_size]
jne .cleanup
 
mov eax, [file]
cmp dword [eax], 0x4B43504B
jne .exit
mov ebx, [eax+4]
mov [file_size], ebx
stdcall kernel_alloc, ebx
 
test eax, eax
jz .cleanup
 
mov [file2], eax
 
pushad
mov ecx, unpack_mutex
call mutex_lock
popad
 
stdcall unpack, [file], eax
 
pushad
mov ecx, unpack_mutex
call mutex_unlock
popad
 
stdcall kernel_free, [file]
mov eax, [file2]
mov ebx, [file_size]
.exit:
push eax
lea edi, [eax+ebx] ;cleanup remain space
mov ecx, 4096 ;from file end
and ebx, 4095
jz @f
sub ecx, ebx
xor eax, eax
cld
rep stosb
@@:
mov ebx, [file_size]
pop eax
pop edi
pop esi
ret
.cleanup:
stdcall kernel_free, [file]
.fail:
xor eax, eax
xor ebx, ebx
pop edi
pop esi
ret
endp
 
uglobal
align 4
unpack_mutex MUTEX
endg
 
align 4
proc get_proc_ex stdcall, proc_name:dword, imports:dword
 
.look_up:
mov edx, [imports]
test edx, edx
jz .end
mov edx, [edx]
test edx, edx
jz .end
.next:
mov eax, [edx]
test eax, eax
jz .next_table
 
push edx
stdcall strncmp, eax, [proc_name], 256
pop edx
test eax, eax
jz .ok
 
add edx, 8
jmp .next
.next_table:
add [imports], 4
jmp .look_up
.ok:
mov eax, [edx+4]
ret
.end:
xor eax, eax
ret
endp
 
align 4
proc fix_coff_symbols stdcall uses ebx esi, sec:dword, symbols:dword,\
sym_count:dword, strings:dword, imports:dword
locals
retval dd ?
endl
 
mov edi, [symbols]
mov [retval], 1
.fix:
movzx ebx, [edi+COFF_SYM.SectionNumber]
test ebx, ebx
jnz .internal
mov eax, dword [edi+COFF_SYM.Name]
test eax, eax
jnz @F
 
mov edi, [edi+4]
add edi, [strings]
@@:
push edi
stdcall get_proc_ex, edi, [imports]
pop edi
 
xor ebx, ebx
test eax, eax
jnz @F
 
mov esi, msg_unresolved
call sys_msg_board_str
mov esi, edi
call sys_msg_board_str
mov esi, msg_CR
call sys_msg_board_str
 
mov [retval], 0
@@:
mov edi, [symbols]
mov [edi+COFF_SYM.Value], eax
jmp .next
.internal:
cmp bx, -1
je .next
cmp bx, -2
je .next
 
dec ebx
shl ebx, 3
lea ebx, [ebx+ebx*4]
add ebx, [sec]
 
mov eax, [ebx+COFF_SECTION.VirtualAddress]
add [edi+COFF_SYM.Value], eax
.next:
add edi, sizeof.COFF_SYM
mov [symbols], edi
dec [sym_count]
jnz .fix
mov eax, [retval]
ret
endp
 
align 4
proc fix_coff_relocs stdcall uses ebx esi, coff:dword, sym:dword, \
delta:dword
locals
n_sec dd ?
endl
 
mov eax, [coff]
movzx ebx, [eax+COFF_HEADER.nSections]
mov [n_sec], ebx
lea esi, [eax+20]
.fix_sec:
mov edi, [esi+COFF_SECTION.PtrReloc]
add edi, [coff]
 
movzx ecx, [esi+COFF_SECTION.NumReloc]
test ecx, ecx
jz .next
.reloc_loop:
mov ebx, [edi+COFF_RELOC.SymIndex]
add ebx, ebx
lea ebx, [ebx+ebx*8]
add ebx, [sym]
 
mov edx, [ebx+COFF_SYM.Value]
 
cmp [edi+COFF_RELOC.Type], 6
je .dir_32
 
cmp [edi+COFF_RELOC.Type], 20
jne .next_reloc
.rel_32:
mov eax, [edi+COFF_RELOC.VirtualAddress]
add eax, [esi+COFF_SECTION.VirtualAddress]
sub edx, eax
sub edx, 4
jmp .fix
.dir_32:
mov eax, [edi+COFF_RELOC.VirtualAddress]
add eax, [esi+COFF_SECTION.VirtualAddress]
.fix:
add eax, [delta]
add [eax], edx
.next_reloc:
add edi, 10
dec ecx
jnz .reloc_loop
.next:
add esi, sizeof.COFF_SECTION
dec [n_sec]
jnz .fix_sec
.exit:
ret
endp
 
align 4
proc rebase_coff stdcall uses ebx esi, coff:dword, sym:dword, \
delta:dword
locals
n_sec dd ?
endl
 
mov eax, [coff]
movzx ebx, [eax+COFF_HEADER.nSections]
mov [n_sec], ebx
lea esi, [eax+20]
mov edx, [delta]
.fix_sec:
mov edi, [esi+COFF_SECTION.PtrReloc]
add edi, [coff]
 
movzx ecx, [esi+COFF_SECTION.NumReloc]
test ecx, ecx
jz .next
.reloc_loop:
cmp [edi+COFF_RELOC.Type], 6
jne .next_reloc
.dir_32:
mov eax, [edi+COFF_RELOC.VirtualAddress]
add eax, [esi+COFF_SECTION.VirtualAddress]
add [eax+edx], edx
.next_reloc:
add edi, 10
dec ecx
jnz .reloc_loop
.next:
add esi, sizeof.COFF_SECTION
dec [n_sec]
jnz .fix_sec
.exit:
ret
endp
 
align 4
proc load_driver stdcall, driver_name:dword
locals
coff dd ?
sym dd ?
strings dd ?
img_size dd ?
img_base dd ?
start dd ?
 
exports dd ? ;fake exports table
dd ?
file_name rb 13+16+4+1 ; '/sys/drivers/<up-to-16-chars>.obj'
endl
 
lea edx, [file_name]
mov dword [edx], '/sys'
mov dword [edx+4], '/dri'
mov dword [edx+8], 'vers'
mov byte [edx+12], '/'
mov esi, [driver_name]
.redo:
lea edx, [file_name]
lea edi, [edx+13]
mov ecx, 16
@@:
lodsb
test al, al
jz @f
stosb
loop @b
@@:
mov dword [edi], '.obj'
mov byte [edi+4], 0
stdcall load_file, edx
 
test eax, eax
jz .exit
 
mov [coff], eax
 
movzx ecx, [eax+COFF_HEADER.nSections]
xor ebx, ebx
 
lea edx, [eax+20]
@@:
add ebx, [edx+COFF_SECTION.SizeOfRawData]
add ebx, 15
and ebx, not 15
add edx, sizeof.COFF_SECTION
dec ecx
jnz @B
mov [img_size], ebx
 
stdcall kernel_alloc, ebx
test eax, eax
jz .fail
mov [img_base], eax
 
mov edi, eax
xor eax, eax
mov ecx, [img_size]
add ecx, 4095
and ecx, not 4095
shr ecx, 2
cld
rep stosd
 
mov edx, [coff]
movzx ebx, [edx+COFF_HEADER.nSections]
mov edi, [img_base]
lea eax, [edx+20]
@@:
mov [eax+COFF_SECTION.VirtualAddress], edi
mov esi, [eax+COFF_SECTION.PtrRawData]
test esi, esi
jnz .copy
add edi, [eax+COFF_SECTION.SizeOfRawData]
jmp .next
.copy:
add esi, edx
mov ecx, [eax+COFF_SECTION.SizeOfRawData]
cld
rep movsb
.next:
add edi, 15
and edi, not 15
add eax, sizeof.COFF_SECTION
dec ebx
jnz @B
 
mov ebx, [edx+COFF_HEADER.pSymTable]
add ebx, edx
mov [sym], ebx
mov ecx, [edx+COFF_HEADER.nSymbols]
add ecx, ecx
lea ecx, [ecx+ecx*8];ecx*=18 = nSymbols*CSYM_SIZE
add ecx, [sym]
mov [strings], ecx
 
lea ebx, [exports]
mov dword [ebx], kernel_export
mov dword [ebx+4], 0
lea eax, [edx+20]
 
stdcall fix_coff_symbols, eax, [sym], [edx+COFF_HEADER.nSymbols], \
[strings], ebx
test eax, eax
jz .link_fail
 
mov ebx, [coff]
stdcall fix_coff_relocs, ebx, [sym], 0
 
stdcall get_coff_sym, [sym], [ebx+COFF_HEADER.nSymbols], szVersion
test eax, eax
jz .link_fail
 
mov eax, [eax]
shr eax, 16
cmp eax, DRV_COMPAT
jb .ver_fail
 
cmp eax, DRV_CURRENT
ja .ver_fail
 
mov ebx, [coff]
stdcall get_coff_sym, [sym], [ebx+COFF_HEADER.nSymbols], szSTART
mov [start], eax
 
stdcall kernel_free, [coff]
 
mov ebx, [start]
stdcall ebx, DRV_ENTRY
test eax, eax
jnz .ok
 
stdcall kernel_free, [img_base]
 
xor eax, eax
ret
.ok:
mov ebx, [img_base]
mov [eax+SRV.base], ebx
mov ecx, [start]
mov [eax+SRV.entry], ecx
ret
 
.ver_fail:
mov esi, msg_CR
call sys_msg_board_str
mov esi, [driver_name]
call sys_msg_board_str
mov esi, msg_CR
call sys_msg_board_str
mov esi, msg_version
call sys_msg_board_str
mov esi, msg_www
call sys_msg_board_str
jmp .cleanup
 
.link_fail:
mov esi, msg_module
call sys_msg_board_str
mov esi, [driver_name]
call sys_msg_board_str
mov esi, msg_CR
call sys_msg_board_str
.cleanup:
stdcall kernel_free, [img_base]
.fail:
stdcall kernel_free, [coff]
.exit:
xor eax, eax
ret
endp
 
; in: edx -> COFF_SECTION struct
; out: eax = alignment as mask for bits to drop
coff_get_align:
; Rules:
; - if alignment is not given, use default = 4K;
; - if alignment is given and is no more than 4K, use it;
; - if alignment is more than 4K, revert to 4K.
push ecx
mov cl, byte [edx+COFF_SECTION.Characteristics+2]
mov eax, 1
shr cl, 4
dec cl
js .default
cmp cl, 12
jbe @f
.default:
mov cl, 12
@@:
shl eax, cl
pop ecx
dec eax
ret
 
align 4
proc load_library stdcall, file_name:dword
locals
fullname rb 260
fileinfo rb 40
coff dd ?
img_base dd ?
endl
 
cli
 
; resolve file name
mov ebx, [file_name]
lea edi, [fullname+1]
mov byte [edi-1], '/'
stdcall get_full_file_name, edi, 259
test al, al
jz .fail
 
; scan for required DLL in list of already loaded for this process,
; ignore timestamp
mov esi, [CURRENT_TASK]
shl esi, 8
lea edi, [fullname]
mov ebx, [esi+SLOT_BASE+APPDATA.dlls_list_ptr]
test ebx, ebx
jz .not_in_process
mov esi, [ebx+HDLL.fd]
.scan_in_process:
cmp esi, ebx
jz .not_in_process
mov eax, [esi+HDLL.parent]
add eax, DLLDESCR.name
stdcall strncmp, eax, edi, -1
test eax, eax
jnz .next_in_process
; simple variant: load DLL which is already loaded in this process
; just increment reference counters and return address of exports table
inc [esi+HDLL.refcount]
mov ecx, [esi+HDLL.parent]
inc [ecx+DLLDESCR.refcount]
mov eax, [ecx+DLLDESCR.exports]
sub eax, [ecx+DLLDESCR.defaultbase]
add eax, [esi+HDLL.base]
ret
.next_in_process:
mov esi, [esi+HDLL.fd]
jmp .scan_in_process
.not_in_process:
 
; scan in full list, compare timestamp
lea eax, [fileinfo]
stdcall get_fileinfo, edi, eax
test eax, eax
jnz .fail
mov esi, [dll_list.fd]
.scan_for_dlls:
cmp esi, dll_list
jz .load_new
lea eax, [esi+DLLDESCR.name]
stdcall strncmp, eax, edi, -1
test eax, eax
jnz .continue_scan
.test_prev_dll:
mov eax, dword [fileinfo+24]; last modified time
mov edx, dword [fileinfo+28]; last modified date
cmp dword [esi+DLLDESCR.timestamp], eax
jnz .continue_scan
cmp dword [esi+DLLDESCR.timestamp+4], edx
jz .dll_already_loaded
.continue_scan:
mov esi, [esi+DLLDESCR.fd]
jmp .scan_for_dlls
 
; new DLL
.load_new:
; load file
stdcall load_file, edi
test eax, eax
jz .fail
mov [coff], eax
mov dword [fileinfo+32], ebx
 
; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name
mov esi, edi
mov ecx, -1
xor eax, eax
repnz scasb
not ecx
lea eax, [ecx+sizeof.DLLDESCR]
push ecx
call malloc
pop ecx
test eax, eax
jz .fail_and_free_coff
; save timestamp
lea edi, [eax+DLLDESCR.name]
rep movsb
mov esi, eax
mov eax, dword [fileinfo+24]
mov dword [esi+DLLDESCR.timestamp], eax
mov eax, dword [fileinfo+28]
mov dword [esi+DLLDESCR.timestamp+4], eax
; initialize DLLDESCR struct
and dword [esi+DLLDESCR.refcount], 0; no HDLLs yet; later it will be incremented
mov [esi+DLLDESCR.fd], dll_list
mov eax, [dll_list.bk]
mov [dll_list.bk], esi
mov [esi+DLLDESCR.bk], eax
mov [eax+DLLDESCR.fd], esi
 
; calculate size of loaded DLL
mov edx, [coff]
movzx ecx, [edx+COFF_HEADER.nSections]
xor ebx, ebx
 
add edx, 20
@@:
call coff_get_align
add ebx, eax
not eax
and ebx, eax
add ebx, [edx+COFF_SECTION.SizeOfRawData]
add edx, sizeof.COFF_SECTION
dec ecx
jnz @B
; it must be nonzero and not too big
mov [esi+DLLDESCR.size], ebx
test ebx, ebx
jz .fail_and_free_dll
cmp ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR
ja .fail_and_free_dll
; allocate memory for kernel-side image
stdcall kernel_alloc, ebx
test eax, eax
jz .fail_and_free_dll
mov [esi+DLLDESCR.data], eax
; calculate preferred base address
add ebx, 0x1FFF
and ebx, not 0xFFF
mov ecx, [dll_cur_addr]
lea edx, [ecx+ebx]
cmp edx, MAX_DEFAULT_DLL_ADDR
jb @f
mov ecx, MIN_DEFAULT_DLL_ADDR
lea edx, [ecx+ebx]
@@:
mov [esi+DLLDESCR.defaultbase], ecx
mov [dll_cur_addr], edx
 
; copy sections and set correct values for VirtualAddress'es in headers
push esi
mov edx, [coff]
movzx ebx, [edx+COFF_HEADER.nSections]
mov edi, eax
add edx, 20
cld
@@:
call coff_get_align
add ecx, eax
add edi, eax
not eax
and ecx, eax
and edi, eax
mov [edx+COFF_SECTION.VirtualAddress], ecx
add ecx, [edx+COFF_SECTION.SizeOfRawData]
mov esi, [edx+COFF_SECTION.PtrRawData]
push ecx
mov ecx, [edx+COFF_SECTION.SizeOfRawData]
test esi, esi
jnz .copy
xor eax, eax
rep stosb
jmp .next
.copy:
add esi, [coff]
rep movsb
.next:
pop ecx
add edx, sizeof.COFF_SECTION
dec ebx
jnz @B
pop esi
 
; save some additional data from COFF file
; later we will use COFF header, headers for sections and symbol table
; and also relocations table for all sections
mov edx, [coff]
mov ebx, [edx+COFF_HEADER.pSymTable]
mov edi, dword [fileinfo+32]
sub edi, ebx
jc .fail_and_free_data
mov [esi+DLLDESCR.symbols_lim], edi
add ebx, edx
movzx ecx, [edx+COFF_HEADER.nSections]
lea ecx, [ecx*5]
lea edi, [edi+ecx*8+20]
add edx, 20
@@:
movzx eax, [edx+COFF_SECTION.NumReloc]
lea eax, [eax*5]
lea edi, [edi+eax*2]
add edx, sizeof.COFF_SECTION
sub ecx, 5
jnz @b
stdcall kernel_alloc, edi
test eax, eax
jz .fail_and_free_data
mov edx, [coff]
movzx ecx, [edx+COFF_HEADER.nSections]
lea ecx, [ecx*5]
lea ecx, [ecx*2+5]
mov [esi+DLLDESCR.coff_hdr], eax
push esi
mov esi, edx
mov edi, eax
rep movsd
pop esi
mov [esi+DLLDESCR.symbols_ptr], edi
push esi
mov ecx, [edx+COFF_HEADER.nSymbols]
mov [esi+DLLDESCR.symbols_num], ecx
mov ecx, [esi+DLLDESCR.symbols_lim]
mov esi, ebx
rep movsb
pop esi
mov ebx, [esi+DLLDESCR.coff_hdr]
push esi
movzx eax, [edx+COFF_HEADER.nSections]
lea edx, [ebx+20]
@@:
movzx ecx, [edx+COFF_SECTION.NumReloc]
lea ecx, [ecx*5]
mov esi, [edx+COFF_SECTION.PtrReloc]
mov [edx+COFF_SECTION.PtrReloc], edi
sub [edx+COFF_SECTION.PtrReloc], ebx
add esi, [coff]
shr ecx, 1
rep movsd
adc ecx, ecx
rep movsw
add edx, sizeof.COFF_SECTION
dec eax
jnz @b
pop esi
 
; fixup symbols
mov edx, ebx
mov eax, [ebx+COFF_HEADER.nSymbols]
add edx, 20
mov ecx, [esi+DLLDESCR.symbols_num]
lea ecx, [ecx*9]
add ecx, ecx
add ecx, [esi+DLLDESCR.symbols_ptr]
 
stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax, \
ecx, 0
; test eax, eax
; jnz @F
;
;@@:
 
stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], szEXPORTS
test eax, eax
jnz @F
 
stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], sz_EXPORTS
@@:
mov [esi+DLLDESCR.exports], eax
 
; fix relocs in the hidden copy in kernel memory to default address
; it is first fix; usually this will be enough, but second fix
; can be necessary if real load address will not equal assumption
mov eax, [esi+DLLDESCR.data]
sub eax, [esi+DLLDESCR.defaultbase]
stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax
 
stdcall kernel_free, [coff]
 
.dll_already_loaded:
inc [esi+DLLDESCR.refcount]
push esi
call init_heap
pop esi
 
mov edi, [esi+DLLDESCR.size]
stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi
test eax, eax
jnz @f
stdcall user_alloc, edi
test eax, eax
jz .fail_and_dereference
@@:
mov [img_base], eax
mov eax, sizeof.HDLL
call malloc
test eax, eax
jz .fail_and_free_user
mov ebx, [CURRENT_TASK]
shl ebx, 5
mov edx, [CURRENT_TASK+ebx+TASKDATA.pid]
mov [eax+HDLL.pid], edx
push eax
call init_dlls_in_thread
pop ebx
test eax, eax
jz .fail_and_free_user
mov edx, [eax+HDLL.fd]
mov [ebx+HDLL.fd], edx
mov [ebx+HDLL.bk], eax
mov [eax+HDLL.fd], ebx
mov [edx+HDLL.bk], ebx
mov eax, ebx
mov ebx, [img_base]
mov [eax+HDLL.base], ebx
mov [eax+HDLL.size], edi
mov [eax+HDLL.refcount], 1
mov [eax+HDLL.parent], esi
mov edx, ebx
shr edx, 12
or dword [page_tabs+(edx-1)*4], DONT_FREE_BLOCK
; copy entries of page table from kernel-side image to usermode
; use copy-on-write for user-mode image, so map as readonly
xor edi, edi
mov ecx, [esi+DLLDESCR.data]
shr ecx, 12
.map_pages_loop:
mov eax, [page_tabs+ecx*4]
and eax, not 0xFFF
or al, PG_USER
xchg eax, [page_tabs+edx*4]
test al, 1
jz @f
call free_page
@@:
invlpg [ebx+edi]
inc ecx
inc edx
add edi, 0x1000
cmp edi, [esi+DLLDESCR.size]
jb .map_pages_loop
 
; if real user-mode base is not equal to preferred base, relocate image
sub ebx, [esi+DLLDESCR.defaultbase]
jz @f
stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx
@@:
 
mov eax, [esi+DLLDESCR.exports]
sub eax, [esi+DLLDESCR.defaultbase]
add eax, [img_base]
ret
.fail_and_free_data:
stdcall kernel_free, [esi+DLLDESCR.data]
.fail_and_free_dll:
mov eax, esi
call free
.fail_and_free_coff:
stdcall kernel_free, [coff]
.fail:
xor eax, eax
ret
.fail_and_free_user:
stdcall user_free, [img_base]
.fail_and_dereference:
mov eax, 1 ; delete 1 reference
call dereference_dll
xor eax, eax
ret
endp
 
; initialize [APPDATA.dlls_list_ptr] for given thread
; DLL is per-process object, so APPDATA.dlls_list_ptr must be
; kept in sync for all threads of one process.
; out: eax = APPDATA.dlls_list_ptr if all is OK,
; NULL if memory allocation failed
init_dlls_in_thread:
mov ebx, [current_slot]
mov eax, [ebx+APPDATA.dlls_list_ptr]
test eax, eax
jnz .ret
push [ebx+APPDATA.dir_table]
mov eax, 8
call malloc
pop edx
test eax, eax
jz .ret
mov [eax], eax
mov [eax+4], eax
mov ecx, [TASK_COUNT]
mov ebx, SLOT_BASE+256
.set:
cmp [ebx+APPDATA.dir_table], edx
jnz @f
mov [ebx+APPDATA.dlls_list_ptr], eax
@@:
add ebx, 256
dec ecx
jnz .set
.ret:
ret
 
; in: eax = number of references to delete, esi -> DLLDESCR struc
dereference_dll:
sub [esi+DLLDESCR.refcount], eax
jnz .ret
mov eax, [esi+DLLDESCR.fd]
mov edx, [esi+DLLDESCR.bk]
mov [eax+DLLDESCR.bk], edx
mov [edx+DLLDESCR.fd], eax
stdcall kernel_free, [esi+DLLDESCR.coff_hdr]
stdcall kernel_free, [esi+DLLDESCR.data]
mov eax, esi
call free
.ret:
ret
 
destroy_hdll:
push ebx ecx esi edi
push eax
mov ebx, [eax+HDLL.base]
mov esi, [eax+HDLL.parent]
mov edx, [esi+DLLDESCR.size]
; The following actions require the context of application where HDLL is mapped.
; However, destroy_hdll can be called in the context of OS thread when
; cleaning up objects created by the application which is destroyed.
; So remember current cr3 and set it to page table of target.
mov eax, [ecx+APPDATA.dir_table]
; Because we cheat with cr3, disable interrupts: task switch would restore
; page table from APPDATA of current thread.
; Also set [current_slot] because it is used by user_free.
pushf
cli
push [current_slot]
mov [current_slot], ecx
mov ecx, cr3
push ecx
mov cr3, eax
push ebx ; argument for user_free
mov eax, ebx
shr ebx, 12
push ebx
mov esi, [esi+DLLDESCR.data]
shr esi, 12
.unmap_loop:
push eax
mov eax, 2
xchg eax, [page_tabs+ebx*4]
mov ecx, [page_tabs+esi*4]
and eax, not 0xFFF
and ecx, not 0xFFF
cmp eax, ecx
jz @f
call free_page
@@:
pop eax
invlpg [eax]
add eax, 0x1000
inc ebx
inc esi
sub edx, 0x1000
ja .unmap_loop
pop ebx
and dword [page_tabs+(ebx-1)*4], not DONT_FREE_BLOCK
call user_free
; Restore context.
pop eax
mov cr3, eax
pop [current_slot]
popf
; Ok, cheating is done.
pop eax
push eax
mov esi, [eax+HDLL.parent]
mov eax, [eax+HDLL.refcount]
call dereference_dll
pop eax
mov edx, [eax+HDLL.bk]
mov ebx, [eax+HDLL.fd]
mov [ebx+HDLL.bk], edx
mov [edx+HDLL.fd], ebx
call free
pop edi esi ecx ebx
ret
 
; ecx -> APPDATA for slot, esi = dlls_list_ptr
destroy_all_hdlls:
test esi, esi
jz .ret
.loop:
mov eax, [esi+HDLL.fd]
cmp eax, esi
jz free
call destroy_hdll
jmp .loop
.ret:
ret
 
align 4
stop_all_services:
push ebp
mov edx, [srv.fd]
.next:
cmp edx, srv.fd-SRV.fd
je .done
cmp [edx+SRV.magic], ' SRV'
jne .next
cmp [edx+SRV.size], sizeof.SRV
jne .next
 
mov ebx, [edx+SRV.entry]
mov edx, [edx+SRV.fd]
test ebx, ebx
jz .next
 
push edx
mov ebp, esp
push 0
push -1
call ebx
mov esp, ebp
pop edx
jmp .next
.done:
pop ebp
ret
 
; param
; eax= size
; ebx= pid
 
align 4
create_kernel_object:
 
push ebx
call malloc
pop ebx
test eax, eax
jz .fail
 
mov ecx, [current_slot]
add ecx, APP_OBJ_OFFSET
 
pushfd
cli
mov edx, [ecx+APPOBJ.fd]
mov [eax+APPOBJ.fd], edx
mov [eax+APPOBJ.bk], ecx
mov [eax+APPOBJ.pid], ebx
 
mov [ecx+APPOBJ.fd], eax
mov [edx+APPOBJ.bk], eax
popfd
.fail:
ret
 
; param
; eax= object
 
align 4
destroy_kernel_object:
 
pushfd
cli
mov ebx, [eax+APPOBJ.fd]
mov ecx, [eax+APPOBJ.bk]
mov [ebx+APPOBJ.bk], ecx
mov [ecx+APPOBJ.fd], ebx
popfd
 
xor edx, edx ;clear common header
mov [eax], edx
mov [eax+4], edx
mov [eax+8], edx
mov [eax+12], edx
mov [eax+16], edx
 
call free ;release object memory
ret
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/irq.inc
0,0 → 1,229
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
IRQ_RESERVED equ 24
 
IRQ_POOL_SIZE equ 48
 
uglobal
 
align 16
irqh_tab rd sizeof.LHEAD * IRQ_RESERVED / 4
 
irqh_pool rd sizeof.IRQH * IRQ_POOL_SIZE /4
next_irqh rd 1
 
irq_active_set rd 1
irq_failed rd IRQ_RESERVED
 
endg
 
align 4
init_irqs:
 
mov ecx, IRQ_RESERVED
mov edi, irqh_tab
@@:
mov eax, edi
stosd
stosd
loop @B
 
mov ecx, IRQ_POOL_SIZE-1
mov eax, irqh_pool+sizeof.IRQH
mov [next_irqh], irqh_pool
@@:
mov [eax-sizeof.IRQH], eax
add eax, sizeof.IRQH
loop @B
 
mov [eax-sizeof.IRQH], dword 0
ret
 
 
align 4
proc attach_int_handler stdcall, irq:dword, handler:dword, user_data:dword
locals
.irqh dd ?
endl
 
and [.irqh], 0
 
push ebx
 
mov ebx, [irq] ;irq num
test ebx, ebx
jz .err
 
cmp ebx, IRQ_RESERVED
jae .err
 
mov edx, [handler]
test edx, edx
jz .err
 
pushfd
cli
 
;allocate handler
 
mov ecx, [next_irqh]
test ecx, ecx
jz .fail
 
mov eax, [ecx]
mov [next_irqh], eax
mov [.irqh], ecx
 
mov [irq_failed+ebx*4], 0;clear counter
 
mov eax, [user_data]
mov [ecx+IRQH.handler], edx
mov [ecx+IRQH.data], eax
 
lea edx, [irqh_tab+ebx*8]
list_add_tail ecx, edx ;clobber eax
stdcall enable_irq, ebx
 
.fail:
popfd
.err:
pop ebx
mov eax, [.irqh]
ret
 
endp
 
if 0
align 4
proc get_int_handler stdcall, irq:dword
 
mov eax, [irq]
cmp eax, 15
ja .fail
mov eax, [irq_tab + 4 * eax]
ret
.fail:
xor eax, eax
ret
endp
end if
 
 
align 4
proc detach_int_handler
 
ret
endp
 
 
macro irq_serv_h [num] {
forward
align 4
.irq_#num :
push num
jmp .main
}
 
align 16
irq_serv:
 
; .irq_1:
; push 1
; jmp .main
; etc...
 
irq_serv_h 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15
irq_serv_h 16, 17, 18, 19, 20, 21, 22, 23
 
purge irq_serv_h
 
align 16
.main:
save_ring3_context
 
mov ebp, [esp + 32]
mov bx, app_data;os_data
mov ds, bx
mov es, bx
 
cmp [v86_irqhooks+ebp*8], 0
jnz v86_irq
 
cmp bp, 6
jnz @f
push ebp
call [fdc_irq_func]
pop ebp
@@:
 
cmp bp, 14
jnz @f
push ebp
call [irq14_func]
pop ebp
@@:
cmp bp, 15
jnz @f
push ebp
call [irq15_func]
pop ebp
@@:
bts [irq_active_set], ebp
 
lea esi, [irqh_tab+ebp*8] ; esi= list head
mov ebx, esi
.next:
mov ebx, [ebx+IRQH.list.next]; ebx= irqh pointer
cmp ebx, esi
je .done
 
push ebx ; FIX THIS
push edi
push esi
 
push [ebx+IRQH.data]
call [ebx+IRQH.handler]
add esp, 4
 
pop esi
pop edi
pop ebx
 
test eax, eax
jz .next
 
btr [irq_active_set], ebp
jmp .next
 
.done:
btr [irq_active_set], ebp
jnc .exit
 
inc [irq_failed+ebp*4]
.exit:
mov [check_idle_semaphore], 5
 
mov ecx, ebp
call irq_eoi
 
restore_ring3_context
add esp, 4
iret
 
align 4
irqD:
push eax
push ecx
xor eax, eax
out 0xf0, al
mov cl, 13
call irq_eoi
pop ecx
pop eax
iret
 
/kernel/branches/net/core/malloc.inc
0,0 → 1,1035
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
; Small heap based on malloc/free/realloc written by Doug Lea
; Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee)
; Source ftp://gee.cs.oswego.edu/pub/misc/malloc.c
; License http://creativecommons.org/licenses/publicdomain.
 
 
; eax= size
 
; temp
; esi= nb
; ebx= idx
;
align 4
malloc:
push esi
 
; nb = ((size+7)&~7)+8;
 
mov esi, eax ;size
add esi, 7
and esi, -8
add esi, 8
 
mov ecx, mst.mutex
call mutex_lock
 
cmp esi, 256
jae .large
 
mov ecx, esi
shr ecx, 3
or eax, -1
shl eax, cl
and eax, [mst.smallmap]
jz .small
 
push ebp
push edi
 
bsf eax, eax
mov ebx, eax
 
; psize= idx<<3;
; B = &ms.smallbins[idx];
; p = B->fd;
; F = p->fd;
; rsize= psize-nb;
 
lea ebp, [eax*8] ;ebp= psize
shl eax, 4
lea edi, [mst.smallbins+eax] ;edi= B
mov edx, [edi+8] ;edx= p
mov eax, [edx+8] ;eax= F
mov ecx, ebp
sub ecx, esi ;ecx= rsize
 
; if (B == F)
cmp edi, eax
jne @F
 
btr [mst.smallmap], ebx
@@:
 
; B->fd = F;
; F->bk = B;
; if(rsize<16)
 
cmp ecx, 16
mov [edi+8], eax
mov [eax+12], edi
jae .split
 
; p->head = psize|PINUSE_BIT|CINUSE_BIT;
; (p + psize)->head |= PINUSE_BIT;
 
lea eax, [edx+8]
or dword [edx+ebp+4], 1
 
or ebp, 3
mov [edx+4], ebp
 
pop edi
pop ebp
.done:
mov esi, eax
mov ecx, mst.mutex
call mutex_unlock
mov eax, esi
pop esi
ret
 
.split:
lea ebx, [edx+8] ;ebx=mem
 
; r = chunk_plus_offset(p, nb);
; p->head = nb|PINUSE_BIT|CINUSE_BIT;
; r->head = rsize|PINUSE_BIT;
 
lea eax, [edx+esi] ;eax= r
or esi, 3
mov [edx+4], esi
 
mov edx, ecx
or edx, 1
mov [eax+4], edx
 
; (r + rsize)->prev_foot = rsize;
 
mov [eax+ecx], ecx
 
; I = rsize>>3;
 
shr ecx, 3
 
; ms.smallmap |= 1<< I;
bts [mst.smallmap], ecx
 
; B = &ms.smallbins[I];
 
shl ecx, 4
pop edi
pop ebp
add ecx, mst.smallbins ;ecx= B
 
mov edx, [ecx+8] ; F = B->fd;
mov [ecx+8], eax ; B->fd = r;
mov [edx+12], eax ; F->bk = r;
mov [eax+8], edx ; r->fd = F;
mov [eax+12], ecx ; r->bk = B;
 
mov eax, ebx
jmp .done
 
.small:
 
; if (ms.treemap != 0 && (mem = malloc_small(nb)) != 0)
;;;;;;;;;;; start a change <lrz>
mov eax, [mst.treemap]
test eax, eax
;;;;;;;;;;; end the change <lrz>
; cmp [mst.treemap], 0
jz .from_top
mov eax, esi
call malloc_small
test eax, eax
jz .from_top
jmp .done
 
.large:
 
; if (ms.treemap != 0 && (mem = malloc_large(nb)) != 0)
 
cmp [mst.treemap], 0
je .from_top
 
call malloc_large ;esi= nb
test eax, eax
jne .done
.from_top:
 
; if (nb < ms.topsize)
 
mov eax, [mst.topsize]
cmp esi, eax
jae .fail
 
; rsize = ms.topsize -= nb;
; p = ms.top;
 
mov ecx, [mst.top]
sub eax, esi
mov [mst.topsize], eax
 
; r = ms.top = chunk_plus_offset(p, nb);
; r->head = rsize | PINUSE_BIT;
; p->head = nb |PINUSE_BIT|CINUSE_BIT;
 
lea edx, [ecx+esi]
or eax, 1
mov [mst.top], edx
or esi, 3
mov [edx+4], eax
mov [ecx+4], esi
lea eax, [ecx+8]
jmp .done
 
.fail:
xor eax, eax
jmp .done
 
; param
; eax= mem
align 4
free:
test eax, eax
jz .exit
 
push edi
mov edi, eax
add edi, -8
 
; if(p->head & CINUSE_BIT)
 
test byte [edi+4], 2
je .fail
 
mov ecx, mst.mutex
call mutex_lock
 
; psize = p->head & (~3);
 
mov eax, [edi+4]
push esi
mov esi, eax
and esi, -4
 
; next = chunk_plus_offset(p, psize);
; if(!(p->head & PINUSE_BIT))
 
test al, 1
lea ebx, [esi+edi]
jne .next
 
; prevsize = p->prev_foot;
; prev=p - prevsize;
; psize += prevsize;
; p = prev;
 
mov ecx, [edi] ;ecx= prevsize
add esi, ecx ;esi= psize
sub edi, ecx ;edi= p
 
; if (prevsize < 256)
 
cmp ecx, 256
jae .unlink_large
 
mov eax, [edi+8] ;F = p->fd;
mov edx, [edi+12] ;B = p->bk;
 
; if (F == B)
; ms.smallmap &= ~(1<< I);
shr ecx, 3
cmp eax, edx
jne @F
btr [mst.smallmap], ecx
@@:
mov [eax+12], edx ;F->bk = B;
mov [edx+8], eax ;B->fd = F
jmp .next
.unlink_large:
mov edx, edi
call unlink_large_chunk
.next:
 
; if(next->head & PINUSE_BIT)
 
mov eax, [ebx+4]
test al, 1
jz .fail2
 
; if (! (next->head & CINUSE_BIT))
 
test al, 2
jnz .fix_next
 
; if (next == ms.top)
 
cmp ebx, [mst.top]
jne @F
 
; tsize = ms.topsize += psize;
 
mov eax, [mst.topsize]
add eax, esi
mov [mst.topsize], eax
 
; ms.top = p;
; p->head = tsize | PINUSE_BIT;
 
or eax, 1
mov [mst.top], edi
mov [edi+4], eax
.fail2:
mov esi, eax
mov ecx, mst.mutex
call mutex_unlock
mov eax, esi
pop esi
.fail:
pop edi
.exit:
ret
 
@@:
 
; nsize = next->head & ~INUSE_BITS;
 
and eax, -4
add esi, eax ;psize += nsize;
 
; if (nsize < 256)
 
cmp eax, 256
jae .unl_large
 
mov edx, [ebx+8] ;F = next->fd
mov ebx, [ebx+12] ;B = next->bk
 
; if (F == B)
 
cmp edx, ebx
jne @F
mov ecx, eax
shr ecx, 3
btr [mst.smallmap], ecx
@@:
mov [edx+12], ebx ;F->bk = B
 
; p->head = psize|PINUSE_BIT;
 
mov ecx, esi
mov [ebx+8], edx
or ecx, 1
mov [edi+4], ecx
 
; (p+psize)->prev_foot = psize;
 
mov [esi+edi], esi
 
; insert_chunk(p,psize);
 
mov eax, esi
mov ecx, edi
call insert_chunk
jmp .fail2
.unl_large:
 
; unlink_large_chunk((tchunkptr)next);
 
mov edx, ebx
call unlink_large_chunk
; p->head = psize|PINUSE_BIT;
 
mov ecx, esi
or ecx, 1
mov [edi+4], ecx
 
; (p+psize)->prev_foot = psize;
 
mov [esi+edi], esi
 
; insert_chunk(p,psize);
 
mov eax, esi
mov ecx, edi
call insert_chunk
jmp .fail2
.fix_next:
 
; (p+psize)->prev_foot = psize;
; next->head &= ~PINUSE_BIT;
; p->head = psize|PINUSE_BIT;
 
and eax, -2
mov edx, esi
mov [ebx+4], eax
or edx, 1
mov [edi+4], edx
 
; (p+psize)->prev_foot = psize;
 
mov [esi+edi], esi
; insert_chunk(p,psize);
 
mov eax, esi
mov ecx, edi
call insert_chunk
jmp .fail2
 
; param
; ecx = chunk
; eax = size
 
insert_chunk:
 
cmp eax, 256
push esi
mov esi, ecx
jae .large
 
; I = S>>3;
; ms.smallmap |= 1<< I;
 
shr eax, 3
bts [mst.smallmap], eax
 
; B = &ms.smallbins[I];
 
shl eax, 4
add eax, mst.smallbins
mov edx, [eax+8] ;F = B->fd
mov [eax+8], esi ;B->fd = P
mov [edx+12], esi ;F->bk = P
mov [esi+8], edx ;P->fd = F
mov [esi+12], eax ;P->bk = B
pop esi
ret
.large:
mov ebx, eax
call insert_large_chunk
pop esi
ret
 
 
; param
; esi= chunk
; ebx= size
 
insert_large_chunk:
 
; I = compute_tree_index(S);
 
mov edx, ebx
shr edx, 8
bsr eax, edx
lea ecx, [eax+7]
mov edx, ebx
shr edx, cl
and edx, 1
lea ecx, [edx+eax*2]
 
; X->index = I;
mov dword [esi+28], ecx
 
; X->child[0] = X->child[1] = 0;
and dword [esi+20], 0
and dword [esi+16], 0
 
; H = &ms.treebins[I];
 
mov eax, ecx
lea edx, [mst.treebins+eax*4]
 
; if (!(ms.treemap & 1<<I))
bt [mst.treemap], ecx
jc .tree
 
; ms.treemap |= 1<<I;
bts [mst.treemap], ecx
; *H = X;
mov dword [edx], esi
jmp .done
.tree:
 
; T = *H;
mov edx, [edx]
 
; K = S << leftshift_for_tree_index(I);
mov eax, ecx
shr eax, 1
sub ecx, 31
mov edi, 37
sub edi, eax
neg ecx
sbb ecx, ecx
and ecx, edi
mov eax, ebx
shl eax, cl ;eax= K
 
jmp .loop
.not_eq_size:
 
; C = &(T->child[(K >> 31) & 1]);
mov ecx, eax
shr ecx, 31
lea ecx, [edx+ecx*4+16]
 
; K <<= 1;
; if (*C != 0)
mov edi, [ecx]
add eax, eax
test edi, edi
jz .insert_child
 
; T = *C;
mov edx, edi
.loop:
 
; for (;;)
; if ((T->head & ~INUSE_BITS) != S)
 
mov ecx, [edx+4]
and ecx, not 3
cmp ecx, ebx
jne .not_eq_size
 
; F = T->fd;
mov eax, [edx+8]
 
; T->fd = F->bk = X;
mov [eax+12], esi
mov [edx+8], esi
 
; X->fd = F;
; X->bk = T;
; X->parent = 0;
 
and dword [esi+24], 0
mov [esi+8], eax
mov [esi+12], edx
ret
.insert_child:
 
; *C = X;
mov [ecx], esi
.done:
 
; X->parent = T;
mov [esi+24], edx
 
; X->fd = X->bk = X;
mov [esi+12], esi
mov [esi+8], esi
ret
 
 
; param
; edx= chunk
 
unlink_large_chunk:
 
mov eax, [edx+12]
cmp eax, edx
push edi
mov edi, [edx+24]
je @F
 
mov ecx, [edx+8] ;F = X->fd
mov [ecx+12], eax ;F->bk = R;
mov [eax+8], ecx ;R->fd = F
jmp .parent
@@:
mov eax, [edx+20]
test eax, eax
push esi
lea esi, [edx+20]
jne .loop
 
mov eax, [edx+16]
test eax, eax
lea esi, [edx+16]
je .l2
.loop:
cmp dword [eax+20], 0
lea ecx, [eax+20]
jne @F
 
cmp dword [eax+16], 0
lea ecx, [eax+16]
je .l1
@@:
mov eax, [ecx]
mov esi, ecx
jmp .loop
.l1:
mov dword [esi], 0
.l2:
pop esi
.parent:
test edi, edi
je .done
 
mov ecx, [edx+28]
cmp edx, [mst.treebins+ecx*4]
lea ecx, [mst.treebins+ecx*4]
jne .l3
 
test eax, eax
mov [ecx], eax
jne .l5
 
mov ecx, [edx+28]
btr [mst.treemap], ecx
pop edi
ret
 
.l3:
cmp [edi+16], edx
jne @F
 
mov [edi+16], eax
jmp .l4
 
@@:
mov [edi+20], eax
 
.l4:
test eax, eax
je .done
 
.l5:
mov [eax+24], edi
mov ecx, [edx+16]
test ecx, ecx
je .l6
 
mov [eax+16], ecx
mov [ecx+24], eax
 
.l6:
mov edx, [edx+20]
test edx, edx
je .done
 
mov [eax+20], edx
mov [edx+24], eax
 
.done:
pop edi
ret
 
; param
; esi= nb
 
malloc_small:
push ebp
mov ebp, esi
 
push edi
 
bsf eax, [mst.treemap]
mov ecx, [mst.treebins+eax*4]
 
; rsize = (t->head & ~INUSE_BITS) - nb;
 
mov edi, [ecx+4]
and edi, -4
sub edi, esi
 
.loop:
mov ebx, ecx
 
.loop_1:
 
; while ((t = leftmost_child(t)) != 0)
 
mov eax, [ecx+16]
test eax, eax
jz @F
mov ecx, eax
jmp .l1
 
@@:
mov ecx, [ecx+20]
 
.l1:
test ecx, ecx
jz .unlink
 
; trem = (t->head & ~INUSE_BITS) - nb;
 
mov eax, [ecx+4]
and eax, -4
sub eax, ebp
 
; if (trem < rsize)
 
cmp eax, edi
jae .loop_1
 
; rsize = trem;
 
mov edi, eax
jmp .loop
.unlink:
 
 
; r = chunk_plus_offset((mchunkptr)v, nb);
; unlink_large_chunk(v);
 
mov edx, ebx
lea esi, [ebx+ebp]
call unlink_large_chunk
 
; if (rsize < 16)
 
cmp edi, 16
jae .split
 
; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT;
 
lea ecx, [edi+ebp]
 
; (v+rsize + nb)->head |= PINUSE_BIT;
 
add edi, ebx
lea eax, [edi+ebp+4]
pop edi
or ecx, 3
mov [ebx+4], ecx
or dword [eax], 1
pop ebp
 
lea eax, [ebx+8]
ret
 
.split:
 
; v->head = nb|PINUSE_BIT|CINUSE_BIT;
; r->head = rsize|PINUSE_BIT;
; (r+rsize)->prev_foot = rsize;
 
or ebp, 3
mov edx, edi
or edx, 1
 
cmp edi, 256
mov [ebx+4], ebp
mov [esi+4], edx
mov [esi+edi], edi
jae .large
 
shr edi, 3
bts [mst.smallmap], edi
 
mov eax, edi
shl eax, 4
add eax, mst.smallbins
 
mov edx, [eax+8]
mov [eax+8], esi
mov [edx+12], esi
pop edi
mov [esi+12], eax
mov [esi+8], edx
pop ebp
lea eax, [ebx+8]
ret
 
.large:
lea eax, [ebx+8]
push eax
mov ebx, edi
call insert_large_chunk
pop eax
pop edi
pop ebp
ret
 
 
; param
; esi= nb
 
malloc_large:
.idx equ esp+4
.rst equ esp
 
push ebp
push esi
push edi
sub esp, 8
; v = 0;
; rsize = -nb;
 
mov edi, esi
mov ebx, esi
xor ebp, ebp
neg edi
 
; idx = compute_tree_index(nb);
 
mov edx, esi
shr edx, 8
bsr eax, edx
lea ecx, [eax+7]
shr esi, cl
and esi, 1
lea ecx, [esi+eax*2]
mov [.idx], ecx
 
; if ((t = ms.treebins[idx]) != 0)
 
mov eax, [mst.treebins+ecx*4]
test eax, eax
jz .l3
 
; sizebits = nb << leftshift_for_tree_index(idx);
 
cmp ecx, 31
jne @F
xor ecx, ecx
jmp .l1
 
@@:
mov edx, ecx
shr edx, 1
mov ecx, 37
sub ecx, edx
 
.l1:
mov edx, ebx
shl edx, cl
 
; rst = 0;
mov [.rst], ebp
 
.loop:
 
; trem = (t->head & ~INUSE_BITS) - nb;
 
mov ecx, [eax+4]
and ecx, -4
sub ecx, ebx
 
; if (trem < rsize)
 
cmp ecx, edi
jae @F
; v = t;
; if ((rsize = trem) == 0)
 
test ecx, ecx
mov ebp, eax
mov edi, ecx
je .l2
 
@@:
 
; rt = t->child[1];
 
mov ecx, [eax+20]
 
; t = t->child[(sizebits >> 31) & 1];
 
mov esi, edx
shr esi, 31
 
; if (rt != 0 && rt != t)
 
test ecx, ecx
mov eax, [eax+esi*4+16]
jz @F
cmp ecx, eax
jz @F
 
; rst = rt;
mov [.rst], ecx
 
@@:
; if (t == 0)
 
test eax, eax
jz @F
 
; sizebits <<= 1;
 
add edx, edx
jmp .loop
 
@@:
; t = rst;
mov eax, [.rst]
 
.l2:
; if (t == 0 && v == 0)
 
test eax, eax
jne .l4
test ebp, ebp
jne .l7
mov ecx, [.idx]
 
.l3:
 
; leftbits = (-1<<idx) & ms.treemap;
; if (leftbits != 0)
 
or edx, -1
shl edx, cl
and edx, [mst.treemap]
jz @F
 
bsf eax, edx
; t = ms.treebins[i];
mov eax, [mst.treebins+eax*4]
 
@@:
 
; while (t != 0)
test eax, eax
jz .l5
 
.l4:
 
; trem = (t->head & ~INUSE_BITS) - nb;
 
mov ecx, [eax+4]
and ecx, -4
sub ecx, ebx
 
; if (trem < rsize)
 
cmp ecx, edi
jae @F
; rsize = trem;
 
mov edi, ecx
; v = t;
mov ebp, eax
 
@@:
 
; t = leftmost_child(t);
 
mov ecx, [eax+16]
test ecx, ecx
je @F
mov eax, ecx
jmp .l6
 
@@:
mov eax, [eax+20]
 
.l6:
 
; while (t != 0)
 
test eax, eax
jne .l4
 
.l5:
 
; if (v != 0)
 
test ebp, ebp
jz .done
 
.l7:
 
; r = chunk_plus_offset((mchunkptr)v, nb);
; unlink_large_chunk(v);
 
mov edx, ebp
lea esi, [ebx+ebp]
call unlink_large_chunk
 
; if (rsize < 16)
 
cmp edi, 16
jae .large
 
; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT;
 
lea ecx, [edi+ebx]
 
; (v+rsize + nb)->head |= PINUSE_BIT;
 
add edi, ebp
lea eax, [edi+ebx+4]
or ecx, 3
mov [ebp+4], ecx
or dword [eax], 1
lea eax, [ebp+8]
add esp, 8
pop edi
pop esi
pop ebp
ret
 
.large:
 
; v->head = nb|PINUSE_BIT|CINUSE_BIT;
; r->head = rsize|PINUSE_BIT;
 
mov edx, edi
or ebx, 3
mov [ebp+4], ebx
or edx, 1
mov [esi+4], edx
 
; (r+rsize)->prev_foot = rsize;
; insert_large_chunk((tchunkptr)r, rsize);
 
mov [esi+edi], edi
mov eax, edi
mov ecx, esi
call insert_chunk
 
lea eax, [ebp+8]
add esp, 8
pop edi
pop esi
pop ebp
ret
 
.done:
add esp, 8
pop edi
pop esi
pop ebp
xor eax, eax
ret
 
init_malloc:
 
stdcall kernel_alloc, 0x40000
 
mov [mst.top], eax
mov [mst.topsize], 128*1024
mov dword [eax+4], (128*1024) or 1
mov eax, mst.smallbins
 
@@:
mov [eax+8], eax
mov [eax+12], eax
add eax, 16
cmp eax, mst.smallbins+512
jb @B
 
mov ecx, mst.mutex
call mutex_init
 
ret
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/memory.inc
0,0 → 1,1582
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
align 4
proc alloc_page
 
pushfd
cli
push ebx
;//-
cmp [pg_data.pages_free], 1
jle .out_of_memory
;//-
 
mov ebx, [page_start]
mov ecx, [page_end]
.l1:
bsf eax, [ebx];
jnz .found
add ebx, 4
cmp ebx, ecx
jb .l1
pop ebx
popfd
xor eax, eax
ret
.found:
;//-
dec [pg_data.pages_free]
jz .out_of_memory
;//-
btr [ebx], eax
mov [page_start], ebx
sub ebx, sys_pgmap
lea eax, [eax+ebx*8]
shl eax, 12
;//- dec [pg_data.pages_free]
pop ebx
popfd
ret
;//-
.out_of_memory:
mov [pg_data.pages_free], 1
xor eax, eax
pop ebx
popfd
ret
;//-
endp
 
align 4
proc alloc_pages stdcall, count:dword
pushfd
push ebx
push edi
cli
mov eax, [count]
add eax, 7
shr eax, 3
mov [count], eax
;//-
mov ebx, [pg_data.pages_free]
sub ebx, 9
js .out_of_memory
shr ebx, 3
cmp eax, ebx
jg .out_of_memory
;//-
mov ecx, [page_start]
mov ebx, [page_end]
.find:
mov edx, [count]
mov edi, ecx
.match:
cmp byte [ecx], 0xFF
jne .next
dec edx
jz .ok
inc ecx
cmp ecx, ebx
jb .match
.out_of_memory:
.fail:
xor eax, eax
pop edi
pop ebx
popfd
ret
.next:
inc ecx
cmp ecx, ebx
jb .find
pop edi
pop ebx
popfd
xor eax, eax
ret
.ok:
sub ecx, edi
inc ecx
push esi
mov esi, edi
xor eax, eax
rep stosb
sub esi, sys_pgmap
shl esi, 3+12
mov eax, esi
mov ebx, [count]
shl ebx, 3
sub [pg_data.pages_free], ebx
pop esi
pop edi
pop ebx
popfd
ret
endp
 
align 4
proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword
push ebx
mov eax, [phis_addr]
and eax, not 0xFFF
or eax, [flags]
mov ebx, [lin_addr]
shr ebx, 12
mov [page_tabs+ebx*4], eax
mov eax, [lin_addr]
invlpg [eax]
pop ebx
ret
endp
 
align 4
map_space: ;not implemented
 
 
ret
 
 
align 4
proc free_page
;arg: eax page address
pushfd
cli
shr eax, 12 ;page index
bts dword [sys_pgmap], eax ;that's all!
cmc
adc [pg_data.pages_free], 0
shr eax, 3
and eax, not 3 ;dword offset from page_map
add eax, sys_pgmap
cmp [page_start], eax
ja @f
popfd
ret
@@:
mov [page_start], eax
popfd
ret
endp
 
align 4
proc map_io_mem stdcall, base:dword, size:dword, flags:dword
 
push ebx
push edi
mov eax, [size]
add eax, [base]
add eax, 4095
and eax, -4096
mov ecx, [base]
and ecx, -4096
sub eax, ecx
mov [size], eax
 
stdcall alloc_kernel_space, eax
test eax, eax
jz .fail
push eax
 
mov edi, 0x1000
mov ebx, eax
mov ecx, [size]
mov edx, [base]
shr eax, 12
shr ecx, 12
and edx, -4096
or edx, [flags]
@@:
mov [page_tabs+eax*4], edx
invlpg [ebx]
inc eax
add ebx, edi
add edx, edi
loop @B
 
pop eax
mov edx, [base]
and edx, 4095
add eax, edx
.fail:
pop edi
pop ebx
ret
endp
 
; param
; eax= page base + page flags
; ebx= linear address
; ecx= count
 
align 4
commit_pages:
test ecx, ecx
jz .fail
 
push edi
push eax
push ecx
mov ecx, pg_data.mutex
call mutex_lock
pop ecx
pop eax
 
mov edi, ebx
shr edi, 12
lea edi, [page_tabs+edi*4]
@@:
stosd
invlpg [ebx]
add eax, 0x1000
add ebx, 0x1000
loop @B
 
pop edi
 
mov ecx, pg_data.mutex
call mutex_unlock
.fail:
ret
 
 
; param
; eax= base
; ecx= count
 
align 4
release_pages:
 
push ebp
push esi
push edi
push ebx
 
mov esi, eax
mov edi, eax
 
shr esi, 12
lea esi, [page_tabs+esi*4]
 
push ecx
mov ecx, pg_data.mutex
call mutex_lock
pop ecx
 
mov ebp, [pg_data.pages_free]
mov ebx, [page_start]
mov edx, sys_pgmap
@@:
xor eax, eax
xchg eax, [esi]
invlpg [edi]
 
test eax, 1
jz .next
 
shr eax, 12
bts [edx], eax
cmc
adc ebp, 0
shr eax, 3
and eax, -4
add eax, edx
cmp eax, ebx
jae .next
 
mov ebx, eax
.next:
add edi, 0x1000
add esi, 4
loop @B
 
mov [pg_data.pages_free], ebp
mov ecx, pg_data.mutex
call mutex_unlock
 
pop ebx
pop edi
pop esi
pop ebp
ret
 
; param
; eax= base
; ecx= count
 
align 4
unmap_pages:
 
push edi
 
mov edi, eax
mov edx, eax
 
shr edi, 10
add edi, page_tabs
 
xor eax, eax
@@:
stosd
invlpg [edx]
add edx, 0x1000
loop @b
 
pop edi
ret
 
 
align 4
proc map_page_table stdcall, lin_addr:dword, phis_addr:dword
push ebx
mov ebx, [lin_addr]
shr ebx, 22
mov eax, [phis_addr]
and eax, not 0xFFF
or eax, PG_UW ;+PG_NOCACHE
mov dword [master_tab+ebx*4], eax
mov eax, [lin_addr]
shr eax, 10
add eax, page_tabs
invlpg [eax]
pop ebx
ret
endp
 
align 4
proc init_LFB
locals
pg_count dd ?
endl
 
cmp dword [LFBAddress], -1
jne @f
mov [BOOT_VAR+BOOT_MTRR], byte 2
; max VGA=640*480*4=1228800 bytes
; + 32*640*4=81920 bytes for mouse pointer
stdcall alloc_pages, ((1228800+81920)/4096)
 
push eax
call alloc_page
stdcall map_page_table, LFB_BASE, eax
pop eax
or eax, PG_UW
mov ebx, LFB_BASE
; max VGA=640*480*4=1228800 bytes
; + 32*640*4=81920 bytes for mouse pointer
mov ecx, (1228800+81920)/4096
call commit_pages
mov [LFBAddress], dword LFB_BASE
ret
@@:
test [SCR_MODE], word 0100000000000000b
jnz @f
mov [BOOT_VAR+BOOT_MTRR], byte 2
ret
@@:
call init_mtrr
 
mov edx, LFB_BASE
mov esi, [LFBAddress]
mov edi, 0x00C00000
mov dword [exp_lfb+4], edx
 
shr edi, 12
mov [pg_count], edi
shr edi, 10
 
bt [cpu_caps], CAPS_PSE
jnc .map_page_tables
or esi, PG_LARGE+PG_UW
mov edx, sys_pgdir+(LFB_BASE shr 20)
@@:
mov [edx], esi
add edx, 4
add esi, 0x00400000
dec edi
jnz @B
 
bt [cpu_caps], CAPS_PGE
jnc @F
or dword [sys_pgdir+(LFB_BASE shr 20)], PG_GLOBAL
@@:
mov dword [LFBAddress], LFB_BASE
mov eax, cr3 ;flush TLB
mov cr3, eax
ret
 
.map_page_tables:
 
@@:
call alloc_page
stdcall map_page_table, edx, eax
add edx, 0x00400000
dec edi
jnz @B
 
mov eax, [LFBAddress]
mov edi, page_tabs + (LFB_BASE shr 10)
or eax, PG_UW
mov ecx, [pg_count]
cld
@@:
stosd
add eax, 0x1000
dec ecx
jnz @B
 
mov dword [LFBAddress], LFB_BASE
mov eax, cr3 ;flush TLB
mov cr3, eax
 
ret
endp
 
align 4
proc new_mem_resize stdcall, new_size:dword
 
push ebx
push esi
push edi
 
mov edx, [current_slot]
cmp [edx+APPDATA.heap_base], 0
jne .exit
 
mov edi, [new_size]
add edi, 4095
and edi, not 4095
mov [new_size], edi
 
mov esi, [edx+APPDATA.mem_size]
add esi, 4095
and esi, not 4095
 
cmp edi, esi
ja .expand
je .exit
 
mov ebx, edi
shr edi, 12
shr esi, 12
 
mov ecx, pg_data.mutex
call mutex_lock
@@:
mov eax, [app_page_tabs+edi*4]
test eax, 1
jz .next
 
mov dword [app_page_tabs+edi*4], 0
invlpg [ebx]
call free_page
 
.next:
inc edi
add ebx, 0x1000
cmp edi, esi
jb @B
 
mov ecx, pg_data.mutex
call mutex_unlock
 
.update_size:
mov edx, [current_slot]
mov ebx, [new_size]
call update_mem_size
.exit:
pop edi
pop esi
pop ebx
xor eax, eax
ret
 
.expand:
 
mov ecx, pg_data.mutex
call mutex_lock
 
xchg esi, edi
 
push esi ;new size
push edi ;old size
 
add edi, 0x3FFFFF
and edi, not(0x3FFFFF)
add esi, 0x3FFFFF
and esi, not(0x3FFFFF)
 
cmp edi, esi
jae .grow
@@:
call alloc_page
test eax, eax
jz .exit_fail
 
stdcall map_page_table, edi, eax
 
push edi
shr edi, 10
add edi, page_tabs
mov ecx, 1024
xor eax, eax
cld
rep stosd
pop edi
 
add edi, 0x00400000
cmp edi, esi
jb @B
.grow:
pop edi ;old size
pop ecx ;new size
 
shr edi, 10
shr ecx, 10
sub ecx, edi
shr ecx, 2 ;pages count
mov eax, 2
 
add edi, app_page_tabs
rep stosd
 
mov ecx, pg_data.mutex
call mutex_unlock
 
jmp .update_size
 
.exit_fail:
mov ecx, pg_data.mutex
call mutex_unlock
 
add esp, 8
pop edi
pop esi
pop ebx
xor eax, eax
inc eax
ret
endp
 
 
align 4
update_mem_size:
; in: edx = slot base
; ebx = new memory size
; destroys eax,ecx,edx
 
mov [APPDATA.mem_size+edx], ebx
;search threads and update
;application memory size infomation
mov ecx, [APPDATA.dir_table+edx]
mov eax, 2
 
.search_threads:
;eax = current slot
;ebx = new memory size
;ecx = page directory
cmp eax, [TASK_COUNT]
jg .search_threads_end
mov edx, eax
shl edx, 5
cmp word [CURRENT_TASK+edx+TASKDATA.state], 9 ;if slot empty?
jz .search_threads_next
shl edx, 3
cmp [SLOT_BASE+edx+APPDATA.dir_table], ecx ;if it is our thread?
jnz .search_threads_next
mov [SLOT_BASE+edx+APPDATA.mem_size], ebx ;update memory size
.search_threads_next:
inc eax
jmp .search_threads
.search_threads_end:
ret
 
; param
; eax= linear address
;
; retval
; eax= phisical page address
 
align 4
get_pg_addr:
sub eax, OS_BASE
cmp eax, 0x400000
jb @f
shr eax, 12
mov eax, [page_tabs+(eax+(OS_BASE shr 12))*4]
@@:
and eax, 0xFFFFF000
ret
 
 
align 4
; Now it is called from core/sys32::exc_c (see stack frame there)
proc page_fault_handler
 
.err_addr equ ebp-4
 
push ebx ;save exception number (#PF)
mov ebp, esp
mov ebx, cr2
push ebx ;that is locals: .err_addr = cr2
inc [pg_data.pages_faults]
 
mov eax, [pf_err_code]
 
cmp ebx, OS_BASE ;ebx == .err_addr
jb .user_space ;ñòðàíèöà â ïàìÿòè ïðèëîæåíèÿ ;
 
cmp ebx, page_tabs
jb .kernel_space ;ñòðàíèöà â ïàìÿòè ÿäðà
 
cmp ebx, kernel_tabs
jb .alloc;.app_tabs ;òàáëèöû ñòðàíèö ïðèëîæåíèÿ ;
;ïðîñòî ñîçäàäèì îäíó
if 0 ;ïîêà ýòî ïðîñòî ëèøíåå
cmp ebx, LFB_BASE
jb .core_tabs ;òàáëèöû ñòðàíèö ÿäðà
;Îøèáêà
.lfb:
;îáëàñòü LFB
;Îøèáêà
jmp .fail
end if
.core_tabs:
.fail: ;simply return to caller
mov esp, ebp
pop ebx ;restore exception number (#PF)
ret
 
; xchg bx, bx
; add esp,12 ;clear in stack: locals(.err_addr) + #PF + ret_to_caller
; restore_ring3_context
; iretd
 
.user_space:
test eax, PG_MAP
jnz .err_access ;Ñòðàíèöà ïðèñóòñòâóåò
;Îøèáêà äîñòóïà ?
 
shr ebx, 12
mov ecx, ebx
shr ecx, 10
mov edx, [master_tab+ecx*4]
test edx, PG_MAP
jz .fail ;òàáëèöà ñòðàíèö íå ñîçäàíà
;íåâåðíûé àäðåñ â ïðîãðàììå
 
mov eax, [page_tabs+ebx*4]
test eax, 2
jz .fail ;àäðåñ íå çàðåçåðâèðîâàí äëÿ ;
;èñïîëüçîâàíèÿ. Îøèáêà
.alloc:
call alloc_page
test eax, eax
jz .fail
 
stdcall map_page, [.err_addr], eax, PG_UW
 
mov edi, [.err_addr]
and edi, 0xFFFFF000
mov ecx, 1024
xor eax, eax
;cld ;caller is duty for this
rep stosd
.exit: ;iret with repeat fault instruction
add esp, 12;clear in stack: locals(.err_addr) + #PF + ret_to_caller
restore_ring3_context
iretd
 
.err_access:
; access denied? this may be a result of copy-on-write protection for DLL
; check list of HDLLs
and ebx, not 0xFFF
mov eax, [CURRENT_TASK]
shl eax, 8
mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr]
test eax, eax
jz .fail
mov esi, [eax+HDLL.fd]
.scan_hdll:
cmp esi, eax
jz .fail
mov edx, ebx
sub edx, [esi+HDLL.base]
cmp edx, [esi+HDLL.size]
jb .fault_in_hdll
.scan_hdll.next:
mov esi, [esi+HDLL.fd]
jmp .scan_hdll
.fault_in_hdll:
; allocate new page, map it as rw and copy data
call alloc_page
test eax, eax
jz .fail
stdcall map_page, ebx, eax, PG_UW
mov edi, ebx
mov ecx, 1024
sub ebx, [esi+HDLL.base]
mov esi, [esi+HDLL.parent]
mov esi, [esi+DLLDESCR.data]
add esi, ebx
rep movsd
jmp .exit
 
.kernel_space:
test eax, PG_MAP
jz .fail ;ñòðàíèöà íå ïðèñóòñòâóåò
 
test eax, 12 ;U/S (+below)
jnz .fail ;ïðèëîæåíèå îáðàòèëîñü ê ïàìÿòè
;ÿäðà
;test eax, 8
;jnz .fail ;óñòàíîâëåí çàðåçåðâèðîâàííûé áèò
;â òàáëèöàõ ñòðàíèö. äîáàâëåíî â P4/Xeon
 
;ïîïûòêà çàïèñè â çàùèù¸ííóþ ñòðàíèöó ÿäðà
 
cmp ebx, tss._io_map_0
jb .fail
 
cmp ebx, tss._io_map_0+8192
jae .fail
 
; io permission map
; copy-on-write protection
 
call alloc_page
test eax, eax
jz .fail
 
push eax
stdcall map_page, [.err_addr], eax, dword PG_SW
pop eax
mov edi, [.err_addr]
and edi, -4096
lea esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0
 
mov ebx, esi
shr ebx, 12
mov edx, [current_slot]
or eax, PG_SW
mov [edx+APPDATA.io_map+ebx*4], eax
 
add esi, [default_io_map]
mov ecx, 4096/4
;cld ;caller is duty for this
rep movsd
jmp .exit
endp
 
; returns number of mapped bytes
proc map_mem stdcall, lin_addr:dword,slot:dword,\
ofs:dword,buf_size:dword,req_access:dword
push 0 ; initialize number of mapped bytes
 
cmp [buf_size], 0
jz .exit
 
mov eax, [slot]
shl eax, 8
mov eax, [SLOT_BASE+eax+APPDATA.dir_table]
and eax, 0xFFFFF000
 
stdcall map_page, [ipc_pdir], eax, PG_UW
mov ebx, [ofs]
shr ebx, 22
mov esi, [ipc_pdir]
mov edi, [ipc_ptab]
mov eax, [esi+ebx*4]
and eax, 0xFFFFF000
jz .exit
stdcall map_page, edi, eax, PG_UW
; inc ebx
; add edi, 0x1000
; mov eax, [esi+ebx*4]
; test eax, eax
; jz @f
; and eax, 0xFFFFF000
; stdcall map_page, edi, eax
 
@@:
mov edi, [lin_addr]
and edi, 0xFFFFF000
mov ecx, [buf_size]
add ecx, 4095
shr ecx, 12
inc ecx
 
mov edx, [ofs]
shr edx, 12
and edx, 0x3FF
mov esi, [ipc_ptab]
 
.map:
stdcall safe_map_page, [slot], [req_access], [ofs]
jnc .exit
add dword [ebp-4], 4096
add [ofs], 4096
dec ecx
jz .exit
add edi, 0x1000
inc edx
cmp edx, 0x400
jnz .map
inc ebx
mov eax, [ipc_pdir]
mov eax, [eax+ebx*4]
and eax, 0xFFFFF000
jz .exit
stdcall map_page, esi, eax, PG_UW
xor edx, edx
jmp .map
 
.exit:
pop eax
ret
endp
 
proc map_memEx stdcall, lin_addr:dword,slot:dword,\
ofs:dword,buf_size:dword,req_access:dword
push 0 ; initialize number of mapped bytes
 
cmp [buf_size], 0
jz .exit
 
mov eax, [slot]
shl eax, 8
mov eax, [SLOT_BASE+eax+APPDATA.dir_table]
and eax, 0xFFFFF000
 
stdcall map_page, [proc_mem_pdir], eax, PG_UW
mov ebx, [ofs]
shr ebx, 22
mov esi, [proc_mem_pdir]
mov edi, [proc_mem_tab]
mov eax, [esi+ebx*4]
and eax, 0xFFFFF000
test eax, eax
jz .exit
stdcall map_page, edi, eax, PG_UW
 
@@:
mov edi, [lin_addr]
and edi, 0xFFFFF000
mov ecx, [buf_size]
add ecx, 4095
shr ecx, 12
inc ecx
 
mov edx, [ofs]
shr edx, 12
and edx, 0x3FF
mov esi, [proc_mem_tab]
 
.map:
stdcall safe_map_page, [slot], [req_access], [ofs]
jnc .exit
add dword [ebp-4], 0x1000
add edi, 0x1000
add [ofs], 0x1000
inc edx
dec ecx
jnz .map
.exit:
pop eax
ret
endp
 
; in: esi+edx*4 = pointer to page table entry
; in: [slot], [req_access], [ofs] on the stack
; in: edi = linear address to map
; out: CF cleared <=> failed
; destroys: only eax
proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
mov eax, [esi+edx*4]
test al, PG_MAP
jz .not_present
test al, PG_WRITE
jz .resolve_readonly
; normal case: writable page, just map with requested access
.map:
stdcall map_page, edi, eax, [req_access]
stc
.fail:
ret
.not_present:
; check for alloc-on-demand page
test al, 2
jz .fail
; allocate new page, save it to source page table
push ecx
call alloc_page
pop ecx
test eax, eax
jz .fail
or al, PG_UW
mov [esi+edx*4], eax
jmp .map
.resolve_readonly:
; readonly page, probably copy-on-write
; check: readonly request of readonly page is ok
test [req_access], PG_WRITE
jz .map
; find control structure for this page
pushf
cli
cld
push ebx ecx
mov eax, [slot]
shl eax, 8
mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr]
test eax, eax
jz .no_hdll
mov ecx, [eax+HDLL.fd]
.scan_hdll:
cmp ecx, eax
jz .no_hdll
mov ebx, [ofs]
and ebx, not 0xFFF
sub ebx, [ecx+HDLL.base]
cmp ebx, [ecx+HDLL.size]
jb .hdll_found
mov ecx, [ecx+HDLL.fd]
jmp .scan_hdll
.no_hdll:
pop ecx ebx
popf
clc
ret
.hdll_found:
; allocate page, save it in page table, map it, copy contents from base
mov eax, [ecx+HDLL.parent]
add ebx, [eax+DLLDESCR.data]
call alloc_page
test eax, eax
jz .no_hdll
or al, PG_UW
mov [esi+edx*4], eax
stdcall map_page, edi, eax, [req_access]
push esi edi
mov esi, ebx
mov ecx, 4096/4
rep movsd
pop edi esi
pop ecx ebx
popf
stc
ret
endp
 
sys_IPC:
;input:
; ebx=1 - set ipc buffer area
; ecx=address of buffer
; edx=size of buffer
; eax=2 - send message
; ebx=PID
; ecx=address of message
; edx=size of message
 
dec ebx
jnz @f
 
mov eax, [current_slot]
pushf
cli
mov [eax+APPDATA.ipc_start], ecx ;set fields in extended information area
mov [eax+APPDATA.ipc_size], edx
 
add edx, ecx
add edx, 4095
and edx, not 4095
 
.touch:
mov eax, [ecx]
add ecx, 0x1000
cmp ecx, edx
jb .touch
 
popf
mov [esp+32], ebx ;ebx=0
ret
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;2
@@:
dec ebx
jnz @f
 
stdcall sys_ipc_send, ecx, edx, esi
mov [esp+32], eax
ret
@@:
or eax, -1
mov [esp+32], eax
ret
 
;align 4
;proc set_ipc_buff
 
; mov eax,[current_slot]
; pushf
; cli
; mov [eax+APPDATA.ipc_start],ebx ;set fields in extended information area
; mov [eax+APPDATA.ipc_size],ecx
;
; add ecx, ebx
; add ecx, 4095
; and ecx, not 4095
;
;.touch: mov eax, [ebx]
; add ebx, 0x1000
; cmp ebx, ecx
; jb .touch
;
; popf
; xor eax, eax
; ret
;endp
 
proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
locals
dst_slot dd ?
dst_offset dd ?
buf_size dd ?
used_buf dd ?
endl
 
pushf
cli
 
mov eax, [PID]
call pid_to_slot
test eax, eax
jz .no_pid
 
mov [dst_slot], eax
shl eax, 8
mov edi, [eax+SLOT_BASE+0xa0] ;is ipc area defined?
test edi, edi
jz .no_ipc_area
 
mov ebx, edi
and ebx, 0xFFF
mov [dst_offset], ebx
 
mov esi, [eax+SLOT_BASE+0xa4]
mov [buf_size], esi
 
mov ecx, [ipc_tmp]
cmp esi, 0x40000-0x1000; size of [ipc_tmp] minus one page
jbe @f
push esi edi
add esi, 0x1000
stdcall alloc_kernel_space, esi
mov ecx, eax
pop edi esi
@@:
mov [used_buf], ecx
stdcall map_mem, ecx, [dst_slot], \
edi, esi, PG_SW
 
mov edi, [dst_offset]
add edi, [used_buf]
cmp dword [edi], 0
jnz .ipc_blocked ;if dword [buffer]<>0 - ipc blocked now
 
mov edx, dword [edi+4]
lea ebx, [edx+8]
add ebx, [msg_size]
cmp ebx, [buf_size]
ja .buffer_overflow ;esi<0 - not enough memory in buffer
 
mov dword [edi+4], ebx
mov eax, [TASK_BASE]
mov eax, [eax+0x04] ;eax - our PID
add edi, edx
mov [edi], eax
mov ecx, [msg_size]
 
mov [edi+4], ecx
add edi, 8
mov esi, [msg_addr]
; add esi, new_app_base
cld
rep movsb
 
mov ebx, [ipc_tmp]
mov edx, ebx
shr ebx, 12
xor eax, eax
mov [page_tabs+ebx*4], eax
invlpg [edx]
 
mov ebx, [ipc_pdir]
mov edx, ebx
shr ebx, 12
xor eax, eax
mov [page_tabs+ebx*4], eax
invlpg [edx]
 
mov ebx, [ipc_ptab]
mov edx, ebx
shr ebx, 12
xor eax, eax
mov [page_tabs+ebx*4], eax
invlpg [edx]
 
mov eax, [dst_slot]
shl eax, 8
or [eax+SLOT_BASE+0xA8], dword 0x40
cmp dword [check_idle_semaphore], 20
jge .ipc_no_cis
 
mov dword [check_idle_semaphore], 5
.ipc_no_cis:
push 0
jmp .ret
.no_pid:
popf
mov eax, 4
ret
.no_ipc_area:
popf
xor eax, eax
inc eax
ret
.ipc_blocked:
push 2
jmp .ret
.buffer_overflow:
push 3
.ret:
mov eax, [used_buf]
cmp eax, [ipc_tmp]
jz @f
stdcall free_kernel_space, eax
@@:
pop eax
popf
ret
endp
 
align 4
sysfn_meminfo:
 
; add ecx, new_app_base
cmp ecx, OS_BASE
jae .fail
 
mov eax, [pg_data.pages_count]
mov [ecx], eax
shl eax, 12
mov [esp+32], eax
mov eax, [pg_data.pages_free]
mov [ecx+4], eax
mov eax, [pg_data.pages_faults]
mov [ecx+8], eax
mov eax, [heap_size]
mov [ecx+12], eax
mov eax, [heap_free]
mov [ecx+16], eax
mov eax, [heap_blocks]
mov [ecx+20], eax
mov eax, [free_blocks]
mov [ecx+24], eax
ret
.fail:
or dword [esp+32], -1
ret
 
align 4
f68:
cmp ebx, 4
jbe sys_sheduler
 
cmp ebx, 11
jb .fail
 
cmp ebx, 25
ja .fail
 
jmp dword [f68call+ebx*4-11*4]
.11:
call init_heap
mov [esp+32], eax
ret
.12:
stdcall user_alloc, ecx
mov [esp+32], eax
ret
.13:
stdcall user_free, ecx
mov [esp+32], eax
ret
.14:
cmp ecx, OS_BASE
jae .fail
mov edi, ecx
call get_event_ex
mov [esp+32], eax
ret
.16:
test ecx, ecx
jz .fail
cmp ecx, OS_BASE
jae .fail
stdcall get_service, ecx
mov [esp+32], eax
ret
.17:
call srv_handlerEx ;ecx
mov [esp+32], eax
ret
.19:
cmp ecx, OS_BASE
jae .fail
stdcall load_library, ecx
mov [esp+32], eax
ret
.20:
mov eax, edx
mov ebx, ecx
call user_realloc ;in: eax = pointer, ebx = new size
mov [esp+32], eax
ret
.21:
cmp ecx, OS_BASE
jae .fail
 
cmp edx, OS_BASE
jae .fail
 
mov edi, edx
stdcall load_PE, ecx
mov esi, eax
test eax, eax
jz @F
 
push edi
push DRV_ENTRY
call eax
add esp, 8
test eax, eax
jz @F
 
mov [eax+SRV.entry], esi
 
@@:
mov [esp+32], eax
ret
.22:
cmp ecx, OS_BASE
jae .fail
 
stdcall shmem_open, ecx, edx, esi
mov [esp+24], edx
mov [esp+32], eax
ret
 
.23:
cmp ecx, OS_BASE
jae .fail
 
stdcall shmem_close, ecx
mov [esp+32], eax
ret
.24:
mov eax, [current_slot]
xchg ecx, [eax+APPDATA.exc_handler]
xchg edx, [eax+APPDATA.except_mask]
mov [esp+32], ecx ; reg_eax+8
mov [esp+20], edx ; reg_ebx+8
ret
.25:
cmp ecx, 32
jae .fail
mov eax, [current_slot]
btr [eax+APPDATA.except_mask], ecx
setc byte[esp+32]
jecxz @f
bts [eax+APPDATA.except_mask], ecx
@@:
ret
 
.26:
stdcall user_unmap, ecx, edx, esi
mov [esp+32], eax
ret
 
.fail:
xor eax, eax
mov [esp+32], eax
ret
 
 
align 4
f68call: ; keep this table closer to main code
 
dd f68.11 ; init_heap
dd f68.12 ; user_alloc
dd f68.13 ; user_free
dd f68.14 ; get_event_ex
dd f68.fail ; moved to f68.24
dd f68.16 ; get_service
dd f68.17 ; call_service
dd f68.fail ; moved to f68.25
dd f68.19 ; load_dll
dd f68.20 ; user_realloc
dd f68.21 ; load_driver
dd f68.22 ; shmem_open
dd f68.23 ; shmem_close
dd f68.24 ; set exception handler
dd f68.25 ; unmask exception
dd f68.26 ; user_unmap
 
 
align 4
proc load_pe_driver stdcall, file:dword
 
stdcall load_PE, [file]
test eax, eax
jz .fail
 
mov esi, eax
stdcall eax, DRV_ENTRY
test eax, eax
jz .fail
 
mov [eax+SRV.entry], esi
ret
 
.fail:
xor eax, eax
ret
endp
 
 
align 4
proc init_mtrr
 
cmp [BOOT_VAR+BOOT_MTRR], byte 2
je .exit
 
bt [cpu_caps], CAPS_MTRR
jnc .exit
 
mov eax, cr0
or eax, 0x60000000 ;disable caching
mov cr0, eax
wbinvd ;invalidate cache
 
mov ecx, 0x2FF
rdmsr ;
; has BIOS already initialized MTRRs?
test ah, 8
jnz .skip_init
; rarely needed, so mainly placeholder
; main memory - cached
push eax
 
mov eax, [MEM_AMOUNT]
; round eax up to next power of 2
dec eax
bsr ecx, eax
mov ebx, 2
shl ebx, cl
dec ebx
; base of memory range = 0, type of memory range = MEM_WB
xor edx, edx
mov eax, MEM_WB
mov ecx, 0x200
wrmsr
; mask of memory range = 0xFFFFFFFFF - (size - 1), ebx = size - 1
mov eax, 0xFFFFFFFF
mov edx, 0x0000000F
sub eax, ebx
sbb edx, 0
or eax, 0x800
inc ecx
wrmsr
; clear unused MTRRs
xor eax, eax
xor edx, edx
@@:
wrmsr
inc ecx
cmp ecx, 0x210
jb @b
; enable MTRRs
pop eax
or ah, 8
and al, 0xF0; default memtype = UC
mov ecx, 0x2FF
wrmsr
.skip_init:
stdcall set_mtrr, [LFBAddress], [LFBSize], MEM_WC
 
wbinvd ;again invalidate
 
mov eax, cr0
and eax, not 0x60000000
mov cr0, eax ; enable caching
.exit:
ret
endp
 
align 4
proc set_mtrr stdcall, base:dword,size:dword,mem_type:dword
; find unused register
mov ecx, 0x201
@@:
rdmsr
dec ecx
test ah, 8
jz .found
rdmsr
mov al, 0; clear memory type field
cmp eax, [base]
jz .ret
add ecx, 3
cmp ecx, 0x210
jb @b
; no free registers, ignore the call
.ret:
ret
.found:
; found, write values
xor edx, edx
mov eax, [base]
or eax, [mem_type]
wrmsr
 
mov ebx, [size]
dec ebx
mov eax, 0xFFFFFFFF
mov edx, 0x00000000
sub eax, ebx
sbb edx, 0
or eax, 0x800
inc ecx
wrmsr
ret
endp
 
align 4
proc stall stdcall, delay:dword
push ecx
push edx
push ebx
push eax
 
mov eax, [delay]
mul [stall_mcs]
mov ebx, eax ;low
mov ecx, edx ;high
rdtsc
add ebx, eax
adc ecx, edx
@@:
rdtsc
sub eax, ebx
sbb edx, ecx
jb @B
 
pop eax
pop ebx
pop edx
pop ecx
ret
endp
 
align 4
proc create_ring_buffer stdcall, size:dword, flags:dword
locals
buf_ptr dd ?
endl
 
mov eax, [size]
test eax, eax
jz .fail
 
add eax, eax
stdcall alloc_kernel_space, eax
test eax, eax
jz .fail
 
push ebx
 
mov [buf_ptr], eax
 
mov ebx, [size]
shr ebx, 12
push ebx
 
stdcall alloc_pages, ebx
pop ecx
 
test eax, eax
jz .mm_fail
 
push edi
 
or eax, [flags]
mov edi, [buf_ptr]
mov ebx, [buf_ptr]
mov edx, ecx
shl edx, 2
shr edi, 10
@@:
mov [page_tabs+edi], eax
mov [page_tabs+edi+edx], eax
invlpg [ebx]
invlpg [ebx+0x10000]
add eax, 0x1000
add ebx, 0x1000
add edi, 4
dec ecx
jnz @B
 
mov eax, [buf_ptr]
pop edi
pop ebx
ret
.mm_fail:
stdcall free_kernel_space, [buf_ptr]
xor eax, eax
pop ebx
.fail:
ret
endp
 
 
align 4
proc print_mem
mov edi, BOOT_VAR + 0x9104
mov ecx, [edi-4]
test ecx, ecx
jz .done
 
@@:
mov eax, [edi]
mov edx, [edi+4]
add eax, [edi+8]
adc edx, [edi+12]
 
DEBUGF 1, "K : E820 %x%x - %x%x type %d\n", \
[edi+4], [edi],\
edx, eax, [edi+16]
add edi, 20
dec ecx
jnz @b
.done:
ret
endp
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/sys32-sp.inc
0,0 → 1,4
; ste archivo debe ser editado con codificaci¢n CP866
 
msg_sel_ker db "n£cleo", 0
msg_sel_app db "aplicaci¢n", 0
/kernel/branches/net/core/sys32.inc
0,0 → 1,798
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; MenuetOS process management, protected ring3 ;;
;; ;;
;; Distributed under GPL. See file COPYING for details. ;;
;; Copyright 2003 Ville Turjanmaa ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
align 4 ;3A08
build_interrupt_table:
mov edi, idts
mov esi, sys_int
mov ecx, 0x40
mov eax, (10001110b shl 24) + os_code
@@:
movsw ;low word of code-entry
stosd ;interrupt gate type : os_code selector
movsw ;high word of code-entry
loop @b
movsd ;copy low dword of trap gate for int 0x40
movsd ;copy high dword of trap gate for int 0x40
lidt [esi]
ret
 
iglobal
align 4
sys_int:
;exception handlers addresses (for interrupt gate construction)
dd e0,e1,e2,e3,e4,e5,e6,except_7 ; SEE: core/fpu.inc
dd e8,e9,e10,e11,e12,e13,page_fault_exc,e15
dd e16, e17,e18, e19
times 12 dd unknown_interrupt ;int_20..int_31
 
;interrupt handlers addresses (for interrupt gate construction)
; 0x20 .. 0x2F - IRQ handlers
dd irq0, irq_serv.irq_1, irq_serv.irq_2
dd irq_serv.irq_3, irq_serv.irq_4
dd irq_serv.irq_5, irq_serv.irq_6, irq_serv.irq_7
dd irq_serv.irq_8, irq_serv.irq_9, irq_serv.irq_10
dd irq_serv.irq_11, irq_serv.irq_12, irqD, irq_serv.irq_14, irq_serv.irq_15
dd irq_serv.irq_16
dd irq_serv.irq_17
dd irq_serv.irq_18
dd irq_serv.irq_19
dd irq_serv.irq_20
dd irq_serv.irq_21
dd irq_serv.irq_22
dd irq_serv.irq_23
 
times 32 - IRQ_RESERVED dd unknown_interrupt
;int_0x40 gate trap (for directly copied)
dw i40 and 0xFFFF, os_code, 11101111b shl 8, i40 shr 16
 
idtreg: ; data for LIDT instruction (!!! must be immediately below sys_int data)
dw 2*($-sys_int-4)-1
dd idts ;0x8000B100
dw 0 ;ïðîñòî âûðàâíèâàíèå
 
msg_fault_sel dd msg_exc_8,msg_exc_u,msg_exc_a,msg_exc_b
dd msg_exc_c,msg_exc_d,msg_exc_e
 
msg_exc_8 db "Double fault", 0
msg_exc_u db "Undefined Exception", 0
msg_exc_a db "Invalid TSS", 0
msg_exc_b db "Segment not present", 0
msg_exc_c db "Stack fault", 0
msg_exc_d db "General protection fault", 0
msg_exc_e db "Page fault", 0
 
if lang eq sp
include 'core/sys32-sp.inc'
else
msg_sel_ker db "kernel", 0
msg_sel_app db "application", 0
end if
 
endg
 
macro save_ring3_context {
pushad
}
macro restore_ring3_context {
popad
}
macro exc_wo_code [num] {
e#num :
save_ring3_context
mov bl, num
jmp exc_c
} exc_wo_code 0,1,2,3,4,5,6,15,16,19
 
macro exc_w_code [num] {
e#num :
add esp, 4
save_ring3_context
mov bl, num
jmp exc_c
} exc_w_code 8,9,10,11,12,13,17,18
 
 
uglobal
pf_err_code dd ?
endg
 
page_fault_exc: ; äóðàêîóñòî÷èâîñòü: ñåëåêòîðû èñïîð÷åíû...
pop [ss:pf_err_code]; äåéñòâèòåëüíî äî ñëåäóþùåãî #PF
save_ring3_context
mov bl, 14
 
exc_c: ; èñêëþ÷åíèÿ (âñå, êðîìå 7-ãî - #NM)
; Ôðýéì ñòåêà ïðè èñêëþ÷åíèè/ïðåðûâàíèè èç 3-ãî êîëüöà + pushad (ò.å., èìåííî çäåñü)
reg_ss equ esp+0x30
reg_esp3 equ esp+0x2C
reg_eflags equ esp+0x28
reg_cs3 equ esp+0x24
reg_eip equ esp+0x20
; ýòî ôðýéì îò pushad
reg_eax equ esp+0x1C
reg_ecx equ esp+0x18
reg_edx equ esp+0x14
reg_ebx equ esp+0x10
reg_esp0 equ esp+0x0C
reg_ebp equ esp+0x08
reg_esi equ esp+0x04
reg_edi equ esp+0x00
 
mov ax, app_data ;èñêëþ÷åíèå
mov ds, ax ;çàãðóçèì ïðàâèëüíûå çíà÷åíèÿ
mov es, ax ;â ðåãèñòðû
cld ; è ïðèâîäèì DF ê ñòàíäàðòó
movzx ebx, bl
; redirect to V86 manager? (EFLAGS & 0x20000) != 0?
test byte[reg_eflags+2], 2
jnz v86_exc_c
cmp bl, 14 ; #PF
jne @f
call page_fault_handler ; SEE: core/memory.inc
@@:
mov esi, [current_slot]
btr [esi+APPDATA.except_mask], ebx
jnc @f
mov eax, [esi+APPDATA.exc_handler]
test eax, eax
jnz IRetToUserHook
@@:
cli
mov eax, [esi+APPDATA.debugger_slot]
test eax, eax
jnz .debug
sti
; not debuggee => say error and terminate
call show_error_parameters ;; only ONE using, inline ???
 
; kill open sockets
pusha
mov edx, [edx + TASKDATA.pid]
call SOCKET_process_end
popa
 
mov [edx + TASKDATA.state], byte 4 ; terminate
jmp change_task ; stack - here it does not matter at all, SEE: core/shed.inc
.debug:
; we are debugged process, notify debugger and suspend ourself
; eax=debugger PID
mov ecx, 1 ; debug_message code=other_exception
cmp bl, 1 ; #DB
jne .notify ; notify debugger and suspend ourself
mov ebx, dr6 ; debug_message data=DR6_image
xor edx, edx
mov dr6, edx
mov edx, dr7
mov cl, not 8
.l1:
shl dl, 2
jc @f
and bl, cl
@@:
sar cl, 1
jc .l1
mov cl, 3 ; debug_message code=debug_exception
.notify:
push ebx ; debug_message data
mov ebx, [TASK_BASE]
push [ebx+TASKDATA.pid] ; PID
push ecx ; debug_message code ((here: ecx==1/3))
mov cl, 12 ; debug_message size
call debugger_notify ;; only ONE using, inline ??? SEE: core/debug.inc
add esp, 12
mov edx, [TASK_BASE]
mov byte [edx+TASKDATA.state], 1 ; suspended
call change_task ; SEE: core/shed.inc
restore_ring3_context
iretd
 
IRetToUserHook:
xchg eax, [reg_eip]
sub dword[reg_esp3], 8
mov edi, [reg_esp3]
stosd
mov [edi], ebx
restore_ring3_context
; simply return control to interrupted process
unknown_interrupt:
iretd
 
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; bl - error vector
show_error_parameters:
cmp bl, 0x06
jnz .no_ud
push ebx
mov ebx, ud_user_message
mov ebp, notifyapp
call fs_execute_from_sysdir_param
pop ebx
.no_ud:
mov edx, [TASK_BASE];not scratched below
if lang eq sp
DEBUGF 1, "K : Proceso - terminado forzado PID: %x [%s]\n", [edx+TASKDATA.pid], [current_slot]
else
DEBUGF 1, "K : Process - forced terminate PID: %x [%s]\n", [edx+TASKDATA.pid], [current_slot]
end if
cmp bl, 0x08
jb .l0
cmp bl, 0x0e
jbe .l1
.l0:
mov bl, 0x09
.l1:
mov eax, [msg_fault_sel+ebx*4 - 0x08*4]
DEBUGF 1, "K : %s\n", eax
mov eax, [reg_cs3+4]
mov edi, msg_sel_app
mov ebx, [reg_esp3+4]
cmp eax, app_code
je @f
mov edi, msg_sel_ker
mov ebx, [reg_esp0+4]
@@:
DEBUGF 1, "K : EAX : %x EBX : %x ECX : %x\n", [reg_eax+4], [reg_ebx+4], [reg_ecx+4]
DEBUGF 1, "K : EDX : %x ESI : %x EDI : %x\n", [reg_edx+4], [reg_esi+4], [reg_edi+4]
DEBUGF 1, "K : EBP : %x EIP : %x ESP : %x\n", [reg_ebp+4], [reg_eip+4], ebx
DEBUGF 1, "K : Flags : %x CS : %x (%s)\n", [reg_eflags+4], eax, edi
ret
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
restore reg_ss
restore reg_esp3
restore reg_eflags
restore reg_cs
restore reg_eip
restore reg_eax
restore reg_ecx
restore reg_edx
restore reg_ebx
restore reg_esp0
restore reg_ebp
restore reg_esi
restore reg_edi
 
 
align 4
set_application_table_status:
push eax
 
mov eax, [CURRENT_TASK]
shl eax, 5
add eax, CURRENT_TASK+TASKDATA.pid
mov eax, [eax]
 
mov [application_table_status], eax
 
pop eax
 
ret
 
align 4
clear_application_table_status:
push eax
 
mov eax, [CURRENT_TASK]
shl eax, 5
add eax, CURRENT_TASK+TASKDATA.pid
mov eax, [eax]
 
cmp eax, [application_table_status]
jne apptsl1
xor eax, eax
mov [application_table_status], eax
apptsl1:
 
pop eax
 
ret
 
; * eax = 64 - íîìåð ôóíêöèè
; * ebx = 1 - åäèíñòâåííàÿ ïîäôóíêöèÿ
; * ecx = íîâûé ðàçìåð ïàìÿòè
;Âîçâðàùàåìîå çíà÷åíèå:
; * eax = 0 - óñïåøíî
; * eax = 1 - íåäîñòàòî÷íî ïàìÿòè
 
align 4
sys_resize_app_memory:
; ebx = 1 - resize
; ecx = new amount of memory
 
; cmp eax,1
dec ebx
jnz .no_application_mem_resize
stdcall new_mem_resize, ecx
mov [esp+32], eax
.no_application_mem_resize:
ret
 
iglobal
; process_terminating db 'K : Process - terminating',13,10,0
; process_terminated db 'K : Process - done',13,10,0
msg_obj_destroy db 'K : destroy app object',13,10,0
endg
 
; param
; esi= slot
 
align 4
terminate: ; terminate application
 
.slot equ esp ;locals
 
push esi ;save .slot
 
shl esi, 8
cmp [SLOT_BASE+esi+APPDATA.dir_table], 0
jne @F
pop esi
shl esi, 5
mov [CURRENT_TASK+esi+TASKDATA.state], 9
ret
@@:
;mov esi,process_terminating
;call sys_msg_board_str
@@:
cli
cmp [application_table_status], 0
je term9
sti
call change_task
jmp @b
term9:
call set_application_table_status
 
; if the process is in V86 mode...
mov eax, [.slot]
shl eax, 8
mov esi, [eax+SLOT_BASE+APPDATA.pl0_stack]
add esi, RING0_STACK_SIZE
cmp [eax+SLOT_BASE+APPDATA.saved_esp0], esi
jz .nov86
; ...it has page directory for V86 mode
mov esi, [eax+SLOT_BASE+APPDATA.saved_esp0]
mov ecx, [esi+4]
mov [eax+SLOT_BASE+APPDATA.dir_table], ecx
; ...and I/O permission map for V86 mode
mov ecx, [esi+12]
mov [eax+SLOT_BASE+APPDATA.io_map], ecx
mov ecx, [esi+8]
mov [eax+SLOT_BASE+APPDATA.io_map+4], ecx
.nov86:
 
mov esi, [.slot]
shl esi, 8
add esi, SLOT_BASE+APP_OBJ_OFFSET
@@:
mov eax, [esi+APPOBJ.fd]
test eax, eax
jz @F
 
cmp eax, esi
je @F
 
push esi
call [eax+APPOBJ.destroy]
DEBUGF 1,"%s",msg_obj_destroy
pop esi
jmp @B
@@:
 
mov eax, [.slot]
shl eax, 8
stdcall destroy_app_space, [SLOT_BASE+eax+APPDATA.dir_table], [SLOT_BASE+eax+APPDATA.dlls_list_ptr]
 
mov esi, [.slot]
cmp [fpu_owner], esi ; if user fpu last -> fpu user = 1
jne @F
 
mov [fpu_owner], 1
mov eax, [256+SLOT_BASE+APPDATA.fpu_state]
clts
bt [cpu_caps], CAPS_SSE
jnc .no_SSE
fxrstor [eax]
jmp @F
.no_SSE:
fnclex
frstor [eax]
@@:
 
mov [KEY_COUNT], byte 0 ; empty keyboard buffer
mov [BTN_COUNT], byte 0 ; empty button buffer
 
 
; remove defined hotkeys
mov eax, hotkey_list
.loop:
cmp [eax+8], esi
jnz .cont
mov ecx, [eax]
jecxz @f
push dword [eax+12]
pop dword [ecx+12]
@@:
mov ecx, [eax+12]
push dword [eax]
pop dword [ecx]
xor ecx, ecx
mov [eax], ecx
mov [eax+4], ecx
mov [eax+8], ecx
mov [eax+12], ecx
.cont:
add eax, 16
cmp eax, hotkey_list+256*16
jb .loop
; get process PID
mov eax, esi
shl eax, 5
mov eax, [eax+CURRENT_TASK+TASKDATA.pid]
; compare current lock input with process PID
cmp eax, [PID_lock_input]
jne @f
 
xor eax, eax
mov [PID_lock_input], eax
@@:
; remove hotkeys in buffer
mov eax, hotkey_buffer
.loop2:
cmp [eax], esi
jnz .cont2
and dword [eax+4], 0
and dword [eax], 0
.cont2:
add eax, 8
cmp eax, hotkey_buffer+120*8
jb .loop2
 
mov ecx, esi ; remove buttons
bnewba2:
mov edi, [BTN_ADDR]
mov eax, edi
cld
movzx ebx, word [edi]
inc bx
bnewba:
dec bx
jz bnmba
add eax, 0x10
cmp cx, [eax]
jnz bnewba
pusha
mov ecx, ebx
inc ecx
shl ecx, 4
mov ebx, eax
add eax, 0x10
call memmove
dec dword [edi]
popa
jmp bnewba2
bnmba:
 
pusha ; save window coordinates for window restoring
cld
shl esi, 5
add esi, window_data
mov eax, [esi+WDATA.box.left]
mov [draw_limits.left], eax
add eax, [esi+WDATA.box.width]
mov [draw_limits.right], eax
mov eax, [esi+WDATA.box.top]
mov [draw_limits.top], eax
add eax, [esi+WDATA.box.height]
mov [draw_limits.bottom], eax
 
xor eax, eax
mov [esi+WDATA.box.left], eax
mov [esi+WDATA.box.width], eax
mov [esi+WDATA.box.top], eax
mov [esi+WDATA.box.height], eax
mov [esi+WDATA.cl_workarea], eax
mov [esi+WDATA.cl_titlebar], eax
mov [esi+WDATA.cl_frames], eax
mov dword [esi+WDATA.reserved], eax; clear all flags: wstate, redraw, wdrawn
lea edi, [esi-window_data+draw_data]
mov ecx, 32/4
rep stosd
popa
 
; debuggee test
pushad
mov edi, esi
shl edi, 5
mov eax, [SLOT_BASE+edi*8+APPDATA.debugger_slot]
test eax, eax
jz .nodebug
push 8
pop ecx
push dword [CURRENT_TASK+edi+TASKDATA.pid]; PID
push 2
call debugger_notify
pop ecx
pop ecx
.nodebug:
popad
 
mov ebx, [.slot]
shl ebx, 8
push ebx
mov ebx, [SLOT_BASE+ebx+APPDATA.pl0_stack]
 
stdcall kernel_free, ebx
 
pop ebx
mov ebx, [SLOT_BASE+ebx+APPDATA.cur_dir]
stdcall kernel_free, ebx
 
mov edi, [.slot]
shl edi, 8
add edi, SLOT_BASE
 
mov eax, [edi+APPDATA.io_map]
cmp eax, [SLOT_BASE+256+APPDATA.io_map]
je @F
call free_page
@@:
mov eax, [edi+APPDATA.io_map+4]
cmp eax, [SLOT_BASE+256+APPDATA.io_map+4]
je @F
call free_page
@@:
mov eax, 0x20202020
stosd
stosd
stosd
mov ecx, 244/4
xor eax, eax
rep stosd
 
; activate window
movzx eax, word [WIN_STACK + esi*2]
cmp eax, [TASK_COUNT]
jne .dont_activate
pushad
.check_next_window:
dec eax
cmp eax, 1
jbe .nothing_to_activate
lea esi, [WIN_POS+eax*2]
movzx edi, word [esi] ; edi = process
shl edi, 5
cmp [CURRENT_TASK + edi + TASKDATA.state], byte 9 ; skip dead slots
je .check_next_window
add edi, window_data
; \begin{diamond}[19.09.2006]
; skip minimized windows
test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED
jnz .check_next_window
; \end{diamond}
call waredraw
.nothing_to_activate:
popad
.dont_activate:
 
push esi ; remove hd1 & cd & flp reservation
shl esi, 5
mov esi, [esi+CURRENT_TASK+TASKDATA.pid]
cmp [hd1_status], esi
jnz @f
call free_hd_channel
and [hd1_status], 0
@@:
cmp [cd_status], esi
jnz @f
call free_cd_channel
and [cd_status], 0
@@:
cmp [flp_status], esi
jnz @f
and [flp_status], 0
@@:
pop esi
cmp [bgrlockpid], esi
jnz @f
and [bgrlockpid], 0
and [bgrlock], 0
@@:
 
pusha ; remove all port reservations
mov edx, esi
shl edx, 5
add edx, CURRENT_TASK
mov edx, [edx+TASKDATA.pid]
 
rmpr0:
 
mov esi, [RESERVED_PORTS]
 
test esi, esi
jz rmpr9
 
rmpr3:
 
mov edi, esi
shl edi, 4
add edi, RESERVED_PORTS
 
cmp edx, [edi]
je rmpr4
 
dec esi
jnz rmpr3
 
jmp rmpr9
 
rmpr4:
 
mov ecx, 256
sub ecx, esi
shl ecx, 4
 
mov esi, edi
add esi, 16
cld
rep movsb
 
dec dword [RESERVED_PORTS]
 
jmp rmpr0
 
rmpr9:
 
popa
mov edi, esi ; do not run this process slot
shl edi, 5
mov [edi+CURRENT_TASK + TASKDATA.state], byte 9
; debugger test - terminate all debuggees
mov eax, 2
mov ecx, SLOT_BASE+2*0x100+APPDATA.debugger_slot
.xd0:
cmp eax, [TASK_COUNT]
ja .xd1
cmp dword [ecx], esi
jnz @f
and dword [ecx], 0
pushad
xchg eax, ecx
mov ebx, 2
call sys_system
popad
@@:
inc eax
add ecx, 0x100
jmp .xd0
.xd1:
; call systest
sti ; .. and life goes on
 
mov eax, [draw_limits.left]
mov ebx, [draw_limits.top]
mov ecx, [draw_limits.right]
mov edx, [draw_limits.bottom]
call calculatescreen
xor eax, eax
xor esi, esi
call redrawscreen
 
mov [MOUSE_BACKGROUND], byte 0; no mouse background
mov [DONT_DRAW_MOUSE], byte 0; draw mouse
 
and [application_table_status], 0
;mov esi,process_terminated
;call sys_msg_board_str
add esp, 4
ret
restore .slot
 
;iglobal
;if lang eq ru
; boot_sched_1 db '‘®§¤ ­¨¥ GDT TSS 㪠§ â¥«ï',0
; boot_sched_2 db '‘®§¤ ­¨¥ IDT â ¡«¨æë',0
;else
; boot_sched_1 db 'Building gdt tss pointer',0
; boot_sched_2 db 'Building IDT table',0
;end if
;endg
 
 
;build_scheduler:
; mov esi, boot_sched_1
; call boot_log
; call build_process_gdt_tss_pointer
 
; mov esi,boot_sched_2
; call boot_log
; ret
 
; Three following procedures are used to guarantee that
; some part of kernel code will not be terminated from outside
; while it is running.
; Note: they do not protect a thread from terminating due to errors inside
; the thread; accessing a nonexisting memory would still terminate it.
 
; First two procedures must be used in pair by thread-to-be-protected
; to signal the beginning and the end of an important part.
; It is OK to have nested areas.
 
; The last procedure must be used by outside wanna-be-terminators;
; if it is safe to terminate the given thread immediately, it returns eax=1;
; otherwise, it returns eax=0 and notifies the target thread that it should
; terminate itself when leaving a critical area (the last critical area if
; they are nested).
 
; Implementation. Those procedures use one dword in APPDATA for the thread,
; APPDATA.terminate_protection.
; * The upper bit is 1 during normal operations and 0 when terminate is requested.
; * Other bits form a number = depth of critical regions,
; plus 1 if the upper bit is 1.
; * When this dword goes to zero, the thread should be destructed,
; and the procedure in which it happened becomes responsible for destruction.
 
; Enter critical area. Called by thread which wants to be protected.
proc protect_from_terminate
mov edx, [current_slot]
; Atomically increment depth of critical areas and get the old value.
mov eax, 1
lock xadd [edx+APPDATA.terminate_protection], eax
; If the old value was zero, somebody has started to terminate us,
; so we are destructing and cannot do anything protected.
; Otherwise, return to the caller.
test eax, eax
jz @f
ret
@@:
; Wait for somebody to finish us.
call change_task
jmp @b
endp
 
; Leave critical area. Called by thread which wants to be protected.
proc unprotect_from_terminate
mov edx, [current_slot]
; Atomically decrement depth of critical areas.
lock dec [edx+APPDATA.terminate_protection]
; If the result of decrement is zero, somebody has requested termination,
; but at that moment we were inside a critical area; terminate now.
jz sys_end
; Otherwise, return to the caller.
ret
endp
 
; Request termination of thread identified by edx = SLOT_BASE + slot*256.
; Called by anyone.
proc request_terminate
xor eax, eax ; set return value
; Atomically clear the upper bit. If it was already zero, then
; somebody has requested termination before us, so just exit.
lock btr [edx+APPDATA.terminate_protection], 31
jnc .unsafe
; Atomically decrement depth of critical areas.
lock dec [edx+APPDATA.terminate_protection]
; If the result of decrement is nonzero, the target thread is inside a
; critical area; leave termination to leaving that area.
jnz .unsafe
; Otherwise, it is safe to kill the target now and the caller is responsible
; for this. Return eax=1.
inc eax
.unsafe:
ret
endp
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/syscall.inc
0,0 → 1,213
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
; Old style system call converter
align 16
cross_order:
; load all registers in crossed order
mov eax, ebx
mov ebx, ecx
mov ecx, edx
mov edx, esi
mov esi, edi
movzx edi, byte[esp+28 + 4]
sub edi, 53
call dword [servetable+edi*4]
ret
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SYSENTER ENTRY ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 32
sysenter_entry:
; Íàñòðàèâàåì ñòåê
mov esp, [ss:tss._esp0]
sti
push ebp ; save app esp + 4
mov ebp, [ebp] ; ebp - original ebp
;------------------
pushad
cld
 
call protect_from_terminate
 
movzx eax, byte [esp+28]
mov edx, dword [esp+20]
call dword [servetable2 + eax * 4]
 
call unprotect_from_terminate
popad
;------------------
xchg ecx, [ss:esp] ; â âåðøèí ñòåêà - app ecx, ecx - app esp + 4
sub ecx, 4
xchg edx, [ecx] ; edx - return point, & save original edx
push edx
mov edx, [ss:esp + 4]
mov [ecx + 4], edx ; save original ecx
pop edx
sysexit
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SYSTEM CALL ENTRY ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 16
i40:
pushad
cld
call protect_from_terminate
movzx eax, byte [esp+28]
mov edx, dword [esp+20]
call dword [servetable2 + eax * 4]
call unprotect_from_terminate
popad
iretd
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SYSCALL ENTRY ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 32
syscall_entry:
; cli syscall clear IF
xchg esp, [ss:tss._esp0]
push ecx
lea ecx, [esp+4]
xchg ecx, [ss:tss._esp0]
sti
push ecx
mov ecx, [ecx]
;------------------
pushad
cld
call protect_from_terminate
 
movzx eax, byte [esp+28]
mov edx, dword [esp+20]
call dword [servetable2 + eax * 4]
 
call unprotect_from_terminate
popad
;------------------
mov ecx, [ss:esp+4]
pop esp
sysret
 
iglobal
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SYSTEM FUNCTIONS TABLE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
servetable:
dd 0
dd 0
dd 0
dd 0
dd 0
dd file_system ; 58-Common file system interface
dd 0
dd 0
dd 0
dd 0 ; 62-PCI functions
dd sys_msg_board ; 63-System message board
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; NEW SYSTEM FUNCTIONS TABLE ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
servetable2:
 
dd syscall_draw_window ; 0-DrawWindow
dd syscall_setpixel ; 1-SetPixel
dd sys_getkey ; 2-GetKey
dd sys_clock ; 3-GetTime
dd syscall_writetext ; 4-WriteText
dd delay_hs_unprotected ; 5-DelayHs
dd syscall_openramdiskfile ; 6-OpenRamdiskFile
dd syscall_putimage ; 7-PutImage
dd syscall_button ; 8-DefineButton
dd sys_cpuusage ; 9-GetProcessInfo
dd sys_waitforevent ; 10-WaitForEvent
dd sys_getevent ; 11-CheckForEvent
dd sys_redrawstat ; 12-BeginDraw and EndDraw
dd syscall_drawrect ; 13-DrawRect
dd syscall_getscreensize ; 14-GetScreenSize
dd sys_background ; 15-bgr
dd sys_cachetodiskette ; 16-FlushFloppyCache
dd sys_getbutton ; 17-GetButton
dd sys_system ; 18-System Services
dd paleholder ; 19-reserved
dd sys_midi ; 20-ResetMidi and OutputMidi
dd sys_setup ; 21-SetMidiBase,SetKeymap,SetShiftKeymap,.
dd sys_settime ; 22-setting date,time,clock and alarm-clock
dd sys_wait_event_timeout ; 23-TimeOutWaitForEvent
dd syscall_cdaudio ; 24-PlayCdTrack,StopCd and GetCdPlaylist
dd syscall_putarea_backgr ; 25-Put Area to background
dd sys_getsetup ; 26-GetMidiBase,GetKeymap,GetShiftKeymap,.
dd undefined_syscall ; 27-reserved
dd undefined_syscall ; 28-reserved
dd sys_date ; 29-GetDate
dd sys_current_directory ; 30-Get/SetCurrentDirectory
dd undefined_syscall ; 31-reserved
dd undefined_syscall ; 32-reserved
dd undefined_syscall ; 33-reserved
dd syscall_getpixel_WinMap ; 34-GetPixel WinMap
dd syscall_getpixel ; 35-GetPixel
dd syscall_getarea ; 36-GetArea
dd readmousepos ; 37-GetMousePosition_ScreenRelative,.
dd syscall_drawline ; 38-DrawLine
dd sys_getbackground ; 39-GetBackgroundSize,ReadBgrData,.
dd set_app_param ; 40-WantEvents
dd undefined_syscall ; 41- deprecated GetIrqOwner
dd undefined_syscall ; 42- deprecated ReadIrqData
dd sys_outport ; 43-SendDeviceData
dd undefined_syscall ; 44- deprecated ProgramIrqs
dd undefined_syscall ; 45- deprecated ReserveIrq and FreeIrq
dd syscall_reserveportarea ; 46-ReservePortArea and FreePortArea
dd display_number ; 47-WriteNum
dd syscall_display_settings ; 48-SetRedrawType and SetButtonType
dd sys_apm ; 49-Advanced Power Management (APM)
dd syscall_set_window_shape ; 50-Window shape & scale
dd syscall_threads ; 51-Threads
dd undefined_syscall ; 52 old network stack
dd undefined_syscall ; 53 old network stack
dd undefined_syscall ; 54-reserved
dd sound_interface ; 55-Sound interface
dd undefined_syscall ; 56-reserved
dd sys_pcibios ; 57-PCI BIOS32
dd cross_order ; 58-Common file system interface
dd undefined_syscall ; 59-reserved
dd sys_IPC ; 60-Inter Process Communication
dd sys_gs ; 61-Direct graphics access
dd pci_api ;cross_order ; 62-PCI functions
dd cross_order ; 63-System message board
dd sys_resize_app_memory ; 64-Resize application memory usage
dd sys_putimage_palette ; 65-PutImagePalette
dd sys_process_def ; 66-Process definitions - keyboard
dd syscall_move_window ; 67-Window move or resize
dd f68 ; 68-Some internal services
dd sys_debug_services ; 69-Debug
dd file_system_lfn ; 70-Common file system interface, version 2
dd syscall_window_settings ; 71-Window settings
dd sys_sendwindowmsg ; 72-Send window message
dd blit_32 ; 73-blitter;
dd sys_network ; 74-Network stack
dd sys_socket ; 75-Sockets
dd sys_protocols ; 76-Protocols
times 255 - ( ($-servetable2) /4 ) dd undefined_syscall
dd sys_end ; -1-end application
 
endg
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/taskman.inc
0,0 → 1,1245
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
GREEDY_KERNEL equ 0
 
struct APP_HEADER_00_
banner dq ?
version dd ? ;+8
start dd ? ;+12
i_end dd ? ;+16
mem_size dd ? ;+20
i_param dd ? ;+24
ends
 
struct APP_HEADER_01_
banner dq ?
version dd ? ;+8
start dd ? ;+12
i_end dd ? ;+16
mem_size dd ? ;+20
stack_top dd ? ;+24
i_param dd ? ;+28
i_icon dd ? ;+32
ends
 
 
hdrVersion1 = 1 ; it is the old version of the header, without console fields
hdrVersionConsole = 2 ; it is the new version of the header, containing 2 mode dword fields
 
struct APP_HEADER_02_
banner dq ? ; 'MENUET01'
version dd ? ;+8 ; == hdrVersionConsole
start dd ? ;+12
i_end dd ? ;+16
mem_size dd ? ;+20
stack_top dd ? ;+24
i_param dd ? ;+28
i_icon dd ? ;+32
 
stdio dd ?
stderr dd ?
ends
 
 
struct APP_PARAMS
app_cmdline dd ? ;0x00
app_path dd ? ;0x04
app_eip dd ? ;0x08
app_esp dd ? ;0x0C
app_mem dd ? ;0x10
ends
 
; not needed
;macro _clear_ op
;{ mov ecx, op/4
; xor eax, eax
; cld
; rep stosd
;}
 
fs_execute_from_sysdir:
xor ebx, ebx ; command line arguments.
fs_execute_from_sysdir_param:
xor eax, eax ; no STDIO
xor ecx, ecx ; no STDERR
 
xor edx, edx ; flags (currently only debug flag).
mov esi, sysdir_path
 
align 4
proc fs_execute
; eax - STDIO handle
; ecx - STDERR handle
 
; ebx - cmdline
; edx - flags
; ebp - full filename
 
locals
cmdline rd 64 ;256/4
filename rd 256 ;1024/4
flags dd ?
 
save_cr3 dd ?
slot dd ?
slot_base dd ?
file_base dd ?
file_size dd ?
handle dd ? ;temp. for default cursor handle for curr. thread
;app header data
hdr_cmdline dd ? ;0x00
hdr_path dd ? ;0x04
hdr_eip dd ? ;0x08
hdr_esp dd ? ;0x0C
hdr_mem dd ? ;0x10
hdr_i_end dd ? ;0x14
 
hdr_stdio dd ?
hdr_stderr dd ?
endl
 
pushad
 
mov [hdr_stdio], eax
mov [hdr_stderr], ecx
 
cmp [SCR_MODE], word 0x13
jbe @f
 
pushad
stdcall set_cursor, [def_cursor_clock]
mov [handle], eax
mov [redrawmouse_unconditional], 1
call __sys_draw_pointer
popad
 
@@:
mov [flags], edx
 
; [ebp] pointer to filename
 
lea edi, [filename]
lea ecx, [edi+1024]
mov al, '/'
stosb
@@:
cmp edi, ecx
jae .bigfilename
lodsb
stosb
test al, al
jnz @b
mov esi, [ebp]
test esi, esi
jz .namecopied
mov byte [edi-1], '/'
@@:
cmp edi, ecx
jae .bigfilename
lodsb
stosb
test al, al
jnz @b
jmp .namecopied
.bigfilename:
popad
mov eax, -ERROR_FILE_NOT_FOUND
 
jmp .final
 
.namecopied:
 
mov [cmdline], ebx
test ebx, ebx
jz @F
 
lea eax, [cmdline]
mov dword [eax+252], 0
stdcall strncpy, eax, ebx, 255
@@:
lea eax, [filename]
stdcall load_file, eax
 
mov esi, -ERROR_FILE_NOT_FOUND
test eax, eax
jz .err_file
 
mov [file_base], eax
mov [file_size], ebx
 
lea ebx, [hdr_cmdline]
call test_app_header
mov esi, -ERROR_INVALID_HEADER
test eax, eax
jz .err_hdr
 
; The header is OK, so check for the version and if == hdrVersionConsole, patch the header with
; the handles of the console IO socket handlers.
mov edx, [hdr_stdio]
mov ecx, [hdr_stderr]
 
cmp [eax+APP_HEADER_02_.version], hdrVersionConsole
jae .patch_header
 
or edx, ecx
jz .wait_lock
 
mov esi, -ERROR_WRONG_HEADER_VERSION
jmp .err_hdr
 
.patch_header:
mov [eax+APP_HEADER_02_.stdio], edx
mov [eax+APP_HEADER_02_.stderr], ecx
 
.wait_lock:
cmp [application_table_status], 0
je .get_lock
call change_task
jmp .wait_lock
 
.get_lock:
mov eax, 1
xchg eax, [application_table_status]
test eax, eax
jnz .wait_lock
 
call set_application_table_status
 
call get_new_process_place
test eax, eax
mov esi, -ERROR_TOO_MANY_PROCESSES
jz .err
 
mov [slot], eax
shl eax, 8
add eax, SLOT_BASE
mov [slot_base], eax
mov edi, eax
 
;_clear_ 256 ;clean extended information about process
mov ecx, 256/4
xor eax, eax
cld
rep stosd
 
; write application name
lea eax, [filename]
stdcall strrchr, eax, '/' ; now eax points to name without path
 
lea esi, [eax+1]
test eax, eax
jnz @F
lea esi, [filename]
@@:
mov ecx, 11 ; 11 chars for name! 8 - is old value!
mov edi, [slot_base]
.copy_process_name_loop:
lodsb
cmp al, '.'
jz .copy_process_name_done
test al, al
jz .copy_process_name_done
stosb
loop .copy_process_name_loop
.copy_process_name_done:
 
mov ebx, cr3
mov [save_cr3], ebx
 
stdcall create_app_space, [hdr_mem], [file_base], [file_size]
mov esi, -ERROR_MEMORY_NOT_ENOUGH ; no memory
test eax, eax
jz .failed
 
mov ebx, [slot_base]
mov [ebx+APPDATA.dir_table], eax
mov eax, [hdr_mem]
mov [ebx+APPDATA.mem_size], eax
 
xor edx, edx
cmp word [6], '02'
jne @f
 
not edx
@@:
mov [ebx+APPDATA.tls_base], edx
 
if GREEDY_KERNEL
else
mov ecx, [hdr_mem]
mov edi, [file_size]
add edi, 4095
and edi, not 4095
sub ecx, edi
jna @F
 
xor eax, eax
cld
rep stosb
@@:
end if
 
; release only virtual space, not phisical memory
 
stdcall free_kernel_space, [file_base]
lea eax, [hdr_cmdline]
lea ebx, [cmdline]
lea ecx, [filename]
stdcall set_app_params , [slot], eax, ebx, ecx, [flags]
 
mov eax, [save_cr3]
call set_cr3
 
xor ebx, ebx
mov [application_table_status], ebx;unlock application_table_status mutex
mov eax, [process_number];set result
 
jmp .final
 
.failed:
mov eax, [save_cr3]
call set_cr3
.err:
.err_hdr:
stdcall kernel_free, [file_base]
.err_file:
xor eax, eax
mov [application_table_status], eax
mov eax, esi
.final:
cmp [SCR_MODE], word 0x13
jbe @f
pushad
stdcall set_cursor, [handle]
mov [redrawmouse_unconditional], 1
call __sys_draw_pointer
popad
@@:
ret
endp
 
align 4
test_app_header:
virtual at eax
APP_HEADER_00 APP_HEADER_00_
end virtual
virtual at eax
APP_HEADER_01 APP_HEADER_01_
end virtual
 
cmp dword [eax], 'MENU'
jne .fail
cmp word [eax+4], 'ET'
jne .fail
 
cmp [eax+6], word '00'
jne .check_01_header
 
mov ecx, [APP_HEADER_00.start]
mov [ebx+0x08], ecx ;app_eip
mov edx, [APP_HEADER_00.mem_size]
mov [ebx+0x10], edx ;app_mem
shr edx, 1
sub edx, 0x10
mov [ebx+0x0C], edx ;app_esp
mov ecx, [APP_HEADER_00.i_param]
mov [ebx], ecx ;app_cmdline
mov [ebx+4], dword 0 ;app_path
mov edx, [APP_HEADER_00.i_end]
mov [ebx+0x14], edx
ret
 
.check_01_header:
 
cmp [eax+6], word '01'
je @f
cmp [eax+6], word '02'
jne .fail
@@:
mov ecx, [APP_HEADER_01.start]
mov [ebx+0x08], ecx ;app_eip
mov edx, [APP_HEADER_01.mem_size]
 
; \begin{diamond}[20.08.2006]
; sanity check (functions 19,58 load app_i_end bytes and that must
; fit in allocated memory to prevent kernel faults)
cmp edx, [APP_HEADER_01.i_end]
jb .fail
; \end{diamond}[20.08.2006]
 
mov [ebx+0x10], edx ;app_mem
mov ecx, [APP_HEADER_01.stack_top]
mov [ebx+0x0C], ecx ;app_esp
mov edx, [APP_HEADER_01.i_param]
mov [ebx], edx ;app_cmdline
mov ecx, [APP_HEADER_01.i_icon]
mov [ebx+4], ecx ;app_path
mov edx, [APP_HEADER_01.i_end]
mov [ebx+0x14], edx
ret
.fail:
xor eax, eax
ret
 
align 4
proc get_new_process_place
;input:
; none
;result:
; eax=[new_process_place]<>0 - ok
; 0 - failed.
;This function find least empty slot.
;It doesn't increase [TASK_COUNT]!
mov eax, CURRENT_TASK
mov ebx, [TASK_COUNT]
inc ebx
shl ebx, 5
add ebx, eax ;ebx - address of process information for (last+1) slot
.newprocessplace:
;eax = address of process information for current slot
cmp eax, ebx
jz .endnewprocessplace ;empty slot after high boundary
add eax, 0x20
cmp word [eax+0xa], 9;check process state, 9 means that process slot is empty
jnz .newprocessplace
.endnewprocessplace:
mov ebx, eax
sub eax, CURRENT_TASK
shr eax, 5 ;calculate slot index
cmp eax, 256
jge .failed ;it should be <256
mov word [ebx+0xa], 9;set process state to 9 (for slot after hight boundary)
ret
.failed:
xor eax, eax
ret
endp
 
align 4
proc create_app_space stdcall, app_size:dword,img_base:dword,img_size:dword
locals
app_pages dd ?
img_pages dd ?
dir_addr dd ?
app_tabs dd ?
endl
 
mov ecx, pg_data.mutex
call mutex_lock
 
xor eax, eax
mov [dir_addr], eax
 
mov eax, [app_size]
add eax, 4095
and eax, NOT(4095)
mov [app_size], eax
mov ebx, eax
shr eax, 12
mov [app_pages], eax
 
add ebx, 0x3FFFFF
and ebx, NOT(0x3FFFFF)
shr ebx, 22
mov [app_tabs], ebx
 
mov ecx, [img_size]
add ecx, 4095
and ecx, NOT(4095)
 
mov [img_size], ecx
shr ecx, 12
mov [img_pages], ecx
 
if GREEDY_KERNEL
lea eax, [ecx+ebx+2];only image size
else
lea eax, [eax+ebx+2];all requested memory
end if
cmp eax, [pg_data.pages_free]
ja .fail
 
call alloc_page
test eax, eax
jz .fail
mov [dir_addr], eax
stdcall map_page, [tmp_task_pdir], eax, dword PG_SW
 
mov edi, [tmp_task_pdir]
mov ecx, (OS_BASE shr 20)/4
xor eax, eax
cld
rep stosd
 
mov ecx, (OS_BASE shr 20)/4
mov esi, sys_pgdir+(OS_BASE shr 20)
rep movsd
 
mov eax, [dir_addr]
or eax, PG_SW
mov [edi-4096+(page_tabs shr 20)], eax
 
and eax, -4096
call set_cr3
 
mov edx, [app_tabs]
mov edi, new_app_base
@@:
call alloc_page
test eax, eax
jz .fail
 
stdcall map_page_table, edi, eax
add edi, 0x00400000
dec edx
jnz @B
 
mov edi, new_app_base
shr edi, 10
add edi, page_tabs
 
mov ecx, [app_tabs]
shl ecx, 10
xor eax, eax
rep stosd
 
mov ecx, [img_pages]
mov ebx, PG_UW
mov edx, new_app_base
mov esi, [img_base]
mov edi, new_app_base
shr esi, 10
shr edi, 10
add esi, page_tabs
add edi, page_tabs
.remap:
lodsd
or eax, ebx; force user level r/w access
stosd
add edx, 0x1000
dec [app_pages]
dec ecx
jnz .remap
 
mov ecx, [app_pages]
test ecx, ecx
jz .done
 
if GREEDY_KERNEL
mov eax, 0x02
rep stosd
else
 
.alloc:
call alloc_page
test eax, eax
jz .fail
 
stdcall map_page, edx, eax, dword PG_UW
add edx, 0x1000
dec [app_pages]
jnz .alloc
end if
 
.done:
stdcall map_page, [tmp_task_pdir], dword 0, dword PG_UNMAP
 
mov ecx, pg_data.mutex
call mutex_unlock
mov eax, [dir_addr]
ret
.fail:
mov ecx, pg_data.mutex
call mutex_unlock
cmp [dir_addr], 0
je @f
stdcall destroy_app_space, [dir_addr], 0
@@:
xor eax, eax
ret
endp
 
align 4
set_cr3:
 
mov ebx, [current_slot]
mov [ebx+APPDATA.dir_table], eax
mov cr3, eax
ret
 
align 4
proc destroy_page_table stdcall, pg_tab:dword
 
push esi
 
mov esi, [pg_tab]
mov ecx, 1024
.free:
mov eax, [esi]
test eax, 1
jz .next
test eax, 1 shl 9
jnz .next ;skip shared pages
call free_page
.next:
add esi, 4
dec ecx
jnz .free
pop esi
ret
endp
 
align 4
proc destroy_app_space stdcall, pg_dir:dword, dlls_list:dword
 
xor edx, edx
push edx
mov eax, 0x2
mov ebx, [pg_dir]
.loop:
;eax = current slot of process
mov ecx, eax
shl ecx, 5
cmp byte [CURRENT_TASK+ecx+0xa], 9;if process running?
jz @f ;skip empty slots
shl ecx, 3
add ecx, SLOT_BASE
cmp [ecx+APPDATA.dir_table], ebx;compare page directory addresses
jnz @f
mov [ebp-4], ecx
inc edx ;thread found
@@:
inc eax
cmp eax, [TASK_COUNT] ;exit loop if we look through all processes
jle .loop
 
;edx = number of threads
;our process is zombi so it isn't counted
pop ecx
cmp edx, 1
jg .ret
;if there isn't threads then clear memory.
mov esi, [dlls_list]
call destroy_all_hdlls;ecx=APPDATA
 
mov ecx, pg_data.mutex
call mutex_lock
 
mov eax, [pg_dir]
and eax, not 0xFFF
stdcall map_page, [tmp_task_pdir], eax, PG_SW
mov esi, [tmp_task_pdir]
mov edi, (OS_BASE shr 20)/4
.destroy:
mov eax, [esi]
test eax, 1
jz .next
and eax, not 0xFFF
stdcall map_page, [tmp_task_ptab], eax, PG_SW
stdcall destroy_page_table, [tmp_task_ptab]
mov eax, [esi]
call free_page
.next:
add esi, 4
dec edi
jnz .destroy
 
mov eax, [pg_dir]
call free_page
.exit:
stdcall map_page, [tmp_task_ptab], 0, PG_UNMAP
stdcall map_page, [tmp_task_pdir], 0, PG_UNMAP
mov ecx, pg_data.mutex
call mutex_unlock
.ret:
ret
endp
 
align 4
get_pid:
mov eax, [TASK_BASE]
mov eax, [eax+TASKDATA.pid]
ret
 
pid_to_slot:
;Input:
; eax - pid of process
;Output:
; eax - slot of process or 0 if process don't exists
;Search process by PID.
push ebx
push ecx
mov ebx, [TASK_COUNT]
shl ebx, 5
mov ecx, 2*32
 
.loop:
;ecx=offset of current process info entry
;ebx=maximum permitted offset
cmp byte [CURRENT_TASK+ecx+0xa], 9
jz .endloop ;skip empty slots
cmp [CURRENT_TASK+ecx+0x4], eax;check PID
jz .pid_found
.endloop:
add ecx, 32
cmp ecx, ebx
jle .loop
 
pop ecx
pop ebx
xor eax, eax
ret
 
.pid_found:
shr ecx, 5
mov eax, ecx ;convert offset to index of slot
pop ecx
pop ebx
ret
 
check_region:
;input:
; esi - start of buffer
; edx - size of buffer
;result:
; eax = 1 region lays in app memory
; eax = 0 region don't lays in app memory
mov eax, [CURRENT_TASK]
; jmp check_process_region
;-----------------------------------------------------------------------------
;check_process_region:
;input:
; eax - slot
; esi - start of buffer
; edx - size of buffer
;result:
; eax = 1 region lays in app memory
; eax = 0 region don't lays in app memory
 
test edx, edx
jle .ok
shl eax, 5
cmp word [CURRENT_TASK+eax+0xa], 0
jnz .failed
shl eax, 3
mov eax, [SLOT_BASE+eax+0xb8]
test eax, eax
jz .failed
 
mov eax, 1
ret
 
 
; call MEM_Get_Linear_Address
; push ebx
; push ecx
; push edx
; mov edx,ebx
; and edx,not (4096-1)
; sub ebx,edx
; add ecx,ebx
; mov ebx,edx
; add ecx,(4096-1)
; and ecx,not (4096-1)
;.loop:
;;eax - linear address of page directory
;;ebx - current page
;;ecx - current size
; mov edx,ebx
; shr edx,22
; mov edx,[eax+4*edx]
; and edx,not (4096-1)
; test edx,edx
; jz .failed1
; push eax
; mov eax,edx
; call MEM_Get_Linear_Address
; mov edx,ebx
; shr edx,12
; and edx,(1024-1)
; mov eax,[eax+4*edx]
; and eax,not (4096-1)
; test eax,eax
; pop eax
; jz .failed1
; add ebx,4096
; sub ecx,4096
; jg .loop
; pop edx
; pop ecx
; pop ebx
.ok:
mov eax, 1
ret
;
;.failed1:
; pop edx
; pop ecx
; pop ebx
.failed:
xor eax, eax
ret
 
align 4
proc read_process_memory
;Input:
; eax - process slot
; ecx - buffer address
; edx - buffer size
; esi - start address in other process
;Output:
; eax - number of bytes read.
locals
slot dd ?
buff dd ?
r_count dd ?
offset dd ?
tmp_r_cnt dd ?
endl
 
mov [slot], eax
mov [buff], ecx
and [r_count], 0
mov [tmp_r_cnt], edx
mov [offset], esi
 
pushad
.read_mem:
mov edx, [offset]
mov ebx, [tmp_r_cnt]
 
mov ecx, 0x400000
and edx, 0x3FFFFF
sub ecx, edx
cmp ecx, ebx
jbe @f
mov ecx, ebx
@@:
cmp ecx, 0x8000
jna @F
mov ecx, 0x8000
@@:
mov ebx, [offset]
 
push ecx
stdcall map_memEx, [proc_mem_map], \
[slot], ebx, ecx, PG_MAP
pop ecx
 
mov esi, [offset]
and esi, 0xfff
sub eax, esi
jbe .ret
cmp ecx, eax
jbe @f
mov ecx, eax
mov [tmp_r_cnt], eax
@@:
add esi, [proc_mem_map]
mov edi, [buff]
mov edx, ecx
rep movsb
add [r_count], edx
 
add [offset], edx
sub [tmp_r_cnt], edx
jnz .read_mem
.ret:
popad
mov eax, [r_count]
ret
endp
 
align 4
proc write_process_memory
;Input:
; eax - process slot
; ecx - buffer address
; edx - buffer size
; esi - start address in other process
;Output:
; eax - number of bytes written
 
locals
slot dd ?
buff dd ?
w_count dd ?
offset dd ?
tmp_w_cnt dd ?
endl
 
mov [slot], eax
mov [buff], ecx
and [w_count], 0
mov [tmp_w_cnt], edx
mov [offset], esi
 
pushad
.read_mem:
mov edx, [offset]
mov ebx, [tmp_w_cnt]
 
mov ecx, 0x400000
and edx, 0x3FFFFF
sub ecx, edx
cmp ecx, ebx
jbe @f
mov ecx, ebx
@@:
cmp ecx, 0x8000
jna @F
mov ecx, 0x8000
@@:
mov ebx, [offset]
; add ebx, new_app_base
push ecx
stdcall map_memEx, [proc_mem_map], \
[slot], ebx, ecx, PG_SW
pop ecx
 
mov edi, [offset]
and edi, 0xfff
sub eax, edi
jbe .ret
cmp ecx, eax
jbe @f
mov ecx, eax
mov [tmp_w_cnt], eax
@@:
add edi, [proc_mem_map]
mov esi, [buff]
mov edx, ecx
rep movsb
 
add [w_count], edx
add [offset], edx
sub [tmp_w_cnt], edx
jnz .read_mem
.ret:
popad
mov eax, [w_count]
ret
endp
 
align 4
proc new_sys_threads
locals
slot dd ?
app_cmdline dd ? ;0x00
app_path dd ? ;0x04
app_eip dd ? ;0x08
app_esp dd ? ;0x0C
app_mem dd ? ;0x10
endl
 
cmp ebx, 1
jne .failed ;other subfunctions
 
xor eax, eax
mov [app_eip], ecx
mov [app_cmdline], eax
mov [app_esp], edx
mov [app_path], eax
;mov esi,new_process_loading
;call sys_msg_board_str
.wait_lock:
cmp [application_table_status], 0
je .get_lock
call change_task
jmp .wait_lock
 
.get_lock:
mov eax, 1
xchg eax, [application_table_status]
test eax, eax
jnz .wait_lock
 
call set_application_table_status
 
call get_new_process_place
test eax, eax
jz .failed
 
mov [slot], eax
 
mov esi, [current_slot]
mov ebx, esi ;ebx=esi - pointer to extended information about current thread
 
mov edi, eax
shl edi, 8
add edi, SLOT_BASE
mov edx, edi ;edx=edi - pointer to extended infomation about new thread
mov ecx, 256/4
xor eax, eax
cld
rep stosd ;clean extended information about new thread
mov esi, ebx
mov edi, edx
mov ecx, 11
rep movsb ;copy process name
 
mov eax, [ebx+APPDATA.heap_base]
mov [edx+APPDATA.heap_base], eax
 
mov ecx, [ebx+APPDATA.heap_top]
mov [edx+APPDATA.heap_top], ecx
 
mov eax, [ebx+APPDATA.mem_size]
mov [edx+APPDATA.mem_size], eax
 
mov ecx, [ebx+APPDATA.dir_table]
mov [edx+APPDATA.dir_table], ecx;copy page directory
 
mov eax, [ebx+APPDATA.dlls_list_ptr]
mov [edx+APPDATA.dlls_list_ptr], eax
 
mov eax, [ebx+APPDATA.tls_base]
test eax, eax
jz @F
 
push edx
stdcall user_alloc, 4096
pop edx
test eax, eax
jz .failed1;eax=0
@@:
mov [edx+APPDATA.tls_base], eax
 
lea eax, [app_cmdline]
stdcall set_app_params , [slot], eax, dword 0, \
dword 0,dword 0
 
;mov esi,new_process_running
;call sys_msg_board_str ;output information about succefull startup
xor eax, eax
mov [application_table_status], eax ;unlock application_table_status mutex
mov eax, [process_number] ;set result
ret
.failed:
xor eax, eax
.failed1:
mov [application_table_status], eax
dec eax ;-1
ret
endp
 
align 4
tls_app_entry:
 
call init_heap
stdcall user_alloc, 4096
 
mov edx, [current_slot]
mov [edx+APPDATA.tls_base], eax
mov [tls_data_l+2], ax
shr eax, 16
mov [tls_data_l+4], al
mov [tls_data_l+7], ah
mov dx, app_tls
mov fs, dx
popad
iretd
 
 
EFL_IF equ 0x0200
EFL_IOPL1 equ 0x1000
EFL_IOPL2 equ 0x2000
EFL_IOPL3 equ 0x3000
 
 
align 4
proc set_app_params stdcall,slot:dword, params:dword,\
cmd_line:dword, app_path:dword, flags:dword
 
locals
pl0_stack dd ?
endl
 
stdcall kernel_alloc, RING0_STACK_SIZE+512
mov [pl0_stack], eax
 
lea edi, [eax+RING0_STACK_SIZE]
 
mov eax, [slot]
mov ebx, eax
 
shl eax, 8
mov [eax+SLOT_BASE+APPDATA.fpu_state], edi
mov [eax+SLOT_BASE+APPDATA.exc_handler], 0
mov [eax+SLOT_BASE+APPDATA.except_mask], 0
mov [eax+SLOT_BASE+APPDATA.terminate_protection], 80000001h
 
;set default io permission map
mov ecx, [SLOT_BASE+256+APPDATA.io_map]
mov [eax+SLOT_BASE+APPDATA.io_map], ecx
mov ecx, [SLOT_BASE+256+APPDATA.io_map+4]
mov [eax+SLOT_BASE+APPDATA.io_map+4], ecx
 
mov esi, fpu_data
mov ecx, 512/4
rep movsd
 
cmp ebx, [TASK_COUNT]
jle .noinc
inc dword [TASK_COUNT] ;update number of processes
.noinc:
shl ebx, 8
lea edx, [ebx+SLOT_BASE+APP_EV_OFFSET]
mov [SLOT_BASE+APPDATA.fd_ev+ebx], edx
mov [SLOT_BASE+APPDATA.bk_ev+ebx], edx
 
add edx, APP_OBJ_OFFSET-APP_EV_OFFSET
mov [SLOT_BASE+APPDATA.fd_obj+ebx], edx
mov [SLOT_BASE+APPDATA.bk_obj+ebx], edx
 
mov ecx, [def_cursor]
mov [SLOT_BASE+APPDATA.cursor+ebx], ecx
mov eax, [pl0_stack]
mov [SLOT_BASE+APPDATA.pl0_stack+ebx], eax
add eax, RING0_STACK_SIZE
mov [SLOT_BASE+APPDATA.saved_esp0+ebx], eax
 
push ebx
stdcall kernel_alloc, 0x1000
pop ebx
mov esi, [current_slot]
mov esi, [esi+APPDATA.cur_dir]
mov ecx, 0x1000/4
mov edi, eax
mov [ebx+SLOT_BASE+APPDATA.cur_dir], eax
rep movsd
 
shr ebx, 3
mov eax, new_app_base
mov dword [CURRENT_TASK+ebx+0x10], eax
 
.add_command_line:
mov edx, [params]
mov edx, [edx] ;app_cmdline
test edx, edx
jz @f ;application doesn't need parameters
 
mov eax, edx
add eax, 256
jc @f
 
cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8]
ja @f
 
mov byte [edx], 0 ;force empty string if no cmdline given
mov eax, [cmd_line]
test eax, eax
jz @f
stdcall strncpy, edx, eax, 256
@@:
mov edx, [params]
mov edx, [edx+4];app_path
test edx, edx
jz @F ;application don't need path of file
mov eax, edx
add eax, 1024
jc @f
cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8]
ja @f
stdcall strncpy, edx, [app_path], 1024
@@:
mov ebx, [slot]
mov eax, ebx
shl ebx, 5
lea ecx, [draw_data+ebx];ecx - pointer to draw data
 
mov edx, irq0.return
cmp [ebx*8+SLOT_BASE+APPDATA.tls_base], -1
jne @F
mov edx, tls_app_entry
@@:
; set window state to 'normal' (non-minimized/maximized/rolled-up) state
mov [ebx+window_data+WDATA.fl_wstate], WSTATE_NORMAL
mov [ebx+window_data+WDATA.fl_redraw], 1
add ebx, CURRENT_TASK ;ebx - pointer to information about process
mov [ebx+TASKDATA.wnd_number], al;set window number on screen = process slot
 
mov [ebx+TASKDATA.event_mask], dword 1+2+4;set default event flags (see 40 function)
 
inc dword [process_number]
mov eax, [process_number]
mov [ebx+4], eax ;set PID
 
;set draw data to full screen
xor eax, eax
mov [ecx+0], dword eax
mov [ecx+4], dword eax
mov eax, [Screen_Max_X]
mov [ecx+8], eax
mov eax, [Screen_Max_Y]
mov [ecx+12], eax
 
mov ebx, [pl0_stack]
mov esi, [params]
lea ecx, [ebx+REG_EIP]
xor eax, eax
 
mov [ebx+REG_RET], edx
mov [ebx+REG_EDI], eax
mov [ebx+REG_ESI], eax
mov [ebx+REG_EBP], eax
mov [ebx+REG_ESP], ecx;ebx+REG_EIP
mov [ebx+REG_EBX], eax
mov [ebx+REG_EDX], eax
mov [ebx+REG_ECX], eax
mov [ebx+REG_EAX], eax
 
mov eax, [esi+0x08] ;app_eip
mov [ebx+REG_EIP], eax;app_entry
mov [ebx+REG_CS], dword app_code
mov eax, [CURRENT_TASK]
shl eax, 8 ; created by kernel?
cmp [SLOT_BASE+eax+APPDATA.dir_table], sys_pgdir - OS_BASE
jnz @f
cmp [app_path], 0 ; it is a thread?
jnz @f
mov [ebx+REG_CS], dword os_code ; kernel thread
@@:
mov [ebx+REG_EFLAGS], dword EFL_IOPL1+EFL_IF
 
mov eax, [esi+0x0C] ;app_esp
mov [ebx+REG_APP_ESP], eax;app_stack
mov [ebx+REG_SS], dword app_data
 
lea ecx, [ebx+REG_RET]
mov ebx, [slot]
shl ebx, 5
mov [ebx*8+SLOT_BASE+APPDATA.saved_esp], ecx
 
xor ecx, ecx; process state - running
; set if debuggee
test byte [flags], 1
jz .no_debug
inc ecx ; process state - suspended
mov eax, [CURRENT_TASK]
mov [SLOT_BASE+ebx*8+APPDATA.debugger_slot], eax
.no_debug:
mov [CURRENT_TASK+ebx+TASKDATA.state], cl
;mov esi,new_process_running
;call sys_msg_board_str ;output information about succefull startup
ret
endp
 
 
align 4
 
get_stack_base:
mov eax, [current_slot]
mov eax, [eax+APPDATA.pl0_stack]
ret
 
 
include "debug.inc"
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/test_malloc.asm
0,0 → 1,249
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2009-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; Tests of malloc()/free() from the kernel heap.
; This file is not included in the kernel, it is just test application.
use32
db 'MENUET01'
dd 1, start, i_end, mem, mem, 0, 0
 
start:
; Zero-initialize uglobals (as in kernel at boot)
mov ecx, (zeroend - zerostart + 3) / 4
xor eax, eax
mov edi, zerostart
rep stosd
; Initialize small heap (as in kernel at boot)
call init_malloc
; Run tests
call run_test1
call run_test2
call run_test3
; All is OK, return
or eax, -1
int 0x40
 
run_test1:
; basic test
mov eax, 1
call malloc_with_test
mov byte [eax], 0xDD
mov esi, eax
mov eax, 1
call malloc_with_test
cmp byte [esi], 0xDD
jnz memory_destroyed
mov byte [eax], 0xEE
xchg eax, esi
call free
cmp byte [esi], 0xEE
jnz memory_destroyed
xchg eax, esi
call free
ret
 
run_test2:
ret
 
run_test3:
; 1024 times run random operation.
; Randomly select malloc(random size from 1 to 1023)
; or free(random of previously allocated areas)
mov edi, 0x12345678
xor esi, esi ; 0 areas allocated
mov ebx, 1024
.loop:
imul edi, 1103515245
add edi, 12345
mov eax, edi
shr eax, 16
test ebx, 64
jz .prefer_free
.prefer_malloc:
test eax, 3
jz .free
jmp @f
.prefer_free:
test eax, 3
jnz .free
@@:
shr eax, 2
and eax, 1023
jz .loop
push ebx
push eax
; mov ecx, [saved_state_num]
; mov [saved_state+ecx*8], eax
push edi
call malloc_with_test
pop ecx
cmp ecx, edi
jnz edi_destroyed
; mov ecx, [saved_state_num]
; mov [saved_state+ecx*8+4], eax
; inc [saved_state_num]
pop ecx
pop ebx
inc esi
push ecx eax
push edi
mov edi, eax
mov eax, esi
rep stosb
pop edi
jmp .common
.free:
test esi, esi
jz .loop
xor edx, edx
div esi
sub edx, esi
neg edx
dec edx
mov eax, [esp+edx*8]
; mov ecx, [saved_state_num]
; mov [saved_state+ecx*8], -1
; mov [saved_state+ecx*8+4], eax
; inc [saved_state_num]
mov ecx, [esp+edx*8+4]
push edi eax
mov edi, eax
mov al, [edi]
repz scasb
jnz memory_destroyed
pop eax edi
push ebx edx
push edi
call free
pop ecx
cmp ecx, edi
jnz edi_destroyed
pop edx ebx
dec esi
pop eax ecx
push edi
lea edi, [esp+4]
@@:
dec edx
js @f
xchg eax, [edi]
xchg ecx, [edi+4]
add edi, 8
jmp @b
@@:
pop edi
.common:
dec ebx
jnz .loop
@@:
dec esi
js @f
pop eax ecx
call free
jmp @b
@@:
ret
 
malloc_with_test:
; calls malloc() and checks returned value
call malloc
test eax, eax
jz generic_malloc_fail
call check_mutex
call check_range
ret
 
; Stubs for kernel procedures used by heap code
mutex_init:
and dword [ecx], 0
ret
mutex_lock:
inc dword [ecx]
ret
mutex_unlock:
dec dword [ecx]
ret
 
kernel_alloc:
cmp dword [esp+4], bufsize
jnz error1
mov eax, buffer
ret 4
 
macro $Revision [args]
{
}
 
; Error handlers
error1:
mov eax, 1
jmp error_with_code
 
generic_malloc_fail:
mov eax, 2
jmp error_with_code
 
check_mutex:
cmp dword [mst.mutex], 0
jnz @f
ret
@@:
mov eax, 3
jmp error_with_code
 
check_range:
cmp eax, buffer
jb @f
cmp eax, buffer+bufsize
jae @f
ret
@@:
mov eax, 4
jmp error_with_code
 
memory_destroyed:
mov eax, 5
jmp error_with_code
 
edi_destroyed:
mov eax, 6
jmp error_with_code
 
error_with_code:
mov edx, saved_state_num
; eax = error code
; 1 signals error in testing code (wrong bufsize)
; 2 = malloc() returned NULL
; 3 = mutex not released
; 4 = weird returned value from malloc()
; 5 = memory destroyed by malloc() or free()
int3 ; simplest way to report error
jmp $-1 ; just in case
 
; Include main heap code
include '../proc32.inc'
include '../struct.inc'
include '../const.inc'
include 'malloc.inc'
 
i_end:
 
align 4
zerostart:
mst MEM_STATE
 
align 16
bufsize = 0x40000 ; change if malloc.inc changes
buffer rb bufsize
zeroend:
 
saved_state_num dd ?
saved_state rd 0x10000
 
align 4
rb 0x10000 ; for stack
mem:
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/core/timers.inc
0,0 → 1,205
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 2381 $
 
; Simple implementation of timers. All timers are organized in a double-linked
; list, and the OS loop after every timer tick processes the list.
 
; This structure describes a timer for the kernel.
struct TIMER
Next dd ?
Prev dd ?
; These fields organize a double-linked list of all timers.
TimerFunc dd ?
; Function to be called when the timer is activated.
UserData dd ?
; The value that is passed as is to .TimerFunc.
Time dd ?
; Time at which the timer should be activated.
Interval dd ?
; Interval between activations of the timer, in 0.01s.
ends
 
iglobal
align 4
; The head of timer list.
timer_list:
dd timer_list
dd timer_list
endg
uglobal
; These two variables are used to synchronize access to the global list.
; Logically, they form an recursive mutex. Physically, the first variable holds
; the slot number of the current owner or 0, the second variable holds the
; recursion count.
; The mutex should be recursive to allow a timer function to add/delete other
; timers or itself.
timer_list_owner dd 0
timer_list_numlocks dd 0
; A timer function can delete any timer, including itself and the next timer in
; the chain. To handle such situation correctly, we keep the next timer in a
; global variable, so the removing operation can update it.
timer_next dd 0
endg
 
; This internal function acquires the lock for the global list.
lock_timer_list:
mov edx, [CURRENT_TASK]
@@:
xor eax, eax
lock cmpxchg [timer_list_owner], edx
jz @f
cmp eax, edx
jz @f
call change_task
jmp @b
@@:
inc [timer_list_numlocks]
ret
 
; This internal function releases the lock for the global list.
unlock_timer_list:
dec [timer_list_numlocks]
jnz .nothing
mov [timer_list_owner], 0
.nothing:
ret
 
; This function adds a timer.
; If deltaStart is nonzero, the timer is activated after deltaStart hundredths
; of seconds starting from the current time. If interval is nonzero, the timer
; is activated every deltaWork hundredths of seconds starting from the first
; activation. The activated timer calls timerFunc as stdcall function with one
; argument userData.
; Return value is NULL if something has failed or some value which is opaque
; for the caller. Later this value can be used for cancel_timer_hs.
proc timer_hs stdcall uses ebx, deltaStart:dword, interval:dword, \
timerFunc:dword, userData:dword
; 1. Allocate memory for the TIMER structure.
; 1a. Call the allocator.
push sizeof.TIMER
pop eax
call malloc
; 1b. If allocation failed, return (go to 5) with eax = 0.
test eax, eax
jz .nothing
; 2. Setup the TIMER structure.
xchg ebx, eax
; 2a. Copy values from the arguments.
mov ecx, [interval]
mov [ebx+TIMER.Interval], ecx
mov ecx, [timerFunc]
mov [ebx+TIMER.TimerFunc], ecx
mov ecx, [userData]
mov [ebx+TIMER.UserData], ecx
; 2b. Get time of the next activation.
mov ecx, [deltaStart]
test ecx, ecx
jnz @f
mov ecx, [interval]
@@:
add ecx, [timer_ticks]
mov [ebx+TIMER.Time], ecx
; 3. Insert the TIMER structure to the global list.
; 3a. Acquire the lock.
call lock_timer_list
; 3b. Insert an item at ebx to the tail of the timer_list.
mov eax, timer_list
mov ecx, [eax+TIMER.Prev]
mov [ebx+TIMER.Next], eax
mov [ebx+TIMER.Prev], ecx
mov [eax+TIMER.Prev], ebx
mov [ecx+TIMER.Next], ebx
; 3c. Release the lock.
call unlock_timer_list
; 4. Return with eax = pointer to TIMER structure.
xchg ebx, eax
.nothing:
; 5. Returning.
ret
endp
 
; This function removes a timer.
; The only argument is [esp+4] = the value which was returned from timer_hs.
cancel_timer_hs:
push ebx ; save used register to be stdcall
; 1. Remove the TIMER structure from the global list.
; 1a. Acquire the lock.
call lock_timer_list
mov ebx, [esp+4+4]
; 1b. Delete an item at ebx from the double-linked list.
mov eax, [ebx+TIMER.Next]
mov ecx, [ebx+TIMER.Prev]
mov [eax+TIMER.Prev], ecx
mov [ecx+TIMER.Next], eax
; 1c. If we are removing the next timer in currently processing chain,
; the next timer for this timer becomes new next timer.
cmp ebx, [timer_next]
jnz @f
mov [timer_next], eax
@@:
; 1d. Release the lock.
call unlock_timer_list
; 2. Free the TIMER structure.
xchg eax, ebx
call free
; 3. Return.
pop ebx ; restore used register to be stdcall
ret 4 ; purge one dword argument to be stdcall
 
; This function is regularly called from osloop. It processes the global list
; and activates the corresponding timers.
check_timers:
; 1. Acquire the lock.
call lock_timer_list
; 2. Loop over all registered timers, checking time.
; 2a. Get the first item.
mov eax, [timer_list+TIMER.Next]
mov [timer_next], eax
.loop:
; 2b. Check for end of list.
cmp eax, timer_list
jz .done
; 2c. Get and store the next timer.
mov edx, [eax+TIMER.Next]
mov [timer_next], edx
; 2d. Check time for timer activation.
; We can't just compare [timer_ticks] and [TIMER.Time], since overflows are
; possible: if the current time is 0FFFFFFFFh ticks and timer should be
; activated in 3 ticks, the simple comparison will produce incorrect result.
; So we calculate the difference [timer_ticks] - [TIMER.Time]; if it is
; non-negative, the time is over; if it is negative, then either the time is
; not over or we have not processed this timer for 2^31 ticks, what is very
; unlikely.
mov edx, [timer_ticks]
sub edx, [eax+TIMER.Time]
js .next
; The timer should be activated now.
; 2e. Store the timer data in the stack. This is required since 2f can delete
; the timer, invalidating the content.
push [eax+TIMER.UserData] ; parameter for TimerFunc
push [eax+TIMER.TimerFunc] ; to be restored in 2g
; 2f. Calculate time of next activation or delete the timer if it is one-shot.
mov ecx, [eax+TIMER.Interval]
add [eax+TIMER.Time], ecx
test ecx, ecx
jnz .nodelete
stdcall cancel_timer_hs, eax
.nodelete:
; 2g. Activate timer, using data from the stack.
pop eax
call eax
.next:
; 2h. Advance to the next timer and continue the loop.
mov eax, [timer_next]
jmp .loop
.done:
; 3. Release the lock.
call unlock_timer_list
; 4. Return.
ret
/kernel/branches/net/core/exports.inc
0,0 → 1,201
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
iglobal
szKernel db 'KERNEL', 0
szVersion db 'version',0
 
szRegService db 'RegService',0
szGetService db 'GetService',0
szServiceHandler db 'ServiceHandler',0
szAttachIntHandler db 'AttachIntHandler',0
; szGetIntHandler db 'GetIntHandler', 0
szFpuSave db 'FpuSave',0
szFpuRestore db 'FpuRestore',0
szReservePortArea db 'ReservePortArea',0
szBoot_Log db 'Boot_Log',0
 
szMutexInit db 'MutexInit',0
szMutexLock db 'MutexLock',0
szMutexUnlock db 'MutexUnlock',0
 
szPciApi db 'PciApi', 0
szPciRead32 db 'PciRead32', 0
szPciRead16 db 'PciRead16', 0
szPciRead8 db 'PciRead8', 0
szPciWrite8 db 'PciWrite8',0
szPciWrite16 db 'PciWrite16',0
szPciWrite32 db 'PciWrite32',0
 
szAllocPage db 'AllocPage',0
szAllocPages db 'AllocPages',0
szFreePage db 'FreePage',0
szGetPgAddr db 'GetPgAddr',0
szMapPage db 'MapPage',0
szMapSpace db 'MapSpace',0
szMapIoMem db 'MapIoMem',0
szCommitPages db 'CommitPages',0
szReleasePages db 'ReleasePages',0
 
szAllocKernelSpace db 'AllocKernelSpace',0
szFreeKernelSpace db 'FreeKernelSpace',0
szKernelAlloc db 'KernelAlloc',0
szKernelFree db 'KernelFree',0
szUserAlloc db 'UserAlloc',0
szUserFree db 'UserFree',0
szKmalloc db 'Kmalloc',0
szKfree db 'Kfree',0
szCreateRingBuffer db 'CreateRingBuffer',0
 
szGetPid db 'GetPid',0
szCreateObject db 'CreateObject',0
szDestroyObject db 'DestroyObject',0
szCreateEvent db 'CreateEvent',0
szRaiseEvent db 'RaiseEvent',0
szWaitEvent db 'WaitEvent',0
szDestroyEvent db 'DestroyEvent',0
szClearEvent db 'ClearEvent',0
 
szLoadCursor db 'LoadCursor',0
 
szSysMsgBoardStr db 'SysMsgBoardStr', 0
szSysMsgBoardChar db 'SysMsgBoardChar', 0
szGetCurrentTask db 'GetCurrentTask',0
szLFBAddress db 'LFBAddress',0
szLoadFile db 'LoadFile',0
szSendEvent db 'SendEvent',0
szSetMouseData db 'SetMouseData',0
szSetKeyboardData db 'SetKeyboardData',0
szRegKeyboard db 'RegKeyboard',0
szDelKeyboard db 'DelKeyboard',0
szSleep db 'Sleep',0
szGetTimerTicks db 'GetTimerTicks',0
 
szGetDisplay db 'GetDisplay',0
szSetScreen db 'SetScreen',0
 
szStrncat db 'strncat',0
szStrncpy db 'strncpy',0
szstrncmp db 'strncmp',0
szStrnlen db 'strnlen',0
szStrchr db 'strchr',0
szStrrchr db 'strrchr',0
 
szDiskAdd db 'DiskAdd',0
szDiskDel db 'DiskDel',0
szDiskMediaChanged db 'DiskMediaChanged',0
 
szTimerHS db 'TimerHS',0
szCancelTimerHS db 'CancelTimerHS',0
 
szNetRegDev db 'NetRegDev',0
szNetUnRegDev db 'NetUnRegDev',0
szNetPtrToNum db 'NetPtrToNum',0
szNetLinkChanged db 'NetLinkChanged',0
szEth_input db 'Eth_input',0
szIPv4_input db 'IPv4_input',0
 
 
align 16
kernel_export:
dd szRegService , reg_service
dd szGetService , get_service
dd szServiceHandler , srv_handler
dd szAttachIntHandler, attach_int_handler
; dd szGetIntHandler , get_int_handler
dd szFpuSave , fpu_save
dd szFpuRestore , fpu_restore
dd szReservePortArea , r_f_port_area
dd szBoot_Log , boot_log
 
dd szMutexInit , mutex_init ;gcc fastcall
dd szMutexLock , mutex_lock ;gcc fastcall
dd szMutexUnlock , mutex_unlock ;gcc fastcall
 
dd szPciApi , pci_api_drv
dd szPciRead32 , pci_read32
dd szPciRead16 , pci_read16
dd szPciRead8 , pci_read8
dd szPciWrite8 , pci_write8
dd szPciWrite16 , pci_write16
dd szPciWrite32 , pci_write32
 
dd szAllocPage , alloc_page ;stdcall
dd szAllocPages , alloc_pages ;stdcall
dd szFreePage , free_page
dd szMapPage , map_page ;stdcall
dd szMapSpace , map_space
dd szMapIoMem , map_io_mem ;stdcall
dd szGetPgAddr , get_pg_addr
dd szCommitPages , commit_pages ;not implemented
dd szReleasePages , release_pages
 
dd szAllocKernelSpace, alloc_kernel_space ;stdcall
dd szFreeKernelSpace , free_kernel_space ;stdcall
dd szKernelAlloc , kernel_alloc ;stdcall
dd szKernelFree , kernel_free ;stdcall
dd szUserAlloc , user_alloc ;stdcall
dd szUserFree , user_free ;stdcall
dd szKmalloc , malloc
dd szKfree , free
dd szCreateRingBuffer, create_ring_buffer ;stdcall
 
dd szGetPid , get_pid
dd szCreateObject , create_kernel_object
dd szDestroyObject , destroy_kernel_object
dd szCreateEvent , create_event ;see EVENT.inc for specification
dd szRaiseEvent , raise_event ;see EVENT.inc for specification
dd szWaitEvent , wait_event ;see EVENT.inc for specification
dd szDestroyEvent , destroy_event ;see EVENT.inc for specification
dd szClearEvent , clear_event ;see EVENT.inc for specification
 
dd szLoadCursor , load_cursor ;stdcall
 
dd szSysMsgBoardStr , sys_msg_board_str
dd szSysMsgBoardChar , sys_msg_board
dd szGetCurrentTask , get_curr_task
dd szLoadFile , load_file ;retval eax, ebx
dd szSendEvent , send_event ;see EVENT.inc for specification
dd szSetMouseData , set_mouse_data ;stdcall
dd szSetKeyboardData , set_keyboard_data
dd szRegKeyboard , register_keyboard
dd szDelKeyboard , delete_keyboard
dd szSleep , delay_ms
dd szGetTimerTicks , get_timer_ticks
 
dd szGetDisplay , get_display
dd szSetScreen , set_screen
 
dd szStrncat , strncat
dd szStrncpy , strncpy
dd szstrncmp , strncmp
dd szStrnlen , strnlen
dd szStrchr , strchr
dd szStrrchr , strrchr
 
dd szDiskAdd , disk_add
dd szDiskDel , disk_del
dd szDiskMediaChanged, disk_media_changed
 
dd szTimerHS , timer_hs
dd szCancelTimerHS , cancel_timer_hs
 
dd szNetRegDev , NET_add_device
dd szNetUnRegDev , NET_remove_device
dd szNetPtrToNum , NET_ptr_to_num
dd szNetLinkChanged , NET_link_changed
dd szEth_input , ETH_input
dd szIPv4_input , IPv4_input
 
exp_lfb:
dd szLFBAddress , 0
dd 0 ;terminator, must be zero
 
endg
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/debug.inc
0,0 → 1,435
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
; diamond, 2006
sys_debug_services:
cmp ebx, 9
ja @f
jmp dword [sys_debug_services_table+ebx*4]
@@:
ret
iglobal
align 4
sys_debug_services_table:
dd debug_set_event_data
dd debug_getcontext
dd debug_setcontext
dd debug_detach
dd debug_suspend
dd debug_resume
dd debug_read_process_memory
dd debug_write_process_memory
dd debug_terminate
dd debug_set_drx
endg
debug_set_event_data:
; in: ecx = pointer
; destroys eax
mov eax, [current_slot]
mov [eax+APPDATA.dbg_event_mem], ecx
ret
 
get_debuggee_slot:
; in: ecx=PID
; out: CF=1 if error
; CF=0 and eax=slot*0x20 if ok
; out: interrupts disabled
cli
mov eax, ecx
call pid_to_slot
test eax, eax
jz .ret_bad
shl eax, 5
push ebx
mov ebx, [CURRENT_TASK]
cmp [SLOT_BASE+eax*8+APPDATA.debugger_slot], ebx
pop ebx
jnz .ret_bad
; clc ; automatically
ret
.ret_bad:
stc
ret
 
debug_detach:
; in: ecx=pid
; destroys eax,ebx
call get_debuggee_slot
jc .ret
and dword [eax*8+SLOT_BASE+APPDATA.debugger_slot], 0
call do_resume
.ret:
sti
ret
 
debug_terminate:
; in: ecx=pid
call get_debuggee_slot
jc debug_detach.ret
mov ecx, eax
shr ecx, 5
; push 2
; pop ebx
mov edx, esi
jmp sysfn_terminate
 
debug_suspend:
; in: ecx=pid
; destroys eax,ecx
cli
mov eax, ecx
call pid_to_slot
shl eax, 5
jz .ret
mov cl, [CURRENT_TASK+eax+TASKDATA.state] ; process state
test cl, cl
jz .1
cmp cl, 5
jnz .ret
mov cl, 2
.2:
mov [CURRENT_TASK+eax+TASKDATA.state], cl
.ret:
sti
ret
.1:
inc ecx
jmp .2
 
do_resume:
mov cl, [CURRENT_TASK+eax+TASKDATA.state]
cmp cl, 1
jz .1
cmp cl, 2
jnz .ret
mov cl, 5
.2:
mov [CURRENT_TASK+eax+TASKDATA.state], cl
.ret:
ret
.1:
dec ecx
jmp .2
 
debug_resume:
; in: ecx=pid
; destroys eax,ebx
cli
mov eax, ecx
call pid_to_slot
shl eax, 5
jz .ret
call do_resume
.ret:
sti
ret
 
debug_getcontext:
; in:
; ecx=pid
; edx=sizeof(CONTEXT)
; esi->CONTEXT
; destroys eax,ecx,edx,esi,edi
cmp edx, 28h
jnz .ret
; push ecx
; mov ecx, esi
call check_region
; pop ecx
dec eax
jnz .ret
call get_debuggee_slot
jc .ret
mov edi, esi
mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack]
lea esi, [eax+RING0_STACK_SIZE]
 
.ring0:
; note that following code assumes that all interrupt/exception handlers
; saves ring-3 context by pushad in this order
; top of ring0 stack: ring3 stack ptr (ss+esp), iret data (cs+eip+eflags), pushad
sub esi, 8+12+20h
lodsd ;edi
mov [edi+24h], eax
lodsd ;esi
mov [edi+20h], eax
lodsd ; ebp
mov [edi+1Ch], eax
lodsd ;esp
lodsd ;ebx
mov [edi+14h], eax
lodsd ;edx
mov [edi+10h], eax
lodsd ;ecx
mov [edi+0Ch], eax
lodsd ;eax
mov [edi+8], eax
lodsd ;eip
mov [edi], eax
lodsd ;cs
lodsd ;eflags
mov [edi+4], eax
lodsd ;esp
mov [edi+18h], eax
.ret:
sti
ret
 
debug_setcontext:
; in:
; ecx=pid
; edx=sizeof(CONTEXT)
; esi->CONTEXT
; destroys eax,ecx,edx,esi,edi
cmp edx, 28h
jnz .ret
; push ebx
; mov ebx, edx
call check_region
; pop ebx
dec eax
jnz .ret
call get_debuggee_slot
jc .stiret
; mov esi, edx
mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack]
lea edi, [eax+RING0_STACK_SIZE]
 
.ring0:
sub edi, 8+12+20h
mov eax, [esi+24h] ;edi
stosd
mov eax, [esi+20h] ;esi
stosd
mov eax, [esi+1Ch] ;ebp
stosd
scasd
mov eax, [esi+14h] ;ebx
stosd
mov eax, [esi+10h] ;edx
stosd
mov eax, [esi+0Ch] ;ecx
stosd
mov eax, [esi+8] ;eax
stosd
mov eax, [esi] ;eip
stosd
scasd
mov eax, [esi+4] ;eflags
stosd
mov eax, [esi+18h] ;esp
stosd
.stiret:
sti
.ret:
ret
 
debug_set_drx:
call get_debuggee_slot
jc .errret
mov ebp, eax
lea eax, [eax*8+SLOT_BASE+APPDATA.dbg_regs]
; [eax]=dr0, [eax+4]=dr1, [eax+8]=dr2, [eax+C]=dr3
; [eax+10]=dr7
cmp esi, OS_BASE
jae .errret
cmp dl, 3
ja .errret
mov ecx, dr7
;fix me
xchg ecx, edx
shr edx, cl
shr edx, cl
xchg ecx, edx
 
test ecx, 2 ; bit 1+2*index = G0..G3, global break enable
jnz .errret2
test dh, dh
jns .new
; clear breakpoint
movzx edx, dl
add edx, edx
and dword [eax+edx*2], 0 ; clear DR<i>
btr dword [eax+10h], edx ; clear L<i> bit
test byte [eax+10h], 55h
jnz .okret
; imul eax, ebp, tss_step/32
; and byte [eax + tss_data + TSS._trap], not 1
and [ebp*8 + SLOT_BASE+APPDATA.dbg_state], not 1
.okret:
and dword [esp+32], 0
sti
ret
.errret:
sti
mov dword [esp+32], 1
ret
.errret2:
sti
mov dword [esp+32], 2
ret
.new:
; add new breakpoint
; dl=index; dh=flags; esi=address
test dh, 0xF0
jnz .errret
mov cl, dh
and cl, 3
cmp cl, 2
jz .errret
mov cl, dh
shr cl, 2
cmp cl, 2
jz .errret
 
mov ebx, esi
test bl, dl
 
jnz .errret
or byte [eax+10h+1], 3 ; set GE and LE flags
 
movzx edx, dh
movzx ecx, dl
add ecx, ecx
bts dword [eax+10h], ecx ; set L<i> flag
add ecx, ecx
mov [eax+ecx], ebx;esi ; set DR<i>
shl edx, cl
mov ebx, 0xF
shl ebx, cl
not ebx
and [eax+10h+2], bx
or [eax+10h+2], dx ; set R/W and LEN fields
; imul eax, ebp, tss_step/32
; or byte [eax + tss_data + TSS._trap], 1
or [ebp*8 + SLOT_BASE+APPDATA.dbg_state], 1
jmp .okret
 
debug_read_process_memory:
; in:
; ecx=pid
; edx=length
; edi->buffer in debugger
; esi=address in debuggee
; out: [esp+36]=sizeof(read)
; destroys all
; push ebx
; mov ebx, esi
call check_region
; pop ebx
dec eax
jnz .err
call get_debuggee_slot
jc .err
shr eax, 5
mov ecx, edi
call read_process_memory
sti
mov dword [esp+32], eax
ret
.err:
or dword [esp+32], -1
ret
 
debug_write_process_memory:
; in:
; ecx=pid
; edx=length
; edi->buffer in debugger
; esi=address in debuggee
; out: [esp+36]=sizeof(write)
; destroys all
; push ebx
; mov ebx, esi
call check_region
; pop ebx
dec eax
jnz debug_read_process_memory.err
call get_debuggee_slot
jc debug_read_process_memory.err
shr eax, 5
mov ecx, edi
call write_process_memory
sti
mov [esp+32], eax
ret
 
debugger_notify:
; in: eax=debugger slot
; ecx=size of debug message
; [esp+4]..[esp+4+ecx]=message
; interrupts must be disabled!
; destroys all general registers
; interrupts remain disabled
xchg ebp, eax
mov edi, [timer_ticks]
add edi, 500 ; 5 sec timeout
.1:
mov eax, ebp
shl eax, 8
mov esi, [SLOT_BASE+eax+APPDATA.dbg_event_mem]
test esi, esi
jz .ret
; read buffer header
push ecx
push eax
push eax
mov eax, ebp
mov ecx, esp
mov edx, 8
call read_process_memory
cmp eax, edx
jz @f
add esp, 12
jmp .ret
@@:
cmp dword [ecx], 0
jg @f
.2:
pop ecx
pop ecx
pop ecx
cmp dword [CURRENT_TASK], 1
jnz .notos
cmp [timer_ticks], edi
jae .ret
.notos:
sti
call change_task
cli
jmp .1
@@:
mov edx, [ecx+8]
add edx, [ecx+4]
cmp edx, [ecx]
ja .2
; advance buffer position
push edx
mov edx, 4
sub ecx, edx
mov eax, ebp
add esi, edx
call write_process_memory
pop eax
; write message
mov eax, ebp
add esi, edx
add esi, [ecx+8]
add ecx, 20
pop edx
pop edx
pop edx
call write_process_memory
; new debug event
mov eax, ebp
shl eax, 8
or byte [SLOT_BASE+eax+APPDATA.event_mask+1], 1 ; set flag 100h
.ret:
ret
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/export.inc
0,0 → 1,40
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
; Macroinstruction for making export section
 
 
macro export dllname,[label,string]
{ common
local module,addresses,names,ordinal,count
count = 0
forward
count = count+1
common
dd 0,0,0, (module-OS_BASE) , 1
dd count,count,(addresses-OS_BASE),(names-OS_BASE),(ordinal-OS_BASE)
addresses:
forward
dd (label-OS_BASE)
common
names:
forward
local name
dd (name-OS_BASE)
common
ordinal:
count = 0
forward
dw count
count = count+1
common
module db dllname,0
forward
name db string,0
}
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/ext_lib.inc
0,0 → 1,333
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;============================================================================
;
; External kernel dependencies (libraries) loading
;
;============================================================================
 
$Revision $
 
if 0
; The code currently does not work. Kill "if 0/end if" only after correcting
; to current kernel (dll.inc).
macro library [name,fname]
{
forward
dd __#name#_library_table__,__#name#_library_name__
common
dd 0
forward
__#name#_library_name__ db fname,0
}
 
macro import lname,[name,sname]
{
common
align 4
__#lname#_library_table__:
forward
name dd __#name#_import_name__
common
dd 0
forward
__#name#_import_name__ db sname,0
}
 
macro export [name,sname]
{
align 4
forward
dd __#name#_export_name__,name
common
dd 0
forward
__#name#_export_name__ db sname,0
}
 
 
 
align 4 ; loading library (use kernel functions)
proc load_k_library stdcall, file_name:dword
locals
coff dd ?
sym dd ?
strings dd ?
img_size dd ?
img_base dd ?
exports dd ?
endl
 
cli
 
stdcall load_file, [file_name]
test eax, eax
jz .fail
 
mov [coff], eax
movzx ecx, [eax+CFH.nSections]
xor ebx, ebx
 
lea edx, [eax+20]
@@:
add ebx, [edx+CFS.SizeOfRawData]
add ebx, 15
and ebx, not 15
add edx, COFF_SECTION_SIZE
dec ecx
jnz @B
mov [img_size], ebx
 
stdcall kernel_alloc, [img_size]
 
test eax, eax
jz .fail
mov [img_base], eax
 
mov edx, [coff]
movzx ebx, [edx+CFH.nSections]
mov edi, [img_base]
lea eax, [edx+20]
@@:
mov [eax+CFS.VirtualAddress], edi
mov esi, [eax+CFS.PtrRawData]
test esi, esi
jnz .copy
add edi, [eax+CFS.SizeOfRawData]
jmp .next
.copy:
add esi, edx
mov ecx, [eax+CFS.SizeOfRawData]
cld
rep movsb
.next:
add edi, 15
and edi, not 15
add eax, COFF_SECTION_SIZE
dec ebx
jnz @B
 
mov ebx, [edx+CFH.pSymTable]
add ebx, edx
mov [sym], ebx
mov ecx, [edx+CFH.nSymbols]
add ecx, ecx
lea ecx, [ecx+ecx*8];ecx*=18 = nSymbols*CSYM_SIZE
add ecx, [sym]
mov [strings], ecx
 
lea eax, [edx+20]
 
stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols], \
[strings], dword 0
test eax, eax
jnz @F
 
@@:
mov edx, [coff]
movzx ebx, [edx+CFH.nSections]
mov edi, 0
lea eax, [edx+20]
@@:
add [eax+CFS.VirtualAddress], edi ;patch user space offset
add eax, COFF_SECTION_SIZE
dec ebx
jnz @B
 
add edx, 20
stdcall fix_coff_relocs, [coff], edx, [sym]
 
mov ebx, [coff]
stdcall get_coff_sym, [sym], [ebx+CFH.nSymbols], szEXPORTS
mov [exports], eax
 
stdcall kernel_free, [coff]
 
mov eax, [exports]
ret
.fail:
xor eax, eax
ret
endp
 
 
proc dll.Load, import_table:dword
mov esi, [import_table]
.next_lib:
mov edx, [esi]
or edx, edx
jz .exit
push esi
 
mov edi, s_libname
 
mov al, '/'
stosb
mov esi, sysdir_path
@@:
lodsb
stosb
or al, al
jnz @b
dec edi
mov [edi], dword '/lib'
mov [edi+4], byte '/'
add edi, 5
pop esi
push esi
mov esi, [esi+4]
@@:
lodsb
stosb
or al, al
jnz @b
 
pushad
stdcall load_k_library, s_libname
mov [esp+28], eax
popad
or eax, eax
jz .fail
stdcall dll.Link, eax, edx
stdcall dll.Init, [eax+4]
pop esi
add esi, 8
jmp .next_lib
.exit:
xor eax, eax
ret
.fail:
add esp, 4
xor eax, eax
inc eax
ret
endp
 
proc dll.Link, exp:dword,imp:dword
push eax
mov esi, [imp]
test esi, esi
jz .done
.next:
lodsd
test eax, eax
jz .done
stdcall dll.GetProcAddress, [exp], eax
or eax, eax
jz @f
mov [esi-4], eax
jmp .next
@@:
mov dword[esp], 0
.done:
pop eax
ret
endp
 
proc dll.Init, dllentry:dword
pushad
mov eax, mem.Alloc
mov ebx, mem.Free
mov ecx, mem.ReAlloc
mov edx, dll.Load
stdcall [dllentry]
popad
ret
endp
 
proc dll.GetProcAddress, exp:dword,sz_name:dword
mov edx, [exp]
.next:
test edx, edx
jz .end
stdcall strncmp, [edx], [sz_name], dword -1
test eax, eax
jz .ok
add edx, 8
jmp .next
.ok:
mov eax, [edx+4]
.end:
ret
endp
 
;-----------------------------------------------------------------------------
proc mem.Alloc size ;/////////////////////////////////////////////////////////
;-----------------------------------------------------------------------------
push ebx ecx
; mov eax,[size]
; lea ecx,[eax+4+4095]
; and ecx,not 4095
; stdcall kernel_alloc, ecx
; add ecx,-4
; mov [eax],ecx
; add eax,4
 
stdcall kernel_alloc, [size]
 
pop ecx ebx
ret
endp
 
;-----------------------------------------------------------------------------
proc mem.ReAlloc mptr,size;///////////////////////////////////////////////////
;-----------------------------------------------------------------------------
push ebx ecx esi edi eax
mov eax, [mptr]
mov ebx, [size]
or eax, eax
jz @f
lea ecx, [ebx+4+4095]
and ecx, not 4095
add ecx, -4
cmp ecx, [eax-4]
je .exit
@@:
mov eax, ebx
call mem.Alloc
xchg eax, [esp]
or eax, eax
jz .exit
mov esi, eax
xchg eax, [esp]
mov edi, eax
mov ecx, [esi-4]
cmp ecx, [edi-4]
jbe @f
mov ecx, [edi-4]
@@:
add ecx, 3
shr ecx, 2
cld
rep movsd
xchg eax, [esp]
call mem.Free
.exit:
pop eax edi esi ecx ebx
ret
endp
 
;-----------------------------------------------------------------------------
proc mem.Free mptr ;//////////////////////////////////////////////////////////
;-----------------------------------------------------------------------------
; mov eax,[mptr]
; or eax,eax
; jz @f
; push ebx ecx
; lea ecx,[eax-4]
; stdcall kernel_free, ecx
; pop ecx ebx
; @@: ret
stdcall kernel_free, [mptr]
ret
endp
 
uglobal
s_libname db 64 dup (0)
endg
end if
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/fpu.inc
0,0 → 1,183
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
init_fpu:
clts
fninit
 
bt [cpu_caps], CAPS_SSE
jnc .no_SSE
 
mov ebx, cr4
mov ecx, cr0
or ebx, CR4_OSFXSR+CR4_OSXMMEXPT
mov cr4, ebx
 
and ecx, not (CR0_MP+CR0_EM)
or ecx, CR0_NE
mov cr0, ecx
 
mov dword [esp-4], SSE_INIT
ldmxcsr [esp-4]
 
xorps xmm0, xmm0
xorps xmm1, xmm1
xorps xmm2, xmm2
xorps xmm3, xmm3
xorps xmm4, xmm4
xorps xmm5, xmm5
xorps xmm6, xmm6
xorps xmm7, xmm7
fxsave [fpu_data] ;[eax]
ret
.no_SSE:
mov ecx, cr0
and ecx, not CR0_EM
or ecx, CR0_MP+CR0_NE
mov cr0, ecx
fnsave [fpu_data]
ret
 
; param
; eax= 512 bytes memory area
 
align 4
fpu_save:
push ecx
push esi
push edi
 
pushfd
cli
 
clts
mov edi, eax
 
mov ecx, [fpu_owner]
mov esi, [CURRENT_TASK]
cmp ecx, esi
jne .save
 
call save_context
jmp .exit
.save:
mov [fpu_owner], esi
 
shl ecx, 8
mov eax, [ecx+SLOT_BASE+APPDATA.fpu_state]
 
call save_context
 
shl esi, 8
mov esi, [esi+SLOT_BASE+APPDATA.fpu_state]
mov ecx, 512/4
cld
rep movsd
fninit
.exit:
popfd
pop edi
pop esi
pop ecx
ret
 
align 4
save_context:
bt [cpu_caps], CAPS_SSE
jnc .no_SSE
 
fxsave [eax]
ret
.no_SSE:
fnsave [eax]
ret
 
align 4
fpu_restore:
push ecx
push esi
 
mov esi, eax
 
pushfd
cli
 
mov ecx, [fpu_owner]
mov eax, [CURRENT_TASK]
cmp ecx, eax
jne .copy
 
clts
bt [cpu_caps], CAPS_SSE
jnc .no_SSE
 
fxrstor [esi]
popfd
pop esi
pop ecx
ret
.no_SSE:
fnclex ;fix possible problems
frstor [esi]
popfd
pop esi
pop ecx
ret
.copy:
shl eax, 8
mov edi, [eax+SLOT_BASE+APPDATA.fpu_state]
mov ecx, 512/4
cld
rep movsd
popfd
pop esi
pop ecx
ret
 
align 4
except_7: ;#NM exception handler
save_ring3_context
clts
mov ax, app_data;
mov ds, ax
mov es, ax
 
mov ebx, [fpu_owner]
cmp ebx, [CURRENT_TASK]
je .exit
 
shl ebx, 8
mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state]
bt [cpu_caps], CAPS_SSE
jnc .no_SSE
 
fxsave [eax]
mov ebx, [CURRENT_TASK]
mov [fpu_owner], ebx
shl ebx, 8
mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state]
fxrstor [eax]
.exit:
restore_ring3_context
iret
 
.no_SSE:
fnsave [eax]
mov ebx, [CURRENT_TASK]
mov [fpu_owner], ebx
shl ebx, 8
mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state]
frstor [eax]
restore_ring3_context
iret
 
iglobal
fpu_owner dd 0
endg
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/sched.inc
0,0 → 1,400
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; IRQ0 HANDLER (TIMER INTERRUPT) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
align 32
irq0:
pushad
Mov ds, ax, app_data
mov es, ax
inc [timer_ticks]
mov eax, [timer_ticks]
call playNote ; <<<--- Speaker driver
sub eax, [next_usage_update]
cmp eax, 100
jb .nocounter
add [next_usage_update], 100
call updatecputimes
.nocounter:
xor ecx, ecx ; send End Of Interrupt signal
call irq_eoi
btr dword[DONT_SWITCH], 0
jc .return
call find_next_task
jz .return ; if there is only one running process
call do_change_task
.return:
popad
iretd
 
align 4
change_task:
pushfd
cli
pushad
if 0
; \begin{Mario79} ; <- must be refractoried, if used...
cmp [dma_task_switched], 1
jne .find_next_task
mov [dma_task_switched], 0
mov ebx, [dma_process]
cmp [CURRENT_TASK], ebx
je .return
mov edi, [dma_slot_ptr]
mov [CURRENT_TASK], ebx
mov [TASK_BASE], edi
jmp @f
.find_next_task:
; \end{Mario79}
end if
call find_next_task
jz .return ; the same task -> skip switch
@@:
mov byte[DONT_SWITCH], 1
call do_change_task
.return:
popad
popfd
ret
 
uglobal
align 4
; far_jump:
; .offs dd ?
; .sel dw ?
context_counter dd 0 ;noname & halyavin
next_usage_update dd 0
timer_ticks dd 0
; prev_slot dd ?
; event_sched dd ?
endg
 
align 4
update_counters:
mov edi, [TASK_BASE]
rdtsc
sub eax, [edi+TASKDATA.counter_add] ; time stamp counter add
add [edi+TASKDATA.counter_sum], eax ; counter sum
ret
align 4
updatecputimes:
xor eax, eax
xchg eax, [idleuse]
mov [idleusesec], eax
mov ecx, [TASK_COUNT]
mov edi, TASK_DATA
.newupdate:
xor eax, eax
xchg eax, [edi+TASKDATA.counter_sum]
mov [edi+TASKDATA.cpu_usage], eax
add edi, 0x20
loop .newupdate
ret
 
align 4
find_next_task:
;info:
; Find next task to execute
;retval:
; ebx = address of the APPDATA for the selected task (slot-base)
; esi = previous slot-base ([current_slot] at the begin)
; edi = address of the TASKDATA for the selected task
; ZF = 1 if the task is the same
;warning:
; [CURRENT_TASK] = bh , [TASK_BASE] = edi -- as result
; [current_slot] is not set to new value (ebx)!!!
;scratched: eax,ecx
call update_counters ; edi := [TASK_BASE]
Mov esi, ebx, [current_slot]
.loop:
cmp bh, [TASK_COUNT]
jb @f
xor bh, bh
mov edi, CURRENT_TASK
@@:
inc bh ; ebx += APPDATA.size
add edi, 0x20; edi += TASKDATA.size
mov al, [edi+TASKDATA.state]
test al, al
jz .found ; state == 0
cmp al, 5
jne .loop ; state == 1,2,3,4,9
; state == 5
pushad ; more freedom for [APPDATA.wait_test]
call [ebx+APPDATA.wait_test]
mov [esp+28], eax
popad
or eax, eax
jnz @f
; testing for timeout
mov ecx, [timer_ticks]
sub ecx, [ebx+APPDATA.wait_begin]
cmp ecx, [ebx+APPDATA.wait_timeout]
jb .loop
@@:
mov [ebx+APPDATA.wait_param], eax ; retval for wait
mov [edi+TASKDATA.state], 0
.found:
mov [CURRENT_TASK], bh
mov [TASK_BASE], edi
rdtsc ;call _rdtsc
mov [edi+TASKDATA.counter_add], eax; for next using update_counters
cmp ebx, esi ;esi - previous slot-base
ret
;TODO: Íàäî áû óáðàòü èñïîëüçîâàíèå do_change_task èç V86...
; è ïîñëå ýòîãî ïåðåíåñòè îáðàáîòêó TASKDATA.counter_add/sum â do_change_task
 
align 4
do_change_task:
;param:
; ebx = address of the APPDATA for incoming task (new)
;warning:
; [CURRENT_TASK] and [TASK_BASE] must be changed before (e.g. in find_next_task)
; [current_slot] is the outcoming (old), and set here to a new value (ebx)
;scratched: eax,ecx,esi
mov esi, ebx
xchg esi, [current_slot]
; set new stack after saving old
mov [esi+APPDATA.saved_esp], esp
mov esp, [ebx+APPDATA.saved_esp]
; set new thread io-map
Mov dword [page_tabs+((tss._io_map_0 and -4096) shr 10)],eax,[ebx+APPDATA.io_map]
Mov dword [page_tabs+((tss._io_map_1 and -4096) shr 10)],eax,[ebx+APPDATA.io_map+4]
; set new thread memory-map
mov ecx, APPDATA.dir_table
mov eax, [ebx+ecx] ;offset>0x7F
cmp eax, [esi+ecx] ;offset>0x7F
je @f
mov cr3, eax
@@:
; set tss.esp0
 
Mov [tss._esp0],eax,[ebx+APPDATA.saved_esp0]
 
mov edx, [ebx+APPDATA.tls_base]
cmp edx, [esi+APPDATA.tls_base]
je @f
 
mov [tls_data_l+2], dx
shr edx, 16
mov [tls_data_l+4], dl
mov [tls_data_l+7], dh
 
mov dx, app_tls
mov fs, dx
@@:
; set gs selector unconditionally
Mov gs,ax,graph_data
; set CR0.TS
cmp bh, byte[fpu_owner] ;bh == incoming task (new)
clts ;clear a task switch flag
je @f
mov eax, cr0 ;and set it again if the owner
or eax, CR0_TS ;of a fpu has changed
mov cr0, eax
@@: ; set context_counter (only for user pleasure ???)
inc [context_counter] ;noname & halyavin
; set debug-registers, if it's necessary
test byte[ebx+APPDATA.dbg_state], 1
jz @f
xor eax, eax
mov dr6, eax
lea esi, [ebx+ecx+APPDATA.dbg_regs-APPDATA.dir_table];offset>0x7F
cld
macro lodsReg [reg] {
lodsd
mov reg, eax
} lodsReg dr0, dr1, dr2, dr3, dr7
purge lodsReg
@@:
ret
;end.
 
 
 
struct MUTEX_WAITER
list LHEAD
task dd ?
ends
 
;void __fastcall mutex_init(struct mutex *lock)
 
align 4
mutex_init:
mov [ecx+MUTEX.lhead.next], ecx
mov [ecx+MUTEX.lhead.prev], ecx
mov [ecx+MUTEX.count], 1
ret
 
 
;void __fastcall mutex_lock(struct mutex *lock)
 
align 4
mutex_lock:
 
dec [ecx+MUTEX.count]
jns .done
 
pushfd
cli
 
sub esp, sizeof.MUTEX_WAITER
 
list_add_tail esp, ecx ;esp= new waiter, ecx= list head
 
mov edx, [TASK_BASE]
mov [esp+MUTEX_WAITER.task], edx
 
.forever:
 
mov eax, -1
xchg eax, [ecx+MUTEX.count]
dec eax
jz @F
 
mov [edx+TASKDATA.state], 1
call change_task
jmp .forever
@@:
mov edx, [esp+MUTEX_WAITER.list.next]
mov eax, [esp+MUTEX_WAITER.list.prev]
 
mov [eax+MUTEX_WAITER.list.next], edx
mov [edx+MUTEX_WAITER.list.prev], eax
cmp [ecx+MUTEX.lhead.next], ecx
jne @F
 
mov [ecx+MUTEX.count], 0
@@:
add esp, sizeof.MUTEX_WAITER
 
popfd
.done:
ret
 
;void __fastcall mutex_unlock(struct mutex *lock)
 
align 4
mutex_unlock:
 
pushfd
cli
 
mov eax, [ecx+MUTEX.lhead.next]
cmp eax, ecx
mov [ecx+MUTEX.count], 1
je @F
 
mov eax, [eax+MUTEX_WAITER.task]
mov [eax+TASKDATA.state], 0
@@:
popfd
ret
 
 
purge MUTEX_WAITER
 
if 0
 
struc TIMER
{
.next dd ?
.exp_time dd ?
.func dd ?
.arg dd ?
}
 
 
MAX_PROIRITY 0 ; highest, used for kernel tasks
MAX_USER_PRIORITY 0 ; highest priority for user processes
USER_PRIORITY 7 ; default (should correspond to nice 0)
MIN_USER_PRIORITY 14 ; minimum priority for user processes
IDLE_PRIORITY 15 ; lowest, only IDLE process goes here
NR_SCHED_QUEUES 16 ; MUST equal IDLE_PRIORYTY + 1
 
uglobal
rdy_head rd 16
endg
 
align 4
pick_task:
 
xor eax, eax
.pick:
mov ebx, [rdy_head+eax*4]
test ebx, ebx
jz .next
 
mov [next_task], ebx
test [ebx+flags.billable]
jz @F
mov [bill_task], ebx
@@:
ret
.next:
inc eax
jmp .pick
 
; param
; eax= task
;
; retval
; eax= task
; ebx= queue
; ecx= front if 1 or back if 0
align 4
shed:
cmp [eax+.tics_left], 0;signed compare
mov ebx, [eax+.priority]
setg ecx
jg @F
 
mov edx, [eax+.tics_quantum]
mov [eax+.ticks_left], edx
cmp ebx, (IDLE_PRIORITY-1)
je @F
inc ebx
@@:
ret
 
; param
; eax= task
align 4
enqueue:
call shed;eax
cmp [rdy_head+ebx*4], 0
jnz @F
 
mov [rdy_head+ebx*4], eax
mov [rdy_tail+ebx*4], eax
mov [eax+.next_ready], 0
jmp .pick
@@:
test ecx, ecx
jz .back
 
mov ecx, [rdy_head+ebx*4]
mov [eax+.next_ready], ecx
mov [rdy_head+ebx*4], eax
jmp .pick
.back:
mov ecx, [rdy_tail+ebx*4]
mov [ecx+.next_ready], eax
mov [rdy_tail+ebx*4], eax
mov [eax+.next_ready], 0
.pick:
call pick_proc;select next task
ret
 
end if
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/string.inc
0,0 → 1,188
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; Author: Kees J. Bot 1 Jan 1994 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
; size_t strncat(char *s1, const char *s2, size_t n)
; Append string s2 to s1.
 
; char *strchr(const char *s, int c)
 
 
; int strncmp(const char *s1, const char *s2, size_t n)
; Compare two strings.
 
; char *strncpy(char *s1, const char *s2, size_t n)
; Copy string s2 to s1.
 
; size_t strnlen(const char *s, size_t n)
; Return the length of a string.
 
; proc strrchr stdcall, s:dword, c:dword
; Look for the last occurrence a character in a string.
 
proc strncat stdcall, s1:dword, s2:dword, n:dword
push esi
push edi
mov edi, [s1] ; String s1
mov edx, [n] ; Maximum length
 
mov ecx, -1
xor al, al ; Null byte
cld
repne scasb ; Look for the zero byte in s1
dec edi ; Back one up (and clear 'Z' flag)
push edi ; Save end of s1
mov edi, [s2] ; edi = string s2
mov ecx, edx ; Maximum count
repne scasb ; Look for the end of s2
jne @F
inc ecx ; Exclude null byte
@@:
sub edx, ecx ; Number of bytes in s2
mov ecx, edx
mov esi, [s2] ; esi = string s2
pop edi ; edi = end of string s1
rep movsb ; Copy bytes
stosb ; Add a terminating null
mov eax, [s1] ; Return s1
pop edi
pop esi
ret
endp
 
align 4
proc strncmp stdcall, s1:dword, s2:dword, n:dword
 
push esi
push edi
mov ecx, [n]
test ecx, ecx ; Max length is zero?
je .done
 
mov esi, [s1] ; esi = string s1
mov edi, [s2] ; edi = string s2
cld
.compare:
cmpsb ; Compare two bytes
jne .done
cmp byte [esi-1], 0 ; End of string?
je .done
dec ecx ; Length limit reached?
jne .compare
.done:
seta al ; al = (s1 > s2)
setb ah ; ah = (s1 < s2)
sub al, ah
movsx eax, al ; eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1
pop edi
pop esi
ret
endp
 
align 4
proc strncpy stdcall, s1:dword, s2:dword, n:dword
 
push esi
push edi
 
mov ecx, [n] ; Maximum length
mov edi, [s2] ; edi = string s2
xor al, al ; Look for a zero byte
mov edx, ecx ; Save maximum count
cld
repne scasb ; Look for end of s2
sub edx, ecx ; Number of bytes in s2 including null
xchg ecx, edx
mov esi, [s2] ; esi = string s2
mov edi, [s1] ; edi = string s1
rep movsb ; Copy bytes
 
mov ecx, edx ; Number of bytes not copied
rep stosb ; strncpy always copies n bytes by null padding
mov eax, [s1] ; Return s1
pop edi
pop esi
ret
endp
 
align 4
proc strnlen stdcall, s:dword, n:dword
 
push edi
mov edi, [s] ; edi = string
xor al, al ; Look for a zero byte
mov edx, ecx ; Save maximum count
cmp cl, 1 ; 'Z' bit must be clear if ecx = 0
cld
repne scasb ; Look for zero
jne @F
inc ecx ; Don't count zero byte
@@:
mov eax, edx
sub eax, ecx ; Compute bytes scanned
pop edi
ret
endp
 
align 4
proc strchr stdcall, s:dword, c:dword
push edi
cld
mov edi, [s] ; edi = string
mov edx, 16 ; Look at small chunks of the string
.next:
shl edx, 1 ; Chunks become bigger each time
mov ecx, edx
xor al, al ; Look for the zero at the end
repne scasb
pushf ; Remember the flags
sub ecx, edx
neg ecx ; Some or all of the chunk
sub edi, ecx ; Step back
mov eax, [c] ; The character to look for
repne scasb
je .found
popf ; Did we find the end of string earlier?
jne .next ; No, try again
xor eax, eax ; Return NULL
pop edi
ret
.found:
pop eax ; Get rid of those flags
lea eax, [edi-1] ; Address of byte found
pop edi
ret
 
endp
 
 
proc strrchr stdcall, s:dword, c:dword
push edi
mov edi, [s] ; edi = string
mov ecx, -1
xor al, al
cld
repne scasb ; Look for the end of the string
not ecx ; -1 - ecx = Length of the string + null
dec edi ; Put edi back on the zero byte
mov eax, [c] ; The character to look for
std ; Downwards search
repne scasb
cld ; Direction bit back to default
jne .fail
lea eax, [edi+1] ; Found it
pop edi
ret
.fail:
xor eax, eax ; Not there
pop edi
ret
endp
 
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core/sync.inc
0,0 → 1,119
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Synhronization for MenuetOS. ;;
;; Author: Halyavin Andrey, halyavin@land.ru ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
if ~defined sync_inc
sync_inc_fix:
sync_inc fix sync_inc_fix
 
;simplest mutex.
macro SimpleMutex name
{
; iglobal
name dd 0
name#.type = 1
; endg
}
macro WaitSimpleMutex name
{
local start_wait,ok
start_wait=$
cli
cmp [name], dword 0
jz ok
sti
call change_task
jmp start_wait
ok=$
push eax
mov eax, dword [TASK_BASE+second_base_address]
mov eax, [eax+TASKDATA.pid]
mov [name], eax
pop eax
sti
}
macro ReleaseSimpleMutex name
{
mov [name], dword 0
}
macro TryWaitSimpleMutex name ;result in eax and in flags
{
local ok,try_end
cmp [name], dword 0
jz ok
xor eax, eax
jmp try_end
ok=$
xor eax, eax
inc eax
try_end=$
}
macro SimpleCriticalSection name
{
; iglobal
name dd 0
dd 0
name#.type=2
; endg
}
macro WaitSimpleCriticalSection name
{
local start_wait,first_wait,inc_counter,end_wait
push eax
mov eax, [TASK_BASE+second_base_address]
mov eax, [eax+TASKDATA.pid]
start_wait=$
cli
cmp [name], dword 0
jz first_wait
cmp [name], eax
jz inc_counter
sti
call change_task
jmp start_wait
first_wait=$
mov [name], eax
mov [name+4], dword 1
jmp end_wait
inc_counter=$
inc dword [name+4]
end_wait=$
sti
pop eax
}
macro ReleaseSimpleCriticalSection name
{
local release_end
dec dword [name+4]
jnz release_end
mov [name], dword 0
release_end=$
}
macro TryWaitSimpleCriticalSection name ;result in eax and in flags
{
local ok,try_end
mov eax, [CURRENT_TASK+second_base_address]
mov eax, [eax+TASKDATA.pid]
cmp [name], eax
jz ok
cmp [name], 0
jz ok
xor eax, eax
jmp try_end
ok=$
xor eax, eax
inc eax
try_end=$
}
_cli equ call MEM_HeapLock
_sti equ call MEM_HeapUnLock
end if
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/core
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/fs/ext2.inc
0,0 → 1,1238
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; 02.02.2010 turbanoff - support 70.5 ;;
;; 23.01.2010 turbanoff - support 70.0 70.1 ;;
;; ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 2381 $
 
EXT2_BAD_INO = 1
EXT2_ROOT_INO = 2
EXT2_ACL_IDX_INO = 3
EXT2_ACL_DATA_INO = 4
EXT2_BOOT_LOADER_INO = 5
EXT2_UNDEL_DIR_INO = 6
 
;флаги, указываемый в inode файла
EXT2_S_IFREG = 0x8000
EXT2_S_IFDIR = 0x4000
EXT2_S_IFMT = 0xF000 ;маска для типа файла
 
;флаги, указываемые в linked list родительской папки
EXT2_FT_REG_FILE = 1 ;это файл, запись в родительском каталоге
EXT2_FT_DIR = 2 ;это папка
 
;флаги используемые KolibriOS
FS_FT_HIDDEN = 2
FS_FT_DIR = 0x10 ;это папка
FS_FT_ASCII = 0 ;имя в ascii
FS_FT_UNICODE = 1 ;имя в unicode
 
EXT2_FEATURE_INCOMPAT_FILETYPE = 0x0002 ;тип файла должен указываться в директории
EXT4_FEATURE_INCOMPAT_EXTENTS = 0x0040 ;экстенты
EXT4_FEATURE_INCOMPAT_FLEX_BG = 0x0200 ;гибкие группы блоков
;реализованные ext[234] features
EXT4_FEATURE_INCOMPAT_SUPP = EXT2_FEATURE_INCOMPAT_FILETYPE \
or EXT4_FEATURE_INCOMPAT_EXTENTS \
or EXT4_FEATURE_INCOMPAT_FLEX_BG
 
 
;флаги, указываемые для inode в i_flags
EXT2_EXTENTS_FL = 0x00080000
 
struct EXT2_INODE_STRUC
i_mode dw ?
i_uid dw ?
i_size dd ?
i_atime dd ?
i_ctime dd ?
i_mtime dd ?
i_dtime dd ?
i_gid dw ?
i_links_count dw ?
i_blocks dd ?
i_flags dd ?
i_osd1 dd ?
i_block rd 15
i_generation dd ?
i_file_acl dd ?
i_dir_acl dd ?
i_faddr dd ?
i_osd2 dd ? ; 1..12
ends
 
struct EXT2_DIR_STRUC
inode dd ?
rec_len dw ?
name_len db ?
file_type db ?
name db ? ; 0..255
ends
 
struct EXT2_BLOCK_GROUP_DESC
block_bitmap dd ? ;+0
inode_bitmap dd ? ;+4
inode_table dd ? ;+8
free_blocks_count dw ? ;+12
free_inodes_count dw ? ;+14
used_dirs_count dw ? ;+16
pad dw ? ;+18
reserved rb 12;+20
ends
 
struct EXT2_SB_STRUC
inodes_count dd ? ;+0
blocks_count dd ? ;+4
r_block_count dd ? ;+8
free_block_count dd ? ;+12
free_inodes_count dd ? ;+16
first_data_block dd ? ;+20
log_block_size dd ? ;+24
log_frag_size dd ? ;+28
blocks_per_group dd ? ;+32
frags_per_group dd ? ;+36
inodes_per_group dd ? ;+40
mtime dd ? ;+44
wtime dd ? ;+48
mnt_count dw ? ;+52
max_mnt_count dw ? ;+54
magic dw ? ;+56
state dw ? ;+58
errors dw ? ;+60
minor_rev_level dw ? ;+62
lastcheck dd ? ;+64
check_intervals dd ? ;+68
creator_os dd ? ;+72
rev_level dd ? ;+76
def_resuid dw ? ;+80
def_resgid dw ? ;+82
first_ino dd ? ;+84
inode_size dw ? ;+88
block_group_nr dw ? ;+90
feature_compat dd ? ;+92
feature_incompat dd ? ;+96
feature_ro_compat dd ? ;+100
uuid rb 16 ;+104
volume_name rb 16 ;+120
last_mounted rb 64 ;+136
algo_bitmap dd ? ;+200
prealloc_blocks db ? ;+204
preallock_dir_blocks db ? ;+205
reserved_gdt_blocks dw ? ;+206
journal_uuid rb 16 ;+208
journal_inum dd ? ;+224
journal_dev dd ? ;+228
last_orphan dd ? ;+232
hash_seed rd 4 ;+236
def_hash_version db ? ;+252
rb 3 ;+253 reserved
default_mount_options dd ? ;+256
first_meta_bg dd ? ;+260
mkfs_time dd ? ;+264
jnl_blocks rd 17 ;+268
blocks_count_hi dd ? ;+336
r_blocks_count_hi dd ? ;+340
free_blocks_count_hi dd ? ;+344
min_extra_isize dw ? ;+348
want_extra_isize dw ? ;+350
flags dd ? ;+352
raid_stride dw ? ;+356
mmp_interval dw ? ;+358
mmp_block dq ? ;+360
raid_stripe_width dd ? ;+368
log_groups_per_flex db ? ;+372
ends
 
struct EXT4_EXTENT_HEADER ;заголовок блока экстентов/индексов
eh_magic dw ? ;в текущей реализации ext4 должно быть 0xF30A
eh_entries dw ? ;количество экстентов/индексов в блоке
eh_max dw ? ;max количество (используется при записи)
eh_depth dw ? ;глубина дерева (0, если это блок экстентов)
eh_generation dd ? ;???
ends
 
struct EXT4_EXTENT ;экстент
ee_block dd ? ;номер ext4 блока
ee_len dw ? ;длина экстента
ee_start_hi dw ? ;старшие 16 бит 48-битного адреса (пока не используются в KOS)
ee_start_lo dd ? ;младшие 32 бита 48-битного адреса
ends
 
struct EXT4_EXTENT_IDX ;индес - указатель на блок с экстентами/индексами
ei_block dd ? ;номер ext4 блока
ei_leaf_lo dd ? ;младшие 32 бит 48-битного адреса
ei_leaf_hi dw ? ;старшие 16 бит 48-битного адреса (пока не используются в KOS)
ei_unused dw ? ;зарезервировано
ends
 
ext2_test_superblock:
cmp [fs_type], 0x83
jne .no
 
mov eax, [PARTITION_START]
add eax, 2 ;superblock start at 1024b
call hd_read
 
cmp [ebx + EXT2_SB_STRUC.log_block_size], 3 ;0,1,2,3
ja .no
cmp [ebx + EXT2_SB_STRUC.magic], 0xEF53
jne .no
cmp [ebx + EXT2_SB_STRUC.state], 1 ;EXT_VALID_FS=1
jne .no
cmp [ebx + EXT2_SB_STRUC.inodes_per_group], 0
je .no
mov eax, [ebx + EXT2_SB_STRUC.feature_incompat]
test eax, EXT2_FEATURE_INCOMPAT_FILETYPE
jz .no
test eax, not EXT4_FEATURE_INCOMPAT_SUPP
jnz .no
 
; OK, this is correct EXT2 superblock
clc
ret
.no:
; No, this superblock isn't EXT2
stc
ret
 
ext2_setup:
mov [fs_type], 2
 
push 512
call kernel_alloc ; mem for superblock
mov esi, ebx
mov edi, eax
mov ecx, 512/4
rep movsd ; copy sb to reserved mem
mov ebx, eax
mov [ext2_data.sb], eax
 
mov eax, [ebx + EXT2_SB_STRUC.blocks_count]
sub eax, [ebx + EXT2_SB_STRUC.first_data_block]
dec eax
xor edx, edx
div [ebx + EXT2_SB_STRUC.blocks_per_group]
inc eax
mov [ext2_data.groups_count], eax
 
mov ecx, [ebx + EXT2_SB_STRUC.log_block_size]
inc ecx
mov [ext2_data.log_block_size], ecx ; 1, 2, 3, 4 equ 1kb, 2kb, 4kb, 8kb
 
mov eax, 1
shl eax, cl
mov [ext2_data.count_block_in_block], eax
 
shl eax, 7
mov [ext2_data.count_pointer_in_block], eax
mov edx, eax ; потом еще квадрат найдем
 
shl eax, 2
mov [ext2_data.block_size], eax
 
push eax eax ; 2 kernel_alloc
 
mov eax, edx
mul edx
mov [ext2_data.count_pointer_in_block_square], eax
 
call kernel_alloc
mov [ext2_data.ext2_save_block], eax ; and for temp block
call kernel_alloc
mov [ext2_data.ext2_temp_block], eax ; and for get_inode proc
 
movzx ebp, word [ebx + EXT2_SB_STRUC.inode_size]
mov ecx, [ebx + EXT2_SB_STRUC.blocks_per_group]
 
mov [ext2_data.inode_size], ebp
mov [ext2_data.blocks_per_group], ecx
 
push ebp ebp ebp ;3 kernel_alloc
call kernel_alloc
mov [ext2_data.ext2_save_inode], eax
call kernel_alloc
mov [ext2_data.ext2_temp_inode], eax
call kernel_alloc
mov [ext2_data.root_inode], eax
 
mov ebx, eax
mov eax, EXT2_ROOT_INO
call ext2_get_inode ; read root inode
 
jmp return_from_part_set
 
;==================================================================
;read ext2 block form FS to memory
;in: eax = i_block (address of block in ext2 terms)
; ebx = pointer to return memory
;out: eax - error code (0 = no_error)
ext2_get_block:
push ebx ecx
mov ecx, [ext2_data.log_block_size]
shl eax, cl
add eax, [PARTITION_START]
mov ecx, [ext2_data.count_block_in_block]
@@:
call hd_read
cmp [hd_error], 0
jnz .fail
inc eax
add ebx, 512
loop @B
xor eax, eax
@@:
pop ecx ebx
ret
.fail:
mov eax, ERROR_DEVICE
jmp @B
 
;===================================================================
;получает номер блока из extent inode
;in: ecx = номер блока по порядку
; ebp = адрес extent header`а
;out: ecx - адрес очередного блока в случае успеха
; eax - номер ошибки (если равно 0, то ошибки нет)
ext4_block_recursive_search:
cmp word [ebp + EXT4_EXTENT_HEADER.eh_magic], 0xF30A ;EXT4_EXT_MAGIC
jne .fail
movzx ebx, [ebp + EXT4_EXTENT_HEADER.eh_entries]
add ebp, sizeof.EXT4_EXTENT_HEADER
cmp word [ebp - sizeof.EXT4_EXTENT_HEADER + EXT4_EXTENT_HEADER.eh_depth], 0
je .leaf_block ;листовой ли это блок?
;не листовой блок, а индексный ; eax - ext4_extent_idx
test ebx, ebx
jz .fail ;пустой индексный блок -> ошибка
 
;цикл по индексам экстентов
@@:
cmp ebx, 1 ;у индексов не хранится длина,
je .end_search_index ;поэтому, если остался последний - то это нужный
cmp ecx, [ebp + EXT4_EXTENT_IDX.ei_block]
jb .fail
cmp ecx, [ebp + sizeof.EXT4_EXTENT_IDX + EXT4_EXTENT_IDX.ei_block] ;блок слeдующего индекса
jb .end_search_index ;следующий дальше - значит текущий, то что нам нужен
add ebp, sizeof.EXT4_EXTENT_IDX
dec ebx
jmp @B
.end_search_index:
;ebp указывает на нужный extent_idx, считываем следующий блок
mov ebx, [ext2_data.ext2_temp_block]
mov eax, [ebp + EXT4_EXTENT_IDX.ei_leaf_lo]
call ext2_get_block
test eax, eax
jnz .fail
mov ebp, ebx
jmp ext4_block_recursive_search ;рекурсивно прыгаем в начало
.leaf_block: ;листовой блок ebp - ext4_extent
;цикл по экстентам
@@:
test ebx, ebx
jz .fail ;ни один узел не подошел - ошибка
 
mov edx, [ebp + EXT4_EXTENT.ee_block]
cmp ecx, edx
jb .fail ;если меньше, значит он был в предыдущих блоках -> ошибка
 
movzx edi, [ebp + EXT4_EXTENT.ee_len]
add edx, edi
cmp ecx, edx
jb .end_search_extent ;нашли нужный блок
add ebp, sizeof.EXT4_EXTENT
dec ebx
jmp @B
.end_search_extent:
mov edx, [ebp + EXT4_EXTENT.ee_start_lo]
sub ecx, [ebp + EXT4_EXTENT.ee_block] ;разница в ext4 блоках
add ecx, edx
xor eax, eax
ret
 
.fail:
mov eax, ERROR_FS_FAIL
ret
 
;===================================================================
;получает адрес ext2 блока из inode с определнным номером
;in: ecx = номер блока в inode (0..)
; ebp = адрес inode
;out: ecx = адрес очередного блока
; eax - error code
ext2_get_inode_block:
test [ebp + EXT2_INODE_STRUC.i_flags], EXT2_EXTENTS_FL
jz @F
 
pushad
add ebp, EXT2_INODE_STRUC.i_block ;ebp - extent_header
call ext4_block_recursive_search
mov PUSHAD_ECX, ecx
mov PUSHAD_EAX, eax
popad
ret
 
@@:
cmp ecx, 12 ; 0..11 - direct block address
jb .get_direct_block
 
sub ecx, 12
cmp ecx, [ext2_data.count_pointer_in_block] ; 12.. - indirect blocks
jb .get_indirect_block
 
sub ecx, [ext2_data.count_pointer_in_block]
cmp ecx, [ext2_data.count_pointer_in_block_square]
jb .get_double_indirect_block
 
sub ecx, [ext2_data.count_pointer_in_block_square]
;triple indirect block
push edx ebx
 
mov eax, [ebx + EXT2_INODE_STRUC.i_block + 14*4]
mov ebx, [ext2_data.ext2_temp_block]
call ext2_get_block
test eax, eax
jnz .fail
 
xor edx, edx
mov eax, ecx
div [ext2_data.count_pointer_in_block_square]
 
;eax - номер в полученном блоке edx - номер дальше
mov eax, [ebx + eax*4]
call ext2_get_block
test eax, eax
jnz .fail
 
mov eax, edx
jmp @F
 
.get_double_indirect_block:
push edx ebx
 
mov eax, [ebp + EXT2_INODE_STRUC.i_block + 13*4]
mov ebx, [ext2_data.ext2_temp_block]
call ext2_get_block
test eax, eax
jnz .fail
 
mov eax, ecx
@@:
xor edx, edx
div [ext2_data.count_pointer_in_block]
 
mov eax, [ebx + eax*4]
call ext2_get_block
test eax, eax
jnz .fail
 
mov ecx, [ebx + edx*4]
.fail:
pop ebx edx
ret
 
.get_indirect_block:
push ebx
mov eax, [ebp + EXT2_INODE_STRUC.i_block + 12*4]
mov ebx, [ext2_data.ext2_temp_block]
call ext2_get_block
test eax, eax
jnz @F ;если не было ошибки
 
mov ecx, [ebx + ecx*4] ;заносим результат
@@:
pop ebx
ret
 
.get_direct_block:
mov ecx, [ebp + EXT2_INODE_STRUC.i_block + ecx*4]
xor eax, eax
ret
 
;===================================================================
;get content inode by num
;in: eax = inode_num
; ebx = address of inode content
;out: eax - error code
ext2_get_inode:
pushad
mov edi, ebx ;сохраним адрес inode
dec eax
xor edx, edx
mov ecx, [ext2_data.sb]
div [ecx + EXT2_SB_STRUC.inodes_per_group]
 
push edx ;locale num in group
 
mov edx, 32
mul edx ; address block_group in global_desc_table
 
; в eax - смещение группы с inode-ом относительно начала глобальной дескрипторной таблицы
; найдем блок в котором он находится
div [ext2_data.block_size]
add eax, [ecx + EXT2_SB_STRUC.first_data_block]
inc eax
mov ebx, [ext2_data.ext2_temp_block]
call ext2_get_block
test eax, eax
jnz .fail
 
add ebx, edx ; локальный номер в блоке
mov eax, [ebx + EXT2_BLOCK_GROUP_DESC.inode_table]; номер блока - в терминах ext2
 
mov ecx, [ext2_data.log_block_size]
shl eax, cl
add eax, [PARTITION_START] ; а старт раздела - в терминах hdd (512)
 
;eax - указывает на таблицу inode-ов на hdd
mov esi, eax ;сохраним его пока в esi
 
; прибавим локальный адрес inode-а
pop eax ; index
mov ecx, [ext2_data.inode_size]
mul ecx ; (index * inode_size)
mov ebp, 512
div ebp ;поделим на размер блока
 
add eax, esi ;нашли адрес блока для чтения
mov ebx, [ext2_data.ext2_temp_block]
call hd_read
cmp [hd_error], 0
jnz .fail
 
mov esi, edx ;добавим "остаток"
add esi, ebx ;к адресу
rep movsb ;копируем inode
xor eax, eax
.fail:
mov PUSHAD_EAX, eax
popad
ret
 
;----------------------------------------------------------------
;
; ext2_HdReadFolder - read disk folder
;
; esi points to filename
; ebx pointer to structure 32-bit number = first wanted block, 0+
; & flags (bitfields)
; flags: bit 0: 0=ANSI names, 1=UNICODE names
; ecx number of blocks to read, 0+
; edx mem location to return data
;
; ret ebx = blocks read or 0xffffffff folder not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
ext2_HdReadFolder:
cmp byte [esi], 0
jz .root_folder
 
push ebx ecx edx
call ext2_find_lfn ;вернет в ebp адрес inode
pop edx ecx ebx
test eax, eax
jnz .error_ret
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
jz .error_not_found
jmp @F
 
.root_folder:
mov ebp, [ext2_data.root_inode]
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
jz .error_root
;придется копировать inode
push ecx
mov esi, ebp
mov edi, [ext2_data.ext2_save_inode]
mov ecx, [ext2_data.inode_size]
shr ecx, 2
mov ebp, edi
rep movsd
pop ecx
@@:
cmp [ebp + EXT2_INODE_STRUC.i_size], 0 ;папка пуста
je .error_empty_dir
push edx ;адрес результата [edi + 28]
push 0 ;конец очередного блока папки [edi + 24]
push ecx ;сколько файлов нужно прочитать [edi + 20]
push dword [ebx] ;первый "нужный" файл [edi + 16]
push dword [ebx + 4];флаги [edi + 12]
push 0 ;[EXT2_read_in_folder] [edi + 8]
push 0 ;[EXT2_files_in_folder] [edi + 4]
push 0 ;номер блока по порядку [edi]
 
mov edi, edx
mov ecx, 32/4
rep stosd ; fill header zero
mov edi, esp ; edi - указатель на локальные переменные
add edx, 32 ; edx = current mem for return
 
xor ecx, ecx ; получим номер первого блока
call ext2_get_inode_block
test eax, eax
jnz .error_get_block
 
mov eax, ecx
mov ebx, [ext2_data.ext2_save_block]
call ext2_get_block ; и считываем блок с hdd
test eax, eax
jnz .error_get_block
 
mov esi, ebx ; esi = current dir record
add ebx, [ext2_data.block_size]
mov [edi + 24], ebx ; запомним конец очередного блока
 
mov ecx, [edi + 16] ; ecx = first wanted (flags ommited)
 
.find_wanted_start:
jecxz .find_wanted_end
.find_wanted_cycle:
cmp [esi + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used
jz @F
inc dword [edi + 4] ; EXT2_files_in_folder
dec ecx
@@:
movzx ebx, [esi + EXT2_DIR_STRUC.rec_len]
 
cmp ebx, 12 ; минимальная длина записи
jb .error_bad_len
test ebx, 0x3 ; длина записи должна делиться на 4
jnz .error_bad_len
 
sub [ebp + EXT2_INODE_STRUC.i_size], ebx ;вычитаем напрямую из структуры inode
add esi, ebx ; к следующей записи
cmp esi, [edi + 24] ; сравниваем с концом блока
jb .find_wanted_start
 
push .find_wanted_start
.end_block: ;вылетели из цикла
cmp [ebp + EXT2_INODE_STRUC.i_size], 0
jle .end_dir
 
inc dword [edi] ;получаем новый блок
push ecx
mov ecx, [edi]
call ext2_get_inode_block
test eax, eax
jnz .error_get_block
 
mov eax, ecx
mov ebx, [ext2_data.ext2_save_block]
call ext2_get_block
test eax, eax
jnz .error_get_block
 
pop ecx
mov esi, ebx
add ebx, [ext2_data.block_size]
mov [edi + 24], ebx ;запомним конец блока
ret ; опять в цикл
 
.wanted_end:
loop .find_wanted_cycle ; ecx 0 => -1 нужно посчитать сколько файлов
 
;дошли до первого "нужного" файла
.find_wanted_end:
mov ecx, [edi + 20]
.wanted_start: ; ищем first_wanted+count
jecxz .wanted_end
cmp [esi + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used
jz .empty_rec
inc dword [edi + 8]
inc dword [edi + 4]
 
push edi ecx
mov edi, edx ;обнуляем место под очереное имя файла/папки
xor eax, eax
mov ecx, 40 / 4
rep stosd
pop ecx edi
 
push esi edi edx
mov eax, [esi + EXT2_DIR_STRUC.inode] ;получим дочерний inode
mov ebx, [ext2_data.ext2_temp_inode]
call ext2_get_inode
test eax, eax
jnz .error_read_subinode
 
lea edi, [edx + 8]
 
mov eax, [ebx + EXT2_INODE_STRUC.i_ctime] ; переведем время в ntfs формат
xor edx, edx
add eax, 3054539008 ;(369 * 365 + 89) * 24 * 3600
adc edx, 2
call ntfs_datetime_to_bdfe.sec
 
mov eax, [ebx + EXT2_INODE_STRUC.i_atime]
xor edx, edx
add eax, 3054539008
adc edx, 2
call ntfs_datetime_to_bdfe.sec
 
mov eax, [ebx + EXT2_INODE_STRUC.i_mtime]
xor edx, edx
add eax, 3054539008
adc edx, 2
call ntfs_datetime_to_bdfe.sec
 
pop edx ; пока достаем только буфер
test [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR ; для папки размер
jnz @F ; не возвращаем
 
mov eax, [ebx + EXT2_INODE_STRUC.i_size] ;low size
stosd
mov eax, [ebx + EXT2_INODE_STRUC.i_dir_acl] ;high size
stosd
xor dword [edx], FS_FT_DIR ;помечаем, что это файл(2 раза xor)
@@:
xor dword [edx], FS_FT_DIR ;помечаем, что это файл
 
;теперь скопируем имя, сконвертировав из UTF-8 в CP866
push ecx ;edi и esi уже сохранены в стеке
movzx ecx, [esi + EXT2_DIR_STRUC.name_len]
lea edi, [edx + 40]
lea esi, [esi + EXT2_DIR_STRUC.name]
call utf8_to_cp866
and byte [edi], 0
pop ecx edi esi
 
cmp byte [edx + 40], '.' ; в linux файл, начинающийся с точки - скрытый
jne @F
or dword [edx], FS_FT_HIDDEN
@@:
 
add edx, 40 + 264 ; go to next record
dec ecx ; если запись пустая ecx не надо уменьшать
.empty_rec:
movzx ebx, [esi + EXT2_DIR_STRUC.rec_len]
cmp ebx, 12 ; минимальная длина записи
jb .error_bad_len
test ebx, 0x3 ; длина записи должна делиться на 4
jnz .error_bad_len
 
sub [ebp + EXT2_INODE_STRUC.i_size], ebx ;вычитаем напрямую из структуры inode
add esi, ebx
cmp esi, [edi + 24] ;дошли ли до конца блока?
jb .wanted_start
 
push .wanted_start ; дошли
jmp .end_block
 
.end_dir: ;конец папки, когда еще не дошли до нужного файла
mov edx, [edi + 28] ;адрес структуры результата
mov ebx, [edi + 8] ;EXT2_read_in_folder
mov ecx, [edi + 4] ;EXT2_files_in_folder
mov dword [edx], 1 ;version
mov [edx + 4], ebx
mov [edx + 8], ecx
lea esp, [edi + 32]
xor eax, eax ;зарезервировано: нули в текущей реализации
lea edi, [edx + 12]
mov ecx, 20 / 4
rep stosd
ret
 
.error_bad_len:
mov eax, ERROR_FS_FAIL
.error_read_subinode:
.error_get_block:
lea esp, [edi + 32]
.error_ret:
or ebx, -1
ret
.error_empty_dir: ;inode папки без блоков
.error_root: ;root - не папка
mov eax, ERROR_FS_FAIL
jmp .error_ret
 
.error_not_found: ;файл не найден
mov eax, ERROR_FILE_NOT_FOUND
jmp .error_ret
;============================================
;convert UTF-8 string to ASCII-string (codepage 866)
;in: ecx = length source
; esi = source
; edi = buffer
; destroys: eax,esi,edi
utf8_to_cp866:
jecxz .ret
.start:
lodsw
cmp al, 0x80
jb .ascii
 
xchg al, ah ; big-endian
cmp ax, 0xd080
jz .yo1
cmp ax, 0xd191
jz .yo2
cmp ax, 0xd090
jb .unk
cmp ax, 0xd180
jb .rus1
cmp ax, 0xd190
jb .rus2
.unk:
mov al, '_'
jmp .doit
.yo1:
mov al, 0xf0 ; Ё capital
jmp .doit
.yo2:
mov al, 0xf1 ; ё small
jmp .doit
.rus1:
sub ax, 0xd090 - 0x80
jmp .doit
.rus2:
sub ax, 0xd18f - 0xEF
.doit:
stosb
sub ecx, 2
ja .start
ret
 
.ascii:
stosb
dec esi
dec ecx
jnz .start
.ret:
ret
 
;----------------------------------------------------------------
;
; ext2_HdRead - read hard disk
;
; esi points to filename
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to read, 0+
; edx mem location to return data
;
; ret ebx = bytes read or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
 
;--------------------------------------------------------------
ext2_HdRead:
cmp byte [esi], 0
jnz @F
 
.this_is_nofile:
or ebx, -1
mov eax, ERROR_ACCESS_DENIED
ret
 
@@:
push ecx ebx edx
call ext2_find_lfn
pop edx ebx ecx
test eax, eax
jz @F
 
or ebx, -1
mov eax, ERROR_FILE_NOT_FOUND
ret
 
@@:
mov ax, [ebp + EXT2_INODE_STRUC.i_mode]
and ax, EXT2_S_IFMT ;оставляем только тип inode в ax
cmp ax, EXT2_S_IFREG
jne .this_is_nofile
 
mov edi, edx ; edi = pointer to return mem
 
test ebx, ebx
jz @F
mov esi, ebx ; esi = pointer to first_wanted
mov ebx, [esi+4]
mov eax, [esi] ; ebx : eax - стартовый номер байта
 
;///// сравним хватит ли нам файла или нет
cmp [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx
ja .size_great
jb .size_less
 
cmp [ebp + EXT2_INODE_STRUC.i_size], eax
ja .size_great
 
.size_less:
xor ebx, ebx
mov eax, ERROR_END_OF_FILE
ret
@@:
xor ebx, ebx
xor eax, eax
.size_great:
add eax, ecx ;add to first_wanted кол-во байт для чтения
adc ebx, 0
 
cmp [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx
ja .size_great_great
jb .size_great_less
cmp [ebp + EXT2_INODE_STRUC.i_size], eax
jae .size_great_great
 
.size_great_less:
push 1 ;читаем по границе размера
mov ecx, [ebp + EXT2_INODE_STRUC.i_size]
sub ecx, [esi] ;(размер - старт) = сколько читать
jmp @F
 
.size_great_great:
push 0 ;читаем столько сколько запросили
 
@@:
;здесь мы точно знаем сколько байт читать - ecx
;edi - return memory
;esi -> first wanted
 
push ecx ;количество считанных байт
test esi, esi
jz .zero_start
 
;получим кусок из первого блока
mov edx, [esi+4]
mov eax, [esi]
div [ext2_data.block_size]
 
push eax ;счетчик блоков ложим в стек
push ecx
mov ecx, eax
call ext2_get_inode_block
test eax, eax
jnz .error_at_first_block
mov ebx, [ext2_data.ext2_save_block]
mov eax, ecx
call ext2_get_block
test eax, eax
jnz .error_at_first_block
pop ecx
add ebx, edx
 
neg edx
add edx, [ext2_data.block_size] ;block_size - стартовый байт = сколько байт 1-го блока
cmp ecx, edx
jbe .only_one_block
 
mov eax, ecx
sub eax, edx
mov ecx, edx
 
mov esi, ebx
rep movsb ;кусок 1-го блока
jmp .calc_blocks_count
 
.zero_start:
mov eax, ecx
push 0 ;счетчик блоков ложим в стек
;теперь в eax кол-во оставшихся байт для чтения
.calc_blocks_count:
mov ebx, edi ;чтение блока прям в ->ebx
xor edx, edx
div [ext2_data.block_size] ;кол-во байт в последнем блоке (остаток) в edx
mov edi, eax ;кол-во целых блоков в edi
@@:
test edi, edi
jz .finish_block
inc dword [esp]
mov ecx, [esp]
call ext2_get_inode_block
test eax, eax
jnz .error_at_read_cycle
 
mov eax, ecx ;а ebx уже забит нужным значением
call ext2_get_block
test eax, eax
jnz .error_at_read_cycle
add ebx, [ext2_data.block_size]
 
dec edi
jmp @B
 
.finish_block: ;в edx - кол-во байт в последнем блоке
test edx, edx
jz .end_read
 
pop ecx ;счетчик блоков -> ecx
inc ecx
call ext2_get_inode_block
test eax, eax
jnz .error_at_finish_block
 
mov edi, ebx
mov eax, ecx
mov ebx, [ext2_data.ext2_save_block]
call ext2_get_block
test eax, eax
jnz .error_at_finish_block
 
mov ecx, edx
mov esi, ebx
rep movsb ;кусок last блока
jmp @F
 
.end_read:
pop ecx ;счетчик блоков, который хранился в стеке
@@:
pop ebx ;количество считанных байт
pop eax ; 1 или 0 - достигли ли конца файла
test eax, eax
jz @F
 
mov eax, ERROR_END_OF_FILE
ret
@@:
xor eax, eax
ret
.only_one_block:
mov esi, ebx
rep movsb ;кусок last блока
jmp .end_read
.error_at_first_block:
pop edx
.error_at_read_cycle:
pop ebx
.error_at_finish_block:
pop ecx edx
or ebx, -1
ret
 
;----------------------------------------------------------------
; in: esi = file path
; ebx = pointer to dir block
; out: esi - name without parent or not_changed
; ebx - dir_rec of inode children
ext2_test_block_by_name:
sub esp, 256 ;EXT2_filename
mov edx, ebx
add edx, [ext2_data.block_size] ;запомним конец блока
 
.start_rec:
cmp [ebx + EXT2_DIR_STRUC.inode], 0
jz .next_rec
 
mov edi, esp
push esi
movzx ecx, [ebx + EXT2_DIR_STRUC.name_len]
lea esi, [ebx + EXT2_DIR_STRUC.name]
call utf8_to_cp866
 
mov ecx, edi
lea edi, [esp + 4]
sub ecx, edi ;кол-во байт в получившейся строке
 
mov esi, [esp]
@@:
jecxz .test_find
dec ecx
 
lodsb
call char_toupper
 
mov ah, [edi]
inc edi
xchg al, ah
call char_toupper
cmp al, ah
je @B
@@: ;не подошло
pop esi
.next_rec:
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len]
add ebx, eax ;к след. записи
cmp ebx, edx ;проверим конец ли
jb .start_rec
add esp, 256
ret
 
.test_find:
cmp byte [esi], 0
je .ret ;нашли конец
cmp byte [esi], '/'
jne @B
inc esi
.ret:
add esp, 256 + 4
ret
 
;========================
;Ищет inode по строке пути
;in: esi = name
;out: eax - error code
; ebp = inode
; dl - первый байт из имени файла/папки
ext2_find_lfn:
mov ebp, [ext2_data.root_inode]
cmp [ebp + EXT2_INODE_STRUC.i_blocks], 0
je .error_empty_root
.next_path_part:
push [ebp + EXT2_INODE_STRUC.i_blocks]
xor ecx, ecx
.folder_block_cycle:
push ecx
call ext2_get_inode_block
test eax, eax
jnz .error_get_inode_block
mov eax, ecx
mov ebx, [ext2_data.ext2_save_block] ;ebx = cur dir record
call ext2_get_block
test eax, eax
jnz .error_get_block
push esi
call ext2_test_block_by_name
pop edi ecx
 
cmp edi, esi ;нашли имя?
je .next_folder_block ;не нашли -> к след. блоку
cmp byte [esi], 0 ;дошли до "конца" пути -> возваращаемся
jz .get_inode_ret
 
cmp [ebx + EXT2_DIR_STRUC.file_type], EXT2_FT_DIR ;нашли, но это не папка
jne .not_found
 
mov eax, [ebx + EXT2_DIR_STRUC.inode]
mov ebx, [ext2_data.ext2_save_inode] ;все же папка.
call ext2_get_inode
test eax, eax
jnz .error_get_inode
pop ecx ;в стеке лежит кол-во блоков
mov ebp, ebx
jmp .next_path_part
.next_folder_block:
;к следующему блоку в текущей папке
pop eax ;счетчик блоков
sub eax, [ext2_data.count_block_in_block]
jle .not_found
push eax
inc ecx
jmp .folder_block_cycle
 
.not_found:
mov eax, ERROR_FILE_NOT_FOUND
ret
 
.get_inode_ret:
pop ecx ;в стеке лежит кол-во блоков
mov dl, [ebx + EXT2_DIR_STRUC.name] ;в dl - первый символ ()
mov eax, [ebx + EXT2_DIR_STRUC.inode]
mov ebx, [ext2_data.ext2_save_inode]
call ext2_get_inode
mov ebp, ebx
xor eax, eax
ret
 
.error_get_inode_block:
.error_get_block:
pop ecx
.error_get_inode:
pop ebx
.error_empty_root:
mov eax, ERROR_FS_FAIL
ret
 
;----------------------------------------------------------------
;ext2_HdGetFileInfo - read file info from block device
;
;in: esi points to filename
; edx mem location to return data
;--------------------------------------------------------------
ext2_HdGetFileInfo:
xchg bx, bx
cmp byte [esi], 0
jz .is_root
 
push edx
call ext2_find_lfn
mov ebx, edx
pop edx
test eax, eax
jz @F
ret
 
.is_root:
xor ebx, ebx ;root не может быть скрытым
mov ebp, [ext2_data.root_inode]
@@:
xor eax, eax
mov edi, edx
mov ecx, 40/4
rep stosd ; fill zero
 
cmp bl, '.'
jne @F
or dword [edx], FS_FT_HIDDEN
@@:
 
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
jnz @F
mov eax, [ebp + EXT2_INODE_STRUC.i_size] ;low size
mov ebx, [ebp + EXT2_INODE_STRUC.i_dir_acl] ;high size
mov dword [edx+32], eax
mov dword [edx+36], ebx
xor dword [edx], FS_FT_DIR
@@:
xor dword [edx], FS_FT_DIR
 
lea edi, [edx + 8]
mov eax, [ebp + EXT2_INODE_STRUC.i_ctime]
xor edx, edx
add eax, 3054539008
adc edx, 2
call ntfs_datetime_to_bdfe.sec
 
mov eax, [ebp + EXT2_INODE_STRUC.i_atime]
xor edx, edx
add eax, 3054539008
adc edx, 2
call ntfs_datetime_to_bdfe.sec
 
mov eax, [ebp + EXT2_INODE_STRUC.i_mtime]
xor edx, edx
add eax, 3054539008
adc edx, 2
call ntfs_datetime_to_bdfe.sec
 
xor eax, eax
ret
 
ext2_HdRewrite:
ext2_HdWrite:
ext2_HdSetFileEnd:
ext2_HdSetFileInfo:
ext2_HdDelete:
ext2_HdCreateFolder:
xor ebx, ebx
mov eax, ERROR_UNSUPPORTED_FS
ret
/kernel/branches/net/fs/fat12.inc
0,0 → 1,2275
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; FAT12.INC ;;
;; (C) 2005 Mario79, License: GPL ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
n_sector dd 0 ; temporary save for sector value
flp_status dd 0
clust_tmp_flp dd 0 ; used by analyze_directory and analyze_directory_to_write
path_pointer_flp dd 0
pointer_file_name_flp dd 0
save_root_flag db 0
save_flag db 0
root_read db 0 ; 0-necessary to load root, 1-not to load root
flp_fat db 0 ; 0-necessary to load fat, 1-not to load fat
flp_number db 0 ; 1- Floppy A, 2-Floppy B
old_track db 0 ; old value track
flp_label rb 15 ; Label and ID of inserted floppy disk
 
reserve_flp:
 
cli
cmp [flp_status], 0
je reserve_flp_ok
 
sti
call change_task
jmp reserve_flp
 
reserve_flp_ok:
 
push eax
mov eax, [CURRENT_TASK]
shl eax, 5
mov eax, [eax+CURRENT_TASK+TASKDATA.pid]
mov [flp_status], eax
pop eax
sti
ret
 
 
floppy_fileread:
;----------------------------------------------------------------
;
; fileread - sys floppy
;
; eax points to filename 11 chars - for root directory
; ebx first wanted block ; 1+ ; if 0 then set to 1
; ecx number of blocks to read ; 1+ ; if 0 then set to 1
; edx mem location to return data
; esi length of filename 12*X
; edi pointer to path /fd/1/...... - for all files in nested directories
;
; ret ebx = size or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
; 10 = access denied
;--------------------------------------------------------------
 
mov [save_flag], 0
mov [path_pointer_flp], edi
test esi, esi ; return ramdisk root
jnz fr_noroot_1
cmp ebx, 224/16
jbe fr_do_1
mov eax, 5
xor ebx, ebx
mov [flp_status], ebx
ret
 
fr_do_1:
push ebx ecx edx
call read_flp_root
pop edx ecx ebx
cmp [FDC_Status], 0
jne fdc_status_error_1
mov edi, edx
dec ebx
shl ebx, 9
mov esi, FLOPPY_BUFF
add esi, ebx
shl ecx, 9
cld
rep movsb
xor eax, eax
xor ebx, ebx
; mov eax,0 ; ok read
; mov ebx,0
mov [flp_status], eax
ret
fdc_status_error_1:
xor eax, eax
mov [flp_status], eax
mov eax, 10
or ebx, -1
ret
 
fr_noroot_1:
sub esp, 32
call expand_filename
frfloppy_1:
test ebx, ebx
jnz frfl5_1
mov ebx, 1
frfl5_1:
test ecx, ecx
jnz frfl6_1
mov ecx, 1
frfl6_1:
dec ebx
push eax
push eax ebx ecx edx esi edi
call read_flp_fat
cmp [FDC_Status], 0
jne fdc_status_error_3_1
mov [FDD_Track], 0; Öèëèíäð
mov [FDD_Head], 1; Ñòîðîíà
mov [FDD_Sector], 2; Ñåêòîð
call SeekTrack
mov dh, 14
l.20_1:
call ReadSectWithRetr
cmp [FDC_Status], 0
jne fdc_status_error_3_1
mov dl, 16
mov edi, FDD_BUFF
inc [FDD_Sector]
l.21_1:
mov esi, eax ;Name of file we want
mov ecx, 11
cld
rep cmpsb ;Found the file?
je fifound_1 ;Yes
add ecx, 21
add edi, ecx ;Advance to next entry
dec dl
test dl, dl
jnz l.21_1
dec dh
test dh, dh
jnz l.20_1
fdc_status_error_3:
mov eax, 5 ; file not found ?
or ebx, -1
add esp, 32+28
mov [flp_status], 0
ret
fdc_status_error_3_2:
cmp [FDC_Status], 0
je fdc_status_error_3
fdc_status_error_3_1:
add esp, 32+28
jmp fdc_status_error_1
 
fifound_1:
mov eax, [path_pointer_flp]
cmp [eax+36], byte 0
je fifound_2
add edi, 0xf
mov eax, [edi]
and eax, 65535
mov ebx, [path_pointer_flp]
add ebx, 36
call get_cluster_of_a_path_flp
jc fdc_status_error_3_2
mov ebx, [ebx-11+28] ;file size
mov [esp+20], ebx
mov [esp+24], ebx
jmp fifound_3
fifound_2:
mov ebx, [edi-11+28] ;file size
mov [esp+20], ebx
mov [esp+24], ebx
add edi, 0xf
mov eax, [edi]
fifound_3:
and eax, 65535
mov [n_sector], eax ;eax=cluster
frnew_1:
add eax, 31 ;bootsector+2*fat+filenames
cmp [esp+16], dword 0; wanted cluster ?
jne frfl7_1
call read_chs_sector
cmp [FDC_Status], 0
jne fdc_status_error_5
mov edi, [esp+8]
call give_back_application_data_1
add [esp+8], dword 512
dec dword [esp+12] ; last wanted cluster ?
cmp [esp+12], dword 0
je frnoread_1
jmp frfl8_1
frfl7_1:
dec dword [esp+16]
frfl8_1:
mov edi, [n_sector]
shl edi, 1 ;find next cluster from FAT
add edi, FLOPPY_FAT
mov eax, [edi]
and eax, 4095
mov edi, eax
mov [n_sector], edi
cmp edi, 4095 ;eof - cluster
jz frnoread2_1
cmp [esp+24], dword 512;eof - size
jb frnoread_1
sub [esp+24], dword 512
jmp frnew_1
 
read_chs_sector:
call calculate_chs
call ReadSectWithRetr
ret
 
frnoread2_1:
cmp [esp+16], dword 0; eof without read ?
je frnoread_1
mov [fdc_irq_func], fdc_null
pop edi esi edx ecx
add esp, 4
pop ebx; ebx <- eax : size of file
add esp, 36
mov eax, 6; end of file
mov [flp_status], 0
ret
 
frnoread_1:
pop edi esi edx ecx
add esp, 4
pop ebx; ebx <- eax : size of file
add esp, 36
xor eax, eax
mov [flp_status], eax
ret
 
fdc_status_error_5:
pop edi esi edx ecx
add esp, 4
pop ebx; ebx <- eax : size of file
add esp, 36
jmp fdc_status_error_1
 
read_flp_root:
pusha
call check_label
cmp [FDC_Status], 0
jne unnecessary_root_read
cmp [root_read], 1
je unnecessary_root_read
mov [FDD_Track], 0; Öèëèíäð
mov [FDD_Head], 1; Ñòîðîíà
mov [FDD_Sector], 2; Ñåêòîð
mov edi, FLOPPY_BUFF
call SeekTrack
read_flp_root_1:
call ReadSectWithRetr
cmp [FDC_Status], 0
jne unnecessary_root_read
push edi
call give_back_application_data_1
pop edi
add edi, 512
inc [FDD_Sector]
cmp [FDD_Sector], 16
jne read_flp_root_1
mov [root_read], 1
unnecessary_root_read:
popa
ret
 
 
read_flp_fat:
pusha
call check_label
cmp [FDC_Status], 0
jne unnecessary_flp_fat
cmp [flp_fat], 1
je unnecessary_flp_fat
mov [FDD_Track], 0; Öèëèíäð
mov [FDD_Head], 0; Ñòîðîíà
mov [FDD_Sector], 2; Ñåêòîð
mov edi, FLOPPY_BUFF
call SeekTrack
read_flp_fat_1:
call ReadSectWithRetr
cmp [FDC_Status], 0
jne unnecessary_flp_fat
push edi
call give_back_application_data_1
pop edi
add edi, 512
inc [FDD_Sector]
cmp [FDD_Sector], 19
jne read_flp_fat_1
mov [FDD_Sector], 1
mov [FDD_Head], 1
call ReadSectWithRetr
cmp [FDC_Status], 0
jne unnecessary_flp_fat
call give_back_application_data_1
call calculatefatchain_flp
mov [root_read], 0
mov [flp_fat], 1
unnecessary_flp_fat:
popa
ret
 
calculatefatchain_flp:
pushad
 
mov esi, FLOPPY_BUFF
mov edi, FLOPPY_FAT
 
fcnew_1:
mov eax, dword [esi]
mov ebx, dword [esi+4]
mov ecx, dword [esi+8]
mov edx, ecx
shr edx, 4;8 ok
shr dx, 4;7 ok
xor ch, ch
shld ecx, ebx, 20;6 ok
shr cx, 4;5 ok
shld ebx, eax, 12
and ebx, 0x0fffffff;4 ok
shr bx, 4;3 ok
shl eax, 4
and eax, 0x0fffffff;2 ok
shr ax, 4;1 ok
mov dword [edi], eax
add edi, 4
mov dword [edi], ebx
add edi, 4
mov dword [edi], ecx
add edi, 4
mov dword [edi], edx
add edi, 4
add esi, 12
 
cmp edi, FLOPPY_FAT+2856*2;2849 clusters
jnz fcnew_1
 
popad
ret
 
check_label:
pushad
mov [FDD_Track], 0; Öèëèíäð
mov [FDD_Head], 0; Ñòîðîíà
mov [FDD_Sector], 1; Ñåêòîð
call SetUserInterrupts
call FDDMotorON
call RecalibrateFDD
cmp [FDC_Status], 0
jne fdc_status_error
call SeekTrack
cmp [FDC_Status], 0
jne fdc_status_error
call ReadSectWithRetr
cmp [FDC_Status], 0
jne fdc_status_error
mov esi, flp_label
mov edi, FDD_BUFF+39
mov ecx, 15
cld
rep cmpsb
je same_label
mov [root_read], 0
mov [flp_fat], 0
same_label:
mov esi, FDD_BUFF+39
mov edi, flp_label
mov ecx, 15
cld
rep movsb
popad
ret
fdc_status_error:
popad
ret
 
save_flp_root:
pusha
call check_label
cmp [FDC_Status], 0
jne unnecessary_root_save
cmp [root_read], 0
je unnecessary_root_save
mov [FDD_Track], 0; Öèëèíäð
mov [FDD_Head], 1; Ñòîðîíà
mov [FDD_Sector], 2; Ñåêòîð
mov esi, FLOPPY_BUFF
call SeekTrack
save_flp_root_1:
push esi
call take_data_from_application_1
pop esi
add esi, 512
call WriteSectWithRetr
cmp [FDC_Status], 0
jne unnecessary_root_save
inc [FDD_Sector]
cmp [FDD_Sector], 16
jne save_flp_root_1
unnecessary_root_save:
mov [fdc_irq_func], fdc_null
popa
ret
 
save_flp_fat:
pusha
call check_label
cmp [FDC_Status], 0
jne unnecessary_flp_fat_save
cmp [flp_fat], 0
je unnecessary_flp_fat_save
call restorefatchain_flp
mov [FDD_Track], 0; Öèëèíäð
mov [FDD_Head], 0; Ñòîðîíà
mov [FDD_Sector], 2; Ñåêòîð
mov esi, FLOPPY_BUFF
call SeekTrack
save_flp_fat_1:
push esi
call take_data_from_application_1
pop esi
add esi, 512
call WriteSectWithRetr
cmp [FDC_Status], 0
jne unnecessary_flp_fat_save
inc [FDD_Sector]
cmp [FDD_Sector], 19
jne save_flp_fat_1
mov [FDD_Sector], 1
mov [FDD_Head], 1
call take_data_from_application_1
call WriteSectWithRetr
cmp [FDC_Status], 0
jne unnecessary_flp_fat_save
mov [root_read], 0
unnecessary_flp_fat_save:
mov [fdc_irq_func], fdc_null
popa
ret
 
 
restorefatchain_flp: ; restore fat chain
pushad
 
mov esi, FLOPPY_FAT
mov edi, FLOPPY_BUFF
 
fcnew2_1:
mov eax, dword [esi]
mov ebx, dword [esi+4]
shl ax, 4
shl eax, 4
shl bx, 4
shr ebx, 4
shrd eax, ebx, 8
shr ebx, 8
mov dword [edi], eax
add edi, 4
mov word [edi], bx
add edi, 2
add esi, 8
 
cmp edi, FLOPPY_BUFF+0x1200;4274 bytes - all used FAT
jb fcnew2_1
 
mov esi, FLOPPY_BUFF ; duplicate fat chain
mov edi, FLOPPY_BUFF+0x1200
mov ecx, 0x1200/4
cld
rep movsd
 
popad
ret
 
 
save_chs_sector:
call calculate_chs
call WriteSectWithRetr
ret
 
calculate_chs:
mov bl, [FDD_Track]
mov [old_track], bl
mov ebx, 18
xor edx, edx
div ebx
inc edx
mov [FDD_Sector], dl
xor edx, edx
mov ebx, 2
div ebx
mov [FDD_Track], al
mov [FDD_Head], 0
test edx, edx
jz no_head_2
inc [FDD_Head]
no_head_2:
mov dl, [old_track]
cmp dl, [FDD_Track]
je no_seek_track_1
call SeekTrack
no_seek_track_1:
ret
 
 
get_cluster_of_a_path_flp:
;---------------------------------------------------------
; input : EBX = pointer to a path string
; (example: the path "/files/data/document" become
; "files......data.......document...0"
; '.' = space char
; '0' = char(0) (ASCII=0) !!! )
; output : if (CARRY=1) -> ERROR in the PATH
; if (CARRY=0) -> EAX=cluster
;---------------------------------------------------------
 
push edx
mov edx, ebx
 
search_end_of_path_flp:
cmp [save_flag], 0
jne search_end_of_path_flp_1
cmp byte [edx], 0
je found_end_of_path_flp
jmp search_end_of_path_flp_2
search_end_of_path_flp_1:
cmp byte [edx+12], 0
je found_end_of_path_flp
search_end_of_path_flp_2:
inc edx; '/'
call analyze_directory_flp
jc directory_not_found_flp
 
mov eax, [ebx+20-2] ; read the HIGH 16bit cluster field
mov ax, [ebx+26] ; read the LOW 16bit cluster field
and eax, 0xfff ;[fatMASK]
add edx, 11 ; 8+3 (name+extension)
jmp search_end_of_path_flp
 
found_end_of_path_flp:
inc edx
mov [pointer_file_name_flp], edx
pop edx
clc ; no errors
ret
 
directory_not_found_flp:
pop edx
stc ; errors occour
ret
 
analyze_directory_flp:
;--------------------------------
; input : EAX = first cluster of the directory
; EBX = pointer to filename
; output : IF CARRY=0 EAX = sector where th file is found
; EBX = pointer in buffer
; [buffer .. buffer+511]
; ECX,EDX,EDI,EDI not changed
; IF CARRY=1
;--------------------------------
push ebx;[esp+16]
push ecx
push edx
push esi
push edi
 
 
adr56_flp:
mov [clust_tmp_flp], eax
add eax, 31
pusha
call read_chs_sector
popa
cmp [FDC_Status], 0
jne not_found_file_analyze_flp
 
mov ecx, 512/32
mov ebx, FDD_BUFF
 
adr1_analyze_flp:
mov esi, edx;[esp+16]
mov edi, ebx
cld
push ecx
mov ecx, 11
rep cmpsb
pop ecx
je found_file_analyze_flp
 
add ebx, 32
loop adr1_analyze_flp
 
mov eax, [clust_tmp_flp]
shl eax, 1 ;find next cluster from FAT
add eax, FLOPPY_FAT
mov eax, [eax]
and eax, 4095
cmp eax, 0x0ff8
jb adr56_flp
not_found_file_analyze_flp:
pop edi
pop esi
pop edx
pop ecx
add esp, 4
stc ;file not found
ret
 
found_file_analyze_flp:
pop edi
pop esi
pop edx
pop ecx
add esp, 4
clc ;file found
ret
 
 
; \begin{diamond}
fat_find_lfn:
; in: esi->name
; [esp+4] = next
; [esp+8] = first
; [esp+C]... - possibly parameters for first and next
; out: CF=1 - file not found, eax=error code
; else CF=0, esi->next name component, edi->direntry
pusha
lea eax, [esp+0Ch+20h]
call dword [eax-4]
jc .reterr
sub esp, 262*2 ; reserve place for LFN
push 0 ; for fat_get_name: read ASCII name
.l1:
lea ebp, [esp+4]
call fat_get_name
jc .l2
call fat_compare_name
jz .found
.l2:
mov ebp, [esp+8+262*2+4]
lea eax, [esp+0Ch+20h+262*2+4]
call dword [eax-8]
jnc .l1
add esp, 262*2+4
.reterr:
mov [esp+28], eax
stc
popa
ret
.found:
add esp, 262*2+4
mov ebp, [esp+8]
; if this is LFN entry, advance to true entry
cmp byte [edi+11], 0xF
jnz @f
lea eax, [esp+0Ch+20h]
call dword [eax-8]
jc .reterr
@@:
add esp, 8 ; CF=0
push esi
push edi
popa
ret
 
uglobal
; this is for delete support
fd_prev_sector dd ?
fd_prev_prev_sector dd ?
endg
 
flp_root_next:
cmp edi, OS_BASE+0xD200-0x20
jae @f
add edi, 0x20
ret ; CF=0
@@:
; read next sector
inc dword [eax]
cmp dword [eax], 14
jae flp_root_first.readerr
push [fd_prev_sector]
pop [fd_prev_prev_sector]
push eax
mov eax, [eax]
add eax, 19-1
mov [fd_prev_sector], eax
pop eax
flp_root_first:
mov eax, [eax]
pusha
add eax, 19
call read_chs_sector
popa
cmp [FDC_Status], 0
jnz .readerr
mov edi, FDD_BUFF
ret ; CF=0
.readerr:
stc
ret
 
flp_rootmem_first:
mov edi, FLOPPY_BUFF
clc
ret
flp_rootmem_next:
add edi, 0x20
cmp edi, FLOPPY_BUFF+14*0x200
cmc
flp_rootmem_next_write:
flp_rootmem_begin_write:
flp_rootmem_end_write:
ret
flp_rootmem_extend_dir:
stc
ret
 
flp_notroot_next:
cmp edi, OS_BASE+0xD200-0x20
jae flp_notroot_next_sector
add edi, 0x20
ret ; CF=0
flp_notroot_next_sector:
push ecx
mov ecx, [eax]
push [fd_prev_sector]
pop [fd_prev_prev_sector]
add ecx, 31
mov [fd_prev_sector], ecx
mov ecx, [(ecx-31)*2+FLOPPY_FAT]
and ecx, 0xFFF
cmp ecx, 2849
jae flp_notroot_first.err2
mov [eax], ecx
pop ecx
flp_notroot_first:
mov eax, [eax]
cmp eax, 2
jb .err
cmp eax, 2849
jae .err
pusha
add eax, 31
call read_chs_sector
popa
mov edi, FDD_BUFF
cmp [FDC_Status], 0
jnz .err
ret ; CF=0
.err2:
pop ecx
.err:
stc
ret
flp_notroot_begin_write:
pusha
mov eax, [eax]
add eax, 31
call read_chs_sector
popa
ret
flp_notroot_end_write:
pusha
mov eax, [eax]
add eax, 31
call save_chs_sector
popa
ret
flp_notroot_next_write:
cmp edi, OS_BASE+0xD200
jae @f
ret
@@:
call flp_notroot_end_write
jmp flp_notroot_next_sector
flp_notroot_extend_dir:
; find free cluster in FAT
pusha
xor eax, eax
mov edi, FLOPPY_FAT
mov ecx, 2849
repnz scasw
jnz .notfound
mov word [edi-2], 0xFFF ; mark as last cluster
sub edi, FLOPPY_FAT
shr edi, 1
dec edi
mov eax, [esp+28]
mov ecx, [eax]
mov [FLOPPY_FAT+ecx*2], di
mov [eax], edi
xor eax, eax
mov edi, FDD_BUFF
mov ecx, 128
rep stosd
popa
call flp_notroot_end_write
mov edi, FDD_BUFF
clc
ret
.notfound:
popa
stc
ret
 
fd_find_lfn:
; in: esi+ebp -> name
; out: CF=1 - file not found
; else CF=0 and edi->direntry, eax=directory cluster (0 for root)
push esi edi
push 0
push flp_root_first
push flp_root_next
.loop:
call fat_find_lfn
jc .notfound
cmp byte [esi], 0
jz .found
.continue:
test byte [edi+11], 10h
jz .notfound
movzx eax, word [edi+26] ; cluster
mov [esp+8], eax
mov dword [esp+4], flp_notroot_first
mov dword [esp], flp_notroot_next
jmp .loop
.notfound:
add esp, 12
pop edi esi
stc
ret
.found:
test ebp, ebp
jz @f
mov esi, ebp
xor ebp, ebp
jmp .continue
@@:
mov eax, [esp+8]
add eax, 31
cmp dword [esp], flp_root_next
jnz @f
add eax, -31+19
@@:
add esp, 16 ; CF=0
pop esi
ret
 
;----------------------------------------------------------------
;
; fs_FloppyRead - LFN variant for reading floppy
;
; esi points to filename
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to read, 0+
; edx mem location to return data
;
; ret ebx = bytes read or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
fs_FloppyRead:
call read_flp_fat
cmp byte [esi], 0
jnz @f
or ebx, -1
mov eax, 10 ; access denied
ret
@@:
push edi
call fd_find_lfn
jnc .found
pop edi
or ebx, -1
mov eax, 5 ; file not found
ret
.found:
test ebx, ebx
jz .l1
cmp dword [ebx+4], 0
jz @f
xor ebx, ebx
.reteof:
mov eax, 6 ; EOF
pop edi
ret
@@:
mov ebx, [ebx]
.l1:
push ecx edx
push 0
mov eax, [edi+28]
sub eax, ebx
jb .eof
cmp eax, ecx
jae @f
mov ecx, eax
mov byte [esp], 6 ; EOF
@@:
movzx edi, word [edi+26]
.new:
jecxz .done
test edi, edi
jz .eof
cmp edi, 0xFF8
jae .eof
sub ebx, 512
jae .skip
lea eax, [edi+31]
pusha
call read_chs_sector
popa
cmp [FDC_Status], 0
jnz .err
lea eax, [FDD_BUFF+ebx+512]
neg ebx
push ecx
cmp ecx, ebx
jbe @f
mov ecx, ebx
@@:
mov ebx, edx
call memmove
add edx, ecx
sub [esp], ecx
pop ecx
xor ebx, ebx
.skip:
movzx edi, word [edi*2+FLOPPY_FAT]
jmp .new
.done:
mov ebx, edx
pop eax edx ecx edi
sub ebx, edx
ret
.eof:
mov ebx, edx
pop eax edx ecx
jmp .reteof
.err:
mov ebx, edx
pop eax edx ecx edi
sub ebx, edx
mov al, 11
ret
 
;----------------------------------------------------------------
;
; fs_FloppyReadFolder - LFN variant for reading floppy folders
;
; esi points to filename
; ebx pointer to structure: 32-bit number = first wanted block, 0+
; & flags (bitfields)
; flags: bit 0: 0=ANSI names, 1=UNICODE names
; ecx number of blocks to read, 0+
; edx mem location to return data
;
; ret ebx = blocks read or 0xffffffff folder not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
fs_FloppyReadFolder:
call read_flp_fat
push edi
cmp byte [esi], 0
jz .root
call fd_find_lfn
jnc .found
pop edi
or ebx, -1
mov eax, ERROR_FILE_NOT_FOUND
ret
.found:
test byte [edi+11], 0x10 ; do not allow read files
jnz .found_dir
pop edi
or ebx, -1
mov eax, ERROR_ACCESS_DENIED
ret
.found_dir:
movzx eax, word [edi+26]
add eax, 31
push 0
jmp .doit
.root:
mov eax, 19
push 14
.doit:
push ecx ebp
sub esp, 262*2 ; reserve space for LFN
mov ebp, esp
push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE names
mov ebx, [ebx]
; init header
push eax ecx
mov edi, edx
mov ecx, 32/4
xor eax, eax
rep stosd
pop ecx eax
mov byte [edx], 1 ; version
mov esi, edi ; esi points to BDFE
.main_loop:
pusha
call read_chs_sector
popa
cmp [FDC_Status], 0
jnz .error
mov edi, FDD_BUFF
push eax
.l1:
call fat_get_name
jc .l2
cmp byte [edi+11], 0xF
jnz .do_bdfe
add edi, 0x20
cmp edi, OS_BASE+0xD200
jb .do_bdfe
pop eax
inc eax
dec byte [esp+262*2+12]
jz .done
jns @f
; read next sector from FAT
mov eax, [(eax-31-1)*2+FLOPPY_FAT]
and eax, 0xFFF
cmp eax, 0xFF8
jae .done
add eax, 31
mov byte [esp+262*2+12], 0
@@:
pusha
call read_chs_sector
popa
cmp [FDC_Status], 0
jnz .error
mov edi, FDD_BUFF
push eax
.do_bdfe:
inc dword [edx+8] ; new file found
dec ebx
jns .l2
dec ecx
js .l2
inc dword [edx+4] ; new file block copied
call fat_entry_to_bdfe
.l2:
add edi, 0x20
cmp edi, OS_BASE+0xD200
jb .l1
pop eax
inc eax
dec byte [esp+262*2+12]
jz .done
jns @f
; read next sector from FAT
mov eax, [(eax-31-1)*2+FLOPPY_FAT]
and eax, 0xFFF
cmp eax, 0xFF8
jae .done
add eax, 31
mov byte [esp+262*2+12], 0
@@:
jmp .main_loop
.error:
add esp, 262*2+4
pop ebp ecx edi edi
or ebx, -1
mov eax, ERROR_FILE_NOT_FOUND
ret
.done:
add esp, 262*2+4
pop ebp
mov ebx, [edx+4]
xor eax, eax
dec ecx
js @f
mov al, ERROR_END_OF_FILE
@@:
pop ecx edi edi
ret
 
;----------------------------------------------------------------
;
; fs_FloppyRewrite - LFN variant for writing sys floppy
;
; esi points to filename
; ebx ignored (reserved)
; ecx number of bytes to write, 0+
; edx mem location to data
;
; ret ebx = number of written bytes
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
@@:
mov eax, ERROR_ACCESS_DENIED
xor ebx, ebx
ret
fsfrfe2:
popad
fsfrfe:
mov eax, 11
xor ebx, ebx
ret
 
fs_FloppyCreateFolder:
mov al, 1
jmp fs_FloppyRewrite.common
 
fs_FloppyRewrite:
xor eax, eax
.common:
cmp byte [esi], 0
jz @b
call read_flp_fat
cmp [FDC_Status], 0
jnz fsfrfe
pushad
xor edi, edi
push esi
test ebp, ebp
jz @f
mov esi, ebp
@@:
lodsb
test al, al
jz @f
cmp al, '/'
jnz @b
lea edi, [esi-1]
jmp @b
@@:
pop esi
test edi, edi
jnz .noroot
test ebp, ebp
jnz .hasebp
call read_flp_root
cmp [FDC_Status], 0
jnz fsfrfe2
push flp_rootmem_extend_dir
push flp_rootmem_end_write
push flp_rootmem_next_write
push flp_rootmem_begin_write
xor ebp, ebp
push ebp
push flp_rootmem_first
push flp_rootmem_next
jmp .common1
.hasebp:
mov eax, ERROR_ACCESS_DENIED
cmp byte [ebp], 0
jz .ret1
push ebp
xor ebp, ebp
call fd_find_lfn
pop esi
jc .notfound0
jmp .common0
.noroot:
mov eax, ERROR_ACCESS_DENIED
cmp byte [edi+1], 0
jz .ret1
; check existence
mov byte [edi], 0
push edi
call fd_find_lfn
pop esi
mov byte [esi], '/'
jnc @f
.notfound0:
mov eax, ERROR_FILE_NOT_FOUND
.ret1:
mov [esp+28], eax
popad
xor ebx, ebx
ret
@@:
inc esi
.common0:
test byte [edi+11], 0x10 ; must be directory
mov eax, ERROR_ACCESS_DENIED
jz .ret1
movzx ebp, word [edi+26] ; ebp=cluster
mov eax, ERROR_FAT_TABLE
cmp ebp, 2
jb .ret1
cmp ebp, 2849
jae .ret1
push flp_notroot_extend_dir
push flp_notroot_end_write
push flp_notroot_next_write
push flp_notroot_begin_write
push ebp
push flp_notroot_first
push flp_notroot_next
.common1:
call fat_find_lfn
jc .notfound
; found
test byte [edi+11], 10h
jz .exists_file
; found directory; if we are creating directory, return OK,
; if we are creating file, say "access denied"
add esp, 28
popad
test al, al
mov eax, ERROR_ACCESS_DENIED
jz @f
mov al, 0
@@:
xor ebx, ebx
ret
.exists_file:
; found file; if we are creating directory, return "access denied",
; if we are creating file, delete existing file and continue
cmp byte [esp+28+28], 0
jz @f
add esp, 28
popad
mov eax, ERROR_ACCESS_DENIED
xor ebx, ebx
ret
@@:
; delete FAT chain
push edi
xor eax, eax
mov dword [edi+28], eax ; zero size
xchg ax, word [edi+26] ; start cluster
test eax, eax
jz .done1
@@:
cmp eax, 0xFF8
jae .done1
lea edi, [FLOPPY_FAT + eax*2] ; position in FAT
xor eax, eax
xchg ax, [edi]
jmp @b
.done1:
pop edi
call get_time_for_file
mov [edi+22], ax
call get_date_for_file
mov [edi+24], ax
mov [edi+18], ax
or byte [edi+11], 20h ; set 'archive' attribute
jmp .doit
.notfound:
; file is not found; generate short name
call fat_name_is_legal
jc @f
add esp, 28
popad
mov eax, ERROR_FILE_NOT_FOUND
xor ebx, ebx
ret
@@:
sub esp, 12
mov edi, esp
call fat_gen_short_name
.test_short_name_loop:
push esi edi ecx
mov esi, edi
lea eax, [esp+12+12+8]
mov [eax], ebp
call dword [eax-4]
jc .found
.test_short_name_entry:
cmp byte [edi+11], 0xF
jz .test_short_name_cont
mov ecx, 11
push esi edi
repz cmpsb
pop edi esi
jz .short_name_found
.test_short_name_cont:
lea eax, [esp+12+12+8]
call dword [eax-8]
jnc .test_short_name_entry
jmp .found
.short_name_found:
pop ecx edi esi
call fat_next_short_name
jnc .test_short_name_loop
.disk_full:
add esp, 12+28
popa
mov eax, ERROR_DISK_FULL
xor ebx, ebx
ret
.found:
pop ecx edi esi
; now find space in directory
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
mov al, '~'
push ecx edi
mov ecx, 8
repnz scasb
push 1
pop eax ; 1 entry
jnz .notilde
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
xor eax, eax
@@:
cmp byte [esi], 0
jz @f
inc esi
inc eax
jmp @b
@@:
sub esi, eax
add eax, 12+13
mov ecx, 13
push edx
cdq
div ecx
pop edx
.notilde:
push -1
push -1
; find <eax> successive entries in directory
xor ecx, ecx
push eax
lea eax, [esp+12+8+12+8]
mov [eax], ebp
call dword [eax-4]
pop eax
jnc .scan_dir
.fsfrfe3:
add esp, 8+8+12+28
popad
mov eax, 11
xor ebx, ebx
ret
.scan_dir:
cmp byte [edi], 0
jz .free
cmp byte [edi], 0xE5
jz .free
xor ecx, ecx
.scan_cont:
push eax
lea eax, [esp+12+8+12+8]
call dword [eax-8]
pop eax
jnc .scan_dir
cmp [FDC_Status], 0
jnz .fsfrfe3
push eax
lea eax, [esp+12+8+12+8]
call dword [eax+16] ; extend directory
pop eax
jnc .scan_dir
add esp, 8+8+12+28
popad
mov eax, ERROR_DISK_FULL
xor ebx, ebx
ret
.free:
test ecx, ecx
jnz @f
mov [esp], edi
mov ecx, [esp+8+8+12+8]
mov [esp+4], ecx
xor ecx, ecx
@@:
inc ecx
cmp ecx, eax
jb .scan_cont
; found!
; calculate name checksum
push esi ecx
mov esi, [esp+8+8]
mov ecx, 11
xor eax, eax
@@:
ror al, 1
add al, [esi]
inc esi
loop @b
pop ecx esi
pop edi
pop dword [esp+8+12+8]
; edi points to first entry in free chunk
dec ecx
jz .nolfn
push esi
push eax
lea eax, [esp+8+8+12+8]
call dword [eax+4] ; begin write
mov al, 40h
.writelfn:
or al, cl
mov esi, [esp+4]
push ecx
dec ecx
imul ecx, 13
add esi, ecx
stosb
mov cl, 5
call fs_RamdiskRewrite.read_symbols
mov ax, 0xF
stosw
mov al, [esp+4]
stosb
mov cl, 6
call fs_RamdiskRewrite.read_symbols
xor eax, eax
stosw
mov cl, 2
call fs_RamdiskRewrite.read_symbols
pop ecx
lea eax, [esp+8+8+12+8]
call dword [eax+8] ; next write
xor eax, eax
loop .writelfn
pop eax
pop esi
; lea eax, [esp+8+12+8]
; call dword [eax+12] ; end write
.nolfn:
xchg esi, [esp]
mov ecx, 11
rep movsb
mov word [edi], 20h ; attributes
sub edi, 11
pop esi ecx
add esp, 12
mov byte [edi+13], 0 ; tenths of a second at file creation time
call get_time_for_file
mov [edi+14], ax ; creation time
mov [edi+22], ax ; last write time
call get_date_for_file
mov [edi+16], ax ; creation date
mov [edi+24], ax ; last write date
mov [edi+18], ax ; last access date
and word [edi+20], 0 ; high word of cluster
and word [edi+26], 0 ; low word of cluster - to be filled
and dword [edi+28], 0 ; file size - to be filled
cmp byte [esp+28+28], 0
jz .doit
; create directory
mov byte [edi+11], 10h ; attributes: folder
mov ecx, 32*2
mov edx, edi
.doit:
lea eax, [esp+8]
call dword [eax+12] ; flush directory
push ecx
push edi
push 0
mov esi, edx
test ecx, ecx
jz .done
mov ecx, 2849
mov edi, FLOPPY_FAT
push 0 ; first cluster
.write_loop:
; allocate new cluster
xor eax, eax
repnz scasw
mov al, ERROR_DISK_FULL
jnz .ret
dec edi
dec edi
 
mov eax, edi
sub eax, FLOPPY_FAT
 
shr eax, 1 ; eax = cluster
mov word [edi], 0xFFF ; mark as last cluster
xchg edi, [esp+4]
cmp dword [esp], 0
jz .first
stosw
jmp @f
.first:
mov [esp], eax
@@:
mov edi, [esp+4]
inc ecx
; write data
push ecx edi
mov ecx, 512
cmp dword [esp+20], ecx
jae @f
mov ecx, [esp+20]
@@:
mov edi, FDD_BUFF
cmp byte [esp+24+28+28], 0
jnz .writedir
push ecx
rep movsb
pop ecx
.writedircont:
push ecx
sub ecx, 512
neg ecx
push eax
xor eax, eax
rep stosb
pop eax
add eax, 31
pusha
call save_chs_sector
popa
pop ecx
cmp [FDC_Status], 0
jnz .diskerr
sub [esp+20], ecx
pop edi ecx
jnz .write_loop
.done:
xor eax, eax
.ret:
pop ebx edi edi ecx
mov [esp+28+28], eax
lea eax, [esp+8]
call dword [eax+4]
mov [edi+26], bx
mov ebx, esi
sub ebx, edx
mov [edi+28], ebx
call dword [eax+12]
mov [esp+28+16], ebx
test ebp, ebp
jnz @f
call save_flp_root
@@:
add esp, 28
cmp [FDC_Status], 0
jnz .err3
call save_flp_fat
cmp [FDC_Status], 0
jnz .err3
popa
ret
.err3:
popa
mov al, 11
xor ebx, ebx
ret
.diskerr:
sub esi, ecx
mov eax, 11
pop edi ecx
jmp .ret
.writedir:
push ecx
mov ecx, 32/4
push ecx esi
rep movsd
pop esi ecx
mov dword [edi-32], '. '
mov dword [edi-32+4], ' '
mov dword [edi-32+8], ' '
mov byte [edi-32+11], 10h
mov word [edi-32+26], ax
push esi
rep movsd
pop esi
mov dword [edi-32], '.. '
mov dword [edi-32+4], ' '
mov dword [edi-32+8], ' '
mov byte [edi-32+11], 10h
mov ecx, [esp+28+8]
mov word [edi-32+26], cx
pop ecx
jmp .writedircont
 
;----------------------------------------------------------------
;
; fs_FloppyWrite - LFN variant for writing to floppy
;
; esi points to filename
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to write, 0+
; edx mem location to data
;
; ret ebx = bytes written (maybe 0)
; eax = 0 ok write or other = errormsg
;
;--------------------------------------------------------------
 
@@:
push ERROR_ACCESS_DENIED
fs_FloppyWrite.ret0:
pop eax
xor ebx, ebx
ret
 
fs_FloppyWrite.ret11:
push 11
jmp fs_FloppyWrite.ret0
 
fs_FloppyWrite:
cmp byte [esi], 0
jz @b
call read_flp_fat
cmp [FDC_Status], 0
jnz .ret11
pushad
call fd_find_lfn
jnc .found
popad
push ERROR_FILE_NOT_FOUND
jmp .ret0
.found:
; FAT does not support files larger than 4GB
test ebx, ebx
jz .l1
cmp dword [ebx+4], 0
jz @f
.eof:
popad
push ERROR_END_OF_FILE
jmp .ret0
@@:
mov ebx, [ebx]
.l1:
; now edi points to direntry, ebx=start byte to write,
; ecx=number of bytes to write, edx=data pointer
 
; extend file if needed
add ecx, ebx
jc .eof ; FAT does not support files larger than 4GB
push eax ; save directory cluster
push 0 ; return value=0
 
call get_time_for_file
mov [edi+22], ax ; last write time
call get_date_for_file
mov [edi+24], ax ; last write date
mov [edi+18], ax ; last access date
 
push dword [edi+28] ; save current file size
cmp ecx, [edi+28]
jbe .length_ok
cmp ecx, ebx
jz .length_ok
call floppy_extend_file
jnc .length_ok
mov [esp+4], eax
; floppy_extend_file can return two error codes: FAT table error or disk full.
; First case is fatal error, in second case we may write some data
cmp al, ERROR_DISK_FULL
jz .disk_full
pop eax
pop eax
mov [esp+4+28], eax
pop eax
popad
xor ebx, ebx
ret
.disk_full:
; correct number of bytes to write
mov ecx, [edi+28]
cmp ecx, ebx
ja .length_ok
.ret:
pop eax
pop eax
mov [esp+4+28], eax ; eax=return value
pop eax
sub edx, [esp+20]
mov [esp+16], edx ; ebx=number of written bytes
popad
ret
.length_ok:
; save FAT & directory
; note that directory must be saved first because save_flp_fat uses buffer at 0xD000
mov esi, [edi+28]
movzx edi, word [edi+26] ; starting cluster
mov eax, [esp+8]
pusha
call save_chs_sector
popa
cmp [FDC_Status], 0
jnz .device_err
call save_flp_fat
cmp [FDC_Status], 0
jz @f
.device_err:
mov byte [esp+4], 11
jmp .ret
@@:
 
; now ebx=start pos, ecx=end pos, both lie inside file
sub ecx, ebx
jz .ret
call SetUserInterrupts
.write_loop:
; skip unmodified sectors
cmp dword [esp], 0x200
jb .modify
sub ebx, 0x200
jae .skip
add ebx, 0x200
.modify:
lea eax, [edi+31] ; current sector
; get length of data in current sector
push ecx
sub ebx, 0x200
jb .hasdata
neg ebx
xor ecx, ecx
jmp @f
.hasdata:
neg ebx
cmp ecx, ebx
jbe @f
mov ecx, ebx
@@:
; load sector if needed
cmp dword [esp+4], 0 ; we don't need to read uninitialized data
jz .noread
cmp ecx, 0x200 ; we don't need to read sector if it is fully rewritten
jz .noread
cmp ecx, esi ; (same for the last sector)
jz .noread
pusha
call read_chs_sector
popa
cmp [FDC_Status], 0
jz @f
.device_err2:
pop ecx
jmp .device_err
@@:
.noread:
; zero uninitialized data if file was extended (because floppy_extend_file does not this)
push eax ecx edi
xor eax, eax
mov ecx, 0x200
sub ecx, [esp+4+12]
jbe @f
mov edi, FDD_BUFF
add edi, [esp+4+12]
rep stosb
@@:
; zero uninitialized data in the last sector
mov ecx, 0x200
sub ecx, esi
jbe @f
mov edi, FDD_BUFF
add edi, esi
rep stosb
@@:
pop edi ecx eax
; copy new data
push eax
mov eax, edx
neg ebx
jecxz @f
add ebx, FDD_BUFF+0x200
call memmove
xor ebx, ebx
@@:
pop eax
; save sector
pusha
call save_chs_sector
popa
cmp [FDC_Status], 0
jnz .device_err2
add edx, ecx
sub [esp], ecx
pop ecx
jz .done
.skip:
.next_cluster:
movzx edi, word [edi*2+FLOPPY_FAT]
sub esi, 0x200
jae @f
xor esi, esi
@@:
sub dword [esp], 0x200
jae .write_loop
and dword [esp], 0
jmp .write_loop
.done:
mov [fdc_irq_func], fdc_null
jmp .ret
 
floppy_extend_file.zero_size:
xor eax, eax
jmp floppy_extend_file.start_extend
 
; extends file on floppy to given size (new data area is undefined)
; in: edi->direntry, ecx=new size
; out: CF=0 => OK, eax=0
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL)
floppy_extend_file:
push ecx
; find the last cluster of file
movzx eax, word [edi+26] ; first cluster
mov ecx, [edi+28]
jecxz .zero_size
@@:
sub ecx, 0x200
jbe @f
mov eax, [eax*2+FLOPPY_FAT]
and eax, 0xFFF
jz .fat_err
cmp eax, 0xFF8
jb @b
.fat_err:
pop ecx
push ERROR_FAT_TABLE
pop eax
stc
ret
@@:
push eax
mov eax, [eax*2+FLOPPY_FAT]
and eax, 0xFFF
cmp eax, 0xFF8
pop eax
jb .fat_err
; set length to full number of sectors
sub [edi+28], ecx
.start_extend:
pop ecx
; now do extend
push edx esi
mov esi, FLOPPY_FAT+2*2 ; start scan from cluster 2
mov edx, 2847 ; number of clusters to scan
.extend_loop:
cmp [edi+28], ecx
jae .extend_done
; add new sector
push ecx
push edi
.scan:
mov ecx, edx
mov edi, esi
jecxz .disk_full
push eax
xor eax, eax
repnz scasw
pop eax
jnz .disk_full
mov word [edi-2], 0xFFF
mov esi, edi
mov edx, ecx
sub edi, FLOPPY_FAT
shr edi, 1
dec edi ; now edi=new cluster
test eax, eax
jz .first_cluster
mov [FLOPPY_FAT+eax*2], di
jmp @f
.first_cluster:
pop eax ; eax->direntry
push eax
mov [eax+26], di
@@:
mov eax, edi ; eax=new cluster
pop edi ; edi->direntry
pop ecx ; ecx=required size
add dword [edi+28], 0x200
jmp .extend_loop
.extend_done:
mov [edi+28], ecx
pop esi edx
xor eax, eax ; CF=0
ret
.disk_full:
pop edi ecx
pop esi edx
stc
push ERROR_DISK_FULL
pop eax
ret
 
;----------------------------------------------------------------
;
; fs_FloppySetFileEnd - set end of file on floppy
;
; esi points to filename
; ebx points to 64-bit number = new file size
; ecx ignored (reserved)
; edx ignored (reserved)
;
; ret eax = 0 ok or other = errormsg
;
;--------------------------------------------------------------
fs_FloppySetFileEnd:
call read_flp_fat
cmp [FDC_Status], 0
jnz ret11
cmp byte [esi], 0
jnz @f
.access_denied:
push ERROR_ACCESS_DENIED
jmp .ret
@@:
push edi
call fd_find_lfn
jnc @f
pop edi
push ERROR_FILE_NOT_FOUND
.ret:
pop eax
jmp .doret
@@:
; must not be directory
test byte [edi+11], 10h
jz @f
pop edi
jmp .access_denied
@@:
; file size must not exceed 4 Gb
cmp dword [ebx+4], 0
jz @f
pop edi
push ERROR_END_OF_FILE
jmp .ret
@@:
push eax
; set file modification date/time to current
call fat_update_datetime
mov eax, [ebx]
cmp eax, [edi+28]
jb .truncate
ja .expand
pop eax
pushad
call save_chs_sector
popad
pop edi
xor eax, eax
cmp [FDC_Status], 0
jz @f
mov al, 11
@@:
.doret:
mov [fdc_irq_func], fdc_null
ret
.expand:
push ecx
push dword [edi+28] ; save old size
mov ecx, eax
call floppy_extend_file
push eax ; return code
jnc .expand_ok
cmp al, ERROR_DISK_FULL
jz .disk_full
pop eax ecx ecx edi edi
jmp .doret
.device_err:
pop eax
.device_err2:
pop ecx ecx eax edi
push 11
jmp .ret
.disk_full:
.expand_ok:
; save directory & FAT
mov eax, [edi+28]
xchg eax, [esp+12]
movzx edi, word [edi+26]
pusha
call save_chs_sector
popa
cmp [FDC_Status], 0
jnz .device_err
call save_flp_fat
cmp [FDC_Status], 0
jnz .device_err
call SetUserInterrupts
; now zero new data
; edi = current cluster, [esp+12]=new size, [esp+4]=old size, [esp]=return code
.zero_loop:
sub dword [esp+4], 0x200
jae .next_cluster
cmp dword [esp+4], -0x200
jz .noread
lea eax, [edi+31]
pusha
call read_chs_sector
popa
cmp [FDC_Status], 0
jnz .err_next
.noread:
mov ecx, [esp+4]
neg ecx
push edi
mov edi, FDD_BUFF+0x200
add edi, [esp+8]
xor eax, eax
mov [esp+8], eax
rep stosb
pop edi
lea eax, [edi+31]
pusha
call save_chs_sector
popa
cmp [FDC_Status], 0
jz .next_cluster
.err_next:
mov byte [esp], 11
.next_cluster:
sub dword [esp+12], 0x200
jbe .expand_done
movzx edi, word [FLOPPY_FAT+edi*2]
jmp .zero_loop
.expand_done:
pop eax ecx ecx edi edi
jmp .doret
.truncate:
mov [edi+28], eax
push ecx
movzx ecx, word [edi+26]
test eax, eax
jz .zero_size
; find new last sector
@@:
sub eax, 0x200
jbe @f
movzx ecx, word [FLOPPY_FAT+ecx*2]
jmp @b
@@:
; we will zero data at the end of last sector - remember it
push ecx
; terminate FAT chain
lea ecx, [FLOPPY_FAT+ecx+ecx]
push dword [ecx]
mov word [ecx], 0xFFF
pop ecx
and ecx, 0xFFF
jmp .delete
.zero_size:
and word [edi+26], 0
push 0
.delete:
; delete FAT chain starting with ecx
; mark all clusters as free
cmp ecx, 0xFF8
jae .deleted
lea ecx, [FLOPPY_FAT+ecx+ecx]
push dword [ecx]
and word [ecx], 0
pop ecx
and ecx, 0xFFF
jmp .delete
.deleted:
mov edi, [edi+28]
; save directory & FAT
mov eax, [esp+8]
pusha
call save_chs_sector
popa
cmp [FDC_Status], 0
jnz .device_err2
call save_flp_fat
cmp [FDC_Status], 0
jnz .device_err2
; zero last sector, ignore errors
pop eax
add eax, 31
and edi, 0x1FF
jz .truncate_done
call SetUserInterrupts
pusha
call read_chs_sector
popa
add edi, FDD_BUFF
mov ecx, FDD_BUFF+0x200
sub ecx, edi
push eax
xor eax, eax
rep stosb
pop eax
pusha
call save_chs_sector
popa
.truncate_done:
pop ecx eax edi
xor eax, eax
jmp .doret
 
fs_FloppyGetFileInfo:
call read_flp_fat
cmp [FDC_Status], 0
jnz ret11
cmp byte [esi], 0
jnz @f
mov eax, 2 ; unsupported
ret
@@:
push edi
call fd_find_lfn
jmp fs_GetFileInfo_finish
 
ret11:
mov eax, 11
ret
 
fs_FloppySetFileInfo:
call read_flp_fat
cmp [FDC_Status], 0
jnz ret11
cmp byte [esi], 0
jnz @f
mov eax, 2 ; unsupported
ret
@@:
push edi
call fd_find_lfn
jnc @f
pop edi
mov eax, ERROR_FILE_NOT_FOUND
ret
@@:
push eax
call bdfe_to_fat_entry
pop eax
pusha
call save_chs_sector
popa
pop edi
xor eax, eax
cmp [FDC_Status], al
jz @f
mov al, 11
@@:
ret
 
;----------------------------------------------------------------
;
; fs_FloppyDelete - delete file or empty folder from floppy
;
; esi points to filename
;
; ret eax = 0 ok or other = errormsg
;
;--------------------------------------------------------------
fs_FloppyDelete:
call read_flp_fat
cmp [FDC_Status], 0
jz @f
push 11
jmp .pop_ret
@@:
cmp byte [esi], 0
jnz @f
; cannot delete root!
.access_denied:
push ERROR_ACCESS_DENIED
.pop_ret:
pop eax
ret
@@:
and [fd_prev_sector], 0
and [fd_prev_prev_sector], 0
push edi
call fd_find_lfn
jnc .found
pop edi
push ERROR_FILE_NOT_FOUND
jmp .pop_ret
.found:
cmp dword [edi], '. '
jz .access_denied2
cmp dword [edi], '.. '
jz .access_denied2
test byte [edi+11], 10h
jz .dodel
; we can delete only empty folders!
push eax
movzx eax, word [edi+26]
push ebx
pusha
add eax, 31
call read_chs_sector
popa
mov ebx, FDD_BUFF + 2*0x20
.checkempty:
cmp byte [ebx], 0
jz .empty
cmp byte [ebx], 0xE5
jnz .notempty
add ebx, 0x20
cmp ebx, FDD_BUFF + 0x200
jb .checkempty
movzx eax, word [FLOPPY_FAT + eax*2]
pusha
add eax, 31
call read_chs_sector
popa
mov ebx, FDD_BUFF
jmp .checkempty
.notempty:
pop ebx
pop eax
.access_denied2:
pop edi
jmp .access_denied
.empty:
pop ebx
pop eax
pusha
call read_chs_sector
popa
.dodel:
push eax
movzx eax, word [edi+26]
xchg eax, [esp]
; delete folder entry
mov byte [edi], 0xE5
; delete LFN (if present)
.lfndel:
cmp edi, FDD_BUFF
ja @f
cmp [fd_prev_sector], 0
jz .lfndone
push [fd_prev_sector]
push [fd_prev_prev_sector]
pop [fd_prev_sector]
and [fd_prev_prev_sector], 0
pusha
call save_chs_sector
popa
pop eax
pusha
call read_chs_sector
popa
mov edi, FDD_BUFF+0x200
@@:
sub edi, 0x20
cmp byte [edi], 0xE5
jz .lfndone
cmp byte [edi+11], 0xF
jnz .lfndone
mov byte [edi], 0xE5
jmp .lfndel
.lfndone:
pusha
call save_chs_sector
popa
; delete FAT chain
pop eax
test eax, eax
jz .done
@@:
lea eax, [FLOPPY_FAT + eax*2]
push dword [eax]
and word [eax], 0
pop eax
and eax, 0xFFF
jnz @b
.done:
call save_flp_fat
pop edi
xor eax, eax
ret
 
; \end{diamond}
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/fs/fat32.inc
0,0 → 1,2943
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; FAT32.INC ;;
;; ;;
;; FAT16/32 functions for KolibriOS ;;
;; ;;
;; Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it ;;
;; ;;
;; See file COPYING for details ;;
;; 04.02.2007 LFN create folder - diamond ;;
;; 08.10.2006 LFN delete file/folder - diamond ;;
;; 20.08.2006 LFN set file size (truncate/extend) - diamond ;;
;; 17.08.2006 LFN write/append to file - diamond ;;
;; 23.06.2006 LFN start application - diamond ;;
;; 15.06.2006 LFN get/set file/folder info - diamond ;;
;; 27.05.2006 LFN create/rewrite file - diamond ;;
;; 04.05.2006 LFN read folder - diamond ;;
;; 29.04.2006 Elimination of hangup after the ;;
;; expiration hd_wait_timeout - Mario79 ;;
;; 23.04.2006 LFN read file - diamond ;;
;; 28.01.2006 find all Fat16/32 partition in all input point ;;
;; to MBR, see file part_set.inc - Mario79 ;;
;; 15.01.2005 get file size/attr/date, file_append - ATV ;;
;; 04.12.2004 skip volume label, file delete bug fixed - ATV ;;
;; 29.11.2004 get_free_FAT changed, append dir bug fixed - ATV ;;
;; 23.11.2004 don't allow overwrite dir with file - ATV ;;
;; 18.11.2004 get_disk_info and more error codes - ATV ;;
;; 17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV ;;
;; 10.11.2004 removedir clear whole directory structure - ATV ;;
;; 08.11.2004 rename - ATV ;;
;; 30.10.2004 file_read return also dirsize in bytes - ATV ;;
;; 20.10.2004 Makedir/Removedir - ATV ;;
;; 14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx) ;;
;; 06.9.2004 Fix free space by Mario79 added - MH ;;
;; 24.5.2004 Write back buffer for File_write -VT ;;
;; 20.5.2004 File_read function to work with syscall 58 - VT ;;
;; 30.3.2004 Error parameters at function return - VT ;;
;; 01.5.2002 Bugfix in device write - VT ;;
;; 20.5.2002 Hd status check - VT ;;
;; 29.6.2002 Improved fat32 verification - VT ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
cache_max equ 1919 ; max. is 1919*512+0x610000=0x6ffe00
 
PUSHAD_EAX equ [esp+28]
PUSHAD_ECX equ [esp+24]
PUSHAD_EDX equ [esp+20]
PUSHAD_EBX equ [esp+16]
PUSHAD_EBP equ [esp+8]
PUSHAD_ESI equ [esp+4]
PUSHAD_EDI equ [esp+0]
 
; Internal data for every FAT partition.
struct FAT
p PARTITION ; must be the first item
fs_type db ?
fat16_root db 0 ; flag for fat16 rootdir
fat_change db 0 ; 1=fat has changed
db ? ; alignment
Lock MUTEX ? ; currently operations with one partition
; can not be executed in parallel since the
; legacy code is not ready; this mutex guards
; all operations
SECTORS_PER_FAT dd 0x1f3a
NUMBER_OF_FATS dd 0x2
SECTORS_PER_CLUSTER dd 0x8
BYTES_PER_SECTOR dd 0x200 ; Note: if BPS <> 512 need lots of changes
ROOT_CLUSTER dd 2 ; first rootdir cluster
FAT_START dd 0 ; start of fat table
ROOT_START dd 0 ; start of rootdir (only fat16)
ROOT_SECTORS dd 0 ; count of rootdir sectors (only fat16)
DATA_START dd 0 ; start of data area (=first cluster 2)
LAST_CLUSTER dd 0 ; last availabe cluster
ADR_FSINFO dd 0 ; used only by fat32
 
fatRESERVED dd 0x0FFFFFF6
fatBAD dd 0x0FFFFFF7
fatEND dd 0x0FFFFFF8
fatMASK dd 0x0FFFFFFF
 
fatStartScan dd 2
 
cluster_tmp dd 0 ; used by analyze_directory
; and analyze_directory_to_write
 
longname_sec1 dd 0 ; used by analyze_directory to save 2 previous
longname_sec2 dd 0 ; directory sectors for delete long filename
 
fat_in_cache dd -1
 
fat_cache rb 512
buffer rb 512
fsinfo_buffer rb 512
ends
 
uglobal
align 4
partition_count dd 0 ; partitions found by set_FAT32_variables
 
hd_error dd 0 ; set by wait_for_sector_buffer
hd_setup dd 0
hd_wait_timeout dd 0
 
cache_search_start dd 0 ; used by find_empty_slot
endg
 
uglobal
align 4
Sector512: ; label for dev_hdcd.inc
buffer:
times 512 db 0
endg
 
iglobal
align 4
fat_user_functions:
dd (fat_user_functions_end - fat_user_functions - 4) / 4
dd fat_Read
dd fat_ReadFolder
dd fat_Rewrite
dd fat_Write
dd fat_SetFileEnd
dd fat_GetFileInfo
dd fat_SetFileInfo
dd 0
dd fat_Delete
dd fat_CreateFolder
fat_user_functions_end:
endg
 
; these labels are located before the main function to make
; most of jumps to these be short
fat_create_partition.free_return0:
push ebx
mov eax, ebp
call free
pop ebx
pop ebp
fat_create_partition.return0:
xor eax, eax
ret
fat_create_partition:
; bootsector must have been successfully read
cmp dword [esp+4], 1
jnz .return0
; bootsector signature must be correct
cmp word [ebx+0x1fe], 0xaa55
jnz .return0
; sectors per cluster must be nonzero
cmp byte [ebx+0xd], 0
jz .return0
; bytes per sector must be 0x200
cmp word [ebx+0xb], 0x200
jnz .return0
; number of fats must be nonzero
cmp byte [ebx+0x10], 0
jz .return0
; The only reason to be invalid partition now is FAT12. Since the test for
; FAT size requires knowledge of some calculated values, which are also used
; in the normal operation, let's hope for the best and allocate data now; if
; it will prove wrong, just deallocate it.
push ebx
push sizeof.FAT
pop eax
call malloc
pop ebx
test eax, eax
jz .return0
mov ecx, [ebp+8]
mov dword [eax+FAT.p.FirstSector], ecx
mov ecx, [ebp+12]
mov dword [eax+FAT.p.FirstSector+4], ecx
mov ecx, [ebp+16]
mov dword [eax+FAT.p.Length], ecx
mov ecx, [ebp+20]
mov dword [eax+FAT.p.Length+4], ecx
mov [eax+FAT.p.Disk], esi
mov [eax+FAT.p.FSUserFunctions], fat_user_functions
or [eax+FAT.fat_in_cache], -1
mov [eax+FAT.fat_change], 0
push ebp
mov ebp, eax
 
lea ecx, [ebp+FAT.Lock]
call mutex_init
 
movzx eax, word [ebx+0xe] ; sectors reserved
mov [ebp+FAT.FAT_START], eax
 
movzx eax, byte [ebx+0xd] ; sectors per cluster
mov [ebp+FAT.SECTORS_PER_CLUSTER], eax
 
movzx ecx, word [ebx+0xb] ; bytes per sector
mov [ebp+FAT.BYTES_PER_SECTOR], ecx
 
movzx eax, word [ebx+0x11] ; count of rootdir entries (=0 fat32)
shl eax, 5 ; mul 32
dec ecx
add eax, ecx ; round up if not equal count
inc ecx ; bytes per sector
xor edx, edx
div ecx
mov [ebp+FAT.ROOT_SECTORS], eax ; count of rootdir sectors
 
movzx eax, word [ebx+0x16] ; sectors per fat <65536
test eax, eax
jnz @f
mov eax, [ebx+0x24] ; sectors per fat
@@:
mov [ebp+FAT.SECTORS_PER_FAT], eax
 
movzx eax, byte [ebx+0x10] ; number of fats
mov [ebp+FAT.NUMBER_OF_FATS], eax
imul eax, [ebp+FAT.SECTORS_PER_FAT]
add eax, [ebp+FAT.FAT_START]
mov [ebp+FAT.ROOT_START], eax ; rootdir = fat_start + fat_size * fat_count
add eax, [ebp+FAT.ROOT_SECTORS] ; rootdir sectors should be 0 on fat32
mov [ebp+FAT.DATA_START], eax ; data area = rootdir + rootdir_size
 
movzx eax, word [ebx+0x13] ; total sector count <65536
test eax, eax
jnz @f
mov eax, [ebx+0x20] ; total sector count
@@:
mov dword [ebp+FAT.p.Length], eax
and dword [ebp+FAT.p.Length+4], 0
sub eax, [ebp+FAT.DATA_START] ; eax = count of data sectors
xor edx, edx
div [ebp+FAT.SECTORS_PER_CLUSTER]
inc eax
mov [ebp+FAT.LAST_CLUSTER], eax
dec eax ; cluster count
mov [ebp+FAT.fatStartScan], 2
 
; limits by Microsoft Hardware White Paper v1.03
cmp eax, 4085 ; 0xff5
jb .free_return0 ; fat12 not supported
cmp eax, 65525 ; 0xfff5
jb .fat16
.fat32:
mov eax, [ebx+0x2c] ; rootdir cluster
mov [ebp+FAT.ROOT_CLUSTER], eax
movzx eax, word [ebx+0x30]
mov [ebp+FAT.ADR_FSINFO], eax
push ebx
add ebx, 512
call fs_read32_sys
test eax, eax
jnz @f
mov eax, [ebx+0x1ec]
cmp eax, -1
jz @f
mov [ebp+FAT.fatStartScan], eax
@@:
pop ebx
mov [ebp+FAT.fatRESERVED], 0x0FFFFFF6
mov [ebp+FAT.fatBAD], 0x0FFFFFF7
mov [ebp+FAT.fatEND], 0x0FFFFFF8
mov [ebp+FAT.fatMASK], 0x0FFFFFFF
mov al, 32
mov [fs_type], al
mov [ebp+FAT.fs_type], al
mov eax, ebp
pop ebp
ret
.fat16:
and [ebp+FAT.ROOT_CLUSTER], 0
mov [ebp+FAT.fatRESERVED], 0x0000FFF6
mov [ebp+FAT.fatBAD], 0x0000FFF7
mov [ebp+FAT.fatEND], 0x0000FFF8
mov [ebp+FAT.fatMASK], 0x0000FFFF
mov al, 16
mov [fs_type], al
mov [ebp+FAT.fs_type], al
mov eax, ebp
pop ebp
ret
 
set_FAT:
;--------------------------------
; input : EAX = cluster
; EDX = value to save
; EBP = pointer to FAT structure
; output : EDX = old value
;--------------------------------
; out: CF set <=> error
push eax ebx esi
 
cmp eax, 2
jb sfc_error
cmp eax, [ebp+FAT.LAST_CLUSTER]
ja sfc_error
cmp [ebp+FAT.fs_type], 16
je sfc_1
add eax, eax
sfc_1:
add eax, eax
mov esi, 511
and esi, eax ; esi = position in fat sector
shr eax, 9 ; eax = fat sector
add eax, [ebp+FAT.FAT_START]
lea ebx, [ebp+FAT.fat_cache]
 
cmp eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
je sfc_in_cache ; yes
 
cmp [ebp+FAT.fat_change], 0; is fat changed?
je sfc_no_change ; no
call write_fat_sector; yes. write it into disk
jc sfc_error
 
sfc_no_change:
mov [ebp+FAT.fat_in_cache], eax; save fat sector
call fs_read32_sys
test eax, eax
jne sfc_error
 
 
sfc_in_cache:
cmp [ebp+FAT.fs_type], 16
jne sfc_test32
 
sfc_set16:
xchg [ebx+esi], dx ; save new value and get old value
jmp sfc_write
 
sfc_test32:
mov eax, [ebp+FAT.fatMASK]
 
sfc_set32:
and edx, eax
xor eax, -1 ; mask for high bits
and eax, [ebx+esi] ; get high 4 bits
or eax, edx
mov edx, [ebx+esi] ; get old value
mov [ebx+esi], eax ; save new value
 
sfc_write:
mov [ebp+FAT.fat_change], 1; fat has changed
 
sfc_nonzero:
and edx, [ebp+FAT.fatMASK]
 
sfc_return:
pop esi ebx eax
ret
sfc_error:
stc
jmp sfc_return
 
 
get_FAT:
;--------------------------------
; input : EAX = cluster
; EBP = pointer to FAT structure
; output : EAX = next cluster
;--------------------------------
; out: CF set <=> error
push ebx esi
 
cmp [ebp+FAT.fs_type], 16
je gfc_1
add eax, eax
gfc_1:
add eax, eax
mov esi, 511
and esi, eax ; esi = position in fat sector
shr eax, 9 ; eax = fat sector
add eax, [ebp+FAT.FAT_START]
lea ebx, [ebp+FAT.fat_cache]
 
cmp eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
je gfc_in_cache
 
cmp [ebp+FAT.fat_change], 0; is fat changed?
je gfc_no_change ; no
call write_fat_sector; yes. write it into disk
jc hd_error_01
 
gfc_no_change:
mov [ebp+FAT.fat_in_cache], eax
call fs_read32_sys
test eax, eax
jne hd_error_01
 
gfc_in_cache:
mov eax, [ebx+esi]
and eax, [ebp+FAT.fatMASK]
gfc_return:
pop esi ebx
ret
hd_error_01:
stc
jmp gfc_return
 
 
get_free_FAT:
;-----------------------------------------------------------
; output : if CARRY=0 EAX = # first cluster found free
; if CARRY=1 disk full
; Note : for more speed need to use fat_cache directly
;-----------------------------------------------------------
push ecx
mov ecx, [ebp+FAT.LAST_CLUSTER]; counter for full disk
sub ecx, 2
mov eax, [ebp+FAT.fatStartScan]
cmp eax, 2
jb gff_reset
 
gff_test:
cmp eax, [ebp+FAT.LAST_CLUSTER]; if above last cluster start at cluster 2
jbe gff_in_range
gff_reset:
mov eax, 2
 
gff_in_range:
push eax
call get_FAT ; get cluster state
jc gff_not_found_1
 
test eax, eax ; is it free?
pop eax
je gff_found ; yes
inc eax ; next cluster
dec ecx ; is all checked?
jns gff_test ; no
 
gff_not_found:
pop ecx ; yes. disk is full
stc
ret
 
gff_not_found_1:
pop eax
jmp gff_not_found
 
gff_found:
lea ecx, [eax+1]
mov [ebp+FAT.fatStartScan], ecx
pop ecx
clc
ret
 
 
write_fat_sector:
;-----------------------------------------------------------
; write changed fat to disk
;-----------------------------------------------------------
push eax ebx ecx
 
mov [ebp+FAT.fat_change], 0
mov eax, [ebp+FAT.fat_in_cache]
cmp eax, -1
jz write_fat_not_used
lea ebx, [ebp+FAT.fat_cache]
mov ecx, [ebp+FAT.NUMBER_OF_FATS]
 
write_next_fat:
push eax
call fs_write32_sys
test eax, eax
pop eax
jnz write_fat_not_used
 
add eax, [ebp+FAT.SECTORS_PER_FAT]
dec ecx
jnz write_next_fat
 
write_fat_not_used:
pop ecx ebx eax
ret
 
 
 
 
 
bcd2bin:
;----------------------------------
; input : AL=BCD number (eg. 0x11)
; output : AH=0
; AL=decimal number (eg. 11)
;----------------------------------
xor ah, ah
shl ax, 4
shr al, 4
aad
ret
 
 
get_date_for_file:
;-----------------------------------------------------
; Get date from CMOS and pack day,month,year in AX
; DATE bits 0..4 : day of month 0..31
; 5..8 : month of year 1..12
; 9..15 : count of years from 1980
;-----------------------------------------------------
mov al, 0x7 ;day
out 0x70, al
in al, 0x71
call bcd2bin
ror eax, 5
 
mov al, 0x8 ;month
out 0x70, al
in al, 0x71
call bcd2bin
ror eax, 4
 
mov al, 0x9 ;year
out 0x70, al
in al, 0x71
call bcd2bin
add ax, 20 ;because CMOS return only the two last
;digit (eg. 2000 -> 00 , 2001 -> 01) and we
rol eax, 9 ;need the difference with 1980 (eg. 2001-1980)
ret
 
 
get_time_for_file:
;-----------------------------------------------------
; Get time from CMOS and pack hour,minute,second in AX
; TIME bits 0..4 : second (the low bit is lost)
; 5..10 : minute 0..59
; 11..15 : hour 0..23
;-----------------------------------------------------
mov al, 0x0 ;second
out 0x70, al
in al, 0x71
call bcd2bin
ror eax, 6
 
mov al, 0x2 ;minute
out 0x70, al
in al, 0x71
call bcd2bin
ror eax, 6
 
mov al, 0x4 ;hour
out 0x70, al
in al, 0x71
call bcd2bin
rol eax, 11
ret
 
 
set_current_time_for_entry:
;-----------------------------------------------------
; Set current time/date for file entry
; input : ebx = file entry pointer
;-----------------------------------------------------
push eax
call get_time_for_file; update files date/time
mov [ebx+22], ax
call get_date_for_file
mov [ebx+24], ax
pop eax
ret
 
 
 
add_disk_free_space:
;-----------------------------------------------------
; input : ecx = cluster count
; Note : negative = remove clusters from free space
; positive = add clusters to free space
;-----------------------------------------------------
test ecx, ecx ; no change
je add_dfs_no
cmp [ebp+FAT.fs_type], 32 ; free disk space only used by fat32
jne add_dfs_no
 
push eax ebx
mov eax, [ebp+FAT.ADR_FSINFO]
lea ebx, [ebp+FAT.fsinfo_buffer]
call fs_read32_sys
test eax, eax
jnz add_not_fs
 
cmp dword [ebx+0x1fc], 0xaa550000; check sector id
jne add_not_fs
 
add [ebx+0x1e8], ecx
push [ebp+FAT.fatStartScan]
pop dword [ebx+0x1ec]
mov eax, [ebp+FAT.ADR_FSINFO]
call fs_write32_sys
; jc add_not_fs
 
add_not_fs:
pop ebx eax
 
add_dfs_no:
ret
 
 
 
clear_cluster_chain:
;-----------------------------------------------------
; input : eax = first cluster
;-----------------------------------------------------
push eax ecx edx
xor ecx, ecx ; cluster count
 
clean_new_chain:
cmp eax, [ebp+FAT.LAST_CLUSTER]; end of file
ja delete_OK
cmp eax, 2 ; unfinished fat chain or zero length file
jb delete_OK
cmp eax, [ebp+FAT.ROOT_CLUSTER]; don't remove root cluster
jz delete_OK
 
xor edx, edx
call set_FAT ; clear fat entry
jc access_denied_01
 
inc ecx ; update cluster count
mov eax, edx ; old cluster
jmp clean_new_chain
 
delete_OK:
call add_disk_free_space; add clusters to free disk space
clc
access_denied_01:
pop edx ecx eax
ret
 
 
if 0
get_hd_info:
;-----------------------------------------------------------
; output : eax = 0 - ok
; 3 - unknown FS
; 10 - access denied
; edx = cluster size in bytes
; ebx = total clusters on disk
; ecx = free clusters on disk
;-----------------------------------------------------------
cmp [ebp+FAT.fs_type], 16
jz info_fat_ok
cmp [ebp+FAT.fs_type], 32
jz info_fat_ok
xor edx, edx
xor ebx, ebx
xor ecx, ecx
mov eax, ERROR_UNKNOWN_FS
ret
 
info_fat_ok:
; call reserve_hd1
 
xor ecx, ecx ; count of free clusters
mov eax, 2
mov ebx, [ebp+FAT.LAST_CLUSTER]
 
info_cluster:
push eax
call get_FAT ; get cluster info
jc info_access_denied
 
test eax, eax ; is it free?
jnz info_used ; no
inc ecx
 
info_used:
pop eax
inc eax
cmp eax, ebx ; is above last cluster?
jbe info_cluster ; no. test next cluster
 
dec ebx ; cluster count
imul edx, [ebp+FAT.SECTORS_PER_CLUSTER], 512; cluster size in bytes
xor eax, eax
ret
 
info_access_denied:
add esp, 4
xor edx, edx
xor ebx, ebx
xor ecx, ecx
mov eax, ERROR_ACCESS_DENIED
ret
end if
 
update_disk:
;-----------------------------------------------------------
; write changed fat and cache to disk
;-----------------------------------------------------------
cmp [ebp+FAT.fat_change], 0 ; is fat changed?
je upd_no_change
 
call write_fat_sector
jc update_disk_acces_denied
 
upd_no_change:
 
push esi
mov esi, [ebp+PARTITION.Disk]
call disk_sync
pop esi
update_disk_acces_denied:
ret
 
fat_lock:
lea ecx, [ebp+FAT.Lock]
jmp mutex_lock
fat_unlock:
lea ecx, [ebp+FAT.Lock]
jmp mutex_unlock
 
; \begin{diamond}
hd_find_lfn:
; in: ebp -> FAT structure
; in: esi+[esp+4] -> name
; out: CF=1 - file not found, eax=error code
; else CF=0 and edi->direntry, eax=sector
; destroys eax
push esi edi
push 0
push 0
push fat16_root_first
push fat16_root_next
mov eax, [ebp+FAT.ROOT_CLUSTER]
cmp [ebp+FAT.fs_type], 32
jz .fat32
.loop:
call fat_find_lfn
jc .notfound
cmp byte [esi], 0
jz .found
.continue:
test byte [edi+11], 10h
jz .notfound
and dword [esp+12], 0
mov eax, [edi+20-2]
mov ax, [edi+26] ; cluster
.fat32:
mov [esp+8], eax
mov dword [esp+4], fat_notroot_first
mov dword [esp], fat_notroot_next
jmp .loop
.notfound:
add esp, 16
pop edi esi
stc
ret 4
.found:
lea eax, [esp+4+24]
cmp dword [eax], 0
jz @f
mov esi, [eax]
and dword [eax], 0
jmp .continue
@@:
lea eax, [esp+8]
cmp dword [eax], 0
jz .root
call fat_get_sector
jmp .cmn
.root:
mov eax, [eax+4]
add eax, [ebp+FAT.ROOT_START]
.cmn:
add esp, 20 ; CF=0
pop esi
ret 4
 
;----------------------------------------------------------------
;
; fs_HdRead - LFN variant for reading hard disk
;
; Obsolete, will be replaced with filesystem-specific functions.
;
; esi points to filename
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to read, 0+
; edx mem location to return data
;
; ret ebx = bytes read or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
fs_HdRead:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdRead
cmp [fs_type], 2
jz ext2_HdRead
or ebx, -1
mov eax, ERROR_UNKNOWN_FS
ret
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
call fat_Read
pop ebp
ret
 
;----------------------------------------------------------------
; fat_Read - FAT16/32 implementation of reading a file
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_Read:
call fat_lock
push edi
cmp byte [esi], 0
jnz @f
.noaccess:
pop edi
.noaccess_2:
call fat_unlock
or ebx, -1
mov eax, ERROR_ACCESS_DENIED
ret
 
@@:
stdcall hd_find_lfn, [esp+4+4]
jnc .found
pop edi
push eax
call fat_unlock
pop eax
or ebx, -1
ret
 
.found:
test byte [edi+11], 0x10; do not allow read directories
jnz .noaccess
cmp dword [ebx+8], 0
jz @f
xor ebx, ebx
.reteof:
call fat_unlock
mov eax, ERROR_END_OF_FILE
pop edi
ret
@@:
mov ecx, [ebx+12] ; size
mov edx, [ebx+16] ; pointer
mov ebx, [ebx+4] ; file offset
push edx
push 0
mov eax, [edi+28]
sub eax, ebx
jb .eof
cmp eax, ecx
jae @f
mov ecx, eax
mov byte [esp], 6
@@:
mov eax, [edi+20-2]
mov ax, [edi+26]
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
.new_cluster:
jecxz .new_sector
cmp eax, 2
jb .eof
cmp eax, [ebp+FAT.fatRESERVED]
jae .eof
mov [ebp+FAT.cluster_tmp], eax
dec eax
dec eax
mov edi, [ebp+FAT.SECTORS_PER_CLUSTER]
imul eax, edi
add eax, [ebp+FAT.DATA_START]
.new_sector:
test ecx, ecx
jz .done
sub ebx, 512
jae .skip
add ebx, 512
jnz .force_buf
cmp ecx, 512
jb .force_buf
; we may read directly to given buffer
push eax ebx
mov ebx, edx
call fs_read32_app
test eax, eax
pop ebx eax
jne .noaccess_1
add edx, 512
sub ecx, 512
jmp .skip
.force_buf:
; we must read sector to temporary buffer and then copy it to destination
push eax ebx
lea ebx, [ebp+FAT.buffer]
call fs_read32_app
test eax, eax
mov eax, ebx
pop ebx
jne .noaccess_3
add eax, ebx
push ecx
add ecx, ebx
cmp ecx, 512
jbe @f
mov ecx, 512
@@:
sub ecx, ebx
mov ebx, edx
call memmove
add edx, ecx
sub [esp], ecx
pop ecx
pop eax
xor ebx, ebx
.skip:
inc eax
dec edi
jnz .new_sector
mov eax, [ebp+FAT.cluster_tmp]
call get_FAT
jc .noaccess_1
 
jmp .new_cluster
.noaccess_3:
pop eax
.noaccess_1:
pop eax
push ERROR_DEVICE
.done:
mov ebx, edx
call fat_unlock
pop eax edx edi
sub ebx, edx
ret
.eof:
mov ebx, edx
pop eax edx
sub ebx, edx
jmp .reteof
 
;----------------------------------------------------------------
;
; fs_HdReadFolder - LFN variant for reading hard disk folder
;
; Obsolete, will be replaced with filesystem-specific functions.
;
; esi points to filename
; ebx pointer to structure 32-bit number = first wanted block, 0+
; & flags (bitfields)
; flags: bit 0: 0=ANSI names, 1=UNICODE names
; ecx number of blocks to read, 0+
; edx mem location to return data
;
; ret ebx = blocks read or 0xffffffff folder not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
fs_HdReadFolder:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdReadFolder
cmp [fs_type], 2
jz ext2_HdReadFolder
push ERROR_UNSUPPORTED_FS
pop eax
or ebx, -1
ret
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
call fat_ReadFolder
pop ebp
ret
 
;----------------------------------------------------------------
; fat_ReadFolder - FAT16/32 implementation of reading a folder
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_ReadFolder:
call fat_lock
mov eax, [ebp+FAT.ROOT_CLUSTER]
push edi
cmp byte [esi], 0
jz .doit
stdcall hd_find_lfn, [esp+4+4]
jnc .found
pop edi
push eax
call fat_unlock
pop eax
or ebx, -1
ret
.found:
test byte [edi+11], 0x10 ; do not allow read files
jnz .found_dir
pop edi
call fat_unlock
or ebx, -1
mov eax, ERROR_ACCESS_DENIED
ret
.found_dir:
mov eax, [edi+20-2]
mov ax, [edi+26] ; eax=cluster
.doit:
push esi
sub esp, 262*2 ; reserve space for LFN
push dword [ebx+8] ; for fat_get_name: read ANSI/UNICODE name
mov edx, [ebx+16] ; pointer to buffer
; init header
push eax
mov edi, edx
mov ecx, 32/4
xor eax, eax
rep stosd
pop eax
mov byte [edx], 1 ; version
mov esi, edi ; esi points to BDFE
mov ecx, [ebx+12] ; number of blocks to read
mov ebx, [ebx+4] ; index of the first block
.new_cluster:
mov [ebp+FAT.cluster_tmp], eax
test eax, eax
jnz @f
cmp [ebp+FAT.fs_type], 32
jz .notfound
mov eax, [ebp+FAT.ROOT_START]
push [ebp+FAT.ROOT_SECTORS]
push ebx
jmp .new_sector
@@:
dec eax
dec eax
imul eax, [ebp+FAT.SECTORS_PER_CLUSTER]
push [ebp+FAT.SECTORS_PER_CLUSTER]
add eax, [ebp+FAT.DATA_START]
push ebx
.new_sector:
lea ebx, [ebp+FAT.buffer]
mov edi, ebx
push eax
call fs_read32_sys
test eax, eax
pop eax
jnz .notfound2
add ebx, 512
push eax
.l1:
push ebp
lea ebp, [esp+20]
call fat_get_name
pop ebp
jc .l2
cmp byte [edi+11], 0xF
jnz .do_bdfe
add edi, 0x20
cmp edi, ebx
jb .do_bdfe
pop eax
inc eax
dec dword [esp+4]
jnz @f
mov eax, [ebp+FAT.cluster_tmp]
test eax, eax
jz .done
call get_FAT
jc .notfound2
cmp eax, 2
jb .done
cmp eax, [ebp+FAT.fatRESERVED]
jae .done
push eax
mov eax, [ebp+FAT.SECTORS_PER_CLUSTER]
mov [esp+8], eax
pop eax
mov [ebp+FAT.cluster_tmp], eax
dec eax
dec eax
imul eax, [ebp+FAT.SECTORS_PER_CLUSTER]
add eax, [ebp+FAT.DATA_START]
@@:
lea ebx, [ebp+FAT.buffer]
mov edi, ebx
push eax
call fs_read32_sys
test eax, eax
pop eax
jnz .notfound2
add ebx, 512
push eax
.do_bdfe:
inc dword [edx+8] ; new file found
dec dword [esp+4]
jns .l2
dec ecx
js .l2
inc dword [edx+4] ; new file block copied
push ebp
lea ebp, [esp+20]
call fat_entry_to_bdfe
pop ebp
.l2:
add edi, 0x20
cmp edi, ebx
jb .l1
pop eax
inc eax
dec dword [esp+4]
jnz .new_sector
mov eax, [ebp+FAT.cluster_tmp]
test eax, eax
jz .done
call get_FAT
jc .notfound2
cmp eax, 2
jb .done
cmp eax, [ebp+FAT.fatRESERVED]
jae .done
push eax
mov eax, [ebp+FAT.SECTORS_PER_CLUSTER]
mov [esp+8], eax
pop eax
pop ebx
add esp, 4
jmp .new_cluster
.notfound2:
add esp, 8
.notfound:
add esp, 262*2+4
pop esi edi
mov ebx, [edx+4]
call fat_unlock
mov eax, ERROR_DEVICE
ret
.done:
add esp, 262*2+4+8
mov ebx, [edx+4]
xor eax, eax
dec ecx
js @f
mov al, ERROR_END_OF_FILE
@@:
push eax
call fat_unlock
pop eax
pop esi edi
ret
 
fat16_root_next:
push ecx
lea ecx, [ebp+FAT.buffer+0x200-0x20]
cmp edi, ecx
jae fat16_root_next_sector
pop ecx
add edi, 0x20
ret ; CF=0
fat16_root_next_sector:
; read next sector
push [ebp+FAT.longname_sec2]
pop [ebp+FAT.longname_sec1]
mov ecx, [eax+4]
push ecx
add ecx, [ebp+FAT.ROOT_START]
mov [ebp+FAT.longname_sec2], ecx
pop ecx
inc ecx
mov [eax+4], ecx
cmp ecx, [ebp+FAT.ROOT_SECTORS]
pop ecx
jb fat16_root_first
mov eax, ERROR_FILE_NOT_FOUND
stc
ret
fat16_root_first:
mov eax, [eax+4]
add eax, [ebp+FAT.ROOT_START]
push ebx
lea edi, [ebp+FAT.buffer]
mov ebx, edi
call fs_read32_sys
pop ebx
test eax, eax
jnz .readerr
ret ; CF=0
.readerr:
mov eax, ERROR_DEVICE
stc
ret
.notfound:
mov eax, ERROR_FILE_NOT_FOUND
stc
ret
fat16_root_begin_write:
push edi eax
call fat16_root_first
pop eax edi
ret
fat16_root_end_write:
pusha
mov eax, [eax+4]
add eax, [ebp+FAT.ROOT_START]
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
popa
ret
fat16_root_next_write:
push ecx
lea ecx, [ebp+FAT.buffer+0x200]
cmp edi, ecx
jae @f
pop ecx
ret
@@:
call fat16_root_end_write
jmp fat16_root_next_sector
fat16_root_extend_dir:
stc
ret
 
fat_notroot_next:
push ecx
lea ecx, [ebp+FAT.buffer+0x200-0x20]
cmp edi, ecx
jae fat_notroot_next_sector
pop ecx
add edi, 0x20
ret ; CF=0
fat_notroot_next_sector:
push [ebp+FAT.longname_sec2]
pop [ebp+FAT.longname_sec1]
push eax
call fat_get_sector
mov [ebp+FAT.longname_sec2], eax
pop eax
mov ecx, [eax+4]
inc ecx
cmp ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
jae fat_notroot_next_cluster
mov [eax+4], ecx
jmp @f
fat_notroot_next_cluster:
push eax
mov eax, [eax]
call get_FAT
mov ecx, eax
pop eax
jc fat_notroot_first.deverr
cmp ecx, 2
jb fat_notroot_next_err
cmp ecx, [ebp+FAT.fatRESERVED]
jae fat_notroot_next_err
mov [eax], ecx
and dword [eax+4], 0
@@:
pop ecx
fat_notroot_first:
call fat_get_sector
push ebx
lea edi, [ebp+FAT.buffer]
mov ebx, edi
call fs_read32_sys
pop ebx
test eax, eax
jz .ret ; CF=0
push ecx
.deverr:
pop ecx
mov eax, ERROR_DEVICE
stc
.ret:
ret
fat_notroot_next_err:
pop ecx
mov eax, ERROR_FILE_NOT_FOUND
stc
ret
fat_notroot_begin_write:
push eax edi
call fat_notroot_first
pop edi eax
ret
fat_notroot_end_write:
call fat_get_sector
push ebx
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
pop ebx
ret
fat_notroot_next_write:
push ecx
lea ecx, [ebp+FAT.buffer+0x200]
cmp edi, ecx
jae @f
pop ecx
ret
@@:
push eax
call fat_notroot_end_write
pop eax
jmp fat_notroot_next_sector
fat_notroot_extend_dir:
push eax
call get_free_FAT
jnc .found
pop eax
ret ; CF=1
.found:
push edx
mov edx, [ebp+FAT.fatEND]
call set_FAT
jc .writeerr
mov edx, eax
mov eax, [esp+4]
mov eax, [eax]
push edx
call set_FAT
pop edx
jnc @f
.writeerr:
pop edx
pop eax
stc
ret
@@:
push ecx
or ecx, -1
call add_disk_free_space
; zero new cluster
mov ecx, 512/4
lea edi, [ebp+FAT.buffer]
push edi
xor eax, eax
rep stosd
pop edi
pop ecx
mov eax, [esp+4]
mov [eax], edx
and dword [eax+4], 0
pop edx
mov eax, [eax]
dec eax
dec eax
push ebx ecx
mov ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
imul eax, ecx
add eax, [ebp+FAT.DATA_START]
mov ebx, edi
@@:
push eax
call fs_write32_sys
pop eax
inc eax
loop @b
pop ecx ebx eax
clc
ret
 
fat_get_sector:
push ecx
mov ecx, [eax]
dec ecx
dec ecx
imul ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
add ecx, [ebp+FAT.DATA_START]
add ecx, [eax+4]
mov eax, ecx
pop ecx
ret
 
;----------------------------------------------------------------
;
; fs_HdRewrite - LFN variant for writing hard disk
;
; Obsolete, will be replaced with filesystem-specific functions.
;
; esi points to filename
; ebx ignored (reserved)
; ecx number of bytes to write, 0+
; edx mem location to data
;
; ret ebx = number of written bytes
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
fs_HdCreateFolder:
mov al, 1
jmp fs_HdRewrite.common
 
fs_HdRewrite:
xor eax, eax
.common:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdRewrite
cmp [fs_type], 2
jz ext2_HdRewrite
mov eax, ERROR_UNKNOWN_FS
xor ebx, ebx
ret
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
test eax, eax
mov eax, fat_CreateFolder
jnz @f
mov eax, fat_Rewrite
@@:
call eax
pop ebp
ret
 
fshrad:
call fat_unlock
mov eax, ERROR_ACCESS_DENIED
xor ebx, ebx
ret
 
;----------------------------------------------------------------
; fat_CreateFolder - FAT16/32 implementation of creating a folder
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_CreateFolder:
push 1
jmp fat_Rewrite.common
 
;----------------------------------------------------------------
; fat_HdRewrite - FAT16/32 implementation of creating a new file
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_Rewrite:
push 0
.common:
call fat_lock
pop eax
cmp byte [esi], 0
jz fshrad
mov ecx, [ebx+12]
mov edx, [ebx+16]
pushad
xor edi, edi
mov edx, [esp+4+20h]
push esi
test edx, edx
jz @f
mov esi, edx
@@:
lodsb
test al, al
jz @f
cmp al, '/'
jnz @b
lea edi, [esi-1]
jmp @b
@@:
pop esi
test edi, edi
jnz .noroot
test edx, edx
jnz .hasebp
mov edx, [ebp+FAT.ROOT_CLUSTER]
cmp [ebp+FAT.fs_type], 32
jz .pushnotroot
xor edx, edx
push edx
push fat16_root_extend_dir
push fat16_root_end_write
push fat16_root_next_write
push fat16_root_begin_write
push edx
push edx
push fat16_root_first
push fat16_root_next
jmp .common1
.hasebp:
mov eax, ERROR_ACCESS_DENIED
cmp byte [edx], 0
jz .ret1
stdcall hd_find_lfn, 0
mov esi, [esp+4+20h]
jc .ret1
jmp .common0
.noroot:
mov eax, ERROR_ACCESS_DENIED
cmp byte [edi+1], 0
jz .ret1
; check existence
mov byte [edi], 0
push edi
stdcall hd_find_lfn, [esp+4+24h]
pop esi
mov byte [esi], '/'
jnc @f
.notfound0:
mov eax, ERROR_FILE_NOT_FOUND
.ret1:
mov [esp+28], eax
call fat_unlock
popad
xor ebx, ebx
ret
@@:
inc esi
.common0:
test byte [edi+11], 0x10 ; must be directory
mov eax, ERROR_ACCESS_DENIED
jz .ret1
mov edx, [edi+20-2]
mov dx, [edi+26] ; ebp=cluster
mov eax, ERROR_FAT_TABLE
cmp edx, 2
jb .ret1
.pushnotroot:
push edx
push fat_notroot_extend_dir
push fat_notroot_end_write
push fat_notroot_next_write
push fat_notroot_begin_write
push 0
push edx
push fat_notroot_first
push fat_notroot_next
.common1:
call fat_find_lfn
jc .notfound
; found
test byte [edi+11], 10h
jz .exists_file
; found directory; if we are creating directory, return OK,
; if we are creating file, say "access denied"
add esp, 36
call fat_unlock
popad
test al, al
mov eax, ERROR_ACCESS_DENIED
jz @f
mov al, 0
@@:
xor ebx, ebx
ret
.exists_file:
; found file; if we are creating directory, return "access denied",
; if we are creating file, delete existing file and continue
cmp byte [esp+36+28], 0
jz @f
add esp, 36
call fat_unlock
popad
mov eax, ERROR_ACCESS_DENIED
xor ebx, ebx
ret
@@:
; delete FAT chain
push edi
xor eax, eax
mov dword [edi+28], eax ; zero size
xor ecx, ecx
mov eax, [edi+20-2]
mov ax, [edi+26]
mov word [edi+20], cx
mov word [edi+26], cx
test eax, eax
jz .done1
@@:
cmp eax, [ebp+FAT.fatRESERVED]
jae .done1
push edx
xor edx, edx
call set_FAT
mov eax, edx
pop edx
jc .done1
inc ecx
jmp @b
.done1:
pop edi
call get_time_for_file
mov [edi+22], ax
call get_date_for_file
mov [edi+24], ax
mov [edi+18], ax
or byte [edi+11], 20h ; set 'archive' attribute
jmp .doit
.notfound:
; file is not found; generate short name
call fat_name_is_legal
jc @f
add esp, 36
call fat_unlock
popad
mov eax, ERROR_FILE_NOT_FOUND
xor ebx, ebx
ret
@@:
sub esp, 12
mov edi, esp
call fat_gen_short_name
.test_short_name_loop:
push esi edi ecx
mov esi, edi
lea eax, [esp+12+12+8]
mov edx, [eax+24]
mov [eax], edx
and dword [eax+4], 0
call dword [eax-4]
jc .found
.test_short_name_entry:
cmp byte [edi+11], 0xF
jz .test_short_name_cont
mov ecx, 11
push esi edi
repz cmpsb
pop edi esi
jz .short_name_found
.test_short_name_cont:
lea eax, [esp+12+12+8]
call dword [eax-8]
jnc .test_short_name_entry
jmp .found
.short_name_found:
pop ecx edi esi
call fat_next_short_name
jnc .test_short_name_loop
.disk_full:
add esp, 12+36
call fat_unlock
popa
mov eax, ERROR_DISK_FULL
xor ebx, ebx
ret
.found:
pop ecx edi esi
; now find space in directory
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
mov al, '~'
push ecx edi
mov ecx, 8
repnz scasb
push 1
pop eax ; 1 entry
jnz .notilde
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
xor eax, eax
@@:
cmp byte [esi], 0
jz @f
inc esi
inc eax
jmp @b
@@:
sub esi, eax
add eax, 12+13
mov ecx, 13
push edx
cdq
div ecx
pop edx
.notilde:
push -1
push -1
push -1
; find <eax> successive entries in directory
xor ecx, ecx
push eax
lea eax, [esp+16+8+12+8]
mov edx, [eax+24]
mov [eax], edx
and dword [eax+4], 0
call dword [eax-4]
pop eax
jnc .scan_dir
.fsfrfe3:
add esp, 12+8+12+36
call fat_unlock
popad
mov eax, ERROR_DEVICE
xor ebx, ebx
ret
.scan_dir:
cmp byte [edi], 0
jz .free
cmp byte [edi], 0xE5
jz .free
xor ecx, ecx
.scan_cont:
push eax
lea eax, [esp+16+8+12+8]
call dword [eax-8]
mov edx, eax
pop eax
jnc .scan_dir
cmp edx, ERROR_DEVICE
jz .fsfrfe3
push eax
lea eax, [esp+16+8+12+8]
call dword [eax+20] ; extend directory
pop eax
jnc .scan_dir
add esp, 12+8+12+36
call fat_unlock
popad
mov eax, ERROR_DISK_FULL
xor ebx, ebx
ret
.free:
test ecx, ecx
jnz @f
mov [esp], edi
mov ecx, [esp+12+8+12+8]
mov [esp+4], ecx
mov ecx, [esp+12+8+12+12]
mov [esp+8], ecx
xor ecx, ecx
@@:
inc ecx
cmp ecx, eax
jb .scan_cont
; found!
push esi ecx
; If creating a directory, allocate one data cluster now and fail immediately
; if this is impossible. This prevents from creating an invalid directory entry
; on a full disk.
; yup, the argument is quite non-intuitive... but what should I do if
; the entire function uses such arguments? BTW, it refers to al from pushad,
; which in turn is filled with 0 in fat_Rewrite and 1 in fat_CreateFolder.
cmp byte [esp+8+12+8+12+36+28], 0
jz .no.preallocate.folder.data
call get_free_FAT
jnc @f
add esp, 8+12+8
jmp .disk_full
@@:
mov [esp+8+12+8+12+36+20], eax ; store the cluster somewhere
.no.preallocate.folder.data:
; calculate name checksum
mov esi, [esp+8+12]
mov ecx, 11
xor eax, eax
@@:
ror al, 1
add al, [esi]
inc esi
loop @b
pop ecx esi
pop edi
pop dword [esp+8+12+12]
pop dword [esp+8+12+12]
; edi points to first entry in free chunk
dec ecx
jz .nolfn
push esi
push eax
lea eax, [esp+8+8+12+8]
call dword [eax+8] ; begin write
mov al, 40h
.writelfn:
or al, cl
mov esi, [esp+4]
push ecx
dec ecx
imul ecx, 13
add esi, ecx
stosb
mov cl, 5
call fs_RamdiskRewrite.read_symbols
mov ax, 0xF
stosw
mov al, [esp+4]
stosb
mov cl, 6
call fs_RamdiskRewrite.read_symbols
xor eax, eax
stosw
mov cl, 2
call fs_RamdiskRewrite.read_symbols
pop ecx
lea eax, [esp+8+8+12+8]
call dword [eax+12] ; next write
xor eax, eax
loop .writelfn
pop eax
pop esi
; lea eax, [esp+8+12+8]
; call dword [eax+16] ; end write
.nolfn:
xchg esi, [esp]
mov ecx, 11
rep movsb
mov word [edi], 20h ; attributes
sub edi, 11
pop esi ecx
add esp, 12
mov byte [edi+13], 0 ; tenths of a second at file creation time
call get_time_for_file
mov [edi+14], ax ; creation time
mov [edi+22], ax ; last write time
call get_date_for_file
mov [edi+16], ax ; creation date
mov [edi+24], ax ; last write date
mov [edi+18], ax ; last access date
xor ecx, ecx
mov word [edi+20], cx ; high word of cluster
mov word [edi+26], cx ; low word of cluster - to be filled
mov dword [edi+28], ecx ; file size - to be filled
cmp byte [esp+36+28], cl
jz .doit
; create directory
mov byte [edi+11], 10h ; attributes: folder
mov esi, edi
lea eax, [esp+8]
call dword [eax+16] ; flush directory
mov eax, [esp+36+20] ; extract saved cluster
mov [esp+36+20], edi ; this is needed for calculating arg of add_disk_free_space!
push ecx
mov ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
shl ecx, 9
push ecx
push edi
jmp .doit2
.doit:
mov esi, [esp+36+20]
lea eax, [esp+8]
call dword [eax+16] ; flush directory
push ecx
mov ecx, [esp+4+36+24]
push ecx
push edi
test ecx, ecx
jz .done
call get_free_FAT
jc .diskfull
.doit2:
push eax
mov [edi+26], ax
shr eax, 16
mov [edi+20], ax
lea eax, [esp+16+8]
call dword [eax+16] ; flush directory
pop eax
push edx
mov edx, [ebp+FAT.fatEND]
call set_FAT
pop edx
.write_cluster:
push eax
dec eax
dec eax
imul eax, [ebp+FAT.SECTORS_PER_CLUSTER]
add eax, [ebp+FAT.DATA_START]
push [ebp+FAT.SECTORS_PER_CLUSTER]
; write data
.write_sector:
cmp byte [esp+20+36+28], 0
jnz .writedir
mov ecx, 512
cmp dword [esp+12], ecx
jb .writeshort
; we can write directly from given buffer
mov ebx, esi
add esi, ecx
jmp .writecommon
.writeshort:
mov ecx, [esp+12]
push ecx
lea edi, [ebp+FAT.buffer]
mov ebx, edi
rep movsb
.writedircont:
lea ecx, [ebp+FAT.buffer+0x200]
sub ecx, edi
push eax
xor eax, eax
rep stosb
pop eax
pop ecx
.writecommon:
push eax
call fs_write32_app
test eax, eax
pop eax
jnz .writeerr
inc eax
sub dword [esp+12], ecx
jz .writedone
dec dword [esp]
jnz .write_sector
pop eax
; allocate new cluster
pop eax
mov ecx, eax
call get_free_FAT
jc .diskfull
push edx
mov edx, [ebp+FAT.fatEND]
call set_FAT
xchg eax, ecx
mov edx, ecx
call set_FAT
pop edx
xchg eax, ecx
jmp .write_cluster
.diskfull:
mov eax, ERROR_DISK_FULL
jmp .ret
.writeerr:
pop eax eax
sub esi, ecx
mov eax, ERROR_DEVICE
jmp .ret
.writedone:
pop eax eax
.done:
xor eax, eax
.ret:
pop edi ecx
sub esi, [esp+4+36+20]
mov [esp+4+36+28], eax
mov [esp+4+36+16], esi
lea eax, [esp+12]
call dword [eax+8]
mov [edi+28], esi
call dword [eax+16]
mov [esp+36+16], ebx
lea eax, [esi+511]
shr eax, 9
mov ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
lea eax, [eax+ecx-1]
xor edx, edx
div ecx
pop ecx
sub ecx, eax
call add_disk_free_space
add esp, 36
call update_disk
call fat_unlock
popad
ret
.writedir:
push 512
lea edi, [ebp+FAT.buffer]
mov ebx, edi
mov ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
shl ecx, 9
cmp ecx, [esp+16]
jnz .writedircont
dec dword [esp+20]
push esi
mov ecx, 32/4
rep movsd
pop esi
mov dword [edi-32], '. '
mov dword [edi-32+4], ' '
mov dword [edi-32+8], ' '
mov byte [edi-32+11], 10h
push esi
mov ecx, 32/4
rep movsd
pop esi
mov dword [edi-32], '.. '
mov dword [edi-32+4], ' '
mov dword [edi-32+8], ' '
mov byte [edi-32+11], 10h
mov ecx, [esp+20+36]
cmp ecx, [ebp+FAT.ROOT_CLUSTER]
jnz @f
xor ecx, ecx
@@:
mov word [edi-32+26], cx
shr ecx, 16
mov [edi-32+20], cx
jmp .writedircont
 
;----------------------------------------------------------------
;
; fs_HdWrite - LFN variant for writing to hard disk
;
; Obsolete, will be replaced with filesystem-specific functions.
;
; esi points to filename
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to write, 0+
; edx mem location to data
;
; ret ebx = bytes written (maybe 0)
; eax = 0 ok write or other = errormsg
;
;--------------------------------------------------------------
fat_Write.access_denied:
push ERROR_ACCESS_DENIED
fs_HdWrite.ret0:
pop eax
xor ebx, ebx
ret
 
fs_HdWrite.ret11:
push ERROR_DEVICE
jmp fs_HdWrite.ret0
 
fs_HdWrite:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdWrite
cmp [fs_type], 2
jz ext2_HdWrite
push ERROR_UNKNOWN_FS
jmp .ret0
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
call fat_Write
pop ebp
ret
 
;----------------------------------------------------------------
; fat_Write - FAT16/32 implementation of writing to file
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_Write:
cmp byte [esi], 0
jz .access_denied
call fat_lock
push edi
stdcall hd_find_lfn, [esp+4+4]
jnc .found
pop edi
push eax
call fat_unlock
jmp fs_HdWrite.ret0
.found:
; FAT does not support files larger than 4GB
cmp dword [ebx+8], 0
jz @f
.eof:
pop edi
push ERROR_END_OF_FILE
call fat_unlock
jmp fs_HdWrite.ret0
@@:
mov ecx, [ebx+12]
mov edx, [ebx+16]
mov ebx, [ebx+4]
; now edi points to direntry, ebx=start byte to write,
; ecx=number of bytes to write, edx=data pointer
 
; extend file if needed
add ecx, ebx
jc .eof ; FAT does not support files larger than 4GB
push edx
push eax ; save directory sector
push 0 ; return value=0
 
call get_time_for_file
mov [edi+22], ax ; last write time
call get_date_for_file
mov [edi+24], ax ; last write date
mov [edi+18], ax ; last access date
 
push dword [edi+28] ; save current file size
cmp ecx, [edi+28]
jbe .length_ok
cmp ecx, ebx
jz .length_ok
call hd_extend_file
jnc .length_ok
mov [esp+4], eax
; hd_extend_file can return three error codes: FAT table error, device error or disk full.
; First two cases are fatal errors, in third case we may write some data
cmp al, ERROR_DISK_FULL
jz .disk_full
call fat_unlock
pop eax
pop eax
pop ecx
pop edx
pop edi
xor ebx, ebx
ret
.disk_full:
; correct number of bytes to write
mov ecx, [edi+28]
cmp ecx, ebx
ja .length_ok
push 0
.ret:
pop eax
sub edx, [esp+12]
mov ebx, edx ; ebx=number of written bytes
call update_disk
test eax, eax
jz @f
mov byte [esp+4], ERROR_DEVICE
@@:
call fat_unlock
pop eax
pop eax
pop ecx
pop edx
pop edi
ret
.length_ok:
mov esi, [edi+28]
mov eax, [edi+20-2]
mov ax, [edi+26]
mov edi, eax ; edi=current cluster
push 0 ; current sector in cluster
; save directory
mov eax, [esp+12]
push ebx
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
pop ebx
test eax, eax
jz @f
.device_err:
mov byte [esp+8], ERROR_DEVICE
jmp .ret
.fat_err:
mov byte [esp+8], ERROR_FAT_TABLE
jmp .ret
@@:
 
; now ebx=start pos, ecx=end pos, both lie inside file
sub ecx, ebx
jz .ret
.write_loop:
; skip unmodified sectors
cmp dword [esp+4], 0x200
jb .modify
sub ebx, 0x200
jae .skip
add ebx, 0x200
.modify:
; get length of data in current sector
push ecx
sub ebx, 0x200
jb .hasdata
neg ebx
xor ecx, ecx
jmp @f
.hasdata:
neg ebx
cmp ecx, ebx
jbe @f
mov ecx, ebx
@@:
; get current sector number
mov eax, edi
dec eax
dec eax
imul eax, [ebp+FAT.SECTORS_PER_CLUSTER]
add eax, [ebp+FAT.DATA_START]
add eax, [esp+4]
; load sector if needed
cmp dword [esp+8], 0 ; we don't need to read uninitialized data
jz .noread
cmp ecx, 0x200 ; we don't need to read sector if it is fully rewritten
jz .noread
cmp ecx, esi ; (same for the last sector)
jz .noread
push eax ebx
lea ebx, [ebp+FAT.buffer]
call fs_read32_app
test eax, eax
pop ebx eax
jz @f
.device_err2:
pop ecx
jmp .device_err
@@:
.noread:
; zero uninitialized data if file was extended (because hd_extend_file does not this)
push eax ecx edi
xor eax, eax
mov ecx, 0x200
sub ecx, [esp+8+12]
jbe @f
lea edi, [ebp+FAT.buffer]
add edi, [esp+8+12]
rep stosb
@@:
; zero uninitialized data in the last sector
mov ecx, 0x200
sub ecx, esi
jbe @f
lea edi, [ebp+FAT.buffer+esi]
rep stosb
@@:
pop edi ecx
; copy new data
mov eax, edx
neg ebx
jecxz @f
lea ebx, [ebp+FAT.buffer+0x200+ebx]
call memmove
xor ebx, ebx
@@:
pop eax
; save sector
push ebx
lea ebx, [ebp+FAT.buffer]
call fs_write32_app
pop ebx
test eax, eax
jnz .device_err2
add edx, ecx
sub [esp], ecx
pop ecx
jz .ret
.skip:
; next sector
pop eax
inc eax
push eax
cmp eax, [ebp+FAT.SECTORS_PER_CLUSTER]
jb @f
and dword [esp], 0
mov eax, edi
call get_FAT
mov edi, eax
jc .device_err
cmp edi, 2
jb .fat_err
cmp edi, [ebp+FAT.fatRESERVED]
jae .fat_err
@@:
sub esi, 0x200
jae @f
xor esi, esi
@@:
sub dword [esp+4], 0x200
jae @f
and dword [esp+4], 0
@@:
jmp .write_loop
 
hd_extend_file.zero_size:
xor eax, eax
jmp hd_extend_file.start_extend
 
; extends file on hd to given size (new data area is undefined)
; in: edi->direntry, ecx=new size
; out: CF=0 => OK, eax=0
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or ERROR_DEVICE)
hd_extend_file:
push esi
mov esi, [ebp+FAT.SECTORS_PER_CLUSTER]
imul esi, [ebp+FAT.BYTES_PER_SECTOR]
push ecx
; find the last cluster of file
mov eax, [edi+20-2]
mov ax, [edi+26]
mov ecx, [edi+28]
jecxz .zero_size
.last_loop:
sub ecx, esi
jbe .last_found
call get_FAT
jnc @f
.device_err:
pop ecx
.device_err2:
pop esi
push ERROR_DEVICE
.ret_err:
pop eax
stc
ret
@@:
cmp eax, 2
jb .fat_err
cmp eax, [ebp+FAT.fatRESERVED]
jb .last_loop
.fat_err:
pop ecx esi
push ERROR_FAT_TABLE
jmp .ret_err
.last_found:
push eax
call get_FAT
jnc @f
pop eax
jmp .device_err
@@:
cmp eax, [ebp+FAT.fatRESERVED]
pop eax
jb .fat_err
; set length to full number of clusters
sub [edi+28], ecx
.start_extend:
pop ecx
; now do extend
push edx
mov edx, 2 ; start scan from cluster 2
.extend_loop:
cmp [edi+28], ecx
jae .extend_done
; add new cluster
push eax
call get_free_FAT
jc .disk_full
mov edx, [ebp+FAT.fatEND]
call set_FAT
mov edx, eax
pop eax
test eax, eax
jz .first_cluster
push edx
call set_FAT
pop edx
jmp @f
.first_cluster:
ror edx, 16
mov [edi+20], dx
ror edx, 16
mov [edi+26], dx
@@:
push ecx
mov ecx, -1
call add_disk_free_space
pop ecx
mov eax, edx
add [edi+28], esi
jmp .extend_loop
.extend_done:
mov [edi+28], ecx
pop edx esi
xor eax, eax ; CF=0
ret
.device_err3:
pop edx
jmp .device_err2
.disk_full:
pop eax edx esi
push ERROR_DISK_FULL
pop eax
stc
ret
 
;----------------------------------------------------------------
;
; fs_HdSetFileEnd - set end of file on hard disk
;
; Obsolete, will be replaced with filesystem-specific functions.
;
; esi points to filename
; ebx points to 64-bit number = new file size
; ecx ignored (reserved)
; edx ignored (reserved)
;
; ret eax = 0 ok or other = errormsg
;
;--------------------------------------------------------------
fs_HdSetFileEnd:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdSetFileEnd
cmp [fs_type], 2
jz ext2_HdSetFileEnd
push ERROR_UNKNOWN_FS
pop eax
ret
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
call fat_SetFileEnd
pop ebp
ret
 
;----------------------------------------------------------------
; fat_SetFileEnd - FAT16/32 implementation of setting end-of-file
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_SetFileEnd:
call fat_lock
push edi
cmp byte [esi], 0
jnz @f
.access_denied:
push ERROR_ACCESS_DENIED
.ret:
call fat_unlock
pop eax
pop edi
ret
@@:
stdcall hd_find_lfn, [esp+4+4]
jnc @f
.reteax:
push eax
jmp .ret
@@:
; must not be directory
test byte [edi+11], 10h
jnz .access_denied
; file size must not exceed 4 Gb
cmp dword [ebx+8], 0
jz @f
push ERROR_END_OF_FILE
jmp .ret
@@:
push eax ; save directory sector
; set file modification date/time to current
call fat_update_datetime
mov eax, [ebx+4]
cmp eax, [edi+28]
jb .truncate
ja .expand
pop eax
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
pop edi
test eax, eax
jz @f
push ERROR_DEVICE
jmp .ret
@@:
push 0
jmp .ret
.expand:
push ebx ebp ecx
push dword [edi+28] ; save old size
mov ecx, eax
call hd_extend_file
push eax ; return code
jnc .expand_ok
cmp al, ERROR_DISK_FULL
jz .disk_full
.pop_ret:
call update_disk
pop eax ecx ecx ebp ebx ecx
jmp .reteax
.expand_ok:
.disk_full:
; save directory
mov eax, [edi+28]
xchg eax, [esp+20]
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
test eax, eax
mov eax, [edi+20-2]
mov ax, [edi+26]
mov edi, eax
jz @f
.pop_ret11:
mov byte [esp], ERROR_DEVICE
jmp .pop_ret
@@:
test edi, edi
jz .pop_ret
; now zero new data
push 0
; edi=current cluster, [esp]=sector in cluster
; [esp+24]=new size, [esp+8]=old size, [esp+4]=return code
.zero_loop:
cmp edi, 2
jb .error_fat
cmp edi, [ebp+FAT.fatRESERVED]
jae .error_fat
sub dword [esp+8], 0x200
jae .next_cluster
lea eax, [edi-2]
imul eax, [ebp+FAT.SECTORS_PER_CLUSTER]
add eax, [ebp+FAT.DATA_START]
add eax, [esp]
cmp dword [esp+8], -0x200
jz .noread
push eax
lea ebx, [ebp+FAT.buffer]
call fs_read32_app
test eax, eax
pop eax
jnz .err_next
.noread:
mov ecx, [esp+8]
neg ecx
push edi
lea edi, [ebp+FAT.buffer+0x200]
add edi, [esp+12]
push eax
xor eax, eax
mov [esp+16], eax
rep stosb
pop eax
pop edi
call fs_write32_app
test eax, eax
jz .next_cluster
.err_next:
mov byte [esp+4], ERROR_DEVICE
.next_cluster:
pop eax
sub dword [esp+20], 0x200
jbe .pop_ret
inc eax
push eax
cmp eax, [ebp+FAT.SECTORS_PER_CLUSTER]
jb .zero_loop
and dword [esp], 0
mov eax, edi
call get_FAT
mov edi, eax
jnc .zero_loop
pop eax
jmp .pop_ret11
.truncate:
mov [edi+28], eax
push ecx
mov ecx, [edi+20-2]
mov cx, [edi+26]
push eax
test eax, eax
jz .zero_size
; find new last cluster
@@:
cmp ecx, 2
jb .error_fat2
cmp ecx, [ebp+FAT.fatRESERVED]
jae .error_fat2
mov eax, [ebp+FAT.SECTORS_PER_CLUSTER]
shl eax, 9
sub [esp], eax
jbe @f
mov eax, ecx
call get_FAT
mov ecx, eax
jnc @b
.device_err3:
pop eax ecx eax edi
call update_disk
call fat_unlock
push ERROR_DEVICE
pop eax
ret
@@:
; we will zero data at the end of last sector - remember it
push ecx
; terminate FAT chain
push edx
mov eax, ecx
mov edx, [ebp+FAT.fatEND]
call set_FAT
mov eax, edx
pop edx
jnc @f
.device_err4:
pop ecx
jmp .device_err3
.zero_size:
and word [edi+20], 0
and word [edi+26], 0
push 0
mov eax, ecx
@@:
; delete FAT chain
call clear_cluster_chain
jc .device_err4
; save directory
mov eax, [esp+12]
push ebx
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
pop ebx
test eax, eax
jnz .device_err4
; zero last sector, ignore errors
pop ecx
pop eax
dec ecx
imul ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
add ecx, [ebp+FAT.DATA_START]
push eax
sar eax, 9
add ecx, eax
pop eax
and eax, 0x1FF
jz .truncate_done
push ebx eax
mov eax, ecx
lea ebx, [ebp+FAT.buffer]
call fs_read32_app
pop eax
lea edi, [ebp+FAT.buffer+eax]
push ecx
mov ecx, 0x200
sub ecx, eax
xor eax, eax
rep stosb
pop eax
call fs_write32_app
pop ebx
.truncate_done:
pop ecx eax edi
call update_disk
call fat_unlock
xor eax, eax
ret
.error_fat:
pop eax
mov byte [esp], ERROR_FAT_TABLE
jmp .pop_ret
.error_fat2:
pop eax ecx eax edi
call update_disk
call fat_unlock
push ERROR_FAT_TABLE
pop eax
ret
 
fs_HdGetFileInfo:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdGetFileInfo
cmp [fs_type], 2
jz ext2_HdGetFileInfo
mov eax, ERROR_UNKNOWN_FS
ret
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
call fat_GetFileInfo
pop ebp
ret
 
;----------------------------------------------------------------
; fat_GetFileInfo - FAT16/32 implementation of getting file info
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_GetFileInfo:
cmp byte [esi], 0
jnz @f
mov eax, 2
ret
@@:
push edi
call fat_lock
stdcall hd_find_lfn, [esp+4+4]
jc .error
push ebp
xor ebp, ebp
mov esi, [ebx+16]
mov dword [esi+4], ebp
call fat_entry_to_bdfe2
pop ebp
call fat_unlock
xor eax, eax
pop edi
ret
.error:
push eax
call fat_unlock
pop eax
pop edi
ret
 
fs_HdSetFileInfo:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdSetFileInfo
cmp [fs_type], 2
jz ext2_HdSetFileInfo
mov eax, ERROR_UNKNOWN_FS
ret
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
call fat_SetFileInfo
pop ebp
ret
 
;----------------------------------------------------------------
; fat_SetFileInfo - FAT16/32 implementation of setting file info
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_SetFileInfo:
cmp byte [esi], 0
jnz @f
mov eax, 2
ret
@@:
push edi
call fat_lock
stdcall hd_find_lfn, [esp+4+4]
jc .error
push eax
mov edx, [ebx+16]
call bdfe_to_fat_entry
pop eax
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
call update_disk
call fat_unlock
pop edi
xor eax, eax
ret
.error:
push eax
call fat_unlock
pop eax
pop edi
ret
 
;----------------------------------------------------------------
;
; fs_HdDelete - delete file or empty folder from hard disk
;
; Obsolete, will be replaced with filesystem-specific functions.
;
; esi points to filename
;
; ret eax = 0 ok or other = errormsg
;
;--------------------------------------------------------------
fs_HdDelete:
cmp [fs_type], 16
jz @f
cmp [fs_type], 32
jz @f
cmp [fs_type], 1
jz ntfs_HdDelete
cmp [fs_type], 2
jz ext2_HdDelete
push ERROR_UNKNOWN_FS
pop eax
ret
@@:
sub ebx, 4
push ebp
mov ebp, [fs_dependent_data_start.partition]
call fat_Delete
pop ebp
ret
 
;----------------------------------------------------------------
; fat_Delete - FAT16/32 implementation of deleting a file/folder
; in: ebp = pointer to FAT structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
fat_Delete:
call fat_lock
cmp byte [esi], 0
jnz @f
; cannot delete root!
.access_denied:
push ERROR_ACCESS_DENIED
.pop_ret:
call fat_unlock
pop eax
xor ebx, ebx
ret
@@:
and [ebp+FAT.longname_sec1], 0
and [ebp+FAT.longname_sec2], 0
push edi
stdcall hd_find_lfn, [esp+4+4]
jnc .found
pop edi
push ERROR_FILE_NOT_FOUND
jmp .pop_ret
.found:
cmp dword [edi], '. '
jz .access_denied2
cmp dword [edi], '.. '
jz .access_denied2
test byte [edi+11], 10h
jz .dodel
; we can delete only empty folders!
pushad
mov esi, [edi+20-2]
mov si, [edi+26]
xor ecx, ecx
lea eax, [esi-2]
imul eax, [ebp+FAT.SECTORS_PER_CLUSTER]
add eax, [ebp+FAT.DATA_START]
lea ebx, [ebp+FAT.buffer]
call fs_read32_sys
test eax, eax
jnz .err1
lea eax, [ebx+0x200]
add ebx, 2*0x20
.checkempty:
cmp byte [ebx], 0
jz .empty
cmp byte [ebx], 0xE5
jnz .notempty
add ebx, 0x20
cmp ebx, eax
jb .checkempty
inc ecx
cmp ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
jb @f
mov eax, esi
call get_FAT
jc .err1
cmp eax, 2
jb .error_fat
cmp eax, [ebp+FAT.fatRESERVED]
jae .empty
mov esi, eax
xor ecx, ecx
@@:
lea eax, [esi-2]
imul eax, [ebp+FAT.SECTORS_PER_CLUSTER]
add eax, [ebp+FAT.DATA_START]
add eax, ecx
lea ebx, [ebp+FAT.buffer]
call fs_read32_sys
test eax, eax
lea eax, [ebx+0x200]
jz .checkempty
.err1:
popad
.err2:
pop edi
call fat_unlock
push ERROR_DEVICE
pop eax
ret
.error_fat:
popad
pop edi
call fat_unlock
push ERROR_FAT_TABLE
pop eax
ret
.notempty:
popad
.access_denied2:
pop edi
call fat_unlock
push ERROR_ACCESS_DENIED
pop eax
ret
.empty:
popad
push eax ebx
lea ebx, [ebp+FAT.buffer]
call fs_read32_sys
test eax, eax
pop ebx eax
jnz .err2
.dodel:
push eax
mov eax, [edi+20-2]
mov ax, [edi+26]
xchg eax, [esp]
; delete folder entry
mov byte [edi], 0xE5
; delete LFN (if present)
.lfndel:
lea edx, [ebp+FAT.buffer]
cmp edi, edx
ja @f
cmp [ebp+FAT.longname_sec2], 0
jz .lfndone
push [ebp+FAT.longname_sec2]
push [ebp+FAT.longname_sec1]
pop [ebp+FAT.longname_sec2]
and [ebp+FAT.longname_sec1], 0
push ebx
mov ebx, edx
call fs_write32_sys
mov eax, [esp+4]
call fs_read32_sys
pop ebx
pop eax
lea edi, [ebp+FAT.buffer+0x200]
@@:
sub edi, 0x20
cmp byte [edi], 0xE5
jz .lfndone
cmp byte [edi+11], 0xF
jnz .lfndone
mov byte [edi], 0xE5
jmp .lfndel
.lfndone:
push ebx
lea ebx, [ebp+FAT.buffer]
call fs_write32_sys
pop ebx
; delete FAT chain
pop eax
call clear_cluster_chain
call update_disk
call fat_unlock
pop edi
xor eax, eax
ret
 
; \end{diamond}
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/fs/fs-sp.inc
0,0 → 1,13
dir0:
db 'DISCO DURO '
db 'UNIDAD RAM '
db 'DISQUETE '
db 0
 
dir1:
db 'PRIMERO '
db 'SEGUNDO '
db 'TERCERO '
db 'CUARTO '
db 0
 
/kernel/branches/net/fs/fs.inc
0,0 → 1,773
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; System service for filesystem call ;;
;; (C) 2004 Ville Turjanmaa, License: GPL ;;
;; 29.04.2006 Elimination of hangup after the ;;
;; expiration hd_wait_timeout (for LBA) - Mario79 ;;
;; 15.01.2005 get file size/attr/date, ;;
;; file_append (only for hd) - ATV ;;
;; 23.11.2004 test if hd/partition is set - ATV ;;
;; 18.11.2004 get_disk_info and more error codes - ATV ;;
;; 08.11.2004 expand_pathz and rename (only for hd) - ATV ;;
;; 20.10.2004 Makedir/Removedir (only for hd) - ATV ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
iglobal
 
if lang eq sp
include 'fs/fs-sp.inc'
else
dir0:
db 'HARDDISK '
db 'RAMDISK '
db 'FLOPPYDISK '
db 0
 
dir1:
db 'FIRST '
db 'SECOND '
db 'THIRD '
db 'FOURTH '
db 0
end if
 
not_select_IDE db 0
 
hd_address_table:
dd 0x1f0,0x00,0x1f0,0x10
dd 0x170,0x00,0x170,0x10
endg
 
file_system:
 
; IN:
;
; eax = 0 ; read file /RamDisk/First 6
; eax = 8 ; lba read
; eax = 15 ; get_disk_info
;
; OUT:
;
; eax = 0 : read ok
; eax = 1 : no hd base and/or partition defined
; eax = 2 : function is unsupported for this FS
; eax = 3 : unknown FS
; eax = 4 : partition not defined at hd
; eax = 5 : file not found
; eax = 6 : end of file
; eax = 7 : memory pointer not in application area
; eax = 8 : disk full
; eax = 9 : fat table corrupted
; eax = 10 : access denied
; eax = 11 : disk error
;
; ebx = size
 
; \begin{diamond}[18.03.2006]
; for subfunction 16 (start application) error codes must be negative
; because positive values are valid PIDs
; so possible return values are:
; eax > 0 : process created, eax=PID
 
; -0x10 <= eax < 0 : -eax is filesystem error code:
; eax = -1 = 0xFFFFFFFF : no hd base and/or partition defined
; eax = -3 = 0xFFFFFFFD : unknown FS
; eax = -5 = 0xFFFFFFFB : file not found
; eax = -6 = 0xFFFFFFFA : unexpected end of file (probably not executable file)
; eax = -9 = 0xFFFFFFF7 : fat table corrupted
; eax = -10 = 0xFFFFFFF6 : access denied
 
; -0x20 <= eax < -0x10: eax is process creation error code:
; eax = -0x20 = 0xFFFFFFE0 : too many processes
; eax = -0x1F = 0xFFFFFFE1 : not Menuet/Kolibri executable
; eax = -0x1E = 0xFFFFFFE2 : no memory
 
; ebx is not changed
 
; \end{diamond}[18.03.2006]
 
; Extract parameters
; add eax, std_application_base_address ; abs start of info block
 
cmp dword [eax+0], 15; GET_DISK_INFO
je fs_info
 
cmp dword [CURRENT_TASK], 1; no memory checks for kernel requests
jz no_checks_for_kernel
mov edx, eax
cmp dword [eax+0], 1
jnz .usual_check
mov ebx, [eax+12]
; add ebx,std_application_base_address
mov ecx, [eax+8]
call check_region
test eax, eax
jnz area_in_app_mem
 
.error_output:
mov esi, buffer_failed
call sys_msg_board_str
; mov eax,7
mov dword [esp+36], 7
ret
iglobal
buffer_failed db 'K : Buffer check failed',13,10,0
endg
.usual_check:
cmp dword [eax+0], 0
mov ecx, 512
jnz .small_size
mov ecx, [eax+8]
shl ecx, 9
.small_size:
mov ebx, [eax+12]
; add ebx,std_application_base_address
call check_region
test eax, eax
jz .error_output
area_in_app_mem:
mov eax, edx
no_checks_for_kernel:
 
fs_read:
 
mov ebx, [eax+20] ; program wants root directory ?
test bl, bl
je fs_getroot
test bh, bh
jne fs_noroot
fs_getroot:
; \begin{diamond}[18.03.2006]
; root - only read is allowed
; other operations return "access denied", eax=10
; (execute operation returns eax=-10)
cmp dword [eax], 0
jz .read_root
mov dword [esp+36], 10
ret
.read_root:
; \end{diamond}[18.03.2006]
mov esi, dir0
mov edi, [eax+12]
; add edi,std_application_base_address
mov ecx, 11
push ecx
; cld ; already is
rep movsb
mov al, 0x10
stosb
add edi, 32-11-1
pop ecx
rep movsb
stosb
and dword [esp+36], 0; ok read
mov dword [esp+24], 32*2; size of root
ret
 
fs_info: ;start of code - Mihasik
push eax
cmp [eax+21], byte 'r'
je fs_info_r
cmp [eax+21], byte 'R'
je fs_info_r
mov eax, 3 ;if unknown disk
xor ebx, ebx
xor ecx, ecx
xor edx, edx
jmp fs_info1
fs_info_r:
call ramdisk_free_space;if ramdisk
mov ecx, edi ;free space in ecx
shr ecx, 9 ;free clusters
mov ebx, 2847 ;total clusters
mov edx, 512 ;cluster size
xor eax, eax ;always 0
fs_info1:
pop edi
mov [esp+36], eax
mov [esp+24], ebx ; total clusters on disk
mov [esp+32], ecx ; free clusters on disk
mov [edi], edx ; cluster size in bytes
ret ;end of code - Mihasik
 
fs_noroot:
 
push dword [eax+0] ; read/write/delete/.../makedir/rename/lba/run
push dword [eax+4] ; 512 block number to read
push dword [eax+8] ; bytes to write/append or 512 blocks to read
mov ebx, [eax+12]
; add ebx,std_application_base_address
push ebx ; abs start of return/save area
 
lea esi, [eax+20] ; abs start of dir + filename
mov edi, [eax+16]
; add edi,std_application_base_address ; abs start of work area
 
call expand_pathz
 
push edi ; dir start
push ebx ; name of file start
 
mov eax, [edi+1]
cmp eax, 'RD '
je fs_yesramdisk
cmp eax, 'RAMD'
jne fs_noramdisk
 
fs_yesramdisk:
 
cmp byte [edi+1+11], 0
je fs_give_dir1
 
mov eax, [edi+1+12]
cmp eax, '1 '
je fs_yesramdisk_first
cmp eax, 'FIRS'
jne fs_noramdisk
 
fs_yesramdisk_first:
 
cmp dword [esp+20], 8; LBA read ramdisk
jne fs_no_LBA_read_ramdisk
 
mov eax, [esp+16] ; LBA block to read
mov ecx, [esp+8] ; abs pointer to return area
 
call LBA_read_ramdisk
jmp file_system_return
 
 
fs_no_LBA_read_ramdisk:
 
cmp dword [esp+20], 0; READ
jne fs_noramdisk_read
 
mov eax, [esp+4] ; fname
add eax, 2*12+1
mov ebx, [esp+16] ; block start
inc ebx
mov ecx, [esp+12] ; block count
mov edx, [esp+8] ; return
mov esi, [esp+0]
sub esi, eax
add esi, 12+1 ; file name length
call fileread
 
jmp file_system_return
 
 
fs_noramdisk_read:
fs_noramdisk:
 
;********************************************************************
mov eax, [edi+1]
cmp eax, 'FD '
je fs_yesflpdisk
cmp eax, 'FLOP'
jne fs_noflpdisk
 
fs_yesflpdisk:
call reserve_flp
 
cmp byte [edi+1+11], 0
je fs_give_dir1
 
mov eax, [edi+1+12]
cmp eax, '1 '
je fs_yesflpdisk_first
cmp eax, 'FIRS'
je fs_yesflpdisk_first
cmp eax, '2 '
je fs_yesflpdisk_second
cmp eax, 'SECO'
jne fs_noflpdisk
jmp fs_yesflpdisk_second
 
fs_yesflpdisk_first:
mov [flp_number], 1
jmp fs_yesflpdisk_start
fs_yesflpdisk_second:
mov [flp_number], 2
fs_yesflpdisk_start:
cmp dword [esp+20], 0; READ
jne fs_noflpdisk_read
 
mov eax, [esp+4] ; fname
add eax, 2*12+1
mov ebx, [esp+16] ; block start
inc ebx
mov ecx, [esp+12] ; block count
mov edx, [esp+8] ; return
mov esi, [esp+0]
sub esi, eax
add esi, 12+1 ; file name length
call floppy_fileread
 
jmp file_system_return
 
 
fs_noflpdisk_read:
fs_noflpdisk:
;*****************************************************************
 
mov eax, [edi+1]
cmp eax, 'HD0 '
je fs_yesharddisk_IDE0
cmp eax, 'HD1 '
je fs_yesharddisk_IDE1
cmp eax, 'HD2 '
je fs_yesharddisk_IDE2
cmp eax, 'HD3 '
je fs_yesharddisk_IDE3
jmp old_path_harddisk
fs_yesharddisk_IDE0:
call reserve_hd1
mov [hdbase], 0x1f0
mov [hdid], 0x0
mov [hdpos], 1
jmp fs_yesharddisk_partition
fs_yesharddisk_IDE1:
call reserve_hd1
mov [hdbase], 0x1f0
mov [hdid], 0x10
mov [hdpos], 2
jmp fs_yesharddisk_partition
fs_yesharddisk_IDE2:
call reserve_hd1
mov [hdbase], 0x170
mov [hdid], 0x0
mov [hdpos], 3
jmp fs_yesharddisk_partition
fs_yesharddisk_IDE3:
call reserve_hd1
mov [hdbase], 0x170
mov [hdid], 0x10
mov [hdpos], 4
fs_yesharddisk_partition:
call reserve_hd_channel
; call choice_necessity_partition
; jmp fs_yesharddisk_all
jmp fs_for_new_semantic
 
choice_necessity_partition:
mov eax, [edi+1+12]
call StringToNumber
mov [fat32part], eax
choice_necessity_partition_1:
mov ecx, [hdpos]
xor eax, eax
mov [hd_entries], eax; entries in hd cache
mov edx, DRIVE_DATA+2
cmp ecx, 0x80
jb search_partition_array
mov ecx, 4
search_partition_array:
mov bl, [edx]
movzx ebx, bl
add eax, ebx
inc edx
loop search_partition_array
mov ecx, [hdpos]
mov edx, BiosDiskPartitions
sub ecx, 0x80
jb .s
je .f
@@:
mov ebx, [edx]
add edx, 4
add eax, ebx
loop @b
jmp .f
.s:
sub eax, ebx
.f:
add eax, [known_part]; add eax,[fat32part]
dec eax
xor edx, edx
imul eax, 100
add eax, DRIVE_DATA+0xa
mov [transfer_adress], eax
call partition_data_transfer_1
ret
 
old_path_harddisk:
mov eax, [edi+1]
cmp eax, 'HD '
je fs_yesharddisk
cmp eax, 'HARD'
jne fs_noharddisk
 
fs_yesharddisk:
cmp dword [esp+20], 8; LBA read
jne fs_no_LBA_read
mov eax, [esp+16] ; LBA block to read
lea ebx, [edi+1+12] ; pointer to FIRST/SECOND/THIRD/FOURTH
mov ecx, [esp+8] ; abs pointer to return area
call LBA_read
jmp file_system_return
 
fs_no_LBA_read:
 
cmp byte [edi+1+11], 0; directory read
je fs_give_dir1
call reserve_hd1
fs_for_new_semantic:
call choice_necessity_partition
 
fs_yesharddisk_all:
mov eax, 1
mov ebx, [esp+24+24]
cmp [hdpos], 0 ; is hd base set?
jz hd_err_return
cmp [fat32part], 0 ; is partition set?
jnz @f
hd_err_return:
call free_hd_channel
and [hd1_status], 0
jmp file_system_return
@@:
 
call free_hd_channel
and [hd1_status], 0
 
fs_noharddisk:
; \begin{diamond}[18.03.2006]
mov eax, 5 ; file not found
; à ìîæåò áûòü, âîçâðàùàòü äðóãîé êîä îøèáêè?
mov ebx, [esp+24+24]; do not change ebx in application
; \end{diamond}[18.03.2006]
 
file_system_return:
 
add esp, 24
 
mov [esp+36], eax
mov [esp+24], ebx
ret
 
 
fs_give_dir1:
 
; \begin{diamond}[18.03.2006]
; /RD,/FD,/HD - only read is allowed
; other operations return "access denied", eax=10
; (execute operation returns eax=-10)
cmp dword [esp+20], 0
jz .read
add esp, 20
pop ecx
mov dword [esp+36], 10
ret
.read:
; \end{diamond}[18.03.2006]
mov al, 0x10
mov ebx, 1
mov edi, [esp+8]
mov esi, dir1
fs_d1_new:
mov ecx, 11
; cld
rep movsb
stosb
add edi, 32-11-1
dec ebx
jne fs_d1_new
 
add esp, 24
 
and dword [esp+36], 0; ok read
mov dword [esp+24], 32*1; dir/data size
ret
 
 
 
LBA_read_ramdisk:
 
cmp [lba_read_enabled], 1
je lbarrl1
 
xor ebx, ebx
mov eax, 2
ret
 
lbarrl1:
 
cmp eax, 18*2*80
jb lbarrl2
xor ebx, ebx
mov eax, 3
ret
 
lbarrl2:
 
pushad
 
call restorefatchain
 
mov edi, ecx
mov esi, eax
 
shl esi, 9
add esi, RAMDISK
mov ecx, 512/4
; cld
rep movsd
 
popad
 
xor ebx, ebx
xor eax, eax
ret
 
LBA_read:
 
; IN:
;
; eax = LBA block to read
; ebx = pointer to FIRST/SECOND/THIRD/FOURTH
; ecx = abs pointer to return area
 
cmp [lba_read_enabled], 1
je lbarl1
mov eax, 2
ret
 
lbarl1:
 
call reserve_hd1
 
push eax
push ecx
 
mov edi, hd_address_table
mov esi, dir1
mov eax, [ebx]
mov edx, '1 '
mov ecx, 4
blar0:
cmp eax, [esi]
je blar2
cmp eax, edx
je blar2
inc edx
add edi, 8
add esi, 11
dec ecx
jnz blar0
 
mov eax, 1
mov ebx, 1
jmp LBA_read_ret
 
blar2:
mov eax, [edi+0]
mov ebx, [edi+4]
 
mov [hdbase], eax
mov [hdid], ebx
 
call wait_for_hd_idle
cmp [hd_error], 0
jne hd_lba_error
 
; eax = hd port
; ebx = set for primary (0x00) or slave (0x10)
 
cli
 
mov edx, eax
inc edx
xor eax, eax
out dx, al
inc edx
inc eax
out dx, al
inc edx
mov eax, [esp+4]
out dx, al
shr eax, 8
inc edx
out dx, al
shr eax, 8
inc edx
out dx, al
shr eax, 8
inc edx
and al, 1+2+4+8
add al, bl
add al, 128+64+32
out dx, al
 
inc edx
mov al, 20h
out dx, al
 
sti
 
call wait_for_sector_buffer
cmp [hd_error], 0
jne hd_lba_error
 
cli
 
mov edi, [esp+0]
mov ecx, 256
sub edx, 7
cld
rep insw
 
sti
 
xor eax, eax
xor ebx, ebx
 
LBA_read_ret:
mov [hd_error], 0
mov [hd1_status], 0
add esp, 2*4
 
ret
 
 
expand_pathz:
; IN:
; esi = asciiz path & file
; edi = buffer for path & file name
; OUT:
; edi = directory & file : / 11 + / 11 + / 11 - zero terminated
; ebx = /file name - zero terminated
; esi = pointer after source
 
push eax
push ecx
push edi;[esp+0]
 
pathz_start:
mov byte [edi], '/'
inc edi
mov al, 32
mov ecx, 11
cld
rep stosb ; clear filename area
sub edi, 11
mov ebx, edi ; start of dir/file name
 
pathz_new_char:
mov al, [esi]
inc esi
cmp al, 0
je pathz_end
 
cmp al, '/'
jne pathz_not_path
cmp edi, ebx ; skip first '/'
jz pathz_new_char
lea edi, [ebx+11] ; start of next directory
jmp pathz_start
 
pathz_not_path:
cmp al, '.'
jne pathz_not_ext
lea edi, [ebx+8] ; start of extension
jmp pathz_new_char
 
pathz_not_ext:
cmp al, 'a'
jb pathz_not_low
cmp al, 'z'
ja pathz_not_low
sub al, 0x20 ; char to uppercase
 
pathz_not_low:
mov [edi], al
inc edi
mov eax, [esp+0] ; start_of_dest_path
add eax, 512 ; keep maximum path under 512 bytes
cmp edi, eax
jb pathz_new_char
 
pathz_end:
cmp ebx, edi ; if path end with '/'
jnz pathz_put_zero ; go back 1 level
sub ebx, 12
 
pathz_put_zero:
mov byte [ebx+11], 0
dec ebx ; include '/' char into file name
pop edi
pop ecx
pop eax
ret
 
;*******************************************
;* string to number
;* input eax - 4 byte string
;* output eax - number
;*******************************************
StringToNumber:
; ÏÅÐÅÂÎÄ ÑÒÐÎÊÎÂÎÃÎ ×ÈÑËÀ  ×ÈÑËÎÂÎÉ ÂÈÄ
; Âõîä:
; EDI - àäðåñ ñòðîêè ñ ÷èñëîì. Êîíåö ÷èñëà îòìå÷åí êîäîì 0Dh
; Âûõîä:
; CF - èíäèêàòîð îøèáîê:
; 0 - îøèáîê íåò;
; 1 - îøèáêà
; Åñëè CF=0, òî AX - ÷èñëî.
 
push bx
push cx
push dx
push edi
mov [partition_string], eax
mov edi, partition_string
xor cx, cx
i1:
mov al, [edi]
cmp al, 32;13
je i_exit
; cmp al,'0'
; jb err
; cmp al,'9'
; ja err
sub al, 48
shl cx, 1
jc error
mov bx, cx
shl cx, 1
jc error
shl cx, 1
jc error
add cx, bx
jc error
cbw
add cx, ax
jc error
i3:
inc edi
jmp i1
i_exit:
mov ax, cx
clc
i4:
movzx eax, ax
pop edi
pop dx
pop cx
pop bx
ret
 
error:
stc
jmp i4
 
partition_string:
dd 0
db 32
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/fs/fs_lfn.inc
0,0 → 1,1209
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
ERROR_SUCCESS = 0
ERROR_DISK_BASE = 1
ERROR_UNSUPPORTED_FS = 2
ERROR_UNKNOWN_FS = 3
ERROR_PARTITION = 4
ERROR_FILE_NOT_FOUND = 5
ERROR_END_OF_FILE = 6
ERROR_MEMORY_POINTER = 7
ERROR_DISK_FULL = 8
ERROR_FAT_TABLE = 9 ;deprecated
ERROR_FS_FAIL = 9
ERROR_ACCESS_DENIED = 10
ERROR_DEVICE = 11
 
; Errors specific to fn.70.7 - program start
 
ERROR_MEMORY_NOT_ENOUGH = 30
ERROR_INVALID_HEADER = 31
ERROR_TOO_MANY_PROCESSES = 32
ERROR_WRONG_HEADER_VERSION = 33 ; the version of the header is lower than needed for specific feature.
 
image_of_eax EQU esp+32
image_of_ebx EQU esp+20
 
 
struc FileInfoBlock {
.sub_fn dd ?
.offset dd ?
.flags dd ?
.size dd ?
.ptr_buff dd ?
.filename rb 1
.pFilename dd ?
 
; variants
 
label .execFlags dword at .offset
label .execPtrArg dword at .flags
label .execStdIO dword at .size
label .execStdErr dword at .ptr_buff
}
 
virtual at 0
FileInfoBlock FileInfoBlock
end virtual
 
 
; System function 70 - files with long names (LFN)
; diamond, 2006
 
iglobal
; in this table names must be in lowercase
rootdirs:
db 2,'rd'
dd fs_OnRamdisk
dd fs_NextRamdisk
db 7,'ramdisk'
dd fs_OnRamdisk
dd fs_NextRamdisk
db 2,'fd'
dd fs_OnFloppy
dd fs_NextFloppy
db 10,'floppydisk'
dd fs_OnFloppy
dd fs_NextFloppy
db 3,'hd0'
dd fs_OnHd0
dd fs_NextHd0
db 3,'hd1'
dd fs_OnHd1
dd fs_NextHd1
db 3,'hd2'
dd fs_OnHd2
dd fs_NextHd2
db 3,'hd3'
dd fs_OnHd3
dd fs_NextHd3
;**********************************************
db 3,'cd0'
dd fs_OnCd0
dd fs_NextCd
db 3,'cd1'
dd fs_OnCd1
dd fs_NextCd
db 3,'cd2'
dd fs_OnCd2
dd fs_NextCd
db 3,'cd3'
dd fs_OnCd3
dd fs_NextCd
;***********************************************
db 0
 
 
virtual_root_query:
dd fs_HasRamdisk
db 'rd',0
dd fs_HasFloppy
db 'fd',0
dd fs_HasHd0
db 'hd0',0
dd fs_HasHd1
db 'hd1',0
dd fs_HasHd2
db 'hd2',0
dd fs_HasHd3
db 'hd3',0
;**********************************************
dd fs_HasCd0
db 'cd0',0
dd fs_HasCd1
db 'cd1',0
dd fs_HasCd2
db 'cd2',0
dd fs_HasCd3
db 'cd3',0
;**********************************************
dd 0
 
fs_additional_handlers:
dd biosdisk_handler, biosdisk_enum_root
dd dyndisk_handler, dyndisk_enum_root
; add new handlers here
dd 0
 
endg
 
file_system_lfn_protected:
pushad
call protect_from_terminate
call file_system_lfn
call unprotect_from_terminate
popad
mov [image_of_eax], eax
mov [image_of_ebx], ebx
ret
 
file_system_lfn:
; in: ebx->fileinfo block
; operation codes:
; 0 : read file
; 1 : read folder
; 2 : create/rewrite file
; 3 : write/append to file
; 4 : set end of file
; 5 : get file/directory attributes structure
; 6 : set file/directory attributes structure
; 7 : start application
; 8 : delete file
; 9 : create directory
 
; parse file name
lea esi, [ebx+FileInfoBlock.filename]
lodsb
test al, al
jnz @f
mov esi, [esi] ; FileInfoBlock.pFilename actually.
lodsb
@@:
cmp al, '/'
jz .notcurdir
dec esi
mov ebp, esi
test al, al
jnz @f
xor ebp, ebp
@@:
mov esi, [current_slot]
mov esi, [esi+APPDATA.cur_dir]
jmp .parse_normal
.notcurdir:
cmp byte [esi], 0
jz .rootdir
call process_replace_file_name
.parse_normal:
cmp dword [ebx], 7
jne .not_execute
 
mov eax, [ebx+FileInfoBlock.execStdIO] ; or NULL if not needed.
mov ecx, [ebx+FileInfoBlock.execStdErr] ; or NULL if not needed.
mov edx, [ebx+FileInfoBlock.execFlags] ; now only debug flag
mov ebx, [ebx+FileInfoBlock.execPtrArg] ; pointer to string with command line arguments.
 
call fs_execute ; esi+ebp, ebx, edx
mov [image_of_eax], eax
ret
 
.not_execute:
mov edi, rootdirs-8
xor ecx, ecx
push esi
.scan1:
pop esi
add edi, ecx
scasd
scasd
mov cl, byte [edi]
test cl, cl
jz .notfound_try
inc edi
push esi
@@:
lodsb
or al, 20h
scasb
loopz @b
jnz .scan1
lodsb
cmp al, '/'
jz .found1
test al, al
jnz .scan1
pop eax
; directory /xxx
.maindir:
mov esi, [edi+4]
.maindir_noesi:
cmp dword [ebx], 1
jnz .access_denied
xor eax, eax
mov ebp, [ebx+12] ; block count to be read.
mov edx, [ebx+16] ; where to write the result.
; add edx, std_application_base_address
push dword [ebx+4] ; first block
mov ebx, [ebx+8] ; flags
; ebx=flags, [esp]=first block, ebp=number of blocks, edx=return area, esi='Next' handler
mov edi, edx
push ecx
mov ecx, 32/4
rep stosd
pop ecx
mov byte [edx], 1 ; version
.maindir_loop:
call esi
jc .maindir_done
inc dword [edx+8]
dec dword [esp]
jns .maindir_loop
dec ebp
js .maindir_loop
inc dword [edx+4]
mov dword [edi], 0x10 ; attributes: folder
mov dword [edi+4], 1 ; name type: UNICODE
push eax
xor eax, eax
add edi, 8
push ecx
mov ecx, 40/4-2
rep stosd
pop ecx
pop eax
push eax edx
; convert number in eax to decimal UNICODE string
push edi
push ecx
push -'0'
mov ecx, 10
@@:
xor edx, edx
div ecx
push edx
test eax, eax
jnz @b
@@:
pop eax
add al, '0'
stosb
test bl, 1 ; UNICODE name?
jz .ansi2
mov byte [edi], 0
inc edi
.ansi2:
test al, al
jnz @b
mov byte [edi-1], 0
pop ecx
pop edi
; UNICODE name length is 520 bytes, ANSI - 264
add edi, 520
test bl, 1
jnz @f
sub edi, 520-264
@@:
pop edx eax
jmp .maindir_loop
.maindir_done:
pop eax
mov ebx, [edx+4]
xor eax, eax
dec ebp
js @f
mov al, ERROR_END_OF_FILE
@@:
mov [image_of_eax], eax
mov [image_of_ebx], ebx
ret
; directory /
.rootdir:
cmp dword [ebx], 1 ; read folder?
jz .readroot
.access_denied:
mov dword [image_of_eax], 10 ; access denied
ret
 
.readroot:
; virtual root folder - special handler
mov esi, virtual_root_query
mov ebp, [ebx+12]
mov edx, [ebx+16]
; add edx, std_application_base_address
push dword [ebx+4] ; first block
mov ebx, [ebx+8] ; flags
xor eax, eax
; eax=0, [esp]=first block, ebx=flags, ebp=number of blocks, edx=return area
mov edi, edx
mov ecx, 32/4
rep stosd
mov byte [edx], 1 ; version
.readroot_loop:
cmp dword [esi], eax
jz .readroot_done_static
call dword [esi]
add esi, 4
test eax, eax
jnz @f
.readroot_next:
or ecx, -1
xchg esi, edi
repnz scasb
xchg esi, edi
jmp .readroot_loop
@@:
xor eax, eax
inc dword [edx+8]
dec dword [esp]
jns .readroot_next
dec ebp
js .readroot_next
inc dword [edx+4]
mov dword [edi], 0x10 ; attributes: folder
mov dword [edi+4], ebx ; name type: UNICODE
add edi, 8
mov ecx, 40/4-2
rep stosd
push edi
@@:
lodsb
stosb
test bl, 1
jz .ansi
mov byte [edi], 0
inc edi
.ansi:
test eax, eax
jnz @b
pop edi
add edi, 520
test bl, 1
jnz .readroot_loop
sub edi, 520-264
jmp .readroot_loop
.readroot_done_static:
mov esi, fs_additional_handlers-8
sub esp, 16
.readroot_ah_loop:
add esi, 8
cmp dword [esi], 0
jz .readroot_done
xor eax, eax
.readroot_ah_loop2:
push edi
lea edi, [esp+4]
call dword [esi+4]
pop edi
test eax, eax
jz .readroot_ah_loop
inc dword [edx+8]
dec dword [esp+16]
jns .readroot_ah_loop2
dec ebp
js .readroot_ah_loop2
push eax
xor eax, eax
inc dword [edx+4]
mov dword [edi], 0x10 ; attributes: folder
mov dword [edi+4], ebx
add edi, 8
mov ecx, 40/4-2
rep stosd
push esi edi
lea esi, [esp+12]
@@:
lodsb
stosb
test bl, 1
jz .ansi3
mov byte [edi], 0
inc edi
.ansi3:
test al, al
jnz @b
pop edi esi eax
add edi, 520
test bl, 1
jnz .readroot_ah_loop2
sub edi, 520-264
jmp .readroot_ah_loop2
.readroot_done:
add esp, 16
pop eax
mov ebx, [edx+4]
xor eax, eax
dec ebp
js @f
mov al, ERROR_END_OF_FILE
@@:
mov [image_of_eax], eax
mov [image_of_ebx], ebx
ret
.notfound_try:
mov edi, fs_additional_handlers
@@:
cmp dword [edi], 0
jz .notfound
call dword [edi]
scasd
scasd
jmp @b
.notfound:
mov dword [image_of_eax], ERROR_FILE_NOT_FOUND
and dword [image_of_ebx], 0
ret
 
.notfounda:
cmp edi, esp
jnz .notfound
call dword [edi+4]
add esp, 16
jmp .notfound
 
.found1:
pop eax
cmp byte [esi], 0
jz .maindir
.found2:
; read partition number
xor ecx, ecx
xor eax, eax
@@:
lodsb
cmp al, '/'
jz .done1
test al, al
jz .done1
sub al, '0'
cmp al, 9
ja .notfounda
lea ecx, [ecx*5]
lea ecx, [ecx*2+eax]
jmp @b
.done1:
jecxz .notfounda
test al, al
jnz @f
dec esi
@@:
cmp byte [esi], 0
jnz @f
test ebp, ebp
jz @f
mov esi, ebp
xor ebp, ebp
@@:
; now [edi] contains handler address, ecx - partition number,
; esi points to ASCIIZ string - rest of name
jmp dword [edi]
 
; handlers for devices
; in: ecx = 0 => query virtual directory /xxx
; in: ecx = partition number
; esi -> relative (for device) name
; ebx -> fileinfo
; ebp = 0 or pointer to rest of name from folder addressed by esi
; out: [image_of_eax]=image of eax, [image_of_ebx]=image of ebx
 
fs_OnRamdisk:
cmp ecx, 1
jnz file_system_lfn.notfound
mov eax, [ebx]
cmp eax, fs_NumRamdiskServices
jae .not_impl
mov ecx, [ebx+12]
mov edx, [ebx+16]
; add edx, std_application_base_address
add ebx, 4
call dword [fs_RamdiskServices + eax*4]
mov [image_of_eax], eax
mov [image_of_ebx], ebx
ret
.not_impl:
mov dword [image_of_eax], 2 ; not implemented
ret
 
fs_NotImplemented:
mov eax, 2
ret
 
fs_RamdiskServices:
dd fs_RamdiskRead
dd fs_RamdiskReadFolder
dd fs_RamdiskRewrite
dd fs_RamdiskWrite
dd fs_RamdiskSetFileEnd
dd fs_RamdiskGetFileInfo
dd fs_RamdiskSetFileInfo
dd 0
dd fs_RamdiskDelete
dd fs_RamdiskCreateFolder
fs_NumRamdiskServices = ($ - fs_RamdiskServices)/4
 
fs_OnFloppy:
cmp ecx, 2
ja file_system_lfn.notfound
mov eax, [ebx]
cmp eax, fs_NumFloppyServices
jae fs_OnRamdisk.not_impl
call reserve_flp
mov [flp_number], cl
mov ecx, [ebx+12]
mov edx, [ebx+16]
; add edx, std_application_base_address
add ebx, 4
call dword [fs_FloppyServices + eax*4]
and [flp_status], 0
mov [image_of_eax], eax
mov [image_of_ebx], ebx
ret
 
fs_FloppyServices:
dd fs_FloppyRead
dd fs_FloppyReadFolder
dd fs_FloppyRewrite
dd fs_FloppyWrite
dd fs_FloppySetFileEnd
dd fs_FloppyGetFileInfo
dd fs_FloppySetFileInfo
dd 0
dd fs_FloppyDelete
dd fs_FloppyCreateFolder
fs_NumFloppyServices = ($ - fs_FloppyServices)/4
 
fs_OnHd0:
call reserve_hd1
mov [hdbase], 0x1F0
mov [hdid], 0
push 1
jmp fs_OnHd
fs_OnHd1:
call reserve_hd1
mov [hdbase], 0x1F0
mov [hdid], 0x10
push 2
jmp fs_OnHd
fs_OnHd2:
call reserve_hd1
mov [hdbase], 0x170
mov [hdid], 0
push 3
jmp fs_OnHd
fs_OnHd3:
call reserve_hd1
mov [hdbase], 0x170
mov [hdid], 0x10
push 4
fs_OnHd:
call reserve_hd_channel
pop eax
mov [hdpos], eax
cmp ecx, 0x100
jae fs_OnHdAndBd.nf
cmp cl, [DRIVE_DATA+1+eax]
fs_OnHdAndBd:
jbe @f
.nf:
call free_hd_channel
and [hd1_status], 0
mov dword [image_of_eax], 5 ; not found
ret
@@:
mov [known_part], ecx ; mov [fat32part], ecx
push ebx esi
call choice_necessity_partition_1
pop esi ebx
mov ecx, [ebx+12]
mov edx, [ebx+16]
; add edx, std_application_base_address
mov eax, [ebx]
cmp eax, fs_NumHdServices
jae .not_impl
add ebx, 4
call dword [fs_HdServices + eax*4]
call free_hd_channel
and [hd1_status], 0
mov [image_of_eax], eax
mov [image_of_ebx], ebx
ret
.not_impl:
call free_hd_channel
and [hd1_status], 0
mov dword [image_of_eax], 2 ; not implemented
ret
 
fs_HdServices:
dd fs_HdRead
dd fs_HdReadFolder
dd fs_HdRewrite
dd fs_HdWrite
dd fs_HdSetFileEnd
dd fs_HdGetFileInfo
dd fs_HdSetFileInfo
dd 0
dd fs_HdDelete
dd fs_HdCreateFolder
fs_NumHdServices = ($ - fs_HdServices)/4
 
;*******************************************************
fs_OnCd0:
call reserve_cd
mov [ChannelNumber], 1
mov [DiskNumber], 0
push 6
push 1
jmp fs_OnCd
fs_OnCd1:
call reserve_cd
mov [ChannelNumber], 1
mov [DiskNumber], 1
push 4
push 2
jmp fs_OnCd
fs_OnCd2:
call reserve_cd
mov [ChannelNumber], 2
mov [DiskNumber], 0
push 2
push 3
jmp fs_OnCd
fs_OnCd3:
call reserve_cd
mov [ChannelNumber], 2
mov [DiskNumber], 1
push 0
push 4
fs_OnCd:
call reserve_cd_channel
pop eax
mov [cdpos], eax
pop eax
cmp ecx, 0x100
jae .nf
push ecx ebx
mov cl, al
mov bl, [DRIVE_DATA+1]
shr bl, cl
test bl, 2
pop ebx ecx
 
jnz @f
.nf:
call free_cd_channel
and [cd_status], 0
mov dword [image_of_eax], 5 ; not found
ret
@@:
mov ecx, [ebx+12]
mov edx, [ebx+16]
; add edx, std_application_base_address
mov eax, [ebx]
cmp eax, fs_NumCdServices
jae .not_impl
add ebx, 4
call dword [fs_CdServices + eax*4]
call free_cd_channel
and [cd_status], 0
mov [image_of_eax], eax
mov [image_of_ebx], ebx
ret
.not_impl:
call free_cd_channel
and [cd_status], 0
mov dword [image_of_eax], 2 ; not implemented
ret
 
fs_CdServices:
dd fs_CdRead
dd fs_CdReadFolder
dd fs_NotImplemented
dd fs_NotImplemented
dd fs_NotImplemented
dd fs_CdGetFileInfo
dd fs_NotImplemented
dd 0
dd fs_NotImplemented
dd fs_NotImplemented
fs_NumCdServices = ($ - fs_CdServices)/4
 
;*******************************************************
 
fs_HasRamdisk:
mov al, 1 ; we always have ramdisk
ret
 
fs_HasFloppy:
cmp byte [DRIVE_DATA], 0
setnz al
ret
 
fs_HasHd0:
mov al, [DRIVE_DATA+1]
and al, 11000000b
cmp al, 01000000b
setz al
ret
fs_HasHd1:
mov al, [DRIVE_DATA+1]
and al, 00110000b
cmp al, 00010000b
setz al
ret
fs_HasHd2:
mov al, [DRIVE_DATA+1]
and al, 00001100b
cmp al, 00000100b
setz al
ret
fs_HasHd3:
mov al, [DRIVE_DATA+1]
and al, 00000011b
cmp al, 00000001b
setz al
ret
 
;*******************************************************
fs_HasCd0:
mov al, [DRIVE_DATA+1]
and al, 11000000b
cmp al, 10000000b
setz al
ret
fs_HasCd1:
mov al, [DRIVE_DATA+1]
and al, 00110000b
cmp al, 00100000b
setz al
ret
fs_HasCd2:
mov al, [DRIVE_DATA+1]
and al, 00001100b
cmp al, 00001000b
setz al
ret
fs_HasCd3:
mov al, [DRIVE_DATA+1]
and al, 00000011b
cmp al, 00000010b
setz al
ret
;*******************************************************
 
; fs_NextXXX functions:
; in: eax = partition number, from which start to scan
; out: CF=1 => no more partitions
; CF=0 => eax=next partition number
 
fs_NextRamdisk:
; we always have /rd/1
test eax, eax
stc
jnz @f
mov al, 1
clc
@@:
ret
 
fs_NextFloppy:
; we have /fd/1 iff (([DRIVE_DATA] and 0xF0) != 0) and /fd/2 iff (([DRIVE_DATA] and 0x0F) != 0)
test byte [DRIVE_DATA], 0xF0
jz .no1
test eax, eax
jnz .no1
inc eax
ret ; CF cleared
.no1:
test byte [DRIVE_DATA], 0x0F
jz .no2
cmp al, 2
jae .no2
mov al, 2
clc
ret
.no2:
stc
ret
 
; on hdx, we have partitions from 1 to [0x40002+x]
fs_NextHd0:
push 0
jmp fs_NextHd
fs_NextHd1:
push 1
jmp fs_NextHd
fs_NextHd2:
push 2
jmp fs_NextHd
fs_NextHd3:
push 3
fs_NextHd:
pop ecx
movzx ecx, byte [DRIVE_DATA+2+ecx]
cmp eax, ecx
jae fs_NextFloppy.no2
inc eax
clc
ret
 
;*******************************************************
fs_NextCd:
; we always have /cdX/1
test eax, eax
stc
jnz @f
mov al, 1
clc
@@:
ret
;*******************************************************
 
; Additional FS handlers.
; This handler gets the control each time when fn 70 is called
; with unknown item of root subdirectory.
; in: esi -> name
; ebp = 0 or rest of name relative to esi
; out: if the handler processes path, he must not return in file_system_lfn,
; but instead pop return address and return directly to the caller
; otherwise simply return
 
; here we test for /bd<N>/... - BIOS disks
biosdisk_handler:
cmp [NumBiosDisks], 0
jz .ret
mov al, [esi]
or al, 20h
cmp al, 'b'
jnz .ret
mov al, [esi+1]
or al, 20h
cmp al, 'd'
jnz .ret
push esi
inc esi
inc esi
cmp byte [esi], '0'
jb .ret2
cmp byte [esi], '9'
ja .ret2
xor edx, edx
@@:
lodsb
test al, al
jz .ok
cmp al, '/'
jz .ok
sub al, '0'
cmp al, 9
ja .ret2
lea edx, [edx*5]
lea edx, [edx*2+eax]
jmp @b
.ret2:
pop esi
.ret:
ret
.ok:
cmp al, '/'
jz @f
dec esi
@@:
add dl, 80h
xor ecx, ecx
@@:
cmp dl, [BiosDisksData+ecx*4]
jz .ok2
inc ecx
cmp ecx, [NumBiosDisks]
jb @b
jmp .ret2
.ok2:
add esp, 8
test al, al
jnz @f
mov esi, fs_BdNext
jmp file_system_lfn.maindir_noesi
@@:
push ecx
push ecx
push biosdisk_cleanup
push fs_OnBd
mov edi, esp
jmp file_system_lfn.found2
 
fs_BdNext:
cmp eax, [BiosDiskPartitions+ecx*4]
inc eax
cmc
biosdisk_cleanup:
ret
 
fs_OnBd:
pop edx edx edx edx
; edx = disk number, ecx = partition number
; esi+ebp = name
call reserve_hd1
add edx, 0x80
mov [hdpos], edx
cmp ecx, [BiosDiskPartitions+(edx-0x80)*4]
jmp fs_OnHdAndBd
 
; This handler is called when virtual root is enumerated
; and must return all items which can be handled by this.
; It is called several times, first time with eax=0
; in: eax = 0 for first call, previously returned value for subsequent calls
; out: eax = 0 => no more items
; eax != 0 => buffer pointed to by edi contains name of item
 
; here we enumerate existing BIOS disks /bd<N>
biosdisk_enum_root:
cmp eax, [NumBiosDisks]
jae .end
push eax
movzx eax, byte [BiosDisksData+eax*4]
sub al, 80h
push eax
mov al, 'b'
stosb
mov al, 'd'
stosb
pop eax
cmp al, 10
jae .big
add al, '0'
stosb
mov byte [edi], 0
pop eax
inc eax
ret
.end:
xor eax, eax
ret
.big:
push ecx edx
push -'0'
mov ecx, 10
@@:
xor edx, edx
div ecx
push edx
test eax, eax
jnz @b
xchg eax, edx
@@:
pop eax
add al, '0'
stosb
jnz @b
pop edx ecx
pop eax
inc eax
ret
 
process_replace_file_name:
mov ebp, [full_file_name_table]
mov edi, [full_file_name_table.size]
dec edi
shl edi, 7
add edi, ebp
.loop:
cmp edi, ebp
jb .notfound
push esi edi
@@:
cmp byte [edi], 0
jz .dest_done
lodsb
test al, al
jz .cont
or al, 20h
scasb
jz @b
jmp .cont
.dest_done:
cmp byte [esi], 0
jz .found
cmp byte [esi], '/'
jnz .cont
inc esi
jmp .found
.cont:
pop edi esi
sub edi, 128
jmp .loop
.found:
pop edi eax
mov ebp, esi
cmp byte [esi], 0
lea esi, [edi+64]
jnz .ret
.notfound:
xor ebp, ebp
.ret:
ret
 
sys_current_directory:
; mov esi, [current_slot]
; mov esi, [esi+APPDATA.cur_dir]
; mov edx, esi
 
;get length string of appdata.cur_dir
mov eax, [current_slot]
mov edi, [eax+APPDATA.cur_dir]
 
dec ebx
jz .set
dec ebx
jz .get
ret
.get:
; sysfunction 30.2: [for app] eax=30,ebx=2,ecx->buffer,edx=len
; for our code: ebx->buffer,ecx=len
max_cur_dir equ 0x1000
 
mov ebx, edi
 
push ecx
push edi
 
xor eax, eax
mov ecx, max_cur_dir
 
repne scasb ;find zerro at and string
jnz .error ; no zero in cur_dir: internal error, should not happen
 
sub edi, ebx ;lenght for copy
inc edi
mov [esp+32+8], edi ;return in eax
 
cmp edx, edi
jbe @f
mov edx, edi
@@:
;source string
pop esi
;destination string
pop edi
cmp edx, 1
jbe .ret
 
mov al, '/' ;start string with '/'
stosb
mov ecx, edx
rep movsb ;copy string
.ret:
ret
 
.error:
add esp, 8
or dword [esp+32], -1 ;error not found zerro at string ->[eax+APPDATA.cur_dir]
ret
.set:
; sysfunction 30.1: [for app] eax=30,ebx=1,ecx->string
; for our code: ebx->string to set
; use generic resolver with APPDATA.cur_dir as destination
push max_cur_dir ;0x1000
push edi ;destination
mov ebx, ecx
call get_full_file_name
ret
 
; in: ebx = file name, [esp+4] = destination, [esp+8] = sizeof destination
; destroys all registers except ebp,esp
get_full_file_name:
push ebp
mov esi, [current_slot]
mov esi, [esi+APPDATA.cur_dir]
mov edx, esi
@@:
inc esi
cmp byte [esi-1], 0
jnz @b
dec esi
cmp byte [ebx], '/'
jz .set_absolute
; string gives relative path
mov edi, [esp+8] ; destination
.relative:
cmp byte [ebx], 0
jz .set_ok
cmp word [ebx], '.'
jz .set_ok
cmp word [ebx], './'
jnz @f
add ebx, 2
jmp .relative
@@:
cmp word [ebx], '..'
jnz .doset_relative
cmp byte [ebx+2], 0
jz @f
cmp byte [ebx+2], '/'
jnz .doset_relative
@@:
dec esi
cmp byte [esi], '/'
jnz @b
add ebx, 3
jmp .relative
.set_ok:
cmp edx, edi ; is destination equal to APPDATA.cur_dir?
jz .set_ok.cur_dir
sub esi, edx
cmp esi, [esp+12]
jb .set_ok.copy
.fail:
mov byte [edi], 0
xor eax, eax ; fail
pop ebp
ret 8
.set_ok.copy:
mov ecx, esi
mov esi, edx
rep movsb
mov byte [edi], 0
.ret.ok:
mov al, 1 ; ok
pop ebp
ret 8
.set_ok.cur_dir:
mov byte [esi], 0
jmp .ret.ok
.doset_relative:
cmp edx, edi
jz .doset_relative.cur_dir
sub esi, edx
cmp esi, [esp+12]
jae .fail
mov ecx, esi
mov esi, edx
mov edx, edi
rep movsb
jmp .doset_relative.copy
.doset_relative.cur_dir:
mov edi, esi
.doset_relative.copy:
add edx, [esp+12]
mov byte [edi], '/'
inc edi
cmp edi, edx
jae .overflow
@@:
mov al, [ebx]
inc ebx
stosb
test al, al
jz .ret.ok
cmp edi, edx
jb @b
.overflow:
dec edi
jmp .fail
.set_absolute:
lea esi, [ebx+1]
call process_replace_file_name
mov edi, [esp+8]
mov edx, [esp+12]
add edx, edi
.set_copy:
lodsb
stosb
test al, al
jz .set_part2
.set_copy_cont:
cmp edi, edx
jb .set_copy
jmp .overflow
.set_part2:
mov esi, ebp
xor ebp, ebp
test esi, esi
jz .ret.ok
mov byte [edi-1], '/'
jmp .set_copy_cont
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/fs/part_set.inc
0,0 → 1,436
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
;*************************************************************
;* 13.02.2010 Find all partition and check supported FS
;* 12.07.2007 Check all 4 entry of MBR and EMBR
;* 29.04.2006 Elimination of hangup after the
;* expiration hd_wait_timeout - Mario79
;* 28.01.2006 find all Fat16/32 partition in all input point
;* to MBR - Mario79
;*************************************************************
 
uglobal
align 4
 
;******************************************************
; Please do not change this place - variables in text
; Mario79
; START place
;******************************************************
PARTITION_START dd 0x3f
PARTITION_END dd 0
fs_type db 0 ; 1=NTFS, 2=EXT2/3, 16=FAT16, 32=FAT32
align 4
 
fs_dependent_data_start:
; FATxx data
 
.partition dd ?
rb 80
 
fs_dependent_data_end:
file_system_data_size = $ - PARTITION_START
if file_system_data_size > 96
ERROR:
sizeof(file system data) too big!
end if
 
virtual at fs_dependent_data_start
; NTFS data
ntfs_data:
.sectors_per_cluster dd ?
.mft_cluster dd ?
.mftmirr_cluster dd ?
.frs_size dd ? ; FRS size in bytes
.iab_size dd ? ; IndexAllocationBuffer size in bytes
.frs_buffer dd ?
.iab_buffer dd ?
.mft_retrieval dd ?
.mft_retrieval_size dd ?
.mft_retrieval_alloc dd ?
.mft_retrieval_end dd ?
.cur_index_size dd ?
.cur_index_buf dd ?
if $ > fs_dependent_data_end
ERROR:
increase sizeof(fs_dependent_data)!
end if
end virtual
 
virtual at fs_dependent_data_start
; EXT2 data
ext2_data:
.log_block_size dd ?
.block_size dd ?
.count_block_in_block dd ?
.blocks_per_group dd ?
.global_desc_table dd ?
.root_inode dd ? ; pointer to root inode in memory
.inode_size dd ?
.count_pointer_in_block dd ? ; block_size / 4
.count_pointer_in_block_square dd ? ; (block_size / 4)**2
.ext2_save_block dd ? ; ¡«®ª ­  £«®¡ «ì­ãî 1 ¯à®æ¥¤ãàã
.ext2_temp_block dd ? ; ¡«®ª ¤«ï ¬¥«ª¨å ¯à®æ¥¤ãà
.ext2_save_inode dd ? ; inode ­  £«®¡ «ì­ãî ¯à®æ¥¤ãàã
.ext2_temp_inode dd ? ; inode ¤«ï ¬¥«ª¨å ¯à®æ¥¤ãà
.sb dd ? ; superblock
.groups_count dd ?
if $ > fs_dependent_data_end
ERROR:
increase sizeof(fs_dependent_data)!
end if
end virtual
 
;***************************************************************************
; End place
; Mario79
;***************************************************************************
endg
iglobal
 
partition_types: ; list of fat16/32 partitions
db 0x04 ; DOS: fat16 <32M
db 0x06 ; DOS: fat16 >32M
db 0x0b ; WIN95: fat32
db 0x0c ; WIN95: fat32, LBA-mapped
db 0x0e ; WIN95: fat16, LBA-mapped
db 0x14 ; Hidden DOS: fat16 <32M
db 0x16 ; Hidden DOS: fat16 >32M
db 0x1b ; Hidden WIN95: fat32
db 0x1c ; Hidden WIN95: fat32, LBA-mapped
db 0x1e ; Hidden WIN95: fat16, LBA-mapped
db 0xc4 ; DRDOS/secured: fat16 <32M
db 0xc6 ; DRDOS/secured: fat16 >32M
db 0xcb ; DRDOS/secured: fat32
db 0xcc ; DRDOS/secured: fat32, LBA-mapped
db 0xce ; DRDOS/secured: fat16, LBA-mapped
db 0xd4 ; Old Multiuser DOS secured: fat16 <32M
db 0xd6 ; Old Multiuser DOS secured: fat16 >32M
db 0x07 ; NTFS
db 0x27 ; NTFS, hidden
db 0x83 ; Linux native file system (ext2fs)
partition_types_end:
 
 
extended_types: ; list of extended partitions
db 0x05 ; DOS: extended partition
db 0x0f ; WIN95: extended partition, LBA-mapped
db 0xc5 ; DRDOS/secured: extended partition
db 0xd5 ; Old Multiuser DOS secured: extended partition
extended_types_end:
 
endg
 
; Partition chain used:
; MBR <---------------------
; | |
; |-> PARTITION1 |
; |-> EXTENDED PARTITION - ;not need be second partition
; |-> PARTITION3
; |-> PARTITION4
 
set_PARTITION_variables:
set_FAT32_variables: ;deprecated
and [problem_partition], 0
call reserve_hd1
call reserve_hd_channel
 
pushad
 
cmp dword [hdpos], 0
je problem_hd
 
xor ecx, ecx ; partition count
;or edx,-1 ; flag for partition
xor eax, eax ; address MBR
xor ebp, ebp ; extended partition start
 
new_mbr:
test ebp, ebp ; is there extended partition? (MBR or EMBR)
jnz extended_already_set; yes
xchg ebp, eax ; no. set it now
 
extended_already_set:
add eax, ebp ; mbr=mbr+0, ext_part=ext_start+relat_start
mov ebx, buffer
call hd_read
cmp [hd_error], 0
jne problem_hd
 
cmp word [ebx+0x1fe], 0xaa55; is it valid boot sector?
jnz end_partition_chain
push eax ; push only one time
cmp dword [ebx+0x1be+0xc], 0; skip over empty partition
jnz test_primary_partition_0
cmp dword [ebx+0x1be+0xc+16], 0
jnz test_primary_partition_1
cmp dword [ebx+0x1be+0xc+16+16], 0
jnz test_primary_partition_2
cmp dword [ebx+0x1be+0xc+16+16+16], 0
jnz test_primary_partition_3
pop eax
jmp end_partition_chain
 
test_primary_partition_0:
mov al, [ebx+0x1be+4]; get primary partition type
call scan_partition_types
jnz test_primary_partition_1; no. skip over
 
inc ecx
cmp ecx, [known_part]; is it wanted partition?
jnz test_primary_partition_1; no
 
pop eax
;mov edx, eax ; start sector
add eax, [ebx+0x1be+8] ; add relative start
;mov [PARTITON_START],edx
;push edx
mov edx, [ebx+0x1be+12] ; length
;add edx, eax ; add length
;dec edx ; PARTITION_END is inclusive
;mov [PARTITION_END], edx ; note that this can be changed
; when file system data will be available
mov cl, [ebx+0x1be+4] ; fs_type
;mov [fs_type], dl ; save for FS recognizer (separate FAT vs NTFS)
;pop edx
jmp hd_and_partition_ok
 
test_primary_partition_1:
mov al, [ebx+0x1be+4+16]; get primary partition type
call scan_partition_types
jnz test_primary_partition_2 ; no. skip over
 
inc ecx
cmp ecx, [known_part]; is it wanted partition?
jnz test_primary_partition_2 ; no
 
pop eax
add eax, [ebx+0x1be+8+16]
mov edx, [ebx+0x1be+12+16]
mov cl, [ebx+0x1be+4+16]
jmp hd_and_partition_ok
 
;mov edx, eax
;add edx, [ebx+0x1be+8+16]
;push edx
;add edx, [ebx+0x1be+12+16]
;dec edx
;mov [PARTITION_END], edx
;mov al, [ebx+0x1be+4+16]
;mov [fs_type], dl
;pop edx
 
test_primary_partition_2:
mov al, [ebx+0x1be+4+16+16]; get primary partition type
call scan_partition_types
jnz test_primary_partition_3 ; no. skip over
 
inc ecx
cmp ecx, [known_part]; is it wanted partition?
jnz test_primary_partition_3 ; no
 
pop eax
add eax, [ebx+0x1be+8+16+16]
mov edx, [ebx+0x1be+12+16+16]
mov cl, [ebx+0x1be+4+16+16]
jmp hd_and_partition_ok
;mov edx, eax
;add edx, [ebx+0x1be+8+16+16]
;push edx
;add edx, [ebx+0x1be+12+16+16]
;dec edx
;mov [PARTITION_END], edx
;mov al, [ebx+0x1be+4+16+16]
;mov [fs_type], dl
;pop edx
 
test_primary_partition_3:
mov al, [ebx+0x1be+4+16+16+16]; get primary partition type
call scan_partition_types
jnz test_ext_partition_0 ; no. skip over
 
inc ecx
cmp ecx, [known_part]; is it wanted partition?
jnz test_ext_partition_0; no
 
pop eax
add eax, [ebx+0x1be+8+16+16+16]
mov edx, [ebx+0x1be+12+16+16+16]
mov cl, [ebx+0x1be+4+16+16+16]
jmp hd_and_partition_ok
 
;mov edx, eax
;add edx, [ebx+0x1be+8+16+16+16]
;push edx
;add edx, [ebx+0x1be+12+16+16+16]
;dec edx
;mov [PARTITION_END], edx
;mov al, [ebx+0x1be+4+16+16+16]
;mov [fs_type], dl
;pop edx
 
test_ext_partition_0:
pop eax ; ¯à®áâ® ¢ëª¨¤ë¢ ¥¬ ¨§ á⥪ 
mov al, [ebx+0x1be+4]; get extended partition type
call scan_extended_types
jnz test_ext_partition_1
 
mov eax, [ebx+0x1be+8]; add relative start
test eax, eax ; is there extended partition?
jnz new_mbr ; yes. read it
 
test_ext_partition_1:
mov al, [ebx+0x1be+4+16]; get extended partition type
call scan_extended_types
jnz test_ext_partition_2
 
mov eax, [ebx+0x1be+8+16]; add relative start
test eax, eax ; is there extended partition?
jnz new_mbr ; yes. read it
 
test_ext_partition_2:
mov al, [ebx+0x1be+4+16+16]; get extended partition type
call scan_extended_types
jnz test_ext_partition_3
 
mov eax, [ebx+0x1be+8+16+16]; add relative start
test eax, eax ; is there extended partition?
jnz new_mbr ; yes. read it
 
test_ext_partition_3:
mov al, [ebx+0x1be+4+16+16+16]; get extended partition type
call scan_extended_types
jnz end_partition_chain; no. end chain
 
mov eax, [ebx+0x1be+8+16+16+16]; get start of extended partition
test eax, eax ; is there extended partition?
jnz new_mbr ; yes. read it
 
end_partition_chain:
;mov [partition_count],ecx
 
;cmp edx,-1 ; found wanted partition?
;jnz hd_and_partition_ok ; yes. install it
;jmp problem_partition_or_fat
problem_hd:
or [problem_partition], 2
jmp return_from_part_set
 
 
scan_partition_types:
push ecx
mov edi, partition_types
mov ecx, partition_types_end-partition_types
cld
repne scasb ; is partition type ok?
pop ecx
ret
 
scan_extended_types:
push ecx
mov edi, extended_types
mov ecx, extended_types_end-extended_types
cld
repne scasb ; is it extended partition?
pop ecx
ret
 
problem_fat_dec_count: ; bootsector is missing or another problem
; dec [partition_count] ; remove it from partition_count
 
problem_partition_or_fat:
or [problem_partition], 1
 
return_from_part_set:
popad
;mov [fs_type],0
call free_hd_channel
mov [hd1_status], 0 ; free
ret
 
hd_and_partition_ok:
 
;eax = PARTITION_START edx=PARTITION_LENGTH cl=fs_type
mov [fs_type], cl
;mov eax,edx
mov [PARTITION_START], eax
add edx, eax
dec edx
mov [PARTITION_END], edx
 
; mov edx, [PARTITION_END]
; sub edx, eax
; inc edx ; edx = length of partition § ç¥¬ ®­® ­ ¬??
 
; mov [hd_setup],1
mov ebx, buffer
call hd_read ; read boot sector of partition
cmp [hd_error], 0
jz boot_read_ok
cmp [fs_type], 7
jnz problem_fat_dec_count
; NTFS duplicates bootsector:
; NT4/2k/XP+ saves bootsector copy in the end of disk
; NT 3.51 saves bootsector copy in the middle of disk
and [hd_error], 0
mov eax, [PARTITION_END]
call hd_read
cmp [hd_error], 0
jnz @f
call ntfs_test_bootsec
jnc boot_read_ok
@@:
and [hd_error], 0
mov eax, edx
shr eax, 1
add eax, [PARTITION_START]
call hd_read
cmp [hd_error], 0
jnz problem_fat_dec_count ; no chance...
boot_read_ok:
 
; if we are running on NTFS, check bootsector
 
call ntfs_test_bootsec ; test ntfs
jnc ntfs_setup
 
call ext2_test_superblock ; test ext2fs
jnc ext2_setup
 
mov eax, [PARTITION_START] ;ext2 test changes [buffer]
call hd_read
cmp [hd_error], 0
jnz problem_fat_dec_count
 
push 0
mov eax, [PARTITION_END]
sub eax, [PARTITION_START]
inc eax
push eax
push 0
push [PARTITION_START]
push ebp
push ebp
mov ebp, esp
mov esi, 'old' ; special value: there is no DISK structure
push 1 ; bootsector read successfully
call fat_create_partition
add esp, 4*7
test eax, eax
jz problem_fat_dec_count
mov [fs_dependent_data_start.partition], eax
mov al, [eax+FAT.fs_type]
mov [fs_type], al
 
popad
call free_hd_channel
mov [hd1_status], 0 ; free
ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/fs/iso9660.inc
0,0 → 1,761
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
uglobal
cd_current_pointer_of_input dd 0
cd_current_pointer_of_input_2 dd 0
cd_mem_location dd 0
cd_counter_block dd 0
IDE_Channel_1 db 0
IDE_Channel_2 db 0
endg
 
reserve_cd:
 
cli
cmp [cd_status], 0
je reserve_ok2
 
sti
call change_task
jmp reserve_cd
 
reserve_ok2:
 
push eax
mov eax, [CURRENT_TASK]
shl eax, 5
mov eax, [eax+CURRENT_TASK+TASKDATA.pid]
mov [cd_status], eax
pop eax
sti
ret
 
reserve_cd_channel:
cmp [ChannelNumber], 1
jne .IDE_Channel_2
.IDE_Channel_1:
cli
cmp [IDE_Channel_1], 0
je .reserve_ok_1
sti
call change_task
jmp .IDE_Channel_1
.IDE_Channel_2:
cli
cmp [IDE_Channel_2], 0
je .reserve_ok_2
sti
call change_task
jmp .IDE_Channel_2
.reserve_ok_1:
mov [IDE_Channel_1], 1
sti
ret
.reserve_ok_2:
mov [IDE_Channel_2], 1
sti
ret
 
free_cd_channel:
cmp [ChannelNumber], 1
jne .IDE_Channel_2
.IDE_Channel_1:
mov [IDE_Channel_1], 0
sti
ret
.IDE_Channel_2:
mov [IDE_Channel_2], 0
sti
ret
 
uglobal
cd_status dd 0
endg
 
;----------------------------------------------------------------
;
; fs_CdRead - LFN variant for reading CD disk
;
; esi points to filename /dir1/dir2/.../dirn/file,0
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to read, 0+
; edx mem location to return data
;
; ret ebx = bytes read or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
fs_CdRead:
push edi
cmp byte [esi], 0
jnz @f
.noaccess:
pop edi
.noaccess_2:
or ebx, -1
mov eax, ERROR_ACCESS_DENIED
ret
 
.noaccess_3:
pop eax edx ecx edi
jmp .noaccess_2
 
@@:
call cd_find_lfn
jnc .found
pop edi
cmp [DevErrorCode], 0
jne .noaccess_2
or ebx, -1
mov eax, ERROR_FILE_NOT_FOUND
ret
 
.found:
mov edi, [cd_current_pointer_of_input]
test byte [edi+25], 10b; do not allow read directories
jnz .noaccess
test ebx, ebx
jz .l1
cmp dword [ebx+4], 0
jz @f
xor ebx, ebx
.reteof:
mov eax, 6; end of file
pop edi
ret
@@:
mov ebx, [ebx]
.l1:
push ecx edx
push 0
mov eax, [edi+10] ; ðåàëüíûé ðàçìåð ôàéëîâîé ñåêöèè
sub eax, ebx
jb .eof
cmp eax, ecx
jae @f
mov ecx, eax
mov byte [esp], 6
@@:
mov eax, [edi+2]
mov [CDSectorAddress], eax
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
.new_sector:
test ecx, ecx
jz .done
sub ebx, 2048
jae .next
add ebx, 2048
jnz .incomplete_sector
cmp ecx, 2048
jb .incomplete_sector
; we may read and memmove complete sector
mov [CDDataBuf_pointer], edx
call ReadCDWRetr; ÷èòàåì ñåêòîð ôàéëà
cmp [DevErrorCode], 0
jne .noaccess_3
add edx, 2048
sub ecx, 2048
.next:
inc dword [CDSectorAddress]
jmp .new_sector
.incomplete_sector:
; we must read and memmove incomplete sector
mov [CDDataBuf_pointer], CDDataBuf
call ReadCDWRetr; ÷èòàåì ñåêòîð ôàéëà
cmp [DevErrorCode], 0
jne .noaccess_3
push ecx
add ecx, ebx
cmp ecx, 2048
jbe @f
mov ecx, 2048
@@:
sub ecx, ebx
push edi esi ecx
mov edi, edx
lea esi, [CDDataBuf + ebx]
cld
rep movsb
pop ecx esi edi
add edx, ecx
sub [esp], ecx
pop ecx
xor ebx, ebx
jmp .next
 
.done:
mov ebx, edx
pop eax edx ecx edi
sub ebx, edx
ret
.eof:
mov ebx, edx
pop eax edx ecx
sub ebx, edx
jmp .reteof
 
;----------------------------------------------------------------
;
; fs_CdReadFolder - LFN variant for reading CD disk folder
;
; esi points to filename /dir1/dir2/.../dirn/file,0
; ebx pointer to structure 32-bit number = first wanted block, 0+
; & flags (bitfields)
; flags: bit 0: 0=ANSI names, 1=UNICODE names
; ecx number of blocks to read, 0+
; edx mem location to return data
;
; ret ebx = blocks read or 0xffffffff folder not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
fs_CdReadFolder:
push edi
call cd_find_lfn
jnc .found
pop edi
cmp [DevErrorCode], 0
jne .noaccess_1
or ebx, -1
mov eax, ERROR_FILE_NOT_FOUND
ret
.found:
mov edi, [cd_current_pointer_of_input]
test byte [edi+25], 10b ; do not allow read directories
jnz .found_dir
pop edi
.noaccess_1:
or ebx, -1
mov eax, ERROR_ACCESS_DENIED
ret
.found_dir:
mov eax, [edi+2] ; eax=cluster
mov [CDSectorAddress], eax
mov eax, [edi+10] ; ðàçìåð äèðåêòðîðèè
.doit:
; init header
push eax ecx
mov edi, edx
mov ecx, 32/4
xor eax, eax
rep stosd
pop ecx eax
mov byte [edx], 1 ; version
mov [cd_mem_location], edx
add [cd_mem_location], 32
; íà÷èíàåì ïåðåáðîñêó ÁÄÂÊ â ÓÑÂÊ
;.mainloop:
mov [cd_counter_block], dword 0
dec dword [CDSectorAddress]
push ecx
.read_to_buffer:
inc dword [CDSectorAddress]
mov [CDDataBuf_pointer], CDDataBuf
call ReadCDWRetr ; ÷èòàåì ñåêòîð äèðåêòîðèè
cmp [DevErrorCode], 0
jne .noaccess_1
call .get_names_from_buffer
sub eax, 2048
; äèðåêòîðèÿ çàêîí÷èëàñü?
ja .read_to_buffer
mov edi, [cd_counter_block]
mov [edx+8], edi
mov edi, [ebx]
sub [edx+4], edi
xor eax, eax
dec ecx
js @f
mov al, ERROR_END_OF_FILE
@@:
pop ecx edi
mov ebx, [edx+4]
ret
 
.get_names_from_buffer:
mov [cd_current_pointer_of_input_2], CDDataBuf
push eax esi edi edx
.get_names_from_buffer_1:
call cd_get_name
jc .end_buffer
inc dword [cd_counter_block]
mov eax, [cd_counter_block]
cmp [ebx], eax
jae .get_names_from_buffer_1
test ecx, ecx
jz .get_names_from_buffer_1
mov edi, [cd_counter_block]
mov [edx+4], edi
dec ecx
mov esi, ebp
mov edi, [cd_mem_location]
add edi, 40
test dword [ebx+4], 1; 0=ANSI, 1=UNICODE
jnz .unicode
; jmp .unicode
.ansi:
cmp [cd_counter_block], 2
jbe .ansi_parent_directory
cld
lodsw
xchg ah, al
call uni2ansi_char
cld
stosb
; ïðîâåðêà êîíöà ôàéëà
mov ax, [esi]
cmp ax, word 3B00h; ñåïàðàòîð êîíöà ôàéëà ';'
je .cd_get_parameters_of_file_1
; ïðîâåðêà äëÿ ôàéëîâ íå çàêàí÷èâàþùèõñÿ ñåïàðàòîðîì
movzx eax, byte [ebp-33]
add eax, ebp
sub eax, 34
cmp esi, eax
je .cd_get_parameters_of_file_1
; ïðîâåðêà êîíöà ïàïêè
movzx eax, byte [ebp-1]
add eax, ebp
cmp esi, eax
jb .ansi
.cd_get_parameters_of_file_1:
mov [edi], byte 0
call cd_get_parameters_of_file
add [cd_mem_location], 304
jmp .get_names_from_buffer_1
 
.ansi_parent_directory:
cmp [cd_counter_block], 2
je @f
mov [edi], byte '.'
inc edi
jmp .cd_get_parameters_of_file_1
@@:
mov [edi], word '..'
add edi, 2
jmp .cd_get_parameters_of_file_1
 
.unicode:
cmp [cd_counter_block], 2
jbe .unicode_parent_directory
cld
movsw
; ïðîâåðêà êîíöà ôàéëà
mov ax, [esi]
cmp ax, word 3B00h; ñåïàðàòîð êîíöà ôàéëà ';'
je .cd_get_parameters_of_file_2
; ïðîâåðêà äëÿ ôàéëîâ íå çàêàí÷èâàþùèõñÿ ñåïàðàòîðîì
movzx eax, byte [ebp-33]
add eax, ebp
sub eax, 34
cmp esi, eax
je .cd_get_parameters_of_file_2
; ïðîâåðêà êîíöà ïàïêè
movzx eax, byte [ebp-1]
add eax, ebp
cmp esi, eax
jb .unicode
.cd_get_parameters_of_file_2:
mov [edi], word 0
call cd_get_parameters_of_file
add [cd_mem_location], 560
jmp .get_names_from_buffer_1
 
.unicode_parent_directory:
cmp [cd_counter_block], 2
je @f
mov [edi], word 2E00h; '.'
add edi, 2
jmp .cd_get_parameters_of_file_2
@@:
mov [edi], dword 2E002E00h; '..'
add edi, 4
jmp .cd_get_parameters_of_file_2
 
.end_buffer:
pop edx edi esi eax
ret
 
cd_get_parameters_of_file:
mov edi, [cd_mem_location]
cd_get_parameters_of_file_1:
; ïîëó÷àåì àòðèáóòû ôàéëà
xor eax, eax
; ôàéë íå àðõèâèðîâàëñÿ
inc eax
shl eax, 1
; ýòî êàòàëîã?
test [ebp-8], byte 2
jz .file
inc eax
.file:
; ìåòêà òîìà íå êàê â FAT, â ýòîì âèäå îòñóòñâóåò
; ôàéë íå ÿâëÿåòñÿ ñèñòåìíûì
shl eax, 3
; ôàéë ÿâëÿåòñÿ ñêðûòûì? (àòðèáóò ñóùåñòâîâàíèå)
test [ebp-8], byte 1
jz .hidden
inc eax
.hidden:
shl eax, 1
; ôàéë âñåãäà òîëüêî äëÿ ÷òåíèÿ, òàê êàê ýòî CD
inc eax
mov [edi], eax
; ïîëó÷àåì âðåìÿ äëÿ ôàéëà
;÷àñ
movzx eax, byte [ebp-12]
shl eax, 8
;ìèíóòà
mov al, [ebp-11]
shl eax, 8
;ñåêóíäà
mov al, [ebp-10]
;âðåìÿ ñîçäàíèÿ ôàéëà
mov [edi+8], eax
;âðåìÿ ïîñëåäíåãî äîñòóïà
mov [edi+16], eax
;âðåìÿ ïîñëåäíåé çàïèñè
mov [edi+24], eax
; ïîëó÷àåì äàòó äëÿ ôàéëà
;ãîä
movzx eax, byte [ebp-15]
add eax, 1900
shl eax, 8
;ìåñÿö
mov al, [ebp-14]
shl eax, 8
;äåíü
mov al, [ebp-13]
;äàòà ñîçäàíèÿ ôàéëà
mov [edi+12], eax
;âðåìÿ ïîñëåäíåãî äîñòóïà
mov [edi+20], eax
;âðåìÿ ïîñëåäíåé çàïèñè
mov [edi+28], eax
; ïîëó÷àåì òèï äàííûõ èìåíè
xor eax, eax
test dword [ebx+4], 1; 0=ANSI, 1=UNICODE
jnz .unicode_1
mov [edi+4], eax
jmp @f
.unicode_1:
inc eax
mov [edi+4], eax
@@:
; ïîëó÷àåì ðàçìåð ôàéëà â áàéòàõ
xor eax, eax
mov [edi+32+4], eax
mov eax, [ebp-23]
mov [edi+32], eax
ret
 
;----------------------------------------------------------------
;
; fs_CdGetFileInfo - LFN variant for CD
; get file/directory attributes structure
;
;----------------------------------------------------------------
fs_CdGetFileInfo:
cmp byte [esi], 0
jnz @f
mov eax, 2
ret
@@:
push edi
call cd_find_lfn
pushfd
cmp [DevErrorCode], 0
jz @f
popfd
pop edi
mov eax, 11
ret
@@:
popfd
jnc @f
pop edi
mov eax, ERROR_FILE_NOT_FOUND
ret
@@:
 
mov edi, edx
push ebp
mov ebp, [cd_current_pointer_of_input]
add ebp, 33
call cd_get_parameters_of_file_1
pop ebp
and dword [edi+4], 0
pop edi
xor eax, eax
ret
 
;----------------------------------------------------------------
cd_find_lfn:
mov [cd_appl_data], 0
; in: esi+ebp -> name
; out: CF=1 - file not found
; else CF=0 and [cd_current_pointer_of_input] direntry
push eax esi
; 16 ñåêòîð íà÷àëî íàáîðà äåñêðèïòîðîâ òîìîâ
 
call WaitUnitReady
cmp [DevErrorCode], 0
jne .access_denied
 
call prevent_medium_removal
; òåñòîâîå ÷òåíèå
mov [CDSectorAddress], dword 16
mov [CDDataBuf_pointer], CDDataBuf
call ReadCDWRetr;_1
cmp [DevErrorCode], 0
jne .access_denied
 
; âû÷èñëåíèå ïîñëåäíåé ñåññèè
call WaitUnitReady
cmp [DevErrorCode], 0
jne .access_denied
call Read_TOC
mov ah, [CDDataBuf+4+4]
mov al, [CDDataBuf+4+5]
shl eax, 16
mov ah, [CDDataBuf+4+6]
mov al, [CDDataBuf+4+7]
add eax, 15
mov [CDSectorAddress], eax
; mov [CDSectorAddress],dword 15
mov [CDDataBuf_pointer], CDDataBuf
 
.start:
inc dword [CDSectorAddress]
call ReadCDWRetr;_1
cmp [DevErrorCode], 0
jne .access_denied
 
.start_check:
; ïðîâåðêà íà âøèâîñòü
cmp [CDDataBuf+1], dword 'CD00'
jne .access_denied
cmp [CDDataBuf+5], byte '1'
jne .access_denied
; ñåêòîð ÿâëÿåòñÿ òåðìèíàòîðîì íàáîð äåñêðèïòîðîâ òîìîâ?
cmp [CDDataBuf], byte 0xff
je .access_denied
; ñåêòîð ÿâëÿåòñÿ äîïîëíèòåëüíûì è óëó÷øåííûì äåñêðèïòîðîì òîìà?
cmp [CDDataBuf], byte 0x2
jne .start
; ñåêòîð ÿâëÿåòñÿ äîïîëíèòåëüíûì äåñêðèïòîðîì òîìà?
cmp [CDDataBuf+6], byte 0x1
jne .start
 
; ïàðàìåòðû root äèðåêòðîðèè
mov eax, [CDDataBuf+0x9c+2]; íà÷àëî root äèðåêòðîðèè
mov [CDSectorAddress], eax
mov eax, [CDDataBuf+0x9c+10]; ðàçìåð root äèðåêòðîðèè
cmp byte [esi], 0
jnz @f
mov [cd_current_pointer_of_input], CDDataBuf+0x9c
jmp .done
@@:
; íà÷èíàåì ïîèñê
.mainloop:
dec dword [CDSectorAddress]
.read_to_buffer:
inc dword [CDSectorAddress]
mov [CDDataBuf_pointer], CDDataBuf
call ReadCDWRetr ; ÷èòàåì ñåêòîð äèðåêòîðèè
cmp [DevErrorCode], 0
jne .access_denied
push ebp
call cd_find_name_in_buffer
pop ebp
jnc .found
sub eax, 2048
; äèðåêòîðèÿ çàêîí÷èëàñü?
cmp eax, 0
ja .read_to_buffer
; íåò èñêîìîãî ýëåìåíòà öåïî÷êè
.access_denied:
pop esi eax
mov [cd_appl_data], 1
stc
ret
; èñêîìûé ýëåìåíò öåïî÷êè íàéäåí
.found:
; êîíåö ïóòè ôàéëà
cmp byte [esi-1], 0
jz .done
.nested:
mov eax, [cd_current_pointer_of_input]
push dword [eax+2]
pop dword [CDSectorAddress] ; íà÷àëî äèðåêòîðèè
mov eax, [eax+2+8]; ðàçìåð äèðåêòîðèè
jmp .mainloop
; óêàçàòåëü ôàéëà íàéäåí
.done:
test ebp, ebp
jz @f
mov esi, ebp
xor ebp, ebp
jmp .nested
@@:
pop esi eax
mov [cd_appl_data], 1
clc
ret
 
cd_find_name_in_buffer:
mov [cd_current_pointer_of_input_2], CDDataBuf
.start:
call cd_get_name
jc .not_found
call cd_compare_name
jc .start
.found:
clc
ret
.not_found:
stc
ret
 
cd_get_name:
push eax
mov ebp, [cd_current_pointer_of_input_2]
mov [cd_current_pointer_of_input], ebp
mov eax, [ebp]
test eax, eax ; âõîäû çàêîí÷èëèñü?
jz .next_sector
cmp ebp, CDDataBuf+2048 ; áóôåð çàêîí÷èëñÿ?
jae .next_sector
movzx eax, byte [ebp]
add [cd_current_pointer_of_input_2], eax; ñëåäóþùèé âõîä êàòàëîãà
add ebp, 33; óêàçàòåëü óñòàíîâëåí íà íà÷àëî èìåíè
pop eax
clc
ret
.next_sector:
pop eax
stc
ret
 
cd_compare_name:
; compares ASCIIZ-names, case-insensitive (cp866 encoding)
; in: esi->name, ebp->name
; out: if names match: ZF=1 and esi->next component of name
; else: ZF=0, esi is not changed
; destroys eax
push esi eax edi
mov edi, ebp
.loop:
cld
lodsb
push eax
call char_todown
call ansi2uni_char
xchg ah, al
scasw
pop eax
je .coincides
call char_toupper
call ansi2uni_char
xchg ah, al
sub edi, 2
scasw
jne .name_not_coincide
.coincides:
cmp [esi], byte '/'; ðàçäåëèòåëü ïóòè, êîíåö èìåíè òåêóùåãî ýëåìåíòà
je .done
cmp [esi], byte 0; ðàçäåëèòåëü ïóòè, êîíåö èìåíè òåêóùåãî ýëåìåíòà
je .done
jmp .loop
.name_not_coincide:
pop edi eax esi
stc
ret
.done:
; ïðîâåðêà êîíöà ôàéëà
cmp [edi], word 3B00h; ñåïàðàòîð êîíöà ôàéëà ';'
je .done_1
; ïðîâåðêà äëÿ ôàéëîâ íå çàêàí÷èâàþùèõñÿ ñåïàðàòîðîì
movzx eax, byte [ebp-33]
add eax, ebp
sub eax, 34
cmp edi, eax
je .done_1
; ïðîâåðêà êîíöà ïàïêè
movzx eax, byte [ebp-1]
add eax, ebp
cmp edi, eax
jne .name_not_coincide
.done_1:
pop edi eax
add esp, 4
inc esi
clc
ret
 
char_todown:
; convert character to uppercase, using cp866 encoding
; in: al=symbol
; out: al=converted symbol
cmp al, 'A'
jb .ret
cmp al, 'Z'
jbe .az
cmp al, '€'
jb .ret
cmp al, ''
jb .rus1
cmp al, 'Ÿ'
ja .ret
; 0x90-0x9F -> 0xE0-0xEF
add al, 'à'-''
.ret:
ret
.rus1:
; 0x80-0x8F -> 0xA0-0xAF
.az:
add al, 0x20
ret
 
uni2ansi_char:
; convert UNICODE character in al to ANSI character in ax, using cp866 encoding
; in: ax=UNICODE character
; out: al=converted ANSI character
cmp ax, 0x80
jb .ascii
cmp ax, 0x401
jz .yo1
cmp ax, 0x451
jz .yo2
cmp ax, 0x410
jb .unk
cmp ax, 0x440
jb .rus1
cmp ax, 0x450
jb .rus2
.unk:
mov al, '_'
jmp .doit
.yo1:
mov al, 'ð'
jmp .doit
.yo2:
mov al, 'ñ'
jmp .doit
.rus1:
; 0x410-0x43F -> 0x80-0xAF
add al, 0x70
jmp .doit
.rus2:
; 0x440-0x44F -> 0xE0-0xEF
add al, 0xA0
.ascii:
.doit:
ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/fs/ntfs.inc
0,0 → 1,1829
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
ntfs_test_bootsec:
; in: ebx->buffer, edx=size of partition
; out: CF set <=> invalid
; 1. Name=='NTFS '
cmp dword [ebx+3], 'NTFS'
jnz .no
cmp dword [ebx+7], ' '
jnz .no
; 2. Number of bytes per sector is the same as for physical device
; (that is, 0x200 for hard disk)
cmp word [ebx+11], 0x200
jnz .no
; 3. Number of sectors per cluster must be power of 2
movzx eax, byte [ebx+13]
dec eax
js .no
test al, [ebx+13]
jnz .no
; 4. FAT parameters must be zero
cmp word [ebx+14], 0
jnz .no
cmp dword [ebx+16], 0
jnz .no
cmp byte [ebx+20], 0
jnz .no
cmp word [ebx+22], 0
jnz .no
cmp dword [ebx+32], 0
jnz .no
; 5. Number of sectors <= partition size
cmp dword [ebx+0x2C], 0
ja .no
cmp [ebx+0x28], edx
ja .no
; 6. $MFT and $MFTMirr clusters must be within partition
cmp dword [ebx+0x34], 0
ja .no
push edx
movzx eax, byte [ebx+13]
mul dword [ebx+0x30]
test edx, edx
pop edx
jnz .no
cmp eax, edx
ja .no
cmp dword [ebx+0x3C], 0
ja .no
push edx
movzx eax, byte [ebx+13]
mul dword [ebx+0x38]
test edx, edx
pop edx
jnz .no
cmp eax, edx
ja .no
; 7. Clusters per FRS must be either negative and in [-31,-9] or positive and power of 2
movsx eax, byte [ebx+0x40]
cmp al, -31
jl .no
cmp al, -9
jle @f
dec eax
js .no
test [ebx+0x40], al
jnz .no
@@:
; 8. Same for clusters per IndexAllocationBuffer
movsx eax, byte [ebx+0x44]
cmp al, -31
jl .no
cmp al, -9
jle @f
dec eax
js .no
test [ebx+0x44], al
jnz .no
@@:
; OK, this is correct NTFS bootsector
clc
ret
.no:
; No, this bootsector isn't NTFS
stc
ret
 
ntfs_setup: ; CODE XREF: part_set.inc
; By given bootsector, initialize some NTFS variables
; call ntfs_test_bootsec ; checking boot sector was already
; jc problem_fat_dec_count
movzx eax, byte [ebx+13]
mov [ntfs_data.sectors_per_cluster], eax
mov eax, [ebx+0x28]
add eax, [PARTITION_START]
dec eax
mov [PARTITION_END], eax
mov [fs_type], 1
mov eax, [ebx+0x30]
mov [ntfs_data.mft_cluster], eax
mov eax, [ebx+0x38]
mov [ntfs_data.mftmirr_cluster], eax
movsx eax, byte [ebx+0x40]
test eax, eax
js .1
mul [ntfs_data.sectors_per_cluster]
shl eax, 9
jmp .2
.1:
neg eax
mov ecx, eax
mov eax, 1
shl eax, cl
.2:
mov [ntfs_data.frs_size], eax
movsx eax, byte [ebx+0x44]
test eax, eax
js .3
mul [ntfs_data.sectors_per_cluster]
shl eax, 9
jmp .4
.3:
neg eax
mov ecx, eax
mov eax, 1
shl eax, cl
.4:
mov [ntfs_data.iab_size], eax
; allocate space for buffers
add eax, [ntfs_data.frs_size]
push eax
call kernel_alloc
test eax, eax
jz problem_fat_dec_count
mov [ntfs_data.frs_buffer], eax
add eax, [ntfs_data.frs_size]
mov [ntfs_data.iab_buffer], eax
; read $MFT disposition
mov eax, [ntfs_data.mft_cluster]
mul [ntfs_data.sectors_per_cluster]
call ntfs_read_frs_sector
cmp [hd_error], 0
jnz .usemirr
cmp dword [ebx], 'FILE'
jnz .usemirr
call ntfs_restore_usa_frs
jnc .mftok
.usemirr:
and [hd_error], 0
mov eax, [ntfs_data.mftmirr_cluster]
mul [ntfs_data.sectors_per_cluster]
call ntfs_read_frs_sector
cmp [hd_error], 0
jnz @f
cmp dword [ebx], 'FILE'
jnz @f
call ntfs_restore_usa_frs
jnc .mftok
@@:
; $MFT and $MFTMirr invalid!
.fail_free_frs:
push [ntfs_data.frs_buffer]
call kernel_free
jmp problem_fat_dec_count
.fail_free_mft:
push [ntfs_data.mft_retrieval]
call kernel_free
jmp .fail_free_frs
.mftok:
; read $MFT table retrieval information
; start with one page, increase if not enough (when MFT too fragmented)
push ebx
push 0x1000
call kernel_alloc
pop ebx
test eax, eax
jz .fail_free_frs
mov [ntfs_data.mft_retrieval], eax
and [ntfs_data.mft_retrieval_size], 0
mov [ntfs_data.mft_retrieval_alloc], 0x1000/8
; $MFT base record must contain unnamed non-resident $DATA attribute
movzx eax, word [ebx+14h]
add eax, ebx
.scandata:
cmp dword [eax], -1
jz .fail_free_mft
cmp dword [eax], 0x80
jnz @f
cmp byte [eax+9], 0
jz .founddata
@@:
add eax, [eax+4]
jmp .scandata
.founddata:
cmp byte [eax+8], 0
jz .fail_free_mft
; load first portion of $DATA attribute retrieval information
mov edx, [eax+0x18]
mov [ntfs_data.mft_retrieval_end], edx
mov esi, eax
movzx eax, word [eax+0x20]
add esi, eax
sub esp, 10h
.scanmcb:
call ntfs_decode_mcb_entry
jnc .scanmcbend
call .get_mft_retrieval_ptr
mov edx, [esp] ; block length
mov [eax], edx
mov edx, [esp+8] ; block addr (relative)
mov [eax+4], edx
inc [ntfs_data.mft_retrieval_size]
jmp .scanmcb
.scanmcbend:
add esp, 10h
; there may be other portions of $DATA attribute in auxiliary records;
; if they will be needed, they will be loaded later
 
mov [ntfs_data.cur_index_size], 0x1000/0x200
push 0x1000
call kernel_alloc
test eax, eax
jz .fail_free_mft
mov [ntfs_data.cur_index_buf], eax
 
popad
call free_hd_channel
and [hd1_status], 0
ret
 
.get_mft_retrieval_ptr:
pushad
mov eax, [ntfs_data.mft_retrieval_size]
cmp eax, [ntfs_data.mft_retrieval_alloc]
jnz .ok
add eax, 0x1000/8
mov [ntfs_data.mft_retrieval_alloc], eax
shl eax, 3
push eax
call kernel_alloc
test eax, eax
jnz @f
popad
add esp, 14h
jmp .fail_free_mft
@@:
mov esi, [ntfs_data.mft_retrieval]
mov edi, eax
mov ecx, [ntfs_data.mft_retrieval_size]
add ecx, ecx
rep movsd
push [ntfs_data.mft_retrieval]
mov [ntfs_data.mft_retrieval], eax
call kernel_free
mov eax, [ntfs_data.mft_retrieval_size]
.ok:
shl eax, 3
add eax, [ntfs_data.mft_retrieval]
mov [esp+28], eax
popad
ret
 
ntfs_read_frs_sector:
push eax ecx
add eax, [PARTITION_START]
mov ecx, [ntfs_data.frs_size]
shr ecx, 9
mov ebx, [ntfs_data.frs_buffer]
push ebx
@@:
call hd_read
cmp [hd_error], 0
jnz .fail
add ebx, 0x200
inc eax
loop @b
.fail:
pop ebx
pop ecx eax
ret
 
uglobal
align 4
ntfs_cur_attr dd ?
ntfs_cur_iRecord dd ?
ntfs_cur_offs dd ? ; in sectors
ntfs_cur_size dd ? ; in sectors
ntfs_cur_buf dd ?
ntfs_cur_read dd ? ; [output]
ntfs_bCanContinue db ?
rb 3
 
ntfs_attrlist_buf rb 0x400
ntfs_attrlist_mft_buf rb 0x400
ntfs_bitmap_buf rb 0x400
 
ntfs_attr_iRecord dd ?
ntfs_attr_iBaseRecord dd ?
ntfs_attr_offs dd ?
ntfs_attr_list dd ?
ntfs_attr_size dq ?
ntfs_cur_tail dd ?
endg
 
ntfs_read_attr:
; in: global variables
; out: [ntfs_cur_read]
pushad
and [ntfs_cur_read], 0
cmp [ntfs_cur_iRecord], 0
jnz .nomft
cmp [ntfs_cur_attr], 0x80
jnz .nomft
mov eax, [ntfs_data.mft_retrieval_end]
inc eax
mul [ntfs_data.sectors_per_cluster]
cmp eax, [ntfs_cur_offs]
jbe .nomft
; precalculated part of $Mft $DATA
mov esi, [ntfs_data.mft_retrieval]
mov eax, [ntfs_cur_offs]
xor edx, edx
div [ntfs_data.sectors_per_cluster]
; eax = VCN, edx = offset in sectors from beginning of cluster
xor ecx, ecx ; ecx will contain LCN
.mftscan:
add ecx, [esi+4]
sub eax, [esi]
jb @f
add esi, 8
push eax
mov eax, [ntfs_data.mft_retrieval_end]
shl eax, 3
add eax, [ntfs_data.mft_retrieval]
cmp eax, esi
pop eax
jnz .mftscan
jmp .nomft
@@:
push ecx
add ecx, eax
add ecx, [esi]
push eax
push edx
mov eax, [ntfs_data.sectors_per_cluster]
mul ecx
; eax = sector on partition
add eax, [PARTITION_START]
pop edx
add eax, edx
mov ebx, [ntfs_cur_buf]
pop ecx
neg ecx
imul ecx, [ntfs_data.sectors_per_cluster]
sub ecx, edx
cmp ecx, [ntfs_cur_size]
jb @f
mov ecx, [ntfs_cur_size]
@@:
; ecx = number of sequential sectors to read
call hd_read
cmp [hd_error], 0
jnz .errread
add [ntfs_cur_read], 0x200
dec [ntfs_cur_size]
inc [ntfs_cur_offs]
add ebx, 0x200
mov [ntfs_cur_buf], ebx
inc eax
loop @b
pop ecx
xor eax, eax
xor edx, edx
cmp [ntfs_cur_size], eax
jz @f
add esi, 8
push eax
mov eax, [ntfs_data.mft_retrieval_end]
shl eax, 3
add eax, [ntfs_data.mft_retrieval]
cmp eax, esi
pop eax
jz .nomft
jmp .mftscan
@@:
popad
ret
.errread:
pop ecx
.errret:
stc
popad
ret
.nomft:
; 1. Read file record.
; N.B. This will do recursive call of read_attr for $MFT::$Data.
mov eax, [ntfs_cur_iRecord]
mov [ntfs_attr_iRecord], eax
and [ntfs_attr_list], 0
or dword [ntfs_attr_size], -1
or dword [ntfs_attr_size+4], -1
or [ntfs_attr_iBaseRecord], -1
call ntfs_read_file_record
test eax, eax
jz .errret
; 2. Find required attribute.
mov eax, [ntfs_data.frs_buffer]
; a) For auxiliary records, read base record
; N.B. If base record is present,
; base iRecord may be 0 (for $Mft), but SequenceNumber is nonzero
cmp dword [eax+24h], 0
jz @f
mov eax, [eax+20h]
; test eax, eax
; jz @f
.beginfindattr:
mov [ntfs_attr_iRecord], eax
call ntfs_read_file_record
test eax, eax
jz .errret
@@:
; b) Scan for required attribute and for $ATTR_LIST
mov eax, [ntfs_data.frs_buffer]
movzx ecx, word [eax+14h]
add eax, ecx
mov ecx, [ntfs_cur_attr]
and [ntfs_attr_offs], 0
.scanattr:
cmp dword [eax], -1
jz .scandone
cmp dword [eax], ecx
jz .okattr
cmp [ntfs_attr_iBaseRecord], -1
jnz .scancont
cmp dword [eax], 0x20 ; $ATTR_LIST
jnz .scancont
mov [ntfs_attr_list], eax
jmp .scancont
.okattr:
; ignore named $DATA attributes (aka NTFS streams)
cmp ecx, 0x80
jnz @f
cmp byte [eax+9], 0
jnz .scancont
@@:
mov [ntfs_attr_offs], eax
.scancont:
add eax, [eax+4]
jmp .scanattr
.continue:
pushad
and [ntfs_cur_read], 0
.scandone:
; c) Check for required offset and length
mov ecx, [ntfs_attr_offs]
jecxz .noattr
push [ntfs_cur_size]
push [ntfs_cur_read]
call .doreadattr
pop edx
pop eax
jc @f
cmp [ntfs_bCanContinue], 0
jz @f
sub edx, [ntfs_cur_read]
neg edx
shr edx, 9
sub eax, edx
mov [ntfs_cur_size], eax
jnz .not_in_cur
@@:
popad
ret
.noattr:
.not_in_cur:
cmp [ntfs_cur_attr], 0x20
jz @f
mov ecx, [ntfs_attr_list]
test ecx, ecx
jnz .lookattr
.ret_is_attr:
cmp [ntfs_attr_offs], 1 ; CF set <=> ntfs_attr_offs == 0
popad
ret
.lookattr:
; required attribute or required offset was not found in base record;
; it may be present in auxiliary records;
; scan $ATTR_LIST
mov eax, [ntfs_attr_iBaseRecord]
cmp eax, -1
jz @f
call ntfs_read_file_record
test eax, eax
jz .errret
or [ntfs_attr_iBaseRecord], -1
@@:
push [ntfs_cur_offs]
push [ntfs_cur_size]
push [ntfs_cur_read]
push [ntfs_cur_buf]
push dword [ntfs_attr_size]
push dword [ntfs_attr_size+4]
or dword [ntfs_attr_size], -1
or dword [ntfs_attr_size+4], -1
and [ntfs_cur_offs], 0
mov [ntfs_cur_size], 2
and [ntfs_cur_read], 0
mov eax, ntfs_attrlist_buf
cmp [ntfs_cur_iRecord], 0
jnz @f
mov eax, ntfs_attrlist_mft_buf
@@:
mov [ntfs_cur_buf], eax
push eax
call .doreadattr
pop esi
mov edx, 1
pop dword [ntfs_attr_size+4]
pop dword [ntfs_attr_size]
mov ebp, [ntfs_cur_read]
pop [ntfs_cur_buf]
pop [ntfs_cur_read]
pop [ntfs_cur_size]
pop [ntfs_cur_offs]
jc .errret
or edi, -1
lea ebp, [ebp+esi-1Ah]
.scanliststart:
mov eax, [ntfs_cur_attr]
.scanlist:
cmp esi, ebp
jae .scanlistdone
cmp eax, [esi]
jz @f
.scanlistcont:
movzx ecx, word [esi+4]
add esi, ecx
jmp .scanlist
@@:
; ignore named $DATA attributes (aka NTFS streams)
cmp eax, 0x80
jnz @f
cmp byte [esi+6], 0
jnz .scanlistcont
@@:
push eax
mov eax, [esi+8]
test eax, eax
jnz .testf
mov eax, dword [ntfs_attr_size]
and eax, dword [ntfs_attr_size+4]
cmp eax, -1
jnz .testfz
; if attribute is in auxiliary records, its size is defined only in first
mov eax, [esi+10h]
call ntfs_read_file_record
test eax, eax
jnz @f
.errret_pop:
pop eax
jmp .errret
@@:
mov eax, [ntfs_data.frs_buffer]
movzx ecx, word [eax+14h]
add eax, ecx
mov ecx, [ntfs_cur_attr]
@@:
cmp dword [eax], -1
jz .errret_pop
cmp dword [eax], ecx
jz @f
.l1:
add eax, [eax+4]
jmp @b
@@:
cmp eax, 0x80
jnz @f
cmp byte [eax+9], 0
jnz .l1
@@:
cmp byte [eax+8], 0
jnz .sdnores
mov eax, [eax+10h]
mov dword [ntfs_attr_size], eax
and dword [ntfs_attr_size+4], 0
jmp .testfz
.sdnores:
mov ecx, [eax+30h]
mov dword [ntfs_attr_size], ecx
mov ecx, [eax+34h]
mov dword [ntfs_attr_size+4], ecx
.testfz:
xor eax, eax
.testf:
imul eax, [ntfs_data.sectors_per_cluster]
cmp eax, [ntfs_cur_offs]
pop eax
ja @f
mov edi, [esi+10h] ; keep previous iRecord
jmp .scanlistcont
@@:
.scanlistfound:
cmp edi, -1
jnz @f
popad
ret
@@:
mov eax, [ntfs_cur_iRecord]
mov [ntfs_attr_iBaseRecord], eax
mov eax, edi
jmp .beginfindattr
.sde:
popad
stc
ret
.scanlistdone:
sub ebp, ntfs_attrlist_buf-1Ah
cmp [ntfs_cur_iRecord], 0
jnz @f
sub ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf
@@:
cmp ebp, 0x400
jnz .scanlistfound
inc edx
push esi edi
mov esi, ntfs_attrlist_buf+0x200
mov edi, ntfs_attrlist_buf
cmp [ntfs_cur_iRecord], 0
jnz @f
mov esi, ntfs_attrlist_mft_buf+0x200
mov edi, ntfs_attrlist_mft_buf
@@:
mov ecx, 0x200/4
rep movsd
mov eax, edi
pop edi esi
sub esi, 0x200
push [ntfs_cur_offs]
push [ntfs_cur_size]
push [ntfs_cur_read]
push [ntfs_cur_buf]
push dword [ntfs_attr_size]
push dword [ntfs_attr_size+4]
or dword [ntfs_attr_size], -1
or dword [ntfs_attr_size+4], -1
mov [ntfs_cur_offs], edx
mov [ntfs_cur_size], 1
and [ntfs_cur_read], 0
mov [ntfs_cur_buf], eax
mov ecx, [ntfs_attr_list]
push esi edx
call .doreadattr
pop edx esi
mov ebp, [ntfs_cur_read]
pop dword [ntfs_attr_size+4]
pop dword [ntfs_attr_size]
pop [ntfs_cur_buf]
pop [ntfs_cur_read]
pop [ntfs_cur_size]
pop [ntfs_cur_offs]
jc .errret
add ebp, ntfs_attrlist_buf+0x200-0x1A
cmp [ntfs_cur_iRecord], 0
jnz .scanliststart
add ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf
jmp .scanliststart
 
.doreadattr:
mov [ntfs_bCanContinue], 0
cmp byte [ecx+8], 0
jnz .nonresident
mov eax, [ecx+10h] ; length
mov esi, eax
mov edx, [ntfs_cur_offs]
shr eax, 9
cmp eax, edx
jb .okret
shl edx, 9
sub esi, edx
movzx eax, word [ecx+14h]
add edx, eax
add edx, ecx ; edx -> data
mov eax, [ntfs_cur_size]
cmp eax, (0xFFFFFFFF shr 9)+1
jbe @f
mov eax, (0xFFFFFFFF shr 9)+1
@@:
shl eax, 9
cmp eax, esi
jbe @f
mov eax, esi
@@:
; eax = length, edx -> data
mov [ntfs_cur_read], eax
mov ecx, eax
mov eax, edx
mov ebx, [ntfs_cur_buf]
call memmove
and [ntfs_cur_size], 0 ; CF=0
ret
.nonresident:
; Not all auxiliary records contain correct FileSize info
mov eax, dword [ntfs_attr_size]
mov edx, dword [ntfs_attr_size+4]
push eax
and eax, edx
cmp eax, -1
pop eax
jnz @f
mov eax, [ecx+30h] ; FileSize
mov edx, [ecx+34h]
mov dword [ntfs_attr_size], eax
mov dword [ntfs_attr_size+4], edx
@@:
add eax, 0x1FF
adc edx, 0
shrd eax, edx, 9
sub eax, [ntfs_cur_offs]
ja @f
; return with nothing read
and [ntfs_cur_size], 0
.okret:
clc
ret
@@:
; reduce read length
and [ntfs_cur_tail], 0
cmp [ntfs_cur_size], eax
jb @f
mov [ntfs_cur_size], eax
mov eax, dword [ntfs_attr_size]
and eax, 0x1FF
mov [ntfs_cur_tail], eax
@@:
cmp [ntfs_cur_size], 0
jz .okret
mov eax, [ntfs_cur_offs]
xor edx, edx
div [ntfs_data.sectors_per_cluster]
sub eax, [ecx+10h] ; first_vbo
jb .okret
; eax = cluster, edx = starting sector
sub esp, 10h
movzx esi, word [ecx+20h] ; mcb_info_ofs
add esi, ecx
xor ebp, ebp
.readloop:
call ntfs_decode_mcb_entry
jnc .break
add ebp, [esp+8]
sub eax, [esp]
jae .readloop
push ecx
push eax
add eax, [esp+8]
add eax, ebp
imul eax, [ntfs_data.sectors_per_cluster]
add eax, edx
add eax, [PARTITION_START]
pop ecx
neg ecx
imul ecx, [ntfs_data.sectors_per_cluster]
sub ecx, edx
cmp ecx, [ntfs_cur_size]
jb @f
mov ecx, [ntfs_cur_size]
@@:
mov ebx, [ntfs_cur_buf]
@@:
call hd_read
cmp [hd_error], 0
jnz .errread2
add ebx, 0x200
mov [ntfs_cur_buf], ebx
inc eax
add [ntfs_cur_read], 0x200
dec [ntfs_cur_size]
inc [ntfs_cur_offs]
loop @b
pop ecx
xor eax, eax
xor edx, edx
cmp [ntfs_cur_size], 0
jnz .readloop
add esp, 10h
mov eax, [ntfs_cur_tail]
test eax, eax
jz @f
sub eax, 0x200
add [ntfs_cur_read], eax
@@:
clc
ret
.errread2:
pop ecx
add esp, 10h
stc
ret
.break:
add esp, 10h ; CF=0
mov [ntfs_bCanContinue], 1
ret
 
ntfs_read_file_record:
; in: eax=iRecord
; out: [ntfs_data.frs_buffer] contains information
; eax=0 - failed, eax=1 - success
; Read attr $DATA of $Mft, starting from eax*[ntfs_data.frs_size]
push ecx edx
mov ecx, [ntfs_data.frs_size]
mul ecx
shrd eax, edx, 9
shr edx, 9
jnz .err
push [ntfs_attr_iRecord]
push [ntfs_attr_iBaseRecord]
push [ntfs_attr_offs]
push [ntfs_attr_list]
push dword [ntfs_attr_size+4]
push dword [ntfs_attr_size]
push [ntfs_cur_iRecord]
push [ntfs_cur_attr]
push [ntfs_cur_offs]
push [ntfs_cur_size]
push [ntfs_cur_buf]
push [ntfs_cur_read]
mov [ntfs_cur_attr], 0x80 ; $DATA
and [ntfs_cur_iRecord], 0 ; $Mft
mov [ntfs_cur_offs], eax
shr ecx, 9
mov [ntfs_cur_size], ecx
mov eax, [ntfs_data.frs_buffer]
mov [ntfs_cur_buf], eax
call ntfs_read_attr
mov eax, [ntfs_cur_read]
pop [ntfs_cur_read]
pop [ntfs_cur_buf]
pop [ntfs_cur_size]
pop [ntfs_cur_offs]
pop [ntfs_cur_attr]
pop [ntfs_cur_iRecord]
pop dword [ntfs_attr_size]
pop dword [ntfs_attr_size+4]
pop [ntfs_attr_list]
pop [ntfs_attr_offs]
pop [ntfs_attr_iBaseRecord]
pop [ntfs_attr_iRecord]
pop edx ecx
jc .errret
cmp eax, [ntfs_data.frs_size]
jnz .errret
mov eax, [ntfs_data.frs_buffer]
cmp dword [eax], 'FILE'
jnz .errret
push ebx
mov ebx, eax
call ntfs_restore_usa_frs
pop ebx
setnc al
movzx eax, al
.ret:
ret
.err:
pop edx ecx
.errret:
xor eax, eax
ret
 
ntfs_restore_usa_frs:
mov eax, [ntfs_data.frs_size]
ntfs_restore_usa:
pushad
shr eax, 9
mov ecx, eax
inc eax
cmp [ebx+6], ax
jnz .err
movzx eax, word [ebx+4]
lea esi, [eax+ebx]
lodsw
mov edx, eax
lea edi, [ebx+0x1FE]
@@:
cmp [edi], dx
jnz .err
lodsw
stosw
add edi, 0x1FE
loop @b
popad
clc
ret
.err:
popad
stc
ret
 
ntfs_decode_mcb_entry:
push eax ecx edi
lea edi, [esp+16]
xor eax, eax
lodsb
test al, al
jz .end
mov ecx, eax
and ecx, 0xF
cmp ecx, 8
ja .end
push ecx
rep movsb
pop ecx
sub ecx, 8
neg ecx
cmp byte [esi-1], 80h
jae .end
push eax
xor eax, eax
rep stosb
pop ecx
shr ecx, 4
cmp ecx, 8
ja .end
push ecx
rep movsb
pop ecx
sub ecx, 8
neg ecx
cmp byte [esi-1], 80h
cmc
sbb eax, eax
rep stosb
stc
.end:
pop edi ecx eax
ret
 
unichar_toupper:
push eax
call uni2ansi_char
cmp al, '_'
jz .unk
add esp, 4
call char_toupper
jmp ansi2uni_char
.unk:
pop eax
ret
 
ntfs_find_lfn:
; in: esi+ebp -> name
; out: CF=1 - file not found
; else CF=0, [ntfs_cur_iRecord] valid, eax->record in parent directory
mov [ntfs_cur_iRecord], 5 ; start parse from root cluster
.doit2:
mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT
and [ntfs_cur_offs], 0
mov eax, [ntfs_data.cur_index_size]
mov [ntfs_cur_size], eax
mov eax, [ntfs_data.cur_index_buf]
mov [ntfs_cur_buf], eax
call ntfs_read_attr
jnc @f
.ret:
ret
@@:
cmp [ntfs_cur_read], 0x20
jc .ret
pushad
mov esi, [ntfs_data.cur_index_buf]
mov eax, [esi+14h]
add eax, 10h
cmp [ntfs_cur_read], eax
jae .readok1
add eax, 1FFh
shr eax, 9
cmp eax, [ntfs_data.cur_index_size]
ja @f
.stc_ret:
popad
stc
ret
@@:
; reallocate
push eax
push [ntfs_data.cur_index_buf]
call kernel_free
pop eax
mov [ntfs_data.cur_index_size], eax
push eax
call kernel_alloc
test eax, eax
jnz @f
and [ntfs_data.cur_index_size], 0
and [ntfs_data.cur_index_buf], 0
jmp .stc_ret
@@:
mov [ntfs_data.cur_index_buf], eax
popad
jmp .doit2
.readok1:
mov ebp, [esi+8] ; subnode_size
shr ebp, 9
cmp ebp, [ntfs_data.cur_index_size]
jbe .ok2
push esi ebp
push ebp
call kernel_alloc
pop ebp esi
test eax, eax
jz .stc_ret
mov edi, eax
mov ecx, [ntfs_data.cur_index_size]
shl ecx, 9-2
rep movsd
mov esi, eax
mov [ntfs_data.cur_index_size], ebp
push esi ebp
push [ntfs_data.cur_index_buf]
call kernel_free
pop ebp esi
mov [ntfs_data.cur_index_buf], esi
.ok2:
add esi, 10h
mov edi, [esp+4]
; edi -> name, esi -> current index data, ebp = subnode size
.scanloop:
add esi, [esi]
.scanloopint:
test byte [esi+0Ch], 2
jnz .subnode
push esi
add esi, 0x52
movzx ecx, byte [esi-2]
push edi
@@:
lodsw
call unichar_toupper
push eax
mov al, [edi]
inc edi
cmp al, '/'
jz .slash
call char_toupper
call ansi2uni_char
cmp ax, [esp]
pop eax
loopz @b
jz .found
pop edi
pop esi
jb .subnode
.scanloopcont:
movzx eax, word [esi+8]
add esi, eax
jmp .scanloopint
.slash:
pop eax
pop edi
pop esi
.subnode:
test byte [esi+0Ch], 1
jz .notfound
movzx eax, word [esi+8]
mov eax, [esi+eax-8]
mul [ntfs_data.sectors_per_cluster]
mov [ntfs_cur_offs], eax
mov [ntfs_cur_attr], 0xA0 ; $INDEX_ALLOCATION
mov [ntfs_cur_size], ebp
mov eax, [ntfs_data.cur_index_buf]
mov esi, eax
mov [ntfs_cur_buf], eax
call ntfs_read_attr
mov eax, ebp
shl eax, 9
cmp [ntfs_cur_read], eax
jnz .notfound
cmp dword [esi], 'INDX'
jnz .notfound
mov ebx, esi
call ntfs_restore_usa
jc .notfound
add esi, 0x18
jmp .scanloop
.notfound:
popad
stc
ret
.found:
cmp byte [edi], 0
jz .done
cmp byte [edi], '/'
jz .next
pop edi
pop esi
jmp .scanloopcont
.done:
.next:
pop esi
pop esi
mov eax, [esi]
mov [ntfs_cur_iRecord], eax
mov [esp+1Ch], esi
mov [esp+4], edi
popad
inc esi
cmp byte [esi-1], 0
jnz .doit2
test ebp, ebp
jz @f
mov esi, ebp
xor ebp, ebp
jmp .doit2
@@:
ret
 
;----------------------------------------------------------------
;
; ntfs_HdRead - read NTFS hard disk
;
; esi points to filename
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to read, 0+
; edx mem location to return data
;
; ret ebx = bytes read or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
ntfs_HdRead:
cmp byte [esi], 0
jnz @f
or ebx, -1
push ERROR_ACCESS_DENIED
pop eax
ret
@@:
call ntfs_find_lfn
jnc .found
or ebx, -1
push ERROR_FILE_NOT_FOUND
pop eax
ret
.found:
mov [ntfs_cur_attr], 0x80 ; $DATA
and [ntfs_cur_offs], 0
and [ntfs_cur_size], 0
call ntfs_read_attr
jnc @f
or ebx, -1
push ERROR_ACCESS_DENIED
pop eax
ret
@@:
pushad
and dword [esp+10h], 0
xor eax, eax
test ebx, ebx
jz .zero1
cmp dword [ebx+4], 0x200
jb @f
.eof0:
popad
xor ebx, ebx
.eof:
push ERROR_END_OF_FILE
pop eax
ret
@@:
mov eax, [ebx]
test eax, 0x1FF
jz .alignedstart
push edx
mov edx, [ebx+4]
shrd eax, edx, 9
pop edx
mov [ntfs_cur_offs], eax
mov [ntfs_cur_size], 1
mov [ntfs_cur_buf], ntfs_bitmap_buf
call ntfs_read_attr.continue
mov eax, [ebx]
and eax, 0x1FF
lea esi, [ntfs_bitmap_buf+eax]
sub eax, [ntfs_cur_read]
jae .eof0
neg eax
push ecx
cmp ecx, eax
jb @f
mov ecx, eax
@@:
mov [esp+10h+4], ecx
mov edi, edx
rep movsb
mov edx, edi
pop ecx
sub ecx, [esp+10h]
jnz @f
.retok:
popad
xor eax, eax
ret
@@:
cmp [ntfs_cur_read], 0x200
jz .alignedstart
.eof_ebx:
popad
jmp .eof
.alignedstart:
mov eax, [ebx]
push edx
mov edx, [ebx+4]
add eax, 511
adc edx, 0
shrd eax, edx, 9
pop edx
.zero1:
mov [ntfs_cur_offs], eax
mov [ntfs_cur_buf], edx
mov eax, ecx
shr eax, 9
mov [ntfs_cur_size], eax
add eax, [ntfs_cur_offs]
push eax
call ntfs_read_attr.continue
pop [ntfs_cur_offs]
mov eax, [ntfs_cur_read]
add [esp+10h], eax
mov eax, ecx
and eax, not 0x1FF
cmp [ntfs_cur_read], eax
jnz .eof_ebx
and ecx, 0x1FF
jz .retok
add edx, [ntfs_cur_read]
mov [ntfs_cur_size], 1
mov [ntfs_cur_buf], ntfs_bitmap_buf
call ntfs_read_attr.continue
cmp [ntfs_cur_read], ecx
jb @f
mov [ntfs_cur_read], ecx
@@:
xchg ecx, [ntfs_cur_read]
push ecx
mov edi, edx
mov esi, ntfs_bitmap_buf
add [esp+10h+4], ecx
rep movsb
pop ecx
xor eax, eax
cmp ecx, [ntfs_cur_read]
jz @f
mov al, ERROR_END_OF_FILE
@@:
mov [esp+1Ch], eax
popad
ret
 
;----------------------------------------------------------------
;
; ntfs_HdReadFolder - read NTFS hard disk folder
;
; esi points to filename
; ebx pointer to structure 32-bit number = first wanted block, 0+
; & flags (bitfields)
; flags: bit 0: 0=ANSI names, 1=UNICODE names
; ecx number of blocks to read, 0+
; edx mem location to return data
;
; ret ebx = blocks read or 0xffffffff folder not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
ntfs_HdReadFolder:
mov eax, 5 ; root cluster
cmp byte [esi], 0
jz .doit
call ntfs_find_lfn
jnc .doit2
.notfound:
or ebx, -1
push ERROR_FILE_NOT_FOUND
.pop_ret:
pop eax
ret
.doit:
mov [ntfs_cur_iRecord], eax
.doit2:
mov [ntfs_cur_attr], 0x10 ; $STANDARD_INFORMATION
and [ntfs_cur_offs], 0
mov [ntfs_cur_size], 1
mov [ntfs_cur_buf], ntfs_bitmap_buf
call ntfs_read_attr
jc .notfound
mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT
and [ntfs_cur_offs], 0
mov eax, [ntfs_data.cur_index_size]
mov [ntfs_cur_size], eax
mov eax, [ntfs_data.cur_index_buf]
mov [ntfs_cur_buf], eax
call ntfs_read_attr
jnc .ok
cmp [hd_error], 0
jz .notfound
or ebx, -1
push 11
jmp .pop_ret
.ok:
cmp [ntfs_cur_read], 0x20
jae @f
or ebx, -1
.fserr:
push ERROR_FAT_TABLE
jmp .pop_ret
@@:
pushad
mov esi, [ntfs_data.cur_index_buf]
mov eax, [esi+14h]
add eax, 10h
cmp [ntfs_cur_read], eax
jae .readok1
add eax, 1FFh
shr eax, 9
cmp eax, [ntfs_data.cur_index_size]
ja @f
popad
jmp .fserr
@@:
; reallocate
push eax
push [ntfs_data.cur_index_buf]
call kernel_free
pop eax
mov [ntfs_data.cur_index_size], eax
push eax
call kernel_alloc
test eax, eax
jnz @f
and [ntfs_data.cur_index_size], 0
and [ntfs_data.cur_index_buf], 0
.nomem:
popad
or ebx, -1
push 12
pop eax
ret
@@:
mov [ntfs_data.cur_index_buf], eax
popad
jmp .doit2
.readok1:
mov ebp, [esi+8] ; subnode_size
shr ebp, 9
cmp ebp, [ntfs_data.cur_index_size]
jbe .ok2
push esi ebp
push ebp
call kernel_alloc
pop ebp esi
test eax, eax
jz .nomem
mov edi, eax
mov ecx, [ntfs_data.cur_index_size]
shl ecx, 9-2
rep movsd
mov esi, eax
mov [ntfs_data.cur_index_size], ebp
push esi ebp
push [ntfs_data.cur_index_buf]
call kernel_free
pop ebp esi
mov [ntfs_data.cur_index_buf], esi
.ok2:
add esi, 10h
mov ebx, [esp+10h]
mov edx, [esp+14h]
push dword [ebx+4] ; read ANSI/UNICODE name
mov ebx, [ebx]
; init header
mov edi, edx
mov ecx, 32/4
xor eax, eax
rep stosd
mov byte [edx], 1 ; version
mov ecx, [esp+4+18h]
push edx
mov edx, esp
; edi -> BDFE, esi -> current index data, ebp = subnode size, ebx = first wanted block,
; ecx = number of blocks to read
; edx -> parameters block: dd <output>, dd <flags>
cmp [ntfs_cur_iRecord], 5
jz .skip_specials
; dot and dotdot entries
push esi
xor esi, esi
call .add_special_entry
inc esi
call .add_special_entry
pop esi
.skip_specials:
; at first, dump index root
add esi, [esi]
.dump_root:
test byte [esi+0Ch], 2
jnz .dump_root_done
call .add_entry
movzx eax, word [esi+8]
add esi, eax
jmp .dump_root
.dump_root_done:
; now dump all subnodes
push ecx edi
mov edi, ntfs_bitmap_buf
mov [ntfs_cur_buf], edi
mov ecx, 0x400/4
xor eax, eax
rep stosd
mov [ntfs_cur_attr], 0xB0 ; $BITMAP
and [ntfs_cur_offs], 0
mov [ntfs_cur_size], 2
call ntfs_read_attr
pop edi ecx
push 0 ; save offset in $BITMAP attribute
and [ntfs_cur_offs], 0
.dumploop:
mov [ntfs_cur_attr], 0xA0
mov [ntfs_cur_size], ebp
mov eax, [ntfs_data.cur_index_buf]
mov esi, eax
mov [ntfs_cur_buf], eax
push [ntfs_cur_offs]
mov eax, [ntfs_cur_offs]
imul eax, ebp
mov [ntfs_cur_offs], eax
call ntfs_read_attr
pop [ntfs_cur_offs]
mov eax, ebp
shl eax, 9
cmp [ntfs_cur_read], eax
jnz .done
push eax
mov eax, [ntfs_cur_offs]
and eax, 0x400*8-1
bt dword [ntfs_bitmap_buf], eax
pop eax
jnc .dump_subnode_done
cmp dword [esi], 'INDX'
jnz .dump_subnode_done
push ebx
mov ebx, esi
call ntfs_restore_usa
pop ebx
jc .dump_subnode_done
add esi, 0x18
add esi, [esi]
.dump_subnode:
test byte [esi+0Ch], 2
jnz .dump_subnode_done
call .add_entry
movzx eax, word [esi+8]
add esi, eax
jmp .dump_subnode
.dump_subnode_done:
inc [ntfs_cur_offs]
test [ntfs_cur_offs], 0x400*8-1
jnz .dumploop
mov [ntfs_cur_attr], 0xB0
push ecx edi
mov edi, ntfs_bitmap_buf
mov [ntfs_cur_buf], edi
mov ecx, 0x400/4
xor eax, eax
rep stosd
pop edi ecx
pop eax
push [ntfs_cur_offs]
inc eax
mov [ntfs_cur_offs], eax
mov [ntfs_cur_size], 2
push eax
call ntfs_read_attr
pop eax
pop [ntfs_cur_offs]
push eax
jmp .dumploop
.done:
pop eax
pop edx
mov ebx, [edx+4]
pop edx
xor eax, eax
dec ecx
js @f
mov al, ERROR_END_OF_FILE
@@:
mov [esp+1Ch], eax
mov [esp+10h], ebx
popad
ret
 
.add_special_entry:
mov eax, [edx]
inc dword [eax+8] ; new file found
dec ebx
jns .ret
dec ecx
js .ret
inc dword [eax+4] ; new file block copied
mov eax, [edx+4]
mov [edi+4], eax
; mov eax, dword [ntfs_bitmap_buf+0x20]
; or al, 0x10
mov eax, 0x10
stosd
scasd
push edx
mov eax, dword [ntfs_bitmap_buf]
mov edx, dword [ntfs_bitmap_buf+4]
call ntfs_datetime_to_bdfe
mov eax, dword [ntfs_bitmap_buf+0x18]
mov edx, dword [ntfs_bitmap_buf+0x1C]
call ntfs_datetime_to_bdfe
mov eax, dword [ntfs_bitmap_buf+8]
mov edx, dword [ntfs_bitmap_buf+0xC]
call ntfs_datetime_to_bdfe
pop edx
xor eax, eax
stosd
stosd
mov al, '.'
push edi ecx
lea ecx, [esi+1]
test byte [edi-0x24], 1
jz @f
rep stosw
pop ecx
xor eax, eax
stosw
pop edi
add edi, 520
ret
@@:
rep stosb
pop ecx
xor eax, eax
stosb
pop edi
add edi, 264
.ret:
ret
 
.add_entry:
; do not return DOS 8.3 names
cmp byte [esi+0x51], 2
jz .ret
; do not return system files
; ... note that there will be no bad effects if system files also were reported ...
cmp dword [esi], 0x10
jb .ret
mov eax, [edx]
inc dword [eax+8] ; new file found
dec ebx
jns .ret
dec ecx
js .ret
inc dword [eax+4] ; new file block copied
mov eax, [edx+4] ; flags
call ntfs_direntry_to_bdfe
push ecx esi edi
movzx ecx, byte [esi+0x50]
add esi, 0x52
test byte [edi-0x24], 1
jz .ansi
shr ecx, 1
rep movsd
adc ecx, ecx
rep movsw
and word [edi], 0
pop edi
add edi, 520
pop esi ecx
ret
.ansi:
jecxz .skip
@@:
lodsw
call uni2ansi_char
stosb
loop @b
.skip:
xor al, al
stosb
pop edi
add edi, 264
pop esi ecx
ret
 
ntfs_direntry_to_bdfe:
mov [edi+4], eax ; ANSI/UNICODE name
mov eax, [esi+48h]
test eax, 0x10000000
jz @f
and eax, not 0x10000000
or al, 0x10
@@:
stosd
scasd
push edx
mov eax, [esi+0x18]
mov edx, [esi+0x1C]
call ntfs_datetime_to_bdfe
mov eax, [esi+0x30]
mov edx, [esi+0x34]
call ntfs_datetime_to_bdfe
mov eax, [esi+0x20]
mov edx, [esi+0x24]
call ntfs_datetime_to_bdfe
pop edx
mov eax, [esi+0x40]
stosd
mov eax, [esi+0x44]
stosd
ret
 
iglobal
_24 dd 24
_60 dd 60
_10000000 dd 10000000
days400year dd 365*400+100-4+1
days100year dd 365*100+25-1
days4year dd 365*4+1
days1year dd 365
months dd 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
months2 dd 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
_400 dd 400
_100 dd 100
endg
 
ntfs_datetime_to_bdfe:
; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC
push eax
mov eax, edx
xor edx, edx
div [_10000000]
xchg eax, [esp]
div [_10000000]
pop edx
.sec:
; edx:eax = number of seconds since January 1, 1601
push eax
mov eax, edx
xor edx, edx
div [_60]
xchg eax, [esp]
div [_60]
mov [edi], dl
pop edx
; edx:eax = number of minutes
div [_60]
mov [edi+1], dl
; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32)
xor edx, edx
div [_24]
mov [edi+2], dl
mov [edi+3], byte 0
; eax = number of days since January 1, 1601
xor edx, edx
div [days400year]
imul eax, 400
add eax, 1601
mov [edi+6], ax
mov eax, edx
xor edx, edx
div [days100year]
cmp al, 4
jnz @f
dec eax
add edx, [days100year]
@@:
imul eax, 100
add [edi+6], ax
mov eax, edx
xor edx, edx
div [days4year]
shl eax, 2
add [edi+6], ax
mov eax, edx
xor edx, edx
div [days1year]
cmp al, 4
jnz @f
dec eax
add edx, [days1year]
@@:
add [edi+6], ax
push esi edx
mov esi, months
movzx eax, word [edi+6]
test al, 3
jnz .noleap
xor edx, edx
push eax
div [_400]
pop eax
test edx, edx
jz .leap
xor edx, edx
div [_100]
test edx, edx
jz .noleap
.leap:
mov esi, months2
.noleap:
pop edx
xor eax, eax
inc eax
@@:
sub edx, [esi]
jb @f
add esi, 4
inc eax
jmp @b
@@:
add edx, [esi]
pop esi
inc edx
mov [edi+4], dl
mov [edi+5], al
add edi, 8
ret
 
;----------------------------------------------------------------
;
; ntfs_HdRewrite - write to NTFS hard disk
;
; esi points to filename
; ebx ignored (reserved)
; ecx number of bytes to write, 0+
; edx mem location to data
;
; ret ebx = number of written bytes
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
ntfs_HdRewrite:
xor ebx, ebx
mov eax, ERROR_UNSUPPORTED_FS
ret
 
;----------------------------------------------------------------
;
; ntfs_HdWrite - write to NTFS hard disk
;
; esi points to filename
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to write, 0+
; edx mem location to data
;
; ret ebx = bytes written (maybe 0)
; eax = 0 ok write or other = errormsg
;
;--------------------------------------------------------------
ntfs_HdWrite:
xor ebx, ebx
mov eax, ERROR_UNSUPPORTED_FS
ret
 
;----------------------------------------------------------------
;
; ntfs_HdSetFileEnd - set end of file on NTFS hard disk
;
; esi points to filename
; ebx points to 64-bit number = new file size
; ecx ignored (reserved)
; edx ignored (reserved)
;
; ret eax = 0 ok or other = errormsg
;
;--------------------------------------------------------------
ntfs_HdSetFileEnd:
ntfs_HdSetFileInfo:
;----------------------------------------------------------------
;
; ntfs_HdDelete - delete file or empty folder from NTFS hard disk
;
; esi points to filename
;
; ret eax = 0 ok or other = errormsg
;
;--------------------------------------------------------------
ntfs_HdDelete:
mov eax, ERROR_UNSUPPORTED_FS
ret
 
ntfs_HdGetFileInfo:
cmp byte [esi], 0
jnz @f
push 2
pop eax
ret
@@:
call ntfs_find_lfn
jnc .doit
push ERROR_FILE_NOT_FOUND
pop eax
cmp [hd_error], 0
jz @f
mov al, 11
@@:
ret
.doit:
push esi edi
mov esi, eax
mov edi, edx
xor eax, eax
call ntfs_direntry_to_bdfe
pop edi esi
xor eax, eax
ret
 
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/fs/parse_fn.inc
0,0 → 1,236
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;-------------------------------------------------------------------------
;
; File path partial substitution (according to configuration)
;
;
; SPraid
;
;-------------------------------------------------------------------------
 
$Revision $
 
 
iglobal
; pointer to memory for path replace table,
; size of one record is 128 bytes: 64 bytes for search pattern + 64 bytes for replace string
 
; start with one entry: sys -> <sysdir>
full_file_name_table dd sysdir_name
.size dd 1
 
tmp_file_name_size dd 1
endg
 
uglobal
; Parser_params will initialize: sysdir_name = "sys", sysdir_path = <sysdir>
sysdir_name rb 64
sysdir_path rb 64
tmp_file_name_table dd ?
endg
 
; use bx_from_load and init system directory /sys
proc Parser_params
locals
buff db 4 dup(?) ; for test cd
endl
mov eax, [OS_BASE+0x10000+bx_from_load]
mov ecx, sysdir_path
mov [ecx-64], dword 'sys'
cmp al, 'r'; if ram disk
jnz @f
mov [ecx], dword 'RD/?'
mov [ecx+3], byte ah
mov [ecx+4], byte 0
ret
@@:
cmp al, 'm'; if ram disk
jnz @f
mov [ecx], dword 'CD?/'; if cd disk {m}
mov [ecx+4], byte '1'
mov [ecx+5], dword '/KOL'
mov [ecx+9], dword 'IBRI'
mov [ecx+13], byte 0
.next_cd:
mov [ecx+2], byte ah
inc ah
cmp ah, '5'
je .not_found_cd
lea edx, [buff]
pushad
stdcall read_file, read_firstapp, edx, 0, 4
popad
cmp [edx], dword 'MENU'
jne .next_cd
jmp .ok
@@:
sub al, 49
mov [ecx], dword 'HD?/'; if hard disk
mov [ecx+2], byte al
mov [ecx+4], byte ah
mov [ecx+5], dword '/KOL'
mov [ecx+9], dword 'IBRI'
mov [ecx+13], byte 0
.ok:
.not_found_cd:
ret
endp
 
proc load_file_parse_table
stdcall kernel_alloc, 0x1000
mov [tmp_file_name_table], eax
mov edi, eax
mov esi, sysdir_name
mov ecx, 128/4
rep movsd
 
invoke ini.enum_keys, conf_fname, conf_path_sect, get_every_key
 
mov eax, [tmp_file_name_table]
mov [full_file_name_table], eax
mov eax, [tmp_file_name_size]
mov [full_file_name_table.size], eax
ret
endp
 
uglobal
def_val_1 db 0
endg
 
proc get_every_key stdcall, f_name, sec_name, key_name
mov esi, [key_name]
mov ecx, esi
cmp byte [esi], '/'
jnz @f
inc esi
@@:
mov edi, [tmp_file_name_size]
shl edi, 7
cmp edi, 0x1000
jae .stop_parse
add edi, [tmp_file_name_table]
lea ebx, [edi+64]
@@:
cmp edi, ebx
jae .skip_this_key
lodsb
test al, al
jz @f
or al, 20h
stosb
jmp @b
@@:
stosb
 
invoke ini.get_str, [f_name], [sec_name], ecx, ebx, 64, def_val_1
 
cmp byte [ebx], '/'
jnz @f
lea esi, [ebx+1]
mov edi, ebx
mov ecx, 63
rep movsb
@@:
push ebp
mov ebp, [tmp_file_name_table]
mov ecx, [tmp_file_name_size]
jecxz .noreplace
mov eax, ecx
dec eax
shl eax, 7
add ebp, eax
.replace_loop:
mov edi, ebx
mov esi, ebp
@@:
lodsb
test al, al
jz .doreplace
mov dl, [edi]
inc edi
test dl, dl
jz .replace_loop_cont
or dl, 20h
cmp al, dl
jz @b
jmp .replace_loop_cont
.doreplace:
cmp byte [edi], 0
jz @f
cmp byte [edi], '/'
jnz .replace_loop_cont
@@:
lea esi, [ebp+64]
call .replace
jc .skip_this_key2
.replace_loop_cont:
sub ebp, 128
loop .replace_loop
.noreplace:
pop ebp
 
inc [tmp_file_name_size]
.skip_this_key:
xor eax, eax
inc eax
ret
.skip_this_key2:
pop ebp
jmp .skip_this_key
.stop_parse:
xor eax, eax
ret
endp
 
proc get_every_key.replace
; in: ebx->destination, esi->first part of name, edi->second part of name
; maximum length is 64 bytes
; out: CF=1 <=> overflow
; 1) allocate temporary buffer in stack
sub esp, 64
; 2) save second part of name to temporary buffer
push esi
lea esi, [esp+4] ; esi->tmp buffer
xchg esi, edi ; edi->tmp buffer, esi->source
@@:
lodsb
stosb
test al, al
jnz @b
; 3) copy first part of name to destination
pop esi
mov edi, ebx
@@:
lodsb
test al, al
jz @f
stosb
jmp @b
@@:
; 4) restore second part of name from temporary buffer to destination
; (may cause overflow)
lea edx, [ebx+64] ; limit of destination
mov esi, esp
@@:
cmp edi, edx
jae .overflow
lodsb
stosb
test al, al
jnz @b
; all is OK
add esp, 64 ; CF is cleared
ret
.overflow:
; name is too long
add esp, 64
stc
ret
endp
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/fs
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/drivers/i8254x.asm
0,0 → 1,809
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; i8254x driver for KolibriOS ;;
;; ;;
;; based on i8254x.asm from baremetal os ;;
;; ;;
;; Written by hidnplayr (hidnplayr@gmail.com) ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; TODO: make better use of the available descriptors
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
MAX_PKT_SIZE = 16384 ; Maximum packet size
 
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
include '../struct.inc'
include 'netdrv.inc'
 
public START
public service_proc
public version
 
 
 
; Register list
REG_CTRL = 0x0000 ; Control Register
REG_STATUS = 0x0008 ; Device Status Register
REG_CTRLEXT = 0x0018 ; Extended Control Register
REG_MDIC = 0x0020 ; MDI Control Register
REG_FCAL = 0x0028 ; Flow Control Address Low
REG_FCAH = 0x002C ; Flow Control Address High
REG_FCT = 0x0030 ; Flow Control Type
REG_VET = 0x0038 ; VLAN Ether Type
REG_ICR = 0x00C0 ; Interrupt Cause Read
REG_ITR = 0x00C4 ; Interrupt Throttling Register
REG_ICS = 0x00C8 ; Interrupt Cause Set Register
REG_IMS = 0x00D0 ; Interrupt Mask Set/Read Register
REG_IMC = 0x00D8 ; Interrupt Mask Clear Register
REG_RCTL = 0x0100 ; Receive Control Register
REG_FCTTV = 0x0170 ; Flow Control Transmit Timer Value
REG_TXCW = 0x0178 ; Transmit Configuration Word
REG_RXCW = 0x0180 ; Receive Configuration Word
REG_TCTL = 0x0400 ; Transmit Control Register
REG_TIPG = 0x0410 ; Transmit Inter Packet Gap
 
REG_LEDCTL = 0x0E00 ; LED Control
REG_PBA = 0x1000 ; Packet Buffer Allocation
 
REG_RDBAL = 0x2800 ; RX Descriptor Base Address Low
REG_RDBAH = 0x2804 ; RX Descriptor Base Address High
REG_RDLEN = 0x2808 ; RX Descriptor Length
REG_RDH = 0x2810 ; RX Descriptor Head
REG_RDT = 0x2818 ; RX Descriptor Tail
REG_RDTR = 0x2820 ; RX Delay Timer Register
REG_RXDCTL = 0x3828 ; RX Descriptor Control
REG_RADV = 0x282C ; RX Int. Absolute Delay Timer
REG_RSRPD = 0x2C00 ; RX Small Packet Detect Interrupt
 
REG_TXDMAC = 0x3000 ; TX DMA Control
REG_TDBAL = 0x3800 ; TX Descriptor Base Address Low
REG_TDBAH = 0x3804 ; TX Descriptor Base Address High
REG_TDLEN = 0x3808 ; TX Descriptor Length
REG_TDH = 0x3810 ; TX Descriptor Head
REG_TDT = 0x3818 ; TX Descriptor Tail
REG_TIDV = 0x3820 ; TX Interrupt Delay Value
REG_TXDCTL = 0x3828 ; TX Descriptor Control
REG_TADV = 0x382C ; TX Absolute Interrupt Delay Value
REG_TSPMT = 0x3830 ; TCP Segmentation Pad & Min Threshold
 
REG_RXCSUM = 0x5000 ; RX Checksum Control
 
; Register list for i8254x
I82542_REG_RDTR = 0x0108 ; RX Delay Timer Register
I82542_REG_RDBAL = 0x0110 ; RX Descriptor Base Address Low
I82542_REG_RDBAH = 0x0114 ; RX Descriptor Base Address High
I82542_REG_RDLEN = 0x0118 ; RX Descriptor Length
I82542_REG_RDH = 0x0120 ; RDH for i82542
I82542_REG_RDT = 0x0128 ; RDT for i82542
I82542_REG_TDBAL = 0x0420 ; TX Descriptor Base Address Low
I82542_REG_TDBAH = 0x0424 ; TX Descriptor Base Address Low
I82542_REG_TDLEN = 0x0428 ; TX Descriptor Length
I82542_REG_TDH = 0x0430 ; TDH for i82542
I82542_REG_TDT = 0x0438 ; TDT for i82542
 
; CTRL - Control Register (0x0000)
CTRL_FD = 0x00000001 ; Full Duplex
CTRL_LRST = 0x00000008 ; Link Reset
CTRL_ASDE = 0x00000020 ; Auto-speed detection
CTRL_SLU = 0x00000040 ; Set Link Up
CTRL_ILOS = 0x00000080 ; Invert Loss of Signal
CTRL_SPEED_MASK = 0x00000300 ; Speed selection
CTRL_SPEED_SHIFT = 8
CTRL_FRCSPD = 0x00000800 ; Force Speed
CTRL_FRCDPLX = 0x00001000 ; Force Duplex
CTRL_SDP0_DATA = 0x00040000 ; SDP0 data
CTRL_SDP1_DATA = 0x00080000 ; SDP1 data
CTRL_SDP0_IODIR = 0x00400000 ; SDP0 direction
CTRL_SDP1_IODIR = 0x00800000 ; SDP1 direction
CTRL_RST = 0x04000000 ; Device Reset
CTRL_RFCE = 0x08000000 ; RX Flow Ctrl Enable
CTRL_TFCE = 0x10000000 ; TX Flow Ctrl Enable
CTRL_VME = 0x40000000 ; VLAN Mode Enable
CTRL_PHY_RST = 0x80000000 ; PHY reset
 
; STATUS - Device Status Register (0x0008)
STATUS_FD = 0x00000001 ; Full Duplex
STATUS_LU = 0x00000002 ; Link Up
STATUS_TXOFF = 0x00000010 ; Transmit paused
STATUS_TBIMODE = 0x00000020 ; TBI Mode
STATUS_SPEED_MASK = 0x000000C0 ; Link Speed setting
STATUS_SPEED_SHIFT = 6
STATUS_ASDV_MASK = 0x00000300 ; Auto Speed Detection
STATUS_ASDV_SHIFT = 8
STATUS_PCI66 = 0x00000800 ; PCI bus speed
STATUS_BUS64 = 0x00001000 ; PCI bus width
STATUS_PCIX_MODE = 0x00002000 ; PCI-X mode
STATUS_PCIXSPD_MASK = 0x0000C000 ; PCI-X speed
STATUS_PCIXSPD_SHIFT = 14
 
; CTRL_EXT - Extended Device Control Register (0x0018)
CTRLEXT_PHY_INT = 0x00000020 ; PHY interrupt
CTRLEXT_SDP6_DATA = 0x00000040 ; SDP6 data
CTRLEXT_SDP7_DATA = 0x00000080 ; SDP7 data
CTRLEXT_SDP6_IODIR = 0x00000400 ; SDP6 direction
CTRLEXT_SDP7_IODIR = 0x00000800 ; SDP7 direction
CTRLEXT_ASDCHK = 0x00001000 ; Auto-Speed Detect Chk
CTRLEXT_EE_RST = 0x00002000 ; EEPROM reset
CTRLEXT_SPD_BYPS = 0x00008000 ; Speed Select Bypass
CTRLEXT_RO_DIS = 0x00020000 ; Relaxed Ordering Dis.
CTRLEXT_LNKMOD_MASK = 0x00C00000 ; Link Mode
CTRLEXT_LNKMOD_SHIFT = 22
 
; MDIC - MDI Control Register (0x0020)
MDIC_DATA_MASK = 0x0000FFFF ; Data
MDIC_REG_MASK = 0x001F0000 ; PHY Register
MDIC_REG_SHIFT = 16
MDIC_PHY_MASK = 0x03E00000 ; PHY Address
MDIC_PHY_SHIFT = 21
MDIC_OP_MASK = 0x0C000000 ; Opcode
MDIC_OP_SHIFT = 26
MDIC_R = 0x10000000 ; Ready
MDIC_I = 0x20000000 ; Interrupt Enable
MDIC_E = 0x40000000 ; Error
 
; ICR - Interrupt Cause Read (0x00c0)
ICR_TXDW = 0x00000001 ; TX Desc Written back
ICR_TXQE = 0x00000002 ; TX Queue Empty
ICR_LSC = 0x00000004 ; Link Status Change
ICR_RXSEQ = 0x00000008 ; RX Sence Error
ICR_RXDMT0 = 0x00000010 ; RX Desc min threshold reached
ICR_RXO = 0x00000040 ; RX Overrun
ICR_RXT0 = 0x00000080 ; RX Timer Interrupt
ICR_MDAC = 0x00000200 ; MDIO Access Complete
ICR_RXCFG = 0x00000400
ICR_PHY_INT = 0x00001000 ; PHY Interrupt
ICR_GPI_SDP6 = 0x00002000 ; GPI on SDP6
ICR_GPI_SDP7 = 0x00004000 ; GPI on SDP7
ICR_TXD_LOW = 0x00008000 ; TX Desc low threshold hit
ICR_SRPD = 0x00010000 ; Small RX packet detected
 
; RCTL - Receive Control Register (0x0100)
RCTL_EN = 0x00000002 ; Receiver Enable
RCTL_SBP = 0x00000004 ; Store Bad Packets
RCTL_UPE = 0x00000008 ; Unicast Promiscuous Enabled
RCTL_MPE = 0x00000010 ; Xcast Promiscuous Enabled
RCTL_LPE = 0x00000020 ; Long Packet Reception Enable
RCTL_LBM_MASK = 0x000000C0 ; Loopback Mode
RCTL_LBM_SHIFT = 6
RCTL_RDMTS_MASK = 0x00000300 ; RX Desc Min Threshold Size
RCTL_RDMTS_SHIFT = 8
RCTL_MO_MASK = 0x00003000 ; Multicast Offset
RCTL_MO_SHIFT = 12
RCTL_BAM = 0x00008000 ; Broadcast Accept Mode
RCTL_BSIZE_MASK = 0x00030000 ; RX Buffer Size
RCTL_BSIZE_SHIFT = 16
RCTL_VFE = 0x00040000 ; VLAN Filter Enable
RCTL_CFIEN = 0x00080000 ; CFI Enable
RCTL_CFI = 0x00100000 ; Canonical Form Indicator Bit
RCTL_DPF = 0x00400000 ; Discard Pause Frames
RCTL_PMCF = 0x00800000 ; Pass MAC Control Frames
RCTL_BSEX = 0x02000000 ; Buffer Size Extension
RCTL_SECRC = 0x04000000 ; Strip Ethernet CRC
 
; TCTL - Transmit Control Register (0x0400)
TCTL_EN = 0x00000002 ; Transmit Enable
TCTL_PSP = 0x00000008 ; Pad short packets
TCTL_SWXOFF = 0x00400000 ; Software XOFF Transmission
 
; PBA - Packet Buffer Allocation (0x1000)
PBA_RXA_MASK = 0x0000FFFF ; RX Packet Buffer
PBA_RXA_SHIFT = 0
PBA_TXA_MASK = 0xFFFF0000 ; TX Packet Buffer
PBA_TXA_SHIFT = 16
 
; Flow Control Type
FCT_TYPE_DEFAULT = 0x8808
 
; === TX Descriptor fields ===
 
; TX Packet Length (word 2)
TXDESC_LEN_MASK = 0x0000ffff
 
; TX Descriptor CMD field (word 2)
TXDESC_IDE = 0x80000000 ; Interrupt Delay Enable
TXDESC_VLE = 0x40000000 ; VLAN Packet Enable
TXDESC_DEXT = 0x20000000 ; Extension
TXDESC_RPS = 0x10000000 ; Report Packet Sent
TXDESC_RS = 0x08000000 ; Report Status
TXDESC_IC = 0x04000000 ; Insert Checksum
TXDESC_IFCS = 0x02000000 ; Insert FCS
TXDESC_EOP = 0x01000000 ; End Of Packet
 
; TX Descriptor STA field (word 3)
TXDESC_TU = 0x00000008 ; Transmit Underrun
TXDESC_LC = 0x00000004 ; Late Collision
TXDESC_EC = 0x00000002 ; Excess Collisions
TXDESC_DD = 0x00000001 ; Descriptor Done
 
; === RX Descriptor fields ===
 
; RX Packet Length (word 2)
RXDESC_LEN_MASK = 0x0000ffff
 
; RX Descriptor STA field (word 3)
RXDESC_PIF = 0x00000080 ; Passed In-exact Filter
RXDESC_IPCS = 0x00000040 ; IP cksum calculated
RXDESC_TCPCS = 0x00000020 ; TCP cksum calculated
RXDESC_VP = 0x00000008 ; Packet is 802.1Q
RXDESC_IXSM = 0x00000004 ; Ignore cksum indication
RXDESC_EOP = 0x00000002 ; End Of Packet
RXDESC_DD = 0x00000001 ; Descriptor Done
 
 
virtual at ebx
device:
ETH_DEVICE
 
.mmio_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
 
.cur_tx dd ?
.last_tx dd ?
 
rb 0x100 - (($ - device) and 0xff)
.rx_desc rd 256/8
 
rb 0x100 - (($ - device) and 0xff)
.tx_desc rd 256/8
 
sizeof.device_struct = $ - device
 
end virtual
 
section '.flat' code readable align 16
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
 
.entry:
 
DEBUGF 2,"Loading %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
 
.fail:
.exit:
xor eax, eax
ret
 
endp
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne @F
 
cmp [IOCTL.out_size], 4
jb .fail
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
 
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
 
mov eax, [IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet
 
; check if the device is already listed
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax, [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte [device.pci_bus]
jne .next
cmp ah, byte [device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
.next:
add esi, 4
loop .nextdevice
 
 
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, sizeof.device_struct, .fail ; Allocate the buffer for device structure
 
; Fill in the direct call addresses into the struct
 
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], unload
mov [device.name], my_service
 
; save the pci bus and device numbers
 
mov eax, [IOCTL.input]
movzx ecx, byte [eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte [eax+2]
mov [device.pci_dev], ecx
 
; Now, it's time to find the base mmio addres of the PCI device
 
PCI_find_mmio32
 
; Create virtual mapping of the physical memory
 
push 1Bh ; PG_SW+PG_NOCACHE
push 10000h ; size of the map
push eax
call MapIoMem
mov [device.mmio_addr], eax
 
; We've found the mmio address, find IRQ now
 
PCI_find_irq
 
DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.mmio_addr]:8
 
; Ok, the eth_device structure is ready, let's probe the device
call probe ; this function will output in eax
test eax, eax
jnz .err ; If an error occured, exit
 
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
 
call start_i8254x
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
cmp eax, -1
je .destroy
 
ret
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 1,"Trying to find device number of already registered device\n"
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 1,"Kernel says: %u\n", eax
ret
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
; todo: reset device into virgin state
 
.err:
stdcall KernelFree, ebx
 
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
align 4
unload:
; TODO: (in this particular order)
;
; - Stop the device
; - Detach int handler
; - Remove device from local list (device_list)
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
 
or eax, -1
 
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; probe: enables the device (if it really is I8254X)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
probe:
 
DEBUGF 1,"Probe\n"
 
PCI_make_bus_master
 
; TODO: validate the device
 
call read_mac
 
movzx eax, [device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax
jnz @f
DEBUGF 1,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
 
reset_dontstart:
DEBUGF 1,"Reset\n"
 
mov esi, [device.mmio_addr]
 
or dword [esi + REG_CTRL], CTRL_RST ; reset device
.loop:
push esi
xor esi, esi
inc esi
call Sleep
pop esi
test dword [esi + REG_CTRL], CTRL_RST
jnz .loop
 
mov dword [esi + REG_IMC], 0xffffffff ; Disable all interrupt causes
mov eax, dword [esi + REG_ICR] ; Clear any pending interrupts
mov dword [esi + REG_ITR], 0 ; Disable interrupt throttling logic
 
mov dword [esi + REG_PBA], 0x00000030 ; PBA: set the RX buffer size to 48KB (TX buffer is calculated as 64-RX buffer)
mov dword [esi + REG_RDTR], 0 ; RDTR: set no delay
 
mov dword [esi + REG_TXCW], 0x08008060 ; TXCW: set ANE, TxConfigWord (Half/Full duplex, Next Page Reqest)
 
mov eax, [esi + REG_CTRL]
or eax, 1 shl 6 + 1 shl 5
and eax, not (1 shl 3 + 1 shl 7 + 1 shl 30 + 1 shl 31)
mov dword [esi + REG_CTRL], eax ; CTRL: clear LRST, set SLU and ASDE, clear RSTPHY, VME, and ILOS
 
lea edi, [esi + 0x5200] ; MTA: reset
mov eax, 0xffffffff
stosd
stosd
stosd
stosd
 
stdcall KernelAlloc, 48*1024
mov dword [device.rx_desc + 16], eax
GetRealAddr
mov dword [device.rx_desc], eax
mov dword [device.rx_desc + 4], 0
 
lea eax, [device.rx_desc]
GetRealAddr
mov dword [esi + REG_RDBAL], eax ; Receive Descriptor Base Address Low
mov dword [esi + REG_RDBAH], 0 ; Receive Descriptor Base Address High
mov dword [esi + REG_RDLEN], (1 * 128) ; Receive Descriptor Length
mov dword [esi + REG_RDH], 0 ; Receive Descriptor Head
mov dword [esi + REG_RDT], 1 ; Receive Descriptor Tail
mov dword [esi + REG_RCTL], RCTL_EN or RCTL_SBP or RCTL_BAM or RCTL_SECRC or RCTL_UPE or RCTL_MPE
; Receiver Enable, Store Bad Packets, Broadcast Accept Mode, Strip Ethernet CRC from incoming packet, Promiscuous mode
 
mov dword [device.tx_desc], 0
mov dword [device.tx_desc + 4], 0
mov dword [device.tx_desc + 16], 0
 
lea eax, [device.tx_desc]
GetRealAddr
mov dword [esi + REG_TDBAL], eax ; Transmit Descriptor Base Address Low
mov dword [esi + REG_TDBAH], 0 ; Transmit Descriptor Base Address High
mov dword [esi + REG_TDLEN], (1 * 128) ; Transmit Descriptor Length
mov dword [esi + REG_TDH], 0 ; Transmit Descriptor Head
mov dword [esi + REG_TDT], 0 ; Transmit Descriptor Tail
mov dword [esi + REG_TCTL], 0x010400fa ; Enabled, Pad Short Packets, 15 retrys, 64-byte COLD, Re-transmit on Late Collision
mov dword [esi + REG_TIPG], 0x0060200A ; IPGT 10, IPGR1 8, IPGR2 6
 
xor eax, eax
ret
 
align 4
reset:
call reset_dontstart
 
start_i8254x:
 
xor eax, eax
mov [esi + REG_RDTR], eax ; Clear the Receive Delay Timer Register
mov [esi + REG_RADV], eax ; Clear the Receive Interrupt Absolute Delay Timer
mov [esi + REG_RSRPD], eax ; Clear the Receive Small Packet Detect Interrupt
; or eax, 1 shl 0 + 1 shl 7 ; TXDW + RXT0
mov eax, 1+4+16 ;;;; hack!
mov [esi + REG_IMS], eax ; Enable interrupt types
 
mov [device.mtu], 1514
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
xor eax, eax
ret
 
 
 
 
align 4
read_mac:
 
DEBUGF 1,"Read MAC\n"
 
mov esi, [device.mmio_addr]
 
mov eax, [esi+0x5400] ; RAL
test eax, eax
jz .try_eeprom
 
mov dword [device.mac], eax
mov eax, [esi+0x5404] ; RAH
mov word [device.mac+4], ax
 
jmp .mac_ok
 
.try_eeprom:
mov dword [esi+0x14], 0x00000001
mov eax, [esi+0x14]
shr eax, 16
mov word [device.mac], ax
 
mov dword [esi+0x14], 0x00000101
mov eax, [esi+0x14]
shr eax, 16
mov word [device.mac+2], ax
 
mov dword [esi+0x14], 0x00000201
mov eax, [esi+0x14]
shr eax, 16
mov word [device.mac+4], ax
 
.mac_ok:
DEBUGF 1,"MAC = %x-%x-%x-%x-%x-%x\n",\
[device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
transmit:
DEBUGF 2,"\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
DEBUGF 2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
 
cmp dword [esp + 8], 1514
ja .fail
cmp dword [esp + 8], 60
jb .fail
 
 
; Program the descriptor (use legacy mode)
lea edi, [device.tx_desc] ; Transmit Descriptor Base Address
mov dword [edi + 16], eax ; Store the data location (for driver)
GetRealAddr ;
mov dword [edi], eax ; Real addr (for i8254x)
mov dword [edi + 4], 0x00000000 ;
 
mov ecx, [esp + 8]
or ecx, 1 shl 24 + 1 shl 25 + 1 shl 27 ; EOP + IFCS + RS
mov dword [edi + 8], ecx ; Packet size
mov dword [edi + 12], 0x00000000
 
; Tell i8254x wich descriptor(s) we programmed
mov edi, [device.mmio_addr]
mov dword [edi + REG_TDH], 0 ; TDH - Transmit Descriptor Head
mov dword [edi + REG_TDT], 1 ; TDT - Transmit Descriptor Tail
 
; Update stats
inc [device.packets_tx]
mov eax, [esp + 8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
ret 8
 
.fail:
DEBUGF 1,"Send failed\n"
ret 8
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_handler:
 
DEBUGF 1,"\n%s int\n", my_service
;-------------------------------------------
; Find pointer of device wich made IRQ occur
 
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
mov edi, [device.mmio_addr]
mov eax, [edi + REG_ICR]
test eax, eax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
ret
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x ", ebx, eax
 
;---------
; RX done?
 
test eax, ICR_RXDMT0
jz .no_rx
 
push eax ebx
push .retaddr
 
; Get last descriptor addr
lea esi, [device.rx_desc]
 
cmp byte [esi + 12], 0 ; Check status field
je .retaddr
 
movzx ecx, word [esi + 8] ; Get the packet length
DEBUGF 2,"got %u bytes\n", ecx
push ecx
push dword [esi + 16] ; Get packet pointer
 
; Update stats
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
inc dword [device.packets_rx]
 
; allocate new descriptor
stdcall KernelAlloc, 48*1024
mov dword [esi + 16], eax
GetRealAddr
mov dword [esi], eax
 
; reset descriptor status
mov esi, [device.mmio_addr]
mov dword [esi + REG_RDH], 0x00000000 ; Receive Descriptor Head
mov dword [esi + REG_RDT], 0x00000001 ; Receive Descriptor Tail
 
jmp Eth_input
.retaddr:
pop ebx eax
 
.no_rx:
 
;--------------
; Link Changed?
 
test eax, ICR_LSC
jz .no_link
 
DEBUGF 2,"Link Changed\n"
 
.no_link:
 
;---------------
; Transmit done?
 
test eax, ICR_TXDW
jz .no_tx
 
DEBUGF 2,"Transmit done\n"
 
lea edi, [device.tx_desc] ; Transmit Descriptor Base Address
push dword [edi + 16] ; Store the data location (for driver)
call KernelFree
 
.no_tx:
.fail:
ret
 
 
 
 
; End of code
 
section '.data' data readable writable align 16
align 4
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'I8254X',0 ; max 16 chars include zero
 
include_debug_strings ; All data wich FDO uses will be included here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
 
/kernel/branches/net/drivers/RTL8139.asm
0,0 → 1,1122
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Realtek 8139 driver for KolibriOS ;;
;; ;;
;; based on RTL8139.asm driver for menuetos ;;
;; and realtek8139.asm for SolarOS by Eugen Brasoveanu ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
RBLEN = 3 ; Receive buffer size: 0==8K 1==16k 2==32k 3==64k
NUM_TX_DESC = 4
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
 
public START
public service_proc
public version
 
REG_IDR0 = 0x00
REG_MAR0 = 0x08 ; multicast filter register 0
REG_MAR4 = 0x0c ; multicast filter register 4
REG_TSD0 = 0x10 ; transmit status of descriptor
REG_TSAD0 = 0x20 ; transmit start address of descriptor
REG_RBSTART = 0x30 ; RxBuffer start address
REG_COMMAND = 0x37 ; command register
REG_CAPR = 0x38 ; current address of packet read (word) R/W
REG_IMR = 0x3c ; interrupt mask register
REG_ISR = 0x3e ; interrupt status register
REG_TXCONFIG = 0x40 ; transmit configuration register
REG_RXCONFIG = 0x44 ; receive configuration register 0
REG_MPC = 0x4c ; missed packet counter
REG_9346CR = 0x50 ; serial eeprom 93C46 command register
REG_CONFIG1 = 0x52 ; configuration register 1
REG_MSR = 0x58
REG_CONFIG4 = 0x5a ; configuration register 4
REG_HLTCLK = 0x5b ; undocumented halt clock register
REG_BMCR = 0x62 ; basic mode control register
REG_ANAR = 0x66 ; auto negotiation advertisement register
REG_9346CR_WE = 11b shl 6
 
BIT_RUNT = 4 ; total packet length < 64 bytes
BIT_LONG = 3 ; total packet length > 4k
BIT_CRC = 2 ; crc error occured
BIT_FAE = 1 ; frame alignment error occured
BIT_ROK = 0 ; received packet is ok
 
BIT_RST = 4 ; reset bit
BIT_RE = 3 ; receiver enabled
BIT_TE = 2 ; transmitter enabled
BUFE = 1 ; rx buffer is empty, no packet stored
 
BIT_ISR_TOK = 2 ; transmit ok
BIT_ISR_RER = 1 ; receive error interrupt
BIT_ISR_ROK = 0 ; receive ok
 
BIT_TX_MXDMA = 8 ; Max DMA burst size per Tx DMA burst
BIT_TXRR = 4 ; Tx Retry count 16+(TXRR*16)
 
BIT_RXFTH = 13 ; Rx fifo threshold
BIT_RBLEN = 11 ; Ring buffer length indicator
BIT_RX_MXDMA = 8 ; Max DMA burst size per Rx DMA burst
BIT_NOWRAP = 7 ; transfered data wrapping
BIT_9356SEL = 6 ; eeprom selector 9346/9356
BIT_AER = 5 ; accept error packets
BIT_AR = 4 ; accept runt packets
BIT_AB = 3 ; accept broadcast packets
BIT_AM = 2 ; accept multicast packets
BIT_APM = 1 ; accept physical match packets
BIT_AAP = 0 ; accept all packets
 
BIT_93C46_EEM1 = 7 ; RTL8139 eeprom operating mode1
BIT_93C46_EEM0 = 6 ; RTL8139 eeprom operating mode0
BIT_93C46_EECS = 3 ; chip select
BIT_93C46_EESK = 2 ; serial data clock
BIT_93C46_EEDI = 1 ; serial data input
BIT_93C46_EEDO = 0 ; serial data output
 
BIT_LWACT = 4 ; see REG_CONFIG1
BIT_SLEEP = 1 ; sleep bit at older chips
BIT_PWRDWN = 0 ; power down bit at older chips
BIT_PMEn = 0 ; power management enabled
 
BIT_LWPTN = 2 ; see REG_CONFIG4
 
BIT_ERTXTH = 16 ; early TX threshold
BIT_TOK = 15 ; transmit ok
BIT_OWN = 13 ; tx DMA operation is completed
 
BIT_ANE = 12 ; auto negotiation enable
 
BIT_TXFD = 8 ; 100base-T full duplex
BIT_TX = 7 ; 100base-T
BIT_10FD = 6 ; 10base-T full duplex
BIT_10 = 5 ; 10base-T
BIT_SELECTOR = 0 ; binary encoded selector CSMA/CD=00001
 
BIT_IFG1 = 25
BIT_IFG0 = 24
 
TXRR = 8 ; total retries = 16+(TXRR*16)
TX_MXDMA = 6 ; 0=16 1=32 2=64 3=128 4=256 5=512 6=1024 7=2048
ERTXTH = 8 ; in unit of 32 bytes e.g:(8*32)=256
RX_MXDMA = 7 ; 0=16 1=32 2=64 3=128 4=256 5=512 6=1024 7=unlimited
RXFTH = 7 ; 0=16 1=32 2=64 3=128 4=256 5=512 6=1024 7=no threshold
 
RX_CONFIG = (RBLEN shl BIT_RBLEN) or \
(RX_MXDMA shl BIT_RX_MXDMA) or \
(1 shl BIT_NOWRAP) or \
(RXFTH shl BIT_RXFTH) or\
(1 shl BIT_AB) or \ ; Accept broadcast packets
(1 shl BIT_APM) or \ ; Accept physical match packets
(1 shl BIT_AER) or \ ; Accept error packets
(1 shl BIT_AR) or \ ; Accept Runt packets (smaller then 64 bytes)
(1 shl BIT_AM) ; Accept multicast packets
 
RX_BUFFER_SIZE = (8192 shl RBLEN);+16
MAX_ETH_FRAME_SIZE = 1514
 
EE_93C46_REG_ETH_ID = 7 ; MAC offset
EE_93C46_READ_CMD = (6 shl 6) ; 110b + 6bit address
EE_93C56_READ_CMD = (6 shl 8) ; 110b + 8bit address
EE_93C46_CMD_LENGTH = 9 ; start bit + cmd + 6bit address
EE_93C56_CMD_LENGTH = 11 ; start bit + cmd + 8bit ddress
 
VER_RTL8139 = 1100000b
VER_RTL8139A = 1110000b
VER_RTL8139AG = 1110100b
VER_RTL8139B = 1111000b
VER_RTL8130 = VER_RTL8139B
VER_RTL8139C = 1110100b
VER_RTL8100 = 1111010b
VER_RTL8100B = 1110101b
VER_RTL8139D = VER_RTL8100B
VER_RTL8139CP = 1110110b
VER_RTL8101 = 1110111b
 
IDX_RTL8139 = 0
IDX_RTL8139A = 1
IDX_RTL8139B = 2
IDX_RTL8139C = 3
IDX_RTL8100 = 4
IDX_RTL8139D = 5
IDX_RTL8139D = 6
IDX_RTL8101 = 7
 
ISR_SERR = 1 shl 15
ISR_TIMEOUT = 1 shl 14
ISR_LENCHG = 1 shl 13
ISR_FIFOOVW = 1 shl 6
ISR_PUN = 1 shl 5
ISR_RXOVW = 1 shl 4
ISR_TER = 1 shl 3
ISR_TOK = 1 shl 2
ISR_RER = 1 shl 1
ISR_ROK = 1 shl 0
 
INTERRUPT_MASK = ISR_ROK or \
ISR_RXOVW or \
ISR_PUN or \
ISR_FIFOOVW or \
ISR_LENCHG or \
ISR_TOK or \
ISR_TER
 
TSR_OWN = 1 shl 13
TSR_TUN = 1 shl 14
TSR_TOK = 1 shl 15
 
TSR_CDH = 1 shl 28
TSR_OWC = 1 shl 29
TSR_TABT = 1 shl 30
TSR_CRS = 1 shl 31
 
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.rx_buffer dd ?
 
.rx_data_offset dd ?
.io_addr dd ?
 
.curr_tx_desc db ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
.hw_ver_id db ?
 
.TX_DESC rd NUM_TX_DESC
 
.size = $ - device
 
end virtual
 
 
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
 
.entry:
 
DEBUGF 2, "Loading %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
 
.fail:
.exit:
xor eax, eax
ret
 
endp
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne @F
 
cmp [IOCTL.out_size], 4
jb .fail
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
 
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
 
mov eax, [IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet
 
; check if the device is already listed
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
mov ax, [eax+1] ; get the pci bus and device numbers
.nextdevice:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
 
 
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, device.size, .fail ; Allocate the buffer for device structure
 
; Fill in the direct call addresses into the struct
 
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], unload
mov [device.name], my_service
 
; save the pci bus and device numbers
 
mov eax, [IOCTL.input]
movzx ecx, byte[eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte[eax+2]
mov [device.pci_dev], ecx
 
; Now, it's time to find the base io addres of the PCI device
 
PCI_find_io
 
; We've found the io address, find IRQ now
 
PCI_find_irq
 
DEBUGF 2, "Hooking into device, dev:%x, bus:%x, irq:%x, I/O addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
 
; Allocate the receive buffer
 
stdcall CreateRingBuffer, dword (RX_BUFFER_SIZE), dword PG_SW
test eax, eax
jz .err
mov [device.rx_buffer], eax
 
; Ok, the eth_device structure is ready, let's probe the device
 
call probe ; this function will output in eax
test eax, eax
jnz .err ; If an error occured, exit
 
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
cmp eax, -1
je .destroy
 
ret
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 2, "Trying to find device number of already registered device\n"
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 2, "Kernel says: %u\n", eax
ret
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
; todo: reset device into virgin state
 
.err:
stdcall KernelFree, [device.rx_buffer]
stdcall KernelFree, ebx
 
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
align 4
unload:
; TODO: (in this particular order)
;
; - Stop the device
; - Detach int handler
; - Remove device from local list (RTL8139_LIST)
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
 
or eax, -1
 
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; probe: enables the device (if it really is RTL8139)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
probe:
DEBUGF 2, "Probing %s device\n", my_service
 
PCI_make_bus_master
 
; get chip version
set_io 0
set_io REG_TXCONFIG + 2
in ax, dx
shr ah, 2
shr ax, 6
and al, 01111111b
 
; now find it in our array
mov ecx, HW_VER_ARRAY_SIZE-1
.chip_ver_loop:
cmp al, [hw_ver_array + ecx]
je .chip_ver_found
dec ecx
jns .chip_ver_loop
.unknown:
mov ecx, 8
.chip_ver_found:
cmp ecx, 8
ja .unknown
 
mov [device.hw_ver_id], cl
 
mov ecx, [crosslist+ecx*4]
mov [device.name], ecx
 
DEBUGF 2, "Chip version: %s\n", ecx
 
; wake up the chip
set_io 0
set_io REG_HLTCLK
mov al, 'R' ; run the clock
out dx, al
 
; unlock config and BMCR registers
set_io REG_9346CR
mov al, (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0)
out dx, al
 
; enable power management
set_io REG_CONFIG1
in al, dx
cmp [device.hw_ver_id], IDX_RTL8139B
jae .new_chip
; wake up older chips
and al, not ((1 shl BIT_SLEEP) or (1 shl BIT_PWRDWN))
out dx, al
jmp .finish_wake_up
 
; set LWAKE pin to active high (default value).
; it is for Wake-On-LAN functionality of some motherboards.
; this signal is used to inform the motherboard to execute a wake-up process.
; only at newer chips.
.new_chip:
or al, (1 shl BIT_PMEn)
and al, not (1 shl BIT_LWACT)
out dx, al
 
set_io REG_CONFIG4
in al, dx
and al, not (1 shl BIT_LWPTN)
out dx, al
 
; lock config and BMCR registers
.finish_wake_up:
xor al, al
set_io 0
set_io REG_9346CR
out dx, al
DEBUGF 2, "done!\n"
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; reset: Set up all registers and descriptors, clear some values
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
reset:
DEBUGF 2, "Reset\n"
 
; attach int handler
movzx eax, [device.irq_line]
DEBUGF 1, "Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax
jnz @f
DEBUGF 1, "\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
; reset chip
DEBUGF 1, "Resetting chip\n"
set_io 0
set_io REG_COMMAND
mov al, 1 shl BIT_RST
out dx, al
mov cx, 1000 ; wait no longer for the reset
.wait_for_reset:
in al, dx
test al, 1 shl BIT_RST
jz .reset_completed ; RST remains 1 during reset
dec cx
jns .wait_for_reset
DEBUGF 1, "Reset timeout!\n"
.reset_completed:
 
; unlock config and BMCR registers
set_io REG_9346CR
mov al, (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0)
out dx, al
 
; initialize multicast registers (no filtering)
mov eax, 0xffffffff
set_io REG_MAR0
out dx, eax
set_io REG_MAR4
out dx, eax
 
; enable Rx/Tx
 
mov al, (1 shl BIT_RE) or (1 shl BIT_TE)
set_io REG_COMMAND
out dx, al
 
; Rxbuffer size, unlimited dma burst, no wrapping, no rx threshold
; accept broadcast packets, accept physical match packets
mov ax, RX_CONFIG
set_io REG_RXCONFIG
out dx, ax
 
; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144
mov eax, (TX_MXDMA shl BIT_TX_MXDMA) or (TXRR shl BIT_TXRR) or BIT_IFG1 or BIT_IFG0
set_io REG_TXCONFIG
out dx, eax
 
; enable auto negotiation
set_io REG_BMCR
in ax, dx
or ax, (1 shl BIT_ANE)
out dx, ax
 
; set auto negotiation advertisement
set_io REG_ANAR
in ax, dx
or ax, (1 shl BIT_SELECTOR) or (1 shl BIT_10) or (1 shl BIT_10FD) or (1 shl BIT_TX) or (1 shl BIT_TXFD)
out dx, ax
 
; lock config and BMCR registers
xor eax, eax
set_io REG_9346CR
out dx, al
 
; init RX/TX pointers
mov [device.rx_data_offset], eax
mov [device.curr_tx_desc], al
; set_io REG_CAPR
; out dx, ax
 
; clear packet/byte counters
lea edi, [device.bytes_tx]
mov ecx, 6
rep stosd
 
; clear missing packet counter
set_io REG_MPC
out dx, eax
 
; set RxBuffer address, init RX buffer offset
mov eax, [device.rx_buffer]
mov dword[eax], 0 ; clear receive flags for first packet (really needed??)
DEBUGF 2, "RX buffer virtual addr=0x%x\n", eax
GetRealAddr
DEBUGF 2, "RX buffer real addr=0x%x\n", eax
set_io REG_RBSTART
out dx, eax
 
; Read MAC address
call read_mac
 
; enable interrupts
set_io 0
set_io REG_IMR
mov ax, INTERRUPT_MASK
out dx, ax
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
call cable
 
; Indicate that we have successfully reset the card
xor eax, eax
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
transmit:
DEBUGF 1, "\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
DEBUGF 1, "To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
 
cmp dword [esp+8], MAX_ETH_FRAME_SIZE
ja .fail
cmp dword [esp+8], 60
jb .fail
 
; check if we own the current discriptor
set_io 0
set_io REG_TSD0
movzx ecx, [device.curr_tx_desc]
shl ecx, 2
add edx, ecx
in eax, dx
test eax, (1 shl BIT_OWN)
jz .wait_to_send
 
.send_packet:
; get next descriptor
inc [device.curr_tx_desc]
and [device.curr_tx_desc], NUM_TX_DESC-1
 
; Update stats
inc [device.packets_tx]
mov eax, [esp+8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx+4], 0
 
; Set the buffer address
set_io REG_TSAD0
mov eax, [esp+4]
mov [device.TX_DESC+ecx], eax
GetRealAddr
out dx, eax
 
; And the size of the buffer
set_io REG_TSD0
mov eax, [esp+8]
or eax, (ERTXTH shl BIT_ERTXTH) ; Early threshold
out dx, eax
 
DEBUGF 1, "Packet Sent!\n"
xor eax, eax
ret 8
 
.wait_to_send:
DEBUGF 1, "Waiting for timeout\n"
 
push edx
mov esi, 30
stdcall Sleep
pop edx
 
in ax, dx
test ax, (1 shl BIT_OWN)
jnz .send_packet
 
pusha
call reset ; if chip hung, reset it
popa
 
jmp .send_packet
 
.fail:
DEBUGF 1, "failed!\n"
stdcall KernelFree, [esp+4]
or eax, -1
ret 8
 
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_handler:
 
DEBUGF 1, "\n%s int\n", my_service
 
; find pointer of device wich made IRQ occur
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
set_io 0
set_io REG_ISR
in ax, dx ; Get interrupt status
out dx, ax ; send it back to ACK
test ax, ax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
 
.got_it:
 
DEBUGF 1, "Device: %x Status: %x\n", ebx, ax
 
;----------------------------------------------------
; Received packet ok?
 
test ax, ISR_ROK
jz @f
push ax
 
.receive:
set_io 0
set_io REG_COMMAND
in al, dx
test al, BUFE ; test if RX buffer is empty
jnz .finish
 
DEBUGF 1, "RX: "
 
mov eax, [device.rx_buffer]
add eax, [device.rx_data_offset]
test byte [eax], (1 shl BIT_ROK) ; check if packet is ok
jz .reset_rx
 
; packet is ok, copy it
movzx ecx, word [eax+2] ; packet length
sub cx, 4 ; don't copy CRC
 
; Update stats
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
inc [device.packets_rx]
 
DEBUGF 1, "Received %u bytes\n", ecx
 
push ebx eax ecx
stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
pop ecx
test eax, eax ; Test if we allocated succesfully
jz .abort
 
mov edi, eax ; Where we will copy too
 
mov esi, [esp] ; The buffer we will copy from
add esi, 4 ; Dont copy CRC
 
push dword .abort ; Kernel will return to this address after EthReceiver
push ecx edi ; Save buffer pointer and size, to pass to kernel
 
.copy:
shr ecx, 1
jnc .nb
movsb
.nb:
shr ecx, 1
jnc .nw
movsw
.nw:
jz .nd
rep movsd
.nd:
 
jmp Eth_input ; Send it to kernel
 
.abort:
pop eax ebx
; update eth_data_start_offset
movzx eax, word [eax+2] ; packet length
add eax, [device.rx_data_offset]
add eax, 4+3 ; packet header is 4 bytes long + dword alignment
and eax, not 3 ; dword alignment
 
cmp eax, RX_BUFFER_SIZE
jb .no_wrap
DEBUGF 2, "Wrapping"
sub eax, RX_BUFFER_SIZE
.no_wrap:
mov [device.rx_data_offset], eax
DEBUGF 1, "New RX ptr: %d\n", eax
 
set_io 0
set_io REG_CAPR ; update 'Current Address of Packet Read register'
sub eax, 0x10 ; value 0x10 is a constant for CAPR
out dx , ax
 
jmp .receive ; check for multiple packets
 
.reset_rx:
test byte [eax], (1 shl BIT_CRC)
jz .no_crc_error
DEBUGF 2, "\nCRC error!\n"
 
.no_crc_error:
test byte [eax], (1 shl BIT_FAE)
jz .no_fae_error
DEBUGF 1, "\nFrame alignment error!\n"
 
.no_fae_error:
DEBUGF 1, "Reset RX\n"
in al, dx ; read command register
push ax
and al, not (1 shl BIT_RE) ; Clear the RE bit
out dx, al
pop ax
out dx, al ; write original command back
 
add edx, REG_RXCONFIG - REG_COMMAND ; Restore RX configuration
mov ax, RX_CONFIG
out dx, ax
 
.finish:
pop ax
 
;----------------------------------------------------
; Transmit ok / Transmit error
@@:
test ax, ISR_TOK + ISR_TER
jz @f
 
push ax
mov ecx, (NUM_TX_DESC-1)*4
.txdescloop:
set_io 0
set_io REG_TSD0
add edx, ecx
in eax, dx
 
test eax, TSR_OWN ; DMA operation completed
jz .notthisone
 
cmp [device.TX_DESC+ecx], 0
je .notthisone
 
; .notxd:
; test eax, TSR_TUN
; jz .nobun
; DEBUGF 2, "TX: FIFO Buffer underrun!\n"
;
; .nobun:
; test eax, TSR_OWC
; jz .noowc
; DEBUGF 2, "TX: OWC!\n"
;
; .noowc:
; test eax, TSR_TABT
; jz .notabt
; DEBUGF 2, "TX: TABT!\n"
;
; .notabt:
; test eax, TSR_CRS
; jz .nocsl
; DEBUGF 2, "TX: Carrier Sense Lost!\n"
;
; .nocsl:
 
DEBUGF 1, "TX OK: free buffer %x\n", [device.TX_DESC+ecx]:8
push ecx ebx
stdcall KernelFree, [device.TX_DESC+ecx]
pop ebx ecx
mov [device.TX_DESC+ecx], 0
 
.notthisone:
sub ecx, 4
ja .txdescloop
pop ax
 
;----------------------------------------------------
; Rx buffer overflow ?
@@:
test ax, ISR_RXOVW
jz @f
 
push ax
DEBUGF 2, "RX-buffer overflow!\n"
 
set_io 0
set_io REG_ISR
mov ax, ISR_FIFOOVW or ISR_RXOVW
out dx, ax
pop ax
 
;----------------------------------------------------
; Packet underrun?
@@:
test ax, ISR_PUN
jz @f
 
DEBUGF 2, "Packet underrun!\n"
 
;----------------------------------------------------
; Receive FIFO overflow ?
@@:
test ax, ISR_FIFOOVW
jz @f
 
push ax
DEBUGF 2, "RX fifo overflow!\n"
 
set_io 0
set_io REG_ISR
mov ax, ISR_FIFOOVW or ISR_RXOVW
out dx, ax
pop ax
 
;----------------------------------------------------
; Something about Cable changed ?
@@:
test ax, ISR_LENCHG
jz .fail
 
call cable
 
.fail:
DEBUGF 2, "\n"
ret
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Update Cable status ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
cable:
DEBUGF 1, "Updating Cable status\n"
 
set_io 0
set_io REG_MSR
in al, dx
 
test al, 1 shl 2 ; 0 = link ok 1 = link fail
jnz .notconnected
 
test al, 1 shl 3 ; 0 = 100 Mbps 1 = 10 Mbps
jnz .10mbps
 
.100mbps:
mov [device.state], ETH_LINK_100M
call NetLinkChanged
 
ret
 
.10mbps:
mov [device.state], ETH_LINK_10M
call NetLinkChanged
 
ret
 
.notconnected:
mov [device.state], ETH_LINK_DOWN
call NetLinkChanged
 
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Write MAC address ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
write_mac: ; in: mac pushed onto stack (as 3 words)
 
DEBUGF 2, "Writing MAC: "
 
; disable all in command registers
set_io 0
set_io REG_9346CR
xor eax, eax
out dx, al
 
set_io REG_IMR
xor eax, eax
out dx, ax
 
set_io REG_ISR
mov eax, -1
out dx, ax
 
; enable writing
set_io REG_9346CR
mov eax, REG_9346CR_WE
out dx, al
 
; write the mac ...
set_io REG_IDR0
pop eax
out dx, eax
 
set_io REG_IDR0+4
xor eax, eax
pop ax
out dx, eax
 
; disable writing
set_io REG_9346CR
xor eax, eax
out dx, al
 
DEBUGF 2, "ok!\n"
 
; Notice this procedure does not ret, but continues to read_mac instead.
 
 
;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Read MAC address ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;
 
read_mac:
DEBUGF 2, "Reading MAC: "
 
set_io 0
lea edi, [device.mac]
in eax, dx
stosd
add edx, 4
in ax, dx
stosw
 
DEBUGF 2, "%x-%x-%x-%x-%x-%x\n",[edi-6]:2,[edi-5]:2,[edi-4]:2,[edi-3]:2,[edi-2]:2,[edi-1]:2
 
ret
 
 
; End of code
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
align 4 ; Place all initialised data here
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'RTL8139',0 ; max 16 chars include zero
 
device_1 db 'Realtek 8139',0
device_2 db 'Realtek 8139A',0
device_3 db 'Realtek 8139B',0
device_4 db 'Realtek 8139C',0
device_5 db 'Realtek 8100',0
device_6 db 'Realtek 8139D',0
device_7 db 'Realtek 8139CP',0
device_8 db 'Realtek 8101',0
device_unknown db 'Unknown RTL8139 clone', 0
 
crosslist:
dd device_1
dd device_2
dd device_3
dd device_4
dd device_5
dd device_6
dd device_7
dd device_8
dd device_unknown
 
hw_ver_array: ; This array is used by the probe routine to find out wich version of the RTL8139 we are working with
db VER_RTL8139
db VER_RTL8139A
db VER_RTL8139B
db VER_RTL8139C
db VER_RTL8100
db VER_RTL8139D
db VER_RTL8139CP
db VER_RTL8101
db 0
 
HW_VER_ARRAY_SIZE = $-hw_ver_array
 
include_debug_strings ; All data wich FDO uses will be included here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/drivers/bus/mii.inc
0,0 → 1,160
; Generic MII registers.
 
MII_BMCR = 0x00 ; Basic mode control register
MII_BMSR = 0x01 ; Basic mode status register
MII_PHYSID1 = 0x02 ; PHYS ID 1
MII_PHYSID2 = 0x03 ; PHYS ID 2
MII_ADVERTISE = 0x04 ; Advertisement control reg
MII_LPA = 0x05 ; Link partner ability reg
MII_EXPANSION = 0x06 ; Expansion register
MII_CTRL1000 = 0x09 ; 1000BASE-T control
MII_STAT1000 = 0x0a ; 1000BASE-T status
MII_ESTATUS = 0x0f ; Extended Status
MII_DCOUNTER = 0x12 ; Disconnect counter
MII_FCSCOUNTER = 0x13 ; False carrier counter
MII_NWAYTEST = 0x14 ; N-way auto-neg test reg
MII_RERRCOUNTER = 0x15 ; Receive error counter
MII_SREVISION = 0x16 ; Silicon revision
MII_RESV1 = 0x17 ; Reserved...
MII_LBRERROR = 0x18 ; Lpback, rx, bypass error
MII_PHYADDR = 0x19 ; PHY address
MII_RESV2 = 0x1a ; Reserved...
MII_TPISTATUS = 0x1b ; TPI status for 10mbps
MII_NCONFIG = 0x1c ; Network interface config
 
; Basic mode control register.
 
BMCR_RESV = 0x003f ; Unused...
BMCR_SPEED1000 = 0x0040 ; MSB of Speed (1000)
BMCR_CTST = 0x0080 ; Collision test
BMCR_FULLDPLX = 0x0100 ; Full duplex
BMCR_ANRESTART = 0x0200 ; Auto negotiation restart
BMCR_ISOLATE = 0x0400 ; Disconnect DP83840 from MII
BMCR_PDOWN = 0x0800 ; Powerdown the DP83840
BMCR_ANENABLE = 0x1000 ; Enable auto negotiation
BMCR_SPEED100 = 0x2000 ; Select 100Mbps
BMCR_LOOPBACK = 0x4000 ; TXD loopback bits
BMCR_RESET = 0x8000 ; Reset the DP83840
 
; Basic mode status register.
 
BMSR_ERCAP = 0x0001 ; Ext-reg capability
BMSR_JCD = 0x0002 ; Jabber detected
BMSR_LSTATUS = 0x0004 ; Link status
BMSR_ANEGCAPABLE = 0x0008 ; Able to do auto-negotiation
BMSR_RFAULT = 0x0010 ; Remote fault detected
BMSR_ANEGCOMPLETE = 0x0020 ; Auto-negotiation complete
BMSR_RESV = 0x00c0 ; Unused...
BMSR_ESTATEN = 0x0100 ; Extended Status in R15
BMSR_100HALF2 = 0x0200 ; Can do 100BASE-T2 HDX
BMSR_100FULL2 = 0x0400 ; Can do 100BASE-T2 FDX
BMSR_10HALF = 0x0800 ; Can do 10mbps, half-duplex
BMSR_10FULL = 0x1000 ; Can do 10mbps, full-duplex
BMSR_100HALF = 0x2000 ; Can do 100mbps, half-duplex
BMSR_100FULL = 0x4000 ; Can do 100mbps, full-duplex
BMSR_100BASE4 = 0x8000 ; Can do 100mbps, 4k packets
 
; Advertisement control register.
 
ADVERTISE_SLCT = 0x001f ; Selector bits
ADVERTISE_CSMA = 0x0001 ; Only selector supported
ADVERTISE_10HALF = 0x0020 ; Try for 10mbps half-duplex
ADVERTISE_1000XFULL = 0x0020 ; Try for 1000BASE-X full-duplex
ADVERTISE_10FULL = 0x0040 ; Try for 10mbps full-duplex
ADVERTISE_1000XHALF = 0x0040 ; Try for 1000BASE-X half-duplex
ADVERTISE_100HALF = 0x0080 ; Try for 100mbps half-duplex
ADVERTISE_1000XPAUSE = 0x0080 ; Try for 1000BASE-X pause
ADVERTISE_100FULL = 0x0100 ; Try for 100mbps full-duplex
ADVERTISE_1000XPSE_ASYM = 0x0100 ; Try for 1000BASE-X asym pause
ADVERTISE_100BASE4 = 0x0200 ; Try for 100mbps 4k packets
ADVERTISE_PAUSE_CAP = 0x0400 ; Try for pause
ADVERTISE_PAUSE_ASYM = 0x0800 ; Try for asymetric pause
ADVERTISE_RESV = 0x1000 ; Unused...
ADVERTISE_RFAULT = 0x2000 ; Say we can detect faults
ADVERTISE_LPACK = 0x4000 ; Ack link partners response
ADVERTISE_NPAGE = 0x8000 ; Next page bit
 
ADVERTISE_FULL = (ADVERTISE_100FULL or ADVERTISE_10FULL or ADVERTISE_CSMA)
ADVERTISE_ALL = (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL)
 
; Link partner ability register.
 
LPA_SLCT = 0x001f ; Same as advertise selector
LPA_10HALF = 0x0020 ; Can do 10mbps half-duplex
LPA_1000XFULL = 0x0020 ; Can do 1000BASE-X full-duplex
LPA_10FULL = 0x0040 ; Can do 10mbps full-duplex
LPA_1000XHALF = 0x0040 ; Can do 1000BASE-X half-duplex
LPA_100HALF = 0x0080 ; Can do 100mbps half-duplex
LPA_1000XPAUSE = 0x0080 ; Can do 1000BASE-X pause
LPA_100FULL = 0x0100 ; Can do 100mbps full-duplex
LPA_1000XPAUSE_ASYM = 0x0100 ; Can do 1000BASE-X pause asym
LPA_100BASE4 = 0x0200 ; Can do 100mbps 4k packets
LPA_PAUSE_CAP = 0x0400 ; Can pause
LPA_PAUSE_ASYM = 0x0800 ; Can pause asymetrically
LPA_RESV = 0x1000 ; Unused...
LPA_RFAULT = 0x2000 ; Link partner faulted
LPA_LPACK = 0x4000 ; Link partner acked us
LPA_NPAGE = 0x8000 ; Next page bit
 
LPA_DUPLEX = (LPA_10FULL or LPA_100FULL)
LPA_100 = (LPA_100FULL or LPA_100HALF or LPA_100BASE4)
 
; Expansion register for auto-negotiation.
 
EXPANSION_NWAY = 0x0001 ; Can do N-way auto-nego
EXPANSION_LCWP = 0x0002 ; Got new RX page code word
EXPANSION_ENABLENPAGE = 0x0004 ; This enables npage words
EXPANSION_NPCAPABLE = 0x0008 ; Link partner supports npage
EXPANSION_MFAULTS = 0x0010 ; Multiple faults detected
EXPANSION_RESV = 0xffe0 ; Unused...
 
ESTATUS_1000_TFULL = 0x2000 ; Can do 1000BT Full
ESTATUS_1000_THALF = 0x1000 ; Can do 1000BT Half
 
; N-way test register.
 
NWAYTEST_RESV1 = 0x00ff ; Unused...
NWAYTEST_LOOPBACK = 0x0100 ; Enable loopback for N-way
NWAYTEST_RESV2 = 0xfe00 ; Unused...
 
; 1000BASE-T Control register
 
ADVERTISE_1000FULL = 0x0200 ; Advertise 1000BASE-T full duplex
ADVERTISE_1000HALF = 0x0100 ; Advertise 1000BASE-T half duplex
 
; 1000BASE-T Status register
 
LPA_1000LOCALRXOK = 0x2000 ; Link partner local receiver status
LPA_1000REMRXOK = 0x1000 ; Link partner remote receiver status
LPA_1000FULL = 0x0800 ; Link partner 1000BASE-T full duplex
LPA_1000HALF = 0x0400 ; Link partner 1000BASE-T half duplex
 
; Flow control flags
 
FLOW_CTRL_TX = 0x01
FLOW_CTRL_RX = 0x02
 
 
 
if used mii_link_ok
 
align 4
mii_link_ok:
 
DEBUGF 1, "mii_link_ok\n"
 
; First do a dummy read to latch some MII phys
 
mov ecx, MII_BMSR
call mdio_read
 
mov ecx, MII_BMSR
call mdio_read
 
and ax, BMSR_LSTATUS
 
DEBUGF 1, "link status=0x%x\n", ax
 
ret
 
end if
/kernel/branches/net/drivers/bus/pci.inc
0,0 → 1,132
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
; PCI Bus defines
 
PCI_HEADER_TYPE = 0x0e ; 8 bit
PCI_BASE_ADDRESS_0 = 0x10 ; 32 bit
PCI_BASE_ADDRESS_1 = 0x14 ; 32 bits
PCI_BASE_ADDRESS_2 = 0x18 ; 32 bits
PCI_BASE_ADDRESS_3 = 0x1c ; 32 bits
PCI_BASE_ADDRESS_4 = 0x20 ; 32 bits
PCI_BASE_ADDRESS_5 = 0x24 ; 32 bits
PCI_BASE_ADDRESS_SPACE_IO = 0x01
PCI_BASE_ADDRESS_IO_MASK = 0xFFFFFFFC
PCI_BASE_ADDRESS_MEM_MASK = 0xFFFFFFF0
 
; PCI programming
 
PCI_VENDOR_ID = 0x00 ; 16 bit
PCI_DEVICE_ID = 0x02 ; 16 bits
PCI_REG_COMMAND = 0x4 ; command register
PCI_REG_STATUS = 0x6 ; status register
PCI_REVISION_ID = 0x08 ; 8 bits
PCI_REG_LATENCY = 0xd ; latency timer register
PCI_REG_CAP_PTR = 0x34 ; capabilities pointer
PCI_REG_IRQ = 0x3c
PCI_REG_CAPABILITY_ID = 0x0 ; capapility ID in pm register block
PCI_REG_PM_STATUS = 0x4 ; power management status register
PCI_REG_PM_CTRL = 0x4 ; power management control register
PCI_BIT_PIO = 1 ; bit0: io space control
PCI_BIT_MMIO = 2 ; bit1: memory space control
PCI_BIT_MASTER = 4 ; bit2: device acts as a PCI master
 
 
macro PCI_find_io {
 
local .check, .inc, .got
 
xor eax, eax
mov esi, PCI_BASE_ADDRESS_0
.check:
stdcall PciRead32, [device.pci_bus], [device.pci_dev], esi
 
test eax, PCI_BASE_ADDRESS_IO_MASK
jz .inc
 
test eax, PCI_BASE_ADDRESS_SPACE_IO
jz .inc
 
and eax, PCI_BASE_ADDRESS_IO_MASK
jmp .got
 
.inc:
add esi, 4
cmp esi, PCI_BASE_ADDRESS_5
jbe .check
xor eax, eax
 
.got:
mov [device.io_addr], eax
 
}
 
 
macro PCI_find_mmio32 {
 
local .check, .inc, .got
 
mov esi, PCI_BASE_ADDRESS_0
.check:
stdcall PciRead32, [device.pci_bus], [device.pci_dev], esi
 
test eax, PCI_BASE_ADDRESS_SPACE_IO ; mmio address?
jnz .inc
 
test eax, 100b ; 64 bit?
jnz .inc
and eax, not 1111b
jmp .got
 
.inc:
add esi, 4
cmp esi, PCI_BASE_ADDRESS_5
jbe .check
xor eax, eax
 
.got:
mov [device.mmio_addr], eax
}
 
macro PCI_find_irq {
 
stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REG_IRQ
mov [device.irq_line], al
 
}
 
macro PCI_find_rev {
 
stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REVISION_ID
mov [device.revision], al
 
}
 
macro PCI_make_bus_master bus, dev {
 
stdcall PciRead32, [device.pci_bus], [device.pci_dev], PCI_REG_COMMAND
or al, PCI_BIT_MASTER
stdcall PciWrite32, [device.pci_bus], [device.pci_dev], PCI_REG_COMMAND, eax
 
}
 
macro PCI_adjust_latency min {
 
local .not
 
stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REG_LATENCY
cmp al, min
ja .not
mov al, min
stdcall PciWrite8, [device.pci_bus], [device.pci_dev], PCI_REG_LATENCY, eax
.not:
 
}
/kernel/branches/net/drivers/pcnet32.asm
0,0 → 1,1570
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; AMD PCnet driver for KolibriOS ;;
;; ;;
;; By hidnplayr & clevermouse ;;
;; ;;
;; Based on the PCnet32 driver for MenuetOS, by Jarek Pelczar ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
MAX_DEVICES = 4
MAX_ETH_FRAME_SIZE = 1514
 
TX_RING_SIZE = 4
RX_RING_SIZE = 4
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
 
public START
public service_proc
public version
 
 
PORT_AUI = 0x00
PORT_10BT = 0x01
PORT_GPSI = 0x02
PORT_MII = 0x03
PORT_PORTSEL = 0x03
PORT_ASEL = 0x04
PORT_100 = 0x40
PORT_FD = 0x80
 
DMA_MASK = 0xffffffff
 
LOG_TX_BUFFERS = 2 ; FIXME
LOG_RX_BUFFERS = 2
 
TX_RING_MOD_MASK = (TX_RING_SIZE-1)
TX_RING_LEN_BITS = (LOG_TX_BUFFERS shl 12)
 
RX_RING_MOD_MASK = (RX_RING_SIZE-1)
RX_RING_LEN_BITS = (LOG_RX_BUFFERS shl 4)
 
PKT_BUF_SZ = 1544
 
WIO_RDP = 0x10
WIO_RAP = 0x12
WIO_RESET = 0x14
WIO_BDP = 0x16
 
DWIO_RDP = 0x10
DWIO_RAP = 0x14
DWIO_RESET = 0x18
DWIO_BDP = 0x1C
 
; CSR registers
 
CSR_CSR = 0x00
CSR_IAB0 = 0x01
CSR_IAB1 = 0x02
CSR_IMR = 0x03
CSR_TFEAT = 0x04
CSR_EXTCTL1 = 0x05
CSR_DTBLLEN = 0x06
CSR_EXTCTL2 = 0x07
CSR_MAR0 = 0x08
CSR_MAR1 = 0x09
CSR_MAR2 = 0x0A
CSR_MAR3 = 0x0B
CSR_PAR0 = 0x0C
CSR_PAR1 = 0x0D
CSR_PAR2 = 0x0E
CSR_MODE = 0x0F
CSR_RXADDR0 = 0x18
CSR_RXADDR1 = 0x19
CSR_TXADDR0 = 0x1E
CSR_TXADDR1 = 0x1F
CSR_TXPOLL = 0x2F
CSR_RXPOLL = 0x31
CSR_RXRINGLEN = 0x4C
CSR_TXRINGLEN = 0x4E
CSR_DMACTL = 0x50
CSR_BUSTIMER = 0x52
CSR_MEMERRTIMEO = 0x64
CSR_ONNOWMISC = 0x74
CSR_ADVFEAT = 0x7A
CSR_MACCFG = 0x7D
CSR_CHIPID0 = 0x58
CSR_CHIPID1 = 0x59
 
; Control and Status Register (CSR0)
 
CSR_INIT = 1 shl 0
CSR_START = 1 shl 1
CSR_STOP = 1 shl 2
CSR_TX = 1 shl 3
CSR_TXON = 1 shl 4
CSR_RXON = 1 shl 5
CSR_INTEN = 1 shl 6
CSR_INTR = 1 shl 7
CSR_IDONE = 1 shl 8
CSR_TINT = 1 shl 9
CSR_RINT = 1 shl 10
CSR_MERR = 1 shl 11
CSR_MISS = 1 shl 12
CSR_CERR = 1 shl 13
 
; Interrupt masks and deferral control (CSR3)
 
IMR_BSWAP = 0x0004
IMR_ENMBA = 0x0008 ; enable modified backoff alg
IMR_DXMT2PD = 0x0010
IMR_LAPPEN = 0x0020 ; lookahead packet processing enb
IMR_DXSUFLO = 0x0040 ; disable TX stop on underflow
IMR_IDONE = 0x0100
IMR_TINT = 0x0200
IMR_RINT = 0x0400
IMR_MERR = 0x0800
IMR_MISS = 0x1000
 
IMR = IMR_IDONE ; IMR_TINT + IMR_RINT + IMR_MERR + IMR_MISS ;+ IMR_IDONE
 
; Test and features control (CSR4)
 
TFEAT_TXSTRTMASK = 0x0004
TFEAT_TXSTRT = 0x0008
TFEAT_RXCCOFLOWM = 0x0010 ; Rx collision counter oflow
TFEAT_RXCCOFLOW = 0x0020
TFEAT_UINT = 0x0040
TFEAT_UINTREQ = 0x0080
TFEAT_MISSOFLOWM = 0x0100
TFEAT_MISSOFLOW = 0x0200
TFEAT_STRIP_FCS = 0x0400
TFEAT_PAD_TX = 0x0800
TFEAT_TXDPOLL = 0x1000
TFEAT_DMAPLUS = 0x4000
 
; Extended control and interrupt 1 (CSR5)
 
EXTCTL1_SPND = 0x0001 ; suspend
EXTCTL1_MPMODE = 0x0002 ; magic packet mode
EXTCTL1_MPENB = 0x0004 ; magic packet enable
EXTCTL1_MPINTEN = 0x0008 ; magic packet interrupt enable
EXTCTL1_MPINT = 0x0010 ; magic packet interrupt
EXTCTL1_MPPLBA = 0x0020 ; magic packet phys. logical bcast
EXTCTL1_EXDEFEN = 0x0040 ; excessive deferral interrupt enb.
EXTCTL1_EXDEF = 0x0080 ; excessive deferral interrupt
EXTCTL1_SINTEN = 0x0400 ; system interrupt enable
EXTCTL1_SINT = 0x0800 ; system interrupt
EXTCTL1_LTINTEN = 0x4000 ; last TX interrupt enb
EXTCTL1_TXOKINTD = 0x8000 ; TX OK interrupt disable
 
; RX/TX descriptor len (CSR6)
 
DTBLLEN_RLEN = 0x0F00
DTBLLEN_TLEN = 0xF000
 
; Extended control and interrupt 2 (CSR7)
 
EXTCTL2_MIIPDTINTE = 0x0001
EXTCTL2_MIIPDTINT = 0x0002
EXTCTL2_MCCIINTE = 0x0004
EXTCTL2_MCCIINT = 0x0008
EXTCTL2_MCCINTE = 0x0010
EXTCTL2_MCCINT = 0x0020
EXTCTL2_MAPINTE = 0x0040
EXTCTL2_MAPINT = 0x0080
EXTCTL2_MREINTE = 0x0100
EXTCTL2_MREINT = 0x0200
EXTCTL2_STINTE = 0x0400
EXTCTL2_STINT = 0x0800
EXTCTL2_RXDPOLL = 0x1000
EXTCTL2_RDMD = 0x2000
EXTCTL2_RXFRTG = 0x4000
EXTCTL2_FASTSPNDE = 0x8000
 
; Mode (CSR15)
 
MODE_RXD = 0x0001 ; RX disable
MODE_TXD = 0x0002 ; TX disable
MODE_LOOP = 0x0004 ; loopback enable
MODE_TXCRCD = 0x0008
MODE_FORCECOLL = 0x0010
MODE_RETRYD = 0x0020
MODE_INTLOOP = 0x0040
MODE_PORTSEL = 0x0180
MODE_RXVPAD = 0x2000
MODE_RXNOBROAD = 0x4000
MODE_PROMISC = 0x8000
 
; BCR (Bus Control Registers)
 
BCR_MMRA = 0x00 ; Master Mode Read Active
BCR_MMW = 0x01 ; Master Mode Write Active
BCR_MISCCFG = 0x02
BCR_LED0 = 0x04
BCR_LED1 = 0x05
BCR_LED2 = 0x06
BCR_LED3 = 0x07
BCR_DUPLEX = 0x09
BCR_BUSCTL = 0x12
BCR_EECTL = 0x13
BCR_SSTYLE = 0x14
BCR_PCILAT = 0x16
BCR_PCISUBVENID = 0x17
BCR_PCISUBSYSID = 0x18
BCR_SRAMSIZE = 0x19
BCR_SRAMBOUND = 0x1A
BCR_SRAMCTL = 0x1B
BCR_MIICTL = 0x20
BCR_MIIADDR = 0x21
BCR_MIIDATA = 0x22
BCR_PCIVENID = 0x23
BCR_PCIPCAP = 0x24
BCR_DATA0 = 0x25
BCR_DATA1 = 0x26
BCR_DATA2 = 0x27
BCR_DATA3 = 0x28
BCR_DATA4 = 0x29
BCR_DATA5 = 0x2A
BCR_DATA6 = 0x2B
BCR_DATA7 = 0x2C
BCR_ONNOWPAT0 = 0x2D
BCR_ONNOWPAT1 = 0x2E
BCR_ONNOWPAT2 = 0x2F
BCR_PHYSEL = 0x31
 
; RX status register
 
RXSTAT_BPE = 0x0080 ; bus parity error
RXSTAT_ENP = 0x0100 ; end of packet
RXSTAT_STP = 0x0200 ; start of packet
RXSTAT_BUFF = 0x0400 ; buffer error
RXSTAT_CRC = 0x0800 ; CRC error
RXSTAT_OFLOW = 0x1000 ; rx overrun
RXSTAT_FRAM = 0x2000 ; framing error
RXSTAT_ERR = 0x4000 ; error summary
RXSTAT_OWN = 0x8000
 
; TX status register
 
TXSTAT_TRC = 0x0000000F ; transmit retries
TXSTAT_RTRY = 0x04000000 ; retry
TXSTAT_LCAR = 0x08000000 ; lost carrier
TXSTAT_LCOL = 0x10000000 ; late collision
TXSTAT_EXDEF = 0x20000000 ; excessive deferrals
TXSTAT_UFLOW = 0x40000000 ; transmit underrun
TXSTAT_BUFF = 0x80000000 ; buffer error
 
TXCTL_OWN = 0x8000
TXCTL_ERR = 0x4000 ; error summary
TXCTL_ADD_FCS = 0x2000 ; add FCS to pkt
TXCTL_MORE_LTINT = 0x1000
TXCTL_ONE = 0x0800
TXCTL_DEF = 0x0400
TXCTL_STP = 0x0200
TXCTL_ENP = 0x0100
TXCTL_BPE = 0x0080
 
TXCTL_MBO = 0x0000F000
TXCTL_BUFSZ = 0x00000FFF
 
;
 
MAX_PHYS = 32
 
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
; device specific
 
rb 0x100-(($ - device) and 0xff) ; align 256
.private:
.mode_ dw ?
.tlen_rlen dw ?
.phys_addr dp ?
.reserved dw ?
.filter dq ?
.rx_ring_phys dd ?
.tx_ring_phys dd ?
 
rb 0x100-(($ - device) and 0xff) ; align 256
.rx_ring rb RX_RING_SIZE * descriptor.size
 
rb 0x100-(($ - device) and 0xff) ; align 256
.tx_ring rb TX_RING_SIZE * descriptor.size
 
.cur_rx db ?
.cur_tx db ?
.last_tx db ?
.options dd ?
.full_duplex db ?
.chip_version dw ?
.mii db ?
.ltint db ?
.dxsuflo db ?
.fset db ?
.fdx db ?
 
.io_addr dd ?
.irq_line db ?
.pci_bus dd ?
.pci_dev dd ?
 
.phy dw ?
 
.read_csr dd ?
.write_csr dd ?
.read_bcr dd ?
.write_bcr dd ?
.read_rap dd ?
.write_rap dd ?
.sw_reset dd ?
 
device_size = $ - device
 
end virtual
 
struc descriptor {
.base dd ?
.length dw ?
.status dw ?
.msg_length dw ?
.misc dw ?
.virtual dd ?
 
.size:
}
 
virtual at 0
descriptor descriptor
end virtual
 
 
 
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
 
.entry:
 
DEBUGF 1,"Loading %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
 
.fail:
.exit:
xor eax, eax
ret
 
endp
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne @F
 
cmp [IOCTL.out_size], 4
jb .fail
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
 
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
 
mov eax, [IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet
 
; check if the device is already listed
 
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
mov esi, device_list
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax , [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
 
; This device doesnt have its own eth_device structure yet, lets create one
 
.firstdevice:
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, device_size, .fail
 
; Fill in the direct call addresses into the struct
 
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], unload
mov [device.name], my_service
 
; save the pci bus and device numbers
 
mov eax, [IOCTL.input]
movzx ecx, byte[eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte[eax+2]
mov [device.pci_dev], ecx
 
; Now, it's time to find the base io addres of the PCI device
 
PCI_find_io
 
; We've found the io address, find IRQ now
 
PCI_find_irq
 
DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
 
; Ok, the eth_device structure is ready, let's probe the device
; Because initialization fires IRQ, IRQ handler must be aware of this device
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
 
call probe ; this function will output in eax
test eax, eax
jnz .destroy ; If an error occured, exit
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
cmp eax, -1
je .destroy
 
ret
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 1,"Trying to find device number of already registered device\n"
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 1,"Kernel says: %u\n", eax
ret
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
; todo: reset device into virgin state
 
dec [devices]
.err:
DEBUGF 1,"Error, removing all data !\n"
stdcall KernelFree, ebx
 
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
align 4
unload:
; TODO: (in this particular order)
;
; - Stop the device
; - Detach int handler
; - Remove device from local list (RTL8139_LIST)
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
 
or eax,-1
 
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; probe: enables the device (if it really is a PCnet device)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
probe:
 
mov edx, [device.io_addr]
 
call wio_reset
 
xor ecx, ecx
call wio_read_csr
cmp eax, 4
jne .try_dwio
 
; Try Word I/O
mov ax, 88
add edx, WIO_RAP
out dx, ax
nop
nop
in ax, dx
sub edx, WIO_RAP
cmp ax, 88
jne .try_dwio
 
call switch_to_wio
 
jmp .L1
 
.try_dwio:
call dwio_reset
 
xor ecx, ecx
call dwio_read_csr
cmp eax, 4
jne .no_dev
 
; Try Dword I/O
add edx, DWIO_RAP
mov eax, 88
out dx, eax
nop
nop
in eax, dx
sub edx, DWIO_RAP
and eax, 0xffff
cmp eax, 88
jne .no_dev
 
call switch_to_dwio
 
jmp .L1
 
.no_dev:
DEBUGF 1,"PCnet device not found!\n"
mov eax, 1
ret
 
.L1:
mov ecx, CSR_CHIPID0
call [device.read_csr]
 
mov esi, eax
shr esi, 12
 
and ax, 0xfff
cmp ax, 3
jne .no_dev
 
mov ecx, CSR_CHIPID1
call [device.read_csr]
shl eax, 4
or eax, esi
mov [device.chip_version], ax
 
mov [device.fdx], 0
mov [device.mii], 0
mov [device.fset], 0
mov [device.dxsuflo], 0
mov [device.ltint], 0
 
cmp ax, 0x2420
je .L2
cmp ax, 0x2430
je .L2
 
mov [device.fdx], 1
 
cmp ax, 0x2621
je .L4
cmp ax, 0x2623
je .L5
cmp ax, 0x2624
je .L6
cmp ax, 0x2625
je .L7
cmp ax, 0x2626
je .L8
cmp ax, 0x2627
je .L9
 
DEBUGF 1,"Invalid chip rev\n"
jmp .no_dev
.L2:
mov [device.name], device_l2
jmp .L10
.L4:
mov [device.name], device_l4
; mov [device.fdx], 1
jmp .L10
.L5:
mov [device.name], device_l5
; mov [device.fdx], 1
mov [device.mii], 1
mov [device.fset], 1
mov [device.ltint], 1
jmp .L10
.L6:
mov [device.name], device_l6
; mov [device.fdx], 1
mov [device.mii], 1
mov [device.fset], 1
jmp .L10
.L7:
mov [device.name], device_l7
; mov [device.fdx], 1
mov [device.mii], 1
jmp .L10
.L8:
mov [device.name], device_l8
; mov [device.fdx], 1
mov ecx, CSR_RXPOLL
call dword [device.read_bcr]
call dword [device.write_bcr]
jmp .L10
.L9:
mov [device.name], device_l9
; mov [device.fdx], 1
mov [device.mii], 1
.L10:
DEBUGF 1,"device name: %s\n", [device.name]
 
cmp [device.fset], 1
jne .L11
mov ecx, BCR_BUSCTL
call [device.read_bcr]
or eax, 0x800
call [device.write_bcr]
 
mov ecx, CSR_DMACTL
call [device.read_csr]
; and eax, 0xc00
; or eax, 0xc00
mov eax, 0xc00
call [device.write_csr]
 
mov [device.dxsuflo],1
mov [device.ltint],1
.L11:
 
PCI_make_bus_master
 
mov [device.options], PORT_ASEL
mov [device.mode_], MODE_RXD + MODE_TXD ; disable receive and transmit
mov [device.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
 
mov dword [device.filter], 0
mov dword [device.filter+4], 0
 
align 4
reset:
 
; attach int handler
 
movzx eax, [device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax
jnz @f
DEBUGF 1,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
mov edx, [device.io_addr]
 
call [device.sw_reset]
 
; Switch pcnet32 to 32bit mode
mov ecx, BCR_SSTYLE
mov eax, 2
call [device.write_bcr]
 
; set/reset autoselect bit
mov ecx, BCR_MISCCFG
call [device.read_bcr]
and eax, not 2
test [device.options], PORT_ASEL
jz @f
or eax, 2
@@:
call [device.write_bcr]
 
; Handle full duplex setting
cmp byte [device.full_duplex], 0
je .duplex_ok
mov ecx, BCR_DUPLEX
call [device.read_bcr]
and eax, not 3
test [device.options], PORT_FD
jz @f
or eax, 1
cmp [device.options], PORT_FD or PORT_AUI
jne .set_duplex
or eax, 2
jmp .set_duplex
@@:
test [device.options], PORT_ASEL
jz .set_duplex
cmp [device.chip_version], 0x2627
jne .set_duplex
or eax, 3
.set_duplex:
mov ecx, BCR_DUPLEX
call [device.write_bcr]
.duplex_ok:
 
; set/reset GPSI bit in test register
mov ecx, 124
call [device.read_csr]
mov ecx, [device.options]
and ecx, PORT_PORTSEL
cmp ecx, PORT_GPSI
jne @f
or eax, 0x10
@@:
call [device.write_csr]
cmp [device.mii], 0
je .L6
test [device.options], PORT_ASEL
jnz .L6
mov ecx, BCR_MIICTL
call [device.read_bcr]
and eax, not 0x38
test [device.options], PORT_FD
jz @f
or eax, 0x10
@@:
test [device.options], PORT_100
jz @f
or eax, 0x08
@@:
call [device.write_bcr]
jmp .L9
.L6:
test [device.options], PORT_ASEL
jz .L9
mov ecx, BCR_MIICTL
DEBUGF 1,"ASEL, enable auto-negotiation\n"
call [device.read_bcr]
and eax, not 0x98
or eax, 0x20
call [device.write_bcr]
.L9:
cmp [device.ltint], 0
je @f
mov ecx, 5
call [device.read_csr]
or eax, (1 shl 14)
call [device.write_csr]
@@:
mov eax, [device.options]
and eax, PORT_PORTSEL
shl eax, 7
mov [device.mode_], ax
mov dword [device.filter], -1
mov dword [device.filter+4], -1
 
 
 
;-----------------------------
 
test [device.mii], 1
jz .no_mii
 
mov [device.phy], 0
 
.mii_loop:
mov ecx, MII_PHYSID1
call mdio_read
cmp ax, 0xffff
je .next
 
DEBUGF 1, "0x%x\n", ax
 
mov ecx, MII_PHYSID2
call mdio_read
cmp ax, 0xffff
je .next
 
DEBUGF 1, "0x%x\n", ax
 
jmp .got_phy
 
cmp [device.phy], 31
jne .next
mov ax, [device.chip_version]
inc ax
and ax, 0xfffe
cmp ax, 0x2624 ; 79c971 & 79c972 have phantom phy at id 31
je .got_phy
 
.next:
inc [device.phy]
cmp [device.phy], MAX_PHYS
jb .mii_loop
 
DEBUGF 1, "No PHY found!\n"
 
or eax, -1
ret
 
.got_phy:
DEBUGF 1, "Found PHY at 0x%x\n", [device.phy]:4
 
.no_mii:
 
;-----------------------------------------------
 
call read_mac
 
lea esi, [device.mac]
lea edi, [device.phys_addr]
movsd
movsw
 
call init_ring
 
mov edx, [device.io_addr] ; init ring destroys edx
 
lea eax, [device.private]
GetRealAddr
push eax
and eax, 0xffff
mov ecx, 1
call [device.write_csr]
pop eax
shr eax, 16
mov ecx, 2
call [device.write_csr]
 
mov ecx, 4
mov eax, 0x0915
call [device.write_csr]
 
; Set the interrupt mask
mov ecx, CSR_IMR
mov eax, IMR
call [device.write_csr]
 
; Initialise the device
xor ecx, ecx
mov eax, CSR_INIT
call [device.write_csr]
 
mov esi, 100
; xor ecx, ecx
@@:
call [device.read_csr]
test ax, CSR_IDONE
jnz @f
 
dec esi
jnz @r
DEBUGF 1,"Initialize timeout!\n"
@@:
 
; Start the device and enable interrupts
xor ecx, ecx
mov eax, CSR_START + CSR_INTEN
call [device.write_csr]
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
; get link status
mov [device.state], ETH_LINK_UNKOWN
 
call check_media
 
DEBUGF 1,"reset complete\n"
xor eax, eax
ret
 
 
align 4
init_ring:
 
DEBUGF 1,"init ring\n"
 
lea edi, [device.rx_ring]
mov eax, edi
GetRealAddr
mov [device.rx_ring_phys], eax
mov ecx, RX_RING_SIZE
.rx_init:
push ecx
stdcall KernelAlloc, PKT_BUF_SZ
pop ecx
mov [edi + descriptor.virtual], eax
GetRealAddr
mov [edi + descriptor.base], eax
mov [edi + descriptor.length], - PKT_BUF_SZ
mov [edi + descriptor.status], RXSTAT_OWN
mov dword [edi + descriptor.msg_length], 0 ; also clears misc field
add edi, descriptor.size
dec ecx
jnz .rx_init
 
lea edi, [device.tx_ring]
mov eax, edi
GetRealAddr
mov [device.tx_ring_phys], eax
mov ecx, TX_RING_SIZE
.tx_init:
mov [edi + descriptor.status], 0
add edi, descriptor.size
dec ecx
jnz .tx_init
 
mov [device.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
 
mov [device.cur_tx], 0
mov [device.last_tx], 0
mov [device.cur_rx], 0
 
ret
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
transmit:
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
 
cmp dword [esp+8], 1514
ja .nospace ; packet is too long
cmp dword [esp+8], 60
jb .nospace ; packet is too short
 
; check descriptor
lea edi, [device.tx_ring]
movzx eax, [device.cur_tx]
shl eax, 4
add edi, eax
 
test [edi + descriptor.status], TXCTL_OWN
jnz .nospace
; descriptor is free, use it
mov eax, [esp+4]
mov [edi + descriptor.virtual], eax
GetRealAddr
mov [edi + descriptor.base], eax
; set length
mov eax, [esp+8]
neg eax
mov [edi + descriptor.length], ax
; put to transfer queue
mov [edi + descriptor.status], TXCTL_OWN + TXCTL_STP + TXCTL_ENP
 
; trigger an immediate send
mov edx, [device.io_addr]
xor ecx, ecx ; CSR0
call [device.read_csr]
or eax, CSR_TX
call [device.write_csr]
 
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
inc [device.cur_tx]
and [device.cur_tx], TX_RING_SIZE - 1
DEBUGF 2," - Packet Sent! "
 
; Update stats
inc [device.packets_tx]
mov eax, [esp+8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
.finish:
DEBUGF 2," - Done!\n"
xor eax, eax
ret 8
 
.nospace:
DEBUGF 1, 'ERROR: no free transmit descriptors\n'
stdcall KernelFree, [esp+4]
or eax, -1
ret 8
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_handler:
 
DEBUGF 1,"\n%s int\n", my_service
 
; find pointer of device wich made IRQ occur
 
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
mov edx, [device.io_addr]
push ecx
xor ecx, ecx ; CSR0
call [device.read_csr] ; get IRQ reason
call [device.write_csr] ; write it back to ACK
pop ecx
test ax, ax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
ret ; If no device was found, abort (The int was probably for a device, not registered to this driver)
 
.got_it:
DEBUGF 1,"Device: %x status: %x\n", ebx, eax:2
 
push ax
test ax, CSR_RINT
jz .not_receive
 
push ebx
.rx_loop:
pop ebx
movzx eax, [device.cur_rx]
shl eax, 4
lea edi, [device.rx_ring]
add edi, eax ; edi now points to current rx ring entry
 
mov ax, [edi + descriptor.status]
DEBUGF 1,"RX packet status: %x\n", eax:4
 
test ax, RXSTAT_OWN ; If this bit is set, the controller OWN's the packet, if not, we do
jnz .not_receive
 
test ax, RXSTAT_ENP
jz .not_receive
 
test ax, RXSTAT_STP
jz .not_receive
 
movzx ecx, [edi + descriptor.msg_length] ; get packet length in ecx
sub ecx, 4 ;
 
; Set pointers for ETH_input
push ebx
 
push .rx_loop ; return address
push ecx ; packet size
push [edi + descriptor.virtual] ; packet address
 
; Update stats
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
inc [device.packets_rx]
 
; now allocate a new buffer
stdcall KernelAlloc, PKT_BUF_SZ ; Allocate a buffer for the next packet
mov [edi + descriptor.virtual], eax ; set virtual address
GetRealAddr
mov [edi + descriptor.base], eax ; and real address
 
; mov word [edi + descriptor.length], - PKT_BUF_SZ
mov [edi + descriptor.status], RXSTAT_OWN ; give it back to PCnet controller
 
inc [device.cur_rx] ; set next receive descriptor
and [device.cur_rx], RX_RING_SIZE - 1
 
jmp Eth_input
 
.not_receive:
pop ax
 
test ax, CSR_TINT
jz .not_transmit
 
.tx_loop:
lea edi, [device.tx_ring]
movzx eax, [device.last_tx]
shl eax, 4
add edi, eax
 
test [edi + descriptor.status], TXCTL_OWN
jnz .not_transmit
 
mov eax, [edi + descriptor.virtual]
test eax, eax
jz .not_transmit
 
mov [edi + descriptor.virtual], 0
 
DEBUGF 1,"Removing packet %x from memory\n", eax
 
stdcall KernelFree, eax
 
inc [device.last_tx]
and [device.last_tx], TX_RING_SIZE - 1
jmp .tx_loop
 
.not_transmit:
 
ret
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Write MAC address ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
write_mac: ; in: mac pushed onto stack (as 3 words)
 
DEBUGF 1,"Writing MAC: %x-%x-%x-%x-%x-%x",[esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
 
mov edx, [device.io_addr]
add dx, 2
xor eax, eax
 
mov ecx, CSR_PAR0
@@:
pop ax
call [device.write_csr]
DEBUGF 1,"."
inc ecx
cmp ecx, CSR_PAR2
jb @r
 
DEBUGF 1,"\n"
 
; Notice this procedure does not ret, but continues to read_mac instead.
 
;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Read MAC address ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;
align 4
read_mac:
DEBUGF 1,"Reading MAC"
 
mov edx, [device.io_addr]
add dx, 6
@@:
dec dx
dec dx
in ax, dx
push ax
DEBUGF 1,"."
cmp edx, [device.io_addr]
ja @r
 
DEBUGF 1," %x-%x-%x-%x-%x-%x\n",[esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
 
lea edi, [device.mac]
pop ax
stosw
pop ax
stosw
pop ax
stosw
 
ret
 
align 4
switch_to_wio:
 
DEBUGF 1,"Switching to 16-bit mode\n"
 
mov [device.read_csr], wio_read_csr
mov [device.write_csr], wio_write_csr
mov [device.read_bcr], wio_read_bcr
mov [device.write_bcr], wio_write_bcr
mov [device.read_rap], wio_read_rap
mov [device.write_rap], wio_write_rap
mov [device.sw_reset], wio_reset
 
ret
 
align 4
switch_to_dwio:
 
DEBUGF 1,"Switching to 32-bit mode\n"
 
mov [device.read_csr], dwio_read_csr
mov [device.write_csr], dwio_write_csr
mov [device.read_bcr], dwio_read_bcr
mov [device.write_bcr], dwio_write_bcr
mov [device.read_rap], dwio_read_rap
mov [device.write_rap], dwio_write_rap
mov [device.sw_reset], dwio_reset
 
ret
 
 
; ecx - index
; return:
; eax - data
align 4
wio_read_csr:
 
add edx, WIO_RAP
mov ax, cx
out dx, ax
add edx, WIO_RDP - WIO_RAP
in ax, dx
and eax, 0xffff
sub edx, WIO_RDP
 
ret
 
 
; eax - data
; ecx - index
align 4
wio_write_csr:
 
add edx, WIO_RAP
xchg eax, ecx
out dx, ax
xchg eax, ecx
add edx, WIO_RDP - WIO_RAP
out dx, ax
sub edx, WIO_RDP
 
ret
 
 
; ecx - index
; return:
; eax - data
align 4
wio_read_bcr:
 
add edx, WIO_RAP
mov ax, cx
out dx, ax
add edx, WIO_BDP - WIO_RAP
in ax, dx
and eax, 0xffff
sub edx, WIO_BDP
 
ret
 
 
; eax - data
; ecx - index
align 4
wio_write_bcr:
 
add edx, WIO_RAP
xchg eax, ecx
out dx, ax
xchg eax, ecx
add edx, WIO_BDP - WIO_RAP
out dx, ax
sub edx, WIO_BDP
 
ret
 
align 4
wio_read_rap:
 
add edx, WIO_RAP
in ax, dx
and eax, 0xffff
sub edx, WIO_RAP
 
ret
 
; eax - val
align 4
wio_write_rap:
 
add edx, WIO_RAP
out dx, ax
sub edx, WIO_RAP
 
ret
 
align 4
wio_reset:
 
push eax
add edx, WIO_RESET
in ax, dx
pop eax
sub edx, WIO_RESET
 
ret
 
 
 
; ecx - index
; return:
; eax - data
align 4
dwio_read_csr:
 
add edx, DWIO_RAP
mov eax, ecx
out dx, eax
add edx, DWIO_RDP - DWIO_RAP
in eax, dx
and eax, 0xffff
sub edx, DWIO_RDP
 
ret
 
 
; ecx - index
; eax - data
align 4
dwio_write_csr:
 
add edx, DWIO_RAP
xchg eax, ecx
out dx, eax
add edx, DWIO_RDP - DWIO_RAP
xchg eax, ecx
out dx, eax
sub edx, DWIO_RDP
 
ret
 
; ecx - index
; return:
; eax - data
align 4
dwio_read_bcr:
 
add edx, DWIO_RAP
mov eax, ecx
out dx, eax
add edx, DWIO_BDP - DWIO_RAP
in eax, dx
and eax, 0xffff
sub edx, DWIO_BDP
 
ret
 
 
; ecx - index
; eax - data
align 4
dwio_write_bcr:
 
add edx, DWIO_RAP
xchg eax, ecx
out dx, eax
add edx, DWIO_BDP - DWIO_RAP
xchg eax, ecx
out dx, eax
sub edx, DWIO_BDP
 
ret
 
align 4
dwio_read_rap:
 
add edx, DWIO_RAP
in eax, dx
and eax, 0xffff
sub edx, DWIO_RAP
 
ret
 
 
; eax - val
align 4
dwio_write_rap:
 
add edx, DWIO_RAP
out dx, eax
sub edx, DWIO_RAP
 
ret
 
align 4
dwio_reset:
 
push eax
add edx, DWIO_RESET
in eax, dx
pop eax
sub edx, DWIO_RESET
 
ret
 
 
align 4
mdio_read:
 
and ecx, 0x1f
mov ax, [device.phy]
and ax, 0x1f
shl ax, 5
or ax, cx
 
mov ecx, BCR_MIIADDR
call [device.write_bcr]
 
mov ecx, BCR_MIIDATA
call [device.read_bcr]
 
ret
 
 
align 4
mdio_write:
 
push eax
and ecx, 0x1f
mov ax, [device.phy]
and ax, 0x1f
shl ax, 5
or ax, cx
 
mov ecx, BCR_MIIADDR
call [device.write_bcr]
 
pop eax
mov ecx, BCR_MIIDATA
call [device.write_bcr]
 
ret
 
 
align 4
check_media:
 
DEBUGF 1, "check_media\n"
 
test [device.mii], 1
jnz mii_link_ok
 
mov ecx, BCR_LED0
call [device.read_bcr]
cmp eax, 0xc0
 
DEBUGF 1, "link status=0x%x\n", ax
 
ret
 
 
 
; End of code
 
align 4 ; Place all initialised data here
 
devices dd 0
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
my_service db 'PCnet',0 ; max 16 chars include zero
 
device_l2 db "PCnet/PCI 79C970",0
device_l4 db "PCnet/PCI II 79C970A",0
device_l5 db "PCnet/FAST 79C971",0
device_l6 db "PCnet/FAST+ 79C972",0
device_l7 db "PCnet/FAST III 79C973",0
device_l8 db "PCnet/Home 79C978",0
device_l9 db "PCnet/FAST III 79C975",0
 
options_mapping:
dd PORT_ASEL ; 0 Auto-select
dd PORT_AUI ; 1 BNC/AUI
dd PORT_AUI ; 2 AUI/BNC
dd PORT_ASEL ; 3 not supported
dd PORT_10BT or PORT_FD ; 4 10baseT-FD
dd PORT_ASEL ; 5 not supported
dd PORT_ASEL ; 6 not supported
dd PORT_ASEL ; 7 not supported
dd PORT_ASEL ; 8 not supported
dd PORT_MII ; 9 MII 10baseT
dd PORT_MII or PORT_FD ; 10 MII 10baseT-FD
dd PORT_MII ; 11 MII (autosel)
dd PORT_10BT ; 12 10BaseT
dd PORT_MII or PORT_100 ; 13 MII 100BaseTx
dd PORT_MII or PORT_100 or PORT_FD ; 14 MII 100BaseTx-FD
dd PORT_ASEL ; 15 not supported
 
include_debug_strings ; All data wich FDO uses will be included here
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/drivers/netdrv.inc
0,0 → 1,150
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
include 'bus/pci.inc'
include 'bus/mii.inc'
 
; Kernel variables
 
PAGESIZE = 4096
PG_SW = 0x003
PG_NOCACHE = 0x018
 
 
; network driver types
 
NET_TYPE_ETH = 1
NET_TYPE_SLIP = 2
 
; link state
 
ETH_LINK_DOWN = 0 ; Link is down
ETH_LINK_UNKOWN = 1b ; There could be an active link
ETH_LINK_FD = 10b ; full duplex flag
ETH_LINK_10M = 100b ; 10 mbit
ETH_LINK_100M = 1000b ; 100 mbit
ETH_LINK_1G = 10000b ; gigabit
 
 
LAST_IO = 0
macro set_io addr {
 
if addr = 0
mov edx, [device.io_addr]
else if addr = LAST_IO
else
add edx, addr - LAST_IO
end if
 
LAST_IO = addr
}
 
macro allocate_and_clear dest, size, err {
 
; We need to allocate at least 8 pages, if we want a continuous memory in ram
push edx
if (size < 8*4096) & (size > 4096)
stdcall KernelAlloc, 8*4096
else
stdcall KernelAlloc, size
end if
pop edx
 
test eax, eax
jz err
mov dest, eax ; Save the address to it into the device struct
mov edi, eax ; look at last part of code!
 
; Release the unused pages (if any)
if (size < 8*4096) & (size > 4096)
add eax, (size/4096+1)*4096
mov ecx, 8-(size/4096+1)
push edx
call ReleasePages
pop edx
end if
 
; Clear the allocated buffer
mov ecx, size/4 ; divide by 4 because of DWORD
xor eax, eax
rep stosd
 
}
 
struc IOCTL {
.handle dd ?
.io_code dd ?
.input dd ?
.inp_size dd ?
.output dd ?
.out_size dd ?
}
 
virtual at edx
IOCTL IOCTL
end virtual
 
 
if used null_op
align 4
null_op:
or eax, -1
ret
 
end if
 
 
macro GetRealAddr { ; input and output is eax
 
push ax
call GetPgAddr
and word[esp], PAGESIZE - 1
or ax, word[esp]
inc esp
inc esp
 
}
 
macro NET_DEVICE {
 
.type dd ? ; Type field
.mtu dd ? ; Maximal Transmission Unit
.name dd ? ; Ptr to 0 terminated string
 
.unload dd ? ; Ptrs to driver functions
.reset dd ? ;
.transmit dd ? ;
 
.bytes_tx dq ? ; Statistics, updated by the driver
.bytes_rx dq ? ;
.packets_tx dd ? ;
.packets_rx dd ? ;
 
.state dd ? ; link state (0 = no link)
.hwacc dd ? ; bitmask stating enabled HW accelerations
 
.end:
}
 
 
macro ETH_DEVICE {
NET_DEVICE
 
.mac dp ?
dw ? ; qword alignment
 
}
 
 
 
macro SLIP_DEVICE {
NET_DEVICE
 
}
/kernel/branches/net/drivers/3c59x.asm
0,0 → 1,2942
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; 3Com network driver for KolibriOS ;;
;; ;;
;; Ported to KolibriOS net-branch by hidnplayr (28/05/10) ;;
;; ;;
;; Thanks to: scrap metal recyclers, whom provide me with ;;
;; loads of hardware ;;
;; diamond: who makes me understand KolibriOS ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 3C59X.INC ;;
;; ;;
;; Ethernet driver for Menuet OS ;;
;; ;;
;; Driver for 3Com fast etherlink 3c59x and ;;
;; etherlink XL 3c900 and 3c905 cards ;;
;; References: ;;
;; www.3Com.com - data sheets ;;
;; DP83840A.pdf - ethernet physical layer ;;
;; 3c59x.c - linux driver ;;
;; ethernet driver template by Mike Hibbett ;;
;; ;;
;; Credits ;;
;; Mike Hibbett, ;;
;; who kindly supplied me with a 3Com905C-TX-M card ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Copyright (c) 2004, Endre Kozma <endre.kozma@axelero.hu>
;; All rights reserved.
;;
;; Redistribution and use in source and binary forms, with or without
;; modification, are permitted provided that the following conditions are
;; met:
;;
;; 1. Redistributions of source code must retain the above copyright notice,
;; this list of conditions and the following disclaimer.
;;
;; 2. Redistributions in binary form must reproduce the above copyright
;; notice, this list of conditions and the following disclaimer in the
;; documentation and/or other materials provided with the distribution.
;;
;; 3. The name of the author may not be used to endorse or promote products
;; derived from this software without specific prior written permission.
;;
;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
;; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
;; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;;
;; History
;; =======
;; $Log: 3C59X.INC,v $
;; Revision 1.3 2004/07/11 12:21:12 kozma
;; Support of vortex chips (3c59x) added.
;; Support of 3c920 and 3c982 added.
;; Corrections.
;;
;; Revision 1.2 2004/06/12 19:40:20 kozma
;; Function e3c59x_set_available_media added in order to set
;; the default media in case auto detection finds no valid link.
;; Incorrect mii check removed (3c900 Cyclone works now).
;; Cleanups.
;;
;; Revision 1.1 2004/06/12 18:27:15 kozma
;; Initial revision
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
FORCE_FD = 0 ; forcing full duplex mode makes sense at some cards and link types
PROMISCIOUS = 0 ; enables promiscous mode
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
 
public START
public service_proc
public version
 
struc DPD { ; Download Packet Descriptor
 
.next_ptr dd ?
.frame_start_hdr dd ?
.frag_addr dd ? ; for packet data
.frag_len dd ? ; for packet data
.realaddr dd ?
.size = 32
}
 
virtual at 0
dpd DPD
end virtual
 
 
struc UPD { ; Upload Packet Descriptor
 
.next_ptr dd ?
.pkt_status dd ?
.frag_addr dd ?
.frag_len dd ? ; for packet data
.realaddr dd ?
.size = 32
 
}
 
virtual at 0
upd UPD
end virtual
 
; Registers
REG_POWER_MGMT_CTRL = 0x7c
REG_UP_LIST_PTR = 0x38
REG_UP_PKT_STATUS = 0x30
REG_TX_FREE_THRESH = 0x2f
REG_DN_LIST_PTR = 0x24
REG_DMA_CTRL = 0x20
REG_TX_STATUS = 0x1b
REG_RX_STATUS = 0x18
REG_TX_DATA = 0x10
 
; Common window registers
REG_INT_STATUS = 0xe
REG_COMMAND = 0xe
 
; Register window 7
REG_MASTER_STATUS = 0xc
REG_POWER_MGMT_EVENT = 0xc
REG_MASTER_LEN = 0x6
REG_VLAN_ETHER_TYPE = 0x4
REG_VLAN_MASK = 0x0
REG_MASTER_ADDRESS = 0x0
 
; Register window 6
REG_BYTES_XMITTED_OK = 0xc
REG_BYTES_RCVD_OK = 0xa
REG_UPPER_FRAMES_OK = 0x9
REG_FRAMES_DEFERRED = 0x8
REG_FRAMES_RCVD_OK = 0x7
REG_FRAMES_XMITTED_OK = 0x6
REG_RX_OVERRUNS = 0x5
REG_LATE_COLLISIONS = 0x4
REG_SINGLE_COLLISIONS = 0x3
REG_MULTIPLE_COLLISIONS = 0x2
REG_SQE_ERRORS = 0x1
REG_CARRIER_LOST = 0x0
 
; Register window 5
REG_INDICATION_ENABLE = 0xc
REG_INTERRUPT_ENABLE = 0xa
REG_TX_RECLAIM_THRESH = 0x9
REG_RX_FILTER = 0x8
REG_RX_EARLY_THRESH = 0x6
REG_TX_START_THRESH = 0x0
 
; Register window 4
REG_UPPER_BYTES_OK = 0xe
REG_BAD_SSD = 0xc
REG_MEDIA_STATUS = 0xa
REG_PHYSICAL_MGMT = 0x8
REG_NETWORK_DIAGNOSTIC = 0x6
REG_FIFO_DIAGNOSTIC = 0x4
REG_VCO_DIAGNOSTIC = 0x2 ; may not supported
 
; Bits in register window 4
BIT_AUTOSELECT = 24
 
; Register window 3
REG_TX_FREE = 0xc
REG_RX_FREE = 0xa
REG_MEDIA_OPTIONS = 0x8
REG_MAC_CONTROL = 0x6
REG_MAX_PKT_SIZE = 0x4
REG_INTERNAL_CONFIG = 0x0
 
; Register window 2
REG_RESET_OPTIONS = 0xc
REG_STATION_MASK_HI = 0xa
REG_STATION_MASK_MID = 0x8
REG_STATION_MASK_LO = 0x6
REG_STATION_ADDRESS_HI = 0x4
REG_STATION_ADDRESS_MID = 0x2
REG_STATION_ADDRESS_LO = 0x0
 
; Register window 1
REG_TRIGGER_BITS = 0xc
REG_SOS_BITS = 0xa
REG_WAKE_ON_TIMER = 0x8
REG_SMB_RXBYTES = 0x7
REG_SMB_DIAG = 0x5
REG_SMB_ARB = 0x4
REG_SMB_STATUS = 0x2
REG_SMB_ADDRESS = 0x1
REG_SMB_FIFO_DATA = 0x0
 
; Register window 0
REG_EEPROM_DATA = 0xc
REG_EEPROM_COMMAND = 0xa
REG_BIOS_ROM_DATA = 0x8
REG_BIOS_ROM_ADDR = 0x4
 
; Physical management bits
BIT_MGMT_DIR = 2 ; drive with the data written in mgmtData
BIT_MGMT_DATA = 1 ; MII management data bit
BIT_MGMT_CLK = 0 ; MII management clock
 
; MII commands
MII_CMD_MASK = (1111b shl 10)
MII_CMD_READ = (0110b shl 10)
MII_CMD_WRITE = (0101b shl 10)
 
; MII registers
REG_MII_BMCR = 0 ; basic mode control register
REG_MII_BMSR = 1 ; basic mode status register
REG_MII_ANAR = 4 ; auto negotiation advertisement register
REG_MII_ANLPAR = 5 ; auto negotiation link partner ability register
REG_MII_ANER = 6 ; auto negotiation expansion register
 
; MII bits
BIT_MII_AUTONEG_COMPLETE = 5 ; auto-negotiation complete
BIT_MII_PREAMBLE_SUPPRESSION = 6
 
; eeprom bits and commands
EEPROM_CMD_READ = 0x80
EEPROM_BIT_BUSY = 15
 
; eeprom registers
EEPROM_REG_OEM_NODE_ADDR= 0xa
EEPROM_REG_CAPABILITIES = 0x10
 
; Commands for command register
SELECT_REGISTER_WINDOW = (1 shl 11)
 
IS_VORTEX = 0x1
IS_BOOMERANG = 0x2
IS_CYCLONE = 0x4
IS_TORNADO = 0x8
EEPROM_8BIT = 0x10
HAS_PWR_CTRL = 0x20
HAS_MII = 0x40
HAS_NWAY = 0x80
HAS_CB_FNS = 0x100
INVERT_MII_PWR = 0x200
INVERT_LED_PWR = 0x400
MAX_COLLISION_RESET = 0x800
EEPROM_OFFSET = 0x1000
HAS_HWCKSM = 0x2000
EXTRA_PREAMBLE = 0x4000
 
; Status
IntLatch = 0x0001
HostError = 0x0002
TxComplete = 0x0004
TxAvailable = 0x0008
RxComplete = 0x0010
RxEarly = 0x0020
IntReq = 0x0040
StatsFull = 0x0080
DMADone = 0x0100
DownComplete = 0x0200
UpComplete = 0x0400
DMAInProgress = 0x0800 ; 1 shl 11 (DMA controller is still busy)
CmdInProgress = 0x1000 ; 1 shl 12 (EL3_CMD is still busy)
 
S_5_INTS = HostError + RxEarly + UpComplete + DownComplete ;+ TxComplete + RxComplete + TxAvailable
 
; Commands
TotalReset = 0 shl 11
SelectWindow = 1 shl 11
StartCoax = 2 shl 11
RxDisable = 3 shl 11
RxEnable = 4 shl 11
RxReset = 5 shl 11
UpStall = 6 shl 11
UpUnstall = (6 shl 11)+1
DownStall = (6 shl 11)+2
DownUnstall = (6 shl 11)+3
RxDiscard = 8 shl 11
TxEnable = 9 shl 11
TxDisable = 10 shl 11
TxReset = 11 shl 11
FakeIntr = 12 shl 11
AckIntr = 13 shl 11
SetIntrEnb = 14 shl 11
SetStatusEnb = 15 shl 11
SetRxFilter = 16 shl 11
SetRxThreshold = 17 shl 11
SetTxThreshold = 18 shl 11
SetTxStart = 19 shl 11
StartDMAUp = 20 shl 11
StartDMADown = (20 shl 11)+1
StatsEnable = 21 shl 11
StatsDisable = 22 shl 11
StopCoax = 23 shl 11
SetFilterBit = 25 shl 11
 
; Rx mode bits
RxStation = 1
RxMulticast = 2
RxBroadcast = 4
RxProm = 8
 
; RX/TX buffers sizes
MAX_ETH_PKT_SIZE = 1536 ; max packet size
NUM_RX_DESC = 4 ; a power of 2 number
NUM_TX_DESC = 4 ; a power of 2 number
MAX_ETH_FRAME_SIZE = 1520 ; size of ethernet frame + bytes alignment
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.dpd_buffer rd (dpd.size*NUM_TX_DESC)/4
.upd_buffer rd (upd.size*NUM_RX_DESC)/4
.curr_upd dd ?
.prev_dpd dd ?
 
.io_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
rb 3 ; alignment
 
.prev_tx_frame dd ?
.ver_id db ?
.full_bus_master db ?
.has_hwcksm db ?
.preamble db ?
.dn_list_ptr_cleared db ?
 
.size = $ - device
 
end virtual
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
 
.entry:
 
DEBUGF 1,"Loading %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
 
.fail:
.exit:
xor eax, eax
ret
 
endp
 
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne @F
 
cmp [IOCTL.out_size], 4
jb .fail
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
 
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
 
mov eax, [IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types of this hardware dont exist
 
; check if the device is already listed
 
mov ecx, [VORTEX_DEVICES]
test ecx, ecx
jz .maybeboomerang
 
mov esi, VORTEX_LIST
mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax , [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
 
 
.maybeboomerang:
mov ecx, [BOOMERANG_DEVICES]
test ecx, ecx
jz .firstdevice
 
mov esi, BOOMERANG_LIST
mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax , [eax+1] ;
.nextdevice2:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice2
 
 
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
mov ecx, [BOOMERANG_DEVICES]
add ecx, [VORTEX_DEVICES]
cmp ecx, MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, device.size, .fail ; Allocate the buffer for device structure
 
; Fill in the direct call addresses into the struct
 
mov [device.reset], reset
mov [device.transmit], null_op
mov [device.unload], null_op
mov [device.name], my_service
 
; save the pci bus and device numbers
 
mov eax, [IOCTL.input]
movzx ecx, byte[eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte[eax+2]
mov [device.pci_dev], ecx
 
; Now, it's time to find the base io addres of the PCI device
PCI_find_io
 
; We've found the io address, find IRQ now
PCI_find_irq
 
DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
 
; Ok, the eth_device structure is ready, let's probe the device
call probe ; this function will output in eax
test eax, eax
jnz .err ; If an error occured, exit
 
 
movzx ecx, [device.ver_id]
test word [hw_versions+2+ecx*4], IS_VORTEX
jz .not_vortex
 
mov eax, [VORTEX_DEVICES] ; Add the device structure to our device list
mov [VORTEX_LIST+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [VORTEX_DEVICES] ;
 
.register:
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
cmp eax, -1
je .destroy
 
call start_device
ret
 
.not_vortex:
mov eax, [BOOMERANG_DEVICES] ; Add the device structure to our device list
mov [BOOMERANG_LIST+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [BOOMERANG_DEVICES]
 
jmp .register
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 1,"Trying to find device number of already registered device\n"
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 1,"Kernel says: %u\n", eax
ret
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
; todo: reset device into virgin state
 
.err:
stdcall KernelFree, ebx
 
 
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
 
 
 
;***************************************************************************
; Function
; probe
; Description
; Searches for an ethernet card, enables it and clears the rx buffer
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;***************************************************************************
 
align 4
probe:
 
DEBUGF 1,"Probing 3com card\n"
 
PCI_make_bus_master
 
; wake up the card
call wake_up
 
stdcall PciRead32, [device.pci_bus], [device.pci_dev], 0 ; get device/vendor id
 
DEBUGF 1,"Vendor id: 0x%x\n", ax
 
cmp ax, 0x10B7
jne .notfound
shr eax, 16
 
DEBUGF 1,"Vendor ok!, device id: 0x%x\n", ax
 
; get chip version
mov ecx, HW_VERSIONS_SIZE/4-1
.loop:
cmp ax, [hw_versions+ecx*4]
jz .found
loop .loop
.notfound:
DEBUGF 1,"Device id not found in list!\n"
or eax, -1
ret
.found:
mov esi, [hw_str+ecx*4]
DEBUGF 1,"Hardware type: %s\n", esi
mov [device.name], esi
 
mov [device.ver_id], cl
test word [hw_versions+2+ecx*4], HAS_HWCKSM
setnz [device.has_hwcksm]
; set pci latency for vortex cards
test word [hw_versions+2+ecx*4], IS_VORTEX
jz .not_vortex
 
mov eax, 11111000b ; 248 = max latency
stdcall PciWrite32, [device.pci_bus], [device.pci_dev], PCI_REG_LATENCY, eax
 
.not_vortex:
; set RX/TX functions
mov ax, EEPROM_REG_CAPABILITIES
call read_eeprom
test al, 100000b ; full bus master?
setnz [device.full_bus_master]
jnz .boomerang_func
mov [device.transmit], vortex_transmit
DEBUGF 1,"Device is a vortex type\n"
DEBUGF 1,"I'm sorry but vortex code hasnt been tested yet\n"
DEBUGF 1,"Please contact me on hidnplayr@kolibrios.org\n"
DEBUGF 1,"If you can help me finish it!\n"
or eax, -1
ret
jmp @f
.boomerang_func: ; full bus master, so use boomerang functions
mov [device.transmit], boomerang_transmit
DEBUGF 1,"Device is a boomerang type\n"
@@:
call read_mac_eeprom
 
test byte [device.full_bus_master], 0xff
jz .set_preamble
; switch to register window 2
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+2
out dx, ax
; activate xcvr by setting some magic bits
set_io REG_RESET_OPTIONS
in ax, dx
and ax, not 0x4010
movzx ecx, [device.ver_id]
test word [ecx*4+hw_versions+2], INVERT_LED_PWR
jz @f
or al, 0x10
@@:
test word [ecx*4+hw_versions+2], INVERT_MII_PWR
jz @f
or ah, 0x40
@@:
out dx, ax
.set_preamble:
; use preamble as default
mov byte [device.preamble], 1 ; enable preamble
 
call global_reset
 
;--------------------------
; RESET
 
align 4
reset:
 
movzx eax, [device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n",eax:1
 
movzx ecx, [device.ver_id]
test word [hw_versions+2+ecx*4], IS_VORTEX
jz .not_vortex
 
mov esi, int_vortex
jmp .reg_int
 
.not_vortex:
mov esi, int_boomerang
 
.reg_int:
stdcall AttachIntHandler, eax, esi, dword 0
test eax, eax
jnz @f
DEBUGF 1,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW + 0
out dx, ax
 
mov ax, StopCoax
out dx, ax ; stop transceiver
 
mov ax, SELECT_REGISTER_WINDOW + 4
out dx, ax ; disable UTP
 
set_io REG_MEDIA_STATUS
mov ax, 0x0
 
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW + 0
out dx, ax
 
set_io REG_FIFO_DIAGNOSTIC
mov ax, 0
out dx, ax ; disable card
 
mov ax, 1
out dx, ax ; enable card
 
call write_mac
 
 
;<<<<<<<<<<<<<<
 
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW + 1
out dx, ax
 
mov ecx, 32
set_io 0x0b
.loop:
in al, dx
loop .loop
 
; Get rid of stray ints
set_io REG_COMMAND
mov ax, AckIntr + 0xff
out dx, ax
 
mov ax, SetStatusEnb + S_5_INTS
out dx, ax
 
mov ax, SetIntrEnb + S_5_INTS
out dx, ax
 
call set_rx_mode
call set_active_port
 
;>>>>>>>>>>
 
call create_rx_ring
call rx_reset
call tx_reset
 
;>>>>>>>>>>>>>>>>>>
 
xor eax, eax
; clear packet/byte counters
 
lea edi, [device.bytes_tx]
mov ecx, 6
rep stosd
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
ret
 
 
 
 
 
align 4
start_device:
DEBUGF 1,"Starting the device\n"
 
set_io 0
set_io REG_COMMAND
mov ax, SetTxThreshold + 60 ;2047 ; recommended by the manual :)
out dx, ax
 
call check_tx_status
 
set_io 0
set_io REG_COMMAND
; switch to register window 4
mov ax, SELECT_REGISTER_WINDOW+4
out dx, ax
 
; wait for linkDetect
set_io REG_MEDIA_STATUS
mov ecx, 20 ; wait for max 2s
.link_detect_loop:
mov esi, 100
call Sleep ; 100 ms
in ax, dx
test ah, 1000b ; linkDetect
jnz @f
loop .link_detect_loop
DEBUGF 1,"Link detect timed-out!\n"
@@:
 
; print link type
xor eax, eax
bsr ax, word [device.state]
jz @f
sub ax, 4
@@:
 
mov esi, [link_str+eax*4]
DEBUGF 1,"Established Link type: %s\n", esi
 
; enable interrupts
 
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW + 1
out dx, ax
 
mov ax, AckIntr + 0xff
out dx, ax
 
mov ax, SetStatusEnb + S_5_INTS
out dx, ax
 
mov ax, SetIntrEnb + S_5_INTS
out dx, ax
 
; Start RX/TX
 
set_io 0
set_io REG_COMMAND
mov ax, RxEnable
out dx, ax
 
mov ax, TxEnable
out dx, ax
 
set_io REG_COMMAND
mov ax, SetRxThreshold + 208
out dx, ax
 
mov ax, SetTxThreshold + 60 ;16 ; recommended by the manual :)
out dx, ax
 
mov ax, SELECT_REGISTER_WINDOW + 1
out dx, ax
 
ret
 
 
 
 
 
 
 
align 4
set_rx_mode:
 
DEBUGF 1,"Setting RX mode\n"
 
set_io 0
set_io REG_COMMAND
 
if defined PROMISCIOUS
mov ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast + RxProm
else if defined ALLMULTI
mov ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast
else
mov ax, SetRxFilter + RxStation + RxBroadcast
end if
out dx, ax
 
ret
 
 
 
 
 
;***************************************************************************
; Function
; global_reset
; Description
; resets the device
; Parameters:
; ebp - io_addr
; Return value:
; Destroyed registers
; ax, ecx, edx, esi
;
;***************************************************************************1
 
align 4
global_reset:
 
DEBUGF 1,"Global reset..\n"
 
; GlobalReset
set_io 0
set_io REG_COMMAND
xor eax, eax
; or al, 0x14
out dx, ax
; wait for GlobalReset to complete
mov ecx, 64000
.loop:
in ax , dx
test ah , 10000b ; check CmdInProgress
loopz .loop
 
DEBUGF 1,"Waiting for nic to boot..\n"
; wait for 2 seconds for NIC to boot
mov esi, 2000
call Sleep ; 2 seconds
 
DEBUGF 1,"Ok!\n"
 
ret
 
 
 
;***************************************************************************
; Function
; tx_reset
; Description
; resets and enables transmitter engine
;
;***************************************************************************
 
align 4
tx_reset:
DEBUGF 1,"tx reset\n"
 
; TxReset
set_io 0
set_io REG_COMMAND
mov ax, TxReset
out dx, ax
; Wait for TxReset to complete
mov ecx, 200000
.tx_reset_loop:
in ax, dx
test ah, 10000b ; check CmdInProgress
jz .tx_set_prev
dec ecx
jnz .tx_reset_loop
.tx_set_prev:
; init last_dpd
lea eax, [device.dpd_buffer + (NUM_TX_DESC-1)*dpd.size]
mov [device.prev_dpd], eax
 
.tx_enable:
ret
 
 
 
;***************************************************************************
; Function
; rx_reset
; Description
; resets and enables receiver engine
;
;***************************************************************************
 
align 4
rx_reset:
 
DEBUGF 1,"rx reset\n"
 
set_io 0
set_io REG_COMMAND
mov ax, RxReset or 0x4
out dx, ax
 
; wait for RxReset to complete
mov ecx, 200000
.loop:
in ax, dx
test ah, 10000b ; check CmdInProgress
jz .done
dec ecx
jnz .loop
.done:
 
lea eax, [device.upd_buffer]
mov [device.curr_upd], eax
GetRealAddr
set_io 0
set_io REG_UP_LIST_PTR
out dx, eax
 
.rx_enable:
ret
 
 
align 4
create_rx_ring:
; create upd ring
lea eax, [device.upd_buffer]
GetRealAddr
mov edi, eax ; real addr of first descr
 
lea esi, [device.upd_buffer] ; ptr to first descr
lea edx, [device.upd_buffer + (NUM_RX_DESC-1)*upd.size] ; ptr to last descr
 
mov ecx, NUM_RX_DESC
 
.upd_loop:
mov [edx + upd.next_ptr], edi
 
push ecx edx
stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
pop edx ecx
mov [esi + upd.realaddr], eax
call GetPgAddr
mov [esi + upd.frag_addr], eax
and [esi + upd.pkt_status], 0
mov [esi + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
 
DEBUGF 1,"UPD: lin=%x phys=%x len=%x next ptr=%x\n", [esi+upd.realaddr]:8, [esi+upd.frag_addr]:8, [esi+upd.frag_len]:8, edi
DEBUGF 1,"UPD: cur=%x prev=%x\n", esi, edx
 
mov edx, esi
add esi, upd.size
add edi, upd.size
dec ecx
jnz .upd_loop
 
ret
 
 
 
;---------------------------------------------------------------------------
; Function
; try_link_detect
; Description
; try_link_detect checks if link exists
; Parameters
; ebx = device structure
; Return value
; al - 0 ; no link detected
; al - 1 ; link detected
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;---------------------------------------------------------------------------
 
align 4
try_link_detect:
 
DEBUGF 1,"trying to detect link\n"
 
; create self-directed packet
stdcall KernelAlloc, 20 ; create a buffer for the self-directed packet
test eax, eax
jz .fail
 
pushd 20 ; Packet parameters for device.transmit
push eax ;
 
mov edi, eax
 
lea esi, [device.mac]
movsw
movsd
sub esi, 6
movsw
movsd
mov ax , 0x0608
stosw
 
; download self-directed packet
call [device.transmit]
 
; switch to register window 4
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+4
out dx, ax
 
; See if we have received the packet by now..
cmp [device.packets_rx], 0
jnz .link_detected
 
; switch to register window 4
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+4
out dx, ax
 
; read linkbeatdetect
set_io REG_MEDIA_STATUS
in ax, dx
test ah, 1000b ; test linkBeatDetect
jnz .link_detected
xor al, al
jmp .finish
 
.link_detected:
DEBUGF 1,"link detected!\n"
setb al
 
.finish:
test al, al
jz @f
or byte [device.state+1], 100b
@@:
ret
 
.fail:
ret
 
 
 
;***************************************************************************
; Function
; try_phy
; Description
; try_phy checks the auto-negotiation function
; in the PHY at PHY index. It can also be extended to
; include link detection for non-IEEE 802.3u
; auto-negotiation devices, for instance the BCM5000. ; TODO: BCM5000
; Parameters
; ah - PHY index
; ebx - device stucture
; Return value
; al - 0 link is auto-negotiated
; al - 1 no link is auto-negotiated
; Destroyed registers
; eax, ebx, ecx, edx, esi
;
;***************************************************************************
 
align 4
try_phy:
 
DEBUGF 1,"PHY=%u\n", ah
DEBUGF 1,"Detecting if device is auto-negotiation capable\n"
 
mov al, REG_MII_BMCR
push eax
call mdio_read ; returns with window #4
or ah , 0x80 ; software reset
mov esi, eax
mov eax, dword [esp]
call mdio_write ; returns with window #4
 
; wait for reset to complete
mov esi, 2000
stdcall Sleep ; 2s
mov eax, [esp]
call mdio_read ; returns with window #4
test ah , 0x80
jnz .fail1
mov eax, [esp]
 
; wait for a while after reset
mov esi, 20
stdcall Sleep ; 20ms
mov eax, [esp]
mov al , REG_MII_BMSR
call mdio_read ; returns with window #4
test al , 1 ; extended capability supported?
jz .fail2
 
; auto-neg capable?
test al , 1000b
jz .fail2 ; not auto-negotiation capable
 
DEBUGF 1,"Device is auto-negotiation capable\n"
 
; auto-neg complete?
test al , 100000b
jnz .auto_neg_ok
 
DEBUGF 1,"Restarting auto-negotiation\n"
 
; restart auto-negotiation
mov eax, [esp]
mov al , REG_MII_ANAR
push eax
call mdio_read ; returns with window #4
or ax , 1111b shl 5; advertise only 10base-T and 100base-TX
mov esi, eax
pop eax
call mdio_write ; returns with window #4
mov eax, [esp]
call mdio_read ; returns with window #4
mov esi, eax
or bh , 10010b ; restart auto-negotiation
mov eax, [esp]
call mdio_write ; returns with window #4
mov esi, 4000
stdcall Sleep ; 4 seconds
mov eax, [esp]
mov al , REG_MII_BMSR
call mdio_read ; returns with window #4
test al , 100000b ; auto-neg complete?
jnz .auto_neg_ok
jmp .fail3
.auto_neg_ok:
 
DEBUGF 1,"Auto-negotiation complete\n"
 
; compare advertisement and link partner ability registers
mov eax, [esp]
mov al , REG_MII_ANAR
call mdio_read ; returns with window #4
xchg eax, [esp]
mov al , REG_MII_ANLPAR
call mdio_read ; returns with window #4
pop esi
and eax, esi
and eax, 1111100000b
push eax
 
mov word[device.state+2], ax
 
; switch to register window 3
set_io 0
set_io REG_COMMAND
mov ax , SELECT_REGISTER_WINDOW+3
out dx , ax
 
; set full-duplex mode
set_io REG_MAC_CONTROL
in ax , dx
and ax , not 0x120 ; clear full duplex and flow control
pop esi
test esi, 1010b shl 5; check for full-duplex
jz .half_duplex
or ax , 0x120 ; set full duplex and flow control
.half_duplex:
DEBUGF 1,"Using half-duplex\n"
out dx , ax
mov al , 1
ret
 
 
.fail1:
DEBUGF 1,"reset failed!\n"
pop eax
xor al, al
ret
 
.fail2:
DEBUGF 1,"This device is not auto-negotiation capable!\n"
pop eax
xor al, al
ret
 
.fail3:
DEBUGF 1,"auto-negotiation reset failed!\n"
pop eax
xor al, al
ret
 
 
 
;***************************************************************************
; Function
; try_mii
; Description
; try_MII checks the on-chip auto-negotiation logic
; or an off-chip MII PHY, depending upon what is set in
; xcvrSelect by the caller.
; It exits when it finds the first device with a good link.
; Parameters
; ebp - io_addr
; Return value
; al - 0
; al - 1
; Destroyed registers
; eax, ebx, ecx, edx, esi
;
;***************************************************************************
 
align 4
try_mii:
 
DEBUGF 1,"trying to find MII PHY\n"
 
; switch to register window 3
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+3
out dx, ax
set_io REG_INTERNAL_CONFIG
in eax, dx
and eax, (1111b shl 20)
cmp eax, (1000b shl 20) ; is auto-negotiation set?
jne .mii_device
 
DEBUGF 1,"auto-negotiation is set\n"
; switch to register window 4
set_io REG_COMMAND
mov ax , SELECT_REGISTER_WINDOW+4
out dx , ax
 
; PHY==24 is the on-chip auto-negotiation logic
; it supports only 10base-T and 100base-TX
mov ah , 24
call try_phy
test al , al
jz .fail_finish
 
mov cl , 24
jmp .check_preamble
 
.mii_device:
cmp eax, (0110b shl 20)
jne .fail_finish
 
set_io 0
set_io REG_COMMAND
mov ax , SELECT_REGISTER_WINDOW+4
out dx , ax
 
set_io REG_PHYSICAL_MGMT
in ax , dx
and al , (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_DATA)
cmp al , (1 shl BIT_MGMT_DATA)
je .search_for_phy
 
xor al , al
ret
 
.search_for_phy:
; search for PHY
mov cx , 31
.search_phy_loop:
DEBUGF 1,"Searching the PHY\n"
cmp cx , 24
je .next_phy
mov ah , cl ; ah = phy
mov al , REG_MII_BMCR ; al = Basic Mode Status Register
push cx
call mdio_read
pop cx
test ax , ax
jz .next_phy
cmp ax , 0xffff
je .next_phy
mov ah , cl ; ah = phy
push cx
call try_phy
pop cx
test al , al
jnz .check_preamble
.next_phy:
loopw .search_phy_loop
 
.fail_finish:
xor al, al
ret
 
; epilog
.check_preamble:
DEBUGF 1,"Using PHY: %u\nChecking PreAmble\n", cl
push eax ; eax contains the return value of try_phy
; check hard coded preamble forcing
movzx eax, [device.ver_id]
test word [eax*4+hw_versions+2], EXTRA_PREAMBLE
setnz [device.preamble] ; force preamble
jnz .finish
 
; check mii for preamble suppression
mov ah, cl
mov al, REG_MII_BMSR
call mdio_read
test al, 1000000b ; preamble suppression?
setz [device.preamble] ; no
 
.finish:
pop eax
ret
 
 
 
;***************************************************************************
; Function
; test_packet
; Description
; try_loopback try a loopback packet for 10BASE2 or AUI port
; Parameters
; ebx = device structure
;
;***************************************************************************
 
align 4
test_packet:
 
DEBUGF 1,"sending test packet\n"
 
; switch to register window 3
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+3
out dx, ax
 
; set fullDuplexEnable in MacControl register
set_io REG_MAC_CONTROL
in ax, dx
or ax, 0x120
out dx, ax
 
; switch to register window 5
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+5
out dx, ax
 
; set RxFilter to enable individual address matches
mov ax, (10000b shl 11)
set_io REG_RX_FILTER
in al, dx
or al, 1
set_io REG_COMMAND
out dx, ax
 
; issue RxEnable and TxEnable
call rx_reset
call tx_reset
 
; create self-directed packet
stdcall KernelAlloc, 20 ; create a buffer for the self-directed packet
test eax, eax
jz .fail
 
pushd 20 ; Packet parameters for device.transmit
push eax ;
 
mov edi, eax
lea esi, [device.mac]
movsw
movsd
sub esi, 6
movsw
movsd
mov ax , 0x0608
stosw
 
; download self-directed packet
call [device.transmit]
 
; wait for 2s
mov esi, 2000
call Sleep
 
; check if self-directed packet is received
mov eax, [device.packets_rx]
test eax, eax
jnz .finish
 
; switch to register window 3
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+3
out dx, ax
 
; clear fullDuplexEnable in MacControl register
set_io REG_MAC_CONTROL
in ax , dx
and ax , not 0x120
out dx , ax
.fail:
xor eax, eax
 
.finish:
ret
 
 
 
;***************************************************************************
; Function
; try_loopback
; Description
; tries a loopback packet for 10BASE2 or AUI port
; Parameters
; al - 0: 10Mbps AUI connector
; 1: 10BASE-2
; ebp - io_addr
; Return value
; al - 0
; al - 1
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;***************************************************************************
 
align 4
try_loopback:
 
DEBUGF 1,"trying loopback\n"
 
push eax
; switch to register window 3
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+3
out dx, ax
mov eax, [esp]
 
mov cl, al
inc cl
shl cl, 3
or byte [device.state+1], cl
 
test al, al ; aui or coax?
jz .complete_loopback
; enable 100BASE-2 DC-DC converter
mov ax, (10b shl 11) ; EnableDcConverter
out dx, ax
.complete_loopback:
 
mov cx, 2 ; give a port 3 chances to complete a loopback
.next_try:
push ecx
call test_packet
pop ecx
test eax, eax
loopzw .next_try
 
.finish:
xchg eax, [esp]
test al, al
jz .aui_finish
 
; issue DisableDcConverter command
set_io 0
set_io REG_COMMAND
mov ax, (10111b shl 11)
out dx, ax
.aui_finish:
pop eax ; al contains the result of operation
 
test al, al
jnz @f
and byte [device.state+1], not 11000b
@@:
 
ret
 
 
;***************************************************************************
; Function
; set_active_port
; Description
; It selects the media port (transceiver) to be used
; Return value:
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;***************************************************************************
 
align 4
set_active_port:
 
DEBUGF 1,"Trying to find the active port\n"
 
; switch to register window 3
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW + 3
out dx, ax
 
set_io REG_INTERNAL_CONFIG
in eax, dx
test eax, (1 shl 24) ; check if autoselect enable
jz .set_first_available_media
 
; check 100BASE-TX and 10BASE-T
set_io REG_MEDIA_OPTIONS
in ax, dx
test al, 1010b ; check whether 100BASE-TX or 10BASE-T available
jz .mii_device ; they are not available
 
; set auto-negotiation
set_io REG_INTERNAL_CONFIG
in eax, dx
and eax, not (1111b shl 20)
or eax, (1000b shl 20)
out dx, eax
call try_mii
test al, al
jz .mii_device
DEBUGF 1,"Using auto negotiation\n"
ret
 
.mii_device:
; switch to register window 3
set_io 0
; check for off-chip mii device
set_io REG_MEDIA_OPTIONS
in ax, dx
test al, 1000000b ; check miiDevice
jz .base_fx
set_io REG_INTERNAL_CONFIG
in eax, dx
and eax, not (1111b shl 20)
or eax, (0110b shl 20) ; set MIIDevice
out dx, eax
call try_mii
test al, al
jz .base_fx
DEBUGF 1,"Using off-chip mii device\n"
ret
 
.base_fx:
; switch to register window 3
set_io 0
; check for 100BASE-FX
set_io REG_MEDIA_OPTIONS
in ax, dx ; read media option register
test al, 100b ; check 100BASE-FX
jz .aui_enable
set_io REG_INTERNAL_CONFIG
in eax, dx
and eax, not (1111b shl 20)
or eax, (0101b shl 20) ; set 100base-FX
out dx, eax
call try_link_detect
test al, al
jz .aui_enable
DEBUGF 1,"Using 100Base-FX\n"
ret
 
.aui_enable:
; switch to register window 3
set_io 0
; check for 10Mbps AUI connector
set_io REG_MEDIA_OPTIONS
in ax, dx ; read media option register
test al, 100000b ; check 10Mbps AUI connector
jz .coax_available
set_io REG_INTERNAL_CONFIG
in eax, dx
and eax, not (1111b shl 20)
or eax, (0001b shl 20) ; set 10Mbps AUI connector
out dx, eax
xor al, al ; try 10Mbps AUI connector
call try_loopback
test al, al
jz .coax_available
DEBUGF 1,"Using 10Mbps aui\n"
ret
 
.coax_available:
; switch to register window 3
set_io 0
; check for coaxial 10BASE-2 port
set_io REG_MEDIA_OPTIONS
in ax, dx ; read media option register
test al, 10000b ; check 10BASE-2
jz .set_first_available_media
 
set_io REG_INTERNAL_CONFIG
in eax, dx
and eax, not (1111b shl 20)
or eax, (0011b shl 20) ; set 10BASE-2
out dx, eax
mov al, 1
call try_loopback
test al, al
jz .set_first_available_media
DEBUGF 1,"Using 10BASE-2 port\n"
ret
 
.set_first_available_media:
DEBUGF 1,"Using the first available media\n"
 
;***************************************************************************
; Function
; set_available_media
; Description
; sets the first available media
; Parameters
; ebx - ptr to device struct
; Return value
; al - 0
; al - 1
; Destroyed registers
; eax, edx
;
;***************************************************************************
 
align 4
set_available_media:
 
DEBUGF 1,"Setting the available media\n"
; switch to register window 3
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+3
out dx, ax
 
set_io REG_MEDIA_OPTIONS
in ax, dx
DEBUGF 1,"available media:%x\n", al
mov cl, al
 
set_io REG_INTERNAL_CONFIG
in eax, dx
and eax, not (1111b shl 20) ; these bits hold the 'transceiver select' value
 
test cl, 10b ; baseTXAvailable
jz @f
 
DEBUGF 1,"base TX is available\n"
or eax, (100b shl 20)
if defined FORCE_FD
mov word [device.state], (1 shl 8)
else
mov word [device.mode], (1 shl 7)
end if
jmp .set_media
@@:
 
test cl, 100b ; baseFXAvailable
jz @f
 
DEBUGF 1,"base FX is available\n"
or eax, (101b shl 20)
mov word [device.state], (1 shl 10)
jmp .set_media
@@:
 
test cl, 1000000b ; miiDevice
jz @f
 
DEBUGF 1,"mii-device is available\n"
or eax, (0110b shl 20)
mov word [device.state], (1 shl 13)
jmp .set_media
@@:
 
test cl, 1000b ; 10bTAvailable
jz @f
 
DEBUGF 1,"10base-T is available\n"
.set_default:
if FORCE_FD
mov word [device.state], (1 shl 6)
else
mov word [device.state], (1 shl 5)
end if
jmp .set_media
@@:
 
test cl, 10000b ; coaxAvailable
jz @f
 
DEBUGF 1,"coax is available\n"
push eax
set_io REG_COMMAND
mov ax, (10b shl 11) ; EnableDcConverter
out dx, ax
pop eax
 
or eax, (11b shl 20)
mov word [device.state], (1 shl 12)
jmp .set_media
@@:
 
test cl, 10000b ; auiAvailable
jz .set_default
 
DEBUGF 1,"AUI is available\n"
or eax, (1 shl 20)
mov word [device.state], (1 shl 11)
 
.set_media:
set_io 0
set_io REG_INTERNAL_CONFIG
out dx, eax
 
if FORCE_FD
DEBUGF 1,"Forcing full duplex\n"
set_io REG_MAC_CONTROL
in ax, dx
or ax, 0x120
out dx, ax
end if
 
mov al, 1
ret
 
 
 
;***************************************************************************
; Function
; wake_up
; Description
; set the power state to D0
;
;***************************************************************************
 
align 4
wake_up:
 
DEBUGF 1,"Waking up NIC: "
 
; wake up - we directly do it by programming PCI
; check if the device is power management capable
stdcall PciRead32, [device.pci_bus], [device.pci_dev], PCI_REG_STATUS
 
test al, 10000b ; is there "new capabilities" linked list?
jz .device_awake
 
; search for power management register
stdcall PciRead16, [device.pci_bus], [device.pci_dev], PCI_REG_CAP_PTR
cmp al, 0x3f
jbe .device_awake
 
; traverse the list
movzx esi, al
.pm_loop:
stdcall PciRead32, [device.pci_bus], [device.pci_dev], esi
 
cmp al , 1
je .set_pm_state
 
movzx esi, ah
 
test ah , ah
jnz .pm_loop
jmp .device_awake
 
; waku up the device if necessary
.set_pm_state:
 
add esi, PCI_REG_PM_CTRL
stdcall PciRead32, [device.pci_bus], [device.pci_dev], esi
test al, 3
jz .device_awake
and al, not 11b ; set state to D0
stdcall PciWrite32, [device.pci_bus], [device.pci_dev], esi, eax
 
.device_awake:
DEBUGF 1,"Device is awake\n"
 
ret
 
 
 
 
;***************************************************************************
; Function
; write_eeprom
; Description
; reads eeprom
; Note : the caller must switch to the register window 0
; before calling this function
; Parameters:
; ax - register to be read (only the first 63 words can be read)
; cx - value to be read into the register
; Return value:
; ax - word read
; Destroyed registers
; ax, ebx, edx
;
;***************************************************************************
; align 4
;write_eeprom:
; mov edx, [io_addr]
; add edx, REG_EEPROM_COMMAND
; cmp ah, 11b
; ja .finish ; address may have a value of maximal 1023
; shl ax, 2
; shr al, 2
; push eax
;; wait for busy
; mov ebx, 0xffff
;@@:
; in ax, dx
; test ah, 0x80
; jz .write_enable
; dec ebx
; jns @r
;; write enable
;.write_enable:
; xor eax, eax
; mov eax, (11b shl 4)
; out dx, ax
;; wait for busy
; mov ebx, 0xffff
;@@:
; in ax, dx
; test ah, 0x80
; jz .erase_loop
; dec ebx
; jns @r
;.erase_loop:
; pop eax
; push eax
; or ax, (11b shl 6) ; erase register
; out dx, ax
; mov ebx, 0xffff
;@@:
; in ax, dx
; test ah, 0x80
; jz .write_reg
; dec ebx
; jns @r
;.write_reg:
; add edx, REG_EEPROM_DATA-REG_EEPROM_COMMAND
; mov eax, ecx
; out dx, ax
;; write enable
; add edx, REG_EEPROM_COMMAND-REG_EEPROM_DATA
; xor eax, eax
; mov eax, (11b shl 4)
; out dx, ax
; wait for busy
; mov ebx, 0xffff
;@@:
; in ax, dx
; test ah, 0x80
; jz .issue_write_reg
; dec ebx
; jns @r
;.issue_write_reg:
; pop eax
; or ax, 01b shl 6
; out dx, ax
;.finish:
; ret
 
 
;***************************************************************************
; Function
; read_eeprom
; Description
; reads eeprom
; Parameters:
; ax - register to be read (only the first 63 words can be read)
; ebx = driver structure
; Return value:
; ax - word read
; Destroyed registers
; ax, ebx, edx
;
;***************************************************************************
 
align 4
read_eeprom:
 
DEBUGF 1,"Reading from eeprom.. "
 
push eax
; switch to register window 0
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+0
out dx, ax
pop eax
and ax, 111111b ; take only the first 6 bits into account
movzx esi, [device.ver_id]
 
test word [esi*4+hw_versions+2], EEPROM_8BIT
jz @f
add ax, 0x230 ; hardware constant
jmp .read
@@:
 
add ax, EEPROM_CMD_READ
test word [esi*4+hw_versions+2], EEPROM_OFFSET
jz .read
add ax, 0x30
.read:
 
set_io REG_EEPROM_COMMAND
out dx, ax
mov ecx, 0xffff ; duration of about 162 us ;-)
.wait_for_reading:
in ax, dx
test ah, 0x80 ; check bit eepromBusy
jz .read_data
loop .wait_for_reading
.read_data:
set_io REG_EEPROM_DATA
in ax, dx
 
DEBUGF 1,"ok!\n"
 
ret
 
;***************************************************************************
; Function
; mdio_sync
; Description
; initial synchronization
; Parameters
; ebp - io_addr
; Return value
; Destroyed registers
; ax, edx, cl
;
;***************************************************************************
 
align 4
mdio_sync:
 
DEBUGF 1,"syncing mdio\n"
 
; switch to register window 4
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+4
out dx, ax
cmp [device.preamble], 0
je .no_preamble
; send 32 logic ones
set_io REG_PHYSICAL_MGMT
mov ecx, 31
.loop:
mov ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR)
out dx, ax
in ax, dx ; delay
mov ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_CLK)
out dx, ax
in ax, dx ; delay
loop .loop
.no_preamble:
 
ret
 
;***************************************************************************
; Function
; mdio_read
; Description
; read MII register
; see page 16 in D83840A.pdf
; Parameters
; ah - PHY addr
; al - register addr
; ebx = device structure
; Return value
; ax - register read
;
;***************************************************************************
 
align 4
mdio_read:
 
DEBUGF 1,"Reading MII registers\n"
 
push eax
call mdio_sync ; returns with window #4
pop eax
set_io 0
set_io REG_PHYSICAL_MGMT
shl al, 3
shr ax, 3
and ax, not MII_CMD_MASK
or ax, MII_CMD_READ
 
mov esi, eax
mov ecx, 13
.cmd_loop:
mov ax, (1 shl BIT_MGMT_DIR) ; write mii
bt esi, ecx
jnc .zero_bit
or al, (1 shl BIT_MGMT_DATA)
 
.zero_bit:
out dx, ax
push ax
in ax, dx ; delay
pop ax
or al, (1 shl BIT_MGMT_CLK) ; write
out dx, ax
in ax, dx ; delay
loop .cmd_loop
 
; read data (18 bits with the two transition bits)
mov ecx, 17
xor esi, esi
.read_loop:
shl esi, 1
xor eax, eax ; read comand
out dx, ax
in ax, dx ; delay
in ax, dx
test al, (1 shl BIT_MGMT_DATA)
jz .dont_set
inc esi
.dont_set:
mov ax, (1 shl BIT_MGMT_CLK)
out dx, ax
in ax, dx ; delay
loop .read_loop
mov eax, esi
 
ret
 
 
 
;***************************************************************************
; Function
; mdio_write
; Description
; write MII register
; see page 16 in D83840A.pdf
; Parameters
; ah - PHY addr
; al - register addr
; si - word to be written
; Return value
; ax - register read
;
;***************************************************************************
 
align 4
mdio_write:
 
DEBUGF 1,"Writing MII registers\n"
 
push eax
call mdio_sync
pop eax
set_io 0
set_io REG_PHYSICAL_MGMT
shl al, 3
shr ax, 3
and ax, not MII_CMD_MASK
or ax, MII_CMD_WRITE
shl eax, 2
or eax, 10b ; transition bits
shl eax, 16
mov ax, si
mov esi, eax
mov ecx, 31
 
.cmd_loop:
mov ax, (1 shl BIT_MGMT_DIR) ; write mii
bt esi, ecx
jnc @f
or al, (1 shl BIT_MGMT_DATA)
@@:
out dx, ax
push eax
in ax, dx ; delay
pop eax
or al, (1 shl BIT_MGMT_CLK) ; write
out dx, ax
in ax, dx ; delay
loop .cmd_loop
 
ret
 
 
;***************************************************************************
; Function
; check_tx_status
; Description
; Checks TxStatus queue.
; Return value
; al - 0 no error was found
; al - 1 error was found TxReset was needed
; Destroyed registers
; eax, ecx, edx, ebp
;
;***************************************************************************
 
align 4
check_tx_status:
 
DEBUGF 1,"Checking TX status\n"
 
; clear TxStatus queue
set_io 0
set_io REG_TX_STATUS
mov ecx, 31 ; max number of queue entries
 
.tx_status_loop:
in al, dx
test al, al
jz .finish ; no error
test al, 0x3f
jnz .error
.no_error_found:
; clear current TxStatus entry which advances the next one
xor al, al
out dx, al
loop .tx_status_loop
 
.finish:
 
ret
 
.error:
call tx_reset
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit (vortex) ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
vortex_transmit:
 
DEBUGF 1,"Sending packet (vortex)\n"
 
cmp dword [esp+8], MAX_ETH_FRAME_SIZE
ja .finish ; packet is too long
 
call check_tx_status
 
; switch to register window 7
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+7
out dx, ax
; check for master operation in progress
set_io REG_MASTER_STATUS
in ax, dx
test ah, 0x80
jnz .finish ; no DMA for sending
; program frame address to be sent
set_io REG_MASTER_ADDRESS
mov eax, [esp+4]
call GetPgAddr
out dx, eax
; program frame length
set_io REG_MASTER_LEN
mov eax, [esp+8]
;;; and eax, not 3
out dx, ax
; start DMA Down
set_io REG_COMMAND
mov ax, (10100b shl 11) + 1 ; StartDMADown
out dx, ax
.finish:
call KernelFree
add esp, 4
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit (boomerang) ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
boomerang_transmit:
 
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
mov eax, [esp+4]
DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
 
cmp dword [esp+8], MAX_ETH_FRAME_SIZE
ja .fail
 
call check_tx_status
 
; calculate descriptor address
mov esi, [device.prev_dpd]
DEBUGF 1,"Previous DPD: %x\n", esi
add esi, dpd.size
lea ecx, [device.dpd_buffer + (NUM_TX_DESC)*dpd.size]
cmp esi, ecx
jb @f
lea esi, [device.dpd_buffer] ; Wrap if needed
@@:
DEBUGF 1,"Found a free DPD: %x\n", esi
 
; check DnListPtr
set_io 0
set_io REG_DN_LIST_PTR
in eax, dx
; mark if Dn_List_Ptr is cleared
test eax, eax
setz [device.dn_list_ptr_cleared]
 
; finish if no more free descriptor is available - FIXME!
; cmp eax, esi
; jz .finish
 
; update statistics
inc [device.packets_tx]
mov ecx, [esp+8] ; buffer size
add dword [device.bytes_tx], ecx
adc dword [device.bytes_tx + 4], 0
 
; program DPD
and [esi+dpd.next_ptr], 0
mov eax, [esp+4] ; Tx buffer address
mov [esi+dpd.realaddr], eax
call GetPgAddr
mov [esi+dpd.frag_addr], eax
mov ecx, [esp+8] ; packet size
or ecx, 0x80000000 ; last fragment
mov [esi+dpd.frag_len], ecx
 
mov ecx, [esp+8] ; packet size
; or ecx, 0x8000 ; transmission complete notification
 
or ecx, 1 shl 31
 
; test byte [device.has_hwcksm], 0xff
; jz @f
; or ecx, (1 shl 26) ; set AddTcpChecksum
;@@:
mov [esi+dpd.frame_start_hdr], ecx
 
DEBUGF 1,"DPD: lin=%x phys=%x len=%x start hdr=%x\n", [esi+dpd.realaddr]:8, [esi+dpd.frag_addr]:8, [esi+dpd.frag_len]:8, [esi+dpd.frame_start_hdr]:8
 
; calculate physical address of dpd
mov eax, esi
GetRealAddr
cmp [device.dn_list_ptr_cleared], 0
jz .add_to_list
 
; write Dn_List_Ptr
DEBUGF 1,"DPD phys addr=%x\n", eax
set_io 0
set_io REG_DN_LIST_PTR
out dx, eax
jmp .finish
 
.add_to_list:
DEBUGF 1,"Adding To list\n"
push eax
; DnStall
set_io 0
set_io REG_COMMAND
mov ax, ((110b shl 11)+2)
out dx, ax
 
; wait for DnStall to complete
DEBUGF 1,"Waiting for DnStall\n"
mov ecx, 6000
.wait_for_stall:
in ax, dx ; read REG_INT_STATUS
test ah, 10000b
jz .dnstall_ok
dec ecx
jnz .wait_for_stall
 
.dnstall_ok:
DEBUGF 1,"DnStall ok!\n"
mov ecx, [device.prev_dpd]
mov [ecx+dpd.next_ptr], eax
 
set_io 0
set_io REG_DN_LIST_PTR
in eax, dx
test eax, eax
pop eax
jnz .dnunstall
 
; if Dn_List_Ptr has been cleared fill it up
DEBUGF 1,"DnList Ptr has been cleared\n"
out dx, eax
 
.dnunstall:
; DnUnStall
set_io 0
set_io REG_COMMAND
mov ax, ((110b shl 11)+3)
out dx, ax
 
.finish:
mov [device.prev_dpd], esi
xor eax, eax
ret 8
 
.fail:
stdcall KernelFree, [esp+4]
or eax, -1
ret 8
 
 
;---------------------------------
; Write MAC
 
align 4
write_mac:
 
DEBUGF 1,"Writing mac\n"
 
set_io 0
set_io REG_COMMAND
 
; switch to register window 2
mov ax, SELECT_REGISTER_WINDOW+2
out dx, ax
 
; write MAC addres back into the station address registers
set_io REG_STATION_ADDRESS_LO
lea esi, [device.mac]
outsw
inc dx
inc dx
outsw
inc dx
inc dx
outsw
 
 
;----------------------------
; Read MAC
 
align 4
read_mac:
 
set_io 0
set_io REG_COMMAND
 
; switch to register window 2
mov ax, SELECT_REGISTER_WINDOW+2
out dx, ax
 
; write MAC addres back into the station address registers
set_io REG_STATION_ADDRESS_LO
lea edi, [device.mac]
insw
inc dx
inc dx
insw
inc dx
inc dx
insw
 
DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
ret
 
 
;------------------------------------
; Read MAC from eeprom
 
align 4
read_mac_eeprom: ; Tested - ok
 
DEBUGF 1,"Reading mac from eeprom\n"
 
; read MAC from eeprom
mov ecx, 3
.mac_loop:
lea ax, [EEPROM_REG_OEM_NODE_ADDR+ecx-1]
push ecx
call read_eeprom
pop ecx
xchg ah, al ; htons
mov word [device.mac+ecx*2-2], ax
loop .mac_loop
 
DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
ret
 
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Vortex Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_vortex:
 
DEBUGF 1,"vortex IRQ %x ",eax:2
 
; find pointer of device wich made IRQ occur
 
mov esi, VORTEX_LIST
mov ecx, [VORTEX_DEVICES]
test ecx, ecx
jz .fail
.nextdevice:
mov ebx, dword [esi]
 
 
set_io 0
set_io REG_INT_STATUS
in ax, dx
;; and ax, INT_MASK
jnz .got_it
 
 
add esi, 4
 
test ax , ax
jnz .got_it
loop .nextdevice
 
.fail:
 
ret
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x ",ebx,eax:4
 
test ax, RxComplete
jz .noRX
 
set_io 0
.rx_status_loop:
; examine RxStatus
set_io REG_RX_STATUS
in ax, dx
test ax, ax
jz .finish
 
test ah, 0x80 ; rxIncomplete
jnz .finish
 
test ah, 0x40
jz .check_length
 
; discard the top frame received advancing the next one
set_io REG_COMMAND
mov ax, (01000b shl 11)
out dx, ax
jmp .rx_status_loop
 
.check_length:
and eax, 0x1fff
cmp eax, MAX_ETH_PKT_SIZE
ja .discard_frame ; frame is too long discard it
 
.check_dma:
mov ecx, eax
; switch to register window 7
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+7
out dx, ax
; check for master operation in progress
set_io REG_MASTER_STATUS
in ax, dx
 
test ah, 0x80
jnz .finish
 
.read_frame:
; program buffer address to read in
push ecx
stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
pop ecx
test eax, eax
jz .finish
 
push .discard_frame
push ecx
push eax
; zero_to_dma eax
set_io REG_MASTER_ADDRESS
out dx, eax
 
; program frame length
set_io REG_MASTER_LEN
mov ax, 1560
out dx, ax
 
; start DMA Up
set_io REG_COMMAND
mov ax, (10100b shl 11) ; StartDMAUp
out dx, ax
 
; check for master operation in progress
set_io REG_MASTER_STATUS ; TODO: use timeout and reset after timeout expired
.dma_loop:
in ax, dx
test ah, 0x80
jnz .dma_loop
 
; registrate the received packet to kernel
jmp Eth_input
 
; discard the top frame received
.discard_frame:
set_io 0
set_io REG_COMMAND
mov ax, (01000b shl 11)
out dx, ax
 
.finish:
 
 
.noRX:
 
test ax, DMADone
jz .noDMA
 
push ax
 
set_io 0
set_io 12
in ax, dx
test ax, 0x1000
jz .nodmaclear
 
mov ax, 0x1000
out dx, ax
 
.nodmaclear:
 
pop ax
 
DEBUGF 1, "DMA Done!\n", cx
 
 
 
.noDMA:
 
 
 
.ACK:
set_io 0
set_io REG_COMMAND
mov ax, AckIntr + IntReq + IntLatch
out dx, ax
 
ret
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Boomerang Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_boomerang:
 
DEBUGF 1,"\nBoomerang int\n"
 
; find pointer of device wich made IRQ occur
 
mov ecx, [BOOMERANG_DEVICES]
test ecx, ecx
jz .nothing
mov esi, BOOMERANG_LIST
.nextdevice:
mov ebx, [esi]
 
set_io 0
set_io REG_INT_STATUS
in ax, dx
test ax, ax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
ret
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x ", ebx, ax
push ax
 
; disable all INTS
 
set_io REG_COMMAND
mov ax, SetIntrEnb
out dx, ax
 
;--------------------------------------------------------------------------
test word[esp], UpComplete
jz .noRX
 
push ebx
 
.receive:
DEBUGF 1,"UpComplete\n"
 
; check if packet is uploaded
mov esi, [device.curr_upd]
test byte [esi+upd.pkt_status+1], 0x80 ; upPktComplete
jz .finish
DEBUGF 1, "Current upd: %x\n", esi
; packet is uploaded check for any error
.check_error:
test byte [esi+upd.pkt_status+1], 0x40 ; upError
jz .copy_packet_length
DEBUGF 1,"Error in packet\n"
and [esi+upd.pkt_status], 0 ; mark packet as read
jmp .finish
.copy_packet_length:
mov ecx, [esi+upd.pkt_status]
and ecx, 0x1fff
 
; cmp ecx, MAX_ETH_PKT_SIZE
; jbe .copy_packet
; and [esi+upd.pkt_status], 0
; jmp .finish
; .copy_packet:
 
DEBUGF 1, "Received %u bytes in buffer %x\n", ecx, [esi+upd.realaddr]:8
 
push dword .loop ;.finish
push ecx
push [esi+upd.realaddr]
 
; update statistics
inc [device.packets_rx]
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
 
; update UPD (Alloc new buffer for next packet)
stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
mov [esi + upd.realaddr], eax
GetRealAddr
mov [esi + upd.frag_addr], eax
and [esi + upd.pkt_status], 0
mov [esi + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
 
; Update UPD pointer
add esi, upd.size
lea ecx, [device.upd_buffer+(NUM_RX_DESC)*upd.size]
cmp esi, ecx
jb @f
lea esi, [device.upd_buffer]
@@:
mov [device.curr_upd], esi
DEBUGF 1, "Next upd: %x\n", esi
 
jmp Eth_input
.loop:
 
mov ebx, [esp]
jmp .receive
 
.finish:
pop ebx
 
; check if the NIC is in the upStall state
set_io 0
set_io REG_UP_PKT_STATUS
in eax, dx
test ah, 0x20 ; UpStalled
jz .noUpUnStall
 
DEBUGF 1, "upUnStalling\n"
; issue upUnStall command
set_io REG_COMMAND
mov ax, ((11b shl 12)+1) ; upUnStall
out dx, ax
 
;;;; FIXME: make upunstall work
 
.noUpUnStall:
.noRX:
test word[esp], DownComplete
jz .noTX
DEBUGF 1, "Downcomplete!\n"
 
mov ecx, NUM_TX_DESC
lea esi, [device.dpd_buffer]
.txloop:
test [esi+dpd.frame_start_hdr], 1 shl 31
jz .maybenext
 
and [esi+dpd.frame_start_hdr], 0
push ecx
stdcall KernelFree, [esi+dpd.realaddr]
pop ecx
 
.maybenext:
add esi, dpd.size
dec ecx
jnz .txloop
 
.noTX:
pop ax
 
set_io 0
set_io REG_COMMAND
or ax, AckIntr
out dx, ax
 
set_io REG_INT_STATUS
in ax, dx
test ax, S_5_INTS
jnz .got_it
 
;re-enable ints
set_io REG_COMMAND
mov ax, SetIntrEnb + S_5_INTS
out dx, ax
 
ret
 
 
 
 
; End of code
align 4 ; Place all initialised data here
 
macro strtbl name, [string]
{
common
label name dword
forward
local label
dd label
forward
label db string, 0
}
 
VORTEX_DEVICES dd 0
BOOMERANG_DEVICES dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db '3C59X',0 ; max 16 chars include zero
 
 
strtbl link_str, \
"No valid link type detected", \
"10BASE-T half duplex", \
"10BASE-T full-duplex", \
"100BASE-TX half duplex", \
"100BASE-TX full duplex", \
"100BASE-T4", \
"100BASE-FX", \
"10Mbps AUI", \
"10Mbps COAX (BNC)", \
"miiDevice - not supported"
 
strtbl hw_str, \
"3c590 Vortex 10Mbps", \
"3c592 EISA 10Mbps Demon/Vortex", \
"3c597 EISA Fast Demon/Vortex", \
"3c595 Vortex 100baseTx", \
"3c595 Vortex 100baseT4", \
"3c595 Vortex 100base-MII", \
"3c900 Boomerang 10baseT", \
"3c900 Boomerang 10Mbps Combo", \
"3c900 Cyclone 10Mbps TPO", \
"3c900 Cyclone 10Mbps Combo", \
"3c900 Cyclone 10Mbps TPC", \
"3c900B-FL Cyclone 10base-FL", \
"3c905 Boomerang 100baseTx", \
"3c905 Boomerang 100baseT4", \
"3c905B Cyclone 100baseTx", \
"3c905B Cyclone 10/100/BNC", \
"3c905B-FX Cyclone 100baseFx", \
"3c905C Tornado", \
"3c980 Cyclone", \
"3c982 Dual Port Server Cyclone", \
"3cSOHO100-TX Hurricane", \
"3c555 Laptop Hurricane", \
"3c556 Laptop Tornado", \
"3c556B Laptop Hurricane", \
"3c575 [Megahertz] 10/100 LAN CardBus", \
"3c575 Boomerang CardBus", \
"3CCFE575BT Cyclone CardBus", \
"3CCFE575CT Tornado CardBus", \
"3CCFE656 Cyclone CardBus", \
"3CCFEM656B Cyclone+Winmodem CardBus", \
"3CXFEM656C Tornado+Winmodem CardBus", \
"3c450 HomePNA Tornado", \
"3c920 Tornado", \
"3c982 Hydra Dual Port A", \
"3c982 Hydra Dual Port B", \
"3c905B-T4", \
"3c920B-EMB-WNM Tornado"
 
 
 
align 4
hw_versions:
dw 0x5900, IS_VORTEX ; 3c590 Vortex 10Mbps
dw 0x5920, IS_VORTEX ; 3c592 EISA 10Mbps Demon/Vortex
dw 0x5970, IS_VORTEX ; 3c597 EISA Fast Demon/Vortex
dw 0x5950, IS_VORTEX ; 3c595 Vortex 100baseTx
dw 0x5951, IS_VORTEX ; 3c595 Vortex 100baseT4
dw 0x5952, IS_VORTEX ; 3c595 Vortex 100base-MII
dw 0x9000, IS_BOOMERANG ; 3c900 Boomerang 10baseT
dw 0x9001, IS_BOOMERANG ; 3c900 Boomerang 10Mbps Combo
dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPO
dw 0x9005, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps Combo
dw 0x9006, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPC
dw 0x900A, IS_CYCLONE or HAS_HWCKSM ; 3c900B-FL Cyclone 10base-FL
dw 0x9050, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseTx
dw 0x9051, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseT4
dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B Cyclone 100baseTx
dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c905B Cyclone 10/100/BNC
dw 0x905A, IS_CYCLONE or HAS_HWCKSM ; 3c905B-FX Cyclone 100baseFx
dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c905C Tornado
dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c980 Cyclone
dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c982 Dual Port Server Cyclone
dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3cSOHO100-TX Hurricane
dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM ; 3c555 Laptop Hurricane
dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM ; 3c556 Laptop Tornado
dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM ; 3c556B Laptop Hurricane
dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 [Megahertz] 10/100 LAN CardBus
dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 Boomerang CardBus
dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE575BT Cyclone CardBus
dw 0x5257, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CCFE575CT Tornado CardBus
dw 0x6560, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE656 Cyclone CardBus
dw 0x6562, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFEM656B Cyclone+Winmodem CardBus
dw 0x6564, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CXFEM656C Tornado+Winmodem CardBus
dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c450 HomePNA Tornado
dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920 Tornado
dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port A
dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port B
dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B-T4
dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920B-EMB-WNM Tornado
HW_VERSIONS_SIZE = $ - hw_versions
 
include_debug_strings ; All data wich FDO uses will be included here
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
 
VORTEX_LIST rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
BOOMERANG_LIST rd MAX_DEVICES
 
 
 
 
/kernel/branches/net/drivers/R6040.asm
0,0 → 1,1111
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; R6040 driver for KolibriOS ;;
;; ;;
;; based on R6040.c from linux ;;
;; ;;
;; Written by Asper (asper.85@mail.ru) ;;
;; and hidnplayr (hidnplayr@gmail.com) ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 2
 
W_MAX_TIMEOUT = 0x0FFF ; max time out delay time
 
TX_TIMEOUT = 6000 ; Time before concluding the transmitter is hung, in ms
 
TX_RING_SIZE = 4 ; RING sizes must be a power of 2
RX_RING_SIZE = 4
 
RX_BUF_LEN_IDX = 3 ; 0==8K, 1==16K, 2==32K, 3==64K
 
; Threshold is bytes transferred to chip before transmission starts.
 
TX_FIFO_THRESH = 256 ; In bytes, rounded down to 32 byte units.
 
; The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024.
 
RX_FIFO_THRESH = 4 ; Rx buffer level before first PCI xfer.
RX_DMA_BURST = 4 ; Maximum PCI burst, '4' is 256 bytes
TX_DMA_BURST = 4
 
 
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
 
public START
public service_proc
public version
 
; Operational parameters that usually are not changed.
 
PHY1_ADDR = 1 ;For MAC1
PHY2_ADDR = 3 ;For MAC2
PHY_MODE = 0x3100 ;PHY CHIP Register 0
PHY_CAP = 0x01E1 ;PHY CHIP Register 4
 
;**************************************************************************
; RDC R6040 Register Definitions
;**************************************************************************
MCR0 = 0x00 ;Control register 0
MCR1 = 0x01 ;Control register 1
MAC_RST = 0x0001 ;Reset the MAC
MBCR = 0x08 ;Bus control
MT_ICR = 0x0C ;TX interrupt control
MR_ICR = 0x10 ;RX interrupt control
MTPR = 0x14 ;TX poll command register
MR_BSR = 0x18 ;RX buffer size
MR_DCR = 0x1A ;RX descriptor control
MLSR = 0x1C ;Last status
MMDIO = 0x20 ;MDIO control register
MDIO_WRITE = 0x4000 ;MDIO write
MDIO_READ = 0x2000 ;MDIO read
MMRD = 0x24 ;MDIO read data register
MMWD = 0x28 ;MDIO write data register
MTD_SA0 = 0x2C ;TX descriptor start address 0
MTD_SA1 = 0x30 ;TX descriptor start address 1
MRD_SA0 = 0x34 ;RX descriptor start address 0
MRD_SA1 = 0x38 ;RX descriptor start address 1
MISR = 0x3C ;Status register
MIER = 0x40 ;INT enable register
MSK_INT = 0x0000 ;Mask off interrupts
RX_FINISH = 0x0001 ;RX finished
RX_NO_DESC = 0x0002 ;No RX descriptor available
RX_FIFO_FULL = 0x0004 ;RX FIFO full
RX_EARLY = 0x0008 ;RX early
TX_FINISH = 0x0010 ;TX finished
TX_EARLY = 0x0080 ;TX early
EVENT_OVRFL = 0x0100 ;Event counter overflow
LINK_CHANGED = 0x0200 ;PHY link changed
ME_CISR = 0x44 ;Event counter INT status
ME_CIER = 0x48 ;Event counter INT enable
MR_CNT = 0x50 ;Successfully received packet counter
ME_CNT0 = 0x52 ;Event counter 0
ME_CNT1 = 0x54 ;Event counter 1
ME_CNT2 = 0x56 ;Event counter 2
ME_CNT3 = 0x58 ;Event counter 3
MT_CNT = 0x5A ;Successfully transmit packet counter
ME_CNT4 = 0x5C ;Event counter 4
MP_CNT = 0x5E ;Pause frame counter register
MAR0 = 0x60 ;Hash table 0
MAR1 = 0x62 ;Hash table 1
MAR2 = 0x64 ;Hash table 2
MAR3 = 0x66 ;Hash table 3
MID_0L = 0x68 ;Multicast address MID0 Low
MID_0M = 0x6A ;Multicast address MID0 Medium
MID_0H = 0x6C ;Multicast address MID0 High
MID_1L = 0x70 ;MID1 Low
MID_1M = 0x72 ;MID1 Medium
MID_1H = 0x74 ;MID1 High
MID_2L = 0x78 ;MID2 Low
MID_2M = 0x7A ;MID2 Medium
MID_2H = 0x7C ;MID2 High
MID_3L = 0x80 ;MID3 Low
MID_3M = 0x82 ;MID3 Medium
MID_3H = 0x84 ;MID3 High
PHY_CC = 0x88 ;PHY status change configuration register
PHY_ST = 0x8A ;PHY status register
MAC_SM = 0xAC ;MAC status machine
MAC_ID = 0xBE ;Identifier register
 
MAX_BUF_SIZE = 0x600 ;1536
 
MBCR_DEFAULT = 0x012A ;MAC Bus Control Register
MCAST_MAX = 3 ;Max number multicast addresses to filter
 
;Descriptor status
DSC_OWNER_MAC = 0x8000 ;MAC is the owner of this descriptor
DSC_RX_OK = 0x4000 ;RX was successfull
DSC_RX_ERR = 0x0800 ;RX PHY error
DSC_RX_ERR_DRI = 0x0400 ;RX dribble packet
DSC_RX_ERR_BUF = 0x0200 ;RX length exceeds buffer size
DSC_RX_ERR_LONG = 0x0100 ;RX length > maximum packet length
DSC_RX_ERR_RUNT = 0x0080 ;RX packet length < 64 byte
DSC_RX_ERR_CRC = 0x0040 ;RX CRC error
DSC_RX_BCAST = 0x0020 ;RX broadcast (no error)
DSC_RX_MCAST = 0x0010 ;RX multicast (no error)
DSC_RX_MCH_HIT = 0x0008 ;RX multicast hit in hash table (no error)
DSC_RX_MIDH_HIT = 0x0004 ;RX MID table hit (no error)
DSC_RX_IDX_MID_MASK = 3 ;RX mask for the index of matched MIDx
 
;PHY settings
ICPLUS_PHY_ID = 0x0243
 
RX_INTS = RX_FIFO_FULL or RX_NO_DESC or RX_FINISH
TX_INTS = TX_FINISH
INT_MASK = RX_INTS or TX_INTS
 
RX_BUF_LEN equ (8192 << RX_BUF_LEN_IDX) ; Size of the in-memory receive ring.
 
IO_SIZE = 256 ; RDC MAC I/O Size
MAX_MAC = 2 ; MAX RDC MAC
 
 
virtual at 0
x_head:
.status dw ? ;0-1
.len dw ? ;2-3
.buf dd ? ;4-7
.ndesc dd ? ;8-B
.rev1 dd ? ;C-F
.vbufp dd ? ;10-13
.vndescp dd ? ;14-17
.skb_ptr dd ? ;18-1B
.rev2 dd ? ;1C-1F
.sizeof:
end virtual
 
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.io_addr dd ?
 
.cur_rx dw ?
.cur_tx dw ?
.last_tx dw ?
.phy_addr dw ?
.phy_mode dw ?
.mcr0 dw ?
.mcr1 dw ?
.switch_sig dw ?
 
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
 
rb 3 ; dword alignment
 
.tx_ring: rb (((x_head.sizeof*TX_RING_SIZE)+32) and 0xfffffff0)
.rx_ring: rb (((x_head.sizeof*RX_RING_SIZE)+32) and 0xfffffff0)
 
.size = $ - device
 
end virtual
 
 
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
 
.entry:
 
DEBUGF 2,"Loading %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
 
.fail:
.exit:
xor eax, eax
ret
 
endp
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne @F
 
cmp [IOCTL.out_size], 4
jb .fail
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
 
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
 
mov eax, [IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet
 
; check if the device is already listed
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax , [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
 
 
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, device.size, .fail ; Allocate the buffer for device structure
 
; Fill in the direct call addresses into the struct
 
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], unload
mov [device.name], my_service
 
; save the pci bus and device numbers
 
mov eax, [IOCTL.input]
movzx ecx, byte[eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte[eax+2]
mov [device.pci_dev], ecx
 
; Now, it's time to find the base io addres of the PCI device
 
PCI_find_io
 
; We've found the io address, find IRQ now
 
PCI_find_irq
 
DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
 
; Ok, the eth_device structure is ready, let's probe the device
cli
 
call probe ; this function will output in eax
test eax, eax
jnz .err_sti ; If an error occured, exit
 
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
sti
 
cmp eax, -1
je .destroy
 
ret
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 1,"Trying to find device number of already registered device\n"
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 1,"Kernel says: %u\n", eax
ret
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
; todo: reset device into virgin state
 
.err_sti:
sti
 
.err:
stdcall KernelFree, ebx
 
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
macro mdio_write reg, val {
stdcall phy_read, [device.io_addr], [device.phy_addr], reg
}
 
macro mdio_write reg, val {
stdcall phy_write, [device.io_addr], [devce.phy_addr], reg, val
}
 
 
align 4
unload:
; TODO: (in this particular order)
;
; - Stop the device
; - Detach int handler
; - Remove device from local list (RTL8139_LIST)
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
 
or eax,-1
 
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; probe: enables the device (if it really is RTL8139)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
probe:
DEBUGF 2,"Probing R6040 device\n"
 
PCI_make_bus_master
 
; If PHY status change register is still set to zero
; it means the bootloader didn't initialize it
 
set_io 0
set_io PHY_CC
in ax, dx
test ax, ax
jnz @f
mov ax, 0x9F07
out dx, ax
@@:
 
call read_mac
 
; Some bootloaders/BIOSes do not initialize MAC address, warn about that
and eax, 0xFF
or eax, dword [device.mac]
test eax, eax
jnz @f
DEBUGF 2, "ERROR: MAC address not initialized!\n"
 
@@:
; Init RDC private data
mov [device.mcr0], 0x1002
;mov [private.phy_addr], 1 ; Asper: Only one network card is supported now.
mov [device.switch_sig], 0
 
; Check the vendor ID on the PHY, if 0xFFFF assume none attached
stdcall phy_read, 1, 2
cmp ax, 0xFFFF
jne @f
DEBUGF 2, "Failed to detect an attached PHY\n" ;, generating random"
mov eax, -1
ret
@@:
 
; Set MAC address
call init_mac_regs
 
; Initialize and alloc RX/TX buffers
call init_txbufs
call init_rxbufs
 
; Read the PHY ID
mov [device.phy_mode], 0x8000
stdcall phy_read, 0, 2
mov [device.switch_sig], ax
cmp ax, ICPLUS_PHY_ID
jne @f
stdcall phy_write, 29, 31, 0x175C ; Enable registers
jmp .phy_readen
@@:
 
; PHY Mode Check
movzx eax, [device.phy_addr]
stdcall phy_write, eax, 4, PHY_CAP
stdcall phy_write, eax, 0, PHY_MODE
 
if PHY_MODE = 0x3100
call phy_mode_chk
mov [device.phy_mode], ax
jmp .phy_readen
end if
 
if not (PHY_MODE and 0x0100)
mov [device.phy_mode], 0
end if
 
.phy_readen:
 
; Set duplex mode
mov ax, [device.phy_mode]
or [device.mcr0], ax
 
; improve performance (by RDC guys)
stdcall phy_read, 30, 17
or ax, 0x4000
stdcall phy_write, 30, 17, eax
 
stdcall phy_read, 30, 17
and ax, not 0x2000
stdcall phy_write, 30, 17, eax
 
stdcall phy_write, 0, 19, 0x0000
stdcall phy_write, 0, 30, 0x01F0
 
; Initialize all Mac registers
call init_mac_regs
 
 
 
align 4
reset:
 
DEBUGF 2,"Resetting R6040\n"
 
; Mask off Interrupt
xor ax, ax
set_io 0
set_io MIER
out dx, ax
 
 
; attach int handler
 
movzx eax, [device.irq_line]
DEBUGF 2,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax
jnz @f
DEBUGF 2,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
 
;Reset RDC MAC
mov eax, MAC_RST
set_io 0
set_io MCR1
out dx, ax
 
mov ecx, 2048 ;limit
.read:
in ax, dx
test ax, 0x1
jnz @f
dec ecx
test ecx, ecx
jnz .read
@@:
;Reset internal state machine
mov ax, 2
set_io MAC_SM
out dx, ax
 
xor ax, ax
out dx, ax
 
mov esi, 5
stdcall Sleep
 
;MAC Bus Control Register
mov ax, MBCR_DEFAULT
set_io 0
set_io MBCR
out dx, ax
 
;Buffer Size Register
mov ax, MAX_BUF_SIZE
set_io MR_BSR
out dx, ax
 
;Write TX ring start address
lea eax, [device.tx_ring]
GetRealAddr
set_io MTD_SA0
out dx, ax
shr eax, 16
set_io MTD_SA1
out dx, ax
 
;Write RX ring start address
lea eax, [device.rx_ring]
GetRealAddr
set_io MRD_SA0
out dx, ax
shr eax, 16
set_io MRD_SA1
out dx, ax
 
;Set interrupt waiting time and packet numbers
xor ax, ax
set_io MT_ICR
out dx, ax
 
;Enable interrupts
mov ax, INT_MASK
set_io MIER
out dx, ax
 
;Enable TX and RX
mov ax, [device.mcr0]
or ax, 0x0002
set_io 0
out dx, ax
 
;Let TX poll the descriptors
;we may got called by tx_timeout which has left
;some unset tx buffers
xor ax, ax
inc ax
set_io 0
set_io MTPR
out dx, ax
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
DEBUGF 1,"Reset ok\n"
xor eax, eax
ret
 
 
 
align 4
init_txbufs:
 
DEBUGF 1,"Init TxBufs\n"
 
lea esi, [device.tx_ring]
lea eax, [device.tx_ring + x_head.sizeof]
GetRealAddr
mov ecx, TX_RING_SIZE
 
.next_desc:
mov [esi + x_head.ndesc], eax
mov [esi + x_head.skb_ptr], 0
mov [esi + x_head.status], DSC_OWNER_MAC
 
add eax, x_head.sizeof
add esi, x_head.sizeof
 
dec ecx
jnz .next_desc
 
lea eax, [device.tx_ring]
GetRealAddr
mov [device.tx_ring + x_head.sizeof*(TX_RING_SIZE - 1) + x_head.ndesc], eax
 
ret
 
 
 
align 4
init_rxbufs:
 
DEBUGF 1,"Init RxBufs\n"
 
lea esi, [device.rx_ring]
lea eax, [device.rx_ring + x_head.sizeof]
GetRealAddr
mov edx, eax
mov ecx, RX_RING_SIZE
 
.next_desc:
mov [esi + x_head.ndesc], edx
 
push esi ecx
stdcall KernelAlloc, MAX_BUF_SIZE
pop ecx esi
 
mov [esi + x_head.skb_ptr], eax
GetRealAddr
mov [esi + x_head.buf], eax
mov [esi + x_head.status], DSC_OWNER_MAC
 
add edx, x_head.sizeof
add esi, x_head.sizeof
 
dec ecx
jnz .next_desc
 
; complete the ring by linking the last to the first
 
lea eax, [device.rx_ring]
GetRealAddr
mov [device.rx_ring + x_head.sizeof*(RX_RING_SIZE - 1) + x_head.ndesc], eax
 
ret
 
 
 
align 4
phy_mode_chk:
 
DEBUGF 1,"Checking PHY mode\n"
 
; PHY Link Status Check
movzx eax, [device.phy_addr]
stdcall phy_read, eax, 1
test eax, 0x4
jz .ret_0x8000
 
; PHY Chip Auto-Negotiation Status
movzx eax, [device.phy_addr]
stdcall phy_read, eax, 1
test eax, 0x0020
jnz .auto_nego
 
; Force Mode
movzx eax, [device.phy_addr]
stdcall phy_read, eax, 0
test eax, 0x100
jnz .ret_0x8000
 
.auto_nego:
; Auto Negotiation Mode
movzx eax, [device.phy_addr]
stdcall phy_read, eax, 5
mov ecx, eax
movzx eax, [device.phy_addr]
stdcall phy_read, eax, 4
and eax, ecx
test eax, 0x140
jnz .ret_0x8000
 
xor eax, eax
ret
 
.ret_0x8000:
mov eax, 0x8000
ret
 
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
transmit:
DEBUGF 2,"\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
DEBUGF 2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
 
cmp dword [esp+8], 1514
ja .fail
cmp dword [esp+8], 60
jb .fail
 
movzx edi, [device.cur_tx]
shl edi, 5
add edi, ebx
add edi, device.tx_ring - ebx
 
DEBUGF 2,"TX buffer status: 0x%x\n", [edi + x_head.status]:4
 
test [edi + x_head.status], DSC_OWNER_MAC ; check if buffer is available
jnz .wait_to_send
 
.do_send:
 
DEBUGF 2,"Sending now\n"
 
mov eax, [esp+4]
mov [edi + x_head.skb_ptr], eax
GetRealAddr
mov [edi + x_head.buf], eax
mov ecx, [esp+8]
mov [edi + x_head.len], cx
mov [edi + x_head.status], DSC_OWNER_MAC
 
; Trigger the MAC to check the TX descriptor
mov ax, 0x01
set_io 0
set_io MTPR
out dx, ax
 
inc [device.cur_tx]
and [device.cur_tx], TX_RING_SIZE - 1
xor eax, eax
 
; Update stats
inc [device.packets_tx]
mov eax, [esp+8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
ret 8
 
.wait_to_send:
 
DEBUGF 2,"Waiting for TX buffer\n"
 
call GetTimerTicks ; returns in eax
lea edx, [eax + 100]
.l2:
test [edi + x_head.status], DSC_OWNER_MAC
jz .do_send
mov esi, 10
call Sleep
call GetTimerTicks
cmp edx, eax
jb .l2
 
DEBUGF 1,"Send timeout\n"
xor eax, eax
dec eax
.fail:
DEBUGF 1,"Send failed\n"
ret 8
 
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_handler:
 
DEBUGF 1,"\n%s int\n", my_service
 
; Find pointer of device wich made IRQ occur
 
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
set_io 0
set_io MISR
in ax, dx
out dx, ax ; send it back to ACK
test ax, ax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing: ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
ret
 
; At this point, test for all possible reasons, and handle accordingly
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x ", ebx, ax
 
push ax
 
test word [esp], RX_FINISH
jz .no_RX
 
push ebx
.more_RX:
pop ebx
 
; Find the current RX descriptor
 
movzx edx, [device.cur_rx]
shl edx, 5
lea edx, [device.rx_ring + edx]
 
; Check the descriptor status
 
mov cx, [edx + x_head.status]
test cx, DSC_OWNER_MAC
jnz .no_RX
 
DEBUGF 2,"packet status=0x%x\n", cx
 
test cx, DSC_RX_ERR ; Global error status set
jnz .no_RX
 
; Packet successfully received
 
movzx ecx, [edx + x_head.len]
and ecx, 0xFFF
sub ecx, 4 ; Do not count the CRC
 
; Update stats
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
inc dword [device.packets_rx]
 
; Push packet size and pointer, kernel will need it..
 
push ebx
push .more_RX
 
push ecx
push [edx + x_head.skb_ptr]
 
DEBUGF 2,"packet ptr=0x%x\n", [edx + x_head.skb_ptr]
 
; reset the RX descriptor
 
push edx
stdcall KernelAlloc, MAX_BUF_SIZE
pop edx
mov [edx + x_head.skb_ptr], eax
GetRealAddr
mov [edx + x_head.buf], eax
mov [edx + x_head.status], DSC_OWNER_MAC
 
; Use next descriptor next time
 
inc [device.cur_rx]
and [device.cur_rx], RX_RING_SIZE - 1
 
; At last, send packet to kernel
 
jmp Eth_input
 
 
.no_RX:
 
test word [esp], TX_FINISH
jz .no_TX
 
.loop_tx:
movzx edi, [device.last_tx]
shl edi, 5
lea edi, [device.tx_ring + edi]
 
test [edi + x_head.status], DSC_OWNER_MAC
jnz .no_TX
 
cmp [edi + x_head.skb_ptr], 0
je .no_TX
 
DEBUGF 2,"Freeing buffer 0x%x\n", [edi + x_head.skb_ptr]
 
push [edi + x_head.skb_ptr]
mov [edi + x_head.skb_ptr], 0
call KernelFree
 
inc [device.last_tx]
and [device.last_tx], TX_RING_SIZE - 1
 
jmp .loop_tx
 
.no_TX:
pop ax
ret
 
 
 
 
align 4
init_mac_regs:
 
DEBUGF 2,"initializing MAC regs\n"
 
; MAC operation register
mov ax, 1
set_io 0
set_io MCR1
out dx, ax
; Reset MAC
mov ax, 2
set_io MAC_SM
out dx, ax
; Reset internal state machine
xor ax, ax
out dx, ax
mov esi, 5
stdcall Sleep
 
call read_mac
 
ret
 
 
 
 
; Read a word data from PHY Chip
 
align 4
proc phy_read stdcall, phy_addr:dword, reg:dword
 
DEBUGF 2,"PHY read, addr=0x%x reg=0x%x\n", [phy_addr]:8, [reg]:8
 
mov eax, [phy_addr]
shl eax, 8
add eax, [reg]
add eax, MDIO_READ
set_io 0
set_io MMDIO
out dx, ax
 
;Wait for the read bit to be cleared.
mov ecx, 2048 ;limit
.read:
in ax, dx
test ax, MDIO_READ
jz @f
dec ecx
jnz .read
@@:
 
set_io MMRD
in ax, dx
and eax, 0xFFFF
 
DEBUGF 2,"PHY read, val=0x%x\n", eax:4
 
ret
 
endp
 
 
 
 
; Write a word data to PHY Chip
 
align 4
proc phy_write stdcall, phy_addr:dword, reg:dword, val:dword
 
DEBUGF 2,"PHY write, addr=0x%x reg=0x%x val=0x%x\n", [phy_addr]:8, [reg]:8, [val]:8
 
mov eax, [val]
set_io 0
set_io MMWD
out dx, ax
 
;Write the command to the MDIO bus
 
mov eax, [phy_addr]
shl eax, 8
add eax, [reg]
add eax, MDIO_WRITE
set_io MMDIO
out dx, ax
 
;Wait for the write bit to be cleared.
mov ecx, 2048 ;limit
.write:
in ax, dx
test ax, MDIO_WRITE
jz @f
dec ecx
jnz .write
@@:
 
DEBUGF 2,"PHY write ok\n"
 
ret
endp
 
 
 
align 4
read_mac:
 
DEBUGF 2,"Reading MAC: "
 
mov cx, 3
lea edi, [device.mac]
set_io 0
set_io MID_0L
.mac:
in ax, dx
stosw
inc dx
inc dx
dec cx
jnz .mac
 
DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[edi-6]:2, [edi-5]:2, [edi-4]:2, [edi-3]:2, [edi-2]:2, [edi-1]:2
 
ret
 
 
 
 
; End of code
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
align 4 ; Place all initialised data here
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'R6040',0 ; max 16 chars include zero
 
include_debug_strings ; All data wich FDO uses will be included here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
/kernel/branches/net/drivers/RTL8029.asm
0,0 → 1,1196
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; RTL8029/ne2000 driver for KolibriOS ;;
;; ;;
;; based on RTL8029.asm driver for menuetos ;;
;; and realtek8029.asm for SolarOS by Eugen Brasoveanu ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; with help from CleverMouse ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.io_addr dd ?
.irq_line db ?
.pci_bus dd ?
.pci_dev dd ?
 
.flags db ?
.vendor db ?
 
.memsize db ?
.rx_start db ?
.tx_start db ?
.bmem dd ?
.rmem dd ?
 
.size = $ - device
 
end virtual
 
 
public START
public service_proc
public version
 
P0_COMMAND = 0x00
P0_PSTART = 0x01
P0_PSTOP = 0x02
P0_BOUND = 0x03
P0_TSR = 0x04
P0_TPSR = 0x04
P0_TBCR0 = 0x05
P0_TBCR1 = 0x06
P0_ISR = 0x07
P0_RSAR0 = 0x08
P0_RSAR1 = 0x09
P0_RBCR0 = 0x0A
P0_RBCR1 = 0x0B
P0_RSR = 0x0C
P0_RCR = 0x0C
P0_TCR = 0x0D
P0_DCR = 0x0E
P0_IMR = 0x0F
 
P1_COMMAND = 0x00
P1_PAR0 = 0x01
P1_PAR1 = 0x02
P1_PAR2 = 0x03
P1_PAR3 = 0x04
P1_PAR4 = 0x05
P1_PAR5 = 0x06
P1_CURR = 0x07
P1_MAR0 = 0x08
 
CMD_PS0 = 0x00 ; Page 0 select
CMD_PS1 = 0x40 ; Page 1 select
CMD_PS2 = 0x80 ; Page 2 select
CMD_RD2 = 0x20 ; Remote DMA control
CMD_RD1 = 0x10
CMD_RD0 = 0x08
CMD_TXP = 0x04 ; transmit packet
CMD_STA = 0x02 ; start
CMD_STP = 0x01 ; stop
 
CMD_RDMA_READ = 001b shl 3
CMD_RDMA_WRITE = 010b shl 3
CMD_RDMA_SEND_PACKET = 011b shl 3
CMD_RDMA_ABORT = 100b shl 3 ; really is 1xx, Abort/Complete Remote DMA
; RDMA_MASK = 111b shl 3 ; internal, mask
 
RCR_MON = 0x20 ; monitor mode
 
DCR_FT1 = 0x40
DCR_LS = 0x08 ; Loopback select
DCR_WTS = 0x01 ; Word transfer select
 
ISR_PRX = 0x01 ; successful recv
ISR_PTX = 0x02 ; successful xmit
ISR_RXE = 0x04 ; receive error
ISR_TXE = 0x08 ; transmit error
ISR_OVW = 0x10 ; Overflow
ISR_CNT = 0x20 ; Counter overflow
ISR_RDC = 0x40 ; Remote DMA complete
ISR_RST = 0x80 ; reset
 
IRQ_MASK = ISR_PRX ;+ ISR_PTX ;+ ISR_RDC + ISR_PTX + ISR_TXE
 
RSTAT_PRX = 1 shl 0 ; successful recv
RSTAT_CRC = 1 shl 1 ; CRC error
RSTAT_FAE = 1 shl 2 ; Frame alignment error
RSTAT_OVER = 1 shl 3 ; FIFO overrun
 
TXBUF_SIZE = 6
RXBUF_END = 32
PAGE_SIZE = 256
 
ETH_ZLEN = 60
ETH_FRAME_LEN = 1514
 
FLAG_PIO = 1 shl 0
FLAG_16BIT = 1 shl 1
 
VENDOR_NONE = 0
VENDOR_WD = 1
VENDOR_NOVELL = 2
VENDOR_3COM = 3
 
NE_ASIC = 0x10
NE_RESET = 0x0F ; Used to reset card
NE_DATA = 0x00 ; Used to read/write NIC mem
 
MEM_8k = 32
MEM_16k = 64
MEM_32k = 128
 
ISA_MAX_ADDR = 0x400
 
 
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; proc START
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
.entry:
DEBUGF 2,"Registering %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
.fail:
.exit:
xor eax, eax
ret
 
endp
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; proc SERVICE_PROC
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [IOCTL.io_code]
 
;------------------------------------------------------
;---------------
cmp eax, 0 ;SRV_GETVERSION
jne @F ;---------------
 
cmp [IOCTL.out_size], 4
jb .fail
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
;------------------------------------------------------
@@: ;---------
cmp eax, 1 ;SRV_HOOK
jne @F ;---------
 
DEBUGF 2,"Checking if device is already listed..\n"
 
mov eax, [IOCTL.input]
 
cmp [IOCTL.inp_size], 3
jb .fail
cmp byte [eax], 1
je .pci
 
cmp [IOCTL.inp_size], 4
jb .fail
cmp byte [eax], 0
je .isa
 
jmp .fail
 
.pci:
 
; check if the device is already listed
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice_pci
 
mov ax, [eax+1] ; get the pci bus and device numbers
.nextdevice:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
 
.firstdevice_pci:
call create_new_struct
 
mov eax, [IOCTL.input]
movzx ecx, byte[eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte[eax+2]
mov [device.pci_dev], ecx
 
; Now, it's time to find the base io addres of the PCI device
 
PCI_find_io
 
; We've found the io address, find IRQ now
 
PCI_find_irq
 
jmp .hook
 
.isa:
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice_isa
mov al, [eax+3]
movzx edi, word [eax+1]
.nextdevice_isa:
mov ebx, [esi]
cmp edi, [device.io_addr]
jne .maybenext
cmp al, [device.irq_line]
je find_device_num
.maybenext:
add esi, 4
loop .nextdevice_isa
 
 
 
.firstdevice_isa:
call create_new_struct
 
mov eax, [IOCTL.input]
movzx ecx, word [eax+1]
mov [device.io_addr], ecx
mov cl, [eax+3]
mov [device.irq_line], cl
 
.hook:
 
DEBUGF 2,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
 
call probe ; this function will output in eax
test eax, eax
jnz .err ; If an error occured, exit
 
mov eax, [devices]
mov [device_list+4*eax], ebx
inc [devices]
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
cmp eax, -1
jz .err
ret
 
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 1,"Trying to find device number of already registered device\n"
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 1,"Kernel says: %u\n", eax
ret
 
.err:
DEBUGF 1,"Failed, removing device structure\n"
stdcall KernelFree, ebx
 
jmp .fail
 
;------------------------------------------------------
@@:
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
create_new_struct:
 
cmp [devices], MAX_DEVICES
jae .fail
 
allocate_and_clear ebx, device.size, .fail ; Allocate the buffer for device structure
 
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], unload
mov [device.name], my_service
 
ret
 
.fail:
add esp, 4 ; return to caller of 'hook'
or eax, -1
ret
 
find_device_num:
 
DEBUGF 1,"Trying to find device number of already registered device\n"
mov ebx, eax
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 1,"Kernel says: %u\n", eax
ret
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
unload: ; TODO
or eax, -1
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; probe: enables the device and clears the rx buffer
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
probe:
mov [device.vendor], VENDOR_NONE
mov [device.bmem], 0
 
DEBUGF 2,"Trying 16-bit mode\n"
 
mov [device.flags], FLAG_16BIT + FLAG_PIO
mov [device.memsize], MEM_32k
mov [device.tx_start], 64
mov [device.rx_start], TXBUF_SIZE + 64
 
set_io 0
set_io P0_DCR
mov al, DCR_WTS + DCR_FT1 + DCR_LS ; word transfer select +
out dx, al
 
set_io P0_PSTART
mov al, MEM_16k
out dx, al
 
set_io P0_PSTOP
mov al, MEM_32k
out dx, al
 
mov esi, my_service
mov di, 16384
mov cx, 14
call PIO_write
 
mov si, 16384
mov cx, 14
sub esp, 16
mov edi, esp
call PIO_read
 
mov esi, esp
add esp, 16
mov edi, my_service
mov ecx, 13
repe cmpsb
je ep_set_vendor
 
DEBUGF 2,"16-bit mode failed\n"
DEBUGF 2,"Trying 8-bit mode\n"
 
mov [device.flags], FLAG_PIO
mov [device.memsize], MEM_16k
mov [device.tx_start], 32
mov [device.rx_start], TXBUF_SIZE + 32
 
set_io NE_ASIC + NE_RESET
in al, dx
out dx, al
 
in al, 0x84
 
set_io P0_COMMAND
mov al, CMD_RD2 + CMD_STP
out dx, al
 
set_io P0_RCR
mov al, RCR_MON
out dx, al
 
set_io P0_DCR
mov al, DCR_FT1 + DCR_LS
out dx, al
 
set_io P0_PSTART
mov al, MEM_8k
out dx, al
 
set_io P0_PSTOP
mov al, MEM_16k
out dx, al
 
mov esi, my_service
mov di, 8192
mov cx, 14
call PIO_write
 
mov si, 8192
mov cx, 14
sub esp, 16
mov edi, esp
call PIO_read
 
mov esi, my_service
mov edi, esp
add esp, 16
mov ecx, 13
repe cmpsb
je ep_set_vendor
 
DEBUGF 2,"This is not a valid ne2000 device!\n"
or eax, -1
ret
 
 
ep_set_vendor:
 
DEBUGF 2,"Mode ok\n"
 
cmp [device.io_addr], ISA_MAX_ADDR
jbe .isa
 
DEBUGF 2,"Card is using PCI bus\n"
 
mov [device.vendor], VENDOR_NOVELL ;;; FIXME
jmp ep_check_have_vendor
 
.isa:
DEBUGF 2,"Card is using ISA bus\n"
 
mov [device.vendor], VENDOR_NOVELL
 
ep_check_have_vendor:
 
 
mov al, [device.vendor]
cmp al, VENDOR_NONE
; je exit
 
cmp al, VENDOR_3COM
je reset
 
mov eax, [device.bmem]
mov [device.rmem], eax
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; reset: Place the chip into a virgin state
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
reset:
DEBUGF 2,"Resetting device\n"
 
; attach int handler
movzx eax, [device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
 
; Stop card + DMA
set_io 0
; set_io P0_COMMAND
mov al, CMD_PS0 + CMD_RDMA_ABORT + CMD_STP
out dx, al
 
; initialize DCR
set_io P0_DCR
mov al, DCR_FT1 + DCR_LS
test [device.flags], FLAG_16BIT
jz @f
or al, DCR_WTS ; word transfer select
@@:
out dx, al
 
; clear remote bytes count
set_io P0_RBCR0
xor al, al
out dx, al
 
set_io P0_RBCR1
out dx, al
 
; initialize Receive configuration register (until all init is done)
set_io P0_RCR
mov al, 0x20 ; monitor mode
out dx, al
 
; transmit configuration register to monitor mode (until all ini is done)
set_io P0_TCR
mov al, 2 ; internal loopback
out dx, al
 
; clear interupt status
set_io P0_ISR
mov al, 0xff
out dx, al
 
; clear IRQ mask ;;;;; CHECKME ;;;;;
set_io P0_IMR
xor al, al
out dx, al
 
; set transmit pointer
set_io P0_TPSR
mov al, [device.tx_start]
out dx, al
 
; set pagestart pointer
set_io P0_PSTART
mov al, [device.rx_start]
out dx, al
 
; set pagestop pointer
set_io P0_PSTOP
mov al, [device.memsize]
out dx, al
 
; set boundary pointer
set_io P0_BOUND
mov al, [device.memsize]
dec al
out dx, al
 
; set curr pointer
set_io P0_COMMAND
mov al, CMD_PS1 ;+ CMD_RD2 + CMD_STP ; page 1, stop mode
out dx, al
 
set_io P1_CURR
mov al, [device.rx_start]
out dx, al
 
set_io P0_COMMAND
mov al, CMD_PS0 ;+ CMD_RD2 + CMD_STA ; go to page 0, start mode
out dx, al
 
; Read MAC address and set it to registers
call read_mac
push .macret
sub esp, 6
lea esi, [device.mac]
mov edi, esp
movsd
movsw
jmp write_mac
.macret:
 
; set IRQ mask
set_io 0
set_io P0_IMR
mov al, IRQ_MASK
out dx, al
 
; start mode
set_io P0_COMMAND
mov al, CMD_STA
out dx, al
 
; clear transmit control register
set_io P0_TCR
xor al, al ; no loopback
out dx, al
 
; set receive control register ;;;;
set_io P0_RCR
mov al, 4 ; accept broadcast
out dx, al
 
; clear packet/byte counters
xor eax, eax
lea edi, [device.bytes_tx]
mov ecx, 6
rep stosd
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], ETH_FRAME_LEN
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
; Indicate that we have successfully reset the card
xor eax, eax
DEBUGF 2,"Done!\n"
 
ret
 
 
 
;***************************************************************************
; Function
; transmit
; buffer in [esp+4], size in [esp+8], pointer to device struct in ebx
;***************************************************************************
 
align 4
transmit:
 
mov esi, [esp + 4]
mov ecx, [esp + 8]
DEBUGF 2,"Transmitting packet, buffer:%x, size:%u\n",esi, ecx
DEBUGF 2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[esi+0]:2,[esi+1]:2,[esi+2]:2,[esi+3]:2,[esi+4]:2,[esi+5]:2,[esi+6]:2,[esi+7]:2,[esi+8]:2,[esi+9]:2,[esi+10]:2,[esi+11]:2,[esi+13]:2,[esi+12]:2
 
cmp ecx, ETH_FRAME_LEN
ja .err ; packet is too long
cmp ecx, ETH_ZLEN
jb .err ; packet is too short
 
movzx edi, [device.tx_start]
shl edi, 8
push cx
call PIO_write
pop cx
 
set_io 0
; set_io P0_COMMAND
mov al, CMD_PS0 + CMD_RD2 + CMD_STA
out dx, al
 
set_io P0_TPSR
mov al, [device.tx_start]
out dx, al
 
set_io P0_TBCR0
mov al, cl
out dx, al
 
set_io P0_TBCR1
mov al, ch
out dx, al
 
set_io P0_COMMAND
mov al, CMD_PS0 + CMD_TXP + CMD_RD2 + CMD_STA
out dx, al
 
DEBUGF 2," - Packet Sent!\n"
 
inc [device.packets_tx]
mov eax, [esp + 8] ; Get packet size in eax
 
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
stdcall KernelFree, [esp+4]
xor eax, eax
ret 8
 
.err:
DEBUGF 2," - Error!\n"
 
or eax, -1
stdcall KernelFree, [esp+4]
ret 8
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Interrupt handler
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_handler:
 
DEBUGF 1,"\n%s int\n", my_service
 
; find pointer of device wich made INT occur
 
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
set_io 0
; set_io P0_COMMAND
mov al, CMD_PS0
out dx, al
 
set_io P0_ISR
in al, dx
test al, al
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
ret
 
.got_it:
 
DEBUGF 1,"Device=%x status=%x\n", ebx, eax:2
 
push ebx
 
test al, ISR_PRX ; packet received ok ?
jz .no_rx
 
test [device.flags], FLAG_PIO
jz .no_rx ; FIXME: Only PIO mode supported for now
 
;
 
pushd .no_rx
 
; allocate a buffer
 
stdcall KernelAlloc, ETH_FRAME_LEN
test eax, eax
jz .fail_2
pushd 0
push eax
 
; read offset for current packet from device
 
set_io 0
set_io P0_BOUND ; boundary ptr is offset to next packet we need to read.
in al, dx
inc al
 
cmp al, [device.memsize]
jb @f
mov al, [device.rx_start]
@@:
mov ch, al
 
set_io P0_COMMAND
mov al, CMD_PS1
out dx, al
 
set_io P1_CURR
in al, dx ; get current page in cl
mov cl, al
 
set_io P1_COMMAND
mov al, CMD_PS0
out dx, al
 
cmp cl, [device.memsize]
jb @f
mov cl, [device.rx_start]
@@:
 
cmp cl, ch
je .fail
 
movzx esi, ch ; we are using 256 byte pages
shl esi, 8 ; esi now holds the offset for current packet
 
; Get packet header in eax
 
sub esp, 4 ; reserve 4 bytes on stack to put packet header in
mov edi, esp
mov cx, 4
call PIO_read
 
mov ecx, [esp] ; ecx now contains packet header
 
; check if packet is ok
 
test ecx, RSTAT_PRX
jz .fail_3
 
; calculate packet length in ecx
 
shr ecx, 16
sub ecx, 4 ; CRC doesnt count as data byte
mov [esp + 4 + 4], ecx
 
; check if packet size is ok
 
cmp ecx, ETH_ZLEN
jb .fail_3
cmp ecx, ETH_FRAME_LEN
ja .fail_3
 
; update stats
 
DEBUGF 2,"Received %u bytes\n", ecx
 
add dword[device.bytes_rx], ecx
adc dword[device.bytes_rx + 4], 0
inc [device.packets_rx]
 
; update read and write pointers
 
add esi, 4
mov edi, [esp + 4]
 
; now check if we can read all data at once (if we cross the end boundary, we need to wrap back to the beginning)
 
xor eax, eax
mov ah, [device.memsize]
sub eax, esi
cmp ecx, eax ; eax = number of bytes till end of buffer, ecx = bytes we need to read
jbe .no_wrap
 
DEBUGF 2,"WRAP!\n"
 
; Read first part
 
sub ecx, eax
push ecx
mov ecx, eax
 
call PIO_read ; Read the data
 
; update pointers
 
add edi, ecx
pop ecx
 
movzx esi, [device.rx_start]
shl esi, 8
 
; now read second part (or only part)
 
.no_wrap:
call PIO_read ; Read the data
 
; update boundary pointer
 
pop eax
mov al, ah
cmp al, [device.rx_start]
jne @f
mov al, [device.memsize]
@@:
 
set_io 0
set_io P0_BOUND
dec al
out dx, al
 
; now send the data to the kernel
 
jmp Eth_input
 
.fail_3:
add esp, 4
.fail:
add esp, 8
.fail_2:
 
 
.no_rx:
pop ebx
DEBUGF 2,"done\n"
 
set_io 0
set_io P0_ISR
mov al, 0xff
out dx, al
 
ret
 
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Write MAC address ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
write_mac: ; in: mac on stack (6 bytes)
 
DEBUGF 1,"Writing MAC\n"
 
set_io 0
mov al, CMD_PS1; + CMD_RD2 + CMD_STP
out dx, al
 
set_io P1_PAR0
mov esi, esp
mov cx, 6
@@:
lodsb
out dx, al
inc dx
loopw @r
 
add esp, 6
 
; Notice this procedure does not ret, but continues to read_mac instead.
 
;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Read MAC address ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;
 
read_mac:
 
DEBUGF 1,"Reading MAC\n"
 
xor esi, esi
mov cx, 16
sub esp, 16
mov edi, esp
call PIO_read
 
mov esi, esp
add esp, 16
lea edi, [device.mac]
mov ecx, 6
.loop:
movsb
test [device.flags], FLAG_16BIT
jz .8bit
inc esi
.8bit:
loop .loop
 
DEBUGF 1,"MAC=%x-%x-%x-%x-%x-%x\n",\
[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
ret
 
 
;***************************************************************************
;
; PIO_read
;
; Description
; Read a frame from the ethernet card via Programmed I/O
; src in si
; cnt in cx
; dst in edi
;***************************************************************************
PIO_read:
 
DEBUGF 1,"PIO Read from %x to %x, %u bytes ", si, edi, cx
 
; start DMA
set_io 0
; set_io P0_COMMAND
mov al, CMD_RD2 + CMD_STA
out dx, al
 
; set length of data we're interested in
set_io P0_RBCR0
mov al, cl
out dx, al
 
set_io P0_RBCR1
mov al, ch
out dx, al
 
; set offset of what we want to read
set_io P0_RSAR0
mov ax, si
out dx, al
 
set_io P0_RSAR1
shr ax, 8
out dx, al
 
; start DMA read
set_io P0_COMMAND
mov al, CMD_RD0 + CMD_STA
out dx, al
 
set_io NE_ASIC
 
test [device.flags], FLAG_16BIT
jz .8bits
 
DEBUGF 1,"(16-bit mode)\n"
 
shr cx, 1 ; note that if the number was odd, carry flag will be set
pushf
 
.16bits:
in ax, dx
stosw
loopw .16bits
 
inc cx
popf
jnc .done
jmp .8bits_
 
.8bits:
DEBUGF 1,"(8-bit mode)\n"
 
.8bits_:
in al, dx
stosb
loopw .8bits_
 
 
.done:
; set_io 0
; set_io P0_ISR
;
; .dmawait: ; Wait for Remote DMA Complete
; in al, dx
; test al, ISR_RDC
; jz .dmawait
; and al, not ISR_RDC
; out dx, al ; clear the bit
 
ret
 
 
 
 
;***************************************************************************
;
; PIO_write
;
; Description
; writes a frame to the ethernet card via Programmed I/O
; dst in di
; cnt in cx
; src in esi
;***************************************************************************
PIO_write:
 
DEBUGF 1,"Eth PIO Write from %x to %x, %u bytes ", esi, di, cx
 
set_io 0
; set_io P0_COMMAND
mov al, CMD_RD2 + CMD_STA
out dx, al
 
set_io P0_ISR
mov al, ISR_RDC
out dx, al
 
set_io P0_RBCR0
mov al, cl
out dx, al
 
set_io P0_RBCR1
mov al, ch
out dx, al
 
mov ax, di
set_io P0_RSAR0
out dx, al
shr ax, 8
set_io P0_RSAR1
out dx, al
 
set_io P0_COMMAND
mov al, CMD_RD1 + CMD_STA
out dx, al
 
set_io NE_ASIC
test [device.flags], FLAG_16BIT
jz .8_bit
 
DEBUGF 1,"(16-bit mode)\n"
 
shr cx, 1 ; note that if the number was odd, carry flag will be set
pushf ; save the flags for later
 
.16bit:
lodsw
out dx, ax
loopw .16bit
 
popf
jnc .done
inc cx
jmp .8_bit_
 
.8_bit:
 
DEBUGF 1,"(8-bit mode)\n"
 
.8_bit_:
lodsb
out dx, al
loopw .8_bit_
 
.done:
; set_io 0
; set_io P0_ISR
; .dmawait: ; Wait for Remote DMA Complete
; in al, dx
; test al, ISR_RDC
; jz .dmawait
; and al, not ISR_RDC
; out dx, al ; clear the bit
 
ret
 
 
 
;all initialized data place here
align 4
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'RTL8029/ne2000',0 ;max 16 chars include zero
 
;device_1 db 'Realtek 8029',0
;device_2 db 'Realtek 8019',0
;device_3 db 'Realtek 8019AS',0
;device_4 db 'ne2000',0
;device_5 db 'DP8390',0
 
include_debug_strings
 
section '.data' data readable writable align 16 ;place all uninitialized data place here
 
device_list rd MAX_DEVICES
 
 
 
 
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/drivers/RTL8169.asm
0,0 → 1,1315
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; RTL8169 driver for KolibriOS ;;
;; ;;
;; Copyright 2007 mike.dld, ;;
;; mike.dld@gmail.com ;;
;; ;;
;; port to net branch by hidnplayr ;;
;; ;;
;; References: ;;
;; r8169.c - linux driver (etherboot project) ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
NUM_TX_DESC = 4
NUM_RX_DESC = 4
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
 
public START
public service_proc
public version
 
 
REG_MAC0 = 0x0 ; Ethernet hardware address
REG_MAR0 = 0x8 ; Multicast filter
REG_TxDescStartAddr = 0x20
REG_TxHDescStartAddr = 0x28
REG_FLASH = 0x30
REG_ERSR = 0x36
REG_ChipCmd = 0x37
REG_TxPoll = 0x38
REG_IntrMask = 0x3C
REG_IntrStatus = 0x3E
REG_TxConfig = 0x40
REG_RxConfig = 0x44
REG_RxMissed = 0x4C
REG_Cfg9346 = 0x50
REG_Config0 = 0x51
REG_Config1 = 0x52
REG_Config2 = 0x53
REG_Config3 = 0x54
REG_Config4 = 0x55
REG_Config5 = 0x56
REG_MultiIntr = 0x5C
REG_PHYAR = 0x60
REG_TBICSR = 0x64
REG_TBI_ANAR = 0x68
REG_TBI_LPAR = 0x6A
REG_PHYstatus = 0x6C
REG_RxMaxSize = 0xDA
REG_CPlusCmd = 0xE0
REG_RxDescStartAddr = 0xE4
REG_ETThReg = 0xEC
REG_FuncEvent = 0xF0
REG_FuncEventMask = 0xF4
REG_FuncPresetState = 0xF8
REG_FuncForceEvent = 0xFC
 
; InterruptStatusBits
ISB_SYSErr = 0x8000
ISB_PCSTimeout = 0x4000
ISB_SWInt = 0x0100
ISB_TxDescUnavail = 0x80
ISB_RxFIFOOver = 0x40
ISB_LinkChg = 0x20
ISB_RxOverflow = 0x10
ISB_TxErr = 0x08
ISB_TxOK = 0x04
ISB_RxErr = 0x02
ISB_RxOK = 0x01
 
; RxStatusDesc
SD_RxRES = 0x00200000
SD_RxCRC = 0x00080000
SD_RxRUNT = 0x00100000
SD_RxRWT = 0x00400000
 
; ChipCmdBits
CMD_Reset = 0x10
CMD_RxEnb = 0x08
CMD_TxEnb = 0x04
CMD_RxBufEmpty = 0x01
 
; Cfg9346Bits
CFG_9346_Lock = 0x00
CFG_9346_Unlock = 0xC0
 
; rx_mode_bits
RXM_AcceptErr = 0x20
RXM_AcceptRunt = 0x10
RXM_AcceptBroadcast = 0x08
RXM_AcceptMulticast = 0x04
RXM_AcceptMyPhys = 0x02
RXM_AcceptAllPhys = 0x01
 
; RxConfigBits
RXC_FIFOShift = 13
RXC_DMAShift = 8
 
; TxConfigBits
TXC_InterFrameGapShift = 24
TXC_DMAShift = 8 ; DMA burst value (0-7) is shift this many bits
 
; PHYstatus
PHYS_TBI_Enable = 0x80
PHYS_TxFlowCtrl = 0x40
PHYS_RxFlowCtrl = 0x20
PHYS_1000bpsF = 0x10
PHYS_100bps = 0x08
PHYS_10bps = 0x04
PHYS_LinkStatus = 0x02
PHYS_FullDup = 0x01
 
; GIGABIT_PHY_registers
PHY_CTRL_REG = 0
PHY_STAT_REG = 1
PHY_AUTO_NEGO_REG = 4
PHY_1000_CTRL_REG = 9
 
; GIGABIT_PHY_REG_BIT
PHY_Restart_Auto_Nego = 0x0200
PHY_Enable_Auto_Nego = 0x1000
 
; PHY_STAT_REG = 1
PHY_Auto_Neco_Comp = 0x0020
 
; PHY_AUTO_NEGO_REG = 4
PHY_Cap_10_Half = 0x0020
PHY_Cap_10_Full = 0x0040
PHY_Cap_100_Half = 0x0080
PHY_Cap_100_Full = 0x0100
 
; PHY_1000_CTRL_REG = 9
PHY_Cap_1000_Full = 0x0200
PHY_Cap_1000_Half = 0x0100
 
PHY_Cap_PAUSE = 0x0400
PHY_Cap_ASYM_PAUSE = 0x0800
 
PHY_Cap_Null = 0x0
 
; _MediaType
MT_10_Half = 0x01
MT_10_Full = 0x02
MT_100_Half = 0x04
MT_100_Full = 0x08
MT_1000_Full = 0x10
 
; _TBICSRBit
TBI_LinkOK = 0x02000000
 
; _DescStatusBit
DSB_OWNbit = 0x80000000
DSB_EORbit = 0x40000000
DSB_FSbit = 0x20000000
DSB_LSbit = 0x10000000
 
RX_BUF_SIZE = 1536 ; Rx Buffer size
 
; max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4)
MAX_ETH_FRAME_SIZE = 1536
 
TX_FIFO_THRESH = 256 ; In bytes
 
RX_FIFO_THRESH = 7 ; 7 means NO threshold, Rx buffer level before first PCI xfer
RX_DMA_BURST = 7 ; Maximum PCI burst, '6' is 1024
TX_DMA_BURST = 7 ; Maximum PCI burst, '6' is 1024
ETTh = 0x3F ; 0x3F means NO threshold
 
EarlyTxThld = 0x3F ; 0x3F means NO early transmit
RxPacketMaxSize = 0x0800 ; Maximum size supported is 16K-1
InterFrameGap = 0x03 ; 3 means InterFrameGap = the shortest one
 
HZ = 1000
 
RTL_MIN_IO_SIZE = 0x80
TX_TIMEOUT = (6*HZ)
 
TIMER_EXPIRE_TIME = 100
 
ETH_HDR_LEN = 14
DEFAULT_MTU = 1500
DEFAULT_RX_BUF_LEN = 1536
 
 
;ifdef JUMBO_FRAME_SUPPORT
; MAX_JUMBO_FRAME_MTU = 10000
; MAX_RX_SKBDATA_SIZE = (MAX_JUMBO_FRAME_MTU + ETH_HDR_LEN )
;else
MAX_RX_SKBDATA_SIZE = 1600
;end if
 
MCFG_METHOD_01 = 0x01
MCFG_METHOD_02 = 0x02
MCFG_METHOD_03 = 0x03
MCFG_METHOD_04 = 0x04
MCFG_METHOD_05 = 0x05
MCFG_METHOD_11 = 0x0b
MCFG_METHOD_12 = 0x0c
MCFG_METHOD_13 = 0x0d
MCFG_METHOD_14 = 0x0e
MCFG_METHOD_15 = 0x0f
 
PCFG_METHOD_1 = 0x01 ; PHY Reg 0x03 bit0-3 == 0x0000
PCFG_METHOD_2 = 0x02 ; PHY Reg 0x03 bit0-3 == 0x0001
PCFG_METHOD_3 = 0x03 ; PHY Reg 0x03 bit0-3 == 0x0002
 
virtual at 0
tx_desc:
.status dd ?
.vlan_tag dd ?
.buf_addr dq ?
.size = $
rb (NUM_TX_DESC-1)*tx_desc.size
.buf_soft_addr dd ?
end virtual
 
virtual at 0
rx_desc:
.status dd ?
.vlan_tag dd ?
.buf_addr dq ?
.size = $
rb (NUM_RX_DESC-1)*rx_desc.size
.buf_soft_addr dd ?
end virtual
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.io_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
 
rb 256-(($ - device) and 255) ; align 256
.tx_ring rb NUM_TX_DESC * tx_desc.size * 2
 
rb 256-(($ - device) and 255) ; align 256
.rx_ring rb NUM_RX_DESC * rx_desc.size * 2
 
tpc:
.mmio_addr dd ? ; memory map physical address
.chipset dd ?
.pcfg dd ?
.mcfg dd ?
.cur_rx dd ? ; Index into the Rx descriptor buffer of next Rx pkt
.cur_tx dd ? ; Index into the Tx descriptor buffer of next Rx pkt
.TxDescArrays dd ? ; Index of Tx Descriptor buffer
.RxDescArrays dd ? ; Index of Rx Descriptor buffer
.TxDescArray dd ? ; Index of 256-alignment Tx Descriptor buffer
.RxDescArray dd ? ; Index of 256-alignment Rx Descriptor buffer
 
device_size = $ - device
 
end virtual
 
intr_mask = ISB_LinkChg or ISB_RxOverflow or ISB_RxFIFOOver or ISB_TxErr or ISB_TxOK or ISB_RxErr or ISB_RxOK
rx_config = (RX_FIFO_THRESH shl RXC_FIFOShift) or (RX_DMA_BURST shl RXC_DMAShift) or 0x0000000E
 
 
macro udelay msec {
 
push esi
mov esi, msec
call Sleep
pop esi
 
}
 
macro WRITE_GMII_REG RegAddr, value {
 
set_io REG_PHYAR
if value eq ax
and eax, 0x0000ffff
or eax, 0x80000000 + (RegAddr shl 16)
else
mov eax, 0x80000000 + (RegAddr shl 16) + value
end if
out dx, eax
 
call PHY_WAIT_WRITE
}
 
macro READ_GMII_REG RegAddr {
 
local .error, .done
 
set_io REG_PHYAR
mov eax, RegAddr shl 16
out dx, eax
 
call PHY_WAIT_READ
jz .error
 
in eax, dx
and eax, 0xFFFF
jmp .done
 
.error:
or eax, -1
.done:
}
 
align 4
PHY_WAIT_READ: ; io addr must already be set to REG_PHYAR
 
udelay 1 ;;;1000
 
push ecx
mov ecx, 2000
; Check if the RTL8169 has completed writing/reading to the specified MII register
@@:
in eax, dx
test eax, 0x80000000
jnz .exit
udelay 1 ;;;100
loop @b
.exit:
pop ecx
ret
 
align 4
PHY_WAIT_WRITE: ; io addr must already be set to REG_PHYAR
 
udelay 1 ;;;1000
 
push ecx
mov ecx, 2000
; Check if the RTL8169 has completed writing/reading to the specified MII register
@@:
in eax, dx
test eax, 0x80000000
jz .exit
udelay 1 ;;;100
loop @b
.exit:
pop ecx
ret
 
 
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
 
.entry:
 
DEBUGF 2,"Loading %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
 
.fail:
.exit:
xor eax, eax
ret
 
endp
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne @F
 
cmp [IOCTL.out_size], 4
jb .fail
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
 
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
 
mov eax, [IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet
 
; check if the device is already listed
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax , [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
 
 
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, device_size, .fail ; Allocate memory to put the device structure in
 
; Fill in the direct call addresses into the struct
 
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], unload
mov [device.name], my_service
 
; save the pci bus and device numbers
 
mov eax, [IOCTL.input]
movzx ecx, byte[eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte[eax+2]
mov [device.pci_dev], ecx
 
; Now, it's time to find the base io addres of the PCI device
 
PCI_find_io
mov [tpc.mmio_addr], eax ; CHECKME
 
; We've found the io address, find IRQ now
 
PCI_find_irq
 
DEBUGF 2,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:8
 
; Ok, the eth_device structure is ready, let's probe the device
; Because initialization fires IRQ, IRQ handler must be aware of this device
mov eax, [devices] ; Add the device structure to our device list
mov [device_list + 4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
 
call probe ; this function will output in eax
test eax, eax
jnz .err2 ; If an error occured, exit
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
cmp eax, -1
je .destroy
 
ret
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 2,"Trying to find device number of already registered device\n"
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 2,"Kernel says: %u\n", eax
ret
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
; todo: reset device into virgin state
 
.err2:
dec [devices]
.err:
DEBUGF 2,"removing device structure\n"
stdcall KernelFree, ebx
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
align 4
unload:
 
ret
 
 
align 4
init_board:
 
DEBUGF 1,"init_board\n"
 
PCI_make_bus_master
 
; Soft reset the chip
set_io 0
set_io REG_ChipCmd
mov al, CMD_Reset
out dx, al
 
; Check that the chip has finished the reset
mov ecx, 1000
set_io REG_ChipCmd
@@: in al, dx
test al, CMD_Reset
jz @f
udelay 10
loop @b
@@:
; identify config method
set_io REG_TxConfig
in eax, dx
and eax, 0x7c800000
DEBUGF 1,"init_board: TxConfig & 0x7c800000 = 0x%x\n", eax
mov esi, mac_info-8
@@: add esi, 8
mov ecx, eax
and ecx, [esi]
cmp ecx, [esi]
jne @b
mov eax, [esi+4]
mov [tpc.mcfg], eax
 
mov [tpc.pcfg], PCFG_METHOD_3
READ_GMII_REG 3
and al, 0x0f
or al, al
jnz @f
mov [tpc.pcfg], PCFG_METHOD_1
jmp .pconf
@@: dec al
jnz .pconf
mov [tpc.pcfg], PCFG_METHOD_2
.pconf:
 
; identify chip attached to board
mov ecx, 10
mov eax, [tpc.mcfg]
@@: dec ecx
js @f
cmp eax, [rtl_chip_info + ecx*8]
jne @b
mov [tpc.chipset], ecx
jmp .match
@@:
; if unknown chip, assume array element #0, original RTL-8169 in this case
DEBUGF 1,"init_board: PCI device: unknown chip version, assuming RTL-8169\n"
set_io REG_TxConfig
in eax, dx
DEBUGF 1,"init_board: PCI device: TxConfig = 0x%x\n", eax
 
mov [tpc.chipset], 0
 
xor eax, eax
inc eax
ret
 
.match:
DEBUGF 1,"init_board: chipset=%u\n", ecx
xor eax,eax
ret
 
 
 
;***************************************************************************
; Function
; probe
; Description
; Searches for an ethernet card, enables it and clears the rx buffer
; If a card was found, it enables the ethernet -> TCPIP link
; Destroyed registers
; eax, ebx, ecx, edx
;
;***************************************************************************
align 4
probe:
 
DEBUGF 1,"probe\n"
 
call init_board
call read_mac
call PHY_config
 
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n"
set_io 0
set_io 0x82
mov al, 0x01
out dx, al
cmp [tpc.mcfg], MCFG_METHOD_03
jae @f
; DEBUGF 1,"K : Set PCI Latency=0x40\n"
; stdcall pci_write_config_byte,PCI_LATENCY_TIMER,0x40
@@:
cmp [tpc.mcfg], MCFG_METHOD_02
jne @f
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n"
set_io 0x82
mov al, 0x01
out dx, al
; DEBUGF 1,"K : Set PHY Reg 0x0bh = 0x00h\n"
WRITE_GMII_REG 0x0b, 0x0000 ; w 0x0b 15 0 0
@@:
; if TBI is not enabled
set_io 0
set_io REG_PHYstatus
in al, dx
test al, PHYS_TBI_Enable
jz .tbi_dis
READ_GMII_REG PHY_AUTO_NEGO_REG
 
; enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged
and eax, 0x0C1F
or eax, PHY_Cap_10_Half or PHY_Cap_10_Full or PHY_Cap_100_Half or PHY_Cap_100_Full
WRITE_GMII_REG PHY_AUTO_NEGO_REG, ax
 
; enable 1000 Full Mode
WRITE_GMII_REG PHY_1000_CTRL_REG, PHY_Cap_1000_Full or PHY_Cap_1000_Half ; rtl8168
 
; Enable auto-negotiation and restart auto-nigotiation
WRITE_GMII_REG PHY_CTRL_REG, PHY_Enable_Auto_Nego or PHY_Restart_Auto_Nego
 
udelay 100
mov ecx, 10000
; wait for auto-negotiation process
@@: dec ecx
jz @f
set_io 0
READ_GMII_REG PHY_STAT_REG
udelay 100
test eax, PHY_Auto_Neco_Comp
jz @b
set_io REG_PHYstatus
in al, dx
jmp @f
.tbi_dis:
udelay 100
@@:
 
 
;***************************************************************************
; Function
; rt8169_reset
; Description
; Place the chip (ie, the ethernet card) into a virgin state
; Destroyed registers
; eax, ebx, ecx, edx
;
;***************************************************************************
align 4
reset:
 
DEBUGF 1,"reset\n"
 
lea eax, [device.tx_ring]
mov [tpc.TxDescArrays], eax
mov [tpc.TxDescArray], eax
 
lea eax, [device.rx_ring]
mov [tpc.RxDescArrays], eax
mov [tpc.RxDescArray], eax
 
call init_ring
call hw_start
 
; clear packet/byte counters
 
xor eax, eax
lea edi, [device.bytes_tx]
mov ecx, 6
rep stosd
 
mov [device.mtu], 1500
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
xor eax, eax
ret
 
 
 
 
 
align 4
PHY_config:
 
DEBUGF 1,"hw_PHY_config: priv.mcfg=%d, priv.pcfg=%d\n",[tpc.mcfg],[tpc.pcfg]
 
cmp [tpc.mcfg], MCFG_METHOD_04
jne .not_4
set_io 0
; WRITE_GMII_REG 0x1F, 0x0001
; WRITE_GMII_REG 0x1b, 0x841e
; WRITE_GMII_REG 0x0e, 0x7bfb
; WRITE_GMII_REG 0x09, 0x273a
WRITE_GMII_REG 0x1F, 0x0002
WRITE_GMII_REG 0x01, 0x90D0
WRITE_GMII_REG 0x1F, 0x0000
jmp .exit
.not_4:
cmp [tpc.mcfg], MCFG_METHOD_02
je @f
cmp [tpc.mcfg], MCFG_METHOD_03
jne .not_2_or_3
@@:
set_io 0
WRITE_GMII_REG 0x1F, 0x0001
WRITE_GMII_REG 0x15, 0x1000
WRITE_GMII_REG 0x18, 0x65C7
WRITE_GMII_REG 0x04, 0x0000
WRITE_GMII_REG 0x03, 0x00A1
WRITE_GMII_REG 0x02, 0x0008
WRITE_GMII_REG 0x01, 0x1020
WRITE_GMII_REG 0x00, 0x1000
WRITE_GMII_REG 0x04, 0x0800
WRITE_GMII_REG 0x04, 0x0000
WRITE_GMII_REG 0x04, 0x7000
WRITE_GMII_REG 0x03, 0xFF41
WRITE_GMII_REG 0x02, 0xDE60
WRITE_GMII_REG 0x01, 0x0140
WRITE_GMII_REG 0x00, 0x0077
WRITE_GMII_REG 0x04, 0x7800
WRITE_GMII_REG 0x04, 0x7000
WRITE_GMII_REG 0x04, 0xA000
WRITE_GMII_REG 0x03, 0xDF01
WRITE_GMII_REG 0x02, 0xDF20
WRITE_GMII_REG 0x01, 0xFF95
WRITE_GMII_REG 0x00, 0xFA00
WRITE_GMII_REG 0x04, 0xA800
WRITE_GMII_REG 0x04, 0xA000
WRITE_GMII_REG 0x04, 0xB000
WRITE_GMII_REG 0x03, 0xFF41
WRITE_GMII_REG 0x02, 0xDE20
WRITE_GMII_REG 0x01, 0x0140
WRITE_GMII_REG 0x00, 0x00BB
WRITE_GMII_REG 0x04, 0xB800
WRITE_GMII_REG 0x04, 0xB000
WRITE_GMII_REG 0x04, 0xF000
WRITE_GMII_REG 0x03, 0xDF01
WRITE_GMII_REG 0x02, 0xDF20
WRITE_GMII_REG 0x01, 0xFF95
WRITE_GMII_REG 0x00, 0xBF00
WRITE_GMII_REG 0x04, 0xF800
WRITE_GMII_REG 0x04, 0xF000
WRITE_GMII_REG 0x04, 0x0000
WRITE_GMII_REG 0x1F, 0x0000
WRITE_GMII_REG 0x0B, 0x0000
jmp .exit
.not_2_or_3:
DEBUGF 1,"tpc.mcfg=%d, discard hw PHY config\n", [tpc.mcfg]
.exit:
ret
 
 
 
align 4
set_rx_mode:
 
DEBUGF 1,"set_rx_mode\n"
 
; IFF_ALLMULTI
; Too many to filter perfectly -- accept all multicasts
set_io 0
set_io REG_RxConfig
in eax, dx
mov ecx, [tpc.chipset]
and eax, [rtl_chip_info + ecx * 8 + 4] ; RxConfigMask
or eax, rx_config or (RXM_AcceptBroadcast or RXM_AcceptMulticast or RXM_AcceptMyPhys)
out dx, eax
 
; Multicast hash filter
set_io REG_MAR0 + 0
or eax, -1
out dx, eax
set_io REG_MAR0 + 4
out dx, eax
 
ret
 
 
align 4
init_ring:
 
DEBUGF 1,"init_ring\n"
 
xor eax, eax
mov [tpc.cur_rx], eax
mov [tpc.cur_tx], eax
 
lea edi, [device.tx_ring]
mov ecx, (NUM_TX_DESC * tx_desc.size) / 4
rep stosd
 
lea edi, [device.rx_ring]
mov ecx, (NUM_RX_DESC * rx_desc.size) / 4
rep stosd
 
mov edi, [tpc.RxDescArray]
mov ecx, NUM_RX_DESC
.loop:
push ecx
stdcall KernelAlloc, RX_BUF_SIZE
mov [edi + rx_desc.buf_soft_addr], eax
call GetPgAddr
mov dword [edi + rx_desc.buf_addr], eax
mov [edi + rx_desc.status], DSB_OWNbit or RX_BUF_SIZE
add edi, rx_desc.size
pop ecx
loop .loop
or [edi - rx_desc.size + rx_desc.status], DSB_EORbit
 
ret
 
 
align 4
hw_start:
 
DEBUGF 1,"hw_start\n"
 
; attach int handler
movzx eax, [device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
 
; Soft reset the chip
set_io 0
set_io REG_ChipCmd
mov al, CMD_Reset
out dx, al
 
DEBUGF 1,"Waiting for chip to reset... "
; Check that the chip has finished the reset
mov ecx, 1000
set_io REG_ChipCmd
@@: in al, dx
test al, CMD_Reset
jz @f
udelay 10
loop @b
@@:
DEBUGF 1,"done!\n"
 
set_io REG_Cfg9346
mov al, CFG_9346_Unlock
out dx, al
 
set_io REG_ChipCmd
mov al, CMD_TxEnb or CMD_RxEnb
out dx, al
 
set_io REG_ETThReg
mov al, ETTh
out dx, al
 
; For gigabit rtl8169
set_io REG_RxMaxSize
mov ax, RxPacketMaxSize
out dx, ax
 
; Set Rx Config register
set_io REG_RxConfig
in ax, dx
mov ecx, [tpc.chipset]
and eax, [rtl_chip_info + ecx * 8 + 4] ; RxConfigMask
or eax, rx_config
out dx, eax
 
; Set DMA burst size and Interframe Gap Time
set_io REG_TxConfig
mov eax, (TX_DMA_BURST shl TXC_DMAShift) or (InterFrameGap shl TXC_InterFrameGapShift)
out dx, eax
 
set_io REG_CPlusCmd
in ax, dx
out dx, ax
 
in ax, dx
or ax, 1 shl 3
cmp [tpc.mcfg], MCFG_METHOD_02
jne @f
cmp [tpc.mcfg], MCFG_METHOD_03
jne @f
or ax,1 shl 14
DEBUGF 1,"Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14\n"
jmp .set
@@:
DEBUGF 1,"Set MAC Reg C+CR Offset 0xE0: bit-3\n"
.set:
set_io REG_CPlusCmd
out dx, ax
 
set_io 0xE2
; mov ax, 0x1517
; out dx, ax
; mov ax, 0x152a
; out dx, ax
; mov ax, 0x282a
; out dx, ax
xor ax, ax
out dx, ax
 
xor eax, eax
mov [tpc.cur_rx], eax
lea eax, [device.tx_ring]
GetRealAddr
set_io REG_TxDescStartAddr
out dx, eax
 
lea eax, [device.rx_ring]
GetRealAddr
set_io REG_RxDescStartAddr
out dx, eax
 
set_io REG_Cfg9346
mov al, CFG_9346_Lock
out dx, al
 
udelay 10
 
xor eax, eax
set_io REG_RxMissed
out dx, eax
 
call set_rx_mode
 
set_io 0
; no early-rx interrupts
set_io REG_MultiIntr
in ax, dx
and ax, 0xF000
out dx, ax
 
; set interrupt mask
set_io REG_IntrMask
mov ax, intr_mask
out dx, ax
 
xor eax, eax
ret
 
 
align 4
read_mac:
 
set_io 0
set_io REG_MAC0
xor ecx, ecx
lea edi, [device.mac]
mov ecx, 6
 
; Get MAC address. FIXME: read EEPROM
@@: in al, dx
stosb
inc edx
loop @r
 
DEBUGF 1,"MAC = %x-%x-%x-%x-%x-%x\n",\
[device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
ret
 
align 4
write_mac:
 
ret 6
 
 
 
 
 
;***************************************************************************
; Function
; transmit
; Description
; Transmits a packet of data via the ethernet card
;
; Destroyed registers
; eax, edx, esi, edi
;
;***************************************************************************
align 4
transmit:
 
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
 
cmp dword [esp+8], MAX_ETH_FRAME_SIZE
ja .fail
 
;----------------------------------
; Find currentTX descriptor address
 
mov eax, tx_desc.size
mul [tpc.cur_tx]
lea esi, [eax + device.tx_ring]
 
DEBUGF 1,"Using TX desc: %x\n", esi
 
;---------------------------
; Program the packet pointer
 
mov eax, [esp + 4]
mov [esi + tx_desc.buf_soft_addr], eax
GetRealAddr
mov dword [esi + tx_desc.buf_addr], eax
 
;------------------------
; Program the packet size
 
mov eax, [esp + 8]
@@: or eax, DSB_OWNbit or DSB_FSbit or DSB_LSbit
cmp [tpc.cur_tx], NUM_TX_DESC - 1
jne @f
or eax, DSB_EORbit
@@: mov [esi + tx_desc.status], eax
 
;-----------------------------------------
; Set the polling bit (start transmission)
 
set_io 0
set_io REG_TxPoll
mov al, 0x40 ; set polling bit
out dx, al
 
;-----------------------
; Update TX descriptor
 
inc [tpc.cur_tx]
and [tpc.cur_tx], NUM_TX_DESC - 1
 
;-------------
; Update stats
 
inc [device.packets_tx]
mov eax, [esp + 8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
xor eax, eax
ret 8
 
.fail:
DEBUGF 1,"transmit failed\n"
or eax, -1
stdcall KernelFree, [esp+4]
ret 8
 
 
;;;DSB_OWNbit
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_handler:
 
DEBUGF 1,"\n%s int\n", my_service
 
; find pointer of device wich made IRQ occur
 
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
set_io 0
set_io REG_IntrStatus
in ax, dx
test ax, ax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x ", ebx, ax
 
cmp ax, 0xFFFF ; if so, hardware is no longer present
je .fail
 
;--------
; Receive
 
test ax, ISB_RxOK
jz .no_rx
 
push ax
push ebx
 
.check_more:
pop ebx
DEBUGF 1,"ebx = 0x%x\n", ebx
mov eax, rx_desc.size
mul [tpc.cur_rx]
lea esi, [eax + device.rx_ring]
 
DEBUGF 1,"RxDesc.status = 0x%x\n", [esi + rx_desc.status]
 
mov eax, [esi + rx_desc.status]
test eax, DSB_OWNbit ;;;
jnz .rx_return
 
DEBUGF 1,"tpc.cur_rx = %u\n", [tpc.cur_rx]
 
test eax, SD_RxRES
jnz .rx_return ;;;;; RX error!
 
push ebx
push .check_more
and eax, 0x00001FFF
add eax, -4 ; we dont need CRC
push eax
DEBUGF 1,"data length = %u\n", ax
 
;-------------
; Update stats
 
add dword [device.bytes_rx], eax
adc dword [device.bytes_rx + 4], 0
inc dword [device.packets_rx]
 
push [esi + rx_desc.buf_soft_addr]
 
;----------------------
; Allocate a new buffer
 
stdcall KernelAlloc, RX_BUF_SIZE
mov [esi + rx_desc.buf_soft_addr], eax
GetRealAddr
mov dword [esi + rx_desc.buf_addr], eax
 
;---------------
; re set OWN bit
 
mov eax, DSB_OWNbit or RX_BUF_SIZE
cmp [tpc.cur_rx], NUM_RX_DESC - 1
jne @f
or eax, DSB_EORbit
@@: mov [esi + rx_desc.status], eax
 
;--------------
; Update rx ptr
 
inc [tpc.cur_rx]
and [tpc.cur_rx], NUM_RX_DESC - 1
 
jmp Eth_input
.rx_return:
 
pop ax
.no_rx:
 
;---------
; Transmit
 
test ax, ISB_TxOK
jz .no_tx
push ax
 
DEBUGF 1,"TX ok!\n"
 
mov ecx, NUM_TX_DESC
lea esi, [device.tx_ring]
.txloop:
cmp [esi + tx_desc.buf_soft_addr], 0
jz .maybenext
 
test [esi + tx_desc.status], DSB_OWNbit
jnz .maybenext
 
push ecx
DEBUGF 1,"Freeing up TX desc: %x\n", esi
stdcall KernelFree, [esi + tx_desc.buf_soft_addr]
pop ecx
and [esi + tx_desc.buf_soft_addr], 0
 
.maybenext:
add esi, tx_desc.size
dec ecx
jnz .txloop
 
pop ax
.no_tx:
 
;-------
; Finish
 
set_io 0
set_io REG_IntrStatus
out dx, ax ; ACK all interrupts
 
.fail:
ret
 
 
 
 
 
 
 
 
 
; End of code
align 4 ; Place all initialised data here
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'RTL8169',0 ; max 16 chars include zero
 
include_debug_strings ; All data wich FDO uses will be included here
 
rtl_chip_info dd \
MCFG_METHOD_01, 0xff7e1880, \ ; RTL8169
MCFG_METHOD_02, 0xff7e1880, \ ; RTL8169s/8110s
MCFG_METHOD_03, 0xff7e1880, \ ; RTL8169s/8110s
MCFG_METHOD_04, 0xff7e1880, \ ; RTL8169sb/8110sb
MCFG_METHOD_05, 0xff7e1880, \ ; RTL8169sc/8110sc
MCFG_METHOD_11, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E
MCFG_METHOD_12, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E
MCFG_METHOD_13, 0xff7e1880, \ ; RTL8101e // PCI-E 8139
MCFG_METHOD_14, 0xff7e1880, \ ; RTL8100e // PCI-E 8139
MCFG_METHOD_15, 0xff7e1880 ; RTL8100e // PCI-E 8139
 
mac_info dd \
0x38800000, MCFG_METHOD_15, \
0x38000000, MCFG_METHOD_12, \
0x34000000, MCFG_METHOD_13, \
0x30800000, MCFG_METHOD_14, \
0x30000000, MCFG_METHOD_11, \
0x18000000, MCFG_METHOD_05, \
0x10000000, MCFG_METHOD_04, \
0x04000000, MCFG_METHOD_03, \
0x00800000, MCFG_METHOD_02, \
0x00000000, MCFG_METHOD_01 ; catch-all
 
name_01 db "RTL8169", 0
name_02_03 db "RTL8169s/8110s", 0
name_04 db "RTL8169sb/8110sb", 0
name_05 db "RTL8169sc/8110sc", 0
name_11_12 db "RTL8168b/8111b", 0 ; PCI-E
name_13 db "RTL8101e", 0 ; PCI-E 8139
name_14_15 db "RTL8100e", 0 ; PCI-E 8139
 
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
 
/kernel/branches/net/drivers/bcm57xx.asm
0,0 → 1,415
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Broadcom NetXtreme 57xx driver for KolibriOS ;;
;; ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; Broadcom's programmers's manual for the BCM57xx ;;
;; http://www.broadcom.com/collateral/pg/57XX-PG105-R.pdf ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; TODO: make better use of the available descriptors
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
 
public START
public service_proc
public version
 
 
virtual at ebx
device:
ETH_DEVICE
 
.mmio_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
 
.cur_tx dd ?
.last_tx dd ?
 
rb 0x100 - (($ - device) and 0xff)
.rx_desc rd 256/8
 
rb 0x100 - (($ - device) and 0xff)
.tx_desc rd 256/8
 
sizeof.device_struct = $ - device
 
end virtual
 
section '.flat' code readable align 16
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
 
.entry:
 
DEBUGF 2,"Loading %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
 
.fail:
.exit:
xor eax, eax
ret
 
endp
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne @F
 
cmp [IOCTL.out_size], 4
jb .fail
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
 
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
 
mov eax, [IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet
 
; check if the device is already listed
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax, [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte [device.pci_bus]
jne .next
cmp ah, byte [device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
.next:
add esi, 4
loop .nextdevice
 
 
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, sizeof.device_struct, .fail ; Allocate the buffer for device structure
 
; Fill in the direct call addresses into the struct
 
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], unload
mov [device.name], my_service
 
; save the pci bus and device numbers
 
mov eax, [IOCTL.input]
movzx ecx, byte [eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte [eax+2]
mov [device.pci_dev], ecx
 
; Now, it's time to find the base mmio addres of the PCI device
 
PCI_find_mmio32
 
; Create virtual mapping of the physical memory
 
push 1Bh ; PG_SW+PG_NOCACHE
push 10000h ; size of the map
push eax
call MapIoMem
mov [device.mmio_addr], eax
 
; We've found the mmio address, find IRQ now
 
PCI_find_irq
 
DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.mmio_addr]:8
 
; Ok, the eth_device structure is ready, let's probe the device
call probe ; this function will output in eax
test eax, eax
jnz .err ; If an error occured, exit
 
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
cmp eax, -1
je .destroy
 
ret
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 1,"Trying to find device number of already registered device\n"
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 1,"Kernel says: %u\n", eax
ret
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
; todo: reset device into virgin state
 
.err:
stdcall KernelFree, ebx
 
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
align 4
unload:
; TODO: (in this particular order)
;
; - Stop the device
; - Detach int handler
; - Remove device from local list (device_list)
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
 
or eax, -1
 
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; probe: enables the device (if it really is I8254X)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
probe:
 
DEBUGF 1,"Probe\n"
 
PCI_make_bus_master
 
; TODO: validate the device
 
 
 
 
 
align 4
reset:
 
DEBUGF 1,"Reset\n"
 
movzx eax, [device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax
jnz @f
DEBUGF 1,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
call read_mac
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
ret
 
 
 
 
align 4
read_mac:
 
DEBUGF 1,"Read MAC\n"
 
mov esi, [device.mmio_addr]
lea edi, [device.mac]
movsd
movsw
 
.mac_ok:
DEBUGF 1,"MAC = %x-%x-%x-%x-%x-%x\n",\
[device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
transmit:
DEBUGF 2,"\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
DEBUGF 2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
 
cmp dword [esp + 8], 1514
ja .fail
cmp dword [esp + 8], 60
jb .fail
 
 
 
 
; Update stats
inc [device.packets_tx]
mov eax, [esp + 8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
ret 8
 
.fail:
DEBUGF 1,"Send failed\n"
ret 8
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_handler:
 
DEBUGF 1,"\n%s int\n", my_service
;-------------------------------------------
; Find pointer of device wich made IRQ occur
 
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
; mov edi, [device.mmio_addr]
; mov eax, [edi + REG_ICR]
test eax, eax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
ret
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x ", ebx, eax
 
ret
 
 
 
 
; End of code
 
section '.data' data readable writable align 16
align 4
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'BCM57XX',0 ; max 16 chars include zero
 
include_debug_strings ; All data wich FDO uses will be included here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
 
/kernel/branches/net/drivers/dec21x4x.asm
0,0 → 1,1696
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; DEC 21x4x driver for KolibriOS ;;
;; ;;
;; Based on dec21140.Asm from Solar OS by ;;
;; Eugen Brasoveanu, ;;
;; Ontanu Bogdan Valentin ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
RX_DES_COUNT = 4 ; no of RX descriptors, must be power of 2
RX_BUFF_SIZE = 2048 ; size of buffer for each descriptor, must be multiple of 4 and <= 2048 TDES1_TBS1_MASK
 
TX_DES_COUNT = 4 ; no of TX descriptors, must be power of 2
TX_BUFF_SIZE = 2048 ; size of buffer for each descriptor, used for memory allocation only
 
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
 
public START
public service_proc
public version
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.rx_p_des dd ? ; descriptors ring with received packets
.tx_p_des dd ? ; descriptors ring with 'to transmit' packets
.tx_free_des dd ? ; Tx descriptors available
.tx_wr_des dd ? ; Tx current descriptor to write data to
.tx_rd_des dd ? ; Tx current descriptor to read TX completion
.rx_crt_des dd ? ; Rx current descriptor
 
.io_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
 
.size = $ - device
 
end virtual
 
;-------------------------------------------
; configuration registers
;-------------------------------------------
CFCS = 4 ; configuration and status register
 
CSR0 = 0x00 ; Bus mode
CSR1 = 0x08 ; Transmit Poll Command
CSR2 = 0x10 ; Receive Poll Command
CSR3 = 0x18 ; Receive list base address
CSR4 = 0x20 ; Transmit list base address
CSR5 = 0x28 ; Status
CSR6 = 0x30 ; Operation mode
CSR7 = 0x38 ; Interrupt enable
CSR8 = 0x40 ; Missed frames and overflow counter
CSR9 = 0x48 ; Boot ROM, serial ROM, and MII management
CSR10 = 0x50 ; Boot ROM programming address
CSR11 = 0x58 ; General-purpose timer
CSR12 = 0x60 ; General-purpose port
CSR13 = 0x68
CSR14 = 0x70
CSR15 = 0x78 ; Watchdog timer
 
;--------bits/commands of CSR0-------------------
CSR0_RESET = 1b
 
CSR0_WIE = 1 shl 24 ; Write and Invalidate Enable
CSR0_RLE = 1 shl 23 ; PCI Read Line Enable
CSR0_RML = 1 shl 21 ; PCI Read Multiple
 
CSR0_CACHEALIGN_NONE = 00b shl 14
CSR0_CACHEALIGN_32 = 01b shl 14
CSR0_CACHEALIGN_64 = 10b shl 14
CSR0_CACHEALIGN_128 = 11b shl 14
 
; using values from linux driver..
CSR0_DEFAULT = CSR0_WIE + CSR0_RLE + CSR0_RML + CSR0_CACHEALIGN_NONE
 
;------- CSR5 -STATUS- bits --------------------------------
CSR5_TI = 1 shl 0 ; Transmit interupt - frame transmition completed
CSR5_TPS = 1 shl 1 ; Transmit process stopped
CSR5_TU = 1 shl 2 ; Transmit Buffer unavailable
CSR5_TJT = 1 shl 3 ; Transmit Jabber Timeout (transmitter had been excessively active)
CSR5_UNF = 1 shl 5 ; Transmit underflow - FIFO underflow
CSR5_RI = 1 shl 6 ; Receive Interrupt
CSR5_RU = 1 shl 7 ; Receive Buffer unavailable
CSR5_RPS = 1 shl 8 ; Receive Process stopped
CSR5_RWT = 1 shl 9 ; Receive Watchdow Timeout
CSR5_ETI = 1 shl 10 ; Early transmit Interrupt
CSR5_GTE = 1 shl 11 ; General Purpose Timer Expired
CSR5_FBE = 1 shl 13 ; Fatal bus error
CSR5_ERI = 1 shl 14 ; Early receive Interrupt
CSR5_AIS = 1 shl 15 ; Abnormal interrupt summary
CSR5_NIS = 1 shl 16 ; normal interrupt summary
CSR5_RS_SH = 17 ; Receive process state -shift
CSR5_RS_MASK = 111b ; -mask
CSR5_TS_SH = 20 ; Transmit process state -shift
CSR5_TS_MASK = 111b ; -mask
CSR5_EB_SH = 23 ; Error bits -shift
CSR5_EB_MASK = 111b ; Error bits -mask
 
;CSR5 TS values
CSR5_TS_STOPPED = 000b
CSR5_TS_RUNNING_FETCHING_DESC = 001b
CSR5_TS_RUNNING_WAITING_TX = 010b
CSR5_TS_RUNNING_READING_BUFF = 011b
CSR5_TS_RUNNING_SETUP_PCKT = 101b
CSR5_TS_SUSPENDED = 110b
CSR5_TS_RUNNING_CLOSING_DESC = 111b
 
;------- CSR6 -OPERATION MODE- bits --------------------------------
CSR6_HP = 1 shl 0 ; Hash/Perfect Receive Filtering mode
CSR6_SR = 1 shl 1 ; Start/Stop receive
CSR6_HO = 1 shl 2 ; Hash only Filtering mode
CSR6_PB = 1 shl 3 ; Pass bad frames
CSR6_IF = 1 shl 4 ; Inverse filtering
CSR6_SB = 1 shl 5 ; Start/Stop backoff counter
CSR6_PR = 1 shl 6 ; Promiscuos mode -default after reset
CSR6_PM = 1 shl 7 ; Pass all multicast
CSR6_F = 1 shl 9 ; Full Duplex mode
CSR6_OM_SH = 10 ; Operating Mode -shift
CSR6_OM_MASK = 11b ; -mask
CSR6_FC = 1 shl 12 ; Force Collision Mode
CSR6_ST = 1 shl 13 ; Start/Stop Transmission Command
CSR6_TR_SH = 14 ; Threshold Control -shift
CSR6_TR_MASK = 11b ; -mask
CSR6_CA = 1 shl 17 ; Capture Effect Enable
CSR6_PS = 1 shl 18 ; Port select SRL / MII/SYM
CSR6_HBD = 1 shl 19 ; Heartbeat Disable
CSR6_SF = 1 shl 21 ; Store and Forward -transmit full packet only
CSR6_TTM = 1 shl 22 ; Transmit Threshold Mode -
CSR6_PCS = 1 shl 23 ; PCS active and MII/SYM port operates in symbol mode
CSR6_SCR = 1 shl 24 ; Scrambler Mode
CSR6_MBO = 1 shl 25 ; Must Be One
CSR6_RA = 1 shl 30 ; Receive All
CSR6_SC = 1 shl 31 ; Special Capture Effect Enable
 
 
;------- CSR7 -INTERRUPT ENABLE- bits --------------------------------
CSR7_TI = 1 shl 0 ; transmit Interrupt Enable (set with CSR7<16> & CSR5<0> )
CSR7_TS = 1 shl 1 ; transmit Stopped Enable (set with CSR7<15> & CSR5<1> )
CSR7_TU = 1 shl 2 ; transmit buffer underrun Enable (set with CSR7<16> & CSR5<2> )
CSR7_TJ = 1 shl 3 ; transmit jabber timeout enable (set with CSR7<15> & CSR5<3> )
CSR7_UN = 1 shl 5 ; underflow Interrupt enable (set with CSR7<15> & CSR5<5> )
CSR7_RI = 1 shl 6 ; receive Interrupt enable (set with CSR7<16> & CSR5<5> )
CSR7_RU = 1 shl 7 ; receive buffer unavailable enable (set with CSR7<15> & CSR5<7> )
CSR7_RS = 1 shl 8 ; Receive stopped enable (set with CSR7<15> & CSR5<8> )
CSR7_RW = 1 shl 9 ; receive watchdog timeout enable (set with CSR7<15> & CSR5<9> )
CSR7_ETE = 1 shl 10 ; Early transmit Interrupt enable (set with CSR7<15> & CSR5<10> )
CSR7_GPT = 1 shl 11 ; general purpose timer enable (set with CSR7<15> & CSR5<11> )
CSR7_FBE = 1 shl 13 ; Fatal bus error enable (set with CSR7<15> & CSR5<13> )
CSR7_ERE = 1 shl 14 ; Early receive enable (set with CSR7<16> & CSR5<14> )
CSR7_AI = 1 shl 15 ; Abnormal Interrupt Summary Enable (enables CSR5<0,3,7,8,9,10,13>)
CSR7_NI = 1 shl 16 ; Normal Interrup Enable (enables CSR5<0,2,6,11,14>)
 
CSR7_DEFAULT = CSR7_TI + CSR7_TS + CSR7_RI + CSR7_RS + CSR7_TU + CSR7_TJ + CSR7_UN + \
CSR7_RU + CSR7_RW + CSR7_FBE + CSR7_AI + CSR7_NI
 
;----------- descriptor structure ---------------------
struc DES {
.status dd ? ; bit 31 is 'own' and rest is 'status'
.length dd ? ; control bits + bytes-count buffer 1 + bytes-count buffer 2
.buffer1 dd ? ; pointer to buffer1
.buffer2 dd ? ; pointer to buffer2 or in this case to next descriptor, as we use a chained structure
.virtaddr dd ?
.size = 64 ; 64, for alignment purposes
}
 
virtual at 0
DES DES
end virtual
 
;common to Rx and Tx
DES0_OWN = 1 shl 31 ; if set, the NIC controls the descriptor, otherwise driver 'owns' the descriptors
 
;receive
RDES0_ZER = 1 shl 0 ; must be 0 if legal length :D
RDES0_CE = 1 shl 1 ; CRC error, valid only on last desc (RDES0<8>=1)
RDES0_DB = 1 shl 2 ; dribbling bit - not multiple of 8 bits, valid only on last desc (RDES0<8>=1)
RDES0_RE = 1 shl 3 ; Report on MII error.. i dont realy know what this means :P
RDES0_RW = 1 shl 4 ; received watchdog timer expiration - must set CSR5<9>, valid only on last desc (RDES0<8>=1)
RDES0_FT = 1 shl 5 ; frame type: 0->IEEE802.0 (len<1500) 1-> ETHERNET frame (len>1500), valid only on last desc (RDES0<8>=1)
RDES0_CS = 1 shl 6 ; Collision seen, valid only on last desc (RDES0<8>=1)
RDES0_TL = 1 shl 7 ; Too long(>1518)-NOT AN ERROR, valid only on last desc (RDES0<8>=1)
RDES0_LS = 1 shl 8 ; Last descriptor of current frame
RDES0_FS = 1 shl 9 ; First descriptor of current frame
RDES0_MF = 1 shl 10 ; Multicast frame, valid only on last desc (RDES0<8>=1)
RDES0_RF = 1 shl 11 ; Runt frame, valid only on last desc (RDES0<8>=1) and id overflow
RDES0_DT_SERIAL = 00b shl 12 ; Data type-Serial recv frame, valid only on last desc (RDES0<8>=1)
RDES0_DT_INTERNAL = 01b shl 12 ; Data type-Internal loopback recv frame, valid only on last desc (RDES0<8>=1)
RDES0_DT_EXTERNAL = 11b shl 12 ; Data type-External loopback recv frame, valid only on last desc (RDES0<8>=1)
RDES0_DE = 1 shl 14 ; Descriptor error - cant own a new desc and frame doesnt fit, valid only on last desc (RDES0<8>=1)
RDES0_ES = 1 shl 15 ; Error Summmary - bits 1+6+11+14, valid only on last desc (RDES0<8>=1)
RDES0_FL_SH = 16 ; Field length shift, valid only on last desc (RDES0<8>=1)
RDES0_FL_MASK = 11111111111111b ; Field length mask (+CRC), valid only on last desc (RDES0<8>=1)
RDES0_FF = 1 shl 30 ; Filtering fail-frame failed address recognition test(must CSR6<30>=1), valid only on last desc (RDES0<8>=1)
 
RDES1_RBS1_MASK = 11111111111b ; first buffer size MASK
RDES1_RBS2_SH = 11 ; second buffer size SHIFT
RDES1_RBS2_MASK = 11111111111b ; second buffer size MASK
RDES1_RCH = 1 shl 24 ; Second address chained - second address (buffer) is next desc address
RDES1_RER = 1 shl 25 ; Receive End of Ring - final descriptor, NIC must return to first desc
 
;transmition
TDES0_DE = 1 shl 0 ; Deffered
TDES0_UF = 1 shl 1 ; Underflow error
TDES0_LF = 1 shl 2 ; Link fail report (only if CSR6<23>=1)
TDES0_CC_SH = 3 ; Collision Count shift - no of collision before transmition
TDES0_CC_MASK = 1111b ; Collision Count mask
TDES0_HF = 1 shl 7 ; Heartbeat fail
TDES0_EC = 1 shl 8 ; Excessive Collisions - >16 collisions
TDES0_LC = 1 shl 9 ; Late collision
TDES0_NC = 1 shl 10 ; No carrier
TDES0_LO = 1 shl 11 ; Loss of carrier
TDES0_TO = 1 shl 14 ; Transmit Jabber Timeout
TDES0_ES = 1 shl 15 ; Error summary TDES0<1+8+9+10+11+14>=1
 
TDES1_TBS1_MASK = 11111111111b ; Buffer 1 size mask
TDES1_TBS2_SH = 11 ; Buffer 2 size shift
TDES1_TBS2_MASK = 11111111111b ; Buffer 2 size mask
TDES1_FT0 = 1 shl 22 ; Filtering type 0
TDES1_DPD = 1 shl 23 ; Disabled padding for packets <64bytes, no padding
TDES1_TCH = 1 shl 24 ; Second address chained - second buffer pointer is to next desc
TDES1_TER = 1 shl 25 ; Transmit end of ring - final descriptor
TDES1_AC = 1 shl 26 ; Add CRC disable -pretty obvious
TDES1_SET = 1 shl 27 ; Setup packet
TDES1_FT1 = 1 shl 28 ; Filtering type 1
TDES1_FS = 1 shl 29 ; First segment - buffer is first segment of frame
TDES1_LS = 1 shl 30 ; Last segment
TDES1_IC = 1 shl 31 ; Interupt on completion (CSR5<0>=1) valid when TDES1<30>=1
 
MAX_ETH_FRAME_SIZE = 1514
 
RX_MEM_TOTAL_SIZE = RX_DES_COUNT*(DES.size+RX_BUFF_SIZE)
TX_MEM_TOTAL_SIZE = TX_DES_COUNT*(DES.size+TX_BUFF_SIZE)
 
;=============================================================================
; serial ROM operations
;=============================================================================
CSR9_SR = 1 shl 11 ; SROM Select
CSR9_RD = 1 shl 14 ; ROM Read Operation
CSR9_SROM_DO = 1 shl 3 ; Data Out for SROM
CSR9_SROM_DI = 1 shl 2 ; Data In to SROM
CSR9_SROM_CK = 1 shl 1 ; clock for SROM
CSR9_SROM_CS = 1 shl 0 ; chip select.. always needed
 
; assume dx is CSR9
macro SROM_Delay {
push eax
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
pop eax
}
 
; assume dx is CSR9
macro MDIO_Delay {
push eax
in eax, dx
pop eax
}
 
macro Bit_Set a_bit {
in eax, dx
or eax, a_bit
out dx , eax
}
 
macro Bit_Clear a_bit {
in eax, dx
and eax, not (a_bit)
out dx, eax
}
 
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
 
.entry:
 
DEBUGF 2,"Loading %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
 
.fail:
.exit:
xor eax, eax
ret
 
endp
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne @F
 
cmp [IOCTL.out_size], 4
jb .fail
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
 
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
 
mov eax, [IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet
 
; check if the device is already listed
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax , [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
 
 
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
push edx
stdcall KernelAlloc, dword device.size ; Allocate the buffer for eth_device structure
pop edx
test eax, eax
jz .fail
mov ebx, eax ; ebx is always used as a pointer to the structure (in driver, but also in kernel code)
 
; Fill in the direct call addresses into the struct
 
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], unload
mov [device.name], my_service
 
; save the pci bus and device numbers
 
mov eax, [IOCTL.input]
movzx ecx, byte[eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte[eax+2]
mov [device.pci_dev], ecx
 
; Now, it's time to find the base io addres of the PCI device
 
PCI_find_io
 
; We've found the io address, find IRQ now
 
PCI_find_irq
 
DEBUGF 2,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:8
 
allocate_and_clear [device.rx_p_des], RX_DES_COUNT*(DES.size+RX_BUFF_SIZE), .err
allocate_and_clear [device.tx_p_des], TX_DES_COUNT*(DES.size+TX_BUFF_SIZE), .err
 
; Ok, the eth_device structure is ready, let's probe the device
; Because initialization fires IRQ, IRQ handler must be aware of this device
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
 
call probe ; this function will output in eax
test eax, eax
jnz .err2 ; If an error occured, exit
 
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
cmp eax, -1
je .destroy
 
ret
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 2,"Trying to find device number of already registered device\n"
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 2,"Kernel says: %u\n", eax
ret
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
; todo: reset device into virgin state
 
.err2:
dec [devices]
.err:
DEBUGF 2,"removing device structure\n"
stdcall KernelFree, [device.rx_p_des]
stdcall KernelFree, [device.tx_p_des]
stdcall KernelFree, ebx
 
 
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
 
align 4
unload:
; TODO: (in this particular order)
;
; - Stop the device
; - Detach int handler
; - Remove device from local list (RTL8139_LIST)
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
 
or eax,-1
 
ret
 
 
macro status {
set_io CSR5
in eax, dx
DEBUGF 1,"CSR5: %x\n", eax
}
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Probe ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
probe:
 
DEBUGF 2,"Probing dec21x4x device: "
 
PCI_make_bus_master
 
stdcall PciRead32, [device.pci_bus], [device.pci_dev], 0 ; get device/vendor id
DEBUGF 1,"Vendor id: 0x%x\n", ax
 
cmp ax, 0x1011
je .dec
cmp ax, 0x1317
je .admtek
jmp .notfound
 
.dec:
shr eax, 16
DEBUGF 1,"Vendor ok!, device id: 0x%x\n", ax ; TODO: use another method to detect chip!
 
cmp ax, 0x0009
je .supported_device
 
cmp ax, 0x0019
je .supported_device2
 
.admtek:
shr eax, 16
DEBUGF 1,"Vendor ok!, device id: 0x%x\n", ax
 
cmp ax, 0x0985
je .supported_device
 
.notfound:
DEBUGF 1,"Device not supported!\n"
or eax, -1
ret
 
.supported_device2:
 
; wake up the 21143
 
xor eax, eax
stdcall PciWrite32, [device.pci_bus], [device.pci_dev], 0x40, eax
 
 
.supported_device:
call SROM_GetWidth ; TODO: use this value returned in ecx
; in the read_word routine!
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Reset ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
reset:
 
DEBUGF 2,"Resetting dec21x4x\n"
 
;-----------------------------------------------------------
; board software reset - if fails, dont do nothing else
 
set_io 0
status
set_io CSR0
mov eax, CSR0_RESET
out dx, eax
 
; wait at least 50 PCI cycles
mov esi, 1000
call Sleep
 
;-----------
; setup CSR0
 
set_io 0
status
set_io CSR0
mov eax, CSR0_DEFAULT
out dx, eax
 
 
; wait at least 50 PCI cycles
mov esi, 1000
call Sleep
 
;-----------------------------------
; Read mac from eeprom to driver ram
 
call read_mac_eeprom
 
;--------------------------------
; insert irq handler on given irq
 
movzx eax, [device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax
jnz @f
DEBUGF 1,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
set_io 0
status
 
call init_ring
 
;--------------------------------------------
; setup CSR3 & CSR4 (pointers to descriptors)
 
set_io 0
status
set_io CSR3
mov eax, [device.rx_p_des]
GetRealAddr
DEBUGF 1,"RX descriptor base address: %x\n", eax
out dx, eax
 
set_io CSR4
mov eax, [device.tx_p_des]
GetRealAddr
DEBUGF 1,"TX descriptor base address: %x\n", eax
out dx, eax
 
;-------------------------------------------------------
; setup interrupt mask register -expect IRQs from now on
 
status
DEBUGF 1,"Enabling interrupts\n"
set_io CSR7
mov eax, CSR7_DEFAULT
out dx, eax
status
 
;----------
; enable RX
 
set_io 0
status
DEBUGF 1,"Enable RX\n"
 
set_io CSR6
Bit_Set CSR6_SR; or CSR6_PR or CSR6_ST
DEBUGF 1,"CSR6: %x\n", eax
 
status
 
call start_link
 
; wait a bit
mov esi, 3000
call Sleep
 
;----------------------------------------------------
; send setup packet to notify the board about the MAC
 
call Send_Setup_Packet
 
xor eax, eax
; clear packet/byte counters
 
lea edi, [device.bytes_tx]
mov ecx, 6
rep stosd
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
DEBUGF 1,"Reset done\n"
 
ret
 
 
 
align 4
init_ring:
 
;------------------------------------------
; Setup RX descriptors (use chained method)
 
mov eax, [device.rx_p_des]
GetRealAddr
mov edx, eax
push eax
lea esi, [eax + RX_DES_COUNT*(DES.size)] ; jump over RX descriptors
mov eax, [device.rx_p_des]
add eax, RX_DES_COUNT*(DES.size) ; jump over RX descriptors
mov edi, [device.rx_p_des]
mov ecx, RX_DES_COUNT
.loop_rx_des:
add edx, DES.size
mov [edi + DES.status], DES0_OWN ; hardware owns buffer
mov [edi + DES.length], 1984 + RDES1_RCH ; only size of first buffer, chained buffers
mov [edi + DES.buffer1], esi ; hw buffer address
mov [edi + DES.buffer2], edx ; pointer to next descriptor
mov [edi + DES.virtaddr], eax ; virtual buffer address
DEBUGF 1,"RX desc: buff addr: %x, next desc: %x, real buff addr: %x, real descr addr: %x \n", esi, edx, eax, edi
 
add esi, RX_BUFF_SIZE
add eax, RX_BUFF_SIZE
add edi, DES.size
dec ecx
jnz .loop_rx_des
 
; set last descriptor as LAST
sub edi, DES.size
or [edi + DES.length], RDES1_RER ; EndOfRing
pop [edi + DES.buffer2] ; point it to the first descriptor
 
;---------------------
; Setup TX descriptors
 
mov eax, [device.tx_p_des]
GetRealAddr
mov edx, eax
push eax
lea esi, [eax + TX_DES_COUNT*(DES.size)] ; jump over TX descriptors
mov eax, [device.tx_p_des]
add eax, TX_DES_COUNT*(DES.size) ; jump over TX descriptors
mov edi, [device.tx_p_des]
mov ecx, TX_DES_COUNT
.loop_tx_des:
add edx, DES.size
mov [edi + DES.status], 0 ; owned by driver
mov [edi + DES.length], TDES1_TCH ; chained method
mov [edi + DES.buffer1], esi ; pointer to buffer
mov [edi + DES.buffer2], edx ; pointer to next descr
mov [edi + DES.virtaddr], eax
DEBUGF 1,"TX desc: buff addr: %x, next desc: %x, virt buff addr: %x, virt descr addr: %x \n", esi, edx, eax, edi
 
add esi, TX_BUFF_SIZE
add eax, TX_BUFF_SIZE
add edi, DES.size
dec ecx
jnz .loop_tx_des
; set last descriptor as LAST
sub edi, DES.size
or [edi + DES.length], TDES1_TER ; EndOfRing
pop [edi + DES.buffer2] ; point it to the first descriptor
 
;------------------
; Reset descriptors
 
mov [device.tx_wr_des], 0
mov [device.tx_rd_des], 0
mov [device.rx_crt_des], 0
mov [device.tx_free_des], TX_DES_COUNT
 
ret
 
 
align 4
start_link:
 
; TODO: write working code here
 
ret
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Send setup packet ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
Send_Setup_Packet:
 
DEBUGF 1,"Sending setup packet\n"
 
; if no descriptors available, out
mov ecx, 1000
@@loop_wait_desc:
cmp [device.tx_free_des], 0
jne @f
 
dec ecx
jnz @@loop_wait_desc
 
mov eax, -1
ret
@@:
 
; go to current send descriptor
mov edi, [device.tx_p_des]
mov eax, [device.tx_wr_des]
DEBUGF 1,"Got free descriptor: %u (%x)", eax, edi
mov edx, DES.size
mul edx
add edi, eax
DEBUGF 1,"=>%x\n", edi
 
; if NOT sending FIRST setup packet, must set current descriptor to 0 size for both buffers,
; and go to next descriptor for real setup packet... ;; TODO: check if 2 descriptors are available
 
; cmp [device.tx_packets], 0
; je .first
;
; and [edi+DES.des1], 0
; mov [edi+DES.des0], DES0_OWN
;
; go to next descriptor
; inc [device.tx_wr_des]
; and [device.tx_wr_des], TX_DES_COUNT-1
;
; dec free descriptors count
; cmp [device.tx_free_des], 0
; jz @f
; dec [device.tx_free_des]
; @@:
;
; ; recompute pointer to current descriptor
; mov edi, [device.tx_p_des]
; mov eax, [device.tx_wr_des]
; mov edx, DES.size
; mul edx
; add edi, eax
 
.first:
 
push edi
; copy setup packet to current descriptor
mov edi, [edi + DES.virtaddr]
; copy the address once
lea esi, [device.mac]
DEBUGF 1,"copying packet to %x from %x\n", edi, esi
mov ecx, 3 ; mac is 6 bytes thus 3 words
.loop:
DEBUGF 1,"%x ", [esi]:4
movsw
inc edi
inc edi
dec ecx
jnz .loop
 
DEBUGF 1,"\n"
 
; copy 15 times the broadcast address
mov ecx, 3*15
mov eax, 0xffffffff
rep stosd
 
pop edi
 
; setup descriptor
DEBUGF 1,"setting up descriptor\n"
mov [edi + DES.length], TDES1_IC + TDES1_SET + TDES1_TCH + 192 ; size must be EXACTLY 192 bytes
mov [edi + DES.status], DES0_OWN
 
DEBUGF 1,"status: %x\n", [edi + DES.status]:8
DEBUGF 1,"length: %x\n", [edi + DES.length]:8
DEBUGF 1,"buffer1: %x\n", [edi + DES.buffer1]:8
DEBUGF 1,"buffer2: %x\n", [edi + DES.buffer2]:8
 
; go to next descriptor
inc [device.tx_wr_des]
and [device.tx_wr_des], TX_DES_COUNT-1
 
; dec free descriptors count
cmp [device.tx_free_des], 0
jz @f
dec [device.tx_free_des]
@@:
 
; start tx
set_io 0
status
set_io CSR6
in eax, dx
test eax, CSR6_ST ; if NOT started, start now
jnz .already_started
or eax, CSR6_ST
DEBUGF 1,"Starting TX\n"
jmp .do_it
.already_started:
; if already started, issue a Transmit Poll command
set_io CSR1
xor eax, eax
DEBUGF 1,"Issuing transmit poll command\n"
.do_it:
out dx, eax
status
 
DEBUGF 1,"Sending setup packet, completed!\n"
 
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
transmit:
 
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
mov eax, [esp+4]
DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
 
cmp dword [esp+8], MAX_ETH_FRAME_SIZE
ja .fail
 
cmp [device.tx_free_des], 0
je .fail
 
;--------------------------
; copy packet to crt buffer
mov eax, [device.tx_wr_des]
mov edx, DES.size
mul edx
add eax, [device.tx_p_des]
mov edi, [eax + DES.virtaddr] ; pointer to buffer
mov esi, [esp+4]
mov ecx, [esp+8]
DEBUGF 1,"copying %u bytes from %x to %x\n", ecx, esi, edi
rep movsb
 
; set packet size
mov ecx, [eax+DES.length]
and ecx, TDES1_TER ; preserve 'End of Ring' bit
or ecx, [esp+8] ; set size
or ecx, TDES1_FS or TDES1_LS or TDES1_IC or TDES1_TCH ; first descr, last descr, interrupt on complete, chained modus
mov [eax+DES.length], ecx
 
; set descriptor info
mov [eax+DES.status], DES0_OWN ; say it is now owned by the 21x4x
 
; start tx
set_io 0
status
set_io CSR6
in eax, dx
test eax, CSR6_ST ; if NOT started, start now
jnz .already_started
or eax, CSR6_ST
DEBUGF 1,"Starting TX\n"
jmp .do_it
.already_started:
; if already started, issues a Transmit Poll command
set_io CSR1
mov eax, -1
.do_it:
out dx , eax
 
; Update stats
 
inc [device.packets_tx]
mov eax, [esp+8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
; go to next descriptor
inc [device.tx_wr_des]
and [device.tx_wr_des], TX_DES_COUNT-1
 
; dec free descriptors count
test [device.tx_free_des], -1
jz .end
dec [device.tx_free_des]
.end:
status
 
DEBUGF 1,"transmit ok\n"
xor eax, eax
stdcall KernelFree, [esp+4]
ret 8
 
.fail:
DEBUGF 1,"transmit failed\n"
or eax, -1
stdcall KernelFree, [esp+4]
ret 8
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_handler:
 
DEBUGF 1,"\n%s int\n", my_service
 
; find pointer of device wich made IRQ occur
 
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
set_io 0
set_io CSR5
in eax, dx
out dx, eax ; send it back to ACK
test eax, eax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
 
.got_it:
 
DEBUGF 1,"Device: %x CSR5: %x ", ebx, ax
 
;----------------------------------
; TX ok?
 
test ax, CSR5_TI
jz .not_tx
push ax esi ecx
 
DEBUGF 1,"TX ok!\n"
; go to current descriptor
mov edi, [device.tx_p_des]
 
mov eax, [device.tx_rd_des]
mov edx, DES.size
mul edx
add edi, eax
.loop_tx:
; done if all desc are free
cmp [device.tx_free_des], TX_DES_COUNT
jz .end_tx
 
mov eax, [edi+DES.status]
 
; we stop at first desc that is owned be NIC
test eax, DES0_OWN
jnz .end_tx
 
; detect is setup packet
cmp eax, (0ffffffffh - DES0_OWN) ; all other bits are 1
jne .not_setup_packet
DEBUGF 1,"Setup Packet detected\n"
.not_setup_packet:
 
DEBUGF 1,"packet status: %x\n", eax
 
; next descriptor
add edi, DES.size
inc [device.tx_rd_des]
and [device.tx_rd_des], TX_DES_COUNT-1
 
; inc free desc
inc [device.tx_free_des]
cmp [device.tx_free_des], TX_DES_COUNT
jbe @f
mov [device.tx_free_des], TX_DES_COUNT
@@:
 
jmp .loop_tx
.end_tx:
;------------------------------------------------------
; here must be called standard Ethernet Tx Irq Handler
;------------------------------------------------------
 
pop ecx esi ax
 
;----------------------------------
; RX irq
.not_tx:
test ax, CSR5_RI
jz .not_rx
push ax esi ecx
 
DEBUGF 1,"RX ok!\n"
 
push ebx
.rx_loop:
pop ebx
 
; get current descriptor
mov edi, [device.rx_p_des]
mov eax, [device.rx_crt_des]
mov edx, DES.size
mul edx
add edi, eax
 
; now check status
mov eax, [edi + DES.status]
 
test eax, DES0_OWN
jnz .end_rx ; current desc is busy, nothing to do
 
test eax, RDES0_FS
jz .end_rx ; current desc is NOT first packet, ERROR!
 
test eax, RDES0_LS ; if not last desc of packet, error for now
jz .end_rx
 
test eax, RDES0_ES
jnz .end_rx
 
mov esi, [edi + DES.virtaddr]
mov ecx, [edi + DES.status]
shr ecx, RDES0_FL_SH
and ecx, RDES0_FL_MASK
sub ecx, 4 ; crc, we dont need it
 
DEBUGF 1,"Received packet!, size=%u, addr:%x\n", ecx, esi
 
push esi edi ecx
stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
pop ecx edi esi
test eax, eax
jz .fail
 
push ebx
push dword .rx_loop
push ecx eax
mov edi, eax
 
; update statistics
inc [device.packets_rx]
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
 
; copy packet data
shr cx , 1
jnc .nb
movsb
.nb:
shr cx , 1
jnc .nw
movsw
.nw:
rep movsd
 
mov [edi + DES.status], DES0_OWN ; free descriptor
inc [device.rx_crt_des] ; next descriptor
and [device.rx_crt_des], RX_DES_COUNT-1
 
jmp Eth_input
 
.end_rx:
.fail:
pop ecx esi ax
.not_rx:
 
jmp .continue
 
 
 
align 4
write_mac: ; in: mac pushed onto stack (as 3 words)
 
DEBUGF 2,"Writing MAC: "
 
; write data into driver cache
mov esi, esp
lea edi, [device.mac]
movsd
movsw
add esp, 6
; send setup packet (only if driver is started)
call Send_Setup_Packet
 
align 4
read_mac:
 
DEBUGF 1,"Read_mac\n"
 
ret
 
 
 
align 4
read_mac_eeprom:
 
DEBUGF 1,"Read_mac_eeprom\n"
 
lea edi, [device.mac]
mov esi, 20/2 ; read words, start address is 20
.loop:
push esi edi
call SROM_Read_Word
pop edi esi
stosw
inc esi
cmp esi, 26/2
jb .loop
 
DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[edi-6]:2,[edi-5]:2,[edi-4]:2,[edi-3]:2,[edi-2]:2,[edi-1]:2
 
ret
 
align 4
write_mac_eeprom:
 
DEBUGF 1,"Write_mac_eeprom\n"
 
ret
 
 
align 4
SROM_GetWidth: ; should be 6 or 8 according to some manuals (returns in ecx)
 
DEBUGF 1,"SROM_GetWidth\n"
 
call SROM_Idle
call SROM_EnterAccessMode
 
; set_io 0
; set_io CSR9
 
; send 110b
 
in eax, dx
or eax, CSR9_SROM_DI
call SROM_out
 
in eax, dx
or eax, CSR9_SROM_DI
call SROM_out
 
in eax, dx
and eax, not (CSR9_SROM_DI)
call SROM_out
mov ecx,1
.loop2:
Bit_Set CSR9_SROM_CK
SROM_Delay
in eax, dx
and eax, CSR9_SROM_DO
jnz .not_zero
 
Bit_Clear CSR9_SROM_CK
SROM_Delay
jmp .end_loop2
.not_zero:
Bit_Clear CSR9_SROM_CK
SROM_Delay
inc ecx
cmp ecx, 12
jbe .loop2
.end_loop2:
DEBUGF 1,"Srom width=%u\n", ecx
call SROM_Idle
call SROM_EnterAccessMode
call SROM_Idle
ret
 
 
align 4
SROM_out:
 
out dx, eax
SROM_Delay
Bit_Set CSR9_SROM_CK
SROM_Delay
Bit_Clear CSR9_SROM_CK
SROM_Delay
 
ret
 
 
 
align 4
SROM_EnterAccessMode:
 
DEBUGF 1,"SROM_EnterAccessMode\n"
 
set_io 0
set_io CSR9
mov eax, CSR9_SR
out dx, eax
SROM_Delay
 
Bit_Set CSR9_RD
SROM_Delay
 
Bit_Clear CSR9_SROM_CK
SROM_Delay
 
Bit_Set CSR9_SROM_CS
SROM_Delay
ret
 
 
 
align 4
SROM_Idle:
 
DEBUGF 1,"SROM_Idle\n"
 
call SROM_EnterAccessMode
; set_io 0
; set_io CSR9
mov ecx, 25
.loop_clk:
 
Bit_Clear CSR9_SROM_CK
SROM_Delay
Bit_Set CSR9_SROM_CK
SROM_Delay
dec ecx
jnz .loop_clk
 
Bit_Clear CSR9_SROM_CK
SROM_Delay
Bit_Clear CSR9_SROM_CS
SROM_Delay
xor eax, eax
out dx, eax
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Read serial EEprom word ;;
;; ;;
;; In: esi = read address ;;
;; OUT: ax = data word ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
SROM_Read_Word:
 
DEBUGF 1,"SROM_Read_word at: %x result: ", esi
 
set_io 0
set_io CSR9
 
; enter access mode
mov eax, CSR9_SR + CSR9_RD
out dx , eax
or eax, CSR9_SROM_CS
out dx , eax
 
; TODO: change this hard-coded 6-bit stuff to use value from srom_getwidth
; send read command "110b" + address to read from
and esi, 111111b
or esi, 110b shl 6
mov ecx, 1 shl 9
.loop_cmd:
mov eax, CSR9_SR + CSR9_RD + CSR9_SROM_CS
test esi, ecx
jz @f
or eax, CSR9_SROM_DI
@@:
out dx , eax
SROM_Delay
or eax, CSR9_SROM_CK
out dx , eax
SROM_Delay
shr ecx, 1
jnz .loop_cmd
 
; read data from SROM
 
xor esi, esi
mov ecx, 17 ;;; TODO: figure out why 17, not 16
.loop_read:
mov eax, CSR9_SR + CSR9_RD + CSR9_SROM_CS + CSR9_SROM_CK
out dx , eax
SROM_Delay
in eax, dx
and eax, CSR9_SROM_DO
shr eax, 3
shl esi, 1
or esi, eax
mov eax, CSR9_SR + CSR9_RD + CSR9_SROM_CS
out dx , eax
SROM_Delay
dec ecx
jnz .loop_read
mov eax, esi
 
DEBUGF 1,"%x\n", ax
 
ret
 
 
 
 
 
 
 
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 
 
 
;*********************************************************************
;* Media Descriptor Code *
;*********************************************************************
 
; MII transceiver control section.
; Read and write the MII registers using software-generated serial
; MDIO protocol. See the MII specifications or DP83840A data sheet
; for details.
 
; The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
; met by back-to-back PCI I/O cycles, but we insert a delay to avoid
; "overclocking" issues or future 66Mhz PCI.
 
; Read and write the MII registers using software-generated serial
; MDIO protocol. It is just different enough from the EEPROM protocol
; to not share code. The maxium data clock rate is 2.5 Mhz.
 
MDIO_SHIFT_CLK = 0x10000
MDIO_DATA_WRITE0 = 0x00000
MDIO_DATA_WRITE1 = 0x20000
MDIO_ENB = 0x00000 ; Ignore the 0x02000 databook setting.
MDIO_ENB_IN = 0x40000
MDIO_DATA_READ = 0x80000
 
; MII transceiver control section.
; Read and write the MII registers using software-generated serial
; MDIO protocol. See the MII specifications or DP83840A data sheet
; for details.
 
align 4
mdio_read: ; phy_id:edx, location:esi
 
DEBUGF 1,"mdio read, phy=%x, location=%x", edx, esi
 
shl edx, 5
or esi, edx
or esi, 0xf6 shl 10
 
set_io 0
set_io CSR9
 
; if (tp->chip_id == LC82C168) {
; int i = 1000;
; outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);
; inl(ioaddr + 0xA0);
; inl(ioaddr + 0xA0);
; while (--i > 0)
; if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))
; return retval & 0xffff;
; return 0xffff;
; }
;
; if (tp->chip_id == COMET) {
; if (phy_id == 1) {
; if (location < 7)
; return inl(ioaddr + 0xB4 + (location<<2));
; else if (location == 17)
; return inl(ioaddr + 0xD0);
; else if (location >= 29 && location <= 31)
; return inl(ioaddr + 0xD4 + ((location-29)<<2));
; }
; return 0xffff;
; }
 
; Establish sync by sending at least 32 logic ones.
 
mov ecx, 32
.loop:
mov eax, MDIO_ENB or MDIO_DATA_WRITE1
out dx, eax
MDIO_Delay
 
or eax, MDIO_SHIFT_CLK
out dx, eax
MDIO_Delay
 
dec ecx
jnz .loop
 
 
; Shift the read command bits out.
 
mov ecx, 1 shl 15
.loop2:
mov eax, MDIO_ENB
test esi, ecx
jz @f
or eax, MDIO_DATA_WRITE1
@@:
out dx, eax
MDIO_Delay
 
or eax, MDIO_SHIFT_CLK
out dx, eax
MDIO_Delay
 
shr ecx, 1
jnz .loop2
 
 
; Read the two transition, 16 data, and wire-idle bits.
 
xor esi, esi
mov ecx, 19
.loop3:
mov eax, MDIO_ENB_IN
out dx, eax
MDIO_Delay
 
shl esi, 1
in eax, dx
test eax, MDIO_DATA_READ
jz @f
inc esi
@@:
 
mov eax, MDIO_ENB_IN or MDIO_SHIFT_CLK
out dx, eax
MDIO_Delay
 
dec ecx
jnz .loop3
 
shr esi, 1
movzx eax, si
 
DEBUGF 1,", data=%x\n", ax
 
ret
 
 
 
 
align 4
mdio_write: ;int phy_id: edx, int location: edi, int value: ax)
 
DEBUGF 1,"mdio write, phy=%x, location=%x, data=%x\n", edx, edi, ax
 
shl edi, 18
or edi, 0x5002 shl 16
shl edx, 23
or edi, edx
mov di, ax
 
set_io 0
set_io CSR9
 
; if (tp->chip_id == LC82C168) {
; int i = 1000;
; outl(cmd, ioaddr + 0xA0);
; do
; if ( ! (inl(ioaddr + 0xA0) & 0x80000000))
; break;
; while (--i > 0);
; return;
; }
 
; if (tp->chip_id == COMET) {
; if (phy_id != 1)
; return;
; if (location < 7)
; outl(value, ioaddr + 0xB4 + (location<<2));
; else if (location == 17)
; outl(value, ioaddr + 0xD0);
; else if (location >= 29 && location <= 31)
; outl(value, ioaddr + 0xD4 + ((location-29)<<2));
; return;
; }
 
 
; Establish sync by sending at least 32 logic ones.
 
mov ecx, 32
.loop:
mov eax, MDIO_ENB or MDIO_DATA_WRITE1
out dx, eax
MDIO_Delay
 
or eax, MDIO_SHIFT_CLK
out dx, eax
MDIO_Delay
 
dec ecx
jnz .loop
 
 
; Shift the command bits out.
 
mov ecx, 1 shl 31
.loop2:
mov eax, MDIO_ENB
test edi, ecx
jz @f
or eax, MDIO_DATA_WRITE1
@@:
out dx, eax
MDIO_Delay
 
or eax, MDIO_SHIFT_CLK
out dx, eax
MDIO_Delay
 
shr ecx, 1
jnz .loop2
 
 
; Clear out extra bits.
 
mov ecx, 2
.loop3:
mov eax, MDIO_ENB
out dx, eax
MDIO_Delay
 
or eax, MDIO_SHIFT_CLK
out dx, eax
MDIO_Delay
 
dec ecx
jnz .loop3
 
ret
 
 
; End of code
align 4 ; Place all initialised data here
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'DEC21X4X',0 ; max 16 chars include zero
 
include_debug_strings ; All data wich FDO uses will be included here
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
 
/kernel/branches/net/drivers/forcedeth.asm
0,0 → 1,1981
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; FORCEDETH.INC ;;
;; ;;
;; Ethernet driver for Kolibri OS ;;
;; ;;
;; Driver for chips of NVIDIA nForce2 ;;
;; References: ;;
;; forcedeth.c - linux driver (etherboot project) ;;
;; ethernet driver template by Mike Hibbett ;;
;; ;;
;; The copyright statement is ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; Copyright 2008 shurf, ;;
;; cit.utc@gmail.com ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
RBLEN = 0 ; Receive buffer size: 0=4K 1=8k 2=16k 3=32k 4=64k
; FIXME: option 1 and 2 will not allocate buffer correctly causing data loss!
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
RX_RING = 4
TX_RING = 4
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
include '../struct.inc'
include 'netdrv.inc'
 
public START
public service_proc
public version
 
;**************************************************************************
; forcedeth Register Definitions
;**************************************************************************
 
PCI_DEVICE_ID_NVIDIA_NVENET_1 = 0x01c3
PCI_DEVICE_ID_NVIDIA_NVENET_2 = 0x0066
PCI_DEVICE_ID_NVIDIA_NVENET_4 = 0x0086
PCI_DEVICE_ID_NVIDIA_NVENET_5 = 0x008c
PCI_DEVICE_ID_NVIDIA_NVENET_3 = 0x00d6
PCI_DEVICE_ID_NVIDIA_NVENET_7 = 0x00df
PCI_DEVICE_ID_NVIDIA_NVENET_6 = 0x00e6
PCI_DEVICE_ID_NVIDIA_NVENET_8 = 0x0056
PCI_DEVICE_ID_NVIDIA_NVENET_9 = 0x0057
PCI_DEVICE_ID_NVIDIA_NVENET_10 = 0x0037
PCI_DEVICE_ID_NVIDIA_NVENET_11 = 0x0038
PCI_DEVICE_ID_NVIDIA_NVENET_12 = 0x0268
PCI_DEVICE_ID_NVIDIA_NVENET_13 = 0x0269
PCI_DEVICE_ID_NVIDIA_NVENET_14 = 0x0372
PCI_DEVICE_ID_NVIDIA_NVENET_15 = 0x0373
 
UNKSETUP1_VAL = 0x16070f
UNKSETUP2_VAL = 0x16
UNKSETUP3_VAL1 = 0x200010
UNKSETUP4_VAL = 8
UNKSETUP5_BIT31 = (1 shl 31)
UNKSETUP6_VAL = 3
 
TXRXCTL_RXCHECK = 0x0400
MIISTAT_ERROR = 0x0001
MIISTAT_MASK = 0x000f
MIISTAT_MASK2 = 0x000f
MIICTL_INUSE = 0x08000
MIICTL_WRITE = 0x00400
MIICTL_ADDRSHIFT = 5
 
MIISPEED_BIT8 = (1 shl 8)
MIIDELAY = 5
 
IRQ_RX_ERROR = 0x0001
IRQ_RX = 0x0002
IRQ_RX_NOBUF = 0x0004
IRQ_LINK = 0x0040
IRQ_TIMER = 0x0020
IRQMASK_WANTED_2 = 0x0147
 
IRQ_RX_ALL = IRQ_RX_ERROR or IRQ_RX or IRQ_RX_NOBUF
IRQ_TX_ALL = 0 ; ???????????
IRQ_OTHER_ALL = IRQ_LINK ;or IRQ_TIMER
 
IRQSTAT_MASK = 0x1ff
 
TXRXCTL_KICK = 0x0001
TXRXCTL_BIT1 = 0x0002
TXRXCTL_BIT2 = 0x0004
TXRXCTL_IDLE = 0x0008
TXRXCTL_RESET = 0x0010
TXRXCTL_RXCHECK = 0x0400
 
MCASTADDRA_FORCE = 0x01
 
MAC_RESET_ASSERT = 0x0F3
 
MISC1_HD = 0x02
MISC1_FORCE = 0x3b0f3c
 
PFF_ALWAYS = 0x7F0008
PFF_PROMISC = 0x80
PFF_MYADDR = 0x20
 
OFFLOAD_HOMEPHY = 0x601
OFFLOAD_NORMAL = 4096 shl RBLEN
 
RNDSEED_MASK = 0x00ff
RNDSEED_FORCE = 0x7f00
RNDSEED_FORCE2 = 0x2d00
RNDSEED_FORCE3 = 0x7400
 
; POLL_DEFAULT is the interval length of the timer source on the nic
; POLL_DEFAULT=97 would result in an interval length of 1 ms
POLL_DEFAULT = 970
 
ADAPTCTL_START = 0x02
ADAPTCTL_LINKUP = 0x04
ADAPTCTL_PHYVALID = 0x40000
ADAPTCTL_RUNNING = 0x100000
ADAPTCTL_PHYSHIFT = 24
 
WAKEUPFLAGS_VAL = 0x7770
 
POWERSTATE_POWEREDUP = 0x8000
POWERSTATE_VALID = 0x0100
POWERSTATE_MASK = 0x0003
POWERSTATE_D0 = 0x0000
POWERSTATE_D1 = 0x0001
POWERSTATE_D2 = 0x0002
POWERSTATE_D3 = 0x0003
 
POWERSTATE2_POWERUP_MASK = 0x0F11
POWERSTATE2_POWERUP_REV_A3= 0x0001
 
RCVCTL_START = 0x01
RCVSTAT_BUSY = 0x01
 
XMITCTL_START = 0x01
 
LINKSPEED_FORCE = 0x10000
LINKSPEED_10 = 1000
LINKSPEED_100 = 100
LINKSPEED_1000 = 50
 
RINGSZ_TXSHIFT = 0
RINGSZ_RXSHIFT = 16
 
LPA_1000FULL = 0x0800
 
; Link partner ability register.
LPA_SLCT = 0x001f ; Same as advertise selector
LPA_10HALF = 0x0020 ; Can do 10mbps half-duplex
LPA_10FULL = 0x0040 ; Can do 10mbps full-duplex
LPA_100HALF = 0x0080 ; Can do 100mbps half-duplex
LPA_100FULL = 0x0100 ; Can do 100mbps full-duplex
LPA_100BASE4 = 0x0200 ; Can do 100mbps 4k packets
LPA_RESV = 0x1c00 ; Unused...
LPA_RFAULT = 0x2000 ; Link partner faulted
LPA_LPACK = 0x4000 ; Link partner acked us
LPA_NPAGE = 0x8000 ; Next page bit
 
MII_READ = (-1)
MII_PHYSID1 = 0x02 ; PHYS ID 1
MII_PHYSID2 = 0x03 ; PHYS ID 2
MII_BMCR = 0x00 ; Basic mode control register
MII_BMSR = 0x01 ; Basic mode status register
MII_ADVERTISE = 0x04 ; Advertisement control reg
MII_LPA = 0x05 ; Link partner ability reg
MII_SREVISION = 0x16 ; Silicon revision
MII_RESV1 = 0x17 ; Reserved...
MII_NCONFIG = 0x1c ; Network interface config
 
; PHY defines
PHY_OUI_MARVELL = 0x5043
PHY_OUI_CICADA = 0x03f1
PHYID1_OUI_MASK = 0x03ff
PHYID1_OUI_SHFT = 6
PHYID2_OUI_MASK = 0xfc00
PHYID2_OUI_SHFT = 10
PHY_INIT1 = 0x0f000
PHY_INIT2 = 0x0e00
PHY_INIT3 = 0x01000
PHY_INIT4 = 0x0200
PHY_INIT5 = 0x0004
PHY_INIT6 = 0x02000
PHY_GIGABIT = 0x0100
 
PHY_TIMEOUT = 0x1
PHY_ERROR = 0x2
 
PHY_100 = 0x1
PHY_1000 = 0x2
PHY_HALF = 0x100
 
PHY_RGMII = 0x10000000
 
; desc_ver values:
; This field has two purposes:
; - Newer nics uses a different ring layout. The layout is selected by
; comparing np->desc_ver with DESC_VER_xy.
; - It contains bits that are forced on when writing to TxRxControl.
DESC_VER_1 = 0x0
DESC_VER_2 = (0x02100 or TXRXCTL_RXCHECK)
 
MAC_ADDR_LEN = 6
 
NV_TX_LASTPACKET = (1 shl 16)
NV_TX_RETRYERROR = (1 shl 19)
NV_TX_LASTPACKET1 = (1 shl 24)
NV_TX_DEFERRED = (1 shl 26)
NV_TX_CARRIERLOST = (1 shl 27)
NV_TX_LATECOLLISION = (1 shl 28)
NV_TX_UNDERFLOW = (1 shl 29)
NV_TX_ERROR = (1 shl 30)
NV_TX_VALID = (1 shl 31)
 
NV_TX2_LASTPACKET = (1 shl 29)
NV_TX2_RETRYERROR = (1 shl 18)
NV_TX2_LASTPACKET1 = (1 shl 23)
NV_TX2_DEFERRED = (1 shl 25)
NV_TX2_CARRIERLOST = (1 shl 26)
NV_TX2_LATECOLLISION = (1 shl 27)
NV_TX2_UNDERFLOW = (1 shl 28)
; error and valid are the same for both
NV_TX2_ERROR = (1 shl 30)
NV_TX2_VALID = (1 shl 31)
 
NV_RX_DESCRIPTORVALID = (1 shl 16)
NV_RX_AVAIL = (1 shl 31)
 
NV_RX2_DESCRIPTORVALID = (1 shl 29)
 
FLAG_MASK_V1 = 0xffff0000
FLAG_MASK_V2 = 0xffffc000
LEN_MASK_V1 = (0xffffffff xor FLAG_MASK_V1)
LEN_MASK_V2 = (0xffffffff xor FLAG_MASK_V2)
 
; Miscelaneous hardware related defines:
NV_PCI_REGSZ_VER1 = 0x270
NV_PCI_REGSZ_VER2 = 0x604
; various timeout delays: all in usec
NV_TXRX_RESET_DELAY = 4
NV_TXSTOP_DELAY1 = 10
NV_TXSTOP_DELAY1MAX = 500000
NV_TXSTOP_DELAY2 = 100
NV_RXSTOP_DELAY1 = 10
NV_RXSTOP_DELAY1MAX = 500000
NV_RXSTOP_DELAY2 = 100
NV_SETUP5_DELAY = 5
NV_SETUP5_DELAYMAX = 50000
NV_POWERUP_DELAY = 5
NV_POWERUP_DELAYMAX = 5000
NV_MIIBUSY_DELAY = 50
NV_MIIPHY_DELAY = 10
NV_MIIPHY_DELAYMAX = 10000
NV_MAC_RESET_DELAY = 64
NV_WAKEUPPATTERNS = 5
NV_WAKEUPMASKENTRIES = 4
 
; Advertisement control register.
ADVERTISE_SLCT = 0x001f ; Selector bits
ADVERTISE_CSMA = 0x0001 ; Only selector supported
ADVERTISE_10HALF = 0x0020 ; Try for 10mbps half-duplex
ADVERTISE_10FULL = 0x0040 ; Try for 10mbps full-duplex
ADVERTISE_100HALF = 0x0080 ; Try for 100mbps half-duplex
ADVERTISE_100FULL = 0x0100 ; Try for 100mbps full-duplex
ADVERTISE_100BASE4 = 0x0200 ; Try for 100mbps 4k packets
ADVERTISE_RESV = 0x1c00 ; Unused...
ADVERTISE_RFAULT = 0x2000 ; Say we can detect faults
ADVERTISE_LPACK = 0x4000 ; Ack link partners response
ADVERTISE_NPAGE = 0x8000 ; Next page bit
 
ADVERTISE_FULL = (ADVERTISE_100FULL or ADVERTISE_10FULL or ADVERTISE_CSMA)
ADVERTISE_ALL = (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL)
 
MII_1000BT_CR = 0x09
MII_1000BT_SR = 0x0a
ADVERTISE_1000FULL = 0x0200
ADVERTISE_1000HALF = 0x0100
 
BMCR_ANRESTART = 0x0200 ; Auto negotiation restart
BMCR_ANENABLE = 0x1000 ; Enable auto negotiation
BMCR_SPEED100 = 0x2000 ; Select 100Mbps
BMCR_LOOPBACK = 0x4000 ; TXD loopback bits
BMCR_RESET = 0x8000 ; Reset the DP83840
 
; Basic mode status register.
BMSR_ERCAP = 0x0001 ; Ext-reg capability
BMSR_JCD = 0x0002 ; Jabber detected
BMSR_LSTATUS = 0x0004 ; Link status
BMSR_ANEGCAPABLE = 0x0008 ; Able to do auto-negotiation
BMSR_RFAULT = 0x0010 ; Remote fault detected
BMSR_ANEGCOMPLETE = 0x0020 ; Auto-negotiation complete
BMSR_RESV = 0x07c0 ; Unused...
BMSR_10HALF = 0x0800 ; Can do 10mbps, half-duplex
BMSR_10FULL = 0x1000 ; Can do 10mbps, full-duplex
BMSR_100HALF = 0x2000 ; Can do 100mbps, half-duplex
BMSR_100FULL = 0x4000 ; Can do 100mbps, full-duplex
BMSR_100BASE4 = 0x8000 ; Can do 100mbps, 4k packets
 
struct TxDesc
PacketBuffer dd ?
FlagLen dd ?
ends
 
struct RxDesc
PacketBuffer dd ?
FlagLen dd ?
ends
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.pci_bus dd ?
.pci_dev dd ?
 
.mmio_addr dd ?
.vendor_id dw ?
.device_id dw ?
.txflags dd ?
.desc_ver dd ?
.irqmask dd ?
.wolenabled dd ?
.in_shutdown dd ?
.cur_rx dd ?
.phyaddr dd ?
.phy_oui dd ?
.gigabit dd ?
.needs_mac_reset dd ?
.linkspeed dd ?
.duplex dd ?
.next_tx dd ?
.nocable dd ?
 
rb 0x100 - (($ - device) and 0xff)
.tx_ring rd (TX_RING * sizeof.TxDesc) /4*2
 
rb 0x100 - (($ - device) and 0xff)
.rx_ring rd (RX_RING * sizeof.RxDesc) /4*2
 
sizeof.device_struct = $ - device
end virtual
 
 
virtual at edi
IrqStatus dd ?
IrqMask dd ?
UnknownSetupReg6 dd ?
PollingInterval dd ?
end virtual
 
virtual at edi + 0x3c
MacReset dd ?
end virtual
 
virtual at edi + 0x80
Misc1 dd ?
TransmitterControl dd ?
TransmitterStatus dd ?
PacketFilterFlags dd ?
OffloadConfig dd ?
ReceiverControl dd ?
ReceiverStatus dd ?
RandomSeed dd ?
UnknownSetupReg1 dd ?
UnknownSetupReg2 dd ?
MacAddrA dd ?
MacAddrB dd ?
MulticastAddrA dd ?
MulticastAddrB dd ?
MulticastMaskA dd ?
MulticastMaskB dd ?
PhyInterface dd ?
end virtual
 
virtual at edi + 0x100
TxRingPhysAddr dd ?
RxRingPhysAddr dd ?
RingSizes dd ?
UnknownTransmitterReg dd ?
LinkSpeed dd ?
end virtual
 
virtual at edi + 0x130
UnknownSetupReg5 dd ?
end virtual
 
virtual at edi + 0x13c
UnknownSetupReg3 dd ?
end virtual
 
virtual at edi + 0x144
TxRxControl dd ?
end virtual
 
virtual at edi + 0x180
MIIStatus dd ?
UnknownSetupReg4 dd ?
AdapterControl dd ?
MIISpeed dd ?
MIIControl dd ?
MIIData dd ?
end virtual
 
virtual at edi + 0x200
WakeUpFlags dd ?
end virtual
 
virtual at edi + 0x26c
PowerState dd ?
end virtual
 
virtual at edi + 0x600
PowerState2 dd ?
end virtual
 
 
section '.flat' code readable align 16
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
 
DEBUGF 2,"Loading %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
 
.exit:
xor eax, eax
ret
 
endp
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne @F
 
cmp [IOCTL.out_size], 4
jb .fail
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
 
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
 
mov eax, [IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet
 
; check if the device is already listed
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax, [eax+1]
.nextdevice:
mov ebx, [esi]
cmp al, byte [device.pci_bus] ; compare with pci and device num in device list (notice the usage of word instead of byte)
jne @f
cmp ah, byte [device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
 
 
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, sizeof.device_struct, .fail ; Allocate the buffer for device structure
 
; Fill in the direct call addresses into the struct
 
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], .fail
mov [device.name], my_service
 
; save the pci bus and device numbers
 
mov eax, [IOCTL.input]
movzx ecx, byte [eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte [eax+2]
mov [device.pci_dev], ecx
 
DEBUGF 1,"Hooking into device, dev:%x, bus:%x\n", [device.pci_dev], [device.pci_bus]
 
; Ok, the eth_device structure is ready, let's probe the device
call probe ; this function will output in eax
test eax, eax
jnz .err ; If an error occured, exit
 
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
cmp eax, -1
je .destroy
 
ret
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 1,"Trying to find device number of already registered device\n"
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 1,"Kernel says: %u\n", eax
ret
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
; todo: reset device into virgin state
 
.err:
stdcall KernelFree, ebx
.fail:
 
ret
 
;------------------------------------------------------
endp
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
 
 
;***************************************************************************
; Function
; probe
; Description
; Searches for an ethernet card, enables it and clears the rx buffer
;
;***************************************************************************
align 4
probe:
 
DEBUGF 1,"probe\n"
 
mov [device.needs_mac_reset], 0
 
PCI_make_bus_master
PCI_adjust_latency 32
PCI_find_mmio32
 
DEBUGF 1,"mmio_addr= 0x%x\n", [device.mmio_addr]:8
 
stdcall MapIoMem, [device.mmio_addr], 2048, (PG_SW + PG_NOCACHE)
test eax, eax
jz fail
mov [device.mmio_addr], eax
mov edi, eax
 
DEBUGF 1,"mapped mmio_addr= 0x%x\n", [device.mmio_addr]:8
 
;-------------------------------------
; handle different descriptor versions
mov [device.desc_ver], DESC_VER_1
movzx eax, [device.device_id]
cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_1
je .ver1
cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_2
je .ver1
cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_3
je .ver1
mov [device.desc_ver], DESC_VER_2
.ver1:
 
call read_mac
 
; disable WOL
mov [WakeUpFlags], 0
mov [device.wolenabled], 0
mov [device.txflags], (NV_TX2_LASTPACKET or NV_TX2_VALID)
cmp [device.desc_ver], DESC_VER_1
jne @f
mov [device.txflags], (NV_TX_LASTPACKET or NV_TX_VALID)
@@:
 
; BEGIN of switch (pci->dev_id)
 
cmp [device.device_id], 0x01C3
jne .next_0x0066
; nforce
mov [device.irqmask], 0 ;;;;;;;;;;;;;;;(IRQMASK_WANTED_2 or IRQ_TIMER)
jmp .find_phy
 
.next_0x0066:
cmp [device.device_id], 0x0066
je @f
cmp [device.device_id], 0x00D6
je @f
jmp .next_0x0086
@@:
mov [device.irqmask], 0 ;;;;;;;;;;;;;;;;(IRQMASK_WANTED_2 or IRQ_TIMER)
cmp [device.desc_ver], DESC_VER_1
jne @f
or [device.txflags], NV_TX_LASTPACKET1
jmp .find_phy
@@:
or [device.txflags], NV_TX2_LASTPACKET1
jmp .find_phy
 
.next_0x0086:
cmp [device.device_id], 0x0086
je @f
cmp [device.device_id], 0x008c
je @f
cmp [device.device_id], 0x00e6
je @f
cmp [device.device_id], 0x00df
je @f
cmp [device.device_id], 0x0056
je @f
cmp [device.device_id], 0x0057
je @f
cmp [device.device_id], 0x0037
je @f
cmp [device.device_id], 0x0038
je @f
jmp .find_phy
 
@@:
mov [device.irqmask], 0 ;;;;;;;;;;;;;;;;(IRQMASK_WANTED_2 or IRQ_TIMER)
 
cmp [device.desc_ver], DESC_VER_1
jne @f
or [device.txflags], NV_TX_LASTPACKET1
jmp .find_phy
@@:
or [device.txflags], NV_TX2_LASTPACKET1
jmp .find_phy
 
.next_0x0268:
; cmp word [device_id], 0x0268
; je @f
; cmp word [device_id], 0x0269
; je @f
; cmp word [device_id], 0x0372
; je @f
; cmp word [device_id], 0x0373
; je @f
; jmp .default_switch
;@@:
cmp [device.device_id], 0x0268
jb .undefined
 
; Get device revision
 
stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REVISION_ID
 
; take phy and nic out of low power mode
mov ecx, [PowerState2]
and ecx, not POWERSTATE2_POWERUP_MASK
cmp [device.device_id], PCI_DEVICE_ID_NVIDIA_NVENET_12
jne @f
cmp [device.device_id], PCI_DEVICE_ID_NVIDIA_NVENET_13
jne @f
cmp al, 0xA3
jb @f
or ecx, POWERSTATE2_POWERUP_REV_A3
@@:
mov [PowerState2], ecx
 
; DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ
mov [device.irqmask], 0 ;;;;;;;;;;;;;;;;(IRQMASK_WANTED_2 or IRQ_TIMER)
mov [device.needs_mac_reset], 1
cmp [device.desc_ver], DESC_VER_1
jne @f
or [device.txflags], NV_TX_LASTPACKET1
jmp .find_phy
@@:
cmp [device.desc_ver], DESC_VER_2
jne .undefined
or [device.txflags], NV_TX2_LASTPACKET1
jmp .find_phy
 
.undefined:
DEBUGF 1,"Your card was undefined in this driver.\n"
DEBUGF 1,"Review driver_data in Kolibri driver and send a patch\n"
 
; Find a suitable phy
; Start with address 1 to 31, then do 0, then fail
 
.find_phy:
xor edx, edx
.phy_loop:
inc edx
and edx, 0x1f ; phyaddr = i & 0x1f
mov eax, MII_PHYSID1
mov ecx, MII_READ
call mii_rw ; EDX - addr, EAX - miireg, ECX - value
 
cmp eax, 0xffff
je .try_next
cmp eax, 0
jl .try_next
mov esi, eax
 
mov eax, MII_PHYSID2
mov ecx, MII_READ
call mii_rw
 
cmp eax, 0xffff
je .try_next
cmp eax, 0
jl .try_next
jmp .got_it
 
.try_next:
test edx, edx
jnz .phy_loop
 
; PHY in isolate mode? No phy attached and user wants to test loopback?
; Very odd, but can be correct.
DEBUGF 1,"Could not find a valid PHY.\n"
jmp .no_phy
 
.got_it:
 
and esi, PHYID1_OUI_MASK
shl esi, PHYID1_OUI_SHFT
 
and eax, PHYID2_OUI_MASK
shr eax, PHYID2_OUI_SHFT
 
DEBUGF 1,"Found PHY 0x%x:0x%x at address 0x%x\n", esi:8, eax:8, edx
 
mov [device.phyaddr], edx
or eax, esi
mov [device.phy_oui], eax
 
call phy_init
 
.no_phy:
 
cmp [device.needs_mac_reset], 0
je @f
call mac_reset
@@:
;***************************************************************************
; Function
; reset
; Description
; Place the chip (ie, the ethernet card) into a virgin state
; No inputs
; All registers destroyed
;
;***************************************************************************
reset:
 
DEBUGF 1,"Resetting\n"
 
stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REG_IRQ
movzx eax, al
stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax
jnz @f
DEBUGF 1,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
; erase previous misconfiguration
 
mov edi, [device.mmio_addr]
mov [MulticastAddrA], MCASTADDRA_FORCE
mov [MulticastAddrB], 0
mov [MulticastMaskA], 0
mov [MulticastMaskB], 0
mov [PacketFilterFlags], 0
mov [TransmitterControl], 0
mov [ReceiverControl], 0
mov [AdapterControl], 0
 
; initialize descriptor rings
 
call init_ring
 
mov [LinkSpeed], 0
mov [UnknownTransmitterReg], 0
 
call txrx_reset
mov [UnknownSetupReg6], 0
mov [device.in_shutdown], 0
 
; give hw rings
 
lea eax, [device.rx_ring]
GetRealAddr
mov [RxRingPhysAddr], eax
 
lea eax, [device.tx_ring]
GetRealAddr
mov [TxRingPhysAddr], eax
 
mov [RingSizes], (((RX_RING - 1) shl RINGSZ_RXSHIFT) + ((TX_RING - 1) shl RINGSZ_TXSHIFT))
 
;
 
mov [device.linkspeed], (LINKSPEED_FORCE or LINKSPEED_10)
mov [device.duplex], 0
mov [LinkSpeed], (LINKSPEED_FORCE or LINKSPEED_10)
mov [UnknownSetupReg3], UNKSETUP3_VAL1
 
mov eax, [device.desc_ver]
mov [TxRxControl], eax
call pci_push
or eax, TXRXCTL_BIT1
mov [TxRxControl], eax
 
stdcall reg_delay, UnknownSetupReg5-edi, UNKSETUP5_BIT31, UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, 0
 
mov [UnknownSetupReg4], 0
mov [MIIStatus], MIISTAT_MASK2
 
;
mov [Misc1], (MISC1_FORCE or MISC1_HD)
 
mov eax, [TransmitterStatus]
mov [TransmitterStatus], eax
 
mov [PacketFilterFlags], PFF_ALWAYS
 
mov [OffloadConfig], OFFLOAD_NORMAL
 
mov eax, [ReceiverStatus]
mov [ReceiverStatus], eax
 
; set random seed
push ebx
stdcall GetTimerTicks ; bad idea, driver is started at system startup in 90% of cases..
pop ebx
 
mov edi, [device.mmio_addr]
 
and eax, RNDSEED_MASK
or eax, RNDSEED_FORCE
mov [RandomSeed], eax
 
mov [UnknownSetupReg1], UNKSETUP1_VAL
mov [UnknownSetupReg2], UNKSETUP2_VAL
mov [PollingInterval], POLL_DEFAULT
mov [UnknownSetupReg6], UNKSETUP6_VAL
 
mov eax, [device.phyaddr]
shl eax, ADAPTCTL_PHYSHIFT
or eax, (ADAPTCTL_PHYVALID or ADAPTCTL_RUNNING)
mov [AdapterControl], eax
 
mov [MIISpeed], (MIISPEED_BIT8 or MIIDELAY)
mov [UnknownSetupReg4], UNKSETUP4_VAL
mov [WakeUpFlags], WAKEUPFLAGS_VAL
or [PowerState], POWERSTATE_POWEREDUP
call pci_push
 
mov esi, 10
call Sleep
 
or [PowerState], POWERSTATE_VALID
mov [IrqMask], 0
 
;;; ; ??? Mask RX interrupts
mov [IrqMask], IRQ_RX_ALL + IRQ_TX_ALL
;;; ; ??? Mask TX interrupts
;;; mov [IrqMask], IRQ_TX_ALL
;;; ; ??? Mask OTHER interrupts
;;; mov [IrqMask], IRQ_OTHER_ALL
call pci_push
 
mov [MIIStatus], MIISTAT_MASK2
mov [IrqStatus], IRQSTAT_MASK
call pci_push
 
mov [MulticastAddrA], MCASTADDRA_FORCE
mov [MulticastAddrB], 0
mov [MulticastMaskA], 0
mov [MulticastMaskB], 0
 
mov [PacketFilterFlags], (PFF_ALWAYS or PFF_MYADDR)
 
call set_multicast
; One manual link speed update: Interrupts are enabled, future link
; speed changes cause interrupts and are handled by nv_link_irq().
 
mov eax, [MIIStatus]
mov [MIIStatus], MIISTAT_MASK
DEBUGF 1,"startup: got 0x%x\n", eax
 
call update_linkspeed
 
mov [TransmitterControl], XMITCTL_START ; start TX
call pci_push
 
mov [device.nocable], 0
test eax, eax
jnz .return
DEBUGF 1,"no link during initialization.\n"
mov [device.nocable], 1
 
.return:
xor eax, eax ; Indicate that we have successfully reset the card
mov [device.mtu], 1514 ;;; FIXME
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
ret
 
 
fail:
or eax, -1
 
ret
 
;--------------------------------------------------------
;
; MII_RW
;
; read/write a register on the PHY.
; Caller must guarantee serialization
; Input: EAX - miireg, EDX - addr, ECX - value
; Output: EAX - retval
;
;--------------------------------------------------------
 
mii_rw:
 
DEBUGF 1,"mii_rw: 0x%x to reg %d at PHY %d\n", ecx, eax, edx
 
push edx
 
mov edi, [device.mmio_addr]
mov [MIIStatus], MIISTAT_MASK
 
test [MIIControl], MIICTL_INUSE
jz @f
mov [MIIControl], MIICTL_INUSE
 
mov esi, NV_MIIBUSY_DELAY
call Sleep
@@:
 
shl edx, MIICTL_ADDRSHIFT
or edx, eax
 
cmp ecx, MII_READ
je @f
 
mov [MIIData], ecx
or edx, MIICTL_WRITE
@@:
mov [MIIControl], edx
 
stdcall reg_delay, MIIControl-edi, MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, 0
 
test eax, eax
jz @f
DEBUGF 1,"mii_rw timed out.\n"
or eax, -1
jmp .return
@@:
 
cmp ecx, MII_READ
je @f
; it was a write operation - fewer failures are detectable
DEBUGF 1,"mii_rw write: ok\n"
xor eax, eax
jmp .return
@@:
 
mov eax, [MIIStatus]
test eax, MIISTAT_ERROR
jz @f
DEBUGF 1,"mii read: failed.\n"
or eax, -1
jmp .return
@@:
 
mov eax, [MIIData]
DEBUGF 1,"mii read: 0x%x.\n", eax
 
.return:
pop edx
ret
 
 
 
 
 
; Input: offset:word, mask:dword, target:dword, delay:word, delaymax:word, msg:dword
; Output: EAX - 0|1
 
proc reg_delay, offset:dword, mask:dword, target:dword, delay:dword, delaymax:dword, msg:dword
 
; DEBUGF 1,"reg_delay\n"
 
push esi
call pci_push
 
.loop:
mov esi, [delay]
call Sleep
mov eax, [delaymax]
sub eax, [delay]
mov [delaymax], eax
 
cmp eax, 0
jl .fail
 
mov eax, [offset]
mov eax, [edi + eax]
and eax, [mask]
cmp eax, [target]
jne .loop
 
pop esi
xor eax, eax
ret
 
.fail:
pop esi
xor eax, eax
inc eax
ret
 
endp
 
 
 
 
 
; Input: none
; Output: EAX - result (0 = OK, other = error)
phy_init:
 
push ebx ecx
; set advertise register
mov edx, [device.phyaddr]
mov eax, MII_ADVERTISE
mov ecx, MII_READ
call mii_rw
 
or eax, (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or 0x800 or 0x400)
 
mov ecx, eax
mov eax, MII_ADVERTISE
call mii_rw
 
test eax, eax
jz @f
 
DEBUGF 1,"phy write to advertise failed.\n"
 
mov eax, PHY_ERROR
jmp .return
@@:
 
; get phy interface type
mov edi, [device.mmio_addr]
mov eax, [PhyInterface]
DEBUGF 1,"phy interface type = 0x%x\n", eax:8
 
; see if gigabit phy
mov eax, MII_BMSR
mov ecx, MII_READ
call mii_rw
test eax, PHY_GIGABIT
jnz .gigabit
mov [device.gigabit], 0
jmp .next_if
 
.gigabit:
mov [device.gigabit], PHY_GIGABIT
 
mov eax, MII_1000BT_CR
mov ecx, MII_READ
call mii_rw
and eax, (not ADVERTISE_1000HALF)
 
test [PhyInterface], PHY_RGMII
jz @f
or eax, ADVERTISE_1000FULL
jmp .next
@@:
 
and eax, (not ADVERTISE_1000FULL)
 
.next:
mov ecx, eax
mov eax, MII_1000BT_CR
call mii_rw
 
test eax, eax
jz .next_if
 
DEBUGF 1,"phy init failed.\n"
 
mov eax, PHY_ERROR
jmp .return
 
.next_if:
 
call phy_reset
test eax, eax
jz @f
 
DEBUGF 1,"phy reset failed.\n"
 
mov eax, PHY_ERROR
jmp .return
@@:
 
; phy vendor specific configuration
cmp [device.phy_oui], PHY_OUI_CICADA
jne .next_if2
test [PhyInterface], PHY_RGMII
jz .next_if2
 
mov eax, MII_RESV1
mov ecx, MII_READ
call mii_rw
 
and eax, (not (PHY_INIT1 or PHY_INIT2))
or eax, (PHY_INIT3 or PHY_INIT4)
mov ecx, eax
mov eax, MII_RESV1
call mii_rw
 
test eax, eax
jz @f
 
DEBUGF 1,"phy init failed.\n"
 
mov eax, PHY_ERROR
jmp .return
@@:
 
mov eax, MII_NCONFIG
mov ecx, MII_READ
call mii_rw
 
or eax, PHY_INIT5
mov ecx, eax
mov eax, MII_NCONFIG
call mii_rw
test eax, eax
jz .next_if2
 
DEBUGF 1,"phy init failed.\n"
 
mov eax, PHY_ERROR
jmp .return
 
 
 
.next_if2:
 
cmp [device.phy_oui], PHY_OUI_CICADA
jne .restart
mov eax, MII_SREVISION
mov ecx, MII_READ
call mii_rw
or eax, PHY_INIT6
mov ecx, eax
mov eax, MII_SREVISION
call mii_rw
test eax, eax
jz .restart
 
DEBUGF 1,"phy init failed.\n"
 
jmp .return
 
.restart:
; restart auto negotiation
 
mov eax, MII_BMCR
mov ecx, MII_READ
call mii_rw
 
or eax, (BMCR_ANRESTART or BMCR_ANENABLE)
mov ecx, eax
mov eax, MII_BMCR
call mii_rw
test eax, eax
jz .ok
 
mov eax, PHY_ERROR
jmp .return
 
.ok:
xor eax, eax
.return:
pop ecx ebx
 
ret
 
 
; Input: none
; Output: EAX - result (0 = OK, other = error)
phy_reset:
 
DEBUGF 1,"phy_reset\n"
 
push ebx ecx edx
 
mov edx, [device.phyaddr]
mov eax, MII_BMCR
mov ecx, MII_READ
call mii_rw
 
or eax, BMCR_RESET
push eax
mov ecx, eax
mov eax, MII_BMCR
call mii_rw
 
test eax, eax
jz @f
 
pop eax
mov eax, 0xffffffff
jmp .return
@@:
 
pop eax
 
mov esi, 500
call Sleep
 
; must wait till reset is deasserted
mov esi, 100 ; FIXME: 100 tries seem excessive
.while_loop:
test eax, BMCR_RESET
jz .while_loop_exit
 
push esi
mov esi, 10
call Sleep
pop esi
 
mov eax, MII_BMCR
mov ecx, MII_READ
call mii_rw
 
dec esi
jnz .while_loop
 
mov eax, 0xffffffff
jmp .return
 
.while_loop_exit:
xor eax, eax
.return:
pop edx ecx ebx
 
ret
 
 
align 4
pci_push:
 
push eax
mov eax, [edi]
pop eax
 
ret
 
 
 
 
align 4
mac_reset:
 
push esi edi
 
DEBUGF 1,"mac_reset.\n"
 
mov edi, [device.mmio_addr]
mov eax, [device.desc_ver]
or eax, (TXRXCTL_BIT2 or TXRXCTL_RESET)
mov [TxRxControl], eax
call pci_push
 
mov [MacReset], MAC_RESET_ASSERT
call pci_push
 
mov esi, NV_MAC_RESET_DELAY
call Sleep
 
mov [MacReset], 0
call pci_push
 
mov esi, NV_MAC_RESET_DELAY
call Sleep
 
mov eax, [device.desc_ver]
or eax, TXRXCTL_BIT2
mov [TxRxControl], eax
call pci_push
 
pop edi esi
 
ret
 
 
 
 
 
align 4
init_ring:
 
DEBUGF 1,"init rings\n"
push eax esi ecx
 
mov [device.next_tx], 0
 
mov ecx, TX_RING
lea esi, [device.tx_ring]
.tx_loop:
mov [esi + TxDesc.FlagLen], 0
add esi, sizeof.TxDesc
dec ecx
jnz .tx_loop
 
mov [device.cur_rx], 0
 
mov ecx, RX_RING
lea esi, [device.rx_ring]
.rx_loop:
push ecx esi
stdcall KernelAlloc, 4096 shl RBLEN ; push/pop esi not needed, but just in case...
pop esi
mov [esi + RX_RING*sizeof.RxDesc], eax
GetRealAddr
mov [esi + RxDesc.PacketBuffer], eax
mov [esi + RxDesc.FlagLen], (4096 shl RBLEN or NV_RX_AVAIL)
add esi, sizeof.RxDesc
pop ecx
dec ecx
jnz .rx_loop
pop ecx esi eax
 
ret
 
 
 
 
 
; Input: none
; Output: none
align 4
txrx_reset:
 
push eax esi
 
DEBUGF 1,"txrx_reset\n"
 
mov edi, [device.mmio_addr]
mov eax, [device.desc_ver]
or eax, (TXRXCTL_BIT2 or TXRXCTL_RESET)
mov [TxRxControl], eax
call pci_push
 
mov esi, NV_TXRX_RESET_DELAY
call Sleep
 
mov eax, [device.desc_ver]
or eax, TXRXCTL_BIT2
mov [TxRxControl], eax
call pci_push
 
pop esi eax
 
ret
 
 
 
 
 
; Input: none
; Output: none
set_multicast:
 
; u32 addr[2];
; u32 mask[2];
; u32 pff;
; u32 alwaysOff[2];
; u32 alwaysOn[2];
;
; memset(addr, 0, sizeof(addr));
; memset(mask, 0, sizeof(mask));
;
; pff = PFF_MYADDR;
;
; alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0;
;
; addr[0] = alwaysOn[0];
; addr[1] = alwaysOn[1];
; mask[0] = alwaysOn[0] | alwaysOff[0];
; mask[1] = alwaysOn[1] | alwaysOff[1];
;
; addr[0] |= MCASTADDRA_FORCE;
; pff |= PFF_ALWAYS;
 
call stop_rx
 
mov edi, [device.mmio_addr]
mov [MulticastAddrA], MCASTADDRA_FORCE
 
mov [MulticastAddrB], 0
mov [MulticastMaskA], 0
mov [MulticastMaskB], 0
mov [PacketFilterFlags], (PFF_MYADDR or PFF_ALWAYS)
 
call start_rx
 
ret
 
 
 
 
 
; Input: none
; Output: none
start_rx:
 
push edi
 
DEBUGF 1,"start_rx\n"
 
; Already running? Stop it.
mov edi, [device.mmio_addr]
mov eax, [ReceiverControl]
test eax, RCVCTL_START
jz @f
mov [ReceiverControl], 0
call pci_push
@@:
 
mov eax, [device.linkspeed]
mov [LinkSpeed], eax
call pci_push
 
mov [ReceiverControl], RCVCTL_START
call pci_push
 
pop edi
 
ret
 
 
 
 
; Input: none
; Output: none
stop_rx:
 
push esi edi
 
DEBUGF 1,"stop_rx.\n"
 
mov edi, [device.mmio_addr]
mov [ReceiverControl], 0
 
push ebx edx edi
stdcall reg_delay, ReceiverStatus-edi, RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, 0
pop edi edx ebx
 
mov esi, NV_RXSTOP_DELAY2
call Sleep
 
mov [LinkSpeed], 0
 
pop edi esi
 
ret
 
 
 
 
; Input: none
; Output: EAX
update_linkspeed:
 
DEBUGF 1,"update linkspeed\n"
 
; BMSR_LSTATUS is latched, read it twice: we want the current value.
mov edx, [device.phyaddr]
mov eax, MII_BMSR
mov ecx, MII_READ
call mii_rw
 
mov eax, MII_BMSR
mov ecx, MII_READ
call mii_rw
test eax, BMSR_LSTATUS ; Link up?
jz .10mbit_hd
 
test eax, BMSR_ANEGCOMPLETE ; still in autonegotiation?
jz .10mbit_hd
 
cmp [device.gigabit], PHY_GIGABIT
jne .no_gigabit
 
;mov edx, [device.phyaddr]
mov eax, MII_1000BT_CR
mov ecx, MII_READ
call mii_rw
push eax
 
;mov edx, [device.phyaddr]
mov eax, MII_1000BT_SR
mov ecx, MII_READ
call mii_rw
pop ecx
 
test eax, LPA_1000FULL
jz .no_gigabit
test ecx, ADVERTISE_1000FULL
jz .no_gigabit
 
DEBUGF 1,"update_linkspeed: GBit ethernet detected.\n"
mov ecx, (LINKSPEED_FORCE or LINKSPEED_1000)
xor eax, eax
inc eax
jmp set_speed
.no_gigabit:
 
;mov edx, [device.phyaddr]
mov eax, MII_ADVERTISE
mov ecx, MII_READ
call mii_rw ; adv = eax
push eax
 
;mov edx, [device.phyaddr]
mov eax, MII_LPA
mov ecx, MII_READ
call mii_rw ; lpa = eax
pop ecx
 
DEBUGF 1,"PHY advertises 0x%x, lpa 0x%x\n", ecx, eax
and eax, ecx ; FIXME: handle parallel detection properly, handle gigabit ethernet
 
test eax, LPA_100FULL
jz @f
DEBUGF 1,"update_linkspeed: 100 mbit full duplex\n"
mov ecx, (LINKSPEED_FORCE or LINKSPEED_100)
xor eax, eax
inc eax
jmp set_speed
@@:
 
test eax, LPA_100HALF
jz @f
DEBUGF 1,"update_linkspeed: 100 mbit half duplex\n"
mov ecx, (LINKSPEED_FORCE or LINKSPEED_100)
xor eax, eax
jmp set_speed
@@:
 
test eax, LPA_10FULL
jz @f
DEBUGF 1,"update_linkspeed: 10 mbit full duplex\n"
mov ecx, (LINKSPEED_FORCE or LINKSPEED_10)
xor eax, eax
inc eax
jmp set_speed
@@:
 
.10mbit_hd:
DEBUGF 1,"update_linkspeed: 10 mbit half duplex\n"
mov ecx, (LINKSPEED_FORCE or LINKSPEED_10)
xor eax, eax
jmp set_speed
 
 
align 4
set_speed:
 
cmp eax, [device.duplex]
jne .update
cmp ecx, [device.linkspeed]
jne .update
 
ret
 
.update:
DEBUGF 1,"update_linkspeed: changing link to 0x%x/XD.\n", ecx
mov [device.duplex], eax
mov [device.linkspeed], ecx
cmp [device.gigabit], PHY_GIGABIT
jne .no_gigabit
 
mov edi, [device.mmio_addr]
mov eax, [RandomSeed]
 
and eax, not (0x3FF00)
mov ecx, eax ; phyreg = ecx
 
mov eax, [device.linkspeed]
and eax, 0xFFF
cmp eax, LINKSPEED_10
jne @f
or ecx, RNDSEED_FORCE3
jmp .end_if4
@@:
 
cmp eax, LINKSPEED_100
jne @f
or ecx, RNDSEED_FORCE2
jmp .end_if4
@@:
 
cmp eax, LINKSPEED_1000
jne .end_if4
or ecx, RNDSEED_FORCE
.end_if4:
mov [RandomSeed], ecx
.no_gigabit:
 
mov ecx, [PhyInterface]
and ecx, not (PHY_HALF or PHY_100 or PHY_1000)
 
cmp [device.duplex], 0
jne @f
or ecx, PHY_HALF
@@:
 
mov eax, [device.linkspeed]
and eax, 0xFFF
cmp eax, LINKSPEED_100
jne @f
or ecx, PHY_100
jmp .end_if5
@@:
 
cmp eax, LINKSPEED_1000
jne .end_if5
or ecx, PHY_1000
 
.end_if5:
mov [PhyInterface], ecx
cmp [device.duplex], 0
je @f
xor ecx, ecx
jmp .next
@@:
 
mov ecx, MISC1_HD
.next:
or ecx, MISC1_FORCE
mov [Misc1], ecx
 
call pci_push
 
mov eax, [device.linkspeed]
mov [LinkSpeed], eax
 
call pci_push
 
ret
 
 
 
 
 
 
align 4
read_mac:
 
mov edi, [device.mmio_addr]
 
mov eax, [MacAddrA]
mov ecx, [MacAddrB]
 
mov dword [device.mac], eax
mov word [device.mac + 4], cx
 
cmp [device.device_id], 0x03E5
jae @f
bswap eax
xchg cl, ch
mov dword [device.mac + 2], eax
mov word [device.mac], cx
@@:
 
DEBUGF 1,"MAC = %x-%x-%x-%x-%x-%x\n", \
[device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
transmit:
DEBUGF 2,"\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
DEBUGF 2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
 
cmp dword [esp + 8], 1514
ja .fail
cmp dword [esp + 8], 60
jb .fail
 
; get the descriptor address
mov eax, [device.next_tx]
mov cl, sizeof.TxDesc
mul cl
lea esi, [device.tx_ring + eax]
mov eax, [esp + 4]
mov [esi + TX_RING*sizeof.TxDesc], eax
GetRealAddr
mov [esi + TxDesc.PacketBuffer], eax
 
mov ecx, [esp + 8]
or ecx, [device.txflags]
mov [esi + TxDesc.FlagLen], eax
 
mov edi, [device.mmio_addr]
mov eax, [device.desc_ver]
or eax, TXRXCTL_KICK
mov [TxRxControl], eax
 
call pci_push
 
inc [device.next_tx]
and [device.next_tx], (TX_RING-1)
 
; Update stats
inc [device.packets_tx]
mov eax, [esp + 8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
xor eax, eax
ret 8
 
.fail:
xor eax, eax
inc eax
ret 8
 
 
 
 
 
 
; Interrupt handler
align 4
int_handler:
DEBUGF 2,"\n%s INT\n", my_service
 
;-------------------------------------------
; Find pointer of device wich made IRQ occur
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .fail
.nextdevice:
mov ebx, dword [esi]
add esi, 4
 
mov edi, [device.mmio_addr]
mov eax, [IrqStatus]
test eax, eax
jnz .got_it
dec ecx
jnz .nextdevice
ret
 
.got_it:
mov [IrqStatus], eax
DEBUGF 2,"IrqStatus = %x\n", eax
 
test eax, IRQ_RX
jz .no_rx
 
.top:
mov eax, [device.cur_rx]
mov cx, sizeof.RxDesc
mul cx
lea esi, [device.rx_ring + eax]
mov eax, [esi + RxDesc.FlagLen]
 
test eax, NV_RX_AVAIL ; still owned by hardware
jnz .return0
 
cmp [device.desc_ver], DESC_VER_1
jne @f
test eax, NV_RX_DESCRIPTORVALID
jz .return0
jmp .next
@@:
test eax, NV_RX2_DESCRIPTORVALID
jz .return0
 
.next:
 
cmp dword [device.desc_ver], DESC_VER_1
jne @f
and eax, LEN_MASK_V1
jmp .next2
@@:
and eax, LEN_MASK_V2
.next2:
 
; got a valid packet - forward it to the network core
push .top
push eax
push dword [esi + RX_RING*sizeof.RxDesc]
 
inc [device.cur_rx]
and [device.cur_rx], (RX_RING-1)
 
; Allocate new buffer
 
stdcall KernelAlloc, 4096 shl RBLEN
mov [esi + RX_RING*sizeof.RxDesc], eax
GetRealAddr
mov [esi + RxDesc.PacketBuffer], eax
mov [esi + RxDesc.FlagLen], (4096 shl RBLEN or NV_RX_AVAIL)
 
jmp Eth_input
 
.return0:
 
 
.no_rx:
test eax, IRQ_RX_ERROR
jz .no_rx_err
 
push eax
DEBUGF 2,"RX error!\n"
 
mov eax, [device.cur_rx]
mov cx, sizeof.RxDesc
mul cx
lea esi, [device.rx_ring + eax]
mov eax, [esi + RxDesc.FlagLen]
 
DEBUGF 2,"Flaglen=%x\n", eax
 
; TODO: allocate new buff
pop eax
 
.no_rx_err:
test eax, IRQ_LINK
jz .no_link
 
push eax
call update_linkspeed
pop eax
 
.no_link:
.fail:
 
ret
 
 
 
 
; End of code
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
align 4 ; Place all initialised data here
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'FORCEDETH',0 ; max 16 chars include zero
 
include_debug_strings ; All data wich FDO uses will be included here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
/kernel/branches/net/drivers/i8255x.asm
0,0 → 1,1245
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; i8255x (Intel eepro 100) driver for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; Some parts of this driver are based on the code of eepro100.c ;;
;; from linux. ;;
;; ;;
;; Intel's programming manual for i8255x: ;;
;; http://www.intel.com/design/network/manuals/8255x_opensdm.htm ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
 
public START
public service_proc
public version
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.io_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
 
.rx_desc dd ?
 
.ee_bus_width db ?
 
rb 0x100 - (($ - device) and 0xff)
 
txfd:
.status dw ?
.command dw ?
.link dd ?
.tx_desc_addr dd ?
.count dd ?
 
.tx_buf_addr0 dd ?
.tx_buf_size0 dd ?
 
rb 0x100 - (($ - device) and 0xff)
 
confcmd:
.status dw ?
.command dw ?
.link dd ?
.data rb 64
 
rb 0x100 - (($ - device) and 0xff)
 
lstats:
tx_good_frames dd ?
tx_coll16_errs dd ?
tx_late_colls dd ?
tx_underruns dd ?
tx_lost_carrier dd ?
tx_deferred dd ?
tx_one_colls dd ?
tx_multi_colls dd ?
tx_total_colls dd ?
 
rx_good_frames dd ?
rx_crc_errs dd ?
rx_align_errs dd ?
rx_resource_errs dd ?
rx_overrun_errs dd ?
rx_colls_errs dd ?
rx_runt_errs dd ?
 
last_tx_buffer dd ? ;;; fixme
 
sizeof.device_struct = $ - device
 
end virtual
 
 
virtual at 0
 
rxfd:
.status dw ?
.command dw ?
.link dd ?
.rx_buf_addr dd ?
.count dw ?
.size dw ?
.packet:
 
end virtual
 
 
; Serial EEPROM
 
EE_SK = 1 shl 0 ; serial clock
EE_CS = 1 shl 1 ; chip select
EE_DI = 1 shl 2 ; data in
EE_DO = 1 shl 3 ; data out
EE_MASK = EE_SK + EE_CS + EE_DI + EE_DO
 
; opcodes, first bit is start bit and must be 1
EE_READ = 110b
EE_WRITE = 101b
EE_ERASE = 111b
 
; The SCB accepts the following controls for the Tx and Rx units:
 
CU_START = 0x0010
CU_RESUME = 0x0020
CU_STATSADDR = 0x0040
CU_SHOWSTATS = 0x0050 ; Dump statistics counters.
CU_CMD_BASE = 0x0060 ; Base address to add CU commands.
CU_DUMPSTATS = 0x0070 ; Dump then reset stats counters.
 
RX_START = 0x0001
RX_RESUME = 0x0002
RX_ABORT = 0x0004
RX_ADDR_LOAD = 0x0006
RX_RESUMENR = 0x0007
INT_MASK = 0x0100
DRVR_INT = 0x0200 ; Driver generated interrupt
 
CmdIASetup = 0x0001
CmdConfigure = 0x0002
CmdTx = 0x0004
CmdTxFlex = 0x0008
Cmdsuspend = 0x4000
 
 
reg_scb_status = 0
reg_scb_cmd = 2
reg_scb_ptr = 4
reg_port = 8
reg_eeprom = 14
reg_mdi_ctrl = 16
 
 
macro delay {
push eax
in ax, dx
in ax, dx
in ax, dx
in ax, dx
in ax, dx
in ax, dx
in ax, dx
in ax, dx
in ax, dx
in ax, dx
pop eax
}
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
 
.entry:
 
DEBUGF 1,"Loading %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
 
.fail:
.exit:
xor eax, eax
ret
 
endp
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne @F
 
cmp [IOCTL.out_size], 4
jb .fail
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
 
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
 
mov eax, [IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet
 
; check if the device is already listed
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax , [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
 
 
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, sizeof.device_struct, .fail ; Allocate the buffer for device structure
 
; Fill in the direct call addresses into the struct
 
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], unload
mov [device.name], my_service
 
; save the pci bus and device numbers
 
mov eax, [IOCTL.input]
movzx ecx, byte[eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte[eax+2]
mov [device.pci_dev], ecx
 
; Now, it's time to find the base io addres of the PCI device
 
PCI_find_io
 
; We've found the io address, find IRQ now
 
PCI_find_irq
 
DEBUGF 2,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
 
; Ok, the eth_device structure is ready, let's probe the device
 
pushf
cli ; disable ints until initialisation is done
 
call probe ; this function will output in eax
test eax, eax
jnz .err ; If an error occured, exit
 
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
 
popf
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
cmp eax, -1
je .err
 
ret
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 2,"Trying to find device number of already registered device\n"
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 2,"Kernel says: %u\n", eax
ret
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.err:
stdcall KernelFree, ebx
 
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
 
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
unload:
; TODO: (in this particular order)
;
; - Stop the device
; - Detach int handler
; - Remove device from local list (device_list)
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
 
or eax,-1
 
ret
 
 
;-------------
;
; Probe
;
;-------------
 
align 4
probe:
 
DEBUGF 1,"Probing i8255x\n"
 
PCI_make_bus_master
 
;---------------------------
; First, identify the device
 
stdcall PciRead32, [device.pci_bus], [device.pci_dev], PCI_VENDOR_ID ; get device/vendor id
 
DEBUGF 1,"Vendor_id=0x%x\n", ax
 
cmp ax, 0x8086
jne .notfound
shr eax, 16
 
DEBUGF 1,"Device_id=0x%x\n", ax
 
mov ecx, DEVICE_IDs
mov edi, device_id_list
repne scasw
jne .notfound
jmp .found
 
.notfound:
DEBUGF 1,"ERROR: Unsupported device!\n"
or eax, -1
ret
 
.found:
 
call ee_get_width
call MAC_read_eeprom
 
;;; TODO: detect phy
 
 
 
;----------
;
; Reset
;
;----------
 
align 4
reset:
 
movzx eax, [device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax
jnz @f
DEBUGF 1,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
DEBUGF 1,"Resetting %s\n", my_service
 
;---------------
; reset the card
 
set_io 0
set_io reg_port
xor eax, eax ; Software Reset
out dx, eax
 
mov esi, 10
call Sleep ; Give the card time to warm up.
 
;---------------------------------
; Tell device where to store stats
 
lea eax, [lstats]
GetRealAddr
set_io 0
set_io reg_scb_ptr
out dx, eax
 
mov ax, INT_MASK + CU_STATSADDR
set_io reg_scb_cmd
out dx, ax
call cmd_wait
 
;-----------------
; setup RX
 
set_io reg_scb_ptr
xor eax, eax
out dx, eax
 
set_io reg_scb_cmd
mov ax, INT_MASK + RX_ADDR_LOAD
out dx, ax
call cmd_wait
 
;-----------------------------
; Create RX and TX descriptors
 
call create_ring
 
; RX start
 
set_io 0
set_io reg_scb_ptr
mov eax, [device.rx_desc]
GetRealAddr
out dx, eax
 
mov ax, INT_MASK + RX_START
set_io reg_scb_cmd
out dx, ax
call cmd_wait
 
; Set-up TX
 
set_io reg_scb_ptr
xor eax, eax
out dx, eax
 
set_io reg_scb_cmd
mov ax, INT_MASK + CU_CMD_BASE
out dx, ax
call cmd_wait
 
; --------------------
 
mov [confcmd.command], CmdConfigure + Cmdsuspend
mov [confcmd.status], 0
lea eax, [txfd]
GetRealAddr
mov [confcmd.link], eax
 
mov esi, confcmd_data
lea edi, [confcmd.data]
mov ecx, 22
rep movsb
 
mov byte[confcmd.data + 1], 0x88 ; fifo of 8 each
mov byte[confcmd.data + 4], 0
mov byte[confcmd.data + 5], 0x80
mov byte[confcmd.data + 15], 0x48
mov byte[confcmd.data + 19], 0x80
mov byte[confcmd.data + 21], 0x05
 
mov [txfd.command], CmdIASetup
mov [txfd.status], 0
lea eax, [confcmd]
GetRealAddr
mov [txfd.link], eax
 
;;; copy in our MAC
 
lea edi, [txfd.tx_desc_addr]
lea esi, [device.mac]
movsd
movsw
 
set_io reg_scb_ptr
lea eax, [txfd]
GetRealAddr
out dx, eax
 
; Start CU & enable ints
 
set_io reg_scb_cmd
mov ax, CU_START
out dx, ax
call cmd_wait
 
;-----------------------
; build txfd structure (again!)
 
lea eax, [txfd]
GetRealAddr
mov [txfd.link], eax
mov [txfd.count], 0x02208000
lea eax, [txfd.tx_buf_addr0]
GetRealAddr
mov [txfd.tx_desc_addr], eax
 
; Indicate that we have successfully reset the card
 
DEBUGF 1,"Resetting %s complete\n", my_service
 
mov [device.mtu], 1514
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
xor eax, eax ; indicate that we have successfully reset the card
ret
 
 
align 4
create_ring:
 
DEBUGF 1,"Creating ring\n"
 
;---------------------
; build rxfd structure
 
stdcall KernelAlloc, 2000
mov [device.rx_desc], eax
mov esi, eax
GetRealAddr
mov [esi + rxfd.status], 0x0000
mov [esi + rxfd.command], 0x0000
mov [esi + rxfd.link], eax
mov [esi + rxfd.count], 0
mov [esi + rxfd.size], 1528
 
;-----------------------
; build txfd structure
 
lea eax, [txfd]
GetRealAddr
mov [txfd.link], eax
mov [txfd.count], 0x02208000
lea eax, [txfd.tx_buf_addr0]
GetRealAddr
mov [txfd.tx_desc_addr], eax
 
ret
 
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
transmit:
 
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
 
cmp dword [esp+8], 1514
ja .error ; packet is too long
cmp dword [esp+8], 60
jb .error ; packet is too short
 
;;; TODO: check if current descriptor is in use
; fill in buffer address and size
mov eax, [esp+4]
mov [last_tx_buffer], eax ;;; FIXME
GetRealAddr
mov [txfd.tx_buf_addr0], eax
mov eax, [esp+8]
mov [txfd.tx_buf_size0], eax
 
mov [txfd.status], 0
mov [txfd.command], Cmdsuspend + CmdTx + CmdTxFlex + 1 shl 15 ;;; EL bit
 
; mov [txfd.count], 0x02208000 ;;;;;;;;;;;
 
; Inform device of the new/updated transmit descriptor
lea eax, [txfd]
GetRealAddr
set_io 0
set_io reg_scb_ptr
out dx, eax
 
; Start the transmit
mov ax, CU_START
set_io reg_scb_cmd
out dx, ax
call cmd_wait
 
; set_io 0 ;; why?
; in ax, dx ;;
;
; @@:
; cmp [txfd.status], 0 ; wait for completion? dont seems a good idea to me..
; je @r
;
; set_io 0 ;; why?
; in ax, dx ;;
 
; Update stats
inc [device.packets_tx]
mov eax, [esp + 8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
DEBUGF 1,"Transmit OK\n"
 
xor eax, eax
ret 8
 
.error:
stdcall KernelFree, [esp+4]
or eax, -1
ret 8
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_handler:
 
DEBUGF 1,"\n%s int\n", my_service
 
; find pointer of device wich made IRQ occur
 
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
; set_io 0 ; reg_scb_status = 0
set_io reg_scb_status
in ax, dx
out dx, ax ; send it back to ACK
test ax, ax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x\n", ebx, ax
 
test ax, 1 shl 14 ; did we receive a frame?
jz .no_rx
 
push ax
 
DEBUGF 1,"Receiving\n"
 
push ebx
.rx_loop:
pop ebx
 
mov esi, [device.rx_desc]
cmp [esi + rxfd.status], 0 ; we could also check bits C and OK (bit 15 and 13)
je .nodata
 
DEBUGF 1,"rxfd status=0x%x\n", [esi + rxfd.status]:4
 
movzx ecx, [esi + rxfd.count]
and ecx, 0x3fff
 
push ebx
push .rx_loop
push ecx
add esi, rxfd.packet
push esi
 
; Update stats
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
inc dword [device.packets_rx]
 
; allocate new descriptor
 
stdcall KernelAlloc, 2000
mov [device.rx_desc], eax
mov esi, eax
GetRealAddr
mov [esi + rxfd.status], 0x0000
mov [esi + rxfd.command], 0xc000 ; End of list + Suspend
mov [esi + rxfd.link], eax
mov [esi + rxfd.count], 0
mov [esi + rxfd.size], 1528
 
; restart RX
 
set_io 0
set_io reg_scb_ptr
; lea eax, [device.rx_desc]
; GetRealAddr
out dx, eax
 
set_io reg_scb_cmd
mov ax, RX_START
out dx, ax
call cmd_wait
 
; And give packet to kernel
 
jmp Eth_input
 
.nodata:
DEBUGF 1, "no more data\n"
pop ax
 
.no_rx:
 
; Cleanup after TX
cmp [txfd.status], 0
je .done
cmp [last_tx_buffer], 0
je .done
push ax
DEBUGF 1, "Removing packet 0x%x from RAM!\n", [last_tx_buffer]
stdcall KernelFree, [last_tx_buffer]
mov [last_tx_buffer], 0
pop ax
 
.done:
and ax, 00111100b
cmp ax, 00001000b
jne .fail
 
DEBUGF 1, "out of resources!\n"
; Restart the RX
 
; allocate new descriptor
 
stdcall KernelAlloc, 2000
mov [device.rx_desc], eax
mov esi, eax
GetRealAddr
mov [esi + rxfd.status], 0x0000
mov [esi + rxfd.command], 0xc000 ; End of list + Suspend
mov [esi + rxfd.link], eax
mov [esi + rxfd.count], 0
mov [esi + rxfd.size], 1528
 
; restart RX
 
set_io 0
set_io reg_scb_ptr
; lea eax, [device.rx_desc]
; GetRealAddr
out dx, eax
 
set_io reg_scb_cmd
mov ax, RX_START
out dx, ax
call cmd_wait
 
.fail:
 
ret
 
 
 
 
align 4
cmd_wait:
 
in al, dx
test al, al
jnz cmd_wait
 
ret
 
 
 
 
 
 
align 4
ee_read: ; esi = address to read
 
DEBUGF 1,"Eeprom read from 0x%x", esi
 
set_io 0
set_io reg_eeprom
 
;-----------------------------------------------------
; Prepend start bit + read opcode to the address field
; and shift it to the very left bits of esi
 
mov cl, 29
sub cl, [device.ee_bus_width]
shl esi, cl
or esi, EE_READ shl 29
 
movzx ecx, [device.ee_bus_width]
add ecx, 3
 
mov al, EE_CS
out dx, al
delay
 
;-----------------------
; Write this to the chip
 
.loop:
mov al, EE_CS + EE_SK
shl esi, 1
jnc @f
or al, EE_DI
@@:
out dx, al
delay
 
and al, not EE_SK
out dx, al
delay
 
loop .loop
 
;------------------------------
; Now read the data from eeprom
 
xor esi, esi
mov ecx, 16
 
.loop2:
shl esi, 1
mov al, EE_CS + EE_SK
out dx, al
delay
 
in al, dx
test al, EE_DO
jz @f
inc esi
@@:
 
mov al, EE_CS
out dx, al
delay
 
loop .loop2
 
;-----------------------
; de-activate the eeprom
 
xor ax, ax
out dx, ax
 
 
DEBUGF 1,"=0x%x\n", esi:4
ret
 
 
 
align 4
ee_write: ; esi = address to write to, di = data
 
DEBUGF 1,"Eeprom write 0x%x to 0x%x\n", di, esi
 
set_io 0
set_io reg_eeprom
 
;-----------------------------------------------------
; Prepend start bit + write opcode to the address field
; and shift it to the very left bits of esi
 
mov cl, 29
sub cl, [device.ee_bus_width]
shl esi, cl
or esi, EE_WRITE shl 29
 
movzx ecx, [device.ee_bus_width]
add ecx, 3
 
mov al, EE_CS ; enable chip
out dx, al
 
;-----------------------
; Write this to the chip
 
.loop:
mov al, EE_CS + EE_SK
shl esi, 1
jnc @f
or al, EE_DI
@@:
out dx, al
delay
 
and al, not EE_SK
out dx, al
delay
 
loop .loop
 
;-----------------------------
; Now write the data to eeprom
 
mov ecx, 16
 
.loop2:
mov al, EE_CS + EE_SK
shl di, 1
jnc @f
or al, EE_DI
@@:
out dx, al
delay
 
and al, not EE_SK
out dx, al
delay
 
loop .loop2
 
;-----------------------
; de-activate the eeprom
 
xor al, al
out dx, al
 
 
ret
 
 
 
align 4
ee_get_width:
 
; DEBUGF 1,"Eeprom get width\n"
 
set_io 0
set_io reg_eeprom
 
mov al, EE_CS ; activate eeprom
out dx, al
delay
 
mov si, EE_READ shl 13
xor ecx, ecx
.loop:
mov al, EE_CS + EE_SK
shl si, 1
jnc @f
or al, EE_DI
@@:
out dx, al
delay
 
and al, not EE_SK
out dx, al
delay
 
inc ecx
 
cmp ecx, 15
jae .give_up
 
in al, dx
test al, EE_DO
jnz .loop
 
.give_up:
xor al, al
out dx, al ; de-activate eeprom
 
sub cl, 3 ; dont count the opcode bits
 
mov [device.ee_bus_width], cl
DEBUGF 1,"Eeprom width=%u bit\n", ecx
 
 
;-----------------------
; de-activate the eeprom
 
xor eax, eax
out dx, eax
 
ret
 
 
 
; cx = phy addr
; dx = phy reg addr
 
; ax = data
 
align 4
mdio_read:
 
DEBUGF 1,"MDIO read\n"
 
shl ecx, 21 ; PHY addr
shl edx, 16 ; PHY reg addr
 
mov eax, ecx
or eax, edx
or eax, 10b shl 26 ; read opcode
 
set_io 0
set_io reg_mdi_ctrl
out dx, eax
 
.wait:
delay
in eax, dx
test eax, 1 shl 28 ; ready bit
jz .wait
 
ret
 
; ax = data
; cx = phy addr
; dx = phy reg addr
 
; ax = data
 
align 4
mdio_write:
 
DEBUGF 1,"MDIO write\n"
 
and eax, 0xffff
 
shl ecx, 21 ; PHY addr
shl edx, 16 ; PHY reg addr
 
or eax, ecx
or eax, edx
or eax, 01b shl 26 ; write opcode
 
set_io 0
set_io reg_mdi_ctrl
out dx, eax
 
.wait:
delay
in eax, dx
test eax, 1 shl 28 ; ready bit
jz .wait
 
ret
 
read_mac:
 
ret
 
 
 
align 4
MAC_read_eeprom:
 
mov esi, 0
call ee_read
mov word[device.mac], si
 
mov esi, 1
call ee_read
mov word[device.mac+2], si
 
mov esi, 2
call ee_read
mov word[device.mac+4], si
 
 
ret
 
 
align 4
MAC_write:
 
;;;;
 
ret
 
 
 
 
; End of code
 
align 4 ; Place all initialised data here
 
devices dd 0 ; number of currently running devices
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'i8255x', 0 ; max 16 chars include zero
devicename db 'Intel Etherexpress pro/100', 0
 
confcmd_data db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1
db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2
db 0x80, 0x3f, 0x05 ; 22 bytes total
 
 
device_id_list:
 
dw 0x1029
dw 0x1030
dw 0x1031
dw 0x1032
dw 0x1033
dw 0x1034
dw 0x1038
dw 0x1039
dw 0x103A
dw 0x103B
dw 0x103C
dw 0x103D
dw 0x103E
dw 0x1050
dw 0x1051
dw 0x1052
dw 0x1053
dw 0x1054
dw 0x1055
dw 0x1056
dw 0x1057
dw 0x1059
dw 0x1064
dw 0x1065
dw 0x1066
dw 0x1067
dw 0x1068
dw 0x1069
dw 0x106A
dw 0x106B
dw 0x1091
dw 0x1092
dw 0x1093
dw 0x1094
dw 0x1095
dw 0x10fe
dw 0x1209
dw 0x1229
dw 0x2449
dw 0x2459
dw 0x245D
dw 0x27DC
 
DEVICE_IDs = ($ - device_id_list) / 2
 
mac_82557_D100_A = 0
mac_82557_D100_B = 1
mac_82557_D100_C = 2
mac_82558_D101_A4 = 4
mac_82558_D101_B0 = 5
mac_82559_D101M = 8
mac_82559_D101S = 9
mac_82550_D102 = 12
mac_82550_D102_C = 13
mac_82551_E = 14
mac_82551_F = 15
mac_82551_10 = 16
mac_unknown = 0xFF
 
phy_100a = 0x000003E0
phy_100c = 0x035002A8
phy_82555_tx = 0x015002A8
phy_nsc_tx = 0x5C002000
phy_82562_et = 0x033002A8
phy_82562_em = 0x032002A8
phy_82562_ek = 0x031002A8
phy_82562_eh = 0x017002A8
phy_82552_v = 0xd061004d
phy_unknown = 0xFFFFFFFF
 
 
include_debug_strings ; All data wich FDO uses will be included here
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
/kernel/branches/net/drivers/imports.inc
0,0 → 1,102
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
macro kernel_export [name]{
forward
if used name
if DEBUG
display 'uses: ',`name,#13,#10
end if
extrn name
end if
}
; all exported kernel functions and data
 
 
kernel_export \
RegService,\
GetService,\
ServiceHandler,\
AttachIntHandler,\
GetIntHandler,\
FpuSave,\
FpuRestore,\
ReservePortArea,\
Boot_Log,\
\
MutexInit,\
MutexLock,\
MutexUnlock,\
\
PciApi,\
PciRead32,\
PciRead16,\
PciRead8,\
PciWrite8,\
PciWrite16,\
PciWrite32,\
\
AllocPage,\
AllocPages,\
FreePage,\
MapPage,\
MapSpace,\
MapIoMem,\
GetPgAddr,\
CommitPages,\
ReleasePages,\
\
AllocKernelSpace,\
FreeKernelSpace,\
KernelAlloc,\
KernelFree,\
UserAlloc,\
UserFree,\
Kmalloc,\
Kfree,\
CreateRingBuffer,\
\
GetPid,\
CreateObject,\
DestroyObject,\
CreateEvent,\
RaiseEvent,\
WaitEvent,\
DestroyEvent,\
ClearEvent,\
\
LoadCursor,\
SelectHwCursor,\
SetHwCursor,\
HwCursorRestore,\
HwCursorCreate,\
\
SysMsgBoardStr,\
SysMsgBoardChar,\
GetCurrentTask,\
LoadFile,\
SendEvent,\
SetMouseData,\
Sleep,\
GetTimerTicks,\
\
strncat,\
strncpy,\
strncmp,\
strnlen,\
strchr,\
strrchr,\
\
LFBAddress,\
GetDisplay,\
SetScreen,\
\
NetRegDev,\
NetUnRegDev,\
NetPtrToNum,\
NetLinkChanged,\
Eth_input,\
IPv4_input
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/drivers/mtd80x.asm
0,0 → 1,1258
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; MTD80x driver for KolibriOS ;;
;; ;;
;; Based on mtd80x.c from the etherboot project ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
NUM_TX_DESC = 4
NUM_RX_DESC = 4
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
 
public START
public service_proc
public version
 
 
; for different PHY
 
MysonPHY = 1
AhdocPHY = 2
SeeqPHY = 3
MarvellPHY = 4
Myson981 = 5
LevelOnePHY = 6
OtherPHY = 10
 
; Offsets to the Command and Status Registers.
 
PAR0 = 0x0 ; physical address 0-3
PAR1 = 0x04 ; physical address 4-5
MAR0 = 0x08 ; multicast address 0-3
MAR1 = 0x0C ; multicast address 4-7
FAR0 = 0x10 ; flow-control address 0-3
FAR1 = 0x14 ; flow-control address 4-5
TCRRCR = 0x18 ; receive & transmit configuration
BCR = 0x1C ; bus command
TXPDR = 0x20 ; transmit polling demand
RXPDR = 0x24 ; receive polling demand
RXCWP = 0x28 ; receive current word pointer
TXLBA = 0x2C ; transmit list base address
RXLBA = 0x30 ; receive list base address
ISR = 0x34 ; interrupt status
IMR = 0x38 ; interrupt mask
FTH = 0x3C ; flow control high/low threshold
MANAGEMENT = 0x40 ; bootrom/eeprom and mii management
TALLY = 0x44 ; tally counters for crc and mpa
TSR = 0x48 ; tally counter for transmit status
BMCRSR = 0x4c ; basic mode control and status
PHYIDENTIFIER = 0x50 ; phy identifier
ANARANLPAR = 0x54 ; auto-negotiation advertisement and link partner ability
ANEROCR = 0x58 ; auto-negotiation expansion and pci conf.
BPREMRPSR = 0x5c ; bypass & receive error mask and phy status
 
; Bits in the interrupt status/enable registers.
 
RFCON = 0x00020000 ; receive flow control xon packet
RFCOFF = 0x00010000 ; receive flow control xoff packet
LSCStatus = 0x00008000 ; link status change
ANCStatus = 0x00004000 ; autonegotiation completed
FBE = 0x00002000 ; fatal bus error
FBEMask = 0x00001800 ; mask bit12-11
ParityErr = 0x00000000 ; parity error
TargetErr = 0x00001000 ; target abort
MasterErr = 0x00000800 ; master error
TUNF = 0x00000400 ; transmit underflow
ROVF = 0x00000200 ; receive overflow
ETI = 0x00000100 ; transmit early int
ERI = 0x00000080 ; receive early int
CNTOVF = 0x00000040 ; counter overflow
RBU = 0x00000020 ; receive buffer unavailable
TBU = 0x00000010 ; transmit buffer unavilable
TI = 0x00000008 ; transmit interrupt
RI = 0x00000004 ; receive interrupt
RxErr = 0x00000002 ; receive error
 
; Bits in the NetworkConfig register.
 
RxModeMask = 0xe0
AcceptAllPhys = 0x80 ; promiscuous mode
AcceptBroadcast = 0x40 ; accept broadcast
AcceptMulticast = 0x20 ; accept mutlicast
AcceptRunt = 0x08 ; receive runt pkt
ALP = 0x04 ; receive long pkt
AcceptErr = 0x02 ; receive error pkt
 
AcceptMyPhys = 0x00000000
RxEnable = 0x00000001
RxFlowCtrl = 0x00002000
TxEnable = 0x00040000
TxModeFDX = 0x00100000
TxThreshold = 0x00e00000
 
PS1000 = 0x00010000
PS10 = 0x00080000
FD = 0x00100000
 
 
; Bits in network_desc.status
 
RXOWN = 0x80000000 ; own bit
FLNGMASK = 0x0fff0000 ; frame length
FLNGShift = 16
MARSTATUS = 0x00004000 ; multicast address received
BARSTATUS = 0x00002000 ; broadcast address received
PHYSTATUS = 0x00001000 ; physical address received
RXFSD = 0x00000800 ; first descriptor
RXLSD = 0x00000400 ; last descriptor
ErrorSummary = 0x80 ; error summary
RUNT = 0x40 ; runt packet received
LONG = 0x20 ; long packet received
FAE = 0x10 ; frame align error
CRC = 0x08 ; crc error
RXER = 0x04 ; receive error
 
; rx_desc_control_bits
 
RXIC = 0x00800000 ; interrupt control
RBSShift = 0
 
; tx_desc_status_bits
 
TXOWN = 0x80000000 ; own bit
JABTO = 0x00004000 ; jabber timeout
CSL = 0x00002000 ; carrier sense lost
LC = 0x00001000 ; late collision
EC = 0x00000800 ; excessive collision
UDF = 0x00000400 ; fifo underflow
DFR = 0x00000200 ; deferred
HF = 0x00000100 ; heartbeat fail
NCRMask = 0x000000ff ; collision retry count
NCRShift = 0
 
; tx_desc_control_bits
 
TXIC = 0x80000000 ; interrupt control
ETIControl = 0x40000000 ; early transmit interrupt
TXLD = 0x20000000 ; last descriptor
TXFD = 0x10000000 ; first descriptor
CRCEnable = 0x08000000 ; crc control
PADEnable = 0x04000000 ; padding control
RetryTxLC = 0x02000000 ; retry late collision
PKTSMask = 0x3ff800 ; packet size bit21-11
PKTSShift = 11
TBSMask = 0x000007ff ; transmit buffer bit 10-0
TBSShift = 0
 
; BootROM/EEPROM/MII Management Register
 
MASK_MIIR_MII_READ = 0x00000000
MASK_MIIR_MII_WRITE = 0x00000008
MASK_MIIR_MII_MDO = 0x00000004
MASK_MIIR_MII_MDI = 0x00000002
MASK_MIIR_MII_MDC = 0x00000001
 
; ST+OP+PHYAD+REGAD+TA
 
OP_READ = 0x6000 ; ST:01+OP:10+PHYAD+REGAD+TA:Z0
OP_WRITE = 0x5002 ; ST:01+OP:01+PHYAD+REGAD+TA:10
 
; -------------------------------------------------------------------------
; Constants for Myson PHY
; -------------------------------------------------------------------------
 
MysonPHYID = 0xd0000302
MysonPHYID0 = 0x0302
StatusRegister = 18
SPEED100 = 0x0400 ; bit10
FULLMODE = 0x0800 ; bit11
 
; -------------------------------------------------------------------------
; Constants for Seeq 80225 PHY
; -------------------------------------------------------------------------
 
SeeqPHYID0 = 0x0016
MIIRegister18 = 18
SPD_DET_100 = 0x80
DPLX_DET_FULL = 0x40
 
; -------------------------------------------------------------------------
; Constants for Ahdoc 101 PHY
; -------------------------------------------------------------------------
 
AhdocPHYID0 = 0x0022
DiagnosticReg = 18
DPLX_FULL = 0x0800
Speed_100 = 0x0400
 
; --------------------------------------------------------------------------
; Constants
; --------------------------------------------------------------------------
 
MarvellPHYID0 = 0x0141
LevelOnePHYID0 = 0x0013
 
MII1000BaseTControlReg = 9
MII1000BaseTStatusReg = 10
SpecificReg = 17
 
; for 1000BaseT Control Register
 
PHYAbletoPerform1000FullDuplex = 0x0200
PHYAbletoPerform1000HalfDuplex = 0x0100
PHY1000AbilityMask = 0x300
 
; for phy specific status register, marvell phy.
 
SpeedMask = 0x0c000
Speed_1000M = 0x08000
Speed_100M = 0x4000
Speed_10M = 0
Full_Duplex = 0x2000
 
; for phy specific status register, levelone phy
 
LXT1000_100M = 0x08000
LXT1000_1000M = 0x0c000
LXT1000_Full = 0x200
 
; for PHY
 
LinkIsUp = 0x0004
LinkIsUp2 = 0x00040000
 
 
 
virtual at 0
 
mtd_desc:
.status dd ?
.control dd ?
.buffer dd ?
.next_desc dd ?
 
.next_desc_logical dd ?
.skbuff dd ?
 
.reserved1 dd ?
.reserved2 dd ?
 
.size = $
 
end virtual
 
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.tx_desc rb NUM_TX_DESC*mtd_desc.size
.rx_desc rb NUM_RX_DESC*mtd_desc.size
 
.io_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
.dev_id dw ?
 
.flags dd ?
 
.crvalue dd ?
.bcrvalue dd ?
 
.cur_rx dd ?
.cur_tx dd ?
 
; These values are keep track of the transceiver/media in use.
 
.linkok dd ?
.line_speed dd ?
.duplexmode dd ?
.default_port dd ?
.PHYType dd ?
 
; MII transceiver section.
 
.mii_cnt dd ? ; MII device addresses.
.phys db ? ; MII device addresses.
 
device_size = $ - device
 
end virtual
 
 
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
 
.entry:
 
DEBUGF 2,"Loading %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
 
.fail:
.exit:
xor eax, eax
ret
 
endp
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne @F
 
cmp [IOCTL.out_size], 4
jb .fail
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
 
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
 
mov eax, [IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet
 
; check if the device is already listed
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax , [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
 
 
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, device_size, .fail
 
; Fill in the direct call addresses into the struct
 
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], unload
mov [device.name], my_service
 
; save the pci bus and device numbers
 
mov eax, [IOCTL.input]
movzx ecx, byte[eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte[eax+2]
mov [device.pci_dev], ecx
 
; Now, it's time to find the base io addres of the PCI device
 
PCI_find_io
 
; We've found the io address, find IRQ now
 
PCI_find_irq
 
DEBUGF 2,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:8
 
; Ok, the eth_device structure is ready, let's probe the device
; Because initialization fires IRQ, IRQ handler must be aware of this device
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
 
call probe ; this function will output in eax
test eax, eax
jnz .err2 ; If an error occured, exit
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
cmp eax, -1
je .destroy
 
ret
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 2,"Trying to find device number of already registered device\n"
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 2,"Kernel says: %u\n", eax
ret
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
; todo: reset device into virgin state
 
.err2:
dec [devices]
.err:
DEBUGF 2,"removing device structure\n"
stdcall KernelFree, ebx
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
 
align 4
unload:
; TODO: (in this particular order)
;
; - Stop the device
 
; /* Disable Tx Rx*/
; outl( mtdx.crvalue & (~TxEnable) & (~RxEnable), mtdx.ioaddr + TCRRCR );
;
; /* Reset the chip to erase previous misconfiguration. */
; mtd_reset(nic);
 
; - Detach int handler
; - Remove device from local list (device_list)
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
 
or eax,-1
 
ret
 
 
;-------
;
; PROBE
;
;-------
align 4
probe:
 
DEBUGF 2,"Probing mtd80x device\n"
 
PCI_make_bus_master
 
stdcall PciRead32, [device.pci_bus], [device.pci_dev], 0
 
cmp ax, 0x1516
jne .notfound
shr eax, 16
mov [device.dev_id], ax
 
cmp ax, 0x0800
je .has_mii_xcvr
 
cmp ax, 0x0803
je .has_chip_xcvr
 
cmp ax, 0x0891
je .has_mii_xcvr
 
.notfound:
DEBUGF 1,"Device not supported!\n"
xor eax, eax
dec eax
ret
 
.has_chip_xcvr:
DEBUGF 1,"Device has chip xcvr\n"
 
jmp .xcvr_set
 
.has_mii_xcvr:
DEBUGF 1,"Device has mii xcvr\n"
 
.xcvr_set:
 
call read_mac
 
; Reset the chip to erase previous misconfiguration.
 
set_io 0
set_io BCR
xor eax, eax
inc eax
out dx, eax
 
; find the connected MII xcvrs
 
cmp [device.dev_id], 0x0803
je .is_803
 
; int phy, phy_idx = 0;
;
; for (phy = 1; phy < 32 && phy_idx < 1; phy++) {
; int mii_status = mdio_read(nic, phy, 1);
;
; if (mii_status != 0xffff && mii_status != 0x0000) {
; mtdx.phys[phy_idx] = phy;
;
; DBG ( "%s: MII PHY found at address %d, status "
; "0x%4.4x.\n", mtdx.nic_name, phy, mii_status );
; /* get phy type */
; {
; unsigned int data;
;
; data = mdio_read(nic, mtdx.phys[phy_idx], 2);
; if (data equ= SeeqPHYID0)
; mtdx.PHYType = SeeqPHY;
; else if (data equ= AhdocPHYID0)
; mtdx.PHYType = AhdocPHY;
; else if (data equ= MarvellPHYID0)
; mtdx.PHYType = MarvellPHY;
; else if (data equ= MysonPHYID0)
; mtdx.PHYType = Myson981;
; else if (data equ= LevelOnePHYID0)
; mtdx.PHYType = LevelOnePHY;
; else
; mtdx.PHYType = OtherPHY;
; }
; phy_idx++;
; }
; }
;
; mtdx.mii_cnt = phy_idx;
; if (phy_idx equ= 0) {
; printf("%s: MII PHY not found -- this device may "
; "not operate correctly.\n", mtdx.nic_name);
; }
 
jmp .no_803
 
.is_803:
 
mov [device.phys], 32
 
; get phy type
set_io 0
set_io PHYIDENTIFIER
in eax, dx
 
cmp eax, MysonPHYID
jne @f
 
mov [device.PHYType], MysonPHY
DEBUGF 1,"MysonPHY\n"
jmp .no_803
 
@@:
mov [device.PHYType], OtherPHY
DEBUGF 1,"OtherPHY\n"
 
.no_803:
 
;-------
;
; RESET
;
;-------
align 4
reset:
 
DEBUGF 1,"Resetting mtd80x\n"
 
;--------------------------------
; insert irq handler on given irq
 
movzx eax, [device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax
jnz @f
DEBUGF 1,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
; Reset the chip to erase previous misconfiguration.
 
set_io 0
set_io BCR
xor eax, eax
inc eax
out dx, eax
 
call init_ring
 
; Initialize other registers.
; Configure the PCI bus bursts and FIFO thresholds.
 
mov [device.bcrvalue], 0x10 ; little-endian, 8 burst length
mov [device.crvalue], 0xa00 ; 128 burst length
 
cmp [device.dev_id], 0x891
jne @f
or [device.bcrvalue], 0x200 ; set PROG bit
or [device.crvalue], 0x02000000 ; set enhanced bit
@@:
 
or [device.crvalue], RxEnable + TxThreshold + TxEnable
 
call set_rx_mode
 
set_io 0
set_io BCR
mov eax, [device.bcrvalue]
out dx, eax
 
set_io TCRRCR
mov eax, [device.crvalue]
out dx, eax
 
call getlinkstatus
call getlinktype
 
; Restart Rx engine if stopped.
 
set_io 0
set_io RXPDR
xor eax, eax
out dx, eax
 
; Enable interrupts
 
set_io 0
set_io ISR
mov eax, (FBE or TUNF or CNTOVF or RBU or TI or RI)
out dx, eax
 
set_io IMR
; mov eax, (FBE or TUNF or CNTOVF or RBU or TI or RI)
out dx, eax
 
; clear packet/byte counters
 
xor eax, eax
lea edi, [device.bytes_tx]
mov ecx, 6
rep stosd
 
mov [device.mtu], 1514
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
xor eax, eax
ret
 
 
 
 
align 4
init_ring:
 
DEBUGF 1,"initializing rx and tx ring\n"
 
; Initialize all Rx descriptors
 
lea esi, [device.rx_desc]
mov [device.cur_rx], esi
mov ecx, NUM_RX_DESC
.rx_desc_loop:
mov [esi + mtd_desc.status], RXOWN
mov [esi + mtd_desc.control], 1536 shl RBSShift
 
lea eax, [esi + mtd_desc.size]
mov [esi + mtd_desc.next_desc_logical], eax
push ecx esi
GetRealAddr
mov [esi + mtd_desc.next_desc], eax
 
stdcall KernelAlloc, 1536
pop esi
push esi
mov [esi + mtd_desc.skbuff], eax
call GetPgAddr
pop esi ecx
mov [esi + mtd_desc.buffer], eax
 
add esi, mtd_desc.size
loop .rx_desc_loop
 
; Mark the last entry as wrapping the ring.
 
lea eax, [device.rx_desc]
mov [esi - mtd_desc.size + mtd_desc.next_desc_logical], eax
push esi
GetRealAddr
pop esi
mov [esi - mtd_desc.size + mtd_desc.next_desc], eax
 
set_io 0
set_io RXLBA
out dx, eax
 
; Initialize all Tx descriptors
 
lea esi, [device.tx_desc]
mov [device.cur_tx], esi
mov ecx, NUM_TX_DESC
.tx_desc_loop:
mov [esi + mtd_desc.status], 0
 
lea eax, [esi + mtd_desc.size]
mov [esi + mtd_desc.next_desc_logical], eax
push ecx esi
GetRealAddr
pop esi ecx
mov [esi + mtd_desc.next_desc], eax
 
add esi, mtd_desc.size
loop .tx_desc_loop
 
; Mark the last entry as wrapping the ring.
 
lea eax, [device.tx_desc]
mov [esi - mtd_desc.size + mtd_desc.next_desc_logical], eax
push esi
GetRealAddr
pop esi
mov [esi - mtd_desc.size + mtd_desc.next_desc], eax
 
set_io 0
set_io TXLBA
out dx, eax
 
ret
 
 
align 4
set_rx_mode:
 
DEBUGF 1,"Setting RX mode\n"
 
; Too many to match, or accept all multicasts.
 
set_io 0
set_io MAR0
xor eax, eax
not eax
out dx, eax
set_io MAR1
out dx, eax
 
and [device.crvalue], not (RxModeMask)
or [device.crvalue], AcceptBroadcast + AcceptMulticast + AcceptMyPhys
 
ret
 
 
align 4
getlinkstatus:
 
DEBUGF 1,"Getting link status\n"
 
mov [device.linkok], 0
 
cmp [device.PHYType], MysonPHY
jne .no_myson_phy
 
set_io 0
set_io BMCRSR
mov ecx, 1000
.loop1:
in eax, dx
test eax, LinkIsUp2
jnz .link_ok
 
push ecx edx ebx
mov esi, 10
call Sleep
pop ebx edx ecx
loop .loop1
 
ret
 
.no_myson_phy:
 
; for (i = 0; i < DelayTime; ++i) {
; if (mdio_read(nic, mtdx.phys[0], MII_BMSR) & BMSR_LSTATUS) {
; mtdx.linkok = 1;
; return;
; }
; m80x_delay(100);
 
ret
 
.link_ok:
DEBUGF 1,"Link is up\n"
inc [device.linkok]
ret
 
 
 
 
align 4
getlinktype:
 
DEBUGF 1,"Getting link type\n"
 
cmp [device.PHYType], MysonPHY
jne .no_myson_phy
 
DEBUGF 1,"myson PHY\n"
 
set_io 0
set_io TCRRCR
in eax, dx
 
mov [device.duplexmode], 1 ; 1 = half duplex
test eax, FD
jne @f
DEBUGF 1,"full duplex\n"
inc [device.duplexmode] ; 2 = full duplex
@@:
 
mov [device.line_speed], 1 ; 1 = 10M
test eax, PS10
jne @f
DEBUGF 1,"100mbit\n"
inc [device.line_speed] ; 2 = 100M
@@:
 
ret
 
.no_myson_phy:
 
DEBUGF 1,"no myson phy\n"
 
; if (mtdx.PHYType equ= SeeqPHY) { /* this PHY is SEEQ 80225 */
; unsigned int data;
;
; data = mdio_read(dev, mtdx.phys[0], MIIRegister18);
; if (data & SPD_DET_100)
; mtdx.line_speed = 2; /* 100M */
; else
; mtdx.line_speed = 1; /* 10M */
; if (data & DPLX_DET_FULL)
; mtdx.duplexmode = 2; /* full duplex mode */
; else
; mtdx.duplexmode = 1; /* half duplex mode */
; } else if (mtdx.PHYType equ= AhdocPHY) {
; unsigned int data;
;
; data = mdio_read(dev, mtdx.phys[0], DiagnosticReg);
; if (data & Speed_100)
; mtdx.line_speed = 2; /* 100M */
; else
; mtdx.line_speed = 1; /* 10M */
; if (data & DPLX_FULL)
; mtdx.duplexmode = 2; /* full duplex mode */
; else
; mtdx.duplexmode = 1; /* half duplex mode */
; }
; else if (mtdx.PHYType equ= MarvellPHY) {
; unsigned int data;
;
; data = mdio_read(dev, mtdx.phys[0], SpecificReg);
; if (data & Full_Duplex)
; mtdx.duplexmode = 2; /* full duplex mode */
; else
; mtdx.duplexmode = 1; /* half duplex mode */
; data &= SpeedMask;
; if (data equ= Speed_1000M)
; mtdx.line_speed = 3; /* 1000M */
; else if (data equ= Speed_100M)
; mtdx.line_speed = 2; /* 100M */
; else
; mtdx.line_speed = 1; /* 10M */
; }
; else if (mtdx.PHYType equ= Myson981) {
; unsigned int data;
;
; data = mdio_read(dev, mtdx.phys[0], StatusRegister);
;
; if (data & SPEED100)
; mtdx.line_speed = 2;
; else
; mtdx.line_speed = 1;
;
; if (data & FULLMODE)
; mtdx.duplexmode = 2;
; else
; mtdx.duplexmode = 1;
; }
; else if (mtdx.PHYType equ= LevelOnePHY) {
; unsigned int data;
;
; data = mdio_read(dev, mtdx.phys[0], SpecificReg);
; if (data & LXT1000_Full)
; mtdx.duplexmode = 2; /* full duplex mode */
; else
; mtdx.duplexmode = 1; /* half duplex mode */
; data &= SpeedMask;
; if (data equ= LXT1000_1000M)
; mtdx.line_speed = 3; /* 1000M */
; else if (data equ= LXT1000_100M)
; mtdx.line_speed = 2; /* 100M */
; else
; mtdx.line_speed = 1; /* 10M */
; }
 
; // chage crvalue
; // mtdx.crvalue&equ(~PS10)&(~FD);
; mtdx.crvalue &= (~PS10) & (~FD) & (~PS1000);
; if (mtdx.line_speed equ= 1)
; mtdx.crvalue |= PS10;
; else if (mtdx.line_speed equ= 3)
; mtdx.crvalue |= PS1000;
; if (mtdx.duplexmode equ= 2)
; mtdx.crvalue |= FD;
;
 
ret
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
transmit:
 
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
mov eax, [esp+4]
DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
 
cmp dword [esp+8], 1514
ja .fail
 
mov esi, [device.cur_tx]
push [esi + mtd_desc.next_desc_logical]
pop [device.cur_tx]
 
; todo: check if descriptor is not owned by the device!
 
mov eax, [esp + 4]
mov [esi + mtd_desc.skbuff], eax
GetRealAddr
mov [esi + mtd_desc.buffer], eax
 
mov eax, [esp + 8]
shl eax, PKTSShift ; packet size
or eax, TXLD + TXFD + CRCEnable + PADEnable + TXIC + 1536 shl TBSShift ; buffer size
mov [esi + mtd_desc.control], eax
 
mov [esi + mtd_desc.status], TXOWN
 
;-------------
; Update stats
 
inc [device.packets_tx]
mov eax, [esp+8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
; Point to transmit descriptor
 
set_io 0
set_io TXLBA
mov eax, esi
GetRealAddr
out dx, eax
 
; set_io TCRRCR
; mov eax, [device.crvalue]
; out dx, eax
 
; Wake the potentially-idle transmit channel.
 
set_io TXPDR ; TX Poll
xor eax, eax
out dx, eax
 
DEBUGF 1,"transmit ok\n"
xor eax, eax
ret 8
 
.fail:
DEBUGF 1,"transmit failed\n"
or eax, -1
stdcall KernelFree, [esp + 4]
ret 8
 
 
 
align 4
read_mac:
 
set_io 0
set_io PAR0
lea edi, [device.mac]
insd
stosd
set_io PAR1
insw
stosw
 
DEBUGF 1,"MAC = %x-%x-%x-%x-%x-%x\n",\
[device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
ret
 
align 4
write_mac:
 
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_handler:
 
DEBUGF 1,"\n%s int\n", my_service
 
; find pointer of device wich made IRQ occur
 
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
set_io 0
set_io ISR
in eax, dx
out dx, eax ; send it back to ACK
test eax, eax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x ", ebx, ax
 
test ax, RI ; receive interrupt
jz .no_rx
 
DEBUGF 1,"Receive interrupt\n"
.rx:
push ax
 
.rx_loop:
mov esi, [device.cur_rx]
 
test [esi + mtd_desc.status], RXOWN
jnz .fail_rx
 
push .rx_complete
 
mov ecx, [esi + mtd_desc.status]
shr ecx, FLNGShift
sub ecx, 4 ; we dont need CRC
push ecx
 
;-------------
; Update stats
 
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
inc dword [device.packets_rx]
 
 
push [esi + mtd_desc.skbuff]
 
jmp Eth_input
 
.rx_complete:
mov esi, [device.cur_rx]
 
mov [esi + mtd_desc.control], 1536 shl RBSShift
 
stdcall KernelAlloc, 1536
mov [esi + mtd_desc.skbuff], eax
call GetPgAddr
mov [esi + mtd_desc.buffer], eax
 
mov [esi + mtd_desc.status], RXOWN
 
mov eax, [esi + mtd_desc.next_desc_logical]
mov [device.cur_rx], eax
 
jmp .rx_loop
;
; while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
; {
; mtdx.cur_rx->status = RXOWN;
; mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
; }
;
; /* Restart Rx engine if stopped. */
; outl(0, mtdx.ioaddr + RXPDR);
 
.fail_rx:
DEBUGF 1,"RX failed\n"
 
pop ax
.no_rx:
 
test ax, TI ; transmit interrupt
jz .no_tx
 
DEBUGF 1,"Transmit interrupt\n"
push ax
 
lea esi, [device.tx_desc]
mov ecx, NUM_TX_DESC
.tx_loop:
 
test [esi + mtd_desc.status], TXOWN
jnz .skip_this_one
 
mov eax, [esi + mtd_desc.skbuff]
test eax, eax
je .skip_this_one
 
mov [esi + mtd_desc.skbuff], 0
 
DEBUGF 1,"freeing buffer:%x\n", eax
stdcall KernelFree, eax
 
.skip_this_one:
mov esi, [esi + mtd_desc.next_desc_logical]
loop .tx_loop
 
pop ax
 
.no_tx:
 
test ax, TBU
jz .no_tbu
 
DEBUGF 1,"Transmit buffer unavailable!\n"
 
.no_tbu:
 
.fail:
 
ret
 
 
; End of code
 
align 4 ; Place all initialised data here
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'mtd80x',0 ; max 16 chars include zero
 
 
; 0x1516, 0x0800, "MTD800", "Myson MTD800"
; 0x1516, 0x0803, "MTD803", "Surecom EP-320X"
; 0x1516, 0x0891, "MTD891", "Myson MTD891"
 
 
include_debug_strings ; All data wich FDO uses will be included here
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
 
/kernel/branches/net/drivers/rhine.asm
0,0 → 1,1670
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; rhine.asm ;;
;; ;;
;; Ethernet driver for Kolibri OS ;;
;; ;;
;; This driver is based on the via-rhine driver from ;;
;; the etherboot 5.0.6 project. The copyright statement is ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; Rewritten in flat assembler by Asper (asper.85@mail.ru) ;;
;; and hidnplayr (hidnplayr@gmail.com) ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
TX_RING_SIZE = 4
RX_RING_SIZE = 4
 
; max time out delay time
W_MAX_TIMEOUT = 0x0FFF
 
; Size of the in-memory receive ring.
RX_BUF_LEN_IDX = 3 ; 0==8K, 1==16K, 2==32K, 3==64K
RX_BUF_LEN = (8192 shl RX_BUF_LEN_IDX)
 
; PCI Tuning Parameters
; Threshold is bytes transferred to chip before transmission starts.
TX_FIFO_THRESH = 256 ; In bytes, rounded down to 32 byte units.
 
; The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024.
RX_FIFO_THRESH = 4 ; Rx buffer level before first PCI xfer.
RX_DMA_BURST = 4 ; Maximum PCI burst, '4' is 256 bytes
TX_DMA_BURST = 4
 
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
 
public START
public service_proc
public version
 
 
;**************************************************************************
; VIA Rhine Register Definitions
;**************************************************************************
byPAR0 = 0x00
byRCR = 0x06
byTCR = 0x07
byCR0 = 0x08
byCR1 = 0x09
byISR0 = 0x0c
byISR1 = 0x0d
byIMR0 = 0x0e
byIMR1 = 0x0f
byMAR0 = 0x10
byMAR1 = 0x11
byMAR2 = 0x12
byMAR3 = 0x13
byMAR4 = 0x14
byMAR5 = 0x15
byMAR6 = 0x16
byMAR7 = 0x17
dwCurrentRxDescAddr = 0x18
dwCurrentTxDescAddr = 0x1c
dwCurrentRDSE0 = 0x20
dwCurrentRDSE1 = 0x24
dwCurrentRDSE2 = 0x28
dwCurrentRDSE3 = 0x2c
dwNextRDSE0 = 0x30
dwNextRDSE1 = 0x34
dwNextRDSE2 = 0x38
dwNextRDSE3 = 0x3c
dwCurrentTDSE0 = 0x40
dwCurrentTDSE1 = 0x44
dwCurrentTDSE2 = 0x48
dwCurrentTDSE3 = 0x4c
dwNextTDSE0 = 0x50
dwNextTDSE1 = 0x54
dwNextTDSE2 = 0x58
dwNextTDSE3 = 0x5c
dwCurrRxDMAPtr = 0x60
dwCurrTxDMAPtr = 0x64
byMPHY = 0x6c
byMIISR = 0x6d
byBCR0 = 0x6e
byBCR1 = 0x6f
byMIICR = 0x70
byMIIAD = 0x71
wMIIDATA = 0x72
byEECSR = 0x74
byTEST = 0x75
byGPIO = 0x76
byCFGA = 0x78
byCFGB = 0x79
byCFGC = 0x7a
byCFGD = 0x7b
wTallyCntMPA = 0x7c
wTallyCntCRC = 0x7d
bySTICKHW = 0x83
byWOLcrClr = 0xA4
byWOLcgClr = 0xA7
byPwrcsrClr = 0xAC
 
;--------------------- Exioaddr Definitions -------------------------
 
; Bits in the RCR register
RCR_RRFT2 = 0x80
RCR_RRFT1 = 0x40
RCR_RRFT0 = 0x20
RCR_PROM = 0x10
RCR_AB = 0x08
RCR_AM = 0x04
RCR_AR = 0x02
RCR_SEP = 0x01
; Bits in the TCR register
TCR_RTSF = 0x80
TCR_RTFT1 = 0x40
TCR_RTFT0 = 0x20
TCR_OFSET = 0x08
TCR_LB1 = 0x04 ; loopback[1]
TCR_LB0 = 0x02 ; loopback[0]
; Bits in the CR0 register
CR0_RDMD = 0x40 ; rx descriptor polling demand
CR0_TDMD = 0x20 ; tx descriptor polling demand
CR0_TXON = 0x10
CR0_RXON = 0x08
CR0_STOP = 0x04 ; stop NIC, default = 1
CR0_STRT = 0x02 ; start NIC
CR0_INIT = 0x01 ; start init process
; Bits in the CR1 register
CR1_SFRST = 0x80 ; software reset
CR1_RDMD1 = 0x40 ; RDMD1
CR1_TDMD1 = 0x20 ; TDMD1
CR1_KEYPAG = 0x10 ; turn on par/key
CR1_DPOLL = 0x08 ; disable rx/tx auto polling
CR1_FDX = 0x04 ; full duplex mode
CR1_ETEN = 0x02 ; early tx mode
CR1_EREN = 0x01 ; early rx mode
; Bits in the CR register
CR_RDMD = 0x0040 ; rx descriptor polling demand
CR_TDMD = 0x0020 ; tx descriptor polling demand
CR_TXON = 0x0010
CR_RXON = 0x0008
CR_STOP = 0x0004 ; stop NIC, default = 1
CR_STRT = 0x0002 ; start NIC
CR_INIT = 0x0001 ; start init process
CR_SFRST = 0x8000 ; software reset
CR_RDMD1 = 0x4000 ; RDMD1
CR_TDMD1 = 0x2000 ; TDMD1
CR_KEYPAG = 0x1000 ; turn on par/key
CR_DPOLL = 0x0800 ; disable rx/tx auto polling
CR_FDX = 0x0400 ; full duplex mode
CR_ETEN = 0x0200 ; early tx mode
CR_EREN = 0x0100 ; early rx mode
; Bits in the IMR0 register
IMR0_CNTM = 0x80
IMR0_BEM = 0x40
IMR0_RUM = 0x20
IMR0_TUM = 0x10
IMR0_TXEM = 0x08
IMR0_RXEM = 0x04
IMR0_PTXM = 0x02
IMR0_PRXM = 0x01
; define imrshadow
IMRShadow = 0x5AFF
; Bits in the IMR1 register
IMR1_INITM = 0x80
IMR1_SRCM = 0x40
IMR1_NBFM = 0x10
IMR1_PRAIM = 0x08
IMR1_RES0M = 0x04
IMR1_ETM = 0x02
IMR1_ERM = 0x01
; Bits in the ISR register
ISR_INITI = 0x8000
ISR_SRCI = 0x4000
ISR_ABTI = 0x2000
ISR_NORBF = 0x1000
ISR_PKTRA = 0x0800
ISR_RES0 = 0x0400
ISR_ETI = 0x0200
ISR_ERI = 0x0100
ISR_CNT = 0x0080
ISR_BE = 0x0040
ISR_RU = 0x0020
ISR_TU = 0x0010
ISR_TXE = 0x0008
ISR_RXE = 0x0004
ISR_PTX = 0x0002
ISR_PRX = 0x0001
; Bits in the ISR0 register
ISR0_CNT = 0x80
ISR0_BE = 0x40
ISR0_RU = 0x20
ISR0_TU = 0x10
ISR0_TXE = 0x08
ISR0_RXE = 0x04
ISR0_PTX = 0x02
ISR0_PRX = 0x01
; Bits in the ISR1 register
ISR1_INITI = 0x80
ISR1_SRCI = 0x40
ISR1_NORBF = 0x10
ISR1_PKTRA = 0x08
ISR1_ETI = 0x02
ISR1_ERI = 0x01
; ISR ABNORMAL CONDITION
ISR_ABNORMAL = ISR_BE+ISR_RU+ISR_TU+ISR_CNT+ISR_NORBF+ISR_PKTRA
; Bits in the MIISR register
MIISR_MIIERR = 0x08
MIISR_MRERR = 0x04
MIISR_LNKFL = 0x02
MIISR_SPEED = 0x01
; Bits in the MIICR register
MIICR_MAUTO = 0x80
MIICR_RCMD = 0x40
MIICR_WCMD = 0x20
MIICR_MDPM = 0x10
MIICR_MOUT = 0x08
MIICR_MDO = 0x04
MIICR_MDI = 0x02
MIICR_MDC = 0x01
; Bits in the EECSR register
EECSR_EEPR = 0x80 ; eeprom programed status, 73h means programed
EECSR_EMBP = 0x40 ; eeprom embeded programming
EECSR_AUTOLD = 0x20 ; eeprom content reload
EECSR_DPM = 0x10 ; eeprom direct programming
EECSR_CS = 0x08 ; eeprom CS pin
EECSR_SK = 0x04 ; eeprom SK pin
EECSR_DI = 0x02 ; eeprom DI pin
EECSR_DO = 0x01 ; eeprom DO pin
; Bits in the BCR0 register
BCR0_CRFT2 = 0x20
BCR0_CRFT1 = 0x10
BCR0_CRFT0 = 0x08
BCR0_DMAL2 = 0x04
BCR0_DMAL1 = 0x02
BCR0_DMAL0 = 0x01
; Bits in the BCR1 register
BCR1_CTSF = 0x20
BCR1_CTFT1 = 0x10
BCR1_CTFT0 = 0x08
BCR1_POT2 = 0x04
BCR1_POT1 = 0x02
BCR1_POT0 = 0x01
; Bits in the CFGA register
CFGA_EELOAD = 0x80 ; enable eeprom embeded and direct programming
CFGA_JUMPER = 0x40
CFGA_MTGPIO = 0x08
CFGA_T10EN = 0x02
CFGA_AUTO = 0x01
; Bits in the CFGB register
CFGB_PD = 0x80
CFGB_POLEN = 0x02
CFGB_LNKEN = 0x01
; Bits in the CFGC register
CFGC_M10TIO = 0x80
CFGC_M10POL = 0x40
CFGC_PHY1 = 0x20
CFGC_PHY0 = 0x10
CFGC_BTSEL = 0x08
CFGC_BPS2 = 0x04 ; bootrom select[2]
CFGC_BPS1 = 0x02 ; bootrom select[1]
CFGC_BPS0 = 0x01 ; bootrom select[0]
; Bits in the CFGD register
CFGD_GPIOEN = 0x80
CFGD_DIAG = 0x40
CFGD_MAGIC = 0x10
CFGD_RANDOM = 0x08
CFGD_CFDX = 0x04
CFGD_CEREN = 0x02
CFGD_CETEN = 0x01
; Bits in RSR
RSR_RERR = 0x00000001
RSR_CRC = 0x00000002
RSR_FAE = 0x00000004
RSR_FOV = 0x00000008
RSR_LONG = 0x00000010
RSR_RUNT = 0x00000020
RSR_SERR = 0x00000040
RSR_BUFF = 0x00000080
RSR_EDP = 0x00000100
RSR_STP = 0x00000200
RSR_CHN = 0x00000400
RSR_PHY = 0x00000800
RSR_BAR = 0x00001000
RSR_MAR = 0x00002000
RSR_RXOK = 0x00008000
RSR_ABNORMAL = RSR_RERR+RSR_LONG+RSR_RUNT
; Bits in TSR
TSR_NCR0 = 0x00000001
TSR_NCR1 = 0x00000002
TSR_NCR2 = 0x00000004
TSR_NCR3 = 0x00000008
TSR_COLS = 0x00000010
TSR_CDH = 0x00000080
TSR_ABT = 0x00000100
TSR_OWC = 0x00000200
TSR_CRS = 0x00000400
TSR_UDF = 0x00000800
TSR_TBUFF = 0x00001000
TSR_SERR = 0x00002000
TSR_JAB = 0x00004000
TSR_TERR = 0x00008000
TSR_ABNORMAL = TSR_TERR+TSR_OWC+TSR_ABT+TSR_JAB+TSR_CRS
TSR_OWN_BIT = 0x80000000
 
CB_DELAY_LOOP_WAIT = 10 ; 10ms
; enabled mask value of irq
W_IMR_MASK_VALUE = 0x1BFF ; initial value of IMR
 
; Ethernet address filter type
PKT_TYPE_DIRECTED = 0x0001 ; obsolete, directed address is always accepted
PKT_TYPE_MULTICAST = 0x0002
PKT_TYPE_ALL_MULTICAST = 0x0004
PKT_TYPE_BROADCAST = 0x0008
PKT_TYPE_PROMISCUOUS = 0x0020
PKT_TYPE_LONG = 0x2000
PKT_TYPE_RUNT = 0x4000
PKT_TYPE_ERROR = 0x8000 ; accept error packets, e.g. CRC error
 
; Loopback mode
 
NIC_LB_NONE = 0x00
NIC_LB_INTERNAL = 0x01
NIC_LB_PHY = 0x02 ; MII or Internal-10BaseT loopback
 
PKT_BUF_SZ = 1536 ; Size of each temporary Rx buffer.
 
PCI_REG_MODE3 = 0x53
MODE3_MIION = 0x04 ; in PCI_REG_MOD3 OF PCI space
 
; VIA Rhine revisions
VT86C100A = 0x00
VTunknown0 = 0x20
VT6102 = 0x40
VT8231 = 0x50 ; Integrated MAC
VT8233 = 0x60 ; Integrated MAC
VT8235 = 0x74 ; Integrated MAC
VT8237 = 0x78 ; Integrated MAC
VTunknown1 = 0x7C
VT6105 = 0x80
VT6105_B0 = 0x83
VT6105L = 0x8A
VT6107 = 0x8C
VTunknown2 = 0x8E
VT6105M = 0x90
 
; Rx status bits
RX_SBITS_RERR = 1 shl 0
RX_SBITS_CRC_ERROR = 1 shl 1
RX_SBITS_FAE = 1 shl 2
RX_SBITS_FOV = 1 shl 3
RX_SBITS_TOOLONG = 1 shl 4
RX_SBITS_RUNT = 1 shl 5
RX_SBITS_SERR = 1 shl 6
RX_SBITS_BUFF = 1 shl 7
RX_SBITS_EDP = 1 shl 8
RX_SBITS_STP = 1 shl 9
RX_SBITS_CHN = 1 shl 10
RX_SBITS_PHY = 1 shl 11
RX_SBITS_BAR = 1 shl 12
RX_SBITS_MAR = 1 shl 13
RX_SBITS_RESERVED_1 = 1 shl 14
RX_SBITS_RXOK = 1 shl 15
RX_SBITS_FRAME_LENGTH = 0x7FF shl 16
RX_SBITS_RESERVED_2 = 0xF shl 27
RX_SBITS_OWN_BIT = 1 shl 31
 
; Rx control bits
RX_CBITS_RX_BUF_SIZE = 0x7FF
RX_CBITS_EXTEND_RX_BUF_SIZE = 0xF shl 11
RX_CBITS_RESERVED_1 = 0x1FFFF shl 15
 
; Tx status bits
TX_SBITS_NCR0 = 1 shl 0
TX_SBITS_NCR1 = 1 shl 1
TX_SBITS_NCR2 = 1 shl 2
TX_SBITS_NCR3 = 1 shl 3
TX_SBITS_COLS = 1 shl 4
TX_SBITS_RESERVED_1 = 1 shl 5
TX_SBITS_CDH = 1 shl 7
TX_SBITS_ABT = 1 shl 8
TX_SBITS_OWC = 1 shl 9
TX_SBITS_CRS = 1 shl 10
TX_SBITS_UDF = 1 shl 11
TX_SBITS_TBUFF = 1 shl 12
TX_SBITS_SERR = 1 shl 13
TX_SBITS_JAB = 1 shl 14
TX_SBITS_TERR = 1 shl 15
TX_SBITS_RESERVED_2 = 0x7FFF shl 16
TX_SBITS_OWN_BIT = 1 shl 31
 
; Tx control bits
TX_CBITS_TX_BUF_SIZE = 0x7FF
TX_CBITS_EXTEND_TX_BUF_SIZE = 0xF shl 11
TX_CBITS_CHN = 1 shl 15
TX_CBITS_CRC = 1 shl 16
TX_CBITS_RESERVED_1 = 0xF shl 17
TX_CBITS_STP = 1 shl 21
TX_CBITS_EDP = 1 shl 22
TX_CBITS_IC = 1 shl 23
TX_CBITS_RESERVED_2 = 0xFF shl 24
 
 
 
; Offsets to the device registers.
StationAddr = 0x00
RxConfig = 0x06
TxConfig = 0x07
ChipCmd = 0x08
IntrStatus = 0x0C
IntrEnable = 0x0E
MulticastFilter0 = 0x10
MulticastFilter1 = 0x14
RxRingPtr = 0x18
TxRingPtr = 0x1C
GFIFOTest = 0x54
MIIPhyAddr = 0x6C
MIIStatus = 0x6D
PCIBusConfig = 0x6E
MIICmd = 0x70
MIIRegAddr = 0x71
MIIData = 0x72
MACRegEEcsr = 0x74
ConfigA = 0x78
ConfigB = 0x79
ConfigC = 0x7A
ConfigD = 0x7B
RxMissed = 0x7C
RxCRCErrs = 0x7E
MiscCmd = 0x81
StickyHW = 0x83
IntrStatus2 = 0x84
WOLcrClr = 0xA4
WOLcgClr = 0xA7
PwrcsrClr = 0xAC
 
; Bits in the interrupt status/mask registers.
IntrRxDone = 0x0001
IntrRxErr = 0x0004
IntrRxEmpty = 0x0020
IntrTxDone = 0x0002
IntrTxError = 0x0008
IntrTxUnderrun = 0x0010
IntrPCIErr = 0x0040
IntrStatsMax = 0x0080
IntrRxEarly = 0x0100
IntrRxOverflow = 0x0400
IntrRxDropped = 0x0800
IntrRxNoBuf = 0x1000
IntrTxAborted = 0x2000
IntrLinkChange = 0x4000
IntrRxWakeUp = 0x8000
IntrNormalSummary = 0x0003
IntrAbnormalSummary = 0xC260
IntrTxDescRace = 0x080000 ; mapped from IntrStatus2
IntrTxErrSummary = 0x082218
 
DEFAULT_INTR = (IntrRxDone or IntrRxErr or IntrRxEmpty or IntrRxOverflow or IntrRxDropped or IntrRxNoBuf)
 
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.io_addr dd ?
.pci_dev dd ?
.pci_bus dd ?
.revision db ?
.irq_line db ?
.chip_id dw ?
 
.cur_rx dw ?
.cur_tx dw ?
.last_tx dw ?
 
rb 0x100-(($ - device) and 0xff) ; align 256
.tx_ring rb tx_head.sizeof*TX_RING_SIZE
 
rb 0x100-(($ - device) and 0xff) ; align 256
.rx_ring rb rx_head.sizeof*RX_RING_SIZE
 
.size = $ - device
 
end virtual
 
virtual at 0
rx_head:
.status dd ?
.control dd ?
.buff_addr dd ? ; address
.next_desc dd ? ;
 
.buff_addr_virt dd ?
rd 3 ; alignment
.sizeof:
end virtual
 
 
virtual at 0
tx_head:
.status dd ?
.control dd ?
.buff_addr dd ? ; address
.next_desc dd ? ;
 
.buff_addr_virt dd ?
rd 3 ; alignment
.sizeof:
end virtual
 
 
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
 
.entry:
 
DEBUGF 2,"Loading %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
 
.fail:
.exit:
xor eax, eax
ret
 
endp
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne @F
 
cmp [IOCTL.out_size], 4
jb .fail
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
 
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
 
mov eax, [IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet
 
; check if the device is already listed
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax , [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
 
 
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, device.size, .fail ; Allocate the buffer for device structure
 
; Fill in the direct call addresses into the struct
 
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], unload
mov [device.name], my_service
 
; save the pci bus and device numbers
 
mov eax, [IOCTL.input]
movzx ecx, byte[eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte[eax+2]
mov [device.pci_dev], ecx
 
; Now, it's time to find the base io addres of the PCI device
 
PCI_find_io
 
; We've found the io address, find IRQ now
 
PCI_find_irq
 
DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
 
; Ok, the eth_device structure is ready, let's probe the device
;;; cli
 
call probe ; this function will output in eax
test eax, eax
jnz .err_sti ; If an error occured, exit
 
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
;;; sti
 
cmp eax, -1
je .destroy
 
ret
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 1,"Trying to find device number of already registered device\n"
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 1,"Kernel says: %u\n", eax
ret
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
; todo: reset device into virgin state
 
.err_sti:
sti
 
.err:
stdcall KernelFree, ebx
 
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
 
probe:
 
mov eax, [device.io_addr]
DEBUGF 1, "Probing card at 0x%x\n", eax
 
; make the card a bus master
PCI_make_bus_master
 
; get device id
stdcall PciRead16, [device.pci_bus], [device.pci_dev], PCI_DEVICE_ID
mov [device.chip_id], ax
 
; get revision id.
PCI_find_rev
 
movzx eax, [device.revision]
DEBUGF 1, "Card revision = 0x%x\n", eax
 
; D-Link provided reset code (with comment additions)
cmp al, 0x40
jb .below_x40
 
mov ax, [device.chip_id]
DEBUGF 1, "Enabling Sticky Bit Workaround for Chip_id: 0x%x\n", ax
 
; clear sticky bit before reset & read ethernet address
set_io 0
set_io bySTICKHW
in al, dx
and al, 0xFC
out dx, al
 
; (bits written are cleared?)
; disable force PME-enable
set_io byWOLcgClr
mov al, 0x80
out dx, al
 
; disable power-event config bit
mov al, 0xFF
out dx, al
 
; clear power status (undocumented in vt6102 docs?)
set_io byPwrcsrClr
out dx, al
 
.below_x40:
 
; Reset the chip to erase previous misconfiguration.
set_io 0
set_io byCR0
mov ax, CR_SFRST
out dx, ax
 
; if vt3043 delay after reset
cmp [device.revision], 0x40
jae @f
mov esi, 2000 ; 2000ms
call Sleep
@@:
 
; polling till software reset complete
mov ecx, W_MAX_TIMEOUT
.poll_again:
in ax, dx
test ax, CR_SFRST
jz @f
loop .poll_again
DEBUGF 1, "Soft reset timeout!\n"
@@:
 
; issue AUTOLoad in EECSR to reload eeprom
set_io byEECSR
mov al, 0x20
out dx, al
 
; if vt3065 delay after reset
cmp [device.revision], 0x40
jb .not_vt3065
 
; delay 8ms to let MAC stable
mov esi, 8 ; 8ms
call Sleep
 
; for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA
; turned on. it makes MAC receive magic packet
; automatically. So, we turn it off. (D-Link)
 
set_io byCFGA
in al, dx
and al, 0xFE
out dx, al
 
; turn on bit2 in PCI configuration register 0x53 , only for 3065
stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REG_MODE3
or al, MODE3_MIION
stdcall PciWrite8, [device.pci_bus], [device.pci_dev], PCI_REG_MODE3, eax
.not_vt3065:
 
; back off algorithm, disable the right-most 4-bit off CFGD
set_io 0
set_io byCFGD
in al, dx
and al, not (CFGD_RANDOM or CFGD_CFDX or CFGD_CEREN or CFGD_CETEN)
out dx, al
 
; reload eeprom
call reload_eeprom
 
; read MAC
call read_mac
 
; restart MII auto-negotiation
stdcall WriteMII, 0, 1 shl 9, 1
 
DEBUGF 1, "Analyzing Media type, this may take several seconds"
 
mov ecx, 5
.read_again:
DEBUGF 1, "."
mov esi, 1
call Sleep
 
stdcall ReadMII, 1
test eax, 0x0020
jnz .read_done
loop .read_again
DEBUGF 1, "timeout!\n"
.read_done:
DEBUGF 1, " OK\n"
 
if DEBUG
 
set_io 0
set_io 0x6C
in al, dx
and eax, 0xFF
DEBUGF 1, "MII : Address %x\n", ax
 
stdcall ReadMII, 1
DEBUGF 1, "status 0x%x\n", ax
 
stdcall ReadMII, 4
DEBUGF 1, "advertising 0x%x\n", ax
 
stdcall ReadMII, 5
DEBUGF 1, "link 0x%x\n", ax
 
end if
 
; query MII to know LineSpeed, duplex mode
set_io 0
set_io MIIStatus
in al, dx
test al, MIISR_SPEED
jz .100mbps
DEBUGF 1, "Linespeed=10Mbs\n"
jmp @f
 
.100mbps:
DEBUGF 1, "Linespeed=100Mbs\n"
@@:
 
call QueryAuto
 
test eax, 1
jz .halfduplex
 
DEBUGF 1, "Fullduplex\n"
set_io 0
set_io byCR0
mov ax, CR_FDX
out dx, ax
jmp @f
 
.halfduplex:
DEBUGF 1, "Halfduplex\n"
@@:
 
; set MII 10 FULL ON, only apply in vt3043
cmp [device.chip_id], 0x3043
jne @f
stdcall WriteMII, 0x17, 1 shl 1, 1
@@:
 
; turn on MII link change
set_io 0
set_io byMIICR
in al, dx
and al, 0x7F
out dx, al
push eax
 
call MIIDelay
 
set_io byMIIAD
mov al, 0x41
out dx, al
 
call MIIDelay
 
pop eax
or al, 0x80
set_io byMIICR
out dx, al
 
;**************************************************************************;
;* ETH_RESET - Reset adapter *;
;**************************************************************************;
 
reset:
 
DEBUGF 1, "reset\n"
 
; attach int handler
 
movzx eax, [device.irq_line]
DEBUGF 2,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax
jnz @f
DEBUGF 2,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
; Soft reset the chip.
set_io 0
set_io byCR0
mov ax, CR_SFRST
out dx, ax
 
call MIIDelay
 
; Initialize rings
call init_ring
 
; Setup Multicast
call set_rx_mode
 
; set TCR RCR threshold to store and forward
set_io 0
set_io byBCR0
mov al, 0x3E
out dx, al
 
set_io byBCR1
mov al, 0x38
out dx, al
 
set_io byRCR
mov al, 0x2C
out dx, al
 
set_io byTCR
mov al, 0x60
out dx, al
 
; Set Fulldupex
 
call QueryAuto
test eax, eax ; full duplex?
jz @f
 
set_io 0
set_io byCFGD
mov al, CFGD_CFDX
out dx, al
 
set_io byCR0
mov ax, CR_FDX
out dx, ax
@@:
 
; ENABLE interrupts
set_io 0
set_io byIMR0
mov ax, DEFAULT_INTR
out dx, ax
 
; KICK NIC to WORK
 
set_io byCR0
in ax, dx
and ax, not CR_STOP
or ax, CR_STRT or CR_TXON or CR_RXON or CR_DPOLL
out dx, ax
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
; say reset was successfull
xor eax, eax
ret
 
 
 
align 4
unload:
 
call reset
push eax edx
DEBUGF 1, "rhine disable\n"
 
; Switch to loopback mode to avoid hardware races.
set_io 0
set_io byTCR
mov al, 0x61
out dx, al
 
; Stop the chip's Tx and Rx processes.
set_io byCR0
mov ax, CR_STOP
out dx, ax
pop edx eax
 
ret
 
 
 
 
align 4
reload_eeprom:
 
DEBUGF 1, "Reload eeprom\n"
 
set_io 0
set_io byEECSR
mov al, 0x20
out dx, al
; Typically 2 cycles to reload.
mov ecx, 150
.reload:
in al, dx
test al, 0x20
jz @f
loop .reload
DEBUGF 1, "Reload timeout!\n"
@@:
 
ret
 
; Initialize the Rx and Tx rings, along with various 'dev' bits.
align 4
init_ring:
 
DEBUGF 1, "Init ring\n"
 
lea edi, [device.rx_ring]
mov eax, edi
GetRealAddr
mov esi, eax
push esi
mov ecx, RX_RING_SIZE
.rx_init:
add esi, rx_head.sizeof
mov [edi + rx_head.status], RX_SBITS_OWN_BIT
mov [edi + rx_head.control], PKT_BUF_SZ
push ecx
stdcall KernelAlloc, PKT_BUF_SZ
pop ecx
mov [edi + rx_head.buff_addr_virt], eax
GetRealAddr
mov [edi + rx_head.buff_addr], eax ; buffer ptr
mov [edi + rx_head.next_desc], esi ; next head
add edi, rx_head.sizeof
dec ecx
jnz .rx_init
pop [edi - rx_head.sizeof + rx_head.next_desc] ; Mark the last entry as wrapping the ring.
 
 
lea edi, [device.tx_ring]
mov eax, edi
GetRealAddr
mov esi, eax
push esi
mov ecx, TX_RING_SIZE
.tx_init:
add esi, tx_head.sizeof
mov [edi + tx_head.status], 0
mov [edi + tx_head.control], 0x00E08000
mov [edi + tx_head.buff_addr], 0
mov [edi + tx_head.next_desc], esi
mov [edi + tx_head.buff_addr_virt], 0
add edi, tx_head.sizeof
dec ecx
jnz .tx_init
pop [edi - tx_head.sizeof + tx_head.next_desc] ; Mark the last entry as wrapping the ring.
 
; write Descriptors to MAC
lea eax, [device.rx_ring]
GetRealAddr
set_io 0
set_io dwCurrentRxDescAddr
out dx, eax
 
lea eax, [device.tx_ring]
GetRealAddr
set_io dwCurrentTxDescAddr
out dx, eax
 
xor eax, eax
mov [device.cur_rx], ax
mov [device.cur_tx], ax
mov [device.last_tx], ax
 
ret
 
 
align 4
QueryAuto:
 
DEBUGF 1, "Query Auto\n"
 
push ecx
stdcall ReadMII, 0x04 ; advertised
mov ecx, eax
stdcall ReadMII, 0x05
and ecx, eax
 
xor eax, eax
test ecx, 0x100
jnz .one
 
and ecx, 0x1C0
cmp ecx, 0x40
jne .zero
.one:
inc eax
DEBUGF 1, "AutoNego OK!\n"
.zero:
pop ecx
 
ret
 
 
proc ReadMII stdcall, byMIIIndex:dword
 
; DEBUGF 1, "ReadMII Index=%x\n", [byMIIIndex]
 
push esi ebx ecx edx
 
set_io 0
set_io byMIIAD
in al, dx
mov bl, al
 
set_io byMIICR
in al, dx
mov bh, al
and al, 0x7F
out dx, al
 
call MIIDelay
 
mov al, byte [byMIIIndex]
set_io byMIIAD
out dx, al
 
call MIIDelay
 
set_io byMIICR
in al, dx
or al, 0x40
out dx, al
 
mov ecx, 200
.read_again:
in al, dx
test al, 0x40
jz @f
 
mov esi, 10
call Sleep
dec ecx
jnz .read_again
DEBUGF 1, "\nReadMII timeout!\n"
@@:
 
call MIIDelay
 
set_io byMIIAD
in ax, dx
 
push eax
mov ax, bx
set_io byMIIAD
out dx, al
 
shr ax, 8
set_io byMIICR
out dx, al
 
call MIIDelay
 
pop eax
and eax, 0xFFFF
rol ax, 8 ;;;;; I dont know how or why but it seems needed...
 
pop edx ecx ebx esi
ret
endp
 
proc WriteMII stdcall, byMIISetByte:dword, byMIISetBit:dword, byMIIOP:dword
 
; DEBUGF 1, "WriteMII SetByte=%x SetBit=%x OP=%x\n", [byMIISetByte], [byMIISetBit], [byMIIOP]
 
push ebx eax ecx edx
 
set_io 0
set_io byMIIAD
in al, dx
mov bl, al
 
set_io byMIICR
in al, dx
mov bh, al
and al, 0x7F
out dx, al
 
call MIIDelay
 
mov al, byte [byMIISetByte]
set_io byMIIAD
out dx, al
 
call MIIDelay
 
set_io byMIICR
in al, dx
or al, 0x40
out dx, al
 
mov ecx, 200
.read_again0:
in al, dx
test al, 0x40
jz .done
 
mov esi, 10
call Sleep
dec ecx
jnz .read_again0
DEBUGF 1, "WriteMII timeout 1\n"
.done:
 
call MIIDelay
 
set_io wMIIDATA
in ax, dx
 
mov ecx, [byMIISetBit]
rol cx, 8 ;;;;;;;;;;;;;;;;; CHECKME
 
cmp byte [byMIIOP], 0
jne @f
not ecx
and ax, cx
jmp .end_mascarad
@@:
or ax, cx
.end_mascarad:
 
set_io wMIIDATA
out dx, ax
 
call MIIDelay
 
set_io byMIICR
in al, dx
or al, 0x20
out dx, al
 
mov ecx, 200
.read_again1:
in al, dx
test al, 0x20
jz @f
 
mov esi, 10
call Sleep
dec ecx
jnz .read_again1
DEBUGF 1, "WriteMII timeout 2\n"
@@:
 
call MIIDelay
 
mov ax, bx
and al, 0x7F
set_io byMIIAD
out dx, al
 
shr ax, 8
set_io byMIICR
out dx, al
 
call MIIDelay
 
pop edx ecx eax ebx
ret
endp
 
 
align 4
MIIDelay:
 
mov ecx, 0x7FFF
@@:
in al, 0x61
in al, 0x61
in al, 0x61
in al, 0x61
loop @b
 
ret
 
 
align 4
set_rx_mode:
 
DEBUGF 1, "Set RX mode\n"
 
; ! IFF_PROMISC
mov eax, 0xffffffff
set_io 0
set_io byMAR0
out dx, eax
 
set_io byMAR4
out dx, eax
 
set_io byRCR
mov al, 0x6C ;rx_mode = 0x0C;
out dx, al ;outb(0x60 /* thresh */ | rx_mode, byRCR );
 
ret
 
 
 
 
 
; Beware of PCI posted writes
macro IOSYNC
{
set_io StationAddr
in al, dx
}
 
 
 
align 4
read_mac:
 
DEBUGF 1, "Ethernet Address: "
 
lea edi, [device.mac]
set_io 0
set_io byPAR0
mov ecx, 6
.next:
in al, dx
stosb
DEBUGF 1, "-%x", al
inc edx
dec ecx
jnz .next
DEBUGF 1, "\n"
 
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
transmit:
DEBUGF 2,"\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
DEBUGF 2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
 
cmp dword [esp+8], 1514
ja .fail
cmp dword [esp+8], 60
jb .fail
 
movzx eax, [device.cur_tx]
mov ecx, tx_head.sizeof
mul ecx
lea edi, [device.tx_ring]
add edi, eax
 
cmp [edi + tx_head.buff_addr_virt], 0
jne .fail
 
mov eax, [esp+4]
mov [edi + tx_head.buff_addr_virt], eax
GetRealAddr
mov [edi + tx_head.buff_addr], eax
mov ecx, [esp+8]
and ecx, TX_CBITS_TX_BUF_SIZE
or ecx, 0x00E08000
mov [edi + tx_head.control], ecx
or [edi + tx_head.status], TX_SBITS_OWN_BIT
 
set_io 0
set_io byCR1
in al, dx
or al, CR1_TDMD1
out dx, al
 
inc [device.cur_tx]
and [device.cur_tx], TX_RING_SIZE-1
 
;outw(IMRShadow,byIMR0); ;
 
; Update stats
inc [device.packets_tx]
mov ecx, [esp+8] ;;;;;
add dword [device.bytes_tx], ecx
adc dword [device.bytes_tx + 4], 0
 
ret 8
 
.fail:
DEBUGF 1, "Failed!\n"
 
ret 8
 
 
 
 
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_handler:
 
DEBUGF 1,"\n%s int ", my_service
 
; Find pointer of device wich made IRQ occur
 
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
set_io 0
set_io IntrStatus
in ax, dx
out dx, ax ; send it back to ACK
test ax, ax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing: ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
DEBUGF 1, "not for me\n"
ret
 
 
.got_it:
 
DEBUGF 1, "status=0x%x\n", ax
 
push ax
 
test ax, IntrRxDone
jz .not_RX
 
push ebx
.more_RX:
pop ebx
 
; Get the current descripter pointer
 
movzx eax, [device.cur_rx]
mov ecx, rx_head.sizeof
mul ecx
lea edi, [device.rx_ring]
add edi, eax
 
; Check it's status
 
test [edi + rx_head.status], RX_SBITS_OWN_BIT
jnz .not_bit_own
 
DEBUGF 1, "Packet status = 0x%x\n", [edi + rx_head.status]
 
; TODO: check error bits
 
; get length
 
mov ecx, [edi + rx_head.status]
and ecx, RX_SBITS_FRAME_LENGTH
shr ecx, 16
sub ecx, 4 ; We dont want CRC
 
; Update stats
 
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
inc [device.packets_rx]
 
; Push packet size and pointer, kernel will need it..
 
push ebx
push .more_RX ; return ptr
 
push ecx ; full packet size
push [edi + rx_head.buff_addr_virt]
 
; reset the RX descriptor
 
push edi
stdcall KernelAlloc, PKT_BUF_SZ
pop edi
mov [edi + rx_head.buff_addr_virt], eax
GetRealAddr
mov [edi + rx_head.buff_addr], eax
mov [edi + rx_head.status], RX_SBITS_OWN_BIT
 
; Use next descriptor next time
 
inc [device.cur_rx]
and [device.cur_rx], RX_RING_SIZE - 1
 
; At last, send packet to kernel
 
jmp Eth_input
 
.not_bit_own:
.not_RX:
 
pop ax
 
test ax, IntrTxDone
jz .not_TX
 
.loop_tx:
movzx eax, [device.last_tx]
mov ecx, tx_head.sizeof
mul ecx
lea edi, [device.tx_ring]
add edi, eax
 
test [edi + tx_head.status], TX_SBITS_OWN_BIT
jnz .not_TX
 
cmp [edi + tx_head.buff_addr_virt], 0
je .not_TX
 
DEBUGF 1,"Freeing buffer 0x%x\n", [edi + tx_head.buff_addr_virt]
 
push [edi + tx_head.buff_addr_virt]
mov [edi + tx_head.buff_addr_virt], 0
call KernelFree
 
inc [device.last_tx]
and [device.last_tx], TX_RING_SIZE - 1
 
jmp .loop_tx
 
.not_TX:
 
; On Rhine-II, Bit 3 indicates Tx descriptor write-back race.
if 0
cmp [device.chip_id], 0x3065 ;if (tp->chip_id == 0x3065)
jne @f
push ax
xor eax, eax
set_io IntrStatus2
in al, dx ; intr_status |= inb(nic->ioaddr + IntrStatus2) << 16;
shl eax, 16
pop ax
@@:
end if
 
if 0
 
; Acknowledge all of the current interrupt sources ASAP.
xor ecx, ecx
test eax, IntrTxDescRace
jz @f
set_io 0
set_io IntrStatus2
push ax
mov al, 0x08
out dx, al
pop ax
@@:
set_io 0
set_io IntrStatus
out dx, ax
IOSYNC
 
end if
 
ret
 
 
 
 
 
; End of code
 
section '.data' data readable writable align 16 ; place all uninitialized data here
align 4 ; Place all initialised data here
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'RHINE',0 ; max 16 chars including zero
 
devicelist:
dd 0x30431106, rhine_3043;, RHINE_IOTYPE, RHINE_I_IOSIZE, CanHaveMII or ReqTxAlign or HasV1TxStat
dd 0x61001106, rhine_6100;, RHINE_IOTYPE, RHINE_I_IOSIZE, CanHaveMII or ReqTxAlign or HasV1TxStat
dd 0x30651106, rhine_6102;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL
dd 0x31061106, rhine_6105;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL
; Duplicate entry, with 'M' features enabled.
dd 0x31061106, rhine_6105;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL or HasIPChecksum or HasVLAN
dd 0x30531106, rhine_3053;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL
dd 0
 
rhine_3043 db "VIA VT3043 Rhine", 0
rhine_6100 db "VIA VT86C100A Rhine", 0
rhine_6102 db "VIA VT6102 Rhine-II", 0
rhine_6105 db "VIA VT6105LOM Rhine-III (3106)", 0
rhine_3053 db "VIA VT6105M Rhine-III (3053 prototype)", 0
 
include_debug_strings ; All data wich FDO uses will be included here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
/kernel/branches/net/drivers/sis900.asm
0,0 → 1,1214
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Ethernet driver for KolibriOS ;;
;; This is an adaptation of MenuetOS driver with minimal changes. ;;
;; Changes were made by CleverMouse. Original copyright follows. ;;
;; ;;
;; This driver is based on the SIS900 driver from ;;
;; the etherboot 5.0.6 project. The copyright statement is ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; remaining parts Copyright 2004 Jason Delozier, ;;
;; cordata51@hotmail.com ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;; Updates: ;;
;; Revision Look up table and SIS635 Mac Address by Jarek Pelczar ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
NUM_RX_DESC = 4 ; Number of RX descriptors
NUM_TX_DESC = 4 ; Number of TX descriptors
RX_BUFF_SZ = 1520 ; Buffer size for each Rx buffer
TX_BUFF_SZ = 1516 ; Buffer size for each Tx buffer
MAX_ETH_FRAME_SIZE = 1516
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
DSIZE = 0x00000fff
CRC_SIZE = 4
RFADDR_shift = 16
 
; If you are having problems sending/receiving packet try changing the
; Max DMA Burst, Possible settings are as follows:
;
; 0x00000000 = 512 bytes
; 0x00100000 = 4 bytes
; 0x00200000 = 8 bytes
; 0x00300000 = 16 bytes
; 0x00400000 = 32 bytes
; 0x00500000 = 64 bytes
; 0x00600000 = 128 bytes
; 0x00700000 = 256 bytes
 
RX_DMA = 0x00600000
TX_DMA = 0x00600000
 
;-------------------------------------------------------------------------------------------------
; Symbolic offsets to registers.
cr = 0x0 ; Command Register
cfg = 0x4 ; Configuration Register
mear = 0x8 ; EEPROM Access Register
ptscr = 0xc ; PCI Test Control Register
isr = 0x10 ; Interrupt Status Register
imr = 0x14 ; Interrupt Mask Register
ier = 0x18 ; Interrupt Enable Register
epar = 0x18 ; Enhanced PHY Access Register
txdp = 0x20 ; Transmit Descriptor Pointer Register
txcfg = 0x24 ; Transmit Configuration Register
rxdp = 0x30 ; Receive Descriptor Pointer Register
rxcfg = 0x34 ; Receive Configuration Register
flctrl = 0x38 ; Flow Control Register
rxlen = 0x3c ; Receive Packet Length Register
rfcr = 0x48 ; Receive Filter Control Register
rfdr = 0x4C ; Receive Filter Data Register
pmctrl = 0xB0 ; Power Management Control Register
pmer = 0xB4 ; Power Management Wake-up Event Register
 
; Command Register Bits
RELOAD = 0x00000400
ACCESSMODE = 0x00000200
RESET = 0x00000100
SWI = 0x00000080
RxRESET = 0x00000020
TxRESET = 0x00000010
RxDIS = 0x00000008
RxENA = 0x00000004
TxDIS = 0x00000002
TxENA = 0x00000001
 
; Configuration Register Bits
DESCRFMT = 0x00000100 ; 7016 specific
REQALG = 0x00000080
SB = 0x00000040
POW = 0x00000020
EXD = 0x00000010
PESEL = 0x00000008
LPM = 0x00000004
BEM = 0x00000001
RND_CNT = 0x00000400
FAIR_BACKOFF = 0x00000200
EDB_MASTER_EN = 0x00002000
 
; Eeprom Access Reigster Bits
MDC = 0x00000040
MDDIR = 0x00000020
MDIO = 0x00000010 ; 7016 specific
EECS = 0x00000008
EECLK = 0x00000004
EEDO = 0x00000002
EEDI = 0x00000001
 
; TX Configuration Register Bits
ATP = 0x10000000 ; Automatic Transmit Padding
MLB = 0x20000000 ; Mac Loopback Enable
HBI = 0x40000000 ; HeartBeat Ignore (Req for full-dup)
CSI = 0x80000000 ; CarrierSenseIgnore (Req for full-du
 
; RX Configuration Register Bits
AJAB = 0x08000000 ;
ATX = 0x10000000 ; Accept Transmit Packets
ARP = 0x40000000 ; accept runt packets (<64bytes)
AEP = 0x80000000 ; accept error packets
 
; Interrupt Register Bits
WKEVT = 0x10000000
TxPAUSEEND = 0x08000000
TxPAUSE = 0x04000000
TxRCMP = 0x02000000 ; Transmit Reset Complete
RxRCMP = 0x01000000 ; Receive Reset Complete
DPERR = 0x00800000
SSERR = 0x00400000
RMABT = 0x00200000
RTABT = 0x00100000
RxSOVR = 0x00010000
HIBERR = 0x00008000
SWINT = 0x00001000
MIBINT = 0x00000800
TxURN = 0x00000400
TxIDLE = 0x00000200
TxERR = 0x00000100
TxDESC = 0x00000080
TxOK = 0x00000040
RxORN = 0x00000020
RxIDLE = 0x00000010
RxEARLY = 0x00000008
RxERR = 0x00000004
RxDESC = 0x00000002
RxOK = 0x00000001
 
; Interrupt Enable Register Bits
IE = RxOK + TxOK
 
; Revision ID
SIS900B_900_REV = 0x03
SIS630A_900_REV = 0x80
SIS630E_900_REV = 0x81
SIS630S_900_REV = 0x82
SIS630EA1_900_REV = 0x83
SIS630ET_900_REV = 0x84
SIS635A_900_REV = 0x90
SIS900_960_REV = 0x91
 
; Receive Filter Control Register Bits
RFEN = 0x80000000 ; enable
RFAAB = 0x40000000 ; accept all broadcasts
RFAAM = 0x20000000 ; accept all multicasts
RFAAP = 0x10000000 ; accept all packets
 
; Reveive Filter Data Mask
RFDAT = 0x0000FFFF
 
; Eeprom Address
EEPROMSignature = 0x00
EEPROMVendorID = 0x02
EEPROMDeviceID = 0x03
EEPROMMACAddr = 0x08
EEPROMChecksum = 0x0b
 
; The EEPROM commands include the alway-set leading bit.
EEread = 0x0180
EEwrite = 0x0140
EEerase = 0x01C0
EEwriteEnable = 0x0130
EEwriteDisable = 0x0100
EEeraseAll = 0x0120
EEwriteAll = 0x0110
EEaddrMask = 0x013F
EEcmdShift = 16
 
; For SiS962 or SiS963, request the eeprom software access
EEREQ = 0x00000400
EEDONE = 0x00000200
EEGNT = 0x00000100
 
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
 
public START
public version
 
 
virtual at ebx
device:
 
ETH_DEVICE
 
.io_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
.cur_rx db ?
.cur_tx db ?
.last_tx db ?
.pci_revision db ?
.table_entries db ?
rb 2 ; alignment
 
.txd rd (4 * NUM_TX_DESC)
.rxd rd (4 * NUM_RX_DESC)
 
.size = $ - device
 
end virtual
 
macro ee_delay {
push eax
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
pop eax
}
 
 
section '.flat' code readable align 16
 
; Driver entry point - register our service when the driver is loading.
; TODO: add needed operations when unloading
START:
cmp dword [esp+4], 1
jne .exit
stdcall RegService, my_service, service_proc
ret 4
.exit:
xor eax, eax
ret 4
 
; Service procedure for the driver - handle all I/O requests for the driver.
; Currently handled requests are: SRV_GETVERSION = 0 and SRV_HOOK = 1.
service_proc:
; 1. Get parameter from the stack: [esp+4] is the first parameter,
; pointer to IOCTL structure.
mov edx, [esp+4] ; edx -> IOCTL
; 2. Get request code and select a handler for the code.
mov eax, [IOCTL.io_code]
test eax, eax ; check for SRV_GETVERSION
jnz @f
; 3. This is SRV_GETVERSION request, no input, 4 bytes output, API_VERSION.
; 3a. Output size must be at least 4 bytes.
cmp [IOCTL.out_size], 4
jb .fail
; 3b. Write result to the output buffer.
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
; 3c. Return success.
xor eax, eax
ret 4
@@:
dec eax ; check for SRV_HOOK
jnz .fail
; 4. This is SRV_HOOK request, input defines the device to hook, no output.
; 4a. The driver works only with PCI devices,
; so input must be at least 3 bytes long.
cmp [IOCTL.inp_size], 3
jb .fail
; 4b. First byte of input is bus type, 1 stands for PCI.
mov eax, [IOCTL.input]
cmp byte [eax], 1
jne .fail
; 4c. Second and third bytes of the input define the device: bus and dev.
; Word in bx holds both bytes.
mov bx, [eax+1]
; 4d. Check if the device was already hooked,
; scan through the list of known devices.
; check if the device is already listed
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax, [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
; 4e. This device doesn't have its own eth_device structure yet, let's create one
.firstdevice:
; 4f. Check that we have place for new device.
cmp [devices], MAX_DEVICES
jae .fail
; 4g. Allocate memory for device descriptor and receive+transmit buffers.
; 4h. Zero the structure.
allocate_and_clear ebx, device.size, .fail
; 4i. Save PCI coordinates
mov eax, [IOCTL.input]
movzx ecx, byte[eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte[eax+2]
mov [device.pci_dev], ecx
; 4j. Fill in the direct call addresses into the struct.
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], unload
mov [device.name], my_service
 
; 4k. Now, it's time to find the base io addres of the PCI device
; TODO: implement check if bus and dev exist on this machine
 
; Now, it's time to find the base io addres of the PCI device
PCI_find_io
 
; We've found the io address, find IRQ now
PCI_find_irq
 
; 4m. Add new device to the list (required for int_handler).
mov eax, [devices]
mov [device_list+4*eax], ebx
inc [devices]
 
; 4m. Ok, the eth_device structure is ready, let's probe the device
call probe
test eax, eax
jnz .destroy
; 4n. If device was successfully initialized, register it for the kernel.
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
cmp eax, -1
je .destroy
 
ret 4
 
; 5. If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
ret 4
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
dec [devices]
; todo: reset device into virgin state
 
.err:
stdcall KernelFree, ebx
 
.fail:
xor eax, eax
ret 4
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
unload:
; TODO: (in this particular order)
;
; - Stop the device
; - Detach int handler
; - Remove device from local list
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
 
or eax,-1
 
ret
 
;***************************************************************************
;
; probe
;
; checks the card and enables it
;
; TODO: probe mii transceivers
;
;***************************************************************************
align 4
probe:
DEBUGF 1, "Probe\n"
 
; wake up device CHECKME
stdcall PciWrite8, [device.pci_bus], [device.pci_dev], 0x40, 0
 
PCI_make_bus_master
 
PCI_adjust_latency 64
 
; Get Card Revision
stdcall PciRead8, [device.pci_bus], [device.pci_dev], 0x08
mov [device.pci_revision], al ; save the revision for later use
 
; Look up through the specific_table
mov esi, specific_table
.tableloop:
cmp dword [esi], 0 ; Check if we reached end of the list
je .notsupported
cmp al, [esi] ; Check if revision is OK
je .ok
add esi, 12 ; Advance to next entry
jmp .tableloop
 
.ok:
 
call dword[esi + 4] ; "get MAC" function
 
; Set table entries
mov [device.table_entries], 16
cmp [device.pci_revision], SIS635A_900_REV
jae @f
cmp [device.pci_revision], SIS900B_900_REV
je @f
mov [device.table_entries], 8
@@:
 
; TODO: Probe for mii transceiver
 
jmp reset
 
.notsupported:
DEBUGF 1, "Device not supported\n"
or eax, -1
 
ret
 
reset:
 
DEBUGF 1, "reset\n"
 
movzx eax, [device.irq_line]
stdcall AttachIntHandler, eax, int_handler, 0
 
;--------------------------------------------
; Disable Interrupts and reset Receive Filter
 
set_io 0
set_io ier
xor eax, eax
out dx, eax
 
set_io imr
out dx, eax
 
set_io rfcr
out dx, eax
 
;-----------
; Reset Card
 
set_io cr
in eax, dx ; Get current Command Register
or eax, RESET + RxRESET + TxRESET ; set flags
out dx, eax ; Write new Command Register
 
;----------
; Wait loop
 
set_io isr
mov ecx, 1000
.loop:
dec ecx
jz .fail
in eax, dx ; read interrupt status
test eax, TxRCMP + RxRCMP
jz .loop
DEBUGF 1, "status=%x\n", eax
 
;------------------------------------------------------
; Set Configuration Register depending on Card Revision
 
set_io cfg
mov eax, PESEL ; Configuration Register Bit
cmp [device.pci_revision], SIS635A_900_REV
je .match
cmp [device.pci_revision], SIS900B_900_REV ; Check card revision
jne .done
.match: ; Revision match
or eax, RND_CNT ; Configuration Register Bit
.done:
out dx, eax
 
DEBUGF 1, "Initialising RX Filter\n"
 
; Get Receive Filter Control Register
set_io rfcr
in eax, dx
push eax
 
; disable packet filtering before setting filter
and eax, not RFEN
out dx, eax
 
; load MAC addr to filter data register
xor ecx, ecx
.macloop:
mov eax, ecx
set_io 0
set_io rfcr
shl eax, 16 ; high word of eax tells card which mac byte to write
out dx, eax ;
set_io rfdr
mov ax, word [device.mac + ecx*2] ; Get Mac ID word
out dx, ax ; Send Mac ID
inc cl ; send next word
cmp cl, 3 ; more to send?
jne .macloop
 
; enable packet filtering
pop eax ; old register value
set_io rfcr
or eax, RFEN ; enable filtering
out dx, eax ; set register
 
DEBUGF 1, "Initialising TX Descriptors\n"
 
mov ecx, NUM_TX_DESC
lea esi, [device.txd]
.txdescloop:
lea eax, [esi + 16] ; next ptr
GetRealAddr
mov dword [esi], eax ; link to next desc
mov dword [esi + 4], 0 ; status field
mov dword [esi + 8], 0 ; ptr to buffer
add esi, 16
dec ecx
jnz .txdescloop
 
lea eax, [device.txd]
GetRealAddr
mov dword [esi - 16], eax ; correct last descriptor link ptr
 
set_io txdp ; TX Descriptor Pointer
; lea eax, [device.txd]
; GetRealAddr
out dx, eax
 
mov [device.cur_tx], 0 ; Set current tx descriptor to 0
mov [device.last_tx], 0
 
DEBUGF 1, "Initialising RX Descriptors\n"
 
mov ecx, NUM_RX_DESC
lea esi, [device.rxd]
.rxdescloop:
lea eax, [esi + 16] ; next ptr
GetRealAddr
mov dword [esi], eax
mov dword [esi + 4], RX_BUFF_SZ ; size
 
push ecx esi
stdcall KernelAlloc, RX_BUFF_SZ
pop esi ecx
test eax, eax
jz .fail
mov dword [esi + 12], eax ; address
GetRealAddr
mov dword [esi + 8], eax ; real address
add esi, 16
dec ecx
jnz .rxdescloop
 
lea eax, [device.rxd]
GetRealAddr
mov dword [esi - 16], eax ; correct last descriptor link ptr
 
set_io 0
set_io rxdp
; lea eax, [device.rxd]
; GetRealAddr
out dx, eax
 
mov [device.cur_rx], 0 ; Set current rx descriptor to 0
 
DEBUGF 1, "setting RX mode\n"
 
xor cl, cl
.rxfilterloop:
set_io 0
set_io rfcr ; Receive Filter Control Reg offset
mov eax, 4 ; determine table entry
add al, cl
shl eax, 16
out dx, eax ; tell card which entry to modify
 
set_io rfdr ; Receive Filter Control Reg offset
mov eax, 0xffff ; entry value
out dx, ax ; write value to table in card
 
inc cl ; next entry
cmp cl, [device.table_entries]
jb .rxfilterloop
 
set_io rfcr ; Receive Filter Control Register offset
mov eax, RFAAB + RFAAM + RFAAP + RFEN
out dx, eax
 
set_io rxcfg ; Receive Config Register offset
mov eax, ATX + RX_DMA + 2 ; 0x2 : RX Drain Threshold = 8*8=64 bytes
out dx, eax
 
DEBUGF 1, "setting TX mode\n"
 
set_io txcfg ; Transmit config Register offset
mov eax, ATP + HBI + CSI + TX_DMA + 0x120
; TX Fill threshold = 0x100
; TX Drain Threshold = 0x20
out dx, eax
 
DEBUGF 1, "Enabling interrupts\n"
 
set_io imr
mov eax, IE ; Interrupt enable mask
out dx, eax
 
set_io cr
in eax, dx
or eax, RxENA ; Enable Receive
out dx, eax
 
set_io ier ; Interrupt enable
mov eax, 1
out dx, eax
 
mov [device.mtu], 1514
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
xor eax, eax
ret
 
.fail:
DEBUGF 1, "Resetting device failed\n"
or eax, -1
 
ret
 
 
;***************************************************************************
;
; SIS960_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
;
; SiS962 or SiS963 model, use EEPROM to store MAC address.
; EEPROM is shared by LAN and 1394.
; When access EEPROM, send EEREQ signal to hardware first, and wait for EEGNT.
; If EEGNT is ON, EEPROM is permitted to be accessed by LAN, otherwise is not.
; After MAC address is read from EEPROM, send
; EEDONE signal to refuse EEPROM access by LAN.
; The EEPROM map of SiS962 or SiS963 is different to SiS900.
; The signature field in SiS962 or SiS963 spec is meaningless.
;
; Return 0 is EAX = failure
;
;***************************************************************************
align 4
SIS960_get_mac_addr:
DEBUGF 1, "SIS960 - get mac: "
 
;-------------------------------
; Send Request for eeprom access
 
set_io 0
set_io mear ; Eeprom access register
mov eax, EEREQ ; Request access to eeprom
out dx, eax ; Send request
 
;-----------------------------------------------------
; Loop 4000 times and if access not granted, error out
 
mov ecx, 4000
.loop:
in eax, dx ; get eeprom status
test eax, EEGNT ; see if eeprom access granted flag is set
jnz .got_access ; if it is, go access the eeprom
loop .loop ; else keep waiting
 
DEBUGF 1, "Access to EEprom failed!\n", 0
 
set_io mear ; Eeprom access register
mov eax, EEDONE ; tell eeprom we are done
out dx, eax
 
or eax, -1 ; error
ret
 
.got_access:
 
;------------------------------------------
; EEprom access granted, read MAC from card
 
; zero based so 3-16 bit reads will take place
 
mov ecx, 2
.read_loop:
mov eax, EEPROMMACAddr ; Base Mac Address
add eax, ecx ; Current Mac Byte Offset
push ecx
call read_eeprom ; try to read 16 bits
pop ecx
mov word [device.mac+ecx*2], ax ; save 16 bits to the MAC ID varible
dec ecx ; one less word to read
jns .read_loop ; if more read more
mov eax, 1 ; return non-zero indicating success
 
DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
;-------------------------------------
; Tell EEPROM We are Done Accessing It
 
.done:
set_io 0
set_io mear ; Eeprom access register
mov eax, EEDONE ; tell eeprom we are done
out dx, eax
 
xor eax, eax ; ok
ret
 
 
 
 
;***************************************************************************
;
; get_mac_addr: - Get MAC address for stand alone SiS900 model
;
; Older SiS900 and friends, use EEPROM to store MAC address.
;
;***************************************************************************
align 4
SIS900_get_mac_addr:
DEBUGF 1, "SIS900 - get mac: "
 
;------------------------------------
; check to see if we have sane EEPROM
 
mov eax, EEPROMSignature ; Base Eeprom Signature
call read_eeprom ; try to read 16 bits
cmp ax, 0xffff
je .err
test ax, ax
je .err
 
;-----------
; Read MacID
 
; zero based so 3-16 bit reads will take place
 
mov ecx, 2
.loop:
mov eax, EEPROMMACAddr ; Base Mac Address
add eax, ecx ; Current Mac Byte Offset
push ecx
call read_eeprom ; try to read 16 bits
pop ecx
mov word [device.mac+ecx*2], ax ; save 16 bits to the MAC ID storage
dec ecx ; one less word to read
jns .loop ; if more read more
 
DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
xor eax, eax
ret
 
 
.err:
DEBUGF 1, "Access to EEprom failed!\n", 0
 
or eax, -1
ret
 
 
;***************************************************************************
;
; Get_Mac_SIS635_900_REV: - Get MAC address for model 635
;
;***************************************************************************
align 4
Get_Mac_SIS635_900_REV:
DEBUGF 1, "SIS635 - get mac: "
 
set_io 0
set_io rfcr
in eax, dx
mov esi, eax
 
set_io cr
or eax, RELOAD
out dx, eax
 
xor eax, eax
out dx, eax
 
;-----------------------------------------------
; Disable packet filtering before setting filter
 
set_io rfcr
mov eax, esi
and eax, not RFEN
out dx, eax
 
;---------------------------------
; Load MAC to filter data register
 
xor ecx, ecx
lea edi, [device.mac]
.loop:
set_io 0
set_io rfcr
mov eax, ecx
shl eax, RFADDR_shift
out dx, eax
 
set_io rfdr
in ax, dx
stosw
inc ecx
cmp ecx, 3
jb .loop
 
;------------------------
; Enable packet filtering
 
set_io rfcr
mov eax, esi
or eax, RFEN
out dx, eax
 
DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
xor eax, eax
ret
 
;***************************************************************************
;
; read_eeprom
;
; reads and returns a given location from EEPROM
;
; IN: si = addr
; OUT: ax = data
;
;***************************************************************************
align 4
read_eeprom:
 
set_io 0
set_io mear
 
xor eax, eax ; start send
out dx, eax
ee_delay
 
or eax, EECLK
out dx, eax
ee_delay
 
;------------------------------------
; Send the read command
 
or esi, EEread
mov ecx, 1 shl 9
 
.loop:
mov eax, EECS
test esi, ecx
jz @f
or eax, EEDI
@@:
out dx, eax
ee_delay
 
or eax, EECLK
out dx, eax
ee_delay
 
shr esi, 1
jnc .loop
 
mov eax, EECS
out dx, eax
ee_delay
 
;------------------------
; Read 16-bits of data in
 
xor esi, esi
mov cx, 16
.loop2:
mov eax, EECS
out dx, eax
ee_delay
 
or eax, EECLK
out dx, eax
ee_delay
 
in eax, dx
shl esi, 1
test eax, EEDO
jz @f
inc esi
@@:
loop .loop2
 
;----------------------------
; Terminate the EEPROM access
 
xor eax, eax
out dx, eax
ee_delay
 
mov eax, EECLK
out dx, eax
ee_delay
 
movzx eax, si
 
ret
 
 
 
align 4
write_mac:
DEBUGF 1,'Setting MAC is not supported for SIS900 card.\n'
add esp, 6
ret
 
 
 
 
;***************************************************************************
; Function
; transmit
; Description
; Transmits a packet of data via the ethernet card
; buffer pointer in [esp+4]
; size of buffer in [esp+8]
; pointer to device structure in ebx
;
;***************************************************************************
align 4
transmit:
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
mov eax, [esp+4]
DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
 
cmp dword [esp + 8], MAX_ETH_FRAME_SIZE
ja .error
cmp dword [esp + 8], 60
jb .error
 
movzx ecx, [device.cur_tx]
shl ecx, 4 ; *16
lea ecx, [device.txd + ecx]
 
test dword [ecx + 4], 0x80000000 ; card owns descriptor ?
jnz .error
 
mov eax, [esp + 4]
mov dword [ecx + 12], eax
GetRealAddr
mov dword [ecx + 8], eax ; buffer address
 
mov eax, [esp + 8]
and eax, DSIZE
or eax, 0x80000000 ; card owns descriptor
mov dword [ecx + 4], eax ; status field
 
set_io 0
set_io cr
in eax, dx
or eax, TxENA ; Enable the transmit state machine
out dx, eax
 
inc [device.cur_tx]
and [device.cur_tx], NUM_TX_DESC-1
 
; update stats
mov ecx, [esp + 8]
inc [device.packets_tx]
add dword [device.bytes_tx], ecx
adc dword [device.bytes_tx + 4], 0
 
.finish:
DEBUGF 1,"Packet sent!\n"
xor eax, eax
ret 8
 
.error:
DEBUGF 1,"ERROR!\n"
stdcall KernelFree, [esp+4]
or eax, -1
ret 8
 
 
;***************************************************************************
;
; int_handler
;
; handles received IRQs, which signal received packets
;
; Currently only supports one descriptor per packet, if packet is fragmented
; between multiple descriptors you will lose part of the packet
;
;***************************************************************************
 
align 4
int_handler:
 
DEBUGF 1,"\n%s int\n", my_service
 
; find pointer of device which made IRQ occur
 
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
set_io 0
set_io isr
in eax, dx ; note that this clears all interrupts
test ax, IE
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
ret
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x ", ebx, ax
 
test ax, RxOK
jz .no_rx_
 
push ax
 
.rx_loop:
 
;-----------
; Get Status
movzx eax, [device.cur_rx] ; find current descriptor
shl eax, 4 ; * 16
mov ecx, dword[device.rxd + eax + 4] ; get receive status
 
;-------------------------------------------
; Check RX_Status to see if packet is waiting
test ecx, 0x80000000
jz .no_rx
 
;----------------------------------------------
; There is a packet waiting check it for errors
test ecx, 0x67C0000 ; see if there are any errors
jnz .error_status
 
;---------------------
; Check size of packet
and ecx, DSIZE ; get packet size minus CRC
sub ecx, CRC_SIZE ; make sure packet contains data
jbe .error_size
 
; update statistics
inc dword [device.packets_rx]
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
 
push ebx
push .return
push ecx ; packet size
pushd [device.rxd + eax + 12] ; packet ptr
DEBUGF 1, "Packet received OK\n"
jmp Eth_input
.return:
pop ebx
 
; Reset status, allow ethernet card access to descriptor
stdcall KernelAlloc, RX_BUFF_SZ
test eax, eax
jz .fail
movzx ecx, [device.cur_rx]
shl ecx, 4 ; *16
lea ecx, [device.rxd + ecx]
mov dword [ecx + 12], eax
GetRealAddr
mov dword [ecx + 8], eax
mov dword [ecx + 4], RX_BUFF_SZ
 
inc [device.cur_rx] ; get next descriptor
and [device.cur_rx], NUM_RX_DESC-1 ; only 4 descriptors 0-3
 
jmp .rx_loop
 
.no_rx:
set_io 0
set_io cr
in eax, dx
or eax, RxENA ; Re-Enable the Receive state machine
out dx, eax
 
pop ax
 
.no_rx_:
test ax, TxOK
jz .no_tx
 
DEBUGF 1, "TX ok!\n"
 
.tx_loop:
movzx ecx, [device.last_tx]
shl ecx, 4 ; *16
lea ecx, [device.txd + ecx]
 
test dword [ecx + 4], 0x80000000 ; card owns descr
jnz .no_tx
cmp dword [ecx + 12], 0
je .no_tx
 
DEBUGF 1, "Freeing packet = %x\n", [ecx + 12]:8
push dword [ecx + 12]
mov dword [ecx + 12], 0
call KernelFree
 
inc [device.last_tx]
and [device.last_tx], NUM_TX_DESC-1
jmp .tx_loop
 
.no_tx:
 
ret
 
.error_status:
DEBUGF 1, "Packet error: %x\n", ecx
jmp .fail
 
.error_size:
DEBUGF 1, "Packet too large/small\n"
jmp .fail
 
.fail:
DEBUGF 1, "FAILED\n"
jmp $
ret
 
 
 
; End of code
 
align 4 ; Place all initialised data here
 
devices dd 0
 
specific_table:
; dd SIS630A_900_REV, Get_Mac_SIS630A_900_REV, 0
; dd SIS630E_900_REV, Get_Mac_SIS630E_900_REV, 0
dd SIS630S_900_REV, Get_Mac_SIS635_900_REV, 0
dd SIS630EA1_900_REV, Get_Mac_SIS635_900_REV, 0
dd SIS630ET_900_REV, Get_Mac_SIS635_900_REV, 0 ;SIS630ET_900_REV_SpecialFN
dd SIS635A_900_REV, Get_Mac_SIS635_900_REV, 0
dd SIS900_960_REV, SIS960_get_mac_addr, 0
dd SIS900B_900_REV, SIS900_get_mac_addr, 0
dd 0 ; end of list
 
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'SIS900',0 ; max 16 chars include zero
 
include_debug_strings ; All data wich FDO uses will be included here
 
section '.data' data readable writable align 16; place all uninitialized data place here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/drivers/sceletone.asm
0,0 → 1,173
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;driver sceletone
 
format MS COFF
 
DEBUG equ 1
 
API_VERSION equ 0 ;debug
 
include 'proc32.inc'
include 'imports.inc'
 
struc IOCTL
{ .handle dd ?
.io_code dd ?
.input dd ?
.inp_size dd ?
.output dd ?
.out_size dd ?
}
 
virtual at 0
IOCTL IOCTL
end virtual
 
public START
public service_proc
public version
 
DRV_ENTRY equ 1
DRV_EXIT equ -1
STRIDE equ 4 ;size of row in devices table
 
SRV_GETVERSION equ 0
 
section '.flat' code readable align 16
 
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
.entry:
 
if DEBUG
mov esi, msgInit
call SysMsgBoardStr
end if
 
stdcall RegService, my_service, service_proc
ret
.fail:
.exit:
xor eax, eax
ret
endp
 
handle equ IOCTL.handle
io_code equ IOCTL.io_code
input equ IOCTL.input
inp_size equ IOCTL.inp_size
output equ IOCTL.output
out_size equ IOCTL.out_size
 
align 4
proc service_proc stdcall, ioctl:dword
 
mov ebx, [ioctl]
mov eax, [ebx+io_code]
cmp eax, SRV_GETVERSION
jne @F
 
mov eax, [ebx+output]
cmp [ebx+out_size], 4
jne .fail
mov [eax], dword API_VERSION
xor eax, eax
ret
@@:
.fail:
or eax, -1
ret
endp
 
restore handle
restore io_code
restore input
restore inp_size
restore output
restore out_size
 
align 4
proc detect
locals
last_bus dd ?
endl
 
xor eax, eax
mov [bus], eax
inc eax
call PciApi
cmp eax, -1
je .err
 
mov [last_bus], eax
 
.next_bus:
and [devfn], 0
.next_dev:
stdcall PciRead32, [bus], [devfn], dword 0
test eax, eax
jz .next
cmp eax, -1
je .next
 
mov edi, devices
@@:
mov ebx, [edi]
test ebx, ebx
jz .next
 
cmp eax, ebx
je .found
 
add edi, STRIDE
jmp @B
.next:
inc [devfn]
cmp [devfn], 256
jb .next_dev
mov eax, [bus]
inc eax
mov [bus], eax
cmp eax, [last_bus]
jna .next_bus
xor eax, eax
ret
.found:
xor eax, eax
inc eax
ret
.err:
xor eax, eax
ret
endp
 
DEVICE_ID equ 1234; pci device id
VENDOR_ID equ 5678; device vendor id
 
 
;all initialized data place here
 
align 4
devices dd (DEVICE_ID shl 16)+VENDOR_ID
dd 0 ;terminator
 
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
 
my_service db 'MY_SERVICE',0 ;max 16 chars include zero
 
msgInit db 'detect hardware...',13,10,0
msgPCI db 'PCI accsess not supported',13,10,0
msgFail db 'device not found',13,10,0
 
section '.data' data readable writable align 16
 
;all uninitialized data place here
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/drivers/fdo.inc
0,0 → 1,432
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
;
; Formatted Debug Output (FDO)
; Copyright (c) 2005-2006, mike.dld
; Created: 2005-01-29, Changed: 2006-11-10
;
; For questions and bug reports, mail to mike.dld@gmail.com
;
; Available format specifiers are: %s, %d, %u, %x (with partial width support)
;
 
; to be defined:
; __DEBUG__ equ 1
; __DEBUG_LEVEL__ equ 5
 
macro debug_func name {
if used name
name@of@func equ name
}
 
macro debug_beginf {
align 4
name@of@func:
}
 
debug_endf fix end if
 
macro DEBUGS _sign,[_str] {
common
local tp
tp equ 0
match _arg:_num,_str \{
DEBUGS_N _sign,_num,_arg
tp equ 1
\}
match =0 _arg,tp _str \{
DEBUGS_N _sign,,_arg
\}
}
 
macro DEBUGS_N _sign,_num,[_str] {
common
pushf
pushad
local ..str,..label,is_str
is_str = 0
forward
if _str eqtype ''
is_str = 1
end if
common
if is_str = 1
jmp ..label
..str db _str,0
..label:
add esp,4*8+4
mov edx,..str
sub esp,4*8+4
else
mov edx,_str
end if
if ~_num eq
if _num eqtype eax
if _num in <eax,ebx,ecx,edx,edi,ebp,esp>
mov esi,_num
else if ~_num eq esi
movzx esi,_num
end if
else if _num eqtype 0
mov esi,_num
else
local tp
tp equ 0
match [_arg],_num \{
mov esi,dword[_arg]
tp equ 1
\}
match =0 =dword[_arg],tp _num \{
mov esi,dword[_arg]
tp equ 1
\}
match =0 =word[_arg],tp _num \{
movzx esi,word[_arg]
tp equ 1
\}
match =0 =byte[_arg],tp _num \{
movzx esi,byte[_arg]
tp equ 1
\}
match =0,tp \{
'Error: specified string width is incorrect'
\}
end if
else
mov esi,0x7FFFFFFF
end if
call fdo_debug_outstr
popad
popf
}
 
macro DEBUGD _sign,_dec {
local tp
tp equ 0
match _arg:_num,_dec \{
DEBUGD_N _sign,_num,_arg
tp equ 1
\}
match =0 _arg,tp _dec \{
DEBUGD_N _sign,,_arg
\}
}
 
macro DEBUGD_N _sign,_num,_dec {
pushf
pushad
if (~_num eq)
if (_dec eqtype eax | _dec eqtype 0)
'Error: precision allowed only for in-memory variables'
end if
if (~_num in <1,2,4>)
if _sign
'Error: 1, 2 and 4 are only allowed for precision in %d'
else
'Error: 1, 2 and 4 are only allowed for precision in %u'
end if
end if
end if
if _dec eqtype eax
if _dec in <ebx,ecx,edx,esi,edi,ebp,esp>
mov eax,_dec
else if ~_dec eq eax
if _sign = 1
movsx eax,_dec
else
movzx eax,_dec
end if
end if
else if _dec eqtype 0
mov eax,_dec
else
add esp,4*8+4
if _num eq
mov eax,dword _dec
else if _num = 1
if _sign = 1
movsx eax,byte _dec
else
movzx eax,byte _dec
end if
else if _num = 2
if _sign = 1
movsx eax,word _dec
else
movzx eax,word _dec
end if
else
mov eax,dword _dec
end if
sub esp,4*8+4
end if
mov cl,_sign
call fdo_debug_outdec
popad
popf
}
 
macro DEBUGH _sign,_hex {
local tp
tp equ 0
match _arg:_num,_hex \{
DEBUGH_N _sign,_num,_arg
tp equ 1
\}
match =0 _arg,tp _hex \{
DEBUGH_N _sign,,_arg
\}
}
 
macro DEBUGH_N _sign,_num,_hex {
pushf
pushad
if (~_num eq) & (~_num in <1,2,3,4,5,6,7,8>)
'Error: 1..8 are only allowed for precision in %x'
end if
if _hex eqtype eax
if _hex in <eax,ebx,ecx,edx,esi,edi,ebp,esp>
if ~_hex eq eax
mov eax,_hex
end if
mov edx,8
else if _hex in <ax,bx,cx,dx,si,di,bp,sp>
if ~_hex eq ax
movzx eax,_hex
end if
if (_num eq)
mov edx,4
end if
else if _hex in <al,ah,bl,bh,cl,ch,dl,dh>
if ~_hex eq al
movzx eax,_hex
end if
if (_num eq)
mov edx,2
end if
end if
else if _hex eqtype 0
mov eax,_hex
else
add esp,4*8+4
mov eax,dword _hex
sub esp,4*8+4
end if
if ~_num eq
mov edx,_num
else
if ~_hex eqtype eax
mov edx,8
end if
end if
call fdo_debug_outhex
popad
popf
}
 
;-----------------------------------------------------------------------------
 
debug_func fdo_debug_outchar
debug_beginf
pushad
movzx ebx,al
mov eax,1
; mov ecx,sys_msg_board
; call ecx ; sys_msg_board
stdcall SysMsgBoardChar
popad
ret
debug_endf
 
debug_func fdo_debug_outstr
debug_beginf
mov eax,1
.l1: dec esi
js .l2
movzx ebx,byte[edx]
or bl,bl
jz .l2
; mov ecx,sys_msg_board
; call ecx ; sys_msg_board
stdcall SysMsgBoardChar
inc edx
jmp .l1
.l2: ret
debug_endf
 
debug_func fdo_debug_outdec
debug_beginf
or cl,cl
jz @f
or eax,eax
jns @f
neg eax
push eax
mov al,'-'
call fdo_debug_outchar
pop eax
@@: push 10
pop ecx
push -'0'
.l1: xor edx,edx
div ecx
push edx
test eax,eax
jnz .l1
.l2: pop eax
add al,'0'
jz .l3
call fdo_debug_outchar
jmp .l2
.l3: ret
debug_endf
 
debug_func fdo_debug_outhex
__fdo_hexdigits db '0123456789ABCDEF'
debug_beginf
mov cl,dl
neg cl
add cl,8
shl cl,2
rol eax,cl
.l1: rol eax,4
push eax
and eax,0x0000000F
mov al,[__fdo_hexdigits+eax]
call fdo_debug_outchar
pop eax
dec edx
jnz .l1
ret
debug_endf
 
;-----------------------------------------------------------------------------
 
macro DEBUGF _level,_format,[_arg] {
common
if __DEBUG__ = 1 & _level >= __DEBUG_LEVEL__
local ..f1,f2,a1,a2,c1,c2,c3,..lbl
_debug_str_ equ __debug_str_ # a1
a1 = 0
c2 = 0
c3 = 0
f2 = 0
repeat ..lbl-..f1
virtual at 0
db _format,0,0
load c1 word from %-1
end virtual
if c1 = '%s'
virtual at 0
db _format,0,0
store word 0 at %-1
load c1 from f2-c2
end virtual
if c1 <> 0
DEBUGS 0,_debug_str_+f2-c2
end if
c2 = c2 + 1
f2 = %+1
DEBUGF_HELPER S,a1,0,_arg
else if c1 = '%x'
virtual at 0
db _format,0,0
store word 0 at %-1
load c1 from f2-c2
end virtual
if c1 <> 0
DEBUGS 0,_debug_str_+f2-c2
end if
c2 = c2 + 1
f2 = %+1
DEBUGF_HELPER H,a1,0,_arg
else if c1 = '%d' | c1 = '%u'
local c4
if c1 = '%d'
c4 = 1
else
c4 = 0
end if
virtual at 0
db _format,0,0
store word 0 at %-1
load c1 from f2-c2
end virtual
if c1 <> 0
DEBUGS 0,_debug_str_+f2-c2
end if
c2 = c2 + 1
f2 = %+1
DEBUGF_HELPER D,a1,c4,_arg
else if c1 = '\n'
c3 = c3 + 1
end if
end repeat
virtual at 0
db _format,0,0
load c1 from f2-c2
end virtual
if (c1<>0)&(f2<>..lbl-..f1-1)
DEBUGS 0,_debug_str_+f2-c2
end if
virtual at 0
..f1 db _format,0
..lbl:
__debug_strings equ __debug_strings,_debug_str_,<_format>,..lbl-..f1-1-c2-c3
end virtual
end if
}
 
macro __include_debug_strings dummy,[_id,_fmt,_len] {
common
local c1,a1,a2
forward
if defined _len & ~_len eq
_id:
a1 = 0
a2 = 0
repeat _len
virtual at 0
db _fmt,0,0
load c1 word from %+a2-1
end virtual
if (c1='%s')|(c1='%x')|(c1='%d')|(c1='%u')
db 0
a2 = a2 + 1
else if (c1='\n')
dw $0A0D
a1 = a1 + 1
a2 = a2 + 1
else
db c1 and 0x0FF
end if
end repeat
db 0
end if
}
 
macro DEBUGF_HELPER _letter,_num,_sign,[_arg] {
common
local num
num = 0
forward
if num = _num
DEBUG#_letter _sign,_arg
end if
num = num+1
common
_num = _num+1
}
 
macro include_debug_strings {
if __DEBUG__ = 1
match dbg_str,__debug_strings \{
__include_debug_strings dbg_str
\}
end if
}
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/drivers/proc32.inc
0,0 → 1,268
 
; Macroinstructions for defining and calling procedures
 
macro stdcall proc,[arg] ; directly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call proc }
 
macro invoke proc,[arg] ; indirectly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call [proc] }
 
macro ccall proc,[arg] ; directly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call proc
if size@ccall
add esp,size@ccall
end if }
 
macro cinvoke proc,[arg] ; indirectly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call [proc]
if size@ccall
add esp,size@ccall
end if }
 
macro proc [args] ; define procedure
{ common
match name params, args>
\{ define@proc name,<params \} }
 
prologue@proc equ prologuedef
 
macro prologuedef procname,flag,parmbytes,localbytes,reglist
{ if parmbytes | localbytes
push ebp
mov ebp,esp
if localbytes
sub esp,localbytes
end if
end if
irps reg, reglist \{ push reg \} }
 
epilogue@proc equ epiloguedef
 
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
{ irps reg, reglist \{ reverse pop reg \}
if parmbytes | localbytes
leave
end if
if flag and 10000b
retn
else
retn parmbytes
end if }
 
macro define@proc name,statement
{ local params,flag,regs,parmbytes,localbytes,current
if used name
name:
match =stdcall args, statement \{ params equ args
flag = 11b \}
match =stdcall, statement \{ params equ
flag = 11b \}
match =c args, statement \{ params equ args
flag = 10001b \}
match =c, statement \{ params equ
flag = 10001b \}
match =params, params \{ params equ statement
flag = 0 \}
virtual at ebp+8
match =uses reglist=,args, params \{ regs equ reglist
params equ args \}
match =regs =uses reglist, regs params \{ regs equ reglist
params equ \}
match =regs, regs \{ regs equ \}
match =,args, params \{ defargs@proc args \}
match =args@proc args, args@proc params \{ defargs@proc args \}
parmbytes = $ - (ebp+8)
end virtual
name # % = parmbytes/4
all@vars equ
current = 0
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
macro locals
\{ virtual at ebp-localbytes+current
macro label . \\{ deflocal@proc .,:, \\}
struc db [val] \\{ \common deflocal@proc .,db,val \\}
struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
macro endl
\{ purge label
restruc db,dw,dp,dd,dt,dq
restruc rb,rw,rp,rd,rt,rq
restruc byte,word,dword,pword,tword,qword
current = $-(ebp-localbytes)
end virtual \}
macro ret operand
\{ match any, operand \\{ retn operand \\}
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs>
\\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2
end if \} }
 
macro defargs@proc [arg]
{ common
if ~ arg eq
forward
local ..arg,current@arg
match argname:type, arg
\{ current@arg equ argname
label ..arg type
argname equ ..arg
if dqword eq type
dd ?,?,?,?
else if tbyte eq type
dd ?,?,?
else if qword eq type | pword eq type
dd ?,?
else
dd ?
end if \}
match =current@arg,current@arg
\{ current@arg equ arg
arg equ ..arg
..arg dd ? \}
common
args@proc equ current@arg
forward
restore current@arg
common
end if }
 
macro deflocal@proc name,def,[val]
{ common
match vars, all@vars \{ all@vars equ all@vars, \}
all@vars equ all@vars name
forward
local ..var,..tmp
..var def val
match =?, val \{ ..tmp equ \}
match any =dup (=?), val \{ ..tmp equ \}
match tmp : value, ..tmp : val
\{ tmp: end virtual
initlocal@proc ..var,def value
virtual at tmp\}
common
match first rest, ..var, \{ name equ first \} }
 
macro initlocal@proc name,def
{ virtual at name
def
size@initlocal = $ - name
end virtual
position@initlocal = 0
while size@initlocal > position@initlocal
virtual at name
def
if size@initlocal - position@initlocal < 2
current@initlocal = 1
load byte@initlocal byte from name+position@initlocal
else if size@initlocal - position@initlocal < 4
current@initlocal = 2
load word@initlocal word from name+position@initlocal
else
current@initlocal = 4
load dword@initlocal dword from name+position@initlocal
end if
end virtual
if current@initlocal = 1
mov byte [name+position@initlocal],byte@initlocal
else if current@initlocal = 2
mov word [name+position@initlocal],word@initlocal
else
mov dword [name+position@initlocal],dword@initlocal
end if
position@initlocal = position@initlocal + current@initlocal
end while }
 
macro endp
{ purge ret,locals,endl
finish@proc
purge finish@proc
restore regs@proc
match all,args@proc \{ restore all \}
restore args@proc
match all,all@vars \{ restore all \} }
 
macro local [var]
{ common
locals
forward done@local equ
match varname[count]:vartype, var
\{ match =BYTE, vartype \\{ varname rb count
restore done@local \\}
match =WORD, vartype \\{ varname rw count
restore done@local \\}
match =DWORD, vartype \\{ varname rd count
restore done@local \\}
match =PWORD, vartype \\{ varname rp count
restore done@local \\}
match =QWORD, vartype \\{ varname rq count
restore done@local \\}
match =TBYTE, vartype \\{ varname rt count
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
rq count+count
restore done@local \\}
match , done@local \\{ virtual
varname vartype
end virtual
rb count*sizeof.\#vartype
restore done@local \\} \}
match :varname:vartype, done@local:var
\{ match =BYTE, vartype \\{ varname db ?
restore done@local \\}
match =WORD, vartype \\{ varname dw ?
restore done@local \\}
match =DWORD, vartype \\{ varname dd ?
restore done@local \\}
match =PWORD, vartype \\{ varname dp ?
restore done@local \\}
match =QWORD, vartype \\{ varname dq ?
restore done@local \\}
match =TBYTE, vartype \\{ varname dt ?
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
dq ?,?
restore done@local \\}
match , done@local \\{ varname vartype
restore done@local \\} \}
match ,done@local
\{ var
restore done@local \}
common
endl }
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
/kernel/branches/net/drivers
Property changes:
Added: svn:ignore
+*.obj
/kernel/branches/net/blkdev/disk.inc
0,0 → 1,1305
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2011-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 2381 $
 
; =============================================================================
; ================================= Constants =================================
; =============================================================================
; Error codes for callback functions.
DISK_STATUS_OK = 0 ; success
DISK_STATUS_GENERAL_ERROR = -1; if no other code is suitable
DISK_STATUS_INVALID_CALL = 1 ; invalid input parameters
DISK_STATUS_NO_MEDIA = 2 ; no media present
DISK_STATUS_END_OF_MEDIA = 3 ; end of media while reading/writing data
; Driver flags. Represent bits in DISK.DriverFlags.
DISK_NO_INSERT_NOTIFICATION = 1
; Media flags. Represent bits in DISKMEDIAINFO.Flags.
DISK_MEDIA_READONLY = 1
 
; If too many partitions are detected,there is probably an error on the disk.
; 256 partitions should be enough for any reasonable use.
; Also, the same number is limiting the number of MBRs to process; if
; too many MBRs are visible,there probably is a loop in the MBR structure.
MAX_NUM_PARTITIONS = 256
 
; =============================================================================
; ================================ Structures =================================
; =============================================================================
; This structure defines all callback functions for working with the physical
; device. They are implemented by a driver. Objects with this structure reside
; in a driver.
struct DISKFUNC
strucsize dd ?
; Size of the structure. This field is intended for possible extensions of
; this structure. If a new function is added to this structure and a driver
; implements an old version, the caller can detect this by checking .strucsize,
; so the driver remains compatible.
close dd ?
; The pointer to the function which frees all driver-specific resources for
; the disk.
; Optional, may be NULL.
; void close(void* userdata);
closemedia dd ?
; The pointer to the function which informs the driver that the kernel has
; finished all processing with the current media. If media is removed, the
; driver should decline all requests to that media with DISK_STATUS_NO_MEDIA,
; even if new media is inserted, until this function is called. If media is
; removed, a new call to 'disk_media_changed' is not allowed until this
; function is called.
; Optional, may be NULL (if media is not removable).
; void closemedia(void* userdata);
querymedia dd ?
; The pointer to the function which determines capabilities of the media.
; int querymedia(void* userdata, DISKMEDIAINFO* info);
; Return value: one of DISK_STATUS_*
read dd ?
; The pointer to the function which reads data from the device.
; int read(void* userdata, void* buffer, __int64 startsector, int* numsectors);
; input: *numsectors = number of sectors to read
; output: *numsectors = number of sectors which were successfully read
; Return value: one of DISK_STATUS_*
write dd ?
; The pointer to the function which writes data to the device.
; Optional, may be NULL.
; int write(void* userdata, void* buffer, __int64 startsector, int* numsectors);
; input: *numsectors = number of sectors to write
; output: *numsectors = number of sectors which were successfully written
; Return value: one of DISK_STATUS_*
flush dd ?
; The pointer to the function which flushes the internal device cache.
; Optional, may be NULL.
; int flush(void* userdata);
; Return value: one of DISK_STATUS_*
; Note that read/write are called by the cache manager, so a driver should not
; create a software cache. This function is implemented for flushing a hardware
; cache, if it exists.
adjust_cache_size dd ?
; The pointer to the function which returns the cache size for this device.
; Optional, may be NULL.
; unsigned int adjust_cache_size(unsigned int suggested_size);
; Return value: 0 = disable cache, otherwise = used cache size in bytes.
ends
 
; This structure holds information on a medium.
; Objects with this structure are allocated by the kernel as a part of the DISK
; structure and are filled by a driver in the 'querymedia' callback.
struct DISKMEDIAINFO
Flags dd ?
; Combination of DISK_MEDIA_* bits.
SectorSize dd ?
; Size of the sector.
Capacity dq ?
; Size of the media in sectors.
ends
 
; This structure represents the disk cache. To follow the old implementation,
; there are two distinct caches for a disk, one for "system" data,and the other
; for "application" data.
struct DISKCACHE
mutex MUTEX
; Lock to protect the cache.
; The following fields are inherited from data32.inc:cache_ideX.
pointer dd ?
data_size dd ? ; unused
data dd ?
sad_size dd ?
search_start dd ?
ends
 
; This structure represents a disk device and its media for the kernel.
; This structure is allocated by the kernel in the 'disk_add' function,
; freed in the 'disk_dereference' function.
struct DISK
; Fields of disk object
Next dd ?
Prev dd ?
; All disk devices are linked in one list with these two fields.
; Head of the list is the 'disk_list' variable.
Functions dd ?
; Pointer to the 'DISKFUNC' structure with driver functions.
Name dd ?
; Pointer to the string used for accesses through the global filesystem.
UserData dd ?
; This field is passed to all callback functions so a driver can decide which
; physical device is addressed.
DriverFlags dd ?
; Bitfield. Currently only DISK_NO_INSERT_NOTIFICATION bit is defined.
; If it is set, the driver will never issue 'disk_media_changed' notification
; with argument set to true, so the kernel must try to detect media during
; requests from the file system.
RefCount dd ?
; Count of active references to this structure. One reference is kept during
; the lifetime of the structure between 'disk_add' and 'disk_del'.
; Another reference is taken during any filesystem operation for this disk.
; One reference is added if media is inserted.
; The structure is destroyed when the reference count decrements to zero:
; this usually occurs in 'disk_del', but can be delayed to the end of last
; filesystem operation, if one is active.
MediaLock MUTEX
; Lock to protect the MEDIA structure. See the description after
; 'disk_list_mutex' for the locking strategy.
; Fields of media object
MediaInserted db ?
; 0 if media is not inserted, nonzero otherwise.
MediaUsed db ?
; 0 if media fields are not used, nonzero otherwise. If .MediaRefCount is
; nonzero, this field is nonzero too; however, when .MediaRefCount goes
; to zero, there is some time interval during which media object is still used.
align 4
; The following fields are not valid unless either .MediaInserted is nonzero
; or they are accessed from a code which has obtained the reference when
; .MediaInserted was nonzero.
MediaRefCount dd ?
; Count of active references to the media object. One reference is kept during
; the lifetime of the media between two calls to 'disk_media_changed'.
; Another reference is taken during any filesystem operation for this media.
; The callback 'closemedia' is called when the reference count decrements to
; zero: this usually occurs in 'disk_media_changed', but can be delayed to the
; end of the last filesystem operation, if one is active.
MediaInfo DISKMEDIAINFO
; This field keeps information on the current media.
NumPartitions dd ?
; Number of partitions on this media.
Partitions dd ?
; Pointer to array of .NumPartitions pointers to PARTITION structures.
cache_size dd ?
; inherited from cache_ideX_size
SysCache DISKCACHE
AppCache DISKCACHE
; Two caches for the disk.
ends
 
; This structure represents one partition for the kernel. This is a base
; template, the actual contents after common fields is determined by the
; file system code for this partition.
struct PARTITION
FirstSector dq ?
; First sector of the partition.
Length dq ?
; Length of the partition in sectors.
Disk dd ?
; Pointer to parent DISK structure.
FSUserFunctions dd ?
; Handlers for the sysfunction 70h. This field is a pointer to the following
; array. The first dword is a number of supported subfunctions, other dwords
; point to handlers of corresponding subfunctions.
; This field is 0 if file system is not recognized.
; ...fs-specific data may follow...
ends
 
; This is an external structure, it represents an entry in the partition table.
struct PARTITION_TABLE_ENTRY
Bootable db ?
; 80h = bootable partition, 0 = non-bootable partition, other values = invalid
FirstHead db ?
FirstSector db ?
FirstTrack db ?
; Coordinates of first sector in CHS.
Type db ?
; Partition type, one of predefined constants. 0 = empty, several types denote
; extended partition (see process_partition_table_entry), we are not interested
; in other values.
LastHead db ?
LastSector db ?
LastTrack db ?
; Coordinates of last sector in CHS.
FirstAbsSector dd ?
; Coordinate of first sector in LBA.
Length dd ?
; Length of the partition in sectors.
ends
 
; =============================================================================
; ================================ Global data ================================
; =============================================================================
iglobal
; The pseudo-item for the list of all DISK structures.
; Initialized to the empty list.
disk_list:
dd disk_list
dd disk_list
endg
uglobal
; This mutex guards all operations with the global list of DISK structures.
disk_list_mutex MUTEX
; * There are two dependent objects, a disk and a media. In the simplest case,
; disk and media are both non-removable. However, in the general case both
; can be removed at any time, simultaneously or only media,and this makes things
; complicated.
; * For efficiency, both disk and media objects are located in the one
; structure named DISK. However, logically they are different.
; * The following operations use data of disk object: adding (disk_add);
; deleting (disk_del); filesystem (fs_lfn which eventually calls
; dyndisk_handler or dyndisk_enum_root).
; * The following operations use data of media object: adding/removing
; (disk_media_changed); filesystem (fs_lfn which eventually calls
; dyndisk_handler; dyndisk_enum_root doesn't work with media).
; * Notifications disk_add, disk_media_changed, disk_del are synchronized
; between themselves, this is a requirement for the driver. However, file
; system operations are asynchronous, can be issued at any time by any
; thread.
; * We must prevent a situation when a filesystem operation thinks that the
; object is still valid but in fact the notification has destroyed the
; object. So we keep a reference counter for both disk and media and destroy
; the object when this counter goes to zero.
; * The driver must know when it is safe to free driver-allocated resources.
; The object can be alive even after death notification has completed.
; We use special callbacks to satisfy both assertions: 'close' for the disk
; and 'closemedia' for the media. The destruction of the object includes
; calling the corresponding callback.
; * Each filesystem operation keeps one reference for the disk and one
; reference for the media. Notification disk_del forces notification on the
; media death, so the reference counter for the disk is always not less than
; the reference counter for the media.
; * Two operations "get the object" and "increment the reference counter" can
; not be done simultaneously. We use a mutex to guard the consistency here.
; It must be a part of the container for the object, so that this mutex can
; be acquired as a part of getting the object from the container. The
; container for disk object is the global list, and this list is guarded by
; 'disk_list_mutex'. The container for media object is the disk object, and
; the corresponding mutex is DISK.MediaLock.
; * Notifications do not change the data of objects, they can only remove
; objects. Thus we don't need another synchronization at this level. If two
; filesystem operations are referencing the same filesystem data, this is
; better resolved at the level of the filesystem.
endg
 
iglobal
; The function 'disk_scan_partitions' needs three 512-byte buffers for
; MBR, bootsector and fs-temporary sector data. It can not use the static
; buffers always, since it can be called for two or more disks in parallel.
; However, this case is not typical. We reserve three static 512-byte buffers
; and a flag that these buffers are currently used. If 'disk_scan_partitions'
; detects that the buffers are currently used, it allocates buffers from the
; heap.
; The flag is implemented as a global dword variable. When the static buffers
; are not used, the value is -1. When the static buffers are used, the value
; is normally 0 and temporarily can become greater. The function increments
; this value. If the resulting value is zero, it uses the buffers and
; decrements the value when the job is done. Otherwise, it immediately
; decrements the value and uses buffers from the heap, allocated in the
; beginning and freed in the end.
partition_buffer_users dd -1
endg
uglobal
; The static buffers for MBR, bootsector and fs-temporary sector data.
align 16
mbr_buffer rb 512
bootsect_buffer rb 512
fs_tmp_buffer rb 512
endg
 
iglobal
; This is the array of default implementations of driver callbacks.
; Same as DRIVERFUNC structure except for the first field; all functions must
; have the default implementations.
align 4
disk_default_callbacks:
dd disk_default_close
dd disk_default_closemedia
dd disk_default_querymedia
dd disk_default_read
dd disk_default_write
dd disk_default_flush
dd disk_default_adjust_cache_size
endg
 
; =============================================================================
; ================================= Functions =================================
; =============================================================================
 
; This function registers a disk device.
; This includes:
; - allocating an internal structure describing this device;
; - registering this structure in the global filesystem.
; The function initializes the disk as if there is no media. If a media is
; present, the function 'disk_media_changed' should be called after this
; function succeeds.
; Parameters:
; [esp+4] = pointer to DISKFUNC structure with the callbacks
; [esp+8] = pointer to name (ASCIIZ string)
; [esp+12] = userdata to be passed to the callbacks as is.
; [esp+16] = flags, bitfield. Currently only DISK_NO_INSERT_NOTIFICATION bit
; is defined.
; Return value:
; NULL = operation has failed
; non-NULL = handle of the disk. This handle can be used
; in the operations with other Disk* functions.
; The handle is the pointer to the internal structure DISK.
disk_add:
push ebx esi ; save used registers to be stdcall
; 1. Allocate the DISK structure.
; 1a. Call the heap manager.
push sizeof.DISK
pop eax
call malloc
; 1b. Check the result. If allocation failed, return (go to 9) with eax = 0.
test eax, eax
jz .nothing
; 2. Copy the disk name to the DISK structure.
; 2a. Get length of the name, including the terminating zero.
mov ebx, [esp+8+8] ; ebx = pointer to name
push eax ; save allocated pointer to DISK
xor eax, eax ; the argument of malloc() is in eax
@@:
inc eax
cmp byte [ebx+eax-1], 0
jnz @b
; 2b. Call the heap manager. Note that it can change ebx.
push ebx
call malloc
pop ebx
; 2c. Check the result. If allocation failed, go to 7.
pop esi ; restore allocated pointer to DISK
test eax, eax
jz .free
; 2d. Store the allocated pointer to the DISK structure.
mov [esi+DISK.Name], eax
; 2e. Copy the name.
@@:
mov dl, [ebx]
mov [eax], dl
inc ebx
inc eax
test dl, dl
jnz @b
; 3. Copy other arguments of the function to the DISK structure.
mov eax, [esp+4+8]
mov [esi+DISK.Functions], eax
mov eax, [esp+12+8]
mov [esi+DISK.UserData], eax
mov eax, [esp+16+8]
mov [esi+DISK.DriverFlags], eax
; 4. Initialize other fields of the DISK structure.
; Media is not inserted, reference counter is 1.
lea ecx, [esi+DISK.MediaLock]
call mutex_init
xor eax, eax
mov dword [esi+DISK.MediaInserted], eax
inc eax
mov [esi+DISK.RefCount], eax
; The DISK structure is initialized.
; 5. Insert the new structure to the global list.
; 5a. Acquire the mutex.
mov ecx, disk_list_mutex
call mutex_lock
; 5b. Insert item to the tail of double-linked list.
mov edx, disk_list
list_add_tail esi, edx ;esi= new edx= list head
; 5c. Release the mutex.
call mutex_unlock
; 6. Return with eax = pointer to DISK.
xchg eax, esi
jmp .nothing
.free:
; Memory allocation for DISK structure succeeded, but for disk name failed.
; 7. Free the DISK structure.
xchg eax, esi
call free
; 8. Return with eax = 0.
xor eax, eax
.nothing:
; 9. Return.
pop esi ebx ; restore used registers to be stdcall
ret 16 ; purge 4 dword arguments to be stdcall
 
; This function deletes a disk device from the global filesystem.
; This includes:
; - removing a media including all partitions;
; - deleting this structure from the global filesystem;
; - dereferencing the DISK structure and possibly destroying it.
; Parameters:
; [esp+4] = handle of the disk, i.e. the pointer to the DISK structure.
; Return value: none.
disk_del:
push esi ; save used registers to be stdcall
; 1. Force media to be removed. If the media is already removed, the
; call does nothing.
mov esi, [esp+4+4] ; esi = handle of the disk
stdcall disk_media_changed, esi, 0
; 2. Delete the structure from the global list.
; 2a. Acquire the mutex.
mov ecx, disk_list_mutex
call mutex_lock
; 2b. Delete item from double-linked list.
mov eax, [esi+DISK.Next]
mov edx, [esi+DISK.Prev]
mov [eax+DISK.Prev], edx
mov [edx+DISK.Next], eax
; 2c. Release the mutex.
call mutex_unlock
; 3. The structure still has one reference created in disk_add. Remove this
; reference. If there are no other references, disk_dereference will free the
; structure.
call disk_dereference
; 4. Return.
pop esi ; restore used registers to be stdcall
ret 4 ; purge 1 dword argument to be stdcall
 
; This is an internal function which removes a previously obtained reference
; to the disk. If this is the last reference, this function lets the driver
; finalize all associated data, and afterwards frees the DISK structure.
; esi = pointer to DISK structure
disk_dereference:
; 1. Decrement reference counter. Use atomic operation to correctly handle
; possible simultaneous calls.
lock dec [esi+DISK.RefCount]
; 2. If the result is nonzero, there are other references, so nothing to do.
; In this case, return (go to 4).
jnz .nothing
; 3. If we are here, we just removed the last reference and must destroy the
; disk object.
; 3a. Call the driver.
mov al, DISKFUNC.close
stdcall disk_call_driver
; 3b. Free the structure.
xchg eax, esi
push ebx
call free
pop ebx
; 4. Return.
.nothing:
ret
 
; This is an internal function which removes a previously obtained reference
; to the media. If this is the last reference, this function calls 'closemedia'
; callback to signal the driver that the processing has finished and it is safe
; to inform about a new media.
; esi = pointer to DISK structure
disk_media_dereference:
; 1. Decrement reference counter. Use atomic operation to correctly handle
; possible simultaneous calls.
lock dec [esi+DISK.MediaRefCount]
; 2. If the result is nonzero, there are other references, so nothing to do.
; In this case, return (go to 4).
jnz .nothing
; 3. If we are here, we just removed the last reference and must destroy the
; media object.
; Note that the same place inside the DISK structure is reused for all media
; objects, so we must guarantee that reusing does not happen while freeing.
; Reusing is only possible when someone processes a new media. There are two
; mutually exclusive variants:
; * driver issues media insert notifications (DISK_NO_INSERT_NOTIFICATION bit
; in DISK.DriverFlags is not set). In this case, we require from the driver
; that such notification (except for the first one) can occur only after a
; call to 'closemedia' callback.
; * driver does not issue media insert notifications. In this case, the kernel
; itself must sometimes check whether media is inserted. We have the flag
; DISK.MediaUsed, visible to the kernel. This flag signals to the other parts
; of kernel that the way is free.
; In the first case other parts of the kernel do not use DISK.MediaUsed, so it
; does not matter when this flag is cleared. In the second case this flag must
; be cleared after all other actions, including call to 'closemedia'.
; 3a. Free all partitions.
push esi edi
mov edi, [esi+DISK.NumPartitions]
mov esi, [esi+DISK.Partitions]
test edi, edi
jz .nofree
.freeloop:
lodsd
call free
dec edi
jnz .freeloop
.nofree:
pop edi esi
; 3b. Free the cache.
call disk_free_cache
; 3c. Call the driver.
mov al, DISKFUNC.closemedia
stdcall disk_call_driver
; 3d. Clear the flag.
mov [esi+DISK.MediaUsed], 0
.nothing:
ret
 
; This function is called by the driver and informs the kernel that the media
; has changed. If the media is non-removable, it is called exactly once
; immediately after 'disk_add' and once from 'disk_del'.
; Parameters:
; [esp+4] = handle of the disk, i.e. the pointer to the DISK structure.
; [esp+8] = new status of the media: zero = no media, nonzero = media inserted.
disk_media_changed:
push ebx esi edi ; save used registers to be stdcall
; 1. Remove the existing media, if it is present.
mov esi, [esp+4+12] ; esi = pointer to DISK
; 1a. Check whether it is present. Since DISK.MediaInserted is changed only
; in this function and calls to this function are synchronized, no lock is
; required for checking.
cmp [esi+DISK.MediaInserted], 0
jz .noremove
; We really need to remove the media.
; 1b. Acquire mutex.
lea ecx, [esi+DISK.MediaLock]
call mutex_lock
; 1c. Clear the flag.
mov [esi+DISK.MediaInserted], 0
; 1d. Release mutex.
call mutex_unlock
; 1e. Remove the "lifetime" reference and possibly destroy the structure.
call disk_media_dereference
.noremove:
; 2. Test whether there is new media.
cmp dword [esp+8+12], 0
jz .noinsert
; Yep, there is.
; 3. Process the new media. We assume that all media fields are available to
; use, see comments in 'disk_media_dereference' (this covers using by previous
; media referencers) and note that calls to this function are synchronized
; (this covers using by new media referencers).
; 3a. Call the 'querymedia' callback.
; .Flags are set to zero for possible future extensions.
lea edx, [esi+DISK.MediaInfo]
and [edx+DISKMEDIAINFO.Flags], 0
mov al, DISKFUNC.querymedia
stdcall disk_call_driver, edx
; 3b. Check the result of the callback. Abort if it failed.
test eax, eax
jnz .noinsert
; 3c. Allocate the cache unless disabled by the driver. Abort if failed.
call disk_init_cache
test al, al
jz .noinsert
; 3d. Acquire the lifetime reference for the media object.
inc [esi+DISK.MediaRefCount]
; 3e. Scan for partitions. Ignore result; the list of partitions is valid even
; on errors.
call disk_scan_partitions
; 3f. Media is inserted and available for use.
inc [esi+DISK.MediaInserted]
.noinsert:
; 4. Return.
pop edi esi ebx ; restore used registers to be stdcall
ret 8 ; purge 2 dword arguments to be stdcall
 
; This function is a thunk for all functions of a disk driver.
; It checks whether the referenced function is implemented in the driver.
; If so, this function jumps to the function in the driver.
; Otherwise, it jumps to the default implementation.
; al = offset of function in the DISKFUNC structure;
; esi = pointer to the DISK structure;
; stack is the same as for the corresponding function except that the
; first parameter (void* userdata) is prepended automatically.
disk_call_driver:
movzx eax, al ; eax = offset of function in the DISKFUNC structure
; 1. Prepend the first argument to the stack.
pop ecx ; ecx = return address
push [esi+DISK.UserData] ; add argument
push ecx ; save return address
; 2. Check that the required function is inside the table. If not, go to 5.
mov ecx, [esi+DISK.Functions]
cmp eax, [ecx+DISKFUNC.strucsize]
jae .default
; 3. Check that the required function is implemented. If not, go to 5.
mov ecx, [ecx+eax]
test ecx, ecx
jz .default
; 4. Jump to the required function.
jmp ecx
.default:
; 5. Driver does not implement the required function; use default implementation.
jmp dword [disk_default_callbacks+eax-4]
 
; The default implementation of DISKFUNC.querymedia.
disk_default_querymedia:
push DISK_STATUS_INVALID_CALL
pop eax
ret 8
 
; The default implementation of DISKFUNC.read and DISKFUNC.write.
disk_default_read:
disk_default_write:
push DISK_STATUS_INVALID_CALL
pop eax
ret 20
 
; The default implementation of DISKFUNC.close, DISKFUNC.closemedia and
; DISKFUNC.flush.
disk_default_close:
disk_default_closemedia:
disk_default_flush:
xor eax, eax
ret 4
 
; The default implementation of DISKFUNC.adjust_cache_size.
disk_default_adjust_cache_size:
mov eax, [esp+8]
ret 8
 
; This is an internal function called from 'disk_media_changed' when a new media
; is detected. It creates the list of partitions for the media.
; If media is not partitioned, then the list consists of one partition which
; covers all the media.
; esi = pointer to the DISK structure.
disk_scan_partitions:
; 1. Initialize .NumPartitions and .Partitions fields as zeros: empty list.
and [esi+DISK.NumPartitions], 0
and [esi+DISK.Partitions], 0
; 2. Currently we can work only with 512-bytes sectors. Check this restriction.
; The only exception is 2048-bytes CD/DVD, but they are not supported yet by
; this code.
cmp [esi+DISK.MediaInfo.SectorSize], 512
jz .doscan
DEBUGF 1,'K : sector size is %d, only 512 is supported\n',[esi+DISK.MediaInfo.SectorSize]
ret
.doscan:
; 3. Acquire the buffer for MBR and bootsector tests. See the comment before
; the 'partition_buffer_users' variable.
mov ebx, mbr_buffer ; assume the global buffer is free
lock inc [partition_buffer_users]
jz .buffer_acquired ; yes, it is free
lock dec [partition_buffer_users] ; no, we must allocate
stdcall kernel_alloc, 512*3
test eax, eax
jz .nothing
xchg eax, ebx
.buffer_acquired:
; MBR/EBRs are organized in the chain. We use a loop over MBR/EBRs, but no
; more than MAX_NUM_PARTITION times.
; 4. Prepare things for the loop.
; ebp will hold the sector number for current MBR/EBR.
; [esp] will hold the sector number for current extended partition, if there
; is one.
; [esp+4] will hold the counter that prevents long loops.
push ebp ; save ebp
push MAX_NUM_PARTITIONS ; the counter of max MBRs to process
xor ebp, ebp ; start from sector zero
push ebp ; no extended partition yet
.new_mbr:
; 5. Read the current sector.
; Note that 'read' callback operates with 64-bit sector numbers, so we must
; push additional zero as a high dword of sector number.
mov al, DISKFUNC.read
push 1
stdcall disk_call_driver, ebx, ebp, 0, esp
pop ecx
; 6. If the read has failed, abort the loop.
dec ecx
jnz .mbr_failed
; 7. Check the MBR/EBR signature. If it is wrong, abort the loop.
; Soon we will access the partition table which starts at ebx+0x1BE,
; so we can fill its address right now. If we do it now, then the addressing
; [ecx+0x40] is shorter than [ebx+0x1fe]: one-byte offset vs 4-bytes offset.
lea ecx, [ebx+0x1be] ; ecx -> partition table
cmp word [ecx+0x40], 0xaa55
jnz .mbr_failed
; 8. The MBR is treated differently from EBRs. For MBR we additionally need to
; execute step 9 and possibly step 10.
test ebp, ebp
jnz .mbr
; The partition table can be present or not present. In the first case, we just
; read the MBR. In the second case, we just read the bootsector for a
; filesystem.
; The following algorithm is used to distinguish between these cases.
; A. If at least one entry of the partition table is invalid, this is
; a bootsector. See the description of 'is_partition_table_entry' for
; definition of validity.
; B. If all entries are empty (filesystem type field is zero) and the first
; byte is jmp opcode (0EBh or 0E9h), this is a bootsector which happens to
; have zeros in the place of partition table.
; C. Otherwise, this is an MBR.
; 9. Test for MBR vs bootsector.
; 9a. Check entries. If any is invalid, go to 10 (rule A).
call is_partition_table_entry
jc .notmbr
add ecx, 10h
call is_partition_table_entry
jc .notmbr
add ecx, 10h
call is_partition_table_entry
jc .notmbr
add ecx, 10h
call is_partition_table_entry
jc .notmbr
; 9b. Check types of the entries. If at least one is nonzero, go to 11 (rule C).
mov al, [ecx-30h+PARTITION_TABLE_ENTRY.Type]
or al, [ecx-20h+PARTITION_TABLE_ENTRY.Type]
or al, [ecx-10h+PARTITION_TABLE_ENTRY.Type]
or al, [ecx+PARTITION_TABLE_ENTRY.Type]
jnz .mbr
; 9c. Empty partition table or bootsector with many zeroes? (rule B)
cmp byte [ebx], 0EBh
jz .notmbr
cmp byte [ebx], 0E9h
jnz .mbr
.notmbr:
; 10. This is not an MBR. The media is not partitioned. Create one partition
; which covers all the media and abort the loop.
stdcall disk_add_partition, 0, 0, \
dword [esi+DISK.MediaInfo.Capacity], dword [esi+DISK.MediaInfo.Capacity+4]
jmp .done
.mbr:
; 11. Process all entries of the new MBR/EBR
lea ecx, [ebx+0x1be] ; ecx -> partition table
push 0 ; assume no extended partition
call process_partition_table_entry
add ecx, 10h
call process_partition_table_entry
add ecx, 10h
call process_partition_table_entry
add ecx, 10h
call process_partition_table_entry
pop ebp
; 12. Test whether we found a new EBR and should continue the loop.
; 12a. If there was no next EBR, return.
test ebp, ebp
jz .done
; Ok, we have EBR.
; 12b. EBRs addresses are relative to the start of extended partition.
; For simplicity, just abort if an 32-bit overflow occurs; large disks
; are most likely partitioned with GPT, not MBR scheme, since the precise
; calculation here would increase limit just twice at the price of big
; compatibility problems.
pop eax ; load extended partition
add ebp, eax
jc .mbr_failed
; 12c. If extended partition has not yet started, start it.
test eax, eax
jnz @f
mov eax, ebp
@@:
; 12c. If the limit is not exceeded, continue the loop.
dec dword [esp]
push eax ; store extended partition
jnz .new_mbr
.mbr_failed:
.done:
; 13. Cleanup after the loop.
pop eax ; not important anymore
pop eax ; not important anymore
pop ebp ; restore ebp
; 14. Release the buffer.
; 14a. Test whether it is the global buffer or we have allocated it.
cmp ebx, mbr_buffer
jz .release_partition_buffer
; 14b. If we have allocated it, free it.
xchg eax, ebx
call free
jmp .nothing
; 14c. Otherwise, release reference.
.release_partition_buffer:
lock dec [partition_buffer_users]
.nothing:
; 15. Return.
ret
 
; This is an internal function called from disk_scan_partitions. It checks
; whether the entry pointed to by ecx is a valid entry of partition table.
; The entry is valid if the first byte is 0 or 80h, the first sector plus the
; length is less than twice the size of media. Multiplication by two is
; required since the size mentioned in the partition table can be slightly
; greater than the real size.
is_partition_table_entry:
; 1. Check .Bootable field.
mov al, [ecx+PARTITION_TABLE_ENTRY.Bootable]
and al, 7Fh
jnz .invalid
; 3. Calculate first sector + length. Note that .FirstAbsSector is relative
; to the MBR/EBR, so the real sum is ebp + .FirstAbsSector + .Length.
mov eax, ebp
xor edx, edx
add eax, [ecx+PARTITION_TABLE_ENTRY.FirstAbsSector]
adc edx, 0
add eax, [ecx+PARTITION_TABLE_ENTRY.Length]
adc edx, 0
; 4. Divide by two.
shr edx, 1
rcr eax, 1
; 5. Compare with capacity. If the subtraction (edx:eax) - .Capacity does not
; overflow, this is bad.
sub eax, dword [esi+DISK.MediaInfo.Capacity]
sbb edx, dword [esi+DISK.MediaInfo.Capacity+4]
jnc .invalid
.valid:
; 5. Return success: CF is cleared.
clc
ret
.invalid:
; 6. Return fail: CF is set.
stc
ret
 
; This is an internal function called from disk_scan_partitions. It processes
; the entry pointed to by ecx.
; * If the entry is invalid, just ignore this entry.
; * If the type is zero, just ignore this entry.
; * If the type is one of types for extended partition, store the address
; of this partition as the new MBR in [esp+4].
; * Otherwise, add the partition to the list of partitions for this disk.
; We don't use the type from the entry to identify the file system;
; fs-specific checks do this more reliably.
process_partition_table_entry:
; 1. Check for valid entry. If invalid, return (go to 5).
call is_partition_table_entry
jc .nothing
; 2. Check for empty entry. If invalid, return (go to 5).
mov al, [ecx+PARTITION_TABLE_ENTRY.Type]
test al, al
jz .nothing
; 3. Check for extended partition. If extended, go to 6.
irp type,\
0x05,\ ; DOS: extended partition
0x0f,\ ; WIN95: extended partition, LBA-mapped
0xc5,\ ; DRDOS/secured: extended partition
0xd5 ; Old Multiuser DOS secured: extended partition
{
cmp al, type
jz .extended
}
; 4. If we are here, that is a normal partition. Add it to the list.
; Note that the first sector is relative to MBR/EBR.
mov eax, ebp
xor edx, edx
add eax, [ecx+PARTITION_TABLE_ENTRY.FirstAbsSector]
adc edx, 0
push ecx
stdcall disk_add_partition, eax, edx, \
[ecx+PARTITION_TABLE_ENTRY.Length], 0
pop ecx
.nothing:
; 5. Return.
ret
.extended:
; 6. If we are here, that is an extended partition. Store the address.
mov eax, [ecx+PARTITION_TABLE_ENTRY.FirstAbsSector]
mov [esp+4], eax
ret
 
; This is an internal function called from disk_scan_partitions and
; process_partition_table_entry. It adds one partition to the list of
; partitions for the media.
proc disk_add_partition stdcall uses ebx edi, start:qword, length:qword
; 1. Check that this partition will not exceed the limit on total number.
cmp [esi+DISK.NumPartitions], MAX_NUM_PARTITIONS
jae .nothing
; 2. Check that this partition does not overlap with any already registered
; partition. Since any file system assumes that the disk data will not change
; outside of its control, such overlap could be destructive.
; Since the number of partitions is usually very small and is guaranteed not
; to be large, the simple linear search is sufficient.
; 2a. Prepare the loop: edi will point to the current item of .Partitions
; array, ecx will be the current item, ebx will hold number of items left.
mov edi, [esi+DISK.Partitions]
mov ebx, [esi+DISK.NumPartitions]
test ebx, ebx
jz .partitionok
.scan_existing:
; 2b. Get the next partition.
mov ecx, [edi]
add edi, 4
; The range [.FirstSector, .FirstSector+.Length) must be either entirely to
; the left of [start, start+length) or entirely to the right.
; 2c. Subtract .FirstSector - start. The possible overflow distinguish between
; cases "to the left" (2e) and "to the right" (2d).
mov eax, dword [ecx+PARTITION.FirstSector]
mov edx, dword [ecx+PARTITION.FirstSector+4]
sub eax, dword [start]
sbb edx, dword [start+4]
jb .less
; 2d. .FirstSector is greater than or equal to start. Check that .FirstSector
; is greater than or equal to start+length; the subtraction
; (.FirstSector-start) - length must not cause overflow. Go to 2g if life is
; good or to 2f in the other case.
sub eax, dword [length]
sbb edx, dword [length+4]
jb .overlap
jmp .next_existing
.less:
; 2e. .FirstSector is less than start. Check that .FirstSector+.Length is less
; than or equal to start. If the addition (.FirstSector-start) + .Length does
; not cause overflow, then .FirstSector + .Length is strictly less than start;
; since the equality is also valid, use decrement preliminarily. Go to 2g or
; 2f depending on the overflow.
sub eax, 1
sbb edx, 0
add eax, dword [ecx+PARTITION.Length]
adc edx, dword [ecx+PARTITION.Length+4]
jnc .next_existing
.overlap:
; 2f. The partition overlaps with previously registered partition. Say warning
; and return with nothing done.
dbgstr 'two partitions overlap, ignoring the last one'
jmp .nothing
.next_existing:
; 2g. The partition does not overlap with the current partition. Continue the
; loop.
dec ebx
jnz .scan_existing
.partitionok:
; 3. The partition has passed tests. Reallocate the partitions array for a new
; entry.
; 3a. Call the allocator.
mov eax, [esi+DISK.NumPartitions]
inc eax ; one more entry
shl eax, 2 ; each entry is dword
call malloc
; 3b. Test the result. If failed, return with nothing done.
test eax, eax
jz .nothing
; 3c. Copy the old array to the new array.
mov edi, eax
push esi
mov ecx, [esi+DISK.NumPartitions]
mov esi, [esi+DISK.Partitions]
rep movsd
pop esi
; 3d. Set the field in the DISK structure to the new array.
xchg [esi+DISK.Partitions], eax
; 3e. Free the old array.
call free
; 4. Recognize the file system.
; 4a. Call the filesystem recognizer. It will allocate the PARTITION structure
; with possible filesystem-specific fields.
call disk_detect_partition
; 4b. Check return value. If zero, return with list not changed; so far only
; the array was reallocated, this is ok for other code.
test eax, eax
jz .nothing
; 5. Insert the new partition to the list.
stosd
inc [esi+DISK.NumPartitions]
; 6. Return.
.nothing:
ret
endp
 
; This is an internal function called from disk_add_partition.
; It tries to recognize the file system on the partition and allocates the
; corresponding PARTITION structure with filesystem-specific fields.
disk_detect_partition:
; This function inherits the stack frame from disk_add_partition. In stdcall
; with ebp-based frame arguments start from ebp+8, since [ebp]=saved ebp
; and [ebp+4]=return address.
virtual at ebp+8
.start dq ?
.length dq ?
end virtual
; When disk_add_partition is called, ebx contains a pointer to
; a two-sectors-sized buffer. This function saves ebx in the stack
; immediately before ebp.
virtual at ebp-4
.buffer dd ?
end virtual
; 1. Read the bootsector to the buffer.
mov al, DISKFUNC.read
mov ebx, [.buffer]
add ebx, 512
push 1
stdcall disk_call_driver, ebx, dword [.start], dword [.start+4], esp
; 2. Run tests for all supported filesystems. If at least one test succeeded,
; go to 4.
; For tests: qword [ebp+8] = partition start, qword [ebp+10h] = partition
; length, [esp] = 0 if reading bootsector failed or 1 if succeeded,
; ebx points to the buffer for bootsector.
call fat_create_partition
test eax, eax
jnz .success
; 3. No file system has recognized the volume, so just allocate the PARTITION
; structure without extra fields.
push sizeof.PARTITION
pop eax
call malloc
test eax, eax
jz .nothing
mov edx, dword [.start]
mov dword [eax+PARTITION.FirstSector], edx
mov edx, dword [.start+4]
mov dword [eax+PARTITION.FirstSector+4], edx
mov edx, dword [.length]
mov dword [eax+PARTITION.Length], edx
mov edx, dword [.length+4]
mov dword [eax+PARTITION.Length+4], edx
mov [eax+PARTITION.Disk], esi
and [eax+PARTITION.FSUserFunctions], 0
.success:
.nothing:
; 4. Return with eax = pointer to PARTITION or NULL.
pop ecx
ret
 
; This function is called from file_system_lfn.
; This handler gets the control each time when fn 70 is called
; with unknown item of root subdirectory.
; in: esi -> name
; ebp = 0 or rest of name relative to esi
; out: if the handler processes path, it must not return in file_system_lfn,
; but instead pop return address and return directly to the caller
; otherwise simply return
dyndisk_handler:
push ebx edi ; save registers used in file_system_lfn
; 1. Acquire the mutex.
mov ecx, disk_list_mutex
call mutex_lock
; 2. Loop over the list of DISK structures.
; 2a. Initialize.
mov ebx, disk_list
.scan:
; 2b. Get the next item.
mov ebx, [ebx+DISK.Next]
; 2c. Check whether the list is done. If so, go to 3.
cmp ebx, disk_list
jz .notfound
; 2d. Compare names. If names match, go to 5.
mov edi, [ebx+DISK.Name]
push esi
@@:
; esi points to the name from fs operation; it is terminated by zero or slash.
lodsb
test al, al
jz .eoin_dec
cmp al, '/'
jz .eoin
; edi points to the disk name.
inc edi
; edi points to lowercase name, this is a requirement for the driver.
; Characters at esi can have any register. Lowercase the current character.
; This lowercasing works for latin letters and digits; since the disk name
; should not contain other symbols, this is ok.
or al, 20h
cmp al, [edi-1]
jz @b
.wrongname:
; 2f. Names don't match. Continue the loop.
pop esi
jmp .scan
.notfound:
; The loop is done and no name matches.
; 3. Release the mutex.
call mutex_unlock
; 4. Return normally.
pop edi ebx ; restore registers used in file_system_lfn
ret
; part of 2d: the name matches partially, but we must check that this is full
; equality.
.eoin_dec:
dec esi
.eoin:
cmp byte [edi], 0
jnz .wrongname
; We found the addressed DISK structure.
; 5. Reference the disk.
lock inc [ebx+DISK.RefCount]
; 6. Now we are sure that the DISK structure is not going to die at least
; while we are working with it, so release the global mutex.
call mutex_unlock
pop ecx ; pop from the stack saved value of esi
; 7. Acquire the mutex for media object.
pop edi ; restore edi
lea ecx, [ebx+DISK.MediaLock]
call mutex_lock
; 8. Get the media object. If it is not NULL, reference it.
xor edx, edx
cmp [ebx+DISK.MediaInserted], dl
jz @f
mov edx, ebx
inc [ebx+DISK.MediaRefCount]
@@:
; 9. Now we are sure that the media object, if it exists, is not going to die
; at least while we are working with it, so release the mutex for media object.
call mutex_unlock
mov ecx, ebx
pop ebx eax ; restore ebx, pop return address
; 10. Check whether the fs operation wants to enumerate partitions (go to 11)
; or work with some concrete partition (go to 12).
cmp byte [esi], 0
jnz .haspartition
; 11. The fs operation wants to enumerate partitions.
; 11a. Only "list directory" operation is applicable to /<diskname> path. Check
; the operation code. If wrong, go to 13.
cmp dword [ebx], 1
jnz .access_denied
; 11b. If the media is inserted, use 'fs_dyndisk_next' as an enumeration
; procedure. Otherwise, use 'fs_dyndisk_next_nomedia'.
mov esi, fs_dyndisk_next_nomedia
test edx, edx
jz @f
mov esi, fs_dyndisk_next
@@:
; 11c. Let the procedure from fs_lfn.inc do the job.
jmp file_system_lfn.maindir_noesi
.haspartition:
; 12. The fs operation has specified some partition.
; 12a. Store parameters for callback functions.
push edx
push ecx
; 12b. Store callback functions.
push dyndisk_cleanup
push fs_dyndisk
mov edi, esp
; 12c. Let the procedure from fs_lfn.inc do the job.
jmp file_system_lfn.found2
.access_denied:
; 13. Fail the operation with the appropriate code.
mov dword [esp+32], ERROR_ACCESS_DENIED
.cleanup:
; 14. Cleanup.
mov esi, ecx ; disk*dereference assume that esi points to DISK
.cleanup_esi:
test edx, edx ; if there are no media, we didn't reference it
jz @f
call disk_media_dereference
@@:
call disk_dereference
; 15. Return.
ret
 
; This is a callback for cleaning up things called from file_system_lfn.found2.
dyndisk_cleanup:
mov esi, [edi+8]
mov edx, [edi+12]
jmp dyndisk_handler.cleanup_esi
 
; This is a callback for enumerating partitions called from
; file_system_lfn.maindir in the case of inserted media.
; It just increments eax until DISK.NumPartitions reached and then
; cleans up.
fs_dyndisk_next:
cmp eax, [ecx+DISK.NumPartitions]
jae .nomore
inc eax
clc
ret
.nomore:
pusha
mov esi, ecx
call disk_media_dereference
call disk_dereference
popa
stc
ret
 
; This is a callback for enumerating partitions called from
; file_system_lfn.maindir in the case of missing media.
; In this case we create one pseudo-partition.
fs_dyndisk_next_nomedia:
cmp eax, 1
jae .nomore
inc eax
clc
ret
.nomore:
pusha
mov esi, ecx
call disk_dereference
popa
stc
ret
 
; This is a callback for doing real work with selected partition.
; Currently this is just placeholder, since no file systems are supported.
; edi = esp -> {dd fs_dyndisk, dd dyndisk_cleanup, dd pointer to DISK, dd media object}
; ecx = partition number, esi+ebp = ASCIIZ name
fs_dyndisk:
dec ecx ; convert to zero-based partition index
pop edx edx edx eax ; edx = pointer to DISK, eax = NULL or edx
test eax, eax
jz .nomedia
.main:
cmp ecx, [edx+DISK.NumPartitions]
jae .notfound
mov eax, [edx+DISK.Partitions]
mov eax, [eax+ecx*4]
mov edi, [eax+PARTITION.FSUserFunctions]
test edi, edi
jz .nofs
mov ecx, [ebx]
cmp [edi], ecx
jbe .unsupported
push edx
push ebp
mov ebp, eax
call dword [edi+4+ecx*4]
pop ebp
pop edx
mov dword [esp+32], eax
mov dword [esp+20], ebx
.cleanup:
mov esi, edx
call disk_media_dereference
call disk_dereference
ret
.nofs:
mov dword [esp+32], ERROR_UNKNOWN_FS
jmp .cleanup
.notfound:
mov dword [esp+32], ERROR_FILE_NOT_FOUND
jmp .cleanup
.unsupported:
mov dword [esp+32], ERROR_UNSUPPORTED_FS
jmp .cleanup
.nomedia:
test ecx, ecx
jnz .notfound
test byte [edx+DISK.DriverFlags], DISK_NO_INSERT_NOTIFICATION
jz .deverror
; if the driver does not support insert notifications and we are the only fs
; operation with this disk, issue the fake insert notification; if media is
; still not inserted, 'disk_media_changed' will detect this and do nothing
lea ecx, [edx+DISK.MediaLock]
call mutex_lock
cmp [edx+DISK.MediaRefCount], 1
jnz .noluck
call mutex_unlock
push edx
stdcall disk_media_changed, edx, 1
pop edx
lea ecx, [edx+DISK.MediaLock]
call mutex_lock
cmp [edx+DISK.MediaInserted], 0
jz .noluck
lock inc [edx+DISK.MediaRefCount]
call mutex_unlock
xor ecx, ecx
jmp .main
.noluck:
call mutex_unlock
.deverror:
mov dword [esp+32], ERROR_DEVICE
mov esi, edx
call disk_dereference
ret
 
; This function is called from file_system_lfn.
; This handler is called when virtual root is enumerated
; and must return all items which can be handled by this.
; It is called several times, first time with eax=0
; in: eax = 0 for first call, previously returned value for subsequent calls
; out: eax = 0 => no more items
; eax != 0 => buffer pointed to by edi contains name of item
dyndisk_enum_root:
push edx ; save register used in file_system_lfn
mov ecx, disk_list_mutex ; it will be useful
; 1. If this is the first call, acquire the mutex and initialize.
test eax, eax
jnz .notfirst
call mutex_lock
mov eax, disk_list
.notfirst:
; 2. Get next item.
mov eax, [eax+DISK.Next]
; 3. If there are no more items, go to 6.
cmp eax, disk_list
jz .last
; 4. Copy name from the DISK structure to edi.
push eax esi
mov esi, [eax+DISK.Name]
@@:
lodsb
stosb
test al, al
jnz @b
pop esi eax
; 5. Return with eax = item.
pop edx ; restore register used in file_system_lfn
ret
.last:
; 6. Release the mutex and return with eax = 0.
call mutex_unlock
xor eax, eax
pop edx ; restore register used in file_system_lfn
ret
/kernel/branches/net/blkdev/disk_cache.inc
0,0 → 1,645
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2011-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 2381 $
 
; This function is intended to replace the old 'hd_read' function when
; [hdd_appl_data] = 0, so its input/output parameters are the same, except
; that it can't use the global variables 'hd_error' and 'hdd_appl_data'.
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure
; eax is relative to partition start
; out: eax = error code; 0 = ok
fs_read32_sys:
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure,
; this request should be processed by hd_read.
cmp [ebp+PARTITION.Disk], 'old'
jnz @f
add eax, dword [ebp+PARTITION.FirstSector]
mov [hdd_appl_data], 0
call hd_read
mov [hdd_appl_data], 1 ; restore to default state
mov eax, [hd_error]
ret
@@:
; In the normal case, save ecx, set ecx to SysCache and let the common part
; do its work.
push ecx
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.SysCache
jmp fs_read32_common
 
; This function is intended to replace the old 'hd_read' function when
; [hdd_appl_data] = 1, so its input/output parameters are the same, except
; that it can't use the global variables 'hd_error' and 'hdd_appl_data'.
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure
; eax is relative to partition start
; out: eax = error code; 0 = ok
fs_read32_app:
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure,
; this request should be processed by hd_read.
cmp [ebp+PARTITION.Disk], 'old'
jnz @f
add eax, dword [ebp+PARTITION.FirstSector]
mov [hdd_appl_data], 1
call hd_read
mov eax, [hd_error]
ret
@@:
; In the normal case, save ecx, set ecx to AppCache and let the common part
; do its work.
push ecx
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.AppCache
 
; This label is the common part of fs_read32_sys and fs_read32_app.
fs_read32_common:
; 1. Check that the required sector is inside the partition. If no, return
; DISK_STATUS_END_OF_MEDIA.
cmp dword [ebp+PARTITION.Length+4], 0
jnz @f
cmp dword [ebp+PARTITION.Length], eax
ja @f
mov eax, DISK_STATUS_END_OF_MEDIA
pop ecx
ret
@@:
; 2. Get the absolute sector on the disk.
push edx esi
xor edx, edx
add eax, dword [ebp+PARTITION.FirstSector]
adc edx, dword [ebp+PARTITION.FirstSector+4]
; 3. If there is no cache for this disk, just pass the request to the driver.
cmp [ecx+DISKCACHE.pointer], 0
jnz .scancache
push 1
push esp ; numsectors
push edx ; startsector
push eax ; startsector
push ebx ; buffer
mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.read
call disk_call_driver
pop ecx
pop esi edx
pop ecx
ret
.scancache:
; 4. Scan the cache.
push edi ecx ; scan cache
push edx eax
virtual at esp
.sector_lo dd ?
.sector_hi dd ?
.cache dd ?
end virtual
; The following code is inherited from hd_read. The differences are:
; all code is protected by the cache lock; instead of static calls
; to hd_read_dma/hd_read_pio/bd_read the dynamic call to DISKFUNC.read is used;
; sector is 64-bit, not 32-bit.
call mutex_lock
mov eax, [.sector_lo]
mov edx, [.sector_hi]
mov esi, [ecx+DISKCACHE.pointer]
mov ecx, [ecx+DISKCACHE.sad_size]
add esi, 12
 
mov edi, 1
 
.hdreadcache:
 
cmp dword [esi+8], 0 ; empty
je .nohdcache
 
cmp [esi], eax ; correct sector
jne .nohdcache
cmp [esi+4], edx ; correct sector
je .yeshdcache
 
.nohdcache:
 
add esi, 12
inc edi
dec ecx
jnz .hdreadcache
 
mov esi, [.cache]
call find_empty_slot64 ; ret in edi
test eax, eax
jnz .read_done
 
push 1
push esp
push edx
push [.sector_lo+12]
mov ecx, [.cache+16]
mov eax, edi
shl eax, 9
add eax, [ecx+DISKCACHE.data]
push eax
mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.read
call disk_call_driver
pop ecx
dec ecx
jnz .read_done
 
mov ecx, [.cache]
lea eax, [edi*3]
mov esi, [ecx+DISKCACHE.pointer]
lea esi, [eax*4+esi]
 
mov eax, [.sector_lo]
mov edx, [.sector_hi]
mov [esi], eax ; sector number
mov [esi+4], edx ; sector number
mov dword [esi+8], 1; hd read - mark as same as in hd
 
.yeshdcache:
 
mov esi, edi
mov ecx, [.cache]
shl esi, 9
add esi, [ecx+DISKCACHE.data]
 
mov edi, ebx
mov ecx, 512/4
rep movsd ; move data
xor eax, eax ; successful read
.read_done:
mov ecx, [.cache]
push eax
call mutex_unlock
pop eax
add esp, 12
pop edi esi edx ecx
ret
 
; This function is intended to replace the old 'hd_write' function when
; [hdd_appl_data] = 0, so its input/output parameters are the same, except
; that it can't use the global variables 'hd_error' and 'hdd_appl_data'.
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure
; eax is relative to partition start
; out: eax = error code; 0 = ok
fs_write32_sys:
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure,
; this request should be processed by hd_write.
cmp [ebp+PARTITION.Disk], 'old'
jnz @f
add eax, dword [ebp+PARTITION.FirstSector]
mov [hdd_appl_data], 0
call hd_write
mov [hdd_appl_data], 1 ; restore to default state
mov eax, [hd_error]
ret
@@:
; In the normal case, save ecx, set ecx to SysCache and let the common part
; do its work.
push ecx
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.SysCache
jmp fs_write32_common
 
; This function is intended to replace the old 'hd_write' function when
; [hdd_appl_data] = 1, so its input/output parameters are the same, except
; that it can't use the global variables 'hd_error' and 'hdd_appl_data'.
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure
; eax is relative to partition start
; out: eax = error code; 0 = ok
fs_write32_app:
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure,
; this request should be processed by hd_write.
cmp [ebp+PARTITION.Disk], 'old'
jnz @f
add eax, dword [ebp+PARTITION.FirstSector]
mov [hdd_appl_data], 1
call hd_write
mov eax, [hd_error]
ret
@@:
; In the normal case, save ecx, set ecx to AppCache and let the common part
; do its work.
push ecx
mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.AppCache
 
; This label is the common part of fs_read32_sys and fs_read32_app.
fs_write32_common:
; 1. Check that the required sector is inside the partition. If no, return
; DISK_STATUS_END_OF_MEDIA.
cmp dword [ebp+PARTITION.Length+4], 0
jnz @f
cmp dword [ebp+PARTITION.Length], eax
ja @f
mov eax, DISK_STATUS_END_OF_MEDIA
pop ecx
ret
@@:
push edx esi
; 2. Get the absolute sector on the disk.
xor edx, edx
add eax, dword [ebp+PARTITION.FirstSector]
adc edx, dword [ebp+PARTITION.FirstSector+4]
; 3. If there is no cache for this disk, just pass request to the driver.
cmp [ecx+DISKCACHE.pointer], 0
jnz .scancache
push 1
push esp ; numsectors
push edx ; startsector
push eax ; startsector
push ebx ; buffer
mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.write
call disk_call_driver
pop ecx
pop esi edx
pop ecx
ret
.scancache:
; 4. Scan the cache.
push edi ecx ; scan cache
push edx eax
virtual at esp
.sector_lo dd ?
.sector_hi dd ?
.cache dd ?
end virtual
; The following code is inherited from hd_write. The differences are:
; all code is protected by the cache lock;
; sector is 64-bit, not 32-bit.
call mutex_lock
 
; check if the cache already has the sector and overwrite it
mov eax, [.sector_lo]
mov edx, [.sector_hi]
mov esi, [ecx+DISKCACHE.pointer]
mov ecx, [ecx+DISKCACHE.sad_size]
add esi, 12
 
mov edi, 1
 
.hdwritecache:
cmp dword [esi+8], 0 ; if cache slot is empty
je .not_in_cache_write
 
cmp [esi], eax ; if the slot has the sector
jne .not_in_cache_write
cmp [esi+4], edx ; if the slot has the sector
je .yes_in_cache_write
 
.not_in_cache_write:
 
add esi, 12
inc edi
dec ecx
jnz .hdwritecache
 
; sector not found in cache
; write the block to a new location
 
mov esi, [.cache]
call find_empty_slot64 ; ret in edi
test eax, eax
jne .hd_write_access_denied
 
mov ecx, [.cache]
lea eax, [edi*3]
mov esi, [ecx+DISKCACHE.pointer]
lea esi, [eax*4+esi]
 
mov eax, [.sector_lo]
mov edx, [.sector_hi]
mov [esi], eax ; sector number
mov [esi+4], edx ; sector number
 
.yes_in_cache_write:
 
mov dword [esi+8], 2 ; write - differs from hd
 
shl edi, 9
mov ecx, [.cache]
add edi, [ecx+DISKCACHE.data]
 
mov esi, ebx
mov ecx, 512/4
rep movsd ; move data
xor eax, eax ; success
.hd_write_access_denied:
mov ecx, [.cache]
push eax
call mutex_unlock
pop eax
add esp, 12
pop edi esi edx ecx
ret
 
; This internal function is called from fs_read32_* and fs_write32_*. It is the
; analogue of find_empty_slot for 64-bit sectors.
find_empty_slot64:
;-----------------------------------------------------------
; find empty or read slot, flush cache if next 12.5% is used by write
; output : edi = cache slot
;-----------------------------------------------------------
.search_again:
mov ecx, [esi+DISKCACHE.sad_size]
mov edi, [esi+DISKCACHE.search_start]
shr ecx, 3
.search_for_empty:
inc edi
cmp edi, [esi+DISKCACHE.sad_size]
jbe .inside_cache
mov edi, 1
.inside_cache:
lea eax, [edi*3]
shl eax, 2
add eax, [esi+DISKCACHE.pointer]
cmp dword [eax+8], 2
jb .found_slot ; it's empty or read
dec ecx
jnz .search_for_empty
stdcall write_cache64, [ebp+PARTITION.Disk] ; no empty slots found, write all
test eax, eax
jne .found_slot_access_denied
jmp .search_again ; and start again
.found_slot:
mov [esi+DISKCACHE.search_start], edi
xor eax, eax ; success
.found_slot_access_denied:
ret
 
; This function is intended to replace the old 'write_cache' function.
proc write_cache64 uses ecx edx esi edi, disk:dword
locals
cache_chain_started dd 0
cache_chain_size dd ?
cache_chain_pos dd ?
cache_chain_ptr dd ?
endl
saved_esi_pos = 16+12 ; size of local variables + size of registers before esi
; If there is no cache for this disk, nothing to do.
cmp [esi+DISKCACHE.pointer], 0
jz .flush
;-----------------------------------------------------------
; write all changed sectors to disk
;-----------------------------------------------------------
 
; write difference ( 2 ) from cache to DISK
mov ecx, [esi+DISKCACHE.sad_size]
mov esi, [esi+DISKCACHE.pointer]
add esi, 12
mov edi, 1
.write_cache_more:
cmp dword [esi+8], 2 ; if cache slot is not different
jne .write_chain
mov dword [esi+8], 1 ; same as in hd
mov eax, [esi]
mov edx, [esi+4] ; edx:eax = sector to write
; Îáúåäèíÿåì çàïèñü öåïî÷êè ïîñëåäîâàòåëüíûõ ñåêòîðîâ â îäíî îáðàùåíèå ê äèñêó
cmp ecx, 1
jz .nonext
cmp dword [esi+12+8], 2
jnz .nonext
push eax edx
add eax, 1
adc edx, 0
cmp eax, [esi+12]
jnz @f
cmp edx, [esi+12+4]
@@:
pop edx eax
jnz .nonext
cmp [cache_chain_started], 1
jz @f
mov [cache_chain_started], 1
mov [cache_chain_size], 0
mov [cache_chain_pos], edi
mov [cache_chain_ptr], esi
@@:
inc [cache_chain_size]
cmp [cache_chain_size], 16
jnz .continue
jmp .write_chain
.nonext:
call .flush_cache_chain
test eax, eax
jnz .nothing
mov [cache_chain_size], 1
mov [cache_chain_ptr], esi
call .write_cache_sector
test eax, eax
jnz .nothing
jmp .continue
.write_chain:
call .flush_cache_chain
test eax, eax
jnz .nothing
.continue:
add esi, 12
inc edi
dec ecx
jnz .write_cache_more
call .flush_cache_chain
test eax, eax
jnz .nothing
.flush:
mov esi, [disk]
mov al, DISKFUNC.flush
call disk_call_driver
.nothing:
ret
 
.flush_cache_chain:
xor eax, eax
cmp [cache_chain_started], eax
jz @f
call .write_cache_chain
mov [cache_chain_started], 0
@@:
retn
 
.write_cache_sector:
mov [cache_chain_size], 1
mov [cache_chain_pos], edi
.write_cache_chain:
pusha
mov edi, [cache_chain_pos]
mov ecx, [ebp-saved_esi_pos]
shl edi, 9
add edi, [ecx+DISKCACHE.data]
mov ecx, [cache_chain_size]
push ecx
push esp ; numsectors
mov eax, [cache_chain_ptr]
pushd [eax+4]
pushd [eax] ; startsector
push edi ; buffer
mov esi, [ebp]
mov esi, [esi+PARTITION.Disk]
mov al, DISKFUNC.write
call disk_call_driver
pop ecx
mov [esp+28], eax
popa
retn
endp
 
; This internal function is called from disk_add to initialize the caching for
; a new DISK.
; The algorithm is inherited from getcache.inc: take 1/32 part of the available
; physical memory, round down to 8 pages, limit by 128K from below and by 1M
; from above. Reserve 1/8 part of the cache for system data and 7/8 for app
; data.
; After the size is calculated, but before the cache is allocated, the device
; driver can adjust the size. In particular, setting size to zero disables
; caching: there is no sense in a cache for a ramdisk. In fact, such action
; is most useful example of a non-trivial adjustment.
; esi = pointer to DISK structure
disk_init_cache:
; 1. Calculate the suggested cache size.
; 1a. Get the size of free physical memory in pages.
mov eax, [pg_data.pages_free]
; 1b. Use the value to calculate the size.
shl eax, 12 - 5 ; 1/32 of it in bytes
and eax, -8*4096 ; round down to the multiple of 8 pages
; 1c. Force lower and upper limits.
cmp eax, 1024*1024
jb @f
mov eax, 1024*1024
@@:
cmp eax, 128*1024
ja @f
mov eax, 128*1024
@@:
; 1d. Give a chance to the driver to adjust the size.
push eax
mov al, DISKFUNC.adjust_cache_size
call disk_call_driver
; Cache size calculated.
mov [esi+DISK.cache_size], eax
test eax, eax
jz .nocache
; 2. Allocate memory for the cache.
; 2a. Call the allocator.
stdcall kernel_alloc, eax
test eax, eax
jnz @f
; 2b. If it failed, say a message and return with eax = 0.
dbgstr 'no memory for disk cache'
jmp .nothing
@@:
; 3. Fill two DISKCACHE structures.
mov [esi+DISK.SysCache.pointer], eax
lea ecx, [esi+DISK.SysCache.mutex]
call mutex_init
lea ecx, [esi+DISK.AppCache.mutex]
call mutex_init
; The following code is inherited from getcache.inc.
mov edx, [esi+DISK.SysCache.pointer]
and [esi+DISK.SysCache.search_start], 0
and [esi+DISK.AppCache.search_start], 0
mov eax, [esi+DISK.cache_size]
shr eax, 3
mov [esi+DISK.SysCache.data_size], eax
add edx, eax
imul eax, 7
mov [esi+DISK.AppCache.data_size], eax
mov [esi+DISK.AppCache.pointer], edx
 
mov eax, [esi+DISK.SysCache.data_size]
push ebx
call calculate_for_hd64
pop ebx
add eax, [esi+DISK.SysCache.pointer]
mov [esi+DISK.SysCache.data], eax
mov [esi+DISK.SysCache.sad_size], ecx
 
push edi
mov edi, [esi+DISK.SysCache.pointer]
lea ecx, [ecx*3]
xor eax, eax
rep stosd
pop edi
 
mov eax, [esi+DISK.AppCache.data_size]
push ebx
call calculate_for_hd64
pop ebx
add eax, [esi+DISK.AppCache.pointer]
mov [esi+DISK.AppCache.data], eax
mov [esi+DISK.AppCache.sad_size], ecx
 
push edi
mov edi, [esi+DISK.AppCache.pointer]
lea ecx, [ecx*3]
xor eax, eax
rep stosd
pop edi
 
; 4. Return with nonzero al.
mov al, 1
; 5. Return.
.nothing:
ret
; No caching is required for this driver. Zero cache pointers and return with
; nonzero al.
.nocache:
mov [esi+DISK.SysCache.pointer], eax
mov [esi+DISK.AppCache.pointer], eax
mov al, 1
ret
 
calculate_for_hd64:
push eax
mov ebx, eax
shr eax, 9
lea eax, [eax*3]
shl eax, 2
sub ebx, eax
shr ebx, 9
mov ecx, ebx
shl ebx, 9
pop eax
sub eax, ebx
dec ecx
ret
 
 
; This internal function is called from disk_media_dereference to free the
; allocated cache, if there is one.
; esi = pointer to DISK structure
disk_free_cache:
; The algorithm is straightforward.
mov eax, [esi+DISK.SysCache.pointer]
test eax, eax
jz .nothing
stdcall kernel_free, eax
.nothing:
ret
 
; This function flushes all modified data from both caches for the given DISK.
; esi = pointer to DISK
disk_sync:
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure,
; this request should be processed by write_cache.
cmp esi, 'old'
jnz @f
mov [hdd_appl_data], 0
call write_cache
mov [hdd_appl_data], 1
call write_cache
mov eax, [hd_error]
ret
@@:
; The algorithm is straightforward.
push esi
push esi ; for second write_cache64
push esi ; for first write_cache64
add esi, DISK.SysCache
call write_cache64
add esi, DISK.AppCache - DISK.SysCache
call write_cache64
pop esi
ret
/kernel/branches/net/blkdev/hd_drv.inc
0,0 → 1,1047
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
; Low-level driver for HDD access
; DMA support by Mario79
; Access through BIOS by diamond
 
align 4
hd_read:
;-----------------------------------------------------------
; input : eax = block to read
; ebx = destination
;-----------------------------------------------------------
and [hd_error], 0
push ecx esi edi ; scan cache
 
; mov ecx,cache_max ; entries in cache
; mov esi,HD_CACHE+8
call calculate_cache
add esi, 8
 
mov edi, 1
 
hdreadcache:
 
cmp dword [esi+4], 0; empty
je nohdcache
 
cmp [esi], eax ; correct sector
je yeshdcache
 
nohdcache:
 
add esi, 8
inc edi
dec ecx
jnz hdreadcache
 
call find_empty_slot ; ret in edi
cmp [hd_error], 0
jne return_01
; Read through BIOS?
cmp [hdpos], 0x80
jae .bios
; hd_read_{dma,pio} use old ATA with 28 bit for sector number
cmp eax, 0x10000000
jb @f
inc [hd_error]
jmp return_01
@@:
; DMA read is permitted if [allow_dma_access]=1 or 2
cmp [allow_dma_access], 2
ja .nodma
cmp [dma_hdd], 1
jnz .nodma
call hd_read_dma
jmp @f
.nodma:
call hd_read_pio
jmp @f
.bios:
call bd_read
@@:
cmp [hd_error], 0
jne return_01
; lea esi,[edi*8+HD_CACHE]
; push eax
call calculate_cache_1
lea esi, [edi*8+esi]
; pop eax
 
mov [esi], eax ; sector number
mov dword [esi+4], 1; hd read - mark as same as in hd
 
yeshdcache:
 
mov esi, edi
shl esi, 9
; add esi,HD_CACHE+65536
push eax
call calculate_cache_2
add esi, eax
pop eax
 
mov edi, ebx
mov ecx, 512/4
cld
rep movsd ; move data
return_01:
pop edi esi ecx
ret
 
align 4
hd_read_pio:
push eax edx
 
call wait_for_hd_idle
cmp [hd_error], 0
jne hd_read_error
 
cli
xor eax, eax
mov edx, [hdbase]
inc edx
out dx, al; ATAFeatures ॣ¨áâà "®á®¡¥­­®á⥩"
inc edx
inc eax
out dx, al; ATASectorCount áçñâ稪 ᥪâ®à®¢
inc edx
mov eax, [esp+4]
out dx, al; ATASectorNumber ॣ¨áâà ­®¬¥à  ᥪâ®à 
shr eax, 8
inc edx
out dx, al; ATACylinder ­®¬¥à 樫¨­¤à  (¬« ¤è¨© ¡ ©â)
shr eax, 8
inc edx
out dx, al; ­®¬¥à 樫¨­¤à  (áâ à訩 ¡ ©â)
shr eax, 8
inc edx
and al, 1+2+4+8
add al, byte [hdid]
add al, 128+64+32
out dx, al; ­®¬¥à £®«®¢ª¨/­®¬¥à ¤¨áª 
inc edx
mov al, 20h
out dx, al; ATACommand ॣ¨áâà ª®¬ ­¤
sti
 
call wait_for_sector_buffer
 
cmp [hd_error], 0
jne hd_read_error
 
cli
push edi
shl edi, 9
; add edi,HD_CACHE+65536
push eax
call calculate_cache_2
add edi, eax
pop eax
 
mov ecx, 256
mov edx, [hdbase]
cld
rep insw
pop edi
sti
 
pop edx eax
ret
 
disable_ide_int:
; mov edx,[hdbase]
; add edx,0x206
; mov al,2
; out dx,al
cli
ret
 
enable_ide_int:
; mov edx,[hdbase]
; add edx,0x206
; mov al,0
; out dx,al
sti
ret
 
align 4
hd_write:
;-----------------------------------------------------------
; input : eax = block
; ebx = pointer to memory
;-----------------------------------------------------------
push ecx esi edi
 
; check if the cache already has the sector and overwrite it
 
; mov ecx,cache_max
; mov esi,HD_CACHE+8
call calculate_cache
add esi, 8
 
mov edi, 1
 
hdwritecache:
 
cmp dword [esi+4], 0; if cache slot is empty
je not_in_cache_write
 
cmp [esi], eax ; if the slot has the sector
je yes_in_cache_write
 
not_in_cache_write:
 
add esi, 8
inc edi
dec ecx
jnz hdwritecache
 
; sector not found in cache
; write the block to a new location
 
call find_empty_slot ; ret in edi
cmp [hd_error], 0
jne hd_write_access_denied
 
; lea esi,[edi*8+HD_CACHE]
; push eax
call calculate_cache_1
lea esi, [edi*8+esi]
; pop eax
 
mov [esi], eax ; sector number
 
yes_in_cache_write:
 
mov dword [esi+4], 2; write - differs from hd
 
shl edi, 9
; add edi,HD_CACHE+65536
push eax
call calculate_cache_2
add edi, eax
pop eax
 
mov esi, ebx
mov ecx, 512/4
cld
rep movsd ; move data
hd_write_access_denied:
pop edi esi ecx
ret
 
align 4
cache_write_pio:
cmp dword[esi], 0x10000000
jae .bad
; call disable_ide_int
 
call wait_for_hd_idle
cmp [hd_error], 0
jne hd_write_error
 
cli
xor eax, eax
mov edx, [hdbase]
inc edx
out dx, al
inc edx
inc eax
out dx, al
inc edx
mov eax, [esi] ; eax = sector to write
out dx, al
shr eax, 8
inc edx
out dx, al
shr eax, 8
inc edx
out dx, al
shr eax, 8
inc edx
and al, 1+2+4+8
add al, byte [hdid]
add al, 128+64+32
out dx, al
inc edx
mov al, 30h
out dx, al
sti
 
call wait_for_sector_buffer
 
cmp [hd_error], 0
jne hd_write_error
 
push ecx esi
 
cli
mov esi, edi
shl esi, 9
; add esi,HD_CACHE+65536 ; esi = from memory position
push eax
call calculate_cache_2
add esi, eax
pop eax
 
mov ecx, 256
mov edx, [hdbase]
cld
rep outsw
sti
 
; call enable_ide_int
pop esi ecx
 
ret
.bad:
inc [hd_error]
ret
 
save_hd_wait_timeout:
 
push eax
mov eax, [timer_ticks]
add eax, 300 ; 3 sec timeout
mov [hd_wait_timeout], eax
pop eax
ret
 
align 4
check_hd_wait_timeout:
 
push eax
mov eax, [hd_wait_timeout]
cmp [timer_ticks], eax
jg hd_timeout_error
pop eax
mov [hd_error], 0
ret
 
;iglobal
; hd_timeout_str db 'K : FS - HD timeout',0
; hd_read_str db 'K : FS - HD read error',0
; hd_write_str db 'K : FS - HD write error',0
; hd_lba_str db 'K : FS - HD LBA error',0
;endg
 
hd_timeout_error:
 
; call clear_hd_cache
; call clear_application_table_status
; mov esi,hd_timeout_str
; call sys_msg_board_str
if lang eq sp
DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
else
DEBUGF 1,"K : FS - HD timeout\n"
end if
 
mov [hd_error], 1
pop eax
ret
 
hd_read_error:
 
; call clear_hd_cache
; call clear_application_table_status
; mov esi,hd_read_str
; call sys_msg_board_str
if lang eq sp
DEBUGF 1,"K : FS - HD error de lectura\n"
else
DEBUGF 1,"K : FS - HD read error\n"
end if
pop edx eax
ret
 
hd_write_error:
 
; call clear_hd_cache
; call clear_application_table_status
; mov esi,hd_write_str
; call sys_msg_board_str
if lang eq sp
DEBUGF 1,"K : FS - HD error de escritura\n"
else
DEBUGF 1,"K : FS - HD write error\n"
end if
ret
 
hd_write_error_dma:
; call clear_hd_cache
; call clear_application_table_status
; mov esi, hd_write_str
; call sys_msg_board_str
if lang eq sp
DEBUGF 1,"K : FS - HD error de escritura\n"
else
DEBUGF 1,"K : FS - HD write error\n"
end if
pop esi
ret
 
hd_lba_error:
; call clear_hd_cache
; call clear_application_table_status
; mov esi,hd_lba_str
; call sys_msg_board_str
if lang eq sp
DEBUGF 1,"K : FS - HD error en LBA\n"
else
DEBUGF 1,"K : FS - HD LBA error\n"
end if
jmp LBA_read_ret
 
 
align 4
wait_for_hd_idle:
 
push eax edx
 
call save_hd_wait_timeout
 
mov edx, [hdbase]
add edx, 0x7
 
wfhil1:
 
call check_hd_wait_timeout
cmp [hd_error], 0
jne @f
 
in al, dx
test al, 128
jnz wfhil1
 
@@:
 
pop edx eax
ret
 
 
align 4
wait_for_sector_buffer:
 
push eax edx
 
mov edx, [hdbase]
add edx, 0x7
 
call save_hd_wait_timeout
 
hdwait_sbuf: ; wait for sector buffer to be ready
 
call check_hd_wait_timeout
cmp [hd_error], 0
jne @f
 
in al, dx
test al, 8
jz hdwait_sbuf
 
mov [hd_error], 0
 
cmp [hd_setup], 1 ; do not mark error for setup request
je buf_wait_ok
 
test al, 1 ; previous command ended up with an error
jz buf_wait_ok
@@:
mov [hd_error], 1
 
buf_wait_ok:
 
pop edx eax
ret
 
; \begin{Mario79}
align 4
wait_for_sector_dma_ide0:
push eax
push edx
call save_hd_wait_timeout
.wait:
call change_task
cmp [irq14_func], hdd_irq14
jnz .done
call check_hd_wait_timeout
cmp [hd_error], 0
jz .wait
mov [irq14_func], hdd_irq_null
mov dx, [IDEContrRegsBaseAddr]
mov al, 0
out dx, al
.done:
pop edx
pop eax
ret
 
align 4
wait_for_sector_dma_ide1:
push eax
push edx
call save_hd_wait_timeout
.wait:
call change_task
cmp [irq15_func], hdd_irq15
jnz .done
call check_hd_wait_timeout
cmp [hd_error], 0
jz .wait
mov [irq15_func], hdd_irq_null
mov dx, [IDEContrRegsBaseAddr]
add dx, 8
mov al, 0
out dx, al
.done:
pop edx
pop eax
ret
 
iglobal
align 4
; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
IDE_descriptor_table:
dd IDE_DMA
dw 0x2000
dw 0x8000
 
dma_cur_sector dd not 40h
dma_hdpos dd 0
irq14_func dd hdd_irq_null
irq15_func dd hdd_irq_null
endg
 
uglobal
; all uglobals are zeroed at boot
dma_process dd 0
dma_slot_ptr dd 0
cache_chain_pos dd 0
cache_chain_ptr dd 0
cache_chain_size db 0
cache_chain_started db 0
dma_task_switched db 0
dma_hdd db 0
allow_dma_access db 0
endg
 
align 4
hdd_irq14:
pushfd
cli
pushad
mov [irq14_func], hdd_irq_null
mov dx, [IDEContrRegsBaseAddr]
mov al, 0
out dx, al
; call update_counters
; mov ebx, [dma_process]
; cmp [CURRENT_TASK], ebx
; jz .noswitch
; mov [dma_task_switched], 1
; mov edi, [dma_slot_ptr]
; mov eax, [CURRENT_TASK]
; mov [dma_process], eax
; mov eax, [TASK_BASE]
; mov [dma_slot_ptr], eax
; mov [CURRENT_TASK], ebx
; mov [TASK_BASE], edi
; mov byte [DONT_SWITCH], 1
; call do_change_task
.noswitch:
popad
popfd
align 4
hdd_irq_null:
ret
 
align 4
hdd_irq15:
pushfd
cli
pushad
mov [irq15_func], hdd_irq_null
mov dx, [IDEContrRegsBaseAddr]
add dx, 8
mov al, 0
out dx, al
; call update_counters
; mov ebx, [dma_process]
; cmp [CURRENT_TASK], ebx
; jz .noswitch
; mov [dma_task_switched], 1
; mov edi, [dma_slot_ptr]
; mov eax, [CURRENT_TASK]
; mov [dma_process], eax
; mov eax, [TASK_BASE]
; mov [dma_slot_ptr], eax
; mov [CURRENT_TASK], ebx
; mov [TASK_BASE], edi
; mov byte [DONT_SWITCH], 1
; call do_change_task
.noswitch:
popad
popfd
ret
 
align 4
hd_read_dma:
push eax
push edx
mov edx, [dma_hdpos]
cmp edx, [hdpos]
jne .notread
mov edx, [dma_cur_sector]
cmp eax, edx
jb .notread
add edx, 15
cmp [esp+4], edx
ja .notread
mov eax, [esp+4]
sub eax, [dma_cur_sector]
shl eax, 9
add eax, (OS_BASE+IDE_DMA)
push ecx esi edi
mov esi, eax
shl edi, 9
; add edi, HD_CACHE+0x10000
push eax
call calculate_cache_2
add edi, eax
pop eax
 
mov ecx, 512/4
cld
rep movsd
pop edi esi ecx
pop edx
pop eax
ret
.notread:
mov eax, IDE_descriptor_table
mov dword [eax], IDE_DMA
mov word [eax+4], 0x2000
sub eax, OS_BASE
mov dx, [IDEContrRegsBaseAddr]
cmp [hdbase], 0x1F0
jz @f
add edx, 8
@@:
push edx
add edx, 4
out dx, eax
pop edx
mov al, 0
out dx, al
add edx, 2
mov al, 6
out dx, al
call wait_for_hd_idle
cmp [hd_error], 0
jnz hd_read_error
call disable_ide_int
xor eax, eax
mov edx, [hdbase]
inc edx
out dx, al
inc edx
mov eax, 10h
out dx, al
inc edx
mov eax, [esp+4]
out dx, al
shr eax, 8
inc edx
out dx, al
shr eax, 8
inc edx
out dx, al
shr eax, 8
inc edx
and al, 0xF
add al, byte [hdid]
add al, 11100000b
out dx, al
inc edx
mov al, 0xC8
out dx, al
mov dx, [IDEContrRegsBaseAddr]
cmp [hdbase], 0x1F0
jz @f
add dx, 8
@@:
mov al, 9
out dx, al
mov eax, [CURRENT_TASK]
mov [dma_process], eax
mov eax, [TASK_BASE]
mov [dma_slot_ptr], eax
cmp [hdbase], 0x1F0
jnz .ide1
mov [irq14_func], hdd_irq14
jmp @f
.ide1:
mov [irq15_func], hdd_irq15
@@:
call enable_ide_int
cmp [hdbase], 0x1F0
jnz .wait_ide1
call wait_for_sector_dma_ide0
jmp @f
.wait_ide1:
call wait_for_sector_dma_ide1
@@:
cmp [hd_error], 0
jnz hd_read_error
mov eax, [hdpos]
mov [dma_hdpos], eax
pop edx
pop eax
mov [dma_cur_sector], eax
jmp hd_read_dma
 
align 4
write_cache_sector:
mov [cache_chain_size], 1
mov [cache_chain_pos], edi
write_cache_chain:
cmp [hdpos], 0x80
jae bd_write_cache_chain
mov eax, [cache_chain_ptr]
cmp dword[eax], 0x10000000
jae .bad
push esi
mov eax, IDE_descriptor_table
mov edx, eax
pusha
mov esi, [cache_chain_pos]
shl esi, 9
call calculate_cache_2
add esi, eax
mov edi, (OS_BASE+IDE_DMA)
mov dword [edx], IDE_DMA
movzx ecx, [cache_chain_size]
shl ecx, 9
mov word [edx+4], cx
shr ecx, 2
cld
rep movsd
popa
sub eax, OS_BASE
mov dx, [IDEContrRegsBaseAddr]
cmp [hdbase], 0x1F0
jz @f
add edx, 8
@@:
push edx
add edx, 4
out dx, eax
pop edx
mov al, 0
out dx, al
add edx, 2
mov al, 6
out dx, al
call wait_for_hd_idle
cmp [hd_error], 0
jnz hd_write_error_dma
call disable_ide_int
xor eax, eax
mov edx, [hdbase]
inc edx
out dx, al
inc edx
mov al, [cache_chain_size]
out dx, al
inc edx
mov esi, [cache_chain_ptr]
mov eax, [esi]
out dx, al
shr eax, 8
inc edx
out dx, al
shr eax, 8
inc edx
out dx, al
shr eax, 8
inc edx
and al, 0xF
add al, byte [hdid]
add al, 11100000b
out dx, al
inc edx
mov al, 0xCA
out dx, al
mov dx, [IDEContrRegsBaseAddr]
cmp [hdbase], 0x1F0
jz @f
add dx, 8
@@:
mov al, 1
out dx, al
mov eax, [CURRENT_TASK]
mov [dma_process], eax
mov eax, [TASK_BASE]
mov [dma_slot_ptr], eax
cmp [hdbase], 0x1F0
jnz .ide1
mov [irq14_func], hdd_irq14
jmp @f
.ide1:
mov [irq15_func], hdd_irq15
@@:
call enable_ide_int
mov [dma_cur_sector], not 0x40
cmp [hdbase], 0x1F0
jnz .wait_ide1
call wait_for_sector_dma_ide0
jmp @f
.wait_ide1:
call wait_for_sector_dma_ide1
@@:
cmp [hd_error], 0
jnz hd_write_error_dma
pop esi
ret
.bad:
inc [hd_error]
ret
 
uglobal
IDEContrRegsBaseAddr dw ?
endg
; \end{Mario79}
 
; \begin{diamond}
uglobal
bios_hdpos dd 0 ; 0 is invalid value for [hdpos]
bios_cur_sector dd ?
bios_read_len dd ?
endg
bd_read:
push eax
push edx
mov edx, [bios_hdpos]
cmp edx, [hdpos]
jne .notread
mov edx, [bios_cur_sector]
cmp eax, edx
jb .notread
add edx, [bios_read_len]
dec edx
cmp eax, edx
ja .notread
sub eax, [bios_cur_sector]
shl eax, 9
add eax, (OS_BASE+0x9A000)
push ecx esi edi
mov esi, eax
shl edi, 9
; add edi, HD_CACHE+0x10000
push eax
call calculate_cache_2
add edi, eax
pop eax
 
mov ecx, 512/4
cld
rep movsd
pop edi esi ecx
pop edx
pop eax
ret
.notread:
push ecx
mov dl, 42h
mov ecx, 16
call int13_call
pop ecx
test eax, eax
jnz .v86err
test edx, edx
jz .readerr
mov [bios_read_len], edx
mov edx, [hdpos]
mov [bios_hdpos], edx
pop edx
pop eax
mov [bios_cur_sector], eax
jmp bd_read
.readerr:
.v86err:
mov [hd_error], 1
jmp hd_read_error
 
bd_write_cache_chain:
pusha
mov esi, [cache_chain_pos]
shl esi, 9
call calculate_cache_2
add esi, eax
mov edi, OS_BASE + 0x9A000
movzx ecx, [cache_chain_size]
push ecx
shl ecx, 9-2
rep movsd
pop ecx
mov dl, 43h
mov eax, [cache_chain_ptr]
mov eax, [eax]
call int13_call
test eax, eax
jnz .v86err
cmp edx, ecx
jnz .writeerr
popa
ret
.v86err:
.writeerr:
popa
mov [hd_error], 1
jmp hd_write_error
 
uglobal
int13_regs_in rb sizeof.v86_regs
int13_regs_out rb sizeof.v86_regs
endg
 
int13_call:
; Because this code uses fixed addresses,
; it can not be run simultaniously by many threads.
; In current implementation it is protected by common mutex 'hd1_status'
mov word [OS_BASE + 510h], 10h ; packet length
mov word [OS_BASE + 512h], cx ; number of sectors
mov dword [OS_BASE + 514h], 9A000000h ; buffer 9A00:0000
mov dword [OS_BASE + 518h], eax
and dword [OS_BASE + 51Ch], 0
push ebx ecx esi edi
mov ebx, int13_regs_in
mov edi, ebx
mov ecx, sizeof.v86_regs/4
xor eax, eax
rep stosd
mov byte [ebx+v86_regs.eax+1], dl
mov eax, [hdpos]
lea eax, [BiosDisksData+(eax-80h)*4]
mov dl, [eax]
mov byte [ebx+v86_regs.edx], dl
movzx edx, byte [eax+1]
; mov dl, 5
test edx, edx
jnz .hasirq
dec edx
jmp @f
.hasirq:
pushad
stdcall enable_irq, edx
popad
@@:
mov word [ebx+v86_regs.esi], 510h
mov word [ebx+v86_regs.ss], 9000h
mov word [ebx+v86_regs.esp], 0A000h
mov word [ebx+v86_regs.eip], 500h
mov [ebx+v86_regs.eflags], 20200h
mov esi, [sys_v86_machine]
mov ecx, 0x502
push fs
call v86_start
pop fs
and [bios_hdpos], 0
pop edi esi ecx ebx
movzx edx, byte [OS_BASE + 512h]
test byte [int13_regs_out+v86_regs.eflags], 1
jnz @f
mov edx, ecx
@@:
ret
; \end{diamond}
 
reserve_hd1:
 
cli
cmp [hd1_status], 0
je reserve_ok1
 
sti
call change_task
jmp reserve_hd1
 
reserve_ok1:
 
push eax
mov eax, [CURRENT_TASK]
shl eax, 5
mov eax, [eax+CURRENT_TASK+TASKDATA.pid]
mov [hd1_status], eax
pop eax
sti
ret
;********************************************
 
uglobal
hd_in_cache db ?
endg
 
reserve_hd_channel:
; BIOS disk accesses are protected with common mutex hd1_status
; This must be modified when hd1_status will not be valid!
cmp [hdpos], 0x80
jae .ret
cmp [hdbase], 0x1F0
jne .IDE_Channel_2
.IDE_Channel_1:
cli
cmp [IDE_Channel_1], 0
je .reserve_ok_1
sti
call change_task
jmp .IDE_Channel_1
.IDE_Channel_2:
cli
cmp [IDE_Channel_2], 0
je .reserve_ok_2
sti
call change_task
jmp .IDE_Channel_2
.reserve_ok_1:
mov [IDE_Channel_1], 1
push eax
mov al, 1
jmp @f
.reserve_ok_2:
mov [IDE_Channel_2], 1
push eax
mov al, 3
@@:
cmp [hdid], 1
sbb al, -1
mov [hd_in_cache], al
pop eax
sti
.ret:
ret
 
free_hd_channel:
; see comment at reserve_hd_channel
cmp [hdpos], 0x80
jae .ret
cmp [hdbase], 0x1F0
jne .IDE_Channel_2
.IDE_Channel_1:
mov [IDE_Channel_1], 0
.ret:
ret
.IDE_Channel_2:
mov [IDE_Channel_2], 0
ret
;********************************************
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/blkdev/ide_cache.inc
0,0 → 1,920
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;**************************************************************************
;
; [cache_ide[X]_pointer]
; or [cache_ide[X]_data_pointer] first entry in cache list
;
; +0 - lba sector
; +4 - state of cache sector
; 0 = empty
; 1 = used for read ( same as in hd )
; 2 = used for write ( differs from hd )
;
; [cache_ide[X]_system_data]
; or [cache_ide[x]_appl_data] - cache entries
;
;**************************************************************************
 
$Revision $
 
 
align 4
write_cache:
;-----------------------------------------------------------
; write all changed sectors to disk
;-----------------------------------------------------------
push eax ecx edx esi edi
 
; write difference ( 2 ) from cache to hd
call calculate_cache
add esi, 8
mov edi, 1
write_cache_more:
cmp dword [esi+4], 2; if cache slot is not different
jne .write_chain
mov dword [esi+4], 1; same as in hd
mov eax, [esi] ; eax = sector to write
cmp eax, [PARTITION_START]
jb danger
cmp eax, [PARTITION_END]
ja danger
cmp [hdpos], 0x80
jae @f
; DMA write is permitted only if [allow_dma_access]=1
cmp [allow_dma_access], 2
jae .nodma
cmp [dma_hdd], 1
jnz .nodma
@@:
; Ž¡ê¥¤¨­ï¥¬ § ¯¨áì 楯®çª¨ ¯®á«¥¤®¢ â¥«ì­ëå ᥪâ®à®¢ ¢ ®¤­® ®¡à é¥­¨¥ ª ¤¨áªã
cmp ecx, 1
jz .nonext
cmp dword [esi+8+4], 2
jnz .nonext
push eax
inc eax
cmp eax, [esi+8]
pop eax
jnz .nonext
cmp [cache_chain_started], 1
jz @f
mov [cache_chain_started], 1
mov [cache_chain_size], 0
mov [cache_chain_pos], edi
mov [cache_chain_ptr], esi
@@:
inc [cache_chain_size]
cmp [cache_chain_size], 16
jnz .continue
jmp .write_chain
.nonext:
call flush_cache_chain
mov [cache_chain_size], 1
mov [cache_chain_ptr], esi
call write_cache_sector
jmp .continue
.nodma:
call cache_write_pio
.write_chain:
call flush_cache_chain
.continue:
danger:
add esi, 8
inc edi
dec ecx
jnz write_cache_more
call flush_cache_chain
return_02:
pop edi esi edx ecx eax
ret
 
flush_cache_chain:
cmp [cache_chain_started], 0
jz @f
call write_cache_chain
mov [cache_chain_started], 0
@@:
ret
;--------------------------------------------------------------------
align 4
find_empty_slot:
;-----------------------------------------------------------
; find empty or read slot, flush cache if next 10% is used by write
; output : edi = cache slot
;-----------------------------------------------------------
; push ecx esi
 
search_again:
call calculate_cache_3
shr ecx, 3
search_for_empty:
inc edi
call calculate_cache_4
jbe inside_cache
mov edi, 1
inside_cache:
push esi
call calculate_cache_1
cmp dword [edi*8+esi+4], 2
pop esi
jb found_slot ; it's empty or read
dec ecx
jnz search_for_empty
call write_cache ; no empty slots found, write all
cmp [hd_error], 0
jne found_slot_access_denied
jmp search_again ; and start again
found_slot:
call calculate_cache_5
found_slot_access_denied:
ret
;--------------------------------------------------------------------
align 4
clear_hd_cache:
ret
;--------------------------------------------------------------------
align 4
calculate_cache:
; mov ecx,cache_max ; entries in cache
; mov esi,HD_CACHE+8
 
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [hdpos], 1
jne .ide1
cmp [hdd_appl_data], 0
jne .ide0_appl_data
mov ecx, [cache_ide0_system_sad_size]
mov esi, [cache_ide0_pointer]
ret
.ide0_appl_data:
mov ecx, [cache_ide0_appl_sad_size]
mov esi, [cache_ide0_data_pointer]
ret
.ide1:
cmp [hdpos], 2
jne .ide2
cmp [hdd_appl_data], 0
jne .ide1_appl_data
mov ecx, [cache_ide1_system_sad_size]
mov esi, [cache_ide1_pointer]
ret
.ide1_appl_data:
mov ecx, [cache_ide1_appl_sad_size]
mov esi, [cache_ide1_data_pointer]
ret
.ide2:
cmp [hdpos], 3
jne .ide3
cmp [hdd_appl_data], 0
jne .ide2_appl_data
mov ecx, [cache_ide2_system_sad_size]
mov esi, [cache_ide2_pointer]
ret
.ide2_appl_data:
mov ecx, [cache_ide2_appl_sad_size]
mov esi, [cache_ide2_data_pointer]
ret
.ide3:
cmp [hdpos], 4
jne .noide
cmp [hdd_appl_data], 0
jne .ide3_appl_data
mov ecx, [cache_ide3_system_sad_size]
mov esi, [cache_ide3_pointer]
ret
.ide3_appl_data:
mov ecx, [cache_ide3_appl_sad_size]
mov esi, [cache_ide3_data_pointer]
ret
.noide:
push eax
mov eax, [hdpos]
sub eax, 80h
cmp byte [BiosDisksData+eax*4+2], -1
jz @f
movzx eax, byte [BiosDisksData+eax*4+2]
imul eax, cache_ide1-cache_ide0
add eax, cache_ide0
jmp .get
@@:
imul eax, cache_ide1-cache_ide0
add eax, BiosDiskCaches
.get:
cmp [hdd_appl_data], 0
jne .bd_appl_data
mov ecx, [cache_ide0_system_sad_size-cache_ide0+eax]
mov esi, [cache_ide0_pointer-cache_ide0+eax]
pop eax
ret
.bd_appl_data:
mov ecx, [cache_ide0_appl_sad_size-cache_ide0+eax]
mov esi, [cache_ide0_data_pointer-cache_ide0+eax]
pop eax
ret
;--------------------------------------------------------------------
align 4
calculate_cache_1:
; lea esi,[edi*8+HD_CACHE]
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [hdpos], 1
jne .ide1
cmp [hdd_appl_data], 0
jne .ide0_appl_data
mov esi, [cache_ide0_pointer]
ret
.ide0_appl_data:
mov esi, [cache_ide0_data_pointer]
ret
.ide1:
cmp [hdpos], 2
jne .ide2
cmp [hdd_appl_data], 0
jne .ide1_appl_data
mov esi, [cache_ide1_pointer]
ret
.ide1_appl_data:
mov esi, [cache_ide1_data_pointer]
ret
.ide2:
cmp [hdpos], 3
jne .ide3
cmp [hdd_appl_data], 0
jne .ide2_appl_data
mov esi, [cache_ide2_pointer]
ret
.ide2_appl_data:
mov esi, [cache_ide2_data_pointer]
ret
.ide3:
cmp [hdpos], 4
jne .noide
cmp [hdd_appl_data], 0
jne .ide3_appl_data
mov esi, [cache_ide3_pointer]
ret
.ide3_appl_data:
mov esi, [cache_ide3_data_pointer]
ret
.noide:
push eax
mov eax, [hdpos]
sub eax, 80h
cmp byte [BiosDisksData+eax*4+2], -1
jz @f
movzx eax, byte [BiosDisksData+eax*4+2]
imul eax, cache_ide1-cache_ide0
add eax, cache_ide0
jmp .get
@@:
imul eax, cache_ide1-cache_ide0
add eax, BiosDiskCaches
.get:
cmp [hdd_appl_data], 0
jne .bd_appl_data
mov esi, [cache_ide0_pointer-cache_ide0+eax]
pop eax
ret
.bd_appl_data:
mov esi, [cache_ide0_data_pointer-cache_ide0+eax]
pop eax
ret
 
;--------------------------------------------------------------------
align 4
calculate_cache_2:
; add esi,HD_CACHE+65536
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [hdpos], 1
jne .ide1
cmp [hdd_appl_data], 0
jne .ide0_appl_data
mov eax, [cache_ide0_system_data]
ret
.ide0_appl_data:
mov eax, [cache_ide0_appl_data]
ret
.ide1:
cmp [hdpos], 2
jne .ide2
cmp [hdd_appl_data], 0
jne .ide1_appl_data
mov eax, [cache_ide1_system_data]
ret
.ide1_appl_data:
mov eax, [cache_ide1_appl_data]
ret
.ide2:
cmp [hdpos], 3
jne .ide3
cmp [hdd_appl_data], 0
jne .ide2_appl_data
mov eax, [cache_ide2_system_data]
ret
.ide2_appl_data:
mov eax, [cache_ide2_appl_data]
ret
.ide3:
cmp [hdpos], 4
jne .noide
cmp [hdd_appl_data], 0
jne .ide3_appl_data
mov eax, [cache_ide3_system_data]
ret
.ide3_appl_data:
mov eax, [cache_ide3_appl_data]
ret
.noide:
mov eax, [hdpos]
sub eax, 80h
cmp byte [BiosDisksData+eax*4+2], -1
jz @f
movzx eax, byte [BiosDisksData+eax*4+2]
imul eax, cache_ide1-cache_ide0
add eax, cache_ide0
jmp .get
@@:
imul eax, cache_ide1-cache_ide0
add eax, BiosDiskCaches
.get:
cmp [hdd_appl_data], 0
jne .bd_appl_data
mov eax, [cache_ide0_system_data-cache_ide0+eax]
ret
.bd_appl_data:
mov eax, [cache_ide0_appl_data-cache_ide0+eax]
ret
;--------------------------------------------------------------------
align 4
calculate_cache_3:
; mov ecx,cache_max*10/100
; mov edi,[cache_search_start]
 
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [hdpos], 1
jne .ide1
cmp [hdd_appl_data], 0
jne .ide0_appl_data
mov ecx, [cache_ide0_system_sad_size]
mov edi, [cache_ide0_search_start]
ret
.ide0_appl_data:
mov ecx, [cache_ide0_appl_sad_size]
mov edi, [cache_ide0_appl_search_start]
ret
.ide1:
cmp [hdpos], 2
jne .ide2
cmp [hdd_appl_data], 0
jne .ide1_appl_data
mov ecx, [cache_ide1_system_sad_size]
mov edi, [cache_ide1_search_start]
ret
.ide1_appl_data:
mov ecx, [cache_ide1_appl_sad_size]
mov edi, [cache_ide1_appl_search_start]
ret
.ide2:
cmp [hdpos], 3
jne .ide3
cmp [hdd_appl_data], 0
jne .ide2_appl_data
mov ecx, [cache_ide2_system_sad_size]
mov edi, [cache_ide2_search_start]
ret
.ide2_appl_data:
mov ecx, [cache_ide2_appl_sad_size]
mov edi, [cache_ide2_appl_search_start]
ret
.ide3:
cmp [hdpos], 4
jne .noide
cmp [hdd_appl_data], 0
jne .ide3_appl_data
mov ecx, [cache_ide3_system_sad_size]
mov edi, [cache_ide3_search_start]
ret
.ide3_appl_data:
mov ecx, [cache_ide3_appl_sad_size]
mov edi, [cache_ide3_appl_search_start]
ret
.noide:
push eax
mov eax, [hdpos]
sub eax, 80h
cmp byte [BiosDisksData+eax*4+2], -1
jz @f
movzx eax, byte [BiosDisksData+eax*4+2]
imul eax, cache_ide1-cache_ide0
add eax, cache_ide0
jmp .get
@@:
imul eax, cache_ide1-cache_ide0
add eax, BiosDiskCaches
.get:
cmp [hdd_appl_data], 0
jne .bd_appl_data
mov ecx, [cache_ide0_system_sad_size-cache_ide0+eax]
mov edi, [cache_ide0_search_start-cache_ide0+eax]
pop eax
ret
.bd_appl_data:
mov ecx, [cache_ide0_appl_sad_size-cache_ide0+eax]
mov edi, [cache_ide0_appl_search_start-cache_ide0+eax]
pop eax
ret
;--------------------------------------------------------------------
align 4
calculate_cache_4:
; cmp edi,cache_max
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [hdpos], 1
jne .ide1
cmp [hdd_appl_data], 0
jne .ide0_appl_data
cmp edi, [cache_ide0_system_sad_size]
ret
.ide0_appl_data:
cmp edi, [cache_ide0_appl_sad_size]
ret
.ide1:
cmp [hdpos], 2
jne .ide2
cmp [hdd_appl_data], 0
jne .ide1_appl_data
cmp edi, [cache_ide1_system_sad_size]
ret
.ide1_appl_data:
cmp edi, [cache_ide1_appl_sad_size]
ret
.ide2:
cmp [hdpos], 3
jne .ide3
cmp [hdd_appl_data], 0
jne .ide2_appl_data
cmp edi, [cache_ide2_system_sad_size]
ret
.ide2_appl_data:
cmp edi, [cache_ide2_appl_sad_size]
ret
.ide3:
cmp [hdpos], 4
jne .noide
cmp [hdd_appl_data], 0
jne .ide3_appl_data
cmp edi, [cache_ide3_system_sad_size]
ret
.ide3_appl_data:
cmp edi, [cache_ide3_appl_sad_size]
ret
.noide:
push eax
mov eax, [hdpos]
sub eax, 80h
cmp byte [BiosDisksData+eax*4+2], -1
jz @f
movzx eax, byte [BiosDisksData+eax*4+2]
imul eax, cache_ide1-cache_ide0
add eax, cache_ide0
jmp .get
@@:
imul eax, cache_ide1-cache_ide0
add eax, BiosDiskCaches
.get:
cmp [hdd_appl_data], 0
jne .bd_appl_data
cmp edi, [cache_ide0_system_sad_size-cache_ide0+eax]
pop eax
ret
.bd_appl_data:
cmp edi, [cache_ide0_appl_sad_size-cache_ide0+eax]
pop eax
ret
 
;--------------------------------------------------------------------
align 4
calculate_cache_5:
; mov [cache_search_start],edi
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [hdpos], 1
jne .ide1
cmp [hdd_appl_data], 0
jne .ide0_appl_data
mov [cache_ide0_search_start], edi
ret
.ide0_appl_data:
mov [cache_ide0_appl_search_start], edi
ret
.ide1:
cmp [hdpos], 2
jne .ide2
cmp [hdd_appl_data], 0
jne .ide1_appl_data
mov [cache_ide1_search_start], edi
ret
.ide1_appl_data:
mov [cache_ide1_appl_search_start], edi
ret
.ide2:
cmp [hdpos], 3
jne .ide3
cmp [hdd_appl_data], 0
jne .ide2_appl_data
mov [cache_ide2_search_start], edi
ret
.ide2_appl_data:
mov [cache_ide2_appl_search_start], edi
ret
.ide3:
cmp [hdpos], 4
jne .noide
cmp [hdd_appl_data], 0
jne .ide3_appl_data
mov [cache_ide3_search_start], edi
ret
.ide3_appl_data:
mov [cache_ide3_appl_search_start], edi
ret
.noide:
push eax
mov eax, [hdpos]
sub eax, 80h
cmp byte [BiosDisksData+eax*4+2], -1
jz @f
movzx eax, byte [BiosDisksData+eax*4+2]
imul eax, cache_ide1-cache_ide0
add eax, cache_ide0
jmp .get
@@:
imul eax, cache_ide1-cache_ide0
add eax, BiosDiskCaches
.get:
cmp [hdd_appl_data], 0
jne .bd_appl_data
mov [cache_ide0_search_start-cache_ide0+eax], edi
pop eax
ret
.bd_appl_data:
mov [cache_ide0_appl_search_start-cache_ide0+eax], edi
pop eax
ret
 
;--------------------------------------------------------------------
align 4
find_empty_slot_CD_cache:
;-----------------------------------------------------------
; find empty or read slot, flush cache if next 10% is used by write
; output : edi = cache slot
;-----------------------------------------------------------
.search_again:
call cd_calculate_cache_3
.search_for_empty:
inc edi
call cd_calculate_cache_4
jbe .inside_cache
mov edi, 1
.inside_cache:
call cd_calculate_cache_5
ret
;--------------------------------------------------------------------
clear_CD_cache:
pusha
.ide0:
xor eax, eax
cmp [cdpos], 1
jne .ide1
mov [cache_ide0_search_start], eax
mov ecx, [cache_ide0_system_sad_size]
mov edi, [cache_ide0_pointer]
call .clear
mov [cache_ide0_appl_search_start], eax
mov ecx, [cache_ide0_appl_sad_size]
mov edi, [cache_ide0_data_pointer]
jmp .continue
.ide1:
cmp [cdpos], 2
jne .ide2
mov [cache_ide1_search_start], eax
mov ecx, [cache_ide1_system_sad_size]
mov edi, [cache_ide1_pointer]
call .clear
mov [cache_ide1_appl_search_start], eax
mov ecx, [cache_ide1_appl_sad_size]
mov edi, [cache_ide1_data_pointer]
jmp .continue
.ide2:
cmp [cdpos], 3
jne .ide3
mov [cache_ide2_search_start], eax
mov ecx, [cache_ide2_system_sad_size]
mov edi, [cache_ide2_pointer]
call .clear
mov [cache_ide2_appl_search_start], eax
mov ecx, [cache_ide2_appl_sad_size]
mov edi, [cache_ide2_data_pointer]
jmp .continue
.ide3:
mov [cache_ide3_search_start], eax
mov ecx, [cache_ide3_system_sad_size]
mov edi, [cache_ide3_pointer]
call .clear
mov [cache_ide3_appl_search_start], eax
mov ecx, [cache_ide3_appl_sad_size]
mov edi, [cache_ide3_data_pointer]
.continue:
call .clear
popa
ret
.clear:
shl ecx, 1
cld
rep stosd
ret
;--------------------------------------------------------------------
align 4
cd_calculate_cache:
; mov ecx,cache_max ; entries in cache
; mov esi,HD_CACHE+8
 
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [cdpos], 1
jne .ide1
cmp [cd_appl_data], 0
jne .ide0_appl_data
mov ecx, [cache_ide0_system_sad_size]
mov esi, [cache_ide0_pointer]
ret
.ide0_appl_data:
mov ecx, [cache_ide0_appl_sad_size]
mov esi, [cache_ide0_data_pointer]
ret
.ide1:
cmp [cdpos], 2
jne .ide2
cmp [cd_appl_data], 0
jne .ide1_appl_data
mov ecx, [cache_ide1_system_sad_size]
mov esi, [cache_ide1_pointer]
ret
.ide1_appl_data:
mov ecx, [cache_ide1_appl_sad_size]
mov esi, [cache_ide1_data_pointer]
ret
.ide2:
cmp [cdpos], 3
jne .ide3
cmp [cd_appl_data], 0
jne .ide2_appl_data
mov ecx, [cache_ide2_system_sad_size]
mov esi, [cache_ide2_pointer]
ret
.ide2_appl_data:
mov ecx, [cache_ide2_appl_sad_size]
mov esi, [cache_ide2_data_pointer]
ret
.ide3:
cmp [cd_appl_data], 0
jne .ide3_appl_data
mov ecx, [cache_ide3_system_sad_size]
mov esi, [cache_ide3_pointer]
ret
.ide3_appl_data:
mov ecx, [cache_ide3_appl_sad_size]
mov esi, [cache_ide3_data_pointer]
ret
;--------------------------------------------------------------------
align 4
cd_calculate_cache_1:
; lea esi,[edi*8+HD_CACHE]
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [cdpos], 1
jne .ide1
cmp [cd_appl_data], 0
jne .ide0_appl_data
mov esi, [cache_ide0_pointer]
ret
.ide0_appl_data:
mov esi, [cache_ide0_data_pointer]
ret
.ide1:
cmp [cdpos], 2
jne .ide2
cmp [cd_appl_data], 0
jne .ide1_appl_data
mov esi, [cache_ide1_pointer]
ret
.ide1_appl_data:
mov esi, [cache_ide1_data_pointer]
ret
.ide2:
cmp [cdpos], 3
jne .ide3
cmp [cd_appl_data], 0
jne .ide2_appl_data
mov esi, [cache_ide2_pointer]
ret
.ide2_appl_data:
mov esi, [cache_ide2_data_pointer]
ret
.ide3:
cmp [cd_appl_data], 0
jne .ide3_appl_data
mov esi, [cache_ide3_pointer]
ret
.ide3_appl_data:
mov esi, [cache_ide3_data_pointer]
ret
;--------------------------------------------------------------------
align 4
cd_calculate_cache_2:
; add esi,HD_CACHE+65536
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [cdpos], 1
jne .ide1
cmp [cd_appl_data], 0
jne .ide0_appl_data
mov eax, [cache_ide0_system_data]
ret
.ide0_appl_data:
mov eax, [cache_ide0_appl_data]
ret
.ide1:
cmp [cdpos], 2
jne .ide2
cmp [cd_appl_data], 0
jne .ide1_appl_data
mov eax, [cache_ide1_system_data]
ret
.ide1_appl_data:
mov eax, [cache_ide1_appl_data]
ret
.ide2:
cmp [cdpos], 3
jne .ide3
cmp [cd_appl_data], 0
jne .ide2_appl_data
mov eax, [cache_ide2_system_data]
ret
.ide2_appl_data:
mov eax, [cache_ide2_appl_data]
ret
.ide3:
cmp [cd_appl_data], 0
jne .ide3_appl_data
mov eax, [cache_ide3_system_data]
ret
.ide3_appl_data:
mov eax, [cache_ide3_appl_data]
ret
;--------------------------------------------------------------------
align 4
cd_calculate_cache_3:
; mov ecx,cache_max*10/100
; mov edi,[cache_search_start]
 
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [cdpos], 1
jne .ide1
cmp [cd_appl_data], 0
jne .ide0_appl_data
mov edi, [cache_ide0_search_start]
ret
.ide0_appl_data:
mov edi, [cache_ide0_appl_search_start]
ret
.ide1:
cmp [cdpos], 2
jne .ide2
cmp [cd_appl_data], 0
jne .ide1_appl_data
mov edi, [cache_ide1_search_start]
ret
.ide1_appl_data:
mov edi, [cache_ide1_appl_search_start]
ret
.ide2:
cmp [cdpos], 3
jne .ide3
cmp [cd_appl_data], 0
jne .ide2_appl_data
mov edi, [cache_ide2_search_start]
ret
.ide2_appl_data:
mov edi, [cache_ide2_appl_search_start]
ret
.ide3:
cmp [cd_appl_data], 0
jne .ide3_appl_data
mov edi, [cache_ide3_search_start]
ret
.ide3_appl_data:
mov edi, [cache_ide3_appl_search_start]
ret
;--------------------------------------------------------------------
align 4
cd_calculate_cache_4:
; cmp edi,cache_max
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [cdpos], 1
jne .ide1
cmp [cd_appl_data], 0
jne .ide0_appl_data
cmp edi, [cache_ide0_system_sad_size]
ret
.ide0_appl_data:
cmp edi, [cache_ide0_appl_sad_size]
ret
.ide1:
cmp [cdpos], 2
jne .ide2
cmp [cd_appl_data], 0
jne .ide1_appl_data
cmp edi, [cache_ide1_system_sad_size]
ret
.ide1_appl_data:
cmp edi, [cache_ide1_appl_sad_size]
ret
.ide2:
cmp [cdpos], 3
jne .ide3
cmp [cd_appl_data], 0
jne .ide2_appl_data
cmp edi, [cache_ide2_system_sad_size]
ret
.ide2_appl_data:
cmp edi, [cache_ide2_appl_sad_size]
ret
.ide3:
cmp [cd_appl_data], 0
jne .ide3_appl_data
cmp edi, [cache_ide3_system_sad_size]
ret
.ide3_appl_data:
cmp edi, [cache_ide3_appl_sad_size]
ret
;--------------------------------------------------------------------
align 4
cd_calculate_cache_5:
; mov [cache_search_start],edi
; 1 - IDE0 ... 4 - IDE3
.ide0:
cmp [cdpos], 1
jne .ide1
cmp [cd_appl_data], 0
jne .ide0_appl_data
mov [cache_ide0_search_start], edi
ret
.ide0_appl_data:
mov [cache_ide0_appl_search_start], edi
ret
.ide1:
cmp [cdpos], 2
jne .ide2
cmp [cd_appl_data], 0
jne .ide1_appl_data
mov [cache_ide1_search_start], edi
ret
.ide1_appl_data:
mov [cache_ide1_appl_search_start], edi
ret
.ide2:
cmp [cdpos], 3
jne .ide3
cmp [cd_appl_data], 0
jne .ide2_appl_data
mov [cache_ide2_search_start], edi
ret
.ide2_appl_data:
mov [cache_ide2_appl_search_start], edi
ret
.ide3:
cmp [cd_appl_data], 0
jne .ide3_appl_data
mov [cache_ide3_search_start], edi
ret
.ide3_appl_data:
mov [cache_ide3_appl_search_start], edi
ret
;--------------------------------------------------------------------
;align 4
;calculate_linear_to_real:
; shr eax, 12
; mov eax, [page_tabs+eax*4]
; and eax, 0xFFFFF000
; ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/blkdev/rdsave.inc
0,0 → 1,30
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
iglobal
saverd_fileinfo:
dd 2 ; subfunction: write
dd 0 ; (reserved)
dd 0 ; (reserved)
dd 1440*1024 ; size 1440 Kb
dd RAMDISK
db 0
.name:
dd ?
endg
sysfn_saveramdisk: ; 18.6 = SAVE FLOPPY IMAGE (HD version only)
call restorefatchain
mov ebx, saverd_fileinfo
mov [saverd_fileinfo.name], ecx
pushad
call file_system_lfn_protected ;in ebx
popad
mov [esp+32], eax
ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/blkdev/cd_drv.inc
0,0 → 1,931
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
;**********************************************************
; Íåïîñðåäñòâåííàÿ ðàáîòà ñ óñòðîéñòâîì ÑD (ATAPI)
;**********************************************************
; Àâòîð ÷àñòè èñõîäíîãî òåêñòà Êóëàêîâ Âëàäèìèð Ãåííàäüåâè÷
; Àäàïòàöèÿ, äîðàáîòêà è ðàçðàáîòêà Mario79,<Lrz>
 
; Ìàêñèìàëüíîå êîëè÷åñòâî ïîâòîðåíèé îïåðàöèè ÷òåíèÿ
MaxRetr equ 10
; Ïðåäåëüíîå âðåìÿ îæèäàíèÿ ãîòîâíîñòè ê ïðèåìó êîìàíäû
; (â òèêàõ)
BSYWaitTime equ 1000 ;2
NoTickWaitTime equ 0xfffff
CDBlockSize equ 2048
;********************************************
;* ×ÒÅÍÈÅ ÑÅÊÒÎÐÀ Ñ ÏÎÂÒÎÐÀÌÈ *
;* Ìíîãîêðàòíîå ïîâòîðåíèå ÷òåíèÿ ïðè ñáîÿõ *
;********************************************
ReadCDWRetr:
;-----------------------------------------------------------
; input : eax = block to read
; ebx = destination
;-----------------------------------------------------------
pushad
mov eax, [CDSectorAddress]
mov ebx, [CDDataBuf_pointer]
call cd_calculate_cache
xor edi, edi
add esi, 8
inc edi
.hdreadcache:
; cmp dword [esi+4],0 ; empty
; je .nohdcache
cmp [esi], eax ; correct sector
je .yeshdcache
.nohdcache:
add esi, 8
inc edi
dec ecx
jnz .hdreadcache
call find_empty_slot_CD_cache ; ret in edi
 
push edi
push eax
call cd_calculate_cache_2
shl edi, 11
add edi, eax
mov [CDDataBuf_pointer], edi
pop eax
pop edi
 
call ReadCDWRetr_1
cmp [DevErrorCode], 0
jne .exit
 
mov [CDDataBuf_pointer], ebx
call cd_calculate_cache_1
lea esi, [edi*8+esi]
mov [esi], eax ; sector number
; mov dword [esi+4],1 ; hd read - mark as same as in hd
.yeshdcache:
mov esi, edi
shl esi, 11;9
push eax
call cd_calculate_cache_2
add esi, eax
pop eax
mov edi, ebx;[CDDataBuf_pointer]
mov ecx, 512;/4
cld
rep movsd ; move data
.exit:
popad
ret
 
ReadCDWRetr_1:
pushad
 
; Öèêë, ïîêà êîìàíäà íå âûïîëíåíà óñïåøíî èëè íå
; èñ÷åðïàíî êîëè÷åñòâî ïîïûòîê
mov ECX, MaxRetr
@@NextRetr:
; Ïîäàòü êîìàíäó
;*************************************************
;* ÏÎËÍÎÅ ×ÒÅÍÈÅ ÑÅÊÒÎÐÀ ÊÎÌÏÀÊÒ-ÄÈÑÊÀ *
;* Ñ÷èòûâàþòñÿ äàííûå ïîëüçîâàòåëÿ, èíôîðìàöèÿ *
;* ñóáêàíàëà è êîíòðîëüíàÿ èíôîðìàöèÿ *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðìåííûå: *
;* ChannelNumber - íîìåð êàíàëà; *
;* DiskNumber - íîìåð äèñêà íà êàíàëå; *
;* CDSectorAddress - àäðåñ ñ÷èòûâàåìîãî ñåêòîðà. *
;* Äàííûå ñ÷èòûâàåòñÿ â ìàññèâ CDDataBuf. *
;*************************************************
;ReadCD:
push ecx
; pusha
; Çàäàòü ðàçìåð ñåêòîðà
; mov [CDBlockSize],2048 ;2352
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû
call clear_packet_buffer
; Ñôîðìèðîâàòü ïàêåòíóþ êîìàíäó äëÿ ñ÷èòûâàíèÿ
; ñåêòîðà äàííûõ
; Çàäàòü êîä êîìàíäû Read CD
mov [PacketCommand], byte 0x28;0xBE
; Çàäàòü àäðåñ ñåêòîðà
mov AX, word [CDSectorAddress+2]
xchg AL, AH
mov word [PacketCommand+2], AX
mov AX, word [CDSectorAddress]
xchg AL, AH
mov word [PacketCommand+4], AX
; mov eax,[CDSectorAddress]
; mov [PacketCommand+2],eax
; Çàäàòü êîëè÷åñòâî ñ÷èòûâàåìûõ ñåêòîðîâ
mov [PacketCommand+8], byte 1
; Çàäàòü ñ÷èòûâàíèå äàííûõ â ïîëíîì îáúåìå
; mov [PacketCommand+9],byte 0xF8
; Ïîäàòü êîìàíäó
call SendPacketDatCommand
pop ecx
; ret
 
; cmp [DevErrorCode],0
test eax, eax
jz @@End_4
 
or ecx, ecx ;{SPraid.simba} (for cd load)
jz @@End_4
dec ecx
 
cmp [timer_ticks_enable], 0
jne @f
mov eax, NoTickWaitTime
.wait:
dec eax
; test eax,eax
jz @@NextRetr
jmp .wait
@@:
; Çàäåðæêà íà 2,5 ñåêóíäû
; mov EAX,[timer_ticks]
; add EAX,50 ;250
;@@Wait:
; call change_task
; cmp EAX,[timer_ticks]
; ja @@Wait
loop @@NextRetr
@@End_4:
mov dword [DevErrorCode], eax
popad
ret
 
 
; Óíèâåðñàëüíûå ïðîöåäóðû, îáåñïå÷èâàþùèå âûïîëíåíèå
; ïàêåòíûõ êîìàíä â ðåæèìå PIO
 
; Ìàêñèìàëüíî äîïóñòèìîå âðåìÿ îæèäàíèÿ ðåàêöèè
; óñòðîéñòâà íà ïàêåòíóþ êîìàíäó (â òèêàõ)
 
MaxCDWaitTime equ 1000 ;200 ;10 ñåêóíä
uglobal
; Îáëàñòü ïàìÿòè äëÿ ôîðìèðîâàíèÿ ïàêåòíîé êîìàíäû
PacketCommand:
rb 12 ;DB 12 DUP (?)
; Îáëàñòü ïàìÿòè äëÿ ïðèåìà äàííûõ îò äèñêîâîäà
;CDDataBuf DB 4096 DUP (0)
; Ðàçìåð ïðèíèìàåìîãî áëîêà äàííûõ â áàéòàõ
;CDBlockSize DW ?
; Àäðåñ ñ÷èòûâàåìîãî ñåêòîðà äàííûõ
CDSectorAddress:
DD ?
; Âðåìÿ íà÷àëà î÷åðåäíîé îïåðàöèè ñ äèñêîì
TickCounter_1 DD 0
; Âðåìÿ íà÷àëà îæèäàíèÿ ãîòîâíîñòè óñòðîéñòâà
WURStartTime DD 0
; óêàçàòåëü áóôåðà äëÿ ñ÷èòûâàíèÿ
CDDataBuf_pointer dd 0
endg
;****************************************************
;* ÏÎÑËÀÒÜ ÓÑÒÐÎÉÑÒÂÓ ATAPI ÏÀÊÅÒÍÓÞ ÊÎÌÀÍÄÓ, *
;* ÏÐÅÄÓÑÌÀÒÐÈÂÀÞÙÓÞ ÏÅÐÅÄÀ×Ó ÎÄÍÎÃÎ ÑÅÊÒÎÐÀ ÄÀÍÍÛÕ *
;* ÐÀÇÌÅÐÎÌ 2048 ÁÀÉÒ ÎÒ ÓÑÒÐÎÉÑÒÂÀ Ê ÕÎÑÒÓ *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðìåííûå: *
;* ChannelNumber - íîìåð êàíàëà; *
;* DiskNumber - íîìåð äèñêà íà êàíàëå; *
;* PacketCommand - 12-áàéòíûé êîìàíäíûé ïàêåò; *
;* CDBlockSize - ðàçìåð ïðèíèìàåìîãî áëîêà äàííûõ. *
; return eax DevErrorCode
;****************************************************
SendPacketDatCommand:
xor eax, eax
; mov byte [DevErrorCode],al
; Çàäàòü ðåæèì CHS
mov byte [ATAAddressMode], al
; Ïîñëàòü ATA-êîìàíäó ïåðåäà÷è ïàêåòíîé êîìàíäû
mov byte [ATAFeatures], al
mov byte [ATASectorCount], al
mov byte [ATASectorNumber], al
; Çàãðóçèòü ðàçìåð ïåðåäàâàåìîãî áëîêà
mov [ATAHead], al
; mov AX,[CDBlockSize]
mov [ATACylinder], CDBlockSize
mov [ATACommand], 0A0h
call SendCommandToHDD_1
test eax, eax
; cmp [DevErrorCode],0 ;ïðîâåðèòü êîä îøèáêè
jnz @@End_8 ;çàêîí÷èòü, ñîõðàíèâ êîä îøèáêè
 
; Îæèäàíèå ãîòîâíîñòè äèñêîâîäà ê ïðèåìó
; ïàêåòíîé êîìàíäû
mov DX, [ATABasePortAddr]
add DX, 7 ;ïîðò 1õ7h
mov ecx, NoTickWaitTime
@@WaitDevice0:
cmp [timer_ticks_enable], 0
jne @f
dec ecx
; test ecx,ecx
jz @@Err1_1
jmp .test
@@:
call change_task
; Ïðîâåðèòü âðåìÿ âûïîëíåíèÿ êîìàíäû
mov EAX, [timer_ticks]
sub EAX, [TickCounter_1]
cmp EAX, BSYWaitTime
ja @@Err1_1 ;îøèáêà òàéì-àóòà
; Ïðîâåðèòü ãîòîâíîñòü
.test:
in AL, DX
test AL, 80h ;ñîñòîÿíèå ñèãíàëà BSY
jnz @@WaitDevice0
test AL, 1 ;ñîñòîÿíèå ñèãíàëà ERR
jnz @@Err6
test AL, 08h ;ñîñòîÿíèå ñèãíàëà DRQ
jz @@WaitDevice0
; Ïîñëàòü ïàêåòíóþ êîìàíäó
cli
mov DX, [ATABasePortAddr]
mov AX, [PacketCommand]
out DX, AX
mov AX, [PacketCommand+2]
out DX, AX
mov AX, [PacketCommand+4]
out DX, AX
mov AX, [PacketCommand+6]
out DX, AX
mov AX, [PacketCommand+8]
out DX, AX
mov AX, [PacketCommand+10]
out DX, AX
sti
; Îæèäàíèå ãîòîâíîñòè äàííûõ
mov DX, [ATABasePortAddr]
add DX, 7 ;ïîðò 1õ7h
mov ecx, NoTickWaitTime
@@WaitDevice1:
cmp [timer_ticks_enable], 0
jne @f
dec ecx
; test ecx,ecx
jz @@Err1_1
jmp .test_1
@@:
call change_task
; Ïðîâåðèòü âðåìÿ âûïîëíåíèÿ êîìàíäû
mov EAX, [timer_ticks]
sub EAX, [TickCounter_1]
cmp EAX, MaxCDWaitTime
ja @@Err1_1 ;îøèáêà òàéì-àóòà
; Ïðîâåðèòü ãîòîâíîñòü
.test_1:
in AL, DX
test AL, 80h ;ñîñòîÿíèå ñèãíàëà BSY
jnz @@WaitDevice1
test AL, 1 ;ñîñòîÿíèå ñèãíàëà ERR
jnz @@Err6_temp
test AL, 08h ;ñîñòîÿíèå ñèãíàëà DRQ
jz @@WaitDevice1
; Ïðèíÿòü áëîê äàííûõ îò êîíòðîëëåðà
mov EDI, [CDDataBuf_pointer];0x7000 ;CDDataBuf
; Çàãðóçèòü àäðåñ ðåãèñòðà äàííûõ êîíòðîëëåðà
mov DX, [ATABasePortAddr];ïîðò 1x0h
; Çàãðóçèòü â ñ÷åò÷èê ðàçìåð áëîêà â áàéòàõ
xor ecx, ecx
mov CX, CDBlockSize
; Âû÷èñëèòü ðàçìåð áëîêà â 16-ðàçðÿäíûõ ñëîâàõ
shr CX, 1;ðàçäåëèòü ðàçìåð áëîêà íà 2
; Ïðèíÿòü áëîê äàííûõ
cli
cld
rep insw
sti
; Óñïåøíîå çàâåðøåíèå ïðèåìà äàííûõ
@@End_8:
xor eax, eax
ret
 
; Çàïèñàòü êîä îøèáêè
@@Err1_1:
xor eax, eax
inc eax
ret
; mov [DevErrorCode],1
; ret
@@Err6_temp:
mov eax, 7
ret
; mov [DevErrorCode],7
; ret
@@Err6:
mov eax, 6
ret
; mov [DevErrorCode],6
;@@End_8:
; ret
 
 
 
;***********************************************
;* ÏÎÑËÀÒÜ ÓÑÒÐÎÉÑÒÂÓ ATAPI ÏÀÊÅÒÍÓÞ ÊÎÌÀÍÄÓ, *
;* ÍÅ ÏÐÅÄÓÑÌÀÒÐÈÂÀÞÙÓÞ ÏÅÐÅÄÀ×È ÄÀÍÍÛÕ *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç *
;* ãëîáàëüíûå ïåðìåííûå: *
;* ChannelNumber - íîìåð êàíàëà; *
;* DiskNumber - íîìåð äèñêà íà êàíàëå; *
;* PacketCommand - 12-áàéòíûé êîìàíäíûé ïàêåò. *
;***********************************************
SendPacketNoDatCommand:
pushad
xor eax, eax
; mov byte [DevErrorCode],al
; Çàäàòü ðåæèì CHS
mov byte [ATAAddressMode], al
; Ïîñëàòü ATA-êîìàíäó ïåðåäà÷è ïàêåòíîé êîìàíäû
mov byte [ATAFeatures], al
mov byte [ATASectorCount], al
mov byte [ATASectorNumber], al
mov word [ATACylinder], ax
mov byte [ATAHead], al
mov [ATACommand], 0A0h
call SendCommandToHDD_1
; cmp [DevErrorCode],0 ;ïðîâåðèòü êîä îøèáêè
test eax, eax
jnz @@End_9 ;çàêîí÷èòü, ñîõðàíèâ êîä îøèáêè
; Îæèäàíèå ãîòîâíîñòè äèñêîâîäà ê ïðèåìó
; ïàêåòíîé êîìàíäû
mov DX, [ATABasePortAddr]
add DX, 7 ;ïîðò 1õ7h
@@WaitDevice0_1:
call change_task
; Ïðîâåðèòü âðåìÿ îæèäàíèÿ
mov EAX, [timer_ticks]
sub EAX, [TickCounter_1]
cmp EAX, BSYWaitTime
ja @@Err1_3 ;îøèáêà òàéì-àóòà
; Ïðîâåðèòü ãîòîâíîñòü
in AL, DX
test AL, 80h ;ñîñòîÿíèå ñèãíàëà BSY
jnz @@WaitDevice0_1
test AL, 1 ;ñîñòîÿíèå ñèãíàëà ERR
jnz @@Err6_1
test AL, 08h ;ñîñòîÿíèå ñèãíàëà DRQ
jz @@WaitDevice0_1
; Ïîñëàòü ïàêåòíóþ êîìàíäó
; cli
mov DX, [ATABasePortAddr]
mov AX, word [PacketCommand]
out DX, AX
mov AX, word [PacketCommand+2]
out DX, AX
mov AX, word [PacketCommand+4]
out DX, AX
mov AX, word [PacketCommand+6]
out DX, AX
mov AX, word [PacketCommand+8]
out DX, AX
mov AX, word [PacketCommand+10]
out DX, AX
; sti
cmp [ignore_CD_eject_wait], 1
je @@clear_DEC
; Îæèäàíèå ïîäòâåðæäåíèÿ ïðèåìà êîìàíäû
mov DX, [ATABasePortAddr]
add DX, 7 ;ïîðò 1õ7h
@@WaitDevice1_1:
call change_task
; Ïðîâåðèòü âðåìÿ âûïîëíåíèÿ êîìàíäû
mov EAX, [timer_ticks]
sub EAX, [TickCounter_1]
cmp EAX, MaxCDWaitTime
ja @@Err1_3 ;îøèáêà òàéì-àóòà
; Îæèäàòü îñâîáîæäåíèÿ óñòðîéñòâà
in AL, DX
test AL, 80h ;ñîñòîÿíèå ñèãíàëà BSY
jnz @@WaitDevice1_1
test AL, 1 ;ñîñòîÿíèå ñèãíàëà ERR
jnz @@Err6_1
test AL, 40h ;ñîñòîÿíèå ñèãíàëà DRDY
jz @@WaitDevice1_1
@@clear_DEC:
and [DevErrorCode], 0
popad
ret
; Çàïèñàòü êîä îøèáêè
@@Err1_3:
xor eax, eax
inc eax
jmp @@End_9
@@Err6_1:
mov eax, 6
@@End_9:
mov [DevErrorCode], eax
popad
ret
 
;****************************************************
;* ÏÎÑËÀÒÜ ÊÎÌÀÍÄÓ ÇÀÄÀÍÍÎÌÓ ÄÈÑÊÓ *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðåìåííûå: *
;* ChannelNumber - íîìåð êàíàëà (1 èëè 2); *
;* DiskNumber - íîìåð äèñêà (0 èëè 1); *
;* ATAFeatures - "îñîáåííîñòè"; *
;* ATASectorCount - êîëè÷åñòâî ñåêòîðîâ; *
;* ATASectorNumber - íîìåð íà÷àëüíîãî ñåêòîðà; *
;* ATACylinder - íîìåð íà÷àëüíîãî öèëèíäðà; *
;* ATAHead - íîìåð íà÷àëüíîé ãîëîâêè; *
;* ATAAddressMode - ðåæèì àäðåñàöèè (0-CHS, 1-LBA); *
;* ATACommand - êîä êîìàíäû. *
;* Ïîñëå óñïåøíîãî âûïîëíåíèÿ ôóíêöèè: *
;* â ATABasePortAddr - áàçîâûé àäðåñ HDD; *
;* â DevErrorCode - íîëü. *
;* Ïðè âîçíèêíîâåíèè îøèáêè â DevErrorCode áóäåò *
;* âîçâðàùåí êîä îøèáêè â eax *
;****************************************************
SendCommandToHDD_1:
; pushad
; mov [DevErrorCode],0 not need
; Ïðîâåðèòü çíà÷åíèå êîäà ðåæèìà
cmp [ATAAddressMode], 1
ja @@Err2_4
; Ïðîâåðèòü êîððåêòíîñòü íîìåðà êàíàëà
mov BX, [ChannelNumber]
cmp BX, 1
jb @@Err3_4
cmp BX, 2
ja @@Err3_4
; Óñòàíîâèòü áàçîâûé àäðåñ
dec BX
shl BX, 1
movzx ebx, bx
mov AX, [ebx+StandardATABases]
mov [ATABasePortAddr], AX
; Îæèäàíèå ãîòîâíîñòè HDD ê ïðèåìó êîìàíäû
; Âûáðàòü íóæíûé äèñê
mov DX, [ATABasePortAddr]
add DX, 6 ;àäðåñ ðåãèñòðà ãîëîâîê
mov AL, [DiskNumber]
cmp AL, 1 ;ïðîâåðèòü íîìåðà äèñêà
ja @@Err4_4
shl AL, 4
or AL, 10100000b
out DX, AL
; Îæèäàòü, ïîêà äèñê íå áóäåò ãîòîâ
inc DX
mov eax, [timer_ticks]
mov [TickCounter_1], eax
mov ecx, NoTickWaitTime
@@WaitHDReady_2:
cmp [timer_ticks_enable], 0
jne @f
dec ecx
; test ecx,ecx
jz @@Err1_4
jmp .test
@@:
call change_task
; Ïðîâåðèòü âðåìÿ îæèäàíèÿ
mov eax, [timer_ticks]
sub eax, [TickCounter_1]
cmp eax, BSYWaitTime;300 ;îæèäàòü 3 ñåê.
ja @@Err1_4 ;îøèáêà òàéì-àóòà
; Ïðî÷èòàòü ðåãèñòð ñîñòîÿíèÿ
.test:
in AL, DX
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà BSY
test AL, 80h
jnz @@WaitHDReady_2
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà DRQ
test AL, 08h
jnz @@WaitHDReady_2
 
; Çàãðóçèòü êîìàíäó â ðåãèñòðû êîíòðîëëåðà
cli
mov DX, [ATABasePortAddr]
inc DX ;ðåãèñòð "îñîáåííîñòåé"
mov AL, [ATAFeatures]
out DX, AL
inc DX ;ñ÷åò÷èê ñåêòîðîâ
mov AL, [ATASectorCount]
out DX, AL
inc DX ;ðåãèñòð íîìåðà ñåêòîðà
mov AL, [ATASectorNumber]
out DX, AL
inc DX ;íîìåð öèëèíäðà (ìëàäøèé áàéò)
mov AX, [ATACylinder]
out DX, AL
inc DX ;íîìåð öèëèíäðà (ñòàðøèé áàéò)
mov AL, AH
out DX, AL
inc DX ;íîìåð ãîëîâêè/íîìåð äèñêà
mov AL, [DiskNumber]
shl AL, 4
cmp [ATAHead], 0Fh;ïðîâåðèòü íîìåð ãîëîâêè
ja @@Err5_4
or AL, [ATAHead]
or AL, 10100000b
mov AH, [ATAAddressMode]
shl AH, 6
or AL, AH
out DX, AL
; Ïîñëàòü êîìàíäó
mov AL, [ATACommand]
inc DX ;ðåãèñòð êîìàíä
out DX, AL
sti
; Ñáðîñèòü ïðèçíàê îøèáêè
; mov [DevErrorCode],0
@@End_10:
xor eax, eax
ret
; Çàïèñàòü êîä îøèáêè
@@Err1_4:
xor eax, eax
inc eax
; mov [DevErrorCode],1
ret
@@Err2_4:
mov eax, 2
; mov [DevErrorCode],2
ret
@@Err3_4:
mov eax, 3
; mov [DevErrorCode],3
ret
@@Err4_4:
mov eax, 4
; mov [DevErrorCode],4
ret
@@Err5_4:
mov eax, 5
; mov [DevErrorCode],5
; Çàâåðøåíèå ðàáîòû ïðîãðàììû
ret
; sti
; popad
 
;*************************************************
;* ÎÆÈÄÀÍÈÅ ÃÎÒÎÂÍÎÑÒÈ ÓÑÒÐÎÉÑÒÂÀ Ê ÐÀÁÎÒÅ *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðìåííûå: *
;* ChannelNumber - íîìåð êàíàëà; *
;* DiskNumber - íîìåð äèñêà íà êàíàëå. *
;*************************************************
WaitUnitReady:
pusha
; Çàïîìíèòü âðåìÿ íà÷àëà îïåðàöèè
mov EAX, [timer_ticks]
mov [WURStartTime], EAX
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû
call clear_packet_buffer
; Ñôîðìèðîâàòü êîìàíäó TEST UNIT READY
mov [PacketCommand], word 00h
; ÖÈÊË ÎÆÈÄÀÍÈß ÃÎÒÎÂÍÎÑÒÈ ÓÑÒÐÎÉÑÒÂÀ
mov ecx, NoTickWaitTime
@@SendCommand:
; Ïîäàòü êîìàíäó ïðîâåðêè ãîòîâíîñòè
call SendPacketNoDatCommand
cmp [timer_ticks_enable], 0
jne @f
cmp [DevErrorCode], 0
je @@End_11
dec ecx
; cmp ecx,0
jz .Error
jmp @@SendCommand
@@:
call change_task
; Ïðîâåðèòü êîä îøèáêè
cmp [DevErrorCode], 0
je @@End_11
; Ïðîâåðèòü âðåìÿ îæèäàíèÿ ãîòîâíîñòè
mov EAX, [timer_ticks]
sub EAX, [WURStartTime]
cmp EAX, MaxCDWaitTime
jb @@SendCommand
.Error:
; Îøèáêà òàéì-àóòà
mov [DevErrorCode], 1
@@End_11:
popa
ret
 
;*************************************************
;* ÇÀÏÐÅÒÈÒÜ ÑÌÅÍÓ ÄÈÑÊÀ *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðìåííûå: *
;* ChannelNumber - íîìåð êàíàëà; *
;* DiskNumber - íîìåð äèñêà íà êàíàëå. *
;*************************************************
prevent_medium_removal:
pusha
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû
call clear_packet_buffer
; Çàäàòü êîä êîìàíäû
mov [PacketCommand], byte 0x1E
; Çàäàòü êîä çàïðåòà
mov [PacketCommand+4], byte 11b
; Ïîäàòü êîìàíäó
call SendPacketNoDatCommand
mov eax, ATAPI_IDE0_lock
add eax, [cdpos]
dec eax
mov [eax], byte 1
popa
ret
 
;*************************************************
;* ÐÀÇÐÅØÈÒÜ ÑÌÅÍÓ ÄÈÑÊÀ *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðìåííûå: *
;* ChannelNumber - íîìåð êàíàëà; *
;* DiskNumber - íîìåð äèñêà íà êàíàëå. *
;*************************************************
allow_medium_removal:
pusha
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû
call clear_packet_buffer
; Çàäàòü êîä êîìàíäû
mov [PacketCommand], byte 0x1E
; Çàäàòü êîä çàïðåòà
mov [PacketCommand+4], byte 00b
; Ïîäàòü êîìàíäó
call SendPacketNoDatCommand
mov eax, ATAPI_IDE0_lock
add eax, [cdpos]
dec eax
mov [eax], byte 0
popa
ret
 
;*************************************************
;* ÇÀÃÐÓÇÈÒÜ ÍÎÑÈÒÅËÜ Â ÄÈÑÊÎÂÎÄ *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðìåííûå: *
;* ChannelNumber - íîìåð êàíàëà; *
;* DiskNumber - íîìåð äèñêà íà êàíàëå. *
;*************************************************
LoadMedium:
pusha
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû
call clear_packet_buffer
; Ñôîðìèðîâàòü êîìàíäó START/STOP UNIT
; Çàäàòü êîä êîìàíäû
mov [PacketCommand], word 1Bh
; Çàäàòü îïåðàöèþ çàãðóçêè íîñèòåëÿ
mov [PacketCommand+4], word 00000011b
; Ïîäàòü êîìàíäó
call SendPacketNoDatCommand
popa
ret
 
;*************************************************
;* ÈÇÂËÅ×Ü ÍÎÑÈÒÅËÜ ÈÇ ÄÈÑÊÎÂÎÄÀ *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðìåííûå: *
;* ChannelNumber - íîìåð êàíàëà; *
;* DiskNumber - íîìåð äèñêà íà êàíàëå. *
;*************************************************
EjectMedium:
pusha
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû
call clear_packet_buffer
; Ñôîðìèðîâàòü êîìàíäó START/STOP UNIT
; Çàäàòü êîä êîìàíäû
mov [PacketCommand], word 1Bh
; Çàäàòü îïåðàöèþ èçâëå÷åíèÿ íîñèòåëÿ
mov [PacketCommand+4], word 00000010b
; Ïîäàòü êîìàíäó
call SendPacketNoDatCommand
popa
ret
 
;*************************************************
;* Ïðîâåðèòü ñîáûòèå íàæàòèÿ êíîïêè èçâëå÷åíèÿ *
;* äèñêà *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðåìåííûå: *
;* ChannelNumber - íîìåð êàíàëà; *
;* DiskNumber - íîìåð äèñêà íà êàíàëå. *
;*************************************************
align 4
check_ATAPI_device_event:
pusha
mov eax, [timer_ticks]
sub eax, [timer_ATAPI_check]
cmp eax, 100
jb .end_1
mov al, [DRIVE_DATA+1]
and al, 11b
cmp al, 10b
jz .ide3
.ide2_1:
mov al, [DRIVE_DATA+1]
and al, 1100b
cmp al, 1000b
jz .ide2
.ide1_1:
mov al, [DRIVE_DATA+1]
and al, 110000b
cmp al, 100000b
jz .ide1
.ide0_1:
mov al, [DRIVE_DATA+1]
and al, 11000000b
cmp al, 10000000b
jz .ide0
.end:
 
sti
mov eax, [timer_ticks]
mov [timer_ATAPI_check], eax
.end_1:
popa
ret
 
.ide3:
cli
cmp [ATAPI_IDE3_lock], 1
jne .ide2_1
cmp [IDE_Channel_2], 0
jne .ide1_1
cmp [cd_status], 0
jne .end
mov [IDE_Channel_2], 1
call reserve_ok2
mov [ChannelNumber], 2
mov [DiskNumber], 1
mov [cdpos], 4
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
je .eject_ide3
call syscall_cdaudio.free
jmp .ide2_1
.eject_ide3:
call .eject
call syscall_cdaudio.free
jmp .ide2_1
 
.ide2:
cli
cmp [ATAPI_IDE2_lock], 1
jne .ide1_1
cmp [IDE_Channel_2], 0
jne .ide1_1
cmp [cd_status], 0
jne .end
mov [IDE_Channel_2], 1
call reserve_ok2
mov [ChannelNumber], 2
mov [DiskNumber], 0
mov [cdpos], 3
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
je .eject_ide2
call syscall_cdaudio.free
jmp .ide1_1
.eject_ide2:
call .eject
call syscall_cdaudio.free
jmp .ide1_1
 
.ide1:
cli
cmp [ATAPI_IDE1_lock], 1
jne .ide0_1
cmp [IDE_Channel_1], 0
jne .end
cmp [cd_status], 0
jne .end
mov [IDE_Channel_1], 1
call reserve_ok2
mov [ChannelNumber], 1
mov [DiskNumber], 1
mov [cdpos], 2
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
je .eject_ide1
call syscall_cdaudio.free
jmp .ide0_1
.eject_ide1:
call .eject
call syscall_cdaudio.free
jmp .ide0_1
 
.ide0:
cli
cmp [ATAPI_IDE0_lock], 1
jne .end
cmp [IDE_Channel_1], 0
jne .end
cmp [cd_status], 0
jne .end
mov [IDE_Channel_1], 1
call reserve_ok2
mov [ChannelNumber], 1
mov [DiskNumber], 0
mov [cdpos], 1
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
je .eject_ide0
call syscall_cdaudio.free
jmp .end
.eject_ide0:
call .eject
call syscall_cdaudio.free
jmp .end
 
.eject:
call clear_CD_cache
call allow_medium_removal
mov [ignore_CD_eject_wait], 1
call EjectMedium
mov [ignore_CD_eject_wait], 0
ret
iglobal
timer_ATAPI_check dd 0
ATAPI_IDE0_lock db 0
ATAPI_IDE1_lock db 0
ATAPI_IDE2_lock db 0
ATAPI_IDE3_lock db 0
ignore_CD_eject_wait db 0
endg
;*************************************************
;* Ïîëó÷èòü ñîîáùåíèå î ñîáûòèè èëè ñîñòîÿíèè *
;* óñòðîéñòâà *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðåìåííûå: *
;* ChannelNumber - íîìåð êàíàëà; *
;* DiskNumber - íîìåð äèñêà íà êàíàëå. *
;*************************************************
GetEvent_StatusNotification:
pusha
mov [CDDataBuf_pointer], CDDataBuf
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû
call clear_packet_buffer
; Çàäàòü êîä êîìàíäû
mov [PacketCommand], byte 4Ah
mov [PacketCommand+1], byte 00000001b
; Çàäàòü çàïðîñ êëàññà ñîîáùåíèé
mov [PacketCommand+4], byte 00010000b
; Ðàçìåð âûäåëåííîé îáëàñòè
mov [PacketCommand+7], byte 8h
mov [PacketCommand+8], byte 0h
; Ïîäàòü êîìàíäó
call SendPacketDatCommand
popa
ret
 
;*************************************************
; ïðî÷èòàòü èíôîðìàöèþ èç TOC
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðåìåííûå: *
;* ChannelNumber - íîìåð êàíàëà; *
;* DiskNumber - íîìåð äèñêà íà êàíàëå. *
;*************************************************
Read_TOC:
pusha
mov [CDDataBuf_pointer], CDDataBuf
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû
call clear_packet_buffer
; Ñôîðìèðîâàòü ïàêåòíóþ êîìàíäó äëÿ ñ÷èòûâàíèÿ
; ñåêòîðà äàííûõ
mov [PacketCommand], byte 0x43
; Çàäàòü ôîðìàò
mov [PacketCommand+2], byte 1
; Ðàçìåð âûäåëåííîé îáëàñòè
mov [PacketCommand+7], byte 0xFF
mov [PacketCommand+8], byte 0h
; Ïîäàòü êîìàíäó
call SendPacketDatCommand
popa
ret
 
;*************************************************
;* ÎÏÐÅÄÅËÈÒÜ ÎÁÙÅÅ ÊÎËÈ×ÅÑÒÂÎ ÑÅÊÒÎÐΠÍÀ ÄÈÑÊÅ *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðåìåííûå: *
;* ChannelNumber - íîìåð êàíàëà; *
;* DiskNumber - íîìåð äèñêà íà êàíàëå. *
;*************************************************
;ReadCapacity:
; pusha
;; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû
; call clear_packet_buffer
;; Çàäàòü ðàçìåð áóôåðà â áàéòàõ
; mov [CDBlockSize],8
;; Ñôîðìèðîâàòü êîìàíäó READ CAPACITY
; mov [PacketCommand],word 25h
;; Ïîäàòü êîìàíäó
; call SendPacketDatCommand
; popa
; ret
 
clear_packet_buffer:
; Î÷èñòèòü áóôåð ïàêåòíîé êîìàíäû
and [PacketCommand], dword 0
and [PacketCommand+4], dword 0
and [PacketCommand+8], dword 0
ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/blkdev/cdrom.inc
0,0 → 1,271
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
sys_cd_audio:
 
cmp word [cdbase], word 0
jnz @f
mov eax, 1
ret
@@:
 
; eax=1 cdplay at ebx 0x00FFSSMM
; eax=2 get tracklist size of ecx to [ebx]
; eax=3 stop/pause playing
 
cmp eax, 1
jnz nocdp
call sys_cdplay
ret
nocdp:
 
cmp eax, 2
jnz nocdtl
mov edi, [TASK_BASE]
add edi, TASKDATA.mem_start
add ebx, [edi]
call sys_cdtracklist
ret
nocdtl:
 
cmp eax, 3
jnz nocdpause
call sys_cdpause
ret
nocdpause:
 
mov eax, 0xffffff01
ret
 
 
 
sys_cd_atapi_command:
 
pushad
 
mov dx, word [cdbase]
add dx, 6
mov ax, word [cdid]
out dx, al
mov esi, 10
call delay_ms
mov dx, word [cdbase]
add dx, 7
in al, dx
and al, 0x80
cmp al, 0
jnz res
jmp cdl6
res:
mov dx, word [cdbase]
add dx, 7
mov al, 0x8
out dx, al
mov dx, word [cdbase]
add dx, 0x206
mov al, 0xe
out dx, al
mov esi, 1
call delay_ms
mov dx, word [cdbase]
add dx, 0x206
mov al, 0x8
out dx, al
mov esi, 30
call delay_ms
xor cx, cx
cdl5:
inc cx
cmp cx, 10
jz cdl6
mov dx, word [cdbase]
add dx, 7
in al, dx
and al, 0x88
cmp al, 0x00
jz cdl5
mov esi, 100
call delay_ms
jmp cdl5
cdl6:
mov dx, word [cdbase]
add dx, 4
mov al, 0
out dx, al
mov dx, word [cdbase]
add dx, 5
mov al, 0
out dx, al
mov dx, word [cdbase]
add dx, 7
mov al, 0xec
out dx, al
mov esi, 5
call delay_ms
mov dx, word [cdbase]
add dx, 1
mov al, 0
out dx, al
add dx, 1
mov al, 0
out dx, al
add dx, 1
mov al, 0
out dx, al
add dx, 1
mov al, 0
out dx, al
add dx, 1
mov al, 128
out dx, al
add dx, 2
mov al, 0xa0
out dx, al
xor cx, cx
mov dx, word [cdbase]
add dx, 7
cdl1:
inc cx
cmp cx, 100
jz cdl2
in al, dx
and ax, 0x88
cmp al, 0x8
jz cdl2
mov esi, 2
call delay_ms
jmp cdl1
cdl2:
 
popad
ret
 
 
sys_cdplay:
 
mov ax, 5
push ax
push ebx
cdplay:
call sys_cd_atapi_command
cli
mov dx, word [cdbase]
mov ax, 0x0047
out dx, ax
mov al, 1
mov ah, [esp+0]; min xx
out dx, ax
mov ax, [esp+1]; fr sec
out dx, ax
mov ax, 256+99
out dx, ax
mov ax, 0x0001
out dx, ax
mov ax, 0x0000
out dx, ax
mov esi, 10
call delay_ms
sti
add dx, 7
in al, dx
test al, 1
jz cdplayok
mov ax, [esp+4]
dec ax
mov [esp+4], ax
cmp ax, 0
jz cdplayfail
jmp cdplay
cdplayfail:
cdplayok:
pop ebx
pop ax
xor eax, eax
ret
 
 
sys_cdtracklist:
 
push ebx
tcdplay:
call sys_cd_atapi_command
mov dx, word [cdbase]
mov ax, 0x43+2*256
out dx, ax
mov ax, 0x0
out dx, ax
mov ax, 0x0
out dx, ax
mov ax, 0x0
out dx, ax
mov ax, 200
out dx, ax
mov ax, 0x0
out dx, ax
in al, dx
mov cx, 1000
mov dx, word [cdbase]
add dx, 7
cld
cdtrnwewait:
mov esi, 10
call delay_ms
in al, dx
and al, 128
cmp al, 0
jz cdtrl1
loop cdtrnwewait
cdtrl1:
; read the result
mov ecx, [esp+0]
mov dx, word [cdbase]
cdtrread:
add dx, 7
in al, dx
and al, 8
cmp al, 8
jnz cdtrdone
sub dx, 7
in ax, dx
mov [ecx], ax
add ecx, 2
jmp cdtrread
cdtrdone:
pop ecx
xor eax, eax
ret
 
 
sys_cdpause:
 
call sys_cd_atapi_command
 
mov dx, word [cdbase]
mov ax, 0x004B
out dx, ax
mov ax, 0
out dx, ax
mov ax, 0
out dx, ax
mov ax, 0
out dx, ax
mov ax, 0
out dx, ax
mov ax, 0
out dx, ax
 
mov esi, 10
call delay_ms
add dx, 7
in al, dx
 
xor eax, eax
ret
 
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/blkdev/fdc.inc
0,0 → 1,71
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
iglobal
;function pointers.
fdc_irq_func dd fdc_null
endg
 
uglobal
dmasize db 0x0
dmamode db 0x0
endg
 
fdc_init: ;start with clean tracks.
mov edi, OS_BASE+0xD201
mov al, 0
mov ecx, 160
rep stosb
ret
 
fdc_irq:
call [fdc_irq_func]
fdc_null:
ret
 
save_image:
call reserve_flp
call restorefatchain
pusha
call check_label
cmp [FDC_Status], 0
jne unnecessary_save_image
mov [FDD_Track], 0; Öèëèíäð
mov [FDD_Head], 0; Ñòîðîíà
mov [FDD_Sector], 1; Ñåêòîð
mov esi, RAMDISK
call SeekTrack
save_image_1:
push esi
call take_data_from_application_1
pop esi
add esi, 512
call WriteSectWithRetr
; call WriteSector
cmp [FDC_Status], 0
jne unnecessary_save_image
inc [FDD_Sector]
cmp [FDD_Sector], 19
jne save_image_1
mov [FDD_Sector], 1
inc [FDD_Head]
cmp [FDD_Head], 2
jne save_image_1
mov [FDD_Head], 0
inc [FDD_Track]
call SeekTrack
cmp [FDD_Track], 80
jne save_image_1
unnecessary_save_image:
mov [fdc_irq_func], fdc_null
popa
mov [flp_status], 0
ret
 
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/blkdev/flp_drv.inc
0,0 → 1,630
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
;**********************************************************
; Íåïîñðåäñòâåííàÿ ðàáîòà ñ êîíòðîëëåðîì ãèáêîãî äèñêà
;**********************************************************
; Àâòîð èñõîäíîãî òåêñòà Êóëàêîâ Âëàäèìèð Ãåííàäüåâè÷.
; Àäàïòàöèÿ è äîðàáîòêà Mario79
 
;give_back_application_data: ; ïåðåñëàòü ïðèëîæåíèþ
; mov edi,[TASK_BASE]
; mov edi,[edi+TASKDATA.mem_start]
; add edi,ecx
give_back_application_data_1:
mov esi, FDD_BUFF;FDD_DataBuffer ;0x40000
xor ecx, ecx
mov cx, 128
cld
rep movsd
ret
 
;take_data_from_application: ; âçÿòü èç ïðèëîæåíè
; mov esi,[TASK_BASE]
; mov esi,[esi+TASKDATA.mem_start]
; add esi,ecx
take_data_from_application_1:
mov edi, FDD_BUFF;FDD_DataBuffer ;0x40000
xor ecx, ecx
mov cx, 128
cld
rep movsd
ret
 
; Êîäû çàâåðøåíèÿ îïåðàöèè ñ êîíòðîëëåðîì (FDC_Status)
FDC_Normal equ 0 ;íîðìàëüíîå çàâåðøåíèå
FDC_TimeOut equ 1 ;îøèáêà òàéì-àóòà
FDC_DiskNotFound equ 2 ;â äèñêîâîäå íåò äèñêà
FDC_TrackNotFound equ 3 ;äîðîæêà íå íàéäåíà
FDC_SectorNotFound equ 4 ;ñåêòîð íå íàéäåí
 
; Ìàêñèìàëüíûå çíà÷åíèÿ êîîðäèíàò ñåêòîðà (çàäàííûå
; çíà÷åíèÿ ñîîòâåòñòâóþò ïàðàìåòðàì ñòàíäàðòíîãî
; òðåõäþéìîâîãî ãèáêîãî äèñêà îáúåìîì 1,44 Ìá)
MAX_Track equ 79
MAX_Head equ 1
MAX_Sector equ 18
 
uglobal
; Ñ÷åò÷èê òèêîâ òàéìåðà
TickCounter dd ?
; Êîä çàâåðøåíèÿ îïåðàöèè ñ êîíòðîëëåðîì ÍÃÌÄ
FDC_Status DB ?
; Ôëàã ïðåðûâàíèÿ îò ÍÃÌÄ
FDD_IntFlag DB ?
; Ìîìåíò íà÷àëà ïîñëåäíåé îïåðàöèè ñ ÍÃÌÄ
FDD_Time DD ?
; Íîìåð äèñêîâîäà
FDD_Type db 0
; Êîîðäèíàòû ñåêòîðà
FDD_Track DB ?
FDD_Head DB ?
FDD_Sector DB ?
 
; Áëîê ðåçóëüòàòà îïåðàöèè
FDC_ST0 DB ?
FDC_ST1 DB ?
FDC_ST2 DB ?
FDC_C DB ?
FDC_H DB ?
FDC_R DB ?
FDC_N DB ?
; Ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ÷òåíè
ReadRepCounter DB ?
; Ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ðåêàëèáðîâêè
RecalRepCounter DB ?
endg
; Îáëàñòü ïàìÿòè äëÿ õðàíåíèÿ ïðî÷èòàííîãî ñåêòîðà
;FDD_DataBuffer: times 512 db 0 ;DB 512 DUP (?)
fdd_motor_status db 0
timer_fdd_motor dd 0
 
;*************************************
;* ÈÍÈÖÈÀËÈÇÀÖÈß ÐÅÆÈÌÀ ÏÄÏ ÄËß ÍÃÌÄ *
;*************************************
Init_FDC_DMA:
pushad
mov al, 0
out 0x0c, al; reset the flip-flop to a known state.
mov al, 6 ; mask channel 2 so we can reprogram it.
out 0x0a, al
mov al, [dmamode]; 0x46 -> Read from floppy - 0x4A Write to floppy
out 0x0b, al
mov al, 0
out 0x0c, al; reset the flip-flop to a known state.
mov eax, 0xD000
out 0x04, al; set the channel 2 starting address to 0
shr eax, 8
out 0x04, al
shr eax, 8
out 0x81, al
mov al, 0
out 0x0c, al; reset flip-flop
mov al, 0xff;set count (actual size -1)
out 0x5, al
mov al, 0x1;[dmasize] ;(0x1ff = 511 / 0x23ff =9215)
out 0x5, al
mov al, 2
out 0xa, al
popad
ret
 
;***********************************
;* ÇÀÏÈÑÀÒÜ ÁÀÉÒ Â ÏÎÐÒ ÄÀÍÍÛÕ FDC *
;* Ïàðàìåòðû: *
;* AL - âûâîäèìûé áàéò. *
;***********************************
FDCDataOutput:
; pusha
push eax ecx edx
mov AH, AL ;çàïîìíèòü áàéò â AH
; Ñáðîñèòü ïåðåìåííóþ ñîñòîÿíèÿ êîíòðîëëåðà
mov [FDC_Status], FDC_Normal
; Ïðîâåðèòü ãîòîâíîñòü êîíòðîëëåðà ê ïðèåìó äàííûõ
mov DX, 3F4h ;(ïîðò ñîñòîÿíèÿ FDC)
mov ecx, 0x10000 ;óñòàíîâèòü ñ÷åò÷èê òàéì-àóòà
@@TestRS:
in AL, DX ;ïðî÷èòàòü ðåãèñòð RS
and AL, 0C0h ;âûäåëèòü ðàçðÿäû 6 è 7
cmp AL, 80h ;ïðîâåðèòü ðàçðÿäû 6 è 7
je @@OutByteToFDC
loop @@TestRS
; Îøèáêà òàéì-àóòà
mov [FDC_Status], FDC_TimeOut
jmp @@End_5
; Âûâåñòè áàéò â ïîðò äàííûõ
@@OutByteToFDC:
inc DX
mov AL, AH
out DX, AL
@@End_5:
; popa
pop edx ecx eax
ret
 
;******************************************
;* ÏÐÎ×ÈÒÀÒÜ ÁÀÉÒ ÈÇ ÏÎÐÒÀ ÄÀÍÍÛÕ FDC *
;* Ïðîöåäóðà íå èìååò âõîäíûõ ïàðàìåòðîâ. *
;* Âûõîäíûå äàííûå: *
;* AL - ñ÷èòàííûé áàéò. *
;******************************************
FDCDataInput:
push ECX
push DX
; Ñáðîñèòü ïåðåìåííóþ ñîñòîÿíèÿ êîíòðîëëåðà
mov [FDC_Status], FDC_Normal
; Ïðîâåðèòü ãîòîâíîñòü êîíòðîëëåðà ê ïåðåäà÷å äàííûõ
mov DX, 3F4h ;(ïîðò ñîñòîÿíèÿ FDC)
xor CX, CX ;óñòàíîâèòü ñ÷åò÷èê òàéì-àóòà
@@TestRS_1:
in AL, DX ;ïðî÷èòàòü ðåãèñòð RS
and AL, 0C0h ;âûäëèòü ðàçðÿäû 6 è 7
cmp AL, 0C0h ;ïðîâåðèòü ðàçðÿäû 6 è 7
je @@GetByteFromFDC
loop @@TestRS_1
; Îøèáêà òàéì-àóòà
mov [FDC_Status], FDC_TimeOut
jmp @@End_6
; Ââåñòè áàéò èç ïîðòà äàííûõ
@@GetByteFromFDC:
inc DX
in AL, DX
@@End_6:
pop DX
pop ECX
ret
 
;*********************************************
;* ÎÁÐÀÁÎÒ×ÈÊ ÏÐÅÐÛÂÀÍÈß ÎÒ ÊÎÍÒÐÎËËÅÐÀ ÍÃÌÄ *
;*********************************************
FDCInterrupt:
; Óñòàíîâèòü ôëàã ïðåðûâàíè
mov [FDD_IntFlag], 1
ret
 
 
;******************************************
;* ÓÑÒÀÍÎÂÈÒÜ ÍÎÂÛÉ ÎÁÐÀÁÎÒ×ÈÊ ÏÐÅÐÛÂÀÍÈÉ *
;* ÍÃÌÄ *
;******************************************
SetUserInterrupts:
mov [fdc_irq_func], FDCInterrupt
ret
 
;*******************************************
;* ÎÆÈÄÀÍÈÅ ÏÐÅÐÛÂÀÍÈß ÎÒ ÊÎÍÒÐÎËËÅÐÀ ÍÃÌÄ *
;*******************************************
WaitFDCInterrupt:
pusha
; Ñáðîñèòü áàéò ñîñòîÿíèÿ îïåðàöèè
mov [FDC_Status], FDC_Normal
; Ñáðîñèòü ôëàã ïðåðûâàíè
mov [FDD_IntFlag], 0
; Îáíóëèòü ñ÷åò÷èê òèêîâ
mov eax, [timer_ticks]
mov [TickCounter], eax
; Îæèäàòü óñòàíîâêè ôëàãà ïðåðûâàíèÿ ÍÃÌÄ
@@TestRS_2:
cmp [FDD_IntFlag], 0
jnz @@End_7 ;ïðåðûâàíèå ïðîèçîøëî
call change_task
mov eax, [timer_ticks]
sub eax, [TickCounter]
cmp eax, 50 ;25 ;5 ;îæèäàòü 5 òèêîâ
jb @@TestRS_2
; jl @@TestRS_2
; Îøèáêà òàéì-àóòà
mov [FDC_Status], FDC_TimeOut
; mov [flp_status],0
@@End_7:
popa
ret
 
;*********************************
;* ÂÊËÞ×ÈÒÜ ÌÎÒÎÐ ÄÈÑÊÎÂÎÄÀ "A:" *
;*********************************
FDDMotorON:
pusha
; cmp [fdd_motor_status],1
; je fdd_motor_on
mov al, [flp_number]
cmp [fdd_motor_status], al
je fdd_motor_on
; Ïðîèçâåñòè ñáðîñ êîíòðîëëåðà ÍÃÌÄ
mov DX, 3F2h;ïîðò óïðàâëåíèÿ äâèãàòåëÿìè
mov AL, 0
out DX, AL
; Âûáðàòü è âêëþ÷èòü ìîòîð äèñêîâîäà
cmp [flp_number], 1
jne FDDMotorON_B
; call FDDMotorOFF_B
mov AL, 1Ch ; Floppy A
jmp FDDMotorON_1
FDDMotorON_B:
; call FDDMotorOFF_A
mov AL, 2Dh ; Floppy B
FDDMotorON_1:
out DX, AL
; Îáíóëèòü ñ÷åò÷èê òèêîâ
mov eax, [timer_ticks]
mov [TickCounter], eax
; Îæèäàòü 0,5 ñ
@@dT:
call change_task
mov eax, [timer_ticks]
sub eax, [TickCounter]
cmp eax, 50 ;10
jb @@dT
cmp [flp_number], 1
jne fdd_motor_on_B
mov [fdd_motor_status], 1
jmp fdd_motor_on
fdd_motor_on_B:
mov [fdd_motor_status], 2
fdd_motor_on:
call save_timer_fdd_motor
popa
ret
 
;*****************************************
;* ÑÎÕÐÀÍÅÍÈÅ ÓÊÀÇÀÒÅËß ÂÐÅÌÅÍÈ *
;*****************************************
save_timer_fdd_motor:
mov eax, [timer_ticks]
mov [timer_fdd_motor], eax
ret
 
;*****************************************
;* ÏÐÎÂÅÐÊÀ ÇÀÄÅÐÆÊÈ ÂÛÊËÞ×ÅÍÈß ÌÎÒÎÐÀ *
;*****************************************
align 4
check_fdd_motor_status:
cmp [fdd_motor_status], 0
je end_check_fdd_motor_status_1
mov eax, [timer_ticks]
sub eax, [timer_fdd_motor]
cmp eax, 500
jb end_check_fdd_motor_status
call FDDMotorOFF
mov [fdd_motor_status], 0
end_check_fdd_motor_status_1:
mov [flp_status], 0
end_check_fdd_motor_status:
ret
 
;**********************************
;* ÂÛÊËÞ×ÈÒÜ ÌÎÒÎÐ ÄÈÑÊÎÂÎÄÀ *
;**********************************
FDDMotorOFF:
push AX
push DX
cmp [flp_number], 1
jne FDDMotorOFF_1
call FDDMotorOFF_A
jmp FDDMotorOFF_2
FDDMotorOFF_1:
call FDDMotorOFF_B
FDDMotorOFF_2:
pop DX
pop AX
; ñáðîñ ôëàãîâ êåøèðîâàíèÿ â ñâÿçè ñ óñòàðåâàíèåì èíôîðìàöèè
mov [root_read], 0
mov [flp_fat], 0
ret
 
FDDMotorOFF_A:
mov DX, 3F2h;ïîðò óïðàâëåíèÿ äâèãàòåëÿìè
mov AL, 0Ch ; Floppy A
out DX, AL
ret
 
FDDMotorOFF_B:
mov DX, 3F2h;ïîðò óïðàâëåíèÿ äâèãàòåëÿìè
mov AL, 5h ; Floppy B
out DX, AL
ret
 
;*******************************
;* ÐÅÊÀËÈÁÐÎÂÊÀ ÄÈÑÊÎÂÎÄÀ "A:" *
;*******************************
RecalibrateFDD:
pusha
call save_timer_fdd_motor
; Ïîäàòü êîìàíäó "Ðåêàëèáðîâêà"
mov AL, 07h
call FDCDataOutput
mov AL, 00h
call FDCDataOutput
; Îæèäàòü çàâåðøåíèÿ îïåðàöèè
call WaitFDCInterrupt
; cmp [FDC_Status],0
; je no_fdc_status_error
; mov [flp_status],0
;no_fdc_status_error:
call save_timer_fdd_motor
popa
ret
 
;*****************************************************
;* ÏÎÈÑÊ ÄÎÐÎÆÊÈ *
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: *
;* FDD_Track - íîìåð äîðîæêè (0-79); *
;* FDD_Head - íîìåð ãîëîâêè (0-1). *
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status. *
;*****************************************************
SeekTrack:
pusha
call save_timer_fdd_motor
; Ïîäàòü êîìàíäó "Ïîèñê"
mov AL, 0Fh
call FDCDataOutput
; Ïåðåäàòü áàéò íîìåðà ãîëîâêè/íàêîïèòåë
mov AL, [FDD_Head]
shl AL, 2
call FDCDataOutput
; Ïåðåäàòü áàéò íîìåðà äîðîæêè
mov AL, [FDD_Track]
call FDCDataOutput
; Îæèäàòü çàâåðøåíèÿ îïåðàöèè
call WaitFDCInterrupt
cmp [FDC_Status], FDC_Normal
jne @@Exit
; Ñîõðàíèòü ðåçóëüòàò ïîèñêà
mov AL, 08h
call FDCDataOutput
call FDCDataInput
mov [FDC_ST0], AL
call FDCDataInput
mov [FDC_C], AL
; Ïðîâåðèòü ðåçóëüòàò ïîèñêà
; Ïîèñê çàâåðøåí?
test [FDC_ST0], 100000b
je @@Err
; Çàäàííûé òðåê íàéäåí?
mov AL, [FDC_C]
cmp AL, [FDD_Track]
jne @@Err
; Íîìåð ãîëîâêè ñîâïàäàåò ñ çàäàííûì?
mov AL, [FDC_ST0]
and AL, 100b
shr AL, 2
cmp AL, [FDD_Head]
jne @@Err
; Îïåðàöèÿ çàâåðøåíà óñïåøíî
mov [FDC_Status], FDC_Normal
jmp @@Exit
@@Err: ; Òðåê íå íàéäåí
mov [FDC_Status], FDC_TrackNotFound
; mov [flp_status],0
@@Exit:
call save_timer_fdd_motor
popa
ret
 
;*******************************************************
;* ×ÒÅÍÈÅ ÑÅÊÒÎÐÀ ÄÀÍÍÛÕ *
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: *
;* FDD_Track - íîìåð äîðîæêè (0-79); *
;* FDD_Head - íîìåð ãîëîâêè (0-1); *
;* FDD_Sector - íîìåð ñåêòîðà (1-18). *
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status. *
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè ÷òåíèÿ *
;* ñîäåðæèìîå ñåêòîðà áóäåò çàíåñåíî â FDD_DataBuffer. *
;*******************************************************
ReadSector:
pushad
call save_timer_fdd_motor
; Óñòàíîâèòü ñêîðîñòü ïåðåäà÷è 500 Êáàéò/ñ
mov AX, 0
mov DX, 03F7h
out DX, AL
; Èíèöèàëèçèðîâàòü êàíàë ïðÿìîãî äîñòóïà ê ïàìÿòè
mov [dmamode], 0x46
call Init_FDC_DMA
; Ïîäàòü êîìàíäó "×òåíèå äàííûõ"
mov AL, 0E6h ;÷òåíèå â ìóëüòèòðåêîâîì ðåæèìå
call FDCDataOutput
mov AL, [FDD_Head]
shl AL, 2
call FDCDataOutput
mov AL, [FDD_Track]
call FDCDataOutput
mov AL, [FDD_Head]
call FDCDataOutput
mov AL, [FDD_Sector]
call FDCDataOutput
mov AL, 2 ;êîä ðàçìåðà ñåêòîðà (512 áàéò)
call FDCDataOutput
mov AL, 18 ;+1; 3Fh ;÷èñëî ñåêòîðîâ íà äîðîæêå
call FDCDataOutput
mov AL, 1Bh ;çíà÷åíèå GPL
call FDCDataOutput
mov AL, 0FFh;çíà÷åíèå DTL
call FDCDataOutput
; Îæèäàåì ïðåðûâàíèå ïî çàâåðøåíèè îïåðàöèè
call WaitFDCInterrupt
cmp [FDC_Status], FDC_Normal
jne @@Exit_1
; Ñ÷èòûâàåì ñòàòóñ çàâåðøåíèÿ îïåðàöèè
call GetStatusInfo
test [FDC_ST0], 11011000b
jnz @@Err_1
mov [FDC_Status], FDC_Normal
jmp @@Exit_1
@@Err_1:
mov [FDC_Status], FDC_SectorNotFound
; mov [flp_status],0
@@Exit_1:
call save_timer_fdd_motor
popad
ret
 
;*******************************************************
;* ×ÒÅÍÈÅ ÑÅÊÒÎÐÀ (Ñ ÏÎÂÒÎÐÅÍÈÅÌ ÎÏÅÐÀÖÈÈ ÏÐÈ ÑÁÎÅ) *
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: *
;* FDD_Track - íîìåð äîðîæêè (0-79); *
;* FDD_Head - íîìåð ãîëîâêè (0-1); *
;* FDD_Sector - íîìåð ñåêòîðà (1-18). *
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status. *
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè ÷òåíèÿ *
;* ñîäåðæèìîå ñåêòîðà áóäåò çàíåñåíî â FDD_DataBuffer. *
;*******************************************************
ReadSectWithRetr:
pusha
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ðåêàëèáðîâêè
mov [RecalRepCounter], 0
@@TryAgain:
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ÷òåíè
mov [ReadRepCounter], 0
@@ReadSector_1:
call ReadSector
cmp [FDC_Status], 0
je @@Exit_2
cmp [FDC_Status], 1
je @@Err_3
; Òðîåêðàòíîå ïîâòîðåíèå ÷òåíè
inc [ReadRepCounter]
cmp [ReadRepCounter], 3
jb @@ReadSector_1
; Òðîåêðàòíîå ïîâòîðåíèå ðåêàëèáðîâêè
call RecalibrateFDD
call SeekTrack
inc [RecalRepCounter]
cmp [RecalRepCounter], 3
jb @@TryAgain
; mov [flp_status],0
@@Exit_2:
popa
ret
@@Err_3:
mov [flp_status], 0
popa
ret
 
;*******************************************************
;* ÇÀÏÈÑÜ ÑÅÊÒÎÐÀ ÄÀÍÍÛÕ *
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: *
;* FDD_Track - íîìåð äîðîæêè (0-79); *
;* FDD_Head - íîìåð ãîëîâêè (0-1); *
;* FDD_Sector - íîìåð ñåêòîðà (1-18). *
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status. *
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè çàïèñè *
;* ñîäåðæèìîå FDD_DataBuffer áóäåò çàíåñåíî â ñåêòîð. *
;*******************************************************
WriteSector:
pushad
call save_timer_fdd_motor
; Óñòàíîâèòü ñêîðîñòü ïåðåäà÷è 500 Êáàéò/ñ
mov AX, 0
mov DX, 03F7h
out DX, AL
; Èíèöèàëèçèðîâàòü êàíàë ïðÿìîãî äîñòóïà ê ïàìÿòè
mov [dmamode], 0x4A
call Init_FDC_DMA
; Ïîäàòü êîìàíäó "Çàïèñü äàííûõ"
mov AL, 0xC5 ;0x45 ;çàïèñü â ìóëüòèòðåêîâîì ðåæèìå
call FDCDataOutput
mov AL, [FDD_Head]
shl AL, 2
call FDCDataOutput
mov AL, [FDD_Track]
call FDCDataOutput
mov AL, [FDD_Head]
call FDCDataOutput
mov AL, [FDD_Sector]
call FDCDataOutput
mov AL, 2 ;êîä ðàçìåðà ñåêòîðà (512 áàéò)
call FDCDataOutput
mov AL, 18; 3Fh ;÷èñëî ñåêòîðîâ íà äîðîæêå
call FDCDataOutput
mov AL, 1Bh ;çíà÷åíèå GPL
call FDCDataOutput
mov AL, 0FFh;çíà÷åíèå DTL
call FDCDataOutput
; Îæèäàåì ïðåðûâàíèå ïî çàâåðøåíèè îïåðàöèè
call WaitFDCInterrupt
cmp [FDC_Status], FDC_Normal
jne @@Exit_3
; Ñ÷èòûâàåì ñòàòóñ çàâåðøåíèÿ îïåðàöèè
call GetStatusInfo
test [FDC_ST0], 11000000b ;11011000b
jnz @@Err_2
mov [FDC_Status], FDC_Normal
jmp @@Exit_3
@@Err_2:
mov [FDC_Status], FDC_SectorNotFound
@@Exit_3:
call save_timer_fdd_motor
popad
ret
 
;*******************************************************
;* ÇÀÏÈÑÜ ÑÅÊÒÎÐÀ (Ñ ÏÎÂÒÎÐÅÍÈÅÌ ÎÏÅÐÀÖÈÈ ÏÐÈ ÑÁÎÅ) *
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: *
;* FDD_Track - íîìåð äîðîæêè (0-79); *
;* FDD_Head - íîìåð ãîëîâêè (0-1); *
;* FDD_Sector - íîìåð ñåêòîðà (1-18). *
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status. *
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè çàïèñè *
;* ñîäåðæèìîå FDD_DataBuffer áóäåò çàíåñåíî â ñåêòîð. *
;*******************************************************
WriteSectWithRetr:
pusha
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ðåêàëèáðîâêè
mov [RecalRepCounter], 0
@@TryAgain_1:
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ÷òåíè
mov [ReadRepCounter], 0
@@WriteSector_1:
call WriteSector
cmp [FDC_Status], 0
je @@Exit_4
cmp [FDC_Status], 1
je @@Err_4
; Òðîåêðàòíîå ïîâòîðåíèå ÷òåíè
inc [ReadRepCounter]
cmp [ReadRepCounter], 3
jb @@WriteSector_1
; Òðîåêðàòíîå ïîâòîðåíèå ðåêàëèáðîâêè
call RecalibrateFDD
call SeekTrack
inc [RecalRepCounter]
cmp [RecalRepCounter], 3
jb @@TryAgain_1
@@Exit_4:
popa
ret
@@Err_4:
mov [flp_status], 0
popa
ret
 
;*********************************************
;* ÏÎËÓ×ÈÒÜ ÈÍÔÎÐÌÀÖÈÞ Î ÐÅÇÓËÜÒÀÒÅ ÎÏÅÐÀÖÈÈ *
;*********************************************
GetStatusInfo:
push AX
call FDCDataInput
mov [FDC_ST0], AL
call FDCDataInput
mov [FDC_ST1], AL
call FDCDataInput
mov [FDC_ST2], AL
call FDCDataInput
mov [FDC_C], AL
call FDCDataInput
mov [FDC_H], AL
call FDCDataInput
mov [FDC_R], AL
call FDCDataInput
mov [FDC_N], AL
pop AX
ret
 
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/blkdev/rd.inc
0,0 → 1,2273
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; RAMDISK functions ;;
;; (C) 2004 Ville Turjanmaa, License: GPL ;;
;; Addings by M.Lisovin ;;
;; LFN support by diamond ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
; calculate fat chain
 
calculatefatchain:
 
pushad
 
mov esi, RAMDISK+512
mov edi, RAMDISK_FAT
 
fcnew:
mov eax, dword [esi]
mov ebx, dword [esi+4]
mov ecx, dword [esi+8]
mov edx, ecx
shr edx, 4;8 ok
shr dx, 4;7 ok
xor ch, ch
shld ecx, ebx, 20;6 ok
shr cx, 4;5 ok
shld ebx, eax, 12
and ebx, 0x0fffffff;4 ok
shr bx, 4;3 ok
shl eax, 4
and eax, 0x0fffffff;2 ok
shr ax, 4;1 ok
mov dword [edi], eax
mov dword [edi+4], ebx
mov dword [edi+8], ecx
mov dword [edi+12], edx
add edi, 16
add esi, 12
 
cmp edi, RAMDISK_FAT+2856*2;2849 clusters
jnz fcnew
 
popad
ret
 
 
restorefatchain: ; restore fat chain
 
pushad
 
mov esi, RAMDISK_FAT
mov edi, RAMDISK+512
 
fcnew2:
mov eax, dword [esi]
mov ebx, dword [esi+4]
shl ax, 4
shl eax, 4
shl bx, 4
shr ebx, 4
shrd eax, ebx, 8
shr ebx, 8
mov dword [edi], eax
mov word [edi+4], bx
add edi, 6
add esi, 8
 
cmp edi, RAMDISK+512+4278;4274 bytes - all used FAT
jb fcnew2
 
mov esi, RAMDISK+512 ; duplicate fat chain
mov edi, RAMDISK+512+0x1200
mov ecx, 1069;4274/4
cld
rep movsd
 
popad
ret
 
 
ramdisk_free_space:
;---------------------------------------------
;
; returns free space in edi
; rewr.by Mihasik
;---------------------------------------------
 
push eax ebx ecx
 
mov edi, RAMDISK_FAT;start of FAT
xor ax, ax;Free cluster=0x0000 in FAT
xor ebx, ebx;counter
mov ecx, 2849;2849 clusters
cld
rdfs1:
repne scasw
jnz rdfs2 ;if last cluster not 0
inc ebx
test ecx, ecx
jnz rdfs1
rdfs2:
shl ebx, 9;free clusters*512
mov edi, ebx
 
pop ecx ebx eax
ret
 
 
expand_filename:
;---------------------------------------------
;
; exapand filename with '.' to 11 character
; eax - pointer to filename
;---------------------------------------------
 
push esi edi ebx
 
mov edi, esp ; check for '.' in the name
add edi, 12+8
 
mov esi, eax
 
mov eax, edi
mov [eax+0], dword ' '
mov [eax+4], dword ' '
mov [eax+8], dword ' '
 
flr1:
 
cmp [esi], byte '.'
jne flr2
mov edi, eax
add edi, 7
jmp flr3
 
flr2:
 
mov bl, [esi]
mov [edi], bl
 
flr3:
 
inc esi
inc edi
 
mov ebx, eax
add ebx, 11
 
cmp edi, ebx
jbe flr1
 
pop ebx edi esi
ret
 
fileread:
;----------------------------------------------------------------
;
; fileread - sys floppy
;
; eax points to filename 11 chars
; ebx first wanted block ; 1+ ; if 0 then set to 1
; ecx number of blocks to read ; 1+ ; if 0 then set to 1
; edx mem location to return data
; esi length of filename 12*X 0=root
;
; ret ebx = size or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
test ebx, ebx;if ebx=0 - set to 1
jnz frfl5
inc ebx
frfl5:
test ecx, ecx;if ecx=0 - set to 1
jnz frfl6
inc ecx
frfl6:
test esi, esi ; return ramdisk root
jnz fr_noroot ;if not root
cmp ebx, 14 ;14 clusters=root dir
ja oorr
cmp ecx, 14
ja oorr
jmp fr_do
oorr:
mov eax, 5 ;out of root range (fnf)
xor ebx, ebx
dec ebx ;0xffffffff
ret
 
fr_do: ;reading rootdir
mov edi, edx
dec ebx
push edx
mov edx, ecx
add edx, ebx
cmp edx, 15 ;ebx+ecx=14+1
pushf
jbe fr_do1
sub edx, 14
sub ecx, edx
fr_do1:
shl ebx, 9
mov esi, RAMDISK+512*19
add esi, ebx
shl ecx, 7
cld
rep movsd
popf
pop edx
jae fr_do2
xor eax, eax; ok read
xor ebx, ebx
ret
fr_do2: ;if last cluster
mov eax, 6;end of file
xor ebx, ebx
ret
 
fr_noroot:
 
sub esp, 32
call expand_filename
 
dec ebx
 
push eax
 
push eax ebx ecx edx esi edi
call rd_findfile
je fifound
add esp, 32+28 ;if file not found
ret
 
fifound:
 
mov ebx, [edi-11+28] ;file size
mov [esp+20], ebx
mov [esp+24], ebx
add edi, 0xf
movzx eax, word [edi]
mov edi, eax ;edi=cluster
 
frnew:
 
add eax, 31 ;bootsector+2*fat+filenames
shl eax, 9 ;*512
add eax, RAMDISK ;image base
mov ebx, [esp+8]
mov ecx, 512 ;[esp+4]
 
cmp [esp+16], dword 0 ; wanted cluster ?
jne frfl7
call memmove
add [esp+8], dword 512
dec dword [esp+12] ; last wanted cluster ?
je frnoread
jmp frfl8
frfl7:
dec dword [esp+16]
frfl8:
movzx eax, word [edi*2+RAMDISK_FAT] ; find next cluster from FAT
mov edi, eax
cmp edi, 4095 ;eof - cluster
jz frnoread2
 
cmp [esp+24], dword 512 ;eof - size
jb frnoread
sub [esp+24], dword 512
 
jmp frnew
 
frnoread2:
 
cmp [esp+16], dword 0 ; eof without read ?
je frnoread
 
pop edi esi edx ecx
add esp, 4
pop ebx ; ebx <- eax : size of file
add esp, 36
mov eax, 6 ; end of file
ret
 
frnoread:
 
pop edi esi edx ecx
add esp, 4
pop ebx ; ebx <- eax : size of file
add esp, 36
xor eax, eax;read ok
ret
 
 
 
rd_findfile:
;by Mihasik
;IN: eax - pointer to filename OUT: filestring+11 in edi or notZero in flags and fnf in eax,ebx
 
mov edi, RAMDISK+512*18+512;Point at directory
cld
rd_newsearch:
mov esi, eax
mov ecx, 11
rep cmpsb
je rd_ff
add cl, 21
add edi, ecx
cmp edi, RAMDISK+512*33
jb rd_newsearch
mov eax, 5 ;if file not found - eax=5
xor ebx, ebx
dec ebx ;ebx=0xffffffff and zf=0
rd_ff:
ret
 
; \begin{diamond}
 
uni2ansi_str:
; convert UNICODE zero-terminated string to ASCII-string (codepage 866)
; in: esi->source, edi->buffer (may be esi=edi)
; destroys: eax,esi,edi
lodsw
test ax, ax
jz .done
cmp ax, 0x80
jb .ascii
cmp ax, 0x401
jz .yo1
cmp ax, 0x451
jz .yo2
cmp ax, 0x410
jb .unk
cmp ax, 0x440
jb .rus1
cmp ax, 0x450
jb .rus2
.unk:
mov al, '_'
jmp .doit
.yo1:
mov al, 'ð'
jmp .doit
.yo2:
mov al, 'ñ'
jmp .doit
.rus1:
; 0x410-0x43F -> 0x80-0xAF
add al, 0x70
jmp .doit
.rus2:
; 0x440-0x44F -> 0xE0-0xEF
add al, 0xA0
.ascii:
.doit:
stosb
jmp uni2ansi_str
.done:
mov byte [edi], 0
ret
 
ansi2uni_char:
; convert ANSI character in al to UNICODE character in ax, using cp866 encoding
mov ah, 0
; 0x00-0x7F - trivial map
cmp al, 0x80
jb .ret
; 0x80-0xAF -> 0x410-0x43F
cmp al, 0xB0
jae @f
add ax, 0x410-0x80
.ret:
ret
@@:
; 0xE0-0xEF -> 0x440-0x44F
cmp al, 0xE0
jb .unk
cmp al, 0xF0
jae @f
add ax, 0x440-0xE0
ret
; 0xF0 -> 0x401
; 0xF1 -> 0x451
@@:
cmp al, 'ð'
jz .yo1
cmp al, 'ñ'
jz .yo2
.unk:
mov al, '_' ; ah=0
ret
.yo1:
mov ax, 0x401
ret
.yo2:
mov ax, 0x451
ret
 
char_toupper:
; convert character to uppercase, using cp866 encoding
; in: al=symbol
; out: al=converted symbol
cmp al, 'a'
jb .ret
cmp al, 'z'
jbe .az
cmp al, 'ñ'
jz .yo1
cmp al, ' '
jb .ret
cmp al, 'à'
jb .rus1
cmp al, 'ï'
ja .ret
; 0xE0-0xEF -> 0x90-0x9F
sub al, 'à'-''
.ret:
ret
.rus1:
; 0xA0-0xAF -> 0x80-0x8F
.az:
and al, not 0x20
ret
.yo1:
; 0xF1 -> 0xF0
dec ax
ret
 
fat_get_name:
; in: edi->FAT entry
; out: CF=1 - no valid entry
; else CF=0 and ebp->ASCIIZ-name
; (maximum length of filename is 255 (wide) symbols without trailing 0,
; but implementation requires buffer 261 words)
; destroys eax
cmp byte [edi], 0
jz .no
cmp byte [edi], 0xE5
jnz @f
.no:
stc
ret
@@:
cmp byte [edi+11], 0xF
jz .longname
test byte [edi+11], 8
jnz .no
push ecx
push edi ebp
test byte [ebp-4], 1
jnz .unicode_short
 
mov eax, [edi]
mov ecx, [edi+4]
mov [ebp], eax
mov [ebp+4], ecx
 
mov ecx, 8
@@:
cmp byte [ebp+ecx-1], ' '
loope @b
 
mov eax, [edi+8]
cmp al, ' '
je .done
shl eax, 8
mov al, '.'
 
lea ebp, [ebp+ecx+1]
mov [ebp], eax
mov ecx, 3
@@:
rol eax, 8
cmp al, ' '
jne .done
loop @b
dec ebp
.done:
and byte [ebp+ecx+1], 0 ; CF=0
pop ebp edi ecx
ret
.unicode_short:
mov ecx, 8
push ecx
@@:
mov al, [edi]
inc edi
call ansi2uni_char
mov [ebp], ax
inc ebp
inc ebp
loop @b
pop ecx
@@:
cmp word [ebp-2], ' '
jnz @f
dec ebp
dec ebp
loop @b
@@:
mov word [ebp], '.'
inc ebp
inc ebp
mov ecx, 3
push ecx
@@:
mov al, [edi]
inc edi
call ansi2uni_char
mov [ebp], ax
inc ebp
inc ebp
loop @b
pop ecx
@@:
cmp word [ebp-2], ' '
jnz @f
dec ebp
dec ebp
loop @b
dec ebp
dec ebp
@@:
and word [ebp], 0 ; CF=0
pop ebp edi ecx
ret
.longname:
; LFN
mov al, byte [edi]
and eax, 0x3F
dec eax
cmp al, 20
jae .no ; ignore invalid entries
mov word [ebp+260*2], 0 ; force null-terminating for orphans
imul eax, 13*2
add ebp, eax
test byte [edi], 0x40
jz @f
mov word [ebp+13*2], 0
@@:
push eax
; now copy name from edi to ebp ...
mov eax, [edi+1]
mov [ebp], eax ; symbols 1,2
mov eax, [edi+5]
mov [ebp+4], eax ; 3,4
mov eax, [edi+9]
mov [ebp+8], ax ; 5
mov eax, [edi+14]
mov [ebp+10], eax ; 6,7
mov eax, [edi+18]
mov [ebp+14], eax ; 8,9
mov eax, [edi+22]
mov [ebp+18], eax ; 10,11
mov eax, [edi+28]
mov [ebp+22], eax ; 12,13
; ... done
pop eax
sub ebp, eax
test eax, eax
jz @f
; if this is not first entry, more processing required
stc
ret
@@:
; if this is first entry:
test byte [ebp-4], 1
jnz .ret
; buffer at ebp contains UNICODE name, convert it to ANSI
push esi edi
mov esi, ebp
mov edi, ebp
call uni2ansi_str
pop edi esi
.ret:
clc
ret
 
fat_compare_name:
; compares ASCIIZ-names, case-insensitive (cp866 encoding)
; in: esi->name, ebp->name
; out: if names match: ZF=1 and esi->next component of name
; else: ZF=0, esi is not changed
; destroys eax
push ebp esi
.loop:
mov al, [ebp]
inc ebp
call char_toupper
push eax
lodsb
call char_toupper
cmp al, [esp]
jnz .done
pop eax
test al, al
jnz .loop
dec esi
pop eax
pop ebp
xor eax, eax ; set ZF flag
ret
.done:
cmp al, '/'
jnz @f
cmp byte [esp], 0
jnz @f
mov [esp+4], esi
@@:
pop eax
pop esi ebp
ret
 
fat_time_to_bdfe:
; in: eax=FAT time
; out: eax=BDFE time
push ecx edx
mov ecx, eax
mov edx, eax
shr eax, 11
shl eax, 16 ; hours
and edx, 0x1F
add edx, edx
mov al, dl ; seconds
shr ecx, 5
and ecx, 0x3F
mov ah, cl ; minutes
pop edx ecx
ret
 
fat_date_to_bdfe:
push ecx edx
mov ecx, eax
mov edx, eax
shr eax, 9
add ax, 1980
shl eax, 16 ; year
and edx, 0x1F
mov al, dl ; day
shr ecx, 5
and ecx, 0xF
mov ah, cl ; month
pop edx ecx
ret
 
bdfe_to_fat_time:
push edx
mov edx, eax
shr eax, 16
and dh, 0x3F
shl eax, 6
or al, dh
shr dl, 1
and dl, 0x1F
shl eax, 5
or al, dl
pop edx
ret
 
bdfe_to_fat_date:
push edx
mov edx, eax
shr eax, 16
sub ax, 1980
and dh, 0xF
shl eax, 4
or al, dh
and dl, 0x1F
shl eax, 5
or al, dl
pop edx
ret
 
fat_entry_to_bdfe:
; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
; destroys eax
mov eax, [ebp-4]
mov [esi+4], eax ; ASCII/UNICODE name
fat_entry_to_bdfe2:
movzx eax, byte [edi+11]
mov [esi], eax ; attributes
movzx eax, word [edi+14]
call fat_time_to_bdfe
mov [esi+8], eax ; creation time
movzx eax, word [edi+16]
call fat_date_to_bdfe
mov [esi+12], eax ; creation date
and dword [esi+16], 0 ; last access time is not supported on FAT
movzx eax, word [edi+18]
call fat_date_to_bdfe
mov [esi+20], eax ; last access date
movzx eax, word [edi+22]
call fat_time_to_bdfe
mov [esi+24], eax ; last write time
movzx eax, word [edi+24]
call fat_date_to_bdfe
mov [esi+28], eax ; last write date
mov eax, [edi+28]
mov [esi+32], eax ; file size (low dword)
xor eax, eax
mov [esi+36], eax ; file size (high dword)
test ebp, ebp
jz .ret
push ecx edi
lea edi, [esi+40]
mov esi, ebp
test byte [esi-4], 1
jz .ansi
mov ecx, 260/2
rep movsd
mov [edi-2], ax
@@:
mov esi, edi
pop edi ecx
.ret:
ret
.ansi:
mov ecx, 264/4
rep movsd
mov [edi-1], al
jmp @b
 
bdfe_to_fat_entry:
; convert BDFE at edx to FAT entry at edi
; destroys eax
; attributes byte
test byte [edi+11], 8 ; volume label?
jnz @f
mov al, [edx]
and al, 0x27
and byte [edi+11], 0x10
or byte [edi+11], al
@@:
mov eax, [edx+8]
call bdfe_to_fat_time
mov [edi+14], ax ; creation time
mov eax, [edx+12]
call bdfe_to_fat_date
mov [edi+16], ax ; creation date
mov eax, [edx+20]
call bdfe_to_fat_date
mov [edi+18], ax ; last access date
mov eax, [edx+24]
call bdfe_to_fat_time
mov [edi+22], ax ; last write time
mov eax, [edx+28]
call bdfe_to_fat_date
mov [edi+24], ax ; last write date
ret
 
ramdisk_root_first:
mov edi, RAMDISK+512*19
clc
ret
ramdisk_root_next:
add edi, 0x20
cmp edi, RAMDISK+512*33
cmc
ret
 
ramdisk_root_extend_dir:
stc
ret
 
uglobal
; this is for delete support
rd_prev_sector dd ?
rd_prev_prev_sector dd ?
endg
 
ramdisk_notroot_next:
add edi, 0x20
test edi, 0x1FF
jz ramdisk_notroot_next_sector
ret ; CF=0
ramdisk_notroot_next_sector:
push ecx
mov ecx, [eax]
push [rd_prev_sector]
pop [rd_prev_prev_sector]
mov [rd_prev_sector], ecx
mov ecx, [ecx*2+RAMDISK_FAT]
and ecx, 0xFFF
cmp ecx, 2849
jae ramdisk_notroot_first.err2
mov [eax], ecx
pop ecx
ramdisk_notroot_first:
mov eax, [eax]
cmp eax, 2
jb .err
cmp eax, 2849
jae .err
shl eax, 9
lea edi, [eax+(31 shl 9)+RAMDISK]
clc
ret
.err2:
pop ecx
.err:
stc
ret
ramdisk_notroot_next_write:
test edi, 0x1FF
jz ramdisk_notroot_next_sector
ramdisk_root_next_write:
ret
 
ramdisk_notroot_extend_dir:
pusha
xor eax, eax
mov edi, RAMDISK_FAT
mov ecx, 2849
repnz scasw
jnz .notfound
mov word [edi-2], 0xFFF
sub edi, RAMDISK_FAT
shr edi, 1
dec edi
mov eax, [esp+28]
mov ecx, [eax]
mov [RAMDISK_FAT+ecx*2], di
mov [eax], edi
shl edi, 9
add edi, (31 shl 9)+RAMDISK
mov [esp], edi
xor eax, eax
mov ecx, 128
rep stosd
popa
clc
ret
.notfound:
popa
stc
ret
 
rd_find_lfn:
; in: esi+ebp -> name
; out: CF=1 - file not found
; else CF=0 and edi->direntry
push esi edi
push 0
push ramdisk_root_first
push ramdisk_root_next
.loop:
call fat_find_lfn
jc .notfound
cmp byte [esi], 0
jz .found
.continue:
test byte [edi+11], 10h
jz .notfound
movzx eax, word [edi+26]
mov [esp+8], eax
mov dword [esp+4], ramdisk_notroot_first
mov dword [esp], ramdisk_notroot_next
test eax, eax
jnz .loop
mov dword [esp+4], ramdisk_root_first
mov dword [esp], ramdisk_notroot_next
jmp .loop
.notfound:
add esp, 12
pop edi esi
stc
ret
.found:
test ebp, ebp
jz @f
mov esi, ebp
xor ebp, ebp
jmp .continue
@@:
mov eax, [esp+8]
add esp, 16 ; CF=0
pop esi
ret
 
;----------------------------------------------------------------
;
; fs_RamdiskRead - LFN variant for reading sys floppy
;
; esi points to filename
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to read, 0+
; edx mem location to return data
;
; ret ebx = bytes read or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
fs_RamdiskRead:
cmp byte [esi], 0
jnz @f
or ebx, -1
mov eax, 10 ; access denied
ret
@@:
push edi
call rd_find_lfn
jnc .found
pop edi
or ebx, -1
mov eax, 5 ; file not found
ret
.found:
test ebx, ebx
jz .l1
cmp dword [ebx+4], 0
jz @f
xor ebx, ebx
.reteof:
mov eax, 6 ; EOF
pop edi
ret
@@:
mov ebx, [ebx]
.l1:
push ecx edx
push 0
mov eax, [edi+28]
sub eax, ebx
jb .eof
cmp eax, ecx
jae @f
mov ecx, eax
mov byte [esp], 6 ; EOF
@@:
movzx edi, word [edi+26] ; cluster
.new:
jecxz .done
test edi, edi
jz .eof
cmp edi, 0xFF8
jae .eof
lea eax, [edi+31] ; bootsector+2*fat+filenames
shl eax, 9 ; *512
add eax, RAMDISK ; image base
; now eax points to data of cluster
sub ebx, 512
jae .skip
lea eax, [eax+ebx+512]
neg ebx
push ecx
cmp ecx, ebx
jbe @f
mov ecx, ebx
@@:
mov ebx, edx
call memmove
add edx, ecx
sub [esp], ecx
pop ecx
xor ebx, ebx
.skip:
movzx edi, word [edi*2+RAMDISK_FAT] ; find next cluster from FAT
jmp .new
.eof:
mov ebx, edx
pop eax edx ecx
sub ebx, edx
jmp .reteof
.done:
mov ebx, edx
pop eax edx ecx edi
sub ebx, edx
ret
 
;----------------------------------------------------------------
;
; fs_RamdiskReadFolder - LFN variant for reading sys floppy folder
;
; esi points to filename; only root is folder on ramdisk
; ebx pointer to structure 32-bit number = first wanted block
; & flags (bitfields)
; flags: bit 0: 0=ANSI names, 1=UNICODE names
; ecx number of blocks to read, 0+
; edx mem location to return data
;
; ret ebx = size or 0xffffffff file not found
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
fs_RamdiskReadFolder:
push edi
cmp byte [esi], 0
jz .root
call rd_find_lfn
jnc .found
pop edi
or ebx, -1
mov eax, ERROR_FILE_NOT_FOUND
ret
.found:
test byte [edi+11], 0x10
jnz .found_dir
pop edi
or ebx, -1
mov eax, ERROR_ACCESS_DENIED
ret
.found_dir:
movzx eax, word [edi+26]
add eax, 31
push 0
jmp .doit
.root:
mov eax, 19
push 14
.doit:
push esi ecx ebp
sub esp, 262*2 ; reserve space for LFN
mov ebp, esp
push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE names
mov ebx, [ebx]
; init header
push eax ecx
mov edi, edx
mov ecx, 32/4
xor eax, eax
rep stosd
mov byte [edx], 1 ; version
pop ecx eax
mov esi, edi ; esi points to block of data of folder entry (BDFE)
.main_loop:
mov edi, eax
shl edi, 9
add edi, RAMDISK
push eax
.l1:
call fat_get_name
jc .l2
cmp byte [edi+11], 0xF
jnz .do_bdfe
add edi, 0x20
test edi, 0x1FF
jnz .do_bdfe
pop eax
inc eax
dec byte [esp+262*2+16]
jz .done
jns @f
; read next sector from FAT
mov eax, [(eax-31-1)*2+RAMDISK_FAT]
and eax, 0xFFF
cmp eax, 0xFF8
jae .done
add eax, 31
mov byte [esp+262*2+16], 0
@@:
mov edi, eax
shl edi, 9
add edi, RAMDISK
push eax
.do_bdfe:
inc dword [edx+8] ; new file found
dec ebx
jns .l2
dec ecx
js .l2
inc dword [edx+4] ; new file block copied
call fat_entry_to_bdfe
.l2:
add edi, 0x20
test edi, 0x1FF
jnz .l1
pop eax
inc eax
dec byte [esp+262*2+16]
jz .done
jns @f
; read next sector from FAT
mov eax, [(eax-31-1)*2+RAMDISK_FAT]
and eax, 0xFFF
cmp eax, 0xFF8
jae .done
add eax, 31
mov byte [esp+262*2+16], 0
@@:
jmp .main_loop
.done:
add esp, 262*2+4
pop ebp
mov ebx, [edx+4]
xor eax, eax
dec ecx
js @f
mov al, ERROR_END_OF_FILE
@@:
pop ecx esi edi edi
ret
 
iglobal
label fat_legal_chars byte
; 0 = not allowed
; 1 = allowed only in long names
; 3 = allowed
times 32 db 0
; ! " # $ % & ' ( ) * + , - . /
db 1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0
; 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
db 3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0
; @ A B C D E F G H I J K L M N O
db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
; P Q R S T U V W X Y Z [ \ ] ^ _
db 3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3
; ` a b c d e f g h i j k l m n o
db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
; p q r s t u v w x y z { | } ~
db 3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0
endg
 
fat_name_is_legal:
; in: esi->(long) name
; out: CF set <=> legal
; destroys eax
push esi
xor eax, eax
@@:
lodsb
test al, al
jz .done
cmp al, 80h
jae .big
test [fat_legal_chars+eax], 1
jnz @b
.err:
pop esi
clc
ret
.big:
; 0x80-0xAF, 0xE0-0xEF
cmp al, 0xB0
jb @b
cmp al, 0xE0
jb .err
cmp al, 0xF0
jb @b
jmp .err
.done:
sub esi, [esp]
cmp esi, 257
pop esi
ret
 
fat_next_short_name:
; in: edi->8+3 name
; out: name corrected
; CF=1 <=> error
pushad
mov ecx, 8
mov al, '~'
std
push edi
add edi, 7
repnz scasb
pop edi
cld
jz .tilde
; tilde is not found, insert "~1" at end
add edi, 6
cmp word [edi], ' '
jnz .insert_tilde
@@:
dec edi
cmp byte [edi], ' '
jz @b
inc edi
.insert_tilde:
mov word [edi], '~1'
popad
clc
ret
.tilde:
push edi
add edi, 7
xor ecx, ecx
@@:
; after tilde may be only digits and trailing spaces
cmp byte [edi], '~'
jz .break
cmp byte [edi], ' '
jz .space
cmp byte [edi], '9'
jnz .found
dec edi
jmp @b
.space:
dec edi
inc ecx
jmp @b
.found:
inc byte [edi]
add dword [esp], 8
jmp .zerorest
.break:
jecxz .noplace
inc edi
mov al, '1'
@@:
xchg al, [edi]
inc edi
cmp al, ' '
mov al, '0'
jnz @b
.succ:
pop edi
popad
clc
ret
.noplace:
dec edi
cmp edi, [esp]
jz .err
add dword [esp], 8
mov word [edi], '~1'
inc edi
inc edi
@@:
mov byte [edi], '0'
.zerorest:
inc edi
cmp edi, [esp]
jb @b
pop edi
popad
;clc ; automatically
ret
.err:
pop edi
popad
stc
ret
 
fat_gen_short_name:
; in: esi->long name
; edi->buffer (8+3=11 chars)
; out: buffer filled
pushad
mov eax, ' '
push edi
stosd
stosd
stosd
pop edi
xor eax, eax
push 8
pop ebx
lea ecx, [edi+8]
.loop:
lodsb
test al, al
jz .done
call char_toupper
cmp al, ' '
jz .space
cmp al, 80h
ja .big
test [fat_legal_chars+eax], 2
jnz .symbol
.inv_symbol:
mov al, '_'
or bh, 1
.symbol:
cmp al, '.'
jz .dot
.normal_symbol:
dec bl
jns .store
mov bl, 0
.space:
or bh, 1
jmp .loop
.store:
stosb
jmp .loop
.big:
cmp al, 0xB0
jb .normal_symbol
cmp al, 0xE0
jb .inv_symbol
cmp al, 0xF0
jb .normal_symbol
jmp .inv_symbol
.dot:
test bh, 2
jz .firstdot
pop ebx
add ebx, edi
sub ebx, ecx
push ebx
cmp ebx, ecx
jb @f
pop ebx
push ecx
@@:
cmp edi, ecx
jbe .skip
@@:
dec edi
mov al, [edi]
dec ebx
mov [ebx], al
mov byte [edi], ' '
cmp edi, ecx
ja @b
.skip:
mov bh, 3
jmp @f
.firstdot:
cmp bl, 8
jz .space
push edi
or bh, 2
@@:
mov edi, ecx
mov bl, 3
jmp .loop
.done:
test bh, 2
jz @f
pop edi
@@:
lea edi, [ecx-8]
test bh, 1
jz @f
call fat_next_short_name
@@:
popad
ret
 
;----------------------------------------------------------------
;
; fs_RamdiskRewrite - LFN variant for writing ramdisk
; fs_RamdiskCreateFolder - create folder on ramdisk
;
; esi points to file/folder name
; ebx ignored (reserved)
; ecx number of bytes to write, 0+ (ignored for folders)
; edx mem location to data (ignored for folders)
;
; ret ebx = number of written bytes
; eax = 0 ok read or other = errormsg
;
;--------------------------------------------------------------
@@:
mov eax, ERROR_ACCESS_DENIED
xor ebx, ebx
ret
 
fs_RamdiskCreateFolder:
mov al, 1 ; create folder
jmp fs_RamdiskRewrite.common
 
fs_RamdiskRewrite:
xor eax, eax ; create file
.common:
cmp byte [esi], 0
jz @b
pushad
xor edi, edi
push esi
test ebp, ebp
jz @f
mov esi, ebp
@@:
lodsb
test al, al
jz @f
cmp al, '/'
jnz @b
lea edi, [esi-1]
jmp @b
@@:
pop esi
test edi, edi
jnz .noroot
test ebp, ebp
jnz .hasebp
push ramdisk_root_extend_dir
push ramdisk_root_next_write
push edi
push ramdisk_root_first
push ramdisk_root_next
jmp .common1
.hasebp:
mov eax, ERROR_ACCESS_DENIED
cmp byte [ebp], 0
jz .ret1
push ebp
xor ebp, ebp
call rd_find_lfn
pop esi
jc .notfound0
jmp .common0
.noroot:
mov eax, ERROR_ACCESS_DENIED
cmp byte [edi+1], 0
jz .ret1
; check existence
mov byte [edi], 0
push edi
call rd_find_lfn
pop esi
mov byte [esi], '/'
jnc @f
.notfound0:
mov eax, ERROR_FILE_NOT_FOUND
.ret1:
mov [esp+28], eax
popad
xor ebx, ebx
ret
@@:
inc esi
.common0:
test byte [edi+11], 0x10 ; must be directory
mov eax, ERROR_ACCESS_DENIED
jz .ret1
movzx ebp, word [edi+26] ; ebp=cluster
mov eax, ERROR_FAT_TABLE
cmp ebp, 2
jb .ret1
cmp ebp, 2849
jae .ret1
push ramdisk_notroot_extend_dir
push ramdisk_notroot_next_write
push ebp
push ramdisk_notroot_first
push ramdisk_notroot_next
.common1:
call fat_find_lfn
jc .notfound
; found
test byte [edi+11], 10h
jz .exists_file
; found directory; if we are creating directory, return OK,
; if we are creating file, say "access denied"
add esp, 20
popad
test al, al
mov eax, ERROR_ACCESS_DENIED
jz @f
mov al, 0
@@:
xor ebx, ebx
ret
.exists_file:
; found file; if we are creating directory, return "access denied",
; if we are creating file, delete existing file and continue
cmp byte [esp+20+28], 0
jz @f
add esp, 20
popad
mov eax, ERROR_ACCESS_DENIED
xor ebx, ebx
ret
@@:
; delete FAT chain
push edi
xor eax, eax
mov dword [edi+28], eax ; zero size
xchg ax, word [edi+26] ; start cluster
test eax, eax
jz .done1
@@:
cmp eax, 0xFF8
jae .done1
lea edi, [RAMDISK_FAT + eax*2] ; position in FAT
xor eax, eax
xchg ax, [edi]
jmp @b
.done1:
pop edi
call get_time_for_file
mov [edi+22], ax
call get_date_for_file
mov [edi+24], ax
mov [edi+18], ax
or byte [edi+11], 20h ; set 'archive' attribute
jmp .doit
.notfound:
; file is not found; generate short name
call fat_name_is_legal
jc @f
add esp, 20
popad
mov eax, ERROR_FILE_NOT_FOUND
xor ebx, ebx
ret
@@:
sub esp, 12
mov edi, esp
call fat_gen_short_name
.test_short_name_loop:
push esi edi ecx
mov esi, edi
lea eax, [esp+12+12+8]
mov [eax], ebp
call dword [eax-4]
jc .found
.test_short_name_entry:
cmp byte [edi+11], 0xF
jz .test_short_name_cont
mov ecx, 11
push esi edi
repz cmpsb
pop edi esi
jz .short_name_found
.test_short_name_cont:
lea eax, [esp+12+12+8]
call dword [eax-8]
jnc .test_short_name_entry
jmp .found
.short_name_found:
pop ecx edi esi
call fat_next_short_name
jnc .test_short_name_loop
.disk_full:
add esp, 12+20
popad
mov eax, ERROR_DISK_FULL
xor ebx, ebx
ret
.found:
pop ecx edi esi
; now find space in directory
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
mov al, '~'
push ecx edi
mov ecx, 8
repnz scasb
push 1
pop eax ; 1 entry
jnz .notilde
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
xor eax, eax
@@:
cmp byte [esi], 0
jz @f
inc esi
inc eax
jmp @b
@@:
sub esi, eax
add eax, 12+13
mov ecx, 13
push edx
cdq
div ecx
pop edx
.notilde:
push -1
push -1
; find <eax> successive entries in directory
xor ecx, ecx
push eax
lea eax, [esp+12+8+12+8]
mov [eax], ebp
call dword [eax-4]
pop eax
.scan_dir:
cmp byte [edi], 0
jz .free
cmp byte [edi], 0xE5
jz .free
xor ecx, ecx
.scan_cont:
push eax
lea eax, [esp+12+8+12+8]
call dword [eax-8]
pop eax
jnc .scan_dir
push eax
lea eax, [esp+12+8+12+8]
call dword [eax+8] ; extend directory
pop eax
jnc .scan_dir
add esp, 8+8+12+20
popad
mov eax, ERROR_DISK_FULL
xor ebx, ebx
ret
.free:
test ecx, ecx
jnz @f
mov [esp], edi
mov ecx, [esp+8+8+12+8]
mov [esp+4], ecx
xor ecx, ecx
@@:
inc ecx
cmp ecx, eax
jb .scan_cont
; found!
; calculate name checksum
push esi ecx
mov esi, [esp+8+8]
mov ecx, 11
xor eax, eax
@@:
ror al, 1
add al, [esi]
inc esi
loop @b
pop ecx esi
pop edi
pop dword [esp+8+12+8]
; edi points to last entry in free chunk
dec ecx
jz .nolfn
push esi
push eax
mov al, 40h
.writelfn:
or al, cl
mov esi, [esp+4]
push ecx
dec ecx
imul ecx, 13
add esi, ecx
stosb
mov cl, 5
call .read_symbols
mov ax, 0xF
stosw
mov al, [esp+4]
stosb
mov cl, 6
call .read_symbols
xor eax, eax
stosw
mov cl, 2
call .read_symbols
pop ecx
lea eax, [esp+8+8+12+8]
call dword [eax+4] ; next write
xor eax, eax
loop .writelfn
pop eax
pop esi
.nolfn:
xchg esi, [esp]
mov ecx, 11
rep movsb
mov word [edi], 20h ; attributes
sub edi, 11
pop esi ecx
add esp, 12
mov byte [edi+13], 0 ; tenths of a second at file creation time
call get_time_for_file
mov [edi+14], ax ; creation time
mov [edi+22], ax ; last write time
call get_date_for_file
mov [edi+16], ax ; creation date
mov [edi+24], ax ; last write date
mov [edi+18], ax ; last access date
and word [edi+20], 0 ; high word of cluster
and word [edi+26], 0 ; low word of cluster - to be filled
and dword [edi+28], 0 ; file size - to be filled
cmp byte [esp+20+28], 0
jz .doit
; create directory
mov byte [edi+11], 10h ; attributes: folder
mov ecx, 32*2
mov edx, edi
.doit:
push edx
push ecx
push edi
add edi, 26 ; edi points to low word of cluster
push edi
jecxz .done
mov ecx, 2849
mov edi, RAMDISK_FAT
.write_loop:
; allocate new cluster
xor eax, eax
repnz scasw
jnz .disk_full2
dec edi
dec edi
 
; lea eax, [edi-(RAMDISK_FAT)]
 
mov eax, edi
sub eax, RAMDISK_FAT
 
shr eax, 1 ; eax = cluster
mov word [edi], 0xFFF ; mark as last cluster
xchg edi, [esp]
stosw
pop edi
push edi
inc ecx
; write data
cmp byte [esp+16+20+28], 0
jnz .writedir
shl eax, 9
add eax, RAMDISK+31*512
.writefile:
mov ebx, edx
xchg eax, ebx
push ecx
mov ecx, 512
cmp dword [esp+12], ecx
jae @f
mov ecx, [esp+12]
@@:
call memmove
add edx, ecx
sub [esp+12], ecx
pop ecx
jnz .write_loop
.done:
mov ebx, edx
pop edi edi ecx edx
sub ebx, edx
mov [edi+28], ebx
add esp, 20
mov [esp+16], ebx
popad
xor eax, eax
ret
.disk_full2:
mov ebx, edx
pop edi edi ecx edx
sub ebx, edx
mov [edi+28], ebx
add esp, 20
mov [esp+16], ebx
popad
push ERROR_DISK_FULL
pop eax
ret
.writedir:
mov edi, eax
shl edi, 9
add edi, RAMDISK+31*512
mov esi, edx
mov ecx, 32/4
push ecx
rep movsd
mov dword [edi-32], '. '
mov dword [edi-32+4], ' '
mov dword [edi-32+8], ' '
mov byte [edi-32+11], 10h
mov word [edi-32+26], ax
mov esi, edx
pop ecx
rep movsd
mov dword [edi-32], '.. '
mov dword [edi-32+4], ' '
mov dword [edi-32+8], ' '
mov byte [edi-32+11], 10h
mov eax, [esp+16+8]
mov word [edi-32+26], ax
xor eax, eax
mov ecx, (512-32*2)/4
rep stosd
pop edi edi ecx edx
add esp, 20
popad
xor eax, eax
xor ebx, ebx
ret
 
.read_symbol:
or ax, -1
test esi, esi
jz .retFFFF
lodsb
test al, al
jnz ansi2uni_char
xor eax, eax
xor esi, esi
.retFFFF:
ret
 
.read_symbols:
call .read_symbol
stosw
loop .read_symbols
ret
 
;----------------------------------------------------------------
;
; fs_RamdiskWrite - LFN variant for writing to sys floppy
;
; esi points to filename
; ebx pointer to 64-bit number = first wanted byte, 0+
; may be ebx=0 - start from first byte
; ecx number of bytes to write, 0+
; edx mem location to data
;
; ret ebx = bytes written (maybe 0)
; eax = 0 ok write or other = errormsg
;
;--------------------------------------------------------------
@@:
push ERROR_ACCESS_DENIED
fs_RamdiskWrite.ret0:
pop eax
xor ebx, ebx
ret
 
fs_RamdiskWrite:
cmp byte [esi], 0
jz @b
pushad
call rd_find_lfn
jnc .found
popad
push ERROR_FILE_NOT_FOUND
jmp .ret0
.found:
; must not be directory
test byte [edi+11], 10h
jz @f
popad
push ERROR_ACCESS_DENIED
jmp .ret0
@@:
; FAT does not support files larger than 4GB
test ebx, ebx
jz .l1
cmp dword [ebx+4], 0
jz @f
.eof:
popad
push ERROR_END_OF_FILE
jmp .ret0
@@:
mov ebx, [ebx]
.l1:
; now edi points to direntry, ebx=start byte to write,
; ecx=number of bytes to write, edx=data pointer
call fat_update_datetime
 
; extend file if needed
add ecx, ebx
jc .eof ; FAT does not support files larger than 4GB
push 0 ; return value=0
cmp ecx, [edi+28]
jbe .length_ok
cmp ecx, ebx
jz .length_ok
call ramdisk_extend_file
jnc .length_ok
; ramdisk_extend_file can return two error codes: FAT table error or disk full.
; First case is fatal error, in second case we may write some data
mov [esp], eax
cmp al, ERROR_DISK_FULL
jz .disk_full
pop eax
mov [esp+28], eax
popad
xor ebx, ebx
ret
.disk_full:
; correct number of bytes to write
mov ecx, [edi+28]
cmp ecx, ebx
ja .length_ok
.ret:
pop eax
mov [esp+28], eax ; eax=return value
sub edx, [esp+20]
mov [esp+16], edx ; ebx=number of written bytes
popad
ret
.length_ok:
; now ebx=start pos, ecx=end pos, both lie inside file
sub ecx, ebx
jz .ret
movzx edi, word [edi+26] ; starting cluster
.write_loop:
sub ebx, 0x200
jae .next_cluster
push ecx
neg ebx
cmp ecx, ebx
jbe @f
mov ecx, ebx
@@:
mov eax, edi
shl eax, 9
add eax, RAMDISK+31*512+0x200
sub eax, ebx
mov ebx, eax
mov eax, edx
call memmove
xor ebx, ebx
add edx, ecx
sub [esp], ecx
pop ecx
jz .ret
.next_cluster:
movzx edi, word [edi*2+RAMDISK_FAT]
jmp .write_loop
 
ramdisk_extend_file.zero_size:
xor eax, eax
jmp ramdisk_extend_file.start_extend
 
; extends file on ramdisk to given size, new data area is filled by 0
; in: edi->direntry, ecx=new size
; out: CF=0 => OK, eax=0
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL)
ramdisk_extend_file:
push ecx
; find the last cluster of file
movzx eax, word [edi+26] ; first cluster
mov ecx, [edi+28]
jecxz .zero_size
@@:
sub ecx, 0x200
jbe @f
mov eax, [eax*2+RAMDISK_FAT]
and eax, 0xFFF
jz .fat_err
cmp eax, 0xFF8
jb @b
.fat_err:
pop ecx
push ERROR_FAT_TABLE
pop eax
stc
ret
@@:
push eax
mov eax, [eax*2+RAMDISK_FAT]
and eax, 0xFFF
cmp eax, 0xFF8
pop eax
jb .fat_err
; set length to full number of sectors and make sure that last sector is zero-padded
sub [edi+28], ecx
push eax edi
mov edi, eax
shl edi, 9
lea edi, [edi+RAMDISK+31*512+0x200+ecx]
neg ecx
xor eax, eax
rep stosb
pop edi eax
.start_extend:
pop ecx
; now do extend
push edx esi
mov esi, RAMDISK_FAT+2*2 ; start scan from cluster 2
mov edx, 2847 ; number of clusters to scan
.extend_loop:
cmp [edi+28], ecx
jae .extend_done
; add new sector
push ecx
mov ecx, edx
push edi
mov edi, esi
jecxz .disk_full
push eax
xor eax, eax
repnz scasw
pop eax
jnz .disk_full
mov word [edi-2], 0xFFF
mov esi, edi
mov edx, ecx
sub edi, RAMDISK_FAT
shr edi, 1
dec edi ; now edi=new cluster
test eax, eax
jz .first_cluster
mov [RAMDISK_FAT+eax*2], di
jmp @f
.first_cluster:
pop eax ; eax->direntry
push eax
mov [eax+26], di
@@:
push edi
shl edi, 9
add edi, RAMDISK+31*512
xor eax, eax
mov ecx, 512/4
rep stosd
pop eax ; eax=new cluster
pop edi ; edi->direntry
pop ecx ; ecx=required size
add dword [edi+28], 0x200
jmp .extend_loop
.extend_done:
mov [edi+28], ecx
pop esi edx
xor eax, eax ; CF=0
ret
.disk_full:
pop edi ecx
pop esi edx
stc
push ERROR_DISK_FULL
pop eax
ret
 
fat_update_datetime:
call get_time_for_file
mov [edi+22], ax ; last write time
call get_date_for_file
mov [edi+24], ax ; last write date
mov [edi+18], ax ; last access date
ret
 
;----------------------------------------------------------------
;
; fs_RamdiskSetFileEnd - set end of file on ramdisk
;
; esi points to filename
; ebx points to 64-bit number = new file size
; ecx ignored (reserved)
; edx ignored (reserved)
;
; ret eax = 0 ok or other = errormsg
;
;--------------------------------------------------------------
fs_RamdiskSetFileEnd:
cmp byte [esi], 0
jnz @f
.access_denied:
push ERROR_ACCESS_DENIED
jmp .ret
@@:
push edi
call rd_find_lfn
jnc @f
pop edi
push ERROR_FILE_NOT_FOUND
.ret:
pop eax
ret
@@:
; must not be directory
test byte [edi+11], 10h
jz @f
pop edi
jmp .access_denied
@@:
; file size must not exceed 4Gb
cmp dword [ebx+4], 0
jz @f
pop edi
push ERROR_END_OF_FILE
jmp .ret
@@:
; set file modification date/time to current
call fat_update_datetime
mov eax, [ebx]
cmp eax, [edi+28]
jb .truncate
ja .expand
pop edi
xor eax, eax
ret
.expand:
push ecx
mov ecx, eax
call ramdisk_extend_file
pop ecx
pop edi
ret
.truncate:
mov [edi+28], eax
push ecx
movzx ecx, word [edi+26]
test eax, eax
jz .zero_size
; find new last sector
@@:
sub eax, 0x200
jbe @f
movzx ecx, word [RAMDISK_FAT+ecx*2]
jmp @b
@@:
; zero data at the end of last sector
push ecx
mov edi, ecx
shl edi, 9
lea edi, [edi+RAMDISK+31*512+eax+0x200]
mov ecx, eax
neg ecx
xor eax, eax
rep stosb
pop ecx
; terminate FAT chain
lea ecx, [RAMDISK_FAT+ecx+ecx]
push dword [ecx]
mov word [ecx], 0xFFF
pop ecx
and ecx, 0xFFF
jmp .delete
.zero_size:
and word [edi+26], 0
.delete:
; delete FAT chain starting with ecx
; mark all clusters as free
cmp ecx, 0xFF8
jae .deleted
lea ecx, [RAMDISK_FAT+ecx+ecx]
push dword [ecx]
and word [ecx], 0
pop ecx
and ecx, 0xFFF
jmp .delete
.deleted:
pop ecx
pop edi
xor eax, eax
ret
 
fs_RamdiskGetFileInfo:
cmp byte [esi], 0
jnz @f
mov eax, 2 ; unsupported
ret
@@:
push edi
call rd_find_lfn
fs_GetFileInfo_finish:
jnc @f
pop edi
mov eax, ERROR_FILE_NOT_FOUND
ret
@@:
push esi ebp
xor ebp, ebp
mov esi, edx
and dword [esi+4], 0
call fat_entry_to_bdfe2
pop ebp esi
pop edi
xor eax, eax
ret
 
fs_RamdiskSetFileInfo:
cmp byte [esi], 0
jnz @f
mov eax, 2 ; unsupported
ret
@@:
push edi
call rd_find_lfn
jnc @f
pop edi
mov eax, ERROR_FILE_NOT_FOUND
ret
@@:
call bdfe_to_fat_entry
pop edi
xor eax, eax
ret
 
;----------------------------------------------------------------
;
; fs_RamdiskDelete - delete file or empty folder from ramdisk
;
; esi points to filename
;
; ret eax = 0 ok or other = errormsg
;
;--------------------------------------------------------------
fs_RamdiskDelete:
cmp byte [esi], 0
jnz @f
; cannot delete root!
.access_denied:
push ERROR_ACCESS_DENIED
.pop_ret:
pop eax
ret
@@:
and [rd_prev_sector], 0
and [rd_prev_prev_sector], 0
push edi
call rd_find_lfn
jnc .found
pop edi
push ERROR_FILE_NOT_FOUND
jmp .pop_ret
.found:
cmp dword [edi], '. '
jz .access_denied2
cmp dword [edi], '.. '
jz .access_denied2
test byte [edi+11], 10h
jz .dodel
; we can delete only empty folders!
movzx eax, word [edi+26]
push ebx
mov ebx, eax
shl ebx, 9
add ebx, RAMDISK + 31*0x200 + 2*0x20
.checkempty:
cmp byte [ebx], 0
jz .empty
cmp byte [ebx], 0xE5
jnz .notempty
add ebx, 0x20
test ebx, 0x1FF
jnz .checkempty
movzx eax, word [RAMDISK_FAT + eax*2]
test eax, eax
jz .empty
mov ebx, eax
shl ebx, 9
add ebx, RAMDISK + 31*0x200
jmp .checkempty
.notempty:
pop ebx
.access_denied2:
pop edi
jmp .access_denied
.empty:
pop ebx
.dodel:
movzx eax, word [edi+26]
; delete folder entry
mov byte [edi], 0xE5
; delete LFN (if present)
.lfndel:
test edi, 0x1FF
jnz @f
cmp [rd_prev_sector], 0
jz @f
cmp [rd_prev_sector], -1
jz .lfndone
mov edi, [rd_prev_sector]
push [rd_prev_prev_sector]
pop [rd_prev_sector]
or [rd_prev_prev_sector], -1
shl edi, 9
add edi, RAMDISK + 31*0x200 + 0x200
@@:
sub edi, 0x20
cmp byte [edi], 0xE5
jz .lfndone
cmp byte [edi+11], 0xF
jnz .lfndone
mov byte [edi], 0xE5
jmp .lfndel
.lfndone:
; delete FAT chain
test eax, eax
jz .done
lea eax, [RAMDISK_FAT + eax*2]
push dword [eax]
and word [eax], 0
pop eax
and eax, 0xFFF
jmp .lfndone
.done:
pop edi
xor eax, eax
ret
 
; \end{diamond}
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/blkdev
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/boot/bootcode.inc
0,0 → 1,1384
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; BOOTCODE.INC ;;
;; ;;
;; KolibriOS 16-bit loader, ;;
;; based on bootcode for MenuetOS ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
;==========================================================================
;
; 16 BIT FUNCTIONS
;
;==========================================================================
 
 
putchar:
; in: al=character
mov ah, 0Eh
mov bh, 0
int 10h
ret
 
print:
; in: si->string
mov al, 186
call putchar
mov al, ' '
call putchar
 
printplain:
; in: si->string
pusha
lodsb
@@:
call putchar
lodsb
test al, al
jnz @b
popa
ret
 
getkey:
; get number in range [bl,bh] (bl,bh in ['0'..'9'])
; in: bx=range
; out: ax=digit (1..9, 10 for 0)
mov ah, 0
int 16h
cmp al, bl
jb getkey
cmp al, bh
ja getkey
push ax
call putchar
pop ax
and ax, 0Fh
jnz @f
mov al, 10
@@:
ret
 
setcursor:
; in: dl=column, dh=row
mov ah, 2
mov bh, 0
int 10h
ret
 
macro _setcursor row,column
{
mov dx, row*256 + column
call setcursor
}
 
boot_read_floppy:
push si
xor si, si
mov ah, 2 ; read
@@:
push ax
int 0x13
pop ax
jnc @f
inc si
cmp si, 10
jb @b
sayerr_badsect:
mov si, badsect
sayerr_plain:
call printplain
jmp $
@@:
pop si
ret
 
; convert abs. sector number (AX) to BIOS T:H:S
; sector number = (abs.sector%BPB_SecPerTrk)+1
; pre.track number = (abs.sector/BPB_SecPerTrk)
; head number = pre.track number%BPB_NumHeads
; track number = pre.track number/BPB_NumHeads
; Return: cl - sector number
; ch - track number
; dl - drive number (0 = a:)
; dh - head number
conv_abs_to_THS:
push bx
mov bx, word [BPB_SecPerTrk]
xor dx, dx
div bx
inc dx
mov cl, dl ; cl = sector number
mov bx, word [BPB_NumHeads]
xor dx, dx
div bx
; !!!!!!! ax = track number, dx = head number
mov ch, al ; ch=track number
xchg dh, dl ; dh=head number
mov dl, 0 ; dl=0 (drive 0 (a:))
pop bx
retn
; needed variables
BPB_SecPerTrk dw 0 ; sectors per track
BPB_NumHeads dw 0 ; number of heads
BPB_FATSz16 dw 0 ; size of FAT
BPB_RootEntCnt dw 0 ; count of root dir. entries
BPB_BytsPerSec dw 0 ; bytes per sector
BPB_RsvdSecCnt dw 0 ; number of reserved sectors
BPB_TotSec16 dw 0 ; count of the sectors on the volume
BPB_SecPerClus db 0 ; number of sectors per cluster
BPB_NumFATs db 0 ; number of FAT tables
abs_sector_adj dw 0 ; adjustment to make abs. sector number
end_of_FAT dw 0 ; end of FAT table
FirstDataSector dw 0 ; begin of data
 
;=========================================================================
;
; 16 BIT CODE
;
;=========================================================================
 
include 'bootvesa.inc' ;Include source for boot vesa
if defined extended_primary_loader
include 'parsers.inc'
end if
 
start_of_code:
 
if defined extended_primary_loader
; save data from primary loader
mov word [cs:bootcallback], si
mov word [cs:bootcallback+2], ds
push cs
pop ds
mov [bootdevice], ax
mov [bootfs], bx
 
; set up stack
mov ax, 3000h
mov ss, ax
mov sp, 0EC00h
 
; try to load configuration file
mov ax, 1
mov di, config_file_struct
call [bootcallback]
cld
push cs
pop es
; bx=0 - ok, bx=1 - part of file loaded, assume this is ok
cmp bx, 1
ja .config_bad
; configuration file was loaded, parse
; if length is too big, use first 0FFFFh bytes
test dx, dx
jz @f
mov ax, 0FFFFh
@@:
; ds:si will be pointer to current data, dx = limit
xchg ax, dx
push 4000h
pop ds
xor si, si
.parse_loop:
; skip spaces
cmp si, dx
jae .parse_done
lodsb
cmp al, ' '
jbe .parse_loop
dec si
; loop over all possible configuration values
mov bx, config_file_variables
.find_variant:
; get length
mov cx, [es:bx]
; zero length = end of list
jecxz .find_newline
; skip over length
inc bx
inc bx
mov di, bx
; skip over string
add bx, cx
; test whether we have at least cx symbols left
mov ax, cx
add ax, si
jc .next_variant1
cmp ax, dx
jae .next_variant1
; save current position
push si
; compare strings
repz cmpsb
jnz .next_variant2
; strings are equal; look for "=" with possible spaces before and after
@@:
cmp si, dx
jae .next_variant2
lodsb
cmp al, ' '
jbe @b
cmp al, '='
jnz .next_variant2
; ok, we found the true variant
; ignore saved position on the stack
pop ax
; call the parser
call word [es:bx]
; line parsed, find next
.find_newline:
cmp si, dx
jae .parse_done
lodsb
cmp al, 13
jz .parse_loop
cmp al, 10
jz .parse_loop
jmp .find_newline
.next_variant2:
; continue to the next variant, restoring current position
pop si
.next_variant1:
; continue to the next variant
; skip over the parser
inc bx
inc bx
jmp .find_variant
.parse_done:
.config_bad:
 
; set up segment registers
push cs
pop ds
else
cld
; \begin{diamond}[02.12.2005]
; if bootloader sets ax = 'KL', then ds:si points to loader block
cmp ax, 'KL'
jnz @f
mov word [cs:cfgmanager.loader_block], si
mov word [cs:cfgmanager.loader_block+2], ds
@@:
; \end{diamond}[02.12.2005]
 
; if bootloader sets cx = 'HA' and dx = 'RD', then bx contains identifier of source hard disk
; (see comment to bx_from_load)
cmp cx, 'HA'
jnz no_hd_load
cmp dx, 'RD'
jnz no_hd_load
mov word [cs:bx_from_load], bx ; {SPraid}[13.03.2007]
no_hd_load:
 
; set up stack
mov ax, 3000h
mov ss, ax
mov sp, 0EC00h
; set up segment registers
push cs
pop ds
push cs
pop es
end if
 
; set videomode
mov ax, 3
int 0x10
 
if lang eq ru
; Load & set russian VGA font (RU.INC)
mov bp, RU_FNT1 ; RU_FNT1 - First part
mov bx, 1000h ; 768 bytes
mov cx, 30h ; 48 symbols
mov dx, 80h ; 128 - position of first symbol
mov ax, 1100h
int 10h
 
mov bp, RU_FNT2 ; RU_FNT2 -Second part
mov bx, 1000h ; 512 bytes
mov cx, 20h ; 32 symbols
mov dx, 0E0h ; 224 - position of first symbol
mov ax, 1100h
int 10h
; End set VGA russian font
else if lang eq et
mov bp, ET_FNT ; ET_FNT1
mov bx, 1000h ;
mov cx, 255 ; 256 symbols
xor dx, dx ; 0 - position of first symbol
mov ax, 1100h
int 10h
end if
 
; draw frames
push 0xb800
pop es
xor di, di
mov ah, 1*16+15
 
; draw top
mov si, d80x25_top
mov cx, d80x25_top_num * 80
@@:
lodsb
stosw
loop @b
; draw spaces
mov si, space_msg
mov dx, 25 - d80x25_top_num - d80x25_bottom_num
dfl1:
push si
mov cx, 80
@@:
lodsb
stosw
loop @b
pop si
dec dx
jnz dfl1
; draw bottom
mov si, d80x25_bottom
mov cx, d80x25_bottom_num * 80
@@:
lodsb
stosw
loop @b
 
mov byte [space_msg+80], 0 ; now space_msg is null terminated
 
_setcursor d80x25_top_num,0
 
 
; TEST FOR 386+
 
mov bx, 0x4000
pushf
pop ax
mov dx, ax
xor ax, bx
push ax
popf
pushf
pop ax
and ax, bx
and dx, bx
cmp ax, dx
jnz cpugood
mov si, not386
sayerr:
call print
jmp $
cpugood:
 
push 0
popf
sti
 
; set up esp
movzx esp, sp
 
push 0
pop es
and word [es:BOOT_IDE_BASE_ADDR], 0
; \begin{Mario79}
; find HDD IDE DMA PCI device
; check for PCI BIOS
mov ax, 0xB101
int 0x1A
jc .nopci
cmp edx, 'PCI '
jnz .nopci
; find PCI class code
; class 1 = mass storage
; subclass 1 = IDE controller
; a) class 1, subclass 1, programming interface 0x80
mov ax, 0xB103
mov ecx, 1*10000h + 1*100h + 0x80
xor si, si ; device index = 0
int 0x1A
jnc .found
; b) class 1, subclass 1, programming interface 0x8A
mov ax, 0xB103
mov ecx, 1*10000h + 1*100h + 0x8A
xor si, si ; device index = 0
int 0x1A
jnc .found
; c) class 1, subclass 1, programming interface 0x85
mov ax, 0xB103
mov ecx, 1*10000h + 1*100h + 0x85
xor si, si
int 0x1A
jc .nopci
.found:
; get memory base
mov ax, 0xB10A
mov di, 0x20 ; memory base is config register at 0x20
int 0x1A
jc .nopci
and cx, 0xFFF0 ; clear address decode type
mov [es:BOOT_IDE_BASE_ADDR], cx
.nopci:
; \end{Mario79}
 
mov al, 0xf6 ; Ñáðîñ êëàâèàòóðû, ðàçðåøèòü ñêàíèðîâàíèå
out 0x60, al
xor cx, cx
wait_loop: ; variant 2
; reading state of port of 8042 controller
in al, 64h
and al, 00000010b ; ready flag
; wait until 8042 controller is ready
loopnz wait_loop
 
;;;/diamond today 5.02.2008
; set keyboard typematic rate & delay
mov al, 0xf3
out 0x60, al
xor cx, cx
@@:
in al, 64h
test al, 2
loopnz @b
mov al, 0
out 0x60, al
xor cx, cx
@@:
in al, 64h
test al, 2
loopnz @b
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; --------------- APM ---------------------
and word [es:BOOT_APM_VERSION], 0 ; ver = 0.0 (APM not found)
mov ax, 0x5300
xor bx, bx
int 0x15
jc apm_end ; APM not found
test cx, 2
jz apm_end ; APM 32-bit protected-mode interface not supported
mov [es:BOOT_APM_VERSION], ax ; Save APM Version
mov [es:BOOT_APM_FLAGS], cx ; Save APM flags
 
; Write APM ver ----
and ax, 0xf0f
add ax, '00'
mov si, msg_apm
mov [si + 5], ah
mov [si + 7], al
_setcursor 0, 3
call printplain
; ------------------
 
mov ax, 0x5304 ; Disconnect interface
xor bx, bx
int 0x15
mov ax, 0x5303 ; Connect 32 bit mode interface
xor bx, bx
int 0x15
 
mov [es:BOOT_APM_ENTRY], ebx
mov [es:BOOT_APM_CODE_32], ax
mov [es:BOOT_APM_CODE_16], cx
mov [es:BOOT_APM_DATA_16], dx
 
apm_end:
_setcursor d80x25_top_num, 0
 
if ~ defined extended_primary_loader
;CHECK current of code
cmp [cfgmanager.loader_block], -1
jz noloaderblock
les bx, [cfgmanager.loader_block]
cmp byte [es:bx], 1
mov si, loader_block_error
jnz sayerr
push 0
pop es
end if
 
noloaderblock:
; DISPLAY VESA INFORMATION
call print_vesa_info
call calc_vmodes_table
call check_first_parm ;check and enable cursor_pos
 
; \begin{diamond}[30.11.2005]
cfgmanager:
; settings:
; a) preboot_graph = graphical mode
; preboot_gprobe = probe this mode?
; b) preboot_dma = use DMA access?
; c) preboot_vrrm = use VRR?
; d) preboot_device = from what boot?
 
; determine default settings
if ~ defined extended_primary_loader
mov [.bSettingsChanged], 0
end if
 
;.preboot_gr_end:
mov di, preboot_device
; if image in memory is present and [preboot_device] is uninitialized,
; set it to use this preloaded image
cmp byte [di], 0
jnz .preboot_device_inited
if defined extended_primary_loader
inc byte [di]
cmp byte [bootdevice], 'f' ; floppy?
jz .preboot_device_inited
inc byte [di]
else
cmp [.loader_block], -1
jz @f
les bx, [.loader_block]
test byte [es:bx+1], 1
jz @f
mov byte [di], 3
jmp .preboot_device_inited
@@:
; otherwise, set [preboot_device] to 1 (default value - boot from floppy)
mov byte [di], 1
end if
.preboot_device_inited:
; following 4 lines set variables to 1 if its current value is 0
cmp byte [di+preboot_dma-preboot_device], 1
adc byte [di+preboot_dma-preboot_device], 0
cmp byte [di+preboot_biosdisk-preboot_device], 1
adc byte [di+preboot_biosdisk-preboot_device], 0
;; default value for VRR is OFF
; cmp byte [di+preboot_vrrm-preboot_device], 0
; jnz @f
; mov byte [di+preboot_vrrm-preboot_device], 2
;@@:
; notify user
_setcursor 5,2
 
mov si, linef
call printplain
mov si, start_msg
call print
mov si, time_msg
call print
; get start time
call .gettime
mov [.starttime], eax
mov word [.timer], .newtimer
mov word [.timer+2], cs
.printcfg:
 
_setcursor 9,0
mov si, current_cfg_msg
call print
mov si, curvideo_msg
call print
 
call draw_current_vmode
 
mov si, usebd_msg
cmp [preboot_biosdisk], 1
call .say_on_off
; mov si, vrrm_msg
; cmp [preboot_vrrm], 1
; call .say_on_off
mov si, preboot_device_msg
call print
mov al, [preboot_device]
if defined extended_primary_loader
and eax, 3
else
and eax, 7
end if
mov si, [preboot_device_msgs+eax*2]
call printplain
.show_remarks:
; show remarks in gray color
mov di, ((21-num_remarks)*80 + 2)*2
push 0xB800
pop es
mov cx, num_remarks
mov si, remarks
.write_remarks:
lodsw
push si
xchg ax, si
mov ah, 1*16+7 ; background: blue (1), foreground: gray (7)
push di
.write_remark:
lodsb
test al, al
jz @f
stosw
jmp .write_remark
@@:
pop di
pop si
add di, 80*2
loop .write_remarks
.wait:
_setcursor 25,0 ; out of screen
; set timer interrupt handler
cli
push 0
pop es
push dword [es:8*4]
pop dword [.oldtimer]
push dword [.timer]
pop dword [es:8*4]
; mov eax, [es:8*4]
; mov [.oldtimer], eax
; mov eax, [.timer]
; mov [es:8*4], eax
sti
; wait for keypressed
xor ax, ax
int 16h
push ax
; restore timer interrupt
; push 0
; pop es
mov eax, [.oldtimer]
mov [es:8*4], eax
mov [.timer], eax
 
_setcursor 7,0
mov si, space_msg
call printplain
; clear remarks and restore normal attributes
push es
mov di, ((21-num_remarks)*80 + 2)*2
push 0xB800
pop es
mov cx, num_remarks
mov ax, ' ' + (1*16 + 15)*100h
@@:
push cx
mov cx, 76
rep stosw
pop cx
add di, 4*2
loop @b
pop es
pop ax
; switch on key
cmp al, 13
jz .continue
or al, 20h
cmp al, 'a'
jz .change_a
cmp al, 'b'
jz .change_b
; cmp al, 'c'
; jz .change_c
cmp al, 'c' ; 'd'
jnz .show_remarks
_setcursor 15,0
mov si, bdev
call print
if defined extended_primary_loader
mov bx, '12'
else
mov bx, '14'
end if
call getkey
mov [preboot_device], al
_setcursor 13,0
.d:
if ~ defined extended_primary_loader
mov [.bSettingsChanged], 1
end if
call clear_vmodes_table ;clear vmodes_table
jmp .printcfg
.change_a:
.loops:
call draw_vmodes_table
_setcursor 25,0 ; out of screen
xor ax, ax
int 0x16
; call clear_table_cursor ;clear current position of cursor
 
mov si, word [cursor_pos]
 
cmp ah, 0x48;x,0x48E0 ; up
jne .down
cmp si, modes_table
jbe .loops
sub word [cursor_pos], size_of_step
jmp .loops
 
.down:
cmp ah, 0x50;x,0x50E0 ; down
jne .pgup
cmp word[es:si+10], -1
je .loops
add word [cursor_pos], size_of_step
jmp .loops
 
.pgup:
cmp ah, 0x49 ; page up
jne .pgdn
sub si, size_of_step*long_v_table
cmp si, modes_table
jae @f
mov si, modes_table
@@:
mov word [cursor_pos], si
mov si, word [home_cursor]
sub si, size_of_step*long_v_table
cmp si, modes_table
jae @f
mov si, modes_table
@@:
mov word [home_cursor], si
jmp .loops
 
.pgdn:
cmp ah, 0x51 ; page down
jne .enter
mov ax, [end_cursor]
add si, size_of_step*long_v_table
cmp si, ax
jb @f
mov si, ax
sub si, size_of_step
@@:
mov word [cursor_pos], si
mov si, word [home_cursor]
sub ax, size_of_step*long_v_table
add si, size_of_step*long_v_table
cmp si, ax
jb @f
mov si, ax
@@:
mov word [home_cursor], si
jmp .loops
 
.enter:
cmp al, 0x0D;x,0x1C0D ; enter
jne .loops
push word [cursor_pos]
pop bp
push word [es:bp]
pop word [x_save]
push word [es:bp+2]
pop word [y_save]
push word [es:bp+6]
pop word [number_vm]
mov word [preboot_graph], bp ;save choose
jmp .d
 
.change_b:
_setcursor 15,0
; mov si, ask_dma
; call print
; mov bx, '13'
; call getkey
; mov [preboot_dma], al
mov si, ask_bd
call print
mov bx, '12'
call getkey
mov [preboot_biosdisk], al
_setcursor 11,0
jmp .d
;.change_c:
; _setcursor 15,0
; mov si, vrrmprint
; call print
; mov bx, '12'
; call getkey
; mov [preboot_vrrm], al
; _setcursor 12,0
; jmp .d
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.say_on_off:
pushf
call print
mov si, on_msg
popf
jz @f
mov si, off_msg
@@:
jmp printplain
; novesa and vervesa strings are not used at the moment of executing this code
virtual at novesa
.oldtimer dd ?
.starttime dd ?
if ~ defined extended_primary_loader
.bSettingsChanged db ?
end if
.timer dd ?
end virtual
if ~ defined extended_primary_loader
.loader_block dd -1
end if
.gettime:
mov ah, 0
int 1Ah
xchg ax, cx
shl eax, 10h
xchg ax, dx
ret
.newtimer:
push ds
push cs
pop ds
pushf
call [.oldtimer]
pushad
call .gettime
sub eax, [.starttime]
if defined extended_primary_loader
sub ax, [preboot_timeout]
else
sub ax, 18*5
end if
jae .timergo
neg ax
add ax, 18-1
mov bx, 18
xor dx, dx
div bx
if lang eq ru
; ¯®¤®¦¤¨â¥ 5 ᥪ㭤, 4/3/2 ᥪ㭤ë, 1 ᥪ㭤ã
cmp al, 5
mov cl, ' '
jae @f
cmp al, 1
mov cl, 'ã'
jz @f
mov cl, 'ë'
@@:
mov [time_str+9], cl
else if lang eq et
cmp al, 1
ja @f
mov [time_str+9], ' '
mov [time_str+10], ' '
@@:
else if lang eq sp
; esperar 5/4/3/2 segundos, 1 segundo
cmp al, 1
mov cl, 's'
ja @f
mov cl, ' '
@@:
mov [time_str+10], cl
else
; wait 5/4/3/2 seconds, 1 second
cmp al, 1
mov cl, 's'
ja @f
mov cl, ' '
@@:
mov [time_str+9], cl
end if
add al, '0'
mov [time_str+1], al
mov si, time_msg
_setcursor 7,0
call print
_setcursor 25,0
popad
pop ds
iret
.timergo:
push 0
pop es
mov eax, [.oldtimer]
mov [es:8*4], eax
mov sp, 0EC00h
.continue:
sti
_setcursor 6,0
mov si, space_msg
call printplain
call printplain
_setcursor 6,0
mov si, loading_msg
call print
_setcursor 15,0
if ~ defined extended_primary_loader
cmp [.bSettingsChanged], 0
jz .load
cmp [.loader_block], -1
jz .load
les bx, [.loader_block]
mov eax, [es:bx+3]
push ds
pop es
test eax, eax
jz .load
push eax
mov si, save_quest
call print
.waityn:
mov ah, 0
int 16h
or al, 20h
cmp al, 'n'
jz .loadc
cmp al, 'y'
jnz .waityn
call putchar
mov byte [space_msg+80], 186
 
pop eax
push cs
push .cont
push eax
retf ;call back
.loadc:
pop eax
.cont:
push cs
pop ds
mov si, space_msg
mov byte [si+80], 0
_setcursor 15,0
call printplain
_setcursor 15,0
.load:
end if
; \end{diamond}[02.12.2005]
 
; ASK GRAPHICS MODE
 
call set_vmode
 
; GRAPHICS ACCELERATION
; force yes
mov [es:BOOT_MTRR], byte 1
 
; DMA ACCESS TO HD
 
mov al, [preboot_dma]
mov [es:BOOT_DMA], al
 
;; VRR_M USE
;
; mov al,[preboot_vrrm]
; mov [es:0x9030], al
 
; BOOT DEVICE
 
mov al, [preboot_device]
dec al
mov [boot_dev], al
 
; GET MEMORY MAP
include '../detect/biosmem.inc'
 
; READ DISKETTE TO MEMORY
 
cmp [boot_dev], 0
jne no_sys_on_floppy
mov si, diskload
call print
xor ax, ax ; reset drive
xor dx, dx
int 0x13
; do we boot from CD-ROM?
mov ah, 41h
mov bx, 55AAh
xor dx, dx
int 0x13
jc .nocd
cmp bx, 0AA55h
jnz .nocd
mov ah, 48h
push ds
push es
pop ds
mov si, 0xa000
mov word [si], 30
int 0x13
pop ds
jc .nocd
push ds
lds si, [es:si+26]
test byte [ds:si+10], 40h
pop ds
jz .nocd
; yes - read all floppy by 18 sectors
 
; TODO: !!!! read only first sector and set variables !!!!!
; ...
; TODO: !!! then read flippy image track by track
mov cx, 0x0001 ; startcyl,startsector
.a1:
push cx dx
mov al, 18
mov bx, 0xa000
call boot_read_floppy
mov si, movedesc
push es
push ds
pop es
mov cx, 256*18
mov ah, 0x87
int 0x15
pop es
pop dx cx
test ah, ah
jnz sayerr_floppy
add dword [si+8*3+2], 512*18
inc dh
cmp dh, 2
jnz .a1
mov dh, 0
inc ch
cmp ch, 80
jae ok_sys_on_floppy
pusha
mov al, ch
shr ch, 2
add al, ch
aam
xchg al, ah
add ax, '00'
mov si, pros
mov [si], ax
call printplain
popa
jmp .a1
.nocd:
; no - read only used sectors from floppy
; now load floppy image to memory
; at first load boot sector and first FAT table
 
; read only first sector and fill variables
mov cx, 0x0001 ; first logical sector
xor dx, dx ; head = 0, drive = 0 (a:)
mov al, 1 ; read one sector
mov bx, 0xB000 ; es:bx -> data area
call boot_read_floppy
; fill the necessary parameters to work with a floppy
mov ax, word [es:bx+24]
mov word [BPB_SecPerTrk], ax
mov ax, word [es:bx+26]
mov word [BPB_NumHeads], ax
mov ax, word [es:bx+17]
mov word [BPB_RootEntCnt], ax
mov ax, word [es:bx+14]
mov word [BPB_RsvdSecCnt], ax
mov ax, word [es:bx+19]
mov word [BPB_TotSec16], ax
mov al, byte [es:bx+13]
mov byte [BPB_SecPerClus], al
mov al, byte [es:bx+16]
mov byte [BPB_NumFATs], al
;<Lrz> 18.11.2008
mov ax, word [es:bx+22]
mov word [BPB_FATSz16], ax
mov cx, word [es:bx+11]
mov word [BPB_BytsPerSec], cx
 
; count of clusters in FAT12 ((size_of_FAT*2)/3)
; mov ax, word [BPB_FATSz16]
; mov cx, word [BPB_BytsPerSec]
;end <Lrz> 18.11.2008
xor dx, dx
mul cx
shl ax, 1
mov cx, 3
div cx ; now ax - number of clusters in FAT12
mov word [end_of_FAT], ax
 
; load first FAT table
mov cx, 0x0002 ; startcyl,startsector ; TODO!!!!!
xor dx, dx ; starthead,drive
mov al, byte [BPB_FATSz16] ; no of sectors to read
add bx, word [BPB_BytsPerSec] ; es:bx -> data area
call boot_read_floppy
mov bx, 0xB000
 
; and copy them to extended memory
mov si, movedesc
mov [si+8*2+3], bh ; from
mov ax, word [BPB_BytsPerSec]
shr ax, 1 ; words per sector
mov cx, word [BPB_RsvdSecCnt]
add cx, word [BPB_FATSz16]
mul cx
push ax ; save to stack count of words in boot+FAT
xchg ax, cx
push es
push ds
pop es
mov ah, 0x87
int 0x15
pop es
test ah, ah
jz @f
sayerr_floppy:
mov dx, 0x3f2
mov al, 0
out dx, al
sayerr_memmove:
mov si, memmovefailed
jmp sayerr_plain
@@:
pop ax ; restore from stack count of words in boot+FAT
shl ax, 1 ; make bytes count from count of words
and eax, 0ffffh
add dword [si+8*3+2], eax
 
; copy first FAT to second copy
; TODO: BPB_NumFATs !!!!!
add bx, word [BPB_BytsPerSec] ; !!! TODO: may be need multiply by BPB_RsvdSecCnt !!!
mov byte [si+8*2+3], bh ; bx - begin of FAT
mov ax, word [BPB_BytsPerSec]
shr ax, 1 ; words per sector
mov cx, word [BPB_FATSz16]
mul cx
mov cx, ax ; cx - count of words in FAT
 
push es
push ds
pop es
mov ah, 0x87
int 0x15
pop es
test ah, ah
jnz sayerr_floppy
mov ax, cx
shl ax, 1
and eax, 0ffffh ; ax - count of bytes in FAT
add dword [si+8*3+2], eax
; reading RootDir
; TODO: BPB_NumFATs
add bx, ax
add bx, 100h
and bx, 0ff00h ; bx - place in buffer to write RootDir
push bx
 
mov bx, word [BPB_BytsPerSec]
shr bx, 5 ; divide bx by 32
mov ax, word [BPB_RootEntCnt]
xor dx, dx
div bx
push ax ; ax - count of RootDir sectors
 
mov ax, word [BPB_FATSz16]
xor cx, cx
mov cl, byte [BPB_NumFATs]
mul cx
add ax, word [BPB_RsvdSecCnt] ; ax - first sector of RootDir
 
mov word [FirstDataSector], ax
pop bx
push bx
add word [FirstDataSector], bx ; Begin of data region of floppy
; read RootDir
call conv_abs_to_THS
pop ax
pop bx ; place in buffer to write
push ax
call boot_read_floppy ; read RootDir into buffer
; copy RootDir
mov byte [si+8*2+3], bh ; from buffer
pop ax ; ax = count of RootDir sectors
mov cx, word [BPB_BytsPerSec]
mul cx
shr ax, 1
mov cx, ax ; count of words to copy
push es
push ds
pop es
mov ah, 0x87
int 0x15
pop es
 
mov ax, cx
shl ax, 1
and eax, 0ffffh ; ax - count of bytes in RootDir
add dword [si+8*3+2], eax ; add count of bytes copied
 
; Reading data clusters from floppy
mov byte [si+8*2+3], bh
push bx
 
mov di, 2 ; First data cluster
.read_loop:
mov bx, di
shr bx, 1 ; bx+di = di*1.5
jnc .even
test word [es:bx+di+0xB200], 0xFFF0 ; TODO: may not be 0xB200 !!!
jmp @f
.even:
test word [es:bx+di+0xB200], 0xFFF ; TODO: may not be 0xB200 !!!
 
@@:
jz .skip
; read cluster di
;.read:
;conv cluster di to abs. sector ax
; ax = (N-2) * BPB_SecPerClus + FirstDataSector
mov ax, di
sub ax, 2
xor bx, bx
mov bl, byte [BPB_SecPerClus]
mul bx
add ax, word [FirstDataSector]
call conv_abs_to_THS
pop bx
push bx
mov al, byte [BPB_SecPerClus] ; number of sectors in cluster
call boot_read_floppy
push es
push ds
pop es
pusha
;
mov ax, word [BPB_BytsPerSec]
xor cx, cx
mov cl, byte [BPB_SecPerClus]
mul cx
shr ax, 1 ; ax = (BPB_BytsPerSec * BPB_SecPerClus)/2
mov cx, ax ; number of words to copy (count words in cluster)
;
mov ah, 0x87
int 0x15 ; copy data
test ah, ah
popa
pop es
jnz sayerr_floppy
; skip cluster di
.skip:
mov ax, word [BPB_BytsPerSec]
xor cx, cx
mov cl, byte [BPB_SecPerClus]
mul cx
and eax, 0ffffh ; ax - count of bytes in cluster
add dword [si+8*3+2], eax
 
mov ax, word [end_of_FAT] ; max cluster number
pusha
; draw percentage
; total clusters: ax
; read clusters: di
xchg ax, di
mov cx, 100
mul cx
div di
aam
xchg al, ah
add ax, '00'
mov si, pros
cmp [si], ax
jz @f
mov [si], ax
call printplain
@@:
popa
inc di
cmp di, word [end_of_FAT] ; max number of cluster
jnz .read_loop
pop bx ; clear stack
 
ok_sys_on_floppy:
mov si, backspace2
call printplain
mov si, okt
call printplain
no_sys_on_floppy:
xor ax, ax ; reset drive
xor dx, dx
int 0x13
mov dx, 0x3f2 ; floppy motor off
mov al, 0
out dx, al
 
if defined extended_primary_loader
cmp [boot_dev], 1
jne no_sys_from_primary
; load kolibri.img using callback from primary loader
and word [movedesc + 24 + 2], 0
mov byte [movedesc + 24 + 4], 10h
; read in blocks of 64K until file is fully loaded
mov ax, 1
.repeat:
mov di, image_file_struct
call [bootcallback]
push cs
pop ds
push cs
pop es
cmp bx, 1
ja sayerr_badsect
push bx
mov si, movedesc
and word [si + 16 + 2], 0
mov byte [si + 16 + 4], 4
mov ah, 87h
mov cx, 8000h
int 15h
pop bx
test ah, ah
jnz sayerr_memmove
inc byte [si + 24 + 4]
test bx, bx
jz no_sys_from_primary
mov ax, 2
jmp .repeat
no_sys_from_primary:
end if
 
; SET GRAPHICS
 
xor ax, ax
mov es, ax
 
mov ax, [es:BOOT_VESA_MODE] ; vga & 320x200
mov bx, ax
cmp ax, 0x13
je setgr
cmp ax, 0x12
je setgr
mov ax, 0x4f02 ; Vesa
setgr:
int 0x10
test ah, ah
mov si, fatalsel
jnz v_mode_error
; set mode 0x12 graphics registers:
cmp bx, 0x12
jne gmok2
 
mov al, 0x05
mov dx, 0x03ce
push dx
out dx, al ; select GDC mode register
mov al, 0x02
inc dx
out dx, al ; set write mode 2
 
mov al, 0x02
mov dx, 0x03c4
out dx, al ; select VGA sequencer map mask register
mov al, 0x0f
inc dx
out dx, al ; set mask for all planes 0-3
 
mov al, 0x08
pop dx
out dx, al ; select GDC bit mask register
; for writes to 0x03cf
gmok2:
push ds
pop es
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/boot/booten.inc
0,0 → 1,101
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;======================================================================
;
; BOOT DATA
;
;======================================================================
 
$Revision: 2455 $
 
 
d80x25_bottom:
db 186,' KolibriOS is based on MenuetOS and comes with ABSOLUTELY '
db 'NO WARRANTY ',186
db 186,' See file COPYING for details '
db ' ',186
line_full_bottom
d80x25_bottom_num = 3
 
msg_apm db " APM x.x ", 0
novesa db "Display: EGA/CGA",13,10,0
s_vesa db "Version of VESA: "
.ver db "?.?",13,10,0
 
gr_mode db "Select a videomode: ",13,10,0
 
ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0
 
if defined extended_primary_loader
bdev db "Load ramdisk from [1-floppy; 2-kolibri.img]: ",0
else
bdev db "Load ramdisk from [1-floppy; 2-C:\kolibri.img (FAT32);"
db 13,10,186," "
db "3-use preloaded ram-image from kernel restart;"
db 13,10,186," "
db "4-create blank image]: ",0
end if
 
prnotfnd db "Fatal - Videomode not found.",0
 
not386 db "Fatal - CPU 386+ required.",0
fatalsel db "Fatal - Graphics mode not supported by hardware.",0
pres_key db "Press any key to choose a new videomode.",0
badsect db 13,10,186," Fatal - Bad sector. Replace floppy.",0
memmovefailed db 13,10,186," Fatal - Int 0x15 move failed.",0
okt db " ... OK"
linef db 13,10,0
diskload db "Loading diskette: 00 %",8,8,8,8,0
pros db "00"
backspace2 db 8,8,0
boot_dev db 0 ; 0=floppy, 1=hd
start_msg db "Press [abcd] to change settings, press [Enter] to continue booting",13,10,0
time_msg db " or wait "
time_str db " 5 seconds"
db " before automatical continuation",13,10,0
current_cfg_msg db "Current settings:",13,10,0
curvideo_msg db " [a] Videomode: ",0
 
mode0 db "320x200, EGA/CGA 256 colors",13,10,0
mode9 db "640x480, VGA 16 colors",13,10,0
 
usebd_msg db " [b] Add disks visible by BIOS:",0
on_msg db " on",13,10,0
off_msg db " off",13,10,0
 
preboot_device_msg db " [c] Floppy image: ",0
 
if defined extended_primary_loader
preboot_device_msgs dw 0,pdm1,pdm2,0
pdm1 db "real floppy",13,10,0
pdm2 db "C:\kolibri.img (FAT32)",13,10,0
else
preboot_device_msgs dw 0,pdm1,pdm2,pdm3
pdm1 db "real floppy",13,10,0
pdm2 db "C:\kolibri.img (FAT32)",13,10,0
pdm3 db "use already loaded image",13,10,0
pdm4 db "create blank image",13,10,0
end if
 
loading_msg db "Loading KolibriOS...",0
 
if ~ defined extended_primary_loader
save_quest db "Remember current settings? [y/n]: ",0
loader_block_error db "Bootloader data invalid, I cannot continue. Stopped.",0
end if
 
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿',13,10,0
_r1 db 186,' ³ 320x200 EGA/CGA 256 colors ³ ³',13,10,0
_r2 db 186,' ³ 640x480 VGA 16 colors ³ ³',13,10,0
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³',13,10,0
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ',13,10,0
 
remark1 db "Default values were selected to match most of configurations, but not all.",0
remark2 db "If the system does not boot, try to disable the item [b].",0
remarks dw remark1, remark2
num_remarks = 2
/kernel/branches/net/boot/bootet.inc
0,0 → 1,101
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;======================================================================
;
; BOOT DATA
;
;======================================================================
 
$Revision$
 
d80x25_bottom:
db 186,' KolibriOS pohineb MenuetOS ja kaasas IGASUGUSE GARANTI'
db 'ITA ',186
db 186,' Naha faili COPYING detailid '
db ' ',186
line_full_bottom
d80x25_bottom_num = 3
 
msg_apm db " APM x.x ", 0
novesa db "Ekraan: EGA/CGA",13,10,0
s_vesa db "Vesa versioon: "
.ver db "?.?",13,10,0
 
gr_mode db "Vali videomode: ",13,10,0
 
ask_bd db "Lisa kettad nahtavaks BIOS reziim V86? [1-jah, 2-no]: ",0
 
if defined extended_primary_loader
bdev db "Paigalda mäluketas [1-diskett; 2-kolibri.img]: ",0
else
bdev db "Paigalda mäluketas [1-diskett; 2-C:\kolibri.img (FAT32);"
db 13,10,186," "
db "3-kasuta eellaaditud mäluketast kerneli restardist;"
db 13,10,186," "
db "4-loo tühi pilt]: ",0
end if
 
prnotfnd db "Fataalne - Videoreziimi ei leitud.",0
 
not386 db "Fataalne - CPU 386+ on vajalik.",0
fatalsel db "Fataalne - Graafilist reziimi riistvara ei toeta.",0
pres_key db "Vajutage suvalist klahvi, et valida uus videomode.",0
badsect db 13,10,186," Fataalne - Vigane sektor. Asenda diskett.",0
memmovefailed db 13,10,186," Fataalne - Int 0x15 liigutamine ebaõnnestus.",0
okt db " ... OK"
linef db 13,10,0
diskload db "Loen disketti: 00 %",8,8,8,8,0
pros db "00"
backspace2 db 8,8,0
boot_dev db 0 ; 0=floppy, 1=hd
start_msg db "Vajuta [abcd] seadete muutmiseks, vajuta [Enter] laadimise jätkamiseks",13,10,0
time_msg db " või oota "
time_str db " 5 sekundit"
db " automaatseks jätkamiseks",13,10,0
current_cfg_msg db "Praegused seaded:",13,10,0
curvideo_msg db " [a] Videoreziim: ",0
 
mode0 db "320x200, EGA/CGA 256 värvi",0
mode9 db "640x480, VGA 16 värvi",0
 
usebd_msg db " [b] Lisa kettad nahtavaks BIOS:",0
on_msg db " sees",13,10,0
off_msg db " väljas",13,10,0
 
preboot_device_msg db " [c] Disketi kujutis: ",0
 
if defined extended_primary_loader
preboot_device_msgs dw 0,pdm1,pdm2,0
pdm1 db "reaalne diskett",13,10,0
pdm2 db "kolibri.img",13,10,0
else
preboot_device_msgs dw 0,pdm1,pdm2,pdm3
pdm1 db "reaalne diskett",13,10,0
pdm2 db "C:\kolibri.img (FAT32)",13,10,0
pdm3 db "kasuta juba laaditud kujutist",13,10,0
pdm4 db "loo tühi pilt",13,10,0
end if
 
loading_msg db "Laadin KolibriOS...",0
 
if ~ defined extended_primary_loader
save_quest db "Jäta meelde praegused seaded? [y/n]: ",0
loader_block_error db "Alglaaduri andmed vigased, ei saa jätkata. Peatatud.",0
end if
 
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿',13,10,0
_r1 db 186,' ³ 320x200 EGA/CGA 256 colors ³ ³',13,10,0
_r2 db 186,' ³ 640x480 VGA 16 colors ³ ³',13,10,0
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³',13,10,0
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ',13,10,0
 
remark1 db "Vaikimisi maaratud vaartused on valitud mugavuse enamikes, kuid mitte koik.",0
remark2 db "Kui susteem ei kaivitu, proovige lulitada kirje [b].",0
remarks dw remark1, remark2
num_remarks = 2
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/boot/bootge.inc
0,0 → 1,101
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;======================================================================
;
; BOOT DATA
;
;======================================================================
 
$Revision$
 
 
d80x25_bottom:
db 186,' KolibriOS basiert auf MenuetOS und wird ohne jegliche '
db ' Garantie vertrieben ',186
db 186,' Details stehen in der Datei COPYING '
db ' ',186
line_full_bottom
d80x25_bottom_num = 3
 
msg_apm db " APM x.x ", 0
novesa db "Anzeige: EGA/CGA ",13,10,0
s_vesa db "Vesa-Version: "
.ver db "?.?",13,10,0
 
gr_mode db "Wahlen Sie einen videomode: ",13,10,0
 
ask_bd db "Add-Festplatten sichtbar BIOS in V86-Modus emuliert? [1-ja, 2 nein]: ",0
 
if defined extended_primary_loader
bdev db "Lade die Ramdisk von [1-Diskette; 2-kolibri.img]: ",0
else
bdev db "Lade die Ramdisk von [1-Diskette; 2-C:\kolibri.img (FAT32);"
db 13,10,186," "
db "3-benutze ein bereits geladenes Kernel image;"
db 13,10,186," "
db "4-create blank image]: ",0
end if
 
prnotfnd db "Fatal - Videomodus nicht gefunden.",0
 
not386 db "Fatal - CPU 386+ benoetigt.",0
fatalsel db "Fatal - Grafikmodus nicht unterstuetzt.",0
pres_key db "Drucken Sie eine beliebige Taste, um eine neue videomode wahlen.",0
badsect db 13,10,186," Fatal - Sektorfehler, Andere Diskette neutzen.",0
memmovefailed db 13,10,186," Fatal - Int 0x15 Fehler.",0
okt db " ... OK"
linef db 13,10,0
diskload db "Lade Diskette: 00 %",8,8,8,8,0
pros db "00"
backspace2 db 8,8,0
boot_dev db 0 ; 0=floppy, 1=hd
start_msg db "Druecke [abcd], um die Einstellungen zu aendern, druecke [Enter] zum starten",13,10,0
time_msg db " oder warte "
time_str db " 5 Sekunden"
db " bis zum automatischen Start",13,10,0
current_cfg_msg db "Aktuelle Einstellungen:",13,10,0
curvideo_msg db " [a] Videomodus: ",0
 
mode0 db "320x200, EGA/CGA 256 colors",13,10,0
mode9 db "640x480, VGA 16 colors",13,10,0
 
usebd_msg db " [b] Add-Festplatten sichtbar durch das BIOS:",0
on_msg db " an",13,10,0
off_msg db " aus",13,10,0
 
preboot_device_msg db " [c] Diskettenimage: ",0
 
if defined extended_primary_loader
preboot_device_msgs dw 0,pdm1,pdm2,0
pdm1 db "Echte Diskette",13,10,0
pdm2 db "kolibri.img",13,10,0
else
preboot_device_msgs dw 0,pdm1,pdm2,pdm3
pdm1 db "Echte Diskette",13,10,0
pdm2 db "C:\kolibri.img (FAT32)",13,10,0
pdm3 db "Nutze bereits geladenes Image",13,10,0
pdm4 db "create blank image",13,10,0
end if
 
loading_msg db "Lade KolibriOS...",0
 
if ~ defined extended_primary_loader
save_quest db "Aktuelle Einstellungen speichern? [y/n]: ",0
loader_block_error db "Bootloader Daten ungueltig, Kann nicht fortfahren. Angehalten.",0
end if
 
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿',13,10,0
_r1 db 186,' ³ 320x200 EGA/CGA 256 colors ³ ³',13,10,0
_r2 db 186,' ³ 640x480 VGA 16 colors ³ ³',13,10,0
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³',13,10,0
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ',13,10,0
 
remark1 db "Die Standardwerte sind fur die meisten gewahlt, aber nicht fur jedermann.",0
remark2 db "Wenn das System nicht bootet, versuchen, das Element [b] deaktivieren.",0
remarks dw remark1, remark2
num_remarks = 2
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/boot/bootru.inc
0,0 → 1,101
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;=================================================================
;
; BOOT DATA
;
;=================================================================
 
$Revision$
 
 
d80x25_bottom:
db 186,' KolibriOS ®á­®¢ ­  ­  MenuetOS ¨ … …„Ž‘’€‚‹Ÿ…’ ˆ'
db 'Š€Šˆ• ƒ€A’ˆ‰. ',186
db 186,' ®¤à®¡­¥¥ ᬮâà¨â¥ ¢ ä ©«¥ COPYING.TXT '
db ' ',186
line_full_bottom
d80x25_bottom_num = 3
 
msg_apm db " APM x.x ", 0
novesa db "‚¨¤¥®ª àâ : EGA/CGA",13,10,0
s_vesa db "‚¥àá¨ï VESA: "
.ver db "?.?",13,10,0
 
gr_mode db "‚ë¡¥à¨â¥ ¢¨¤¥®à¥¦¨¬: ",13,10,0
 
ask_bd db "„®¡ ¢¨âì ¤¨áª¨, ¢¨¤¨¬ë¥ ç¥à¥§ BIOS ¢ ०¨¬¥ V86? [1-¤ , 2-­¥â]: ",0
 
if defined extended_primary_loader
bdev db "‡ £à㧨âì ®¡à § ¨§ [1-¤¨áª¥â ; 2-kolibri.img ¨§ ¯ ¯ª¨ § £à㧪¨]: ",0
else
bdev db "‡ £à㧨âì ®¡à § ¨§ [1-¤¨áª¥â ; 2-C:\kolibri.img (FAT32);"
db 13,10,186," "
db "3-¨á¯®«ì§®¢ âì 㦥 § £à㦥­­ë© ®¡à §;"
db 13,10,186," "
db "4-ᮧ¤ âì ç¨áâë© ®¡à §]: ",0
end if
 
prnotfnd db "Žè¨¡ª  - ‚¨¤¥®à¥¦¨¬ ­¥ ­ ©¤¥­.",0
 
not386 db "Žè¨¡ª  - ’ॡã¥âáï ¯à®æ¥áá®à 386+.",0
fatalsel db "Žè¨¡ª  - ‚ë¡à ­­ë© ¢¨¤¥®à¥¦¨¬ ­¥ ¯®¤¤¥à¦¨¢ ¥âáï.",0
pres_key db " ¦¨¬¨â¥ «î¡ãî ª« ¢¨èã, ¤«ï ¯¥à¥å®¤  ¢ ¢ë¡®à ०¨¬®¢.",0
badsect db 13,10,186," Žè¨¡ª  - „¨áª¥â  ¯®¢à¥¦¤¥­ . ®¯à®¡ã©â¥ ¤àã£ãî.",0
memmovefailed db 13,10,186," Žè¨¡ª  - Int 0x15 move failed.",0
okt db " ... OK"
linef db 13,10,0
diskload db "‡ £à㧪  ¤¨áª¥âë: 00 %",8,8,8,8,0
pros db "00"
backspace2 db 8,8,0
boot_dev db 0
start_msg db " ¦¬¨â¥ [abcd] ¤«ï ¨§¬¥­¥­¨ï ­ áâ஥ª, [Enter] ¤«ï ¯à®¤®«¦¥­¨ï § £à㧪¨",13,10,0
time_msg db " ¨«¨ ¯®¤®¦¤¨â¥ "
time_str db " 5 ᥪ㭤 "
db " ¤®  ¢â®¬ â¨ç¥áª®£® ¯à®¤®«¦¥­¨ï",13,10,0
current_cfg_msg db "’¥ªã騥 ­ áâனª¨:",13,10,0
curvideo_msg db " [a] ‚¨¤¥®à¥¦¨¬: ",0
 
mode0 db "320x200, EGA/CGA 256 梥⮢",13,10,0
mode9 db "640x480, VGA 16 梥⮢",13,10,0
 
usebd_msg db " [b] „®¡ ¢¨âì ¤¨áª¨, ¢¨¤¨¬ë¥ ç¥à¥§ BIOS:",0
on_msg db " ¢ª«",13,10,0
off_msg db " ¢ëª«",13,10,0
 
preboot_device_msg db " [c] Ž¡à § ¤¨áª¥âë: ",0
 
if defined extended_primary_loader
preboot_device_msgs dw 0,pdm1,pdm2,0
pdm1 db "­ áâ®ïé ï ¤¨áª¥â ",13,10,0
pdm2 db "kolibri.img ¨§ ¯ ¯ª¨ § £à㧪¨",13,10,0
else
preboot_device_msgs dw 0,pdm1,pdm2,pdm3,pdm4
pdm1 db "­ áâ®ïé ï ¤¨áª¥â ",13,10,0
pdm2 db "C:\kolibri.img (FAT32)",13,10,0
pdm3 db "¨á¯®«ì§®¢ âì 㦥 § £à㦥­­ë© ®¡à §",13,10,0
pdm4 db "ᮧ¤ âì ç¨áâë© ®¡à §",13,10,0
end if
 
loading_msg db "ˆ¤ñâ § £à㧪  KolibriOS...",0
 
if ~ defined extended_primary_loader ; saving not supported in this case
save_quest db "‡ ¯®¬­¨âì ⥪ã騥 ­ áâனª¨? [y/n]: ",0
loader_block_error db "Žè¨¡ª  ¢ ¤ ­­ëå ­ ç «ì­®£® § £àã§ç¨ª , ¯à®¤®«¦¥­¨¥ ­¥¢®§¬®¦­®.",0
end if
 
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ',13,10,0
_r1 db 186,' ³ 320x200 EGA/CGA 256 梥⮢ ³ ³ ',13,10,0
_r2 db 186,' ³ 640x480 VGA 16 梥⮢ ³ ³ ',13,10,0
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³ ',13,10,0
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ',13,10,0
 
remark1 db "‡­ ç¥­¨ï ¯® 㬮«ç ­¨î ¢ë¡à ­ë ¤«ï 㤮¡á⢠ ¡®«ì設á⢠, ­® ­¥ ¢á¥å.",0
remark2 db "…᫨ 㠂 á ­¥ £à㧨âáï á¨á⥬ , ¯®¯à®¡ã©â¥ ®âª«îç¨âì ¯ã­ªâ [b].",0
remarks dw remark1, remark2
num_remarks = 2
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/boot/bootsp.inc
0,0 → 1,103
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;======================================================================
;
; BOOT DATA
;
;======================================================================
 
; Para modificar ‚ste archivo es necesario abrirlo con codificaci¢n CP850
 
$Revision: 2455 $
 
 
d80x25_bottom:
db 186,' KolibriOS est  basado en MenuetOS y viene ABSOLUTAMENTE '
db 'SIN GARANT¡A ',186
db 186,' Lee el archivo COPYING por m s detalles '
db ' ',186
line_full_bottom
d80x25_bottom_num = 3
 
msg_apm db " APM x.x ", 0
novesa db "Monitor: EGA/CGA",13,10,0
s_vesa db "Versi¢n de VESA: "
.ver db "?.?",13,10,0
 
gr_mode db "Selecciona un modo de video: ",13,10,0
 
ask_bd db "¨Agregar discos visibles por el BIOS emulados en modo V86? [1-si, 2-no]: ",0
 
if defined extended_primary_loader
bdev db "Cargar unidad ram desde [1-disquete; 2-kolibri.img]: ",0
else
bdev db "Cargar unidad ram desde [1-disquete; 2-C:\kolibri.img (FAT32);"
db 13,10,186," "
db "3-usar imagen precargada en el reinicio del n£cleo;"
db 13,10,186," "
db "4-crear imagen vac¡a]: ",0
end if
 
prnotfnd db "Fatal - Modo de video no encontrado.",0
 
not386 db "Fatal - CPU 386+ requerido.",0
fatalsel db "Fatal - Modo de gr ficos no soportado por hardware.",0
pres_key db "Presiona una tecla para seleccionar otro modo de video.",0
badsect db 13,10,186," Fatal - Sector mal. Reemplaze el disquete.",0
memmovefailed db 13,10,186," Fatal - Int 0x15 move failed.",0
okt db " ... BIEN"
linef db 13,10,0
diskload db "Cargando disquete: 00 %",8,8,8,8,0
pros db "00"
backspace2 db 8,8,0
boot_dev db 0 ; 0=floppy, 1=hd
start_msg db "Presiona [abcd] para cambiar la configuraci¢n, [Enter] para continuar",13,10,0
time_msg db " o espera "
time_str db " 5 segundos"
db " para que inicie autom ticamente",13,10,0
current_cfg_msg db "Configuraci¢n actual:",13,10,0
curvideo_msg db " [a] Modo de video: ",0
 
mode0 db "320x200, EGA/CGA 256 colores",13,10,0
mode9 db "640x480, VGA 16 colores",13,10,0
 
usebd_msg db " [b] Agregar discos visibles por el BIOS:",0
on_msg db " activado",13,10,0
off_msg db " desactivado",13,10,0
 
preboot_device_msg db " [c] Imagen de disquete: ",0
 
if defined extended_primary_loader
preboot_device_msgs dw 0,pdm1,pdm2,0
pdm1 db "disquete real",13,10,0
pdm2 db "C:\kolibri.img (FAT32)",13,10,0
else
preboot_device_msgs dw 0,pdm1,pdm2,pdm3
pdm1 db "disquete real",13,10,0
pdm2 db "C:\kolibri.img (FAT32)",13,10,0
pdm3 db "usar imagen ya cargada",13,10,0
pdm4 db "crear imagen vac¡a",13,10,0
end if
 
loading_msg db "Cargando KolibriOS...",0
 
if ~ defined extended_primary_loader
save_quest db "¨Recordar configuraci¢n actual? [s/n]: ",0
loader_block_error db "Bootloader inv lido, no puedo continuar. Detenido.",0
end if
 
_st db 186,' ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿',13,10,0
_r1 db 186,' ³ 320x200 EGA/CGA 256 colores ³ ³',13,10,0
_r2 db 186,' ³ 640x480 VGA 16 colores ³ ³',13,10,0
_rs db 186,' ³ ????x????@?? SVGA VESA ³ ³',13,10,0
_bt db 186,' ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ',13,10,0
 
remark1 db "Los valores por defecto puede que no funcionen en algunas configuraciones.",0
remark2 db "Si el sistema no inicia, prueba deshabilitar la opci¢n [b].",0
remarks dw remark1, remark2
num_remarks = 2
/kernel/branches/net/boot/bootstr.inc
0,0 → 1,63
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
; boot data: common strings (for all languages)
macro line_full_top {
db 201
times 78 db 205
db 187
}
macro line_full_bottom {
db 200
times 78 db 205
db 188
}
macro line_half {
db 186,' '
times 76 db 0xc4
db ' ',186
}
macro line_space {
db 186
times 78 db 32
db 186
}
d80x25_top:
line_full_top
cur_line_pos = 75
store byte ' ' at d80x25_top+cur_line_pos+1
rev_var = __REV__
while rev_var > 0
store byte rev_var mod 10 + '0' at d80x25_top+cur_line_pos
cur_line_pos = cur_line_pos - 1
rev_var = rev_var / 10
end while
store byte ' ' at d80x25_top+cur_line_pos
store dword ' SVN' at d80x25_top+cur_line_pos-4
 
space_msg:
line_space
verstr:
; line_space
; version string
db 186,32
repeat 78
load a byte from version+%-1
if a = 13
break
end if
db a
end repeat
repeat 78 - ($-verstr)
db ' '
end repeat
db 32,186
line_half
d80x25_top_num = 4
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/boot/bootvesa.inc
0,0 → 1,794
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
struc VBE_VGAInfo {
.VESASignature dd ? ; char
.VESAVersion dw ? ; short
.OemStringPtr dd ? ; char *
.Capabilities dd ? ; ulong
.VideoModePtr dd ? ; ulong
.TotalMemory dw ? ; short
; VBE 2.0+
.OemSoftwareRev db ? ; short
.OemVendorNamePtr dw ? ; char *
.OemProductNamePtr dw ? ; char *
.OemProductRevPtr dw ? ; char *
.reserved rb 222 ; char
.OemData rb 256 ; char
}
 
struc VBE_ModeInfo {
.ModeAttributes dw ? ; short
.WinAAttributes db ? ; char
.WinBAttributes db ? ; char
.WinGranularity dw ? ; short
.WinSize dw ? ; short
.WinASegment dw ? ; ushort
.WinBSegment dw ? ; ushort
.WinFuncPtr dd ? ; void *
.BytesPerScanLine dw ? ; short
.XRes dw ? ; short
.YRes dw ? ; short
.XCharSize db ? ; char
.YCharSize db ? ; char
.NumberOfPlanes db ? ; char
.BitsPerPixel db ? ; char
.NumberOfBanks db ? ; char
.MemoryModel db ? ; char
.BankSize db ? ; char
.NumberOfImagePages db ? ; char
.res1 db ? ; char
.RedMaskSize db ? ; char
.RedFieldPosition db ? ; char
.GreenMaskSize db ? ; char
.GreenFieldPosition db ? ; char
.BlueMaskSize db ? ; char
.BlueFieldPosition db ? ; char
.RsvedMaskSize db ? ; char
.RsvedFieldPosition db ? ; char
.DirectColorModeInfo db ? ; char ; MISSED IN THIS TUTORIAL!! SEE ABOVE
; VBE 2.0+
.PhysBasePtr dd ? ; ulong
.OffScreenMemOffset dd ? ; ulong
.OffScreenMemSize dw ? ; short
; VBE 3.0+
.LinbytesPerScanLine dw ? ; short
.BankNumberOfImagePages db ? ; char
.LinNumberOfImagePages db ? ; char
.LinRedMaskSize db ? ; char
.LinRedFieldPosition db ? ; char
.LingreenMaskSize db ? ; char
.LinGreenFieldPosition db ? ; char
.LinBlueMaskSize db ? ; char
.LinBlueFieldPosition db ? ; char
.LinRsvdMaskSize db ? ; char
.LinRsvdFieldPosition db ? ; char
.MaxPixelClock dd ? ; ulong
.res2 rb 190 ; char
}
 
virtual at $A000
vi VBE_VGAInfo
mi VBE_ModeInfo
modes_table:
end virtual
cursor_pos dw 0 ;âðåìåííîå õðàíåíèå êóðñîðà.
home_cursor dw 0 ;current shows rows a table
end_cursor dw 0 ;end of position current shows rows a table
scroll_start dw 0 ;start position of scroll bar
scroll_end dw 0 ;end position of scroll bar
long_v_table equ 9 ;long of visible video table
size_of_step equ 10
scroll_area_size equ (long_v_table-2)
int2str:
dec bl
jz @f
xor edx, edx
div ecx
push edx
call int2str
pop eax
@@:
or al, 0x30
mov [ds:di], al
inc di
ret
 
int2strnz:
cmp eax, ecx
jb @f
xor edx, edx
div ecx
push edx
call int2strnz
pop eax
@@:
or al, 0x30
mov [es:di], al
inc di
ret
 
;-------------------------------------------------------
;Write message about incorrect v_mode and write message about jmp on swith v_mode
v_mode_error:
_setcursor 19,2
mov si, fatalsel
call printplain
_setcursor 20,2
mov si, pres_key
call printplain
xor eax, eax
int 16h
jmp cfgmanager.d
;-------------------------------------------------------
;
 
 
 
;-------------------------------------------------------
print_vesa_info:
_setcursor 5,2
 
mov [es:vi.VESASignature], 'VBE2'
mov ax, 0x4F00
mov di, vi ;0xa000
int 0x10
or ah, ah
jz @f
mov [es:vi.VESASignature], 'VESA'
mov ax, $4F00
mov di, vi
int 0x10
or ah, ah
jnz .exit
@@:
cmp [es:vi.VESASignature], 'VESA'
jne .exit
cmp [es:vi.VESAVersion], 0x0100
jb .exit
jmp .vesaok2
 
.exit:
mov si, novesa
call printplain
ret
 
.vesaok2:
mov ax, [es:vi.VESAVersion]
add ax, '00'
 
mov [s_vesa.ver], ah
mov [s_vesa.ver+2], al
mov si, s_vesa
call printplain
 
_setcursor 4,2
mov si, word[es:vi.OemStringPtr]
mov di, si
 
push ds
mov ds, word[es:vi.OemStringPtr+2]
call printplain
pop ds
 
ret
;-----------------------------------------------------------------------------
 
calc_vmodes_table:
pushad
 
; push 0
; pop es
 
lfs si, [es:vi.VideoModePtr]
 
mov bx, modes_table
;save no vesa mode of work 320x200, EGA/CGA 256 梥⮢ and 640x480, VGA 16 梥⮢
mov word [es:bx], 640
mov word [es:bx+2], 480
mov word [es:bx+6], 0x13
mov word [es:bx+10], 640
mov word [es:bx+12], 480
mov word [es:bx+16], 0x12
add bx, 20
.next_mode:
mov cx, word [fs:si]; mode number
cmp cx, -1
je .modes_ok.2
 
mov ax, 0x4F01
mov di, mi
int 0x10
 
or ah, ah
jnz .modes_ok.2;vesa_info.exit
 
test [es:mi.ModeAttributes], 00000001b ;videomode support ?
jz @f
test [es:mi.ModeAttributes], 00010000b ;picture ?
jz @f
test [es:mi.ModeAttributes], 10000000b ;LFB ?
jz @f
 
cmp [es:mi.BitsPerPixel], 24 ;It show only videomodes to have support 24 and 32 bpp
jb @f
 
; cmp [es:mi.BitsPerPixel],16
; jne .l0
; cmp [es:mi.GreenMaskSize],5
; jne .l0
; mov [es:mi.BitsPerPixel],15
 
 
.l0:
cmp [es:mi.XRes], 640
jb @f
cmp [es:mi.YRes], 480
jb @f
; cmp [es:mi.BitsPerPixel],8
; jb @f
 
mov ax, [es:mi.XRes]
mov [es:bx+0], ax ; +0[2] : resolution X
mov ax, [es:mi.YRes]
mov [es:bx+2], ax ; +2[2] : resolution Y
mov ax, [es:mi.ModeAttributes]
mov [es:bx+4], ax ; +4[2] : attributes
 
cmp [s_vesa.ver], '2'
; jb .lp1
jb @f ; We do not use Vesa 1.2 mode is now
 
or cx, 0x4000 ; use LFB
.lp1:
mov [es:bx+6], cx ; +6 : mode number
movzx ax, byte [es:mi.BitsPerPixel]
mov word [es:bx+8], ax ; +8 : bits per pixel
add bx, size_of_step ; size of record
 
@@:
add si, 2
jmp .next_mode
 
.modes_ok.2:
 
mov word[es:bx], -1 ;end video table
mov word[end_cursor], bx ;save end cursor position
;;;;;;;;;;;;;;;;;;
;Sort array
; mov si,modes_table
;.new_mode:
; mov ax,word [es:si]
; cmp ax,-1
; je .exxit
; add ax,word [es:si+2]
; add ax,word [es:si+8]
; mov bp,si
;.again:
; add bp,12
; mov bx,word [es:bp]
; cmp bx,-1
; je .exit
; add bx,word [es:bp+2]
; add bx,word [es:bp+8]
;
; cmp ax,bx
; ja .loops
; jmp .again
;.loops:
; push dword [es:si]
; push dword [es:si+4]
; push dword [es:si+8]
; push dword [es:bp]
; push dword [es:bp+4]
; push dword [es:bp+8]
;
; pop dword [es:si+8]
; pop dword [es:si+4]
; pop dword [es:si]
; pop dword [es:bp+8]
; pop dword [es:bp+4]
; pop dword [es:bp]
; jmp .new_mode
;
;.exit: add si,12
; jmp .new_mode
;.exxit:
popad
ret
 
;-----------------------------------------------------------------------------
 
draw_current_vmode:
push 0
pop es
 
mov si, word [cursor_pos]
 
cmp word [es:si+6], 0x12
je .no_vesa_0x12
 
cmp word [es:si+6], 0x13
je .no_vesa_0x13
 
if defined extended_primary_loader
mov di, config_file_variables
else
mov di, loader_block_error
end if
movzx eax, word[es:si+0]
mov ecx, 10
call int2strnz
mov byte[es:di], 'x'
inc di
movzx eax, word[es:si+2]
call int2strnz
mov byte[es:di], 'x'
inc di
movzx eax, word[es:si+8]
call int2strnz
mov dword[es:di], 0x00000d0a
if defined extended_primary_loader
mov si, config_file_variables
else
mov si, loader_block_error
end if
push ds
push es
pop ds
call printplain
pop ds
ret
.no_vesa_0x13:
mov si, mode0
jmp .print
.no_vesa_0x12:
mov si, mode9
.print:
call printplain
ret
;-----------------------------------------------------------------------------
check_first_parm:
if defined extended_primary_loader
mov cx, [number_vm]
jcxz .novbemode
mov si, modes_table
.findvbemode:
cmp [es:si+6], cx
jnz @f
cmp word [es:si+8], 32
je .ok_found_mode
cmp word [es:si+8], 24
je .ok_found_mode
@@:
add si, size_of_step
cmp word [es:si], -1
jnz .findvbemode
.novbemode:
mov ax, [x_save]
test ax, ax
jz .zerro
mov bx, [y_save]
mov si, modes_table
call .loops
test ax, ax
jz .ok_found_mode
else
mov si, word [preboot_graph]
test si, si
jnz .no_zero ;if no zero
end if
.zerro:
; mov ax,modes_table
; mov word [cursor_pos],ax
; mov word [home_cursor],ax
; mov word [preboot_graph],ax
;SET default video of mode first probe will fined a move of work 1024x768@32
 
mov ax, 1024
mov bx, 768
mov si, modes_table
call .loops
test ax, ax
jz .ok_found_mode
mov ax, 800
mov bx, 600
mov si, modes_table
call .loops
test ax, ax
jz .ok_found_mode
mov ax, 640
mov bx, 480
mov si, modes_table
call .loops
test ax, ax
jz .ok_found_mode
 
mov si, modes_table
if ~ defined extended_primary_loader
jmp .ok_found_mode
 
 
 
.no_zero:
mov bp, word [number_vm]
cmp bp, word [es:si+6]
jz .ok_found_mode
mov ax, word [x_save]
mov bx, word [y_save]
mov si, modes_table
call .loops
test ax, ax
jz .ok_found_mode
 
mov si, modes_table
; cmp ax,modes_table
; jb .zerro ;check on correct if bellow
; cmp ax,word [end_cursor]
; ja .zerro ;check on correct if anymore
end if
 
.ok_found_mode:
mov word [home_cursor], si
; mov word [cursor_pos],si
mov word [preboot_graph], si
mov ax, si
 
mov ecx, long_v_table
 
.loop:
add ax, size_of_step
cmp ax, word [end_cursor]
jae .next_step
loop .loop
.next_step:
sub ax, size_of_step*long_v_table
cmp ax, modes_table
jae @f
mov ax, modes_table
@@:
 
mov word [home_cursor], ax
mov si, [preboot_graph]
mov word [cursor_pos], si
 
push word [es:si]
pop word [x_save]
push word [es:si+2]
pop word [y_save]
push word [es:si+6]
pop word [number_vm]
 
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;
.loops:
cmp ax, word [es:si]
jne .next
cmp bx, word [es:si+2]
jne .next
cmp word [es:si+8], 32
je .ok
cmp word [es:si+8], 24
je .ok
.next:
add si, size_of_step
cmp word [es:si], -1
je .exit
jmp .loops
.ok:
xor ax, ax
ret
.exit:
or ax, -1
ret
 
 
;-----------------------------------------------------------------------------
 
;default_vmode:
;-----------------------------------------------------------------------------
draw_vmodes_table:
_setcursor 9, 2
mov si, gr_mode
call printplain
 
mov si, _st
call printplain
 
push word [cursor_pos]
pop ax
push word [home_cursor]
pop si
mov cx, si
 
cmp ax, si
je .ok
jb .low
 
 
add cx, size_of_step*long_v_table
cmp ax, cx
jb .ok
sub cx, size_of_step*long_v_table
add cx, size_of_step
cmp cx, word[end_cursor]
jae .ok
add si, size_of_step
push si
pop word [home_cursor]
jmp .ok
 
 
.low:
sub cx, size_of_step
cmp cx, modes_table
jb .ok
push cx
push cx
pop word [home_cursor]
pop si
 
 
.ok:
; calculate scroll position
push si
mov ax, [end_cursor]
sub ax, modes_table
mov bx, size_of_step
cwd
div bx
mov si, ax ; si = size of list
mov ax, [home_cursor]
sub ax, modes_table
cwd
div bx
mov di, ax
mov ax, scroll_area_size*long_v_table
cwd
div si
test ax, ax
jnz @f
inc ax
@@:
cmp al, scroll_area_size
jb @f
mov al, scroll_area_size
@@:
mov cx, ax
; cx = scroll height
; calculate scroll pos
xor bx, bx ; initialize scroll pos
sub al, scroll_area_size+1
neg al
sub si, long_v_table-1
jbe @f
mul di
div si
mov bx, ax
@@:
inc bx
imul ax, bx, size_of_step
add ax, [home_cursor]
mov [scroll_start], ax
imul cx, size_of_step
add ax, cx
mov [scroll_end], ax
pop si
mov bp, long_v_table ;show rows
.@@_next_bit:
;clear cursor
mov ax, ' '
mov word[ds:_r1+21], ax
mov word[ds:_r1+50], ax
 
mov word[ds:_r2+21], ax
mov word[ds:_r2+45], ax
 
mov word[ds:_rs+21], ax
mov word[ds:_rs+46], ax
; draw string
cmp word [es:si+6], 0x12
je .show_0x12
cmp word [es:si+6], 0x13
je .show_0x13
 
movzx eax, word[es:si]
cmp ax, -1
je .@@_end
mov di, _rs+23
mov ecx, 10
mov bl, 4
call int2str
movzx eax, word[es:si+2]
inc di
mov bl, 4
call int2str
 
movzx eax, word[es:si+8]
inc di
mov bl, 2
call int2str
 
cmp si, word [cursor_pos]
jne .next
;draw cursor
mov word[ds:_rs+21], '>>'
mov word[ds:_rs+46], '<<'
 
 
.next:
push si
mov si, _rs
.@@_sh:
; add to the string pseudographics for scrollbar
pop bx
push bx
mov byte [si+53], ' '
cmp bx, [scroll_start]
jb @f
cmp bx, [scroll_end]
jae @f
mov byte [si+53], 0xDB ; filled bar
@@:
push bx
add bx, size_of_step
cmp bx, [end_cursor]
jnz @f
mov byte [si+53], 31 ; 'down arrow' symbol
@@:
sub bx, [home_cursor]
cmp bx, size_of_step*long_v_table
jnz @f
mov byte [si+53], 31 ; 'down arrow' symbol
@@:
pop bx
cmp bx, [home_cursor]
jnz @f
mov byte [si+53], 30 ; 'up arrow' symbol
@@:
call printplain
pop si
add si, size_of_step
 
dec bp
jnz .@@_next_bit
 
.@@_end:
mov si, _bt
call printplain
ret
.show_0x13:
push si
 
cmp si, word [cursor_pos]
jne @f
mov word[ds:_r1+21], '>>'
mov word[ds:_r1+50], '<<'
@@:
mov si, _r1
jmp .@@_sh
.show_0x12:
push si
cmp si, word [cursor_pos]
jne @f
 
mov word[ds:_r2+21], '>>'
mov word[ds:_r2+45], '<<'
@@:
mov si, _r2
jmp .@@_sh
 
;-----------------------------------------------------------------------------
;Clear arrea of current video page (0xb800)
clear_vmodes_table:
pusha
; draw frames
push es
push 0xb800
pop es
mov di, 1444
xor ax, ax
mov ah, 1*16+15
mov cx, 70
mov bp, 12
.loop_start:
rep stosw
mov cx, 70
add di, 20
dec bp
jns .loop_start
pop es
popa
ret
 
;-----------------------------------------------------------------------------
 
set_vmode:
push 0 ;0;x1000
pop es
 
mov si, word [preboot_graph] ;[preboot_graph]
mov cx, word [es:si+6] ; number of mode
 
mov ax, word [es:si+0] ; resolution X
mov bx, word [es:si+2] ; resolution Y
 
 
mov word [es:BOOT_X_RES], ax ; resolution X
mov word [es:BOOT_Y_RES], bx ; resolution Y
mov word [es:BOOT_VESA_MODE], cx ; number of mode
 
cmp cx, 0x12
je .mode0x12_0x13
cmp cx, 0x13
je .mode0x12_0x13
 
 
; cmp byte [s_vesa.ver], '2'
; jb .vesa12
 
; VESA 2 and Vesa 3
 
mov ax, 0x4f01
and cx, 0xfff
mov di, mi;0xa000
int 0x10
; LFB
mov eax, [es:mi.PhysBasePtr];di+0x28]
mov [es:BOOT_LFB], eax
; ---- vbe voodoo
BytesPerLine equ 0x10
mov ax, [es:di+BytesPerLine]
mov [es:BOOT_PITCH], ax
; BPP
cmp [es:mi.BitsPerPixel], 16
jne .l0
cmp [es:mi.GreenMaskSize], 5
jne .l0
mov [es:mi.BitsPerPixel], 15
.l0:
mov al, byte [es:di+0x19]
mov [es:BOOT_BPP], al
jmp .exit
 
.mode0x12_0x13:
mov byte [es:BOOT_BPP], 32
or dword [es:BOOT_LFB], 0xFFFFFFFF; 0x800000
 
 
; VESA 1.2 PM BANK SWITCH ADDRESS
 
;.vesa12:
; mov ax, 0x4f0A
; xor bx, bx
; int 0x10
; xor eax, eax
; xor ebx, ebx
; mov ax, es
; shl eax, 4
; mov bx, di
; add eax, ebx
; movzx ebx, word[es:di]
; add eax, ebx
; push 0x0000
; pop es
; mov [es:0x9014], eax
.exit:
ret
 
;=============================================================================
;=============================================================================
;=============================================================================
 
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/boot/et.inc
0,0 → 1,16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
; Full ASCII code font
; only õ and ä added
; Kaitz
ET_FNT:
fontfile file "ETFONT.FNT"
 
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/boot/parsers.inc
0,0 → 1,170
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 2288 $
 
; All parsers are called with ds:si -> value of the variable,
; possibly with spaces before, and dx = limit of config file.
 
; Three subroutines parse_char, parse_number and parse_bool set CF
; if something has failed, otherwise return the value in al/ax.
 
parse_timeout:
; timeout is a number not greater than 9
call parse_number
jc .nothing
cmp ax, 9
jbe @f
mov ax, 9
@@:
imul ax, 18
mov [es:preboot_timeout], ax
.nothing:
ret
 
parse_resolution:
; resolution is <width>*<height>, 'x' can be used instead of '*'
; parse width
call parse_number
jc .nothing
; save width
xchg ax, bx
; test for 'x' or '*'
call parse_char
cmp al, 'x'
jz @f
cmp al, '*'
jnz .nothing
@@:
; parse height
call parse_number
jc .nothing
; write width and height
mov [es:x_save], bx
mov [es:y_save], ax
.nothing:
ret
 
parse_vbemode:
; vbemode is a number
call parse_number
jc .nothing
mov [es:number_vm], ax
.nothing:
ret
 
;parse_vrr:
;; vrr is a boolean setting
; call parse_bool
; jc .nothing
;; convert 0 to 2, 1 to 1
; inc ax
; xor al, 3
; mov [es:preboot_vrrm], al
;.nothing:
; ret
 
parse_biosdisks:
; using biosdisks is a boolean setting
call parse_bool
jc .nothing
; convert 0 to 2, 1 to 1
inc ax
xor al, 3
mov [es:preboot_biosdisk], al
.nothing:
ret
 
parse_imgfrom:
; boot device (1-floppy 2-kolibri.img using primary loader)
call parse_number
jc .nothing
cmp al, 1
jb .nothing
cmp al, 2
ja .nothing
mov [es:preboot_device], al
.nothing:
ret
 
parse_char:
; skip spaces and return the next character or CF if EOF.
cmp si, dx
jae .eof
lodsb
cmp al, ' '
jbe parse_char
ret
.eof:
stc
ret
 
parse_number:
; initialize high part of ax to zero
xor ax, ax
; skip spaces
call parse_char
jc .bad
; al should be a digit
sub al, '0'
cmp al, 9
ja .bad
; accumulate the value in cx
xchg cx, ax
@@:
cmp si, dx
jae .eof
lodsb
sub al, '0'
cmp al, 9
ja .end
imul cx, 10
add cx, ax
jmp @b
; if the end is caused by non-digit, unwind the last character
.end:
dec si
.eof:
xchg cx, ax
clc
ret
.bad:
stc
ret
 
parse_bool:
; skip spaces
call parse_char
jc .bad
; Boolean false can be represented as 0=no=off,
; boolean true can be represented as 1=yes=on.
cmp al, '0'
jz .false
cmp al, '1'
jz .true
mov ah, al
cmp si, dx
jae .bad
lodsb
cmp ax, 'n'*256 + 'o'
jz .false
cmp ax, 'o'*256 + 'f'
jz .false
cmp ax, 'y'*256 + 'e'
jz .true
cmp ax, 'o'*256 + 'n'
jz .true
.bad:
stc
ret
.true:
xor ax, ax
inc ax
ret
.false:
xor ax, ax
ret
/kernel/branches/net/boot/preboot.inc
0,0 → 1,42
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
display_modechg db 0 ; display mode change for text, yes/no (0 or 2)
;
; !! Important note !!
;
; Must be set to 2, to avoid two screenmode
; changes within a very short period of time.
 
display_atboot db 0 ; show boot screen messages ( 2-no )
 
preboot_graph dw 0 ; graph mode
x_save dw 0 ; x
y_save dw 0 ; y
number_vm dw 0 ;
;pixel_save dw 0 ; per to pixel
preboot_gprobe db 0 ; probe vesa3 videomodes (1-no, 2-yes)
;preboot_vrrm db 0 ; use VRR_M (1-yes, 2- no)
preboot_dma db 0 ; use DMA for access to HDD (1-always, 2-only for read, 3-never)
preboot_device db 0 ; boot device
; (1-floppy 2-harddisk 3-kernel restart 4-format ram disk)
;!!!! 0 - autodetect !!!!
preboot_blogesc = 0 ; start immediately after bootlog
preboot_biosdisk db 0 ; use V86 to access disks through BIOS (1-yes, 2-no)
if defined extended_primary_loader
preboot_timeout dw 5*18 ; timeout in 1/18th of second for config settings screen
end if
 
if $>0x200
ERROR:
prebooting parameters must fit in first sector!!!
end if
hdsysimage db 'KOLIBRI.IMG',0 ; load from
image_save db 'KOLIBRI.IMG',0 ; save to
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/boot/rdload.inc
0,0 → 1,134
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
; READ RAMDISK IMAGE FROM HD
 
cmp [boot_dev+OS_BASE+0x10000], 1
jne no_sys_on_hd
 
test [DRIVE_DATA+1], byte 0x40
jz position_2
mov [hdbase], 0x1f0
mov [hdid], 0x0
mov [hdpos], 1
mov [fat32part], 0
position_1_1:
inc [fat32part]
call search_and_read_image
cmp [image_retrieved], 1
je yes_sys_on_hd
movzx eax, byte [DRIVE_DATA+2]
cmp [fat32part], eax
jle position_1_1
position_2:
test [DRIVE_DATA+1], byte 0x10
jz position_3
mov [hdbase], 0x1f0
mov [hdid], 0x10
mov [hdpos], 2
mov [fat32part], 0
position_2_1:
inc [fat32part]
call search_and_read_image
cmp [image_retrieved], 1
je yes_sys_on_hd
movzx eax, byte [DRIVE_DATA+3]
cmp eax, [fat32part]
jle position_2_1
position_3:
test [DRIVE_DATA+1], byte 0x4
jz position_4
mov [hdbase], 0x170
mov [hdid], 0x0
mov [hdpos], 3
mov [fat32part], 0
position_3_1:
inc [fat32part]
call search_and_read_image
cmp [image_retrieved], 1
je yes_sys_on_hd
movzx eax, byte [DRIVE_DATA+4]
cmp eax, [fat32part]
jle position_3_1
position_4:
test [DRIVE_DATA+1], byte 0x1
jz no_sys_on_hd
mov [hdbase], 0x170
mov [hdid], 0x10
mov [hdpos], 4
mov [fat32part], 0
position_4_1:
inc [fat32part]
call search_and_read_image
cmp [image_retrieved], 1
je yes_sys_on_hd
movzx eax, byte [DRIVE_DATA+5]
cmp eax, [fat32part]
jle position_4_1
jmp yes_sys_on_hd
 
search_and_read_image:
call set_FAT32_variables
mov edx, bootpath
call read_image
test eax, eax
jz image_present
mov edx, bootpath2
call read_image
test eax, eax
jz image_present
ret
image_present:
mov [image_retrieved], 1
ret
 
iglobal
align 4
read_image_fsinfo:
dd 0 ; function: read
dq 0 ; offset: zero
dd 1474560/512 ; size
dd RAMDISK ; buffer
db 0
dd hdsysimage+OS_BASE+0x10000
endg
 
read_image:
mov ebx, read_image_fsinfo
pushad
call file_system_lfn_protected
popad
ret
 
image_retrieved db 0
counter_of_partitions db 0
no_sys_on_hd:
; test_to_format_ram_disk (need if not using ram disk)
cmp [boot_dev+OS_BASE+0x10000], 3
jne not_format_ram_disk
; format_ram_disk
mov edi, RAMDISK
mov ecx, 0x1080
xor eax, eax
@@:
stosd
loop @b
 
mov ecx, 0x58F7F
mov eax, 0xF6F6F6F6
@@:
stosd
loop @b
mov [RAMDISK+0x200], dword 0xFFFFF0 ; fat table
mov [RAMDISK+0x4200], dword 0xFFFFF0
not_format_ram_disk:
yes_sys_on_hd:
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/boot/ru.inc
0,0 → 1,102
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
; Generated by RUFNT.EXE
; By BadBugsKiller (C)
; Modifyed by BadBugsKiller 12.01.2004 17:45
; Øðèôò óìåíüøåí â ðàçìåðå è òåïåðü ñîñòîèò èç 2-óõ ÷àñòåé,
; ñîäåðæàùèõ òîëüêî ñèìâîëû ðóññêîãî àëôàâèòà.
; ñèìâîëû â êîäèðîâêå ASCII (ÄÎÑ'îâñêàÿ), êîäîâàÿ ñòðàíèöà 866.
RU_FNT1:
db 0x00, 0x00, 0x1E, 0x36, 0x66, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xFE, 0x62, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0x81, 0x00, 0x00
db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xDB, 0xDB, 0x5A, 0x5A, 0x7E, 0x7E, 0x5A, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00
db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xCF, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xFF, 0xDB, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00
db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFF, 0x03, 0x03, 0x00, 0x00
db 0x00, 0x00, 0xF8, 0xF0, 0xB0, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xF3, 0xDB, 0xDB, 0xDB, 0xDB, 0xF3, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x26, 0x3E, 0x26, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x3E, 0x66, 0x66, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x02, 0x06, 0x7C, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x62, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0xC3, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0x54, 0x7C, 0x54, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3C, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00
RU_FNT2:
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00
db 0x00, 0x00, 0x00, 0x3C, 0x18, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x18, 0x3C, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x03, 0x03, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB0, 0xB0, 0x3E, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xF6, 0xDE, 0xDE, 0xF6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3E, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC6, 0xC6, 0x7E, 0x36, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00
db 0x6C, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xFC, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC8, 0xF8, 0xC8, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xF8, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00
db 0x66, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00
db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00
db 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0xCF, 0xCD, 0xEF, 0xEC, 0xFF, 0xDC, 0xDC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/boot/shutdown.inc
0,0 → 1,212
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Shutdown for Menuet ;;
;; ;;
;; Distributed under General Public License ;;
;; See file COPYING for details. ;;
;; Copyright 2003 Ville Turjanmaa ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
align 4
pr_mode_exit:
 
; setup stack
mov ax, 0x3000
mov ss, ax
mov esp, 0x0EC00
; setup ds
push cs
pop ds
 
lidt [old_ints_h]
;remap IRQs
mov al, 0x11
out 0x20, al
call rdelay
out 0xA0, al
call rdelay
 
mov al, 0x08
out 0x21, al
call rdelay
mov al, 0x70
out 0xA1, al
call rdelay
 
mov al, 0x04
out 0x21, al
call rdelay
mov al, 0x02
out 0xA1, al
call rdelay
 
mov al, 0x01
out 0x21, al
call rdelay
out 0xA1, al
call rdelay
 
mov al, 0xB8
out 0x21, al
call rdelay
mov al, 0xBD
out 0xA1, al
sti
 
temp_3456:
xor ax, ax
mov es, ax
mov al, byte [es:0x9030]
cmp al, 1
jl nbw
cmp al, 4
jle nbw32
 
nbw:
in al, 0x60
cmp al, 6
jae nbw
mov bl, al
nbw2:
in al, 0x60
cmp al, bl
je nbw2
cmp al, 240;ax,240
jne nbw31
mov al, bl
dec ax
jmp nbw32
nbw31:
add bl, 128
cmp al, bl
jne nbw
sub al, 129
 
nbw32:
 
dec ax
dec ax ; 2 = power off
jnz no_apm_off
call APM_PowerOff
jmp $
no_apm_off:
 
if ~ defined extended_primary_loader ; kernel restarting is not supported
dec ax ; 3 = reboot
jnz restart_kernel ; 4 = restart kernel
end if
push 0x40
pop ds
mov word[0x0072], 0x1234
jmp 0xF000:0xFFF0
 
 
rdelay:
ret
 
APM_PowerOff:
mov ax, 5304h
xor bx, bx
int 15h
;!!!!!!!!!!!!!!!!!!!!!!!!
mov ax, 0x5300
xor bx, bx
int 0x15
push ax
 
mov ax, 0x5301
xor bx, bx
int 0x15
 
mov ax, 0x5308
mov bx, 1
mov cx, bx
int 0x15
 
mov ax, 0x530E
xor bx, bx
pop cx
int 0x15
 
mov ax, 0x530D
mov bx, 1
mov cx, bx
int 0x15
 
mov ax, 0x530F
mov bx, 1
mov cx, bx
int 0x15
 
mov ax, 0x5307
mov bx, 1
mov cx, 3
int 0x15
;!!!!!!!!!!!!!!!!!!!!!!!!
ret
 
if ~ defined extended_primary_loader
restart_kernel:
 
mov ax, 0x0003 ; set text mode for screen
int 0x10
jmp 0x4000:0000
 
restart_kernel_4000:
cli
 
push ds
pop es
mov cx, 0x8000
push cx
push 0x7000
pop ds
xor si, si
xor di, di
rep movsw
pop cx
mov ds, cx
push 0x2000
pop es
rep movsw
push 0x9000
pop ds
push 0x3000
pop es
mov cx, 0xE000/2
rep movsw
 
wbinvd ; write and invalidate cache
 
mov al, 00110100b
out 43h, al
jcxz $+2
mov al, 0xFF
out 40h, al
jcxz $+2
out 40h, al
jcxz $+2
sti
 
; (hint by Black_mirror)
; We must read data from keyboard port,
; because there may be situation when previous keyboard interrupt is lost
; (due to return to real mode and IRQ reprogramming)
; and next interrupt will not be generated (as keyboard waits for handling)
in al, 0x60
 
; bootloader interface
push 0x1000
pop ds
mov si, kernel_restart_bootblock
mov ax, 'KL'
jmp 0x1000:0000
end if
 
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/boot/ETFONT.FNT
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mergeinfo
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/kernel/branches/net/boot
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/data32sp.inc
0,0 → 1,40
boot_initirq db 'Inicializar IRQ',0
boot_picinit db 'Inicializar PIC',0
boot_v86machine db 'Inicializar sistema V86',0
boot_inittimer db 'Inicializar reloj del sistema (IRQ0)',0
boot_initapic db 'Prueba inicializar APIC',0
boot_enableirq db 'Habilitar interrupciones 2, 6, 13, 14, 15',0
boot_enablint_ide db 'Habiliar interrupciones en controladores IDE',0
boot_detectfloppy db 'Buscar unidades de disquete',0
boot_detecthdcd db 'Buscar discos duros y unidades ATAPI',0
boot_getcache db 'Tomar memoria para cach‚',0
boot_detectpart db 'Buscar particiones en discos',0
boot_init_sys db 'Inicializar directorio del sistema /sys',0
boot_loadlibs db 'Cargando librer¡as (.obj)',0
boot_memdetect db 'Determinando cantidad de memoria',0
boot_tss db 'Configurando TSSs',0
boot_cpuid db 'Leyendo CPUIDs',0
; boot_devices db 'Detectando dispositivos',0
boot_setmouse db 'Configurando el rat¢n',0
boot_windefs db 'Setting window defaults',0
boot_bgr db 'Calculating background',0
boot_resirqports db 'Reservando IRQs y puertos',0
boot_setostask db 'Configurando tarea OS',0
boot_allirqs db 'Desenmascarando IRQs',0
boot_tsc db 'Leyendo TSC',0
boot_cpufreq db 'La frequencia del CPU es ',' ',' MHz',0
boot_pal_ega db 'Configurando paleta EGA/CGA 320x200',0
boot_pal_vga db 'Configurando paleta VGA 640x480',0
boot_failed db 'Fallo al iniciar la primer aplicaci¢n',0
boot_mtrr db 'Configurando MTRR',0
 
boot_APIC_found db 'APIC habilitado', 0
boot_APIC_nfound db 'APIC no encontrado', 0
if preboot_blogesc
boot_tasking db 'Todo configurado - presiona ESC para iniciar',0
end if
 
msg_version db 'versi¢n incompatible del controlador',13,10,0
msg_www db 'por favor, visita www.kolibrios.org',13,10,0
 
ud_user_message db 'Error: instrucci¢n no soportada por el procesador',0
/kernel/branches/net/detect/biosdisk.inc
0,0 → 1,81
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2008-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; Detect all BIOS hard drives.
; diamond, 2008
 
xor cx, cx
mov es, cx
mov di, 0x9080
mov byte [es:di-1], cl
cmp [preboot_biosdisk], 1
jnz bdde
mov dl, 80h
bdds:
mov ah, 15h
push cx dx di
int 13h
pop di dx cx
jc bddc
test ah, ah
jz bddc
inc cx
mov ah, 48h
push ds
push es
pop ds
mov si, 0xA000
mov word [si], 1Eh
mov ah, 48h
int 13h
pop ds
jc bddc2
inc byte [es:0x907F]
cmp word [es:si], 1Eh
jb bddl
cmp word [es:si+1Ah], 0xFFFF
jz bddl
mov al, dl
stosb
push ds
lds si, [es:si+1Ah]
mov al, [si+6]
and al, 0xF
stosb
mov al, byte [si+4]
shr al, 4
and ax, 1
cmp word [si], 1F0h
jz @f
inc ax
inc ax
cmp word [si], 170h
jz @f
or ax, -1
; mov ax, -1
@@:
stosw
pop ds
jmp bddc2
bddl:
mov al, dl
stosb
xor ax, ax
stosb
dec ax
stosw
; mov al, 0
; stosb
; mov ax, -1
; stosw
bddc2:
cmp cl, [es:0x475]
jae bdde
bddc:
inc dl
jnz bdds
bdde:
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/detect/biosmem.inc
0,0 → 1,43
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2009-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; Query physical memory map from BIOS.
; diamond, 2009
 
push ds
; first call to fn E820
mov eax, 0xE820
xor ebx, ebx
mov es, bx
mov ds, bx
mov di, 0x9104
mov [di-4], ebx ; no blocks yet
mov ecx, 20
mov edx, 0x534D4150
int 15h
jc no_E820
cmp eax, 0x534D4150
jnz no_E820
e820_mem_loop:
; cmp byte [di+16], 1 ; ignore non-free areas
; jnz e820_mem_next
inc byte [0x9100]
add di, 20
e820_mem_next:
; consequent calls to fn E820
test ebx, ebx
jz e820_test_done
cmp byte [0x9100], 32
jae e820_test_done
mov eax, 0xE820
int 15h
jc e820_test_done
jmp e820_mem_loop
no_E820:
; let's hope for mem_test from init.inc
e820_test_done:
pop ds
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/detect/sear_par.inc
0,0 → 1,161
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
;****************************************************
; ïîèñê ëîãè÷åñêèõ äèñêîâ íà îáíàðóæåííûõ HDD
; è çàíåñåíèå äàííûõ â îáëàñòü òàáëèöû
; àâòîð Mario79
;****************************************************
mov [transfer_adress], DRIVE_DATA+0xa
search_partitions_ide0:
test [DRIVE_DATA+1], byte 0x40
jz search_partitions_ide1
mov [hdbase], 0x1f0
mov [hdid], 0x0
mov [hdpos], 1
mov [known_part], 1
search_partitions_ide0_1:
call set_PARTITION_variables
test [problem_partition], 2
jnz search_partitions_ide1 ; not found part
test [problem_partition], 1
jnz @F ; not found known_part
;cmp [problem_partition],0
;jne search_partitions_ide1
inc byte [DRIVE_DATA+2]
call partition_data_transfer
add [transfer_adress], 100
@@:
inc [known_part]
jmp search_partitions_ide0_1
 
search_partitions_ide1:
test [DRIVE_DATA+1], byte 0x10
jz search_partitions_ide2
mov [hdbase], 0x1f0
mov [hdid], 0x10
mov [hdpos], 2
mov [known_part], 1
search_partitions_ide1_1:
call set_PARTITION_variables
test [problem_partition], 2
jnz search_partitions_ide2
test [problem_partition], 1
jnz @F
;cmp [problem_partition],0
;jne search_partitions_ide2
inc byte [DRIVE_DATA+3]
call partition_data_transfer
add [transfer_adress], 100
@@:
inc [known_part]
jmp search_partitions_ide1_1
 
search_partitions_ide2:
test [DRIVE_DATA+1], byte 0x4
jz search_partitions_ide3
mov [hdbase], 0x170
mov [hdid], 0x0
mov [hdpos], 3
mov [known_part], 1
search_partitions_ide2_1:
call set_PARTITION_variables
test [problem_partition], 2
jnz search_partitions_ide3
test [problem_partition], 1
jnz @F
;cmp [problem_partition],0
;jne search_partitions_ide3
inc byte [DRIVE_DATA+4]
call partition_data_transfer
add [transfer_adress], 100
@@:
inc [known_part]
jmp search_partitions_ide2_1
 
search_partitions_ide3:
test [DRIVE_DATA+1], byte 0x1
jz end_search_partitions_ide
mov [hdbase], 0x170
mov [hdid], 0x10
mov [hdpos], 4
mov [known_part], 1
search_partitions_ide3_1:
call set_PARTITION_variables
test [problem_partition], 2
jnz end_search_partitions_ide
test [problem_partition], 1
jnz @F
;cmp [problem_partition],0
;jne end_search_partitions_ide
inc byte [DRIVE_DATA+5]
call partition_data_transfer
add [transfer_adress], 100
@@:
inc [known_part]
jmp search_partitions_ide3_1
 
end_search_partitions_ide:
mov [hdpos], 80h
mov ecx, [NumBiosDisks]
test ecx, ecx
jz end_search_partitions
start_search_partitions_bd:
push ecx
mov eax, [hdpos]
and [BiosDiskPartitions+(eax-80h)*4], 0
mov [known_part], 1
search_partitions_bd:
call set_PARTITION_variables
test [problem_partition], 2
jnz end_search_partitions_bd
test [problem_partition], 1
jnz @F
;cmp [problem_partition], 0
;jne end_search_partitions_bd
mov eax, [hdpos]
inc [BiosDiskPartitions+(eax-80h)*4]
call partition_data_transfer
add [transfer_adress], 100
@@:
inc [known_part]
jmp search_partitions_bd
end_search_partitions_bd:
pop ecx
inc [hdpos]
loop start_search_partitions_bd
jmp end_search_partitions
 
problem_partition db 0 ; used for partitions search
 
include '../fs/part_set.inc'
 
partition_data_transfer:
mov edi, [transfer_adress]
mov esi, PARTITION_START ;start of file_system_data
mov ecx, (file_system_data_size+3)/4
rep movsd
ret
uglobal
transfer_adress dd 0
endg
partition_data_transfer_1:
; cli
push edi
mov edi, PARTITION_START
mov esi, [transfer_adress]
mov ecx, (file_system_data_size+3)/4
rep movsd
pop edi
; sti
ret
 
end_search_partitions:
 
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/detect/dev_fd.inc
0,0 → 1,37
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
;***************************************************
; ïðåäâàðèòåëüíàÿ î÷èñòêà îáëàñòè òàáëèöû
; ïîèñê è çàíåñåíèå â òàáëèöó ïðèâîäîâ FDD
; àâòîð Mario79
;***************************************************
xor eax, eax
mov edi, DRIVE_DATA
mov ecx, 16384
cld
rep stosd
 
mov al, 0x10
out 0x70, al
mov cx, 0xff
wait_cmos:
dec cx
test cx, cx
jnz wait_cmos
in al, 0x71
mov [DRIVE_DATA], al
test al, al
jz @f
in al, 0x21
and al, 10111111b ; Enable IRQ6
out 0x21, al
@@:
 
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/detect/dev_hdcd.inc
0,0 → 1,394
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
;******************************************************
; ïîèñê ïðèâîäîâ HDD è CD
; àâòîð èñõîäíîãî òåêñòà Êóëàêîâ Âëàäèìèð Ãåííàäüåâè÷.
; àäàïòàöèÿ è äîðàáîòêà Mario79
;******************************************************
 
;****************************************************
;* ÏÎÈÑÊ HDD è CD *
;****************************************************
FindHDD:
mov [ChannelNumber], 1
mov [DiskNumber], 0
call FindHDD_3
; mov ax,[Sector512+176]
; mov [DRIVE_DATA+6],ax
; mov ax,[Sector512+126]
; mov [DRIVE_DATA+8],ax
; mov ax,[Sector512+128]
; mov [DRIVE_DATA+8],ax
mov [DiskNumber], 1
call FindHDD_3
; mov al,[Sector512+176]
; mov [DRIVE_DATA+7],al
inc [ChannelNumber]
mov [DiskNumber], 0
call FindHDD_3
; mov al,[Sector512+176]
; mov [DRIVE_DATA+8],al
mov [DiskNumber], 1
call FindHDD_1
; mov al,[Sector512+176]
; mov [DRIVE_DATA+9],al
 
jmp EndFindHDD
 
FindHDD_1:
call ReadHDD_ID
cmp [DevErrorCode], 0
jne FindHDD_2
cmp [Sector512+6], word 16
ja FindHDD_2
cmp [Sector512+12], word 255
ja FindHDD_2
inc byte [DRIVE_DATA+1]
jmp FindHDD_2_2
FindHDD_2:
call DeviceReset
cmp [DevErrorCode], 0
jne FindHDD_2_2
call ReadCD_ID
cmp [DevErrorCode], 0
jne FindHDD_2_2
inc byte [DRIVE_DATA+1]
inc byte [DRIVE_DATA+1]
FindHDD_2_2:
ret
 
FindHDD_3:
call FindHDD_1
shl byte [DRIVE_DATA+1], 2
ret
 
 
; Àäðåñ ñ÷èòûâàåìîãî ñåêòîðà â ðåæèìå LBA
uglobal
SectorAddress DD ?
endg
;*************************************************
;* ×ÒÅÍÈÅ ÈÄÅÍÒÈÔÈÊÀÒÎÐÀ ÆÅÑÒÊÎÃÎ ÄÈÑÊÀ *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðåìåííûå: *
;* ChannelNumber - íîìåð êàíàëà (1 èëè 2); *
;* DiskNumber - íîìåð äèñêà íà êàíàëå (0 èëè 1). *
;* Èäåíòèôèêàöèîííûé áëîê äàííûõ ñ÷èòûâàåòñÿ *
;* â ìàññèâ Sector512. *
;*************************************************
ReadHDD_ID:
; Çàäàòü ðåæèì CHS
mov [ATAAddressMode], 0
; Ïîñëàòü êîìàíäó èäåíòèôèêàöèè óñòðîéñòâà
mov [ATAFeatures], 0
mov [ATAHead], 0
mov [ATACommand], 0ECh
call SendCommandToHDD
cmp [DevErrorCode], 0;ïðîâåðèòü êîä îøèáêè
jne @@End ;çàêîí÷èòü, ñîõðàíèâ êîä îøèáêè
mov DX, [ATABasePortAddr]
add DX, 7 ;àäðåñ ðåãèñòðà ñîñòîÿíè
mov ecx, 0xffff
@@WaitCompleet:
; Ïðîâåðèòü âðåìÿ âûïîëíåíèÿ êîìàíäû
dec ecx
; cmp ecx,0
jz @@Error1 ;îøèáêà òàéì-àóòà
; Ïðîâåðèòü ãîòîâíîñòü
in AL, DX
test AL, 80h ;ñîñòîÿíèå ñèãíàëà BSY
jnz @@WaitCompleet
test AL, 1 ;ñîñòîÿíèå ñèãíàëà ERR
jnz @@Error6
test AL, 08h ;ñîñòîÿíèå ñèãíàëà DRQ
jz @@WaitCompleet
; Ïðèíÿòü áëîê äàííûõ îò êîíòðîëëåðà
; mov AX,DS
; mov ES,AX
mov EDI, Sector512 ;offset Sector512
mov DX, [ATABasePortAddr];ðåãèñòð äàííûõ
mov CX, 256 ;÷èñëî ñ÷èòûâàåìûõ ñëîâ
rep insw ;ïðèíÿòü áëîê äàííûõ
ret
; Çàïèñàòü êîä îøèáêè
@@Error1:
mov [DevErrorCode], 1
ret
@@Error6:
mov [DevErrorCode], 6
@@End:
ret
 
 
iglobal
; Ñòàíäàðòíûå áàçîâûå àäðåñà êàíàëîâ 1 è 2
StandardATABases DW 1F0h, 170h
endg
uglobal
; Íîìåð êàíàëà
ChannelNumber DW ?
; Íîìåð äèñêà
DiskNumber DB ?
; Áàçîâûé àäðåñ ãðóïïû ïîðòîâ êîíòðîëëåðà ATA
ATABasePortAddr DW ?
; Ïàðàìåòðû ATA-êîìàíäû
ATAFeatures DB ? ;îñîáåííîñòè
ATASectorCount DB ? ;êîëè÷åñòâî îáðàáàòûâàåìûõ ñåêòîðîâ
ATASectorNumber DB ? ;íîìåð íà÷àëüíîãî ñåêòîðà
ATACylinder DW ? ;íîìåð íà÷àëüíîãî öèëèíäðà
ATAHead DB ? ;íîìåð íà÷àëüíîé ãîëîâêè
ATAAddressMode DB ? ;ðåæèì àäðåñàöèè (0 - CHS, 1 - LBA)
ATACommand DB ? ;êîä êîìàíäû, ïîäëåæàùåé âûïîëíåíèþ
; Êîä îøèáêè (0 - íåò îøèáîê, 1 - ïðåâûøåí äîïóñòèìûé
; èíòåðâàë îæèäàíèÿ, 2 - íåâåðíûé êîä ðåæèìà àäðåñàöèè,
; 3 - íåâåðíûé íîìåð êàíàëà, 4 - íåâåðíûé íîìåð äèñêà,
; 5 - íåâåðíûé íîìåð ãîëîâêè, 6 - îøèáêà ïðè âûïîëíåíèè
; êîìàíäû)
DevErrorCode dd ?
endg
;****************************************************
;* ÏÎÑËÀÒÜ ÊÎÌÀÍÄÓ ÇÀÄÀÍÍÎÌÓ ÄÈÑÊÓ *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðåìåííûå: *
;* ChannelNumber - íîìåð êàíàëà (1 èëè 2); *
;* DiskNumber - íîìåð äèñêà (0 èëè 1); *
;* ATAFeatures - "îñîáåííîñòè"; *
;* ATASectorCount - êîëè÷åñòâî ñåêòîðîâ; *
;* ATASectorNumber - íîìåð íà÷àëüíîãî ñåêòîðà; *
;* ATACylinder - íîìåð íà÷àëüíîãî öèëèíäðà; *
;* ATAHead - íîìåð íà÷àëüíîé ãîëîâêè; *
;* ATAAddressMode - ðåæèì àäðåñàöèè (0-CHS, 1-LBA); *
;* ATACommand - êîä êîìàíäû. *
;* Ïîñëå óñïåøíîãî âûïîëíåíèÿ ôóíêöèè: *
;* â ATABasePortAddr - áàçîâûé àäðåñ HDD; *
;* â DevErrorCode - íîëü. *
;* Ïðè âîçíèêíîâåíèè îøèáêè â DevErrorCode áóäåò *
;* âîçâðàùåí êîä îøèáêè. *
;****************************************************
SendCommandToHDD:
; Ïðîâåðèòü çíà÷åíèå êîäà ðåæèìà
cmp [ATAAddressMode], 1
ja @@Err2
; Ïðîâåðèòü êîððåêòíîñòü íîìåðà êàíàëà
mov BX, [ChannelNumber]
cmp BX, 1
jb @@Err3
cmp BX, 2
ja @@Err3
; Óñòàíîâèòü áàçîâûé àäðåñ
dec BX
shl BX, 1
movzx ebx, bx
mov AX, [ebx+StandardATABases]
mov [ATABasePortAddr], AX
; Îæèäàíèå ãîòîâíîñòè HDD ê ïðèåìó êîìàíäû
; Âûáðàòü íóæíûé äèñê
mov DX, [ATABasePortAddr]
add DX, 6 ;àäðåñ ðåãèñòðà ãîëîâîê
mov AL, [DiskNumber]
cmp AL, 1 ;ïðîâåðèòü íîìåðà äèñêà
ja @@Err4
shl AL, 4
or AL, 10100000b
out DX, AL
; Îæèäàòü, ïîêà äèñê íå áóäåò ãîòîâ
inc DX
mov ecx, 0xfff
; mov eax,[timer_ticks]
; mov [TickCounter_1],eax
@@WaitHDReady:
; Ïðîâåðèòü âðåìÿ îæèäàíè
dec ecx
; cmp ecx,0
jz @@Err1
; mov eax,[timer_ticks]
; sub eax,[TickCounter_1]
; cmp eax,300 ;îæèäàòü 300 òèêîâ
; ja @@Err1 ;îøèáêà òàéì-àóòà
; Ïðî÷èòàòü ðåãèñòð ñîñòîÿíè
in AL, DX
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà BSY
test AL, 80h
jnz @@WaitHDReady
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà DRQ
test AL, 08h
jnz @@WaitHDReady
; Çàãðóçèòü êîìàíäó â ðåãèñòðû êîíòðîëëåðà
cli
mov DX, [ATABasePortAddr]
inc DX ;ðåãèñòð "îñîáåííîñòåé"
mov AL, [ATAFeatures]
out DX, AL
inc DX ;ñ÷åò÷èê ñåêòîðîâ
mov AL, [ATASectorCount]
out DX, AL
inc DX ;ðåãèñòð íîìåðà ñåêòîðà
mov AL, [ATASectorNumber]
out DX, AL
inc DX ;íîìåð öèëèíäðà (ìëàäøèé áàéò)
mov AX, [ATACylinder]
out DX, AL
inc DX ;íîìåð öèëèíäðà (ñòàðøèé áàéò)
mov AL, AH
out DX, AL
inc DX ;íîìåð ãîëîâêè/íîìåð äèñêà
mov AL, [DiskNumber]
shl AL, 4
cmp [ATAHead], 0Fh;ïðîâåðèòü íîìåð ãîëîâêè
ja @@Err5
or AL, [ATAHead]
or AL, 10100000b
mov AH, [ATAAddressMode]
shl AH, 6
or AL, AH
out DX, AL
; Ïîñëàòü êîìàíäó
mov AL, [ATACommand]
inc DX ;ðåãèñòð êîìàíä
out DX, AL
sti
; Ñáðîñèòü ïðèçíàê îøèáêè
mov [DevErrorCode], 0
ret
; Çàïèñàòü êîä îøèáêè
@@Err1:
mov [DevErrorCode], 1
ret
@@Err2:
mov [DevErrorCode], 2
ret
@@Err3:
mov [DevErrorCode], 3
ret
@@Err4:
mov [DevErrorCode], 4
ret
@@Err5:
mov [DevErrorCode], 5
; Çàâåðøåíèå ðàáîòû ïðîãðàììû
ret
 
;*************************************************
;* ×ÒÅÍÈÅ ÈÄÅÍÒÈÔÈÊÀÒÎÐÀ ÓÑÒÐÎÉÑÒÂÀ ATAPI *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðìåííûå: *
;* ChannelNumber - íîìåð êàíàëà; *
;* DiskNumber - íîìåð äèñêà íà êàíàëå. *
;* Èäåíòèôèêàöèîííûé áëîê äàííûõ ñ÷èòûâàåòñÿ *
;* â ìàññèâ Sector512. *
;*************************************************
ReadCD_ID:
; Çàäàòü ðåæèì CHS
mov [ATAAddressMode], 0
; Ïîñëàòü êîìàíäó èäåíòèôèêàöèè óñòðîéñòâà
mov [ATAFeatures], 0
mov [ATASectorCount], 0
mov [ATASectorNumber], 0
mov [ATACylinder], 0
mov [ATAHead], 0
mov [ATACommand], 0A1h
call SendCommandToHDD
cmp [DevErrorCode], 0;ïðîâåðèòü êîä îøèáêè
jne @@End_1 ;çàêîí÷èòü, ñîõðàíèâ êîä îøèáêè
; Îæèäàòü ãîòîâíîñòü äàííûõ HDD
mov DX, [ATABasePortAddr]
add DX, 7 ;ïîðò 1õ7h
mov ecx, 0xffff
@@WaitCompleet_1:
; Ïðîâåðèòü âðåì
dec ecx
; cmp ecx,0
jz @@Error1_1 ;îøèáêà òàéì-àóòà
; Ïðîâåðèòü ãîòîâíîñòü
in AL, DX
test AL, 80h ;ñîñòîÿíèå ñèãíàëà BSY
jnz @@WaitCompleet_1
test AL, 1 ;ñîñòîÿíèå ñèãíàëà ERR
jnz @@Error6_1
test AL, 08h ;ñîñòîÿíèå ñèãíàëà DRQ
jz @@WaitCompleet_1
; Ïðèíÿòü áëîê äàííûõ îò êîíòðîëëåðà
; mov AX,DS
; mov ES,AX
mov EDI, Sector512 ;offset Sector512
mov DX, [ATABasePortAddr];ïîðò 1x0h
mov CX, 256;÷èñëî ñ÷èòûâàåìûõ ñëîâ
rep insw
ret
; Çàïèñàòü êîä îøèáêè
@@Error1_1:
mov [DevErrorCode], 1
ret
@@Error6_1:
mov [DevErrorCode], 6
@@End_1:
ret
 
;*************************************************
;* ÑÁÐÎÑ ÓÑÒÐÎÉÑÒÂÀ *
;* Âõîäíûå ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå *
;* ïåðåìåííûå: *
;* ChannelNumber - íîìåð êàíàëà (1 èëè 2); *
;* DiskNumber - íîìåð äèñêà (0 èëè 1). *
;*************************************************
DeviceReset:
; Ïðîâåðèòü êîððåêòíîñòü íîìåðà êàíàëà
mov BX, [ChannelNumber]
cmp BX, 1
jb @@Err3_2
cmp BX, 2
ja @@Err3_2
; Óñòàíîâèòü áàçîâûé àäðåñ
dec BX
shl BX, 1
movzx ebx, bx
mov DX, [ebx+StandardATABases]
mov [ATABasePortAddr], DX
; Âûáðàòü íóæíûé äèñê
add DX, 6 ;àäðåñ ðåãèñòðà ãîëîâîê
mov AL, [DiskNumber]
cmp AL, 1 ;ïðîâåðèòü íîìåðà äèñêà
ja @@Err4_2
shl AL, 4
or AL, 10100000b
out DX, AL
; Ïîñëàòü êîìàíäó "Ñáðîñ"
mov AL, 08h
inc DX ;ðåãèñòð êîìàíä
out DX, AL
mov ecx, 0x80000
@@WaitHDReady_1:
; Ïðîâåðèòü âðåìÿ îæèäàíè
dec ecx
; cmp ecx,0
je @@Err1_2 ;îøèáêà òàéì-àóòà
; Ïðî÷èòàòü ðåãèñòð ñîñòîÿíè
in AL, DX
; Ïðîâåðèòü ñîñòîÿíèå ñèãíàëà BSY
test AL, 80h
jnz @@WaitHDReady_1
; Ñáðîñèòü ïðèçíàê îøèáêè
mov [DevErrorCode], 0
ret
; Îáðàáîòêà îøèáîê
@@Err1_2:
mov [DevErrorCode], 1
ret
@@Err3_2:
mov [DevErrorCode], 3
ret
@@Err4_2:
mov [DevErrorCode], 4
; Çàïèñàòü êîä îøèáêè
ret
 
EndFindHDD:
 
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/detect/disks.inc
0,0 → 1,15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
include 'dev_fd.inc'
include 'dev_hdcd.inc'
include 'getcache.inc'
include 'sear_par.inc'
 
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/detect/getcache.inc
0,0 → 1,212
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
pusha
 
mov eax, [pg_data.pages_free]
; 1/32
shr eax, 5
; round off up to 8 pages
shr eax, 3
shl eax, 3
; translate pages in butes *4096
shl eax, 12
; check a upper size of the cache, no more than 1 Mb on the physical device
cmp eax, 1024*1024
jbe @f
mov eax, 1024*1024
jmp .continue
@@:
; check a lower size of the cache, not less than 128 Kb on the physical device
cmp eax, 128*1024
jae @f
mov eax, 128*1024
@@:
.continue:
mov [cache_ide0_size], eax
mov [cache_ide1_size], eax
mov [cache_ide2_size], eax
mov [cache_ide3_size], eax
xor eax, eax
mov [hdd_appl_data], 1;al
mov [cd_appl_data], 1
mov ch, [DRIVE_DATA+1]
mov cl, ch
and cl, 11b
je .ide2
mov esi, cache_ide3
call get_cache_ide
.ide2:
mov cl, ch
shr cl, 2
and cl, 11b
je .ide1
mov esi, cache_ide2
call get_cache_ide
.ide1:
mov cl, ch
shr cl, 4
and cl, 11b
je .ide0
mov esi, cache_ide1
call get_cache_ide
.ide0:
mov cl, ch
shr cl, 6
and cl, 11b
je @f
mov esi, cache_ide0
call get_cache_ide
@@:
xor ecx, ecx
cmp [NumBiosDisks], ecx
jz .endbd
mov esi, BiosDiskCaches
.loopbd:
push ecx
movsx ecx, byte [BiosDisksData+ecx*4+2]
inc ecx
jz .getbd
add ecx, ecx
movzx eax, byte [DRIVE_DATA+1]
shl eax, cl
and ah, 3
cmp ah, 1
jz .contbd
pop ecx
mov byte [BiosDisksData+ecx*4+2], -1
push ecx
.getbd:
mov eax, [cache_ide0_size]
mov [esi+cache_ide0_size-cache_ide0], eax
mov cl, 1
call get_cache_ide
.contbd:
pop ecx
add esi, cache_ide1-cache_ide0
inc ecx
cmp ecx, [NumBiosDisks]
jb .loopbd
.endbd:
jmp end_get_cache
 
get_cache_ide:
and [esi+cache_ide0_search_start-cache_ide0], 0
and [esi+cache_ide0_appl_search_start-cache_ide0], 0
push ecx
stdcall kernel_alloc, [esi+cache_ide0_size-cache_ide0]
mov [esi+cache_ide0_pointer-cache_ide0], eax
pop ecx
mov edx, eax
mov eax, [esi+cache_ide0_size-cache_ide0]
shr eax, 3
mov [esi+cache_ide0_system_data_size-cache_ide0], eax
mov ebx, eax
imul eax, 7
mov [esi+cache_ide0_appl_data_size-cache_ide0], eax
add ebx, edx
mov [esi+cache_ide0_data_pointer-cache_ide0], ebx
 
cmp cl, 10b
je .cd
push ecx
mov eax, [esi+cache_ide0_system_data_size-cache_ide0]
call calculate_for_hd
add eax, [esi+cache_ide0_pointer-cache_ide0]
mov [esi+cache_ide0_system_data-cache_ide0], eax
mov [esi+cache_ide0_system_sad_size-cache_ide0], ecx
 
push edi
mov edi, [esi+cache_ide0_pointer-cache_ide0]
call clear_ide_cache
pop edi
 
mov eax, [esi+cache_ide0_appl_data_size-cache_ide0]
call calculate_for_hd
add eax, [esi+cache_ide0_data_pointer-cache_ide0]
mov [esi+cache_ide0_appl_data-cache_ide0], eax
mov [esi+cache_ide0_appl_sad_size-cache_ide0], ecx
 
push edi
mov edi, [esi+cache_ide0_data_pointer-cache_ide0]
call clear_ide_cache
pop edi
 
pop ecx
ret
.cd:
push ecx
mov eax, [esi+cache_ide0_system_data_size-cache_ide0]
call calculate_for_cd
add eax, [esi+cache_ide0_pointer-cache_ide0]
mov [esi+cache_ide0_system_data-cache_ide0], eax
mov [esi+cache_ide0_system_sad_size-cache_ide0], ecx
 
push edi
mov edi, [esi+cache_ide0_pointer-cache_ide0]
call clear_ide_cache
pop edi
 
mov eax, [esi+cache_ide0_appl_data_size-cache_ide0]
call calculate_for_cd
add eax, [esi+cache_ide0_data_pointer-cache_ide0]
mov [esi+cache_ide0_appl_data-cache_ide0], eax
mov [esi+cache_ide0_appl_sad_size-cache_ide0], ecx
 
push edi
mov edi, [esi+cache_ide0_data_pointer-cache_ide0]
call clear_ide_cache
pop edi
 
pop ecx
ret
 
calculate_for_hd:
push eax
mov ebx, eax
shr eax, 9
shl eax, 3
sub ebx, eax
shr ebx, 9
mov ecx, ebx
shl ebx, 9
pop eax
sub eax, ebx
dec ecx
ret
 
calculate_for_cd:
push eax
mov ebx, eax
shr eax, 11
shl eax, 3
sub ebx, eax
shr ebx, 11
mov ecx, ebx
shl ebx, 11
pop eax
sub eax, ebx
dec ecx
ret
 
clear_ide_cache:
push eax
shl ecx, 1
xor eax, eax
cld
rep stosd
pop eax
ret
 
end_get_cache:
; mov [cache_ide0_pointer],HD_CACHE
; mov [cache_ide0_system_data],HD_CACHE+65536
; mov [cache_ide0_system_sad_size],1919
popa
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/detect
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/hid/keyboard.inc
0,0 → 1,552
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
;; Distributed under terms of the GNU General Public License ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
VKEY_LSHIFT = 0000000000000001b
VKEY_RSHIFT = 0000000000000010b
VKEY_LCONTROL = 0000000000000100b
VKEY_RCONTROL = 0000000000001000b
VKEY_LALT = 0000000000010000b
VKEY_RALT = 0000000000100000b
VKEY_CAPSLOCK = 0000000001000000b
VKEY_NUMLOCK = 0000000010000000b
VKEY_SCRLOCK = 0000000100000000b
VKEY_LWIN = 0000001000000000b
VKEY_RWIN = 0000010000000000b
 
VKEY_SHIFT = 0000000000000011b
VKEY_CONTROL = 0000000000001100b
VKEY_ALT = 0000000000110000b
 
uglobal
align 4
kb_state dd 0
ext_code db 0
 
keyboard_mode db 0
keyboard_data db 0
 
altmouseb db 0
ctrl_alt_del db 0
 
kb_lights db 0
old_kb_lights db 0
 
align 4
hotkey_scancodes rd 256 ; we have 256 scancodes
hotkey_list rd 256*4 ; max 256 defined hotkeys
hotkey_buffer rd 120*2 ; buffer for 120 hotkeys
endg
 
iglobal
hotkey_tests dd hotkey_test0
dd hotkey_test1
dd hotkey_test2
dd hotkey_test3
dd hotkey_test4
hotkey_tests_num = 5
endg
;---------------------------------------------------------------------
hotkey_test0:
test al, al
setz al
ret
;---------------------------------------------------------------------
hotkey_test1:
test al, al
setnp al
ret
;---------------------------------------------------------------------
hotkey_test2:
cmp al, 3
setz al
ret
;---------------------------------------------------------------------
hotkey_test3:
cmp al, 1
setz al
ret
;---------------------------------------------------------------------
hotkey_test4:
cmp al, 2
setz al
ret
;---------------------------------------------------------------------
hotkey_do_test:
push eax
mov edx, [kb_state]
shr edx, cl
add cl, cl
mov eax, [eax+4]
shr eax, cl
and eax, 15
cmp al, hotkey_tests_num
jae .fail
xchg eax, edx
and al, 3
call [hotkey_tests + edx*4]
cmp al, 1
pop eax
ret
;--------------------------------------
.fail:
stc
pop eax
ret
;---------------------------------------------------------------------
align 4
set_keyboard_data:
movzx eax, word[TASK_COUNT]; top window process
movzx eax, word[WIN_POS+eax*2]
shl eax, 8
mov al, [SLOT_BASE+eax+APPDATA.keyboard_mode]
mov [keyboard_mode], al
mov eax, ecx
push ebx esi edi ebp
call send_scancode
pop ebp edi esi ebx
ret
;---------------------------------------------------------------------
struct KEYBOARD
next dd ?
prev dd ?
functions dd ?
userdata dd ?
ends
struct KBDFUNC
strucsize dd ?
close dd ?
setlights dd ?
ends
 
iglobal
keyboards:
dd keyboards
dd keyboards
endg
uglobal
keyboard_list_mutex MUTEX
endg
 
register_keyboard:
push ebx
push sizeof.KEYBOARD
pop eax
call malloc
test eax, eax
jz .nothing
mov ecx, [esp+4+4]
mov [eax+KEYBOARD.functions], ecx
mov ecx, [esp+8+4]
mov [eax+KEYBOARD.userdata], ecx
xchg eax, ebx
mov ecx, keyboard_list_mutex
call mutex_lock
mov ecx, keyboards
mov edx, [ecx+KEYBOARD.prev]
mov [ebx+KEYBOARD.next], ecx
mov [ebx+KEYBOARD.prev], edx
mov [edx+KEYBOARD.next], ebx
mov [ecx+KEYBOARD.prev], ebx
mov ecx, [ebx+KEYBOARD.functions]
cmp [ecx+KBDFUNC.strucsize], KBDFUNC.setlights
jbe .unlock
mov ecx, [ecx+KBDFUNC.setlights]
test ecx, ecx
jz .unlock
stdcall ecx, [ebx+KEYBOARD.userdata], dword [kb_lights]
.unlock:
mov ecx, keyboard_list_mutex
call mutex_unlock
xchg eax, ebx
.nothing:
pop ebx
ret 8
 
delete_keyboard:
push ebx
mov ebx, [esp+4+4]
mov ecx, keyboard_list_mutex
call mutex_lock
mov eax, [ebx+KEYBOARD.next]
mov edx, [ebx+KEYBOARD.prev]
mov [eax+KEYBOARD.prev], edx
mov [edx+KEYBOARD.next], eax
call mutex_unlock
mov ecx, [ebx+KEYBOARD.functions]
cmp [ecx+KBDFUNC.strucsize], KBDFUNC.close
jbe .nothing
mov ecx, [ecx+KBDFUNC.close]
test ecx, ecx
jz .nothing
stdcall ecx, [ebx+KEYBOARD.userdata]
.nothing:
pop ebx
ret 4
;---------------------------------------------------------------------
align 4
irq1:
movzx eax, word[TASK_COUNT]; top window process
movzx eax, word[WIN_POS+eax*2]
shl eax, 8
mov al, [SLOT_BASE+eax+APPDATA.keyboard_mode]
mov [keyboard_mode], al
in al, 0x60
;--------------------------------------
send_scancode:
mov [keyboard_data], al
; ch = scancode
; cl = ext_code
; bh = 0 - normal key
; bh = 1 - modifier (Shift/Ctrl/Alt)
; bh = 2 - extended code
mov ch, al
cmp al, 0xE0
je @f
cmp al, 0xE1
jne .normal_code
@@:
mov bh, 2
mov [ext_code], al
jmp .writekey
;--------------------------------------
.normal_code:
mov cl, 0
xchg cl, [ext_code]
and al, 0x7F
mov bh, 1
;--------------------------------------
@@:
cmp al, 0x5B
jne @f
cmp cl, 0xE0
jne @f
mov eax, VKEY_LWIN
mov bh, 0
jmp .modifier
;--------------------------------------
@@:
cmp al, 0x5C
jne @f
cmp cl, 0xE0
jne @f
mov eax, VKEY_RWIN
mov bh, 0
jmp .modifier
;--------------------------------------
@@:
cmp al, 0x2A
jne @f
cmp cl, 0xE0
je .writekey
mov eax, VKEY_LSHIFT
jmp .modifier
;--------------------------------------
@@:
cmp al, 0x36
jne @f
cmp cl, 0xE0
je .writekey
mov eax, VKEY_RSHIFT
jmp .modifier
;--------------------------------------
@@:
cmp al, 0x38
jne @f
mov eax, VKEY_LALT
test cl, cl
jz .modifier
mov al, VKEY_RALT
jmp .modifier
;--------------------------------------
@@:
cmp al, 0x1D
jne @f
mov eax, VKEY_LCONTROL
test cl, cl
jz .modifier
mov al, VKEY_RCONTROL
cmp cl, 0xE0
jz .modifier
mov [ext_code], cl
jmp .writekey
;--------------------------------------
@@:
cmp al, 0x3A
jne @f
mov bl, 4
mov eax, VKEY_CAPSLOCK
jmp .no_key.xor
;--------------------------------------
@@:
cmp al, 0x45
jne @f
test cl, cl
jnz .writekey
mov bl, 2
mov eax, VKEY_NUMLOCK
jmp .no_key.xor
;--------------------------------------
@@:
cmp al, 0x46
jne @f
mov bl, 1
mov eax, VKEY_SCRLOCK
jmp .no_key.xor
;--------------------------------------
@@:
xor ebx, ebx
test ch, ch
js .writekey
movzx eax, ch ; plain key
mov bl, [keymap+eax]
mov edx, [kb_state]
test dl, VKEY_CONTROL ; ctrl alt del
jz .noctrlaltdel
test dl, VKEY_ALT
jz .noctrlaltdel
cmp ch, 53h
jne .noctrlaltdel
mov [ctrl_alt_del], 1
.noctrlaltdel:
test dl, VKEY_CONTROL ; ctrl on ?
jz @f
sub bl, 0x60
@@:
test dl, VKEY_CAPSLOCK ; caps lock on ?
jz .no_caps_lock
test dl, VKEY_SHIFT ; shift on ?
jz .keymap_shif
jmp @f
;--------------------------------------
.no_caps_lock:
test dl, VKEY_SHIFT ; shift on ?
jz @f
.keymap_shif:
mov bl, [keymap_shift+eax]
@@:
test dl, VKEY_ALT ; alt on ?
jz @f
mov bl, [keymap_alt+eax]
@@:
jmp .writekey
;--------------------------------------
.modifier:
test ch, ch
js .modifier.up
or [kb_state], eax
jmp .writekey
;--------------------------------------
.modifier.up:
not eax
and [kb_state], eax
jmp .writekey
;--------------------------------------
.no_key.xor:
mov bh, 0
test ch, ch
js .writekey
xor [kb_state], eax
xor [kb_lights], bl
.writekey:
pushad
; test for system hotkeys
movzx eax, ch
cmp bh, 1
ja .nohotkey
jb @f
xor eax, eax
@@:
mov eax, [hotkey_scancodes + eax*4]
.hotkey_loop:
test eax, eax
jz .nohotkey
mov cl, 0
call hotkey_do_test
jc .hotkey_cont
mov cl, 2
call hotkey_do_test
jc .hotkey_cont
mov cl, 4
call hotkey_do_test
jnc .hotkey_found
.hotkey_cont:
mov eax, [eax]
jmp .hotkey_loop
;--------------------------------------
.hotkey_found:
mov eax, [eax+8]
; put key in buffer for process in slot eax
mov edi, hotkey_buffer
@@:
cmp dword [edi], 0
jz .found_free
add edi, 8
cmp edi, hotkey_buffer+120*8
jb @b
; no free space - replace first entry
mov edi, hotkey_buffer
.found_free:
mov [edi], eax
movzx eax, ch
cmp bh, 1
jnz @f
xor eax, eax
@@:
mov [edi+4], ax
mov eax, [kb_state]
mov [edi+6], ax
 
cmp [PID_lock_input], dword 0
je .nohotkey
 
popad
jmp .exit.irq1
;--------------------------------------
.nohotkey:
popad
 
cmp [keyboard_mode], 0; return from keymap
jne .scancode
test bh, bh
jnz .exit.irq1
test bl, bl
jz .exit.irq1
 
test [kb_state], VKEY_NUMLOCK
jz .dowrite
cmp cl, 0xE0
jz .dowrite
cmp ch, 55
jnz @f
mov bl, 0x2A ;*
jmp .dowrite
;--------------------------------------
@@:
cmp ch, 71
jb .dowrite
cmp ch, 83
ja .dowrite
movzx eax, ch
mov bl, [numlock_map + eax - 71]
jmp .dowrite
;--------------------------------------
.scancode:
mov bl, ch
.dowrite:
movzx eax, byte[KEY_COUNT]
cmp al, 120
jae .exit.irq1
inc eax
mov [KEY_COUNT], al
mov [KEY_COUNT+eax], bl
.exit.irq1:
mov [check_idle_semaphore], 5
ret
;---------------------------------------------------------------------
set_lights:
push ebx esi
mov ecx, keyboard_list_mutex
call mutex_lock
mov esi, keyboards
.loop:
mov esi, [esi+KEYBOARD.next]
cmp esi, keyboards
jz .done
mov eax, [esi+KEYBOARD.functions]
cmp dword [eax], KBDFUNC.setlights
jbe .loop
mov eax, [eax+KBDFUNC.setlights]
test eax, eax
jz .loop
stdcall eax, [esi+KEYBOARD.userdata], dword [kb_lights]
jmp .loop
.done:
mov ecx, keyboard_list_mutex
call mutex_unlock
pop esi ebx
ret
 
ps2_set_lights:
stdcall disable_irq, 1
mov al, 0xED
call kb_write
mov al, [esp+8]
call kb_write
stdcall enable_irq, 1
ret 8
 
;// mike.dld ]
check_lights_state:
mov al, [kb_lights]
cmp al, [old_kb_lights]
jz .nothing
mov [old_kb_lights], al
call set_lights
.nothing:
ret
;---------------------------------------------------------------------
numlock_map:
db 0x37 ;Num 7
db 0x38 ;Num 8
db 0x39 ;Num 9
db 0x2D ;Num -
db 0x34 ;Num 4
db 0x35 ;Num 5
db 0x36 ;Num 6
db 0x2B ;Num +
db 0x31 ;Num 1
db 0x32 ;Num 2
db 0x33 ;Num 3
db 0x30 ;Num 0
db 0x2E ;Num .
;---------------------------------------------------------------------
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/hid/mousedrv.inc
0,0 → 1,552
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
; check mouse
;
;
; FB00 -> FB0F mouse memory 00 chunk count - FB0A-B x - FB0C-D y
; FB10 -> FB17 mouse color mem
; FB21 x move
; FB22 y move
; FB30 color temp
; FB28 high bits temp
; FB4A -> FB4D FB4A-B x-under - FB4C-D y-under
; FC00 -> FCFE com1/ps2 buffer
; FCFF com1/ps2 buffer count starting from FC00
 
uglobal
;--------------------------------------
align 4
mousecount dd 0x0
mousedata dd 0x0
Y_UNDER_sub_CUR_hot_y_add_curh:
dw 0
Y_UNDER_subtraction_CUR_hot_y:
dw 0
X_UNDER_sub_CUR_hot_x_add_curh:
dw 0
X_UNDER_subtraction_CUR_hot_x:
dw 0
endg
 
iglobal
;--------------------------------------
align 4
mouse_delay dd 10
mouse_speed_factor:
dd 3
mouse_timer_ticks dd 0
endg
;-----------------------------------------------------------------------------
align 4
draw_mouse_under:
; return old picture
cmp [_display.restore_cursor], 0
je @F
 
pushad
movzx eax, word [X_UNDER]
movzx ebx, word [Y_UNDER]
stdcall [_display.restore_cursor], eax, ebx
popad
ret
;--------------------------------------
align 4
@@:
pushad
xor ecx, ecx
xor edx, edx
;--------------------------------------
align 4
mres:
movzx eax, word [X_UNDER]
movzx ebx, word [Y_UNDER]
add eax, ecx
add ebx, edx
push ecx
push edx
push eax
push ebx
mov eax, edx
shl eax, 6
shl ecx, 2
add eax, ecx
add eax, mouseunder
mov ecx, [eax]
pop ebx
pop eax
mov edi, 1 ; force
or ecx, 0x04000000 ; don't save to mouseunder area
; call [putpixel]
call __sys_putpixel
pop edx
pop ecx
inc ecx
cmp ecx, 16
jnz mres
xor ecx, ecx
inc edx
cmp edx, 24
jnz mres
popad
ret
;-----------------------------------------------------------------------------
align 4
save_draw_mouse:
cmp [_display.move_cursor], 0
je .no_hw_cursor
pushad
 
mov [X_UNDER], ax
mov [Y_UNDER], bx
movzx eax, word [MOUSE_Y]
movzx ebx, word [MOUSE_X]
push eax
push ebx
 
; mov ecx, [Screen_Max_X]
; inc ecx
; mul ecx
mov eax, [d_width_calc_area + eax*4]
 
add eax, [_WinMapAddress]
movzx edx, byte [ebx+eax]
shl edx, 8
mov esi, [edx+SLOT_BASE+APPDATA.cursor]
 
cmp esi, [current_cursor]
je .draw
 
mov eax, [TASK_COUNT]
movzx eax, word [WIN_POS+eax*2]
shl eax, 8
 
cmp eax, edx
je @F
 
mov esi, [def_cursor]
cmp esi, [current_cursor]
je .draw
 
@@:
push esi
call [_display.select_cursor]
mov [current_cursor], esi
;--------------------------------------
align 4
.draw:
stdcall [_display.move_cursor], esi
popad
ret
;--------------------------------------
;align 4
;.fail:
; mov ecx, [def_cursor]
; mov [edx+SLOT_BASE+APPDATA.cursor], ecx
; stdcall [_display.move_cursor], ecx ; stdcall: [esp]=ebx,eax
; popad
; ret
;--------------------------------------
align 4
.no_hw_cursor:
pushad
; save & draw
mov [X_UNDER], ax
mov [Y_UNDER], bx
push eax
push ebx
mov ecx, 0
mov edx, 0
;--------------------------------------
align 4
drm:
push eax
push ebx
push ecx
push edx
; helloworld
push ecx
add eax, ecx; save picture under mouse
add ebx, edx
push ecx
or ecx, 0x04000000 ; don't load to mouseunder area
call getpixel
mov [COLOR_TEMP], ecx
pop ecx
mov eax, edx
shl eax, 6
shl ecx, 2
add eax, ecx
add eax, mouseunder
mov ebx, [COLOR_TEMP]
and ebx, 0xffffff
mov [eax], ebx
pop ecx
mov edi, edx ; y cycle
shl edi, 4 ; *16 bytes per row
add edi, ecx ; x cycle
mov esi, edi
add edi, esi
add edi, esi ; *3
add edi, [MOUSE_PICTURE] ; we have our str address
mov esi, edi
add esi, 16*24*3
push ecx
mov ecx, [COLOR_TEMP]
call combine_colors
and ecx, 0xffffff
mov [MOUSE_COLOR_MEM], ecx
pop ecx
pop edx
pop ecx
pop ebx
pop eax
add eax, ecx ; we have x coord+cycle
add ebx, edx ; and y coord+cycle
push ecx
mov ecx, [MOUSE_COLOR_MEM]
mov edi, 1 ; force
or ecx, 0x04000000 ; don't save to mouseunder area
; call [putpixel]
call __sys_putpixel
pop ecx
mov ebx, [esp+0] ; pure y coord again
mov eax, [esp+4] ; and x
inc ecx ; +1 cycle
cmp ecx, 16 ; if more than 16
jnz drm
xor ecx, ecx
inc edx
cmp edx, 24
jnz drm
add esp, 8
popad
ret
;-----------------------------------------------------------------------------
align 4
combine_colors:
; in
; ecx - color ( 00 RR GG BB )
; edi - ref to new color byte
; esi - ref to alpha byte
;
; out
; ecx - new color ( roughly (ecx*[esi]>>8)+([edi]*[esi]>>8) )
push eax
push ebx
push edx
push ecx
xor ecx, ecx
; byte 2
mov eax, 0xff
sub al, [esi+0]
mov ebx, [esp]
shr ebx, 16
and ebx, 0xff
mul ebx
shr eax, 8
add ecx, eax
xor eax, eax
xor ebx, ebx
mov al, [edi+0]
mov bl, [esi+0]
mul ebx
shr eax, 8
add ecx, eax
shl ecx, 8
; byte 1
mov eax, 0xff
sub al, [esi+1]
mov ebx, [esp]
shr ebx, 8
and ebx, 0xff
mul ebx
shr eax, 8
add ecx, eax
xor eax, eax
xor ebx, ebx
mov al, [edi+1]
mov bl, [esi+1]
mul ebx
shr eax, 8
add ecx, eax
shl ecx, 8
; byte 2
mov eax, 0xff
sub al, [esi+2]
mov ebx, [esp]
and ebx, 0xff
mul ebx
shr eax, 8
add ecx, eax
xor eax, eax
xor ebx, ebx
mov al, [edi+2]
mov bl, [esi+2]
mul ebx
shr eax, 8
add ecx, eax
pop eax
pop edx
pop ebx
pop eax
ret
;-----------------------------------------------------------------------------
align 4
check_mouse_area_for_getpixel:
; in:
; eax = x
; ebx = y
; out:
; ecx = new color
push eax ebx
; check for Y
xor ecx, ecx
mov cx, [Y_UNDER] ; [MOUSE_Y]
 
cmp ebx, ecx
jb .no_mouse_area
add ecx, 23 ; mouse cursor Y size
cmp ebx, ecx
ja .no_mouse_area
; offset Y
sub bx, [Y_UNDER] ;[MOUSE_Y]
;--------------------------------------
; check for X
xor ecx, ecx
mov cx, [X_UNDER] ;[MOUSE_X]
cmp eax, ecx
jb .no_mouse_area
add ecx, 15 ; mouse cursor X size
cmp eax, ecx
ja .no_mouse_area
; offset X
sub ax, [X_UNDER] ;[MOUSE_X]
;--------------------------------------
; eax = offset x
; ebx = offset y
shl ebx, 6 ;y
shl eax, 2 ;x
add eax, ebx
add eax, mouseunder
mov ecx, [eax]
and ecx, 0xffffff
or ecx, 0xff000000
pop ebx eax
ret
;--------------------------------------
align 4
.no_mouse_area:
xor ecx, ecx
pop ebx eax
ret
;-----------------------------------------------------------------------------
align 4
check_mouse_area_for_putpixel:
; in:
; ecx = x shl 16 + y
; eax = color
; out:
; eax = new color
push eax
; check for Y
mov ax, [Y_UNDER] ; [MOUSE_Y]
cmp cx, ax
jb .no_mouse_area
add ax, 23 ; mouse cursor Y size
cmp cx, ax
ja .no_mouse_area
; offset Y
sub cx, [Y_UNDER] ;[MOUSE_Y]
mov ax, cx
shl eax, 16
;--------------------------------------
; check for X
mov ax, [X_UNDER] ;[MOUSE_X]
shr ecx, 16
cmp cx, ax
jb .no_mouse_area
add ax, 15 ; mouse cursor X size
cmp cx, ax
ja .no_mouse_area
; offset X
sub cx, [X_UNDER] ;[MOUSE_X]
mov ax, cx
;--------------------------------------
; eax = (offset y) shl 16 + (offset x)
 
pop ecx
 
push eax ebx
 
mov ebx, eax
shr ebx, 16 ;y
and eax, 0xffff ;x
 
shl ebx, 6
shl eax, 2
add eax, ebx
add eax, mouseunder
and ecx, 0xFFFFFF
mov [eax], ecx
 
pop ebx eax
 
push esi edi
rol eax, 16
movzx edi, ax ; y cycle
shl edi, 4 ; *16 bytes per row
shr eax, 16
add edi, eax ; x cycle
lea edi, [edi*3]
add edi, [MOUSE_PICTURE] ; we have our str address
mov esi, edi
add esi, 16*24*3
call combine_colors
pop edi esi
;--------------------------------------
align 4
.end:
mov eax, ecx
ret
;--------------------------------------
align 4
.no_mouse_area:
pop eax
ret
;-----------------------------------------------------------------------------
align 4
__sys_draw_pointer:
pushad
movzx ecx, word [X_UNDER]
movzx edx, word [Y_UNDER]
movzx ebx, word [MOUSE_Y]
movzx eax, word [MOUSE_X]
cmp [redrawmouse_unconditional], 0
je @f
mov [redrawmouse_unconditional], 0
jmp redrawmouse
;--------------------------------------
align 4
@@:
cmp eax, ecx
jne redrawmouse
cmp ebx, edx
je nodmp
;--------------------------------------
align 4
redrawmouse:
pushfd
cli
call draw_mouse_under
call save_draw_mouse
 
; mov eax, [_display.select_cursor]
; test eax, eax
; jz @f
cmp [_display.select_cursor], select_cursor
jne @f
 
xor eax, eax
mov esi, [current_cursor]
 
mov ax, [Y_UNDER]
sub eax, [esi+CURSOR.hot_y]
mov [Y_UNDER_subtraction_CUR_hot_y], ax
add eax, [cur.h]
mov [Y_UNDER_sub_CUR_hot_y_add_curh], ax
 
mov ax, [X_UNDER]
sub eax, [esi+CURSOR.hot_x]
mov [X_UNDER_subtraction_CUR_hot_x], ax
add eax, [cur.w]
mov [X_UNDER_sub_CUR_hot_x_add_curh], ax
;--------------------------------------
align 4
@@:
popfd
;--------------------------------------
align 4
nodmp:
popad
ret
;-----------------------------------------------------------------------------
align 4
proc set_mouse_data stdcall, BtnState:dword, XMoving:dword, YMoving:dword, VScroll:dword, HScroll:dword
 
mov eax, [BtnState]
mov [BTN_DOWN], eax
 
mov eax, [XMoving]
call mouse_acceleration
add ax, [MOUSE_X];[XCoordinate]
cmp ax, 0
jge @@M1
mov eax, 0
jmp @@M2
;--------------------------------------
align 4
@@M1:
cmp ax, [Screen_Max_X];ScreenLength
jl @@M2
mov ax, [Screen_Max_X];ScreenLength-1
;--------------------------------------
align 4
@@M2:
mov [MOUSE_X], ax;[XCoordinate]
 
mov eax, [YMoving]
neg eax
call mouse_acceleration
 
add ax, [MOUSE_Y];[YCoordinate]
cmp ax, 0
jge @@M3
mov ax, 0
jmp @@M4
;--------------------------------------
align 4
@@M3:
cmp ax, [Screen_Max_Y];ScreenHeigth
jl @@M4
mov ax, [Screen_Max_Y];ScreenHeigth-1
;--------------------------------------
align 4
@@M4:
mov [MOUSE_Y], ax;[YCoordinate]
 
mov eax, [VScroll]
add [MOUSE_SCROLL_V], ax
 
mov eax, [HScroll]
add [MOUSE_SCROLL_H], ax
 
mov [mouse_active], 1
mov eax, [timer_ticks]
mov [mouse_timer_ticks], eax
ret
endp
;-----------------------------------------------------------------------------
align 4
mouse_acceleration:
push eax
mov eax, [timer_ticks]
sub eax, [mouse_timer_ticks]
cmp eax, [mouse_delay]
pop eax
ja @f
;push edx
imul eax, [mouse_speed_factor]
;pop edx
;--------------------------------------
align 4
@@:
ret
;-----------------------------------------------------------------------------
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/hid/set_dtc.inc
0,0 → 1,203
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
;setting date,time,clock and alarm-clock
;add sys_settime at servetable as for ex. 22 fcn:
; 22 - SETTING DATE TIME, CLOCK AND ALARM-CLOCK
; ebx =0 - set time ecx - 00SSMMHH
; ebx =1 - set date ecx=00DDMMYY
; ebx =2 - set day of week ecx- 1-7
; ebx =3 - set alarm-clock ecx - 00SSMMHH
; out: 0 -Ok 1 -wrong format 2 -battery low
sys_settime:
cli
mov al, 0x0d
out 0x70, al
in al, 0x71
bt ax, 7
jnc bat_low
cmp ebx, 2;day of week
jne nosetweek
test ecx, ecx ;test day of week
je wrongtime
cmp ecx, 7
ja wrongtime
mov edx, 0x70
call startstopclk
dec edx
mov al, 6
out dx, al
inc edx
mov al, cl
out dx, al
jmp endsettime
nosetweek: ;set date
cmp ebx, 1
jne nosetdate
cmp cl, 0x99;test year
ja wrongtime
shl ecx, 4
cmp cl, 0x90
ja wrongtime
cmp ch, 0x99;test month
ja wrongtime
shr ecx, 4
test ch, ch
je wrongtime
cmp ch, 0x12
ja wrongtime
shl ecx, 8
bswap ecx ;ebx=00YYMMDD
test cl, cl ;test day
je wrongtime
shl ecx, 4
cmp cl, 0x90
ja wrongtime
shr ecx, 4
cmp ch, 2 ;February
jne testday
cmp cl, 0x29
ja wrongtime
jmp setdate
testday:
cmp ch, 8
jb testday1;Aug-Dec
bt cx, 8
jnc days31
jmp days30
testday1:
bt cx, 8 ;Jan-Jul ex.Feb
jnc days30
days31:
cmp cl, 0x31
ja wrongtime
jmp setdate
days30:
cmp cl, 0x30
ja wrongtime
setdate:
mov edx, 0x70
call startstopclk
dec edx
mov al, 7 ;set days
out dx, al
inc edx
mov al, cl
out dx, al
dec edx
mov al, 8 ;set months
out dx, al
inc edx
mov al, ch
out dx, al
dec edx
mov al, 9 ;set years
out dx, al
inc edx
shr ecx, 8
mov al, ch
out dx, al
jmp endsettime
nosetdate: ;set time or alarm-clock
cmp ebx, 3
ja wrongtime
cmp cl, 0x23
ja wrongtime
cmp ch, 0x59
ja wrongtime
shl ecx, 4
cmp cl, 0x90
ja wrongtime
cmp ch, 0x92
ja wrongtime
shl ecx, 4
bswap ecx ;00HHMMSS
cmp cl, 0x59
ja wrongtime
shl ecx, 4
cmp cl, 0x90
ja wrongtime
shr ecx, 4
 
mov edx, 0x70
call startstopclk
dec edx
cmp ebx, 3
je setalarm
xor eax, eax;al=0-set seconds
out dx, al
inc edx
mov al, cl
out dx, al
dec edx
mov al, 2 ;set minutes
out dx, al
inc edx
mov al, ch
out dx, al
dec edx
mov al, 4 ;set hours
out dx, al
inc edx
shr ecx, 8
mov al, ch
out dx, al
jmp endsettime
setalarm:
mov al, 1;set seconds for al.
out dx, al
inc edx
mov al, cl
out dx, al
dec edx
mov al, 3;set minutes for al.
out dx, al
inc edx
mov al, ch
out dx, al
dec edx
mov al, 5;set hours for al.
out dx, al
inc edx
shr ecx, 8
mov al, ch
out dx, al
dec edx
mov al, 0x0b;enable irq's
out dx, al
inc dx
in al, dx
bts ax, 5;set bit 5
out dx, al
endsettime:
dec edx
call startstopclk
sti
and [esp+36-4], dword 0
ret
bat_low:
sti
mov [esp+36-4], dword 2
ret
wrongtime:
sti
mov [esp+36-4], dword 1
ret
 
startstopclk:
mov al, 0x0b
out dx, al
inc dx
in al, dx
btc ax, 7
out dx, al
ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/hid
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/kernel32.inc
0,0 → 1,260
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; KERNEL32.INC ;;
;; ;;
;; Included 32 bit kernel files for MenuetOS ;;
;; ;;
;; This file is kept separate as it will be easier to ;;
;; maintain and compile with an automated SETUP program ;;
;; in the future. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
struct POINT
x dd ?
y dd ?
ends
 
struct RECT
left dd ?
top dd ?
right dd ?
bottom dd ?
ends
 
struct BOX
left dd ?
top dd ?
width dd ?
height dd ?
ends
 
struct DISPMODE
width dw ?
height dw ?
bpp dw ?
freq dw ?
ends
 
; constants definition
WSTATE_NORMAL = 00000000b
WSTATE_MAXIMIZED = 00000001b
WSTATE_MINIMIZED = 00000010b
WSTATE_ROLLEDUP = 00000100b
 
WSTATE_REDRAW = 00000001b
WSTATE_WNDDRAWN = 00000010b
 
WSTYLE_HASCAPTION = 00010000b
WSTYLE_CLIENTRELATIVE = 00100000b
 
struct TASKDATA
event_mask dd ?
pid dd ?
dw ?
state db ?
db ?
dw ?
wnd_number db ?
db ?
mem_start dd ?
counter_sum dd ?
counter_add dd ?
cpu_usage dd ?
ends
 
TSTATE_RUNNING = 0
TSTATE_RUN_SUSPENDED = 1
TSTATE_WAIT_SUSPENDED = 2
TSTATE_ZOMBIE = 3
TSTATE_TERMINATING = 4
TSTATE_WAITING = 5
TSTATE_FREE = 9
 
; structures definition
struct WDATA
box BOX
cl_workarea dd ?
cl_titlebar dd ?
cl_frames dd ?
reserved db ?
fl_wstate db ?
fl_wdrawn db ?
fl_redraw db ?
ends
 
label WDATA.fl_wstyle byte at WDATA.cl_workarea + 3
 
struct DBG_REGS
dr0 dd ?
dr1 dd ?
dr2 dd ?
dr3 dd ?
dr7 dd ?
ends
 
struct APPDATA
app_name rb 11
rb 5
 
fpu_state dd ? ;+16
ev_count_ dd ? ;unused ;+20
exc_handler dd ? ;+24
except_mask dd ? ;+28
pl0_stack dd ? ;+32
heap_base dd ? ;+36
heap_top dd ? ;+40
cursor dd ? ;+44
fd_ev dd ? ;+48
bk_ev dd ? ;+52
fd_obj dd ? ;+56
bk_obj dd ? ;+60
saved_esp dd ? ;+64
io_map rd 2 ;+68
dbg_state dd ? ;+76
cur_dir dd ? ;+80
wait_timeout dd ? ;+84
saved_esp0 dd ? ;+88
wait_begin dd ? ;+92 +++
wait_test dd ? ;+96 +++
wait_param dd ? ;+100 +++
tls_base dd ? ;+104
dlls_list_ptr dd ? ;+108
event_filter dd ? ;+112
rb 12 ;+116
 
wnd_shape dd ? ;+128
wnd_shape_scale dd ? ;+132
dd ? ;+136
mem_size dd ? ;+140
saved_box BOX
ipc_start dd ?
ipc_size dd ?
event_mask dd ?
debugger_slot dd ?
terminate_protection dd ?
keyboard_mode db ?
rb 3
dir_table dd ?
dbg_event_mem dd ?
dbg_regs DBG_REGS
wnd_caption dd ?
wnd_clientbox BOX
 
ends
 
 
; Core functions
include "core/sync.inc" ; macros for synhronization objects
include "core/sys32.inc" ; process management
include "core/sched.inc" ; process scheduling
include "core/syscall.inc" ; system call
include "core/fpu.inc" ; all fpu/sse support
include "core/memory.inc"
include "core/heap.inc" ; kernel and app heap
include "core/malloc.inc" ; small kernel heap
include "core/taskman.inc"
include "core/dll.inc"
include "core/peload.inc" ;
include "core/exports.inc"
include "core/string.inc"
include "core/v86.inc" ; virtual-8086 manager
include "core/irq.inc" ; irq handling functions
include "core/apic.inc" ; Interrupt Controller functions
include "core/timers.inc"
 
; GUI stuff
include "gui/window.inc"
include "gui/event.inc"
include "gui/font.inc"
include "gui/button.inc"
 
; shutdown
 
; file system
 
include "blkdev/disk.inc" ; support for plug-n-play disks
include "blkdev/disk_cache.inc" ; caching for plug-n-play disks
include "fs/fs.inc" ; syscall
include "fs/fat32.inc" ; read / write for fat32 filesystem
include "fs/ntfs.inc" ; read / write for ntfs filesystem
include "fs/fat12.inc" ; read / write for fat12 filesystem
include "blkdev/rd.inc" ; ramdisk read /write
include "fs/fs_lfn.inc" ; syscall, version 2
include "fs/iso9660.inc" ; read for iso9660 filesystem CD
include "fs/ext2.inc" ; read / write for ext2 filesystem
 
; sound
 
include "sound/playnote.inc" ; player Note for Speaker PC
 
; display
 
;include "video/vesa12.inc" ; Vesa 1.2 functions
include "video/vesa20.inc" ; Vesa 2.0 functions
include "video/blitter.inc" ;
include "video/vga.inc" ; VGA 16 color functions
include "video/cursors.inc" ; cursors functions
 
; Network Interface & TCPIP Stack
 
include "network/stack.inc"
 
;include "drivers/uart.inc"
 
 
; Mouse pointer
 
include "gui/mouse.inc"
 
; Window skinning
 
include "gui/skincode.inc"
 
; Pci functions
 
include "bus/pci/pci32.inc"
 
; Floppy drive controller
 
include "blkdev/fdc.inc"
include "blkdev/flp_drv.inc"
 
; IDE cache
include "blkdev/ide_cache.inc"
 
; HD drive controller
include "blkdev/hd_drv.inc"
 
; CD drive controller
 
include "blkdev/cdrom.inc"
include "blkdev/cd_drv.inc"
 
; Character devices
 
include "hid/keyboard.inc"
include "hid/mousedrv.inc"
 
; setting date,time,clock and alarm-clock
 
include "hid/set_dtc.inc"
 
;% -include
 
;parser file names
include "fs/parse_fn.inc"
 
; work with conf lib
include "core/conf_lib.inc"
 
; load external lib
include "core/ext_lib.inc"
 
; list of external functions
include "imports.inc"
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/kernelsp.inc
0,0 → 1,4
; ste archivo debe ser editado con codificaci¢n CP866
 
version db 'Kolibri OS versi¢n 0.7.7.0+ ',13,10,13,10,0
diff16 "fin del c¢digo del kernel",0,$
/kernel/branches/net/memmap.inc
0,0 → 1,280
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; MEMORY MAP
;
; Boot:
;
; 0:9000 byte bits per pixel
; 0:9001 word scanline length
; 0:9008 word vesa video mode
; 0:900A word X res
; 0:900C word Y res
; 0:9010 byte mouse port - not used
; 0:9014 dword Vesa 1.2 pm bank switch
; 0:9018 dword Vesa 2.0 LFB address
; 0:901C byte 0 or 1 : enable MTRR graphics acceleration
; 0:901D byte not used anymore (0 or 1 : enable system log display)
; 0:901E byte 0 or 1 : enable direct lfb write, paging disabled
; 0:901F byte DMA write : 1=yes, 2=no
; 0:9020 8bytes pci data
; 0:9030 byte VRR start enabled 1, 2-no
; 0:9031 word IDEContrRegsBaseAddr
; 0x9040 - dword - entry point of APM BIOS
; 0x9044 - word - version (BCD)
; 0x9046 - word - flags
; 0:907F byte number of BIOS hard disks
; 0:9080 Nbytes BIOS hard disks
; 0:9100 word available physical memory map: number of blocks
; 0:9104 available physical memory map: blocks
;
; Runtime:
;
; 0x00000000 -> 0x7FFFFFFF application 2Gb
 
; 0x80000000 -> 0FFF physical page zero - do not write
; (used by int 13h in some configurations)
;
; 0x80001000 -> 2FFF window_data - 256 entries
;
; 0000 dword x start
; 0004 dword y start
; 0008 dword x size
; 000C dword y size
; 0010 dword color of work area
; 0014 dword color of grab bar
; 0018 dword color of frames
; 001C dword window flags, +30 = window drawn, +31 redraw flag
;
; 3000 -> 4FFF task list - 256 entries
;
; 00 dword process count
; 04 dword no of processes
; 10 dword base of running process at 0x3000+
;
; 20 dword application event mask
; 24 dword PID - process identification number
; 2a byte slot state: 0=running, 1,2=suspended
; 3=zombie, 4=terminate,
; 5=waiting for event, 9 = not used
; 2e byte window number on screen
; 30 dword exact position in memory
; 34 dword counter sum
; 38 dword time stamp counter add
; 3c dword cpu usage in cpu timer tics
;
;
; 5000 -> 68FF free (6k6)
; 6900 -> 6EFF saved picture under mouse pointer (1k5)
;
; 6F00 -> 6FFF free (256)
;
; 7000 -> 7FFF used CD driver
;
; 8000 -> A3FF used FLOPPY driver
;
; A400 -> B0FF free (3k3), unused ACTIVE_PROC_STACK
 
; B100 -> B307 IDT for int_0x00..int_0x40
 
; B308 -> BFFF free (3k3)
 
; C000 -> C3FF window stack C000 no of windows - all in words
; C402 -> C7FF window position in stack
; D000 -> D1FF FDC controller
; D200 -> D3FF FDC controller for Fat12
; D400 -> DFFF free (3k)
; E000 byte multitasking started
; E020 dword putpixel address
; E024 dword getpixel address
; E030 dword Vesa 1.2 pm bank switch address
; E034 -> F1FF free (4k5)
; F200 dword mousepicture -pointer
; F204 dword mouse appearance counter
; F208 -> F2FF free (248)
; F300 dword x & y temp for windowmove
; F304 -> F3FF free (252)
; F400 byte no of keys in buffer
; F401 byte 'buffer'
; F402 -> F4FF reserved for keys
; F500 byte no of buttons in buffer
; F501 dword 'buffer'
; F502 -> F5FF reserved for buttons
; F600 dword tsc / second
; F604 byte (unused?) mouse port: 1 ps2, 2 com1, 3 com2
; F605 -> FAFF free (1k2)
; FB00 -> FB0F mouse memory 00 chunk count, that includes:
; FB08 word -- mouse H-scroll
; FB0A word -- mouse x
; FB0C word -- mouse y
; FB0E word -- mouse V-scroll
; FB10 -> FB17 mouse color mem
; FB21 x move
; FB22 y move
; FB28 high bits temp
; FB30 color temp
; FB40 byte buttons down
; FB44 byte 0 mouse down -> do not draw
; FB4A -> FB4D FB4A-B x-under - FB4C-D y-under
; FBF1 byte bits per pixel
; FC00 -> FCFE com1/ps2 buffer
; FCFF com1/ps2 buffer count starting from FC00
; FD00 -> FDFF free (256)
; FE00 dword screen x size
; FE04 dword screen y size
; FE08 dword screen y multiplier
; FE0C dword screen mode
; FE10 -> FE7F free (112)
; FE80 dword address of LFB in physical
; FE84 dword address of applications memory start in physical ?
; FE88 dword address of button list
; FE8C dword memory to use
; FE90 -> FEFF free (112)
; FF00 byte 1 = system shutdown request
; FF01 byte task activation request?
; FFF0 byte >0 if redraw background request from app
; FFF1 byte free
; FFF2 write and read bank in screen
; FFF4 byte 0 if first mouse draw & do not return picture under
; FFF5 byte 1 do not draw pointer
; FFFF byte do not change task for 1/100 sec.
;
; 0x80010000 -> 6CBFF kernel, 32-bit run-time code (up to 371 Kb)
 
; 0x8006CC00 -> 6DBFF stack at boot time (4Kb)
;
; 0x8006DC00 -> 6E5FF free (2560)
; 0x8006E600 -> 6Efff free (2560)
; 0x8006F000 -> 6FFFF main page directory
 
; 0x80070000 -> 7FFFF data of retrieved disks and partitions (Mario79)
; 0x80080000 -> 8FFFF additional app info, in 256 byte steps - 256 entries
;
; 00 11db name of app running
; 0x10 dword pointer to fpu save area
; 0x14 dword event count
; 0x18 dword user fpu exceptoins handler
; 0x1c dword user sse exceptions handler
; 20 dword PL0 stack base
; 24 dword user heap base
; 28 dword user heap top
; 2c dword window cursor handle
; 30 dword first event in list
; 34 dword last event in list
; 38 dword first kernel object in list
; 3c dword last kernel object in list
; 40 dword thread esp
; 44 dword io permission map page 0
; 48 dword io permission map page 1
; 4c dword debug state: 1= load debug registers
; 50 dword current directory ptr
; 54 dword wait timeout
; 58 dword thread TSS._esp0 (= pl0 stack base + size except for V86)
; 5C-7F unused
;
; 80 dword address of random shaped window area
; 84 byte shape area scale
; 88 dword free
; 8C dword application memory size
; 90 dword window X position save
; 94 dword window Y position save
; 98 dword window X size save
; 9C dword window Y size save
; A0 dword IPC memory start
; A4 dword IPC memory size
; A8 dword event bits: mouse, stack,..
; AC dword 0 or debugger slot
; B0 dword free
; B4 byte keyboard mode: 0 = keymap, 1 = scancodes
; B8 dword physical address of directory table
; BC dword address of debug event memory
; C0 5 dd thread debug registers: DR0,DR1,DR2,DR3,DR7
;
; 0x80090000 -> 9FFFF tmp (64k) - unused?
; 0x800A0000 -> AFFFF screen access area
; 0x800B0000 -> FFFFF bios rest in peace -area (320k) ?
; 0x80100000 -> 27FFFF diskette image (1m5)
; 0x80280000 -> 281FFF ramdisk fat (8k)
; 0x80282000 -> 283FFF floppy fat (8k)
;
; 0x80284000 -> 28BFFF HDD DMA AREA (32k)
; 0x8028C000 -> 297FFF free (48k)
;
; 0x80298000 -> 29FFFF auxiliary table for background smoothing code (32k)
;
; 0x802A0000 -> 2B00FF wav device buffer (64k)
; 0x802A0000 -> 2B00FF wav device status (256)
;
; 0x802B0100 -> 2B3FFD free (15k7)
;
; 0x802B3FEE -> 2B3FEF button info (64K+ 16 + 2 byte)
; 2B3FEE 0000 word number of buttons
; 2B3FF0 first button entry
;
; button entry at 0x10
; +0000 word process number
; +0002 word button id number : bits 00-15
; +0004 word x start
; +0006 word x size
; +0008 word y start
; +000A word y size
; +000C word button id number : bits 16-31
;
; 0x802C4000 -> 2C9FFF area for fast getting offset to LFB (24k)
; BPSLine_calc_area
; 0x802CA000 -> 2CFFFF area for fast getting offset to _WinMapAddress (24k)
; d_width_calc_area
;
; 0x802D0000 -> 2DFFFF reserved port area (64k)
;
; 0000 dword no of port areas reserved
; 0010 dword process id
; dword start port
; dword end port
; dword 0
;
; 0x802E0000 -> 2EFFFF irq data area (64k) ;BOOT_VAR
;
; 0x802F0000 -> 2F3FFF tcp memory stack_data_start eth_data_start (16k)
;
; 0x802F4000 -> 30ffff stack_data | stack_data_end (112k)
;
; 0x80310000 -> 317fff resendQ (32k)
;
; 0x80318000 -> 31ffff skin_data (32k)
;
; 0x80320000 -> 323FF3 draw data - 256 entries (4k)
; 00 dword draw limit - x start
; 04 dword draw limit - y start
; 08 dword draw limit - x end
; 0C dword draw limit - y end
;
; 0x8032BFF4 -> 32BFFF background info
; 0x80323FF4 BgrDrawMode
; 0x80323FF8 BgrDataWidth
; 0x80323FFC BgrDataHeight
;
; 0x80324000 page map (length b = memsize shr 15)
; 0x80324000 + b start of static pagetables
 
; 0x803FFFFF <- no direct address translation beyond this point
; =============================================================
 
; 0x805FF000 -> 5FFF80 TSS
; 0x80600000 -> 601FFF i/o maps
 
; 0x80800000 -> kernel heap
; 0x80FFFFFF heap min limit
; 0xFDBFFFFF heap max limit
 
; 0xF0000000 -> 0xF1FFFFFF PCI-express extended config space
; 0xFDC00000 -> 0xFDFFFFFF page tables 4Mb
; 0xFE000000 -> 0xFFFFFFFF LFB 32Mb
; 0xFE000000 -> 0xFE7FFFFF application available LFB 8Mb
; 0xFE800000 -> 0xFFFFFFFF kernel LFB part 24 Mb
 
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/video/blitter.inc
0,0 → 1,429
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2011-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
struct BLITTER_BLOCK
xmin dd ?
ymin dd ?
xmax dd ?
ymax dd ?
ends
 
 
struct BLITTER
dc RECT
sc RECT
dst_x dd ? ; 32
dst_y dd ? ; 36
src_x dd ? ; 40
src_y dd ? ; 44
w dd ? ; 48
h dd ? ; 52
 
bitmap dd ? ; 56
stride dd ? ; 60
ends
 
 
 
align 4
block_clip:
;esi= clip RECT ptr
;edi= RECT ptr
;return code:
;eax= 0 - draw, 1 - don't draw
 
push ebx
 
mov eax, [edi+RECT.left]
mov ebx, [edi+RECT.right]
mov ecx, [esi+RECT.left] ;clip.left
mov edx, [esi+RECT.right] ;clip.right
 
cmp eax, edx ;left >= clip.right
jge .fail
 
cmp ebx, ecx ;right < clip.left
jl .fail
 
cmp eax, ecx ;left >= clip.left
jae @F
 
mov eax, ecx
@@:
mov [edi+RECT.left], eax
 
cmp ebx, edx ;right <= clip.right
jle @f
mov ebx, edx
@@:
mov [edi+RECT.right], ebx
 
mov eax, [edi+RECT.top]
mov ebx, [edi+RECT.bottom]
mov ecx, [esi+RECT.top] ;clip.top
mov edx, [esi+RECT.bottom] ;clip.bottom
 
cmp eax, edx ;top >= clip.bottom
jge .fail
 
cmp ebx, ecx ;bottom < clip.top
jl .fail
 
cmp eax, ecx ;top >= clip.top
jae @F
 
mov eax, ecx
@@:
mov [edi+RECT.top], eax
 
cmp ebx, edx ;bottom <= clip.bottom
jle @f
mov ebx, edx
@@:
mov [edi+RECT.bottom], ebx
pop ebx
xor eax, eax
ret
.fail:
pop ebx
mov eax, 1
ret
 
 
align 4
blit_clip:
 
.sx0 equ 8
.sy0 equ 12
.sx1 equ 16
.sy1 equ 20
 
.dx0 equ 24
.dy0 equ 28
.dx1 equ 32
.dy1 equ 36
 
 
push edi
push esi
push ebx
sub esp, 40
 
mov ebx, ecx
mov edx, [ecx+BLITTER.src_x]
mov [esp+.sx0], edx
mov eax, [ecx+BLITTER.src_y]
mov [esp+.sy0], eax
add edx, [ecx+BLITTER.w]
add eax, [ecx+BLITTER.h]
mov [esp+.sx1], edx
mov [esp+.sy1], eax
 
lea edi, [esp+.sx0]
lea esi, [ebx+BLITTER.sc]
 
call block_clip
test eax, eax
mov esi, 1
jnz .done
 
mov edi, [esp+.sx0]
mov edx, [ebx+BLITTER.dst_x]
add edx, edi
sub edx, [ebx+BLITTER.src_x]
mov [esp+.dx0], edx
 
mov ecx, [esp+.sy0]
mov eax, [ebx+BLITTER.dst_y]
add eax, ecx
sub eax, [ebx+BLITTER.src_y]
mov [esp+.dy0], eax
 
sub edx, edi
add edx, [esp+.sx1]
mov [esp+.dx1], edx
 
sub eax, ecx
add eax, [esp+.sy1]
mov [esp+.dy1], eax
 
lea edi, [esp+.dx0]
lea esi, [ebx+BLITTER.dc]
call block_clip
test eax, eax
mov esi, 1
jnz .done
 
mov edx, [esp+.dx0]
mov eax, [esp+.dx1]
sub eax, edx
mov [ebx+BLITTER.w], eax
 
mov eax, [esp+.dy0]
mov ecx, [esp+.dy1]
sub ecx, eax
mov [ebx+BLITTER.h], ecx
 
mov ecx, [ebx+BLITTER.src_x]
add ecx, edx
sub ecx, [ebx+BLITTER.dst_x]
mov [ebx+BLITTER.src_x], ecx
 
mov ecx, [ebx+BLITTER.src_y]
add ecx, eax
sub ecx, [ebx+BLITTER.dst_y]
mov [ebx+BLITTER.src_y], ecx
mov [ebx+BLITTER.dst_x], edx
mov [ebx+BLITTER.dst_y], eax
xor esi, esi
.done:
mov eax, esi
add esp, 40
pop ebx
pop esi
pop edi
 
 
purge .sx0
purge .sy0
purge .sx1
purge .sy1
 
purge .dx0
purge .dy0
purge .dx1
purge .dy1
 
ret
 
align 4
blit_32:
push ebp
push edi
push esi
push ebx
sub esp, 72
 
mov eax, [TASK_BASE]
mov ebx, [eax-twdw + WDATA.box.width]
mov edx, [eax-twdw + WDATA.box.height]
inc ebx
inc edx
 
xor eax, eax
 
mov [esp+BLITTER.dc.left], eax
mov [esp+BLITTER.dc.top], eax
mov [esp+BLITTER.dc.right], ebx
mov [esp+BLITTER.dc.bottom], edx
 
mov [esp+BLITTER.sc.left], eax
mov [esp+BLITTER.sc.top], eax
mov eax, [ecx+24]
 
mov [esp+BLITTER.sc.right], eax
mov eax, [ecx+28]
 
mov [esp+BLITTER.sc.bottom], eax
 
mov eax, [ecx]
mov [esp+BLITTER.dst_x], eax
mov eax, [ecx+4]
mov [esp+BLITTER.dst_y], eax
 
mov eax, [ecx+16]
mov [esp+BLITTER.src_x], eax
mov eax, [ecx+20]
mov [esp+BLITTER.src_y], eax
mov eax, [ecx+8]
mov [esp+BLITTER.w], eax
mov eax, [ecx+12]
mov [esp+BLITTER.h], eax
 
 
mov eax, [ecx+32]
mov [esp+56], eax
mov eax, [ecx+36]
mov [esp+60], eax
 
mov ecx, esp
call blit_clip
test eax, eax
jne .L57
 
mov eax, [TASK_BASE]
 
mov ebx, [esp+BLITTER.dst_x]
mov ebp, [esp+BLITTER.dst_y]
add ebx, [eax-twdw + WDATA.box.left]
add ebp, [eax-twdw + WDATA.box.top]
 
mov ecx, ebx
add ecx, [esp+BLITTER.w]
shl ecx, 16
mov cx, bp
add ecx, [esp+BLITTER.h]
 
mov edi, ebp
 
; imul edi, [_display.pitch]
mov edi, [BPSLine_calc_area+edi*4]
; imul ebp, [_display.width]
mov ebp, [d_width_calc_area+ebp*4]
 
add ebp, ebx
add ebp, [_WinMapAddress]
 
mov eax, [esp+BLITTER.src_y]
imul eax, [esp+BLITTER.stride]
mov esi, [esp+BLITTER.src_x]
lea esi, [eax+esi*4]
add esi, [esp+BLITTER.bitmap]
 
mov eax, ecx
mov ecx, [esp+BLITTER.h]
mov edx, [esp+BLITTER.w]
 
test ecx, ecx ;FIXME check clipping
jz .L57
 
test edx, edx
jz .L57
 
cmp [_display.bpp], 32
jne .core_24
 
lea edi, [edi+ebx*4]
 
mov ebx, [CURRENT_TASK]
align 4
.outer32:
xor ecx, ecx
 
align 4
.inner32:
cmp [ebp+ecx], bl
jne .skip
;--------------------------------------
push eax
mov eax, [esi+ecx*4]
 
; check for hardware cursor
cmp [_display.select_cursor], select_cursor
je @f
cmp [_display.select_cursor], 0
jne .no_mouseunder
;--------------------------------------
align 4
@@:
push ecx
 
mov ecx, [esp+4]
ror ecx, 16
sub ecx, edx
rol ecx, 16
sub ecx, [esp+BLITTER.h + 8]
 
; check mouse area for putpixel
call [_display.check_mouse]
pop ecx
;--------------------------------------
align 4
.no_mouseunder:
; store to real LFB
mov [LFB_BASE+edi+ecx*4], eax
pop eax
;--------------------------------------
align 4
.skip:
inc ecx
dec edx
jnz .inner32
 
add esi, [esp+BLITTER.stride]
add edi, [_display.pitch]
add ebp, [_display.width]
 
mov edx, [esp+BLITTER.w]
dec [esp+BLITTER.h]
jnz .outer32
 
.done:
; call [draw_pointer]
; call __sys_draw_pointer
.L57:
add esp, 72
pop ebx
pop esi
pop edi
pop ebp
ret
 
.core_24:
lea ebx, [ebx+ebx*2]
lea edi, [LFB_BASE+edi+ebx]
mov ebx, [CURRENT_TASK]
 
align 4
.outer24:
mov [esp+64], edi
xor ecx, ecx
 
align 4
.inner24:
cmp [ebp+ecx], bl
jne .skip_1
;--------------------------------------
push eax
mov eax, [esi+ecx*4]
 
lea edi, [edi+ecx*2]
 
; check for hardware cursor
cmp [_display.select_cursor], select_cursor
je @f
cmp [_display.select_cursor], 0
jne .no_mouseunder_1
;--------------------------------------
align 4
@@:
push ecx
 
mov ecx, [esp+4]
ror ecx, 16
sub ecx, edx
rol ecx, 16
sub ecx, [esp+BLITTER.h + 8]
 
; check mouse area for putpixel
call [_display.check_mouse]
pop ecx
;--------------------------------------
align 4
.no_mouseunder_1:
mov [edi+ecx], ax
shr eax, 16
mov [edi+ecx+2], al
 
pop eax
;--------------------------------------
align 4
.skip_1:
mov edi, [esp+64]
inc ecx
dec edx
jnz .inner24
 
add esi, [esp+BLITTER.stride]
add edi, [_display.pitch]
add ebp, [_display.width]
 
mov edx, [esp+BLITTER.w]
dec [esp+BLITTER.h]
jnz .outer24
 
jmp .done
/kernel/branches/net/video/cursors.inc
0,0 → 1,1049
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
LOAD_FROM_FILE equ 0
LOAD_FROM_MEM equ 1
LOAD_INDIRECT equ 2
LOAD_SYSTEM equ 3
 
struct BITMAPINFOHEADER
Size dd ?
Width dd ?
Height dd ?
Planes dw ?
BitCount dw ?
Compression dd ?
SizeImage dd ?
XPelsPerMeter dd ?
YPelsPerMeter dd ?
ClrUsed dd ?
ClrImportant dd ?
ends
;------------------------------------------------------------------------------
align 4
proc init_cursor stdcall, dst:dword, src:dword
locals
rBase dd ?
pQuad dd ?
pBits dd ?
pAnd dd ?
width dd ?
height dd ?
counter dd ?
endl
 
mov esi, [src]
add esi, [esi+18]
mov eax, esi
 
cmp [esi+BITMAPINFOHEADER.BitCount], 24
je .img_24
cmp [esi+BITMAPINFOHEADER.BitCount], 8
je .img_8
cmp [esi+BITMAPINFOHEADER.BitCount], 4
je .img_4
;--------------------------------------
align 4
.img_2:
add eax, [esi]
mov [pQuad], eax
add eax, 8
mov [pBits], eax
add eax, 128
mov [pAnd], eax
mov eax, [esi+4]
mov [width], eax
mov ebx, [esi+8]
shr ebx, 1
mov [height], ebx
 
mov edi, [dst]
add edi, 32*31*4
mov [rBase], edi
 
mov esi, [pQuad]
;--------------------------------------
align 4
.l21:
mov ebx, [pBits]
mov ebx, [ebx]
bswap ebx
mov eax, [pAnd]
mov eax, [eax]
bswap eax
mov [counter], 32
;--------------------------------------
align 4
@@:
xor edx, edx
shl eax, 1
setc dl
dec edx
 
xor ecx, ecx
shl ebx, 1
setc cl
mov ecx, [esi+ecx*4]
and ecx, edx
and edx, 0xFF000000
or edx, ecx
mov [edi], edx
 
add edi, 4
dec [counter]
jnz @B
 
add [pBits], 4
add [pAnd], 4
mov edi, [rBase]
sub edi, 128
mov [rBase], edi
sub [height], 1
jnz .l21
ret
;--------------------------------------
align 4
.img_4:
add eax, [esi]
mov [pQuad], eax
add eax, 64
mov [pBits], eax
add eax, 0x200
mov [pAnd], eax
mov eax, [esi+4]
mov [width], eax
mov ebx, [esi+8]
shr ebx, 1
mov [height], ebx
 
mov edi, [dst]
add edi, 32*31*4
mov [rBase], edi
 
mov esi, [pQuad]
mov ebx, [pBits]
;--------------------------------------
align 4
.l4:
mov eax, [pAnd]
mov eax, [eax]
bswap eax
mov [counter], 16
;--------------------------------------
align 4
@@:
xor edx, edx
shl eax, 1
setc dl
dec edx
 
movzx ecx, byte [ebx]
and cl, 0xF0
shr ecx, 2
mov ecx, [esi+ecx]
and ecx, edx
and edx, 0xFF000000
or edx, ecx
mov [edi], edx
 
xor edx, edx
shl eax, 1
setc dl
dec edx
 
movzx ecx, byte [ebx]
and cl, 0x0F
mov ecx, [esi+ecx*4]
and ecx, edx
and edx, 0xFF000000
or edx, ecx
mov [edi+4], edx
 
inc ebx
add edi, 8
dec [counter]
jnz @B
 
add [pAnd], 4
mov edi, [rBase]
sub edi, 128
mov [rBase], edi
sub [height], 1
jnz .l4
ret
;--------------------------------------
align 4
.img_8:
add eax, [esi]
mov [pQuad], eax
add eax, 1024
mov [pBits], eax
add eax, 1024
mov [pAnd], eax
mov eax, [esi+4]
mov [width], eax
mov ebx, [esi+8]
shr ebx, 1
mov [height], ebx
 
mov edi, [dst]
add edi, 32*31*4
mov [rBase], edi
 
mov esi, [pQuad]
mov ebx, [pBits]
;--------------------------------------
align 4
.l81:
mov eax, [pAnd]
mov eax, [eax]
bswap eax
mov [counter], 32
;--------------------------------------
align 4
@@:
xor edx, edx
shl eax, 1
setc dl
dec edx
 
movzx ecx, byte [ebx]
mov ecx, [esi+ecx*4]
and ecx, edx
and edx, 0xFF000000
or edx, ecx
mov [edi], edx
 
inc ebx
add edi, 4
dec [counter]
jnz @B
 
add [pAnd], 4
mov edi, [rBase]
sub edi, 128
mov [rBase], edi
sub [height], 1
jnz .l81
ret
;--------------------------------------
align 4
.img_24:
add eax, [esi]
mov [pQuad], eax
add eax, 0xC00
mov [pAnd], eax
mov eax, [esi+BITMAPINFOHEADER.Width]
mov [width], eax
mov ebx, [esi+BITMAPINFOHEADER.Height]
shr ebx, 1
mov [height], ebx
 
mov edi, [dst]
add edi, 32*31*4
mov [rBase], edi
 
mov esi, [pAnd]
mov ebx, [pQuad]
;--------------------------------------
align 4
.row_24:
mov eax, [esi]
bswap eax
mov [counter], 32
;--------------------------------------
align 4
@@:
xor edx, edx
shl eax, 1
setc dl
dec edx
 
mov ecx, [ebx]
and ecx, 0x00FFFFFF
and ecx, edx
and edx, 0xFF000000
or edx, ecx
mov [edi], edx
add ebx, 3
add edi, 4
dec [counter]
jnz @B
 
add esi, 4
mov edi, [rBase]
sub edi, 128
mov [rBase], edi
sub [height], 1
jnz .row_24
ret
endp
;------------------------------------------------------------------------------
align 4
proc set_cursor stdcall, hcursor:dword
mov eax, [hcursor]
cmp [eax+CURSOR.magic], 'CURS'
jne .fail
; cmp [eax+CURSOR.size], CURSOR_SIZE
; jne .fail
mov ebx, [current_slot]
xchg eax, [ebx+APPDATA.cursor]
ret
;--------------------------------------
align 4
.fail:
mov eax, [def_cursor]
mov ebx, [current_slot]
xchg eax, [ebx+APPDATA.cursor]
ret
endp
;------------------------------------------------------------------------------
align 4
; param
; eax= pid
; ebx= src
; ecx= flags
 
create_cursor:
.src equ esp
.flags equ esp+4
.hcursor equ esp+8
 
sub esp, 4 ;space for .hcursor
push ecx
push ebx
 
mov ebx, eax
mov eax, sizeof.CURSOR
call create_kernel_object
test eax, eax
jz .fail
 
mov [.hcursor], eax
 
xor ebx, ebx
mov [eax+CURSOR.magic], 'CURS'
mov [eax+CURSOR.destroy], destroy_cursor
mov [eax+CURSOR.hot_x], ebx
mov [eax+CURSOR.hot_y], ebx
 
stdcall kernel_alloc, 0x1000
test eax, eax
jz .fail
 
mov edi, [.hcursor]
mov [edi+CURSOR.base], eax
 
mov esi, [.src]
mov ebx, [.flags]
cmp bx, LOAD_INDIRECT
je .indirect
 
movzx ecx, word [esi+10]
movzx edx, word [esi+12]
mov [edi+CURSOR.hot_x], ecx
mov [edi+CURSOR.hot_y], edx
 
stdcall init_cursor, eax, esi
 
align 4
.add_cursor:
mov ecx, [.hcursor]
lea ecx, [ecx+CURSOR.list_next]
lea edx, [_display.cr_list.next]
 
pushfd
cli
list_add ecx, edx ;list_add_tail(new, head)
popfd
 
mov eax, [.hcursor]
cmp [_display.init_cursor], 0
je .fail
 
push eax
call [_display.init_cursor]
add esp, 4
 
mov eax, [.hcursor]
;--------------------------------------
align 4
.fail:
add esp, 12
ret
;--------------------------------------
align 4
.indirect:
shr ebx, 16
movzx ecx, bh
movzx edx, bl
mov [edi+CURSOR.hot_x], ecx
mov [edi+CURSOR.hot_y], edx
 
xchg edi, eax
mov ecx, 1024
cld
rep movsd
jmp .add_cursor
;------------------------------------------------------------------------------
align 4
proc load_cursor stdcall, src:dword, flags:dword
locals
handle dd ?
endl
 
xor eax, eax
cmp [create_cursor], eax
je .fail2
 
mov [handle], eax
cmp word [flags], LOAD_FROM_FILE
jne @F
 
stdcall load_file, [src]
test eax, eax
jz .fail
mov [src], eax
;--------------------------------------
align 4
@@:
push ebx
push esi
push edi
 
mov eax, [CURRENT_TASK]
shl eax, 5
mov eax, [CURRENT_TASK+eax+4]
mov ebx, [src]
mov ecx, [flags]
call create_cursor ;eax, ebx, ecx
mov [handle], eax
 
cmp word [flags], LOAD_FROM_FILE
jne .exit
stdcall kernel_free, [src]
;--------------------------------------
align 4
.exit:
pop edi
pop esi
pop ebx
;--------------------------------------
align 4
.fail:
mov eax, [handle]
;--------------------------------------
align 4
.fail2:
ret
endp
;------------------------------------------------------------------------------
align 4
proc delete_cursor stdcall, hcursor:dword
 
; DEBUGF 1,'K : delete_cursor %x\n', [hcursor]
 
mov esi, [hcursor]
 
cmp [esi+CURSOR.magic], 'CURS'
jne .fail
 
mov ebx, [CURRENT_TASK]
shl ebx, 5
mov ebx, [CURRENT_TASK+ebx+4]
cmp ebx, [esi+CURSOR.pid]
jne .fail
 
mov ebx, [current_slot]
cmp esi, [ebx+APPDATA.cursor]
jne @F
mov eax, [def_cursor]
mov [ebx+APPDATA.cursor], eax
;--------------------------------------
align 4
@@:
mov eax, [hcursor]
call [eax+APPOBJ.destroy]
;--------------------------------------
align 4
.fail:
ret
endp
;------------------------------------------------------------------------------
align 4
; param
; eax= cursor
destroy_cursor:
 
push eax
stdcall kernel_free, [eax+CURSOR.base]
 
mov eax, [esp]
lea eax, [eax+CURSOR.list_next]
 
pushfd
cli
list_del eax
popfd
 
pop eax
call destroy_kernel_object
ret
;------------------------------------------------------------------------------
align 4
select_cursor:
mov eax, [esp+4]
mov [_display.cursor], eax
ret 4
;------------------------------------------------------------------------------
align 4
proc restore_24 stdcall, x:dword, y:dword
 
push ebx
 
mov ebx, [cur_saved_base]
mov edx, [cur.h]
test edx, edx
jz .ret
 
push esi
push edi
 
mov esi, cur_saved_data
mov ecx, [cur.w]
lea ecx, [ecx+ecx*2]
push ecx
;--------------------------------------
align 4
@@:
mov edi, ebx
add ebx, [BytesPerScanLine]
 
mov ecx, [esp]
rep movsb
dec edx
jnz @B
 
pop ecx
pop edi
pop esi
;--------------------------------------
align 4
.ret:
pop ebx
ret
endp
;------------------------------------------------------------------------------
align 4
proc restore_32 stdcall, x:dword, y:dword
 
push ebx
 
mov ebx, [cur_saved_base]
mov edx, [cur.h]
test edx, edx
jz .ret
 
push esi
push edi
 
mov esi, cur_saved_data
;--------------------------------------
align 4
@@:
mov edi, ebx
add ebx, [BytesPerScanLine]
 
mov ecx, [cur.w]
rep movsd
dec edx
jnz @B
 
pop edi
;--------------------------------------
align 4
.ret:
pop esi
pop ebx
ret
endp
;------------------------------------------------------------------------------
align 4
proc move_cursor_24 stdcall, hcursor:dword, x:dword, y:dword
locals
h dd ?
_dx dd ?
_dy dd ?
endl
 
mov esi, [hcursor]
mov ecx, [x]
mov eax, [y]
; mov ebx, [BytesPerScanLine]
 
xor edx, edx
sub ecx, [esi+CURSOR.hot_x]
lea ebx, [ecx+32-1]
mov [x], ecx
sets dl
dec edx
and ecx, edx ;clip x to 0<=x
mov [cur.left], ecx
mov edi, ecx
sub edi, [x]
mov [_dx], edi
 
xor edx, edx
sub eax, [esi+CURSOR.hot_y]
lea edi, [eax+32-1]
mov [y], eax
sets dl
dec edx
and eax, edx ;clip y to 0<=y
mov [cur.top], eax
mov edx, eax
sub edx, [y]
mov [_dy], edx
 
; mul dword [BytesPerScanLine]
mov eax, [BPSLine_calc_area+eax*4]
lea edx, [LFB_BASE+ecx*3]
add edx, eax
mov [cur_saved_base], edx
 
cmp ebx, [Screen_Max_X]
jbe @F
mov ebx, [Screen_Max_X]
;--------------------------------------
align 4
@@:
cmp edi, [Screen_Max_Y]
jbe @F
mov edi, [Screen_Max_Y]
;--------------------------------------
align 4
@@:
mov [cur.right], ebx
mov [cur.bottom], edi
 
sub ebx, [x]
sub edi, [y]
inc ebx
inc edi
sub ebx, [_dx]
sub edi, [_dy]
 
mov [cur.w], ebx
mov [cur.h], edi
mov [h], edi
 
mov eax, edi
mov edi, cur_saved_data
;--------------------------------------
align 4
@@:
mov esi, edx
add edx, [BytesPerScanLine]
mov ecx, [cur.w]
lea ecx, [ecx+ecx*2]
rep movsb
dec eax
jnz @B
 
;draw cursor
mov ebx, [cur_saved_base]
mov eax, [_dy]
shl eax, 5
add eax, [_dx]
 
mov esi, [hcursor]
mov esi, [esi+CURSOR.base]
lea edx, [esi+eax*4]
;--------------------------------------
align 4
.row:
mov ecx, [cur.w]
mov esi, edx
mov edi, ebx
add edx, 32*4
add ebx, [BytesPerScanLine]
;--------------------------------------
align 4
.pix:
lodsd
test eax, 0xFF000000
jz @F
mov [edi], ax
shr eax, 16
mov [edi+2], al
;--------------------------------------
align 4
@@:
add edi, 3
dec ecx
jnz .pix
 
dec [h]
jnz .row
ret
endp
;------------------------------------------------------------------------------
align 4
proc move_cursor_32 stdcall, hcursor:dword, x:dword, y:dword
locals
h dd ?
_dx dd ?
_dy dd ?
endl
 
mov esi, [hcursor]
mov ecx, [x]
mov eax, [y]
 
xor edx, edx
sub ecx, [esi+CURSOR.hot_x]
lea ebx, [ecx+32-1]
mov [x], ecx
sets dl
dec edx
and ecx, edx ;clip x to 0<=x
mov [cur.left], ecx
mov edi, ecx
sub edi, [x]
mov [_dx], edi
 
xor edx, edx
sub eax, [esi+CURSOR.hot_y]
lea edi, [eax+32-1]
mov [y], eax
sets dl
dec edx
and eax, edx ;clip y to 0<=y
mov [cur.top], eax
mov edx, eax
sub edx, [y]
mov [_dy], edx
 
; mul dword [BytesPerScanLine]
mov eax, [BPSLine_calc_area+eax*4]
lea edx, [LFB_BASE+eax+ecx*4]
mov [cur_saved_base], edx
 
cmp ebx, [Screen_Max_X]
jbe @F
mov ebx, [Screen_Max_X]
;--------------------------------------
align 4
@@:
cmp edi, [Screen_Max_Y]
jbe @F
mov edi, [Screen_Max_Y]
;--------------------------------------
align 4
@@:
mov [cur.right], ebx
mov [cur.bottom], edi
 
sub ebx, [x]
sub edi, [y]
inc ebx
inc edi
sub ebx, [_dx]
sub edi, [_dy]
 
mov [cur.w], ebx
mov [cur.h], edi
mov [h], edi
 
mov eax, edi
mov edi, cur_saved_data
;--------------------------------------
align 4
@@:
mov esi, edx
add edx, [BytesPerScanLine]
mov ecx, [cur.w]
rep movsd
dec eax
jnz @B
 
;draw cursor
mov ebx, [cur_saved_base]
mov eax, [_dy]
shl eax, 5
add eax, [_dx]
 
mov esi, [hcursor]
mov esi, [esi+CURSOR.base]
lea edx, [esi+eax*4]
;--------------------------------------
align 4
.row:
mov ecx, [cur.w]
mov esi, edx
mov edi, ebx
add edx, 32*4
add ebx, [BytesPerScanLine]
;--------------------------------------
align 4
.pix:
lodsd
test eax, 0xFF000000
jz @F
mov [edi], eax
;--------------------------------------
align 4
@@:
add edi, 4
dec ecx
jnz .pix
 
dec [h]
jnz .row
ret
endp
;------------------------------------------------------------------------------
align 4
check_mouse_area_for_getpixel_new:
; in:
; eax = x
; ebx = y
; out:
; ecx = new color
;--------------------------------------
; check for Y
cmp bx, [Y_UNDER_subtraction_CUR_hot_y]
jb .no_mouse_area
 
cmp bx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae .no_mouse_area
;--------------------------------------
; check for X
cmp ax, [X_UNDER_subtraction_CUR_hot_x]
jb .no_mouse_area
 
cmp ax, [X_UNDER_sub_CUR_hot_x_add_curh]
jae .no_mouse_area
;--------------------------------------
push eax ebx
; offset X
movzx ecx, word [X_UNDER_subtraction_CUR_hot_x]
sub eax, ecx ; x1
; offset Y
movzx ecx, word [Y_UNDER_subtraction_CUR_hot_y]
sub ebx, ecx ; y1
;--------------------------------------
; ebx = offset y
; eax = offset x
imul ebx, [cur.w] ;y
add eax, ebx
mov ebx, eax
shl eax, 2
cmp [ScreenBPP], byte 32
je @f
sub eax, ebx
;--------------------------------------
align 4
@@:
add eax, cur_saved_data
mov ecx, [eax]
and ecx, 0xffffff
add ecx, 0xff000000
pop ebx eax
ret
;--------------------------------------
align 4
.no_mouse_area:
xor ecx, ecx
ret
;-----------------------------------------------------------------------------
align 4
check_mouse_area_for_putpixel_new:
; in:
; ecx = x shl 16 + y
; eax = color
; out:
; eax = new color
;--------------------------------------
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae .no_mouse_area
 
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb .no_mouse_area
 
rol ecx, 16
;--------------------------------------
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae .no_mouse_area
 
sub cx, [X_UNDER_subtraction_CUR_hot_x]
jb .no_mouse_area
 
ror ecx, 16
;--------------------------------------
align 4
.1:
push eax
;--------------------------------------
; ecx = (offset x) shl 16 + (offset y)
push ebx
mov ebx, ecx
shr ebx, 16 ; x
and ecx, 0xffff ; y
 
cmp ecx, [cur.h]
jae @f
 
cmp ebx, [cur.w]
jb .ok
;--------------------------------------
align 4
@@:
; DEBUGF 1, "K : SHIT HAPPENS: %x %x \n", ecx,ebx
pop ebx
jmp .sh ; SORRY! SHIT HAPPENS!
;--------------------------------------
align 4
.ok:
; ecx = offset y
; ebx = offset x
push ebx ecx
imul ecx, [cur.w] ;y
add ecx, ebx
mov ebx, ecx
shl ecx, 2
cmp [ScreenBPP], byte 24
je .24
and eax, 0xFFFFFF
mov [ecx + cur_saved_data], eax ;store new color to
jmp @f
;--------------------------------------
align 4
.24:
sub ecx, ebx
mov [ecx + cur_saved_data], ax ;store new color to
shr eax, 16
mov [ecx + cur_saved_data + 2], al ;store new color to
;--------------------------------------
align 4
@@:
pop ecx ebx
 
shl ecx, 5
add ecx, ebx
 
mov eax, [current_cursor]
mov eax, [eax+CURSOR.base]
lea eax, [eax+ecx*4]
mov eax, [eax]
 
pop ebx
 
test eax, 0xFF000000
jz @f
 
add esp, 4
ret
;--------------------------------------
align 4
.sh:
mov ecx, -1
;--------------------------------------
align 4
@@:
pop eax
;--------------------------------------
align 4
.no_mouse_area:
ret
;------------------------------------------------------------------------------
align 4
get_display:
mov eax, _display
ret
;------------------------------------------------------------------------------
align 4
init_display:
xor eax, eax
mov edi, _display
 
mov [edi+display_t.init_cursor], eax
mov [edi+display_t.select_cursor], eax
mov [edi+display_t.show_cursor], eax
mov [edi+display_t.move_cursor], eax
mov [edi+display_t.restore_cursor], eax
 
lea ecx, [edi+display_t.cr_list.next]
mov [edi+display_t.cr_list.next], ecx
mov [edi+display_t.cr_list.prev], ecx
 
cmp [SCR_MODE], word 0x13
jbe .fail
 
test word [SCR_MODE], 0x4000
jz .fail
; jmp .fail
 
mov ebx, restore_32
mov ecx, move_cursor_32
movzx eax, byte [ScreenBPP]
cmp eax, 32
je @F
 
mov ebx, restore_24
mov ecx, move_cursor_24
cmp eax, 24
jne .fail
;--------------------------------------
align 4
@@:
mov [_display.select_cursor], select_cursor
mov [_display.move_cursor], ecx
mov [_display.restore_cursor], ebx
mov [_display.check_mouse], check_mouse_area_for_putpixel_new
mov [_display.check_m_pixel], check_mouse_area_for_getpixel_new
 
cmp [PUTPIXEL], dword VGA_putpixel
je @f
cmp [ScreenBPP], byte 32
je .32
mov [PUTPIXEL], dword Vesa20_putpixel24_new
jmp @f
;--------------------------------------
align 4
.32:
mov [PUTPIXEL], dword Vesa20_putpixel32_new
;--------------------------------------
align 4
@@:
stdcall load_cursor, clock_arrow, dword LOAD_FROM_MEM
mov [def_cursor_clock], eax
stdcall load_cursor, def_arrow, dword LOAD_FROM_MEM
mov [def_cursor], eax
ret
;--------------------------------------
align 4
.fail:
xor eax, eax
mov [_display.select_cursor], eax
mov [_display.move_cursor], eax
ret
;------------------------------------------------------------------------------
align 4
def_arrow:
file 'arrow.cur'
;------------------------------------------------------------------------------
align 4
clock_arrow:
file 'arrow_clock.cur'
;------------------------------------------------------------------------------
 
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/video/vesa12.inc
0,0 → 1,1004
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; VESA12.INC ;;
;; ;;
;; Vesa 1.2 functions for MenuetOS ;;
;; ;;
;; Copyright 2002 Ville Turjanmaa ;;
;; ;;
;; quickcode@mail.ru - bankswitch for S3 cards ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
TRIDENT equ 0
S3_VIDEO equ 0
INTEL_VIDEO equ 0
 
if TRIDENT
if S3_VIDEO or INTEL_VIDEO
stop
end if
end if
 
if S3_VIDEO
if TRIDENT or INTEL_VIDEO
stop
end if
end if
 
if INTEL_VIDEO
if S3_VIDEO or TRIDENT
stop
end if
end if
 
 
; A complete video driver should include the following types of function
;
; Putpixel
; Getpixel
;
; Drawimage
; Drawbar
;
; Drawbackground
;
;
; Modifying the set_bank -function is mostly enough
; for different Vesa 1.2 setups.
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
; set_bank for Trident videocards, work on Trident 9440
; modified by Mario79
 
if TRIDENT
set_bank:
pushfd
cli
cmp al, [BANK_RW]
je .retsb
 
mov [BANK_RW], al
push dx
mov dx, 3D8h
out dx, al
pop dx
.retsb:
popfd
ret
end if
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
; set_bank for S3 videocards, work on S3 ViRGE PCI (325)
; modified by kmeaw
 
if S3_VIDEO
set_bank:
pushfd
cli
cmp al, [BANK_RW]
je .retsb
 
mov [BANK_RW], al
push ax
push dx
push cx
mov cl, al
mov dx, 0x3D4
mov al, 0x38
out dx, al ;CR38 Register Lock 1 ;Note: Traditionally 48h is used to
;unlock and 00h to lock
inc dx
mov al, 0x48
out dx, al ;3d5 -?
dec dx
mov al, 0x31
out dx, al ;CR31 Memory Configuration Register
;0 Enable Base Address Offset (CPUA BASE). Enables bank operation if set, ;disables if clear.
;4-5 Bit 16-17 of the Display Start Address. For the 801/5,928 see index 51h,
;for the 864/964 see index 69h.
 
inc dx
in al, dx
dec dx
mov ah, al
mov al, 0x31
out dx, ax
mov al, ah
or al, 9
inc dx
out dx, al
dec dx
mov al, 0x35
out dx, al ;CR35 CRT Register Lock
inc dx
in al, dx
dec dx
and al, 0xF0
mov ch, cl
and ch, 0x0F
or ch, al
mov al, 0x35
out dx, al
inc dx
mov al, ch
out dx, ax
dec dx
mov al, 0x51 ;Extended System Control 2 Register
out dx, al
inc dx
in al, dx
dec dx
and al, 0xF3
shr cl, 2
and cl, 0x0C
or cl, al
mov al, 0x51
out dx, al
inc dx
mov al, cl
out dx, al
dec dx
mov al, 0x38
out dx, al
inc dx
xor al, al
out dx, al
dec dx
pop cx
pop dx
pop ax
.retsb:
popfd
ret
end if
 
;Set bank function for Intel 810/815 chipsets
; *****Modified by Protopopius, Russia.*****
; ********* http://menuetos.hut.ru **************
; ************************************************
 
if INTEL_VIDEO
 
set_bank:
pushfd
cli
 
cmp al, [BANK_RW]
je .retsb
 
mov [BANK_RW], al
push ax
push dx
mov dx, 3CEh
mov ah, al ; Save value for later use
mov al, 10h ; Index GR10 (Address Mapping)
out dx, al ; Select GR10
inc dl
mov al, 3 ; Set bits 0 and 1 (Enable linear page mapping)
out dx, al ; Write value
dec dl
mov al, 11h ; Index GR11 (Page Selector)
out dx, al ; Select GR11
inc dl
mov al, ah ; Write address
out dx, al ; Write the value
pop dx
pop ax
.retsb:
popfd
ret
end if
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
 
if (TRIDENT or S3_VIDEO or INTEL_VIDEO)
else
set_bank:
pushfd
cli
 
cmp al, [BANK_RW]
je .retsb
 
mov [BANK_RW], al
push ax
push dx
mov ah, al
mov dx, 0x03D4
mov al, 0x39
out dx, al
inc dl
mov al, 0xA5
out dx, al
dec dl
mov al, 6Ah
out dx, al
inc dl
mov al, ah
out dx, al
dec dl
mov al, 0x39
out dx, al
inc dl
mov al, 0x5A
out dx, al
dec dl
pop dx
pop ax
 
.retsb:
popfd
ret
end if
 
vesa12_drawbackground:
 
call [_display.disable_mouse]
 
push eax
push ebx
push ecx
push edx
 
xor edx, edx
mov eax, dword[BgrDataWidth]
mov ebx, dword[BgrDataHeight]
mul ebx
mov ebx, 3
mul ebx
mov [imax], eax
mov eax, [draw_data+32+RECT.left]
mov ebx, [draw_data+32+RECT.top]
xor edi, edi;no force
 
v12dp3:
 
push eax
push ebx
 
cmp [BgrDrawMode], dword 1 ; tiled background
jne no_vesa12_tiled_bgr
 
push edx
 
xor edx, edx
div dword [BgrDataWidth]
 
push edx
mov eax, ebx
xor edx, edx
div dword [BgrDataHeight]
mov ebx, edx
pop eax
 
pop edx
 
no_vesa12_tiled_bgr:
 
cmp [BgrDrawMode], dword 2 ; stretched background
jne no_vesa12_stretched_bgr
 
push edx
 
mul dword [BgrDataWidth]
mov ecx, [Screen_Max_X]
inc ecx
div ecx
 
push eax
mov eax, ebx
mul dword [BgrDataHeight]
mov ecx, [Screen_Max_Y]
inc ecx
div ecx
mov ebx, eax
pop eax
 
pop edx
 
no_vesa12_stretched_bgr:
 
 
mov esi, ebx
imul esi, dword [BgrDataWidth]
add esi, eax
lea esi, [esi*3]
add esi, [img_background];IMG_BACKGROUND
pop ebx
pop eax
 
v12di4:
 
mov cl, [esi+2]
shl ecx, 16
mov cx, [esi]
pusha
mov esi, eax
mov edi, ebx
mov eax, [Screen_Max_X]
add eax, 1
mul ebx
add eax, [_WinMapAddress]
cmp [eax+esi], byte 1
jnz v12nbgp
mov eax, [BytesPerScanLine]
mov ebx, edi
mul ebx
add eax, esi
lea eax, [VGABasePtr+eax+esi*2]
cmp [ScreenBPP], byte 24
jz v12bgl3
add eax, esi
 
v12bgl3:
 
push ebx
push eax
 
sub eax, VGABasePtr
 
shr eax, 16
call set_bank
pop eax
and eax, 65535
add eax, VGABasePtr
pop ebx
 
mov [eax], cx
add eax, 2
shr ecx, 16
mov [eax], cl
sti
 
v12nbgp:
 
popa
add esi, 3
inc eax
cmp eax, [draw_data+32+RECT.right]
jg v12nodp31
jmp v12dp3
 
v12nodp31:
 
mov eax, [draw_data+32+RECT.left]
inc ebx
cmp ebx, [draw_data+32+RECT.bottom]
jg v12dp4
jmp v12dp3
 
v12dp4:
 
pop edx
pop ecx
pop ebx
pop eax
ret
 
 
vesa12_drawbar:
 
call [_display.disable_mouse]
 
;; mov [novesachecksum],dword 0
sub edx, ebx
sub ecx, eax
push esi
push edi
push eax
push ebx
push ecx
push edx
mov ecx, [TASK_BASE]
add eax, [ecx-twdw+WDATA.box.left]
add ebx, [ecx-twdw+WDATA.box.top]
push eax
mov eax, ebx ; y
mov ebx, [BytesPerScanLine]
mul ebx
pop ecx
add eax, ecx ; x
add eax, ecx
add eax, ecx
cmp [ScreenBPP], byte 24; 24 or 32 bpp ? - x start
jz dbpi2412
add eax, ecx
 
dbpi2412:
 
add eax, VGABasePtr
mov edi, eax
 
; x size
 
mov eax, [esp+4]; [esp+6]
mov ecx, eax
add ecx, eax
add ecx, eax
cmp [ScreenBPP], byte 24; 24 or 32 bpp ? - x size
jz dbpi24312
add ecx, eax
 
dbpi24312:
 
mov ebx, [esp+0]
 
; check limits ?
 
push eax
push ecx
mov eax, [TASK_BASE]
mov ecx, [eax+draw_data-CURRENT_TASK+RECT.left]
cmp ecx, 0
jnz dbcblimitlset12
mov ecx, [eax+draw_data-CURRENT_TASK+RECT.top]
cmp ecx, 0
jnz dbcblimitlset12
mov ecx, [eax+draw_data-CURRENT_TASK+RECT.right]
cmp ecx, [Screen_Max_X]
jnz dbcblimitlset12
mov ecx, [eax+draw_data-CURRENT_TASK+RECT.bottom]
cmp ecx, [Screen_Max_Y]
jnz dbcblimitlset12
pop ecx
pop eax
push dword 0
jmp dbcblimitlno12
 
dbcblimitlset12:
 
pop ecx
pop eax
push dword 1
 
dbcblimitlno12:
 
cmp [ScreenBPP], byte 24; 24 or 32 bpp ?
jz dbpi24bit12
jmp dbpi32bit12
 
 
; DRAWBAR 24 BBP
 
 
dbpi24bit12:
 
push eax
push ebx
push edx
mov eax, ecx
mov ebx, 3
div ebx
mov ecx, eax
pop edx
pop ebx
pop eax
cld
 
dbnewpi12:
 
push ebx
push edi
push ecx
 
xor edx, edx
mov eax, edi
sub eax, VGABasePtr
mov ebx, 3
div ebx
add eax, [_WinMapAddress]
mov ebx, [CURRENT_TASK]
cld
 
dbnp2412:
 
mov dl, [eax]
push eax
push ecx
cmp dl, bl
jnz dbimp24no12
cmp [esp+5*4], dword 0
jz dbimp24yes12
; call dbcplimit
; jnz dbimp24no12
 
dbimp24yes12:
 
push edi
mov eax, edi
sub eax, VGABasePtr
shr eax, 16
call set_bank
and edi, 0xffff
add edi, VGABasePtr
mov eax, [esp+8+3*4+16+4+4]
stosw
shr eax, 16
stosb
sti
pop edi
add edi, 3
pop ecx
pop eax
inc eax
loop dbnp2412
jmp dbnp24d12
 
dbimp24no12:
 
pop ecx
pop eax
cld
add edi, 3
inc eax
loop dbnp2412
 
dbnp24d12:
 
mov eax, [esp+3*4+16+4]
test eax, 0x80000000
jz nodbgl2412
cmp al, 0
jz nodbgl2412
dec eax
mov [esp+3*4+16+4], eax
 
nodbgl2412:
 
pop ecx
pop edi
pop ebx
add edi, [BytesPerScanLine]
dec ebx
jz dbnonewpi12
jmp dbnewpi12
 
dbnonewpi12:
 
add esp, 7*4
 
ret
 
 
; DRAWBAR 32 BBP
 
 
dbpi32bit12:
 
cld
shr ecx, 2
 
dbnewpi3212:
 
push ebx
push edi
push ecx
 
mov eax, edi
sub eax, VGABasePtr
shr eax, 2
add eax, [_WinMapAddress]
mov ebx, [CURRENT_TASK]
cld
 
dbnp3212:
 
mov dl, [eax]
push eax
push ecx
cmp dl, bl
jnz dbimp32no12
cmp [esp+5*4], dword 0
jz dbimp32yes12
; call dbcplimit
; jnz dbimp32no12
 
dbimp32yes12:
 
push edi
mov eax, edi
sub eax, VGABasePtr
shr eax, 16
call set_bank
and edi, 0xffff
add edi, VGABasePtr
mov eax, [esp+8+3*4+16+4+4]
stosw
shr eax, 16
stosb
sti
pop edi
add edi, 4
inc ebp
pop ecx
pop eax
inc eax
loop dbnp3212
jmp dbnp32d12
 
dbimp32no12:
 
pop ecx
pop eax
inc eax
add edi, 4
inc ebp
loop dbnp3212
 
dbnp32d12:
 
mov eax, [esp+12+16+4]
test eax, 0x80000000
jz nodbgl3212
cmp al, 0
jz nodbgl3212
dec eax
mov [esp+12+16+4], eax
 
nodbgl3212:
 
pop ecx
pop edi
pop ebx
add edi, [BytesPerScanLine]
dec ebx
jz nodbnewpi3212
jmp dbnewpi3212
 
nodbnewpi3212:
 
add esp, 7*4
ret
 
 
Vesa12_putpixel24:
 
mov edi, eax; x
mov eax, ebx; y
lea edi, [edi+edi*2]
mov ebx, [BytesPerScanLine]
mul ebx
add edi, eax
mov eax, edi
shr eax, 16
call set_bank
and edi, 65535
add edi, VGABasePtr
mov eax, [esp+28]
stosw
shr eax, 16
mov [edi], al
sti
ret
 
 
 
Vesa12_putpixel32:
 
mov edi, eax; x
mov eax, ebx; y
shl edi, 2
mov ebx, [BytesPerScanLine]
mul ebx
add edi, eax
mov eax, edi
shr eax, 16
call set_bank
and edi, 65535
add edi, VGABasePtr
mov ecx, [esp+28]
mov [edi], ecx
sti
ret
 
 
Vesa12_getpixel24:
 
mov edi, eax; x
mov eax, ebx; y
lea edi, [edi+edi*2]
mov ebx, [BytesPerScanLine]
mul ebx
add edi, eax
mov eax, edi
shr eax, 16
call set_bank
and edi, 65535
add edi, VGABasePtr
mov ecx, [edi]
and ecx, 255*256*256+255*256+255
sti
ret
 
 
Vesa12_getpixel32:
 
mov edi, eax; x
mov eax, ebx; y
shl edi, 2
mov ebx, [BytesPerScanLine]
xor edx, edx
mul ebx
add edi, eax
mov eax, edi
shr eax, 16
call set_bank
and edi, 65535
add edi, VGABasePtr
mov ecx, [edi]
and ecx, 255*256*256+255*256+255
sti
 
ret
 
 
 
vesa12_putimage:
; ebx = pointer to image
; ecx = size [x|y]
; edx = coordinates [x|y]
; ebp = pointer to 'get' function
; esi = pointer to 'init' function
; edi = parameter for 'get' function
 
; mov ebx,image
; mov ecx,320*65536+240
; mov edx,20*65536+20
 
call [_display.disable_mouse]
 
mov [novesachecksum], dword 0
push esi
push edi
push eax
push ebx
push ecx
push edx
movzx eax, word [esp+2]
movzx ebx, word [esp+0]
mov ecx, [TASK_BASE]
add eax, [ecx-twdw+WDATA.box.left]
add ebx, [ecx-twdw+WDATA.box.top]
push eax
mov eax, ebx ; y
mul dword [BytesPerScanLine]
pop ecx
add eax, ecx ; x
add eax, ecx
add eax, ecx
cmp [ScreenBPP], byte 24; 24 or 32 bpp ? - x start
jz pi2412
add eax, ecx
 
pi2412:
 
add eax, VGABasePtr
mov edi, eax
 
; x size
 
movzx ecx, word [esp+6]
 
mov esi, [esp+8]
movzx ebx, word [esp+4]
 
; check limits while draw ?
 
push ecx
mov eax, [TASK_BASE]
cmp dword [eax+draw_data-CURRENT_TASK+RECT.left], 0
jnz dbcblimitlset212
cmp dword [eax+draw_data-CURRENT_TASK+RECT.top], 0
jnz dbcblimitlset212
mov ecx, [eax+draw_data-CURRENT_TASK+RECT.right]
cmp ecx, [Screen_Max_X]
jnz dbcblimitlset212
mov ecx, [eax+draw_data-CURRENT_TASK+RECT.bottom]
cmp ecx, [Screen_Max_Y]
jnz dbcblimitlset212
pop ecx
push 0
jmp dbcblimitlno212
 
dbcblimitlset212:
 
pop ecx
push 1
 
dbcblimitlno212:
 
cmp [ScreenBPP], byte 24; 24 or 32 bpp ?
jnz pi32bit12
 
pi24bit12:
 
newpi12:
 
push edi
push ecx
push ebx
 
mov edx, edi
sub edx, VGABasePtr
mov ebx, 3
div ebx
add edx, [_WinMapAddress]
mov ebx, [CURRENT_TASK]
mov bh, [esp+4*3]
 
np2412:
 
cmp bl, [edx]
jnz imp24no12
; mov eax,[esi]
push dword [esp+4*3+20]
call ebp
; cmp bh,0
; jz imp24yes12
; call dbcplimit
; jnz imp24no12
 
imp24yes12:
 
push edi
push eax
mov eax, edi
sub eax, VGABasePtr
shr eax, 16
call set_bank
pop eax
and edi, 0xffff
add edi, VGABasePtr
mov [edi], ax
shr eax, 16
mov [edi+2], al
pop edi
 
imp24no12:
 
inc edx
; add esi,3
add edi, 3
dec ecx
jnz np2412
 
np24d12:
 
pop ebx
pop ecx
pop edi
 
add edi, [BytesPerScanLine]
add esi, [esp+32]
cmp ebp, putimage_get1bpp
jz .correct
cmp ebp, putimage_get2bpp
jz .correct
cmp ebp, putimage_get4bpp
jnz @f
.correct:
mov eax, [esp+20]
mov byte[eax], 80h
@@:
dec ebx
jnz newpi12
 
nonewpi12:
 
pop eax edx ecx ebx eax edi esi
xor eax, eax
ret
 
 
pi32bit12:
 
newpi3212:
 
push edi
push ecx
push ebx
 
mov edx, edi
sub edx, VGABasePtr
shr edx, 2
add edx, [_WinMapAddress]
mov ebx, [CURRENT_TASK]
mov bh, [esp+4*3]
 
np3212:
 
cmp bl, [edx]
jnz imp32no12
; mov eax,[esi]
push dword [esp+4*3+20]
call ebp
; cmp bh,0
; jz imp32yes12
; call dbcplimit
; jnz imp32no12
 
imp32yes12:
 
push edi
push eax
mov eax, edi
sub eax, VGABasePtr
shr eax, 16
call set_bank
pop eax
and edi, 0xffff
mov [edi+VGABasePtr], eax
pop edi
 
imp32no12:
 
inc edx
; add esi,3
add edi, 4
dec ecx
jnz np3212
 
np32d12:
 
pop ebx
pop ecx
pop edi
 
add edi, [BytesPerScanLine]
cmp ebp, putimage_get1bpp
jz .correct
cmp ebp, putimage_get2bpp
jz .correct
cmp ebp, putimage_get4bpp
jnz @f
.correct:
mov eax, [esp+20]
mov byte[eax], 80h
@@:
dec ebx
jnz newpi3212
 
nonewpi3212:
 
pop eax edx ecx ebx eax edi esi
xor eax, eax
ret
 
 
vesa12_read_screen_pixel:
 
and eax, 0x3FFFFF
cmp [ScreenBPP], byte 24; 24 or 32 bpp ?
jz v12rsp24
mov edi, eax
shl edi, 2
mov eax, edi
shr eax, 16
call set_bank
and edi, 65535
add edi, VGABasePtr
mov eax, [edi]
and eax, 0x00ffffff
ret
v12rsp24:
 
imul eax, 3
mov edi, eax
shr eax, 16
call set_bank
and edi, 65535
add edi, VGABasePtr
mov eax, [edi]
and eax, 0x00ffffff
ret
 
 
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/video/vesa20.inc
0,0 → 1,2150
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; VESA20.INC ;;
;; ;;
;; Vesa 2.0 functions for MenuetOS ;;
;; ;;
;; Copyright 2002 Ville Turjanmaa ;;
;; Alexey, kgaz@crosswindws.net ;;
;; - Voodoo compatible graphics ;;
;; Juan M. Caravaca ;;
;; - Graphics optimimizations eg. drawline ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
; If you're planning to write your own video driver I suggest
; you replace the VESA12.INC file and see those instructions.
 
;Screen_Max_X equ 0xfe00
;Screen_Max_Y equ 0xfe04
;BytesPerScanLine equ 0xfe08
;LFBAddress equ 0xfe80
;ScreenBPP equ 0xfbf1
 
 
 
;-----------------------------------------------------------------------------
; getpixel
;
; in:
; eax = x coordinate
; ebx = y coordinate
;
; ret:
; ecx = 00 RR GG BB
;-----------------------------------------------------------------------------
align 4
getpixel:
push eax ebx edx edi
call dword [GETPIXEL]
pop edi edx ebx eax
ret
;-----------------------------------------------------------------------------
align 4
Vesa20_getpixel24:
; eax = x
; ebx = y
;--------------------------------------
; check for hardware cursor
cmp [_display.select_cursor], select_cursor
je @f
cmp [_display.select_cursor], 0
jne .no_mouseunder
;--------------------------------------
align 4
@@:
; check mouse area for putpixel
test ecx, 0x04000000 ; don't load to mouseunder area
jnz .no_mouseunder
call [_display.check_m_pixel]
test ecx, ecx ;0xff000000
jnz @f
;--------------------------------------
align 4
.no_mouseunder:
;--------------------------------------
; imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier
mov ebx, [BPSLine_calc_area+ebx*4]
lea edi, [eax+eax*2]; edi = x*3
add edi, ebx ; edi = x*3+(y*y multiplier)
mov ecx, [LFB_BASE+edi]
;--------------------------------------
align 4
@@:
and ecx, 0xffffff
ret
;-----------------------------------------------------------------------------
align 4
Vesa20_getpixel32:
;--------------------------------------
; check for hardware cursor
cmp [_display.select_cursor], select_cursor
je @f
cmp [_display.select_cursor], 0
jne .no_mouseunder
;--------------------------------------
align 4
@@:
; check mouse area for putpixel
test ecx, 0x04000000 ; don't load to mouseunder area
jnz .no_mouseunder
call [_display.check_m_pixel]
test ecx, ecx ;0xff000000
jnz @f
;--------------------------------------
align 4
.no_mouseunder:
;--------------------------------------
; imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier
mov ebx, [BPSLine_calc_area+ebx*4]
lea edi, [ebx+eax*4]; edi = x*4+(y*y multiplier)
mov ecx, [LFB_BASE+edi]
;--------------------------------------
align 4
@@:
and ecx, 0xffffff
ret
;-----------------------------------------------------------------------------
virtual at esp
putimg:
.real_sx dd ?
.real_sy dd ?
.image_sx dd ?
.image_sy dd ?
.image_cx dd ?
.image_cy dd ?
.pti dd ?
.abs_cx dd ?
.abs_cy dd ?
.line_increment dd ?
.winmap_newline dd ?
.screen_newline dd ?
.real_sx_and_abs_cx dd ?
.real_sy_and_abs_cy dd ?
.stack_data = 4*14
.edi dd ?
.esi dd ?
.ebp dd ?
.esp dd ?
.ebx dd ?
.edx dd ?
.ecx dd ?
.eax dd ?
.ret_addr dd ?
.arg_0 dd ?
end virtual
;-----------------------------------------------------------------------------
align 16
; ebx = pointer
; ecx = size [x|y]
; edx = coordinates [x|y]
; ebp = pointer to 'get' function
; esi = pointer to 'init' function
; edi = parameter for 'get' function
vesa20_putimage:
pushad
sub esp, putimg.stack_data
; save pointer to image
mov [putimg.pti], ebx
; unpack the size
mov eax, ecx
and ecx, 0xFFFF
shr eax, 16
mov [putimg.image_sx], eax
mov [putimg.image_sy], ecx
; unpack the coordinates
mov eax, edx
and edx, 0xFFFF
shr eax, 16
mov [putimg.image_cx], eax
mov [putimg.image_cy], edx
; calculate absolute (i.e. screen) coordinates
mov eax, [TASK_BASE]
mov ebx, [eax-twdw + WDATA.box.left]
add ebx, [putimg.image_cx]
mov [putimg.abs_cx], ebx
mov ebx, [eax-twdw + WDATA.box.top]
add ebx, [putimg.image_cy]
mov [putimg.abs_cy], ebx
; real_sx = MIN(wnd_sx-image_cx, image_sx);
mov ebx, [eax-twdw + WDATA.box.width]; ebx = wnd_sx
; \begin{diamond}[20.08.2006]
; note that WDATA.box.width is one pixel less than real window x-size
inc ebx
; \end{diamond}[20.08.2006]
sub ebx, [putimg.image_cx]
ja @f
add esp, putimg.stack_data
popad
ret
;--------------------------------------
align 4
@@:
cmp ebx, [putimg.image_sx]
jbe .end_x
mov ebx, [putimg.image_sx]
;--------------------------------------
align 4
.end_x:
mov [putimg.real_sx], ebx
; init real_sy
mov ebx, [eax-twdw + WDATA.box.height]; ebx = wnd_sy
; \begin{diamond}[20.08.2006]
inc ebx
; \end{diamond}[20.08.2006]
sub ebx, [putimg.image_cy]
ja @f
add esp, putimg.stack_data
popad
ret
;--------------------------------------
align 4
@@:
cmp ebx, [putimg.image_sy]
jbe .end_y
mov ebx, [putimg.image_sy]
;--------------------------------------
align 4
.end_y:
mov [putimg.real_sy], ebx
; line increment
mov eax, [putimg.image_sx]
mov ecx, [putimg.real_sx]
sub eax, ecx
;; imul eax, [putimg.source_bpp]
; lea eax, [eax + eax * 2]
call esi
add eax, [putimg.arg_0]
mov [putimg.line_increment], eax
; winmap new line increment
mov eax, [Screen_Max_X]
inc eax
sub eax, [putimg.real_sx]
mov [putimg.winmap_newline], eax
; screen new line increment
mov eax, [BytesPerScanLine]
movzx ebx, byte [ScreenBPP]
shr ebx, 3
imul ecx, ebx
sub eax, ecx
mov [putimg.screen_newline], eax
; pointer to image
mov esi, [putimg.pti]
; pointer to screen
mov edx, [putimg.abs_cy]
; imul edx, [BytesPerScanLine]
mov edx, [BPSLine_calc_area+edx*4]
mov eax, [putimg.abs_cx]
; movzx ebx, byte [ScreenBPP]
; shr ebx, 3
imul eax, ebx
add edx, eax
; pointer to pixel map
mov eax, [putimg.abs_cy]
; imul eax, [Screen_Max_X]
; add eax, [putimg.abs_cy]
mov eax, [d_width_calc_area + eax*4]
 
add eax, [putimg.abs_cx]
add eax, [_WinMapAddress]
xchg eax, ebp
;--------------------------------------
mov ecx, [putimg.real_sx]
add ecx, [putimg.abs_cx]
mov [putimg.real_sx_and_abs_cx], ecx
mov ecx, [putimg.real_sy]
add ecx, [putimg.abs_cy]
mov [putimg.real_sy_and_abs_cy], ecx
;--------------------------------------
; get process number
mov ebx, [CURRENT_TASK]
cmp byte [ScreenBPP], 32
je put_image_end_32
;--------------------------------------
put_image_end_24:
mov edi, [putimg.real_sy]
;--------------------------------------
; check for hardware cursor
mov ecx, [_display.select_cursor]
cmp ecx, select_cursor
je put_image_end_24_new
cmp ecx, 0
je put_image_end_24_old
;--------------------------------------
align 4
.new_line:
mov ecx, [putimg.real_sx]
;--------------------------------------
align 4
.new_x:
push [putimg.edi]
mov eax, [putimg.ebp+4]
call eax
cmp [ebp], bl
jne .skip
;--------------------------------------
; store to real LFB
mov [LFB_BASE+edx], ax
shr eax, 16
mov [LFB_BASE+edx+2], al
;--------------------------------------
align 4
.skip:
add edx, 3
inc ebp
dec ecx
jnz .new_x
 
add esi, [putimg.line_increment]
add edx, [putimg.screen_newline];[BytesPerScanLine]
add ebp, [putimg.winmap_newline];[Screen_Max_X]
 
cmp [putimg.ebp], putimage_get1bpp
jz .correct
cmp [putimg.ebp], putimage_get2bpp
jz .correct
cmp [putimg.ebp], putimage_get4bpp
jnz @f
;--------------------------------------
align 4
.correct:
mov eax, [putimg.edi]
mov byte [eax], 80h
;--------------------------------------
align 4
@@:
dec edi
jnz .new_line
;--------------------------------------
align 4
.finish:
add esp, putimg.stack_data
popad
ret
;------------------------------------------------------------------------------
align 4
put_image_end_24_old:
;--------------------------------------
align 4
.new_line:
mov ecx, [putimg.real_sx]
;--------------------------------------
align 4
.new_x:
push [putimg.edi]
mov eax, [putimg.ebp+4]
call eax
cmp [ebp], bl
jne .skip
;--------------------------------------
push ecx
 
neg ecx
add ecx, [putimg.real_sx_and_abs_cx + 4]
shl ecx, 16
add ecx, [putimg.real_sy_and_abs_cy + 4]
sub ecx, edi
 
; check mouse area for putpixel
call check_mouse_area_for_putpixel
pop ecx
; store to real LFB
mov [LFB_BASE+edx], ax
shr eax, 16
mov [LFB_BASE+edx+2], al
;--------------------------------------
align 4
.skip:
add edx, 3
inc ebp
dec ecx
jnz .new_x
 
add esi, [putimg.line_increment]
add edx, [putimg.screen_newline];[BytesPerScanLine]
add ebp, [putimg.winmap_newline];[Screen_Max_X]
 
cmp [putimg.ebp], putimage_get1bpp
jz .correct
cmp [putimg.ebp], putimage_get2bpp
jz .correct
cmp [putimg.ebp], putimage_get4bpp
jnz @f
;--------------------------------------
align 4
.correct:
mov eax, [putimg.edi]
mov byte [eax], 80h
;--------------------------------------
align 4
@@:
dec edi
jnz .new_line
jmp put_image_end_24.finish
;------------------------------------------------------------------------------
align 4
put_image_end_24_new:
;--------------------------------------
align 4
.new_line:
mov ecx, [putimg.real_sx]
;--------------------------------------
align 4
.new_x:
push [putimg.edi]
mov eax, [putimg.ebp+4]
call eax
cmp [ebp], bl
jne .skip
;--------------------------------------
push ecx
;--------------------------------------
align 4
.sh:
neg ecx
add ecx, [putimg.real_sx_and_abs_cx + 4]
;--------------------------------------
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae .no_mouse_area
 
sub cx, [X_UNDER_subtraction_CUR_hot_x]
jb .no_mouse_area
 
shl ecx, 16
 
add ecx, [putimg.real_sy_and_abs_cy + 4]
sub ecx, edi
;--------------------------------------
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae .no_mouse_area
 
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb .no_mouse_area
;--------------------------------------
; check mouse area for putpixel
call check_mouse_area_for_putpixel_new.1
cmp ecx, -1 ;SHIT HAPPENS?
jne .no_mouse_area
 
mov ecx, [esp]
jmp .sh
;--------------------------------------
align 4
.no_mouse_area:
pop ecx
; store to real LFB
mov [LFB_BASE+edx], ax
shr eax, 16
mov [LFB_BASE+edx+2], al
;--------------------------------------
align 4
.skip:
add edx, 3
inc ebp
dec ecx
jnz .new_x
 
add esi, [putimg.line_increment]
add edx, [putimg.screen_newline];[BytesPerScanLine]
add ebp, [putimg.winmap_newline];[Screen_Max_X]
 
cmp [putimg.ebp], putimage_get1bpp
jz .correct
cmp [putimg.ebp], putimage_get2bpp
jz .correct
cmp [putimg.ebp], putimage_get4bpp
jnz @f
;--------------------------------------
align 4
.correct:
mov eax, [putimg.edi]
mov byte [eax], 80h
;--------------------------------------
align 4
@@:
dec edi
jnz .new_line
jmp put_image_end_24.finish
;------------------------------------------------------------------------------
align 4
put_image_end_32:
mov edi, [putimg.real_sy]
;--------------------------------------
; check for hardware cursor
mov ecx, [_display.select_cursor]
cmp ecx, select_cursor
je put_image_end_32_new
cmp ecx, 0
je put_image_end_32_old
;--------------------------------------
align 4
.new_line:
mov ecx, [putimg.real_sx]
;--------------------------------------
align 4
.new_x:
push [putimg.edi]
mov eax, [putimg.ebp+4]
call eax
cmp [ebp], bl
jne .skip
;--------------------------------------
; store to real LFB
mov [LFB_BASE+edx], eax
;--------------------------------------
align 4
.skip:
add edx, 4
inc ebp
dec ecx
jnz .new_x
 
add esi, [putimg.line_increment]
add edx, [putimg.screen_newline];[BytesPerScanLine]
add ebp, [putimg.winmap_newline];[Screen_Max_X]
 
cmp [putimg.ebp], putimage_get1bpp
jz .correct
cmp [putimg.ebp], putimage_get2bpp
jz .correct
cmp [putimg.ebp], putimage_get4bpp
jnz @f
;--------------------------------------
align 4
.correct:
mov eax, [putimg.edi]
mov byte [eax], 80h
;--------------------------------------
align 4
@@:
dec edi
jnz .new_line
;--------------------------------------
align 4
.finish:
add esp, putimg.stack_data
popad
cmp [SCR_MODE], dword 0x12
jne @f
call VGA__putimage
;--------------------------------------
align 4
@@:
mov [EGA_counter], 1
ret
;------------------------------------------------------------------------------
align 4
put_image_end_32_old:
;--------------------------------------
align 4
.new_line:
mov ecx, [putimg.real_sx]
;--------------------------------------
align 4
.new_x:
push [putimg.edi]
mov eax, [putimg.ebp+4]
call eax
cmp [ebp], bl
jne .skip
;--------------------------------------
push ecx
 
neg ecx
add ecx, [putimg.real_sx_and_abs_cx + 4]
shl ecx, 16
add ecx, [putimg.real_sy_and_abs_cy + 4]
sub ecx, edi
 
; check mouse area for putpixel
call check_mouse_area_for_putpixel
pop ecx
; store to real LFB
mov [LFB_BASE+edx], eax
;--------------------------------------
align 4
.skip:
add edx, 4
inc ebp
dec ecx
jnz .new_x
 
add esi, [putimg.line_increment]
add edx, [putimg.screen_newline];[BytesPerScanLine]
add ebp, [putimg.winmap_newline];[Screen_Max_X]
 
cmp [putimg.ebp], putimage_get1bpp
jz .correct
cmp [putimg.ebp], putimage_get2bpp
jz .correct
cmp [putimg.ebp], putimage_get4bpp
jnz @f
;--------------------------------------
align 4
.correct:
mov eax, [putimg.edi]
mov byte [eax], 80h
;--------------------------------------
align 4
@@:
dec edi
jnz .new_line
jmp put_image_end_32.finish
;------------------------------------------------------------------------------
align 4
put_image_end_32_new:
;--------------------------------------
align 4
.new_line:
mov ecx, [putimg.real_sx]
;--------------------------------------
align 4
.new_x:
push [putimg.edi]
mov eax, [putimg.ebp+4]
call eax
cmp [ebp], bl
jne .skip
;--------------------------------------
push ecx
;--------------------------------------
align 4
.sh:
neg ecx
add ecx, [putimg.real_sx_and_abs_cx + 4]
;--------------------------------------
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae .no_mouse_area
 
sub cx, [X_UNDER_subtraction_CUR_hot_x]
jb .no_mouse_area
 
shl ecx, 16
 
add ecx, [putimg.real_sy_and_abs_cy + 4]
sub ecx, edi
;--------------------------------------
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae .no_mouse_area
 
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb .no_mouse_area
;--------------------------------------
; check mouse area for putpixel
call check_mouse_area_for_putpixel_new.1
cmp ecx, -1 ;SHIT HAPPENS?
jne .no_mouse_area
 
mov ecx, [esp]
jmp .sh
;--------------------------------------
align 4
.no_mouse_area:
pop ecx
; store to real LFB
mov [LFB_BASE+edx], eax
;--------------------------------------
align 4
.skip:
add edx, 4
inc ebp
dec ecx
jnz .new_x
 
add esi, [putimg.line_increment]
add edx, [putimg.screen_newline];[BytesPerScanLine]
add ebp, [putimg.winmap_newline];[Screen_Max_X]
 
cmp [putimg.ebp], putimage_get1bpp
jz .correct
cmp [putimg.ebp], putimage_get2bpp
jz .correct
cmp [putimg.ebp], putimage_get4bpp
jnz @f
;--------------------------------------
align 4
.correct:
mov eax, [putimg.edi]
mov byte [eax], 80h
;--------------------------------------
align 4
@@:
dec edi
jnz .new_line
jmp put_image_end_32.finish
;------------------------------------------------------------------------------
align 4
__sys_putpixel:
 
; eax = x coordinate
; ebx = y coordinate
; ecx = ?? RR GG BB ; 0x01000000 negation
; 0x02000000 used for draw_rectangle without top line
; for example drawwindow_III and drawwindow_IV
; edi = 0x00000001 force
 
;;; mov [novesachecksum], dword 0
pushad
cmp [Screen_Max_X], eax
jb .exit
cmp [Screen_Max_Y], ebx
jb .exit
test edi, 1 ; force ?
jnz .forced
 
; not forced:
mov edx, [d_width_calc_area + ebx*4]
add edx, [_WinMapAddress]
movzx edx, byte [eax+edx]
cmp edx, [CURRENT_TASK]
jne .exit
;--------------------------------------
align 4
.forced:
; check if negation
test ecx, 0x01000000
jz .noneg
 
call getpixel
not ecx
 
rol ecx, 8
mov cl, [esp+32-8+3]
ror ecx, 8
mov [esp+32-8], ecx
;--------------------------------------
align 4
.noneg:
; OK to set pixel
call dword [PUTPIXEL]; call the real put_pixel function
;--------------------------------------
align 4
.exit:
popad
ret
;-----------------------------------------------------------------------------
align 4
Vesa20_putpixel24:
; eax = x
; ebx = y
mov ecx, eax
shl ecx, 16
mov cx, bx
 
; imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier
mov ebx, [BPSLine_calc_area+ebx*4]
lea edi, [eax+eax*2]; edi = x*3
mov eax, [esp+32-8+4]
;--------------------------------------
; check for hardware cursor
cmp [_display.select_cursor], 0
jne @f
; check mouse area for putpixel
test eax, 0x04000000
jnz @f
call check_mouse_area_for_putpixel
;--------------------------------------
align 4
@@:
; store to real LFB
mov [LFB_BASE+ebx+edi], ax
shr eax, 16
mov [LFB_BASE+ebx+edi+2], al
ret
;-----------------------------------------------------------------------------
align 4
Vesa20_putpixel24_new:
; eax = x
; ebx = y
mov ecx, eax
shl ecx, 16
mov cx, bx
 
; imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier
mov ebx, [BPSLine_calc_area+ebx*4]
lea edi, [eax+eax*2]; edi = x*3
mov eax, [esp+32-8+4]
;--------------------------------------
; check for hardware cursor
cmp [_display.select_cursor], select_cursor
jne @f
; check mouse area for putpixel
test eax, 0x04000000
jnz @f
;--------------------------------------
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae @f
 
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb @f
 
rol ecx, 16
;--------------------------------------
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae @f
 
sub cx, [X_UNDER_subtraction_CUR_hot_x]
jb @f
 
ror ecx, 16
 
call check_mouse_area_for_putpixel_new.1
;--------------------------------------
align 4
@@:
; store to real LFB
mov [LFB_BASE+ebx+edi], ax
shr eax, 16
mov [LFB_BASE+ebx+edi+2], al
ret
;-----------------------------------------------------------------------------
align 4
Vesa20_putpixel32:
; eax = x
; ebx = y
mov ecx, eax
shl ecx, 16
mov cx, bx
 
; imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier
mov ebx, [BPSLine_calc_area+ebx*4]
lea edi, [ebx+eax*4]; edi = x*4+(y*y multiplier)
mov eax, [esp+32-8+4]; eax = color
;--------------------------------------
; check for hardware cursor
cmp [_display.select_cursor], 0
jne @f
; check mouse area for putpixel
test eax, 0x04000000
jnz @f
call check_mouse_area_for_putpixel
;--------------------------------------
align 4
@@:
and eax, 0xffffff
; store to real LFB
mov [LFB_BASE+edi], eax
ret
;-----------------------------------------------------------------------------
align 4
Vesa20_putpixel32_new:
; eax = x
; ebx = y
mov ecx, eax
shl ecx, 16
mov cx, bx
 
; imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier
mov ebx, [BPSLine_calc_area+ebx*4]
lea edi, [ebx+eax*4]; edi = x*4+(y*y multiplier)
mov eax, [esp+32-8+4]; eax = color
;--------------------------------------
; check for hardware cursor
cmp [_display.select_cursor], select_cursor
jne @f
; check mouse area for putpixel
test eax, 0x04000000
jnz @f
;--------------------------------------
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae @f
 
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb @f
 
rol ecx, 16
;--------------------------------------
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae @f
 
sub cx, [X_UNDER_subtraction_CUR_hot_x]
jb @f
 
ror ecx, 16
 
call check_mouse_area_for_putpixel_new.1
;--------------------------------------
align 4
@@:
and eax, 0xffffff
; store to real LFB
mov [LFB_BASE+edi], eax
ret
;-----------------------------------------------------------------------------
align 4
calculate_edi:
; mov edi, ebx
; imul edi, [Screen_Max_X]
; add edi, ebx
mov edi, [d_width_calc_area + ebx*4]
add edi, eax
ret
;-----------------------------------------------------------------------------
; DRAWLINE
;-----------------------------------------------------------------------------
align 4
__sys_draw_line:
; draw a line
; eax = HIWORD = x1
; LOWORD = x2
; ebx = HIWORD = y1
; LOWORD = y2
; ecx = color
; edi = force ?
pusha
 
dl_x1 equ esp+20
dl_y1 equ esp+16
dl_x2 equ esp+12
dl_y2 equ esp+8
dl_dx equ esp+4
dl_dy equ esp+0
 
xor edx, edx ; clear edx
xor esi, esi ; unpack arguments
xor ebp, ebp
mov si, ax ; esi = x2
mov bp, bx ; ebp = y2
shr eax, 16 ; eax = x1
shr ebx, 16 ; ebx = y1
push eax ; save x1
push ebx ; save y1
push esi ; save x2
push ebp ; save y2
; checking x-axis...
sub esi, eax ; esi = x2-x1
push esi ; save y2-y1
jl .x2lx1 ; is x2 less than x1 ?
jg .no_vline ; x1 > x2 ?
mov edx, ebp ; else (if x1=x2)
call vline
push edx ; necessary to rightly restore stack frame at .exit
jmp .exit
;--------------------------------------
align 4
.x2lx1:
neg esi ; get esi absolute value
;--------------------------------------
align 4
.no_vline:
; checking y-axis...
sub ebp, ebx ; ebp = y2-y1
push ebp ; save y2-y1
jl .y2ly1 ; is y2 less than y1 ?
jg .no_hline ; y1 > y2 ?
mov edx, [dl_x2]; else (if y1=y2)
call hline
jmp .exit
;--------------------------------------
align 4
.y2ly1:
neg ebp ; get ebp absolute value
;--------------------------------------
align 4
.no_hline:
cmp ebp, esi
jle .x_rules ; |y2-y1| < |x2-x1| ?
cmp [dl_y2], ebx; make sure y1 is at the begining
jge .no_reverse1
neg dword [dl_dx]
mov edx, [dl_x2]
mov [dl_x2], eax
mov [dl_x1], edx
mov edx, [dl_y2]
mov [dl_y2], ebx
mov [dl_y1], edx
;--------------------------------------
align 4
.no_reverse1:
mov eax, [dl_dx]
cdq ; extend eax sing to edx
shl eax, 16 ; using 16bit fix-point maths
idiv ebp ; eax = ((x2-x1)*65536)/(y2-y1)
;--------------------------------------
; correction for the remainder of the division
shl edx, 1
cmp ebp, edx
jb @f
inc eax
;--------------------------------------
align 4
@@:
;--------------------------------------
mov edx, ebp ; edx = counter (number of pixels to draw)
mov ebp, 1 *65536; <<16 ; ebp = dy = 1.0
mov esi, eax ; esi = dx
jmp .y_rules
;--------------------------------------
align 4
.x_rules:
cmp [dl_x2], eax ; make sure x1 is at the begining
jge .no_reverse2
neg dword [dl_dy]
mov edx, [dl_x2]
mov [dl_x2], eax
mov [dl_x1], edx
mov edx, [dl_y2]
mov [dl_y2], ebx
mov [dl_y1], edx
;--------------------------------------
align 4
.no_reverse2:
xor edx, edx
mov eax, [dl_dy]
cdq ; extend eax sing to edx
shl eax, 16 ; using 16bit fix-point maths
idiv esi ; eax = ((y2-y1)*65536)/(x2-x1)
;--------------------------------------
; correction for the remainder of the division
shl edx, 1
cmp esi, edx
jb @f
inc eax
;--------------------------------------
align 4
@@:
;--------------------------------------
mov edx, esi ; edx = counter (number of pixels to draw)
mov esi, 1 *65536;<< 16 ; esi = dx = 1.0
mov ebp, eax ; ebp = dy
;--------------------------------------
align 4
.y_rules:
mov eax, [dl_x1]
mov ebx, [dl_y1]
shl eax, 16
shl ebx, 16
 
and ecx, 0xFBFFFFFF ;negate 0x04000000 save to mouseunder area
;-----------------------------------------------------------------------------
align 4
.draw:
push eax ebx
;--------------------------------------
; correction for the remainder of the division
test ah, 0x80
jz @f
add eax, 1 shl 16
;--------------------------------------
align 4
@@:
;--------------------------------------
shr eax, 16
;--------------------------------------
; correction for the remainder of the division
test bh, 0x80
jz @f
add ebx, 1 shl 16
;--------------------------------------
align 4
@@:
;--------------------------------------
shr ebx, 16
; and ecx, 0xFBFFFFFF ;negate 0x04000000 save to mouseunder area
; call [putpixel]
call __sys_putpixel
pop ebx eax
add ebx, ebp ; y = y+dy
add eax, esi ; x = x+dx
dec edx
jnz .draw
; force last drawn pixel to be at (x2,y2)
mov eax, [dl_x2]
mov ebx, [dl_y2]
; and ecx, 0xFBFFFFFF ;negate 0x04000000 save to mouseunder area
; call [putpixel]
call __sys_putpixel
;--------------------------------------
align 4
.exit:
add esp, 6*4
popa
; call [draw_pointer]
ret
;------------------------------------------------------------------------------
align 4
hline:
; draw an horizontal line
; eax = x1
; edx = x2
; ebx = y
; ecx = color
; edi = force ?
push eax edx
cmp edx, eax ; make sure x2 is above x1
jge @f
xchg eax, edx
;--------------------------------------
align 4
@@:
and ecx, 0xFBFFFFFF ;negate 0x04000000 save to mouseunder area
;--------------------------------------
align 4
@@:
; call [putpixel]
call __sys_putpixel
inc eax
cmp eax, edx
jle @b
pop edx eax
ret
;------------------------------------------------------------------------------
align 4
vline:
; draw a vertical line
; eax = x
; ebx = y1
; edx = y2
; ecx = color
; edi = force ?
push ebx edx
cmp edx, ebx ; make sure y2 is above y1
jge @f
xchg ebx, edx
;--------------------------------------
align 4
@@:
and ecx, 0xFBFFFFFF ;negate 0x04000000 save to mouseunder area
;--------------------------------------
align 4
@@:
; call [putpixel]
call __sys_putpixel
inc ebx
cmp ebx, edx
jle @b
pop edx ebx
ret
;------------------------------------------------------------------------------
align 4
virtual at esp
drbar:
.bar_sx dd ?
.bar_sy dd ?
.bar_cx dd ?
.bar_cy dd ?
.abs_cx dd ?
.abs_cy dd ?
.real_sx dd ?
.real_sy dd ?
.color dd ?
.line_inc_scr dd ?
.line_inc_map dd ?
.real_sx_and_abs_cx dd ?
.real_sy_and_abs_cy dd ?
.stack_data = 4*13
end virtual
;--------------------------------------
align 4
; eax cx
; ebx cy
; ecx xe
; edx ye
; edi color
vesa20_drawbar:
pushad
sub esp, drbar.stack_data
mov [drbar.color], edi
sub edx, ebx
jle .exit ;// mike.dld, 2005-01-29
sub ecx, eax
jle .exit ;// mike.dld, 2005-01-29
mov [drbar.bar_sy], edx
mov [drbar.bar_sx], ecx
mov [drbar.bar_cx], eax
mov [drbar.bar_cy], ebx
mov edi, [TASK_BASE]
add eax, [edi-twdw + WDATA.box.left]; win_cx
add ebx, [edi-twdw + WDATA.box.top]; win_cy
mov [drbar.abs_cx], eax
mov [drbar.abs_cy], ebx
; real_sx = MIN(wnd_sx-bar_cx, bar_sx);
mov ebx, [edi-twdw + WDATA.box.width]; ebx = wnd_sx
; \begin{diamond}[20.08.2006]
; note that WDATA.box.width is one pixel less than real window x-size
inc ebx
; \end{diamond}[20.08.2006]
sub ebx, [drbar.bar_cx]
ja @f
;--------------------------------------
align 4
.exit: ;// mike.dld, 2005-01-29
add esp, drbar.stack_data
popad
xor eax, eax
inc eax
ret
;--------------------------------------
align 4
@@:
cmp ebx, [drbar.bar_sx]
jbe .end_x
mov ebx, [drbar.bar_sx]
;--------------------------------------
align 4
.end_x:
mov [drbar.real_sx], ebx
; real_sy = MIN(wnd_sy-bar_cy, bar_sy);
mov ebx, [edi-twdw + WDATA.box.height]; ebx = wnd_sy
; \begin{diamond}[20.08.2006]
inc ebx
; \end{diamond}
sub ebx, [drbar.bar_cy]
ja @f
add esp, drbar.stack_data
popad
xor eax, eax
inc eax
ret
;--------------------------------------
align 4
@@:
cmp ebx, [drbar.bar_sy]
jbe .end_y
mov ebx, [drbar.bar_sy]
;--------------------------------------
align 4
.end_y:
mov [drbar.real_sy], ebx
; line_inc_map
mov eax, [Screen_Max_X]
sub eax, [drbar.real_sx]
inc eax
mov [drbar.line_inc_map], eax
; line_inc_scr
mov eax, [drbar.real_sx]
movzx ebx, byte [ScreenBPP]
shr ebx, 3
imul eax, ebx
neg eax
add eax, [BytesPerScanLine]
mov [drbar.line_inc_scr], eax
; pointer to screen
mov edx, [drbar.abs_cy]
; imul edx, [BytesPerScanLine]
mov edx, [BPSLine_calc_area+edx*4]
mov eax, [drbar.abs_cx]
imul eax, ebx
add edx, eax
; pointer to pixel map
mov eax, [drbar.abs_cy]
; imul eax, [Screen_Max_X]
; add eax, [drbar.abs_cy]
mov eax, [d_width_calc_area + eax*4]
 
add eax, [drbar.abs_cx]
add eax, [_WinMapAddress]
xchg eax, ebp
;--------------------------------------
mov ebx, [drbar.real_sx]
add ebx, [drbar.abs_cx]
mov [drbar.real_sx_and_abs_cx], ebx
mov ebx, [drbar.real_sy]
add ebx, [drbar.abs_cy]
mov [drbar.real_sy_and_abs_cy], ebx
 
add edx, LFB_BASE
;--------------------------------------
; get process number
mov ebx, [CURRENT_TASK] ; bl - process num
mov esi, [drbar.real_sy]
mov eax, [drbar.color] ; BBGGRR00
rol eax, 8
mov bh, al ; 0x80 drawing gradient bars
ror eax, 8
cmp byte [ScreenBPP], 24
jne draw_bar_end_32
;--------------------------------------
align 4
draw_bar_end_24:
; eax - color high RRGGBB
; bl - process num
; ecx - temp
; edx - pointer to screen
; esi - counter
; edi - counter
;--------------------------------------
; check for hardware cursor
mov ecx, [_display.select_cursor]
cmp ecx, select_cursor
je draw_bar_end_24_new
cmp ecx, 0
je draw_bar_end_24_old
;--------------------------------------
align 4
.new_y:
mov edi, [drbar.real_sx]
;--------------------------------------
align 4
.new_x:
cmp byte [ebp], bl
jne .skip
;--------------------------------------
; store to real LFB
mov [edx], ax
shr eax, 16
mov [edx + 2], al
;--------------------------------------
align 4
.skip:
; add pixel
add edx, 3
inc ebp
dec edi
jnz .new_x
; add line
add edx, [drbar.line_inc_scr]
add ebp, [drbar.line_inc_map]
; drawing gradient bars
test bh, 0x80
jz @f
test al, al
jz @f
dec al
;--------------------------------------
align 4
@@:
dec esi
jnz .new_y
;--------------------------------------
align 4
.end:
add esp, drbar.stack_data
popad
xor eax, eax
ret
;------------------------------------------------------------------------------
align 4
draw_bar_end_24_old:
;--------------------------------------
align 4
.new_y:
mov edi, [drbar.real_sx]
;--------------------------------------
align 4
.new_x:
cmp byte [ebp], bl
jne .skip
;--------------------------------------
mov ecx, [drbar.real_sx_and_abs_cx]
sub ecx, edi
shl ecx, 16
add ecx, [drbar.real_sy_and_abs_cy]
sub ecx, esi
; check mouse area for putpixel
call check_mouse_area_for_putpixel
; store to real LFB
mov [edx], ax
shr eax, 16
mov [edx + 2], al
mov eax, [drbar.color]
;--------------------------------------
align 4
.skip:
; add pixel
add edx, 3
inc ebp
dec edi
jnz .new_x
; add line
add edx, [drbar.line_inc_scr]
add ebp, [drbar.line_inc_map]
; drawing gradient bars
test bh, 0x80
jz @f
test al, al
jz @f
dec al
;--------------------------------------
align 4
@@:
dec esi
jnz .new_y
jmp draw_bar_end_24.end
;------------------------------------------------------------------------------
align 4
draw_bar_end_24_new:
;--------------------------------------
align 4
.new_y:
mov edi, [drbar.real_sx]
;--------------------------------------
align 4
.new_x:
cmp byte [ebp], bl
jne .skip
;--------------------------------------
mov ecx, [drbar.real_sy_and_abs_cy]
sub ecx, esi
;--------------------------------------
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae .no_mouse_area
 
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb .no_mouse_area
 
rol ecx, 16
add ecx, [drbar.real_sx_and_abs_cx]
sub ecx, edi
;--------------------------------------
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae .no_mouse_area
 
sub cx, [X_UNDER_subtraction_CUR_hot_x]
jb .no_mouse_area
 
ror ecx, 16
;--------------------------------------
; check mouse area for putpixel
push eax
call check_mouse_area_for_putpixel_new.1
mov [edx], ax
shr eax, 16
mov [edx + 2], al
pop eax
jmp .skip
; store to real LFB
;--------------------------------------
align 4
.no_mouse_area:
mov [edx], ax
ror eax, 16
mov [edx + 2], al
rol eax, 16
;--------------------------------------
align 4
.skip:
; add pixel
add edx, 3
inc ebp
dec edi
jnz .new_x
; add line
add edx, [drbar.line_inc_scr]
add ebp, [drbar.line_inc_map]
; drawing gradient bars
test bh, 0x80
jz @f
test al, al
jz @f
dec al
;--------------------------------------
align 4
@@:
dec esi
jnz .new_y
jmp draw_bar_end_24.end
;------------------------------------------------------------------------------
align 4
draw_bar_end_32:
; eax - color high RRGGBB
; bl - process num
; ecx - temp
; edx - pointer to screen
; esi - counter
; edi - counter
;--------------------------------------
; check for hardware cursor
mov ecx, [_display.select_cursor]
cmp ecx, select_cursor
je draw_bar_end_32_new
cmp ecx, 0
je draw_bar_end_32_old
;--------------------------------------
align 4
.new_y:
mov edi, [drbar.real_sx]
;--------------------------------------
align 4
.new_x:
cmp byte [ebp], bl
jne .skip
;--------------------------------------
; store to real LFB
mov [edx], eax
mov eax, [drbar.color]
;--------------------------------------
align 4
.skip:
; add pixel
add edx, 4
inc ebp
dec edi
jnz .new_x
; add line
add edx, [drbar.line_inc_scr]
add ebp, [drbar.line_inc_map]
; drawing gradient bars
test bh, 0x80
jz @f
test al, al
jz @f
dec al
;--------------------------------------
align 4
@@:
dec esi
jnz .new_y
;--------------------------------------
align 4
.end:
add esp, drbar.stack_data
popad
cmp [SCR_MODE], dword 0x12
jne @f
call VGA_draw_bar
;--------------------------------------
align 4
@@:
xor eax, eax
mov [EGA_counter], 1
ret
;------------------------------------------------------------------------------
align 4
draw_bar_end_32_old:
;--------------------------------------
align 4
.new_y:
mov edi, [drbar.real_sx]
;--------------------------------------
align 4
.new_x:
cmp byte [ebp], bl
jne .skip
;--------------------------------------
mov ecx, [drbar.real_sx_and_abs_cx]
sub ecx, edi
shl ecx, 16
add ecx, [drbar.real_sy_and_abs_cy]
sub ecx, esi
 
; check mouse area for putpixel
call check_mouse_area_for_putpixel
; store to real LFB
mov [edx], eax
mov eax, [drbar.color]
;--------------------------------------
align 4
.skip:
; add pixel
add edx, 4
inc ebp
dec edi
jnz .new_x
; add line
add edx, [drbar.line_inc_scr]
add ebp, [drbar.line_inc_map]
; drawing gradient bars
test bh, 0x80
jz @f
test al, al
jz @f
dec al
;--------------------------------------
align 4
@@:
dec esi
jnz .new_y
jmp draw_bar_end_32.end
;------------------------------------------------------------------------------
align 4
draw_bar_end_32_new:
;--------------------------------------
align 4
.new_y:
mov edi, [drbar.real_sx]
;--------------------------------------
align 4
.new_x:
cmp byte [ebp], bl
jne .skip
;--------------------------------------
mov ecx, [drbar.real_sy_and_abs_cy]
sub ecx, esi
;--------------------------------------
; check for Y
cmp cx, [Y_UNDER_sub_CUR_hot_y_add_curh]
jae .no_mouse_area
 
sub cx, [Y_UNDER_subtraction_CUR_hot_y]
jb .no_mouse_area
 
rol ecx, 16
add ecx, [drbar.real_sx_and_abs_cx]
sub ecx, edi
;--------------------------------------
; check for X
cmp cx, [X_UNDER_sub_CUR_hot_x_add_curh]
jae .no_mouse_area
 
sub cx, [X_UNDER_subtraction_CUR_hot_x]
jb .no_mouse_area
 
ror ecx, 16
;--------------------------------------
; check mouse area for putpixel
push eax
call check_mouse_area_for_putpixel_new.1
mov [edx], eax
pop eax
jmp .skip
; store to real LFB
;--------------------------------------
align 4
.no_mouse_area:
mov [edx], eax
;--------------------------------------
align 4
.skip:
; add pixel
add edx, 4
inc ebp
dec edi
jnz .new_x
; add line
add edx, [drbar.line_inc_scr]
add ebp, [drbar.line_inc_map]
; drawing gradient bars
test bh, 0x80
jz @f
test al, al
jz @f
dec al
;--------------------------------------
align 4
@@:
dec esi
jnz .new_y
jmp draw_bar_end_32.end
;------------------------------------------------------------------------------
align 4
vesa20_drawbackground_tiled:
pushad
; External loop for all y from start to end
mov ebx, [draw_data+32+RECT.top] ; y start
;--------------------------------------
align 4
dp2:
mov ebp, [draw_data+32+RECT.left] ; x start
; 1) Calculate pointers in WinMapAddress (does pixel belong to OS thread?) [ebp]
; and LFB data (output for our function) [edi]
; mov eax, [BytesPerScanLine]
; mul ebx
mov eax, [BPSLine_calc_area+ebx*4]
xchg ebp, eax
add ebp, eax
add ebp, eax
add ebp, eax
cmp [ScreenBPP], byte 24 ; 24 or 32 bpp ? - x size
jz @f
add ebp, eax
;--------------------------------------
align 4
@@:
add ebp, LFB_BASE
; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB
call calculate_edi
xchg edi, ebp
add ebp, [_WinMapAddress]
; Now eax=x, ebx=y, edi->output, ebp=offset in WinMapAddress
; 2) Calculate offset in background memory block
push eax
xor edx, edx
mov eax, ebx
div dword [BgrDataHeight] ; edx := y mod BgrDataHeight
pop eax
push eax
mov ecx, [BgrDataWidth]
mov esi, edx
imul esi, ecx ; esi := (y mod BgrDataHeight) * BgrDataWidth
xor edx, edx
div ecx ; edx := x mod BgrDataWidth
sub ecx, edx
add esi, edx ; esi := (y mod BgrDataHeight)*BgrDataWidth + (x mod BgrDataWidth)
pop eax
lea esi, [esi*3]
add esi, [img_background]
xor edx, edx
inc edx
; 3) Loop through redraw rectangle and copy background data
; Registers meaning:
; eax = x, ebx = y (screen coordinates)
; ecx = deltax - number of pixels left in current tile block
; edx = 1
; esi -> bgr memory, edi -> output
; ebp = offset in WinMapAddress
;--------------------------------------
align 4
dp3:
cmp [ebp], dl
jnz nbgp
;--------------------------------------
push eax ecx
 
mov ecx, eax
shl ecx, 16
add ecx, ebx
 
mov eax, [esi]
 
; check for hardware cursor
cmp [_display.select_cursor], select_cursor
je @f
cmp [_display.select_cursor], 0
jne .no_mouseunder
;--------------------------------------
align 4
@@:
and eax, 0xffffff
; check mouse area for putpixel
call [_display.check_mouse]
;--------------------------------------
align 4
.no_mouseunder:
; store to real LFB
mov [edi], ax
shr eax, 16
mov [edi+2], al
 
pop ecx eax
;--------------------------------------
align 4
nbgp:
add esi, 3
add edi, 3
;--------------------------------------
align 4
@@:
cmp [ScreenBPP], byte 25 ; 24 or 32 bpp?
sbb edi, -1 ; +1 for 32 bpp
; I do not use 'inc eax' because this is slightly slower then 'add eax,1'
add ebp, edx
add eax, edx
cmp eax, [draw_data+32+RECT.right]
ja dp4
sub ecx, edx
jnz dp3
; next tile block on x-axis
mov ecx, [BgrDataWidth]
sub esi, ecx
sub esi, ecx
sub esi, ecx
jmp dp3
;--------------------------------------
align 4
dp4:
; next scan line
inc ebx
cmp ebx, [draw_data+32+RECT.bottom]
jbe dp2
popad
mov [EGA_counter], 1
cmp [SCR_MODE], dword 0x12
jne @f
call VGA_drawbackground
;--------------------------------------
align 4
@@:
ret
;------------------------------------------------------------------------------
align 4
vesa20_drawbackground_stretch:
pushad
; Helper variables
; calculate 2^32*(BgrDataWidth-1) mod (ScreenWidth-1)
mov eax, [BgrDataWidth]
dec eax
xor edx, edx
div dword [Screen_Max_X]
push eax ; high
xor eax, eax
div dword [Screen_Max_X]
push eax ; low
; the same for height
mov eax, [BgrDataHeight]
dec eax
xor edx, edx
div dword [Screen_Max_Y]
push eax ; high
xor eax, eax
div dword [Screen_Max_Y]
push eax ; low
; External loop for all y from start to end
mov ebx, [draw_data+32+RECT.top] ; y start
mov ebp, [draw_data+32+RECT.left] ; x start
; 1) Calculate pointers in WinMapAddress (does pixel belong to OS thread?) [ebp]
; and LFB data (output for our function) [edi]
; mov eax, [BytesPerScanLine]
; mul ebx
mov eax, [BPSLine_calc_area+ebx*4]
xchg ebp, eax
add ebp, eax
add ebp, eax
add ebp, eax
cmp [ScreenBPP], byte 24 ; 24 or 32 bpp ? - x size
jz @f
add ebp, eax
;--------------------------------------
align 4
@@:
; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB
call calculate_edi
xchg edi, ebp
; Now eax=x, ebx=y, edi->output, ebp=offset in WinMapAddress
push ebx
push eax
; 2) Calculate offset in background memory block
mov eax, ebx
imul ebx, dword [esp+12]
mul dword [esp+8]
add edx, ebx ; edx:eax = y * 2^32*(BgrDataHeight-1)/(ScreenHeight-1)
mov esi, edx
imul esi, [BgrDataWidth]
push edx
push eax
mov eax, [esp+8]
mul dword [esp+28]
push eax
mov eax, [esp+12]
mul dword [esp+28]
add [esp], edx
pop edx ; edx:eax = x * 2^32*(BgrDataWidth-1)/(ScreenWidth-1)
add esi, edx
lea esi, [esi*3]
add esi, [img_background]
push eax
push edx
push esi
; 3) Smooth horizontal
;--------------------------------------
align 4
bgr_resmooth0:
mov ecx, [esp+8]
mov edx, [esp+4]
mov esi, [esp]
push edi
mov edi, bgr_cur_line
call smooth_line
;--------------------------------------
align 4
bgr_resmooth1:
mov eax, [esp+16+4]
inc eax
cmp eax, [BgrDataHeight]
jae bgr.no2nd
mov ecx, [esp+8+4]
mov edx, [esp+4+4]
mov esi, [esp+4]
add esi, [BgrDataWidth]
add esi, [BgrDataWidth]
add esi, [BgrDataWidth]
mov edi, bgr_next_line
call smooth_line
;--------------------------------------
align 4
bgr.no2nd:
pop edi
;--------------------------------------
align 4
sdp3:
xor esi, esi
mov ecx, [esp+12]
; 4) Loop through redraw rectangle and copy background data
; Registers meaning:
; esi = offset in current line, edi -> output
; ebp = offset in WinMapAddress
; dword [esp] = offset in bgr data
; qword [esp+4] = x * 2^32 * (BgrDataWidth-1) / (ScreenWidth-1)
; qword [esp+12] = y * 2^32 * (BgrDataHeight-1) / (ScreenHeight-1)
; dword [esp+20] = x
; dword [esp+24] = y
; precalculated constants:
; qword [esp+28] = 2^32*(BgrDataHeight-1)/(ScreenHeight-1)
; qword [esp+36] = 2^32*(BgrDataWidth-1)/(ScreenWidth-1)
;--------------------------------------
align 4
sdp3a:
mov eax, [_WinMapAddress]
cmp [ebp+eax], byte 1
jnz snbgp
mov eax, [bgr_cur_line+esi]
test ecx, ecx
jz .novert
mov ebx, [bgr_next_line+esi]
call [overlapping_of_points_ptr]
;--------------------------------------
align 4
.novert:
push ecx
; check for hardware cursor
cmp [_display.select_cursor], select_cursor
je @f
cmp [_display.select_cursor], 0
jne .no_mouseunder
;--------------------------------------
align 4
@@:
mov ecx, [esp+20+4] ;x
shl ecx, 16
add ecx, [esp+24+4] ;y
; check mouse area for putpixel
call [_display.check_mouse]
;--------------------------------------
align 4
.no_mouseunder:
; store to real LFB
mov [LFB_BASE+edi], ax
shr eax, 16
mov [LFB_BASE+edi+2], al
pop ecx
;--------------------------------------
align 4
snbgp:
cmp [ScreenBPP], byte 25
sbb edi, -4
add ebp, 1
mov eax, [esp+20]
add eax, 1
mov [esp+20], eax
add esi, 4
cmp eax, [draw_data+32+RECT.right]
jbe sdp3a
;--------------------------------------
align 4
sdp4:
; next y
mov ebx, [esp+24]
add ebx, 1
mov [esp+24], ebx
cmp ebx, [draw_data+32+RECT.bottom]
ja sdpdone
; advance edi, ebp to next scan line
sub eax, [draw_data+32+RECT.left]
sub ebp, eax
add ebp, [Screen_Max_X]
add ebp, 1
sub edi, eax
sub edi, eax
sub edi, eax
cmp [ScreenBPP], byte 24
jz @f
sub edi, eax
;--------------------------------------
align 4
@@:
add edi, [BytesPerScanLine]
; restore ecx,edx; advance esi to next background line
mov eax, [esp+28]
mov ebx, [esp+32]
add [esp+12], eax
mov eax, [esp+16]
adc [esp+16], ebx
sub eax, [esp+16]
mov ebx, eax
lea eax, [eax*3]
imul eax, [BgrDataWidth]
sub [esp], eax
mov eax, [draw_data+32+RECT.left]
mov [esp+20], eax
test ebx, ebx
jz sdp3
cmp ebx, -1
jnz bgr_resmooth0
push edi
mov esi, bgr_next_line
mov edi, bgr_cur_line
mov ecx, [Screen_Max_X]
inc ecx
rep movsd
jmp bgr_resmooth1
;--------------------------------------
align 4
sdpdone:
add esp, 44
popad
mov [EGA_counter], 1
cmp [SCR_MODE], dword 0x12
jne @f
call VGA_drawbackground
;--------------------------------------
align 4
@@:
ret
 
uglobal
;--------------------------------------
align 4
bgr_cur_line rd 1920 ; maximum width of screen
bgr_next_line rd 1920
;--------------------------------------
endg
;--------------------------------------
align 4
smooth_line:
mov al, [esi+2]
shl eax, 16
mov ax, [esi]
test ecx, ecx
jz @f
mov ebx, [esi+2]
shr ebx, 8
call [overlapping_of_points_ptr]
;--------------------------------------
align 4
@@:
stosd
mov eax, [esp+20+8]
add eax, 1
mov [esp+20+8], eax
cmp eax, [draw_data+32+RECT.right]
ja @f
add ecx, [esp+36+8]
mov eax, edx
adc edx, [esp+40+8]
sub eax, edx
lea eax, [eax*3]
sub esi, eax
jmp smooth_line
;--------------------------------------
align 4
@@:
mov eax, [draw_data+32+RECT.left]
mov [esp+20+8], eax
ret
;------------------------------------------------------------------------------
align 16
overlapping_of_points:
if 0
; this version of procedure works, but is slower than next version
push ecx edx
mov edx, eax
push esi
shr ecx, 24
mov esi, ecx
mov ecx, ebx
movzx ebx, dl
movzx eax, cl
sub eax, ebx
movzx ebx, dh
imul eax, esi
add dl, ah
movzx eax, ch
sub eax, ebx
imul eax, esi
add dh, ah
ror ecx, 16
ror edx, 16
movzx eax, cl
movzx ebx, dl
sub eax, ebx
imul eax, esi
pop esi
add dl, ah
mov eax, edx
pop edx
ror eax, 16
pop ecx
ret
else
push ecx edx
mov edx, eax
push esi
shr ecx, 26
mov esi, ecx
mov ecx, ebx
shl esi, 9
movzx ebx, dl
movzx eax, cl
sub eax, ebx
movzx ebx, dh
add dl, [BgrAuxTable+(eax+0x100)+esi]
movzx eax, ch
sub eax, ebx
add dh, [BgrAuxTable+(eax+0x100)+esi]
ror ecx, 16
ror edx, 16
movzx eax, cl
movzx ebx, dl
sub eax, ebx
add dl, [BgrAuxTable+(eax+0x100)+esi]
pop esi
mov eax, edx
pop edx
ror eax, 16
pop ecx
ret
end if
 
iglobal
;--------------------------------------
align 4
overlapping_of_points_ptr dd overlapping_of_points
;--------------------------------------
endg
;------------------------------------------------------------------------------
align 4
init_background:
mov edi, BgrAuxTable
xor edx, edx
;--------------------------------------
align 4
.loop2:
mov eax, edx
shl eax, 8
neg eax
mov ecx, 0x200
;--------------------------------------
align 4
.loop1:
mov byte [edi], ah
inc edi
add eax, edx
loop .loop1
add dl, 4
jnz .loop2
test byte [cpu_caps+(CAPS_MMX/8)], 1 shl (CAPS_MMX mod 8)
jz @f
mov [overlapping_of_points_ptr], overlapping_of_points_mmx
;--------------------------------------
align 4
@@:
ret
;------------------------------------------------------------------------------
align 16
overlapping_of_points_mmx:
movd mm0, eax
movd mm4, eax
movd mm1, ebx
pxor mm2, mm2
punpcklbw mm0, mm2
punpcklbw mm1, mm2
psubw mm1, mm0
movd mm3, ecx
psrld mm3, 24
packuswb mm3, mm3
packuswb mm3, mm3
pmullw mm1, mm3
psrlw mm1, 8
packuswb mm1, mm2
paddb mm4, mm1
movd eax, mm4
ret
;------------------------------------------------------------------------------
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/video/arrow_clock.cur
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/kernel/branches/net/video/vga.inc
0,0 → 1,534
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; VGA.INC ;;
;; ;;
;; 640x480 mode 0x12 VGA functions for MenuetOS ;;
;; ;;
;; Paul Butcher, paul.butcher@asa.co.uk ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
;------------------------------------------------------------------------------
align 4
paletteVGA:
 
;16 colour palette
mov dx, 0x3c8
mov al, 0
out dx, al
 
mov ecx, 16
mov dx, 0x3c9
xor eax, eax
;--------------------------------------
align 4
palvganew:
mov al, 0
test ah, 4
jz palvgalbl1
add al, 31
test ah, 8
jz palvgalbl1
add al, 32
;--------------------------------------
align 4
palvgalbl1:
out dx, al; red 0,31 or 63
mov al, 0
test ah, 2
jz palvgalbl2
add al, 31
test ah, 8
jz palvgalbl2
add al, 32
;--------------------------------------
align 4
palvgalbl2:
out dx, al; blue 0,31 or 63
mov al, 0
test ah, 1
jz palvgalbl3
add al, 31
test ah, 8
jz palvgalbl3
add al, 32
;--------------------------------------
align 4
palvgalbl3:
out dx, al; green 0,31 or 63
add ah, 1
loop palvganew
; mov dx, 3ceh
; mov ax, 0005h
; out dx, ax
ret
;------------------------------------------------------------------------------
align 4
palette320x200:
mov edx, 0x3c8
xor eax, eax
out dx, al
mov ecx, 256
mov edx, 0x3c9
xor eax, eax
;--------------------------------------
align 4
palnew:
mov al, 0
test ah, 64
jz pallbl1
add al, 21
;--------------------------------------
align 4
pallbl1:
test ah, 128
jz pallbl2
add al, 42
;--------------------------------------
align 4
pallbl2:
out dx, al
mov al, 0
test ah, 8
jz pallbl3
add al, 8
;--------------------------------------
align 4
pallbl3:
test ah, 16
jz pallbl4
add al, 15
;--------------------------------------
align 4
pallbl4:
test ah, 32
jz pallbl5
add al, 40
;--------------------------------------
align 4
pallbl5:
out dx, al
mov al, 0
test ah, 1
jz pallbl6
add al, 8
;--------------------------------------
align 4
pallbl6:
test ah, 2
jz pallbl7
add al, 15
;--------------------------------------
align 4
pallbl7:
test ah, 4
jz pallbl8
add al, 40
;--------------------------------------
align 4
pallbl8:
out dx, al
add ah, 1
loop palnew
ret
;------------------------------------------------------------------------------
align 4
uglobal
novesachecksum dd 0x0
EGA_counter db 0
VGA_drawing_screen db 0
VGA_8_pixels:
rb 16
temp:
.cx dd 0
endg
;------------------------------------------------------------------------------
align 4
checkVga_N13:
cmp [SCR_MODE], dword 0x13
jne @f
 
pushad
cmp [EGA_counter], 1
je novesal
mov ecx, [MOUSE_X]
cmp ecx, [novesachecksum]
jne novesal
popad
;--------------------------------------
align 4
@@:
ret
;--------------------------------------
align 4
novesal:
mov [novesachecksum], ecx
mov ecx, 0
movzx eax, word [MOUSE_Y]
cmp eax, 100
jge m13l3
mov eax, 100
;--------------------------------------
align 4
m13l3:
cmp eax, 480-100
jbe m13l4
mov eax, 480-100
;--------------------------------------
align 4
m13l4:
sub eax, 100
imul eax, 640*4
add ecx, eax
movzx eax, word [MOUSE_X]
cmp eax, 160
jge m13l1
mov eax, 160
;--------------------------------------
align 4
m13l1:
cmp eax, 640-160
jbe m13l2
mov eax, 640-160
;--------------------------------------
align 4
m13l2:
sub eax, 160
shl eax, 2
add ecx, eax
mov esi, [LFBAddress]
add esi, ecx
mov edi, VGABasePtr
mov edx, 200
mov ecx, 320
cld
;--------------------------------------
align 4
m13pix:
lodsd
test eax, eax
jz .save_pixel
push eax
mov ebx, eax
and eax, (128+64+32) ; blue
shr eax, 5
and ebx, (128+64+32)*256; green
shr ebx, 8+2
add eax, ebx
pop ebx
and ebx, (128+64)*256*256; red
shr ebx, 8+8
add eax, ebx
;--------------------------------------
align 4
.save_pixel:
stosb
loop m13pix
mov ecx, 320
add esi, 4*(640-320)
dec edx
jnz m13pix
mov [EGA_counter], 0
popad
ret
;------------------------------------------------------------------------------
align 4
VGA_drawbackground:
; draw all
pushad
mov esi, [LFBAddress]
mov edi, VGABasePtr
mov ebx, 640/32; 640*480/(8*4)
mov edx, 480
;--------------------------------------
align 4
@@:
push ebx edx esi edi
shl edx, 9
lea edx, [edx+edx*4]
add esi, edx
shr edx, 5
add edi, edx
call VGA_draw_long_line
pop edi esi edx ebx
dec edx
jnz @r
call VGA_draw_long_line_1
popad
ret
;------------------------------------------------------------------------------
align 4
VGA_draw_long_line:
mov dx, 3ceh
mov ax, 0ff08h
cli
out dx, ax
mov ax, 0005h
out dx, ax
;--------------------------------------
align 4
m12pix:
call VGA_draw_32_pixels
dec ebx
jnz m12pix
mov dx, 3c4h
mov ax, 0ff02h
out dx, ax
mov dx, 3ceh
mov ax, 0205h
out dx, ax
mov dx, 3ceh
mov al, 08h
out dx, al
sti
ret
;------------------------------------------------------------------------------
align 4
VGA_draw_32_pixels:
xor eax, eax
mov ebp, VGA_8_pixels
mov [ebp], eax
mov [ebp+4], eax
mov [ebp+8], eax
mov [ebp+12], eax
mov ch, 4
;--------------------------------------
align 4
.main_loop:
mov cl, 8
;--------------------------------------
align 4
.convert_pixels_to_VGA:
lodsd ; eax = 24bit colour
test eax, eax
jz .end
rol eax, 8
mov al, ch
ror eax, 8
mov ch, 1
dec cl
shl ch, cl
cmp al, 85
jbe .p13green
or [ebp], ch
cmp al, 170
jbe .p13green
or [ebp+12], ch
;--------------------------------------
align 4
.p13green:
cmp ah, 85
jbe .p13red
or [ebp+4], ch
cmp ah, 170
jbe .p13red
or [ebp+12], ch
;--------------------------------------
align 4
.p13red:
shr eax, 8
cmp ah, 85
jbe .p13cont
or [ebp+8], ch
cmp ah, 170
jbe .p13cont
or [ebp+12], ch
;--------------------------------------
align 4
.p13cont:
ror eax, 8
mov ch, ah
inc cl
;--------------------------------------
align 4
.end:
dec cl
jnz .convert_pixels_to_VGA
inc ebp
dec ch
jnz .main_loop
push esi
sub ebp, 4
mov esi, ebp
mov dx, 3c4h
mov ah, 1h
;--------------------------------------
align 4
@@:
mov al, 02h
out dx, ax
xchg ax, bp
lodsd
mov [edi], eax
xchg ax, bp
shl ah, 1
cmp ah, 10h
jnz @r
add edi, 4
pop esi
ret
;------------------------------------------------------------------------------
align 4
VGA_putpixel:
; eax = x
; ebx = y
mov ecx, eax
mov eax, [esp+32-8+4] ; color
;--------------------------------------
; check for hardware cursor
cmp [_display.select_cursor], select_cursor
je @f
cmp [_display.select_cursor], 0
jne .no_mouseunder
;--------------------------------------
align 4
@@:
push ecx
shl ecx, 16
mov cx, bx
; check mouse area for putpixel
test eax, 0x04000000
jnz @f
call [_display.check_mouse]
;--------------------------------------
align 4
@@:
pop ecx
;--------------------------------------
align 4
.no_mouseunder:
shl ebx, 9
lea ebx, [ebx+ebx*4] ; óìíîæåíèå íà 5
lea edx, [ebx+ecx*4] ; + x*BytesPerPixel (Vesa2.0 32)
mov edi, edx
add edi, [LFBAddress] ; + LFB address
mov [edi], eax ; write to LFB for Vesa2.0
shr edx, 5 ; change BytesPerPixel to 1/8
mov edi, edx
add edi, VGABasePtr ; address of pixel in VGA area
and ecx, 0x07 ; bit no. (modulo 8)
pushfd
; edi = address, eax = 24bit colour, ecx = bit no. (modulo 8)
xor edx, edx
test eax, eax
jz .p13cont
cmp al, 85
jbe .p13green
or dl, 0x01
cmp al, 170
jbe .p13green
or dl, 0x08
;--------------------------------------
align 4
.p13green:
cmp ah, 85
jbe .p13red
or dl, 0x02
cmp ah, 170
jbe .p13red
or dl, 0x08
;--------------------------------------
align 4
.p13red:
shr eax, 8
cmp ah, 85
jbe .p13cont
or dl, 0x04
cmp ah, 170
jbe .p13cont
or dl, 0x08
;--------------------------------------
align 4
.p13cont:
ror edx, 8
inc cl
xor eax, eax
inc ah
shr ax, cl
mov dx, 3cfh
cli
out dx, al
mov al, [edi] ; dummy read
rol edx, 8
mov [edi], dl
popfd
ret
;------------------------------------------------------------------------------
align 4
VGA__putimage:
; ecx = size [x|y]
; edx = coordinates [x|y]
pushad
rol edx, 16
movzx eax, dx
rol edx, 16
movzx ebx, dx
movzx edx, cx
rol ecx, 16
movzx ecx, cx
call VGA_draw_bar_1
popad
ret
;------------------------------------------------------------------------------
align 4
VGA_draw_bar:
; eax cx
; ebx cy
; ecx xe
; edx ye
pushad
sub ecx, eax
sub edx, ebx
and eax, 0xffff
and ebx, 0xffff
and ecx, 0xffff
and edx, 0xffff
call VGA_draw_bar_1
popad
ret
;------------------------------------------------------------------------------
align 4
VGA_draw_bar_1:
mov [temp.cx], eax
mov eax, [TASK_BASE]
add ebx, [eax-twdw + 4]
mov eax, [eax-twdw + 0]
add eax, [temp.cx]
and eax, 0xfff8
shl ebx, 9
lea ebx, [ebx+ebx*4]; óìíîæåíèå íà 5
lea ebx, [ebx+eax*4] ; + x*BytesPerPixel (Vesa2.0 32)
mov esi, ebx
add esi, [LFBAddress] ; + LFB address
shr ebx, 5 ; change BytesPerPixel to 1/8
mov edi, ebx
add edi, VGABasePtr ; address of pixel in VGA area
mov ebx, ecx
shr ebx, 5
inc ebx
;--------------------------------------
align 4
.main_loop:
call VGA_draw_long_line_1
dec edx
jnz .main_loop
call VGA_draw_long_line_1
ret
;------------------------------------------------------------------------------
align 4
VGA_draw_long_line_1:
push ebx edx esi edi
shl edx, 9
lea edx, [edx+edx*4]
add esi, edx
shr edx, 5
add edi, edx
call VGA_draw_long_line
pop edi esi edx ebx
ret
;------------------------------------------------------------------------------
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/video/arrow.cur
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mergeinfo
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/kernel/branches/net/video
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/README.TXT
0,0 → 1,13
This code is experimental, none of the used programming interfaces (API, driver calls,..) are definite solutions.
Lot of work needs to be done, and descissions need to be made.
 
But, everyone is free to explore the code, make suggestions or write parts of the code.
 
I'm open for discussion on hidnplayr@gmail.com or as hidnplayr in #kolibrios on the freenode IRC network.
Some information about API and things under construction can be found on http://wiki.kolibrios.org/wiki/New_stack
Binary versions can be found at http://builds.kolibrios.org/new-stack/
 
All bug reports may be sent to me via e-mail, or through the bugtracker on http://bugs.kolibrios.org
 
 
Hidnplayr
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/sys.conf
0,0 → 1,12
[path]
/rd/1=/sys
/rd/1/dll=/sys/lib
 
[gui]
mouse_speed=1
mouse_delay=0x00A
 
[dev]
sb16=0x220
sound_dma=1
midibase=0x320
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/macros.inc
0,0 → 1,199
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
__REV = 0
 
macro $Revision a {
match =: Num =$,a \{
if __REV < Num
__REV = Num
end if
\}
}
 
$Revision $
 
 
;// mike.dld, 2006-29-01 [
 
; macros definition
macro diff16 title,l1,l2
{
local s,d
s = l2-l1
display title,': 0x'
repeat 16
d = 48 + s shr ((16-%) shl 2) and $0F
if d > 57
d = d + 65-57-1
end if
display d
end repeat
display 13,10
}
macro diff10 title,l1,l2
{
local s,d,z,m
s = l2-l1
z = 0
m = 1000000000
display title,': '
repeat 10
d = '0' + s / m
s = s - (s/m)*m
m = m / 10
if d <> '0'
z = 1
end if
if z <> 0
display d
end if
end repeat
display 13,10
}
 
include 'kglobals.inc'
 
; \begin{diamond}[29.09.2006]
; may be useful for kernel debugging
; example 1:
; dbgstr 'Hello, World!'
; example 2:
; dbgstr 'Hello, World!', save_flags
macro dbgstr string*, f
{
local a
iglobal_nested
a db 'K : ',string,13,10,0
endg_nested
if ~ f eq
pushfd
end if
push esi
mov esi, a
call sys_msg_board_str
pop esi
if ~ f eq
popfd
end if
}
; \end{diamond}[29.09.2006]
 
macro Mov op1,op2,op3 ; op1 = op2 = op3
{
mov op2, op3
mov op1, op2
}
 
macro __list_add new, prev, next
{
mov [next+LHEAD.prev], new
mov [new+LHEAD.next], next
mov [new+LHEAD.prev], prev
mov [prev+LHEAD.next], new
}
 
macro list_add new, head
{
mov eax, [head+LHEAD.next]
__list_add new, head, eax
}
 
macro list_add_tail new, head
{
mov eax, [head+LHEAD.prev]
__list_add new, eax, head
}
 
macro list_del entry
{
mov edx, [entry+list_fd]
mov ecx, [entry+list_bk]
mov [edx+list_bk], ecx
mov [ecx+list_fd], edx
}
 
 
 
if __CPU_type eq p5 ; CMOVcc isnt supported on the P5
 
cmove fix cmovz
macro cmovz reg1, reg2 {
 
local .jumpaddr
 
jnz .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
cmovne fix cmovnz
macro cmovnz reg1, reg2 {
 
local .jumpaddr
 
jz .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
macro cmovg reg1, reg2 {
 
local .jumpaddr
 
jle .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
macro cmovl reg1, reg2 {
 
local .jumpaddr
 
jge .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
macro cmova reg1, reg2 {
 
local .jumpaddr
 
jbe .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
macro cmovb reg1, reg2 {
 
local .jumpaddr
 
jae .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
macro cmovae reg1, reg2 {
 
local .jumpaddr
 
jb .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
macro cmovbe reg1, reg2 {
 
local .jumpaddr
 
ja .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
end if
 
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/data16.inc
0,0 → 1,91
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
flm db 0
preboot_lfb db 0
preboot_bootlog db 0
boot_drive db 0
bx_from_load:
dw 'r1' ; ñòðóêòóðà äëÿ õðàíåíèÿ ïàðàìåòðîâ- îòêóäà ãàøðóçèëèñü, áåðåòñÿ íèæå èç bx ; {SPraid}[13.03.2007]
; a,b,c,d - âèí÷åñòåðû, r - ðàì äèñê
; # äèñêà... ñèìâîë, à íå áàéò. '1', à íå 1
 
align 4
old_ints_h:
dw 0x400
dd 0
dw 0
 
if ~ defined extended_primary_loader ; restart from memory is not supported in extended primary loader cfg
kernel_restart_bootblock:
db 1 ; version
dw 1 ; floppy image is in memory
dd 0 ; cannot save parameters
end if
 
; table for move to extended memory (int 15h, ah=87h)
align 8
movedesc:
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
 
db 0xff,0xff,0x0,0xa0,0x00,0x93,0x0,0x0
db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0
 
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
 
fwmovedesc:
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
 
db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0
db 0xff,0xff,0x0,0xa0,0x00,0x93,0x0,0x0
 
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0
 
if defined extended_primary_loader
; look in PrimaryLoader.txt for the description
bootdevice dw 0 ; ax from primary loader
bootfs dw 0 ; bx from primary loader
bootcallback dd 0 ; ds:si from primary loader
; data for configuration file loading, look in PrimaryLoader.txt
config_file_struct:
dw 0, 4000h ; load to 4000:0000
dw 16 ; read no more than 16*4K = 64K
db 'config.ini',0
; data for configuration file parsing
macro config_variable string,parser
{
local len
len dw 0
db string
store word $ - len - 2 at len
dw parser
}
config_file_variables:
config_variable 'timeout', parse_timeout
config_variable 'resolution', parse_resolution
config_variable 'vbemode', parse_vbemode
; config_variable 'vrr', parse_vrr
config_variable 'biosdisks', parse_biosdisks
config_variable 'imgfrom', parse_imgfrom
dw 0
; data for image file loading, look in PrimaryLoader.txt
image_file_struct:
dw 0, 4000h ; load to 4000:0000
dw 16 ; read no more than 16*4K = 64K
db 'kolibri.img',0
end if
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/fdo.inc
0,0 → 1,444
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
_esp equ esp
 
;
; Formatted Debug Output (FDO)
; Copyright (c) 2005-2006, mike.dld
; Created: 2005-01-29, Changed: 2006-11-10
;
; For questions and bug reports, mail to mike.dld@gmail.com
;
; Available format specifiers are: %s, %d, %u, %x (with partial width support)
;
 
; to be defined:
; __DEBUG__ equ 1
; __DEBUG_LEVEL__ equ 5
 
macro debug_func name {
if used name
name@of@func equ name
}
 
macro debug_beginf {
align 4
name@of@func:
}
 
debug_endf fix end if
 
macro DEBUGS _sign,[_str] {
common
local tp
tp equ 0
match _arg:_num,_str \{
DEBUGS_N _sign,_num,_arg
tp equ 1
\}
match =0 _arg,tp _str \{
DEBUGS_N _sign,,_arg
\}
}
 
macro DEBUGS_N _sign,_num,[_str] {
common
pushf
pushad
local ..str,..label,is_str
is_str = 0
forward
if _str eqtype ''
is_str = 1
end if
common
if is_str = 1
jmp ..label
..str db _str,0
..label:
mov edx, ..str
else
esp equ esp+4*8+4
mov edx, _str
esp equ _esp
end if
if ~_num eq
if _num eqtype eax
if _num in <eax,ebx,ecx,edx,edi,ebp,esp>
mov esi, _num
else if ~_num eq esi
movzx esi, _num
end if
else if _num eqtype 0
mov esi, _num
else
local tp
tp equ 0
match [_arg],_num \{
mov esi, dword[_arg]
tp equ 1
\}
match =0 =dword[_arg],tp _num \{
mov esi, dword[_arg]
tp equ 1
\}
match =0 =word[_arg],tp _num \{
movzx esi, word[_arg]
tp equ 1
\}
match =0 =byte[_arg],tp _num \{
movzx esi, byte[_arg]
tp equ 1
\}
match =0,tp \{
'Error: specified string width is incorrect'
\}
end if
else
mov esi, 0x7FFFFFFF
end if
call fdo_debug_outstr
popad
popf
}
 
macro DEBUGD _sign,_dec {
local tp
tp equ 0
match _arg:_num,_dec \{
DEBUGD_N _sign,_num,_arg
tp equ 1
\}
match =0 _arg,tp _dec \{
DEBUGD_N _sign,,_arg
\}
}
 
macro DEBUGD_N _sign,_num,_dec {
pushf
pushad
if (~_num eq)
if (_dec eqtype eax | _dec eqtype 0)
'Error: precision allowed only for in-memory variables'
end if
if (~_num in <1,2,4>)
if _sign
'Error: 1, 2 and 4 are only allowed for precision in %d'
else
'Error: 1, 2 and 4 are only allowed for precision in %u'
end if
end if
end if
if _dec eqtype eax
if _dec in <ebx,ecx,edx,esi,edi,ebp,esp>
mov eax, _dec
else if ~_dec eq eax
if _sign = 1
movsx eax, _dec
else
movzx eax, _dec
end if
end if
else if _dec eqtype 0
mov eax, _dec
else
; add esp,4*8+4
esp equ esp+4*8+4
if _num eq
mov eax, dword _dec
else if _num = 1
if _sign = 1
movsx eax, byte _dec
else
movzx eax, byte _dec
end if
else if _num = 2
if _sign = 1
movsx eax, word _dec
else
movzx eax, word _dec
end if
else
mov eax, dword _dec
end if
esp equ _esp
; sub esp,4*8+4
end if
mov cl, _sign
call fdo_debug_outdec
popad
popf
}
 
macro DEBUGH _sign,_hex {
local tp
tp equ 0
match _arg:_num,_hex \{
DEBUGH_N _sign,_num,_arg
tp equ 1
\}
match =0 _arg,tp _hex \{
DEBUGH_N _sign,,_arg
\}
}
 
macro DEBUGH_N _sign,_num,_hex {
pushf
pushad
if (~_num eq) & (~_num in <1,2,3,4,5,6,7,8>)
'Error: 1..8 are only allowed for precision in %x'
end if
if _hex eqtype eax
if _hex in <eax,ebx,ecx,edx,esi,edi,ebp,esp>
if ~_hex eq eax
mov eax, _hex
end if
mov edx, 8
else if _hex in <ax,bx,cx,dx,si,di,bp,sp>
if ~_hex eq ax
movzx eax, _hex
end if
if (_num eq)
mov edx, 4
end if
else if _hex in <al,ah,bl,bh,cl,ch,dl,dh>
if ~_hex eq al
movzx eax, _hex
end if
if (_num eq)
mov edx, 2
end if
end if
else if _hex eqtype 0
mov eax, _hex
else
; add esp,4*8+4
esp equ esp+4*8+4
mov eax, dword _hex
esp equ _esp
; sub esp,4*8+4
end if
if ~_num eq
mov edx, _num
else
if ~_hex eqtype eax
mov edx, 8
end if
end if
call fdo_debug_outhex
popad
popf
}
 
;-----------------------------------------------------------------------------
 
debug_func fdo_debug_outchar
debug_beginf
pushad
movzx ebx, al
mov eax, 1
mov ecx, sys_msg_board
call ecx ; sys_msg_board
popad
ret
debug_endf
 
debug_func fdo_debug_outstr
debug_beginf
mov eax, 1
.l1:
dec esi
js .l2
movzx ebx, byte[edx]
or bl, bl
jz .l2
mov ecx, sys_msg_board
call ecx ; sys_msg_board
inc edx
jmp .l1
.l2:
ret
debug_endf
 
debug_func fdo_debug_outdec
debug_beginf
or cl, cl
jz @f
or eax, eax
jns @f
neg eax
push eax
mov al, '-'
call fdo_debug_outchar
pop eax
@@:
push 10
pop ecx
push -'0'
.l1:
xor edx, edx
div ecx
push edx
test eax, eax
jnz .l1
.l2:
pop eax
add al, '0'
jz .l3
call fdo_debug_outchar
jmp .l2
.l3:
ret
debug_endf
 
debug_func fdo_debug_outhex
__fdo_hexdigits db '0123456789ABCDEF'
debug_beginf
mov cl, dl
neg cl
add cl, 8
shl cl, 2
rol eax, cl
.l1:
rol eax, 4
push eax
and eax, 0x0000000F
mov al, [__fdo_hexdigits+eax]
call fdo_debug_outchar
pop eax
dec edx
jnz .l1
ret
debug_endf
 
;-----------------------------------------------------------------------------
 
macro DEBUGF _level,_format,[_arg] {
common
if __DEBUG__ = 1 & _level >= __DEBUG_LEVEL__
local ..f1,f2,a1,a2,c1,c2,c3,..lbl
_debug_str_ equ __debug_str_ # a1
a1 = 0
c2 = 0
c3 = 0
f2 = 0
repeat ..lbl-..f1
virtual at 0
db _format,0,0
load c1 word from %-1
end virtual
if c1 = '%s'
virtual at 0
db _format,0,0
store word 0 at %-1
load c1 from f2-c2
end virtual
if c1 <> 0
DEBUGS 0,_debug_str_+f2-c2
end if
c2 = c2 + 1
f2 = %+1
DEBUGF_HELPER S,a1,0,_arg
else if c1 = '%x'
virtual at 0
db _format,0,0
store word 0 at %-1
load c1 from f2-c2
end virtual
if c1 <> 0
DEBUGS 0,_debug_str_+f2-c2
end if
c2 = c2 + 1
f2 = %+1
DEBUGF_HELPER H,a1,0,_arg
else if c1 = '%d' | c1 = '%u'
local c4
if c1 = '%d'
c4 = 1
else
c4 = 0
end if
virtual at 0
db _format,0,0
store word 0 at %-1
load c1 from f2-c2
end virtual
if c1 <> 0
DEBUGS 0,_debug_str_+f2-c2
end if
c2 = c2 + 1
f2 = %+1
DEBUGF_HELPER D,a1,c4,_arg
else if c1 = '\n'
c3 = c3 + 1
end if
end repeat
virtual at 0
db _format,0,0
load c1 from f2-c2
end virtual
if (c1<>0)&(f2<>..lbl-..f1-1)
DEBUGS 0,_debug_str_+f2-c2
end if
virtual at 0
..f1 db _format,0
..lbl:
__debug_strings equ __debug_strings,_debug_str_,<_format>,..lbl-..f1-1-c2-c3
end virtual
end if
}
 
macro __include_debug_strings dummy,[_id,_fmt,_len] {
common
local c1,a1,a2
forward
if defined _len & ~_len eq
_id:
a1 = 0
a2 = 0
repeat _len
virtual at 0
db _fmt,0,0
load c1 word from %+a2-1
end virtual
if (c1='%s')|(c1='%x')|(c1='%d')|(c1='%u')
db 0
a2 = a2 + 1
else if (c1='\n')
dw $0A0D
a1 = a1 + 1
a2 = a2 + 1
else
db c1 and 0x0FF
end if
end repeat
db 0
end if
}
 
macro DEBUGF_HELPER _letter,_num,_sign,[_arg] {
common
local num
num = 0
forward
if num = _num
DEBUG#_letter _sign,_arg
end if
num = num+1
common
_num = _num+1
}
 
macro include_debug_strings {
if __DEBUG__ = 1
match dbg_str,__debug_strings \{
__include_debug_strings dbg_str
\}
end if
}
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/imports.inc
0,0 → 1,27
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;============================================================================
;
; External kernel dependencies
;
;============================================================================
 
$Revision $
 
 
align 4
@IMPORT:
 
library \
libini,'libini.obj'
 
import libini, \
ini.lib_init,'lib_init',\
ini.get_str,'ini.get_str',\
ini.enum_keys,'ini.enum_keys',\
ini.get_int,'ini.get_int'
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/init.inc
0,0 → 1,591
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
MEM_WB equ 6 ;write-back memory
MEM_WC equ 1 ;write combined memory
MEM_UC equ 0 ;uncached memory
 
align 4
proc mem_test
; if we have BIOS with fn E820, skip the test
cmp dword [BOOT_VAR-OS_BASE + 0x9100], 0
jnz .ret
 
mov eax, cr0
and eax, not (CR0_CD+CR0_NW)
or eax, CR0_CD ;disable caching
mov cr0, eax
wbinvd ;invalidate cache
 
xor edi, edi
mov ebx, 'TEST'
@@:
add edi, 0x100000
xchg ebx, dword [edi]
cmp dword [edi], 'TEST'
xchg ebx, dword [edi]
je @b
 
and eax, not (CR0_CD+CR0_NW) ;enable caching
mov cr0, eax
inc dword [BOOT_VAR-OS_BASE + 0x9100]
xor eax, eax
mov [BOOT_VAR-OS_BASE + 0x9104], eax
mov [BOOT_VAR-OS_BASE + 0x9108], eax
mov [BOOT_VAR-OS_BASE + 0x910C], edi
mov [BOOT_VAR-OS_BASE + 0x9110], eax
.ret:
ret
endp
 
align 4
proc init_mem
; calculate maximum allocatable address and number of allocatable pages
mov edi, BOOT_VAR-OS_BASE + 0x9104
mov ecx, [edi-4]
xor esi, esi; esi will hold total amount of memory
xor edx, edx; edx will hold maximum allocatable address
.calcmax:
; round all to pages
mov eax, [edi]
cmp [edi+16], byte 1
jne .unusable
 
test eax, 0xFFF
jz @f
neg eax
and eax, 0xFFF
add [edi], eax
adc dword [edi+4], 0
sub [edi+8], eax
sbb dword [edi+12], 0
jc .unusable
@@:
and dword [edi+8], not 0xFFF
jz .unusable
; ignore memory after 4 Gb
cmp dword [edi+4], 0
jnz .unusable
mov eax, [edi]
cmp dword [edi+12], 0
jnz .overflow
add eax, [edi+8]
jnc @f
.overflow:
mov eax, 0xFFFFF000
@@:
cmp edx, eax
jae @f
mov edx, eax
@@:
sub eax, [edi]
mov [edi+8], eax
add esi, eax
jmp .usable
.unusable:
; and dword [edi+8], 0
.usable:
add edi, 20
loop .calcmax
.calculated:
mov [MEM_AMOUNT-OS_BASE], esi
mov [pg_data.mem_amount-OS_BASE], esi
shr esi, 12
mov [pg_data.pages_count-OS_BASE], esi
 
shr edx, 12
add edx, 31
and edx, not 31
shr edx, 3
mov [pg_data.pagemap_size-OS_BASE], edx
 
add edx, (sys_pgmap-OS_BASE)+4095
and edx, not 4095
mov [tmp_page_tabs], edx
 
mov edx, esi
and edx, -1024
cmp edx, (OS_BASE/4096)
jbe @F
mov edx, (OS_BASE/4096)
jmp .set
@@:
cmp edx, (HEAP_BASE-OS_BASE+HEAP_MIN_SIZE)/4096
jae .set
mov edx, (HEAP_BASE-OS_BASE+HEAP_MIN_SIZE)/4096
.set:
mov [pg_data.kernel_pages-OS_BASE], edx
shr edx, 10
mov [pg_data.kernel_tables-OS_BASE], edx
 
xor eax, eax
mov edi, sys_pgdir-OS_BASE
mov ecx, 4096/4
cld
rep stosd
 
mov edx, (sys_pgdir-OS_BASE)+ 0x800; (OS_BASE shr 20)
bt [cpu_caps-OS_BASE], CAPS_PSE
jnc .no_PSE
 
mov ebx, cr4
or ebx, CR4_PSE
mov eax, PG_LARGE+PG_SW
mov cr4, ebx
dec [pg_data.kernel_tables-OS_BASE]
 
mov [edx], eax
add edx, 4
 
mov edi, [tmp_page_tabs]
jmp .map_kernel_heap ; new kernel fits to the first 4Mb - nothing to do with ".map_low"
.no_PSE:
mov eax, PG_SW
mov ecx, [tmp_page_tabs]
shr ecx, 12
.map_low:
mov edi, [tmp_page_tabs]
@@: ;
stosd
add eax, 0x1000
dec ecx
jnz @B
 
.map_kernel_heap:
mov ecx, [pg_data.kernel_tables-OS_BASE]
shl ecx, 10
xor eax, eax
rep stosd
 
mov ecx, [pg_data.kernel_tables-OS_BASE]
mov eax, [tmp_page_tabs]
or eax, PG_SW
mov edi, edx
 
.map_kernel_tabs:
stosd
add eax, 0x1000
dec ecx
jnz .map_kernel_tabs
 
mov dword [sys_pgdir-OS_BASE+(page_tabs shr 20)], sys_pgdir+PG_SW-OS_BASE
 
mov edi, (sys_pgdir-OS_BASE)
lea esi, [edi+(OS_BASE shr 20)]
movsd
movsd
ret
endp
 
align 4
proc init_page_map
; mark all memory as unavailable
mov edi, sys_pgmap-OS_BASE
mov ecx, [pg_data.pagemap_size-OS_BASE]
shr ecx, 2
xor eax, eax
cld
rep stosd
 
; scan through memory map and mark free areas as available
mov ebx, BOOT_VAR-OS_BASE + 0x9104
mov edx, [ebx-4]
.scanmap:
cmp [ebx+16], byte 1
jne .next
 
mov ecx, [ebx+8]
shr ecx, 12; ecx = number of pages
jz .next
mov edi, [ebx]
shr edi, 12; edi = first page
mov eax, edi
shr edi, 5
shl edi, 2
add edi, sys_pgmap-OS_BASE
and eax, 31
jz .startok
add ecx, eax
sub ecx, 32
jbe .onedword
push ecx
mov ecx, eax
or eax, -1
shl eax, cl
or [edi], eax
add edi, 4
pop ecx
.startok:
push ecx
shr ecx, 5
or eax, -1
rep stosd
pop ecx
and ecx, 31
neg eax
shl eax, cl
dec eax
or [edi], eax
jmp .next
.onedword:
add ecx, 32
sub ecx, eax
@@:
bts [edi], eax
inc eax
loop @b
.next:
add ebx, 20
dec edx
jnz .scanmap
 
; mark kernel memory as allocated (unavailable)
mov ecx, [tmp_page_tabs]
mov edx, [pg_data.pages_count-OS_BASE]
shr ecx, 12
add ecx, [pg_data.kernel_tables-OS_BASE]
sub edx, ecx
mov [pg_data.pages_free-OS_BASE], edx
 
mov edi, sys_pgmap-OS_BASE
mov ebx, ecx
shr ecx, 5
xor eax, eax
rep stosd
 
not eax
mov ecx, ebx
and ecx, 31
shl eax, cl
and [edi], eax
add edi, OS_BASE
mov [page_start-OS_BASE], edi;
 
mov ebx, sys_pgmap
add ebx, [pg_data.pagemap_size-OS_BASE]
mov [page_end-OS_BASE], ebx
 
ret
endp
 
align 4
 
init_BIOS32:
mov edi, 0xE0000
.pcibios_nxt:
cmp dword[edi], '_32_'; "magic" word
je .BIOS32_found
.pcibios_nxt2:
add edi, 0x10
cmp edi, 0xFFFF0
je .BIOS32_not_found
jmp .pcibios_nxt
.BIOS32_found: ; magic word found, check control summ
 
movzx ecx, byte[edi + 9]
shl ecx, 4
mov esi, edi
xor eax, eax
cld ; paranoia
@@:
lodsb
add ah, al
loop @b
jnz .pcibios_nxt2; control summ must be zero
; BIOS32 service found !
mov ebp, [edi + 4]
mov [bios32_entry], ebp
; check PCI BIOS present
mov eax, '$PCI'
xor ebx, ebx
push cs ; special for 'ret far' from BIOS
call ebp
test al, al
jnz .PCI_BIOS32_not_found
 
; çäåñü ñîçäàþòñÿ äèñêðèïòîðû äëÿ PCI BIOS
 
add ebx, OS_BASE
dec ecx
mov [(pci_code_32-OS_BASE)], cx ;limit 0-15
mov [(pci_data_32-OS_BASE)], cx ;limit 0-15
 
mov [(pci_code_32-OS_BASE)+2], bx ;base 0-15
mov [(pci_data_32-OS_BASE)+2], bx ;base 0-15
 
shr ebx, 16
mov [(pci_code_32-OS_BASE)+4], bl ;base 16-23
mov [(pci_data_32-OS_BASE)+4], bl ;base 16-23
 
shr ecx, 16
and cl, 0x0F
mov ch, bh
add cx, D32
mov [(pci_code_32-OS_BASE)+6], cx ;lim 16-19 &
mov [(pci_data_32-OS_BASE)+6], cx ;base 24-31
 
mov [(pci_bios_entry-OS_BASE)], edx
; jmp .end
.PCI_BIOS32_not_found:
; çäåñü äîëæíà çàïîëíÿòñÿ pci_emu_dat
.BIOS32_not_found:
.end:
ret
 
align 4
proc test_cpu
locals
cpu_type dd ?
cpu_id dd ?
cpu_Intel dd ?
cpu_AMD dd ?
endl
 
xor eax, eax
mov [cpu_type], eax
mov [cpu_caps-OS_BASE], eax
mov [cpu_caps+4-OS_BASE], eax
 
pushfd
pop eax
mov ecx, eax
xor eax, 0x40000
push eax
popfd
pushfd
pop eax
xor eax, ecx
mov [cpu_type], CPU_386
jz .end_cpuid
push ecx
popfd
 
mov [cpu_type], CPU_486
mov eax, ecx
xor eax, 0x200000
push eax
popfd
pushfd
pop eax
xor eax, ecx
je .end_cpuid
mov [cpu_id], 1
 
xor eax, eax
cpuid
 
mov [cpu_vendor-OS_BASE], ebx
mov [cpu_vendor+4-OS_BASE], edx
mov [cpu_vendor+8-OS_BASE], ecx
cmp ebx, dword [intel_str-OS_BASE]
jne .check_AMD
cmp edx, dword [intel_str+4-OS_BASE]
jne .check_AMD
cmp ecx, dword [intel_str+8-OS_BASE]
jne .check_AMD
mov [cpu_Intel], 1
cmp eax, 1
jl .end_cpuid
mov eax, 1
cpuid
mov [cpu_sign-OS_BASE], eax
mov [cpu_info-OS_BASE], ebx
mov [cpu_caps-OS_BASE], edx
mov [cpu_caps+4-OS_BASE], ecx
 
shr eax, 8
and eax, 0x0f
ret
.end_cpuid:
mov eax, [cpu_type]
ret
 
.check_AMD:
cmp ebx, dword [AMD_str-OS_BASE]
jne .unknown
cmp edx, dword [AMD_str+4-OS_BASE]
jne .unknown
cmp ecx, dword [AMD_str+8-OS_BASE]
jne .unknown
mov [cpu_AMD], 1
cmp eax, 1
jl .unknown
mov eax, 1
cpuid
mov [cpu_sign-OS_BASE], eax
mov [cpu_info-OS_BASE], ebx
mov [cpu_caps-OS_BASE], edx
mov [cpu_caps+4-OS_BASE], ecx
shr eax, 8
and eax, 0x0f
ret
.unknown:
mov eax, 1
cpuid
mov [cpu_sign-OS_BASE], eax
mov [cpu_info-OS_BASE], ebx
mov [cpu_caps-OS_BASE], edx
mov [cpu_caps+4-OS_BASE], ecx
shr eax, 8
and eax, 0x0f
ret
endp
 
iglobal
align 4
acpi_lapic_base dd 0xfee00000 ; default local apic base
endg
 
uglobal
align 4
acpi_rsdp rd 1
acpi_rsdt rd 1
acpi_madt rd 1
 
acpi_dev_data rd 1
acpi_dev_size rd 1
 
acpi_rsdt_base rd 1
acpi_madt_base rd 1
acpi_ioapic_base rd 1
 
cpu_count rd 1
smpt rd 16
endg
 
ACPI_HI_RSDP_WINDOW_START equ 0x000E0000
ACPI_HI_RSDP_WINDOW_END equ 0x00100000
ACPI_RSDP_CHECKSUM_LENGTH equ 20
ACPI_MADT_SIGN equ 0x43495041
 
 
acpi_locate:
push ebx
mov ebx, ACPI_HI_RSDP_WINDOW_START
.check:
cmp [ebx], dword 0x20445352
jne .next
cmp [ebx+4], dword 0x20525450
jne .next
 
mov edx, ebx
mov ecx, ACPI_RSDP_CHECKSUM_LENGTH
xor eax, eax
.sum:
add al, [edx]
inc edx
loop .sum
 
test al, al
jnz .next
 
mov eax, ebx
pop ebx
ret
.next:
add ebx, 16
cmp ebx, ACPI_HI_RSDP_WINDOW_END
jb .check
 
pop ebx
xor eax, eax
ret
 
align 4
rsdt_find: ;ecx= rsdt edx= SIG
push ebx
push esi
 
lea ebx, [ecx+36]
mov esi, [ecx+4]
add esi, ecx
align 4
.next:
mov eax, [ebx]
cmp [eax], edx
je .done
 
add ebx, 4
cmp ebx, esi
jb .next
 
xor eax, eax
pop esi
pop ebx
ret
 
.done:
mov eax, [ebx]
pop esi
pop ebx
ret
 
align 4
check_acpi:
 
call acpi_locate
test eax, eax
jz .done
 
mov ecx, [eax+16]
mov edx, ACPI_MADT_SIGN
mov [acpi_rsdt_base-OS_BASE], ecx
call rsdt_find
test eax, eax
jz .done
 
mov [acpi_madt_base-OS_BASE], eax
mov ecx, [eax+36]
mov [acpi_lapic_base-OS_BASE], ecx
 
mov edi, smpt-OS_BASE
mov ebx, [ecx+0x20]
shr ebx, 24 ; read APIC ID
 
mov [edi], ebx ; bootstrap always first
inc [cpu_count-OS_BASE]
add edi, 4
 
lea edx, [eax+44]
mov ecx, [eax+4]
add ecx, eax
.check:
mov eax, [edx]
cmp al, 0
jne .io_apic
 
shr eax, 24 ; get APIC ID
cmp eax, ebx ; skip self
je .next
 
test [edx+4], byte 1 ; is enabled ?
jz .next
 
cmp [cpu_count-OS_BASE], 16
jae .next
 
stosd ; store APIC ID
inc [cpu_count-OS_BASE]
.next:
mov eax, [edx]
movzx eax, ah
add edx, eax
cmp edx, ecx
jb .check
.done:
ret
 
.io_apic:
cmp al, 1
jne .next
 
mov eax, [edx+4]
mov [acpi_ioapic_base-OS_BASE], eax
jmp .next
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/kglobals.inc
0,0 → 1,69
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
;------------------------------------------------------------------
; use "iglobal" for inserting initialized global data definitions.
;------------------------------------------------------------------
macro iglobal {
IGlobals equ IGlobals,
macro __IGlobalBlock { }
 
macro iglobal_nested {
IGlobals equ IGlobals,
macro __IGlobalBlock \{ }
 
;-------------------------------------------------------------
; use 'uglobal' for inserting uninitialized global definitions.
; even when you define some data values, these variables
; will be stored as uninitialized data.
;-------------------------------------------------------------
macro uglobal {
UGlobals equ UGlobals,
macro __UGlobalBlock { }
 
macro uglobal_nested {
UGlobals equ UGlobals,
macro __UGlobalBlock \{ }
 
endg fix } ; Use endg for ending iglobal and uglobal blocks.
endg_nested fix \}
 
macro IncludeIGlobals{
macro IGlobals dummy,[n] \{ __IGlobalBlock
purge __IGlobalBlock \}
match I, IGlobals \{ I \} }
 
 
macro IncludeUGlobals{
macro UGlobals dummy,[n] \{
\common
\local begin, size
begin = $
virtual at $
\forward
__UGlobalBlock
purge __UGlobalBlock
\common
size = $ - begin
end virtual
rb size
\}
match U, UGlobals \{ U \} }
 
macro IncludeAllGlobals {
IncludeIGlobals
IncludeUGlobals
}
iglobal
endg
 
uglobal
endg
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/proc32.inc
0,0 → 1,277
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
 
; Macroinstructions for defining and calling procedures
 
macro stdcall proc,[arg] ; directly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call proc }
 
macro invoke proc,[arg] ; indirectly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call [proc] }
 
macro ccall proc,[arg] ; directly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call proc
if size@ccall
add esp, size@ccall
end if }
 
macro cinvoke proc,[arg] ; indirectly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call [proc]
if size@ccall
add esp, size@ccall
end if }
 
macro proc [args] ; define procedure
{ common
match name params, args>
\{ define@proc name,<params \} }
 
prologue@proc equ prologuedef
 
macro prologuedef procname,flag,parmbytes,localbytes,reglist
{ if parmbytes | localbytes
push ebp
mov ebp, esp
if localbytes
sub esp, localbytes
end if
end if
irps reg, reglist \{ push reg \} }
 
epilogue@proc equ epiloguedef
 
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
{ irps reg, reglist \{ reverse pop reg \}
if parmbytes | localbytes
leave
end if
if (flag and 10000b) | (parmbytes=0)
retn
else
retn parmbytes
end if }
 
macro define@proc name,statement
{ local params,flag,regs,parmbytes,localbytes,current
if used name
name:
match =stdcall args, statement \{ params equ args
flag = 11b \}
match =stdcall, statement \{ params equ
flag = 11b \}
match =c args, statement \{ params equ args
flag = 10001b \}
match =c, statement \{ params equ
flag = 10001b \}
match =params, params \{ params equ statement
flag = 0 \}
virtual at ebp+8
match =uses reglist=,args, params \{ regs equ reglist
params equ args \}
match =regs =uses reglist, regs params \{ regs equ reglist
params equ \}
match =regs, regs \{ regs equ \}
match =,args, params \{ defargs@proc args \}
match =args@proc args, args@proc params \{ defargs@proc args \}
parmbytes = $ - (ebp+8)
end virtual
name # % = parmbytes/4
all@vars equ
current = 0
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
macro locals
\{ virtual at ebp-localbytes+current
macro label . \\{ deflocal@proc .,:, \\}
struc db [val] \\{ \common deflocal@proc .,db,val \\}
struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
macro endl
\{ purge label
restruc db,dw,dp,dd,dt,dq
restruc rb,rw,rp,rd,rt,rq
restruc byte,word,dword,pword,tword,qword
current = $-(ebp-localbytes)
end virtual \}
macro ret operand
\{ match any, operand \\{ retn operand \\}
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs>
\\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2
end if \} }
 
macro defargs@proc [arg]
{ common
if ~ arg eq
forward
local ..arg,current@arg
match argname:type, arg
\{ current@arg equ argname
label ..arg type
argname equ ..arg
if dqword eq type
dd ?,?,?,?
else if tbyte eq type
dd ?,?,?
else if qword eq type | pword eq type
dd ?,?
else
dd ?
end if \}
match =current@arg,current@arg
\{ current@arg equ arg
arg equ ..arg
..arg dd ? \}
common
args@proc equ current@arg
forward
restore current@arg
common
end if }
 
macro deflocal@proc name,def,[val]
{ common
match vars, all@vars \{ all@vars equ all@vars, \}
all@vars equ all@vars name
forward
local ..var,..tmp
..var def val
match =?, val \{ ..tmp equ \}
match any =dup (=?), val \{ ..tmp equ \}
match tmp : value, ..tmp : val
\{ tmp: end virtual
initlocal@proc ..var,def value
virtual at tmp\}
common
match first rest, ..var, \{ name equ first \} }
 
macro initlocal@proc name,def
{ virtual at name
def
size@initlocal = $ - name
end virtual
position@initlocal = 0
while size@initlocal > position@initlocal
virtual at name
def
if size@initlocal - position@initlocal < 2
current@initlocal = 1
load byte@initlocal byte from name+position@initlocal
else if size@initlocal - position@initlocal < 4
current@initlocal = 2
load word@initlocal word from name+position@initlocal
else
current@initlocal = 4
load dword@initlocal dword from name+position@initlocal
end if
end virtual
if current@initlocal = 1
mov byte [name+position@initlocal], byte@initlocal
else if current@initlocal = 2
mov word [name+position@initlocal], word@initlocal
else
mov dword [name+position@initlocal], dword@initlocal
end if
position@initlocal = position@initlocal + current@initlocal
end while }
 
macro endp
{ purge ret,locals,endl
finish@proc
purge finish@proc
restore regs@proc
match all,args@proc \{ restore all \}
restore args@proc
match all,all@vars \{ restore all \} }
 
macro local [var]
{ common
locals
forward done@local equ
match varname[count]:vartype, var
\{ match =BYTE, vartype \\{ varname rb count
restore done@local \\}
match =WORD, vartype \\{ varname rw count
restore done@local \\}
match =DWORD, vartype \\{ varname rd count
restore done@local \\}
match =PWORD, vartype \\{ varname rp count
restore done@local \\}
match =QWORD, vartype \\{ varname rq count
restore done@local \\}
match =TBYTE, vartype \\{ varname rt count
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
rq count+count
restore done@local \\}
match , done@local \\{ virtual
varname vartype
end virtual
rb count*sizeof.\#vartype
restore done@local \\} \}
match :varname:vartype, done@local:var
\{ match =BYTE, vartype \\{ varname db ?
restore done@local \\}
match =WORD, vartype \\{ varname dw ?
restore done@local \\}
match =DWORD, vartype \\{ varname dd ?
restore done@local \\}
match =PWORD, vartype \\{ varname dp ?
restore done@local \\}
match =QWORD, vartype \\{ varname dq ?
restore done@local \\}
match =TBYTE, vartype \\{ varname dt ?
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
dq ?,?
restore done@local \\}
match , done@local \\{ varname vartype
restore done@local \\} \}
match ,done@local
\{ var
restore done@local \}
common
endl }
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/sound/playnote.inc
0,0 → 1,166
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; PLAYNOTE.INC version 1.1 22 November 2003 ;;
;; ;;
;; Player Notes for Speaker PC ;;
;; subfunction #55 from function #55 Menuet OS ;;
;; ;;
;; Copyright 2003 VaStaNi ;;
;; vastani@ukr.net ;;
;; >>>- SIMPLY - QUICKLY - SHORTLY -<<< ;;
;; ;;
;; Note: playnote.txt ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision $
 
align 4
sound_interface:
 
cmp eax, ebx ; this is subfunction #55 ?
jne retFunc55 ; if no then return.
 
cmp byte [sound_flag], 0
jne retFunc55
 
movzx eax, byte [countDelayNote]
or al, al ; player is busy ?
jnz retFunc55 ; return counter delay Note
 
mov [memAdrNote], esi;edx
call get_pid
mov [pidProcessNote], eax
xor eax, eax ; Ok! EAX = 0
retFunc55:
mov [esp+32], eax ; return value EAX for application
ret
 
iglobal
align 4
kontrOctave dw 0x4742, 0x4342, 0x3F7C, 0x3BEC, 0x388F, 0x3562
dw 0x3264, 0x2F8F, 0x2CE4, 0x2A5F, 0x2802, 0x25BF
memAdrNote dd 0
pidProcessNote dd 0
slotProcessNote dd 0
count_timer_Note dd 1
mem8253r42 dw 0
countDelayNote db 0
endg
 
playNote:
; jmp NotPlayNotes
mov esi, [memAdrNote]
or esi, esi ; ESI = 0 ? - OFF Notes Play ?
jz NotPlayNotes ; if ESI = 0 -> ignore play pocedure
cmp eax, [count_timer_Note]
jb NotPlayNotes
push eax
inc eax
mov [count_timer_Note], eax
mov al, [countDelayNote]
dec al ; decrement counter Delay for Playing Note
jz NewLoadNote@Delay
cmp al, 0xFF ; this is first Note Play ?
jne NextDelayNote
;This is FIRST Note, save counter channel 2 chip 8253
mov al, 0xB6 ; control byte to timer chip 8253
out 0x43, al ; Send it to the control port chip 8253
in al, 0x42 ; Read Lower byte counter channel 2 chip 8253
mov ah, al ; AH = Lower byte counter channel 2
in al, 0x42 ; Read Upper byte counter channel 2 chip 8253
mov [mem8253r42], ax ; Save counter channel 2 timer chip 8253
NewLoadNote@Delay:
cld
; lodsb ; load AL - counter Delay
call ReadNoteByte
or al, al ; THE END ?
jz EndPlayNote
cmp al, 0x81
jnc NoteforOctave
mov [countDelayNote], al
; lodsw ; load AX - counter for Note!
call ReadNoteByte
mov ah, al
call ReadNoteByte
xchg al, ah
jmp pokeNote
 
EndPlayNote: ; THE END Play Notes!
in al, 0x61 ; Get contents of system port B chip 8255
and al, 0xFC ; Turn OFF timer and speaker
out 0x61, al ; Send out new values to port B chip 8255
mov ax, [mem8253r42] ; memorize counter channel 2 timer chip 8253
xchg al, ah ; reverse byte in word
out 0x42, al ; restore Lower byte counter channel 2
mov al, ah ; AL = Upper byte counter channel 2
out 0x42, al ; restore Upper byte channel 2
xor eax, eax ; EAX = 0
mov [memAdrNote], eax; clear header control Delay-Note string
NextDelayNote:
mov [countDelayNote], al; save new counter delay Note
pop eax
NotPlayNotes:
RET
 
NoteforOctave:
sub al, 0x81 ; correction value for delay Note
mov [countDelayNote], al; save counter delay this new Note
; lodsb ; load pack control code
call ReadNoteByte
cmp al, 0xFF ; this is PAUSE ?
jne packCode ; no, this is PACK CODE
in al, 0x61 ; Get contents of system port B chip 8255
and al, 0xFC ; Turn OFF timer and speaker
out 0x61, al ; Send out new values to port B chip 8255
jmp saveESI
 
packCode:
mov cl, al ; save code
and al, 0xF ; clear upper bits
dec al ; correction
add al, al ; transform number to offset constant
movsx eax, al ; EAX - offset
add eax, dword kontrOctave; EAX - address from constant
mov ax, [eax] ; read constant
shr cl, 4 ; transform for number Octave
shr ax, cl ; calculate from Note this Octave!
pokeNote:
out 0x42, al ; Lower byte Out to channel 2 timer chip 8253
mov al, ah
out 0x42, al ; Upper byte Out to channel 2 timer chip 8253
in al, 0x61 ; Get contents of system port B chip 8255
or al, 3 ; Turn ON timer and speaker
out 0x61, al ; Send out new values to port B chip 8255
saveESI:
; mov [memAdrNote], esi ; save new header control Delay-Note string
pop eax
RET
ReadNoteByte:
;result:
; al - note
push eax
push ecx
push edx
push esi
 
mov eax, [pidProcessNote]
call pid_to_slot
test eax, eax
jz .failed
lea ecx, [esp+12]
mov edx, 1
mov esi, [memAdrNote]
inc [memAdrNote]
 
call read_process_memory
.failed:
pop esi
pop edx
pop ecx
pop eax
ret
;------------------- END CODE -------------------
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/sound
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/struct.inc
0,0 → 1,240
 
; Macroinstructions for defining data structures
 
macro struct name
{ virtual at 0
fields@struct equ name
match child parent, name \{ fields@struct equ child,fields@\#parent \}
sub@struct equ
struc db [val] \{ \common define field@struct .,db,<val>
fields@struct equ fields@struct,field@struct \}
struc dw [val] \{ \common define field@struct .,dw,<val>
fields@struct equ fields@struct,field@struct \}
struc du [val] \{ \common define field@struct .,du,<val>
fields@struct equ fields@struct,field@struct \}
struc dd [val] \{ \common define field@struct .,dd,<val>
fields@struct equ fields@struct,field@struct \}
struc dp [val] \{ \common define field@struct .,dp,<val>
fields@struct equ fields@struct,field@struct \}
struc dq [val] \{ \common define field@struct .,dq,<val>
fields@struct equ fields@struct,field@struct \}
struc dt [val] \{ \common define field@struct .,dt,<val>
fields@struct equ fields@struct,field@struct \}
struc rb count \{ define field@struct .,db,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rw count \{ define field@struct .,dw,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rd count \{ define field@struct .,dd,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rp count \{ define field@struct .,dp,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rq count \{ define field@struct .,dq,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rt count \{ define field@struct .,dt,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro db [val] \{ \common \local anonymous
define field@struct anonymous,db,<val>
fields@struct equ fields@struct,field@struct \}
macro dw [val] \{ \common \local anonymous
define field@struct anonymous,dw,<val>
fields@struct equ fields@struct,field@struct \}
macro du [val] \{ \common \local anonymous
define field@struct anonymous,du,<val>
fields@struct equ fields@struct,field@struct \}
macro dd [val] \{ \common \local anonymous
define field@struct anonymous,dd,<val>
fields@struct equ fields@struct,field@struct \}
macro dp [val] \{ \common \local anonymous
define field@struct anonymous,dp,<val>
fields@struct equ fields@struct,field@struct \}
macro dq [val] \{ \common \local anonymous
define field@struct anonymous,dq,<val>
fields@struct equ fields@struct,field@struct \}
macro dt [val] \{ \common \local anonymous
define field@struct anonymous,dt,<val>
fields@struct equ fields@struct,field@struct \}
macro rb count \{ \local anonymous
define field@struct anonymous,db,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rw count \{ \local anonymous
define field@struct anonymous,dw,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rd count \{ \local anonymous
define field@struct anonymous,dd,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rp count \{ \local anonymous
define field@struct anonymous,dp,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rq count \{ \local anonymous
define field@struct anonymous,dq,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rt count \{ \local anonymous
define field@struct anonymous,dt,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro union \{ fields@struct equ fields@struct,,union,<
sub@struct equ union \}
macro struct \{ fields@struct equ fields@struct,,substruct,<
sub@struct equ substruct \} }
 
macro ends
{ match , sub@struct \{ restruc db,dw,du,dd,dp,dq,dt
restruc rb,rw,rd,rp,rq,rt
purge db,dw,du,dd,dp,dq,dt
purge rb,rw,rd,rp,rq,rt
purge union,struct
match name tail,fields@struct, \\{ if $
display 'Error: definition of ',\\`name,' contains illegal instructions.',0Dh,0Ah
err
end if \\}
match name=,fields,fields@struct \\{ fields@struct equ
make@struct name,fields
define fields@\\#name fields \\}
end virtual \}
match any, sub@struct \{ fields@struct equ fields@struct> \}
restore sub@struct }
 
macro make@struct name,[field,type,def]
{ common
local define
define equ name
forward
local sub
match , field \{ make@substruct type,name,sub def
define equ define,.,sub, \}
match any, field \{ define equ define,.#field,type,<def> \}
common
match fields, define \{ define@struct fields \} }
 
macro define@struct name,[field,type,def]
{ common
virtual
db `name
load initial@struct byte from 0
if initial@struct = '.'
display 'Error: name of structure should not begin with a dot.',0Dh,0Ah
err
end if
end virtual
local list
list equ
forward
if ~ field eq .
name#field type def
sizeof.#name#field = $ - name#field
else
label name#.#type
rb sizeof.#type
end if
local value
match any, list \{ list equ list, \}
list equ list <value>
common
sizeof.#name = $
restruc name
match values, list \{
struc name value \\{ \\local \\..base
match any, fields@struct \\\{ fields@struct equ fields@struct,.,name,<values> \\\}
match , fields@struct \\\{ label \\..base
forward
match , value \\\\{ field type def \\\\}
match any, value \\\\{ field type value
if ~ field eq .
rb sizeof.#name#field - ($-field)
end if \\\\}
common label . at \\..base \\\}
\\}
macro name value \\{
match any, fields@struct \\\{ \\\local anonymous
fields@struct equ fields@struct,anonymous,name,<values> \\\}
match , fields@struct \\\{
forward
match , value \\\\{ type def \\\\}
match any, value \\\\{ \\\\local ..field
..field = $
type value
if ~ field eq .
rb sizeof.#name#field - ($-..field)
end if \\\\}
common \\\} \\} \} }
 
macro enable@substruct
{ macro make@substruct substruct,parent,name,[field,type,def]
\{ \common
\local define
define equ parent,name
\forward
\local sub
match , field \\{ match any, type \\\{ enable@substruct
make@substruct type,parent,sub def
purge make@substruct
define equ define,.,sub, \\\} \\}
match any, field \\{ define equ define,.\#field,type,<def> \\}
\common
match fields, define \\{ define@\#substruct fields \\} \} }
 
enable@substruct
 
macro define@union parent,name,[field,type,def]
{ common
virtual at parent#.#name
forward
if ~ field eq .
virtual at parent#.#name
parent#field type def
sizeof.#parent#field = $ - parent#field
end virtual
if sizeof.#parent#field > $ - parent#.#name
rb sizeof.#parent#field - ($ - parent#.#name)
end if
else
virtual at parent#.#name
label parent#.#type
type def
end virtual
label name#.#type at parent#.#name
if sizeof.#type > $ - parent#.#name
rb sizeof.#type - ($ - parent#.#name)
end if
end if
common
sizeof.#name = $ - parent#.#name
end virtual
struc name [value] \{ \common
label .\#name
last@union equ
forward
match any, last@union \\{ virtual at .\#name
field type def
end virtual \\}
match , last@union \\{ match , value \\\{ field type def \\\}
match any, value \\\{ field type value \\\} \\}
last@union equ field
common rb sizeof.#name - ($ - .\#name) \}
macro name [value] \{ \common \local ..anonymous
..anonymous name value \} }
 
macro define@substruct parent,name,[field,type,def]
{ common
virtual at parent#.#name
forward
if ~ field eq .
parent#field type def
sizeof.#parent#field = $ - parent#field
else
label parent#.#type
rb sizeof.#type
end if
common
sizeof.#name = $ - parent#.#name
end virtual
struc name value \{
label .\#name
forward
match , value \\{ field type def \\}
match any, value \\{ field type value
if ~ field eq .
rb sizeof.#parent#field - ($-field)
end if \\}
common \}
macro name value \{ \local ..anonymous
..anonymous name \} }
/kernel/branches/net/unpacker.inc
0,0 → 1,528
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
; void __stdcall unpack(void* packed_data, void* unpacked_data);
unpack:
pushad
mov esi, [esp+32+4]
mov edi, [esp+32+8]
mov eax, [esi+8]
and al, 0xC0
cmp al, 0xC0
jz .failed
mov eax, [esi+8]
push eax
add esi, 12
and al, not 0xC0
dec al
jz .lzma
.failed:
pop eax
popad
ret 8
.lzma:
call .lzma_unpack
.common:
pop eax
test al, 0x80
jnz .ctr1
test al, 0x40
jz .ok
lodsd
mov ecx, eax
jecxz .ok
mov dl, [esi]
mov esi, [esp+32+8]
.c1:
lodsb
sub al, 0E8h
cmp al, 1
ja .c1
cmp byte [esi], dl
jnz .c1
lodsd
; "bswap eax" is not supported on i386
shr ax, 8
ror eax, 16
xchg al, ah
sub eax, esi
add eax, [esp+32+8]
mov [esi-4], eax
loop .c1
.ok:
popad
ret 8
.ctr1:
lodsd
mov ecx, eax
jecxz .ok
mov dl, [esi]
mov esi, [esp+32+8]
.c2:
lodsb
@@:
cmp al, 0xF
jnz .f
lodsb
cmp al, 80h
jb @b
cmp al, 90h
jb @f
.f:
sub al, 0E8h
cmp al, 1
ja .c2
@@:
cmp byte [esi], dl
jnz .c2
lodsd
shr ax, 8
ror eax, 16
xchg al, ah
sub eax, esi
add eax, [esp+32+8]
mov [esi-4], eax
loop .c2
jmp .ok
 
.lzma_unpack:
 
.pb = 2 ; pos state bits
.lp = 0 ; literal pos state bits
.lc = 3 ; literal context bits
.posStateMask = ((1 shl .pb)-1)
.literalPosMask = ((1 shl .lp)-1)
 
.kNumPosBitsMax = 4
.kNumPosStatesMax = (1 shl .kNumPosBitsMax)
 
.kLenNumLowBits = 3
.kLenNumLowSymbols = (1 shl .kLenNumLowBits)
.kLenNumMidBits = 3
.kLenNumMidSymbols = (1 shl .kLenNumMidBits)
.kLenNumHighBits = 8
.kLenNumHighSymbols = (1 shl .kLenNumHighBits)
 
.LenChoice = 0
.LenChoice2 = 1
.LenLow = 2
.LenMid = (.LenLow + (.kNumPosStatesMax shl .kLenNumLowBits))
.LenHigh = (.LenMid + (.kNumPosStatesMax shl .kLenNumMidBits))
.kNumLenProbs = (.LenHigh + .kLenNumHighSymbols)
 
.kNumStates = 12
.kNumLitStates = 7
.kStartPosModelIndex = 4
.kEndPosModelIndex = 14
.kNumFullDistances = (1 shl (.kEndPosModelIndex/2))
.kNumPosSlotBits = 6
.kNumLenToPosStates = 4
.kNumAlignBits = 4
.kAlignTableSize = (1 shl .kNumAlignBits)
.kMatchMinLen = 2
 
.IsMatch = 0
.IsRep = (.IsMatch + (.kNumStates shl .kNumPosBitsMax))
.IsRepG0 = (.IsRep + .kNumStates)
.IsRepG1 = (.IsRepG0 + .kNumStates)
.IsRepG2 = (.IsRepG1 + .kNumStates)
.IsRep0Long = (.IsRepG2 + .kNumStates)
.PosSlot = (.IsRep0Long + (.kNumStates shl .kNumPosBitsMax))
.SpecPos = (.PosSlot + (.kNumLenToPosStates shl .kNumPosSlotBits))
.Align_ = (.SpecPos + .kNumFullDistances - .kEndPosModelIndex)
.Lencoder = (.Align_ + .kAlignTableSize)
.RepLencoder = (.Lencoder + .kNumLenProbs)
.Literal = (.RepLencoder + .kNumLenProbs)
 
.LZMA_BASE_SIZE = 1846 ; must be ==Literal
.LZMA_LIT_SIZE = 768
 
.kNumTopBits = 24
.kTopValue = (1 shl .kNumTopBits)
 
.kNumBitModelTotalBits = 11
.kBitModelTotal = (1 shl .kNumBitModelTotalBits)
.kNumMoveBits = 5
 
push edi
; int state=0;
xor ebx, ebx
mov [.previousByte], bl
; unsigned rep0=1,rep1=1,rep2=1,rep3=1;
mov eax, 1
mov edi, .rep0
stosd
stosd
stosd
stosd
; int len=0;
; result=0;
mov ecx, .Literal + (.LZMA_LIT_SIZE shl (.lc+.lp))
mov eax, .kBitModelTotal/2
mov edi, [.p]
rep stosd
; RangeDecoderInit
; rd->ExtraBytes = 0
; rd->Buffer = stream
; rd->BufferLim = stream+bufferSize
; rd->Range = 0xFFFFFFFF
pop edi
mov ebp, [esi-8] ; dest_length
add ebp, edi ; ebp = destination limit
lodsd
; rd->code_ = eax
mov [.code_], eax
or [.range], -1
.main_loop:
cmp edi, ebp
jae .main_loop_done
mov edx, edi
and edx, .posStateMask
mov eax, ebx
shl eax, .kNumPosBitsMax+2
lea eax, [.IsMatch*4 + eax + edx*4]
add eax, [.p]
call .RangeDecoderBitDecode
jc .1
movzx eax, [.previousByte]
if .literalPosMask
mov ah, dl
and ah, .literalPosMask
end if
shr eax, 8-.lc
imul eax, .LZMA_LIT_SIZE*4
add eax, .Literal*4
add eax, [.p]
cmp ebx, .kNumLitStates
jb .literal
xor edx, edx
sub edx, [.rep0]
mov dl, [edi + edx]
call .LzmaLiteralDecodeMatch
jmp @f
.literal:
call .LzmaLiteralDecode
@@:
mov [.previousByte], al
stosb
mov al, bl
cmp bl, 4
jb @f
mov al, 3
cmp bl, 10
jb @f
mov al, 6
@@:
sub bl, al
jmp .main_loop
.1:
lea eax, [.IsRep*4 + ebx*4]
add eax, [.p]
call .RangeDecoderBitDecode
jnc .10
lea eax, [.IsRepG0*4 + ebx*4]
add eax, [.p]
call .RangeDecoderBitDecode
jc .111
mov eax, ebx
shl eax, .kNumPosBitsMax+2
lea eax, [.IsRep0Long*4 + eax + edx*4]
add eax, [.p]
call .RangeDecoderBitDecode
jc .1101
cmp bl, 7
setae bl
lea ebx, [9 + ebx + ebx]
xor edx, edx
sub edx, [.rep0]
mov al, [edi + edx]
stosb
mov [.previousByte], al
jmp .main_loop
.111:
lea eax, [.IsRepG1*4 + ebx*4]
add eax, [.p]
call .RangeDecoderBitDecode
mov eax, [.rep1]
jnc .l3
.l1:
lea eax, [.IsRepG2*4 + ebx*4]
add eax, [.p]
call .RangeDecoderBitDecode
mov eax, [.rep2]
jnc .l2
xchg [.rep3], eax
.l2:
push [.rep1]
pop [.rep2]
.l3:
xchg eax, [.rep0]
mov [.rep1], eax
.1101:
mov eax, .RepLencoder*4
add eax, [.p]
call .LzmaLenDecode
cmp bl, 7
setc bl
adc bl, bl
xor bl, 3
add bl, 8
jmp .repmovsb
.10:
mov eax, [.rep0]
xchg eax, [.rep1]
xchg eax, [.rep2]
xchg eax, [.rep3]
cmp bl, 7
setc bl
adc bl, bl
xor bl, 3
add bl, 7
mov eax, .Lencoder*4
add eax, [.p]
call .LzmaLenDecode
mov eax, .kNumLenToPosStates-1
cmp eax, ecx
jb @f
mov eax, ecx
@@:
push ecx
mov ecx, .kNumPosSlotBits
shl eax, cl
shl eax, 2
add eax, .PosSlot*4
add eax, [.p]
call .RangeDecoderBitTreeDecode
mov [.rep0], ecx
cmp ecx, .kStartPosModelIndex
jb .l6
push ecx
mov eax, ecx
and eax, 1
shr ecx, 1
or eax, 2
dec ecx
shl eax, cl
mov [.rep0], eax
pop edx
cmp edx, .kEndPosModelIndex
jae .l5
sub eax, edx
shl eax, 2
add eax, (.SpecPos - 1)*4
add eax, [.p]
call .RangeDecoderReverseBitTreeDecode
add [.rep0], ecx
jmp .l6
.l5:
sub ecx, .kNumAlignBits
call .RangeDecoderDecodeDirectBits
mov ecx, .kNumAlignBits
shl eax, cl
add [.rep0], eax
mov eax, .Align_*4
add eax, [.p]
call .RangeDecoderReverseBitTreeDecode
add [.rep0], ecx
.l6:
pop ecx
inc [.rep0]
jz .main_loop_done
.repmovsb:
add ecx, .kMatchMinLen
push esi
mov esi, edi
sub esi, [.rep0]
rep movsb
pop esi
mov al, [edi-1]
mov [.previousByte], al
jmp .main_loop
.main_loop_done:
ret
 
.RangeDecoderBitDecode:
; in: eax->prob
; out: CF=bit; destroys eax
push edx
mov edx, [.range]
shr edx, .kNumBitModelTotalBits
imul edx, [eax]
cmp [.code_], edx
jae .ae
mov [.range], edx
mov edx, .kBitModelTotal
sub edx, [eax]
shr edx, .kNumMoveBits
add [eax], edx
clc
.n:
lahf
cmp [.range], .kTopValue
jae @f
shl [.range], 8
shl [.code_], 8
lodsb
mov byte [.code_], al
@@:
sahf
pop edx
ret
.ae:
sub [.range], edx
sub [.code_], edx
mov edx, [eax]
shr edx, .kNumMoveBits
sub [eax], edx
stc
jmp .n
 
.RangeDecoderDecodeDirectBits:
; in: ecx=numTotalBits
; out: eax=result; destroys edx
xor eax, eax
.l:
shr [.range], 1
shl eax, 1
mov edx, [.code_]
sub edx, [.range]
jb @f
mov [.code_], edx
or eax, 1
@@:
cmp [.range], .kTopValue
jae @f
shl [.range], 8
shl [.code_], 8
push eax
lodsb
mov byte [.code_], al
pop eax
@@:
loop .l
ret
 
.LzmaLiteralDecode:
; in: eax->probs
; out: al=byte; destroys edx
push ecx
mov ecx, 1
@@:
push eax
lea eax, [eax+ecx*4]
call .RangeDecoderBitDecode
pop eax
adc cl, cl
jnc @b
.LzmaLiteralDecode.ret:
mov al, cl
pop ecx
ret
.LzmaLiteralDecodeMatch:
; in: eax->probs, dl=matchByte
; out: al=byte; destroys edx
push ecx
mov ecx, 1
.LzmaLiteralDecodeMatch.1:
add dl, dl
setc ch
push eax
lea eax, [eax+ecx*4+0x100*4]
call .RangeDecoderBitDecode
pop eax
adc cl, cl
jc .LzmaLiteralDecode.ret
xor ch, cl
test ch, 1
mov ch, 0
jnz @b
jmp .LzmaLiteralDecodeMatch.1
 
.LzmaLenDecode:
; in: eax->prob, edx=posState
; out: ecx=len
push eax
add eax, .LenChoice*4
call .RangeDecoderBitDecode
pop eax
jnc .0
push eax
add eax, .LenChoice2*4
call .RangeDecoderBitDecode
pop eax
jc @f
mov ecx, .kLenNumMidBits
shl edx, cl
lea eax, [eax + .LenMid*4 + edx*4]
call .RangeDecoderBitTreeDecode
add ecx, .kLenNumLowSymbols
ret
@@:
add eax, .LenHigh*4
mov ecx, .kLenNumHighBits
call .RangeDecoderBitTreeDecode
add ecx, .kLenNumLowSymbols + .kLenNumMidSymbols
ret
.0:
mov ecx, .kLenNumLowBits
shl edx, cl
lea eax, [eax + .LenLow*4 + edx*4]
.RangeDecoderBitTreeDecode:
; in: eax->probs,ecx=numLevels
; out: ecx=length; destroys edx
push ebx
mov edx, 1
mov ebx, edx
@@:
push eax
lea eax, [eax+edx*4]
call .RangeDecoderBitDecode
pop eax
adc dl, dl
add bl, bl
loop @b
sub dl, bl
pop ebx
mov ecx, edx
ret
.RangeDecoderReverseBitTreeDecode:
; in: eax->probs,ecx=numLevels
; out: ecx=length; destroys edx
push ebx ecx
mov edx, 1
xor ebx, ebx
@@:
push eax
lea eax, [eax+edx*4]
call .RangeDecoderBitDecode
lahf
adc edx, edx
sahf
rcr ebx, 1
pop eax
loop @b
pop ecx
rol ebx, cl
mov ecx, ebx
pop ebx
ret
 
uglobal
align 4
;unpack.p rd unpack.LZMA_BASE_SIZE + (unpack.LZMA_LIT_SIZE shl (unpack.lc+unpack.lp))
unpack.p dd ?
unpack.code_ dd ?
unpack.range dd ?
unpack.rep0 dd ?
unpack.rep1 dd ?
unpack.rep2 dd ?
unpack.rep3 dd ?
unpack.previousByte db ?
endg
Property changes:
Added: svn:keywords
+Revision
\ No newline at end of property
Added: svn:mergeinfo
/kernel/branches/net/build.bat
0,0 → 1,161
@echo off
cls
set languages=en
set drivers=3c59x dec21x4x i8255x mtd80x pcnet32 r6040 rtl8029 rtl8139 rtl8169 sis900
set apps=arpcfg icmp netcfg netstat nslookup synergyc tcpserv telnet tftpc zeroconf
set libs=network
set targets=all kernel apps libs drivers clean
 
call :Check_Target %1
for %%a in (all kernel) do if %%a==%target% call :Check_Lang %2
call :Target_%target%
 
if ERRORLEVEL 0 goto Exit_OK
 
echo There was an error executing script.
echo For any help, please send a report.
pause
goto :eof
 
 
 
 
:Check_Lang
set res=%1
:Check_Lang_loop
for %%a in (%languages%) do if %%a==%res% set lang=%res%
if defined lang goto :eof
 
echo Language '%res%' is incorrect
echo Enter valid language [ %languages% ]:
 
set /P res=">
goto Check_Lang_loop
goto :eof
 
:Check_Target
set res=%1
:Check_Target_loop
for %%a in (%targets%) do if %%a==%res% set target=%res%
if defined target goto :eof
 
echo Target '%res%' is incorrect
echo Enter valid target [ %targets% ]:
 
set /P res=">
goto Check_Target_loop
goto :eof
 
 
:Target_kernel
echo *** building kernel with language '%lang%' ...
 
if not exist bin mkdir bin
echo lang fix %lang% > lang.inc
fasm -m 65536 kernel.asm bin\kernel.mnt
if not %errorlevel%==0 goto :Error_FasmFailed
erase lang.inc
goto :eof
 
 
:Target_all
call :Target_kernel
call :Target_apps
call :Target_libs
call :Target_drivers
goto :eof
 
 
:Target_apps
echo *** building applications ...
 
if not exist bin\apps mkdir bin\apps
cd applications
for %%a in (%apps%) do (
fasm -m 65536 %%a\%%a.asm ..\bin\apps\%%a
if not %errorlevel%==0 goto :Error_FasmFailed
)
cd ..
 
goto :eof
 
 
:Target_libs
echo *** building libraries ...
 
if not exist bin\lib mkdir bin\lib
cd applications\libraries
for %%a in (%libs%) do (
fasm -m 65536 %%a\%%a.asm ..\..\bin\lib\%%a.obj
if not %errorlevel%==0 goto :Error_FasmFailed
)
cd ..\..
 
goto :eof
 
 
:Target_drivers
echo *** building drivers ...
 
if not exist bin\drivers mkdir bin\drivers
cd drivers
for %%a in (%drivers%) do (
fasm -m 65536 %%a.asm ..\bin\drivers\%%a.obj
if not %errorlevel%==0 goto :Error_FasmFailed
)
cd ..
 
 
kpack >nul 2>&1
 
if %errorlevel%==9009 goto :Error_KpackFailed
 
echo *
echo ##############################################
echo *
echo Kpack KolibriOS drivers?
echo *
 
set /P res=[y/n]?
 
if "%res%"=="y" (
 
echo *
echo Compressing system
 
echo *
for %%a in (bin\drivers\*.obj) do (
echo ================== kpack %%a
kpack %%a
if not %errorlevel%==0 goto :Error_KpackFailed
)
 
)
goto :eof
 
:Target_clean
echo *** cleaning ...
rmdir /S /Q bin
goto :Exit_OK
 
 
:Error_FasmFailed
echo error: fasm execution failed
erase lang.inc >nul 2>&1
echo.
pause
exit 1
 
:Error_KpackFailed
echo *** NOTICE ***
echo If you want to pack all applications you may
echo place "kpack" in accessible directory or system %PATH%.
echo You can get this tool from KolibriOS distribution kit.
pause
exit 1
 
:Exit_OK
echo.
echo all operations have been done
pause
exit 0
Property changes:
Added: svn:mergeinfo
/kernel/branches/net/COPYING.TXT
0,0 → 1,347
 
GNU GENERAL PUBLIC LICENSE
 
Version 2, June 1991
 
 
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
 
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
 
 
Preamble
 
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
 
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
 
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
 
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
 
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
 
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
 
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
 
The precise terms and conditions for copying, distribution and
modification follow.
 
 
GNU GENERAL PUBLIC LICENSE
 
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
 
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
 
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
 
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
 
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
 
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
 
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
 
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
 
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
 
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
 
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
 
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
 
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
 
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
 
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
 
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
 
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
 
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
 
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
 
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
 
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
 
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
 
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
 
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
 
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
 
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
 
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
 
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
 
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
 
NO WARRANTY
 
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
 
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
 
END OF TERMS AND CONDITIONS
 
Appendix: How to Apply These Terms to Your New Programs
 
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
 
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
 
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
Also add information on how to contact you by electronic and paper mail.
 
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
 
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
 
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
 
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
 
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
 
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
 
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
Property changes:
Added: svn:mergeinfo
/kernel/branches/net
Property changes:
Added: svn:ignore
+bin