Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 913 → Rev 914

/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(&current_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: