Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 3589 → Rev 3588

/kernel/branches/Kolibri-acpi/bus/usb/ehci.inc
222,7 → 222,7
; ------------------------------ hardware fields ------------------------------
FrameList rd 1024
; Entry n corresponds to the head of the frame list to be executed in
; the frames n,n+1024,n+2048,n+3072,...
; the frames n,n+1024,n+2048,n+3096,...
; The first bit of each entry is Terminate bit, 1 = the frame is empty.
; Bits 1-2 are Type field, one of EHCI_TYPE_* constants.
; Bits 3-4 must be zero.
/kernel/branches/Kolibri-acpi/bus/usb/uhci.inc
126,7 → 126,7
; ------------------------------ hardware fields ------------------------------
FrameList rd 1024
; Entry n corresponds to the head of the frame list to be executed in
; the frames n,n+1024,n+2048,n+3072,...
; the frames n,n+1024,n+2048,n+3096,...
; The first bit of each entry is Terminate bit, 1 = the frame is empty.
; The second bit of each entry is QH/TD select bit, 1 = the entry points to
; QH, 0 = to TD.
/kernel/branches/Kolibri-acpi/data32.inc
375,6 → 375,9
PUTPIXEL rd 1
GETPIXEL rd 1
 
BgrDrawMode rd 1
BgrDataWidth rd 1
BgrDataHeight rd 1
REDRAW_BACKGROUND rb 4
 
MOUSE_PICTURE rd 1
477,12 → 480,6
mem_BACKGROUND rd 1
static_background_data rd 1
 
BgrDrawMode rd 1
BgrDataWidth rd 1
BgrDataHeight rd 1
 
skin_data rd 1
 
cache_ide0:
cache_ide0_pointer rd 1
cache_ide0_size rd 1 ; not use
556,6 → 553,7
FLOPPY_BUFF: rb 16*1024
BUTTON_INFO: rb 16*1024
BgrAuxTable: rb 32*1024
skin_data: rb 32*1024
 
;IDE_DMA: rb 32*1024
 
/kernel/branches/Kolibri-acpi/docs/sysfuncs.txt
2394,17 → 2394,8
</UL>
 
======================================================================
=========================== Function 52 ==============================
======================================================================
 
WARNING: This function is obsolete and is only present in the
documentation as a guide to understand/port the older network
applications. For new programs, use function 74
 
======================================================================
=== Function 52, subfunction 0 - get network driver configuration. ===
======================================================================
 
Parameters:
* eax = 52 - function number
* ebx = 0 - subfunction number
2567,14 → 2558,6
* for other ecx: eax = -1 indicates an error
 
======================================================================
=========================== Function 53 ==============================
======================================================================
 
WARNING: This function is obsolete and is only present in the
documentation as a guide to understand/port the older network
applications. For new programs, use function 75.
 
======================================================================
============ Function 53, subfunction 0 - open UDP-socket. ===========
======================================================================
Parameters:
4598,201 → 4581,6
* function does not return value
 
======================================================================
= Function 74, Subfunction -1, Get number of active network devices. =
======================================================================
Parameters:
* eax = 74 - function number
* bl = -1 - subfunction number
Returned value:
* eax = number of active network devices
 
======================================================================
======== Function 74, Subfunction 0, Get network device type. ========
======================================================================
Parameters:
* eax = 74 - function number
* bl = 0 - subfunction number
* bh = device number
Returned value:
* eax = device type
 
======================================================================
======== Function 74, Subfunction 1, Get network device name. ========
======================================================================
Parameters:
* eax = 74 - function number
* bl = 1 - subfunction number
* bh = device number
* ecx = pointer to 64 byte buffer
Returned value:
* eax = -1 on error
* The network device name is written into the buffer, on success
 
======================================================================
========= Function 74, Subfunction 2, Reset network device. ==========
======================================================================
Parameters:
* eax = 74 - function number
* bl = 2 - subfunction number
* bh = device number
Returned value:
* eax = -1 on error
 
======================================================================
========== Function 74, Subfunction 3, Stop network device. ==========
======================================================================
Parameters:
* eax = 74 - function number
* bl = 3 - subfunction number
* bh = device number
Returned value:
* eax = -1 on error
 
======================================================================
============== Function 75, Subfunction 0, Open socket. ==============
======================================================================
Parameters:
* eax = 75 - function number
* bl = 0 - subfunction number
* ecx = domain
* edx = type
* esi = protocol
Returned value:
* eax = socket number, -1 on error
 
======================================================================
============= Function 75, Subfunction 1, Close socket. ==============
======================================================================
Parameters:
* eax = 75 - function number
* bl = 1 - subfunction number
* ecx = socket number
Returned value:
* eax = -1 on error
 
======================================================================
================== Function 75, Subfunction 2, Bind. =================
======================================================================
Parameters:
* eax = 75 - function number
* bl = 2 - subfunction number
* ecx = socket number
* edx = pointer to sockaddr structure
* esi = length of sockaddr structure
Returned value:
* eax = -1 on error
 
======================================================================
================= Function 75, Subfunction 3, Listen. ================
======================================================================
Parameters:
* eax = 75 - function number
* bl = 3 - subfunction number
* ecx = socket number
* edx = backlog
Returned value:
* eax = -1 on error
 
======================================================================
================ Function 75, Subfunction 4, Connect. ================
======================================================================
Parameters:
* eax = 75 - function number
* bl = 4 - subfunction number
* ecx = socket number
* edx = pointer to sockaddr structure
* esi = length of sockaddr structure
Returned value:
* eax = -1 on error
 
======================================================================
================= Function 75, Subfunction 5, Accept. ================
======================================================================
Parameters:
* eax = 75 - function number
* bl = 5 - subfunction number
* ecx = socket number
* edx = pointer to sockaddr structure
* esi = length of sockaddr structure
Returned value:
* eax = -1 on error
 
======================================================================
================== Function 75, Subfunction 6, Send. =================
======================================================================
Parameters:
* eax = 75 - function number
* bl = 6 - subfunction number
* ecx = socket number
* edx = pointer to buffer
* esi = length of buffer
Returned value:
* eax = number of bytes copied, -1 on error
 
======================================================================
================ Function 75, Subfunction 7, Receive. ================
======================================================================
Parameters:
* eax = 75 - function number
* bl = 7 - subfunction number
* ecx = socket number
* edx = pointer to buffer
* esi = length of buffer
* edi = flags
Returned value:
* eax = number of bytes copied, -1 on error
 
======================================================================
=========== Function 75, Subfunction 8, Set socket options. ==========
======================================================================
Parameters:
* eax = 75 - function number
* bl = 8 - subfunction number
* ecx = socket number
* edx = pointer to optstruct
Returned value:
* eax = -1 on error
Remarks:
 
Optstruct: dd level
dd optionname
dd optlength
db options...
 
======================================================================
=========== Function 75, Subfunction 9, Get socket options. ==========
======================================================================
Parameters:
* eax = 75 - function number
* bl = 9 - subfunction number
* ecx = socket number
* edx = pointer to optstruct
Returned value:
* eax = -1 on error
Remarks:
 
Optstruct: dd level
dd optionname
dd optlength
db options...
 
======================================================================
============ Function 75, Subfunction 10, Get socketpair. ===========
======================================================================
Parameters:
* eax = 75 - function number
* bl = 10 - subfunction number
Returned value:
* eax = socketnum1, -1 on error
* ebx = socketnum2
Remarks:
 
Optstruct: dd level
dd optionname
dd optlength
db options...
 
======================================================================
=============== Function -1 - terminate thread/process ===============
======================================================================
Parameters:
/kernel/branches/Kolibri-acpi/docs/usbapi.txt
4,8 → 4,8
print some information, reads and parses configuration descriptor. For every
interface the kernel looks for class code of this interface and loads the
corresponding COFF driver. Currently the correspondence is hardcoded into
the kernel code and looks as follows: 3 = usbhid.obj, 7 = usbprint.obj,
8 = usbstor.obj, 9 is handled by the kernel itself, other = usbother.obj.
the kernel code and looks as follows: 3 = usbhid.obj, 8 = usbstor.obj,
9 is handled by the kernel itself, other = usbother.obj.
 
The driver must be standard driver in COFF format, exporting procedure
named "START" and a variable named "version". Loader calls "START" procedure
46,7 → 46,7
void* interfacedescr
);
 
The parameter 'pipe0' is a handle of the control pipe for endpoint zero
The parameter 'controlpipe' is a handle of the control pipe for endpoint zero
of the device. It can be used as the argument of USBControlTransferAsync.
The parameter 'configdescr' points to USB configuration descriptor
and all associated data, as returned by GET_DESCRIPTOR request.
93,20 → 93,7
The parameter 'interval' is ignored for control and bulk endpoints.
For interrupt endpoints, it sets the polling interval in milliseconds.
The function returns a handle to the pipe or NULL on failure.
The output handle becomes invalid when a) it is explicitly closed with
the following function or b) the function DeviceDisconnected provided
by the driver returns.
 
void __stdcall USBClosePipe(
void* pipe
);
 
Releases all resources associated with the given pipe. The only parameter
must be a handle returned by USBOpenPipe.
When a device is disconnected, all associated pipes are closed by the kernel;
there is no need to ever call this function if all pipes are used continuously
while a device is connected.
 
void* __stdcall USBNormalTransferAsync(
void* pipe,
void* buffer,
117,7 → 104,7
);
void* __stdcall USBControlTransferAsync(
void* pipe,
void* setup,
void* config,
void* buffer,
int size,
void* callback,
129,12 → 116,12
for given pipe. Type and direction of transfer are fixed for bulk and interrupt
endpoints and are set in USBOpenPipe. The second function inserts a control
transfer to the transfer queue for given pipe. Direction of a control transfer
is concluded from 'setup' packet, bit 7 of byte 0 is set for IN transfers
is concluded from 'config' packet, bit 7 of byte 0 is set for IN transfers
and cleared for OUT transfers. These function return immediately; when data
are transferred, the callback function will be called.
 
The parameter 'pipe' is a handle returned by USBOpenPipe.
The parameter 'setup' of USBControlTransferAsync points to 8-byte
The parameter 'config' of USBControlTransferAsync points to 8-byte
configuration packet as defined by USB.
The parameter 'buffer' is a pointer to buffer. For IN transfers, it will be
filled with the data. For OUT transfers, it should contain data to be
187,12 → 174,10
; possible only for isochronous transfers
USB_STATUS_BUFUNDERRUN = 13 ; underflow of internal controller buffer
; possible only for isochronous transfers
USB_STATUS_CLOSED = 16 ; pipe closed, either explicitly with USBClosePipe
; or due to device disconnect
USB_STATUS_DISCONNECTED = 16 ; device disconnected
 
If several transfers are queued for the same pipe, their callback functions
are called in the same order as they were queued.
When a pipe is closed, either explicitly with USBClosePipe, or
implicitly due to device disconnect, all callback functions are called
with USB_STATUS_CLOSED. The call to DeviceDisconnected() occurs after
When the device is disconnected, all callback functions are called
with USB_STATUS_DISCONNECTED. The call to DeviceDisconnected() occurs after
all callbacks.
/kernel/branches/Kolibri-acpi/drivers/usbhid.asm
File deleted
/kernel/branches/Kolibri-acpi/drivers/usbstor.asm
File deleted
/kernel/branches/Kolibri-acpi/gui/event.inc
516,7 → 516,7
btr ecx, eax ; сбрасываем проверяемый бит маски
; переходим на обработчик этого (eax) бита
cmp eax, 10
jae .loop ; eax=[10..31], ignored (event 11...32)
jae .loop ; eax=[10..31], ignored (event 10...32)
 
cmp eax, 3
je .loop ; eax=3, ignored (event 4)
/kernel/branches/Kolibri-acpi/gui/window.inc
1024,8 → 1024,6
; no it's not, just activate the window
call window._.window_activate
xor eax, eax
ret
 
;--------------------------------------
align 4
.exit:
/kernel/branches/Kolibri-acpi/gui/skincode.inc
17,16 → 17,21
stdcall load_file, ebx
test eax, eax
jz .notfound
 
cmp dword [eax], 'SKIN'
jnz .noskin
cmp ebx, 32*1024
jb @f
mov ebx, 32*1024
;--------------------------------------
align 4
@@:
lea ecx, [ebx+3]
shr ecx, 2
mov esi, eax
mov edi, skin_data
rep movsd
stdcall kernel_free, eax
 
xchg eax, [skin_data]
test eax, eax
jz @f
 
stdcall kernel_free, eax
@@:
call parse_skin_data
xor eax, eax
ret
40,7 → 45,8
align 4
.noskin:
stdcall kernel_free, eax
mov eax, 2
push 2
pop eax
ret
;------------------------------------------------------------------------------
struct SKIN_HEADER
92,7 → 98,7
;------------------------------------------------------------------------------
align 4
parse_skin_data:
mov ebp, [skin_data]
mov ebp, skin_data
cmp [ebp+SKIN_HEADER.ident], 'SKIN'
jne .exit
 
103,7 → 109,7
rep stosd
 
mov ebx, [ebp+SKIN_HEADER.params]
add ebx, [skin_data]
add ebx, skin_data
mov eax, [ebx+SKIN_PARAMS.skin_height]
mov [_skinh], eax
mov eax, [ebx+SKIN_PARAMS.colors.inner]
129,7 → 135,7
mov dword[_skinmargins+4], eax
 
mov ebx, [ebp+SKIN_HEADER.bitmaps]
add ebx, [skin_data]
add ebx, skin_data
;--------------------------------------
align 4
.lp1:
154,7 → 160,7
dec eax
jnz .not_oper
mov esi, [ebx+SKIN_BITMAPS.data]
add esi, [skin_data]
add esi, skin_data
mov eax, [esi+0]
neg eax
mov edx, skin_active.oper.data
189,7 → 195,7
align 4
.next_bitmap:
mov ecx, [ebx+SKIN_BITMAPS.data]
add ecx, [skin_data]
add ecx, skin_data
mov [edx+4], eax
mov eax, [ecx+0]
mov [edx+8], eax
201,7 → 207,7
align 4
.end_bitmaps:
mov ebx, [ebp+SKIN_HEADER.buttons]
add ebx, [skin_data]
add ebx, skin_data
;--------------------------------------
align 4
.lp2:
390,8 → 396,7
;--------------------------------------
align 4
@@:
mov eax, [skin_data]
cmp [eax], dword 'SKIN'
cmp dword[skin_data], 'SKIN'
je @f
xor eax, eax
xor ebx, ebx
433,8 → 438,7
;--------------------------------------
align 4
_noinside2:
mov eax, [skin_data]
cmp [eax], dword 'SKIN'
cmp dword[skin_data], 'SKIN'
jne no_skin_add_button
;* close button
mov edi, [BTN_ADDR]
/kernel/branches/Kolibri-acpi/kernel.asm
77,7 → 77,7
USE_COM_IRQ equ 1 ; make irq 3 and irq 4 available for PCI devices
 
; Enabling the next line will enable serial output console
;debug_com_base equ 0x3f8 ; 0x3f8 is com1, 0x2f8 is com2, 0x3e8 is com3, 0x2e8 is com4, no irq's are used
debug_com_base equ 0x3f8 ; 0x3f8 is com1, 0x2f8 is com2, 0x3e8 is com3, 0x2e8 is com4, no irq's are used
; The following constant, if nonzero, duplicates debug output to the screen.
debug_direct_print equ 0
 
163,6 → 163,35
include "bus/pci/pci16.inc"
include "detect/biosdisk.inc"
 
FDD_BUFF equ (OS_BASE+0x000D000)
 
sys_pgdir equ (OS_BASE+0x006F000)
 
VGABasePtr equ (OS_BASE+0x00A0000)
 
RAMDISK equ (OS_BASE+0x0100000)
 
CLEAN_ZONE equ 0x284000
IDE_DMA equ 0x284000
 
BOOT_VAR equ (OS_BASE+0x02E0000)
 
TASK_COUNT equ (CURRENT_TASK+0x04)
TASK_BASE equ (CURRENT_TASK+0x10)
TASK_DATA equ (CURRENT_TASK+0x20)
TASK_EVENT equ (CURRENT_TASK+0x20)
 
BPSLine_calc_area equ (OS_BASE+0x02C4000)
 
d_width_calc_area equ (OS_BASE+0x02CA000)
 
stack_data_start equ (OS_BASE+0x02F0000)
eth_data_start equ (OS_BASE+0x02F0000)
stack_data equ (OS_BASE+0x02F4000)
stack_data_end equ (OS_BASE+0x030ffff)
resendQ equ (OS_BASE+0x0310000)
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SWITCH TO 32 BIT PROTECTED MODE ;;
405,17 → 434,15
dec eax
mov [Screen_Max_Y], eax
mov [screen_workarea.bottom], eax
movzx eax, word [BOOT_VAR+BOOT_VESA_MODE]; screen mode
mov [SCR_MODE], eax
; mov eax, [BOOT_VAR+0x9014] ; Vesa 1.2 bnk sw add
; mov [BANK_SWITCH], eax
mov [BytesPerScanLine], word 640*4 ; Bytes PerScanLine
cmp [SCR_MODE], word 0x13 ; 320x200
mov ax, word [BOOT_VAR+BOOT_VESA_MODE] ; screen mode
mov [SCR_MODE], ax
mov [BytesPerScanLine], 640*4 ; Bytes PerScanLine
cmp [SCR_MODE], 0x13 ; 320x200
je @f
cmp [SCR_MODE], word 0x12 ; VGA 640x480
cmp [SCR_MODE], 0x12 ; VGA 640x480
je @f
movzx eax, word[BOOT_VAR+BOOT_PITCH] ; for other modes
mov [BytesPerScanLine], ax
mov [BytesPerScanLine], eax
mov [_display.pitch], eax
@@:
mov eax, [_display.width]
1241,7 → 1268,6
xor eax, eax
mov [BTN_ADDR], dword BUTTON_INFO ; address of button list
 
mov byte [MOUSE_BUFF_COUNT], al ; mouse buffer
mov byte [KEY_COUNT], al ; keyboard buffer
mov byte [BTN_COUNT], al ; button buffer
; mov [MOUSE_X],dword 100*65536+100 ; mouse x/y
4969,7 → 4995,7
.1: ; resolution
mov eax, [Screen_Max_X]
shl eax, 16
mov ax, [Screen_Max_Y]
mov ax, word [Screen_Max_Y]
add eax, 0x00010001
mov [esp+32], eax
ret
5068,9 → 5094,9
 
align 4
syscall_getscreensize: ; GetScreenSize
mov ax, [Screen_Max_X]
mov eax, [Screen_Max_X]
shl eax, 16
mov ax, [Screen_Max_Y]
mov ax, word [Screen_Max_Y]
mov [esp + 32], eax
ret
 
/kernel/branches/Kolibri-acpi/network/ARP.inc
177,7 → 177,7
 
inc [ARP_PACKETS_RX + 4*edi] ; update stats
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: got packet from %u.%u.%u.%u through device %u\n",\
DEBUGF 1,"ARP_input: got packet from %u.%u.%u.%u through device %u\n",\
[edx + ARP_header.SenderIP]:1, [edx + ARP_header.SenderIP + 1]:1,\
[edx + ARP_header.SenderIP + 2]:1, [edx + ARP_header.SenderIP + 3]:1, edi
 
194,7 → 194,7
cmp [edx + ARP_header.Opcode], ARP_REP_OPCODE
jne .maybe_request
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: It's a reply\n"
DEBUGF 1,"ARP_input: It's a reply\n"
 
mov ecx, [NumARP]
test ecx, ecx
208,16 → 208,16
dec ecx
jnz .loop
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: no matching entry found\n"
DEBUGF 1,"ARP_input: no matching entry found\n"
jmp .exit
 
.gotit:
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: found matching entry\n"
DEBUGF 1,"ARP_input: found matching entry\n"
 
cmp [esi + ARP_entry.TTL], ARP_STATIC_ENTRY ; if it is a static entry, dont touch it
je .exit
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: updating entry\n"
DEBUGF 1,"ARP_input: updating entry\n"
 
mov [esi + ARP_entry.Status], ARP_VALID_MAPPING
mov [esi + ARP_entry.TTL], ARP_ENTRY_TTL
236,7 → 236,7
cmp [edx + ARP_header.Opcode], ARP_REQ_OPCODE
jne .exit
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: its a request\n"
DEBUGF 1,"ARP_input: its a request\n"
 
mov eax, [IP_LIST + 4*edi]
cmp eax, [edx + ARP_header.TargetIP] ; Is it looking for my IP address?
277,7 → 277,7
; mov ax , ETHER_ARP ; It's already there, I'm sure of it!
; stosw
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: Sending reply\n"
DEBUGF 1,"ARP_input: Sending reply\n"
 
call [ebx + NET_DEVICE.transmit]
ret
284,13 → 284,13
 
.collision:
inc [ARP_CONFLICTS + 4*edi]
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: IP address conflict detected!\n"
DEBUGF 1,"ARP_input: IP address conflict detected!\n"
 
.exit:
call kernel_free
add esp, 4 ; pop (balance stack)
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: exiting\n"
DEBUGF 1,"ARP_input: exiting\n"
ret
 
 
310,7 → 310,7
pushd [IP_LIST + edi] ; SenderIP
inc [ARP_PACKETS_TX + edi] ; assume we will succeed
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_output_request: ip=%u.%u.%u.%u\n",\
DEBUGF 1,"ARP_output_request: ip=%u.%u.%u.%u\n",\
[esp + 4]:1, [esp + 5]:1, [esp + 6]:1, [esp + 7]:1
 
mov ebx, [NET_DRV_LIST + edi] ; device ptr
344,7 → 344,7
pop eax ; DestIP
stosd ;
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_output_request: device=%x\n", ebx
DEBUGF 1,"ARP_output_request: device=%x\n", ebx
 
push edx ecx
call [ebx + NET_DEVICE.transmit]
352,7 → 352,7
 
.exit:
add esp, 4 + 4
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_output_request: failed\n"
DEBUGF 1,"ARP_output_request: failed\n"
sub eax, eax
ret
 
369,7 → 369,7
align 4
ARP_add_entry:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_add_entry: "
DEBUGF 1,"ARP_add_entry: "
 
mov ecx, [NumARP]
cmp ecx, ARP_TABLE_SIZE ; list full ?
400,12 → 400,12
rep movsw
inc [NumARP]
sub edi, sizeof.ARP_entry
DEBUGF DEBUG_NETWORK_VERBOSE, "entry=%u\n", eax
DEBUGF 1,"entry=%u\n", eax
 
ret
 
.error:
DEBUGF DEBUG_NETWORK_VERBOSE, "failed\n"
DEBUGF 1,"failed\n"
mov eax, -1
ret
 
421,8 → 421,8
align 4
ARP_del_entry:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_del_entry: entry=%x entrys=%u\n", esi, [NumARP]
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_del_entry: IP=%u.%u.%u.%u\n", \
DEBUGF 1,"ARP_del_entry: entry=%x entrys=%u\n", esi, [NumARP]
DEBUGF 1,"ARP_del_entry: IP=%u.%u.%u.%u\n", \
[esi + ARP_entry.IP]:1, [esi + ARP_entry.IP + 1]:1, [esi + ARP_entry.IP + 2]:1, [esi + ARP_entry.IP + 3]:1
 
mov ecx, ARP_table + (ARP_TABLE_SIZE - 1) * sizeof.ARP_entry
438,7 → 438,7
rep stosw
 
dec [NumARP]
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_del_entry: success\n"
DEBUGF 1,"ARP_del_entry: success\n"
 
ret
 
463,9 → 463,9
align 4
ARP_IP_to_MAC:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: %u.%u", al, ah
DEBUGF 1,"ARP_IP_to_MAC: %u.%u", al, ah
rol eax, 16
DEBUGF DEBUG_NETWORK_VERBOSE, ".%u.%u\n", al, ah
DEBUGF 1,".%u.%u\n", al, ah
rol eax, 16
 
cmp eax, 0xffffffff
485,7 → 485,7
loop .scan_loop
 
.not_in_list:
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: preparing for ARP request\n"
DEBUGF 1,"ARP_IP_to_MAC: preparing for ARP request\n"
 
;--------------------
; Send an ARP request
535,16 → 535,16
end if
 
.valid:
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: found MAC\n"
DEBUGF 1,"ARP_IP_to_MAC: found MAC\n"
movzx eax, word[esi + ARP_entry.MAC]
mov ebx, dword[esi + ARP_entry.MAC + 2]
ret
 
.full:
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: table is full!\n"
DEBUGF 1,"ARP_IP_to_MAC: table is full!\n"
add esp, 8
.give_up:
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: entry has no valid mapping!\n"
DEBUGF 1,"ARP_IP_to_MAC: entry has no valid mapping!\n"
mov eax, -1
ret
 
/kernel/branches/Kolibri-acpi/network/IPv4.inc
112,7 → 112,7
jmp .done
 
.died:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4 Fragment slot timed-out!\n"
DEBUGF 2,"IPv4 Fragment slot timed-out!\n"
;;; TODO: clear all entry's of timed-out slot
jmp .next
 
205,10 → 205,10
align 4
IPv4_input: ; TODO: add IPv4 raw sockets support
 
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input, packet from: %u.%u.%u.%u ",\
DEBUGF 2,"IPv4_input, packet from: %u.%u.%u.%u ",\
[edx + IPv4_header.SourceAddress + 0]:1,[edx + IPv4_header.SourceAddress + 1]:1,\
[edx + IPv4_header.SourceAddress + 2]:1,[edx + IPv4_header.SourceAddress + 3]:1
DEBUGF DEBUG_NETWORK_VERBOSE, "to: %u.%u.%u.%u\n",\
DEBUGF 2,"to: %u.%u.%u.%u\n",\
[edx + IPv4_header.DestinationAddress + 0]:1,[edx + IPv4_header.DestinationAddress + 1]:1,\
[edx + IPv4_header.DestinationAddress + 2]:1,[edx + IPv4_header.DestinationAddress + 3]:1
 
218,7 → 218,7
IPv4_checksum edx
jnz .dump ; if checksum isn't valid then dump packet
 
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Checksum ok\n"
DEBUGF 1,"IPv4_input: Checksum ok\n"
 
;-----------------------------------
; Check if destination IP is correct
256,7 → 256,7
 
; or it's just not meant for us.. :(
 
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Destination address does not match!\n"
DEBUGF 2,"IPv4_input: Destination address does not match!\n"
jmp .dump
 
;------------------------
300,10 → 300,10
cmp al, IP_PROTO_ICMP
je ICMP_input
 
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: unknown protocol %u\n", al
DEBUGF 2,"IPv4_input: unknown protocol %u\n", al
 
.dump:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: dumping\n"
DEBUGF 1,"IPv4_input: dumping\n"
inc [IP_packets_dumped] ; FIXME: use correct interface
call kernel_free
add esp, 4 ; pop (balance stack)
319,7 → 319,7
xchg al, ah
shl ax, 3
 
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: fragmented packet offset=%u id=%x\n", ax, [edx + IPv4_header.Identification]:4
DEBUGF 1,"IPv4_input: fragmented packet offset=%u id=%x\n", ax, [edx + IPv4_header.Identification]:4
 
test ax, ax ; Is this the first packet of the fragment?
jz .is_first_fragment
328,7 → 328,7
;-------------------------------------------------------
; We have a fragmented IP packet, but it's not the first
 
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Middle fragment packet received!\n"
DEBUGF 1,"IPv4_input: Middle fragment packet received!\n"
 
call IPv4_find_fragment_slot
cmp esi, -1
361,7 → 361,7
; We have received the first fragment
 
.is_first_fragment:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: First fragment packet received!\n"
DEBUGF 1,"IPv4_input: First fragment packet received!\n"
; try to locate a free slot..
mov ecx, MAX_FRAGMENTS
mov esi, FRAGMENT_LIST
395,7 → 395,7
; We have received the last fragment
 
.is_last_fragment:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Last fragment packet received!\n"
DEBUGF 1,"IPv4_input: Last fragment packet received!\n"
 
call IPv4_find_fragment_slot
cmp esi, -1
411,12 → 411,12
jne .destroy_slot_pop ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
mov cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.TotalLength] ; Add total length
xchg cl, ch
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx
DEBUGF 1,"IPv4_input: Packet size=%u\n", cx
add ax, cx
movzx cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL] ; Sub Header length
and cx, 0x000F
shl cx, 2
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Header size=%u\n", cx
DEBUGF 1,"IPv4_input: Header size=%u\n", cx
sub ax, cx
mov edi, esi
mov esi, [esi + FRAGMENT_entry.NextPtr]
431,9 → 431,9
 
mov cx, [edx + IPv4_header.TotalLength] ; Note: This time we dont substract Header length
xchg cl, ch
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx
DEBUGF 1,"IPv4_input: Packet size=%u\n", cx
add ax, cx
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Received data size=%u\n", eax
DEBUGF 1,"IPv4_input: Total Received data size=%u\n", eax
 
push eax
mov ax, [edx + IPv4_header.FlagsAndFragmentOffset]
441,7 → 441,7
shl ax, 3
add cx, ax
pop eax
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Fragment size=%u\n", ecx
DEBUGF 1,"IPv4_input: Total Fragment size=%u\n", ecx
 
cmp ax, cx
jne .destroy_slot_pop
457,7 → 457,7
movzx ecx, [edx + sizeof.FRAGMENT_entry + IPv4_header.FlagsAndFragmentOffset] ; Calculate the fragment offset
xchg cl, ch ; intel byte order
shl cx, 3 ; multiply by 8 and clear first 3 bits
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Fragment offset=%u\n", cx
DEBUGF 1,"IPv4_input: Fragment offset=%u\n", cx
 
lea edi, [eax + ecx] ; Notice that edi will be equal to eax for first fragment
movzx ebx, [edx + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL] ; Find header size (in ebx) of fragment
504,7 → 504,7
.destroy_slot_pop:
add esp, 4
.destroy_slot:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Destroy fragment slot!\n"
DEBUGF 1,"IPv4_input: Destroy fragment slot!\n"
; TODO!
jmp .dump
 
568,7 → 568,7
align 4
IPv4_output:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_output: size=%u\n", ecx
DEBUGF 1,"IPv4_output: size=%u\n", ecx
 
cmp ecx, 65500 ; Max IPv4 packet size
ja .too_large
614,23 → 614,23
 
IPv4_checksum edi
add edi, sizeof.IPv4_header
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_output: success!\n"
DEBUGF 2,"IPv4_output: success!\n"
ret
 
.eth_error:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_output: ethernet error\n"
DEBUGF 2,"IPv4_output: ethernet error\n"
add esp, 3*4+2+6
xor edi, edi
ret
 
.arp_error:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_output: ARP error=%x\n", eax
DEBUGF 2,"IPv4_output: ARP error=%x\n", eax
add esp, 3*4+2
xor edi, edi
ret
 
.too_large:
DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output: Packet too large!\n"
DEBUGF 2,"IPv4_output: Packet too large!\n"
xor edi, edi
ret
 
713,7 → 713,7
 
IPv4_checksum edi ;;;; todo: checksum for IP packet with options!
add edi, sizeof.IPv4_header
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_output_raw: device=%x\n", ebx
DEBUGF 2,"IPv4_output_raw: device=%x\n", ebx
call [ebx + NET_DEVICE.transmit]
ret
 
722,7 → 722,7
.arp_error:
add esp, 8+4+4
.too_large:
DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output_raw: Failed\n"
DEBUGF 2,"IPv4_output_raw: Failed\n"
sub edi, edi
ret
 
742,7 → 742,7
align 4
IPv4_fragment:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_fragment\n"
DEBUGF 1,"IPv4_fragment\n"
 
and ecx, not 111b ; align 4
 
770,7 → 770,7
push dword 0 ; offset
 
.new_fragment:
DEBUGF DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: new fragment"
DEBUGF 1,"Ipv4_fragment: new fragment"
 
 
mov eax, [esp + 3*4]
792,7 → 792,7
add esi, [esp] ; offset
 
mov ecx, [esp + 1*4]
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_fragment: copying %u bytes\n", ecx
DEBUGF 1,"IPv4_fragment: copying %u bytes\n", ecx
rep movsb
 
; now, correct header
829,7 → 829,7
sub ecx, [esp+2*4] ; ptr to ip header
add ecx, [esp] ; offset
 
DEBUGF DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: %u bytes remaining\n", ecx
DEBUGF 1,"Ipv4_fragment: %u bytes remaining\n", ecx
 
cmp ecx, [esp+1*4]
jae .new_fragment
838,11 → 838,11
jmp .new_fragment
 
.err:
DEBUGF DEBUG_NETWORK_ERROR, "Ipv4_fragment: failed\n"
DEBUGF 1,"Ipv4_fragment: failed\n"
.done:
add esp, 12 + 4 + 6
.err2:
DEBUGF DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: dumping\n"
DEBUGF 1,"Ipv4_fragment: dumping\n"
call kernel_free
add esp, 4
 
886,7 → 886,7
mov eax, [GATEWAY_LIST]
 
.found_it:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
DEBUGF 1,"IPv4_dest_to_dev: %u\n", edi
ret
 
.broadcast:
/kernel/branches/Kolibri-acpi/network/IPv6.inc
83,7 → 83,7
align 4
IPv6_input:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input from: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\
DEBUGF 2,"IPv6_input from: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\
[edx + IPv6_header.SourceAddress + 0]:2,[edx + IPv6_header.SourceAddress + 1]:2,\
[edx + IPv6_header.SourceAddress + 2]:2,[edx + IPv6_header.SourceAddress + 3]:2,\
[edx + IPv6_header.SourceAddress + 4]:2,[edx + IPv6_header.SourceAddress + 5]:2,\
93,7 → 93,7
[edx + IPv6_header.SourceAddress + 12]:2,[edx + IPv6_header.SourceAddress + 13]:2,\
[edx + IPv6_header.SourceAddress + 14]:2,[edx + IPv6_header.SourceAddress + 15]:2
 
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input to: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\
DEBUGF 1,"IPv6_input to: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\
[edx + IPv6_header.DestinationAddress + 0]:2,[edx + IPv6_header.DestinationAddress + 1]:2,\
[edx + IPv6_header.DestinationAddress + 2]:2,[edx + IPv6_header.DestinationAddress + 3]:2,\
[edx + IPv6_header.DestinationAddress + 4]:2,[edx + IPv6_header.DestinationAddress + 5]:2,\
143,10 → 143,10
; cmp al, 58
; je ICMP6_input
 
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - unknown protocol: %u\n", al
DEBUGF 2,"IPv6_input - unknown protocol: %u\n", al
 
.dump:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - dumping\n"
DEBUGF 1,"IPv6_input - dumping\n"
call kernel_free
add esp, 4
 
166,7 → 166,7
; Hop-by-Hop
 
.hop_by_hop:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - hop by hop\n"
DEBUGF 1,"IPv6_input - hop by hop\n"
pushw [esi] ; 8 bit identifier for option type
movzx eax, byte[esi + 1] ; Hdr Ext Len
inc eax ; first 8 octets not counted
195,7 → 195,7
 
.pad_n:
movzx eax, byte[esi + 1]
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - pad %u\n", eax
DEBUGF 1,"IPv6_input - pad %u\n", eax
inc esi
inc esi
add esi, eax
203,7 → 203,7
jmp .hop_by_hop
 
.pad_1:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - pad 1\n"
DEBUGF 1,"IPv6_input - pad 1\n"
inc esi
dec ecx
jmp .hop_by_hop
211,11 → 211,11
 
 
.dest_opts:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - dest opts\n"
DEBUGF 1,"IPv6_input - dest opts\n"
jmp .nextheader
 
.routing:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - routing\n"
DEBUGF 1,"IPv6_input - routing\n"
pushw [esi] ; 8 bit identifier for option type
movzx eax, byte[esi + 1] ; Hdr Ext Len
inc eax ; first 8 octets not counted
238,7 → 238,7
jmp .nextheader
 
.fragment:
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - fragment\n"
DEBUGF 1,"IPv6_input - fragment\n"
 
jmp .nextheader
 
/kernel/branches/Kolibri-acpi/network/PPPoE.inc
59,7 → 59,7
align 4
PPPoE_discovery_input:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_discovery_input\n"
DEBUGF 2,"PPPoE_discovery_input\n"
 
; First, find open PPPoE socket
 
84,7 → 84,7
jmp SOCKET_input
 
.dump:
DEBUGF DEBUG_NETWORK_VERBOSE, 'PPPoE_discovery_input: dumping\n'
DEBUGF 1,'PPPoE_discovery_input: dumping\n'
call kernel_free
add esp, 4
ret
103,7 → 103,7
align 4
PPPoE_discovery_output:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_discovery_output: socket=%x buffer=%x size=%d\n", eax, esi, ecx
DEBUGF 2,"PPPoE_discovery_output: socket=%x buffer=%x size=%d\n", eax, esi, ecx
 
; RFC2516: An entire PADI packet (including the PPPoE header) MUST NOT
; exceed 1484 octets.
123,7 → 123,7
cmp [ebx + NET_DEVICE.type], NET_TYPE_ETH
jne .bad
 
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_discovery_output: device=%x\n", ebx
DEBUGF 2,"PPPoE_discovery_output: device=%x\n", ebx
 
; Create packet.
push ecx esi
193,7 → 193,7
xchg cl, ch
 
mov ax, [edx + PPPoE_frame.SessionID]
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_input: session ID=%x, length=%u\n", ax, cx
DEBUGF 2,"PPPoE_input: session ID=%x, length=%u\n", ax, cx
cmp ax, [PPPoE_SID]
jne .dump
 
207,10 → 207,10
; je IPv6_input
 
jmp PPPoE_discovery_input ; Send LCP,CHAP,CBCP,... packets to the PPP dialer
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_input: Unknown protocol=%x\n", ax
DEBUGF 2,"PPPoE_input: Unknown protocol=%x\n", ax
 
.dump:
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_input: dumping\n"
DEBUGF 2,"PPPoE_input: dumping\n"
call kernel_free
add esp, 4
ret
238,7 → 238,7
align 4
PPPoE_output:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_output: size=%u device=%x\n", ecx, ebx
DEBUGF 1,"PPPoE_output: size=%u device=%x\n", ecx, ebx
 
pushw di
pushw [PPPoE_SID]
263,7 → 263,7
sub ecx, 2
add edi, PPPoE_frame.Payload + 2
 
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_output: success!\n"
DEBUGF 1,"PPPoE_output: success!\n"
ret
 
 
276,7 → 276,7
 
PPPoE_start_connection:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_start_connection: %x\n", cx
DEBUGF 2,"PPPoE_start_connection: %x\n", cx
 
cmp [PPPoE_SID], 0
jne .fail
296,7 → 296,7
align 4
PPPoE_stop_connection:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_stop_connection\n"
DEBUGF 2,"PPPoE_stop_connection\n"
 
xor eax, eax
mov [PPPoE_SID], ax
/kernel/branches/Kolibri-acpi/network/ethernet.inc
56,7 → 56,7
mov eax, [esp]
mov ecx, [esp+4]
 
DEBUGF DEBUG_NETWORK_VERBOSE,"ETH_input: size=%u\n", ecx
DEBUGF 1,"ETH_input: size=%u\n", ecx
cmp ecx, ETH_FRAME_MINIMUM
jb .dump
sub ecx, sizeof.ETH_header
79,10 → 79,10
cmp ax, ETHER_PPP_SESSION
je PPPoE_session_input
 
DEBUGF DEBUG_NETWORK_ERROR, "ETH_input: Unknown packet type=%x\n", ax
DEBUGF 2,"ETH_input: Unknown packet type=%x\n", ax
 
.dump:
DEBUGF DEBUG_NETWORK_VERBOSE,"ETH_input: dumping\n"
DEBUGF 2,"ETH_input: dumping\n"
call kernel_free
add esp, 4
ret
107,7 → 107,7
align 4
ETH_output:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_output: size=%u device=%x\n", ecx, ebx
DEBUGF 1,"ETH_output: size=%u device=%x\n", ecx, ebx
 
cmp ecx, [ebx + NET_DEVICE.mtu]
ja .exit
137,7 → 137,7
cmp edx, ETH_FRAME_MINIMUM
jbe .adjust_size
.done:
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_output: ptr=%x size=%u\n", eax, edx
DEBUGF 1,"ETH_output: ptr=%x size=%u\n", eax, edx
ret
 
.adjust_size:
146,13 → 146,13
jmp .done
 
.out_of_ram:
DEBUGF DEBUG_NETWORK_ERROR, "ETH_output: Out of ram!\n"
DEBUGF 2,"ETH_output: Out of ram!\n"
add esp, 4+4+2+4
sub edi, edi
ret
 
.exit:
DEBUGF DEBUG_NETWORK_ERROR, "ETH_output: Packet too large!\n"
DEBUGF 2,"ETH_output: Packet too large!\n"
sub edi, edi
ret
 
/kernel/branches/Kolibri-acpi/network/icmp.inc
142,7 → 142,7
align 4
ICMP_input:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ICMP_input:\n"
DEBUGF 1,"ICMP_input:\n"
 
; First, check the checksum (altough some implementations ignore it)
 
163,7 → 163,7
; We well re-use the packet so we can create the response as fast as possible
; Notice: this only works on pure ethernet
 
DEBUGF DEBUG_NETWORK_VERBOSE, "got echo request\n"
DEBUGF 1,"got echo request\n"
mov [edx + ICMP_header.Type], ICMP_ECHOREPLY ; Change Packet type to reply
 
mov esi, [esp] ; Start of buffer
258,7 → 258,7
; je .dump
; inc [ICMP_PACKETS_RX+edi]
 
DEBUGF DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
DEBUGF 1,"socket=%x\n", eax
 
pusha
lea ecx, [eax + SOCKET.mutex]
270,10 → 270,10
 
 
.checksum_mismatch:
DEBUGF DEBUG_NETWORK_VERBOSE, "checksum mismatch\n"
DEBUGF 1,"checksum mismatch\n"
 
.dump:
DEBUGF DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
DEBUGF 1,"ICMP_input: dumping\n"
 
call kernel_free
add esp, 4 ; pop (balance stack)
297,7 → 297,7
align 4
ICMP_output:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
DEBUGF 1,"Creating ICMP Packet\n"
 
push esi edi dx
 
308,7 → 308,7
call IPv4_output
jz .exit
 
DEBUGF DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx
DEBUGF 1,"full icmp packet size: %u\n", edx
 
pop word [edi + ICMP_header.Type] ; Write both type and code bytes at once
pop dword [edi + ICMP_header.Identifier] ; identifier and sequence number
333,11 → 333,11
 
sub edi, edx ;;; TODO: find a better way to remember start of packet
push edx edi
DEBUGF DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
DEBUGF 1,"Sending ICMP Packet\n"
call [ebx + NET_DEVICE.transmit]
ret
.exit:
DEBUGF DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
DEBUGF 1,"Creating ICMP Packet failed\n"
add esp, 2*4 + 2
ret
 
356,7 → 356,7
align 4
ICMP_output_raw:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
DEBUGF 1,"Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
 
push edx
 
371,7 → 371,7
push eax
 
push edi ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi
DEBUGF 1,"copying %u bytes from %x to %x\n", ecx, esi, edi
rep movsb
pop ecx edi
 
383,11 → 383,11
call checksum_2
mov [edi + ICMP_header.Checksum], dx
 
DEBUGF DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
DEBUGF 1,"Sending ICMP Packet\n"
call [ebx + NET_DEVICE.transmit]
ret
.exit:
DEBUGF DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
DEBUGF 1,"Creating ICMP Packet failed\n"
add esp, 4
ret
 
/kernel/branches/Kolibri-acpi/network/loopback.inc
59,7 → 59,7
push ecx
push eax
 
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_input: size=%u\n", ecx
DEBUGF 1,"LOOP_input: size=%u\n", ecx
lea edx, [eax + 2]
mov ax, word[eax]
mov ebx, LOOPBACK_DEVICE
67,10 → 67,10
cmp ax, ETHER_IPv4
je IPv4_input
 
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_input: Unknown packet type=%x\n", ax
DEBUGF 2,"LOOP_input: Unknown packet type=%x\n", ax
 
.dump:
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_input: dumping\n"
DEBUGF 2,"LOOP_input: dumping\n"
call kernel_free
add esp, 4
ret
93,7 → 93,7
align 4
LOOP_output:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_output\n"
DEBUGF 1,"LOOP_output\n"
 
push ecx
push di
114,11 → 114,11
mov ebx, LOOPBACK_DEVICE
 
.done:
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_output: ptr=%x size=%u\n", eax, edx
DEBUGF 2,"LOOP_output: ptr=%x size=%u\n", eax, edx
ret
 
.out_of_ram:
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_output: failed\n"
DEBUGF 2,"LOOP_output: failed\n"
add esp, 2+4
sub edi, edi
ret
/kernel/branches/Kolibri-acpi/network/socket.inc
263,7 → 263,7
.number = ($ - .table) / 4 - 1
 
s_error:
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET: error\n"
DEBUGF 2,"SOCKET: error\n"
mov dword [esp+32], -1
 
ret
281,7 → 281,7
align 4
SOCKET_open:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi
DEBUGF 2,"SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi
 
push ecx edx esi
call SOCKET_alloc
289,7 → 289,7
jz s_error
 
mov [esp+32], edi ; return socketnumber
DEBUGF DEBUG_NETWORK_VERBOSE, "socknum=%u\n", edi
DEBUGF 2,"socknum=%u\n", edi
 
; push edx
; and edx, SO_NONBLOCK
321,7 → 321,7
je .pppoe
 
.no_ppp:
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_open: Unknown socket family/protocol\n"
DEBUGF 2,"Unknown socket family/protocol\n"
ret
 
align 4
394,7 → 394,7
align 4
SOCKET_bind:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
DEBUGF 2,"SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
 
call SOCKET_num_to_ptr
jz s_error
444,7 → 444,7
call SOCKET_check_port
jz s_error ; ZF is set by socket_check_port, on error
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_bind: local ip=%u.%u.%u.%u\n",\
DEBUGF 1,"SOCKET_bind: local ip=%u.%u.%u.%u\n",\
[eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
[eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
 
467,7 → 467,7
align 4
SOCKET_connect:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
DEBUGF 2,"SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
 
call SOCKET_num_to_ptr
jz s_error
616,7 → 616,7
align 4
SOCKET_listen:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
DEBUGF 2,"SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
 
call SOCKET_num_to_ptr
jz s_error
668,7 → 668,7
align 4
SOCKET_accept:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
DEBUGF 2,"SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
 
call SOCKET_num_to_ptr
jz s_error
718,7 → 718,7
align 4
SOCKET_close:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_close: socknum=%u\n", ecx
DEBUGF 2,"SOCKET_close: socknum=%u\n", ecx
 
call SOCKET_num_to_ptr
jz s_error
767,21 → 767,18
align 4
SOCKET_receive:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
DEBUGF 2,"SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
 
call SOCKET_num_to_ptr
jz s_error
 
call [eax + SOCKET.rcv_proc]
jmp [eax + SOCKET.rcv_proc]
 
mov [esp+32], eax
ret
 
 
align 4
SOCKET_receive_dgram:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: DGRAM\n"
DEBUGF 1,"SOCKET_receive: DGRAM\n"
 
mov ebx, esi
mov edi, edx ; addr to buffer
790,15 → 787,15
get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .block ; destroys esi and ecx
 
mov ecx, [esi + socket_queue_entry.data_size]
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: %u bytes data\n", ecx
DEBUGF 1,"SOCKET_receive: %u bytes data\n", ecx
 
cmp ecx, ebx
ja .too_small
 
push ecx
push [esi + socket_queue_entry.buf_ptr] ; save the buffer addr so we can clear it later
mov esi, [esi + socket_queue_entry.data_ptr]
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
DEBUGF 1,"SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
mov [esp+32+4], ecx ; return number of bytes copied
 
; copy the data
shr ecx, 1
815,20 → 812,16
.nd:
 
call kernel_free ; remove the packet
pop eax
 
ret
 
.too_small:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Buffer too small\n"
.fail:
mov eax, -1
ret
DEBUGF 2,"SOCKET_receive: Buffer too small\n"
jmp s_error
 
.block:
test [eax + SOCKET.options], SO_NONBLOCK
jnz .fail
jnz s_error
 
call SOCKET_block
jmp .loop
853,7 → 846,7
align 4
SOCKET_receive_stream:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: STREAM\n"
DEBUGF 1,"SOCKET_receive: STREAM\n"
 
mov ebx, edi
mov ecx, esi
873,11 → 866,12
call SOCKET_ring_read
call SOCKET_ring_free
 
mov eax, ecx ; return number of bytes copied
mov [esp+32], ecx ; return number of bytes copied
ret
 
.peek:
mov eax, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
mov ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
mov [esp+32], ecx ; return number of bytes available
ret
 
.block:
888,18 → 882,11
jmp .loop
 
.return0:
test [eax + SOCKET.options], SS_CANTRCVMORE
jz .ok
 
xor eax, eax
dec eax
xor ecx, ecx
mov [esp+32], ecx
ret
 
.ok:
xor eax, eax
ret
 
 
;-----------------------------------------------------------------
;
; SOCKET_send
915,7 → 902,7
align 4
SOCKET_send:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
DEBUGF 2,"SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
 
call SOCKET_num_to_ptr
jz s_error
929,7 → 916,7
align 4
SOCKET_send_udp:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: UDP\n"
DEBUGF 1,"SOCKET_send: UDP\n"
 
mov [esp+32], ecx
call UDP_output
941,7 → 928,7
align 4
SOCKET_send_tcp:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: TCP\n"
DEBUGF 1,"SOCKET_send: TCP\n"
 
push eax
add eax, STREAM_SOCKET.snd
957,7 → 944,7
align 4
SOCKET_send_ip:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n"
DEBUGF 1,"SOCKET_send: IPv4\n"
 
mov [esp+32], ecx
call IPv4_output_raw
969,7 → 956,7
align 4
SOCKET_send_icmp:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n"
DEBUGF 1,"SOCKET_send: ICMP\n"
 
mov [esp+32], ecx
call ICMP_output_raw
981,7 → 968,7
align 4
SOCKET_send_pppoe:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: PPPoE\n"
DEBUGF 1,"SOCKET_send: PPPoE\n"
 
mov [esp+32], ecx
mov ebx, [eax + SOCKET.device]
1011,7 → 998,7
align 4
SOCKET_send_local_:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: LOCAL\n"
DEBUGF 1,"SOCKET_send: LOCAL\n"
 
; get the other side's socket and check if it still exists
mov eax, [eax + SOCKET.device]
1050,7 → 1037,7
align 4
SOCKET_get_opt:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_get_opt\n"
DEBUGF 2,"SOCKET_get_opt\n"
 
call SOCKET_num_to_ptr
jz s_error
1100,7 → 1087,7
align 4
SOCKET_set_opt:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt\n"
DEBUGF 2,"SOCKET_set_opt\n"
 
call SOCKET_num_to_ptr
jz s_error
1129,7 → 1116,7
jz s_error
mov [eax + SOCKET.device], edx
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
DEBUGF 1,"SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
 
mov dword [esp+32], 0 ; success!
ret
1171,7 → 1158,7
align 4
SOCKET_pair:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_pair\n"
DEBUGF 2,"SOCKET_pair\n"
 
call SOCKET_alloc
jz s_error
1230,7 → 1217,7
align 4
SOCKET_debug:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_debug\n"
DEBUGF 1,"SOCKET_debug\n"
 
mov edi, edx
 
1279,7 → 1266,7
align 4
SOCKET_find_port:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_find_port\n"
DEBUGF 2,"SOCKET_find_port\n"
 
push ebx esi ecx
 
1340,7 → 1327,7
align 4
SOCKET_check_port:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_check_port: "
DEBUGF 2,"SOCKET_check_port: "
 
mov ecx, [eax + SOCKET.Protocol]
mov edx, [eax + IP_SOCKET.LocalIP]
1360,11 → 1347,11
cmp [esi + UDP_SOCKET.LocalPort], bx
jne .next_socket
 
DEBUGF DEBUG_NETWORK_VERBOSE, "local port %x already in use\n", bx ; FIXME: find a way to print big endian values with debugf
DEBUGF 2,"local port %x already in use\n", bx ; FIXME: find a way to print big endian values with debugf
ret
 
.port_ok:
DEBUGF DEBUG_NETWORK_VERBOSE, "local port %x is free\n", bx ; FIXME: find a way to print big endian values with debugf
DEBUGF 2,"local port %x is free\n", bx ; FIXME: find a way to print big endian values with debugf
mov [eax + UDP_SOCKET.LocalPort], bx
or bx, bx ; clear the zero-flag
ret
1391,7 → 1378,7
align 4
SOCKET_input:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
DEBUGF 2,"SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
 
mov [esp+4], ecx
push esi
1399,7 → 1386,7
 
add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_input: success\n"
DEBUGF 1,"SOCKET_input: success\n"
add esp, sizeof.socket_queue_entry
 
pusha
1410,7 → 1397,7
jmp SOCKET_notify
 
.full:
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket %x is full!\n", eax
DEBUGF 2,"SOCKET_input: socket %x is full!\n", eax
 
pusha
lea ecx, [eax + SOCKET.mutex]
1437,7 → 1424,7
stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
pop edx
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_created: %x\n", eax
DEBUGF 1,"SOCKET_ring_created: %x\n", eax
 
pusha
lea ecx, [esi + RING_BUFFER.mutex]
1471,7 → 1458,7
align 4
SOCKET_ring_write:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
DEBUGF 1,"SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
 
; lock mutex
pusha
1487,7 → 1474,7
mov ecx, edi
.copy:
mov edi, [eax + RING_BUFFER.write_ptr]
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
DEBUGF 2,"SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
 
; update write ptr
push edi
1545,7 → 1532,7
align 4
SOCKET_ring_read:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
DEBUGF 1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
 
pusha
lea ecx, [eax + RING_BUFFER.mutex]
1568,7 → 1555,7
ja .less_data
 
.copy:
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
DEBUGF 2,"SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
push ecx
shr ecx, 1
jnc .nb
1591,7 → 1578,7
call mutex_unlock ; TODO: check what registers this function actually destroys
popa
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: no data at all!\n"
DEBUGF 1,"SOCKET_ring_read: no data at all!\n"
xor ecx, ecx
ret
 
1615,7 → 1602,7
align 4
SOCKET_ring_free:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
DEBUGF 1,"SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
 
push eax ecx
lea ecx, [eax + RING_BUFFER.mutex]
1640,7 → 1627,7
ret
 
.error: ; we could free all available bytes, but that would be stupid, i guess..
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: buffer=%x error!\n", eax
DEBUGF 1,"SOCKET_ring_free: buffer=%x error!\n", eax
add [eax + RING_BUFFER.size], ecx
 
push eax
1665,7 → 1652,7
align 4
SOCKET_block:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax
DEBUGF 1,"SOCKET_block: %x\n", eax
 
pushf
cli
1680,7 → 1667,7
 
; Remember the thread ID so we can wake it up again
mov edx, [edx + TASKDATA.pid]
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_block: suspending thread: %u\n", edx
DEBUGF 1,"SOCKET_block: suspending thread: %u\n", edx
mov [eax + SOCKET.TID], edx
pop edx
 
1687,7 → 1674,7
call change_task
popf
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_block: continueing\n"
DEBUGF 1,"SOCKET_block: continueing\n"
 
ret
 
1705,7 → 1692,7
align 4
SOCKET_notify:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_notify: %x\n", eax
DEBUGF 1,"SOCKET_notify: %x\n", eax
 
call SOCKET_check
jz .error
1741,7 → 1728,7
shl ecx, 8
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Raised a network event!\n"
DEBUGF 1,"SOCKET_notify: Raised a network event!\n"
 
jmp .done
 
1769,7 → 1756,7
 
; Run the thread
mov [esi + TASKDATA.state], 0 ; Running
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Unblocked socket!\n"
DEBUGF 1,"SOCKET_notify: Unblocked socket!\n"
 
.done:
pop esi ecx eax
1798,7 → 1785,7
push ebx
 
stdcall kernel_alloc, SOCKETBUFFSIZE
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax
DEBUGF 1, "SOCKET_alloc: ptr=%x\n", eax
or eax, eax
jz .exit
 
1834,7 → 1821,7
.last_socket:
mov [last_socket_num], edi
mov [eax + SOCKET.Number], edi
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: number=%u\n", edi
DEBUGF 1, "SOCKET_alloc: number=%u\n", edi
 
; Fill in PID
mov ebx, [TASK_BASE]
1891,7 → 1878,7
align 4
SOCKET_free:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_free: %x\n", eax
DEBUGF 1, "SOCKET_free: %x\n", eax
 
call SOCKET_check
jz .error
1919,7 → 1906,7
mov ebx, [eax + SOCKET.NextPtr]
mov eax, [eax + SOCKET.PrevPtr]
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
DEBUGF 1, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
 
test eax, eax
jz @f
1934,7 → 1921,7
call kernel_free
pop ebx
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_free: success!\n"
DEBUGF 1, "SOCKET_free: success!\n"
 
.error:
ret
1952,7 → 1939,7
align 4
SOCKET_fork:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_fork: %x\n", ebx
DEBUGF 1,"SOCKET_fork: %x\n", ebx
 
; Exit if backlog queue is full
mov eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
1984,7 → 1971,7
.fail2:
add esp, 4+4+4
.fail:
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_fork: failed\n"
DEBUGF 1,"SOCKET_fork: failed\n"
xor eax, eax
ret
 
2003,7 → 1990,7
align 4
SOCKET_num_to_ptr:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_num_to_ptr: num=%u ", ecx
DEBUGF 1,"SOCKET_num_to_ptr: num=%u ", ecx
 
mov eax, net_sockets
 
2016,11 → 2003,11
 
test eax, eax
 
DEBUGF DEBUG_NETWORK_VERBOSE, "ptr=%x\n", eax
DEBUGF 1,"ptr=%x\n", eax
ret
 
.error:
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_nuto_ptr: not found\n", eax
DEBUGF 1,"not found\n", eax
ret
 
 
2038,7 → 2025,7
align 4
SOCKET_ptr_to_num:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ptr_to_num: ptr=%x ", eax
DEBUGF 1,"SOCKET_ptr_to_num: ptr=%x ", eax
 
call SOCKET_check
jz .error
2045,11 → 2032,11
 
mov eax, [eax + SOCKET.Number]
 
DEBUGF DEBUG_NETWORK_VERBOSE, "num=%u\n", eax
DEBUGF 1,"num=%u\n", eax
ret
 
.error:
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_ptr_to_num: not found\n", eax
DEBUGF 1,"not found\n", eax
ret
 
 
2067,7 → 2054,7
align 4
SOCKET_check:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_check: %x\n", eax
DEBUGF 1,"SOCKET_check: %x\n", eax
 
push ebx
mov ebx, net_sockets
2101,7 → 2088,7
align 4
SOCKET_check_owner:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_check_owner: %x\n", eax
DEBUGF 1,"SOCKET_check_owner: %x\n", eax
 
push ebx
mov ebx, [TASK_BASE]
2129,7 → 2116,7
align 4
SOCKET_process_end:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx
DEBUGF 1, "SOCKET_process_end: %x\n", edx
 
push ebx
mov ebx, net_sockets
2143,7 → 2130,7
cmp [ebx + SOCKET.PID], edx
jne .next_socket
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: killing socket %x\n", ebx
DEBUGF 1, "SOCKET_process_end: killing socket %x\n", ebx
 
mov [ebx + SOCKET.PID], 0
mov eax, ebx
2173,7 → 2160,7
align 4
SOCKET_is_connecting:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_connecting: %x\n", eax
DEBUGF 1,"SOCKET_is_connecting: %x\n", eax
 
and [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
or [eax + SOCKET.options], SS_ISCONNECTING
2194,7 → 2181,7
align 4
SOCKET_is_connected:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_connected: %x\n", eax
DEBUGF 1,"SOCKET_is_connected: %x\n", eax
 
and [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
or [eax + SOCKET.options], SS_ISCONNECTED
2216,7 → 2203,7
align 4
SOCKET_is_disconnecting:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnecting: %x\n", eax
DEBUGF 1,"SOCKET_is_disconnecting: %x\n", eax
 
and [eax + SOCKET.options], not (SS_ISCONNECTING)
or [eax + SOCKET.options], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
2237,7 → 2224,7
align 4
SOCKET_is_disconnected:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnected: %x\n", eax
DEBUGF 1,"SOCKET_is_disconnected: %x\n", eax
 
and [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
or [eax + SOCKET.options], SS_CANTRCVMORE + SS_CANTSENDMORE
2270,12 → 2257,10
align 4
SOCKET_cant_recv_more:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax
DEBUGF 1,"SOCKET_cant_recv_more: %x\n", eax
 
or [eax + SOCKET.options], SS_CANTRCVMORE
 
call SOCKET_notify
 
ret
 
 
2292,11 → 2277,8
align 4
SOCKET_cant_send_more:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_cant_send_more: %x\n", eax
DEBUGF 1,"SOCKET_cant_send_more: %x\n", eax
 
or [eax + SOCKET.options], SS_CANTSENDMORE
mov [eax + SOCKET.snd_proc], s_error
 
call SOCKET_notify
 
ret
/kernel/branches/Kolibri-acpi/network/stack.inc
28,9 → 28,6
net_tmr_count dw ?
endg
 
DEBUG_NETWORK_ERROR = 1
DEBUG_NETWORK_VERBOSE = 0
 
MAX_NET_DEVICES = 16
ARP_BLOCK = 1 ; true or false
 
308,12 → 305,12
align 4
NET_link_changed:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "NET_link_changed device=0x%x status=0x%x\n", ebx, [ebx + NET_DEVICE.state]
DEBUGF 1,"NET_link_changed device=0x%x status=0x%x\n", ebx, [ebx + NET_DEVICE.state]
 
align 4
NET_send_event:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "NET_send_event\n"
DEBUGF 1,"NET_send_event\n"
 
; Send event to all applications
push edi ecx
343,7 → 340,7
align 4
NET_add_device:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "NET_Add_Device: %x\n", ebx ;;; TODO: use mutex to lock net device list
DEBUGF 1,"NET_Add_Device: %x\n", ebx ;;; TODO: use mutex to lock net device list
 
cmp [NET_RUNNING], MAX_NET_DEVICES
jae .error
387,12 → 384,12
 
call NET_send_event
 
DEBUGF DEBUG_NETWORK_VERBOSE, "Device number: %u\n", eax
DEBUGF 1,"Device number: %u\n", eax
ret
 
.error:
or eax, -1
DEBUGF DEBUG_NETWORK_ERROR, "Adding network device failed\n"
DEBUGF 2,"Adding network device failed\n"
ret
 
 
410,7 → 407,7
align 4
NET_set_default:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "NET_set_default: device=%x\n", eax
DEBUGF 1,"NET_set_default: device=%x\n", eax
 
cmp eax, MAX_NET_DEVICES
jae .error
420,12 → 417,12
 
mov [NET_DEFAULT], eax
 
DEBUGF DEBUG_NETWORK_VERBOSE, "NET_set_default: succes\n"
DEBUGF 1,"NET_set_default: succes\n"
ret
 
.error:
or eax, -1
DEBUGF DEBUG_NETWORK_ERROR, "NET_set_default: failed\n"
DEBUGF 1,"NET_set_default: failed\n"
ret
 
 
637,7 → 634,7
.not_zero:
xchg dl, dh
 
DEBUGF DEBUG_NETWORK_VERBOSE, "Checksum: %x\n", dx
DEBUGF 1,"Checksum: %x\n", dx
 
ret
 
/kernel/branches/Kolibri-acpi/network/tcp_input.inc
60,7 → 60,7
 
.fail:
popf
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n"
DEBUGF 2, "TCP incoming queue is full, discarding packet!\n"
 
inc [TCP_segments_missed] ; FIXME: use correct interface
 
97,7 → 97,7
mov edi, [esi + TCP_queue_entry.ip_ptr] ; ptr to ipv4 source address, followed by ipv4 destination address
mov esi, [esi + TCP_queue_entry.segment_ptr] ; change esi last
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: size=%u time=%d\n", ecx, [timer_ticks]
DEBUGF 1,"TCP_input: size=%u time=%d\n", ecx, [timer_ticks]
 
mov edx, esi
 
127,7 → 127,7
movzx eax, [edx + TCP_header.DataOffset]
sub ecx, eax ; substract TCP header size from total segment size
jb .drop_no_socket ; If total segment size is less then the advertised header size, drop packet
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes of data\n", ecx
DEBUGF 1,"TCP_input: %u bytes of data\n", ecx
 
;-------------------------------------------
; Convert Big-endian values to little endian
176,7 → 176,7
test ax, ax
jnz .socket_loop
.found_socket: ; ebx now contains the socketpointer
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2
DEBUGF 1,"TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2
 
;-------------
; update stats
197,7 → 197,7
call mutex_lock
popa
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: socket locked\n"
DEBUGF 1,"TCP_input: socket locked\n"
 
;---------------------------
; disable all temporary bits
220,7 → 220,7
test [ebx + SOCKET.options], SO_ACCEPTCON
jz .no_accept
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Accepting new connection\n"
DEBUGF 1,"TCP_input: Accepting new connection\n"
 
pusha
lea ecx, [ebx + SOCKET.mutex]
263,7 → 263,7
cmp ecx, sizeof.TCP_header ; Does header contain any options?
je .no_options
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Segment has options\n"
DEBUGF 1,"TCP_input: Segment has options\n"
 
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
;;; cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
290,7 → 290,7
; je .opt_sack
cmp al, TCP_OPT_TIMESTAMP
je .opt_timestamp
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: unknown option:%u\n", al
DEBUGF 1,"TCP_input: unknown option:%u\n", al
jmp .no_options ; If we reach here, some unknown options were received, skip them all!
 
.opt_maxseg:
303,7 → 303,7
 
lodsw
rol ax, 8
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Maxseg=%u\n", ax
DEBUGF 1,"TCP_input: Maxseg=%u\n", ax
call TCP_mss
@@:
jmp .opt_loop
317,7 → 317,7
test [edx + TCP_header.Flags], TH_SYN
jz @f
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got window scale option\n"
DEBUGF 1,"TCP_input: Got window scale option\n"
or [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
 
lodsb
336,7 → 336,7
test [edx + TCP_header.Flags], TH_SYN
jz @f
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Selective Acknowledgement permitted\n"
DEBUGF 1,"TCP_input: Selective Acknowledgement permitted\n"
or [ebx + TCP_SOCKET.t_flags], TF_SACK_PERMIT
 
@@:
348,7 → 348,7
cmp al, 10 ; length must be 10
jne .no_options
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got timestamp option\n"
DEBUGF 1,"TCP_input: Got timestamp option\n"
 
test [edx + TCP_header.Flags], TH_SYN
jz @f
372,7 → 372,7
cmp eax, [ebx + TCP_SOCKET.ts_val]
jge .no_paws
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: PAWS: detected an old segment\n"
DEBUGF 1,"TCP_input: PAWS: detected an old segment\n"
 
mov eax, [esp+4+4] ; tcp_now
sub eax, [ebx + TCP_SOCKET.ts_recent_age]
450,7 → 450,7
sub eax, [ebx + TCP_SOCKET.SND_UNA]
jbe .not_uni_xfer
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are sender\n"
DEBUGF 1,"TCP_input: Header prediction: we are sender\n"
 
;---------------------------------
; Packet is a pure ACK, process it
524,7 → 524,7
 
; Complete processing of received data
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are receiving %u bytes\n", ecx
DEBUGF 1,"TCP_input: Header prediction: we are receiving %u bytes\n", ecx
 
add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied
 
545,7 → 545,7
 
.not_uni_xfer:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction failed\n"
DEBUGF 1,"TCP_input: Header prediction failed\n"
 
; Calculate receive window size
 
558,7 → 558,7
jg @f
mov eax, edx
@@:
DEBUGF DEBUG_NETWORK_VERBOSE, "Receive window size=%d\n", eax
DEBUGF 1,"Receive window size=%d\n", eax
mov [ebx + TCP_SOCKET.RCV_WND], eax
pop edx
 
579,12 → 579,12
sub eax, [edx + TCP_header.SequenceNumber]
jle .no_duplicate
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes duplicate data!\n", eax
DEBUGF 1,"TCP_input: %u bytes duplicate data!\n", eax
 
test [edx + TCP_header.Flags], TH_SYN
jz .no_dup_syn
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: got duplicate syn\n"
DEBUGF 1,"TCP_input: got duplicate syn\n"
 
and [edx + TCP_header.Flags], not (TH_SYN)
inc [edx + TCP_header.SequenceNumber]
613,7 → 613,7
 
; send an ACK and resynchronize and drop any data.
; But keep on processing for RST or ACK
DEBUGF DEBUG_NETWORK_VERBOSE, "616\n"
DEBUGF 1, "616\n"
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
mov eax, ecx
;TODO: update stats
658,7 → 658,7
sub eax, [ebx + TCP_SOCKET.RCV_WND] ; eax now holds the number of bytes to drop
jle .no_excess_data
 
DEBUGF DEBUG_NETWORK_VERBOSE, "%d bytes beyond right edge of window\n", eax
DEBUGF 1,"%d bytes beyond right edge of window\n", eax
 
;;; TODO: update stats
cmp eax, ecx
687,7 → 687,7
cmp eax, [ebx + TCP_SOCKET.RCV_NXT]
jne .drop_after_ack
 
DEBUGF DEBUG_NETWORK_VERBOSE, "690\n"
DEBUGF 1, "690\n"
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
;;; TODO: update stats
jmp .no_excess_data
715,7 → 715,7
sub eax, ecx
jae .no_timestamp
 
DEBUGF DEBUG_NETWORK_VERBOSE, "Recording timestamp\n"
DEBUGF 1,"Recording timestamp\n"
 
mov eax, [esp + 4] ; tcp_now
mov [ebx + TCP_SOCKET.ts_recent_age], eax
729,7 → 729,7
test [edx + TCP_header.Flags], TH_RST
jz .no_rst
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got an RST flag\n"
DEBUGF 1,"TCP_input: Got an RST flag\n"
 
mov eax, [ebx + TCP_SOCKET.t_state]
shl eax, 2
749,18 → 749,18
dd .rst_close ; TCPS_TIMED_WAIT
 
.econnrefused:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Connection refused\n"
DEBUGF 1,"TCP_input: Connection refused\n"
 
mov [ebx + SOCKET.errorcode], ECONNREFUSED
jmp .close
 
.econnreset:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Connection reset\n"
DEBUGF 1,"TCP_input: Connection reset\n"
 
mov [ebx + SOCKET.errorcode], ECONNRESET
 
.close:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Closing connection\n"
DEBUGF 1,"TCP_input: Closing connection\n"
 
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
;;; TODO: update stats (tcp drops)
769,7 → 769,7
jmp .drop_no_socket
 
.rst_close:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Closing with reset\n"
DEBUGF 1,"TCP_input: Closing with reset\n"
 
mov eax, ebx
call TCP_close
799,7 → 799,7
jb .ack_processed ; states: closed, listen, syn_sent
ja .no_syn_rcv ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_received\n"
DEBUGF 1,"TCP_input: state=syn_received\n"
 
mov eax, [edx + TCP_header.AckNumber]
cmp [ebx + TCP_SOCKET.SND_UNA], eax
846,7 → 846,7
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jne .reset_dupacks
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Processing duplicate ACK\n"
DEBUGF 1,"TCP_input: Processing duplicate ACK\n"
 
; If we have outstanding data, other than a window probe, this is a completely duplicate ACK
; (window info didnt change) The ACK is the biggest we've seen and we've seen exactly our rexmt threshold of them,
927,7 → 927,7
.no_re_xmit:
jbe .not_dup_ack
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Increasing congestion window\n"
DEBUGF 1,"TCP_input: Increasing congestion window\n"
 
mov eax, [ebx + TCP_SOCKET.t_maxseg]
add [ebx + TCP_SOCKET.SND_CWND], eax
980,7 → 980,7
 
;;; TODO: update stats
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: acceptable ACK for %u bytes\n", edi
DEBUGF 1,"TCP_input: acceptable ACK for %u bytes\n", edi
 
;------------------------------------------
; RTT measurements and retransmission timer (912-926)
1073,7 → 1073,7
call SOCKET_ring_free
pop ebx edx ecx
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is acked\n"
DEBUGF 1,"TCP_input: our FIN is acked\n"
stc
 
jmp .wakeup
1088,7 → 1088,7
sub [ebx + TCP_SOCKET.SND_WND], ecx
pop edx ecx
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is not acked\n"
DEBUGF 1,"TCP_input: our FIN is not acked\n"
clc
 
;----------------------------------------
1176,7 → 1176,7
align 4
.LISTEN:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=listen\n"
DEBUGF 1,"TCP_input: state=listen\n"
 
test [edx + TCP_header.Flags], TH_RST
jnz .drop
1228,7 → 1228,7
align 4
.SYN_SENT:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_sent\n"
DEBUGF 1,"TCP_input: state=syn_sent\n"
 
test [edx + TCP_header.Flags], TH_ACK
jz @f
1288,7 → 1288,7
test [edx + TCP_header.Flags], TH_ACK
jz .simultaneous_open
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: active open\n"
DEBUGF 1,"TCP_input: active open\n"
 
;;; TODO: update stats
 
1316,7 → 1316,7
 
.simultaneous_open:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: simultaneous open\n"
DEBUGF 1,"TCP_input: simultaneous open\n"
; We have received a syn but no ACK, so we are having a simultaneous open..
mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
 
1339,7 → 1339,7
 
.ack_processed:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK processed\n"
DEBUGF 1,"TCP_input: ACK processed\n"
 
;----------------------------------------------
; check if we need to update window information
1373,7 → 1373,7
@@:
mov [ebx + TCP_SOCKET.SND_WND], eax
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Updating window to %u\n", eax
DEBUGF 1,"TCP_input: Updating window to %u\n", eax
 
push [edx + TCP_header.SequenceNumber]
pop [ebx + TCP_SOCKET.SND_WL1]
1467,7 → 1467,7
 
call TCP_reassemble
 
DEBUGF DEBUG_NETWORK_VERBOSE, "1470\n"
DEBUGF 1, "1470\n"
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
 
.data_done:
1478,12 → 1478,12
test [edx + TCP_header.Flags], TH_FIN
jz .final_processing
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Processing FIN\n"
DEBUGF 1,"TCP_input: Processing FIN\n"
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
jae .not_first_fin
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: First FIN for this connection\n"
DEBUGF 1,"TCP_input: First FIN for this connection\n"
 
mov eax, ebx
call SOCKET_cant_recv_more
1534,7 → 1534,7
 
 
.drop_after_ack:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop after ACK\n"
DEBUGF 1,"TCP_input: Drop after ACK\n"
 
push edx ebx
lea ecx, [ebx + SOCKET.mutex]
1548,7 → 1548,7
jmp .need_output
 
.drop_with_reset:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop with reset\n"
DEBUGF 1,"TCP_input: Drop with reset\n"
 
push ebx edx
lea ecx, [ebx + SOCKET.mutex]
1571,7 → 1571,7
; Final processing
 
.final_processing:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n"
DEBUGF 1,"TCP_input: Final processing\n"
 
push ebx
lea ecx, [ebx + SOCKET.mutex]
1583,14 → 1583,14
 
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW
jz .dumpit
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n"
DEBUGF 1,"TCP_input: ACK now!\n"
 
.need_output:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n"
DEBUGF 1,"TCP_input: need output\n"
call TCP_output
 
.dumpit:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n"
DEBUGF 1,"TCP_input: dumping\n"
 
call kernel_free
add esp, 4
1641,7 → 1641,7
; Drop
 
.drop:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Dropping segment\n"
DEBUGF 1,"TCP_input: Dropping segment\n"
 
pusha
lea ecx, [ebx + SOCKET.mutex]
1656,7 → 1656,7
call SOCKET_free
 
.drop_no_socket:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop (no socket)\n"
DEBUGF 1,"TCP_input: Drop (no socket)\n"
 
call kernel_free
add esp, 4
/kernel/branches/Kolibri-acpi/network/tcp_output.inc
28,7 → 28,7
align 4
TCP_output:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: socket=%x\n", eax
DEBUGF 1,"TCP_output: socket=%x\n", eax
 
push eax
lea ecx, [eax + SOCKET.mutex]
78,7 → 78,7
cmp [eax + TCP_SOCKET.t_force], 0
je .no_force
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: forcing data out\n"
DEBUGF 1,"TCP_output: forcing data out\n"
 
test ecx, ecx
jnz .no_zero_window
202,7 → 202,7
;----------------------------------------
; Check if a window update should be sent (154)
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: window=%d\n", ecx
DEBUGF 1,"TCP_output: window=%d\n", ecx
 
; Compare available window to amount of window known to peer (as advertised window less next expected input)
; If the difference is at least two max size segments, or at least 50% of the maximum possible window,
237,7 → 237,7
;--------------------------
; Should a segment be sent? (174)
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: 174\n"
DEBUGF 1,"TCP_output: 174\n"
 
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW ; we need to ACK
jnz TCP_send
273,7 → 273,7
cmp [eax + TCP_SOCKET.timer_persist], 0 ; Persist timer already expired?
jne @f
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: Entering persist state\n"
DEBUGF 1,"TCP_output: Entering persist state\n"
 
mov [eax + TCP_SOCKET.t_rxtshift], 0
call TCP_set_persist
282,7 → 282,7
;----------------------------
; No reason to send a segment (219)
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: No reason to send a segment\n"
DEBUGF 1,"TCP_output: No reason to send a segment\n"
 
pusha
lea ecx, [eax + SOCKET.mutex]
313,7 → 313,7
align 4
TCP_send:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: socket=%x length=%u flags=%x\n", eax, esi, dl
DEBUGF 1,"TCP_send: socket=%x length=%u flags=%x\n", eax, esi, dl
 
push eax ; save socket ptr
push esi ; and data length too
337,7 → 337,7
push ecx
add di, 4
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: added maxseg option\n"
DEBUGF 1,"TCP_send: added maxseg option\n"
 
test [eax + TCP_SOCKET.t_flags], TF_REQ_SCALE
jz .no_scale
355,7 → 355,7
pushw TCP_OPT_WINDOW + 3 shl 8
add di, 4
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: added scale option\n"
DEBUGF 1,"TCP_send: added scale option\n"
 
.no_scale:
.no_syn:
381,7 → 381,7
pushd TCP_OPT_NOP + TCP_OPT_NOP shl 8 + TCP_OPT_TIMESTAMP shl 16 + 10 shl 24
add di, 12
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: added timestamp\n"
DEBUGF 1,"TCP_send: added timestamp\n"
 
.no_timestamp:
 
538,7 → 538,7
;----------------
; Send the packet
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: Sending with device %x\n", ebx
DEBUGF 1,"TCP_send: Sending with device %x\n", ebx
call [ebx + NET_DEVICE.transmit]
jnz .send_error
 
580,7 → 580,7
test [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT
jnz TCP_output.again
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: success!\n"
DEBUGF 1,"TCP_send: success!\n"
 
xor eax, eax
ret
597,7 → 597,7
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: IP error\n"
DEBUGF 1,"TCP_send: IP error\n"
 
or eax, -1
ret
609,7 → 609,7
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: sending failed\n"
DEBUGF 1,"TCP_send: sending failed\n"
 
or eax, -2
ret
/kernel/branches/Kolibri-acpi/network/tcp_subr.inc
119,7 → 119,7
align 4
TCP_pull_out_of_band:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_pull_out_of_band\n"
DEBUGF 1,"TCP_pull_out_of_band\n"
 
;;;; 1282-1305
 
145,7 → 145,7
align 4
TCP_drop:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_drop: %x\n", eax
DEBUGF 1,"TCP_drop: %x\n", eax
 
cmp [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
jb .no_syn_received
184,7 → 184,7
align 4
TCP_close:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_close: %x\n", eax
DEBUGF 1,"TCP_close: %x\n", eax
 
;;; TODO: update RTT and mean deviation
;;; TODO: update slow start threshold
212,7 → 212,7
mov edx, [eax + TCP_SOCKET.t_state]
movzx edx, byte [edx + .flaglist]
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_outflags: socket=%x flags=%x\n", eax, dl
DEBUGF 1,"TCP_outflags: socket=%x flags=%x\n", eax, dl
 
ret
 
248,7 → 248,7
align 4
TCP_respond:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: socket=%x flags=%x\n", ebx, cl
DEBUGF 1,"TCP_respond_socket: socket=%x flags=%x\n", ebx, cl
 
;---------------------
; Create the IP packet
305,7 → 305,7
ret
 
.error:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: failed\n"
DEBUGF 1,"TCP_respond_socket: failed\n"
add esp, 2 + 4
 
ret
327,7 → 327,7
align 4
TCP_respond_segment:
 
DEBUGF DEBUG_NETWORK_VERBOSE,"TCP_respond_segment: frame=%x flags=%x\n", edx, cl
DEBUGF 1,"TCP_respond_segment: frame=%x flags=%x\n", edx, cl
 
;---------------------
; Create the IP packet
381,7 → 381,7
ret
 
.error:
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_segment: failed\n"
DEBUGF 1,"TCP_respond_segment: failed\n"
add esp, 2+4
 
ret
416,7 → 416,7
align 4
TCP_set_persist:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_set_persist\n"
DEBUGF 1,"TCP_set_persist\n"
 
; First, check if retransmit timer is not set, retransmit and persist are mutually exclusive
 
454,7 → 454,7
align 4
TCP_xmit_timer:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_xmit_timer: socket=%x rtt=%d0ms\n", ebx, eax
DEBUGF 1,"TCP_xmit_timer: socket=%x rtt=%d0ms\n", ebx, eax
 
;TODO: update stats
 
/kernel/branches/Kolibri-acpi/network/tcp_timer.inc
87,7 → 87,7
dec [eax + TCP_SOCKET.timer_retransmission]
jnz .check_more2
 
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: Retransmission timer expired\n", eax
DEBUGF 1,"socket %x: Retransmission timer expired\n", eax
 
push eax
call TCP_output
97,7 → 97,7
dec [eax + TCP_SOCKET.timer_keepalive]
jnz .check_more3
 
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: Keepalive expired\n", eax
DEBUGF 1,"socket %x: Keepalive expired\n", eax
 
cmp [eax + TCP_SOCKET.state], TCPS_ESTABLISHED
ja .dont_kill
126,13 → 126,13
dec [eax + TCP_SOCKET.timer_timed_wait]
jnz .check_more5
 
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: 2MSL timer expired\n", eax
DEBUGF 1,"socket %x: 2MSL timer expired\n", eax
 
.check_more5:
dec [eax + TCP_SOCKET.timer_persist]
jnz .loop
 
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: persist timer expired\n", eax
DEBUGF 1,"socket %x: persist timer expired\n", eax
 
call TCP_set_persist
mov [eax + TCP_SOCKET.t_force], 1
/kernel/branches/Kolibri-acpi/network/tcp_usreq.inc
27,7 → 27,7
align 4
TCP_usrclosed:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_usrclosed: %x\n", eax
DEBUGF 1,"TCP_usrclosed: %x\n", eax
 
push ebx
mov ebx, [eax + TCP_SOCKET.t_state]
87,7 → 87,7
align 4
TCP_disconnect:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_disconnect: %x\n", eax
DEBUGF 1,"TCP_disconnect: %x\n", eax
 
cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
jb TCP_close
/kernel/branches/Kolibri-acpi/network/udp.inc
116,7 → 116,7
align 4
UDP_input:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: size=%u\n", ecx
DEBUGF 1,"UDP_input: size=%u\n", ecx
 
; First validate, checksum
 
129,7 → 129,7
jnz .checksum_mismatch
 
.no_checksum:
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: checksum ok\n"
DEBUGF 1,"UDP_input: checksum ok\n"
 
; Convert length to little endian
 
158,7 → 158,7
cmp [eax + UDP_SOCKET.LocalPort], dx
jne .next_socket
 
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: socket=%x\n", eax
DEBUGF 1,"UDP_input: socket=%x\n", eax
 
;;; TODO: when packet is processed, check more sockets!
 
196,7 → 196,7
call mutex_lock
popa
 
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf
DEBUGF 1,"UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf
mov [eax + UDP_SOCKET.RemotePort], cx
inc [eax + UDP_SOCKET.firstpacket]
 
204,12 → 204,12
 
 
.checksum_mismatch:
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: checksum mismatch\n"
DEBUGF 2,"UDP_input: checksum mismatch\n"
 
.dump:
call kernel_free
add esp, 4 ; pop (balance stack)
DEBUGF DEBUG_NETWORK_VERBOSE,"UDP_input: dumping\n"
DEBUGF 2,"UDP_input: dumping\n"
 
ret
 
229,13 → 229,13
align 4
UDP_output:
 
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi
DEBUGF 1,"UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi
 
mov dx, [eax + UDP_SOCKET.RemotePort]
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_output: remote port=%x, ", dx ; FIXME: find a way to print big endian values with debugf
DEBUGF 1,"UDP_output: remote port=%x, ", dx ; FIXME: find a way to print big endian values with debugf
rol edx, 16
mov dx, [eax + UDP_SOCKET.LocalPort]
DEBUGF DEBUG_NETWORK_VERBOSE, "local port=%x\n", dx
DEBUGF 1,"local port=%x\n", dx
 
sub esp, 8 ; Data ptr and data size will be placed here
push edx esi
270,7 → 270,7
mov [edi + UDP_header.Checksum], 0
UDP_checksum (edi-4), (edi-8) ; FIXME: IPv4 packet could have options..
 
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_output: sending with device %x\n", ebx
DEBUGF 1,"UDP_output: sending with device %x\n", ebx
call [ebx + NET_DEVICE.transmit]
test eax, eax
jnz @f
280,7 → 280,7
ret
 
.fail:
DEBUGF DEBUG_NETWORK_ERROR, "UDP_output: failed\n"
DEBUGF 1,"UDP_output: failed\n"
add esp, 4+4+8
or eax, -1
ret
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/pcnet32.inc
0,0 → 1,848
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; PCNET32.INC ;;
;; ;;
;; Ethernet driver for Menuet OS ;;
;; ;;
;; - Version 1.0 31 July 2004: ;;
;; Initial release ;;
;; ;;
;; - Version 1.01 29 March 2008: ;;
;; Adapted to work with kolibrios flat kernel ;;
;; Debug info is updated, and now uses DEBUGF macro ;;
;; by hidnplayr@kolibrios.org ;;
;; ;;
;; This driver is based on the PCNet32 driver from ;;
;; the etherboot 5.0.6 project. The copyright statement is ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; remaining parts Copyright 2004 Jarek Pelczar, ;;
;; jpelczar@interia.pl ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
PCNET32_PORT_AUI equ 0x00
PCNET32_PORT_10BT equ 0x01
PCNET32_PORT_GPSI equ 0x02
PCNET32_PORT_MII equ 0x03
PCNET32_PORT_PORTSEL equ 0x03
PCNET32_PORT_ASEL equ 0x04
PCNET32_PORT_100 equ 0x40
PCNET32_PORT_FD equ 0x80
PCNET32_DMA_MASK equ 0xffffffff
 
PCNET32_LOG_TX_BUFFERS equ 1
PCNET32_LOG_RX_BUFFERS equ 2
 
PCNET32_TX_RING_SIZE equ (1 shl PCNET32_LOG_TX_BUFFERS)
PCNET32_TX_RING_MOD_MASK equ (PCNET32_TX_RING_SIZE-1)
PCNET32_TX_RING_LEN_BITS equ 0
PCNET32_RX_RING_SIZE equ (1 shl PCNET32_LOG_RX_BUFFERS)
PCNET32_RX_RING_MOD_MASK equ (PCNET32_RX_RING_SIZE-1)
PCNET32_RX_RING_LEN_BITS equ (PCNET32_LOG_RX_BUFFERS shl 4)
PCNET32_PKT_BUF_SZ equ 1544
PCNET32_PKT_BUF_SZ_NEG equ 0xf9f8
 
pcnet32_txb equ (eth_data_start)
pcnet32_rxb equ ((pcnet32_txb+(PCNET32_PKT_BUF_SZ*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0)
pcnet32_tx_ring equ ((pcnet32_rxb+(PCNET32_PKT_BUF_SZ*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0)
pcnet32_rx_ring equ ((pcnet32_tx_ring+(16*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0)
 
virtual at ((pcnet32_rx_ring+(16*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0)
pcnet32_private:
.mode dw ?
.tlen_rlen dw ?
.phys_addr db ?,?,?,?,?,?
.reserved dw ?
.filter dd ?,?
.rx_ring dd ?
.tx_ring dd ?
.cur_rx dd ?
.cur_tx dd ?
.dirty_rx dd ?
.dirty_tx dd ?
.tx_full db ?
.options dd ?
.full_duplex db ?
.chip_version dd ?
.mii db ?
.ltint db ?
.dxsuflo db ?
.fset db ?
.fdx db ?
end virtual
 
virtual at 0
pcnet32_rx_head:
.base dd ?
.buf_length dw ?
.status dw ?
.msg_length dd ?
.reserved dd ?
end virtual
 
virtual at 0
pcnet32_tx_head:
.base dd ?
.length dw ?
.status dw ?
.misc dd ?
.reserved dd ?
end virtual
 
uglobal
pcnet32_access:
.read_csr dd ?
.write_csr dd ?
.read_bcr dd ?
.write_bcr dd ?
.read_rap dd ?
.write_rap dd ?
.reset dd ?
endg
 
iglobal
pcnet32_options_mapping:
dd PCNET32_PORT_ASEL ; 0 Auto-select
dd PCNET32_PORT_AUI ; 1 BNC/AUI
dd PCNET32_PORT_AUI ; 2 AUI/BNC
dd PCNET32_PORT_ASEL ; 3 not supported
dd PCNET32_PORT_10BT or PCNET32_PORT_FD ; 4 10baseT-FD
dd PCNET32_PORT_ASEL ; 5 not supported
dd PCNET32_PORT_ASEL ; 6 not supported
dd PCNET32_PORT_ASEL ; 7 not supported
dd PCNET32_PORT_ASEL ; 8 not supported
dd PCNET32_PORT_MII ; 9 MII 10baseT
dd PCNET32_PORT_MII or PCNET32_PORT_FD ; 10 MII 10baseT-FD
dd PCNET32_PORT_MII ; 11 MII (autosel)
dd PCNET32_PORT_10BT ; 12 10BaseT
dd PCNET32_PORT_MII or PCNET32_PORT_100 ; 13 MII 100BaseTx
dd PCNET32_PORT_MII or PCNET32_PORT_100 or PCNET32_PORT_FD ; 14 MII 100BaseTx-FD
dd PCNET32_PORT_ASEL ; 15 not supported
endg
 
PCNET32_WIO_RDP equ 0x10
PCNET32_WIO_RAP equ 0x12
PCNET32_WIO_RESET equ 0x14
PCNET32_WIO_BDP equ 0x16
PCNET32_DWIO_RDP equ 0x10
PCNET32_DWIO_RAP equ 0x14
PCNET32_DWIO_RESET equ 0x18
PCNET32_DWIO_BDP equ 0x1C
PCNET32_TOTAL_SIZE equ 0x20
; ebx - index
; return:
; eax - data
pcnet32_wio_read_csr:
push edx
lea edx, [ebp+PCNET32_WIO_RAP]
mov ax, bx
out dx, ax
lea edx, [ebp+PCNET32_WIO_RDP]
in ax, dx
and eax, 0xffff
pop edx
ret
; eax - data
; ebx - index
pcnet32_wio_write_csr:
push edx
lea edx, [ebp+PCNET32_WIO_RAP]
xchg eax, ebx
out dx, ax
xchg eax, ebx
lea edx, [ebp+PCNET32_WIO_RDP]
out dx, ax
pop edx
ret
; ebx - index
; return:
; eax - data
pcnet32_wio_read_bcr:
push edx
lea edx, [ebp+PCNET32_WIO_RAP]
mov ax, bx
out dx, ax
lea edx, [ebp+PCNET32_WIO_BDP]
in ax, dx
and eax, 0xffff
pop edx
ret
; eax - data
; ebx - index
pcnet32_wio_write_bcr:
push edx
lea edx, [ebp+PCNET32_WIO_RAP]
xchg eax, ebx
out dx, ax
xchg eax, ebx
lea edx, [ebp+PCNET32_WIO_BDP]
out dx, ax
pop edx
ret
pcnet32_wio_read_rap:
push edx
lea edx, [ebp+PCNET32_WIO_RAP]
in ax, dx
and eax, 0xffff
pop edx
ret
; eax - val
pcnet32_wio_write_rap:
push edx
lea edx, [ebp+PCNET32_WIO_RAP]
out dx, ax
pop edx
ret
pcnet32_wio_reset:
push edx
push eax
lea edx, [ebp+PCNET32_WIO_RESET]
in ax, dx
pop eax
pop edx
ret
pcnet32_wio_check:
push edx
mov ax, 88
lea edx, [ebp+PCNET32_WIO_RAP]
out dx, ax
nop
nop
in ax, dx
cmp ax, 88
sete al
pop edx
ret
 
iglobal
pcnet32_wio:
dd pcnet32_wio_read_csr
dd pcnet32_wio_write_csr
dd pcnet32_wio_read_bcr
dd pcnet32_wio_write_bcr
dd pcnet32_wio_read_rap
dd pcnet32_wio_write_rap
dd pcnet32_wio_reset
endg
 
; ebx - index
; return:
; eax - data
pcnet32_dwio_read_csr:
push edx
lea edx, [ebp+PCNET32_DWIO_RAP]
mov eax, ebx
out dx, eax
lea edx, [ebp+PCNET32_DWIO_RDP]
in eax, dx
and eax, 0xffff
pop edx
ret
; ebx - index
; eax - data
pcnet32_dwio_write_csr:
push edx
lea edx, [ebp+PCNET32_DWIO_RAP]
xchg eax, ebx
out dx, eax
lea edx, [ebp+PCNET32_DWIO_RDP]
xchg eax, ebx
out dx, eax
pop edx
ret
; ebx - index
; return:
; eax - data
pcnet32_dwio_read_bcr:
push edx
lea edx, [ebp+PCNET32_DWIO_RAP]
mov eax, ebx
out dx, eax
lea edx, [ebp+PCNET32_DWIO_BDP]
in eax, dx
and eax, 0xffff
pop edx
ret
; ebx - index
; eax - data
pcnet32_dwio_write_bcr:
push edx
lea edx, [ebp+PCNET32_DWIO_RAP]
xchg eax, ebx
out dx, eax
lea edx, [ebp+PCNET32_DWIO_BDP]
xchg eax, ebx
out dx, eax
pop edx
ret
pcnet32_dwio_read_rap:
push edx
lea edx, [ebp+PCNET32_DWIO_RAP]
in eax, dx
and eax, 0xffff
pop edx
ret
; eax - val
pcnet32_dwio_write_rap:
push edx
lea edx, [ebp+PCNET32_DWIO_RAP]
out dx, eax
pop edx
ret
pcnet32_dwio_reset:
push edx
push eax
lea edx, [ebp+PCNET32_DWIO_RESET]
in eax, dx
pop eax
pop edx
ret
pcnet32_dwio_check:
push edx
lea edx, [PCNET32_DWIO_RAP]
mov eax, 88
out dx, eax
nop
nop
in eax, dx
and eax, 0xffff
cmp eax, 88
sete al
pop edx
ret
 
iglobal
pcnet32_dwio:
dd pcnet32_dwio_read_csr
dd pcnet32_dwio_write_csr
dd pcnet32_dwio_read_bcr
dd pcnet32_dwio_write_bcr
dd pcnet32_dwio_read_rap
dd pcnet32_dwio_write_rap
dd pcnet32_dwio_reset
endg
 
 
 
pcnet32_init_ring:
mov [pcnet32_private.tx_full], 0
mov [pcnet32_private.cur_rx], 0
mov [pcnet32_private.cur_tx], 0
mov [pcnet32_private.dirty_rx], 0
mov [pcnet32_private.dirty_tx], 0
mov edi, pcnet32_rx_ring
mov ecx, PCNET32_RX_RING_SIZE
mov ebx, pcnet32_rxb
sub ebx, OS_BASE
.rx_init:
mov [edi+pcnet32_rx_head.base], ebx
mov [edi+pcnet32_rx_head.buf_length], word PCNET32_PKT_BUF_SZ_NEG
mov [edi+pcnet32_rx_head.status], word 0x8000
add ebx, PCNET32_PKT_BUF_SZ
; inc ebx
add edi, 16
loop .rx_init
mov edi, pcnet32_tx_ring
mov ecx, PCNET32_TX_RING_SIZE
.tx_init:
mov [edi+pcnet32_tx_head.base], dword 0
mov [edi+pcnet32_tx_head.status], word 0
add edi, 16
loop .tx_init
mov [pcnet32_private.tlen_rlen], (PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS)
mov esi, node_addr
mov edi, pcnet32_private.phys_addr
cld
movsd
movsw
mov eax, pcnet32_rx_ring
sub eax, OS_BASE
mov dword [pcnet32_private.rx_ring], eax
 
mov eax, pcnet32_tx_ring
sub eax, OS_BASE
mov dword [pcnet32_private.tx_ring], eax
ret
 
 
 
pcnet32_reset:
; Reset PCNET32
mov ebp, [io_addr]
call dword [pcnet32_access.reset]
; set 32bit mode
mov ebx, 20
mov eax, 2
call dword [pcnet32_access.write_bcr]
; set/reset autoselect bit
mov ebx, 2
call dword [pcnet32_access.read_bcr]
and eax, not 2
test [pcnet32_private.options], PCNET32_PORT_ASEL
jz .L1
or eax, 2
.L1:
call dword [pcnet32_access.write_bcr]
; Handle full duplex setting
cmp byte [pcnet32_private.full_duplex], 0
je .L2
mov ebx, 9
call dword [pcnet32_access.read_bcr]
and eax, not 3
test [pcnet32_private.options], PCNET32_PORT_FD
jz .L3
or eax, 1
cmp [pcnet32_private.options], PCNET32_PORT_FD or PCNET32_PORT_AUI
jne .L4
or eax, 2
jmp .L4
.L3:
test [pcnet32_private.options], PCNET32_PORT_ASEL
jz .L4
cmp [pcnet32_private.chip_version], 0x2627
jne .L4
or eax, 3
.L4:
mov ebx, 9
call dword [pcnet32_access.write_bcr]
.L2:
; set/reset GPSI bit
mov ebx, 124
call dword [pcnet32_access.read_csr]
mov ecx, [pcnet32_private.options]
and ecx, PCNET32_PORT_PORTSEL
cmp ecx, PCNET32_PORT_GPSI
jne .L5
or eax, 0x10
.L5:
call dword [pcnet32_access.write_csr]
cmp [pcnet32_private.mii], 0
je .L6
test [pcnet32_private.options], PCNET32_PORT_ASEL
jnz .L6
mov ebx, 32
call dword [pcnet32_access.read_bcr]
and eax, not 0x38
test [pcnet32_private.options], PCNET32_PORT_FD
jz .L7
or eax, 0x10
.L7:
test [pcnet32_private.options], PCNET32_PORT_100
jz .L8
or eax, 0x08
.L8:
call dword [pcnet32_access.write_bcr]
jmp .L9
.L6:
test [pcnet32_private.options], PCNET32_PORT_ASEL
jz .L9
mov ebx, 32
; DEBUGF 1," K : ASEL, enable auto-negotiation\n"
call dword [pcnet32_access.read_bcr]
and eax, not 0x98
or eax, 0x20
call dword [pcnet32_access.write_bcr]
.L9:
cmp [pcnet32_private.ltint], 0
je .L10
mov ebx, 5
call dword [pcnet32_access.read_csr]
or eax, (1 shl 14)
call dword [pcnet32_access.write_csr]
.L10:
mov eax, [pcnet32_private.options]
and eax, PCNET32_PORT_PORTSEL
shl eax, 7
mov [pcnet32_private.mode], ax
mov [pcnet32_private.filter], dword 0xffffffff
mov [pcnet32_private.filter+4], dword 0xffffffff
call pcnet32_init_ring
mov ebx, 1
mov eax, pcnet32_private
sub eax, OS_BASE
and eax, 0xffff
call dword [pcnet32_access.write_csr]
mov eax, pcnet32_private
sub eax, OS_BASE
mov ebx, 2
shr eax, 16
call dword [pcnet32_access.write_csr]
mov ebx, 4
mov eax, 0x0915
call dword [pcnet32_access.write_csr]
mov ebx, 0
mov eax, 1
call dword [pcnet32_access.write_csr]
mov ecx, 100
.L11:
xor ebx, ebx
call dword [pcnet32_access.read_csr]
test ax, 0x100
jnz .L12
loop .L11
.L12:
; DEBUGF 1," K : hardware reset\n"
xor ebx, ebx
mov eax, 0x0002
call dword [pcnet32_access.write_csr]
xor ebx, ebx
call dword [pcnet32_access.read_csr]
; DEBUGF 1," K : PCNET reset complete\n"
ret
 
 
 
pcnet32_adjust_pci_device:
;*******Get current setting************************
mov al, 2 ;read a word
mov bh, [pci_dev]
mov ah, [pci_bus]
mov bl, 0x04 ;from command Register
call pci_read_reg
;******see if its already set as bus master********
mov bx, ax
and bx, 5
cmp bx, 5
je pcnet32_adjust_pci_device_Latency
;******Make card a bus master*******
mov cx, ax ;value to write
mov bh, [pci_dev]
mov al, 2 ;write a word
or cx, 5
mov ah, [pci_bus]
mov bl, 0x04 ;to command register
call pci_write_reg
;******Check latency setting***********
pcnet32_adjust_pci_device_Latency:
;*******Get current latency setting************************
; mov al, 1 ;read a byte
; mov bh, [pci_dev]
; mov ah, [pci_bus]
; mov bl, 0x0D ;from Lantency Timer Register
; call pci_read_reg
;******see if its aat least 64 clocks********
; cmp ax,64
; jge pcnet32_adjust_pci_device_Done
;******Set latency to 32 clocks*******
; mov cx, 64 ;value to write
; mov bh, [pci_dev]
; mov al, 1 ;write a byte
; mov ah, [pci_bus]
; mov bl, 0x0D ;to Lantency Timer Register
; call pci_write_reg
;******Check latency setting***********
pcnet32_adjust_pci_device_Done:
ret
 
 
 
 
pcnet32_probe:
mov ebp, [io_addr]
call pcnet32_wio_reset
xor ebx, ebx
call pcnet32_wio_read_csr
cmp eax, 4
jne .try_dwio
call pcnet32_wio_check
and al, al
jz .try_dwio
; DEBUGF 1," K : Using WIO\n"
mov esi, pcnet32_wio
jmp .L1
.try_dwio:
call pcnet32_dwio_reset
xor ebx, ebx
call pcnet32_dwio_read_csr
cmp eax, 4
jne .no_dev
call pcnet32_dwio_check
and al, al
jz .no_dev
; DEBUGF 1," K : Using DWIO\n"
mov esi, pcnet32_dwio
jmp .L1
.no_dev:
DEBUGF 1," K : PCNET32 not found\n"
ret
.L1:
mov edi, pcnet32_access
mov ecx, 7
cld
rep movsd
mov ebx, 88
call dword [pcnet32_access.read_csr]
mov ecx, eax
mov ebx, 89
call dword [pcnet32_access.read_csr]
shl eax, 16
or eax, ecx
mov ecx, eax
and ecx, 0xfff
cmp ecx, 3
jne .no_dev
shr eax, 12
and eax, 0xffff
mov [pcnet32_private.chip_version], eax
; DEBUGF 1," K : PCNET32 chip version OK\n"
mov [pcnet32_private.fdx], 0
mov [pcnet32_private.mii], 0
mov [pcnet32_private.fset], 0
mov [pcnet32_private.dxsuflo], 0
mov [pcnet32_private.ltint], 0
mov eax, [pcnet32_private.chip_version]
cmp eax, 0x2420
je .L2
cmp eax, 0x2430
je .L3
cmp eax, 0x2621
je .L4
cmp eax, 0x2623
je .L5
cmp eax, 0x2624
je .L6
cmp eax, 0x2625
je .L7
cmp eax, 0x2626
je .L8
cmp eax, 0x2627
je .L9
DEBUGF 1," K : Invalid chip rev\n"
jmp .no_dev
.L2:
; DEBUGF 1," K : PCnet/PCI 79C970\n"
jmp .L10
.L3:
; DEBUGF 1," K : PCnet/PCI 79C970\n"
jmp .L10
.L4:
; DEBUGF 1," K : PCnet/PCI II 79C970A\n"
mov [pcnet32_private.fdx], 1
jmp .L10
.L5:
; DEBUGF 1," K : PCnet/FAST 79C971\n"
mov [pcnet32_private.fdx], 1
mov [pcnet32_private.mii], 1
mov [pcnet32_private.fset], 1
mov [pcnet32_private.ltint], 1
jmp .L10
.L6:
; DEBUGF 1," K : PCnet/FAST+ 79C972\n"
mov [pcnet32_private.fdx], 1
mov [pcnet32_private.mii], 1
mov [pcnet32_private.fset], 1
jmp .L10
.L7:
; DEBUGF 1," K : PCnet/FAST III 79C973\n"
mov [pcnet32_private.fdx], 1
mov [pcnet32_private.mii], 1
jmp .L10
.L8:
; DEBUGF 1," K : PCnet/Home 79C978\n"
mov [pcnet32_private.fdx], 1
mov ebx, 49
call dword [pcnet32_access.read_bcr]
call dword [pcnet32_access.write_bcr]
jmp .L10
.L9:
; DEBUGF 1," K : PCnet/FAST III 79C975\n"
mov [pcnet32_private.fdx], 1
mov [pcnet32_private.mii], 1
.L10:
cmp [pcnet32_private.fset], 1
jne .L11
mov ebx, 18
call dword [pcnet32_access.read_bcr]
or eax, 0x800
call dword [pcnet32_access.write_bcr]
mov ebx, 80
call dword [pcnet32_access.read_csr]
and eax, 0xc00
or eax, 0xc00
call dword [pcnet32_access.write_csr]
mov [pcnet32_private.dxsuflo], 1
mov [pcnet32_private.ltint], 1
.L11:
; read MAC
mov edi, node_addr
mov edx, ebp
mov ecx, 6
.Lmac:
in al, dx
stosb
inc edx
loop .Lmac
; DEBUGF 1," K : MAC read\n"
call pcnet32_adjust_pci_device
; DEBUGF 1," K : PCI done\n"
mov eax, PCNET32_PORT_ASEL
mov [pcnet32_private.options], eax
mov [pcnet32_private.mode], word 0x0003
mov [pcnet32_private.tlen_rlen], word (PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS)
mov esi, node_addr
mov edi, pcnet32_private.phys_addr
cld
movsd
movsw
mov [pcnet32_private.filter], dword 0
mov [pcnet32_private.filter+4], dword 0
mov eax, pcnet32_rx_ring
sub eax, OS_BASE
mov dword [pcnet32_private.rx_ring], eax
 
mov eax, pcnet32_tx_ring
sub eax, OS_BASE
mov dword [pcnet32_private.tx_ring], eax
; DEBUGF 1," K : Switching to 32\n"
mov ebx, 20
mov eax, 2
call dword [pcnet32_access.write_bcr]
mov ebx, 1
mov eax, ((pcnet32_private - OS_BASE) and 0xffff)
call dword [pcnet32_access.write_csr]
mov ebx, 2
mov eax, ((pcnet32_private - OS_BASE) shr 16) and 0xffff
call dword [pcnet32_access.write_csr]
mov ebx, 0
mov eax, 1
call dword [pcnet32_access.write_csr]
mov esi, 1
call delay_ms
call pcnet32_reset
mov eax, [pci_data]
mov [eth_status], eax
ret
 
 
 
pcnet32_poll:
xor ax, ax
mov [eth_rx_data_len], ax
mov eax, [pcnet32_private.cur_rx]
and eax, PCNET32_RX_RING_MOD_MASK
mov ebx, eax
imul esi, eax, PCNET32_PKT_BUF_SZ
add esi, pcnet32_rxb
shl ebx, 4
add ebx, pcnet32_rx_ring
mov cx, [ebx+pcnet32_rx_head.status]
test cx, 0x8000
jnz .L1
cmp ch, 3
jne .L1
mov ecx, [ebx+pcnet32_rx_head.msg_length]
and ecx, 0xfff
sub ecx, 4
mov [eth_rx_data_len], cx
; DEBUGF 1," K : PCNETRX: %ub\n",cx
push ecx
shr ecx, 2
mov edi, Ether_buffer
cld
rep movsd
pop ecx
and ecx, 3
rep movsb
mov [ebx+pcnet32_rx_head.buf_length], word PCNET32_PKT_BUF_SZ_NEG
or [ebx+pcnet32_rx_head.status], word 0x8000
inc [pcnet32_private.cur_rx]
.L1:
ret
 
 
 
 
; Pointer to 48 bit destination address in edi
; Type of packet in bx
; size of packet in ecx
; pointer to packet data in esi
pcnet32_xmit:
push edi
push esi
push ebx
push ecx
; DEBUGF 1," K : PCNETTX\n"
mov esi, edi
mov edi, [pcnet32_private.cur_tx]
imul edi, PCNET32_PKT_BUF_SZ
add edi, pcnet32_txb; edi=ptxb
mov eax, edi
cld ; copy MAC
movsd
movsw
mov esi, node_addr
cld
movsd
movsw
mov [edi], bx
add edi, 2
mov esi, [esp+8]
mov ecx, [esp]
push ecx
shr ecx, 2
cld
rep movsd
pop ecx
and ecx, 3
rep movsb
; mov ecx,[esp]
; add ecx,14 ; ETH_HLEN
; xor eax,eax
; pad to min length (60=ETH_ZLEN)
; cmp ecx,60
; jae .L1
; sub ecx,60
; cld
; rep stosb
;.L1:
mov edi, pcnet32_tx_ring+0; entry=0
mov ecx, [esp]
add ecx, 14
cmp cx, 60
jae .L1
mov cx, 60
.L1:
neg cx
mov [edi+pcnet32_tx_head.length], cx
mov [edi+pcnet32_tx_head.misc], dword 0
sub eax, OS_BASE
mov [edi+pcnet32_tx_head.base], eax
mov [edi+pcnet32_tx_head.status], word 0x8300
; trigger an immediate send poll
mov ebx, 0
mov eax, 0x0008; 0x0048
mov ebp, [io_addr]
call dword [pcnet32_access.write_csr]
mov dword [pcnet32_private.cur_tx], 0
; wait for TX to complete
mov ecx, [timer_ticks];[0xfdf0]
add ecx, 100
.L2:
mov ax, [edi+pcnet32_tx_head.status]
test ax, 0x8000
jz .L3
cmp ecx, [timer_ticks];[0xfdf0]
jb .L4
mov esi, 10
call delay_ms
jnz .L2
.L4:
DEBUGF 1," K : PCNET: Send timeout\n"
.L3:
mov dword [edi+pcnet32_tx_head.base], 0
pop ecx
pop ebx
pop esi
pop edi
ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/3c59x.inc
0,0 → 1,2404
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
;; Copyright (c) 2004, Endre Kozma <endre.kozma@axelero.hu>
;; All rights reserved.
;;
;; Redistribution and use in source and binary forms, with or without
;; modification, are permitted provided that the following conditions are
;; met:
;;
;; 1. Redistributions of source code must retain the above copyright notice,
;; this list of conditions and the following disclaimer.
;;
;; 2. Redistributions in binary form must reproduce the above copyright
;; notice, this list of conditions and the following disclaimer in the
;; documentation and/or other materials provided with the distribution.
;;
;; 3. The name of the author may not be used to endorse or promote products
;; derived from this software without specific prior written permission.
;;
;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
;; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
;; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 3C59X.INC ;;
;; ;;
;; Ethernet driver for Menuet OS ;;
;; ;;
;; Driver for 3Com fast etherlink 3c59x and ;;
;; etherlink XL 3c900 and 3c905 cards ;;
;; References: ;;
;; www.3Com.com - data sheets ;;
;; DP83840A.pdf - ethernet physical layer ;;
;; 3c59x.c - linux driver ;;
;; ethernet driver template by Mike Hibbett ;;
;; ;;
;; Credits ;;
;; Mike Hibbett, ;;
;; who kindly supplied me with a 3Com905C-TX-M card ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; History
;; =======
;; $Log: 3C59X.INC,v $
;; Revision 1.3 2004/07/11 12:21:12 kozma
;; Support of vortex chips (3c59x) added.
;; Support of 3c920 and 3c982 added.
;; Corrections.
;;
;; Revision 1.2 2004/06/12 19:40:20 kozma
;; Function e3c59x_set_available_media added in order to set
;; the default media in case auto detection finds no valid link.
;; Incorrect mii check removed (3c900 Cyclone works now).
;; Cleanups.
;;
;; Revision 1.1 2004/06/12 18:27:15 kozma
;; Initial revision
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; comment the next line out if you don't want debug info printed
; on the debug board. This option adds a lot of bytes to the driver
; so it's worth to comment it out.
; E3C59X_DEBUG equ 1
 
; forcing full duplex mode makes sense at some cards and link types
E3C59X_FORCE_FD equ 1
 
macro virt_to_dma reg
{
sub reg, OS_BASE
}
 
macro dma_to_virt reg
{
add reg, OS_BASE
}
 
macro zero_to_virt reg
{
 
}
 
macro virt_to_zero reg
{
 
}
 
macro zero_to_dma reg
{
sub reg, OS_BASE
}
 
macro dma_to_zero reg
{
add reg, OS_BASE
}
 
macro strtbl name, [string]
{
common
label name dword
forward
local label
dd label
forward
label db string, 0
}
 
; Ethernet frame symbols
ETH_ALEN equ 6
ETH_HLEN equ (2*ETH_ALEN+2)
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for
; mininmum 64bytes frame length
; PCI programming
PCI_REG_COMMAND equ 0x4 ; command register
PCI_REG_STATUS equ 0x6 ; status register
PCI_REG_LATENCY equ 0xd ; latency timer register
PCI_REG_CAP_PTR equ 0x34 ; capabilities pointer
PCI_REG_CAPABILITY_ID equ 0x0 ; capapility ID in pm register block
PCI_REG_PM_STATUS equ 0x4 ; power management status register
PCI_REG_PM_CTRL equ 0x4 ; power management control register
PCI_BIT_PIO equ 0 ; bit0: io space control
PCI_BIT_MMIO equ 1 ; bit1: memory space control
PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master
; Registers
E3C59X_REG_POWER_MGMT_CTRL equ 0x7c
E3C59X_REG_UP_LIST_PTR equ 0x38
E3C59X_REG_UP_PKT_STATUS equ 0x30
E3C59X_REG_TX_FREE_THRESH equ 0x2f
E3C59X_REG_DN_LIST_PTR equ 0x24
E3C59X_REG_DMA_CTRL equ 0x20
E3C59X_REG_TX_STATUS equ 0x1b
E3C59X_REG_RX_STATUS equ 0x18
E3C59X_REG_TX_DATA equ 0x10
; Common window registers
E3C59X_REG_INT_STATUS equ 0xe
E3C59X_REG_COMMAND equ 0xe
; Register window 7
E3C59X_REG_MASTER_STATUS equ 0xc
E3C59X_REG_POWER_MGMT_EVENT equ 0xc
E3C59X_REG_MASTER_LEN equ 0x6
E3C59X_REG_VLAN_ETHER_TYPE equ 0x4
E3C59X_REG_VLAN_MASK equ 0x0
E3C59X_REG_MASTER_ADDRESS equ 0x0
; Register window 6
E3C59X_REG_BYTES_XMITTED_OK equ 0xc
E3C59X_REG_BYTES_RCVD_OK equ 0xa
E3C59X_REG_UPPER_FRAMES_OK equ 0x9
E3C59X_REG_FRAMES_DEFERRED equ 0x8
E3C59X_REG_FRAMES_RCVD_OK equ 0x7
E3C59X_REG_FRAMES_XMITTED_OK equ 0x6
E3C59X_REG_RX_OVERRUNS equ 0x5
E3C59X_REG_LATE_COLLISIONS equ 0x4
E3C59X_REG_SINGLE_COLLISIONS equ 0x3
E3C59X_REG_MULTIPLE_COLLISIONS equ 0x2
E3C59X_REG_SQE_ERRORS equ 0x1
E3C59X_REG_CARRIER_LOST equ 0x0
; Register window 5
E3C59X_REG_INDICATION_ENABLE equ 0xc
E3C59X_REG_INTERRUPT_ENABLE equ 0xa
E3C59X_REG_TX_RECLAIM_THRESH equ 0x9
E3C59X_REG_RX_FILTER equ 0x8
E3C59X_REG_RX_EARLY_THRESH equ 0x6
E3C59X_REG_TX_START_THRESH equ 0x0
; Register window 4
E3C59X_REG_UPPER_BYTES_OK equ 0xe
E3C59X_REG_BAD_SSD equ 0xc
E3C59X_REG_MEDIA_STATUS equ 0xa
E3C59X_REG_PHYSICAL_MGMT equ 0x8
E3C59X_REG_NETWORK_DIAGNOSTIC equ 0x6
E3C59X_REG_FIFO_DIAGNOSTIC equ 0x4
E3C59X_REG_VCO_DIAGNOSTIC equ 0x2 ; may not supported
; Bits in register window 4
E3C59X_BIT_AUTOSELECT equ 24
; Register window 3
E3C59X_REG_TX_FREE equ 0xc
E3C59X_REG_RX_FREE equ 0xa
E3C59X_REG_MEDIA_OPTIONS equ 0x8
E3C59X_REG_MAC_CONTROL equ 0x6
E3C59X_REG_MAX_PKT_SIZE equ 0x4
E3C59X_REG_INTERNAL_CONFIG equ 0x0
; Register window 2
E3C59X_REG_RESET_OPTIONS equ 0xc
E3C59X_REG_STATION_MASK_HI equ 0xa
E3C59X_REG_STATION_MASK_MID equ 0x8
E3C59X_REG_STATION_MASK_LO equ 0x6
E3C59X_REG_STATION_ADDRESS_HI equ 0x4
E3C59X_REG_STATION_ADDRESS_MID equ 0x2
E3C59X_REG_STATION_ADDRESS_LO equ 0x0
; Register window 1
E3C59X_REG_TRIGGER_BITS equ 0xc
E3C59X_REG_SOS_BITS equ 0xa
E3C59X_REG_WAKE_ON_TIMER equ 0x8
E3C59X_REG_SMB_RXBYTES equ 0x7
E3C59X_REG_SMB_DIAG equ 0x5
E3C59X_REG_SMB_ARB equ 0x4
E3C59X_REG_SMB_STATUS equ 0x2
E3C59X_REG_SMB_ADDRESS equ 0x1
E3C59X_REG_SMB_FIFO_DATA equ 0x0
; Register window 0
E3C59X_REG_EEPROM_DATA equ 0xc
E3C59X_REG_EEPROM_COMMAND equ 0xa
E3C59X_REG_BIOS_ROM_DATA equ 0x8
E3C59X_REG_BIOS_ROM_ADDR equ 0x4
; Physical management bits
E3C59X_BIT_MGMT_DIR equ 2 ; drive with the data written in mgmtData
E3C59X_BIT_MGMT_DATA equ 1 ; MII management data bit
E3C59X_BIT_MGMT_CLK equ 0 ; MII management clock
; MII commands
E3C59X_MII_CMD_MASK equ (1111b shl 10)
E3C59X_MII_CMD_READ equ (0110b shl 10)
E3C59X_MII_CMD_WRITE equ (0101b shl 10)
; MII registers
E3C59X_REG_MII_BMCR equ 0 ; basic mode control register
E3C59X_REG_MII_BMSR equ 1 ; basic mode status register
E3C59X_REG_MII_ANAR equ 4 ; auto negotiation advertisement register
E3C59X_REG_MII_ANLPAR equ 5 ; auto negotiation link partner ability register
E3C59X_REG_MII_ANER equ 6 ; auto negotiation expansion register
; MII bits
E3C59X_BIT_MII_AUTONEG_COMPLETE equ 5 ; auto-negotiation complete
E3C59X_BIT_MII_PREAMBLE_SUPPRESSION equ 6
; eeprom bits and commands
E3C59X_EEPROM_CMD_READ equ 0x80
E3C59X_EEPROM_BIT_BUSY equ 15
; eeprom registers
E3C59X_EEPROM_REG_OEM_NODE_ADDR equ 0xa
E3C59X_EEPROM_REG_CAPABILITIES equ 0x10
; Commands for command register
E3C59X_SELECT_REGISTER_WINDOW equ (1 shl 11)
 
IS_VORTEX equ 0x1
IS_BOOMERANG equ 0x2
IS_CYCLONE equ 0x4
IS_TORNADO equ 0x8
EEPROM_8BIT equ 0x10
HAS_PWR_CTRL equ 0x20
HAS_MII equ 0x40
HAS_NWAY equ 0x80
HAS_CB_FNS equ 0x100
INVERT_MII_PWR equ 0x200
INVERT_LED_PWR equ 0x400
MAX_COLLISION_RESET equ 0x800
EEPROM_OFFSET equ 0x1000
HAS_HWCKSM equ 0x2000
EXTRA_PREAMBLE equ 0x4000
 
iglobal
align 4
e3c59x_hw_versions:
dw 0x5900, IS_VORTEX ; 3c590 Vortex 10Mbps
dw 0x5920, IS_VORTEX ; 3c592 EISA 10Mbps Demon/Vortex
dw 0x5970, IS_VORTEX ; 3c597 EISA Fast Demon/Vortex
dw 0x5950, IS_VORTEX ; 3c595 Vortex 100baseTx
dw 0x5951, IS_VORTEX ; 3c595 Vortex 100baseT4
dw 0x5952, IS_VORTEX ; 3c595 Vortex 100base-MII
dw 0x9000, IS_BOOMERANG ; 3c900 Boomerang 10baseT
dw 0x9001, IS_BOOMERANG ; 3c900 Boomerang 10Mbps Combo
dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPO
dw 0x9005, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps Combo
dw 0x9006, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPC
dw 0x900A, IS_CYCLONE or HAS_HWCKSM ; 3c900B-FL Cyclone 10base-FL
dw 0x9050, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseTx
dw 0x9051, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseT4
dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B Cyclone 100baseTx
dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c905B Cyclone 10/100/BNC
dw 0x905A, IS_CYCLONE or HAS_HWCKSM ; 3c905B-FX Cyclone 100baseFx
dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c905C Tornado
dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c980 Cyclone
dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c982 Dual Port Server Cyclone
dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3cSOHO100-TX Hurricane
dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM ; 3c555 Laptop Hurricane
dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS \
or INVERT_MII_PWR or HAS_HWCKSM ; 3c556 Laptop Tornado
dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS \
or INVERT_MII_PWR or HAS_HWCKSM ; 3c556B Laptop Hurricane
dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 [Megahertz] 10/100 LAN CardBus
dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 Boomerang CardBus
dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT \
or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE575BT Cyclone CardBus
dw 0x5257, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \
or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CCFE575CT Tornado CardBus
dw 0x6560, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \
or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE656 Cyclone CardBus
dw 0x6562, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \
or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFEM656B Cyclone+Winmodem CardBus
dw 0x6564, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \
or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CXFEM656C Tornado+Winmodem CardBus
dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c450 HomePNA Tornado
dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920 Tornado
dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port A
dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port B
dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B-T4
dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920B-EMB-WNM Tornado
E3C59X_HW_VERSIONS_SIZE= $-e3c59x_hw_versions
endg
 
; RX/TX buffers sizes
E3C59X_MAX_ETH_PKT_SIZE equ 1536 ; max packet size
E3C59X_NUM_RX_DESC equ 4 ; a power of 2 number
E3C59X_NUM_TX_DESC equ 4 ; a power of 2 number
E3C59X_RX_BUFFER_SIZE equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_RX_DESC)
E3C59X_TX_BUFFER_SIZE equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_TX_DESC)
; Download Packet Descriptor
E3C59X_DPD_DN_NEXT_PTR equ 0
E3C59X_DPD_FRAME_START_HDR equ 4
E3C59X_DPD_DN_FRAG_ADDR equ 8 ; for packet data
E3C59X_DPD_DN_FRAG_LEN equ 12 ; for packet data
E3C59X_DPD_SIZE equ 16 ; a power of 2 number
; Upload Packet Descriptor
E3C59X_UPD_UP_NEXT_PTR equ 0
E3C59X_UPD_PKT_STATUS equ 4
E3C59X_UPD_UP_FRAG_ADDR equ 8 ; for packet data
E3C59X_UPD_UP_FRAG_LEN equ 12 ; for packet data
E3C59X_UPD_SIZE equ 16
 
; RX/TX buffers
if defined E3C59X_LINUX
E3C59X_MAX_ETH_FRAME_SIZE = 160 ; size of ethernet frame + bytes alignment
e3c59x_rx_buff = 0
else
E3C59X_MAX_ETH_FRAME_SIZE = 1520 ; size of ethernet frame + bytes alignment
e3c59x_rx_buff = eth_data_start
end if
 
e3c59x_tx_buff = e3c59x_rx_buff+E3C59X_RX_BUFFER_SIZE
e3c59x_dpd_buff = e3c59x_tx_buff+E3C59X_TX_BUFFER_SIZE
e3c59x_upd_buff = e3c59x_dpd_buff+(E3C59X_DPD_SIZE*E3C59X_NUM_TX_DESC)
 
uglobal
e3c59x_curr_upd:
dd 0
e3c59x_prev_dpd:
dd 0
e3c59x_prev_tx_frame:
dd 0
e3c59x_transmit_function:
dd 0
e3c59x_receive_function:
dd 0
endg
 
iglobal
e3c59x_ver_id:
db 17
endg
 
uglobal
e3c59x_full_bus_master:
db 0
e3c59x_has_hwcksm:
db 0
e3c59x_preamble:
db 0
e3c59x_dn_list_ptr_cleared:
db 0
e3c59x_self_directed_packet:
rb 6
endg
 
if defined E3C59X_DEBUG
e3c59x_hw_type_str:
db "Detected hardware type : ", 0
e3c59x_device_str:
db "Device ID : 0x"
e3c59x_device_id_str:
db "ffff", 13, 10, 0
e3c59x_vendor_str:
db "Vendor ID : 0x"
e3c59x_vendor_id_str:
db "ffff", 13, 10, 0
e3c59x_io_info_str:
db "IO address : 0x"
e3c59x_io_addr_str:
db "ffff", 13, 10, 0
e3c59x_mac_info_str:
db "MAC address : "
e3c59x_mac_addr_str:
db "ff:ff:ff:ff:ff:ff", 13, 10, 0
e3c59x_boomerang_str:
db " (boomerang)", 13, 10, 0
e3c59x_vortex_str:
db " (vortex)", 13, 10, 0
e3c59x_link_type_str:
db "Established link type : ", 0
e3c59x_new_line_str:
db 13, 10, 0
e3c59x_link_type:
dd 0
 
e3c59x_charset:
db '0123456789abcdef'
 
strtbl e3c59x_link_str, \
"No valid link type detected", \
"10BASE-T half duplex", \
"10BASE-T full-duplex", \
"100BASE-TX half duplex", \
"100BASE-TX full duplex", \
"100BASE-T4", \
"100BASE-FX", \
"10Mbps AUI", \
"10Mbps COAX (BNC)", \
"miiDevice - not supported"
 
strtbl e3c59x_hw_str, \
"3c590 Vortex 10Mbps", \
"3c592 EISA 10Mbps Demon/Vortex", \
"3c597 EISA Fast Demon/Vortex", \
"3c595 Vortex 100baseTx", \
"3c595 Vortex 100baseT4", \
"3c595 Vortex 100base-MII", \
"3c900 Boomerang 10baseT", \
"3c900 Boomerang 10Mbps Combo", \
"3c900 Cyclone 10Mbps TPO", \
"3c900 Cyclone 10Mbps Combo", \
"3c900 Cyclone 10Mbps TPC", \
"3c900B-FL Cyclone 10base-FL", \
"3c905 Boomerang 100baseTx", \
"3c905 Boomerang 100baseT4", \
"3c905B Cyclone 100baseTx", \
"3c905B Cyclone 10/100/BNC", \
"3c905B-FX Cyclone 100baseFx", \
"3c905C Tornado", \
"3c980 Cyclone", \
"3c982 Dual Port Server Cyclone", \
"3cSOHO100-TX Hurricane", \
"3c555 Laptop Hurricane", \
"3c556 Laptop Tornado", \
"3c556B Laptop Hurricane", \
"3c575 [Megahertz] 10/100 LAN CardBus", \
"3c575 Boomerang CardBus", \
"3CCFE575BT Cyclone CardBus", \
"3CCFE575CT Tornado CardBus", \
"3CCFE656 Cyclone CardBus", \
"3CCFEM656B Cyclone+Winmodem CardBus", \
"3CXFEM656C Tornado+Winmodem CardBus", \
"3c450 HomePNA Tornado", \
"3c920 Tornado", \
"3c982 Hydra Dual Port A", \
"3c982 Hydra Dual Port B", \
"3c905B-T4", \
"3c920B-EMB-WNM Tornado"
 
end if ; defined E3C59X_DEBUG
 
;***************************************************************************
; Function
; e3c59x_debug
; Description
; prints debug info to the debug board
; Parameters
; ebp - io_addr
; Return value
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;***************************************************************************
if defined E3C59X_DEBUG
align 4
e3c59x_debug:
pushad
; print device type
mov esi, e3c59x_hw_type_str
call sys_msg_board_str
movzx ecx, byte [e3c59x_ver_id]
mov esi, [e3c59x_hw_str+ecx*4]
call sys_msg_board_str
mov esi, e3c59x_boomerang_str
cmp dword [e3c59x_transmit_function], e3c59x_boomerang_transmit
jz .boomerang
mov esi, e3c59x_vortex_str
.boomerang:
call sys_msg_board_str
; print device/vendor
mov ax, [pci_data+2]
mov cl, 2
mov ebx, e3c59x_device_id_str
call e3c59x_print_hex
mov esi, e3c59x_device_str
call sys_msg_board_str
mov ax, [pci_data]
mov cl, 2
mov ebx, e3c59x_vendor_id_str
call e3c59x_print_hex
mov esi, e3c59x_vendor_str
call sys_msg_board_str
; print io address
mov ax, [io_addr]
mov ebx, e3c59x_io_addr_str
mov cl, 2
call e3c59x_print_hex
mov esi, e3c59x_io_info_str
call sys_msg_board_str
; print MAC address
mov ebx, e3c59x_mac_addr_str
xor ecx, ecx
.mac_loop:
push ecx
mov al, [node_addr+ecx]
mov cl, 1
call e3c59x_print_hex
inc ebx
pop ecx
inc cl
cmp cl, 6
jne .mac_loop
mov esi, e3c59x_mac_info_str
call sys_msg_board_str
; print link type
mov esi, e3c59x_link_type_str
call sys_msg_board_str
xor eax, eax
bsr ax, word [e3c59x_link_type]
jz @f
sub ax, 4
@@:
mov esi, [e3c59x_link_str+eax*4]
call sys_msg_board_str
mov esi, e3c59x_new_line_str
call sys_msg_board_str
popad
ret
 
;***************************************************************************
; Function
; e3c59x_print_hex
; Description
; prints a hexadecimal value
; Parameters
; eax - value to be printed out
; ebx - where to print
; cl - value size (1, 2, 4)
; Return value
; ebx - end address after the print
; Destroyed registers
; eax, ebx
;
;***************************************************************************
align 4
e3c59x_print_hex:
cmp cl, 1
je .print_byte
cmp cl, 2
jz .print_word
.print_dword:
push eax
bswap eax
xchg ah, al
call .print_word
pop eax
.print_word:
push eax
xchg ah, al
call .print_byte
pop eax
.print_byte:
movzx eax, al
push eax
and al, 0xf0
shr al, 4
mov al, byte [eax+e3c59x_charset]
mov [ebx], al
inc ebx
pop eax
and al, 0x0f
mov al, byte [eax+e3c59x_charset]
mov [ebx], al
inc ebx
ret
end if ; defined E3C59X_DEBUG
 
;***************************************************************************
; Function
; e3c59x_try_link_detect
; Description
; e3c59x_try_link_detect checks if link exists
; Parameters
; ebp - io_addr
; Return value
; al - 0 ; no link detected
; al - 1 ; link detected
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;***************************************************************************
align 4
e3c59x_try_link_detect:
; download self-directed packet
mov edi, node_addr
mov bx, 0x0608 ; packet type
mov esi, e3c59x_self_directed_packet
mov ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes
call dword [e3c59x_transmit_function]
; switch to register window 5
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+5
out dx, ax
; program RxFilter for promiscuous operation
mov ax, (10000b shl 11)
lea edx, [ebp+E3C59X_REG_RX_FILTER]
in al, dx
or al, 1111b
lea edx, [ebp+E3C59X_REG_COMMAND]
out dx, ax
; switch to register window 4
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4
out dx, ax
; check loop
xor ebx, ebx
mov ecx, 0xffff ; 65535 tries
.loop:
push ecx ebx
call dword [e3c59x_receive_function]
pop ebx ecx
test al, al
jnz .finish
.no_packet_received:
; switch to register window 4
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4
out dx, ax
; read linkbeatdetect
lea edx, [ebp+E3C59X_REG_MEDIA_STATUS]
in ax, dx
test ah, 1000b ; test linkBeatDetect
jnz .link_detected
xor al, al
jmp .finish
.link_detected:
; test carrierSense
test al, 100000b
jz .no_carrier_sense
inc ebx
.no_carrier_sense:
dec ecx
jns .loop
; assume the link is good if 0 < ebx < 25 %
test ebx, ebx
setnz al
jz .finish
cmp ebx, 16384 ; 25%
setb al
.finish:
if defined E3C59X_DEBUG
test al, al
jz @f
or byte [e3c59x_link_type+1], 100b
@@:
end if ; defined E3C59X_DEBUG
ret
 
;***************************************************************************
; Function
; e3c59x_try_phy
; Description
; e3c59x_try_phy checks the auto-negotiation function
; in the PHY at PHY index. It can also be extended to
; include link detection for non-IEEE 802.3u
; auto-negotiation devices, for instance the BCM5000.
; Parameters
; ah - PHY index
; ebp - io_addr
; Return value
; al - 0 link is auto-negotiated
; al - 1 no link is auto-negotiated
; Destroyed registers
; eax, ebx, ecx, edx, esi
;
;***************************************************************************
align 4
e3c59x_try_phy:
mov al, E3C59X_REG_MII_BMCR
push eax
call e3c59x_mdio_read ; returns with window #4
or ah, 0x80 ; software reset
mov ebx, eax
pop eax
push eax
call e3c59x_mdio_write ; returns with window #4
; wait for reset to complete
mov esi, 2000 ; 2000ms = 2s
call delay_ms
pop eax
push eax
call e3c59x_mdio_read ; returns with window #4
test ah, 0x80
jnz .fail_finish
pop eax
push eax
; wait for a while after reset
mov esi, 20 ; 20ms
call delay_ms
pop eax
push eax
mov al, E3C59X_REG_MII_BMSR
call e3c59x_mdio_read ; returns with window #4
test al, 1 ; extended capability supported?
jz .no_ext_cap
; auto-neg capable?
test al, 1000b
jz .fail_finish ; not auto-negotiation capable
; auto-neg complete?
test al, 100000b
jnz .auto_neg_ok
; restart auto-negotiation
pop eax
push eax
mov al, E3C59X_REG_MII_ANAR
push eax
call e3c59x_mdio_read ; returns with window #4
or ax, (1111b shl 5) ; advertise only 10base-T and 100base-TX
mov ebx, eax
pop eax
call e3c59x_mdio_write ; returns with window #4
pop eax
push eax
call e3c59x_mdio_read ; returns with window #4
mov ebx, eax
or bh, 10010b ; restart auto-negotiation
pop eax
push eax
call e3c59x_mdio_write ; returns with window #4
mov esi, 4000 ; 4000ms = 4 seconds
call delay_ms
pop eax
push eax
mov al, E3C59X_REG_MII_BMSR
call e3c59x_mdio_read ; returns with window #4
test al, 100000b ; auto-neg complete?
jnz .auto_neg_ok
jmp .fail_finish
.auto_neg_ok:
; compare advertisement and link partner ability registers
pop eax
push eax
mov al, E3C59X_REG_MII_ANAR
call e3c59x_mdio_read ; returns with window #4
xchg eax, [esp]
mov al, E3C59X_REG_MII_ANLPAR
call e3c59x_mdio_read ; returns with window #4
pop ebx
and eax, ebx
and eax, 1111100000b
push eax
if defined E3C59X_DEBUG
mov word [e3c59x_link_type], ax
end if ; defined E3C59X_DEBUG
; switch to register window 3
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3
out dx, ax
; set full-duplex mode
lea edx, [ebp+E3C59X_REG_MAC_CONTROL]
in ax, dx
and ax, not 0x120 ; clear full duplex and flow control
pop ebx
test ebx, (1010b shl 5) ; check for full-duplex
jz .half_duplex
or ax, 0x120 ; set full duplex and flow control
.half_duplex:
out dx, ax
mov al, 1
ret
.no_ext_cap:
; not yet implemented BCM5000
.fail_finish:
pop eax
xor al, al
ret
 
;***************************************************************************
; Function
; e3c59x_try_mii
; Description
; e3c59x_try_MII checks the on-chip auto-negotiation logic
; or an off-chip MII PHY, depending upon what is set in
; xcvrSelect by the caller.
; It exits when it finds the first device with a good link.
; Parameters
; ebp - io_addr
; Return value
; al - 0
; al - 1
; Destroyed registers
; eax, ebx, ecx, edx, esi
;
;***************************************************************************
align 4
e3c59x_try_mii:
; switch to register window 3
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3
out dx, ax
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
in eax, dx
and eax, (1111b shl 20)
cmp eax, (1000b shl 20) ; is auto-negotiation set?
jne .mii_device
; auto-negotiation is set
; switch to register window 4
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4
out dx, ax
; PHY==24 is the on-chip auto-negotiation logic
; it supports only 10base-T and 100base-TX
mov ah, 24
call e3c59x_try_phy
test al, al
jz .fail_finish
mov cl, 24
jmp .check_preamble
.mii_device:
cmp eax, (0110b shl 20)
jne .fail_finish
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4
out dx, ax
lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT]
in ax, dx
and al, (1 shl E3C59X_BIT_MGMT_DIR) or (1 shl E3C59X_BIT_MGMT_DATA)
cmp al, (1 shl E3C59X_BIT_MGMT_DATA)
je .serch_for_phy
xor al, al
ret
.serch_for_phy:
; search for PHY
mov cl, 31
.search_phy_loop:
cmp cl, 24
je .next_phy
mov ah, cl ; ah = phy
mov al, E3C59X_REG_MII_BMCR ; al = Basic Mode Status Register
push ecx
call e3c59x_mdio_read
pop ecx
test ax, ax
jz .next_phy
cmp ax, 0xffff
je .next_phy
mov ah, cl ; ah = phy
push ecx
call e3c59x_try_phy
pop ecx
test al, al
jnz .check_preamble
.next_phy:
dec cl
jns .search_phy_loop
.fail_finish:
xor al, al
ret
; epilog
.check_preamble:
push eax ; eax contains the return value of e3c59x_try_phy
; check hard coded preamble forcing
movzx eax, byte [e3c59x_ver_id]
test word [eax*4+e3c59x_hw_versions+2], EXTRA_PREAMBLE
setnz [e3c59x_preamble] ; force preamble
jnz .finish
; check mii for preamble suppression
mov ah, cl
mov al, E3C59X_REG_MII_BMSR
call e3c59x_mdio_read
test al, 1000000b ; preamble suppression?
setz [e3c59x_preamble] ; no
.finish:
pop eax
ret
 
;***************************************************************************
; Function
; e3c59x_test_packet
; Description
; e3c59x_try_loopback try a loopback packet for 10BASE2 or AUI port
; Parameters
; ebp - io_addr
; Return value
; al - 0
; al - 1
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;***************************************************************************
align 4
e3c59x_test_packet:
; switch to register window 3
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3
out dx, ax
; set fullDuplexEnable in MacControl register
lea edx, [ebp+E3C59X_REG_MAC_CONTROL]
in ax, dx
or ax, 0x120
out dx, ax
; switch to register window 5
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+5
out dx, ax
; set RxFilter to enable individual address matches
mov ax, (10000b shl 11)
lea edx, [ebp+E3C59X_REG_RX_FILTER]
in al, dx
or al, 1
lea edx, [ebp+E3C59X_REG_COMMAND]
out dx, ax
; issue RxEnable and TxEnable
call e3c59x_rx_reset
call e3c59x_tx_reset
; download a self-directed test packet
mov edi, node_addr
mov bx, 0x0608 ; packet type
mov esi, e3c59x_self_directed_packet
mov ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes
call dword [e3c59x_transmit_function]
; wait for 2s
mov esi, 2000 ; 2000ms = 2s
call delay_ms
; check if self-directed packet is received
call dword [e3c59x_receive_function]
test al, al
jnz .finish
; switch to register window 3
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3
out dx, ax
; clear fullDuplexEnable in MacControl register
lea edx, [ebp+E3C59X_REG_MAC_CONTROL]
in ax, dx
and ax, not 0x120
out dx, ax
xor al, al
.finish:
ret
 
;***************************************************************************
; Function
; e3c59x_try_loopback
; Description
; tries a loopback packet for 10BASE2 or AUI port
; Parameters
; al - 0: 10Mbps AUI connector
; 1: 10BASE-2
; ebp - io_addr
; Return value
; al - 0
; al - 1
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;***************************************************************************
align 4
e3c59x_try_loopback:
push eax
; switch to register window 3
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3
out dx, ax
pop eax
push eax
if defined E3C59X_DEBUG
mov bl, al
inc bl
shl bl, 3
or byte [e3c59x_link_type+1], bl
end if ; defined E3C59X_DEBUG
test al, al ; aui or coax?
jz .complete_loopback
; enable 100BASE-2 DC-DC converter
mov ax, (10b shl 11) ; EnableDcConverter
out dx, ax
.complete_loopback:
mov cl, 2 ; give a port 3 chances to complete a loopback
.next_try:
push ecx
call e3c59x_test_packet
pop ecx
test al, al
jnz .finish
dec cl
jns .next_try
.finish:
xchg eax, [esp]
test al, al
jz .aui_finish
; issue DisableDcConverter command
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, (10111b shl 11)
out dx, ax
.aui_finish:
pop eax ; al contains the result of operation
if defined E3C59X_DEBUG
test al, al
jnz @f
and byte [e3c59x_link_type+1], not 11000b
@@:
end if ; defined E3C59X_DEBUG
ret
 
;***************************************************************************
; Function
; e3c59x_set_available_media
; Description
; sets the first available media
; Parameters
; ebp - io_addr
; Return value
; al - 0
; al - 1
; Destroyed registers
; eax, edx
;
;***************************************************************************
align 4
e3c59x_set_available_media:
; switch to register window 3
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3
out dx, ax
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
in eax, dx
push eax
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
in ax, dx
test al, 10b
jz @f
; baseTXAvailable
pop eax
and eax, not (1111b shl 20)
or eax, (100b shl 20)
if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD
mov word [e3c59x_link_type], (1 shl 8)
else if defined E3C59X_DEBUG
mov word [e3c59x_link_type], (1 shl 7)
end if
jmp .set_media
@@:
test al, 100b
jz @f
; baseFXAvailable
pop eax
and eax, not (1111b shl 20)
or eax, (101b shl 20)
if defined E3C59X_DEBUG
mov word [e3c59x_link_type], (1 shl 10)
end if
jmp .set_media
@@:
test al, 1000000b
jz @f
; miiDevice
pop eax
and eax, not (1111b shl 20)
or eax, (0110b shl 20)
if defined E3C59X_DEBUG
mov word [e3c59x_link_type], (1 shl 13)
end if
jmp .set_media
@@:
test al, 1000b
jz @f
.set_default:
; 10bTAvailable
pop eax
and eax, not (1111b shl 20)
if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD
mov word [e3c59x_link_type], (1 shl 6)
else if defined E3C59X_DEBUG
mov word [e3c59x_link_type], (1 shl 5)
end if ; E3C59X_FORCE_FD
jmp .set_media
@@:
test al, 10000b
jz @f
; coaxAvailable
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, (10b shl 11) ; EnableDcConverter
out dx, ax
pop eax
and eax, not (1111b shl 20)
or eax, (11b shl 20)
if defined E3C59X_DEBUG
mov word [e3c59x_link_type], (1 shl 12)
end if ; defined E3C59X_DEBUG
jmp .set_media
@@:
test al, 10000b
jz .set_default
; auiAvailable
pop eax
and eax, not (1111b shl 20)
or eax, (1 shl 20)
if defined E3C59X_DEBUG
mov word [e3c59x_link_type], (1 shl 11)
end if ; defined E3C59X_DEBUG
.set_media:
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
out dx, eax
if defined E3C59X_FORCE_FD
; set fullDuplexEnable in MacControl register
lea edx, [ebp+E3C59X_REG_MAC_CONTROL]
in ax, dx
or ax, 0x120
out dx, ax
end if ; E3C59X_FORCE_FD
mov al, 1
ret
 
;***************************************************************************
; Function
; e3c59x_set_active_port
; Description
; It selects the media port (transceiver) to be used
; Parameters:
; ebp - io_addr
; Return value:
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;***************************************************************************
align 4
e3c59x_set_active_port:
; switch to register window 3
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3
out dx, ax
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
in eax, dx
test eax, (1 shl 24) ; check if autoselect enable
jz .set_first_available_media
; check 100BASE-TX and 10BASE-T
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
in ax, dx
test al, 1010b ; check whether 100BASE-TX or 10BASE-T available
jz .mii_device ; they are not available
; set auto-negotiation
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
in eax, dx
and eax, not (1111b shl 20)
or eax, (1000b shl 20)
out dx, eax
call e3c59x_try_mii
test al, al
jz .mii_device
ret
.mii_device:
; switch to register window 3
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3
out dx, ax
; check for off-chip mii device
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
in ax, dx
test al, 1000000b ; check miiDevice
jz .base_fx
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
in eax, dx
and eax, not (1111b shl 20)
or eax, (0110b shl 20) ; set MIIDevice
out dx, eax
call e3c59x_try_mii
test al, al
jz .base_fx
ret
.base_fx:
; switch to register window 3
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3
out dx, ax
; check for 100BASE-FX
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
in ax, dx ; read media option register
test al, 100b ; check 100BASE-FX
jz .aui_enable
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
in eax, dx
and eax, not (1111b shl 20)
or eax, (0101b shl 20) ; set 100base-FX
out dx, eax
call e3c59x_try_link_detect
test al, al
jz .aui_enable
ret
.aui_enable:
; switch to register window 3
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3
out dx, ax
; check for 10Mbps AUI connector
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
in ax, dx ; read media option register
test al, 100000b ; check 10Mbps AUI connector
jz .coax_available
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
in eax, dx
and eax, not (1111b shl 20)
or eax, (0001b shl 20) ; set 10Mbps AUI connector
out dx, eax
xor al, al ; try 10Mbps AUI connector
call e3c59x_try_loopback
test al, al
jz .coax_available
ret
.coax_available:
; switch to register window 3
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+3
out dx, ax
; check for coaxial 10BASE-2 port
lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS]
in ax, dx ; read media option register
test al, 10000b ; check 10BASE-2
jz .set_first_available_media
lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG]
in eax, dx
and eax, not (1111b shl 20)
or eax, (0011b shl 20) ; set 10BASE-2
out dx, eax
mov al, 1
call e3c59x_try_loopback
test al, al
jz .set_first_available_media
ret
.set_first_available_media:
jmp e3c59x_set_available_media
 
;***************************************************************************
; Function
; e3c59x_wake_up
; Description
; set the power state to D0
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;***************************************************************************
align 4
e3c59x_wake_up:
; wake up - we directly do it by programming PCI
; check if the device is power management capable
mov al, 2
mov ah, [pci_bus]
mov bl, PCI_REG_STATUS
mov bh, [pci_dev]
push eax ebx
call pci_read_reg
test al, 10000b ; is there "new capabilities" linked list?
pop ebx eax
jz .device_awake
; search for power management register
mov al, 1
mov bl, PCI_REG_CAP_PTR
push eax ebx
call pci_read_reg
mov cl, al
cmp cl, 0x3f
pop ebx eax
jbe .device_awake
; traverse the list
mov al, 2
.pm_loop:
mov bl, cl
push eax ebx
call pci_read_reg
cmp al, 1
je .set_pm_state
test ah, ah
mov cl, ah
pop ebx eax
jnz .pm_loop
jmp .device_awake
; waku up the device if necessary
.set_pm_state:
pop ebx eax
add bl, PCI_REG_PM_CTRL
push eax ebx
call pci_read_reg
mov cx, ax
test cl, 3
pop ebx eax
jz .device_awake
and cl, not 11b ; set state to D0
call pci_write_reg
.device_awake:
ret
 
;***************************************************************************
; Function
; e3c59x_probe
; Description
; Searches for an ethernet card, enables it and clears the rx buffer
; If a card was found, it enables the ethernet -> TCPIP link
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;***************************************************************************
align 4
e3c59x_probe:
movzx ebp, word [io_addr]
mov al, 2
mov ah, [pci_bus]
mov bh, [pci_dev]
mov bl, PCI_REG_COMMAND
push ebp eax ebx
call pci_read_reg
mov cx, ax
or cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO)
and cl, not (1 shl PCI_BIT_MMIO)
pop ebx eax
call pci_write_reg
; wake up the card
call e3c59x_wake_up
pop ebp
; get chip version
mov ax, [pci_data+2]
mov ecx, E3C59X_HW_VERSIONS_SIZE/4-1
.chip_ver_loop:
cmp ax, [e3c59x_hw_versions+ecx*4]
jz .chip_ver_found
dec ecx
jns .chip_ver_loop
xor ecx, ecx
.chip_ver_found:
mov [e3c59x_ver_id], cl
test word [e3c59x_hw_versions+2+ecx*4], HAS_HWCKSM
setnz [e3c59x_has_hwcksm]
; set pci latency for vortex cards
test word [e3c59x_hw_versions+2+ecx*4], IS_VORTEX
jz .not_vortex
mov cx, 11111000b ; 248 = max latency
mov al, 1
mov ah, [pci_bus]
mov bl, PCI_REG_LATENCY
mov bh, [pci_dev]
call pci_write_reg
.not_vortex:
; set RX/TX functions
mov ax, E3C59X_EEPROM_REG_CAPABILITIES
call e3c59x_read_eeprom
test al, 100000b ; full bus master?
setnz [e3c59x_full_bus_master]
jnz .boomerang_func
mov dword [e3c59x_transmit_function], e3c59x_vortex_transmit
mov dword [e3c59x_receive_function], e3c59x_vortex_poll
jmp @f
.boomerang_func: ; full bus master, so use boomerang functions
mov dword [e3c59x_transmit_function], e3c59x_boomerang_transmit
mov dword [e3c59x_receive_function], e3c59x_boomerang_poll
@@:
; read MAC from eeprom
mov ecx, 2
.mac_loop:
lea ax, [E3C59X_EEPROM_REG_OEM_NODE_ADDR+ecx]
call e3c59x_read_eeprom
xchg ah, al ; htons
mov [node_addr+ecx*2], ax
dec ecx
jns .mac_loop
test byte [e3c59x_full_bus_master], 0xff
jz .set_preamble
; switch to register window 2
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+2
out dx, ax
; activate xcvr by setting some magic bits
lea edx, [ebp+E3C59X_REG_RESET_OPTIONS]
in ax, dx
and ax, not 0x4010
movzx ebx, byte [e3c59x_ver_id]
test word [ebx*4+e3c59x_hw_versions+2], INVERT_LED_PWR
jz @f
or al, 0x10
@@:
test word [ebx*4+e3c59x_hw_versions+2], INVERT_MII_PWR
jz @f
or ah, 0x40
@@:
out dx, ax
.set_preamble:
; use preamble as default
mov byte [e3c59x_preamble], 1 ; enable preamble
 
;***************************************************************************
; Function
; e3c59x_reset
; Description
; Place the chip (ie, the ethernet card) into a virgin state
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;***************************************************************************
e3c59x_reset:
; issue global reset
call e3c59x_global_reset
; disable interrupts
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, (1110b shl 11)
out dx, ax
; enable Statistics
mov ax, (10101b shl 11)
out dx, ax
; set indication
mov ax, (1111b shl 11) or 0x6c6
out dx, ax
; acknowledge (clear) every interrupt indicator
mov ax, (1101b shl 11) or 0x661
out dx, ax
; switch to register window 2
mov ax, E3C59X_SELECT_REGISTER_WINDOW+2
out dx, ax
; write MAC addres back into the station address registers
lea edx, [ebp+E3C59X_REG_STATION_ADDRESS_LO]
mov esi, node_addr
cld
outsw
add edx, 2
outsw
add edx, 2
outsw
add edx, 2
; clear station mask
xor eax, eax
out dx, ax
add edx, 2
out dx, ax
add edx, 2
out dx, ax
; switch to register window 6
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+6
out dx, ax
; clear all statistics by reading
lea edx, [ebp+E3C59X_REG_CARRIER_LOST]
mov cl, 9
.stat_clearing_loop:
in al, dx
inc edx
dec cl
jns .stat_clearing_loop
in ax, dx
add dx, 2
in ax, dx
; switch to register window 4
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4
out dx, ax
; clear BadSSD
lea edx, [ebp+E3C59X_REG_BAD_SSD]
in al, dx
; clear extra statistics bit in NetworkDiagnostic
lea edx, [ebp+E3C59X_REG_NETWORK_DIAGNOSTIC]
in ax, dx
or ax, 0x0040
out dx, ax
; SetRxEarlyThreshold
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, (10001b shl 11)+(E3C59X_MAX_ETH_PKT_SIZE shr 2)
out dx, ax
test byte [e3c59x_full_bus_master], 0xff
jz .skip_boomerang_setting
; set upRxEarlyEnable
lea edx, [ebp+E3C59X_REG_DMA_CTRL]
in eax, dx
or eax, 0x20
out dx, eax
; TxFreeThreshold
lea edx, [ebp+E3C59X_REG_TX_FREE_THRESH]
mov al, (E3C59X_MAX_ETH_PKT_SIZE / 256)
out dx, al
; program DnListPtr
lea edx, [ebp+E3C59X_REG_DN_LIST_PTR]
xor eax, eax
out dx, eax
.skip_boomerang_setting:
; initialization
call e3c59x_rx_reset
call e3c59x_tx_reset
call e3c59x_set_active_port
call e3c59x_rx_reset
call e3c59x_tx_reset
; switch to register window 5
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+5
out dx, ax
; program RxFilter for promiscuous operation
mov ax, (10000b shl 11)
lea edx, [ebp+E3C59X_REG_RX_FILTER]
in al, dx
or al, 1111b
lea edx, [ebp+E3C59X_REG_COMMAND]
out dx, ax
; switch to register window 4
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4
out dx, ax
; wait for linkDetect
lea edx, [ebp+E3C59X_REG_MEDIA_STATUS]
mov cl, 20 ; wait for max 2s
mov esi, 100 ; 100ms
.link_detect_loop:
call delay_ms
in ax, dx
test ah, 1000b ; linkDetect
jnz @f
dec cl
jnz .link_detect_loop
@@:
; Indicate that we have successfully reset the card
mov eax, [pci_data]
mov [eth_status], eax
if defined E3C59X_DEBUG
call e3c59x_debug
end if ; defined E3C59X_DEBUG
ret
 
;***************************************************************************
; Function
; e3c59x_global_reset
; Description
; resets the device
; Parameters:
; ebp - io_addr
; Return value:
; Destroyed registers
; ax, ecx, edx, esi
;
;***************************************************************************
align 4
e3c59x_global_reset:
; GlobalReset
lea edx, [ebp+E3C59X_REG_COMMAND]
xor eax, eax
; or al, 0x14
out dx, ax
; wait for GlobalReset to complete
mov ecx, 64000
.global_reset_loop:
in ax, dx
test ah, 10000b ; check CmdInProgress
jz .finish
dec ecx
jnz .global_reset_loop
.finish:
; wait for 2 seconds for NIC to boot
mov esi, 2000 ; 2000ms = 2s
push ebp
call delay_ms
pop ebp
ret
 
;***************************************************************************
; Function
; e3c59x_tx_reset
; Description
; resets and enables transmitter engine
; Parameters:
; ebp - io_addr
; Return value:
; Destroyed registers
; ax, ecx, edx
;
;***************************************************************************
align 4
e3c59x_tx_reset:
; TxReset
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, (01011b shl 11)
out dx, ax
; Wait for TxReset to complete
mov ecx, 200000
.tx_reset_loop:
in ax, dx
test ah, 10000b ; check CmdInProgress
jz .tx_set_prev
dec ecx
jns .tx_reset_loop
.tx_set_prev:
test byte [e3c59x_full_bus_master], 0xff
jz .tx_enable
; init last_dpd
mov dword [e3c59x_prev_dpd], e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE
mov dword [e3c59x_prev_tx_frame], e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE
.tx_enable:
mov ax, (01001b shl 11) ; TxEnable
out dx, ax
ret
 
;***************************************************************************
; Function
; e3c59x_rx_reset
; Description
; resets and enables receiver engine
; Parameters:
; ebp - io_addr
; Return value:
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;***************************************************************************
align 4
e3c59x_rx_reset:
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, (0101b shl 11) or 0x4 ; RxReset
out dx, ax
; wait for RxReset to complete
mov ecx, 200000
.rx_reset_loop:
in ax, dx
test ah, 10000b ; check CmdInProgress
jz .setup_upd
dec ecx
jns .rx_reset_loop
.setup_upd:
; check if full bus mastering
test byte [e3c59x_full_bus_master], 0xff
jz .rx_enable
; create upd ring
mov eax, e3c59x_upd_buff
zero_to_virt eax
mov [e3c59x_curr_upd], eax
mov esi, eax
virt_to_dma esi
mov edi, e3c59x_rx_buff
zero_to_dma edi
mov ebx, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE
zero_to_virt ebx
mov cl, E3C59X_NUM_RX_DESC-1
.upd_loop:
mov [ebx+E3C59X_UPD_UP_NEXT_PTR], esi
and dword [eax+E3C59X_UPD_PKT_STATUS], 0
mov [eax+E3C59X_UPD_UP_FRAG_ADDR], edi
mov dword [eax+E3C59X_UPD_UP_FRAG_LEN], E3C59X_MAX_ETH_FRAME_SIZE or (1 shl 31)
add edi, E3C59X_MAX_ETH_FRAME_SIZE
add esi, E3C59X_UPD_SIZE
mov ebx, eax
add eax, E3C59X_UPD_SIZE
dec cl
jns .upd_loop
mov eax, e3c59x_upd_buff
zero_to_dma eax
lea edx, [ebp+E3C59X_REG_UP_LIST_PTR]
out dx, eax ; write E3C59X_REG_UP_LIST_PTR
lea edx, [ebp+E3C59X_REG_COMMAND]
.rx_enable:
mov ax, (00100b shl 11) ; RxEnable
out dx, ax
ret
 
;***************************************************************************
; Function
; e3c59x_write_eeprom
; Description
; reads eeprom
; Note : the caller must switch to the register window 0
; before calling this function
; Parameters:
; ax - register to be read (only the first 63 words can be read)
; cx - value to be read into the register
; Return value:
; ax - word read
; Destroyed registers
; ax, ebx, edx
;
;***************************************************************************
; align 4
;e3c59x_write_eeprom:
; mov edx, [io_addr]
; add edx, E3C59X_REG_EEPROM_COMMAND
; cmp ah, 11b
; ja .finish ; address may have a value of maximal 1023
; shl ax, 2
; shr al, 2
; push eax
;; wait for busy
; mov ebx, 0xffff
;@@:
; in ax, dx
; test ah, 0x80
; jz .write_enable
; dec ebx
; jns @r
;; write enable
;.write_enable:
; xor eax, eax
; mov eax, (11b shl 4)
; out dx, ax
;; wait for busy
; mov ebx, 0xffff
;@@:
; in ax, dx
; test ah, 0x80
; jz .erase_loop
; dec ebx
; jns @r
;.erase_loop:
; pop eax
; push eax
; or ax, (11b shl 6) ; erase register
; out dx, ax
; mov ebx, 0xffff
;@@:
; in ax, dx
; test ah, 0x80
; jz .write_reg
; dec ebx
; jns @r
;.write_reg:
; add edx, E3C59X_REG_EEPROM_DATA-E3C59X_REG_EEPROM_COMMAND
; mov eax, ecx
; out dx, ax
;; write enable
; add edx, E3C59X_REG_EEPROM_COMMAND-E3C59X_REG_EEPROM_DATA
; xor eax, eax
; mov eax, (11b shl 4)
; out dx, ax
; wait for busy
; mov ebx, 0xffff
;@@:
; in ax, dx
; test ah, 0x80
; jz .issue_write_reg
; dec ebx
; jns @r
;.issue_write_reg:
; pop eax
; or ax, 01b shl 6
; out dx, ax
;.finish:
; ret
;***************************************************************************
; Function
; e3c59x_read_eeprom
; Description
; reads eeprom
; Parameters:
; ax - register to be read (only the first 63 words can be read)
; ebp - io_addr
; Return value:
; ax - word read
; Destroyed registers
; ax, ebx, edx, ebp
;
;***************************************************************************
align 4
e3c59x_read_eeprom:
push eax
; switch to register window 0
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+0
out dx, ax
pop eax
and ax, 111111b ; take only the first 6 bits into account
movzx ebx, byte [e3c59x_ver_id]
test word [ebx*4+e3c59x_hw_versions+2], EEPROM_8BIT
jz @f
add ax, 0x230 ; hardware constant
jmp .read
@@:
add ax, E3C59X_EEPROM_CMD_READ
test word [ebx*4+e3c59x_hw_versions+2], EEPROM_OFFSET
jz .read
add ax, 0x30
.read:
lea edx, [ebp+E3C59X_REG_EEPROM_COMMAND]
out dx, ax
mov ebx, 0xffff ; duration of about 162 us ;-)
.wait_for_reading:
in ax, dx
test ah, 0x80 ; check bit eepromBusy
jz .read_data
dec ebx
jns .wait_for_reading
.read_data:
lea edx, [ebp+E3C59X_REG_EEPROM_DATA]
in ax, dx
ret
 
;***************************************************************************
; Function
; e3c59x_mdio_sync
; Description
; initial synchronization
; Parameters
; ebp - io_addr
; Return value
; Destroyed registers
; ax, edx, cl
;
;***************************************************************************
align 4
e3c59x_mdio_sync:
; switch to register window 4
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+4
out dx, ax
cmp byte [e3c59x_preamble], 0
je .no_preamble
; send 32 logic ones
lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT]
mov cl, 31
.loop:
mov ax, (1 shl E3C59X_BIT_MGMT_DATA) or (1 shl E3C59X_BIT_MGMT_DIR)
out dx, ax
in ax, dx ; delay
mov ax, (1 shl E3C59X_BIT_MGMT_DATA) \
or (1 shl E3C59X_BIT_MGMT_DIR) \
or (1 shl E3C59X_BIT_MGMT_CLK)
out dx, ax
in ax, dx ; delay
dec cl
jns .loop
.no_preamble:
ret
 
;***************************************************************************
; Function
; e3c59x_mdio_read
; Description
; read MII register
; see page 16 in D83840A.pdf
; Parameters
; ah - PHY addr
; al - register addr
; ebp - io_addr
; Return value
; ax - register read
; Destroyed registers
; eax, ebx, cx, edx
;
;***************************************************************************
align 4
e3c59x_mdio_read:
push eax
call e3c59x_mdio_sync ; returns with window #4
pop eax
lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT]
shl al, 3
shr ax, 3
and ax, not E3C59X_MII_CMD_MASK
or ax, E3C59X_MII_CMD_READ
mov ebx, eax
xor ecx, ecx
mov cl, 13
.cmd_loop:
mov ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii
bt ebx, ecx
jnc .zero_bit
or al, (1 shl E3C59X_BIT_MGMT_DATA)
.zero_bit:
out dx, ax
push eax
in ax, dx ; delay
pop eax
or al, (1 shl E3C59X_BIT_MGMT_CLK) ; write
out dx, ax
in ax, dx ; delay
dec cl
jns .cmd_loop
; read data (18 bits with the two transition bits)
mov cl, 17
xor ebx, ebx
.read_loop:
shl ebx, 1
xor eax, eax ; read comand
out dx, ax
in ax, dx ; delay
in ax, dx
test al, (1 shl E3C59X_BIT_MGMT_DATA)
jz .dont_set
inc ebx
.dont_set:
mov ax, (1 shl E3C59X_BIT_MGMT_CLK)
out dx, ax
in ax, dx ; delay
dec cl
jns .read_loop
mov eax, ebx
ret
 
;***************************************************************************
; Function
; e3c59x_mdio_write
; Description
; write MII register
; see page 16 in D83840A.pdf
; Parameters
; ah - PHY addr
; al - register addr
; bx - word to be written
; ebp - io_addr
; Return value
; ax - register read
; Destroyed registers
; eax, ebx, cx, edx
;
;***************************************************************************
align 4
e3c59x_mdio_write:
push eax
call e3c59x_mdio_sync
pop eax
lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT]
shl al, 3
shr ax, 3
and ax, not E3C59X_MII_CMD_MASK
or ax, E3C59X_MII_CMD_WRITE
shl eax, 2
or eax, 10b ; transition bits
shl eax, 16
mov ax, bx
mov ebx, eax
mov ecx, 31
.cmd_loop:
mov ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii
bt ebx, ecx
jnc .zero_bit
or al, (1 shl E3C59X_BIT_MGMT_DATA)
.zero_bit:
out dx, ax
push eax
in ax, dx ; delay
pop eax
or al, (1 shl E3C59X_BIT_MGMT_CLK) ; write
out dx, ax
in ax, dx ; delay
dec ecx
jns .cmd_loop
ret
 
;***************************************************************************
; Function
; e3c59x_transmit
; Description
; Transmits a packet of data via the ethernet card
; edi - Pointer to 48 bit destination address
; bx - Type of packet
; ecx - size of packet
; esi - pointer to packet data
; ebp - io_addr
; Destroyed registers
; eax, ecx, edx, ebp
;
;***************************************************************************
align 4
e3c59x_transmit:
jmp dword [e3c59x_transmit_function]
 
;***************************************************************************
; Function
; e3c59x_check_tx_status
; Description
; Checks TxStatus queue.
; Return value
; al - 0 no error was found
; al - 1 error was found TxReset is needed
; Destroyed registers
; eax, ecx, edx, ebp
;
;***************************************************************************
e3c59x_check_tx_status:
movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC
; clear TxStatus queue
lea edx, [ebp+E3C59X_REG_TX_STATUS]
mov cl, 31 ; max number of queue entries
.tx_status_loop:
in al, dx
test al, al
jz .finish ; no error
test al, 0x3f
jnz .finish ; error
.no_error_found:
; clear current TxStatus entry which advances the next one
xor al, al
out dx, al
dec cl
jns .tx_status_loop
.finish:
ret
 
;***************************************************************************
; Function
; e3c59x_vortex_transmit
; Description
; Transmits a packet of data via the ethernet card
; edi - Pointer to 48 bit destination address
; bx - Type of packet
; ecx - size of packet
; esi - pointer to packet data
; ebp - io_addr
; Destroyed registers
; eax, edx, ecx, edi, esi, ebp
;
;***************************************************************************
align 4
e3c59x_vortex_transmit:
push ecx
call e3c59x_check_tx_status
pop ecx
test al, al
jz .no_error_found
jmp e3c59x_tx_reset
.no_error_found:
; switch to register window 7
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+7
out dx, ax
; check for master operation in progress
lea edx, [ebp+E3C59X_REG_MASTER_STATUS]
in ax, dx
test ah, 0x80
jnz .finish ; no DMA for sending
; dword boundary correction
cmp ecx, E3C59X_MAX_ETH_FRAME_SIZE
ja .finish ; packet is too long
; write Frame Start Header
mov eax, ecx
; add header length and extend the complete length to dword boundary
add eax, ETH_HLEN+3
and eax, not 3
lea edx, [ebp+E3C59X_REG_TX_DATA]
out dx, eax
; prepare the complete frame
push esi
mov esi, edi
mov edi, e3c59x_tx_buff
zero_to_virt edi
cld
; copy destination address
movsd
movsw
; copy source address
mov esi, node_addr
movsd
movsw
; copy packet type
mov [edi], bx
add edi, 2
; copy packet data
pop esi
push ecx
shr ecx, 2
rep movsd
pop ecx
and ecx, 3
rep movsb
mov ecx, eax
; program frame address to be sent
lea edx, [ebp+E3C59X_REG_MASTER_ADDRESS]
mov eax, e3c59x_tx_buff
zero_to_dma eax
out dx, eax
; program frame length
lea edx, [ebp+E3C59X_REG_MASTER_LEN]
mov eax, ecx
out dx, ax
; start DMA Down
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, (10100b shl 11) + 1 ; StartDMADown
out dx, ax
.finish:
ret
 
;***************************************************************************
; Function
; e3c59x_boomerang_transmit
; Description
; Transmits a packet of data via the ethernet card
; edi - Pointer to 48 bit destination address
; bx - Type of packet
; ecx - size of packet
; esi - pointer to packet data
; ebp - io_addr
; Destroyed registers
; eax, ebx, ecx, edx, esi, edi, ebp
;
;***************************************************************************
align 4
e3c59x_boomerang_transmit:
push ecx
call e3c59x_check_tx_status
pop ecx
test al, al
jz .no_error_found
jmp e3c59x_tx_reset
.no_error_found:
cmp ecx, E3C59X_MAX_ETH_FRAME_SIZE
ja .finish ; packet is too long
; calculate descriptor address
mov eax, [e3c59x_prev_dpd]
cmp eax, e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE
jb @f
; wrap around
mov eax, e3c59x_dpd_buff-E3C59X_DPD_SIZE
@@:
add eax, E3C59X_DPD_SIZE
zero_to_virt eax
push eax
; check DnListPtr
lea edx, [ebp+E3C59X_REG_DN_LIST_PTR]
in eax, dx
; mark if Dn_List_Ptr is cleared
test eax, eax
setz [e3c59x_dn_list_ptr_cleared]
; finish if no more free descriptor is available - FIXME!
cmp eax, [esp]
pop eax
jz .finish
push eax esi
mov esi, edi
; calculate tx_buffer address
mov edi, [e3c59x_prev_tx_frame]
cmp edi, e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE
jb @f
; wrap around
mov edi, e3c59x_tx_buff-E3C59X_MAX_ETH_FRAME_SIZE
@@:
add edi, E3C59X_MAX_ETH_FRAME_SIZE
zero_to_virt edi
mov eax, edi
cld
; copy destination address
movsd
movsw
; copy source address
mov esi, node_addr
movsd
movsw
; copy packet type
mov [edi], bx
add edi, 2
; copy packet data
pop esi
push ecx
shr ecx, 2
rep movsd
pop ecx
push ecx
and ecx, 3
rep movsb
; padding, do we really need it?
pop ecx
add ecx, ETH_HLEN
cmp ecx, ETH_ZLEN
jae @f
mov ecx, ETH_ZLEN
@@:
; calculate
mov ebx, ecx
;test byte [e3c59x_has_hwcksm], 0xff
;jz @f
;or ebx, (1 shl 26) ; set AddTcpChecksum
;@@:
or ebx, 0x8000 ; transmission complete notification
or ecx, 0x80000000 ; last fragment
; program DPD
mov edi, eax
pop eax
and dword [eax+E3C59X_DPD_DN_NEXT_PTR], 0
mov dword [eax+E3C59X_DPD_FRAME_START_HDR], ebx
virt_to_dma edi
mov dword [eax+E3C59X_DPD_DN_FRAG_ADDR], edi
mov [eax+E3C59X_DPD_DN_FRAG_LEN], ecx
; calculate physical address
virt_to_dma eax
push eax
cmp byte [e3c59x_dn_list_ptr_cleared], 0
jz .add_to_list
; write Dn_List_Ptr
out dx, eax
jmp .finish
.add_to_list:
; DnStall
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, ((110b shl 11)+2)
out dx, ax
; wait for DnStall to complete
mov ecx, 6000
.wait_for_stall:
in ax, dx ; read E3C59X_REG_INT_STATUS
test ah, 10000b
jz .dnstall_ok
dec ecx
jnz .wait_for_stall
.dnstall_ok:
pop eax
push eax
mov ebx, [e3c59x_prev_dpd]
zero_to_virt ebx
mov [ebx], eax
lea edx, [ebp+E3C59X_REG_DN_LIST_PTR]
in eax, dx
test eax, eax
jnz .dnunstall
; if Dn_List_Ptr has been cleared fill it up
pop eax
push eax
out dx, eax
.dnunstall:
; DnUnStall
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, ((110b shl 11)+3)
out dx, ax
.finish:
pop eax
dma_to_zero eax
mov [e3c59x_prev_dpd], eax
dma_to_zero edi
mov [e3c59x_prev_tx_frame], edi
ret
 
;***************************************************************************
; Function
; e3c59x_poll
; Description
; Polls the ethernet card for a received packet
; Received data, if any, ends up in Ether_buffer
; Destroyed registers
; eax, ebx, edx, ecx, edi, esi, ebp
;
;***************************************************************************
align 4
e3c59x_poll:
jmp dword [e3c59x_receive_function]
 
;***************************************************************************
; Function
; e3c59x_vortex_poll
; Description
; Polls the ethernet card for a received packet
; Received data, if any, ends up in Ether_buffer
; Parameters
; ebp - io_addr
; Return value
; al - 0 ; no packet received
; al - 1 ; packet received
; Destroyed registers
; eax, ebx, edx, ecx, edi, esi, ebp
;
;***************************************************************************
align 4
e3c59x_vortex_poll:
and word [eth_rx_data_len], 0 ; assume no packet received
movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC
.rx_status_loop:
; examine RxStatus
lea edx, [ebp+E3C59X_REG_RX_STATUS]
in ax, dx
test ax, ax
jz .finish
test ah, 0x80 ; rxIncomplete
jz .check_error
jmp .finish
.check_error:
test ah, 0x40
jz .check_length
; discard the top frame received advancing the next one
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, (01000b shl 11)
out dx, ax
jmp .rx_status_loop
.check_length:
and eax, 0x1fff
cmp eax, E3C59X_MAX_ETH_PKT_SIZE
ja .discard_frame ; frame is too long discard it
.check_dma:
push eax
; switch to register window 7
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, E3C59X_SELECT_REGISTER_WINDOW+7
out dx, ax
; check for master operation in progress
lea edx, [ebp+E3C59X_REG_MASTER_STATUS]
in ax, dx
test ah, 0x80
jz .read_frame ; no DMA for receiving
pop eax
jmp .finish
.read_frame:
; program buffer address to read in
lea edx, [ebp+E3C59X_REG_MASTER_ADDRESS]
if defined E3C59X_LINUX
mov eax, e3c59x_rx_buff
zero_to_dma eax
else
mov eax, Ether_buffer
end if
out dx, eax
; program frame length
lea edx, [ebp+E3C59X_REG_MASTER_LEN]
mov ax, 1560
out dx, ax
; start DMA Up
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, (10100b shl 11) ; StartDMAUp
out dx, ax
; check for master operation in progress
.dma_loop:
lea edx, [ebp+E3C59X_REG_MASTER_STATUS]
in ax, dx
test ah, 0x80
jnz .dma_loop
; registrate the received packet length
pop eax
mov word [eth_rx_data_len], ax
; discard the top frame received
.discard_frame:
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, (01000b shl 11)
out dx, ax
.finish:
; set return value
cmp word [eth_rx_data_len], 0
setne al
ret
 
;***************************************************************************
; Function
; e3c59x_boomerang_poll
; Description
; Polls the ethernet card for a received packet
; Received data, if any, ends up in Ether_buffer
; Parameters
; ebp - io_addr
; Return value
; al - 0 ; no packet received
; al - 1 ; packet received
; Destroyed registers
; eax, edx, ecx, edi, esi, ebp
;
;***************************************************************************
align 4
e3c59x_boomerang_poll:
and word [eth_rx_data_len], 0 ; assume no packet received
movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC
; check if packet is uploaded
mov eax, [e3c59x_curr_upd]
test byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x80 ; upPktComplete
jnz .check_error
jmp .finish
; packet is uploaded check for any error
.check_error:
test byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x40 ; upError
jz .copy_packet_length
and dword [eax+E3C59X_UPD_PKT_STATUS], 0
jmp .finish
.copy_packet_length:
mov ecx, [eax+E3C59X_UPD_PKT_STATUS]
and ecx, 0x1fff
cmp ecx, E3C59X_MAX_ETH_PKT_SIZE
jbe .copy_packet
and dword [eax+E3C59X_UPD_PKT_STATUS], 0
jmp .finish
.copy_packet:
push ecx
mov word [eth_rx_data_len], cx
mov esi, [eax+E3C59X_UPD_UP_FRAG_ADDR]
dma_to_virt esi
mov edi, Ether_buffer
shr ecx, 2 ; first copy dword-wise
cld
rep movsd ; copy the dwords
pop ecx
and ecx, 3
rep movsb ; copy the rest bytes
mov eax, [e3c59x_curr_upd]
and dword [eax+E3C59X_UPD_PKT_STATUS], 0
virt_to_zero eax
cmp eax, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE
jb .no_wrap
; wrap around
mov eax, e3c59x_upd_buff-E3C59X_UPD_SIZE
.no_wrap:
add eax, E3C59X_UPD_SIZE
zero_to_virt eax
mov [e3c59x_curr_upd], eax
.finish:
; check if the NIC is in the upStall state
lea edx, [ebp+E3C59X_REG_UP_PKT_STATUS]
in eax, dx
test ah, 0x20 ; UpStalled
jz .noUpUnStall
; issue upUnStall command
lea edx, [ebp+E3C59X_REG_COMMAND]
mov ax, ((110b shl 11)+1) ; upUnStall
out dx, ax
.noUpUnStall:
; set return value
cmp word [eth_rx_data_len], 0
setnz al
ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/forcedeth.inc
0,0 → 1,2696
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. 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$
 
;********************************************************************
; 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 edx, dword [edi+NvRegMacAddrB]
mov dword [forcedeth_orig_mac1], edx
 
; save MAC-address to global variable node_addr
mov dword [node_addr], eax
mov word [node_addr+4], dx
 
; reverse if desired
cmp word [forcedeth_device_id], 0x03E5
jae .no_reverse_mac
mov al, byte [node_addr]
xchg al, byte [node_addr+5]
mov byte [node_addr], al
mov al, byte [node_addr+1]
xchg al, byte [node_addr+4]
mov byte [node_addr+4], al
mov al, byte [node_addr+2]
xchg al, byte [node_addr+3]
mov byte [node_addr+3], al
.no_reverse_mac:
 
; 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
;@@:
cmp word [forcedeth_device_id], 0x0268
jb .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
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/i8255x.inc
0,0 → 1,794
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; I8255X.INC ;;
;; ;;
;; Ethernet driver for Menuet OS ;;
;; ;;
;; Version 0.3 11 August 2003 ;;
;; ;;
;; This driver is based on the eepro100 driver from ;;
;; the etherboot 5.0.6 project. The copyright statement is ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; remaining parts Copyright 2002 Mike Hibbett, ;;
;; mikeh@oceanfree.net ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
;********************************************************************
; Interface
; I8255x_reset
; I8255x_probe
; I8255x_poll
; I8255x_transmit
;
; These functions are referenced in ethernet.inc
;
;********************************************************************
 
 
rxfd_status equ eth_data_start
rxfd_command equ eth_data_start + 2
rxfd_link equ eth_data_start + 4
rxfd_rx_buf_addr equ eth_data_start + 8
rxfd_count equ eth_data_start + 12
rxfd_size equ eth_data_start + 14
rxfd_packet equ eth_data_start + 16
 
 
 
uglobal
eeprom_data:
times 16 dd 0
 
align 4
 
lstats:
tx_good_frames:
dd 0
tx_coll16_errs:
dd 0
tx_late_colls:
dd 0
tx_underruns:
dd 0
tx_lost_carrier:
dd 0
tx_deferred:
dd 0
tx_one_colls:
dd 0
tx_multi_colls:
dd 0
tx_total_colls:
dd 0
rx_good_frames:
dd 0
rx_crc_errs:
dd 0
rx_align_errs:
dd 0
rx_resource_errs:
dd 0
rx_overrun_errs:
dd 0
rx_colls_errs:
dd 0
rx_runt_errs:
dd 0
done_marker:
dd 0
 
align 4
 
confcmd:
confcmd_status:
dw 0
confcmd_command:
dw 0
confcmd_link:
dd 0
endg
 
iglobal
confcmd_data:
db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1
db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2
db 0x80, 0x3f, 0x05
endg
 
uglobal
align 4
 
txfd:
txfd_status:
dw 0
txfd_command:
dw 0
txfd_link:
dd 0
txfd_tx_desc_addr:
dd 0
txfd_count:
dd 0
txfd_tx_buf_addr0:
dd 0
txfd_tx_buf_size0:
dd 0
txfd_tx_buf_addr1:
dd 0
txfd_tx_buf_size1:
dd 0
 
align 4
 
hdr:
hdr_dst_addr:
times 6 db 0
hdr_src_addr:
times 6 db 0
hdr_type:
dw 0
endg
 
 
;***************************************************************************
; Function
; wait_for_cmd_done
;
; Description
; waits for the hardware to complete a command
; port address in edx
;
; al destroyed
;***************************************************************************
wait_for_cmd_done:
in al, dx
cmp al, 0
jne wait_for_cmd_done
ret
 
 
 
;***************************************************************************
; Function
; mdio_read
;
; Description
; This probably reads a register in the "physical media interface chip"
; Phy_id in ebx
; location in ecx
;
; Data returned in eax
;
;***************************************************************************
mdio_read:
mov edx, [io_addr]
add edx, 16 ; SCBCtrlMDI
 
mov eax, 0x08000000
shl ecx, 16
or eax, ecx
shl ebx, 21
or eax, ebx
 
out dx, eax
 
mrlp:
call delay_us
in eax, dx
mov ecx, eax
and ecx, 0x10000000
jz mrlp
 
and eax, 0xffff
ret
 
 
 
;***************************************************************************
; Function
; mdio_write
;
; Description
; This probably writes a register in the "physical media interface chip"
; Phy_id in ebx
; location in ecx
; data in edx
; Data returned in eax
;
;***************************************************************************
mdio_write:
mov eax, 0x04000000
shl ecx, 16
or eax, ecx
shl ebx, 21
or eax, ebx
or eax, edx
 
mov edx, [io_addr]
add edx, 16 ; SCBCtrlMDI
out dx, eax
 
mwlp:
call delay_us
in eax, dx
mov ecx, eax
and ecx, 0x10000000
jz mwlp
 
and eax, 0xffff
ret
 
 
 
;/***********************************************************************/
;/* I82557 related defines */
;/***********************************************************************/
 
; Serial EEPROM section.
; A "bit" grungy, but we work our way through bit-by-bit :->.
; EEPROM_Ctrl bits.
EE_SHIFT_CLK equ 0x01 ; EEPROM shift clock.
EE_CS equ 0x02 ; EEPROM chip select.
EE_DATA_WRITE equ 0x04 ; EEPROM chip data in.
EE_DATA_READ equ 0x08 ; EEPROM chip data out.
EE_WRITE_0 equ 0x4802
EE_WRITE_1 equ 0x4806
EE_ENB equ 0x4802
 
 
; The EEPROM commands include the alway-set leading bit.
EE_READ_CMD equ 6
 
; The SCB accepts the following controls for the Tx and Rx units:
CU_START equ 0x0010
CU_RESUME equ 0x0020
CU_STATSADDR equ 0x0040
CU_SHOWSTATS equ 0x0050 ; Dump statistics counters.
CU_CMD_BASE equ 0x0060 ; Base address to add to add CU commands.
CU_DUMPSTATS equ 0x0070 ; Dump then reset stats counters.
 
RX_START equ 0x0001
RX_RESUME equ 0x0002
RX_ABORT equ 0x0004
RX_ADDR_LOAD equ 0x0006
RX_RESUMENR equ 0x0007
INT_MASK equ 0x0100
DRVR_INT equ 0x0200 ; Driver generated interrupt.
 
 
;***************************************************************************
; Function
; do_eeprom_cmd
;
; Description
; writes a cmd to the ethernet cards eeprom, by bit bashing
; cmd in ebx
; cmd length in ecx
; return in eax
;***************************************************************************
do_eeprom_cmd:
mov edx, [io_addr]; We only require the value in dx
add dx, 14 ; the value SCBeeprom
 
mov ax, EE_ENB
out dx, ax
call delay_us
 
mov ax, 0x4803 ; EE_ENB | EE_SHIFT_CLK
out dx, ax
call delay_us
 
; dx holds ee_addr
; ecx holds count
; eax holds cmd
xor edi, edi ; this will be the receive data
 
dec_001:
mov esi, 1
 
dec ecx
shl esi, cl
inc ecx
and esi, ebx
mov eax, EE_WRITE_0; I am assuming this doesnt affect the flags..
cmp esi, 0
jz dec_002
mov eax, EE_WRITE_1
 
dec_002:
out dx, ax
call delay_us
 
or ax, EE_SHIFT_CLK
out dx, ax
call delay_us
 
shl edi, 1
 
in ax, dx
and ax, EE_DATA_READ
cmp ax, 0
jz dec_003
inc edi
 
dec_003:
loop dec_001
 
mov ax, EE_ENB
out dx, ax
call delay_us
 
mov ax, 0x4800
out dx, ax
call delay_us
 
mov eax, edi
 
ret
 
 
;***************************************************************************
; Function
; I8255x_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
;
;***************************************************************************
I8255x_probe:
DEBUGF 1," K : Probing i8255x device \n"
mov eax, [io_addr]
 
mov ebx, [pci_bus]
mov ecx, [pci_dev]
mov edx, 0x04 ; PCI_COMMAND
call pcibios_read_config_word
 
or ax, 0x05
mov ebx, [pci_bus]
mov ecx, [pci_dev]
mov edx, 0x04 ; PCI_COMMAND
call pcibios_write_config_word
 
mov ebx, 0x6000000
mov ecx, 27
call do_eeprom_cmd
and eax, 0xffe0000
cmp eax, 0xffe0000
je bige
 
mov ebx, 0x1800000
mov ecx, 0x40
jmp doread
 
bige:
mov ebx, 0x6000000
mov ecx, 0x100
 
doread:
; do-eeprom-cmd will destroy all registers
; we have eesize in ecx
; read_cmd in ebx
 
; Ignore full eeprom - just load the mac address
mov ecx, 0
 
drlp:
push ecx ; save count
push ebx
mov eax, ecx
shl eax, 16
or ebx, eax
mov ecx, 27
call do_eeprom_cmd
 
pop ebx
pop ecx
 
mov edx, ecx
shl edx, 2
mov esi, eeprom_data
add esi, edx
mov [esi], eax
 
inc ecx
cmp ecx, 16
jne drlp
 
; OK, we have the MAC address.
; Now reset the card
 
mov edx, [io_addr]
add dx, 8 ; SCBPort
xor eax, eax ; The reset cmd == 0
out dx, eax
 
mov esi, 10
call delay_ms ; Give the card time to warm up.
 
mov eax, lstats
mov edx, [io_addr]
add edx, 4 ; SCBPointer
out dx, eax
 
mov eax, 0x0140 ; INT_MASK | CU_STATSADDR
mov edx, [io_addr]
add edx, 2 ; SCBCmd
out dx, ax
 
call wait_for_cmd_done
 
mov eax, 0
mov edx, [io_addr]
add edx, 4 ; SCBPointer
out dx, eax
 
mov eax, 0x0106 ; INT_MASK | RX_ADDR_LOAD
mov edx, [io_addr]
add edx, 2 ; SCBCmd
out dx, ax
 
call wait_for_cmd_done
 
; build rxrd structure
mov ax, 0x0001
mov [rxfd_status], ax
mov ax, 0x0000
mov [rxfd_command], ax
 
mov eax, rxfd_status
sub eax, OS_BASE
mov [rxfd_link], eax
 
mov eax, Ether_buffer
sub eax, OS_BASE
mov [rxfd_rx_buf_addr], eax
 
mov ax, 0
mov [rxfd_count], ax
 
mov ax, 1528
mov [rxfd_size], ax
 
mov edx, [io_addr]
add edx, 4 ; SCBPointer
 
mov eax, rxfd_status
sub eax, OS_BASE
out dx, eax
 
mov edx, [io_addr]
add edx, 2 ; SCBCmd
 
mov ax, 0x0101 ; INT_MASK | RX_START
out dx, ax
 
call wait_for_cmd_done
 
; start the reciver
 
mov ax, 0
mov [rxfd_status], ax
 
mov ax, 0xc000
mov [rxfd_command], ax
 
mov edx, [io_addr]
add edx, 4 ; SCBPointer
 
mov eax, rxfd_status
sub eax, OS_BASE
out dx, eax
 
mov edx, [io_addr]
add edx, 2 ; SCBCmd
 
mov ax, 0x0101 ; INT_MASK | RX_START
out dx, ax
 
; Init TX Stuff
 
mov edx, [io_addr]
add edx, 4 ; SCBPointer
 
mov eax, 0
out dx, eax
 
mov edx, [io_addr]
add edx, 2 ; SCBCmd
 
mov ax, 0x0160 ; INT_MASK | CU_CMD_BASE
out dx, ax
 
call wait_for_cmd_done
 
; Set TX Base address
 
; First, set up confcmd values
 
mov ax, 2
mov [confcmd_command], ax
mov eax, txfd
sub eax, OS_BASE
mov [confcmd_link], eax
 
mov ax, 1
mov [txfd_command], ax ; CmdIASetup
 
mov ax, 0
mov [txfd_status], ax
 
mov eax, confcmd
sub eax, OS_BASE
mov [txfd_link], eax
 
 
 
; ETH_ALEN is 6 bytes
 
mov esi, eeprom_data
mov edi, node_addr
mov ecx, 3
drp000:
mov eax, [esi]
mov [edi], al
shr eax, 8
inc edi
mov [edi], al
inc edi
add esi, 4
loop drp000
 
; Hard code your MAC address into node_addr at this point,
; If you cannot read the MAC address from the eeprom in the previous step.
; You also have to write the mac address into txfd_tx_desc_addr, rather
; than taking data from eeprom_data
 
mov esi, eeprom_data
mov edi, txfd_tx_desc_addr
mov ecx, 3
drp001:
mov eax, [esi]
mov [edi], al
shr eax, 8
inc edi
mov [edi], al
inc edi
add esi, 4
loop drp001
 
 
mov esi, eeprom_data + (6 * 4)
mov eax, [esi]
shr eax, 8
and eax, 0x3f
cmp eax, 4 ; DP83840
je drp002
cmp eax, 10 ; DP83840A
je drp002
jmp drp003
 
drp002:
mov ebx, [esi]
and ebx, 0x1f
push ebx
mov ecx, 23
call mdio_read
pop ebx
or eax, 0x0422
mov ecx, 23
mov edx, eax
call mdio_write
 
drp003:
mov ax, 0x4002 ; Cmdsuspend | CmdConfigure
mov [confcmd_command], ax
mov ax, 0
mov [confcmd_status], ax
mov eax, txfd
mov [confcmd_link], eax
mov ebx, confcmd_data
mov al, 0x88 ; fifo of 8 each
mov [ebx + 1], al
mov al, 0
mov [ebx + 4], al
mov al, 0x80
mov [ebx + 5], al
mov al, 0x48
mov [ebx + 15], al
mov al, 0x80
mov [ebx + 19], al
mov al, 0x05
mov [ebx + 21], al
 
mov eax, txfd
sub eax, OS_BASE
mov edx, [io_addr]
add edx, 4 ; SCBPointer
out dx, eax
 
mov eax, 0x0110 ; INT_MASK | CU_START
mov edx, [io_addr]
add edx, 2 ; SCBCmd
out dx, ax
 
call wait_for_cmd_done
jmp skip
 
; wait for thing to start
drp004:
mov ax, [txfd_status]
cmp ax, 0
je drp004
 
skip:
; Indicate that we have successfully reset the card
mov eax, [pci_data]
mov [eth_status], eax
 
I8255x_exit:
ret
 
 
 
;***************************************************************************
; Function
; I8255x_reset
; Description
; Place the chip (ie, the ethernet card) into a virgin state
; No inputs
; All registers destroyed
;
;***************************************************************************
I8255x_reset:
ret
 
 
 
;***************************************************************************
; Function
; I8255x_poll
;
; Description
; Polls the ethernet card for a received packet
; Received data, if any, ends up in Ether_buffer
;
;***************************************************************************
I8255x_poll:
mov ax, 0 ; assume no data
mov [eth_rx_data_len], ax
 
mov ax, [rxfd_status]
cmp ax, 0
je i8p_exit
 
mov ax, 0
mov [rxfd_status], ax
 
mov ax, 0xc000
mov [rxfd_command], ax
 
mov edx, [io_addr]
add edx, 4 ; SCBPointer
 
mov eax, rxfd_status
sub eax, OS_BASE
out dx, eax
 
mov edx, [io_addr]
add edx, 2 ; SCBCmd
 
mov ax, 0x0101 ; INT_MASK | RX_START
out dx, ax
 
call wait_for_cmd_done
 
mov esi, rxfd_packet
mov edi, Ether_buffer
mov ecx, 1518
cld
rep movsb
 
mov ax, [rxfd_count]
and ax, 0x3fff
mov [eth_rx_data_len], ax
 
i8p_exit:
ret
 
 
 
;***************************************************************************
; Function
; I8255x_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
;
;***************************************************************************
I8255x_transmit:
 
mov [hdr_type], bx
 
mov eax, [edi]
mov [hdr_dst_addr], eax
mov ax, [edi+4]
mov [hdr_dst_addr+4], ax
 
mov eax, [node_addr]
mov [hdr_src_addr], eax
mov ax, [node_addr+4]
mov [hdr_src_addr+4], ax
 
mov edx, [io_addr]
in ax, dx
and ax, 0xfc00
out dx, ax
 
xor ax, ax
mov [txfd_status], ax
mov ax, 0x400C ; Cmdsuspend | CmdTx | CmdTxFlex
mov [txfd_command], ax
mov eax, txfd
mov [txfd_link], eax
mov eax, 0x02208000
mov [txfd_count], eax
mov eax, txfd_tx_buf_addr0
sub eax, OS_BASE
mov [txfd_tx_desc_addr], eax
mov eax, hdr
sub eax, OS_BASE
mov [txfd_tx_buf_addr0], eax
mov eax, 14; sizeof hdr
mov [txfd_tx_buf_size0], eax
 
; Copy the buffer address and size in
mov eax, esi
sub eax, OS_BASE
mov [txfd_tx_buf_addr1], eax
mov eax, ecx
mov [txfd_tx_buf_size1], eax
 
mov eax, txfd
sub eax, OS_BASE
mov edx, [io_addr]
add edx, 4 ; SCBPointer
out dx, eax
 
mov ax, 0x0110 ; INT_MASK | CU_START
mov edx, [io_addr]
add edx, 2 ; SCBCmd
out dx, ax
 
call wait_for_cmd_done
 
mov edx, [io_addr]
in ax, dx
 
I8t_001:
mov ax, [txfd_status]
cmp ax, 0
je I8t_001
 
mov edx, [io_addr]
in ax, dx
 
ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/rtl8029.inc
0,0 → 1,976
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; RTL8029.INC ;;
;; ;;
;; Ethernet driver for Menuet OS ;;
;; ;;
;; Version 0.2 31 July 2002 ;;
;; ;;
;; This driver is based on the ns8390 driver from ;;
;; the etherboot 5.0.6 project. The copyright statement is ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; remaining parts Copyright 2002 Mike Hibbett, ;;
;; mikeh@oceanfree.net ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;; While this implementation handles only PCI bus RTL8029 ;;
;; hardware, it can be easily adapted to other NE2000 clone ;;
;; products. I just dont have any to try! ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
;********************************************************************
; Interface
; rtl8029_reset
; rtl8029_probe
; rtl8029_poll
; rtl8029_transmit
;
;********************************************************************
 
 
 
 
;**************************************************************************
; 8390 Register Definitions
;**************************************************************************
D8390_P0_COMMAND equ 0x00
D8390_P0_PSTART equ 0x01
D8390_P0_PSTOP equ 0x02
D8390_P0_BOUND equ 0x03
D8390_P0_TSR equ 0x04
D8390_P0_TPSR equ 0x04
D8390_P0_TBCR0 equ 0x05
D8390_P0_TBCR1 equ 0x06
D8390_P0_ISR equ 0x07
D8390_P0_RSAR0 equ 0x08
D8390_P0_RSAR1 equ 0x09
D8390_P0_RBCR0 equ 0x0A
D8390_P0_RBCR1 equ 0x0B
D8390_P0_RSR equ 0x0C
D8390_P0_RCR equ 0x0C
D8390_P0_TCR equ 0x0D
D8390_P0_DCR equ 0x0E
D8390_P0_IMR equ 0x0F
D8390_P1_COMMAND equ 0x00
D8390_P1_PAR0 equ 0x01
D8390_P1_PAR1 equ 0x02
D8390_P1_PAR2 equ 0x03
D8390_P1_PAR3 equ 0x04
D8390_P1_PAR4 equ 0x05
D8390_P1_PAR5 equ 0x06
D8390_P1_CURR equ 0x07
D8390_P1_MAR0 equ 0x08
 
D8390_COMMAND_PS0 equ 0x0 ; Page 0 select
D8390_COMMAND_PS1 equ 0x40 ; Page 1 select
D8390_COMMAND_PS2 equ 0x80 ; Page 2 select
D8390_COMMAND_RD2 equ 0x20 ; Remote DMA control
D8390_COMMAND_RD1 equ 0x10
D8390_COMMAND_RD0 equ 0x08
D8390_COMMAND_TXP equ 0x04 ; transmit packet
D8390_COMMAND_STA equ 0x02 ; start
D8390_COMMAND_STP equ 0x01 ; stop
 
D8390_COMMAND_RD2_STA equ 0x22
D8390_COMMAND_RD2_STP equ 0x21
D8390_COMMAND_RD1_STA equ 0x12
D8390_COMMAND_RD0_STA equ 0x0A
D8390_COMMAND_PS0_RD2_STP equ 0x21
D8390_COMMAND_PS1_RD2_STP equ 0x61
D8390_COMMAND_PS0_RD2_STA equ 0x22
D8390_COMMAND_PS0_TXP_RD2_STA equ 0x26
 
D8390_RCR_MON equ 0x20 ; monitor mode
 
D8390_DCR_FT1 equ 0x40
D8390_DCR_LS equ 0x08 ; Loopback select
D8390_DCR_WTS equ 0x01 ; Word transfer select
 
D8390_DCR_FT1_LS equ 0x48
D8390_DCR_WTS_FT1_LS equ 0x49
 
D8390_ISR_PRX equ 0x01 ; successful recv
D8390_ISR_PTX equ 0x02 ; successful xmit
D8390_ISR_RXE equ 0x04 ; receive error
D8390_ISR_TXE equ 0x08 ; transmit error
D8390_ISR_OVW equ 0x10 ; Overflow
D8390_ISR_CNT equ 0x20 ; Counter overflow
D8390_ISR_RDC equ 0x40 ; Remote DMA complete
D8390_ISR_RST equ 0x80 ; reset
 
D8390_RSTAT_PRX equ 0x01 ; successful recv
D8390_RSTAT_CRC equ 0x02 ; CRC error
D8390_RSTAT_FAE equ 0x04 ; Frame alignment error
D8390_RSTAT_OVER equ 0x08 ; FIFO overrun
 
D8390_TXBUF_SIZE equ 6
D8390_RXBUF_END equ 32
D8390_PAGE_SIZE equ 256
 
ETH_ALEN equ 6
ETH_HLEN equ 14
ETH_ZLEN equ 60
ETH_FRAME_LEN equ 1514
 
FLAG_PIO equ 0x01
FLAG_16BIT equ 0x02
ASIC_PIO equ 0
 
VENDOR_NONE equ 0
VENDOR_WD equ 1
VENDOR_NOVELL equ 2
VENDOR_3COM equ 3
 
NE_ASIC_OFFSET equ 0x10
NE_RESET equ 0x0F ; Used to reset card
NE_DATA equ 0x00 ; Used to read/write NIC mem
 
MEM_8192 equ 32
MEM_16384 equ 64
MEM_32768 equ 128
 
ISA_MAX_ADDR equ 0x400
 
uglobal
eth_flags:
db 0
eth_vendor:
db 0
eth_nic_base:
dw 0
eth_asic_base:
dw 0
eth_memsize:
db 0
eth_rx_start:
db 0
eth_tx_start:
db 0
eth_bmem:
dd 0
eth_rmem:
dd 0
romdata:
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
endg
 
iglobal
test_data:
db 'NE*000 memory',0
test_buffer:
db ' ',0
endg
 
uglobal
eth_type:
dw 0
pkthdr:
db 0,0,0,0 ; status, next, (short) len
pktoff:
dw 0
eth_rx_data_ptr:
dd 0
eth_tmp_len:
dw 0
endg
 
 
 
;***************************************************************************
; Function
; eth_pio_read
;
; Description
; Read a frame from the ethernet card via Programmed I/O
; src in ebx
; cnt in ecx
; dst in edi
;***************************************************************************
eth_pio_read:
mov al, [eth_flags]
and al, FLAG_16BIT
cmp al, 0
je epr_001
 
inc ecx
and ecx, 0xFFFFFFFE
 
epr_001:
mov al, D8390_COMMAND_RD2_STA
mov dx, [eth_nic_base]
add dx, D8390_P0_COMMAND
out dx, al
 
mov al, cl
mov dx, [eth_nic_base]
add dx, D8390_P0_RBCR0
out dx, al
 
mov al, ch
mov dx, [eth_nic_base]
add dx, D8390_P0_RBCR1
out dx, al
 
mov al, bl
mov dx, [eth_nic_base]
add dx, D8390_P0_RSAR0
out dx, al
 
mov al, bh
mov dx, [eth_nic_base]
add dx, D8390_P0_RSAR1
out dx, al
 
mov al, D8390_COMMAND_RD0_STA
mov dx, [eth_nic_base]
add dx, D8390_P0_COMMAND
out dx, al
 
mov dx, [eth_asic_base]
add dx, ASIC_PIO
 
mov al, [eth_flags]
and al, FLAG_16BIT
cmp al, 0
je epr_003
 
shr ecx, 1
 
epr_002:
; 2 bytes at a time
in ax, dx
mov [edi], ax
add edi, 2
loop epr_002
ret
 
epr_003:
; 1 byte at a time
in al, dx
mov [edi], al
inc edi
loop epr_003
ret
 
 
 
 
;***************************************************************************
; Function
; eth_pio_write
;
; Description
; writes a frame to the ethernet card via Programmed I/O
; dst in ebx
; cnt in ecx
; src in esi
;***************************************************************************
eth_pio_write:
mov al, [eth_flags]
and al, FLAG_16BIT
cmp al, 0
je epw_001
 
inc ecx
and ecx, 0xFFFFFFFE
 
epw_001:
mov al, D8390_COMMAND_RD2_STA
mov dx, [eth_nic_base]
add dx, D8390_P0_COMMAND
out dx, al
 
mov al, D8390_ISR_RDC
mov dx, [eth_nic_base]
add dx, D8390_P0_ISR
out dx, al
 
 
mov al, cl
mov dx, [eth_nic_base]
add dx, D8390_P0_RBCR0
out dx, al
 
mov al, ch
mov dx, [eth_nic_base]
add dx, D8390_P0_RBCR1
out dx, al
 
mov al, bl
mov dx, [eth_nic_base]
add dx, D8390_P0_RSAR0
out dx, al
 
mov al, bh
mov dx, [eth_nic_base]
add dx, D8390_P0_RSAR1
out dx, al
 
mov al, D8390_COMMAND_RD1_STA
mov dx, [eth_nic_base]
add dx, D8390_P0_COMMAND
out dx, al
 
mov dx, [eth_asic_base]
add dx, ASIC_PIO
 
mov al, [eth_flags]
and al, FLAG_16BIT
cmp al, 0
je epw_003
 
shr ecx, 1
 
epw_002:
; 2 bytes at a time
mov ax, [esi]
add esi, 2
out dx, ax
 
loop epw_002
jmp epw_004
 
epw_003:
; 1 byte at a time
mov al, [esi]
inc esi
out dx, al
loop epw_003
 
epw_004:
mov dx, [eth_nic_base]
add dx, D8390_P0_ISR
 
epw_005:
in al, dx
and al, D8390_ISR_RDC
cmp al, D8390_ISR_RDC
jne epw_005
 
ret
 
 
 
;***************************************************************************
; Function
; rtl8029_reset
; Description
; Place the chip (ie, the ethernet card) into a virgin state
; No inputs
; All registers destroyed
;
;***************************************************************************
rtl8029_reset:
mov bx, [eth_nic_base]
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_PS0_RD2_STP
out dx, al
 
mov dx, bx
add dx, D8390_P0_DCR
mov al, [eth_flags]
and al, FLAG_16BIT
cmp al, FLAG_16BIT
jne nsr_001
 
mov al, 0x49
jmp nsr_002
 
nsr_001:
mov al, 0x48
 
nsr_002:
out dx, al
 
xor al, al
 
mov dx, bx
add dx, D8390_P0_RBCR0
out dx, al
 
mov dx, bx
add dx, D8390_P0_RBCR1
out dx, al
 
mov dx, bx
add dx, D8390_P0_RCR
mov al, 0x20
out dx, al
 
mov dx, bx
add dx, D8390_P0_TCR
mov al, 2
out dx, al
 
mov dx, bx
add dx, D8390_P0_TPSR
mov al, [eth_tx_start]
out dx, al
 
mov dx, bx
add dx, D8390_P0_PSTART
mov al, [eth_rx_start]
out dx, al
 
mov dx, bx
add dx, D8390_P0_PSTOP
mov al, [eth_memsize]
out dx, al
 
mov dx, bx
add dx, D8390_P0_BOUND
mov al, [eth_memsize]
dec al
out dx, al
 
mov dx, bx
add dx, D8390_P0_ISR
mov al, 0xff
out dx, al
 
mov dx, bx
add dx, D8390_P0_IMR
xor al, al
out dx, al
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_PS1_RD2_STP
out dx, al
 
mov dx, bx
add dx, D8390_P1_PAR0
mov esi, node_addr
mov ecx, ETH_ALEN
 
nsr_003:
mov al, [esi]
out dx, al
 
inc esi
inc dx
loop nsr_003
 
mov dx, bx
add dx, D8390_P1_MAR0
mov ecx, ETH_ALEN
 
mov al, 0xff
 
nsr_004:
out dx, al
inc dx
loop nsr_004
 
mov dx, bx
add dx, D8390_P1_CURR
mov al, [eth_rx_start]
out dx, al
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_PS0_RD2_STA
out dx, al
 
mov dx, bx
add dx, D8390_P0_ISR
mov al, 0xff
out dx, al
 
mov dx, bx
add dx, D8390_P0_TCR
mov al, 0
out dx, al
 
mov dx, bx
add dx, D8390_P0_RCR
mov al, 4
out dx, al
 
ret
 
 
 
;***************************************************************************
; Function
; rtl8029_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
;
;***************************************************************************
rtl8029_probe:
mov eax, [io_addr]
mov [eth_nic_base], ax ; The IO address space is 16 bit only
 
mov al, VENDOR_NONE
mov [eth_vendor], al
 
mov al, [eth_vendor]
cmp al, VENDOR_NONE
 
jne ep_check_have_vendor
xor eax, eax
mov [eth_bmem], eax
 
mov al, FLAG_PIO
mov [eth_flags], al
 
mov ax, [eth_nic_base]
add ax, NE_ASIC_OFFSET
mov [eth_asic_base], ax
 
mov al, MEM_16384
mov [eth_memsize], al
 
mov al, 32
mov [eth_tx_start], al
 
add al, D8390_TXBUF_SIZE
mov [eth_rx_start], al
 
mov dx, [eth_asic_base]
add dx, NE_RESET
 
in al, dx
out dx, al
 
in al, 0x84
 
mov bx, [eth_nic_base]
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_RD2_STP
out dx, al
 
mov dx, bx
add dx, D8390_P0_RCR
mov al, D8390_RCR_MON
out dx, al
 
mov dx, bx
add dx, D8390_P0_DCR
mov al, D8390_DCR_FT1_LS
out dx, al
 
mov dx, bx
add dx, D8390_P0_PSTART
mov al, MEM_8192
out dx, al
 
mov dx, bx
add dx, D8390_P0_PSTOP
mov al, MEM_16384
out dx, al
 
mov esi, test_data
mov ebx, 8192
mov ecx, 14
call eth_pio_write
 
mov ebx, 8192
mov ecx, 14
mov edi, test_buffer
call eth_pio_read
 
mov esi, test_buffer
mov edi, test_data
mov ecx, 13
cld
rep cmpsb
 
je ep_set_vendor
 
mov al, [eth_flags]
or al, FLAG_16BIT
mov [eth_flags], al
 
mov al, MEM_32768
mov [eth_memsize], al
 
mov al, 64
mov [eth_tx_start], al
 
add al, D8390_TXBUF_SIZE
mov [eth_rx_start], al
 
mov bx, [eth_nic_base]
 
mov dx, bx
add dx, D8390_P0_DCR
mov al, D8390_DCR_WTS_FT1_LS
out dx, al
 
mov dx, bx
add dx, D8390_P0_PSTART
mov al, MEM_16384
out dx, al
 
mov dx, bx
add dx, D8390_P0_PSTOP
mov al, MEM_32768
out dx, al
 
mov esi, test_data
mov ebx, 16384
mov ecx, 14
call eth_pio_write
 
mov ebx, 16384
mov ecx, 14
mov edi, test_buffer
call eth_pio_read
 
mov esi, test_buffer
mov edi, test_data
mov ecx, 13
cld
rep cmpsb
 
ep_set_vendor:
; this bit is odd - probably left over from my hacking
mov ax, [eth_nic_base]
cmp ax, 0
je rtl8029_exit
cmp ax, ISA_MAX_ADDR
jbe ep_001
mov al, [eth_flags]
or al, FLAG_16BIT
mov [eth_flags], al
 
ep_001:
mov al, VENDOR_NOVELL
mov [eth_vendor], al
 
mov ebx, 0
mov ecx, 16
mov edi, romdata
call eth_pio_read
 
 
mov ecx, ETH_ALEN
mov esi, romdata
mov edi, node_addr
 
mov bl, [eth_flags]
and bl, FLAG_16BIT
 
ep_002:
mov al, [esi]
mov [edi], al
 
inc edi
inc esi
cmp bl, FLAG_16BIT
jne ep_003
 
inc esi
 
ep_003:
loop ep_002
 
ep_check_have_vendor:
mov al, [eth_vendor]
cmp al, VENDOR_NONE
je rtl8029_exit
 
cmp al, VENDOR_3COM
je ep_reset_card
 
mov eax, [eth_bmem]
mov [eth_rmem], eax
 
ep_reset_card:
; Reset the card
call rtl8029_reset
 
; Indicate that we have successfully reset the card
mov eax, [pci_data]
mov [eth_status], eax
 
rtl8029_exit:
ret
 
 
 
;***************************************************************************
; Function
; rtl8029_poll
;
; Description
; Polls the ethernet card for a received packet
; Received data, if any, ends up in Ether_buffer
;
;***************************************************************************
rtl8029_poll:
mov eax, Ether_buffer
mov [eth_rx_data_ptr], eax
 
mov bx, [eth_nic_base]
 
mov dx, bx
add dx, D8390_P0_RSR
in al, dx
 
and al, D8390_RSTAT_PRX
cmp al, D8390_RSTAT_PRX
jne nsp_exit
 
mov dx, bx
add dx, D8390_P0_BOUND
in al, dx
inc al
 
cmp al, [eth_memsize]
jb nsp_001
 
mov al, [eth_rx_start]
 
nsp_001:
mov ch, al
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_PS1
out dx, al
 
mov dx, bx
add dx, D8390_P1_CURR
in al, dx ; get current page
mov cl, al
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_PS0
out dx, al
 
cmp cl, [eth_memsize]
jb nsp_002
 
mov cl, [eth_rx_start]
 
nsp_002:
cmp cl, ch
je nsp_exit
 
xor ax, ax
mov ah, ch
 
mov [pktoff], ax
 
mov al, [eth_flags]
and al, FLAG_PIO
cmp al, FLAG_PIO
jne nsp_003
 
movzx ebx, word [pktoff]
mov edi, pkthdr
mov ecx, 4
call eth_pio_read
jmp nsp_004
 
nsp_003:
mov edi, [eth_rmem]
movzx eax, word [pktoff]
add edi, eax
mov eax, [edi]
mov [pkthdr], eax
 
nsp_004:
mov ax, [pktoff]
add ax, 4
mov [pktoff], ax
 
mov ax, [pkthdr + 2]
sub ax, 4
 
mov [eth_tmp_len], ax
 
cmp ax, ETH_ZLEN
jb nsp_exit
 
cmp ax, ETH_FRAME_LEN
ja nsp_exit
 
mov al, [pkthdr]
and al, D8390_RSTAT_PRX
cmp al, D8390_RSTAT_PRX
jne nsp_exit
 
; Right, we can now get the data
 
mov ax, [eth_tmp_len]
mov [eth_rx_data_len], ax
 
xor ebx, ebx
mov bh, [eth_memsize]
sub bx, [pktoff]
 
cmp [eth_tmp_len], bx
jbe nsp_005
 
mov al, [eth_flags]
and al, FLAG_PIO
cmp al, FLAG_PIO
jne nsp_006
 
push ebx
mov ecx, ebx
xor ebx, ebx
mov bx, [pktoff]
mov edi, [eth_rx_data_ptr]
call eth_pio_read
pop ebx
jmp nsp_007
 
nsp_006:
; Not implemented, as we are using PIO mode on this card
 
nsp_007:
xor ax, ax
mov ah, [eth_rx_start]
mov [pktoff], ax
 
mov eax, [eth_rx_data_ptr]
add eax, ebx
mov [eth_rx_data_ptr], eax
 
mov ax, [eth_tmp_len]
sub ax, bx
mov [eth_tmp_len], ax
 
nsp_005:
mov al, [eth_flags]
and al, FLAG_PIO
cmp al, FLAG_PIO
jne nsp_008
 
xor ebx, ebx
mov bx, [pktoff]
xor ecx, ecx
mov cx, [eth_tmp_len]
mov edi, [eth_rx_data_ptr]
call eth_pio_read
jmp nsp_009
 
nsp_008:
; Not implemented, as we are using PIO mode on this card
 
nsp_009:
mov al, [pkthdr+1]
cmp al, [eth_rx_start]
jne nsp_010
 
mov al, [eth_memsize]
 
nsp_010:
mov dx, [eth_nic_base]
add dx, D8390_P0_BOUND
dec al
out dx, al
 
nsp_exit:
ret
 
 
 
;***************************************************************************
; Function
; rtl8029_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
;
;***************************************************************************
rtl8029_transmit:
mov [eth_type], bx
 
pusha
 
mov esi, edi
xor bx, bx
mov bh, [eth_tx_start]
mov ecx, ETH_ALEN
call eth_pio_write
 
mov esi, node_addr
xor bx, bx
mov bh, [eth_tx_start]
add bx, ETH_ALEN
mov ecx, ETH_ALEN
call eth_pio_write
 
mov esi, eth_type
xor bx, bx
mov bh, [eth_tx_start]
add bx, ETH_ALEN
add bx, ETH_ALEN
mov ecx, 2
call eth_pio_write
 
popa
 
xor bx, bx
mov bh, [eth_tx_start]
add bx, ETH_HLEN
push ecx
call eth_pio_write
pop ecx
 
add ecx, ETH_HLEN
cmp ecx, ETH_ZLEN
jae nst_001
 
mov ecx, ETH_ZLEN
 
nst_001:
push ecx
 
mov bx, [eth_nic_base]
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_PS0_RD2_STA
out dx, al
 
mov dx, bx
add dx, D8390_P0_TPSR
mov al, [eth_tx_start]
out dx, al
 
pop ecx
 
mov dx, bx
add dx, D8390_P0_TBCR0
mov al, cl
out dx, al
 
mov dx, bx
add dx, D8390_P0_TBCR1
mov al, ch
out dx, al
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_PS0_TXP_RD2_STA
out dx, al
 
ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/rtl8139.inc
0,0 → 1,624
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; RTL8139.INC ;;
;; ;;
;; Ethernet driver for Menuet OS ;;
;; ;;
;; Version 0.2 11 August 2003 ;;
;; ;;
;; Driver for chips of RealTek 8139 family ;;
;; References: ;;
;; www.realtek.com.hw - data sheets ;;
;; rtl8139.c - linux driver ;;
;; 8139too.c - linux driver ;;
;; ethernet driver template by Mike Hibbett ;;
;; ;;
;; The copyright statement is ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; Copyright 2003 Endre Kozma, ;;
;; endre.kozma@axelero.hu ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;; 10.01.2007 Bugfix for l8139_transmit from Paolo Franchetti ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
ETH_ALEN equ 6
ETH_HLEN equ (2 * ETH_ALEN + 2)
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for
; mininmum 64bytes frame length
 
PCI_REG_COMMAND equ 0x04 ; command register
PCI_BIT_PIO equ 0 ; bit0: io space control
PCI_BIT_MMIO equ 1 ; bit1: memory space control
PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master
 
RTL8139_REG_MAR0 equ 0x08 ; multicast filter register 0
RTL8139_REG_MAR4 equ 0x0c ; multicast filter register 4
RTL8139_REG_TSD0 equ 0x10 ; transmit status of descriptor
RTL8139_REG_TSAD0 equ 0x20 ; transmit start address of descriptor
RTL8139_REG_RBSTART equ 0x30 ; RxBuffer start address
RTL8139_REG_COMMAND equ 0x37 ; command register
RTL8139_REG_CAPR equ 0x38 ; current address of packet read
RTL8139_REG_IMR equ 0x3c ; interrupt mask register
RTL8139_REG_ISR equ 0x3e ; interrupt status register
RTL8139_REG_TXCONFIG equ 0x40 ; transmit configuration register
RTL8139_REG_TXCONFIG_0 equ 0x40 ; transmit configuration register 0
RTL8139_REG_TXCONFIG_1 equ 0x41 ; transmit configuration register 1
RTL8139_REG_TXCONFIG_2 equ 0x42 ; transmit configuration register 2
RTL8139_REG_TXCONFIG_3 equ 0x43 ; transmit configuration register 3
RTL8139_REG_RXCONFIG equ 0x44 ; receive configuration register 0
RTL8139_REG_RXCONFIG_0 equ 0x44 ; receive configuration register 0
RTL8139_REG_RXCONFIG_1 equ 0x45 ; receive configuration register 1
RTL8139_REG_RXCONFIG_2 equ 0x46 ; receive configuration register 2
RTL8139_REG_RXCONFIG_3 equ 0x47 ; receive configuration register 3
RTL8139_REG_MPC equ 0x4c ; missed packet counter
RTL8139_REG_9346CR equ 0x50 ; serial eeprom 93C46 command register
RTL8139_REG_CONFIG1 equ 0x52 ; configuration register 1
RTL8139_REG_CONFIG4 equ 0x5a ; configuration register 4
RTL8139_REG_HLTCLK equ 0x5b ; undocumented halt clock register
RTL8139_REG_BMCR equ 0x62 ; basic mode control register
RTL8139_REG_ANAR equ 0x66 ; auto negotiation advertisement register
 
; 5.1 packet header
RTL8139_BIT_RUNT equ 4 ; total packet length < 64 bytes
RTL8139_BIT_LONG equ 3 ; total packet length > 4k
RTL8139_BIT_CRC equ 2 ; crc error occured
RTL8139_BIT_FAE equ 1 ; frame alignment error occured
RTL8139_BIT_ROK equ 0 ; received packet is ok
; 5.4 command register
RTL8139_BIT_RST equ 4 ; reset bit
RTL8139_BIT_RE equ 3 ; receiver enabled
RTL8139_BIT_TE equ 2 ; transmitter enabled
RTL8139_BIT_BUFE equ 0 ; rx buffer is empty, no packet stored
; 5.6 interrupt status register
RTL8139_BIT_ISR_TOK equ 2 ; transmit ok
RTL8139_BIT_ISR_RER equ 1 ; receive error interrupt
RTL8139_BIT_ISR_ROK equ 0 ; receive ok
; 5.7 transmit configyration register
RTL8139_BIT_TX_MXDMA equ 8 ; Max DMA burst size per Tx DMA burst
RTL8139_BIT_TXRR equ 4 ; Tx Retry count 16+(TXRR*16)
; 5.8 receive configuration register
RTL8139_BIT_RXFTH equ 13 ; Rx fifo threshold
RTL8139_BIT_RBLEN equ 11 ; Ring buffer length indicator
RTL8139_BIT_RX_MXDMA equ 8 ; Max DMA burst size per Rx DMA burst
RTL8139_BIT_NOWRAP equ 7 ; transfered data wrapping
RTL8139_BIT_9356SEL equ 6 ; eeprom selector 9346/9356
RTL8139_BIT_AER equ 5 ; accept error packets
RTL8139_BIT_AR equ 4 ; accept runt packets
RTL8139_BIT_AB equ 3 ; accept broadcast packets
RTL8139_BIT_AM equ 2 ; accept multicast packets
RTL8139_BIT_APM equ 1 ; accept physical match packets
RTL8139_BIT_AAP equ 0 ; accept all packets
; 5.9 93C46/93C56 command register
RTL8139_BIT_93C46_EEM1 equ 7 ; RTL8139 eeprom operating mode1
RTL8139_BIT_93C46_EEM0 equ 6 ; RTL8139 eeprom operating mode0
RTL8139_BIT_93C46_EECS equ 3 ; chip select
RTL8139_BIT_93C46_EESK equ 2 ; serial data clock
RTL8139_BIT_93C46_EEDI equ 1 ; serial data input
RTL8139_BIT_93C46_EEDO equ 0 ; serial data output
; 5.11 configuration register 1
RTL8139_BIT_LWACT equ 4 ; see RTL8139_REG_CONFIG1
RTL8139_BIT_SLEEP equ 1 ; sleep bit at older chips
RTL8139_BIT_PWRDWN equ 0 ; power down bit at older chips
RTL8139_BIT_PMEn equ 0 ; power management enabled
; 5.14 configuration register 4
RTL8139_BIT_LWPTN equ 2 ; see RTL8139_REG_CONFIG4
; 6.2 transmit status register
RTL8139_BIT_ERTXTH equ 16 ; early TX threshold
RTL8139_BIT_TOK equ 15 ; transmit ok
RTL8139_BIT_OWN equ 13 ; tx DMA operation is completed
; 6.18 basic mode control register
RTL8139_BIT_ANE equ 12 ; auto negotiation enable
; 6.20 auto negotiation advertisement register
RTL8139_BIT_TXFD equ 8 ; 100base-T full duplex
RTL8139_BIT_TX equ 7 ; 100base-T
RTL8139_BIT_10FD equ 6 ; 10base-T full duplex
RTL8139_BIT_10 equ 5 ; 10base-T
RTL8139_BIT_SELECTOR equ 0 ; binary encoded selector CSMA/CD=00001
; RX/TX buffer size
RTL8139_RBLEN equ 0 ; 0==8K 1==16k 2==32k 3==64k
RTL8139_RX_BUFFER_SIZE equ (8192 shl RTL8139_RBLEN)
MAX_ETH_FRAME_SIZE equ 1516 ; exactly 1514 wthout CRC
RTL8139_NUM_TX_DESC equ 4
RTL8139_TX_BUFFER_SIZE equ (MAX_ETH_FRAME_SIZE * RTL8139_NUM_TX_DESC)
RTL8139_TXRR equ 8 ; total retries = 16+(TXRR*16)
RTL8139_TX_MXDMA equ 6 ; 0==16 1==32 2==64 3==128
; 4==256 5==512 6==1024 7==2048
RTL8139_ERTXTH equ 8 ; in unit of 32 bytes e.g:(8*32)=256
RTL8139_RX_MXDMA equ 7 ; 0==16 1==32 2==64 3==128
; 4==256 5==512 6==1024 7==unlimited
RTL8139_RXFTH equ 7 ; 0==16 1==32 2==64 3==128
; 4==256 5==512 6==1024 7==no threshold
RTL8139_RX_CONFIG equ ((RTL8139_RBLEN shl RTL8139_BIT_RBLEN) \
or (RTL8139_RX_MXDMA shl RTL8139_BIT_RX_MXDMA) \
or (1 shl RTL8139_BIT_NOWRAP) \
or (RTL8139_RXFTH shl RTL8139_BIT_RXFTH) \
or (1 shl RTL8139_BIT_AB) or (1 shl RTL8139_BIT_APM) \
or (1 shl RTL8139_BIT_AER) or (1 shl RTL8139_BIT_AR) \
or (1 shl RTL8139_BIT_AM))
RTL8139_TX_TIMEOUT equ 30 ; 300 milliseconds timeout
 
EE_93C46_REG_ETH_ID equ 7 ; MAC offset
EE_93C46_READ_CMD equ (6 shl 6) ; 110b + 6bit address
EE_93C56_READ_CMD equ (6 shl 8) ; 110b + 8bit address
EE_93C46_CMD_LENGTH equ 9 ; start bit + cmd + 6bit address
EE_93C56_CMD_LENGTH equ 11 ; start bit + cmd + 8bit ddress
 
VER_RTL8139 equ 1100000b
VER_RTL8139A equ 1110000b
; VER_RTL8139AG equ 1110100b
VER_RTL8139B equ 1111000b
VER_RTL8130 equ VER_RTL8139B
VER_RTL8139C equ 1110100b
VER_RTL8100 equ 1111010b
VER_RTL8100B equ 1110101b
VER_RTL8139D equ VER_RTL8100B
VER_RTL8139CP equ 1110110b
VER_RTL8101 equ 1110111b
 
IDX_RTL8139 equ 0
IDX_RTL8139A equ 1
IDX_RTL8139B equ 2
IDX_RTL8139C equ 3
IDX_RTL8100 equ 4
IDX_RTL8139D equ 5
IDX_RTL8139D equ 6
IDX_RTL8101 equ 7
 
 
; These two must be 4 byte aligned ( which they are )
rtl8139_rx_buff equ eth_data_start
rtl8139_tx_buff equ rtl8139_rx_buff + (RTL8139_RX_BUFFER_SIZE + MAX_ETH_FRAME_SIZE)
 
uglobal
align 4
rtl8139_rx_buff_offset:
dd 0
curr_tx_desc dd 0
endg
 
iglobal
hw_ver_array:
db VER_RTL8139, VER_RTL8139A, VER_RTL8139B, VER_RTL8139C
db VER_RTL8100, VER_RTL8139D, VER_RTL8139CP, VER_RTL8101
HW_VER_ARRAY_SIZE = $-hw_ver_array
endg
 
uglobal
hw_ver_id:
db 0
endg
 
;***************************************************************************
; Function
; rtl8139_probe
; Description
; Searches for an ethernet card, enables it and clears the rx buffer
; If a card was found, it enables the ethernet -> TCPIP link
; Destroyed registers
; eax, ebx, ecx, edx
;
;***************************************************************************
rtl8139_probe:
; enable the device
mov al, 2
mov ah, [pci_bus]
mov bh, [pci_dev]
mov bl, PCI_REG_COMMAND
call pci_read_reg
mov cx, ax
or cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO)
and cl, not (1 shl PCI_BIT_MMIO)
mov al, 2
mov ah, [pci_bus]
mov bh, [pci_dev]
mov bl, PCI_REG_COMMAND
call pci_write_reg
; get chip version
mov edx, [io_addr]
add edx, RTL8139_REG_TXCONFIG_2
in ax, dx
shr ah, 2
shr ax, 6
and al, 01111111b
mov ecx, HW_VER_ARRAY_SIZE-1
.chip_ver_loop:
cmp al, [hw_ver_array+ecx]
je .chip_ver_found
dec ecx
jns .chip_ver_loop
xor cl, cl ; default RTL8139
.chip_ver_found:
mov [hw_ver_id], cl
; wake up the chip
mov edx, [io_addr]
add edx, RTL8139_REG_HLTCLK
mov al, 'R' ; run the clock
out dx, al
; unlock config and BMCR registers
add edx, RTL8139_REG_9346CR - RTL8139_REG_HLTCLK
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0)
out dx, al
; enable power management
add edx, RTL8139_REG_CONFIG1 - RTL8139_REG_9346CR
in al, dx
cmp byte [hw_ver_id], IDX_RTL8139B
jl .old_chip
; set LWAKE pin to active high (default value).
; it is for Wake-On-LAN functionality of some motherboards.
; this signal is used to inform the motherboard to execute a wake-up process.
; only at newer chips.
or al, (1 shl RTL8139_BIT_PMEn)
and al, not (1 shl RTL8139_BIT_LWACT)
out dx, al
add edx, RTL8139_REG_CONFIG4 - RTL8139_REG_CONFIG1
in al, dx
and al, not (1 shl RTL8139_BIT_LWPTN)
out dx, al
jmp .finish_wake_up
.old_chip:
; wake up older chips
and al, not ((1 shl RTL8139_BIT_SLEEP) or (1 shl RTL8139_BIT_PWRDWN))
out dx, al
.finish_wake_up:
; lock config and BMCR registers
xor al, al
mov edx, [io_addr]
add edx, RTL8139_REG_9346CR
out dx, al
;***************************************************************************
; Function
; rt8139_reset
; Description
; Place the chip (ie, the ethernet card) into a virgin state
; Destroyed registers
; eax, ebx, ecx, edx
;
;***************************************************************************
rtl8139_reset:
mov edx, [io_addr]
add edx, RTL8139_REG_COMMAND
mov al, 1 shl RTL8139_BIT_RST
out dx, al
mov cx, 1000 ; wait no longer for the reset
.wait_for_reset:
in al, dx
test al, 1 shl RTL8139_BIT_RST
jz .reset_completed ; RST remains 1 during reset
dec cx
jns .wait_for_reset
.reset_completed:
; get MAC (hardware address)
mov ecx, 2
.mac_read_loop:
lea eax, [EE_93C46_REG_ETH_ID+ecx]
push ecx
call rtl8139_read_eeprom
pop ecx
mov [node_addr+ecx*2], ax
dec ecx
jns .mac_read_loop
; unlock config and BMCR registers
mov edx, [io_addr]
add edx, RTL8139_REG_9346CR
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0)
out dx, al
; initialize multicast registers (no filtering)
mov eax, 0xffffffff
add edx, RTL8139_REG_MAR0 - RTL8139_REG_9346CR
out dx, eax
add edx, RTL8139_REG_MAR4 - RTL8139_REG_MAR0
out dx, eax
; enable Rx/Tx
mov al, (1 shl RTL8139_BIT_RE) or (1 shl RTL8139_BIT_TE)
add edx, RTL8139_REG_COMMAND - RTL8139_REG_MAR4
out dx, al
; 32k Rxbuffer, unlimited dma burst, no wrapping, no rx threshold
; accept broadcast packets, accept physical match packets
mov eax, RTL8139_RX_CONFIG
add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND
out dx, eax
; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144
mov eax, (RTL8139_TX_MXDMA shl RTL8139_BIT_TX_MXDMA) \
or (RTL8139_TXRR shl RTL8139_BIT_TXRR)
add edx, RTL8139_REG_TXCONFIG - RTL8139_REG_RXCONFIG
out dx, eax
; enable auto negotiation
add edx, RTL8139_REG_BMCR - RTL8139_REG_TXCONFIG
in ax, dx
or ax, (1 shl RTL8139_BIT_ANE)
out dx, ax
; set auto negotiation advertisement
add edx, RTL8139_REG_ANAR - RTL8139_REG_BMCR
in ax, dx
or ax, (1 shl RTL8139_BIT_SELECTOR) or (1 shl RTL8139_BIT_10) \
or (1 shl RTL8139_BIT_10FD) or (1 shl RTL8139_BIT_TX) \
or (1 shl RTL8139_BIT_TXFD)
out dx, ax
; lock config and BMCR registers
xor eax, eax
add edx, RTL8139_REG_9346CR - RTL8139_REG_ANAR
out dx, al
; init RX/TX pointers
mov [rtl8139_rx_buff_offset], eax
mov [curr_tx_desc], eax
; clear missing packet counter
add edx, RTL8139_REG_MPC - RTL8139_REG_9346CR
out dx, eax
; disable all interrupts
add edx, RTL8139_REG_IMR - RTL8139_REG_MPC
out dx, ax
; set RxBuffer address, init RX buffer offset, init TX ring
mov eax, rtl8139_rx_buff ; simba
sub eax, OS_BASE
add edx, RTL8139_REG_RBSTART - RTL8139_REG_IMR
out dx, eax
; Indicate that we have successfully reset the card
mov eax, [pci_data]
mov [eth_status], eax
ret
 
;***************************************************************************
; Function
; rtl8139_read_eeprom
; Description
; reads eeprom type 93c46 and 93c56
; Parameters
; al - word to be read (6bit in case of 93c46 and 8bit otherwise)
; Return value
; ax - word read in
; Destroyed register(s)
; eax, cx, ebx, edx
;
;***************************************************************************
rtl8139_read_eeprom:
movzx ebx, al
mov edx, [io_addr]
add edx, RTL8139_REG_RXCONFIG
in al, dx
test al, (1 shl RTL8139_BIT_9356SEL)
jz .type_93c46
; and bl, 01111111b ; don't care first bit
or bx, EE_93C56_READ_CMD ; it contains start bit
mov cx, EE_93C56_CMD_LENGTH-1 ; cmd_loop counter
jmp .read_eeprom
.type_93c46:
and bl, 00111111b
or bx, EE_93C46_READ_CMD ; it contains start bit
mov cx, EE_93C46_CMD_LENGTH-1 ; cmd_loop counter
.read_eeprom:
add edx, RTL8139_REG_9346CR - RTL8139_REG_RXCONFIG_0
; mov al, (1 shl RTL8139_BIT_93C46_EEM1)
; out dx, al
mov al, (1 shl RTL8139_BIT_93C46_EEM1) \
or (1 shl RTL8139_BIT_93C46_EECS) ; wake up the eeprom
out dx, al
.cmd_loop:
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS)
bt bx, cx
jnc .zero_bit
or al, (1 shl RTL8139_BIT_93C46_EEDI)
.zero_bit:
out dx, al
; push eax
; in eax, dx ; eeprom delay
; pop eax
or al, (1 shl RTL8139_BIT_93C46_EESK)
out dx, al
; in eax, dx ; eeprom delay
dec cx
jns .cmd_loop
; in eax, dx ; eeprom delay
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS)
out dx, al
mov cl, 0xf
.read_loop:
shl ebx, 1
mov al, (1 shl RTL8139_BIT_93C46_EEM1) \
or (1 shl RTL8139_BIT_93C46_EECS) \
or (1 shl RTL8139_BIT_93C46_EESK)
out dx, al
; in eax, dx ; eeprom delay
in al, dx
and al, (1 shl RTL8139_BIT_93C46_EEDO)
jz .dont_set
inc ebx
.dont_set:
mov al, (1 shl RTL8139_BIT_93C46_EEM1) \
or (1 shl RTL8139_BIT_93C46_EECS)
out dx, al
; in eax, dx ; eeprom delay
dec cl
jns .read_loop
xor al, al
out dx, al
mov ax, bx
ret
 
;***************************************************************************
; Function
; rtl8139_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
; Destroyed registers
; eax, edx, esi, edi
; ToDo
; for waiting of timeout the rtl8139 internal timer
; should be used
;
;***************************************************************************
rtl8139_transmit:
cmp ecx, MAX_ETH_FRAME_SIZE
jg .finish ; packet is too long
push ecx
; check descriptor
mov ecx, [curr_tx_desc]
mov edx, [io_addr]
lea edx, [edx+ecx*4+RTL8139_REG_TSD0]
push edx ebx
in ax, dx
test ax, 0x1fff ; or no size given
jz .send_packet
and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN)
cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN)
jz .send_packet
; wait for timeout
mov ebx, RTL8139_TX_TIMEOUT
mov eax, 0x5 ; delay x/100 secs
int 0x40
in ax, dx
and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN)
cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN)
jz .send_packet
; chip hung, reset it
call rtl8139_reset
; reset the card
.send_packet:
; calculate tx_buffer address
pop ebx
push esi
mov eax, MAX_ETH_FRAME_SIZE
mul dword [curr_tx_desc]
mov esi, edi
lea edi, [rtl8139_tx_buff+eax]
mov eax, edi
cld
; copy destination address
movsd
movsw
; copy source address
mov esi, node_addr
movsd
movsw
; copy packet type
mov [edi], bx
add edi, 2
; copy the packet data
pop esi edx ecx
push ecx
shr ecx, 2
rep movsd
pop ecx
push ecx
and ecx, 3
rep movsb
; set address
sub eax, OS_BASE
add edx, RTL8139_REG_TSAD0 - RTL8139_REG_TSD0
out dx, eax
; set size and early threshold
pop eax ; pick up the size
add eax, ETH_HLEN
cmp eax, ETH_ZLEN
jnc .no_pad
mov eax, ETH_ZLEN
.no_pad:
or eax, (RTL8139_ERTXTH shl RTL8139_BIT_ERTXTH)
add edx, RTL8139_REG_TSD0 - RTL8139_REG_TSAD0
out dx, eax
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
inc dword [curr_tx_desc]
and dword [curr_tx_desc], 3
.finish:
ret
 
;***************************************************************************
; Function
; rtl8139_poll
;
; Description
; Polls the ethernet card for a received packet
; Received data, if any, ends up in Ether_buffer
; Destroyed register(s)
; eax, edx, ecx
;
;***************************************************************************
rtl8139_poll:
mov word [eth_rx_data_len], 0
mov edx, [io_addr]
add edx, RTL8139_REG_COMMAND
in al, dx
test al, (1 shl RTL8139_BIT_BUFE)
jnz .finish
; new packet received copy it from rx_buffer into Ether_buffer
mov eax, rtl8139_rx_buff
add eax, [rtl8139_rx_buff_offset]
; check if packet is ok
test byte [eax], (1 shl RTL8139_BIT_ROK)
jz .reset_rx
; packet is ok copy it into the Ether_buffer
movzx ecx, word [eax+2] ; packet length
sub ecx, 4 ; don't copy CRC
mov word [eth_rx_data_len], cx
push ecx
shr ecx, 2 ; first copy dword-wise
lea esi, [eax+4] ; don't copy the packet header
mov edi, Ether_buffer
cld
rep movsd ; copy the dwords
pop ecx
and ecx, 3
rep movsb ; copy the rest bytes
; update rtl8139_rx_buff_offset
movzx eax, word [eax+2] ; packet length
add eax, [rtl8139_rx_buff_offset]
add eax, 4+3 ; packet header is 4 bytes long + dword alignment
and eax, not 3 ; dword alignment
cmp eax, RTL8139_RX_BUFFER_SIZE
jl .no_wrap
sub eax, RTL8139_RX_BUFFER_SIZE
.no_wrap:
mov [rtl8139_rx_buff_offset], eax
; update CAPR register
sub eax, 0x10 ; value 0x10 is a constant for CAPR
add edx, RTL8139_REG_CAPR - RTL8139_REG_COMMAND
out dx, ax
.finish:
; clear active interrupt sources
mov edx, [io_addr]
add edx, RTL8139_REG_ISR
in ax, dx
out dx, ax
ret
.reset_rx:
in al, dx ; read command register
push eax
and al, not (1 shl RTL8139_BIT_RE)
out dx, al
pop eax
out dx, al
add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND
mov ax, RTL8139_RX_CONFIG
out dx, ax
ret
 
rtl8139_cable:
pusha
mov edx, [io_addr]
add edx, 0x58
in al, dx
test al, 1 SHL 2
jnz .notconnected
popa
xor al, al
inc al
ret
.notconnected:
popa
xor al, al
ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/rtl8169.inc
0,0 → 1,1239
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; RTL8169.INC ;;
;; ;;
;; Ethernet driver for Menuet OS ;;
;; ;;
;; Version 0.1 11 February 2007 ;;
;; ;;
;; Driver for chips of RealTek 8169 family ;;
;; References: ;;
;; r8169.c - linux driver (etherboot project) ;;
;; ethernet driver template by Mike Hibbett ;;
;; ;;
;; The copyright statement is ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; Copyright 2007 mike.dld, ;;
;; mike.dld@gmail.com ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
ETH_ALEN equ 6
ETH_HLEN equ (2 * ETH_ALEN + 2)
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for
; mininmum 64bytes frame length
 
RTL8169_REG_MAC0 equ 0x0 ; Ethernet hardware address
RTL8169_REG_MAR0 equ 0x8 ; Multicast filter
RTL8169_REG_TxDescStartAddr equ 0x20
RTL8169_REG_TxHDescStartAddr equ 0x28
RTL8169_REG_FLASH equ 0x30
RTL8169_REG_ERSR equ 0x36
RTL8169_REG_ChipCmd equ 0x37
RTL8169_REG_TxPoll equ 0x38
RTL8169_REG_IntrMask equ 0x3C
RTL8169_REG_IntrStatus equ 0x3E
RTL8169_REG_TxConfig equ 0x40
RTL8169_REG_RxConfig equ 0x44
RTL8169_REG_RxMissed equ 0x4C
RTL8169_REG_Cfg9346 equ 0x50
RTL8169_REG_Config0 equ 0x51
RTL8169_REG_Config1 equ 0x52
RTL8169_REG_Config2 equ 0x53
RTL8169_REG_Config3 equ 0x54
RTL8169_REG_Config4 equ 0x55
RTL8169_REG_Config5 equ 0x56
RTL8169_REG_MultiIntr equ 0x5C
RTL8169_REG_PHYAR equ 0x60
RTL8169_REG_TBICSR equ 0x64
RTL8169_REG_TBI_ANAR equ 0x68
RTL8169_REG_TBI_LPAR equ 0x6A
RTL8169_REG_PHYstatus equ 0x6C
RTL8169_REG_RxMaxSize equ 0xDA
RTL8169_REG_CPlusCmd equ 0xE0
RTL8169_REG_RxDescStartAddr equ 0xE4
RTL8169_REG_ETThReg equ 0xEC
RTL8169_REG_FuncEvent equ 0xF0
RTL8169_REG_FuncEventMask equ 0xF4
RTL8169_REG_FuncPresetState equ 0xF8
RTL8169_REG_FuncForceEvent equ 0xFC
 
; InterruptStatusBits
RTL8169_ISB_SYSErr equ 0x8000
RTL8169_ISB_PCSTimeout equ 0x4000
RTL8169_ISB_SWInt equ 0x0100
RTL8169_ISB_TxDescUnavail equ 0x80
RTL8169_ISB_RxFIFOOver equ 0x40
RTL8169_ISB_LinkChg equ 0x20
RTL8169_ISB_RxOverflow equ 0x10
RTL8169_ISB_TxErr equ 0x08
RTL8169_ISB_TxOK equ 0x04
RTL8169_ISB_RxErr equ 0x02
RTL8169_ISB_RxOK equ 0x01
 
; RxStatusDesc
RTL8169_SD_RxRES equ 0x00200000
RTL8169_SD_RxCRC equ 0x00080000
RTL8169_SD_RxRUNT equ 0x00100000
RTL8169_SD_RxRWT equ 0x00400000
 
; ChipCmdBits
RTL8169_CMD_Reset equ 0x10
RTL8169_CMD_RxEnb equ 0x08
RTL8169_CMD_TxEnb equ 0x04
RTL8169_CMD_RxBufEmpty equ 0x01
 
; Cfg9346Bits
RTL8169_CFG_9346_Lock equ 0x00
RTL8169_CFG_9346_Unlock equ 0xC0
 
; rx_mode_bits
RTL8169_RXM_AcceptErr equ 0x20
RTL8169_RXM_AcceptRunt equ 0x10
RTL8169_RXM_AcceptBroadcast equ 0x08
RTL8169_RXM_AcceptMulticast equ 0x04
RTL8169_RXM_AcceptMyPhys equ 0x02
RTL8169_RXM_AcceptAllPhys equ 0x01
 
; RxConfigBits
RTL8169_RXC_FIFOShift equ 13
RTL8169_RXC_DMAShift equ 8
 
; TxConfigBits
RTL8169_TXC_InterFrameGapShift equ 24
RTL8169_TXC_DMAShift equ 8 ; DMA burst value (0-7) is shift this many bits
 
; rtl8169_PHYstatus
RTL8169_PHYS_TBI_Enable equ 0x80
RTL8169_PHYS_TxFlowCtrl equ 0x40
RTL8169_PHYS_RxFlowCtrl equ 0x20
RTL8169_PHYS_1000bpsF equ 0x10
RTL8169_PHYS_100bps equ 0x08
RTL8169_PHYS_10bps equ 0x04
RTL8169_PHYS_LinkStatus equ 0x02
RTL8169_PHYS_FullDup equ 0x01
 
; GIGABIT_PHY_registers
RTL8169_PHY_CTRL_REG equ 0
RTL8169_PHY_STAT_REG equ 1
RTL8169_PHY_AUTO_NEGO_REG equ 4
RTL8169_PHY_1000_CTRL_REG equ 9
 
; GIGABIT_PHY_REG_BIT
RTL8169_PHY_Restart_Auto_Nego equ 0x0200
RTL8169_PHY_Enable_Auto_Nego equ 0x1000
 
; PHY_STAT_REG = 1;
RTL8169_PHY_Auto_Neco_Comp equ 0x0020
 
; PHY_AUTO_NEGO_REG = 4;
RTL8169_PHY_Cap_10_Half equ 0x0020
RTL8169_PHY_Cap_10_Full equ 0x0040
RTL8169_PHY_Cap_100_Half equ 0x0080
RTL8169_PHY_Cap_100_Full equ 0x0100
 
; PHY_1000_CTRL_REG = 9;
RTL8169_PHY_Cap_1000_Full equ 0x0200
RTL8169_PHY_Cap_1000_Half equ 0x0100
 
RTL8169_PHY_Cap_PAUSE equ 0x0400
RTL8169_PHY_Cap_ASYM_PAUSE equ 0x0800
 
RTL8169_PHY_Cap_Null equ 0x0
 
; _MediaType
RTL8169_MT_10_Half equ 0x01
RTL8169_MT_10_Full equ 0x02
RTL8169_MT_100_Half equ 0x04
RTL8169_MT_100_Full equ 0x08
RTL8169_MT_1000_Full equ 0x10
 
; _TBICSRBit
RTL8169_TBI_LinkOK equ 0x02000000
 
; _DescStatusBit
RTL8169_DSB_OWNbit equ 0x80000000
RTL8169_DSB_EORbit equ 0x40000000
RTL8169_DSB_FSbit equ 0x20000000
RTL8169_DSB_LSbit equ 0x10000000
 
; MAC address length
MAC_ADDR_LEN equ 6
 
; max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4)
MAX_ETH_FRAME_SIZE equ 1536
 
TX_FIFO_THRESH equ 256 ; In bytes
 
RX_FIFO_THRESH equ 7 ; 7 means NO threshold, Rx buffer level before first PCI xfer
RX_DMA_BURST equ 7 ; Maximum PCI burst, '6' is 1024
TX_DMA_BURST equ 7 ; Maximum PCI burst, '6' is 1024
ETTh equ 0x3F ; 0x3F means NO threshold
 
EarlyTxThld equ 0x3F ; 0x3F means NO early transmit
RxPacketMaxSize equ 0x0800 ; Maximum size supported is 16K-1
InterFrameGap equ 0x03 ; 3 means InterFrameGap = the shortest one
 
NUM_TX_DESC equ 1 ; Number of Tx descriptor registers
NUM_RX_DESC equ 4 ; Number of Rx descriptor registers
RX_BUF_SIZE equ 1536 ; Rx Buffer size
 
HZ equ 1000
 
RTL_MIN_IO_SIZE equ 0x80
TX_TIMEOUT equ (6*HZ)
 
RTL8169_TIMER_EXPIRE_TIME equ 100
 
ETH_HDR_LEN equ 14
DEFAULT_MTU equ 1500
DEFAULT_RX_BUF_LEN equ 1536
 
 
;#ifdef RTL8169_JUMBO_FRAME_SUPPORT
;#define MAX_JUMBO_FRAME_MTU ( 10000 )
;#define MAX_RX_SKBDATA_SIZE ( MAX_JUMBO_FRAME_MTU + ETH_HDR_LEN )
;#else
MAX_RX_SKBDATA_SIZE equ 1600
;#endif //end #ifdef RTL8169_JUMBO_FRAME_SUPPORT
 
;#ifdef RTL8169_USE_IO
;!!!#define RTL_W8(reg, val8) outb ((val8), ioaddr + (reg))
macro RTL_W8 reg,val8 {
if ~reg eq dx
mov dx, word[rtl8169_tpc.mmio_addr]
add dx, reg
end if
if ~val8 eq al
mov al, val8
end if
out dx, al
}
;!!!#define RTL_W16(reg, val16) outw ((val16), ioaddr + (reg))
macro RTL_W16 reg,val16 {
if ~reg eq dx
mov dx, word[rtl8169_tpc.mmio_addr]
add dx, reg
end if
if ~val16 eq ax
mov ax, val16
end if
out dx, ax
}
;!!!#define RTL_W32(reg, val32) outl ((val32), ioaddr + (reg))
macro RTL_W32 reg,val32 {
if ~reg eq dx
mov dx, word[rtl8169_tpc.mmio_addr]
add dx, reg
end if
if ~val32 eq eax
mov eax, val32
end if
out dx, eax
}
;!!!#define RTL_R8(reg) inb (ioaddr + (reg))
macro RTL_R8 reg {
if ~reg eq dx
mov dx, word[rtl8169_tpc.mmio_addr]
add dx, reg
end if
in al, dx
}
;!!!#define RTL_R16(reg) inw (ioaddr + (reg))
macro RTL_R16 reg {
if ~reg eq dx
mov dx, word[rtl8169_tpc.mmio_addr]
add dx, reg
end if
in ax, dx
}
;!!!#define RTL_R32(reg) ((unsigned long) inl (ioaddr + (reg)))
macro RTL_R32 reg {
if ~reg eq dx
mov dx, word[rtl8169_tpc.mmio_addr]
add dx, reg
end if
in eax, dx
}
;#else
; write/read MMIO register
;#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
;#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
;#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg))
;#define RTL_R8(reg) readb (ioaddr + (reg))
;#define RTL_R16(reg) readw (ioaddr + (reg))
;#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg)))
;#endif
 
MCFG_METHOD_01 equ 0x01
MCFG_METHOD_02 equ 0x02
MCFG_METHOD_03 equ 0x03
MCFG_METHOD_04 equ 0x04
MCFG_METHOD_05 equ 0x05
MCFG_METHOD_11 equ 0x0b
MCFG_METHOD_12 equ 0x0c
MCFG_METHOD_13 equ 0x0d
MCFG_METHOD_14 equ 0x0e
MCFG_METHOD_15 equ 0x0f
 
PCFG_METHOD_1 equ 0x01 ; PHY Reg 0x03 bit0-3 == 0x0000
PCFG_METHOD_2 equ 0x02 ; PHY Reg 0x03 bit0-3 == 0x0001
PCFG_METHOD_3 equ 0x03 ; PHY Reg 0x03 bit0-3 == 0x0002
 
PCI_COMMAND_IO equ 0x1 ; Enable response in I/O space
PCI_COMMAND_MEM equ 0x2 ; Enable response in mem space
PCI_COMMAND_MASTER equ 0x4 ; Enable bus mastering
PCI_LATENCY_TIMER equ 0x0d ; 8 bits
PCI_COMMAND_SPECIAL equ 0x8 ; Enable response to special cycles
PCI_COMMAND_INVALIDATE equ 0x10 ; Use memory write and invalidate
PCI_COMMAND_VGA_PALETTE equ 0x20 ; Enable palette snooping
PCI_COMMAND_PARITY equ 0x40 ; Enable parity checking
PCI_COMMAND_WAIT equ 0x80 ; Enable address/data stepping
PCI_COMMAND_SERR equ 0x100 ; Enable SERR
PCI_COMMAND_FAST_BACK equ 0x200 ; Enable back-to-back writes
 
struc rtl8169_TxDesc {
.status dd ?
.vlan_tag dd ?
.buf_addr dd ?
.buf_Haddr dd ?
}
virtual at 0
rtl8169_TxDesc rtl8169_TxDesc
sizeof.rtl8169_TxDesc = $ - rtl8169_TxDesc
end virtual
 
struc rtl8169_RxDesc {
.status dd ?
.vlan_tag dd ?
.buf_addr dd ?
.buf_Haddr dd ?
}
virtual at 0
rtl8169_RxDesc rtl8169_RxDesc
sizeof.rtl8169_RxDesc = $ - rtl8169_RxDesc
end virtual
 
virtual at eth_data_start
 
; Define the TX Descriptor
align 256
rtl8169_tx_ring rb NUM_TX_DESC * sizeof.rtl8169_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
rtl8169_txb rb NUM_TX_DESC * RX_BUF_SIZE
 
; Define the RX Descriptor
align 256
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
; part of this buffer
align 256
rtl8169_rxb rb NUM_RX_DESC * RX_BUF_SIZE
 
rtl8169_tpc:
.mmio_addr dd ? ; memory map physical address
.chipset dd ?
.pcfg dd ?
.mcfg dd ?
.cur_rx dd ? ; Index into the Rx descriptor buffer of next Rx pkt
.cur_tx dd ? ; Index into the Tx descriptor buffer of next Rx pkt
.TxDescArrays dd ? ; Index of Tx Descriptor buffer
.RxDescArrays dd ? ; Index of Rx Descriptor buffer
.TxDescArray dd ? ; Index of 256-alignment Tx Descriptor buffer
.RxDescArray dd ? ; Index of 256-alignment Rx Descriptor buffer
.RxBufferRing rd NUM_RX_DESC ; Index of Rx Buffer array
.Tx_skbuff rd NUM_TX_DESC
 
end virtual
 
rtl8169_intr_mask = RTL8169_ISB_LinkChg or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxFIFOOver or RTL8169_ISB_TxErr or RTL8169_ISB_TxOK or RTL8169_ISB_RxErr or RTL8169_ISB_RxOK
rtl8169_rx_config = (RX_FIFO_THRESH shl RTL8169_RXC_FIFOShift) or (RX_DMA_BURST shl RTL8169_RXC_DMAShift) or 0x0000000E
 
iglobal
 
;static struct {
; const char *name;
; u8 mcfg; /* depend on RTL8169 docs */
; u32 RxConfigMask; /* should clear the bits supported by this chip */
;}
rtl_chip_info dd \
MCFG_METHOD_01, 0xff7e1880, \ ; RTL8169
MCFG_METHOD_02, 0xff7e1880, \ ; RTL8169s/8110s
MCFG_METHOD_03, 0xff7e1880, \ ; RTL8169s/8110s
MCFG_METHOD_04, 0xff7e1880, \ ; RTL8169sb/8110sb
MCFG_METHOD_05, 0xff7e1880, \ ; RTL8169sc/8110sc
MCFG_METHOD_11, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E
MCFG_METHOD_12, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E
MCFG_METHOD_13, 0xff7e1880, \ ; RTL8101e // PCI-E 8139
MCFG_METHOD_14, 0xff7e1880, \ ; RTL8100e // PCI-E 8139
MCFG_METHOD_15, 0xff7e1880 ; RTL8100e // PCI-E 8139
 
mac_info dd \
0x38800000, MCFG_METHOD_15, \
0x38000000, MCFG_METHOD_12, \
0x34000000, MCFG_METHOD_13, \
0x30800000, MCFG_METHOD_14, \
0x30000000, MCFG_METHOD_11, \
0x18000000, MCFG_METHOD_05, \
0x10000000, MCFG_METHOD_04, \
0x04000000, MCFG_METHOD_03, \
0x00800000, MCFG_METHOD_02, \
0x00000000, MCFG_METHOD_01 ; catch-all
 
endg
 
PCI_COMMAND_IO equ 0x1 ; Enable response in I/O space
PCI_COMMAND_MEM equ 0x2 ; Enable response in mem space
PCI_COMMAND_MASTER equ 0x4 ; Enable bus mastering
PCI_LATENCY_TIMER equ 0x0d ; 8 bits
PCI_COMMAND_SPECIAL equ 0x8 ; Enable response to special cycles
PCI_COMMAND_INVALIDATE equ 0x10 ; Use memory write and invalidate
PCI_COMMAND_VGA_PALETTE equ 0x20 ; Enable palette snooping
PCI_COMMAND_PARITY equ 0x40 ; Enable parity checking
PCI_COMMAND_WAIT equ 0x80 ; Enable address/data stepping
PCI_COMMAND_SERR equ 0x100 ; Enable SERR
PCI_COMMAND_FAST_BACK equ 0x200 ; Enable back-to-back writes
 
PCI_VENDOR_ID equ 0x00 ; 16 bits
PCI_DEVICE_ID equ 0x02 ; 16 bits
PCI_COMMAND equ 0x04 ; 16 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_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
 
PCI_BASE_ADDRESS_IO_MASK equ (not 0x03)
PCI_BASE_ADDRESS_MEM_MASK equ (not 0x0f)
PCI_BASE_ADDRESS_SPACE_IO equ 0x01
PCI_ROM_ADDRESS equ 0x30 ; 32 bits
 
proc CONFIG_CMD,where:byte
movzx eax, byte[pci_bus]
shl eax, 8
mov al, [pci_dev]
shl eax, 8
mov al, [where]
and al, not 3
or eax, 0x80000000
ret
endp
 
proc pci_read_config_byte,where:dword
push edx
stdcall CONFIG_CMD, [where]
mov dx, 0xCF8
out dx, eax
mov edx, [where]
and edx, 3
add edx, 0xCFC
in al, dx
pop edx
ret
endp
 
proc pci_read_config_word,where:dword
push edx
stdcall CONFIG_CMD, [where]
mov dx, 0xCF8
out dx, eax
mov edx, [where]
and edx, 2
add edx, 0xCFC
in ax, dx
pop edx
ret
endp
 
proc pci_read_config_dword,where:dword
push edx
stdcall CONFIG_CMD, [where]
mov edx, 0xCF8
out dx, eax
mov edx, 0xCFC
in eax, dx
pop edx
ret
endp
 
proc pci_write_config_byte,where:dword,value:byte
push edx
stdcall CONFIG_CMD, [where]
mov dx, 0xCF8
out dx, eax
mov edx, [where]
and edx, 3
add edx, 0xCFC
mov al, [value]
out dx, al
pop edx
ret
endp
 
proc pci_write_config_word,where:dword,value:word
push edx
stdcall CONFIG_CMD, [where]
mov dx, 0xCF8
out dx, eax
mov edx, [where]
and edx, 2
add edx, 0xCFC
mov ax, [value]
out dx, ax
pop edx
ret
endp
 
proc pci_write_config_dword,where:dword,value:dword
push edx
stdcall CONFIG_CMD, [where]
mov edx, 0xCF8
out dx, eax
mov edx, 0xCFC
mov eax, [value]
out dx, eax
pop edx
ret
endp
 
; Set device to be a busmaster in case BIOS neglected to do so.
; Also adjust PCI latency timer to a reasonable value, 32.
proc adjust_pci_device
 
; DEBUGF 1,"K : adjust_pci_device\n"
 
stdcall pci_read_config_word, PCI_COMMAND
mov bx, ax
or bx, PCI_COMMAND_MASTER or PCI_COMMAND_IO
cmp ax, bx
je @f
; DEBUGF 1,"K : adjust_pci_device: The PCI BIOS has not enabled this device!\nK : Updating PCI command %x->%x. pci_bus %x pci_device_fn %x\n",ax,bx,[pci_bus]:2,[pci_dev]:2
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
stdcall pci_write_config_byte, PCI_LATENCY_TIMER, 32
@@:
ret
endp
 
; Find the start of a pci resource
proc pci_bar_start,index:dword
stdcall pci_read_config_dword, [index]
test eax, PCI_BASE_ADDRESS_SPACE_IO
jz @f
and eax, PCI_BASE_ADDRESS_IO_MASK
jmp .exit
@@:
push eax
and eax, PCI_BASE_ADDRESS_MEM_TYPE_MASK
cmp eax, PCI_BASE_ADDRESS_MEM_TYPE_64
jne .not64
mov eax, [index]
add eax, 4
stdcall pci_read_config_dword, eax
or eax, eax
jz .not64
; DEBUGF 1,"K : pci_bar_start: Unhandled 64bit BAR\n"
add esp, 4
or eax, -1
ret
.not64:
pop eax
and eax, PCI_BASE_ADDRESS_MEM_MASK
.exit:
ret
endp
 
proc rtl8169_init_board
 
; DEBUGF 1,"K : rtl8169_init_board\n"
 
call adjust_pci_device
 
stdcall pci_bar_start, PCI_BASE_ADDRESS_0
mov [rtl8169_tpc.mmio_addr], eax
; Soft reset the chip
RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_Reset
 
; Check that the chip has finished the reset
mov ecx, 1000
@@:
RTL_R8 RTL8169_REG_ChipCmd
test al, RTL8169_CMD_Reset
jz @f
stdcall udelay, 10
loop @b
@@:
; identify config method
RTL_R32 RTL8169_REG_TxConfig
and eax, 0x7c800000
; DEBUGF 1,"K : rtl8169_init_board: TxConfig & 0x7c800000 = 0x%x\n",eax
mov esi, mac_info-8
@@:
add esi, 8
mov ecx, eax
and ecx, [esi]
cmp ecx, [esi]
jne @b
mov eax, [esi+4]
mov [rtl8169_tpc.mcfg], eax
 
mov [rtl8169_tpc.pcfg], PCFG_METHOD_3
stdcall RTL8169_READ_GMII_REG, 3
and al, 0x0f
or al, al
jnz @f
mov [rtl8169_tpc.pcfg], PCFG_METHOD_1
jmp .pconf
@@:
dec al
jnz .pconf
mov [rtl8169_tpc.pcfg], PCFG_METHOD_2
.pconf:
 
; identify chip attached to board
mov ecx, 10
mov eax, [rtl8169_tpc.mcfg]
@@:
dec ecx
js @f
cmp eax, [rtl_chip_info+ecx*8]
jne @b
mov [rtl8169_tpc.chipset], ecx
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"
RTL_R32 RTL8169_REG_TxConfig
; DEBUGF 1,"K : rtl8169_init_board: PCI device: TxConfig = 0x%x\n",eax
 
mov [rtl8169_tpc.chipset], 0
 
xor eax, eax
inc eax
ret
 
.match:
xor eax, eax
ret
endp
 
proc rtl8169_hw_PHY_config
 
; DEBUGF 1,"K : rtl8169_hw_PHY_config: priv.mcfg=%d, priv.pcfg=%d\n",[rtl8169_tpc.mcfg],[rtl8169_tpc.pcfg]
 
; DBG_PRINT("priv->mcfg=%d, priv->pcfg=%d\n", tpc->mcfg, tpc->pcfg);
 
cmp [rtl8169_tpc.mcfg], MCFG_METHOD_04
jne .not_4
; stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0001
; stdcall RTL8169_WRITE_GMII_REG,0x1b,0x841e
; stdcall RTL8169_WRITE_GMII_REG,0x0e,0x7bfb
; stdcall RTL8169_WRITE_GMII_REG,0x09,0x273a
stdcall RTL8169_WRITE_GMII_REG, 0x1F, 0x0002
stdcall RTL8169_WRITE_GMII_REG, 0x01, 0x90D0
stdcall RTL8169_WRITE_GMII_REG, 0x1F, 0x0000
jmp .exit
.not_4:
cmp [rtl8169_tpc.mcfg], MCFG_METHOD_02
je @f
cmp [rtl8169_tpc.mcfg], MCFG_METHOD_03
jne .not_2_or_3
@@:
stdcall RTL8169_WRITE_GMII_REG, 0x1F, 0x0001
stdcall RTL8169_WRITE_GMII_REG, 0x15, 0x1000
stdcall RTL8169_WRITE_GMII_REG, 0x18, 0x65C7
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x0000
stdcall RTL8169_WRITE_GMII_REG, 0x03, 0x00A1
stdcall RTL8169_WRITE_GMII_REG, 0x02, 0x0008
stdcall RTL8169_WRITE_GMII_REG, 0x01, 0x1020
stdcall RTL8169_WRITE_GMII_REG, 0x00, 0x1000
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x0800
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x0000
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x7000
stdcall RTL8169_WRITE_GMII_REG, 0x03, 0xFF41
stdcall RTL8169_WRITE_GMII_REG, 0x02, 0xDE60
stdcall RTL8169_WRITE_GMII_REG, 0x01, 0x0140
stdcall RTL8169_WRITE_GMII_REG, 0x00, 0x0077
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x7800
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x7000
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xA000
stdcall RTL8169_WRITE_GMII_REG, 0x03, 0xDF01
stdcall RTL8169_WRITE_GMII_REG, 0x02, 0xDF20
stdcall RTL8169_WRITE_GMII_REG, 0x01, 0xFF95
stdcall RTL8169_WRITE_GMII_REG, 0x00, 0xFA00
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xA800
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xA000
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xB000
stdcall RTL8169_WRITE_GMII_REG, 0x03, 0xFF41
stdcall RTL8169_WRITE_GMII_REG, 0x02, 0xDE20
stdcall RTL8169_WRITE_GMII_REG, 0x01, 0x0140
stdcall RTL8169_WRITE_GMII_REG, 0x00, 0x00BB
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xB800
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xB000
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xF000
stdcall RTL8169_WRITE_GMII_REG, 0x03, 0xDF01
stdcall RTL8169_WRITE_GMII_REG, 0x02, 0xDF20
stdcall RTL8169_WRITE_GMII_REG, 0x01, 0xFF95
stdcall RTL8169_WRITE_GMII_REG, 0x00, 0xBF00
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xF800
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xF000
stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x0000
stdcall RTL8169_WRITE_GMII_REG, 0x1F, 0x0000
stdcall RTL8169_WRITE_GMII_REG, 0x0B, 0x0000
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]
.exit:
ret
endp
 
;proc pci_write_config_byte
; ret
;endp
 
proc RTL8169_WRITE_GMII_REG,RegAddr:byte,value:dword
 
;;; DEBUGF 1,"K : RTL8169_WRITE_GMII_REG: 0x%x 0x%x\n",[RegAddr]:2,[value]
 
movzx eax, [RegAddr]
shl eax, 16
or eax, [value]
or eax, 0x80000000
RTL_W32 RTL8169_REG_PHYAR,eax
stdcall udelay, 1 ;;;1000
 
mov ecx, 2000
; Check if the RTL8169 has completed writing to the specified MII register
@@:
RTL_R32 RTL8169_REG_PHYAR
test eax, 0x80000000
jz .exit
stdcall udelay, 1 ;;;100
loop @b
.exit:
ret
endp
 
proc RTL8169_READ_GMII_REG,RegAddr:byte
 
;;; DEBUGF 1,"K : RTL8169_READ_GMII_REG: 0x%x\n",[RegAddr]:2
 
push ecx
movzx eax, [RegAddr]
shl eax, 16
; or eax,0x0
RTL_W32 RTL8169_REG_PHYAR,eax
stdcall udelay, 1 ;;;1000
 
mov ecx, 2000
; Check if the RTL8169 has completed retrieving data from the specified MII register
@@:
RTL_R32 RTL8169_REG_PHYAR
test eax, 0x80000000
jnz .exit
stdcall udelay, 1 ;;;100
loop @b
 
or eax, -1
pop ecx
ret
.exit:
RTL_R32 RTL8169_REG_PHYAR
and eax, 0xFFFF
pop ecx
ret
endp
 
proc rtl8169_set_rx_mode
 
; DEBUGF 1,"K : rtl8169_set_rx_mode\n"
 
; IFF_ALLMULTI
; Too many to filter perfectly -- accept all multicasts
RTL_R32 RTL8169_REG_RxConfig
mov ecx, [rtl8169_tpc.chipset]
and eax, [rtl_chip_info + ecx * 8 + 4]; RxConfigMask
or eax, rtl8169_rx_config or (RTL8169_RXM_AcceptBroadcast or RTL8169_RXM_AcceptMulticast or RTL8169_RXM_AcceptMyPhys)
RTL_W32 RTL8169_REG_RxConfig,eax
 
; Multicast hash filter
RTL_W32 RTL8169_REG_MAR0 + 0,0xffffffff
RTL_W32 RTL8169_REG_MAR0 + 4,0xffffffff
ret
endp
 
proc rtl8169_init_ring
 
; DEBUGF 1,"K : rtl8169_init_ring\n"
 
xor eax, eax
mov [rtl8169_tpc.cur_rx], eax
mov [rtl8169_tpc.cur_tx], eax
 
mov edi, [rtl8169_tpc.TxDescArray]
mov ecx, (NUM_TX_DESC * sizeof.rtl8169_TxDesc) / 4
cld
rep stosd
mov edi, [rtl8169_tpc.RxDescArray]
mov ecx, (NUM_RX_DESC * sizeof.rtl8169_RxDesc) / 4
rep stosd
 
mov edi, rtl8169_tpc.Tx_skbuff
mov eax, rtl8169_txb
mov ecx, NUM_TX_DESC
@@:
stosd
inc eax ; add eax,RX_BUF_SIZE ???
loop @b
 
;!!! for (i = 0; i < NUM_RX_DESC; i++) {
;!!! if (i == (NUM_RX_DESC - 1))
;!!! tpc->RxDescArray[i].status = (OWNbit | EORbit) | RX_BUF_SIZE;
;!!! else
;!!! tpc->RxDescArray[i].status = OWNbit | RX_BUF_SIZE;
;!!! tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE];
;!!! tpc->RxDescArray[i].buf_addr = virt_to_bus(tpc->RxBufferRing[i]);
;!!! }
mov esi, rtl8169_tpc.RxBufferRing
mov edi, [rtl8169_tpc.RxDescArray]
mov eax, rtl8169_rxb
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
add eax, RX_BUF_SIZE
loop @b
 
or [edi - sizeof.rtl8169_RxDesc + rtl8169_RxDesc.status], RTL8169_DSB_EORbit
 
ret
endp
 
proc rtl8169_hw_start
 
; DEBUGF 1,"K : rtl8169_hw_start\n"
 
; Soft reset the chip
RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_Reset
; Check that the chip has finished the reset
mov ecx, 1000
@@:
RTL_R8 RTL8169_REG_ChipCmd
and al, RTL8169_CMD_Reset
jz @f
stdcall udelay, 10
loop @b
@@:
RTL_W8 RTL8169_REG_Cfg9346,RTL8169_CFG_9346_Unlock
RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_TxEnb or RTL8169_CMD_RxEnb
RTL_W8 RTL8169_REG_ETThReg,ETTh
; For gigabit rtl8169
RTL_W16 RTL8169_REG_RxMaxSize,RxPacketMaxSize
; Set Rx Config register
RTL_R32 RTL8169_REG_RxConfig
mov ecx, [rtl8169_tpc.chipset]
and eax, [rtl_chip_info + ecx * 8 + 4]; RxConfigMask
or eax, rtl8169_rx_config
RTL_W32 RTL8169_REG_RxConfig,eax
; Set DMA burst size and Interframe Gap Time
RTL_W32 RTL8169_REG_TxConfig,(TX_DMA_BURST shl RTL8169_TXC_DMAShift) or (InterFrameGap shl RTL8169_TXC_InterFrameGapShift)
RTL_R16 RTL8169_REG_CPlusCmd
RTL_W16 RTL8169_REG_CPlusCmd,ax
 
RTL_R16 RTL8169_REG_CPlusCmd
or ax, 1 shl 3
cmp [rtl8169_tpc.mcfg], MCFG_METHOD_02
jne @f
cmp [rtl8169_tpc.mcfg], MCFG_METHOD_03
jne @f
or ax, 1 shl 14
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14\n"
jmp .set
@@:;DEBUGF 1,"K : Set MAC Reg C+CR Offset 0xE0: bit-3\n"
.set:
RTL_W16 RTL8169_REG_CPlusCmd,ax
 
; RTL_W16 0xE2,0x1517
; RTL_W16 0xE2,0x152a
; RTL_W16 0xE2,0x282a
RTL_W16 0xE2,0x0000
 
MOV [rtl8169_tpc.cur_rx],0
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
call rtl8169_set_rx_mode
; no early-rx interrupts
RTL_R16 RTL8169_REG_MultiIntr
and ax, 0xF000
RTL_W16 RTL8169_REG_MultiIntr,ax
RTL_W16 RTL8169_REG_IntrMask,0 ; rtl8169_intr_mask
ret
endp
 
proc udelay,msec:dword
push esi
mov esi, [msec]
call delay_ms
pop esi
ret
endp
 
;***************************************************************************
; Function
; rtl8169_probe
; Description
; Searches for an ethernet card, enables it and clears the rx buffer
; If a card was found, it enables the ethernet -> TCPIP link
; Destroyed registers
; eax, ebx, ecx, edx
;
;***************************************************************************
proc rtl8169_probe
 
; 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
 
mov ecx, MAC_ADDR_LEN
mov edx, [rtl8169_tpc.mmio_addr]
add edx, RTL8169_REG_MAC0
xor ebx, ebx
; Get MAC address. FIXME: read EEPROM
@@:
RTL_R8 dx
mov [node_addr+ebx], al
inc edx
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
 
; Config PHY
stdcall rtl8169_hw_PHY_config
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n"
RTL_W8 0x82,0x01
cmp [rtl8169_tpc.mcfg], MCFG_METHOD_03
jae @f
; DEBUGF 1,"K : Set PCI Latency=0x40\n"
; stdcall pci_write_config_byte,PCI_LATENCY_TIMER,0x40
@@:
cmp [rtl8169_tpc.mcfg], MCFG_METHOD_02
jne @f
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n"
RTL_W8 0x82,0x01
; DEBUGF 1,"K : Set PHY Reg 0x0bh = 0x00h\n"
stdcall RTL8169_WRITE_GMII_REG, 0x0b, 0x0000 ; w 0x0b 15 0 0
@@:
; if TBI is not enabled
RTL_R8 RTL8169_REG_PHYstatus
test al, RTL8169_PHYS_TBI_Enable
jz .tbi_dis
stdcall RTL8169_READ_GMII_REG, RTL8169_PHY_AUTO_NEGO_REG
; enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged
and eax, 0x0C1F
or eax, RTL8169_PHY_Cap_10_Half or RTL8169_PHY_Cap_10_Full or RTL8169_PHY_Cap_100_Half or RTL8169_PHY_Cap_100_Full
stdcall RTL8169_WRITE_GMII_REG, RTL8169_PHY_AUTO_NEGO_REG, eax
; enable 1000 Full Mode
stdcall RTL8169_WRITE_GMII_REG, RTL8169_PHY_1000_CTRL_REG, RTL8169_PHY_Cap_1000_Full or RTL8169_PHY_Cap_1000_Half; rtl8168
; Enable auto-negotiation and restart auto-nigotiation
stdcall RTL8169_WRITE_GMII_REG, RTL8169_PHY_CTRL_REG, RTL8169_PHY_Enable_Auto_Nego or RTL8169_PHY_Restart_Auto_Nego
stdcall udelay, 100
mov ecx, 10000
; wait for auto-negotiation process
@@:
dec ecx
jz @f
stdcall RTL8169_READ_GMII_REG, RTL8169_PHY_STAT_REG
stdcall udelay, 100
test eax, RTL8169_PHY_Auto_Neco_Comp
jz @b
RTL_R8 RTL8169_REG_PHYstatus
jmp @f
.tbi_dis:
stdcall udelay, 100
@@:
call rtl8169_reset
ret
endp
 
;***************************************************************************
; Function
; rt8169_reset
; Description
; Place the chip (ie, the ethernet card) into a virgin state
; Destroyed registers
; eax, ebx, ecx, edx
;
;***************************************************************************
proc rtl8169_reset
 
; 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
mov [rtl8169_tpc.TxDescArray], rtl8169_tx_ring
 
mov [rtl8169_tpc.RxDescArrays], rtl8169_rx_ring
; Rx Desscriptor needs 256 bytes alignment
mov [rtl8169_tpc.RxDescArray], rtl8169_rx_ring
 
call rtl8169_init_ring
call rtl8169_hw_start
; Construct a perfect filter frame with the mac address as first match
; and broadcast for all others
mov edi, rtl8169_txb
or al, -1
mov ecx, 192
cld
rep stosb
 
mov esi, node_addr
mov edi, rtl8169_txb
movsd
movsw
 
mov eax, [pci_data]
mov [eth_status], eax
ret
endp
 
;***************************************************************************
; Function
; rtl8169_transmit
; Description
; Transmits a packet of data via the ethernet card
; d - edi - Pointer to 48 bit destination address
; t - bx - Type of packet
; s - ecx - size of packet
; p - esi - pointer to packet data
; Destroyed registers
; eax, edx, esi, edi
;
;***************************************************************************
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
 
push ecx edx esi
mov eax, MAX_ETH_FRAME_SIZE
mul [rtl8169_tpc.cur_tx]
mov esi, edi
; point to the current txb incase multiple tx_rings are used
mov edi, [rtl8169_tpc.Tx_skbuff + eax * 4]
mov eax, edi
cld
; copy destination address
movsd
movsw
; copy source address
mov esi, node_addr
movsd
movsw
; copy packet type
mov [edi], bx
add edi, 2
; copy the packet data
pop esi edx ecx
push ecx
shr ecx, 2
rep movsd
pop ecx
push ecx
and ecx, 3
rep movsb
 
;!!! s += ETH_HLEN;
;!!! s &= 0x0FFF;
;!!! while (s < ETH_ZLEN)
;!!! ptxb[s++] = '\0';
mov edi, eax
pop ecx
push eax
add ecx, ETH_HLEN
and ecx, 0x0FFF
xor al, al
add edi, ecx
@@:
cmp ecx, ETH_ZLEN
jae @f
stosb
inc ecx
jmp @b
@@:
pop eax
 
mov ebx, eax
mov eax, sizeof.rtl8169_TxDesc
mul [rtl8169_tpc.cur_tx]
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
jae @f
mov eax, ETH_ZLEN
@@:
or eax, RTL8169_DSB_OWNbit or RTL8169_DSB_FSbit or RTL8169_DSB_LSbit
cmp [rtl8169_tpc.cur_tx], NUM_TX_DESC - 1
jne @f
or eax, RTL8169_DSB_EORbit
@@:
mov [ebx + rtl8169_TxDesc.status], eax
 
RTL_W8 RTL8169_REG_TxPoll,0x40 ; set polling bit
 
inc [rtl8169_tpc.cur_tx]
and [rtl8169_tpc.cur_tx], NUM_TX_DESC - 1
 
;!!! to = currticks() + TX_TIMEOUT;
;!!! while ((tpc->TxDescArray[entry].status & OWNbit) && (currticks() < to)); /* wait */
mov ecx, TX_TIMEOUT / 10
@@:
test [ebx + rtl8169_TxDesc.status], RTL8169_DSB_OWNbit
jnz @f
stdcall udelay, 10
loop @b
; DEBUGF 1,"K : rtl8169_transmit: TX Time Out\n"
@@:
 
ret
endp
 
;***************************************************************************
; Function
; rtl8169_poll
;
; Description
; Polls the ethernet card for a received packet
; Received data, if any, ends up in Ether_buffer
; Destroyed register(s)
; eax, edx, ecx
;
;***************************************************************************
proc rtl8169_poll
 
; DEBUGF 1,"K : rtl8169_poll\n" ;: 0x%x : none\n",[io_addr]:8
 
mov word[eth_rx_data_len], 0
 
mov eax, sizeof.rtl8169_RxDesc
mul [rtl8169_tpc.cur_rx]
add eax, [rtl8169_tpc.RxDescArray]
mov ebx, eax
 
; DEBUGF 1,"K : rtl8169_RxDesc.status = 0x%x\n",[ebx + rtl8169_RxDesc.status]
 
test [ebx + rtl8169_RxDesc.status], RTL8169_DSB_OWNbit; 0x80000600
jnz .exit
 
; DEBUGF 1,"K : rtl8169_tpc.cur_rx = %u\n",[rtl8169_tpc.cur_rx]
 
; h/w no longer present (hotplug?) or major error, bail
RTL_R16 RTL8169_REG_IntrStatus
 
; DEBUGF 1,"K : IntrStatus = 0x%x\n",ax
 
cmp ax, 0xFFFF
je .exit
 
push eax
and ax, not (RTL8169_ISB_RxFIFOOver or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxOK)
RTL_W16 RTL8169_REG_IntrStatus,ax
 
mov eax, [ebx + rtl8169_RxDesc.status]
 
; DEBUGF 1,"K : RxDesc.status = 0x%x\n",eax
 
test eax, RTL8169_SD_RxRES
jnz .else
and eax, 0x00001FFF
; jz .exit.pop
add eax, -4
mov [eth_rx_data_len], ax
 
; DEBUGF 1,"K : rtl8169_poll: data length = %u\n",ax
 
push eax
mov ecx, eax
shr ecx, 2
mov eax, [rtl8169_tpc.cur_rx]
mov edx, [rtl8169_tpc.RxBufferRing + eax * 4]
mov esi, edx
mov edi, Ether_buffer
cld
rep movsd
pop ecx
and ecx, 3
rep movsb
 
mov eax, RTL8169_DSB_OWNbit or RX_BUF_SIZE
cmp [rtl8169_tpc.cur_rx], NUM_RX_DESC - 1
jne @f
or eax, RTL8169_DSB_EORbit
@@:
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"
; FIXME: shouldn't I reset the status on an error
@@:
inc [rtl8169_tpc.cur_rx]
and [rtl8169_tpc.cur_rx], NUM_RX_DESC - 1
.exit.pop:
pop eax
and ax, RTL8169_ISB_RxFIFOOver or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxOK
RTL_W16 RTL8169_REG_IntrStatus,ax
.exit:
ret
endp
 
proc rtl8169_cable
ret
endp
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/sis900.inc
0,0 → 1,1166
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; SIS900.INC ;;
;; ;;
;; Ethernet driver for Menuet OS ;;
;; ;;
;; Version 0.4 26 April 2004 ;;
;; ;;
;; This driver is based on the SIS900 driver from ;;
;; the etherboot 5.0.6 project. The copyright statement is ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; remaining parts Copyright 2004 Jason Delozier, ;;
;; cordata51@hotmail.com ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;; Updates: ;;
;; Revision Look up table and SIS635 Mac Address by Jarek Pelczar ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
;********************************************************************
; Interface
; SIS900_reset
; SIS900_probe
; SIS900_poll
; SIS900_transmit
;
;********************************************************************
;********************************************************************
; Comments:
; Known to work with the following SIS900 ethernet cards:
; - Device ID: 0x0900 Vendor ID: 0x1039 Revision: 0x91
; - Device ID: 0x0900 Vendor ID: 0x1039 Revision: 0x90
;
; If your card is not listed, try it and let me know if it
; functions properly and it will be aded to the list. If not
; we may be able to add support for it.
;
; How To Use:
; Add the following lines to Ethernet.inc in their appropriate locations
;
; include "Sis900.INC"
; dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll,
; SIS900_transmit
; dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll,
; SIS900_transmit ;untested
;
; ToDo:
; - Enable MII interface for reading speed
; and duplex settings.
;
; - Update Poll routine to support packet fragmentation.
;
; - Add additional support for other sis900 based cards
;
;********************************************************************
 
; comment the next line out if you don't want debug info printed
; on the debug board. This option adds a lot of bytes to the driver
; so it's worth to comment it out.
; SIS900_DEBUG equ 1
 
 
;* buffers and descriptors
cur_rx db 0
NUM_RX_DESC equ 4 ;* Number of RX descriptors *
NUM_TX_DESC equ 1 ;* Number of TX descriptors *
RX_BUFF_SZ equ 1520 ;* Buffer size for each Rx buffer *
TX_BUFF_SZ equ 1516 ;* Buffer size for each Tx buffer *
 
uglobal
align 4
txd:
times (3 * NUM_TX_DESC) dd 0
rxd:
times (3 * NUM_RX_DESC) dd 0
endg
 
txb equ eth_data_start
rxb equ txb + (NUM_TX_DESC * TX_BUFF_SZ)
SIS900_ETH_ALEN equ 6 ;* Size of Ethernet address *
SIS900_ETH_HLEN equ 14 ;* Size of ethernet header *
SIS900_ETH_ZLEN equ 60 ;* Minimum packet length *
SIS900_DSIZE equ 0x00000fff
SIS900_CRC_SIZE equ 4
SIS900_RFADDR_shift equ 16
;SIS900 Symbolic offsets to registers.
SIS900_cr equ 0x0 ; Command Register
SIS900_cfg equ 0x4 ; Configuration Register
SIS900_mear equ 0x8 ; EEPROM Access Register
SIS900_ptscr equ 0xc ; PCI Test Control Register
SIS900_isr equ 0x10 ; Interrupt Status Register
SIS900_imr equ 0x14 ; Interrupt Mask Register
SIS900_ier equ 0x18 ; Interrupt Enable Register
SIS900_epar equ 0x18 ; Enhanced PHY Access Register
SIS900_txdp equ 0x20 ; Transmit Descriptor Pointer Register
SIS900_txcfg equ 0x24 ; Transmit Configuration Register
SIS900_rxdp equ 0x30 ; Receive Descriptor Pointer Register
SIS900_rxcfg equ 0x34 ; Receive Configuration Register
SIS900_flctrl equ 0x38 ; Flow Control Register
SIS900_rxlen equ 0x3c ; Receive Packet Length Register
SIS900_rfcr equ 0x48 ; Receive Filter Control Register
SIS900_rfdr equ 0x4C ; Receive Filter Data Register
SIS900_pmctrl equ 0xB0 ; Power Management Control Register
SIS900_pmer equ 0xB4 ; Power Management Wake-up Event Register
;SIS900 Command Register Bits
SIS900_RELOAD equ 0x00000400
SIS900_ACCESSMODE equ 0x00000200
SIS900_RESET equ 0x00000100
SIS900_SWI equ 0x00000080
SIS900_RxRESET equ 0x00000020
SIS900_TxRESET equ 0x00000010
SIS900_RxDIS equ 0x00000008
SIS900_RxENA equ 0x00000004
SIS900_TxDIS equ 0x00000002
SIS900_TxENA equ 0x00000001
;SIS900 Configuration Register Bits
SIS900_DESCRFMT equ 0x00000100 ; 7016 specific
SIS900_REQALG equ 0x00000080
SIS900_SB equ 0x00000040
SIS900_POW equ 0x00000020
SIS900_EXD equ 0x00000010
SIS900_PESEL equ 0x00000008
SIS900_LPM equ 0x00000004
SIS900_BEM equ 0x00000001
SIS900_RND_CNT equ 0x00000400
SIS900_FAIR_BACKOFF equ 0x00000200
SIS900_EDB_MASTER_EN equ 0x00002000
;SIS900 Eeprom Access Reigster Bits
SIS900_MDC equ 0x00000040
SIS900_MDDIR equ 0x00000020
SIS900_MDIO equ 0x00000010 ; 7016 specific
SIS900_EECS equ 0x00000008
SIS900_EECLK equ 0x00000004
SIS900_EEDO equ 0x00000002
SIS900_EEDI equ 0x00000001
;SIS900 TX Configuration Register Bits
SIS900_ATP equ 0x10000000 ;Automatic Transmit Padding
SIS900_MLB equ 0x20000000 ;Mac Loopback Enable
SIS900_HBI equ 0x40000000 ;HeartBeat Ignore (Req for full-dup)
SIS900_CSI equ 0x80000000 ;CarrierSenseIgnore (Req for full-du
;SIS900 RX Configuration Register Bits
SIS900_AJAB equ 0x08000000 ;
SIS900_ATX equ 0x10000000 ;Accept Transmit Packets
SIS900_ARP equ 0x40000000 ;accept runt packets (<64bytes)
SIS900_AEP equ 0x80000000 ;accept error packets
;SIS900 Interrupt Reigster Bits
SIS900_WKEVT equ 0x10000000
SIS900_TxPAUSEEND equ 0x08000000
SIS900_TxPAUSE equ 0x04000000
SIS900_TxRCMP equ 0x02000000
SIS900_RxRCMP equ 0x01000000
SIS900_DPERR equ 0x00800000
SIS900_SSERR equ 0x00400000
SIS900_RMABT equ 0x00200000
SIS900_RTABT equ 0x00100000
SIS900_RxSOVR equ 0x00010000
SIS900_HIBERR equ 0x00008000
SIS900_SWINT equ 0x00001000
SIS900_MIBINT equ 0x00000800
SIS900_TxURN equ 0x00000400
SIS900_TxIDLE equ 0x00000200
SIS900_TxERR equ 0x00000100
SIS900_TxDESC equ 0x00000080
SIS900_TxOK equ 0x00000040
SIS900_RxORN equ 0x00000020
SIS900_RxIDLE equ 0x00000010
SIS900_RxEARLY equ 0x00000008
SIS900_RxERR equ 0x00000004
SIS900_RxDESC equ 0x00000002
SIS900_RxOK equ 0x00000001
;SIS900 Interrupt Enable Reigster Bits
SIS900_IE equ 0x00000001
;SIS900 Revision ID
SIS900B_900_REV equ 0x03
SIS630A_900_REV equ 0x80
SIS630E_900_REV equ 0x81
SIS630S_900_REV equ 0x82
SIS630EA1_900_REV equ 0x83
SIS630ET_900_REV equ 0x84
SIS635A_900_REV equ 0x90
SIS900_960_REV equ 0x91
;SIS900 Receive Filter Control Register Bits
SIS900_RFEN equ 0x80000000
SIS900_RFAAB equ 0x40000000
SIS900_RFAAM equ 0x20000000
SIS900_RFAAP equ 0x10000000
SIS900_RFPromiscuous equ 0x70000000
;SIS900 Reveive Filter Data Mask
SIS900_RFDAT equ 0x0000FFFF
;SIS900 Eeprom Address
SIS900_EEPROMSignature equ 0x00
SIS900_EEPROMVendorID equ 0x02
SIS900_EEPROMDeviceID equ 0x03
SIS900_EEPROMMACAddr equ 0x08
SIS900_EEPROMChecksum equ 0x0b
;The EEPROM commands include the alway-set leading bit.
;SIS900 Eeprom Command
SIS900_EEread equ 0x0180
SIS900_EEwrite equ 0x0140
SIS900_EEerase equ 0x01C0
SIS900_EEwriteEnable equ 0x0130
SIS900_EEwriteDisable equ 0x0100
SIS900_EEeraseAll equ 0x0120
SIS900_EEwriteAll equ 0x0110
SIS900_EEaddrMask equ 0x013F
SIS900_EEcmdShift equ 16
;For SiS962 or SiS963, request the eeprom software access
SIS900_EEREQ equ 0x00000400
SIS900_EEDONE equ 0x00000200
SIS900_EEGNT equ 0x00000100
;General Varibles
SIS900_pci_revision:
db 0
SIS900_Status dd 0x03000000
sis900_specific_table:
; dd SIS630A_900_REV,Get_Mac_SIS630A_900_REV,0
; dd SIS630E_900_REV,Get_Mac_SIS630E_900_REV,0
dd SIS630S_900_REV,Get_Mac_SIS635_900_REV,0
dd SIS630EA1_900_REV,Get_Mac_SIS635_900_REV,0
dd SIS630ET_900_REV,Get_Mac_SIS635_900_REV,0;SIS630ET_900_REV_SpecialFN
dd SIS635A_900_REV,Get_Mac_SIS635_900_REV,0
dd SIS900_960_REV,SIS960_get_mac_addr,0
dd SIS900B_900_REV,SIS900_get_mac_addr,0
dd 0,0,0,0 ; end of list
sis900_get_mac_func:
dd 0
sis900_special_func:
dd 0
sis900_table_entries:
db 8
 
;***************************************************************************
; Function
; SIS900_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
;not done - still need to probe mii transcievers
;***************************************************************************
if defined SIS900_DEBUG
SIS900_Debug_Str_Unsupported db 'Sorry your card is unsupported ',13,10,0
end if
SIS900_probe:
;******Wake Up Chip*******
mov al, 4
mov bh, [pci_dev]
mov ecx, 0
mov ah, [pci_bus]
mov bl, 0x40
call pci_write_reg
;*******Set some PCI Settings*********
call SIS900_adjust_pci_device
;*****Get Card Revision******
mov al, 1 ;one byte to read
mov bh, [pci_dev]
mov ah, [pci_bus]
mov bl, 0x08 ;Revision Register
call pci_read_reg
mov [SIS900_pci_revision], al;save the revision for later use
;****** Look up through the sis900_specific_table
mov esi, sis900_specific_table
.probe_loop:
cmp dword [esi], 0 ; Check if we reached end of the list
je .probe_loop_failed
cmp al, [esi] ; Check if revision is OK
je .probe_loop_ok
add esi, 12 ; Advance to next entry
jmp .probe_loop
.probe_loop_failed:
jmp SIS900_Probe_Unsupported
;*********Find Get Mac Function*********
.probe_loop_ok:
mov eax, [esi+4] ; Get pointer to "get MAC" function
mov [sis900_get_mac_func], eax
mov eax, [esi+8] ; Get pointer to special initialization fn
mov [sis900_special_func], eax
;******** Get MAC ********
call dword [sis900_get_mac_func]
;******** Call special initialization fn if requested ********
cmp dword [sis900_special_func], 0
je .no_special_init
call dword [sis900_special_func]
.no_special_init:
;******** Set table entries ********
mov al, [SIS900_pci_revision]
cmp al, SIS635A_900_REV
jae .ent16
cmp al, SIS900B_900_REV
je .ent16
jmp .ent8
.ent16:
mov byte [sis900_table_entries], 16
.ent8:
;*******Probe for mii transceiver*******
;TODO!!*********************
;*******Initialize Device*******
call sis900_init
ret
 
SIS900_Probe_Unsupported:
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Str_Unsupported
call sys_msg_board_str
end if
ret
;***************************************************************************
; Function: sis900_init
;
; Description: resets the ethernet controller chip and various
; data structures required for sending and receiving packets.
;
; Arguments:
;
; returns: none
;not done
;***************************************************************************
sis900_init:
call SIS900_reset ;Done
call SIS900_init_rxfilter;Done
call SIS900_init_txd;Done
call SIS900_init_rxd ;Done
call SIS900_set_rx_mode;done
call SIS900_set_tx_mode
;call SIS900_check_mode
ret
 
;***************************************************************************
; Function
; SIS900_reset
; Description
; disables interrupts and soft resets the controller chip
;
;done+
;***************************************************************************
if defined SIS900_DEBUG
SIS900_Debug_Reset_Failed db 'Reset Failed ',0
end if
SIS900_reset:
;******Disable Interrupts and reset Receive Filter*******
mov ebp, [io_addr] ; base address
xor eax, eax ; 0 to initialize
lea edx, [ebp+SIS900_ier]
out dx, eax ; Write 0 to location
lea edx, [ebp+SIS900_imr]
out dx, eax ; Write 0 to location
lea edx, [ebp+SIS900_rfcr]
out dx, eax ; Write 0 to location
;*******Reset Card***********************************************
lea edx, [ebp+SIS900_cr]
in eax, dx ; Get current Command Register
or eax, SIS900_RESET ; set flags
or eax, SIS900_RxRESET ;
or eax, SIS900_TxRESET ;
out dx, eax ; Write new Command Register
;*******Wait Loop************************************************
lea edx, [ebp+SIS900_isr]
mov ecx, [SIS900_Status]; Status we would like to see from card
mov ebx, 2001 ; only loop 1000 times
SIS900_Wait:
dec ebx ; 1 less loop
jz SIS900_DoneWait_e ; 1000 times yet?
in eax, dx ; move interrup status to eax
and eax, ecx
xor ecx, eax
jz SIS900_DoneWait
jmp SIS900_Wait
SIS900_DoneWait_e:
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Reset_Failed
call sys_msg_board_str
end if
SIS900_DoneWait:
;*******Set Configuration Register depending on Card Revision********
lea edx, [ebp+SIS900_cfg]
mov eax, SIS900_PESEL ; Configuration Register Bit
mov bl, [SIS900_pci_revision]; card revision
mov cl, SIS635A_900_REV ; Check card revision
cmp bl, cl
je SIS900_RevMatch
mov cl, SIS900B_900_REV ; Check card revision
cmp bl, cl
je SIS900_RevMatch
out dx, eax ; no revision match
jmp SIS900_Reset_Complete
SIS900_RevMatch: ; Revision match
or eax, SIS900_RND_CNT ; Configuration Register Bit
out dx, eax
SIS900_Reset_Complete:
mov eax, [pci_data]
mov [eth_status], eax
ret
 
;***************************************************************************
; Function: sis_init_rxfilter
;
; Description: sets receive filter address to our MAC address
;
; Arguments:
;
; returns:
;done+
;***************************************************************************
SIS900_init_rxfilter:
;****Get Receive Filter Control Register ********
mov ebp, [io_addr] ; base address
lea edx, [ebp+SIS900_rfcr]
in eax, dx ; get register
push eax
;****disable packet filtering before setting filter*******
mov eax, SIS900_RFEN;move receive filter enable flag
not eax ;1s complement
pop ebx ;and with our saved register
and eax, ebx ;disable receiver
push ebx ;save filter for another use
out dx, eax ;set receive disabled
;********load MAC addr to filter data register*********
xor ecx, ecx
SIS900_RXINT_Mac_Write:
;high word of eax tells card which mac byte to write
mov eax, ecx
lea edx, [ebp+SIS900_rfcr]
shl eax, 16 ;
out dx, eax ;
lea edx, [ebp+SIS900_rfdr]
mov ax, word [node_addr+ecx*2]; Get Mac ID word
out dx, ax ; Send Mac ID
inc cl ; send next word
cmp cl, 3 ; more to send?
jne SIS900_RXINT_Mac_Write
;********enable packet filitering *****
pop eax ;old register value
lea edx, [ebp+SIS900_rfcr]
or eax, SIS900_RFEN;enable filtering
out dx, eax ;set register
ret
 
;***************************************************************************
;*
;* Function: sis_init_txd
;*
;* Description: initializes the Tx descriptor
;*
;* Arguments:
;*
;* returns:
;*done
;***************************************************************************
SIS900_init_txd:
;********** initialize TX descriptor **************
mov [txd], dword 0 ;put link to next descriptor in link field
mov [txd+4], dword 0;clear status field
mov [txd+8], dword txb - OS_BASE;save address to buffer ptr field
;*************** load Transmit Descriptor Register ***************
mov dx, [io_addr] ; base address
add dx, SIS900_txdp ; TX Descriptor Pointer
mov eax, txd - OS_BASE ; First Descriptor
out dx, eax ; move the pointer
ret
 
;***************************************************************************
;* Function: sis_init_rxd
;*
;* Description: initializes the Rx descriptor ring
;*
;* Arguments:
;*
;* Returns:
;*done
;***************************************************************************
SIS900_init_rxd:
xor ecx, ecx
mov [cur_rx], cl ;Set cuurent rx discriptor to 0
;******** init RX descriptors ********
SIS900_init_rxd_Loop:
mov eax, ecx ;current descriptor
imul eax, 12 ;
mov ebx, ecx ;determine next link descriptor
inc ebx ;
cmp ebx, NUM_RX_DESC ;
jne SIS900_init_rxd_Loop_0 ;
xor ebx, ebx ;
SIS900_init_rxd_Loop_0: ;
imul ebx, 12 ;
add ebx, rxd - OS_BASE ;
mov [rxd+eax], ebx ;save link to next descriptor
mov [rxd+eax+4], dword RX_BUFF_SZ ;status bits init to buf size
mov ebx, ecx ;find where the buf is located
imul ebx, RX_BUFF_SZ ;
add ebx, rxb - OS_BASE ;
mov [rxd+eax+8], ebx ;save buffer pointer
inc ecx ;next descriptor
cmp ecx, NUM_RX_DESC ;
jne SIS900_init_rxd_Loop ;
;********* load Receive Descriptor Register with address of first
; descriptor*********
mov dx, [io_addr]
add dx, SIS900_rxdp
mov eax, rxd - OS_BASE
out dx, eax
ret
 
;***************************************************************************
;* Function: sis900_set_tx_mode
;*
;* Description:
;* sets the transmit mode to allow for full duplex
;*
;*
;* Arguments:
;*
;* Returns:
;*
;* Comments:
;* If you are having problems transmitting packet try changing the
;* Max DMA Burst, Possible settings are as follows:
;* 0x00000000 = 512 bytes
;* 0x00100000 = 4 bytes
;* 0x00200000 = 8 bytes
;* 0x00300000 = 16 bytes
;* 0x00400000 = 32 bytes
;* 0x00500000 = 64 bytes
;* 0x00600000 = 128 bytes
;* 0x00700000 = 256 bytes
;***************************************************************************
SIS900_set_tx_mode:
mov ebp, [io_addr]
lea edx, [ebp+SIS900_cr]
in eax, dx ; Get current Command Register
or eax, SIS900_TxENA;Enable Receive
out dx, eax
lea edx, [ebp+SIS900_txcfg]; Transmit config Register offset
mov eax, SIS900_ATP ;allow automatic padding
or eax, SIS900_HBI ;allow heartbeat ignore
or eax, SIS900_CSI ;allow carrier sense ignore
or eax, 0x00600000 ;Max DMA Burst
or eax, 0x00000100 ;TX Fill Threshold
or eax, 0x00000020 ;TX Drain Threshold
out dx, eax
ret
 
;***************************************************************************
;* Function: sis900_set_rx_mode
;*
;* Description:
;* sets the receive mode to accept all broadcast packets and packets
;* with our MAC address, and reject all multicast packets. Also allows
;* full-duplex
;*
;* Arguments:
;*
;* Returns:
;*
;* Comments:
;* If you are having problems receiving packet try changing the
;* Max DMA Burst, Possible settings are as follows:
;* 0x00000000 = 512 bytes
;* 0x00100000 = 4 bytes
;* 0x00200000 = 8 bytes
;* 0x00300000 = 16 bytes
;* 0x00400000 = 32 bytes
;* 0x00500000 = 64 bytes
;* 0x00600000 = 128 bytes
;* 0x00700000 = 256 bytes
;***************************************************************************
SIS900_mc_filter:
times 16 dw 0
SIS900_set_rx_mode:
mov ebp, [io_addr]
;**************update Multicast Hash Table in Receive Filter
mov ebx, 0xffff
xor cl, cl
SIS900_set_rx_mode_Loop:
mov eax, ecx
shl eax, 1
mov [SIS900_mc_filter+eax], bx
lea edx, [ebp+SIS900_rfcr] ; Receive Filter Control Reg offset
mov eax, 4 ;determine table entry
add al, cl
shl eax, 16
out dx, eax ;tell card which entry to modify
lea edx, [ebp+SIS900_rfdr] ; Receive Filter Control Reg offset
mov eax, ebx ;entry value
out dx, ax ;write value to table in card
inc cl ;next entry
cmp cl, [sis900_table_entries];
jl SIS900_set_rx_mode_Loop
;*******Set Receive Filter Control Register*************
lea edx, [ebp+SIS900_rfcr] ; Receive Filter Control Register offset
mov eax, SIS900_RFAAB ;accecpt all broadcast packets
or eax, SIS900_RFAAM ;accept all multicast packets
or eax, SIS900_RFAAP ;Accept all packets
or eax, SIS900_RFEN ;enable receiver filter
out dx, eax
;******Enable Receiver************
lea edx, [ebp+SIS900_cr]; Command Register offset
in eax, dx ; Get current Command Register
or eax, SIS900_RxENA;Enable Receive
out dx, eax
;*********Set
lea edx, [ebp+SIS900_rxcfg] ; Receive Config Register offset
mov eax, SIS900_ATX ;Accept Transmit Packets
; (Req for full-duplex and PMD Loopback)
or eax, 0x00600000 ;Max DMA Burst
or eax, 0x00000002 ;RX Drain Threshold, 8X8 bytes or 64bytes
out dx, eax ;
ret
 
;***************************************************************************
; * SIS960_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
; * @pci_dev: the sis900 pci device
; * @net_dev: the net device to get address for
; *
; * SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM
; * is shared by
; * LAN and 1394. When access EEPROM, send EEREQ signal to hardware first
; * and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access
; * by LAN, otherwise is not. After MAC address is read from EEPROM, send
; * EEDONE signal to refuse EEPROM access by LAN.
; * The EEPROM map of SiS962 or SiS963 is different to SiS900.
; * The signature field in SiS962 or SiS963 spec is meaningless.
; * MAC address is read into @net_dev->dev_addr.
; *done
;*
;* Return 0 is EAX = failure
;*Done+
;***************************************************************************
if defined SIS900_DEBUG
SIS900_Debug_Str_GetMac_Start db 'Attempting to get SIS900 Mac ID: ',13,10,0
SIS900_Debug_Str_GetMac_Failed db 'Access to EEprom Failed',13,10,0
SIS900_Debug_Str_GetMac_Address db 'Your Mac ID is: ',0
SIS900_Debug_Str_GetMac_Address2 db 'Your SIS96x Mac ID is: ',0
end if
SIS960_get_mac_addr:
mov ebp, [io_addr]
;**********Send Request for eeprom access*********************
lea edx, [ebp+SIS900_mear] ; Eeprom access register
mov eax, SIS900_EEREQ ; Request access to eeprom
out dx, eax ; Send request
xor ebx, ebx ;
;******Loop 4000 times and if access not granted error out*****
SIS96X_Get_Mac_Wait:
in eax, dx ;get eeprom status
and eax, SIS900_EEGNT ;see if eeprom access granted flag is set
jnz SIS900_Got_EEP_Access ;if it is, go access the eeprom
inc ebx ;else keep waiting
cmp ebx, 4000 ;have we tried 4000 times yet?
jl SIS96X_Get_Mac_Wait ;if not ask again
xor eax, eax ;return zero in eax indicating failure
;*******Debug **********************
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Str_GetMac_Failed
call sys_msg_board_str
end if
jmp SIS960_get_mac_addr_done
;**********EEprom access granted, read MAC from card*************
SIS900_Got_EEP_Access:
; zero based so 3-16 bit reads will take place
mov ecx, 2
SIS96x_mac_read_loop:
mov eax, SIS900_EEPROMMACAddr;Base Mac Address
add eax, ecx ;Current Mac Byte Offset
push ecx
call sis900_read_eeprom ;try to read 16 bits
pop ecx
mov [node_addr+ecx*2], ax ;save 16 bits to the MAC ID varible
dec ecx ;one less word to read
jns SIS96x_mac_read_loop ;if more read more
mov eax, 1 ;return non-zero indicating success
;*******Debug Print MAC ID to debug window**********************
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Str_GetMac_Address2
call sys_msg_board_str
mov edx, node_addr
call Create_Mac_String
end if
;**********Tell EEPROM We are Done Accessing It*********************
SIS960_get_mac_addr_done:
lea edx, [ebp+SIS900_mear] ; Eeprom access register
mov eax, SIS900_EEDONE ;tell eeprom we are done
out dx, eax
ret
;***************************************************************************
;* sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model
;* @pci_dev: the sis900 pci device
;* @net_dev: the net device to get address for
;*
;* Older SiS900 and friends, use EEPROM to store MAC address.
;* MAC address is read from read_eeprom() into @net_dev->dev_addr.
;* done/untested
;***************************************************************************
SIS900_get_mac_addr:
;*******Debug **********************
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Str_GetMac_Start
call sys_msg_board_str
end if
;******** check to see if we have sane EEPROM *******
mov eax, SIS900_EEPROMSignature;Base Eeprom Signature
call sis900_read_eeprom ;try to read 16 bits
cmp ax, 0xffff
je SIS900_Bad_Eeprom
cmp ax, 0
je SIS900_Bad_Eeprom
;**************Read MacID**************
; zero based so 3-16 bit reads will take place
mov ecx, 2
SIS900_mac_read_loop:
mov eax, SIS900_EEPROMMACAddr;Base Mac Address
add eax, ecx ;Current Mac Byte Offset
push ecx
call sis900_read_eeprom ;try to read 16 bits
pop ecx
mov [node_addr+ecx*2], ax ;save 16 bits to the MAC ID storage
dec ecx ;one less word to read
jns SIS900_mac_read_loop ;if more read more
mov eax, 1 ;return non-zero indicating success
;*******Debug Print MAC ID to debug window**********************
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Str_GetMac_Address
call sys_msg_board_str
mov edx, node_addr
call Create_Mac_String
end if
ret
 
SIS900_Bad_Eeprom:
xor eax, eax
;*******Debug **********************
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Str_GetMac_Failed
call sys_msg_board_str
end if
ret
;***************************************************************************
;* Get_Mac_SIS635_900_REV: - Get MAC address for model 635
;*
;*
;***************************************************************************
Get_Mac_SIS635_900_REV:
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Str_GetMac_Start
call sys_msg_board_str
end if
mov ebp, [io_addr]
lea edx, [ebp+SIS900_rfcr]
in eax, dx
mov edi, eax; EDI=rfcrSave
lea edx, [ebp+SIS900_cr]
or eax, SIS900_RELOAD
out dx, eax
xor eax, eax
out dx, eax
; Disable packet filtering before setting filter
lea edx, [ebp+SIS900_rfcr]
mov eax, edi
and edi, not SIS900_RFEN
out dx, eax
; Load MAC to filter data register
xor ecx, ecx
mov esi, node_addr
.get_mac_loop:
lea edx, [ebp+SIS900_rfcr]
mov eax, ecx
shl eax, SIS900_RFADDR_shift
out dx, eax
lea edx, [ebp+SIS900_rfdr]
in eax, dx
mov [esi], ax
add esi, 2
inc ecx
cmp ecx, 3
jne .get_mac_loop
; Enable packet filtering
;lea edx,[ebp+SIS900_rfcr]
;mov eax,edi
;or eax,SIS900_RFEN
;out dx, eax
;*******Debug Print MAC ID to debug window**********************
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Str_GetMac_Address
call sys_msg_board_str
mov edx, node_addr
call Create_Mac_String
end if
ret
;***************************************************************************
;* Function: sis900_read_eeprom
;*
;* Description: reads and returns a given location from EEPROM
;*
;* Arguments: eax - location: requested EEPROM location
;*
;* Returns: eax : contents of requested EEPROM location
;*
; Read Serial EEPROM through EEPROM Access Register, Note that location is
; in word (16 bits) unit */
;done+
;***************************************************************************
sis900_read_eeprom:
push esi
push edx
push ecx
push ebx
mov ebp, [io_addr]
mov ebx, eax ;location of Mac byte to read
or ebx, SIS900_EEread ;
lea edx, [ebp+SIS900_mear]; Eeprom access register
xor eax, eax ; start send
out dx, eax
call SIS900_Eeprom_Delay_1
mov eax, SIS900_EECLK
out dx, eax
call SIS900_Eeprom_Delay_1
;************ Shift the read command (9) bits out. *********
mov cl, 8 ;
sis900_read_eeprom_Send:
mov eax, 1
shl eax, cl
and eax, ebx
jz SIS900_Read_Eeprom_8
mov eax, 9
jmp SIS900_Read_Eeprom_9
SIS900_Read_Eeprom_8:
mov eax, 8
SIS900_Read_Eeprom_9:
out dx, eax
call SIS900_Eeprom_Delay_1
or eax, SIS900_EECLK
out dx, eax
call SIS900_Eeprom_Delay_1
cmp cl, 0
je sis900_read_eeprom_Send_Done
dec cl
jmp sis900_read_eeprom_Send
;*********************
sis900_read_eeprom_Send_Done:
mov eax, SIS900_EECS ;
out dx, eax
call SIS900_Eeprom_Delay_1
;********** Read 16-bits of data in ***************
mov cx, 16 ;16 bits to read
sis900_read_eeprom_Send2:
mov eax, SIS900_EECS
out dx, eax
call SIS900_Eeprom_Delay_1
or eax, SIS900_EECLK
out dx, eax
call SIS900_Eeprom_Delay_1
in eax, dx
shl ebx, 1
and eax, SIS900_EEDO
jz SIS900_Read_Eeprom_0
or ebx, 1
SIS900_Read_Eeprom_0:
dec cx
jnz sis900_read_eeprom_Send2
;************** Terminate the EEPROM access. **************
xor eax, eax
out dx, eax
call SIS900_Eeprom_Delay_1
mov eax, SIS900_EECLK
out dx, eax
mov eax, ebx
and eax, 0x0000ffff ;return only 16 bits
pop ebx
pop ecx
pop edx
pop esi
ret
;***************************************************************************
; Function
; SIS900_Eeprom_Delay_1
; Description
;
;
;
;
;***************************************************************************
SIS900_Eeprom_Delay_1:
push eax
in eax, dx
pop eax
ret
 
;***************************************************************************
; Function
; SIS900_poll
; Description
; polls card to see if there is a packet waiting
;
; Currently only supports one descriptor per packet, if packet is fragmented
; between multiple descriptors you will lose part of the packet
;***************************************************************************
if defined SIS900_DEBUG
SIS900_Debug_Pull_Packet_good db 'Good Packet Waiting: ',13,10,0
SIS900_Debug_Pull_Bad_Packet_Status db 'Bad Packet Waiting: Status',13,10,0
SIS900_Debug_Pull_Bad_Packet_Size db 'Bad Packet Waiting: Size',13,10,0
end if
SIS900_poll:
;**************Get Status **************
xor eax, eax ;get RX_Status
mov [eth_rx_data_len], ax
mov al, [cur_rx] ;find current discriptor
imul eax, 12 ;
mov ecx, [rxd+eax+4] ; get receive status
;**************Check Status **************
mov ebx, ecx ;move status
;Check RX_Status to see if packet is waiting
and ebx, 0x80000000
jnz SIS900_poll_IS_packet
ret
;**********There is a packet waiting check it for errors**************
SIS900_poll_IS_packet:
mov ebx, ecx ;move status
and ebx, 0x67C0000 ;see if there are any errors
jnz SIS900_Poll_Error_Status
;**************Check size of packet*************
and ecx, SIS900_DSIZE ;get packet size minus CRC
cmp cx, SIS900_CRC_SIZE
;make sure packet contains data
jle SIS900_Poll_Error_Size
;*******Copy Good Packet to receive buffer******
sub cx, SIS900_CRC_SIZE ;dont want crc
mov word [eth_rx_data_len], cx ;save size of packet
;**********Continue copying packet****************
push ecx
; first copy dword-wise, divide size by 4
shr ecx, 2
mov esi, [rxd+eax+8] ; set source
add esi, OS_BASE ; get linear address
mov edi, Ether_buffer ; set destination
cld ; clear direction
rep movsd ; copy the dwords
pop ecx
and ecx, 3 ;
rep movsb
;********Debug, tell user we have a good packet*************
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Pull_Packet_good
call sys_msg_board_str
end if
jmp SIS900_Poll_Cnt ;
;*************Error occured let user know through debug window***********
SIS900_Poll_Error_Status:
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Pull_Bad_Packet_Status
call sys_msg_board_str
end if
jmp SIS900_Poll_Cnt
SIS900_Poll_Error_Size:
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Pull_Bad_Packet_Size
call sys_msg_board_str
end if
;*************Increment to next available descriptor**************
SIS900_Poll_Cnt:
;Reset status, allow ethernet card access to descriptor
mov ecx, RX_BUFF_SZ
mov [rxd+eax+4], ecx ;
inc [cur_rx] ;get next descriptor
and [cur_rx], 3 ;only 4 descriptors 0-3
;******Enable Receiver************
mov ebp, [io_addr] ; Base Address
lea edx, [ebp+SIS900_cr]; Command Register offset
in eax, dx ; Get current Command Register
or eax, SIS900_RxENA;Enable Receive
out dx, eax
ret
;***************************************************************************
; Function
; SIS900_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
;
; only one transmit descriptor is used
;
;***************************************************************************
if defined SIS900_DEBUG
SIS900_Debug_Transmit_Packet db 'Transmitting Packet: ',13,10,0
SIS900_Debug_Transmit_Packet_Err db 'Transmitting Packet Error: ',13,10,0
end if
str1 db 'Transmitting packet:',13,10,0
str2 db ' ',0
SIS900_transmit:
mov ebp, [io_addr] ; Base Address
;******** Stop the transmitter ********
lea edx, [ebp+SIS900_cr]; Command Register offset
in eax, dx ; Get current Command Register
or eax, SIS900_TxDIS; Disable Transmitter
out dx, eax
;*******load Transmit Descriptor Register *******
lea edx, [ebp+SIS900_txdp]
mov eax, txd - OS_BASE
out dx, eax
;******* copy packet to descriptor*******
push esi
mov esi, edi ;copy destination addess
mov edi, txb
cld
movsd
movsw
mov esi, node_addr;copy my mac address
movsd
movsw
mov [edi], bx ;copy packet type
add edi, 2
pop esi ;restore pointer to source of packet
push ecx ;save packet size
shr ecx, 2 ;divide by 4, size in bytes send in dwords
rep movsd ;copy data to decriptor
pop ecx ;restore packet size
push ecx ;save packet size
and ecx, 3 ;last three bytes if not a multiple of 4
rep movsb
;**************set length tag**************
pop ecx ;restore packet size
add ecx, SIS900_ETH_HLEN;add header to length
and ecx, SIS900_DSIZE;
;**************pad to minimum packet size **************not needed
;cmp ecx, SIS900_ETH_ZLEN
;jge SIS900_transmit_Size_Ok
;push ecx
;mov ebx, SIS900_ETH_ZLEN
;sub ebx, ecx
;mov ecx, ebx
;rep movsb
;pop ecx
SIS900_transmit_Size_Ok:
mov [txd+4], dword 0x80000000 ;card owns descriptor
or [txd+4], ecx ;set size of packet
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Transmit_Packet
call sys_msg_board_str
end if
;***************restart the transmitter ********
lea edx, [ebp+SIS900_cr]
in eax, dx ; Get current Command Register
or eax, SIS900_TxENA; Enable Transmitter
out dx, eax
;****make sure packet transmitted successfully****
; mov esi,10
; call delay_ms
mov eax, [txd+4]
and eax, 0x6200000
jz SIS900_transmit_OK
;**************Tell user there was an error through debug window
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Transmit_Packet_Err
call sys_msg_board_str
end if
SIS900_transmit_OK:
;******** Disable interrupts by clearing the interrupt mask. ********
lea edx, [ebp+SIS900_imr] ; Interupt Mask Register
xor eax, eax
out dx, eax
ret
 
;***************************************************************************
;* Function: Create_Mac_String
;*
;* Description: Converts the 48 bit value to a string for display
;*
;* String Format: XX:XX:XX:XX:XX:XX
;*
;* Arguments: node_addr is location of 48 bit MAC ID
;*
;* Returns: Prints string to general debug window
;*
;*
;done
;***************************************************************************
if defined SIS900_DEBUG
 
SIS900_Char_String db '0','1','2','3','4','5','6','7','8','9'
db 'A','B','C','D','E','F'
Mac_str_build:
times 20 db 0
Create_Mac_String:
pusha
xor ecx, ecx
Create_Mac_String_loop:
mov al, byte [edx+ecx];[node_addr+ecx]
push eax
shr eax, 4
and eax, 0x0f
mov bl, byte [SIS900_Char_String+eax]
mov [Mac_str_build+ecx*3], bl
pop eax
and eax, 0x0f
mov bl, byte [SIS900_Char_String+eax]
mov [Mac_str_build+1+ecx*3], bl
cmp ecx, 5
je Create_Mac_String_done
mov bl, ':'
mov [Mac_str_build+2+ecx*3], bl
inc ecx
jmp Create_Mac_String_loop
Create_Mac_String_done: ;Insert CR and Zero Terminate
mov [Mac_str_build+2+ecx*3], byte 13
mov [Mac_str_build+3+ecx*3], byte 10
mov [Mac_str_build+4+ecx*3], byte 0
mov esi, Mac_str_build
call sys_msg_board_str ;Print String to message board
popa
ret
end if
;***************************************************************************
;* Set device to be a busmaster in case BIOS neglected to do so.
;* Also adjust PCI latency timer to a reasonable value, 64.
;***************************************************************************
SIS900_adjust_pci_device:
;*******Get current setting************************
mov al, 2 ;read a word
mov bh, [pci_dev]
mov ah, [pci_bus]
mov bl, 0x04 ;from command Register
call pci_read_reg
;******see if its already set as bus master********
mov bx, ax
and bx, 5
cmp bx, 5
je SIS900_adjust_pci_device_Latency
;******Make card a bus master*******
mov cx, ax ;value to write
mov bh, [pci_dev]
mov al, 2 ;write a word
or cx, 5
mov ah, [pci_bus]
mov bl, 0x04 ;to command register
call pci_write_reg
;******Check latency setting***********
SIS900_adjust_pci_device_Latency:
;*******Get current latency setting************************
mov al, 1 ;read a byte
mov bh, [pci_dev]
mov ah, [pci_bus]
mov bl, 0x0D ;from Lantency Timer Register
call pci_read_reg
;******see if its aat least 64 clocks********
cmp ax, 64
jge SIS900_adjust_pci_device_Done
;******Set latency to 32 clocks*******
mov cx, 64 ;value to write
mov bh, [pci_dev]
mov al, 1 ;write a byte
mov ah, [pci_bus]
mov bl, 0x0D ;to Lantency Timer Register
call pci_write_reg
;******Check latency setting***********
SIS900_adjust_pci_device_Done:
ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/r6040.inc
0,0 → 1,813
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; R6040 driver for KolibriOS ;;
;; ;;
;; based on R6040.c from linux ;;
;; ;;
;; Written by Asper (asper.85@mail.ru) ;;
;; and hidnplayr (hidnplayr@gmail.com) ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
 
;********************************************************************
; Interface
; r6040_reset
; r6040_probe
; r6040_poll
; r6040_transmit
;
; These functions are referenced in ethernet.inc
;
;********************************************************************
 
;; A few user-configurable values.
 
TX_RING_SIZE equ 4
RX_RING_SIZE equ 4
 
; ethernet address length
ETH_ALEN equ 6
ETH_HLEN equ (2 * ETH_ALEN + 2)
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for
; mininmum 64bytes frame length
; system timer frequency
HZ equ 1000
 
; max time out delay time
W_MAX_TIMEOUT equ 0x0FFF
 
;; Size of the in-memory receive ring.
RX_BUF_LEN_IDX equ 3 ;; 0==8K, 1==16K, 2==32K, 3==64K
RX_BUF_LEN equ (8192 << RX_BUF_LEN_IDX)
 
;-; Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4).
;-TX_BUF_SIZE equ 1536
;-RX_BUF_SIZE equ 1536
 
;; PCI Tuning Parameters
; Threshold is bytes transferred to chip before transmission starts.
TX_FIFO_THRESH equ 256 ;; In bytes, rounded down to 32 byte units.
 
;; The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024.
RX_FIFO_THRESH equ 4 ;; Rx buffer level before first PCI xfer.
RX_DMA_BURST equ 4 ;; Maximum PCI burst, '4' is 256 bytes
TX_DMA_BURST equ 4
 
;; Operational parameters that usually are not changed.
PHY1_ADDR equ 1 ;For MAC1
PHY2_ADDR equ 3 ;For MAC2
PHY_MODE equ 0x3100 ;PHY CHIP Register 0
PHY_CAP equ 0x01E1 ;PHY CHIP Register 4
 
;; Time in jiffies before concluding the transmitter is hung.
TX_TIMEOUT equ ((6000*HZ)/1000)
 
R6040_IO_SIZE equ 256 ; RDC MAC I/O Size
MAX_MAC equ 2 ; MAX RDC MAC
 
;**************************************************************************
; RDC R6040 Register Definitions
;**************************************************************************
MCR0 equ 0x00 ;Control register 0
MCR1 equ 0x01 ;Control register 1
MAC_RST equ 0x0001 ;Reset the MAC
MBCR equ 0x08 ;Bus control
MT_ICR equ 0x0C ;TX interrupt control
MR_ICR equ 0x10 ;RX interrupt control
MTPR equ 0x14 ;TX poll command register
MR_BSR equ 0x18 ;RX buffer size
MR_DCR equ 0x1A ;RX descriptor control
MLSR equ 0x1C ;Last status
MMDIO equ 0x20 ;MDIO control register
MDIO_WRITE equ 0x4000 ;MDIO write
MDIO_READ equ 0x2000 ;MDIO read
MMRD equ 0x24 ;MDIO read data register
MMWD equ 0x28 ;MDIO write data register
MTD_SA0 equ 0x2C ;TX descriptor start address 0
MTD_SA1 equ 0x30 ;TX descriptor start address 1
MRD_SA0 equ 0x34 ;RX descriptor start address 0
MRD_SA1 equ 0x38 ;RX descriptor start address 1
MISR equ 0x3C ;Status register
MIER equ 0x40 ;INT enable register
MSK_INT equ 0x0000 ;Mask off interrupts
RX_FINISH equ 0x0001 ;RX finished
RX_NO_DESC equ 0x0002 ;No RX descriptor available
RX_FIFO_FULL equ 0x0004 ;RX FIFO full
RX_EARLY equ 0x0008 ;RX early
TX_FINISH equ 0x0010 ;TX finished
TX_EARLY equ 0x0080 ;TX early
EVENT_OVRFL equ 0x0100 ;Event counter overflow
LINK_CHANGED equ 0x0200 ;PHY link changed
ME_CISR equ 0x44 ;Event counter INT status
ME_CIER equ 0x48 ;Event counter INT enable
MR_CNT equ 0x50 ;Successfully received packet counter
ME_CNT0 equ 0x52 ;Event counter 0
ME_CNT1 equ 0x54 ;Event counter 1
ME_CNT2 equ 0x56 ;Event counter 2
ME_CNT3 equ 0x58 ;Event counter 3
MT_CNT equ 0x5A ;Successfully transmit packet counter
ME_CNT4 equ 0x5C ;Event counter 4
MP_CNT equ 0x5E ;Pause frame counter register
MAR0 equ 0x60 ;Hash table 0
MAR1 equ 0x62 ;Hash table 1
MAR2 equ 0x64 ;Hash table 2
MAR3 equ 0x66 ;Hash table 3
MID_0L equ 0x68 ;Multicast address MID0 Low
MID_0M equ 0x6A ;Multicast address MID0 Medium
MID_0H equ 0x6C ;Multicast address MID0 High
MID_1L equ 0x70 ;MID1 Low
MID_1M equ 0x72 ;MID1 Medium
MID_1H equ 0x74 ;MID1 High
MID_2L equ 0x78 ;MID2 Low
MID_2M equ 0x7A ;MID2 Medium
MID_2H equ 0x7C ;MID2 High
MID_3L equ 0x80 ;MID3 Low
MID_3M equ 0x82 ;MID3 Medium
MID_3H equ 0x84 ;MID3 High
PHY_CC equ 0x88 ;PHY status change configuration register
PHY_ST equ 0x8A ;PHY status register
MAC_SM equ 0xAC ;MAC status machine
MAC_ID equ 0xBE ;Identifier register
 
MAX_BUF_SIZE equ 0x600 ;1536
 
MBCR_DEFAULT equ 0x012A ;MAC Bus Control Register
MCAST_MAX equ 3 ;Max number multicast addresses to filter
 
;Descriptor status
DSC_OWNER_MAC equ 0x8000 ;MAC is the owner of this descriptor
DSC_RX_OK equ 0x4000 ;RX was successfull
DSC_RX_ERR equ 0x0800 ;RX PHY error
DSC_RX_ERR_DRI equ 0x0400 ;RX dribble packet
DSC_RX_ERR_BUF equ 0x0200 ;RX length exceeds buffer size
DSC_RX_ERR_LONG equ 0x0100 ;RX length > maximum packet length
DSC_RX_ERR_RUNT equ 0x0080 ;RX packet length < 64 byte
DSC_RX_ERR_CRC equ 0x0040 ;RX CRC error
DSC_RX_BCAST equ 0x0020 ;RX broadcast (no error)
DSC_RX_MCAST equ 0x0010 ;RX multicast (no error)
DSC_RX_MCH_HIT equ 0x0008 ;RX multicast hit in hash table (no error)
DSC_RX_MIDH_HIT equ 0x0004 ;RX MID table hit (no error)
DSC_RX_IDX_MID_MASK equ 3 ;RX mask for the index of matched MIDx
 
;PHY settings
ICPLUS_PHY_ID equ 0x0243
 
RX_INTS equ RX_FIFO_FULL or RX_NO_DESC or RX_FINISH
TX_INTS equ TX_FINISH
INT_MASK equ RX_INTS or TX_INTS
 
 
r6040_txb equ (eth_data_start)
r6040_rxb equ ((r6040_txb+(MAX_BUF_SIZE*TX_RING_SIZE)+32) and 0xfffffff0)
r6040_tx_ring equ ((r6040_rxb+(MAX_BUF_SIZE*RX_RING_SIZE)+32) and 0xfffffff0)
r6040_rx_ring equ ((r6040_tx_ring+(r6040_x_head.sizeof*TX_RING_SIZE)+32) and 0xfffffff0)
 
virtual at ((r6040_rx_ring+(r6040_x_head.sizeof*RX_RING_SIZE)+32) and 0xfffffff0)
r6040_private:
.rx_ring dd ?
.tx_ring dd ?
.cur_rx dw ?
.cur_tx dw ?
.phy_addr dw ?
.phy_mode dw ?
.mcr0 dw ?
.mcr1 dw ?
.switch_sig dw ?
end virtual
 
virtual at 0
r6040_x_head:
.status dw ? ;0-1
.len dw ? ;2-3
.buf dd ? ;4-7
.ndesc dd ? ;8-B
.rev1 dd ? ;C-F
.vbufp dd ? ;10-13
.vndescp dd ? ;14-17
.skb_ptr dd ? ;18-1B
.rev2 dd ? ;1C-1F
.sizeof:
end virtual
 
 
 
; Read a word data from PHY Chip
proc r6040_phy_read stdcall, phy_addr:dword, reg:dword
push ecx edx
mov eax, [phy_addr]
shl eax, 8
add eax, [reg]
add eax, MDIO_READ
mov edx, [io_addr]
add edx, MMDIO
out dx, ax
;Wait for the read bit to be cleared.
mov ecx, 2048 ;limit
xor eax, eax
.read:
in ax, dx
test ax, MDIO_READ
jz @f
dec ecx
test ecx, ecx
jnz .read
@@:
mov edx, [io_addr]
add edx, MMRD
in ax, dx
and eax, 0xFFFF
pop edx ecx
ret
endp
 
; Write a word data to PHY Chip
proc r6040_phy_write stdcall, phy_addr:dword, reg:dword, val:dword
push eax ecx edx
mov eax, [val]
mov edx, [io_addr]
add edx, MMWD
out dx, ax
;Write the command to the MDIO bus
mov eax, [phy_addr]
shl eax, 8
add eax, [reg]
add eax, MDIO_WRITE
mov edx, [io_addr]
add edx, MMDIO
out dx, ax
;Wait for the write bit to be cleared.
mov ecx, 2048 ;limit
xor eax, eax
.write:
in ax, dx
test ax, MDIO_WRITE
jz @f
dec ecx
test ecx, ecx
jnz .write
@@:
pop edx ecx eax
ret
endp
 
macro r6040_mdio_write reg, val {
stdcall r6040_phy_read, [io_addr], [r6040_private.phy_addr], reg
}
 
macro r6040_mdio_write reg, val {
stdcall r6040_phy_write, [io_addr], [r6040_private.phy_addr], reg, val
}
 
 
proc r6040_init_ring_desc stdcall, desc_ring:dword, size:dword
push eax ecx esi
mov ecx, [size]
test ecx, ecx
jz .out
 
mov esi, [desc_ring]
mov eax, esi
.next_desc:
add eax, r6040_x_head.sizeof - OS_BASE
mov [esi+r6040_x_head.ndesc], eax
add eax, OS_BASE
mov [esi+r6040_x_head.vndescp], eax
mov esi, eax
dec ecx
jnz .next_desc
 
sub esi, r6040_x_head.sizeof
mov eax, [desc_ring]
mov [esi+r6040_x_head.vndescp], eax
sub eax, OS_BASE
mov [esi+r6040_x_head.ndesc], eax
.out:
pop esi ecx eax
ret
endp
 
 
 
 
r6040_init_rxbufs:
 
stdcall r6040_init_ring_desc, r6040_rx_ring, RX_RING_SIZE
 
; Allocate skbs for the rx descriptors
mov esi, r6040_rx_ring
mov ebx, r6040_rxb
mov ecx, RX_RING_SIZE
mov eax, r6040_rx_ring
.next_desc:
mov [esi+r6040_x_head.skb_ptr], ebx
mov [esi+r6040_x_head.buf], ebx
sub [esi+r6040_x_head.buf], OS_BASE
mov [esi+r6040_x_head.status], DSC_OWNER_MAC
 
mov eax, [esi+r6040_x_head.vndescp]
mov esi, eax
 
add ebx, MAX_BUF_SIZE
dec ecx
jnz .next_desc
 
xor eax, eax
.out:
 
ret
 
 
r6040_probe:
 
DEBUGF 1, "Probing r6040\n"
 
call adjust_pci_device
 
 
; If PHY status change register is still set to zero
; it means the bootloader didn't initialize it
mov edx, [io_addr]
add edx, PHY_CC
in ax, dx
test ax, ax
jnz @f
mov eax, 0x9F07
out dx, ax
@@:
; Set MAC address
mov ecx, 3
mov edi, node_addr
mov edx, [io_addr]
add edx, MID_0L
.mac:
in ax, dx
stosw
add edx, 2
dec ecx
jnz .mac
; Some bootloaders/BIOSes do not initialize
; MAC address, warn about that
and eax, 0xFF
or eax, [node_addr]
test eax, eax
jnz @f
DEBUGF 1, "K : MAC address not initialized\n" ;, generating random"
;Asper: Add here generate function call!
; Temporary workaround: init by constant adress
mov dword [node_addr], 0x00006000
mov word [node_addr+4], 0x0001
@@:
; Init RDC private data
mov [r6040_private.mcr0], 0x1002
;mov [r6040_private.phy_addr], 1 ; Asper: Only one network card is supported now.
mov [r6040_private.switch_sig], 0
 
; Check the vendor ID on the PHY, if 0xFFFF assume none attached
stdcall r6040_phy_read, 1, 2
cmp ax, 0xFFFF
jne @f
DEBUGF 1, "K : Failed to detect an attached PHY\n" ;, generating random"
mov eax, -1
ret
@@:
 
; Set MAC address
call r6040_mac_address
 
 
; Initialize and alloc RX/TX buffers
stdcall r6040_init_ring_desc, r6040_tx_ring, TX_RING_SIZE
call r6040_init_rxbufs ;r6040_alloc_rxbufs
test eax, eax
jnz .out
 
; Read the PHY ID
mov [r6040_private.phy_mode], 0x8000
stdcall r6040_phy_read, 0, 2
mov [r6040_private.switch_sig], ax
cmp ax, ICPLUS_PHY_ID
jne @f
stdcall r6040_phy_write, 29, 31, 0x175C ; Enable registers
jmp .phy_readen
@@:
 
; PHY Mode Check
movzx eax, [r6040_private.phy_addr]
stdcall r6040_phy_write, eax, 4, PHY_CAP
stdcall r6040_phy_write, eax, 0, PHY_MODE
; if PHY_MODE = 0x3100
call r6040_phy_mode_chk
mov [r6040_private.phy_mode], ax
jmp .phy_readen
; end if
; if not (PHY_MODE and 0x0100)
mov [r6040_private.phy_mode], 0
; end if
.phy_readen:
 
; Set duplex mode
mov ax, [r6040_private.phy_mode]
or [r6040_private.mcr0], ax
 
; improve performance (by RDC guys)
stdcall r6040_phy_read, 30, 17
or ax, 0x4000
stdcall r6040_phy_write, 30, 17, eax
 
stdcall r6040_phy_read, 30, 17
xor ax, -1
or ax, 0x2000
xor ax, -1
stdcall r6040_phy_write, 30, 17, eax
 
stdcall r6040_phy_write, 0, 19, 0x0000
stdcall r6040_phy_write, 0, 30, 0x01F0
 
; Initialize all Mac registers
call r6040_reset
 
xor eax, eax
.out:
ret
 
 
 
 
 
 
align 4
r6040_reset:
 
DEBUGF 1, "Resetting r6040\n"
 
push eax ecx edx
; Mask off Interrupt
mov eax, MSK_INT
mov edx, [io_addr]
add edx, MIER
out dx, ax
 
;Reset RDC MAC
mov eax, MAC_RST
mov edx, [io_addr]
add edx, MCR1
out dx, ax
 
mov ecx, 2048 ;limit
.read:
in ax, dx
test ax, 0x1
jnz @f
dec ecx
test ecx, ecx
jnz .read
@@:
;Reset internal state machine
mov ax, 2
mov edx, [io_addr]
add edx, MAC_SM
out dx, ax
xor ax, ax
out dx, ax
mov esi, 5
call delay_ms
 
;MAC Bus Control Register
mov ax, MBCR_DEFAULT
mov edx, [io_addr]
add edx, MBCR
out dx, ax
 
;Buffer Size Register
mov ax, MAX_BUF_SIZE
mov edx, [io_addr]
add edx, MR_BSR
out dx, ax
 
;Write TX ring start address
mov eax, r6040_tx_ring - OS_BASE ;Asper: Maybe we can just write dword? Hidnplayr: better use word, as described in datasheet.
mov edx, [io_addr]
add edx, MTD_SA0
out dx, ax
shr eax, 16
add edx, MTD_SA1 - MTD_SA0
out dx, ax
 
;Write RX ring start address
mov eax, r6040_rx_ring - OS_BASE ;Asper: Maybe we can just write dword?
mov edx, [io_addr]
add edx, MRD_SA0
out dx, ax
shr eax, 16
add edx, MRD_SA1 - MRD_SA0
out dx, ax
 
;Set interrupt waiting time and packet numbers
xor ax, ax
mov edx, [io_addr]
add edx, MT_ICR
out dx, ax
 
;Asper: ~ Disable ints ;Enable interrupts
;mov ax, MSK_INT ;INT_MASK ;Asper ~
;mov edx, [io_addr]
;add edx, MIER
;out dx, ax
 
;Enable TX and RX
mov ax, [r6040_private.mcr0]
or ax, 0x0002
mov edx, [io_addr]
out dx, ax
 
;Let TX poll the descriptors
;we may got called by r6040_tx_timeout which has left
;some unset tx buffers
xor ax, ax
inc ax
mov edx, [io_addr]
add edx, MTPR
out dx, ax
 
pop edx ecx eax
 
DEBUGF 1, "reset ok!\n"
 
; Indicate that we have successfully reset the card
mov eax, [pci_data]
mov [eth_status], eax
ret
 
 
 
proc r6040_tx_timeout
push eax edx
;...
inc [stats.tx_errors]
;Reset MAC and re-init all registers
call r6040_init_mac_regs
pop edx eax
ret
endp
 
proc r6040_get_stats
push eax edx
mov edx, [io_addr]
add edx, ME_CNT1
in al, dx
add [stats.rx_crc_errors], al
mov edx, [io_addr]
add edx, ME_CNT0
in al, dx
add [stats.multicast], al
pop edx eax
ret
endp
 
;...
 
proc r6040_phy_mode_chk
push ebx
;PHY Link Status Check
movzx eax, [r6040_private.phy_addr]
stdcall r6040_phy_read, eax, 1
test eax, 0x4
jnz @f
mov eax, 0x8000 ;Link Failed, full duplex
@@:
;PHY Chip Auto-Negotiation Status
movzx eax, [r6040_private.phy_addr]
stdcall r6040_phy_read, eax, 1
test eax, 0x0020
jz .force_mode
;Auto Negotuiation Mode
movzx eax, [r6040_private.phy_addr]
stdcall r6040_phy_read, eax, 5
mov ebx, eax
movzx eax, [r6040_private.phy_addr]
stdcall r6040_phy_read, eax, 4
and eax, ebx
test eax, 0x140
jz .ret_0
jmp .ret_0x8000
.force_mode:
;Force Mode
movzx eax, [r6040_private.phy_addr]
stdcall r6040_phy_read, eax, 0
test eax, 0x100
jz .ret_0
.ret_0x8000:
mov eax, 0x8000
pop ebx
ret
.ret_0:
xor eax, eax
pop ebx
ret
endp
 
 
 
;***************************************************************************
; Function
; r6040_rx
; Description
; polls card to see if there is a packet waiting
;
; Currently only supports one descriptor per packet, if packet is fragmented
; between multiple descriptors you will lose part of the packet
;***************************************************************************
r6040_poll:
push ebx ecx esi edi
 
xor eax, eax
mov [eth_rx_data_len], ax
 
movzx eax, [r6040_private.cur_rx]
mov ebx, eax
shl ebx, 5
 
mov cx, [ebx+r6040_rx_ring+r6040_x_head.status] ; Read the descriptor status
test cx, DSC_OWNER_MAC
jnz .out
 
test cx, DSC_RX_ERR ; Global error status set
jz .no_dsc_rx_err
;...
jmp .out
 
.no_dsc_rx_err:
; Packet successfully received
movzx ecx, [ebx+r6040_rx_ring+r6040_x_head.len]
and ecx, 0xFFF
sub ecx, 4 ; Do not count the CRC
mov [eth_rx_data_len], cx
mov esi, [ebx+r6040_rx_ring+r6040_x_head.skb_ptr]
 
push ecx
shr ecx, 2
mov edi, Ether_buffer
cld
rep movsd
pop ecx
and ecx, 3
rep movsb
 
or [ebx+r6040_rx_ring+r6040_x_head.status], DSC_OWNER_MAC
 
inc [r6040_private.cur_rx]
and [r6040_private.cur_rx], RX_RING_SIZE-1
 
xor eax, eax
.out:
pop edi esi ecx ebx
ret
 
 
 
;***************************************************************************
; Function
; r6040_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
;
;***************************************************************************
r6040_transmit:
cmp ecx, MAX_BUF_SIZE
jg .out ; packet is too long
 
push edi esi ebx ecx
 
movzx eax, [r6040_private.cur_tx]
shl eax, 5
 
; DEBUGF 1,"R6040: TX buffer status: 0x%x, eax=%u\n", [eax + r6040_tx_ring + r6040_x_head.status]:4, eax
 
test [r6040_tx_ring + eax + r6040_x_head.status], 0x8000 ; check if buffer is available
jz .l3
 
push ecx esi
mov ecx, [timer_ticks]
add ecx, 100
.l2:
test [r6040_tx_ring + eax + r6040_x_head.status], 0x8000
jz .l5
cmp ecx, [timer_ticks]
jb .l4
mov esi, 10
call delay_ms
jmp .l2
 
.l4:
pop esi ecx
DEBUGF 1,"R6040: Send timeout\n"
jmp .out
 
.l5:
pop esi ecx
.l3:
push eax
 
mov esi, edi
 
; point to the current tx buffer
movzx edi, [r6040_private.cur_tx]
imul edi, MAX_BUF_SIZE
add edi, r6040_txb
lea eax, [edi - OS_BASE] ; real buffer address in eax
 
; copy destination address
movsd
movsw
; copy source address
mov esi, node_addr
movsd
movsw
; copy packet type
mov [edi], bx
add edi, 2
 
mov esi, [esp+8+4]
mov ecx, [esp+4]
; copy the packet data
push ecx
shr ecx, 2
rep movsd
pop ecx
and ecx, 3
rep movsb
 
pop edi
 
mov ecx, [esp]
add ecx, ETH_HLEN
cmp cx, ETH_ZLEN
jae @f
mov cx, ETH_ZLEN
@@:
 
mov [r6040_tx_ring + edi + r6040_x_head.len], cx
mov [r6040_tx_ring + edi + r6040_x_head.buf], eax
mov [r6040_tx_ring + edi + r6040_x_head.status], 0x8000
 
; Trigger the MAC to check the TX descriptor
mov ax, 0x01
mov edx, [io_addr]
add edx, MTPR
out dx, ax
 
inc [r6040_private.cur_tx]
and [r6040_private.cur_tx], TX_RING_SIZE-1
xor eax, eax
 
pop ecx ebx esi edi
.out:
ret
 
 
 
r6040_mac_address:
push eax ecx edx esi edi
; MAC operation register
mov ax, 1
mov edx, [io_addr]
add edx, MCR1
out dx, ax
; Reset MAC
mov ax, 2
mov edx, [io_addr]
add edx, MAC_SM
out dx, ax
; Reset internal state machine
xor ax, ax
out dx, ax
mov esi, 5
call delay_ms
 
; Restore MAC Address
mov ecx, 3
mov edi, node_addr
mov edx, [io_addr]
add edx, MID_0L
.mac:
in ax, dx
stosw
add edx, 2
dec ecx
jnz .mac
 
pop edi esi edx ecx eax
ret
 
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers
Property changes:
Added: svn:ignore
+*.mnt
+lang.inc
+*.bat
+out.txt
+scin*
+*.obj
/kernel/branches/Kolibri-acpi/network/eth_drv/arp.inc
0,0 → 1,557
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ARP.INC ;;
;; ;;
;; Address Resolution Protocol ;;
;; ;;
;; This file contains the following: ;;
;; arp_table_manager - Manages an ARPTable ;;
;; arp_request - Sends an ARP request on the ethernet ;;
;; arp_handler - Called when an ARP packet is received ;;
;; ;;
;; Changes history: ;;
;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;;
;; 11.11.2006 - [Johnny_B] and [smb] ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
ARP_NO_ENTRY equ 0
ARP_VALID_MAPPING equ 1
ARP_AWAITING_RESPONSE equ 2
ARP_RESPONSE_TIMEOUT equ 3
 
struc ARP_ENTRY ;=14 bytes
{ .IP dd ? ;+00
.MAC dp ? ;+04
.Status dw ? ;+10
.TTL dw ? ;+12 : ( in seconds )
}
 
virtual at 0
ARP_ENTRY ARP_ENTRY
end virtual
 
; The TTL field is decremented every second, and is deleted when it
; reaches 0. It is refreshed every time a packet is received
; If the TTL field is 0xFFFF it is a static entry and is never deleted
; The status field can be the following values:
; 0x0000 entry not used
; 0x0001 entry holds a valid mapping
; 0x0002 entry contains an IP address, awaiting ARP response
; 0x0003 No response received to ARP request.
; The last status value is provided to allow the network layer to delete
; a packet that is queued awaiting an ARP response
 
 
; The follow is the ARP Table.
; This table must be manually updated and the kernel recompilied if
; changes are made to it.
; Empty entries are filled with zeros
 
ARP_ENTRY_SIZE equ 14 ; Number of bytes per entry
ARP_TABLE_SIZE equ 20 ; Size of table
ARP_TABLE_ENTRIES equ 0 ; Number of static entries in the table
 
;TO ADD A STATIC ENTRY, DONT FORGET, PUT "ARPTable" from "uglobal" to "iglobal"!!!
;AND ALSO - IP and MAC have net byte-order, BUT STATUS AND TTL HAVE A MIRROR BYTE-ORDER!!!
uglobal
ARPTable:
;example, static entry -> db 11,22,33,44, 0x11,0x22,0x33,0x44,0x55,0x66, 0x01,0x00, 0xFF,0xFF
times ( ARP_TABLE_SIZE - ARP_TABLE_ENTRIES ) * ARP_ENTRY_SIZE db 0
endg
 
iglobal
NumARP:
dd ARP_TABLE_ENTRIES
ARPTable_ptr dd ARPTable ;pointer to ARPTable
endg
 
ARP_REQ_OPCODE equ 0x0100 ;request
ARP_REP_OPCODE equ 0x0200 ;reply
 
struc ARP_PACKET
{ .HardwareType dw ? ;+00
.ProtocolType dw ? ;+02
.HardwareSize db ? ;+04
.ProtocolSize db ? ;+05
.Opcode dw ? ;+06
.SenderMAC dp ? ;+08
.SenderIP dd ? ;+14
.TargetMAC dp ? ;+18
.TargetIP dd ? ;+24
}
 
virtual at 0
ARP_PACKET ARP_PACKET
end virtual
 
 
 
;***************************************************************************
; Function
; arp_table_manager [by Johnny_B]
;
; Description
; Does a most required operations with ARP-table
; IN:
; Operation: see Opcode's constants below
; Index: Index of entry in the ARP-table
; Extra: Extra parameter for some Opcodes
; OUT:
; EAX = Returned value depends on opcodes, more detailed see below
;
;***************************************************************************
;Opcode's constants
ARP_TABLE_ADD equ 1
ARP_TABLE_DEL equ 2
ARP_TABLE_GET equ 3
ARP_TABLE_GET_ENTRIES_NUMBER equ 4
ARP_TABLE_IP_TO_MAC equ 5
ARP_TABLE_TIMER equ 6
 
;Index's constants
EXTRA_IS_ARP_PACKET_PTR equ 0 ;if Extra contain pointer to ARP_PACKET
EXTRA_IS_ARP_ENTRY_PTR equ -1 ;if Extra contain pointer to ARP_ENTRY
 
align 4
proc arp_table_manager stdcall uses ebx esi edi ecx edx,\
Opcode:DWORD,Index:DWORD,Extra:DWORD
 
mov ebx, dword[ARPTable_ptr];ARPTable base
mov ecx, dword[NumARP] ;ARP-entries counter
 
mov eax, dword[Opcode]
cmp eax, ARP_TABLE_TIMER
je .timer
cmp eax, ARP_TABLE_ADD
je .add
cmp eax, ARP_TABLE_DEL
je .del
cmp eax, ARP_TABLE_GET
je .get
cmp eax, ARP_TABLE_IP_TO_MAC
je .ip_to_mac
cmp eax, ARP_TABLE_GET_ENTRIES_NUMBER
je .get_entries_number
jmp .exit ;if unknown opcode
 
 
;;BEGIN TIMER
;;Description: it must be callback every second. It is responsible for removing expired routes.
;;IN: Operation: ARP_TABLE_TIMER
;; Index: must be zero
;; Extra: must be zero
;;OUT:
;; EAX=not defined
;;
.timer:
test ecx, ecx
jz .exit;if NumARP=0 nothing to do
sub ecx, ARP_TABLE_ENTRIES;ecx=dynamic entries number
jz .exit;if NumARP=number of static entries then exit
 
add ebx, ARP_TABLE_ENTRIES*ARP_ENTRY_SIZE;ebx=dynamic entries base
 
.timer_loop:
movsx esi, word [ebx + ARP_ENTRY.TTL]
cmp esi, 0xFFFFFFFF
je .timer_loop_end;if TTL==0xFFFF then it's static entry
 
test esi, esi
jnz .timer_loop_end_with_dec;if TTL!=0
 
; Ok, TTL is 0
;if Status==AWAITING_RESPONSE and TTL==0
;then we have to change it to ARP_RESPONSE_TIMEOUT
cmp word [ebx + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE
jne @f
 
mov word [ebx + ARP_ENTRY.Status], ARP_RESPONSE_TIMEOUT
mov word [ebx + ARP_ENTRY.TTL], word 0x000A;10 sec
jmp .timer_loop_end
 
@@:
;if TTL==0 and Status==VALID_MAPPING, we have to delete it
;if TTL==0 and Status==RESPONSE_TIMEOUT, delete too
mov esi, dword[NumARP]
sub esi, ecx ;esi=index of entry, will be deleted
stdcall arp_table_manager, ARP_TABLE_DEL, esi, 0;opcode,index,extra
jmp .timer_loop_end
 
 
.timer_loop_end_with_dec:
dec word [ebx + ARP_ENTRY.TTL];decrease TTL
.timer_loop_end:
add ebx, ARP_ENTRY_SIZE
loop .timer_loop
 
jmp .exit
;;END TIMER
 
;;BEGIN ADD
;;Description: it adds an entry in the table. If ARP-table already
;; contains same IP, it will be updated.
;;IN: Operation: ARP_TABLE_ADD
;; Index: specifies what contains Extra-parameter
;; Extra: if Index==EXTRA_IS_ARP_PACKET_PTR,
;; then Extra contains pointer to ARP_PACKET,
;; otherwise Extra contains pointer to ARP_ENTRY
;;OUT:
;; EAX=index of entry, that has been added
;;
.add:
 
sub esp, ARP_ENTRY_SIZE;Allocate ARP_ENTRY_SIZE byte in stack
 
mov esi, [Extra];pointer
mov edi, [Index];opcode
 
cmp edi, EXTRA_IS_ARP_PACKET_PTR
je .arp_packet_to_entry;if Extra contain ptr to ARP_PACKET and we have to form arp-entry
;else it contain ptr to arp-entry
 
cld
; esi already has been loaded
mov edi, esp ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add)
mov ecx, ARP_ENTRY_SIZE/2;ARP_ENTRY_SIZE must be even number!!!
rep movsw ;copy
jmp .search
 
.arp_packet_to_entry:
mov edx, dword[esi + ARP_PACKET.SenderIP];esi=base of ARP_PACKET
mov [esp + ARP_ENTRY.IP], edx
 
cld
lea esi, [esi + ARP_PACKET.SenderMAC]
lea edi, [esp + ARP_ENTRY.MAC]
movsd
movsw
mov word[esp + ARP_ENTRY.Status], ARP_VALID_MAPPING; specify the type - a valid entry
mov word[esp + ARP_ENTRY.TTL], 0x0E10; = 1 hour
 
.search:
mov edx, dword[esp + ARP_ENTRY.IP];edx=IP-address, which we'll search
mov ecx, dword[NumARP] ;ecx=ARP-entries counter
jecxz .add_to_end ;if ARP-entries number == 0
imul eax, ecx, ARP_ENTRY_SIZE ;eax=current table size(in bytes)
@@:
sub eax, ARP_ENTRY_SIZE
cmp dword[ebx + eax + ARP_ENTRY.IP], edx
loopnz @b
jz .replace ; found, replace existing entry, ptr to it is in eax
 
.add_to_end:
;else add to end
or eax, -1;set eax=0xFFFFFFFF if adding is impossible
mov ecx, dword[NumARP]
cmp ecx, ARP_TABLE_SIZE
je .add_exit;if arp-entries number is equal to arp-table maxsize
 
imul eax, dword[NumARP], ARP_ENTRY_SIZE;eax=ptr to end of ARPTable
inc dword [NumARP];increase ARP-entries counter
 
.replace:
cld
mov esi, esp ;esp=base of ARP-entry, that will be added
lea edi, [ebx + eax] ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add)
mov ecx, ARP_ENTRY_SIZE/2;ARP_ENTRY_SIZE must be even number!!!
rep movsw
 
mov ecx, ARP_ENTRY_SIZE
xor edx, edx;"div" takes operand from EDX:EAX
div ecx ;eax=index of entry, which has been added
 
.add_exit:
add esp, ARP_ENTRY_SIZE;free stack
jmp .exit
;;END ADD
 
;;BEGIN DEL
;;Description: it deletes an entry in the table.
;;IN: Operation: ARP_TABLE_DEL
;; Index: index of entry, that should be deleted
;; Extra: must be zero
;;OUT:
;; EAX=not defined
;;
.del:
mov esi, [Index]
imul esi, ARP_ENTRY_SIZE
 
mov ecx, (ARP_TABLE_SIZE - 1) * ARP_ENTRY_SIZE
sub ecx, esi
 
lea edi, [ebx + esi] ;edi=ptr to entry that should be deleted
lea esi, [edi + ARP_ENTRY_SIZE];esi=ptr to next entry
 
shr ecx, 1 ;ecx/2 => ARP_ENTRY_SIZE MUST BE EVEN NUMBER!
cld
rep movsw
 
dec dword[NumARP];decrease arp-entries counter
jmp .exit
;;END DEL
 
;;BEGIN GET
;;Description: it reads an entry of table into buffer.
;;IN: Operation: ARP_TABLE_GET
;; Index: index of entry, that should be read
;; Extra: pointer to buffer for reading(size must be equal to ARP_ENTRY_SIZE)
;;OUT:
;; EAX=not defined
;;
.get:
mov esi, [Index]
imul esi, ARP_ENTRY_SIZE;esi=ptr to required ARP_ENTRY
mov edi, [Extra] ;edi=buffer for reading
mov ecx, ARP_ENTRY_SIZE/2; must be even number!!!
cld
rep movsw
jmp .exit
;;END GET
 
;;BEGIN IP_TO_MAC
;;Description: it gets an IP from Index, scans each entry in the table and writes
;; MAC, that relates to specified IP, into buffer specified in Extra.
;; And if it cannot find an IP-address in the table, it does an ARP-request of that.
;;IN: Operation: ARP_TABLE_IP_TO_MAC
;; Index: IP that should be transformed into MAC
;; Extra: pointer to buffer where will be written the MAC-address.
;;OUT:
;; EAX=ARP table entry status code.
;; If EAX==ARP_NO_ENTRY, IP isn't found in the table and we have sent the request.
;; If EAX==ARP_AWAITING_RESPONSE, we wait the response from remote system.
;; If EAX==ARP_RESPONSE_TIMEOUT, remote system not responds too long.
;; If EAX==ARP_VALID_MAPPING, all is ok, we've got a true MAC.
;;
;; If MAC will equal to a zero, in the buffer. It means, that IP-address was not yet
;; resolved, or that doesn't exist. I recommend you, to do at most 3-5 calls of this
;; function with 1sec delay. sure, only if it not return a valid MAC after a first call.
;;
.ip_to_mac:
 
xor eax, eax
mov edi, dword[Extra]
cld
stosd
stosw
 
 
; first, check destination IP to see if it is on 'this' network.
; The test is:
; if ( destIP & subnet_mask == stack_ip & subnet_mask )
; destination is local
; else
; destination is remote, so pass to gateway
 
mov eax, [Index] ;eax=required IP
mov esi, eax
and esi, [subnet_mask]
mov ecx, [stack_ip]
and ecx, [subnet_mask]
cmp esi, ecx
je @f ;if we and target IP are located in the same network
mov eax, [gateway_ip]
mov [Index], eax
@@:
 
cmp dword[NumARP], 0
je .ip_to_mac_send_request;if ARP-table not contain an entries, we have to request IP.
;EAX will be containing a zero, it's equal to ARP_NO_ENTRY
 
mov ecx, dword[NumARP]
imul esi, ecx, ARP_ENTRY_SIZE;esi=current ARP-table size
 
@@:
sub esi, ARP_ENTRY_SIZE
cmp [ebx + esi], eax ; ebx=ARPTable base
loopnz @b ; Return back if non match
jnz .ip_to_mac_send_request; and request IP->MAC if none found in the table
 
; Return the entry status in eax
movzx eax, word[ebx + esi + ARP_ENTRY.Status]
 
; esi holds index
cld
lea esi, [ebx + esi + ARP_ENTRY.MAC]
mov edi, [Extra];edi=ptr to buffer for write MAC
movsd
movsw
jmp .exit
 
.ip_to_mac_send_request:
stdcall arp_request, [Index], stack_ip, node_addr;TargetIP,SenderIP_ptr,SenderMAC_ptr
mov eax, ARP_NO_ENTRY
jmp .exit
 
;;END IP_TO_MAC
 
;;BEGIN GET_ENTRIES_NUMBER
;;Description: returns an ARP-entries number in the ARPTable
;;IN: Operation: ARP_TABLE_GET_ENTRIES_NUMBER
;; Index: must be zero
;; Extra: must be zero
;;OUT:
;; EAX=ARP-entries number in the ARPTable
.get_entries_number:
mov eax, dword[NumARP]
jmp .exit
;;END GET_ENTRIES_NUMBER
 
.exit:
ret
endp
 
 
;***************************************************************************
; Function
; arp_handler
;
; Description
; Called when an ARP packet is received on the ethernet
; Header + Data is in Ether_buffer[]
; It looks to see if the packet is a request to resolve this Hosts
; IP address. If it is, send the ARP reply packet.
; This Hosts IP address is in dword [stack_ip] ( in network format )
; This Hosts MAC address is in node_addr[6]
; All registers may be destroyed
;
;***************************************************************************
arp_handler:
; Is this a REQUEST?
; Is this a request for My Host IP
; Yes - So construct a response message.
; Send this message to the ethernet card for transmission
 
stdcall arp_table_manager, ARP_TABLE_ADD, EXTRA_IS_ARP_PACKET_PTR, ETH_FRAME.Data + ARP_PACKET
 
inc dword[arp_rx_count];increase ARP-packets counter
 
cmp word[ETH_FRAME.Data + ARP_PACKET.Opcode], ARP_REQ_OPCODE; Is this a request packet?
jne .exit ; No - so exit
 
mov eax, [stack_ip]
cmp eax, dword[ETH_FRAME.Data + ARP_PACKET.TargetIP] ; Is it looking for my IP address?
jne .exit ; No - so quit now
 
; OK, it is a request for my MAC address. Build the frame and send it
; We can reuse the packet.
 
mov word[ETH_FRAME.Data + ARP_PACKET.Opcode], ARP_REP_OPCODE
 
cld
mov esi, ETH_FRAME.Data + ARP_PACKET.SenderMAC
mov edi, ETH_FRAME.Data + ARP_PACKET.TargetMAC
movsd
movsw
 
mov esi, ETH_FRAME.Data + ARP_PACKET.SenderIP
mov edi, ETH_FRAME.Data + ARP_PACKET.TargetIP
movsd
 
mov esi, node_addr
mov edi, ETH_FRAME.Data + ARP_PACKET.SenderMAC
movsd
movsw
 
mov esi, stack_ip
mov edi, ETH_FRAME.Data + ARP_PACKET.SenderIP
movsd
 
; Now, send it!
mov edi, ETH_FRAME.Data + ARP_PACKET.TargetMAC;ptr to destination MAC address
mov bx, ETHER_ARP ;type of protocol
mov ecx, 28 ;data size
mov esi, ETH_FRAME.Data + ARP_PACKET ;ptr to data
push ebp
call dword [drvr_transmit] ;transmit packet
pop ebp
 
.exit:
ret
 
 
;***************************************************************************
; Function
; arp_request [by Johnny_B]
;
; Description
; Sends an ARP request on the ethernet
; IN:
; TargetIP : requested IP address
; SenderIP_ptr : POINTER to sender's IP address(our system's address)
; SenderMAC_ptr : POINTER to sender's MAC address(our system's address)
; OUT:
; EAX=0 (if all is ok), otherwise EAX is not defined
;
; EBX,ESI,EDI will be saved
;
;***************************************************************************
proc arp_request stdcall uses ebx esi edi,\
TargetIP:DWORD, SenderIP_ptr:DWORD, SenderMAC_ptr:DWORD
 
inc dword[arp_tx_count]; increase counter
 
sub esp, 28; allocate memory for ARP_PACKET
 
mov word[esp + ARP_PACKET.HardwareType], 0x0100;Ethernet
mov word[esp + ARP_PACKET.ProtocolType], 0x0008;IP
mov byte[esp + ARP_PACKET.HardwareSize], 0x06;MAC-addr length
mov byte[esp + ARP_PACKET.ProtocolSize], 0x04;IP-addr length
mov word[esp + ARP_PACKET.Opcode], 0x0100 ;Request
 
cld
mov esi, [SenderMAC_ptr]
lea edi, [esp + ARP_PACKET.SenderMAC] ;Our MAC-addr
movsd
movsw
 
mov esi, [SenderIP_ptr]
lea edi, [esp + ARP_PACKET.SenderIP] ;Our IP-addr
movsd
 
xor eax, eax
lea edi, [esp + ARP_PACKET.TargetMAC] ;Required MAC-addr(zeroed)
stosd
stosw
 
mov esi, dword[TargetIP]
mov dword[esp + ARP_PACKET.TargetIP], esi;Required IP-addr(we get it as function parameter)
 
; Now, send it!
mov edi, broadcast_add ; Pointer to 48 bit destination address
mov bx, ETHER_ARP ; Type of packet
mov ecx, 28 ; size of packet
lea esi, [esp + ARP_PACKET]; pointer to packet data
push ebp
call dword [drvr_transmit]; Call the drivers transmit function
pop ebp
 
add esp, 28; free memory, allocated before for ARP_PACKET
 
; Add an entry in the ARP table, awaiting response
sub esp, ARP_ENTRY_SIZE;allocate memory for ARP-entry
 
mov esi, dword[TargetIP]
mov dword[esp + ARP_ENTRY.IP], esi
 
lea edi, [esp + ARP_ENTRY.MAC]
xor eax, eax
stosd
stosw
 
mov word[esp + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE
mov word[esp + ARP_ENTRY.TTL], 0x000A; 10 seconds
 
stdcall arp_table_manager, ARP_TABLE_ADD, EXTRA_IS_ARP_ENTRY_PTR, esp
add esp, ARP_ENTRY_SIZE; free memory
 
.exit:
ret
endp
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/ethernet.inc
0,0 → 1,525
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ETHERNET.INC ;;
;; ;;
;; Ethernet network layer for Menuet OS ;;
;; ;;
;; This file contains the following: ;;
;; PCI bus scanning for valid devices ;;
;; Table of supported ethernet drivers ;;
;; Code to identify and activate a supported driver ;;
;; ARP handler ;;
;; Driver interface to the IP layer ;;
;; Gateway support ;;
;; ;;
;; Individual driver files are included here ;;
;; ;;
;; The PCI bus scanning code was ported from the etherboot ;;
;; 5.0.6 project. The copyright statement for that code is ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; remaining parts Copyright 2002 Mike Hibbett ;;
;; mikeh@oceanfree.net ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
;********************************************************************
; Interface
; ethernet_driver called by stack_handler in stack.inc
; eth_probe called by app_stack_handler in stack.inc
;
;********************************************************************
 
ETHER_IP equ 0x0008 ; Reversed from 0800 for intel
ETHER_ARP equ 0x0608 ; Reversed from 0806 for intel
ETHER_RARP equ 0x3580
 
struc ETH_FRAME
{ .DstMAC dp ? ;destination MAC-address [6 bytes]
.SrcMAC dp ? ;source MAC-address [6 bytes]
.Type dw ? ;type of the upper-layer protocol [2 bytes]
.Data db ? ;data [46-1500 bytes]
}
 
virtual at Ether_buffer
ETH_FRAME ETH_FRAME
end virtual
 
 
; Some useful information on data structures
 
; Ethernet Packet - ARP Request example
;
; 0 1 2 3
; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
;
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | Dest H/W Address |
; | ( 14 byte header ) |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | | Source H/W Address |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | Protocol - ARP 08 06 |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | H/W Type 00 01 | Protocol Type 08 00 |
; | ( ARP Request packet ) |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | HLen 0x06 | PLen 0x04 | OpCode 00 01 |
; | ( 0001 for request, 0002 for reply ) |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | Source Hardware Address ( MAC Address ) |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | | Source IP Address |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | | Destination Hardware Address |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | Destination IP Address |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
; Include individual drivers source files at this point.
; If you create a new driver, include it below.
 
include "drivers/rtl8029.inc"
include "drivers/i8255x.inc"
include "drivers/rtl8139.inc"
include "drivers/3c59x.inc"
include "drivers/sis900.inc"
include "drivers/pcnet32.inc"
include "drivers/rtl8169.inc"
include "drivers/forcedeth.inc"
include "drivers/r6040.inc"
 
; PCICards
; ========
; PCI vendor and hardware types for hardware supported by the above drivers
; If you add a driver, ensure you update this datastructure, otherwise the
; card will not be probed.
; Each driver is defined by 4 double words. These are
; PCIVendorDevice probeFunction ResetFunction PollFunction transmitFunction
; The last entry must be kept at all zeros, to indicate the end of the list
; As a PCI driver may support more than one hardware implementation, there may
; be several lines which refer to the same functions.
; The first driver found on the PCI bus will be the one used.
 
PCICARDS_ENTRY_SIZE equ 24 ; Size of each PCICARDS entry
 
iglobal
PCICards:
dd 0x12098086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0
dd 0x10298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0
dd 0x12298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0
dd 0x10308086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0
dd 0x24498086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0
dd 0x10688086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0
 
dd 0x802910ec, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit, 0
 
dd 0x813910ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0x813810ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0x12111113, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0x13601500, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0x13604033, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0x13001186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0x13401186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0xab0613d1, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0xa1171259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0xa11e1259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0xab0614ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0xab0714ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0x123411db, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0x91301432, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0x101202ac, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0x0106018a, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0x1211126c, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0x81391743, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
dd 0x8139021b, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
 
dd 0x816810ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0
dd 0x816910ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0
dd 0x011616ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0
dd 0x43001186, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0
dd 0x816710ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0
 
dd 0x590010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x592010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x597010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x595010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x595110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x595210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x900010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x900110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x900410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x900510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x900610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x900A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x905010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x905110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x905510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x905810b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x905A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x920010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x980010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x980510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x764610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x505510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x605510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x605610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x5b5710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x505710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x515710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x525710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x656010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x656210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x656410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
dd 0x450010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
 
dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0
dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0
 
dd 0x20001022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0
dd 0x26251022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0
dd 0x20011022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0
 
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
dd 0x03e510de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x03e610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x03ee10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x03ef10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x045010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x045110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x045210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x045310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x054c10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x054d10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x054e10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x054f10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x07dc10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x07dd10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x07de10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x07df10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x076010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; MCP77 Ethernet Controller
dd 0x076110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x076210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x076310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x0ab010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x0ab110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x0ab210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x0ab310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
dd 0x0d7d10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
 
dd 0x604017F3, r6040_probe, r6040_reset, r6040_poll, r6040_transmit, 0
 
rb PCICARDS_ENTRY_SIZE ; end of list marker, do not remove
endg
 
uglobal
;Net-stack's interface's settings
node_addr:
db 0,0,0,0,0,0
gateway_ip:
dd 0
dns_ip:
dd 0
 
eth_rx_data_len:
dw 0
eth_status:
dd 0
io_addr:
dd 0
hdrtype:
db 0
vendor_device:
dd 0
pci_data:
dd 0
pci_dev:
dd 0
pci_bus:
dd 0
 
; These will hold pointers to the selected driver functions
drvr_probe:
dd 0
drvr_reset:
dd 0
drvr_poll:
dd 0
drvr_transmit:
dd 0
drvr_cable:
dd 0
 
endg
 
iglobal
broadcast_add:
db 0xff,0xff,0xff,0xff,0xff,0xff
subnet_mask:
dd 0x00ffffff ; 255.255.255.0
endg
 
include "arp.inc" ;arp-protocol functions
include "pci.inc" ;PCI bus access functions
 
 
;***************************************************************************
; Function
; eth_tx
;
; Description
; Looks at the NET1OUT_QUEUE for data to send.
; Stores that destination IP in a location used by the tx routine
; Looks up the MAC address in the ARP table; stores that where
; the tx routine can get it
; Get the length of the data. Store that where the tx routine wants it
; Call tx
; Places buffer on empty queue when the tx routine finished
;
;***************************************************************************
proc eth_tx stdcall uses ebx esi edi
local MACAddress dp ? ;allocate 6 bytes in the stack
 
; Look for a buffer to tx
mov eax, NET1OUT_QUEUE
call dequeue
cmp ax, NO_BUFFER
je .exit ; Exit if no buffer available
 
push eax;save buffer number
 
; convert buffer pointer eax to the absolute address
imul eax, IPBUFFSIZE
add eax, IPbuffs
 
; Extract the destination IP
; find the destination IP in the ARP table, get MAC
; store this MAC in 'MACAddress'
mov ebx, eax ; Save buffer address
mov edx, [ebx + 16] ; get destination address
 
; If the destination address is 255.255.255.255,
; set the MACAddress to all ones ( broadcast )
cld
mov esi, broadcast_add
lea edi, [MACAddress]
movsd
movsw
cmp edx, 0xffffffff
je .send ; If it is broadcast, just send
 
lea eax, [MACAddress];cause this is local variable
stdcall arp_table_manager, ARP_TABLE_IP_TO_MAC, edx, eax;opcode,IP,MAC_ptr - Get the MAC address.
 
cmp eax, ARP_VALID_MAPPING
je .send
 
; No valid entry. Has the request been sent, but timed out?
cmp eax, ARP_RESPONSE_TIMEOUT
je .freebuf
 
.wait_response: ;we wait arp-response
; Re-queue the packet, and exit
pop ebx
mov eax, NET1OUT_QUEUE
call queue ; Get the buffer back
jmp .exit
 
.send: ;if ARP_VALID_MAPPING then send the packet
lea edi, [MACAddress] ; Pointer to 48 bit destination address
movzx ecx, word[ebx+2] ; Size of IP packet to send
xchg ch, cl ; because mirror byte-order
mov esi, ebx ; Pointer to packet data
mov bx, ETHER_IP ; Type of packet
push ebp
call dword [drvr_transmit]; Call the drivers transmit function
pop ebp
 
; OK, we have sent a packet, so increment the count
inc dword [ip_tx_count]
 
; And finally, return the buffer to the free queue
.freebuf:
pop eax
call freeBuff
 
.exit:
ret
endp
 
;***************************************************************************
; Function
; ether_IP_handler
;
; Description
; Called when an IP ethernet packet is received on the ethernet
; Header + Data is in Ether_buffer[]
; We just need to get a buffer from the 'free' queue, and
; store the packet in it, then insert the packet number into the
; IPRX queue.
; If no queue entry is available, the packet is silently discarded
; All registers may be destroyed
;
;***************************************************************************
;uglobal
; ether_IP_handler_cnt dd ?
;endg
ether_IP_handler:
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je eiph00x
 
; convert buffer pointer eax to the absolute address
push eax
mov ecx, IPBUFFSIZE
mul ecx
add eax, IPbuffs
 
mov edi, eax
 
; get a pointer to the start of the DATA
mov esi, ETH_FRAME.Data
 
; Now store it all away
mov ecx, IPBUFFSIZE / 4 ; Copy all of the available
; data across - worse case
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
call queue
 
eiph00x:
ret
 
;***************************************************************************
; Function
; eth_probe
; Description
; Searches for an ethernet card. If found, the card is enabled and
; the ethernet -> IP link established
;
; This function scans the PCI bus looking for a supported device.
; ISA bus is currently not supported.
;
; eax is 0 if no hardware found
;***************************************************************************
eth_probe:
; Find a card on the PCI bus, and get it's address
call scan_bus ; Find the ethernet cards PIC address
xor eax, eax
cmp [io_addr], eax
je ep_00x ; Return 0 in eax if no cards found
 
call dword [drvr_probe] ; Call the drivers probe function
 
mov eax, [io_addr] ; return a non zero value
 
ep_00x:
ret
 
;***************************************************************************
; Function
; ethernet_driver
;
; Description
; The ethernet RX and TX handler
; This is a kernel function, called by stack_handler
;
;***************************************************************************
ethernet_driver:
; Do nothing if the driver is inactive
cmp [ethernet_active], byte 0
je eth_exit
 
call eth_rx
call eth_tx
 
eth_exit:
ret
 
;***************************************************************************
; Function
; eth_rx
;
; Description
; Polls the ethernet card for received data. Extracts if present
; Depending on the Protocol within the packet:
; ARP : Pass to ARP_handler. This may result in an ARP reply
; being tx'ed
; IP : Store in an IP buffer
;
;***************************************************************************
eth_rx:
xor ax, ax
mov [eth_rx_data_len], ax
call dword [drvr_poll] ; Call the drivers poll function
 
mov ax, [eth_rx_data_len]
cmp ax, 0
je .exit
 
 
; Check the protocol. Call appropriate handler
 
mov ax, [ETH_FRAME.Type]; The address of the protocol word
 
cmp ax, ETHER_IP
je .is_ip ; It's IP
 
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"
inc dword [ip_rx_count]
call ether_IP_handler
jmp .exit
 
.is_arp:
; DEBUGF 1,"K : eth_rx - ARP packet\n"
; At this point, the packet is still in the Ether_buffer
call arp_handler
 
.exit:
ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/pci.inc
0,0 → 1,351
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
;***************************************************************************
;
; PCI CODE FOLLOWS
;
; the following functions provide access to the PCI interface.
; These functions are used by scan_bus, and also some ethernet drivers
;
;***************************************************************************
 
; PCI Bus defines
PCI_HEADER_TYPE equ 0x0e ;8 bit
PCI_BASE_ADDRESS_0 equ 0x10 ;32 bit
PCI_BASE_ADDRESS_5 equ 0x24 ;32 bits
PCI_BASE_ADDRESS_SPACE_IO equ 0x01
PCI_VENDOR_ID equ 0x00 ;16 bit
PCI_BASE_ADDRESS_IO_MASK equ 0xFFFFFFFC
 
;***************************************************************************
; Function
; config_cmd
;
; Description
; creates a command dword for use with the PCI bus
; bus # in ebx
; devfn in ecx
; where in edx
;
; command dword returned in eax
; Only eax destroyed
;***************************************************************************
config_cmd:
push ecx
mov eax, ebx
shl eax, 16
or eax, 0x80000000
shl ecx, 8
or eax, ecx
pop ecx
or eax, edx
and eax, 0xFFFFFFFC
ret
 
;***************************************************************************
; Function
; pcibios_read_config_byte
;
; Description
; reads a byte from the PCI config space
; bus # in ebx
; devfn in ecx
; where in edx ( ls 16 bits significant )
;
; byte returned in al ( rest of eax zero )
; Only eax/edx destroyed
;***************************************************************************
pcibios_read_config_byte:
call config_cmd
push dx
mov dx, 0xCF8
out dx, eax
pop dx
 
xor eax, eax
and dx, 0x03
add dx, 0xCFC
; and dx, 0xFFC
in al, dx
ret
 
;***************************************************************************
; Function
; pcibios_read_config_word
;
; Description
; reads a word from the PCI config space
; bus # in ebx
; devfn in ecx
; where in edx ( ls 16 bits significant )
;
; word returned in ax ( rest of eax zero )
; Only eax/edx destroyed
;***************************************************************************
pcibios_read_config_word:
call config_cmd
push dx
mov dx, 0xCF8
out dx, eax
pop dx
 
xor eax, eax
and dx, 0x02
add dx, 0xCFC
; and dx, 0xFFC
in ax, dx
ret
 
;***************************************************************************
; Function
; pcibios_read_config_dword
;
; Description
; reads a dword from the PCI config space
; bus # in ebx
; devfn in ecx
; where in edx ( ls 16 bits significant )
;
; dword returned in eax
; Only eax/edx destroyed
;***************************************************************************
pcibios_read_config_dword:
push edx
call config_cmd
push dx
mov dx, 0xCF8
out dx, eax
pop dx
xor eax, eax
mov dx, 0xCFC
in eax, dx
pop edx
ret
 
;***************************************************************************
; Function
; pcibios_write_config_byte
;
; Description
; write a byte in al to the PCI config space
; bus # in ebx
; devfn in ecx
; where in edx ( ls 16 bits significant )
;
; Only eax/edx destroyed
;***************************************************************************
pcibios_write_config_byte:
push ax
call config_cmd
push dx
mov dx, 0xCF8
out dx, eax
pop dx
pop ax
 
and dx, 0x03
add dx, 0xCFC
out dx, al
ret
 
;***************************************************************************
; Function
; pcibios_write_config_word
;
; Description
; write a word in ax to the PCI config space
; bus # in ebx
; devfn in ecx
; where in edx ( ls 16 bits significant )
;
; Only eax/edx destroyed
;***************************************************************************
pcibios_write_config_word:
push ax
call config_cmd
push dx
mov dx, 0xCF8
out dx, eax
pop dx
pop ax
 
and dx, 0x02
add dx, 0xCFC
out dx, ax
ret
 
;***************************************************************************
; Function
; delay_us
;
; Description
; delays for 30 to 60 us
;
; I would prefer this routine to be able to delay for
; a selectable number of microseconds, but this works for now.
;
; If you know a better way to do 2us delay, pleae tell me!
;***************************************************************************
delay_us:
push eax
push ecx
 
mov ecx, 2
 
in al, 0x61
and al, 0x10
mov ah, al
cld
 
dcnt1:
in al, 0x61
and al, 0x10
cmp al, ah
jz dcnt1
 
mov ah, al
loop dcnt1
 
pop ecx
pop eax
 
ret
 
;***************************************************************************
; Function
; scan_bus
;
; Description
; Scans the PCI bus for a supported device
; If a supported device is found, the drvr_ variables are initialised
; to that drivers functions ( as defined in the PCICards table)
;
; io_addr holds card I/O space. 32 bit, but only LS 16 bits valid
; pci_data holds the PCI vendor + device code
; pci_dev holds PCI bus dev #
; pci_bus holds PCI bus #
;
; io_addr will be zero if no card found
;
;***************************************************************************
scan_bus:
xor eax, eax
mov [hdrtype], al
mov [pci_data], eax
 
xor ebx, ebx ; ebx = bus# 0 .. 255
 
sb_bus_loop:
xor ecx, ecx ; ecx = devfn# 0 .. 254 ( not 255? )
 
sb_devf_loop:
mov eax, ecx
and eax, 0x07
 
cmp eax, 0
jne sb_001
 
mov edx, PCI_HEADER_TYPE
call pcibios_read_config_byte
mov [hdrtype], al
jmp sb_002
 
sb_001:
mov al, [hdrtype]
and al, 0x80
cmp al, 0x80
jne sb_inc_devf
 
sb_002:
mov edx, PCI_VENDOR_ID
call pcibios_read_config_dword
mov [vendor_device], eax
cmp eax, 0xffffffff
je sb_empty
cmp eax, 0
jne sb_check_vendor
 
sb_empty:
mov [hdrtype], byte 0
jmp sb_inc_devf
 
sb_check_vendor:
; iterate though PCICards until end or match found
mov esi, PCICards
 
sb_check:
cmp [esi], dword 0
je sb_inc_devf ; Quit if at last entry
cmp eax, [esi]
je sb_got_card
add esi, PCICARDS_ENTRY_SIZE
jmp sb_check
 
sb_got_card:
; indicate that we have found the card
mov [pci_data], eax
mov [pci_dev], ecx
mov [pci_bus], ebx
 
; Define the driver functions
push eax
mov eax, [esi+4]
mov [drvr_probe], eax
mov eax, [esi+8]
mov [drvr_reset], eax
mov eax, [esi+12]
mov [drvr_poll], eax
mov eax, [esi+16]
mov [drvr_transmit], eax
mov eax, [esi+20]
mov [drvr_cable], eax
pop eax
 
mov edx, PCI_BASE_ADDRESS_0
 
sb_reg_check:
call pcibios_read_config_dword
mov [io_addr], eax
and eax, PCI_BASE_ADDRESS_IO_MASK
cmp eax, 0
je sb_inc_reg
mov eax, [io_addr]
and eax, PCI_BASE_ADDRESS_SPACE_IO
cmp eax, 0
je sb_inc_reg
 
mov eax, [io_addr]
and eax, PCI_BASE_ADDRESS_IO_MASK
mov [io_addr], eax
 
sb_exit1:
ret
 
sb_inc_reg:
add edx, 4
cmp edx, PCI_BASE_ADDRESS_5
jbe sb_reg_check
 
sb_inc_devf:
inc ecx
cmp ecx, 255
jb sb_devf_loop
inc ebx
cmp ebx, 256
jb sb_bus_loop
 
; We get here if we didn't find our card
; set io_addr to 0 as an indication
xor eax, eax
mov [io_addr], eax
 
sb_exit2:
ret
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv
Property changes:
Added: svn:ignore
+*.mnt
+lang.inc
+*.bat
+out.txt
+scin*
+*.obj
/kernel/branches/Kolibri-acpi/network/ip.inc
0,0 → 1,248
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; IP.INC ;;
;; ;;
;; IP Processes for Menuet OS TCP/IP stack ;;
;; ;;
;; Version 0.3 29 August 2002 ;;
;; ;;
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
 
; IP underlying protocols numbers
PROTOCOL_ICMP equ 1
PROTOCOL_TCP equ 6
PROTOCOL_UDP equ 17
 
struc IP_PACKET
{ .VersionAndIHL db ? ;+00 - Version[0-3 bits] and IHL(header length)[4-7 bits]
.TypeOfService db ? ;+01
.TotalLength dw ? ;+02
.Identification dw ? ;+04
.FlagsAndFragmentOffset dw ? ;+06 - Flags[0-2] and FragmentOffset[3-15]
.TimeToLive db ? ;+08
.Protocol db ? ;+09
.HeaderChecksum dw ? ;+10
.SourceAddress dd ? ;+12
.DestinationAddress dd ? ;+16
.DataOrOptional dd ? ;+20
}
 
virtual at 0
IP_PACKET IP_PACKET
end virtual
 
 
;*******************************************************************
; Interface
;
; ip_rx processes all packets received by the network layer
; It calls the appropriate protocol handler
;
;
;
;*******************************************************************
 
 
;
; IP Packet after reception - Normal IP packet format
;
; 0 1 2 3
; 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
;
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;0 |Version| IHL |Type of Service| Total Length |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;4 | Identification |Flags| Fragment Offset |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;8 | Time to Live | Protocol | Header Checksum |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;12 | Source Address |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;16 | Destination Address |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;20 | Data |
; +-+-+-.......... -+
;
;
; [smb] attention! according to RFC 791 IP packet may have 'options' sections,
; so we can't simply think, that data have offset 20. We must calculate offset from
; IHL field
;
macro GET_IHL reg, header_addr
{
movzx reg, byte [header_addr]
; we need 4-7 bits, so....
and reg, 0x0000000F
; IHL keeps number of octets, so we need to << 2 'reg'
shl reg, 2
}
 
 
include "tcp.inc"
include "udp.inc"
include "icmp.inc"
 
;***************************************************************************
; Function
; ip_rx
;
; Description
; This is a kernel function, called by stack_handler
; Processes all IP-packets received by the network layer
; It calls the appropriate protocol handler
;
;***************************************************************************
proc ip_rx stdcall
local buffer_number dd ?
 
; Look for a buffer to tx
mov eax, IPIN_QUEUE
call dequeue
cmp ax, NO_BUFFER
je .exit ; Exit if no buffer available
 
mov [buffer_number], eax;save buffer number
 
; convert buffer pointer eax to the absolute address
imul eax, IPBUFFSIZE
add eax, IPbuffs
 
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], 0; clear checksum field - need to when
; recalculating checksum
; this needs two data pointers and two size #.
; 2nd pointer can be of length 0
 
GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx
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!!!
 
; 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
je @f
 
; If the IP address is 255.255.255.255, accept it
; - it is a broadcast packet, which we need for dhcp
 
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)
; DEBUGF 1, "K : ip_rx - ihl: %x - 05\n", al
jnz .dump.3 ;then dump it
 
; DEBUGF 1, "K : ip_rx - ttl: %x - 00\n", [ebx + IP_PACKET.TimeToLive]:2
 
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.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
 
mov al, [ebx + IP_PACKET.Protocol]
 
cmp al , PROTOCOL_TCP
jne .not_tcp
; DEBUGF 1,"K : ip_rx - TCP packet\n"
mov eax, dword[buffer_number]
call tcp_rx
jmp .exit
 
.not_tcp:
cmp al, PROTOCOL_UDP
jne .not_udp
; DEBUGF 1,"K : ip_rx - UDP packet\n"
mov eax, dword[buffer_number]
call udp_rx
jmp .exit
 
.not_udp:
cmp al, PROTOCOL_ICMP
jne .dump.6 ;protocol ain't supported
 
; DEBUGF 1,"K : ip_rx - ICMP packet\n"
;GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx
mov eax, dword[buffer_number]
stdcall icmp_rx, eax, ebx, ecx;buffer_number,IPPacketBase,IPHeaderLength
jmp .exit
 
 
.dump.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 (ttl: %u)\n", [ebx + IP_PACKET.TimeToLive]
jmp .dump.x
 
.dump.5:
DEBUGF 1, "K : ip_rx - dumped (flags: 0x%x)\n", ax
jmp .dump.x
 
.dump.6:
DEBUGF 1, "K : ip_rx - dumped (proto: %u)\n", [ebx + IP_PACKET.Protocol]:1
 
.dump.x:
inc dword[dumped_rx_count]
mov eax, [buffer_number]
call freeBuff
 
.exit:
ret
endp
 
Property changes:
Added: svn:keywords
+Rev
\ No newline at end of property