Merge new network stack with trunk

git-svn-id: svn://kolibrios.org@3545 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr
2013-05-28 17:34:26 +00:00
parent 43f6a7d07a
commit e4cf34c0de
247 changed files with 47019 additions and 18473 deletions
+2 -1
View File
@@ -6,7 +6,8 @@
#/RD/1/CROPFLAT "XS800 YS480" 1 # set limits of screen
#/RD/1/COMMOUSE "" 1 # COM mice detector
#/RD/1/DEVELOP/BOARD "" 1 # Load DEBUG board
#/RD/1/refrscrn "" 1 # Refresh screen
#/RD/1/refrscrn "" 1 # Refresh screen
/RD/1/NETWORK/NETCFG A 1 #
/RD/1/NETWORK/ZEROCONF "" 1 # Network configuration
/RD/1/MEDIA/PALITRA "H 007DCEDF 003C427F" 1 #SET BG
/RD/1/@PANEL "" 1 # Start panel
+149 -333
View File
@@ -1,387 +1,203 @@
What is implemented
===================
eax = 74 - Work directly with network interface
ebx = -1 (Get number of active network devices)
The following features are present in the TCP/IP stack code:
out:
eax = number of active network devices
IP layer.
ICMP.
TCP layer.
UDP layer.
local loopback.
Realtek 8029 PCI ethernet interface.
Realtek 8139 PCI ethernet interface.
Intel i8255x PCI ethernet interface.
Dynamic ARP table.
PPP dialer
And the following internet applcations are implemented
bh = device number, for all following functions !
HTTP Server
Telnet
POP Client
DNS Name resolver
MP3 Server
TFTP Client
IRC Client
There are also a number of experimental applications for streaming music
and performing interprocess communication via sockets. A Web broswer is in
development
bl = 0 (Get device type)
out:
eax = device type number
What is not implemented
=======================
bl = 1 (Get device name)
The IP layer does not process header options.
The IP layer does not support routing.
Packet fragmentation is not supported.
in:
ecx = pointer to 64 byte buffer
out:
name is copied into the buffer
eax = -1 on error
bl = 2 (Reset the device)
How to configure Kolibri for PPP
===============================
in
none
out
eax = -1 on error
See ppp.txt
bl = 3 (Stop device)
in
none
out
eax = -1 on error
How to configure Kolibri for Ethernet
====================================
First, you need to have a supported ethernet card fitted, or present
on your motherboard. If you are uncertain what type of hardware you
have, try to configue the stack. If you have supported hardware it
will be found, and enabled.
TO BE FIGURED OUT
Setting Up the ARP Table
------------------------
Kolibri's ARP table is dynamically created and maintained; You can see what
hosts Kolibri has communicated with by running the ARPSTAT application.
eax = 75 - Work with Sockets
Enabling Ethernet
-----------------
These functions work like the ones found in UNIX (and windows)
for more info, please read http://beej.us/guide/bgnet/
Boot Kolibri, then select STACKCFG from the NET menu.
Press the 'Read' Button, then select 'Packet Driver'.
Press 'Change' next to the IP address, and enter the IP address you want
to use. Make sure it is on the same sub-net as the LAN to which you are
connected.
Press 'Apply' to action the changes.
Close the program.
bl = 0 (Open Socket)
in:
ecx = domain
edx = type
esi = protocol
out:
eax = socket number, -1 on error
The stack is now running, which you can test by pinging Kolibri from a
remote host.
bl = 1 (Close Socket)
in:
ecx = socket number
out:
eax = -1 on error
The simplest way to connect two PC's together is using a 'Null Modem'
Ethernet cable. These simply cross certain wires over. They can be
purchased from PC stores, but are simple to make. Details can be found
on the web. Look on google for 'ethernet cross over cable' or similar.
bl = 2 (Bind)
in:
ecx = socket number
edx = pointer to sockaddr structure
esi = length of sockaddr structure
out:
eax = -1 on error
How to use TCP/IP locally, with no Network
==========================================
bl = 3 (Listen)
Kolibri supports a form of local loopback that means applications on the
same PC can communicate with each other via sockets as though they
were on separate hosts. To connect to an application on the same machine,
specify the local IP address as the destination address. You do not even
need to configure the stack for ethernet; local loopback will work without
any network hardware. It's great for development and testing.
in:
ecx = socket number
edx = backlog
out:
eax = -1 on error
bl = 4 (connect)
Application Programming Interface
=================================
in:
ecx = socket number
edx = pointer to sockaddr structure
esi = length of sockaddr structure
out:
eax = -1 on error
The developer can access the stack through interrupt 0x40, function 53.
The file TFTPC.ASM gives a good example of how to use the programming
interface ( at least, for UDP), but as network communication is complex
I'll give an overview.
bl = 5 (accept)
in:
ecx = socket number
edx = pointer to sockaddr structure
esi = length of sockaddr structure
out:
eax = socket number, -1 on error
Sockets
=======
bl = 6 (send)
Applications connect to each other and pass information between themselves
through a mechanism called a 'socket'. Sockets are end-points for
communication; You need one at each application to communicate.
in:
ecx = socket number
edx = pointer to buffer
esi = length of buffer
edi = flags
out:
eax = -1 on error
Using sockets is a little like using files on an OS; You open them, read
and write to them, then close them. The only thing that makes life slightly
more complicated is that unlike with a file, you have something intelligent
at the other end ( which for example may not want to close when you do! )
bl = 7 (receive)
Lets deal with the terminology before we go any further.
in:
ecx = socket number
edx = pointer to buffer
esi = length of buffer
edi = flags
out:
eax = number of bytes copied, -1 on error
socket A unique identifier used by the application for communication.
local port A number that identifies this application on the local host.
Ports are a way to allow multiple applications to communicate
with other hosts without the data becoming mixed up. ( The
technical term is 'multiplex' ). Port numbers are 16 bit.
remote port A number that identifies the application on the remote host
to which we are communicating with. To the remote host, this is
it's 'local port'. Port numbers are 16 bit.
IP Address A 32 bit number that identifies the remote host PC that we are
communicating with.
Passive Refers to the mode by which a socket is opened; When opening in
passive mode, the local PC is awaiting an incoming connection.
Active Refers to the mode by which a socket is opened; When opening in
active mode, the local PC will attempt to connect to a remote
PC.
bl = 8 (set socket options)
When you connect to a socket on a remote PC, you need to specify more than
just the IP address, otherwise the remote stack will not know to which
application it should send your data. You must fully qualify the address,
which means you specify the IP address and the port number. This would be
written like this
in:
ecx = socket number
edx = level
esi = optionname
edi = ptr to buffer
192.168.1.10:80 ; Connect to port 80 on the machine 192.168.1.10
The buffer's first dword is the length of the buffer, minus the first dword offcourse
Port numbers are important. Some are 'well known' and provide access to
common applications. For example port 80 is used by HTTP servers; That
way I can connect to a webserver on a host without having to find out
what port number the application is listening on.
out:
eax = -1 on error
This brings me to the way in which you open a socket; As I said earlier,
there are two modes, Passive and Active. A webserver would open a passive
socket, as it is waiting for incoming connection requests. A web browser
would open an active socket because it is attempting to connect to a
specified remote host.
bl = 9 (get socket options
in:
ecx = socket number
edx = level
esi = optionname
edi = ptr to buffer
Access to programming interface
===============================
The developer accesses the stack functions through interrupt 0x40,
function 53. Some functions may be accessed through function 52, but these
are mainly for stack configuration.
Here is a summary of the functions that you may use and the parameter
definitions.
The buffer's first dword is the length of the buffer, minus the first dword offcourse
out:
eax = -1 on error, socket option otherwise
Get Local IP Address
--------------------
eax = 52
ebx = 1
TIP
IP address returned in eax ( in internet byte order )
when you import 'network.inc' and 'macros.inc' into your source code, you can use the following syntax to work with sockets:
Write to stack input queue
--------------------------
eax = 52
ebx = 6
edx = number of bytes to write
esi = pointer to data ( in application space )
for example, to open a socket
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
This interface is for slow network drivers only ( PPP, SLIP )
mcall socket, AF_INET, SOCK_DGRAM,0
mov [socketnum], eax
then to connect to a server
Read data from network output queue
-----------------------------------
eax = 52
ebx = 8
esi = pointer to data ( in application space )
mcall connect, [socketnum], sockaddr, 18
On return, eax holds number of bytes transferred.
This interface is for slow network drivers only ( PPP, SLIP )
eax = 76 - Work with protocols
Open a UDP socket
-----------------
eax = 53
ebx = 0
ecx = local port
edx = remote port
esi = remote ip address ( in internet byte order )
high half of ebx = protocol number (for all subfunctions!)
bh = device number (for all subfunctions!)
bl = subfunction number, depends on protocol type
The socket number allocated is returned in eax.
A return value of 0xFFFFFFFF means no socket could be opened.
For Ethernet protocol
0 - Read # Packets send
1 - Read # Packets received
2 - Read # Bytes send
3 - Read # Bytes received
4 - Read MAC
5 - Write MAC
6 - Read IN-QUEUE size
7 - Read OUT-QUEUE size
For IPv4 protocol
Open a TCP socket
-----------------
eax = 53
ebx = 5
ecx = local port
edx = remote port
esi = remote ip address ( in internet byte order )
edi = mode : SOCKET_PASSIVE or SOCKET_ACTIVE ( defined in stack.inc )
0 - Read # IP packets send
1 - Read # IP packets received
2 - Read IP
3 - Write IP
4 - Read DNS
5 - Write DNS
6 - Read subnet
7 - Write subnet
8 - Read gateway
9 - Write gateway
For ARP protocol
The socket number allocated is returned in eax.
A return value of 0xFFFFFFFF means no socket could be opened.
0 - Read # ARP packets send
1 - Read # ARP packets received
2 - Get # ARP entry's
3 - Read ARP entry
4 - Add static ARP entry
5 - Remove ARP entry (-1 = remove all)
For ICMP protocol
0 - Read # ICMP packets send
1 - Read # ICMP packets received
3 - enable/disable ICMP echo reply
For UDP protocol
Close a socket (UDP Only )
--------------------------
eax = 53
ebx = 1
ecx = socket number
0 - Read # UDP packets send
1 - Read # UDP packets received
For TCP protocol
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
Close a socket (TCP Only )
--------------------------
eax = 53
ebx = 8
ecx = socket number
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
Poll socket
-----------
eax = 53
ebx = 2
ecx = socket number
On return, eax holds the number of bytes in the receive buffer.
Read socket data
----------------
eax = 53
ebx = 3
ecx = socket number
On return, eax holds the number of bytes remaining, bl holds a data byte.
Write to socket ( UDP only )
----------------------------
eax = 53
ebx = 4
ecx = socket number
edx = number of bytes to write
esi = pointer to data ( in application space )
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
Return socket status ( TCP only )
---------------------------------
eax = 53
ebx = 6
ecx = socket number
On return, eax holds the sockets TCP status.
This function can be used to determine when a socket has actually connected
to another socket - data cannot be written to a socket until the connection
is established (TCB_ESTABLISHED). The states a socket can be in are defined
in stack.inc as TCB_
Write to socket ( TCP only )
----------------------------
eax = 53
ebx = 7
ecx = socket number
edx = number of bytes to write
esi = pointer to data ( in application space )
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
Check port number
-----------------
eax = 53
ebx = 9
ecx = port number
This function is used to determine if a port number
is in use by any sockets as a local port number. Local
port numbers are normally unique.
On return, eax is 1 for port number not in use, 0 otherwise.
Opening a TCP socket in Kolibri
===============================
There are two ways to open a socket - Passive or Active.
In a Passive connection your application 'listens' for incoming
requests from remote applications. Typically this will be done when
you are implementing a server application that allows any other
application to connect to it. You would specify a 'known' local
port number, such as 80 for a web server. You would leave the
remote IP and remote port number as 0, which indicates any
remote application may connect.
Once the socket has been opened you would wait for an incoming
connection before doing anything. This can be by either checking
the socket status for TCB_ESTABLISHED, or waiting for data in the
receive buffer.
In an Active connection, you are making a connection to a specified
remote port. The remote IP and remote port parameters must be filled
in with non-zero values ( otherwise, what are you connecting to? ).
You also specify a unique local port number so the remote application
can uniquely identify you - after all, there may be several applications
on your machine connected to the same remote host. See below for finding
a unique port number.
How to find an unused local port number
=======================================
Typically when you are creating an active connection to a remote
socket you will want to choose a unique local port number. Local
port numbers normally start from 1000; The following code may
be used to obtain an unused port number prior to making the
open socket call.
mov ecx, 1000 ; local port starting at 1000
getlp:
inc ecx
push ecx
mov eax, 53
mov ebx, 9
int 0x40
pop ecx
cmp eax, 0 ; is this local port in use?
jz getlp ; yes - so try next
; ecx contains a free local port number
Writing data to a socket
========================
There are two functions available depending on whether the socket
was opened for TCP or UDP protocol; The call parameters are the
same however. When the socket is being opened for TCP, use the
status function to poll for a connection - data cannot be written
to a socket until another socket has connected to it, and the
state of the socket is TCB_ESTABLISHED.
When you write data, the call results in a single IP packet being
created and transmitted. Thus the user application is responsible for
the size of transmitted packets. Keep the packet sizes under 768 bytes.
If you are writing a terminal program like telnet, you may want to send
a packet for each keystroke ( inefficient ) or use a timer to send data
periodically ( say, every second ).
Reading data from a socket
==========================
There is one function to read data from a sockets receive buffer. This
function retrieves one byte at a time. You can use the poll function to
test the receive buffer for data.
Closing a socket
================
Simply call the appropriate function - there is one for TCP, and another
for UDP. When closing a TCP socket, don't forget that the other end
may continue to send data, so the socket may remain active for a
few seconds after your call.
If you have any questions or have suggestions for improving this
document please contact me at mikeh@oceanfree.net.
0 - Read # TCP packets send
1 - Read # TCP packets received
+11 -19
View File
@@ -128,27 +128,19 @@ Hex-Editor /rd/1/develop/heed
#15 **** NET ****
Servers > /@16
Clients > /@17
Configuration /rd/1/network/stackcfg
Zero-Config /rd/1/network/zeroconf
Network status /rd/1/network/ethstat
ARP status /rd/1/network/arpstat
Zero-Config /sys/network/zeroconf
network Config /sys/network/netcfg
Network status /sys/network/netstat
ARP status /sys/network/arpcfg
#16 **** SERVERS ****
SMTPS /rd/1/network/smtps
HTTPS /rd/1/network/https
FTPS /rd/1/network/ftps
FTP daemon /sys/network/ftpd
#17 **** CLIENTS ****
TFTP client /rd/1/network/tftpc
Internet-chess /rd/1/network/chess
Internet downloader /rd/1/network/downloader
Text-based browser /rd/1/htmlv
NNTP-NewsGroups /rd/1/network/nntpc
TELNET /rd/1/network/telnet
POP - MAIL /rd/1/network/popc
IRC client /rd/1/network/airc
YAHOO messenger (demo) /rd/1/network/ym
JMail /rd/1/network/jmail
VNC client /rd/1/network/vncclient
DNS resolver /rd/1/network/nslookup
IRC client /sys/network/ircc
TFTP client /sys/network/tftpc
Ping /sys/network/ping
Telnet client /sys/network/telnet
Synergy client /sys/network/synergyc
DNS lookup /sys/network/nslookup
#18 **** OTHER ****
Analogue clock /rd/1/demos/aclock
Binary clock /rd/1/demos/bcdclk
+9
View File
@@ -0,0 +1,9 @@
[ipconfig]
; type should be static or zeroconf
; zeroconf means the service first tries to contact a DHCP server
; If dhcp is not available, it switches to link-local
type = zeroconf
ip = 192.168.1.150
gateway = 192.168.1.1
dns = 192.168.1.1
subnet = 255.255.255.0
+1
View File
@@ -7,6 +7,7 @@
#/RD/1/COMMOUSE "" 1 # COM mice detector
#/RD/1/DEVELOP/BOARD "" 1 # Load DEBUG board
#/RD/1/refrscrn "" 1 # Refresh screen
/RD/1/NETWORK/NETCFG A 1 #
/RD/1/NETWORK/ZEROCONF "" 1 # Network configuration
/RD/1/MEDIA/PALITRA "H 007DCEDF 003C427F" 1 #SET BG
/RD/1/@PANEL "" 1 # Start panel
+11 -19
View File
@@ -133,27 +133,19 @@ HEX-।
#15 **** NET ****
Серверы > /@16
Клиенты > /@17
Конфигурация /rd/1/network/stackcfg
Zero-Config /rd/1/network/zeroconf
Статус сети /rd/1/network/ethstat
Статус ARP /rd/1/network/arpstat
Zero-Config /sys/network/zeroconf
network Config /sys/network/netcfg
Network status /sys/network/netstat
ARP status /sys/network/arpcfg
#16 **** SERVERS ****
SMTPS /rd/1/network/smtps
HTTPS /rd/1/network/https
FTPS /rd/1/network/ftps
FTP daemon /sys/network/ftpd
#17 **** CLIENTS ****
TFTP-клиент /rd/1/network/tftpc
Интернет-шахматы /rd/1/network/chess
Интернет загрузчик /rd/1/network/downloader
Текстовый браузер /rd/1/htmlv
NNTP-группы новостей /rd/1/network/nntpc
TELNET /rd/1/network/telnet
POP-почта /rd/1/network/popc
IRC-клиент /rd/1/network/airc
YAHOO IM (демо) /rd/1/network/ym
JMail /rd/1/network/jmail
VNC-клиент /rd/1/network/vncclient
DNS resolver /rd/1/network/nslookup
IRC client /sys/network/ircc
TFTP client /sys/network/tftpc
Ping /sys/network/ping
Telnet client /sys/network/telnet
Synergy client /sys/network/synergyc
DNS lookup /sys/network/nslookup
#18 **** OTHER ****
Аналоговые часы /rd/1/demos/aclock
Бинарные часы /rd/1/demos/bcdclk
+9
View File
@@ -0,0 +1,9 @@
[ipconfig]
; type should be static or zeroconf
; zeroconf means the service first tries to contact a DHCP server
; If dhcp is not available, it switches to link-local
type = zeroconf
ip = 192.168.1.150
gateway = 192.168.1.1
dns = 192.168.1.1
subnet = 255.255.255.0
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+424
View File
@@ -0,0 +1,424 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Broadcom NetXtreme 57xx driver for KolibriOS ;;
;; ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; Broadcom's programmers's manual for the BCM57xx ;;
;; http://www.broadcom.com/collateral/pg/57XX-PG105-R.pdf ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TODO: make better use of the available descriptors
format MS COFF
API_VERSION = 0x01000100
DRIVER_VERSION = 5
MAX_DEVICES = 16
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 2
include '../proc32.inc'
include '../imports.inc'
include '../fdo.inc'
include '../netdrv.inc'
public START
public service_proc
public version
virtual at ebx
device:
ETH_DEVICE
.mmio_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
.cur_tx dd ?
.last_tx dd ?
rb 0x100 - (($ - device) and 0xff)
.rx_desc rd 256/8
rb 0x100 - (($ - device) and 0xff)
.tx_desc rd 256/8
sizeof.device_struct = $ - device
end virtual
section '.flat' code readable align 16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
proc START stdcall, state:dword
cmp [state], 1
jne .exit
.entry:
DEBUGF 2,"Loading %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
.fail:
.exit:
xor eax, eax
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
proc service_proc stdcall, ioctl:dword
mov edx, [ioctl]
mov eax, [IOCTL.io_code]
;------------------------------------------------------
cmp eax, 0 ;SRV_GETVERSION
jne @F
cmp [IOCTL.out_size], 4
jb .fail
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
xor eax, eax
ret
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
mov eax, [IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet
; check if the device is already listed
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax, [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte [device.pci_bus]
jne .next
cmp ah, byte [device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
.next:
add esi, 4
loop .nextdevice
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
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
; 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
; save the pci bus and device numbers
mov eax, [IOCTL.input]
movzx ecx, byte [eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte [eax+2]
mov [device.pci_dev], ecx
; Now, it's time to find the base mmio addres of the PCI device
PCI_find_mmio32
; 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
; We've found the mmio address, find IRQ now
PCI_find_irq
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
; Ok, the eth_device structure is ready, let's probe the device
call probe ; this function will output in eax
test eax, eax
jnz .err ; If an error occured, exit
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
mov [device.type], NET_TYPE_ETH
call NetRegDev
cmp eax, -1
je .destroy
ret
; If the device was already loaded, find the device number and return it in eax
.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
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 1,"Kernel says: %u\n", eax
ret
; If an error occured, remove all allocated data and exit (returning -1 in eax)
.destroy:
; todo: reset device into virgin state
.err:
stdcall KernelFree, ebx
.fail:
or eax, -1
ret
;------------------------------------------------------
endp
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
align 4
unload:
; TODO: (in this particular order)
;
; - Stop the device
; - Detach int handler
; - Remove device from local list (device_list)
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
or eax, -1
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; probe: enables the device (if it really is I8254X)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
probe:
DEBUGF 1,"Probe\n"
PCI_make_bus_master
; TODO: validate the device
align 4
reset:
DEBUGF 1,"Reset\n"
movzx eax, [device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax
jnz @f
DEBUGF 1,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
call read_mac
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
ret
align 4
read_mac:
DEBUGF 1,"Read MAC\n"
mov esi, [device.mmio_addr]
lea edi, [device.mac]
movsd
movsw
.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
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
transmit:
DEBUGF 2,"\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
DEBUGF 2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
cmp dword [esp + 8], 1514
ja .fail
cmp dword [esp + 8], 60
jb .fail
; Update stats
inc [device.packets_tx]
mov eax, [esp + 8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
ret 8
.fail:
DEBUGF 1,"Send failed\n"
ret 8
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
align 4
int_handler:
push ebx esi edi
DEBUGF 1,"\n%s int\n", my_service
;-------------------------------------------
; Find pointer of device wich made IRQ occur
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
; mov edi, [device.mmio_addr]
; mov eax, [edi + REG_ICR]
test eax, eax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
pop edi esi ebx
xor eax, eax
ret
.got_it:
DEBUGF 1,"Device: %x Status: %x ", ebx, eax
pop edi esi ebx
xor eax, eax
inc eax
ret
; End of code
section '.data' data readable writable align 16
align 4
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'BCM57XX',0 ; max 16 chars include zero
include_debug_strings ; All data wich FDO uses will be included here
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+818
View File
@@ -0,0 +1,818 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; i8254x driver for KolibriOS ;;
;; ;;
;; based on i8254x.asm from baremetal os ;;
;; ;;
;; Written by hidnplayr (hidnplayr@gmail.com) ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TODO: make better use of the available descriptors
format MS COFF
API_VERSION = 0x01000100
DRIVER_VERSION = 5
MAX_DEVICES = 16
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 2
MAX_PKT_SIZE = 16384 ; Maximum packet size
include '../proc32.inc'
include '../imports.inc'
include '../fdo.inc'
include '../struct.inc'
include '../netdrv.inc'
public START
public service_proc
public version
; Register list
REG_CTRL = 0x0000 ; Control Register
REG_STATUS = 0x0008 ; Device Status Register
REG_CTRLEXT = 0x0018 ; Extended Control Register
REG_MDIC = 0x0020 ; MDI Control Register
REG_FCAL = 0x0028 ; Flow Control Address Low
REG_FCAH = 0x002C ; Flow Control Address High
REG_FCT = 0x0030 ; Flow Control Type
REG_VET = 0x0038 ; VLAN Ether Type
REG_ICR = 0x00C0 ; Interrupt Cause Read
REG_ITR = 0x00C4 ; Interrupt Throttling Register
REG_ICS = 0x00C8 ; Interrupt Cause Set Register
REG_IMS = 0x00D0 ; Interrupt Mask Set/Read Register
REG_IMC = 0x00D8 ; Interrupt Mask Clear Register
REG_RCTL = 0x0100 ; Receive Control Register
REG_FCTTV = 0x0170 ; Flow Control Transmit Timer Value
REG_TXCW = 0x0178 ; Transmit Configuration Word
REG_RXCW = 0x0180 ; Receive Configuration Word
REG_TCTL = 0x0400 ; Transmit Control Register
REG_TIPG = 0x0410 ; Transmit Inter Packet Gap
REG_LEDCTL = 0x0E00 ; LED Control
REG_PBA = 0x1000 ; Packet Buffer Allocation
REG_RDBAL = 0x2800 ; RX Descriptor Base Address Low
REG_RDBAH = 0x2804 ; RX Descriptor Base Address High
REG_RDLEN = 0x2808 ; RX Descriptor Length
REG_RDH = 0x2810 ; RX Descriptor Head
REG_RDT = 0x2818 ; RX Descriptor Tail
REG_RDTR = 0x2820 ; RX Delay Timer Register
REG_RXDCTL = 0x3828 ; RX Descriptor Control
REG_RADV = 0x282C ; RX Int. Absolute Delay Timer
REG_RSRPD = 0x2C00 ; RX Small Packet Detect Interrupt
REG_TXDMAC = 0x3000 ; TX DMA Control
REG_TDBAL = 0x3800 ; TX Descriptor Base Address Low
REG_TDBAH = 0x3804 ; TX Descriptor Base Address High
REG_TDLEN = 0x3808 ; TX Descriptor Length
REG_TDH = 0x3810 ; TX Descriptor Head
REG_TDT = 0x3818 ; TX Descriptor Tail
REG_TIDV = 0x3820 ; TX Interrupt Delay Value
REG_TXDCTL = 0x3828 ; TX Descriptor Control
REG_TADV = 0x382C ; TX Absolute Interrupt Delay Value
REG_TSPMT = 0x3830 ; TCP Segmentation Pad & Min Threshold
REG_RXCSUM = 0x5000 ; RX Checksum Control
; Register list for i8254x
I82542_REG_RDTR = 0x0108 ; RX Delay Timer Register
I82542_REG_RDBAL = 0x0110 ; RX Descriptor Base Address Low
I82542_REG_RDBAH = 0x0114 ; RX Descriptor Base Address High
I82542_REG_RDLEN = 0x0118 ; RX Descriptor Length
I82542_REG_RDH = 0x0120 ; RDH for i82542
I82542_REG_RDT = 0x0128 ; RDT for i82542
I82542_REG_TDBAL = 0x0420 ; TX Descriptor Base Address Low
I82542_REG_TDBAH = 0x0424 ; TX Descriptor Base Address Low
I82542_REG_TDLEN = 0x0428 ; TX Descriptor Length
I82542_REG_TDH = 0x0430 ; TDH for i82542
I82542_REG_TDT = 0x0438 ; TDT for i82542
; CTRL - Control Register (0x0000)
CTRL_FD = 0x00000001 ; Full Duplex
CTRL_LRST = 0x00000008 ; Link Reset
CTRL_ASDE = 0x00000020 ; Auto-speed detection
CTRL_SLU = 0x00000040 ; Set Link Up
CTRL_ILOS = 0x00000080 ; Invert Loss of Signal
CTRL_SPEED_MASK = 0x00000300 ; Speed selection
CTRL_SPEED_SHIFT = 8
CTRL_FRCSPD = 0x00000800 ; Force Speed
CTRL_FRCDPLX = 0x00001000 ; Force Duplex
CTRL_SDP0_DATA = 0x00040000 ; SDP0 data
CTRL_SDP1_DATA = 0x00080000 ; SDP1 data
CTRL_SDP0_IODIR = 0x00400000 ; SDP0 direction
CTRL_SDP1_IODIR = 0x00800000 ; SDP1 direction
CTRL_RST = 0x04000000 ; Device Reset
CTRL_RFCE = 0x08000000 ; RX Flow Ctrl Enable
CTRL_TFCE = 0x10000000 ; TX Flow Ctrl Enable
CTRL_VME = 0x40000000 ; VLAN Mode Enable
CTRL_PHY_RST = 0x80000000 ; PHY reset
; STATUS - Device Status Register (0x0008)
STATUS_FD = 0x00000001 ; Full Duplex
STATUS_LU = 0x00000002 ; Link Up
STATUS_TXOFF = 0x00000010 ; Transmit paused
STATUS_TBIMODE = 0x00000020 ; TBI Mode
STATUS_SPEED_MASK = 0x000000C0 ; Link Speed setting
STATUS_SPEED_SHIFT = 6
STATUS_ASDV_MASK = 0x00000300 ; Auto Speed Detection
STATUS_ASDV_SHIFT = 8
STATUS_PCI66 = 0x00000800 ; PCI bus speed
STATUS_BUS64 = 0x00001000 ; PCI bus width
STATUS_PCIX_MODE = 0x00002000 ; PCI-X mode
STATUS_PCIXSPD_MASK = 0x0000C000 ; PCI-X speed
STATUS_PCIXSPD_SHIFT = 14
; CTRL_EXT - Extended Device Control Register (0x0018)
CTRLEXT_PHY_INT = 0x00000020 ; PHY interrupt
CTRLEXT_SDP6_DATA = 0x00000040 ; SDP6 data
CTRLEXT_SDP7_DATA = 0x00000080 ; SDP7 data
CTRLEXT_SDP6_IODIR = 0x00000400 ; SDP6 direction
CTRLEXT_SDP7_IODIR = 0x00000800 ; SDP7 direction
CTRLEXT_ASDCHK = 0x00001000 ; Auto-Speed Detect Chk
CTRLEXT_EE_RST = 0x00002000 ; EEPROM reset
CTRLEXT_SPD_BYPS = 0x00008000 ; Speed Select Bypass
CTRLEXT_RO_DIS = 0x00020000 ; Relaxed Ordering Dis.
CTRLEXT_LNKMOD_MASK = 0x00C00000 ; Link Mode
CTRLEXT_LNKMOD_SHIFT = 22
; MDIC - MDI Control Register (0x0020)
MDIC_DATA_MASK = 0x0000FFFF ; Data
MDIC_REG_MASK = 0x001F0000 ; PHY Register
MDIC_REG_SHIFT = 16
MDIC_PHY_MASK = 0x03E00000 ; PHY Address
MDIC_PHY_SHIFT = 21
MDIC_OP_MASK = 0x0C000000 ; Opcode
MDIC_OP_SHIFT = 26
MDIC_R = 0x10000000 ; Ready
MDIC_I = 0x20000000 ; Interrupt Enable
MDIC_E = 0x40000000 ; Error
; ICR - Interrupt Cause Read (0x00c0)
ICR_TXDW = 0x00000001 ; TX Desc Written back
ICR_TXQE = 0x00000002 ; TX Queue Empty
ICR_LSC = 0x00000004 ; Link Status Change
ICR_RXSEQ = 0x00000008 ; RX Sence Error
ICR_RXDMT0 = 0x00000010 ; RX Desc min threshold reached
ICR_RXO = 0x00000040 ; RX Overrun
ICR_RXT0 = 0x00000080 ; RX Timer Interrupt
ICR_MDAC = 0x00000200 ; MDIO Access Complete
ICR_RXCFG = 0x00000400
ICR_PHY_INT = 0x00001000 ; PHY Interrupt
ICR_GPI_SDP6 = 0x00002000 ; GPI on SDP6
ICR_GPI_SDP7 = 0x00004000 ; GPI on SDP7
ICR_TXD_LOW = 0x00008000 ; TX Desc low threshold hit
ICR_SRPD = 0x00010000 ; Small RX packet detected
; RCTL - Receive Control Register (0x0100)
RCTL_EN = 0x00000002 ; Receiver Enable
RCTL_SBP = 0x00000004 ; Store Bad Packets
RCTL_UPE = 0x00000008 ; Unicast Promiscuous Enabled
RCTL_MPE = 0x00000010 ; Xcast Promiscuous Enabled
RCTL_LPE = 0x00000020 ; Long Packet Reception Enable
RCTL_LBM_MASK = 0x000000C0 ; Loopback Mode
RCTL_LBM_SHIFT = 6
RCTL_RDMTS_MASK = 0x00000300 ; RX Desc Min Threshold Size
RCTL_RDMTS_SHIFT = 8
RCTL_MO_MASK = 0x00003000 ; Multicast Offset
RCTL_MO_SHIFT = 12
RCTL_BAM = 0x00008000 ; Broadcast Accept Mode
RCTL_BSIZE_MASK = 0x00030000 ; RX Buffer Size
RCTL_BSIZE_SHIFT = 16
RCTL_VFE = 0x00040000 ; VLAN Filter Enable
RCTL_CFIEN = 0x00080000 ; CFI Enable
RCTL_CFI = 0x00100000 ; Canonical Form Indicator Bit
RCTL_DPF = 0x00400000 ; Discard Pause Frames
RCTL_PMCF = 0x00800000 ; Pass MAC Control Frames
RCTL_BSEX = 0x02000000 ; Buffer Size Extension
RCTL_SECRC = 0x04000000 ; Strip Ethernet CRC
; TCTL - Transmit Control Register (0x0400)
TCTL_EN = 0x00000002 ; Transmit Enable
TCTL_PSP = 0x00000008 ; Pad short packets
TCTL_SWXOFF = 0x00400000 ; Software XOFF Transmission
; PBA - Packet Buffer Allocation (0x1000)
PBA_RXA_MASK = 0x0000FFFF ; RX Packet Buffer
PBA_RXA_SHIFT = 0
PBA_TXA_MASK = 0xFFFF0000 ; TX Packet Buffer
PBA_TXA_SHIFT = 16
; Flow Control Type
FCT_TYPE_DEFAULT = 0x8808
; === TX Descriptor fields ===
; TX Packet Length (word 2)
TXDESC_LEN_MASK = 0x0000ffff
; TX Descriptor CMD field (word 2)
TXDESC_IDE = 0x80000000 ; Interrupt Delay Enable
TXDESC_VLE = 0x40000000 ; VLAN Packet Enable
TXDESC_DEXT = 0x20000000 ; Extension
TXDESC_RPS = 0x10000000 ; Report Packet Sent
TXDESC_RS = 0x08000000 ; Report Status
TXDESC_IC = 0x04000000 ; Insert Checksum
TXDESC_IFCS = 0x02000000 ; Insert FCS
TXDESC_EOP = 0x01000000 ; End Of Packet
; TX Descriptor STA field (word 3)
TXDESC_TU = 0x00000008 ; Transmit Underrun
TXDESC_LC = 0x00000004 ; Late Collision
TXDESC_EC = 0x00000002 ; Excess Collisions
TXDESC_DD = 0x00000001 ; Descriptor Done
; === RX Descriptor fields ===
; RX Packet Length (word 2)
RXDESC_LEN_MASK = 0x0000ffff
; RX Descriptor STA field (word 3)
RXDESC_PIF = 0x00000080 ; Passed In-exact Filter
RXDESC_IPCS = 0x00000040 ; IP cksum calculated
RXDESC_TCPCS = 0x00000020 ; TCP cksum calculated
RXDESC_VP = 0x00000008 ; Packet is 802.1Q
RXDESC_IXSM = 0x00000004 ; Ignore cksum indication
RXDESC_EOP = 0x00000002 ; End Of Packet
RXDESC_DD = 0x00000001 ; Descriptor Done
virtual at ebx
device:
ETH_DEVICE
.mmio_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
.cur_tx dd ?
.last_tx dd ?
rb 0x100 - (($ - device) and 0xff)
.rx_desc rd 256/8
rb 0x100 - (($ - device) and 0xff)
.tx_desc rd 256/8
sizeof.device_struct = $ - device
end virtual
section '.flat' code readable align 16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
proc START stdcall, state:dword
cmp [state], 1
jne .exit
.entry:
DEBUGF 2,"Loading %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
.fail:
.exit:
xor eax, eax
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
proc service_proc stdcall, ioctl:dword
mov edx, [ioctl]
mov eax, [IOCTL.io_code]
;------------------------------------------------------
cmp eax, 0 ;SRV_GETVERSION
jne @F
cmp [IOCTL.out_size], 4
jb .fail
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
xor eax, eax
ret
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
mov eax, [IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet
; check if the device is already listed
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax, [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte [device.pci_bus]
jne .next
cmp ah, byte [device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
.next:
add esi, 4
loop .nextdevice
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
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
; 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
; save the pci bus and device numbers
mov eax, [IOCTL.input]
movzx ecx, byte [eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte [eax+2]
mov [device.pci_dev], ecx
; Now, it's time to find the base mmio addres of the PCI device
PCI_find_mmio32
; 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
; We've found the mmio address, find IRQ now
PCI_find_irq
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
; Ok, the eth_device structure is ready, let's probe the device
call probe ; this function will output in eax
test eax, eax
jnz .err ; If an error occured, exit
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
call start_i8254x
mov [device.type], NET_TYPE_ETH
call NetRegDev
cmp eax, -1
je .destroy
ret
; If the device was already loaded, find the device number and return it in eax
.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
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 1,"Kernel says: %u\n", eax
ret
; If an error occured, remove all allocated data and exit (returning -1 in eax)
.destroy:
; todo: reset device into virgin state
.err:
stdcall KernelFree, ebx
.fail:
or eax, -1
ret
;------------------------------------------------------
endp
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
align 4
unload:
; TODO: (in this particular order)
;
; - Stop the device
; - Detach int handler
; - Remove device from local list (device_list)
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
or eax, -1
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; probe: enables the device (if it really is I8254X)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
probe:
DEBUGF 1,"Probe\n"
PCI_make_bus_master
; TODO: validate the device
call read_mac
movzx eax, [device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax
jnz @f
DEBUGF 1,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
reset_dontstart:
DEBUGF 1,"Reset\n"
mov esi, [device.mmio_addr]
or dword [esi + REG_CTRL], CTRL_RST ; reset device
.loop:
push esi
xor esi, esi
inc esi
call Sleep
pop esi
test dword [esi + REG_CTRL], CTRL_RST
jnz .loop
mov dword [esi + REG_IMC], 0xffffffff ; Disable all interrupt causes
mov eax, dword [esi + REG_ICR] ; Clear any pending interrupts
mov dword [esi + REG_ITR], 0 ; Disable interrupt throttling logic
mov dword [esi + REG_PBA], 0x00000030 ; PBA: set the RX buffer size to 48KB (TX buffer is calculated as 64-RX buffer)
mov dword [esi + REG_RDTR], 0 ; RDTR: set no delay
mov dword [esi + REG_TXCW], 0x08008060 ; TXCW: set ANE, TxConfigWord (Half/Full duplex, Next Page Reqest)
mov eax, [esi + REG_CTRL]
or eax, 1 shl 6 + 1 shl 5
and eax, not (1 shl 3 + 1 shl 7 + 1 shl 30 + 1 shl 31)
mov dword [esi + REG_CTRL], eax ; CTRL: clear LRST, set SLU and ASDE, clear RSTPHY, VME, and ILOS
lea edi, [esi + 0x5200] ; MTA: reset
mov eax, 0xffffffff
stosd
stosd
stosd
stosd
stdcall KernelAlloc, 48*1024
mov dword [device.rx_desc + 16], eax
GetRealAddr
mov dword [device.rx_desc], eax
mov dword [device.rx_desc + 4], 0
lea eax, [device.rx_desc]
GetRealAddr
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], (1 * 128) ; Receive Descriptor Length
mov dword [esi + REG_RDH], 0 ; Receive Descriptor Head
mov dword [esi + REG_RDT], 1 ; Receive Descriptor Tail
mov dword [esi + REG_RCTL], RCTL_EN or RCTL_SBP or RCTL_BAM or RCTL_SECRC or RCTL_UPE or RCTL_MPE
; Receiver Enable, Store Bad Packets, Broadcast Accept Mode, Strip Ethernet CRC from incoming packet, Promiscuous mode
mov dword [device.tx_desc], 0
mov dword [device.tx_desc + 4], 0
mov dword [device.tx_desc + 16], 0
lea eax, [device.tx_desc]
GetRealAddr
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], (1 * 128) ; Transmit Descriptor Length
mov dword [esi + REG_TDH], 0 ; Transmit Descriptor Head
mov dword [esi + REG_TDT], 0 ; Transmit Descriptor Tail
mov dword [esi + REG_TCTL], 0x010400fa ; Enabled, Pad Short Packets, 15 retrys, 64-byte COLD, Re-transmit on Late Collision
mov dword [esi + REG_TIPG], 0x0060200A ; IPGT 10, IPGR1 8, IPGR2 6
xor eax, eax
ret
align 4
reset:
call reset_dontstart
start_i8254x:
xor eax, eax
mov [esi + REG_RDTR], eax ; Clear the Receive Delay Timer Register
mov [esi + REG_RADV], eax ; Clear the Receive Interrupt Absolute Delay Timer
mov [esi + REG_RSRPD], eax ; Clear the Receive Small Packet Detect Interrupt
; or eax, 1 shl 0 + 1 shl 7 ; TXDW + RXT0
mov eax, 1+4+16 ;;;; hack!
mov [esi + REG_IMS], eax ; Enable interrupt types
mov [device.mtu], 1514
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
xor eax, eax
ret
align 4
read_mac:
DEBUGF 1,"Read MAC\n"
mov esi, [device.mmio_addr]
mov eax, [esi+0x5400] ; RAL
test eax, eax
jz .try_eeprom
mov dword [device.mac], eax
mov eax, [esi+0x5404] ; RAH
mov word [device.mac+4], ax
jmp .mac_ok
.try_eeprom:
mov dword [esi+0x14], 0x00000001
mov eax, [esi+0x14]
shr eax, 16
mov word [device.mac], ax
mov dword [esi+0x14], 0x00000101
mov eax, [esi+0x14]
shr eax, 16
mov word [device.mac+2], ax
mov dword [esi+0x14], 0x00000201
mov eax, [esi+0x14]
shr eax, 16
mov word [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
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
transmit:
DEBUGF 2,"\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
DEBUGF 2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
cmp dword [esp + 8], 1514
ja .fail
cmp dword [esp + 8], 60
jb .fail
; Program the descriptor (use legacy mode)
lea edi, [device.tx_desc] ; Transmit Descriptor Base Address
mov dword [edi + 16], eax ; Store the data location (for driver)
GetRealAddr ;
mov dword [edi], eax ; Real addr (for i8254x)
mov dword [edi + 4], 0x00000000 ;
mov ecx, [esp + 8]
or ecx, 1 shl 24 + 1 shl 25 + 1 shl 27 ; EOP + IFCS + RS
mov dword [edi + 8], ecx ; Packet size
mov dword [edi + 12], 0x00000000
; Tell i8254x wich descriptor(s) we programmed
mov edi, [device.mmio_addr]
mov dword [edi + REG_TDH], 0 ; TDH - Transmit Descriptor Head
mov dword [edi + REG_TDT], 1 ; TDT - Transmit Descriptor Tail
; Update stats
inc [device.packets_tx]
mov eax, [esp + 8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
ret 8
.fail:
DEBUGF 1,"Send failed\n"
ret 8
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
align 4
int_handler:
push ebx esi edi
DEBUGF 1,"\n%s int\n", my_service
;-------------------------------------------
; Find pointer of device wich made IRQ occur
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
mov edi, [device.mmio_addr]
mov eax, [edi + REG_ICR]
test eax, eax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
pop edi esi ebx
xor eax, eax
ret
.got_it:
DEBUGF 1,"Device: %x Status: %x ", ebx, eax
;---------
; RX done?
test eax, ICR_RXDMT0
jz .no_rx
push eax ebx
push .retaddr
; Get last descriptor addr
lea esi, [device.rx_desc]
cmp byte [esi + 12], 0 ; Check status field
je .retaddr
movzx ecx, word [esi + 8] ; Get the packet length
DEBUGF 2,"got %u bytes\n", ecx
push ecx
push dword [esi + 16] ; Get packet pointer
; Update stats
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
inc dword [device.packets_rx]
; allocate new descriptor
stdcall KernelAlloc, 48*1024
mov dword [esi + 16], eax
GetRealAddr
mov dword [esi], eax
; reset descriptor status
mov esi, [device.mmio_addr]
mov dword [esi + REG_RDH], 0x00000000 ; Receive Descriptor Head
mov dword [esi + REG_RDT], 0x00000001 ; Receive Descriptor Tail
jmp Eth_input
.retaddr:
pop ebx eax
.no_rx:
;--------------
; Link Changed?
test eax, ICR_LSC
jz .no_link
DEBUGF 2,"Link Changed\n"
.no_link:
;---------------
; Transmit done?
test eax, ICR_TXDW
jz .no_tx
DEBUGF 2,"Transmit done\n"
lea edi, [device.tx_desc] ; Transmit Descriptor Base Address
push dword [edi + 16] ; Store the data location (for driver)
call KernelFree
.no_tx:
.fail:
pop edi esi ebx
xor eax, eax
inc eax
ret
; End of code
section '.data' data readable writable align 16
align 4
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'I8254X',0 ; max 16 chars include zero
include_debug_strings ; All data wich FDO uses will be included here
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+432
View File
@@ -0,0 +1,432 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Formatted Debug Output (FDO)
; Copyright (c) 2005-2006, mike.dld
; Created: 2005-01-29, Changed: 2006-11-10
;
; For questions and bug reports, mail to mike.dld@gmail.com
;
; Available format specifiers are: %s, %d, %u, %x (with partial width support)
;
; to be defined:
; __DEBUG__ equ 1
; __DEBUG_LEVEL__ equ 5
macro debug_func name {
if used name
name@of@func equ name
}
macro debug_beginf {
align 4
name@of@func:
}
debug_endf fix end if
macro DEBUGS _sign,[_str] {
common
local tp
tp equ 0
match _arg:_num,_str \{
DEBUGS_N _sign,_num,_arg
tp equ 1
\}
match =0 _arg,tp _str \{
DEBUGS_N _sign,,_arg
\}
}
macro DEBUGS_N _sign,_num,[_str] {
common
pushf
pushad
local ..str,..label,is_str
is_str = 0
forward
if _str eqtype ''
is_str = 1
end if
common
if is_str = 1
jmp ..label
..str db _str,0
..label:
add esp,4*8+4
mov edx,..str
sub esp,4*8+4
else
mov edx,_str
end if
if ~_num eq
if _num eqtype eax
if _num in <eax,ebx,ecx,edx,edi,ebp,esp>
mov esi,_num
else if ~_num eq esi
movzx esi,_num
end if
else if _num eqtype 0
mov esi,_num
else
local tp
tp equ 0
match [_arg],_num \{
mov esi,dword[_arg]
tp equ 1
\}
match =0 =dword[_arg],tp _num \{
mov esi,dword[_arg]
tp equ 1
\}
match =0 =word[_arg],tp _num \{
movzx esi,word[_arg]
tp equ 1
\}
match =0 =byte[_arg],tp _num \{
movzx esi,byte[_arg]
tp equ 1
\}
match =0,tp \{
'Error: specified string width is incorrect'
\}
end if
else
mov esi,0x7FFFFFFF
end if
call fdo_debug_outstr
popad
popf
}
macro DEBUGD _sign,_dec {
local tp
tp equ 0
match _arg:_num,_dec \{
DEBUGD_N _sign,_num,_arg
tp equ 1
\}
match =0 _arg,tp _dec \{
DEBUGD_N _sign,,_arg
\}
}
macro DEBUGD_N _sign,_num,_dec {
pushf
pushad
if (~_num eq)
if (_dec eqtype eax | _dec eqtype 0)
'Error: precision allowed only for in-memory variables'
end if
if (~_num in <1,2,4>)
if _sign
'Error: 1, 2 and 4 are only allowed for precision in %d'
else
'Error: 1, 2 and 4 are only allowed for precision in %u'
end if
end if
end if
if _dec eqtype eax
if _dec in <ebx,ecx,edx,esi,edi,ebp,esp>
mov eax,_dec
else if ~_dec eq eax
if _sign = 1
movsx eax,_dec
else
movzx eax,_dec
end if
end if
else if _dec eqtype 0
mov eax,_dec
else
add esp,4*8+4
if _num eq
mov eax,dword _dec
else if _num = 1
if _sign = 1
movsx eax,byte _dec
else
movzx eax,byte _dec
end if
else if _num = 2
if _sign = 1
movsx eax,word _dec
else
movzx eax,word _dec
end if
else
mov eax,dword _dec
end if
sub esp,4*8+4
end if
mov cl,_sign
call fdo_debug_outdec
popad
popf
}
macro DEBUGH _sign,_hex {
local tp
tp equ 0
match _arg:_num,_hex \{
DEBUGH_N _sign,_num,_arg
tp equ 1
\}
match =0 _arg,tp _hex \{
DEBUGH_N _sign,,_arg
\}
}
macro DEBUGH_N _sign,_num,_hex {
pushf
pushad
if (~_num eq) & (~_num in <1,2,3,4,5,6,7,8>)
'Error: 1..8 are only allowed for precision in %x'
end if
if _hex eqtype eax
if _hex in <eax,ebx,ecx,edx,esi,edi,ebp,esp>
if ~_hex eq eax
mov eax,_hex
end if
mov edx,8
else if _hex in <ax,bx,cx,dx,si,di,bp,sp>
if ~_hex eq ax
movzx eax,_hex
end if
if (_num eq)
mov edx,4
end if
else if _hex in <al,ah,bl,bh,cl,ch,dl,dh>
if ~_hex eq al
movzx eax,_hex
end if
if (_num eq)
mov edx,2
end if
end if
else if _hex eqtype 0
mov eax,_hex
else
add esp,4*8+4
mov eax,dword _hex
sub esp,4*8+4
end if
if ~_num eq
mov edx,_num
else
if ~_hex eqtype eax
mov edx,8
end if
end if
call fdo_debug_outhex
popad
popf
}
;-----------------------------------------------------------------------------
debug_func fdo_debug_outchar
debug_beginf
pushad
movzx ebx,al
mov eax,1
; mov ecx,sys_msg_board
; call ecx ; sys_msg_board
stdcall SysMsgBoardChar
popad
ret
debug_endf
debug_func fdo_debug_outstr
debug_beginf
mov eax,1
.l1: dec esi
js .l2
movzx ebx,byte[edx]
or bl,bl
jz .l2
; mov ecx,sys_msg_board
; call ecx ; sys_msg_board
stdcall SysMsgBoardChar
inc edx
jmp .l1
.l2: ret
debug_endf
debug_func fdo_debug_outdec
debug_beginf
or cl,cl
jz @f
or eax,eax
jns @f
neg eax
push eax
mov al,'-'
call fdo_debug_outchar
pop eax
@@: push 10
pop ecx
push -'0'
.l1: xor edx,edx
div ecx
push edx
test eax,eax
jnz .l1
.l2: pop eax
add al,'0'
jz .l3
call fdo_debug_outchar
jmp .l2
.l3: ret
debug_endf
debug_func fdo_debug_outhex
__fdo_hexdigits db '0123456789ABCDEF'
debug_beginf
mov cl,dl
neg cl
add cl,8
shl cl,2
rol eax,cl
.l1: rol eax,4
push eax
and eax,0x0000000F
mov al,[__fdo_hexdigits+eax]
call fdo_debug_outchar
pop eax
dec edx
jnz .l1
ret
debug_endf
;-----------------------------------------------------------------------------
macro DEBUGF _level,_format,[_arg] {
common
if __DEBUG__ = 1 & _level >= __DEBUG_LEVEL__
local ..f1,f2,a1,a2,c1,c2,c3,..lbl
_debug_str_ equ __debug_str_ # a1
a1 = 0
c2 = 0
c3 = 0
f2 = 0
repeat ..lbl-..f1
virtual at 0
db _format,0,0
load c1 word from %-1
end virtual
if c1 = '%s'
virtual at 0
db _format,0,0
store word 0 at %-1
load c1 from f2-c2
end virtual
if c1 <> 0
DEBUGS 0,_debug_str_+f2-c2
end if
c2 = c2 + 1
f2 = %+1
DEBUGF_HELPER S,a1,0,_arg
else if c1 = '%x'
virtual at 0
db _format,0,0
store word 0 at %-1
load c1 from f2-c2
end virtual
if c1 <> 0
DEBUGS 0,_debug_str_+f2-c2
end if
c2 = c2 + 1
f2 = %+1
DEBUGF_HELPER H,a1,0,_arg
else if c1 = '%d' | c1 = '%u'
local c4
if c1 = '%d'
c4 = 1
else
c4 = 0
end if
virtual at 0
db _format,0,0
store word 0 at %-1
load c1 from f2-c2
end virtual
if c1 <> 0
DEBUGS 0,_debug_str_+f2-c2
end if
c2 = c2 + 1
f2 = %+1
DEBUGF_HELPER D,a1,c4,_arg
else if c1 = '\n'
c3 = c3 + 1
end if
end repeat
virtual at 0
db _format,0,0
load c1 from f2-c2
end virtual
if (c1<>0)&(f2<>..lbl-..f1-1)
DEBUGS 0,_debug_str_+f2-c2
end if
virtual at 0
..f1 db _format,0
..lbl:
__debug_strings equ __debug_strings,_debug_str_,<_format>,..lbl-..f1-1-c2-c3
end virtual
end if
}
macro __include_debug_strings dummy,[_id,_fmt,_len] {
common
local c1,a1,a2
forward
if defined _len & ~_len eq
_id:
a1 = 0
a2 = 0
repeat _len
virtual at 0
db _fmt,0,0
load c1 word from %+a2-1
end virtual
if (c1='%s')|(c1='%x')|(c1='%d')|(c1='%u')
db 0
a2 = a2 + 1
else if (c1='\n')
dw $0A0D
a1 = a1 + 1
a2 = a2 + 1
else
db c1 and 0x0FF
end if
end repeat
db 0
end if
}
macro DEBUGF_HELPER _letter,_num,_sign,[_arg] {
common
local num
num = 0
forward
if num = _num
DEBUG#_letter _sign,_arg
end if
num = num+1
common
_num = _num+1
}
macro include_debug_strings {
if __DEBUG__ = 1
match dbg_str,__debug_strings \{
__include_debug_strings dbg_str
\}
end if
}
+102 -151
View File
@@ -1,151 +1,102 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; all exported kernel functions and data
if used RegService
extrn RegService
end if
if used GetService
extrn GetService
end if
if used ServiceHandler
extrn ServiceHandler
end if
if used AttachIntHandler
extrn AttachIntHandler
end if
if used FpuSave
extrn FpuSave
end if
if used FpuRestore
extrn FpuRestore
end if
if used PciApi
extrn PciApi
end if
if used PciRead32
extrn PciRead32
end if
if used PciRead8
extrn PciRead8
end if
if used PciWrite8
extrn PciWrite8
end if
if used AllocPage
extrn AllocPage
end if
if used AllocPages
extrn AllocPages
end if
if used FreePage
extrn FreePage
end if
if used MapPage
extrn MapPage
end if
if used MapSpace
extrn MapSpace
end if
if used GetPgAddr
extrn GetPgAddr
end if
if used CommitPages
extrn CommitPages
end if
if used ReleasePages
extrn ReleasePages
end if
if used AllocKernelSpace
extrn AllocKernelSpace
end if
if used FreeKernelSpace
extrn FreeKernelSpace
end if
if used KernelAlloc
extrn KernelAlloc
end if
if used KernelFree
extrn KernelFree
end if
if used UserAlloc
extrn UserAlloc
end if
if used UserFree
extrn UserFree
end if
if used Kmalloc
extrn Kmalloc
end if
if used Kfree
extrn Kfree
end if
if used CreateObject
extrn CreateObject
end if
if used DestroyObject
extrn DestroyObject
end if
if used CreateEvent
extrn CreateEvent
end if
if used RaiseEvent
extrn RaiseEvent
end if
if used WaitEvent
extrn WaitEvent
end if
if used DestroyEvent
extrn DestroyEvent
end if
if used ClearEvent
extrn ClearEvent
end if
if used LoadCursor
extrn LoadCursor
end if
if used SetHwCursor
extrn SetHwCursor
end if
if used HwCursorRestore
extrn HwCursorRestore
end if
if used HwCursorCreate
extrn HwCursorCreate
end if
if used SysMsgBoardStr
extrn SysMsgBoardStr
end if
if used GetCurrentTask
extrn GetCurrentTask
end if
if used LoadFile
extrn LoadFile
end if
if used SendEvent
extrn SendEvent
end if
if used SetMouseData
extrn SetMouseData
end if
if used Sleep
extrn Sleep
end if
if used GetTimerTicks
extrn GetTimerTicks
end if
if used LFBAddress
extrn LFBAddress
end if
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
macro kernel_export [name]{
forward
if used name
if DEBUG
display 'uses: ',`name,#13,#10
end if
extrn name
end if
}
; all exported kernel functions and data
kernel_export \
RegService,\
GetService,\
ServiceHandler,\
AttachIntHandler,\
GetIntHandler,\
FpuSave,\
FpuRestore,\
ReservePortArea,\
Boot_Log,\
\
MutexInit,\
MutexLock,\
MutexUnlock,\
\
PciApi,\
PciRead32,\
PciRead16,\
PciRead8,\
PciWrite8,\
PciWrite16,\
PciWrite32,\
\
AllocPage,\
AllocPages,\
FreePage,\
MapPage,\
MapSpace,\
MapIoMem,\
GetPgAddr,\
CommitPages,\
ReleasePages,\
\
AllocKernelSpace,\
FreeKernelSpace,\
KernelAlloc,\
KernelFree,\
UserAlloc,\
UserFree,\
Kmalloc,\
Kfree,\
CreateRingBuffer,\
\
GetPid,\
CreateObject,\
DestroyObject,\
CreateEvent,\
RaiseEvent,\
WaitEvent,\
DestroyEvent,\
ClearEvent,\
\
LoadCursor,\
SelectHwCursor,\
SetHwCursor,\
HwCursorRestore,\
HwCursorCreate,\
\
SysMsgBoardStr,\
SysMsgBoardChar,\
GetCurrentTask,\
LoadFile,\
SendEvent,\
SetMouseData,\
Sleep,\
GetTimerTicks,\
\
strncat,\
strncpy,\
strncmp,\
strnlen,\
strchr,\
strrchr,\
\
LFBAddress,\
GetDisplay,\
SetScreen,\
\
NetRegDev,\
NetUnRegDev,\
NetPtrToNum,\
NetLinkChanged,\
Eth_input,\
IPv4_input
+160
View File
@@ -0,0 +1,160 @@
; Generic MII registers.
MII_BMCR = 0x00 ; Basic mode control register
MII_BMSR = 0x01 ; Basic mode status register
MII_PHYSID1 = 0x02 ; PHYS ID 1
MII_PHYSID2 = 0x03 ; PHYS ID 2
MII_ADVERTISE = 0x04 ; Advertisement control reg
MII_LPA = 0x05 ; Link partner ability reg
MII_EXPANSION = 0x06 ; Expansion register
MII_CTRL1000 = 0x09 ; 1000BASE-T control
MII_STAT1000 = 0x0a ; 1000BASE-T status
MII_ESTATUS = 0x0f ; Extended Status
MII_DCOUNTER = 0x12 ; Disconnect counter
MII_FCSCOUNTER = 0x13 ; False carrier counter
MII_NWAYTEST = 0x14 ; N-way auto-neg test reg
MII_RERRCOUNTER = 0x15 ; Receive error counter
MII_SREVISION = 0x16 ; Silicon revision
MII_RESV1 = 0x17 ; Reserved...
MII_LBRERROR = 0x18 ; Lpback, rx, bypass error
MII_PHYADDR = 0x19 ; PHY address
MII_RESV2 = 0x1a ; Reserved...
MII_TPISTATUS = 0x1b ; TPI status for 10mbps
MII_NCONFIG = 0x1c ; Network interface config
; Basic mode control register.
BMCR_RESV = 0x003f ; Unused...
BMCR_SPEED1000 = 0x0040 ; MSB of Speed (1000)
BMCR_CTST = 0x0080 ; Collision test
BMCR_FULLDPLX = 0x0100 ; Full duplex
BMCR_ANRESTART = 0x0200 ; Auto negotiation restart
BMCR_ISOLATE = 0x0400 ; Disconnect DP83840 from MII
BMCR_PDOWN = 0x0800 ; Powerdown the DP83840
BMCR_ANENABLE = 0x1000 ; Enable auto negotiation
BMCR_SPEED100 = 0x2000 ; Select 100Mbps
BMCR_LOOPBACK = 0x4000 ; TXD loopback bits
BMCR_RESET = 0x8000 ; Reset the DP83840
; Basic mode status register.
BMSR_ERCAP = 0x0001 ; Ext-reg capability
BMSR_JCD = 0x0002 ; Jabber detected
BMSR_LSTATUS = 0x0004 ; Link status
BMSR_ANEGCAPABLE = 0x0008 ; Able to do auto-negotiation
BMSR_RFAULT = 0x0010 ; Remote fault detected
BMSR_ANEGCOMPLETE = 0x0020 ; Auto-negotiation complete
BMSR_RESV = 0x00c0 ; Unused...
BMSR_ESTATEN = 0x0100 ; Extended Status in R15
BMSR_100HALF2 = 0x0200 ; Can do 100BASE-T2 HDX
BMSR_100FULL2 = 0x0400 ; Can do 100BASE-T2 FDX
BMSR_10HALF = 0x0800 ; Can do 10mbps, half-duplex
BMSR_10FULL = 0x1000 ; Can do 10mbps, full-duplex
BMSR_100HALF = 0x2000 ; Can do 100mbps, half-duplex
BMSR_100FULL = 0x4000 ; Can do 100mbps, full-duplex
BMSR_100BASE4 = 0x8000 ; Can do 100mbps, 4k packets
; Advertisement control register.
ADVERTISE_SLCT = 0x001f ; Selector bits
ADVERTISE_CSMA = 0x0001 ; Only selector supported
ADVERTISE_10HALF = 0x0020 ; Try for 10mbps half-duplex
ADVERTISE_1000XFULL = 0x0020 ; Try for 1000BASE-X full-duplex
ADVERTISE_10FULL = 0x0040 ; Try for 10mbps full-duplex
ADVERTISE_1000XHALF = 0x0040 ; Try for 1000BASE-X half-duplex
ADVERTISE_100HALF = 0x0080 ; Try for 100mbps half-duplex
ADVERTISE_1000XPAUSE = 0x0080 ; Try for 1000BASE-X pause
ADVERTISE_100FULL = 0x0100 ; Try for 100mbps full-duplex
ADVERTISE_1000XPSE_ASYM = 0x0100 ; Try for 1000BASE-X asym pause
ADVERTISE_100BASE4 = 0x0200 ; Try for 100mbps 4k packets
ADVERTISE_PAUSE_CAP = 0x0400 ; Try for pause
ADVERTISE_PAUSE_ASYM = 0x0800 ; Try for asymetric pause
ADVERTISE_RESV = 0x1000 ; Unused...
ADVERTISE_RFAULT = 0x2000 ; Say we can detect faults
ADVERTISE_LPACK = 0x4000 ; Ack link partners response
ADVERTISE_NPAGE = 0x8000 ; Next page bit
ADVERTISE_FULL = (ADVERTISE_100FULL or ADVERTISE_10FULL or ADVERTISE_CSMA)
ADVERTISE_ALL = (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL)
; Link partner ability register.
LPA_SLCT = 0x001f ; Same as advertise selector
LPA_10HALF = 0x0020 ; Can do 10mbps half-duplex
LPA_1000XFULL = 0x0020 ; Can do 1000BASE-X full-duplex
LPA_10FULL = 0x0040 ; Can do 10mbps full-duplex
LPA_1000XHALF = 0x0040 ; Can do 1000BASE-X half-duplex
LPA_100HALF = 0x0080 ; Can do 100mbps half-duplex
LPA_1000XPAUSE = 0x0080 ; Can do 1000BASE-X pause
LPA_100FULL = 0x0100 ; Can do 100mbps full-duplex
LPA_1000XPAUSE_ASYM = 0x0100 ; Can do 1000BASE-X pause asym
LPA_100BASE4 = 0x0200 ; Can do 100mbps 4k packets
LPA_PAUSE_CAP = 0x0400 ; Can pause
LPA_PAUSE_ASYM = 0x0800 ; Can pause asymetrically
LPA_RESV = 0x1000 ; Unused...
LPA_RFAULT = 0x2000 ; Link partner faulted
LPA_LPACK = 0x4000 ; Link partner acked us
LPA_NPAGE = 0x8000 ; Next page bit
LPA_DUPLEX = (LPA_10FULL or LPA_100FULL)
LPA_100 = (LPA_100FULL or LPA_100HALF or LPA_100BASE4)
; Expansion register for auto-negotiation.
EXPANSION_NWAY = 0x0001 ; Can do N-way auto-nego
EXPANSION_LCWP = 0x0002 ; Got new RX page code word
EXPANSION_ENABLENPAGE = 0x0004 ; This enables npage words
EXPANSION_NPCAPABLE = 0x0008 ; Link partner supports npage
EXPANSION_MFAULTS = 0x0010 ; Multiple faults detected
EXPANSION_RESV = 0xffe0 ; Unused...
ESTATUS_1000_TFULL = 0x2000 ; Can do 1000BT Full
ESTATUS_1000_THALF = 0x1000 ; Can do 1000BT Half
; N-way test register.
NWAYTEST_RESV1 = 0x00ff ; Unused...
NWAYTEST_LOOPBACK = 0x0100 ; Enable loopback for N-way
NWAYTEST_RESV2 = 0xfe00 ; Unused...
; 1000BASE-T Control register
ADVERTISE_1000FULL = 0x0200 ; Advertise 1000BASE-T full duplex
ADVERTISE_1000HALF = 0x0100 ; Advertise 1000BASE-T half duplex
; 1000BASE-T Status register
LPA_1000LOCALRXOK = 0x2000 ; Link partner local receiver status
LPA_1000REMRXOK = 0x1000 ; Link partner remote receiver status
LPA_1000FULL = 0x0800 ; Link partner 1000BASE-T full duplex
LPA_1000HALF = 0x0400 ; Link partner 1000BASE-T half duplex
; Flow control flags
FLOW_CTRL_TX = 0x01
FLOW_CTRL_RX = 0x02
if used mii_link_ok
align 4
mii_link_ok:
DEBUGF 1, "mii_link_ok\n"
; First do a dummy read to latch some MII phys
mov ecx, MII_BMSR
call mdio_read
mov ecx, MII_BMSR
call mdio_read
and ax, BMSR_LSTATUS
DEBUGF 1, "link status=0x%x\n", ax
ret
end if
+150
View File
@@ -0,0 +1,150 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
include 'pci.inc'
include 'mii.inc'
; Kernel variables
PAGESIZE = 4096
PG_SW = 0x003
PG_NOCACHE = 0x018
; 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
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 allocate_and_clear dest, size, err {
; We need to allocate at least 8 pages, if we want a continuous memory in ram
push edx
if (size < 8*4096) & (size > 4096)
stdcall KernelAlloc, 8*4096
else
stdcall KernelAlloc, size
end if
pop edx
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)
push edx
call ReleasePages
pop edx
end if
; Clear the allocated buffer
mov ecx, size/4 ; divide by 4 because of DWORD
xor eax, eax
rep stosd
}
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 GetRealAddr { ; input and output is eax
push ax
call GetPgAddr
and word[esp], PAGESIZE - 1
or ax, word[esp]
inc esp
inc esp
}
macro 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
.end:
}
macro ETH_DEVICE {
NET_DEVICE
.mac dp ?
dw ? ; qword alignment
}
macro SLIP_DEVICE {
NET_DEVICE
}
+132
View File
@@ -0,0 +1,132 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; PCI Bus defines
PCI_HEADER_TYPE = 0x0e ; 8 bit
PCI_BASE_ADDRESS_0 = 0x10 ; 32 bit
PCI_BASE_ADDRESS_1 = 0x14 ; 32 bits
PCI_BASE_ADDRESS_2 = 0x18 ; 32 bits
PCI_BASE_ADDRESS_3 = 0x1c ; 32 bits
PCI_BASE_ADDRESS_4 = 0x20 ; 32 bits
PCI_BASE_ADDRESS_5 = 0x24 ; 32 bits
PCI_BASE_ADDRESS_SPACE_IO = 0x01
PCI_BASE_ADDRESS_IO_MASK = 0xFFFFFFFC
PCI_BASE_ADDRESS_MEM_MASK = 0xFFFFFFF0
; PCI programming
PCI_VENDOR_ID = 0x00 ; 16 bit
PCI_DEVICE_ID = 0x02 ; 16 bits
PCI_REG_COMMAND = 0x4 ; command register
PCI_REG_STATUS = 0x6 ; status register
PCI_REVISION_ID = 0x08 ; 8 bits
PCI_REG_LATENCY = 0xd ; latency timer register
PCI_REG_CAP_PTR = 0x34 ; capabilities pointer
PCI_REG_IRQ = 0x3c
PCI_REG_CAPABILITY_ID = 0x0 ; capapility ID in pm register block
PCI_REG_PM_STATUS = 0x4 ; power management status register
PCI_REG_PM_CTRL = 0x4 ; power management control register
PCI_BIT_PIO = 1 ; bit0: io space control
PCI_BIT_MMIO = 2 ; bit1: memory space control
PCI_BIT_MASTER = 4 ; bit2: device acts as a PCI master
macro PCI_find_io {
local .check, .inc, .got
xor eax, eax
mov esi, PCI_BASE_ADDRESS_0
.check:
stdcall PciRead32, [device.pci_bus], [device.pci_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
jmp .got
.inc:
add esi, 4
cmp esi, PCI_BASE_ADDRESS_5
jbe .check
xor eax, eax
.got:
mov [device.io_addr], eax
}
macro PCI_find_mmio32 {
local .check, .inc, .got
mov esi, PCI_BASE_ADDRESS_0
.check:
stdcall PciRead32, [device.pci_bus], [device.pci_dev], esi
test eax, PCI_BASE_ADDRESS_SPACE_IO ; mmio address?
jnz .inc
test eax, 100b ; 64 bit?
jnz .inc
and eax, not 1111b
jmp .got
.inc:
add esi, 4
cmp esi, PCI_BASE_ADDRESS_5
jbe .check
xor eax, eax
.got:
mov [device.mmio_addr], eax
}
macro PCI_find_irq {
stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REG_IRQ
mov [device.irq_line], al
}
macro PCI_find_rev {
stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REVISION_ID
mov [device.revision], al
}
macro PCI_make_bus_master bus, dev {
stdcall PciRead32, [device.pci_bus], [device.pci_dev], PCI_REG_COMMAND
or al, PCI_BIT_MASTER
stdcall PciWrite32, [device.pci_bus], [device.pci_dev], PCI_REG_COMMAND, eax
}
macro PCI_adjust_latency min {
local .not
stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REG_LATENCY
cmp al, min
ja .not
mov al, min
stdcall PciWrite8, [device.pci_bus], [device.pci_dev], PCI_REG_LATENCY, eax
.not:
}
+268 -268
View File
@@ -1,268 +1,268 @@
; Macroinstructions for defining and calling procedures
macro stdcall proc,[arg] ; directly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call proc }
macro invoke proc,[arg] ; indirectly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call [proc] }
macro ccall proc,[arg] ; directly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call proc
if size@ccall
add esp,size@ccall
end if }
macro cinvoke proc,[arg] ; indirectly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call [proc]
if size@ccall
add esp,size@ccall
end if }
macro proc [args] ; define procedure
{ common
match name params, args>
\{ define@proc name,<params \} }
prologue@proc equ prologuedef
macro prologuedef procname,flag,parmbytes,localbytes,reglist
{ if parmbytes | localbytes
push ebp
mov ebp,esp
if localbytes
sub esp,localbytes
end if
end if
irps reg, reglist \{ push reg \} }
epilogue@proc equ epiloguedef
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
{ irps reg, reglist \{ reverse pop reg \}
if parmbytes | localbytes
leave
end if
if (flag and 10000b) | (parmbytes=0)
retn
else
retn parmbytes
end if }
macro define@proc name,statement
{ local params,flag,regs,parmbytes,localbytes,current
if used name
name:
match =stdcall args, statement \{ params equ args
flag = 11b \}
match =stdcall, statement \{ params equ
flag = 11b \}
match =c args, statement \{ params equ args
flag = 10001b \}
match =c, statement \{ params equ
flag = 10001b \}
match =params, params \{ params equ statement
flag = 0 \}
virtual at ebp+8
match =uses reglist=,args, params \{ regs equ reglist
params equ args \}
match =regs =uses reglist, regs params \{ regs equ reglist
params equ \}
match =regs, regs \{ regs equ \}
match =,args, params \{ defargs@proc args \}
match =args@proc args, args@proc params \{ defargs@proc args \}
parmbytes = $ - (ebp+8)
end virtual
name # % = parmbytes/4
all@vars equ
current = 0
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
macro locals
\{ virtual at ebp-localbytes+current
macro label . \\{ deflocal@proc .,:, \\}
struc db [val] \\{ \common deflocal@proc .,db,val \\}
struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
macro endl
\{ purge label
restruc db,dw,dp,dd,dt,dq
restruc rb,rw,rp,rd,rt,rq
restruc byte,word,dword,pword,tword,qword
current = $-(ebp-localbytes)
end virtual \}
macro ret operand
\{ match any, operand \\{ retn operand \\}
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs>
\\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2
end if \} }
macro defargs@proc [arg]
{ common
if ~ arg eq
forward
local ..arg,current@arg
match argname:type, arg
\{ current@arg equ argname
label ..arg type
argname equ ..arg
if dqword eq type
dd ?,?,?,?
else if tbyte eq type
dd ?,?,?
else if qword eq type | pword eq type
dd ?,?
else
dd ?
end if \}
match =current@arg,current@arg
\{ current@arg equ arg
arg equ ..arg
..arg dd ? \}
common
args@proc equ current@arg
forward
restore current@arg
common
end if }
macro deflocal@proc name,def,[val]
{ common
match vars, all@vars \{ all@vars equ all@vars, \}
all@vars equ all@vars name
forward
local ..var,..tmp
..var def val
match =?, val \{ ..tmp equ \}
match any =dup (=?), val \{ ..tmp equ \}
match tmp : value, ..tmp : val
\{ tmp: end virtual
initlocal@proc ..var,def value
virtual at tmp\}
common
match first rest, ..var, \{ name equ first \} }
macro initlocal@proc name,def
{ virtual at name
def
size@initlocal = $ - name
end virtual
position@initlocal = 0
while size@initlocal > position@initlocal
virtual at name
def
if size@initlocal - position@initlocal < 2
current@initlocal = 1
load byte@initlocal byte from name+position@initlocal
else if size@initlocal - position@initlocal < 4
current@initlocal = 2
load word@initlocal word from name+position@initlocal
else
current@initlocal = 4
load dword@initlocal dword from name+position@initlocal
end if
end virtual
if current@initlocal = 1
mov byte [name+position@initlocal],byte@initlocal
else if current@initlocal = 2
mov word [name+position@initlocal],word@initlocal
else
mov dword [name+position@initlocal],dword@initlocal
end if
position@initlocal = position@initlocal + current@initlocal
end while }
macro endp
{ purge ret,locals,endl
finish@proc
purge finish@proc
restore regs@proc
match all,args@proc \{ restore all \}
restore args@proc
match all,all@vars \{ restore all \} }
macro local [var]
{ common
locals
forward done@local equ
match varname[count]:vartype, var
\{ match =BYTE, vartype \\{ varname rb count
restore done@local \\}
match =WORD, vartype \\{ varname rw count
restore done@local \\}
match =DWORD, vartype \\{ varname rd count
restore done@local \\}
match =PWORD, vartype \\{ varname rp count
restore done@local \\}
match =QWORD, vartype \\{ varname rq count
restore done@local \\}
match =TBYTE, vartype \\{ varname rt count
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
rq count+count
restore done@local \\}
match , done@local \\{ virtual
varname vartype
end virtual
rb count*sizeof.\#vartype
restore done@local \\} \}
match :varname:vartype, done@local:var
\{ match =BYTE, vartype \\{ varname db ?
restore done@local \\}
match =WORD, vartype \\{ varname dw ?
restore done@local \\}
match =DWORD, vartype \\{ varname dd ?
restore done@local \\}
match =PWORD, vartype \\{ varname dp ?
restore done@local \\}
match =QWORD, vartype \\{ varname dq ?
restore done@local \\}
match =TBYTE, vartype \\{ varname dt ?
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
dq ?,?
restore done@local \\}
match , done@local \\{ varname vartype
restore done@local \\} \}
match ,done@local
\{ var
restore done@local \}
common
endl }
; Macroinstructions for defining and calling procedures
macro stdcall proc,[arg] ; directly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call proc }
macro invoke proc,[arg] ; indirectly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call [proc] }
macro ccall proc,[arg] ; directly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call proc
if size@ccall
add esp,size@ccall
end if }
macro cinvoke proc,[arg] ; indirectly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call [proc]
if size@ccall
add esp,size@ccall
end if }
macro proc [args] ; define procedure
{ common
match name params, args>
\{ define@proc name,<params \} }
prologue@proc equ prologuedef
macro prologuedef procname,flag,parmbytes,localbytes,reglist
{ if parmbytes | localbytes
push ebp
mov ebp,esp
if localbytes
sub esp,localbytes
end if
end if
irps reg, reglist \{ push reg \} }
epilogue@proc equ epiloguedef
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
{ irps reg, reglist \{ reverse pop reg \}
if parmbytes | localbytes
leave
end if
if (flag and 10000b) | (parmbytes=0)
retn
else
retn parmbytes
end if }
macro define@proc name,statement
{ local params,flag,regs,parmbytes,localbytes,current
if used name
name:
match =stdcall args, statement \{ params equ args
flag = 11b \}
match =stdcall, statement \{ params equ
flag = 11b \}
match =c args, statement \{ params equ args
flag = 10001b \}
match =c, statement \{ params equ
flag = 10001b \}
match =params, params \{ params equ statement
flag = 0 \}
virtual at ebp+8
match =uses reglist=,args, params \{ regs equ reglist
params equ args \}
match =regs =uses reglist, regs params \{ regs equ reglist
params equ \}
match =regs, regs \{ regs equ \}
match =,args, params \{ defargs@proc args \}
match =args@proc args, args@proc params \{ defargs@proc args \}
parmbytes = $ - (ebp+8)
end virtual
name # % = parmbytes/4
all@vars equ
current = 0
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
macro locals
\{ virtual at ebp-localbytes+current
macro label . \\{ deflocal@proc .,:, \\}
struc db [val] \\{ \common deflocal@proc .,db,val \\}
struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
macro endl
\{ purge label
restruc db,dw,dp,dd,dt,dq
restruc rb,rw,rp,rd,rt,rq
restruc byte,word,dword,pword,tword,qword
current = $-(ebp-localbytes)
end virtual \}
macro ret operand
\{ match any, operand \\{ retn operand \\}
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs>
\\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2
end if \} }
macro defargs@proc [arg]
{ common
if ~ arg eq
forward
local ..arg,current@arg
match argname:type, arg
\{ current@arg equ argname
label ..arg type
argname equ ..arg
if dqword eq type
dd ?,?,?,?
else if tbyte eq type
dd ?,?,?
else if qword eq type | pword eq type
dd ?,?
else
dd ?
end if \}
match =current@arg,current@arg
\{ current@arg equ arg
arg equ ..arg
..arg dd ? \}
common
args@proc equ current@arg
forward
restore current@arg
common
end if }
macro deflocal@proc name,def,[val]
{ common
match vars, all@vars \{ all@vars equ all@vars, \}
all@vars equ all@vars name
forward
local ..var,..tmp
..var def val
match =?, val \{ ..tmp equ \}
match any =dup (=?), val \{ ..tmp equ \}
match tmp : value, ..tmp : val
\{ tmp: end virtual
initlocal@proc ..var,def value
virtual at tmp\}
common
match first rest, ..var, \{ name equ first \} }
macro initlocal@proc name,def
{ virtual at name
def
size@initlocal = $ - name
end virtual
position@initlocal = 0
while size@initlocal > position@initlocal
virtual at name
def
if size@initlocal - position@initlocal < 2
current@initlocal = 1
load byte@initlocal byte from name+position@initlocal
else if size@initlocal - position@initlocal < 4
current@initlocal = 2
load word@initlocal word from name+position@initlocal
else
current@initlocal = 4
load dword@initlocal dword from name+position@initlocal
end if
end virtual
if current@initlocal = 1
mov byte [name+position@initlocal],byte@initlocal
else if current@initlocal = 2
mov word [name+position@initlocal],word@initlocal
else
mov dword [name+position@initlocal],dword@initlocal
end if
position@initlocal = position@initlocal + current@initlocal
end while }
macro endp
{ purge ret,locals,endl
finish@proc
purge finish@proc
restore regs@proc
match all,args@proc \{ restore all \}
restore args@proc
match all,all@vars \{ restore all \} }
macro local [var]
{ common
locals
forward done@local equ
match varname[count]:vartype, var
\{ match =BYTE, vartype \\{ varname rb count
restore done@local \\}
match =WORD, vartype \\{ varname rw count
restore done@local \\}
match =DWORD, vartype \\{ varname rd count
restore done@local \\}
match =PWORD, vartype \\{ varname rp count
restore done@local \\}
match =QWORD, vartype \\{ varname rq count
restore done@local \\}
match =TBYTE, vartype \\{ varname rt count
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
rq count+count
restore done@local \\}
match , done@local \\{ virtual
varname vartype
end virtual
rb count*sizeof.\#vartype
restore done@local \\} \}
match :varname:vartype, done@local:var
\{ match =BYTE, vartype \\{ varname db ?
restore done@local \\}
match =WORD, vartype \\{ varname dw ?
restore done@local \\}
match =DWORD, vartype \\{ varname dd ?
restore done@local \\}
match =PWORD, vartype \\{ varname dp ?
restore done@local \\}
match =QWORD, vartype \\{ varname dq ?
restore done@local \\}
match =TBYTE, vartype \\{ varname dt ?
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
dq ?,?
restore done@local \\}
match , done@local \\{ varname vartype
restore done@local \\} \}
match ,done@local
\{ var
restore done@local \}
common
endl }
+240
View File
@@ -0,0 +1,240 @@
; Macroinstructions for defining data structures
macro struct name
{ virtual at 0
fields@struct equ name
match child parent, name \{ fields@struct equ child,fields@\#parent \}
sub@struct equ
struc db [val] \{ \common define field@struct .,db,<val>
fields@struct equ fields@struct,field@struct \}
struc dw [val] \{ \common define field@struct .,dw,<val>
fields@struct equ fields@struct,field@struct \}
struc du [val] \{ \common define field@struct .,du,<val>
fields@struct equ fields@struct,field@struct \}
struc dd [val] \{ \common define field@struct .,dd,<val>
fields@struct equ fields@struct,field@struct \}
struc dp [val] \{ \common define field@struct .,dp,<val>
fields@struct equ fields@struct,field@struct \}
struc dq [val] \{ \common define field@struct .,dq,<val>
fields@struct equ fields@struct,field@struct \}
struc dt [val] \{ \common define field@struct .,dt,<val>
fields@struct equ fields@struct,field@struct \}
struc rb count \{ define field@struct .,db,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rw count \{ define field@struct .,dw,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rd count \{ define field@struct .,dd,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rp count \{ define field@struct .,dp,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rq count \{ define field@struct .,dq,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rt count \{ define field@struct .,dt,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro db [val] \{ \common \local anonymous
define field@struct anonymous,db,<val>
fields@struct equ fields@struct,field@struct \}
macro dw [val] \{ \common \local anonymous
define field@struct anonymous,dw,<val>
fields@struct equ fields@struct,field@struct \}
macro du [val] \{ \common \local anonymous
define field@struct anonymous,du,<val>
fields@struct equ fields@struct,field@struct \}
macro dd [val] \{ \common \local anonymous
define field@struct anonymous,dd,<val>
fields@struct equ fields@struct,field@struct \}
macro dp [val] \{ \common \local anonymous
define field@struct anonymous,dp,<val>
fields@struct equ fields@struct,field@struct \}
macro dq [val] \{ \common \local anonymous
define field@struct anonymous,dq,<val>
fields@struct equ fields@struct,field@struct \}
macro dt [val] \{ \common \local anonymous
define field@struct anonymous,dt,<val>
fields@struct equ fields@struct,field@struct \}
macro rb count \{ \local anonymous
define field@struct anonymous,db,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rw count \{ \local anonymous
define field@struct anonymous,dw,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rd count \{ \local anonymous
define field@struct anonymous,dd,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rp count \{ \local anonymous
define field@struct anonymous,dp,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rq count \{ \local anonymous
define field@struct anonymous,dq,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rt count \{ \local anonymous
define field@struct anonymous,dt,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro union \{ fields@struct equ fields@struct,,union,<
sub@struct equ union \}
macro struct \{ fields@struct equ fields@struct,,substruct,<
sub@struct equ substruct \} }
macro ends
{ match , sub@struct \{ restruc db,dw,du,dd,dp,dq,dt
restruc rb,rw,rd,rp,rq,rt
purge db,dw,du,dd,dp,dq,dt
purge rb,rw,rd,rp,rq,rt
purge union,struct
match name tail,fields@struct, \\{ if $
display 'Error: definition of ',\\`name,' contains illegal instructions.',0Dh,0Ah
err
end if \\}
match name=,fields,fields@struct \\{ fields@struct equ
make@struct name,fields
define fields@\\#name fields \\}
end virtual \}
match any, sub@struct \{ fields@struct equ fields@struct> \}
restore sub@struct }
macro make@struct name,[field,type,def]
{ common
local define
define equ name
forward
local sub
match , field \{ make@substruct type,name,sub def
define equ define,.,sub, \}
match any, field \{ define equ define,.#field,type,<def> \}
common
match fields, define \{ define@struct fields \} }
macro define@struct name,[field,type,def]
{ common
virtual
db `name
load initial@struct byte from 0
if initial@struct = '.'
display 'Error: name of structure should not begin with a dot.',0Dh,0Ah
err
end if
end virtual
local list
list equ
forward
if ~ field eq .
name#field type def
sizeof.#name#field = $ - name#field
else
label name#.#type
rb sizeof.#type
end if
local value
match any, list \{ list equ list, \}
list equ list <value>
common
sizeof.#name = $
restruc name
match values, list \{
struc name value \\{ \\local \\..base
match any, fields@struct \\\{ fields@struct equ fields@struct,.,name,<values> \\\}
match , fields@struct \\\{ label \\..base
forward
match , value \\\\{ field type def \\\\}
match any, value \\\\{ field type value
if ~ field eq .
rb sizeof.#name#field - ($-field)
end if \\\\}
common label . at \\..base \\\}
\\}
macro name value \\{
match any, fields@struct \\\{ \\\local anonymous
fields@struct equ fields@struct,anonymous,name,<values> \\\}
match , fields@struct \\\{
forward
match , value \\\\{ type def \\\\}
match any, value \\\\{ \\\\local ..field
..field = $
type value
if ~ field eq .
rb sizeof.#name#field - ($-..field)
end if \\\\}
common \\\} \\} \} }
macro enable@substruct
{ macro make@substruct substruct,parent,name,[field,type,def]
\{ \common
\local define
define equ parent,name
\forward
\local sub
match , field \\{ match any, type \\\{ enable@substruct
make@substruct type,parent,sub def
purge make@substruct
define equ define,.,sub, \\\} \\}
match any, field \\{ define equ define,.\#field,type,<def> \\}
\common
match fields, define \\{ define@\#substruct fields \\} \} }
enable@substruct
macro define@union parent,name,[field,type,def]
{ common
virtual at parent#.#name
forward
if ~ field eq .
virtual at parent#.#name
parent#field type def
sizeof.#parent#field = $ - parent#field
end virtual
if sizeof.#parent#field > $ - parent#.#name
rb sizeof.#parent#field - ($ - parent#.#name)
end if
else
virtual at parent#.#name
label parent#.#type
type def
end virtual
label name#.#type at parent#.#name
if sizeof.#type > $ - parent#.#name
rb sizeof.#type - ($ - parent#.#name)
end if
end if
common
sizeof.#name = $ - parent#.#name
end virtual
struc name [value] \{ \common
label .\#name
last@union equ
forward
match any, last@union \\{ virtual at .\#name
field type def
end virtual \\}
match , last@union \\{ match , value \\\{ field type def \\\}
match any, value \\\{ field type value \\\} \\}
last@union equ field
common rb sizeof.#name - ($ - .\#name) \}
macro name [value] \{ \common \local ..anonymous
..anonymous name value \} }
macro define@substruct parent,name,[field,type,def]
{ common
virtual at parent#.#name
forward
if ~ field eq .
parent#field type def
sizeof.#parent#field = $ - parent#field
else
label parent#.#type
rb sizeof.#type
end if
common
sizeof.#name = $ - parent#.#name
end virtual
struc name value \{
label .\#name
forward
match , value \\{ field type def \\}
match any, value \\{ field type value
if ~ field eq .
rb sizeof.#parent#field - ($-field)
end if \\}
common \}
macro name value \{ \local ..anonymous
..anonymous name \} }
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,390 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ftpc.asm - FTP client for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
format binary as ""
__DEBUG__ = 0
__DEBUG_LEVEL__ = 1
BUFFERSIZE = 1024
STATUS_CONNECTING = 0
STATUS_CONNECTED = 1
STATUS_NEEDPASSWORD = 1
STATUS_LOGGED_IN = 3
use32
; standard header
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem+0x1000 ; required memory
dd mem+0x1000 ; stack pointer
dd s ; parameters
dd 0 ; path
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
include '../debug-fdo.inc'
include '../network.inc'
include 'usercommands.inc'
include 'servercommands.inc'
; entry point
start:
DEBUGF 1, "hello"
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
; initialize console
push 1
call [con_start]
push title
push 25
push 80
push 25
push 80
call [con_init]
; Check for parameters
cmp byte [s], 0
jne resolve
main:
call [con_cls]
; Welcome user
push str1
call [con_write_asciiz]
; write prompt
push str2
call [con_write_asciiz]
; read string
mov esi, s
push 256
push esi
call [con_gets]
; check for exit
test eax, eax
jz done
cmp byte [esi], 10
jz done
resolve:
; delete terminating '\n'
mov esi, s
@@:
lodsb
cmp al, 0x20
ja @r
mov byte [esi-1], 0
; call [con_cls]
push str3
call [con_write_asciiz]
push s
call [con_write_asciiz]
; resolve name
push esp ; reserve stack place
push esp ; fourth parameter
push 0 ; third parameter
push 0 ; second parameter
push s ; first parameter
call [getaddrinfo]
pop esi
; test for error
test eax, eax
jnz fail
; write results
push str8
call [con_write_asciiz]
; mov edi, esi
; convert IP address to decimal notation
mov eax, [esi+addrinfo.ai_addr]
mov eax, [eax+sockaddr_in.sin_addr]
mov [sockaddr1.ip], eax
push eax
call [inet_ntoa]
; write result
push eax
call [con_write_asciiz]
; free allocated memory
push esi
call [freeaddrinfo]
push str9
call [con_write_asciiz]
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
jz fail2
mov [socketnum], eax
mcall connect, [socketnum], sockaddr1, 18
mcall 40, 1 shl 7
mov [status], STATUS_CONNECTING
mov [offset], buffer_ptr
wait_for_serverdata:
mcall 10
call [con_get_flags]
test eax, 0x200 ; con window closed?
jnz exit
; receive socket data
mcall recv, [socketnum], [offset], BUFFERSIZE, 0
inc eax
jz wait_for_serverdata
dec eax
jz wait_for_serverdata
; extract commands, copy them to "s" buffer
add eax, buffer_ptr ; eax = end pointer
mov esi, buffer_ptr ; esi = current pointer
.nextcommand:
mov edi, s
.byteloop:
cmp esi, eax
jae wait_for_serverdata
lodsb
cmp al, 10 ; excellent, we might have a command
je .got_command
cmp al, 13 ; just ignore this crap
je .byteloop
stosb
jmp .byteloop
; we have a newline check if its a command
.got_command:
xor al, al
stosb
; push esi eax
; print it to the screen
pushd s
call [con_write_asciiz]
pushd str4 ; newline
call [con_write_asciiz]
; cmp byte[s+2], " "
; jne .not_command
lea ecx, [edi - s]
call server_parser
; .not_command:
; pop eax esi
; jmp .nextcommand
wait_for_usercommand:
cmp [status], STATUS_CONNECTED
je .connected
cmp [status], STATUS_NEEDPASSWORD
je .needpass
; write prompt
push str2
call [con_write_asciiz]
; read string
mov esi, s
push 256
push esi
call [con_gets]
call [con_get_flags]
test eax, 0x200 ; con window closed?
jnz exit
cmp dword[s], "list"
je cmd_list
cmp dword[s], "help"
je cmd_help
push str_unkown
call [con_write_asciiz]
jmp wait_for_usercommand
.connected:
push str_user
call [con_write_asciiz]
mov dword[s], "USER"
mov byte[s+4], " "
jmp .send
.needpass:
push str_pass
call [con_write_asciiz]
mov dword[s], "PASS"
mov byte[s+4], " "
.send:
; read string
mov esi, s+5
push 256
push esi
call [con_gets]
mov edi, s+5
mov ecx, 256
xor al, al
repne scasb
lea esi, [edi-s-1]
mcall send, [socketnum], s
jmp wait_for_usercommand
open_dataconnection:
cmp [status], STATUS_LOGGED_IN
jne .fail
mov dword[s], "PASV"
mov byte[s+4], 10
mcall send, [socketnum], s, 5
ret
.fail:
push str6
call [con_write_asciiz]
ret
fail2:
push str6
call [con_write_asciiz]
jmp fail.wait
fail:
push str5
call [con_write_asciiz]
.wait:
push str10
call [con_write_asciiz]
call [con_getch2]
jmp main
done:
push 1
call [con_exit]
exit:
mcall close, [socketnum]
mcall -1
; data
title db 'FTP client',0
str1 db 'FTP client for KolibriOS v0.01',10,10,'Please enter ftp server address.',10,0
str2 db '> ',0
str3 db 'Connecting to ',0
str4 db 10,0
str5 db 10,'Name resolution failed.',10,0
str6 db 10,'Socket error.',10,0
str8 db ' (',0
str9 db ')',10,0
str10 db 'Push any key to continue.',0
str_user db "username: ",0
str_pass db "password: ",0
str_unkown db "unkown command",10,0
str_help db "available commands:",10,10
db "help list",10,0
str_open db "opening data socket",10,0
sockaddr1:
dw AF_INET4
.port dw 0x1500 ; 21
.ip dd 0
rb 10
sockaddr2:
dw AF_INET4
.port dw 0
.ip dd 0
rb 10
include_debug_strings ; ALWAYS present in data section
; import
align 4
@IMPORT:
library network, 'network.obj', console, 'console.obj'
import network, \
getaddrinfo, 'getaddrinfo', \
freeaddrinfo, 'freeaddrinfo', \
inet_ntoa, 'inet_ntoa'
import console, \
con_start, 'START', \
con_init, 'con_init', \
con_write_asciiz,'con_write_asciiz', \
con_exit, 'con_exit', \
con_gets, 'con_gets',\
con_cls, 'con_cls',\
con_getch2, 'con_getch2',\
con_set_cursor_pos, 'con_set_cursor_pos',\
con_write_string, 'con_write_string',\
con_get_flags, 'con_get_flags'
i_end:
active_passive db ?
socketnum dd ?
datasocket dd ?
buffer_ptr rb 2*BUFFERSIZE
status db ?
offset dd ?
s rb 1024
mem:
@@ -0,0 +1,114 @@
server_parser:
; Commands are always 3 numbers and followed by a space
; If a server decides it needs multiline output,
; first lines will have a dash instead of space after numbers,
; thus they are simply ignored.
cmp dword[s], "150 "
je data_ok
cmp dword[s], "220 "
je welcome
cmp dword[s], "227 "
je pasv_ok
cmp dword[s], "230 "
je login_ok
cmp dword[s], "331 "
je pass
ret
welcome:
mov [status], STATUS_CONNECTED
ret
pass:
mov [status], STATUS_NEEDPASSWORD
ret
login_ok:
mov [status], STATUS_LOGGED_IN
ret
pasv_ok:
sub ecx, 5
jb .fail
mov al, "("
mov edi, s + 5
repne scasb
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
je fail
mov [datasocket], eax
mov esi, edi
call ascii_dec
mov byte[sockaddr2.ip+0], bl
call ascii_dec
mov byte[sockaddr2.ip+1], bl
call ascii_dec
mov byte[sockaddr2.ip+2], bl
call ascii_dec
mov byte[sockaddr2.ip+3], bl
call ascii_dec
mov byte[sockaddr2.port+1], bl
call ascii_dec
mov byte[sockaddr2.port+0], bl
push str_open
call [con_write_asciiz]
mcall connect, [datasocket], sockaddr2, 18
.fail:
ret
data_ok:
mcall recv, [datasocket], buffer_ptr, BUFFERSIZE, 0 ; fixme: use other buffer
inc eax
jz .fail
dec eax
jz .fail
mov byte[buffer_ptr + eax], 0
pushd buffer_ptr
call [con_write_asciiz]
.fail:
ret
ascii_dec:
xor ebx, ebx
mov cl, 3
.loop:
lodsb
sub al, '0'
jb .done
cmp al, 9
ja .done
lea ebx, [ebx*4+ebx]
shl ebx, 1
add bl, al
dec cl
jnz .loop
.done:
ret
@@ -0,0 +1,17 @@
cmd_list:
call open_dataconnection
mov dword[s], "LIST"
mov word[s+4], 0x0d0a
mcall send, [socketnum], s, 6
jmp wait_for_serverdata
cmd_help:
push str_help
call [con_write_asciiz]
jmp wait_for_usercommand
@@ -78,6 +78,21 @@ window_refresh:
ret
window_updated:
mov edi, [window_print]
test [edi + window.flags], FLAG_UPDATED
jnz .skip
or [edi + window.flags], FLAG_UPDATED
; now play a sound :)
.skip:
ret
print_text: ; eax = start ptr
; dl = end char
pusha
+10 -9
View File
@@ -19,11 +19,11 @@
O_BINARY = 00000000b
O_READ = 00000001b
O_READ = 00000001b
O_WRITE = 00000010b
O_CREATE = 00000100b
O_SHARE = 00001000b
O_TEXT = 00010000b
O_TEXT = 00010000b
SEEK_SET = 0
SEEK_CUR = 1
@@ -54,7 +54,7 @@ struct FileInfoBlock
Flags dd ?
Count dd ?
Buffer dd ?
db ?
db ?
FileName dd ?
ends
@@ -62,7 +62,7 @@ struct FileInfoHeader
Version dd ?
FilesRead dd ?
FilesCount dd ?
rd 5
rd 5
ends
struct FileInfoA
@@ -78,7 +78,7 @@ struct FileInfoA
FileSizeHigh dd ?
ends
ends
FileName rb 252
FileName rb 264
ends
struct FileInfoW
@@ -94,12 +94,12 @@ struct FileInfoW
FileSizeHigh dd ?
ends
ends
FileName rw 260
FileName rw 264
ends
virtual at 0
FileInfo FileInfoA
FileInfo fix FileInfoA
FileInfo FileInfoA
FileInfo fix FileInfoA
sizeof.FileInfo fix sizeof.FileInfoA
end virtual
@@ -109,4 +109,5 @@ FA_SYSTEM = 00000100b
FA_LABEL = 00001000b
FA_FOLDER = 00010000b
FA_ARCHIVED = 00100000b
FA_ANY = 00111111b
FA_NORMAL = 01000000b
FA_ANY = 01111111b
+11 -10
View File
@@ -178,16 +178,16 @@ shmem_list:
.fd dd shmem_list
dll_list:
.bk dd dll_list
.fd dd dll_list
pcidev_list:
.bk dd pcidev_list
.fd dd pcidev_list
MAX_DEFAULT_DLL_ADDR = 0x80000000
MIN_DEFAULT_DLL_ADDR = 0x70000000
dll_cur_addr dd MIN_DEFAULT_DLL_ADDR
.bk dd dll_list
.fd dd dll_list
pcidev_list:
.bk dd pcidev_list
.fd dd pcidev_list
MAX_DEFAULT_DLL_ADDR = 0x80000000
MIN_DEFAULT_DLL_ADDR = 0x70000000
dll_cur_addr dd MIN_DEFAULT_DLL_ADDR
; supported videomodes
@@ -500,4 +500,5 @@ BiosDisksData rb 200h
BiosDiskCaches rb 80h*(cache_ide1-cache_ide0)
BiosDiskPartitions rd 80h
tetten:
IncludeUGlobals
+1 -1
View File
@@ -527,7 +527,7 @@ align 4
cmp eax, 5
je .mouse_check ; eax=5, retvals=eax+1 (event 6)
ja .FlagAutoReset ; eax=[6..8], retvals=eax+1 (event 7...10)
ja .FlagAutoReset ; eax=[6..9], retvals=eax+1 (event 7...10)
cmp eax, 1
jae .BtKy ; eax=[1,2], retvals=eax+1 (event 2,3)
+36 -35
View File
@@ -77,11 +77,12 @@ $Revision $
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
include "proc32.inc"
include "kglobals.inc"
include "lang.inc"
;include "lang.inc"
lang fix en
include "const.inc"
max_processes equ 255
@@ -136,7 +137,7 @@ use16
if lang eq sp
include "kernelsp.inc" ; spanish kernel messages
else
version db 'Kolibri OS version 0.7.7.0+ ',13,10,13,10,0
version db 'Kolibri OS network development ',13,10,13,10,0
end if
include "boot/bootstr.inc" ; language-independent boot messages
@@ -789,13 +790,13 @@ end if
; call build_scheduler; sys32.inc
; mov esi, boot_devices
; call boot_log
mov [pci_access_enabled], 1
call pci_enum
; SET PRELIMINARY WINDOW STACK AND POSITIONS
; call boot_log
mov [pci_access_enabled], 1
call pci_enum
; SET PRELIMINARY WINDOW STACK AND POSITIONS
mov esi, boot_windefs
call boot_log
call set_window_defaults
@@ -4615,16 +4616,16 @@ sys_msg_board_dword:
pop eax
pop ecx
loop @b
popad
ret
msg_board_data_size = 65536 ; Must be power of two
uglobal
msg_board_data rb msg_board_data_size
msg_board_count dd 0x0
endg
popad
ret
msg_board_data_size = 65536 ; Must be power of two
uglobal
msg_board_data rb msg_board_data_size
msg_board_count dd 0x0
endg
sys_msg_board:
; eax=1 : write : bl byte to write
@@ -4651,13 +4652,13 @@ if defined debug_com_base
pop ax dx
end if
mov [msg_board_data+ecx], bl
inc ecx
and ecx, msg_board_data_size - 1
mov [msg_board_count], ecx
mov [check_idle_semaphore], 5
ret
mov [msg_board_data+ecx], bl
inc ecx
and ecx, msg_board_data_size - 1
mov [msg_board_count], ecx
mov [check_idle_semaphore], 5
ret
.smbl1:
cmp eax, 2
jne .smbl2
@@ -4744,14 +4745,14 @@ align 4
movzx ecx, cl
lea ecx, [hotkey_scancodes+ecx*4]
mov edx, [ecx]
mov [eax], edx
mov [ecx], eax
mov [eax+12], ecx
test edx, edx
jz @f
mov [edx+12], eax
@@:
and dword [esp+32], 0
mov [eax], edx
mov [ecx], eax
mov [eax+12], ecx
test edx, edx
jz @f
mov [edx+12], eax
@@:
and dword [esp+32], 0
ret
;-----------------------------------------------------------------------------
align 4
+2 -1
View File
@@ -399,7 +399,8 @@ EVENT_MOUSE equ 0x00000020
EVENT_IPC equ 0x00000040
EVENT_NETWORK equ 0x00000080
EVENT_DEBUG equ 0x00000100
EVENT_EXTENDED equ 0x00000200
EVENT_NETWORK2 equ 0x00000200
EVENT_EXTENDED equ 0x00000400
EV_INTR equ 1
-47
View File
@@ -72,54 +72,7 @@ ugui_mouse_delay_def db '0x00A',0
udev_midibase db 'midibase',0
udev_midibase_def db '0x320',0
endg
;set up netvork configuration
proc set_network_conf
locals
par db 30 dup(?)
endl
pushad
;[net]
;active
lea eax, [par]
invoke ini.get_int, conf_fname, unet, unet_active, 0
or eax, eax
jz .do_not_set_net
mov eax, [stack_config]
and eax, 0xFFFFFF80
add eax, 3
mov [stack_config], eax
call ash_eth_enable
;addr
lea eax, [par]
push eax
invoke ini.get_str, conf_fname, unet, unet_addr, eax, 30, unet_def
pop eax
stdcall do_inet_adr, eax
mov [stack_ip], eax
;mask
lea eax, [par]
push eax
invoke ini.get_str, conf_fname, unet, unet_mask, eax, 30, unet_def
pop eax
stdcall do_inet_adr, eax
mov [subnet_mask], eax
;gate
lea eax, [par]
push eax
invoke ini.get_str, conf_fname, unet, unet_gate, eax, 30, unet_def
pop eax
stdcall do_inet_adr, eax
mov [gateway_ip], eax
.do_not_set_net:
popad
ret
endp
iglobal
if lang eq sp
include 'core/conf_lib-sp.inc'
+12
View File
@@ -101,6 +101,12 @@ iglobal
szUSBNormalTransferAsync db 'USBNormalTransferAsync',0
szUSBControlTransferAsync db 'USBControlTransferAsync',0
szNetRegDev db 'NetRegDev',0
szNetUnRegDev db 'NetUnRegDev',0
szNetPtrToNum db 'NetPtrToNum',0
szNetLinkChanged db 'NetLinkChanged',0
szEth_input db 'Eth_input',0
align 16
kernel_export:
dd szRegService , reg_service
@@ -191,6 +197,12 @@ kernel_export:
dd szUSBNormalTransferAsync, usb_normal_transfer_async
dd szUSBControlTransferAsync, usb_control_async
dd szNetRegDev , NET_add_device
dd szNetUnRegDev , NET_remove_device
dd szNetPtrToNum , NET_ptr_to_num
dd szNetLinkChanged , NET_link_changed
dd szEth_input , ETH_input
exp_lfb:
dd szLFBAddress , 0
dd 0 ;terminator, must be zero
+6 -6
View File
@@ -112,7 +112,7 @@ iglobal
align 4
servetable:
dd socket ; 53-Socket interface
dd 0
dd 0
dd 0
dd 0
@@ -182,8 +182,8 @@ iglobal
dd sys_apm ; 49-Advanced Power Management (APM)
dd syscall_set_window_shape ; 50-Window shape & scale
dd syscall_threads ; 51-Threads
dd stack_driver_stat ; 52-Stack driver status
dd cross_order ; 53-Socket interface
dd undefined_syscall ; 52-Stack driver status
dd undefined_syscall ; 53-Socket interface
dd undefined_syscall ; 54-reserved
dd sound_interface ; 55-Sound interface
dd undefined_syscall ; 56-reserved
@@ -204,9 +204,9 @@ iglobal
dd syscall_window_settings ; 71-Window settings
dd sys_sendwindowmsg ; 72-Send window message
dd blit_32 ; 73-blitter;
dd undefined_syscall ; 74-reserved for new stack
dd undefined_syscall ; 75-reserved for new stack
dd undefined_syscall ; 76-reserved for new stack
dd sys_network ; 74-reserved for new stack
dd sys_socket ; 75-reserved for new stack
dd sys_protocols ; 76-reserved for new stack
times 255 - ( ($-servetable2) /4 ) dd undefined_syscall
dd sys_end ; -1-end application
+3 -3
View File
@@ -515,8 +515,8 @@ align 4
jz .no_events ; исчерпали все биты маски, но ничего не нашли ???
btr ecx, eax ; сбрасываем проверяемый бит маски
; переходим на обработчик этого (eax) бита
cmp eax, 9
jae .loop ; eax=[9..31], ignored (event 10...32)
cmp eax, 10
jae .loop ; eax=[10..31], ignored (event 10...32)
cmp eax, 3
je .loop ; eax=3, ignored (event 4)
@@ -527,7 +527,7 @@ align 4
cmp eax, 5
je .mouse_check ; eax=5, retvals=eax+1 (event 6)
ja .FlagAutoReset ; eax=[6..8], retvals=eax+1 (event 7...9)
ja .FlagAutoReset ; eax=[6..9], retvals=eax+1 (event 7...10)
cmp eax, 1
jae .BtKy ; eax=[1,2], retvals=eax+1 (event 2,3)
+14 -35
View File
@@ -77,7 +77,7 @@ $Revision$
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
@@ -638,12 +638,6 @@ no_mode_0x12:
mov dword [current_slot], SLOT_BASE + 256*2
mov dword [TASK_BASE], CURRENT_TASK + 32*2
stdcall kernel_alloc, 0x10000/8
mov edi, eax
mov [network_free_ports], eax
or eax, -1
mov ecx, 0x10000/32
rep stosd
; REDIRECT ALL IRQ'S TO INT'S 0x20-0x2f
mov esi, boot_initirq
@@ -883,12 +877,6 @@ end if
stdcall map_page, tss._io_map_1, \
[SLOT_BASE+256+APPDATA.io_map+4], PG_MAP
mov ax, [OS_BASE+0x10000+bx_from_load]
cmp ax, 'r1'; if not rused ram disk - load network configuration from files {SPraid.simba}
je no_st_network
call set_network_conf
no_st_network:
; LOAD FIRST APPLICATION
cli
@@ -2028,6 +2016,13 @@ sys_end:
call restore_default_cursor_before_killing
popa
@@:
;--------------------------------------
; kill all sockets this process owns
pusha
mov edx, [TASK_BASE]
mov edx, [edx+TASKDATA.pid]
call SOCKET_process_end
popa
;--------------------------------------
mov ecx, [current_slot]
mov eax, [ecx+APPDATA.tls_base]
@@ -2154,6 +2149,12 @@ sysfn_terminate: ; 18.2 = TERMINATE
pop edx ecx
test eax, eax
jz noprocessterminate
;--------------------------------------
; terminate all network sockets it used
pusha
mov eax, edx
call SOCKET_process_end
popa
;--------------------------------------
cmp [_display.select_cursor], 0
je .restore_end
@@ -5366,28 +5367,6 @@ syscall_threads: ; CreateThreads
align 4
stack_driver_stat:
call app_stack_handler ; Stack status
; mov [check_idle_semaphore],5 ; enable these for zero delay
; call change_task ; between sent packet
mov [esp+32], eax
ret
align 4
socket: ; Socket interface
call app_socket_handler
; mov [check_idle_semaphore],5 ; enable these for zero delay
; call change_task ; between sent packet
mov [esp+36], eax
mov [esp+24], ebx
ret
paleholder:
ret
;------------------------------------------------------------------------------
+645
View File
@@ -0,0 +1,645 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ARP.INC ;;
;; ;;
;; Part of the tcp/ip network stack for KolibriOS ;;
;; ;;
;; Based on the work of [Johnny_B] and [smb] ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June- 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision: 3386 $
ARP_NO_ENTRY = 0
ARP_VALID_MAPPING = 1
ARP_AWAITING_RESPONSE = 2
ARP_RESPONSE_TIMEOUT = 3
ARP_REQUEST_TTL = 31 ; 20 s
ARP_ENTRY_TTL = 937 ; 600 s
ARP_STATIC_ENTRY = -1
ARP_REQ_OPCODE = 0x0100 ; request
ARP_REP_OPCODE = 0x0200 ; reply
ARP_TABLE_SIZE = 20 ; Size of table
struct ARP_entry
IP dd ?
MAC dp ?
Status dw ?
TTL dw ?
ends
struct ARP_header
HardwareType dw ?
ProtocolType dw ?
HardwareSize db ?
ProtocolSize db ?
Opcode dw ?
SenderMAC dp ?
SenderIP dd ?
TargetMAC dp ?
TargetIP dd ?
ends
align 4
uglobal
NumARP dd ?
ARP_table rb ARP_TABLE_SIZE * sizeof.ARP_entry ; TODO: separate ARP table and stats per interface
ARP_PACKETS_TX rd MAX_NET_DEVICES
ARP_PACKETS_RX rd MAX_NET_DEVICES
ARP_CONFLICTS rd MAX_NET_DEVICES
endg
;-----------------------------------------------------------------
;
; ARP_init
;
; This function resets all ARP variables
;
;-----------------------------------------------------------------
macro ARP_init {
xor eax, eax
mov [NumARP], eax
mov edi, ARP_PACKETS_TX
mov ecx, 3*MAX_NET_DEVICES
rep stosd
}
;---------------------------------------------------------------------------
;
; ARP_decrease_entry_ttls
;
;---------------------------------------------------------------------------
macro ARP_decrease_entry_ttls {
local .loop
local .exit
; 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
mov ecx, [NumARP]
test ecx, ecx
jz .exit
mov esi, ARP_table
.loop:
cmp [esi + ARP_entry.TTL], ARP_STATIC_ENTRY
je .next
dec [esi + ARP_entry.TTL]
jz .time_out
.next:
add esi, sizeof.ARP_entry
dec ecx
jnz .loop
jmp .exit
.time_out:
cmp [esi + ARP_entry.Status], ARP_AWAITING_RESPONSE
je .response_timeout
push esi ecx
call ARP_del_entry
pop ecx esi
jmp .next
.response_timeout:
mov [esi + ARP_entry.Status], ARP_RESPONSE_TIMEOUT
mov [esi + ARP_entry.TTL], 10
jmp .next
.exit:
}
;-----------------------------------------------------------------
;
; ARP_input
;
; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
; packet size (without ethernet header) in ecx
; packet ptr in edx
; device ptr in ebx
; OUT: /
;
;-----------------------------------------------------------------
align 4
ARP_input:
;-----------------------------------------
; Check validity and print some debug info
cmp ecx, sizeof.ARP_header
jb .exit
call NET_ptr_to_num
cmp edi, -1
jz .exit
inc [ARP_PACKETS_RX + 4*edi] ; update stats
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
;------------------------------
; First, check for IP collision
mov eax, [edx + ARP_header.SenderIP]
cmp eax, [IP_LIST + 4*edi]
je .collision
;---------------------
; Handle reply packets
cmp [edx + ARP_header.Opcode], ARP_REP_OPCODE
jne .maybe_request
DEBUGF 1,"ARP_input: It's a reply\n"
mov ecx, [NumARP]
test ecx, ecx
jz .exit
mov esi, ARP_table
.loop:
cmp [esi + ARP_entry.IP], eax
je .gotit
add esi, sizeof.ARP_entry
dec ecx
jnz .loop
DEBUGF 1,"ARP_input: no matching entry found\n"
jmp .exit
.gotit:
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 1,"ARP_input: updating entry\n"
mov [esi + ARP_entry.Status], ARP_VALID_MAPPING
mov [esi + ARP_entry.TTL], ARP_ENTRY_TTL
mov eax, dword [edx + ARP_header.SenderMAC]
mov dword [esi + ARP_entry.MAC], eax
mov cx, word [edx + ARP_header.SenderMAC + 4]
mov word [esi + ARP_entry.MAC + 4], cx
jmp .exit
;-----------------------
; Handle request packets
.maybe_request:
cmp [edx + ARP_header.Opcode], ARP_REQ_OPCODE
jne .exit
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?
jne .exit
push eax
push edi
; OK, it is a request for one of our MAC addresses.
; Build the frame and send it. We can reuse the buffer. (faster then using ARP_create_packet)
lea esi, [edx + ARP_header.SenderMAC]
lea edi, [edx + ARP_header.TargetMAC]
movsd ; Move Sender Mac to Dest MAC
movsw ;
movsd ; Move sender IP to Dest IP
pop esi
mov esi, [NET_DRV_LIST + 4*esi]
lea esi, [esi + ETH_DEVICE.mac]
lea edi, [edx + ARP_header.SenderMAC]
movsd ; Copy MAC address from in MAC_LIST
movsw ;
pop eax
stosd ; Write our IP
mov [edx + ARP_header.Opcode], ARP_REP_OPCODE
; Now, Fill in ETHERNET header
mov edi, [esp]
lea esi, [edx + ARP_header.TargetMAC]
movsd
movsw
lea esi, [edx + ARP_header.SenderMAC]
movsd
movsw
; mov ax , ETHER_ARP ; It's already there, I'm sure of it!
; stosw
DEBUGF 1,"ARP_input: Sending reply\n"
call [ebx + NET_DEVICE.transmit]
ret
.collision:
inc [ARP_CONFLICTS + 4*edi]
DEBUGF 1,"ARP_input: IP address conflict detected!\n"
.exit:
call kernel_free
add esp, 4 ; pop (balance stack)
DEBUGF 1,"ARP_input: exiting\n"
ret
;---------------------------------------------------------------------------
;
; ARP_output_request
;
; IN: ip in eax
; device in edi
; OUT: /
;
;---------------------------------------------------------------------------
align 4
ARP_output_request:
push eax ; DestIP
pushd [IP_LIST + edi] ; SenderIP
inc [ARP_PACKETS_TX + edi] ; assume we will succeed
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
lea eax, [ebx + ETH_DEVICE.mac] ; local device mac
mov edx, ETH_BROADCAST ; broadcast mac
mov ecx, sizeof.ARP_header
mov di, ETHER_ARP
call ETH_output
jz .exit
mov ecx, eax
mov [edi + ARP_header.HardwareType], 0x0100 ; Ethernet
mov [edi + ARP_header.ProtocolType], 0x0008 ; IP
mov [edi + ARP_header.HardwareSize], 6 ; MAC-addr length
mov [edi + ARP_header.ProtocolSize], 4 ; IP-addr length
mov [edi + ARP_header.Opcode], ARP_REQ_OPCODE ; Request
add edi, ARP_header.SenderMAC
lea esi, [ebx + ETH_DEVICE.mac] ; SenderMac
movsw ;
movsd ;
pop eax ; SenderIP
stosd ;
mov eax, -1 ; DestMac
stosd ;
stosw ;
pop eax ; DestIP
stosd ;
DEBUGF 1,"ARP_output_request: device=%x\n", ebx
push edx ecx
call [ebx + NET_DEVICE.transmit]
ret
.exit:
add esp, 4 + 4
DEBUGF 1,"ARP_output_request: failed\n"
sub eax, eax
ret
;-----------------------------------------------------------------
;
; ARP_add_entry (or update)
;
; IN: esi = ptr to entry (can easily be made on the stack)
; OUT: eax = entry #, -1 on error
; edi = ptr to newly created entry
;
;----------------------------------------------------------------- ; TODO: use a mutex
align 4
ARP_add_entry:
DEBUGF 1,"ARP_add_entry: "
mov ecx, [NumARP]
cmp ecx, ARP_TABLE_SIZE ; list full ?
jae .error
xor eax, eax
mov edi, ARP_table
mov ecx, [esi + ARP_entry.IP]
.loop:
cmp [edi + ARP_entry.Status], ARP_NO_ENTRY ; is this slot empty?
je .add
cmp [edi + ARP_entry.IP], ecx ; if not, check if it doesnt collide
jne .maybe_next
cmp [edi + ARP_entry.TTL], ARP_STATIC_ENTRY ; ok, its the same IP, update it if not static
jne .add
.maybe_next: ; try the next slot
add edi, sizeof.ARP_entry
inc eax
cmp eax, ARP_TABLE_SIZE
jae .error
jmp .loop
.add:
mov ecx, sizeof.ARP_entry/2
rep movsw
inc [NumARP]
sub edi, sizeof.ARP_entry
DEBUGF 1,"entry=%u\n", eax
ret
.error:
DEBUGF 1,"failed\n"
mov eax, -1
ret
;-----------------------------------------------------------------
;
; ARP_del_entry
;
; IN: esi = ptr to arp entry
; OUT: /
;
;-----------------------------------------------------------------
align 4
ARP_del_entry:
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
sub ecx, esi
shr ecx, 1
mov edi, esi
add esi, sizeof.ARP_entry
rep movsw
xor eax, eax
mov ecx, sizeof.ARP_entry/2
rep stosw
dec [NumARP]
DEBUGF 1,"ARP_del_entry: success\n"
ret
;-----------------------------------------------------------------
;
; ARP_IP_to_MAC
;
; This function translates an IP address to a MAC address
;
; IN: eax = IPv4 address
; edi = device number
; OUT: eax = -1 on error, -2 means request send
; else, ax = first two bytes of mac (high 16 bits of eax will be 0)
; ebx = last four bytes of mac
; edi = unchanged
;
;-----------------------------------------------------------------
align 4
ARP_IP_to_MAC:
DEBUGF 1,"ARP_IP_to_MAC: %u.%u", al, ah
rol eax, 16
DEBUGF 1,".%u.%u\n", al, ah
rol eax, 16
cmp eax, 0xffffffff
je .broadcast
;--------------------------------
; Try to find the IP in ARP_table
mov ecx, [NumARP]
test ecx, ecx
jz .not_in_list
mov esi, ARP_table + ARP_entry.IP
.scan_loop:
cmp [esi], eax
je .found_it
add esi, sizeof.ARP_entry
loop .scan_loop
.not_in_list:
DEBUGF 1,"ARP_IP_to_MAC: preparing for ARP request\n"
;--------------------
; Send an ARP request
push eax edi ; save IP for ARP_output_request
; Now create the ARP entry
pushw ARP_REQUEST_TTL ; TTL
pushw ARP_AWAITING_RESPONSE ; status
pushd 0 ; mac
pushw 0
pushd eax ; ip
mov esi, esp
call ARP_add_entry
add esp, sizeof.ARP_entry ; clear the entry from stack
cmp eax, -1 ; did ARP_add_entry fail?
je .full
mov esi, edi
pop edi eax ; IP in eax, device number in edi, for ARP_output_request
push esi edi
call ARP_output_request ; And send a request
pop edi esi
;-----------------------------------------------
; At this point, we got an ARP entry in the list
.found_it:
cmp [esi + ARP_entry.Status], ARP_VALID_MAPPING ; Does it have a MAC assigned?
je .valid
if ARP_BLOCK
cmp [esi + ARP_entry.Status], ARP_AWAITING_RESPONSE ; Are we waiting for reply from remote end?
jne .give_up
push esi
mov esi, 10 ; wait 10 ms
call delay_ms
pop esi
jmp .found_it ; now check again
else
jmp .give_up
end if
.valid:
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 1,"ARP_IP_to_MAC: table is full!\n"
add esp, 8
.give_up:
DEBUGF 1,"ARP_IP_to_MAC: entry has no valid mapping!\n"
mov eax, -1
ret
.broadcast:
mov eax, 0x0000ffff
mov ebx, 0xffffffff
ret
;-----------------------------------------------------------------
;
; ARP_API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT: ?
;
;-----------------------------------------------------------------
align 4
ARP_api:
movzx eax, bh
shl eax, 2
and ebx, 0xff
cmp ebx, .number
ja .error
jmp dword [.table + 4*ebx]
.table:
dd .packets_tx ; 0
dd .packets_rx ; 1
dd .entries ; 2
dd .read ; 3
dd .write ; 4
dd .remove ; 5
dd .send_announce ; 6
dd .conflicts ; 7
.number = ($ - .table) / 4 - 1
.error:
mov eax, -1
ret
.packets_tx:
mov eax, [ARP_PACKETS_TX + eax]
ret
.packets_rx:
mov eax, [ARP_PACKETS_RX + eax]
ret
.conflicts:
mov eax, [ARP_CONFLICTS + eax]
ret
.entries:
mov eax, [NumARP]
ret
.read:
cmp ecx, [NumARP]
jae .error
; edi = pointer to buffer
; ecx = # entry
imul ecx, sizeof.ARP_entry
add ecx, ARP_table
mov esi, ecx
mov ecx, sizeof.ARP_entry/2
rep movsw
xor eax, eax
ret
.write:
; esi = pointer to buffer
call ARP_add_entry ; out: eax = entry number, -1 on error
ret
.remove:
; ecx = # entry
cmp ecx, [NumARP]
jae .error
imul ecx, sizeof.ARP_entry
lea esi, [ARP_table + ecx]
call ARP_del_entry
ret
.send_announce:
mov edi, eax
mov eax, [IP_LIST + eax]
call ARP_output_request ; now send a gratuitous ARP
ret
File diff suppressed because it is too large Load Diff
+298
View File
@@ -0,0 +1,298 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2012-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; IPv6.INC ;;
;; ;;
;; Part of the tcp/ip network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision: 3251 $
struct IPv6_header
VersionTrafficFlow dd ? ; Version[0-3], Traffic class[4-11], Flow Label [12-31]
PayloadLength dw ? ; 16 bits, unsigned length of payload (extension headers are part of this)
NextHeader db ? ; Values are same as in IPv4 'Protocol' field
HopLimit db ? ; Decremented by every node, packet is discarded when it reaches 0
SourceAddress rd 4 ; 128-bit addresses
DestinationAddress rd 4 ;
Payload rb 0
ends
align 4
uglobal
IPv6:
.addresses rd 4*MAX_NET_DEVICES
.subnet rd 4*MAX_NET_DEVICES
.dns rd 4*MAX_NET_DEVICES
.gateway rd 4*MAX_NET_DEVICES
.packets_tx rd MAX_NET_DEVICES
.packets_rx rd MAX_NET_DEVICES
endg
;-----------------------------------------------------------------
;
; IPv6_init
;
; This function resets all IP variables
;
;-----------------------------------------------------------------
macro IPv6_init {
xor eax, eax
mov edi, IPv6
mov ecx, (4*4*4+2*4)MAX_IP
rep stosd
}
;-----------------------------------------------------------------
;
; IPv6_input:
;
; Will check if IPv6 Packet isnt damaged
; and call appropriate handler. (TCP/UDP/ICMP/..)
;
; It will also re-construct fragmented packets
;
; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
; pointer to device struct in ebx
; pointer to IPv6 header in edx
; size of IPv6 packet in ecx
; OUT: /
;
;-----------------------------------------------------------------
align 4
IPv6_input:
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,\
[edx + IPv6_header.SourceAddress + 6]:2,[edx + IPv6_header.SourceAddress + 7]:2,\
[edx + IPv6_header.SourceAddress + 8]:2,[edx + IPv6_header.SourceAddress + 9]:2,\
[edx + IPv6_header.SourceAddress + 10]:2,[edx + IPv6_header.SourceAddress + 11]:2,\
[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 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,\
[edx + IPv6_header.DestinationAddress + 6]:2,[edx + IPv6_header.DestinationAddress + 7]:2,\
[edx + IPv6_header.DestinationAddress + 8]:2,[edx + IPv6_header.DestinationAddress + 9]:2,\
[edx + IPv6_header.DestinationAddress + 10]:2,[edx + IPv6_header.DestinationAddress + 11]:2,\
[edx + IPv6_header.DestinationAddress + 12]:2,[edx + IPv6_header.DestinationAddress + 13]:2,\
[edx + IPv6_header.DestinationAddress + 14]:2,[edx + IPv6_header.DestinationAddress + 15]:2
sub ecx, sizeof.IPv6_header
jb .dump
cmp cx, [edx + IPv6_header.PayloadLength]
jb .dump
;-------------------------------------------------------------------
; No, it's just a regular IP packet, pass it to the higher protocols
.handle_it:
movzx ecx, [edx + IPv6_header.PayloadLength]
lea edi, [edx + IPv6_header.SourceAddress] ; make edi ptr to source and dest IPv6 address
lea esi, [edx + IPv6_header.Payload] ; make esi ptr to data
mov al, [edx + IPv6_header.NextHeader]
.scan:
cmp al, 59 ; no next
je .dump
cmp al, 0
je .hop_by_hop
cmp al, 43
je .routing
cmp al, 44
je .fragment
cmp al, 60
je .dest_opts
; cmp al, IP_PROTO_TCP
; je TCP_input
; cmp al, IP_PROTO_UDP
; je UDP_input
; cmp al, 58
; je ICMP6_input
DEBUGF 2,"IPv6_input - unknown protocol: %u\n", al
.dump:
DEBUGF 1,"IPv6_input - dumping\n"
call kernel_free
add esp, 4
ret
.dump_options:
add esp, 2+4+4
jmp .dump
.nextheader:
pop esi
pop ecx
pop ax
jmp .scan
;-------------------------
; Hop-by-Hop
.hop_by_hop:
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
shl eax, 3 ; * 8
sub ecx, eax
push ecx
add eax, esi
push eax
inc esi
inc esi
mov al, [esi]
cmp al, 0
je .pad_1
cmp al, 1
je .pad_n
; TODO: check with other known options
; unknown option.. discard packet or not?
; check highest two bits
test al, 0xc0 ; discard packet
jnz .dump_options
.pad_n:
movzx eax, byte[esi + 1]
DEBUGF 1,"IPv6_input - pad %u\n", eax
inc esi
inc esi
add esi, eax
sub ecx, eax
jmp .hop_by_hop
.pad_1:
DEBUGF 1,"IPv6_input - pad 1\n"
inc esi
dec ecx
jmp .hop_by_hop
.dest_opts:
DEBUGF 1,"IPv6_input - dest opts\n"
jmp .nextheader
.routing:
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
shl eax, 3 ; * 8
sub ecx, eax
push ecx
add eax, esi
push eax
inc esi
inc esi
cmp al, 0
je .pad_1
cmp al, 1
je .pad_n
mov al, [esi] ; routing type
jmp .nextheader
.fragment:
DEBUGF 1,"IPv6_input - fragment\n"
jmp .nextheader
;---------------------------------------------------------------------------
;
; IPv6_API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;---------------------------------------------------------------------------
align 4
IPv6_api:
movzx eax, bh
shl eax, 2
and ebx, 0x000000ff
cmp ebx, .number
ja .error
jmp dword [.table + 4*ebx]
.table:
dd .packets_tx ; 0
dd .packets_rx ; 1
; dd .read_ip ; 2
; dd .write_ip ; 3
; dd .read_dns ; 4
; dd .write_dns ; 5
; dd .read_subnet ; 6
; dd .write_subnet ; 7
; dd .read_gateway ; 8
; dd .write_gateway ; 9
.number = ($ - .table) / 4 - 1
.error:
mov eax, -1
ret
.packets_tx:
mov eax, [IPv6.packets_tx + eax]
ret
.packets_rx:
mov eax, [IPv6.packets_rx + eax]
ret
+340
View File
@@ -0,0 +1,340 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; PPPoE.INC ;;
;; ;;
;; Part of the tcp/ip network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
struct PPPoE_frame
VersionAndType db ?
Code db ?
SessionID dw ?
Length dw ? ; Length of payload, does NOT include the length PPPoE header.
Payload rb 0
ends
uglobal
PPPoE_SID dw ?
PPPoE_MAC dp ?
endg
;-----------------------------------------------------------------
;
; PPPoE_init
;
; This function resets all IP variables
;
;-----------------------------------------------------------------
macro PPPoE_init {
call PPPoE_stop_connection
}
;-----------------------------------------------------------------
;
; PPPoE discovery input
;
; Handler of received Ethernet packet with type = Discovery
;
;
; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
; pointer to device struct in ebx
; pointer to PPP header in edx
; size of PPP packet in ecx
; OUT: /
;
;-----------------------------------------------------------------
align 4
PPPoE_discovery_input:
DEBUGF 2,"PPPoE_discovery_input\n"
; First, find open PPPoE socket
mov eax, net_sockets
.next_socket:
mov eax, [eax + SOCKET.NextPtr]
or eax, eax
jz .dump
cmp [eax + SOCKET.Domain], AF_PPP
jne .next_socket
cmp [eax + SOCKET.Protocol], PPP_PROTO_ETHERNET
jne .next_socket
; Now, send it to the this socket
mov ecx, [esp + 4]
mov esi, [esp]
jmp SOCKET_input
.dump:
DEBUGF 1,'PPPoE_discovery_input: dumping\n'
call kernel_free
add esp, 4
ret
;--------------------------------------
;
; Send discovery packet
;
; IN: eax = socket pointer
; ecx = number of bytes to send
; esi = pointer to data
;
;--------------------------------------
align 4
PPPoE_discovery_output:
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.
cmp ecx, 1484 + 14
ja .bad
; Check that device exists and is ethernet device
mov ebx, [eax + SOCKET.device]
cmp ebx, MAX_NET_DEVICES
ja .bad
mov ebx, [NET_DRV_LIST + 4*ebx]
test ebx, ebx
jz .bad
cmp [ebx + NET_DEVICE.type], NET_TYPE_ETH
jne .bad
DEBUGF 2,"PPPoE_discovery_output: device=%x\n", ebx
; Create packet.
push ecx esi
stdcall kernel_alloc, 1500
pop esi ecx
test eax, eax
jz .bad
mov edx, ecx
mov edi, eax
rep movsb
cmp edx, 60 ; Min ETH size
ja @f
mov edx, 60
@@:
push edx eax ; size and packet ptr for driver send proc
; Overwrite source MAC and protocol type
lea edi, [eax + ETH_header.SrcMAC]
lea esi, [ebx + ETH_DEVICE.mac]
movsd
movsw
cmp word[edi], ETHER_PPP_SESSION ; Allow only PPP_discovery, or LCP
je @f
mov ax, ETHER_PPP_DISCOVERY
stosw
@@:
; And send the packet
call [ebx + NET_DEVICE.transmit]
xor eax, eax
ret
.bad:
or eax, -1
ret
;-----------------------------------------------------------------
;
; PPPoE session input
;
; Handler of received Ethernet packet with type = Session
;
;
; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
; pointer to device struct in ebx
; pointer to PPP header in edx
; size of PPP packet in ecx
; OUT: /
;
;-----------------------------------------------------------------
align 4
PPPoE_session_input:
cmp [edx + PPPoE_frame.VersionAndType], 0x11
jne .dump
cmp [edx + PPPoE_frame.Code], 0x00
jne .dump
movzx ecx, [edx + PPPoE_frame.Length]
xchg cl, ch
mov ax, [edx + PPPoE_frame.SessionID]
DEBUGF 2,"PPPoE_input: session ID=%x, length=%u\n", ax, cx
cmp ax, [PPPoE_SID]
jne .dump
mov ax, word [edx + PPPoE_frame.Payload]
add edx, PPPoE_frame.Payload + 2
cmp ax, PPP_IPv4
je IPv4_input
; cmp ax, PPP_IPv6
; je IPv6_input
jmp PPPoE_discovery_input ; Send LCP,CHAP,CBCP,... packets to the PPP dialer
DEBUGF 2,"PPPoE_input: Unknown protocol=%x\n", ax
.dump:
DEBUGF 2,"PPPoE_input: dumping\n"
call kernel_free
add esp, 4
ret
;-----------------------------------------------------------------
;
; PPPoE_output
;
; IN:
; ebx = device ptr
; ecx = packet size
;
; di = protocol
;
; OUT: edi = 0 on error, pointer to buffer otherwise
; eax = buffer start
; ebx = to device structure
; ecx = unchanged (packet size of embedded data)
; edx = size of complete buffer
;
;-----------------------------------------------------------------
align 4
PPPoE_output:
DEBUGF 1,"PPPoE_output: size=%u device=%x\n", ecx, ebx
pushw di
pushw [PPPoE_SID]
lea eax, [ebx + ETH_DEVICE.mac]
lea edx, [PPPoE_MAC]
add ecx, PPPoE_frame.Payload + 2
mov di, ETHER_PPP_SESSION
call ETH_output
jz .eth_error
sub ecx, PPPoE_frame.Payload
mov [edi + PPPoE_frame.VersionAndType], 0x11
mov [edi + PPPoE_frame.Code], 0
popw [edi + PPPoE_frame.SessionID]
xchg cl, ch
mov [edi + PPPoE_frame.Length], cx
xchg cl, ch
pop word [edi + PPPoE_frame.Payload]
sub ecx, 2
add edi, PPPoE_frame.Payload + 2
DEBUGF 1,"PPPoE_output: success!\n"
ret
.eth_error:
add esp, 4
xor edi, edi
ret
PPPoE_start_connection:
DEBUGF 2,"PPPoE_start_connection: %x\n", cx
cmp [PPPoE_SID], 0
jne .fail
mov [PPPoE_SID], cx
mov dword [PPPoE_MAC], edx
mov word [PPPoE_MAC + 4], si
xor eax, eax
ret
.fail:
or eax, -1
ret
align 4
PPPoE_stop_connection:
DEBUGF 2,"PPPoE_stop_connection\n"
xor eax, eax
mov [PPPoE_SID], ax
mov dword [PPPoE_MAC], eax
mov word [PPPoE_MAC + 4], ax
ret
;---------------------------------------------------------------------------
;
; PPPoE API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;---------------------------------------------------------------------------
align 4
PPPoE_api:
movzx eax, bh
shl eax, 2
and ebx, 0xff
cmp ebx, .number
ja .error
jmp dword [.table + 4*ebx]
.table:
dd PPPoE_start_connection ; 0
dd PPPoE_stop_connection ; 1
.number = ($ - .table) / 4 - 1
.error:
mov eax, -1
ret
-557
View File
@@ -1,557 +0,0 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 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
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,794 +0,0 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 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
@@ -1,848 +0,0 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 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