Changes in net_branch:

Fixed yet another bug in RTL8139 driver (should be almost bug-free now)
Added 3com driver (only boomerang cards tested)
If somebody has a vortex type 3com card, please help me debug the driver!



git-svn-id: svn://kolibrios.org@1472 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2010-05-28 15:40:36 +00:00
parent 28d7f704a9
commit 9ca8f38b9e
3 changed files with 3385 additions and 247 deletions

File diff suppressed because it is too large Load Diff

View File

@ -21,11 +21,12 @@ format MS COFF
DEBUG equ 1 DEBUG equ 1
__DEBUG__ equ 1 __DEBUG__ equ 1
__DEBUG_LEVEL__ equ 1 __DEBUG_LEVEL__ equ 2
include 'proc32.inc' include 'proc32.inc'
include 'imports.inc' include 'imports.inc'
include 'fdo.inc' include 'fdo.inc'
include 'netdrv.inc'
OS_BASE equ 0; OS_BASE equ 0;
new_app_base equ 0x60400000 new_app_base equ 0x60400000
@ -35,18 +36,6 @@ public START
public service_proc public service_proc
public version public version
struc IOCTL {
.handle dd ?
.io_code dd ?
.input dd ?
.inp_size dd ?
.output dd ?
.out_size dd ?
}
virtual at 0
IOCTL IOCTL
end virtual
struc ETH_DEVICE { struc ETH_DEVICE {
; pointers to procedures ; pointers to procedures
@ -75,23 +64,15 @@ struc ETH_DEVICE {
.pci_dev db ? .pci_dev db ?
.irq_line db ? .irq_line db ?
.hw_ver_id db ? .hw_ver_id db ?
.size:
.size = $ - device
} }
virtual at 0 virtual at ebx
device ETH_DEVICE device ETH_DEVICE
end virtual end virtual
; 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
; RTL8139 specific defines ; RTL8139 specific defines
MAX_RTL8139 equ 16 ; Max number of devices this driver may handle MAX_RTL8139 equ 16 ; Max number of devices this driver may handle
@ -194,13 +175,13 @@ end virtual
(RX_MXDMA shl BIT_RX_MXDMA) or \ (RX_MXDMA shl BIT_RX_MXDMA) or \
(1 shl BIT_NOWRAP) or \ (1 shl BIT_NOWRAP) or \
(RXFTH shl BIT_RXFTH) or\ (RXFTH shl BIT_RXFTH) or\
(1 shl BIT_AB) or \ (1 shl BIT_AB) or \ ; Accept broadcast packets
(1 shl BIT_APM) or \ (1 shl BIT_APM) or \ ; Accept physical match packets
(1 shl BIT_AER) or \ (1 shl BIT_AER) or \ ; Accept error packets
(1 shl BIT_AR) or \ (1 shl BIT_AR) or \ ; Accept Runt packets (smaller then 64 bytes)
(1 shl BIT_AM) (1 shl BIT_AM) ; Accept multicast packets
RX_BUFFER_SIZE equ (8192 shl RBLEN) RX_BUFFER_SIZE equ (8192 shl RBLEN);+16
MAX_ETH_FRAME_SIZE equ 1516 ; exactly 1514 wthout CRC MAX_ETH_FRAME_SIZE equ 1516 ; exactly 1514 wthout CRC
NUM_TX_DESC equ 4 NUM_TX_DESC equ 4
TX_BUF_SIZE equ 4096 ; size of one tx buffer (set to 4kb because of KolibriOS's page size) TX_BUF_SIZE equ 4096 ; size of one tx buffer (set to 4kb because of KolibriOS's page size)
@ -279,7 +260,7 @@ proc START stdcall, state:dword
.entry: .entry:
DEBUGF 1,"Loading rtl8139 driver\n" DEBUGF 2,"Loading rtl8139 driver\n"
stdcall RegService, my_service, service_proc stdcall RegService, my_service, service_proc
ret ret
@ -302,16 +283,20 @@ align 4
proc service_proc stdcall, ioctl:dword proc service_proc stdcall, ioctl:dword
mov edx, [ioctl] mov edx, [ioctl]
<<<<<<< .mine
mov eax, [IOCTL.io_code]
=======
mov eax, [edx+IOCTL.io_code] mov eax, [edx+IOCTL.io_code]
>>>>>>> .r1471
;------------------------------------------------------ ;------------------------------------------------------
cmp eax, 0 ;SRV_GETVERSION cmp eax, 0 ;SRV_GETVERSION
jne @F jne @F
cmp [edx+IOCTL.out_size], 4 cmp [IOCTL.out_size], 4
jl .fail jl .fail
mov eax, [edx+IOCTL.output] mov eax, [IOCTL.output]
mov [eax], dword API_VERSION mov [eax], dword API_VERSION
xor eax, eax xor eax, eax
@ -322,10 +307,10 @@ proc service_proc stdcall, ioctl:dword
cmp eax, 1 ;SRV_HOOK cmp eax, 1 ;SRV_HOOK
jne .fail jne .fail
cmp [edx + IOCTL.inp_size], 3 ; Data input must be at least 3 bytes cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jl .fail jl .fail
mov eax, [edx + IOCTL.input] mov eax, [IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet jne .fail ; other types arent supported for this card yet
@ -335,15 +320,17 @@ proc service_proc stdcall, ioctl:dword
mov ecx, [RTL8139_DEV] mov ecx, [RTL8139_DEV]
test ecx, ecx test ecx, ecx
jz .firstdevice jz .firstdevice
; mov eax, [edx+IOCTL.input] ; get the pci bus and device numbers
mov bx , [eax+1] ;
.nextdevice:
lodsd
cmp bx , word [eax + device.pci_bus] ; compare with pci and device num in RTL8139 list (notice the usage of word instead of byte)
je .find_devicenum ; Device is already loaded, let's find it's device number
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax , [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp ax , word [device.pci_bus] ; compare with pci and device num in device list (notice the usage of word instead of byte)
je .find_devicenum ; Device is already loaded, let's find it's device number
add esi, 4
loop .nextdevice loop .nextdevice
; This device doesnt have its own eth_device structure yet, lets create one ; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice: .firstdevice:
cmp [RTL8139_DEV], MAX_RTL8139 ; First check if the driver can handle one more card cmp [RTL8139_DEV], MAX_RTL8139 ; First check if the driver can handle one more card
@ -358,94 +345,41 @@ proc service_proc stdcall, ioctl:dword
; Fill in the direct call addresses into the struct ; Fill in the direct call addresses into the struct
mov dword [ebx+device.reset], reset mov dword [device.reset], reset
mov dword [ebx+device.transmit], transmit mov dword [device.transmit], transmit
mov dword [ebx+device.get_MAC], read_mac mov dword [device.get_MAC], read_mac
mov dword [ebx+device.set_MAC], write_mac mov dword [device.set_MAC], write_mac
mov dword [ebx+device.unload], unload mov dword [device.unload], unload
mov dword [ebx+device.name], my_service mov dword [device.name], my_service
; save the pci bus and device numbers ; save the pci bus and device numbers
mov eax, [edx+IOCTL.input] mov eax, [IOCTL.input]
mov cl , [eax+1] mov cl , [eax+1]
mov [ebx+device.pci_bus], cl mov [device.pci_bus], cl
mov cl , [eax+2] mov cl , [eax+2]
mov [ebx+device.pci_dev], cl mov [device.pci_dev], cl
; Now, it's time to find the base io addres of the PCI device ; Now, it's time to find the base io addres of the PCI device
; TODO: implement check if bus and dev exist on this machine ; TODO: implement check if bus and dev exist on this machine
mov edx, PCI_BASE_ADDRESS_0 find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
.reg_check:
movzx eax, byte [ebx+device.pci_bus]
movzx ecx, byte [ebx+device.pci_dev]
push edx ecx
stdcall PciRead16, eax ,ecx ,edx
pop ecx edx
mov [ebx+device.io_addr], eax
and eax, PCI_BASE_ADDRESS_IO_MASK
test eax, eax
jz .inc_reg
mov eax, [ebx+device.io_addr]
and eax, PCI_BASE_ADDRESS_SPACE_IO
test eax, eax
jz .inc_reg
mov eax, [ebx+device.io_addr]
and eax, PCI_BASE_ADDRESS_IO_MASK
mov [ebx+device.io_addr], eax
jmp .got_io
.inc_reg:
add edx, 4
cmp edx, PCI_BASE_ADDRESS_5
jbe .reg_check
.got_io:
; We've found the io address, find IRQ now ; We've found the io address, find IRQ now
movzx eax, byte [ebx+device.pci_bus] movzx eax, byte [device.pci_bus]
movzx ecx, byte [ebx+device.pci_dev] movzx ecx, byte [device.pci_dev]
push ebx push ebx
stdcall PciRead8, eax ,ecx ,0x3c ; 0x3c is the offset where irq can be found stdcall PciRead8, eax ,ecx ,0x3c ; 0x3c is the offset where irq can be found
pop ebx pop ebx
mov byte [ebx+device.irq_line], al mov byte [device.irq_line], al
DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\ DEBUGF 2,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[ebx+device.pci_dev]:1,[ebx+device.pci_bus]:1,[ebx+device.irq_line]:1,[ebx+device.io_addr]:4 [device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
; Allocate the Receive buffer
stdcall KernelAlloc, dword (RX_BUFFER_SIZE+MAX_ETH_FRAME_SIZE) allocate_and_clear [device.rx_buffer], (RX_BUFFER_SIZE+MAX_ETH_FRAME_SIZE), .err
test eax, eax allocate_and_clear [device.tx_buffer], (TX_BUF_SIZE*NUM_TX_DESC), .err
jz .err
mov [ebx+device.rx_buffer], eax ; Save the address to it into the device struct
; Now, Clear the allocated buffer
cld
mov edi, eax
mov ecx, (RX_BUFFER_SIZE)/4 ; divide by 4 because we are going to use DWORD
xor eax, eax
rep stosd
; Allocate the Transmit Buffer
stdcall KernelAlloc, dword (TX_BUF_SIZE*NUM_TX_DESC)
test eax, eax
jz .err
mov [ebx+device.tx_buffer], eax
; This one needs to be cleared too..
mov edi, eax
mov ecx, (TX_BUF_SIZE*NUM_TX_DESC)/4
xor eax, eax
rep stosd
; Ok, the eth_device structure is ready, let's probe the device ; Ok, the eth_device structure is ready, let's probe the device
@ -467,12 +401,12 @@ proc service_proc stdcall, ioctl:dword
; If the device was already loaded, find the device number and return it in eax ; If the device was already loaded, find the device number and return it in eax
.find_devicenum: .find_devicenum:
DEBUGF 1,"Trying to find device number of already registered device\n" DEBUGF 2,"Trying to find device number of already registered device\n"
mov ebx, eax mov ebx, eax
call EthStruc2Dev ; This kernel procedure converts a pointer to device struct in ebx call EthStruc2Dev ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi ; into a device number in edi
mov eax, edi ; Application wants it in eax instead mov eax, edi ; Application wants it in eax instead
DEBUGF 1,"Kernel says: %u\n", eax DEBUGF 2,"Kernel says: %u\n", eax
ret ret
; If an error occured, remove all allocated data and exit (returning -1 in eax) ; If an error occured, remove all allocated data and exit (returning -1 in eax)
@ -481,8 +415,8 @@ proc service_proc stdcall, ioctl:dword
; todo: reset device into virgin state ; todo: reset device into virgin state
.err: .err:
stdcall KernelFree, dword [ebx+device.rx_buffer] stdcall KernelFree, dword [device.rx_buffer]
stdcall KernelFree, dword [ebx+device.tx_buffer] stdcall KernelFree, dword [device.tx_buffer]
stdcall KernelFree, ebx stdcall KernelFree, ebx
@ -525,23 +459,12 @@ align 4
probe: probe:
DEBUGF 2,"Probing rtl8139 device: " DEBUGF 2,"Probing rtl8139 device: "
; enable the device make_bus_master [device.pci_bus], [device.pci_dev]
movzx eax, byte [ebx+device.pci_bus]
movzx ecx, byte [ebx+device.pci_dev]
stdcall PciRead32, eax ,ecx ,PCI_REG_CMD
mov cx , ax
or cl , (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO)
and cl , not (1 shl PCI_BIT_MMIO)
movzx eax, byte [ebx+device.pci_bus]
movzx edx, byte [ebx+device.pci_dev]
stdcall PciWrite32, eax ,edx ,PCI_REG_CMD, ecx
; get chip version ; get chip version
mov edx, [ebx+device.io_addr] set_io 0
add edx, REG_TXCONFIG + 2 set_io REG_TXCONFIG + 2
in ax , dx in ax , dx
shr ah , 2 shr ah , 2
shr ax , 6 shr ax , 6
@ -554,33 +477,33 @@ probe:
jns .chip_ver_loop jns .chip_ver_loop
xor cl , cl ; default RTL8139 xor cl , cl ; default RTL8139
.chip_ver_found: .chip_ver_found:
mov [ebx+device.hw_ver_id], cl mov [device.hw_ver_id], cl
shl ecx, 2 shl ecx, 2
add ecx, name_crosslist add ecx, crosslist
mov ecx, [ecx] mov ecx, [ecx]
mov dword [ebx+device.name], ecx mov [device.name], ecx
DEBUGF 1,"Chip version: %s\n",ecx DEBUGF 2,"Chip version: %s\n",ecx
; wake up the chip ; wake up the chip
mov edx, [ebx+device.io_addr] set_io 0
add edx, REG_HLTCLK set_io REG_HLTCLK
mov al , 'R' ; run the clock mov al , 'R' ; run the clock
out dx , al out dx , al
; unlock config and BMCR registers ; unlock config and BMCR registers
add edx, REG_9346CR - REG_HLTCLK set_io REG_9346CR
mov al , (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0) mov al , (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0)
out dx , al out dx , al
; enable power management ; enable power management
add edx, REG_CONFIG1 - REG_9346CR set_io REG_CONFIG1
in al , dx in al , dx
cmp byte [ebx+device.hw_ver_id], IDX_RTL8139B cmp [device.hw_ver_id], IDX_RTL8139B
jl .old_chip jl .old_chip
; set LWAKE pin to active high (default value). ; set LWAKE pin to active high (default value).
@ -591,10 +514,12 @@ probe:
or al , (1 shl BIT_PMEn) or al , (1 shl BIT_PMEn)
and al , not (1 shl BIT_LWACT) and al , not (1 shl BIT_LWACT)
out dx , al out dx , al
add edx, REG_CONFIG4 - REG_CONFIG1
set_io REG_CONFIG4
in al , dx in al , dx
and al , not (1 shl BIT_LWPTN) and al , not (1 shl BIT_LWPTN)
out dx , al out dx , al
jmp .finish_wake_up jmp .finish_wake_up
.old_chip: .old_chip:
@ -607,8 +532,8 @@ probe:
; lock config and BMCR registers ; lock config and BMCR registers
xor al , al xor al , al
mov edx, [ebx+device.io_addr] set_io 0
add edx, REG_9346CR set_io REG_9346CR
out dx , al out dx , al
DEBUGF 2,"done!\n" DEBUGF 2,"done!\n"
@ -624,7 +549,7 @@ reset:
; attach int handler ; attach int handler
movzx eax, [ebx+device.irq_line] movzx eax, [device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x, ",eax:1 DEBUGF 1,"Attaching int handler to irq %x, ",eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0 stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax test eax, eax
@ -637,8 +562,8 @@ reset:
; reset chip ; reset chip
DEBUGF 1,"Resetting chip\n" DEBUGF 1,"Resetting chip\n"
mov edx, [ebx+device.io_addr] set_io 0
add edx, REG_COMMAND set_io REG_COMMAND
mov al , 1 shl BIT_RST mov al , 1 shl BIT_RST
out dx , al out dx , al
mov cx , 1000 ; wait no longer for the reset mov cx , 1000 ; wait no longer for the reset
@ -652,48 +577,48 @@ reset:
; unlock config and BMCR registers ; unlock config and BMCR registers
mov edx, [ebx+device.io_addr] set_io REG_9346CR
add edx, REG_9346CR
mov al , (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0) mov al , (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0)
out dx , al out dx , al
; initialize multicast registers (no filtering) ; initialize multicast registers (no filtering)
mov eax, 0xffffffff mov eax, 0xffffffff
add edx, REG_MAR0 - REG_9346CR set_io REG_MAR0
out dx , eax out dx , eax
add edx, REG_MAR4 - REG_MAR0 set_io REG_MAR4
out dx , eax out dx , eax
; enable Rx/Tx ; enable Rx/Tx
mov al , (1 shl BIT_RE) or (1 shl BIT_TE) mov al , (1 shl BIT_RE) or (1 shl BIT_TE)
add edx, REG_COMMAND - REG_MAR4 set_io REG_COMMAND
out dx , al out dx , al
; 32k Rxbuffer, unlimited dma burst, no wrapping, no rx threshold ; 32k Rxbuffer, unlimited dma burst, no wrapping, no rx threshold
; accept broadcast packets, accept physical match packets ; accept broadcast packets, accept physical match packets
mov ax , RX_CONFIG mov ax , RX_CONFIG
add edx, REG_RXCONFIG - REG_COMMAND set_io REG_RXCONFIG
out dx , ax out dx , ax
; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144 ; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144
mov eax , (TX_MXDMA shl BIT_TX_MXDMA) or (TXRR shl BIT_TXRR) or BIT_IFG1 or BIT_IFG0 mov eax , (TX_MXDMA shl BIT_TX_MXDMA) or (TXRR shl BIT_TXRR) or BIT_IFG1 or BIT_IFG0
add edx, REG_TXCONFIG - REG_RXCONFIG set_io REG_TXCONFIG
out dx , eax out dx , eax
; enable auto negotiation ; enable auto negotiation
add edx, REG_BMCR - REG_TXCONFIG set_io REG_BMCR
in ax , dx in ax , dx
or ax , (1 shl BIT_ANE) or ax , (1 shl BIT_ANE)
out dx , ax out dx , ax
; set auto negotiation advertisement ; set auto negotiation advertisement
add edx, REG_ANAR - REG_BMCR set_io REG_ANAR
in ax , dx in ax , dx
or ax , (1 shl BIT_SELECTOR) or (1 shl BIT_10) or (1 shl BIT_10FD) or (1 shl BIT_TX) or (1 shl BIT_TXFD) or ax , (1 shl BIT_SELECTOR) or (1 shl BIT_10) or (1 shl BIT_10FD) or (1 shl BIT_TX) or (1 shl BIT_TXFD)
out dx , ax out dx , ax
@ -701,52 +626,52 @@ reset:
; lock config and BMCR registers ; lock config and BMCR registers
xor eax, eax xor eax, eax
add edx, REG_9346CR - REG_ANAR set_io REG_9346CR
out dx , al out dx , al
; init RX/TX pointers ; init RX/TX pointers
mov [ebx+device.rx_data_offset], eax mov [device.rx_data_offset], eax
mov [ebx+device.curr_tx_desc], al mov [device.curr_tx_desc], al
; clear packet/byte counters ; clear packet/byte counters
lea edi, [ebx+device.bytes_tx] ; TODO: check if destroying edi, ecx doesnt harm anything lea edi, [device.bytes_tx]
mov ecx, 6 mov ecx, 6
rep stosd rep stosd
; clear missing packet counter ; clear missing packet counter
add edx, REG_MPC - REG_9346CR set_io REG_MPC
out dx , eax out dx , eax
; Set up the 4 Txbuffer descriptors ; Set up the 4 Txbuffer descriptors
add edx, REG_TSAD0 - REG_MPC set_io REG_TSAD0
mov eax, [ebx+device.tx_buffer] mov eax, [device.tx_buffer]
mov ecx, 4 mov ecx, 4
.loop: .loop:
push eax push eax
call GetPgAddr call GetPgAddr
DEBUGF 2,"Desc: %x ", eax DEBUGF 1,"Desc: %x ", eax
out dx , eax out dx , eax
add dx , 4 add dx , 4
pop eax pop eax
add eax, TX_BUF_SIZE add eax, TX_BUF_SIZE
loop .loop loop .loop
; set RxBuffer address, init RX buffer offset, init TX ring ; set RxBuffer address, init RX buffer offset
mov eax, [ebx+device.rx_buffer] mov eax, [device.rx_buffer]
call GetPgAddr call GetPgAddr
mov edx, [ebx+device.io_addr] set_io 0
add edx, REG_RBSTART set_io REG_RBSTART
out dx , eax out dx , eax
; enable interrupts ; enable interrupts
mov eax, INTERRUPT_MASK mov eax, INTERRUPT_MASK
add edx, REG_IMR - REG_RBSTART set_io REG_IMR
out dx , ax out dx , ax
; Read MAC address ; Read MAC address
@ -786,9 +711,9 @@ transmit:
jl .finish ; packet is too short jl .finish ; packet is too short
; check descriptor ; check descriptor
; DEBUGF 1,"Checking descriptor, " DEBUGF 1,"Checking descriptor, "
movzx ecx, [ebx+device.curr_tx_desc] movzx ecx, [device.curr_tx_desc]
mov edx, [ebx+device.io_addr] mov edx, [device.io_addr]
lea edx, [edx+ecx*4+REG_TSD0] lea edx, [edx+ecx*4+REG_TSD0]
in ax, dx in ax, dx
test ax, 0x1fff ; or no size given test ax, 0x1fff ; or no size given
@ -797,7 +722,7 @@ transmit:
cmp ax, (1 shl BIT_TOK) or (1 shl BIT_OWN) cmp ax, (1 shl BIT_TOK) or (1 shl BIT_OWN)
jz .send_packet jz .send_packet
; wait for timeout ; wait for timeout
; DEBUGF 1,"Waiting for timeout, " DEBUGF 1,"Waiting for timeout, "
push edx ebx ; TODO : rtl8139 internal timer should be used instead push edx ebx ; TODO : rtl8139 internal timer should be used instead
stdcall Sleep, TX_TIMEOUT ; ? What registers does this destroy ? stdcall Sleep, TX_TIMEOUT ; ? What registers does this destroy ?
@ -811,13 +736,13 @@ transmit:
call reset ; reset the card call reset ; reset the card
pop dx pop dx
.send_packet: .send_packet:
; DEBUGF 1,"Sending packet, " DEBUGF 1,"Sending packet, "
push edx push edx
movzx eax, [ebx+device.curr_tx_desc] ; calculate the current tx_buffer address movzx eax, [device.curr_tx_desc] ; calculate the current tx_buffer address
mov edx, TX_BUF_SIZE ;MAX_ETH_FRAME_SIZE ; mov edx, TX_BUF_SIZE ;MAX_ETH_FRAME_SIZE ;
mul edx ; mul edx ;
mov edi, [ebx+device.tx_buffer] ; mov edi, [device.tx_buffer] ;
add edi, eax ; Store it in edi add edi, eax ; Store it in edi
pop edx pop edx
@ -829,22 +754,22 @@ transmit:
and ecx, 3 ; and ecx, 3 ;
rep movsb ; rep movsb ;
inc [ebx+device.packets_tx] ; inc [device.packets_tx] ;
mov eax, [esp+8] ; Get packet size in eax mov eax, [esp+8] ; Get packet size in eax
add dword [ebx + device.bytes_tx], eax add dword [device.bytes_tx], eax
adc dword [ebx + device.bytes_tx + 4], 0 adc dword [device.bytes_tx + 4], 0
; or eax, (ERTXTH shl BIT_ERTXTH) ; Set descriptor size and the early tx treshold into the correct Transmission status register (TSD0, TSD1, TSD2 or TSD3) ; or eax, (ERTXTH shl BIT_ERTXTH) ; Set descriptor size and the early tx treshold into the correct Transmission status register (TSD0, TSD1, TSD2 or TSD3)
out dx , eax ; out dx , eax ;
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ... ; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
inc [ebx+device.curr_tx_desc] inc [device.curr_tx_desc]
and [ebx+device.curr_tx_desc], 3 and [device.curr_tx_desc], 3
DEBUGF 2," - Packet Sent! " DEBUGF 1," - Packet Sent! "
.finish: .finish:
DEBUGF 2," - Done!\n" DEBUGF 1," - Done!\n"
ret ret
@ -869,8 +794,8 @@ int_handler:
.nextdevice: .nextdevice:
mov ebx, dword [esi] mov ebx, dword [esi]
mov edx, dword [ebx+device.io_addr] ; get IRQ reason set_io 0
add edx, REG_ISR set_io REG_ISR
in ax , dx in ax , dx
out dx , ax ; send it back to ACK out dx , ax ; send it back to ACK
@ -897,64 +822,80 @@ int_handler:
push ax push ax
.receive: .receive:
mov edx, dword [ebx+device.io_addr] ; get IRQ reason set_io 0
add edx, REG_COMMAND ; set_io REG_COMMAND
in al , dx ; in al , dx
test al , BUFE ; test if RX buffer is empty test al , BUFE ; test if RX buffer is empty
jnz .finish ; jnz .finish ;
DEBUGF 2,"RX: " DEBUGF 1,"RX: "
mov eax, dword [ebx+device.rx_buffer] mov eax, [device.rx_buffer]
add eax, dword [ebx+device.rx_data_offset] add eax, [device.rx_data_offset]
test byte [eax], (1 shl BIT_ROK) ; check if packet is ok test byte [eax], (1 shl BIT_ROK) ; check if packet is ok
jz .reset_rx jz .reset_rx
; packet is ok, copy it
; packet is ok, copy it
movzx ecx, word [eax+2] ; packet length movzx ecx, word [eax+2] ; packet length
add dword [ebx + device.bytes_rx], ecx ; Update stats
adc dword [ebx + device.bytes_rx + 4], 0 ; Update stats
inc dword [ebx + device.packets_rx] ; add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
inc dword [device.packets_rx]
sub ecx, 4 ; don't copy CRC sub ecx, 4 ; don't copy CRC
DEBUGF 1,"Received %u bytes\n", ecx DEBUGF 1,"Received %u bytes\n", ecx
push ebx eax ecx push ebx eax ecx
stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
pop ecx pop ecx
test eax, eax ; Test if we allocated succesfully test eax, eax ; Test if we allocated succesfully
jz .abort ; jz .abort
mov edi, eax ; Set up registers to copy the packet
mov esi, [esp] ; mov edi, eax ; Where we will copy too
mov esi, [esp] ; The buffer we will copy from
add esi, 4 ; Dont copy CRC add esi, 4 ; Dont copy CRC
push dword .abort ; Kernel will return to this address after EthReceiver push dword .abort ; Kernel will return to this address after EthReceiver
push ecx edi ; Save buffer pointer and size, to pass to kernel push ecx edi ; Save buffer pointer and size, to pass to kernel
shr ecx, 2 .copy:
cld shr ecx, 1
rep movsd ; copy the dwords jnc .nb
mov ecx, [esp+4] movsb
and ecx, 3 .nb:
rep movsb ; copy the rest bytes shr ecx, 1
jnc .nw
movsw
.nw:
jz .nd
rep movsd
.nd:
jmp EthReceiver ; Send it to kernel jmp EthReceiver ; Send it to kernel
.abort: .abort:
pop eax ebx pop eax ebx
; update eth_data_start_offset ; update eth_data_start_offset
movzx eax, word [eax+2] ; packet length movzx eax, word [eax+2] ; packet length
add eax, [ebx+device.rx_data_offset] add eax, [device.rx_data_offset]
add eax, 4+3 ; packet header is 4 bytes long + dword alignment add eax, 4+3 ; packet header is 4 bytes long + dword alignment
and eax, not 3 ; dword alignment and eax, not 3 ; dword alignment
cmp eax, RX_BUFFER_SIZE cmp eax, RX_BUFFER_SIZE
jl .no_wrap jl .no_wrap
DEBUGF 2,"Wrapping"
sub eax, RX_BUFFER_SIZE sub eax, RX_BUFFER_SIZE
.no_wrap: .no_wrap:
mov [ebx+device.rx_data_offset], eax mov [device.rx_data_offset], eax
DEBUGF 1,"New RX ptr: %u", eax DEBUGF 1,"New RX ptr: %d ", eax
mov edx, dword [ebx+device.io_addr] set_io 0
add edx, REG_CAPR ; update 'Current Address of Packet Read register' set_io REG_CAPR ; update 'Current Address of Packet Read register'
sub eax, 0x10 ; value 0x10 is a constant for CAPR sub eax, 0x10 ; value 0x10 is a constant for CAPR
out dx , ax out dx , ax
@ -996,33 +937,33 @@ int_handler:
jz @f jz @f
push ax push ax
cmp [ebx+device.curr_tx_desc], 4 cmp [device.curr_tx_desc], 4
jz .notxd jz .notxd
mov edx, [ebx+device.io_addr] set_io 0
movzx ecx, [ebx+device.curr_tx_desc] movzx ecx, [device.curr_tx_desc]
lea edx, [edx+ecx*4+REG_TSD0] lea edx, [edx+ecx*4+REG_TSD0]
in eax, dx in eax, dx
.notxd: .notxd:
test eax, TSR_TUN test eax, TSR_TUN
jz .nobun jz .nobun
DEBUGF 1, "TX: FIFO Buffer underrun!\n" DEBUGF 2, "TX: FIFO Buffer underrun!\n"
.nobun: .nobun:
test eax, TSR_OWC test eax, TSR_OWC
jz .noowc jz .noowc
DEBUGF 1, "TX: OWC!\n" DEBUGF 2, "TX: OWC!\n"
.noowc: .noowc:
test eax, TSR_TABT test eax, TSR_TABT
jz .notabt jz .notabt
DEBUGF 1, "TX: TABT!\n" DEBUGF 2, "TX: TABT!\n"
.notabt: .notabt:
test eax, TSR_CRS test eax, TSR_CRS
jz .nocsl jz .nocsl
DEBUGF 1, "TX: Carrier Sense Lost!\n" DEBUGF 2, "TX: Carrier Sense Lost!\n"
.nocsl: .nocsl:
; test eax, TSR_OWN or TSR_TOK ; test eax, TSR_OWN or TSR_TOK
@ -1039,7 +980,7 @@ int_handler:
test ax, ISR_TOK test ax, ISR_TOK
jz @f jz @f
DEBUGF 1, "TX: Transmit OK (desc: %u)\n", [ebx+device.curr_tx_desc]:1 DEBUGF 1, "TX: Transmit OK (desc: %u)\n", [device.curr_tx_desc]:1
;---------------------------------------------------- ;----------------------------------------------------
; Rx buffer overflow ? ; Rx buffer overflow ?
@ -1049,9 +990,9 @@ int_handler:
jz @f jz @f
push ax push ax
DEBUGF 1,"RX-buffer overflow!\n" DEBUGF 2,"RX-buffer overflow!\n"
mov edx, [ebx+device.io_addr] mov edx, [device.io_addr]
add edx, REG_ISR add edx, REG_ISR
mov ax , ISR_FIFOOVW or ISR_RXOVW mov ax , ISR_FIFOOVW or ISR_RXOVW
out dx , ax out dx , ax
@ -1065,7 +1006,7 @@ int_handler:
test ax, ISR_PUN test ax, ISR_PUN
jz @f jz @f
DEBUGF 1,"Packet underrun!\n" DEBUGF 2,"Packet underrun!\n"
;---------------------------------------------------- ;----------------------------------------------------
; Receive FIFO overflow ? ; Receive FIFO overflow ?
@ -1077,7 +1018,7 @@ int_handler:
push ax push ax
DEBUGF 2,"RX fifo overflox!\n" DEBUGF 2,"RX fifo overflox!\n"
mov edx, [ebx+device.io_addr] mov edx, [device.io_addr]
add edx, REG_ISR add edx, REG_ISR
mov ax , ISR_FIFOOVW or ISR_RXOVW mov ax , ISR_FIFOOVW or ISR_RXOVW
out dx , ax out dx , ax
@ -1097,7 +1038,7 @@ int_handler:
.fail: .fail:
DEBUGF 2,"\n" DEBUGF 1,"\n"
ret ret
@ -1113,7 +1054,7 @@ align 4
cable: cable:
DEBUGF 1,"Checking Cable status: " DEBUGF 1,"Checking Cable status: "
mov edx, dword [ebx+device.io_addr] mov edx, dword [device.io_addr]
add edx, REG_MSR add edx, REG_MSR
in al , dx in al , dx
@ -1126,7 +1067,7 @@ cable:
shr al, 2 shr al, 2
and al, 3 and al, 3
mov byte [ebx+device.mode+3], al mov byte [device.mode+3], al
DEBUGF 1,"Done!\n" DEBUGF 1,"Done!\n"
ret ret
@ -1141,48 +1082,47 @@ ret
align 4 align 4
write_mac: ; in: mac pushed onto stack (as 3 words) write_mac: ; in: mac pushed onto stack (as 3 words)
DEBUGF 1,"Writing MAC: " DEBUGF 2,"Writing MAC: "
; disable all in command registers ; disable all in command registers
mov edx, [ebx+device.io_addr] set_io 0
add edx, REG_9346CR set_io REG_9346CR
xor eax, eax xor eax, eax
out dx , al out dx , al
add edx, REG_IMR - REG_9346CR set_io REG_IMR
xor eax, eax xor eax, eax
out dx , ax out dx , ax
add edx, REG_ISR - REG_IMR set_io REG_ISR
mov eax, -1 mov eax, -1
out dx , ax out dx , ax
; enable writing ; enable writing
set_io REG_9346CR
add edx, REG_9346CR - REG_ISR
mov eax, REG_9346CR_WE mov eax, REG_9346CR_WE
out dx , al out dx , al
; write the mac ... ; write the mac ...
add edx, REG_IDR0 - REG_9346CR set_io REG_IDR0
pop eax pop eax
out dx , eax out dx , eax
add edx, 4 set_io REG_IDR0+4
xor eax, eax xor eax, eax
pop ax pop ax
out dx , eax out dx , eax
; disable writing ; disable writing
add edx, REG_9346CR -REG_IDR0 set_io REG_9346CR
xor eax, eax xor eax, eax
out dx , al out dx , al
DEBUGF 1,"ok!\n" DEBUGF 2,"ok!\n"
; Notice this procedure does not ret, but continues to read_mac instead. ; Notice this procedure does not ret, but continues to read_mac instead.
@ -1194,17 +1134,17 @@ write_mac: ; in: mac pushed onto stack (as 3 words)
;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;
read_mac: read_mac:
DEBUGF 1,"Reading MAC: " DEBUGF 2,"Reading MAC: "
mov edx, [ebx + device.io_addr] set_io 0
lea edi, [ebx + device.mac] lea edi, [device.mac]
in eax, dx in eax, dx
stosd stosd
add edx, 4 add edx, 4
in ax, dx in ax, dx
stosw stosw
DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",[edi-6]:2,[edi-5]:2,[edi-4]:2,[edi-3]:2,[edi-2]:2,[edi-1]:2 DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[edi-6]:2,[edi-5]:2,[edi-4]:2,[edi-3]:2,[edi-2]:2,[edi-1]:2
ret ret
@ -1225,10 +1165,10 @@ align 4
read_eeprom: read_eeprom:
DEBUGF 2,"Reading eeprom, " DEBUGF 2,"Reading eeprom, "
mov edx, [ebx+device.io_addr] set_io 0
push ebx push ebx
movzx ebx, al movzx ebx, al
add edx, REG_RXCONFIG set_io REG_RXCONFIG
in al, dx in al, dx
test al, (1 shl BIT_9356SEL) test al, (1 shl BIT_9356SEL)
jz .type_93c46 jz .type_93c46
@ -1241,7 +1181,7 @@ read_eeprom:
or bx, EE_93C46_READ_CMD ; it contains start bit or bx, EE_93C46_READ_CMD ; it contains start bit
mov cx, EE_93C46_CMD_LENGTH-1 ; cmd_loop counter mov cx, EE_93C46_CMD_LENGTH-1 ; cmd_loop counter
.read_eeprom: .read_eeprom:
add edx, REG_9346CR - REG_RXCONFIG set_io REG_9346CR
; mov al, (1 shl BIT_93C46_EEM1) ; mov al, (1 shl BIT_93C46_EEM1)
; out dx, al ; out dx, al
mov al, (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EECS) ; wake up the eeprom mov al, (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EECS) ; wake up the eeprom
@ -1305,14 +1245,14 @@ device_6 db 'Realtek 8139D',0
device_7 db 'Realtek 8139CP',0 device_7 db 'Realtek 8139CP',0
device_8 db 'Realtek 8101',0 device_8 db 'Realtek 8101',0
name_crosslist dd device_1 crosslist dd device_1
dd device_2 dd device_2
dd device_3 dd device_3
dd device_4 dd device_4
dd device_5 dd device_5
dd device_6 dd device_6
dd device_7 dd device_7
dd device_8 dd device_8
hw_ver_array db VER_RTL8139 ; This array is used by the probe routine to find out wich version of the RTL8139 we are working with hw_ver_array db VER_RTL8139 ; This array is used by the probe routine to find out wich version of the RTL8139 we are working with
db VER_RTL8139A db VER_RTL8139A

View File

@ -0,0 +1,180 @@
; 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
; 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
PAGESIZE equ 4096
LAST_IO = 0
macro set_io addr {
if addr = 0
mov edx, [device.io_addr]
else if addr = LAST_IO
else
add edx, addr - LAST_IO
end if
LAST_IO = addr
}
macro diff16 title,l1,l2
{
local s,d
s = l2-l1
display title,': 0x'
repeat 16
d = 48 + s shr ((16-%) shl 2) and $0F
if d > 57
d = d + 65-57-1
end if
display d
end repeat
display 13,10
}
macro allocate_and_clear dest, size, err {
; We need to allocate at least 8 pages, if we want a continuous memory in ram
if (size < 8*4096) & (size > 4096)
stdcall KernelAlloc, 8*4096
else
stdcall KernelAlloc, size
end if
test eax, eax
jz err
mov dest, eax ; Save the address to it into the device struct
mov edi, eax ; look at last part of code!
; Release the unused pages (if any)
if (size < 8*4096) & (size > 4096)
add eax, (size/4096+1)*4096
mov ecx, 8-(size/4096+1)
call ReleasePages
end if
; Clear the allocated buffer
;mov edi, eax
mov ecx, size/4 ; divide by 4 because of DWORD
xor eax, eax
rep stosd
}
macro find_io bus, dev, io {
local .check, .inc, .got
xor eax, eax
mov esi, PCI_BASE_ADDRESS_0
movzx ecx, bus
movzx edx, dev
.check:
stdcall PciRead16, ecx ,edx ,esi
mov io , eax
and eax, PCI_BASE_ADDRESS_IO_MASK
test eax, eax
jz .inc
mov eax, io
and eax, PCI_BASE_ADDRESS_SPACE_IO
test eax, eax
jz .inc
mov eax, io
and eax, PCI_BASE_ADDRESS_IO_MASK
mov io , eax
jmp .got
.inc:
add esi, 4
cmp esi, PCI_BASE_ADDRESS_5
jbe .check
.got:
}
macro make_bus_master bus, dev {
movzx ecx, bus
movzx edx, dev
stdcall PciRead32, ecx ,edx ,PCI_REG_COMMAND
or al, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO)
and al, not (1 shl PCI_BIT_MMIO)
stdcall PciWrite32, ecx, edx, PCI_REG_COMMAND, eax
}
struc IOCTL {
.handle dd ?
.io_code dd ?
.input dd ?
.inp_size dd ?
.output dd ?
.out_size dd ?
}
virtual at edx
IOCTL IOCTL
end virtual
if used null_op
align 4
null_op:
or eax, -1
ret
end if
macro virt_to_dma { ; input is eax
push ax
and word[esp], PAGESIZE - 1
call GetPgAddr
or ax, word[esp]
inc esp
inc esp
}