Merge new network stack with trunk
git-svn-id: svn://kolibrios.org@3545 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
43f6a7d07a
commit
e4cf34c0de
@ -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
|
||||
|
@ -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
|
||||
bh = device number, for all following functions !
|
||||
|
||||
And the following internet applcations are implemented
|
||||
bl = 0 (Get device type)
|
||||
|
||||
HTTP Server
|
||||
Telnet
|
||||
POP Client
|
||||
DNS Name resolver
|
||||
MP3 Server
|
||||
TFTP Client
|
||||
IRC Client
|
||||
out:
|
||||
eax = device type number
|
||||
|
||||
There are also a number of experimental applications for streaming music
|
||||
and performing interprocess communication via sockets. A Web broswer is in
|
||||
development
|
||||
bl = 1 (Get device name)
|
||||
|
||||
in:
|
||||
ecx = pointer to 64 byte buffer
|
||||
out:
|
||||
name is copied into the buffer
|
||||
eax = -1 on error
|
||||
|
||||
What is not implemented
|
||||
=======================
|
||||
bl = 2 (Reset the device)
|
||||
|
||||
The IP layer does not process header options.
|
||||
The IP layer does not support routing.
|
||||
Packet fragmentation is not supported.
|
||||
in
|
||||
none
|
||||
out
|
||||
eax = -1 on error
|
||||
|
||||
bl = 3 (Stop device)
|
||||
|
||||
How to configure Kolibri for PPP
|
||||
===============================
|
||||
in
|
||||
none
|
||||
out
|
||||
eax = -1 on error
|
||||
|
||||
See ppp.txt
|
||||
TO BE FIGURED OUT
|
||||
|
||||
eax = 75 - Work with Sockets
|
||||
|
||||
How to configure Kolibri for Ethernet
|
||||
====================================
|
||||
These functions work like the ones found in UNIX (and windows)
|
||||
for more info, please read http://beej.us/guide/bgnet/
|
||||
|
||||
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.
|
||||
bl = 0 (Open Socket)
|
||||
|
||||
Setting Up the ARP Table
|
||||
------------------------
|
||||
in:
|
||||
ecx = domain
|
||||
edx = type
|
||||
esi = protocol
|
||||
out:
|
||||
eax = socket number, -1 on error
|
||||
|
||||
Kolibri's ARP table is dynamically created and maintained; You can see what
|
||||
hosts Kolibri has communicated with by running the ARPSTAT application.
|
||||
bl = 1 (Close Socket)
|
||||
|
||||
Enabling Ethernet
|
||||
-----------------
|
||||
in:
|
||||
ecx = socket number
|
||||
out:
|
||||
eax = -1 on error
|
||||
|
||||
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 = 2 (Bind)
|
||||
|
||||
in:
|
||||
ecx = socket number
|
||||
edx = pointer to sockaddr structure
|
||||
esi = length of sockaddr structure
|
||||
out:
|
||||
eax = -1 on error
|
||||
|
||||
The stack is now running, which you can test by pinging Kolibri from a
|
||||
remote host.
|
||||
bl = 3 (Listen)
|
||||
|
||||
in:
|
||||
ecx = socket number
|
||||
edx = backlog
|
||||
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 = 4 (connect)
|
||||
|
||||
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 = 5 (accept)
|
||||
|
||||
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 = pointer to sockaddr structure
|
||||
esi = length of sockaddr structure
|
||||
out:
|
||||
eax = socket number, -1 on error
|
||||
|
||||
bl = 6 (send)
|
||||
|
||||
Application Programming Interface
|
||||
=================================
|
||||
in:
|
||||
ecx = socket number
|
||||
edx = pointer to buffer
|
||||
esi = length of buffer
|
||||
edi = flags
|
||||
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 = 7 (receive)
|
||||
|
||||
in:
|
||||
ecx = socket number
|
||||
edx = pointer to buffer
|
||||
esi = length of buffer
|
||||
edi = flags
|
||||
out:
|
||||
eax = number of bytes copied, -1 on error
|
||||
|
||||
Sockets
|
||||
=======
|
||||
bl = 8 (set socket options)
|
||||
|
||||
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 = level
|
||||
esi = optionname
|
||||
edi = ptr to buffer
|
||||
|
||||
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! )
|
||||
The buffer's first dword is the length of the buffer, minus the first dword offcourse
|
||||
|
||||
Lets deal with the terminology before we go any further.
|
||||
out:
|
||||
eax = -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 = 9 (get 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, socket option otherwise
|
||||
|
||||
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.
|
||||
TIP
|
||||
|
||||
when you import 'network.inc' and 'macros.inc' into your source code, you can use the following syntax to work with sockets:
|
||||
|
||||
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.
|
||||
|
||||
for example, to open a socket
|
||||
|
||||
Get Local IP Address
|
||||
--------------------
|
||||
eax = 52
|
||||
ebx = 1
|
||||
mcall socket, AF_INET, SOCK_DGRAM,0
|
||||
mov [socketnum], eax
|
||||
|
||||
IP address returned in eax ( in internet byte order )
|
||||
then to connect to a server
|
||||
|
||||
mcall connect, [socketnum], sockaddr, 18
|
||||
|
||||
Write to stack input queue
|
||||
--------------------------
|
||||
eax = 52
|
||||
ebx = 6
|
||||
edx = number of bytes to write
|
||||
esi = pointer to data ( in application space )
|
||||
|
||||
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
|
||||
This interface is for slow network drivers only ( PPP, SLIP )
|
||||
eax = 76 - Work with protocols
|
||||
|
||||
high half of ebx = protocol number (for all subfunctions!)
|
||||
bh = device number (for all subfunctions!)
|
||||
bl = subfunction number, depends on protocol type
|
||||
|
||||
Read data from network output queue
|
||||
-----------------------------------
|
||||
eax = 52
|
||||
ebx = 8
|
||||
esi = pointer to data ( in application space )
|
||||
For Ethernet protocol
|
||||
|
||||
On return, eax holds number of bytes transferred.
|
||||
This interface is for slow network drivers only ( PPP, SLIP )
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
Open a UDP socket
|
||||
-----------------
|
||||
eax = 53
|
||||
ebx = 0
|
||||
ecx = local port
|
||||
edx = remote port
|
||||
esi = remote ip address ( in internet byte order )
|
||||
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
|
||||
|
||||
The socket number allocated is returned in eax.
|
||||
A return value of 0xFFFFFFFF means no socket could be opened.
|
||||
0 - Read # ICMP packets send
|
||||
1 - Read # ICMP packets received
|
||||
3 - enable/disable ICMP echo reply
|
||||
For UDP protocol
|
||||
|
||||
0 - Read # UDP packets send
|
||||
1 - Read # UDP packets received
|
||||
For TCP 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 )
|
||||
|
||||
The socket number allocated is returned in eax.
|
||||
A return value of 0xFFFFFFFF means no socket could be opened.
|
||||
|
||||
|
||||
Close a socket (UDP Only )
|
||||
--------------------------
|
||||
eax = 53
|
||||
ebx = 1
|
||||
ecx = socket number
|
||||
|
||||
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
|
@ -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
data/eng/network.ini
Normal file
9
data/eng/network.ini
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
<EFBFBD>âĄŕĄâ-č ĺ¬ âë /rd/1/network/chess
|
||||
<EFBFBD>âĄŕĄâ § Łŕă§ç¨Ş /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
|
||||
<EFBFBD>¨ àë¥ ç áë /rd/1/demos/bcdclk
|
||||
|
9
data/rus/network.ini
Normal file
9
data/rus/network.ini
Normal 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
|
2954
drivers/ethernet/3c59x.asm
Normal file
2954
drivers/ethernet/3c59x.asm
Normal file
File diff suppressed because it is too large
Load Diff
1120
drivers/ethernet/R6040.asm
Normal file
1120
drivers/ethernet/R6040.asm
Normal file
File diff suppressed because it is too large
Load Diff
1203
drivers/ethernet/RTL8029.asm
Normal file
1203
drivers/ethernet/RTL8029.asm
Normal file
File diff suppressed because it is too large
Load Diff
1131
drivers/ethernet/RTL8139.asm
Normal file
1131
drivers/ethernet/RTL8139.asm
Normal file
File diff suppressed because it is too large
Load Diff
1324
drivers/ethernet/RTL8169.asm
Normal file
1324
drivers/ethernet/RTL8169.asm
Normal file
File diff suppressed because it is too large
Load Diff
424
drivers/ethernet/bcm57xx.asm
Normal file
424
drivers/ethernet/bcm57xx.asm
Normal 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
|
||||
|
||||
|
1702
drivers/ethernet/dec21x4x.asm
Normal file
1702
drivers/ethernet/dec21x4x.asm
Normal file
File diff suppressed because it is too large
Load Diff
1992
drivers/ethernet/forcedeth.asm
Normal file
1992
drivers/ethernet/forcedeth.asm
Normal file
File diff suppressed because it is too large
Load Diff
818
drivers/ethernet/i8254x.asm
Normal file
818
drivers/ethernet/i8254x.asm
Normal 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
|
||||
|
||||
|
1255
drivers/ethernet/i8255x.asm
Normal file
1255
drivers/ethernet/i8255x.asm
Normal file
File diff suppressed because it is too large
Load Diff
1266
drivers/ethernet/mtd80x.asm
Normal file
1266
drivers/ethernet/mtd80x.asm
Normal file
File diff suppressed because it is too large
Load Diff
1578
drivers/ethernet/pcnet32.asm
Normal file
1578
drivers/ethernet/pcnet32.asm
Normal file
File diff suppressed because it is too large
Load Diff
1679
drivers/ethernet/rhine.asm
Normal file
1679
drivers/ethernet/rhine.asm
Normal file
File diff suppressed because it is too large
Load Diff
1222
drivers/ethernet/sis900.asm
Normal file
1222
drivers/ethernet/sis900.asm
Normal file
File diff suppressed because it is too large
Load Diff
432
drivers/fdo.inc
Normal file
432
drivers/fdo.inc
Normal 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
|
||||
}
|
@ -1,151 +1,102 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
|
||||
;; 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
|
||||
|
||||
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
|
||||
|
||||
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
drivers/mii.inc
Normal file
160
drivers/mii.inc
Normal 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
drivers/netdrv.inc
Normal file
150
drivers/netdrv.inc
Normal 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
drivers/pci.inc
Normal file
132
drivers/pci.inc
Normal 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:
|
||||
|
||||
}
|
240
drivers/struct.inc
Normal file
240
drivers/struct.inc
Normal 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 \} }
|
1201
kernel/branches/net/applications/downloader/downloader.asm
Normal file
1201
kernel/branches/net/applications/downloader/downloader.asm
Normal file
File diff suppressed because it is too large
Load Diff
390
kernel/branches/net/applications/ftpc/ftpc.asm
Normal file
390
kernel/branches/net/applications/ftpc/ftpc.asm
Normal file
@ -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:
|
114
kernel/branches/net/applications/ftpc/servercommands.inc
Normal file
114
kernel/branches/net/applications/ftpc/servercommands.inc
Normal file
@ -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
|
17
kernel/branches/net/applications/ftpc/usercommands.inc
Normal file
17
kernel/branches/net/applications/ftpc/usercommands.inc
Normal file
@ -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
|
||||
|
@ -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
|
||||
|
@ -500,4 +500,5 @@ BiosDisksData rb 200h
|
||||
BiosDiskCaches rb 80h*(cache_ide1-cache_ide0)
|
||||
BiosDiskPartitions rd 80h
|
||||
|
||||
tetten:
|
||||
IncludeUGlobals
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
kernel/trunk/network/ARP.inc
Normal file
645
kernel/trunk/network/ARP.inc
Normal 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
|
||||
|
1019
kernel/trunk/network/IPv4.inc
Normal file
1019
kernel/trunk/network/IPv4.inc
Normal file
File diff suppressed because it is too large
Load Diff
298
kernel/trunk/network/IPv6.inc
Normal file
298
kernel/trunk/network/IPv6.inc
Normal 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
kernel/trunk/network/PPPoE.inc
Normal file
340
kernel/trunk/network/PPPoE.inc
Normal 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
|
@ -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
|
||||
PCNET32_DWIO_BDP equ 0x1C
|
||||
PCNET32_TOTAL_SIZE equ 0x20
|
||||
; ebx - index
|
||||
; return:
|
||||
; eax - data
|
||||
pcnet32_wio_read_csr:
|
||||
push edx
|
||||
lea edx, [ebp+PCNET32_WIO_RAP]
|
||||
mov ax, bx
|
||||
out dx, ax
|
||||
lea edx, [ebp+PCNET32_WIO_RDP]
|
||||
in ax, dx
|
||||
and eax, 0xffff
|
||||
pop edx
|
||||
ret
|
||||
; eax - data
|
||||
; ebx - index
|
||||
pcnet32_wio_write_csr:
|
||||
push edx
|
||||
lea edx, [ebp+PCNET32_WIO_RAP]
|
||||
xchg eax, ebx
|
||||
out dx, ax
|
||||
xchg eax, ebx
|
||||
lea edx, [ebp+PCNET32_WIO_RDP]
|
||||
out dx, ax
|
||||
pop edx
|
||||
ret
|
||||
; ebx - index
|
||||
; return:
|
||||
; eax - data
|
||||
pcnet32_wio_read_bcr:
|
||||
push edx
|
||||
lea edx, [ebp+PCNET32_WIO_RAP]
|
||||
mov ax, bx
|
||||
out dx, ax
|
||||
lea edx, [ebp+PCNET32_WIO_BDP]
|
||||
in ax, dx
|
||||
and eax, 0xffff
|
||||
pop edx
|
||||
ret
|
||||
; eax - data
|
||||
; ebx - index
|
||||
pcnet32_wio_write_bcr:
|
||||
push edx
|
||||
lea edx, [ebp+PCNET32_WIO_RAP]
|
||||
xchg eax, ebx
|
||||
out dx, ax
|
||||
xchg eax, ebx
|
||||
lea edx, [ebp+PCNET32_WIO_BDP]
|
||||
out dx, ax
|
||||
pop edx
|
||||
ret
|
||||
pcnet32_wio_read_rap:
|
||||
push edx
|
||||
lea edx, [ebp+PCNET32_WIO_RAP]
|
||||
in ax, dx
|
||||
and eax, 0xffff
|
||||
pop edx
|
||||
ret
|
||||
; eax - val
|
||||
pcnet32_wio_write_rap:
|
||||
push edx
|
||||
lea edx, [ebp+PCNET32_WIO_RAP]
|
||||
out dx, ax
|
||||
pop edx
|
||||
ret
|
||||
pcnet32_wio_reset:
|
||||
push edx
|
||||
push eax
|
||||
lea edx, [ebp+PCNET32_WIO_RESET]
|
||||
in ax, dx
|
||||
pop eax
|
||||
pop edx
|
||||
ret
|
||||
pcnet32_wio_check:
|
||||
push edx
|
||||
mov ax, 88
|
||||
lea edx, [ebp+PCNET32_WIO_RAP]
|
||||
out dx, ax
|
||||
nop
|
||||
nop
|
||||
in ax, dx
|
||||
cmp ax, 88
|
||||
sete al
|
||||
pop edx
|
||||
ret
|
||||
|
||||
iglobal
|
||||
pcnet32_wio:
|
||||
dd pcnet32_wio_read_csr
|
||||
dd pcnet32_wio_write_csr
|
||||
dd pcnet32_wio_read_bcr
|
||||
dd pcnet32_wio_write_bcr
|
||||
dd pcnet32_wio_read_rap
|
||||
dd pcnet32_wio_write_rap
|
||||
dd pcnet32_wio_reset
|
||||
endg
|
||||
|
||||
; ebx - index
|
||||
; return:
|
||||
; eax - data
|
||||
pcnet32_dwio_read_csr:
|
||||
push edx
|
||||
lea edx, [ebp+PCNET32_DWIO_RAP]
|
||||
mov eax, ebx
|
||||
out dx, eax
|
||||
lea edx, [ebp+PCNET32_DWIO_RDP]
|
||||
in eax, dx
|
||||
and eax, 0xffff
|
||||
pop edx
|
||||
ret
|
||||
; ebx - index
|
||||
; eax - data
|
||||
pcnet32_dwio_write_csr:
|
||||
push edx
|
||||
lea edx, [ebp+PCNET32_DWIO_RAP]
|
||||
xchg eax, ebx
|
||||
out dx, eax
|
||||
lea edx, [ebp+PCNET32_DWIO_RDP]
|
||||
xchg eax, ebx
|
||||
out dx, eax
|
||||
pop edx
|
||||
ret
|
||||
; ebx - index
|
||||
; return:
|
||||
; eax - data
|
||||
pcnet32_dwio_read_bcr:
|
||||
push edx
|
||||
lea edx, [ebp+PCNET32_DWIO_RAP]
|
||||
mov eax, ebx
|
||||
out dx, eax
|
||||
lea edx, [ebp+PCNET32_DWIO_BDP]
|
||||
in eax, dx
|
||||
and eax, 0xffff
|
||||
pop edx
|
||||
ret
|
||||
; ebx - index
|
||||
; eax - data
|
||||
pcnet32_dwio_write_bcr:
|
||||
push edx
|
||||
lea edx, [ebp+PCNET32_DWIO_RAP]
|
||||
xchg eax, ebx
|
||||
out dx, eax
|
||||
lea edx, [ebp+PCNET32_DWIO_BDP]
|
||||
xchg eax, ebx
|
||||
out dx, eax
|
||||
pop edx
|
||||
ret
|
||||
pcnet32_dwio_read_rap:
|
||||
push edx
|
||||
lea edx, [ebp+PCNET32_DWIO_RAP]
|
||||
in eax, dx
|
||||
and eax, 0xffff
|
||||
pop edx
|
||||
ret
|
||||
; eax - val
|
||||
pcnet32_dwio_write_rap:
|
||||
push edx
|
||||
lea edx, [ebp+PCNET32_DWIO_RAP]
|
||||
out dx, eax
|
||||
pop edx
|
||||
ret
|
||||
pcnet32_dwio_reset:
|
||||
push edx
|
||||
push eax
|
||||
lea edx, [ebp+PCNET32_DWIO_RESET]
|
||||
in eax, dx
|
||||
pop eax
|
||||
pop edx
|
||||
ret
|
||||
pcnet32_dwio_check:
|
||||
push edx
|
||||
lea edx, [PCNET32_DWIO_RAP]
|
||||
mov eax, 88
|
||||
out dx, eax
|
||||
nop
|
||||
nop
|
||||
in eax, dx
|
||||
and eax, 0xffff
|
||||
cmp eax, 88
|
||||
sete al
|
||||
pop edx
|
||||
ret
|
||||
|
||||
iglobal
|
||||
pcnet32_dwio:
|
||||
dd pcnet32_dwio_read_csr
|
||||
dd pcnet32_dwio_write_csr
|
||||
dd pcnet32_dwio_read_bcr
|
||||
dd pcnet32_dwio_write_bcr
|
||||
dd pcnet32_dwio_read_rap
|
||||
dd pcnet32_dwio_write_rap
|
||||
dd pcnet32_dwio_reset
|
||||
endg
|
||||
|
||||
|
||||
|
||||
pcnet32_init_ring:
|
||||
mov [pcnet32_private.tx_full], 0
|
||||
mov [pcnet32_private.cur_rx], 0
|
||||
mov [pcnet32_private.cur_tx], 0
|
||||
mov [pcnet32_private.dirty_rx], 0
|
||||
mov [pcnet32_private.dirty_tx], 0
|
||||
mov edi, pcnet32_rx_ring
|
||||
mov ecx, PCNET32_RX_RING_SIZE
|
||||
mov ebx, pcnet32_rxb
|
||||
sub ebx, OS_BASE
|
||||
.rx_init:
|
||||
mov [edi+pcnet32_rx_head.base], ebx
|
||||
mov [edi+pcnet32_rx_head.buf_length], word PCNET32_PKT_BUF_SZ_NEG
|
||||
mov [edi+pcnet32_rx_head.status], word 0x8000
|
||||
add ebx, PCNET32_PKT_BUF_SZ
|
||||
; inc ebx
|
||||
add edi, 16
|
||||
loop .rx_init
|
||||
mov edi, pcnet32_tx_ring
|
||||
mov ecx, PCNET32_TX_RING_SIZE
|
||||
.tx_init:
|
||||
mov [edi+pcnet32_tx_head.base], dword 0
|
||||
mov [edi+pcnet32_tx_head.status], word 0
|
||||
add edi, 16
|
||||
loop .tx_init
|
||||
mov [pcnet32_private.tlen_rlen], (PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS)
|
||||
mov esi, node_addr
|
||||
mov edi, pcnet32_private.phys_addr
|
||||
cld
|
||||
movsd
|
||||
movsw
|
||||
mov eax, pcnet32_rx_ring
|
||||
sub eax, OS_BASE
|
||||
mov dword [pcnet32_private.rx_ring], eax
|
||||
|
||||
mov eax, pcnet32_tx_ring
|
||||
sub eax, OS_BASE
|
||||
mov dword [pcnet32_private.tx_ring], eax
|
||||
ret
|
||||
|
||||
|
||||
|
||||
pcnet32_reset:
|
||||
; Reset PCNET32
|
||||
mov ebp, [io_addr]
|
||||
call dword [pcnet32_access.reset]
|
||||
; set 32bit mode
|
||||
mov ebx, 20
|
||||
mov eax, 2
|
||||
call dword [pcnet32_access.write_bcr]
|
||||
; set/reset autoselect bit
|
||||
mov ebx, 2
|
||||
call dword [pcnet32_access.read_bcr]
|
||||
and eax, not 2
|
||||
test [pcnet32_private.options], PCNET32_PORT_ASEL
|
||||
jz .L1
|
||||
or eax, 2
|
||||
.L1:
|
||||
call dword [pcnet32_access.write_bcr]
|
||||
; Handle full duplex setting
|
||||
cmp byte [pcnet32_private.full_duplex], 0
|
||||
je .L2
|
||||
mov ebx, 9
|
||||
call dword [pcnet32_access.read_bcr]
|
||||
and eax, not 3
|
||||
test [pcnet32_private.options], PCNET32_PORT_FD
|
||||
jz .L3
|
||||
or eax, 1
|
||||
cmp [pcnet32_private.options], PCNET32_PORT_FD or PCNET32_PORT_AUI
|
||||
jne .L4
|
||||
or eax, 2
|
||||
jmp .L4
|
||||
.L3:
|
||||
test [pcnet32_private.options], PCNET32_PORT_ASEL
|
||||
jz .L4
|
||||
cmp [pcnet32_private.chip_version], 0x2627
|
||||
jne .L4
|
||||
or eax, 3
|
||||
.L4:
|
||||
mov ebx, 9
|
||||
call dword [pcnet32_access.write_bcr]
|
||||
.L2:
|
||||
; set/reset GPSI bit
|
||||
mov ebx, 124
|
||||
call dword [pcnet32_access.read_csr]
|
||||
mov ecx, [pcnet32_private.options]
|
||||
and ecx, PCNET32_PORT_PORTSEL
|
||||
cmp ecx, PCNET32_PORT_GPSI
|
||||
jne .L5
|
||||
or eax, 0x10
|
||||
.L5:
|
||||
call dword [pcnet32_access.write_csr]
|
||||
cmp [pcnet32_private.mii], 0
|
||||
je .L6
|
||||
test [pcnet32_private.options], PCNET32_PORT_ASEL
|
||||
jnz .L6
|
||||
mov ebx, 32
|
||||
call dword [pcnet32_access.read_bcr]
|
||||
and eax, not 0x38
|
||||
test [pcnet32_private.options], PCNET32_PORT_FD
|
||||
jz .L7
|
||||
or eax, 0x10
|
||||
.L7:
|
||||
test [pcnet32_private.options], PCNET32_PORT_100
|
||||
jz .L8
|
||||
or eax, 0x08
|
||||
.L8:
|
||||
call dword [pcnet32_access.write_bcr]
|
||||
jmp .L9
|
||||
.L6:
|
||||
test [pcnet32_private.options], PCNET32_PORT_ASEL
|
||||
jz .L9
|
||||
mov ebx, 32
|
||||
; DEBUGF 1," K : ASEL, enable auto-negotiation\n"
|
||||
call dword [pcnet32_access.read_bcr]
|
||||
and eax, not 0x98
|
||||
or eax, 0x20
|
||||
call dword [pcnet32_access.write_bcr]
|
||||
.L9:
|
||||
cmp [pcnet32_private.ltint], 0
|
||||
je .L10
|
||||
mov ebx, 5
|
||||
call dword [pcnet32_access.read_csr]
|
||||
or eax, (1 shl 14)
|
||||
call dword [pcnet32_access.write_csr]
|
||||
.L10:
|
||||
mov eax, [pcnet32_private.options]
|
||||
and eax, PCNET32_PORT_PORTSEL
|
||||
shl eax, 7
|
||||
mov [pcnet32_private.mode], ax
|
||||
mov [pcnet32_private.filter], dword 0xffffffff
|
||||
mov [pcnet32_private.filter+4], dword 0xffffffff
|
||||
call pcnet32_init_ring
|
||||
mov ebx, 1
|
||||
mov eax, pcnet32_private
|
||||
sub eax, OS_BASE
|
||||
and eax, 0xffff
|
||||
call dword [pcnet32_access.write_csr]
|
||||
mov eax, pcnet32_private
|
||||
sub eax, OS_BASE
|
||||
mov ebx, 2
|
||||
shr eax, 16
|
||||
call dword [pcnet32_access.write_csr]
|
||||
mov ebx, 4
|
||||
mov eax, 0x0915
|
||||
call dword [pcnet32_access.write_csr]
|
||||
mov ebx, 0
|
||||
mov eax, 1
|
||||
call dword [pcnet32_access.write_csr]
|
||||
mov ecx, 100
|
||||
.L11:
|
||||
xor ebx, ebx
|
||||
call dword [pcnet32_access.read_csr]
|
||||
test ax, 0x100
|
||||
jnz .L12
|
||||
loop .L11
|
||||
.L12:
|
||||
; DEBUGF 1," K : hardware reset\n"
|
||||
xor ebx, ebx
|
||||
mov eax, 0x0002
|
||||
call dword [pcnet32_access.write_csr]
|
||||
xor ebx, ebx
|
||||
call dword [pcnet32_access.read_csr]
|
||||
; DEBUGF 1," K : PCNET reset complete\n"
|
||||
ret
|
||||
|
||||
|
||||
|
||||
pcnet32_adjust_pci_device:
|
||||
;*******Get current setting************************
|
||||
mov al, 2 ;read a word
|
||||
mov bh, [pci_dev]
|
||||
mov ah, [pci_bus]
|
||||
mov bl, 0x04 ;from command Register
|
||||
call pci_read_reg
|
||||
;******see if its already set as bus master********
|
||||
mov bx, ax
|
||||
and bx, 5
|
||||
cmp bx, 5
|
||||
je pcnet32_adjust_pci_device_Latency
|
||||
;******Make card a bus master*******
|
||||
mov cx, ax ;value to write
|
||||
mov bh, [pci_dev]
|
||||
mov al, 2 ;write a word
|
||||
or cx, 5
|
||||
mov ah, [pci_bus]
|
||||
mov bl, 0x04 ;to command register
|
||||
call pci_write_reg
|
||||
;******Check latency setting***********
|
||||
pcnet32_adjust_pci_device_Latency:
|
||||
;*******Get current latency setting************************
|
||||
; mov al, 1 ;read a byte
|
||||
; mov bh, [pci_dev]
|
||||
; mov ah, [pci_bus]
|
||||
; mov bl, 0x0D ;from Lantency Timer Register
|
||||
; call pci_read_reg
|
||||
;******see if its aat least 64 clocks********
|
||||
; cmp ax,64
|
||||
; jge pcnet32_adjust_pci_device_Done
|
||||
;******Set latency to 32 clocks*******
|
||||
; mov cx, 64 ;value to write
|
||||
; mov bh, [pci_dev]
|
||||
; mov al, 1 ;write a byte
|
||||
; mov ah, [pci_bus]
|
||||
; mov bl, 0x0D ;to Lantency Timer Register
|
||||
; call pci_write_reg
|
||||
;******Check latency setting***********
|
||||
pcnet32_adjust_pci_device_Done:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
pcnet32_probe:
|
||||
mov ebp, [io_addr]
|
||||
call pcnet32_wio_reset
|
||||
xor ebx, ebx
|
||||
call pcnet32_wio_read_csr
|
||||
cmp eax, 4
|
||||
jne .try_dwio
|
||||
call pcnet32_wio_check
|
||||
and al, al
|
||||
jz .try_dwio
|
||||
; DEBUGF 1," K : Using WIO\n"
|
||||
mov esi, pcnet32_wio
|
||||
jmp .L1
|
||||
.try_dwio:
|
||||
call pcnet32_dwio_reset
|
||||
xor ebx, ebx
|
||||
call pcnet32_dwio_read_csr
|
||||
cmp eax, 4
|
||||
jne .no_dev
|
||||
call pcnet32_dwio_check
|
||||
and al, al
|
||||
jz .no_dev
|
||||
; DEBUGF 1," K : Using DWIO\n"
|
||||
mov esi, pcnet32_dwio
|
||||
jmp .L1
|
||||
.no_dev:
|
||||
DEBUGF 1," K : PCNET32 not found\n"
|
||||
ret
|
||||
.L1:
|
||||
mov edi, pcnet32_access
|
||||
mov ecx, 7
|
||||
cld
|
||||
rep movsd
|
||||
mov ebx, 88
|
||||
call dword [pcnet32_access.read_csr]
|
||||
mov ecx, eax
|
||||
mov ebx, 89
|
||||
call dword [pcnet32_access.read_csr]
|
||||
shl eax, 16
|
||||
or eax, ecx
|
||||
mov ecx, eax
|
||||
and ecx, 0xfff
|
||||
cmp ecx, 3
|
||||
jne .no_dev
|
||||
shr eax, 12
|
||||
and eax, 0xffff
|
||||
mov [pcnet32_private.chip_version], eax
|
||||
; DEBUGF 1," K : PCNET32 chip version OK\n"
|
||||
mov [pcnet32_private.fdx], 0
|
||||
mov [pcnet32_private.mii], 0
|
||||
mov [pcnet32_private.fset], 0
|
||||
mov [pcnet32_private.dxsuflo], 0
|
||||
mov [pcnet32_private.ltint], 0
|
||||
mov eax, [pcnet32_private.chip_version]
|
||||
cmp eax, 0x2420
|
||||
je .L2
|
||||
cmp eax, 0x2430
|
||||
je .L3
|
||||
cmp eax, 0x2621
|
||||
je .L4
|
||||
cmp eax, 0x2623
|
||||
je .L5
|
||||
cmp eax, 0x2624
|
||||
je .L6
|
||||
cmp eax, 0x2625
|
||||
je .L7
|
||||
cmp eax, 0x2626
|
||||
je .L8
|
||||
cmp eax, 0x2627
|
||||
je .L9
|
||||
DEBUGF 1," K : Invalid chip rev\n"
|
||||
jmp .no_dev
|
||||
.L2:
|
||||
; DEBUGF 1," K : PCnet/PCI 79C970\n"
|
||||
jmp .L10
|
||||
.L3:
|
||||
; DEBUGF 1," K : PCnet/PCI 79C970\n"
|
||||
jmp .L10
|
||||
.L4:
|
||||
; DEBUGF 1," K : PCnet/PCI II 79C970A\n"
|
||||
mov [pcnet32_private.fdx], 1
|
||||
jmp .L10
|
||||
.L5:
|
||||
; DEBUGF 1," K : PCnet/FAST 79C971\n"
|
||||
mov [pcnet32_private.fdx], 1
|
||||
mov [pcnet32_private.mii], 1
|
||||
mov [pcnet32_private.fset], 1
|
||||
mov [pcnet32_private.ltint], 1
|
||||
jmp .L10
|
||||
.L6:
|
||||
; DEBUGF 1," K : PCnet/FAST+ 79C972\n"
|
||||
mov [pcnet32_private.fdx], 1
|
||||
mov [pcnet32_private.mii], 1
|
||||
mov [pcnet32_private.fset], 1
|
||||
jmp .L10
|
||||
.L7:
|
||||
; DEBUGF 1," K : PCnet/FAST III 79C973\n"
|
||||
mov [pcnet32_private.fdx], 1
|
||||
mov [pcnet32_private.mii], 1
|
||||
jmp .L10
|
||||
.L8:
|
||||
; DEBUGF 1," K : PCnet/Home 79C978\n"
|
||||
mov [pcnet32_private.fdx], 1
|
||||
mov ebx, 49
|
||||
call dword [pcnet32_access.read_bcr]
|
||||
call dword [pcnet32_access.write_bcr]
|
||||
jmp .L10
|
||||
.L9:
|
||||
; DEBUGF 1," K : PCnet/FAST III 79C975\n"
|
||||
mov [pcnet32_private.fdx], 1
|
||||
mov [pcnet32_private.mii], 1
|
||||
.L10:
|
||||
cmp [pcnet32_private.fset], 1
|
||||
jne .L11
|
||||
mov ebx, 18
|
||||
call dword [pcnet32_access.read_bcr]
|
||||
or eax, 0x800
|
||||
call dword [pcnet32_access.write_bcr]
|
||||
mov ebx, 80
|
||||
call dword [pcnet32_access.read_csr]
|
||||
and eax, 0xc00
|
||||
or eax, 0xc00
|
||||
call dword [pcnet32_access.write_csr]
|
||||
mov [pcnet32_private.dxsuflo], 1
|
||||
mov [pcnet32_private.ltint], 1
|
||||
.L11:
|
||||
; read MAC
|
||||
mov edi, node_addr
|
||||
mov edx, ebp
|
||||
mov ecx, 6
|
||||
.Lmac:
|
||||
in al, dx
|
||||
stosb
|
||||
inc edx
|
||||
loop .Lmac
|
||||
; DEBUGF 1," K : MAC read\n"
|
||||
call pcnet32_adjust_pci_device
|
||||
; DEBUGF 1," K : PCI done\n"
|
||||
mov eax, PCNET32_PORT_ASEL
|
||||
mov [pcnet32_private.options], eax
|
||||
mov [pcnet32_private.mode], word 0x0003
|
||||
mov [pcnet32_private.tlen_rlen], word (PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS)
|
||||
mov esi, node_addr
|
||||
mov edi, pcnet32_private.phys_addr
|
||||
cld
|
||||
movsd
|
||||
movsw
|
||||
mov [pcnet32_private.filter], dword 0
|
||||
mov [pcnet32_private.filter+4], dword 0
|
||||
mov eax, pcnet32_rx_ring
|
||||
sub eax, OS_BASE
|
||||
mov dword [pcnet32_private.rx_ring], eax
|
||||
|
||||
mov eax, pcnet32_tx_ring
|
||||
sub eax, OS_BASE
|
||||
mov dword [pcnet32_private.tx_ring], eax
|
||||
; DEBUGF 1," K : Switching to 32\n"
|
||||
mov ebx, 20
|
||||
mov eax, 2
|
||||
call dword [pcnet32_access.write_bcr]
|
||||
mov ebx, 1
|
||||
mov eax, ((pcnet32_private - OS_BASE) and 0xffff)
|
||||
call dword [pcnet32_access.write_csr]
|
||||
mov ebx, 2
|
||||
mov eax, ((pcnet32_private - OS_BASE) shr 16) and 0xffff
|
||||
call dword [pcnet32_access.write_csr]
|
||||
mov ebx, 0
|
||||
mov eax, 1
|
||||
call dword [pcnet32_access.write_csr]
|
||||
mov esi, 1
|
||||
call delay_ms
|
||||
call pcnet32_reset
|
||||
mov eax, [pci_data]
|
||||
mov [eth_status], eax
|
||||
ret
|
||||
|
||||
|
||||
|
||||
pcnet32_poll:
|
||||
xor ax, ax
|
||||
mov [eth_rx_data_len], ax
|
||||
mov eax, [pcnet32_private.cur_rx]
|
||||
and eax, PCNET32_RX_RING_MOD_MASK
|
||||
mov ebx, eax
|
||||
imul esi, eax, PCNET32_PKT_BUF_SZ
|
||||
add esi, pcnet32_rxb
|
||||
shl ebx, 4
|
||||
add ebx, pcnet32_rx_ring
|
||||
mov cx, [ebx+pcnet32_rx_head.status]
|
||||
test cx, 0x8000
|
||||
jnz .L1
|
||||
cmp ch, 3
|
||||
jne .L1
|
||||
mov ecx, [ebx+pcnet32_rx_head.msg_length]
|
||||
and ecx, 0xfff
|
||||
sub ecx, 4
|
||||
mov [eth_rx_data_len], cx
|
||||
; DEBUGF 1," K : PCNETRX: %ub\n",cx
|
||||
push ecx
|
||||
shr ecx, 2
|
||||
mov edi, Ether_buffer
|
||||
cld
|
||||
rep movsd
|
||||
pop ecx
|
||||
and ecx, 3
|
||||
rep movsb
|
||||
mov [ebx+pcnet32_rx_head.buf_length], word PCNET32_PKT_BUF_SZ_NEG
|
||||
or [ebx+pcnet32_rx_head.status], word 0x8000
|
||||
inc [pcnet32_private.cur_rx]
|
||||
.L1:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
; Pointer to 48 bit destination address in edi
|
||||
; Type of packet in bx
|
||||
; size of packet in ecx
|
||||
; pointer to packet data in esi
|
||||
pcnet32_xmit:
|
||||
push edi
|
||||
push esi
|
||||
push ebx
|
||||
push ecx
|
||||
; DEBUGF 1," K : PCNETTX\n"
|
||||
mov esi, edi
|
||||
mov edi, [pcnet32_private.cur_tx]
|
||||
imul edi, PCNET32_PKT_BUF_SZ
|
||||
add edi, pcnet32_txb; edi=ptxb
|
||||
mov eax, edi
|
||||
cld ; copy MAC
|
||||
movsd
|
||||
movsw
|
||||
mov esi, node_addr
|
||||
cld
|
||||
movsd
|
||||
movsw
|
||||
mov [edi], bx
|
||||
add edi, 2
|
||||
mov esi, [esp+8]
|
||||
mov ecx, [esp]
|
||||
push ecx
|
||||
shr ecx, 2
|
||||
cld
|
||||
rep movsd
|
||||
pop ecx
|
||||
and ecx, 3
|
||||
rep movsb
|
||||
; mov ecx,[esp]
|
||||
; add ecx,14 ; ETH_HLEN
|
||||
; xor eax,eax
|
||||
; pad to min length (60=ETH_ZLEN)
|
||||
; cmp ecx,60
|
||||
; jae .L1
|
||||
; sub ecx,60
|
||||
; cld
|
||||
; rep stosb
|
||||
;.L1:
|
||||
mov edi, pcnet32_tx_ring+0; entry=0
|
||||
mov ecx, [esp]
|
||||
add ecx, 14
|
||||
cmp cx, 60
|
||||
jae .L1
|
||||
mov cx, 60
|
||||
.L1:
|
||||
neg cx
|
||||
mov [edi+pcnet32_tx_head.length], cx
|
||||
mov [edi+pcnet32_tx_head.misc], dword 0
|
||||
sub eax, OS_BASE
|
||||
mov [edi+pcnet32_tx_head.base], eax
|
||||
mov [edi+pcnet32_tx_head.status], word 0x8300
|
||||
; trigger an immediate send poll
|
||||
mov ebx, 0
|
||||
mov eax, 0x0008; 0x0048
|
||||
mov ebp, [io_addr]
|
||||
call dword [pcnet32_access.write_csr]
|
||||
mov dword [pcnet32_private.cur_tx], 0
|
||||
; wait for TX to complete
|
||||
mov ecx, [timer_ticks];[0xfdf0]
|
||||
add ecx, 100
|
||||
.L2:
|
||||
mov ax, [edi+pcnet32_tx_head.status]
|
||||
test ax, 0x8000
|
||||
jz .L3
|
||||
cmp ecx, [timer_ticks];[0xfdf0]
|
||||
jb .L4
|
||||
mov esi, 10
|
||||
call delay_ms
|
||||
jnz .L2
|
||||
.L4:
|
||||
DEBUGF 1," K : PCNET: Send timeout\n"
|
||||
.L3:
|
||||
mov dword [edi+pcnet32_tx_head.base], 0
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop esi
|
||||
pop edi
|
||||
ret
|
@ -1,813 +0,0 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; R6040 driver for KolibriOS ;;
|
||||
;; ;;
|
||||
;; based on R6040.c from linux ;;
|
||||
;; ;;
|
||||
;; Written by Asper (asper.85@mail.ru) ;;
|
||||
;; and hidnplayr (hidnplayr@gmail.com) ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
|
||||
;********************************************************************
|
||||
; Interface
|
||||
; r6040_reset
|
||||
; r6040_probe
|
||||
; r6040_poll
|
||||
; r6040_transmit
|
||||
;
|
||||
; These functions are referenced in ethernet.inc
|
||||
;
|
||||
;********************************************************************
|
||||
|
||||
;; A few user-configurable values.
|
||||
|
||||
TX_RING_SIZE equ 4
|
||||
RX_RING_SIZE equ 4
|
||||
|
||||
; ethernet address length
|
||||
ETH_ALEN equ 6
|
||||
ETH_HLEN equ (2 * ETH_ALEN + 2)
|
||||
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for
|
||||
; mininmum 64bytes frame length
|
||||
; system timer frequency
|
||||
HZ equ 1000
|
||||
|
||||
; max time out delay time
|
||||
W_MAX_TIMEOUT equ 0x0FFF
|
||||
|
||||
;; Size of the in-memory receive ring.
|
||||
RX_BUF_LEN_IDX equ 3 ;; 0==8K, 1==16K, 2==32K, 3==64K
|
||||
RX_BUF_LEN equ (8192 << RX_BUF_LEN_IDX)
|
||||
|
||||
;-; Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4).
|
||||
;-TX_BUF_SIZE equ 1536
|
||||
;-RX_BUF_SIZE equ 1536
|
||||
|
||||
;; PCI Tuning Parameters
|
||||
; Threshold is bytes transferred to chip before transmission starts.
|
||||
TX_FIFO_THRESH equ 256 ;; In bytes, rounded down to 32 byte units.
|
||||
|
||||
;; The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024.
|
||||
RX_FIFO_THRESH equ 4 ;; Rx buffer level before first PCI xfer.
|
||||
RX_DMA_BURST equ 4 ;; Maximum PCI burst, '4' is 256 bytes
|
||||
TX_DMA_BURST equ 4
|
||||
|
||||
;; Operational parameters that usually are not changed.
|
||||
PHY1_ADDR equ 1 ;For MAC1
|
||||
PHY2_ADDR equ 3 ;For MAC2
|
||||
PHY_MODE equ 0x3100 ;PHY CHIP Register 0
|
||||
PHY_CAP equ 0x01E1 ;PHY CHIP Register 4
|
||||
|
||||
;; Time in jiffies before concluding the transmitter is hung.
|
||||
TX_TIMEOUT equ ((6000*HZ)/1000)
|
||||
|
||||
R6040_IO_SIZE equ 256 ; RDC MAC I/O Size
|
||||
MAX_MAC equ 2 ; MAX RDC MAC
|
||||
|
||||
;**************************************************************************
|
||||
; RDC R6040 Register Definitions
|
||||
;**************************************************************************
|
||||
MCR0 equ 0x00 ;Control register 0
|
||||
MCR1 equ 0x01 ;Control register 1
|
||||
MAC_RST equ 0x0001 ;Reset the MAC
|
||||
MBCR equ 0x08 ;Bus control
|
||||
MT_ICR equ 0x0C ;TX interrupt control
|
||||
MR_ICR equ 0x10 ;RX interrupt control
|
||||
MTPR equ 0x14 ;TX poll command register
|
||||
MR_BSR equ 0x18 ;RX buffer size
|
||||
MR_DCR equ 0x1A ;RX descriptor control
|
||||
MLSR equ 0x1C ;Last status
|
||||
MMDIO equ 0x20 ;MDIO control register
|
||||
MDIO_WRITE equ 0x4000 ;MDIO write
|
||||
MDIO_READ equ 0x2000 ;MDIO read
|
||||
MMRD equ 0x24 ;MDIO read data register
|
||||
MMWD equ 0x28 ;MDIO write data register
|
||||
MTD_SA0 equ 0x2C ;TX descriptor start address 0
|
||||
MTD_SA1 equ 0x30 ;TX descriptor start address 1
|
||||
MRD_SA0 equ 0x34 ;RX descriptor start address 0
|
||||
MRD_SA1 equ 0x38 ;RX descriptor start address 1
|
||||
MISR equ 0x3C ;Status register
|
||||
MIER equ 0x40 ;INT enable register
|
||||
MSK_INT equ 0x0000 ;Mask off interrupts
|
||||
RX_FINISH equ 0x0001 ;RX finished
|
||||
RX_NO_DESC equ 0x0002 ;No RX descriptor available
|
||||
RX_FIFO_FULL equ 0x0004 ;RX FIFO full
|
||||
RX_EARLY equ 0x0008 ;RX early
|
||||
TX_FINISH equ 0x0010 ;TX finished
|
||||
TX_EARLY equ 0x0080 ;TX early
|
||||
EVENT_OVRFL equ 0x0100 ;Event counter overflow
|
||||
LINK_CHANGED equ 0x0200 ;PHY link changed
|
||||
ME_CISR equ 0x44 ;Event counter INT status
|
||||
ME_CIER equ 0x48 ;Event counter INT enable
|
||||
MR_CNT equ 0x50 ;Successfully received packet counter
|
||||
ME_CNT0 equ 0x52 ;Event counter 0
|
||||
ME_CNT1 equ 0x54 ;Event counter 1
|
||||
ME_CNT2 equ 0x56 ;Event counter 2
|
||||
ME_CNT3 equ 0x58 ;Event counter 3
|
||||
MT_CNT equ 0x5A ;Successfully transmit packet counter
|
||||
ME_CNT4 equ 0x5C ;Event counter 4
|
||||
MP_CNT equ 0x5E ;Pause frame counter register
|
||||
MAR0 equ 0x60 ;Hash table 0
|
||||
MAR1 equ 0x62 ;Hash table 1
|
||||
MAR2 equ 0x64 ;Hash table 2
|
||||
MAR3 equ 0x66 ;Hash table 3
|
||||
MID_0L equ 0x68 ;Multicast address MID0 Low
|
||||
MID_0M equ 0x6A ;Multicast address MID0 Medium
|
||||
MID_0H equ 0x6C ;Multicast address MID0 High
|
||||
MID_1L equ 0x70 ;MID1 Low
|
||||
MID_1M equ 0x72 ;MID1 Medium
|
||||
MID_1H equ 0x74 ;MID1 High
|
||||
MID_2L equ 0x78 ;MID2 Low
|
||||
MID_2M equ 0x7A ;MID2 Medium
|
||||
MID_2H equ 0x7C ;MID2 High
|
||||
MID_3L equ 0x80 ;MID3 Low
|
||||
MID_3M equ 0x82 ;MID3 Medium
|
||||
MID_3H equ 0x84 ;MID3 High
|
||||
PHY_CC equ 0x88 ;PHY status change configuration register
|
||||
PHY_ST equ 0x8A ;PHY status register
|
||||
MAC_SM equ 0xAC ;MAC status machine
|
||||
MAC_ID equ 0xBE ;Identifier register
|
||||
|
||||
MAX_BUF_SIZE equ 0x600 ;1536
|
||||
|
||||
MBCR_DEFAULT equ 0x012A ;MAC Bus Control Register
|
||||
MCAST_MAX equ 3 ;Max number multicast addresses to filter
|
||||
|
||||
;Descriptor status
|
||||
DSC_OWNER_MAC equ 0x8000 ;MAC is the owner of this descriptor
|
||||
DSC_RX_OK equ 0x4000 ;RX was successfull
|
||||
DSC_RX_ERR equ 0x0800 ;RX PHY error
|
||||
DSC_RX_ERR_DRI equ 0x0400 ;RX dribble packet
|
||||
DSC_RX_ERR_BUF equ 0x0200 ;RX length exceeds buffer size
|
||||
DSC_RX_ERR_LONG equ 0x0100 ;RX length > maximum packet length
|
||||
DSC_RX_ERR_RUNT equ 0x0080 ;RX packet length < 64 byte
|
||||
DSC_RX_ERR_CRC equ 0x0040 ;RX CRC error
|
||||
DSC_RX_BCAST equ 0x0020 ;RX broadcast (no error)
|
||||
DSC_RX_MCAST equ 0x0010 ;RX multicast (no error)
|
||||
DSC_RX_MCH_HIT equ 0x0008 ;RX multicast hit in hash table (no error)
|
||||
DSC_RX_MIDH_HIT equ 0x0004 ;RX MID table hit (no error)
|
||||
DSC_RX_IDX_MID_MASK equ 3 ;RX mask for the index of matched MIDx
|
||||
|
||||
;PHY settings
|
||||
ICPLUS_PHY_ID equ 0x0243
|
||||
|
||||
RX_INTS equ RX_FIFO_FULL or RX_NO_DESC or RX_FINISH
|
||||
TX_INTS equ TX_FINISH
|
||||
INT_MASK equ RX_INTS or TX_INTS
|
||||
|
||||
|
||||
r6040_txb equ (eth_data_start)
|
||||
r6040_rxb equ ((r6040_txb+(MAX_BUF_SIZE*TX_RING_SIZE)+32) and 0xfffffff0)
|
||||
r6040_tx_ring equ ((r6040_rxb+(MAX_BUF_SIZE*RX_RING_SIZE)+32) and 0xfffffff0)
|
||||
r6040_rx_ring equ ((r6040_tx_ring+(r6040_x_head.sizeof*TX_RING_SIZE)+32) and 0xfffffff0)
|
||||
|
||||
virtual at ((r6040_rx_ring+(r6040_x_head.sizeof*RX_RING_SIZE)+32) and 0xfffffff0)
|
||||
r6040_private:
|
||||
.rx_ring dd ?
|
||||
.tx_ring dd ?
|
||||
.cur_rx dw ?
|
||||
.cur_tx dw ?
|
||||
.phy_addr dw ?
|
||||
.phy_mode dw ?
|
||||
.mcr0 dw ?
|
||||
.mcr1 dw ?
|
||||
.switch_sig dw ?
|
||||
end virtual
|
||||
|
||||
virtual at 0
|
||||
r6040_x_head:
|
||||
.status dw ? ;0-1
|
||||
.len dw ? ;2-3
|
||||
.buf dd ? ;4-7
|
||||
.ndesc dd ? ;8-B
|
||||
.rev1 dd ? ;C-F
|
||||
.vbufp dd ? ;10-13
|
||||
.vndescp dd ? ;14-17
|
||||
.skb_ptr dd ? ;18-1B
|
||||
.rev2 dd ? ;1C-1F
|
||||
.sizeof:
|
||||
end virtual
|
||||
|
||||
|
||||
|
||||
; Read a word data from PHY Chip
|
||||
proc r6040_phy_read stdcall, phy_addr:dword, reg:dword
|
||||
push ecx edx
|
||||
mov eax, [phy_addr]
|
||||
shl eax, 8
|
||||
add eax, [reg]
|
||||
add eax, MDIO_READ
|
||||
mov edx, [io_addr]
|
||||
add edx, MMDIO
|
||||
out dx, ax
|
||||
;Wait for the read bit to be cleared.
|
||||
mov ecx, 2048 ;limit
|
||||
xor eax, eax
|
||||
.read:
|
||||
in ax, dx
|
||||
test ax, MDIO_READ
|
||||
jz @f
|
||||
dec ecx
|
||||
test ecx, ecx
|
||||
jnz .read
|
||||
@@:
|
||||
mov edx, [io_addr]
|
||||
add edx, MMRD
|
||||
in ax, dx
|
||||
and eax, 0xFFFF
|
||||
pop edx ecx
|
||||
ret
|
||||
endp
|
||||
|
||||
; Write a word data to PHY Chip
|
||||
proc r6040_phy_write stdcall, phy_addr:dword, reg:dword, val:dword
|
||||
push eax ecx edx
|
||||
mov eax, [val]
|
||||
mov edx, [io_addr]
|
||||
add edx, MMWD
|
||||
out dx, ax
|
||||
;Write the command to the MDIO bus
|
||||
mov eax, [phy_addr]
|
||||
shl eax, 8
|
||||
add eax, [reg]
|
||||
add eax, MDIO_WRITE
|
||||
mov edx, [io_addr]
|
||||
add edx, MMDIO
|
||||
out dx, ax
|
||||
;Wait for the write bit to be cleared.
|
||||
mov ecx, 2048 ;limit
|
||||
xor eax, eax
|
||||
.write:
|
||||
in ax, dx
|
||||
test ax, MDIO_WRITE
|
||||
jz @f
|
||||
dec ecx
|
||||
test ecx, ecx
|
||||
jnz .write
|
||||
@@:
|
||||
pop edx ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
macro r6040_mdio_write reg, val {
|
||||
stdcall r6040_phy_read, [io_addr], [r6040_private.phy_addr], reg
|
||||
}
|
||||
|
||||
macro r6040_mdio_write reg, val {
|
||||
stdcall r6040_phy_write, [io_addr], [r6040_private.phy_addr], reg, val
|
||||
}
|
||||
|
||||
|
||||
proc r6040_init_ring_desc stdcall, desc_ring:dword, size:dword
|
||||
push eax ecx esi
|
||||
mov ecx, [size]
|
||||
test ecx, ecx
|
||||
jz .out
|
||||
|
||||
mov esi, [desc_ring]
|
||||
mov eax, esi
|
||||
.next_desc:
|
||||
add eax, r6040_x_head.sizeof - OS_BASE
|
||||
mov [esi+r6040_x_head.ndesc], eax
|
||||
add eax, OS_BASE
|
||||
mov [esi+r6040_x_head.vndescp], eax
|
||||
mov esi, eax
|
||||
dec ecx
|
||||
jnz .next_desc
|
||||
|
||||
sub esi, r6040_x_head.sizeof
|
||||
mov eax, [desc_ring]
|
||||
mov [esi+r6040_x_head.vndescp], eax
|
||||
sub eax, OS_BASE
|
||||
mov [esi+r6040_x_head.ndesc], eax
|
||||
.out:
|
||||
pop esi ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
|
||||
|
||||
|
||||
r6040_init_rxbufs:
|
||||
|
||||
stdcall r6040_init_ring_desc, r6040_rx_ring, RX_RING_SIZE
|
||||
|
||||
; Allocate skbs for the rx descriptors
|
||||
mov esi, r6040_rx_ring
|
||||
mov ebx, r6040_rxb
|
||||
mov ecx, RX_RING_SIZE
|
||||
mov eax, r6040_rx_ring
|
||||
.next_desc:
|
||||
mov [esi+r6040_x_head.skb_ptr], ebx
|
||||
mov [esi+r6040_x_head.buf], ebx
|
||||
sub [esi+r6040_x_head.buf], OS_BASE
|
||||
mov [esi+r6040_x_head.status], DSC_OWNER_MAC
|
||||
|
||||
mov eax, [esi+r6040_x_head.vndescp]
|
||||
mov esi, eax
|
||||
|
||||
add ebx, MAX_BUF_SIZE
|
||||
dec ecx
|
||||
jnz .next_desc
|
||||
|
||||
xor eax, eax
|
||||
.out:
|
||||
|
||||
ret
|
||||
|
||||
|
||||
r6040_probe:
|
||||
|
||||
DEBUGF 1, "Probing r6040\n"
|
||||
|
||||
call adjust_pci_device
|
||||
|
||||
|
||||
; If PHY status change register is still set to zero
|
||||
; it means the bootloader didn't initialize it
|
||||
mov edx, [io_addr]
|
||||
add edx, PHY_CC
|
||||
in ax, dx
|
||||
test ax, ax
|
||||
jnz @f
|
||||
mov eax, 0x9F07
|
||||
out dx, ax
|
||||
@@:
|
||||
; Set MAC address
|
||||
mov ecx, 3
|
||||
mov edi, node_addr
|
||||
mov edx, [io_addr]
|
||||
add edx, MID_0L
|
||||
.mac:
|
||||
in ax, dx
|
||||
stosw
|
||||
add edx, 2
|
||||
dec ecx
|
||||
jnz .mac
|
||||
; Some bootloaders/BIOSes do not initialize
|
||||
; MAC address, warn about that
|
||||
and eax, 0xFF
|
||||
or eax, [node_addr]
|
||||
test eax, eax
|
||||
jnz @f
|
||||
DEBUGF 1, "K : MAC address not initialized\n" ;, generating random"
|
||||
;Asper: Add here generate function call!
|
||||
; Temporary workaround: init by constant adress
|
||||
mov dword [node_addr], 0x00006000
|
||||
mov word [node_addr+4], 0x0001
|
||||
@@:
|
||||
; Init RDC private data
|
||||
mov [r6040_private.mcr0], 0x1002
|
||||
;mov [r6040_private.phy_addr], 1 ; Asper: Only one network card is supported now.
|
||||
mov [r6040_private.switch_sig], 0
|
||||
|
||||
; Check the vendor ID on the PHY, if 0xFFFF assume none attached
|
||||
stdcall r6040_phy_read, 1, 2
|
||||
cmp ax, 0xFFFF
|
||||
jne @f
|
||||
DEBUGF 1, "K : Failed to detect an attached PHY\n" ;, generating random"
|
||||
mov eax, -1
|
||||
ret
|
||||
@@:
|
||||
|
||||
; Set MAC address
|
||||
call r6040_mac_address
|
||||
|
||||
|
||||
; Initialize and alloc RX/TX buffers
|
||||
stdcall r6040_init_ring_desc, r6040_tx_ring, TX_RING_SIZE
|
||||
call r6040_init_rxbufs ;r6040_alloc_rxbufs
|
||||
test eax, eax
|
||||
jnz .out
|
||||
|
||||
; Read the PHY ID
|
||||
mov [r6040_private.phy_mode], 0x8000
|
||||
stdcall r6040_phy_read, 0, 2
|
||||
mov [r6040_private.switch_sig], ax
|
||||
cmp ax, ICPLUS_PHY_ID
|
||||
jne @f
|
||||
stdcall r6040_phy_write, 29, 31, 0x175C ; Enable registers
|
||||
jmp .phy_readen
|
||||
@@:
|
||||
|
||||
; PHY Mode Check
|
||||
movzx eax, [r6040_private.phy_addr]
|
||||
stdcall r6040_phy_write, eax, 4, PHY_CAP
|
||||
stdcall r6040_phy_write, eax, 0, PHY_MODE
|
||||
; if PHY_MODE = 0x3100
|
||||
call r6040_phy_mode_chk
|
||||
mov [r6040_private.phy_mode], ax
|
||||
jmp .phy_readen
|
||||
; end if
|
||||
; if not (PHY_MODE and 0x0100)
|
||||
mov [r6040_private.phy_mode], 0
|
||||
; end if
|
||||
.phy_readen:
|
||||
|
||||
; Set duplex mode
|
||||
mov ax, [r6040_private.phy_mode]
|
||||
or [r6040_private.mcr0], ax
|
||||
|
||||
; improve performance (by RDC guys)
|
||||
stdcall r6040_phy_read, 30, 17
|
||||
or ax, 0x4000
|
||||
stdcall r6040_phy_write, 30, 17, eax
|
||||
|
||||
stdcall r6040_phy_read, 30, 17
|
||||
xor ax, -1
|
||||
or ax, 0x2000
|
||||
xor ax, -1
|
||||
stdcall r6040_phy_write, 30, 17, eax
|
||||
|
||||
stdcall r6040_phy_write, 0, 19, 0x0000
|
||||
stdcall r6040_phy_write, 0, 30, 0x01F0
|
||||
|
||||
; Initialize all Mac registers
|
||||
call r6040_reset
|
||||
|
||||
xor eax, eax
|
||||
.out:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
align 4
|
||||
r6040_reset:
|
||||
|
||||
DEBUGF 1, "Resetting r6040\n"
|
||||
|
||||
push eax ecx edx
|
||||
; Mask off Interrupt
|
||||
mov eax, MSK_INT
|
||||
mov edx, [io_addr]
|
||||
add edx, MIER
|
||||
out dx, ax
|
||||
|
||||
;Reset RDC MAC
|
||||
mov eax, MAC_RST
|
||||
mov edx, [io_addr]
|
||||
add edx, MCR1
|
||||
out dx, ax
|
||||
|
||||
mov ecx, 2048 ;limit
|
||||
.read:
|
||||
in ax, dx
|
||||
test ax, 0x1
|
||||
jnz @f
|
||||
dec ecx
|
||||
test ecx, ecx
|
||||
jnz .read
|
||||
@@:
|
||||
;Reset internal state machine
|
||||
mov ax, 2
|
||||
mov edx, [io_addr]
|
||||
add edx, MAC_SM
|
||||
out dx, ax
|
||||
xor ax, ax
|
||||
out dx, ax
|
||||
mov esi, 5
|
||||
call delay_ms
|
||||
|
||||
;MAC Bus Control Register
|
||||
mov ax, MBCR_DEFAULT
|
||||
mov edx, [io_addr]
|
||||
add edx, MBCR
|
||||
out dx, ax
|
||||
|
||||
;Buffer Size Register
|
||||
mov ax, MAX_BUF_SIZE
|
||||
mov edx, [io_addr]
|
||||
add edx, MR_BSR
|
||||
out dx, ax
|
||||
|
||||
;Write TX ring start address
|
||||
mov eax, r6040_tx_ring - OS_BASE ;Asper: Maybe we can just write dword? Hidnplayr: better use word, as described in datasheet.
|
||||
mov edx, [io_addr]
|
||||
add edx, MTD_SA0
|
||||
out dx, ax
|
||||
shr eax, 16
|
||||
add edx, MTD_SA1 - MTD_SA0
|
||||
out dx, ax
|
||||
|
||||
;Write RX ring start address
|
||||
mov eax, r6040_rx_ring - OS_BASE ;Asper: Maybe we can just write dword?
|
||||
mov edx, [io_addr]
|
||||
add edx, MRD_SA0
|
||||
out dx, ax
|
||||
shr eax, 16
|
||||
add edx, MRD_SA1 - MRD_SA0
|
||||
out dx, ax
|
||||
|
||||
;Set interrupt waiting time and packet numbers
|
||||
xor ax, ax
|
||||
mov edx, [io_addr]
|
||||
add edx, MT_ICR
|
||||
out dx, ax
|
||||
|
||||
;Asper: ~ Disable ints ;Enable interrupts
|
||||
;mov ax, MSK_INT ;INT_MASK ;Asper ~
|
||||
;mov edx, [io_addr]
|
||||
;add edx, MIER
|
||||
;out dx, ax
|
||||
|
||||
;Enable TX and RX
|
||||
mov ax, [r6040_private.mcr0]
|
||||
or ax, 0x0002
|
||||
mov edx, [io_addr]
|
||||
out dx, ax
|
||||
|
||||
;Let TX poll the descriptors
|
||||
;we may got called by r6040_tx_timeout which has left
|
||||
;some unset tx buffers
|
||||
xor ax, ax
|
||||
inc ax
|
||||
mov edx, [io_addr]
|
||||
add edx, MTPR
|
||||
out dx, ax
|
||||
|
||||
pop edx ecx eax
|
||||
|
||||
DEBUGF 1, "reset ok!\n"
|
||||
|
||||
; Indicate that we have successfully reset the card
|
||||
mov eax, [pci_data]
|
||||
mov [eth_status], eax
|
||||
ret
|
||||
|
||||
|
||||
|
||||
proc r6040_tx_timeout
|
||||
push eax edx
|
||||
;...
|
||||
inc [stats.tx_errors]
|
||||
;Reset MAC and re-init all registers
|
||||
call r6040_init_mac_regs
|
||||
pop edx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
proc r6040_get_stats
|
||||
push eax edx
|
||||
mov edx, [io_addr]
|
||||
add edx, ME_CNT1
|
||||
in al, dx
|
||||
add [stats.rx_crc_errors], al
|
||||
mov edx, [io_addr]
|
||||
add edx, ME_CNT0
|
||||
in al, dx
|
||||
add [stats.multicast], al
|
||||
pop edx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
;...
|
||||
|
||||
proc r6040_phy_mode_chk
|
||||
push ebx
|
||||
;PHY Link Status Check
|
||||
movzx eax, [r6040_private.phy_addr]
|
||||
stdcall r6040_phy_read, eax, 1
|
||||
test eax, 0x4
|
||||
jnz @f
|
||||
mov eax, 0x8000 ;Link Failed, full duplex
|
||||
@@:
|
||||
;PHY Chip Auto-Negotiation Status
|
||||
movzx eax, [r6040_private.phy_addr]
|
||||
stdcall r6040_phy_read, eax, 1
|
||||
test eax, 0x0020
|
||||
jz .force_mode
|
||||
;Auto Negotuiation Mode
|
||||
movzx eax, [r6040_private.phy_addr]
|
||||
stdcall r6040_phy_read, eax, 5
|
||||
mov ebx, eax
|
||||
movzx eax, [r6040_private.phy_addr]
|
||||
stdcall r6040_phy_read, eax, 4
|
||||
and eax, ebx
|
||||
test eax, 0x140
|
||||
jz .ret_0
|
||||
jmp .ret_0x8000
|
||||
.force_mode:
|
||||
;Force Mode
|
||||
movzx eax, [r6040_private.phy_addr]
|
||||
stdcall r6040_phy_read, eax, 0
|
||||
test eax, 0x100
|
||||
jz .ret_0
|
||||
.ret_0x8000:
|
||||
mov eax, 0x8000
|
||||
pop ebx
|
||||
ret
|
||||
.ret_0:
|
||||
xor eax, eax
|
||||
pop ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; r6040_rx
|
||||
; Description
|
||||
; polls card to see if there is a packet waiting
|
||||
;
|
||||
; Currently only supports one descriptor per packet, if packet is fragmented
|
||||
; between multiple descriptors you will lose part of the packet
|
||||
;***************************************************************************
|
||||
r6040_poll:
|
||||
push ebx ecx esi edi
|
||||
|
||||
xor eax, eax
|
||||
mov [eth_rx_data_len], ax
|
||||
|
||||
movzx eax, [r6040_private.cur_rx]
|
||||
mov ebx, eax
|
||||
shl ebx, 5
|
||||
|
||||
mov cx, [ebx+r6040_rx_ring+r6040_x_head.status] ; Read the descriptor status
|
||||
test cx, DSC_OWNER_MAC
|
||||
jnz .out
|
||||
|
||||
test cx, DSC_RX_ERR ; Global error status set
|
||||
jz .no_dsc_rx_err
|
||||
;...
|
||||
jmp .out
|
||||
|
||||
.no_dsc_rx_err:
|
||||
; Packet successfully received
|
||||
movzx ecx, [ebx+r6040_rx_ring+r6040_x_head.len]
|
||||
and ecx, 0xFFF
|
||||
sub ecx, 4 ; Do not count the CRC
|
||||
mov [eth_rx_data_len], cx
|
||||
mov esi, [ebx+r6040_rx_ring+r6040_x_head.skb_ptr]
|
||||
|
||||
push ecx
|
||||
shr ecx, 2
|
||||
mov edi, Ether_buffer
|
||||
cld
|
||||
rep movsd
|
||||
pop ecx
|
||||
and ecx, 3
|
||||
rep movsb
|
||||
|
||||
or [ebx+r6040_rx_ring+r6040_x_head.status], DSC_OWNER_MAC
|
||||
|
||||
inc [r6040_private.cur_rx]
|
||||
and [r6040_private.cur_rx], RX_RING_SIZE-1
|
||||
|
||||
xor eax, eax
|
||||
.out:
|
||||
pop edi esi ecx ebx
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; r6040_transmit
|
||||
; Description
|
||||
; Transmits a packet of data via the ethernet card
|
||||
; Pointer to 48 bit destination address in edi
|
||||
; Type of packet in bx
|
||||
; size of packet in ecx
|
||||
; pointer to packet data in esi
|
||||
;
|
||||
;***************************************************************************
|
||||
r6040_transmit:
|
||||
cmp ecx, MAX_BUF_SIZE
|
||||
jg .out ; packet is too long
|
||||
|
||||
push edi esi ebx ecx
|
||||
|
||||
movzx eax, [r6040_private.cur_tx]
|
||||
shl eax, 5
|
||||
|
||||
; DEBUGF 1,"R6040: TX buffer status: 0x%x, eax=%u\n", [eax + r6040_tx_ring + r6040_x_head.status]:4, eax
|
||||
|
||||
test [r6040_tx_ring + eax + r6040_x_head.status], 0x8000 ; check if buffer is available
|
||||
jz .l3
|
||||
|
||||
push ecx esi
|
||||
mov ecx, [timer_ticks]
|
||||
add ecx, 100
|
||||
.l2:
|
||||
test [r6040_tx_ring + eax + r6040_x_head.status], 0x8000
|
||||
jz .l5
|
||||
cmp ecx, [timer_ticks]
|
||||
jb .l4
|
||||
mov esi, 10
|
||||
call delay_ms
|
||||
jmp .l2
|
||||
|
||||
.l4:
|
||||
pop esi ecx
|
||||
DEBUGF 1,"R6040: Send timeout\n"
|
||||
jmp .out
|
||||
|
||||
.l5:
|
||||
pop esi ecx
|
||||
.l3:
|
||||
push eax
|
||||
|
||||
mov esi, edi
|
||||
|
||||
; point to the current tx buffer
|
||||
movzx edi, [r6040_private.cur_tx]
|
||||
imul edi, MAX_BUF_SIZE
|
||||
add edi, r6040_txb
|
||||
lea eax, [edi - OS_BASE] ; real buffer address in eax
|
||||
|
||||
; copy destination address
|
||||
movsd
|
||||
movsw
|
||||
; copy source address
|
||||
mov esi, node_addr
|
||||
movsd
|
||||
movsw
|
||||
; copy packet type
|
||||
mov [edi], bx
|
||||
add edi, 2
|
||||
|
||||
mov esi, [esp+8+4]
|
||||
mov ecx, [esp+4]
|
||||
; copy the packet data
|
||||
push ecx
|
||||
shr ecx, 2
|
||||
rep movsd
|
||||
pop ecx
|
||||
and ecx, 3
|
||||
rep movsb
|
||||
|
||||
pop edi
|
||||
|
||||
mov ecx, [esp]
|
||||
add ecx, ETH_HLEN
|
||||
cmp cx, ETH_ZLEN
|
||||
jae @f
|
||||
mov cx, ETH_ZLEN
|
||||
@@:
|
||||
|
||||
mov [r6040_tx_ring + edi + r6040_x_head.len], cx
|
||||
mov [r6040_tx_ring + edi + r6040_x_head.buf], eax
|
||||
mov [r6040_tx_ring + edi + r6040_x_head.status], 0x8000
|
||||
|
||||
; Trigger the MAC to check the TX descriptor
|
||||
mov ax, 0x01
|
||||
mov edx, [io_addr]
|
||||
add edx, MTPR
|
||||
out dx, ax
|
||||
|
||||
inc [r6040_private.cur_tx]
|
||||
and [r6040_private.cur_tx], TX_RING_SIZE-1
|
||||
xor eax, eax
|
||||
|
||||
pop ecx ebx esi edi
|
||||
.out:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
r6040_mac_address:
|
||||
push eax ecx edx esi edi
|
||||
; MAC operation register
|
||||
mov ax, 1
|
||||
mov edx, [io_addr]
|
||||
add edx, MCR1
|
||||
out dx, ax
|
||||
; Reset MAC
|
||||
mov ax, 2
|
||||
mov edx, [io_addr]
|
||||
add edx, MAC_SM
|
||||
out dx, ax
|
||||
; Reset internal state machine
|
||||
xor ax, ax
|
||||
out dx, ax
|
||||
mov esi, 5
|
||||
call delay_ms
|
||||
|
||||
; Restore MAC Address
|
||||
mov ecx, 3
|
||||
mov edi, node_addr
|
||||
mov edx, [io_addr]
|
||||
add edx, MID_0L
|
||||
.mac:
|
||||
in ax, dx
|
||||
stosw
|
||||
add edx, 2
|
||||
dec ecx
|
||||
jnz .mac
|
||||
|
||||
pop edi esi edx ecx eax
|
||||
ret
|
||||
|
@ -1,976 +0,0 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; RTL8029.INC ;;
|
||||
;; ;;
|
||||
;; Ethernet driver for Menuet OS ;;
|
||||
;; ;;
|
||||
;; Version 0.2 31 July 2002 ;;
|
||||
;; ;;
|
||||
;; This driver is based on the ns8390 driver from ;;
|
||||
;; the etherboot 5.0.6 project. The copyright statement is ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;; remaining parts Copyright 2002 Mike Hibbett, ;;
|
||||
;; mikeh@oceanfree.net ;;
|
||||
;; ;;
|
||||
;; See file COPYING for details ;;
|
||||
;; ;;
|
||||
;; While this implementation handles only PCI bus RTL8029 ;;
|
||||
;; hardware, it can be easily adapted to other NE2000 clone ;;
|
||||
;; products. I just dont have any to try! ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
$Revision$
|
||||
|
||||
|
||||
;********************************************************************
|
||||
; Interface
|
||||
; rtl8029_reset
|
||||
; rtl8029_probe
|
||||
; rtl8029_poll
|
||||
; rtl8029_transmit
|
||||
;
|
||||
;********************************************************************
|
||||
|
||||
|
||||
|
||||
|
||||
;**************************************************************************
|
||||
; 8390 Register Definitions
|
||||
;**************************************************************************
|
||||
D8390_P0_COMMAND equ 0x00
|
||||
D8390_P0_PSTART equ 0x01
|
||||
D8390_P0_PSTOP equ 0x02
|
||||
D8390_P0_BOUND equ 0x03
|
||||
D8390_P0_TSR equ 0x04
|
||||
D8390_P0_TPSR equ 0x04
|
||||
D8390_P0_TBCR0 equ 0x05
|
||||
D8390_P0_TBCR1 equ 0x06
|
||||
D8390_P0_ISR equ 0x07
|
||||
D8390_P0_RSAR0 equ 0x08
|
||||
D8390_P0_RSAR1 equ 0x09
|
||||
D8390_P0_RBCR0 equ 0x0A
|
||||
D8390_P0_RBCR1 equ 0x0B
|
||||
D8390_P0_RSR equ 0x0C
|
||||
D8390_P0_RCR equ 0x0C
|
||||
D8390_P0_TCR equ 0x0D
|
||||
D8390_P0_DCR equ 0x0E
|
||||
D8390_P0_IMR equ 0x0F
|
||||
D8390_P1_COMMAND equ 0x00
|
||||
D8390_P1_PAR0 equ 0x01
|
||||
D8390_P1_PAR1 equ 0x02
|
||||
D8390_P1_PAR2 equ 0x03
|
||||
D8390_P1_PAR3 equ 0x04
|
||||
D8390_P1_PAR4 equ 0x05
|
||||
D8390_P1_PAR5 equ 0x06
|
||||
D8390_P1_CURR equ 0x07
|
||||
D8390_P1_MAR0 equ 0x08
|
||||
|
||||
D8390_COMMAND_PS0 equ 0x0 ; Page 0 select
|
||||
D8390_COMMAND_PS1 equ 0x40 ; Page 1 select
|
||||
D8390_COMMAND_PS2 equ 0x80 ; Page 2 select
|
||||
D8390_COMMAND_RD2 equ 0x20 ; Remote DMA control
|
||||
D8390_COMMAND_RD1 equ 0x10
|
||||
D8390_COMMAND_RD0 equ 0x08
|
||||
D8390_COMMAND_TXP equ 0x04 ; transmit packet
|
||||
D8390_COMMAND_STA equ 0x02 ; start
|
||||
D8390_COMMAND_STP equ 0x01 ; stop
|
||||
|
||||
D8390_COMMAND_RD2_STA equ 0x22
|
||||
D8390_COMMAND_RD2_STP equ 0x21
|
||||
D8390_COMMAND_RD1_STA equ 0x12
|
||||
D8390_COMMAND_RD0_STA equ 0x0A
|
||||
D8390_COMMAND_PS0_RD2_STP equ 0x21
|
||||
D8390_COMMAND_PS1_RD2_STP equ 0x61
|
||||
D8390_COMMAND_PS0_RD2_STA equ 0x22
|
||||
D8390_COMMAND_PS0_TXP_RD2_STA equ 0x26
|
||||
|
||||
D8390_RCR_MON equ 0x20 ; monitor mode
|
||||
|
||||
D8390_DCR_FT1 equ 0x40
|
||||
D8390_DCR_LS equ 0x08 ; Loopback select
|
||||
D8390_DCR_WTS equ 0x01 ; Word transfer select
|
||||
|
||||
D8390_DCR_FT1_LS equ 0x48
|
||||
D8390_DCR_WTS_FT1_LS equ 0x49
|
||||
|
||||
D8390_ISR_PRX equ 0x01 ; successful recv
|
||||
D8390_ISR_PTX equ 0x02 ; successful xmit
|
||||
D8390_ISR_RXE equ 0x04 ; receive error
|
||||
D8390_ISR_TXE equ 0x08 ; transmit error
|
||||
D8390_ISR_OVW equ 0x10 ; Overflow
|
||||
D8390_ISR_CNT equ 0x20 ; Counter overflow
|
||||
D8390_ISR_RDC equ 0x40 ; Remote DMA complete
|
||||
D8390_ISR_RST equ 0x80 ; reset
|
||||
|
||||
D8390_RSTAT_PRX equ 0x01 ; successful recv
|
||||
D8390_RSTAT_CRC equ 0x02 ; CRC error
|
||||
D8390_RSTAT_FAE equ 0x04 ; Frame alignment error
|
||||
D8390_RSTAT_OVER equ 0x08 ; FIFO overrun
|
||||
|
||||
D8390_TXBUF_SIZE equ 6
|
||||
D8390_RXBUF_END equ 32
|
||||
D8390_PAGE_SIZE equ 256
|
||||
|
||||
ETH_ALEN equ 6
|
||||
ETH_HLEN equ 14
|
||||
ETH_ZLEN equ 60
|
||||
ETH_FRAME_LEN equ 1514
|
||||
|
||||
FLAG_PIO equ 0x01
|
||||
FLAG_16BIT equ 0x02
|
||||
ASIC_PIO equ 0
|
||||
|
||||
VENDOR_NONE equ 0
|
||||
VENDOR_WD equ 1
|
||||
VENDOR_NOVELL equ 2
|
||||
VENDOR_3COM equ 3
|
||||
|
||||
NE_ASIC_OFFSET equ 0x10
|
||||
NE_RESET equ 0x0F ; Used to reset card
|
||||
NE_DATA equ 0x00 ; Used to read/write NIC mem
|
||||
|
||||
MEM_8192 equ 32
|
||||
MEM_16384 equ 64
|
||||
MEM_32768 equ 128
|
||||
|
||||
ISA_MAX_ADDR equ 0x400
|
||||
|
||||
uglobal
|
||||
eth_flags:
|
||||
db 0
|
||||
eth_vendor:
|
||||
db 0
|
||||
eth_nic_base:
|
||||
dw 0
|
||||
eth_asic_base:
|
||||
dw 0
|
||||
eth_memsize:
|
||||
db 0
|
||||
eth_rx_start:
|
||||
db 0
|
||||
eth_tx_start:
|
||||
db 0
|
||||
eth_bmem:
|
||||
dd 0
|
||||
eth_rmem:
|
||||
dd 0
|
||||
romdata:
|
||||
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
endg
|
||||
|
||||
iglobal
|
||||
test_data:
|
||||
db 'NE*000 memory',0
|
||||
test_buffer:
|
||||
db ' ',0
|
||||
endg
|
||||
|
||||
uglobal
|
||||
eth_type:
|
||||
dw 0
|
||||
pkthdr:
|
||||
db 0,0,0,0 ; status, next, (short) len
|
||||
pktoff:
|
||||
dw 0
|
||||
eth_rx_data_ptr:
|
||||
dd 0
|
||||
eth_tmp_len:
|
||||
dw 0
|
||||
endg
|
||||
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; eth_pio_read
|
||||
;
|
||||
; Description
|
||||
; Read a frame from the ethernet card via Programmed I/O
|
||||
; src in ebx
|
||||
; cnt in ecx
|
||||
; dst in edi
|
||||
;***************************************************************************
|
||||
eth_pio_read:
|
||||
mov al, [eth_flags]
|
||||
and al, FLAG_16BIT
|
||||
cmp al, 0
|
||||
je epr_001
|
||||
|
||||
inc ecx
|
||||
and ecx, 0xFFFFFFFE
|
||||
|
||||
epr_001:
|
||||
mov al, D8390_COMMAND_RD2_STA
|
||||
mov dx, [eth_nic_base]
|
||||
add dx, D8390_P0_COMMAND
|
||||
out dx, al
|
||||
|
||||
mov al, cl
|
||||
mov dx, [eth_nic_base]
|
||||
add dx, D8390_P0_RBCR0
|
||||
out dx, al
|
||||
|
||||
mov al, ch
|
||||
mov dx, [eth_nic_base]
|
||||
add dx, D8390_P0_RBCR1
|
||||
out dx, al
|
||||
|
||||
mov al, bl
|
||||
mov dx, [eth_nic_base]
|
||||
add dx, D8390_P0_RSAR0
|
||||
out dx, al
|
||||
|
||||
mov al, bh
|
||||
mov dx, [eth_nic_base]
|
||||
add dx, D8390_P0_RSAR1
|
||||
out dx, al
|
||||
|
||||
mov al, D8390_COMMAND_RD0_STA
|
||||
mov dx, [eth_nic_base]
|
||||
add dx, D8390_P0_COMMAND
|
||||
out dx, al
|
||||
|
||||
mov dx, [eth_asic_base]
|
||||
add dx, ASIC_PIO
|
||||
|
||||
mov al, [eth_flags]
|
||||
and al, FLAG_16BIT
|
||||
cmp al, 0
|
||||
je epr_003
|
||||
|
||||
shr ecx, 1
|
||||
|
||||
epr_002:
|
||||
; 2 bytes at a time
|
||||
in ax, dx
|
||||
mov [edi], ax
|
||||
add edi, 2
|
||||
loop epr_002
|
||||
ret
|
||||
|
||||
epr_003:
|
||||
; 1 byte at a time
|
||||
in al, dx
|
||||
mov [edi], al
|
||||
inc edi
|
||||
loop epr_003
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; eth_pio_write
|
||||
;
|
||||
; Description
|
||||
; writes a frame to the ethernet card via Programmed I/O
|
||||
; dst in ebx
|
||||
; cnt in ecx
|
||||
; src in esi
|
||||
;***************************************************************************
|
||||
eth_pio_write:
|
||||
mov al, [eth_flags]
|
||||
and al, FLAG_16BIT
|
||||
cmp al, 0
|
||||
je epw_001
|
||||
|
||||
inc ecx
|
||||
and ecx, 0xFFFFFFFE
|
||||
|
||||
epw_001:
|
||||
mov al, D8390_COMMAND_RD2_STA
|
||||
mov dx, [eth_nic_base]
|
||||
add dx, D8390_P0_COMMAND
|
||||
out dx, al
|
||||
|
||||
mov al, D8390_ISR_RDC
|
||||
mov dx, [eth_nic_base]
|
||||
add dx, D8390_P0_ISR
|
||||
out dx, al
|
||||
|
||||
|
||||
mov al, cl
|
||||
mov dx, [eth_nic_base]
|
||||
add dx, D8390_P0_RBCR0
|
||||
out dx, al
|
||||
|
||||
mov al, ch
|
||||
mov dx, [eth_nic_base]
|
||||
add dx, D8390_P0_RBCR1
|
||||
out dx, al
|
||||
|
||||
mov al, bl
|
||||
mov dx, [eth_nic_base]
|
||||
add dx, D8390_P0_RSAR0
|
||||
out dx, al
|
||||
|
||||
mov al, bh
|
||||
mov dx, [eth_nic_base]
|
||||
add dx, D8390_P0_RSAR1
|
||||
out dx, al
|
||||
|
||||
mov al, D8390_COMMAND_RD1_STA
|
||||
mov dx, [eth_nic_base]
|
||||
add dx, D8390_P0_COMMAND
|
||||
out dx, al
|
||||
|
||||
mov dx, [eth_asic_base]
|
||||
add dx, ASIC_PIO
|
||||
|
||||
mov al, [eth_flags]
|
||||
and al, FLAG_16BIT
|
||||
cmp al, 0
|
||||
je epw_003
|
||||
|
||||
shr ecx, 1
|
||||
|
||||
epw_002:
|
||||
; 2 bytes at a time
|
||||
mov ax, [esi]
|
||||
add esi, 2
|
||||
out dx, ax
|
||||
|
||||
loop epw_002
|
||||
jmp epw_004
|
||||
|
||||
epw_003:
|
||||
; 1 byte at a time
|
||||
mov al, [esi]
|
||||
inc esi
|
||||
out dx, al
|
||||
loop epw_003
|
||||
|
||||
epw_004:
|
||||
mov dx, [eth_nic_base]
|
||||
add dx, D8390_P0_ISR
|
||||
|
||||
epw_005:
|
||||
in al, dx
|
||||
and al, D8390_ISR_RDC
|
||||
cmp al, D8390_ISR_RDC
|
||||
jne epw_005
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; rtl8029_reset
|
||||
; Description
|
||||
; Place the chip (ie, the ethernet card) into a virgin state
|
||||
; No inputs
|
||||
; All registers destroyed
|
||||
;
|
||||
;***************************************************************************
|
||||
rtl8029_reset:
|
||||
mov bx, [eth_nic_base]
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_COMMAND
|
||||
mov al, D8390_COMMAND_PS0_RD2_STP
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_DCR
|
||||
mov al, [eth_flags]
|
||||
and al, FLAG_16BIT
|
||||
cmp al, FLAG_16BIT
|
||||
jne nsr_001
|
||||
|
||||
mov al, 0x49
|
||||
jmp nsr_002
|
||||
|
||||
nsr_001:
|
||||
mov al, 0x48
|
||||
|
||||
nsr_002:
|
||||
out dx, al
|
||||
|
||||
xor al, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_RBCR0
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_RBCR1
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_RCR
|
||||
mov al, 0x20
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_TCR
|
||||
mov al, 2
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_TPSR
|
||||
mov al, [eth_tx_start]
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_PSTART
|
||||
mov al, [eth_rx_start]
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_PSTOP
|
||||
mov al, [eth_memsize]
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_BOUND
|
||||
mov al, [eth_memsize]
|
||||
dec al
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_ISR
|
||||
mov al, 0xff
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_IMR
|
||||
xor al, al
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_COMMAND
|
||||
mov al, D8390_COMMAND_PS1_RD2_STP
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P1_PAR0
|
||||
mov esi, node_addr
|
||||
mov ecx, ETH_ALEN
|
||||
|
||||
nsr_003:
|
||||
mov al, [esi]
|
||||
out dx, al
|
||||
|
||||
inc esi
|
||||
inc dx
|
||||
loop nsr_003
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P1_MAR0
|
||||
mov ecx, ETH_ALEN
|
||||
|
||||
mov al, 0xff
|
||||
|
||||
nsr_004:
|
||||
out dx, al
|
||||
inc dx
|
||||
loop nsr_004
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P1_CURR
|
||||
mov al, [eth_rx_start]
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_COMMAND
|
||||
mov al, D8390_COMMAND_PS0_RD2_STA
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_ISR
|
||||
mov al, 0xff
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_TCR
|
||||
mov al, 0
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_RCR
|
||||
mov al, 4
|
||||
out dx, al
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; rtl8029_probe
|
||||
; Description
|
||||
; Searches for an ethernet card, enables it and clears the rx buffer
|
||||
; If a card was found, it enables the ethernet -> TCPIP link
|
||||
;
|
||||
;***************************************************************************
|
||||
rtl8029_probe:
|
||||
mov eax, [io_addr]
|
||||
mov [eth_nic_base], ax ; The IO address space is 16 bit only
|
||||
|
||||
mov al, VENDOR_NONE
|
||||
mov [eth_vendor], al
|
||||
|
||||
mov al, [eth_vendor]
|
||||
cmp al, VENDOR_NONE
|
||||
|
||||
jne ep_check_have_vendor
|
||||
xor eax, eax
|
||||
mov [eth_bmem], eax
|
||||
|
||||
mov al, FLAG_PIO
|
||||
mov [eth_flags], al
|
||||
|
||||
mov ax, [eth_nic_base]
|
||||
add ax, NE_ASIC_OFFSET
|
||||
mov [eth_asic_base], ax
|
||||
|
||||
mov al, MEM_16384
|
||||
mov [eth_memsize], al
|
||||
|
||||
mov al, 32
|
||||
mov [eth_tx_start], al
|
||||
|
||||
add al, D8390_TXBUF_SIZE
|
||||
mov [eth_rx_start], al
|
||||
|
||||
mov dx, [eth_asic_base]
|
||||
add dx, NE_RESET
|
||||
|
||||
in al, dx
|
||||
out dx, al
|
||||
|
||||
in al, 0x84
|
||||
|
||||
mov bx, [eth_nic_base]
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_COMMAND
|
||||
mov al, D8390_COMMAND_RD2_STP
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_RCR
|
||||
mov al, D8390_RCR_MON
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_DCR
|
||||
mov al, D8390_DCR_FT1_LS
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_PSTART
|
||||
mov al, MEM_8192
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_PSTOP
|
||||
mov al, MEM_16384
|
||||
out dx, al
|
||||
|
||||
mov esi, test_data
|
||||
mov ebx, 8192
|
||||
mov ecx, 14
|
||||
call eth_pio_write
|
||||
|
||||
mov ebx, 8192
|
||||
mov ecx, 14
|
||||
mov edi, test_buffer
|
||||
call eth_pio_read
|
||||
|
||||
mov esi, test_buffer
|
||||
mov edi, test_data
|
||||
mov ecx, 13
|
||||
cld
|
||||
rep cmpsb
|
||||
|
||||
je ep_set_vendor
|
||||
|
||||
mov al, [eth_flags]
|
||||
or al, FLAG_16BIT
|
||||
mov [eth_flags], al
|
||||
|
||||
mov al, MEM_32768
|
||||
mov [eth_memsize], al
|
||||
|
||||
mov al, 64
|
||||
mov [eth_tx_start], al
|
||||
|
||||
add al, D8390_TXBUF_SIZE
|
||||
mov [eth_rx_start], al
|
||||
|
||||
mov bx, [eth_nic_base]
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_DCR
|
||||
mov al, D8390_DCR_WTS_FT1_LS
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_PSTART
|
||||
mov al, MEM_16384
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_PSTOP
|
||||
mov al, MEM_32768
|
||||
out dx, al
|
||||
|
||||
mov esi, test_data
|
||||
mov ebx, 16384
|
||||
mov ecx, 14
|
||||
call eth_pio_write
|
||||
|
||||
mov ebx, 16384
|
||||
mov ecx, 14
|
||||
mov edi, test_buffer
|
||||
call eth_pio_read
|
||||
|
||||
mov esi, test_buffer
|
||||
mov edi, test_data
|
||||
mov ecx, 13
|
||||
cld
|
||||
rep cmpsb
|
||||
|
||||
ep_set_vendor:
|
||||
; this bit is odd - probably left over from my hacking
|
||||
mov ax, [eth_nic_base]
|
||||
cmp ax, 0
|
||||
je rtl8029_exit
|
||||
cmp ax, ISA_MAX_ADDR
|
||||
jbe ep_001
|
||||
mov al, [eth_flags]
|
||||
or al, FLAG_16BIT
|
||||
mov [eth_flags], al
|
||||
|
||||
ep_001:
|
||||
mov al, VENDOR_NOVELL
|
||||
mov [eth_vendor], al
|
||||
|
||||
mov ebx, 0
|
||||
mov ecx, 16
|
||||
mov edi, romdata
|
||||
call eth_pio_read
|
||||
|
||||
|
||||
mov ecx, ETH_ALEN
|
||||
mov esi, romdata
|
||||
mov edi, node_addr
|
||||
|
||||
mov bl, [eth_flags]
|
||||
and bl, FLAG_16BIT
|
||||
|
||||
ep_002:
|
||||
mov al, [esi]
|
||||
mov [edi], al
|
||||
|
||||
inc edi
|
||||
inc esi
|
||||
cmp bl, FLAG_16BIT
|
||||
jne ep_003
|
||||
|
||||
inc esi
|
||||
|
||||
ep_003:
|
||||
loop ep_002
|
||||
|
||||
ep_check_have_vendor:
|
||||
mov al, [eth_vendor]
|
||||
cmp al, VENDOR_NONE
|
||||
je rtl8029_exit
|
||||
|
||||
cmp al, VENDOR_3COM
|
||||
je ep_reset_card
|
||||
|
||||
mov eax, [eth_bmem]
|
||||
mov [eth_rmem], eax
|
||||
|
||||
ep_reset_card:
|
||||
; Reset the card
|
||||
call rtl8029_reset
|
||||
|
||||
; Indicate that we have successfully reset the card
|
||||
mov eax, [pci_data]
|
||||
mov [eth_status], eax
|
||||
|
||||
rtl8029_exit:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; rtl8029_poll
|
||||
;
|
||||
; Description
|
||||
; Polls the ethernet card for a received packet
|
||||
; Received data, if any, ends up in Ether_buffer
|
||||
;
|
||||
;***************************************************************************
|
||||
rtl8029_poll:
|
||||
mov eax, Ether_buffer
|
||||
mov [eth_rx_data_ptr], eax
|
||||
|
||||
mov bx, [eth_nic_base]
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_RSR
|
||||
in al, dx
|
||||
|
||||
and al, D8390_RSTAT_PRX
|
||||
cmp al, D8390_RSTAT_PRX
|
||||
jne nsp_exit
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_BOUND
|
||||
in al, dx
|
||||
inc al
|
||||
|
||||
cmp al, [eth_memsize]
|
||||
jb nsp_001
|
||||
|
||||
mov al, [eth_rx_start]
|
||||
|
||||
nsp_001:
|
||||
mov ch, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_COMMAND
|
||||
mov al, D8390_COMMAND_PS1
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P1_CURR
|
||||
in al, dx ; get current page
|
||||
mov cl, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_COMMAND
|
||||
mov al, D8390_COMMAND_PS0
|
||||
out dx, al
|
||||
|
||||
cmp cl, [eth_memsize]
|
||||
jb nsp_002
|
||||
|
||||
mov cl, [eth_rx_start]
|
||||
|
||||
nsp_002:
|
||||
cmp cl, ch
|
||||
je nsp_exit
|
||||
|
||||
xor ax, ax
|
||||
mov ah, ch
|
||||
|
||||
mov [pktoff], ax
|
||||
|
||||
mov al, [eth_flags]
|
||||
and al, FLAG_PIO
|
||||
cmp al, FLAG_PIO
|
||||
jne nsp_003
|
||||
|
||||
movzx ebx, word [pktoff]
|
||||
mov edi, pkthdr
|
||||
mov ecx, 4
|
||||
call eth_pio_read
|
||||
jmp nsp_004
|
||||
|
||||
nsp_003:
|
||||
mov edi, [eth_rmem]
|
||||
movzx eax, word [pktoff]
|
||||
add edi, eax
|
||||
mov eax, [edi]
|
||||
mov [pkthdr], eax
|
||||
|
||||
nsp_004:
|
||||
mov ax, [pktoff]
|
||||
add ax, 4
|
||||
mov [pktoff], ax
|
||||
|
||||
mov ax, [pkthdr + 2]
|
||||
sub ax, 4
|
||||
|
||||
mov [eth_tmp_len], ax
|
||||
|
||||
cmp ax, ETH_ZLEN
|
||||
jb nsp_exit
|
||||
|
||||
cmp ax, ETH_FRAME_LEN
|
||||
ja nsp_exit
|
||||
|
||||
mov al, [pkthdr]
|
||||
and al, D8390_RSTAT_PRX
|
||||
cmp al, D8390_RSTAT_PRX
|
||||
jne nsp_exit
|
||||
|
||||
; Right, we can now get the data
|
||||
|
||||
mov ax, [eth_tmp_len]
|
||||
mov [eth_rx_data_len], ax
|
||||
|
||||
xor ebx, ebx
|
||||
mov bh, [eth_memsize]
|
||||
sub bx, [pktoff]
|
||||
|
||||
cmp [eth_tmp_len], bx
|
||||
jbe nsp_005
|
||||
|
||||
mov al, [eth_flags]
|
||||
and al, FLAG_PIO
|
||||
cmp al, FLAG_PIO
|
||||
jne nsp_006
|
||||
|
||||
push ebx
|
||||
mov ecx, ebx
|
||||
xor ebx, ebx
|
||||
mov bx, [pktoff]
|
||||
mov edi, [eth_rx_data_ptr]
|
||||
call eth_pio_read
|
||||
pop ebx
|
||||
jmp nsp_007
|
||||
|
||||
nsp_006:
|
||||
; Not implemented, as we are using PIO mode on this card
|
||||
|
||||
nsp_007:
|
||||
xor ax, ax
|
||||
mov ah, [eth_rx_start]
|
||||
mov [pktoff], ax
|
||||
|
||||
mov eax, [eth_rx_data_ptr]
|
||||
add eax, ebx
|
||||
mov [eth_rx_data_ptr], eax
|
||||
|
||||
mov ax, [eth_tmp_len]
|
||||
sub ax, bx
|
||||
mov [eth_tmp_len], ax
|
||||
|
||||
nsp_005:
|
||||
mov al, [eth_flags]
|
||||
and al, FLAG_PIO
|
||||
cmp al, FLAG_PIO
|
||||
jne nsp_008
|
||||
|
||||
xor ebx, ebx
|
||||
mov bx, [pktoff]
|
||||
xor ecx, ecx
|
||||
mov cx, [eth_tmp_len]
|
||||
mov edi, [eth_rx_data_ptr]
|
||||
call eth_pio_read
|
||||
jmp nsp_009
|
||||
|
||||
nsp_008:
|
||||
; Not implemented, as we are using PIO mode on this card
|
||||
|
||||
nsp_009:
|
||||
mov al, [pkthdr+1]
|
||||
cmp al, [eth_rx_start]
|
||||
jne nsp_010
|
||||
|
||||
mov al, [eth_memsize]
|
||||
|
||||
nsp_010:
|
||||
mov dx, [eth_nic_base]
|
||||
add dx, D8390_P0_BOUND
|
||||
dec al
|
||||
out dx, al
|
||||
|
||||
nsp_exit:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; rtl8029_transmit
|
||||
;
|
||||
; Description
|
||||
; Transmits a packet of data via the ethernet card
|
||||
; Pointer to 48 bit destination address in edi
|
||||
; Type of packet in bx
|
||||
; size of packet in ecx
|
||||
; pointer to packet data in esi
|
||||
;
|
||||
;***************************************************************************
|
||||
rtl8029_transmit:
|
||||
mov [eth_type], bx
|
||||
|
||||
pusha
|
||||
|
||||
mov esi, edi
|
||||
xor bx, bx
|
||||
mov bh, [eth_tx_start]
|
||||
mov ecx, ETH_ALEN
|
||||
call eth_pio_write
|
||||
|
||||
mov esi, node_addr
|
||||
xor bx, bx
|
||||
mov bh, [eth_tx_start]
|
||||
add bx, ETH_ALEN
|
||||
mov ecx, ETH_ALEN
|
||||
call eth_pio_write
|
||||
|
||||
mov esi, eth_type
|
||||
xor bx, bx
|
||||
mov bh, [eth_tx_start]
|
||||
add bx, ETH_ALEN
|
||||
add bx, ETH_ALEN
|
||||
mov ecx, 2
|
||||
call eth_pio_write
|
||||
|
||||
popa
|
||||
|
||||
xor bx, bx
|
||||
mov bh, [eth_tx_start]
|
||||
add bx, ETH_HLEN
|
||||
push ecx
|
||||
call eth_pio_write
|
||||
pop ecx
|
||||
|
||||
add ecx, ETH_HLEN
|
||||
cmp ecx, ETH_ZLEN
|
||||
jae nst_001
|
||||
|
||||
mov ecx, ETH_ZLEN
|
||||
|
||||
nst_001:
|
||||
push ecx
|
||||
|
||||
mov bx, [eth_nic_base]
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_COMMAND
|
||||
mov al, D8390_COMMAND_PS0_RD2_STA
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_TPSR
|
||||
mov al, [eth_tx_start]
|
||||
out dx, al
|
||||
|
||||
pop ecx
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_TBCR0
|
||||
mov al, cl
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_TBCR1
|
||||
mov al, ch
|
||||
out dx, al
|
||||
|
||||
mov dx, bx
|
||||
add dx, D8390_P0_COMMAND
|
||||
mov al, D8390_COMMAND_PS0_TXP_RD2_STA
|
||||
out dx, al
|
||||
|
||||
ret
|
@ -1,624 +0,0 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; RTL8139.INC ;;
|
||||
;; ;;
|
||||
;; Ethernet driver for Menuet OS ;;
|
||||
;; ;;
|
||||
;; Version 0.2 11 August 2003 ;;
|
||||
;; ;;
|
||||
;; Driver for chips of RealTek 8139 family ;;
|
||||
;; References: ;;
|
||||
;; www.realtek.com.hw - data sheets ;;
|
||||
;; rtl8139.c - linux driver ;;
|
||||
;; 8139too.c - linux driver ;;
|
||||
;; ethernet driver template by Mike Hibbett ;;
|
||||
;; ;;
|
||||
;; The copyright statement is ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;; Copyright 2003 Endre Kozma, ;;
|
||||
;; endre.kozma@axelero.hu ;;
|
||||
;; ;;
|
||||
;; See file COPYING for details ;;
|
||||
;; ;;
|
||||
;; 10.01.2007 Bugfix for l8139_transmit from Paolo Franchetti ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
$Revision$
|
||||
|
||||
|
||||
ETH_ALEN equ 6
|
||||
ETH_HLEN equ (2 * ETH_ALEN + 2)
|
||||
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for
|
||||
; mininmum 64bytes frame length
|
||||
|
||||
PCI_REG_COMMAND equ 0x04 ; command register
|
||||
PCI_BIT_PIO equ 0 ; bit0: io space control
|
||||
PCI_BIT_MMIO equ 1 ; bit1: memory space control
|
||||
PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master
|
||||
|
||||
RTL8139_REG_MAR0 equ 0x08 ; multicast filter register 0
|
||||
RTL8139_REG_MAR4 equ 0x0c ; multicast filter register 4
|
||||
RTL8139_REG_TSD0 equ 0x10 ; transmit status of descriptor
|
||||
RTL8139_REG_TSAD0 equ 0x20 ; transmit start address of descriptor
|
||||
RTL8139_REG_RBSTART equ 0x30 ; RxBuffer start address
|
||||
RTL8139_REG_COMMAND equ 0x37 ; command register
|
||||
RTL8139_REG_CAPR equ 0x38 ; current address of packet read
|
||||
RTL8139_REG_IMR equ 0x3c ; interrupt mask register
|
||||
RTL8139_REG_ISR equ 0x3e ; interrupt status register
|
||||
RTL8139_REG_TXCONFIG equ 0x40 ; transmit configuration register
|
||||
RTL8139_REG_TXCONFIG_0 equ 0x40 ; transmit configuration register 0
|
||||
RTL8139_REG_TXCONFIG_1 equ 0x41 ; transmit configuration register 1
|
||||
RTL8139_REG_TXCONFIG_2 equ 0x42 ; transmit configuration register 2
|
||||
RTL8139_REG_TXCONFIG_3 equ 0x43 ; transmit configuration register 3
|
||||
RTL8139_REG_RXCONFIG equ 0x44 ; receive configuration register 0
|
||||
RTL8139_REG_RXCONFIG_0 equ 0x44 ; receive configuration register 0
|
||||
RTL8139_REG_RXCONFIG_1 equ 0x45 ; receive configuration register 1
|
||||
RTL8139_REG_RXCONFIG_2 equ 0x46 ; receive configuration register 2
|
||||
RTL8139_REG_RXCONFIG_3 equ 0x47 ; receive configuration register 3
|
||||
RTL8139_REG_MPC equ 0x4c ; missed packet counter
|
||||
RTL8139_REG_9346CR equ 0x50 ; serial eeprom 93C46 command register
|
||||
RTL8139_REG_CONFIG1 equ 0x52 ; configuration register 1
|
||||
RTL8139_REG_CONFIG4 equ 0x5a ; configuration register 4
|
||||
RTL8139_REG_HLTCLK equ 0x5b ; undocumented halt clock register
|
||||
RTL8139_REG_BMCR equ 0x62 ; basic mode control register
|
||||
RTL8139_REG_ANAR equ 0x66 ; auto negotiation advertisement register
|
||||
|
||||
; 5.1 packet header
|
||||
RTL8139_BIT_RUNT equ 4 ; total packet length < 64 bytes
|
||||
RTL8139_BIT_LONG equ 3 ; total packet length > 4k
|
||||
RTL8139_BIT_CRC equ 2 ; crc error occured
|
||||
RTL8139_BIT_FAE equ 1 ; frame alignment error occured
|
||||
RTL8139_BIT_ROK equ 0 ; received packet is ok
|
||||
; 5.4 command register
|
||||
RTL8139_BIT_RST equ 4 ; reset bit
|
||||
RTL8139_BIT_RE equ 3 ; receiver enabled
|
||||
RTL8139_BIT_TE equ 2 ; transmitter enabled
|
||||
RTL8139_BIT_BUFE equ 0 ; rx buffer is empty, no packet stored
|
||||
; 5.6 interrupt status register
|
||||
RTL8139_BIT_ISR_TOK equ 2 ; transmit ok
|
||||
RTL8139_BIT_ISR_RER equ 1 ; receive error interrupt
|
||||
RTL8139_BIT_ISR_ROK equ 0 ; receive ok
|
||||
; 5.7 transmit configyration register
|
||||
RTL8139_BIT_TX_MXDMA equ 8 ; Max DMA burst size per Tx DMA burst
|
||||
RTL8139_BIT_TXRR equ 4 ; Tx Retry count 16+(TXRR*16)
|
||||
; 5.8 receive configuration register
|
||||
RTL8139_BIT_RXFTH equ 13 ; Rx fifo threshold
|
||||
RTL8139_BIT_RBLEN equ 11 ; Ring buffer length indicator
|
||||
RTL8139_BIT_RX_MXDMA equ 8 ; Max DMA burst size per Rx DMA burst
|
||||
RTL8139_BIT_NOWRAP equ 7 ; transfered data wrapping
|
||||
RTL8139_BIT_9356SEL equ 6 ; eeprom selector 9346/9356
|
||||
RTL8139_BIT_AER equ 5 ; accept error packets
|
||||
RTL8139_BIT_AR equ 4 ; accept runt packets
|
||||
RTL8139_BIT_AB equ 3 ; accept broadcast packets
|
||||
RTL8139_BIT_AM equ 2 ; accept multicast packets
|
||||
RTL8139_BIT_APM equ 1 ; accept physical match packets
|
||||
RTL8139_BIT_AAP equ 0 ; accept all packets
|
||||
; 5.9 93C46/93C56 command register
|
||||
RTL8139_BIT_93C46_EEM1 equ 7 ; RTL8139 eeprom operating mode1
|
||||
RTL8139_BIT_93C46_EEM0 equ 6 ; RTL8139 eeprom operating mode0
|
||||
RTL8139_BIT_93C46_EECS equ 3 ; chip select
|
||||
RTL8139_BIT_93C46_EESK equ 2 ; serial data clock
|
||||
RTL8139_BIT_93C46_EEDI equ 1 ; serial data input
|
||||
RTL8139_BIT_93C46_EEDO equ 0 ; serial data output
|
||||
; 5.11 configuration register 1
|
||||
RTL8139_BIT_LWACT equ 4 ; see RTL8139_REG_CONFIG1
|
||||
RTL8139_BIT_SLEEP equ 1 ; sleep bit at older chips
|
||||
RTL8139_BIT_PWRDWN equ 0 ; power down bit at older chips
|
||||
RTL8139_BIT_PMEn equ 0 ; power management enabled
|
||||
; 5.14 configuration register 4
|
||||
RTL8139_BIT_LWPTN equ 2 ; see RTL8139_REG_CONFIG4
|
||||
; 6.2 transmit status register
|
||||
RTL8139_BIT_ERTXTH equ 16 ; early TX threshold
|
||||
RTL8139_BIT_TOK equ 15 ; transmit ok
|
||||
RTL8139_BIT_OWN equ 13 ; tx DMA operation is completed
|
||||
; 6.18 basic mode control register
|
||||
RTL8139_BIT_ANE equ 12 ; auto negotiation enable
|
||||
; 6.20 auto negotiation advertisement register
|
||||
RTL8139_BIT_TXFD equ 8 ; 100base-T full duplex
|
||||
RTL8139_BIT_TX equ 7 ; 100base-T
|
||||
RTL8139_BIT_10FD equ 6 ; 10base-T full duplex
|
||||
RTL8139_BIT_10 equ 5 ; 10base-T
|
||||
RTL8139_BIT_SELECTOR equ 0 ; binary encoded selector CSMA/CD=00001
|
||||
; RX/TX buffer size
|
||||
RTL8139_RBLEN equ 0 ; 0==8K 1==16k 2==32k 3==64k
|
||||
RTL8139_RX_BUFFER_SIZE equ (8192 shl RTL8139_RBLEN)
|
||||
MAX_ETH_FRAME_SIZE equ 1516 ; exactly 1514 wthout CRC
|
||||
RTL8139_NUM_TX_DESC equ 4
|
||||
RTL8139_TX_BUFFER_SIZE equ (MAX_ETH_FRAME_SIZE * RTL8139_NUM_TX_DESC)
|
||||
RTL8139_TXRR equ 8 ; total retries = 16+(TXRR*16)
|
||||
RTL8139_TX_MXDMA equ 6 ; 0==16 1==32 2==64 3==128
|
||||
; 4==256 5==512 6==1024 7==2048
|
||||
RTL8139_ERTXTH equ 8 ; in unit of 32 bytes e.g:(8*32)=256
|
||||
RTL8139_RX_MXDMA equ 7 ; 0==16 1==32 2==64 3==128
|
||||
; 4==256 5==512 6==1024 7==unlimited
|
||||
RTL8139_RXFTH equ 7 ; 0==16 1==32 2==64 3==128
|
||||
; 4==256 5==512 6==1024 7==no threshold
|
||||
RTL8139_RX_CONFIG equ ((RTL8139_RBLEN shl RTL8139_BIT_RBLEN) \
|
||||
or (RTL8139_RX_MXDMA shl RTL8139_BIT_RX_MXDMA) \
|
||||
or (1 shl RTL8139_BIT_NOWRAP) \
|
||||
or (RTL8139_RXFTH shl RTL8139_BIT_RXFTH) \
|
||||
or (1 shl RTL8139_BIT_AB) or (1 shl RTL8139_BIT_APM) \
|
||||
or (1 shl RTL8139_BIT_AER) or (1 shl RTL8139_BIT_AR) \
|
||||
or (1 shl RTL8139_BIT_AM))
|
||||
RTL8139_TX_TIMEOUT equ 30 ; 300 milliseconds timeout
|
||||
|
||||
EE_93C46_REG_ETH_ID equ 7 ; MAC offset
|
||||
EE_93C46_READ_CMD equ (6 shl 6) ; 110b + 6bit address
|
||||
EE_93C56_READ_CMD equ (6 shl 8) ; 110b + 8bit address
|
||||
EE_93C46_CMD_LENGTH equ 9 ; start bit + cmd + 6bit address
|
||||
EE_93C56_CMD_LENGTH equ 11 ; start bit + cmd + 8bit ddress
|
||||
|
||||
VER_RTL8139 equ 1100000b
|
||||
VER_RTL8139A equ 1110000b
|
||||
; VER_RTL8139AG equ 1110100b
|
||||
VER_RTL8139B equ 1111000b
|
||||
VER_RTL8130 equ VER_RTL8139B
|
||||
VER_RTL8139C equ 1110100b
|
||||
VER_RTL8100 equ 1111010b
|
||||
VER_RTL8100B equ 1110101b
|
||||
VER_RTL8139D equ VER_RTL8100B
|
||||
VER_RTL8139CP equ 1110110b
|
||||
VER_RTL8101 equ 1110111b
|
||||
|
||||
IDX_RTL8139 equ 0
|
||||
IDX_RTL8139A equ 1
|
||||
IDX_RTL8139B equ 2
|
||||
IDX_RTL8139C equ 3
|
||||
IDX_RTL8100 equ 4
|
||||
IDX_RTL8139D equ 5
|
||||
IDX_RTL8139D equ 6
|
||||
IDX_RTL8101 equ 7
|
||||
|
||||
|
||||
; These two must be 4 byte aligned ( which they are )
|
||||
rtl8139_rx_buff equ eth_data_start
|
||||
rtl8139_tx_buff equ rtl8139_rx_buff + (RTL8139_RX_BUFFER_SIZE + MAX_ETH_FRAME_SIZE)
|
||||
|
||||
uglobal
|
||||
align 4
|
||||
rtl8139_rx_buff_offset:
|
||||
dd 0
|
||||
curr_tx_desc dd 0
|
||||
endg
|
||||
|
||||
iglobal
|
||||
hw_ver_array:
|
||||
db VER_RTL8139, VER_RTL8139A, VER_RTL8139B, VER_RTL8139C
|
||||
db VER_RTL8100, VER_RTL8139D, VER_RTL8139CP, VER_RTL8101
|
||||
HW_VER_ARRAY_SIZE = $-hw_ver_array
|
||||
endg
|
||||
|
||||
uglobal
|
||||
hw_ver_id:
|
||||
db 0
|
||||
endg
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; rtl8139_probe
|
||||
; Description
|
||||
; Searches for an ethernet card, enables it and clears the rx buffer
|
||||
; If a card was found, it enables the ethernet -> TCPIP link
|
||||
; Destroyed registers
|
||||
; eax, ebx, ecx, edx
|
||||
;
|
||||
;***************************************************************************
|
||||
rtl8139_probe:
|
||||
; enable the device
|
||||
mov al, 2
|
||||
mov ah, [pci_bus]
|
||||
mov bh, [pci_dev]
|
||||
mov bl, PCI_REG_COMMAND
|
||||
call pci_read_reg
|
||||
mov cx, ax
|
||||
or cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO)
|
||||
and cl, not (1 shl PCI_BIT_MMIO)
|
||||
mov al, 2
|
||||
mov ah, [pci_bus]
|
||||
mov bh, [pci_dev]
|
||||
mov bl, PCI_REG_COMMAND
|
||||
call pci_write_reg
|
||||
; get chip version
|
||||
mov edx, [io_addr]
|
||||
add edx, RTL8139_REG_TXCONFIG_2
|
||||
in ax, dx
|
||||
shr ah, 2
|
||||
shr ax, 6
|
||||
and al, 01111111b
|
||||
mov ecx, HW_VER_ARRAY_SIZE-1
|
||||
.chip_ver_loop:
|
||||
cmp al, [hw_ver_array+ecx]
|
||||
je .chip_ver_found
|
||||
dec ecx
|
||||
jns .chip_ver_loop
|
||||
xor cl, cl ; default RTL8139
|
||||
.chip_ver_found:
|
||||
mov [hw_ver_id], cl
|
||||
; wake up the chip
|
||||
mov edx, [io_addr]
|
||||
add edx, RTL8139_REG_HLTCLK
|
||||
mov al, 'R' ; run the clock
|
||||
out dx, al
|
||||
; unlock config and BMCR registers
|
||||
add edx, RTL8139_REG_9346CR - RTL8139_REG_HLTCLK
|
||||
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0)
|
||||
out dx, al
|
||||
; enable power management
|
||||
add edx, RTL8139_REG_CONFIG1 - RTL8139_REG_9346CR
|
||||
in al, dx
|
||||
cmp byte [hw_ver_id], IDX_RTL8139B
|
||||
jl .old_chip
|
||||
; set LWAKE pin to active high (default value).
|
||||
; it is for Wake-On-LAN functionality of some motherboards.
|
||||
; this signal is used to inform the motherboard to execute a wake-up process.
|
||||
; only at newer chips.
|
||||
or al, (1 shl RTL8139_BIT_PMEn)
|
||||
and al, not (1 shl RTL8139_BIT_LWACT)
|
||||
out dx, al
|
||||
add edx, RTL8139_REG_CONFIG4 - RTL8139_REG_CONFIG1
|
||||
in al, dx
|
||||
and al, not (1 shl RTL8139_BIT_LWPTN)
|
||||
out dx, al
|
||||
jmp .finish_wake_up
|
||||
.old_chip:
|
||||
; wake up older chips
|
||||
and al, not ((1 shl RTL8139_BIT_SLEEP) or (1 shl RTL8139_BIT_PWRDWN))
|
||||
out dx, al
|
||||
.finish_wake_up:
|
||||
; lock config and BMCR registers
|
||||
xor al, al
|
||||
mov edx, [io_addr]
|
||||
add edx, RTL8139_REG_9346CR
|
||||
out dx, al
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; rt8139_reset
|
||||
; Description
|
||||
; Place the chip (ie, the ethernet card) into a virgin state
|
||||
; Destroyed registers
|
||||
; eax, ebx, ecx, edx
|
||||
;
|
||||
;***************************************************************************
|
||||
rtl8139_reset:
|
||||
mov edx, [io_addr]
|
||||
add edx, RTL8139_REG_COMMAND
|
||||
mov al, 1 shl RTL8139_BIT_RST
|
||||
out dx, al
|
||||
mov cx, 1000 ; wait no longer for the reset
|
||||
.wait_for_reset:
|
||||
in al, dx
|
||||
test al, 1 shl RTL8139_BIT_RST
|
||||
jz .reset_completed ; RST remains 1 during reset
|
||||
dec cx
|
||||
jns .wait_for_reset
|
||||
.reset_completed:
|
||||
; get MAC (hardware address)
|
||||
mov ecx, 2
|
||||
.mac_read_loop:
|
||||
lea eax, [EE_93C46_REG_ETH_ID+ecx]
|
||||
push ecx
|
||||
call rtl8139_read_eeprom
|
||||
pop ecx
|
||||
mov [node_addr+ecx*2], ax
|
||||
dec ecx
|
||||
jns .mac_read_loop
|
||||
; unlock config and BMCR registers
|
||||
mov edx, [io_addr]
|
||||
add edx, RTL8139_REG_9346CR
|
||||
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0)
|
||||
out dx, al
|
||||
; initialize multicast registers (no filtering)
|
||||
mov eax, 0xffffffff
|
||||
add edx, RTL8139_REG_MAR0 - RTL8139_REG_9346CR
|
||||
out dx, eax
|
||||
add edx, RTL8139_REG_MAR4 - RTL8139_REG_MAR0
|
||||
out dx, eax
|
||||
; enable Rx/Tx
|
||||
mov al, (1 shl RTL8139_BIT_RE) or (1 shl RTL8139_BIT_TE)
|
||||
add edx, RTL8139_REG_COMMAND - RTL8139_REG_MAR4
|
||||
out dx, al
|
||||
; 32k Rxbuffer, unlimited dma burst, no wrapping, no rx threshold
|
||||
; accept broadcast packets, accept physical match packets
|
||||
mov eax, RTL8139_RX_CONFIG
|
||||
add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND
|
||||
out dx, eax
|
||||
; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144
|
||||
mov eax, (RTL8139_TX_MXDMA shl RTL8139_BIT_TX_MXDMA) \
|
||||
or (RTL8139_TXRR shl RTL8139_BIT_TXRR)
|
||||
add edx, RTL8139_REG_TXCONFIG - RTL8139_REG_RXCONFIG
|
||||
out dx, eax
|
||||
; enable auto negotiation
|
||||
add edx, RTL8139_REG_BMCR - RTL8139_REG_TXCONFIG
|
||||
in ax, dx
|
||||
or ax, (1 shl RTL8139_BIT_ANE)
|
||||
out dx, ax
|
||||
; set auto negotiation advertisement
|
||||
add edx, RTL8139_REG_ANAR - RTL8139_REG_BMCR
|
||||
in ax, dx
|
||||
or ax, (1 shl RTL8139_BIT_SELECTOR) or (1 shl RTL8139_BIT_10) \
|
||||
or (1 shl RTL8139_BIT_10FD) or (1 shl RTL8139_BIT_TX) \
|
||||
or (1 shl RTL8139_BIT_TXFD)
|
||||
out dx, ax
|
||||
; lock config and BMCR registers
|
||||
xor eax, eax
|
||||
add edx, RTL8139_REG_9346CR - RTL8139_REG_ANAR
|
||||
out dx, al
|
||||
; init RX/TX pointers
|
||||
mov [rtl8139_rx_buff_offset], eax
|
||||
mov [curr_tx_desc], eax
|
||||
; clear missing packet counter
|
||||
add edx, RTL8139_REG_MPC - RTL8139_REG_9346CR
|
||||
out dx, eax
|
||||
; disable all interrupts
|
||||
add edx, RTL8139_REG_IMR - RTL8139_REG_MPC
|
||||
out dx, ax
|
||||
; set RxBuffer address, init RX buffer offset, init TX ring
|
||||
mov eax, rtl8139_rx_buff ; simba
|
||||
sub eax, OS_BASE
|
||||
add edx, RTL8139_REG_RBSTART - RTL8139_REG_IMR
|
||||
out dx, eax
|
||||
; Indicate that we have successfully reset the card
|
||||
mov eax, [pci_data]
|
||||
mov [eth_status], eax
|
||||
ret
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; rtl8139_read_eeprom
|
||||
; Description
|
||||
; reads eeprom type 93c46 and 93c56
|
||||
; Parameters
|
||||
; al - word to be read (6bit in case of 93c46 and 8bit otherwise)
|
||||
; Return value
|
||||
; ax - word read in
|
||||
; Destroyed register(s)
|
||||
; eax, cx, ebx, edx
|
||||
;
|
||||
;***************************************************************************
|
||||
rtl8139_read_eeprom:
|
||||
movzx ebx, al
|
||||
mov edx, [io_addr]
|
||||
add edx, RTL8139_REG_RXCONFIG
|
||||
in al, dx
|
||||
test al, (1 shl RTL8139_BIT_9356SEL)
|
||||
jz .type_93c46
|
||||
; and bl, 01111111b ; don't care first bit
|
||||
or bx, EE_93C56_READ_CMD ; it contains start bit
|
||||
mov cx, EE_93C56_CMD_LENGTH-1 ; cmd_loop counter
|
||||
jmp .read_eeprom
|
||||
.type_93c46:
|
||||
and bl, 00111111b
|
||||
or bx, EE_93C46_READ_CMD ; it contains start bit
|
||||
mov cx, EE_93C46_CMD_LENGTH-1 ; cmd_loop counter
|
||||
.read_eeprom:
|
||||
add edx, RTL8139_REG_9346CR - RTL8139_REG_RXCONFIG_0
|
||||
; mov al, (1 shl RTL8139_BIT_93C46_EEM1)
|
||||
; out dx, al
|
||||
mov al, (1 shl RTL8139_BIT_93C46_EEM1) \
|
||||
or (1 shl RTL8139_BIT_93C46_EECS) ; wake up the eeprom
|
||||
out dx, al
|
||||
.cmd_loop:
|
||||
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS)
|
||||
bt bx, cx
|
||||
jnc .zero_bit
|
||||
or al, (1 shl RTL8139_BIT_93C46_EEDI)
|
||||
.zero_bit:
|
||||
out dx, al
|
||||
; push eax
|
||||
; in eax, dx ; eeprom delay
|
||||
; pop eax
|
||||
or al, (1 shl RTL8139_BIT_93C46_EESK)
|
||||
out dx, al
|
||||
; in eax, dx ; eeprom delay
|
||||
dec cx
|
||||
jns .cmd_loop
|
||||
; in eax, dx ; eeprom delay
|
||||
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS)
|
||||
out dx, al
|
||||
mov cl, 0xf
|
||||
.read_loop:
|
||||
shl ebx, 1
|
||||
mov al, (1 shl RTL8139_BIT_93C46_EEM1) \
|
||||
or (1 shl RTL8139_BIT_93C46_EECS) \
|
||||
or (1 shl RTL8139_BIT_93C46_EESK)
|
||||
out dx, al
|
||||
; in eax, dx ; eeprom delay
|
||||
in al, dx
|
||||
and al, (1 shl RTL8139_BIT_93C46_EEDO)
|
||||
jz .dont_set
|
||||
inc ebx
|
||||
.dont_set:
|
||||
mov al, (1 shl RTL8139_BIT_93C46_EEM1) \
|
||||
or (1 shl RTL8139_BIT_93C46_EECS)
|
||||
out dx, al
|
||||
; in eax, dx ; eeprom delay
|
||||
dec cl
|
||||
jns .read_loop
|
||||
xor al, al
|
||||
out dx, al
|
||||
mov ax, bx
|
||||
ret
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; rtl8139_transmit
|
||||
; Description
|
||||
; Transmits a packet of data via the ethernet card
|
||||
; Pointer to 48 bit destination address in edi
|
||||
; Type of packet in bx
|
||||
; Size of packet in ecx
|
||||
; Pointer to packet data in esi
|
||||
; Destroyed registers
|
||||
; eax, edx, esi, edi
|
||||
; ToDo
|
||||
; for waiting of timeout the rtl8139 internal timer
|
||||
; should be used
|
||||
;
|
||||
;***************************************************************************
|
||||
rtl8139_transmit:
|
||||
cmp ecx, MAX_ETH_FRAME_SIZE
|
||||
jg .finish ; packet is too long
|
||||
push ecx
|
||||
; check descriptor
|
||||
mov ecx, [curr_tx_desc]
|
||||
mov edx, [io_addr]
|
||||
lea edx, [edx+ecx*4+RTL8139_REG_TSD0]
|
||||
push edx ebx
|
||||
in ax, dx
|
||||
test ax, 0x1fff ; or no size given
|
||||
jz .send_packet
|
||||
and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN)
|
||||
cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN)
|
||||
jz .send_packet
|
||||
; wait for timeout
|
||||
mov ebx, RTL8139_TX_TIMEOUT
|
||||
mov eax, 0x5 ; delay x/100 secs
|
||||
int 0x40
|
||||
in ax, dx
|
||||
and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN)
|
||||
cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN)
|
||||
jz .send_packet
|
||||
; chip hung, reset it
|
||||
call rtl8139_reset
|
||||
; reset the card
|
||||
.send_packet:
|
||||
; calculate tx_buffer address
|
||||
pop ebx
|
||||
push esi
|
||||
mov eax, MAX_ETH_FRAME_SIZE
|
||||
mul dword [curr_tx_desc]
|
||||
mov esi, edi
|
||||
lea edi, [rtl8139_tx_buff+eax]
|
||||
mov eax, edi
|
||||
cld
|
||||
; copy destination address
|
||||
movsd
|
||||
movsw
|
||||
; copy source address
|
||||
mov esi, node_addr
|
||||
movsd
|
||||
movsw
|
||||
; copy packet type
|
||||
mov [edi], bx
|
||||
add edi, 2
|
||||
; copy the packet data
|
||||
pop esi edx ecx
|
||||
push ecx
|
||||
shr ecx, 2
|
||||
rep movsd
|
||||
pop ecx
|
||||
push ecx
|
||||
and ecx, 3
|
||||
rep movsb
|
||||
; set address
|
||||
sub eax, OS_BASE
|
||||
add edx, RTL8139_REG_TSAD0 - RTL8139_REG_TSD0
|
||||
out dx, eax
|
||||
; set size and early threshold
|
||||
pop eax ; pick up the size
|
||||
add eax, ETH_HLEN
|
||||
cmp eax, ETH_ZLEN
|
||||
jnc .no_pad
|
||||
mov eax, ETH_ZLEN
|
||||
.no_pad:
|
||||
or eax, (RTL8139_ERTXTH shl RTL8139_BIT_ERTXTH)
|
||||
add edx, RTL8139_REG_TSD0 - RTL8139_REG_TSAD0
|
||||
out dx, eax
|
||||
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
|
||||
inc dword [curr_tx_desc]
|
||||
and dword [curr_tx_desc], 3
|
||||
.finish:
|
||||
ret
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; rtl8139_poll
|
||||
;
|
||||
; Description
|
||||
; Polls the ethernet card for a received packet
|
||||
; Received data, if any, ends up in Ether_buffer
|
||||
; Destroyed register(s)
|
||||
; eax, edx, ecx
|
||||
;
|
||||
;***************************************************************************
|
||||
rtl8139_poll:
|
||||
mov word [eth_rx_data_len], 0
|
||||
mov edx, [io_addr]
|
||||
add edx, RTL8139_REG_COMMAND
|
||||
in al, dx
|
||||
test al, (1 shl RTL8139_BIT_BUFE)
|
||||
jnz .finish
|
||||
; new packet received copy it from rx_buffer into Ether_buffer
|
||||
mov eax, rtl8139_rx_buff
|
||||
add eax, [rtl8139_rx_buff_offset]
|
||||
; check if packet is ok
|
||||
test byte [eax], (1 shl RTL8139_BIT_ROK)
|
||||
jz .reset_rx
|
||||
; packet is ok copy it into the Ether_buffer
|
||||
movzx ecx, word [eax+2] ; packet length
|
||||
sub ecx, 4 ; don't copy CRC
|
||||
mov word [eth_rx_data_len], cx
|
||||
push ecx
|
||||
shr ecx, 2 ; first copy dword-wise
|
||||
lea esi, [eax+4] ; don't copy the packet header
|
||||
mov edi, Ether_buffer
|
||||
cld
|
||||
rep movsd ; copy the dwords
|
||||
pop ecx
|
||||
and ecx, 3
|
||||
rep movsb ; copy the rest bytes
|
||||
; update rtl8139_rx_buff_offset
|
||||
movzx eax, word [eax+2] ; packet length
|
||||
add eax, [rtl8139_rx_buff_offset]
|
||||
add eax, 4+3 ; packet header is 4 bytes long + dword alignment
|
||||
and eax, not 3 ; dword alignment
|
||||
cmp eax, RTL8139_RX_BUFFER_SIZE
|
||||
jl .no_wrap
|
||||
sub eax, RTL8139_RX_BUFFER_SIZE
|
||||
.no_wrap:
|
||||
mov [rtl8139_rx_buff_offset], eax
|
||||
; update CAPR register
|
||||
sub eax, 0x10 ; value 0x10 is a constant for CAPR
|
||||
add edx, RTL8139_REG_CAPR - RTL8139_REG_COMMAND
|
||||
out dx, ax
|
||||
.finish:
|
||||
; clear active interrupt sources
|
||||
mov edx, [io_addr]
|
||||
add edx, RTL8139_REG_ISR
|
||||
in ax, dx
|
||||
out dx, ax
|
||||
ret
|
||||
.reset_rx:
|
||||
in al, dx ; read command register
|
||||
push eax
|
||||
and al, not (1 shl RTL8139_BIT_RE)
|
||||
out dx, al
|
||||
pop eax
|
||||
out dx, al
|
||||
add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND
|
||||
mov ax, RTL8139_RX_CONFIG
|
||||
out dx, ax
|
||||
ret
|
||||
|
||||
rtl8139_cable:
|
||||
pusha
|
||||
mov edx, [io_addr]
|
||||
add edx, 0x58
|
||||
in al, dx
|
||||
test al, 1 SHL 2
|
||||
jnz .notconnected
|
||||
popa
|
||||
xor al, al
|
||||
inc al
|
||||
ret
|
||||
.notconnected:
|
||||
popa
|
||||
xor al, al
|
||||
ret
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,525 +0,0 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; ETHERNET.INC ;;
|
||||
;; ;;
|
||||
;; Ethernet network layer for Menuet OS ;;
|
||||
;; ;;
|
||||
;; This file contains the following: ;;
|
||||
;; PCI bus scanning for valid devices ;;
|
||||
;; Table of supported ethernet drivers ;;
|
||||
;; Code to identify and activate a supported driver ;;
|
||||
;; ARP handler ;;
|
||||
;; Driver interface to the IP layer ;;
|
||||
;; Gateway support ;;
|
||||
;; ;;
|
||||
;; Individual driver files are included here ;;
|
||||
;; ;;
|
||||
;; The PCI bus scanning code was ported from the etherboot ;;
|
||||
;; 5.0.6 project. The copyright statement for that code is ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;; remaining parts Copyright 2002 Mike Hibbett ;;
|
||||
;; mikeh@oceanfree.net ;;
|
||||
;; ;;
|
||||
;; See file COPYING for details ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
$Revision$
|
||||
|
||||
|
||||
;********************************************************************
|
||||
; Interface
|
||||
; ethernet_driver called by stack_handler in stack.inc
|
||||
; eth_probe called by app_stack_handler in stack.inc
|
||||
;
|
||||
;********************************************************************
|
||||
|
||||
ETHER_IP equ 0x0008 ; Reversed from 0800 for intel
|
||||
ETHER_ARP equ 0x0608 ; Reversed from 0806 for intel
|
||||
ETHER_RARP equ 0x3580
|
||||
|
||||
struc ETH_FRAME
|
||||
{ .DstMAC dp ? ;destination MAC-address [6 bytes]
|
||||
.SrcMAC dp ? ;source MAC-address [6 bytes]
|
||||
.Type dw ? ;type of the upper-layer protocol [2 bytes]
|
||||
.Data db ? ;data [46-1500 bytes]
|
||||
}
|
||||
|
||||
virtual at Ether_buffer
|
||||
ETH_FRAME ETH_FRAME
|
||||
end virtual
|
||||
|
||||
|
||||
; Some useful information on data structures
|
||||
|
||||
; Ethernet Packet - ARP Request example
|
||||
;
|
||||
; 0 1 2 3
|
||||
; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
;
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | Dest H/W Address |
|
||||
; | ( 14 byte header ) |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | | Source H/W Address |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | Protocol - ARP 08 06 |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | H/W Type 00 01 | Protocol Type 08 00 |
|
||||
; | ( ARP Request packet ) |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | HLen 0x06 | PLen 0x04 | OpCode 00 01 |
|
||||
; | ( 0001 for request, 0002 for reply ) |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | Source Hardware Address ( MAC Address ) |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | | Source IP Address |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | | Destination Hardware Address |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | Destination IP Address |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
; Include individual drivers source files at this point.
|
||||
; If you create a new driver, include it below.
|
||||
|
||||
include "drivers/rtl8029.inc"
|
||||
include "drivers/i8255x.inc"
|
||||
include "drivers/rtl8139.inc"
|
||||
include "drivers/3c59x.inc"
|
||||
include "drivers/sis900.inc"
|
||||
include "drivers/pcnet32.inc"
|
||||
include "drivers/rtl8169.inc"
|
||||
include "drivers/forcedeth.inc"
|
||||
include "drivers/r6040.inc"
|
||||
|
||||
; PCICards
|
||||
; ========
|
||||
; PCI vendor and hardware types for hardware supported by the above drivers
|
||||
; If you add a driver, ensure you update this datastructure, otherwise the
|
||||
; card will not be probed.
|
||||
; Each driver is defined by 4 double words. These are
|
||||
; PCIVendorDevice probeFunction ResetFunction PollFunction transmitFunction
|
||||
; The last entry must be kept at all zeros, to indicate the end of the list
|
||||
; As a PCI driver may support more than one hardware implementation, there may
|
||||
; be several lines which refer to the same functions.
|
||||
; The first driver found on the PCI bus will be the one used.
|
||||
|
||||
PCICARDS_ENTRY_SIZE equ 24 ; Size of each PCICARDS entry
|
||||
|
||||
iglobal
|
||||
PCICards:
|
||||
dd 0x12098086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0
|
||||
dd 0x10298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0
|
||||
dd 0x12298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0
|
||||
dd 0x10308086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0
|
||||
dd 0x24498086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0
|
||||
dd 0x10688086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0
|
||||
|
||||
dd 0x802910ec, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit, 0
|
||||
|
||||
dd 0x813910ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0x813810ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0x12111113, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0x13601500, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0x13604033, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0x13001186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0x13401186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0xab0613d1, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0xa1171259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0xa11e1259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0xab0614ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0xab0714ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0x123411db, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0x91301432, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0x101202ac, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0x0106018a, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0x1211126c, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0x81391743, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
dd 0x8139021b, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable
|
||||
|
||||
dd 0x816810ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0
|
||||
dd 0x816910ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0
|
||||
dd 0x011616ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0
|
||||
dd 0x43001186, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0
|
||||
dd 0x816710ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0
|
||||
|
||||
dd 0x590010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x592010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x597010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x595010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x595110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x595210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x900010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x900110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x900410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x900510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x900610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x900A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x905010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x905110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x905510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x905810b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x905A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x920010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x980010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x980510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x764610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x505510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x605510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x605610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x5b5710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x505710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x515710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x525710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x656010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x656210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x656410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
dd 0x450010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0
|
||||
|
||||
dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0
|
||||
dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0
|
||||
|
||||
dd 0x20001022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0
|
||||
dd 0x26251022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0
|
||||
dd 0x20011022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0
|
||||
|
||||
dd 0x006610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; nVidia Corporation nForce2 Ethernet Controller
|
||||
dd 0x01c310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x00D610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x008610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x008c10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x00e610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x00df10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x005610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x005710de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x003710de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x003810de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x026810de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x026910de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x037210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x037310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x03e510de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x03e610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x03ee10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x03ef10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x045010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x045110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x045210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x045310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x054c10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x054d10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x054e10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x054f10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x07dc10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x07dd10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x07de10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x07df10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x076010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; MCP77 Ethernet Controller
|
||||
dd 0x076110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x076210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x076310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x0ab010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x0ab110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x0ab210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x0ab310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
dd 0x0d7d10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested
|
||||
|
||||
dd 0x604017F3, r6040_probe, r6040_reset, r6040_poll, r6040_transmit, 0
|
||||
|
||||
rb PCICARDS_ENTRY_SIZE ; end of list marker, do not remove
|
||||
endg
|
||||
|
||||
uglobal
|
||||
;Net-stack's interface's settings
|
||||
node_addr:
|
||||
db 0,0,0,0,0,0
|
||||
gateway_ip:
|
||||
dd 0
|
||||
dns_ip:
|
||||
dd 0
|
||||
|
||||
eth_rx_data_len:
|
||||
dw 0
|
||||
eth_status:
|
||||
dd 0
|
||||
io_addr:
|
||||
dd 0
|
||||
hdrtype:
|
||||
db 0
|
||||
vendor_device:
|
||||
dd 0
|
||||
pci_data:
|
||||
dd 0
|
||||
pci_dev:
|
||||
dd 0
|
||||
pci_bus:
|
||||
dd 0
|
||||
|
||||
; These will hold pointers to the selected driver functions
|
||||
drvr_probe:
|
||||
dd 0
|
||||
drvr_reset:
|
||||
dd 0
|
||||
drvr_poll:
|
||||
dd 0
|
||||
drvr_transmit:
|
||||
dd 0
|
||||
drvr_cable:
|
||||
dd 0
|
||||
|
||||
endg
|
||||
|
||||
iglobal
|
||||
broadcast_add:
|
||||
db 0xff,0xff,0xff,0xff,0xff,0xff
|
||||
subnet_mask:
|
||||
dd 0x00ffffff ; 255.255.255.0
|
||||
endg
|
||||
|
||||
include "arp.inc" ;arp-protocol functions
|
||||
include "pci.inc" ;PCI bus access functions
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; eth_tx
|
||||
;
|
||||
; Description
|
||||
; Looks at the NET1OUT_QUEUE for data to send.
|
||||
; Stores that destination IP in a location used by the tx routine
|
||||
; Looks up the MAC address in the ARP table; stores that where
|
||||
; the tx routine can get it
|
||||
; Get the length of the data. Store that where the tx routine wants it
|
||||
; Call tx
|
||||
; Places buffer on empty queue when the tx routine finished
|
||||
;
|
||||
;***************************************************************************
|
||||
proc eth_tx stdcall uses ebx esi edi
|
||||
local MACAddress dp ? ;allocate 6 bytes in the stack
|
||||
|
||||
; Look for a buffer to tx
|
||||
mov eax, NET1OUT_QUEUE
|
||||
call dequeue
|
||||
cmp ax, NO_BUFFER
|
||||
je .exit ; Exit if no buffer available
|
||||
|
||||
push eax;save buffer number
|
||||
|
||||
; convert buffer pointer eax to the absolute address
|
||||
imul eax, IPBUFFSIZE
|
||||
add eax, IPbuffs
|
||||
|
||||
; Extract the destination IP
|
||||
; find the destination IP in the ARP table, get MAC
|
||||
; store this MAC in 'MACAddress'
|
||||
mov ebx, eax ; Save buffer address
|
||||
mov edx, [ebx + 16] ; get destination address
|
||||
|
||||
; If the destination address is 255.255.255.255,
|
||||
; set the MACAddress to all ones ( broadcast )
|
||||
cld
|
||||
mov esi, broadcast_add
|
||||
lea edi, [MACAddress]
|
||||
movsd
|
||||
movsw
|
||||
cmp edx, 0xffffffff
|
||||
je .send ; If it is broadcast, just send
|
||||
|
||||
lea eax, [MACAddress];cause this is local variable
|
||||
stdcall arp_table_manager, ARP_TABLE_IP_TO_MAC, edx, eax;opcode,IP,MAC_ptr - Get the MAC address.
|
||||
|
||||
cmp eax, ARP_VALID_MAPPING
|
||||
je .send
|
||||
|
||||
; No valid entry. Has the request been sent, but timed out?
|
||||
cmp eax, ARP_RESPONSE_TIMEOUT
|
||||
je .freebuf
|
||||
|
||||
.wait_response: ;we wait arp-response
|
||||
; Re-queue the packet, and exit
|
||||
pop ebx
|
||||
mov eax, NET1OUT_QUEUE
|
||||
call queue ; Get the buffer back
|
||||
jmp .exit
|
||||
|
||||
.send: ;if ARP_VALID_MAPPING then send the packet
|
||||
lea edi, [MACAddress] ; Pointer to 48 bit destination address
|
||||
movzx ecx, word[ebx+2] ; Size of IP packet to send
|
||||
xchg ch, cl ; because mirror byte-order
|
||||
mov esi, ebx ; Pointer to packet data
|
||||
mov bx, ETHER_IP ; Type of packet
|
||||
push ebp
|
||||
call dword [drvr_transmit]; Call the drivers transmit function
|
||||
pop ebp
|
||||
|
||||
; OK, we have sent a packet, so increment the count
|
||||
inc dword [ip_tx_count]
|
||||
|
||||
; And finally, return the buffer to the free queue
|
||||
.freebuf:
|
||||
pop eax
|
||||
call freeBuff
|
||||
|
||||
.exit:
|
||||
ret
|
||||
endp
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; ether_IP_handler
|
||||
;
|
||||
; Description
|
||||
; Called when an IP ethernet packet is received on the ethernet
|
||||
; Header + Data is in Ether_buffer[]
|
||||
; We just need to get a buffer from the 'free' queue, and
|
||||
; store the packet in it, then insert the packet number into the
|
||||
; IPRX queue.
|
||||
; If no queue entry is available, the packet is silently discarded
|
||||
; All registers may be destroyed
|
||||
;
|
||||
;***************************************************************************
|
||||
;uglobal
|
||||
; ether_IP_handler_cnt dd ?
|
||||
;endg
|
||||
ether_IP_handler:
|
||||
mov eax, EMPTY_QUEUE
|
||||
call dequeue
|
||||
cmp ax, NO_BUFFER
|
||||
je eiph00x
|
||||
|
||||
; convert buffer pointer eax to the absolute address
|
||||
push eax
|
||||
mov ecx, IPBUFFSIZE
|
||||
mul ecx
|
||||
add eax, IPbuffs
|
||||
|
||||
mov edi, eax
|
||||
|
||||
; get a pointer to the start of the DATA
|
||||
mov esi, ETH_FRAME.Data
|
||||
|
||||
; Now store it all away
|
||||
mov ecx, IPBUFFSIZE / 4 ; Copy all of the available
|
||||
; data across - worse case
|
||||
cld
|
||||
rep movsd
|
||||
|
||||
; inc [ether_IP_handler_cnt]
|
||||
; DEBUGF 1, "K : ether_IP_handler (%u)\n", [ether_IP_handler_cnt]
|
||||
|
||||
; And finally, place the buffer in the IPRX queue
|
||||
pop ebx
|
||||
mov eax, IPIN_QUEUE
|
||||
call queue
|
||||
|
||||
eiph00x:
|
||||
ret
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; eth_probe
|
||||
; Description
|
||||
; Searches for an ethernet card. If found, the card is enabled and
|
||||
; the ethernet -> IP link established
|
||||
;
|
||||
; This function scans the PCI bus looking for a supported device.
|
||||
; ISA bus is currently not supported.
|
||||
;
|
||||
; eax is 0 if no hardware found
|
||||
;***************************************************************************
|
||||
eth_probe:
|
||||
; Find a card on the PCI bus, and get it's address
|
||||
call scan_bus ; Find the ethernet cards PIC address
|
||||
xor eax, eax
|
||||
cmp [io_addr], eax
|
||||
je ep_00x ; Return 0 in eax if no cards found
|
||||
|
||||
call dword [drvr_probe] ; Call the drivers probe function
|
||||
|
||||
mov eax, [io_addr] ; return a non zero value
|
||||
|
||||
ep_00x:
|
||||
ret
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; ethernet_driver
|
||||
;
|
||||
; Description
|
||||
; The ethernet RX and TX handler
|
||||
; This is a kernel function, called by stack_handler
|
||||
;
|
||||
;***************************************************************************
|
||||
ethernet_driver:
|
||||
; Do nothing if the driver is inactive
|
||||
cmp [ethernet_active], byte 0
|
||||
je eth_exit
|
||||
|
||||
call eth_rx
|
||||
call eth_tx
|
||||
|
||||
eth_exit:
|
||||
ret
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; eth_rx
|
||||
;
|
||||
; Description
|
||||
; Polls the ethernet card for received data. Extracts if present
|
||||
; Depending on the Protocol within the packet:
|
||||
; ARP : Pass to ARP_handler. This may result in an ARP reply
|
||||
; being tx'ed
|
||||
; IP : Store in an IP buffer
|
||||
;
|
||||
;***************************************************************************
|
||||
eth_rx:
|
||||
xor ax, ax
|
||||
mov [eth_rx_data_len], ax
|
||||
call dword [drvr_poll] ; Call the drivers poll function
|
||||
|
||||
mov ax, [eth_rx_data_len]
|
||||
cmp ax, 0
|
||||
je .exit
|
||||
|
||||
|
||||
; Check the protocol. Call appropriate handler
|
||||
|
||||
mov ax, [ETH_FRAME.Type]; The address of the protocol word
|
||||
|
||||
cmp ax, ETHER_IP
|
||||
je .is_ip ; It's IP
|
||||
|
||||
cmp ax, ETHER_ARP
|
||||
je .is_arp ; It is ARP
|
||||
|
||||
; DEBUGF 1,"K : eth_rx - dumped (%u)\n", ax
|
||||
inc [dumped_rx_count]
|
||||
jmp .exit ; If not IP or ARP, ignore
|
||||
|
||||
.is_ip:
|
||||
; DEBUGF 1,"K : eth_rx - IP packet\n"
|
||||
inc dword [ip_rx_count]
|
||||
call ether_IP_handler
|
||||
jmp .exit
|
||||
|
||||
.is_arp:
|
||||
; DEBUGF 1,"K : eth_rx - ARP packet\n"
|
||||
; At this point, the packet is still in the Ether_buffer
|
||||
call arp_handler
|
||||
|
||||
.exit:
|
||||
ret
|
@ -1,351 +0,0 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
$Revision$
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
;
|
||||
; PCI CODE FOLLOWS
|
||||
;
|
||||
; the following functions provide access to the PCI interface.
|
||||
; These functions are used by scan_bus, and also some ethernet drivers
|
||||
;
|
||||
;***************************************************************************
|
||||
|
||||
; PCI Bus defines
|
||||
PCI_HEADER_TYPE equ 0x0e ;8 bit
|
||||
PCI_BASE_ADDRESS_0 equ 0x10 ;32 bit
|
||||
PCI_BASE_ADDRESS_5 equ 0x24 ;32 bits
|
||||
PCI_BASE_ADDRESS_SPACE_IO equ 0x01
|
||||
PCI_VENDOR_ID equ 0x00 ;16 bit
|
||||
PCI_BASE_ADDRESS_IO_MASK equ 0xFFFFFFFC
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; config_cmd
|
||||
;
|
||||
; Description
|
||||
; creates a command dword for use with the PCI bus
|
||||
; bus # in ebx
|
||||
; devfn in ecx
|
||||
; where in edx
|
||||
;
|
||||
; command dword returned in eax
|
||||
; Only eax destroyed
|
||||
;***************************************************************************
|
||||
config_cmd:
|
||||
push ecx
|
||||
mov eax, ebx
|
||||
shl eax, 16
|
||||
or eax, 0x80000000
|
||||
shl ecx, 8
|
||||
or eax, ecx
|
||||
pop ecx
|
||||
or eax, edx
|
||||
and eax, 0xFFFFFFFC
|
||||
ret
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; pcibios_read_config_byte
|
||||
;
|
||||
; Description
|
||||
; reads a byte from the PCI config space
|
||||
; bus # in ebx
|
||||
; devfn in ecx
|
||||
; where in edx ( ls 16 bits significant )
|
||||
;
|
||||
; byte returned in al ( rest of eax zero )
|
||||
; Only eax/edx destroyed
|
||||
;***************************************************************************
|
||||
pcibios_read_config_byte:
|
||||
call config_cmd
|
||||
push dx
|
||||
mov dx, 0xCF8
|
||||
out dx, eax
|
||||
pop dx
|
||||
|
||||
xor eax, eax
|
||||
and dx, 0x03
|
||||
add dx, 0xCFC
|
||||
; and dx, 0xFFC
|
||||
in al, dx
|
||||
ret
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; pcibios_read_config_word
|
||||
;
|
||||
; Description
|
||||
; reads a word from the PCI config space
|
||||
; bus # in ebx
|
||||
; devfn in ecx
|
||||
; where in edx ( ls 16 bits significant )
|
||||
;
|
||||
; word returned in ax ( rest of eax zero )
|
||||
; Only eax/edx destroyed
|
||||
;***************************************************************************
|
||||
pcibios_read_config_word:
|
||||
call config_cmd
|
||||
push dx
|
||||
mov dx, 0xCF8
|
||||
out dx, eax
|
||||
pop dx
|
||||
|
||||
xor eax, eax
|
||||
and dx, 0x02
|
||||
add dx, 0xCFC
|
||||
; and dx, 0xFFC
|
||||
in ax, dx
|
||||
ret
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; pcibios_read_config_dword
|
||||
;
|
||||
; Description
|
||||
; reads a dword from the PCI config space
|
||||
; bus # in ebx
|
||||
; devfn in ecx
|
||||
; where in edx ( ls 16 bits significant )
|
||||
;
|
||||
; dword returned in eax
|
||||
; Only eax/edx destroyed
|
||||
;***************************************************************************
|
||||
pcibios_read_config_dword:
|
||||
push edx
|
||||
call config_cmd
|
||||
push dx
|
||||
mov dx, 0xCF8
|
||||
out dx, eax
|
||||
pop dx
|
||||
xor eax, eax
|
||||
mov dx, 0xCFC
|
||||
in eax, dx
|
||||
pop edx
|
||||
ret
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; pcibios_write_config_byte
|
||||
;
|
||||
; Description
|
||||
; write a byte in al to the PCI config space
|
||||
; bus # in ebx
|
||||
; devfn in ecx
|
||||
; where in edx ( ls 16 bits significant )
|
||||
;
|
||||
; Only eax/edx destroyed
|
||||
;***************************************************************************
|
||||
pcibios_write_config_byte:
|
||||
push ax
|
||||
call config_cmd
|
||||
push dx
|
||||
mov dx, 0xCF8
|
||||
out dx, eax
|
||||
pop dx
|
||||
pop ax
|
||||
|
||||
and dx, 0x03
|
||||
add dx, 0xCFC
|
||||
out dx, al
|
||||
ret
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; pcibios_write_config_word
|
||||
;
|
||||
; Description
|
||||
; write a word in ax to the PCI config space
|
||||
; bus # in ebx
|
||||
; devfn in ecx
|
||||
; where in edx ( ls 16 bits significant )
|
||||
;
|
||||
; Only eax/edx destroyed
|
||||
;***************************************************************************
|
||||
pcibios_write_config_word:
|
||||
push ax
|
||||
call config_cmd
|
||||
push dx
|
||||
mov dx, 0xCF8
|
||||
out dx, eax
|
||||
pop dx
|
||||
pop ax
|
||||
|
||||
and dx, 0x02
|
||||
add dx, 0xCFC
|
||||
out dx, ax
|
||||
ret
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; delay_us
|
||||
;
|
||||
; Description
|
||||
; delays for 30 to 60 us
|
||||
;
|
||||
; I would prefer this routine to be able to delay for
|
||||
; a selectable number of microseconds, but this works for now.
|
||||
;
|
||||
; If you know a better way to do 2us delay, pleae tell me!
|
||||
;***************************************************************************
|
||||
delay_us:
|
||||
push eax
|
||||
push ecx
|
||||
|
||||
mov ecx, 2
|
||||
|
||||
in al, 0x61
|
||||
and al, 0x10
|
||||
mov ah, al
|
||||
cld
|
||||
|
||||
dcnt1:
|
||||
in al, 0x61
|
||||
and al, 0x10
|
||||
cmp al, ah
|
||||
jz dcnt1
|
||||
|
||||
mov ah, al
|
||||
loop dcnt1
|
||||
|
||||
pop ecx
|
||||
pop eax
|
||||
|
||||
ret
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; scan_bus
|
||||
;
|
||||
; Description
|
||||
; Scans the PCI bus for a supported device
|
||||
; If a supported device is found, the drvr_ variables are initialised
|
||||
; to that drivers functions ( as defined in the PCICards table)
|
||||
;
|
||||
; io_addr holds card I/O space. 32 bit, but only LS 16 bits valid
|
||||
; pci_data holds the PCI vendor + device code
|
||||
; pci_dev holds PCI bus dev #
|
||||
; pci_bus holds PCI bus #
|
||||
;
|
||||
; io_addr will be zero if no card found
|
||||
;
|
||||
;***************************************************************************
|
||||
scan_bus:
|
||||
xor eax, eax
|
||||
mov [hdrtype], al
|
||||
mov [pci_data], eax
|
||||
|
||||
xor ebx, ebx ; ebx = bus# 0 .. 255
|
||||
|
||||
sb_bus_loop:
|
||||
xor ecx, ecx ; ecx = devfn# 0 .. 254 ( not 255? )
|
||||
|
||||
sb_devf_loop:
|
||||
mov eax, ecx
|
||||
and eax, 0x07
|
||||
|
||||
cmp eax, 0
|
||||
jne sb_001
|
||||
|
||||
mov edx, PCI_HEADER_TYPE
|
||||
call pcibios_read_config_byte
|
||||
mov [hdrtype], al
|
||||
jmp sb_002
|
||||
|
||||
sb_001:
|
||||
mov al, [hdrtype]
|
||||
and al, 0x80
|
||||
cmp al, 0x80
|
||||
jne sb_inc_devf
|
||||
|
||||
sb_002:
|
||||
mov edx, PCI_VENDOR_ID
|
||||
call pcibios_read_config_dword
|
||||
mov [vendor_device], eax
|
||||
cmp eax, 0xffffffff
|
||||
je sb_empty
|
||||
cmp eax, 0
|
||||
jne sb_check_vendor
|
||||
|
||||
sb_empty:
|
||||
mov [hdrtype], byte 0
|
||||
jmp sb_inc_devf
|
||||
|
||||
sb_check_vendor:
|
||||
; iterate though PCICards until end or match found
|
||||
mov esi, PCICards
|
||||
|
||||
sb_check:
|
||||
cmp [esi], dword 0
|
||||
je sb_inc_devf ; Quit if at last entry
|
||||
cmp eax, [esi]
|
||||
je sb_got_card
|
||||
add esi, PCICARDS_ENTRY_SIZE
|
||||
jmp sb_check
|
||||
|
||||
sb_got_card:
|
||||
; indicate that we have found the card
|
||||
mov [pci_data], eax
|
||||
mov [pci_dev], ecx
|
||||
mov [pci_bus], ebx
|
||||
|
||||
; Define the driver functions
|
||||
push eax
|
||||
mov eax, [esi+4]
|
||||
mov [drvr_probe], eax
|
||||
mov eax, [esi+8]
|
||||
mov [drvr_reset], eax
|
||||
mov eax, [esi+12]
|
||||
mov [drvr_poll], eax
|
||||
mov eax, [esi+16]
|
||||
mov [drvr_transmit], eax
|
||||
mov eax, [esi+20]
|
||||
mov [drvr_cable], eax
|
||||
pop eax
|
||||
|
||||
mov edx, PCI_BASE_ADDRESS_0
|
||||
|
||||
sb_reg_check:
|
||||
call pcibios_read_config_dword
|
||||
mov [io_addr], eax
|
||||
and eax, PCI_BASE_ADDRESS_IO_MASK
|
||||
cmp eax, 0
|
||||
je sb_inc_reg
|
||||
mov eax, [io_addr]
|
||||
and eax, PCI_BASE_ADDRESS_SPACE_IO
|
||||
cmp eax, 0
|
||||
je sb_inc_reg
|
||||
|
||||
mov eax, [io_addr]
|
||||
and eax, PCI_BASE_ADDRESS_IO_MASK
|
||||
mov [io_addr], eax
|
||||
|
||||
sb_exit1:
|
||||
ret
|
||||
|
||||
sb_inc_reg:
|
||||
add edx, 4
|
||||
cmp edx, PCI_BASE_ADDRESS_5
|
||||
jbe sb_reg_check
|
||||
|
||||
sb_inc_devf:
|
||||
inc ecx
|
||||
cmp ecx, 255
|
||||
jb sb_devf_loop
|
||||
inc ebx
|
||||
cmp ebx, 256
|
||||
jb sb_bus_loop
|
||||
|
||||
; We get here if we didn't find our card
|
||||
; set io_addr to 0 as an indication
|
||||
xor eax, eax
|
||||
mov [io_addr], eax
|
||||
|
||||
sb_exit2:
|
||||
ret
|
233
kernel/trunk/network/ethernet.inc
Normal file
233
kernel/trunk/network/ethernet.inc
Normal file
@ -0,0 +1,233 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; ETHERNET.INC ;;
|
||||
;; ;;
|
||||
;; Ethernet network layer for KolibriOS ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr@kolibrios.org ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
$Revision: 3346 $
|
||||
|
||||
ETH_FRAME_MINIMUM = 60
|
||||
|
||||
struct ETH_header
|
||||
|
||||
DstMAC dp ? ; destination MAC-address
|
||||
SrcMAC dp ? ; source MAC-address
|
||||
Type dw ? ; type of the upper-layer protocol
|
||||
|
||||
ends
|
||||
|
||||
struct ETH_DEVICE NET_DEVICE
|
||||
|
||||
mac dp ?
|
||||
|
||||
ends
|
||||
|
||||
align 4
|
||||
iglobal
|
||||
|
||||
ETH_BROADCAST dp 0xffffffffffff
|
||||
endg
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ETH_input
|
||||
;
|
||||
; This function is called by ethernet drivers,
|
||||
; It pushes the received ethernet packets onto the eth_in_queue
|
||||
;
|
||||
; IN: [esp] = Pointer to buffer
|
||||
; [esp+4] = size of buffer
|
||||
; ebx = pointer to eth_device
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
ETH_input:
|
||||
mov eax, [esp]
|
||||
mov ecx, [esp+4]
|
||||
|
||||
DEBUGF 1,"ETH_input: size=%u\n", ecx
|
||||
cmp ecx, ETH_FRAME_MINIMUM
|
||||
jb .dump
|
||||
sub ecx, sizeof.ETH_header
|
||||
|
||||
lea edx, [eax + sizeof.ETH_header]
|
||||
mov ax, [eax + ETH_header.Type]
|
||||
|
||||
cmp ax, ETHER_IPv4
|
||||
je IPv4_input
|
||||
|
||||
cmp ax, ETHER_ARP
|
||||
je ARP_input
|
||||
|
||||
cmp ax, ETHER_IPv6
|
||||
je IPv6_input
|
||||
|
||||
cmp ax, ETHER_PPP_DISCOVERY
|
||||
je PPPoE_discovery_input
|
||||
|
||||
cmp ax, ETHER_PPP_SESSION
|
||||
je PPPoE_session_input
|
||||
|
||||
DEBUGF 2,"ETH_input: Unknown packet type=%x\n", ax
|
||||
|
||||
.dump:
|
||||
DEBUGF 2,"ETH_input: dumping\n"
|
||||
call kernel_free
|
||||
add esp, 4
|
||||
ret
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ETH_output
|
||||
;
|
||||
; IN: eax = pointer to source mac
|
||||
; ebx = device ptr
|
||||
; ecx = packet size
|
||||
; edx = pointer to destination mac
|
||||
; 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
|
||||
ETH_output:
|
||||
|
||||
DEBUGF 1,"ETH_output: size=%u device=%x\n", ecx, ebx
|
||||
|
||||
cmp ecx, [ebx + NET_DEVICE.mtu]
|
||||
ja .exit
|
||||
|
||||
push ecx
|
||||
push di eax edx
|
||||
|
||||
add ecx, sizeof.ETH_header
|
||||
stdcall kernel_alloc, ecx
|
||||
test eax, eax
|
||||
jz .out_of_ram
|
||||
mov edi, eax
|
||||
|
||||
pop esi
|
||||
movsd
|
||||
movsw
|
||||
pop esi
|
||||
movsd
|
||||
movsw
|
||||
pop ax
|
||||
stosw
|
||||
|
||||
lea eax, [edi - sizeof.ETH_header] ; Set eax to buffer start
|
||||
pop ecx
|
||||
lea edx, [ecx + sizeof.ETH_header] ; Set edx to complete buffer size
|
||||
|
||||
cmp edx, ETH_FRAME_MINIMUM
|
||||
jbe .adjust_size
|
||||
.done:
|
||||
DEBUGF 1,"ETH_output: ptr=%x size=%u\n", eax, edx
|
||||
ret
|
||||
|
||||
.adjust_size:
|
||||
mov edx, ETH_FRAME_MINIMUM
|
||||
test edx, edx ; clear zero flag
|
||||
jmp .done
|
||||
|
||||
.out_of_ram:
|
||||
DEBUGF 2,"ETH_output: Out of ram!\n"
|
||||
add esp, 4+4+2+4
|
||||
sub edi, edi
|
||||
ret
|
||||
|
||||
.exit:
|
||||
DEBUGF 2,"ETH_output: Packet too large!\n"
|
||||
sub edi, edi
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ETH_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
|
||||
ETH_api:
|
||||
|
||||
cmp bh, MAX_NET_DEVICES
|
||||
ja .error
|
||||
movzx eax, bh
|
||||
mov eax, dword [NET_DRV_LIST + 4*eax]
|
||||
cmp [eax + NET_DEVICE.type], NET_TYPE_ETH
|
||||
jne .error
|
||||
|
||||
and ebx, 0xff
|
||||
cmp ebx, .number
|
||||
ja .error
|
||||
jmp dword [.table + 4*ebx]
|
||||
|
||||
.table:
|
||||
dd .packets_tx ; 0
|
||||
dd .packets_rx ; 1
|
||||
dd .bytes_tx ; 2
|
||||
dd .bytes_rx ; 3
|
||||
dd .read_mac ; 4
|
||||
dd .state ; 5
|
||||
.number = ($ - .table) / 4 - 1
|
||||
|
||||
.error:
|
||||
or eax, -1
|
||||
ret
|
||||
|
||||
.packets_tx:
|
||||
mov eax, [eax + NET_DEVICE.packets_tx]
|
||||
|
||||
ret
|
||||
|
||||
.packets_rx:
|
||||
mov eax, [eax + NET_DEVICE.packets_rx]
|
||||
ret
|
||||
|
||||
.bytes_tx:
|
||||
mov ebx, dword [eax + NET_DEVICE.bytes_tx + 4]
|
||||
mov eax, dword [eax + NET_DEVICE.bytes_tx]
|
||||
mov [esp+20+4], ebx ; TODO: fix this ugly code
|
||||
ret
|
||||
|
||||
.bytes_rx:
|
||||
mov ebx, dword [eax + NET_DEVICE.bytes_rx + 4]
|
||||
mov eax, dword [eax + NET_DEVICE.bytes_rx]
|
||||
mov [esp+20+4], ebx ; TODO: fix this ugly code
|
||||
ret
|
||||
|
||||
|
||||
.read_mac:
|
||||
movzx ebx, word [eax + ETH_DEVICE.mac]
|
||||
mov eax, dword [eax + ETH_DEVICE.mac + 2]
|
||||
mov [esp+20+4], ebx ; TODO: fix this ugly code
|
||||
ret
|
||||
|
||||
.state:
|
||||
mov eax, [eax + NET_DEVICE.state]
|
||||
ret
|
||||
|
@ -1,193 +1,431 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; ICMP.INC ;;
|
||||
;; ;;
|
||||
;; Internet Control Message Protocol ( RFC 792 ) ;;
|
||||
;; ;;
|
||||
;; Last revision: 11.11.2006 ;;
|
||||
;; ;;
|
||||
;; This file contains the following: ;;
|
||||
;; icmp_rx - processes ICMP-packets received by the IP layer ;;
|
||||
;; ;;
|
||||
;; Changes history: ;;
|
||||
;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;;
|
||||
;; 11.11.2006 - [Johnny_B] and [smb] ;;
|
||||
;; ;;
|
||||
;; Current status: ;;
|
||||
;; This implemetation of ICMP proto supports message of ECHO type.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
$Revision$
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; ICMP.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 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
struc ICMP_PACKET
|
||||
{ .Type db ? ;+00
|
||||
.Code db ? ;+01
|
||||
.Checksum dw ? ;+02
|
||||
.Identifier dw ? ;+04
|
||||
.SequenceNumber dw ? ;+06
|
||||
.Data db ? ;+08
|
||||
$Revision: 2924 $
|
||||
|
||||
; ICMP types & codes
|
||||
|
||||
ICMP_ECHOREPLY = 0 ; echo reply message
|
||||
|
||||
ICMP_UNREACH = 3
|
||||
ICMP_UNREACH_NET = 0 ; bad net
|
||||
ICMP_UNREACH_HOST = 1 ; bad host
|
||||
ICMP_UNREACH_PROTOCOL = 2 ; bad protocol
|
||||
ICMP_UNREACH_PORT = 3 ; bad port
|
||||
ICMP_UNREACH_NEEDFRAG = 4 ; IP_DF caused drop
|
||||
ICMP_UNREACH_SRCFAIL = 5 ; src route failed
|
||||
ICMP_UNREACH_NET_UNKNOWN = 6 ; unknown net
|
||||
ICMP_UNREACH_HOST_UNKNOWN = 7 ; unknown host
|
||||
ICMP_UNREACH_ISOLATED = 8 ; src host isolated
|
||||
ICMP_UNREACH_NET_PROHIB = 9 ; prohibited access
|
||||
ICMP_UNREACH_HOST_PROHIB = 10 ; ditto
|
||||
ICMP_UNREACH_TOSNET = 11 ; bad tos for net
|
||||
ICMP_UNREACH_TOSHOST = 12 ; bad tos for host
|
||||
ICMP_UNREACH_FILTER_PROHIB = 13 ; admin prohib
|
||||
ICMP_UNREACH_HOST_PRECEDENCE = 14 ; host prec vio.
|
||||
ICMP_UNREACH_PRECEDENCE_CUTOFF = 15 ; prec cutoff
|
||||
|
||||
ICMP_SOURCEQUENCH = 4 ; Packet lost, slow down
|
||||
|
||||
ICMP_REDIRECT = 5 ; shorter route, codes:
|
||||
ICMP_REDIRECT_NET = 0 ; for network
|
||||
ICMP_REDIRECT_HOST = 1 ; for host
|
||||
ICMP_REDIRECT_TOSNET = 2 ; for tos and net
|
||||
ICMP_REDIRECT_TOSHOST = 3 ; for tos and host
|
||||
|
||||
ICMP_ALTHOSTADDR = 6 ; alternate host address
|
||||
ICMP_ECHO = 8 ; echo service
|
||||
ICMP_ROUTERADVERT = 9 ; router advertisement
|
||||
ICMP_ROUTERADVERT_NORMAL = 0 ; normal advertisement
|
||||
ICMP_ROUTERADVERT_NOROUTE_COMMON= 16 ; selective routing
|
||||
|
||||
ICMP_ROUTERSOLICIT = 10 ; router solicitation
|
||||
ICMP_TIMXCEED = 11 ; time exceeded, code:
|
||||
ICMP_TIMXCEED_INTRANS = 0 ; ttl==0 in transit
|
||||
ICMP_TIMXCEED_REASS = 1 ; ttl==0 in reass
|
||||
|
||||
ICMP_PARAMPROB = 12 ; ip header bad
|
||||
ICMP_PARAMPROB_ERRATPTR = 0 ; error at param ptr
|
||||
ICMP_PARAMPROB_OPTABSENT = 1 ; req. opt. absent
|
||||
ICMP_PARAMPROB_LENGTH = 2 ; bad length
|
||||
|
||||
ICMP_TSTAMP = 13 ; timestamp request
|
||||
ICMP_TSTAMPREPLY = 14 ; timestamp reply
|
||||
ICMP_IREQ = 15 ; information request
|
||||
ICMP_IREQREPLY = 16 ; information reply
|
||||
ICMP_MASKREQ = 17 ; address mask request
|
||||
ICMP_MASKREPLY = 18 ; address mask reply
|
||||
ICMP_TRACEROUTE = 30 ; traceroute
|
||||
ICMP_DATACONVERR = 31 ; data conversion error
|
||||
ICMP_MOBILE_REDIRECT = 32 ; mobile host redirect
|
||||
ICMP_IPV6_WHEREAREYOU = 33 ; IPv6 where-are-you
|
||||
ICMP_IPV6_IAMHERE = 34 ; IPv6 i-am-here
|
||||
ICMP_MOBILE_REGREQUEST = 35 ; mobile registration req
|
||||
ICMP_MOBILE_REGREPLY = 36 ; mobile registreation reply
|
||||
ICMP_SKIP = 39 ; SKIP
|
||||
|
||||
ICMP_PHOTURIS = 40 ; Photuris
|
||||
ICMP_PHOTURIS_UNKNOWN_INDEX = 1 ; unknown sec index
|
||||
ICMP_PHOTURIS_AUTH_FAILED = 2 ; auth failed
|
||||
ICMP_PHOTURIS_DECRYPT_FAILED = 3 ; decrypt failed
|
||||
|
||||
|
||||
|
||||
struct ICMP_header
|
||||
|
||||
Type db ?
|
||||
Code db ?
|
||||
Checksum dw ?
|
||||
Identifier dw ?
|
||||
SequenceNumber dw ?
|
||||
|
||||
ends
|
||||
|
||||
|
||||
align 4
|
||||
uglobal
|
||||
ICMP_PACKETS_TX rd MAX_NET_DEVICES
|
||||
ICMP_PACKETS_RX rd MAX_NET_DEVICES
|
||||
endg
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ICMP_init
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
|
||||
macro ICMP_init {
|
||||
|
||||
xor eax, eax
|
||||
mov edi, ICMP_PACKETS_TX
|
||||
mov ecx, 2*MAX_NET_DEVICES
|
||||
rep stosd
|
||||
|
||||
}
|
||||
|
||||
virtual at 0
|
||||
ICMP_PACKET ICMP_PACKET
|
||||
end virtual
|
||||
|
||||
|
||||
; Example:
|
||||
; ECHO message format
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ICMP_input:
|
||||
;
|
||||
; 0 1 2 3
|
||||
; 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | Type | Code | Checksum |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | Identifier | Sequence Number |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | Data ...
|
||||
; +-+-+-+-+-
|
||||
; This procedure will send reply's to ICMP echo's
|
||||
; and insert packets into sockets when needed
|
||||
;
|
||||
|
||||
; IN: Pointer to buffer in [esp]
|
||||
; size of buffer in [esp+4]
|
||||
; ebx = pointer to device struct
|
||||
; ecx = ICMP Packet size
|
||||
; esi = ptr to ICMP Packet data
|
||||
; edi = ptr to ipv4 source and dest address
|
||||
;
|
||||
; ICMP types & codes, RFC 792 and FreeBSD's ICMP sources
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
ICMP_input:
|
||||
|
||||
ICMP_ECHOREPLY equ 0 ; echo reply message
|
||||
DEBUGF 1,"ICMP_input:\n"
|
||||
|
||||
ICMP_UNREACH equ 3
|
||||
ICMP_UNREACH_NET equ 0 ; bad net
|
||||
ICMP_UNREACH_HOST equ 1 ; bad host
|
||||
ICMP_UNREACH_PROTOCOL equ 2 ; bad protocol
|
||||
ICMP_UNREACH_PORT equ 3 ; bad port
|
||||
ICMP_UNREACH_NEEDFRAG equ 4 ; IP_DF caused drop
|
||||
ICMP_UNREACH_SRCFAIL equ 5 ; src route failed
|
||||
ICMP_UNREACH_NET_UNKNOWN equ 6 ; unknown net
|
||||
ICMP_UNREACH_HOST_UNKNOWN equ 7 ; unknown host
|
||||
ICMP_UNREACH_ISOLATED equ 8 ; src host isolated
|
||||
ICMP_UNREACH_NET_PROHIB equ 9 ; prohibited access
|
||||
ICMP_UNREACH_HOST_PROHIB equ 10 ; ditto
|
||||
ICMP_UNREACH_TOSNET equ 11 ; bad tos for net
|
||||
ICMP_UNREACH_TOSHOST equ 12 ; bad tos for host
|
||||
ICMP_UNREACH_FILTER_PROHIB equ 13 ; admin prohib
|
||||
ICMP_UNREACH_HOST_PRECEDENCE equ 14 ; host prec vio.
|
||||
ICMP_UNREACH_PRECEDENCE_CUTOFF equ 15 ; prec cutoff
|
||||
; First, check the checksum (altough some implementations ignore it)
|
||||
|
||||
ICMP_SOURCEQUENCH equ 4 ; packet lost, slow down
|
||||
push esi ecx
|
||||
push [esi + ICMP_header.Checksum]
|
||||
mov [esi + ICMP_header.Checksum], 0
|
||||
xor edx, edx
|
||||
call checksum_1
|
||||
call checksum_2
|
||||
pop si
|
||||
cmp dx, si
|
||||
pop ecx edx
|
||||
jne .checksum_mismatch
|
||||
|
||||
ICMP_REDIRECT equ 5 ; shorter route, codes:
|
||||
ICMP_REDIRECT_NET equ 0 ; for network
|
||||
ICMP_REDIRECT_HOST equ 1 ; for host
|
||||
ICMP_REDIRECT_TOSNET equ 2 ; for tos and net
|
||||
ICMP_REDIRECT_TOSHOST equ 3 ; for tos and host
|
||||
cmp [edx + ICMP_header.Type], ICMP_ECHO ; Is this an echo request?
|
||||
jne .check_sockets
|
||||
|
||||
ICMP_ALTHOSTADDR equ 6 ; alternate host address
|
||||
ICMP_ECHO equ 8 ; echo service
|
||||
ICMP_ROUTERADVERT equ 9 ; router advertisement
|
||||
ICMP_ROUTERADVERT_NORMAL equ 0 ; normal advertisement
|
||||
ICMP_ROUTERADVERT_NOROUTE_COMMON equ 16 ; selective routing
|
||||
; We well re-use the packet so we can create the response as fast as possible
|
||||
; Notice: this only works on pure ethernet
|
||||
|
||||
ICMP_ROUTERSOLICIT equ 10 ; router solicitation
|
||||
ICMP_TIMXCEED equ 11 ; time exceeded, code:
|
||||
ICMP_TIMXCEED_INTRANS equ 0 ; ttl==0 in transit
|
||||
ICMP_TIMXCEED_REASS equ 1 ; ttl==0 in reass
|
||||
DEBUGF 1,"got echo request\n"
|
||||
mov [edx + ICMP_header.Type], ICMP_ECHOREPLY ; Change Packet type to reply
|
||||
|
||||
ICMP_PARAMPROB equ 12 ; ip header bad
|
||||
ICMP_PARAMPROB_ERRATPTR equ 0 ; error at param ptr
|
||||
ICMP_PARAMPROB_OPTABSENT equ 1 ; req. opt. absent
|
||||
ICMP_PARAMPROB_LENGTH equ 2 ; bad length
|
||||
mov esi, [esp] ; Start of buffer
|
||||
|
||||
ICMP_TSTAMP equ 13 ; timestamp request
|
||||
ICMP_TSTAMPREPLY equ 14 ; timestamp reply
|
||||
ICMP_IREQ equ 15 ; information request
|
||||
ICMP_IREQREPLY equ 16 ; information reply
|
||||
ICMP_MASKREQ equ 17 ; address mask request
|
||||
ICMP_MASKREPLY equ 18 ; address mask reply
|
||||
ICMP_TRACEROUTE equ 30 ; traceroute
|
||||
ICMP_DATACONVERR equ 31 ; data conversion error
|
||||
ICMP_MOBILE_REDIRECT equ 32 ; mobile host redirect
|
||||
ICMP_IPV6_WHEREAREYOU equ 33 ; IPv6 where-are-you
|
||||
ICMP_IPV6_IAMHERE equ 34 ; IPv6 i-am-here
|
||||
ICMP_MOBILE_REGREQUEST equ 35 ; mobile registration req
|
||||
ICMP_MOBILE_REGREPLY equ 36 ; mobile registreation reply
|
||||
ICMP_SKIP equ 39 ; SKIP
|
||||
cmp dword[edi + 4], 1 shl 24 + 127
|
||||
je .loopback
|
||||
|
||||
ICMP_PHOTURIS equ 40 ; Photuris
|
||||
ICMP_PHOTURIS_UNKNOWN_INDEX equ 1 ; unknown sec index
|
||||
ICMP_PHOTURIS_AUTH_FAILED equ 2 ; auth failed
|
||||
ICMP_PHOTURIS_DECRYPT_FAILED equ 3 ; decrypt failed
|
||||
; Update stats (and validate device ptr)
|
||||
call NET_ptr_to_num
|
||||
cmp edi,-1
|
||||
je .dump
|
||||
inc [ICMP_PACKETS_RX + 4*edi]
|
||||
inc [ICMP_PACKETS_TX + 4*edi]
|
||||
|
||||
; exchange dest and source address in IP header
|
||||
; exchange dest and source MAC in ETH header
|
||||
push dword [esi + ETH_header.DstMAC]
|
||||
push dword [esi + ETH_header.SrcMAC]
|
||||
pop dword [esi + ETH_header.DstMAC]
|
||||
pop dword [esi + ETH_header.SrcMAC]
|
||||
push word [esi + ETH_header.DstMAC + 4]
|
||||
push word [esi + ETH_header.SrcMAC + 4]
|
||||
pop word [esi + ETH_header.DstMAC + 4]
|
||||
pop word [esi + ETH_header.SrcMAC + 4]
|
||||
add esi, sizeof.ETH_header-2
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; icmp_rx [by Johnny_B]
|
||||
;
|
||||
; Description
|
||||
; ICMP protocol handler
|
||||
; This is a kernel function, called by ip_rx
|
||||
;
|
||||
; IN:
|
||||
; buffer_number - # of IP-buffer. This buffer must be reused or marked as empty afterwards
|
||||
; IPPacketBase - IP_PACKET base address
|
||||
; IPHeaderLength - Header length of IP_PACKET
|
||||
;
|
||||
; OUT:
|
||||
; EAX=not defined
|
||||
;
|
||||
; All used registers will be saved
|
||||
;
|
||||
;***************************************************************************
|
||||
proc icmp_rx stdcall uses ebx esi edi,\
|
||||
buffer_number:DWORD,IPPacketBase:DWORD,IPHeaderLength:DWORD
|
||||
.loopback:
|
||||
add esi, 2
|
||||
push [esi + IPv4_header.SourceAddress]
|
||||
push [esi + IPv4_header.DestinationAddress]
|
||||
pop [esi + IPv4_header.SourceAddress]
|
||||
pop [esi + IPv4_header.DestinationAddress]
|
||||
|
||||
mov esi, [IPPacketBase];esi=IP_PACKET base address
|
||||
mov edi, esi
|
||||
add edi, [IPHeaderLength];edi=ICMP_PACKET base address
|
||||
; Recalculate ip header checksum
|
||||
movzx ecx, [esi + IPv4_header.VersionAndIHL] ; Calculate IP Header length by using IHL field
|
||||
and ecx, 0x0f
|
||||
shl cx, 2
|
||||
mov edi, ecx ; IP header length
|
||||
mov eax, edx ; ICMP packet start addr
|
||||
|
||||
cmp byte[edi + ICMP_PACKET.Type], ICMP_ECHO; Is this an echo request? discard if not
|
||||
jz .icmp_echo
|
||||
push esi ; Calculate the IP checksum
|
||||
xor edx, edx ;
|
||||
call checksum_1 ;
|
||||
call checksum_2 ;
|
||||
pop esi ;
|
||||
mov [esi + IPv4_header.HeaderChecksum], dx ;
|
||||
|
||||
mov eax, [buffer_number]
|
||||
call freeBuff
|
||||
jmp .exit
|
||||
; Recalculate ICMP CheckSum
|
||||
movzx ecx, [esi + IPv4_header.TotalLength] ; Find length of IP Packet
|
||||
xchg ch, cl ;
|
||||
sub ecx, edi ; IP packet length - IP header length = ICMP packet length
|
||||
|
||||
.icmp_echo:
|
||||
mov esi, eax ; Calculate ICMP checksum
|
||||
xor edx, edx ;
|
||||
call checksum_1 ;
|
||||
call checksum_2 ;
|
||||
mov [eax + ICMP_header.Checksum], dx ;
|
||||
|
||||
; swap the source and destination addresses
|
||||
mov ecx, [esi + IP_PACKET.DestinationAddress]
|
||||
mov ebx, [esi + IP_PACKET.SourceAddress]
|
||||
mov [esi + IP_PACKET.DestinationAddress], ebx
|
||||
mov [esi + IP_PACKET.SourceAddress], ecx
|
||||
|
||||
; recalculate the IP header checksum
|
||||
mov eax, [IPHeaderLength]
|
||||
stdcall checksum_jb, esi, eax;buf_ptr,buf_size
|
||||
|
||||
mov byte[esi + IP_PACKET.HeaderChecksum], ah
|
||||
mov byte[esi + IP_PACKET.HeaderChecksum + 1], al ; ?? correct byte order?
|
||||
|
||||
mov byte[edi + ICMP_PACKET.Type], ICMP_ECHOREPLY; change the request to a response
|
||||
mov word[edi + ICMP_PACKET.Checksum], 0; clear ICMP checksum prior to re-calc
|
||||
|
||||
; Calculate the length of the ICMP data ( IP payload)
|
||||
xor eax, eax
|
||||
mov ah, byte[esi + IP_PACKET.TotalLength]
|
||||
mov al, byte[esi + IP_PACKET.TotalLength + 1]
|
||||
sub ax, word[IPHeaderLength];ax=ICMP-packet length
|
||||
|
||||
stdcall checksum_jb, edi, eax;buf_ptr,buf_size
|
||||
|
||||
mov byte[edi + ICMP_PACKET.Checksum], ah
|
||||
mov byte[edi + ICMP_PACKET.Checksum + 1], al
|
||||
|
||||
; Queue packet for transmission
|
||||
mov ebx, [buffer_number]
|
||||
mov eax, NET1OUT_QUEUE
|
||||
call queue
|
||||
|
||||
.exit:
|
||||
; Transmit the packet (notice that packet ptr and packet size have been on stack since start of the procedure!)
|
||||
call [ebx + NET_DEVICE.transmit]
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
.check_sockets:
|
||||
; Look for an open ICMP socket
|
||||
|
||||
mov esi, [edi] ; ipv4 source address
|
||||
mov eax, net_sockets
|
||||
.try_more:
|
||||
; mov , [edx + ICMP_header.Identifier]
|
||||
.next_socket:
|
||||
mov eax, [eax + SOCKET.NextPtr]
|
||||
or eax, eax
|
||||
jz .dump
|
||||
|
||||
cmp [eax + SOCKET.Domain], AF_INET4
|
||||
jne .next_socket
|
||||
|
||||
cmp [eax + SOCKET.Protocol], IP_PROTO_ICMP
|
||||
jne .next_socket
|
||||
|
||||
cmp [eax + IP_SOCKET.RemoteIP], esi
|
||||
jne .next_socket
|
||||
|
||||
; cmp [eax + ICMP_SOCKET.Identifier],
|
||||
; jne .next_socket
|
||||
|
||||
; call IPv4_dest_to_dev
|
||||
; cmp edi,-1
|
||||
; je .dump
|
||||
; inc [ICMP_PACKETS_RX+edi]
|
||||
|
||||
DEBUGF 1,"socket=%x\n", eax
|
||||
|
||||
pusha
|
||||
lea ecx, [eax + SOCKET.mutex]
|
||||
call mutex_lock
|
||||
popa
|
||||
|
||||
mov esi, edx
|
||||
jmp SOCKET_input
|
||||
|
||||
|
||||
.checksum_mismatch:
|
||||
DEBUGF 1,"checksum mismatch\n"
|
||||
|
||||
.dump:
|
||||
DEBUGF 1,"ICMP_input: dumping\n"
|
||||
|
||||
call kernel_free
|
||||
add esp, 4 ; pop (balance stack)
|
||||
|
||||
ret
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ICMP_output
|
||||
;
|
||||
; IN: eax = dest ip
|
||||
; ebx = source ip
|
||||
; ecx = data length
|
||||
; dh = type
|
||||
; dl = code
|
||||
; esi = data offset
|
||||
; edi = identifier shl 16 + sequence number
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
ICMP_output:
|
||||
|
||||
DEBUGF 1,"Creating ICMP Packet\n"
|
||||
|
||||
push esi edi dx
|
||||
|
||||
mov edx, [eax + IP_SOCKET.LocalIP]
|
||||
mov eax, [eax + IP_SOCKET.RemoteIP]
|
||||
add ecx, sizeof.ICMP_header
|
||||
mov di, IP_PROTO_ICMP SHL 8 + 128 ; TTL
|
||||
call IPv4_output
|
||||
jz .exit
|
||||
|
||||
DEBUGF 1,"full icmp packet size: %u\n", edx
|
||||
|
||||
pop word [edi + ICMP_header.Type] ; Write both type and code bytes at once
|
||||
pop dword [edi + ICMP_header.Identifier] ; identifier and sequence number
|
||||
mov [edi + ICMP_header.Checksum], 0
|
||||
|
||||
push ebx ecx edx
|
||||
mov esi, edi
|
||||
xor edx, edx
|
||||
call checksum_1
|
||||
call checksum_2
|
||||
mov [edi + ICMP_header.Checksum], dx
|
||||
pop edx ecx ebx esi
|
||||
|
||||
sub ecx, sizeof.ICMP_header
|
||||
add edi, sizeof.ICMP_header
|
||||
push cx
|
||||
shr cx, 2
|
||||
rep movsd
|
||||
pop cx
|
||||
and cx, 3
|
||||
rep movsb
|
||||
|
||||
sub edi, edx ;;; TODO: find a better way to remember start of packet
|
||||
push edx edi
|
||||
DEBUGF 1,"Sending ICMP Packet\n"
|
||||
call [ebx + NET_DEVICE.transmit]
|
||||
ret
|
||||
.exit:
|
||||
DEBUGF 1,"Creating ICMP Packet failed\n"
|
||||
add esp, 2*4 + 2
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ICMP_output
|
||||
;
|
||||
; IN: eax = socket ptr
|
||||
; ecx = data length
|
||||
; esi = data offset
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
ICMP_output_raw:
|
||||
|
||||
DEBUGF 1,"Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
|
||||
|
||||
push edx
|
||||
|
||||
mov di, IP_PROTO_ICMP SHL 8 + 128 ; TTL
|
||||
mov edx, [eax + IP_SOCKET.LocalIP]
|
||||
mov eax, [eax + IP_SOCKET.RemoteIP]
|
||||
call IPv4_output
|
||||
jz .exit
|
||||
|
||||
pop esi
|
||||
push edx
|
||||
push eax
|
||||
|
||||
push edi ecx
|
||||
DEBUGF 1,"copying %u bytes from %x to %x\n", ecx, esi, edi
|
||||
rep movsb
|
||||
pop ecx edi
|
||||
|
||||
mov [edi + ICMP_header.Checksum], 0
|
||||
|
||||
mov esi, edi
|
||||
xor edx, edx
|
||||
call checksum_1
|
||||
call checksum_2
|
||||
mov [edi + ICMP_header.Checksum], dx
|
||||
|
||||
DEBUGF 1,"Sending ICMP Packet\n"
|
||||
call [ebx + NET_DEVICE.transmit]
|
||||
ret
|
||||
.exit:
|
||||
DEBUGF 1,"Creating ICMP Packet failed\n"
|
||||
add esp, 4
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ICMP_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
|
||||
ICMP_api:
|
||||
|
||||
movzx eax, bh
|
||||
shl eax, 2
|
||||
|
||||
test bl, bl
|
||||
jz .packets_tx ; 0
|
||||
dec bl
|
||||
jz .packets_rx ; 1
|
||||
|
||||
.error:
|
||||
mov eax, -1
|
||||
ret
|
||||
|
||||
.packets_tx:
|
||||
mov eax, [ICMP_PACKETS_TX + eax]
|
||||
ret
|
||||
|
||||
.packets_rx:
|
||||
mov eax, [ICMP_PACKETS_RX + eax]
|
||||
ret
|
||||
endp
|
||||
|
@ -1,248 +0,0 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; ;;
|
||||
;; IP.INC ;;
|
||||
;; ;;
|
||||
;; IP Processes for Menuet OS TCP/IP stack ;;
|
||||
;; ;;
|
||||
;; Version 0.3 29 August 2002 ;;
|
||||
;; ;;
|
||||
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;;
|
||||
;; ;;
|
||||
;; See file COPYING for details ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
$Revision$
|
||||
|
||||
|
||||
; IP underlying protocols numbers
|
||||
PROTOCOL_ICMP equ 1
|
||||
PROTOCOL_TCP equ 6
|
||||
PROTOCOL_UDP equ 17
|
||||
|
||||
struc IP_PACKET
|
||||
{ .VersionAndIHL db ? ;+00 - Version[0-3 bits] and IHL(header length)[4-7 bits]
|
||||
.TypeOfService db ? ;+01
|
||||
.TotalLength dw ? ;+02
|
||||
.Identification dw ? ;+04
|
||||
.FlagsAndFragmentOffset dw ? ;+06 - Flags[0-2] and FragmentOffset[3-15]
|
||||
.TimeToLive db ? ;+08
|
||||
.Protocol db ? ;+09
|
||||
.HeaderChecksum dw ? ;+10
|
||||
.SourceAddress dd ? ;+12
|
||||
.DestinationAddress dd ? ;+16
|
||||
.DataOrOptional dd ? ;+20
|
||||
}
|
||||
|
||||
virtual at 0
|
||||
IP_PACKET IP_PACKET
|
||||
end virtual
|
||||
|
||||
|
||||
;*******************************************************************
|
||||
; Interface
|
||||
;
|
||||
; ip_rx processes all packets received by the network layer
|
||||
; It calls the appropriate protocol handler
|
||||
;
|
||||
;
|
||||
;
|
||||
;*******************************************************************
|
||||
|
||||
|
||||
;
|
||||
; IP Packet after reception - Normal IP packet format
|
||||
;
|
||||
; 0 1 2 3
|
||||
; 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
|
||||
;
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
;0 |Version| IHL |Type of Service| Total Length |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
;4 | Identification |Flags| Fragment Offset |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
;8 | Time to Live | Protocol | Header Checksum |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
;12 | Source Address |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
;16 | Destination Address |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
;20 | Data |
|
||||
; +-+-+-.......... -+
|
||||
;
|
||||
;
|
||||
; [smb] attention! according to RFC 791 IP packet may have 'options' sections,
|
||||
; so we can't simply think, that data have offset 20. We must calculate offset from
|
||||
; IHL field
|
||||
;
|
||||
macro GET_IHL reg, header_addr
|
||||
{
|
||||
movzx reg, byte [header_addr]
|
||||
|
||||
; we need 4-7 bits, so....
|
||||
and reg, 0x0000000F
|
||||
|
||||
; IHL keeps number of octets, so we need to << 2 'reg'
|
||||
shl reg, 2
|
||||
}
|
||||
|
||||
|
||||
include "tcp.inc"
|
||||
include "udp.inc"
|
||||
include "icmp.inc"
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; ip_rx
|
||||
;
|
||||
; Description
|
||||
; This is a kernel function, called by stack_handler
|
||||
; Processes all IP-packets received by the network layer
|
||||
; It calls the appropriate protocol handler
|
||||
;
|
||||
;***************************************************************************
|
||||
proc ip_rx stdcall
|
||||
local buffer_number dd ?
|
||||
|
||||
; Look for a buffer to tx
|
||||
mov eax, IPIN_QUEUE
|
||||
call dequeue
|
||||
cmp ax, NO_BUFFER
|
||||
je .exit ; Exit if no buffer available
|
||||
|
||||
mov [buffer_number], eax;save buffer number
|
||||
|
||||
; convert buffer pointer eax to the absolute address
|
||||
imul eax, IPBUFFSIZE
|
||||
add eax, IPbuffs
|
||||
|
||||
mov ebx, eax; ebx=pointer to IP_PACKET
|
||||
|
||||
; DEBUGF 1, "K : ip_rx - proto: %u\n", [ebx + IP_PACKET.Protocol]:1
|
||||
|
||||
; Validate the IP checksum
|
||||
mov dx, word[ebx + IP_PACKET.HeaderChecksum]
|
||||
xchg dh, dl ; Get the checksum in intel format
|
||||
|
||||
mov [ebx + IP_PACKET.HeaderChecksum], 0; clear checksum field - need to when
|
||||
; recalculating checksum
|
||||
; this needs two data pointers and two size #.
|
||||
; 2nd pointer can be of length 0
|
||||
|
||||
GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx
|
||||
stdcall checksum_jb, ebx, ecx;buf_ptr, buf_size
|
||||
cmp dx, ax
|
||||
|
||||
; DEBUGF 1, "K : ip_rx - checksums: %x - %x\n", dx, ax
|
||||
|
||||
jnz .dump.1;if CHECKSUM isn't valid then dump packet
|
||||
mov edx, ebx; EDX (IP-BUFFER POINTER) WILL BE USED FOR *_rx HANDLERS BELOW!!!
|
||||
|
||||
; DEBUGF 1, "K : ip_rx - dest: %x - %x\n", [ebx + IP_PACKET.DestinationAddress], [stack_ip]
|
||||
|
||||
; Validate the IP address, if it isn't broadcast
|
||||
mov eax, [stack_ip]
|
||||
cmp dword[ebx + IP_PACKET.DestinationAddress], eax
|
||||
je @f
|
||||
|
||||
; If the IP address is 255.255.255.255, accept it
|
||||
; - it is a broadcast packet, which we need for dhcp
|
||||
|
||||
mov eax, [ebx + IP_PACKET.DestinationAddress]
|
||||
cmp eax, 0xffffffff
|
||||
je @f
|
||||
mov ecx, [stack_ip]
|
||||
and eax, [subnet_mask]
|
||||
and ecx, [subnet_mask]
|
||||
cmp eax, ecx
|
||||
jne .dump.2
|
||||
mov eax, [ebx + IP_PACKET.DestinationAddress]
|
||||
or eax, [subnet_mask]
|
||||
cmp eax, 0xffffffff
|
||||
jne .dump.2
|
||||
|
||||
@@:
|
||||
mov al, [ebx + IP_PACKET.VersionAndIHL]
|
||||
and al, 0x0f;get IHL(header length)
|
||||
cmp al, 0x05;if IHL!= 5*4(20 bytes)
|
||||
; DEBUGF 1, "K : ip_rx - ihl: %x - 05\n", al
|
||||
jnz .dump.3 ;then dump it
|
||||
|
||||
; DEBUGF 1, "K : ip_rx - ttl: %x - 00\n", [ebx + IP_PACKET.TimeToLive]:2
|
||||
|
||||
cmp [ebx + IP_PACKET.TimeToLive], 0
|
||||
je .dump.4 ;if TTL==0 then dump it
|
||||
|
||||
mov ax, [ebx + IP_PACKET.FlagsAndFragmentOffset]
|
||||
and ax, 0xFFBF;get flags
|
||||
; DEBUGF 1, "K : ip_rx - flags: %x - 0000\n", ax
|
||||
cmp ax, 0 ;if some flags was set then we dump this packet
|
||||
jnz .dump.5 ;the flags should be used for fragmented packets
|
||||
|
||||
; Check the protocol, and call the appropriate handler
|
||||
; Each handler will re-use or free the queue buffer as appropriate
|
||||
|
||||
mov al, [ebx + IP_PACKET.Protocol]
|
||||
|
||||
cmp al , PROTOCOL_TCP
|
||||
jne .not_tcp
|
||||
; DEBUGF 1,"K : ip_rx - TCP packet\n"
|
||||
mov eax, dword[buffer_number]
|
||||
call tcp_rx
|
||||
jmp .exit
|
||||
|
||||
.not_tcp:
|
||||
cmp al, PROTOCOL_UDP
|
||||
jne .not_udp
|
||||
; DEBUGF 1,"K : ip_rx - UDP packet\n"
|
||||
mov eax, dword[buffer_number]
|
||||
call udp_rx
|
||||
jmp .exit
|
||||
|
||||
.not_udp:
|
||||
cmp al, PROTOCOL_ICMP
|
||||
jne .dump.6 ;protocol ain't supported
|
||||
|
||||
; DEBUGF 1,"K : ip_rx - ICMP packet\n"
|
||||
;GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx
|
||||
mov eax, dword[buffer_number]
|
||||
stdcall icmp_rx, eax, ebx, ecx;buffer_number,IPPacketBase,IPHeaderLength
|
||||
jmp .exit
|
||||
|
||||
|
||||
.dump.1:
|
||||
; DEBUGF 1, "K : ip_rx - dumped (checksum: 0x%x-0x%x)\n", dx, ax
|
||||
jmp .dump.x
|
||||
|
||||
.dump.2:
|
||||
; DEBUGF 1, "K : ip_rx - dumped (ip: %u.%u.%u.%u)\n", [ebx + IP_PACKET.DestinationAddress + 0]:1, [ebx + IP_PACKET.DestinationAddress + 1]:1, [ebx + IP_PACKET.DestinationAddress + 2]:1, [ebx + IP_PACKET.DestinationAddress + 3]:1
|
||||
jmp .dump.x
|
||||
|
||||
.dump.3:
|
||||
; DEBUGF 1, "K : ip_rx - dumped (ihl: %u)\n", al
|
||||
jmp .dump.x
|
||||
|
||||
.dump.4:
|
||||
; DEBUGF 1, "K : ip_rx - dumped (ttl: %u)\n", [ebx + IP_PACKET.TimeToLive]
|
||||
jmp .dump.x
|
||||
|
||||
.dump.5:
|
||||
; DEBUGF 1, "K : ip_rx - dumped (flags: 0x%x)\n", ax
|
||||
jmp .dump.x
|
||||
|
||||
.dump.6:
|
||||
; DEBUGF 1, "K : ip_rx - dumped (proto: %u)\n", [ebx + IP_PACKET.Protocol]:1
|
||||
|
||||
.dump.x:
|
||||
inc dword[dumped_rx_count]
|
||||
mov eax, [buffer_number]
|
||||
call freeBuff
|
||||
|
||||
.exit:
|
||||
ret
|
||||
endp
|
||||
|
126
kernel/trunk/network/loopback.inc
Normal file
126
kernel/trunk/network/loopback.inc
Normal file
@ -0,0 +1,126 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; loopback.inc ;;
|
||||
;; ;;
|
||||
;; LoopBack device for KolibriOS ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr@kolibrios.org ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
$Revision: 2891 $
|
||||
|
||||
iglobal
|
||||
|
||||
LOOPBACK_DEVICE:
|
||||
.type dd NET_TYPE_LOOPBACK
|
||||
.mtu dd 4096
|
||||
.name dd .namestr
|
||||
|
||||
.unload dd .dummy_fn
|
||||
.reset dd .dummy_fn
|
||||
.transmit dd LOOP_input
|
||||
|
||||
.bytes_tx dq 0
|
||||
.bytes_rx dq 0
|
||||
.packets_tx dd 0
|
||||
.packets_rx dd 0
|
||||
|
||||
.namestr db 'loopback', 0
|
||||
|
||||
.dummy_fn:
|
||||
ret
|
||||
|
||||
endg
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; LOOP_input
|
||||
;
|
||||
; IN: [esp+4] = Pointer to buffer
|
||||
; [esp+8] = size of buffer
|
||||
;
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
LOOP_input:
|
||||
pop ebx
|
||||
pop eax
|
||||
pop ecx
|
||||
|
||||
push ebx
|
||||
push ecx
|
||||
push eax
|
||||
|
||||
DEBUGF 1,"LOOP_input: size=%u\n", ecx
|
||||
lea edx, [eax + 2]
|
||||
mov ax, word[eax]
|
||||
mov ebx, LOOPBACK_DEVICE
|
||||
|
||||
cmp ax, ETHER_IPv4
|
||||
je IPv4_input
|
||||
|
||||
DEBUGF 2,"LOOP_input: Unknown packet type=%x\n", ax
|
||||
|
||||
.dump:
|
||||
DEBUGF 2,"LOOP_input: dumping\n"
|
||||
call kernel_free
|
||||
add esp, 4
|
||||
ret
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; LOOP_output
|
||||
;
|
||||
; IN:
|
||||
; 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
|
||||
LOOP_output:
|
||||
|
||||
DEBUGF 1,"LOOP_output\n"
|
||||
|
||||
push ecx
|
||||
push di
|
||||
|
||||
add ecx, 2
|
||||
cmp ecx, [LOOPBACK_DEVICE.mtu]
|
||||
ja .out_of_ram
|
||||
stdcall kernel_alloc, ecx
|
||||
test eax, eax
|
||||
jz .out_of_ram
|
||||
mov edi, eax
|
||||
pop ax
|
||||
stosw
|
||||
|
||||
lea eax, [edi - 2] ; Set eax to buffer start
|
||||
pop ecx
|
||||
lea edx, [ecx + 2] ; Set edx to complete buffer size
|
||||
mov ebx, LOOPBACK_DEVICE
|
||||
|
||||
.done:
|
||||
DEBUGF 2,"LOOP_output: ptr=%x size=%u\n", eax, edx
|
||||
ret
|
||||
|
||||
.out_of_ram:
|
||||
DEBUGF 2,"LOOP_output: failed\n"
|
||||
add esp, 2+4
|
||||
sub edi, edi
|
||||
ret
|
||||
|
||||
|
@ -1,229 +1,100 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; queue.inc ;;
|
||||
;; ;;
|
||||
;; QUEUE.INC ;;
|
||||
;; Written by hidnplayr@kolibrios.org ;;
|
||||
;; ;;
|
||||
;; Buffer queue management for Menuet OS TCP/IP Stack ;;
|
||||
;; ;;
|
||||
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;;
|
||||
;; ;;
|
||||
;; See file COPYING for details ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
$Revision$
|
||||
$Revision: 2305 $
|
||||
|
||||
|
||||
;*******************************************************************
|
||||
; Interface
|
||||
; The Queues implemented by these macros form a ring-buffer.
|
||||
; The data to these queue's always looks like this:
|
||||
;
|
||||
; queueInit Configures the queues to empty
|
||||
; dequeue Removes a buffer pointer from a queue
|
||||
; queue Inserts a buffer pointer into a queue
|
||||
; freeBuff Adds the buffer pointer to the list of free buffers
|
||||
; queueSize Returns the number of entries in a queue
|
||||
;
|
||||
; The various defines for queue names can be found in stack.inc
|
||||
;
|
||||
;*******************************************************************
|
||||
; At top, you have the queue struct, wich has the size (number of currently queued packets, read and write pointers.
|
||||
; This struct is followed by a number of slots wich you can read and write to using the macros.
|
||||
; How these slots look like is up to you to chose, normally they should have at least a pointer to where the real data is.
|
||||
; (you can see some examples below)
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; freeBuff
|
||||
;
|
||||
; Description
|
||||
; Adds a buffer number to the beginning of the free list.
|
||||
; buffer number in eax ( ms word zeroed )
|
||||
; all other registers preserved
|
||||
; This always works, so no error returned
|
||||
;***************************************************************************
|
||||
;uglobal
|
||||
; freeBuff_cnt dd ?
|
||||
;endg
|
||||
freeBuff:
|
||||
; inc [freeBuff_cnt]
|
||||
; DEBUGF 1, "K : freeBuff (%u)\n", [freeBuff_cnt]
|
||||
push ebx
|
||||
push ecx
|
||||
mov ebx, queues + EMPTY_QUEUE * 2
|
||||
cli ; Ensure that another process does not interfer
|
||||
mov cx, [ebx]
|
||||
mov [ebx], ax
|
||||
mov [queueList + eax * 2], cx
|
||||
sti
|
||||
pop ecx
|
||||
pop ebx
|
||||
struct queue
|
||||
|
||||
ret
|
||||
size dd ? ; number of queued packets in this queue
|
||||
w_ptr dd ? ; current writing pointer in queue
|
||||
r_ptr dd ? ; current reading pointer
|
||||
|
||||
ends
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; queueSize
|
||||
;
|
||||
; Description
|
||||
; Counts the number of entries in a queue
|
||||
; queue number in ebx ( ms word zeroed )
|
||||
; Queue size returned in eax
|
||||
; This always works, so no error returned
|
||||
;***************************************************************************
|
||||
queueSize:
|
||||
xor eax, eax
|
||||
shl ebx, 1
|
||||
add ebx, queues
|
||||
movzx ecx, word [ebx]
|
||||
cmp cx, NO_BUFFER
|
||||
je qs_exit
|
||||
; The following macros share these inputs:
|
||||
|
||||
qs_001:
|
||||
inc eax
|
||||
shl ecx, 1
|
||||
add ecx, queueList
|
||||
movzx ecx, word [ecx]
|
||||
cmp cx, NO_BUFFER
|
||||
je qs_exit
|
||||
jmp qs_001
|
||||
; ptr = pointer to where the queue data is located
|
||||
; size = number of slots/entrys in the queue
|
||||
; entry_size = size of one slot, in bytes
|
||||
; failaddr = the address where macro will jump to when there is no data in the queue
|
||||
|
||||
qs_exit:
|
||||
ret
|
||||
; additionally, add_to_queue requires you to set esi to the data wich you want to queue
|
||||
; get_from_queue on the other hand will return a pointer in esi, to the entry you're interessed in
|
||||
; PS: macros WILL destroy ecx and edi
|
||||
|
||||
macro add_to_queue ptr, size, entry_size, failaddr {
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; queue
|
||||
;
|
||||
; Description
|
||||
; Adds a buffer number to the *end* of a queue
|
||||
; This is quite quick because these queues will be short
|
||||
; queue number in eax ( ms word zeroed )
|
||||
; buffer number in ebx ( ms word zeroed )
|
||||
; all other registers preserved
|
||||
; This always works, so no error returned
|
||||
;***************************************************************************
|
||||
;uglobal
|
||||
; queue_cnt dd ?
|
||||
;endg
|
||||
queue:
|
||||
; inc [queue_cnt]
|
||||
; DEBUGF 1, "K : queue (%u)\n", [queue_cnt]
|
||||
push ebx
|
||||
shl ebx, 1
|
||||
add ebx, queueList ; eax now holds address of queue entry
|
||||
mov [ebx], word NO_BUFFER; This buffer will be the last
|
||||
cmp [ptr + queue.size], size ; Check if queue isnt full
|
||||
jae failaddr
|
||||
|
||||
cli
|
||||
shl eax, 1
|
||||
add eax, queues ; eax now holds address of queue
|
||||
movzx ebx, word [eax]
|
||||
inc [ptr + queue.size] ; if not full, queue one more
|
||||
|
||||
cmp bx, NO_BUFFER
|
||||
jne qu_001
|
||||
mov edi, [ptr + queue.w_ptr] ; Current write pointer (FIFO!)
|
||||
mov ecx, entry_size/4 ; Write the queue entry
|
||||
rep movsd ;
|
||||
|
||||
pop ebx
|
||||
; The list is empty, so add this to the head
|
||||
mov [eax], bx
|
||||
jmp qu_exit
|
||||
lea ecx, [size*entry_size+ptr+sizeof.queue]
|
||||
cmp edi, ecx ; entry size
|
||||
jb .no_wrap
|
||||
|
||||
qu_001:
|
||||
; Find the last entry
|
||||
shl ebx, 1
|
||||
add ebx, queueList
|
||||
mov eax, ebx
|
||||
movzx ebx, word [ebx]
|
||||
cmp bx, NO_BUFFER
|
||||
jne qu_001
|
||||
sub edi, size*entry_size
|
||||
|
||||
mov ebx, eax
|
||||
pop eax
|
||||
mov [ebx], ax
|
||||
.no_wrap:
|
||||
mov [ptr + queue.w_ptr], edi
|
||||
|
||||
qu_exit:
|
||||
sti
|
||||
ret
|
||||
}
|
||||
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; dequeue
|
||||
;
|
||||
; Description
|
||||
; removes a buffer number from the head of a queue
|
||||
; This is fast, as it unlinks the first entry in the list
|
||||
; queue number in eax ( ms word zeroed )
|
||||
; buffer number returned in eax ( ms word zeroed )
|
||||
; all other registers preserved
|
||||
;
|
||||
;***************************************************************************
|
||||
;uglobal
|
||||
; dequeue_cnt dd ?
|
||||
;endg
|
||||
dequeue:
|
||||
push ebx
|
||||
shl eax, 1
|
||||
add eax, queues ; eax now holds address of queue
|
||||
mov ebx, eax
|
||||
cli
|
||||
movzx eax, word [eax]
|
||||
cmp ax, NO_BUFFER
|
||||
je dq_exit
|
||||
; inc [dequeue_cnt]
|
||||
; DEBUGF 1, "K : dequeue (%u)\n", [dequeue_cnt]
|
||||
push eax
|
||||
shl eax, 1
|
||||
add eax, queueList ; eax now holds address of queue entry
|
||||
mov ax, [eax]
|
||||
mov [ebx], ax
|
||||
pop eax
|
||||
macro get_from_queue ptr, size, entry_size, failaddr {
|
||||
|
||||
dq_exit:
|
||||
sti
|
||||
pop ebx
|
||||
ret
|
||||
cmp [ptr + queue.size], 0 ; any packets queued?
|
||||
je failaddr
|
||||
|
||||
dec [ptr + queue.size] ; if so, dequeue one
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; queueInit
|
||||
;
|
||||
; Description
|
||||
; Initialises the queues to empty, and creates the free queue
|
||||
; list.
|
||||
;
|
||||
;***************************************************************************
|
||||
queueInit:
|
||||
mov esi, queues
|
||||
mov ecx, NUMQUEUES
|
||||
mov ax, NO_BUFFER
|
||||
mov esi, [ptr + queue.r_ptr]
|
||||
push esi
|
||||
|
||||
qi001:
|
||||
mov [esi], ax
|
||||
inc esi
|
||||
inc esi
|
||||
loop qi001
|
||||
add esi, entry_size
|
||||
|
||||
mov esi, queues + ( 2 * EMPTY_QUEUE )
|
||||
lea ecx, [size*entry_size+ptr+sizeof.queue]
|
||||
cmp esi, ecx ; entry size
|
||||
jb .no_wrap
|
||||
|
||||
; Initialise empty queue list
|
||||
sub esi, size*entry_size
|
||||
|
||||
xor ax, ax
|
||||
mov [esi], ax
|
||||
.no_wrap:
|
||||
mov dword [ptr + queue.r_ptr], esi
|
||||
|
||||
mov ecx, NUMQUEUEENTRIES - 1
|
||||
mov esi, queueList
|
||||
pop esi
|
||||
|
||||
qi002:
|
||||
inc ax
|
||||
mov [esi], ax
|
||||
inc esi
|
||||
inc esi
|
||||
loop qi002
|
||||
}
|
||||
|
||||
mov ax, NO_BUFFER
|
||||
mov [esi], ax
|
||||
macro init_queue ptr {
|
||||
|
||||
ret
|
||||
mov [ptr + queue.size] , 0
|
||||
lea edi, [ptr + sizeof.queue]
|
||||
mov [ptr + queue.w_ptr], edi
|
||||
mov [ptr + queue.r_ptr], edi
|
||||
}
|
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
1663
kernel/trunk/network/tcp_input.inc
Normal file
1663
kernel/trunk/network/tcp_input.inc
Normal file
File diff suppressed because it is too large
Load Diff
621
kernel/trunk/network/tcp_output.inc
Normal file
621
kernel/trunk/network/tcp_output.inc
Normal file
@ -0,0 +1,621 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; Part of the TCP/IP network stack for KolibriOS ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr@kolibrios.org ;;
|
||||
;; ;;
|
||||
;; Based on the code of 4.4BSD ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
$Revision: 3289 $
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; TCP_output
|
||||
;
|
||||
; IN: eax = socket pointer
|
||||
;
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
TCP_output:
|
||||
|
||||
DEBUGF 1,"TCP_output: socket=%x\n", eax
|
||||
|
||||
push eax
|
||||
lea ecx, [eax + SOCKET.mutex]
|
||||
call mutex_lock
|
||||
pop eax
|
||||
|
||||
; We'll detect the length of the data to be transmitted, and flags to be used
|
||||
; If there is some data, or any critical controls to send (SYN / RST), then transmit
|
||||
; Otherwise, investigate further
|
||||
|
||||
mov ebx, [eax + TCP_SOCKET.SND_MAX]
|
||||
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
|
||||
jbe .not_idle
|
||||
|
||||
mov ebx, [eax + TCP_SOCKET.t_idle]
|
||||
cmp ebx, [eax + TCP_SOCKET.t_rxtcur]
|
||||
jbe .not_idle
|
||||
|
||||
; We have been idle for a while and no ACKS are expected to clock out any data we send..
|
||||
; Slow start to get ack "clock" running again.
|
||||
|
||||
mov ebx, [eax + TCP_SOCKET.t_maxseg]
|
||||
mov [eax + TCP_SOCKET.SND_CWND], ebx
|
||||
|
||||
.not_idle:
|
||||
.again:
|
||||
mov [eax + TCP_SOCKET.temp_bits], 0
|
||||
|
||||
mov ebx, [eax + TCP_SOCKET.SND_NXT] ; calculate offset (71)
|
||||
sub ebx, [eax + TCP_SOCKET.SND_UNA] ;
|
||||
|
||||
mov ecx, [eax + TCP_SOCKET.SND_WND] ; determine window
|
||||
cmp ecx, [eax + TCP_SOCKET.SND_CWND] ;
|
||||
jb @f ;
|
||||
mov ecx, [eax + TCP_SOCKET.SND_CWND] ;
|
||||
@@: ;
|
||||
|
||||
call TCP_outflags ; flags in dl
|
||||
|
||||
;------------------------
|
||||
; data being forced out ?
|
||||
|
||||
; If in persist timeout with window of 0, send 1 byte.
|
||||
; Otherwise, if window is small but nonzero, and timer expired,
|
||||
; we will send what we can and go to transmit state
|
||||
|
||||
cmp [eax + TCP_SOCKET.t_force], 0
|
||||
je .no_force
|
||||
|
||||
DEBUGF 1,"TCP_output: forcing data out\n"
|
||||
|
||||
test ecx, ecx
|
||||
jnz .no_zero_window
|
||||
|
||||
cmp ebx, [eax + STREAM_SOCKET.snd.size]
|
||||
jae @f
|
||||
|
||||
and dl, not (TH_FIN)
|
||||
|
||||
@@:
|
||||
inc ecx
|
||||
jmp .no_force
|
||||
|
||||
.no_zero_window:
|
||||
mov [eax + TCP_SOCKET.timer_persist], 0
|
||||
mov [eax + TCP_SOCKET.t_rxtshift], 0
|
||||
|
||||
.no_force:
|
||||
|
||||
;--------------------------------
|
||||
; Calculate how much data to send (106)
|
||||
|
||||
mov esi, [eax + STREAM_SOCKET.snd.size]
|
||||
cmp esi, ecx
|
||||
jb @f
|
||||
mov esi, ecx
|
||||
@@:
|
||||
sub esi, ebx
|
||||
|
||||
|
||||
;------------------------
|
||||
; check for window shrink (107)
|
||||
|
||||
; If FIN has been set, but not ACKed, but we havent been called to retransmit, esi will be -1
|
||||
; Otherwise, window shrank after we sent into it.
|
||||
|
||||
jae .not_persist
|
||||
|
||||
; enter persist state
|
||||
xor esi, esi
|
||||
|
||||
; If window shrank to 0
|
||||
test ecx, ecx
|
||||
jnz @f
|
||||
|
||||
; cancel pending retransmit
|
||||
mov [eax + TCP_SOCKET.timer_retransmission], 0
|
||||
|
||||
; pull SND_NXT back to (closed) window, We will enter persist state below.
|
||||
push [eax + TCP_SOCKET.SND_UNA]
|
||||
pop [eax + TCP_SOCKET.SND_NXT]
|
||||
@@:
|
||||
|
||||
; If window didn't close completely, just wait for an ACK
|
||||
|
||||
.not_persist:
|
||||
|
||||
;---------------------------
|
||||
; Send one segment at a time (124)
|
||||
|
||||
cmp esi, [eax + TCP_SOCKET.t_maxseg]
|
||||
jbe @f
|
||||
|
||||
mov esi, [eax + TCP_SOCKET.t_maxseg]
|
||||
or [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT
|
||||
@@:
|
||||
|
||||
;--------------------------------------------
|
||||
; Turn of FIN flag if send buffer not emptied (128)
|
||||
|
||||
mov edi, [eax + TCP_SOCKET.SND_NXT]
|
||||
add edi, esi
|
||||
sub edi, [eax + TCP_SOCKET.SND_UNA]
|
||||
cmp edi, [eax + STREAM_SOCKET.snd.size]
|
||||
jae @f
|
||||
and dl, not (TH_FIN)
|
||||
|
||||
@@:
|
||||
|
||||
;-------------------------------
|
||||
; calculate window advertisement (130)
|
||||
|
||||
mov ecx, SOCKET_MAXDATA
|
||||
sub ecx, [eax + STREAM_SOCKET.rcv.size]
|
||||
|
||||
;------------------------------
|
||||
; Sender silly window avoidance (131)
|
||||
|
||||
test esi, esi
|
||||
jz .len_zero
|
||||
|
||||
cmp esi, [eax + TCP_SOCKET.t_maxseg]
|
||||
je TCP_send
|
||||
|
||||
add ebx, esi ; offset + length
|
||||
cmp ebx, [eax + STREAM_SOCKET.snd.size]
|
||||
jb @f
|
||||
|
||||
test [eax + TCP_SOCKET.t_flags], TF_NODELAY
|
||||
jnz TCP_send
|
||||
|
||||
mov ebx, [eax + TCP_SOCKET.SND_MAX]
|
||||
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
|
||||
je TCP_send
|
||||
@@:
|
||||
|
||||
test [eax + TCP_SOCKET.t_force], -1 ;;;
|
||||
jnz TCP_send
|
||||
|
||||
mov ebx, [eax + TCP_SOCKET.max_sndwnd]
|
||||
shr ebx, 1
|
||||
cmp esi, ebx
|
||||
jae TCP_send
|
||||
|
||||
mov ebx, [eax + TCP_SOCKET.SND_NXT]
|
||||
cmp ebx, [eax + TCP_SOCKET.SND_MAX]
|
||||
jb TCP_send
|
||||
|
||||
.len_zero:
|
||||
|
||||
;----------------------------------------
|
||||
; Check if a window update should be sent (154)
|
||||
|
||||
DEBUGF 1,"TCP_output: window=%d\n", ecx
|
||||
|
||||
; Compare available window to amount of window known to peer (as advertised window less next expected input)
|
||||
; If the difference is at least two max size segments, or at least 50% of the maximum possible window,
|
||||
; Then we want to send a window update to the peer.
|
||||
|
||||
test ecx, ecx
|
||||
jz .no_window
|
||||
|
||||
push ecx
|
||||
mov cl, [eax + TCP_SOCKET.RCV_SCALE]
|
||||
mov ebx, TCP_max_win
|
||||
shl ebx, cl
|
||||
pop ecx
|
||||
cmp ebx, ecx
|
||||
jb @f
|
||||
mov ebx, ecx
|
||||
@@:
|
||||
sub ebx, [eax + TCP_SOCKET.RCV_ADV]
|
||||
add ebx, [eax + TCP_SOCKET.RCV_NXT]
|
||||
|
||||
mov edi, [eax + TCP_SOCKET.t_maxseg]
|
||||
shl edi, 1
|
||||
|
||||
; cmp ebx, edi
|
||||
; jae TCP_send
|
||||
|
||||
; cmp ebx, [eax + TCP_SOCKET.] ;;; TODO: check with receive buffer high water mark
|
||||
; jae TCP_send
|
||||
|
||||
.no_window:
|
||||
|
||||
;--------------------------
|
||||
; Should a segment be sent? (174)
|
||||
|
||||
DEBUGF 1,"TCP_output: 174\n"
|
||||
|
||||
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW ; we need to ACK
|
||||
jnz TCP_send
|
||||
|
||||
test dl, TH_SYN + TH_RST ; we need to send a SYN or RST
|
||||
jnz TCP_send
|
||||
|
||||
mov ebx, [eax + TCP_SOCKET.SND_UP] ; when urgent pointer is beyond start of send bufer
|
||||
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
|
||||
ja TCP_send
|
||||
|
||||
test dl, TH_FIN
|
||||
jz .enter_persist ; no reason to send, enter persist state
|
||||
|
||||
; FIN was set, only send if not already sent, or on retransmit
|
||||
|
||||
test [eax + TCP_SOCKET.t_flags], TF_SENTFIN
|
||||
jz TCP_send
|
||||
|
||||
mov ebx, [eax + TCP_SOCKET.SND_NXT]
|
||||
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
|
||||
je TCP_send
|
||||
|
||||
;--------------------
|
||||
; Enter persist state (191)
|
||||
|
||||
.enter_persist:
|
||||
|
||||
cmp [eax + STREAM_SOCKET.snd.size], 0 ; Data ready to send?
|
||||
jne @f
|
||||
cmp [eax + TCP_SOCKET.timer_retransmission], 0
|
||||
jne @f
|
||||
cmp [eax + TCP_SOCKET.timer_persist], 0 ; Persist timer already expired?
|
||||
jne @f
|
||||
|
||||
DEBUGF 1,"TCP_output: Entering persist state\n"
|
||||
|
||||
mov [eax + TCP_SOCKET.t_rxtshift], 0
|
||||
call TCP_set_persist
|
||||
@@:
|
||||
|
||||
;----------------------------
|
||||
; No reason to send a segment (219)
|
||||
|
||||
DEBUGF 1,"TCP_output: No reason to send a segment\n"
|
||||
|
||||
pusha
|
||||
lea ecx, [eax + SOCKET.mutex]
|
||||
call mutex_unlock
|
||||
popa
|
||||
|
||||
; Fixme: returnvalue?
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------
|
||||
;
|
||||
; Send a segment (222)
|
||||
;
|
||||
; eax = socket pointer
|
||||
; esi = data len
|
||||
; dl = flags
|
||||
;
|
||||
;-----------------------------------------------
|
||||
align 4
|
||||
TCP_send:
|
||||
|
||||
DEBUGF 1,"TCP_send: socket=%x length=%u flags=%x\n", eax, esi, dl
|
||||
|
||||
push eax ; save socket ptr
|
||||
push esi ; and data length too
|
||||
mov edi, sizeof.TCP_header ; edi will contain headersize
|
||||
|
||||
;------------------------------------
|
||||
; Send options with first SYN segment
|
||||
|
||||
test dl, TH_SYN
|
||||
jz .options_done
|
||||
|
||||
push [eax + TCP_SOCKET.ISS]
|
||||
pop [eax + TCP_SOCKET.SND_NXT]
|
||||
|
||||
test [eax + TCP_SOCKET.t_flags], TF_NOOPT
|
||||
jnz .options_done
|
||||
|
||||
mov ecx, 1460 ;;;; FIXME: use routing blablabla to determine MSS
|
||||
or ecx, TCP_OPT_MAXSEG shl 24 + 4 shl 16
|
||||
bswap ecx
|
||||
push ecx
|
||||
add di, 4
|
||||
|
||||
DEBUGF 1,"TCP_send: added maxseg option\n"
|
||||
|
||||
test [eax + TCP_SOCKET.t_flags], TF_REQ_SCALE
|
||||
jz .no_scale
|
||||
|
||||
test dl, TH_ACK
|
||||
jz .scale_opt
|
||||
|
||||
test [eax + TCP_SOCKET.t_flags], TF_RCVD_SCALE
|
||||
jz .no_scale
|
||||
|
||||
.scale_opt:
|
||||
mov cl, [eax + TCP_SOCKET.request_r_scale]
|
||||
mov ch, TCP_OPT_NOP
|
||||
pushw cx
|
||||
pushw TCP_OPT_WINDOW + 3 shl 8
|
||||
add di, 4
|
||||
|
||||
DEBUGF 1,"TCP_send: added scale option\n"
|
||||
|
||||
.no_scale:
|
||||
.no_syn:
|
||||
|
||||
;------------------------------------
|
||||
; Make the timestamp option if needed
|
||||
|
||||
test [eax + TCP_SOCKET.t_flags], TF_REQ_TSTMP
|
||||
jz .no_timestamp
|
||||
|
||||
test dl, TH_RST
|
||||
jnz .no_timestamp
|
||||
|
||||
test dl, TH_ACK
|
||||
jz .timestamp
|
||||
|
||||
test [eax + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
|
||||
jz .no_timestamp
|
||||
|
||||
.timestamp:
|
||||
pushd 0
|
||||
pushd [timer_ticks]
|
||||
pushd TCP_OPT_NOP + TCP_OPT_NOP shl 8 + TCP_OPT_TIMESTAMP shl 16 + 10 shl 24
|
||||
add di, 12
|
||||
|
||||
DEBUGF 1,"TCP_send: added timestamp\n"
|
||||
|
||||
.no_timestamp:
|
||||
|
||||
; <Add additional options here>
|
||||
|
||||
.options_done:
|
||||
|
||||
; eax = socket ptr
|
||||
; edx = flags
|
||||
; edi = header size
|
||||
; esi = data len
|
||||
|
||||
;---------------------------------------------
|
||||
; check if we dont exceed the max segment size (270)
|
||||
|
||||
add esi, edi ; total TCP segment size
|
||||
cmp esi, [eax + TCP_SOCKET.t_maxseg]
|
||||
jbe .no_overflow
|
||||
|
||||
mov esi, [eax + TCP_SOCKET.t_maxseg]
|
||||
or [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT
|
||||
.no_overflow:
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
; Start by pushing all TCP header values in reverse order on stack
|
||||
; (essentially, creating the tcp header on the stack!)
|
||||
|
||||
pushw 0 ; .UrgentPointer dw ?
|
||||
pushw 0 ; .Checksum dw ?
|
||||
pushw 0x00a0 ; .Window dw ? ;;;;;;; FIXME (370)
|
||||
shl edi, 2 ; .DataOffset db ? only 4 left-most bits
|
||||
shl dx, 8
|
||||
or dx, di ; .Flags db ?
|
||||
pushw dx
|
||||
shr edi, 2 ; .DataOffset db ?
|
||||
|
||||
push [eax + TCP_SOCKET.RCV_NXT] ; .AckNumber dd ?
|
||||
ntohd [esp]
|
||||
|
||||
push [eax + TCP_SOCKET.SND_NXT] ; .SequenceNumber dd ?
|
||||
ntohd [esp]
|
||||
|
||||
push [eax + TCP_SOCKET.RemotePort] ; .DestinationPort dw ?
|
||||
push [eax + TCP_SOCKET.LocalPort] ; .SourcePort dw ?
|
||||
|
||||
push edi ; header size
|
||||
|
||||
;---------------------
|
||||
; Create the IP packet
|
||||
|
||||
mov ecx, esi
|
||||
|
||||
mov ebx, [eax + SOCKET.device]
|
||||
mov edx, [eax + IP_SOCKET.LocalIP] ; source ip
|
||||
mov eax, [eax + IP_SOCKET.RemoteIP] ; dest ip
|
||||
mov di, IP_PROTO_TCP shl 8 + 128
|
||||
call IPv4_output
|
||||
jz .ip_error
|
||||
|
||||
;-----------------------------------------
|
||||
; Move TCP header from stack to TCP packet
|
||||
|
||||
push ecx
|
||||
mov ecx, [esp + 4]
|
||||
lea esi, [esp + 8]
|
||||
shr ecx, 2 ; count is in bytes, we will work with dwords
|
||||
rep movsd
|
||||
pop ecx ; full TCP packet size
|
||||
|
||||
pop esi ; headersize
|
||||
add esp, esi ; remove it from stack
|
||||
|
||||
push edx ; packet size for send proc
|
||||
push eax ; packet ptr for send proc
|
||||
|
||||
mov edx, edi ; begin of data
|
||||
sub edx, esi ; begin of packet (edi = begin of data)
|
||||
push ecx
|
||||
sub ecx, esi ; data size
|
||||
|
||||
;--------------
|
||||
; Copy the data
|
||||
|
||||
; eax = ptr to ring struct
|
||||
; ecx = buffer size
|
||||
; edi = ptr to buffer
|
||||
|
||||
mov eax, [esp + 16] ; get socket ptr
|
||||
|
||||
push edx
|
||||
push [eax + TCP_SOCKET.SND_NXT] ; we'll need this for timing the transmission
|
||||
test ecx, ecx
|
||||
jz .nodata
|
||||
mov edx, [eax + TCP_SOCKET.SND_NXT]
|
||||
add [eax + TCP_SOCKET.SND_NXT], ecx ; update sequence number <<< CHECKME
|
||||
sub edx, [eax + TCP_SOCKET.SND_UNA] ; offset
|
||||
add eax, STREAM_SOCKET.snd
|
||||
call SOCKET_ring_read
|
||||
.nodata:
|
||||
pop edi
|
||||
pop esi ; begin of data
|
||||
pop ecx ; full packet size
|
||||
mov eax, [esp + 12] ; socket ptr
|
||||
|
||||
;----------------------------------
|
||||
; initialize retransmit timer (400)
|
||||
|
||||
;TODO: check t_force and persist
|
||||
|
||||
test [esi + TCP_header.Flags], TH_SYN + TH_FIN ; syn and fin take a sequence number
|
||||
jz @f
|
||||
inc [eax + TCP_SOCKET.SND_NXT]
|
||||
test [esi + TCP_header.Flags], TH_FIN
|
||||
jz @f
|
||||
or [eax + TCP_SOCKET.t_flags], TF_SENTFIN ; if we sent a fin, set the sentfin flag
|
||||
@@:
|
||||
|
||||
mov edx, [eax + TCP_SOCKET.SND_NXT]
|
||||
cmp edx, [eax + TCP_SOCKET.SND_MAX] ; is this a retransmission?
|
||||
jbe @f
|
||||
mov [eax + TCP_SOCKET.SND_MAX], edx ; [eax + TCP_SOCKET.SND_NXT] from before we updated it
|
||||
|
||||
cmp [eax + TCP_SOCKET.t_rtt], 0 ; are we currently timing anything?
|
||||
je @f
|
||||
mov [eax + TCP_SOCKET.t_rtt], 1 ; nope, start transmission timer
|
||||
mov [eax + TCP_SOCKET.t_rtseq], edi
|
||||
;TODO: update stats
|
||||
@@:
|
||||
|
||||
; set retransmission timer if not already set, and not doing an ACK or keepalive probe
|
||||
|
||||
cmp [eax + TCP_SOCKET.timer_retransmission], 0 ;;;; FIXME
|
||||
ja .retransmit_set
|
||||
|
||||
cmp edx, [eax + TCP_SOCKET.SND_UNA] ; edx is still [eax + TCP_SOCKET.SND_NXT]
|
||||
je .retransmit_set
|
||||
|
||||
mov edx, [eax + TCP_SOCKET.t_rxtcur]
|
||||
mov [eax + TCP_SOCKET.timer_retransmission], edx
|
||||
|
||||
cmp [eax + TCP_SOCKET.timer_persist], 0
|
||||
jne .retransmit_set
|
||||
mov [eax + TCP_SOCKET.timer_persist], 0
|
||||
mov [eax + TCP_SOCKET.t_rxtshift], 0
|
||||
|
||||
.retransmit_set:
|
||||
|
||||
;--------------------
|
||||
; Create the checksum
|
||||
|
||||
TCP_checksum (eax + IP_SOCKET.LocalIP), (eax + IP_SOCKET.RemoteIP)
|
||||
mov [esi + TCP_header.Checksum], dx
|
||||
|
||||
;----------------
|
||||
; Send the packet
|
||||
|
||||
DEBUGF 1,"TCP_send: Sending with device %x\n", ebx
|
||||
call [ebx + NET_DEVICE.transmit]
|
||||
jnz .send_error
|
||||
|
||||
;---------------
|
||||
; Ok, data sent!
|
||||
|
||||
pop ecx
|
||||
pop eax
|
||||
|
||||
inc [TCP_segments_tx] ; FIXME: correct interface?
|
||||
|
||||
; update advertised receive window
|
||||
test ecx, ecx
|
||||
jz @f
|
||||
add ecx, [eax + TCP_SOCKET.RCV_NXT]
|
||||
cmp ecx, [eax + TCP_SOCKET.RCV_ADV]
|
||||
jbe @f
|
||||
mov [eax + TCP_SOCKET.RCV_ADV], ecx
|
||||
@@:
|
||||
|
||||
; update last ack sent
|
||||
push [eax + TCP_SOCKET.RCV_NXT]
|
||||
pop [eax + TCP_SOCKET.last_ack_sent]
|
||||
|
||||
; and flags
|
||||
and [eax + TCP_SOCKET.t_flags], not (TF_ACKNOW + TF_DELACK)
|
||||
|
||||
;--------------
|
||||
; unlock socket
|
||||
|
||||
push eax
|
||||
lea ecx, [eax + SOCKET.mutex]
|
||||
call mutex_unlock
|
||||
pop eax
|
||||
|
||||
;-----------------------------
|
||||
; Check if we need more output
|
||||
|
||||
test [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT
|
||||
jnz TCP_output.again
|
||||
|
||||
DEBUGF 1,"TCP_send: success!\n"
|
||||
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
|
||||
.ip_error:
|
||||
pop ecx
|
||||
add esp, ecx
|
||||
add esp, 4
|
||||
pop eax
|
||||
|
||||
mov [eax + TCP_SOCKET.timer_retransmission], TCP_time_re_min
|
||||
|
||||
lea ecx, [eax + SOCKET.mutex]
|
||||
call mutex_unlock
|
||||
|
||||
DEBUGF 1,"TCP_send: IP error\n"
|
||||
|
||||
or eax, -1
|
||||
ret
|
||||
|
||||
|
||||
.send_error:
|
||||
add esp, 8
|
||||
|
||||
lea ecx, [eax + SOCKET.mutex]
|
||||
call mutex_unlock
|
||||
|
||||
DEBUGF 1,"TCP_send: sending failed\n"
|
||||
|
||||
or eax, -2
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
546
kernel/trunk/network/tcp_subr.inc
Normal file
546
kernel/trunk/network/tcp_subr.inc
Normal file
@ -0,0 +1,546 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; Part of the TCP/IP network stack for KolibriOS ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr@kolibrios.org ;;
|
||||
;; ;;
|
||||
;; Based on the code of 4.4BSD ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
$Revision: 3514 $
|
||||
|
||||
align 4
|
||||
iglobal
|
||||
TCP_backoff db 0,1,2,3,4,5,6,6,6,6,6,6,6
|
||||
endg
|
||||
|
||||
macro TCP_checksum IP1, IP2 {
|
||||
|
||||
;-------------
|
||||
; Pseudoheader
|
||||
|
||||
; protocol type
|
||||
mov edx, IP_PROTO_TCP
|
||||
|
||||
; source address
|
||||
add dl, byte [IP1+1]
|
||||
adc dh, byte [IP1+0]
|
||||
adc dl, byte [IP1+3]
|
||||
adc dh, byte [IP1+2]
|
||||
|
||||
; destination address
|
||||
adc dl, byte [IP2+1]
|
||||
adc dh, byte [IP2+0]
|
||||
adc dl, byte [IP2+3]
|
||||
adc dh, byte [IP2+2]
|
||||
|
||||
; size
|
||||
adc dl, cl
|
||||
adc dh, ch
|
||||
|
||||
adc edx, 0
|
||||
|
||||
;---------------------
|
||||
; Real header and data
|
||||
|
||||
push esi
|
||||
call checksum_1
|
||||
call checksum_2
|
||||
pop esi
|
||||
|
||||
} ; returns in dx only
|
||||
|
||||
|
||||
|
||||
|
||||
macro TCP_sendseqinit ptr {
|
||||
|
||||
push edi ;;;; i dont like this static use of edi
|
||||
mov edi, [ptr + TCP_SOCKET.ISS]
|
||||
mov [ptr + TCP_SOCKET.SND_UP], edi
|
||||
mov [ptr + TCP_SOCKET.SND_MAX], edi
|
||||
mov [ptr + TCP_SOCKET.SND_NXT], edi
|
||||
mov [ptr + TCP_SOCKET.SND_UNA], edi
|
||||
pop edi
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
macro TCP_rcvseqinit ptr {
|
||||
|
||||
push edi
|
||||
mov edi, [ptr + TCP_SOCKET.IRS]
|
||||
inc edi
|
||||
mov [ptr + TCP_SOCKET.RCV_NXT], edi
|
||||
mov [ptr + TCP_SOCKET.RCV_ADV], edi
|
||||
pop edi
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
macro TCP_init_socket socket {
|
||||
|
||||
mov [socket + TCP_SOCKET.t_maxseg], TCP_mss_default
|
||||
mov [socket + TCP_SOCKET.t_flags], TF_REQ_SCALE or TF_REQ_TSTMP
|
||||
|
||||
mov [socket + TCP_SOCKET.t_srtt], TCP_time_srtt_default
|
||||
mov [socket + TCP_SOCKET.t_rttvar], TCP_time_rtt_default * 4
|
||||
mov [socket + TCP_SOCKET.t_rttmin], TCP_time_re_min
|
||||
;;; TODO: TCP_time_rangeset
|
||||
|
||||
mov [socket + TCP_SOCKET.SND_CWND], TCP_max_win shl TCP_max_winshift
|
||||
mov [socket + TCP_SOCKET.SND_SSTHRESH], TCP_max_win shl TCP_max_winshift
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
;---------------------------
|
||||
;
|
||||
; TCP_pull_out_of_band
|
||||
;
|
||||
; IN: eax =
|
||||
; ebx = socket ptr
|
||||
; edx = tcp packet ptr
|
||||
;
|
||||
; OUT: /
|
||||
;
|
||||
;---------------------------
|
||||
|
||||
align 4
|
||||
TCP_pull_out_of_band:
|
||||
|
||||
DEBUGF 1,"TCP_pull_out_of_band\n"
|
||||
|
||||
;;;; 1282-1305
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;-------------------------
|
||||
;
|
||||
; TCP_drop
|
||||
;
|
||||
; IN: eax = socket ptr
|
||||
; ebx = error number
|
||||
;
|
||||
; OUT: eax = socket ptr
|
||||
;
|
||||
;-------------------------
|
||||
align 4
|
||||
TCP_drop:
|
||||
|
||||
DEBUGF 1,"TCP_drop: %x\n", eax
|
||||
|
||||
cmp [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
|
||||
jb .no_syn_received
|
||||
|
||||
mov [eax + TCP_SOCKET.t_state], TCPS_CLOSED
|
||||
|
||||
call TCP_output
|
||||
|
||||
;;; TODO: update stats
|
||||
|
||||
jmp TCP_close
|
||||
|
||||
.no_syn_received:
|
||||
|
||||
;;; TODO: update stats
|
||||
|
||||
;;; TODO: check if error code is "Connection timed out' and handle accordingly
|
||||
|
||||
mov [eax + SOCKET.errorcode], ebx
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;-------------------------
|
||||
;
|
||||
; TCP_close
|
||||
;
|
||||
; IN: eax = socket ptr
|
||||
; OUT: eax = socket ptr
|
||||
;
|
||||
;-------------------------
|
||||
align 4
|
||||
TCP_close:
|
||||
|
||||
DEBUGF 1,"TCP_close: %x\n", eax
|
||||
|
||||
;;; TODO: update RTT and mean deviation
|
||||
;;; TODO: update slow start threshold
|
||||
|
||||
call SOCKET_is_disconnected
|
||||
call SOCKET_free
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
;-------------------------
|
||||
;
|
||||
; TCP_outflags
|
||||
;
|
||||
; IN: eax = socket ptr
|
||||
;
|
||||
; OUT: edx = flags
|
||||
;
|
||||
;-------------------------
|
||||
align 4
|
||||
TCP_outflags:
|
||||
|
||||
mov edx, [eax + TCP_SOCKET.t_state]
|
||||
movzx edx, byte [edx + .flaglist]
|
||||
|
||||
DEBUGF 1,"TCP_outflags: socket=%x flags=%x\n", eax, dl
|
||||
|
||||
ret
|
||||
|
||||
.flaglist:
|
||||
|
||||
db TH_RST + TH_ACK ; TCPS_CLOSED
|
||||
db 0 ; TCPS_LISTEN
|
||||
db TH_SYN ; TCPS_SYN_SENT
|
||||
db TH_SYN + TH_ACK ; TCPS_SYN_RECEIVED
|
||||
db TH_ACK ; TCPS_ESTABLISHED
|
||||
db TH_ACK ; TCPS_CLOSE_WAIT
|
||||
db TH_FIN + TH_ACK ; TCPS_FIN_WAIT_1
|
||||
db TH_FIN + TH_ACK ; TCPS_CLOSING
|
||||
db TH_FIN + TH_ACK ; TCPS_LAST_ACK
|
||||
db TH_ACK ; TCPS_FIN_WAIT_2
|
||||
db TH_ACK ; TCPS_TIMED_WAIT
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;---------------------------------------
|
||||
;
|
||||
; The fast way to send an ACK/RST/keepalive segment
|
||||
;
|
||||
; TCP_respond
|
||||
;
|
||||
; IN: ebx = socket ptr
|
||||
; cl = flags
|
||||
;
|
||||
;--------------------------------------
|
||||
align 4
|
||||
TCP_respond:
|
||||
|
||||
DEBUGF 1,"TCP_respond_socket: socket=%x flags=%x\n", ebx, cl
|
||||
|
||||
;---------------------
|
||||
; Create the IP packet
|
||||
|
||||
push cx ebx
|
||||
mov eax, [ebx + IP_SOCKET.RemoteIP]
|
||||
mov edx, [ebx + IP_SOCKET.LocalIP]
|
||||
mov ecx, sizeof.TCP_header
|
||||
mov di, IP_PROTO_TCP shl 8 + 128
|
||||
call IPv4_output
|
||||
test edi, edi
|
||||
jz .error
|
||||
pop esi cx
|
||||
push edx eax
|
||||
|
||||
;-----------------------------------------------
|
||||
; Fill in the TCP header by using the socket ptr
|
||||
|
||||
mov ax, [esi + TCP_SOCKET.LocalPort]
|
||||
stosw
|
||||
mov ax, [esi + TCP_SOCKET.RemotePort]
|
||||
stosw
|
||||
mov eax, [esi + TCP_SOCKET.SND_NXT]
|
||||
bswap eax
|
||||
stosd
|
||||
mov eax, [esi + TCP_SOCKET.RCV_NXT]
|
||||
bswap eax
|
||||
stosd
|
||||
mov al, 0x50 ; Dataoffset: 20 bytes (TCP_header.DataOffset)
|
||||
stosb
|
||||
mov al, cl
|
||||
stosb
|
||||
; mov ax, [esi + TCP_SOCKET.RCV_WND]
|
||||
; rol ax, 8
|
||||
mov ax, 0x00a0 ;;;;;;; FIXME
|
||||
stosw ; window
|
||||
xor eax, eax
|
||||
stosd ; checksum + urgentpointer
|
||||
|
||||
;---------------------
|
||||
; Fill in the checksum
|
||||
|
||||
.checksum:
|
||||
sub edi, sizeof.TCP_header
|
||||
mov ecx, sizeof.TCP_header
|
||||
xchg esi, edi
|
||||
TCP_checksum (edi + IP_SOCKET.LocalIP), (edi + IP_SOCKET.RemoteIP)
|
||||
mov [esi+TCP_header.Checksum], dx
|
||||
|
||||
;--------------------
|
||||
; And send the segment
|
||||
|
||||
call [ebx + NET_DEVICE.transmit]
|
||||
ret
|
||||
|
||||
.error:
|
||||
DEBUGF 1,"TCP_respond_socket: failed\n"
|
||||
add esp, 2 + 4
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;-------------------------
|
||||
; TCP_respond_segment:
|
||||
;
|
||||
; IN: edx = segment ptr (a previously received segment)
|
||||
; edi = ptr to dest and src IPv4 addresses
|
||||
; cl = flags
|
||||
|
||||
align 4
|
||||
TCP_respond_segment:
|
||||
|
||||
DEBUGF 1,"TCP_respond_segment: frame=%x flags=%x\n", edx, cl
|
||||
|
||||
;---------------------
|
||||
; Create the IP packet
|
||||
|
||||
push cx edx
|
||||
mov ebx, [edi + 4]
|
||||
mov eax, [edi]
|
||||
mov ecx, sizeof.TCP_header
|
||||
mov di, IP_PROTO_TCP shl 8 + 128
|
||||
call IPv4_output
|
||||
jz .error
|
||||
pop esi cx
|
||||
|
||||
push edx eax
|
||||
|
||||
;---------------------------------------------------
|
||||
; Fill in the TCP header by using a received segment
|
||||
|
||||
mov ax, [esi + TCP_header.DestinationPort]
|
||||
stosw
|
||||
mov ax, [esi + TCP_header.SourcePort]
|
||||
stosw
|
||||
mov eax, [esi + TCP_header.AckNumber]
|
||||
bswap eax
|
||||
stosd
|
||||
xor eax, eax
|
||||
stosd
|
||||
mov al, 0x50 ; Dataoffset: 20 bytes (sizeof.TCP_header/4 shl 4)
|
||||
stosb
|
||||
mov al, cl
|
||||
stosb
|
||||
mov ax, 1280
|
||||
rol ax, 8
|
||||
stosw ; window
|
||||
xor eax, eax
|
||||
stosd ; checksum + urgentpointer
|
||||
|
||||
;---------------------
|
||||
; Fill in the checksum
|
||||
|
||||
lea esi, [edi - sizeof.TCP_header]
|
||||
mov ecx, sizeof.TCP_header
|
||||
TCP_checksum (esi - sizeof.IPv4_header + IPv4_header.DestinationAddress),\ ; FIXME
|
||||
(esi - sizeof.IPv4_header + IPv4_header.SourceAddress)
|
||||
mov [esi + TCP_header.Checksum], dx
|
||||
|
||||
;--------------------
|
||||
; And send the segment
|
||||
|
||||
call [ebx + NET_DEVICE.transmit]
|
||||
ret
|
||||
|
||||
.error:
|
||||
DEBUGF 1,"TCP_respond_segment: failed\n"
|
||||
add esp, 2+4
|
||||
|
||||
ret
|
||||
|
||||
|
||||
macro TCPT_RANGESET timer, value, min, max {
|
||||
|
||||
local .min
|
||||
local .max
|
||||
local .done
|
||||
|
||||
cmp value, min
|
||||
jb .min
|
||||
cmp value, max
|
||||
ja .max
|
||||
|
||||
mov timer, value
|
||||
jmp .done
|
||||
|
||||
.min:
|
||||
mov timer, value
|
||||
jmp .done
|
||||
|
||||
.max:
|
||||
mov timer, value
|
||||
jmp .done
|
||||
|
||||
.done:
|
||||
}
|
||||
|
||||
|
||||
align 4
|
||||
TCP_set_persist:
|
||||
|
||||
DEBUGF 1,"TCP_set_persist\n"
|
||||
|
||||
; First, check if retransmit timer is not set, retransmit and persist are mutually exclusive
|
||||
|
||||
cmp [eax + TCP_SOCKET.timer_retransmission], 0
|
||||
ja @f
|
||||
|
||||
; calculate RTO
|
||||
push ebx
|
||||
mov ebx, [eax + TCP_SOCKET.t_srtt]
|
||||
shr ebx, 2
|
||||
add ebx, [eax + TCP_SOCKET.t_rttvar]
|
||||
shr ebx, 1
|
||||
|
||||
mov cl, [eax + TCP_SOCKET.t_rxtshift]
|
||||
shl ebx, cl
|
||||
|
||||
; Start/restart persistance timer.
|
||||
|
||||
TCPT_RANGESET [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max
|
||||
|
||||
pop ebx
|
||||
|
||||
cmp [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift
|
||||
jae @f
|
||||
inc [eax + TCP_SOCKET.t_rxtshift]
|
||||
@@:
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; eax = rtt
|
||||
; ebx = socket ptr
|
||||
|
||||
align 4
|
||||
TCP_xmit_timer:
|
||||
|
||||
DEBUGF 1,"TCP_xmit_timer: socket=%x rtt=%d0ms\n", ebx, eax
|
||||
|
||||
;TODO: update stats
|
||||
|
||||
cmp [ebx + TCP_SOCKET.t_rtt], 0
|
||||
je .no_rtt_yet
|
||||
|
||||
; srtt is stored as a fixed point with 3 bits after the binary point.
|
||||
; The following magic is equivalent of the smoothing algorithm in rfc793 with an alpha of .875
|
||||
; (srtt = rtt/8 + srtt*7/8 in fixed point)
|
||||
; Adjust rtt to origin 0.
|
||||
|
||||
push ecx
|
||||
mov ecx, [ebx + TCP_SOCKET.t_srtt]
|
||||
shr ecx, TCP_RTT_SHIFT
|
||||
sub eax, ecx
|
||||
dec eax
|
||||
pop ecx
|
||||
|
||||
add [ebx + TCP_SOCKET.t_srtt], eax
|
||||
ja @f
|
||||
mov [ebx + TCP_SOCKET.t_srtt], 1
|
||||
@@:
|
||||
|
||||
; We accumulate a smoothed rtt variance (actually, a smoothed mean difference),
|
||||
; then set the retransmit timer to smoothed rtt + 4 times the smoothed variance.
|
||||
; rttvar is stored as fixed point with 2 bits after the binary point.
|
||||
; The following is equivalent to rfc793 smoothing with an alpha of .75
|
||||
; (rttvar = rttvar*3/4 + delta/4) (delta = eax)
|
||||
|
||||
; get abs(eax)
|
||||
push edx
|
||||
cdq
|
||||
xor eax, edx
|
||||
sub eax, edx
|
||||
|
||||
mov edx, [ebx + TCP_SOCKET.t_rttvar]
|
||||
shr edx, TCP_RTTVAR_SHIFT
|
||||
sub eax, edx
|
||||
pop edx
|
||||
|
||||
add [ebx + TCP_SOCKET.t_rttvar], eax
|
||||
ja @f
|
||||
mov [ebx + TCP_SOCKET.t_rttvar], 1
|
||||
@@:
|
||||
ret
|
||||
|
||||
|
||||
.no_rtt_yet:
|
||||
|
||||
push ecx
|
||||
mov ecx, eax
|
||||
shl ecx, TCP_RTT_SHIFT
|
||||
mov [ebx + TCP_SOCKET.t_srtt], ecx
|
||||
|
||||
shl eax, TCP_RTTVAR_SHIFT - 1
|
||||
mov [ebx + TCP_SOCKET.t_rttvar], eax
|
||||
pop ecx
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
; eax = max segment size
|
||||
; ebx = socket ptr
|
||||
align 4
|
||||
TCP_mss:
|
||||
|
||||
cmp eax, 1420 ; FIXME
|
||||
jbe @f
|
||||
mov eax, 1420
|
||||
@@:
|
||||
mov [ebx + TCP_SOCKET.t_maxseg], eax
|
||||
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
; ebx = socket ptr
|
||||
; edx = segment ptr
|
||||
align 4
|
||||
TCP_reassemble:
|
||||
|
||||
|
||||
|
||||
ret
|
||||
|
168
kernel/trunk/network/tcp_timer.inc
Normal file
168
kernel/trunk/network/tcp_timer.inc
Normal file
@ -0,0 +1,168 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; Part of the TCP/IP network stack for KolibriOS ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr@kolibrios.org ;;
|
||||
;; ;;
|
||||
;; Based on the code of 4.4BSD ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
$Revision: 3143 $
|
||||
|
||||
;----------------------
|
||||
; 160 ms timer
|
||||
;----------------------
|
||||
macro TCP_timer_160ms {
|
||||
|
||||
local .loop
|
||||
local .exit
|
||||
|
||||
mov ebx, net_sockets
|
||||
.loop:
|
||||
mov ebx, [ebx + SOCKET.NextPtr]
|
||||
or ebx, ebx
|
||||
jz .exit
|
||||
|
||||
cmp [ebx + SOCKET.Domain], AF_INET4
|
||||
jne .loop
|
||||
|
||||
cmp [ebx + SOCKET.Protocol], IP_PROTO_TCP
|
||||
jne .loop
|
||||
|
||||
test [ebx + TCP_SOCKET.t_flags], TF_DELACK
|
||||
jz .loop
|
||||
and [ebx + TCP_SOCKET.t_flags], not (TF_DELACK)
|
||||
|
||||
push ebx
|
||||
mov cl, TH_ACK
|
||||
call TCP_respond
|
||||
; and [ebx + TCP_SOCKET.t_flags], TF_ACKNOW ;;
|
||||
; mov eax, ebx ;;
|
||||
; call TCP_output ;;
|
||||
pop ebx
|
||||
|
||||
jmp .loop
|
||||
|
||||
.exit:
|
||||
|
||||
}
|
||||
|
||||
|
||||
;----------------------
|
||||
; 640 ms timer
|
||||
;----------------------
|
||||
macro TCP_timer_640ms {
|
||||
|
||||
local .loop
|
||||
local .exit
|
||||
|
||||
; Update TCP sequence number
|
||||
|
||||
add [TCP_sequence_num], 64000
|
||||
|
||||
; scan through all the active TCP sockets, decrementing ALL timers
|
||||
; timers do not have the chance to wrap because the keepalive timer will kill the socket when it expires
|
||||
|
||||
mov eax, net_sockets
|
||||
.loop:
|
||||
mov eax, [eax + SOCKET.NextPtr]
|
||||
.check_only:
|
||||
or eax, eax
|
||||
jz .exit
|
||||
|
||||
cmp [eax + SOCKET.Domain], AF_INET4
|
||||
jne .loop
|
||||
|
||||
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
|
||||
jne .loop
|
||||
|
||||
inc [eax + TCP_SOCKET.t_idle]
|
||||
dec [eax + TCP_SOCKET.timer_retransmission]
|
||||
jnz .check_more2
|
||||
|
||||
DEBUGF 1,"socket %x: Retransmission timer expired\n", eax
|
||||
|
||||
push eax
|
||||
call TCP_output
|
||||
pop eax
|
||||
|
||||
.check_more2:
|
||||
dec [eax + TCP_SOCKET.timer_keepalive]
|
||||
jnz .check_more3
|
||||
|
||||
DEBUGF 1,"socket %x: Keepalive expired\n", eax
|
||||
|
||||
cmp [eax + TCP_SOCKET.state], TCPS_ESTABLISHED
|
||||
ja .dont_kill
|
||||
|
||||
push eax
|
||||
call TCP_disconnect
|
||||
pop eax
|
||||
jmp .loop
|
||||
|
||||
.dont_kill:
|
||||
test [eax + SOCKET.options], SO_KEEPALIVE
|
||||
jz .reset_keepalive
|
||||
|
||||
push eax
|
||||
mov ebx, eax
|
||||
xor cl, cl
|
||||
call TCP_respond ; send keepalive
|
||||
pop eax
|
||||
mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
|
||||
jmp .check_more3
|
||||
|
||||
.reset_keepalive:
|
||||
mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_idle
|
||||
|
||||
.check_more3:
|
||||
dec [eax + TCP_SOCKET.timer_timed_wait]
|
||||
jnz .check_more5
|
||||
|
||||
DEBUGF 1,"socket %x: 2MSL timer expired\n", eax
|
||||
|
||||
.check_more5:
|
||||
dec [eax + TCP_SOCKET.timer_persist]
|
||||
jnz .loop
|
||||
|
||||
DEBUGF 1,"socket %x: persist timer expired\n", eax
|
||||
|
||||
call TCP_set_persist
|
||||
mov [eax + TCP_SOCKET.t_force], 1
|
||||
push eax
|
||||
call TCP_output
|
||||
pop eax
|
||||
mov [eax + TCP_SOCKET.t_force], 0
|
||||
|
||||
jmp .loop
|
||||
.exit:
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
; eax = socket
|
||||
|
||||
TCP_cancel_timers:
|
||||
|
||||
push eax edi
|
||||
|
||||
lea edi, [eax + TCP_SOCKET.timer_retransmission]
|
||||
xor eax, eax
|
||||
stosd
|
||||
stosd
|
||||
stosd
|
||||
stosd
|
||||
stosd
|
||||
|
||||
pop edi eax
|
||||
|
||||
|
||||
ret
|
102
kernel/trunk/network/tcp_usreq.inc
Normal file
102
kernel/trunk/network/tcp_usreq.inc
Normal file
@ -0,0 +1,102 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; Part of the TCP/IP network stack for KolibriOS ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr@kolibrios.org ;;
|
||||
;; ;;
|
||||
;; Based on the code of 4.4BSD ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
;-------------------------
|
||||
;
|
||||
; TCP_usrclose
|
||||
;
|
||||
; Move connection to next state, based on process close.
|
||||
;
|
||||
; IN: eax = socket ptr
|
||||
;
|
||||
;-------------------------
|
||||
align 4
|
||||
TCP_usrclosed:
|
||||
|
||||
DEBUGF 1,"TCP_usrclosed: %x\n", eax
|
||||
|
||||
push ebx
|
||||
mov ebx, [eax + TCP_SOCKET.t_state]
|
||||
mov ebx, dword [.switch + ebx*4]
|
||||
jmp ebx
|
||||
|
||||
.switch:
|
||||
|
||||
dd .close ; TCPS_CLOSED
|
||||
dd .close ; TCPS_LISTEN
|
||||
dd .close ; TCPS_SYN_SENT
|
||||
dd .wait1 ; TCPS_SYN_RECEIVED
|
||||
dd .wait1 ; TCPS_ESTABLISHED
|
||||
dd .last_ack ; TCPS_CLOSE_WAIT
|
||||
dd .ret ; TCPS_FIN_WAIT_1
|
||||
dd .ret ; TCPS_CLOSING
|
||||
dd .ret ; TCPS_LAST_ACK
|
||||
dd .disc ; TCPS_FIN_WAIT_2
|
||||
dd .disc ; TCPS_TIMED_WAIT
|
||||
|
||||
|
||||
.close:
|
||||
mov [eax + TCP_SOCKET.t_state], TCPS_CLOSED
|
||||
call TCP_close
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
.wait1:
|
||||
mov [eax + TCP_SOCKET.t_state], TCPS_FIN_WAIT_1
|
||||
; TODO: set timer?
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
.last_ack:
|
||||
mov [eax + TCP_SOCKET.t_state], TCPS_LAST_ACK
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
.disc:
|
||||
call SOCKET_is_disconnected
|
||||
; TODO: set timer?
|
||||
.ret:
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
;-------------------------
|
||||
;
|
||||
; TCP_disconnect
|
||||
;
|
||||
; IN: eax = socket ptr
|
||||
; OUT: eax = socket ptr
|
||||
;
|
||||
;-------------------------
|
||||
align 4
|
||||
TCP_disconnect:
|
||||
|
||||
DEBUGF 1,"TCP_disconnect: %x\n", eax
|
||||
|
||||
cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
|
||||
jb TCP_close
|
||||
|
||||
|
||||
; TODO: implement LINGER ?
|
||||
|
||||
call SOCKET_is_disconnecting
|
||||
call TCP_usrclosed
|
||||
call TCP_output
|
||||
|
||||
ret
|
@ -1,153 +1,325 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; ;;
|
||||
;; UDP.INC ;;
|
||||
;; ;;
|
||||
;; UDP Processes for Menuet OS TCP/IP stack ;;
|
||||
;; ;;
|
||||
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;;
|
||||
;; ;;
|
||||
;; See file COPYING for details ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; UDP.INC ;;
|
||||
;; ;;
|
||||
;; Part of the tcp/ip network stack for KolibriOS ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr@kolibrios.org ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
$Revision$
|
||||
$Revision: 2995 $
|
||||
|
||||
|
||||
;*******************************************************************
|
||||
; Interface
|
||||
;
|
||||
; udp_rx Handles received IP packets with the UDP protocol
|
||||
;
|
||||
;*******************************************************************
|
||||
struct UDP_header
|
||||
|
||||
SourcePort dw ?
|
||||
DestinationPort dw ?
|
||||
Length dw ? ; Length of (UDP Header + Data)
|
||||
Checksum dw ?
|
||||
|
||||
ends
|
||||
|
||||
|
||||
;
|
||||
; UDP Payload ( Data field in IP datagram )
|
||||
;
|
||||
; 0 1 2 3
|
||||
; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
;
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | Source Port | Destination Port |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | Length ( UDP Header + Data ) | Checksum |
|
||||
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
; | UDP Data |
|
||||
; +-+-+-.......... -+
|
||||
;
|
||||
align 4
|
||||
uglobal
|
||||
UDP_PACKETS_TX rd MAX_NET_DEVICES
|
||||
UDP_PACKETS_RX rd MAX_NET_DEVICES
|
||||
endg
|
||||
|
||||
struc UDP_PACKET
|
||||
{ .SourcePort dw ? ;+00
|
||||
.DestinationPort dw ? ;+02
|
||||
.Length dw ? ;+04 - Length of (UDP Header + Data)
|
||||
.Checksum dw ? ;+06
|
||||
.Data db ? ;+08
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; UDP_init
|
||||
;
|
||||
; This function resets all UDP variables
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
macro UDP_init {
|
||||
|
||||
xor eax, eax
|
||||
mov edi, UDP_PACKETS_TX
|
||||
mov ecx, 2*MAX_NET_DEVICES
|
||||
rep stosd
|
||||
}
|
||||
|
||||
virtual at 0
|
||||
UDP_PACKET UDP_PACKET
|
||||
end virtual
|
||||
|
||||
macro UDP_checksum IP1, IP2 { ; esi = ptr to udp packet, ecx = packet size, destroys: ecx, edx
|
||||
|
||||
; Pseudoheader
|
||||
mov edx, IP_PROTO_UDP
|
||||
|
||||
add dl, [IP1+1]
|
||||
adc dh, [IP1+0]
|
||||
adc dl, [IP1+3]
|
||||
adc dh, [IP1+2]
|
||||
|
||||
adc dl, [IP2+1]
|
||||
adc dh, [IP2+0]
|
||||
adc dl, [IP2+3]
|
||||
adc dh, [IP2+2]
|
||||
|
||||
adc dl, cl ; byte[esi+UDP_header.Length+1]
|
||||
adc dh, ch ; byte[esi+UDP_header.Length+0]
|
||||
|
||||
; Done with pseudoheader, now do real header
|
||||
adc dl, byte[esi+UDP_header.SourcePort+1]
|
||||
adc dh, byte[esi+UDP_header.SourcePort+0]
|
||||
|
||||
adc dl, byte[esi+UDP_header.DestinationPort+1]
|
||||
adc dh, byte[esi+UDP_header.DestinationPort+0]
|
||||
|
||||
adc dl, byte[esi+UDP_header.Length+1]
|
||||
adc dh, byte[esi+UDP_header.Length+0]
|
||||
|
||||
adc edx, 0
|
||||
|
||||
; Done with header, now do data
|
||||
push esi
|
||||
movzx ecx, [esi+UDP_header.Length]
|
||||
rol cx , 8
|
||||
sub cx , sizeof.UDP_header
|
||||
add esi, sizeof.UDP_header
|
||||
|
||||
call checksum_1
|
||||
call checksum_2
|
||||
pop esi
|
||||
|
||||
add [esi+UDP_header.Checksum], dx ; this final instruction will set or clear ZF :)
|
||||
|
||||
}
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
; Function
|
||||
; udp_rx [by Johnny_B]
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; Description
|
||||
; UDP protocol handler
|
||||
; This is a kernel function, called by ip_rx
|
||||
; IP buffer address given in edx
|
||||
; IP buffer number in eax
|
||||
; Free up (or re-use) IP buffer when finished
|
||||
; UDP_input:
|
||||
;
|
||||
;***************************************************************************
|
||||
; Called by IPv4_input,
|
||||
; this procedure will inject the udp data diagrams in the application sockets.
|
||||
;
|
||||
; IN: [esp] = Pointer to buffer
|
||||
; [esp+4] = size of buffer
|
||||
; ebx = ptr to device struct
|
||||
; ecx = UDP Packet size
|
||||
; esi = ptr to UDP header
|
||||
; edi = ptr to ipv4 source and dest address
|
||||
;
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
UDP_input:
|
||||
|
||||
proc udp_rx stdcall
|
||||
push eax
|
||||
DEBUGF 1,"UDP_input: size=%u\n", ecx
|
||||
|
||||
; First validate the header & checksum. Discard buffer if error
|
||||
; First validate, checksum
|
||||
|
||||
neg [esi + UDP_header.Checksum] ; substract checksum from 0
|
||||
jz .no_checksum ; if checksum is zero, it is considered valid
|
||||
|
||||
; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct
|
||||
|
||||
UDP_checksum (edi), (edi+4)
|
||||
jnz .checksum_mismatch
|
||||
|
||||
.no_checksum:
|
||||
DEBUGF 1,"UDP_input: checksum ok\n"
|
||||
|
||||
; Convert length to little endian
|
||||
|
||||
rol [esi + UDP_header.Length], 8
|
||||
|
||||
; Look for a socket where
|
||||
; IP Packet UDP Destination Port = local Port
|
||||
; IP Packet SA = Remote IP
|
||||
|
||||
mov ax, [edx + 20 + UDP_PACKET.DestinationPort] ; get the local port from
|
||||
; the IP packet's UDP header
|
||||
|
||||
mov ebx, net_sockets
|
||||
mov cx, [esi + UDP_header.SourcePort]
|
||||
mov dx, [esi + UDP_header.DestinationPort]
|
||||
mov edi, [edi + 4] ; ipv4 source address
|
||||
mov eax, net_sockets
|
||||
|
||||
.next_socket:
|
||||
mov ebx, [ebx + SOCKET.NextPtr]
|
||||
or ebx, ebx
|
||||
jz .exit ; No match, so exit
|
||||
cmp [ebx + SOCKET.LocalPort], ax ; ax will hold the 'wrong' value,
|
||||
; but the comparision is correct
|
||||
jne .next_socket ; Return back if no match
|
||||
mov eax, [eax + SOCKET.NextPtr]
|
||||
or eax, eax
|
||||
jz .dump
|
||||
|
||||
; For dhcp, we must allow any remote server to respond.
|
||||
; I will accept the first incoming response to be the one
|
||||
; I bind to, if the socket is opened with a destination IP address of
|
||||
; 255.255.255.255
|
||||
cmp [ebx + SOCKET.RemoteIP], 0xffffffff
|
||||
je @f
|
||||
cmp [eax + SOCKET.Domain], AF_INET4
|
||||
jne .next_socket
|
||||
|
||||
mov eax, [edx + IP_PACKET.SourceAddress] ; get the Source address from the IP packet
|
||||
cmp [ebx + SOCKET.RemoteIP], eax
|
||||
jne .exit ; Quit if the source IP is not valid
|
||||
cmp [eax + SOCKET.Protocol], IP_PROTO_UDP
|
||||
jne .next_socket
|
||||
|
||||
@@: ; OK - we have a valid UDP packet for this socket.
|
||||
; First, update the sockets remote port number with the incoming msg
|
||||
; - it will have changed
|
||||
; from the original ( 69 normally ) to allow further connects
|
||||
mov ax, [edx + 20 + UDP_PACKET.SourcePort] ; get the UDP source port
|
||||
; ( was 69, now new )
|
||||
mov [ebx + SOCKET.RemotePort], ax
|
||||
cmp [eax + UDP_SOCKET.LocalPort], dx
|
||||
jne .next_socket
|
||||
|
||||
; Now, copy data to socket. We have socket address as [eax + sockets].
|
||||
; We have IP packet in edx
|
||||
DEBUGF 1,"UDP_input: socket=%x\n", eax
|
||||
|
||||
; get # of bytes in ecx
|
||||
movzx ecx, [edx + IP_PACKET.TotalLength] ; total length of IP packet. Subtract
|
||||
xchg cl, ch ; 20 + 8 gives data length
|
||||
sub ecx, 28
|
||||
;;; TODO: when packet is processed, check more sockets!
|
||||
|
||||
mov eax, [ebx + SOCKET.rxDataCount] ; get # of bytes already in buffer
|
||||
add [ebx + SOCKET.rxDataCount], ecx ; increment the count of bytes in buffer
|
||||
; cmp [eax + IP_SOCKET.RemoteIP], 0xffffffff
|
||||
; je @f
|
||||
; cmp [eax + IP_SOCKET.RemoteIP], edi
|
||||
; jne .next_socket
|
||||
; @@:
|
||||
;
|
||||
; FIXME: UDP should check remote IP, but not under all circumstances!
|
||||
|
||||
; ecx has count, edx points to data
|
||||
cmp [eax + UDP_SOCKET.firstpacket], 0
|
||||
je .updateport
|
||||
|
||||
add edx, 28 ; edx now points to the data
|
||||
lea edi, [ebx + eax + SOCKETHEADERSIZE]
|
||||
mov esi, edx
|
||||
cmp [eax + UDP_SOCKET.RemotePort], cx
|
||||
jne .dump
|
||||
|
||||
cld
|
||||
rep movsb ; copy the data across
|
||||
pusha
|
||||
lea ecx, [eax + SOCKET.mutex]
|
||||
call mutex_lock
|
||||
popa
|
||||
|
||||
; flag an event to the application
|
||||
mov eax, [ebx + SOCKET.PID] ; get socket owner PID
|
||||
mov ecx, 1
|
||||
mov esi, TASK_DATA + TASKDATA.pid
|
||||
.updatesock:
|
||||
inc [UDP_PACKETS_RX] ; Fixme: correct interface?
|
||||
|
||||
.next_pid:
|
||||
cmp [esi], eax
|
||||
je .found_pid
|
||||
inc ecx
|
||||
add esi, 0x20
|
||||
cmp ecx, [TASK_COUNT]
|
||||
jbe .next_pid
|
||||
movzx ecx, [esi + UDP_header.Length]
|
||||
sub ecx, sizeof.UDP_header
|
||||
add esi, sizeof.UDP_header
|
||||
|
||||
jmp .exit
|
||||
jmp SOCKET_input
|
||||
|
||||
.found_pid:
|
||||
shl ecx, 8
|
||||
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event
|
||||
.updateport:
|
||||
pusha
|
||||
lea ecx, [eax + SOCKET.mutex]
|
||||
call mutex_lock
|
||||
popa
|
||||
|
||||
DEBUGF 1,"UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf
|
||||
mov [eax + UDP_SOCKET.RemotePort], cx
|
||||
inc [eax + UDP_SOCKET.firstpacket]
|
||||
|
||||
jmp .updatesock
|
||||
|
||||
|
||||
.checksum_mismatch:
|
||||
DEBUGF 2,"UDP_input: checksum mismatch\n"
|
||||
|
||||
.dump:
|
||||
call kernel_free
|
||||
add esp, 4 ; pop (balance stack)
|
||||
DEBUGF 2,"UDP_input: dumping\n"
|
||||
|
||||
.exit:
|
||||
pop eax
|
||||
call freeBuff ; Discard the packet
|
||||
ret
|
||||
endp
|
||||
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; UDP_output
|
||||
;
|
||||
; IN: eax = socket pointer
|
||||
; ecx = number of bytes to send
|
||||
; esi = pointer to data
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
|
||||
align 4
|
||||
UDP_output:
|
||||
|
||||
DEBUGF 1,"UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi
|
||||
|
||||
mov dx, [eax + UDP_SOCKET.RemotePort]
|
||||
DEBUGF 1,"UDP_output: remote port=%x, ", dx ; FIXME: find a way to print big endian values with debugf
|
||||
rol edx, 16
|
||||
mov dx, [eax + UDP_SOCKET.LocalPort]
|
||||
DEBUGF 1,"local port=%x\n", dx
|
||||
|
||||
sub esp, 8 ; Data ptr and data size will be placed here
|
||||
push edx esi
|
||||
mov ebx, [eax + SOCKET.device]
|
||||
mov edx, [eax + IP_SOCKET.LocalIP]
|
||||
mov eax, [eax + IP_SOCKET.RemoteIP]
|
||||
mov di, IP_PROTO_UDP shl 8 + 128
|
||||
add ecx, sizeof.UDP_header
|
||||
call IPv4_output
|
||||
jz .fail
|
||||
mov [esp + 8], eax ; pointer to buffer start
|
||||
mov [esp + 8 + 4], edx ; buffer size
|
||||
|
||||
mov [edi + UDP_header.Length], cx
|
||||
rol [edi + UDP_header.Length], 8
|
||||
|
||||
pop esi
|
||||
push edi ecx
|
||||
sub ecx, sizeof.UDP_header
|
||||
add edi, sizeof.UDP_header
|
||||
shr ecx, 2
|
||||
rep movsd
|
||||
mov ecx, [esp]
|
||||
and ecx, 3
|
||||
rep movsb
|
||||
pop ecx edi
|
||||
|
||||
pop dword [edi + UDP_header.SourcePort]
|
||||
|
||||
; Checksum
|
||||
mov esi, edi
|
||||
mov [edi + UDP_header.Checksum], 0
|
||||
UDP_checksum (edi-4), (edi-8) ; FIXME: IPv4 packet could have options..
|
||||
|
||||
DEBUGF 1,"UDP_output: sending with device %x\n", ebx
|
||||
call [ebx + NET_DEVICE.transmit]
|
||||
test eax, eax
|
||||
jnz @f
|
||||
inc [UDP_PACKETS_TX] ; FIXME: correct device?
|
||||
@@:
|
||||
|
||||
ret
|
||||
|
||||
.fail:
|
||||
DEBUGF 1,"UDP_output: failed\n"
|
||||
add esp, 4+4+8
|
||||
or eax, -1
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
;
|
||||
; UDP_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
|
||||
UDP_api:
|
||||
|
||||
movzx eax, bh
|
||||
shl eax, 2
|
||||
|
||||
test bl, bl
|
||||
jz .packets_tx ; 0
|
||||
dec bl
|
||||
jz .packets_rx ; 1
|
||||
|
||||
.error:
|
||||
mov eax, -1
|
||||
ret
|
||||
|
||||
.packets_tx:
|
||||
mov eax, [UDP_PACKETS_TX + eax]
|
||||
ret
|
||||
|
||||
.packets_rx:
|
||||
mov eax, [UDP_PACKETS_RX + eax]
|
||||
ret
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,22 +1,27 @@
|
||||
; Socket types
|
||||
SOCK_STREAM = 1
|
||||
SOCK_DGRAM = 2
|
||||
SOCK_RAW = 3 ; not supported by the kernel
|
||||
SOCK_RAW = 3
|
||||
|
||||
; Socket options
|
||||
SO_NONBLOCK = 1 shl 31
|
||||
|
||||
; IP protocols
|
||||
IPPROTO_IP = 0
|
||||
IPPROTO_ICMP = 1 ; not supported by the kernel
|
||||
IPPROTO_ICMP = 1
|
||||
IPPROTO_TCP = 6
|
||||
IPPROTO_UDP = 17
|
||||
|
||||
; Address families
|
||||
AF_UNSPEC = 0
|
||||
AF_INET = 2 ; IPv4
|
||||
;AF_INET6 = 28 ; IPv6 (not supported)
|
||||
AF_LOCAL = 1
|
||||
AF_INET4 = 2 ; IPv4
|
||||
AF_INET6 = 28 ; IPv6 (not supported yet)
|
||||
|
||||
PF_UNSPEC = AF_UNSPEC
|
||||
PF_INET = AF_INET
|
||||
;PF_INET6 = AF_INET6
|
||||
PF_LOCAL = AF_LOCAL
|
||||
PF_INET4 = AF_INET4
|
||||
PF_INET6 = AF_INET6
|
||||
|
||||
; Flags for addrinfo
|
||||
AI_PASSIVE = 1
|
||||
@ -28,9 +33,17 @@ AI_ADDRCONFIG = 0x400
|
||||
; internal definition
|
||||
AI_SUPPORTED = 0x40F
|
||||
|
||||
; for system function 76
|
||||
API_ETH = 0 shl 16
|
||||
API_IPv4 = 1 shl 16
|
||||
API_ICMP = 2 shl 16
|
||||
API_UDP = 3 shl 16
|
||||
API_TCP = 4 shl 16
|
||||
API_ARP = 5 shl 16
|
||||
API_PPPOE = 6 shl 16
|
||||
|
||||
struct sockaddr_in
|
||||
sin_len db ? ; uint8_t
|
||||
sin_family db ? ; sa_family_t
|
||||
sin_family dw ? ; sa_family_t
|
||||
sin_port dw ? ; in_port_t
|
||||
sin_addr dd ? ; struct in_addr
|
||||
sin_zero rb 8 ; zero
|
||||
@ -43,8 +56,8 @@ struct addrinfo
|
||||
ai_protocol dd ? ; 0 or IPPROTO_*
|
||||
ai_addrlen dd ? ; length of ai_addr
|
||||
ai_canonname dd ? ; char*
|
||||
ai_addr dd ? ; struct sockaddr*
|
||||
ai_next dd ? ; struct addrinfo*
|
||||
ai_addr dd ? ; struct sockaddr*
|
||||
ai_next dd ? ; struct addrinfo*
|
||||
ends
|
||||
|
||||
EAI_ADDRFAMILY = 1
|
||||
@ -59,3 +72,23 @@ EAI_SOCKTYPE = 10
|
||||
EAI_BADHINTS = 12
|
||||
EAI_PROTOCOL = 13
|
||||
EAI_OVERFLOW = 14
|
||||
|
||||
socket fix 75, 0
|
||||
close fix 75, 1
|
||||
bind fix 75, 2
|
||||
listen fix 75, 3
|
||||
connect fix 75, 4
|
||||
accept fix 75, 5
|
||||
send fix 75, 6
|
||||
recv fix 75, 7
|
||||
setsockopt fix 75, 8
|
||||
getsockopt fix 75, 9
|
||||
socketpair fix 75, 10
|
||||
|
||||
|
||||
struct ARP_entry
|
||||
IP dd ?
|
||||
MAC dp ?
|
||||
status dw ?
|
||||
TTL dw ?
|
||||
ends
|
||||
|
156
programs/network/arpcfg/arpcfg.asm
Normal file
156
programs/network/arpcfg/arpcfg.asm
Normal file
@ -0,0 +1,156 @@
|
||||
;
|
||||
; ARPmanager for KolibriOS
|
||||
;
|
||||
; hidnplayr@gmail.com
|
||||
;
|
||||
|
||||
format binary as ""
|
||||
|
||||
use32
|
||||
|
||||
org 0x0
|
||||
|
||||
db 'MENUET01' ; 8 byte id
|
||||
dd 0x01 ; header version
|
||||
dd START ; start of code
|
||||
dd IM_END ; size of image
|
||||
dd (I_END+0x100) ; memory for app
|
||||
dd (I_END+0x100) ; esp
|
||||
dd 0x0 , 0x0 ; I_Param , I_Icon
|
||||
|
||||
include '../macros.inc'
|
||||
purge mov, add, sub
|
||||
include '../struct.inc'
|
||||
include '../network.inc'
|
||||
|
||||
START:
|
||||
|
||||
redraw:
|
||||
|
||||
mcall 12, 1
|
||||
mcall 0, 100 shl 16 + 520, 100 shl 16 + 240, 0x34bcbcbc, , str_name
|
||||
mcall 4, 25 shl 16 + 31, 0x80000000, str_legend
|
||||
mcall 12, 2
|
||||
|
||||
draw_stats:
|
||||
|
||||
mov edx, 50 shl 16 + 50
|
||||
mov [last], 0
|
||||
|
||||
.loop:
|
||||
mcall 76, API_ARP + 3, [last],,, arp_buf
|
||||
cmp eax, -1
|
||||
je mainloop
|
||||
|
||||
mcall 4, edx, 0x80000000, str_entry
|
||||
mov edx, ebx
|
||||
|
||||
mov eax, 47
|
||||
mov ebx, 0x00030000
|
||||
mov esi, 0x40000000
|
||||
mov edi, 0x00bcbcbc
|
||||
xor ecx, ecx
|
||||
|
||||
mov cl, byte[arp_buf.IP+0]
|
||||
mcall
|
||||
|
||||
mov cl, byte[arp_buf.IP+1]
|
||||
add edx, 24 shl 16
|
||||
mcall
|
||||
|
||||
mov cl, byte[arp_buf.IP+2]
|
||||
add edx, 24 shl 16
|
||||
mcall
|
||||
|
||||
mov cl, byte[arp_buf.IP+3]
|
||||
add edx, 24 shl 16
|
||||
mcall
|
||||
|
||||
|
||||
mov ebx, 0x00020100
|
||||
mov cl, byte[arp_buf.MAC+0]
|
||||
add edx, 36 shl 16
|
||||
mcall
|
||||
|
||||
mov cl, byte[arp_buf.MAC+1]
|
||||
add edx, 18 shl 16
|
||||
mcall
|
||||
|
||||
mov cl, byte[arp_buf.MAC+2]
|
||||
add edx, 18 shl 16
|
||||
mcall
|
||||
|
||||
mov cl, byte[arp_buf.MAC+3]
|
||||
add edx, 18 shl 16
|
||||
mcall
|
||||
|
||||
mov cl, byte[arp_buf.MAC+4]
|
||||
add edx, 18 shl 16
|
||||
mcall
|
||||
|
||||
mov cl, byte[arp_buf.MAC+5]
|
||||
add edx, 18 shl 16
|
||||
mcall
|
||||
|
||||
mov ebx, 0x00040000
|
||||
mov cx, [arp_buf.status]
|
||||
add edx, 30 shl 16
|
||||
mcall
|
||||
|
||||
mov cx, [arp_buf.TTL]
|
||||
add edx, 60 shl 16
|
||||
mcall
|
||||
|
||||
add dx, 20
|
||||
rol edx, 16
|
||||
mov dx, 50
|
||||
rol edx, 16
|
||||
inc [last]
|
||||
|
||||
jmp .loop
|
||||
|
||||
|
||||
mainloop:
|
||||
|
||||
mcall 23,50 ; wait for event with timeout (0,5 s)
|
||||
|
||||
cmp eax, 1
|
||||
je redraw
|
||||
cmp eax, 2
|
||||
je key
|
||||
cmp eax, 3
|
||||
je button
|
||||
|
||||
jmp draw_stats
|
||||
|
||||
|
||||
key:
|
||||
mcall 2
|
||||
jmp mainloop
|
||||
|
||||
|
||||
button: ; button
|
||||
mcall 17 ; get id
|
||||
cmp ah, 1
|
||||
je exit
|
||||
jmp redraw
|
||||
|
||||
exit:
|
||||
mcall -1
|
||||
|
||||
|
||||
|
||||
; DATA AREA
|
||||
|
||||
str_name db 'ARP manager', 0
|
||||
str_legend db '# IP-address MAC-address Status TTL', 0
|
||||
str_entry db ' . . . - - - - - s', 0
|
||||
|
||||
IM_END:
|
||||
|
||||
last dd ?
|
||||
arp_buf ARP_entry
|
||||
|
||||
I_END:
|
||||
|
||||
|
160
programs/network/dll.inc
Normal file
160
programs/network/dll.inc
Normal file
@ -0,0 +1,160 @@
|
||||
;-----------------------------------------------------------------------------
|
||||
proc mem.Alloc size ;/////////////////////////////////////////////////////////
|
||||
;-----------------------------------------------------------------------------
|
||||
push ebx ecx
|
||||
mov eax,[size]
|
||||
lea ecx,[eax+4+4095]
|
||||
and ecx, not 4095
|
||||
mcall 68,12
|
||||
test eax, eax
|
||||
jz @f
|
||||
add ecx,-4
|
||||
mov [eax],ecx
|
||||
add eax,4
|
||||
@@:
|
||||
pop ecx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
proc mem.ReAlloc mptr,size;///////////////////////////////////////////////////
|
||||
;-----------------------------------------------------------------------------
|
||||
push ebx ecx esi edi eax
|
||||
mov eax,[mptr]
|
||||
mov ebx,[size]
|
||||
or eax,eax
|
||||
jz @f
|
||||
lea ecx,[ebx+4+4095]
|
||||
and ecx,not 4095
|
||||
add ecx,-4
|
||||
cmp ecx,[eax-4]
|
||||
je .exit
|
||||
@@: mov eax,ebx
|
||||
call mem.Alloc
|
||||
xchg eax,[esp]
|
||||
or eax,eax
|
||||
jz .exit
|
||||
mov esi,eax
|
||||
xchg eax,[esp]
|
||||
mov edi,eax
|
||||
mov ecx,[esi-4]
|
||||
cmp ecx,[edi-4]
|
||||
jbe @f
|
||||
mov ecx,[edi-4]
|
||||
@@: add ecx,3
|
||||
shr ecx,2
|
||||
cld
|
||||
rep movsd
|
||||
xchg eax,[esp]
|
||||
call mem.Free
|
||||
.exit:
|
||||
pop eax edi esi ecx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
proc mem.Free mptr ;//////////////////////////////////////////////////////////
|
||||
;-----------------------------------------------------------------------------
|
||||
mov eax,[mptr]
|
||||
or eax,eax
|
||||
jz @f
|
||||
push ebx ecx
|
||||
lea ecx,[eax-4]
|
||||
mcall 68,13
|
||||
pop ecx ebx
|
||||
@@: ret
|
||||
endp
|
||||
|
||||
|
||||
proc dll.Load, import_table:dword
|
||||
mov esi,[import_table]
|
||||
.next_lib: mov edx,[esi]
|
||||
or edx,edx
|
||||
jz .exit
|
||||
push esi
|
||||
mov esi,[esi+4]
|
||||
mov edi,s_libdir.fname
|
||||
@@: lodsb
|
||||
stosb
|
||||
or al,al
|
||||
jnz @b
|
||||
mcall 68,19,s_libdir
|
||||
or eax,eax
|
||||
jz .fail
|
||||
stdcall dll.Link,eax,edx
|
||||
stdcall dll.Init,[eax+4]
|
||||
pop esi
|
||||
add esi,8
|
||||
jmp .next_lib
|
||||
.exit: xor eax,eax
|
||||
ret
|
||||
.fail: add esp,4
|
||||
xor eax,eax
|
||||
inc eax
|
||||
ret
|
||||
endp
|
||||
|
||||
proc dll.Link, exp:dword,imp:dword
|
||||
push eax
|
||||
mov esi,[imp]
|
||||
test esi,esi
|
||||
jz .done
|
||||
.next: lodsd
|
||||
test eax,eax
|
||||
jz .done
|
||||
stdcall dll.GetProcAddress,[exp],eax
|
||||
or eax,eax
|
||||
jz @f
|
||||
mov [esi-4],eax
|
||||
jmp .next
|
||||
@@: mov dword[esp],0
|
||||
.done: pop eax
|
||||
ret
|
||||
endp
|
||||
|
||||
proc dll.Init, dllentry:dword
|
||||
pushad
|
||||
mov eax,mem.Alloc
|
||||
mov ebx,mem.Free
|
||||
mov ecx,mem.ReAlloc
|
||||
mov edx,dll.Load
|
||||
stdcall [dllentry]
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
|
||||
proc dll.GetProcAddress, exp:dword,sz_name:dword
|
||||
mov edx,[exp]
|
||||
xor eax,eax
|
||||
.next: or edx,edx
|
||||
jz .end
|
||||
cmp dword[edx],0
|
||||
jz .end
|
||||
stdcall strcmp,[edx],[sz_name]
|
||||
test eax,eax
|
||||
jz .ok
|
||||
add edx,8
|
||||
jmp .next
|
||||
.ok: mov eax,[edx+4]
|
||||
.end: ret
|
||||
endp
|
||||
|
||||
proc strcmp, str1:dword,str2:dword
|
||||
push esi edi
|
||||
mov esi,[str1]
|
||||
mov edi,[str2]
|
||||
xor eax,eax
|
||||
@@: lodsb
|
||||
scasb
|
||||
jne .fail
|
||||
or al,al
|
||||
jnz @b
|
||||
jmp .ok
|
||||
.fail: or eax,-1
|
||||
.ok: pop edi esi
|
||||
ret
|
||||
endp
|
||||
|
||||
s_libdir:
|
||||
db '/sys/lib/'
|
||||
.fname rb 32
|
1135
programs/network/ftpd/commands.inc
Normal file
1135
programs/network/ftpd/commands.inc
Normal file
File diff suppressed because it is too large
Load Diff
455
programs/network/ftpd/ftpd.asm
Normal file
455
programs/network/ftpd/ftpd.asm
Normal file
@ -0,0 +1,455 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2010-2012. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; ftpd.asm - FTP Daemon for KolibriOS ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr@kolibrios.org ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
DEBUG = 0 ; if set to one, program will run in a single thread
|
||||
|
||||
BUFFERSIZE = 8192
|
||||
|
||||
; using multiple's of 4
|
||||
STATE_CONNECTED = 0*4
|
||||
STATE_LOGIN = 1*4
|
||||
STATE_LOGIN_FAIL = 2*4 ; When an invalid username was given
|
||||
STATE_ACTIVE = 3*4
|
||||
|
||||
TYPE_UNDEF = 0
|
||||
|
||||
TYPE_ASCII = 00000100b
|
||||
TYPE_EBDIC = 00001000b
|
||||
; subtypes for ascii & ebdic (np = default)
|
||||
TYPE_NP = 00000001b ; non printable
|
||||
TYPE_TELNET = 00000010b
|
||||
TYPE_ASA = 00000011b
|
||||
|
||||
TYPE_IMAGE = 01000000b ; binary data
|
||||
TYPE_LOCAL = 10000000b ; bits per byte must be specified
|
||||
; lower 4 bits will hold this value
|
||||
MODE_NOTREADY = 0
|
||||
MODE_ACTIVE = 1
|
||||
MODE_PASSIVE_WAIT = 2
|
||||
MODE_PASSIVE_OK = 3
|
||||
MODE_PASSIVE_FAILED = 4
|
||||
|
||||
PERMISSION_EXEC = 1b ; LIST
|
||||
PERMISSION_READ = 10b
|
||||
PERMISSION_WRITE = 100b
|
||||
PERMISSION_DELETE = 1000b
|
||||
PERMISSION_CD = 10000b ; Change Directory
|
||||
|
||||
ABORT = 1 shl 31
|
||||
|
||||
format binary as ""
|
||||
|
||||
use32
|
||||
|
||||
org 0x0
|
||||
|
||||
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 params ; parameters
|
||||
dd path ; path
|
||||
|
||||
include '../macros.inc'
|
||||
purge mov,add,sub
|
||||
include '../proc32.inc'
|
||||
include '../dll.inc'
|
||||
include '../struct.inc'
|
||||
include '../libio.inc'
|
||||
|
||||
include '../network.inc'
|
||||
|
||||
macro sendFTP str {
|
||||
local string, length
|
||||
xor edi, edi
|
||||
mcall send, [ebp + thread_data.socketnum], string, length
|
||||
|
||||
iglobal
|
||||
string db str, 13, 10
|
||||
length = $ - string
|
||||
\}
|
||||
}
|
||||
|
||||
include 'commands.inc'
|
||||
|
||||
start:
|
||||
mcall 68, 11 ; init heap
|
||||
mcall 40, 1 shl 7 ; we only want network events
|
||||
|
||||
; load libraries
|
||||
stdcall dll.Load, @IMPORT
|
||||
test eax, eax
|
||||
jnz exit
|
||||
|
||||
; find path to main settings file (ftpd.ini)
|
||||
mov edi, path ; Calculate the length of zero-terminated string
|
||||
xor al, al
|
||||
mov ecx, 1024
|
||||
repne scasb
|
||||
dec edi
|
||||
mov esi, str_ini ; append it with '.ini', 0
|
||||
movsd
|
||||
movsb
|
||||
|
||||
; now create the second path (users.ini)
|
||||
std
|
||||
mov al, '/'
|
||||
repne scasb
|
||||
lea ecx, [edi - path + 2]
|
||||
cld
|
||||
mov esi, path
|
||||
mov edi, path2
|
||||
rep movsb
|
||||
mov esi, str_users
|
||||
movsd
|
||||
movsd
|
||||
movsw
|
||||
|
||||
; initialize console
|
||||
invoke con_start, 1
|
||||
invoke con_init, -1, -1, -1, -1, title
|
||||
|
||||
; get settings from ini
|
||||
invoke ini.get_str, path, str_ftpd, str_ip, ini_buf, 16, 0
|
||||
mov esi, ini_buf
|
||||
mov cl, '.'
|
||||
call ip_to_dword
|
||||
mov [serverip], ebx
|
||||
|
||||
invoke ini.get_int, path, str_ftpd, str_port, 21
|
||||
xchg al, ah
|
||||
mov [sockaddr1.port], ax
|
||||
|
||||
xchg al, ah
|
||||
invoke con_printf, str1, eax
|
||||
add esp, 8
|
||||
|
||||
; open listening socket
|
||||
mcall socket, AF_INET4, SOCK_STREAM, 0
|
||||
cmp eax, -1
|
||||
je sock_err
|
||||
mov [socketnum], eax
|
||||
|
||||
invoke con_write_asciiz, str2
|
||||
|
||||
; mcall setsockopt, [socketnum], SOL_SOCKET, SO_REUSEADDR, &yes,
|
||||
; cmp eax, -1
|
||||
; je opt_err
|
||||
|
||||
mcall bind, [socketnum], sockaddr1, sockaddr1.length
|
||||
cmp eax, -1
|
||||
je bind_err
|
||||
|
||||
invoke con_write_asciiz, str2
|
||||
|
||||
invoke ini.get_int, path, str_ftpd, str_conn, 1 ; Backlog (max connections)
|
||||
mov edx, eax
|
||||
|
||||
invoke con_write_asciiz, str2
|
||||
|
||||
mcall listen, [socketnum]
|
||||
cmp eax, -1
|
||||
je listen_err
|
||||
|
||||
invoke con_write_asciiz, str2b
|
||||
|
||||
invoke ini.get_int, path, str_pasv, str_start, 2000
|
||||
mov [pasv_start], ax
|
||||
invoke ini.get_int, path, str_pasv, str_end, 5000
|
||||
mov [pasv_end], ax
|
||||
|
||||
mov [alive], 1
|
||||
|
||||
mainloop:
|
||||
mcall 23, 100 ; Wait here for incoming connections on the base socket (socketnum)
|
||||
; One second timeout, we will use this to check if console is still working
|
||||
|
||||
test eax, eax ; network event?
|
||||
jz .checkconsole
|
||||
|
||||
if DEBUG
|
||||
jmp threadstart
|
||||
else
|
||||
mcall 51, 1, threadstart, 0 ; Start a new thread for every incoming connection
|
||||
; NOTE: upon initialisation of the thread, stack will not be available!
|
||||
end if
|
||||
jmp mainloop
|
||||
|
||||
.checkconsole:
|
||||
|
||||
invoke con_get_flags ; Is console still running?
|
||||
test eax, 0x0200
|
||||
jz mainloop
|
||||
mcall close, [socketnum] ; kill the listening socket
|
||||
mov [alive], 0
|
||||
mcall -1 ; and exit
|
||||
|
||||
diff16 "threadstart", 0, $
|
||||
|
||||
threadstart:
|
||||
;;; mcall 68, 11 ; init heap
|
||||
mcall 68, 12, sizeof.thread_data ; allocate the thread data struct
|
||||
test eax, eax
|
||||
je exit
|
||||
|
||||
lea esp, [eax + thread_data.stack] ; init stack
|
||||
mov ebp, eax
|
||||
|
||||
mcall 40, 1 shl 7 ; we only want network events for this thread
|
||||
|
||||
lea ebx, [ebp + thread_data.buffer] ; get information about the current process
|
||||
or ecx, -1
|
||||
mcall 9
|
||||
mov eax, dword [ebp + thread_data.buffer + 30] ; PID is at offset 30
|
||||
mov [ebp + thread_data.pid], eax
|
||||
|
||||
invoke con_set_flags, 0x03
|
||||
invoke con_printf, str8, [ebp + thread_data.pid] ; print on the console that we have created the new thread successfully
|
||||
add esp, 8 ; balance stack
|
||||
invoke con_set_flags, 0x07
|
||||
|
||||
mcall accept, [socketnum], sockaddr1, sockaddr1.length ; time to accept the awaiting connection..
|
||||
cmp eax, -1
|
||||
je thread_exit
|
||||
mov [ebp + thread_data.socketnum], eax
|
||||
|
||||
if DEBUG
|
||||
mcall close, [socketnum] ; close the listening socket
|
||||
end if
|
||||
|
||||
mov [ebp + thread_data.state], STATE_CONNECTED
|
||||
mov [ebp + thread_data.permissions], 0
|
||||
mov [ebp + thread_data.mode], MODE_NOTREADY
|
||||
lea eax, [ebp + thread_data.buffer]
|
||||
mov [ebp + thread_data.buffer_ptr], eax
|
||||
mov [ebp + thread_data.passivesocknum], -1
|
||||
|
||||
sendFTP "220 Welcome to KolibriOS FTP daemon"
|
||||
|
||||
diff16 "threadloop", 0, $
|
||||
threadloop:
|
||||
; Check if our socket is still connected
|
||||
mcall send, [ebp + thread_data.socketnum], 0, 0 ; Try to send zero bytes, if socket is closed, this will return -1
|
||||
cmp eax, -1
|
||||
je thread_exit
|
||||
|
||||
cmp [alive], 0 ; Did main thread take a run for it?
|
||||
je thread_exit
|
||||
|
||||
mcall 10 ; Wait for network event
|
||||
|
||||
cmp [ebp + thread_data.mode], MODE_PASSIVE_WAIT
|
||||
jne .not_passive
|
||||
mov ecx, [ebp + thread_data.passivesocknum]
|
||||
lea edx, [ebp + thread_data.datasock]
|
||||
mov esi, sizeof.thread_data.datasock
|
||||
mcall accept
|
||||
cmp eax, -1
|
||||
je .not_passive
|
||||
mov [ebp + thread_data.datasocketnum], eax
|
||||
mov [ebp + thread_data.mode], MODE_PASSIVE_OK
|
||||
mcall close ; [ebp + thread_data.passivesocknum]
|
||||
mov [ebp + thread_data.passivesocknum], -1
|
||||
|
||||
invoke con_write_asciiz, str_datasock
|
||||
.not_passive:
|
||||
|
||||
mov ecx, [ebp + thread_data.socketnum]
|
||||
mov edx, [ebp + thread_data.buffer_ptr]
|
||||
mov esi, sizeof.thread_data.buffer ;;; FIXME
|
||||
mcall recv
|
||||
inc eax ; error? (-1)
|
||||
jz threadloop
|
||||
dec eax ; 0 bytes read?
|
||||
jz threadloop
|
||||
|
||||
mov edi, [ebp + thread_data.buffer_ptr]
|
||||
add [ebp + thread_data.buffer_ptr], eax
|
||||
|
||||
; Check if we received a newline character, if not, wait for more data
|
||||
mov ecx, eax
|
||||
mov al, 13
|
||||
repne scasb
|
||||
jne threadloop
|
||||
|
||||
; We got a command!
|
||||
mov byte [edi + 1], 0 ; append string with zero byte
|
||||
lea esi, [ebp + thread_data.buffer]
|
||||
mov ecx, [ebp + thread_data.buffer_ptr]
|
||||
sub ecx, esi
|
||||
mov [ebp + thread_data.buffer_ptr], esi ; reset buffer ptr
|
||||
|
||||
invoke con_set_flags, 0x02 ; print received data to console (in green color)
|
||||
invoke con_write_asciiz, str_newline
|
||||
invoke con_write_asciiz, esi
|
||||
invoke con_set_flags, 0x07
|
||||
|
||||
push threadloop
|
||||
jmp parse_cmd
|
||||
|
||||
listen_err:
|
||||
invoke con_set_flags, 0x0c ; print errors in red
|
||||
invoke con_write_asciiz, str3
|
||||
jmp done
|
||||
|
||||
bind_err:
|
||||
invoke con_set_flags, 0x0c ; print errors in red
|
||||
invoke con_write_asciiz, str4
|
||||
jmp done
|
||||
|
||||
sock_err:
|
||||
invoke con_set_flags, 0x0c ; print errors in red
|
||||
invoke con_write_asciiz, str6
|
||||
jmp done
|
||||
|
||||
done:
|
||||
invoke con_exit, 0
|
||||
exit:
|
||||
mcall -1
|
||||
|
||||
|
||||
thread_exit:
|
||||
invoke con_set_flags, 0x03 ; print thread info in blue
|
||||
invoke con_printf, str_bye, [ebp + thread_data.pid] ; print on the console that we are about to kill the thread
|
||||
add esp, 8 ; balance stack
|
||||
mcall 68, 13, ebp ; free the memory
|
||||
mcall -1 ; and kill the thread
|
||||
|
||||
|
||||
; initialized data
|
||||
|
||||
title db 'KolibriOS FTP daemon 0.1', 0
|
||||
str1 db 'Starting FTP daemon on port %u.', 0
|
||||
str2 db '.', 0
|
||||
str2b db ' OK!',10,0
|
||||
str3 db 'Listen error',10,0
|
||||
str4 db 10,'ERROR: local port is already in use.',10,0
|
||||
;str5 db 'Setsockopt error.',10,10,0
|
||||
str6 db 'ERROR: Could not open socket.',10,0
|
||||
str7 db 'Got data!',10,10,0
|
||||
str8 db 10,'Thread %d created',10,0
|
||||
str_bye db 10,'Thread %d killed',10,0
|
||||
|
||||
str_logged_in db 'Login ok',10,0
|
||||
str_pass_ok db 'Password ok',10,0
|
||||
str_pass_err db 'Password/Username incorrect',10,0
|
||||
str_pwd db 'Current directory is "%s"\n',0
|
||||
str_err2 db 'ERROR: cannot open the directory.',10,0
|
||||
str_datasock db 'Passive data socket connected.',10,0
|
||||
str_notfound db 'ERROR: file not found.',10,0
|
||||
str_sockerr db 'ERROR: socket error.',10,0
|
||||
|
||||
str_newline db 10, 0
|
||||
str_mask db '*', 0
|
||||
str_infinity db 0xff, 0xff, 0xff, 0xff, 0
|
||||
|
||||
months dd 'Jan '
|
||||
dd 'Feb '
|
||||
dd 'Mar '
|
||||
dd 'Apr '
|
||||
dd 'May '
|
||||
dd 'Jun '
|
||||
dd 'Jul '
|
||||
dd 'Aug '
|
||||
dd 'Sep '
|
||||
dd 'Oct '
|
||||
dd 'Nov '
|
||||
dd 'Dec '
|
||||
|
||||
str_users db 'users'
|
||||
str_ini db '.ini', 0
|
||||
str_port db 'port', 0
|
||||
str_ftpd db 'ftpd', 0
|
||||
str_conn db 'conn', 0
|
||||
str_ip db 'ip', 0
|
||||
str_pass db 'pass', 0
|
||||
str_home db 'home', 0
|
||||
str_mode db 'mode', 0
|
||||
str_pasv db 'pasv', 0
|
||||
str_start db 'start', 0
|
||||
str_end db 'end', 0
|
||||
|
||||
|
||||
sockaddr1:
|
||||
dw AF_INET4
|
||||
.port dw 0
|
||||
.ip dd 0
|
||||
rb 10
|
||||
.length = $ - sockaddr1
|
||||
|
||||
; import
|
||||
|
||||
align 4
|
||||
@IMPORT:
|
||||
|
||||
diff16 "import", 0, $
|
||||
|
||||
library console, 'console.obj',\
|
||||
libini, 'libini.obj', \
|
||||
libio, 'libio.obj'
|
||||
|
||||
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_printf, 'con_printf',\
|
||||
con_getch2, 'con_getch2',\
|
||||
con_set_cursor_pos, 'con_set_cursor_pos',\
|
||||
con_set_flags, 'con_set_flags',\
|
||||
con_get_flags, 'con_get_flags'
|
||||
|
||||
import libini,\
|
||||
ini.get_str, 'ini_get_str',\
|
||||
ini.get_int, 'ini_get_int'
|
||||
|
||||
import libio,\
|
||||
file.size, 'file_size',\
|
||||
file.open, 'file_open',\
|
||||
file.read, 'file_read',\
|
||||
file.close, 'file_close',\
|
||||
file.find.first, 'file_find_first',\
|
||||
file.find.next, 'file_find_next',\
|
||||
file.find.close, 'file_find_close'
|
||||
|
||||
|
||||
IncludeIGlobals
|
||||
|
||||
|
||||
i_end:
|
||||
|
||||
diff16 "i_end", 0, $
|
||||
|
||||
; uninitialised data
|
||||
|
||||
socketnum dd ?
|
||||
path rb 1024
|
||||
path2 rb 1024
|
||||
params rb 1024
|
||||
serverip dd ?
|
||||
pasv_start dw ?
|
||||
pasv_end dw ?
|
||||
pasv_port dw ?
|
||||
|
||||
ini_buf rb 3*4+3+1
|
||||
|
||||
alive db ?
|
||||
|
||||
mem:
|
||||
|
||||
|
8
programs/network/ftpd/ftpd.ini
Normal file
8
programs/network/ftpd/ftpd.ini
Normal file
@ -0,0 +1,8 @@
|
||||
[ftpd]
|
||||
port=21
|
||||
conn=10
|
||||
ip=127.0.0.1
|
||||
|
||||
[pasv]
|
||||
start=2000
|
||||
end=5000
|
20
programs/network/ftpd/users.ini
Normal file
20
programs/network/ftpd/users.ini
Normal file
@ -0,0 +1,20 @@
|
||||
; Access modes
|
||||
;
|
||||
; List = 1
|
||||
; Read = 2
|
||||
; Write = 4
|
||||
; Delete = 8
|
||||
; Change directory = 16
|
||||
|
||||
|
||||
[anonymous]
|
||||
; leavy pass empty to disable it
|
||||
pass=
|
||||
home=/rd/1/
|
||||
mode=3
|
||||
|
||||
[test]
|
||||
pass=1234
|
||||
home=/rd/1/
|
||||
mode=31
|
||||
|
77
programs/network/icmp/icmp.inc
Normal file
77
programs/network/icmp/icmp.inc
Normal file
@ -0,0 +1,77 @@
|
||||
; ICMP types & codes
|
||||
|
||||
ICMP_ECHOREPLY equ 0 ; echo reply message
|
||||
|
||||
ICMP_UNREACH equ 3
|
||||
ICMP_UNREACH_NET equ 0 ; bad net
|
||||
ICMP_UNREACH_HOST equ 1 ; bad host
|
||||
ICMP_UNREACH_PROTOCOL equ 2 ; bad protocol
|
||||
ICMP_UNREACH_PORT equ 3 ; bad port
|
||||
ICMP_UNREACH_NEEDFRAG equ 4 ; IP_DF caused drop
|
||||
ICMP_UNREACH_SRCFAIL equ 5 ; src route failed
|
||||
ICMP_UNREACH_NET_UNKNOWN equ 6 ; unknown net
|
||||
ICMP_UNREACH_HOST_UNKNOWN equ 7 ; unknown host
|
||||
ICMP_UNREACH_ISOLATED equ 8 ; src host isolated
|
||||
ICMP_UNREACH_NET_PROHIB equ 9 ; prohibited access
|
||||
ICMP_UNREACH_HOST_PROHIB equ 10 ; ditto
|
||||
ICMP_UNREACH_TOSNET equ 11 ; bad tos for net
|
||||
ICMP_UNREACH_TOSHOST equ 12 ; bad tos for host
|
||||
ICMP_UNREACH_FILTER_PROHIB equ 13 ; admin prohib
|
||||
ICMP_UNREACH_HOST_PRECEDENCE equ 14 ; host prec vio.
|
||||
ICMP_UNREACH_PRECEDENCE_CUTOFF equ 15 ; prec cutoff
|
||||
|
||||
ICMP_SOURCEQUENCH equ 4 ; Packet lost, slow down
|
||||
|
||||
ICMP_REDIRECT equ 5 ; shorter route, codes:
|
||||
ICMP_REDIRECT_NET equ 0 ; for network
|
||||
ICMP_REDIRECT_HOST equ 1 ; for host
|
||||
ICMP_REDIRECT_TOSNET equ 2 ; for tos and net
|
||||
ICMP_REDIRECT_TOSHOST equ 3 ; for tos and host
|
||||
|
||||
ICMP_ALTHOSTADDR equ 6 ; alternate host address
|
||||
ICMP_ECHO equ 8 ; echo service
|
||||
ICMP_ROUTERADVERT equ 9 ; router advertisement
|
||||
ICMP_ROUTERADVERT_NORMAL equ 0 ; normal advertisement
|
||||
ICMP_ROUTERADVERT_NOROUTE_COMMON equ 16 ; selective routing
|
||||
|
||||
ICMP_ROUTERSOLICIT equ 10 ; router solicitation
|
||||
ICMP_TIMXCEED equ 11 ; time exceeded, code:
|
||||
ICMP_TIMXCEED_INTRANS equ 0 ; ttl==0 in transit
|
||||
ICMP_TIMXCEED_REASS equ 1 ; ttl==0 in reass
|
||||
|
||||
ICMP_PARAMPROB equ 12 ; ip header bad
|
||||
ICMP_PARAMPROB_ERRATPTR equ 0 ; error at param ptr
|
||||
ICMP_PARAMPROB_OPTABSENT equ 1 ; req. opt. absent
|
||||
ICMP_PARAMPROB_LENGTH equ 2 ; bad length
|
||||
|
||||
ICMP_TSTAMP equ 13 ; timestamp request
|
||||
ICMP_TSTAMPREPLY equ 14 ; timestamp reply
|
||||
ICMP_IREQ equ 15 ; information request
|
||||
ICMP_IREQREPLY equ 16 ; information reply
|
||||
ICMP_MASKREQ equ 17 ; address mask request
|
||||
ICMP_MASKREPLY equ 18 ; address mask reply
|
||||
ICMP_TRACEROUTE equ 30 ; traceroute
|
||||
ICMP_DATACONVERR equ 31 ; data conversion error
|
||||
ICMP_MOBILE_REDIRECT equ 32 ; mobile host redirect
|
||||
ICMP_IPV6_WHEREAREYOU equ 33 ; IPv6 where-are-you
|
||||
ICMP_IPV6_IAMHERE equ 34 ; IPv6 i-am-here
|
||||
ICMP_MOBILE_REGREQUEST equ 35 ; mobile registration req
|
||||
ICMP_MOBILE_REGREPLY equ 36 ; mobile registreation reply
|
||||
ICMP_SKIP equ 39 ; SKIP
|
||||
|
||||
ICMP_PHOTURIS equ 40 ; Photuris
|
||||
ICMP_PHOTURIS_UNKNOWN_INDEX equ 1 ; unknown sec index
|
||||
ICMP_PHOTURIS_AUTH_FAILED equ 2 ; auth failed
|
||||
ICMP_PHOTURIS_DECRYPT_FAILED equ 3 ; decrypt failed
|
||||
|
||||
|
||||
|
||||
virtual at 0
|
||||
ICMP_Packet:
|
||||
.Type db ?
|
||||
.Code db ?
|
||||
.Checksum dw ?
|
||||
.Identifier dw ?
|
||||
.SequenceNumber dw ?
|
||||
.Data:
|
||||
end virtual
|
256
programs/network/icmp/ping.asm
Normal file
256
programs/network/icmp/ping.asm
Normal file
@ -0,0 +1,256 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2010-2012. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; ping.asm - ICMP echo client for KolibriOS ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr@kolibrios.org ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
format binary as ""
|
||||
|
||||
use32
|
||||
org 0x0
|
||||
|
||||
db 'MENUET01' ; signature
|
||||
dd 1 ; header version
|
||||
dd start ; entry point
|
||||
dd I_END ; initialized size
|
||||
dd mem ; required memory
|
||||
dd mem ; stack pointer
|
||||
dd s ; parameters
|
||||
dd 0 ; path
|
||||
|
||||
|
||||
BUFFERSIZE equ 1500
|
||||
; useful includes
|
||||
include '../macros.inc'
|
||||
purge mov,add,sub
|
||||
include '../proc32.inc'
|
||||
include '../dll.inc'
|
||||
include '../network.inc'
|
||||
|
||||
include 'icmp.inc'
|
||||
|
||||
|
||||
start:
|
||||
; 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]
|
||||
; main loop
|
||||
cmp byte[s], 0
|
||||
jne resolve
|
||||
main:
|
||||
; 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
|
||||
; delete terminating '\n'
|
||||
push esi
|
||||
@@:
|
||||
lodsb
|
||||
test al, al
|
||||
jnz @b
|
||||
mov byte [esi-2], al
|
||||
pop esi
|
||||
|
||||
resolve:
|
||||
; 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
|
||||
|
||||
; 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
|
||||
mov [ip_ptr], eax
|
||||
|
||||
push eax
|
||||
|
||||
; free allocated memory
|
||||
push esi
|
||||
call [freeaddrinfo]
|
||||
|
||||
push str4
|
||||
call [con_write_asciiz]
|
||||
|
||||
mcall socket, AF_INET4, SOCK_RAW, IPPROTO_ICMP
|
||||
cmp eax, -1
|
||||
jz fail2
|
||||
mov [socketnum], eax
|
||||
|
||||
mcall connect, [socketnum], sockaddr1, 18
|
||||
|
||||
mcall 40, 1 shl 7 ; + 7
|
||||
; call [con_cls]
|
||||
|
||||
mov [count], 4
|
||||
|
||||
mainloop:
|
||||
push str3
|
||||
call [con_write_asciiz]
|
||||
push [ip_ptr]
|
||||
call [con_write_asciiz]
|
||||
|
||||
mcall 26,9
|
||||
mov [time_reference], eax
|
||||
mcall send, [socketnum], icmp_packet, icmp_packet.length, 0
|
||||
|
||||
mcall 23, 300 ; 3 seconds time-out
|
||||
mcall 26,9
|
||||
neg [time_reference]
|
||||
add [time_reference], eax
|
||||
|
||||
mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, 0
|
||||
cmp eax, -1
|
||||
je .no_response
|
||||
|
||||
; validate the packet
|
||||
lea esi, [buffer_ptr + ICMP_Packet.Data]
|
||||
mov edi, icmp_packet.data
|
||||
mov ecx, 32/4
|
||||
repe cmpsd
|
||||
jne .miscomp
|
||||
|
||||
push [time_reference]
|
||||
push str7
|
||||
call [con_printf]
|
||||
|
||||
jmp continue
|
||||
|
||||
.miscomp:
|
||||
sub edi, icmp_packet.data
|
||||
push edi
|
||||
push str9
|
||||
call [con_printf]
|
||||
jmp continue
|
||||
|
||||
.no_response:
|
||||
push str8
|
||||
call [con_write_asciiz]
|
||||
|
||||
continue:
|
||||
dec [count]
|
||||
jz done
|
||||
mcall 5, 100 ; wait a second
|
||||
inc [icmp_packet.id]
|
||||
jmp mainloop
|
||||
|
||||
|
||||
|
||||
done:
|
||||
push str10
|
||||
call [con_write_asciiz]
|
||||
call [con_getch2]
|
||||
push 1
|
||||
call [con_exit]
|
||||
exit:
|
||||
mcall -1
|
||||
|
||||
fail:
|
||||
push str5
|
||||
call [con_write_asciiz]
|
||||
jmp done
|
||||
fail2:
|
||||
push str6
|
||||
call [con_write_asciiz]
|
||||
jmp done
|
||||
|
||||
|
||||
; data
|
||||
title db 'ICMP - echo client',0
|
||||
str2 db '> ',0
|
||||
str3 db 'Ping to ',0
|
||||
str4 db 10,0
|
||||
str5 db 'Name resolution failed.',10,0
|
||||
str6 db 'Could not open socket',10,0
|
||||
str7 db ' time= %u0ms',10,0
|
||||
str8 db ' timeout!',10,0
|
||||
str9 db ' miscompare at offset %u',10,0
|
||||
str10 db 10,'Press any key to exit',0
|
||||
|
||||
sockaddr1:
|
||||
dw AF_INET4
|
||||
.port dw 0
|
||||
.ip dd 0
|
||||
rb 10
|
||||
|
||||
time_reference dd ?
|
||||
ip_ptr dd ?
|
||||
count dd ?
|
||||
|
||||
|
||||
; 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_printf, 'con_printf', \
|
||||
con_exit, 'con_exit', \
|
||||
con_gets, 'con_gets',\
|
||||
con_cls, 'con_cls',\
|
||||
con_getch2, 'con_getch2',\
|
||||
con_set_cursor_pos, 'con_set_cursor_pos'
|
||||
|
||||
socketnum dd ?
|
||||
|
||||
icmp_packet: db 8 ; type
|
||||
db 0 ; code
|
||||
dw 0 ;
|
||||
.id dw 0x0000 ; identifier
|
||||
.seq dw 0x0001 ; sequence number
|
||||
.data db 'abcdefghijklmnopqrstuvwxyz012345678'
|
||||
.length = $ - icmp_packet
|
||||
|
||||
I_END:
|
||||
|
||||
buffer_ptr rb BUFFERSIZE
|
||||
|
||||
s rb 1024
|
||||
rb 4096 ; stack
|
||||
mem:
|
317
programs/network/ircc/encodings.inc
Normal file
317
programs/network/ircc/encodings.inc
Normal file
@ -0,0 +1,317 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
get_next_byte:
|
||||
; Load next byte from the packet, translating to cp866 if necessary
|
||||
; At input esi = pointer to data, edx = limit of data
|
||||
; Output is either (translated) byte in al with CF set or CF cleared.
|
||||
mov eax, [encoding]
|
||||
jmp [get_byte_table+eax*4]
|
||||
|
||||
get_byte_cp866:
|
||||
cmp esi, edx
|
||||
jae .nothing
|
||||
lodsb
|
||||
.nothing:
|
||||
ret
|
||||
|
||||
get_byte_cp1251:
|
||||
cmp esi, edx
|
||||
jae .nothing
|
||||
lodsb
|
||||
cmp al, 0x80
|
||||
jb @f
|
||||
and eax, 0x7F
|
||||
mov al, [cp1251_table+eax]
|
||||
@@:
|
||||
stc
|
||||
.nothing:
|
||||
ret
|
||||
|
||||
get_byte_utf8:
|
||||
; UTF8 decoding is slightly complicated.
|
||||
; One character can occupy one or more bytes.
|
||||
; The boundary in packets theoretically can be anywhere in data,
|
||||
; so this procedure keeps internal state between calls and handles
|
||||
; one byte at a time, looping until character is read or packet is over.
|
||||
; Globally, there are two distinct tasks: decode byte sequence to unicode char
|
||||
; and convert this unicode char to our base encoding (that is cp866).
|
||||
; 1. Check that there are data.
|
||||
cmp esi, edx
|
||||
jae .nothing
|
||||
; 2. Load byte.
|
||||
lodsb
|
||||
movzx ecx, al
|
||||
; 3. Bytes in an UTF8 sequence can be of any of three types.
|
||||
; If most significant bit is cleared, sequence is one byte and usual ASCII char.
|
||||
; First byte of a sequence must be 11xxxxxx, other bytes are 10yyyyyy.
|
||||
and al, 0xC0
|
||||
jns .single_byte
|
||||
jp .first_byte
|
||||
; 4. This byte is not first in UTF8 sequence.
|
||||
; 4a. Check that the sequence was started. If no, it is invalid byte
|
||||
; and we simply ignore it.
|
||||
cmp [utf8_bytes_rest], 0
|
||||
jz get_byte_utf8
|
||||
; 4b. Otherwise, it is really next byte and it gives some more bits of char.
|
||||
mov eax, [utf8_char]
|
||||
shl eax, 6
|
||||
lea eax, [eax+ecx-0x80]
|
||||
; 4c. Decrement number of bytes rest in the sequence.
|
||||
; If it goes to zero, character is read, so return it.
|
||||
dec [utf8_bytes_rest]
|
||||
jz .got_char
|
||||
mov [utf8_char], eax
|
||||
jmp get_byte_utf8
|
||||
; 5. If the byte is first in UTF8 sequence, calculate the number of leading 1s
|
||||
; - it equals total number of bytes in the sequence; some other bits rest for
|
||||
; leading bits in the character.
|
||||
.first_byte:
|
||||
mov eax, -1
|
||||
@@:
|
||||
inc eax
|
||||
add cl, cl
|
||||
js @b
|
||||
mov [utf8_bytes_rest], eax
|
||||
xchg eax, ecx
|
||||
inc ecx
|
||||
shr al, cl
|
||||
mov [utf8_char], eax
|
||||
jmp get_byte_utf8
|
||||
; 6. If the byte is ASCII char, it is the character.
|
||||
.single_byte:
|
||||
xchg eax, ecx
|
||||
.got_char:
|
||||
; We got the character, now abandon a possible sequence in progress.
|
||||
and [utf8_bytes_rest], 0
|
||||
; Now second task. The unicode character is in eax, and now we shall convert it
|
||||
; to cp866.
|
||||
cmp eax, 0x80
|
||||
jb .done
|
||||
; 0x410-0x43F -> 0x80-0xAF, 0x440-0x44F -> 0xE0-0xEF, 0x401 -> 0xF0, 0x451 -> 0xF1
|
||||
cmp eax, 0x401
|
||||
jz .YO
|
||||
cmp eax, 0x451
|
||||
jz .yo
|
||||
cmp eax, 0x410
|
||||
jb .unrecognized
|
||||
cmp eax, 0x440
|
||||
jb .part1
|
||||
cmp eax, 0x450
|
||||
jae .unrecognized
|
||||
sub al, (0x40-0xE0) and 0xFF
|
||||
ret
|
||||
.part1:
|
||||
sub al, 0x10-0x80
|
||||
.nothing:
|
||||
.done:
|
||||
ret
|
||||
.unrecognized:
|
||||
mov al, '?'
|
||||
stc
|
||||
ret
|
||||
.YO:
|
||||
mov al, 0xF0
|
||||
stc
|
||||
ret
|
||||
.yo:
|
||||
mov al, 0xF1
|
||||
stc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
print_character:
|
||||
|
||||
pusha
|
||||
|
||||
cmp bl, 13 ; line beginning
|
||||
jne nobol
|
||||
|
||||
mov ecx, [pos]
|
||||
inc ecx
|
||||
boll1:
|
||||
dec ecx
|
||||
mov eax, ecx
|
||||
xor edx, edx
|
||||
mov ebx, [textbox_width]
|
||||
div ebx
|
||||
test edx, edx
|
||||
jnz boll1
|
||||
mov [pos], ecx
|
||||
jmp newdata
|
||||
nobol:
|
||||
|
||||
cmp bl, 10 ; line down
|
||||
jne nolf
|
||||
|
||||
addx1:
|
||||
inc [pos]
|
||||
mov eax, [pos]
|
||||
xor edx, edx
|
||||
mov ecx, [textbox_width]
|
||||
div ecx
|
||||
test edx, edx
|
||||
jnz addx1
|
||||
mov eax, [pos]
|
||||
jmp cm1
|
||||
nolf:
|
||||
no_lf_ret:
|
||||
|
||||
|
||||
cmp bl, 15 ; character
|
||||
jbe newdata
|
||||
|
||||
mov eax, [irc_data]
|
||||
shl eax, 8
|
||||
mov al, bl
|
||||
mov [irc_data], eax
|
||||
|
||||
mov eax, [pos]
|
||||
;---- draw data
|
||||
pusha
|
||||
|
||||
and ebx, 0xff
|
||||
add eax, [text_start]
|
||||
mov [eax], bl
|
||||
|
||||
popa
|
||||
;---- draw data
|
||||
|
||||
mov eax, [pos]
|
||||
inc eax
|
||||
cm1:
|
||||
mov ebx, [scroll+4]
|
||||
imul ebx, [textbox_width]
|
||||
cmp eax, ebx
|
||||
jb noeaxz
|
||||
|
||||
mov esi, [text_start]
|
||||
add esi, [textbox_width]
|
||||
|
||||
mov edi, [text_start]
|
||||
mov ecx, ebx
|
||||
rep movsb
|
||||
|
||||
mov esi, [text_start]
|
||||
mov ecx, [textbox_width]
|
||||
imul ecx, 61
|
||||
add esi, ecx
|
||||
|
||||
mov edi, [text_start]
|
||||
mov ecx, [textbox_width]
|
||||
imul ecx, 60
|
||||
add edi, ecx
|
||||
mov ecx, ebx
|
||||
rep movsb
|
||||
|
||||
mov eax, ebx
|
||||
sub eax, [textbox_width]
|
||||
noeaxz:
|
||||
mov [pos], eax
|
||||
|
||||
newdata:
|
||||
mov eax, [window_print]
|
||||
or [eax + window.flags], FLAG_UPDATED
|
||||
|
||||
popa
|
||||
ret
|
||||
|
||||
|
||||
|
||||
recode_to_cp866:
|
||||
rep movsb
|
||||
ret
|
||||
|
||||
recode_to_cp1251:
|
||||
xor eax, eax
|
||||
jecxz .nothing
|
||||
.loop:
|
||||
lodsb
|
||||
cmp al,0x80
|
||||
jb @f
|
||||
mov al, [cp866_table-0x80+eax]
|
||||
@@: stosb
|
||||
loop .loop
|
||||
.nothing:
|
||||
ret
|
||||
|
||||
recode_to_utf8:
|
||||
jecxz .nothing
|
||||
.loop:
|
||||
lodsb
|
||||
cmp al, 0x80
|
||||
jb .single_byte
|
||||
and eax, 0x7F
|
||||
mov ax, [utf8_table+eax*2]
|
||||
stosw
|
||||
loop .loop
|
||||
ret
|
||||
.single_byte:
|
||||
stosb
|
||||
loop .loop
|
||||
.nothing:
|
||||
ret
|
||||
|
||||
recode:
|
||||
mov eax, [encoding]
|
||||
jmp [recode_proc+eax*4]
|
||||
|
||||
|
||||
|
||||
encoding dd UTF8
|
||||
recode_proc dd recode_to_cp866, recode_to_cp1251, recode_to_utf8
|
||||
get_byte_table dd get_byte_cp866, get_byte_cp1251, get_byte_utf8
|
||||
|
||||
|
||||
cp1251_table:
|
||||
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; 8
|
||||
db '?','?','?','?','?',$F9,'?','?' , '?','?','?','?','?','?','?','?' ; 9
|
||||
db '?',$F6,$F7,'?',$FD,'?','?','?' , $F0,'?',$F2,'?','?','?','?',$F4 ; A
|
||||
db $F8,'?','?','?','?','?','?',$FA , $F1,$FC,$F3,'?','?','?','?',$F5 ; B
|
||||
db $80,$81,$82,$83,$84,$85,$86,$87 , $88,$89,$8A,$8B,$8C,$8D,$8E,$8F ; C
|
||||
db $90,$91,$92,$93,$94,$95,$96,$97 , $98,$99,$9A,$9B,$9C,$9D,$9E,$9F ; D
|
||||
db $A0,$A1,$A2,$A3,$A4,$A5,$A6,$A7 , $A8,$A9,$AA,$AB,$AC,$AD,$AE,$AF ; E
|
||||
db $E0,$E1,$E2,$E3,$E4,$E5,$E6,$E7 , $E8,$E9,$EA,$EB,$EC,$ED,$EE,$EF ; F
|
||||
|
||||
; 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
|
||||
utf8_table:
|
||||
times 80h dw 0x98C3 ; default placeholder
|
||||
|
||||
; 0x80-0xAF -> 0x90D0-0xBFD0
|
||||
repeat 0x30
|
||||
store byte 0xD0 at utf8_table+2*(%-1)
|
||||
store byte 0x90+%-1 at utf8_table+2*%-1
|
||||
end repeat
|
||||
|
||||
; 0xE0-0xEF -> 0x80D1-0x8FD1
|
||||
repeat 0x10
|
||||
store byte 0xD1 at utf8_table+2*(0xE0-0x80+%-1)
|
||||
store byte 0x80+%-1 at utf8_table+2*(0xE0-0x80+%)-1
|
||||
end repeat
|
||||
|
||||
; 0xF0 -> 0x81D0, 0xF1 -> 0x91D1
|
||||
store dword 0x91D181D0 at utf8_table+2*(0xF0-0x80)
|
||||
|
||||
cp866_table:
|
||||
db $C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7 , $C8,$C9,$CA,$CB,$CC,$CD,$CE,$CF ; 8
|
||||
db $D0,$D1,$D2,$D3,$D4,$D5,$D6,$D7 , $D8,$D9,$DA,$DB,$DC,$DD,$DE,$DF ; 9
|
||||
db $E0,$E1,$E2,$E3,$E4,$E5,$E6,$E7 , $E8,$E9,$EA,$EB,$EC,$ED,$EE,$EF ; A
|
||||
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; B
|
||||
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; C
|
||||
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; D
|
||||
db $F0,$F1,$F2,$F3,$F4,$F5,$F6,$F7 , $F8,$F9,$FA,$FB,$FC,$FD,$FE,$FF ; E
|
||||
db $A8,$B8,$AA,$BA,$AF,$BF,$A1,$A2 , $B0,$95,$B7,'?',$B9,$A4,'?','?' ; F
|
||||
|
||||
; 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
|
316
programs/network/ircc/gui.inc
Normal file
316
programs/network/ircc/gui.inc
Normal file
@ -0,0 +1,316 @@
|
||||
draw_window:
|
||||
|
||||
pusha
|
||||
|
||||
mcall 9, thread_info, -1 ; get current window size
|
||||
mov eax, dword[thread_info+42] ; window xsize
|
||||
mov ebx, dword[thread_info+46] ; ysize
|
||||
mov edx, dword[thread_info+62] ; work area xsize
|
||||
mov esi, dword[thread_info+66] ; ysize
|
||||
sub eax, edx
|
||||
sub ebx, esi
|
||||
|
||||
cmp edx, WIN_MIN_X
|
||||
jae .x_ok
|
||||
mov edx, WIN_MIN_X
|
||||
.x_ok:
|
||||
mov [xsize], edx
|
||||
add edx, eax
|
||||
|
||||
cmp esi, WIN_MIN_Y
|
||||
jae .y_ok
|
||||
mov esi, WIN_MIN_Y
|
||||
.y_ok:
|
||||
mov [ysize], esi
|
||||
add esi, ebx
|
||||
mcall 67, -1, -1 ; set the new sizes
|
||||
|
||||
mcall 12, 1
|
||||
xor eax, eax ; draw window
|
||||
mov ebx, WIN_MIN_X
|
||||
mov ecx, WIN_MIN_Y
|
||||
mov edx, [colors.work]
|
||||
add edx, 0x33000000
|
||||
mov edi, str_programname
|
||||
mcall
|
||||
mcall 12, 2 ;; when do we actually need this??
|
||||
|
||||
mov ebx, [xsize]
|
||||
mov ecx, [ysize]
|
||||
sub cx, 15 ;;;;
|
||||
push cx
|
||||
shl ecx, 16
|
||||
pop cx
|
||||
mov edx, [colors.work_graph]
|
||||
mcall 38 ; draw line
|
||||
|
||||
mov ecx, TOP_Y SHL 16 + TOP_Y
|
||||
mcall
|
||||
|
||||
mov edi, [window_open]
|
||||
cmp [edi + window.type], WINDOWTYPE_CHANNEL
|
||||
jne .not_channel
|
||||
|
||||
; draw a vertical separator line
|
||||
mov ebx, [xsize]
|
||||
sub ebx, USERLIST_X + SCROLLBAR_WIDTH + 3
|
||||
push bx
|
||||
shl ebx, 16
|
||||
pop bx
|
||||
mov ecx, [ysize]
|
||||
add ecx, TOP_Y SHL 16 -(15) ;;;;
|
||||
mcall
|
||||
|
||||
call redraw_channel_list
|
||||
|
||||
.not_channel:
|
||||
mov edx, [edi + window.data_ptr]
|
||||
add edx, window_data.text
|
||||
call draw_channel_text
|
||||
|
||||
; editbox
|
||||
|
||||
mov eax, [ysize]
|
||||
sub eax, 12 ;;;;;;
|
||||
mov [edit1.top], eax
|
||||
|
||||
mov eax, [xsize]
|
||||
mov [edit1.width], eax
|
||||
|
||||
push dword edit1
|
||||
call [edit_box_draw]
|
||||
|
||||
; tabs
|
||||
|
||||
call draw_windownames
|
||||
|
||||
popa
|
||||
ret
|
||||
|
||||
|
||||
|
||||
redraw_channel_list:
|
||||
|
||||
; First, calculate scrollbar
|
||||
|
||||
mov ebx, [window_open]
|
||||
mov eax, [ebx + window.users] ; number of users in the open window
|
||||
mov [scroll1.max_area], eax
|
||||
|
||||
mov eax, [ysize]
|
||||
sub eax, TOP_Y + 15 ;;;;
|
||||
push eax
|
||||
mov [scroll1.y_size], ax
|
||||
|
||||
mov eax, [xsize]
|
||||
sub eax, SCROLLBAR_WIDTH
|
||||
mov [scroll1.x_pos], ax
|
||||
|
||||
pop eax ; scrollbar height
|
||||
xor edx, edx
|
||||
mov ecx, 10
|
||||
div ecx
|
||||
mov [scroll1.cur_area], eax
|
||||
|
||||
; Do we need a scrollbar?
|
||||
cmp eax, [scroll1.max_area]
|
||||
jae .noscroll
|
||||
|
||||
; Is the current position greater then the max position?
|
||||
cmp eax, [scroll1.position]
|
||||
ja @f
|
||||
mov [scroll1.position], eax
|
||||
@@:
|
||||
|
||||
; OK, draw the scrollbar
|
||||
mov [scroll1.all_redraw], 1
|
||||
|
||||
push dword scroll1
|
||||
call [scrollbar_v_draw]
|
||||
|
||||
jmp print_channel_list
|
||||
|
||||
.noscroll:
|
||||
mov [scroll1.position], 0
|
||||
|
||||
|
||||
|
||||
print_channel_list:
|
||||
|
||||
pusha
|
||||
; Now, draw the usernames themselves
|
||||
|
||||
; first, draw an invisible button
|
||||
mov ebx, [xsize]
|
||||
sub ebx, USERLIST_X + SCROLLBAR_WIDTH
|
||||
shl ebx, 16
|
||||
push ebx
|
||||
mov bx, USERLIST_X
|
||||
mov ecx, [ysize]
|
||||
add ecx, TEXT_Y shl 16 - (TEXT_Y + 15) ;;;;; + 10???
|
||||
push ecx ebx
|
||||
mov edx, 50 + 1 shl 29 + 1 shl 30
|
||||
mcall 8
|
||||
|
||||
; now draw rectangle to clear the names
|
||||
pop ebx ecx
|
||||
mov edx, [colors.work]
|
||||
mcall 13
|
||||
|
||||
; now draw the names according with scrollbar position and window size
|
||||
mov eax, [scroll1.position]
|
||||
xor edx, edx
|
||||
mov ecx, MAX_NICK_LEN
|
||||
mul ecx
|
||||
mov edx, eax
|
||||
mov eax, [window_open]
|
||||
mov ebp, [eax + window.selected]
|
||||
add edx, [eax + window.data_ptr]
|
||||
sub ebp, [scroll1.position]
|
||||
add edx, window_data.names
|
||||
|
||||
pop ebx
|
||||
mov bx, TEXT_Y
|
||||
mov ecx, [colors.work_text]
|
||||
or ecx, 0x80000000 ; ASCIIZ string
|
||||
mov eax, 4 ; draw text
|
||||
|
||||
mov edi, [ysize] ; Calculate how many names will fit on screen
|
||||
sub edi, TEXT_Y + 15 ;+ 10 ;;;;;
|
||||
.loop:
|
||||
cmp byte[edx], 0 ; end of list?
|
||||
je .done
|
||||
|
||||
dec ebp ; is this name selected?
|
||||
jnz .nothighlight
|
||||
; yes, highlight it
|
||||
pusha
|
||||
mov cx, bx
|
||||
mov bx, USERLIST_X
|
||||
shl ecx, 16
|
||||
mov cx, 10 - 1
|
||||
mov edx, 0x00000055 ; blue!
|
||||
mcall 13
|
||||
popa
|
||||
|
||||
mov ecx, 0x8000ffff ; cyan!
|
||||
mcall
|
||||
|
||||
mov ecx, [colors.work_text]
|
||||
or ecx, 0x80000000 ; ASCIIZ string
|
||||
jmp .next
|
||||
|
||||
.nothighlight:
|
||||
mcall
|
||||
|
||||
.next:
|
||||
add edx, MAX_NICK_LEN ; next name
|
||||
add ebx, 10 ; height distance between lines
|
||||
sub edi, 10
|
||||
ja .loop
|
||||
|
||||
.done:
|
||||
popa
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
draw_channel_text:
|
||||
|
||||
pusha
|
||||
|
||||
mov eax, 4 ; draw text
|
||||
mov ebx, TEXT_X shl 16 + TEXT_Y
|
||||
mov ecx, 12 ; 12 lines max ?
|
||||
mov esi, [textbox_width]
|
||||
|
||||
.dct:
|
||||
pusha
|
||||
mov cx, bx
|
||||
shl ecx, 16
|
||||
mov cx, 9 ; character height
|
||||
mov eax, 13 ; draw rectangle
|
||||
mov ebx, TEXT_X shl 16
|
||||
mov bx, word[textbox_width]
|
||||
imul bx, 6 ; character width
|
||||
mov edx, [colors.work]
|
||||
mcall
|
||||
popa
|
||||
|
||||
push ecx
|
||||
mov ecx, [colors.work_text]
|
||||
cmp word[edx], '* '
|
||||
jne .no_red
|
||||
mov ecx, 0x00aa0000
|
||||
jmp .draw
|
||||
.no_red:
|
||||
|
||||
cmp word[edx], '**'
|
||||
jne .no_light_blue
|
||||
cmp byte[edx+2], '*'
|
||||
jne .no_light_blue
|
||||
mov ecx, 0x000000aa
|
||||
jmp .draw
|
||||
.no_light_blue:
|
||||
|
||||
cmp byte[edx], '#'
|
||||
jne .no_blue
|
||||
mov ecx, 0x0000aa00
|
||||
; jmp .draw
|
||||
.no_blue:
|
||||
|
||||
.draw:
|
||||
mcall
|
||||
add edx, [textbox_width]
|
||||
add ebx, 10 ; height distance between lines
|
||||
|
||||
pop ecx
|
||||
loop .dct
|
||||
|
||||
popa
|
||||
ret
|
||||
|
||||
|
||||
|
||||
draw_windownames:
|
||||
|
||||
mov eax, 8
|
||||
mov ebx, 5 shl 16 + 120
|
||||
mov ecx, 12 shl 16 + 12
|
||||
mov edx, WINDOW_BTN_START
|
||||
mov edi, windows
|
||||
.more_btn:
|
||||
mov esi, [colors.work_button]
|
||||
cmp [window_open], edi
|
||||
jne @f
|
||||
not esi
|
||||
and esi, 0x00ffffff
|
||||
@@:
|
||||
mcall
|
||||
inc edx
|
||||
add ebx, 125 shl 16
|
||||
add edi, sizeof.window
|
||||
cmp [edi + window.data_ptr], 0
|
||||
jne .more_btn
|
||||
|
||||
mov eax, 4
|
||||
mov ebx, 10 shl 16 + 15
|
||||
mov ecx, [colors.work_button_text]
|
||||
or ecx, 0x80000000 ; ASCIIZ string
|
||||
lea edx, [windows + window.name]
|
||||
mov esi, MAX_WINDOWS
|
||||
.more:
|
||||
mcall
|
||||
add edx, sizeof.window
|
||||
cmp byte[edx], 0
|
||||
je .enough
|
||||
add ebx, 125 shl 16
|
||||
dec esi
|
||||
jnz .more
|
||||
.enough:
|
||||
|
||||
ret
|
||||
|
||||
|
476
programs/network/ircc/ircc.asm
Normal file
476
programs/network/ircc/ircc.asm
Normal file
@ -0,0 +1,476 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; IRC client for KolibriOS ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr@kolibrios.org, ;;
|
||||
;; text encoder/decoder by Clevermouse. ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
version equ '0.1'
|
||||
|
||||
; connection status
|
||||
STATUS_DISCONNECTED = 0
|
||||
STATUS_RESOLVING = 1
|
||||
STATUS_CONNECTING = 2
|
||||
STATUS_CONNECTED = 3
|
||||
|
||||
; window flags
|
||||
FLAG_UPDATED = 1 shl 0
|
||||
FLAG_CLOSE = 1 shl 1
|
||||
FLAG_RECEIVING_NAMES = 1 shl 2
|
||||
|
||||
; window types
|
||||
WINDOWTYPE_SERVER = 0
|
||||
WINDOWTYPE_CHANNEL = 1
|
||||
WINDOWTYPE_CHAT = 2
|
||||
WINDOWTYPE_LIST = 3
|
||||
WINDOWTYPE_DCC = 4
|
||||
|
||||
; supported encodings
|
||||
CP866 = 0
|
||||
CP1251 = 1
|
||||
UTF8 = 2
|
||||
|
||||
; settings
|
||||
USERCMD_MAX_SIZE = 400
|
||||
|
||||
WIN_MIN_X = 600
|
||||
WIN_MIN_Y = 165
|
||||
|
||||
TEXT_X = 5
|
||||
TEXT_Y = 30
|
||||
|
||||
TOP_Y = 25
|
||||
|
||||
MAX_WINDOWS = 20
|
||||
MAX_USERS = 4096
|
||||
|
||||
MAX_NICK_LEN = 32
|
||||
MAX_REAL_LEN = 32 ; realname
|
||||
MAX_SERVER_NAME = 256
|
||||
|
||||
MAX_CHANNEL_LEN = 40
|
||||
MAX_CHANNELS = 37
|
||||
|
||||
MAX_COMMAND_LEN = 512
|
||||
|
||||
TIMESTAMP = 3 ; 3 = hh:mm:ss, 2 = hh:mm, 0 = no timestamp
|
||||
|
||||
MAX_WINDOWNAME_LEN = 256
|
||||
|
||||
WINDOW_BTN_START = 100
|
||||
|
||||
SCROLLBAR_WIDTH = 12
|
||||
|
||||
USERLIST_X = 98
|
||||
|
||||
|
||||
format binary as ""
|
||||
|
||||
use32
|
||||
|
||||
org 0x0
|
||||
|
||||
db 'MENUET01' ; 8 byte id
|
||||
dd 1 ; header version
|
||||
dd START ; program start
|
||||
dd I_END ; program image size
|
||||
dd IM_END+2048 ; required amount of memory
|
||||
dd IM_END+2048
|
||||
dd param
|
||||
dd path
|
||||
|
||||
include "../macros.inc"
|
||||
include "../proc32.inc"
|
||||
include "../dll.inc"
|
||||
include "../network.inc"
|
||||
include "../struct.inc"
|
||||
include '../../../../../programs/develop/libraries/box_lib/trunk/box_lib.mac'
|
||||
|
||||
struct window
|
||||
data_ptr dd ? ; zero if not used
|
||||
flags db ?
|
||||
type db ?
|
||||
name rb MAX_WINDOWNAME_LEN
|
||||
users dd ?
|
||||
users_scroll dd ?
|
||||
selected dd ? ; selected user, 0 if none selected
|
||||
ends
|
||||
|
||||
struct window_data
|
||||
text rb 120*60
|
||||
title rb 256
|
||||
names rb MAX_NICK_LEN * MAX_USERS
|
||||
usertext rb 256
|
||||
usertextlen dd ?
|
||||
ends
|
||||
|
||||
include "encodings.inc"
|
||||
include "window.inc" ; also contains text print routines
|
||||
include "serverparser.inc"
|
||||
include "userparser.inc"
|
||||
include "socket.inc"
|
||||
include "gui.inc"
|
||||
include "users.inc"
|
||||
|
||||
|
||||
START:
|
||||
|
||||
mcall 68, 11 ; init heap so we can allocate memory dynamically
|
||||
|
||||
; wanted events
|
||||
mcall 40, EVM_REDRAW + EVM_KEY + EVM_BUTTON + EVM_STACK + EVM_MOUSE
|
||||
|
||||
; load libraries
|
||||
stdcall dll.Load, @IMPORT
|
||||
test eax, eax
|
||||
jnz exit
|
||||
|
||||
; find path to main settings file (ircc.ini)
|
||||
mov edi, path ; Calculate the length of zero-terminated string
|
||||
xor al, al
|
||||
mov ecx, 1024
|
||||
repne scasb
|
||||
dec edi
|
||||
mov eax, '.ini'
|
||||
stosd
|
||||
xor al, al
|
||||
stosb
|
||||
|
||||
; Fill the window buffer with zeros
|
||||
mov edi, windows
|
||||
mov ecx, (sizeof.window*MAX_WINDOWS+3)/4
|
||||
xor eax, eax
|
||||
rep stosd
|
||||
|
||||
; clear command area too
|
||||
mov edi, servercommand
|
||||
mov ecx, 600/4
|
||||
rep stosd
|
||||
|
||||
; allocate window data block
|
||||
call window_create
|
||||
mov ebx, windows
|
||||
mov [ebx + window.data_ptr], eax
|
||||
mov [ebx + window.flags], 0
|
||||
mov [ebx + window.type], WINDOWTYPE_SERVER
|
||||
add eax, window_data.text
|
||||
mov [text_start], eax
|
||||
|
||||
call window_refresh
|
||||
|
||||
; get system colors
|
||||
mcall 48, 3, colors, 40
|
||||
|
||||
; set edit box and scrollbar colors
|
||||
mov eax, [colors.work]
|
||||
mov [scroll1.bg_color], eax
|
||||
|
||||
mov eax, [colors.work_button]
|
||||
mov [scroll1.front_color], eax
|
||||
|
||||
mov eax, [colors.work_text]
|
||||
mov [scroll1.line_color], eax
|
||||
|
||||
; get settings from ini
|
||||
invoke ini.get_str, path, str_user, str_nick, user_nick, MAX_NICK_LEN, default_nick
|
||||
invoke ini.get_str, path, str_user, str_real, user_real_name, MAX_REAL_LEN, default_real
|
||||
|
||||
; Welcome user
|
||||
mov esi, str_welcome
|
||||
call print_text2
|
||||
|
||||
call draw_window ;;; FIXME (gui is not correctly drawn first time)
|
||||
|
||||
redraw:
|
||||
call draw_window
|
||||
|
||||
still:
|
||||
|
||||
; wait here for event
|
||||
mcall 10
|
||||
|
||||
dec eax
|
||||
jz redraw
|
||||
|
||||
dec eax
|
||||
jz main_window_key
|
||||
|
||||
dec eax
|
||||
jz button
|
||||
|
||||
cmp al, 3
|
||||
je mouse
|
||||
|
||||
call process_network_event
|
||||
|
||||
mov edx, [window_open]
|
||||
test [edx + window.flags], FLAG_UPDATED
|
||||
jz .no_update
|
||||
and [edx + window.flags], not FLAG_UPDATED
|
||||
mov edx, [edx + window.data_ptr]
|
||||
add edx, window_data.text
|
||||
call draw_channel_text
|
||||
.no_update:
|
||||
call print_channel_list
|
||||
|
||||
jmp still
|
||||
|
||||
button:
|
||||
|
||||
mcall 17 ; get id
|
||||
shr eax, 8
|
||||
|
||||
cmp ax, 1 ; close program
|
||||
je exit
|
||||
|
||||
cmp ax, 50
|
||||
jne @f
|
||||
|
||||
mcall 37, 1 ; Get mouse position
|
||||
sub ax, TEXT_Y
|
||||
mov bl, 10
|
||||
div bl
|
||||
and eax, 0x000000ff
|
||||
inc eax
|
||||
add eax, [scroll1.position]
|
||||
mov ebx, [window_open]
|
||||
mov [ebx + window.selected], eax
|
||||
|
||||
call print_channel_list
|
||||
|
||||
jmp still
|
||||
|
||||
@@:
|
||||
sub ax, WINDOW_BTN_START
|
||||
jb exit
|
||||
|
||||
cmp ax, MAX_WINDOWS
|
||||
ja exit
|
||||
|
||||
mov dx, sizeof.window
|
||||
mul dx
|
||||
shl edx, 16
|
||||
mov dx, ax
|
||||
add edx, windows
|
||||
cmp [edx + window.data_ptr], 0
|
||||
je exit
|
||||
mov [window_open], edx
|
||||
call window_refresh
|
||||
call draw_window
|
||||
|
||||
jmp still
|
||||
exit:
|
||||
mcall -1
|
||||
|
||||
|
||||
|
||||
main_window_key:
|
||||
|
||||
mcall 2
|
||||
|
||||
push dword edit1
|
||||
call [edit_box_key]
|
||||
|
||||
cmp ah, 13 ; enter
|
||||
jne no_send2
|
||||
|
||||
call user_parser
|
||||
|
||||
mov [edit1.size], 0
|
||||
mov [edit1.pos], 0
|
||||
|
||||
push dword edit1
|
||||
call [edit_box_draw]
|
||||
|
||||
mov edx, [window_open]
|
||||
mov edx, [edx + window.data_ptr]
|
||||
add edx, window_data.text
|
||||
call draw_channel_text
|
||||
|
||||
jmp still
|
||||
no_send2:
|
||||
|
||||
jmp still
|
||||
|
||||
mouse:
|
||||
push dword edit1
|
||||
call [edit_box_mouse]
|
||||
|
||||
; TODO: check if scrollbar is active
|
||||
push [scroll1.position]
|
||||
push dword scroll1
|
||||
call [scrollbar_v_mouse]
|
||||
pop eax
|
||||
cmp eax, [scroll1.position] ; did the scrollbar move?
|
||||
je @f
|
||||
call print_channel_list
|
||||
@@:
|
||||
|
||||
jmp still
|
||||
|
||||
|
||||
; DATA AREA
|
||||
|
||||
encoding_text:
|
||||
db 'CP866 '
|
||||
db 'CP1251'
|
||||
db 'UTF-8 '
|
||||
encoding_text_len = 6
|
||||
|
||||
action_header db '*** ', 0
|
||||
action_header_short db '* ', 0
|
||||
ctcp_header db '-> [',0
|
||||
ctcp_version db '] VERSION',10,0
|
||||
ctcp_ping db '] PING',10,0
|
||||
ctcp_time db '] TIME',10,0
|
||||
has_left_channel db ' has left ', 0
|
||||
joins_channel db ' has joined ', 0
|
||||
is_now_known_as db ' is now known as ', 0
|
||||
has_quit_irc db ' has quit IRC', 10, 0
|
||||
sets_mode db ' sets mode ', 0
|
||||
kicked db ' is kicked from ', 0
|
||||
str_talking db 'Now talking in ',0
|
||||
str_topic db 'Topic is ',0
|
||||
str_setby db 'Set by ',0
|
||||
|
||||
str_version db 'VERSION '
|
||||
str_programname db 'KolibriOS IRC client ', version, 0
|
||||
|
||||
str_user db 'user', 0
|
||||
str_nick db 'nick', 0
|
||||
str_real db 'realname', 0
|
||||
str_email db 'email', 0
|
||||
|
||||
default_nick db 'kolibri_user', 0
|
||||
default_real db 'Kolibri User', 0
|
||||
|
||||
str_welcome db 10
|
||||
db ' ______________________ __ __ __',10
|
||||
db '| \______ \_ ___ \ ____ | | |__| ____ _____/ |_',10
|
||||
db '| || _/ \ \/ _/ ___\| | | |/ __ \ / \ __\',10
|
||||
db '| || | \ \____ \ \___| |_| \ ___/| | \ |',10
|
||||
db '|___||____|_ /\______ / \___ >____/__|\___ >___| /__|',10
|
||||
db ' \/ \/ \/ \/ \/',10
|
||||
db 10
|
||||
db 'Welcome to IRC client ',version,' for KolibriOS',10
|
||||
db 10
|
||||
db 'Type /help for help',10,0
|
||||
|
||||
str_nickchange db 'Nickname is now ',0
|
||||
str_realchange db 'Real name is now ',0
|
||||
str_dotnewline db '.',10, 0
|
||||
str_newline db 10, 0
|
||||
str_connecting db 10,'* Connecting to ',0
|
||||
str_help db 10,'following commands are available:',10
|
||||
db 10
|
||||
db '/nick <nick> : change nickname to <nick>',10
|
||||
db '/real <real name> : change real name to <real name>',10
|
||||
db '/server <address> : connect to server <address>',10
|
||||
db '/code <code> : change codepage to cp866, cp1251, or utf8',10,0
|
||||
|
||||
str_1 db ' -',0
|
||||
str_2 db '- ',0
|
||||
|
||||
str_sockerr db 'Socket Error',10,0
|
||||
str_dnserr db 'Unable to resolve hostname.',10,0
|
||||
str_refused db 'Connection refused',10,0
|
||||
|
||||
sockaddr1:
|
||||
dw AF_INET4
|
||||
.port dw 0x0b1a ; 6667
|
||||
.ip dd 0
|
||||
rb 10
|
||||
|
||||
|
||||
status dd STATUS_DISCONNECTED
|
||||
|
||||
text_start dd ? ; pointer to current textbox data
|
||||
irc_data dd 0x0 ; encoder
|
||||
textbox_width dd 80 ; in characters, not pixels ;)
|
||||
pos dd 66 * 11 ; encoder
|
||||
|
||||
window_open dd windows
|
||||
window_print dd windows
|
||||
|
||||
scroll dd 1
|
||||
dd 12
|
||||
|
||||
align 4
|
||||
@IMPORT:
|
||||
|
||||
library network, 'network.obj',\
|
||||
libini, 'libini.obj',\
|
||||
boxlib, 'box_lib.obj'
|
||||
|
||||
import network,\
|
||||
getaddrinfo, 'getaddrinfo',\
|
||||
freeaddrinfo, 'freeaddrinfo',\
|
||||
inet_ntoa, 'inet_ntoa'
|
||||
|
||||
import libini,\
|
||||
ini.get_str, 'ini_get_str',\
|
||||
ini.get_int, 'ini_get_int'
|
||||
|
||||
import boxlib,\
|
||||
edit_box_draw ,'edit_box' ,\
|
||||
edit_box_key ,'edit_box_key' ,\
|
||||
edit_box_mouse ,'edit_box_mouse' ,\
|
||||
scrollbar_v_draw ,'scrollbar_v_draw' ,\
|
||||
scrollbar_v_mouse,'scrollbar_v_mouse'
|
||||
|
||||
|
||||
usercommand db '/server chat.freenode.net', 0
|
||||
rb MAX_COMMAND_LEN
|
||||
|
||||
I_END:
|
||||
|
||||
; width, left, top
|
||||
edit1 edit_box 0, 0, 0, 0xffffff, 0x6f9480, 0, 0, 0, USERCMD_MAX_SIZE, usercommand, mouse_dd, ed_focus, 25, 25
|
||||
; xsize, xpos, ysize, ypos, max, cur, pos, bgcol, frcol, linecol
|
||||
scroll1 scrollbar SCROLLBAR_WIDTH, 300, 150, TOP_Y, 10, 100, 0, 0, 0, 0, 0, 1
|
||||
scroll2 scrollbar SCROLLBAR_WIDTH, 300, 150, TOP_Y, 10, 100, 0, 0, 0, 0, 0, 1
|
||||
|
||||
main_PID dd ? ; identifier of main thread
|
||||
utf8_bytes_rest dd ? ; bytes rest in current UTF8 sequence
|
||||
utf8_char dd ? ; first bits of current UTF8 character
|
||||
gai_reqdata rb 32 ; buffer for getaddrinfo_start/process
|
||||
ip_list dd ? ; will be filled as pointer to addrinfo list
|
||||
packetbuf rb 1024 ; buffer for packets to server
|
||||
path rb 1024
|
||||
param rb 1024
|
||||
|
||||
socketnum dd ?
|
||||
|
||||
servercommand rb 600
|
||||
|
||||
thread_info rb 1024
|
||||
xsize dd ?
|
||||
ysize dd ?
|
||||
|
||||
colors system_colors
|
||||
|
||||
irc_server_name rb MAX_SERVER_NAME
|
||||
|
||||
user_nick rb MAX_NICK_LEN
|
||||
user_real_name rb MAX_REAL_LEN
|
||||
|
||||
windows rb MAX_WINDOWS*sizeof.window
|
||||
|
||||
mouse_dd dd ?
|
||||
|
||||
IM_END:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
8
programs/network/ircc/ircc.ini
Normal file
8
programs/network/ircc/ircc.ini
Normal file
@ -0,0 +1,8 @@
|
||||
[user]
|
||||
nick = kolibri_user
|
||||
realname = tetten
|
||||
|
||||
[colors]
|
||||
action1 = 0x000000aa
|
||||
action2 = 0x0000aa00
|
||||
action3 = 0x00aa0000
|
928
programs/network/ircc/serverparser.inc
Normal file
928
programs/network/ircc/serverparser.inc
Normal file
@ -0,0 +1,928 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
server_parser:
|
||||
|
||||
mov esi, servercommand
|
||||
|
||||
cmp byte [esi], ':'
|
||||
jne .parse
|
||||
|
||||
.spaceloop:
|
||||
lodsb
|
||||
test al, al
|
||||
jz .fail
|
||||
cmp al, ' '
|
||||
jne .spaceloop
|
||||
|
||||
.parse:
|
||||
mov eax, [esi]
|
||||
or eax, 0x20202020
|
||||
mov edi, server_commands
|
||||
mov ecx, server_commands.number
|
||||
|
||||
.loop:
|
||||
scasd
|
||||
je .got_cmd
|
||||
add edi, 4
|
||||
dec ecx
|
||||
jnz .loop
|
||||
|
||||
.fail:
|
||||
ret
|
||||
|
||||
.got_cmd:
|
||||
jmp dword[edi]
|
||||
|
||||
|
||||
server_commands:
|
||||
|
||||
dd '322 ', cmd_322 ; RPL_LIST
|
||||
dd '323 ', cmd_323 ; RPL_LISTEND
|
||||
dd '328 ', cmd_328
|
||||
dd '332 ', cmd_topic
|
||||
dd '333 ', cmd_333 ; nickname and time of topic
|
||||
dd '353 ', cmd_353 ; name reply
|
||||
dd '366 ', cmd_366 ; end of names list
|
||||
dd '372 ', cmd_372 ; motd
|
||||
dd '375 ', cmd_375 ; start of motd
|
||||
dd '376 ', cmd_376 ; end of motd
|
||||
dd '421 ', cmd_421 ; unknown command
|
||||
dd 'join', cmd_join
|
||||
dd 'kick', cmd_kick
|
||||
dd 'mode', cmd_mode
|
||||
dd 'nick', cmd_nick
|
||||
dd 'part', cmd_part
|
||||
dd 'ping', cmd_ping
|
||||
dd 'priv', cmd_privmsg
|
||||
dd 'quit', cmd_quit
|
||||
dd 'noti', cmd_notice
|
||||
|
||||
.number = ($ - server_commands) / 8
|
||||
|
||||
|
||||
align 4
|
||||
compare_to_nick:
|
||||
|
||||
push esi
|
||||
mov ecx, MAX_NICK_LEN
|
||||
mov esi, user_nick
|
||||
.loop:
|
||||
lodsb
|
||||
cmp al, ' '
|
||||
jbe .done
|
||||
cmp al, 'a'
|
||||
jb .ok
|
||||
cmp al, 'z'
|
||||
ja .ok
|
||||
sub al, 0x20
|
||||
.ok:
|
||||
|
||||
mov bl, byte[edi]
|
||||
cmp bl, 'a'
|
||||
jb .ok2
|
||||
cmp bl, 'z'
|
||||
ja .ok2
|
||||
sub bl, 0x20
|
||||
.ok2:
|
||||
cmp bl, al
|
||||
jne .not_equal
|
||||
inc edi
|
||||
dec ecx
|
||||
jnz .loop
|
||||
|
||||
.done:
|
||||
xor eax, eax
|
||||
pop esi
|
||||
ret
|
||||
|
||||
.not_equal:
|
||||
or eax, -1
|
||||
pop esi
|
||||
ret
|
||||
|
||||
align 4
|
||||
skip_nick:
|
||||
|
||||
; First: skip the NICK (maybe we should verify it?)
|
||||
.nick:
|
||||
lodsb
|
||||
cmp al, ' '
|
||||
je .skip
|
||||
cmp al, ':'
|
||||
je .skip
|
||||
jmp .nick
|
||||
|
||||
; skip all leading spaces and semicolons
|
||||
.skip:
|
||||
lodsb
|
||||
cmp al, ' '
|
||||
je .skip
|
||||
cmp al, ':'
|
||||
je .skip
|
||||
dec esi
|
||||
|
||||
ret
|
||||
|
||||
|
||||
align 4
|
||||
find_window: ; esi is ptr to windowname
|
||||
|
||||
push esi
|
||||
|
||||
mov edi, esi
|
||||
call compare_to_nick
|
||||
jne .nochat
|
||||
|
||||
mov esi, servercommand+1
|
||||
.nochat:
|
||||
|
||||
; now search for window in list
|
||||
mov ebx, windows
|
||||
mov [window_print], ebx ; set first window (server window) as default output window
|
||||
.scanloop:
|
||||
cmp [ebx + window.data_ptr], 0
|
||||
je .create_it
|
||||
push esi
|
||||
lea edi, [ebx + window.name]
|
||||
mov ecx, MAX_WINDOWNAME_LEN
|
||||
repe cmpsb
|
||||
pop esi
|
||||
cmp byte[edi-1], 0
|
||||
je .got_it
|
||||
add ebx, sizeof.window
|
||||
; TODO: check buffer limits ?
|
||||
jmp .scanloop
|
||||
|
||||
; create channel window - search for empty slot
|
||||
.create_it:
|
||||
mov ebx, windows
|
||||
mov ecx, MAX_WINDOWS
|
||||
.scanloop2:
|
||||
cmp [ebx + window.data_ptr], 0
|
||||
je .free_found
|
||||
add ebx, sizeof.window
|
||||
dec ecx
|
||||
jnz .scanloop2
|
||||
; Error: no more available windows!
|
||||
jmp .just_skip
|
||||
|
||||
.free_found:
|
||||
push ebx
|
||||
call window_create
|
||||
pop ebx
|
||||
test eax, eax
|
||||
jz .just_skip
|
||||
mov [ebx + window.data_ptr], eax
|
||||
mov [ebx + window.type], WINDOWTYPE_CHAT
|
||||
mov [ebx + window.flags], 0
|
||||
|
||||
call window_set_name
|
||||
|
||||
mov [window_open], ebx
|
||||
mov [window_print], ebx
|
||||
call window_refresh
|
||||
|
||||
call draw_windownames
|
||||
jmp .just_skip
|
||||
|
||||
; found it!
|
||||
.got_it:
|
||||
mov [window_print], ebx
|
||||
call window_refresh
|
||||
|
||||
.just_skip:
|
||||
pop esi
|
||||
.skip1:
|
||||
; skip text
|
||||
lodsb
|
||||
test al, al
|
||||
jz .quit
|
||||
cmp al, ' '
|
||||
jne .skip1
|
||||
dec esi
|
||||
; now skip trailing spaces and semicolons
|
||||
.skip2:
|
||||
lodsb
|
||||
test al, al
|
||||
jz .quit
|
||||
cmp al, ' '
|
||||
je .skip2
|
||||
cmp al, ':'
|
||||
je .skip2
|
||||
dec esi
|
||||
|
||||
.quit:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cmd_328:
|
||||
cmd_421:
|
||||
cmd_372:
|
||||
cmd_375:
|
||||
cmd_376:
|
||||
add esi, 4
|
||||
jmp cmd_notice.loop
|
||||
|
||||
cmd_notice:
|
||||
|
||||
cmp byte[servercommand], ':'
|
||||
jne .gogogo
|
||||
|
||||
mov byte [esi-1], 0
|
||||
push esi
|
||||
mov esi, str_1
|
||||
call print_text2
|
||||
mov esi, servercommand+1
|
||||
call print_text2
|
||||
mov esi, str_2
|
||||
call print_text2
|
||||
pop esi
|
||||
|
||||
.gogogo:
|
||||
add esi, 6
|
||||
|
||||
.loop:
|
||||
inc esi
|
||||
cmp byte [esi], 0
|
||||
je .fail
|
||||
cmp byte [esi], ' '
|
||||
jne .loop
|
||||
|
||||
.loop2:
|
||||
inc esi
|
||||
cmp byte [esi], 0
|
||||
je .fail
|
||||
cmp byte [esi], ' '
|
||||
je .loop2
|
||||
cmp byte [esi], ':'
|
||||
je .loop2
|
||||
|
||||
call print_text2
|
||||
mov esi, str_newline
|
||||
call print_text2
|
||||
|
||||
.fail:
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
cmd_ping:
|
||||
|
||||
; Just change PING to PONG
|
||||
mov dword[esi], 'PONG'
|
||||
|
||||
; Find the end of the command
|
||||
lea edi, [esi + 5]
|
||||
xor al, al
|
||||
repne scasb
|
||||
|
||||
; Now send it back
|
||||
mov edx, esi
|
||||
mov esi, edi
|
||||
mov word [esi], 0x0d0a
|
||||
inc esi
|
||||
inc esi
|
||||
sub esi, edx
|
||||
mcall send, [socketnum], , , 0
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
cmd_privmsg:
|
||||
|
||||
add esi, 8 ; skip 'PRIVMSG '
|
||||
call find_window ; esi now points to end of destination name
|
||||
|
||||
cmp byte[esi], 1
|
||||
je cmd_ctcp
|
||||
|
||||
cmp dword[esi], 'ACTI' ; Action?
|
||||
je .action
|
||||
|
||||
; nope, just plain old privmsg
|
||||
if TIMESTAMP
|
||||
call print_timestamp
|
||||
end if
|
||||
|
||||
push esi
|
||||
mov bl, '<'
|
||||
call print_character
|
||||
|
||||
mov eax, servercommand+1
|
||||
mov dl, '!'
|
||||
call print_text
|
||||
|
||||
mov bl, '>'
|
||||
call print_character
|
||||
|
||||
mov bl, ' '
|
||||
call print_character
|
||||
|
||||
pop esi
|
||||
call print_text2
|
||||
|
||||
mov bl, 10
|
||||
call print_character
|
||||
|
||||
.fail:
|
||||
ret
|
||||
|
||||
.action:
|
||||
add esi, 8
|
||||
push esi
|
||||
if TIMESTAMP
|
||||
call print_timestamp
|
||||
end if
|
||||
|
||||
mov esi, action_header_short
|
||||
call print_text2
|
||||
|
||||
mov eax, servercommand+1
|
||||
mov dl, ' '
|
||||
call print_text
|
||||
|
||||
mov bl, ' '
|
||||
call print_character
|
||||
|
||||
pop esi
|
||||
call print_text2
|
||||
|
||||
mov bl, 10
|
||||
call print_character
|
||||
|
||||
ret
|
||||
|
||||
cmd_ctcp:
|
||||
inc esi
|
||||
|
||||
cmp dword[esi], 'VERS'
|
||||
je .version
|
||||
|
||||
cmp dword[esi], 'TIME'
|
||||
je .time
|
||||
|
||||
cmp dword[esi], 'PING'
|
||||
je .ping
|
||||
|
||||
ret
|
||||
|
||||
.time:
|
||||
mov byte [esi+4], ' '
|
||||
lea edi, [esi+5]
|
||||
|
||||
; TODO: add system date (fn 29) in human readable format
|
||||
|
||||
mcall 3 ; get system time
|
||||
|
||||
mov ecx, 3
|
||||
.timeloop:
|
||||
mov bl, al
|
||||
shr al, 4
|
||||
add al, '0'
|
||||
stosb
|
||||
|
||||
mov al, bl
|
||||
and al, 0x0f
|
||||
add al, '0'
|
||||
stosb
|
||||
|
||||
dec ecx
|
||||
jz .timedone
|
||||
|
||||
mov al, ':'
|
||||
stosb
|
||||
shr eax, 8
|
||||
jmp .timeloop
|
||||
|
||||
.timedone:
|
||||
xor al, al
|
||||
stosb
|
||||
call ctcp_reply
|
||||
|
||||
if TIMESTAMP
|
||||
call print_timestamp
|
||||
end if
|
||||
|
||||
mov esi, ctcp_header
|
||||
call print_text2
|
||||
|
||||
mov esi, servercommand+1
|
||||
call print_text2
|
||||
|
||||
mov esi, ctcp_time
|
||||
call print_text2
|
||||
|
||||
ret
|
||||
|
||||
.version:
|
||||
mov esi, str_version
|
||||
call ctcp_reply
|
||||
|
||||
if TIMESTAMP
|
||||
call print_timestamp
|
||||
end if
|
||||
|
||||
mov esi, ctcp_header
|
||||
call print_text2
|
||||
|
||||
mov esi, servercommand+1
|
||||
call print_text2
|
||||
|
||||
mov esi, ctcp_version
|
||||
call print_text2
|
||||
|
||||
ret
|
||||
|
||||
.ping:
|
||||
call ctcp_reply
|
||||
|
||||
if TIMESTAMP
|
||||
call print_timestamp
|
||||
end if
|
||||
|
||||
mov esi, ctcp_header
|
||||
call print_text2
|
||||
|
||||
mov esi, servercommand+1
|
||||
call print_text2
|
||||
|
||||
mov esi, ctcp_ping
|
||||
call print_text2
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
ctcp_reply:
|
||||
|
||||
push esi
|
||||
|
||||
mov dword [usercommand], 'NOTI'
|
||||
mov dword [usercommand+4], 'CE '
|
||||
|
||||
mov esi, servercommand+1
|
||||
mov edi, usercommand+7
|
||||
.nickloop:
|
||||
lodsb
|
||||
cmp al, '!'
|
||||
je .done
|
||||
cmp al, ' '
|
||||
je .done
|
||||
test al, al
|
||||
je .fail
|
||||
stosb
|
||||
jmp .nickloop
|
||||
.done:
|
||||
mov byte [esi-1], 0
|
||||
mov ax, ' :'
|
||||
stosw
|
||||
mov al, 1
|
||||
stosb
|
||||
|
||||
pop esi
|
||||
.replyloop:
|
||||
lodsb
|
||||
cmp al, 1
|
||||
jbe .done2
|
||||
stosb
|
||||
jmp .replyloop
|
||||
.done2:
|
||||
|
||||
mov al, 1
|
||||
stosb
|
||||
mov ax, 0x0a0d
|
||||
stosw
|
||||
|
||||
lea esi, [edi - usercommand]
|
||||
mcall send, [socketnum], usercommand, , 0
|
||||
.fail:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
cmd_part:
|
||||
add esi, 5 ; skip 'PART '
|
||||
push esi
|
||||
call skip_nick
|
||||
call find_window
|
||||
pop esi
|
||||
|
||||
; Is it me who parted?
|
||||
mov edi, servercommand+1
|
||||
call compare_to_nick
|
||||
jne .dont_close
|
||||
|
||||
; yes, close the window
|
||||
mov edi, [window_print]
|
||||
mov [edi + window.flags], FLAG_UPDATED + FLAG_CLOSE
|
||||
|
||||
ret
|
||||
|
||||
; somebody else parted, just print message
|
||||
.dont_close:
|
||||
push esi
|
||||
mov esi, action_header
|
||||
call print_text2
|
||||
|
||||
mov eax, servercommand+1
|
||||
mov dl, '!'
|
||||
mov cl, ' '
|
||||
call print_text
|
||||
|
||||
mov esi, has_left_channel
|
||||
call print_text2
|
||||
|
||||
pop esi
|
||||
call print_text2
|
||||
|
||||
mov esi, str_newline
|
||||
call print_text2
|
||||
|
||||
mov ebx, [window_print]
|
||||
mov esi, servercommand+1
|
||||
call user_remove
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
cmd_join:
|
||||
add esi, 5 ; skip 'JOIN '
|
||||
|
||||
; compare nick: did we join a channel?
|
||||
mov edi, servercommand+1
|
||||
call compare_to_nick
|
||||
jne .no_new_window
|
||||
|
||||
; create channel window - search for empty slot
|
||||
mov ebx, windows
|
||||
mov ecx, MAX_WINDOWS
|
||||
.loop:
|
||||
cmp [ebx + window.data_ptr], 0
|
||||
je .free_found
|
||||
add ebx, sizeof.window
|
||||
dec ecx
|
||||
jnz .loop
|
||||
; Error: no more available windows!! ;;;;; TODO
|
||||
.fail:
|
||||
ret
|
||||
|
||||
.free_found:
|
||||
push ebx
|
||||
call window_create
|
||||
pop ebx
|
||||
test eax, eax
|
||||
jz .fail
|
||||
mov [ebx + window.data_ptr], eax
|
||||
mov [ebx + window.type], WINDOWTYPE_CHANNEL
|
||||
mov [ebx + window.flags], 0
|
||||
|
||||
call window_set_name
|
||||
|
||||
mov [window_open], ebx
|
||||
mov [window_print], ebx
|
||||
call window_refresh
|
||||
|
||||
push esi
|
||||
mov esi, action_header
|
||||
call print_text2
|
||||
|
||||
mov esi, str_talking
|
||||
call print_text2
|
||||
|
||||
pop eax
|
||||
mov dl, ' '
|
||||
call print_text
|
||||
|
||||
mov esi, str_dotnewline
|
||||
call print_text2
|
||||
|
||||
call draw_window
|
||||
|
||||
ret
|
||||
|
||||
.no_new_window:
|
||||
push esi
|
||||
call find_window
|
||||
|
||||
mov esi, action_header
|
||||
call print_text2
|
||||
|
||||
mov eax, servercommand+1
|
||||
mov dl, '!'
|
||||
call print_text
|
||||
|
||||
mov esi, joins_channel
|
||||
call print_text2
|
||||
|
||||
pop esi
|
||||
call print_text2
|
||||
|
||||
mov esi, str_newline
|
||||
call print_text2
|
||||
|
||||
mov ebx, [window_print]
|
||||
mov esi, servercommand+1
|
||||
call user_add
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
cmd_nick:
|
||||
; NOTE: This command applies to a user, and thus has no specific channel
|
||||
add esi, 5 ; skip 'NICK '
|
||||
|
||||
cmp byte[esi], ':' ; TODO: skip all spaces and semicolons?
|
||||
jne @f
|
||||
inc esi
|
||||
@@:
|
||||
|
||||
; Change the nick in the current userlist. TODO: check other channels too!
|
||||
push esi
|
||||
mov ebx, [window_print]
|
||||
|
||||
mov esi, servercommand+1
|
||||
call user_remove
|
||||
|
||||
mov esi, [esp]
|
||||
call user_add
|
||||
|
||||
call redraw_channel_list
|
||||
|
||||
; Is it me who changed nick?
|
||||
mov edi, servercommand+1
|
||||
call compare_to_nick
|
||||
pop esi
|
||||
jne .not_me
|
||||
|
||||
mov ecx, MAX_NICK_LEN-1
|
||||
push esi
|
||||
.copyloop:
|
||||
lodsb
|
||||
test al, al
|
||||
jz .copydone
|
||||
cmp al, ' '
|
||||
je .copydone
|
||||
stosb
|
||||
dec ecx
|
||||
jnz .copyloop
|
||||
.copydone:
|
||||
xor al, al
|
||||
stosb
|
||||
pop esi
|
||||
.not_me:
|
||||
|
||||
; Now print a message on the current channel
|
||||
push esi
|
||||
mov esi, action_header_short
|
||||
call print_text2
|
||||
|
||||
mov eax, servercommand+1
|
||||
mov dl, '!'
|
||||
call print_text
|
||||
|
||||
mov esi, is_now_known_as
|
||||
call print_text2
|
||||
|
||||
pop esi
|
||||
call print_text2
|
||||
|
||||
mov esi, str_newline
|
||||
call print_text2
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
cmd_kick:
|
||||
add esi, 5 ; skip 'KICK '
|
||||
; Is it me who got kicked?
|
||||
mov edi, servercommand+1
|
||||
call compare_to_nick
|
||||
jne .not_me
|
||||
|
||||
; TODO: mark channel as disconnected
|
||||
|
||||
.not_me:
|
||||
; find the channel user has been kicked from
|
||||
push esi
|
||||
call skip_nick
|
||||
call find_window
|
||||
|
||||
mov esi, action_header_short
|
||||
call print_text2
|
||||
|
||||
mov eax, servercommand+1
|
||||
mov dl, '!'
|
||||
call print_text
|
||||
|
||||
mov esi, kicked
|
||||
call print_text2
|
||||
|
||||
pop esi
|
||||
call print_text2
|
||||
|
||||
mov esi, str_newline
|
||||
call print_text2
|
||||
|
||||
mov ebx, [window_print]
|
||||
mov esi, servercommand+1
|
||||
call user_remove
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
cmd_quit:
|
||||
; NOTE: This command applies to a user, and thus has no specific channel
|
||||
|
||||
mov esi, action_header
|
||||
call print_text2
|
||||
|
||||
mov eax, servercommand+1
|
||||
mov dl, '!'
|
||||
call print_text
|
||||
|
||||
mov esi, has_quit_irc
|
||||
call print_text2
|
||||
|
||||
; TODO: check other channels on same server too!
|
||||
mov ebx, [window_print]
|
||||
mov esi, servercommand+1
|
||||
call user_remove
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
cmd_mode:
|
||||
|
||||
add esi, 5 ; skip 'MODE '
|
||||
|
||||
push esi
|
||||
mov esi, action_header_short
|
||||
call print_text2
|
||||
|
||||
mov eax, servercommand+1
|
||||
mov dl, ' '
|
||||
call print_text
|
||||
|
||||
mov esi, sets_mode
|
||||
call print_text2
|
||||
|
||||
pop esi
|
||||
call print_text2
|
||||
|
||||
mov esi, str_newline
|
||||
call print_text2
|
||||
|
||||
;;; TODO: change username if needed
|
||||
|
||||
ret
|
||||
|
||||
|
||||
cmd_353: ; channel usernames reply
|
||||
|
||||
add esi, 4 ; skip '353 '
|
||||
call skip_nick
|
||||
inc esi ; channel type '*', '=' or '@'
|
||||
inc esi ; ' '
|
||||
call find_window
|
||||
|
||||
; now find window ptr and check if this is the first 353 message
|
||||
mov ebx, [window_print]
|
||||
test [ebx + window.flags], FLAG_RECEIVING_NAMES
|
||||
jnz .add
|
||||
|
||||
or [ebx + window.flags], FLAG_RECEIVING_NAMES
|
||||
; mov [ebx + window.users], 0
|
||||
; TODO: remove all users?
|
||||
|
||||
.add:
|
||||
push esi
|
||||
call user_add
|
||||
pop esi
|
||||
|
||||
.namesloop:
|
||||
lodsb
|
||||
test al, al
|
||||
jz .done
|
||||
cmp al, ' ' ; names list is separated with spaces
|
||||
jne .namesloop
|
||||
jmp .add
|
||||
|
||||
.done:
|
||||
call redraw_channel_list
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cmd_366: ; channel usernames end
|
||||
|
||||
add esi, 4 ; skip '366 '
|
||||
call skip_nick
|
||||
call find_window
|
||||
|
||||
mov ebx, [window_print]
|
||||
and [ebx + window.flags], not FLAG_RECEIVING_NAMES
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
cmd_topic:
|
||||
|
||||
add esi, 4 ; skip '332 '
|
||||
call skip_nick
|
||||
call find_window
|
||||
|
||||
push esi
|
||||
mov esi, action_header
|
||||
call print_text2
|
||||
|
||||
mov esi, str_topic
|
||||
call print_text2
|
||||
|
||||
pop esi
|
||||
call print_text2
|
||||
|
||||
mov esi, str_newline
|
||||
call print_text2
|
||||
|
||||
ret
|
||||
|
||||
|
||||
cmd_333:
|
||||
|
||||
add esi, 4 ; skip '333 '
|
||||
call skip_nick ;;;;
|
||||
call find_window
|
||||
|
||||
; mov ecx, 2 ; number of spaces to find ;;; CHECKME
|
||||
; .loop:
|
||||
; lodsb
|
||||
; test al, al
|
||||
; je .fail
|
||||
; cmp al, ' '
|
||||
; jne .loop
|
||||
; dec ecx
|
||||
; jnz .loop ; find some more spaces
|
||||
|
||||
push esi
|
||||
mov esi, action_header
|
||||
call print_text2
|
||||
|
||||
mov esi, str_setby
|
||||
call print_text2
|
||||
|
||||
; pop esi
|
||||
; call print_text2
|
||||
|
||||
pop eax
|
||||
mov dl, '!'
|
||||
call print_text
|
||||
|
||||
mov esi, str_newline
|
||||
call print_text2
|
||||
|
||||
.fail:
|
||||
ret
|
||||
|
||||
cmd_322:
|
||||
add esi, 4
|
||||
|
||||
call skip_nick
|
||||
|
||||
call print_text2
|
||||
|
||||
mov esi, str_newline
|
||||
call print_text2
|
||||
|
||||
ret
|
||||
|
||||
cmd_323:
|
||||
|
||||
ret
|
242
programs/network/ircc/socket.inc
Normal file
242
programs/network/ircc/socket.inc
Normal file
@ -0,0 +1,242 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
socket_connect:
|
||||
|
||||
; cmp [status], STATUS_CONNECTED ; TODO
|
||||
; je disconnect
|
||||
|
||||
; ignore if status is not "disconnected"
|
||||
cmp [status], STATUS_DISCONNECTED
|
||||
jne .nothing
|
||||
|
||||
mov esi, str_connecting
|
||||
call print_text2
|
||||
mov esi, irc_server_name
|
||||
call print_text2
|
||||
mov esi, str_dotnewline
|
||||
call print_text2
|
||||
|
||||
; update status
|
||||
inc [status] ; was STATUS_DISCONNECTED, now STATUS_RESOLVING
|
||||
|
||||
; resolve name
|
||||
push esp ; reserve stack place
|
||||
push esp ; fourth parameter
|
||||
push 0 ; third parameter
|
||||
push 0 ; second parameter
|
||||
push irc_server_name
|
||||
call [getaddrinfo]
|
||||
pop esi
|
||||
; test for error
|
||||
test eax, eax
|
||||
jnz .fail_dns
|
||||
|
||||
; fill in ip in sockstruct
|
||||
mov eax, [esi + addrinfo.ai_addr]
|
||||
mov eax, [eax + sockaddr_in.sin_addr]
|
||||
mov [sockaddr1.ip], eax
|
||||
|
||||
; free allocated memory
|
||||
push esi
|
||||
call [freeaddrinfo]
|
||||
|
||||
; update status
|
||||
inc [status]
|
||||
|
||||
; connect
|
||||
mcall socket, AF_INET4, SOCK_STREAM, 0
|
||||
cmp eax, -1
|
||||
jz .fail
|
||||
mov [socketnum], eax
|
||||
|
||||
mcall connect, [socketnum], sockaddr1, 18
|
||||
cmp eax, -1
|
||||
jz .fail_refused
|
||||
|
||||
.nothing:
|
||||
ret
|
||||
|
||||
.fail:
|
||||
mov [status], STATUS_DISCONNECTED
|
||||
|
||||
mov esi, str_sockerr
|
||||
call print_text2
|
||||
|
||||
ret
|
||||
|
||||
.fail_dns:
|
||||
mov [status], STATUS_DISCONNECTED
|
||||
|
||||
mov esi, str_dnserr
|
||||
call print_text2
|
||||
|
||||
ret
|
||||
|
||||
.fail_refused:
|
||||
mov [status], STATUS_DISCONNECTED
|
||||
|
||||
mov esi, str_refused
|
||||
call print_text2
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
socket_write_userinfo:
|
||||
|
||||
; create packet in packetbuf
|
||||
mov edi, packetbuf
|
||||
|
||||
mov eax, 'NICK'
|
||||
stosd
|
||||
mov al, ' '
|
||||
stosb
|
||||
mov esi, user_nick
|
||||
mov ecx, MAX_NICK_LEN
|
||||
.loop:
|
||||
lodsb
|
||||
test al, al
|
||||
jz .done
|
||||
stosb
|
||||
dec ecx
|
||||
jnz .loop
|
||||
.done:
|
||||
mov ax, 0x0d0a
|
||||
stosw
|
||||
|
||||
mov eax, 'USER'
|
||||
stosd
|
||||
mov al, ' '
|
||||
stosb
|
||||
mov esi, user_nick
|
||||
mov ecx, MAX_NICK_LEN
|
||||
.loop2:
|
||||
lodsb
|
||||
test al, al
|
||||
jz .done2
|
||||
stosb
|
||||
dec ecx
|
||||
jnz .loop2
|
||||
.done2:
|
||||
mov eax, ' 8 *'
|
||||
stosd
|
||||
mov ax, ' :'
|
||||
stosw
|
||||
mov al, ' '
|
||||
stosb
|
||||
mov esi, user_real_name
|
||||
mov ecx, MAX_REAL_LEN
|
||||
.loop3:
|
||||
lodsb
|
||||
test al, al
|
||||
jz .done3
|
||||
stosb
|
||||
dec ecx
|
||||
jnz .loop3
|
||||
.done3:
|
||||
mov ax, 0x0d0a
|
||||
stosw
|
||||
|
||||
lea esi, [edi - packetbuf]
|
||||
mcall send, [socketnum], packetbuf, , 0
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
process_network_event:
|
||||
; values for status: 0, 1, 2, 3
|
||||
mov eax, [status]
|
||||
dec eax
|
||||
; 0 = STATUS_DISCONNECTED - do nothing
|
||||
; (ignore network events if we are disconnected from network)
|
||||
js .nothing
|
||||
; 1 = STATUS_RESOLVING
|
||||
jz .nothing
|
||||
; 2 = STATUS_CONNECTING
|
||||
dec eax
|
||||
jz .connecting
|
||||
; 3 = STATUS_CONNECTED
|
||||
jmp .connected
|
||||
|
||||
.nothing:
|
||||
ret
|
||||
|
||||
.connecting:
|
||||
call socket_write_userinfo
|
||||
|
||||
; The connection has been established, change status from "connecting" to "connected".
|
||||
inc [status]
|
||||
|
||||
.connected:
|
||||
call read_incoming_data
|
||||
ret
|
||||
|
||||
|
||||
disconnect:
|
||||
|
||||
cmp [status], STATUS_DISCONNECTED
|
||||
je .nothing
|
||||
|
||||
mcall close, [socketnum]
|
||||
|
||||
mov [status], STATUS_DISCONNECTED
|
||||
|
||||
.nothing:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
read_incoming_data:
|
||||
|
||||
pusha
|
||||
|
||||
; TODO: read more data if we receive one full packet
|
||||
|
||||
.nextpacket:
|
||||
mcall recv, [socketnum], packetbuf, 1024 ; read a packet
|
||||
inc eax ; check if we got one
|
||||
jz .done
|
||||
dec eax
|
||||
jz .done
|
||||
|
||||
; ok we have data, now feed it to the recoder
|
||||
|
||||
lea edx, [packetbuf + eax] ; edx = end pointer
|
||||
mov esi, packetbuf ; esi = start pointer
|
||||
.nextcommand:
|
||||
mov edi, servercommand
|
||||
.byteloop:
|
||||
call get_next_byte ; reads byte from [esi] to al
|
||||
jnc .nextpacket ; if CF is set, we need more data
|
||||
cmp al, 10
|
||||
je .got_command
|
||||
cmp al, 13
|
||||
je .got_command
|
||||
stosb
|
||||
jmp .byteloop
|
||||
|
||||
; we have a command, call the serverparser
|
||||
|
||||
.got_command:
|
||||
mov byte[edi], 0 ; mark the end of the command
|
||||
push esi edx
|
||||
call server_parser
|
||||
pop edx esi
|
||||
jmp .nextcommand
|
||||
|
||||
.done:
|
||||
popa
|
||||
|
||||
ret
|
318
programs/network/ircc/userparser.inc
Normal file
318
programs/network/ircc/userparser.inc
Normal file
@ -0,0 +1,318 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
user_parser:
|
||||
|
||||
mov eax, [edit1.size]
|
||||
mov word [usercommand + eax], 0x0a0d ; terminate the line
|
||||
|
||||
cmp byte[usercommand], '/' ; is it a server command ?
|
||||
je server_command
|
||||
|
||||
; Ignore data commands when not connected.
|
||||
cmp [status], STATUS_CONNECTED
|
||||
jne sdts_ret
|
||||
|
||||
; Ok, we said something, print it to our textbox
|
||||
|
||||
; TODO: dont send if it's a server window?
|
||||
|
||||
push [window_open] ; print to the current window
|
||||
pop [window_print]
|
||||
call window_refresh
|
||||
|
||||
if TIMESTAMP
|
||||
call print_timestamp
|
||||
end if
|
||||
|
||||
mov bl, '<'
|
||||
call print_character
|
||||
|
||||
mov esi, user_nick
|
||||
call print_text2
|
||||
|
||||
mov bl,'>'
|
||||
call print_character
|
||||
mov bl,' '
|
||||
call print_character
|
||||
|
||||
mov eax, [edit1.size]
|
||||
mov byte[usercommand + eax],0
|
||||
|
||||
mov esi, usercommand
|
||||
call print_text2
|
||||
|
||||
mov bl, 10
|
||||
call print_character
|
||||
|
||||
; and now send it to the server
|
||||
|
||||
mov dword[packetbuf], 'priv'
|
||||
mov dword[packetbuf+4], 'msg '
|
||||
|
||||
mov esi, [window_open]
|
||||
add esi, window.name
|
||||
mov edi, packetbuf+8
|
||||
mov ecx, MAX_WINDOWNAME_LEN
|
||||
.loop:
|
||||
lodsb
|
||||
test al, al
|
||||
jz .done
|
||||
stosb
|
||||
dec ecx
|
||||
jnz .loop
|
||||
.done:
|
||||
|
||||
mov ax, ' :'
|
||||
stosw
|
||||
|
||||
mov esi, usercommand
|
||||
mov ecx, [edit1.size]
|
||||
inc ecx
|
||||
call recode
|
||||
|
||||
mov al, 10
|
||||
stosb
|
||||
|
||||
lea esi, [edi - packetbuf]
|
||||
mcall send, [socketnum], packetbuf, , 0
|
||||
|
||||
sdts_ret:
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
user_commands:
|
||||
dd 'nick', cmd_usr_nick
|
||||
dd 'real', cmd_usr_real
|
||||
dd 'serv', cmd_usr_server
|
||||
dd 'help', cmd_usr_help
|
||||
dd 'code', cmd_usr_code
|
||||
; TODO: All other commands require a connection to the server.
|
||||
dd 'quer', cmd_usr_quer
|
||||
dd 'quit', cmd_usr_quit
|
||||
|
||||
.number = ($ - user_commands) / 8
|
||||
|
||||
|
||||
|
||||
server_command:
|
||||
|
||||
mov eax, dword[usercommand+1]
|
||||
or eax, 0x20202020
|
||||
|
||||
mov edi, user_commands
|
||||
mov ecx, user_commands.number
|
||||
.loop:
|
||||
scasd
|
||||
je .got_cmd
|
||||
add edi, 4
|
||||
dec ecx
|
||||
jnz .loop
|
||||
jmp cmd_usr_send ; If none of the previous commands, just send to server
|
||||
|
||||
.got_cmd:
|
||||
jmp dword[edi]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cmd_usr_quit:
|
||||
|
||||
cmp [edit1.size], 5
|
||||
je .ok
|
||||
jb cmd_usr_send
|
||||
cmp byte[usercommand+5], ' '
|
||||
jne cmd_usr_send
|
||||
|
||||
.ok:
|
||||
call cmd_usr_send
|
||||
|
||||
mcall close, [socketnum]
|
||||
|
||||
mov ecx, MAX_WINDOWS
|
||||
mov edi, windows
|
||||
.loop:
|
||||
mov [edi + window.flags], FLAG_CLOSE
|
||||
add edi, sizeof.window
|
||||
dec ecx
|
||||
jnz .loop
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
cmd_usr_nick:
|
||||
|
||||
cmp [edit1.size], 5
|
||||
je .justprint
|
||||
cmp byte[usercommand+5], ' '
|
||||
jne cmd_usr_send
|
||||
|
||||
mov ecx, MAX_NICK_LEN
|
||||
mov esi, usercommand+6
|
||||
mov edi, user_nick
|
||||
.loop:
|
||||
lodsb
|
||||
cmp al, 13
|
||||
je .done
|
||||
stosb
|
||||
dec ecx
|
||||
jnz .loop
|
||||
.done:
|
||||
xor al, al
|
||||
stosb
|
||||
|
||||
cmp [socketnum], 0
|
||||
je .justprint
|
||||
|
||||
lea esi, [edi - usercommand]
|
||||
mcall send, [socketnum], usercommand+1, , 0
|
||||
|
||||
.justprint:
|
||||
mov esi, str_nickchange
|
||||
call print_text2
|
||||
mov esi, user_nick
|
||||
call print_text2
|
||||
mov esi, str_dotnewline
|
||||
call print_text2
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
cmd_usr_real:
|
||||
|
||||
cmp byte[usercommand+5], ' '
|
||||
jne cmd_usr_send
|
||||
|
||||
mov ecx, MAX_REAL_LEN
|
||||
mov esi, usercommand+6
|
||||
mov edi, user_real_name
|
||||
.loop:
|
||||
lodsb
|
||||
cmp al, 13
|
||||
je .done
|
||||
stosb
|
||||
dec ecx
|
||||
jnz .loop
|
||||
.done:
|
||||
xor al, al
|
||||
stosb
|
||||
|
||||
mov esi, str_realchange
|
||||
call print_text2
|
||||
mov esi, user_real_name
|
||||
call print_text2
|
||||
mov esi, str_dotnewline
|
||||
call print_text2
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
cmd_usr_server:
|
||||
|
||||
mov eax, dword[usercommand+5] ; check for 'er ', we only checked 'serv'
|
||||
or eax, 0x00002020
|
||||
and eax, 0x00ffffff
|
||||
cmp eax, 'er '
|
||||
jne cmd_usr_send
|
||||
|
||||
mov ecx, [edit1.size] ; ok now set the address
|
||||
sub ecx, 8
|
||||
|
||||
mov esi, usercommand+8
|
||||
push esi
|
||||
mov edi, irc_server_name
|
||||
rep movsb
|
||||
xor al, al
|
||||
stosb
|
||||
pop esi
|
||||
|
||||
; set it also in window name
|
||||
mov ebx, [window_print]
|
||||
call window_set_name
|
||||
|
||||
; now connect
|
||||
call socket_connect
|
||||
|
||||
ret
|
||||
|
||||
|
||||
cmd_usr_quer:
|
||||
|
||||
mov ecx, MAX_WINDOWS
|
||||
mov ebx, windows
|
||||
.loop:
|
||||
cmp [ebx + window.data_ptr], 0
|
||||
je .found
|
||||
add ebx, sizeof.window
|
||||
dec ecx
|
||||
jnz .loop
|
||||
|
||||
; error: no available channels ! FIXME
|
||||
|
||||
ret
|
||||
|
||||
|
||||
.found:
|
||||
call window_create
|
||||
test eax, eax
|
||||
jz .error
|
||||
mov [ebx + window.data_ptr], eax
|
||||
|
||||
mov esi, usercommand+7
|
||||
call window_set_name
|
||||
|
||||
mov [ebx + window.type], WINDOWTYPE_CHAT
|
||||
mov [ebx + window.flags], 0
|
||||
|
||||
.error:
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
cmd_usr_help:
|
||||
|
||||
mov esi, str_help
|
||||
call print_text2
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
cmd_usr_code:
|
||||
|
||||
; TODO
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
cmd_usr_send:
|
||||
|
||||
mov esi, usercommand+1
|
||||
mov ecx, [edit1.size]
|
||||
inc ecx
|
||||
mov edi, packetbuf
|
||||
call recode
|
||||
|
||||
lea esi, [edi - packetbuf]
|
||||
mcall send, [socketnum], packetbuf, , 0
|
||||
|
||||
ret
|
||||
|
164
programs/network/ircc/users.inc
Normal file
164
programs/network/ircc/users.inc
Normal file
@ -0,0 +1,164 @@
|
||||
|
||||
|
||||
; esi is ptr to nick
|
||||
; ebx is ptr to window
|
||||
align 4
|
||||
user_add:
|
||||
|
||||
cmp [ebx + window.users], MAX_USERS
|
||||
jae fail
|
||||
|
||||
mov edi, [ebx + window.data_ptr]
|
||||
add edi, window_data.names
|
||||
mov ebp, [ebx + window.users]
|
||||
inc ebp ; CHECKME
|
||||
|
||||
push esi edi
|
||||
.restart:
|
||||
mov ecx, MAX_NICK_LEN
|
||||
.loop1:
|
||||
lodsb
|
||||
cmp al, '@'
|
||||
jne @f
|
||||
mov al, ' ' ; give @ highest priority
|
||||
@@:
|
||||
cmp al, 'A'
|
||||
jb @f
|
||||
cmp al, 'Z'
|
||||
ja @f
|
||||
add al, 'a' - 'A' ; convert to lowercase
|
||||
@@:
|
||||
dec ecx
|
||||
jz .got_it
|
||||
|
||||
.loop2:
|
||||
mov dl, [edi]
|
||||
cmp dl, 0
|
||||
je .got_it
|
||||
cmp dl, '@'
|
||||
jne @f
|
||||
mov dl, ' ' ; give @ highest priority
|
||||
@@:
|
||||
cmp dl, 'A'
|
||||
jb @f
|
||||
cmp dl, 'Z'
|
||||
ja @f
|
||||
add dl, 'a' - 'A' ; convert to lowercase
|
||||
@@:
|
||||
cmp al, dl
|
||||
jb .got_it
|
||||
je .check_next
|
||||
|
||||
pop edi esi
|
||||
add edi, MAX_NICK_LEN
|
||||
push esi edi
|
||||
|
||||
dec ebp
|
||||
jnz .restart
|
||||
|
||||
.check_next:
|
||||
inc edi
|
||||
jmp .loop1
|
||||
|
||||
.got_it:
|
||||
pop edi esi
|
||||
|
||||
; OK, insert it here..
|
||||
|
||||
; mov all trailing usernames by MAX_NICK_LEN bytes
|
||||
push esi edi
|
||||
mov esi, [ebx + window.data_ptr]
|
||||
add esi, window_data.names + MAX_NICK_LEN * (MAX_USERS - 1)
|
||||
|
||||
mov ecx, esi
|
||||
sub ecx, edi
|
||||
add ecx, MAX_NICK_LEN
|
||||
shr ecx, 2
|
||||
lea edi, [esi + MAX_NICK_LEN]
|
||||
std
|
||||
rep movsd
|
||||
cld
|
||||
pop edi esi
|
||||
|
||||
; Now insert our new username
|
||||
mov ecx, MAX_NICK_LEN-1
|
||||
.fill:
|
||||
lodsb
|
||||
cmp al, ' '
|
||||
je .done
|
||||
cmp al, '!'
|
||||
je .done
|
||||
stosb
|
||||
loop .fill
|
||||
.done:
|
||||
xor al, al
|
||||
stosb
|
||||
|
||||
inc [ebx + window.users]
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; esi is ptr to nick
|
||||
; ebx is ptr to window
|
||||
align 4
|
||||
user_remove:
|
||||
|
||||
call user_find
|
||||
jz fail
|
||||
|
||||
lea esi, [edi + MAX_NICK_LEN]
|
||||
mov ecx, [ebx + window.data_ptr]
|
||||
add ecx, window_data.names + MAX_NICK_LEN * MAX_USERS
|
||||
sub ecx, esi
|
||||
shr ecx, 2
|
||||
rep movsd
|
||||
|
||||
dec [ebx + window.users]
|
||||
xor eax, eax
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; IN:
|
||||
; esi is ptr to nick
|
||||
; ebx is ptr to window
|
||||
; OUT:
|
||||
; edi is ptr to nick in userlist
|
||||
align 4
|
||||
user_find:
|
||||
|
||||
mov eax, [ebx + window.users]
|
||||
test eax, eax
|
||||
jz fail
|
||||
mov edi, [ebx + window.data_ptr]
|
||||
add edi, window_data.names
|
||||
|
||||
.loop:
|
||||
push esi edi
|
||||
mov ecx, MAX_NICK_LEN
|
||||
repe cmpsb
|
||||
cmp byte[edi-1], 0
|
||||
je .got_it
|
||||
; TODO: check byte[esi] too!
|
||||
pop edi esi
|
||||
add edi, MAX_NICK_LEN
|
||||
dec eax
|
||||
jnz .loop
|
||||
jmp fail
|
||||
|
||||
.got_it:
|
||||
pop edi esi
|
||||
test edi, edi ; to clear zero flag
|
||||
|
||||
ret
|
||||
|
||||
|
||||
fail:
|
||||
|
||||
xor edi, edi
|
||||
ret
|
167
programs/network/ircc/window.inc
Normal file
167
programs/network/ircc/window.inc
Normal file
@ -0,0 +1,167 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
window_create:
|
||||
|
||||
; allocate the window data block
|
||||
mcall 68, 12, sizeof.window_data
|
||||
test eax, eax
|
||||
jz .fail
|
||||
|
||||
; fill it with all zeros
|
||||
push eax
|
||||
mov edi, eax
|
||||
mov ecx, (sizeof.window_data+3)/4
|
||||
xor eax, eax
|
||||
rep stosd
|
||||
pop eax
|
||||
|
||||
.fail:
|
||||
ret
|
||||
|
||||
|
||||
window_set_name: ; esi = ptr to name, ebx = window ptr
|
||||
|
||||
pusha
|
||||
|
||||
; Skip heading spaces
|
||||
.spaceloop:
|
||||
cmp byte[esi], ' '
|
||||
jne .done
|
||||
inc esi
|
||||
jmp .spaceloop
|
||||
.done:
|
||||
|
||||
; Now copy it
|
||||
lea edi, [ebx + window.name]
|
||||
mov ecx, MAX_WINDOWNAME_LEN
|
||||
.loop:
|
||||
lodsb
|
||||
cmp al, 0x21
|
||||
jbe .addzero
|
||||
stosb
|
||||
dec ecx
|
||||
jnz .loop
|
||||
.addzero:
|
||||
xor al, al
|
||||
stosb
|
||||
|
||||
call draw_windownames ; redraw it
|
||||
|
||||
popa
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
window_refresh:
|
||||
|
||||
; set the correct buffer pointers ; FIXME: what is it good for?
|
||||
mov eax, [textbox_width] ;
|
||||
imul eax, 11 ;
|
||||
mov [pos], eax ;
|
||||
|
||||
mov eax, [window_print]
|
||||
mov eax, [eax + window.data_ptr]
|
||||
add eax, window_data.text
|
||||
mov [text_start], eax
|
||||
|
||||
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
|
||||
ptr2:
|
||||
mov bl, [eax]
|
||||
|
||||
cmp bl, dl
|
||||
je ptr_ret
|
||||
cmp bl, 0
|
||||
je ptr_ret
|
||||
call print_character
|
||||
|
||||
inc eax
|
||||
jmp ptr2
|
||||
|
||||
ptr_ret:
|
||||
popa
|
||||
ret
|
||||
|
||||
|
||||
print_text2: ; esi = ptr to ASCIIZ string
|
||||
|
||||
pusha
|
||||
.loop:
|
||||
lodsb
|
||||
test al, al
|
||||
jz .done
|
||||
mov bl, al
|
||||
call print_character
|
||||
jmp .loop
|
||||
|
||||
.done:
|
||||
popa
|
||||
ret
|
||||
|
||||
|
||||
if TIMESTAMP
|
||||
print_timestamp:
|
||||
|
||||
pusha
|
||||
mcall 3 ; get system time
|
||||
|
||||
mov bl, '['
|
||||
call print_character
|
||||
mov ecx, TIMESTAMP
|
||||
.loop:
|
||||
mov bl, al
|
||||
shr bl, 4
|
||||
add bl, '0'
|
||||
call print_character
|
||||
|
||||
mov bl, al
|
||||
and bl, 0x0f
|
||||
add bl, '0'
|
||||
call print_character
|
||||
|
||||
dec ecx
|
||||
jz .done
|
||||
|
||||
mov bl, ':'
|
||||
call print_character
|
||||
shr eax, 8
|
||||
jmp .loop
|
||||
.done:
|
||||
mov bl, ']'
|
||||
call print_character
|
||||
mov bl, ' '
|
||||
call print_character
|
||||
|
||||
popa
|
||||
ret
|
||||
end if
|
113
programs/network/libio.inc
Normal file
113
programs/network/libio.inc
Normal file
@ -0,0 +1,113 @@
|
||||
;;================================================================================================;;
|
||||
;;//// libio.inc //// (c) mike.dld, 2007-2008 ////////////////////////////////////////////////////;;
|
||||
;;================================================================================================;;
|
||||
;; ;;
|
||||
;; This file is part of Common development libraries (Libs-Dev). ;;
|
||||
;; ;;
|
||||
;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
|
||||
;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
|
||||
;; of the License, or (at your option) any later version. ;;
|
||||
;; ;;
|
||||
;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
|
||||
;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
|
||||
;; Lesser General Public License for more details. ;;
|
||||
;; ;;
|
||||
;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
|
||||
;; If not, see <http://www.gnu.org/licenses/>. ;;
|
||||
;; ;;
|
||||
;;================================================================================================;;
|
||||
|
||||
|
||||
O_BINARY = 00000000b
|
||||
O_READ = 00000001b
|
||||
O_WRITE = 00000010b
|
||||
O_CREATE = 00000100b
|
||||
O_SHARE = 00001000b
|
||||
O_TEXT = 00010000b
|
||||
|
||||
SEEK_SET = 0
|
||||
SEEK_CUR = 1
|
||||
SEEK_END = 2
|
||||
|
||||
struct FileDateTime
|
||||
union
|
||||
time dd ?
|
||||
struct
|
||||
sec db ?
|
||||
min db ?
|
||||
hour db ?
|
||||
ends
|
||||
ends
|
||||
union
|
||||
date dd ?
|
||||
struct
|
||||
day db ?
|
||||
month db ?
|
||||
year dw ?
|
||||
ends
|
||||
ends
|
||||
ends
|
||||
|
||||
struct FileInfoBlock
|
||||
Function dd ?
|
||||
Position dd ?
|
||||
Flags dd ?
|
||||
Count dd ?
|
||||
Buffer dd ?
|
||||
db ?
|
||||
FileName dd ?
|
||||
ends
|
||||
|
||||
struct FileInfoHeader
|
||||
Version dd ?
|
||||
FilesRead dd ?
|
||||
FilesCount dd ?
|
||||
rd 5
|
||||
ends
|
||||
|
||||
struct FileInfoA
|
||||
Attributes dd ?
|
||||
Flags dd ?
|
||||
DateCreate FileDateTime
|
||||
DateAccess FileDateTime
|
||||
DateModify FileDateTime
|
||||
union
|
||||
FileSize dq ?
|
||||
struct
|
||||
FileSizeLow dd ?
|
||||
FileSizeHigh dd ?
|
||||
ends
|
||||
ends
|
||||
FileName rb 264
|
||||
ends
|
||||
|
||||
struct FileInfoW
|
||||
Attributes dd ?
|
||||
Flags dd ?
|
||||
DateCreate FileDateTime
|
||||
DateAccess FileDateTime
|
||||
DateModify FileDateTime
|
||||
union
|
||||
FileSize dq ?
|
||||
struct
|
||||
FileSizeLow dd ?
|
||||
FileSizeHigh dd ?
|
||||
ends
|
||||
ends
|
||||
FileName rw 264
|
||||
ends
|
||||
|
||||
virtual at 0
|
||||
FileInfo FileInfoA
|
||||
FileInfo fix FileInfoA
|
||||
sizeof.FileInfo fix sizeof.FileInfoA
|
||||
end virtual
|
||||
|
||||
FA_READONLY = 00000001b
|
||||
FA_HIDDEN = 00000010b
|
||||
FA_SYSTEM = 00000100b
|
||||
FA_LABEL = 00001000b
|
||||
FA_FOLDER = 00010000b
|
||||
FA_ARCHIVED = 00100000b
|
||||
FA_NORMAL = 01000000b
|
||||
FA_ANY = 01111111b
|
588
programs/network/macros.inc
Normal file
588
programs/network/macros.inc
Normal file
@ -0,0 +1,588 @@
|
||||
@^ fix macro comment {
|
||||
^@ fix }
|
||||
|
||||
; -------------------------
|
||||
macro library [lname,fname]
|
||||
{
|
||||
forward
|
||||
dd __#lname#_library_table__,__#lname#_library_name__
|
||||
common
|
||||
dd 0
|
||||
forward
|
||||
align 4
|
||||
__#lname#_library_name__ db fname,0
|
||||
}
|
||||
|
||||
macro import lname,[name,sname]
|
||||
{
|
||||
common
|
||||
align 4
|
||||
__#lname#_library_table__:
|
||||
forward
|
||||
if used name
|
||||
name dd __#name#_import_name__
|
||||
end if
|
||||
common
|
||||
dd 0
|
||||
forward
|
||||
if used name
|
||||
align 4
|
||||
__#name#_import_name__ db sname,0
|
||||
end if
|
||||
}
|
||||
|
||||
macro export [name,sname]
|
||||
{
|
||||
forward
|
||||
dd __#name#_export_name__,name
|
||||
common
|
||||
dd 0
|
||||
forward
|
||||
align 4
|
||||
__#name#_export_name__ db sname,0
|
||||
}
|
||||
; -------------------------
|
||||
|
||||
macro m2m dest,src {
|
||||
push src
|
||||
pop dest
|
||||
}
|
||||
|
||||
|
||||
macro iglobal {
|
||||
IGlobals equ IGlobals,
|
||||
macro __IGlobalBlock { }
|
||||
|
||||
macro uglobal {
|
||||
UGlobals equ UGlobals,
|
||||
macro __UGlobalBlock { }
|
||||
|
||||
endg fix } ; Use endg for ending iglobal and uglobal blocks.
|
||||
|
||||
|
||||
macro IncludeIGlobals{
|
||||
macro IGlobals dummy,[n] \{ __IGlobalBlock
|
||||
purge __IGlobalBlock \}
|
||||
match I, IGlobals \{ I \} }
|
||||
|
||||
macro IncludeUGlobals{
|
||||
macro UGlobals dummy,[n] \{
|
||||
\common
|
||||
\local begin, size
|
||||
begin = $
|
||||
virtual at $
|
||||
\forward
|
||||
__UGlobalBlock
|
||||
purge __UGlobalBlock
|
||||
\common
|
||||
size = $ - begin
|
||||
end virtual
|
||||
rb size
|
||||
\}
|
||||
match U, UGlobals \{ U \} }
|
||||
|
||||
uglobal
|
||||
endg
|
||||
|
||||
iglobal
|
||||
endg
|
||||
|
||||
|
||||
; new application structure
|
||||
macro meos_app_start
|
||||
{
|
||||
use32
|
||||
org 0x0
|
||||
|
||||
db 'MENUET01'
|
||||
dd 0x01
|
||||
dd __start
|
||||
dd __end
|
||||
dd __memory
|
||||
dd __stack
|
||||
|
||||
if used __params & ~defined __params
|
||||
dd __params
|
||||
else
|
||||
dd 0x0
|
||||
end if
|
||||
|
||||
dd 0x0
|
||||
}
|
||||
MEOS_APP_START fix meos_app_start
|
||||
|
||||
macro code
|
||||
{
|
||||
__start:
|
||||
}
|
||||
CODE fix code
|
||||
|
||||
macro data
|
||||
{
|
||||
__data:
|
||||
IncludeIGlobals
|
||||
}
|
||||
DATA fix data
|
||||
|
||||
macro udata
|
||||
{
|
||||
if used __params & ~defined __params
|
||||
__params:
|
||||
db 0
|
||||
__end:
|
||||
rb 255
|
||||
else
|
||||
__end:
|
||||
end if
|
||||
__udata:
|
||||
IncludeUGlobals
|
||||
}
|
||||
UDATA fix udata
|
||||
|
||||
macro meos_app_end
|
||||
{
|
||||
align 32
|
||||
rb 2048
|
||||
__stack:
|
||||
__memory:
|
||||
}
|
||||
MEOS_APP_END fix meos_app_end
|
||||
|
||||
|
||||
; macro for defining multiline text data
|
||||
struc mstr [sstring]
|
||||
{
|
||||
forward
|
||||
local ssize
|
||||
virtual at 0
|
||||
db sstring
|
||||
ssize = $
|
||||
end virtual
|
||||
dd ssize
|
||||
db sstring
|
||||
common
|
||||
dd -1
|
||||
}
|
||||
|
||||
; macro for defining multiline text data
|
||||
struc mls [sstring]
|
||||
{
|
||||
forward
|
||||
local ssize
|
||||
virtual at 0
|
||||
db sstring ; mod
|
||||
ssize = $
|
||||
end virtual
|
||||
db ssize
|
||||
db sstring
|
||||
common
|
||||
db -1 ; mod
|
||||
}
|
||||
|
||||
|
||||
|
||||
; strings
|
||||
macro sz name,[data] { ; from MFAR [mike.dld]
|
||||
common
|
||||
if used name
|
||||
name db data
|
||||
.size = $-name
|
||||
end if
|
||||
}
|
||||
|
||||
macro lsz name,[lng,data] { ; from MFAR [mike.dld]
|
||||
common
|
||||
if used name
|
||||
label name
|
||||
forward
|
||||
if lang eq lng
|
||||
db data
|
||||
end if
|
||||
common
|
||||
.size = $-name
|
||||
end if
|
||||
}
|
||||
|
||||
macro szc name,elsz,[data] { ; from MFAR [mike.dld]
|
||||
common
|
||||
local s,m
|
||||
m = 0
|
||||
if used name
|
||||
label name
|
||||
forward
|
||||
virtual at 0
|
||||
db data
|
||||
s = $
|
||||
end virtual
|
||||
d#elsz s
|
||||
if m < s
|
||||
m = s
|
||||
end if
|
||||
db data
|
||||
common
|
||||
.size = $-name
|
||||
.maxl = m
|
||||
end if
|
||||
}
|
||||
|
||||
macro lszc name,elsz,[lng,data] { ; from MFAR [mike.dld]
|
||||
common
|
||||
local s,m,c
|
||||
m = 0
|
||||
c = 0
|
||||
if used name
|
||||
label name
|
||||
forward
|
||||
if lang eq lng
|
||||
virtual at 0
|
||||
db data
|
||||
s = $
|
||||
end virtual
|
||||
d#elsz s
|
||||
if m < s
|
||||
m = s
|
||||
end if
|
||||
db data
|
||||
c = c+1
|
||||
end if
|
||||
common
|
||||
.size = $-name
|
||||
.maxl = m
|
||||
.count = c
|
||||
end if
|
||||
}
|
||||
|
||||
|
||||
; easy system call macro
|
||||
macro mpack dest, hsrc, lsrc
|
||||
{
|
||||
if (hsrc eqtype 0) & (lsrc eqtype 0)
|
||||
mov dest, (hsrc) shl 16 + lsrc
|
||||
else
|
||||
if (hsrc eqtype 0) & (~lsrc eqtype 0)
|
||||
mov dest, (hsrc) shl 16
|
||||
add dest, lsrc
|
||||
else
|
||||
mov dest, hsrc
|
||||
shl dest, 16
|
||||
add dest, lsrc
|
||||
end if
|
||||
end if
|
||||
}
|
||||
|
||||
macro __mov reg,a,b { ; mike.dld
|
||||
if (~a eq)&(~b eq)
|
||||
mpack reg,a,b
|
||||
else if (~a eq)&(b eq)
|
||||
mov reg,a
|
||||
end if
|
||||
}
|
||||
|
||||
|
||||
include 'config.inc'
|
||||
;__CPU_type equ p5
|
||||
SYSENTER_VAR equ 0
|
||||
|
||||
macro mcall a,b,c,d,e,f { ; mike.dld, updated by Ghost for Fast System Calls
|
||||
local ..ret_point
|
||||
__mov eax,a
|
||||
__mov ebx,b
|
||||
__mov ecx,c
|
||||
__mov edx,d
|
||||
__mov esi,e
|
||||
__mov edi,f
|
||||
|
||||
if __CPU_type eq p5
|
||||
int 0x40
|
||||
else
|
||||
if __CPU_type eq p6
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
push ..ret_point ; it may be 2 or 5 byte
|
||||
sysenter
|
||||
..ret_point:
|
||||
pop edx
|
||||
pop ecx
|
||||
|
||||
else
|
||||
if __CPU_type eq k6
|
||||
push ecx
|
||||
syscall
|
||||
pop ecx
|
||||
else
|
||||
display 'ERROR : unknown CPU type (set to p5)', 10, 13
|
||||
__CPU_type equ p5
|
||||
int 0x40
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
}
|
||||
|
||||
|
||||
; -------------------------
|
||||
macro header a,[b] {
|
||||
common
|
||||
use32
|
||||
org 0
|
||||
db 'MENUET',a
|
||||
forward
|
||||
if b eq
|
||||
dd 0
|
||||
else
|
||||
dd b
|
||||
end if }
|
||||
macro section name { align 16
|
||||
label name }
|
||||
macro func name {
|
||||
if ~used name
|
||||
display 'FUNC NOT USED: ',`name,13,10
|
||||
else
|
||||
align 4
|
||||
name:
|
||||
;diff16 `name,0,name
|
||||
;pushad
|
||||
;pushfd
|
||||
;dps `name
|
||||
;newline
|
||||
;mcall 5,1
|
||||
;popfd
|
||||
;popad
|
||||
}
|
||||
macro endf { end if }
|
||||
|
||||
macro diff16 title,l1,l2
|
||||
{
|
||||
local s,d
|
||||
s = l2-l1
|
||||
display title,': 0x'
|
||||
repeat 8
|
||||
d = '0' + s shr ((8-%) shl 2) and $0F
|
||||
if d > '9'
|
||||
d = d + 'A'-'9'-1
|
||||
end if
|
||||
display d
|
||||
end repeat
|
||||
display 13,10
|
||||
}
|
||||
|
||||
macro diff10 title,l1,l2
|
||||
{
|
||||
local s,d,z,m
|
||||
s = l2-l1
|
||||
z = 0
|
||||
m = 1000000000
|
||||
display title,': '
|
||||
repeat 10
|
||||
d = '0' + s / m
|
||||
s = s - (s/m)*m
|
||||
m = m / 10
|
||||
if d <> '0'
|
||||
z = 1
|
||||
end if
|
||||
if z <> 0
|
||||
display d
|
||||
end if
|
||||
end repeat
|
||||
display 13,10
|
||||
}
|
||||
|
||||
; optimize the code for size
|
||||
__regs fix <eax,ebx,ecx,edx,esi,edi,ebp,esp>
|
||||
|
||||
macro add arg1,arg2
|
||||
{
|
||||
if (arg2 eqtype 0)
|
||||
if (arg2) = 1
|
||||
inc arg1
|
||||
else
|
||||
add arg1,arg2
|
||||
end if
|
||||
else
|
||||
add arg1,arg2
|
||||
end if
|
||||
}
|
||||
|
||||
macro sub arg1,arg2
|
||||
{
|
||||
if (arg2 eqtype 0)
|
||||
if (arg2) = 1
|
||||
dec arg1
|
||||
else
|
||||
sub arg1,arg2
|
||||
end if
|
||||
else
|
||||
sub arg1,arg2
|
||||
end if
|
||||
}
|
||||
|
||||
macro mov arg1,arg2
|
||||
{
|
||||
if (arg1 in __regs) & ((arg2 eqtype 0) | (arg2 eqtype '0'))
|
||||
if (arg2) = 0
|
||||
xor arg1,arg1
|
||||
else if (arg2) = 1
|
||||
xor arg1,arg1
|
||||
inc arg1
|
||||
else if (arg2) = -1
|
||||
or arg1,-1
|
||||
else if (arg2) > -128 & (arg2) < 128
|
||||
push arg2
|
||||
pop arg1
|
||||
else
|
||||
mov arg1,arg2
|
||||
end if
|
||||
else
|
||||
mov arg1,arg2
|
||||
end if
|
||||
}
|
||||
|
||||
|
||||
macro RGB [a] {
|
||||
common
|
||||
match (r=,g=,b),a \{
|
||||
\dd ((r) shl 16) or ((g) shl 8) or (b)
|
||||
\}
|
||||
}
|
||||
|
||||
|
||||
struc POINT _t,_dx,_dy {
|
||||
.x _t _dx
|
||||
.y _t _dy
|
||||
}
|
||||
|
||||
; structure definition helper
|
||||
include 'struct.inc'
|
||||
|
||||
struct RECT
|
||||
left dd ?
|
||||
top dd ?
|
||||
right dd ?
|
||||
bottom dd ?
|
||||
ends
|
||||
|
||||
struct BOX
|
||||
left dd ?
|
||||
top dd ?
|
||||
width dd ?
|
||||
height dd ?
|
||||
ends
|
||||
|
||||
; structures used in MeOS
|
||||
struct process_information
|
||||
cpu_usage dd ? ; +0
|
||||
window_stack_position dw ? ; +4
|
||||
window_stack_value dw ? ; +6
|
||||
dw ? ; +8
|
||||
process_name rb 12 ; +10
|
||||
memory_start dd ? ; +22
|
||||
used_memory dd ? ; +26
|
||||
PID dd ? ; +30
|
||||
box BOX ; +34
|
||||
slot_state dw ? ; +50
|
||||
dw ? ; +52
|
||||
client_box BOX ; +54
|
||||
wnd_state db ? ; +70
|
||||
rb (1024-71)
|
||||
ends
|
||||
|
||||
struct system_colors
|
||||
frame dd ?
|
||||
grab dd ?
|
||||
grab_button dd ?
|
||||
grab_button_text dd ?
|
||||
grab_text dd ?
|
||||
work dd ?
|
||||
work_button dd ?
|
||||
work_button_text dd ?
|
||||
work_text dd ?
|
||||
work_graph dd ?
|
||||
ends
|
||||
|
||||
struct FILEDATE
|
||||
Second db ?
|
||||
Minute db ?
|
||||
Hour db ?
|
||||
db ?
|
||||
Day db ?
|
||||
Month db ?
|
||||
Year dw ?
|
||||
ends
|
||||
|
||||
struct FILEINFO
|
||||
Attributes dd ?
|
||||
IsUnicode db ?
|
||||
db 3 dup(?)
|
||||
DateCreate FILEDATE
|
||||
DateAccess FILEDATE
|
||||
DateModify FILEDATE
|
||||
Size dq ?
|
||||
ends
|
||||
|
||||
|
||||
if __CPU_type eq p5 ; CMOVcc isnt supported on the P5
|
||||
|
||||
cmove fix cmovz
|
||||
macro cmovz reg1, reg2 {
|
||||
|
||||
local .jumpaddr
|
||||
|
||||
jnz .jumpaddr
|
||||
mov reg1, reg2
|
||||
.jumpaddr:
|
||||
}
|
||||
|
||||
cmovne fix cmovnz
|
||||
macro cmovnz reg1, reg2 {
|
||||
|
||||
local .jumpaddr
|
||||
|
||||
jz .jumpaddr
|
||||
mov reg1, reg2
|
||||
.jumpaddr:
|
||||
}
|
||||
|
||||
macro cmovg reg1, reg2 {
|
||||
|
||||
local .jumpaddr
|
||||
|
||||
jle .jumpaddr
|
||||
mov reg1, reg2
|
||||
.jumpaddr:
|
||||
}
|
||||
|
||||
macro cmovl reg1, reg2 {
|
||||
|
||||
local .jumpaddr
|
||||
|
||||
jge .jumpaddr
|
||||
mov reg1, reg2
|
||||
.jumpaddr:
|
||||
}
|
||||
|
||||
end if
|
||||
|
||||
; constants
|
||||
|
||||
; events
|
||||
EV_IDLE = 0
|
||||
EV_TIMER = 0
|
||||
EV_REDRAW = 1
|
||||
EV_KEY = 2
|
||||
EV_BUTTON = 3
|
||||
EV_EXIT = 4
|
||||
EV_BACKGROUND = 5
|
||||
EV_MOUSE = 6
|
||||
EV_IPC = 7
|
||||
EV_STACK = 8
|
||||
|
||||
; event mask bits for function 40
|
||||
EVM_REDRAW = 1b
|
||||
EVM_KEY = 10b
|
||||
EVM_BUTTON = 100b
|
||||
EVM_EXIT = 1000b
|
||||
EVM_BACKGROUND = 10000b
|
||||
EVM_MOUSE = 100000b
|
||||
EVM_IPC = 1000000b
|
||||
EVM_STACK = 10000000b
|
||||
EVM_DEBUG = 100000000b
|
||||
EVM_STACK2 = 1000000000b
|
198
programs/network/netcfg/drivers.inc
Normal file
198
programs/network/netcfg/drivers.inc
Normal file
@ -0,0 +1,198 @@
|
||||
driverlist:
|
||||
db 'RTL8139',0
|
||||
dd 0x813910ec
|
||||
dd 0x813810ec
|
||||
dd 0x12111113
|
||||
dd 0x13601500
|
||||
dd 0x13604033
|
||||
dd 0x13001186
|
||||
dd 0x13401186
|
||||
dd 0xab0613d1
|
||||
dd 0xa1171259
|
||||
dd 0xa11e1259
|
||||
dd 0xab0614ea
|
||||
dd 0xab0714ea
|
||||
dd 0x123411db
|
||||
dd 0x91301432
|
||||
dd 0x101202ac
|
||||
dd 0x0106018a
|
||||
dd 0x1211126c
|
||||
dd 0x81391743
|
||||
dd 0x8139021b
|
||||
dd 0x0 ; end
|
||||
|
||||
db 'RTL8029',0
|
||||
dd 0x802910ec
|
||||
dd 0x0
|
||||
|
||||
db 'I8255X',0
|
||||
dd 0x12098086
|
||||
dd 0x10298086
|
||||
dd 0x12298086
|
||||
dd 0x10308086
|
||||
dd 0x24498086
|
||||
dd 0x0
|
||||
|
||||
db 'RTL8169',0
|
||||
dd 0x816810ec
|
||||
dd 0x816910ec
|
||||
dd 0x011616ec
|
||||
dd 0x43001186
|
||||
dd 0x813610ec
|
||||
dd 0x0
|
||||
|
||||
db '3C59X',0
|
||||
dd 0x590010b7
|
||||
dd 0x592010b7
|
||||
dd 0x597010b7
|
||||
dd 0x595010b7
|
||||
dd 0x595110b7
|
||||
dd 0x595210b7
|
||||
dd 0x900010b7
|
||||
dd 0x900110b7
|
||||
dd 0x900410b7
|
||||
dd 0x900510b7
|
||||
dd 0x900610b7
|
||||
dd 0x900A10b7
|
||||
dd 0x905010b7
|
||||
dd 0x905110b7
|
||||
dd 0x905510b7
|
||||
dd 0x905810b7
|
||||
dd 0x905A10b7
|
||||
dd 0x920010b7
|
||||
dd 0x980010b7
|
||||
dd 0x980510b7
|
||||
dd 0x764610b7
|
||||
dd 0x505510b7
|
||||
dd 0x605510b7
|
||||
dd 0x605610b7
|
||||
dd 0x5b5710b7
|
||||
dd 0x505710b7
|
||||
dd 0x515710b7
|
||||
dd 0x525710b7
|
||||
dd 0x656010b7
|
||||
dd 0x656210b7
|
||||
dd 0x656410b7
|
||||
dd 0x450010b7
|
||||
dd 0x0
|
||||
|
||||
db 'SIS900',0
|
||||
dd 0x09001039
|
||||
dd 0x70161039
|
||||
dd 0x0
|
||||
|
||||
db 'PCNET32',0
|
||||
dd 0x20001022
|
||||
dd 0x26251022
|
||||
dd 0x20011022
|
||||
dd 0x0
|
||||
|
||||
db 'FORCEDETH',0
|
||||
dd 0x006610de
|
||||
dd 0x01c310de
|
||||
dd 0x00D610de
|
||||
dd 0x008610de
|
||||
dd 0x008c10de
|
||||
dd 0x00e610de
|
||||
dd 0x00df10de
|
||||
dd 0x005610de
|
||||
dd 0x005710de
|
||||
dd 0x003710de
|
||||
dd 0x003810de
|
||||
dd 0x026810de
|
||||
dd 0x026910de
|
||||
dd 0x037210de
|
||||
dd 0x037310de
|
||||
dd 0x03e510de
|
||||
dd 0x03e610de
|
||||
dd 0x03ee10de
|
||||
dd 0x03ef10de
|
||||
dd 0x045010de
|
||||
dd 0x045110de
|
||||
dd 0x045210de
|
||||
dd 0x045310de
|
||||
dd 0x054c10de
|
||||
dd 0x054d10de
|
||||
dd 0x054e10de
|
||||
dd 0x054f10de
|
||||
dd 0x07dc10de
|
||||
dd 0x07dd10de
|
||||
dd 0x07de10de
|
||||
dd 0x07df10de
|
||||
dd 0x076010de
|
||||
dd 0x076110de
|
||||
dd 0x076210de
|
||||
dd 0x076310de
|
||||
dd 0x0ab010de
|
||||
dd 0x0ab110de
|
||||
dd 0x0ab210de
|
||||
dd 0x0ab310de
|
||||
dd 0x0d7d10de
|
||||
dd 0x0
|
||||
|
||||
db 'MTD80X',0
|
||||
dd 0x08031516
|
||||
dd 0x08001516
|
||||
dd 0x08911516
|
||||
dd 0x0
|
||||
|
||||
db 'dec21x4x',0
|
||||
dd 0x00091011
|
||||
dd 0x00191011
|
||||
dd 0x09851317
|
||||
dd 0x0
|
||||
|
||||
db 'R6040',0
|
||||
dd 0x604017F3
|
||||
dd 0x0
|
||||
|
||||
db 'i8254x',0
|
||||
dd 0x10008086 ; 82542 (Fiber)
|
||||
dd 0x10018086 ; 82543GC (Fiber)
|
||||
dd 0x10048086 ; 82543GC (Copper)
|
||||
dd 0x10088086 ; 82544EI (Copper)
|
||||
dd 0x10098086 ; 82544EI (Fiber)
|
||||
dd 0x100A8086 ; 82540EM
|
||||
dd 0x100C8086 ; 82544GC (Copper)
|
||||
dd 0x100D8086 ; 82544GC (LOM)
|
||||
dd 0x100E8086 ; 82540EM
|
||||
dd 0x100F8086 ; 82545EM (Copper)
|
||||
dd 0x10108086 ; 82546EB (Copper)
|
||||
dd 0x10118086 ; 82545EM (Fiber)
|
||||
dd 0x10128086 ; 82546EB (Fiber)
|
||||
dd 0x10138086 ; 82541EI
|
||||
dd 0x10148086 ; 82541ER
|
||||
dd 0x10158086 ; 82540EM (LOM)
|
||||
dd 0x10168086 ; 82540EP (Mobile)
|
||||
dd 0x10178086 ; 82540EP
|
||||
dd 0x10188086 ; 82541EI
|
||||
dd 0x10198086 ; 82547EI
|
||||
dd 0x101a8086 ; 82547EI (Mobile)
|
||||
dd 0x101d8086 ; 82546EB
|
||||
dd 0x101e8086 ; 82540EP (Mobile)
|
||||
dd 0x10268086 ; 82545GM
|
||||
dd 0x10278086 ; 82545GM
|
||||
dd 0x10288086 ; 82545GM
|
||||
dd 0x105b8086 ; 82546GB (Copper)
|
||||
dd 0x10758086 ; 82547GI
|
||||
dd 0x10768086 ; 82541GI
|
||||
dd 0x10778086 ; 82541GI
|
||||
dd 0x10788086 ; 82541ER
|
||||
dd 0x10798086 ; 82546GB
|
||||
dd 0x107a8086 ; 82546GB
|
||||
dd 0x107b8086 ; 82546GB
|
||||
dd 0x107c8086 ; 82541PI
|
||||
dd 0x10b58086 ; 82546GB (Copper)
|
||||
dd 0x11078086 ; 82544EI
|
||||
dd 0x11128086 ; 82544GC
|
||||
dd 0x0
|
||||
|
||||
db 'RHINE', 0 ; VIA Rhine
|
||||
dd 0x30431106
|
||||
dd 0x61001106
|
||||
dd 0x30651106
|
||||
dd 0x31061106
|
||||
dd 0x30531106
|
||||
dd 0x0
|
||||
|
||||
dd 0x0 ; driverlist end
|
548
programs/network/netcfg/netcfg.asm
Normal file
548
programs/network/netcfg/netcfg.asm
Normal file
@ -0,0 +1,548 @@
|
||||
;
|
||||
; Netcfg v1.02
|
||||
;
|
||||
; Application to load network drivers in KolibriOS
|
||||
;
|
||||
; By hidnplayr
|
||||
;
|
||||
|
||||
format binary as ""
|
||||
|
||||
use32
|
||||
org 0x0
|
||||
|
||||
db 'MENUET01' ; 8 byte id
|
||||
dd 0x01 ; header version
|
||||
dd START ; start of code
|
||||
dd IM_END ; size of image
|
||||
dd (I_END+0x100) ; memory for app
|
||||
dd (I_END+0x100) ; esp
|
||||
dd param, 0x0 ; I_Param , I_Icon
|
||||
|
||||
type_ethernet equ 1
|
||||
|
||||
include '../macros.inc'
|
||||
|
||||
START:
|
||||
; first, check boot parameters
|
||||
|
||||
cmp byte[param], 0
|
||||
je .noparams
|
||||
|
||||
mcall 40, 0
|
||||
|
||||
push .exit
|
||||
cmp byte[param], 'A' ; A for All
|
||||
je Get_PCI_Info
|
||||
|
||||
cmp byte[param], 'F' ; F for First
|
||||
je Get_PCI_Info
|
||||
|
||||
ret
|
||||
|
||||
.exit:
|
||||
mcall -1
|
||||
|
||||
.noparams:
|
||||
call draw_window
|
||||
|
||||
still:
|
||||
mcall 10 ; wait here for event
|
||||
dec eax ; redraw request ?
|
||||
jz red
|
||||
dec eax ; key in buffer ?
|
||||
jz key
|
||||
dec eax ; button in buffer ?
|
||||
jz button
|
||||
jmp still
|
||||
|
||||
red: ; redraw
|
||||
mcall 9, Proc_Info, -1 ; window redraw requested so get new window coordinates and size
|
||||
mov eax, [Proc_Info.box.left]; store the window coordinates into the Form Structure
|
||||
mov [Form + 2], ax ; x start position
|
||||
mov eax, [Proc_Info.box.top];
|
||||
mov [Form + 6], ax ; ystart position
|
||||
mov eax, [Proc_Info.box.width] ;
|
||||
mov [Form], ax ; window width
|
||||
mov eax, [Proc_Info.box.height] ;
|
||||
mov [Form + 4] ,ax ; window height
|
||||
call draw_window ; go redraw window now
|
||||
jmp still
|
||||
|
||||
key: ; key
|
||||
mcall 2 ; just read it and ignore
|
||||
jmp still
|
||||
button: ; button
|
||||
mcall 17 ; get id
|
||||
|
||||
cmp ah, 1 ; button id = 1 ?
|
||||
jne @f
|
||||
exit: mcall -1 ; close this program
|
||||
@@:
|
||||
cmp eax,0x0000ff00
|
||||
jg load_drv
|
||||
|
||||
cmp ah, 4
|
||||
je hook
|
||||
|
||||
cmp ah, 5
|
||||
je reset
|
||||
|
||||
cmp ah, 6
|
||||
je unload
|
||||
|
||||
jmp still
|
||||
|
||||
|
||||
load_drv:
|
||||
shr eax, 16
|
||||
mov word [selected], ax
|
||||
|
||||
mov bl , 6 ; get a dword
|
||||
mov bh , ah ; bus
|
||||
mov ch , al ; dev
|
||||
mov cl , 0 ; offset to device/vendor id
|
||||
mcall 62 ; get ID's
|
||||
|
||||
mov word [PCI_Vendor], ax
|
||||
shr eax, 16
|
||||
mov word [PCI_Device], ax
|
||||
call get_drv_ptr
|
||||
|
||||
mov ecx, eax
|
||||
mcall 68, 16
|
||||
|
||||
mov [IOCTL.handle], eax
|
||||
|
||||
call draw_window
|
||||
|
||||
cmp [IOCTL.handle], 0
|
||||
jne still
|
||||
|
||||
mcall 4, 20 shl 16 + 30, 1 shl 31 + 0x00ff0000 , load_error
|
||||
|
||||
jmp still
|
||||
|
||||
|
||||
hook:
|
||||
mov ax , [selected]
|
||||
test ax , ax
|
||||
jz still
|
||||
|
||||
mov [hardwareinfo.pci_dev], al
|
||||
mov [hardwareinfo.pci_bus], ah
|
||||
|
||||
mov [IOCTL.io_code], 1 ; SRV_HOOK
|
||||
mov [IOCTL.inp_size], 3
|
||||
mov [IOCTL.input], hardwareinfo
|
||||
mov [IOCTL.out_size], 0
|
||||
mov [IOCTL.output], 0
|
||||
|
||||
mcall 68, 17, IOCTL
|
||||
|
||||
mov byte[drivernumber], al
|
||||
|
||||
jmp still
|
||||
|
||||
reset:
|
||||
movzx ebx, byte[drivernumber]
|
||||
mcall 74,,2
|
||||
|
||||
jmp still
|
||||
|
||||
unload:
|
||||
movzx ebx, byte[drivernumber]
|
||||
mcall 74,,3
|
||||
|
||||
jmp still
|
||||
|
||||
draw_window:
|
||||
mcall 12, 1 ; start of draw
|
||||
mcall 0, dword [Form], dword [Form + 4], 0x13ffffff, 0x805080d0, title
|
||||
|
||||
call Get_PCI_Info ; get pci version and last bus, scan for and draw each pci device
|
||||
|
||||
cmp edx, 20 shl 16 + 110
|
||||
je .nonefound
|
||||
|
||||
mcall 4, 20 shl 16 + 100, 1 shl 31 + 0x00000000 , caption
|
||||
|
||||
cmp [selected], 0
|
||||
jz .done
|
||||
cmp [IOCTL.handle] ,0
|
||||
jz .done
|
||||
|
||||
mcall 8, 18 shl 16 + 100, 35 shl 16 + 18, 4, 0x00007f00
|
||||
mcall ,, 55 shl 16 + 18, 5, 0x0000007f
|
||||
mcall ,, 75 shl 16 + 18, 6, 0x007f0000
|
||||
|
||||
mcall 4, 33 shl 16 + 42, 1 shl 31 + 0x00ffffff , btn_start
|
||||
mcall , 33 shl 16 + 62, , btn_reset
|
||||
mcall , 36 shl 16 + 82, , btn_stop
|
||||
|
||||
jmp .done
|
||||
|
||||
.nonefound:
|
||||
mcall 4, 20 shl 16 + 30, 1 shl 31 + 0x00ff0000 , nonefound
|
||||
.done:
|
||||
mcall 12, 2 ; end of draw
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;------------------------------------------------------------------
|
||||
;* Gets the PCI Version and Last Bus
|
||||
Get_PCI_Info:
|
||||
mcall 62, 0
|
||||
mov word [PCI_Version], ax
|
||||
mcall 62, 1
|
||||
mov byte [PCI_LastBus], al
|
||||
;----------------------------------------------------------
|
||||
;* Get all devices on PCI Bus
|
||||
mov edx, 20 shl 16 + 110 ; set start write position
|
||||
cmp al , 0xff ; 0xFF means no pci bus found
|
||||
jne Pci_Exists ;
|
||||
ret ; if no bus then leave
|
||||
Pci_Exists:
|
||||
mov byte [V_Bus], 0 ; reset varibles
|
||||
mov byte [V_Dev], 0 ;
|
||||
Start_Enum:
|
||||
mov bl , 6 ; get a dword
|
||||
mov bh , byte [V_Bus] ; bus of pci device
|
||||
mov ch , byte [V_Dev] ; device number/function
|
||||
mov cl , 0 ; offset to device/vendor id
|
||||
mcall 62 ; get ID's
|
||||
|
||||
cmp ax, 0 ; Vendor ID should not be 0 or 0xFFFF
|
||||
je nextDev ; check next device if nothing exists here
|
||||
cmp ax, 0xffff ;
|
||||
je nextDev ;
|
||||
|
||||
mov word [PCI_Vendor], ax ; There is a device here, save the ID's
|
||||
shr eax, 16 ;
|
||||
mov word [PCI_Device], ax ;
|
||||
mov bl , 4 ; Read config byte
|
||||
mov bh , byte [V_Bus] ; Bus #
|
||||
mov ch , byte [V_Dev] ; Device # on bus
|
||||
mov cl , 0x08 ; Register to read (Get Revision)
|
||||
mcall 62 ; Read it
|
||||
mov byte [PCI_Rev], al ; Save it
|
||||
mov cl , 0x0b ; Register to read (Get class)
|
||||
mcall 62 ; Read it
|
||||
|
||||
mov byte [PCI_Class], al ; Save it
|
||||
mov cl , 0x0a ; Register to read (Get Subclass)
|
||||
mcall 62 ; Read it
|
||||
mov byte [PCI_SubClass], al ; Save it
|
||||
mov cl , 0x09 ; Register to read (Get Interface)
|
||||
mcall 62 ; Read it
|
||||
mov [PCI_Interface], al ; Save it
|
||||
mov cl , 0x3c ; Register to read (Get IRQ)
|
||||
@@: mcall 62 ; Read it
|
||||
mov [PCI_IRQ], al ; Save it
|
||||
|
||||
; cmp byte [PCI_Class], 0 ; device from before class codes
|
||||
; je @f
|
||||
|
||||
cmp byte [PCI_Class], 2 ; network controller
|
||||
jne nextDev
|
||||
; @@:
|
||||
|
||||
cmp byte[param], 0
|
||||
jne load_and_start
|
||||
|
||||
mov cl, 0x0e
|
||||
mcall 62
|
||||
|
||||
push eax
|
||||
call Print_New_Device ; print device info to screen
|
||||
pop eax
|
||||
test al, al
|
||||
js nextDev
|
||||
|
||||
nextdev2:
|
||||
test byte [V_Dev], 7
|
||||
jnz nextDev
|
||||
|
||||
or byte [V_Dev], 7
|
||||
|
||||
nextDev:
|
||||
inc [V_Dev] ; lower 3 bits are the function number
|
||||
|
||||
jnz Start_Enum ; jump until we reach zero
|
||||
mov byte [V_Dev], 0 ; reset device number
|
||||
inc byte [V_Bus] ; next bus
|
||||
mov al , byte [PCI_LastBus] ; get last bus
|
||||
cmp byte [V_Bus], al ; was it last bus
|
||||
jbe Start_Enum ; if not jump to keep searching
|
||||
ret
|
||||
|
||||
|
||||
|
||||
load_and_start:
|
||||
|
||||
call get_drv_ptr
|
||||
cmp eax, lbl_none
|
||||
je .next
|
||||
|
||||
mov ecx, eax
|
||||
mcall 68, 16
|
||||
test eax, eax
|
||||
jz .next
|
||||
mov [IOCTL.handle], eax
|
||||
|
||||
mov al, [V_Dev]
|
||||
mov [hardwareinfo.pci_dev], al
|
||||
mov al, [V_Bus]
|
||||
mov [hardwareinfo.pci_bus], al
|
||||
|
||||
mov [IOCTL.io_code], 1 ; SRV_HOOK
|
||||
mov [IOCTL.inp_size], 3
|
||||
mov [IOCTL.input], hardwareinfo
|
||||
mov [IOCTL.out_size], 0
|
||||
mov [IOCTL.output], 0
|
||||
|
||||
mcall 68, 17, IOCTL
|
||||
|
||||
.next:
|
||||
cmp byte[param], 'A'
|
||||
je nextdev2
|
||||
jmp exit
|
||||
|
||||
|
||||
|
||||
;------------------------------------------------------------------
|
||||
;* Print device info to screen
|
||||
Print_New_Device:
|
||||
|
||||
push edx ; Magic ! (to print a button...)
|
||||
|
||||
mov ebx, 18 shl 16
|
||||
mov bx , [Form]
|
||||
sub bx , 36
|
||||
|
||||
mov cx , dx
|
||||
dec cx
|
||||
shl ecx, 16
|
||||
add ecx, 9
|
||||
|
||||
movzx edx, byte [V_Bus]
|
||||
shl dx , 8
|
||||
mov dl , byte [V_Dev]
|
||||
|
||||
mov esi, 0x0000c0ff ; color: yellow if selected, blue otherwise
|
||||
cmp word [selected], dx
|
||||
jne @f
|
||||
mov esi, 0x00c0c000
|
||||
@@:
|
||||
|
||||
shl edx, 8
|
||||
or dl , 0xff
|
||||
|
||||
mcall 8
|
||||
pop edx
|
||||
|
||||
xor esi, esi ; Color of text
|
||||
movzx ecx, word [PCI_Vendor] ; number to be written
|
||||
mcall 47, 0x00040100 ; Write Vendor ID
|
||||
|
||||
add edx, (4*6+18) shl 16
|
||||
movzx ecx, word [PCI_Device] ; get Vendor ID
|
||||
mcall ; Draw Vendor ID to Window
|
||||
|
||||
add edx, (4*6+18) shl 16
|
||||
movzx ecx, byte [V_Bus] ; get bus number
|
||||
mcall ,0x00020100 ; draw bus number to screen
|
||||
|
||||
add edx, (2*6+18) shl 16
|
||||
movzx ecx, byte [V_Dev] ; get device number
|
||||
shr ecx, 3 ; device number is bits 3-7
|
||||
mcall ; Draw device Number To Window
|
||||
|
||||
add edx, (2*6+18) shl 16
|
||||
movzx ecx, byte [PCI_Rev] ; get revision number
|
||||
mcall ; Draw Revision to screen
|
||||
|
||||
add edx, (2*6+18) shl 16
|
||||
movzx ecx, [PCI_IRQ]
|
||||
cmp cl , 0x0f ; IRQ must be between 0 and 15
|
||||
ja @f
|
||||
mcall
|
||||
@@:
|
||||
;
|
||||
;Write Names
|
||||
movzx ebx, dx ; Set y position
|
||||
or ebx, 230 shl 16 ; set Xposition
|
||||
|
||||
;------------------------------------------------------------------
|
||||
; Prints the Vendor's Name based on Vendor ID
|
||||
;------------------------------------------------------------------
|
||||
mov edx, VendorsTab
|
||||
mov cx , word[PCI_Vendor]
|
||||
|
||||
.fn: mov ax , [edx]
|
||||
add edx, 6
|
||||
test ax , ax
|
||||
jz .find
|
||||
cmp ax , cx
|
||||
jne .fn
|
||||
.find: mov edx, [edx - 4]
|
||||
mcall 4,, 0x80000000 ; lets print the vendor Name
|
||||
|
||||
;------------------------------------------------------------------
|
||||
; Get description based on Class/Subclass
|
||||
;------------------------------------------------------------------
|
||||
mov eax, dword [PCI_Class]
|
||||
and eax, 0xffffff
|
||||
xor edx, edx
|
||||
xor esi, esi
|
||||
.fnc: inc esi
|
||||
mov ecx, [Classes + esi * 8 - 8]
|
||||
cmp cx , 0xffff
|
||||
je .endfc
|
||||
cmp cx , ax
|
||||
jne .fnc
|
||||
test ecx, 0xff000000
|
||||
jz @f
|
||||
mov edx, [Classes + esi * 8 - 4]
|
||||
jmp .fnc
|
||||
@@: cmp eax, ecx
|
||||
jne .fnc
|
||||
xor edx, edx
|
||||
.endfc: test edx, edx
|
||||
jnz @f
|
||||
mov edx, [Classes + esi * 8 - 4]
|
||||
@@:
|
||||
add ebx, 288 shl 16
|
||||
mcall 4,, 0x80000000,, 32 ; draw the text
|
||||
movzx edx, bx ; get y coordinate
|
||||
add edx, 0x0014000A ; add 10 to y coordinate and set x coordinate to 20
|
||||
|
||||
;------------------------------------------------------------------
|
||||
; Print Driver Name
|
||||
;------------------------------------------------------------------
|
||||
push edx
|
||||
add ebx, 120 shl 16
|
||||
push ebx
|
||||
|
||||
call get_drv_ptr
|
||||
mov edx, eax
|
||||
pop ebx
|
||||
mcall 4,,0x80000000 ; lets print the vendor Name
|
||||
pop edx
|
||||
ret
|
||||
|
||||
get_drv_ptr:
|
||||
mov eax, driverlist ; eax will be the pointer to latest driver title
|
||||
mov ebx, driverlist ; ebx is the current pointer
|
||||
mov ecx, dword[PCI_Vendor] ; the device/vendor id of we want to find
|
||||
|
||||
driverloop:
|
||||
inc ebx
|
||||
|
||||
cmp byte[ebx],0
|
||||
jne driverloop
|
||||
|
||||
inc ebx ; the device/vendor id list for the driver eax is pointing to starts here.
|
||||
|
||||
deviceloop:
|
||||
cmp dword[ebx],0
|
||||
je nextdriver
|
||||
|
||||
cmp dword[ebx],ecx
|
||||
je driverfound
|
||||
|
||||
add ebx,4
|
||||
jmp deviceloop
|
||||
|
||||
nextdriver:
|
||||
add ebx,4
|
||||
|
||||
cmp dword[ebx],0
|
||||
je nodriver
|
||||
|
||||
mov eax,ebx
|
||||
jmp driverloop
|
||||
|
||||
nodriver:
|
||||
mov eax, lbl_none ; lets print the vendor Name
|
||||
ret
|
||||
|
||||
driverfound:
|
||||
ret
|
||||
|
||||
include 'vendors.inc'
|
||||
include 'drivers.inc'
|
||||
|
||||
|
||||
;------------------------------------------------------------------
|
||||
; DATA AREA
|
||||
|
||||
|
||||
DATA
|
||||
|
||||
|
||||
Form: dw 800 ; window width (no more, special for 800x600)
|
||||
dw 100 ; window x start
|
||||
dw 220 ; window height
|
||||
dw 100 ; window y start
|
||||
|
||||
title db 'Network Driver Control Center', 0
|
||||
|
||||
caption db 'Vendor Device Bus Dev Rev IRQ Company Description DRIVER',0
|
||||
nonefound db 'No compatible devices were found!',0
|
||||
btn_start db 'Start device',0
|
||||
btn_reset db 'Reset device',0
|
||||
btn_stop db 'Stop device',0
|
||||
lbl_none db 'none',0
|
||||
load_error db 'Could not load driver!',0
|
||||
|
||||
hardwareinfo:
|
||||
.type db 1 ; pci
|
||||
.pci_bus db ?
|
||||
.pci_dev db ?
|
||||
|
||||
|
||||
IM_END:
|
||||
|
||||
;------------------------------------------------------------------
|
||||
; UNINITIALIZED DATA AREA
|
||||
|
||||
|
||||
IOCTL:
|
||||
.handle dd ?
|
||||
.io_code dd ?
|
||||
.input dd ?
|
||||
.inp_size dd ?
|
||||
.output dd ?
|
||||
.out_size dd ?
|
||||
|
||||
drivernumber db ?
|
||||
MAC dp ?
|
||||
|
||||
|
||||
type db ?
|
||||
selected dw ?
|
||||
V_Bus db ?
|
||||
V_Dev db ?
|
||||
PCI_Version dw ?
|
||||
PCI_LastBus db ?
|
||||
PCI_Vendor dw ?
|
||||
PCI_Device dw ?
|
||||
PCI_Bus db ?
|
||||
PCI_Dev db ?
|
||||
PCI_Rev db ?
|
||||
; don`t change order!!!
|
||||
PCI_Class db ?
|
||||
PCI_SubClass db ?
|
||||
PCI_Interface db ?
|
||||
PCI_IRQ db ?
|
||||
|
||||
Proc_Info process_information
|
||||
|
||||
param rb 1024
|
||||
|
||||
|
||||
I_END:
|
1072
programs/network/netcfg/vendors.inc
Normal file
1072
programs/network/netcfg/vendors.inc
Normal file
File diff suppressed because it is too large
Load Diff
614
programs/network/netstat/netstat.asm
Normal file
614
programs/network/netstat/netstat.asm
Normal file
@ -0,0 +1,614 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2010-2013. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; netstat.asm - Network Status Tool for KolibriOS ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr@kolibrios.org ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
format binary as ""
|
||||
|
||||
use32
|
||||
|
||||
org 0x0
|
||||
|
||||
db 'MENUET01' ; 8 byte id
|
||||
dd 0x01 ; header version
|
||||
dd START ; start of code
|
||||
dd I_END ; size of image
|
||||
dd (I_END+0x100) ; memory for app
|
||||
dd (I_END+0x100) ; esp
|
||||
dd I_PARAM , 0x0 ; I_Param , I_Icon
|
||||
|
||||
include '..\macros.inc'
|
||||
include '..\network.inc'
|
||||
|
||||
START:
|
||||
mcall 40, EVM_REDRAW + EVM_BUTTON + EVM_STACK2
|
||||
|
||||
redraw:
|
||||
mcall 12, 1
|
||||
mcall 0, 100 shl 16 + 600, 100 shl 16 + 240, 0x34bcbcbc, , name ; draw window
|
||||
|
||||
call draw_interfaces
|
||||
|
||||
mov edx, 101
|
||||
mov esi, 0x00aaaaff
|
||||
mov edi, 0x00aaffff
|
||||
|
||||
cmp dl, [mode]
|
||||
cmove esi, edi
|
||||
mcall 8, 25 shl 16 + 65, 25 shl 16 + 20
|
||||
|
||||
.morebuttons:
|
||||
inc edx
|
||||
add ebx, 75 shl 16
|
||||
mov esi, 0x00aaaaff
|
||||
|
||||
cmp dl, [mode]
|
||||
cmove esi, edi
|
||||
mcall
|
||||
|
||||
cmp edx, 105
|
||||
jle .morebuttons
|
||||
|
||||
mcall 4, 28 shl 16 + 31, 0x80000000, modes
|
||||
|
||||
cmp [mode], 101
|
||||
jne .no_eth
|
||||
|
||||
mcall 4, 20 shl 16 + 75, 0x80000000, str_packets_tx
|
||||
add ebx, 18
|
||||
mov edx, str_packets_rx
|
||||
mcall
|
||||
add ebx, 18
|
||||
mov edx, str_bytes_tx
|
||||
mcall
|
||||
add ebx, 18
|
||||
mov edx, str_bytes_rx
|
||||
mcall
|
||||
add ebx, 18
|
||||
mov edx, str_MAC
|
||||
mcall
|
||||
add ebx, 18
|
||||
mov edx, str_link
|
||||
mcall
|
||||
|
||||
mov ebx, API_ETH + 4
|
||||
mov bh, [device]
|
||||
mcall 76
|
||||
push eax
|
||||
push bx
|
||||
|
||||
mov edx, 135 shl 16 + 75 + 4*18
|
||||
call draw_mac
|
||||
jmp end_of_draw
|
||||
|
||||
.no_eth:
|
||||
|
||||
cmp [mode], 102
|
||||
jne .no_ip
|
||||
|
||||
mcall 4, 20 shl 16 + 75, 0x80000000, str_packets_tx
|
||||
add ebx, 18
|
||||
mov edx, str_packets_rx
|
||||
mcall
|
||||
add ebx, 18
|
||||
mov edx, str_ip
|
||||
mcall
|
||||
add ebx, 18
|
||||
mov edx, str_dns
|
||||
mcall
|
||||
add ebx, 18
|
||||
mov edx, str_subnet
|
||||
mcall
|
||||
add ebx, 18
|
||||
mov edx, str_gateway
|
||||
mcall
|
||||
|
||||
|
||||
mov ebx, API_IPv4 + 8
|
||||
mov bh, [device]
|
||||
mcall 76
|
||||
push eax
|
||||
|
||||
dec bl
|
||||
dec bl
|
||||
mcall 76
|
||||
push eax
|
||||
|
||||
dec bl
|
||||
dec bl
|
||||
mcall 76
|
||||
push eax
|
||||
|
||||
dec bl
|
||||
dec bl
|
||||
mcall 76
|
||||
push eax
|
||||
|
||||
mov edx, 135 shl 16 + 75 + 2*18
|
||||
call draw_ip
|
||||
|
||||
add edx, 18
|
||||
call draw_ip
|
||||
|
||||
add edx, 18
|
||||
call draw_ip
|
||||
|
||||
add edx, 18
|
||||
call draw_ip
|
||||
|
||||
jmp end_of_draw
|
||||
|
||||
.no_ip:
|
||||
|
||||
cmp [mode], 103
|
||||
jne .no_arp
|
||||
|
||||
mcall 4, 20 shl 16 + 75, 0x80000000, str_packets_tx
|
||||
add ebx, 18
|
||||
mov edx, str_packets_rx
|
||||
mcall
|
||||
add ebx, 18
|
||||
mov edx, str_arp
|
||||
mcall
|
||||
add ebx, 18
|
||||
mov edx, str_conflicts
|
||||
mcall
|
||||
|
||||
jmp end_of_draw
|
||||
|
||||
.no_arp:
|
||||
|
||||
mcall 4, 20 shl 16 + 75, 0x80000000, str_packets_tx
|
||||
|
||||
add ebx, 18
|
||||
mov edx, str_packets_rx
|
||||
mcall
|
||||
|
||||
cmp [mode], 106
|
||||
jne end_of_draw
|
||||
|
||||
add ebx, 18
|
||||
mov edx, str_missed
|
||||
mcall
|
||||
|
||||
add ebx, 18
|
||||
mov edx, str_dumped
|
||||
mcall
|
||||
|
||||
|
||||
|
||||
end_of_draw:
|
||||
mcall 12, 2
|
||||
|
||||
draw_stats:
|
||||
|
||||
cmp [mode], 101
|
||||
jne not_101
|
||||
|
||||
mov ebx, API_ETH
|
||||
mov bh, [device]
|
||||
@@:
|
||||
push ebx
|
||||
mcall 76
|
||||
pop ebx
|
||||
push eax
|
||||
inc bl
|
||||
cmp bl, 3
|
||||
jbe @r
|
||||
inc bl
|
||||
mcall 76
|
||||
push eax
|
||||
|
||||
mov ebx, 0x000a0000
|
||||
pop ecx
|
||||
mov edx, 135 shl 16 + 75 + 5*18
|
||||
mov esi, 0x40000000
|
||||
mov edi, 0x00bcbcbc
|
||||
mcall 47
|
||||
|
||||
sub edx, 18*2
|
||||
pop ecx
|
||||
mcall
|
||||
|
||||
sub edx, 18
|
||||
pop ecx
|
||||
mcall
|
||||
|
||||
sub edx, 18
|
||||
pop ecx
|
||||
mcall
|
||||
|
||||
sub edx, 18
|
||||
pop ecx
|
||||
mcall
|
||||
|
||||
jmp mainloop
|
||||
|
||||
|
||||
not_101:
|
||||
|
||||
cmp [mode], 102
|
||||
jne not_102
|
||||
|
||||
mov ebx, API_IPv4
|
||||
mov bh, [device]
|
||||
push ebx
|
||||
mcall 76
|
||||
pop ebx
|
||||
push eax
|
||||
|
||||
inc bl
|
||||
push ebx
|
||||
mcall 76
|
||||
pop ebx
|
||||
push eax
|
||||
|
||||
|
||||
mov ebx, 0x000a0000
|
||||
pop ecx
|
||||
mov edx, 135 shl 16 + 75 + 18
|
||||
mov esi, 0x40000000
|
||||
mov edi, 0x00bcbcbc
|
||||
mcall 47
|
||||
|
||||
sub edx, 18
|
||||
pop ecx
|
||||
mcall
|
||||
|
||||
jmp mainloop
|
||||
|
||||
|
||||
not_102:
|
||||
|
||||
cmp [mode], 103
|
||||
jne not_103
|
||||
|
||||
mov ebx, API_ARP
|
||||
mov bh, [device]
|
||||
push ebx
|
||||
mcall 76
|
||||
pop ebx
|
||||
push eax
|
||||
|
||||
inc bl
|
||||
push ebx
|
||||
mcall 76
|
||||
pop ebx
|
||||
push eax
|
||||
|
||||
inc bl
|
||||
push ebx
|
||||
mcall 76
|
||||
pop ebx
|
||||
push eax
|
||||
|
||||
mov bl, 7
|
||||
push ebx
|
||||
mcall 76
|
||||
pop ebx
|
||||
push eax
|
||||
|
||||
mov ebx, 0x000a0000
|
||||
pop ecx
|
||||
mov edx, 135 shl 16 + 75 + 3*18
|
||||
mov esi, 0x40000000
|
||||
mov edi, 0x00bcbcbc
|
||||
mcall 47
|
||||
|
||||
sub edx, 18
|
||||
pop ecx
|
||||
mcall
|
||||
|
||||
sub edx, 18
|
||||
pop ecx
|
||||
mcall
|
||||
|
||||
sub edx, 18
|
||||
pop ecx
|
||||
mcall
|
||||
|
||||
jmp mainloop
|
||||
|
||||
not_103:
|
||||
|
||||
cmp [mode], 104
|
||||
jne not_104
|
||||
|
||||
mov ebx, API_ICMP
|
||||
mov bh, [device]
|
||||
push ebx
|
||||
mcall 76
|
||||
pop ebx
|
||||
push eax
|
||||
|
||||
inc bl
|
||||
push ebx
|
||||
mcall 76
|
||||
pop ebx
|
||||
push eax
|
||||
|
||||
mov ebx, 0x000a0000
|
||||
pop ecx
|
||||
mov edx, 135 shl 16 + 75 + 18
|
||||
mov esi, 0x40000000
|
||||
mov edi, 0x00bcbcbc
|
||||
mcall 47
|
||||
|
||||
sub edx, 18
|
||||
pop ecx
|
||||
mcall
|
||||
|
||||
jmp mainloop
|
||||
|
||||
not_104:
|
||||
|
||||
cmp [mode], 105
|
||||
jne not_105
|
||||
|
||||
mov ebx, API_UDP
|
||||
mov bh, [device]
|
||||
push ebx
|
||||
mcall 76
|
||||
pop ebx
|
||||
push eax
|
||||
|
||||
inc bl
|
||||
push ebx
|
||||
mcall 76
|
||||
pop ebx
|
||||
push eax
|
||||
|
||||
mov ebx, 0x000a0000
|
||||
pop ecx
|
||||
mov edx, 135 shl 16 + 75 + 18
|
||||
mov esi, 0x40000000
|
||||
mov edi, 0x00bcbcbc
|
||||
mcall 47
|
||||
|
||||
sub edx, 18
|
||||
pop ecx
|
||||
mcall
|
||||
|
||||
jmp mainloop
|
||||
|
||||
not_105:
|
||||
|
||||
cmp [mode], 106
|
||||
jne not_106
|
||||
|
||||
mov ebx, API_TCP
|
||||
mov bh, [device]
|
||||
push ebx
|
||||
mcall 76
|
||||
pop ebx
|
||||
push eax
|
||||
|
||||
inc bl
|
||||
push ebx
|
||||
mcall 76
|
||||
pop ebx
|
||||
push eax
|
||||
|
||||
inc bl
|
||||
push ebx
|
||||
mcall 76
|
||||
pop ebx
|
||||
push eax
|
||||
|
||||
inc bl
|
||||
push ebx
|
||||
mcall 76
|
||||
pop ebx
|
||||
push eax
|
||||
|
||||
mov ebx, 0x000a0000
|
||||
pop ecx
|
||||
mov edx, 135 shl 16 + 75 + 18*3
|
||||
mov esi, 0x40000000
|
||||
mov edi, 0x00bcbcbc
|
||||
mcall 47
|
||||
|
||||
sub edx, 18
|
||||
pop ecx
|
||||
mcall
|
||||
|
||||
sub edx, 18
|
||||
pop ecx
|
||||
mcall
|
||||
|
||||
sub edx, 18
|
||||
pop ecx
|
||||
mcall
|
||||
|
||||
jmp mainloop
|
||||
|
||||
not_106:
|
||||
|
||||
mainloop:
|
||||
|
||||
mcall 23, 50 ; wait for event with timeout (0,5 s)
|
||||
|
||||
cmp eax, 1
|
||||
je redraw
|
||||
cmp eax, 3
|
||||
je button
|
||||
cmp eax, 11
|
||||
je redraw
|
||||
|
||||
jmp draw_stats
|
||||
|
||||
button: ; button
|
||||
mcall 17 ; get id
|
||||
cmp ah, 1
|
||||
je exit
|
||||
cmp ah, 0
|
||||
je .interface
|
||||
mov [mode], ah
|
||||
jmp redraw
|
||||
|
||||
.interface:
|
||||
shr eax, 16
|
||||
mov [device], al
|
||||
jmp redraw
|
||||
|
||||
exit:
|
||||
mcall -1
|
||||
|
||||
|
||||
|
||||
draw_mac:
|
||||
|
||||
mov eax, 47
|
||||
mov ebx, 0x00020100
|
||||
mov esi, 0x40000000
|
||||
mov edi, 0x00bcbcbc
|
||||
|
||||
mov cl, [esp+4]
|
||||
mcall
|
||||
|
||||
mov cl, [esp+4+1]
|
||||
add edx, 15 shl 16
|
||||
mcall
|
||||
|
||||
mov cl, [esp+4+2]
|
||||
add edx, 15 shl 16
|
||||
mcall
|
||||
|
||||
mov cl, [esp+4+3]
|
||||
add edx, 15 shl 16
|
||||
mcall
|
||||
|
||||
mov cl, [esp+4+4]
|
||||
add edx, 15 shl 16
|
||||
mcall
|
||||
|
||||
mov cl, [esp+4+5]
|
||||
add edx, 15 shl 16
|
||||
mcall
|
||||
|
||||
sub edx, 5*15 shl 16
|
||||
|
||||
ret 6
|
||||
|
||||
|
||||
draw_ip:
|
||||
|
||||
mov eax, 47
|
||||
mov ebx, 0x00030000
|
||||
mov esi, 0x40000000
|
||||
mov edi, 0x00bcbcbc
|
||||
|
||||
xor ecx, ecx
|
||||
|
||||
mov cl, [esp+4]
|
||||
mcall
|
||||
|
||||
mov cl, [esp+4+1]
|
||||
add edx, 30 shl 16
|
||||
mcall
|
||||
|
||||
mov cl, [esp+4+2]
|
||||
add edx, 30 shl 16
|
||||
mcall
|
||||
|
||||
mov cl, [esp+4+3]
|
||||
add edx, 30 shl 16
|
||||
mcall
|
||||
|
||||
sub edx, 3*30 shl 16
|
||||
ret 4
|
||||
|
||||
|
||||
draw_interfaces:
|
||||
|
||||
mov [.btnpos], 8 shl 16 + 20
|
||||
mov [.txtpos], 490 shl 16 + 15
|
||||
|
||||
mcall 74, -1 ; get number of active network devices
|
||||
mov ecx, eax
|
||||
|
||||
xor ebx, ebx ; get device type
|
||||
.loop:
|
||||
mcall 74
|
||||
cmp eax, 1 ; ethernet?
|
||||
je .hit
|
||||
inc bh
|
||||
jb .loop ; tried all 256?
|
||||
ret
|
||||
|
||||
|
||||
.hit:
|
||||
push ecx ebx
|
||||
movzx edx, bh
|
||||
shl edx, 8
|
||||
mov esi, 0x00aaaaff
|
||||
cmp bh, [device]
|
||||
cmove esi, 0x00aaffff
|
||||
mcall 8, 485 shl 16 + 100, [.btnpos]
|
||||
mov ebx, [esp]
|
||||
inc bl
|
||||
mov ecx, namebuf
|
||||
mov edx, namebuf
|
||||
mcall 74 ; get device name
|
||||
cmp eax, -1
|
||||
jne @f
|
||||
mov edx, str_unknown
|
||||
@@:
|
||||
mcall 4, [.txtpos], 0x80000000 ; print the name
|
||||
pop ebx ecx
|
||||
|
||||
inc bh
|
||||
|
||||
add [.btnpos], 25 shl 16
|
||||
add [.txtpos], 25
|
||||
|
||||
dec ecx
|
||||
jnz .loop
|
||||
|
||||
ret
|
||||
|
||||
.btnpos dd ?
|
||||
.txtpos dd ?
|
||||
|
||||
|
||||
|
||||
|
||||
; DATA AREA
|
||||
|
||||
name db 'Netstat', 0
|
||||
mode db 101
|
||||
device db 0
|
||||
modes db 'Ethernet IPv4 ARP ICMP UDP TCP', 0
|
||||
|
||||
str_packets_tx db 'Packets sent:', 0
|
||||
str_packets_rx db 'Packets received:', 0
|
||||
str_bytes_tx db 'Bytes sent:', 0
|
||||
str_bytes_rx db 'Bytes received:', 0
|
||||
str_MAC db 'MAC address:', 0
|
||||
str_ip db 'IP address:', 0
|
||||
str_dns db 'DNS address:', 0
|
||||
str_subnet db 'Subnet mask:', 0
|
||||
str_gateway db 'Standard gateway:', 0
|
||||
str_arp db 'ARP entrys:', 0
|
||||
str_conflicts db 'ARP conflicts:', 0
|
||||
str_unknown db 'unknown', 0
|
||||
str_missed db 'Packets missed:',0
|
||||
str_dumped db 'Packets dumped:',0
|
||||
str_link db 'Link state:',0
|
||||
|
||||
namebuf rb 64
|
||||
|
||||
I_PARAM rb 1024
|
||||
|
||||
I_END:
|
||||
|
||||
|
94
programs/network/network.inc
Normal file
94
programs/network/network.inc
Normal file
@ -0,0 +1,94 @@
|
||||
; Socket types
|
||||
SOCK_STREAM = 1
|
||||
SOCK_DGRAM = 2
|
||||
SOCK_RAW = 3
|
||||
|
||||
; Socket options
|
||||
SO_NONBLOCK = 1 shl 31
|
||||
|
||||
; IP protocols
|
||||
IPPROTO_IP = 0
|
||||
IPPROTO_ICMP = 1
|
||||
IPPROTO_TCP = 6
|
||||
IPPROTO_UDP = 17
|
||||
|
||||
; Address families
|
||||
AF_UNSPEC = 0
|
||||
AF_LOCAL = 1
|
||||
AF_INET4 = 2 ; IPv4
|
||||
AF_INET6 = 28 ; IPv6 (not supported yet)
|
||||
|
||||
PF_UNSPEC = AF_UNSPEC
|
||||
PF_LOCAL = AF_LOCAL
|
||||
PF_INET4 = AF_INET4
|
||||
PF_INET6 = AF_INET6
|
||||
|
||||
; Flags for addrinfo
|
||||
AI_PASSIVE = 1
|
||||
AI_CANONNAME = 2
|
||||
AI_NUMERICHOST = 4
|
||||
AI_NUMERICSERV = 8
|
||||
AI_ADDRCONFIG = 0x400
|
||||
|
||||
; internal definition
|
||||
AI_SUPPORTED = 0x40F
|
||||
|
||||
; for system function 76
|
||||
API_ETH = 0 shl 16
|
||||
API_IPv4 = 1 shl 16
|
||||
API_ICMP = 2 shl 16
|
||||
API_UDP = 3 shl 16
|
||||
API_TCP = 4 shl 16
|
||||
API_ARP = 5 shl 16
|
||||
API_PPPOE = 6 shl 16
|
||||
|
||||
struct sockaddr_in
|
||||
sin_family dw ? ; sa_family_t
|
||||
sin_port dw ? ; in_port_t
|
||||
sin_addr dd ? ; struct in_addr
|
||||
sin_zero rb 8 ; zero
|
||||
ends
|
||||
|
||||
struct addrinfo
|
||||
ai_flags dd ? ; bitmask of AI_*
|
||||
ai_family dd ? ; PF_*
|
||||
ai_socktype dd ? ; SOCK_*
|
||||
ai_protocol dd ? ; 0 or IPPROTO_*
|
||||
ai_addrlen dd ? ; length of ai_addr
|
||||
ai_canonname dd ? ; char*
|
||||
ai_addr dd ? ; struct sockaddr*
|
||||
ai_next dd ? ; struct addrinfo*
|
||||
ends
|
||||
|
||||
EAI_ADDRFAMILY = 1
|
||||
EAI_AGAIN = 2
|
||||
EAI_BADFLAGS = 3
|
||||
EAI_FAIL = 4
|
||||
EAI_FAMILY = 5
|
||||
EAI_MEMORY = 6
|
||||
EAI_NONAME = 8
|
||||
EAI_SERVICE = 9
|
||||
EAI_SOCKTYPE = 10
|
||||
EAI_BADHINTS = 12
|
||||
EAI_PROTOCOL = 13
|
||||
EAI_OVERFLOW = 14
|
||||
|
||||
socket fix 75, 0
|
||||
close fix 75, 1
|
||||
bind fix 75, 2
|
||||
listen fix 75, 3
|
||||
connect fix 75, 4
|
||||
accept fix 75, 5
|
||||
send fix 75, 6
|
||||
recv fix 75, 7
|
||||
setsockopt fix 75, 8
|
||||
getsockopt fix 75, 9
|
||||
socketpair fix 75, 10
|
||||
|
||||
|
||||
struct ARP_entry
|
||||
IP dd ?
|
||||
MAC dp ?
|
||||
status dw ?
|
||||
TTL dw ?
|
||||
ends
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user