Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 4521 → Rev 4522

/drivers/ethernet/i8254x.asm
14,14 → 14,15
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
format PE DLL native
entry START
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
CURRENT_API = 0x0200
COMPATIBLE_API = 0x0100
API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API
 
MAX_DEVICES = 16
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only
 
30,19 → 31,14
RX_RING_SIZE = 8 ; Must be a power of 2, and minimum 8
TX_RING_SIZE = 8 ; Must be a power of 2, and minimum 8
 
section '.flat' readable writable executable
 
include '../proc32.inc'
include '../struct.inc'
include '../macros.inc'
include '../proc32.inc'
include '../imports.inc'
include '../fdo.inc'
include '../netdrv.inc'
include '../netdrv_pe.inc'
 
public START
public service_proc
public version
 
 
 
; Register list
REG_CTRL = 0x0000 ; Control Register
REG_STATUS = 0x0008 ; Device Status Register
270,33 → 266,27
RXDESC_EOP = 0x00000002 ; End Of Packet
RXDESC_DD = 0x00000001 ; Descriptor Done
 
virtual at ebx
device:
ETH_DEVICE
struct device ETH_DEVICE
 
.mmio_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
mmio_addr dd ?
pci_bus dd ?
pci_dev dd ?
irq_line db ?
 
.cur_rx dd ?
.cur_tx dd ?
.last_tx dd ?
cur_rx dd ?
cur_tx dd ?
last_tx dd ?
 
rb 0x100 - (($ - device) and 0xff) ; align 256
.rx_desc rb RX_RING_SIZE*sizeof.RDESC*2
rb 0x100 - ($ and 0xff) ; align 256
 
rb 0x100 - (($ - device) and 0xff) ; align 256
.tx_desc rb TX_RING_SIZE*sizeof.TDESC*2
rx_desc rb RX_RING_SIZE*sizeof.RDESC*2
 
sizeof.device_struct = $ - device
rb 0x100 - ($ and 0xff) ; align 256
 
end virtual
tx_desc rb TX_RING_SIZE*sizeof.TDESC*2
 
ends
 
section '.flat' code readable align 16
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
304,20 → 294,16
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc START stdcall, state:dword
proc START stdcall, reason:dword, cmdline:dword
 
cmp [state], 1
jne .exit
cmp [reason], DRV_ENTRY
jne .fail
 
.entry:
 
DEBUGF 1,"Loading driver\n"
stdcall RegService, my_service, service_proc
invoke RegService, my_service, service_proc
ret
 
.fail:
.exit:
xor eax, eax
ret
 
324,8 → 310,6
endp
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
347,7 → 331,7
cmp [edx + IOCTL.out_size], 4
jb .fail
mov eax, [edx + IOCTL.output]
mov [eax], dword API_VERSION
mov dword[eax], API_VERSION
 
xor eax, eax
ret
375,9 → 359,9
mov ax, [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte [device.pci_bus]
cmp al, byte[ebx + device.pci_bus]
jne .next
cmp ah, byte [device.pci_dev]
cmp ah, byte[ebx + device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
.next:
add esi, 4
389,41 → 373,39
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, sizeof.device_struct, .fail ; Allocate the buffer for device structure
allocate_and_clear ebx, sizeof.device, .fail ; Allocate the buffer for device structure
 
; Fill in the direct call addresses into the struct
 
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], unload
mov [device.name], my_service
mov [ebx + device.reset], reset
mov [ebx + device.transmit], transmit
mov [ebx + device.unload], unload
mov [ebx + device.name], my_service
 
; save the pci bus and device numbers
 
mov eax, [edx + IOCTL.input]
movzx ecx, byte [eax+1]
mov [device.pci_bus], ecx
mov [ebx + device.pci_bus], ecx
movzx ecx, byte [eax+2]
mov [device.pci_dev], ecx
mov [ebx + device.pci_dev], ecx
 
; Now, it's time to find the base mmio addres of the PCI device
 
PCI_find_mmio32
stdcall PCI_find_mmio32, [ebx + device.pci_bus], [ebx + device.pci_dev] ; returns in eax
 
; Create virtual mapping of the physical memory
 
push 1Bh ; PG_SW+PG_NOCACHE
push 10000h ; size of the map
push eax
call MapIoMem
mov [device.mmio_addr], eax
invoke MapIoMem, eax, 10000h, PG_SW+PG_NOCACHE
mov [ebx + device.mmio_addr], eax
 
; We've found the mmio address, find IRQ now
 
PCI_find_irq
invoke PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
mov [ebx + device.irq_line], al
 
DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.mmio_addr]:8
[ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.mmio_addr]:8
 
; Ok, the eth_device structure is ready, let's probe the device
call probe ; this function will output in eax
436,9 → 418,8
 
call start_i8254x
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
mov [ebx + device.type], NET_TYPE_ETH
invoke NetRegDev
cmp eax, -1
je .destroy
 
448,7 → 429,7
 
.find_devicenum:
DEBUGF 1,"Trying to find device number of already registered device\n"
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
invoke NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 1,"Kernel says: %u\n", eax
460,7 → 441,7
; todo: reset device into virgin state
 
.err:
stdcall KernelFree, ebx
invoke KernelFree, ebx
 
.fail:
or eax, -1
503,15 → 484,18
 
DEBUGF 1,"Probe\n"
 
PCI_make_bus_master
; Make the device a bus master
invoke PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
or al, PCI_CMD_MASTER
invoke PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
 
; TODO: validate the device
 
call read_mac
 
movzx eax, [device.irq_line]
movzx eax, [ebx + device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
invoke AttachIntHandler, eax, int_handler, ebx
test eax, eax
jnz @f
DEBUGF 2,"Could not attach int handler!\n"
523,7 → 507,7
reset_dontstart:
DEBUGF 1,"Reset\n"
 
mov esi, [device.mmio_addr]
mov esi, [ebx + device.mmio_addr]
 
or dword[esi + REG_CTRL], CTRL_RST ; reset device
.loop:
530,7 → 514,7
push esi
xor esi, esi
inc esi
call Sleep
invoke Sleep
pop esi
test dword[esi + REG_CTRL], CTRL_RST
jnz .loop
567,17 → 551,17
align 4
init_rx:
 
lea edi, [device.rx_desc]
lea edi, [ebx + device.rx_desc]
mov ecx, RX_RING_SIZE
.loop:
push ecx
push edi
stdcall KernelAlloc, MAX_PKT_SIZE
invoke KernelAlloc, MAX_PKT_SIZE
DEBUGF 1,"RX buffer: 0x%x\n", eax
pop edi
mov dword[edi + RX_RING_SIZE*sizeof.RDESC], eax
push edi
GetRealAddr
invoke GetPhysAddr
pop edi
mov [edi + RDESC.addr_l], eax
mov [edi + RDESC.addr_h], 0
588,10 → 572,10
dec ecx
jnz .loop
 
mov [device.cur_rx], 0
mov [ebx + device.cur_rx], 0
 
lea eax, [device.rx_desc]
GetRealAddr
lea eax, [ebx + device.rx_desc]
invoke GetPhysAddr
mov dword[esi + REG_RDBAL], eax ; Receive Descriptor Base Address Low
mov dword[esi + REG_RDBAH], 0 ; Receive Descriptor Base Address High
mov dword[esi + REG_RDLEN], RX_RING_SIZE*sizeof.RDESC ; Receive Descriptor Length
607,7 → 591,7
align 4
init_tx:
 
lea edi, [device.tx_desc]
lea edi, [ebx + device.tx_desc]
mov ecx, TX_RING_SIZE
.loop:
mov [edi + TDESC.addr_l], eax
618,11 → 602,11
dec ecx
jnz .loop
 
mov [device.cur_tx], 0
mov [device.last_tx], 0
mov [ebx + device.cur_tx], 0
mov [ebx + device.last_tx], 0
 
lea eax, [device.tx_desc]
GetRealAddr
lea eax, [ebx + device.tx_desc]
invoke GetPhysAddr
mov dword[esi + REG_TDBAL], eax ; Transmit Descriptor Base Address Low
mov dword[esi + REG_TDBAH], 0 ; Transmit Descriptor Base Address High
mov dword[esi + REG_TDLEN], RX_RING_SIZE*sizeof.TDESC ; Transmit Descriptor Length
640,7 → 624,7
 
start_i8254x:
 
mov esi, [device.mmio_addr]
mov esi, [ebx + device.mmio_addr]
or dword[esi + REG_RCTL], RCTL_EN ; Enable the receiver
 
xor eax, eax
651,8 → 635,8
mov dword[esi + REG_IMS], 0x1F6DC ; Enable interrupt types
mov eax, [esi + REG_ICR] ; Clear pending interrupts
 
mov [device.mtu], 1514
mov [device.state], ETH_LINK_UNKOWN ; Set link state to unknown
mov [ebx + device.mtu], 1514
mov [ebx + device.state], ETH_LINK_UNKOWN ; Set link state to unknown
 
xor eax, eax
ret
665,15 → 649,15
 
DEBUGF 1,"Read MAC\n"
 
mov esi, [device.mmio_addr]
mov esi, [ebx + device.mmio_addr]
 
mov eax, [esi+0x5400] ; RAL
test eax, eax
jz .try_eeprom
 
mov dword[device.mac], eax
mov dword[ebx + device.mac], eax
mov eax, [esi+0x5404] ; RAH
mov word[device.mac+4], ax
mov word[ebx + device.mac+4], ax
 
jmp .mac_ok
 
681,21 → 665,22
mov dword[esi+0x14], 0x00000001
mov eax, [esi+0x14]
shr eax, 16
mov word[device.mac], ax
mov word[ebx + device.mac], ax
 
mov dword[esi+0x14], 0x00000101
mov eax, [esi+0x14]
shr eax, 16
mov word[device.mac+2], ax
mov word[ebx + device.mac+2], ax
 
mov dword[esi+0x14], 0x00000201
mov eax, [esi+0x14]
shr eax, 16
mov word[device.mac+4], ax
mov word[ebx + device.mac+4], ax
 
.mac_ok:
DEBUGF 1,"MAC = %x-%x-%x-%x-%x-%x\n",\
[device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
[ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,\
[ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
 
ret
 
726,12 → 711,12
jb .fail
 
; Program the descriptor (use legacy mode)
mov edi, [device.cur_tx]
mov edi, [ebx + device.cur_tx]
DEBUGF 1, "Using TX desc: %u\n", edi
shl edi, 4 ; edi = edi * sizeof.TDESC
lea edi, [device.tx_desc + edi]
lea edi, [ebx + device.tx_desc + edi]
mov dword[edi + TX_RING_SIZE*sizeof.TDESC], eax ; Store the data location (for driver)
GetRealAddr
invoke GetPhysAddr
mov [edi + TDESC.addr_l], eax ; Data location (for hardware)
mov [edi + TDESC.addr_h], 0
 
740,19 → 725,19
mov [edi + TDESC.length_cso_cmd], ecx
mov [edi + TDESC.status], 0
 
; Tell i8254x wich descriptor(s) we programmed
mov edi, [device.mmio_addr]
mov eax, [device.cur_tx]
; Tell i8254x wich descriptor(s) we programmed, by moving the tail
mov edi, [ebx + device.mmio_addr]
mov eax, [ebx + device.cur_tx]
inc eax
and eax, TX_RING_SIZE-1
mov [device.cur_tx], eax
mov [ebx + device.cur_tx], eax
mov dword[edi + REG_TDT], eax ; TDT - Transmit Descriptor Tail
 
; Update stats
inc [device.packets_tx]
inc [ebx + device.packets_tx]
mov eax, [buffersize]
add dword[device.bytes_tx], eax
adc dword[device.bytes_tx + 4], 0
add dword[ebx + device.bytes_tx], eax
adc dword[ebx + device.bytes_tx + 4], 0
 
popf
xor eax, eax
760,7 → 745,7
 
.fail:
DEBUGF 2,"Send failed\n"
stdcall KernelFree, [bufferptr]
invoke KernelFree, [bufferptr]
popf
or eax, -1
ret
789,8 → 774,7
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
mov edi, [device.mmio_addr]
mov edi, [ebx + device.mmio_addr]
mov eax, [edi + REG_ICR]
test eax, eax
jnz .got_it
805,7 → 789,6
ret
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x\n", ebx, eax
 
;---------
818,9 → 801,9
.retaddr:
pop ebx eax
; Get last descriptor addr
mov esi, [device.cur_rx]
mov esi, [ebx + device.cur_rx]
shl esi, 4 ; esi = esi * sizeof.RDESC
lea esi, [device.rx_desc + esi]
lea esi, [ebx + device.rx_desc + esi]
cmp byte[esi + RDESC.status_h], 0 ; Check status field
je .no_rx
 
832,30 → 815,30
push dword[esi + RX_RING_SIZE*sizeof.RDESC] ; Get packet pointer
 
; Update stats
add dword[device.bytes_rx], ecx
adc dword[device.bytes_rx + 4], 0
inc [device.packets_rx]
add dword[ebx + device.bytes_rx], ecx
adc dword[ebx + device.bytes_rx + 4], 0
inc [ebx + device.packets_rx]
 
; Allocate new descriptor
push esi
stdcall KernelAlloc, MAX_PKT_SIZE
invoke KernelAlloc, MAX_PKT_SIZE
pop esi
mov dword[esi + RX_RING_SIZE*sizeof.RDESC], eax
GetRealAddr
invoke GetPhysAddr
mov [esi + RDESC.addr_l], eax
mov [esi + RDESC.status_l], 0
mov [esi + RDESC.status_h], 0
 
; Move the receive descriptor tail
mov esi, [device.mmio_addr]
mov eax, [device.cur_rx]
mov esi, [ebx + device.mmio_addr]
mov eax, [ebx + device.cur_rx]
mov [esi + REG_RDT], eax
 
; Move to next rx desc
inc [device.cur_rx]
and [device.cur_rx], RX_RING_SIZE-1
inc [ebx + device.cur_rx]
and [ebx + device.cur_rx], RX_RING_SIZE-1
 
jmp Eth_input
jmp [Eth_input]
.no_rx:
 
;--------------
877,9 → 860,9
DEBUGF 1,"Transmit done\n"
 
.txdesc_loop:
mov edi, [device.last_tx]
mov edi, [ebx + device.last_tx]
shl edi, 4 ; edi = edi * sizeof.TDESC
lea edi, [device.tx_desc + edi]
lea edi, [ebx + device.tx_desc + edi]
test [edi + TDESC.status], TXDESC_DD ; Descriptor done?
jz .no_tx
cmp dword[edi + TX_RING_SIZE*sizeof.TDESC], 0
890,11 → 873,11
push ebx
push dword[edi + TX_RING_SIZE*sizeof.TDESC]
mov dword[edi + TX_RING_SIZE*sizeof.TDESC], 0
call KernelFree
invoke KernelFree
pop ebx
 
inc [device.last_tx]
and [device.last_tx], TX_RING_SIZE-1
inc [ebx + device.last_tx]
and [ebx + device.last_tx], TX_RING_SIZE-1
jmp .txdesc_loop
 
.no_tx:
901,7 → 884,6
pop edi esi ebx
xor eax, eax
inc eax
 
ret
 
 
909,15 → 891,14
 
; End of code
 
section '.data' data readable writable align 16
align 4
section '.data' readable writable
include '../peimport.inc'
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
include_debug_strings
my_service db 'I8254X',0 ; max 16 chars include zero
 
include_debug_strings ; All data wich FDO uses will be included here
 
align 4
devices dd 0
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
 
/drivers/netdrv_pe.inc
0,0 → 1,130
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; This macro will prepend driver name to all debug output through DEBUGF macro
; The driver name is taken from my_service label
 
if defined my_service
 
macro DEBUGF _level,_format, [args] {
common DEBUGF _level, "%s: " # _format, my_service, args
}
 
end if
 
include 'pci_pe.inc'
include 'mii.inc'
 
; Kernel variables
 
PAGESIZE = 4096
 
; Network driver types
 
NET_TYPE_ETH = 1
NET_TYPE_SLIP = 2
 
; Link state
 
ETH_LINK_DOWN = 0 ; Link is down
ETH_LINK_UNKOWN = 1b ; There could be an active link
ETH_LINK_FD = 10b ; full duplex flag
ETH_LINK_10M = 100b ; 10 mbit
ETH_LINK_100M = 1000b ; 100 mbit
ETH_LINK_1G = 10000b ; gigabit
 
; Macro to easily set i/o addresses to access device.
; In the beginning of a procedure (or ofter edx may have been destroyed),
; always use set_io with offset 0 to reset the variables.
 
LAST_IO = 0
 
macro set_io baseaddr, offset {
 
if offset = 0
mov edx, baseaddr
else if offset = LAST_IO
else
add edx, offset - LAST_IO
end if
 
LAST_IO = offset
}
 
; Macro to allocate a contiguous buffer in memory
; And initialise it to all zeros
 
; This macro will destroy eax, ecx and edi !
 
macro allocate_and_clear dest, size, err {
 
; We need to allocate at least 8 pages, if we want a contiguous area in ram
push edx
if (size < 8*4096) & (size > 4096)
invoke KernelAlloc, 8*4096
else
invoke KernelAlloc, size
end if
pop edx
 
test eax, eax
jz err
mov dest, eax
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)
push edx
invoke ReleasePages
pop edx
end if
 
; Clear the allocated buffer
mov ecx, size/4 ; divide by 4 because of DWORD
xor eax, eax
rep stosd
 
if (size - size/4*4)
mov ecx, size - size/4*4
rep stosb
end if
 
}
 
 
struct NET_DEVICE
 
type dd ? ; Type field
mtu dd ? ; Maximal Transmission Unit
name dd ? ; Ptr to 0 terminated string
 
unload dd ? ; Ptrs to driver functions
reset dd ? ;
transmit dd ? ;
 
bytes_tx dq ? ; Statistics, updated by the driver
bytes_rx dq ? ;
packets_tx dd ? ;
packets_rx dd ? ;
 
state dd ? ; link state (0 = no link)
hwacc dd ? ; bitmask stating enabled HW accelerations
 
ends
 
 
struct ETH_DEVICE NET_DEVICE
 
mac dp ?
dw ? ; qword alignment
 
ends
/drivers/pci_pe.inc
0,0 → 1,117
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
struct PCI_header
 
vendor_id dw ?
device_id dw ?
command dw ?
status dw ?
revision_id db ?
prog_if db ?
subclass db ?
class_code db ?
cache_line_size db ?
latency_timer db ?
header_type db ?
bist db ?
 
ends
 
struct PCI_header00 PCI_header
 
base_addr_0 dd ?
base_addr_1 dd ?
base_addr_2 dd ?
base_addr_3 dd ?
base_addr_4 dd ?
base_addr_5 dd ?
cardbus_cis_ptr dd ?
subsys_vendor dw ?
subsys_id dw ?
exp_rom_addr dd ?
cap_ptr db ?
reserved rb 7
interrupt_line db ?
interrupt_pin db ?
min_grant db ?
max_latency db ?
 
ends
 
; Base address bits
PCI_BASE_ADDRESS_SPACE_IO = 0x01
PCI_BASE_ADDRESS_IO_MASK = 0xFFFFFFFC
PCI_BASE_ADDRESS_MEM_MASK = 0xFFFFFFF0
 
; command bits
PCI_CMD_PIO = 1 ; bit0: io space control
PCI_CMD_MMIO = 2 ; bit1: memory space control
PCI_CMD_MASTER = 4 ; bit2: device acts as a PCI master
 
 
if used PCI_find_io
proc PCI_find_io stdcall bus, dev
 
push esi
xor eax, eax
mov esi, PCI_BASE_ADDRESS_0
.check:
invoke PciRead32, [bus], [dev], esi
 
test eax, PCI_BASE_ADDRESS_IO_MASK
jz .inc
 
test eax, PCI_BASE_ADDRESS_SPACE_IO
jz .inc
 
and eax, PCI_BASE_ADDRESS_IO_MASK
pop esi
ret
 
.inc:
add esi, 4
cmp esi, PCI_BASE_ADDRESS_5
jbe .check
pop esi
xor eax, eax
ret
 
endp
end if
 
 
if used PCI_find_mmio32
proc PCI_find_mmio32 stdcall bus, dev
 
push esi
mov esi, PCI_header00.base_addr_0
.check:
invoke PciRead32, [bus], [dev], esi
 
test eax, PCI_BASE_ADDRESS_SPACE_IO ; mmio address?
jnz .inc
 
test eax, 100b ; 64 bit?
jnz .inc
and eax, not 1111b
pop esi
ret
 
.inc:
add esi, 4
cmp esi, PCI_header00.base_addr_5
jbe .check
xor eax, eax
pop esi
ret
 
endp
end if
/drivers/peimport.inc
150,5 → 150,12
TimerHS,\
CancelTimerHS,\
\
NetRegDev,\
NetUnRegDev,\
NetPtrToNum,\
NetLinkChanged,\
Eth_input,\
IPv4_input,\
\
GetPCIList
end data