/kernel/branches/kolibri_pe/core/dll.c |
---|
277,12 → 277,13 |
( 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); |
289,6 → 290,9 |
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 |
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 |
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,19 → 415,27 |
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(); |
if (! link_pe(0)) |
430,6 → 445,7 |
"int $0x40"::"a"(-1)); |
}; |
// __asm__ __volatile__ ( |
// "xchgw %bx, %bx"); |
481,7 → 497,7 |
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 |
return NULL; |
}; |
create_image(img_base, (addr_t)raw); |
create_image(img_base, (addr_t)raw, false); |
mem_free(raw); |
609,6 → 625,7 |
{ |
PIMAGE_IMPORT_BY_NAME ord; |
addr_t addr; |
*iat=0; |
if ( thunk->u1.AddressOfData == 0 ) |
break; |
615,7 → 632,9 |
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 |
622,7 → 641,6 |
{ |
ord = MakePtr(PIMAGE_IMPORT_BY_NAME, |
thunk->u1.AddressOfData, img_base); |
*iat=0; |
DBG("import %s", ord->Name); |
639,7 → 657,7 |
{ |
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; |
}; |
/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 |
/kernel/branches/kolibri_pe/core/heap.inc |
---|
32,20 → 32,20 |
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 |
/kernel/branches/kolibri_pe/core/pe.c |
---|
40,7 → 40,6 |
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 |
}; |
*/ |
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 |
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 |
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 |
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 |
*/ |
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 |
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) |
{ |
/kernel/branches/kolibri_pe/core/taskman.inc |
---|
146,11 → 146,12 |
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 |
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 |
mov eax, [save_cr3] |
call set_cr3 |
mov eax,[process_number] ;set result |
mov [application_table_status], 0 ;unlock application_table_status mutex |
mov eax,[process_number] ;set result |
pop edi |
pop esi |
433,8 → 434,8 |
DEBUGF 1,"%s",new_process_running |
.err: |
mov eax,[process_number] ;set result |
mov [application_table_status], 0 ;unlock application_table_status mutex |
mov eax,[process_number] ;set result |
pop edi |
pop esi |
/kernel/branches/kolibri_pe/docs/sysfuncr.txt |
---|
3402,9 → 3402,9 |
* 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 |
* ®®à¤¨ âë ¨§®¡à ¦¥¨ï - íâ® ª®®à¤¨ âë ¢¥à奣® «¥¢®£® 㣫 |
¨§®¡à ¦¥¨ï ®â®á¨â¥«ì® ®ª . |
* §¬¥à ¨§®¡à ¦¥¨ï ¢ ¡ ©â å ¥áâì xsize*ysize. |
* ®à¬ â ¨§®¡à ¦¥¨ï á 1 ¡¨â®¬ ¯¨ªá¥«ì: ª ¦¤ë© ¡ ©â ¨§®¡à ¦¥¨ï, |
§ ¨áª«î票¥¬, ¡ëâì ¬®¦¥â, ¯®á«¥¤¨å ¡ ©â®¢ áâப, ᮤ¥à¦¨â |
¨ä®à¬ æ¨î ® 梥⥠8 ¯¨ªá¥«¥©, áâ à訩 ¡¨â ᮮ⢥âáâ¢ã¥â ¯¥à¢®¬ã |
¯¨ªá¥«î. |
* ®à¬ â ¨§®¡à ¦¥¨ï á 4 ¡¨â ¬¨ ¯¨ªá¥«ì: ª ¦¤ë© ¡ ©â ¨§®¡à ¦¥¨ï, |
§ ¨áª«î票¥¬ ¯®á«¥¤¨å ¡ ©â®¢ áâப (¥á«¨ è¨à¨ ¨§®¡à ¦¥¨ï |
¥çñâ ), ᮤ¥à¦¨â ¨ä®à¬ æ¨î ® 梥⥠2 ¯¨ªá¥«¥©, áâ àè ï â¥âà ¤ |
ᮮ⢥âáâ¢ã¥â ¯¥à¢®¬ã ¯¨ªá¥«î. |
* ®à¬ â ¨§®¡à ¦¥¨ï á 8 ¡¨â ¬¨ ¯¨ªá¥«ì: ª ¦¤ë© ¡ ©â ¨§®¡à ¦¥¨ï |
à áᬠâਢ ¥âáï ª ª ¨¤¥ªá ¢ ¯ «¨âà¥. |
* ᫨ ¨§®¡à ¦¥¨¥ ¨á¯®«ì§ã¥â ¥ ¢á¥ 256 梥⮢, ¬¥ìè¥, |
à §¬¥à ¯ «¨âàë ¬®¦¥â ¡ëâì ¬¥ìè¥ 256. |
* ®à¬ â ¨§®¡à ¦¥¨ï á 16 ¡¨â ¬¨ ¯¨ªá¥«ì: 梥⠪ ¦¤®£® ¯¨ªá¥«ï |
* ®à¬ â ¨§®¡à ¦¥¨ï á 15 ¡¨â ¬¨ ¯¨ªá¥«ì: 梥⠪ ¦¤®£® ¯¨ªá¥«ï |
ª®¤¨àã¥âáï ª ª (¢ ¡¨â®¢®¬ ¯à¥¤áâ ¢«¥¨¨) 0RRRRRGGGGGBBBBB - |
¯® 5 ¯¨ªá¥«¥© ª ¦¤ë© 梥â. |
* ®à¬ â ¨§®¡à ¦¥¨ï á 16 ¡¨â ¬¨ ¯¨ªá¥«ì: 梥⠪ ¦¤®£® ¯¨ªá¥«ï |
ª®¤¨àã¥âáï ª ª RRRRRGGGGGGBBBBB (á奬 5+6+5). |
* ®à¬ â ¨§®¡à ¦¥¨ï á 24 ¡¨â ¬¨ ¯¨ªá¥«ì: 梥⠪ ¦¤®£® ¯¨ªá¥«ï |
ª®¤¨àã¥âáï âà¥¬ï ¡ ©â ¬¨ - ¯®á«¥¤®¢ â¥«ì® á¨ïï, §¥«ñ ï, |
ªà á ï á®áâ ¢«ïî騥 梥â . |
/kernel/branches/kolibri_pe/drivers/ati2d.asm |
---|
1195,62 → 1195,186 |
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 (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 (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 0 ;terminator |
version dd (5 shl 16) or (API_VERSION and 0xFFFF) |
/kernel/branches/kolibri_pe/drivers/r500hw.inc |
---|
5,6 → 5,10 |
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 <lverhaegen@novell.com> |
Copyright 2008 Matthias Hopf <mhopf@novell.com> |
Copyright 2008 Egbert Eich <eich@novell.com> |
662,7 → 666,7 |
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 |
/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. |
/kernel/branches/kolibri_pe/fs/fs_lfn.inc |
---|
432,11 → 432,12 |
push ebx |
call _sys_exec |
add esp, 12 |
mov [image_of_eax], eax |
add esp, 12 |
ret |
; handlers for devices |
; in: ecx = 0 => query virtual directory /xxx |
; in: ecx = partition number |
/kernel/branches/kolibri_pe/include/pe.h |
---|
46,6 → 46,10 |
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,6 → 196,7 |
#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); |
198,6 → 203,6 |
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"); |
/kernel/branches/kolibri_pe/kernel.asm |
---|
4314,6 → 4314,30 |
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 |
4321,6 → 4345,12 |
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 |
mov ebp, putimage_get16bpp |
4342,15 → 4372,28 |
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 |
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,8 → 4491,27 |
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 |
; ecx x end |
/kernel/branches/kolibri_pe/makefile |
---|
46,6 → 46,7 |
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,\ |
/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 |
/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 |
; 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,7 → 524,7 |
; 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 |
531,13 → 531,13 |
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 |
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 |
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 |
; 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 |
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 |
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 |
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,7 → 716,7 |
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 |
723,7 → 723,7 |
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 |
730,7 → 730,7 |
@@: RTL_R32 RTL8169_REG_PHYAR |
test eax,0x80000000 |
jz .exit |
stdcall udelay,100 |
stdcall udelay,1 ;;;100 |
loop @b |
.exit: |
ret |
738,7 → 738,7 |
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] |
745,7 → 745,7 |
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 |
752,7 → 752,7 |
@@: 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 |
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 |
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 |
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 |
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 |
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 |
;*************************************************************************** |
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 |
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 |
;*************************************************************************** |
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 |
;*************************************************************************** |
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 |
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 |
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 |
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 |
@@: 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] |
/kernel/branches/kolibri_pe/network/eth_drv/ethernet.inc |
---|
104,6 → 104,7 |
include "drivers/sis900.inc" |
include "drivers/pcnet32.inc" |
include "drivers/rtl8169.inc" |
include "drivers/forcedeth.inc" |
; PCICards |
; ======== |
153,6 → 154,7 |
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 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 |
; 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 |
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 |
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 |
/kernel/branches/kolibri_pe/network/ip.inc |
---|
87,6 → 87,10 |
} |
include "tcp.inc" |
include "udp.inc" |
include "icmp.inc" |
;*************************************************************************** |
; Function |
; ip_rx |
114,11 → 118,13 |
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,9 → 133,13 |
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] |
cmp dword[ebx + IP_PACKET.DestinationAddress], eax |
137,22 → 147,37 |
; 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 |
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,7 → 194,7 |
.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 |
176,9 → 201,9 |
.not_udp: |
cmp al , PROTOCOL_ICMP |
jne .dump ;protocol ain't supported |
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 |
185,13 → 210,32 |
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 |
.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 |
.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, dword[buffer_number] |
mov eax, [buffer_number] |
call freeBuff |
.exit: |
/kernel/branches/kolibri_pe/network/queue.inc |
---|
43,18 → 43,19 |
; 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 |
; 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 |
; all other registers preserved |
; |
;*************************************************************************** |
uglobal |
dequeue_cnt dd ? |
endg |
dequeue: |
push ebx |
shl eax, 1 |
164,6 → 173,8 |
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 |
/kernel/branches/kolibri_pe/network/socket.inc |
---|
77,21 → 77,23 |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
; 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 |
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 |
; 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 |
dec al ; return 'in use' |
;*************************************************************************** |
; 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: |
.exit: |
ret |
endp |
;*************************************************************************** |
199,18 → 287,16 |
; 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,18 → 305,18 |
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 |
;*************************************************************************** |
; Function |
; socket_open_tcp |
245,94 → 331,111 |
; 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 |
@@: mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB |
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 |
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 |
mov bl, TH_SYN |
xor ecx, ecx |
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 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 |
;*************************************************************************** |
; Function |
; socket_close |
342,26 → 445,33 |
; 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 |
;*************************************************************************** |
; Function |
; socket_close_tcp |
371,7 → 481,9 |
; 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 |
378,105 → 490,113 |
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 |
sct003: |
.last_resendq: |
popa |
Index2RealAddr ebx |
mov [sktAddr], ebx |
mov eax, 0xFFFFFFFF ; assume this operation will fail.. |
cmp [ebx + SOCKET.Status], dword SOCK_EMPTY |
jz sct_exit |
stdcall net_socket_num_to_addr, ebx |
or eax, eax |
jz .error |
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 |
;xxx mov bl, TH_FIN + TH_ACK |
mov bl, TH_FIN ;xxx |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_packet, [sockAddr] |
call buildTCPPacket |
mov ebx, [sktAddr] |
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 |
;*************************************************************************** |
; Function |
; socket_poll |
486,12 → 606,20 |
; 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,14 → 631,27 |
; 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 |
;*************************************************************************** |
; Function |
; socket_read |
520,12 → 661,16 |
; 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 |
537,18 → 682,19 |
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 |
; 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,33 → 743,36 |
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 |
retn ; exit, or go back to shift remaining bytes if any |
endp |
.exit: |
ret ; exit, or go back to shift remaining bytes if any |
;*************************************************************************** |
; Function |
; socket_write |
631,19 → 785,22 |
; 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 eax, 0xFFFFFFFF |
mov ebx, eax |
; 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 |
662,55 → 819,46 |
; 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 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 |
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 |
; 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 eax, [edx + IP_PACKET.DestinationAddress] |
mov [pseudoHeader+4], eax |
mov ax, 0x1100 ; 0 + protocol |
mov [pseudoHeader+8], ax |
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,44 → 904,43 |
; 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 |
xchg al, ah |
mov [edx + IP_PACKET.HeaderChecksum], ax |
mov [edx + 10], ah |
mov [edx + 11], al |
; 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 |
;*************************************************************************** |
; Function |
; socket_write_tcp |
807,30 → 953,33 |
; 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 eax, 0xFFFFFFFF |
mov ebx, eax |
mov [sockAddr], ebx |
; 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 |
push eax |
push ecx |
call buildTCPPacket |
mov bl, TH_ACK |
stdcall build_tcp_packet, [sockAddr] |
pop ecx |
; Check destination IP address. |
852,13 → 1002,12 |
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 |
865,11 → 1014,11 |
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 |
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,20 → 1048,19 |
; 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 |
; convert source buffer pointer eax to the absolute address |
926,9 → 1074,11 |
cld |
rep movsb |
swt001: |
.exit: |
xor eax, eax |
ret |
swt_exit: |
.error: |
or eax, -1 |
ret |
endp |
/kernel/branches/kolibri_pe/network/stack.inc |
---|
37,7 → 37,7 |
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 |
; 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 |
; 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 |
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 |
;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 |
include "queue.inc" |
include "eth_drv/ethernet.inc" |
include "ip.inc" |
include "icmp.inc" |
include "tcp.inc" |
include "udp.inc" |
include "socket.inc" |
;*************************************************************************** |
171,8 → 173,11 |
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 |
/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_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 |
; 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 |
push [ebx + SOCKET.PrevPtr] |
stdcall net_socket_free, ebx |
pop ebx |
jmp .next_socket |
xor eax, eax |
mov ecx, SOCKETHEADERSIZE |
cld |
rep stosb |
tth3: |
popa |
jmp tth1a |
loop tth1 |
ret |
.decrement_wnd: |
; TODO - prove it works! |
tth4: |
dec dword [eax + sockets + 72] |
loop tth1 |
ret |
dec [ebx + SOCKET.wndsizeTimer] |
jmp .next_socket |
tth_exit: |
.exit: |
ret |
endp |
;*************************************************************************** |
169,7 → 165,8 |
; 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 |
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 |
@@: ; we have one. decrement it's timer by 1 |
dec word [esi+2] |
mov ax, [esi+2] |
cmp ax, 0 |
je tth002a |
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 |
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 |
; 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,30 → 256,27 |
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: |
popad |
tth005: |
popa |
inc ecx |
add esi, 4 |
jmp tth001 |
add esi, 8 |
jmp .next_resendq |
tth003: |
.exit: |
ret |
endp |
;*************************************************************************** |
; Function |
; tcp_rx |
299,7 → 289,8 |
; 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 |
; 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 |
; 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,49 → 386,71 |
; 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 |
;*************************************************************************** |
; Function |
; buildTCPPacket |
434,7 → 465,8 |
; 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,82 → 476,68 |
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 |
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 |
526,24 → 544,21 |
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 eax, [edx + IP_PACKET.DestinationAddress] |
mov [pseudoHeader+4], eax |
mov ax, 0x0600 ; 0 + protocol |
mov [pseudoHeader+8], ax |
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 |
; store it in the TCP checksum ( in the correct order! ) |
mov ax, [checkResult] |
rol ax, 8 |
mov [edx + 20 + TCP_PACKET.Checksum], ax |
mov [edx + 20 + 16], ah |
mov [edx + 20 + 17], al |
; Fill in the IP header checksum |
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 |
mov [edx + 10], ah |
mov [edx + 11], al |
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 |
; 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 eax |
stdcall net_socket_addr_to_num, ebx |
; get skt number in al |
shr eax, 12 |
; 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 |
mov ebx, [eax + sockets+28] |
cmp ebx, TCB_LISTEN |
jb tsm_exit |
cmp ebx, TCB_CLOSED |
ja tsm_exit |
dec ebx |
call dword [TCBStateHandler+ebx*4] |
mov eax, [ebx + SOCKET.TCBState] |
cmp eax, TCB_LISTEN |
jb .exit |
cmp eax, TCB_CLOSED |
ja .exit |
tsm_exit: |
stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr] |
.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 |
mov bl, TH_SYN + 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 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 |
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 |
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 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, 4 |
jmp ste001 |
add esi, 8 |
jmp .next_resendq |
ste002: |
dec dword [arp_rx_count] ; ************ TEST ONLY! |
;@@: 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 ste001 |
.last_resendq: |
popad |
ste003: |
popa |
;xxx ; was it a reset? |
;xxx test [edx + 20 + TCP_PACKET.Flags], TH_RST |
;xxx jz @f |
; was it a reset? |
mov bl, [edx + 33] |
and bl, 0x04 |
cmp bl, 0x04 |
jne ste003a |
;xxx mov [ebx + SOCKET.TCBState], TCB_CLOSED |
;xxx jmp .exit |
mov esi, [sktAddr] |
mov ebx, TCB_CLOSED |
mov [esi + 28], ebx |
jmp ste_exit |
@@: ; Send an ACK to that fin, and enter closewait state |
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 |
jnz .data ; Read data, if any |
cmp ecx, 0 |
jnz ste_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 |
1065,79 → 998,75 |
mov ecx,1 |
mov esi,TASK_DATA+TASKDATA.pid |
news: |
.next_pid: |
cmp [esi],eax |
je foundPID1 |
je .found_pid |
inc ecx |
add esi,0x20 |
cmp ecx,[TASK_COUNT] |
jbe news |
jbe .next_pid |
foundPID1: |
.found_pid: |
shl ecx,8 |
or dword [ecx+SLOT_BASE+APPDATA.event_mask],dword 10000000b ; stack event |
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 |
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 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 |
stateTCB_FIN_WAIT_1: |
proc stateTCB_FIN_WAIT_1 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 stfw1_001 |
mov al, [edx + 20 + TCP_PACKET.Flags] |
and al, TH_FIN + TH_ACK |
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 |
1144,160 → 1073,116 |
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 |
proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD |
test [edx + 20 + TCP_PACKET.Flags], TH_FIN |
jz .exit |
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 |
; 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 |
lea esi, [ebx + SOCKET.RCV_NXT] |
call inc_inet_esi |
stfw2001: |
add esi, 56 |
call add_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 |
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 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 |
test [edx + 20 + TCP_PACKET.Flags], TH_ACK |
jz .exit |
mov edi, [sktAddr] |
; 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 |
/kernel/branches/kolibri_pe/network/udp.inc |
---|
71,7 → 71,8 |
; 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,69 → 81,53 |
; 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 |
; ecx has count, edx points to data |
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 |
add edx, 28 ; edx now points to the data |
mov edi, ebx |
lea edi, [ebx + eax + SOCKETHEADERSIZE] |
mov esi, edx |
cld |
149,25 → 134,28 |
rep movsb ; copy the data across |
; flag an event to the application |
pop eax |
mov eax, [ebx + SOCKET.PID] ; get socket owner PID |
mov ecx,1 |
mov esi,TASK_DATA+TASKDATA.pid |
newsearch: |
.next_pid: |
cmp [esi],eax |
je foundPID |
je .found_pid |
inc ecx |
add esi,0x20 |
cmp ecx,[TASK_COUNT] |
jbe newsearch |
jbe .next_pid |
foundPID: |
jmp .exit |
.found_pid: |
shl ecx,8 |
or dword [ecx+SLOT_BASE+APPDATA.event_mask],dword 10000000b ; stack event |
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event |
mov [check_idle_semaphore],200 |
udprx_001: |
.exit: |
pop eax |
call freeBuff ; Discard the packet |
ret |
endp |
/kernel/branches/kolibri_pe/video/vesa12.inc |
---|
880,6 → 880,14 |
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 |
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 |
/kernel/branches/kolibri_pe/video/vesa20.inc |
---|
163,7 → 163,8 |
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 |
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 |
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 |
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: |