diff --git a/kernel/branches/kolibri_pe/core/dll.c b/kernel/branches/kolibri_pe/core/dll.c index 9d68fb1ac3..c4f507b115 100644 --- a/kernel/branches/kolibri_pe/core/dll.c +++ b/kernel/branches/kolibri_pe/core/dll.c @@ -277,18 +277,22 @@ int sys_exec(char *path, char *cmdline, u32_t flags) ( raw[1] == 0x30305445) ) ) { - DBG("leagacy Kolibri application\n"); + DBG("leagacy Kolibri application"); int tmp = mnt_exec(raw, raw_size, path, cmdline, flags); + DBG(" pid %x\n",tmp); return tmp; } - if( ! validate_pe(raw, raw_size) ) + if( ! validate_pe(raw, raw_size, true) ) { DBG("invalid executable file %s\n", path); mem_free(raw); return -31; } + dos = (PIMAGE_DOS_HEADER)raw; + nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); + pathsize = strlen(path)+1; if( cmdline ) @@ -359,8 +363,7 @@ int sys_exec(char *path, char *cmdline, u32_t flags) DBG("create stack at %x\n\tpath %x\n\tcmdline %x\n", ex_stack, ex_stack->path, ex_stack->cmdline); - pe_app_param(path, raw, ex_pg_dir, ex_stack); - return 0; + return pe_app_param(path, raw, ex_pg_dir, ex_stack); }; #define master_tab (page_tabs+ (page_tabs>>10)) @@ -394,6 +397,10 @@ void sys_app_entry(addr_t raw, thr_stack_t *thr_stack, exec_stack_t *ex_stack) size_t img_size; count_t img_pages; + size_t stack_size; + addr_t img_stack; + addr_t *pte; + count_t i; u32_t tmp; @@ -408,18 +415,26 @@ void sys_app_entry(addr_t raw, thr_stack_t *thr_stack, exec_stack_t *ex_stack) list_initialize(¤t_slot->dll_list); + pte = (addr_t*)page_tabs; img_pages = img_size >> 12; - for(i = 0; i < img_pages; i++) - { - addr_t page = core_alloc(0); - ((u32_t*)page_tabs)[i] = page | 7; /* FIXME */ - } + stack_size = (nt->OptionalHeader.SizeOfStackReserve + 4095) & ~4095; + img_stack = 0x7FFFF000 - stack_size; + stack_size>>= 12; + + while (img_pages--) + *pte++ = 2; + + pte = &((addr_t*)page_tabs)[img_stack>>12]; + + while(stack_size--) + *pte++ = 0x02; addr_t stack_page = ((addr_t)ex_stack-OS_BASE) & ~4095; - ((u32_t*)page_tabs)[0x7FFFF000>>12] = stack_page | 7; - create_image(0, raw); + *pte = stack_page | 7; + + create_image(0, raw, false); init_user_heap(); @@ -430,8 +445,9 @@ void sys_app_entry(addr_t raw, thr_stack_t *thr_stack, exec_stack_t *ex_stack) "int $0x40"::"a"(-1)); }; -// __asm__ __volatile__ ( -// "xchgw %bx, %bx"); + + // __asm__ __volatile__ ( + // "xchgw %bx, %bx"); addr_t entry = nt->OptionalHeader.AddressOfEntryPoint + nt->OptionalHeader.ImageBase; @@ -481,7 +497,7 @@ dll_t* __fastcall load_dll(const char *path) return NULL; }; - if( ! validate_pe(raw, raw_size) ) + if( ! validate_pe(raw, raw_size, false) ) { DBG("invalid pe file %s\n", path); mem_free(raw); @@ -508,7 +524,7 @@ dll_t* __fastcall load_dll(const char *path) return NULL; }; - create_image(img_base, (addr_t)raw); + create_image(img_base, (addr_t)raw, false); mem_free(raw); @@ -609,22 +625,24 @@ bool link_pe(addr_t img_base) { PIMAGE_IMPORT_BY_NAME ord; addr_t addr; + *iat=0; if ( thunk->u1.AddressOfData == 0 ) break; if ( thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG ) { - // printf(" %4u\n", thunk->u1.Ordinal & 0xFFFF); + u16_t ordinal; + ordinal = thunk->u1.Ordinal & 0xFFFF; + *iat = functions[ordinal-exp->Base] + exp_dll->img_base; break; } else { ord = MakePtr(PIMAGE_IMPORT_BY_NAME, thunk->u1.AddressOfData, img_base); - *iat=0; - DBG("import %s", ord->Name); + DBG("import %s ", ord->Name); if(strncmp(ord->Name, MakePtr(char*,funcname[ord->Hint],exp_dll->img_base),32)) @@ -639,7 +657,7 @@ bool link_pe(addr_t img_base) { u16_t ordinal; ordinal = ordinals[ind]; - DBG(" \t\tat %x\n", functions[ordinal] + exp_dll->img_base); + DBG("ordinal %d\t\tat %x\n", ordinal, functions[ordinal] + exp_dll->img_base); *iat = functions[ordinal] + exp_dll->img_base; break; }; diff --git a/kernel/branches/kolibri_pe/core/export.asm b/kernel/branches/kolibri_pe/core/export.asm index d05e479cd8..d940c1ba7a 100644 --- a/kernel/branches/kolibri_pe/core/export.asm +++ b/kernel/branches/kolibri_pe/core/export.asm @@ -3,7 +3,7 @@ .section .drectve - .ascii " -export:CreateImage" # cdecl +# .ascii " -export:CreateImage" # cdecl .ascii " -export:LoadFile" # stdcall .ascii " -export:Kmalloc" # eax FIXME diff --git a/kernel/branches/kolibri_pe/core/heap.inc b/kernel/branches/kolibri_pe/core/heap.inc index 004a20c5dd..03fe733a19 100644 --- a/kernel/branches/kolibri_pe/core/heap.inc +++ b/kernel/branches/kolibri_pe/core/heap.inc @@ -32,20 +32,20 @@ init_heap: sub eax, 4096 ret @@: - mov esi, [ebx+APPDATA.mem_size] - add esi, 4095 - and esi, not 4095 - mov [ebx+APPDATA.mem_size], esi + mov edx, [ebx+APPDATA.mem_size] + add edx, 4095 + and edx, not 4095 + mov [ebx+APPDATA.mem_size], edx mov eax, HEAP_TOP - mov [ebx+APPDATA.heap_base], esi + mov [ebx+APPDATA.heap_base], edx mov [ebx+APPDATA.heap_top], eax - sub eax, esi - shr esi, 10 + sub eax, edx + shr edx, 10 mov ecx, eax sub eax, 4096 or ecx, FREE_BLOCK - mov [page_tabs+esi], ecx + mov [page_tabs+edx], ecx ret align 4 diff --git a/kernel/branches/kolibri_pe/core/pe.c b/kernel/branches/kolibri_pe/core/pe.c index f1f4aae520..2cb86e1c9c 100644 --- a/kernel/branches/kolibri_pe/core/pe.c +++ b/kernel/branches/kolibri_pe/core/pe.c @@ -40,7 +40,6 @@ static inline void sec_clear(addr_t dst, size_t len) int __stdcall strncmp(const char *s1, const char *s2, size_t n); -void __export create_image(addr_t img_base, addr_t raw) asm ("CreateImage"); bool link_image(addr_t img_base); md_t* __fastcall load_image(const char *path); @@ -59,7 +58,7 @@ void* __fastcall load_pe(const char *path) }; */ -bool validate_pe(void *raw, size_t raw_size) +bool validate_pe(void *raw, size_t raw_size, bool is_exec) { PIMAGE_DOS_HEADER dos; PIMAGE_NT_HEADERS32 nt; @@ -80,9 +79,18 @@ bool validate_pe(void *raw, size_t raw_size) if(nt->Signature != IMAGE_NT_SIGNATURE) return false; + if(nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) + return false; + + if(is_exec && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL)) + return false; + if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) return false; + if( is_exec && nt->OptionalHeader.ImageBase != 0) + return false; + if(nt->OptionalHeader.SectionAlignment < PAGE_SIZE) { if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment) @@ -127,7 +135,7 @@ md_t* __fastcall load_image(const char *path) return NULL; }; - if( ! validate_pe(raw, raw_size) ) + if( ! validate_pe(raw, raw_size, false) ) { DBG("invalid pe file %s\n", path); mem_free(raw); @@ -150,7 +158,7 @@ md_t* __fastcall load_image(const char *path) img_base = img_md->base; - create_image(img_base, (addr_t)raw); + create_image(img_base, (addr_t)raw, true); mem_free(raw); @@ -190,7 +198,7 @@ addr_t get_proc_addr(addr_t module, char *name) */ -void create_image(addr_t img_base, addr_t raw) +void create_image(addr_t img_base, addr_t raw, bool force_clear) { PIMAGE_DOS_HEADER dos; PIMAGE_NT_HEADERS32 nt; @@ -223,13 +231,16 @@ void create_image(addr_t img_base, addr_t raw) if(img_sec->SizeOfRawData) sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData); + if(force_clear) + { sec_size = (img_sec->Misc.VirtualSize + sec_align -1) & -sec_align; if(sec_size > img_sec->SizeOfRawData) sec_clear(dest_ptr + img_sec->SizeOfRawData, sec_size - img_sec->SizeOfRawData); + }; img_sec++; - } + }; if(nt->OptionalHeader.DataDirectory[5].Size) { diff --git a/kernel/branches/kolibri_pe/core/taskman.inc b/kernel/branches/kolibri_pe/core/taskman.inc index 760f67b061..1d310cacb8 100644 --- a/kernel/branches/kolibri_pe/core/taskman.inc +++ b/kernel/branches/kolibri_pe/core/taskman.inc @@ -146,11 +146,12 @@ proc mnt_exec stdcall file_base:dword, file_size:dword, \ test al, al jnz @b + lea edi, [cmdline] + mov dword [edi],0 mov esi, [cmd_line] test esi, esi jz .no_cmdline - lea edi, [cmdline] lea ecx, [edi+255] mov [edi+252], dword 0 @@: @@ -226,8 +227,8 @@ proc mnt_exec stdcall file_base:dword, file_size:dword, \ mov ecx, [hdr_mem] mov edi, [file_size] - add edi, 4095 - and edi, not 4095 + ; add edi, 4095 + ; and edi, not 4095 sub ecx, edi jna @F @@ -246,8 +247,8 @@ proc mnt_exec stdcall file_base:dword, file_size:dword, \ mov eax, [save_cr3] call set_cr3 - mov [application_table_status], 0 ;unlock application_table_status mutex mov eax,[process_number] ;set result + mov [application_table_status], 0 ;unlock application_table_status mutex pop edi pop esi @@ -433,8 +434,8 @@ proc pe_app_param stdcall path:dword, raw:dword, ex_pg_dir:dword, ex_stack:dword DEBUGF 1,"%s",new_process_running .err: - mov [application_table_status], 0 ;unlock application_table_status mutex mov eax,[process_number] ;set result + mov [application_table_status], 0 ;unlock application_table_status mutex pop edi pop esi diff --git a/kernel/branches/kolibri_pe/docs/sysfuncr.txt b/kernel/branches/kolibri_pe/docs/sysfuncr.txt index 0d27bd762d..841cbabef2 100644 --- a/kernel/branches/kolibri_pe/docs/sysfuncr.txt +++ b/kernel/branches/kolibri_pe/docs/sysfuncr.txt @@ -3402,9 +3402,9 @@ IPC * ebx = указатель на изображение * ecx = [размер по оси x]*65536 + [размер по оси y] * edx = [координата по оси x]*65536 + [координата по оси y] - * esi = число бит на пиксель, должно быть 8, 16, 24 или 32 - * edi = указатель на палитру (256 цветов 0x00RRGGBB); - игнорируется при esi = 16, 24 и 32 + * esi = число бит на пиксель, должно быть 1, 4, 8, 15, 16, 24 или 32 + * edi = указатель на палитру (2 в степени esi цветов 0x00RRGGBB); + игнорируется при esi > 8 * ebp = смещение данных каждой следующей строки изображения относительно предыдущей Возвращаемое значение: @@ -3413,13 +3413,23 @@ IPC * Координаты изображения - это координаты верхнего левого угла изображения относительно окна. * Размер изображения в байтах есть xsize*ysize. + * Формат изображения с 1 битом на пиксель: каждый байт изображения, + за исключением, быть может, последних байтов строк, содержит + информацию о цвете 8 пикселей, старший бит соответствует первому + пикселю. + * Формат изображения с 4 битами на пиксель: каждый байт изображения, + за исключением последних байтов строк (если ширина изображения + нечётна), содержит информацию о цвете 2 пикселей, старшая тетрада + соответствует первому пикселю. * Формат изображения с 8 битами на пиксель: каждый байт изображения рассматривается как индекс в палитре. * Если изображение использует не все 256 цветов, а меньше, размер палитры может быть меньше 256. - * Формат изображения с 16 битами на пиксель: цвет каждого пикселя + * Формат изображения с 15 битами на пиксель: цвет каждого пикселя кодируется как (в битовом представлении) 0RRRRRGGGGGBBBBB - по 5 пикселей на каждый цвет. + * Формат изображения с 16 битами на пиксель: цвет каждого пикселя + кодируется как RRRRRGGGGGGBBBBB (схема 5+6+5). * Формат изображения с 24 битами на пиксель: цвет каждого пикселя кодируется тремя байтами - последовательно синяя, зелёная, красная составляющие цвета. diff --git a/kernel/branches/kolibri_pe/drivers/ati2d.asm b/kernel/branches/kolibri_pe/drivers/ati2d.asm index 0915797cee..b27a296a6d 100644 --- a/kernel/branches/kolibri_pe/drivers/ati2d.asm +++ b/kernel/branches/kolibri_pe/drivers/ati2d.asm @@ -1195,61 +1195,185 @@ devices: dd (0x5D4D shl 16)+VID_ATI, init_r200 ;R480 X850 dd (0x5D52 shl 16)+VID_ATI, init_r200 ;R480 X850 - dd (0x791E shl 16)+VID_ATI, init_r500 ;RS690 X1200 - - dd (0x7140 shl 16)+VID_ATI, init_r500 ;RV515 X1300 - dd (0x7142 shl 16)+VID_ATI, init_r500 ;RV515 X1300 - dd (0x7146 shl 16)+VID_ATI, init_r500 ;RV515 X1300 - dd (0x714D shl 16)+VID_ATI, init_r500 ;RV515 X1300 - dd (0x714E shl 16)+VID_ATI, init_r500 ;RV515 X1300 - - dd (0x7183 shl 16)+VID_ATI, init_r500 ;RV515 X1300 - dd (0x7187 shl 16)+VID_ATI, init_r500 ;RV515 X1300 - dd (0x718F shl 16)+VID_ATI, init_r500 ;RV515 X1300 - - dd (0x7143 shl 16)+VID_ATI, init_r500 ;RV515 X1550 - dd (0x7147 shl 16)+VID_ATI, init_r500 ;RV515 X1550 - dd (0x715F shl 16)+VID_ATI, init_r500 ;RV515 X1550 - dd (0x7193 shl 16)+VID_ATI, init_r500 ;RV515 X1550 - dd (0x719F shl 16)+VID_ATI, init_r500 ;RV515 X1550 - - dd (0x71C0 shl 16)+VID_ATI, init_r500 ;RV530 X1600 - dd (0x71C1 shl 16)+VID_ATI, init_r500 ;RV535 X1650 - dd (0x71C2 shl 16)+VID_ATI, init_r500 ;RV530 X1600 - dd (0x71C3 shl 16)+VID_ATI, init_r500 ;RV535 X1600 - dd (0x71C6 shl 16)+VID_ATI, init_r500 ;RV530 X1600 - dd (0x71C7 shl 16)+VID_ATI, init_r500 ;RV534 X1650 - - dd (0x7181 shl 16)+VID_ATI, init_r500 ;RV515 X1600 - dd (0x71CD shl 16)+VID_ATI, init_r500 ;RV530 X1600 - - dd (0x7291 shl 16)+VID_ATI, init_r500 ;R580 X1650 - dd (0x7293 shl 16)+VID_ATI, init_r500 ;R580 X1650 - - dd (0x7100 shl 16)+VID_ATI, init_r500 ;RV520 X1800 - dd (0x7109 shl 16)+VID_ATI, init_r500 ;RV520 X1800 - dd (0x710A shl 16)+VID_ATI, init_r500 ;RV520 X1800 GTO - - dd (0x7249 shl 16)+VID_ATI, init_r500 ;RV580 X1900 - dd (0x724B shl 16)+VID_ATI, init_r500 ;RV580 X1900 GT - - dd (0x7240 shl 16)+VID_ATI, init_r500 ;RV580 X1950 - dd (0x7244 shl 16)+VID_ATI, init_r500 ;RV580 X1950 - dd (0x7248 shl 16)+VID_ATI, init_r500 ;RV580 X1950 - - dd (0x7288 shl 16)+VID_ATI, init_r500 ;R580 X1950 GT - dd (0x7280 shl 16)+VID_ATI, init_r500 ;R580 X1950 PRO - - dd (0x94C3 shl 16)+VID_ATI, init_r500 ;RV610 HD 2400 PRO - dd (0x94C1 shl 16)+VID_ATI, init_r500 ;RV610 HD 2400 XT - - dd (0x9589 shl 16)+VID_ATI, init_r500 ;RV630 HD 2600 PRO - dd (0x958A shl 16)+VID_ATI, init_r500 ;RV630 HD 2600 X2 - dd (0x9588 shl 16)+VID_ATI, init_r500 ;RV630 HD 2600 XT - - dd (0x9403 shl 16)+VID_ATI, init_r500 ;R600 HD 2900 PRO - dd (0x9409 shl 16)+VID_ATI, init_r500 ;R600 HD 2900 XT - + dd (0x7100 shl 16)+VID_ATI, init_r500 ;Radeon X1800 + dd (0x7101 shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1800 XT + dd (0x7102 shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1800 + dd (0x7103 shl 16)+VID_ATI, init_r500 ;Mobility FireGL V7200 + dd (0x7104 shl 16)+VID_ATI, init_r500 ;FireGL V7200 + dd (0x7105 shl 16)+VID_ATI, init_r500 ;FireGL V5300 + dd (0x7106 shl 16)+VID_ATI, init_r500 ;Mobility FireGL V7100 + dd (0x7108 shl 16)+VID_ATI, init_r500 ;Radeon X1800 + dd (0x7109 shl 16)+VID_ATI, init_r500 ;Radeon X1800 + dd (0x710A shl 16)+VID_ATI, init_r500 ;Radeon X1800 + dd (0x710B shl 16)+VID_ATI, init_r500 ;Radeon X1800 + dd (0x710C shl 16)+VID_ATI, init_r500 ;Radeon X1800 + dd (0x710E shl 16)+VID_ATI, init_r500 ;FireGL V7300 + dd (0x710F shl 16)+VID_ATI, init_r500 ;FireGL V7350 + dd (0x7140 shl 16)+VID_ATI, init_r500 ;Radeon X1600/X1550 + dd (0x7141 shl 16)+VID_ATI, init_r500 ;RV505 + dd (0x7142 shl 16)+VID_ATI, init_r500 ;Radeon X1300/X1550 + dd (0x7143 shl 16)+VID_ATI, init_r500 ;Radeon X1550 + dd (0x7144 shl 16)+VID_ATI, init_r500 ;M54-GL + dd (0x7145 shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1400 + dd (0x7146 shl 16)+VID_ATI, init_r500 ;Radeon X1300/X1550 + dd (0x7147 shl 16)+VID_ATI, init_r500 ;Radeon X1550 64-bit + dd (0x7149 shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1300 + dd (0x714A shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1300 + dd (0x714B shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1300 + dd (0x714C shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1300 + dd (0x714D shl 16)+VID_ATI, init_r500 ;Radeon X1300 + dd (0x714E shl 16)+VID_ATI, init_r500 ;Radeon X1300 + dd (0x714F shl 16)+VID_ATI, init_r500 ;RV505 + dd (0x7151 shl 16)+VID_ATI, init_r500 ;RV505 + dd (0x7152 shl 16)+VID_ATI, init_r500 ;FireGL V3300 + dd (0x7153 shl 16)+VID_ATI, init_r500 ;FireGL V3350 + dd (0x715E shl 16)+VID_ATI, init_r500 ;Radeon X1300 + dd (0x715F shl 16)+VID_ATI, init_r500 ;Radeon X1550 64-bit + dd (0x7180 shl 16)+VID_ATI, init_r500 ;Radeon X1300/X1550 + dd (0x7181 shl 16)+VID_ATI, init_r500 ;Radeon X1600 + dd (0x7183 shl 16)+VID_ATI, init_r500 ;Radeon X1300/X1550 + dd (0x7186 shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1450 + dd (0x7187 shl 16)+VID_ATI, init_r500 ;Radeon X1300/X1550 + dd (0x7188 shl 16)+VID_ATI, init_r500 ;Mobility Radeon X2300 + dd (0x718A shl 16)+VID_ATI, init_r500 ;Mobility Radeon X2300 + dd (0x718B shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1350 + dd (0x718C shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1350 + dd (0x718D shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1450 + dd (0x718F shl 16)+VID_ATI, init_r500 ;Radeon X1300 + dd (0x7193 shl 16)+VID_ATI, init_r500 ;Radeon X1550 + dd (0x7196 shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1350 + dd (0x719B shl 16)+VID_ATI, init_r500 ;FireMV 2250 + dd (0x719F shl 16)+VID_ATI, init_r500 ;Radeon X1550 64-bit + dd (0x71C0 shl 16)+VID_ATI, init_r500 ;Radeon X1600 + dd (0x71C1 shl 16)+VID_ATI, init_r500 ;Radeon X1650 + dd (0x71C2 shl 16)+VID_ATI, init_r500 ;Radeon X1600 + dd (0x71C3 shl 16)+VID_ATI, init_r500 ;Radeon X1600 + dd (0x71C4 shl 16)+VID_ATI, init_r500 ;Mobility FireGL V5200 + dd (0x71C5 shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1600 + dd (0x71C6 shl 16)+VID_ATI, init_r500 ;Radeon X1650 + dd (0x71C7 shl 16)+VID_ATI, init_r500 ;Radeon X1650 + dd (0x71CD shl 16)+VID_ATI, init_r500 ;Radeon X1600 + dd (0x71CE shl 16)+VID_ATI, init_r500 ;Radeon X1300 XT/X1600 Pro + dd (0x71D2 shl 16)+VID_ATI, init_r500 ;FireGL V3400 + dd (0x71D4 shl 16)+VID_ATI, init_r500 ;Mobility FireGL V5250 + dd (0x71D5 shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1700 + dd (0x71D6 shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1700 XT + dd (0x71DA shl 16)+VID_ATI, init_r500 ;FireGL V5200 + dd (0x71DE shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1700 + dd (0x7200 shl 16)+VID_ATI, init_r500 ;Radeon X2300HD + dd (0x7210 shl 16)+VID_ATI, init_r500 ;Mobility Radeon HD 2300 + dd (0x7211 shl 16)+VID_ATI, init_r500 ;Mobility Radeon HD 2300 + dd (0x7240 shl 16)+VID_ATI, init_r500 ;Radeon X1950 + dd (0x7243 shl 16)+VID_ATI, init_r500 ;Radeon X1900 + dd (0x7244 shl 16)+VID_ATI, init_r500 ;Radeon X1950 + dd (0x7245 shl 16)+VID_ATI, init_r500 ;Radeon X1900 + dd (0x7246 shl 16)+VID_ATI, init_r500 ;Radeon X1900 + dd (0x7247 shl 16)+VID_ATI, init_r500 ;Radeon X1900 + dd (0x7248 shl 16)+VID_ATI, init_r500 ;Radeon X1900 + dd (0x7249 shl 16)+VID_ATI, init_r500 ;Radeon X1900 + dd (0x724A shl 16)+VID_ATI, init_r500 ;Radeon X1900 + dd (0x724B shl 16)+VID_ATI, init_r500 ;Radeon X1900 + dd (0x724C shl 16)+VID_ATI, init_r500 ;Radeon X1900 + dd (0x724D shl 16)+VID_ATI, init_r500 ;Radeon X1900 + dd (0x724E shl 16)+VID_ATI, init_r500 ;AMD Stream Processor + dd (0x724F shl 16)+VID_ATI, init_r500 ;Radeon X1900 + dd (0x7280 shl 16)+VID_ATI, init_r500 ;Radeon X1950 + dd (0x7281 shl 16)+VID_ATI, init_r500 ;RV560 + dd (0x7283 shl 16)+VID_ATI, init_r500 ;RV560 + dd (0x7284 shl 16)+VID_ATI, init_r500 ;Mobility Radeon X1900 + dd (0x7287 shl 16)+VID_ATI, init_r500 ;RV560 + dd (0x7288 shl 16)+VID_ATI, init_r500 ;Radeon X1950 GT + dd (0x7289 shl 16)+VID_ATI, init_r500 ;RV570 + dd (0x728B shl 16)+VID_ATI, init_r500 ;RV570 + dd (0x728C shl 16)+VID_ATI, init_r500 ;ATI FireGL V7400 + dd (0x7290 shl 16)+VID_ATI, init_r500 ;RV560 + dd (0x7291 shl 16)+VID_ATI, init_r500 ;Radeon X1650 + dd (0x7293 shl 16)+VID_ATI, init_r500 ;Radeon X1650 + dd (0x7297 shl 16)+VID_ATI, init_r500 ;RV560 + dd (0x791E shl 16)+VID_ATI, init_r500 ;Radeon X1200 + dd (0x791F shl 16)+VID_ATI, init_r500 ;Radeon X1200 + dd (0x793F shl 16)+VID_ATI, init_r500 ;Radeon Xpress 1200 + dd (0x7941 shl 16)+VID_ATI, init_r500 ;Radeon Xpress 1200 + dd (0x7942 shl 16)+VID_ATI, init_r500 ;Radeon Xpress 1200 (M) + dd (0x796C shl 16)+VID_ATI, init_r500 ;RS740 + dd (0x796D shl 16)+VID_ATI, init_r500 ;RS740M + dd (0x796E shl 16)+VID_ATI, init_r500 ;ATI Radeon 2100 RS740 + dd (0x796F shl 16)+VID_ATI, init_r500 ;RS740M + dd (0x9400 shl 16)+VID_ATI, init_r500 ;Radeon HD 2900 XT + dd (0x9401 shl 16)+VID_ATI, init_r500 ;Radeon HD 2900 XT + dd (0x9402 shl 16)+VID_ATI, init_r500 ;Radeon HD 2900 XT + dd (0x9403 shl 16)+VID_ATI, init_r500 ;Radeon HD 2900 Pro + dd (0x9405 shl 16)+VID_ATI, init_r500 ;Radeon HD 2900 GT + dd (0x940A shl 16)+VID_ATI, init_r500 ;FireGL V8650 + dd (0x940B shl 16)+VID_ATI, init_r500 ;FireGL V8600 + dd (0x940F shl 16)+VID_ATI, init_r500 ;FireGL V7600 + dd (0x94C0 shl 16)+VID_ATI, init_r500 ;RV610 + dd (0x94C1 shl 16)+VID_ATI, init_r500 ;Radeon HD 2400 XT + dd (0x94C3 shl 16)+VID_ATI, init_r500 ;Radeon HD 2400 Pro + dd (0x94C4 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 2400 PRO AGP + dd (0x94C5 shl 16)+VID_ATI, init_r500 ;FireGL V4000 + dd (0x94C6 shl 16)+VID_ATI, init_r500 ;RV610 + dd (0x94C7 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 2350 + dd (0x94C8 shl 16)+VID_ATI, init_r500 ;Mobility Radeon HD 2400 XT + dd (0x94C9 shl 16)+VID_ATI, init_r500 ;Mobility Radeon HD 2400 + dd (0x94CB shl 16)+VID_ATI, init_r500 ;ATI RADEON E2400 + dd (0x94CC shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 2400 + dd (0x9500 shl 16)+VID_ATI, init_r500 ;RV670 + dd (0x9501 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD3870 + dd (0x9504 shl 16)+VID_ATI, init_r500 ;ATI Mobility Radeon HD 3850 + dd (0x9505 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD3850 + dd (0x9506 shl 16)+VID_ATI, init_r500 ;ATI Mobility Radeon HD 3850 X2 + dd (0x9507 shl 16)+VID_ATI, init_r500 ;RV670 + dd (0x9508 shl 16)+VID_ATI, init_r500 ;ATI Mobility Radeon HD 3870 + dd (0x9509 shl 16)+VID_ATI, init_r500 ;ATI Mobility Radeon HD 3870 X2 + dd (0x950F shl 16)+VID_ATI, init_r500 ;ATI Radeon HD3870 X2 + dd (0x9511 shl 16)+VID_ATI, init_r500 ;ATI FireGL V7700 + dd (0x9515 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 3850 AGP + dd (0x9517 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 3960 + dd (0x9519 shl 16)+VID_ATI, init_r500 ;FireStream 9170 + dd (0x9580 shl 16)+VID_ATI, init_r500 ;RV630 + dd (0x9581 shl 16)+VID_ATI, init_r500 ;Mobility Radeon HD 2600 + dd (0x9583 shl 16)+VID_ATI, init_r500 ;Mobility Radeon HD 2600 XT + dd (0x9586 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 2600 XT AGP + dd (0x9587 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 2600 Pro AGP + dd (0x9588 shl 16)+VID_ATI, init_r500 ;Radeon HD 2600 XT + dd (0x9589 shl 16)+VID_ATI, init_r500 ;Radeon HD 2600 Pro + dd (0x958A shl 16)+VID_ATI, init_r500 ;Gemini RV630 + dd (0x958B shl 16)+VID_ATI, init_r500 ;Gemini ATI Mobility Radeon HD 2600 XT + dd (0x958C shl 16)+VID_ATI, init_r500 ;FireGL V5600 + dd (0x958D shl 16)+VID_ATI, init_r500 ;FireGL V3600 + dd (0x958E shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 2600 LE + dd (0x958F shl 16)+VID_ATI, init_r500 ;ATI Mobility FireGL Graphics Processor + dd (0x9590 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 3600 Series + dd (0x9591 shl 16)+VID_ATI, init_r500 ;Mobility Radeon HD 3650 + dd (0x9593 shl 16)+VID_ATI, init_r500 ;Mobility Radeon HD 3670 + dd (0x9595 shl 16)+VID_ATI, init_r500 ;Mobility FireGL V5700 + dd (0x9596 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 3650 AGP + dd (0x9597 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 3600 Series + dd (0x9598 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 3670 + dd (0x9599 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 3600 Series + dd (0x959B shl 16)+VID_ATI, init_r500 ;Mobility FireGL Graphics Processor + dd (0x95C0 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 3470 + dd (0x95C2 shl 16)+VID_ATI, init_r500 ;ATI Mobility Radeon HD 3430 (M82) + dd (0x95C4 shl 16)+VID_ATI, init_r500 ;Mobility Radeon HD 3400 Series (M82) + dd (0x95C5 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 3450 + dd (0x95C7 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 3430 + dd (0x95CC shl 16)+VID_ATI, init_r500 ;Fire PRO Professional Graphics ASIC + dd (0x95CD shl 16)+VID_ATI, init_r500 ;ATI FireMV 2450 + dd (0x95CE shl 16)+VID_ATI, init_r500 ;ATI FireMV 2260 + dd (0x95CF shl 16)+VID_ATI, init_r500 ;ATI FireMV 2260 + dd (0x9610 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 3200 Graphics + dd (0x9611 shl 16)+VID_ATI, init_r500 ;ATI Radeon 3100 Graphics + dd (0x9612 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 3200 Graphics + dd (0x9613 shl 16)+VID_ATI, init_r500 ;ATI Radeon 3100 Graphics + dd (0x9614 shl 16)+VID_ATI, init_r500 ;ATI Radeon HD 3300 Graphics + dd (0x9440 shl 16)+VID_ATI, init_r500 ;ATI Radeon 4800 Series + dd (0x9441 shl 16)+VID_ATI, init_r500 ;ATI Radeon 4870 X2 + dd (0x9442 shl 16)+VID_ATI, init_r500 ;ATI Radeon 4800 Series + dd (0x9444 shl 16)+VID_ATI, init_r500 ;Everest ATI FirePro Graphics Accelerator + dd (0x9446 shl 16)+VID_ATI, init_r500 ;K2 ATI FirePro Graphics Accelerator + dd (0x944E shl 16)+VID_ATI, init_r500 ;RV770 + dd (0x9456 shl 16)+VID_ATI, init_r500 ;Denali ATI FirePro Graphics dd 0 ;terminator diff --git a/kernel/branches/kolibri_pe/drivers/r500hw.inc b/kernel/branches/kolibri_pe/drivers/r500hw.inc index 32181825bc..a2ce9ac695 100644 --- a/kernel/branches/kolibri_pe/drivers/r500hw.inc +++ b/kernel/branches/kolibri_pe/drivers/r500hw.inc @@ -5,6 +5,10 @@ if 0 The below code is a rework from code in xf86-video-radeonhd/src/r5xx_accel.c, xf86-video-radeonhd/src/r5xx_xaa.c + git://anongit.freedesktop.org/git/nouveau/xf86-video-radeonhd + git://anongit.freedesktop.org/git/xorg/driver/xf86-video-ati + + Copyright 2008 Luc Verhaegen Copyright 2008 Matthias Hopf Copyright 2008 Egbert Eich @@ -662,7 +666,7 @@ proc R5xxSetupForSolidFill stdcall,color:dword, rop:dword, planemask:dword or edx, [rhd.control] or edx, (R5XX_GMC_BRUSH_SOLID_COLOR or R5XX_GMC_SRC_DATATYPE_COLOR) -; Save for later clipping */ +; Save for later clipping mov [rhd.control_saved], edx mov eax, 4 diff --git a/kernel/branches/kolibri_pe/drivers/sb16/README.TXT b/kernel/branches/kolibri_pe/drivers/sb16/README.TXT new file mode 100644 index 0000000000..7f82babacd --- /dev/null +++ b/kernel/branches/kolibri_pe/drivers/sb16/README.TXT @@ -0,0 +1,72 @@ +Nable 21.05.2008. +This driver is my contribution (or donation) to KolibriOS. This is provided +AS IS in hope it'll be useful, but WITHOUT ANY WARRANTY! No responcibility +for any hardware damage or data loss. Use at your own risk! + +;------------------------------------------------------------------------------- +;Changelog: +;------------------------------------------------------------------------------- +v0.2 - DEV_SET(GET)_MASTERVOL functions are unlocked and implemented. + +v0.1 - first release. + +;------------------------------------------------------------------------------- +;Tiny FAQ for sound driver by Nable for SB16 sound card. +;------------------------------------------------------------------------------- + +;What is it?-------------------------------------------------------------------- + As you may know there is a sound subsystem ('INFINITY') in KolibriOS. +This subsystem includes mixer and separate interface for soundplayer +program and driver, so player application don't need to know what soundcard +is installed and how to cope with it, all work with card do the driver. +Before this time there were drivers only for AC97 integrated sound, but I +don't have such at home and if I would upgrade my computer with a newest +hardware, with 100% probability integrated sound will be HD Codec, nowadays +AC97 is not actual (2008 year is at calendar). But I'm not planning to upgrade +my computer so much now (and in next 5-6 years), writing the driver for my PCI +ESS Maestro1 card is difficult for me (may be some time later), so I decided +to write a driver for SB16. At first it is easy, there are many working +examples for DOS, there are heaps of good documentation and as an ISA device +SB16 can be programmed through I/O ports (about 5 ports are used), that is +more easy than PCI access. Now, enough lirics, lets go to physics :-) + If you still don't understand what stuff is it, I'll tell this in brief: +with this driver you can play MP3 and WAV music (using AC97SND player) and +sounds (some games and DOSBOX can produce sound output through sound +subsystem) in KolibriOS. + +;Yeah! I need sound in Kolibri and I have SB16 card. Whats then?---------------- + At first copy my SOUND.OBJ to /sys/drivers at your Kolibri system. Note, +that if you have AC97 card and it's driver started - then new driver won't +run until reboot. Then run BOARD and go to 'user' tab. Then try to run +AC97SND player. At BOARD you will see the following (if you had a proper +card): +|----------------------------| +|detecting hardware... | <- detector startup message +|DSP found at port 220h | <- if you have a proper card, it'll be +|DSP version 4.13 - SB16 | autodetected. Numbers may be different. +|failed to attach IRQ5 | <- don't mention. Old kernels reserve IRQ5 +|owner's handler: 0x80D74284 | see below how to fix it. +|----------------------------| + At first, note that DSP version must be 4.xx or higher. Older cards are not +supported in this first release, maybe some time later. If nothing detected +but PNP/BIOS or some other OS detects your card - I'm sorry, it's perverted +PNP card like OPTi16, that is like HD Codec - until you init it through +PCI->ISA bridge (HD Codec of course through PCI->PCI bridge), map it, etc, +you can't use it in any way. I'd rather write a PCI device driver, than +for this extreme perversion. If your card detected and has a proper version +but you see 'failed to attach IRQ' - delete stroke 'mov [irq_owner+4*5],1' from the +file kernel.asm of your kernel source, save it, rebuild kernel, copy new +kernel to /sys/ (did you rename 'kernel' to 'kernel.mnt'? You should do it), +restart kernel (Ctrl+Alt+F12, Home). THE EASIER WAY IS TO USE A NEWER KERNEL, +since SVN802 it's fixed. +Now everything should be OK. + +;It works for a part of the second and then stops, but system doesn't hang------ +Go to 'config.inc' of my driver and change 'sb_irq_num' value from 5 to 7. +Then save, rebuild driver (compile 'sound.asm'), put 'sound' to /sys/drivers/ +(you need to rename file 'sound' to 'sound.obj'), restart kernel and try again +to produce sound. + +;------------------------------------------------------------------------------- +Ask your questions at KolibriOS forum: board.kolibrios.org +I'll try to answer you if possible. \ No newline at end of file diff --git a/kernel/branches/kolibri_pe/fs/fs_lfn.inc b/kernel/branches/kolibri_pe/fs/fs_lfn.inc index 4929e22578..f302f9d421 100644 --- a/kernel/branches/kolibri_pe/fs/fs_lfn.inc +++ b/kernel/branches/kolibri_pe/fs/fs_lfn.inc @@ -432,11 +432,12 @@ file_system_lfn: push ebx call _sys_exec - mov [image_of_eax], eax add esp, 12 - + mov [image_of_eax], eax ret + + ; handlers for devices ; in: ecx = 0 => query virtual directory /xxx ; in: ecx = partition number diff --git a/kernel/branches/kolibri_pe/include/pe.h b/kernel/branches/kolibri_pe/include/pe.h index ef92290469..7eb136ffcb 100644 --- a/kernel/branches/kolibri_pe/include/pe.h +++ b/kernel/branches/kolibri_pe/include/pe.h @@ -46,6 +46,10 @@ typedef struct _IMAGE_FILE_HEADER WORD Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; +#define IMAGE_FILE_DLL 0x2000 + +#define IMAGE_FILE_MACHINE_I386 0x014c /* Intel 386 or later processors + and compatible processors */ typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; DWORD Size; @@ -192,12 +196,13 @@ extern dll_t core_dll; #define MakePtr( cast, ptr, addValue ) (cast)( (addr_t)(ptr) + (addr_t)(addValue) ) +bool validate_pe(void *raw, size_t raw_size, bool is_exec); dll_t * find_dll(link_t *list, const char *name); md_t* __fastcall load_image(const char *path); -void __export create_image(addr_t img_base, addr_t image) asm ("CreateImage"); +void create_image(addr_t img_base, addr_t raw, bool force_clear) asm ("CreateImage"); diff --git a/kernel/branches/kolibri_pe/kernel.asm b/kernel/branches/kolibri_pe/kernel.asm index 54d20671f4..1f3e6ff1f3 100644 --- a/kernel/branches/kolibri_pe/kernel.asm +++ b/kernel/branches/kolibri_pe/kernel.asm @@ -4314,12 +4314,42 @@ sys_putimage_palette: add dx, word [eax+SLOT_BASE+APPDATA.wnd_clientbox.left] rol edx, 16 .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 +@@: + cmp esi, 4 + jnz @f + push edi + push 0ffffff80h + mov edi, esp + call put_4bit_image + pop eax + pop edi + ret +@@: push ebp esi ebp cmp esi, 8 jnz @f mov ebp, putimage_get8bpp mov esi, putimage_init8bpp jmp sys_putimage_bpp +@@: + cmp esi, 15 + jnz @f + mov ebp, putimage_get15bpp + mov esi, putimage_init15bpp + jmp sys_putimage_bpp @@: cmp esi, 16 jnz @f @@ -4342,15 +4372,28 @@ sys_putimage_palette: pop ebp esi ebp ret +put_mono_image: + push ebp esi ebp + mov ebp, putimage_get1bpp + mov esi, putimage_init1bpp + jmp sys_putimage_bpp +put_4bit_image: + push ebp esi ebp + mov ebp, putimage_get4bpp + mov esi, putimage_init4bpp + jmp sys_putimage_bpp + putimage_init24bpp: lea eax, [eax*3] putimage_init8bpp: ret +align 16 putimage_get24bpp: mov eax, [esi] add esi, 3 ret 4 +align 16 putimage_get8bpp: movzx eax, byte [esi] push edx @@ -4360,17 +4403,79 @@ putimage_get8bpp: inc esi ret 4 +putimage_init1bpp: + add eax, ecx + push ecx + add eax, 7 + add ecx, 7 + shr eax, 3 + shr ecx, 3 + sub eax, ecx + pop ecx + ret +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 + +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 + putimage_init32bpp: shl eax, 2 ret +align 16 putimage_get32bpp: lodsd ret 4 +putimage_init15bpp: putimage_init16bpp: add eax, eax ret -putimage_get16bpp: +align 16 +putimage_get15bpp: ; 0RRRRRGGGGGBBBBB -> 00000000RRRRR000GGGGG000BBBBB000 push ecx edx movzx eax, word [esi] @@ -4386,7 +4491,26 @@ putimage_get16bpp: or eax, ecx or eax, edx pop edx ecx - ret + 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 ; eax x beginning ; ebx y beginning diff --git a/kernel/branches/kolibri_pe/makefile b/kernel/branches/kolibri_pe/makefile index 689253bcaf..a467aebe18 100644 --- a/kernel/branches/kolibri_pe/makefile +++ b/kernel/branches/kolibri_pe/makefile @@ -46,6 +46,7 @@ H_SRC:= \ include/link.h \ include/core.h \ include/mm.h \ + include/pe.h \ include/slab.h PE_OBJS = $(patsubst %.s, bin/%.obj, $(patsubst %.asm, bin/%.obj,\ diff --git a/kernel/branches/kolibri_pe/network/eth_drv/drivers/forcedeth.inc b/kernel/branches/kolibri_pe/network/eth_drv/drivers/forcedeth.inc new file mode 100644 index 0000000000..0578f6440f --- /dev/null +++ b/kernel/branches/kolibri_pe/network/eth_drv/drivers/forcedeth.inc @@ -0,0 +1,2683 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; FORCEDETH.INC ;; +;; ;; +;; Ethernet driver for Kolibri OS ;; +;; ;; +;; Version 0.1 24 June 2008 - 23 Sep 2008 ;; +;; ;; +;; 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 ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision: 867 $ + +;******************************************************************** +; Interface +; forcedeth_reset +; forcedeth_probe +; forcedeth_poll +; forcedeth_transmit +; forcedeth_cable +; +;******************************************************************** + +;************************************************************************** +; forcedeth Register Definitions +;************************************************************************** + +PCI_REG_COMMAND equ 0x04 ; command register + +PCI_COMMAND_IO equ 0x01 ; Enable response in I/O space +PCI_COMMAND_MASTER equ 0x04 ; Enable bus mastering +PCI_LATENCY_TIMER equ 0x0d ; 8 bits + +PCI_VENDOR_ID equ 0x00 ; 16 bit +PCI_REVISION_ID equ 0x08 ; 8 bits + +PCI_BASE_ADDRESS_0 equ 0x10 ; 32 bits +PCI_BASE_ADDRESS_1 equ 0x14 ; 32 bits +PCI_BASE_ADDRESS_2 equ 0x18 ; 32 bits +PCI_BASE_ADDRESS_3 equ 0x1c ; 32 bits +PCI_BASE_ADDRESS_4 equ 0x20 ; 32 bits +PCI_BASE_ADDRESS_5 equ 0x24 ; 32 bits + +PCI_BASE_ADDRESS_SPACE_IO equ 0x01 +PCI_BASE_ADDRESS_IO_MASK equ (not 0x03) +PCI_BASE_ADDRESS_MEM_MASK equ (not 0x0f) + +PCI_BASE_ADDRESS_MEM_TYPE_MASK equ 0x06 +PCI_BASE_ADDRESS_MEM_TYPE_32 equ 0x00 ; 32 bit address +PCI_BASE_ADDRESS_MEM_TYPE_1M equ 0x02 ; Below 1M [obsolete] +PCI_BASE_ADDRESS_MEM_TYPE_64 equ 0x04 ; 64 bit address + +; NIC specific static variables go here +PCI_DEVICE_ID_NVIDIA_NVENET_1 equ 0x01c3 +PCI_DEVICE_ID_NVIDIA_NVENET_2 equ 0x0066 +PCI_DEVICE_ID_NVIDIA_NVENET_4 equ 0x0086 +PCI_DEVICE_ID_NVIDIA_NVENET_5 equ 0x008c +PCI_DEVICE_ID_NVIDIA_NVENET_3 equ 0x00d6 +PCI_DEVICE_ID_NVIDIA_NVENET_7 equ 0x00df +PCI_DEVICE_ID_NVIDIA_NVENET_6 equ 0x00e6 +PCI_DEVICE_ID_NVIDIA_NVENET_8 equ 0x0056 +PCI_DEVICE_ID_NVIDIA_NVENET_9 equ 0x0057 +PCI_DEVICE_ID_NVIDIA_NVENET_10 equ 0x0037 +PCI_DEVICE_ID_NVIDIA_NVENET_11 equ 0x0038 +PCI_DEVICE_ID_NVIDIA_NVENET_12 equ 0x0268 +PCI_DEVICE_ID_NVIDIA_NVENET_13 equ 0x0269 +PCI_DEVICE_ID_NVIDIA_NVENET_14 equ 0x0372 +PCI_DEVICE_ID_NVIDIA_NVENET_15 equ 0x0373 + +ETH_DATA_LEN equ 1500 + +; rx/tx mac addr + type + vlan + align + slack +RX_NIC_BUFSIZE equ (ETH_DATA_LEN + 64) +; even more slack +RX_ALLOC_BUFSIZE equ (ETH_DATA_LEN + 128) + +NvRegIrqStatus equ 0x00 +NvRegIrqMask equ 0x04 +NvRegUnknownSetupReg6 equ 0x08 +NvRegPollingInterval equ 0x0c +NvRegMacReset equ 0x3c +NvRegMisc1 equ 0x80 +NvRegTransmitterControl equ 0x84 +NvRegTransmitterStatus equ 0x88 +NvRegPacketFilterFlags equ 0x8c +NvRegOffloadConfig equ 0x90 +NvRegReceiverControl equ 0x94 +NvRegReceiverStatus equ 0x98 +NvRegRandomSeed equ 0x9c +NvRegUnknownSetupReg1 equ 0xA0 +NvRegUnknownSetupReg2 equ 0xA4 +NvRegMacAddrA equ 0xA8 ; MAC address low +NvRegMacAddrB equ 0xAC ; MAC address high +NvRegMulticastAddrA equ 0xB0 +NvRegMulticastAddrB equ 0xB4 +NvRegMulticastMaskA equ 0xB8 +NvRegMulticastMaskB equ 0xBC +NvRegPhyInterface equ 0xC0 +NvRegTxRingPhysAddr equ 0x100 +NvRegRxRingPhysAddr equ 0x104 +NvRegRingSizes equ 0x108 +NvRegUnknownTransmitterReg equ 0x10c +NvRegLinkSpeed equ 0x110 +NvRegUnknownSetupReg5 equ 0x130 +NvRegUnknownSetupReg3 equ 0x13c +NvRegTxRxControl equ 0x144 +NvRegMIIStatus equ 0x180 +NvRegUnknownSetupReg4 equ 0x184 +NvRegAdapterControl equ 0x188 +NvRegMIISpeed equ 0x18c +NvRegMIIControl equ 0x190 +NvRegMIIData equ 0x194 +NvRegWakeUpFlags equ 0x200 +NvRegPowerState equ 0x26c +NvRegPowerState2 equ 0x600 + +NVREG_UNKSETUP1_VAL equ 0x16070f +NVREG_UNKSETUP2_VAL equ 0x16 +NVREG_UNKSETUP3_VAL1 equ 0x200010 +NVREG_UNKSETUP4_VAL equ 8 +NVREG_UNKSETUP5_BIT31 equ (1 shl 31) +NVREG_UNKSETUP6_VAL equ 3 + +NVREG_TXRXCTL_RXCHECK equ 0x0400 +NVREG_MIISTAT_ERROR equ 0x0001 +NVREG_MIISTAT_MASK equ 0x000f +NVREG_MIISTAT_MASK2 equ 0x000f +NVREG_MIICTL_INUSE equ 0x08000 +NVREG_MIICTL_WRITE equ 0x00400 +NVREG_MIICTL_ADDRSHIFT equ 5 + +NVREG_MIISPEED_BIT8 equ (1 shl 8) +NVREG_MIIDELAY equ 5 + +NVREG_IRQ_RX_ERROR equ 0x0001 +NVREG_IRQ_RX equ 0x0002 +NVREG_IRQ_RX_NOBUF equ 0x0004 +NVREG_IRQ_LINK equ 0x0040 +NVREG_IRQ_TIMER equ 0x0020 +NVREG_IRQMASK_WANTED_2 equ 0x0147 + +NVREG_IRQ_RX_ALL equ (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF) +NVREG_IRQ_TX_ALL equ 0 ; ??????????? +NVREG_IRQ_OTHER_ALL equ (NVREG_IRQ_LINK or NVREG_IRQ_TIMER) + +NVREG_IRQSTAT_MASK equ 0x1ff + +NVREG_TXRXCTL_KICK equ 0x0001 +NVREG_TXRXCTL_BIT1 equ 0x0002 +NVREG_TXRXCTL_BIT2 equ 0x0004 +NVREG_TXRXCTL_IDLE equ 0x0008 +NVREG_TXRXCTL_RESET equ 0x0010 +NVREG_TXRXCTL_RXCHECK equ 0x0400 + +NVREG_MCASTADDRA_FORCE equ 0x01 + +NVREG_MAC_RESET_ASSERT equ 0x0F3 + +NVREG_MISC1_HD equ 0x02 +NVREG_MISC1_FORCE equ 0x3b0f3c + +NVREG_PFF_ALWAYS equ 0x7F0008 +NVREG_PFF_PROMISC equ 0x80 +NVREG_PFF_MYADDR equ 0x20 + +NVREG_OFFLOAD_HOMEPHY equ 0x601 +NVREG_OFFLOAD_NORMAL equ RX_NIC_BUFSIZE + +NVREG_RNDSEED_MASK equ 0x00ff +NVREG_RNDSEED_FORCE equ 0x7f00 +NVREG_RNDSEED_FORCE2 equ 0x2d00 +NVREG_RNDSEED_FORCE3 equ 0x7400 + +; NVREG_POLL_DEFAULT is the interval length of the timer source on the nic +; NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms +NVREG_POLL_DEFAULT equ 970 + +NVREG_ADAPTCTL_START equ 0x02 +NVREG_ADAPTCTL_LINKUP equ 0x04 +NVREG_ADAPTCTL_PHYVALID equ 0x40000 +NVREG_ADAPTCTL_RUNNING equ 0x100000 +NVREG_ADAPTCTL_PHYSHIFT equ 24 + +NVREG_WAKEUPFLAGS_VAL equ 0x7770 + +NVREG_POWERSTATE_POWEREDUP equ 0x8000 +NVREG_POWERSTATE_VALID equ 0x0100 +NVREG_POWERSTATE_MASK equ 0x0003 +NVREG_POWERSTATE_D0 equ 0x0000 +NVREG_POWERSTATE_D1 equ 0x0001 +NVREG_POWERSTATE_D2 equ 0x0002 +NVREG_POWERSTATE_D3 equ 0x0003 + +NVREG_POWERSTATE2_POWERUP_MASK equ 0x0F11 +NVREG_POWERSTATE2_POWERUP_REV_A3 equ 0x0001 + +NVREG_RCVCTL_START equ 0x01 +NVREG_RCVSTAT_BUSY equ 0x01 + +NVREG_XMITCTL_START equ 0x01 + +NVREG_LINKSPEED_FORCE equ 0x10000 +NVREG_LINKSPEED_10 equ 1000 +NVREG_LINKSPEED_100 equ 100 +NVREG_LINKSPEED_1000 equ 50 + +NVREG_RINGSZ_TXSHIFT equ 0 +NVREG_RINGSZ_RXSHIFT equ 16 + +LPA_1000FULL equ 0x0800 + +; Link partner ability register. +LPA_SLCT equ 0x001f ; Same as advertise selector +LPA_10HALF equ 0x0020 ; Can do 10mbps half-duplex +LPA_10FULL equ 0x0040 ; Can do 10mbps full-duplex +LPA_100HALF equ 0x0080 ; Can do 100mbps half-duplex +LPA_100FULL equ 0x0100 ; Can do 100mbps full-duplex +LPA_100BASE4 equ 0x0200 ; Can do 100mbps 4k packets +LPA_RESV equ 0x1c00 ; Unused... +LPA_RFAULT equ 0x2000 ; Link partner faulted +LPA_LPACK equ 0x4000 ; Link partner acked us +LPA_NPAGE equ 0x8000 ; Next page bit + +MII_READ equ (-1) +MII_PHYSID1 equ 0x02 ; PHYS ID 1 +MII_PHYSID2 equ 0x03 ; PHYS ID 2 +MII_BMCR equ 0x00 ; Basic mode control register +MII_BMSR equ 0x01 ; Basic mode status register +MII_ADVERTISE equ 0x04 ; Advertisement control reg +MII_LPA equ 0x05 ; Link partner ability reg +MII_SREVISION equ 0x16 ; Silicon revision +MII_RESV1 equ 0x17 ; Reserved... +MII_NCONFIG equ 0x1c ; Network interface config + +; PHY defines +PHY_OUI_MARVELL equ 0x5043 +PHY_OUI_CICADA equ 0x03f1 +PHYID1_OUI_MASK equ 0x03ff +PHYID1_OUI_SHFT equ 6 +PHYID2_OUI_MASK equ 0xfc00 +PHYID2_OUI_SHFT equ 10 +PHY_INIT1 equ 0x0f000 +PHY_INIT2 equ 0x0e00 +PHY_INIT3 equ 0x01000 +PHY_INIT4 equ 0x0200 +PHY_INIT5 equ 0x0004 +PHY_INIT6 equ 0x02000 +PHY_GIGABIT equ 0x0100 + +PHY_TIMEOUT equ 0x1 +PHY_ERROR equ 0x2 + +PHY_100 equ 0x1 +PHY_1000 equ 0x2 +PHY_HALF equ 0x100 + +PHY_RGMII equ 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 NvRegTxRxControl. +DESC_VER_1 equ 0x0 +DESC_VER_2 equ (0x02100 or NVREG_TXRXCTL_RXCHECK) + +MAC_ADDR_LEN equ 6 + +NV_TX_LASTPACKET equ (1 shl 16) +NV_TX_RETRYERROR equ (1 shl 19) +NV_TX_LASTPACKET1 equ (1 shl 24) +NV_TX_DEFERRED equ (1 shl 26) +NV_TX_CARRIERLOST equ (1 shl 27) +NV_TX_LATECOLLISION equ (1 shl 28) +NV_TX_UNDERFLOW equ (1 shl 29) +NV_TX_ERROR equ (1 shl 30) +NV_TX_VALID equ (1 shl 31) + +NV_TX2_LASTPACKET equ (1 shl 29) +NV_TX2_RETRYERROR equ (1 shl 18) +NV_TX2_LASTPACKET1 equ (1 shl 23) +NV_TX2_DEFERRED equ (1 shl 25) +NV_TX2_CARRIERLOST equ (1 shl 26) +NV_TX2_LATECOLLISION equ (1 shl 27) +NV_TX2_UNDERFLOW equ (1 shl 28) +; error and valid are the same for both +NV_TX2_ERROR equ (1 shl 30) +NV_TX2_VALID equ (1 shl 31) + +NV_RX_DESCRIPTORVALID equ (1 shl 16) +NV_RX_AVAIL equ (1 shl 31) + +NV_RX2_DESCRIPTORVALID equ (1 shl 29) + +RX_RING equ 4 +TX_RING equ 2 + +FLAG_MASK_V1 equ 0xffff0000 +FLAG_MASK_V2 equ 0xffffc000 +LEN_MASK_V1 equ (0xffffffff xor FLAG_MASK_V1) +LEN_MASK_V2 equ (0xffffffff xor FLAG_MASK_V2) + +; Miscelaneous hardware related defines: +NV_PCI_REGSZ_VER1 equ 0x270 +NV_PCI_REGSZ_VER2 equ 0x604 +; various timeout delays: all in usec +NV_TXRX_RESET_DELAY equ 4 +NV_TXSTOP_DELAY1 equ 10 +NV_TXSTOP_DELAY1MAX equ 500000 +NV_TXSTOP_DELAY2 equ 100 +NV_RXSTOP_DELAY1 equ 10 +NV_RXSTOP_DELAY1MAX equ 500000 +NV_RXSTOP_DELAY2 equ 100 +NV_SETUP5_DELAY equ 5 +NV_SETUP5_DELAYMAX equ 50000 +NV_POWERUP_DELAY equ 5 +NV_POWERUP_DELAYMAX equ 5000 +NV_MIIBUSY_DELAY equ 50 +NV_MIIPHY_DELAY equ 10 +NV_MIIPHY_DELAYMAX equ 10000 +NV_MAC_RESET_DELAY equ 64 +NV_WAKEUPPATTERNS equ 5 +NV_WAKEUPMASKENTRIES equ 4 + +; Advertisement control register. +ADVERTISE_SLCT equ 0x001f ; Selector bits +ADVERTISE_CSMA equ 0x0001 ; Only selector supported +ADVERTISE_10HALF equ 0x0020 ; Try for 10mbps half-duplex +ADVERTISE_10FULL equ 0x0040 ; Try for 10mbps full-duplex +ADVERTISE_100HALF equ 0x0080 ; Try for 100mbps half-duplex +ADVERTISE_100FULL equ 0x0100 ; Try for 100mbps full-duplex +ADVERTISE_100BASE4 equ 0x0200 ; Try for 100mbps 4k packets +ADVERTISE_RESV equ 0x1c00 ; Unused... +ADVERTISE_RFAULT equ 0x2000 ; Say we can detect faults +ADVERTISE_LPACK equ 0x4000 ; Ack link partners response +ADVERTISE_NPAGE equ 0x8000 ; Next page bit + +ADVERTISE_FULL equ (ADVERTISE_100FULL or ADVERTISE_10FULL or ADVERTISE_CSMA) +ADVERTISE_ALL equ (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL) + +MII_1000BT_CR equ 0x09 +MII_1000BT_SR equ 0x0a +ADVERTISE_1000FULL equ 0x0200 +ADVERTISE_1000HALF equ 0x0100 + +BMCR_ANRESTART equ 0x0200 ; Auto negotiation restart +BMCR_ANENABLE equ 0x1000 ; Enable auto negotiation +BMCR_SPEED100 equ 0x2000 ; Select 100Mbps +BMCR_LOOPBACK equ 0x4000 ; TXD loopback bits +BMCR_RESET equ 0x8000 ; Reset the DP83840 + +; Basic mode status register. +BMSR_ERCAP equ 0x0001 ; Ext-reg capability +BMSR_JCD equ 0x0002 ; Jabber detected +BMSR_LSTATUS equ 0x0004 ; Link status +BMSR_ANEGCAPABLE equ 0x0008 ; Able to do auto-negotiation +BMSR_RFAULT equ 0x0010 ; Remote fault detected +BMSR_ANEGCOMPLETE equ 0x0020 ; Auto-negotiation complete +BMSR_RESV equ 0x07c0 ; Unused... +BMSR_10HALF equ 0x0800 ; Can do 10mbps, half-duplex +BMSR_10FULL equ 0x1000 ; Can do 10mbps, full-duplex +BMSR_100HALF equ 0x2000 ; Can do 100mbps, half-duplex +BMSR_100FULL equ 0x4000 ; Can do 100mbps, full-duplex +BMSR_100BASE4 equ 0x8000 ; Can do 100mbps, 4k packets + +ETH_ALEN equ 6 +ETH_HLEN equ (2 * ETH_ALEN + 2) +ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for + ; mininmum 64bytes frame length + +uglobal +forcedeth_mmio_addr dd 0 ; memory map physical address +forcedeth_mmio_size dd 0 ; size of memory bar +forcedeth_vendor_id dw 0 ; Vendor ID +forcedeth_device_id dw 0 ; Device ID +forcedeth_orig_mac0 dd 0 ; MAC +forcedeth_orig_mac1 dd 0 ; MAC +forcedeth_mapio_addr dd 0 ; mapped IO address +forcedeth_txflags dd 0 ; +forcedeth_desc_ver dd 0 ; +forcedeth_irqmask dd 0 ; IRQ-mask +forcedeth_wolenabled dd 0 ; WOL +forcedeth_in_shutdown dd 0 ; +forcedeth_cur_rx dd 0 ; +forcedeth_refill_rx dd 0 ; +forcedeth_phyaddr dd 0 ; +forcedeth_phy_oui dd 0 ; +forcedeth_gigabit dd 0 ; +forcedeth_needs_mac_reset dd 0 ; +forcedeth_linkspeed dd 0 ; +forcedeth_duplex dd 0 ; +forcedeth_next_tx dd 0 ; next TX descriptor number +forcedeth_nic_tx dd 0 ; ??? d'nt used ??? +forcedeth_packetlen dd 0 ; +forcedeth_nocable dd 0 ; no cable present +endg + +struc forcedeth_TxDesc { + .PacketBuffer dd ? + .FlagLen dd ? +} +virtual at 0 + forcedeth_TxDesc forcedeth_TxDesc + sizeof.forcedeth_TxDesc = $ - forcedeth_TxDesc +end virtual + +struc forcedeth_RxDesc { + .PacketBuffer dd ? + .FlagLen dd ? +} +virtual at 0 + forcedeth_RxDesc forcedeth_RxDesc + sizeof.forcedeth_RxDesc = $ - forcedeth_RxDesc +end virtual + +virtual at eth_data_start + ; Define the TX Descriptor + align 256 + forcedeth_tx_ring rb TX_RING * sizeof.forcedeth_TxDesc + ; Create a static buffer of size RX_BUF_SZ for each + ; TX Descriptor. All descriptors point to a + ; part of this buffer + align 256 + forcedeth_txb rb TX_RING * RX_NIC_BUFSIZE + + ; Define the RX Descriptor + align 256 + forcedeth_rx_ring rb RX_RING * sizeof.forcedeth_RxDesc + ; Create a static buffer of size RX_BUF_SZ for each + ; RX Descriptor. All descriptors point to a + ; part of this buffer + align 256 + forcedeth_rxb rb RX_RING * RX_NIC_BUFSIZE +end virtual + + +;*************************************************************************** +; Function +; forcedeth_reset +; Description +; Place the chip (ie, the ethernet card) into a virgin state +; No inputs +; All registers destroyed +; +;*************************************************************************** +forcedeth_reset: + + ; 1) erase previous misconfiguration + ; 4.1-1: stop adapter: ignored, 4.3 seems to be overkill + + ; writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA) + mov edi, dword [forcedeth_mapio_addr] + mov dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE + + ; writel(0, base + NvRegMulticastAddrB) + mov dword [edi+NvRegMulticastAddrB], 0 + + ; writel(0, base + NvRegMulticastMaskA) + mov dword [edi+NvRegMulticastMaskA], 0 + + ; writel(0, base + NvRegMulticastMaskB) + mov dword [edi+NvRegMulticastMaskB], 0 + + ; writel(0, base + NvRegPacketFilterFlags) + mov dword [edi+NvRegPacketFilterFlags], 0 + + ; writel(0, base + NvRegTransmitterControl) + mov dword [edi+NvRegTransmitterControl], 0 + + ; writel(0, base + NvRegReceiverControl) + mov dword [edi+NvRegReceiverControl], 0 + + ; writel(0, base + NvRegAdapterControl) + mov dword [edi+NvRegAdapterControl], 0 + + + ; 2) initialize descriptor rings + ; init_ring(nic) + call forcedeth_init_ring + + ; writel(0, base + NvRegLinkSpeed) + mov dword [edi+NvRegLinkSpeed], 0 + + ; writel(0, base + NvRegUnknownTransmitterReg) + mov dword [edi+NvRegUnknownTransmitterReg], 0 + + ; txrx_reset(nic) + call forcedeth_txrx_reset + + ; writel(0, base + NvRegUnknownSetupReg6) + mov dword [edi+NvRegUnknownSetupReg6], 0 + + ; np->in_shutdown = 0 + mov dword [forcedeth_in_shutdown], 0 + + + ; 3) set mac address + ; writel(mac[0], base + NvRegMacAddrA) + mov eax, dword [forcedeth_orig_mac0] + mov dword [edi+NvRegMacAddrA], eax + + ; writel(mac[1], base + NvRegMacAddrB) + mov eax, dword [forcedeth_orig_mac1] + mov dword [edi+NvRegMacAddrB], eax + + + ; 4) give hw rings + ; writel((u32) virt_to_le32desc(&rx_ring[0]), base + NvRegRxRingPhysAddr) + mov eax, forcedeth_rx_ring + +;DEBUGF 1," K : FORCEDETH: rx_ring at 0x%x\n", eax + + sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov dword [edi+NvRegRxRingPhysAddr], eax + + ; writel((u32) virt_to_le32desc(&tx_ring[0]), base + NvRegTxRingPhysAddr) + mov eax, forcedeth_tx_ring + sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov dword [edi+NvRegTxRingPhysAddr], eax + + ; writel(((RX_RING - 1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING - 1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes) + mov dword [edi+NvRegRingSizes], (((RX_RING - 1) shl NVREG_RINGSZ_RXSHIFT) + ((TX_RING - 1) shl NVREG_RINGSZ_TXSHIFT)) + + ; 5) continue setup + ; np->linkspeed = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 + mov dword [forcedeth_linkspeed], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) + + ; np->duplex = 0 + mov dword [forcedeth_duplex], 0 + + ; writel(np->linkspeed, base + NvRegLinkSpeed) + mov dword [edi+NvRegLinkSpeed], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) + + ; writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3) + mov dword [edi+NvRegUnknownSetupReg3], NVREG_UNKSETUP3_VAL1 + + ; writel(np->desc_ver, base + NvRegTxRxControl) + mov eax, dword [forcedeth_desc_ver] + mov dword [edi+NvRegTxRxControl], eax + + ; pci_push(base) + call forcedeth_pci_push + + ; writel(NVREG_TXRXCTL_BIT1 | np->desc_ver, base + NvRegTxRxControl) + or eax, NVREG_TXRXCTL_BIT1 + mov dword [edi+NvRegTxRxControl], eax + + ; reg_delay(NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, "open: SetupReg5, Bit 31 remained off\n") + push ebx edx edi ;;;;;;;;;;;;;;;;;;;;;; + stdcall forcedeth_reg_delay,NvRegUnknownSetupReg5,NVREG_UNKSETUP5_BIT31,NVREG_UNKSETUP5_BIT31,NV_SETUP5_DELAY,NV_SETUP5_DELAYMAX,0 + pop edi edx ebx ;;;;;;;;;;;;;;;;;;;;;; + + ; writel(0, base + NvRegUnknownSetupReg4) + mov dword [edi+NvRegUnknownSetupReg4], 0 + + ; writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus) + mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK2 + + + ; printf("%d-Mbs Link, %s-Duplex\n", np->linkspeed & NVREG_LINKSPEED_10 ? 10 : 100, np->duplex ? "Full" : "Half") +;;;;;;;;;;; DEBUGF + + ; 6) continue setup + + ; writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1) + mov dword [edi+NvRegMisc1], (NVREG_MISC1_FORCE or NVREG_MISC1_HD) + + ; writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus) + mov eax, dword [edi+NvRegTransmitterStatus] + mov dword [edi+NvRegTransmitterStatus], eax + + ; writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags) + mov dword [edi+NvRegPacketFilterFlags], NVREG_PFF_ALWAYS + + ; writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig) + mov dword [edi+NvRegOffloadConfig], NVREG_OFFLOAD_NORMAL + + ; writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus) + mov eax, dword [edi+NvRegReceiverStatus] + mov dword [edi+NvRegReceiverStatus], eax + + ; Get a random number + ; i = random() + push edi + stdcall sys_clock ; eax = 0x00SSMMHH (current system time) + pop edi + + ; writel(NVREG_RNDSEED_FORCE | (i & NVREG_RNDSEED_MASK), base + NvRegRandomSeed) + and eax, NVREG_RNDSEED_MASK + or eax, NVREG_RNDSEED_FORCE + mov dword [edi+NvRegRandomSeed], eax + + ; writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1) + mov dword [edi+NvRegUnknownSetupReg1], NVREG_UNKSETUP1_VAL + + ; writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2) + mov dword [edi+NvRegUnknownSetupReg2], NVREG_UNKSETUP2_VAL + + ; writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval) + mov dword [edi+NvRegPollingInterval], NVREG_POLL_DEFAULT + + ; writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6) + mov dword [edi+NvRegUnknownSetupReg6], NVREG_UNKSETUP6_VAL + + ; writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT) | NVREG_ADAPTCTL_PHYVALID | NVREG_ADAPTCTL_RUNNING, + ; base + NvRegAdapterControl) + mov eax, dword [forcedeth_phyaddr] + shl eax, NVREG_ADAPTCTL_PHYSHIFT + or eax, (NVREG_ADAPTCTL_PHYVALID or NVREG_ADAPTCTL_RUNNING) + mov dword [edi+NvRegAdapterControl], eax + + ; writel(NVREG_MIISPEED_BIT8 | NVREG_MIIDELAY, base + NvRegMIISpeed) + mov dword [edi+NvRegMIISpeed], (NVREG_MIISPEED_BIT8 or NVREG_MIIDELAY) + + ; writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4) + mov dword [edi+NvRegUnknownSetupReg4], NVREG_UNKSETUP4_VAL + + ; writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags) + mov dword [edi+NvRegWakeUpFlags], NVREG_WAKEUPFLAGS_VAL + + ; i = readl(base + NvRegPowerState) + mov eax, dword [edi+NvRegPowerState] + + ; if ((i & NVREG_POWERSTATE_POWEREDUP) == 0) + test eax, NVREG_POWERSTATE_POWEREDUP + jnz @f + ; writel(NVREG_POWERSTATE_POWEREDUP | i, base + NvRegPowerState) + or eax, NVREG_POWERSTATE_POWEREDUP + mov dword [edi+NvRegPowerState], eax + +@@: + + ; pci_push(base) + call forcedeth_pci_push + + ; nv_udelay(10) + mov esi, 10 + call forcedeth_nv_udelay + + ; writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState) + mov eax, dword [edi+NvRegPowerState] + or eax, NVREG_POWERSTATE_VALID + mov dword [edi+NvRegPowerState], eax + + ; ??? disable all interrupts ??? + ; writel(0, base + NvRegIrqMask) + mov dword [edi+NvRegIrqMask], 0 + +;;; ; ??? Mask RX interrupts +;;; mov dword [edi+NvRegIrqMask], NVREG_IRQ_RX_ALL +;;; ; ??? Mask TX interrupts +;;; ;mov dword [edi+NvRegIrqMask], NVREG_IRQ_TX_ALL +;;; ; ??? Mask OTHER interrupts +;;; mov dword [edi+NvRegIrqMask], NVREG_IRQ_OTHER_ALL + + ; pci_push(base) + call forcedeth_pci_push + + ; writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus) + mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK2 + + ; writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus) + mov dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK + + ; pci_push(base) + call forcedeth_pci_push + + + ; writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA) + mov dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE + + ; writel(0, base + NvRegMulticastAddrB) + mov dword [edi+NvRegMulticastAddrB], 0 + + ; writel(0, base + NvRegMulticastMaskA) + mov dword [edi+NvRegMulticastMaskA], 0 + + ; writel(0, base + NvRegMulticastMaskB) + mov dword [edi+NvRegMulticastMaskB], 0 + + ; writel(NVREG_PFF_ALWAYS | NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags) + mov dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_ALWAYS or NVREG_PFF_MYADDR) + + ; set_multicast(nic) + call forcedeth_set_multicast + + ; One manual link speed update: Interrupts are enabled, future link + ; speed changes cause interrupts and are handled by nv_link_irq(). + + ; miistat = readl(base + NvRegMIIStatus) + mov eax, dword [edi+NvRegMIIStatus] + + ; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); + mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK + + ; dprintf(("startup: got 0x%hX.\n", miistat)); +;;; DEBUGF 1," K : FORCEDETH: startup: got 0x%x\n", eax + + + ; ret = update_linkspeed(nic) + call forcedeth_update_linkspeed + push eax + + ; start_tx(nic) + call forcedeth_start_tx + + pop eax + +; if (ret) { +; //Start Connection netif_carrier_on(dev); +; } else { +; printf("no link during initialization.\n"); +; } + + ;*** added by shurf (21.09.2008) + mov dword [forcedeth_nocable], 0 + ;*** + + test eax, eax + jnz .return + DEBUGF 1," K : FORCEDETH: no link during initialization.\n" + + ;*** added by shurf (21.09.2008) + mov dword [forcedeth_nocable], 1 + ;*** + +.return: + +; Indicate that we have successfully reset the card + mov eax, dword [pci_data] + mov dword [eth_status], eax + ret + + + +;*************************************************************************** +; Function +; forcedeth_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 +; +;*************************************************************************** +forcedeth_probe: + +; DEBUGF 1," K : FORCEDETH: 0x%x 0x%x, 0x%x\n", [io_addr]:8,[pci_bus]:2,[pci_dev]:2 + + mov dword [forcedeth_needs_mac_reset], 0 + +; BEGIN of adjust_pci_device() + ; read word from PCI-device + mov al, 1 ;;;;;;;;;;;;;;2 + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_REG_COMMAND + call pci_read_reg + mov bx, ax ; new command + or bx, PCI_COMMAND_MASTER + or bx, PCI_COMMAND_IO + cmp bx, ax + je @f + ; Enabling PCI-device (make card as bus master) + DEBUGF 1," K : FORCEDETH: Updating PCI command 0x%x->0x%x\n", ax, bx + mov cx, bx + mov al, 1 ;;;;;;;;;;;;2 + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_REG_COMMAND + call pci_write_reg + + ; Check latency settings +@@: + ; Get current latency settings from Latency timer register (byte) + mov al, 0 ;;;;;;;;;1 + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_LATENCY_TIMER + call pci_read_reg + + ; see if its at least 32 + cmp al, 32 + jge @f + ; set latency to 32 + DEBUGF 1, "K : FORCEDETH: PCI latency timer (CFLT) is unreasonably low at %d.\n", al + DEBUGF 1, "K : FORCEDETH: Setting to 32 clocks.\n" + mov cl, 32 + mov al, 0 ;;;;;;;1 + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_LATENCY_TIMER + call pci_write_reg +; END of adjust_pci_device() + +@@: +; BEGIN of pci_bar_start (addr = pci_bar_start(pci, PCI_BASE_ADDRESS_0)) + mov al, 2 ; dword + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_BASE_ADDRESS_0 + call pci_read_reg + test eax, PCI_BASE_ADDRESS_SPACE_IO + jz @f + and eax, PCI_BASE_ADDRESS_IO_MASK + jmp .next +@@: push eax + and eax, PCI_BASE_ADDRESS_MEM_TYPE_MASK + cmp eax, PCI_BASE_ADDRESS_MEM_TYPE_64 + jne .not64 + mov al, 2 ; dword + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_BASE_ADDRESS_0 + 4 + call pci_read_reg + or eax, eax + jz .not64 + DEBUGF 1,"K : FORCEDETH: pci_bar_start: Unhandled 64bit BAR\n" + or eax, -1 + jmp .next +.not64: + pop eax + and eax, PCI_BASE_ADDRESS_MEM_MASK +.next: +; END of pci_bar_start +; addr = eax + mov dword [forcedeth_mmio_addr], eax + + +; BEGIN of pci_bar_size (sz = pci_bar_size(pci, PCI_BASE_ADDRESS_0)) + + ; Save original bar + mov al, 2 ; dword + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_BASE_ADDRESS_0 + call pci_read_reg + mov dword [forcedeth_tmp_start], eax + ; Compute which bits can be set + ; (ecx - value to write) + mov al, 2 ; dword + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_BASE_ADDRESS_0 + mov ecx, (not 0) + call pci_write_reg + mov al, 2 ; dword + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_BASE_ADDRESS_0 + call pci_read_reg + push eax + ; Restore the original size + mov al, 2 ; dword + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_BASE_ADDRESS_0 + mov ecx, dword [forcedeth_tmp_start] + call pci_write_reg + ; Find the significant bits + pop eax + test dword [forcedeth_tmp_start], PCI_BASE_ADDRESS_SPACE_IO + jz @f + and eax, PCI_BASE_ADDRESS_IO_MASK + jmp .next2 +@@: and eax, PCI_BASE_ADDRESS_MEM_MASK +.next2: + ; Find the lowest bit set + mov ecx, eax + sub eax, 1 + not eax + and ecx, eax + +; END of pci_bar_start + mov dword [forcedeth_mmio_size], ecx + + DEBUGF 1," K : FORCEDETH: mmio_addr= 0x%x [mmio_size= 0x%x]\n", [forcedeth_mmio_addr]:8, [forcedeth_mmio_size]:8 + + ; Get Vendor and Device ID + mov al, 2 + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_VENDOR_ID + call pci_read_reg + mov word [forcedeth_vendor_id], ax + shr eax, 16 + mov word [forcedeth_device_id], ax + + DEBUGF 1," K : FORCEDETH: vendor_id= 0x%x device_id= 0x%x\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4 + + ; handle different descriptor versions + mov eax, dword [forcedeth_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 dword [forcedeth_desc_ver], DESC_VER_2 + jmp @f +.ver1: mov dword [forcedeth_desc_ver], DESC_VER_1 +@@: + ; read the mac address + ; map memory + stdcall map_io_mem, [forcedeth_mmio_addr], [forcedeth_mmio_size], (PG_SW+PG_NOCACHE) + test eax, eax + jz .fail + + mov dword [forcedeth_mapio_addr], eax + mov edi, eax + mov eax, dword [edi+NvRegMacAddrA] + mov dword [forcedeth_orig_mac0], eax + mov eax, dword [edi+NvRegMacAddrB] + mov dword [forcedeth_orig_mac1], eax + + ; save MAC-address to global variable node_addr + mov ecx, MAC_ADDR_LEN + xor ebx, ebx + mov edx, forcedeth_orig_mac0 + add edx, (MAC_ADDR_LEN-1) +@@: mov al, byte [edx] + mov byte [node_addr+ebx], al + inc ebx + dec edx + loop @b + +; DEBUGF 1," K : FORCEDETH: orig_mac0= 0x%x\n", [forcedeth_orig_mac0]:8 +; DEBUGF 1," K : FORCEDETH: orig_mac1= 0x%x\n", [forcedeth_orig_mac1]:8 + DEBUGF 1," K : FORCEDETH: MAC = %x-%x-%x-%x-%x-%x\n", [node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2, + + ; disable WOL + mov edi, dword [forcedeth_mapio_addr] + mov dword [edi+NvRegWakeUpFlags], 0 + mov dword [forcedeth_wolenabled], 0 + + mov dword [forcedeth_txflags], (NV_TX2_LASTPACKET or NV_TX2_VALID) + cmp dword [forcedeth_desc_ver], DESC_VER_1 + jne @f + mov dword [forcedeth_txflags], (NV_TX_LASTPACKET or NV_TX_VALID) +@@: + +; BEGIN of switch (pci->dev_id) + + cmp word [forcedeth_device_id], 0x01C3 + jne .next_0x0066 + ; nforce + mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) + jmp .end_switch + +.next_0x0066: + cmp word [forcedeth_device_id], 0x0066 + je @f + cmp word [forcedeth_device_id], 0x00D6 + je @f + jmp .next_0x0086 +@@: + mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) + cmp dword [forcedeth_desc_ver], DESC_VER_1 + jne @f + or dword [forcedeth_txflags], NV_TX_LASTPACKET1 + jmp .end_switch +@@: or dword [forcedeth_txflags], NV_TX2_LASTPACKET1 + jmp .end_switch + +.next_0x0086: + cmp word [forcedeth_device_id], 0x0086 + je @f + cmp word [forcedeth_device_id], 0x008c + je @f + cmp word [forcedeth_device_id], 0x00e6 + je @f + cmp word [forcedeth_device_id], 0x00df + je @f + cmp word [forcedeth_device_id], 0x0056 + je @f + cmp word [forcedeth_device_id], 0x0057 + je @f + cmp word [forcedeth_device_id], 0x0037 + je @f + cmp word [forcedeth_device_id], 0x0038 + je @f + jmp .next_0x0268 +@@: + ; np->irqmask = NVREG_IRQMASK_WANTED_2; + ; np->irqmask |= NVREG_IRQ_TIMER; + mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) + + ; if (np->desc_ver == DESC_VER_1) + cmp dword [forcedeth_desc_ver], DESC_VER_1 + jne @f + ; np->tx_flags |= NV_TX_LASTPACKET1; + or dword [forcedeth_txflags], NV_TX_LASTPACKET1 + jmp .end_switch + ; else +@@: + ; np->tx_flags |= NV_TX2_LASTPACKET1; + or dword [forcedeth_txflags], NV_TX2_LASTPACKET1 + + ; break; + jmp .end_switch + +.next_0x0268: + cmp word [forcedeth_device_id], 0x0268 + je @f + cmp word [forcedeth_device_id], 0x0269 + je @f + cmp word [forcedeth_device_id], 0x0372 + je @f + cmp word [forcedeth_device_id], 0x0373 + je @f + jmp .default_switch +@@: + ; pci_read_config_byte(pci, PCI_REVISION_ID, &revision_id); + mov al, 0 ; byte + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_REVISION_ID + call pci_read_reg + mov ecx, eax ; cl = revision_id + + ; take phy and nic out of low power mode + ; powerstate = readl(base + NvRegPowerState2); + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [edi+NvRegPowerState2] ; eax = powerstate + + ; powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK; + and eax, not NVREG_POWERSTATE2_POWERUP_MASK + + ; if ((pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_12||pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_13)&&revision_id>=0xA3) + cmp dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_12 + je @f + cmp dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_13 + je @f + jmp .end_if +@@: + cmp cl, 0xA3 + jl .end_if + ; powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3; + or eax, NVREG_POWERSTATE2_POWERUP_REV_A3 + +.end_if: + + ; writel(powerstate, base + NvRegPowerState2); + mov dword [edi+NvRegPowerState2], eax + + ; //DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ + ; np->irqmask = NVREG_IRQMASK_WANTED_2; + ; np->irqmask |= NVREG_IRQ_TIMER; + mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) + + ; needs_mac_reset = 1; + mov dword [forcedeth_needs_mac_reset], 1 + + ; if (np->desc_ver == DESC_VER_1) + cmp dword [forcedeth_desc_ver], DESC_VER_1 + jne @f + ; np->tx_flags |= NV_TX_LASTPACKET1; + or dword [forcedeth_txflags], NV_TX_LASTPACKET1 + jmp .end_if2 +@@: + ; else + ; np->tx_flags |= NV_TX2_LASTPACKET1; + or dword [forcedeth_txflags], NV_TX2_LASTPACKET1 + +.end_if2: + ; break; + jmp .end_switch + +.default_switch: + DEBUGF 1," K : FORCEDETH: Your card was undefined in this driver.\n" + DEBUGF 1," K : FORCEDETH: Review driver_data in Kolibri driver and send a patch\n" + +.end_switch: + +; END of switch (pci->dev_id) + + + ; Find a suitable phy + mov dword [forcedeth_tmp_i], 1 +.for_loop: + ; for (i = 1; i <= 32; i++) + ; phyaddr = i & 0x1f + mov ebx, dword [forcedeth_tmp_i] + and ebx, 0x1f + + ; id1 = mii_rw(phyaddr, MII_PHYSID1, MII_READ) + ;EBX - addr, EAX - miireg, ECX - value + mov eax, MII_PHYSID1 + mov ecx, MII_READ + call forcedeth_mii_rw ; id1 = eax + + ; if (id1 < 0 || id1 == 0xffff) + cmp eax, 0xffffffff + je .continue_for + test eax, 0x80000000 + jnz .continue_for + mov dword [forcedeth_tmp_id1], eax + + ; id2 = mii_rw(nic, phyaddr, MII_PHYSID2, MII_READ) + mov eax, MII_PHYSID2 + mov ecx, MII_READ + call forcedeth_mii_rw ; id2 = eax + + ; if (id2 < 0 || id2 == 0xffff) + cmp eax, 0xffffffff + je .continue_for + test eax, 0x80000000 + jnz .continue_for + mov dword [forcedeth_tmp_id2], eax + + jmp .break_for +.continue_for: + inc dword [forcedeth_tmp_i] + cmp dword [forcedeth_tmp_i], 32 + jle .for_loop + jmp .end_for + +.break_for: + +;;;; DEBUGF 1," K : FORCEDETH: id1=0x%x id2=0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8 + + ; id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT + mov eax, dword [forcedeth_tmp_id1] + and eax, PHYID1_OUI_MASK + shl eax, PHYID1_OUI_SHFT + mov dword [forcedeth_tmp_id1], eax + + ; id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT + mov eax, dword [forcedeth_tmp_id2] + and eax, PHYID2_OUI_MASK + shr eax, PHYID2_OUI_SHFT + mov dword [forcedeth_tmp_id2], eax + + DEBUGF 1," K : FORCEDETH: Found PHY 0x%x:0x%x at address 0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8, ebx + + ; np->phyaddr = phyaddr; + mov dword [forcedeth_phyaddr], ebx + + ; np->phy_oui = id1 | id2; + mov eax, dword [forcedeth_tmp_id1] + or eax, dword [forcedeth_tmp_id2] + mov dword [forcedeth_phy_oui], eax + +.end_for: + + ; if (i == 33) + cmp dword [forcedeth_tmp_i], 33 + jne @f + ; PHY in isolate mode? No phy attached and user wants to + ; test loopback? Very odd, but can be correct. + + DEBUGF 1," K : FORCEDETH: Could not find a valid PHY.\n" + + jmp .next3 + +@@: + + ; if (i != 33) + ; reset it + call forcedeth_phy_init + +.next3: + +; dprintf(("%s: forcedeth.c: subsystem: %hX:%hX bound to %s\n", +; pci->name, pci->vendor, pci->dev_id, pci->name)); + DEBUGF 1," K : FORCEDETH: subsystem: 0x%x:0x%x bound to forcedeth\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4 + + +; if(needs_mac_reset) mac_reset(nic); + cmp dword [forcedeth_needs_mac_reset], 0 + je @f + call forcedeth_mac_reset + +@@: + + ; if(!forcedeth_reset(nic)) return 0; // no valid link + call forcedeth_reset + test eax, eax + jnz @f + mov eax, 0 + jmp .return + +@@: + + ; point to NIC specific routines + ; dev->disable = forcedeth_disable; + ; nic->poll = forcedeth_poll; + ; nic->transmit = forcedeth_transmit; + ; nic->irq = forcedeth_irq; + ;;;;;;;;;stdcall attach_int_handler, 11, forcedeth_int_handler, 0 + + ; return 1 + mov eax, 1 + jmp .return + +.fail: + mov eax, 0 + +.return: + ret + +uglobal +forcedeth_tmp_start dd ? +forcedeth_tmp_reg dd ? +forcedeth_tmp_i dd ? +forcedeth_tmp_id1 dd ? +forcedeth_tmp_id2 dd ? +forcedeth_tmp_phyinterface dd ? +forcedeth_tmp_newls dd ? +forcedeth_tmp_newdup dd ? +forcedeth_tmp_retval dd ? +forcedeth_tmp_control_1000 dd ? +forcedeth_tmp_lpa dd ? +forcedeth_tmp_adv dd ? +forcedeth_tmp_len dd ? +forcedeth_tmp_valid dd ? +forcedeth_tmp_nr dd ? +forcedeth_tmp_ptxb dd ? +endg + +;*************************************************************************** +; Function +; forcedeth_poll +; +; Description +; Polls the ethernet card for a received packet +; Received data, if any, ends up in Ether_buffer +; +;*************************************************************************** +forcedeth_poll: + + mov word [eth_rx_data_len], 0 + + ; ???????????????????????????? + ; ??? Clear events? ??? + mov edi, dword [forcedeth_mapio_addr] + mov dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK + ; ???????????????????????????? + +.top: + + ; i = np->cur_rx % RX_RING + mov eax, dword [forcedeth_cur_rx] + and eax, (RX_RING-1) + mov dword [forcedeth_tmp_i], eax + + ; Flags = le32_to_cpu(rx_ring[i].FlagLen) + ; Flags = rx_ring[i].FlagLen + mov cl, sizeof.forcedeth_RxDesc + mul cl + add eax, forcedeth_rx_ring + mov ebx, eax + mov eax, [ebx + forcedeth_RxDesc.FlagLen] + + + ; if (Flags & NV_RX_AVAIL) + test eax, NV_RX_AVAIL + ; return 0; /* still owned by hardware, */ + ; still owned by hardware + jnz .return0 + +;;;;; DEBUGF 1,"poll: FlagLen = %x\n", eax + + ; if (np->desc_ver == DESC_VER_1) { + cmp dword [forcedeth_desc_ver], DESC_VER_1 + jne @f + ; if (!(Flags & NV_RX_DESCRIPTORVALID)) + test eax, NV_RX_DESCRIPTORVALID + ; return 0; + jz .return0 + jmp .next + ; } else { +@@: + ; if (!(Flags & NV_RX2_DESCRIPTORVALID)) + test eax, NV_RX2_DESCRIPTORVALID + ; return 0; + jz .return0 + ; } + +.next: + + ; len = nv_descr_getlength(&rx_ring[i], np->desc_ver) + ; len = rx_ring[i].FlagLen & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2); + ; eax = FlagLen + cmp dword [forcedeth_desc_ver], DESC_VER_1 + jne @f + and eax, LEN_MASK_V1 + jmp .next2 +@@: + and eax, LEN_MASK_V2 + +.next2: + + ; mov dword [forcedeth_tmp_len], eax + + ; valid = 1 + mov dword [forcedeth_tmp_valid], 1 + + ; got a valid packet - forward it to the network core + ; nic->packetlen = len; + mov dword [forcedeth_packetlen], eax + ; + mov word [eth_rx_data_len], ax +;;;;;;;;; DEBUGF 1,"poll: packet len = 0x%x\n", [forcedeth_packetlen] + + + ; memcpy(nic->packet, rxb + (i * RX_NIC_BUFSIZE), nic->packetlen); + ; Copy packet to system buffer (Ether_buffer) + ;???? ecx = (len-4) + mov ecx, eax + push ecx + shr ecx, 2 + + ; rxb + (i * RX_NIC_BUFSIZE) + mov eax, dword [forcedeth_tmp_i] + mov bx, RX_NIC_BUFSIZE + mul bx + add eax, forcedeth_rxb + + mov esi, eax + mov edi, Ether_buffer + cld ; set to increment + rep movsd ; mov dword from [esi++] to [edi++] + pop ecx + and ecx, 3 ; copy rest 1-3 bytes + rep movsb + + ; wmb(); + ; ??? + + ; np->cur_rx++; + inc dword [forcedeth_cur_rx] + + ; if (!valid) + cmp dword [forcedeth_tmp_valid], 0 + jne @f + ; goto top; + jmp .top +@@: + ; alloc_rx(nic); + call forcedeth_alloc_rx + + ; return 1; + jmp .return1 + +;;;;; DEBUGF 1,"K : FORCEDETH: poll: ...\n" + + +.return0: + mov eax, 0 + jmp .return +.return1: + mov eax, 1 +.return: + ;;push eax + + ; ???????????????????????????????????????????????? + ; ????? clear interrupt mask/status + ; read IRQ status + ;;mov edi, dword [forcedeth_mapio_addr] + ;;mov eax, dword [edi+NvRegIrqStatus] + + ; clear events + ;;and eax, not (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF or NVREG_IRQ_LINK or NVREG_IRQ_TIMER) + + ; write IRQ status + ;;mov dword [edi+NvRegIrqStatus], eax + ; ???????????????????????????????????????????????? + + ;;pop eax + ret + + +;*************************************************************************** +; Function +; forcedeth_transmit +; +; Description +; Transmits a packet of data via the ethernet card +; Pointer to 48 bit destination address in edi +; Type of packet in bx +; size of packet in ecx +; pointer to packet data in esi +; +;*************************************************************************** +forcedeth_transmit: + + ; send the packet to destination +;pusha +;DEBUGF 1,"K : FORCEDETH: transmit: packet type = 0x%x\n", ebx +;DEBUGF 1,"K : FORCEDETH: transmit: packet len = 0x%x\n", ecx +;mov eax, dword [edi] +;DEBUGF 1,"K : FORCEDETH: transmit: dest adr = 0x%x\n", eax +;mov eax, dword [edi+4] +;DEBUGF 1,"K : FORCEDETH: transmit: dest adr2 = 0x%x\n", eax +;mov eax, dword [node_addr] +;DEBUGF 1,"K : FORCEDETH: transmit: src adr = 0x%x\n", eax +;mov eax, dword [node_addr+4] +;DEBUGF 1,"K : FORCEDETH: transmit: src adr2 = 0x%x\n", eax +;popa + + ; int nr = np->next_tx % TX_RING + mov eax, dword [forcedeth_next_tx] + and eax, (TX_RING-1) + mov dword [forcedeth_tmp_nr], eax + + ; point to the current txb incase multiple tx_rings are used + ; ptxb = txb + (nr * RX_NIC_BUFSIZE) + push ecx + mov cx, RX_NIC_BUFSIZE + mul cx ; AX*CX, result to DX:AX + add eax, forcedeth_txb + mov dword [forcedeth_tmp_ptxb], eax + push esi + mov esi, edi ; dst MAC + mov edi, eax ; packet buffer + cld ; set to increment + + ; copy the packet to ring buffer + ; memcpy(ptxb, d, ETH_ALEN); /* dst */ + movsd + movsw + + ; memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */ + mov esi, node_addr + movsd + movsw + + ; nstype = htons((u16) t); /* type */ + ; memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2); /* type */ + mov word [edi], bx + add edi, 2 + + ; memcpy(ptxb + ETH_HLEN, p, s); + pop esi + pop ecx + push ecx + shr ecx, 2 ; count in dwords + rep movsd ; copy dwords from [esi+=4] to [edi+=4] + pop ecx + push ecx + and ecx, 3 ; copy rest 1-3 bytes + rep movsb ; copy bytess from [esi++] to [edi++] + + + ; s += ETH_HLEN; + ; while (s < ETH_ZLEN) /* pad to min length */ + ; ptxb[s++] = '\0'; + ; pad to min length + pop ecx + add ecx, ETH_HLEN + push ecx ; header length + data length + cmp ecx, ETH_ZLEN + jge @f + mov eax, ETH_ZLEN + sub eax, ecx + xchg eax, ecx + mov al, 0 + rep stosb ; copy byte from al to [edi++] + +@@: + + ; tx_ring[nr].PacketBuffer = (u32) virt_to_le32desc(ptxb); + mov eax, dword [forcedeth_tmp_nr] + mov cl, sizeof.forcedeth_TxDesc + mul cl + add eax, forcedeth_tx_ring + mov ebx, eax + mov eax, dword [forcedeth_tmp_ptxb] + sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov [ebx + forcedeth_TxDesc.PacketBuffer], eax + +;DEBUGF 1,"K : FORCEDETH: transmit: PacketBuffer = 0x%x\n", eax +;DEBUGF 1,"K : FORCEDETH: transmit: txflags = 0x%x\n", [forcedeth_txflags]:8 + + ; wmb(); + ; tx_ring[nr].FlagLen = cpu_to_le32((s - 1) | np->tx_flags); + pop eax ; header length + data length + mov ecx, dword [forcedeth_txflags] + or eax, ecx + mov [ebx + forcedeth_TxDesc.FlagLen], eax + + ; writel(NVREG_TXRXCTL_KICK | np->desc_ver, base + NvRegTxRxControl); + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [forcedeth_desc_ver] + or eax, NVREG_TXRXCTL_KICK + mov dword [edi+NvRegTxRxControl], eax + + ; pci_push(base); + call forcedeth_pci_push + + ; np->next_tx++ + inc dword [forcedeth_next_tx] ; may be need to reset? Overflow? + + ret + +;*************************************************************************** +; Function +; forcedeth_cable +; +; Description +; Return AL=0, if cable is not connected +; Returm AL=1, if cable is connected +; +;*************************************************************************** +forcedeth_cable: + + mov al, 1 + cmp dword [forcedeth_nocable], 1 + jne .return + mov al, 0 + +.return: + ret + +;*************************************************************************** + + +; read/write a register on the PHY. +; Caller must guarantee serialization +; Input: EAX - miireg, EBX - addr, ECX - value +; Output: EAX - retval +forcedeth_mii_rw: + push ebx + push eax ; save miireg + ; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus) + mov edi, dword [forcedeth_mapio_addr] + mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK + + ; reg = readl(base + NvRegMIIControl) + mov eax, dword [edi+NvRegMIIControl] + test eax, NVREG_MIICTL_INUSE + jz @f + ; writel(NVREG_MIICTL_INUSE, base + NvRegMIIControl) + mov dword [edi+NvRegMIIControl], NVREG_MIICTL_INUSE + ; nv_udelay(NV_MIIBUSY_DELAY) + mov esi, NV_MIIBUSY_DELAY + call forcedeth_nv_udelay +@@: + ; reg = (addr << NVREG_MIICTL_ADDRSHIFT) | miireg + pop edx ; restore miireg + mov eax, ebx + shl eax, NVREG_MIICTL_ADDRSHIFT + or eax, edx + mov dword [forcedeth_tmp_reg], eax + + cmp ecx, MII_READ + je @f + ; writel(value, base + NvRegMIIData) + mov dword [edi+NvRegMIIData], ecx + ; reg |= NVREG_MIICTL_WRITE + or dword [forcedeth_tmp_reg], NVREG_MIICTL_WRITE +@@: + ; writel(reg, base + NvRegMIIControl) + mov eax, dword [forcedeth_tmp_reg] + mov dword [edi+NvRegMIIControl], eax + + push ebx edx edi ;;;;;;;;;;;;;;;;;;;;;; + + ; reg_delay(NvRegMIIControl, NVREG_MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL) + stdcall forcedeth_reg_delay,NvRegMIIControl,NVREG_MIICTL_INUSE,0,NV_MIIPHY_DELAY,NV_MIIPHY_DELAYMAX,0 + + pop edi edx ebx ;;;;;;;;;;;;;;;;;;;;;; + + test eax, eax + jz @f +;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw of reg %d at PHY %d timed out.\n", edx, ebx + mov eax, 0xffffffff + jmp .return +@@: + cmp ecx, MII_READ + je @f + ;it was a write operation - fewer failures are detectable +;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw wrote 0x%x to reg %d at PHY %d\n", ecx, edx, ebx + mov eax, 0 + jmp .return +@@: + ; readl(base + NvRegMIIStatus) + mov eax, dword [edi+NvRegMIIStatus] + test eax, NVREG_MIISTAT_ERROR + jz @f +;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw of reg %d at PHY %d failed.\n", edx, ebx + mov eax, 0xffffffff + jmp .return +@@: + ; retval = readl(base + NvRegMIIData) + mov eax, dword [edi+NvRegMIIData] +;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw read from reg %d at PHY %d: 0x%x.\n", edx, ebx, eax +.return: + pop ebx + ret + + + +; Input: ESI - delay +; Output: none +forcedeth_nv_udelay: + + push ebx + cmp dword [forcedeth_in_shutdown], 0 + jne @f + call forcedeth_udelay ; delay on ESI + jmp .return +@@: + +.loop: + cmp esi, 0 + je .return + ; Don't allow an rx_ring overflow to happen + ; while shutting down the NIC it will + ; kill the receive function. + + call forcedeth_drop_rx + mov ebx, 3 ; sleep = 3 + cmp ebx, esi ; if(sleep > delay) + jle @f + mov ebx, esi ; sleep = delay +@@: + push esi + mov esi, ebx + ; udelay(sleep) + call forcedeth_udelay ; delay on ESI + pop esi + sub esi, ebx ; delay -= sleep + jmp .loop + +.return: + pop ebx + ret + + +; Input: none +; Output: none +forcedeth_drop_rx: + + push eax ebx ecx edi + + ; events = readl(base + NvRegIrqStatus) + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [edi+NvRegIrqStatus] + + test eax, eax + jz @f + ; writel(events, base + NvRegIrqStatus) + mov dword [edi+NvRegIrqStatus], eax +@@: + ;if (!(events & (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF))) + test eax, (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF) + jz .return + +.loop: + ; i = np->cur_rx % RX_RING + mov eax, dword [forcedeth_cur_rx] + and eax, (RX_RING-1) + ; //Flags = le32_to_cpu(rx_ring[i].FlagLen) + ; Flags = rx_ring[i].FlagLen + mov cl, sizeof.forcedeth_RxDesc + mul cl + add eax, forcedeth_rx_ring + mov ebx, eax + mov eax, [ebx + forcedeth_RxDesc.FlagLen] + ; len = nv_descr_getlength(&rx_ring[i], np->desc_ver) + ; > len = Flags & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2) + ; ??? len don't used later !!! ??? + ; ... + test eax, NV_RX_AVAIL + jnz .return ; still owned by hardware, + ; wmb() + ; ??? may be empty function ??? + ; np->cur_rx++ + inc dword [forcedeth_cur_rx] + ; alloc_rx(NULL) + call forcedeth_alloc_rx +.return: + pop edi ecx ebx eax + ret + + +; Fill rx ring entries. +; Return 1 if the allocations for the skbs failed and the +; rx engine is without Available descriptors +; Input: none +; Output: none +forcedeth_alloc_rx: + + push eax ebx ecx edx + ; refill_rx = np->refill_rx + mov ecx, dword [forcedeth_refill_rx] +.loop: + cmp dword [forcedeth_cur_rx], ecx + je .loop_end + ; nr = refill_rx % RX_RING + mov eax, ecx + and eax, (RX_RING-1) ; nr + ; rx_ring[nr].PacketBuffer = &rxb[nr * RX_NIC_BUFSIZE] + push ecx + push eax + mov cl, sizeof.forcedeth_RxDesc + mul cl + add eax, forcedeth_rx_ring + mov ebx, eax + pop eax + mov cx, RX_NIC_BUFSIZE + mul cx + pop ecx + add eax, forcedeth_rxb + sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov [ebx + forcedeth_RxDesc.PacketBuffer], eax + ; wmb() + ; ... + ; rx_ring[nr].FlagLen = RX_NIC_BUFSIZE | NV_RX_AVAIL + mov [ebx + forcedeth_RxDesc.FlagLen], (RX_NIC_BUFSIZE or NV_RX_AVAIL) + inc ecx + jmp .loop + +.loop_end: + ; np->refill_rx = refill_rx + mov [forcedeth_refill_rx], ecx +.return: + pop edx ecx ebx eax + ret + + +; Delay in millisec +; Input: ESI - delay in ms +; Output: none +forcedeth_udelay: + call delay_ms + ret + +; Input: offset:word, mask:dword, target:dword, delay:word, delaymax:word, msg:dword +; Output: EAX - 0|1 +;;;;proc forcedeth_reg_delay,offset:word,mask:dword,target:dword,delay:word,delaymax:word,msg:dword +proc forcedeth_reg_delay,offset:dword,mask:dword,target:dword,delay:dword,delaymax:dword,msg:dword + + push ebx esi edi + ; pci_push(base) + call forcedeth_pci_push +.loop: + ; nv_udelay(delay) + mov esi, dword [delay] + call forcedeth_nv_udelay ; delay in esi + mov eax, dword [delaymax] + sub eax, dword [delay] + mov dword [delaymax], eax + ; if (delaymax < 0) + test dword [delaymax], 0x80000000 + jz @f + ; return 1 + mov eax, 1 + jmp .return +@@: + ; while ((readl(base + offset) & mask) != target) + mov edi, dword [forcedeth_mapio_addr] + mov ebx, dword [offset] + mov eax, dword [edi+ebx] + and eax, dword [mask] + cmp eax, dword [target] + jne .loop + xor eax, eax +.return: + pop edi esi ebx + ret +endp + + +; Input: none +; Output: none +forcedeth_pci_push: + push eax edi + ;force out pending posted writes + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [edi] + pop edi eax + ret + + +; Input: none +; Output: EAX - result (0 = OK, other = error) +forcedeth_phy_init: + + push ebx ecx + + ; set advertise register + ; reg = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ); + ; EBX - addr, EAX - miireg, ECX - value + mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_ADVERTISE + mov ecx, MII_READ + call forcedeth_mii_rw ; reg = eax + + ; reg |= + ; (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | + ; ADVERTISE_100FULL | 0x800 | 0x400); + or eax, (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or 0x800 or 0x400) + + ; if (mii_rw(nic, np->phyaddr, MII_ADVERTISE, reg)) + ; EBX - addr, EAX - miireg, ECX - value + mov ecx, eax ; reg + mov eax, MII_ADVERTISE + call forcedeth_mii_rw ; eax -> return + + test eax, eax + jz @f + ; printf("phy write to advertise failed.\n"); + DEBUGF 1," K : FORCEDETH: phy write to advertise failed.\n" + + ; return PHY_ERROR; + mov eax, PHY_ERROR + jmp .return +@@: + ; get phy interface type + ; phyinterface = readl(base + NvRegPhyInterface); + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [edi+NvRegPhyInterface] ; phyinterface = eax + mov dword [forcedeth_tmp_phyinterface], eax + +;;;;;;;;;;;;;;;;;;;;;;;;; +DEBUGF 1," K : FORCEDETH: phy interface type = 0x%x\n", [forcedeth_tmp_phyinterface]:8 +;;;;;;;;;;;;;;;;;;;;;;;;; + + ; see if gigabit phy + ; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ); + ; EBX - addr, EAX - miireg, ECX - value + mov eax, MII_BMSR + mov ecx, MII_READ + call forcedeth_mii_rw ; mii_status = eax + + ; if (mii_status & PHY_GIGABIT) + test eax, PHY_GIGABIT + jnz .gigabit + ; np->gigabit = 0; + mov dword [forcedeth_gigabit], 0 + jmp .next_if + +.gigabit: + ; np->gigabit = PHY_GIGABIT; + mov dword [forcedeth_gigabit], PHY_GIGABIT + + ; mii_control_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ); + ; EBX - addr, EAX - miireg, ECX - value + mov eax, MII_1000BT_CR + mov ecx, MII_READ + call forcedeth_mii_rw ; mii_control_1000 = eax + + ; mii_control_1000 &= ~ADVERTISE_1000HALF; + and eax, (not ADVERTISE_1000HALF) + + ; if (phyinterface & PHY_RGMII) + test dword [forcedeth_tmp_phyinterface], PHY_RGMII + jz @f + ; mii_control_1000 |= ADVERTISE_1000FULL + or eax, ADVERTISE_1000FULL + jmp .next +@@: + ; mii_control_1000 &= ~ADVERTISE_1000FULL + and eax, (not ADVERTISE_1000FULL) + +.next: + ; if (mii_rw(nic, np->phyaddr, MII_1000BT_CR, mii_control_1000)) + ; EBX - addr, EAX - miireg, ECX - value + mov ecx, eax + mov eax, MII_1000BT_CR + call forcedeth_mii_rw ; eax -> return + + test eax, eax + jz .next_if + + ; printf("phy init failed.\n"); + DEBUGF 1," K : FORCEDETH: phy init failed.\n" + + ; return PHY_ERROR; + mov eax, PHY_ERROR + jmp .return + +.next_if: + + ; reset the phy + ; if (phy_reset(nic)) + call forcedeth_phy_reset + test eax, eax + jz @f + ; printf("phy reset failed\n") + DEBUGF 1," K : FORCEDETH: phy reset failed.\n" + ; return PHY_ERROR + mov eax, PHY_ERROR + jmp .return +@@: + + ; phy vendor specific configuration + ; if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII)) + cmp dword [forcedeth_phy_oui], PHY_OUI_CICADA + jne .next_if2 + test dword [forcedeth_tmp_phyinterface], PHY_RGMII + jz .next_if2 + + ; phy_reserved = mii_rw(nic, np->phyaddr, MII_RESV1, MII_READ) + ; EBX - addr, EAX - miireg, ECX - value + mov eax, MII_RESV1 + mov ecx, MII_READ + call forcedeth_mii_rw ; phy_reserved = eax + + ; phy_reserved &= ~(PHY_INIT1 | PHY_INIT2) + and eax, (not (PHY_INIT1 or PHY_INIT2)) + ; phy_reserved |= (PHY_INIT3 | PHY_INIT4) + or eax, (PHY_INIT3 or PHY_INIT4) + + ; if (mii_rw(nic, np->phyaddr, MII_RESV1, phy_reserved)) + ; EBX - addr, EAX - miireg, ECX - value + mov ecx, eax + mov eax, MII_RESV1 + call forcedeth_mii_rw ; eax -> return + test eax, eax + jz @f + ; printf("phy init failed.\n") + DEBUGF 1," K : FORCEDETH: phy init failed.\n" + ; return PHY_ERROR + mov eax, PHY_ERROR + jmp .return +@@: + ; phy_reserved = mii_rw(nic, np->phyaddr, MII_NCONFIG, MII_READ); + ; EBX - addr, EAX - miireg, ECX - value + mov eax, MII_NCONFIG + mov ecx, MII_READ + call forcedeth_mii_rw ; phy_reserved = eax + + ; phy_reserved |= PHY_INIT5 + or eax, PHY_INIT5 + + ; if (mii_rw(nic, np->phyaddr, MII_NCONFIG, phy_reserved)) + ; EBX - addr, EAX - miireg, ECX - value + mov ecx, eax + mov eax, MII_NCONFIG + call forcedeth_mii_rw ; eax -> return + test eax, eax + jz .next_if2 + ; printf("phy init failed.\n") + DEBUGF 1," K : FORCEDETH: phy init failed.\n" + ; return PHY_ERROR + mov eax, PHY_ERROR + jmp .return + +.next_if2: + + ; if (np->phy_oui == PHY_OUI_CICADA) + cmp dword [forcedeth_phy_oui], PHY_OUI_CICADA + jne .restart + + ; phy_reserved = mii_rw(nic, np->phyaddr, MII_SREVISION, MII_READ) + ; EBX - addr, EAX - miireg, ECX - value + mov eax, MII_SREVISION + mov ecx, MII_READ + call forcedeth_mii_rw ; phy_reserved = eax + + ; phy_reserved |= PHY_INIT6 + or eax, PHY_INIT6 + + ; if (mii_rw(nic, np->phyaddr, MII_SREVISION, phy_reserved)) + mov ecx, eax + mov eax, MII_SREVISION + call forcedeth_mii_rw ; eax -> return + test eax, eax + jz .restart + ; printf("phy init failed.\n"); + DEBUGF 1," K : FORCEDETH: phy init failed.\n" + ; return PHY_ERROR; + jmp .return + +.restart: + ; restart auto negotiation + ; mii_control = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ) + ; EBX - addr, EAX - miireg, ECX - value + mov eax, MII_BMCR + mov ecx, MII_READ + call forcedeth_mii_rw ; mii_control = eax + + ; mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE) + or eax, (BMCR_ANRESTART or BMCR_ANENABLE) + + ; if (mii_rw(nic, np->phyaddr, MII_BMCR, mii_control)) + mov ecx, eax + mov eax, MII_BMCR + call forcedeth_mii_rw ; eax -> return + test eax, eax + jz .ok + + ; return PHY_ERROR; + mov eax, PHY_ERROR + jmp .return + +.ok: + mov eax, 0 +.return: + pop ecx ebx + ret + + +; Input: none +; Output: EAX - result (0 = OK, other = error) +forcedeth_phy_reset: + + push ebx ecx edx + + ; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ); + ; EBX - addr, EAX - miireg, ECX - value + mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_BMCR + mov ecx, MII_READ + call forcedeth_mii_rw ; miicontrol = eax + + ; miicontrol |= BMCR_RESET; + or eax, BMCR_RESET + push eax + + ; if (mii_rw(nic, np->phyaddr, MII_BMCR, miicontrol)) + ; EBX - addr, EAX - miireg, ECX - value + mov ecx, eax + mov eax, MII_BMCR + call forcedeth_mii_rw ; miicontrol = eax + + test eax, eax + jz @f + pop eax + mov eax, 0xffffffff + jmp .return +@@: + pop eax + + ; wait for 500ms + ; mdelay(500) + mov esi, 500 + call forcedeth_udelay + + ; must wait till reset is deasserted + ; while (miicontrol & BMCR_RESET) { + mov edx, 100 +.while_loop: + test eax, BMCR_RESET + jz .while_loop_exit + + ; mdelay(10); + mov esi, 10 + call forcedeth_udelay + + ; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ); + ; EBX - addr, EAX - miireg, ECX - value + mov eax, MII_BMCR + mov ecx, MII_READ + call forcedeth_mii_rw ; miicontrol = eax + + ; FIXME: 100 tries seem excessive + ; if (tries++ > 100) + dec edx + jnz .while_loop + ; return -1; + mov eax, 0xffffffff + jmp .return +.while_loop_exit: + ; return 0 + mov eax, 0 +.return: + pop edx ecx ebx + ret + +; Input: none +; Output: none +forcedeth_mac_reset: + push esi edi + + ; dprintf("mac_reset\n") + DEBUGF 1," K : FORCEDETH: mac_reset.\n" + + ; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl) + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [forcedeth_desc_ver] + or eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET) + mov dword [edi+NvRegTxRxControl], eax + + ; pci_push(base) + call forcedeth_pci_push + + ; writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset) + mov dword [edi+NvRegMacReset], NVREG_MAC_RESET_ASSERT + + ; pci_push(base) + call forcedeth_pci_push + + ; udelay(NV_MAC_RESET_DELAY) + mov esi, NV_MAC_RESET_DELAY + call forcedeth_nv_udelay + + ; writel(0, base + NvRegMacReset) + mov dword [edi+NvRegMacReset], 0 + + ; pci_push(base) + call forcedeth_pci_push + + ; udelay(NV_MAC_RESET_DELAY) + mov esi, NV_MAC_RESET_DELAY + call forcedeth_nv_udelay + + ; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl) + mov eax, dword [forcedeth_desc_ver] + or eax, NVREG_TXRXCTL_BIT2 + mov dword [edi+NvRegTxRxControl], eax + + ; pci_push(base) + call forcedeth_pci_push + + pop edi esi + ret + +; Input: none +; Output: none +forcedeth_init_ring: + push eax ebx ecx + + ; np->next_tx = np->nic_tx = 0 + mov dword[forcedeth_next_tx], 0 + mov dword[forcedeth_nic_tx], 0 + + ; for (i = 0; i < TX_RING; i++) + mov ecx, TX_RING + +.for_loop: + ; tx_ring[i].FlagLen = 0; + mov eax, ecx + dec eax + mov bl, sizeof.forcedeth_TxDesc + mul bl + add eax, forcedeth_tx_ring + mov ebx, eax + mov dword [ebx + forcedeth_TxDesc.FlagLen], 0 + loop .for_loop + + ; np->cur_rx = RX_RING; + mov dword [forcedeth_cur_rx], RX_RING + ; np->refill_rx = 0; + mov dword [forcedeth_refill_rx], 0 + + ;for (i = 0; i < RX_RING; i++) + mov ecx, RX_RING + +.for_loop2: + ; rx_ring[i].FlagLen = 0; + mov eax, ecx + dec eax + mov bl, sizeof.forcedeth_RxDesc + mul bl + add eax, forcedeth_rx_ring + mov ebx, eax + mov dword [ebx + forcedeth_RxDesc.FlagLen], 0 + loop .for_loop2 + + ; alloc_rx(nic); + call forcedeth_alloc_rx + +.return: + pop ecx ebx eax + ret + +; Input: none +; Output: none +forcedeth_txrx_reset: + push eax esi edi + + ; dprintf(("txrx_reset\n")) + DEBUGF 1," K : FORCEDETH: txrx_reset.\n" + + ; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl) + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [forcedeth_desc_ver] + or eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET) + mov dword [edi+NvRegTxRxControl], eax + + ; pci_push(base) + call forcedeth_pci_push + + ; nv_udelay(NV_TXRX_RESET_DELAY) + mov esi, NV_TXRX_RESET_DELAY + call forcedeth_nv_udelay + + ; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl) + mov eax, dword [forcedeth_desc_ver] + or eax, NVREG_TXRXCTL_BIT2 + mov dword [edi+NvRegTxRxControl], eax + + ; pci_push(base) + call forcedeth_pci_push + +.return: + pop edi esi eax + ret + +; Input: none +; Output: none +forcedeth_set_multicast: + push edi + + ; 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 = NVREG_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] |= NVREG_MCASTADDRA_FORCE; + ; pff |= NVREG_PFF_ALWAYS; + ; stop_rx(); + call forcedeth_stop_rx + ; writel(addr[0], base + NvRegMulticastAddrA); + mov edi, dword [forcedeth_mapio_addr] + mov dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE + ; writel(addr[1], base + NvRegMulticastAddrB); + mov dword [edi+NvRegMulticastAddrB], 0 + ; writel(mask[0], base + NvRegMulticastMaskA); + mov dword [edi+NvRegMulticastMaskA], 0 + ; writel(mask[1], base + NvRegMulticastMaskB); + mov dword [edi+NvRegMulticastMaskB], 0 + ; writel(pff, base + NvRegPacketFilterFlags); + mov dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_MYADDR or NVREG_PFF_ALWAYS) + ; start_rx(nic); + call forcedeth_start_rx + +.return: + pop edi + ret + +; Input: none +; Output: none +forcedeth_start_rx: + push edi + + ; dprintf(("start_rx\n")) + DEBUGF 1," K : FORCEDETH: start_rx.\n" + + ; Already running? Stop it. + ; if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) { + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [edi+NvRegReceiverControl] + test eax, NVREG_RCVCTL_START + jz @f + ; writel(0, base + NvRegReceiverControl) + mov dword [edi+NvRegReceiverControl], 0 + ; pci_push(base) + call forcedeth_pci_push + +@@: + + ; writel(np->linkspeed, base + NvRegLinkSpeed); + mov eax, dword [forcedeth_linkspeed] + mov dword [edi+NvRegLinkSpeed], eax + ; pci_push(base); + call forcedeth_pci_push + ; writel(NVREG_RCVCTL_START, base + NvRegReceiverControl); + mov dword [edi+NvRegReceiverControl], NVREG_RCVCTL_START + ; pci_push(base); + call forcedeth_pci_push + +.return: + pop edi + ret + +; Input: none +; Output: none +forcedeth_stop_rx: + push esi edi + + ; dprintf(("stop_rx\n")) + DEBUGF 1," K : FORCEDETH: stop_rx.\n" + + ; writel(0, base + NvRegReceiverControl) + mov edi, dword [forcedeth_mapio_addr] + mov dword [edi+NvRegReceiverControl], 0 + + push ebx edx edi ;;;;;;;;;;;;;;;;;;;;;; + ; reg_delay(NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, "stop_rx: ReceiverStatus remained busy"); + stdcall forcedeth_reg_delay,NvRegReceiverStatus,NVREG_RCVSTAT_BUSY,0,NV_RXSTOP_DELAY1,NV_RXSTOP_DELAY1MAX,0 + pop edi edx ebx ;;;;;;;;;;;;;;;;;;;;;; + + + ; nv_udelay(NV_RXSTOP_DELAY2) + mov esi, NV_RXSTOP_DELAY2 + call forcedeth_nv_udelay + + ; writel(0, base + NvRegLinkSpeed) + mov dword [edi+NvRegLinkSpeed], 0 + +.return: + pop edi esi + ret + +; Input: none +; Output: EAX +forcedeth_update_linkspeed: + push ebx ecx esi edi + + ; BMSR_LSTATUS is latched, read it twice: + ; we want the current value. + + ; mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ) + ;EBX - addr, EAX - miireg, ECX - value + mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_BMSR + mov ecx, MII_READ + call forcedeth_mii_rw + + + ; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ) + ;EBX - addr, EAX - miireg, ECX - value + mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_BMSR + mov ecx, MII_READ + call forcedeth_mii_rw ; mii_status = eax + + ; yhlu + + ; for(i=0;i<30;i++) { + mov ecx, 30 +.for_loop: + push ecx + + ; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ); + ;EBX - addr, EAX - miireg, ECX - value + ;mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_BMSR + mov ecx, MII_READ + call forcedeth_mii_rw ; mii_status = eax + + ; if((mii_status & BMSR_LSTATUS) && (mii_status & BMSR_ANEGCOMPLETE)) break; + test eax, BMSR_LSTATUS + jz @f + test eax, BMSR_ANEGCOMPLETE + jz @f + ; break + pop ecx + jmp .break + +@@: + + ; mdelay(100); + push eax ; ??? + mov esi, 100 + call forcedeth_udelay + pop eax ; ??? + + pop ecx + loop .for_loop + +.break: + + ; if (!(mii_status & BMSR_LSTATUS)) { + test eax, BMSR_LSTATUS + jnz @f + + ; printf("no link detected by phy - falling back to 10HD.\n") + DEBUGF 1," K : FORCEDETH: update_linkspeed: no link detected by phy - falling back to 10HD.\n" + + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) + + ; newdup = 0; + mov dword [forcedeth_tmp_newdup], 0 + ; retval = 0; + mov dword [forcedeth_tmp_retval], 0 + + ; goto set_speed; + jmp .set_speed + +@@: + + ; check auto negotiation is complete + ; if (!(mii_status & BMSR_ANEGCOMPLETE)) { + test eax, BMSR_ANEGCOMPLETE + jnz @f + + ; still in autonegotiation - configure nic for 10 MBit HD and wait. + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) + + ; newdup = 0 + mov dword [forcedeth_tmp_newdup], 0 + + ; retval = 0 + mov dword [forcedeth_tmp_retval], 0 + + ; printf("autoneg not completed - falling back to 10HD.\n") + DEBUGF 1," K : FORCEDETH: update_linkspeed: autoneg not completed - falling back to 10HD.\n" + + ; goto set_speed + jmp .set_speed + +@@: + + ; retval = 1 + mov dword [forcedeth_tmp_retval], 1 + + ; if (np->gigabit == PHY_GIGABIT) { + cmp dword [forcedeth_gigabit], PHY_GIGABIT + jne .end_if + ; control_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ) + ;EBX - addr, EAX - miireg, ECX - value + ;mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_1000BT_CR + mov ecx, MII_READ + call forcedeth_mii_rw ; control_1000 = eax + mov dword [forcedeth_tmp_control_1000], eax + + ; status_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_SR, MII_READ) + ;EBX - addr, EAX - miireg, ECX - value + ;mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_1000BT_SR + mov ecx, MII_READ + call forcedeth_mii_rw ; status_1000 = eax + ;mov dword [forcedeth_tmp_status_1000], eax + + ; if ((control_1000 & ADVERTISE_1000FULL) && + ; (status_1000 & LPA_1000FULL)) { + test eax, LPA_1000FULL + jz .end_if + test dword [forcedeth_tmp_control_1000], ADVERTISE_1000FULL + jz .end_if + + ; printf ("update_linkspeed: GBit ethernet detected.\n") + DEBUGF 1," K : FORCEDETH: update_linkspeed: GBit ethernet detected.\n" + + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_1000 + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_1000) + + ; newdup = 1 + mov dword [forcedeth_tmp_newdup], 1 + + ; goto set_speed + jmp .set_speed + +.end_if: + + ; adv = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ); + ;EBX - addr, EAX - miireg, ECX - value + ;mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_ADVERTISE + mov ecx, MII_READ + call forcedeth_mii_rw ; adv = eax + mov dword [forcedeth_tmp_adv], eax + + ; lpa = mii_rw(nic, np->phyaddr, MII_LPA, MII_READ); + ;EBX - addr, EAX - miireg, ECX - value + ;mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_LPA + mov ecx, MII_READ + call forcedeth_mii_rw ; lpa = eax + mov dword [forcedeth_tmp_lpa], eax + + ; dprintf(("update_linkspeed: PHY advertises 0x%hX, lpa 0x%hX.\n", adv, lpa)); + DEBUGF 1," K : FORCEDETH: update_linkspeed: PHY advertises 0x%x, lpa 0x%x.\n", [forcedeth_tmp_adv]:8, [forcedeth_tmp_lpa]:8 + + ; FIXME: handle parallel detection properly, handle gigabit ethernet + ; lpa = lpa & adv + mov eax, dword [forcedeth_tmp_adv] + and dword [forcedeth_tmp_lpa], eax + + mov eax, dword [forcedeth_tmp_lpa] + + ; if (lpa & LPA_100FULL) { + test eax, LPA_100FULL + jz @f + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100 + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100) + ; newdup = 1 + mov dword [forcedeth_tmp_newdup], 1 + jmp .set_speed +@@: + ; } else if (lpa & LPA_100HALF) { + test eax, LPA_100HALF + jz @f + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100 + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100) + ; newdup = 0 + mov dword [forcedeth_tmp_newdup], 0 + jmp .set_speed +@@: + ; } else if (lpa & LPA_10FULL) { + test eax, LPA_10FULL + jz @f + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) + ; newdup = 1 + mov dword [forcedeth_tmp_newdup], 1 + jmp .set_speed +@@: + ; } else if (lpa & LPA_10HALF) { + test eax, LPA_10HALF + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10; + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) + ; newdup = 0; + mov dword [forcedeth_tmp_newdup], 0 + jmp .set_speed +@@: + ; } else { + ; printf("bad ability %hX - falling back to 10HD.\n", lpa) + DEBUGF 1," K : FORCEDETH: update_linkspeed: bad ability 0x%x - falling back to 10HD.\n", eax + + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) + ; newdup = 0 + mov dword [forcedeth_tmp_newdup], 0 + ; } + +.set_speed: + + ; if (np->duplex == newdup && np->linkspeed == newls) + mov eax, dword [forcedeth_tmp_newdup] + cmp eax, dword [forcedeth_duplex] + jne .end_if2 + mov eax, dword [forcedeth_tmp_newls] + cmp eax, dword [forcedeth_linkspeed] + jne .end_if2 + ; return retval; + jmp .return + +.end_if2: + + ; dprintf(("changing link setting from %d/%s to %d/%s.\n", + ; np->linkspeed, np->duplex ? "Full-Duplex": "Half-Duplex", newls, newdup ? "Full-Duplex": "Half-Duplex")) + DEBUGF 1," K : FORCEDETH: update_linkspeed: changing link from %x/XD to %x/XD.\n", [forcedeth_linkspeed]:8, [forcedeth_tmp_newls]:8 ; !!!!!!!!!!!!!!!!!!!!!!!!!!!! + + ; np->duplex = newdup + mov eax, dword [forcedeth_tmp_newdup] + mov dword [forcedeth_duplex], eax + + ; np->linkspeed = newls + mov eax, [forcedeth_tmp_newls] + mov dword [forcedeth_linkspeed], eax + + ; if (np->gigabit == PHY_GIGABIT) { + cmp dword [forcedeth_gigabit], PHY_GIGABIT + jne .end_if3 + + ; phyreg = readl(base + NvRegRandomSeed); + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [edi+NvRegRandomSeed] + + ; phyreg &= ~(0x3FF00); + and eax, not (0x3FF00) + mov ecx, eax ; phyreg = ecx + + ; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10) + mov eax, dword [forcedeth_linkspeed] + and eax, 0xFFF + cmp eax, NVREG_LINKSPEED_10 + jne @f + ; phyreg |= NVREG_RNDSEED_FORCE3 + or ecx, NVREG_RNDSEED_FORCE3 + jmp .end_if4 +@@: + ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100) + cmp eax, NVREG_LINKSPEED_100 + jne @f + ; phyreg |= NVREG_RNDSEED_FORCE2 + or ecx, NVREG_RNDSEED_FORCE2 + jmp .end_if4 +@@: + ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000) + cmp eax, NVREG_LINKSPEED_1000 + jne .end_if4 + ; phyreg |= NVREG_RNDSEED_FORCE + or ecx, NVREG_RNDSEED_FORCE +.end_if4: + ; writel(phyreg, base + NvRegRandomSeed) + mov dword [edi+NvRegRandomSeed], ecx + +.end_if3: + + ; phyreg = readl(base + NvRegPhyInterface) + mov ecx, dword [edi+NvRegPhyInterface] + + ; phyreg &= ~(PHY_HALF | PHY_100 | PHY_1000) + and ecx, not (PHY_HALF or PHY_100 or PHY_1000) + + ; if (np->duplex == 0) + cmp dword [forcedeth_duplex], 0 + jne @f + ; phyreg |= PHY_HALF + or ecx, PHY_HALF +@@: + ; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100) + mov eax, dword [forcedeth_linkspeed] + and eax, 0xFFF + cmp eax, NVREG_LINKSPEED_100 + jne @f + ; phyreg |= PHY_100 + or ecx, PHY_100 + jmp .end_if5 +@@: + ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000) + cmp eax, NVREG_LINKSPEED_1000 + jne .end_if5 + ; phyreg |= PHY_1000 + or ecx, PHY_1000 + +.end_if5: + + ; writel(phyreg, base + NvRegPhyInterface) + mov dword [edi+NvRegPhyInterface], ecx + + ; writel(NVREG_MISC1_FORCE | (np->duplex ? 0 : NVREG_MISC1_HD), base + NvRegMisc1); + cmp dword [forcedeth_duplex], 0 + je @f + mov ecx, 0 + jmp .next +@@: + mov ecx, NVREG_MISC1_HD +.next: + or ecx, NVREG_MISC1_FORCE + mov dword [edi+NvRegMisc1], ecx + + ; pci_push(base) + call forcedeth_pci_push + + ; writel(np->linkspeed, base + NvRegLinkSpeed) + mov eax, dword [forcedeth_linkspeed] + mov dword [edi+NvRegLinkSpeed], eax + + ; pci_push(base) + call forcedeth_pci_push + +.return: + ; return retval + mov eax, dword [forcedeth_tmp_retval] + pop edi esi ecx ebx + ret + + +; Input: none +; Output: none +forcedeth_start_tx: + push edi + ; dprintf(("start_tx\n")) + DEBUGF 1," K : FORCEDETH: start_tx.\n" + + ; writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl) + mov edi, dword [forcedeth_mapio_addr] + mov dword [edi+NvRegTransmitterControl], NVREG_XMITCTL_START + + ; pci_push(base) + call forcedeth_pci_push + +.return: + pop edi + ret + +; Interrupt handler +forcedeth_int_handler: + DEBUGF 1," K : FORCEDETH: interrupt handler.\n" + + ret + diff --git a/kernel/branches/kolibri_pe/network/eth_drv/drivers/rtl8169.inc b/kernel/branches/kolibri_pe/network/eth_drv/drivers/rtl8169.inc index 5c7ca4b262..498fd15459 100644 --- a/kernel/branches/kolibri_pe/network/eth_drv/drivers/rtl8169.inc +++ b/kernel/branches/kolibri_pe/network/eth_drv/drivers/rtl8169.inc @@ -1,4 +1,4 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; ;; Distributed under terms of the GNU General Public License ;; @@ -339,7 +339,7 @@ rtl8169_txb rb NUM_TX_DESC * RX_BUF_SIZE ; Define the RX Descriptor align 256 -rtl8169_rx_ring rb NUM_RX_DESC * sizeof.rtl8169_TxDesc +rtl8169_rx_ring rb NUM_RX_DESC * sizeof.rtl8169_RxDesc ; Create a static buffer of size RX_BUF_SZ for each ; RX Descriptor All descriptors point to a @@ -524,20 +524,20 @@ endp ; Also adjust PCI latency timer to a reasonable value, 32. proc adjust_pci_device - DEBUGF 1,"K : adjust_pci_device\n" +; DEBUGF 1,"K : adjust_pci_device\n" stdcall pci_read_config_word,PCI_COMMAND mov bx,ax or bx,PCI_COMMAND_MASTER or PCI_COMMAND_IO cmp ax,bx je @f - DEBUGF 1,"K : adjust_pci_device: The PCI BIOS has not enabled this device!\nK : Updating PCI command %x->%x. pci_bus %x pci_device_fn %x\n",ax,bx,[pci_bus]:2,[pci_dev]:2 +; DEBUGF 1,"K : adjust_pci_device: The PCI BIOS has not enabled this device!\nK : Updating PCI command %x->%x. pci_bus %x pci_device_fn %x\n",ax,bx,[pci_bus]:2,[pci_dev]:2 stdcall pci_write_config_word,PCI_COMMAND,ebx @@: stdcall pci_read_config_byte,PCI_LATENCY_TIMER cmp al,32 jae @f - DEBUGF 1,"K : adjust_pci_device: PCI latency timer (CFLT) is unreasonably low at %d.\nK : Setting to 32 clocks.\n",al +; DEBUGF 1,"K : adjust_pci_device: PCI latency timer (CFLT) is unreasonably low at %d.\nK : Setting to 32 clocks.\n",al stdcall pci_write_config_byte,PCI_LATENCY_TIMER,32 @@: ret @@ -559,7 +559,7 @@ proc pci_bar_start,index:dword stdcall pci_read_config_dword,eax or eax,eax jz .not64 - DEBUGF 1,"K : pci_bar_start: Unhandled 64bit BAR\n" +; DEBUGF 1,"K : pci_bar_start: Unhandled 64bit BAR\n" add esp,4 or eax,-1 ret @@ -572,7 +572,7 @@ endp proc rtl8169_init_board - DEBUGF 1,"K : rtl8169_init_board\n" +; DEBUGF 1,"K : rtl8169_init_board\n" call adjust_pci_device @@ -592,7 +592,7 @@ proc rtl8169_init_board ; identify config method RTL_R32 RTL8169_REG_TxConfig and eax,0x7c800000 - DEBUGF 1,"K : rtl8169_init_board: TxConfig & 0x7c800000 = 0x%x\n",eax +; DEBUGF 1,"K : rtl8169_init_board: TxConfig & 0x7c800000 = 0x%x\n",eax mov esi,mac_info-8 @@: add esi,8 mov ecx,eax @@ -625,9 +625,9 @@ proc rtl8169_init_board jmp .match @@: ; if unknown chip, assume array element #0, original RTL-8169 in this case - DEBUGF 1,"K : rtl8169_init_board: PCI device: unknown chip version, assuming RTL-8169\n" +; DEBUGF 1,"K : rtl8169_init_board: PCI device: unknown chip version, assuming RTL-8169\n" RTL_R32 RTL8169_REG_TxConfig - DEBUGF 1,"K : rtl8169_init_board: PCI device: TxConfig = 0x%x\n",eax +; DEBUGF 1,"K : rtl8169_init_board: PCI device: TxConfig = 0x%x\n",eax mov [rtl8169_tpc.chipset],0 @@ -642,7 +642,7 @@ endp proc rtl8169_hw_PHY_config - DEBUGF 1,"K : rtl8169_hw_PHY_config: priv.mcfg=%d, priv.pcfg=%d\n",[rtl8169_tpc.mcfg],[rtl8169_tpc.pcfg] +; DEBUGF 1,"K : rtl8169_hw_PHY_config: priv.mcfg=%d, priv.pcfg=%d\n",[rtl8169_tpc.mcfg],[rtl8169_tpc.pcfg] ; DBG_PRINT("priv->mcfg=%d, priv->pcfg=%d\n", tpc->mcfg, tpc->pcfg); @@ -705,7 +705,7 @@ proc rtl8169_hw_PHY_config jmp .exit .not_2_or_3: ; DBG_PRINT("tpc->mcfg=%d. Discard hw PHY config.\n", tpc->mcfg); - DEBUGF 1,"K : tpc.mcfg=%d, discard hw PHY config\n",[rtl8169_tpc.mcfg] +; DEBUGF 1,"K : tpc.mcfg=%d, discard hw PHY config\n",[rtl8169_tpc.mcfg] .exit: ret endp @@ -716,21 +716,21 @@ endp proc RTL8169_WRITE_GMII_REG,RegAddr:byte,value:dword - DEBUGF 1,"K : RTL8169_WRITE_GMII_REG: 0x%x 0x%x\n",[RegAddr]:2,[value] +;;; DEBUGF 1,"K : RTL8169_WRITE_GMII_REG: 0x%x 0x%x\n",[RegAddr]:2,[value] movzx eax,[RegAddr] shl eax,16 or eax,[value] or eax,0x80000000 RTL_W32 RTL8169_REG_PHYAR,eax - stdcall udelay,1000 + stdcall udelay,1 ;;;1000 mov ecx,2000 ; Check if the RTL8169 has completed writing to the specified MII register @@: RTL_R32 RTL8169_REG_PHYAR test eax,0x80000000 jz .exit - stdcall udelay,100 + stdcall udelay,1 ;;;100 loop @b .exit: ret @@ -738,21 +738,21 @@ endp proc RTL8169_READ_GMII_REG,RegAddr:byte - DEBUGF 1,"K : RTL8169_READ_GMII_REG: 0x%x\n",[RegAddr]:2 +;;; DEBUGF 1,"K : RTL8169_READ_GMII_REG: 0x%x\n",[RegAddr]:2 push ecx movzx eax,[RegAddr] shl eax,16 ; or eax,0x0 RTL_W32 RTL8169_REG_PHYAR,eax - stdcall udelay,1000 + stdcall udelay,1 ;;;1000 mov ecx,2000 ; Check if the RTL8169 has completed retrieving data from the specified MII register @@: RTL_R32 RTL8169_REG_PHYAR test eax,0x80000000 jnz .exit - stdcall udelay,100 + stdcall udelay,1 ;;;100 loop @b or eax,-1 @@ -767,7 +767,7 @@ endp proc rtl8169_set_rx_mode - DEBUGF 1,"K : rtl8169_set_rx_mode\n" +; DEBUGF 1,"K : rtl8169_set_rx_mode\n" ; IFF_ALLMULTI ; Too many to filter perfectly -- accept all multicasts @@ -785,7 +785,7 @@ endp proc rtl8169_init_ring - DEBUGF 1,"K : rtl8169_init_ring\n" +; DEBUGF 1,"K : rtl8169_init_ring\n" xor eax,eax mov [rtl8169_tpc.cur_rx],eax @@ -820,6 +820,7 @@ proc rtl8169_init_ring mov ecx,NUM_RX_DESC @@: mov [esi],eax mov [edi+rtl8169_RxDesc.buf_addr],eax + sub [edi+rtl8169_RxDesc.buf_addr],OS_BASE ; shurf 28.09.2008 mov [edi+rtl8169_RxDesc.status],RTL8169_DSB_OWNbit or RX_BUF_SIZE add esi,4 add edi,sizeof.rtl8169_RxDesc @@ -833,7 +834,7 @@ endp proc rtl8169_hw_start - DEBUGF 1,"K : rtl8169_hw_start\n" +; DEBUGF 1,"K : rtl8169_hw_start\n" ; Soft reset the chip RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_Reset @@ -879,8 +880,14 @@ proc rtl8169_hw_start RTL_W16 0xE2,0x0000 MOV [rtl8169_tpc.cur_rx],0 - RTL_W32 RTL8169_REG_TxDescStartAddr,[rtl8169_tpc.TxDescArray] - RTL_W32 RTL8169_REG_RxDescStartAddr,[rtl8169_tpc.RxDescArray] + push eax ; shurf 28.09.2008 + mov eax, [rtl8169_tpc.TxDescArray] ; shurf 28.09.2008 + sub eax, OS_BASE ; shurf 28.09.2008 + RTL_W32 RTL8169_REG_TxDescStartAddr,eax ;[rtl8169_tpc.TxDescArray] ; shurf 28.09.2008 + mov eax, [rtl8169_tpc.RxDescArray] ; shurf 28.09.2008 + sub eax, OS_BASE ; shurf 28.09.2008 + RTL_W32 RTL8169_REG_RxDescStartAddr,eax ;[rtl8169_tpc.RxDescArray] ; shurf 28.09.2008 + pop eax ; shurf 28.09.2008 RTL_W8 RTL8169_REG_Cfg9346,RTL8169_CFG_9346_Lock stdcall udelay,10 RTL_W32 RTL8169_REG_RxMissed,0 @@ -913,7 +920,7 @@ endp ;*************************************************************************** proc rtl8169_probe - DEBUGF 1,"K : rtl8169_probe: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 +; DEBUGF 1,"K : rtl8169_probe: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 call rtl8169_init_board @@ -928,7 +935,7 @@ proc rtl8169_probe inc ebx loop @b - DEBUGF 1,"K : rtl8169_probe: MAC = %x-%x-%x-%x-%x-%x\n",[node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2 +; DEBUGF 1,"K : rtl8169_probe: MAC = %x-%x-%x-%x-%x-%x\n",[node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2 ; Config PHY stdcall rtl8169_hw_PHY_config @@ -988,7 +995,7 @@ endp ;*************************************************************************** proc rtl8169_reset - DEBUGF 1,"K : rtl8169_reset: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 +; DEBUGF 1,"K : rtl8169_reset: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 mov [rtl8169_tpc.TxDescArrays],rtl8169_tx_ring ; Tx Desscriptor needs 256 bytes alignment @@ -1033,7 +1040,7 @@ endp ;*************************************************************************** proc rtl8169_transmit - DEBUGF 1,"K : rtl8169_transmit\n" ;: 0x%x : 0x%x 0x%x 0x%x 0x%x\n",[io_addr]:8,edi,bx,ecx,esi +; DEBUGF 1,"K : rtl8169_transmit\n" ;: 0x%x : 0x%x 0x%x 0x%x 0x%x\n",[io_addr]:8,edi,bx,ecx,esi push ecx edx esi mov eax,MAX_ETH_FRAME_SIZE @@ -1087,6 +1094,7 @@ proc rtl8169_transmit add eax,[rtl8169_tpc.TxDescArray] xchg eax,ebx mov [ebx + rtl8169_TxDesc.buf_addr],eax + sub [ebx + rtl8169_TxDesc.buf_addr],OS_BASE ; shurf 28.09.2008 mov eax,ecx cmp eax,ETH_ZLEN @@ -1110,7 +1118,7 @@ proc rtl8169_transmit jnz @f stdcall udelay,10 loop @b - DEBUGF 1,"K : rtl8169_transmit: TX Time Out\n" +; DEBUGF 1,"K : rtl8169_transmit: TX Time Out\n" @@: ret @@ -1168,7 +1176,7 @@ proc rtl8169_poll add eax,-4 mov [eth_rx_data_len],ax - DEBUGF 1,"K : rtl8169_poll: data length = %u\n",ax +; DEBUGF 1,"K : rtl8169_poll: data length = %u\n",ax push eax mov ecx,eax @@ -1190,9 +1198,10 @@ proc rtl8169_poll @@: mov [ebx + rtl8169_RxDesc.status],eax mov [ebx + rtl8169_RxDesc.buf_addr],edx + sub [ebx + rtl8169_RxDesc.buf_addr],OS_BASE ; shurf 28.09.2008 jmp @f .else: - DEBUGF 1,"K : rtl8169_poll: Rx Error\n" +; DEBUGF 1,"K : rtl8169_poll: Rx Error\n" ; FIXME: shouldn't I reset the status on an error @@: inc [rtl8169_tpc.cur_rx] diff --git a/kernel/branches/kolibri_pe/network/eth_drv/ethernet.inc b/kernel/branches/kolibri_pe/network/eth_drv/ethernet.inc index b296f2ff7b..74df50176d 100644 --- a/kernel/branches/kolibri_pe/network/eth_drv/ethernet.inc +++ b/kernel/branches/kolibri_pe/network/eth_drv/ethernet.inc @@ -104,6 +104,7 @@ include "drivers/3c59x.inc" include "drivers/sis900.inc" include "drivers/pcnet32.inc" include "drivers/rtl8169.inc" +include "drivers/forcedeth.inc" ; PCICards ; ======== @@ -153,6 +154,7 @@ dd 0x816810ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 dd 0x816910ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 dd 0x011616ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 dd 0x43001186, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 +dd 0x816710ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 dd 0x590010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 dd 0x592010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 @@ -200,6 +202,23 @@ dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0 ;dd 0x08001516, mtd80x_probe, mtd80x_reset, mtd80x_poll, mtd80x_transmit, mtd80x_cable ;dd 0x08911516, mtd80x_probe, mtd80x_reset, mtd80x_poll, mtd80x_transmit, mtd80x_cable +dd 0x006610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; nVidia Corporation nForce2 Ethernet Controller +dd 0x01c310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x00D610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x008610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x008c10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x00e610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x00df10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x005610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x005710de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x003710de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x003810de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x026810de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x026910de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x037210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x037310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested + + rb PCICARDS_ENTRY_SIZE ; end of list marker, do not remove endg @@ -334,6 +353,9 @@ endp ; All registers may be destroyed ; ;*************************************************************************** +uglobal + ether_IP_handler_cnt dd ? +endg ether_IP_handler: mov eax, EMPTY_QUEUE call dequeue @@ -357,6 +379,9 @@ ether_IP_handler: cld rep movsd +; inc [ether_IP_handler_cnt] +; DEBUGF 1, "K : ether_IP_handler (%u)\n", [ether_IP_handler_cnt] + ; And finally, place the buffer in the IPRX queue pop ebx mov eax, IPIN_QUEUE @@ -443,16 +468,18 @@ eth_rx: cmp ax, ETHER_ARP je .is_arp ; It is ARP + DEBUGF 1,"K : eth_rx - dumped (%u)\n", ax + inc [dumped_rx_count] jmp .exit ; If not IP or ARP, ignore .is_ip: - DEBUGF 1,"K : eth_rx - IP packet\n" +; DEBUGF 1,"K : eth_rx - IP packet\n" inc dword [ip_rx_count] call ether_IP_handler jmp .exit .is_arp: - DEBUGF 1,"K : eth_rx - ARP packet\n" +; DEBUGF 1,"K : eth_rx - ARP packet\n" ; At this point, the packet is still in the Ether_buffer call arp_handler diff --git a/kernel/branches/kolibri_pe/network/ip.inc b/kernel/branches/kolibri_pe/network/ip.inc index a57e082bc0..e1b5b4882b 100644 --- a/kernel/branches/kolibri_pe/network/ip.inc +++ b/kernel/branches/kolibri_pe/network/ip.inc @@ -87,6 +87,10 @@ macro GET_IHL reg, header_addr } +include "tcp.inc" +include "udp.inc" +include "icmp.inc" + ;*************************************************************************** ; Function ; ip_rx @@ -114,11 +118,13 @@ local buffer_number dd ? mov ebx, eax ; ebx=pointer to IP_PACKET +; DEBUGF 1, "K : ip_rx - proto: %u\n", [ebx + IP_PACKET.Protocol]:1 + ; Validate the IP checksum mov dx, word[ebx + IP_PACKET.HeaderChecksum] xchg dh,dl ; Get the checksum in intel format - mov [ebx + IP_PACKET.HeaderChecksum], word 0 ; clear checksum field - need to when + mov [ebx + IP_PACKET.HeaderChecksum], 0 ; clear checksum field - need to when ; recalculating checksum ; this needs two data pointers and two size #. ; 2nd pointer can be of length 0 @@ -127,8 +133,12 @@ local buffer_number dd ? stdcall checksum_jb, ebx, ecx ;buf_ptr, buf_size cmp dx, ax +; DEBUGF 1, "K : ip_rx - checksums: %x - %x\n", dx, ax + + jnz .dump.1 ;if CHECKSUM isn't valid then dump packet mov edx, ebx ; EDX (IP-BUFFER POINTER) WILL BE USED FOR *_rx HANDLERS BELOW!!! - jnz .dump ;if CHECKSUM isn't valid then dump packet + +; DEBUGF 1, "K : ip_rx - dest: %x - %x\n", [ebx + IP_PACKET.DestinationAddress], [stack_ip] ; Validate the IP address, if it isn't broadcast mov eax, [stack_ip] @@ -137,22 +147,37 @@ local buffer_number dd ? ; If the IP address is 255.255.255.255, accept it ; - it is a broadcast packet, which we need for dhcp - cmp dword[ebx + IP_PACKET.DestinationAddress], 0xffffffff - jne .dump + + mov eax, [ebx + IP_PACKET.DestinationAddress] + cmp eax, 0xffffffff + ;je @f + ;mov ecx, [stack_ip] + ;and eax, [subnet_mask] + ;and ecx, [subnet_mask] + ;cmp eax, ecx + ;jne .dump.2 + ;mov eax, [ebx + IP_PACKET.DestinationAddress] + ;or eax, [subnet_mask] + ;cmp eax, 0xffffffff + jne .dump.2 @@: mov al, [ebx + IP_PACKET.VersionAndIHL] and al, 0x0f ;get IHL(header length) cmp al, 0x05 ;if IHL!= 5*4(20 bytes) - jnz .dump ;then dump it +; DEBUGF 1, "K : ip_rx - ihl: %x - 05\n", al + jnz .dump.3 ;then dump it - cmp byte[ebx + IP_PACKET.TimeToLive], byte 0 - je .dump ;if TTL==0 then dump it +; DEBUGF 1, "K : ip_rx - ttl: %x - 00\n", [ebx + IP_PACKET.TimeToLive]:2 - mov ax, word[ebx + IP_PACKET.FlagsAndFragmentOffset] + cmp [ebx + IP_PACKET.TimeToLive], 0 + je .dump.4 ;if TTL==0 then dump it + + mov ax, [ebx + IP_PACKET.FlagsAndFragmentOffset] and ax, 0xFFBF ;get flags +; DEBUGF 1, "K : ip_rx - flags: %x - 0000\n", ax cmp ax, 0 ;if some flags was set then we dump this packet - jnz .dump ;the flags should be used for fragmented packets + jnz .dump.5 ;the flags should be used for fragmented packets ; Check the protocol, and call the appropriate handler ; Each handler will re-use or free the queue buffer as appropriate @@ -161,7 +186,7 @@ local buffer_number dd ? cmp al , PROTOCOL_TCP jne .not_tcp - DEBUGF 1,"K : ip_rx - TCP packet\n" +; DEBUGF 1,"K : ip_rx - TCP packet\n" mov eax, dword[buffer_number] call tcp_rx jmp .exit @@ -169,29 +194,48 @@ local buffer_number dd ? .not_tcp: cmp al, PROTOCOL_UDP jne .not_udp - DEBUGF 1,"K : ip_rx - UDP packet\n" +; DEBUGF 1,"K : ip_rx - UDP packet\n" mov eax, dword[buffer_number] call udp_rx jmp .exit .not_udp: - cmp al , PROTOCOL_ICMP - jne .dump ;protocol ain't supported + cmp al, PROTOCOL_ICMP + jne .dump.6 ;protocol ain't supported - DEBUGF 1,"K : ip_rx - ICMP packet\n" +; DEBUGF 1,"K : ip_rx - ICMP packet\n" ;GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx mov eax, dword[buffer_number] stdcall icmp_rx,eax,ebx,ecx ;buffer_number,IPPacketBase,IPHeaderLength jmp .exit -.dump: - ; No protocol handler available, so - ; silently dump the packet, freeing up the queue buffer + .dump.1: + DEBUGF 1, "K : ip_rx - dumped (checksum: 0x%x-0x%x)\n", dx, ax + jmp .dump.x - inc dword [dumped_rx_count] + .dump.2: + DEBUGF 1, "K : ip_rx - dumped (ip: %u.%u.%u.%u)\n", [ebx + IP_PACKET.DestinationAddress + 0]:1, [ebx + IP_PACKET.DestinationAddress + 1]:1, [ebx + IP_PACKET.DestinationAddress + 2]:1, [ebx + IP_PACKET.DestinationAddress + 3]:1 + jmp .dump.x - mov eax, dword[buffer_number] + .dump.3: + DEBUGF 1, "K : ip_rx - dumped (ihl: %u)\n", al + jmp .dump.x + + .dump.4: + DEBUGF 1, "K : ip_rx - dumped (ihl: %u)\n", [ebx + IP_PACKET.TimeToLive] + jmp .dump.x + + .dump.5: + DEBUGF 1, "K : ip_rx - dumped (flags: 0x%x)\n", ax + jmp .dump.x + + .dump.6: + DEBUGF 1, "K : ip_rx - dumped (proto: %u)\n", [ebx + IP_PACKET.Protocol]:1 + + .dump.x: + inc dword[dumped_rx_count] + mov eax, [buffer_number] call freeBuff .exit: diff --git a/kernel/branches/kolibri_pe/network/queue.inc b/kernel/branches/kolibri_pe/network/queue.inc index 15b458f1a1..01da8ea3ad 100644 --- a/kernel/branches/kolibri_pe/network/queue.inc +++ b/kernel/branches/kolibri_pe/network/queue.inc @@ -43,18 +43,19 @@ $Revision$ ; all other registers preserved ; This always works, so no error returned ;*************************************************************************** +uglobal + freeBuff_cnt dd ? +endg freeBuff: +; inc [freeBuff_cnt] +; DEBUGF 1, "K : freeBuff (%u)\n", [freeBuff_cnt] push ebx push ecx - mov ebx, EMPTY_QUEUE - shl ebx, 1 - add ebx, queues + mov ebx, queues + EMPTY_QUEUE * 2 cli ; Ensure that another process does not interfer - movzx ecx, word [ebx] + mov cx, [ebx] mov [ebx], ax - shl eax, 1 - add eax, queueList - mov [eax], cx + mov [queueList + eax * 2], cx sti pop ecx pop ebx @@ -105,7 +106,12 @@ qs_exit: ; all other registers preserved ; This always works, so no error returned ;*************************************************************************** +uglobal + queue_cnt dd ? +endg queue: +; inc [queue_cnt] +; DEBUGF 1, "K : queue (%u)\n", [queue_cnt] push ebx shl ebx, 1 add ebx, queueList ; eax now holds address of queue entry @@ -155,6 +161,9 @@ qu_exit: ; all other registers preserved ; ;*************************************************************************** +uglobal + dequeue_cnt dd ? +endg dequeue: push ebx shl eax, 1 @@ -164,6 +173,8 @@ dequeue: movzx eax, word [eax] cmp ax, NO_BUFFER je dq_exit +; inc [dequeue_cnt] +; DEBUGF 1, "K : dequeue (%u)\n", [dequeue_cnt] push eax shl eax, 1 add eax, queueList ; eax now holds address of queue entry diff --git a/kernel/branches/kolibri_pe/network/socket.inc b/kernel/branches/kolibri_pe/network/socket.inc index 9d197ddf99..e0f2be12bf 100644 --- a/kernel/branches/kolibri_pe/network/socket.inc +++ b/kernel/branches/kolibri_pe/network/socket.inc @@ -77,21 +77,23 @@ $Revision$ ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; 72| Retransmit queue # NOW WINDOW SIZE TIMER INTEL format| ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; 76| RX offset from -; 76| RX Data | +; 76| RX Data Buffer | ; +-+-+-.......... -+ ; so, define struct struc SOCKET -{ .Status dd ? ;+00 - Status ( of this buffer ) +{ + .PrevPtr dd ? + .NextPtr dd ? + .Status dd ? ;+00 - Status ( of this buffer ) .PID dd ? ;+04 - Application Process ID .LocalIP dd ? ;+08 - Local IP Address .LocalPort dw ? ;+12 - Local Port - .UnusedL dw ? ;+14 - may be removed in future .RemoteIP dd ? ;+16 - Remote IP Address .RemotePort dw ? ;+20 - Remote Port - .UnusedR dw ? ;+22 - may be removed in future + .OrigRemoteIP dd ? + .OrigRemotePort dw ? .rxDataCount dd ? ;+24 - Rx Data Count .TCBState dd ? ;+28 - TCB STATE .TCBTimer dd ? ;+32 - TCB Timer (seconds) @@ -113,21 +115,132 @@ virtual at 0 end virtual ; simple macro calcing real memory address of SOCKET struct by socket's -macro Index2RealAddr reg -{ - shl reg, 12 - add reg, sockets -} +;macro Index2RealAddr reg +;{ +; shl reg, 12 +; add reg, sockets +;} ;Constants ; current socket statuses -SOCK_EMPTY equ 0 ; socket not in use -SOCK_OPEN equ 1 ; open issued, but no data sent +SOCK_EMPTY = 0 ; socket not in use +SOCK_OPEN = 1 ; open issued, but no data sent ; TCP opening modes SOCKET_PASSIVE equ 0 SOCKET_ACTIVE equ 1 +proc net_socket_alloc stdcall uses ebx ecx edx edi + mov ecx, SOCKETBUFFSIZE + mov edx, PG_SW + call @mem_alloc@8 + DEBUGF 1, "K : net_socket_alloc (0x%x)\n", eax + or eax, eax + jz .exit + + push eax + mov edi, eax + mov ecx, SOCKETBUFFSIZE / 4 + cld + xor eax, eax + rep stosd + pop eax + + mov ebx, net_sockets + push [ebx + SOCKET.NextPtr] + mov [ebx + SOCKET.NextPtr], eax + mov [eax + SOCKET.PrevPtr], ebx + pop ebx + mov [eax + SOCKET.NextPtr], ebx + or ebx, ebx + jz @f + mov [ebx + SOCKET.PrevPtr], eax + + @@: mov ebx, [TASK_BASE] + mov ebx, [ebx + TASKDATA.pid] + mov [eax + SOCKET.PID], ebx + + .exit: + ret +endp + +proc net_socket_free stdcall uses ebx ecx edx, sock:DWORD + mov eax, [sock] + DEBUGF 1, "K : net_socket_free (0x%x)\n", eax + or eax, eax + jz .error + + mov ebx, net_sockets + mov ecx, [TASK_BASE] + mov ecx, [ecx + TASKDATA.pid] + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .error + cmp ebx, eax + jne .next_socket + ;cmp [ebx + SOCKET.PID], ecx + ;jne .next_socket + + mov ebx, [eax + SOCKET.NextPtr] + mov eax, [eax + SOCKET.PrevPtr] + mov [eax + SOCKET.NextPtr], ebx + or ebx, ebx + jz @f + mov [ebx + SOCKET.PrevPtr], eax + +@@: + mov ecx, [sock] + call @mem_free@4 + ret + + .error: + DEBUGF 1, "K : failed\n" + ret +endp + +proc net_socket_num_to_addr stdcall uses ebx ecx, x:DWORD +; FIXME: do real transform + mov eax, [x] + mov ebx, net_sockets + mov ecx, [TASK_BASE] + mov ecx, [ecx + TASKDATA.pid] + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .error + cmp ebx, eax + jne .next_socket + ;cmp [ebx + SOCKET.PID], ecx + ;jne .next_socket + ret + + .error: + xor eax, eax + ret +endp + +proc net_socket_addr_to_num stdcall uses ebx ecx, x:DWORD +; FIXME: do real transform + mov eax, [x] + mov ebx, net_sockets + mov ecx, [TASK_BASE] + mov ecx, [ecx + TASKDATA.pid] + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .error + cmp ebx, eax + jne .next_socket + ;cmp [ebx + SOCKET.PID], ecx + ;jne .next_socket + ret + + .error: + xor eax, eax + ret +endp + ;*************************************************************************** ; Function ; is_localport_unused @@ -140,51 +253,26 @@ SOCKET_ACTIVE equ 1 ; On return, eax = 1 for free, 0 for in use ; ;*************************************************************************** -is_localport_unused: - mov al, bh - mov ah, bl - mov bx, ax +proc is_localport_unused stdcall - mov edx, SOCKETBUFFSIZE * NUM_SOCKETS - mov ecx, NUM_SOCKETS - mov eax, 0 ; Assume the return value is 'in use' + xchg bl, bh -ilu1: - sub edx, SOCKETBUFFSIZE - cmp [edx + sockets + SOCKET.LocalPort], bx - loopnz ilu1 ; Return back if the socket is occupied + xor eax, eax ; Assume the return value is 'free' + inc al + mov edx, net_sockets - jz ilu_exit - inc eax ; return port not in use + .next_socket: + mov edx, [edx + SOCKET.NextPtr] + or edx, edx + jz .exit + cmp [edx + SOCKET.LocalPort], bx + jne .next_socket ; Return back if the port is not occupied -ilu_exit: - ret - - - -;*************************************************************************** -; Function -; get_free_socket -; -; Description -; -;*************************************************************************** -get_free_socket: - push ecx - mov eax, SOCKETBUFFSIZE * NUM_SOCKETS - mov ecx, NUM_SOCKETS - -gfs1: - sub eax, SOCKETBUFFSIZE - cmp [eax + sockets + SOCKET.Status], dword SOCK_EMPTY - loopnz gfs1 ; Return back if the socket is occupied - mov eax, ecx - pop ecx - jz gfs_exit - mov eax, 0xFFFFFFFF - -gfs_exit: + dec al ; return 'in use' + + .exit: ret +endp ;*************************************************************************** @@ -199,18 +287,16 @@ gfs_exit: ; return socket # in eax, -1 if none available ; ;*************************************************************************** -socket_open: - call get_free_socket +proc socket_open stdcall + call net_socket_alloc + or eax, eax + jz .error - cmp eax, 0xFFFFFFFF - jz so_exit + DEBUGF 1, "K : socket_open (0x%x)\n", eax - ; ax holds the socket number that is free. Get real address push eax - Index2RealAddr eax - - mov [eax + SOCKET.Status], dword SOCK_OPEN + mov [eax + SOCKET.Status], SOCK_OPEN xchg bh, bl mov [eax + SOCKET.LocalPort], bx xchg ch, cl @@ -219,16 +305,16 @@ socket_open: mov ebx, [stack_ip] mov [eax + SOCKET.LocalIP], ebx mov [eax + SOCKET.RemoteIP], edx - mov [eax + SOCKET.rxDataCount], dword 0 ; recieved data count - mov esi, [TASK_BASE] - mov ebx, [esi+TASKDATA.pid] - mov [eax + SOCKET.PID], ebx ; save the process ID - pop eax ; Get the socket number back, so we can return it + ;pop eax ; Get the socket number back, so we can return it + stdcall net_socket_addr_to_num + ret -so_exit: + .error: + DEBUGF 1, "K : socket_open (fail)\n" + or eax, -1 ret - +endp ;*************************************************************************** @@ -245,92 +331,109 @@ so_exit: ; return socket # in eax, -1 if none available ; ;*************************************************************************** -socket_open_tcp: - call get_free_socket +proc socket_open_tcp stdcall +local sockAddr dd ? - cmp eax, 0xFFFFFFFF - jz so_exit + cmp esi, SOCKET_PASSIVE + jne .skip_port_check - ; ax holds the socket number that is free. Get real address - push eax - Index2RealAddr eax + push ebx + mov eax, ebx + xchg al, ah + mov ebx, net_sockets - mov [sktAddr], eax - mov [eax], dword SOCK_OPEN + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .last_socket + cmp [ebx + SOCKET.TCBState], TCB_LISTEN + jne .next_socket + cmp [ebx + SOCKET.LocalPort], ax + jne .next_socket + + xchg al, ah + DEBUGF 1, "K : error: port %u is listened by 0x%x\n", ax, ebx + pop ebx + jmp .error + + .last_socket: + pop ebx + + .skip_port_check: + call net_socket_alloc + or eax, eax + jz .error + + DEBUGF 1, "K : socket_open_tcp (0x%x)\n", eax + + mov [sockAddr], eax ; TODO - check this works! - mov [eax + SOCKET.wndsizeTimer], dword 0 ; Reset the window timer. + ;xxx: already 0 (intialized by net_socket_alloc) + ;mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer. xchg bh, bl mov [eax + SOCKET.LocalPort], bx -; mov [eax + 12], byte bh ; Local port ( LS 16 bits ) -; mov [eax + 13], byte bl ; Local port ( LS 16 bits ) - xchg ch, cl mov [eax + SOCKET.RemotePort], cx -; mov [eax + 20], ch ; Remote Port ( LS 16 bits ) -; mov [eax + 21], cl ; Remote Port ( LS 16 bits ) - + mov [eax + SOCKET.OrigRemotePort], cx mov ebx, [stack_ip] mov [eax + SOCKET.LocalIP], ebx mov [eax + SOCKET.RemoteIP], edx - mov [eax + SOCKET.rxDataCount], dword 0 + mov [eax + SOCKET.OrigRemoteIP], edx - ; Now fill in TCB state mov ebx, TCB_LISTEN cmp esi, SOCKET_PASSIVE - jz sot_001 + je @f mov ebx, TCB_SYN_SENT - -sot_001: - mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB - - mov esi, [TASK_BASE] - mov ecx, [esi+TASKDATA.pid] - mov [eax + SOCKET.PID], ecx ; save the process ID + @@: mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB cmp ebx, TCB_LISTEN - je sot_done + je .exit ; Now, if we are in active mode, then we have to send a SYN to the specified remote port mov eax, EMPTY_QUEUE call dequeue cmp ax, NO_BUFFER - je sot_done + je .exit push eax - mov bl, 0x02 ; SYN - mov ecx, 0 - - call buildTCPPacket + mov bl, TH_SYN + xor ecx, ecx + stdcall build_tcp_packet, [sockAddr] mov eax, NET1OUT_QUEUE mov edx, [stack_ip] - mov ecx, [sktAddr ] - mov ecx, [ecx + 16] - cmp edx, ecx - jne sot_notlocal + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local mov eax, IPIN_QUEUE -sot_notlocal: + .not_local: ; Send it. pop ebx call queue - mov esi, [sktAddr] + mov esi, [sockAddr] ; increment SND.NXT in socket - add esi, 48 + add esi, SOCKET.SND_NXT call inc_inet_esi -sot_done: - pop eax ; Get the socket number back, so we can return it + .exit: + mov ebx, [sockAddr] + mov [ebx + SOCKET.Status], SOCK_OPEN + ;pop eax ; Get the socket number back, so we can return it + stdcall net_socket_addr_to_num, ebx + ret -sot_exit: + .error: + DEBUGF 1, "K : socket_open_tcp (fail)\n" + or eax, -1 ret - +endp ;*************************************************************************** @@ -342,24 +445,31 @@ sot_exit: ; returns 0 for ok, -1 for socket not open (fail) ; ;*************************************************************************** -socket_close: - mov eax, 0xFFFFFFFF ; assume this operation will fail.. - cmp ebx, NUM_SOCKETS - jae sc_exit - Index2RealAddr ebx - cmp [ebx + SOCKET.Status], dword SOCK_EMPTY - jz sc_exit +proc socket_close stdcall + DEBUGF 1, "K : socket_close (0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error + + cmp [eax + SOCKET.Status], dword SOCK_EMPTY + jz .error ; Clear the socket varaibles + stdcall net_socket_free, eax +; mov edi, eax +; xor eax, eax +; mov ecx, SOCKETHEADERSIZE +; cld +; rep stosb + xor eax, eax - mov edi, ebx - mov ecx, SOCKETHEADERSIZE - cld - rep stosb + ret -sc_exit: + .error: + DEBUGF 1, "K : socket_close (fail)\n" + or eax, -1 ret - +endp ;*************************************************************************** @@ -371,110 +481,120 @@ sc_exit: ; returns 0 for ok, -1 for socket not open (fail) ; ;*************************************************************************** -socket_close_tcp: +proc socket_close_tcp stdcall +local sockAddr dd ? + DEBUGF 1, "K : socket_close_tcp (0x%x)\n", ebx ; first, remove any resend entries pusha mov esi, resendQ mov ecx, 0 -sct001: + .next_resendq: cmp ecx, NUMRESENDENTRIES - je sct003 ; None left - cmp [esi], bl - je sct002 ; found one + je .last_resendq ; None left + ;cmp [esi], bl ; XTODO: bl -> ebx + cmp [esi + 4], ebx + je @f ; found one inc ecx - add esi, 4 - jmp sct001 + add esi, 8 + jmp .next_resendq -sct002: + ;@@: mov byte[esi], 0xff ; XTODO: 0xff -> 0 + @@: mov dword[esi + 4], 0 + inc ecx + add esi, 8 + jmp .next_resendq - mov [esi], byte 0xFF - jmp sct001 + .last_resendq: + popa -sct003: - popa + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error - Index2RealAddr ebx - mov [sktAddr], ebx - mov eax, 0xFFFFFFFF ; assume this operation will fail.. - cmp [ebx + SOCKET.Status], dword SOCK_EMPTY - jz sct_exit + mov ebx, eax + mov [sockAddr], eax + cmp [ebx + SOCKET.Status], SOCK_EMPTY + je .error + + cmp [ebx + SOCKET.TCBState], TCB_LISTEN ;xxx + je .destroy_tcb ;xxx + cmp [ebx + SOCKET.TCBState], TCB_SYN_SENT ;xxx + je .destroy_tcb ;xxx ; Now construct the response, and queue for sending by IP mov eax, EMPTY_QUEUE call dequeue cmp ax, NO_BUFFER - je stl_exit + je .error push eax - mov bl, 0x11 ; FIN + ACK - mov ecx, 0 - mov esi, 0 - - call buildTCPPacket - - mov ebx, [sktAddr] +;xxx mov bl, TH_FIN + TH_ACK + mov bl, TH_FIN ;xxx + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] + mov ebx, [sockAddr] ; increament SND.NXT in socket - mov esi, 48 - add esi, ebx + lea esi, [ebx + SOCKET.SND_NXT] call inc_inet_esi ; Get the socket state mov eax, [ebx + SOCKET.TCBState] - cmp eax, TCB_LISTEN - je destroyTCB - cmp eax, TCB_SYN_SENT - je destroyTCB +;xxx cmp eax, TCB_LISTEN +;xxx je .destroy_tcb +;xxx cmp eax, TCB_SYN_SENT +;xxx je .destroy_tcb cmp eax, TCB_SYN_RECEIVED - je sct_finwait1 + je .fin_wait_1 cmp eax, TCB_ESTABLISHED - je sct_finwait1 + je .fin_wait_1 ; assume CLOSE WAIT ; Send a fin, then enter last-ack state - mov eax, TCB_LAST_ACK - mov [ebx + SOCKET.TCBState], eax - xor eax, eax - jmp sct_send + ; TODO: check if it's really a TCB_CLOSE_WAIT + mov [ebx + SOCKET.TCBState], TCB_LAST_ACK + jmp .send -sct_finwait1: + .fin_wait_1: ; Send a fin, then enter finwait2 state - mov eax, TCB_FIN_WAIT_1 - mov [ebx + SOCKET.TCBState], eax - xor eax, eax + mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1 -sct_send: + .send: mov eax, NET1OUT_QUEUE mov edx, [stack_ip] - mov ecx, [sktAddr ] - mov ecx, [ecx + 16] - cmp edx, ecx - jne sct_notlocal + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local mov eax, IPIN_QUEUE -sct_notlocal: + .not_local: ; Send it. pop ebx call queue - jmp sct_exit + jmp .exit -destroyTCB: - pop eax - ; Clear the socket varaibles + .destroy_tcb: +;xxx pop eax + + ; Clear the socket variables +;xxx stdcall net_socket_free, [sockAddr] + stdcall net_socket_free, ebx + + .exit: xor eax, eax - mov edi, ebx - mov ecx, SOCKETHEADERSIZE - cld - rep stosb + ret -sct_exit: + .error: + DEBUGF 1, "K : socket_close_tcp (fail)\n" + or eax, -1 ret - +endp ;*************************************************************************** @@ -486,12 +606,20 @@ sct_exit: ; returns count in eax. ; ;*************************************************************************** -socket_poll: - Index2RealAddr ebx - mov eax, [ebx + SOCKET.rxDataCount] +proc socket_poll stdcall +; DEBUGF 1, "socket_poll(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error + mov eax, [eax + SOCKET.rxDataCount] ret + .error: + ;or eax, -1 + xor eax, eax + ret +endp ;*************************************************************************** @@ -503,12 +631,25 @@ socket_poll: ; returns TCB state in eax. ; ;*************************************************************************** -socket_status: - Index2RealAddr ebx - mov eax, [ebx + SOCKET.TCBState] +proc socket_status stdcall +;; DEBUGF 1, "socket_status(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error + mov eax, [eax + SOCKET.TCBState] + ret + + .error: + ;or eax, -1 + xor eax, eax ret +endp +; Index2RealAddr ebx +; mov eax, [ebx + SOCKET.TCBState] +; +; ret ;*************************************************************************** @@ -520,35 +661,40 @@ socket_status: ; returns # of bytes remaining in eax, data in bl ; ;*************************************************************************** -socket_read: - Index2RealAddr ebx +proc socket_read stdcall +; DEBUGF 1, "socket_read(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error + + mov ebx, eax mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes - mov ecx, 1 test eax, eax - jz sr2 + jz .error dec eax mov esi, ebx ; esi is address of socket mov [ebx + SOCKET.rxDataCount], eax ; store new count - ;movzx ebx, byte [ebx + SOCKET.rxData] ; get the byte - movzx ebx, byte [ebx + SOCKETHEADERSIZE] ; get the byte + ;movzx ebx, byte[ebx + SOCKET.rxData] ; get the byte + movzx ebx, byte[ebx + SOCKETHEADERSIZE] ; get the byte add esi, SOCKETHEADERSIZE mov edi, esi inc esi mov ecx, (SOCKETBUFFSIZE - SOCKETHEADERSIZE) / 4 + lea edi, [ebx + SOCKETHEADERSIZE] + lea esi, [edi + 1] cld rep movsd - xor ecx, ecx -sr1: - jmp sor_exit + ret -sr2: - xor bl, bl - -sor_exit: + .error: + ;or eax, -1 + xor eax, eax + xor ebx, ebx ret +endp ;*************************************************************************** @@ -562,22 +708,27 @@ sor_exit: ; returns # of bytes copied in eax ; ;*************************************************************************** -socket_read_packet: - Index2RealAddr ebx ; get real socket address +proc socket_read_packet stdcall +; DEBUGF 1, "socket_read_packet(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx ; get real socket address + or eax, eax + jz .error + + mov ebx, eax mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes test eax, eax ; if count of bytes is zero.. jz .exit ; exit function (eax will be zero) test edx, edx ; if buffer size is zero, copy all data - jz .copyallbytes + jz .copy_all_bytes cmp edx, eax ; if buffer size is larger then the bytes of data, copy all data - jge .copyallbytes + jge .copy_all_bytes sub eax, edx ; store new count (data bytes in buffer - bytes we're about to copy) mov [ebx + SOCKET.rxDataCount], eax ; push eax mov eax, edx ; number of bytes we want to copy must be in eax - call .startcopy ; copy to the application + call .start_copy ; copy to the application mov esi, ebx ; now we're going to copy the remaining bytes to the beginning add esi, SOCKETHEADERSIZE ; we dont need to copy the header @@ -592,31 +743,34 @@ socket_read_packet: and ecx, 3 rep movsb ; copy remaining bytes + .exit: ret ; at last, exit -.copyallbytes: + .error: + ;or eax, -1 + xor eax, eax + ret + + .copy_all_bytes: xor esi, esi mov [ebx + SOCKET.rxDataCount], esi ; store new count (zero) + call .start_copy + ret -.startcopy: - mov edi, ecx ; - ; add edi, std_application_base_address ; get data pointer to buffer in application - - mov esi, ebx ; + .start_copy: + mov edi, ecx + mov esi, ebx add esi, SOCKETHEADERSIZE ; we dont need to copy the header mov ecx, eax ; eax is count of bytes push ecx shr ecx, 2 ; divide eax by 4 cld ; copy all full dwords - rep movsd ; + rep movsd pop ecx and ecx, 3 rep movsb ; copy the rest bytes - -.exit: - ret ; exit, or go back to shift remaining bytes if any - - + retn ; exit, or go back to shift remaining bytes if any +endp ;*************************************************************************** @@ -631,19 +785,22 @@ socket_read_packet: ; could not queue IP packet ) ; ;*************************************************************************** -socket_write: - Index2RealAddr ebx +proc socket_write stdcall +; DEBUGF 1, "socket_write(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx ; get real socket address + or eax, eax + jz .error + + mov ebx, eax - mov eax, 0xFFFFFFFF ; If the socket is invalid, return with an error code - cmp [ebx], dword SOCK_EMPTY - je sw_exit - + cmp [ebx + SOCKET.Status], SOCK_EMPTY + je .error mov eax, EMPTY_QUEUE call dequeue cmp ax, NO_BUFFER - je sw_exit + je .error ; Save the queue entry number push eax @@ -661,56 +818,47 @@ socket_write: ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr - ; Fill in the IP header ( some data is in the socket descriptor) - mov eax, [ebx + 8] - mov [edx + 12], eax ; source IP - mov eax, [ebx + 16] - mov [edx + 16], eax ; Destination IP + ; Fill in the IP header (some data is in the socket descriptor) + mov eax, [ebx + SOCKET.LocalIP] + mov [edx + IP_PACKET.SourceAddress], eax + mov eax, [ebx + SOCKET.RemoteIP] + mov [edx + IP_PACKET.DestinationAddress], eax - mov al, 0x45 - mov [edx], al ; Version, IHL - xor al, al - mov [edx + 1], al ; Type of service + mov [edx + IP_PACKET.VersionAndIHL], 0x45 + mov [edx + IP_PACKET.TypeOfService], 0 pop eax ; Get the UDP data length push eax add eax, 20 + 8 ; add IP header and UDP header lengths - mov [edx + 2], ah - mov [edx + 3], al - xor al, al - mov [edx + 4], al - mov [edx + 5], al - mov al, 0x40 - mov [edx + 6], al - xor al, al - mov [edx + 7], al - mov al, 0x20 - mov [edx + 8], al - mov al, 17 - mov [edx + 9], al + xchg al, ah + mov [edx + IP_PACKET.TotalLength], ax + xor eax, eax + mov [edx + IP_PACKET.Identification], ax + mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040 + mov [edx + IP_PACKET.TimeToLive], 0x20 + mov [edx + IP_PACKET.Protocol], PROTOCOL_UDP ; Checksum left unfilled - xor ax, ax - mov [edx + 10], ax + mov [edx + IP_PACKET.HeaderChecksum], ax - ; Fill in the UDP header ( some data is in the socket descriptor) - mov ax, [ebx + 12] - mov [edx + 20], ax + ; Fill in the UDP header (some data is in the socket descriptor) + mov ax, [ebx + SOCKET.LocalPort] + mov [edx + 20 + UDP_PACKET.SourcePort], ax - mov ax, [ebx + 20] - mov [edx + 20 + 2], ax + mov ax, [ebx + SOCKET.RemotePort] + mov [edx + 20 + UDP_PACKET.DestinationPort], ax pop eax push eax add eax, 8 - mov [edx + 20 + 4], ah - mov [edx + 20 + 5], al + xchg al, ah + mov [edx + 20 + UDP_PACKET.Length], ax ; Checksum left unfilled - xor ax, ax - mov [edx + 20 + 6], ax + xor eax, eax + mov [edx + 20 + UDP_PACKET.Checksum], ax pop ecx ; count of bytes to send mov ebx, ecx ; need the length later @@ -730,16 +878,15 @@ socket_write: ; we have edx as IPbuffer ptr. ; Fill in the UDP checksum ; First, fill in pseudoheader - mov eax, [edx + 12] + mov eax, [edx + IP_PACKET.SourceAddress] mov [pseudoHeader], eax - mov eax, [edx + 16] - mov [pseudoHeader+4], eax - mov ax, 0x1100 ; 0 + protocol - mov [pseudoHeader+8], ax + mov eax, [edx + IP_PACKET.DestinationAddress] + mov [pseudoHeader + 4], eax + mov word[pseudoHeader + 8], PROTOCOL_UDP shl 8 + 0 ; 0 + protocol add ebx, 8 mov eax, ebx - mov [pseudoHeader+10], ah - mov [pseudoHeader+11], al + xchg al, ah + mov [pseudoHeader + 10], ax mov eax, pseudoHeader mov [checkAdd1], eax @@ -757,42 +904,41 @@ socket_write: ; If the UDP checksum computes to 0, we must make it 0xffff ; (0 is reserved for 'not used') - cmp ax, 0 - jne sw_001 + test ax, ax + jnz @f mov ax, 0xffff -sw_001: - mov [edx + 20 + 6], ah - mov [edx + 20 + 7], al + @@: xchg al, ah + mov [edx + 20 + UDP_PACKET.Checksum], ax ; Fill in the IP header checksum GET_IHL ecx,edx ; get IP-Header length stdcall checksum_jb,edx,ecx ; buf_ptr, buf_size - - mov [edx + 10], ah - mov [edx + 11], al + xchg al, ah + mov [edx + IP_PACKET.HeaderChecksum], ax ; Check destination IP address. ; If it is the local host IP, route it back to IP_RX pop ebx mov eax, NET1OUT_QUEUE - - mov ecx, [ edx + 16] + mov ecx, [edx + SOCKET.RemoteIP] mov edx, [stack_ip] cmp edx, ecx - jne sw_notlocal + jne .not_local mov eax, IPIN_QUEUE -sw_notlocal: + .not_local: ; Send it. call queue xor eax, eax + ret -sw_exit: + .error: + or eax, -1 ret - +endp ;*************************************************************************** @@ -807,30 +953,33 @@ sw_exit: ; could not queue IP packet ) ; ;*************************************************************************** -socket_write_tcp: - Index2RealAddr ebx +proc socket_write_tcp stdcall +local sockAddr dd ? - mov [sktAddr], ebx +; DEBUGF 1, "socket_write_tcp(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error + + mov ebx, eax + mov [sockAddr], ebx - mov eax, 0xFFFFFFFF ; If the socket is invalid, return with an error code - cmp [ebx], dword SOCK_EMPTY - je swt_exit + cmp [ebx + SOCKET.Status], SOCK_EMPTY + je .error ; If the sockets window timer is nonzero, do not queue packet ; TODO - done - cmp [ebx + SOCKET.wndsizeTimer], dword 0 - jne swt_exit + cmp [ebx + SOCKET.wndsizeTimer], 0 + jne .error mov eax, EMPTY_QUEUE call dequeue cmp ax, NO_BUFFER - je swt_exit + je .error push eax - mov bl, 0x10 ; ACK - ; Get the address of the callers data mov edi, [TASK_BASE] add edi, TASKDATA.mem_start @@ -841,7 +990,8 @@ socket_write_tcp: push eax push ecx - call buildTCPPacket + mov bl, TH_ACK + stdcall build_tcp_packet, [sockAddr] pop ecx ; Check destination IP address. @@ -852,24 +1002,23 @@ socket_write_tcp: mov eax, NET1OUT_QUEUE mov edx, [stack_ip] - mov ecx, [sktAddr ] - mov ecx, [ecx + 16] - cmp edx, ecx - jne swt_notlocal + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local mov eax, IPIN_QUEUE -swt_notlocal: + .not_local: pop ecx push ebx ; save ipbuffer number call queue - mov esi, [sktAddr] + mov esi, [sockAddr] ; increament SND.NXT in socket ; Amount to increment by is in ecx - add esi, 48 + add esi, SOCKET.SND_NXT call add_inet_esi pop ebx @@ -879,17 +1028,17 @@ swt_notlocal: mov esi, resendQ mov ecx, 0 -swt003: + .next_resendq: cmp ecx, NUMRESENDENTRIES - je swt001 ; None found - cmp [esi], byte 0xFF - je swt002 ; found one + je .exit ; None found + ;cmp byte[esi], 0xff ; XTODO: 0xff -> 0 + cmp dword[esi + 4], 0 + je @f ; found one inc ecx - add esi, 4 - jmp swt003 + add esi, 8 + jmp .next_resendq -swt002: - push ebx + @@: push ebx ; OK, we have a buffer descriptor ptr in esi. ; resend entry # in ecx @@ -899,19 +1048,18 @@ swt002: ; retry time ; fill IP buffer associated with this descriptor - mov eax, [sktAddr] - sub eax, sockets - shr eax, 12 ; get skt # - mov [esi], al - mov [esi + 1], byte TCP_RETRIES - mov [esi + 2], word TCP_TIMEOUT + stdcall net_socket_addr_to_num, [sockAddr] + ;mov [esi], al ; XTODO: al -> eax + mov [esi + 4], eax + mov byte[esi + 1], TCP_RETRIES + mov word[esi + 2], TCP_TIMEOUT inc ecx ; Now get buffer location, and copy buffer across. argh! more copying,, mov edi, resendBuffer - IPBUFFSIZE -swt002a: - add edi, IPBUFFSIZE - loop swt002a + + @@: add edi, IPBUFFSIZE + loop @b ; we have dest buffer location in edi pop eax @@ -926,9 +1074,11 @@ swt002a: cld rep movsb -swt001: + .exit: xor eax, eax + ret -swt_exit: + .error: + or eax, -1 ret - +endp diff --git a/kernel/branches/kolibri_pe/network/stack.inc b/kernel/branches/kolibri_pe/network/stack.inc index eefc30457a..f5cd8a1343 100644 --- a/kernel/branches/kolibri_pe/network/stack.inc +++ b/kernel/branches/kolibri_pe/network/stack.inc @@ -37,7 +37,7 @@ $Revision$ uglobal StackCounters: - dumped_rx_count: dd 0 + dumped_rx_count dd 0 arp_tx_count: dd 0 arp_rx_count: dd 0 ip_rx_count: dd 0 @@ -46,9 +46,9 @@ endg ; socket buffers SOCKETBUFFSIZE equ 4096 ; state + config + buffer. -SOCKETHEADERSIZE equ 76 ; thus 4096 - SOCKETHEADERSIZE bytes data +SOCKETHEADERSIZE equ 76+8+8 ; thus 4096 - SOCKETHEADERSIZE bytes data -NUM_SOCKETS equ 16 ; Number of open sockets supported. Was 20 +;NUM_SOCKETS equ 16 ; Number of open sockets supported. Was 20 ; IPBUFF status values BUFF_EMPTY equ 0 @@ -94,7 +94,7 @@ ethernet_active equ stack_data + 9 ; TODO :: empty memory area ; Address of selected socket -sktAddr equ stack_data + 32 +;sktAddr equ stack_data + 32 ; Parameter to checksum routine - data ptr checkAdd1 equ stack_data + 36 ; Parameter to checksum routine - 2nd data ptr @@ -110,8 +110,8 @@ checkResult equ stack_data + 48 pseudoHeader equ stack_data + 50 ; receive and transmit IP buffer allocation -sockets equ stack_data + 62 -Next_free2 equ sockets + (SOCKETBUFFSIZE * NUM_SOCKETS) +;sockets equ stack_data + 62 +Next_free2 equ stack_data + 62;Next_free2 equ sockets + (SOCKETBUFFSIZE * NUM_SOCKETS) ; 1560 byte buffer for rx / tx ethernet packets Ether_buffer equ Next_free2 Next_free3 equ Ether_buffer + 1518 @@ -128,9 +128,14 @@ last_1hsTick equ queueList + ( 2 * NUMQUEUEENTRIES ) ;resendQ equ 0x770000 -resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP +;resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP ; XTODO: validate size +resendBuffer equ resendQ + ( 8 * NUMRESENDENTRIES ) ; for TCP +uglobal +net_sockets rd 2 +endg + ; simple macro for memory set operation macro _memset_dw adr,value,amount { @@ -151,9 +156,6 @@ macro _memset_dw adr,value,amount include "queue.inc" include "eth_drv/ethernet.inc" include "ip.inc" -include "icmp.inc" -include "tcp.inc" -include "udp.inc" include "socket.inc" ;*************************************************************************** @@ -171,7 +173,10 @@ include "socket.inc" stack_init: ; Init two address spaces with default values _memset_dw stack_data_start, 0, 0x20000/4 - _memset_dw resendQ, 0xFFFFFFFF, NUMRESENDENTRIES + _memset_dw resendQ, 0, NUMRESENDENTRIES * 2 + + mov [net_sockets], 0 + mov [net_sockets + 4], 0 ; Queries initialization call queueInit diff --git a/kernel/branches/kolibri_pe/network/tcp.inc b/kernel/branches/kolibri_pe/network/tcp.inc index 9b88503983..f27b5ffd04 100644 --- a/kernel/branches/kolibri_pe/network/tcp.inc +++ b/kernel/branches/kolibri_pe/network/tcp.inc @@ -15,6 +15,7 @@ ;; v0.6 : Added reset handling in the established state ;; ;; Added a timer per socket to allow delays when ;; ;; rx window gets below 1KB ;; +;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $Revision$ @@ -30,9 +31,16 @@ TCB_FIN_WAIT_2 equ 6 TCB_CLOSE_WAIT equ 7 TCB_CLOSING equ 8 TCB_LAST_ACK equ 9 -TCB_TIME_WAIT equ 10 +TCB_TIMED_WAIT equ 10 TCB_CLOSED equ 11 +TH_FIN = 0x01 +TH_SYN = 0x02 +TH_RST = 0x04 +TH_PUSH = 0x08 +TH_ACK = 0x10 +TH_URG = 0x20 + TWOMSL equ 10 ; # of secs to wait before closing socket TCP_RETRIES equ 5 ; Number of times to resend a packet @@ -102,62 +110,50 @@ end virtual ; when the TCB timer expires ; ;*************************************************************************** -tcp_tcb_handler: + +proc tcp_tcb_handler stdcall uses ebx ; scan through all the sockets, decrementing active timers - mov eax, SOCKETBUFFSIZE * NUM_SOCKETS - mov ecx, NUM_SOCKETS + mov ebx, net_sockets -tth1: - sub eax, SOCKETBUFFSIZE - cmp [eax + sockets + 32], dword 0 - jne tth2 + cmp [ebx + SOCKET.NextPtr], 0 + je .exit + DEBUGF 1, "K : sockets:\n" -tth1a: - cmp [eax + sockets + 72], dword 0 - jne tth4 + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .exit - loop tth1 - ret + DEBUGF 1, "K : %x: %x-%x-%x-%u\n", ebx, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState] -tth2: + cmp [ebx + SOCKET.TCBTimer], 0 + jne .decrement_tcb + cmp [ebx + SOCKET.wndsizeTimer], 0 + jne .decrement_wnd + jmp .next_socket + + .decrement_tcb: ; decrement it, delete socket if TCB timer = 0 & socket in timewait state - pusha - dec dword [eax + sockets + 32] - cmp [eax + sockets + 32], dword 0 - jne tth3 + dec [ebx + SOCKET.TCBTimer] + jnz .next_socket - cmp [eax + sockets + 28], dword TCB_TIME_WAIT - jne tth3 + cmp [ebx + SOCKET.TCBState], TCB_TIMED_WAIT + jne .next_socket - ; OK, delete socket - mov edi, eax - add edi, sockets - - xor eax, eax - mov ecx, SOCKETHEADERSIZE - cld - rep stosb - -tth3: - popa - - jmp tth1a - - loop tth1 - ret + push [ebx + SOCKET.PrevPtr] + stdcall net_socket_free, ebx + pop ebx + jmp .next_socket + .decrement_wnd: ; TODO - prove it works! -tth4: - dec dword [eax + sockets + 72] - loop tth1 - ret - - - - -tth_exit: + dec [ebx + SOCKET.wndsizeTimer] + jmp .next_socket + + .exit: ret +endp ;*************************************************************************** @@ -169,7 +165,8 @@ tth_exit: ; This is a kernel function, called by stack_handler ; ;*************************************************************************** -tcp_tx_handler: + +proc tcp_tx_handler stdcall ; decrement all resend buffers timers. If they ; expire, queue them for sending, and restart the timer. ; If the retries counter reach 0, delete the entry @@ -177,63 +174,60 @@ tcp_tx_handler: mov esi, resendQ mov ecx, 0 -tth001: + .next_resendq: cmp ecx, NUMRESENDENTRIES - je tth003 ; None left - cmp [esi], byte 0xFF - jne tth002 ; found one + je .exit ; None left + ;cmp [esi], byte 0xFF ; XTODO: 0xff -> 0 + cmp dword[esi + 4], 0 + jne @f ; found one inc ecx - add esi, 4 - jmp tth001 + add esi, 8 + jmp .next_resendq -tth002: - ; we have one. decrement it's timer by 1 - dec word [esi+2] - mov ax, [esi+2] - cmp ax, 0 - je tth002a + @@: ; we have one. decrement it's timer by 1 + dec word[esi + 2] + jz @f inc ecx - add esi, 4 - jmp tth001 ; Timer not zero, so move on + add esi, 8 + jmp .next_resendq ; Timer not zero, so move on -tth002a: - mov bl, 0xff + @@: + ;mov bl, 0xff ; XTODO: bl -> ebx, 0xff -> 0 + xor ebx, ebx ; restart timer, and decrement retries ; After the first resend, back of on next, by a factor of 5 - mov [esi+2], word TCP_TIMEOUT * 5 - dec byte [esi+1] - mov al, [esi+1] - cmp al, 0 - jne tth004 + mov [esi + 2], word TCP_TIMEOUT * 5 + dec byte[esi + 1] + jnz @f ; retries now 0, so delete from queue - xchg [esi], bl -tth004: + ;xchg [esi], bl ; XTODO: bl -> ebx + xchg [esi + 4], ebx - ; resend packet - pusha + @@: ; resend packet + pushad mov eax, EMPTY_QUEUE call dequeue cmp ax, NO_BUFFER - jne tth004z + jne .tth004z ; TODO - try again in 10ms. - cmp bl, 0xff - jne tth004za - mov [esi], bl + ;cmp bl, 0xff ; XTODO: 0xff -> 0 + test ebx, ebx + jnz @f + ;mov [esi], bl ; XTODO: bl -> ebx + mov [esi + 4], ebx -tth004za: - ; Mark it to expire in 10ms - 1 tick - mov [esi+1], byte 1 - mov [esi+2], word 1 - jmp tth005 + @@: ; Mark it to expire in 10ms - 1 tick + mov byte[esi + 1], 1 + mov word[esi + 2], 1 + jmp .tth005 -tth004z: + .tth004z: ; we have a buffer # in ax - push eax - push ecx + push eax ecx mov ecx, IPBUFFSIZE mul ecx add eax, IPbuffs @@ -241,20 +235,19 @@ tth004z: ; we have the buffer address in eax mov edi, eax pop ecx - ; get resend data address - inc ecx ; Now get buffer location, and copy buffer across. argh! more copying,, - mov esi, resendBuffer - IPBUFFSIZE -tth004a: - add esi, IPBUFFSIZE - loop tth004a + mov esi, resendBuffer + @@: add esi, IPBUFFSIZE + loop @b ; we have resend buffer location in esi mov ecx, IPBUFFSIZE ; copy data across + push edi cld rep movsb + pop edi ; queue packet @@ -263,28 +256,25 @@ tth004a: mov eax, NET1OUT_QUEUE mov edx, [stack_ip] - mov ecx, [ edi + 16 ] - cmp edx, ecx - jne tth004b + cmp edx, [edi + IP_PACKET.DestinationAddress] + jne .not_local mov eax, IPIN_QUEUE -tth004b: + .not_local: pop ebx call queue - -tth005: - popa + .tth005: + popad inc ecx - add esi, 4 - jmp tth001 + add esi, 8 + jmp .next_resendq -tth003: + .exit: ret - - +endp ;*************************************************************************** @@ -299,7 +289,8 @@ tth003: ; Free up (or re-use) IP buffer when finished ; ;*************************************************************************** -tcp_rx: + +proc tcp_rx stdcall uses ebx ; The process is as follows. ; Look for a socket with matching remote IP, remote port, local port ; if not found, then @@ -318,28 +309,38 @@ tcp_rx: ; IP Packet SA = Remote IP ; IP Packet TCP Source Port = remote Port - mov eax, SOCKETBUFFSIZE * NUM_SOCKETS - mov ecx, NUM_SOCKETS -ss1: - sub eax, SOCKETBUFFSIZE - movzx ebx, word [edx + 22] ; get the dest. port from the TCP hdr - cmp [eax + sockets + 12], bx ; compare with socket's local port - jnz nxttst1 ; different - try next socket + mov ebx, net_sockets - movzx ebx, word [edx + 20] ; get the source port from the TCP hdr - cmp [eax + sockets + 20], bx ; compare with socket's remote port - jnz nxttst1 ; different - try next socket + .next_socket.1: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .next_socket.1.exit + cmp [ebx + SOCKET.Status], SOCK_OPEN + jne .next_socket.1 - mov ebx, [edx + 12] ; get the source IP Addr from the IP hdr - cmp [eax + sockets + 16], ebx ; compare with socket's remote IP - jnz nxttst1 ; different - try next socket +; DEBUGF 1, "K : tcp_rx - 1.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 + + mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr + cmp [ebx + SOCKET.LocalPort], ax ; get the dest. port from the TCP hdr + jne .next_socket.1 ; different - try next socket + +; DEBUGF 1, "K : tcp_rx - 1.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] + + mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr + cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP + jne .next_socket.1 ; different - try next socket + +; DEBUGF 1, "K : tcp_rx - 1.sport: %x - %x\n", [edx + 20 + TCP_PACKET.SourcePort]:4, [ebx + SOCKET.RemotePort]:4 + + mov ax, [edx + 20 + TCP_PACKET.SourcePort] ; get the source port from the TCP hdr + cmp [ebx + SOCKET.RemotePort], ax ; compare with socket's remote port + jne .next_socket.1 ; different - try next socket ; We have a complete match - use this socket - jmp tcprx_001 + jmp .change_state -nxttst1: - loop ss1 ; Return back if no match + .next_socket.1.exit: ; If we got here, there was no match ; Look for a socket where @@ -347,29 +348,37 @@ nxttst1: ; IP Packet SA = Remote IP ; socket remote Port = 0 - mov eax, SOCKETBUFFSIZE * NUM_SOCKETS - mov ecx, NUM_SOCKETS + mov ebx, net_sockets -ss2: - sub eax, SOCKETBUFFSIZE + .next_socket.2: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .next_socket.2.exit - movzx ebx, word [edx + 22] ; get the dest. port from the TCP hdr - cmp [eax + sockets + 12], bx ; compare with socket's local port - jnz nxttst2 ; different - try next socket + cmp [ebx + SOCKET.Status], SOCK_OPEN + jne .next_socket.2 - mov ebx, [edx + 12] ; get the source IP Addr from the IP hdr - cmp [eax + sockets + 16], ebx ; compare with socket's remote IP - jnz nxttst2 ; different - try next socket +; DEBUGF 1, "K : tcp_rx - 2.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 - mov ebx, 0 - cmp [eax + sockets + 20], bx ; only match a remote socket of 0 - jnz nxttst2 ; different - try next socket + mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr + cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port + jne .next_socket.2 ; different - try next socket + +; DEBUGF 1, "K : tcp_rx - 2.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] + + mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr + cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP + jne .next_socket.2 ; different - try next socket + +; DEBUGF 1, "K : tcp_rx - 2.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 + + cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 + jne .next_socket.2 ; different - try next socket ; We have a complete match - use this socket - jmp tcprx_001 + jmp .change_state -nxttst2: - loop ss2 ; Return back if no match + .next_socket.2.exit: ; If we got here, there was no match ; Look for a socket where @@ -377,47 +386,69 @@ nxttst2: ; socket Remote IP = 0 ; socket remote Port = 0 - mov eax, SOCKETBUFFSIZE * NUM_SOCKETS - mov ecx, NUM_SOCKETS + mov ebx, net_sockets -ss3: - sub eax, SOCKETBUFFSIZE + .next_socket.3: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .next_socket.3.exit - movzx ebx, word [edx + 22] ; get destination port from the TCP hdr - cmp [eax + sockets + 12], bx ; compare with socket's local port - jnz nxttst3 ; different - try next socket + cmp [ebx + SOCKET.Status], SOCK_OPEN + jne .next_socket.3 - mov ebx, 0 - cmp [eax + sockets + 20], bx ; only match a remote socket of 0 - jnz nxttst3 ; different - try next socket +; DEBUGF 1, "K : tcp_rx - 3.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 - mov ebx, 0 - cmp [eax + sockets + 16], ebx ; only match a socket remote IP of 0 - jnz nxttst3 ; different - try next socket + mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get destination port from the TCP hdr + cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port + jne .next_socket.3 ; different - try next socket + +; DEBUGF 1, "K : tcp_rx - 3.addr: 00000000 - %x\n", [ebx + SOCKET.RemoteIP] + + cmp [ebx + SOCKET.RemoteIP], 0 ; only match a socket remote IP of 0 + jne .next_socket.3 ; different - try next socket + +; DEBUGF 1, "K : tcp_rx - 3.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 + + cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 + jne .next_socket.3 ; different - try next socket ; We have a complete match - use this socket - jmp tcprx_001 + jmp .change_state -nxttst3: - loop ss3 ; Return back if no match + .next_socket.3.exit: ; If we got here, we need to reject the packet - inc dword [dumped_rx_count] - jmp tcprx_exit -tcprx_001: + DEBUGF 1, "K : tcp_rx - dumped\n" + DEBUGF 1, "K : --------: %x-%x-%x (flags: %x)\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [edx + IP_PACKET.SourceAddress], [edx + 20 + TCP_PACKET.SourcePort]:4, [edx + 20 + TCP_PACKET.Flags]:2 +; mov ebx, net_sockets +; +; .next_socket.4: +; mov ebx, [ebx + SOCKET.NextPtr] +; or ebx, ebx +; jz .next_socket.4.exit +; DEBUGF 1, "K : %x: %x-%x-%x-%u\n", ebx, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState] +; jne .next_socket.4 +; +; .next_socket.4.exit: + inc [dumped_rx_count] + jmp .exit + + .change_state: + ; We have a valid socket/TCB, so call the TCB State Machine for that skt. - ; socket is pointed to by [eax + sockets] - ; IP packet is pointed to by [edx] + ; socket is pointed to by ebx + ; IP packet is pointed to by edx ; IP buffer number is on stack ( it will be popped at the end) - call tcpStateMachine -tcprx_exit: + stdcall tcpStateMachine, ebx + + .exit: pop eax call freeBuff ret - +endp ;*************************************************************************** @@ -434,7 +465,8 @@ tcprx_exit: ; Transmit buffer number in eax ; ;*************************************************************************** -buildTCPPacket: + +proc build_tcp_packet stdcall, sockAddr:DWORD push ecx ; Save data length ; convert buffer pointer eax to the absolute address @@ -444,106 +476,89 @@ buildTCPPacket: mov edx, eax - mov [edx + 33], bl ; TCP flags + mov [edx + 20 + TCP_PACKET.Flags], bl ; TCP flags - mov ebx, [sktAddr] + mov ebx, [sockAddr] ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr ; Fill in the IP header ( some data is in the socket descriptor) - mov eax, [ebx + 8] - mov [edx + 12], eax ; source IP - mov eax, [ebx + 16] - mov [edx + 16], eax ; Destination IP + mov eax, [ebx + SOCKET.LocalIP] + mov [edx + IP_PACKET.SourceAddress], eax + mov eax, [ebx + SOCKET.RemoteIP] + mov [edx + IP_PACKET.DestinationAddress], eax - mov al, 0x45 - mov [edx], al ; Version, IHL - xor al, al - mov [edx + 1], al ; Type of service + mov [edx + IP_PACKET.VersionAndIHL], 0x45 + mov [edx + IP_PACKET.TypeOfService], 0 pop eax ; Get the TCP data length push eax add eax, 20 + 20 ; add IP header and TCP header lengths - mov [edx + 2], ah - mov [edx + 3], al - xor al, al - mov [edx + 4], al - mov [edx + 5], al - mov al, 0x40 - mov [edx + 6], al - xor al, al - mov [edx + 7], al - mov al, 0x20 - mov [edx + 8], al - mov al, 6 ; TCP protocol - mov [edx + 9], al + rol ax, 8 + mov [edx + IP_PACKET.TotalLength], ax + mov [edx + IP_PACKET.Identification], 0 + mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040 + mov [edx + IP_PACKET.TimeToLive], 0x20 + mov [edx + IP_PACKET.Protocol], PROTOCOL_TCP ; Checksum left unfilled - xor ax, ax - mov [edx + 10], ax + mov [edx + IP_PACKET.HeaderChecksum], 0 - ; Fill in the TCP header ( some data is in the socket descriptor) - mov ax, [ebx + 12] - mov [edx + 20], ax ; Local Port + ; Fill in the TCP header (some data is in the socket descriptor) + mov ax, [ebx + SOCKET.LocalPort] + mov [edx + 20 + TCP_PACKET.SourcePort], ax ; Local Port - mov ax, [ebx + 20] - mov [edx + 20 + 2], ax ; desitination Port + mov ax, [ebx + SOCKET.RemotePort] + mov [edx + 20 + TCP_PACKET.DestinationPort], ax ; desitination Port ; Checksum left unfilled - xor ax, ax - mov [edx + 20 + 16], ax + mov [edx + 20 + TCP_PACKET.Checksum], 0 ; sequence number - mov eax, [ebx + 48] - mov [edx + 20 + 4], eax + mov eax, [ebx + SOCKET.SND_NXT] + mov [edx + 20 + TCP_PACKET.SequenceNumber], eax ; ack number - mov eax, [ebx + 56] - mov [edx + 20 + 8], eax + mov eax, [ebx + SOCKET.RCV_NXT] + mov [edx + 20 + TCP_PACKET.AckNumber], eax ; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size) ; 768 bytes seems better - mov ax, 0x0003 - mov [edx + 20 + 14], ax + mov [edx + 20 + TCP_PACKET.Window], 0x0003 ; Urgent pointer (0) - mov ax, 0 - mov [edx + 20 + 18], ax + mov [edx + 20 + TCP_PACKET.UrgentPointer], 0 ; data offset ( 0x50 ) - mov al, 0x50 - mov [edx + 20 + 12], al + mov [edx + 20 + TCP_PACKET.DataOffset], 0x50 pop ecx ; count of bytes to send mov ebx, ecx ; need the length later cmp ebx, 0 - jz btp_001 + jz @f mov edi, edx add edi, 40 cld rep movsb ; copy the data across -btp_001: - ; we have edx as IPbuffer ptr. + @@: ; we have edx as IPbuffer ptr. ; Fill in the TCP checksum ; First, fill in pseudoheader - mov eax, [edx + 12] + mov eax, [edx + IP_PACKET.SourceAddress] mov [pseudoHeader], eax - mov eax, [edx + 16] - mov [pseudoHeader+4], eax - mov ax, 0x0600 ; 0 + protocol - mov [pseudoHeader+8], ax + mov eax, [edx + IP_PACKET.DestinationAddress] + mov [pseudoHeader + 4], eax + mov word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0 add ebx, 20 - mov eax, ebx - mov [pseudoHeader+10], ah - mov [pseudoHeader+11], al + mov [pseudoHeader + 10], bh + mov [pseudoHeader + 11], bl mov eax, pseudoHeader mov [checkAdd1], eax - mov [checkSize1], word 12 + mov word[checkSize1], 12 mov eax, edx add eax, 20 mov [checkAdd2], eax @@ -554,94 +569,59 @@ btp_001: ; store it in the TCP checksum ( in the correct order! ) mov ax, [checkResult] - - mov [edx + 20 + 16], ah - mov [edx + 20 + 17], al + rol ax, 8 + mov [edx + 20 + TCP_PACKET.Checksum], ax ; Fill in the IP header checksum - GET_IHL eax,edx ; get IP-Header length - stdcall checksum_jb,edx,eax ; buf_ptr, buf_size - - mov [edx + 10], ah - mov [edx + 11], al + GET_IHL eax, edx ; get IP-Header length + stdcall checksum_jb, edx, eax ; buf_ptr, buf_size + rol ax, 8 + mov [edx + IP_PACKET.HeaderChecksum], ax ret +endp ; Increments the 32 bit value pointed to by esi in internet order -inc_inet_esi: +proc inc_inet_esi stdcall push eax - add esi, 3 - mov al, byte[esi] - inc al - mov byte[esi], al - cmp al, 0 - jnz iie_exit - dec esi - mov al, byte[esi] - inc al - mov byte[esi], al - cmp al, 0 - jnz iie_exit - dec esi - mov al, byte[esi] - inc al - mov byte[esi], al - cmp al, 0 - jnz iie_exit - dec esi - mov al, byte[esi] - inc al - mov byte[esi], al - -iie_exit: + mov eax, [esi] + bswap eax + inc eax + bswap eax + mov [esi], eax pop eax ret +endp ; Increments the 32 bit value pointed to by esi in internet order ; by the value in ecx -add_inet_esi: +proc add_inet_esi stdcall push eax - - mov al, [esi] - shl eax, 8 - inc esi - mov al, [esi] - shl eax, 8 - inc esi - mov al, [esi] - shl eax, 8 - inc esi - mov al, [esi] + mov eax, [esi] + bswap eax add eax, ecx - mov [esi], al - dec esi - shr eax, 8 - mov [esi], al - dec esi - shr eax, 8 - mov [esi], al - dec esi - shr eax, 8 - mov [esi], al + bswap eax + mov [esi], eax pop eax ret +endp iglobal - TCBStateHandler: - dd stateTCB_LISTEN - dd stateTCB_SYN_SENT - dd stateTCB_SYN_RECEIVED - dd stateTCB_ESTABLISHED - dd stateTCB_FIN_WAIT_1 - dd stateTCB_FIN_WAIT_2 - dd stateTCB_CLOSE_WAIT - dd stateTCB_CLOSING - dd stateTCB_LAST_ACK - dd stateTCB_TIME_WAIT - dd stateTCB_CLOSED + TCBStateHandler dd \ + stateTCB_LISTEN, \ + stateTCB_SYN_SENT, \ + stateTCB_SYN_RECEIVED, \ + stateTCB_ESTABLISHED, \ + stateTCB_FIN_WAIT_1, \ + stateTCB_FIN_WAIT_2, \ + stateTCB_CLOSE_WAIT, \ + stateTCB_CLOSING, \ + stateTCB_LAST_ACK, \ + stateTCB_TIME_WAIT, \ + stateTCB_CLOSED endg ;*************************************************************************** @@ -653,211 +633,186 @@ endg ; This is a kernel function, called by tcp_rx ; ; IP buffer address given in edx -; Socket/TCB address in [eax + sockets] +; Socket/TCB address in ebx ; ; The IP buffer will be released by the caller ;*************************************************************************** -tcpStateMachine: - mov ebx, sockets - add ebx, eax - mov [sktAddr], ebx +proc tcpStateMachine stdcall, sockAddr:DWORD ; as a packet has been received, update the TCB timer - mov ecx, TWOMSL - mov [ebx + 32], ecx + mov [ebx + SOCKET.TCBTimer], TWOMSL ; If the received packet has an ACK bit set, ; remove any packets in the resend queue that this ; received packet acknowledges - pusha - mov cl, [edx + 33] - and cl, 0x10 - cmp cl, 0x10 - jne tsm001 ; No ACK, so no data yet + pushad + test [edx + 20 + TCP_PACKET.Flags], TH_ACK + jz .call_handler ; No ACK, so no data yet - - ; get skt number in al - shr eax, 12 + ; get skt number in eax + stdcall net_socket_addr_to_num, ebx ; The ack number is in [edx + 28], inet format - ; skt in al + ; skt in eax mov esi, resendQ - mov ecx, 0 + xor ecx, ecx -t001: + .next_resendq: cmp ecx, NUMRESENDENTRIES - je t003 ; None left - cmp [esi], al - je t002 ; found one + je .call_handler ; None left + ;cmp [esi], al ; XTODO: al -> eax + cmp [esi + 4], eax + je @f ; found one inc ecx - add esi, 4 - jmp t001 + add esi, 8 + jmp .next_resendq -t002: ; Can we delete this buffer? + @@: ; Can we delete this buffer? - ; If yes, goto t004. No, goto t001 + ; If yes, goto @@. No, goto .next_resendq ; Get packet data address push ecx - inc ecx ; Now get buffer location, and copy buffer across. argh! more copying,, - mov edi, resendBuffer - IPBUFFSIZE -t002a: - add edi, IPBUFFSIZE - loop t002a + imul edi, ecx, IPBUFFSIZE + add edi, resendBuffer ; we have dest buffer location in edi. incoming packet in edx. ; Get this packets sequence number ; preserve al, ecx, esi, edx - - mov cl, [edi + 24] - shl ecx, 8 - mov cl, [edi + 25] - shl ecx, 8 - mov cl, [edi + 26] - shl ecx, 8 - mov cl, [edi + 27] - movzx ebx, byte [edi + 3] - mov bh, [edi + 2] + mov ecx, [edi + 20 + TCP_PACKET.SequenceNumber] + bswap ecx + movzx ebx, word[edi + 2] + xchg bl, bh sub ebx, 40 add ecx, ebx ; ecx is now seq# of last byte +1, intel format ; get recievd ack #, in intel format - mov bl, [edx + 28] - shl ebx, 8 - mov bl, [edx + 29] - shl ebx, 8 - mov bl, [edx + 30] - shl ebx, 8 - mov bl, [edx + 31] + mov ebx, [edx + 20 + TCP_PACKET.AckNumber] + bswap ebx cmp ebx, ecx ; Finally. ecx = rx'ed ack. ebx = last byte in que ; DANGER! need to handle case that we have just ; passed the 2**32, and wrapped round! pop ecx + jae @f ; if rx > old, delete old - jae t004 ; if rx > old, delete old inc ecx - add esi, 4 - jmp t001 + add esi, 8 + jmp .next_resendq - -t004: - dec dword [arp_rx_count] ; ************ TEST ONLY! - - mov [esi], byte 0xFF + ;@@: mov byte[esi], 0xff ; XTODO: 0xff -> 0 + @@: mov dword[esi + 4], 0 inc ecx - add esi, 4 - jmp t001 + add esi, 8 + jmp .next_resendq -t003: + .call_handler: + popad -tsm001: - popa + ; Call handler for given TCB state - ; Call handler for given TCB state - mov ebx, [eax + sockets+28] - cmp ebx, TCB_LISTEN - jb tsm_exit - cmp ebx, TCB_CLOSED - ja tsm_exit + mov eax, [ebx + SOCKET.TCBState] + cmp eax, TCB_LISTEN + jb .exit + cmp eax, TCB_CLOSED + ja .exit - dec ebx - call dword [TCBStateHandler+ebx*4] + stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr] -tsm_exit: + .exit: ret +endp - -stateTCB_LISTEN: +proc stateTCB_LISTEN stdcall, sockAddr:DWORD ; In this case, we are expecting a SYN packet ; For now, if the packet is a SYN, process it, and send a response ; If not, ignore it ; Look at control flags - mov bl, [edx + 33] - and bl, 0x02 - cmp bl, 0x02 - jnz stl_exit + test [edx + 20 + TCP_PACKET.Flags], TH_SYN + jz .exit ; We have a SYN. update the socket with this IP packets details, ; And send a response - mov ebx, [edx + 12] ; IP source address - mov [eax + sockets + 16], ebx - mov bx, [edx + 20] ; IP source port - mov [eax + sockets + 20], bx - mov ebx, [edx + 24] ; IRS - mov [eax + sockets + 40], ebx - mov [eax + sockets + 56], ebx - mov esi, sockets - add esi, eax - add esi, 56 + mov eax, [edx + IP_PACKET.SourceAddress] + mov [ebx + SOCKET.RemoteIP], eax + mov ax, [edx + 20 + TCP_PACKET.SourcePort] + mov [ebx + SOCKET.RemotePort], ax + mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] + mov [ebx + SOCKET.IRS], eax + mov [ebx + SOCKET.RCV_NXT], eax + lea esi, [ebx + SOCKET.RCV_NXT] call inc_inet_esi ; RCV.NXT - mov ebx, [eax + sockets + 36] ; ISS - mov [eax + sockets + 48], ebx ; SND.NXT + mov eax, [ebx + SOCKET.ISS] + mov [ebx + SOCKET.SND_NXT], eax ; Now construct the response, and queue for sending by IP mov eax, EMPTY_QUEUE call dequeue cmp ax, NO_BUFFER - je stl_exit + je .exit push eax - mov bl, 0x12 ; SYN + ACK - mov ecx, 0 - mov esi, 0 - - call buildTCPPacket + mov bl, TH_SYN + TH_ACK + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] mov eax, NET1OUT_QUEUE mov edx, [stack_ip] - mov ecx, [ sktAddr ] - mov ecx, [ ecx + 16 ] - cmp edx, ecx - jne stl_notlocal + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local mov eax, IPIN_QUEUE -stl_notlocal: + .not_local: ; Send it. pop ebx call queue + mov esi, [sockAddr] + mov [esi + SOCKET.TCBState], TCB_SYN_RECEIVED - mov ebx, TCB_SYN_RECEIVED - mov esi, [sktAddr] - mov [esi + 28], ebx - - ; increament SND.NXT in socket - add esi, 48 + ; increment SND.NXT in socket + add esi, SOCKET.SND_NXT call inc_inet_esi -stl_exit: + .exit: ret +endp - -stateTCB_SYN_SENT: +proc stateTCB_SYN_SENT stdcall, sockAddr:DWORD ; We are awaiting an ACK to our SYN, with a SYM ; Look at control flags - expecting an ACK - mov bl, [edx + 33] - and bl, 0x12 - cmp bl, 0x12 - jnz stss_exit - mov ebx, TCB_ESTABLISHED - mov esi, [sktAddr] - mov [esi + 28], ebx + mov al, [edx + 20 + TCP_PACKET.Flags] + and al, TH_SYN + TH_ACK + cmp al, TH_SYN + TH_ACK + je .syn_ack + test al, TH_SYN + jz .exit + + mov [ebx + SOCKET.TCBState], TCB_SYN_RECEIVED + push TH_SYN + TH_ACK + jmp .send + + .syn_ack: + mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED + push TH_ACK + + .send: ; Store the recv.nxt field - mov eax, [edx + 24] + mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] ; Update our recv.nxt field - mov esi, [sktAddr] - add esi, 56 - mov [esi], eax + mov [ebx + SOCKET.RCV_NXT], eax + lea esi, [ebx + SOCKET.RCV_NXT] call inc_inet_esi ; Send an ACK @@ -865,196 +820,174 @@ stateTCB_SYN_SENT: mov eax, EMPTY_QUEUE call dequeue cmp ax, NO_BUFFER - je stss_exit + pop ebx + je .exit push eax - mov bl, 0x10 ; ACK - mov ecx, 0 - mov esi, 0 - - call buildTCPPacket + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] mov eax, NET1OUT_QUEUE mov edx, [stack_ip] - mov ecx, [ sktAddr ] - mov ecx, [ ecx + 16 ] - cmp edx, ecx - jne stss_notlocal + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local mov eax, IPIN_QUEUE -stss_notlocal: + .not_local: ; Send it. pop ebx call queue -stss_exit: + .exit: ret +endp - -stateTCB_SYN_RECEIVED: +proc stateTCB_SYN_RECEIVED stdcall, sockAddr:DWORD ; In this case, we are expecting an ACK packet ; For now, if the packet is an ACK, process it, ; If not, ignore it + test [edx + 20 + TCP_PACKET.Flags], TH_RST ;xxx + jz .check_ack ;xxx + + push [ebx + SOCKET.OrigRemotePort] [ebx + SOCKET.OrigRemoteIP] + pop [ebx + SOCKET.RemoteIP] [ebx + SOCKET.RemotePort] + + mov [ebx + SOCKET.TCBState], TCB_LISTEN ;xxx + jmp .exit ;xxx + + .check_ack: ;xxx ; Look at control flags - expecting an ACK - mov bl, [edx + 33] - and bl, 0x10 - cmp bl, 0x10 - jnz stsr_exit + test [edx + 20 + TCP_PACKET.Flags], TH_ACK + jz .exit - mov ebx, TCB_ESTABLISHED - mov esi, [sktAddr] - mov [esi + 28], ebx + mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED -stsr_exit: + .exit: ret +endp - -stateTCB_ESTABLISHED: +proc stateTCB_ESTABLISHED stdcall, sockAddr:DWORD ; Here we are expecting data, or a request to close ; OR both... ; Did we receive a FIN or RST? - mov bl, [edx + 33] - and bl, 0x05 - cmp bl, 0 - je ste_chkack +;xxx test [edx + 20 + TCP_PACKET.Flags], TH_FIN + TH_RST +;xxx jz .check_ack + test [edx + 20 + TCP_PACKET.Flags], TH_FIN ;xxx + jz .check_ack ;xxx ; It was a fin or reset. ; Remove resend entries from the queue - I dont want to send any more data - pusha + pushad - mov ebx, [sktAddr] - sub ebx, sockets - shr ebx, 12 ; get skt # + ; get skt # + stdcall net_socket_addr_to_num, ebx mov esi, resendQ mov ecx, 0 -ste001: + .next_resendq: cmp ecx, NUMRESENDENTRIES - je ste003 ; None left - cmp [esi], bl - je ste002 ; found one + je .last_resendq ; None left + ;cmp [esi], al ; XTODO: al -> eax + cmp [esi + 4], eax + je @f ; found one + inc ecx + add esi, 8 + jmp .next_resendq + + ;@@: mov byte[esi], 0xff ; XTODO: 0xff -> 0 + @@: mov dword[esi + 4], 0 inc ecx - add esi, 4 - jmp ste001 + add esi, 8 + jmp .next_resendq -ste002: - dec dword [arp_rx_count] ; ************ TEST ONLY! + .last_resendq: + popad - mov [esi], byte 0xFF - jmp ste001 +;xxx ; was it a reset? +;xxx test [edx + 20 + TCP_PACKET.Flags], TH_RST +;xxx jz @f -ste003: - popa +;xxx mov [ebx + SOCKET.TCBState], TCB_CLOSED +;xxx jmp .exit - ; was it a reset? - mov bl, [edx + 33] - and bl, 0x04 - cmp bl, 0x04 - jne ste003a + @@: ; Send an ACK to that fin, and enter closewait state - mov esi, [sktAddr] - mov ebx, TCB_CLOSED - mov [esi + 28], ebx - jmp ste_exit - -ste003a: - ; Send an ACK to that fin, and enter closewait state - - mov esi, [sktAddr] - mov ebx, TCB_CLOSE_WAIT - mov [esi + 28], ebx - add esi, 56 + mov [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT + lea esi, [ebx + SOCKET.RCV_NXT] mov eax, [esi] ; save original call inc_inet_esi ;; jmp ste_ack - NO, there may be data -ste_chkack: + .check_ack: ; Check that we received an ACK - mov bl, [edx + 33] - and bl, 0x10 - cmp bl, 0x10 - jnz ste_exit - + test [edx + 20 + TCP_PACKET.Flags], TH_ACK + jz .exit ; TODO - done, I think! ; First, look at the incoming window. If this is less than or equal to 1024, - ; Set the socket window timer to 1. This will stop an additional packets being - ; queued. + ; Set the socket window timer to 1. This will stop an additional packets being queued. ; ** I may need to tweak this value, since I do not know how many packets are already queued - mov ch, [edx + 34] - mov cl, [edx + 35] + mov cx, [edx + 20 + TCP_PACKET.Window] + xchg cl, ch cmp cx, 1024 - ja ste004 + ja @f - mov ecx, [sktAddr] - mov [ecx+72], dword 1 + mov [ebx + SOCKET.wndsizeTimer], 1 -ste004: - - ; OK, here is the deal + @@: ; OK, here is the deal ; My recv.nct field holds the seq of the expected next rec byte ; if the recevied sequence number is not equal to this, do not ; increment the recv.nxt field, do not copy data - just send a ; repeat ack. - ; recv.nxt is in dword [edx+24], in inext format + ; recv.nxt is in dword [edx+24], in inet format ; recv seq is in [sktAddr]+56, in inet format ; just do a comparision - mov ecx, [sktAddr] - add ecx, 56 - - cmp [ecx - 56 + 28], dword TCB_CLOSE_WAIT - mov ecx, [ecx] - jne stenofin + mov ecx, [ebx + SOCKET.RCV_NXT] + cmp [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT + jne @f mov ecx, eax -stenofin: - cmp ecx, [edx+24] - jne ste_ack + @@: cmp ecx, [edx + 20 + TCP_PACKET.SequenceNumber] + jne .ack ; Read the data bytes, store in socket buffer - xor ecx, ecx - mov ch, [edx + 2] - mov cl, [edx + 3] + movzx ecx, [edx + IP_PACKET.TotalLength] + xchg cl, ch sub ecx, 40 ; Discard 40 bytes of header - - cmp ecx, 0 - jnz ste_data ; Read data, if any + jnz .data ; Read data, if any ; If we had received a fin, we need to ACK it. - mov esi, [sktAddr] - mov ebx, [esi + 28] - cmp ebx, TCB_CLOSE_WAIT - jz ste_ack - jnz ste_exit + cmp [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT + je .ack + jmp .exit -ste_data: + .data: push ecx - mov esi, [sktAddr] - add [esi + 24], ecx ; increment the count of bytes in buffer + add [ebx + SOCKET.rxDataCount], ecx ; increment the count of bytes in buffer - mov eax, [esi + 4] ; get socket owner PID + mov eax, [ebx + SOCKET.PID] ; get socket owner PID push eax - mov eax, [esi + 24] ; get # of bytes already in buffer + mov eax, [ebx + SOCKET.rxDataCount] ; get # of bytes already in buffer ; point to the location to store the data - add esi, eax - sub esi, ecx - add esi, SOCKETHEADERSIZE + lea edi, [ebx + eax + SOCKETHEADERSIZE] + sub edi, ecx add edx, 40 ; edx now points to the data - mov edi, esi mov esi, edx cld @@ -1062,242 +995,194 @@ ste_data: ; flag an event to the application pop eax - mov ecx,1 - mov esi,TASK_DATA+TASKDATA.pid + mov ecx, 1 + mov esi, TASK_DATA + TASKDATA.pid -news: - cmp [esi],eax - je foundPID1 + .next_pid: + cmp [esi], eax + je .found_pid inc ecx - add esi,0x20 - cmp ecx,[TASK_COUNT] - jbe news + add esi, 0x20 + cmp ecx, [TASK_COUNT] + jbe .next_pid -foundPID1: - shl ecx,8 - or dword [ecx+SLOT_BASE+APPDATA.event_mask],dword 10000000b ; stack event + .found_pid: + shl ecx, 8 + or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event pop ecx ; Update our recv.nxt field - mov esi, [sktAddr] - add esi, 56 + lea esi, [ebx + SOCKET.RCV_NXT] call add_inet_esi -ste_ack: + .ack: ; Send an ACK ; Now construct the response, and queue for sending by IP mov eax, EMPTY_QUEUE call dequeue cmp ax, NO_BUFFER - je ste_exit + je .exit push eax - mov bl, 0x10 ; ACK - mov ecx, 0 - mov esi, 0 - - call buildTCPPacket + mov bl, TH_ACK + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] mov eax, NET1OUT_QUEUE mov edx, [stack_ip] - mov ecx, [ sktAddr ] - mov ecx, [ ecx + 16 ] - cmp edx, ecx - jne ste_notlocal + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local mov eax, IPIN_QUEUE -ste_notlocal: + .not_local: ; Send it. pop ebx call queue -ste_exit: + .exit: ret +endp +proc stateTCB_FIN_WAIT_1 stdcall, sockAddr:DWORD + ; We can either receive an ACK of a fin, or a fin + mov al, [edx + 20 + TCP_PACKET.Flags] + and al, TH_FIN + TH_ACK -stateTCB_FIN_WAIT_1: - ; We can either receive an ACK of a fin, or a fin - mov bl, [edx + 33] - and bl, 0x10 - cmp bl, 0x10 - jnz stfw1_001 + cmp al, TH_ACK + jne @f ; It was an ACK - mov esi, [sktAddr] - mov ebx, TCB_FIN_WAIT_2 - mov [esi + 28], ebx - jmp stfw1_exit + mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_2 + jmp .exit -stfw1_001: - ; It must be a fin then - mov esi, [sktAddr] - mov ebx, TCB_CLOSING - mov [esi + 28], ebx - add esi, 56 + @@: mov [ebx + SOCKET.TCBState], TCB_CLOSING + cmp al, TH_FIN + je @f + mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT + + @@: lea esi, [ebx + SOCKET.RCV_NXT] call inc_inet_esi ; Send an ACK mov eax, EMPTY_QUEUE call dequeue cmp ax, NO_BUFFER - je stfw1_exit + je .exit push eax - mov bl, 0x10 ; ACK - mov ecx, 0 - mov esi, 0 + mov bl, TH_ACK + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] - call buildTCPPacket mov eax, NET1OUT_QUEUE mov edx, [stack_ip] - mov ecx, [ sktAddr ] - mov ecx, [ ecx + 16 ] - cmp edx, ecx - jne stfw1_notlocal + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local mov eax, IPIN_QUEUE -stfw1_notlocal: + .not_local: ; Send it. pop ebx call queue -stfw1_exit: + .exit: ret +endp - -stateTCB_FIN_WAIT_2: - mov esi, [sktAddr] - - ; Get data length - xor ecx, ecx - mov ch, [edx+2] - mov cl, [edx+3] - sub ecx, 40 - - mov bl, [edx + 33] - and bl, 0x01 - cmp bl, 0x01 - jne stfw2001 +proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD + test [edx + 20 + TCP_PACKET.Flags], TH_FIN + jz .exit ; Change state, as we have a fin - mov ebx, TCB_TIME_WAIT - mov [esi + 28], ebx + mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT - inc ecx ; FIN is part of the sequence space - -stfw2001: - add esi, 56 - call add_inet_esi + lea esi, [ebx + SOCKET.RCV_NXT] + call inc_inet_esi ; Send an ACK mov eax, EMPTY_QUEUE call dequeue cmp ax, NO_BUFFER - je stfw2_exit + je .exit push eax - mov bl, 0x10 ; ACK - mov ecx, 0 - mov esi, 0 - - call buildTCPPacket + mov bl, TH_ACK + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] mov eax, NET1OUT_QUEUE mov edx, [stack_ip] - mov ecx, [ sktAddr ] - mov ecx, [ ecx + 16 ] - cmp edx, ecx - jne stfw2_notlocal + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local mov eax, IPIN_QUEUE -stfw2_notlocal: + .not_local: ; Send it. pop ebx call queue - ; Only delete the socket if we received the FIN - - mov edx, [sktAddr] - mov bl, [edx + 33] - and bl, 0x01 - cmp bl, 0x01 - jne stfw2_exit - -; mov edi, [sktAddr] - - ; delete the socket. Should really wait for 2MSL -; xor eax, eax -; mov ecx,SOCKETHEADERSIZE -; cld -; rep stosb - -stfw2_exit: + .exit: ret +endp - -stateTCB_CLOSE_WAIT: +proc stateTCB_CLOSE_WAIT stdcall, sockAddr:DWORD ; Intentionally left empty ; socket_close_tcp handles this ret +endp - -stateTCB_CLOSING: +proc stateTCB_CLOSING stdcall, sockAddr:DWORD ; We can either receive an ACK of a fin, or a fin - mov bl, [edx + 33] - and bl, 0x10 - cmp bl, 0x10 - jnz stc_exit + test [edx + 20 + TCP_PACKET.Flags], TH_ACK + jz .exit - ; It was an ACK + mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT - mov edi, [sktAddr] - - ; delete the socket - xor eax, eax - mov ecx,SOCKETHEADERSIZE - cld - rep stosb - -stc_exit: + .exit: ret +endp - -stateTCB_LAST_ACK: +proc stateTCB_LAST_ACK stdcall, sockAddr:DWORD ; Look at control flags - expecting an ACK - mov bl, [edx + 33] - and bl, 0x10 - cmp bl, 0x10 - jnz stla_exit - - mov edi, [sktAddr] + test [edx + 20 + TCP_PACKET.Flags], TH_ACK + jz .exit ; delete the socket - xor eax, eax - mov ecx,SOCKETHEADERSIZE - cld - rep stosb + stdcall net_socket_free, ebx +; mov edi, ebx +; xor eax, eax +; mov ecx, SOCKETHEADERSIZE +; cld +; rep stosb -stla_exit: + .exit: ret +endp - -stateTCB_TIME_WAIT: +proc stateTCB_TIME_WAIT stdcall, sockAddr:DWORD ret +endp - -stateTCB_CLOSED: +proc stateTCB_CLOSED stdcall, sockAddr:DWORD ret +endp diff --git a/kernel/branches/kolibri_pe/network/udp.inc b/kernel/branches/kolibri_pe/network/udp.inc index a6416c37f7..b0939df3b3 100644 --- a/kernel/branches/kolibri_pe/network/udp.inc +++ b/kernel/branches/kolibri_pe/network/udp.inc @@ -71,7 +71,8 @@ end virtual ; Free up (or re-use) IP buffer when finished ; ;*************************************************************************** -udp_rx: + +proc udp_rx stdcall push eax ; First validate the header & checksum. Discard buffer if error @@ -80,94 +81,81 @@ udp_rx: ; IP Packet UDP Destination Port = local Port ; IP Packet SA = Remote IP - movzx ebx, word [edx + 22] ; get the local port from + mov ax, [edx + 20 + UDP_PACKET.DestinationPort] ; get the local port from ; the IP packet's UDP header - mov eax, SOCKETBUFFSIZE * NUM_SOCKETS - mov ecx, NUM_SOCKETS -fs1: - sub eax, SOCKETBUFFSIZE - cmp [eax + sockets + 12], bx ; bx will hold the 'wrong' value, + mov ebx, net_sockets + + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .exit ; No match, so exit + cmp [ebx + SOCKET.LocalPort], ax ; ax will hold the 'wrong' value, ; but the comparision is correct - loopnz fs1 ; Return back if no match - jz fs_done + jne .next_socket ; Return back if no match - ; No match, so exit - jmp udprx_001 - -fs_done: ; For dhcp, we must allow any remote server to respond. ; I will accept the first incoming response to be the one ; I bind to, if the socket is opened with a destination IP address of ; 255.255.255.255 - mov ebx, [eax + sockets + 16] - cmp ebx, 0xffffffff - je udprx_002 + cmp [ebx + SOCKET.RemoteIP], 0xffffffff + je @f - mov ebx, [edx + 12] ; get the Source address from the IP packet - cmp [eax + sockets + 16], ebx - jne udprx_001 ; Quit if the source IP is not valid + mov eax, [edx + IP_PACKET.SourceAddress] ; get the Source address from the IP packet + cmp [ebx + SOCKET.RemoteIP], ebx + jne .exit ; Quit if the source IP is not valid -udprx_002: - ; OK - we have a valid UDP packet for this socket. + @@: ; OK - we have a valid UDP packet for this socket. ; First, update the sockets remote port number with the incoming msg ; - it will have changed ; from the original ( 69 normally ) to allow further connects - movzx ebx, word [edx + 20] ; get the UDP source port + mov ax, [edx + 20 + UDP_PACKET.SourcePort] ; get the UDP source port ; ( was 69, now new ) - mov [eax + sockets + 20], bx + mov [ebx + SOCKET.RemotePort], ax ; Now, copy data to socket. We have socket address as [eax + sockets]. ; We have IP packet in edx ; get # of bytes in ecx - movzx ecx, byte [edx + 3] ; total length of IP packet. Subtract - mov ch, byte [edx + 2] ; 20 + 8 gives data length + movzx ecx, [edx + IP_PACKET.TotalLength] ; total length of IP packet. Subtract + xchg cl, ch ; 20 + 8 gives data length sub ecx, 28 - mov ebx, eax - add ebx, sockets ; ebx = address of actual socket + mov eax, [ebx + SOCKET.rxDataCount] ; get # of bytes already in buffer + add [ebx + SOCKET.rxDataCount], ecx ; increment the count of bytes in buffer - mov eax, [ebx+ 4] ; get socket owner PID - push eax - - mov eax, [ebx + 24] ; get # of bytes already in buffer - add [ebx + 24], ecx ; increment the count of bytes in buffer - - ; point to the location to store the data - add ebx, eax - add ebx, SOCKETHEADERSIZE - - ; ebx = location for first byte, ecx has count, - ; edx points to data + ; ecx has count, edx points to data add edx, 28 ; edx now points to the data - mov edi, ebx + lea edi, [ebx + eax + SOCKETHEADERSIZE] mov esi, edx cld rep movsb ; copy the data across ; flag an event to the application - pop eax - mov ecx,1 - mov esi,TASK_DATA+TASKDATA.pid + mov eax, [ebx + SOCKET.PID] ; get socket owner PID + mov ecx, 1 + mov esi, TASK_DATA + TASKDATA.pid -newsearch: - cmp [esi],eax - je foundPID + .next_pid: + cmp [esi], eax + je .found_pid inc ecx - add esi,0x20 - cmp ecx,[TASK_COUNT] - jbe newsearch + add esi, 0x20 + cmp ecx, [TASK_COUNT] + jbe .next_pid -foundPID: - shl ecx,8 - or dword [ecx+SLOT_BASE+APPDATA.event_mask],dword 10000000b ; stack event + jmp .exit - mov [check_idle_semaphore],200 + .found_pid: + shl ecx, 8 + or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event -udprx_001: + mov [check_idle_semaphore], 200 + + .exit: pop eax call freeBuff ; Discard the packet ret +endp diff --git a/kernel/branches/kolibri_pe/video/vesa12.inc b/kernel/branches/kolibri_pe/video/vesa12.inc index ebe2fe3fba..e02293cd12 100644 --- a/kernel/branches/kolibri_pe/video/vesa12.inc +++ b/kernel/branches/kolibri_pe/video/vesa12.inc @@ -880,6 +880,14 @@ vesa12_putimage: add edi,[BytesPerScanLine] add esi,[esp+32] + cmp ebp,putimage_get1bpp + jz .correct + cmp ebp,putimage_get4bpp + jnz @f +.correct: + mov eax,[esp+20] + mov byte[eax],80h +@@: dec ebx jnz newpi12 @@ -945,6 +953,14 @@ vesa12_putimage: pop edi add edi,[BytesPerScanLine] + cmp ebp,putimage_get1bpp + jz .correct + cmp ebp,putimage_get4bpp + jnz @f +.correct: + mov eax,[esp+20] + mov byte[eax],80h +@@: dec ebx jnz newpi3212 diff --git a/kernel/branches/kolibri_pe/video/vesa20.inc b/kernel/branches/kolibri_pe/video/vesa20.inc index b87d23586b..d4c4ae440d 100644 --- a/kernel/branches/kolibri_pe/video/vesa20.inc +++ b/kernel/branches/kolibri_pe/video/vesa20.inc @@ -163,7 +163,8 @@ vesa20_putimage: mov [putimg.real_sy], ebx ; line increment mov eax, [putimg.image_sx] - sub eax, [putimg.real_sx] + mov ecx, [putimg.real_sx] + sub eax, ecx ;; imul eax, [putimg.source_bpp] ; lea eax, [eax + eax * 2] call esi @@ -176,7 +177,6 @@ vesa20_putimage: mov [putimg.winmap_newline], eax ; screen new line increment mov eax, [BytesPerScanLine] - mov ecx, [putimg.real_sx] movzx ebx, byte [ScreenBPP] shr ebx, 3 imul ecx, ebx @@ -232,6 +232,14 @@ align 4 add edx, [putimg.screen_newline] ;[BytesPerScanLine] add ebp, [putimg.winmap_newline] ;[Screen_Max_X] ; inc ebp + cmp [putimg.ebp], putimage_get1bpp + jz .correct + cmp [putimg.ebp], putimage_get4bpp + jnz @f +.correct: + mov eax, [putimg.edi] + mov byte [eax], 80h +@@: dec edi jnz .new_line .finish: @@ -265,6 +273,14 @@ align 4 add edx, [putimg.screen_newline] ;[BytesPerScanLine] add ebp, [putimg.winmap_newline] ;[Screen_Max_X] ; inc ebp + cmp [putimg.ebp], putimage_get1bpp + jz .correct + cmp [putimg.ebp], putimage_get4bpp + jnz @f +.correct: + mov eax, [putimg.edi] + mov byte [eax], 80h +@@: dec edi jnz .new_line .finish: