Merge new network stack with trunk
git-svn-id: svn://kolibrios.org@3545 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
@@ -6,7 +6,8 @@
|
||||
#/RD/1/CROPFLAT "XS800 YS480" 1 # set limits of screen
|
||||
#/RD/1/COMMOUSE "" 1 # COM mice detector
|
||||
#/RD/1/DEVELOP/BOARD "" 1 # Load DEBUG board
|
||||
#/RD/1/refrscrn "" 1 # Refresh screen
|
||||
#/RD/1/refrscrn "" 1 # Refresh screen
|
||||
/RD/1/NETWORK/NETCFG A 1 #
|
||||
/RD/1/NETWORK/ZEROCONF "" 1 # Network configuration
|
||||
/RD/1/MEDIA/PALITRA "H 007DCEDF 003C427F" 1 #SET BG
|
||||
/RD/1/@PANEL "" 1 # Start panel
|
||||
|
||||
+149
-333
@@ -1,387 +1,203 @@
|
||||
What is implemented
|
||||
===================
|
||||
eax = 74 - Work directly with network interface
|
||||
ebx = -1 (Get number of active network devices)
|
||||
|
||||
The following features are present in the TCP/IP stack code:
|
||||
out:
|
||||
eax = number of active network devices
|
||||
|
||||
IP layer.
|
||||
ICMP.
|
||||
TCP layer.
|
||||
UDP layer.
|
||||
local loopback.
|
||||
Realtek 8029 PCI ethernet interface.
|
||||
Realtek 8139 PCI ethernet interface.
|
||||
Intel i8255x PCI ethernet interface.
|
||||
Dynamic ARP table.
|
||||
PPP dialer
|
||||
|
||||
And the following internet applcations are implemented
|
||||
bh = device number, for all following functions !
|
||||
|
||||
HTTP Server
|
||||
Telnet
|
||||
POP Client
|
||||
DNS Name resolver
|
||||
MP3 Server
|
||||
TFTP Client
|
||||
IRC Client
|
||||
|
||||
There are also a number of experimental applications for streaming music
|
||||
and performing interprocess communication via sockets. A Web broswer is in
|
||||
development
|
||||
bl = 0 (Get device type)
|
||||
|
||||
out:
|
||||
eax = device type number
|
||||
|
||||
What is not implemented
|
||||
=======================
|
||||
bl = 1 (Get device name)
|
||||
|
||||
The IP layer does not process header options.
|
||||
The IP layer does not support routing.
|
||||
Packet fragmentation is not supported.
|
||||
in:
|
||||
ecx = pointer to 64 byte buffer
|
||||
out:
|
||||
name is copied into the buffer
|
||||
eax = -1 on error
|
||||
|
||||
bl = 2 (Reset the device)
|
||||
|
||||
How to configure Kolibri for PPP
|
||||
===============================
|
||||
in
|
||||
none
|
||||
out
|
||||
eax = -1 on error
|
||||
|
||||
See ppp.txt
|
||||
bl = 3 (Stop device)
|
||||
|
||||
in
|
||||
none
|
||||
out
|
||||
eax = -1 on error
|
||||
|
||||
How to configure Kolibri for Ethernet
|
||||
====================================
|
||||
|
||||
First, you need to have a supported ethernet card fitted, or present
|
||||
on your motherboard. If you are uncertain what type of hardware you
|
||||
have, try to configue the stack. If you have supported hardware it
|
||||
will be found, and enabled.
|
||||
TO BE FIGURED OUT
|
||||
|
||||
Setting Up the ARP Table
|
||||
------------------------
|
||||
|
||||
Kolibri's ARP table is dynamically created and maintained; You can see what
|
||||
hosts Kolibri has communicated with by running the ARPSTAT application.
|
||||
eax = 75 - Work with Sockets
|
||||
|
||||
Enabling Ethernet
|
||||
-----------------
|
||||
These functions work like the ones found in UNIX (and windows)
|
||||
for more info, please read http://beej.us/guide/bgnet/
|
||||
|
||||
Boot Kolibri, then select STACKCFG from the NET menu.
|
||||
Press the 'Read' Button, then select 'Packet Driver'.
|
||||
Press 'Change' next to the IP address, and enter the IP address you want
|
||||
to use. Make sure it is on the same sub-net as the LAN to which you are
|
||||
connected.
|
||||
Press 'Apply' to action the changes.
|
||||
Close the program.
|
||||
bl = 0 (Open Socket)
|
||||
|
||||
in:
|
||||
ecx = domain
|
||||
edx = type
|
||||
esi = protocol
|
||||
out:
|
||||
eax = socket number, -1 on error
|
||||
|
||||
The stack is now running, which you can test by pinging Kolibri from a
|
||||
remote host.
|
||||
bl = 1 (Close Socket)
|
||||
|
||||
in:
|
||||
ecx = socket number
|
||||
out:
|
||||
eax = -1 on error
|
||||
|
||||
The simplest way to connect two PC's together is using a 'Null Modem'
|
||||
Ethernet cable. These simply cross certain wires over. They can be
|
||||
purchased from PC stores, but are simple to make. Details can be found
|
||||
on the web. Look on google for 'ethernet cross over cable' or similar.
|
||||
bl = 2 (Bind)
|
||||
|
||||
in:
|
||||
ecx = socket number
|
||||
edx = pointer to sockaddr structure
|
||||
esi = length of sockaddr structure
|
||||
out:
|
||||
eax = -1 on error
|
||||
|
||||
How to use TCP/IP locally, with no Network
|
||||
==========================================
|
||||
bl = 3 (Listen)
|
||||
|
||||
Kolibri supports a form of local loopback that means applications on the
|
||||
same PC can communicate with each other via sockets as though they
|
||||
were on separate hosts. To connect to an application on the same machine,
|
||||
specify the local IP address as the destination address. You do not even
|
||||
need to configure the stack for ethernet; local loopback will work without
|
||||
any network hardware. It's great for development and testing.
|
||||
in:
|
||||
ecx = socket number
|
||||
edx = backlog
|
||||
out:
|
||||
eax = -1 on error
|
||||
|
||||
bl = 4 (connect)
|
||||
|
||||
Application Programming Interface
|
||||
=================================
|
||||
in:
|
||||
ecx = socket number
|
||||
edx = pointer to sockaddr structure
|
||||
esi = length of sockaddr structure
|
||||
out:
|
||||
eax = -1 on error
|
||||
|
||||
The developer can access the stack through interrupt 0x40, function 53.
|
||||
The file TFTPC.ASM gives a good example of how to use the programming
|
||||
interface ( at least, for UDP), but as network communication is complex
|
||||
I'll give an overview.
|
||||
bl = 5 (accept)
|
||||
|
||||
in:
|
||||
ecx = socket number
|
||||
edx = pointer to sockaddr structure
|
||||
esi = length of sockaddr structure
|
||||
out:
|
||||
eax = socket number, -1 on error
|
||||
|
||||
Sockets
|
||||
=======
|
||||
bl = 6 (send)
|
||||
|
||||
Applications connect to each other and pass information between themselves
|
||||
through a mechanism called a 'socket'. Sockets are end-points for
|
||||
communication; You need one at each application to communicate.
|
||||
in:
|
||||
ecx = socket number
|
||||
edx = pointer to buffer
|
||||
esi = length of buffer
|
||||
edi = flags
|
||||
out:
|
||||
eax = -1 on error
|
||||
|
||||
Using sockets is a little like using files on an OS; You open them, read
|
||||
and write to them, then close them. The only thing that makes life slightly
|
||||
more complicated is that unlike with a file, you have something intelligent
|
||||
at the other end ( which for example may not want to close when you do! )
|
||||
bl = 7 (receive)
|
||||
|
||||
Lets deal with the terminology before we go any further.
|
||||
in:
|
||||
ecx = socket number
|
||||
edx = pointer to buffer
|
||||
esi = length of buffer
|
||||
edi = flags
|
||||
out:
|
||||
eax = number of bytes copied, -1 on error
|
||||
|
||||
socket A unique identifier used by the application for communication.
|
||||
local port A number that identifies this application on the local host.
|
||||
Ports are a way to allow multiple applications to communicate
|
||||
with other hosts without the data becoming mixed up. ( The
|
||||
technical term is 'multiplex' ). Port numbers are 16 bit.
|
||||
remote port A number that identifies the application on the remote host
|
||||
to which we are communicating with. To the remote host, this is
|
||||
it's 'local port'. Port numbers are 16 bit.
|
||||
IP Address A 32 bit number that identifies the remote host PC that we are
|
||||
communicating with.
|
||||
Passive Refers to the mode by which a socket is opened; When opening in
|
||||
passive mode, the local PC is awaiting an incoming connection.
|
||||
Active Refers to the mode by which a socket is opened; When opening in
|
||||
active mode, the local PC will attempt to connect to a remote
|
||||
PC.
|
||||
bl = 8 (set socket options)
|
||||
|
||||
When you connect to a socket on a remote PC, you need to specify more than
|
||||
just the IP address, otherwise the remote stack will not know to which
|
||||
application it should send your data. You must fully qualify the address,
|
||||
which means you specify the IP address and the port number. This would be
|
||||
written like this
|
||||
in:
|
||||
ecx = socket number
|
||||
edx = level
|
||||
esi = optionname
|
||||
edi = ptr to buffer
|
||||
|
||||
192.168.1.10:80 ; Connect to port 80 on the machine 192.168.1.10
|
||||
The buffer's first dword is the length of the buffer, minus the first dword offcourse
|
||||
|
||||
Port numbers are important. Some are 'well known' and provide access to
|
||||
common applications. For example port 80 is used by HTTP servers; That
|
||||
way I can connect to a webserver on a host without having to find out
|
||||
what port number the application is listening on.
|
||||
out:
|
||||
eax = -1 on error
|
||||
|
||||
This brings me to the way in which you open a socket; As I said earlier,
|
||||
there are two modes, Passive and Active. A webserver would open a passive
|
||||
socket, as it is waiting for incoming connection requests. A web browser
|
||||
would open an active socket because it is attempting to connect to a
|
||||
specified remote host.
|
||||
bl = 9 (get socket options
|
||||
|
||||
in:
|
||||
ecx = socket number
|
||||
edx = level
|
||||
esi = optionname
|
||||
edi = ptr to buffer
|
||||
|
||||
Access to programming interface
|
||||
===============================
|
||||
The developer accesses the stack functions through interrupt 0x40,
|
||||
function 53. Some functions may be accessed through function 52, but these
|
||||
are mainly for stack configuration.
|
||||
Here is a summary of the functions that you may use and the parameter
|
||||
definitions.
|
||||
The buffer's first dword is the length of the buffer, minus the first dword offcourse
|
||||
|
||||
out:
|
||||
eax = -1 on error, socket option otherwise
|
||||
|
||||
Get Local IP Address
|
||||
--------------------
|
||||
eax = 52
|
||||
ebx = 1
|
||||
TIP
|
||||
|
||||
IP address returned in eax ( in internet byte order )
|
||||
when you import 'network.inc' and 'macros.inc' into your source code, you can use the following syntax to work with sockets:
|
||||
|
||||
|
||||
Write to stack input queue
|
||||
--------------------------
|
||||
eax = 52
|
||||
ebx = 6
|
||||
edx = number of bytes to write
|
||||
esi = pointer to data ( in application space )
|
||||
for example, to open a socket
|
||||
|
||||
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
|
||||
This interface is for slow network drivers only ( PPP, SLIP )
|
||||
mcall socket, AF_INET, SOCK_DGRAM,0
|
||||
mov [socketnum], eax
|
||||
|
||||
then to connect to a server
|
||||
|
||||
Read data from network output queue
|
||||
-----------------------------------
|
||||
eax = 52
|
||||
ebx = 8
|
||||
esi = pointer to data ( in application space )
|
||||
mcall connect, [socketnum], sockaddr, 18
|
||||
|
||||
On return, eax holds number of bytes transferred.
|
||||
This interface is for slow network drivers only ( PPP, SLIP )
|
||||
|
||||
eax = 76 - Work with protocols
|
||||
|
||||
Open a UDP socket
|
||||
-----------------
|
||||
eax = 53
|
||||
ebx = 0
|
||||
ecx = local port
|
||||
edx = remote port
|
||||
esi = remote ip address ( in internet byte order )
|
||||
high half of ebx = protocol number (for all subfunctions!)
|
||||
bh = device number (for all subfunctions!)
|
||||
bl = subfunction number, depends on protocol type
|
||||
|
||||
The socket number allocated is returned in eax.
|
||||
A return value of 0xFFFFFFFF means no socket could be opened.
|
||||
For Ethernet protocol
|
||||
|
||||
0 - Read # Packets send
|
||||
1 - Read # Packets received
|
||||
2 - Read # Bytes send
|
||||
3 - Read # Bytes received
|
||||
4 - Read MAC
|
||||
5 - Write MAC
|
||||
6 - Read IN-QUEUE size
|
||||
7 - Read OUT-QUEUE size
|
||||
For IPv4 protocol
|
||||
|
||||
Open a TCP socket
|
||||
-----------------
|
||||
eax = 53
|
||||
ebx = 5
|
||||
ecx = local port
|
||||
edx = remote port
|
||||
esi = remote ip address ( in internet byte order )
|
||||
edi = mode : SOCKET_PASSIVE or SOCKET_ACTIVE ( defined in stack.inc )
|
||||
0 - Read # IP packets send
|
||||
1 - Read # IP packets received
|
||||
2 - Read IP
|
||||
3 - Write IP
|
||||
4 - Read DNS
|
||||
5 - Write DNS
|
||||
6 - Read subnet
|
||||
7 - Write subnet
|
||||
8 - Read gateway
|
||||
9 - Write gateway
|
||||
For ARP protocol
|
||||
|
||||
The socket number allocated is returned in eax.
|
||||
A return value of 0xFFFFFFFF means no socket could be opened.
|
||||
0 - Read # ARP packets send
|
||||
1 - Read # ARP packets received
|
||||
2 - Get # ARP entry's
|
||||
3 - Read ARP entry
|
||||
4 - Add static ARP entry
|
||||
5 - Remove ARP entry (-1 = remove all)
|
||||
For ICMP protocol
|
||||
|
||||
0 - Read # ICMP packets send
|
||||
1 - Read # ICMP packets received
|
||||
3 - enable/disable ICMP echo reply
|
||||
For UDP protocol
|
||||
|
||||
Close a socket (UDP Only )
|
||||
--------------------------
|
||||
eax = 53
|
||||
ebx = 1
|
||||
ecx = socket number
|
||||
0 - Read # UDP packets send
|
||||
1 - Read # UDP packets received
|
||||
For TCP protocol
|
||||
|
||||
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
|
||||
|
||||
|
||||
Close a socket (TCP Only )
|
||||
--------------------------
|
||||
eax = 53
|
||||
ebx = 8
|
||||
ecx = socket number
|
||||
|
||||
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
|
||||
|
||||
|
||||
Poll socket
|
||||
-----------
|
||||
eax = 53
|
||||
ebx = 2
|
||||
ecx = socket number
|
||||
|
||||
On return, eax holds the number of bytes in the receive buffer.
|
||||
|
||||
|
||||
Read socket data
|
||||
----------------
|
||||
eax = 53
|
||||
ebx = 3
|
||||
ecx = socket number
|
||||
|
||||
On return, eax holds the number of bytes remaining, bl holds a data byte.
|
||||
|
||||
|
||||
Write to socket ( UDP only )
|
||||
----------------------------
|
||||
eax = 53
|
||||
ebx = 4
|
||||
ecx = socket number
|
||||
edx = number of bytes to write
|
||||
esi = pointer to data ( in application space )
|
||||
|
||||
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
|
||||
|
||||
|
||||
Return socket status ( TCP only )
|
||||
---------------------------------
|
||||
eax = 53
|
||||
ebx = 6
|
||||
ecx = socket number
|
||||
|
||||
On return, eax holds the sockets TCP status.
|
||||
This function can be used to determine when a socket has actually connected
|
||||
to another socket - data cannot be written to a socket until the connection
|
||||
is established (TCB_ESTABLISHED). The states a socket can be in are defined
|
||||
in stack.inc as TCB_
|
||||
|
||||
|
||||
Write to socket ( TCP only )
|
||||
----------------------------
|
||||
eax = 53
|
||||
ebx = 7
|
||||
ecx = socket number
|
||||
edx = number of bytes to write
|
||||
esi = pointer to data ( in application space )
|
||||
|
||||
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
|
||||
|
||||
|
||||
Check port number
|
||||
-----------------
|
||||
eax = 53
|
||||
ebx = 9
|
||||
ecx = port number
|
||||
|
||||
This function is used to determine if a port number
|
||||
is in use by any sockets as a local port number. Local
|
||||
port numbers are normally unique.
|
||||
|
||||
On return, eax is 1 for port number not in use, 0 otherwise.
|
||||
|
||||
|
||||
Opening a TCP socket in Kolibri
|
||||
===============================
|
||||
|
||||
There are two ways to open a socket - Passive or Active.
|
||||
|
||||
In a Passive connection your application 'listens' for incoming
|
||||
requests from remote applications. Typically this will be done when
|
||||
you are implementing a server application that allows any other
|
||||
application to connect to it. You would specify a 'known' local
|
||||
port number, such as 80 for a web server. You would leave the
|
||||
remote IP and remote port number as 0, which indicates any
|
||||
remote application may connect.
|
||||
|
||||
Once the socket has been opened you would wait for an incoming
|
||||
connection before doing anything. This can be by either checking
|
||||
the socket status for TCB_ESTABLISHED, or waiting for data in the
|
||||
receive buffer.
|
||||
|
||||
In an Active connection, you are making a connection to a specified
|
||||
remote port. The remote IP and remote port parameters must be filled
|
||||
in with non-zero values ( otherwise, what are you connecting to? ).
|
||||
You also specify a unique local port number so the remote application
|
||||
can uniquely identify you - after all, there may be several applications
|
||||
on your machine connected to the same remote host. See below for finding
|
||||
a unique port number.
|
||||
|
||||
|
||||
How to find an unused local port number
|
||||
=======================================
|
||||
|
||||
Typically when you are creating an active connection to a remote
|
||||
socket you will want to choose a unique local port number. Local
|
||||
port numbers normally start from 1000; The following code may
|
||||
be used to obtain an unused port number prior to making the
|
||||
open socket call.
|
||||
|
||||
mov ecx, 1000 ; local port starting at 1000
|
||||
|
||||
getlp:
|
||||
inc ecx
|
||||
push ecx
|
||||
mov eax, 53
|
||||
mov ebx, 9
|
||||
int 0x40
|
||||
pop ecx
|
||||
cmp eax, 0 ; is this local port in use?
|
||||
jz getlp ; yes - so try next
|
||||
|
||||
; ecx contains a free local port number
|
||||
|
||||
|
||||
|
||||
Writing data to a socket
|
||||
========================
|
||||
|
||||
There are two functions available depending on whether the socket
|
||||
was opened for TCP or UDP protocol; The call parameters are the
|
||||
same however. When the socket is being opened for TCP, use the
|
||||
status function to poll for a connection - data cannot be written
|
||||
to a socket until another socket has connected to it, and the
|
||||
state of the socket is TCB_ESTABLISHED.
|
||||
|
||||
When you write data, the call results in a single IP packet being
|
||||
created and transmitted. Thus the user application is responsible for
|
||||
the size of transmitted packets. Keep the packet sizes under 768 bytes.
|
||||
If you are writing a terminal program like telnet, you may want to send
|
||||
a packet for each keystroke ( inefficient ) or use a timer to send data
|
||||
periodically ( say, every second ).
|
||||
|
||||
|
||||
Reading data from a socket
|
||||
==========================
|
||||
|
||||
There is one function to read data from a sockets receive buffer. This
|
||||
function retrieves one byte at a time. You can use the poll function to
|
||||
test the receive buffer for data.
|
||||
|
||||
|
||||
Closing a socket
|
||||
================
|
||||
|
||||
Simply call the appropriate function - there is one for TCP, and another
|
||||
for UDP. When closing a TCP socket, don't forget that the other end
|
||||
may continue to send data, so the socket may remain active for a
|
||||
few seconds after your call.
|
||||
|
||||
|
||||
If you have any questions or have suggestions for improving this
|
||||
document please contact me at mikeh@oceanfree.net.
|
||||
0 - Read # TCP packets send
|
||||
1 - Read # TCP packets received
|
||||
+11
-19
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+11
-19
@@ -133,27 +133,19 @@ HEX-।
|
||||
#15 **** NET ****
|
||||
Серверы > /@16
|
||||
Клиенты > /@17
|
||||
Конфигурация /rd/1/network/stackcfg
|
||||
Zero-Config /rd/1/network/zeroconf
|
||||
Статус сети /rd/1/network/ethstat
|
||||
Статус ARP /rd/1/network/arpstat
|
||||
Zero-Config /sys/network/zeroconf
|
||||
network Config /sys/network/netcfg
|
||||
Network status /sys/network/netstat
|
||||
ARP status /sys/network/arpcfg
|
||||
#16 **** SERVERS ****
|
||||
SMTPS /rd/1/network/smtps
|
||||
HTTPS /rd/1/network/https
|
||||
FTPS /rd/1/network/ftps
|
||||
FTP daemon /sys/network/ftpd
|
||||
#17 **** CLIENTS ****
|
||||
TFTP-клиент /rd/1/network/tftpc
|
||||
Интернет-шахматы /rd/1/network/chess
|
||||
Интернет загрузчик /rd/1/network/downloader
|
||||
Текстовый браузер /rd/1/htmlv
|
||||
NNTP-группы новостей /rd/1/network/nntpc
|
||||
TELNET /rd/1/network/telnet
|
||||
POP-почта /rd/1/network/popc
|
||||
IRC-клиент /rd/1/network/airc
|
||||
YAHOO IM (демо) /rd/1/network/ym
|
||||
JMail /rd/1/network/jmail
|
||||
VNC-клиент /rd/1/network/vncclient
|
||||
DNS resolver /rd/1/network/nslookup
|
||||
IRC client /sys/network/ircc
|
||||
TFTP client /sys/network/tftpc
|
||||
Ping /sys/network/ping
|
||||
Telnet client /sys/network/telnet
|
||||
Synergy client /sys/network/synergyc
|
||||
DNS lookup /sys/network/nslookup
|
||||
#18 **** OTHER ****
|
||||
Аналоговые часы /rd/1/demos/aclock
|
||||
Бинарные часы /rd/1/demos/bcdclk
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
[ipconfig]
|
||||
; type should be static or zeroconf
|
||||
; zeroconf means the service first tries to contact a DHCP server
|
||||
; If dhcp is not available, it switches to link-local
|
||||
type = zeroconf
|
||||
ip = 192.168.1.150
|
||||
gateway = 192.168.1.1
|
||||
dns = 192.168.1.1
|
||||
subnet = 255.255.255.0
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,424 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; Broadcom NetXtreme 57xx driver for KolibriOS ;;
|
||||
;; ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;; Broadcom's programmers's manual for the BCM57xx ;;
|
||||
;; http://www.broadcom.com/collateral/pg/57XX-PG105-R.pdf ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; TODO: make better use of the available descriptors
|
||||
|
||||
format MS COFF
|
||||
|
||||
API_VERSION = 0x01000100
|
||||
DRIVER_VERSION = 5
|
||||
|
||||
MAX_DEVICES = 16
|
||||
|
||||
DEBUG = 1
|
||||
__DEBUG__ = 1
|
||||
__DEBUG_LEVEL__ = 2
|
||||
|
||||
|
||||
include '../proc32.inc'
|
||||
include '../imports.inc'
|
||||
include '../fdo.inc'
|
||||
include '../netdrv.inc'
|
||||
|
||||
public START
|
||||
public service_proc
|
||||
public version
|
||||
|
||||
|
||||
virtual at ebx
|
||||
device:
|
||||
ETH_DEVICE
|
||||
|
||||
.mmio_addr dd ?
|
||||
.pci_bus dd ?
|
||||
.pci_dev dd ?
|
||||
.irq_line db ?
|
||||
|
||||
.cur_tx dd ?
|
||||
.last_tx dd ?
|
||||
|
||||
rb 0x100 - (($ - device) and 0xff)
|
||||
.rx_desc rd 256/8
|
||||
|
||||
rb 0x100 - (($ - device) and 0xff)
|
||||
.tx_desc rd 256/8
|
||||
|
||||
sizeof.device_struct = $ - device
|
||||
|
||||
end virtual
|
||||
|
||||
section '.flat' code readable align 16
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; proc START ;;
|
||||
;; ;;
|
||||
;; (standard driver proc) ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
align 4
|
||||
proc START stdcall, state:dword
|
||||
|
||||
cmp [state], 1
|
||||
jne .exit
|
||||
|
||||
.entry:
|
||||
|
||||
DEBUGF 2,"Loading %s driver\n", my_service
|
||||
stdcall RegService, my_service, service_proc
|
||||
ret
|
||||
|
||||
.fail:
|
||||
.exit:
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
endp
|
||||
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; proc SERVICE_PROC ;;
|
||||
;; ;;
|
||||
;; (standard driver proc) ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
align 4
|
||||
proc service_proc stdcall, ioctl:dword
|
||||
|
||||
mov edx, [ioctl]
|
||||
mov eax, [IOCTL.io_code]
|
||||
|
||||
;------------------------------------------------------
|
||||
|
||||
cmp eax, 0 ;SRV_GETVERSION
|
||||
jne @F
|
||||
|
||||
cmp [IOCTL.out_size], 4
|
||||
jb .fail
|
||||
mov eax, [IOCTL.output]
|
||||
mov [eax], dword API_VERSION
|
||||
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
;------------------------------------------------------
|
||||
@@:
|
||||
cmp eax, 1 ;SRV_HOOK
|
||||
jne .fail
|
||||
|
||||
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
|
||||
jb .fail
|
||||
|
||||
mov eax, [IOCTL.input]
|
||||
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
|
||||
jne .fail ; other types arent supported for this card yet
|
||||
|
||||
; check if the device is already listed
|
||||
|
||||
mov esi, device_list
|
||||
mov ecx, [devices]
|
||||
test ecx, ecx
|
||||
jz .firstdevice
|
||||
|
||||
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
|
||||
mov ax, [eax+1] ;
|
||||
.nextdevice:
|
||||
mov ebx, [esi]
|
||||
cmp al, byte [device.pci_bus]
|
||||
jne .next
|
||||
cmp ah, byte [device.pci_dev]
|
||||
je .find_devicenum ; Device is already loaded, let's find it's device number
|
||||
.next:
|
||||
add esi, 4
|
||||
loop .nextdevice
|
||||
|
||||
|
||||
; This device doesnt have its own eth_device structure yet, lets create one
|
||||
.firstdevice:
|
||||
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
|
||||
jae .fail
|
||||
|
||||
allocate_and_clear ebx, sizeof.device_struct, .fail ; Allocate the buffer for device structure
|
||||
|
||||
; Fill in the direct call addresses into the struct
|
||||
|
||||
mov [device.reset], reset
|
||||
mov [device.transmit], transmit
|
||||
mov [device.unload], unload
|
||||
mov [device.name], my_service
|
||||
|
||||
; save the pci bus and device numbers
|
||||
|
||||
mov eax, [IOCTL.input]
|
||||
movzx ecx, byte [eax+1]
|
||||
mov [device.pci_bus], ecx
|
||||
movzx ecx, byte [eax+2]
|
||||
mov [device.pci_dev], ecx
|
||||
|
||||
; Now, it's time to find the base mmio addres of the PCI device
|
||||
|
||||
PCI_find_mmio32
|
||||
|
||||
; Create virtual mapping of the physical memory
|
||||
|
||||
push 1Bh ; PG_SW+PG_NOCACHE
|
||||
push 10000h ; size of the map
|
||||
push eax
|
||||
call MapIoMem
|
||||
mov [device.mmio_addr], eax
|
||||
|
||||
; We've found the mmio address, find IRQ now
|
||||
|
||||
PCI_find_irq
|
||||
|
||||
DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
|
||||
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.mmio_addr]:8
|
||||
|
||||
; Ok, the eth_device structure is ready, let's probe the device
|
||||
call probe ; this function will output in eax
|
||||
test eax, eax
|
||||
jnz .err ; If an error occured, exit
|
||||
|
||||
mov eax, [devices] ; Add the device structure to our device list
|
||||
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
|
||||
inc [devices] ;
|
||||
|
||||
mov [device.type], NET_TYPE_ETH
|
||||
call NetRegDev
|
||||
|
||||
cmp eax, -1
|
||||
je .destroy
|
||||
|
||||
ret
|
||||
|
||||
; If the device was already loaded, find the device number and return it in eax
|
||||
|
||||
.find_devicenum:
|
||||
DEBUGF 1,"Trying to find device number of already registered device\n"
|
||||
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
|
||||
; into a device number in edi
|
||||
mov eax, edi ; Application wants it in eax instead
|
||||
DEBUGF 1,"Kernel says: %u\n", eax
|
||||
ret
|
||||
|
||||
; If an error occured, remove all allocated data and exit (returning -1 in eax)
|
||||
|
||||
.destroy:
|
||||
; todo: reset device into virgin state
|
||||
|
||||
.err:
|
||||
stdcall KernelFree, ebx
|
||||
|
||||
.fail:
|
||||
or eax, -1
|
||||
ret
|
||||
|
||||
;------------------------------------------------------
|
||||
endp
|
||||
|
||||
|
||||
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
|
||||
;; ;;
|
||||
;; Actual Hardware dependent code starts here ;;
|
||||
;; ;;
|
||||
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
|
||||
|
||||
|
||||
align 4
|
||||
unload:
|
||||
; TODO: (in this particular order)
|
||||
;
|
||||
; - Stop the device
|
||||
; - Detach int handler
|
||||
; - Remove device from local list (device_list)
|
||||
; - call unregister function in kernel
|
||||
; - Remove all allocated structures and buffers the card used
|
||||
|
||||
or eax, -1
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; probe: enables the device (if it really is I8254X)
|
||||
;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
align 4
|
||||
probe:
|
||||
|
||||
DEBUGF 1,"Probe\n"
|
||||
|
||||
PCI_make_bus_master
|
||||
|
||||
; TODO: validate the device
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
align 4
|
||||
reset:
|
||||
|
||||
DEBUGF 1,"Reset\n"
|
||||
|
||||
movzx eax, [device.irq_line]
|
||||
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
|
||||
stdcall AttachIntHandler, eax, int_handler, dword 0
|
||||
test eax, eax
|
||||
jnz @f
|
||||
DEBUGF 1,"\nCould not attach int handler!\n"
|
||||
; or eax, -1
|
||||
; ret
|
||||
@@:
|
||||
|
||||
call read_mac
|
||||
|
||||
; Set the mtu, kernel will be able to send now
|
||||
mov [device.mtu], 1514
|
||||
|
||||
; Set link state to unknown
|
||||
mov [device.state], ETH_LINK_UNKOWN
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
align 4
|
||||
read_mac:
|
||||
|
||||
DEBUGF 1,"Read MAC\n"
|
||||
|
||||
mov esi, [device.mmio_addr]
|
||||
lea edi, [device.mac]
|
||||
movsd
|
||||
movsw
|
||||
|
||||
.mac_ok:
|
||||
DEBUGF 1,"MAC = %x-%x-%x-%x-%x-%x\n",\
|
||||
[device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
|
||||
|
||||
ret
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Transmit ;;
|
||||
;; ;;
|
||||
;; In: buffer pointer in [esp+4] ;;
|
||||
;; size of buffer in [esp+8] ;;
|
||||
;; pointer to device structure in ebx ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
align 4
|
||||
transmit:
|
||||
DEBUGF 2,"\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
|
||||
mov eax, [esp+4]
|
||||
DEBUGF 2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
|
||||
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
|
||||
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
|
||||
[eax+13]:2,[eax+12]:2
|
||||
|
||||
cmp dword [esp + 8], 1514
|
||||
ja .fail
|
||||
cmp dword [esp + 8], 60
|
||||
jb .fail
|
||||
|
||||
|
||||
|
||||
|
||||
; Update stats
|
||||
inc [device.packets_tx]
|
||||
mov eax, [esp + 8]
|
||||
add dword [device.bytes_tx], eax
|
||||
adc dword [device.bytes_tx + 4], 0
|
||||
|
||||
ret 8
|
||||
|
||||
.fail:
|
||||
DEBUGF 1,"Send failed\n"
|
||||
ret 8
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Interrupt handler ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
align 4
|
||||
int_handler:
|
||||
|
||||
push ebx esi edi
|
||||
|
||||
DEBUGF 1,"\n%s int\n", my_service
|
||||
;-------------------------------------------
|
||||
; Find pointer of device wich made IRQ occur
|
||||
|
||||
mov ecx, [devices]
|
||||
test ecx, ecx
|
||||
jz .nothing
|
||||
mov esi, device_list
|
||||
.nextdevice:
|
||||
mov ebx, [esi]
|
||||
|
||||
; mov edi, [device.mmio_addr]
|
||||
; mov eax, [edi + REG_ICR]
|
||||
test eax, eax
|
||||
jnz .got_it
|
||||
.continue:
|
||||
add esi, 4
|
||||
dec ecx
|
||||
jnz .nextdevice
|
||||
.nothing:
|
||||
pop edi esi ebx
|
||||
xor eax, eax
|
||||
|
||||
ret
|
||||
|
||||
.got_it:
|
||||
|
||||
DEBUGF 1,"Device: %x Status: %x ", ebx, eax
|
||||
|
||||
pop edi esi ebx
|
||||
xor eax, eax
|
||||
inc eax
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
; End of code
|
||||
|
||||
section '.data' data readable writable align 16
|
||||
align 4
|
||||
|
||||
devices dd 0
|
||||
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
|
||||
my_service db 'BCM57XX',0 ; max 16 chars include zero
|
||||
|
||||
include_debug_strings ; All data wich FDO uses will be included here
|
||||
|
||||
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,818 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; i8254x driver for KolibriOS ;;
|
||||
;; ;;
|
||||
;; based on i8254x.asm from baremetal os ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr (hidnplayr@gmail.com) ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; TODO: make better use of the available descriptors
|
||||
|
||||
format MS COFF
|
||||
|
||||
API_VERSION = 0x01000100
|
||||
DRIVER_VERSION = 5
|
||||
|
||||
MAX_DEVICES = 16
|
||||
|
||||
DEBUG = 1
|
||||
__DEBUG__ = 1
|
||||
__DEBUG_LEVEL__ = 2
|
||||
|
||||
MAX_PKT_SIZE = 16384 ; Maximum packet size
|
||||
|
||||
|
||||
include '../proc32.inc'
|
||||
include '../imports.inc'
|
||||
include '../fdo.inc'
|
||||
include '../struct.inc'
|
||||
include '../netdrv.inc'
|
||||
|
||||
public START
|
||||
public service_proc
|
||||
public version
|
||||
|
||||
|
||||
|
||||
; Register list
|
||||
REG_CTRL = 0x0000 ; Control Register
|
||||
REG_STATUS = 0x0008 ; Device Status Register
|
||||
REG_CTRLEXT = 0x0018 ; Extended Control Register
|
||||
REG_MDIC = 0x0020 ; MDI Control Register
|
||||
REG_FCAL = 0x0028 ; Flow Control Address Low
|
||||
REG_FCAH = 0x002C ; Flow Control Address High
|
||||
REG_FCT = 0x0030 ; Flow Control Type
|
||||
REG_VET = 0x0038 ; VLAN Ether Type
|
||||
REG_ICR = 0x00C0 ; Interrupt Cause Read
|
||||
REG_ITR = 0x00C4 ; Interrupt Throttling Register
|
||||
REG_ICS = 0x00C8 ; Interrupt Cause Set Register
|
||||
REG_IMS = 0x00D0 ; Interrupt Mask Set/Read Register
|
||||
REG_IMC = 0x00D8 ; Interrupt Mask Clear Register
|
||||
REG_RCTL = 0x0100 ; Receive Control Register
|
||||
REG_FCTTV = 0x0170 ; Flow Control Transmit Timer Value
|
||||
REG_TXCW = 0x0178 ; Transmit Configuration Word
|
||||
REG_RXCW = 0x0180 ; Receive Configuration Word
|
||||
REG_TCTL = 0x0400 ; Transmit Control Register
|
||||
REG_TIPG = 0x0410 ; Transmit Inter Packet Gap
|
||||
|
||||
REG_LEDCTL = 0x0E00 ; LED Control
|
||||
REG_PBA = 0x1000 ; Packet Buffer Allocation
|
||||
|
||||
REG_RDBAL = 0x2800 ; RX Descriptor Base Address Low
|
||||
REG_RDBAH = 0x2804 ; RX Descriptor Base Address High
|
||||
REG_RDLEN = 0x2808 ; RX Descriptor Length
|
||||
REG_RDH = 0x2810 ; RX Descriptor Head
|
||||
REG_RDT = 0x2818 ; RX Descriptor Tail
|
||||
REG_RDTR = 0x2820 ; RX Delay Timer Register
|
||||
REG_RXDCTL = 0x3828 ; RX Descriptor Control
|
||||
REG_RADV = 0x282C ; RX Int. Absolute Delay Timer
|
||||
REG_RSRPD = 0x2C00 ; RX Small Packet Detect Interrupt
|
||||
|
||||
REG_TXDMAC = 0x3000 ; TX DMA Control
|
||||
REG_TDBAL = 0x3800 ; TX Descriptor Base Address Low
|
||||
REG_TDBAH = 0x3804 ; TX Descriptor Base Address High
|
||||
REG_TDLEN = 0x3808 ; TX Descriptor Length
|
||||
REG_TDH = 0x3810 ; TX Descriptor Head
|
||||
REG_TDT = 0x3818 ; TX Descriptor Tail
|
||||
REG_TIDV = 0x3820 ; TX Interrupt Delay Value
|
||||
REG_TXDCTL = 0x3828 ; TX Descriptor Control
|
||||
REG_TADV = 0x382C ; TX Absolute Interrupt Delay Value
|
||||
REG_TSPMT = 0x3830 ; TCP Segmentation Pad & Min Threshold
|
||||
|
||||
REG_RXCSUM = 0x5000 ; RX Checksum Control
|
||||
|
||||
; Register list for i8254x
|
||||
I82542_REG_RDTR = 0x0108 ; RX Delay Timer Register
|
||||
I82542_REG_RDBAL = 0x0110 ; RX Descriptor Base Address Low
|
||||
I82542_REG_RDBAH = 0x0114 ; RX Descriptor Base Address High
|
||||
I82542_REG_RDLEN = 0x0118 ; RX Descriptor Length
|
||||
I82542_REG_RDH = 0x0120 ; RDH for i82542
|
||||
I82542_REG_RDT = 0x0128 ; RDT for i82542
|
||||
I82542_REG_TDBAL = 0x0420 ; TX Descriptor Base Address Low
|
||||
I82542_REG_TDBAH = 0x0424 ; TX Descriptor Base Address Low
|
||||
I82542_REG_TDLEN = 0x0428 ; TX Descriptor Length
|
||||
I82542_REG_TDH = 0x0430 ; TDH for i82542
|
||||
I82542_REG_TDT = 0x0438 ; TDT for i82542
|
||||
|
||||
; CTRL - Control Register (0x0000)
|
||||
CTRL_FD = 0x00000001 ; Full Duplex
|
||||
CTRL_LRST = 0x00000008 ; Link Reset
|
||||
CTRL_ASDE = 0x00000020 ; Auto-speed detection
|
||||
CTRL_SLU = 0x00000040 ; Set Link Up
|
||||
CTRL_ILOS = 0x00000080 ; Invert Loss of Signal
|
||||
CTRL_SPEED_MASK = 0x00000300 ; Speed selection
|
||||
CTRL_SPEED_SHIFT = 8
|
||||
CTRL_FRCSPD = 0x00000800 ; Force Speed
|
||||
CTRL_FRCDPLX = 0x00001000 ; Force Duplex
|
||||
CTRL_SDP0_DATA = 0x00040000 ; SDP0 data
|
||||
CTRL_SDP1_DATA = 0x00080000 ; SDP1 data
|
||||
CTRL_SDP0_IODIR = 0x00400000 ; SDP0 direction
|
||||
CTRL_SDP1_IODIR = 0x00800000 ; SDP1 direction
|
||||
CTRL_RST = 0x04000000 ; Device Reset
|
||||
CTRL_RFCE = 0x08000000 ; RX Flow Ctrl Enable
|
||||
CTRL_TFCE = 0x10000000 ; TX Flow Ctrl Enable
|
||||
CTRL_VME = 0x40000000 ; VLAN Mode Enable
|
||||
CTRL_PHY_RST = 0x80000000 ; PHY reset
|
||||
|
||||
; STATUS - Device Status Register (0x0008)
|
||||
STATUS_FD = 0x00000001 ; Full Duplex
|
||||
STATUS_LU = 0x00000002 ; Link Up
|
||||
STATUS_TXOFF = 0x00000010 ; Transmit paused
|
||||
STATUS_TBIMODE = 0x00000020 ; TBI Mode
|
||||
STATUS_SPEED_MASK = 0x000000C0 ; Link Speed setting
|
||||
STATUS_SPEED_SHIFT = 6
|
||||
STATUS_ASDV_MASK = 0x00000300 ; Auto Speed Detection
|
||||
STATUS_ASDV_SHIFT = 8
|
||||
STATUS_PCI66 = 0x00000800 ; PCI bus speed
|
||||
STATUS_BUS64 = 0x00001000 ; PCI bus width
|
||||
STATUS_PCIX_MODE = 0x00002000 ; PCI-X mode
|
||||
STATUS_PCIXSPD_MASK = 0x0000C000 ; PCI-X speed
|
||||
STATUS_PCIXSPD_SHIFT = 14
|
||||
|
||||
; CTRL_EXT - Extended Device Control Register (0x0018)
|
||||
CTRLEXT_PHY_INT = 0x00000020 ; PHY interrupt
|
||||
CTRLEXT_SDP6_DATA = 0x00000040 ; SDP6 data
|
||||
CTRLEXT_SDP7_DATA = 0x00000080 ; SDP7 data
|
||||
CTRLEXT_SDP6_IODIR = 0x00000400 ; SDP6 direction
|
||||
CTRLEXT_SDP7_IODIR = 0x00000800 ; SDP7 direction
|
||||
CTRLEXT_ASDCHK = 0x00001000 ; Auto-Speed Detect Chk
|
||||
CTRLEXT_EE_RST = 0x00002000 ; EEPROM reset
|
||||
CTRLEXT_SPD_BYPS = 0x00008000 ; Speed Select Bypass
|
||||
CTRLEXT_RO_DIS = 0x00020000 ; Relaxed Ordering Dis.
|
||||
CTRLEXT_LNKMOD_MASK = 0x00C00000 ; Link Mode
|
||||
CTRLEXT_LNKMOD_SHIFT = 22
|
||||
|
||||
; MDIC - MDI Control Register (0x0020)
|
||||
MDIC_DATA_MASK = 0x0000FFFF ; Data
|
||||
MDIC_REG_MASK = 0x001F0000 ; PHY Register
|
||||
MDIC_REG_SHIFT = 16
|
||||
MDIC_PHY_MASK = 0x03E00000 ; PHY Address
|
||||
MDIC_PHY_SHIFT = 21
|
||||
MDIC_OP_MASK = 0x0C000000 ; Opcode
|
||||
MDIC_OP_SHIFT = 26
|
||||
MDIC_R = 0x10000000 ; Ready
|
||||
MDIC_I = 0x20000000 ; Interrupt Enable
|
||||
MDIC_E = 0x40000000 ; Error
|
||||
|
||||
; ICR - Interrupt Cause Read (0x00c0)
|
||||
ICR_TXDW = 0x00000001 ; TX Desc Written back
|
||||
ICR_TXQE = 0x00000002 ; TX Queue Empty
|
||||
ICR_LSC = 0x00000004 ; Link Status Change
|
||||
ICR_RXSEQ = 0x00000008 ; RX Sence Error
|
||||
ICR_RXDMT0 = 0x00000010 ; RX Desc min threshold reached
|
||||
ICR_RXO = 0x00000040 ; RX Overrun
|
||||
ICR_RXT0 = 0x00000080 ; RX Timer Interrupt
|
||||
ICR_MDAC = 0x00000200 ; MDIO Access Complete
|
||||
ICR_RXCFG = 0x00000400
|
||||
ICR_PHY_INT = 0x00001000 ; PHY Interrupt
|
||||
ICR_GPI_SDP6 = 0x00002000 ; GPI on SDP6
|
||||
ICR_GPI_SDP7 = 0x00004000 ; GPI on SDP7
|
||||
ICR_TXD_LOW = 0x00008000 ; TX Desc low threshold hit
|
||||
ICR_SRPD = 0x00010000 ; Small RX packet detected
|
||||
|
||||
; RCTL - Receive Control Register (0x0100)
|
||||
RCTL_EN = 0x00000002 ; Receiver Enable
|
||||
RCTL_SBP = 0x00000004 ; Store Bad Packets
|
||||
RCTL_UPE = 0x00000008 ; Unicast Promiscuous Enabled
|
||||
RCTL_MPE = 0x00000010 ; Xcast Promiscuous Enabled
|
||||
RCTL_LPE = 0x00000020 ; Long Packet Reception Enable
|
||||
RCTL_LBM_MASK = 0x000000C0 ; Loopback Mode
|
||||
RCTL_LBM_SHIFT = 6
|
||||
RCTL_RDMTS_MASK = 0x00000300 ; RX Desc Min Threshold Size
|
||||
RCTL_RDMTS_SHIFT = 8
|
||||
RCTL_MO_MASK = 0x00003000 ; Multicast Offset
|
||||
RCTL_MO_SHIFT = 12
|
||||
RCTL_BAM = 0x00008000 ; Broadcast Accept Mode
|
||||
RCTL_BSIZE_MASK = 0x00030000 ; RX Buffer Size
|
||||
RCTL_BSIZE_SHIFT = 16
|
||||
RCTL_VFE = 0x00040000 ; VLAN Filter Enable
|
||||
RCTL_CFIEN = 0x00080000 ; CFI Enable
|
||||
RCTL_CFI = 0x00100000 ; Canonical Form Indicator Bit
|
||||
RCTL_DPF = 0x00400000 ; Discard Pause Frames
|
||||
RCTL_PMCF = 0x00800000 ; Pass MAC Control Frames
|
||||
RCTL_BSEX = 0x02000000 ; Buffer Size Extension
|
||||
RCTL_SECRC = 0x04000000 ; Strip Ethernet CRC
|
||||
|
||||
; TCTL - Transmit Control Register (0x0400)
|
||||
TCTL_EN = 0x00000002 ; Transmit Enable
|
||||
TCTL_PSP = 0x00000008 ; Pad short packets
|
||||
TCTL_SWXOFF = 0x00400000 ; Software XOFF Transmission
|
||||
|
||||
; PBA - Packet Buffer Allocation (0x1000)
|
||||
PBA_RXA_MASK = 0x0000FFFF ; RX Packet Buffer
|
||||
PBA_RXA_SHIFT = 0
|
||||
PBA_TXA_MASK = 0xFFFF0000 ; TX Packet Buffer
|
||||
PBA_TXA_SHIFT = 16
|
||||
|
||||
; Flow Control Type
|
||||
FCT_TYPE_DEFAULT = 0x8808
|
||||
|
||||
; === TX Descriptor fields ===
|
||||
|
||||
; TX Packet Length (word 2)
|
||||
TXDESC_LEN_MASK = 0x0000ffff
|
||||
|
||||
; TX Descriptor CMD field (word 2)
|
||||
TXDESC_IDE = 0x80000000 ; Interrupt Delay Enable
|
||||
TXDESC_VLE = 0x40000000 ; VLAN Packet Enable
|
||||
TXDESC_DEXT = 0x20000000 ; Extension
|
||||
TXDESC_RPS = 0x10000000 ; Report Packet Sent
|
||||
TXDESC_RS = 0x08000000 ; Report Status
|
||||
TXDESC_IC = 0x04000000 ; Insert Checksum
|
||||
TXDESC_IFCS = 0x02000000 ; Insert FCS
|
||||
TXDESC_EOP = 0x01000000 ; End Of Packet
|
||||
|
||||
; TX Descriptor STA field (word 3)
|
||||
TXDESC_TU = 0x00000008 ; Transmit Underrun
|
||||
TXDESC_LC = 0x00000004 ; Late Collision
|
||||
TXDESC_EC = 0x00000002 ; Excess Collisions
|
||||
TXDESC_DD = 0x00000001 ; Descriptor Done
|
||||
|
||||
; === RX Descriptor fields ===
|
||||
|
||||
; RX Packet Length (word 2)
|
||||
RXDESC_LEN_MASK = 0x0000ffff
|
||||
|
||||
; RX Descriptor STA field (word 3)
|
||||
RXDESC_PIF = 0x00000080 ; Passed In-exact Filter
|
||||
RXDESC_IPCS = 0x00000040 ; IP cksum calculated
|
||||
RXDESC_TCPCS = 0x00000020 ; TCP cksum calculated
|
||||
RXDESC_VP = 0x00000008 ; Packet is 802.1Q
|
||||
RXDESC_IXSM = 0x00000004 ; Ignore cksum indication
|
||||
RXDESC_EOP = 0x00000002 ; End Of Packet
|
||||
RXDESC_DD = 0x00000001 ; Descriptor Done
|
||||
|
||||
|
||||
virtual at ebx
|
||||
device:
|
||||
ETH_DEVICE
|
||||
|
||||
.mmio_addr dd ?
|
||||
.pci_bus dd ?
|
||||
.pci_dev dd ?
|
||||
.irq_line db ?
|
||||
|
||||
.cur_tx dd ?
|
||||
.last_tx dd ?
|
||||
|
||||
rb 0x100 - (($ - device) and 0xff)
|
||||
.rx_desc rd 256/8
|
||||
|
||||
rb 0x100 - (($ - device) and 0xff)
|
||||
.tx_desc rd 256/8
|
||||
|
||||
sizeof.device_struct = $ - device
|
||||
|
||||
end virtual
|
||||
|
||||
section '.flat' code readable align 16
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; proc START ;;
|
||||
;; ;;
|
||||
;; (standard driver proc) ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
align 4
|
||||
proc START stdcall, state:dword
|
||||
|
||||
cmp [state], 1
|
||||
jne .exit
|
||||
|
||||
.entry:
|
||||
|
||||
DEBUGF 2,"Loading %s driver\n", my_service
|
||||
stdcall RegService, my_service, service_proc
|
||||
ret
|
||||
|
||||
.fail:
|
||||
.exit:
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
endp
|
||||
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; proc SERVICE_PROC ;;
|
||||
;; ;;
|
||||
;; (standard driver proc) ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
align 4
|
||||
proc service_proc stdcall, ioctl:dword
|
||||
|
||||
mov edx, [ioctl]
|
||||
mov eax, [IOCTL.io_code]
|
||||
|
||||
;------------------------------------------------------
|
||||
|
||||
cmp eax, 0 ;SRV_GETVERSION
|
||||
jne @F
|
||||
|
||||
cmp [IOCTL.out_size], 4
|
||||
jb .fail
|
||||
mov eax, [IOCTL.output]
|
||||
mov [eax], dword API_VERSION
|
||||
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
;------------------------------------------------------
|
||||
@@:
|
||||
cmp eax, 1 ;SRV_HOOK
|
||||
jne .fail
|
||||
|
||||
cmp [IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
|
||||
jb .fail
|
||||
|
||||
mov eax, [IOCTL.input]
|
||||
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
|
||||
jne .fail ; other types arent supported for this card yet
|
||||
|
||||
; check if the device is already listed
|
||||
|
||||
mov esi, device_list
|
||||
mov ecx, [devices]
|
||||
test ecx, ecx
|
||||
jz .firstdevice
|
||||
|
||||
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
|
||||
mov ax, [eax+1] ;
|
||||
.nextdevice:
|
||||
mov ebx, [esi]
|
||||
cmp al, byte [device.pci_bus]
|
||||
jne .next
|
||||
cmp ah, byte [device.pci_dev]
|
||||
je .find_devicenum ; Device is already loaded, let's find it's device number
|
||||
.next:
|
||||
add esi, 4
|
||||
loop .nextdevice
|
||||
|
||||
|
||||
; This device doesnt have its own eth_device structure yet, lets create one
|
||||
.firstdevice:
|
||||
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
|
||||
jae .fail
|
||||
|
||||
allocate_and_clear ebx, sizeof.device_struct, .fail ; Allocate the buffer for device structure
|
||||
|
||||
; Fill in the direct call addresses into the struct
|
||||
|
||||
mov [device.reset], reset
|
||||
mov [device.transmit], transmit
|
||||
mov [device.unload], unload
|
||||
mov [device.name], my_service
|
||||
|
||||
; save the pci bus and device numbers
|
||||
|
||||
mov eax, [IOCTL.input]
|
||||
movzx ecx, byte [eax+1]
|
||||
mov [device.pci_bus], ecx
|
||||
movzx ecx, byte [eax+2]
|
||||
mov [device.pci_dev], ecx
|
||||
|
||||
; Now, it's time to find the base mmio addres of the PCI device
|
||||
|
||||
PCI_find_mmio32
|
||||
|
||||
; Create virtual mapping of the physical memory
|
||||
|
||||
push 1Bh ; PG_SW+PG_NOCACHE
|
||||
push 10000h ; size of the map
|
||||
push eax
|
||||
call MapIoMem
|
||||
mov [device.mmio_addr], eax
|
||||
|
||||
; We've found the mmio address, find IRQ now
|
||||
|
||||
PCI_find_irq
|
||||
|
||||
DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
|
||||
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.mmio_addr]:8
|
||||
|
||||
; Ok, the eth_device structure is ready, let's probe the device
|
||||
call probe ; this function will output in eax
|
||||
test eax, eax
|
||||
jnz .err ; If an error occured, exit
|
||||
|
||||
mov eax, [devices] ; Add the device structure to our device list
|
||||
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
|
||||
inc [devices] ;
|
||||
|
||||
call start_i8254x
|
||||
|
||||
mov [device.type], NET_TYPE_ETH
|
||||
call NetRegDev
|
||||
|
||||
cmp eax, -1
|
||||
je .destroy
|
||||
|
||||
ret
|
||||
|
||||
; If the device was already loaded, find the device number and return it in eax
|
||||
|
||||
.find_devicenum:
|
||||
DEBUGF 1,"Trying to find device number of already registered device\n"
|
||||
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
|
||||
; into a device number in edi
|
||||
mov eax, edi ; Application wants it in eax instead
|
||||
DEBUGF 1,"Kernel says: %u\n", eax
|
||||
ret
|
||||
|
||||
; If an error occured, remove all allocated data and exit (returning -1 in eax)
|
||||
|
||||
.destroy:
|
||||
; todo: reset device into virgin state
|
||||
|
||||
.err:
|
||||
stdcall KernelFree, ebx
|
||||
|
||||
.fail:
|
||||
or eax, -1
|
||||
ret
|
||||
|
||||
;------------------------------------------------------
|
||||
endp
|
||||
|
||||
|
||||
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
|
||||
;; ;;
|
||||
;; Actual Hardware dependent code starts here ;;
|
||||
;; ;;
|
||||
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
|
||||
|
||||
|
||||
align 4
|
||||
unload:
|
||||
; TODO: (in this particular order)
|
||||
;
|
||||
; - Stop the device
|
||||
; - Detach int handler
|
||||
; - Remove device from local list (device_list)
|
||||
; - call unregister function in kernel
|
||||
; - Remove all allocated structures and buffers the card used
|
||||
|
||||
or eax, -1
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; probe: enables the device (if it really is I8254X)
|
||||
;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
align 4
|
||||
probe:
|
||||
|
||||
DEBUGF 1,"Probe\n"
|
||||
|
||||
PCI_make_bus_master
|
||||
|
||||
; TODO: validate the device
|
||||
|
||||
call read_mac
|
||||
|
||||
movzx eax, [device.irq_line]
|
||||
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
|
||||
stdcall AttachIntHandler, eax, int_handler, dword 0
|
||||
test eax, eax
|
||||
jnz @f
|
||||
DEBUGF 1,"\nCould not attach int handler!\n"
|
||||
; or eax, -1
|
||||
; ret
|
||||
@@:
|
||||
|
||||
|
||||
reset_dontstart:
|
||||
DEBUGF 1,"Reset\n"
|
||||
|
||||
mov esi, [device.mmio_addr]
|
||||
|
||||
or dword [esi + REG_CTRL], CTRL_RST ; reset device
|
||||
.loop:
|
||||
push esi
|
||||
xor esi, esi
|
||||
inc esi
|
||||
call Sleep
|
||||
pop esi
|
||||
test dword [esi + REG_CTRL], CTRL_RST
|
||||
jnz .loop
|
||||
|
||||
mov dword [esi + REG_IMC], 0xffffffff ; Disable all interrupt causes
|
||||
mov eax, dword [esi + REG_ICR] ; Clear any pending interrupts
|
||||
mov dword [esi + REG_ITR], 0 ; Disable interrupt throttling logic
|
||||
|
||||
mov dword [esi + REG_PBA], 0x00000030 ; PBA: set the RX buffer size to 48KB (TX buffer is calculated as 64-RX buffer)
|
||||
mov dword [esi + REG_RDTR], 0 ; RDTR: set no delay
|
||||
|
||||
mov dword [esi + REG_TXCW], 0x08008060 ; TXCW: set ANE, TxConfigWord (Half/Full duplex, Next Page Reqest)
|
||||
|
||||
mov eax, [esi + REG_CTRL]
|
||||
or eax, 1 shl 6 + 1 shl 5
|
||||
and eax, not (1 shl 3 + 1 shl 7 + 1 shl 30 + 1 shl 31)
|
||||
mov dword [esi + REG_CTRL], eax ; CTRL: clear LRST, set SLU and ASDE, clear RSTPHY, VME, and ILOS
|
||||
|
||||
lea edi, [esi + 0x5200] ; MTA: reset
|
||||
mov eax, 0xffffffff
|
||||
stosd
|
||||
stosd
|
||||
stosd
|
||||
stosd
|
||||
|
||||
stdcall KernelAlloc, 48*1024
|
||||
mov dword [device.rx_desc + 16], eax
|
||||
GetRealAddr
|
||||
mov dword [device.rx_desc], eax
|
||||
mov dword [device.rx_desc + 4], 0
|
||||
|
||||
lea eax, [device.rx_desc]
|
||||
GetRealAddr
|
||||
mov dword [esi + REG_RDBAL], eax ; Receive Descriptor Base Address Low
|
||||
mov dword [esi + REG_RDBAH], 0 ; Receive Descriptor Base Address High
|
||||
mov dword [esi + REG_RDLEN], (1 * 128) ; Receive Descriptor Length
|
||||
mov dword [esi + REG_RDH], 0 ; Receive Descriptor Head
|
||||
mov dword [esi + REG_RDT], 1 ; Receive Descriptor Tail
|
||||
mov dword [esi + REG_RCTL], RCTL_EN or RCTL_SBP or RCTL_BAM or RCTL_SECRC or RCTL_UPE or RCTL_MPE
|
||||
; Receiver Enable, Store Bad Packets, Broadcast Accept Mode, Strip Ethernet CRC from incoming packet, Promiscuous mode
|
||||
|
||||
mov dword [device.tx_desc], 0
|
||||
mov dword [device.tx_desc + 4], 0
|
||||
mov dword [device.tx_desc + 16], 0
|
||||
|
||||
lea eax, [device.tx_desc]
|
||||
GetRealAddr
|
||||
mov dword [esi + REG_TDBAL], eax ; Transmit Descriptor Base Address Low
|
||||
mov dword [esi + REG_TDBAH], 0 ; Transmit Descriptor Base Address High
|
||||
mov dword [esi + REG_TDLEN], (1 * 128) ; Transmit Descriptor Length
|
||||
mov dword [esi + REG_TDH], 0 ; Transmit Descriptor Head
|
||||
mov dword [esi + REG_TDT], 0 ; Transmit Descriptor Tail
|
||||
mov dword [esi + REG_TCTL], 0x010400fa ; Enabled, Pad Short Packets, 15 retrys, 64-byte COLD, Re-transmit on Late Collision
|
||||
mov dword [esi + REG_TIPG], 0x0060200A ; IPGT 10, IPGR1 8, IPGR2 6
|
||||
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
align 4
|
||||
reset:
|
||||
call reset_dontstart
|
||||
|
||||
start_i8254x:
|
||||
|
||||
xor eax, eax
|
||||
mov [esi + REG_RDTR], eax ; Clear the Receive Delay Timer Register
|
||||
mov [esi + REG_RADV], eax ; Clear the Receive Interrupt Absolute Delay Timer
|
||||
mov [esi + REG_RSRPD], eax ; Clear the Receive Small Packet Detect Interrupt
|
||||
; or eax, 1 shl 0 + 1 shl 7 ; TXDW + RXT0
|
||||
mov eax, 1+4+16 ;;;; hack!
|
||||
mov [esi + REG_IMS], eax ; Enable interrupt types
|
||||
|
||||
mov [device.mtu], 1514
|
||||
|
||||
; Set link state to unknown
|
||||
mov [device.state], ETH_LINK_UNKOWN
|
||||
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
align 4
|
||||
read_mac:
|
||||
|
||||
DEBUGF 1,"Read MAC\n"
|
||||
|
||||
mov esi, [device.mmio_addr]
|
||||
|
||||
mov eax, [esi+0x5400] ; RAL
|
||||
test eax, eax
|
||||
jz .try_eeprom
|
||||
|
||||
mov dword [device.mac], eax
|
||||
mov eax, [esi+0x5404] ; RAH
|
||||
mov word [device.mac+4], ax
|
||||
|
||||
jmp .mac_ok
|
||||
|
||||
.try_eeprom:
|
||||
mov dword [esi+0x14], 0x00000001
|
||||
mov eax, [esi+0x14]
|
||||
shr eax, 16
|
||||
mov word [device.mac], ax
|
||||
|
||||
mov dword [esi+0x14], 0x00000101
|
||||
mov eax, [esi+0x14]
|
||||
shr eax, 16
|
||||
mov word [device.mac+2], ax
|
||||
|
||||
mov dword [esi+0x14], 0x00000201
|
||||
mov eax, [esi+0x14]
|
||||
shr eax, 16
|
||||
mov word [device.mac+4], ax
|
||||
|
||||
.mac_ok:
|
||||
DEBUGF 1,"MAC = %x-%x-%x-%x-%x-%x\n",\
|
||||
[device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
|
||||
|
||||
ret
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Transmit ;;
|
||||
;; ;;
|
||||
;; In: buffer pointer in [esp+4] ;;
|
||||
;; size of buffer in [esp+8] ;;
|
||||
;; pointer to device structure in ebx ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
align 4
|
||||
transmit:
|
||||
DEBUGF 2,"\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
|
||||
mov eax, [esp+4]
|
||||
DEBUGF 2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
|
||||
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
|
||||
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
|
||||
[eax+13]:2,[eax+12]:2
|
||||
|
||||
cmp dword [esp + 8], 1514
|
||||
ja .fail
|
||||
cmp dword [esp + 8], 60
|
||||
jb .fail
|
||||
|
||||
|
||||
; Program the descriptor (use legacy mode)
|
||||
lea edi, [device.tx_desc] ; Transmit Descriptor Base Address
|
||||
mov dword [edi + 16], eax ; Store the data location (for driver)
|
||||
GetRealAddr ;
|
||||
mov dword [edi], eax ; Real addr (for i8254x)
|
||||
mov dword [edi + 4], 0x00000000 ;
|
||||
|
||||
mov ecx, [esp + 8]
|
||||
or ecx, 1 shl 24 + 1 shl 25 + 1 shl 27 ; EOP + IFCS + RS
|
||||
mov dword [edi + 8], ecx ; Packet size
|
||||
mov dword [edi + 12], 0x00000000
|
||||
|
||||
; Tell i8254x wich descriptor(s) we programmed
|
||||
mov edi, [device.mmio_addr]
|
||||
mov dword [edi + REG_TDH], 0 ; TDH - Transmit Descriptor Head
|
||||
mov dword [edi + REG_TDT], 1 ; TDT - Transmit Descriptor Tail
|
||||
|
||||
; Update stats
|
||||
inc [device.packets_tx]
|
||||
mov eax, [esp + 8]
|
||||
add dword [device.bytes_tx], eax
|
||||
adc dword [device.bytes_tx + 4], 0
|
||||
|
||||
ret 8
|
||||
|
||||
.fail:
|
||||
DEBUGF 1,"Send failed\n"
|
||||
ret 8
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Interrupt handler ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
align 4
|
||||
int_handler:
|
||||
|
||||
push ebx esi edi
|
||||
|
||||
DEBUGF 1,"\n%s int\n", my_service
|
||||
;-------------------------------------------
|
||||
; Find pointer of device wich made IRQ occur
|
||||
|
||||
mov ecx, [devices]
|
||||
test ecx, ecx
|
||||
jz .nothing
|
||||
mov esi, device_list
|
||||
.nextdevice:
|
||||
mov ebx, [esi]
|
||||
|
||||
mov edi, [device.mmio_addr]
|
||||
mov eax, [edi + REG_ICR]
|
||||
test eax, eax
|
||||
jnz .got_it
|
||||
.continue:
|
||||
add esi, 4
|
||||
dec ecx
|
||||
jnz .nextdevice
|
||||
.nothing:
|
||||
pop edi esi ebx
|
||||
xor eax, eax
|
||||
|
||||
ret
|
||||
|
||||
.got_it:
|
||||
|
||||
DEBUGF 1,"Device: %x Status: %x ", ebx, eax
|
||||
|
||||
;---------
|
||||
; RX done?
|
||||
|
||||
test eax, ICR_RXDMT0
|
||||
jz .no_rx
|
||||
|
||||
push eax ebx
|
||||
push .retaddr
|
||||
|
||||
; Get last descriptor addr
|
||||
lea esi, [device.rx_desc]
|
||||
|
||||
cmp byte [esi + 12], 0 ; Check status field
|
||||
je .retaddr
|
||||
|
||||
movzx ecx, word [esi + 8] ; Get the packet length
|
||||
DEBUGF 2,"got %u bytes\n", ecx
|
||||
push ecx
|
||||
push dword [esi + 16] ; Get packet pointer
|
||||
|
||||
; Update stats
|
||||
add dword [device.bytes_rx], ecx
|
||||
adc dword [device.bytes_rx + 4], 0
|
||||
inc dword [device.packets_rx]
|
||||
|
||||
; allocate new descriptor
|
||||
stdcall KernelAlloc, 48*1024
|
||||
mov dword [esi + 16], eax
|
||||
GetRealAddr
|
||||
mov dword [esi], eax
|
||||
|
||||
; reset descriptor status
|
||||
mov esi, [device.mmio_addr]
|
||||
mov dword [esi + REG_RDH], 0x00000000 ; Receive Descriptor Head
|
||||
mov dword [esi + REG_RDT], 0x00000001 ; Receive Descriptor Tail
|
||||
|
||||
jmp Eth_input
|
||||
.retaddr:
|
||||
pop ebx eax
|
||||
|
||||
.no_rx:
|
||||
|
||||
;--------------
|
||||
; Link Changed?
|
||||
|
||||
test eax, ICR_LSC
|
||||
jz .no_link
|
||||
|
||||
DEBUGF 2,"Link Changed\n"
|
||||
|
||||
.no_link:
|
||||
|
||||
;---------------
|
||||
; Transmit done?
|
||||
|
||||
test eax, ICR_TXDW
|
||||
jz .no_tx
|
||||
|
||||
DEBUGF 2,"Transmit done\n"
|
||||
|
||||
lea edi, [device.tx_desc] ; Transmit Descriptor Base Address
|
||||
push dword [edi + 16] ; Store the data location (for driver)
|
||||
call KernelFree
|
||||
|
||||
.no_tx:
|
||||
.fail:
|
||||
pop edi esi ebx
|
||||
xor eax, eax
|
||||
inc eax
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
; End of code
|
||||
|
||||
section '.data' data readable writable align 16
|
||||
align 4
|
||||
|
||||
devices dd 0
|
||||
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
|
||||
my_service db 'I8254X',0 ; max 16 chars include zero
|
||||
|
||||
include_debug_strings ; All data wich FDO uses will be included here
|
||||
|
||||
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+432
@@ -0,0 +1,432 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
;
|
||||
; Formatted Debug Output (FDO)
|
||||
; Copyright (c) 2005-2006, mike.dld
|
||||
; Created: 2005-01-29, Changed: 2006-11-10
|
||||
;
|
||||
; For questions and bug reports, mail to mike.dld@gmail.com
|
||||
;
|
||||
; Available format specifiers are: %s, %d, %u, %x (with partial width support)
|
||||
;
|
||||
|
||||
; to be defined:
|
||||
; __DEBUG__ equ 1
|
||||
; __DEBUG_LEVEL__ equ 5
|
||||
|
||||
macro debug_func name {
|
||||
if used name
|
||||
name@of@func equ name
|
||||
}
|
||||
|
||||
macro debug_beginf {
|
||||
align 4
|
||||
name@of@func:
|
||||
}
|
||||
|
||||
debug_endf fix end if
|
||||
|
||||
macro DEBUGS _sign,[_str] {
|
||||
common
|
||||
local tp
|
||||
tp equ 0
|
||||
match _arg:_num,_str \{
|
||||
DEBUGS_N _sign,_num,_arg
|
||||
tp equ 1
|
||||
\}
|
||||
match =0 _arg,tp _str \{
|
||||
DEBUGS_N _sign,,_arg
|
||||
\}
|
||||
}
|
||||
|
||||
macro DEBUGS_N _sign,_num,[_str] {
|
||||
common
|
||||
pushf
|
||||
pushad
|
||||
local ..str,..label,is_str
|
||||
is_str = 0
|
||||
forward
|
||||
if _str eqtype ''
|
||||
is_str = 1
|
||||
end if
|
||||
common
|
||||
if is_str = 1
|
||||
jmp ..label
|
||||
..str db _str,0
|
||||
..label:
|
||||
add esp,4*8+4
|
||||
mov edx,..str
|
||||
sub esp,4*8+4
|
||||
else
|
||||
mov edx,_str
|
||||
end if
|
||||
if ~_num eq
|
||||
if _num eqtype eax
|
||||
if _num in <eax,ebx,ecx,edx,edi,ebp,esp>
|
||||
mov esi,_num
|
||||
else if ~_num eq esi
|
||||
movzx esi,_num
|
||||
end if
|
||||
else if _num eqtype 0
|
||||
mov esi,_num
|
||||
else
|
||||
local tp
|
||||
tp equ 0
|
||||
match [_arg],_num \{
|
||||
mov esi,dword[_arg]
|
||||
tp equ 1
|
||||
\}
|
||||
match =0 =dword[_arg],tp _num \{
|
||||
mov esi,dword[_arg]
|
||||
tp equ 1
|
||||
\}
|
||||
match =0 =word[_arg],tp _num \{
|
||||
movzx esi,word[_arg]
|
||||
tp equ 1
|
||||
\}
|
||||
match =0 =byte[_arg],tp _num \{
|
||||
movzx esi,byte[_arg]
|
||||
tp equ 1
|
||||
\}
|
||||
match =0,tp \{
|
||||
'Error: specified string width is incorrect'
|
||||
\}
|
||||
end if
|
||||
else
|
||||
mov esi,0x7FFFFFFF
|
||||
end if
|
||||
call fdo_debug_outstr
|
||||
popad
|
||||
popf
|
||||
}
|
||||
|
||||
macro DEBUGD _sign,_dec {
|
||||
local tp
|
||||
tp equ 0
|
||||
match _arg:_num,_dec \{
|
||||
DEBUGD_N _sign,_num,_arg
|
||||
tp equ 1
|
||||
\}
|
||||
match =0 _arg,tp _dec \{
|
||||
DEBUGD_N _sign,,_arg
|
||||
\}
|
||||
}
|
||||
|
||||
macro DEBUGD_N _sign,_num,_dec {
|
||||
pushf
|
||||
pushad
|
||||
if (~_num eq)
|
||||
if (_dec eqtype eax | _dec eqtype 0)
|
||||
'Error: precision allowed only for in-memory variables'
|
||||
end if
|
||||
if (~_num in <1,2,4>)
|
||||
if _sign
|
||||
'Error: 1, 2 and 4 are only allowed for precision in %d'
|
||||
else
|
||||
'Error: 1, 2 and 4 are only allowed for precision in %u'
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
if _dec eqtype eax
|
||||
if _dec in <ebx,ecx,edx,esi,edi,ebp,esp>
|
||||
mov eax,_dec
|
||||
else if ~_dec eq eax
|
||||
if _sign = 1
|
||||
movsx eax,_dec
|
||||
else
|
||||
movzx eax,_dec
|
||||
end if
|
||||
end if
|
||||
else if _dec eqtype 0
|
||||
mov eax,_dec
|
||||
else
|
||||
add esp,4*8+4
|
||||
if _num eq
|
||||
mov eax,dword _dec
|
||||
else if _num = 1
|
||||
if _sign = 1
|
||||
movsx eax,byte _dec
|
||||
else
|
||||
movzx eax,byte _dec
|
||||
end if
|
||||
else if _num = 2
|
||||
if _sign = 1
|
||||
movsx eax,word _dec
|
||||
else
|
||||
movzx eax,word _dec
|
||||
end if
|
||||
else
|
||||
mov eax,dword _dec
|
||||
end if
|
||||
sub esp,4*8+4
|
||||
end if
|
||||
mov cl,_sign
|
||||
call fdo_debug_outdec
|
||||
popad
|
||||
popf
|
||||
}
|
||||
|
||||
macro DEBUGH _sign,_hex {
|
||||
local tp
|
||||
tp equ 0
|
||||
match _arg:_num,_hex \{
|
||||
DEBUGH_N _sign,_num,_arg
|
||||
tp equ 1
|
||||
\}
|
||||
match =0 _arg,tp _hex \{
|
||||
DEBUGH_N _sign,,_arg
|
||||
\}
|
||||
}
|
||||
|
||||
macro DEBUGH_N _sign,_num,_hex {
|
||||
pushf
|
||||
pushad
|
||||
if (~_num eq) & (~_num in <1,2,3,4,5,6,7,8>)
|
||||
'Error: 1..8 are only allowed for precision in %x'
|
||||
end if
|
||||
if _hex eqtype eax
|
||||
if _hex in <eax,ebx,ecx,edx,esi,edi,ebp,esp>
|
||||
if ~_hex eq eax
|
||||
mov eax,_hex
|
||||
end if
|
||||
mov edx,8
|
||||
else if _hex in <ax,bx,cx,dx,si,di,bp,sp>
|
||||
if ~_hex eq ax
|
||||
movzx eax,_hex
|
||||
end if
|
||||
if (_num eq)
|
||||
mov edx,4
|
||||
end if
|
||||
else if _hex in <al,ah,bl,bh,cl,ch,dl,dh>
|
||||
if ~_hex eq al
|
||||
movzx eax,_hex
|
||||
end if
|
||||
if (_num eq)
|
||||
mov edx,2
|
||||
end if
|
||||
end if
|
||||
else if _hex eqtype 0
|
||||
mov eax,_hex
|
||||
else
|
||||
add esp,4*8+4
|
||||
mov eax,dword _hex
|
||||
sub esp,4*8+4
|
||||
end if
|
||||
if ~_num eq
|
||||
mov edx,_num
|
||||
else
|
||||
if ~_hex eqtype eax
|
||||
mov edx,8
|
||||
end if
|
||||
end if
|
||||
call fdo_debug_outhex
|
||||
popad
|
||||
popf
|
||||
}
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
debug_func fdo_debug_outchar
|
||||
debug_beginf
|
||||
pushad
|
||||
movzx ebx,al
|
||||
mov eax,1
|
||||
; mov ecx,sys_msg_board
|
||||
; call ecx ; sys_msg_board
|
||||
stdcall SysMsgBoardChar
|
||||
popad
|
||||
ret
|
||||
debug_endf
|
||||
|
||||
debug_func fdo_debug_outstr
|
||||
debug_beginf
|
||||
mov eax,1
|
||||
.l1: dec esi
|
||||
js .l2
|
||||
movzx ebx,byte[edx]
|
||||
or bl,bl
|
||||
jz .l2
|
||||
; mov ecx,sys_msg_board
|
||||
; call ecx ; sys_msg_board
|
||||
stdcall SysMsgBoardChar
|
||||
inc edx
|
||||
jmp .l1
|
||||
.l2: ret
|
||||
debug_endf
|
||||
|
||||
debug_func fdo_debug_outdec
|
||||
debug_beginf
|
||||
or cl,cl
|
||||
jz @f
|
||||
or eax,eax
|
||||
jns @f
|
||||
neg eax
|
||||
push eax
|
||||
mov al,'-'
|
||||
call fdo_debug_outchar
|
||||
pop eax
|
||||
@@: push 10
|
||||
pop ecx
|
||||
push -'0'
|
||||
.l1: xor edx,edx
|
||||
div ecx
|
||||
push edx
|
||||
test eax,eax
|
||||
jnz .l1
|
||||
.l2: pop eax
|
||||
add al,'0'
|
||||
jz .l3
|
||||
call fdo_debug_outchar
|
||||
jmp .l2
|
||||
.l3: ret
|
||||
debug_endf
|
||||
|
||||
debug_func fdo_debug_outhex
|
||||
__fdo_hexdigits db '0123456789ABCDEF'
|
||||
debug_beginf
|
||||
mov cl,dl
|
||||
neg cl
|
||||
add cl,8
|
||||
shl cl,2
|
||||
rol eax,cl
|
||||
.l1: rol eax,4
|
||||
push eax
|
||||
and eax,0x0000000F
|
||||
mov al,[__fdo_hexdigits+eax]
|
||||
call fdo_debug_outchar
|
||||
pop eax
|
||||
dec edx
|
||||
jnz .l1
|
||||
ret
|
||||
debug_endf
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
|
||||
macro DEBUGF _level,_format,[_arg] {
|
||||
common
|
||||
if __DEBUG__ = 1 & _level >= __DEBUG_LEVEL__
|
||||
local ..f1,f2,a1,a2,c1,c2,c3,..lbl
|
||||
_debug_str_ equ __debug_str_ # a1
|
||||
a1 = 0
|
||||
c2 = 0
|
||||
c3 = 0
|
||||
f2 = 0
|
||||
repeat ..lbl-..f1
|
||||
virtual at 0
|
||||
db _format,0,0
|
||||
load c1 word from %-1
|
||||
end virtual
|
||||
if c1 = '%s'
|
||||
virtual at 0
|
||||
db _format,0,0
|
||||
store word 0 at %-1
|
||||
load c1 from f2-c2
|
||||
end virtual
|
||||
if c1 <> 0
|
||||
DEBUGS 0,_debug_str_+f2-c2
|
||||
end if
|
||||
c2 = c2 + 1
|
||||
f2 = %+1
|
||||
DEBUGF_HELPER S,a1,0,_arg
|
||||
else if c1 = '%x'
|
||||
virtual at 0
|
||||
db _format,0,0
|
||||
store word 0 at %-1
|
||||
load c1 from f2-c2
|
||||
end virtual
|
||||
if c1 <> 0
|
||||
DEBUGS 0,_debug_str_+f2-c2
|
||||
end if
|
||||
c2 = c2 + 1
|
||||
f2 = %+1
|
||||
DEBUGF_HELPER H,a1,0,_arg
|
||||
else if c1 = '%d' | c1 = '%u'
|
||||
local c4
|
||||
if c1 = '%d'
|
||||
c4 = 1
|
||||
else
|
||||
c4 = 0
|
||||
end if
|
||||
virtual at 0
|
||||
db _format,0,0
|
||||
store word 0 at %-1
|
||||
load c1 from f2-c2
|
||||
end virtual
|
||||
if c1 <> 0
|
||||
DEBUGS 0,_debug_str_+f2-c2
|
||||
end if
|
||||
c2 = c2 + 1
|
||||
f2 = %+1
|
||||
DEBUGF_HELPER D,a1,c4,_arg
|
||||
else if c1 = '\n'
|
||||
c3 = c3 + 1
|
||||
end if
|
||||
end repeat
|
||||
virtual at 0
|
||||
db _format,0,0
|
||||
load c1 from f2-c2
|
||||
end virtual
|
||||
if (c1<>0)&(f2<>..lbl-..f1-1)
|
||||
DEBUGS 0,_debug_str_+f2-c2
|
||||
end if
|
||||
virtual at 0
|
||||
..f1 db _format,0
|
||||
..lbl:
|
||||
__debug_strings equ __debug_strings,_debug_str_,<_format>,..lbl-..f1-1-c2-c3
|
||||
end virtual
|
||||
end if
|
||||
}
|
||||
|
||||
macro __include_debug_strings dummy,[_id,_fmt,_len] {
|
||||
common
|
||||
local c1,a1,a2
|
||||
forward
|
||||
if defined _len & ~_len eq
|
||||
_id:
|
||||
a1 = 0
|
||||
a2 = 0
|
||||
repeat _len
|
||||
virtual at 0
|
||||
db _fmt,0,0
|
||||
load c1 word from %+a2-1
|
||||
end virtual
|
||||
if (c1='%s')|(c1='%x')|(c1='%d')|(c1='%u')
|
||||
db 0
|
||||
a2 = a2 + 1
|
||||
else if (c1='\n')
|
||||
dw $0A0D
|
||||
a1 = a1 + 1
|
||||
a2 = a2 + 1
|
||||
else
|
||||
db c1 and 0x0FF
|
||||
end if
|
||||
end repeat
|
||||
db 0
|
||||
end if
|
||||
}
|
||||
|
||||
macro DEBUGF_HELPER _letter,_num,_sign,[_arg] {
|
||||
common
|
||||
local num
|
||||
num = 0
|
||||
forward
|
||||
if num = _num
|
||||
DEBUG#_letter _sign,_arg
|
||||
end if
|
||||
num = num+1
|
||||
common
|
||||
_num = _num+1
|
||||
}
|
||||
|
||||
macro include_debug_strings {
|
||||
if __DEBUG__ = 1
|
||||
match dbg_str,__debug_strings \{
|
||||
__include_debug_strings dbg_str
|
||||
\}
|
||||
end if
|
||||
}
|
||||
+102
-151
@@ -1,151 +1,102 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; all exported kernel functions and data
|
||||
|
||||
if used RegService
|
||||
extrn RegService
|
||||
end if
|
||||
if used GetService
|
||||
extrn GetService
|
||||
end if
|
||||
if used ServiceHandler
|
||||
extrn ServiceHandler
|
||||
end if
|
||||
if used AttachIntHandler
|
||||
extrn AttachIntHandler
|
||||
end if
|
||||
if used FpuSave
|
||||
extrn FpuSave
|
||||
end if
|
||||
if used FpuRestore
|
||||
extrn FpuRestore
|
||||
end if
|
||||
|
||||
if used PciApi
|
||||
extrn PciApi
|
||||
end if
|
||||
if used PciRead32
|
||||
extrn PciRead32
|
||||
end if
|
||||
if used PciRead8
|
||||
extrn PciRead8
|
||||
end if
|
||||
if used PciWrite8
|
||||
extrn PciWrite8
|
||||
end if
|
||||
|
||||
if used AllocPage
|
||||
extrn AllocPage
|
||||
end if
|
||||
if used AllocPages
|
||||
extrn AllocPages
|
||||
end if
|
||||
if used FreePage
|
||||
extrn FreePage
|
||||
end if
|
||||
if used MapPage
|
||||
extrn MapPage
|
||||
end if
|
||||
if used MapSpace
|
||||
extrn MapSpace
|
||||
end if
|
||||
if used GetPgAddr
|
||||
extrn GetPgAddr
|
||||
end if
|
||||
if used CommitPages
|
||||
extrn CommitPages
|
||||
end if
|
||||
if used ReleasePages
|
||||
extrn ReleasePages
|
||||
end if
|
||||
|
||||
if used AllocKernelSpace
|
||||
extrn AllocKernelSpace
|
||||
end if
|
||||
if used FreeKernelSpace
|
||||
extrn FreeKernelSpace
|
||||
end if
|
||||
if used KernelAlloc
|
||||
extrn KernelAlloc
|
||||
end if
|
||||
if used KernelFree
|
||||
extrn KernelFree
|
||||
end if
|
||||
if used UserAlloc
|
||||
extrn UserAlloc
|
||||
end if
|
||||
if used UserFree
|
||||
extrn UserFree
|
||||
end if
|
||||
if used Kmalloc
|
||||
extrn Kmalloc
|
||||
end if
|
||||
if used Kfree
|
||||
extrn Kfree
|
||||
end if
|
||||
|
||||
if used CreateObject
|
||||
extrn CreateObject
|
||||
end if
|
||||
if used DestroyObject
|
||||
extrn DestroyObject
|
||||
end if
|
||||
if used CreateEvent
|
||||
extrn CreateEvent
|
||||
end if
|
||||
if used RaiseEvent
|
||||
extrn RaiseEvent
|
||||
end if
|
||||
if used WaitEvent
|
||||
extrn WaitEvent
|
||||
end if
|
||||
if used DestroyEvent
|
||||
extrn DestroyEvent
|
||||
end if
|
||||
if used ClearEvent
|
||||
extrn ClearEvent
|
||||
end if
|
||||
|
||||
if used LoadCursor
|
||||
extrn LoadCursor
|
||||
end if
|
||||
if used SetHwCursor
|
||||
extrn SetHwCursor
|
||||
end if
|
||||
if used HwCursorRestore
|
||||
extrn HwCursorRestore
|
||||
end if
|
||||
if used HwCursorCreate
|
||||
extrn HwCursorCreate
|
||||
end if
|
||||
|
||||
if used SysMsgBoardStr
|
||||
extrn SysMsgBoardStr
|
||||
end if
|
||||
if used GetCurrentTask
|
||||
extrn GetCurrentTask
|
||||
end if
|
||||
if used LoadFile
|
||||
extrn LoadFile
|
||||
end if
|
||||
if used SendEvent
|
||||
extrn SendEvent
|
||||
end if
|
||||
if used SetMouseData
|
||||
extrn SetMouseData
|
||||
end if
|
||||
if used Sleep
|
||||
extrn Sleep
|
||||
end if
|
||||
if used GetTimerTicks
|
||||
extrn GetTimerTicks
|
||||
end if
|
||||
if used LFBAddress
|
||||
extrn LFBAddress
|
||||
end if
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
macro kernel_export [name]{
|
||||
forward
|
||||
if used name
|
||||
if DEBUG
|
||||
display 'uses: ',`name,#13,#10
|
||||
end if
|
||||
extrn name
|
||||
end if
|
||||
}
|
||||
; all exported kernel functions and data
|
||||
|
||||
|
||||
kernel_export \
|
||||
RegService,\
|
||||
GetService,\
|
||||
ServiceHandler,\
|
||||
AttachIntHandler,\
|
||||
GetIntHandler,\
|
||||
FpuSave,\
|
||||
FpuRestore,\
|
||||
ReservePortArea,\
|
||||
Boot_Log,\
|
||||
\
|
||||
MutexInit,\
|
||||
MutexLock,\
|
||||
MutexUnlock,\
|
||||
\
|
||||
PciApi,\
|
||||
PciRead32,\
|
||||
PciRead16,\
|
||||
PciRead8,\
|
||||
PciWrite8,\
|
||||
PciWrite16,\
|
||||
PciWrite32,\
|
||||
\
|
||||
AllocPage,\
|
||||
AllocPages,\
|
||||
FreePage,\
|
||||
MapPage,\
|
||||
MapSpace,\
|
||||
MapIoMem,\
|
||||
GetPgAddr,\
|
||||
CommitPages,\
|
||||
ReleasePages,\
|
||||
\
|
||||
AllocKernelSpace,\
|
||||
FreeKernelSpace,\
|
||||
KernelAlloc,\
|
||||
KernelFree,\
|
||||
UserAlloc,\
|
||||
UserFree,\
|
||||
Kmalloc,\
|
||||
Kfree,\
|
||||
CreateRingBuffer,\
|
||||
\
|
||||
GetPid,\
|
||||
CreateObject,\
|
||||
DestroyObject,\
|
||||
CreateEvent,\
|
||||
RaiseEvent,\
|
||||
WaitEvent,\
|
||||
DestroyEvent,\
|
||||
ClearEvent,\
|
||||
\
|
||||
LoadCursor,\
|
||||
SelectHwCursor,\
|
||||
SetHwCursor,\
|
||||
HwCursorRestore,\
|
||||
HwCursorCreate,\
|
||||
\
|
||||
SysMsgBoardStr,\
|
||||
SysMsgBoardChar,\
|
||||
GetCurrentTask,\
|
||||
LoadFile,\
|
||||
SendEvent,\
|
||||
SetMouseData,\
|
||||
Sleep,\
|
||||
GetTimerTicks,\
|
||||
\
|
||||
strncat,\
|
||||
strncpy,\
|
||||
strncmp,\
|
||||
strnlen,\
|
||||
strchr,\
|
||||
strrchr,\
|
||||
\
|
||||
LFBAddress,\
|
||||
GetDisplay,\
|
||||
SetScreen,\
|
||||
\
|
||||
NetRegDev,\
|
||||
NetUnRegDev,\
|
||||
NetPtrToNum,\
|
||||
NetLinkChanged,\
|
||||
Eth_input,\
|
||||
IPv4_input
|
||||
|
||||
+160
@@ -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
|
||||
@@ -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
@@ -0,0 +1,132 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
; PCI Bus defines
|
||||
|
||||
PCI_HEADER_TYPE = 0x0e ; 8 bit
|
||||
PCI_BASE_ADDRESS_0 = 0x10 ; 32 bit
|
||||
PCI_BASE_ADDRESS_1 = 0x14 ; 32 bits
|
||||
PCI_BASE_ADDRESS_2 = 0x18 ; 32 bits
|
||||
PCI_BASE_ADDRESS_3 = 0x1c ; 32 bits
|
||||
PCI_BASE_ADDRESS_4 = 0x20 ; 32 bits
|
||||
PCI_BASE_ADDRESS_5 = 0x24 ; 32 bits
|
||||
PCI_BASE_ADDRESS_SPACE_IO = 0x01
|
||||
PCI_BASE_ADDRESS_IO_MASK = 0xFFFFFFFC
|
||||
PCI_BASE_ADDRESS_MEM_MASK = 0xFFFFFFF0
|
||||
|
||||
; PCI programming
|
||||
|
||||
PCI_VENDOR_ID = 0x00 ; 16 bit
|
||||
PCI_DEVICE_ID = 0x02 ; 16 bits
|
||||
PCI_REG_COMMAND = 0x4 ; command register
|
||||
PCI_REG_STATUS = 0x6 ; status register
|
||||
PCI_REVISION_ID = 0x08 ; 8 bits
|
||||
PCI_REG_LATENCY = 0xd ; latency timer register
|
||||
PCI_REG_CAP_PTR = 0x34 ; capabilities pointer
|
||||
PCI_REG_IRQ = 0x3c
|
||||
PCI_REG_CAPABILITY_ID = 0x0 ; capapility ID in pm register block
|
||||
PCI_REG_PM_STATUS = 0x4 ; power management status register
|
||||
PCI_REG_PM_CTRL = 0x4 ; power management control register
|
||||
PCI_BIT_PIO = 1 ; bit0: io space control
|
||||
PCI_BIT_MMIO = 2 ; bit1: memory space control
|
||||
PCI_BIT_MASTER = 4 ; bit2: device acts as a PCI master
|
||||
|
||||
|
||||
macro PCI_find_io {
|
||||
|
||||
local .check, .inc, .got
|
||||
|
||||
xor eax, eax
|
||||
mov esi, PCI_BASE_ADDRESS_0
|
||||
.check:
|
||||
stdcall PciRead32, [device.pci_bus], [device.pci_dev], esi
|
||||
|
||||
test eax, PCI_BASE_ADDRESS_IO_MASK
|
||||
jz .inc
|
||||
|
||||
test eax, PCI_BASE_ADDRESS_SPACE_IO
|
||||
jz .inc
|
||||
|
||||
and eax, PCI_BASE_ADDRESS_IO_MASK
|
||||
jmp .got
|
||||
|
||||
.inc:
|
||||
add esi, 4
|
||||
cmp esi, PCI_BASE_ADDRESS_5
|
||||
jbe .check
|
||||
xor eax, eax
|
||||
|
||||
.got:
|
||||
mov [device.io_addr], eax
|
||||
|
||||
}
|
||||
|
||||
|
||||
macro PCI_find_mmio32 {
|
||||
|
||||
local .check, .inc, .got
|
||||
|
||||
mov esi, PCI_BASE_ADDRESS_0
|
||||
.check:
|
||||
stdcall PciRead32, [device.pci_bus], [device.pci_dev], esi
|
||||
|
||||
test eax, PCI_BASE_ADDRESS_SPACE_IO ; mmio address?
|
||||
jnz .inc
|
||||
|
||||
test eax, 100b ; 64 bit?
|
||||
jnz .inc
|
||||
and eax, not 1111b
|
||||
jmp .got
|
||||
|
||||
.inc:
|
||||
add esi, 4
|
||||
cmp esi, PCI_BASE_ADDRESS_5
|
||||
jbe .check
|
||||
xor eax, eax
|
||||
|
||||
.got:
|
||||
mov [device.mmio_addr], eax
|
||||
}
|
||||
|
||||
macro PCI_find_irq {
|
||||
|
||||
stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REG_IRQ
|
||||
mov [device.irq_line], al
|
||||
|
||||
}
|
||||
|
||||
macro PCI_find_rev {
|
||||
|
||||
stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REVISION_ID
|
||||
mov [device.revision], al
|
||||
|
||||
}
|
||||
|
||||
macro PCI_make_bus_master bus, dev {
|
||||
|
||||
stdcall PciRead32, [device.pci_bus], [device.pci_dev], PCI_REG_COMMAND
|
||||
or al, PCI_BIT_MASTER
|
||||
stdcall PciWrite32, [device.pci_bus], [device.pci_dev], PCI_REG_COMMAND, eax
|
||||
|
||||
}
|
||||
|
||||
macro PCI_adjust_latency min {
|
||||
|
||||
local .not
|
||||
|
||||
stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REG_LATENCY
|
||||
cmp al, min
|
||||
ja .not
|
||||
mov al, min
|
||||
stdcall PciWrite8, [device.pci_bus], [device.pci_dev], PCI_REG_LATENCY, eax
|
||||
.not:
|
||||
|
||||
}
|
||||
+268
-268
@@ -1,268 +1,268 @@
|
||||
|
||||
; Macroinstructions for defining and calling procedures
|
||||
|
||||
macro stdcall proc,[arg] ; directly call STDCALL procedure
|
||||
{ common
|
||||
if ~ arg eq
|
||||
reverse
|
||||
pushd arg
|
||||
common
|
||||
end if
|
||||
call proc }
|
||||
|
||||
macro invoke proc,[arg] ; indirectly call STDCALL procedure
|
||||
{ common
|
||||
if ~ arg eq
|
||||
reverse
|
||||
pushd arg
|
||||
common
|
||||
end if
|
||||
call [proc] }
|
||||
|
||||
macro ccall proc,[arg] ; directly call CDECL procedure
|
||||
{ common
|
||||
size@ccall = 0
|
||||
if ~ arg eq
|
||||
reverse
|
||||
pushd arg
|
||||
size@ccall = size@ccall+4
|
||||
common
|
||||
end if
|
||||
call proc
|
||||
if size@ccall
|
||||
add esp,size@ccall
|
||||
end if }
|
||||
|
||||
macro cinvoke proc,[arg] ; indirectly call CDECL procedure
|
||||
{ common
|
||||
size@ccall = 0
|
||||
if ~ arg eq
|
||||
reverse
|
||||
pushd arg
|
||||
size@ccall = size@ccall+4
|
||||
common
|
||||
end if
|
||||
call [proc]
|
||||
if size@ccall
|
||||
add esp,size@ccall
|
||||
end if }
|
||||
|
||||
macro proc [args] ; define procedure
|
||||
{ common
|
||||
match name params, args>
|
||||
\{ define@proc name,<params \} }
|
||||
|
||||
prologue@proc equ prologuedef
|
||||
|
||||
macro prologuedef procname,flag,parmbytes,localbytes,reglist
|
||||
{ if parmbytes | localbytes
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
if localbytes
|
||||
sub esp,localbytes
|
||||
end if
|
||||
end if
|
||||
irps reg, reglist \{ push reg \} }
|
||||
|
||||
epilogue@proc equ epiloguedef
|
||||
|
||||
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
|
||||
{ irps reg, reglist \{ reverse pop reg \}
|
||||
if parmbytes | localbytes
|
||||
leave
|
||||
end if
|
||||
if (flag and 10000b) | (parmbytes=0)
|
||||
retn
|
||||
else
|
||||
retn parmbytes
|
||||
end if }
|
||||
|
||||
macro define@proc name,statement
|
||||
{ local params,flag,regs,parmbytes,localbytes,current
|
||||
if used name
|
||||
name:
|
||||
match =stdcall args, statement \{ params equ args
|
||||
flag = 11b \}
|
||||
match =stdcall, statement \{ params equ
|
||||
flag = 11b \}
|
||||
match =c args, statement \{ params equ args
|
||||
flag = 10001b \}
|
||||
match =c, statement \{ params equ
|
||||
flag = 10001b \}
|
||||
match =params, params \{ params equ statement
|
||||
flag = 0 \}
|
||||
virtual at ebp+8
|
||||
match =uses reglist=,args, params \{ regs equ reglist
|
||||
params equ args \}
|
||||
match =regs =uses reglist, regs params \{ regs equ reglist
|
||||
params equ \}
|
||||
match =regs, regs \{ regs equ \}
|
||||
match =,args, params \{ defargs@proc args \}
|
||||
match =args@proc args, args@proc params \{ defargs@proc args \}
|
||||
parmbytes = $ - (ebp+8)
|
||||
end virtual
|
||||
name # % = parmbytes/4
|
||||
all@vars equ
|
||||
current = 0
|
||||
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
|
||||
macro locals
|
||||
\{ virtual at ebp-localbytes+current
|
||||
macro label . \\{ deflocal@proc .,:, \\}
|
||||
struc db [val] \\{ \common deflocal@proc .,db,val \\}
|
||||
struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
|
||||
struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
|
||||
struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
|
||||
struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
|
||||
struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
|
||||
struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
|
||||
struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
|
||||
struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
|
||||
struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
|
||||
struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
|
||||
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
|
||||
macro endl
|
||||
\{ purge label
|
||||
restruc db,dw,dp,dd,dt,dq
|
||||
restruc rb,rw,rp,rd,rt,rq
|
||||
restruc byte,word,dword,pword,tword,qword
|
||||
current = $-(ebp-localbytes)
|
||||
end virtual \}
|
||||
macro ret operand
|
||||
\{ match any, operand \\{ retn operand \\}
|
||||
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs>
|
||||
\\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
|
||||
macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2
|
||||
end if \} }
|
||||
|
||||
macro defargs@proc [arg]
|
||||
{ common
|
||||
if ~ arg eq
|
||||
forward
|
||||
local ..arg,current@arg
|
||||
match argname:type, arg
|
||||
\{ current@arg equ argname
|
||||
label ..arg type
|
||||
argname equ ..arg
|
||||
if dqword eq type
|
||||
dd ?,?,?,?
|
||||
else if tbyte eq type
|
||||
dd ?,?,?
|
||||
else if qword eq type | pword eq type
|
||||
dd ?,?
|
||||
else
|
||||
dd ?
|
||||
end if \}
|
||||
match =current@arg,current@arg
|
||||
\{ current@arg equ arg
|
||||
arg equ ..arg
|
||||
..arg dd ? \}
|
||||
common
|
||||
args@proc equ current@arg
|
||||
forward
|
||||
restore current@arg
|
||||
common
|
||||
end if }
|
||||
|
||||
macro deflocal@proc name,def,[val]
|
||||
{ common
|
||||
match vars, all@vars \{ all@vars equ all@vars, \}
|
||||
all@vars equ all@vars name
|
||||
forward
|
||||
local ..var,..tmp
|
||||
..var def val
|
||||
match =?, val \{ ..tmp equ \}
|
||||
match any =dup (=?), val \{ ..tmp equ \}
|
||||
match tmp : value, ..tmp : val
|
||||
\{ tmp: end virtual
|
||||
initlocal@proc ..var,def value
|
||||
virtual at tmp\}
|
||||
common
|
||||
match first rest, ..var, \{ name equ first \} }
|
||||
|
||||
macro initlocal@proc name,def
|
||||
{ virtual at name
|
||||
def
|
||||
size@initlocal = $ - name
|
||||
end virtual
|
||||
position@initlocal = 0
|
||||
while size@initlocal > position@initlocal
|
||||
virtual at name
|
||||
def
|
||||
if size@initlocal - position@initlocal < 2
|
||||
current@initlocal = 1
|
||||
load byte@initlocal byte from name+position@initlocal
|
||||
else if size@initlocal - position@initlocal < 4
|
||||
current@initlocal = 2
|
||||
load word@initlocal word from name+position@initlocal
|
||||
else
|
||||
current@initlocal = 4
|
||||
load dword@initlocal dword from name+position@initlocal
|
||||
end if
|
||||
end virtual
|
||||
if current@initlocal = 1
|
||||
mov byte [name+position@initlocal],byte@initlocal
|
||||
else if current@initlocal = 2
|
||||
mov word [name+position@initlocal],word@initlocal
|
||||
else
|
||||
mov dword [name+position@initlocal],dword@initlocal
|
||||
end if
|
||||
position@initlocal = position@initlocal + current@initlocal
|
||||
end while }
|
||||
|
||||
macro endp
|
||||
{ purge ret,locals,endl
|
||||
finish@proc
|
||||
purge finish@proc
|
||||
restore regs@proc
|
||||
match all,args@proc \{ restore all \}
|
||||
restore args@proc
|
||||
match all,all@vars \{ restore all \} }
|
||||
|
||||
macro local [var]
|
||||
{ common
|
||||
locals
|
||||
forward done@local equ
|
||||
match varname[count]:vartype, var
|
||||
\{ match =BYTE, vartype \\{ varname rb count
|
||||
restore done@local \\}
|
||||
match =WORD, vartype \\{ varname rw count
|
||||
restore done@local \\}
|
||||
match =DWORD, vartype \\{ varname rd count
|
||||
restore done@local \\}
|
||||
match =PWORD, vartype \\{ varname rp count
|
||||
restore done@local \\}
|
||||
match =QWORD, vartype \\{ varname rq count
|
||||
restore done@local \\}
|
||||
match =TBYTE, vartype \\{ varname rt count
|
||||
restore done@local \\}
|
||||
match =DQWORD, vartype \\{ label varname dqword
|
||||
rq count+count
|
||||
restore done@local \\}
|
||||
match , done@local \\{ virtual
|
||||
varname vartype
|
||||
end virtual
|
||||
rb count*sizeof.\#vartype
|
||||
restore done@local \\} \}
|
||||
match :varname:vartype, done@local:var
|
||||
\{ match =BYTE, vartype \\{ varname db ?
|
||||
restore done@local \\}
|
||||
match =WORD, vartype \\{ varname dw ?
|
||||
restore done@local \\}
|
||||
match =DWORD, vartype \\{ varname dd ?
|
||||
restore done@local \\}
|
||||
match =PWORD, vartype \\{ varname dp ?
|
||||
restore done@local \\}
|
||||
match =QWORD, vartype \\{ varname dq ?
|
||||
restore done@local \\}
|
||||
match =TBYTE, vartype \\{ varname dt ?
|
||||
restore done@local \\}
|
||||
match =DQWORD, vartype \\{ label varname dqword
|
||||
dq ?,?
|
||||
restore done@local \\}
|
||||
match , done@local \\{ varname vartype
|
||||
restore done@local \\} \}
|
||||
match ,done@local
|
||||
\{ var
|
||||
restore done@local \}
|
||||
common
|
||||
endl }
|
||||
|
||||
; Macroinstructions for defining and calling procedures
|
||||
|
||||
macro stdcall proc,[arg] ; directly call STDCALL procedure
|
||||
{ common
|
||||
if ~ arg eq
|
||||
reverse
|
||||
pushd arg
|
||||
common
|
||||
end if
|
||||
call proc }
|
||||
|
||||
macro invoke proc,[arg] ; indirectly call STDCALL procedure
|
||||
{ common
|
||||
if ~ arg eq
|
||||
reverse
|
||||
pushd arg
|
||||
common
|
||||
end if
|
||||
call [proc] }
|
||||
|
||||
macro ccall proc,[arg] ; directly call CDECL procedure
|
||||
{ common
|
||||
size@ccall = 0
|
||||
if ~ arg eq
|
||||
reverse
|
||||
pushd arg
|
||||
size@ccall = size@ccall+4
|
||||
common
|
||||
end if
|
||||
call proc
|
||||
if size@ccall
|
||||
add esp,size@ccall
|
||||
end if }
|
||||
|
||||
macro cinvoke proc,[arg] ; indirectly call CDECL procedure
|
||||
{ common
|
||||
size@ccall = 0
|
||||
if ~ arg eq
|
||||
reverse
|
||||
pushd arg
|
||||
size@ccall = size@ccall+4
|
||||
common
|
||||
end if
|
||||
call [proc]
|
||||
if size@ccall
|
||||
add esp,size@ccall
|
||||
end if }
|
||||
|
||||
macro proc [args] ; define procedure
|
||||
{ common
|
||||
match name params, args>
|
||||
\{ define@proc name,<params \} }
|
||||
|
||||
prologue@proc equ prologuedef
|
||||
|
||||
macro prologuedef procname,flag,parmbytes,localbytes,reglist
|
||||
{ if parmbytes | localbytes
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
if localbytes
|
||||
sub esp,localbytes
|
||||
end if
|
||||
end if
|
||||
irps reg, reglist \{ push reg \} }
|
||||
|
||||
epilogue@proc equ epiloguedef
|
||||
|
||||
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
|
||||
{ irps reg, reglist \{ reverse pop reg \}
|
||||
if parmbytes | localbytes
|
||||
leave
|
||||
end if
|
||||
if (flag and 10000b) | (parmbytes=0)
|
||||
retn
|
||||
else
|
||||
retn parmbytes
|
||||
end if }
|
||||
|
||||
macro define@proc name,statement
|
||||
{ local params,flag,regs,parmbytes,localbytes,current
|
||||
if used name
|
||||
name:
|
||||
match =stdcall args, statement \{ params equ args
|
||||
flag = 11b \}
|
||||
match =stdcall, statement \{ params equ
|
||||
flag = 11b \}
|
||||
match =c args, statement \{ params equ args
|
||||
flag = 10001b \}
|
||||
match =c, statement \{ params equ
|
||||
flag = 10001b \}
|
||||
match =params, params \{ params equ statement
|
||||
flag = 0 \}
|
||||
virtual at ebp+8
|
||||
match =uses reglist=,args, params \{ regs equ reglist
|
||||
params equ args \}
|
||||
match =regs =uses reglist, regs params \{ regs equ reglist
|
||||
params equ \}
|
||||
match =regs, regs \{ regs equ \}
|
||||
match =,args, params \{ defargs@proc args \}
|
||||
match =args@proc args, args@proc params \{ defargs@proc args \}
|
||||
parmbytes = $ - (ebp+8)
|
||||
end virtual
|
||||
name # % = parmbytes/4
|
||||
all@vars equ
|
||||
current = 0
|
||||
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
|
||||
macro locals
|
||||
\{ virtual at ebp-localbytes+current
|
||||
macro label . \\{ deflocal@proc .,:, \\}
|
||||
struc db [val] \\{ \common deflocal@proc .,db,val \\}
|
||||
struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
|
||||
struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
|
||||
struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
|
||||
struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
|
||||
struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
|
||||
struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
|
||||
struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
|
||||
struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
|
||||
struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
|
||||
struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
|
||||
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
|
||||
macro endl
|
||||
\{ purge label
|
||||
restruc db,dw,dp,dd,dt,dq
|
||||
restruc rb,rw,rp,rd,rt,rq
|
||||
restruc byte,word,dword,pword,tword,qword
|
||||
current = $-(ebp-localbytes)
|
||||
end virtual \}
|
||||
macro ret operand
|
||||
\{ match any, operand \\{ retn operand \\}
|
||||
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs>
|
||||
\\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
|
||||
macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2
|
||||
end if \} }
|
||||
|
||||
macro defargs@proc [arg]
|
||||
{ common
|
||||
if ~ arg eq
|
||||
forward
|
||||
local ..arg,current@arg
|
||||
match argname:type, arg
|
||||
\{ current@arg equ argname
|
||||
label ..arg type
|
||||
argname equ ..arg
|
||||
if dqword eq type
|
||||
dd ?,?,?,?
|
||||
else if tbyte eq type
|
||||
dd ?,?,?
|
||||
else if qword eq type | pword eq type
|
||||
dd ?,?
|
||||
else
|
||||
dd ?
|
||||
end if \}
|
||||
match =current@arg,current@arg
|
||||
\{ current@arg equ arg
|
||||
arg equ ..arg
|
||||
..arg dd ? \}
|
||||
common
|
||||
args@proc equ current@arg
|
||||
forward
|
||||
restore current@arg
|
||||
common
|
||||
end if }
|
||||
|
||||
macro deflocal@proc name,def,[val]
|
||||
{ common
|
||||
match vars, all@vars \{ all@vars equ all@vars, \}
|
||||
all@vars equ all@vars name
|
||||
forward
|
||||
local ..var,..tmp
|
||||
..var def val
|
||||
match =?, val \{ ..tmp equ \}
|
||||
match any =dup (=?), val \{ ..tmp equ \}
|
||||
match tmp : value, ..tmp : val
|
||||
\{ tmp: end virtual
|
||||
initlocal@proc ..var,def value
|
||||
virtual at tmp\}
|
||||
common
|
||||
match first rest, ..var, \{ name equ first \} }
|
||||
|
||||
macro initlocal@proc name,def
|
||||
{ virtual at name
|
||||
def
|
||||
size@initlocal = $ - name
|
||||
end virtual
|
||||
position@initlocal = 0
|
||||
while size@initlocal > position@initlocal
|
||||
virtual at name
|
||||
def
|
||||
if size@initlocal - position@initlocal < 2
|
||||
current@initlocal = 1
|
||||
load byte@initlocal byte from name+position@initlocal
|
||||
else if size@initlocal - position@initlocal < 4
|
||||
current@initlocal = 2
|
||||
load word@initlocal word from name+position@initlocal
|
||||
else
|
||||
current@initlocal = 4
|
||||
load dword@initlocal dword from name+position@initlocal
|
||||
end if
|
||||
end virtual
|
||||
if current@initlocal = 1
|
||||
mov byte [name+position@initlocal],byte@initlocal
|
||||
else if current@initlocal = 2
|
||||
mov word [name+position@initlocal],word@initlocal
|
||||
else
|
||||
mov dword [name+position@initlocal],dword@initlocal
|
||||
end if
|
||||
position@initlocal = position@initlocal + current@initlocal
|
||||
end while }
|
||||
|
||||
macro endp
|
||||
{ purge ret,locals,endl
|
||||
finish@proc
|
||||
purge finish@proc
|
||||
restore regs@proc
|
||||
match all,args@proc \{ restore all \}
|
||||
restore args@proc
|
||||
match all,all@vars \{ restore all \} }
|
||||
|
||||
macro local [var]
|
||||
{ common
|
||||
locals
|
||||
forward done@local equ
|
||||
match varname[count]:vartype, var
|
||||
\{ match =BYTE, vartype \\{ varname rb count
|
||||
restore done@local \\}
|
||||
match =WORD, vartype \\{ varname rw count
|
||||
restore done@local \\}
|
||||
match =DWORD, vartype \\{ varname rd count
|
||||
restore done@local \\}
|
||||
match =PWORD, vartype \\{ varname rp count
|
||||
restore done@local \\}
|
||||
match =QWORD, vartype \\{ varname rq count
|
||||
restore done@local \\}
|
||||
match =TBYTE, vartype \\{ varname rt count
|
||||
restore done@local \\}
|
||||
match =DQWORD, vartype \\{ label varname dqword
|
||||
rq count+count
|
||||
restore done@local \\}
|
||||
match , done@local \\{ virtual
|
||||
varname vartype
|
||||
end virtual
|
||||
rb count*sizeof.\#vartype
|
||||
restore done@local \\} \}
|
||||
match :varname:vartype, done@local:var
|
||||
\{ match =BYTE, vartype \\{ varname db ?
|
||||
restore done@local \\}
|
||||
match =WORD, vartype \\{ varname dw ?
|
||||
restore done@local \\}
|
||||
match =DWORD, vartype \\{ varname dd ?
|
||||
restore done@local \\}
|
||||
match =PWORD, vartype \\{ varname dp ?
|
||||
restore done@local \\}
|
||||
match =QWORD, vartype \\{ varname dq ?
|
||||
restore done@local \\}
|
||||
match =TBYTE, vartype \\{ varname dt ?
|
||||
restore done@local \\}
|
||||
match =DQWORD, vartype \\{ label varname dqword
|
||||
dq ?,?
|
||||
restore done@local \\}
|
||||
match , done@local \\{ varname vartype
|
||||
restore done@local \\} \}
|
||||
match ,done@local
|
||||
\{ var
|
||||
restore done@local \}
|
||||
common
|
||||
endl }
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
|
||||
; Macroinstructions for defining data structures
|
||||
|
||||
macro struct name
|
||||
{ virtual at 0
|
||||
fields@struct equ name
|
||||
match child parent, name \{ fields@struct equ child,fields@\#parent \}
|
||||
sub@struct equ
|
||||
struc db [val] \{ \common define field@struct .,db,<val>
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
struc dw [val] \{ \common define field@struct .,dw,<val>
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
struc du [val] \{ \common define field@struct .,du,<val>
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
struc dd [val] \{ \common define field@struct .,dd,<val>
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
struc dp [val] \{ \common define field@struct .,dp,<val>
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
struc dq [val] \{ \common define field@struct .,dq,<val>
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
struc dt [val] \{ \common define field@struct .,dt,<val>
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
struc rb count \{ define field@struct .,db,count dup (?)
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
struc rw count \{ define field@struct .,dw,count dup (?)
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
struc rd count \{ define field@struct .,dd,count dup (?)
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
struc rp count \{ define field@struct .,dp,count dup (?)
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
struc rq count \{ define field@struct .,dq,count dup (?)
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
struc rt count \{ define field@struct .,dt,count dup (?)
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
macro db [val] \{ \common \local anonymous
|
||||
define field@struct anonymous,db,<val>
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
macro dw [val] \{ \common \local anonymous
|
||||
define field@struct anonymous,dw,<val>
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
macro du [val] \{ \common \local anonymous
|
||||
define field@struct anonymous,du,<val>
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
macro dd [val] \{ \common \local anonymous
|
||||
define field@struct anonymous,dd,<val>
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
macro dp [val] \{ \common \local anonymous
|
||||
define field@struct anonymous,dp,<val>
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
macro dq [val] \{ \common \local anonymous
|
||||
define field@struct anonymous,dq,<val>
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
macro dt [val] \{ \common \local anonymous
|
||||
define field@struct anonymous,dt,<val>
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
macro rb count \{ \local anonymous
|
||||
define field@struct anonymous,db,count dup (?)
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
macro rw count \{ \local anonymous
|
||||
define field@struct anonymous,dw,count dup (?)
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
macro rd count \{ \local anonymous
|
||||
define field@struct anonymous,dd,count dup (?)
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
macro rp count \{ \local anonymous
|
||||
define field@struct anonymous,dp,count dup (?)
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
macro rq count \{ \local anonymous
|
||||
define field@struct anonymous,dq,count dup (?)
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
macro rt count \{ \local anonymous
|
||||
define field@struct anonymous,dt,count dup (?)
|
||||
fields@struct equ fields@struct,field@struct \}
|
||||
macro union \{ fields@struct equ fields@struct,,union,<
|
||||
sub@struct equ union \}
|
||||
macro struct \{ fields@struct equ fields@struct,,substruct,<
|
||||
sub@struct equ substruct \} }
|
||||
|
||||
macro ends
|
||||
{ match , sub@struct \{ restruc db,dw,du,dd,dp,dq,dt
|
||||
restruc rb,rw,rd,rp,rq,rt
|
||||
purge db,dw,du,dd,dp,dq,dt
|
||||
purge rb,rw,rd,rp,rq,rt
|
||||
purge union,struct
|
||||
match name tail,fields@struct, \\{ if $
|
||||
display 'Error: definition of ',\\`name,' contains illegal instructions.',0Dh,0Ah
|
||||
err
|
||||
end if \\}
|
||||
match name=,fields,fields@struct \\{ fields@struct equ
|
||||
make@struct name,fields
|
||||
define fields@\\#name fields \\}
|
||||
end virtual \}
|
||||
match any, sub@struct \{ fields@struct equ fields@struct> \}
|
||||
restore sub@struct }
|
||||
|
||||
macro make@struct name,[field,type,def]
|
||||
{ common
|
||||
local define
|
||||
define equ name
|
||||
forward
|
||||
local sub
|
||||
match , field \{ make@substruct type,name,sub def
|
||||
define equ define,.,sub, \}
|
||||
match any, field \{ define equ define,.#field,type,<def> \}
|
||||
common
|
||||
match fields, define \{ define@struct fields \} }
|
||||
|
||||
macro define@struct name,[field,type,def]
|
||||
{ common
|
||||
virtual
|
||||
db `name
|
||||
load initial@struct byte from 0
|
||||
if initial@struct = '.'
|
||||
display 'Error: name of structure should not begin with a dot.',0Dh,0Ah
|
||||
err
|
||||
end if
|
||||
end virtual
|
||||
local list
|
||||
list equ
|
||||
forward
|
||||
if ~ field eq .
|
||||
name#field type def
|
||||
sizeof.#name#field = $ - name#field
|
||||
else
|
||||
label name#.#type
|
||||
rb sizeof.#type
|
||||
end if
|
||||
local value
|
||||
match any, list \{ list equ list, \}
|
||||
list equ list <value>
|
||||
common
|
||||
sizeof.#name = $
|
||||
restruc name
|
||||
match values, list \{
|
||||
struc name value \\{ \\local \\..base
|
||||
match any, fields@struct \\\{ fields@struct equ fields@struct,.,name,<values> \\\}
|
||||
match , fields@struct \\\{ label \\..base
|
||||
forward
|
||||
match , value \\\\{ field type def \\\\}
|
||||
match any, value \\\\{ field type value
|
||||
if ~ field eq .
|
||||
rb sizeof.#name#field - ($-field)
|
||||
end if \\\\}
|
||||
common label . at \\..base \\\}
|
||||
\\}
|
||||
macro name value \\{
|
||||
match any, fields@struct \\\{ \\\local anonymous
|
||||
fields@struct equ fields@struct,anonymous,name,<values> \\\}
|
||||
match , fields@struct \\\{
|
||||
forward
|
||||
match , value \\\\{ type def \\\\}
|
||||
match any, value \\\\{ \\\\local ..field
|
||||
..field = $
|
||||
type value
|
||||
if ~ field eq .
|
||||
rb sizeof.#name#field - ($-..field)
|
||||
end if \\\\}
|
||||
common \\\} \\} \} }
|
||||
|
||||
macro enable@substruct
|
||||
{ macro make@substruct substruct,parent,name,[field,type,def]
|
||||
\{ \common
|
||||
\local define
|
||||
define equ parent,name
|
||||
\forward
|
||||
\local sub
|
||||
match , field \\{ match any, type \\\{ enable@substruct
|
||||
make@substruct type,parent,sub def
|
||||
purge make@substruct
|
||||
define equ define,.,sub, \\\} \\}
|
||||
match any, field \\{ define equ define,.\#field,type,<def> \\}
|
||||
\common
|
||||
match fields, define \\{ define@\#substruct fields \\} \} }
|
||||
|
||||
enable@substruct
|
||||
|
||||
macro define@union parent,name,[field,type,def]
|
||||
{ common
|
||||
virtual at parent#.#name
|
||||
forward
|
||||
if ~ field eq .
|
||||
virtual at parent#.#name
|
||||
parent#field type def
|
||||
sizeof.#parent#field = $ - parent#field
|
||||
end virtual
|
||||
if sizeof.#parent#field > $ - parent#.#name
|
||||
rb sizeof.#parent#field - ($ - parent#.#name)
|
||||
end if
|
||||
else
|
||||
virtual at parent#.#name
|
||||
label parent#.#type
|
||||
type def
|
||||
end virtual
|
||||
label name#.#type at parent#.#name
|
||||
if sizeof.#type > $ - parent#.#name
|
||||
rb sizeof.#type - ($ - parent#.#name)
|
||||
end if
|
||||
end if
|
||||
common
|
||||
sizeof.#name = $ - parent#.#name
|
||||
end virtual
|
||||
struc name [value] \{ \common
|
||||
label .\#name
|
||||
last@union equ
|
||||
forward
|
||||
match any, last@union \\{ virtual at .\#name
|
||||
field type def
|
||||
end virtual \\}
|
||||
match , last@union \\{ match , value \\\{ field type def \\\}
|
||||
match any, value \\\{ field type value \\\} \\}
|
||||
last@union equ field
|
||||
common rb sizeof.#name - ($ - .\#name) \}
|
||||
macro name [value] \{ \common \local ..anonymous
|
||||
..anonymous name value \} }
|
||||
|
||||
macro define@substruct parent,name,[field,type,def]
|
||||
{ common
|
||||
virtual at parent#.#name
|
||||
forward
|
||||
if ~ field eq .
|
||||
parent#field type def
|
||||
sizeof.#parent#field = $ - parent#field
|
||||
else
|
||||
label parent#.#type
|
||||
rb sizeof.#type
|
||||
end if
|
||||
common
|
||||
sizeof.#name = $ - parent#.#name
|
||||
end virtual
|
||||
struc name value \{
|
||||
label .\#name
|
||||
forward
|
||||
match , value \\{ field type def \\}
|
||||
match any, value \\{ field type value
|
||||
if ~ field eq .
|
||||
rb sizeof.#parent#field - ($-field)
|
||||
end if \\}
|
||||
common \}
|
||||
macro name value \{ \local ..anonymous
|
||||
..anonymous name \} }
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,390 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2013. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; ftpc.asm - FTP client for KolibriOS ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr@kolibrios.org ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
format binary as ""
|
||||
|
||||
__DEBUG__ = 0
|
||||
__DEBUG_LEVEL__ = 1
|
||||
BUFFERSIZE = 1024
|
||||
|
||||
STATUS_CONNECTING = 0
|
||||
STATUS_CONNECTED = 1
|
||||
STATUS_NEEDPASSWORD = 1
|
||||
STATUS_LOGGED_IN = 3
|
||||
|
||||
use32
|
||||
; standard header
|
||||
db 'MENUET01' ; signature
|
||||
dd 1 ; header version
|
||||
dd start ; entry point
|
||||
dd i_end ; initialized size
|
||||
dd mem+0x1000 ; required memory
|
||||
dd mem+0x1000 ; stack pointer
|
||||
dd s ; parameters
|
||||
dd 0 ; path
|
||||
|
||||
include '../macros.inc'
|
||||
purge mov,add,sub
|
||||
include '../proc32.inc'
|
||||
include '../dll.inc'
|
||||
include '../debug-fdo.inc'
|
||||
include '../network.inc'
|
||||
|
||||
include 'usercommands.inc'
|
||||
include 'servercommands.inc'
|
||||
|
||||
; entry point
|
||||
start:
|
||||
|
||||
DEBUGF 1, "hello"
|
||||
; load libraries
|
||||
stdcall dll.Load, @IMPORT
|
||||
test eax, eax
|
||||
jnz exit
|
||||
; initialize console
|
||||
push 1
|
||||
call [con_start]
|
||||
push title
|
||||
push 25
|
||||
push 80
|
||||
push 25
|
||||
push 80
|
||||
call [con_init]
|
||||
|
||||
; Check for parameters
|
||||
cmp byte [s], 0
|
||||
jne resolve
|
||||
|
||||
main:
|
||||
call [con_cls]
|
||||
; Welcome user
|
||||
push str1
|
||||
call [con_write_asciiz]
|
||||
|
||||
; write prompt
|
||||
push str2
|
||||
call [con_write_asciiz]
|
||||
; read string
|
||||
mov esi, s
|
||||
push 256
|
||||
push esi
|
||||
call [con_gets]
|
||||
; check for exit
|
||||
test eax, eax
|
||||
jz done
|
||||
cmp byte [esi], 10
|
||||
jz done
|
||||
|
||||
resolve:
|
||||
|
||||
; delete terminating '\n'
|
||||
mov esi, s
|
||||
@@:
|
||||
lodsb
|
||||
cmp al, 0x20
|
||||
ja @r
|
||||
mov byte [esi-1], 0
|
||||
|
||||
; call [con_cls]
|
||||
push str3
|
||||
call [con_write_asciiz]
|
||||
push s
|
||||
call [con_write_asciiz]
|
||||
|
||||
; resolve name
|
||||
push esp ; reserve stack place
|
||||
push esp ; fourth parameter
|
||||
push 0 ; third parameter
|
||||
push 0 ; second parameter
|
||||
push s ; first parameter
|
||||
call [getaddrinfo]
|
||||
pop esi
|
||||
; test for error
|
||||
test eax, eax
|
||||
jnz fail
|
||||
|
||||
; write results
|
||||
push str8
|
||||
call [con_write_asciiz]
|
||||
; mov edi, esi
|
||||
|
||||
; convert IP address to decimal notation
|
||||
mov eax, [esi+addrinfo.ai_addr]
|
||||
mov eax, [eax+sockaddr_in.sin_addr]
|
||||
mov [sockaddr1.ip], eax
|
||||
push eax
|
||||
call [inet_ntoa]
|
||||
; write result
|
||||
push eax
|
||||
call [con_write_asciiz]
|
||||
; free allocated memory
|
||||
push esi
|
||||
call [freeaddrinfo]
|
||||
|
||||
push str9
|
||||
call [con_write_asciiz]
|
||||
|
||||
mcall socket, AF_INET4, SOCK_STREAM, 0
|
||||
cmp eax, -1
|
||||
jz fail2
|
||||
mov [socketnum], eax
|
||||
|
||||
mcall connect, [socketnum], sockaddr1, 18
|
||||
|
||||
mcall 40, 1 shl 7
|
||||
|
||||
mov [status], STATUS_CONNECTING
|
||||
mov [offset], buffer_ptr
|
||||
|
||||
wait_for_serverdata:
|
||||
mcall 10
|
||||
|
||||
call [con_get_flags]
|
||||
test eax, 0x200 ; con window closed?
|
||||
jnz exit
|
||||
|
||||
; receive socket data
|
||||
mcall recv, [socketnum], [offset], BUFFERSIZE, 0
|
||||
inc eax
|
||||
jz wait_for_serverdata
|
||||
dec eax
|
||||
jz wait_for_serverdata
|
||||
|
||||
; extract commands, copy them to "s" buffer
|
||||
add eax, buffer_ptr ; eax = end pointer
|
||||
mov esi, buffer_ptr ; esi = current pointer
|
||||
.nextcommand:
|
||||
mov edi, s
|
||||
.byteloop:
|
||||
cmp esi, eax
|
||||
jae wait_for_serverdata
|
||||
lodsb
|
||||
cmp al, 10 ; excellent, we might have a command
|
||||
je .got_command
|
||||
cmp al, 13 ; just ignore this crap
|
||||
je .byteloop
|
||||
stosb
|
||||
jmp .byteloop
|
||||
|
||||
; we have a newline check if its a command
|
||||
.got_command:
|
||||
xor al, al
|
||||
stosb
|
||||
; push esi eax
|
||||
|
||||
; print it to the screen
|
||||
pushd s
|
||||
call [con_write_asciiz]
|
||||
pushd str4 ; newline
|
||||
call [con_write_asciiz]
|
||||
|
||||
; cmp byte[s+2], " "
|
||||
; jne .not_command
|
||||
|
||||
lea ecx, [edi - s]
|
||||
call server_parser
|
||||
|
||||
; .not_command:
|
||||
; pop eax esi
|
||||
; jmp .nextcommand
|
||||
|
||||
|
||||
|
||||
|
||||
wait_for_usercommand:
|
||||
|
||||
cmp [status], STATUS_CONNECTED
|
||||
je .connected
|
||||
|
||||
cmp [status], STATUS_NEEDPASSWORD
|
||||
je .needpass
|
||||
|
||||
|
||||
; write prompt
|
||||
push str2
|
||||
call [con_write_asciiz]
|
||||
; read string
|
||||
mov esi, s
|
||||
push 256
|
||||
push esi
|
||||
call [con_gets]
|
||||
|
||||
call [con_get_flags]
|
||||
test eax, 0x200 ; con window closed?
|
||||
jnz exit
|
||||
|
||||
cmp dword[s], "list"
|
||||
je cmd_list
|
||||
|
||||
cmp dword[s], "help"
|
||||
je cmd_help
|
||||
|
||||
push str_unkown
|
||||
call [con_write_asciiz]
|
||||
|
||||
jmp wait_for_usercommand
|
||||
|
||||
|
||||
.connected:
|
||||
|
||||
push str_user
|
||||
call [con_write_asciiz]
|
||||
|
||||
mov dword[s], "USER"
|
||||
mov byte[s+4], " "
|
||||
|
||||
jmp .send
|
||||
|
||||
|
||||
.needpass:
|
||||
push str_pass
|
||||
call [con_write_asciiz]
|
||||
|
||||
mov dword[s], "PASS"
|
||||
mov byte[s+4], " "
|
||||
|
||||
.send:
|
||||
; read string
|
||||
mov esi, s+5
|
||||
push 256
|
||||
push esi
|
||||
call [con_gets]
|
||||
|
||||
mov edi, s+5
|
||||
mov ecx, 256
|
||||
xor al, al
|
||||
repne scasb
|
||||
lea esi, [edi-s-1]
|
||||
mcall send, [socketnum], s
|
||||
|
||||
jmp wait_for_usercommand
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
open_dataconnection:
|
||||
cmp [status], STATUS_LOGGED_IN
|
||||
jne .fail
|
||||
|
||||
mov dword[s], "PASV"
|
||||
mov byte[s+4], 10
|
||||
mcall send, [socketnum], s, 5
|
||||
|
||||
ret
|
||||
|
||||
.fail:
|
||||
push str6
|
||||
call [con_write_asciiz]
|
||||
|
||||
ret
|
||||
|
||||
|
||||
fail2:
|
||||
push str6
|
||||
call [con_write_asciiz]
|
||||
|
||||
jmp fail.wait
|
||||
|
||||
fail:
|
||||
push str5
|
||||
call [con_write_asciiz]
|
||||
.wait:
|
||||
push str10
|
||||
call [con_write_asciiz]
|
||||
call [con_getch2]
|
||||
jmp main
|
||||
|
||||
done:
|
||||
push 1
|
||||
call [con_exit]
|
||||
exit:
|
||||
|
||||
mcall close, [socketnum]
|
||||
mcall -1
|
||||
|
||||
|
||||
|
||||
; data
|
||||
title db 'FTP client',0
|
||||
str1 db 'FTP client for KolibriOS v0.01',10,10,'Please enter ftp server address.',10,0
|
||||
str2 db '> ',0
|
||||
str3 db 'Connecting to ',0
|
||||
str4 db 10,0
|
||||
str5 db 10,'Name resolution failed.',10,0
|
||||
str6 db 10,'Socket error.',10,0
|
||||
str8 db ' (',0
|
||||
str9 db ')',10,0
|
||||
str10 db 'Push any key to continue.',0
|
||||
str_user db "username: ",0
|
||||
str_pass db "password: ",0
|
||||
str_unkown db "unkown command",10,0
|
||||
str_help db "available commands:",10,10
|
||||
db "help list",10,0
|
||||
|
||||
str_open db "opening data socket",10,0
|
||||
|
||||
sockaddr1:
|
||||
dw AF_INET4
|
||||
.port dw 0x1500 ; 21
|
||||
.ip dd 0
|
||||
rb 10
|
||||
|
||||
sockaddr2:
|
||||
dw AF_INET4
|
||||
.port dw 0
|
||||
.ip dd 0
|
||||
rb 10
|
||||
|
||||
include_debug_strings ; ALWAYS present in data section
|
||||
|
||||
|
||||
|
||||
; import
|
||||
align 4
|
||||
@IMPORT:
|
||||
|
||||
library network, 'network.obj', console, 'console.obj'
|
||||
|
||||
import network, \
|
||||
getaddrinfo, 'getaddrinfo', \
|
||||
freeaddrinfo, 'freeaddrinfo', \
|
||||
inet_ntoa, 'inet_ntoa'
|
||||
|
||||
import console, \
|
||||
con_start, 'START', \
|
||||
con_init, 'con_init', \
|
||||
con_write_asciiz,'con_write_asciiz', \
|
||||
con_exit, 'con_exit', \
|
||||
con_gets, 'con_gets',\
|
||||
con_cls, 'con_cls',\
|
||||
con_getch2, 'con_getch2',\
|
||||
con_set_cursor_pos, 'con_set_cursor_pos',\
|
||||
con_write_string, 'con_write_string',\
|
||||
con_get_flags, 'con_get_flags'
|
||||
|
||||
|
||||
i_end:
|
||||
|
||||
active_passive db ?
|
||||
socketnum dd ?
|
||||
datasocket dd ?
|
||||
buffer_ptr rb 2*BUFFERSIZE
|
||||
status db ?
|
||||
offset dd ?
|
||||
|
||||
s rb 1024
|
||||
|
||||
mem:
|
||||
@@ -0,0 +1,114 @@
|
||||
server_parser:
|
||||
|
||||
; Commands are always 3 numbers and followed by a space
|
||||
; If a server decides it needs multiline output,
|
||||
; first lines will have a dash instead of space after numbers,
|
||||
; thus they are simply ignored.
|
||||
|
||||
cmp dword[s], "150 "
|
||||
je data_ok
|
||||
|
||||
cmp dword[s], "220 "
|
||||
je welcome
|
||||
|
||||
cmp dword[s], "227 "
|
||||
je pasv_ok
|
||||
|
||||
cmp dword[s], "230 "
|
||||
je login_ok
|
||||
|
||||
cmp dword[s], "331 "
|
||||
je pass
|
||||
|
||||
ret
|
||||
|
||||
|
||||
welcome:
|
||||
|
||||
mov [status], STATUS_CONNECTED
|
||||
ret
|
||||
|
||||
|
||||
pass:
|
||||
|
||||
mov [status], STATUS_NEEDPASSWORD
|
||||
ret
|
||||
|
||||
|
||||
login_ok:
|
||||
|
||||
mov [status], STATUS_LOGGED_IN
|
||||
ret
|
||||
|
||||
|
||||
pasv_ok:
|
||||
|
||||
sub ecx, 5
|
||||
jb .fail
|
||||
mov al, "("
|
||||
mov edi, s + 5
|
||||
repne scasb
|
||||
|
||||
mcall socket, AF_INET4, SOCK_STREAM, 0
|
||||
cmp eax, -1
|
||||
je fail
|
||||
mov [datasocket], eax
|
||||
|
||||
mov esi, edi
|
||||
call ascii_dec
|
||||
mov byte[sockaddr2.ip+0], bl
|
||||
call ascii_dec
|
||||
mov byte[sockaddr2.ip+1], bl
|
||||
call ascii_dec
|
||||
mov byte[sockaddr2.ip+2], bl
|
||||
call ascii_dec
|
||||
mov byte[sockaddr2.ip+3], bl
|
||||
|
||||
call ascii_dec
|
||||
mov byte[sockaddr2.port+1], bl
|
||||
call ascii_dec
|
||||
mov byte[sockaddr2.port+0], bl
|
||||
|
||||
push str_open
|
||||
call [con_write_asciiz]
|
||||
|
||||
mcall connect, [datasocket], sockaddr2, 18
|
||||
|
||||
.fail:
|
||||
ret
|
||||
|
||||
|
||||
data_ok:
|
||||
|
||||
mcall recv, [datasocket], buffer_ptr, BUFFERSIZE, 0 ; fixme: use other buffer
|
||||
inc eax
|
||||
jz .fail
|
||||
dec eax
|
||||
jz .fail
|
||||
|
||||
mov byte[buffer_ptr + eax], 0
|
||||
pushd buffer_ptr
|
||||
call [con_write_asciiz]
|
||||
|
||||
.fail:
|
||||
ret
|
||||
|
||||
|
||||
ascii_dec:
|
||||
|
||||
xor ebx, ebx
|
||||
mov cl, 3
|
||||
.loop:
|
||||
lodsb
|
||||
sub al, '0'
|
||||
jb .done
|
||||
cmp al, 9
|
||||
ja .done
|
||||
lea ebx, [ebx*4+ebx]
|
||||
shl ebx, 1
|
||||
add bl, al
|
||||
dec cl
|
||||
jnz .loop
|
||||
|
||||
.done:
|
||||
ret
|
||||
@@ -0,0 +1,17 @@
|
||||
cmd_list:
|
||||
|
||||
call open_dataconnection
|
||||
|
||||
mov dword[s], "LIST"
|
||||
mov word[s+4], 0x0d0a
|
||||
mcall send, [socketnum], s, 6
|
||||
|
||||
jmp wait_for_serverdata
|
||||
|
||||
|
||||
cmd_help:
|
||||
|
||||
push str_help
|
||||
call [con_write_asciiz]
|
||||
|
||||
jmp wait_for_usercommand
|
||||
@@ -78,6 +78,21 @@ window_refresh:
|
||||
ret
|
||||
|
||||
|
||||
window_updated:
|
||||
|
||||
mov edi, [window_print]
|
||||
test [edi + window.flags], FLAG_UPDATED
|
||||
jnz .skip
|
||||
|
||||
or [edi + window.flags], FLAG_UPDATED
|
||||
|
||||
; now play a sound :)
|
||||
|
||||
.skip:
|
||||
|
||||
ret
|
||||
|
||||
|
||||
print_text: ; eax = start ptr
|
||||
; dl = end char
|
||||
pusha
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -178,16 +178,16 @@ shmem_list:
|
||||
.fd dd shmem_list
|
||||
|
||||
dll_list:
|
||||
.bk dd dll_list
|
||||
.fd dd dll_list
|
||||
|
||||
pcidev_list:
|
||||
.bk dd pcidev_list
|
||||
.fd dd pcidev_list
|
||||
|
||||
MAX_DEFAULT_DLL_ADDR = 0x80000000
|
||||
MIN_DEFAULT_DLL_ADDR = 0x70000000
|
||||
dll_cur_addr dd MIN_DEFAULT_DLL_ADDR
|
||||
.bk dd dll_list
|
||||
.fd dd dll_list
|
||||
|
||||
pcidev_list:
|
||||
.bk dd pcidev_list
|
||||
.fd dd pcidev_list
|
||||
|
||||
MAX_DEFAULT_DLL_ADDR = 0x80000000
|
||||
MIN_DEFAULT_DLL_ADDR = 0x70000000
|
||||
dll_cur_addr dd MIN_DEFAULT_DLL_ADDR
|
||||
|
||||
; supported videomodes
|
||||
|
||||
@@ -500,4 +500,5 @@ BiosDisksData rb 200h
|
||||
BiosDiskCaches rb 80h*(cache_ide1-cache_ide0)
|
||||
BiosDiskPartitions rd 80h
|
||||
|
||||
tetten:
|
||||
IncludeUGlobals
|
||||
|
||||
@@ -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
|
||||
@@ -789,13 +790,13 @@ end if
|
||||
; call build_scheduler; sys32.inc
|
||||
|
||||
; mov esi, boot_devices
|
||||
; call boot_log
|
||||
|
||||
mov [pci_access_enabled], 1
|
||||
call pci_enum
|
||||
|
||||
; SET PRELIMINARY WINDOW STACK AND POSITIONS
|
||||
|
||||
; call boot_log
|
||||
|
||||
mov [pci_access_enabled], 1
|
||||
call pci_enum
|
||||
|
||||
; SET PRELIMINARY WINDOW STACK AND POSITIONS
|
||||
|
||||
mov esi, boot_windefs
|
||||
call boot_log
|
||||
call set_window_defaults
|
||||
@@ -4615,16 +4616,16 @@ sys_msg_board_dword:
|
||||
pop eax
|
||||
pop ecx
|
||||
loop @b
|
||||
popad
|
||||
ret
|
||||
|
||||
msg_board_data_size = 65536 ; Must be power of two
|
||||
|
||||
uglobal
|
||||
msg_board_data rb msg_board_data_size
|
||||
msg_board_count dd 0x0
|
||||
endg
|
||||
|
||||
popad
|
||||
ret
|
||||
|
||||
msg_board_data_size = 65536 ; Must be power of two
|
||||
|
||||
uglobal
|
||||
msg_board_data rb msg_board_data_size
|
||||
msg_board_count dd 0x0
|
||||
endg
|
||||
|
||||
sys_msg_board:
|
||||
|
||||
; eax=1 : write : bl byte to write
|
||||
@@ -4651,13 +4652,13 @@ if defined debug_com_base
|
||||
pop ax dx
|
||||
|
||||
end if
|
||||
|
||||
mov [msg_board_data+ecx], bl
|
||||
inc ecx
|
||||
and ecx, msg_board_data_size - 1
|
||||
mov [msg_board_count], ecx
|
||||
mov [check_idle_semaphore], 5
|
||||
ret
|
||||
|
||||
mov [msg_board_data+ecx], bl
|
||||
inc ecx
|
||||
and ecx, msg_board_data_size - 1
|
||||
mov [msg_board_count], ecx
|
||||
mov [check_idle_semaphore], 5
|
||||
ret
|
||||
.smbl1:
|
||||
cmp eax, 2
|
||||
jne .smbl2
|
||||
@@ -4744,14 +4745,14 @@ align 4
|
||||
movzx ecx, cl
|
||||
lea ecx, [hotkey_scancodes+ecx*4]
|
||||
mov edx, [ecx]
|
||||
mov [eax], edx
|
||||
mov [ecx], eax
|
||||
mov [eax+12], ecx
|
||||
test edx, edx
|
||||
jz @f
|
||||
mov [edx+12], eax
|
||||
@@:
|
||||
and dword [esp+32], 0
|
||||
mov [eax], edx
|
||||
mov [ecx], eax
|
||||
mov [eax+12], ecx
|
||||
test edx, edx
|
||||
jz @f
|
||||
mov [edx+12], eax
|
||||
@@:
|
||||
and dword [esp+32], 0
|
||||
ret
|
||||
;-----------------------------------------------------------------------------
|
||||
align 4
|
||||
|
||||
@@ -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)
|
||||
|
||||
+14
-35
@@ -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
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,645 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; ARP.INC ;;
|
||||
;; ;;
|
||||
;; Part of the tcp/ip network stack for KolibriOS ;;
|
||||
;; ;;
|
||||
;; Based on the work of [Johnny_B] and [smb] ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr@kolibrios.org ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June- 1991 ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
$Revision: 3386 $
|
||||
|
||||
ARP_NO_ENTRY = 0
|
||||
ARP_VALID_MAPPING = 1
|
||||
ARP_AWAITING_RESPONSE = 2
|
||||
ARP_RESPONSE_TIMEOUT = 3
|
||||
|
||||
ARP_REQUEST_TTL = 31 ; 20 s
|
||||
ARP_ENTRY_TTL = 937 ; 600 s
|
||||
ARP_STATIC_ENTRY = -1
|
||||
|
||||
ARP_REQ_OPCODE = 0x0100 ; request
|
||||
ARP_REP_OPCODE = 0x0200 ; reply
|
||||
|
||||
ARP_TABLE_SIZE = 20 ; Size of table
|
||||
|
||||
struct ARP_entry
|
||||
|
||||
IP dd ?
|
||||
MAC dp ?
|
||||
Status dw ?
|
||||
TTL dw ?
|
||||
|
||||
ends
|
||||
|
||||
struct ARP_header
|
||||
|
||||
HardwareType dw ?
|
||||
ProtocolType dw ?
|
||||
HardwareSize db ?
|
||||
ProtocolSize db ?
|
||||
Opcode dw ?
|
||||
SenderMAC dp ?
|
||||
SenderIP dd ?
|
||||
TargetMAC dp ?
|
||||
TargetIP dd ?
|
||||
|
||||
ends
|
||||
|
||||
align 4
|
||||
uglobal
|
||||
|
||||
NumARP dd ?
|
||||
|
||||
ARP_table rb ARP_TABLE_SIZE * sizeof.ARP_entry ; TODO: separate ARP table and stats per interface
|
||||
|
||||
ARP_PACKETS_TX rd MAX_NET_DEVICES
|
||||
ARP_PACKETS_RX rd MAX_NET_DEVICES
|
||||
ARP_CONFLICTS rd MAX_NET_DEVICES
|
||||
|
||||
|
||||
endg
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ARP_init
|
||||
;
|
||||
; This function resets all ARP variables
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
macro ARP_init {
|
||||
|
||||
xor eax, eax
|
||||
mov [NumARP], eax
|
||||
|
||||
mov edi, ARP_PACKETS_TX
|
||||
mov ecx, 3*MAX_NET_DEVICES
|
||||
rep stosd
|
||||
|
||||
}
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
;
|
||||
; ARP_decrease_entry_ttls
|
||||
;
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
macro ARP_decrease_entry_ttls {
|
||||
|
||||
local .loop
|
||||
local .exit
|
||||
|
||||
; The TTL field is decremented every second, and is deleted when it reaches 0.
|
||||
; It is refreshed every time a packet is received.
|
||||
; If the TTL field is 0xFFFF it is a static entry and is never deleted.
|
||||
; The status field can be the following values:
|
||||
; 0x0000 entry not used
|
||||
; 0x0001 entry holds a valid mapping
|
||||
; 0x0002 entry contains an IP address, awaiting ARP response
|
||||
; 0x0003 No response received to ARP request.
|
||||
; The last status value is provided to allow the network layer to delete
|
||||
; a packet that is queued awaiting an ARP response
|
||||
|
||||
mov ecx, [NumARP]
|
||||
test ecx, ecx
|
||||
jz .exit
|
||||
|
||||
mov esi, ARP_table
|
||||
.loop:
|
||||
cmp [esi + ARP_entry.TTL], ARP_STATIC_ENTRY
|
||||
je .next
|
||||
|
||||
dec [esi + ARP_entry.TTL]
|
||||
jz .time_out
|
||||
|
||||
.next:
|
||||
add esi, sizeof.ARP_entry
|
||||
dec ecx
|
||||
jnz .loop
|
||||
jmp .exit
|
||||
|
||||
.time_out:
|
||||
cmp [esi + ARP_entry.Status], ARP_AWAITING_RESPONSE
|
||||
je .response_timeout
|
||||
|
||||
push esi ecx
|
||||
call ARP_del_entry
|
||||
pop ecx esi
|
||||
|
||||
jmp .next
|
||||
|
||||
.response_timeout:
|
||||
mov [esi + ARP_entry.Status], ARP_RESPONSE_TIMEOUT
|
||||
mov [esi + ARP_entry.TTL], 10
|
||||
|
||||
jmp .next
|
||||
|
||||
.exit:
|
||||
|
||||
}
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ARP_input
|
||||
;
|
||||
; IN: Pointer to buffer in [esp]
|
||||
; size of buffer in [esp+4]
|
||||
; packet size (without ethernet header) in ecx
|
||||
; packet ptr in edx
|
||||
; device ptr in ebx
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
ARP_input:
|
||||
|
||||
;-----------------------------------------
|
||||
; Check validity and print some debug info
|
||||
|
||||
cmp ecx, sizeof.ARP_header
|
||||
jb .exit
|
||||
|
||||
call NET_ptr_to_num
|
||||
cmp edi, -1
|
||||
jz .exit
|
||||
|
||||
inc [ARP_PACKETS_RX + 4*edi] ; update stats
|
||||
|
||||
DEBUGF 1,"ARP_input: got packet from %u.%u.%u.%u through device %u\n",\
|
||||
[edx + ARP_header.SenderIP]:1, [edx + ARP_header.SenderIP + 1]:1,\
|
||||
[edx + ARP_header.SenderIP + 2]:1, [edx + ARP_header.SenderIP + 3]:1, edi
|
||||
|
||||
;------------------------------
|
||||
; First, check for IP collision
|
||||
|
||||
mov eax, [edx + ARP_header.SenderIP]
|
||||
cmp eax, [IP_LIST + 4*edi]
|
||||
je .collision
|
||||
|
||||
;---------------------
|
||||
; Handle reply packets
|
||||
|
||||
cmp [edx + ARP_header.Opcode], ARP_REP_OPCODE
|
||||
jne .maybe_request
|
||||
|
||||
DEBUGF 1,"ARP_input: It's a reply\n"
|
||||
|
||||
mov ecx, [NumARP]
|
||||
test ecx, ecx
|
||||
jz .exit
|
||||
|
||||
mov esi, ARP_table
|
||||
.loop:
|
||||
cmp [esi + ARP_entry.IP], eax
|
||||
je .gotit
|
||||
add esi, sizeof.ARP_entry
|
||||
dec ecx
|
||||
jnz .loop
|
||||
|
||||
DEBUGF 1,"ARP_input: no matching entry found\n"
|
||||
jmp .exit
|
||||
|
||||
.gotit:
|
||||
DEBUGF 1,"ARP_input: found matching entry\n"
|
||||
|
||||
cmp [esi + ARP_entry.TTL], ARP_STATIC_ENTRY ; if it is a static entry, dont touch it
|
||||
je .exit
|
||||
|
||||
DEBUGF 1,"ARP_input: updating entry\n"
|
||||
|
||||
mov [esi + ARP_entry.Status], ARP_VALID_MAPPING
|
||||
mov [esi + ARP_entry.TTL], ARP_ENTRY_TTL
|
||||
|
||||
mov eax, dword [edx + ARP_header.SenderMAC]
|
||||
mov dword [esi + ARP_entry.MAC], eax
|
||||
mov cx, word [edx + ARP_header.SenderMAC + 4]
|
||||
mov word [esi + ARP_entry.MAC + 4], cx
|
||||
|
||||
jmp .exit
|
||||
|
||||
;-----------------------
|
||||
; Handle request packets
|
||||
|
||||
.maybe_request:
|
||||
cmp [edx + ARP_header.Opcode], ARP_REQ_OPCODE
|
||||
jne .exit
|
||||
|
||||
DEBUGF 1,"ARP_input: its a request\n"
|
||||
|
||||
mov eax, [IP_LIST + 4*edi]
|
||||
cmp eax, [edx + ARP_header.TargetIP] ; Is it looking for my IP address?
|
||||
jne .exit
|
||||
|
||||
push eax
|
||||
push edi
|
||||
|
||||
; OK, it is a request for one of our MAC addresses.
|
||||
; Build the frame and send it. We can reuse the buffer. (faster then using ARP_create_packet)
|
||||
|
||||
lea esi, [edx + ARP_header.SenderMAC]
|
||||
lea edi, [edx + ARP_header.TargetMAC]
|
||||
movsd ; Move Sender Mac to Dest MAC
|
||||
movsw ;
|
||||
movsd ; Move sender IP to Dest IP
|
||||
|
||||
pop esi
|
||||
mov esi, [NET_DRV_LIST + 4*esi]
|
||||
lea esi, [esi + ETH_DEVICE.mac]
|
||||
lea edi, [edx + ARP_header.SenderMAC]
|
||||
movsd ; Copy MAC address from in MAC_LIST
|
||||
movsw ;
|
||||
pop eax
|
||||
stosd ; Write our IP
|
||||
|
||||
mov [edx + ARP_header.Opcode], ARP_REP_OPCODE
|
||||
|
||||
; Now, Fill in ETHERNET header
|
||||
|
||||
mov edi, [esp]
|
||||
lea esi, [edx + ARP_header.TargetMAC]
|
||||
movsd
|
||||
movsw
|
||||
lea esi, [edx + ARP_header.SenderMAC]
|
||||
movsd
|
||||
movsw
|
||||
; mov ax , ETHER_ARP ; It's already there, I'm sure of it!
|
||||
; stosw
|
||||
|
||||
DEBUGF 1,"ARP_input: Sending reply\n"
|
||||
|
||||
call [ebx + NET_DEVICE.transmit]
|
||||
ret
|
||||
|
||||
.collision:
|
||||
inc [ARP_CONFLICTS + 4*edi]
|
||||
DEBUGF 1,"ARP_input: IP address conflict detected!\n"
|
||||
|
||||
.exit:
|
||||
call kernel_free
|
||||
add esp, 4 ; pop (balance stack)
|
||||
|
||||
DEBUGF 1,"ARP_input: exiting\n"
|
||||
ret
|
||||
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
;
|
||||
; ARP_output_request
|
||||
;
|
||||
; IN: ip in eax
|
||||
; device in edi
|
||||
; OUT: /
|
||||
;
|
||||
;---------------------------------------------------------------------------
|
||||
align 4
|
||||
ARP_output_request:
|
||||
|
||||
push eax ; DestIP
|
||||
pushd [IP_LIST + edi] ; SenderIP
|
||||
inc [ARP_PACKETS_TX + edi] ; assume we will succeed
|
||||
|
||||
DEBUGF 1,"ARP_output_request: ip=%u.%u.%u.%u\n",\
|
||||
[esp + 4]:1, [esp + 5]:1, [esp + 6]:1, [esp + 7]:1
|
||||
|
||||
mov ebx, [NET_DRV_LIST + edi] ; device ptr
|
||||
|
||||
lea eax, [ebx + ETH_DEVICE.mac] ; local device mac
|
||||
mov edx, ETH_BROADCAST ; broadcast mac
|
||||
mov ecx, sizeof.ARP_header
|
||||
mov di, ETHER_ARP
|
||||
call ETH_output
|
||||
jz .exit
|
||||
|
||||
mov ecx, eax
|
||||
|
||||
mov [edi + ARP_header.HardwareType], 0x0100 ; Ethernet
|
||||
mov [edi + ARP_header.ProtocolType], 0x0008 ; IP
|
||||
mov [edi + ARP_header.HardwareSize], 6 ; MAC-addr length
|
||||
mov [edi + ARP_header.ProtocolSize], 4 ; IP-addr length
|
||||
mov [edi + ARP_header.Opcode], ARP_REQ_OPCODE ; Request
|
||||
|
||||
add edi, ARP_header.SenderMAC
|
||||
|
||||
lea esi, [ebx + ETH_DEVICE.mac] ; SenderMac
|
||||
movsw ;
|
||||
movsd ;
|
||||
pop eax ; SenderIP
|
||||
stosd ;
|
||||
|
||||
mov eax, -1 ; DestMac
|
||||
stosd ;
|
||||
stosw ;
|
||||
pop eax ; DestIP
|
||||
stosd ;
|
||||
|
||||
DEBUGF 1,"ARP_output_request: device=%x\n", ebx
|
||||
|
||||
push edx ecx
|
||||
call [ebx + NET_DEVICE.transmit]
|
||||
ret
|
||||
|
||||
.exit:
|
||||
add esp, 4 + 4
|
||||
DEBUGF 1,"ARP_output_request: failed\n"
|
||||
sub eax, eax
|
||||
ret
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ARP_add_entry (or update)
|
||||
;
|
||||
; IN: esi = ptr to entry (can easily be made on the stack)
|
||||
; OUT: eax = entry #, -1 on error
|
||||
; edi = ptr to newly created entry
|
||||
;
|
||||
;----------------------------------------------------------------- ; TODO: use a mutex
|
||||
align 4
|
||||
ARP_add_entry:
|
||||
|
||||
DEBUGF 1,"ARP_add_entry: "
|
||||
|
||||
mov ecx, [NumARP]
|
||||
cmp ecx, ARP_TABLE_SIZE ; list full ?
|
||||
jae .error
|
||||
|
||||
xor eax, eax
|
||||
mov edi, ARP_table
|
||||
mov ecx, [esi + ARP_entry.IP]
|
||||
.loop:
|
||||
cmp [edi + ARP_entry.Status], ARP_NO_ENTRY ; is this slot empty?
|
||||
je .add
|
||||
|
||||
cmp [edi + ARP_entry.IP], ecx ; if not, check if it doesnt collide
|
||||
jne .maybe_next
|
||||
|
||||
cmp [edi + ARP_entry.TTL], ARP_STATIC_ENTRY ; ok, its the same IP, update it if not static
|
||||
jne .add
|
||||
|
||||
.maybe_next: ; try the next slot
|
||||
add edi, sizeof.ARP_entry
|
||||
inc eax
|
||||
cmp eax, ARP_TABLE_SIZE
|
||||
jae .error
|
||||
jmp .loop
|
||||
|
||||
.add:
|
||||
mov ecx, sizeof.ARP_entry/2
|
||||
rep movsw
|
||||
inc [NumARP]
|
||||
sub edi, sizeof.ARP_entry
|
||||
DEBUGF 1,"entry=%u\n", eax
|
||||
|
||||
ret
|
||||
|
||||
.error:
|
||||
DEBUGF 1,"failed\n"
|
||||
mov eax, -1
|
||||
ret
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ARP_del_entry
|
||||
;
|
||||
; IN: esi = ptr to arp entry
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
ARP_del_entry:
|
||||
|
||||
DEBUGF 1,"ARP_del_entry: entry=%x entrys=%u\n", esi, [NumARP]
|
||||
DEBUGF 1,"ARP_del_entry: IP=%u.%u.%u.%u\n", \
|
||||
[esi + ARP_entry.IP]:1, [esi + ARP_entry.IP + 1]:1, [esi + ARP_entry.IP + 2]:1, [esi + ARP_entry.IP + 3]:1
|
||||
|
||||
mov ecx, ARP_table + (ARP_TABLE_SIZE - 1) * sizeof.ARP_entry
|
||||
sub ecx, esi
|
||||
shr ecx, 1
|
||||
|
||||
mov edi, esi
|
||||
add esi, sizeof.ARP_entry
|
||||
rep movsw
|
||||
|
||||
xor eax, eax
|
||||
mov ecx, sizeof.ARP_entry/2
|
||||
rep stosw
|
||||
|
||||
dec [NumARP]
|
||||
DEBUGF 1,"ARP_del_entry: success\n"
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ARP_IP_to_MAC
|
||||
;
|
||||
; This function translates an IP address to a MAC address
|
||||
;
|
||||
; IN: eax = IPv4 address
|
||||
; edi = device number
|
||||
; OUT: eax = -1 on error, -2 means request send
|
||||
; else, ax = first two bytes of mac (high 16 bits of eax will be 0)
|
||||
; ebx = last four bytes of mac
|
||||
; edi = unchanged
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
ARP_IP_to_MAC:
|
||||
|
||||
DEBUGF 1,"ARP_IP_to_MAC: %u.%u", al, ah
|
||||
rol eax, 16
|
||||
DEBUGF 1,".%u.%u\n", al, ah
|
||||
rol eax, 16
|
||||
|
||||
cmp eax, 0xffffffff
|
||||
je .broadcast
|
||||
|
||||
;--------------------------------
|
||||
; Try to find the IP in ARP_table
|
||||
|
||||
mov ecx, [NumARP]
|
||||
test ecx, ecx
|
||||
jz .not_in_list
|
||||
mov esi, ARP_table + ARP_entry.IP
|
||||
.scan_loop:
|
||||
cmp [esi], eax
|
||||
je .found_it
|
||||
add esi, sizeof.ARP_entry
|
||||
loop .scan_loop
|
||||
|
||||
.not_in_list:
|
||||
DEBUGF 1,"ARP_IP_to_MAC: preparing for ARP request\n"
|
||||
|
||||
;--------------------
|
||||
; Send an ARP request
|
||||
|
||||
push eax edi ; save IP for ARP_output_request
|
||||
|
||||
; Now create the ARP entry
|
||||
pushw ARP_REQUEST_TTL ; TTL
|
||||
pushw ARP_AWAITING_RESPONSE ; status
|
||||
pushd 0 ; mac
|
||||
pushw 0
|
||||
pushd eax ; ip
|
||||
mov esi, esp
|
||||
call ARP_add_entry
|
||||
add esp, sizeof.ARP_entry ; clear the entry from stack
|
||||
|
||||
cmp eax, -1 ; did ARP_add_entry fail?
|
||||
je .full
|
||||
|
||||
mov esi, edi
|
||||
pop edi eax ; IP in eax, device number in edi, for ARP_output_request
|
||||
|
||||
push esi edi
|
||||
call ARP_output_request ; And send a request
|
||||
pop edi esi
|
||||
|
||||
;-----------------------------------------------
|
||||
; At this point, we got an ARP entry in the list
|
||||
.found_it:
|
||||
cmp [esi + ARP_entry.Status], ARP_VALID_MAPPING ; Does it have a MAC assigned?
|
||||
je .valid
|
||||
|
||||
if ARP_BLOCK
|
||||
|
||||
cmp [esi + ARP_entry.Status], ARP_AWAITING_RESPONSE ; Are we waiting for reply from remote end?
|
||||
jne .give_up
|
||||
push esi
|
||||
mov esi, 10 ; wait 10 ms
|
||||
call delay_ms
|
||||
pop esi
|
||||
jmp .found_it ; now check again
|
||||
|
||||
else
|
||||
|
||||
jmp .give_up
|
||||
|
||||
end if
|
||||
|
||||
.valid:
|
||||
DEBUGF 1,"ARP_IP_to_MAC: found MAC\n"
|
||||
movzx eax, word[esi + ARP_entry.MAC]
|
||||
mov ebx, dword[esi + ARP_entry.MAC + 2]
|
||||
ret
|
||||
|
||||
.full:
|
||||
DEBUGF 1,"ARP_IP_to_MAC: table is full!\n"
|
||||
add esp, 8
|
||||
.give_up:
|
||||
DEBUGF 1,"ARP_IP_to_MAC: entry has no valid mapping!\n"
|
||||
mov eax, -1
|
||||
ret
|
||||
|
||||
.broadcast:
|
||||
mov eax, 0x0000ffff
|
||||
mov ebx, 0xffffffff
|
||||
ret
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ARP_API
|
||||
;
|
||||
; This function is called by system function 75
|
||||
;
|
||||
; IN: subfunction number in bl
|
||||
; device number in bh
|
||||
; ecx, edx, .. depends on subfunction
|
||||
;
|
||||
; OUT: ?
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
ARP_api:
|
||||
|
||||
movzx eax, bh
|
||||
shl eax, 2
|
||||
|
||||
and ebx, 0xff
|
||||
cmp ebx, .number
|
||||
ja .error
|
||||
jmp dword [.table + 4*ebx]
|
||||
|
||||
.table:
|
||||
dd .packets_tx ; 0
|
||||
dd .packets_rx ; 1
|
||||
dd .entries ; 2
|
||||
dd .read ; 3
|
||||
dd .write ; 4
|
||||
dd .remove ; 5
|
||||
dd .send_announce ; 6
|
||||
dd .conflicts ; 7
|
||||
.number = ($ - .table) / 4 - 1
|
||||
|
||||
.error:
|
||||
mov eax, -1
|
||||
ret
|
||||
|
||||
.packets_tx:
|
||||
mov eax, [ARP_PACKETS_TX + eax]
|
||||
ret
|
||||
|
||||
.packets_rx:
|
||||
mov eax, [ARP_PACKETS_RX + eax]
|
||||
ret
|
||||
|
||||
.conflicts:
|
||||
mov eax, [ARP_CONFLICTS + eax]
|
||||
ret
|
||||
|
||||
.entries:
|
||||
mov eax, [NumARP]
|
||||
ret
|
||||
|
||||
.read:
|
||||
cmp ecx, [NumARP]
|
||||
jae .error
|
||||
; edi = pointer to buffer
|
||||
; ecx = # entry
|
||||
imul ecx, sizeof.ARP_entry
|
||||
add ecx, ARP_table
|
||||
mov esi, ecx
|
||||
mov ecx, sizeof.ARP_entry/2
|
||||
rep movsw
|
||||
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
.write:
|
||||
; esi = pointer to buffer
|
||||
call ARP_add_entry ; out: eax = entry number, -1 on error
|
||||
ret
|
||||
|
||||
.remove:
|
||||
; ecx = # entry
|
||||
cmp ecx, [NumARP]
|
||||
jae .error
|
||||
imul ecx, sizeof.ARP_entry
|
||||
lea esi, [ARP_table + ecx]
|
||||
call ARP_del_entry
|
||||
ret
|
||||
|
||||
.send_announce:
|
||||
mov edi, eax
|
||||
mov eax, [IP_LIST + eax]
|
||||
call ARP_output_request ; now send a gratuitous ARP
|
||||
ret
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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
|
||||