/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 |