75,17 → 75,11 |
.pci_bus db ? |
.pci_dev db ? |
|
; The following fields up to .tx_ring_phys inclusive form |
; initialization block for hardware; do not modify |
align 4 ; initialization block must be dword-aligned |
.private: |
.mode_ dw ? |
.tlen_rlen dw ? |
.phys_addr dp ? |
.reserved dw ? |
.filter dq ? |
.rx_ring_phys dd ? |
.tx_ring_phys dd ? |
.rx_ring dd ? |
.tx_ring dd ? |
.cur_rx db ? |
122,8 → 116,7 |
.base dd ? |
.length dw ? |
.status dw ? |
.msg_length dw ? |
.misc dw ? |
.misc dd ? |
.reserved dd ? |
|
.size: |
198,12 → 191,12 |
|
PCNET_DMA_MASK equ 0xffffffff |
|
PCNET_LOG_TX_BUFFERS equ 2 |
PCNET_LOG_TX_BUFFERS equ 1 |
PCNET_LOG_RX_BUFFERS equ 2 |
|
PCNET_TX_RING_SIZE equ 4 |
PCNET_TX_RING_MOD_MASK equ (PCNET_TX_RING_SIZE-1) |
PCNET_TX_RING_LEN_BITS equ (PCNET_LOG_TX_BUFFERS shl 12) |
PCNET_TX_RING_LEN_BITS equ 0 |
|
PCNET_RX_RING_SIZE equ 4 |
PCNET_RX_RING_MOD_MASK equ (PCNET_RX_RING_SIZE-1) |
610,8 → 603,6 |
test eax, eax |
jz .err |
mov dword [ebx + device.rx_ring], eax |
call GetPgAddr |
mov dword [ebx + device.rx_ring_phys], eax |
|
; Allocate the TX ring |
|
619,8 → 610,6 |
test eax, eax |
jz .err |
mov dword [ebx + device.tx_ring], eax |
call GetPgAddr |
mov dword [ebx + device.tx_ring_phys], eax |
|
; fill in some of the structure variables |
|
641,11 → 630,9 |
|
mov edi, [ebx + device.tx_ring] |
mov ecx, PCNET_TX_RING_SIZE |
mov eax, [ebx + device.tx_buffer] |
call GetPgAddr |
.tx_init: |
mov [edi + buf_head.base], eax |
add eax, PCNET_PKT_BUF_SZ |
mov [edi + buf_head.base], 0 |
mov [edi + buf_head.status], 0 |
add edi, buf_head.size |
loop .tx_init |
|
652,15 → 639,15 |
mov [ebx + device.tlen_rlen],(PCNET_TX_RING_LEN_BITS or PCNET_RX_RING_LEN_BITS) |
|
; Ok, the eth_device structure is ready, let's probe the device |
; Because initialization fires IRQ, IRQ handler must be aware of this device |
|
call probe ; this function will output in eax |
test eax, eax |
jnz .err ; If an error occured, exit |
|
mov eax, [PCNET_DEV] ; Add the device structure to our device list |
mov [PCNET_LIST+4*eax], ebx ; (IRQ handler uses this list to find device) |
inc [PCNET_DEV] ; |
|
call probe ; this function will output in eax |
test eax, eax |
jnz .destroy ; If an error occured, exit |
|
call EthRegDev |
cmp eax, -1 |
je .destroy |
683,7 → 670,6 |
.destroy: |
; todo: reset device into virgin state |
|
dec [PCNET_DEV] |
.err: |
DEBUGF 1,"Error, removing all data !\n" |
stdcall KernelFree, dword [ebx+device.rx_buffer] |
955,8 → 941,7 |
; ------------------------------------------------ |
end if |
|
; mov esi, 1 |
; call Sleep |
stdcall Sleep, 1 |
|
|
reset: |
1068,13 → 1053,7 |
mov dword [ebx + device.filter], -1 |
mov dword [ebx + device.filter+4], -1 |
|
call read_mac |
|
lea esi, [ebx + device.mac] |
lea edi, [ebx + device.phys_addr] |
movsd |
movsw |
|
lea eax, [ebx + device.private] |
mov ecx, eax |
and ecx, 0xFFF ; KolibriOS PAGE SIZE |
1123,6 → 1102,8 |
xor ecx, ecx |
call [ebx + device.access_read_csr] |
|
call read_mac |
|
xor ecx, ecx |
mov eax, PCNET_CSR_INTEN or PCNET_CSR_START |
call [ebx + device.access_write_csr] |
1159,31 → 1140,30 |
jl .finish ; packet is too short |
|
; check descriptor |
DEBUGF 1,"Checking descriptor, " |
movzx eax, [ebx + device.cur_tx] |
imul edi, eax, PCNET_PKT_BUF_SZ |
shl eax, 4 |
add edi, [ebx + device.tx_buffer] |
add eax, [ebx + device.tx_ring] |
test byte [eax + buf_head.status + 1], 80h |
jnz .nospace |
; descriptor is free, copy data |
mov esi, [esp] |
mov edx, buf_head.size ;;PCNET_PKT_BUF_SZ |
mul dx |
mov edi, [ebx + device.tx_buffer] |
add edi, eax |
|
mov edx, [ebx + device.io_addr] |
|
mov ecx, [esp+4] |
mov edx, ecx |
shr ecx, 2 |
and edx, 3 |
rep movsd |
mov ecx, edx |
rep movsb |
; set length |
mov ecx, [esp+4] |
neg ecx |
mov [eax + buf_head.length], cx |
; put to transfer queue |
mov [eax + buf_head.status], 0x8300 |
neg cx ;;;; |
mov [edi + buf_head.length], cx |
mov [edi + buf_head.misc], 0 |
|
mov eax, [esp] |
mov ecx, eax |
and ecx, 0xfff |
call GetPgAddr |
add eax, ecx |
mov [edi + buf_head.base], eax |
mov [edi + buf_head.status], 0x8300 |
|
; trigger an immediate send |
xor ecx, ecx ; CSR0 |
mov ecx, 0 ; CSR0 |
call [ebx + device.access_read_csr] |
or eax, PCNET_CSR_TX |
call [ebx + device.access_write_csr] |
1200,14 → 1180,10 |
|
ret |
|
.nospace: |
DEBUGF 1, 'ERROR: no free transmit descriptors\n' |
; todo: maybe somehow notify the kernel about the error? |
add esp, 4+4 |
ret |
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Interrupt handler ;; |
1217,7 → 1193,7 |
align 4 |
int_handler: |
|
; DEBUGF 1,"IRQ %x ",eax:2 ; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO |
DEBUGF 1,"IRQ %x ",eax:2 ; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO |
|
; find pointer of device wich made IRQ occur |
|
1230,12 → 1206,12 |
mov edx, [ebx + device.io_addr] ; get IRQ reason |
|
push ecx |
xor ecx, ecx ; CSR0 |
mov ecx, 0 ; CSR0 |
call [ebx + device.access_read_csr] |
pop ecx |
|
test al , al |
js .got_it |
test ax , ax |
jnz .got_it |
|
add esi, 4 |
loop .nextdevice |
1243,16 → 1219,8 |
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver |
|
.got_it: |
|
;------------------------------------------------------- |
; Possible reasons: |
; initialization done - ignore |
; transmit done - ignore |
; packet received - handle |
; Clear ALL IRQ reasons. |
; N.B. One who wants to handle more than one reason must be ready |
; to two or more reasons in one IRQ. |
xor ecx, ecx |
call [ebx + device.access_write_csr] |
; Received packet ok? |
|
test ax, PCNET_CSR_RINT |
1273,18 → 1241,17 |
test cx , PCNET_RXSTAT_OWN ; If this bit is set, the controller OWN's the packet, if not, we do |
jnz .abort |
|
test cx , PCNET_RXSTAT_ENP |
cmp cx , PCNET_RXSTAT_ENP |
jz .abort |
|
test cx , PCNET_RXSTAT_STP |
cmp cx , PCNET_RXSTAT_STP |
jz .abort |
|
movzx ecx, [edi + buf_head.msg_length] ; get packet length in ecx |
movzx ecx, [ebx + buf_head.length] ; get packet length in ecx |
and ecx, 0xfff ; |
sub ecx, 4 ; |
|
push ecx |
stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into |
pop ecx |
test eax, eax ; Test if we allocated succesfully |
jz .abort ; |
|
1300,8 → 1267,8 |
and ecx, 3 |
rep movsb |
|
; mov word [eax + buf_head.length], PCNET_PKT_BUF_SZ_NEG |
mov word [eax + buf_head.status], PCNET_RXSTAT_OWN ; Set OWN bit back to 1 (controller may write to tx-buffer again now) |
mov word [eax + buf_head.length], PCNET_PKT_BUF_SZ_NEG |
or word [eax + buf_head.status], PCNET_RXSTAT_OWN ; Set OWN bit back to 1 (controller may write to tx-buffer again now) |
|
inc [ebx + device.cur_rx] ; update descriptor |
and [ebx + device.cur_rx], 3 ; |
1505,7 → 1472,7 |
dwio_read_csr: |
|
add edx, PCNET_DWIO_RAP |
mov eax, ecx |
mov ecx, eax |
out dx , eax |
add edx, PCNET_DWIO_RDP - PCNET_DWIO_RAP |
in eax, dx |
1535,7 → 1502,7 |
dwio_read_bcr: |
|
add edx, PCNET_DWIO_RAP |
mov eax, ecx |
mov ecx, eax |
out dx , eax |
add edx, PCNET_DWIO_BDP - PCNET_DWIO_RAP |
in eax, dx |