Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 3544 → Rev 3545

/data/eng/autorun.dat
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
/data/eng/docs/STACK.TXT
1,387 → 1,203
What is implemented
===================
eax = 74 - Work directly with network interface
ebx = -1 (Get number of active network devices)
 
The following features are present in the TCP/IP stack code:
out:
eax = number of active network devices
 
IP layer.
ICMP.
TCP layer.
UDP layer.
local loopback.
Realtek 8029 PCI ethernet interface.
Realtek 8139 PCI ethernet interface.
Intel i8255x PCI ethernet interface.
Dynamic ARP table.
PPP dialer
bh = device number, for all following functions !
And the following internet applcations are implemented
bl = 0 (Get device type)
 
HTTP Server
Telnet
POP Client
DNS Name resolver
MP3 Server
TFTP Client
IRC Client
out:
eax = device type number
There are also a number of experimental applications for streaming music
and performing interprocess communication via sockets. A Web broswer is in
development
bl = 1 (Get device name)
 
in:
ecx = pointer to 64 byte buffer
out:
name is copied into the buffer
eax = -1 on error
 
What is not implemented
=======================
bl = 2 (Reset the device)
 
The IP layer does not process header options.
The IP layer does not support routing.
Packet fragmentation is not supported.
in
none
out
eax = -1 on error
 
bl = 3 (Stop device)
 
How to configure Kolibri for PPP
===============================
in
none
out
eax = -1 on error
 
See ppp.txt
TO BE FIGURED OUT
 
eax = 75 - Work with Sockets
 
How to configure Kolibri for Ethernet
====================================
These functions work like the ones found in UNIX (and windows)
for more info, please read http://beej.us/guide/bgnet/
 
First, you need to have a supported ethernet card fitted, or present
on your motherboard. If you are uncertain what type of hardware you
have, try to configue the stack. If you have supported hardware it
will be found, and enabled.
bl = 0 (Open Socket)
 
Setting Up the ARP Table
------------------------
in:
ecx = domain
edx = type
esi = protocol
out:
eax = socket number, -1 on error
 
Kolibri's ARP table is dynamically created and maintained; You can see what
hosts Kolibri has communicated with by running the ARPSTAT application.
bl = 1 (Close Socket)
 
Enabling Ethernet
-----------------
in:
ecx = socket number
out:
eax = -1 on error
 
Boot Kolibri, then select STACKCFG from the NET menu.
Press the 'Read' Button, then select 'Packet Driver'.
Press 'Change' next to the IP address, and enter the IP address you want
to use. Make sure it is on the same sub-net as the LAN to which you are
connected.
Press 'Apply' to action the changes.
Close the program.
bl = 2 (Bind)
 
 
The stack is now running, which you can test by pinging Kolibri from a
remote host.
 
 
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.
 
 
How to use TCP/IP locally, with no Network
==========================================
 
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.
 
 
Application Programming Interface
=================================
 
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.
 
 
Sockets
=======
 
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.
 
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! )
 
Lets deal with the terminology before we go any further.
 
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.
 
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
 
192.168.1.10:80 ; Connect to port 80 on the machine 192.168.1.10
 
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.
 
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.
 
 
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.
 
 
Get Local IP Address
--------------------
eax = 52
ebx = 1
 
IP address returned in eax ( in internet byte order )
 
 
Write to stack input queue
--------------------------
eax = 52
ebx = 6
edx = number of bytes to write
esi = pointer to data ( in application space )
 
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
This interface is for slow network drivers only ( PPP, SLIP )
 
 
Read data from network output queue
-----------------------------------
eax = 52
ebx = 8
esi = pointer to data ( in application space )
 
On return, eax holds number of bytes transferred.
This interface is for slow network drivers only ( PPP, SLIP )
 
 
Open a UDP socket
-----------------
eax = 53
ebx = 0
ecx = local port
edx = remote port
esi = remote ip address ( in internet byte order )
 
The socket number allocated is returned in eax.
A return value of 0xFFFFFFFF means no socket could be opened.
 
 
Open a TCP socket
-----------------
eax = 53
ebx = 5
ecx = local port
edx = remote port
esi = remote ip address ( in internet byte order )
edi = mode : SOCKET_PASSIVE or SOCKET_ACTIVE ( defined in stack.inc )
 
The socket number allocated is returned in eax.
A return value of 0xFFFFFFFF means no socket could be opened.
 
 
Close a socket (UDP Only )
--------------------------
eax = 53
ebx = 1
in:
ecx = socket number
edx = pointer to sockaddr structure
esi = length of sockaddr structure
out:
eax = -1 on error
 
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
bl = 3 (Listen)
 
 
Close a socket (TCP Only )
--------------------------
eax = 53
ebx = 8
in:
ecx = socket number
edx = backlog
out:
eax = -1 on error
 
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
bl = 4 (connect)
 
 
Poll socket
-----------
eax = 53
ebx = 2
in:
ecx = socket number
edx = pointer to sockaddr structure
esi = length of sockaddr structure
out:
eax = -1 on error
 
On return, eax holds the number of bytes in the receive buffer.
bl = 5 (accept)
 
 
Read socket data
----------------
eax = 53
ebx = 3
in:
ecx = socket number
edx = pointer to sockaddr structure
esi = length of sockaddr structure
out:
eax = socket number, -1 on error
 
On return, eax holds the number of bytes remaining, bl holds a data byte.
bl = 6 (send)
 
 
Write to socket ( UDP only )
----------------------------
eax = 53
ebx = 4
in:
ecx = socket number
edx = number of bytes to write
esi = pointer to data ( in application space )
edx = pointer to buffer
esi = length of buffer
edi = flags
out:
eax = -1 on error
 
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
bl = 7 (receive)
 
 
Return socket status ( TCP only )
---------------------------------
eax = 53
ebx = 6
in:
ecx = socket number
edx = pointer to buffer
esi = length of buffer
edi = flags
out:
eax = number of bytes copied, -1 on error
 
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_
bl = 8 (set socket options)
 
 
Write to socket ( TCP only )
----------------------------
eax = 53
ebx = 7
in:
ecx = socket number
edx = number of bytes to write
esi = pointer to data ( in application space )
edx = level
esi = optionname
edi = ptr to buffer
 
On return, eax holds 0 for OK, or 0xFFFFFFFF for error.
The buffer's first dword is the length of the buffer, minus the first dword offcourse
 
out:
eax = -1 on error
 
Check port number
-----------------
eax = 53
ebx = 9
ecx = port number
bl = 9 (get socket options
 
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.
in:
ecx = socket number
edx = level
esi = optionname
edi = ptr to buffer
 
On return, eax is 1 for port number not in use, 0 otherwise.
The buffer's first dword is the length of the buffer, minus the first dword offcourse
 
out:
eax = -1 on error, socket option otherwise
 
Opening a TCP socket in Kolibri
===============================
TIP
 
There are two ways to open a socket - Passive or Active.
when you import 'network.inc' and 'macros.inc' into your source code, you can use the following syntax to work with sockets:
 
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.
for example, to open a socket
 
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.
mcall socket, AF_INET, SOCK_DGRAM,0
mov [socketnum], eax
 
then to connect to a server
 
How to find an unused local port number
=======================================
mcall connect, [socketnum], sockaddr, 18
 
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
eax = 76 - Work with protocols
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
high half of ebx = protocol number (for all subfunctions!)
bh = device number (for all subfunctions!)
bl = subfunction number, depends on protocol type
 
; ecx contains a free local port number
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
 
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
 
Writing data to a socket
========================
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
 
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.
0 - Read # ICMP packets send
1 - Read # ICMP packets received
3 - enable/disable ICMP echo reply
For UDP protocol
 
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 ).
0 - Read # UDP packets send
1 - Read # UDP packets received
For TCP protocol
 
 
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
/data/eng/menu.dat
128,27 → 128,19
#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
/data/eng/network.ini
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
/data/rus/autorun.dat
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
/data/rus/menu.dat
133,27 → 133,19
#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
/data/rus/network.ini
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
/drivers/ethernet/3c59x.asm
0,0 → 1,2954
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; 3Com network driver for KolibriOS ;;
;; ;;
;; Ported to KolibriOS net-branch by hidnplayr (28/05/10) ;;
;; ;;
;; Thanks to: scrap metal recyclers, whom provide me with ;;
;; loads of hardware ;;
;; diamond: who makes me understand KolibriOS ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 3C59X.INC ;;
;; ;;
;; Ethernet driver for Menuet OS ;;
;; ;;
;; Driver for 3Com fast etherlink 3c59x and ;;
;; etherlink XL 3c900 and 3c905 cards ;;
;; References: ;;
;; www.3Com.com - data sheets ;;
;; DP83840A.pdf - ethernet physical layer ;;
;; 3c59x.c - linux driver ;;
;; ethernet driver template by Mike Hibbett ;;
;; ;;
;; Credits ;;
;; Mike Hibbett, ;;
;; who kindly supplied me with a 3Com905C-TX-M card ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Copyright (c) 2004, Endre Kozma <endre.kozma@axelero.hu>
;; All rights reserved.
;;
;; Redistribution and use in source and binary forms, with or without
;; modification, are permitted provided that the following conditions are
;; met:
;;
;; 1. Redistributions of source code must retain the above copyright notice,
;; this list of conditions and the following disclaimer.
;;
;; 2. Redistributions in binary form must reproduce the above copyright
;; notice, this list of conditions and the following disclaimer in the
;; documentation and/or other materials provided with the distribution.
;;
;; 3. The name of the author may not be used to endorse or promote products
;; derived from this software without specific prior written permission.
;;
;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
;; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
;; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;;
;; History
;; =======
;; $Log: 3C59X.INC,v $
;; Revision 1.3 2004/07/11 12:21:12 kozma
;; Support of vortex chips (3c59x) added.
;; Support of 3c920 and 3c982 added.
;; Corrections.
;;
;; Revision 1.2 2004/06/12 19:40:20 kozma
;; Function e3c59x_set_available_media added in order to set
;; the default media in case auto detection finds no valid link.
;; Incorrect mii check removed (3c900 Cyclone works now).
;; Cleanups.
;;
;; Revision 1.1 2004/06/12 18:27:15 kozma
;; Initial revision
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
FORCE_FD = 0 ; forcing full duplex mode makes sense at some cards and link types
PROMISCIOUS = 0 ; enables promiscous mode
 
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
 
struc DPD { ; Download Packet Descriptor
 
.next_ptr dd ?
.frame_start_hdr dd ?
.frag_addr dd ? ; for packet data
.frag_len dd ? ; for packet data
.realaddr dd ?
.size = 32
}
 
virtual at 0
dpd DPD
end virtual
 
 
struc UPD { ; Upload Packet Descriptor
 
.next_ptr dd ?
.pkt_status dd ?
.frag_addr dd ?
.frag_len dd ? ; for packet data
.realaddr dd ?
.size = 32
 
}
 
virtual at 0
upd UPD
end virtual
 
; Registers
REG_POWER_MGMT_CTRL = 0x7c
REG_UP_LIST_PTR = 0x38
REG_UP_PKT_STATUS = 0x30
REG_TX_FREE_THRESH = 0x2f
REG_DN_LIST_PTR = 0x24
REG_DMA_CTRL = 0x20
REG_TX_STATUS = 0x1b
REG_RX_STATUS = 0x18
REG_TX_DATA = 0x10
 
; Common window registers
REG_INT_STATUS = 0xe
REG_COMMAND = 0xe
 
; Register window 7
REG_MASTER_STATUS = 0xc
REG_POWER_MGMT_EVENT = 0xc
REG_MASTER_LEN = 0x6
REG_VLAN_ETHER_TYPE = 0x4
REG_VLAN_MASK = 0x0
REG_MASTER_ADDRESS = 0x0
 
; Register window 6
REG_BYTES_XMITTED_OK = 0xc
REG_BYTES_RCVD_OK = 0xa
REG_UPPER_FRAMES_OK = 0x9
REG_FRAMES_DEFERRED = 0x8
REG_FRAMES_RCVD_OK = 0x7
REG_FRAMES_XMITTED_OK = 0x6
REG_RX_OVERRUNS = 0x5
REG_LATE_COLLISIONS = 0x4
REG_SINGLE_COLLISIONS = 0x3
REG_MULTIPLE_COLLISIONS = 0x2
REG_SQE_ERRORS = 0x1
REG_CARRIER_LOST = 0x0
 
; Register window 5
REG_INDICATION_ENABLE = 0xc
REG_INTERRUPT_ENABLE = 0xa
REG_TX_RECLAIM_THRESH = 0x9
REG_RX_FILTER = 0x8
REG_RX_EARLY_THRESH = 0x6
REG_TX_START_THRESH = 0x0
 
; Register window 4
REG_UPPER_BYTES_OK = 0xe
REG_BAD_SSD = 0xc
REG_MEDIA_STATUS = 0xa
REG_PHYSICAL_MGMT = 0x8
REG_NETWORK_DIAGNOSTIC = 0x6
REG_FIFO_DIAGNOSTIC = 0x4
REG_VCO_DIAGNOSTIC = 0x2 ; may not supported
 
; Bits in register window 4
BIT_AUTOSELECT = 24
 
; Register window 3
REG_TX_FREE = 0xc
REG_RX_FREE = 0xa
REG_MEDIA_OPTIONS = 0x8
REG_MAC_CONTROL = 0x6
REG_MAX_PKT_SIZE = 0x4
REG_INTERNAL_CONFIG = 0x0
 
; Register window 2
REG_RESET_OPTIONS = 0xc
REG_STATION_MASK_HI = 0xa
REG_STATION_MASK_MID = 0x8
REG_STATION_MASK_LO = 0x6
REG_STATION_ADDRESS_HI = 0x4
REG_STATION_ADDRESS_MID = 0x2
REG_STATION_ADDRESS_LO = 0x0
 
; Register window 1
REG_TRIGGER_BITS = 0xc
REG_SOS_BITS = 0xa
REG_WAKE_ON_TIMER = 0x8
REG_SMB_RXBYTES = 0x7
REG_SMB_DIAG = 0x5
REG_SMB_ARB = 0x4
REG_SMB_STATUS = 0x2
REG_SMB_ADDRESS = 0x1
REG_SMB_FIFO_DATA = 0x0
 
; Register window 0
REG_EEPROM_DATA = 0xc
REG_EEPROM_COMMAND = 0xa
REG_BIOS_ROM_DATA = 0x8
REG_BIOS_ROM_ADDR = 0x4
 
; Physical management bits
BIT_MGMT_DIR = 2 ; drive with the data written in mgmtData
BIT_MGMT_DATA = 1 ; MII management data bit
BIT_MGMT_CLK = 0 ; MII management clock
 
; MII commands
MII_CMD_MASK = (1111b shl 10)
MII_CMD_READ = (0110b shl 10)
MII_CMD_WRITE = (0101b shl 10)
 
; MII registers
REG_MII_BMCR = 0 ; basic mode control register
REG_MII_BMSR = 1 ; basic mode status register
REG_MII_ANAR = 4 ; auto negotiation advertisement register
REG_MII_ANLPAR = 5 ; auto negotiation link partner ability register
REG_MII_ANER = 6 ; auto negotiation expansion register
 
; MII bits
BIT_MII_AUTONEG_COMPLETE = 5 ; auto-negotiation complete
BIT_MII_PREAMBLE_SUPPRESSION = 6
 
; eeprom bits and commands
EEPROM_CMD_READ = 0x80
EEPROM_BIT_BUSY = 15
 
; eeprom registers
EEPROM_REG_OEM_NODE_ADDR= 0xa
EEPROM_REG_CAPABILITIES = 0x10
 
; Commands for command register
SELECT_REGISTER_WINDOW = (1 shl 11)
 
IS_VORTEX = 0x1
IS_BOOMERANG = 0x2
IS_CYCLONE = 0x4
IS_TORNADO = 0x8
EEPROM_8BIT = 0x10
HAS_PWR_CTRL = 0x20
HAS_MII = 0x40
HAS_NWAY = 0x80
HAS_CB_FNS = 0x100
INVERT_MII_PWR = 0x200
INVERT_LED_PWR = 0x400
MAX_COLLISION_RESET = 0x800
EEPROM_OFFSET = 0x1000
HAS_HWCKSM = 0x2000
EXTRA_PREAMBLE = 0x4000
 
; Status
IntLatch = 0x0001
HostError = 0x0002
TxComplete = 0x0004
TxAvailable = 0x0008
RxComplete = 0x0010
RxEarly = 0x0020
IntReq = 0x0040
StatsFull = 0x0080
DMADone = 0x0100
DownComplete = 0x0200
UpComplete = 0x0400
DMAInProgress = 0x0800 ; 1 shl 11 (DMA controller is still busy)
CmdInProgress = 0x1000 ; 1 shl 12 (EL3_CMD is still busy)
 
S_5_INTS = HostError + RxEarly + UpComplete + DownComplete ;+ TxComplete + RxComplete + TxAvailable
 
; Commands
TotalReset = 0 shl 11
SelectWindow = 1 shl 11
StartCoax = 2 shl 11
RxDisable = 3 shl 11
RxEnable = 4 shl 11
RxReset = 5 shl 11
UpStall = 6 shl 11
UpUnstall = (6 shl 11)+1
DownStall = (6 shl 11)+2
DownUnstall = (6 shl 11)+3
RxDiscard = 8 shl 11
TxEnable = 9 shl 11
TxDisable = 10 shl 11
TxReset = 11 shl 11
FakeIntr = 12 shl 11
AckIntr = 13 shl 11
SetIntrEnb = 14 shl 11
SetStatusEnb = 15 shl 11
SetRxFilter = 16 shl 11
SetRxThreshold = 17 shl 11
SetTxThreshold = 18 shl 11
SetTxStart = 19 shl 11
StartDMAUp = 20 shl 11
StartDMADown = (20 shl 11)+1
StatsEnable = 21 shl 11
StatsDisable = 22 shl 11
StopCoax = 23 shl 11
SetFilterBit = 25 shl 11
 
; Rx mode bits
RxStation = 1
RxMulticast = 2
RxBroadcast = 4
RxProm = 8
 
; RX/TX buffers sizes
MAX_ETH_PKT_SIZE = 1536 ; max packet size
NUM_RX_DESC = 4 ; a power of 2 number
NUM_TX_DESC = 4 ; a power of 2 number
MAX_ETH_FRAME_SIZE = 1520 ; size of ethernet frame + bytes alignment
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.dpd_buffer rd (dpd.size*NUM_TX_DESC)/4
.upd_buffer rd (upd.size*NUM_RX_DESC)/4
.curr_upd dd ?
.prev_dpd dd ?
 
.io_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
rb 3 ; alignment
 
.prev_tx_frame dd ?
.ver_id db ?
.full_bus_master db ?
.has_hwcksm db ?
.preamble db ?
.dn_list_ptr_cleared db ?
 
.size = $ - 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 1,"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 of this hardware dont exist
 
; check if the device is already listed
 
mov ecx, [VORTEX_DEVICES]
test ecx, ecx
jz .maybeboomerang
 
mov esi, VORTEX_LIST
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 @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
 
 
.maybeboomerang:
mov ecx, [BOOMERANG_DEVICES]
test ecx, ecx
jz .firstdevice
 
mov esi, BOOMERANG_LIST
mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax , [eax+1] ;
.nextdevice2:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice2
 
 
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
mov ecx, [BOOMERANG_DEVICES]
add ecx, [VORTEX_DEVICES]
cmp ecx, MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, device.size, .fail ; Allocate the buffer for device structure
 
; Fill in the direct call addresses into the struct
 
mov [device.reset], reset
mov [device.transmit], null_op
mov [device.unload], null_op
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 io addres of the PCI device
PCI_find_io
 
; We've found the io 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.io_addr]:4
 
; 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
 
 
movzx ecx, [device.ver_id]
test word [hw_versions+2+ecx*4], IS_VORTEX
jz .not_vortex
 
mov eax, [VORTEX_DEVICES] ; Add the device structure to our device list
mov [VORTEX_LIST+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [VORTEX_DEVICES] ;
 
.register:
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
cmp eax, -1
je .destroy
 
call start_device
ret
 
.not_vortex:
mov eax, [BOOMERANG_DEVICES] ; Add the device structure to our device list
mov [BOOMERANG_LIST+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [BOOMERANG_DEVICES]
 
jmp .register
 
; 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 ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
 
 
 
;***************************************************************************
; Function
; probe
; Description
; Searches for an ethernet card, enables it and clears the rx buffer
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;***************************************************************************
 
align 4
probe:
 
DEBUGF 1,"Probing 3com card\n"
 
PCI_make_bus_master
 
; wake up the card
call wake_up
 
stdcall PciRead32, [device.pci_bus], [device.pci_dev], 0 ; get device/vendor id
 
DEBUGF 1,"Vendor id: 0x%x\n", ax
 
cmp ax, 0x10B7
jne .notfound
shr eax, 16
 
DEBUGF 1,"Vendor ok!, device id: 0x%x\n", ax
 
; get chip version
mov ecx, HW_VERSIONS_SIZE/4-1
.loop:
cmp ax, [hw_versions+ecx*4]
jz .found
loop .loop
.notfound:
DEBUGF 1,"Device id not found in list!\n"
or eax, -1
ret
.found:
mov esi, [hw_str+ecx*4]
DEBUGF 1,"Hardware type: %s\n", esi
mov [device.name], esi
 
mov [device.ver_id], cl
test word [hw_versions+2+ecx*4], HAS_HWCKSM
setnz [device.has_hwcksm]
; set pci latency for vortex cards
test word [hw_versions+2+ecx*4], IS_VORTEX
jz .not_vortex
 
mov eax, 11111000b ; 248 = max latency
stdcall PciWrite32, [device.pci_bus], [device.pci_dev], PCI_REG_LATENCY, eax
 
.not_vortex:
; set RX/TX functions
mov ax, EEPROM_REG_CAPABILITIES
call read_eeprom
test al, 100000b ; full bus master?
setnz [device.full_bus_master]
jnz .boomerang_func
mov [device.transmit], vortex_transmit
DEBUGF 1,"Device is a vortex type\n"
DEBUGF 1,"I'm sorry but vortex code hasnt been tested yet\n"
DEBUGF 1,"Please contact me on hidnplayr@kolibrios.org\n"
DEBUGF 1,"If you can help me finish it!\n"
or eax, -1
ret
jmp @f
.boomerang_func: ; full bus master, so use boomerang functions
mov [device.transmit], boomerang_transmit
DEBUGF 1,"Device is a boomerang type\n"
@@:
call read_mac_eeprom
 
test byte [device.full_bus_master], 0xff
jz .set_preamble
; switch to register window 2
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+2
out dx, ax
; activate xcvr by setting some magic bits
set_io REG_RESET_OPTIONS
in ax, dx
and ax, not 0x4010
movzx ecx, [device.ver_id]
test word [ecx*4+hw_versions+2], INVERT_LED_PWR
jz @f
or al, 0x10
@@:
test word [ecx*4+hw_versions+2], INVERT_MII_PWR
jz @f
or ah, 0x40
@@:
out dx, ax
.set_preamble:
; use preamble as default
mov byte [device.preamble], 1 ; enable preamble
 
call global_reset
 
;--------------------------
; RESET
 
align 4
reset:
 
movzx eax, [device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n",eax:1
 
movzx ecx, [device.ver_id]
test word [hw_versions+2+ecx*4], IS_VORTEX
jz .not_vortex
 
mov esi, int_vortex
jmp .reg_int
 
.not_vortex:
mov esi, int_boomerang
 
.reg_int:
stdcall AttachIntHandler, eax, esi, dword 0
test eax, eax
jnz @f
DEBUGF 1,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW + 0
out dx, ax
 
mov ax, StopCoax
out dx, ax ; stop transceiver
 
mov ax, SELECT_REGISTER_WINDOW + 4
out dx, ax ; disable UTP
 
set_io REG_MEDIA_STATUS
mov ax, 0x0
 
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW + 0
out dx, ax
 
set_io REG_FIFO_DIAGNOSTIC
mov ax, 0
out dx, ax ; disable card
 
mov ax, 1
out dx, ax ; enable card
 
call write_mac
 
 
;<<<<<<<<<<<<<<
 
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW + 1
out dx, ax
 
mov ecx, 32
set_io 0x0b
.loop:
in al, dx
loop .loop
 
; Get rid of stray ints
set_io REG_COMMAND
mov ax, AckIntr + 0xff
out dx, ax
 
mov ax, SetStatusEnb + S_5_INTS
out dx, ax
 
mov ax, SetIntrEnb + S_5_INTS
out dx, ax
 
call set_rx_mode
call set_active_port
 
;>>>>>>>>>>
 
call create_rx_ring
call rx_reset
call tx_reset
 
;>>>>>>>>>>>>>>>>>>
 
xor eax, eax
; clear packet/byte counters
 
lea edi, [device.bytes_tx]
mov ecx, 6
rep stosd
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
ret
 
 
 
 
 
align 4
start_device:
DEBUGF 1,"Starting the device\n"
 
set_io 0
set_io REG_COMMAND
mov ax, SetTxThreshold + 60 ;2047 ; recommended by the manual :)
out dx, ax
 
call check_tx_status
 
set_io 0
set_io REG_COMMAND
; switch to register window 4
mov ax, SELECT_REGISTER_WINDOW+4
out dx, ax
 
; wait for linkDetect
set_io REG_MEDIA_STATUS
mov ecx, 20 ; wait for max 2s
.link_detect_loop:
mov esi, 100
call Sleep ; 100 ms
in ax, dx
test ah, 1000b ; linkDetect
jnz @f
loop .link_detect_loop
DEBUGF 1,"Link detect timed-out!\n"
@@:
 
; print link type
xor eax, eax
bsr ax, word [device.state]
jz @f
sub ax, 4
@@:
 
mov esi, [link_str+eax*4]
DEBUGF 1,"Established Link type: %s\n", esi
 
; enable interrupts
 
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW + 1
out dx, ax
 
mov ax, AckIntr + 0xff
out dx, ax
 
mov ax, SetStatusEnb + S_5_INTS
out dx, ax
 
mov ax, SetIntrEnb + S_5_INTS
out dx, ax
 
; Start RX/TX
 
set_io 0
set_io REG_COMMAND
mov ax, RxEnable
out dx, ax
 
mov ax, TxEnable
out dx, ax
 
set_io REG_COMMAND
mov ax, SetRxThreshold + 208
out dx, ax
 
mov ax, SetTxThreshold + 60 ;16 ; recommended by the manual :)
out dx, ax
 
mov ax, SELECT_REGISTER_WINDOW + 1
out dx, ax
 
ret
 
 
 
 
 
 
 
align 4
set_rx_mode:
 
DEBUGF 1,"Setting RX mode\n"
 
set_io 0
set_io REG_COMMAND
 
if defined PROMISCIOUS
mov ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast + RxProm
else if defined ALLMULTI
mov ax, SetRxFilter + RxStation + RxMulticast + RxBroadcast
else
mov ax, SetRxFilter + RxStation + RxBroadcast
end if
out dx, ax
 
ret
 
 
 
 
 
;***************************************************************************
; Function
; global_reset
; Description
; resets the device
; Parameters:
; ebp - io_addr
; Return value:
; Destroyed registers
; ax, ecx, edx, esi
;
;***************************************************************************1
 
align 4
global_reset:
 
DEBUGF 1,"Global reset..\n"
 
; GlobalReset
set_io 0
set_io REG_COMMAND
xor eax, eax
; or al, 0x14
out dx, ax
; wait for GlobalReset to complete
mov ecx, 64000
.loop:
in ax , dx
test ah , 10000b ; check CmdInProgress
loopz .loop
 
DEBUGF 1,"Waiting for nic to boot..\n"
; wait for 2 seconds for NIC to boot
mov esi, 2000
call Sleep ; 2 seconds
 
DEBUGF 1,"Ok!\n"
 
ret
 
 
 
;***************************************************************************
; Function
; tx_reset
; Description
; resets and enables transmitter engine
;
;***************************************************************************
 
align 4
tx_reset:
DEBUGF 1,"tx reset\n"
 
; TxReset
set_io 0
set_io REG_COMMAND
mov ax, TxReset
out dx, ax
; Wait for TxReset to complete
mov ecx, 200000
.tx_reset_loop:
in ax, dx
test ah, 10000b ; check CmdInProgress
jz .tx_set_prev
dec ecx
jnz .tx_reset_loop
.tx_set_prev:
; init last_dpd
lea eax, [device.dpd_buffer + (NUM_TX_DESC-1)*dpd.size]
mov [device.prev_dpd], eax
 
.tx_enable:
ret
 
 
 
;***************************************************************************
; Function
; rx_reset
; Description
; resets and enables receiver engine
;
;***************************************************************************
 
align 4
rx_reset:
 
DEBUGF 1,"rx reset\n"
 
set_io 0
set_io REG_COMMAND
mov ax, RxReset or 0x4
out dx, ax
 
; wait for RxReset to complete
mov ecx, 200000
.loop:
in ax, dx
test ah, 10000b ; check CmdInProgress
jz .done
dec ecx
jnz .loop
.done:
 
lea eax, [device.upd_buffer]
mov [device.curr_upd], eax
GetRealAddr
set_io 0
set_io REG_UP_LIST_PTR
out dx, eax
 
.rx_enable:
ret
 
 
align 4
create_rx_ring:
; create upd ring
lea eax, [device.upd_buffer]
GetRealAddr
mov edi, eax ; real addr of first descr
 
lea esi, [device.upd_buffer] ; ptr to first descr
lea edx, [device.upd_buffer + (NUM_RX_DESC-1)*upd.size] ; ptr to last descr
 
mov ecx, NUM_RX_DESC
 
.upd_loop:
mov [edx + upd.next_ptr], edi
 
push ecx edx
stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
pop edx ecx
mov [esi + upd.realaddr], eax
call GetPgAddr
mov [esi + upd.frag_addr], eax
and [esi + upd.pkt_status], 0
mov [esi + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
 
DEBUGF 1,"UPD: lin=%x phys=%x len=%x next ptr=%x\n", [esi+upd.realaddr]:8, [esi+upd.frag_addr]:8, [esi+upd.frag_len]:8, edi
DEBUGF 1,"UPD: cur=%x prev=%x\n", esi, edx
 
mov edx, esi
add esi, upd.size
add edi, upd.size
dec ecx
jnz .upd_loop
 
ret
 
 
 
;---------------------------------------------------------------------------
; Function
; try_link_detect
; Description
; try_link_detect checks if link exists
; Parameters
; ebx = device structure
; Return value
; al - 0 ; no link detected
; al - 1 ; link detected
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;---------------------------------------------------------------------------
 
align 4
try_link_detect:
 
DEBUGF 1,"trying to detect link\n"
 
; create self-directed packet
stdcall KernelAlloc, 20 ; create a buffer for the self-directed packet
test eax, eax
jz .fail
 
pushd 20 ; Packet parameters for device.transmit
push eax ;
 
mov edi, eax
 
lea esi, [device.mac]
movsw
movsd
sub esi, 6
movsw
movsd
mov ax , 0x0608
stosw
 
; download self-directed packet
call [device.transmit]
 
; switch to register window 4
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+4
out dx, ax
 
; See if we have received the packet by now..
cmp [device.packets_rx], 0
jnz .link_detected
 
; switch to register window 4
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+4
out dx, ax
 
; read linkbeatdetect
set_io REG_MEDIA_STATUS
in ax, dx
test ah, 1000b ; test linkBeatDetect
jnz .link_detected
xor al, al
jmp .finish
 
.link_detected:
DEBUGF 1,"link detected!\n"
setb al
 
.finish:
test al, al
jz @f
or byte [device.state+1], 100b
@@:
ret
 
.fail:
ret
 
 
 
;***************************************************************************
; Function
; try_phy
; Description
; try_phy checks the auto-negotiation function
; in the PHY at PHY index. It can also be extended to
; include link detection for non-IEEE 802.3u
; auto-negotiation devices, for instance the BCM5000. ; TODO: BCM5000
; Parameters
; ah - PHY index
; ebx - device stucture
; Return value
; al - 0 link is auto-negotiated
; al - 1 no link is auto-negotiated
; Destroyed registers
; eax, ebx, ecx, edx, esi
;
;***************************************************************************
 
align 4
try_phy:
 
DEBUGF 1,"PHY=%u\n", ah
DEBUGF 1,"Detecting if device is auto-negotiation capable\n"
 
mov al, REG_MII_BMCR
push eax
call mdio_read ; returns with window #4
or ah , 0x80 ; software reset
mov esi, eax
mov eax, dword [esp]
call mdio_write ; returns with window #4
 
; wait for reset to complete
mov esi, 2000
stdcall Sleep ; 2s
mov eax, [esp]
call mdio_read ; returns with window #4
test ah , 0x80
jnz .fail1
mov eax, [esp]
 
; wait for a while after reset
mov esi, 20
stdcall Sleep ; 20ms
mov eax, [esp]
mov al , REG_MII_BMSR
call mdio_read ; returns with window #4
test al , 1 ; extended capability supported?
jz .fail2
 
; auto-neg capable?
test al , 1000b
jz .fail2 ; not auto-negotiation capable
 
DEBUGF 1,"Device is auto-negotiation capable\n"
 
; auto-neg complete?
test al , 100000b
jnz .auto_neg_ok
 
DEBUGF 1,"Restarting auto-negotiation\n"
 
; restart auto-negotiation
mov eax, [esp]
mov al , REG_MII_ANAR
push eax
call mdio_read ; returns with window #4
or ax , 1111b shl 5; advertise only 10base-T and 100base-TX
mov esi, eax
pop eax
call mdio_write ; returns with window #4
mov eax, [esp]
call mdio_read ; returns with window #4
mov esi, eax
or bh , 10010b ; restart auto-negotiation
mov eax, [esp]
call mdio_write ; returns with window #4
mov esi, 4000
stdcall Sleep ; 4 seconds
mov eax, [esp]
mov al , REG_MII_BMSR
call mdio_read ; returns with window #4
test al , 100000b ; auto-neg complete?
jnz .auto_neg_ok
jmp .fail3
.auto_neg_ok:
 
DEBUGF 1,"Auto-negotiation complete\n"
 
; compare advertisement and link partner ability registers
mov eax, [esp]
mov al , REG_MII_ANAR
call mdio_read ; returns with window #4
xchg eax, [esp]
mov al , REG_MII_ANLPAR
call mdio_read ; returns with window #4
pop esi
and eax, esi
and eax, 1111100000b
push eax
 
mov word[device.state+2], ax
 
; switch to register window 3
set_io 0
set_io REG_COMMAND
mov ax , SELECT_REGISTER_WINDOW+3
out dx , ax
 
; set full-duplex mode
set_io REG_MAC_CONTROL
in ax , dx
and ax , not 0x120 ; clear full duplex and flow control
pop esi
test esi, 1010b shl 5; check for full-duplex
jz .half_duplex
or ax , 0x120 ; set full duplex and flow control
.half_duplex:
DEBUGF 1,"Using half-duplex\n"
out dx , ax
mov al , 1
ret
 
 
.fail1:
DEBUGF 1,"reset failed!\n"
pop eax
xor al, al
ret
 
.fail2:
DEBUGF 1,"This device is not auto-negotiation capable!\n"
pop eax
xor al, al
ret
 
.fail3:
DEBUGF 1,"auto-negotiation reset failed!\n"
pop eax
xor al, al
ret
 
 
 
;***************************************************************************
; Function
; try_mii
; Description
; try_MII checks the on-chip auto-negotiation logic
; or an off-chip MII PHY, depending upon what is set in
; xcvrSelect by the caller.
; It exits when it finds the first device with a good link.
; Parameters
; ebp - io_addr
; Return value
; al - 0
; al - 1
; Destroyed registers
; eax, ebx, ecx, edx, esi
;
;***************************************************************************
 
align 4
try_mii:
 
DEBUGF 1,"trying to find MII PHY\n"
 
; switch to register window 3
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+3
out dx, ax
set_io REG_INTERNAL_CONFIG
in eax, dx
and eax, (1111b shl 20)
cmp eax, (1000b shl 20) ; is auto-negotiation set?
jne .mii_device
 
DEBUGF 1,"auto-negotiation is set\n"
; switch to register window 4
set_io REG_COMMAND
mov ax , SELECT_REGISTER_WINDOW+4
out dx , ax
 
; PHY==24 is the on-chip auto-negotiation logic
; it supports only 10base-T and 100base-TX
mov ah , 24
call try_phy
test al , al
jz .fail_finish
 
mov cl , 24
jmp .check_preamble
 
.mii_device:
cmp eax, (0110b shl 20)
jne .fail_finish
 
set_io 0
set_io REG_COMMAND
mov ax , SELECT_REGISTER_WINDOW+4
out dx , ax
 
set_io REG_PHYSICAL_MGMT
in ax , dx
and al , (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_DATA)
cmp al , (1 shl BIT_MGMT_DATA)
je .search_for_phy
 
xor al , al
ret
 
.search_for_phy:
; search for PHY
mov cx , 31
.search_phy_loop:
DEBUGF 1,"Searching the PHY\n"
cmp cx , 24
je .next_phy
mov ah , cl ; ah = phy
mov al , REG_MII_BMCR ; al = Basic Mode Status Register
push cx
call mdio_read
pop cx
test ax , ax
jz .next_phy
cmp ax , 0xffff
je .next_phy
mov ah , cl ; ah = phy
push cx
call try_phy
pop cx
test al , al
jnz .check_preamble
.next_phy:
loopw .search_phy_loop
 
.fail_finish:
xor al, al
ret
 
; epilog
.check_preamble:
DEBUGF 1,"Using PHY: %u\nChecking PreAmble\n", cl
push eax ; eax contains the return value of try_phy
; check hard coded preamble forcing
movzx eax, [device.ver_id]
test word [eax*4+hw_versions+2], EXTRA_PREAMBLE
setnz [device.preamble] ; force preamble
jnz .finish
 
; check mii for preamble suppression
mov ah, cl
mov al, REG_MII_BMSR
call mdio_read
test al, 1000000b ; preamble suppression?
setz [device.preamble] ; no
 
.finish:
pop eax
ret
 
 
 
;***************************************************************************
; Function
; test_packet
; Description
; try_loopback try a loopback packet for 10BASE2 or AUI port
; Parameters
; ebx = device structure
;
;***************************************************************************
 
align 4
test_packet:
 
DEBUGF 1,"sending test packet\n"
 
; switch to register window 3
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+3
out dx, ax
 
; set fullDuplexEnable in MacControl register
set_io REG_MAC_CONTROL
in ax, dx
or ax, 0x120
out dx, ax
 
; switch to register window 5
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+5
out dx, ax
 
; set RxFilter to enable individual address matches
mov ax, (10000b shl 11)
set_io REG_RX_FILTER
in al, dx
or al, 1
set_io REG_COMMAND
out dx, ax
 
; issue RxEnable and TxEnable
call rx_reset
call tx_reset
 
; create self-directed packet
stdcall KernelAlloc, 20 ; create a buffer for the self-directed packet
test eax, eax
jz .fail
 
pushd 20 ; Packet parameters for device.transmit
push eax ;
 
mov edi, eax
lea esi, [device.mac]
movsw
movsd
sub esi, 6
movsw
movsd
mov ax , 0x0608
stosw
 
; download self-directed packet
call [device.transmit]
 
; wait for 2s
mov esi, 2000
call Sleep
 
; check if self-directed packet is received
mov eax, [device.packets_rx]
test eax, eax
jnz .finish
 
; switch to register window 3
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+3
out dx, ax
 
; clear fullDuplexEnable in MacControl register
set_io REG_MAC_CONTROL
in ax , dx
and ax , not 0x120
out dx , ax
.fail:
xor eax, eax
 
.finish:
ret
 
 
 
;***************************************************************************
; Function
; try_loopback
; Description
; tries a loopback packet for 10BASE2 or AUI port
; Parameters
; al - 0: 10Mbps AUI connector
; 1: 10BASE-2
; ebp - io_addr
; Return value
; al - 0
; al - 1
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;***************************************************************************
 
align 4
try_loopback:
 
DEBUGF 1,"trying loopback\n"
 
push eax
; switch to register window 3
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+3
out dx, ax
mov eax, [esp]
 
mov cl, al
inc cl
shl cl, 3
or byte [device.state+1], cl
 
test al, al ; aui or coax?
jz .complete_loopback
; enable 100BASE-2 DC-DC converter
mov ax, (10b shl 11) ; EnableDcConverter
out dx, ax
.complete_loopback:
 
mov cx, 2 ; give a port 3 chances to complete a loopback
.next_try:
push ecx
call test_packet
pop ecx
test eax, eax
loopzw .next_try
 
.finish:
xchg eax, [esp]
test al, al
jz .aui_finish
 
; issue DisableDcConverter command
set_io 0
set_io REG_COMMAND
mov ax, (10111b shl 11)
out dx, ax
.aui_finish:
pop eax ; al contains the result of operation
 
test al, al
jnz @f
and byte [device.state+1], not 11000b
@@:
 
ret
 
 
;***************************************************************************
; Function
; set_active_port
; Description
; It selects the media port (transceiver) to be used
; Return value:
; Destroyed registers
; eax, ebx, ecx, edx, edi, esi
;
;***************************************************************************
 
align 4
set_active_port:
 
DEBUGF 1,"Trying to find the active port\n"
 
; switch to register window 3
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW + 3
out dx, ax
 
set_io REG_INTERNAL_CONFIG
in eax, dx
test eax, (1 shl 24) ; check if autoselect enable
jz .set_first_available_media
 
; check 100BASE-TX and 10BASE-T
set_io REG_MEDIA_OPTIONS
in ax, dx
test al, 1010b ; check whether 100BASE-TX or 10BASE-T available
jz .mii_device ; they are not available
 
; set auto-negotiation
set_io REG_INTERNAL_CONFIG
in eax, dx
and eax, not (1111b shl 20)
or eax, (1000b shl 20)
out dx, eax
call try_mii
test al, al
jz .mii_device
DEBUGF 1,"Using auto negotiation\n"
ret
 
.mii_device:
; switch to register window 3
set_io 0
; check for off-chip mii device
set_io REG_MEDIA_OPTIONS
in ax, dx
test al, 1000000b ; check miiDevice
jz .base_fx
set_io REG_INTERNAL_CONFIG
in eax, dx
and eax, not (1111b shl 20)
or eax, (0110b shl 20) ; set MIIDevice
out dx, eax
call try_mii
test al, al
jz .base_fx
DEBUGF 1,"Using off-chip mii device\n"
ret
 
.base_fx:
; switch to register window 3
set_io 0
; check for 100BASE-FX
set_io REG_MEDIA_OPTIONS
in ax, dx ; read media option register
test al, 100b ; check 100BASE-FX
jz .aui_enable
set_io REG_INTERNAL_CONFIG
in eax, dx
and eax, not (1111b shl 20)
or eax, (0101b shl 20) ; set 100base-FX
out dx, eax
call try_link_detect
test al, al
jz .aui_enable
DEBUGF 1,"Using 100Base-FX\n"
ret
 
.aui_enable:
; switch to register window 3
set_io 0
; check for 10Mbps AUI connector
set_io REG_MEDIA_OPTIONS
in ax, dx ; read media option register
test al, 100000b ; check 10Mbps AUI connector
jz .coax_available
set_io REG_INTERNAL_CONFIG
in eax, dx
and eax, not (1111b shl 20)
or eax, (0001b shl 20) ; set 10Mbps AUI connector
out dx, eax
xor al, al ; try 10Mbps AUI connector
call try_loopback
test al, al
jz .coax_available
DEBUGF 1,"Using 10Mbps aui\n"
ret
 
.coax_available:
; switch to register window 3
set_io 0
; check for coaxial 10BASE-2 port
set_io REG_MEDIA_OPTIONS
in ax, dx ; read media option register
test al, 10000b ; check 10BASE-2
jz .set_first_available_media
 
set_io REG_INTERNAL_CONFIG
in eax, dx
and eax, not (1111b shl 20)
or eax, (0011b shl 20) ; set 10BASE-2
out dx, eax
mov al, 1
call try_loopback
test al, al
jz .set_first_available_media
DEBUGF 1,"Using 10BASE-2 port\n"
ret
 
.set_first_available_media:
DEBUGF 1,"Using the first available media\n"
 
;***************************************************************************
; Function
; set_available_media
; Description
; sets the first available media
; Parameters
; ebx - ptr to device struct
; Return value
; al - 0
; al - 1
; Destroyed registers
; eax, edx
;
;***************************************************************************
 
align 4
set_available_media:
 
DEBUGF 1,"Setting the available media\n"
; switch to register window 3
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+3
out dx, ax
 
set_io REG_MEDIA_OPTIONS
in ax, dx
DEBUGF 1,"available media:%x\n", al
mov cl, al
 
set_io REG_INTERNAL_CONFIG
in eax, dx
and eax, not (1111b shl 20) ; these bits hold the 'transceiver select' value
 
test cl, 10b ; baseTXAvailable
jz @f
 
DEBUGF 1,"base TX is available\n"
or eax, (100b shl 20)
if defined FORCE_FD
mov word [device.state], (1 shl 8)
else
mov word [device.mode], (1 shl 7)
end if
jmp .set_media
@@:
 
test cl, 100b ; baseFXAvailable
jz @f
 
DEBUGF 1,"base FX is available\n"
or eax, (101b shl 20)
mov word [device.state], (1 shl 10)
jmp .set_media
@@:
 
test cl, 1000000b ; miiDevice
jz @f
 
DEBUGF 1,"mii-device is available\n"
or eax, (0110b shl 20)
mov word [device.state], (1 shl 13)
jmp .set_media
@@:
 
test cl, 1000b ; 10bTAvailable
jz @f
 
DEBUGF 1,"10base-T is available\n"
.set_default:
if FORCE_FD
mov word [device.state], (1 shl 6)
else
mov word [device.state], (1 shl 5)
end if
jmp .set_media
@@:
 
test cl, 10000b ; coaxAvailable
jz @f
 
DEBUGF 1,"coax is available\n"
push eax
set_io REG_COMMAND
mov ax, (10b shl 11) ; EnableDcConverter
out dx, ax
pop eax
 
or eax, (11b shl 20)
mov word [device.state], (1 shl 12)
jmp .set_media
@@:
 
test cl, 10000b ; auiAvailable
jz .set_default
 
DEBUGF 1,"AUI is available\n"
or eax, (1 shl 20)
mov word [device.state], (1 shl 11)
 
.set_media:
set_io 0
set_io REG_INTERNAL_CONFIG
out dx, eax
 
if FORCE_FD
DEBUGF 1,"Forcing full duplex\n"
set_io REG_MAC_CONTROL
in ax, dx
or ax, 0x120
out dx, ax
end if
 
mov al, 1
ret
 
 
 
;***************************************************************************
; Function
; wake_up
; Description
; set the power state to D0
;
;***************************************************************************
 
align 4
wake_up:
 
DEBUGF 1,"Waking up NIC: "
 
; wake up - we directly do it by programming PCI
; check if the device is power management capable
stdcall PciRead32, [device.pci_bus], [device.pci_dev], PCI_REG_STATUS
 
test al, 10000b ; is there "new capabilities" linked list?
jz .device_awake
 
; search for power management register
stdcall PciRead16, [device.pci_bus], [device.pci_dev], PCI_REG_CAP_PTR
cmp al, 0x3f
jbe .device_awake
 
; traverse the list
movzx esi, al
.pm_loop:
stdcall PciRead32, [device.pci_bus], [device.pci_dev], esi
 
cmp al , 1
je .set_pm_state
 
movzx esi, ah
 
test ah , ah
jnz .pm_loop
jmp .device_awake
 
; waku up the device if necessary
.set_pm_state:
 
add esi, PCI_REG_PM_CTRL
stdcall PciRead32, [device.pci_bus], [device.pci_dev], esi
test al, 3
jz .device_awake
and al, not 11b ; set state to D0
stdcall PciWrite32, [device.pci_bus], [device.pci_dev], esi, eax
 
.device_awake:
DEBUGF 1,"Device is awake\n"
 
ret
 
 
 
 
;***************************************************************************
; Function
; write_eeprom
; Description
; reads eeprom
; Note : the caller must switch to the register window 0
; before calling this function
; Parameters:
; ax - register to be read (only the first 63 words can be read)
; cx - value to be read into the register
; Return value:
; ax - word read
; Destroyed registers
; ax, ebx, edx
;
;***************************************************************************
; align 4
;write_eeprom:
; mov edx, [io_addr]
; add edx, REG_EEPROM_COMMAND
; cmp ah, 11b
; ja .finish ; address may have a value of maximal 1023
; shl ax, 2
; shr al, 2
; push eax
;; wait for busy
; mov ebx, 0xffff
;@@:
; in ax, dx
; test ah, 0x80
; jz .write_enable
; dec ebx
; jns @r
;; write enable
;.write_enable:
; xor eax, eax
; mov eax, (11b shl 4)
; out dx, ax
;; wait for busy
; mov ebx, 0xffff
;@@:
; in ax, dx
; test ah, 0x80
; jz .erase_loop
; dec ebx
; jns @r
;.erase_loop:
; pop eax
; push eax
; or ax, (11b shl 6) ; erase register
; out dx, ax
; mov ebx, 0xffff
;@@:
; in ax, dx
; test ah, 0x80
; jz .write_reg
; dec ebx
; jns @r
;.write_reg:
; add edx, REG_EEPROM_DATA-REG_EEPROM_COMMAND
; mov eax, ecx
; out dx, ax
;; write enable
; add edx, REG_EEPROM_COMMAND-REG_EEPROM_DATA
; xor eax, eax
; mov eax, (11b shl 4)
; out dx, ax
; wait for busy
; mov ebx, 0xffff
;@@:
; in ax, dx
; test ah, 0x80
; jz .issue_write_reg
; dec ebx
; jns @r
;.issue_write_reg:
; pop eax
; or ax, 01b shl 6
; out dx, ax
;.finish:
; ret
 
 
;***************************************************************************
; Function
; read_eeprom
; Description
; reads eeprom
; Parameters:
; ax - register to be read (only the first 63 words can be read)
; ebx = driver structure
; Return value:
; ax - word read
; Destroyed registers
; ax, ebx, edx
;
;***************************************************************************
 
align 4
read_eeprom:
 
DEBUGF 1,"Reading from eeprom.. "
 
push eax
; switch to register window 0
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+0
out dx, ax
pop eax
and ax, 111111b ; take only the first 6 bits into account
movzx esi, [device.ver_id]
 
test word [esi*4+hw_versions+2], EEPROM_8BIT
jz @f
add ax, 0x230 ; hardware constant
jmp .read
@@:
 
add ax, EEPROM_CMD_READ
test word [esi*4+hw_versions+2], EEPROM_OFFSET
jz .read
add ax, 0x30
.read:
 
set_io REG_EEPROM_COMMAND
out dx, ax
mov ecx, 0xffff ; duration of about 162 us ;-)
.wait_for_reading:
in ax, dx
test ah, 0x80 ; check bit eepromBusy
jz .read_data
loop .wait_for_reading
.read_data:
set_io REG_EEPROM_DATA
in ax, dx
 
DEBUGF 1,"ok!\n"
 
ret
 
;***************************************************************************
; Function
; mdio_sync
; Description
; initial synchronization
; Parameters
; ebp - io_addr
; Return value
; Destroyed registers
; ax, edx, cl
;
;***************************************************************************
 
align 4
mdio_sync:
 
DEBUGF 1,"syncing mdio\n"
 
; switch to register window 4
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+4
out dx, ax
cmp [device.preamble], 0
je .no_preamble
; send 32 logic ones
set_io REG_PHYSICAL_MGMT
mov ecx, 31
.loop:
mov ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR)
out dx, ax
in ax, dx ; delay
mov ax, (1 shl BIT_MGMT_DATA) or (1 shl BIT_MGMT_DIR) or (1 shl BIT_MGMT_CLK)
out dx, ax
in ax, dx ; delay
loop .loop
.no_preamble:
 
ret
 
;***************************************************************************
; Function
; mdio_read
; Description
; read MII register
; see page 16 in D83840A.pdf
; Parameters
; ah - PHY addr
; al - register addr
; ebx = device structure
; Return value
; ax - register read
;
;***************************************************************************
 
align 4
mdio_read:
 
DEBUGF 1,"Reading MII registers\n"
 
push eax
call mdio_sync ; returns with window #4
pop eax
set_io 0
set_io REG_PHYSICAL_MGMT
shl al, 3
shr ax, 3
and ax, not MII_CMD_MASK
or ax, MII_CMD_READ
 
mov esi, eax
mov ecx, 13
.cmd_loop:
mov ax, (1 shl BIT_MGMT_DIR) ; write mii
bt esi, ecx
jnc .zero_bit
or al, (1 shl BIT_MGMT_DATA)
 
.zero_bit:
out dx, ax
push ax
in ax, dx ; delay
pop ax
or al, (1 shl BIT_MGMT_CLK) ; write
out dx, ax
in ax, dx ; delay
loop .cmd_loop
 
; read data (18 bits with the two transition bits)
mov ecx, 17
xor esi, esi
.read_loop:
shl esi, 1
xor eax, eax ; read comand
out dx, ax
in ax, dx ; delay
in ax, dx
test al, (1 shl BIT_MGMT_DATA)
jz .dont_set
inc esi
.dont_set:
mov ax, (1 shl BIT_MGMT_CLK)
out dx, ax
in ax, dx ; delay
loop .read_loop
mov eax, esi
 
ret
 
 
 
;***************************************************************************
; Function
; mdio_write
; Description
; write MII register
; see page 16 in D83840A.pdf
; Parameters
; ah - PHY addr
; al - register addr
; si - word to be written
; Return value
; ax - register read
;
;***************************************************************************
 
align 4
mdio_write:
 
DEBUGF 1,"Writing MII registers\n"
 
push eax
call mdio_sync
pop eax
set_io 0
set_io REG_PHYSICAL_MGMT
shl al, 3
shr ax, 3
and ax, not MII_CMD_MASK
or ax, MII_CMD_WRITE
shl eax, 2
or eax, 10b ; transition bits
shl eax, 16
mov ax, si
mov esi, eax
mov ecx, 31
 
.cmd_loop:
mov ax, (1 shl BIT_MGMT_DIR) ; write mii
bt esi, ecx
jnc @f
or al, (1 shl BIT_MGMT_DATA)
@@:
out dx, ax
push eax
in ax, dx ; delay
pop eax
or al, (1 shl BIT_MGMT_CLK) ; write
out dx, ax
in ax, dx ; delay
loop .cmd_loop
 
ret
 
 
;***************************************************************************
; Function
; check_tx_status
; Description
; Checks TxStatus queue.
; Return value
; al - 0 no error was found
; al - 1 error was found TxReset was needed
; Destroyed registers
; eax, ecx, edx, ebp
;
;***************************************************************************
 
align 4
check_tx_status:
 
DEBUGF 1,"Checking TX status\n"
 
; clear TxStatus queue
set_io 0
set_io REG_TX_STATUS
mov ecx, 31 ; max number of queue entries
 
.tx_status_loop:
in al, dx
test al, al
jz .finish ; no error
test al, 0x3f
jnz .error
.no_error_found:
; clear current TxStatus entry which advances the next one
xor al, al
out dx, al
loop .tx_status_loop
 
.finish:
 
ret
 
.error:
call tx_reset
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit (vortex) ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
vortex_transmit:
 
DEBUGF 1,"Sending packet (vortex)\n"
 
cmp dword [esp+8], MAX_ETH_FRAME_SIZE
ja .finish ; packet is too long
 
call check_tx_status
 
; switch to register window 7
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+7
out dx, ax
; check for master operation in progress
set_io REG_MASTER_STATUS
in ax, dx
test ah, 0x80
jnz .finish ; no DMA for sending
; program frame address to be sent
set_io REG_MASTER_ADDRESS
mov eax, [esp+4]
call GetPgAddr
out dx, eax
; program frame length
set_io REG_MASTER_LEN
mov eax, [esp+8]
;;; and eax, not 3
out dx, ax
; start DMA Down
set_io REG_COMMAND
mov ax, (10100b shl 11) + 1 ; StartDMADown
out dx, ax
.finish:
call KernelFree
add esp, 4
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit (boomerang) ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
boomerang_transmit:
 
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
mov eax, [esp+4]
DEBUGF 1,"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], MAX_ETH_FRAME_SIZE
ja .fail
 
call check_tx_status
 
; calculate descriptor address
mov esi, [device.prev_dpd]
DEBUGF 1,"Previous DPD: %x\n", esi
add esi, dpd.size
lea ecx, [device.dpd_buffer + (NUM_TX_DESC)*dpd.size]
cmp esi, ecx
jb @f
lea esi, [device.dpd_buffer] ; Wrap if needed
@@:
DEBUGF 1,"Found a free DPD: %x\n", esi
 
; check DnListPtr
set_io 0
set_io REG_DN_LIST_PTR
in eax, dx
; mark if Dn_List_Ptr is cleared
test eax, eax
setz [device.dn_list_ptr_cleared]
 
; finish if no more free descriptor is available - FIXME!
; cmp eax, esi
; jz .finish
 
; update statistics
inc [device.packets_tx]
mov ecx, [esp+8] ; buffer size
add dword [device.bytes_tx], ecx
adc dword [device.bytes_tx + 4], 0
 
; program DPD
and [esi+dpd.next_ptr], 0
mov eax, [esp+4] ; Tx buffer address
mov [esi+dpd.realaddr], eax
call GetPgAddr
mov [esi+dpd.frag_addr], eax
mov ecx, [esp+8] ; packet size
or ecx, 0x80000000 ; last fragment
mov [esi+dpd.frag_len], ecx
 
mov ecx, [esp+8] ; packet size
; or ecx, 0x8000 ; transmission complete notification
 
or ecx, 1 shl 31
 
; test byte [device.has_hwcksm], 0xff
; jz @f
; or ecx, (1 shl 26) ; set AddTcpChecksum
;@@:
mov [esi+dpd.frame_start_hdr], ecx
 
DEBUGF 1,"DPD: lin=%x phys=%x len=%x start hdr=%x\n", [esi+dpd.realaddr]:8, [esi+dpd.frag_addr]:8, [esi+dpd.frag_len]:8, [esi+dpd.frame_start_hdr]:8
 
; calculate physical address of dpd
mov eax, esi
GetRealAddr
cmp [device.dn_list_ptr_cleared], 0
jz .add_to_list
 
; write Dn_List_Ptr
DEBUGF 1,"DPD phys addr=%x\n", eax
set_io 0
set_io REG_DN_LIST_PTR
out dx, eax
jmp .finish
 
.add_to_list:
DEBUGF 1,"Adding To list\n"
push eax
; DnStall
set_io 0
set_io REG_COMMAND
mov ax, ((110b shl 11)+2)
out dx, ax
 
; wait for DnStall to complete
DEBUGF 1,"Waiting for DnStall\n"
mov ecx, 6000
.wait_for_stall:
in ax, dx ; read REG_INT_STATUS
test ah, 10000b
jz .dnstall_ok
dec ecx
jnz .wait_for_stall
 
.dnstall_ok:
DEBUGF 1,"DnStall ok!\n"
mov ecx, [device.prev_dpd]
mov [ecx+dpd.next_ptr], eax
 
set_io 0
set_io REG_DN_LIST_PTR
in eax, dx
test eax, eax
pop eax
jnz .dnunstall
 
; if Dn_List_Ptr has been cleared fill it up
DEBUGF 1,"DnList Ptr has been cleared\n"
out dx, eax
 
.dnunstall:
; DnUnStall
set_io 0
set_io REG_COMMAND
mov ax, ((110b shl 11)+3)
out dx, ax
 
.finish:
mov [device.prev_dpd], esi
xor eax, eax
ret 8
 
.fail:
stdcall KernelFree, [esp+4]
or eax, -1
ret 8
 
 
;---------------------------------
; Write MAC
 
align 4
write_mac:
 
DEBUGF 1,"Writing mac\n"
 
set_io 0
set_io REG_COMMAND
 
; switch to register window 2
mov ax, SELECT_REGISTER_WINDOW+2
out dx, ax
 
; write MAC addres back into the station address registers
set_io REG_STATION_ADDRESS_LO
lea esi, [device.mac]
outsw
inc dx
inc dx
outsw
inc dx
inc dx
outsw
 
 
;----------------------------
; Read MAC
 
align 4
read_mac:
 
set_io 0
set_io REG_COMMAND
 
; switch to register window 2
mov ax, SELECT_REGISTER_WINDOW+2
out dx, ax
 
; write MAC addres back into the station address registers
set_io REG_STATION_ADDRESS_LO
lea edi, [device.mac]
insw
inc dx
inc dx
insw
inc dx
inc dx
insw
 
DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
ret
 
 
;------------------------------------
; Read MAC from eeprom
 
align 4
read_mac_eeprom: ; Tested - ok
 
DEBUGF 1,"Reading mac from eeprom\n"
 
; read MAC from eeprom
mov ecx, 3
.mac_loop:
lea ax, [EEPROM_REG_OEM_NODE_ADDR+ecx-1]
push ecx
call read_eeprom
pop ecx
xchg ah, al ; htons
mov word [device.mac+ecx*2-2], ax
loop .mac_loop
 
DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
ret
 
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Vortex Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_vortex:
 
push ebx esi edi
 
DEBUGF 1,"\n%s int\n", my_service
 
; find pointer of device wich made IRQ occur
 
mov esi, VORTEX_LIST
mov ecx, [VORTEX_DEVICES]
test ecx, ecx
jz .nothing
.nextdevice:
mov ebx, dword [esi]
 
 
set_io 0
set_io REG_INT_STATUS
in ax, dx
and ax, S_5_INTS
jnz .nothing
 
add esi, 4
 
test ax , ax
jnz .got_it
loop .nextdevice
 
.nothing:
pop edi esi ebx
xor eax, eax
 
ret
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x ",ebx,eax:4
 
test ax, RxComplete
jz .noRX
 
set_io 0
.rx_status_loop:
; examine RxStatus
set_io REG_RX_STATUS
in ax, dx
test ax, ax
jz .finish
 
test ah, 0x80 ; rxIncomplete
jnz .finish
 
test ah, 0x40
jz .check_length
 
; discard the top frame received advancing the next one
set_io REG_COMMAND
mov ax, (01000b shl 11)
out dx, ax
jmp .rx_status_loop
 
.check_length:
and eax, 0x1fff
cmp eax, MAX_ETH_PKT_SIZE
ja .discard_frame ; frame is too long discard it
 
.check_dma:
mov ecx, eax
; switch to register window 7
set_io 0
set_io REG_COMMAND
mov ax, SELECT_REGISTER_WINDOW+7
out dx, ax
; check for master operation in progress
set_io REG_MASTER_STATUS
in ax, dx
 
test ah, 0x80
jnz .finish
 
.read_frame:
; program buffer address to read in
push ecx
stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
pop ecx
test eax, eax
jz .finish
 
push .discard_frame
push ecx
push eax
; zero_to_dma eax
set_io REG_MASTER_ADDRESS
out dx, eax
 
; program frame length
set_io REG_MASTER_LEN
mov ax, 1560
out dx, ax
 
; start DMA Up
set_io REG_COMMAND
mov ax, (10100b shl 11) ; StartDMAUp
out dx, ax
 
; check for master operation in progress
set_io REG_MASTER_STATUS ; TODO: use timeout and reset after timeout expired
.dma_loop:
in ax, dx
test ah, 0x80
jnz .dma_loop
 
; registrate the received packet to kernel
jmp Eth_input
 
; discard the top frame received
.discard_frame:
set_io 0
set_io REG_COMMAND
mov ax, (01000b shl 11)
out dx, ax
 
.finish:
 
 
.noRX:
 
test ax, DMADone
jz .noDMA
 
push ax
 
set_io 0
set_io 12
in ax, dx
test ax, 0x1000
jz .nodmaclear
 
mov ax, 0x1000
out dx, ax
 
.nodmaclear:
 
pop ax
 
DEBUGF 1, "DMA Done!\n", cx
 
 
 
.noDMA:
 
 
 
.ACK:
set_io 0
set_io REG_COMMAND
mov ax, AckIntr + IntReq + IntLatch
out dx, ax
 
pop edi esi ebx
 
ret
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Boomerang Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_boomerang:
 
push ebx esi edi
 
DEBUGF 1,"\n%s int\n", my_service
 
; find pointer of device wich made IRQ occur
 
mov ecx, [BOOMERANG_DEVICES]
test ecx, ecx
jz .nothing
mov esi, BOOMERANG_LIST
.nextdevice:
mov ebx, [esi]
 
set_io 0
set_io REG_INT_STATUS
in ax, dx
test ax, ax
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, ax
push ax
 
; disable all INTS
 
set_io REG_COMMAND
mov ax, SetIntrEnb
out dx, ax
 
;--------------------------------------------------------------------------
test word[esp], UpComplete
jz .noRX
 
push ebx
 
.receive:
DEBUGF 1,"UpComplete\n"
 
; check if packet is uploaded
mov esi, [device.curr_upd]
test byte [esi+upd.pkt_status+1], 0x80 ; upPktComplete
jz .finish
DEBUGF 1, "Current upd: %x\n", esi
; packet is uploaded check for any error
.check_error:
test byte [esi+upd.pkt_status+1], 0x40 ; upError
jz .copy_packet_length
DEBUGF 1,"Error in packet\n"
and [esi+upd.pkt_status], 0 ; mark packet as read
jmp .finish
.copy_packet_length:
mov ecx, [esi+upd.pkt_status]
and ecx, 0x1fff
 
; cmp ecx, MAX_ETH_PKT_SIZE
; jbe .copy_packet
; and [esi+upd.pkt_status], 0
; jmp .finish
; .copy_packet:
 
DEBUGF 1, "Received %u bytes in buffer %x\n", ecx, [esi+upd.realaddr]:8
 
push dword .loop ;.finish
push ecx
push [esi+upd.realaddr]
 
; update statistics
inc [device.packets_rx]
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
 
; update UPD (Alloc new buffer for next packet)
stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
mov [esi + upd.realaddr], eax
GetRealAddr
mov [esi + upd.frag_addr], eax
and [esi + upd.pkt_status], 0
mov [esi + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
 
; Update UPD pointer
add esi, upd.size
lea ecx, [device.upd_buffer+(NUM_RX_DESC)*upd.size]
cmp esi, ecx
jb @f
lea esi, [device.upd_buffer]
@@:
mov [device.curr_upd], esi
DEBUGF 1, "Next upd: %x\n", esi
 
jmp Eth_input
.loop:
 
mov ebx, [esp]
jmp .receive
 
.finish:
pop ebx
 
; check if the NIC is in the upStall state
set_io 0
set_io REG_UP_PKT_STATUS
in eax, dx
test ah, 0x20 ; UpStalled
jz .noUpUnStall
 
DEBUGF 1, "upUnStalling\n"
; issue upUnStall command
set_io REG_COMMAND
mov ax, ((11b shl 12)+1) ; upUnStall
out dx, ax
 
;;;; FIXME: make upunstall work
 
.noUpUnStall:
.noRX:
test word[esp], DownComplete
jz .noTX
DEBUGF 1, "Downcomplete!\n"
 
mov ecx, NUM_TX_DESC
lea esi, [device.dpd_buffer]
.txloop:
test [esi+dpd.frame_start_hdr], 1 shl 31
jz .maybenext
 
and [esi+dpd.frame_start_hdr], 0
push ecx
stdcall KernelFree, [esi+dpd.realaddr]
pop ecx
 
.maybenext:
add esi, dpd.size
dec ecx
jnz .txloop
 
.noTX:
pop ax
 
set_io 0
set_io REG_COMMAND
or ax, AckIntr
out dx, ax
 
set_io REG_INT_STATUS
in ax, dx
test ax, S_5_INTS
jnz .got_it
 
;re-enable ints
set_io REG_COMMAND
mov ax, SetIntrEnb + S_5_INTS
out dx, ax
 
pop edi esi ebx
 
ret
 
 
 
 
; End of code
align 4 ; Place all initialised data here
 
macro strtbl name, [string]
{
common
label name dword
forward
local label
dd label
forward
label db string, 0
}
 
VORTEX_DEVICES dd 0
BOOMERANG_DEVICES dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db '3C59X',0 ; max 16 chars include zero
 
 
strtbl link_str, \
"No valid link type detected", \
"10BASE-T half duplex", \
"10BASE-T full-duplex", \
"100BASE-TX half duplex", \
"100BASE-TX full duplex", \
"100BASE-T4", \
"100BASE-FX", \
"10Mbps AUI", \
"10Mbps COAX (BNC)", \
"miiDevice - not supported"
 
strtbl hw_str, \
"3c590 Vortex 10Mbps", \
"3c592 EISA 10Mbps Demon/Vortex", \
"3c597 EISA Fast Demon/Vortex", \
"3c595 Vortex 100baseTx", \
"3c595 Vortex 100baseT4", \
"3c595 Vortex 100base-MII", \
"3c900 Boomerang 10baseT", \
"3c900 Boomerang 10Mbps Combo", \
"3c900 Cyclone 10Mbps TPO", \
"3c900 Cyclone 10Mbps Combo", \
"3c900 Cyclone 10Mbps TPC", \
"3c900B-FL Cyclone 10base-FL", \
"3c905 Boomerang 100baseTx", \
"3c905 Boomerang 100baseT4", \
"3c905B Cyclone 100baseTx", \
"3c905B Cyclone 10/100/BNC", \
"3c905B-FX Cyclone 100baseFx", \
"3c905C Tornado", \
"3c980 Cyclone", \
"3c982 Dual Port Server Cyclone", \
"3cSOHO100-TX Hurricane", \
"3c555 Laptop Hurricane", \
"3c556 Laptop Tornado", \
"3c556B Laptop Hurricane", \
"3c575 [Megahertz] 10/100 LAN CardBus", \
"3c575 Boomerang CardBus", \
"3CCFE575BT Cyclone CardBus", \
"3CCFE575CT Tornado CardBus", \
"3CCFE656 Cyclone CardBus", \
"3CCFEM656B Cyclone+Winmodem CardBus", \
"3CXFEM656C Tornado+Winmodem CardBus", \
"3c450 HomePNA Tornado", \
"3c920 Tornado", \
"3c982 Hydra Dual Port A", \
"3c982 Hydra Dual Port B", \
"3c905B-T4", \
"3c920B-EMB-WNM Tornado"
 
 
 
align 4
hw_versions:
dw 0x5900, IS_VORTEX ; 3c590 Vortex 10Mbps
dw 0x5920, IS_VORTEX ; 3c592 EISA 10Mbps Demon/Vortex
dw 0x5970, IS_VORTEX ; 3c597 EISA Fast Demon/Vortex
dw 0x5950, IS_VORTEX ; 3c595 Vortex 100baseTx
dw 0x5951, IS_VORTEX ; 3c595 Vortex 100baseT4
dw 0x5952, IS_VORTEX ; 3c595 Vortex 100base-MII
dw 0x9000, IS_BOOMERANG ; 3c900 Boomerang 10baseT
dw 0x9001, IS_BOOMERANG ; 3c900 Boomerang 10Mbps Combo
dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPO
dw 0x9005, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps Combo
dw 0x9006, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPC
dw 0x900A, IS_CYCLONE or HAS_HWCKSM ; 3c900B-FL Cyclone 10base-FL
dw 0x9050, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseTx
dw 0x9051, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseT4
dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B Cyclone 100baseTx
dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c905B Cyclone 10/100/BNC
dw 0x905A, IS_CYCLONE or HAS_HWCKSM ; 3c905B-FX Cyclone 100baseFx
dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c905C Tornado
dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c980 Cyclone
dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c982 Dual Port Server Cyclone
dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3cSOHO100-TX Hurricane
dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM ; 3c555 Laptop Hurricane
dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM ; 3c556 Laptop Tornado
dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS or INVERT_MII_PWR or HAS_HWCKSM ; 3c556B Laptop Hurricane
dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 [Megahertz] 10/100 LAN CardBus
dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 Boomerang CardBus
dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE575BT Cyclone CardBus
dw 0x5257, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CCFE575CT Tornado CardBus
dw 0x6560, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE656 Cyclone CardBus
dw 0x6562, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFEM656B Cyclone+Winmodem CardBus
dw 0x6564, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CXFEM656C Tornado+Winmodem CardBus
dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c450 HomePNA Tornado
dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920 Tornado
dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port A
dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port B
dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B-T4
dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920B-EMB-WNM Tornado
HW_VERSIONS_SIZE = $ - hw_versions
 
include_debug_strings ; All data wich FDO uses will be included here
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
 
VORTEX_LIST rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
BOOMERANG_LIST rd MAX_DEVICES
 
 
 
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/ethernet/R6040.asm
0,0 → 1,1120
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; R6040 driver for KolibriOS ;;
;; ;;
;; based on R6040.c from linux ;;
;; ;;
;; Written by Asper (asper.85@mail.ru) ;;
;; and hidnplayr (hidnplayr@gmail.com) ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 2
 
W_MAX_TIMEOUT = 0x0FFF ; max time out delay time
 
TX_TIMEOUT = 6000 ; Time before concluding the transmitter is hung, in ms
 
TX_RING_SIZE = 4 ; RING sizes must be a power of 2
RX_RING_SIZE = 4
 
RX_BUF_LEN_IDX = 3 ; 0==8K, 1==16K, 2==32K, 3==64K
 
; Threshold is bytes transferred to chip before transmission starts.
 
TX_FIFO_THRESH = 256 ; In bytes, rounded down to 32 byte units.
 
; The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024.
 
RX_FIFO_THRESH = 4 ; Rx buffer level before first PCI xfer.
RX_DMA_BURST = 4 ; Maximum PCI burst, '4' is 256 bytes
TX_DMA_BURST = 4
 
 
 
include '../proc32.inc'
include '../imports.inc'
include '../fdo.inc'
include '../netdrv.inc'
 
public START
public service_proc
public version
 
; Operational parameters that usually are not changed.
 
PHY1_ADDR = 1 ;For MAC1
PHY2_ADDR = 3 ;For MAC2
PHY_MODE = 0x3100 ;PHY CHIP Register 0
PHY_CAP = 0x01E1 ;PHY CHIP Register 4
 
;**************************************************************************
; RDC R6040 Register Definitions
;**************************************************************************
MCR0 = 0x00 ;Control register 0
MCR1 = 0x01 ;Control register 1
MAC_RST = 0x0001 ;Reset the MAC
MBCR = 0x08 ;Bus control
MT_ICR = 0x0C ;TX interrupt control
MR_ICR = 0x10 ;RX interrupt control
MTPR = 0x14 ;TX poll command register
MR_BSR = 0x18 ;RX buffer size
MR_DCR = 0x1A ;RX descriptor control
MLSR = 0x1C ;Last status
MMDIO = 0x20 ;MDIO control register
MDIO_WRITE = 0x4000 ;MDIO write
MDIO_READ = 0x2000 ;MDIO read
MMRD = 0x24 ;MDIO read data register
MMWD = 0x28 ;MDIO write data register
MTD_SA0 = 0x2C ;TX descriptor start address 0
MTD_SA1 = 0x30 ;TX descriptor start address 1
MRD_SA0 = 0x34 ;RX descriptor start address 0
MRD_SA1 = 0x38 ;RX descriptor start address 1
MISR = 0x3C ;Status register
MIER = 0x40 ;INT enable register
MSK_INT = 0x0000 ;Mask off interrupts
RX_FINISH = 0x0001 ;RX finished
RX_NO_DESC = 0x0002 ;No RX descriptor available
RX_FIFO_FULL = 0x0004 ;RX FIFO full
RX_EARLY = 0x0008 ;RX early
TX_FINISH = 0x0010 ;TX finished
TX_EARLY = 0x0080 ;TX early
EVENT_OVRFL = 0x0100 ;Event counter overflow
LINK_CHANGED = 0x0200 ;PHY link changed
ME_CISR = 0x44 ;Event counter INT status
ME_CIER = 0x48 ;Event counter INT enable
MR_CNT = 0x50 ;Successfully received packet counter
ME_CNT0 = 0x52 ;Event counter 0
ME_CNT1 = 0x54 ;Event counter 1
ME_CNT2 = 0x56 ;Event counter 2
ME_CNT3 = 0x58 ;Event counter 3
MT_CNT = 0x5A ;Successfully transmit packet counter
ME_CNT4 = 0x5C ;Event counter 4
MP_CNT = 0x5E ;Pause frame counter register
MAR0 = 0x60 ;Hash table 0
MAR1 = 0x62 ;Hash table 1
MAR2 = 0x64 ;Hash table 2
MAR3 = 0x66 ;Hash table 3
MID_0L = 0x68 ;Multicast address MID0 Low
MID_0M = 0x6A ;Multicast address MID0 Medium
MID_0H = 0x6C ;Multicast address MID0 High
MID_1L = 0x70 ;MID1 Low
MID_1M = 0x72 ;MID1 Medium
MID_1H = 0x74 ;MID1 High
MID_2L = 0x78 ;MID2 Low
MID_2M = 0x7A ;MID2 Medium
MID_2H = 0x7C ;MID2 High
MID_3L = 0x80 ;MID3 Low
MID_3M = 0x82 ;MID3 Medium
MID_3H = 0x84 ;MID3 High
PHY_CC = 0x88 ;PHY status change configuration register
PHY_ST = 0x8A ;PHY status register
MAC_SM = 0xAC ;MAC status machine
MAC_ID = 0xBE ;Identifier register
 
MAX_BUF_SIZE = 0x600 ;1536
 
MBCR_DEFAULT = 0x012A ;MAC Bus Control Register
MCAST_MAX = 3 ;Max number multicast addresses to filter
 
;Descriptor status
DSC_OWNER_MAC = 0x8000 ;MAC is the owner of this descriptor
DSC_RX_OK = 0x4000 ;RX was successfull
DSC_RX_ERR = 0x0800 ;RX PHY error
DSC_RX_ERR_DRI = 0x0400 ;RX dribble packet
DSC_RX_ERR_BUF = 0x0200 ;RX length exceeds buffer size
DSC_RX_ERR_LONG = 0x0100 ;RX length > maximum packet length
DSC_RX_ERR_RUNT = 0x0080 ;RX packet length < 64 byte
DSC_RX_ERR_CRC = 0x0040 ;RX CRC error
DSC_RX_BCAST = 0x0020 ;RX broadcast (no error)
DSC_RX_MCAST = 0x0010 ;RX multicast (no error)
DSC_RX_MCH_HIT = 0x0008 ;RX multicast hit in hash table (no error)
DSC_RX_MIDH_HIT = 0x0004 ;RX MID table hit (no error)
DSC_RX_IDX_MID_MASK = 3 ;RX mask for the index of matched MIDx
 
;PHY settings
ICPLUS_PHY_ID = 0x0243
 
RX_INTS = RX_FIFO_FULL or RX_NO_DESC or RX_FINISH
TX_INTS = TX_FINISH
INT_MASK = RX_INTS or TX_INTS
 
RX_BUF_LEN equ (8192 << RX_BUF_LEN_IDX) ; Size of the in-memory receive ring.
 
IO_SIZE = 256 ; RDC MAC I/O Size
MAX_MAC = 2 ; MAX RDC MAC
 
 
virtual at 0
x_head:
.status dw ? ;0-1
.len dw ? ;2-3
.buf dd ? ;4-7
.ndesc dd ? ;8-B
.rev1 dd ? ;C-F
.vbufp dd ? ;10-13
.vndescp dd ? ;14-17
.skb_ptr dd ? ;18-1B
.rev2 dd ? ;1C-1F
.sizeof:
end virtual
 
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.io_addr dd ?
 
.cur_rx dw ?
.cur_tx dw ?
.last_tx dw ?
.phy_addr dw ?
.phy_mode dw ?
.mcr0 dw ?
.mcr1 dw ?
.switch_sig dw ?
 
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
 
rb 3 ; dword alignment
 
.tx_ring: rb (((x_head.sizeof*TX_RING_SIZE)+32) and 0xfffffff0)
.rx_ring: rb (((x_head.sizeof*RX_RING_SIZE)+32) and 0xfffffff0)
 
.size = $ - 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 @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
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, device.size, .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 io addres of the PCI device
 
PCI_find_io
 
; We've found the io 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.io_addr]:4
 
; Ok, the eth_device structure is ready, let's probe the device
cli
 
call probe ; this function will output in eax
test eax, eax
jnz .err_sti ; 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
sti
 
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_sti:
sti
 
.err:
stdcall KernelFree, ebx
 
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
macro mdio_write reg, val {
stdcall phy_read, [device.io_addr], [device.phy_addr], reg
}
 
macro mdio_write reg, val {
stdcall phy_write, [device.io_addr], [devce.phy_addr], reg, val
}
 
 
align 4
unload:
; TODO: (in this particular order)
;
; - Stop the device
; - Detach int handler
; - Remove device from local list (RTL8139_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 RTL8139)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
probe:
DEBUGF 2,"Probing R6040 device\n"
 
PCI_make_bus_master
 
; If PHY status change register is still set to zero
; it means the bootloader didn't initialize it
 
set_io 0
set_io PHY_CC
in ax, dx
test ax, ax
jnz @f
mov ax, 0x9F07
out dx, ax
@@:
 
call read_mac
 
; Some bootloaders/BIOSes do not initialize MAC address, warn about that
and eax, 0xFF
or eax, dword [device.mac]
test eax, eax
jnz @f
DEBUGF 2, "ERROR: MAC address not initialized!\n"
 
@@:
; Init RDC private data
mov [device.mcr0], 0x1002
;mov [private.phy_addr], 1 ; Asper: Only one network card is supported now.
mov [device.switch_sig], 0
 
; Check the vendor ID on the PHY, if 0xFFFF assume none attached
stdcall phy_read, 1, 2
cmp ax, 0xFFFF
jne @f
DEBUGF 2, "Failed to detect an attached PHY\n" ;, generating random"
mov eax, -1
ret
@@:
 
; Set MAC address
call init_mac_regs
 
; Initialize and alloc RX/TX buffers
call init_txbufs
call init_rxbufs
 
; Read the PHY ID
mov [device.phy_mode], 0x8000
stdcall phy_read, 0, 2
mov [device.switch_sig], ax
cmp ax, ICPLUS_PHY_ID
jne @f
stdcall phy_write, 29, 31, 0x175C ; Enable registers
jmp .phy_readen
@@:
 
; PHY Mode Check
movzx eax, [device.phy_addr]
stdcall phy_write, eax, 4, PHY_CAP
stdcall phy_write, eax, 0, PHY_MODE
 
if PHY_MODE = 0x3100
call phy_mode_chk
mov [device.phy_mode], ax
jmp .phy_readen
end if
 
if not (PHY_MODE and 0x0100)
mov [device.phy_mode], 0
end if
 
.phy_readen:
 
; Set duplex mode
mov ax, [device.phy_mode]
or [device.mcr0], ax
 
; improve performance (by RDC guys)
stdcall phy_read, 30, 17
or ax, 0x4000
stdcall phy_write, 30, 17, eax
 
stdcall phy_read, 30, 17
and ax, not 0x2000
stdcall phy_write, 30, 17, eax
 
stdcall phy_write, 0, 19, 0x0000
stdcall phy_write, 0, 30, 0x01F0
 
; Initialize all Mac registers
call init_mac_regs
 
 
 
align 4
reset:
 
DEBUGF 2,"Resetting R6040\n"
 
; Mask off Interrupt
xor ax, ax
set_io 0
set_io MIER
out dx, ax
 
 
; attach int handler
 
movzx eax, [device.irq_line]
DEBUGF 2,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax
jnz @f
DEBUGF 2,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
 
;Reset RDC MAC
mov eax, MAC_RST
set_io 0
set_io MCR1
out dx, ax
 
mov ecx, 2048 ;limit
.read:
in ax, dx
test ax, 0x1
jnz @f
dec ecx
test ecx, ecx
jnz .read
@@:
;Reset internal state machine
mov ax, 2
set_io MAC_SM
out dx, ax
 
xor ax, ax
out dx, ax
 
mov esi, 5
stdcall Sleep
 
;MAC Bus Control Register
mov ax, MBCR_DEFAULT
set_io 0
set_io MBCR
out dx, ax
 
;Buffer Size Register
mov ax, MAX_BUF_SIZE
set_io MR_BSR
out dx, ax
 
;Write TX ring start address
lea eax, [device.tx_ring]
GetRealAddr
set_io MTD_SA0
out dx, ax
shr eax, 16
set_io MTD_SA1
out dx, ax
 
;Write RX ring start address
lea eax, [device.rx_ring]
GetRealAddr
set_io MRD_SA0
out dx, ax
shr eax, 16
set_io MRD_SA1
out dx, ax
 
;Set interrupt waiting time and packet numbers
xor ax, ax
set_io MT_ICR
out dx, ax
 
;Enable interrupts
mov ax, INT_MASK
set_io MIER
out dx, ax
 
;Enable TX and RX
mov ax, [device.mcr0]
or ax, 0x0002
set_io 0
out dx, ax
 
;Let TX poll the descriptors
;we may got called by tx_timeout which has left
;some unset tx buffers
xor ax, ax
inc ax
set_io 0
set_io MTPR
out dx, ax
 
; 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
 
DEBUGF 1,"Reset ok\n"
xor eax, eax
ret
 
 
 
align 4
init_txbufs:
 
DEBUGF 1,"Init TxBufs\n"
 
lea esi, [device.tx_ring]
lea eax, [device.tx_ring + x_head.sizeof]
GetRealAddr
mov ecx, TX_RING_SIZE
 
.next_desc:
mov [esi + x_head.ndesc], eax
mov [esi + x_head.skb_ptr], 0
mov [esi + x_head.status], DSC_OWNER_MAC
 
add eax, x_head.sizeof
add esi, x_head.sizeof
 
dec ecx
jnz .next_desc
 
lea eax, [device.tx_ring]
GetRealAddr
mov [device.tx_ring + x_head.sizeof*(TX_RING_SIZE - 1) + x_head.ndesc], eax
 
ret
 
 
 
align 4
init_rxbufs:
 
DEBUGF 1,"Init RxBufs\n"
 
lea esi, [device.rx_ring]
lea eax, [device.rx_ring + x_head.sizeof]
GetRealAddr
mov edx, eax
mov ecx, RX_RING_SIZE
 
.next_desc:
mov [esi + x_head.ndesc], edx
 
push esi ecx
stdcall KernelAlloc, MAX_BUF_SIZE
pop ecx esi
 
mov [esi + x_head.skb_ptr], eax
GetRealAddr
mov [esi + x_head.buf], eax
mov [esi + x_head.status], DSC_OWNER_MAC
 
add edx, x_head.sizeof
add esi, x_head.sizeof
 
dec ecx
jnz .next_desc
 
; complete the ring by linking the last to the first
 
lea eax, [device.rx_ring]
GetRealAddr
mov [device.rx_ring + x_head.sizeof*(RX_RING_SIZE - 1) + x_head.ndesc], eax
 
ret
 
 
 
align 4
phy_mode_chk:
 
DEBUGF 1,"Checking PHY mode\n"
 
; PHY Link Status Check
movzx eax, [device.phy_addr]
stdcall phy_read, eax, 1
test eax, 0x4
jz .ret_0x8000
 
; PHY Chip Auto-Negotiation Status
movzx eax, [device.phy_addr]
stdcall phy_read, eax, 1
test eax, 0x0020
jnz .auto_nego
 
; Force Mode
movzx eax, [device.phy_addr]
stdcall phy_read, eax, 0
test eax, 0x100
jnz .ret_0x8000
 
.auto_nego:
; Auto Negotiation Mode
movzx eax, [device.phy_addr]
stdcall phy_read, eax, 5
mov ecx, eax
movzx eax, [device.phy_addr]
stdcall phy_read, eax, 4
and eax, ecx
test eax, 0x140
jnz .ret_0x8000
 
xor eax, eax
ret
 
.ret_0x8000:
mov eax, 0x8000
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
 
movzx edi, [device.cur_tx]
shl edi, 5
add edi, ebx
add edi, device.tx_ring - ebx
 
DEBUGF 2,"TX buffer status: 0x%x\n", [edi + x_head.status]:4
 
test [edi + x_head.status], DSC_OWNER_MAC ; check if buffer is available
jnz .wait_to_send
 
.do_send:
 
DEBUGF 2,"Sending now\n"
 
mov eax, [esp+4]
mov [edi + x_head.skb_ptr], eax
GetRealAddr
mov [edi + x_head.buf], eax
mov ecx, [esp+8]
mov [edi + x_head.len], cx
mov [edi + x_head.status], DSC_OWNER_MAC
 
; Trigger the MAC to check the TX descriptor
mov ax, 0x01
set_io 0
set_io MTPR
out dx, ax
 
inc [device.cur_tx]
and [device.cur_tx], TX_RING_SIZE - 1
xor eax, eax
 
; 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
 
.wait_to_send:
 
DEBUGF 2,"Waiting for TX buffer\n"
 
call GetTimerTicks ; returns in eax
lea edx, [eax + 100]
.l2:
test [edi + x_head.status], DSC_OWNER_MAC
jz .do_send
mov esi, 10
call Sleep
call GetTimerTicks
cmp edx, eax
jb .l2
 
DEBUGF 1,"Send timeout\n"
xor eax, eax
dec eax
.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]
 
set_io 0
set_io MISR
in ax, dx
out dx, ax ; send it back to ACK
test ax, ax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
pop edi esi ebx
xor eax, eax
 
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
 
 
; At this point, test for all possible reasons, and handle accordingly
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x ", ebx, ax
 
push ax
 
test word [esp], RX_FINISH
jz .no_RX
 
push ebx
.more_RX:
pop ebx
 
; Find the current RX descriptor
 
movzx edx, [device.cur_rx]
shl edx, 5
lea edx, [device.rx_ring + edx]
 
; Check the descriptor status
 
mov cx, [edx + x_head.status]
test cx, DSC_OWNER_MAC
jnz .no_RX
 
DEBUGF 2,"packet status=0x%x\n", cx
 
test cx, DSC_RX_ERR ; Global error status set
jnz .no_RX
 
; Packet successfully received
 
movzx ecx, [edx + x_head.len]
and ecx, 0xFFF
sub ecx, 4 ; Do not count the CRC
 
; Update stats
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
inc dword [device.packets_rx]
 
; Push packet size and pointer, kernel will need it..
 
push ebx
push .more_RX
 
push ecx
push [edx + x_head.skb_ptr]
 
DEBUGF 2,"packet ptr=0x%x\n", [edx + x_head.skb_ptr]
 
; reset the RX descriptor
 
push edx
stdcall KernelAlloc, MAX_BUF_SIZE
pop edx
mov [edx + x_head.skb_ptr], eax
GetRealAddr
mov [edx + x_head.buf], eax
mov [edx + x_head.status], DSC_OWNER_MAC
 
; Use next descriptor next time
 
inc [device.cur_rx]
and [device.cur_rx], RX_RING_SIZE - 1
 
; At last, send packet to kernel
 
jmp Eth_input
 
 
.no_RX:
 
test word [esp], TX_FINISH
jz .no_TX
 
.loop_tx:
movzx edi, [device.last_tx]
shl edi, 5
lea edi, [device.tx_ring + edi]
 
test [edi + x_head.status], DSC_OWNER_MAC
jnz .no_TX
 
cmp [edi + x_head.skb_ptr], 0
je .no_TX
 
DEBUGF 2,"Freeing buffer 0x%x\n", [edi + x_head.skb_ptr]
 
push [edi + x_head.skb_ptr]
mov [edi + x_head.skb_ptr], 0
call KernelFree
 
inc [device.last_tx]
and [device.last_tx], TX_RING_SIZE - 1
 
jmp .loop_tx
 
.no_TX:
pop ax
 
pop edi esi ebx
 
ret
 
 
 
 
align 4
init_mac_regs:
 
DEBUGF 2,"initializing MAC regs\n"
 
; MAC operation register
mov ax, 1
set_io 0
set_io MCR1
out dx, ax
; Reset MAC
mov ax, 2
set_io MAC_SM
out dx, ax
; Reset internal state machine
xor ax, ax
out dx, ax
mov esi, 5
stdcall Sleep
 
call read_mac
 
ret
 
 
 
 
; Read a word data from PHY Chip
 
align 4
proc phy_read stdcall, phy_addr:dword, reg:dword
 
DEBUGF 2,"PHY read, addr=0x%x reg=0x%x\n", [phy_addr]:8, [reg]:8
 
mov eax, [phy_addr]
shl eax, 8
add eax, [reg]
add eax, MDIO_READ
set_io 0
set_io MMDIO
out dx, ax
 
;Wait for the read bit to be cleared.
mov ecx, 2048 ;limit
.read:
in ax, dx
test ax, MDIO_READ
jz @f
dec ecx
jnz .read
@@:
 
set_io MMRD
in ax, dx
and eax, 0xFFFF
 
DEBUGF 2,"PHY read, val=0x%x\n", eax:4
 
ret
 
endp
 
 
 
 
; Write a word data to PHY Chip
 
align 4
proc phy_write stdcall, phy_addr:dword, reg:dword, val:dword
 
DEBUGF 2,"PHY write, addr=0x%x reg=0x%x val=0x%x\n", [phy_addr]:8, [reg]:8, [val]:8
 
mov eax, [val]
set_io 0
set_io MMWD
out dx, ax
 
;Write the command to the MDIO bus
 
mov eax, [phy_addr]
shl eax, 8
add eax, [reg]
add eax, MDIO_WRITE
set_io MMDIO
out dx, ax
 
;Wait for the write bit to be cleared.
mov ecx, 2048 ;limit
.write:
in ax, dx
test ax, MDIO_WRITE
jz @f
dec ecx
jnz .write
@@:
 
DEBUGF 2,"PHY write ok\n"
 
ret
endp
 
 
 
align 4
read_mac:
 
DEBUGF 2,"Reading MAC: "
 
mov cx, 3
lea edi, [device.mac]
set_io 0
set_io MID_0L
.mac:
in ax, dx
stosw
inc dx
inc dx
dec cx
jnz .mac
 
DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[edi-6]:2, [edi-5]:2, [edi-4]:2, [edi-3]:2, [edi-2]:2, [edi-1]:2
 
ret
 
 
 
 
; End of code
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
align 4 ; Place all initialised data here
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'R6040',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
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/ethernet/RTL8029.asm
0,0 → 1,1203
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; RTL8029/ne2000 driver for KolibriOS ;;
;; ;;
;; based on RTL8029.asm driver for menuetos ;;
;; and realtek8029.asm for SolarOS by Eugen Brasoveanu ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; with help from CleverMouse ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
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'
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.io_addr dd ?
.irq_line db ?
.pci_bus dd ?
.pci_dev dd ?
 
.flags db ?
.vendor db ?
 
.memsize db ?
.rx_start db ?
.tx_start db ?
.bmem dd ?
.rmem dd ?
 
.size = $ - device
 
end virtual
 
 
public START
public service_proc
public version
 
P0_COMMAND = 0x00
P0_PSTART = 0x01
P0_PSTOP = 0x02
P0_BOUND = 0x03
P0_TSR = 0x04
P0_TPSR = 0x04
P0_TBCR0 = 0x05
P0_TBCR1 = 0x06
P0_ISR = 0x07
P0_RSAR0 = 0x08
P0_RSAR1 = 0x09
P0_RBCR0 = 0x0A
P0_RBCR1 = 0x0B
P0_RSR = 0x0C
P0_RCR = 0x0C
P0_TCR = 0x0D
P0_DCR = 0x0E
P0_IMR = 0x0F
 
P1_COMMAND = 0x00
P1_PAR0 = 0x01
P1_PAR1 = 0x02
P1_PAR2 = 0x03
P1_PAR3 = 0x04
P1_PAR4 = 0x05
P1_PAR5 = 0x06
P1_CURR = 0x07
P1_MAR0 = 0x08
 
CMD_PS0 = 0x00 ; Page 0 select
CMD_PS1 = 0x40 ; Page 1 select
CMD_PS2 = 0x80 ; Page 2 select
CMD_RD2 = 0x20 ; Remote DMA control
CMD_RD1 = 0x10
CMD_RD0 = 0x08
CMD_TXP = 0x04 ; transmit packet
CMD_STA = 0x02 ; start
CMD_STP = 0x01 ; stop
 
CMD_RDMA_READ = 001b shl 3
CMD_RDMA_WRITE = 010b shl 3
CMD_RDMA_SEND_PACKET = 011b shl 3
CMD_RDMA_ABORT = 100b shl 3 ; really is 1xx, Abort/Complete Remote DMA
; RDMA_MASK = 111b shl 3 ; internal, mask
 
RCR_MON = 0x20 ; monitor mode
 
DCR_FT1 = 0x40
DCR_LS = 0x08 ; Loopback select
DCR_WTS = 0x01 ; Word transfer select
 
ISR_PRX = 0x01 ; successful recv
ISR_PTX = 0x02 ; successful xmit
ISR_RXE = 0x04 ; receive error
ISR_TXE = 0x08 ; transmit error
ISR_OVW = 0x10 ; Overflow
ISR_CNT = 0x20 ; Counter overflow
ISR_RDC = 0x40 ; Remote DMA complete
ISR_RST = 0x80 ; reset
 
IRQ_MASK = ISR_PRX ;+ ISR_PTX ;+ ISR_RDC + ISR_PTX + ISR_TXE
 
RSTAT_PRX = 1 shl 0 ; successful recv
RSTAT_CRC = 1 shl 1 ; CRC error
RSTAT_FAE = 1 shl 2 ; Frame alignment error
RSTAT_OVER = 1 shl 3 ; FIFO overrun
 
TXBUF_SIZE = 6
RXBUF_END = 32
PAGE_SIZE = 256
 
ETH_ZLEN = 60
ETH_FRAME_LEN = 1514
 
FLAG_PIO = 1 shl 0
FLAG_16BIT = 1 shl 1
 
VENDOR_NONE = 0
VENDOR_WD = 1
VENDOR_NOVELL = 2
VENDOR_3COM = 3
 
NE_ASIC = 0x10
NE_RESET = 0x0F ; Used to reset card
NE_DATA = 0x00 ; Used to read/write NIC mem
 
MEM_8k = 32
MEM_16k = 64
MEM_32k = 128
 
ISA_MAX_ADDR = 0x400
 
 
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; proc START
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
.entry:
DEBUGF 2,"Registering %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
.fail:
.exit:
xor eax, eax
ret
 
endp
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; proc SERVICE_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 @F ;---------
 
DEBUGF 2,"Checking if device is already listed..\n"
 
mov eax, [IOCTL.input]
 
cmp [IOCTL.inp_size], 3
jb .fail
cmp byte [eax], 1
je .pci
 
cmp [IOCTL.inp_size], 4
jb .fail
cmp byte [eax], 0
je .isa
 
jmp .fail
 
.pci:
 
; check if the device is already listed
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice_pci
 
mov ax, [eax+1] ; get the pci bus and device numbers
.nextdevice:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
 
.firstdevice_pci:
call create_new_struct
 
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 io addres of the PCI device
 
PCI_find_io
 
; We've found the io address, find IRQ now
 
PCI_find_irq
 
jmp .hook
 
.isa:
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice_isa
mov al, [eax+3]
movzx edi, word [eax+1]
.nextdevice_isa:
mov ebx, [esi]
cmp edi, [device.io_addr]
jne .maybenext
cmp al, [device.irq_line]
je find_device_num
.maybenext:
add esi, 4
loop .nextdevice_isa
 
 
 
.firstdevice_isa:
call create_new_struct
 
mov eax, [IOCTL.input]
movzx ecx, word [eax+1]
mov [device.io_addr], ecx
mov cl, [eax+3]
mov [device.irq_line], cl
 
.hook:
 
DEBUGF 2,"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.io_addr]:4
 
call probe ; this function will output in eax
test eax, eax
jnz .err ; If an error occured, exit
 
mov eax, [devices]
mov [device_list+4*eax], ebx
inc [devices]
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
cmp eax, -1
jz .err
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
 
.err:
DEBUGF 1,"Failed, removing device structure\n"
stdcall KernelFree, ebx
 
jmp .fail
 
;------------------------------------------------------
@@:
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
create_new_struct:
 
cmp [devices], MAX_DEVICES
jae .fail
 
allocate_and_clear ebx, device.size, .fail ; Allocate the buffer for device structure
 
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], unload
mov [device.name], my_service
 
ret
 
.fail:
add esp, 4 ; return to caller of 'hook'
or eax, -1
ret
 
find_device_num:
 
DEBUGF 1,"Trying to find device number of already registered device\n"
mov ebx, eax
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
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
unload: ; TODO
or eax, -1
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; probe: enables the device and clears the rx buffer
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
probe:
mov [device.vendor], VENDOR_NONE
mov [device.bmem], 0
 
DEBUGF 2,"Trying 16-bit mode\n"
 
mov [device.flags], FLAG_16BIT + FLAG_PIO
mov [device.memsize], MEM_32k
mov [device.tx_start], 64
mov [device.rx_start], TXBUF_SIZE + 64
 
set_io 0
set_io P0_DCR
mov al, DCR_WTS + DCR_FT1 + DCR_LS ; word transfer select +
out dx, al
 
set_io P0_PSTART
mov al, MEM_16k
out dx, al
 
set_io P0_PSTOP
mov al, MEM_32k
out dx, al
 
mov esi, my_service
mov di, 16384
mov cx, 14
call PIO_write
 
mov si, 16384
mov cx, 14
sub esp, 16
mov edi, esp
call PIO_read
 
mov esi, esp
add esp, 16
mov edi, my_service
mov ecx, 13
repe cmpsb
je ep_set_vendor
 
DEBUGF 2,"16-bit mode failed\n"
DEBUGF 2,"Trying 8-bit mode\n"
 
mov [device.flags], FLAG_PIO
mov [device.memsize], MEM_16k
mov [device.tx_start], 32
mov [device.rx_start], TXBUF_SIZE + 32
 
set_io NE_ASIC + NE_RESET
in al, dx
out dx, al
 
in al, 0x84
 
set_io P0_COMMAND
mov al, CMD_RD2 + CMD_STP
out dx, al
 
set_io P0_RCR
mov al, RCR_MON
out dx, al
 
set_io P0_DCR
mov al, DCR_FT1 + DCR_LS
out dx, al
 
set_io P0_PSTART
mov al, MEM_8k
out dx, al
 
set_io P0_PSTOP
mov al, MEM_16k
out dx, al
 
mov esi, my_service
mov di, 8192
mov cx, 14
call PIO_write
 
mov si, 8192
mov cx, 14
sub esp, 16
mov edi, esp
call PIO_read
 
mov esi, my_service
mov edi, esp
add esp, 16
mov ecx, 13
repe cmpsb
je ep_set_vendor
 
DEBUGF 2,"This is not a valid ne2000 device!\n"
or eax, -1
ret
 
 
ep_set_vendor:
 
DEBUGF 2,"Mode ok\n"
 
cmp [device.io_addr], ISA_MAX_ADDR
jbe .isa
 
DEBUGF 2,"Card is using PCI bus\n"
 
mov [device.vendor], VENDOR_NOVELL ;;; FIXME
jmp ep_check_have_vendor
 
.isa:
DEBUGF 2,"Card is using ISA bus\n"
 
mov [device.vendor], VENDOR_NOVELL
 
ep_check_have_vendor:
 
 
mov al, [device.vendor]
cmp al, VENDOR_NONE
; je exit
 
cmp al, VENDOR_3COM
je reset
 
mov eax, [device.bmem]
mov [device.rmem], eax
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; reset: Place the chip into a virgin state
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
reset:
DEBUGF 2,"Resetting device\n"
 
; attach int handler
movzx eax, [device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
 
; Stop card + DMA
set_io 0
; set_io P0_COMMAND
mov al, CMD_PS0 + CMD_RDMA_ABORT + CMD_STP
out dx, al
 
; initialize DCR
set_io P0_DCR
mov al, DCR_FT1 + DCR_LS
test [device.flags], FLAG_16BIT
jz @f
or al, DCR_WTS ; word transfer select
@@:
out dx, al
 
; clear remote bytes count
set_io P0_RBCR0
xor al, al
out dx, al
 
set_io P0_RBCR1
out dx, al
 
; initialize Receive configuration register (until all init is done)
set_io P0_RCR
mov al, 0x20 ; monitor mode
out dx, al
 
; transmit configuration register to monitor mode (until all ini is done)
set_io P0_TCR
mov al, 2 ; internal loopback
out dx, al
 
; clear interupt status
set_io P0_ISR
mov al, 0xff
out dx, al
 
; clear IRQ mask ;;;;; CHECKME ;;;;;
set_io P0_IMR
xor al, al
out dx, al
 
; set transmit pointer
set_io P0_TPSR
mov al, [device.tx_start]
out dx, al
 
; set pagestart pointer
set_io P0_PSTART
mov al, [device.rx_start]
out dx, al
 
; set pagestop pointer
set_io P0_PSTOP
mov al, [device.memsize]
out dx, al
 
; set boundary pointer
set_io P0_BOUND
mov al, [device.memsize]
dec al
out dx, al
 
; set curr pointer
set_io P0_COMMAND
mov al, CMD_PS1 ;+ CMD_RD2 + CMD_STP ; page 1, stop mode
out dx, al
 
set_io P1_CURR
mov al, [device.rx_start]
out dx, al
 
set_io P0_COMMAND
mov al, CMD_PS0 ;+ CMD_RD2 + CMD_STA ; go to page 0, start mode
out dx, al
 
; Read MAC address and set it to registers
call read_mac
push .macret
sub esp, 6
lea esi, [device.mac]
mov edi, esp
movsd
movsw
jmp write_mac
.macret:
 
; set IRQ mask
set_io 0
set_io P0_IMR
mov al, IRQ_MASK
out dx, al
 
; start mode
set_io P0_COMMAND
mov al, CMD_STA
out dx, al
 
; clear transmit control register
set_io P0_TCR
xor al, al ; no loopback
out dx, al
 
; set receive control register ;;;;
set_io P0_RCR
mov al, 4 ; accept broadcast
out dx, al
 
; clear packet/byte counters
xor eax, eax
lea edi, [device.bytes_tx]
mov ecx, 6
rep stosd
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], ETH_FRAME_LEN
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
; Indicate that we have successfully reset the card
xor eax, eax
DEBUGF 2,"Done!\n"
 
ret
 
 
 
;***************************************************************************
; Function
; transmit
; buffer in [esp+4], size in [esp+8], pointer to device struct in ebx
;***************************************************************************
 
align 4
transmit:
 
mov esi, [esp + 4]
mov ecx, [esp + 8]
DEBUGF 2,"Transmitting packet, buffer:%x, size:%u\n",esi, ecx
DEBUGF 2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[esi+0]:2,[esi+1]:2,[esi+2]:2,[esi+3]:2,[esi+4]:2,[esi+5]:2,[esi+6]:2,[esi+7]:2,[esi+8]:2,[esi+9]:2,[esi+10]:2,[esi+11]:2,[esi+13]:2,[esi+12]:2
 
cmp ecx, ETH_FRAME_LEN
ja .err ; packet is too long
cmp ecx, ETH_ZLEN
jb .err ; packet is too short
 
movzx edi, [device.tx_start]
shl edi, 8
push cx
call PIO_write
pop cx
 
set_io 0
; set_io P0_COMMAND
mov al, CMD_PS0 + CMD_RD2 + CMD_STA
out dx, al
 
set_io P0_TPSR
mov al, [device.tx_start]
out dx, al
 
set_io P0_TBCR0
mov al, cl
out dx, al
 
set_io P0_TBCR1
mov al, ch
out dx, al
 
set_io P0_COMMAND
mov al, CMD_PS0 + CMD_TXP + CMD_RD2 + CMD_STA
out dx, al
 
DEBUGF 2," - Packet Sent!\n"
 
inc [device.packets_tx]
mov eax, [esp + 8] ; Get packet size in eax
 
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
stdcall KernelFree, [esp+4]
xor eax, eax
ret 8
 
.err:
DEBUGF 2," - Error!\n"
 
or eax, -1
stdcall KernelFree, [esp+4]
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 INT occur
 
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
set_io 0
; set_io P0_COMMAND
mov al, CMD_PS0
out dx, al
 
set_io P0_ISR
in al, dx
test al, al
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\n", ebx, eax:2
 
push ebx
 
test al, ISR_PRX ; packet received ok ?
jz .no_rx
 
test [device.flags], FLAG_PIO
jz .no_rx ; FIXME: Only PIO mode supported for now
 
;
 
pushd .no_rx
 
; allocate a buffer
 
stdcall KernelAlloc, ETH_FRAME_LEN
test eax, eax
jz .fail_2
pushd 0
push eax
 
; read offset for current packet from device
 
set_io 0
set_io P0_BOUND ; boundary ptr is offset to next packet we need to read.
in al, dx
inc al
 
cmp al, [device.memsize]
jb @f
mov al, [device.rx_start]
@@:
mov ch, al
 
set_io P0_COMMAND
mov al, CMD_PS1
out dx, al
 
set_io P1_CURR
in al, dx ; get current page in cl
mov cl, al
 
set_io P1_COMMAND
mov al, CMD_PS0
out dx, al
 
cmp cl, [device.memsize]
jb @f
mov cl, [device.rx_start]
@@:
 
cmp cl, ch
je .fail
 
movzx esi, ch ; we are using 256 byte pages
shl esi, 8 ; esi now holds the offset for current packet
 
; Get packet header in eax
 
sub esp, 4 ; reserve 4 bytes on stack to put packet header in
mov edi, esp
mov cx, 4
call PIO_read
 
mov ecx, [esp] ; ecx now contains packet header
 
; check if packet is ok
 
test ecx, RSTAT_PRX
jz .fail_3
 
; calculate packet length in ecx
 
shr ecx, 16
sub ecx, 4 ; CRC doesnt count as data byte
mov [esp + 4 + 4], ecx
 
; check if packet size is ok
 
cmp ecx, ETH_ZLEN
jb .fail_3
cmp ecx, ETH_FRAME_LEN
ja .fail_3
 
; update stats
 
DEBUGF 2,"Received %u bytes\n", ecx
 
add dword[device.bytes_rx], ecx
adc dword[device.bytes_rx + 4], 0
inc [device.packets_rx]
 
; update read and write pointers
 
add esi, 4
mov edi, [esp + 4]
 
; now check if we can read all data at once (if we cross the end boundary, we need to wrap back to the beginning)
 
xor eax, eax
mov ah, [device.memsize]
sub eax, esi
cmp ecx, eax ; eax = number of bytes till end of buffer, ecx = bytes we need to read
jbe .no_wrap
 
DEBUGF 2,"WRAP!\n"
 
; Read first part
 
sub ecx, eax
push ecx
mov ecx, eax
 
call PIO_read ; Read the data
 
; update pointers
 
add edi, ecx
pop ecx
 
movzx esi, [device.rx_start]
shl esi, 8
 
; now read second part (or only part)
 
.no_wrap:
call PIO_read ; Read the data
 
; update boundary pointer
 
pop eax
mov al, ah
cmp al, [device.rx_start]
jne @f
mov al, [device.memsize]
@@:
 
set_io 0
set_io P0_BOUND
dec al
out dx, al
 
; now send the data to the kernel
 
jmp Eth_input
 
.fail_3:
add esp, 4
.fail:
add esp, 8
.fail_2:
 
 
.no_rx:
pop ebx
DEBUGF 2,"done\n"
 
set_io 0
set_io P0_ISR
mov al, 0xff
out dx, al
 
pop edi esi ebx
 
ret
 
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Write MAC address ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
write_mac: ; in: mac on stack (6 bytes)
 
DEBUGF 1,"Writing MAC\n"
 
set_io 0
mov al, CMD_PS1; + CMD_RD2 + CMD_STP
out dx, al
 
set_io P1_PAR0
mov esi, esp
mov cx, 6
@@:
lodsb
out dx, al
inc dx
loopw @r
 
add esp, 6
 
; Notice this procedure does not ret, but continues to read_mac instead.
 
;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Read MAC address ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;
 
read_mac:
 
DEBUGF 1,"Reading MAC\n"
 
xor esi, esi
mov cx, 16
sub esp, 16
mov edi, esp
call PIO_read
 
mov esi, esp
add esp, 16
lea edi, [device.mac]
mov ecx, 6
.loop:
movsb
test [device.flags], FLAG_16BIT
jz .8bit
inc esi
.8bit:
loop .loop
 
DEBUGF 1,"MAC=%x-%x-%x-%x-%x-%x\n",\
[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
ret
 
 
;***************************************************************************
;
; PIO_read
;
; Description
; Read a frame from the ethernet card via Programmed I/O
; src in si
; cnt in cx
; dst in edi
;***************************************************************************
PIO_read:
 
DEBUGF 1,"PIO Read from %x to %x, %u bytes ", si, edi, cx
 
; start DMA
set_io 0
; set_io P0_COMMAND
mov al, CMD_RD2 + CMD_STA
out dx, al
 
; set length of data we're interested in
set_io P0_RBCR0
mov al, cl
out dx, al
 
set_io P0_RBCR1
mov al, ch
out dx, al
 
; set offset of what we want to read
set_io P0_RSAR0
mov ax, si
out dx, al
 
set_io P0_RSAR1
shr ax, 8
out dx, al
 
; start DMA read
set_io P0_COMMAND
mov al, CMD_RD0 + CMD_STA
out dx, al
 
set_io NE_ASIC
 
test [device.flags], FLAG_16BIT
jz .8bits
 
DEBUGF 1,"(16-bit mode)\n"
 
shr cx, 1 ; note that if the number was odd, carry flag will be set
pushf
 
.16bits:
in ax, dx
stosw
loopw .16bits
 
inc cx
popf
jnc .done
jmp .8bits_
 
.8bits:
DEBUGF 1,"(8-bit mode)\n"
 
.8bits_:
in al, dx
stosb
loopw .8bits_
 
 
.done:
; set_io 0
; set_io P0_ISR
;
; .dmawait: ; Wait for Remote DMA Complete
; in al, dx
; test al, ISR_RDC
; jz .dmawait
; and al, not ISR_RDC
; out dx, al ; clear the bit
 
ret
 
 
 
 
;***************************************************************************
;
; PIO_write
;
; Description
; writes a frame to the ethernet card via Programmed I/O
; dst in di
; cnt in cx
; src in esi
;***************************************************************************
PIO_write:
 
DEBUGF 1,"Eth PIO Write from %x to %x, %u bytes ", esi, di, cx
 
set_io 0
; set_io P0_COMMAND
mov al, CMD_RD2 + CMD_STA
out dx, al
 
set_io P0_ISR
mov al, ISR_RDC
out dx, al
 
set_io P0_RBCR0
mov al, cl
out dx, al
 
set_io P0_RBCR1
mov al, ch
out dx, al
 
mov ax, di
set_io P0_RSAR0
out dx, al
shr ax, 8
set_io P0_RSAR1
out dx, al
 
set_io P0_COMMAND
mov al, CMD_RD1 + CMD_STA
out dx, al
 
set_io NE_ASIC
test [device.flags], FLAG_16BIT
jz .8_bit
 
DEBUGF 1,"(16-bit mode)\n"
 
shr cx, 1 ; note that if the number was odd, carry flag will be set
pushf ; save the flags for later
 
.16bit:
lodsw
out dx, ax
loopw .16bit
 
popf
jnc .done
inc cx
jmp .8_bit_
 
.8_bit:
 
DEBUGF 1,"(8-bit mode)\n"
 
.8_bit_:
lodsb
out dx, al
loopw .8_bit_
 
.done:
; set_io 0
; set_io P0_ISR
; .dmawait: ; Wait for Remote DMA Complete
; in al, dx
; test al, ISR_RDC
; jz .dmawait
; and al, not ISR_RDC
; out dx, al ; clear the bit
 
ret
 
 
 
;all initialized data place here
align 4
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'RTL8029/ne2000',0 ;max 16 chars include zero
 
;device_1 db 'Realtek 8029',0
;device_2 db 'Realtek 8019',0
;device_3 db 'Realtek 8019AS',0
;device_4 db 'ne2000',0
;device_5 db 'DP8390',0
 
include_debug_strings
 
section '.data' data readable writable align 16 ;place all uninitialized data place here
 
device_list rd MAX_DEVICES
 
 
 
 
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/ethernet/RTL8139.asm
0,0 → 1,1131
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Realtek 8139 driver for KolibriOS ;;
;; ;;
;; based on RTL8139.asm driver for menuetos ;;
;; and realtek8139.asm for SolarOS by Eugen Brasoveanu ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
RBLEN = 3 ; Receive buffer size: 0==8K 1==16k 2==32k 3==64k
NUM_TX_DESC = 4
 
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
 
REG_IDR0 = 0x00
REG_MAR0 = 0x08 ; multicast filter register 0
REG_MAR4 = 0x0c ; multicast filter register 4
REG_TSD0 = 0x10 ; transmit status of descriptor
REG_TSAD0 = 0x20 ; transmit start address of descriptor
REG_RBSTART = 0x30 ; RxBuffer start address
REG_COMMAND = 0x37 ; command register
REG_CAPR = 0x38 ; current address of packet read (word) R/W
REG_IMR = 0x3c ; interrupt mask register
REG_ISR = 0x3e ; interrupt status register
REG_TXCONFIG = 0x40 ; transmit configuration register
REG_RXCONFIG = 0x44 ; receive configuration register 0
REG_MPC = 0x4c ; missed packet counter
REG_9346CR = 0x50 ; serial eeprom 93C46 command register
REG_CONFIG1 = 0x52 ; configuration register 1
REG_MSR = 0x58
REG_CONFIG4 = 0x5a ; configuration register 4
REG_HLTCLK = 0x5b ; undocumented halt clock register
REG_BMCR = 0x62 ; basic mode control register
REG_ANAR = 0x66 ; auto negotiation advertisement register
REG_9346CR_WE = 11b shl 6
 
BIT_RUNT = 4 ; total packet length < 64 bytes
BIT_LONG = 3 ; total packet length > 4k
BIT_CRC = 2 ; crc error occured
BIT_FAE = 1 ; frame alignment error occured
BIT_ROK = 0 ; received packet is ok
 
BIT_RST = 4 ; reset bit
BIT_RE = 3 ; receiver enabled
BIT_TE = 2 ; transmitter enabled
BUFE = 1 ; rx buffer is empty, no packet stored
 
BIT_ISR_TOK = 2 ; transmit ok
BIT_ISR_RER = 1 ; receive error interrupt
BIT_ISR_ROK = 0 ; receive ok
 
BIT_TX_MXDMA = 8 ; Max DMA burst size per Tx DMA burst
BIT_TXRR = 4 ; Tx Retry count 16+(TXRR*16)
 
BIT_RXFTH = 13 ; Rx fifo threshold
BIT_RBLEN = 11 ; Ring buffer length indicator
BIT_RX_MXDMA = 8 ; Max DMA burst size per Rx DMA burst
BIT_NOWRAP = 7 ; transfered data wrapping
BIT_9356SEL = 6 ; eeprom selector 9346/9356
BIT_AER = 5 ; accept error packets
BIT_AR = 4 ; accept runt packets
BIT_AB = 3 ; accept broadcast packets
BIT_AM = 2 ; accept multicast packets
BIT_APM = 1 ; accept physical match packets
BIT_AAP = 0 ; accept all packets
 
BIT_93C46_EEM1 = 7 ; RTL8139 eeprom operating mode1
BIT_93C46_EEM0 = 6 ; RTL8139 eeprom operating mode0
BIT_93C46_EECS = 3 ; chip select
BIT_93C46_EESK = 2 ; serial data clock
BIT_93C46_EEDI = 1 ; serial data input
BIT_93C46_EEDO = 0 ; serial data output
 
BIT_LWACT = 4 ; see REG_CONFIG1
BIT_SLEEP = 1 ; sleep bit at older chips
BIT_PWRDWN = 0 ; power down bit at older chips
BIT_PMEn = 0 ; power management enabled
 
BIT_LWPTN = 2 ; see REG_CONFIG4
 
BIT_ERTXTH = 16 ; early TX threshold
BIT_TOK = 15 ; transmit ok
BIT_OWN = 13 ; tx DMA operation is completed
 
BIT_ANE = 12 ; auto negotiation enable
 
BIT_TXFD = 8 ; 100base-T full duplex
BIT_TX = 7 ; 100base-T
BIT_10FD = 6 ; 10base-T full duplex
BIT_10 = 5 ; 10base-T
BIT_SELECTOR = 0 ; binary encoded selector CSMA/CD=00001
 
BIT_IFG1 = 25
BIT_IFG0 = 24
 
TXRR = 8 ; total retries = 16+(TXRR*16)
TX_MXDMA = 6 ; 0=16 1=32 2=64 3=128 4=256 5=512 6=1024 7=2048
ERTXTH = 8 ; in unit of 32 bytes e.g:(8*32)=256
RX_MXDMA = 7 ; 0=16 1=32 2=64 3=128 4=256 5=512 6=1024 7=unlimited
RXFTH = 7 ; 0=16 1=32 2=64 3=128 4=256 5=512 6=1024 7=no threshold
 
RX_CONFIG = (RBLEN shl BIT_RBLEN) or \
(RX_MXDMA shl BIT_RX_MXDMA) or \
(1 shl BIT_NOWRAP) or \
(RXFTH shl BIT_RXFTH) or\
(1 shl BIT_AB) or \ ; Accept broadcast packets
(1 shl BIT_APM) or \ ; Accept physical match packets
(1 shl BIT_AER) or \ ; Accept error packets
(1 shl BIT_AR) or \ ; Accept Runt packets (smaller then 64 bytes)
(1 shl BIT_AM) ; Accept multicast packets
 
RX_BUFFER_SIZE = (8192 shl RBLEN);+16
MAX_ETH_FRAME_SIZE = 1514
 
EE_93C46_REG_ETH_ID = 7 ; MAC offset
EE_93C46_READ_CMD = (6 shl 6) ; 110b + 6bit address
EE_93C56_READ_CMD = (6 shl 8) ; 110b + 8bit address
EE_93C46_CMD_LENGTH = 9 ; start bit + cmd + 6bit address
EE_93C56_CMD_LENGTH = 11 ; start bit + cmd + 8bit ddress
 
VER_RTL8139 = 1100000b
VER_RTL8139A = 1110000b
VER_RTL8139AG = 1110100b
VER_RTL8139B = 1111000b
VER_RTL8130 = VER_RTL8139B
VER_RTL8139C = 1110100b
VER_RTL8100 = 1111010b
VER_RTL8100B = 1110101b
VER_RTL8139D = VER_RTL8100B
VER_RTL8139CP = 1110110b
VER_RTL8101 = 1110111b
 
IDX_RTL8139 = 0
IDX_RTL8139A = 1
IDX_RTL8139B = 2
IDX_RTL8139C = 3
IDX_RTL8100 = 4
IDX_RTL8139D = 5
IDX_RTL8139D = 6
IDX_RTL8101 = 7
 
ISR_SERR = 1 shl 15
ISR_TIMEOUT = 1 shl 14
ISR_LENCHG = 1 shl 13
ISR_FIFOOVW = 1 shl 6
ISR_PUN = 1 shl 5
ISR_RXOVW = 1 shl 4
ISR_TER = 1 shl 3
ISR_TOK = 1 shl 2
ISR_RER = 1 shl 1
ISR_ROK = 1 shl 0
 
INTERRUPT_MASK = ISR_ROK or \
ISR_RXOVW or \
ISR_PUN or \
ISR_FIFOOVW or \
ISR_LENCHG or \
ISR_TOK or \
ISR_TER
 
TSR_OWN = 1 shl 13
TSR_TUN = 1 shl 14
TSR_TOK = 1 shl 15
 
TSR_CDH = 1 shl 28
TSR_OWC = 1 shl 29
TSR_TABT = 1 shl 30
TSR_CRS = 1 shl 31
 
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.rx_buffer dd ?
 
.rx_data_offset dd ?
.io_addr dd ?
 
.curr_tx_desc db ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
.hw_ver_id db ?
 
.TX_DESC rd NUM_TX_DESC
 
.size = $ - 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 ax, [eax+1] ; get the pci bus and device numbers
.nextdevice:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
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, device.size, .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 io addres of the PCI device
 
PCI_find_io
 
; We've found the io address, find IRQ now
 
PCI_find_irq
 
DEBUGF 2, "Hooking into device, dev:%x, bus:%x, irq:%x, I/O addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
 
; Allocate the receive buffer
 
stdcall CreateRingBuffer, dword (RX_BUFFER_SIZE), dword PG_SW
test eax, eax
jz .err
mov [device.rx_buffer], eax
 
; 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 2, "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 2, "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, [device.rx_buffer]
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 (RTL8139_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 RTL8139)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
probe:
DEBUGF 2, "Probing %s device\n", my_service
 
PCI_make_bus_master
 
; get chip version
set_io 0
set_io REG_TXCONFIG + 2
in ax, dx
shr ah, 2
shr ax, 6
and al, 01111111b
 
; now find it in our array
mov ecx, HW_VER_ARRAY_SIZE-1
.chip_ver_loop:
cmp al, [hw_ver_array + ecx]
je .chip_ver_found
dec ecx
jns .chip_ver_loop
.unknown:
mov ecx, 8
.chip_ver_found:
cmp ecx, 8
ja .unknown
 
mov [device.hw_ver_id], cl
 
mov ecx, [crosslist+ecx*4]
mov [device.name], ecx
 
DEBUGF 2, "Chip version: %s\n", ecx
 
; wake up the chip
set_io 0
set_io REG_HLTCLK
mov al, 'R' ; run the clock
out dx, al
 
; unlock config and BMCR registers
set_io REG_9346CR
mov al, (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0)
out dx, al
 
; enable power management
set_io REG_CONFIG1
in al, dx
cmp [device.hw_ver_id], IDX_RTL8139B
jae .new_chip
; wake up older chips
and al, not ((1 shl BIT_SLEEP) or (1 shl BIT_PWRDWN))
out dx, al
jmp .finish_wake_up
 
; set LWAKE pin to active high (default value).
; it is for Wake-On-LAN functionality of some motherboards.
; this signal is used to inform the motherboard to execute a wake-up process.
; only at newer chips.
.new_chip:
or al, (1 shl BIT_PMEn)
and al, not (1 shl BIT_LWACT)
out dx, al
 
set_io REG_CONFIG4
in al, dx
and al, not (1 shl BIT_LWPTN)
out dx, al
 
; lock config and BMCR registers
.finish_wake_up:
xor al, al
set_io 0
set_io REG_9346CR
out dx, al
DEBUGF 2, "done!\n"
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; reset: Set up all registers and descriptors, clear some values
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
reset:
DEBUGF 2, "Reset\n"
 
; attach int handler
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 chip
DEBUGF 1, "Resetting chip\n"
set_io 0
set_io REG_COMMAND
mov al, 1 shl BIT_RST
out dx, al
mov cx, 1000 ; wait no longer for the reset
.wait_for_reset:
in al, dx
test al, 1 shl BIT_RST
jz .reset_completed ; RST remains 1 during reset
dec cx
jns .wait_for_reset
DEBUGF 1, "Reset timeout!\n"
.reset_completed:
 
; unlock config and BMCR registers
set_io REG_9346CR
mov al, (1 shl BIT_93C46_EEM1) or (1 shl BIT_93C46_EEM0)
out dx, al
 
; initialize multicast registers (no filtering)
mov eax, 0xffffffff
set_io REG_MAR0
out dx, eax
set_io REG_MAR4
out dx, eax
 
; enable Rx/Tx
 
mov al, (1 shl BIT_RE) or (1 shl BIT_TE)
set_io REG_COMMAND
out dx, al
 
; Rxbuffer size, unlimited dma burst, no wrapping, no rx threshold
; accept broadcast packets, accept physical match packets
mov ax, RX_CONFIG
set_io REG_RXCONFIG
out dx, ax
 
; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144
mov eax, (TX_MXDMA shl BIT_TX_MXDMA) or (TXRR shl BIT_TXRR) or BIT_IFG1 or BIT_IFG0
set_io REG_TXCONFIG
out dx, eax
 
; enable auto negotiation
set_io REG_BMCR
in ax, dx
or ax, (1 shl BIT_ANE)
out dx, ax
 
; set auto negotiation advertisement
set_io REG_ANAR
in ax, dx
or ax, (1 shl BIT_SELECTOR) or (1 shl BIT_10) or (1 shl BIT_10FD) or (1 shl BIT_TX) or (1 shl BIT_TXFD)
out dx, ax
 
; lock config and BMCR registers
xor eax, eax
set_io REG_9346CR
out dx, al
 
; init RX/TX pointers
mov [device.rx_data_offset], eax
mov [device.curr_tx_desc], al
; set_io REG_CAPR
; out dx, ax
 
; clear packet/byte counters
lea edi, [device.bytes_tx]
mov ecx, 6
rep stosd
 
; clear missing packet counter
set_io REG_MPC
out dx, eax
 
; set RxBuffer address, init RX buffer offset
mov eax, [device.rx_buffer]
mov dword[eax], 0 ; clear receive flags for first packet (really needed??)
DEBUGF 2, "RX buffer virtual addr=0x%x\n", eax
GetRealAddr
DEBUGF 2, "RX buffer real addr=0x%x\n", eax
set_io REG_RBSTART
out dx, eax
 
; Read MAC address
call read_mac
 
; enable interrupts
set_io 0
set_io REG_IMR
mov ax, INTERRUPT_MASK
out dx, ax
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
call cable
 
; Indicate that we have successfully reset the card
xor eax, eax
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
transmit:
DEBUGF 1, "\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
DEBUGF 1, "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], MAX_ETH_FRAME_SIZE
ja .fail
cmp dword [esp+8], 60
jb .fail
 
; check if we own the current discriptor
set_io 0
set_io REG_TSD0
movzx ecx, [device.curr_tx_desc]
shl ecx, 2
add edx, ecx
in eax, dx
test eax, (1 shl BIT_OWN)
jz .wait_to_send
 
.send_packet:
; get next descriptor
inc [device.curr_tx_desc]
and [device.curr_tx_desc], NUM_TX_DESC-1
 
; Update stats
inc [device.packets_tx]
mov eax, [esp+8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx+4], 0
 
; Set the buffer address
set_io REG_TSAD0
mov eax, [esp+4]
mov [device.TX_DESC+ecx], eax
GetRealAddr
out dx, eax
 
; And the size of the buffer
set_io REG_TSD0
mov eax, [esp+8]
or eax, (ERTXTH shl BIT_ERTXTH) ; Early threshold
out dx, eax
 
DEBUGF 1, "Packet Sent!\n"
xor eax, eax
ret 8
 
.wait_to_send:
DEBUGF 1, "Waiting for timeout\n"
 
push edx
mov esi, 30
stdcall Sleep
pop edx
 
in ax, dx
test ax, (1 shl BIT_OWN)
jnz .send_packet
 
pusha
call reset ; if chip hung, reset it
popa
 
jmp .send_packet
 
.fail:
DEBUGF 1, "failed!\n"
stdcall KernelFree, [esp+4]
or eax, -1
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]
 
set_io 0
set_io REG_ISR
in ax, dx ; Get interrupt status
out dx, ax ; send it back to ACK
test ax, ax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
pop edi esi ebx
xor eax, eax
 
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
 
.got_it:
 
DEBUGF 1, "Device: %x Status: %x\n", ebx, ax
 
;----------------------------------------------------
; Received packet ok?
 
test ax, ISR_ROK
jz @f
push ax
 
.receive:
set_io 0
set_io REG_COMMAND
in al, dx
test al, BUFE ; test if RX buffer is empty
jnz .finish
 
DEBUGF 1, "RX: "
 
mov eax, [device.rx_buffer]
add eax, [device.rx_data_offset]
test byte [eax], (1 shl BIT_ROK) ; check if packet is ok
jz .reset_rx
 
; packet is ok, copy it
movzx ecx, word [eax+2] ; packet length
sub cx, 4 ; don't copy CRC
 
; Update stats
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
inc [device.packets_rx]
 
DEBUGF 1, "Received %u bytes\n", ecx
 
push ebx eax ecx
stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
pop ecx
test eax, eax ; Test if we allocated succesfully
jz .abort
 
mov edi, eax ; Where we will copy too
 
mov esi, [esp] ; The buffer we will copy from
add esi, 4 ; Dont copy CRC
 
push dword .abort ; Kernel will return to this address after EthReceiver
push ecx edi ; Save buffer pointer and size, to pass to kernel
 
.copy:
shr ecx, 1
jnc .nb
movsb
.nb:
shr ecx, 1
jnc .nw
movsw
.nw:
jz .nd
rep movsd
.nd:
 
jmp Eth_input ; Send it to kernel
 
.abort:
pop eax ebx
; update eth_data_start_offset
movzx eax, word [eax+2] ; packet length
add eax, [device.rx_data_offset]
add eax, 4+3 ; packet header is 4 bytes long + dword alignment
and eax, not 3 ; dword alignment
 
cmp eax, RX_BUFFER_SIZE
jb .no_wrap
DEBUGF 2, "Wrapping"
sub eax, RX_BUFFER_SIZE
.no_wrap:
mov [device.rx_data_offset], eax
DEBUGF 1, "New RX ptr: %d\n", eax
 
set_io 0
set_io REG_CAPR ; update 'Current Address of Packet Read register'
sub eax, 0x10 ; value 0x10 is a constant for CAPR
out dx , ax
 
jmp .receive ; check for multiple packets
 
.reset_rx:
test byte [eax], (1 shl BIT_CRC)
jz .no_crc_error
DEBUGF 2, "\nCRC error!\n"
 
.no_crc_error:
test byte [eax], (1 shl BIT_FAE)
jz .no_fae_error
DEBUGF 1, "\nFrame alignment error!\n"
 
.no_fae_error:
DEBUGF 1, "Reset RX\n"
in al, dx ; read command register
push ax
and al, not (1 shl BIT_RE) ; Clear the RE bit
out dx, al
pop ax
out dx, al ; write original command back
 
add edx, REG_RXCONFIG - REG_COMMAND ; Restore RX configuration
mov ax, RX_CONFIG
out dx, ax
 
.finish:
pop ax
 
;----------------------------------------------------
; Transmit ok / Transmit error
@@:
test ax, ISR_TOK + ISR_TER
jz @f
 
push ax
mov ecx, (NUM_TX_DESC-1)*4
.txdescloop:
set_io 0
set_io REG_TSD0
add edx, ecx
in eax, dx
 
test eax, TSR_OWN ; DMA operation completed
jz .notthisone
 
cmp [device.TX_DESC+ecx], 0
je .notthisone
 
; .notxd:
; test eax, TSR_TUN
; jz .nobun
; DEBUGF 2, "TX: FIFO Buffer underrun!\n"
;
; .nobun:
; test eax, TSR_OWC
; jz .noowc
; DEBUGF 2, "TX: OWC!\n"
;
; .noowc:
; test eax, TSR_TABT
; jz .notabt
; DEBUGF 2, "TX: TABT!\n"
;
; .notabt:
; test eax, TSR_CRS
; jz .nocsl
; DEBUGF 2, "TX: Carrier Sense Lost!\n"
;
; .nocsl:
 
DEBUGF 1, "TX OK: free buffer %x\n", [device.TX_DESC+ecx]:8
push ecx ebx
stdcall KernelFree, [device.TX_DESC+ecx]
pop ebx ecx
mov [device.TX_DESC+ecx], 0
 
.notthisone:
sub ecx, 4
ja .txdescloop
pop ax
 
;----------------------------------------------------
; Rx buffer overflow ?
@@:
test ax, ISR_RXOVW
jz @f
 
push ax
DEBUGF 2, "RX-buffer overflow!\n"
 
set_io 0
set_io REG_ISR
mov ax, ISR_FIFOOVW or ISR_RXOVW
out dx, ax
pop ax
 
;----------------------------------------------------
; Packet underrun?
@@:
test ax, ISR_PUN
jz @f
 
DEBUGF 2, "Packet underrun!\n"
 
;----------------------------------------------------
; Receive FIFO overflow ?
@@:
test ax, ISR_FIFOOVW
jz @f
 
push ax
DEBUGF 2, "RX fifo overflow!\n"
 
set_io 0
set_io REG_ISR
mov ax, ISR_FIFOOVW or ISR_RXOVW
out dx, ax
pop ax
 
;----------------------------------------------------
; Something about Cable changed ?
@@:
test ax, ISR_LENCHG
jz .fail
 
call cable
 
.fail:
DEBUGF 2, "\n"
pop edi esi ebx
xor eax, eax
inc eax
 
ret
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Update Cable status ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
cable:
DEBUGF 1, "Updating Cable status\n"
 
set_io 0
set_io REG_MSR
in al, dx
 
test al, 1 shl 2 ; 0 = link ok 1 = link fail
jnz .notconnected
 
test al, 1 shl 3 ; 0 = 100 Mbps 1 = 10 Mbps
jnz .10mbps
 
.100mbps:
mov [device.state], ETH_LINK_100M
call NetLinkChanged
 
ret
 
.10mbps:
mov [device.state], ETH_LINK_10M
call NetLinkChanged
 
ret
 
.notconnected:
mov [device.state], ETH_LINK_DOWN
call NetLinkChanged
 
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Write MAC address ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
write_mac: ; in: mac pushed onto stack (as 3 words)
 
DEBUGF 2, "Writing MAC: "
 
; disable all in command registers
set_io 0
set_io REG_9346CR
xor eax, eax
out dx, al
 
set_io REG_IMR
xor eax, eax
out dx, ax
 
set_io REG_ISR
mov eax, -1
out dx, ax
 
; enable writing
set_io REG_9346CR
mov eax, REG_9346CR_WE
out dx, al
 
; write the mac ...
set_io REG_IDR0
pop eax
out dx, eax
 
set_io REG_IDR0+4
xor eax, eax
pop ax
out dx, eax
 
; disable writing
set_io REG_9346CR
xor eax, eax
out dx, al
 
DEBUGF 2, "ok!\n"
 
; Notice this procedure does not ret, but continues to read_mac instead.
 
 
;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Read MAC address ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;
 
read_mac:
DEBUGF 2, "Reading MAC: "
 
set_io 0
lea edi, [device.mac]
in eax, dx
stosd
add edx, 4
in ax, dx
stosw
 
DEBUGF 2, "%x-%x-%x-%x-%x-%x\n",[edi-6]:2,[edi-5]:2,[edi-4]:2,[edi-3]:2,[edi-2]:2,[edi-1]:2
 
ret
 
 
; End of code
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
align 4 ; Place all initialised data here
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'RTL8139',0 ; max 16 chars include zero
 
device_1 db 'Realtek 8139',0
device_2 db 'Realtek 8139A',0
device_3 db 'Realtek 8139B',0
device_4 db 'Realtek 8139C',0
device_5 db 'Realtek 8100',0
device_6 db 'Realtek 8139D',0
device_7 db 'Realtek 8139CP',0
device_8 db 'Realtek 8101',0
device_unknown db 'Unknown RTL8139 clone', 0
 
crosslist:
dd device_1
dd device_2
dd device_3
dd device_4
dd device_5
dd device_6
dd device_7
dd device_8
dd device_unknown
 
hw_ver_array: ; This array is used by the probe routine to find out wich version of the RTL8139 we are working with
db VER_RTL8139
db VER_RTL8139A
db VER_RTL8139B
db VER_RTL8139C
db VER_RTL8100
db VER_RTL8139D
db VER_RTL8139CP
db VER_RTL8101
db 0
 
HW_VER_ARRAY_SIZE = $-hw_ver_array
 
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
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/ethernet/RTL8169.asm
0,0 → 1,1324
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; RTL8169 driver for KolibriOS ;;
;; ;;
;; Copyright 2007 mike.dld, ;;
;; mike.dld@gmail.com ;;
;; ;;
;; port to net branch by hidnplayr ;;
;; ;;
;; References: ;;
;; r8169.c - linux driver (etherboot project) ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 2
 
NUM_TX_DESC = 4
NUM_RX_DESC = 4
 
include '../proc32.inc'
include '../imports.inc'
include '../fdo.inc'
include '../netdrv.inc'
 
public START
public service_proc
public version
 
 
REG_MAC0 = 0x0 ; Ethernet hardware address
REG_MAR0 = 0x8 ; Multicast filter
REG_TxDescStartAddr = 0x20
REG_TxHDescStartAddr = 0x28
REG_FLASH = 0x30
REG_ERSR = 0x36
REG_ChipCmd = 0x37
REG_TxPoll = 0x38
REG_IntrMask = 0x3C
REG_IntrStatus = 0x3E
REG_TxConfig = 0x40
REG_RxConfig = 0x44
REG_RxMissed = 0x4C
REG_Cfg9346 = 0x50
REG_Config0 = 0x51
REG_Config1 = 0x52
REG_Config2 = 0x53
REG_Config3 = 0x54
REG_Config4 = 0x55
REG_Config5 = 0x56
REG_MultiIntr = 0x5C
REG_PHYAR = 0x60
REG_TBICSR = 0x64
REG_TBI_ANAR = 0x68
REG_TBI_LPAR = 0x6A
REG_PHYstatus = 0x6C
REG_RxMaxSize = 0xDA
REG_CPlusCmd = 0xE0
REG_RxDescStartAddr = 0xE4
REG_ETThReg = 0xEC
REG_FuncEvent = 0xF0
REG_FuncEventMask = 0xF4
REG_FuncPresetState = 0xF8
REG_FuncForceEvent = 0xFC
 
; InterruptStatusBits
ISB_SYSErr = 0x8000
ISB_PCSTimeout = 0x4000
ISB_SWInt = 0x0100
ISB_TxDescUnavail = 0x80
ISB_RxFIFOOver = 0x40
ISB_LinkChg = 0x20
ISB_RxOverflow = 0x10
ISB_TxErr = 0x08
ISB_TxOK = 0x04
ISB_RxErr = 0x02
ISB_RxOK = 0x01
 
; RxStatusDesc
SD_RxRES = 0x00200000
SD_RxCRC = 0x00080000
SD_RxRUNT = 0x00100000
SD_RxRWT = 0x00400000
 
; ChipCmdBits
CMD_Reset = 0x10
CMD_RxEnb = 0x08
CMD_TxEnb = 0x04
CMD_RxBufEmpty = 0x01
 
; Cfg9346Bits
CFG_9346_Lock = 0x00
CFG_9346_Unlock = 0xC0
 
; rx_mode_bits
RXM_AcceptErr = 0x20
RXM_AcceptRunt = 0x10
RXM_AcceptBroadcast = 0x08
RXM_AcceptMulticast = 0x04
RXM_AcceptMyPhys = 0x02
RXM_AcceptAllPhys = 0x01
 
; RxConfigBits
RXC_FIFOShift = 13
RXC_DMAShift = 8
 
; TxConfigBits
TXC_InterFrameGapShift = 24
TXC_DMAShift = 8 ; DMA burst value (0-7) is shift this many bits
 
; PHYstatus
PHYS_TBI_Enable = 0x80
PHYS_TxFlowCtrl = 0x40
PHYS_RxFlowCtrl = 0x20
PHYS_1000bpsF = 0x10
PHYS_100bps = 0x08
PHYS_10bps = 0x04
PHYS_LinkStatus = 0x02
PHYS_FullDup = 0x01
 
; GIGABIT_PHY_registers
PHY_CTRL_REG = 0
PHY_STAT_REG = 1
PHY_AUTO_NEGO_REG = 4
PHY_1000_CTRL_REG = 9
 
; GIGABIT_PHY_REG_BIT
PHY_Restart_Auto_Nego = 0x0200
PHY_Enable_Auto_Nego = 0x1000
 
; PHY_STAT_REG = 1
PHY_Auto_Neco_Comp = 0x0020
 
; PHY_AUTO_NEGO_REG = 4
PHY_Cap_10_Half = 0x0020
PHY_Cap_10_Full = 0x0040
PHY_Cap_100_Half = 0x0080
PHY_Cap_100_Full = 0x0100
 
; PHY_1000_CTRL_REG = 9
PHY_Cap_1000_Full = 0x0200
PHY_Cap_1000_Half = 0x0100
 
PHY_Cap_PAUSE = 0x0400
PHY_Cap_ASYM_PAUSE = 0x0800
 
PHY_Cap_Null = 0x0
 
; _MediaType
MT_10_Half = 0x01
MT_10_Full = 0x02
MT_100_Half = 0x04
MT_100_Full = 0x08
MT_1000_Full = 0x10
 
; _TBICSRBit
TBI_LinkOK = 0x02000000
 
; _DescStatusBit
DSB_OWNbit = 0x80000000
DSB_EORbit = 0x40000000
DSB_FSbit = 0x20000000
DSB_LSbit = 0x10000000
 
RX_BUF_SIZE = 1536 ; Rx Buffer size
 
; max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4)
MAX_ETH_FRAME_SIZE = 1536
 
TX_FIFO_THRESH = 256 ; In bytes
 
RX_FIFO_THRESH = 7 ; 7 means NO threshold, Rx buffer level before first PCI xfer
RX_DMA_BURST = 7 ; Maximum PCI burst, '6' is 1024
TX_DMA_BURST = 7 ; Maximum PCI burst, '6' is 1024
ETTh = 0x3F ; 0x3F means NO threshold
 
EarlyTxThld = 0x3F ; 0x3F means NO early transmit
RxPacketMaxSize = 0x0800 ; Maximum size supported is 16K-1
InterFrameGap = 0x03 ; 3 means InterFrameGap = the shortest one
 
HZ = 1000
 
RTL_MIN_IO_SIZE = 0x80
TX_TIMEOUT = (6*HZ)
 
TIMER_EXPIRE_TIME = 100
 
ETH_HDR_LEN = 14
DEFAULT_MTU = 1500
DEFAULT_RX_BUF_LEN = 1536
 
 
;ifdef JUMBO_FRAME_SUPPORT
; MAX_JUMBO_FRAME_MTU = 10000
; MAX_RX_SKBDATA_SIZE = (MAX_JUMBO_FRAME_MTU + ETH_HDR_LEN )
;else
MAX_RX_SKBDATA_SIZE = 1600
;end if
 
MCFG_METHOD_01 = 0x01
MCFG_METHOD_02 = 0x02
MCFG_METHOD_03 = 0x03
MCFG_METHOD_04 = 0x04
MCFG_METHOD_05 = 0x05
MCFG_METHOD_11 = 0x0b
MCFG_METHOD_12 = 0x0c
MCFG_METHOD_13 = 0x0d
MCFG_METHOD_14 = 0x0e
MCFG_METHOD_15 = 0x0f
 
PCFG_METHOD_1 = 0x01 ; PHY Reg 0x03 bit0-3 == 0x0000
PCFG_METHOD_2 = 0x02 ; PHY Reg 0x03 bit0-3 == 0x0001
PCFG_METHOD_3 = 0x03 ; PHY Reg 0x03 bit0-3 == 0x0002
 
virtual at 0
tx_desc:
.status dd ?
.vlan_tag dd ?
.buf_addr dq ?
.size = $
rb (NUM_TX_DESC-1)*tx_desc.size
.buf_soft_addr dd ?
end virtual
 
virtual at 0
rx_desc:
.status dd ?
.vlan_tag dd ?
.buf_addr dq ?
.size = $
rb (NUM_RX_DESC-1)*rx_desc.size
.buf_soft_addr dd ?
end virtual
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.io_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
 
rb 256-(($ - device) and 255) ; align 256
.tx_ring rb NUM_TX_DESC * tx_desc.size * 2
 
rb 256-(($ - device) and 255) ; align 256
.rx_ring rb NUM_RX_DESC * rx_desc.size * 2
 
tpc:
.mmio_addr dd ? ; memory map physical address
.chipset dd ?
.pcfg dd ?
.mcfg dd ?
.cur_rx dd ? ; Index into the Rx descriptor buffer of next Rx pkt
.cur_tx dd ? ; Index into the Tx descriptor buffer of next Rx pkt
.TxDescArrays dd ? ; Index of Tx Descriptor buffer
.RxDescArrays dd ? ; Index of Rx Descriptor buffer
.TxDescArray dd ? ; Index of 256-alignment Tx Descriptor buffer
.RxDescArray dd ? ; Index of 256-alignment Rx Descriptor buffer
 
device_size = $ - device
 
end virtual
 
intr_mask = ISB_LinkChg or ISB_RxOverflow or ISB_RxFIFOOver or ISB_TxErr or ISB_TxOK or ISB_RxErr or ISB_RxOK
rx_config = (RX_FIFO_THRESH shl RXC_FIFOShift) or (RX_DMA_BURST shl RXC_DMAShift) or 0x0000000E
 
 
macro udelay msec {
 
push esi
mov esi, msec
call Sleep
pop esi
 
}
 
macro WRITE_GMII_REG RegAddr, value {
 
set_io REG_PHYAR
if value eq ax
and eax, 0x0000ffff
or eax, 0x80000000 + (RegAddr shl 16)
else
mov eax, 0x80000000 + (RegAddr shl 16) + value
end if
out dx, eax
 
call PHY_WAIT_WRITE
}
 
macro READ_GMII_REG RegAddr {
 
local .error, .done
 
set_io REG_PHYAR
mov eax, RegAddr shl 16
out dx, eax
 
call PHY_WAIT_READ
jz .error
 
in eax, dx
and eax, 0xFFFF
jmp .done
 
.error:
or eax, -1
.done:
}
 
align 4
PHY_WAIT_READ: ; io addr must already be set to REG_PHYAR
 
udelay 1 ;;;1000
 
push ecx
mov ecx, 2000
; Check if the RTL8169 has completed writing/reading to the specified MII register
@@:
in eax, dx
test eax, 0x80000000
jnz .exit
udelay 1 ;;;100
loop @b
.exit:
pop ecx
ret
 
align 4
PHY_WAIT_WRITE: ; io addr must already be set to REG_PHYAR
 
udelay 1 ;;;1000
 
push ecx
mov ecx, 2000
; Check if the RTL8169 has completed writing/reading to the specified MII register
@@:
in eax, dx
test eax, 0x80000000
jz .exit
udelay 1 ;;;100
loop @b
.exit:
pop ecx
ret
 
 
 
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 @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
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, device_size, .fail ; Allocate memory to put the device structure in
 
; 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 io addres of the PCI device
 
PCI_find_io
mov [tpc.mmio_addr], eax ; CHECKME
 
; We've found the io address, find IRQ now
 
PCI_find_irq
 
DEBUGF 2,"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.io_addr]:8
 
; Ok, the eth_device structure is ready, let's probe the device
; Because initialization fires IRQ, IRQ handler must be aware of this device
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 probe ; this function will output in eax
test eax, eax
jnz .err2 ; If an error occured, exit
 
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 2,"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 2,"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
 
.err2:
dec [devices]
.err:
DEBUGF 2,"removing device structure\n"
stdcall KernelFree, ebx
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
align 4
unload:
 
ret
 
 
align 4
init_board:
 
DEBUGF 1,"init_board\n"
 
PCI_make_bus_master
 
; Soft reset the chip
set_io 0
set_io REG_ChipCmd
mov al, CMD_Reset
out dx, al
 
; Check that the chip has finished the reset
mov ecx, 1000
set_io REG_ChipCmd
@@: in al, dx
test al, CMD_Reset
jz @f
udelay 10
loop @b
@@:
; identify config method
set_io REG_TxConfig
in eax, dx
and eax, 0x7c800000
DEBUGF 1,"init_board: TxConfig & 0x7c800000 = 0x%x\n", eax
mov esi, mac_info-8
@@: add esi, 8
mov ecx, eax
and ecx, [esi]
cmp ecx, [esi]
jne @b
mov eax, [esi+4]
mov [tpc.mcfg], eax
 
mov [tpc.pcfg], PCFG_METHOD_3
READ_GMII_REG 3
and al, 0x0f
or al, al
jnz @f
mov [tpc.pcfg], PCFG_METHOD_1
jmp .pconf
@@: dec al
jnz .pconf
mov [tpc.pcfg], PCFG_METHOD_2
.pconf:
 
; identify chip attached to board
mov ecx, 10
mov eax, [tpc.mcfg]
@@: dec ecx
js @f
cmp eax, [rtl_chip_info + ecx*8]
jne @b
mov [tpc.chipset], ecx
jmp .match
@@:
; if unknown chip, assume array element #0, original RTL-8169 in this case
DEBUGF 1,"init_board: PCI device: unknown chip version, assuming RTL-8169\n"
set_io REG_TxConfig
in eax, dx
DEBUGF 1,"init_board: PCI device: TxConfig = 0x%x\n", eax
 
mov [tpc.chipset], 0
 
xor eax, eax
inc eax
ret
 
.match:
DEBUGF 1,"init_board: chipset=%u\n", ecx
xor eax,eax
ret
 
 
 
;***************************************************************************
; Function
; probe
; Description
; Searches for an ethernet card, enables it and clears the rx buffer
; If a card was found, it enables the ethernet -> TCPIP link
; Destroyed registers
; eax, ebx, ecx, edx
;
;***************************************************************************
align 4
probe:
 
DEBUGF 1,"probe\n"
 
call init_board
call read_mac
call PHY_config
 
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n"
set_io 0
set_io 0x82
mov al, 0x01
out dx, al
cmp [tpc.mcfg], MCFG_METHOD_03
jae @f
; DEBUGF 1,"K : Set PCI Latency=0x40\n"
; stdcall pci_write_config_byte,PCI_LATENCY_TIMER,0x40
@@:
cmp [tpc.mcfg], MCFG_METHOD_02
jne @f
; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n"
set_io 0x82
mov al, 0x01
out dx, al
; DEBUGF 1,"K : Set PHY Reg 0x0bh = 0x00h\n"
WRITE_GMII_REG 0x0b, 0x0000 ; w 0x0b 15 0 0
@@:
; if TBI is not enabled
set_io 0
set_io REG_PHYstatus
in al, dx
test al, PHYS_TBI_Enable
jz .tbi_dis
READ_GMII_REG PHY_AUTO_NEGO_REG
 
; enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged
and eax, 0x0C1F
or eax, PHY_Cap_10_Half or PHY_Cap_10_Full or PHY_Cap_100_Half or PHY_Cap_100_Full
WRITE_GMII_REG PHY_AUTO_NEGO_REG, ax
 
; enable 1000 Full Mode
WRITE_GMII_REG PHY_1000_CTRL_REG, PHY_Cap_1000_Full or PHY_Cap_1000_Half ; rtl8168
 
; Enable auto-negotiation and restart auto-nigotiation
WRITE_GMII_REG PHY_CTRL_REG, PHY_Enable_Auto_Nego or PHY_Restart_Auto_Nego
 
udelay 100
mov ecx, 10000
; wait for auto-negotiation process
@@: dec ecx
jz @f
set_io 0
READ_GMII_REG PHY_STAT_REG
udelay 100
test eax, PHY_Auto_Neco_Comp
jz @b
set_io REG_PHYstatus
in al, dx
jmp @f
.tbi_dis:
udelay 100
@@:
 
 
;***************************************************************************
; Function
; rt8169_reset
; Description
; Place the chip (ie, the ethernet card) into a virgin state
; Destroyed registers
; eax, ebx, ecx, edx
;
;***************************************************************************
align 4
reset:
 
DEBUGF 1,"reset\n"
 
lea eax, [device.tx_ring]
mov [tpc.TxDescArrays], eax
mov [tpc.TxDescArray], eax
 
lea eax, [device.rx_ring]
mov [tpc.RxDescArrays], eax
mov [tpc.RxDescArray], eax
 
call init_ring
call hw_start
 
; clear packet/byte counters
 
xor eax, eax
lea edi, [device.bytes_tx]
mov ecx, 6
rep stosd
 
mov [device.mtu], 1500
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
xor eax, eax
ret
 
 
 
 
 
align 4
PHY_config:
 
DEBUGF 1,"hw_PHY_config: priv.mcfg=%d, priv.pcfg=%d\n",[tpc.mcfg],[tpc.pcfg]
 
cmp [tpc.mcfg], MCFG_METHOD_04
jne .not_4
set_io 0
; WRITE_GMII_REG 0x1F, 0x0001
; WRITE_GMII_REG 0x1b, 0x841e
; WRITE_GMII_REG 0x0e, 0x7bfb
; WRITE_GMII_REG 0x09, 0x273a
WRITE_GMII_REG 0x1F, 0x0002
WRITE_GMII_REG 0x01, 0x90D0
WRITE_GMII_REG 0x1F, 0x0000
jmp .exit
.not_4:
cmp [tpc.mcfg], MCFG_METHOD_02
je @f
cmp [tpc.mcfg], MCFG_METHOD_03
jne .not_2_or_3
@@:
set_io 0
WRITE_GMII_REG 0x1F, 0x0001
WRITE_GMII_REG 0x15, 0x1000
WRITE_GMII_REG 0x18, 0x65C7
WRITE_GMII_REG 0x04, 0x0000
WRITE_GMII_REG 0x03, 0x00A1
WRITE_GMII_REG 0x02, 0x0008
WRITE_GMII_REG 0x01, 0x1020
WRITE_GMII_REG 0x00, 0x1000
WRITE_GMII_REG 0x04, 0x0800
WRITE_GMII_REG 0x04, 0x0000
WRITE_GMII_REG 0x04, 0x7000
WRITE_GMII_REG 0x03, 0xFF41
WRITE_GMII_REG 0x02, 0xDE60
WRITE_GMII_REG 0x01, 0x0140
WRITE_GMII_REG 0x00, 0x0077
WRITE_GMII_REG 0x04, 0x7800
WRITE_GMII_REG 0x04, 0x7000
WRITE_GMII_REG 0x04, 0xA000
WRITE_GMII_REG 0x03, 0xDF01
WRITE_GMII_REG 0x02, 0xDF20
WRITE_GMII_REG 0x01, 0xFF95
WRITE_GMII_REG 0x00, 0xFA00
WRITE_GMII_REG 0x04, 0xA800
WRITE_GMII_REG 0x04, 0xA000
WRITE_GMII_REG 0x04, 0xB000
WRITE_GMII_REG 0x03, 0xFF41
WRITE_GMII_REG 0x02, 0xDE20
WRITE_GMII_REG 0x01, 0x0140
WRITE_GMII_REG 0x00, 0x00BB
WRITE_GMII_REG 0x04, 0xB800
WRITE_GMII_REG 0x04, 0xB000
WRITE_GMII_REG 0x04, 0xF000
WRITE_GMII_REG 0x03, 0xDF01
WRITE_GMII_REG 0x02, 0xDF20
WRITE_GMII_REG 0x01, 0xFF95
WRITE_GMII_REG 0x00, 0xBF00
WRITE_GMII_REG 0x04, 0xF800
WRITE_GMII_REG 0x04, 0xF000
WRITE_GMII_REG 0x04, 0x0000
WRITE_GMII_REG 0x1F, 0x0000
WRITE_GMII_REG 0x0B, 0x0000
jmp .exit
.not_2_or_3:
DEBUGF 1,"tpc.mcfg=%d, discard hw PHY config\n", [tpc.mcfg]
.exit:
ret
 
 
 
align 4
set_rx_mode:
 
DEBUGF 1,"set_rx_mode\n"
 
; IFF_ALLMULTI
; Too many to filter perfectly -- accept all multicasts
set_io 0
set_io REG_RxConfig
in eax, dx
mov ecx, [tpc.chipset]
and eax, [rtl_chip_info + ecx * 8 + 4] ; RxConfigMask
or eax, rx_config or (RXM_AcceptBroadcast or RXM_AcceptMulticast or RXM_AcceptMyPhys)
out dx, eax
 
; Multicast hash filter
set_io REG_MAR0 + 0
or eax, -1
out dx, eax
set_io REG_MAR0 + 4
out dx, eax
 
ret
 
 
align 4
init_ring:
 
DEBUGF 1,"init_ring\n"
 
xor eax, eax
mov [tpc.cur_rx], eax
mov [tpc.cur_tx], eax
 
lea edi, [device.tx_ring]
mov ecx, (NUM_TX_DESC * tx_desc.size) / 4
rep stosd
 
lea edi, [device.rx_ring]
mov ecx, (NUM_RX_DESC * rx_desc.size) / 4
rep stosd
 
mov edi, [tpc.RxDescArray]
mov ecx, NUM_RX_DESC
.loop:
push ecx
stdcall KernelAlloc, RX_BUF_SIZE
mov [edi + rx_desc.buf_soft_addr], eax
call GetPgAddr
mov dword [edi + rx_desc.buf_addr], eax
mov [edi + rx_desc.status], DSB_OWNbit or RX_BUF_SIZE
add edi, rx_desc.size
pop ecx
loop .loop
or [edi - rx_desc.size + rx_desc.status], DSB_EORbit
 
ret
 
 
align 4
hw_start:
 
DEBUGF 1,"hw_start\n"
 
; attach int handler
movzx eax, [device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
 
; Soft reset the chip
set_io 0
set_io REG_ChipCmd
mov al, CMD_Reset
out dx, al
 
DEBUGF 1,"Waiting for chip to reset... "
; Check that the chip has finished the reset
mov ecx, 1000
set_io REG_ChipCmd
@@: in al, dx
test al, CMD_Reset
jz @f
udelay 10
loop @b
@@:
DEBUGF 1,"done!\n"
 
set_io REG_Cfg9346
mov al, CFG_9346_Unlock
out dx, al
 
set_io REG_ChipCmd
mov al, CMD_TxEnb or CMD_RxEnb
out dx, al
 
set_io REG_ETThReg
mov al, ETTh
out dx, al
 
; For gigabit rtl8169
set_io REG_RxMaxSize
mov ax, RxPacketMaxSize
out dx, ax
 
; Set Rx Config register
set_io REG_RxConfig
in ax, dx
mov ecx, [tpc.chipset]
and eax, [rtl_chip_info + ecx * 8 + 4] ; RxConfigMask
or eax, rx_config
out dx, eax
 
; Set DMA burst size and Interframe Gap Time
set_io REG_TxConfig
mov eax, (TX_DMA_BURST shl TXC_DMAShift) or (InterFrameGap shl TXC_InterFrameGapShift)
out dx, eax
 
set_io REG_CPlusCmd
in ax, dx
out dx, ax
 
in ax, dx
or ax, 1 shl 3
cmp [tpc.mcfg], MCFG_METHOD_02
jne @f
cmp [tpc.mcfg], MCFG_METHOD_03
jne @f
or ax,1 shl 14
DEBUGF 1,"Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14\n"
jmp .set
@@:
DEBUGF 1,"Set MAC Reg C+CR Offset 0xE0: bit-3\n"
.set:
set_io REG_CPlusCmd
out dx, ax
 
set_io 0xE2
; mov ax, 0x1517
; out dx, ax
; mov ax, 0x152a
; out dx, ax
; mov ax, 0x282a
; out dx, ax
xor ax, ax
out dx, ax
 
xor eax, eax
mov [tpc.cur_rx], eax
lea eax, [device.tx_ring]
GetRealAddr
set_io REG_TxDescStartAddr
out dx, eax
 
lea eax, [device.rx_ring]
GetRealAddr
set_io REG_RxDescStartAddr
out dx, eax
 
set_io REG_Cfg9346
mov al, CFG_9346_Lock
out dx, al
 
udelay 10
 
xor eax, eax
set_io REG_RxMissed
out dx, eax
 
call set_rx_mode
 
set_io 0
; no early-rx interrupts
set_io REG_MultiIntr
in ax, dx
and ax, 0xF000
out dx, ax
 
; set interrupt mask
set_io REG_IntrMask
mov ax, intr_mask
out dx, ax
 
xor eax, eax
ret
 
 
align 4
read_mac:
 
set_io 0
set_io REG_MAC0
xor ecx, ecx
lea edi, [device.mac]
mov ecx, 6
 
; Get MAC address. FIXME: read EEPROM
@@: in al, dx
stosb
inc edx
loop @r
 
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
 
align 4
write_mac:
 
ret 6
 
 
 
 
 
;***************************************************************************
; Function
; transmit
; Description
; Transmits a packet of data via the ethernet card
;
; Destroyed registers
; eax, edx, esi, edi
;
;***************************************************************************
align 4
transmit:
 
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
DEBUGF 1,"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], MAX_ETH_FRAME_SIZE
ja .fail
 
;----------------------------------
; Find currentTX descriptor address
 
mov eax, tx_desc.size
mul [tpc.cur_tx]
lea esi, [eax + device.tx_ring]
 
DEBUGF 1,"Using TX desc: %x\n", esi
 
;---------------------------
; Program the packet pointer
 
mov eax, [esp + 4]
mov [esi + tx_desc.buf_soft_addr], eax
GetRealAddr
mov dword [esi + tx_desc.buf_addr], eax
 
;------------------------
; Program the packet size
 
mov eax, [esp + 8]
@@: or eax, DSB_OWNbit or DSB_FSbit or DSB_LSbit
cmp [tpc.cur_tx], NUM_TX_DESC - 1
jne @f
or eax, DSB_EORbit
@@: mov [esi + tx_desc.status], eax
 
;-----------------------------------------
; Set the polling bit (start transmission)
 
set_io 0
set_io REG_TxPoll
mov al, 0x40 ; set polling bit
out dx, al
 
;-----------------------
; Update TX descriptor
 
inc [tpc.cur_tx]
and [tpc.cur_tx], NUM_TX_DESC - 1
 
;-------------
; Update stats
 
inc [device.packets_tx]
mov eax, [esp + 8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
xor eax, eax
ret 8
 
.fail:
DEBUGF 1,"transmit failed\n"
or eax, -1
stdcall KernelFree, [esp+4]
ret 8
 
 
;;;DSB_OWNbit
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 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]
 
set_io 0
set_io REG_IntrStatus
in ax, dx
test ax, ax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
pop edi esi ebx
xor eax, eax
 
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x ", ebx, ax
 
cmp ax, 0xFFFF ; if so, hardware is no longer present
je .fail
 
;--------
; Receive
 
test ax, ISB_RxOK
jz .no_rx
 
push ax
push ebx
 
.check_more:
pop ebx
DEBUGF 1,"ebx = 0x%x\n", ebx
mov eax, rx_desc.size
mul [tpc.cur_rx]
lea esi, [eax + device.rx_ring]
 
DEBUGF 1,"RxDesc.status = 0x%x\n", [esi + rx_desc.status]
 
mov eax, [esi + rx_desc.status]
test eax, DSB_OWNbit ;;;
jnz .rx_return
 
DEBUGF 1,"tpc.cur_rx = %u\n", [tpc.cur_rx]
 
test eax, SD_RxRES
jnz .rx_return ;;;;; RX error!
 
push ebx
push .check_more
and eax, 0x00001FFF
add eax, -4 ; we dont need CRC
push eax
DEBUGF 1,"data length = %u\n", ax
 
;-------------
; Update stats
 
add dword [device.bytes_rx], eax
adc dword [device.bytes_rx + 4], 0
inc dword [device.packets_rx]
 
push [esi + rx_desc.buf_soft_addr]
 
;----------------------
; Allocate a new buffer
 
stdcall KernelAlloc, RX_BUF_SIZE
mov [esi + rx_desc.buf_soft_addr], eax
GetRealAddr
mov dword [esi + rx_desc.buf_addr], eax
 
;---------------
; re set OWN bit
 
mov eax, DSB_OWNbit or RX_BUF_SIZE
cmp [tpc.cur_rx], NUM_RX_DESC - 1
jne @f
or eax, DSB_EORbit
@@: mov [esi + rx_desc.status], eax
 
;--------------
; Update rx ptr
 
inc [tpc.cur_rx]
and [tpc.cur_rx], NUM_RX_DESC - 1
 
jmp Eth_input
.rx_return:
 
pop ax
.no_rx:
 
;---------
; Transmit
 
test ax, ISB_TxOK
jz .no_tx
push ax
 
DEBUGF 1,"TX ok!\n"
 
mov ecx, NUM_TX_DESC
lea esi, [device.tx_ring]
.txloop:
cmp [esi + tx_desc.buf_soft_addr], 0
jz .maybenext
 
test [esi + tx_desc.status], DSB_OWNbit
jnz .maybenext
 
push ecx
DEBUGF 1,"Freeing up TX desc: %x\n", esi
stdcall KernelFree, [esi + tx_desc.buf_soft_addr]
pop ecx
and [esi + tx_desc.buf_soft_addr], 0
 
.maybenext:
add esi, tx_desc.size
dec ecx
jnz .txloop
 
pop ax
.no_tx:
 
;-------
; Finish
 
set_io 0
set_io REG_IntrStatus
out dx, ax ; ACK all interrupts
 
.fail:
pop edi esi ebx
xor eax, eax
inc eax
 
ret
 
 
 
 
 
 
 
 
 
; End of code
align 4 ; Place all initialised data here
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'RTL8169',0 ; max 16 chars include zero
 
include_debug_strings ; All data wich FDO uses will be included here
 
rtl_chip_info dd \
MCFG_METHOD_01, 0xff7e1880, \ ; RTL8169
MCFG_METHOD_02, 0xff7e1880, \ ; RTL8169s/8110s
MCFG_METHOD_03, 0xff7e1880, \ ; RTL8169s/8110s
MCFG_METHOD_04, 0xff7e1880, \ ; RTL8169sb/8110sb
MCFG_METHOD_05, 0xff7e1880, \ ; RTL8169sc/8110sc
MCFG_METHOD_11, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E
MCFG_METHOD_12, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E
MCFG_METHOD_13, 0xff7e1880, \ ; RTL8101e // PCI-E 8139
MCFG_METHOD_14, 0xff7e1880, \ ; RTL8100e // PCI-E 8139
MCFG_METHOD_15, 0xff7e1880 ; RTL8100e // PCI-E 8139
 
mac_info dd \
0x38800000, MCFG_METHOD_15, \
0x38000000, MCFG_METHOD_12, \
0x34000000, MCFG_METHOD_13, \
0x30800000, MCFG_METHOD_14, \
0x30000000, MCFG_METHOD_11, \
0x18000000, MCFG_METHOD_05, \
0x10000000, MCFG_METHOD_04, \
0x04000000, MCFG_METHOD_03, \
0x00800000, MCFG_METHOD_02, \
0x00000000, MCFG_METHOD_01 ; catch-all
 
name_01 db "RTL8169", 0
name_02_03 db "RTL8169s/8110s", 0
name_04 db "RTL8169sb/8110sb", 0
name_05 db "RTL8169sc/8110sc", 0
name_11_12 db "RTL8168b/8111b", 0 ; PCI-E
name_13 db "RTL8101e", 0 ; PCI-E 8139
name_14_15 db "RTL8100e", 0 ; PCI-E 8139
 
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/ethernet/bcm57xx.asm
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
 
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/ethernet/dec21x4x.asm
0,0 → 1,1702
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; DEC 21x4x driver for KolibriOS ;;
;; ;;
;; Based on dec21140.Asm from Solar OS by ;;
;; Eugen Brasoveanu, ;;
;; Ontanu Bogdan Valentin ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
RX_DES_COUNT = 4 ; no of RX descriptors, must be power of 2
RX_BUFF_SIZE = 2048 ; size of buffer for each descriptor, must be multiple of 4 and <= 2048 TDES1_TBS1_MASK
 
TX_DES_COUNT = 4 ; no of TX descriptors, must be power of 2
TX_BUFF_SIZE = 2048 ; size of buffer for each descriptor, used for memory allocation only
 
 
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
 
.rx_p_des dd ? ; descriptors ring with received packets
.tx_p_des dd ? ; descriptors ring with 'to transmit' packets
.tx_free_des dd ? ; Tx descriptors available
.tx_wr_des dd ? ; Tx current descriptor to write data to
.tx_rd_des dd ? ; Tx current descriptor to read TX completion
.rx_crt_des dd ? ; Rx current descriptor
 
.io_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
 
.size = $ - device
 
end virtual
 
;-------------------------------------------
; configuration registers
;-------------------------------------------
CFCS = 4 ; configuration and status register
 
CSR0 = 0x00 ; Bus mode
CSR1 = 0x08 ; Transmit Poll Command
CSR2 = 0x10 ; Receive Poll Command
CSR3 = 0x18 ; Receive list base address
CSR4 = 0x20 ; Transmit list base address
CSR5 = 0x28 ; Status
CSR6 = 0x30 ; Operation mode
CSR7 = 0x38 ; Interrupt enable
CSR8 = 0x40 ; Missed frames and overflow counter
CSR9 = 0x48 ; Boot ROM, serial ROM, and MII management
CSR10 = 0x50 ; Boot ROM programming address
CSR11 = 0x58 ; General-purpose timer
CSR12 = 0x60 ; General-purpose port
CSR13 = 0x68
CSR14 = 0x70
CSR15 = 0x78 ; Watchdog timer
 
;--------bits/commands of CSR0-------------------
CSR0_RESET = 1b
 
CSR0_WIE = 1 shl 24 ; Write and Invalidate Enable
CSR0_RLE = 1 shl 23 ; PCI Read Line Enable
CSR0_RML = 1 shl 21 ; PCI Read Multiple
 
CSR0_CACHEALIGN_NONE = 00b shl 14
CSR0_CACHEALIGN_32 = 01b shl 14
CSR0_CACHEALIGN_64 = 10b shl 14
CSR0_CACHEALIGN_128 = 11b shl 14
 
; using values from linux driver..
CSR0_DEFAULT = CSR0_WIE + CSR0_RLE + CSR0_RML + CSR0_CACHEALIGN_NONE
 
;------- CSR5 -STATUS- bits --------------------------------
CSR5_TI = 1 shl 0 ; Transmit interupt - frame transmition completed
CSR5_TPS = 1 shl 1 ; Transmit process stopped
CSR5_TU = 1 shl 2 ; Transmit Buffer unavailable
CSR5_TJT = 1 shl 3 ; Transmit Jabber Timeout (transmitter had been excessively active)
CSR5_UNF = 1 shl 5 ; Transmit underflow - FIFO underflow
CSR5_RI = 1 shl 6 ; Receive Interrupt
CSR5_RU = 1 shl 7 ; Receive Buffer unavailable
CSR5_RPS = 1 shl 8 ; Receive Process stopped
CSR5_RWT = 1 shl 9 ; Receive Watchdow Timeout
CSR5_ETI = 1 shl 10 ; Early transmit Interrupt
CSR5_GTE = 1 shl 11 ; General Purpose Timer Expired
CSR5_FBE = 1 shl 13 ; Fatal bus error
CSR5_ERI = 1 shl 14 ; Early receive Interrupt
CSR5_AIS = 1 shl 15 ; Abnormal interrupt summary
CSR5_NIS = 1 shl 16 ; normal interrupt summary
CSR5_RS_SH = 17 ; Receive process state -shift
CSR5_RS_MASK = 111b ; -mask
CSR5_TS_SH = 20 ; Transmit process state -shift
CSR5_TS_MASK = 111b ; -mask
CSR5_EB_SH = 23 ; Error bits -shift
CSR5_EB_MASK = 111b ; Error bits -mask
 
;CSR5 TS values
CSR5_TS_STOPPED = 000b
CSR5_TS_RUNNING_FETCHING_DESC = 001b
CSR5_TS_RUNNING_WAITING_TX = 010b
CSR5_TS_RUNNING_READING_BUFF = 011b
CSR5_TS_RUNNING_SETUP_PCKT = 101b
CSR5_TS_SUSPENDED = 110b
CSR5_TS_RUNNING_CLOSING_DESC = 111b
 
;------- CSR6 -OPERATION MODE- bits --------------------------------
CSR6_HP = 1 shl 0 ; Hash/Perfect Receive Filtering mode
CSR6_SR = 1 shl 1 ; Start/Stop receive
CSR6_HO = 1 shl 2 ; Hash only Filtering mode
CSR6_PB = 1 shl 3 ; Pass bad frames
CSR6_IF = 1 shl 4 ; Inverse filtering
CSR6_SB = 1 shl 5 ; Start/Stop backoff counter
CSR6_PR = 1 shl 6 ; Promiscuos mode -default after reset
CSR6_PM = 1 shl 7 ; Pass all multicast
CSR6_F = 1 shl 9 ; Full Duplex mode
CSR6_OM_SH = 10 ; Operating Mode -shift
CSR6_OM_MASK = 11b ; -mask
CSR6_FC = 1 shl 12 ; Force Collision Mode
CSR6_ST = 1 shl 13 ; Start/Stop Transmission Command
CSR6_TR_SH = 14 ; Threshold Control -shift
CSR6_TR_MASK = 11b ; -mask
CSR6_CA = 1 shl 17 ; Capture Effect Enable
CSR6_PS = 1 shl 18 ; Port select SRL / MII/SYM
CSR6_HBD = 1 shl 19 ; Heartbeat Disable
CSR6_SF = 1 shl 21 ; Store and Forward -transmit full packet only
CSR6_TTM = 1 shl 22 ; Transmit Threshold Mode -
CSR6_PCS = 1 shl 23 ; PCS active and MII/SYM port operates in symbol mode
CSR6_SCR = 1 shl 24 ; Scrambler Mode
CSR6_MBO = 1 shl 25 ; Must Be One
CSR6_RA = 1 shl 30 ; Receive All
CSR6_SC = 1 shl 31 ; Special Capture Effect Enable
 
 
;------- CSR7 -INTERRUPT ENABLE- bits --------------------------------
CSR7_TI = 1 shl 0 ; transmit Interrupt Enable (set with CSR7<16> & CSR5<0> )
CSR7_TS = 1 shl 1 ; transmit Stopped Enable (set with CSR7<15> & CSR5<1> )
CSR7_TU = 1 shl 2 ; transmit buffer underrun Enable (set with CSR7<16> & CSR5<2> )
CSR7_TJ = 1 shl 3 ; transmit jabber timeout enable (set with CSR7<15> & CSR5<3> )
CSR7_UN = 1 shl 5 ; underflow Interrupt enable (set with CSR7<15> & CSR5<5> )
CSR7_RI = 1 shl 6 ; receive Interrupt enable (set with CSR7<16> & CSR5<5> )
CSR7_RU = 1 shl 7 ; receive buffer unavailable enable (set with CSR7<15> & CSR5<7> )
CSR7_RS = 1 shl 8 ; Receive stopped enable (set with CSR7<15> & CSR5<8> )
CSR7_RW = 1 shl 9 ; receive watchdog timeout enable (set with CSR7<15> & CSR5<9> )
CSR7_ETE = 1 shl 10 ; Early transmit Interrupt enable (set with CSR7<15> & CSR5<10> )
CSR7_GPT = 1 shl 11 ; general purpose timer enable (set with CSR7<15> & CSR5<11> )
CSR7_FBE = 1 shl 13 ; Fatal bus error enable (set with CSR7<15> & CSR5<13> )
CSR7_ERE = 1 shl 14 ; Early receive enable (set with CSR7<16> & CSR5<14> )
CSR7_AI = 1 shl 15 ; Abnormal Interrupt Summary Enable (enables CSR5<0,3,7,8,9,10,13>)
CSR7_NI = 1 shl 16 ; Normal Interrup Enable (enables CSR5<0,2,6,11,14>)
 
CSR7_DEFAULT = CSR7_TI + CSR7_TS + CSR7_RI + CSR7_RS + CSR7_TU + CSR7_TJ + CSR7_UN + \
CSR7_RU + CSR7_RW + CSR7_FBE + CSR7_AI + CSR7_NI
 
;----------- descriptor structure ---------------------
struc DES {
.status dd ? ; bit 31 is 'own' and rest is 'status'
.length dd ? ; control bits + bytes-count buffer 1 + bytes-count buffer 2
.buffer1 dd ? ; pointer to buffer1
.buffer2 dd ? ; pointer to buffer2 or in this case to next descriptor, as we use a chained structure
.virtaddr dd ?
.size = 64 ; 64, for alignment purposes
}
 
virtual at 0
DES DES
end virtual
 
;common to Rx and Tx
DES0_OWN = 1 shl 31 ; if set, the NIC controls the descriptor, otherwise driver 'owns' the descriptors
 
;receive
RDES0_ZER = 1 shl 0 ; must be 0 if legal length :D
RDES0_CE = 1 shl 1 ; CRC error, valid only on last desc (RDES0<8>=1)
RDES0_DB = 1 shl 2 ; dribbling bit - not multiple of 8 bits, valid only on last desc (RDES0<8>=1)
RDES0_RE = 1 shl 3 ; Report on MII error.. i dont realy know what this means :P
RDES0_RW = 1 shl 4 ; received watchdog timer expiration - must set CSR5<9>, valid only on last desc (RDES0<8>=1)
RDES0_FT = 1 shl 5 ; frame type: 0->IEEE802.0 (len<1500) 1-> ETHERNET frame (len>1500), valid only on last desc (RDES0<8>=1)
RDES0_CS = 1 shl 6 ; Collision seen, valid only on last desc (RDES0<8>=1)
RDES0_TL = 1 shl 7 ; Too long(>1518)-NOT AN ERROR, valid only on last desc (RDES0<8>=1)
RDES0_LS = 1 shl 8 ; Last descriptor of current frame
RDES0_FS = 1 shl 9 ; First descriptor of current frame
RDES0_MF = 1 shl 10 ; Multicast frame, valid only on last desc (RDES0<8>=1)
RDES0_RF = 1 shl 11 ; Runt frame, valid only on last desc (RDES0<8>=1) and id overflow
RDES0_DT_SERIAL = 00b shl 12 ; Data type-Serial recv frame, valid only on last desc (RDES0<8>=1)
RDES0_DT_INTERNAL = 01b shl 12 ; Data type-Internal loopback recv frame, valid only on last desc (RDES0<8>=1)
RDES0_DT_EXTERNAL = 11b shl 12 ; Data type-External loopback recv frame, valid only on last desc (RDES0<8>=1)
RDES0_DE = 1 shl 14 ; Descriptor error - cant own a new desc and frame doesnt fit, valid only on last desc (RDES0<8>=1)
RDES0_ES = 1 shl 15 ; Error Summmary - bits 1+6+11+14, valid only on last desc (RDES0<8>=1)
RDES0_FL_SH = 16 ; Field length shift, valid only on last desc (RDES0<8>=1)
RDES0_FL_MASK = 11111111111111b ; Field length mask (+CRC), valid only on last desc (RDES0<8>=1)
RDES0_FF = 1 shl 30 ; Filtering fail-frame failed address recognition test(must CSR6<30>=1), valid only on last desc (RDES0<8>=1)
 
RDES1_RBS1_MASK = 11111111111b ; first buffer size MASK
RDES1_RBS2_SH = 11 ; second buffer size SHIFT
RDES1_RBS2_MASK = 11111111111b ; second buffer size MASK
RDES1_RCH = 1 shl 24 ; Second address chained - second address (buffer) is next desc address
RDES1_RER = 1 shl 25 ; Receive End of Ring - final descriptor, NIC must return to first desc
 
;transmition
TDES0_DE = 1 shl 0 ; Deffered
TDES0_UF = 1 shl 1 ; Underflow error
TDES0_LF = 1 shl 2 ; Link fail report (only if CSR6<23>=1)
TDES0_CC_SH = 3 ; Collision Count shift - no of collision before transmition
TDES0_CC_MASK = 1111b ; Collision Count mask
TDES0_HF = 1 shl 7 ; Heartbeat fail
TDES0_EC = 1 shl 8 ; Excessive Collisions - >16 collisions
TDES0_LC = 1 shl 9 ; Late collision
TDES0_NC = 1 shl 10 ; No carrier
TDES0_LO = 1 shl 11 ; Loss of carrier
TDES0_TO = 1 shl 14 ; Transmit Jabber Timeout
TDES0_ES = 1 shl 15 ; Error summary TDES0<1+8+9+10+11+14>=1
 
TDES1_TBS1_MASK = 11111111111b ; Buffer 1 size mask
TDES1_TBS2_SH = 11 ; Buffer 2 size shift
TDES1_TBS2_MASK = 11111111111b ; Buffer 2 size mask
TDES1_FT0 = 1 shl 22 ; Filtering type 0
TDES1_DPD = 1 shl 23 ; Disabled padding for packets <64bytes, no padding
TDES1_TCH = 1 shl 24 ; Second address chained - second buffer pointer is to next desc
TDES1_TER = 1 shl 25 ; Transmit end of ring - final descriptor
TDES1_AC = 1 shl 26 ; Add CRC disable -pretty obvious
TDES1_SET = 1 shl 27 ; Setup packet
TDES1_FT1 = 1 shl 28 ; Filtering type 1
TDES1_FS = 1 shl 29 ; First segment - buffer is first segment of frame
TDES1_LS = 1 shl 30 ; Last segment
TDES1_IC = 1 shl 31 ; Interupt on completion (CSR5<0>=1) valid when TDES1<30>=1
 
MAX_ETH_FRAME_SIZE = 1514
 
RX_MEM_TOTAL_SIZE = RX_DES_COUNT*(DES.size+RX_BUFF_SIZE)
TX_MEM_TOTAL_SIZE = TX_DES_COUNT*(DES.size+TX_BUFF_SIZE)
 
;=============================================================================
; serial ROM operations
;=============================================================================
CSR9_SR = 1 shl 11 ; SROM Select
CSR9_RD = 1 shl 14 ; ROM Read Operation
CSR9_SROM_DO = 1 shl 3 ; Data Out for SROM
CSR9_SROM_DI = 1 shl 2 ; Data In to SROM
CSR9_SROM_CK = 1 shl 1 ; clock for SROM
CSR9_SROM_CS = 1 shl 0 ; chip select.. always needed
 
; assume dx is CSR9
macro SROM_Delay {
push eax
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
pop eax
}
 
; assume dx is CSR9
macro MDIO_Delay {
push eax
in eax, dx
pop eax
}
 
macro Bit_Set a_bit {
in eax, dx
or eax, a_bit
out dx , eax
}
 
macro Bit_Clear a_bit {
in eax, dx
and eax, not (a_bit)
out dx, eax
}
 
 
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 @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
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
 
push edx
stdcall KernelAlloc, dword device.size ; Allocate the buffer for eth_device structure
pop edx
test eax, eax
jz .fail
mov ebx, eax ; ebx is always used as a pointer to the structure (in driver, but also in kernel code)
 
; 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 io addres of the PCI device
 
PCI_find_io
 
; We've found the io address, find IRQ now
 
PCI_find_irq
 
DEBUGF 2,"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.io_addr]:8
 
allocate_and_clear [device.rx_p_des], RX_DES_COUNT*(DES.size+RX_BUFF_SIZE), .err
allocate_and_clear [device.tx_p_des], TX_DES_COUNT*(DES.size+TX_BUFF_SIZE), .err
 
; Ok, the eth_device structure is ready, let's probe the device
; Because initialization fires IRQ, IRQ handler must be aware of this device
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 probe ; this function will output in eax
test eax, eax
jnz .err2 ; If an error occured, exit
 
 
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 2,"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 2,"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
 
.err2:
dec [devices]
.err:
DEBUGF 2,"removing device structure\n"
stdcall KernelFree, [device.rx_p_des]
stdcall KernelFree, [device.tx_p_des]
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 (RTL8139_LIST)
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
 
or eax,-1
 
ret
 
 
macro status {
set_io CSR5
in eax, dx
DEBUGF 1,"CSR5: %x\n", eax
}
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Probe ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
probe:
 
DEBUGF 2,"Probing dec21x4x device: "
 
PCI_make_bus_master
 
stdcall PciRead32, [device.pci_bus], [device.pci_dev], 0 ; get device/vendor id
DEBUGF 1,"Vendor id: 0x%x\n", ax
 
cmp ax, 0x1011
je .dec
cmp ax, 0x1317
je .admtek
jmp .notfound
 
.dec:
shr eax, 16
DEBUGF 1,"Vendor ok!, device id: 0x%x\n", ax ; TODO: use another method to detect chip!
 
cmp ax, 0x0009
je .supported_device
 
cmp ax, 0x0019
je .supported_device2
 
.admtek:
shr eax, 16
DEBUGF 1,"Vendor ok!, device id: 0x%x\n", ax
 
cmp ax, 0x0985
je .supported_device
 
.notfound:
DEBUGF 1,"Device not supported!\n"
or eax, -1
ret
 
.supported_device2:
 
; wake up the 21143
 
xor eax, eax
stdcall PciWrite32, [device.pci_bus], [device.pci_dev], 0x40, eax
 
 
.supported_device:
call SROM_GetWidth ; TODO: use this value returned in ecx
; in the read_word routine!
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Reset ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
reset:
 
DEBUGF 2,"Resetting dec21x4x\n"
 
;-----------------------------------------------------------
; board software reset - if fails, dont do nothing else
 
set_io 0
status
set_io CSR0
mov eax, CSR0_RESET
out dx, eax
 
; wait at least 50 PCI cycles
mov esi, 1000
call Sleep
 
;-----------
; setup CSR0
 
set_io 0
status
set_io CSR0
mov eax, CSR0_DEFAULT
out dx, eax
 
 
; wait at least 50 PCI cycles
mov esi, 1000
call Sleep
 
;-----------------------------------
; Read mac from eeprom to driver ram
 
call read_mac_eeprom
 
;--------------------------------
; insert irq handler on given irq
 
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
@@:
 
set_io 0
status
 
call init_ring
 
;--------------------------------------------
; setup CSR3 & CSR4 (pointers to descriptors)
 
set_io 0
status
set_io CSR3
mov eax, [device.rx_p_des]
GetRealAddr
DEBUGF 1,"RX descriptor base address: %x\n", eax
out dx, eax
 
set_io CSR4
mov eax, [device.tx_p_des]
GetRealAddr
DEBUGF 1,"TX descriptor base address: %x\n", eax
out dx, eax
 
;-------------------------------------------------------
; setup interrupt mask register -expect IRQs from now on
 
status
DEBUGF 1,"Enabling interrupts\n"
set_io CSR7
mov eax, CSR7_DEFAULT
out dx, eax
status
 
;----------
; enable RX
 
set_io 0
status
DEBUGF 1,"Enable RX\n"
 
set_io CSR6
Bit_Set CSR6_SR; or CSR6_PR or CSR6_ST
DEBUGF 1,"CSR6: %x\n", eax
 
status
 
call start_link
 
; wait a bit
mov esi, 3000
call Sleep
 
;----------------------------------------------------
; send setup packet to notify the board about the MAC
 
call Send_Setup_Packet
 
xor eax, eax
; clear packet/byte counters
 
lea edi, [device.bytes_tx]
mov ecx, 6
rep stosd
 
; 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
 
DEBUGF 1,"Reset done\n"
 
ret
 
 
 
align 4
init_ring:
 
;------------------------------------------
; Setup RX descriptors (use chained method)
 
mov eax, [device.rx_p_des]
GetRealAddr
mov edx, eax
push eax
lea esi, [eax + RX_DES_COUNT*(DES.size)] ; jump over RX descriptors
mov eax, [device.rx_p_des]
add eax, RX_DES_COUNT*(DES.size) ; jump over RX descriptors
mov edi, [device.rx_p_des]
mov ecx, RX_DES_COUNT
.loop_rx_des:
add edx, DES.size
mov [edi + DES.status], DES0_OWN ; hardware owns buffer
mov [edi + DES.length], 1984 + RDES1_RCH ; only size of first buffer, chained buffers
mov [edi + DES.buffer1], esi ; hw buffer address
mov [edi + DES.buffer2], edx ; pointer to next descriptor
mov [edi + DES.virtaddr], eax ; virtual buffer address
DEBUGF 1,"RX desc: buff addr: %x, next desc: %x, real buff addr: %x, real descr addr: %x \n", esi, edx, eax, edi
 
add esi, RX_BUFF_SIZE
add eax, RX_BUFF_SIZE
add edi, DES.size
dec ecx
jnz .loop_rx_des
 
; set last descriptor as LAST
sub edi, DES.size
or [edi + DES.length], RDES1_RER ; EndOfRing
pop [edi + DES.buffer2] ; point it to the first descriptor
 
;---------------------
; Setup TX descriptors
 
mov eax, [device.tx_p_des]
GetRealAddr
mov edx, eax
push eax
lea esi, [eax + TX_DES_COUNT*(DES.size)] ; jump over TX descriptors
mov eax, [device.tx_p_des]
add eax, TX_DES_COUNT*(DES.size) ; jump over TX descriptors
mov edi, [device.tx_p_des]
mov ecx, TX_DES_COUNT
.loop_tx_des:
add edx, DES.size
mov [edi + DES.status], 0 ; owned by driver
mov [edi + DES.length], TDES1_TCH ; chained method
mov [edi + DES.buffer1], esi ; pointer to buffer
mov [edi + DES.buffer2], edx ; pointer to next descr
mov [edi + DES.virtaddr], eax
DEBUGF 1,"TX desc: buff addr: %x, next desc: %x, virt buff addr: %x, virt descr addr: %x \n", esi, edx, eax, edi
 
add esi, TX_BUFF_SIZE
add eax, TX_BUFF_SIZE
add edi, DES.size
dec ecx
jnz .loop_tx_des
; set last descriptor as LAST
sub edi, DES.size
or [edi + DES.length], TDES1_TER ; EndOfRing
pop [edi + DES.buffer2] ; point it to the first descriptor
 
;------------------
; Reset descriptors
 
mov [device.tx_wr_des], 0
mov [device.tx_rd_des], 0
mov [device.rx_crt_des], 0
mov [device.tx_free_des], TX_DES_COUNT
 
ret
 
 
align 4
start_link:
 
; TODO: write working code here
 
ret
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Send setup packet ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
Send_Setup_Packet:
 
DEBUGF 1,"Sending setup packet\n"
 
; if no descriptors available, out
mov ecx, 1000
@@loop_wait_desc:
cmp [device.tx_free_des], 0
jne @f
 
dec ecx
jnz @@loop_wait_desc
 
mov eax, -1
ret
@@:
 
; go to current send descriptor
mov edi, [device.tx_p_des]
mov eax, [device.tx_wr_des]
DEBUGF 1,"Got free descriptor: %u (%x)", eax, edi
mov edx, DES.size
mul edx
add edi, eax
DEBUGF 1,"=>%x\n", edi
 
; if NOT sending FIRST setup packet, must set current descriptor to 0 size for both buffers,
; and go to next descriptor for real setup packet... ;; TODO: check if 2 descriptors are available
 
; cmp [device.tx_packets], 0
; je .first
;
; and [edi+DES.des1], 0
; mov [edi+DES.des0], DES0_OWN
;
; go to next descriptor
; inc [device.tx_wr_des]
; and [device.tx_wr_des], TX_DES_COUNT-1
;
; dec free descriptors count
; cmp [device.tx_free_des], 0
; jz @f
; dec [device.tx_free_des]
; @@:
;
; ; recompute pointer to current descriptor
; mov edi, [device.tx_p_des]
; mov eax, [device.tx_wr_des]
; mov edx, DES.size
; mul edx
; add edi, eax
 
.first:
 
push edi
; copy setup packet to current descriptor
mov edi, [edi + DES.virtaddr]
; copy the address once
lea esi, [device.mac]
DEBUGF 1,"copying packet to %x from %x\n", edi, esi
mov ecx, 3 ; mac is 6 bytes thus 3 words
.loop:
DEBUGF 1,"%x ", [esi]:4
movsw
inc edi
inc edi
dec ecx
jnz .loop
 
DEBUGF 1,"\n"
 
; copy 15 times the broadcast address
mov ecx, 3*15
mov eax, 0xffffffff
rep stosd
 
pop edi
 
; setup descriptor
DEBUGF 1,"setting up descriptor\n"
mov [edi + DES.length], TDES1_IC + TDES1_SET + TDES1_TCH + 192 ; size must be EXACTLY 192 bytes
mov [edi + DES.status], DES0_OWN
 
DEBUGF 1,"status: %x\n", [edi + DES.status]:8
DEBUGF 1,"length: %x\n", [edi + DES.length]:8
DEBUGF 1,"buffer1: %x\n", [edi + DES.buffer1]:8
DEBUGF 1,"buffer2: %x\n", [edi + DES.buffer2]:8
 
; go to next descriptor
inc [device.tx_wr_des]
and [device.tx_wr_des], TX_DES_COUNT-1
 
; dec free descriptors count
cmp [device.tx_free_des], 0
jz @f
dec [device.tx_free_des]
@@:
 
; start tx
set_io 0
status
set_io CSR6
in eax, dx
test eax, CSR6_ST ; if NOT started, start now
jnz .already_started
or eax, CSR6_ST
DEBUGF 1,"Starting TX\n"
jmp .do_it
.already_started:
; if already started, issue a Transmit Poll command
set_io CSR1
xor eax, eax
DEBUGF 1,"Issuing transmit poll command\n"
.do_it:
out dx, eax
status
 
DEBUGF 1,"Sending setup packet, completed!\n"
 
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
transmit:
 
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
mov eax, [esp+4]
DEBUGF 1,"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], MAX_ETH_FRAME_SIZE
ja .fail
 
cmp [device.tx_free_des], 0
je .fail
 
;--------------------------
; copy packet to crt buffer
mov eax, [device.tx_wr_des]
mov edx, DES.size
mul edx
add eax, [device.tx_p_des]
mov edi, [eax + DES.virtaddr] ; pointer to buffer
mov esi, [esp+4]
mov ecx, [esp+8]
DEBUGF 1,"copying %u bytes from %x to %x\n", ecx, esi, edi
rep movsb
 
; set packet size
mov ecx, [eax+DES.length]
and ecx, TDES1_TER ; preserve 'End of Ring' bit
or ecx, [esp+8] ; set size
or ecx, TDES1_FS or TDES1_LS or TDES1_IC or TDES1_TCH ; first descr, last descr, interrupt on complete, chained modus
mov [eax+DES.length], ecx
 
; set descriptor info
mov [eax+DES.status], DES0_OWN ; say it is now owned by the 21x4x
 
; start tx
set_io 0
status
set_io CSR6
in eax, dx
test eax, CSR6_ST ; if NOT started, start now
jnz .already_started
or eax, CSR6_ST
DEBUGF 1,"Starting TX\n"
jmp .do_it
.already_started:
; if already started, issues a Transmit Poll command
set_io CSR1
mov eax, -1
.do_it:
out dx , eax
 
; Update stats
 
inc [device.packets_tx]
mov eax, [esp+8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
; go to next descriptor
inc [device.tx_wr_des]
and [device.tx_wr_des], TX_DES_COUNT-1
 
; dec free descriptors count
test [device.tx_free_des], -1
jz .end
dec [device.tx_free_des]
.end:
status
 
DEBUGF 1,"transmit ok\n"
xor eax, eax
stdcall KernelFree, [esp+4]
ret 8
 
.fail:
DEBUGF 1,"transmit failed\n"
or eax, -1
stdcall KernelFree, [esp+4]
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]
 
set_io 0
set_io CSR5
in eax, dx
test eax, eax
jnz .got_it
out dx, eax ; send it back to ACK
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
pop edi esi ebx
xor eax, eax
 
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
 
.got_it:
 
DEBUGF 1,"Device: %x CSR5: %x ", ebx, ax
 
;----------------------------------
; TX ok?
 
test ax, CSR5_TI
jz .not_tx
push ax esi ecx
 
DEBUGF 1,"TX ok!\n"
; go to current descriptor
mov edi, [device.tx_p_des]
 
mov eax, [device.tx_rd_des]
mov edx, DES.size
mul edx
add edi, eax
.loop_tx:
; done if all desc are free
cmp [device.tx_free_des], TX_DES_COUNT
jz .end_tx
 
mov eax, [edi+DES.status]
 
; we stop at first desc that is owned be NIC
test eax, DES0_OWN
jnz .end_tx
 
; detect is setup packet
cmp eax, (0ffffffffh - DES0_OWN) ; all other bits are 1
jne .not_setup_packet
DEBUGF 1,"Setup Packet detected\n"
.not_setup_packet:
 
DEBUGF 1,"packet status: %x\n", eax
 
; next descriptor
add edi, DES.size
inc [device.tx_rd_des]
and [device.tx_rd_des], TX_DES_COUNT-1
 
; inc free desc
inc [device.tx_free_des]
cmp [device.tx_free_des], TX_DES_COUNT
jbe @f
mov [device.tx_free_des], TX_DES_COUNT
@@:
 
jmp .loop_tx
.end_tx:
;------------------------------------------------------
; here must be called standard Ethernet Tx Irq Handler
;------------------------------------------------------
 
pop ecx esi ax
 
;----------------------------------
; RX irq
.not_tx:
test ax, CSR5_RI
jz .not_rx
push ax esi ecx
 
DEBUGF 1,"RX ok!\n"
 
push ebx
.rx_loop:
pop ebx
 
; get current descriptor
mov edi, [device.rx_p_des]
mov eax, [device.rx_crt_des]
mov edx, DES.size
mul edx
add edi, eax
 
; now check status
mov eax, [edi + DES.status]
 
test eax, DES0_OWN
jnz .end_rx ; current desc is busy, nothing to do
 
test eax, RDES0_FS
jz .end_rx ; current desc is NOT first packet, ERROR!
 
test eax, RDES0_LS ; if not last desc of packet, error for now
jz .end_rx
 
test eax, RDES0_ES
jnz .end_rx
 
mov esi, [edi + DES.virtaddr]
mov ecx, [edi + DES.status]
shr ecx, RDES0_FL_SH
and ecx, RDES0_FL_MASK
sub ecx, 4 ; crc, we dont need it
 
DEBUGF 1,"Received packet!, size=%u, addr:%x\n", ecx, esi
 
push esi edi ecx
stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
pop ecx edi esi
test eax, eax
jz .fail
 
push ebx
push dword .rx_loop
push ecx eax
mov edi, eax
 
; update statistics
inc [device.packets_rx]
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
 
; copy packet data
shr cx , 1
jnc .nb
movsb
.nb:
shr cx , 1
jnc .nw
movsw
.nw:
rep movsd
 
mov [edi + DES.status], DES0_OWN ; free descriptor
inc [device.rx_crt_des] ; next descriptor
and [device.rx_crt_des], RX_DES_COUNT-1
 
jmp Eth_input
 
.end_rx:
.fail:
pop ecx esi ax
.not_rx:
 
pop edi esi ebx
ret
 
 
 
align 4
write_mac: ; in: mac pushed onto stack (as 3 words)
 
DEBUGF 2,"Writing MAC: "
 
; write data into driver cache
mov esi, esp
lea edi, [device.mac]
movsd
movsw
add esp, 6
; send setup packet (only if driver is started)
call Send_Setup_Packet
 
align 4
read_mac:
 
DEBUGF 1,"Read_mac\n"
 
ret
 
 
 
align 4
read_mac_eeprom:
 
DEBUGF 1,"Read_mac_eeprom\n"
 
lea edi, [device.mac]
mov esi, 20/2 ; read words, start address is 20
.loop:
push esi edi
call SROM_Read_Word
pop edi esi
stosw
inc esi
cmp esi, 26/2
jb .loop
 
DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[edi-6]:2,[edi-5]:2,[edi-4]:2,[edi-3]:2,[edi-2]:2,[edi-1]:2
 
ret
 
align 4
write_mac_eeprom:
 
DEBUGF 1,"Write_mac_eeprom\n"
 
ret
 
 
align 4
SROM_GetWidth: ; should be 6 or 8 according to some manuals (returns in ecx)
 
DEBUGF 1,"SROM_GetWidth\n"
 
call SROM_Idle
call SROM_EnterAccessMode
 
; set_io 0
; set_io CSR9
 
; send 110b
 
in eax, dx
or eax, CSR9_SROM_DI
call SROM_out
 
in eax, dx
or eax, CSR9_SROM_DI
call SROM_out
 
in eax, dx
and eax, not (CSR9_SROM_DI)
call SROM_out
mov ecx,1
.loop2:
Bit_Set CSR9_SROM_CK
SROM_Delay
in eax, dx
and eax, CSR9_SROM_DO
jnz .not_zero
 
Bit_Clear CSR9_SROM_CK
SROM_Delay
jmp .end_loop2
.not_zero:
Bit_Clear CSR9_SROM_CK
SROM_Delay
inc ecx
cmp ecx, 12
jbe .loop2
.end_loop2:
DEBUGF 1,"Srom width=%u\n", ecx
call SROM_Idle
call SROM_EnterAccessMode
call SROM_Idle
ret
 
 
align 4
SROM_out:
 
out dx, eax
SROM_Delay
Bit_Set CSR9_SROM_CK
SROM_Delay
Bit_Clear CSR9_SROM_CK
SROM_Delay
 
ret
 
 
 
align 4
SROM_EnterAccessMode:
 
DEBUGF 1,"SROM_EnterAccessMode\n"
 
set_io 0
set_io CSR9
mov eax, CSR9_SR
out dx, eax
SROM_Delay
 
Bit_Set CSR9_RD
SROM_Delay
 
Bit_Clear CSR9_SROM_CK
SROM_Delay
 
Bit_Set CSR9_SROM_CS
SROM_Delay
ret
 
 
 
align 4
SROM_Idle:
 
DEBUGF 1,"SROM_Idle\n"
 
call SROM_EnterAccessMode
; set_io 0
; set_io CSR9
mov ecx, 25
.loop_clk:
 
Bit_Clear CSR9_SROM_CK
SROM_Delay
Bit_Set CSR9_SROM_CK
SROM_Delay
dec ecx
jnz .loop_clk
 
Bit_Clear CSR9_SROM_CK
SROM_Delay
Bit_Clear CSR9_SROM_CS
SROM_Delay
xor eax, eax
out dx, eax
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Read serial EEprom word ;;
;; ;;
;; In: esi = read address ;;
;; OUT: ax = data word ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
SROM_Read_Word:
 
DEBUGF 1,"SROM_Read_word at: %x result: ", esi
 
set_io 0
set_io CSR9
 
; enter access mode
mov eax, CSR9_SR + CSR9_RD
out dx , eax
or eax, CSR9_SROM_CS
out dx , eax
 
; TODO: change this hard-coded 6-bit stuff to use value from srom_getwidth
; send read command "110b" + address to read from
and esi, 111111b
or esi, 110b shl 6
mov ecx, 1 shl 9
.loop_cmd:
mov eax, CSR9_SR + CSR9_RD + CSR9_SROM_CS
test esi, ecx
jz @f
or eax, CSR9_SROM_DI
@@:
out dx , eax
SROM_Delay
or eax, CSR9_SROM_CK
out dx , eax
SROM_Delay
shr ecx, 1
jnz .loop_cmd
 
; read data from SROM
 
xor esi, esi
mov ecx, 17 ;;; TODO: figure out why 17, not 16
.loop_read:
mov eax, CSR9_SR + CSR9_RD + CSR9_SROM_CS + CSR9_SROM_CK
out dx , eax
SROM_Delay
in eax, dx
and eax, CSR9_SROM_DO
shr eax, 3
shl esi, 1
or esi, eax
mov eax, CSR9_SR + CSR9_RD + CSR9_SROM_CS
out dx , eax
SROM_Delay
dec ecx
jnz .loop_read
mov eax, esi
 
DEBUGF 1,"%x\n", ax
 
ret
 
 
 
 
 
 
 
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 
 
 
;*********************************************************************
;* Media Descriptor Code *
;*********************************************************************
 
; MII transceiver control section.
; Read and write the MII registers using software-generated serial
; MDIO protocol. See the MII specifications or DP83840A data sheet
; for details.
 
; The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
; met by back-to-back PCI I/O cycles, but we insert a delay to avoid
; "overclocking" issues or future 66Mhz PCI.
 
; Read and write the MII registers using software-generated serial
; MDIO protocol. It is just different enough from the EEPROM protocol
; to not share code. The maxium data clock rate is 2.5 Mhz.
 
MDIO_SHIFT_CLK = 0x10000
MDIO_DATA_WRITE0 = 0x00000
MDIO_DATA_WRITE1 = 0x20000
MDIO_ENB = 0x00000 ; Ignore the 0x02000 databook setting.
MDIO_ENB_IN = 0x40000
MDIO_DATA_READ = 0x80000
 
; MII transceiver control section.
; Read and write the MII registers using software-generated serial
; MDIO protocol. See the MII specifications or DP83840A data sheet
; for details.
 
align 4
mdio_read: ; phy_id:edx, location:esi
 
DEBUGF 1,"mdio read, phy=%x, location=%x", edx, esi
 
shl edx, 5
or esi, edx
or esi, 0xf6 shl 10
 
set_io 0
set_io CSR9
 
; if (tp->chip_id == LC82C168) {
; int i = 1000;
; outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);
; inl(ioaddr + 0xA0);
; inl(ioaddr + 0xA0);
; while (--i > 0)
; if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))
; return retval & 0xffff;
; return 0xffff;
; }
;
; if (tp->chip_id == COMET) {
; if (phy_id == 1) {
; if (location < 7)
; return inl(ioaddr + 0xB4 + (location<<2));
; else if (location == 17)
; return inl(ioaddr + 0xD0);
; else if (location >= 29 && location <= 31)
; return inl(ioaddr + 0xD4 + ((location-29)<<2));
; }
; return 0xffff;
; }
 
; Establish sync by sending at least 32 logic ones.
 
mov ecx, 32
.loop:
mov eax, MDIO_ENB or MDIO_DATA_WRITE1
out dx, eax
MDIO_Delay
 
or eax, MDIO_SHIFT_CLK
out dx, eax
MDIO_Delay
 
dec ecx
jnz .loop
 
 
; Shift the read command bits out.
 
mov ecx, 1 shl 15
.loop2:
mov eax, MDIO_ENB
test esi, ecx
jz @f
or eax, MDIO_DATA_WRITE1
@@:
out dx, eax
MDIO_Delay
 
or eax, MDIO_SHIFT_CLK
out dx, eax
MDIO_Delay
 
shr ecx, 1
jnz .loop2
 
 
; Read the two transition, 16 data, and wire-idle bits.
 
xor esi, esi
mov ecx, 19
.loop3:
mov eax, MDIO_ENB_IN
out dx, eax
MDIO_Delay
 
shl esi, 1
in eax, dx
test eax, MDIO_DATA_READ
jz @f
inc esi
@@:
 
mov eax, MDIO_ENB_IN or MDIO_SHIFT_CLK
out dx, eax
MDIO_Delay
 
dec ecx
jnz .loop3
 
shr esi, 1
movzx eax, si
 
DEBUGF 1,", data=%x\n", ax
 
ret
 
 
 
 
align 4
mdio_write: ;int phy_id: edx, int location: edi, int value: ax)
 
DEBUGF 1,"mdio write, phy=%x, location=%x, data=%x\n", edx, edi, ax
 
shl edi, 18
or edi, 0x5002 shl 16
shl edx, 23
or edi, edx
mov di, ax
 
set_io 0
set_io CSR9
 
; if (tp->chip_id == LC82C168) {
; int i = 1000;
; outl(cmd, ioaddr + 0xA0);
; do
; if ( ! (inl(ioaddr + 0xA0) & 0x80000000))
; break;
; while (--i > 0);
; return;
; }
 
; if (tp->chip_id == COMET) {
; if (phy_id != 1)
; return;
; if (location < 7)
; outl(value, ioaddr + 0xB4 + (location<<2));
; else if (location == 17)
; outl(value, ioaddr + 0xD0);
; else if (location >= 29 && location <= 31)
; outl(value, ioaddr + 0xD4 + ((location-29)<<2));
; return;
; }
 
 
; Establish sync by sending at least 32 logic ones.
 
mov ecx, 32
.loop:
mov eax, MDIO_ENB or MDIO_DATA_WRITE1
out dx, eax
MDIO_Delay
 
or eax, MDIO_SHIFT_CLK
out dx, eax
MDIO_Delay
 
dec ecx
jnz .loop
 
 
; Shift the command bits out.
 
mov ecx, 1 shl 31
.loop2:
mov eax, MDIO_ENB
test edi, ecx
jz @f
or eax, MDIO_DATA_WRITE1
@@:
out dx, eax
MDIO_Delay
 
or eax, MDIO_SHIFT_CLK
out dx, eax
MDIO_Delay
 
shr ecx, 1
jnz .loop2
 
 
; Clear out extra bits.
 
mov ecx, 2
.loop3:
mov eax, MDIO_ENB
out dx, eax
MDIO_Delay
 
or eax, MDIO_SHIFT_CLK
out dx, eax
MDIO_Delay
 
dec ecx
jnz .loop3
 
ret
 
 
; End of code
align 4 ; Place all initialised data here
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'DEC21X4X',0 ; max 16 chars include zero
 
include_debug_strings ; All data wich FDO uses will be included here
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/ethernet/forcedeth.asm
0,0 → 1,1992
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; FORCEDETH.INC ;;
;; ;;
;; Ethernet driver for Kolibri OS ;;
;; ;;
;; Driver for chips of NVIDIA nForce2 ;;
;; References: ;;
;; forcedeth.c - linux driver (etherboot project) ;;
;; ethernet driver template by Mike Hibbett ;;
;; ;;
;; The copyright statement is ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; Copyright 2008 shurf, ;;
;; cit.utc@gmail.com ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
RBLEN = 0 ; Receive buffer size: 0=4K 1=8k 2=16k 3=32k 4=64k
; FIXME: option 1 and 2 will not allocate buffer correctly causing data loss!
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 2
 
RX_RING = 4
TX_RING = 4
 
include '../proc32.inc'
include '../imports.inc'
include '../fdo.inc'
include '../struct.inc'
include '../netdrv.inc'
 
public START
public service_proc
public version
 
;**************************************************************************
; forcedeth Register Definitions
;**************************************************************************
 
PCI_DEVICE_ID_NVIDIA_NVENET_1 = 0x01c3
PCI_DEVICE_ID_NVIDIA_NVENET_2 = 0x0066
PCI_DEVICE_ID_NVIDIA_NVENET_4 = 0x0086
PCI_DEVICE_ID_NVIDIA_NVENET_5 = 0x008c
PCI_DEVICE_ID_NVIDIA_NVENET_3 = 0x00d6
PCI_DEVICE_ID_NVIDIA_NVENET_7 = 0x00df
PCI_DEVICE_ID_NVIDIA_NVENET_6 = 0x00e6
PCI_DEVICE_ID_NVIDIA_NVENET_8 = 0x0056
PCI_DEVICE_ID_NVIDIA_NVENET_9 = 0x0057
PCI_DEVICE_ID_NVIDIA_NVENET_10 = 0x0037
PCI_DEVICE_ID_NVIDIA_NVENET_11 = 0x0038
PCI_DEVICE_ID_NVIDIA_NVENET_12 = 0x0268
PCI_DEVICE_ID_NVIDIA_NVENET_13 = 0x0269
PCI_DEVICE_ID_NVIDIA_NVENET_14 = 0x0372
PCI_DEVICE_ID_NVIDIA_NVENET_15 = 0x0373
 
UNKSETUP1_VAL = 0x16070f
UNKSETUP2_VAL = 0x16
UNKSETUP3_VAL1 = 0x200010
UNKSETUP4_VAL = 8
UNKSETUP5_BIT31 = (1 shl 31)
UNKSETUP6_VAL = 3
 
TXRXCTL_RXCHECK = 0x0400
MIISTAT_ERROR = 0x0001
MIISTAT_MASK = 0x000f
MIISTAT_MASK2 = 0x000f
MIICTL_INUSE = 0x08000
MIICTL_WRITE = 0x00400
MIICTL_ADDRSHIFT = 5
 
MIISPEED_BIT8 = (1 shl 8)
MIIDELAY = 5
 
IRQ_RX_ERROR = 0x0001
IRQ_RX = 0x0002
IRQ_RX_NOBUF = 0x0004
IRQ_LINK = 0x0040
IRQ_TIMER = 0x0020
IRQMASK_WANTED_2 = 0x0147
 
IRQ_RX_ALL = IRQ_RX_ERROR or IRQ_RX or IRQ_RX_NOBUF
IRQ_TX_ALL = 0 ; ???????????
IRQ_OTHER_ALL = IRQ_LINK ;or IRQ_TIMER
 
IRQSTAT_MASK = 0x1ff
 
TXRXCTL_KICK = 0x0001
TXRXCTL_BIT1 = 0x0002
TXRXCTL_BIT2 = 0x0004
TXRXCTL_IDLE = 0x0008
TXRXCTL_RESET = 0x0010
TXRXCTL_RXCHECK = 0x0400
 
MCASTADDRA_FORCE = 0x01
 
MAC_RESET_ASSERT = 0x0F3
 
MISC1_HD = 0x02
MISC1_FORCE = 0x3b0f3c
 
PFF_ALWAYS = 0x7F0008
PFF_PROMISC = 0x80
PFF_MYADDR = 0x20
 
OFFLOAD_HOMEPHY = 0x601
OFFLOAD_NORMAL = 4096 shl RBLEN
 
RNDSEED_MASK = 0x00ff
RNDSEED_FORCE = 0x7f00
RNDSEED_FORCE2 = 0x2d00
RNDSEED_FORCE3 = 0x7400
 
; POLL_DEFAULT is the interval length of the timer source on the nic
; POLL_DEFAULT=97 would result in an interval length of 1 ms
POLL_DEFAULT = 970
 
ADAPTCTL_START = 0x02
ADAPTCTL_LINKUP = 0x04
ADAPTCTL_PHYVALID = 0x40000
ADAPTCTL_RUNNING = 0x100000
ADAPTCTL_PHYSHIFT = 24
 
WAKEUPFLAGS_VAL = 0x7770
 
POWERSTATE_POWEREDUP = 0x8000
POWERSTATE_VALID = 0x0100
POWERSTATE_MASK = 0x0003
POWERSTATE_D0 = 0x0000
POWERSTATE_D1 = 0x0001
POWERSTATE_D2 = 0x0002
POWERSTATE_D3 = 0x0003
 
POWERSTATE2_POWERUP_MASK = 0x0F11
POWERSTATE2_POWERUP_REV_A3= 0x0001
 
RCVCTL_START = 0x01
RCVSTAT_BUSY = 0x01
 
XMITCTL_START = 0x01
 
LINKSPEED_FORCE = 0x10000
LINKSPEED_10 = 1000
LINKSPEED_100 = 100
LINKSPEED_1000 = 50
 
RINGSZ_TXSHIFT = 0
RINGSZ_RXSHIFT = 16
 
LPA_1000FULL = 0x0800
 
; Link partner ability register.
LPA_SLCT = 0x001f ; Same as advertise selector
LPA_10HALF = 0x0020 ; Can do 10mbps half-duplex
LPA_10FULL = 0x0040 ; Can do 10mbps full-duplex
LPA_100HALF = 0x0080 ; Can do 100mbps half-duplex
LPA_100FULL = 0x0100 ; Can do 100mbps full-duplex
LPA_100BASE4 = 0x0200 ; Can do 100mbps 4k packets
LPA_RESV = 0x1c00 ; Unused...
LPA_RFAULT = 0x2000 ; Link partner faulted
LPA_LPACK = 0x4000 ; Link partner acked us
LPA_NPAGE = 0x8000 ; Next page bit
 
MII_READ = (-1)
MII_PHYSID1 = 0x02 ; PHYS ID 1
MII_PHYSID2 = 0x03 ; PHYS ID 2
MII_BMCR = 0x00 ; Basic mode control register
MII_BMSR = 0x01 ; Basic mode status register
MII_ADVERTISE = 0x04 ; Advertisement control reg
MII_LPA = 0x05 ; Link partner ability reg
MII_SREVISION = 0x16 ; Silicon revision
MII_RESV1 = 0x17 ; Reserved...
MII_NCONFIG = 0x1c ; Network interface config
 
; PHY defines
PHY_OUI_MARVELL = 0x5043
PHY_OUI_CICADA = 0x03f1
PHYID1_OUI_MASK = 0x03ff
PHYID1_OUI_SHFT = 6
PHYID2_OUI_MASK = 0xfc00
PHYID2_OUI_SHFT = 10
PHY_INIT1 = 0x0f000
PHY_INIT2 = 0x0e00
PHY_INIT3 = 0x01000
PHY_INIT4 = 0x0200
PHY_INIT5 = 0x0004
PHY_INIT6 = 0x02000
PHY_GIGABIT = 0x0100
 
PHY_TIMEOUT = 0x1
PHY_ERROR = 0x2
 
PHY_100 = 0x1
PHY_1000 = 0x2
PHY_HALF = 0x100
 
PHY_RGMII = 0x10000000
 
; desc_ver values:
; This field has two purposes:
; - Newer nics uses a different ring layout. The layout is selected by
; comparing np->desc_ver with DESC_VER_xy.
; - It contains bits that are forced on when writing to TxRxControl.
DESC_VER_1 = 0x0
DESC_VER_2 = (0x02100 or TXRXCTL_RXCHECK)
 
MAC_ADDR_LEN = 6
 
NV_TX_LASTPACKET = (1 shl 16)
NV_TX_RETRYERROR = (1 shl 19)
NV_TX_LASTPACKET1 = (1 shl 24)
NV_TX_DEFERRED = (1 shl 26)
NV_TX_CARRIERLOST = (1 shl 27)
NV_TX_LATECOLLISION = (1 shl 28)
NV_TX_UNDERFLOW = (1 shl 29)
NV_TX_ERROR = (1 shl 30)
NV_TX_VALID = (1 shl 31)
 
NV_TX2_LASTPACKET = (1 shl 29)
NV_TX2_RETRYERROR = (1 shl 18)
NV_TX2_LASTPACKET1 = (1 shl 23)
NV_TX2_DEFERRED = (1 shl 25)
NV_TX2_CARRIERLOST = (1 shl 26)
NV_TX2_LATECOLLISION = (1 shl 27)
NV_TX2_UNDERFLOW = (1 shl 28)
; error and valid are the same for both
NV_TX2_ERROR = (1 shl 30)
NV_TX2_VALID = (1 shl 31)
 
NV_RX_DESCRIPTORVALID = (1 shl 16)
NV_RX_AVAIL = (1 shl 31)
 
NV_RX2_DESCRIPTORVALID = (1 shl 29)
 
FLAG_MASK_V1 = 0xffff0000
FLAG_MASK_V2 = 0xffffc000
LEN_MASK_V1 = (0xffffffff xor FLAG_MASK_V1)
LEN_MASK_V2 = (0xffffffff xor FLAG_MASK_V2)
 
; Miscelaneous hardware related defines:
NV_PCI_REGSZ_VER1 = 0x270
NV_PCI_REGSZ_VER2 = 0x604
; various timeout delays: all in usec
NV_TXRX_RESET_DELAY = 4
NV_TXSTOP_DELAY1 = 10
NV_TXSTOP_DELAY1MAX = 500000
NV_TXSTOP_DELAY2 = 100
NV_RXSTOP_DELAY1 = 10
NV_RXSTOP_DELAY1MAX = 500000
NV_RXSTOP_DELAY2 = 100
NV_SETUP5_DELAY = 5
NV_SETUP5_DELAYMAX = 50000
NV_POWERUP_DELAY = 5
NV_POWERUP_DELAYMAX = 5000
NV_MIIBUSY_DELAY = 50
NV_MIIPHY_DELAY = 10
NV_MIIPHY_DELAYMAX = 10000
NV_MAC_RESET_DELAY = 64
NV_WAKEUPPATTERNS = 5
NV_WAKEUPMASKENTRIES = 4
 
; Advertisement control register.
ADVERTISE_SLCT = 0x001f ; Selector bits
ADVERTISE_CSMA = 0x0001 ; Only selector supported
ADVERTISE_10HALF = 0x0020 ; Try for 10mbps half-duplex
ADVERTISE_10FULL = 0x0040 ; Try for 10mbps full-duplex
ADVERTISE_100HALF = 0x0080 ; Try for 100mbps half-duplex
ADVERTISE_100FULL = 0x0100 ; Try for 100mbps full-duplex
ADVERTISE_100BASE4 = 0x0200 ; Try for 100mbps 4k packets
ADVERTISE_RESV = 0x1c00 ; 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)
 
MII_1000BT_CR = 0x09
MII_1000BT_SR = 0x0a
ADVERTISE_1000FULL = 0x0200
ADVERTISE_1000HALF = 0x0100
 
BMCR_ANRESTART = 0x0200 ; Auto negotiation restart
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 = 0x07c0 ; Unused...
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
 
struct TxDesc
PacketBuffer dd ?
FlagLen dd ?
ends
 
struct RxDesc
PacketBuffer dd ?
FlagLen dd ?
ends
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.pci_bus dd ?
.pci_dev dd ?
 
.mmio_addr dd ?
.vendor_id dw ?
.device_id dw ?
.txflags dd ?
.desc_ver dd ?
.irqmask dd ?
.wolenabled dd ?
.in_shutdown dd ?
.cur_rx dd ?
.phyaddr dd ?
.phy_oui dd ?
.gigabit dd ?
.needs_mac_reset dd ?
.linkspeed dd ?
.duplex dd ?
.next_tx dd ?
.nocable dd ?
 
rb 0x100 - (($ - device) and 0xff)
.tx_ring rd (TX_RING * sizeof.TxDesc) /4*2
 
rb 0x100 - (($ - device) and 0xff)
.rx_ring rd (RX_RING * sizeof.RxDesc) /4*2
 
sizeof.device_struct = $ - device
end virtual
 
 
virtual at edi
IrqStatus dd ?
IrqMask dd ?
UnknownSetupReg6 dd ?
PollingInterval dd ?
end virtual
 
virtual at edi + 0x3c
MacReset dd ?
end virtual
 
virtual at edi + 0x80
Misc1 dd ?
TransmitterControl dd ?
TransmitterStatus dd ?
PacketFilterFlags dd ?
OffloadConfig dd ?
ReceiverControl dd ?
ReceiverStatus dd ?
RandomSeed dd ?
UnknownSetupReg1 dd ?
UnknownSetupReg2 dd ?
MacAddrA dd ?
MacAddrB dd ?
MulticastAddrA dd ?
MulticastAddrB dd ?
MulticastMaskA dd ?
MulticastMaskB dd ?
PhyInterface dd ?
end virtual
 
virtual at edi + 0x100
TxRingPhysAddr dd ?
RxRingPhysAddr dd ?
RingSizes dd ?
UnknownTransmitterReg dd ?
LinkSpeed dd ?
end virtual
 
virtual at edi + 0x130
UnknownSetupReg5 dd ?
end virtual
 
virtual at edi + 0x13c
UnknownSetupReg3 dd ?
end virtual
 
virtual at edi + 0x144
TxRxControl dd ?
end virtual
 
virtual at edi + 0x180
MIIStatus dd ?
UnknownSetupReg4 dd ?
AdapterControl dd ?
MIISpeed dd ?
MIIControl dd ?
MIIData dd ?
end virtual
 
virtual at edi + 0x200
WakeUpFlags dd ?
end virtual
 
virtual at edi + 0x26c
PowerState dd ?
end virtual
 
virtual at edi + 0x600
PowerState2 dd ?
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
 
DEBUGF 2,"Loading %s driver\n", my_service
stdcall RegService, my_service, service_proc
ret
 
.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] ; compare with pci and device num in device list (notice the usage of word instead of byte)
jne @f
cmp ah, byte [device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
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], .fail
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
 
DEBUGF 1,"Hooking into device, dev:%x, bus:%x\n", [device.pci_dev], [device.pci_bus]
 
; 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:
 
ret
 
;------------------------------------------------------
endp
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
 
 
;***************************************************************************
; Function
; probe
; Description
; Searches for an ethernet card, enables it and clears the rx buffer
;
;***************************************************************************
align 4
probe:
 
DEBUGF 1,"probe\n"
 
mov [device.needs_mac_reset], 0
 
PCI_make_bus_master
PCI_adjust_latency 32
PCI_find_mmio32
 
DEBUGF 1,"mmio_addr= 0x%x\n", [device.mmio_addr]:8
 
stdcall MapIoMem, [device.mmio_addr], 2048, (PG_SW + PG_NOCACHE)
test eax, eax
jz fail
mov [device.mmio_addr], eax
mov edi, eax
 
DEBUGF 1,"mapped mmio_addr= 0x%x\n", [device.mmio_addr]:8
 
;-------------------------------------
; handle different descriptor versions
mov [device.desc_ver], DESC_VER_1
movzx eax, [device.device_id]
cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_1
je .ver1
cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_2
je .ver1
cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_3
je .ver1
mov [device.desc_ver], DESC_VER_2
.ver1:
 
call read_mac
 
; disable WOL
mov [WakeUpFlags], 0
mov [device.wolenabled], 0
mov [device.txflags], (NV_TX2_LASTPACKET or NV_TX2_VALID)
cmp [device.desc_ver], DESC_VER_1
jne @f
mov [device.txflags], (NV_TX_LASTPACKET or NV_TX_VALID)
@@:
 
; BEGIN of switch (pci->dev_id)
 
cmp [device.device_id], 0x01C3
jne .next_0x0066
; nforce
mov [device.irqmask], 0 ;;;;;;;;;;;;;;;(IRQMASK_WANTED_2 or IRQ_TIMER)
jmp .find_phy
 
.next_0x0066:
cmp [device.device_id], 0x0066
je @f
cmp [device.device_id], 0x00D6
je @f
jmp .next_0x0086
@@:
mov [device.irqmask], 0 ;;;;;;;;;;;;;;;;(IRQMASK_WANTED_2 or IRQ_TIMER)
cmp [device.desc_ver], DESC_VER_1
jne @f
or [device.txflags], NV_TX_LASTPACKET1
jmp .find_phy
@@:
or [device.txflags], NV_TX2_LASTPACKET1
jmp .find_phy
 
.next_0x0086:
cmp [device.device_id], 0x0086
je @f
cmp [device.device_id], 0x008c
je @f
cmp [device.device_id], 0x00e6
je @f
cmp [device.device_id], 0x00df
je @f
cmp [device.device_id], 0x0056
je @f
cmp [device.device_id], 0x0057
je @f
cmp [device.device_id], 0x0037
je @f
cmp [device.device_id], 0x0038
je @f
jmp .find_phy
 
@@:
mov [device.irqmask], 0 ;;;;;;;;;;;;;;;;(IRQMASK_WANTED_2 or IRQ_TIMER)
 
cmp [device.desc_ver], DESC_VER_1
jne @f
or [device.txflags], NV_TX_LASTPACKET1
jmp .find_phy
@@:
or [device.txflags], NV_TX2_LASTPACKET1
jmp .find_phy
 
.next_0x0268:
; cmp word [device_id], 0x0268
; je @f
; cmp word [device_id], 0x0269
; je @f
; cmp word [device_id], 0x0372
; je @f
; cmp word [device_id], 0x0373
; je @f
; jmp .default_switch
;@@:
cmp [device.device_id], 0x0268
jb .undefined
 
; Get device revision
 
stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REVISION_ID
 
; take phy and nic out of low power mode
mov ecx, [PowerState2]
and ecx, not POWERSTATE2_POWERUP_MASK
cmp [device.device_id], PCI_DEVICE_ID_NVIDIA_NVENET_12
jne @f
cmp [device.device_id], PCI_DEVICE_ID_NVIDIA_NVENET_13
jne @f
cmp al, 0xA3
jb @f
or ecx, POWERSTATE2_POWERUP_REV_A3
@@:
mov [PowerState2], ecx
 
; DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ
mov [device.irqmask], 0 ;;;;;;;;;;;;;;;;(IRQMASK_WANTED_2 or IRQ_TIMER)
mov [device.needs_mac_reset], 1
cmp [device.desc_ver], DESC_VER_1
jne @f
or [device.txflags], NV_TX_LASTPACKET1
jmp .find_phy
@@:
cmp [device.desc_ver], DESC_VER_2
jne .undefined
or [device.txflags], NV_TX2_LASTPACKET1
jmp .find_phy
 
.undefined:
DEBUGF 1,"Your card was undefined in this driver.\n"
DEBUGF 1,"Review driver_data in Kolibri driver and send a patch\n"
 
; Find a suitable phy
; Start with address 1 to 31, then do 0, then fail
 
.find_phy:
xor edx, edx
.phy_loop:
inc edx
and edx, 0x1f ; phyaddr = i & 0x1f
mov eax, MII_PHYSID1
mov ecx, MII_READ
call mii_rw ; EDX - addr, EAX - miireg, ECX - value
 
cmp eax, 0xffff
je .try_next
cmp eax, 0
jl .try_next
mov esi, eax
 
mov eax, MII_PHYSID2
mov ecx, MII_READ
call mii_rw
 
cmp eax, 0xffff
je .try_next
cmp eax, 0
jl .try_next
jmp .got_it
 
.try_next:
test edx, edx
jnz .phy_loop
 
; PHY in isolate mode? No phy attached and user wants to test loopback?
; Very odd, but can be correct.
DEBUGF 1,"Could not find a valid PHY.\n"
jmp .no_phy
 
.got_it:
 
and esi, PHYID1_OUI_MASK
shl esi, PHYID1_OUI_SHFT
 
and eax, PHYID2_OUI_MASK
shr eax, PHYID2_OUI_SHFT
 
DEBUGF 1,"Found PHY 0x%x:0x%x at address 0x%x\n", esi:8, eax:8, edx
 
mov [device.phyaddr], edx
or eax, esi
mov [device.phy_oui], eax
 
call phy_init
 
.no_phy:
 
cmp [device.needs_mac_reset], 0
je @f
call mac_reset
@@:
;***************************************************************************
; Function
; reset
; Description
; Place the chip (ie, the ethernet card) into a virgin state
; No inputs
; All registers destroyed
;
;***************************************************************************
reset:
 
DEBUGF 1,"Resetting\n"
 
stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REG_IRQ
movzx eax, al
stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax
jnz @f
DEBUGF 1,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
; erase previous misconfiguration
 
mov edi, [device.mmio_addr]
mov [MulticastAddrA], MCASTADDRA_FORCE
mov [MulticastAddrB], 0
mov [MulticastMaskA], 0
mov [MulticastMaskB], 0
mov [PacketFilterFlags], 0
mov [TransmitterControl], 0
mov [ReceiverControl], 0
mov [AdapterControl], 0
 
; initialize descriptor rings
 
call init_ring
 
mov [LinkSpeed], 0
mov [UnknownTransmitterReg], 0
 
call txrx_reset
mov [UnknownSetupReg6], 0
mov [device.in_shutdown], 0
 
; give hw rings
 
lea eax, [device.rx_ring]
GetRealAddr
mov [RxRingPhysAddr], eax
 
lea eax, [device.tx_ring]
GetRealAddr
mov [TxRingPhysAddr], eax
 
mov [RingSizes], (((RX_RING - 1) shl RINGSZ_RXSHIFT) + ((TX_RING - 1) shl RINGSZ_TXSHIFT))
 
;
 
mov [device.linkspeed], (LINKSPEED_FORCE or LINKSPEED_10)
mov [device.duplex], 0
mov [LinkSpeed], (LINKSPEED_FORCE or LINKSPEED_10)
mov [UnknownSetupReg3], UNKSETUP3_VAL1
 
mov eax, [device.desc_ver]
mov [TxRxControl], eax
call pci_push
or eax, TXRXCTL_BIT1
mov [TxRxControl], eax
 
stdcall reg_delay, UnknownSetupReg5-edi, UNKSETUP5_BIT31, UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, 0
 
mov [UnknownSetupReg4], 0
mov [MIIStatus], MIISTAT_MASK2
 
;
mov [Misc1], (MISC1_FORCE or MISC1_HD)
 
mov eax, [TransmitterStatus]
mov [TransmitterStatus], eax
 
mov [PacketFilterFlags], PFF_ALWAYS
 
mov [OffloadConfig], OFFLOAD_NORMAL
 
mov eax, [ReceiverStatus]
mov [ReceiverStatus], eax
 
; set random seed
push ebx
stdcall GetTimerTicks ; bad idea, driver is started at system startup in 90% of cases..
pop ebx
 
mov edi, [device.mmio_addr]
 
and eax, RNDSEED_MASK
or eax, RNDSEED_FORCE
mov [RandomSeed], eax
 
mov [UnknownSetupReg1], UNKSETUP1_VAL
mov [UnknownSetupReg2], UNKSETUP2_VAL
mov [PollingInterval], POLL_DEFAULT
mov [UnknownSetupReg6], UNKSETUP6_VAL
 
mov eax, [device.phyaddr]
shl eax, ADAPTCTL_PHYSHIFT
or eax, (ADAPTCTL_PHYVALID or ADAPTCTL_RUNNING)
mov [AdapterControl], eax
 
mov [MIISpeed], (MIISPEED_BIT8 or MIIDELAY)
mov [UnknownSetupReg4], UNKSETUP4_VAL
mov [WakeUpFlags], WAKEUPFLAGS_VAL
or [PowerState], POWERSTATE_POWEREDUP
call pci_push
 
mov esi, 10
call Sleep
 
or [PowerState], POWERSTATE_VALID
mov [IrqMask], 0
 
;;; ; ??? Mask RX interrupts
mov [IrqMask], IRQ_RX_ALL + IRQ_TX_ALL
;;; ; ??? Mask TX interrupts
;;; mov [IrqMask], IRQ_TX_ALL
;;; ; ??? Mask OTHER interrupts
;;; mov [IrqMask], IRQ_OTHER_ALL
call pci_push
 
mov [MIIStatus], MIISTAT_MASK2
mov [IrqStatus], IRQSTAT_MASK
call pci_push
 
mov [MulticastAddrA], MCASTADDRA_FORCE
mov [MulticastAddrB], 0
mov [MulticastMaskA], 0
mov [MulticastMaskB], 0
 
mov [PacketFilterFlags], (PFF_ALWAYS or PFF_MYADDR)
 
call set_multicast
; One manual link speed update: Interrupts are enabled, future link
; speed changes cause interrupts and are handled by nv_link_irq().
 
mov eax, [MIIStatus]
mov [MIIStatus], MIISTAT_MASK
DEBUGF 1,"startup: got 0x%x\n", eax
 
call update_linkspeed
 
mov [TransmitterControl], XMITCTL_START ; start TX
call pci_push
 
mov [device.nocable], 0
test eax, eax
jnz .return
DEBUGF 1,"no link during initialization.\n"
mov [device.nocable], 1
 
.return:
xor eax, eax ; Indicate that we have successfully reset the card
mov [device.mtu], 1514 ;;; FIXME
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
ret
 
 
fail:
or eax, -1
 
ret
 
;--------------------------------------------------------
;
; MII_RW
;
; read/write a register on the PHY.
; Caller must guarantee serialization
; Input: EAX - miireg, EDX - addr, ECX - value
; Output: EAX - retval
;
;--------------------------------------------------------
 
mii_rw:
 
DEBUGF 1,"mii_rw: 0x%x to reg %d at PHY %d\n", ecx, eax, edx
 
push edx
 
mov edi, [device.mmio_addr]
mov [MIIStatus], MIISTAT_MASK
 
test [MIIControl], MIICTL_INUSE
jz @f
mov [MIIControl], MIICTL_INUSE
 
mov esi, NV_MIIBUSY_DELAY
call Sleep
@@:
 
shl edx, MIICTL_ADDRSHIFT
or edx, eax
 
cmp ecx, MII_READ
je @f
 
mov [MIIData], ecx
or edx, MIICTL_WRITE
@@:
mov [MIIControl], edx
 
stdcall reg_delay, MIIControl-edi, MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, 0
 
test eax, eax
jz @f
DEBUGF 1,"mii_rw timed out.\n"
or eax, -1
jmp .return
@@:
 
cmp ecx, MII_READ
je @f
; it was a write operation - fewer failures are detectable
DEBUGF 1,"mii_rw write: ok\n"
xor eax, eax
jmp .return
@@:
 
mov eax, [MIIStatus]
test eax, MIISTAT_ERROR
jz @f
DEBUGF 1,"mii read: failed.\n"
or eax, -1
jmp .return
@@:
 
mov eax, [MIIData]
DEBUGF 1,"mii read: 0x%x.\n", eax
 
.return:
pop edx
ret
 
 
 
 
 
; Input: offset:word, mask:dword, target:dword, delay:word, delaymax:word, msg:dword
; Output: EAX - 0|1
 
proc reg_delay, offset:dword, mask:dword, target:dword, delay:dword, delaymax:dword, msg:dword
 
; DEBUGF 1,"reg_delay\n"
 
push esi
call pci_push
 
.loop:
mov esi, [delay]
call Sleep
mov eax, [delaymax]
sub eax, [delay]
mov [delaymax], eax
 
cmp eax, 0
jl .fail
 
mov eax, [offset]
mov eax, [edi + eax]
and eax, [mask]
cmp eax, [target]
jne .loop
 
pop esi
xor eax, eax
ret
 
.fail:
pop esi
xor eax, eax
inc eax
ret
 
endp
 
 
 
 
 
; Input: none
; Output: EAX - result (0 = OK, other = error)
phy_init:
 
push ebx ecx
; set advertise register
mov edx, [device.phyaddr]
mov eax, MII_ADVERTISE
mov ecx, MII_READ
call mii_rw
 
or eax, (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or 0x800 or 0x400)
 
mov ecx, eax
mov eax, MII_ADVERTISE
call mii_rw
 
test eax, eax
jz @f
 
DEBUGF 1,"phy write to advertise failed.\n"
 
mov eax, PHY_ERROR
jmp .return
@@:
 
; get phy interface type
mov edi, [device.mmio_addr]
mov eax, [PhyInterface]
DEBUGF 1,"phy interface type = 0x%x\n", eax:8
 
; see if gigabit phy
mov eax, MII_BMSR
mov ecx, MII_READ
call mii_rw
test eax, PHY_GIGABIT
jnz .gigabit
mov [device.gigabit], 0
jmp .next_if
 
.gigabit:
mov [device.gigabit], PHY_GIGABIT
 
mov eax, MII_1000BT_CR
mov ecx, MII_READ
call mii_rw
and eax, (not ADVERTISE_1000HALF)
 
test [PhyInterface], PHY_RGMII
jz @f
or eax, ADVERTISE_1000FULL
jmp .next
@@:
 
and eax, (not ADVERTISE_1000FULL)
 
.next:
mov ecx, eax
mov eax, MII_1000BT_CR
call mii_rw
 
test eax, eax
jz .next_if
 
DEBUGF 1,"phy init failed.\n"
 
mov eax, PHY_ERROR
jmp .return
 
.next_if:
 
call phy_reset
test eax, eax
jz @f
 
DEBUGF 1,"phy reset failed.\n"
 
mov eax, PHY_ERROR
jmp .return
@@:
 
; phy vendor specific configuration
cmp [device.phy_oui], PHY_OUI_CICADA
jne .next_if2
test [PhyInterface], PHY_RGMII
jz .next_if2
 
mov eax, MII_RESV1
mov ecx, MII_READ
call mii_rw
 
and eax, (not (PHY_INIT1 or PHY_INIT2))
or eax, (PHY_INIT3 or PHY_INIT4)
mov ecx, eax
mov eax, MII_RESV1
call mii_rw
 
test eax, eax
jz @f
 
DEBUGF 1,"phy init failed.\n"
 
mov eax, PHY_ERROR
jmp .return
@@:
 
mov eax, MII_NCONFIG
mov ecx, MII_READ
call mii_rw
 
or eax, PHY_INIT5
mov ecx, eax
mov eax, MII_NCONFIG
call mii_rw
test eax, eax
jz .next_if2
 
DEBUGF 1,"phy init failed.\n"
 
mov eax, PHY_ERROR
jmp .return
 
 
 
.next_if2:
 
cmp [device.phy_oui], PHY_OUI_CICADA
jne .restart
mov eax, MII_SREVISION
mov ecx, MII_READ
call mii_rw
or eax, PHY_INIT6
mov ecx, eax
mov eax, MII_SREVISION
call mii_rw
test eax, eax
jz .restart
 
DEBUGF 1,"phy init failed.\n"
 
jmp .return
 
.restart:
; restart auto negotiation
 
mov eax, MII_BMCR
mov ecx, MII_READ
call mii_rw
 
or eax, (BMCR_ANRESTART or BMCR_ANENABLE)
mov ecx, eax
mov eax, MII_BMCR
call mii_rw
test eax, eax
jz .ok
 
mov eax, PHY_ERROR
jmp .return
 
.ok:
xor eax, eax
.return:
pop ecx ebx
 
ret
 
 
; Input: none
; Output: EAX - result (0 = OK, other = error)
phy_reset:
 
DEBUGF 1,"phy_reset\n"
 
push ebx ecx edx
 
mov edx, [device.phyaddr]
mov eax, MII_BMCR
mov ecx, MII_READ
call mii_rw
 
or eax, BMCR_RESET
push eax
mov ecx, eax
mov eax, MII_BMCR
call mii_rw
 
test eax, eax
jz @f
 
pop eax
mov eax, 0xffffffff
jmp .return
@@:
 
pop eax
 
mov esi, 500
call Sleep
 
; must wait till reset is deasserted
mov esi, 100 ; FIXME: 100 tries seem excessive
.while_loop:
test eax, BMCR_RESET
jz .while_loop_exit
 
push esi
mov esi, 10
call Sleep
pop esi
 
mov eax, MII_BMCR
mov ecx, MII_READ
call mii_rw
 
dec esi
jnz .while_loop
 
mov eax, 0xffffffff
jmp .return
 
.while_loop_exit:
xor eax, eax
.return:
pop edx ecx ebx
 
ret
 
 
align 4
pci_push:
 
push eax
mov eax, [edi]
pop eax
 
ret
 
 
 
 
align 4
mac_reset:
 
push esi edi
 
DEBUGF 1,"mac_reset.\n"
 
mov edi, [device.mmio_addr]
mov eax, [device.desc_ver]
or eax, (TXRXCTL_BIT2 or TXRXCTL_RESET)
mov [TxRxControl], eax
call pci_push
 
mov [MacReset], MAC_RESET_ASSERT
call pci_push
 
mov esi, NV_MAC_RESET_DELAY
call Sleep
 
mov [MacReset], 0
call pci_push
 
mov esi, NV_MAC_RESET_DELAY
call Sleep
 
mov eax, [device.desc_ver]
or eax, TXRXCTL_BIT2
mov [TxRxControl], eax
call pci_push
 
pop edi esi
 
ret
 
 
 
 
 
align 4
init_ring:
 
DEBUGF 1,"init rings\n"
push eax esi ecx
 
mov [device.next_tx], 0
 
mov ecx, TX_RING
lea esi, [device.tx_ring]
.tx_loop:
mov [esi + TxDesc.FlagLen], 0
add esi, sizeof.TxDesc
dec ecx
jnz .tx_loop
 
mov [device.cur_rx], 0
 
mov ecx, RX_RING
lea esi, [device.rx_ring]
.rx_loop:
push ecx esi
stdcall KernelAlloc, 4096 shl RBLEN ; push/pop esi not needed, but just in case...
pop esi
mov [esi + RX_RING*sizeof.RxDesc], eax
GetRealAddr
mov [esi + RxDesc.PacketBuffer], eax
mov [esi + RxDesc.FlagLen], (4096 shl RBLEN or NV_RX_AVAIL)
add esi, sizeof.RxDesc
pop ecx
dec ecx
jnz .rx_loop
pop ecx esi eax
 
ret
 
 
 
 
 
; Input: none
; Output: none
align 4
txrx_reset:
 
push eax esi
 
DEBUGF 1,"txrx_reset\n"
 
mov edi, [device.mmio_addr]
mov eax, [device.desc_ver]
or eax, (TXRXCTL_BIT2 or TXRXCTL_RESET)
mov [TxRxControl], eax
call pci_push
 
mov esi, NV_TXRX_RESET_DELAY
call Sleep
 
mov eax, [device.desc_ver]
or eax, TXRXCTL_BIT2
mov [TxRxControl], eax
call pci_push
 
pop esi eax
 
ret
 
 
 
 
 
; Input: none
; Output: none
set_multicast:
 
; u32 addr[2];
; u32 mask[2];
; u32 pff;
; u32 alwaysOff[2];
; u32 alwaysOn[2];
;
; memset(addr, 0, sizeof(addr));
; memset(mask, 0, sizeof(mask));
;
; pff = PFF_MYADDR;
;
; alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0;
;
; addr[0] = alwaysOn[0];
; addr[1] = alwaysOn[1];
; mask[0] = alwaysOn[0] | alwaysOff[0];
; mask[1] = alwaysOn[1] | alwaysOff[1];
;
; addr[0] |= MCASTADDRA_FORCE;
; pff |= PFF_ALWAYS;
 
call stop_rx
 
mov edi, [device.mmio_addr]
mov [MulticastAddrA], MCASTADDRA_FORCE
 
mov [MulticastAddrB], 0
mov [MulticastMaskA], 0
mov [MulticastMaskB], 0
mov [PacketFilterFlags], (PFF_MYADDR or PFF_ALWAYS)
 
call start_rx
 
ret
 
 
 
 
 
; Input: none
; Output: none
start_rx:
 
push edi
 
DEBUGF 1,"start_rx\n"
 
; Already running? Stop it.
mov edi, [device.mmio_addr]
mov eax, [ReceiverControl]
test eax, RCVCTL_START
jz @f
mov [ReceiverControl], 0
call pci_push
@@:
 
mov eax, [device.linkspeed]
mov [LinkSpeed], eax
call pci_push
 
mov [ReceiverControl], RCVCTL_START
call pci_push
 
pop edi
 
ret
 
 
 
 
; Input: none
; Output: none
stop_rx:
 
push esi edi
 
DEBUGF 1,"stop_rx.\n"
 
mov edi, [device.mmio_addr]
mov [ReceiverControl], 0
 
push ebx edx edi
stdcall reg_delay, ReceiverStatus-edi, RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, 0
pop edi edx ebx
 
mov esi, NV_RXSTOP_DELAY2
call Sleep
 
mov [LinkSpeed], 0
 
pop edi esi
 
ret
 
 
 
 
; Input: none
; Output: EAX
update_linkspeed:
 
DEBUGF 1,"update linkspeed\n"
 
; BMSR_LSTATUS is latched, read it twice: we want the current value.
mov edx, [device.phyaddr]
mov eax, MII_BMSR
mov ecx, MII_READ
call mii_rw
 
mov eax, MII_BMSR
mov ecx, MII_READ
call mii_rw
test eax, BMSR_LSTATUS ; Link up?
jz .10mbit_hd
 
test eax, BMSR_ANEGCOMPLETE ; still in autonegotiation?
jz .10mbit_hd
 
cmp [device.gigabit], PHY_GIGABIT
jne .no_gigabit
 
;mov edx, [device.phyaddr]
mov eax, MII_1000BT_CR
mov ecx, MII_READ
call mii_rw
push eax
 
;mov edx, [device.phyaddr]
mov eax, MII_1000BT_SR
mov ecx, MII_READ
call mii_rw
pop ecx
 
test eax, LPA_1000FULL
jz .no_gigabit
test ecx, ADVERTISE_1000FULL
jz .no_gigabit
 
DEBUGF 1,"update_linkspeed: GBit ethernet detected.\n"
mov ecx, (LINKSPEED_FORCE or LINKSPEED_1000)
xor eax, eax
inc eax
jmp set_speed
.no_gigabit:
 
;mov edx, [device.phyaddr]
mov eax, MII_ADVERTISE
mov ecx, MII_READ
call mii_rw ; adv = eax
push eax
 
;mov edx, [device.phyaddr]
mov eax, MII_LPA
mov ecx, MII_READ
call mii_rw ; lpa = eax
pop ecx
 
DEBUGF 1,"PHY advertises 0x%x, lpa 0x%x\n", ecx, eax
and eax, ecx ; FIXME: handle parallel detection properly, handle gigabit ethernet
 
test eax, LPA_100FULL
jz @f
DEBUGF 1,"update_linkspeed: 100 mbit full duplex\n"
mov ecx, (LINKSPEED_FORCE or LINKSPEED_100)
xor eax, eax
inc eax
jmp set_speed
@@:
 
test eax, LPA_100HALF
jz @f
DEBUGF 1,"update_linkspeed: 100 mbit half duplex\n"
mov ecx, (LINKSPEED_FORCE or LINKSPEED_100)
xor eax, eax
jmp set_speed
@@:
 
test eax, LPA_10FULL
jz @f
DEBUGF 1,"update_linkspeed: 10 mbit full duplex\n"
mov ecx, (LINKSPEED_FORCE or LINKSPEED_10)
xor eax, eax
inc eax
jmp set_speed
@@:
 
.10mbit_hd:
DEBUGF 1,"update_linkspeed: 10 mbit half duplex\n"
mov ecx, (LINKSPEED_FORCE or LINKSPEED_10)
xor eax, eax
jmp set_speed
 
 
align 4
set_speed:
 
cmp eax, [device.duplex]
jne .update
cmp ecx, [device.linkspeed]
jne .update
 
ret
 
.update:
DEBUGF 1,"update_linkspeed: changing link to 0x%x/XD.\n", ecx
mov [device.duplex], eax
mov [device.linkspeed], ecx
cmp [device.gigabit], PHY_GIGABIT
jne .no_gigabit
 
mov edi, [device.mmio_addr]
mov eax, [RandomSeed]
 
and eax, not (0x3FF00)
mov ecx, eax ; phyreg = ecx
 
mov eax, [device.linkspeed]
and eax, 0xFFF
cmp eax, LINKSPEED_10
jne @f
or ecx, RNDSEED_FORCE3
jmp .end_if4
@@:
 
cmp eax, LINKSPEED_100
jne @f
or ecx, RNDSEED_FORCE2
jmp .end_if4
@@:
 
cmp eax, LINKSPEED_1000
jne .end_if4
or ecx, RNDSEED_FORCE
.end_if4:
mov [RandomSeed], ecx
.no_gigabit:
 
mov ecx, [PhyInterface]
and ecx, not (PHY_HALF or PHY_100 or PHY_1000)
 
cmp [device.duplex], 0
jne @f
or ecx, PHY_HALF
@@:
 
mov eax, [device.linkspeed]
and eax, 0xFFF
cmp eax, LINKSPEED_100
jne @f
or ecx, PHY_100
jmp .end_if5
@@:
 
cmp eax, LINKSPEED_1000
jne .end_if5
or ecx, PHY_1000
 
.end_if5:
mov [PhyInterface], ecx
cmp [device.duplex], 0
je @f
xor ecx, ecx
jmp .next
@@:
 
mov ecx, MISC1_HD
.next:
or ecx, MISC1_FORCE
mov [Misc1], ecx
 
call pci_push
 
mov eax, [device.linkspeed]
mov [LinkSpeed], eax
 
call pci_push
 
ret
 
 
 
 
 
 
align 4
read_mac:
 
mov edi, [device.mmio_addr]
 
mov eax, [MacAddrA]
mov ecx, [MacAddrB]
 
mov dword [device.mac], eax
mov word [device.mac + 4], cx
 
cmp [device.device_id], 0x03E5
jae @f
bswap eax
xchg cl, ch
mov dword [device.mac + 2], eax
mov word [device.mac], cx
@@:
 
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
 
; get the descriptor address
mov eax, [device.next_tx]
mov cl, sizeof.TxDesc
mul cl
lea esi, [device.tx_ring + eax]
mov eax, [esp + 4]
mov [esi + TX_RING*sizeof.TxDesc], eax
GetRealAddr
mov [esi + TxDesc.PacketBuffer], eax
 
mov ecx, [esp + 8]
or ecx, [device.txflags]
mov [esi + TxDesc.FlagLen], eax
 
mov edi, [device.mmio_addr]
mov eax, [device.desc_ver]
or eax, TXRXCTL_KICK
mov [TxRxControl], eax
 
call pci_push
 
inc [device.next_tx]
and [device.next_tx], (TX_RING-1)
 
; Update stats
inc [device.packets_tx]
mov eax, [esp + 8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
xor eax, eax
ret 8
 
.fail:
xor eax, eax
inc eax
ret 8
 
 
 
 
 
 
; Interrupt handler
align 4
int_handler:
 
push ebx esi edi
 
DEBUGF 2,"\n%s INT\n", my_service
 
;-------------------------------------------
; Find pointer of device wich made IRQ occur
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .fail
.nextdevice:
mov ebx, dword [esi]
add esi, 4
 
mov edi, [device.mmio_addr]
mov eax, [IrqStatus]
test eax, eax
jnz .got_it
dec ecx
jnz .nextdevice
.nothing:
pop edi esi ebx
xor eax, eax
 
ret
 
.got_it:
mov [IrqStatus], eax
DEBUGF 2,"IrqStatus = %x\n", eax
 
test eax, IRQ_RX
jz .no_rx
 
.top:
mov eax, [device.cur_rx]
mov cx, sizeof.RxDesc
mul cx
lea esi, [device.rx_ring + eax]
mov eax, [esi + RxDesc.FlagLen]
 
test eax, NV_RX_AVAIL ; still owned by hardware
jnz .return0
 
cmp [device.desc_ver], DESC_VER_1
jne @f
test eax, NV_RX_DESCRIPTORVALID
jz .return0
jmp .next
@@:
test eax, NV_RX2_DESCRIPTORVALID
jz .return0
 
.next:
 
cmp dword [device.desc_ver], DESC_VER_1
jne @f
and eax, LEN_MASK_V1
jmp .next2
@@:
and eax, LEN_MASK_V2
.next2:
 
; got a valid packet - forward it to the network core
push .top
push eax
push dword [esi + RX_RING*sizeof.RxDesc]
 
inc [device.cur_rx]
and [device.cur_rx], (RX_RING-1)
 
; Allocate new buffer
 
stdcall KernelAlloc, 4096 shl RBLEN
mov [esi + RX_RING*sizeof.RxDesc], eax
GetRealAddr
mov [esi + RxDesc.PacketBuffer], eax
mov [esi + RxDesc.FlagLen], (4096 shl RBLEN or NV_RX_AVAIL)
 
jmp Eth_input
 
.return0:
 
 
.no_rx:
test eax, IRQ_RX_ERROR
jz .no_rx_err
 
push eax
DEBUGF 2,"RX error!\n"
 
mov eax, [device.cur_rx]
mov cx, sizeof.RxDesc
mul cx
lea esi, [device.rx_ring + eax]
mov eax, [esi + RxDesc.FlagLen]
 
DEBUGF 2,"Flaglen=%x\n", eax
 
; TODO: allocate new buff
pop eax
 
.no_rx_err:
test eax, IRQ_LINK
jz .no_link
 
push eax
call update_linkspeed
pop eax
 
.no_link:
.fail:
 
pop edi esi ebx
xor eax, eax
inc eax
 
ret
 
 
 
 
; End of code
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
align 4 ; Place all initialised data here
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'FORCEDETH',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
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/ethernet/i8254x.asm
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
 
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/ethernet/i8255x.asm
0,0 → 1,1255
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; i8255x (Intel eepro 100) driver for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; Some parts of this driver are based on the code of eepro100.c ;;
;; from linux. ;;
;; ;;
;; Intel's programming manual for i8255x: ;;
;; http://www.intel.com/design/network/manuals/8255x_opensdm.htm ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; TODO: use separate descriptors in memory instead of placing them in front of packets!
 
 
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
 
.io_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
 
.rx_desc dd ?
 
.ee_bus_width db ?
 
rb 0x100 - (($ - device) and 0xff)
 
txfd:
.status dw ?
.command dw ?
.link dd ?
.tx_desc_addr dd ?
.count dd ?
 
.tx_buf_addr0 dd ?
.tx_buf_size0 dd ?
 
rb 0x100 - (($ - device) and 0xff)
 
confcmd:
.status dw ?
.command dw ?
.link dd ?
.data rb 64
 
rb 0x100 - (($ - device) and 0xff)
 
lstats:
tx_good_frames dd ?
tx_coll16_errs dd ?
tx_late_colls dd ?
tx_underruns dd ?
tx_lost_carrier dd ?
tx_deferred dd ?
tx_one_colls dd ?
tx_multi_colls dd ?
tx_total_colls dd ?
 
rx_good_frames dd ?
rx_crc_errs dd ?
rx_align_errs dd ?
rx_resource_errs dd ?
rx_overrun_errs dd ?
rx_colls_errs dd ?
rx_runt_errs dd ?
 
last_tx_buffer dd ? ;;; fixme
 
sizeof.device_struct = $ - device
 
end virtual
 
 
virtual at 0
 
rxfd:
.status dw ?
.command dw ?
.link dd ?
.rx_buf_addr dd ?
.count dw ?
.size dw ?
.packet:
 
end virtual
 
 
; Serial EEPROM
 
EE_SK = 1 shl 0 ; serial clock
EE_CS = 1 shl 1 ; chip select
EE_DI = 1 shl 2 ; data in
EE_DO = 1 shl 3 ; data out
EE_MASK = EE_SK + EE_CS + EE_DI + EE_DO
 
; opcodes, first bit is start bit and must be 1
EE_READ = 110b
EE_WRITE = 101b
EE_ERASE = 111b
 
; The SCB accepts the following controls for the Tx and Rx units:
 
CU_START = 0x0010
CU_RESUME = 0x0020
CU_STATSADDR = 0x0040
CU_SHOWSTATS = 0x0050 ; Dump statistics counters.
CU_CMD_BASE = 0x0060 ; Base address to add CU commands.
CU_DUMPSTATS = 0x0070 ; Dump then reset stats counters.
 
RX_START = 0x0001
RX_RESUME = 0x0002
RX_ABORT = 0x0004
RX_ADDR_LOAD = 0x0006
RX_RESUMENR = 0x0007
INT_MASK = 0x0100
DRVR_INT = 0x0200 ; Driver generated interrupt
 
CmdIASetup = 0x0001
CmdConfigure = 0x0002
CmdTx = 0x0004
CmdTxFlex = 0x0008
Cmdsuspend = 0x4000
 
 
reg_scb_status = 0
reg_scb_cmd = 2
reg_scb_ptr = 4
reg_port = 8
reg_eeprom = 14
reg_mdi_ctrl = 16
 
 
macro delay {
push eax
in ax, dx
in ax, dx
in ax, dx
in ax, dx
in ax, dx
in ax, dx
in ax, dx
in ax, dx
in ax, dx
in ax, dx
pop eax
}
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
 
.entry:
 
DEBUGF 1,"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 @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
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 io addres of the PCI device
 
PCI_find_io
 
; We've found the io address, find IRQ now
 
PCI_find_irq
 
DEBUGF 2,"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.io_addr]:4
 
; Ok, the eth_device structure is ready, let's probe the device
 
pushf
cli ; disable ints until initialisation is done
 
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] ;
 
popf
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
cmp eax, -1
je .err
 
ret
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 2,"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 2,"Kernel says: %u\n", eax
ret
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.err:
stdcall KernelFree, ebx
 
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
 
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
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
;
;-------------
 
align 4
probe:
 
DEBUGF 1,"Probing i8255x\n"
 
PCI_make_bus_master
 
;---------------------------
; First, identify the device
 
stdcall PciRead32, [device.pci_bus], [device.pci_dev], PCI_VENDOR_ID ; get device/vendor id
 
DEBUGF 1,"Vendor_id=0x%x\n", ax
 
cmp ax, 0x8086
jne .notfound
shr eax, 16
 
DEBUGF 1,"Device_id=0x%x\n", ax
 
mov ecx, DEVICE_IDs
mov edi, device_id_list
repne scasw
jne .notfound
jmp .found
 
.notfound:
DEBUGF 1,"ERROR: Unsupported device!\n"
or eax, -1
ret
 
.found:
 
call ee_get_width
call MAC_read_eeprom
 
;;; TODO: detect phy
 
 
 
;----------
;
; Reset
;
;----------
 
align 4
reset:
 
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
@@:
 
DEBUGF 1,"Resetting %s\n", my_service
 
;---------------
; reset the card
 
set_io 0
set_io reg_port
xor eax, eax ; Software Reset
out dx, eax
 
mov esi, 10
call Sleep ; Give the card time to warm up.
 
;---------------------------------
; Tell device where to store stats
 
lea eax, [lstats]
GetRealAddr
set_io 0
set_io reg_scb_ptr
out dx, eax
 
mov ax, INT_MASK + CU_STATSADDR
set_io reg_scb_cmd
out dx, ax
call cmd_wait
 
;-----------------
; setup RX
 
set_io reg_scb_ptr
xor eax, eax
out dx, eax
 
set_io reg_scb_cmd
mov ax, INT_MASK + RX_ADDR_LOAD
out dx, ax
call cmd_wait
 
;-----------------------------
; Create RX and TX descriptors
 
call create_ring
 
; RX start
 
set_io 0
set_io reg_scb_ptr
mov eax, [device.rx_desc]
GetRealAddr
out dx, eax
 
mov ax, INT_MASK + RX_START
set_io reg_scb_cmd
out dx, ax
call cmd_wait
 
; Set-up TX
 
set_io reg_scb_ptr
xor eax, eax
out dx, eax
 
set_io reg_scb_cmd
mov ax, INT_MASK + CU_CMD_BASE
out dx, ax
call cmd_wait
 
; --------------------
 
mov [confcmd.command], CmdConfigure + Cmdsuspend
mov [confcmd.status], 0
lea eax, [txfd]
GetRealAddr
mov [confcmd.link], eax
 
mov esi, confcmd_data
lea edi, [confcmd.data]
mov ecx, 22
rep movsb
 
mov byte[confcmd.data + 1], 0x88 ; fifo of 8 each
mov byte[confcmd.data + 4], 0
mov byte[confcmd.data + 5], 0x80
mov byte[confcmd.data + 15], 0x48
mov byte[confcmd.data + 19], 0x80
mov byte[confcmd.data + 21], 0x05
 
mov [txfd.command], CmdIASetup
mov [txfd.status], 0
lea eax, [confcmd]
GetRealAddr
mov [txfd.link], eax
 
;;; copy in our MAC
 
lea edi, [txfd.tx_desc_addr]
lea esi, [device.mac]
movsd
movsw
 
set_io reg_scb_ptr
lea eax, [txfd]
GetRealAddr
out dx, eax
 
; Start CU & enable ints
 
set_io reg_scb_cmd
mov ax, CU_START
out dx, ax
call cmd_wait
 
;-----------------------
; build txfd structure (again!)
 
lea eax, [txfd]
GetRealAddr
mov [txfd.link], eax
mov [txfd.count], 0x02208000
lea eax, [txfd.tx_buf_addr0]
GetRealAddr
mov [txfd.tx_desc_addr], eax
 
; Indicate that we have successfully reset the card
 
DEBUGF 1,"Resetting %s complete\n", my_service
 
mov [device.mtu], 1514
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
xor eax, eax ; indicate that we have successfully reset the card
ret
 
 
align 4
create_ring:
 
DEBUGF 1,"Creating ring\n"
 
;---------------------
; build rxfd structure
 
stdcall KernelAlloc, 2000
mov [device.rx_desc], eax
mov esi, eax
GetRealAddr
mov [esi + rxfd.status], 0x0000
mov [esi + rxfd.command], 0x0000
mov [esi + rxfd.link], eax
mov [esi + rxfd.count], 0
mov [esi + rxfd.size], 1528
 
;-----------------------
; build txfd structure
 
lea eax, [txfd]
GetRealAddr
mov [txfd.link], eax
mov [txfd.count], 0x02208000
lea eax, [txfd.tx_buf_addr0]
GetRealAddr
mov [txfd.tx_desc_addr], eax
 
ret
 
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
transmit:
 
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
DEBUGF 1,"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 .error ; packet is too long
cmp dword [esp+8], 60
jb .error ; packet is too short
 
;;; TODO: check if current descriptor is in use
; fill in buffer address and size
mov eax, [esp+4]
mov [last_tx_buffer], eax ;;; FIXME
GetRealAddr
mov [txfd.tx_buf_addr0], eax
mov eax, [esp+8]
mov [txfd.tx_buf_size0], eax
 
mov [txfd.status], 0
mov [txfd.command], Cmdsuspend + CmdTx + CmdTxFlex + 1 shl 15 ;;; EL bit
 
; mov [txfd.count], 0x02208000 ;;;;;;;;;;;
 
; Inform device of the new/updated transmit descriptor
lea eax, [txfd]
GetRealAddr
set_io 0
set_io reg_scb_ptr
out dx, eax
 
; Start the transmit
mov ax, CU_START
set_io reg_scb_cmd
out dx, ax
call cmd_wait
 
; set_io 0 ;; why?
; in ax, dx ;;
;
; @@:
; cmp [txfd.status], 0 ; wait for completion? dont seems a good idea to me..
; je @r
;
; set_io 0 ;; why?
; in ax, dx ;;
 
; Update stats
inc [device.packets_tx]
mov eax, [esp + 8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
DEBUGF 1,"Transmit OK\n"
 
xor eax, eax
ret 8
 
.error:
stdcall KernelFree, [esp+4]
or eax, -1
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]
 
; set_io 0 ; reg_scb_status = 0
set_io reg_scb_status
in ax, dx
out dx, ax ; send it back to ACK
test ax, ax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
pop edi esi ebx
xor eax, eax
 
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x\n", ebx, ax
 
test ax, 1 shl 14 ; did we receive a frame?
jz .no_rx
 
push ax
 
DEBUGF 1,"Receiving\n"
 
push ebx
.rx_loop:
pop ebx
 
mov esi, [device.rx_desc]
cmp [esi + rxfd.status], 0 ; we could also check bits C and OK (bit 15 and 13)
je .nodata
 
DEBUGF 1,"rxfd status=0x%x\n", [esi + rxfd.status]:4
 
movzx ecx, [esi + rxfd.count]
and ecx, 0x3fff
 
push ebx
push .rx_loop
push ecx
add esi, rxfd.packet
push esi
 
; 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, 2000
mov [device.rx_desc], eax
mov esi, eax
GetRealAddr
mov [esi + rxfd.status], 0x0000
mov [esi + rxfd.command], 0xc000 ; End of list + Suspend
mov [esi + rxfd.link], eax
mov [esi + rxfd.count], 0
mov [esi + rxfd.size], 1528
 
; restart RX
 
set_io 0
set_io reg_scb_ptr
; lea eax, [device.rx_desc]
; GetRealAddr
out dx, eax
 
set_io reg_scb_cmd
mov ax, RX_START
out dx, ax
call cmd_wait
 
; And give packet to kernel
 
jmp Eth_input
 
.nodata:
DEBUGF 1, "no more data\n"
pop ax
 
.no_rx:
 
; Cleanup after TX
cmp [txfd.status], 0
je .done
cmp [last_tx_buffer], 0
je .done
push ax
DEBUGF 1, "Removing packet 0x%x from RAM!\n", [last_tx_buffer]
stdcall KernelFree, [last_tx_buffer]
mov [last_tx_buffer], 0
pop ax
 
.done:
and ax, 00111100b
cmp ax, 00001000b
jne .fail
 
DEBUGF 1, "out of resources!\n"
; Restart the RX
 
; allocate new descriptor
 
stdcall KernelAlloc, 2000
mov [device.rx_desc], eax
mov esi, eax
GetRealAddr
mov [esi + rxfd.status], 0x0000
mov [esi + rxfd.command], 0xc000 ; End of list + Suspend
mov [esi + rxfd.link], eax
mov [esi + rxfd.count], 0
mov [esi + rxfd.size], 1528
 
; restart RX
 
set_io 0
set_io reg_scb_ptr
; lea eax, [device.rx_desc]
; GetRealAddr
out dx, eax
 
set_io reg_scb_cmd
mov ax, RX_START
out dx, ax
call cmd_wait
 
.fail:
pop edi esi ebx
xor eax, eax
inc eax
 
ret
 
 
 
 
align 4
cmd_wait:
 
in al, dx
test al, al
jnz cmd_wait
 
ret
 
 
 
 
 
 
align 4
ee_read: ; esi = address to read
 
DEBUGF 1,"Eeprom read from 0x%x", esi
 
set_io 0
set_io reg_eeprom
 
;-----------------------------------------------------
; Prepend start bit + read opcode to the address field
; and shift it to the very left bits of esi
 
mov cl, 29
sub cl, [device.ee_bus_width]
shl esi, cl
or esi, EE_READ shl 29
 
movzx ecx, [device.ee_bus_width]
add ecx, 3
 
mov al, EE_CS
out dx, al
delay
 
;-----------------------
; Write this to the chip
 
.loop:
mov al, EE_CS + EE_SK
shl esi, 1
jnc @f
or al, EE_DI
@@:
out dx, al
delay
 
and al, not EE_SK
out dx, al
delay
 
loop .loop
 
;------------------------------
; Now read the data from eeprom
 
xor esi, esi
mov ecx, 16
 
.loop2:
shl esi, 1
mov al, EE_CS + EE_SK
out dx, al
delay
 
in al, dx
test al, EE_DO
jz @f
inc esi
@@:
 
mov al, EE_CS
out dx, al
delay
 
loop .loop2
 
;-----------------------
; de-activate the eeprom
 
xor ax, ax
out dx, ax
 
 
DEBUGF 1,"=0x%x\n", esi:4
ret
 
 
 
align 4
ee_write: ; esi = address to write to, di = data
 
DEBUGF 1,"Eeprom write 0x%x to 0x%x\n", di, esi
 
set_io 0
set_io reg_eeprom
 
;-----------------------------------------------------
; Prepend start bit + write opcode to the address field
; and shift it to the very left bits of esi
 
mov cl, 29
sub cl, [device.ee_bus_width]
shl esi, cl
or esi, EE_WRITE shl 29
 
movzx ecx, [device.ee_bus_width]
add ecx, 3
 
mov al, EE_CS ; enable chip
out dx, al
 
;-----------------------
; Write this to the chip
 
.loop:
mov al, EE_CS + EE_SK
shl esi, 1
jnc @f
or al, EE_DI
@@:
out dx, al
delay
 
and al, not EE_SK
out dx, al
delay
 
loop .loop
 
;-----------------------------
; Now write the data to eeprom
 
mov ecx, 16
 
.loop2:
mov al, EE_CS + EE_SK
shl di, 1
jnc @f
or al, EE_DI
@@:
out dx, al
delay
 
and al, not EE_SK
out dx, al
delay
 
loop .loop2
 
;-----------------------
; de-activate the eeprom
 
xor al, al
out dx, al
 
 
ret
 
 
 
align 4
ee_get_width:
 
; DEBUGF 1,"Eeprom get width\n"
 
set_io 0
set_io reg_eeprom
 
mov al, EE_CS ; activate eeprom
out dx, al
delay
 
mov si, EE_READ shl 13
xor ecx, ecx
.loop:
mov al, EE_CS + EE_SK
shl si, 1
jnc @f
or al, EE_DI
@@:
out dx, al
delay
 
and al, not EE_SK
out dx, al
delay
 
inc ecx
 
cmp ecx, 15
jae .give_up
 
in al, dx
test al, EE_DO
jnz .loop
 
.give_up:
xor al, al
out dx, al ; de-activate eeprom
 
sub cl, 3 ; dont count the opcode bits
 
mov [device.ee_bus_width], cl
DEBUGF 1,"Eeprom width=%u bit\n", ecx
 
 
;-----------------------
; de-activate the eeprom
 
xor eax, eax
out dx, eax
 
ret
 
 
 
; cx = phy addr
; dx = phy reg addr
 
; ax = data
 
align 4
mdio_read:
 
DEBUGF 1,"MDIO read\n"
 
shl ecx, 21 ; PHY addr
shl edx, 16 ; PHY reg addr
 
mov eax, ecx
or eax, edx
or eax, 10b shl 26 ; read opcode
 
set_io 0
set_io reg_mdi_ctrl
out dx, eax
 
.wait:
delay
in eax, dx
test eax, 1 shl 28 ; ready bit
jz .wait
 
ret
 
; ax = data
; cx = phy addr
; dx = phy reg addr
 
; ax = data
 
align 4
mdio_write:
 
DEBUGF 1,"MDIO write\n"
 
and eax, 0xffff
 
shl ecx, 21 ; PHY addr
shl edx, 16 ; PHY reg addr
 
or eax, ecx
or eax, edx
or eax, 01b shl 26 ; write opcode
 
set_io 0
set_io reg_mdi_ctrl
out dx, eax
 
.wait:
delay
in eax, dx
test eax, 1 shl 28 ; ready bit
jz .wait
 
ret
 
read_mac:
 
ret
 
 
 
align 4
MAC_read_eeprom:
 
mov esi, 0
call ee_read
mov word[device.mac], si
 
mov esi, 1
call ee_read
mov word[device.mac+2], si
 
mov esi, 2
call ee_read
mov word[device.mac+4], si
 
 
ret
 
 
align 4
MAC_write:
 
;;;;
 
ret
 
 
 
 
; End of code
 
align 4 ; Place all initialised data here
 
devices dd 0 ; number of currently running devices
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'i8255x', 0 ; max 16 chars include zero
devicename db 'Intel Etherexpress pro/100', 0
 
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 ; 22 bytes total
 
 
device_id_list:
 
dw 0x1029
dw 0x1030
dw 0x1031
dw 0x1032
dw 0x1033
dw 0x1034
dw 0x1038
dw 0x1039
dw 0x103A
dw 0x103B
dw 0x103C
dw 0x103D
dw 0x103E
dw 0x1050
dw 0x1051
dw 0x1052
dw 0x1053
dw 0x1054
dw 0x1055
dw 0x1056
dw 0x1057
dw 0x1059
dw 0x1064
dw 0x1065
dw 0x1066
dw 0x1067
dw 0x1068
dw 0x1069
dw 0x106A
dw 0x106B
dw 0x1091
dw 0x1092
dw 0x1093
dw 0x1094
dw 0x1095
dw 0x10fe
dw 0x1209
dw 0x1229
dw 0x2449
dw 0x2459
dw 0x245D
dw 0x27DC
 
DEVICE_IDs = ($ - device_id_list) / 2
 
mac_82557_D100_A = 0
mac_82557_D100_B = 1
mac_82557_D100_C = 2
mac_82558_D101_A4 = 4
mac_82558_D101_B0 = 5
mac_82559_D101M = 8
mac_82559_D101S = 9
mac_82550_D102 = 12
mac_82550_D102_C = 13
mac_82551_E = 14
mac_82551_F = 15
mac_82551_10 = 16
mac_unknown = 0xFF
 
phy_100a = 0x000003E0
phy_100c = 0x035002A8
phy_82555_tx = 0x015002A8
phy_nsc_tx = 0x5C002000
phy_82562_et = 0x033002A8
phy_82562_em = 0x032002A8
phy_82562_ek = 0x031002A8
phy_82562_eh = 0x017002A8
phy_82552_v = 0xd061004d
phy_unknown = 0xFFFFFFFF
 
 
include_debug_strings ; All data wich FDO uses will be included here
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/ethernet/mtd80x.asm
0,0 → 1,1266
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; MTD80x driver for KolibriOS ;;
;; ;;
;; Based on mtd80x.c from the etherboot project ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 2
 
NUM_TX_DESC = 4
NUM_RX_DESC = 4
 
include '../proc32.inc'
include '../imports.inc'
include '../fdo.inc'
include '../netdrv.inc'
 
public START
public service_proc
public version
 
 
; for different PHY
 
MysonPHY = 1
AhdocPHY = 2
SeeqPHY = 3
MarvellPHY = 4
Myson981 = 5
LevelOnePHY = 6
OtherPHY = 10
 
; Offsets to the Command and Status Registers.
 
PAR0 = 0x0 ; physical address 0-3
PAR1 = 0x04 ; physical address 4-5
MAR0 = 0x08 ; multicast address 0-3
MAR1 = 0x0C ; multicast address 4-7
FAR0 = 0x10 ; flow-control address 0-3
FAR1 = 0x14 ; flow-control address 4-5
TCRRCR = 0x18 ; receive & transmit configuration
BCR = 0x1C ; bus command
TXPDR = 0x20 ; transmit polling demand
RXPDR = 0x24 ; receive polling demand
RXCWP = 0x28 ; receive current word pointer
TXLBA = 0x2C ; transmit list base address
RXLBA = 0x30 ; receive list base address
ISR = 0x34 ; interrupt status
IMR = 0x38 ; interrupt mask
FTH = 0x3C ; flow control high/low threshold
MANAGEMENT = 0x40 ; bootrom/eeprom and mii management
TALLY = 0x44 ; tally counters for crc and mpa
TSR = 0x48 ; tally counter for transmit status
BMCRSR = 0x4c ; basic mode control and status
PHYIDENTIFIER = 0x50 ; phy identifier
ANARANLPAR = 0x54 ; auto-negotiation advertisement and link partner ability
ANEROCR = 0x58 ; auto-negotiation expansion and pci conf.
BPREMRPSR = 0x5c ; bypass & receive error mask and phy status
 
; Bits in the interrupt status/enable registers.
 
RFCON = 0x00020000 ; receive flow control xon packet
RFCOFF = 0x00010000 ; receive flow control xoff packet
LSCStatus = 0x00008000 ; link status change
ANCStatus = 0x00004000 ; autonegotiation completed
FBE = 0x00002000 ; fatal bus error
FBEMask = 0x00001800 ; mask bit12-11
ParityErr = 0x00000000 ; parity error
TargetErr = 0x00001000 ; target abort
MasterErr = 0x00000800 ; master error
TUNF = 0x00000400 ; transmit underflow
ROVF = 0x00000200 ; receive overflow
ETI = 0x00000100 ; transmit early int
ERI = 0x00000080 ; receive early int
CNTOVF = 0x00000040 ; counter overflow
RBU = 0x00000020 ; receive buffer unavailable
TBU = 0x00000010 ; transmit buffer unavilable
TI = 0x00000008 ; transmit interrupt
RI = 0x00000004 ; receive interrupt
RxErr = 0x00000002 ; receive error
 
; Bits in the NetworkConfig register.
 
RxModeMask = 0xe0
AcceptAllPhys = 0x80 ; promiscuous mode
AcceptBroadcast = 0x40 ; accept broadcast
AcceptMulticast = 0x20 ; accept mutlicast
AcceptRunt = 0x08 ; receive runt pkt
ALP = 0x04 ; receive long pkt
AcceptErr = 0x02 ; receive error pkt
 
AcceptMyPhys = 0x00000000
RxEnable = 0x00000001
RxFlowCtrl = 0x00002000
TxEnable = 0x00040000
TxModeFDX = 0x00100000
TxThreshold = 0x00e00000
 
PS1000 = 0x00010000
PS10 = 0x00080000
FD = 0x00100000
 
 
; Bits in network_desc.status
 
RXOWN = 0x80000000 ; own bit
FLNGMASK = 0x0fff0000 ; frame length
FLNGShift = 16
MARSTATUS = 0x00004000 ; multicast address received
BARSTATUS = 0x00002000 ; broadcast address received
PHYSTATUS = 0x00001000 ; physical address received
RXFSD = 0x00000800 ; first descriptor
RXLSD = 0x00000400 ; last descriptor
ErrorSummary = 0x80 ; error summary
RUNT = 0x40 ; runt packet received
LONG = 0x20 ; long packet received
FAE = 0x10 ; frame align error
CRC = 0x08 ; crc error
RXER = 0x04 ; receive error
 
; rx_desc_control_bits
 
RXIC = 0x00800000 ; interrupt control
RBSShift = 0
 
; tx_desc_status_bits
 
TXOWN = 0x80000000 ; own bit
JABTO = 0x00004000 ; jabber timeout
CSL = 0x00002000 ; carrier sense lost
LC = 0x00001000 ; late collision
EC = 0x00000800 ; excessive collision
UDF = 0x00000400 ; fifo underflow
DFR = 0x00000200 ; deferred
HF = 0x00000100 ; heartbeat fail
NCRMask = 0x000000ff ; collision retry count
NCRShift = 0
 
; tx_desc_control_bits
 
TXIC = 0x80000000 ; interrupt control
ETIControl = 0x40000000 ; early transmit interrupt
TXLD = 0x20000000 ; last descriptor
TXFD = 0x10000000 ; first descriptor
CRCEnable = 0x08000000 ; crc control
PADEnable = 0x04000000 ; padding control
RetryTxLC = 0x02000000 ; retry late collision
PKTSMask = 0x3ff800 ; packet size bit21-11
PKTSShift = 11
TBSMask = 0x000007ff ; transmit buffer bit 10-0
TBSShift = 0
 
; BootROM/EEPROM/MII Management Register
 
MASK_MIIR_MII_READ = 0x00000000
MASK_MIIR_MII_WRITE = 0x00000008
MASK_MIIR_MII_MDO = 0x00000004
MASK_MIIR_MII_MDI = 0x00000002
MASK_MIIR_MII_MDC = 0x00000001
 
; ST+OP+PHYAD+REGAD+TA
 
OP_READ = 0x6000 ; ST:01+OP:10+PHYAD+REGAD+TA:Z0
OP_WRITE = 0x5002 ; ST:01+OP:01+PHYAD+REGAD+TA:10
 
; -------------------------------------------------------------------------
; Constants for Myson PHY
; -------------------------------------------------------------------------
 
MysonPHYID = 0xd0000302
MysonPHYID0 = 0x0302
StatusRegister = 18
SPEED100 = 0x0400 ; bit10
FULLMODE = 0x0800 ; bit11
 
; -------------------------------------------------------------------------
; Constants for Seeq 80225 PHY
; -------------------------------------------------------------------------
 
SeeqPHYID0 = 0x0016
MIIRegister18 = 18
SPD_DET_100 = 0x80
DPLX_DET_FULL = 0x40
 
; -------------------------------------------------------------------------
; Constants for Ahdoc 101 PHY
; -------------------------------------------------------------------------
 
AhdocPHYID0 = 0x0022
DiagnosticReg = 18
DPLX_FULL = 0x0800
Speed_100 = 0x0400
 
; --------------------------------------------------------------------------
; Constants
; --------------------------------------------------------------------------
 
MarvellPHYID0 = 0x0141
LevelOnePHYID0 = 0x0013
 
MII1000BaseTControlReg = 9
MII1000BaseTStatusReg = 10
SpecificReg = 17
 
; for 1000BaseT Control Register
 
PHYAbletoPerform1000FullDuplex = 0x0200
PHYAbletoPerform1000HalfDuplex = 0x0100
PHY1000AbilityMask = 0x300
 
; for phy specific status register, marvell phy.
 
SpeedMask = 0x0c000
Speed_1000M = 0x08000
Speed_100M = 0x4000
Speed_10M = 0
Full_Duplex = 0x2000
 
; for phy specific status register, levelone phy
 
LXT1000_100M = 0x08000
LXT1000_1000M = 0x0c000
LXT1000_Full = 0x200
 
; for PHY
 
LinkIsUp = 0x0004
LinkIsUp2 = 0x00040000
 
 
 
virtual at 0
 
mtd_desc:
.status dd ?
.control dd ?
.buffer dd ?
.next_desc dd ?
 
.next_desc_logical dd ?
.skbuff dd ?
 
.reserved1 dd ?
.reserved2 dd ?
 
.size = $
 
end virtual
 
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.tx_desc rb NUM_TX_DESC*mtd_desc.size
.rx_desc rb NUM_RX_DESC*mtd_desc.size
 
.io_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
.dev_id dw ?
 
.flags dd ?
 
.crvalue dd ?
.bcrvalue dd ?
 
.cur_rx dd ?
.cur_tx dd ?
 
; These values are keep track of the transceiver/media in use.
 
.linkok dd ?
.line_speed dd ?
.duplexmode dd ?
.default_port dd ?
.PHYType dd ?
 
; MII transceiver section.
 
.mii_cnt dd ? ; MII device addresses.
.phys db ? ; MII device addresses.
 
device_size = $ - 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 @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
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, device_size, .fail
 
; 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 io addres of the PCI device
 
PCI_find_io
 
; We've found the io address, find IRQ now
 
PCI_find_irq
 
DEBUGF 2,"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.io_addr]:8
 
; Ok, the eth_device structure is ready, let's probe the device
; Because initialization fires IRQ, IRQ handler must be aware of this device
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 probe ; this function will output in eax
test eax, eax
jnz .err2 ; If an error occured, exit
 
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 2,"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 2,"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
 
.err2:
dec [devices]
.err:
DEBUGF 2,"removing device structure\n"
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
 
; /* Disable Tx Rx*/
; outl( mtdx.crvalue & (~TxEnable) & (~RxEnable), mtdx.ioaddr + TCRRCR );
;
; /* Reset the chip to erase previous misconfiguration. */
; mtd_reset(nic);
 
; - 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
;
;-------
align 4
probe:
 
DEBUGF 2,"Probing mtd80x device\n"
 
PCI_make_bus_master
 
stdcall PciRead32, [device.pci_bus], [device.pci_dev], 0
 
cmp ax, 0x1516
jne .notfound
shr eax, 16
mov [device.dev_id], ax
 
cmp ax, 0x0800
je .has_mii_xcvr
 
cmp ax, 0x0803
je .has_chip_xcvr
 
cmp ax, 0x0891
je .has_mii_xcvr
 
.notfound:
DEBUGF 1,"Device not supported!\n"
xor eax, eax
dec eax
ret
 
.has_chip_xcvr:
DEBUGF 1,"Device has chip xcvr\n"
 
jmp .xcvr_set
 
.has_mii_xcvr:
DEBUGF 1,"Device has mii xcvr\n"
 
.xcvr_set:
 
call read_mac
 
; Reset the chip to erase previous misconfiguration.
 
set_io 0
set_io BCR
xor eax, eax
inc eax
out dx, eax
 
; find the connected MII xcvrs
 
cmp [device.dev_id], 0x0803
je .is_803
 
; int phy, phy_idx = 0;
;
; for (phy = 1; phy < 32 && phy_idx < 1; phy++) {
; int mii_status = mdio_read(nic, phy, 1);
;
; if (mii_status != 0xffff && mii_status != 0x0000) {
; mtdx.phys[phy_idx] = phy;
;
; DBG ( "%s: MII PHY found at address %d, status "
; "0x%4.4x.\n", mtdx.nic_name, phy, mii_status );
; /* get phy type */
; {
; unsigned int data;
;
; data = mdio_read(nic, mtdx.phys[phy_idx], 2);
; if (data equ= SeeqPHYID0)
; mtdx.PHYType = SeeqPHY;
; else if (data equ= AhdocPHYID0)
; mtdx.PHYType = AhdocPHY;
; else if (data equ= MarvellPHYID0)
; mtdx.PHYType = MarvellPHY;
; else if (data equ= MysonPHYID0)
; mtdx.PHYType = Myson981;
; else if (data equ= LevelOnePHYID0)
; mtdx.PHYType = LevelOnePHY;
; else
; mtdx.PHYType = OtherPHY;
; }
; phy_idx++;
; }
; }
;
; mtdx.mii_cnt = phy_idx;
; if (phy_idx equ= 0) {
; printf("%s: MII PHY not found -- this device may "
; "not operate correctly.\n", mtdx.nic_name);
; }
 
jmp .no_803
 
.is_803:
 
mov [device.phys], 32
 
; get phy type
set_io 0
set_io PHYIDENTIFIER
in eax, dx
 
cmp eax, MysonPHYID
jne @f
 
mov [device.PHYType], MysonPHY
DEBUGF 1,"MysonPHY\n"
jmp .no_803
 
@@:
mov [device.PHYType], OtherPHY
DEBUGF 1,"OtherPHY\n"
 
.no_803:
 
;-------
;
; RESET
;
;-------
align 4
reset:
 
DEBUGF 1,"Resetting mtd80x\n"
 
;--------------------------------
; insert irq handler on given irq
 
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 the chip to erase previous misconfiguration.
 
set_io 0
set_io BCR
xor eax, eax
inc eax
out dx, eax
 
call init_ring
 
; Initialize other registers.
; Configure the PCI bus bursts and FIFO thresholds.
 
mov [device.bcrvalue], 0x10 ; little-endian, 8 burst length
mov [device.crvalue], 0xa00 ; 128 burst length
 
cmp [device.dev_id], 0x891
jne @f
or [device.bcrvalue], 0x200 ; set PROG bit
or [device.crvalue], 0x02000000 ; set enhanced bit
@@:
 
or [device.crvalue], RxEnable + TxThreshold + TxEnable
 
call set_rx_mode
 
set_io 0
set_io BCR
mov eax, [device.bcrvalue]
out dx, eax
 
set_io TCRRCR
mov eax, [device.crvalue]
out dx, eax
 
call getlinkstatus
call getlinktype
 
; Restart Rx engine if stopped.
 
set_io 0
set_io RXPDR
xor eax, eax
out dx, eax
 
; Enable interrupts
 
set_io 0
set_io ISR
mov eax, (FBE or TUNF or CNTOVF or RBU or TI or RI)
out dx, eax
 
set_io IMR
; mov eax, (FBE or TUNF or CNTOVF or RBU or TI or RI)
out dx, eax
 
; clear packet/byte counters
 
xor eax, eax
lea edi, [device.bytes_tx]
mov ecx, 6
rep stosd
 
mov [device.mtu], 1514
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
xor eax, eax
ret
 
 
 
 
align 4
init_ring:
 
DEBUGF 1,"initializing rx and tx ring\n"
 
; Initialize all Rx descriptors
 
lea esi, [device.rx_desc]
mov [device.cur_rx], esi
mov ecx, NUM_RX_DESC
.rx_desc_loop:
mov [esi + mtd_desc.status], RXOWN
mov [esi + mtd_desc.control], 1536 shl RBSShift
 
lea eax, [esi + mtd_desc.size]
mov [esi + mtd_desc.next_desc_logical], eax
push ecx esi
GetRealAddr
mov [esi + mtd_desc.next_desc], eax
 
stdcall KernelAlloc, 1536
pop esi
push esi
mov [esi + mtd_desc.skbuff], eax
call GetPgAddr
pop esi ecx
mov [esi + mtd_desc.buffer], eax
 
add esi, mtd_desc.size
loop .rx_desc_loop
 
; Mark the last entry as wrapping the ring.
 
lea eax, [device.rx_desc]
mov [esi - mtd_desc.size + mtd_desc.next_desc_logical], eax
push esi
GetRealAddr
pop esi
mov [esi - mtd_desc.size + mtd_desc.next_desc], eax
 
set_io 0
set_io RXLBA
out dx, eax
 
; Initialize all Tx descriptors
 
lea esi, [device.tx_desc]
mov [device.cur_tx], esi
mov ecx, NUM_TX_DESC
.tx_desc_loop:
mov [esi + mtd_desc.status], 0
 
lea eax, [esi + mtd_desc.size]
mov [esi + mtd_desc.next_desc_logical], eax
push ecx esi
GetRealAddr
pop esi ecx
mov [esi + mtd_desc.next_desc], eax
 
add esi, mtd_desc.size
loop .tx_desc_loop
 
; Mark the last entry as wrapping the ring.
 
lea eax, [device.tx_desc]
mov [esi - mtd_desc.size + mtd_desc.next_desc_logical], eax
push esi
GetRealAddr
pop esi
mov [esi - mtd_desc.size + mtd_desc.next_desc], eax
 
set_io 0
set_io TXLBA
out dx, eax
 
ret
 
 
align 4
set_rx_mode:
 
DEBUGF 1,"Setting RX mode\n"
 
; Too many to match, or accept all multicasts.
 
set_io 0
set_io MAR0
xor eax, eax
not eax
out dx, eax
set_io MAR1
out dx, eax
 
and [device.crvalue], not (RxModeMask)
or [device.crvalue], AcceptBroadcast + AcceptMulticast + AcceptMyPhys
 
ret
 
 
align 4
getlinkstatus:
 
DEBUGF 1,"Getting link status\n"
 
mov [device.linkok], 0
 
cmp [device.PHYType], MysonPHY
jne .no_myson_phy
 
set_io 0
set_io BMCRSR
mov ecx, 1000
.loop1:
in eax, dx
test eax, LinkIsUp2
jnz .link_ok
 
push ecx edx ebx
mov esi, 10
call Sleep
pop ebx edx ecx
loop .loop1
 
ret
 
.no_myson_phy:
 
; for (i = 0; i < DelayTime; ++i) {
; if (mdio_read(nic, mtdx.phys[0], MII_BMSR) & BMSR_LSTATUS) {
; mtdx.linkok = 1;
; return;
; }
; m80x_delay(100);
 
ret
 
.link_ok:
DEBUGF 1,"Link is up\n"
inc [device.linkok]
ret
 
 
 
 
align 4
getlinktype:
 
DEBUGF 1,"Getting link type\n"
 
cmp [device.PHYType], MysonPHY
jne .no_myson_phy
 
DEBUGF 1,"myson PHY\n"
 
set_io 0
set_io TCRRCR
in eax, dx
 
mov [device.duplexmode], 1 ; 1 = half duplex
test eax, FD
jne @f
DEBUGF 1,"full duplex\n"
inc [device.duplexmode] ; 2 = full duplex
@@:
 
mov [device.line_speed], 1 ; 1 = 10M
test eax, PS10
jne @f
DEBUGF 1,"100mbit\n"
inc [device.line_speed] ; 2 = 100M
@@:
 
ret
 
.no_myson_phy:
 
DEBUGF 1,"no myson phy\n"
 
; if (mtdx.PHYType equ= SeeqPHY) { /* this PHY is SEEQ 80225 */
; unsigned int data;
;
; data = mdio_read(dev, mtdx.phys[0], MIIRegister18);
; if (data & SPD_DET_100)
; mtdx.line_speed = 2; /* 100M */
; else
; mtdx.line_speed = 1; /* 10M */
; if (data & DPLX_DET_FULL)
; mtdx.duplexmode = 2; /* full duplex mode */
; else
; mtdx.duplexmode = 1; /* half duplex mode */
; } else if (mtdx.PHYType equ= AhdocPHY) {
; unsigned int data;
;
; data = mdio_read(dev, mtdx.phys[0], DiagnosticReg);
; if (data & Speed_100)
; mtdx.line_speed = 2; /* 100M */
; else
; mtdx.line_speed = 1; /* 10M */
; if (data & DPLX_FULL)
; mtdx.duplexmode = 2; /* full duplex mode */
; else
; mtdx.duplexmode = 1; /* half duplex mode */
; }
; else if (mtdx.PHYType equ= MarvellPHY) {
; unsigned int data;
;
; data = mdio_read(dev, mtdx.phys[0], SpecificReg);
; if (data & Full_Duplex)
; mtdx.duplexmode = 2; /* full duplex mode */
; else
; mtdx.duplexmode = 1; /* half duplex mode */
; data &= SpeedMask;
; if (data equ= Speed_1000M)
; mtdx.line_speed = 3; /* 1000M */
; else if (data equ= Speed_100M)
; mtdx.line_speed = 2; /* 100M */
; else
; mtdx.line_speed = 1; /* 10M */
; }
; else if (mtdx.PHYType equ= Myson981) {
; unsigned int data;
;
; data = mdio_read(dev, mtdx.phys[0], StatusRegister);
;
; if (data & SPEED100)
; mtdx.line_speed = 2;
; else
; mtdx.line_speed = 1;
;
; if (data & FULLMODE)
; mtdx.duplexmode = 2;
; else
; mtdx.duplexmode = 1;
; }
; else if (mtdx.PHYType equ= LevelOnePHY) {
; unsigned int data;
;
; data = mdio_read(dev, mtdx.phys[0], SpecificReg);
; if (data & LXT1000_Full)
; mtdx.duplexmode = 2; /* full duplex mode */
; else
; mtdx.duplexmode = 1; /* half duplex mode */
; data &= SpeedMask;
; if (data equ= LXT1000_1000M)
; mtdx.line_speed = 3; /* 1000M */
; else if (data equ= LXT1000_100M)
; mtdx.line_speed = 2; /* 100M */
; else
; mtdx.line_speed = 1; /* 10M */
; }
 
; // chage crvalue
; // mtdx.crvalue&equ(~PS10)&(~FD);
; mtdx.crvalue &= (~PS10) & (~FD) & (~PS1000);
; if (mtdx.line_speed equ= 1)
; mtdx.crvalue |= PS10;
; else if (mtdx.line_speed equ= 3)
; mtdx.crvalue |= PS1000;
; if (mtdx.duplexmode equ= 2)
; mtdx.crvalue |= FD;
;
 
ret
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
transmit:
 
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
mov eax, [esp+4]
DEBUGF 1,"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
 
mov esi, [device.cur_tx]
push [esi + mtd_desc.next_desc_logical]
pop [device.cur_tx]
 
; todo: check if descriptor is not owned by the device!
 
mov eax, [esp + 4]
mov [esi + mtd_desc.skbuff], eax
GetRealAddr
mov [esi + mtd_desc.buffer], eax
 
mov eax, [esp + 8]
shl eax, PKTSShift ; packet size
or eax, TXLD + TXFD + CRCEnable + PADEnable + TXIC + 1536 shl TBSShift ; buffer size
mov [esi + mtd_desc.control], eax
 
mov [esi + mtd_desc.status], TXOWN
 
;-------------
; Update stats
 
inc [device.packets_tx]
mov eax, [esp+8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
; Point to transmit descriptor
 
set_io 0
set_io TXLBA
mov eax, esi
GetRealAddr
out dx, eax
 
; set_io TCRRCR
; mov eax, [device.crvalue]
; out dx, eax
 
; Wake the potentially-idle transmit channel.
 
set_io TXPDR ; TX Poll
xor eax, eax
out dx, eax
 
DEBUGF 1,"transmit ok\n"
xor eax, eax
ret 8
 
.fail:
DEBUGF 1,"transmit failed\n"
or eax, -1
stdcall KernelFree, [esp + 4]
ret 8
 
 
 
align 4
read_mac:
 
set_io 0
set_io PAR0
lea edi, [device.mac]
insd
stosd
set_io PAR1
insw
stosw
 
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
 
align 4
write_mac:
 
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 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]
 
set_io 0
set_io ISR
in eax, dx
out dx, eax ; send it back to ACK
test eax, eax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
pop edi esi ebx
xor eax, eax
 
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x ", ebx, ax
 
test ax, RI ; receive interrupt
jz .no_rx
 
DEBUGF 1,"Receive interrupt\n"
.rx:
push ax
 
.rx_loop:
mov esi, [device.cur_rx]
 
test [esi + mtd_desc.status], RXOWN
jnz .fail_rx
 
push .rx_complete
 
mov ecx, [esi + mtd_desc.status]
shr ecx, FLNGShift
sub ecx, 4 ; we dont need CRC
push ecx
 
;-------------
; Update stats
 
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
inc dword [device.packets_rx]
 
 
push [esi + mtd_desc.skbuff]
 
jmp Eth_input
 
.rx_complete:
mov esi, [device.cur_rx]
 
mov [esi + mtd_desc.control], 1536 shl RBSShift
 
stdcall KernelAlloc, 1536
mov [esi + mtd_desc.skbuff], eax
call GetPgAddr
mov [esi + mtd_desc.buffer], eax
 
mov [esi + mtd_desc.status], RXOWN
 
mov eax, [esi + mtd_desc.next_desc_logical]
mov [device.cur_rx], eax
 
jmp .rx_loop
;
; while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
; {
; mtdx.cur_rx->status = RXOWN;
; mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
; }
;
; /* Restart Rx engine if stopped. */
; outl(0, mtdx.ioaddr + RXPDR);
 
.fail_rx:
DEBUGF 1,"RX failed\n"
 
pop ax
.no_rx:
 
test ax, TI ; transmit interrupt
jz .no_tx
 
DEBUGF 1,"Transmit interrupt\n"
push ax
 
lea esi, [device.tx_desc]
mov ecx, NUM_TX_DESC
.tx_loop:
 
test [esi + mtd_desc.status], TXOWN
jnz .skip_this_one
 
mov eax, [esi + mtd_desc.skbuff]
test eax, eax
je .skip_this_one
 
mov [esi + mtd_desc.skbuff], 0
 
DEBUGF 1,"freeing buffer:%x\n", eax
stdcall KernelFree, eax
 
.skip_this_one:
mov esi, [esi + mtd_desc.next_desc_logical]
loop .tx_loop
 
pop ax
 
.no_tx:
 
test ax, TBU
jz .no_tbu
 
DEBUGF 1,"Transmit buffer unavailable!\n"
 
.no_tbu:
 
.fail:
pop edi esi ebx
xor eax, eax
inc eax
 
ret
 
 
; End of code
 
align 4 ; Place all initialised data here
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'mtd80x',0 ; max 16 chars include zero
 
 
; 0x1516, 0x0800, "MTD800", "Myson MTD800"
; 0x1516, 0x0803, "MTD803", "Surecom EP-320X"
; 0x1516, 0x0891, "MTD891", "Myson MTD891"
 
 
include_debug_strings ; All data wich FDO uses will be included here
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/ethernet/pcnet32.asm
0,0 → 1,1578
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; AMD PCnet driver for KolibriOS ;;
;; ;;
;; By hidnplayr & clevermouse ;;
;; ;;
;; Based on the PCnet32 driver for MenuetOS, by Jarek Pelczar ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 2
 
MAX_DEVICES = 4
MAX_ETH_FRAME_SIZE = 1514
 
TX_RING_SIZE = 4
RX_RING_SIZE = 4
 
include '../proc32.inc'
include '../imports.inc'
include '../fdo.inc'
include '../netdrv.inc'
 
public START
public service_proc
public version
 
 
PORT_AUI = 0x00
PORT_10BT = 0x01
PORT_GPSI = 0x02
PORT_MII = 0x03
PORT_PORTSEL = 0x03
PORT_ASEL = 0x04
PORT_100 = 0x40
PORT_FD = 0x80
 
DMA_MASK = 0xffffffff
 
LOG_TX_BUFFERS = 2 ; FIXME
LOG_RX_BUFFERS = 2
 
TX_RING_MOD_MASK = (TX_RING_SIZE-1)
TX_RING_LEN_BITS = (LOG_TX_BUFFERS shl 12)
 
RX_RING_MOD_MASK = (RX_RING_SIZE-1)
RX_RING_LEN_BITS = (LOG_RX_BUFFERS shl 4)
 
PKT_BUF_SZ = 1544
 
WIO_RDP = 0x10
WIO_RAP = 0x12
WIO_RESET = 0x14
WIO_BDP = 0x16
 
DWIO_RDP = 0x10
DWIO_RAP = 0x14
DWIO_RESET = 0x18
DWIO_BDP = 0x1C
 
; CSR registers
 
CSR_CSR = 0x00
CSR_IAB0 = 0x01
CSR_IAB1 = 0x02
CSR_IMR = 0x03
CSR_TFEAT = 0x04
CSR_EXTCTL1 = 0x05
CSR_DTBLLEN = 0x06
CSR_EXTCTL2 = 0x07
CSR_MAR0 = 0x08
CSR_MAR1 = 0x09
CSR_MAR2 = 0x0A
CSR_MAR3 = 0x0B
CSR_PAR0 = 0x0C
CSR_PAR1 = 0x0D
CSR_PAR2 = 0x0E
CSR_MODE = 0x0F
CSR_RXADDR0 = 0x18
CSR_RXADDR1 = 0x19
CSR_TXADDR0 = 0x1E
CSR_TXADDR1 = 0x1F
CSR_TXPOLL = 0x2F
CSR_RXPOLL = 0x31
CSR_RXRINGLEN = 0x4C
CSR_TXRINGLEN = 0x4E
CSR_DMACTL = 0x50
CSR_BUSTIMER = 0x52
CSR_MEMERRTIMEO = 0x64
CSR_ONNOWMISC = 0x74
CSR_ADVFEAT = 0x7A
CSR_MACCFG = 0x7D
CSR_CHIPID0 = 0x58
CSR_CHIPID1 = 0x59
 
; Control and Status Register (CSR0)
 
CSR_INIT = 1 shl 0
CSR_START = 1 shl 1
CSR_STOP = 1 shl 2
CSR_TX = 1 shl 3
CSR_TXON = 1 shl 4
CSR_RXON = 1 shl 5
CSR_INTEN = 1 shl 6
CSR_INTR = 1 shl 7
CSR_IDONE = 1 shl 8
CSR_TINT = 1 shl 9
CSR_RINT = 1 shl 10
CSR_MERR = 1 shl 11
CSR_MISS = 1 shl 12
CSR_CERR = 1 shl 13
 
; Interrupt masks and deferral control (CSR3)
 
IMR_BSWAP = 0x0004
IMR_ENMBA = 0x0008 ; enable modified backoff alg
IMR_DXMT2PD = 0x0010
IMR_LAPPEN = 0x0020 ; lookahead packet processing enb
IMR_DXSUFLO = 0x0040 ; disable TX stop on underflow
IMR_IDONE = 0x0100
IMR_TINT = 0x0200
IMR_RINT = 0x0400
IMR_MERR = 0x0800
IMR_MISS = 0x1000
 
IMR = IMR_IDONE ; IMR_TINT + IMR_RINT + IMR_MERR + IMR_MISS ;+ IMR_IDONE
 
; Test and features control (CSR4)
 
TFEAT_TXSTRTMASK = 0x0004
TFEAT_TXSTRT = 0x0008
TFEAT_RXCCOFLOWM = 0x0010 ; Rx collision counter oflow
TFEAT_RXCCOFLOW = 0x0020
TFEAT_UINT = 0x0040
TFEAT_UINTREQ = 0x0080
TFEAT_MISSOFLOWM = 0x0100
TFEAT_MISSOFLOW = 0x0200
TFEAT_STRIP_FCS = 0x0400
TFEAT_PAD_TX = 0x0800
TFEAT_TXDPOLL = 0x1000
TFEAT_DMAPLUS = 0x4000
 
; Extended control and interrupt 1 (CSR5)
 
EXTCTL1_SPND = 0x0001 ; suspend
EXTCTL1_MPMODE = 0x0002 ; magic packet mode
EXTCTL1_MPENB = 0x0004 ; magic packet enable
EXTCTL1_MPINTEN = 0x0008 ; magic packet interrupt enable
EXTCTL1_MPINT = 0x0010 ; magic packet interrupt
EXTCTL1_MPPLBA = 0x0020 ; magic packet phys. logical bcast
EXTCTL1_EXDEFEN = 0x0040 ; excessive deferral interrupt enb.
EXTCTL1_EXDEF = 0x0080 ; excessive deferral interrupt
EXTCTL1_SINTEN = 0x0400 ; system interrupt enable
EXTCTL1_SINT = 0x0800 ; system interrupt
EXTCTL1_LTINTEN = 0x4000 ; last TX interrupt enb
EXTCTL1_TXOKINTD = 0x8000 ; TX OK interrupt disable
 
; RX/TX descriptor len (CSR6)
 
DTBLLEN_RLEN = 0x0F00
DTBLLEN_TLEN = 0xF000
 
; Extended control and interrupt 2 (CSR7)
 
EXTCTL2_MIIPDTINTE = 0x0001
EXTCTL2_MIIPDTINT = 0x0002
EXTCTL2_MCCIINTE = 0x0004
EXTCTL2_MCCIINT = 0x0008
EXTCTL2_MCCINTE = 0x0010
EXTCTL2_MCCINT = 0x0020
EXTCTL2_MAPINTE = 0x0040
EXTCTL2_MAPINT = 0x0080
EXTCTL2_MREINTE = 0x0100
EXTCTL2_MREINT = 0x0200
EXTCTL2_STINTE = 0x0400
EXTCTL2_STINT = 0x0800
EXTCTL2_RXDPOLL = 0x1000
EXTCTL2_RDMD = 0x2000
EXTCTL2_RXFRTG = 0x4000
EXTCTL2_FASTSPNDE = 0x8000
 
; Mode (CSR15)
 
MODE_RXD = 0x0001 ; RX disable
MODE_TXD = 0x0002 ; TX disable
MODE_LOOP = 0x0004 ; loopback enable
MODE_TXCRCD = 0x0008
MODE_FORCECOLL = 0x0010
MODE_RETRYD = 0x0020
MODE_INTLOOP = 0x0040
MODE_PORTSEL = 0x0180
MODE_RXVPAD = 0x2000
MODE_RXNOBROAD = 0x4000
MODE_PROMISC = 0x8000
 
; BCR (Bus Control Registers)
 
BCR_MMRA = 0x00 ; Master Mode Read Active
BCR_MMW = 0x01 ; Master Mode Write Active
BCR_MISCCFG = 0x02
BCR_LED0 = 0x04
BCR_LED1 = 0x05
BCR_LED2 = 0x06
BCR_LED3 = 0x07
BCR_DUPLEX = 0x09
BCR_BUSCTL = 0x12
BCR_EECTL = 0x13
BCR_SSTYLE = 0x14
BCR_PCILAT = 0x16
BCR_PCISUBVENID = 0x17
BCR_PCISUBSYSID = 0x18
BCR_SRAMSIZE = 0x19
BCR_SRAMBOUND = 0x1A
BCR_SRAMCTL = 0x1B
BCR_MIICTL = 0x20
BCR_MIIADDR = 0x21
BCR_MIIDATA = 0x22
BCR_PCIVENID = 0x23
BCR_PCIPCAP = 0x24
BCR_DATA0 = 0x25
BCR_DATA1 = 0x26
BCR_DATA2 = 0x27
BCR_DATA3 = 0x28
BCR_DATA4 = 0x29
BCR_DATA5 = 0x2A
BCR_DATA6 = 0x2B
BCR_DATA7 = 0x2C
BCR_ONNOWPAT0 = 0x2D
BCR_ONNOWPAT1 = 0x2E
BCR_ONNOWPAT2 = 0x2F
BCR_PHYSEL = 0x31
 
; RX status register
 
RXSTAT_BPE = 0x0080 ; bus parity error
RXSTAT_ENP = 0x0100 ; end of packet
RXSTAT_STP = 0x0200 ; start of packet
RXSTAT_BUFF = 0x0400 ; buffer error
RXSTAT_CRC = 0x0800 ; CRC error
RXSTAT_OFLOW = 0x1000 ; rx overrun
RXSTAT_FRAM = 0x2000 ; framing error
RXSTAT_ERR = 0x4000 ; error summary
RXSTAT_OWN = 0x8000
 
; TX status register
 
TXSTAT_TRC = 0x0000000F ; transmit retries
TXSTAT_RTRY = 0x04000000 ; retry
TXSTAT_LCAR = 0x08000000 ; lost carrier
TXSTAT_LCOL = 0x10000000 ; late collision
TXSTAT_EXDEF = 0x20000000 ; excessive deferrals
TXSTAT_UFLOW = 0x40000000 ; transmit underrun
TXSTAT_BUFF = 0x80000000 ; buffer error
 
TXCTL_OWN = 0x8000
TXCTL_ERR = 0x4000 ; error summary
TXCTL_ADD_FCS = 0x2000 ; add FCS to pkt
TXCTL_MORE_LTINT = 0x1000
TXCTL_ONE = 0x0800
TXCTL_DEF = 0x0400
TXCTL_STP = 0x0200
TXCTL_ENP = 0x0100
TXCTL_BPE = 0x0080
 
TXCTL_MBO = 0x0000F000
TXCTL_BUFSZ = 0x00000FFF
 
;
 
MAX_PHYS = 32
 
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
; device specific
 
rb 0x100-(($ - device) and 0xff) ; align 256
.private:
.mode_ dw ?
.tlen_rlen dw ?
.phys_addr dp ?
.reserved dw ?
.filter dq ?
.rx_ring_phys dd ?
.tx_ring_phys dd ?
 
rb 0x100-(($ - device) and 0xff) ; align 256
.rx_ring rb RX_RING_SIZE * descriptor.size
 
rb 0x100-(($ - device) and 0xff) ; align 256
.tx_ring rb TX_RING_SIZE * descriptor.size
 
.cur_rx db ?
.cur_tx db ?
.last_tx db ?
.options dd ?
.full_duplex db ?
.chip_version dw ?
.mii db ?
.ltint db ?
.dxsuflo db ?
.fset db ?
.fdx db ?
 
.io_addr dd ?
.irq_line db ?
.pci_bus dd ?
.pci_dev dd ?
 
.phy dw ?
 
.read_csr dd ?
.write_csr dd ?
.read_bcr dd ?
.write_bcr dd ?
.read_rap dd ?
.write_rap dd ?
.sw_reset dd ?
 
device_size = $ - device
 
end virtual
 
struc descriptor {
.base dd ?
.length dw ?
.status dw ?
.msg_length dw ?
.misc dw ?
.virtual dd ?
 
.size:
}
 
virtual at 0
descriptor descriptor
end virtual
 
 
 
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
proc START stdcall, state:dword
 
cmp [state], 1
jne .exit
 
.entry:
 
DEBUGF 1,"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 ecx, [devices]
test ecx, ecx
jz .firstdevice
 
mov esi, device_list
; 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 @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
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, device_size, .fail
 
; 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 io addres of the PCI device
 
PCI_find_io
 
; We've found the io 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.io_addr]:4
 
; Ok, the eth_device structure is ready, let's probe the device
; Because initialization fires IRQ, IRQ handler must be aware of this device
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 probe ; this function will output in eax
test eax, eax
jnz .destroy ; If an error occured, exit
 
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
 
dec [devices]
.err:
DEBUGF 1,"Error, removing all data !\n"
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 (RTL8139_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 a PCnet device)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
probe:
 
mov edx, [device.io_addr]
 
call wio_reset
 
xor ecx, ecx
call wio_read_csr
cmp eax, 4
jne .try_dwio
 
; Try Word I/O
mov ax, 88
add edx, WIO_RAP
out dx, ax
nop
nop
in ax, dx
sub edx, WIO_RAP
cmp ax, 88
jne .try_dwio
 
call switch_to_wio
 
jmp .L1
 
.try_dwio:
call dwio_reset
 
xor ecx, ecx
call dwio_read_csr
cmp eax, 4
jne .no_dev
 
; Try Dword I/O
add edx, DWIO_RAP
mov eax, 88
out dx, eax
nop
nop
in eax, dx
sub edx, DWIO_RAP
and eax, 0xffff
cmp eax, 88
jne .no_dev
 
call switch_to_dwio
 
jmp .L1
 
.no_dev:
DEBUGF 1,"PCnet device not found!\n"
mov eax, 1
ret
 
.L1:
mov ecx, CSR_CHIPID0
call [device.read_csr]
 
mov esi, eax
shr esi, 12
 
and ax, 0xfff
cmp ax, 3
jne .no_dev
 
mov ecx, CSR_CHIPID1
call [device.read_csr]
shl eax, 4
or eax, esi
mov [device.chip_version], ax
 
mov [device.fdx], 0
mov [device.mii], 0
mov [device.fset], 0
mov [device.dxsuflo], 0
mov [device.ltint], 0
 
cmp ax, 0x2420
je .L2
cmp ax, 0x2430
je .L2
 
mov [device.fdx], 1
 
cmp ax, 0x2621
je .L4
cmp ax, 0x2623
je .L5
cmp ax, 0x2624
je .L6
cmp ax, 0x2625
je .L7
cmp ax, 0x2626
je .L8
cmp ax, 0x2627
je .L9
 
DEBUGF 1,"Invalid chip rev\n"
jmp .no_dev
.L2:
mov [device.name], device_l2
jmp .L10
.L4:
mov [device.name], device_l4
; mov [device.fdx], 1
jmp .L10
.L5:
mov [device.name], device_l5
; mov [device.fdx], 1
mov [device.mii], 1
mov [device.fset], 1
mov [device.ltint], 1
jmp .L10
.L6:
mov [device.name], device_l6
; mov [device.fdx], 1
mov [device.mii], 1
mov [device.fset], 1
jmp .L10
.L7:
mov [device.name], device_l7
; mov [device.fdx], 1
mov [device.mii], 1
jmp .L10
.L8:
mov [device.name], device_l8
; mov [device.fdx], 1
mov ecx, CSR_RXPOLL
call dword [device.read_bcr]
call dword [device.write_bcr]
jmp .L10
.L9:
mov [device.name], device_l9
; mov [device.fdx], 1
mov [device.mii], 1
.L10:
DEBUGF 1,"device name: %s\n", [device.name]
 
cmp [device.fset], 1
jne .L11
mov ecx, BCR_BUSCTL
call [device.read_bcr]
or eax, 0x800
call [device.write_bcr]
 
mov ecx, CSR_DMACTL
call [device.read_csr]
; and eax, 0xc00
; or eax, 0xc00
mov eax, 0xc00
call [device.write_csr]
 
mov [device.dxsuflo],1
mov [device.ltint],1
.L11:
 
PCI_make_bus_master
 
mov [device.options], PORT_ASEL
mov [device.mode_], MODE_RXD + MODE_TXD ; disable receive and transmit
mov [device.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
 
mov dword [device.filter], 0
mov dword [device.filter+4], 0
 
align 4
reset:
 
; attach int handler
 
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
@@:
 
mov edx, [device.io_addr]
 
call [device.sw_reset]
 
; Switch pcnet32 to 32bit mode
mov ecx, BCR_SSTYLE
mov eax, 2
call [device.write_bcr]
 
; set/reset autoselect bit
mov ecx, BCR_MISCCFG
call [device.read_bcr]
and eax, not 2
test [device.options], PORT_ASEL
jz @f
or eax, 2
@@:
call [device.write_bcr]
 
; Handle full duplex setting
cmp byte [device.full_duplex], 0
je .duplex_ok
mov ecx, BCR_DUPLEX
call [device.read_bcr]
and eax, not 3
test [device.options], PORT_FD
jz @f
or eax, 1
cmp [device.options], PORT_FD or PORT_AUI
jne .set_duplex
or eax, 2
jmp .set_duplex
@@:
test [device.options], PORT_ASEL
jz .set_duplex
cmp [device.chip_version], 0x2627
jne .set_duplex
or eax, 3
.set_duplex:
mov ecx, BCR_DUPLEX
call [device.write_bcr]
.duplex_ok:
 
; set/reset GPSI bit in test register
mov ecx, 124
call [device.read_csr]
mov ecx, [device.options]
and ecx, PORT_PORTSEL
cmp ecx, PORT_GPSI
jne @f
or eax, 0x10
@@:
call [device.write_csr]
cmp [device.mii], 0
je .L6
test [device.options], PORT_ASEL
jnz .L6
mov ecx, BCR_MIICTL
call [device.read_bcr]
and eax, not 0x38
test [device.options], PORT_FD
jz @f
or eax, 0x10
@@:
test [device.options], PORT_100
jz @f
or eax, 0x08
@@:
call [device.write_bcr]
jmp .L9
.L6:
test [device.options], PORT_ASEL
jz .L9
mov ecx, BCR_MIICTL
DEBUGF 1,"ASEL, enable auto-negotiation\n"
call [device.read_bcr]
and eax, not 0x98
or eax, 0x20
call [device.write_bcr]
.L9:
cmp [device.ltint], 0
je @f
mov ecx, 5
call [device.read_csr]
or eax, (1 shl 14)
call [device.write_csr]
@@:
mov eax, [device.options]
and eax, PORT_PORTSEL
shl eax, 7
mov [device.mode_], ax
mov dword [device.filter], -1
mov dword [device.filter+4], -1
 
 
 
;-----------------------------
 
test [device.mii], 1
jz .no_mii
 
mov [device.phy], 0
 
.mii_loop:
mov ecx, MII_PHYSID1
call mdio_read
cmp ax, 0xffff
je .next
 
DEBUGF 1, "0x%x\n", ax
 
mov ecx, MII_PHYSID2
call mdio_read
cmp ax, 0xffff
je .next
 
DEBUGF 1, "0x%x\n", ax
 
jmp .got_phy
 
cmp [device.phy], 31
jne .next
mov ax, [device.chip_version]
inc ax
and ax, 0xfffe
cmp ax, 0x2624 ; 79c971 & 79c972 have phantom phy at id 31
je .got_phy
 
.next:
inc [device.phy]
cmp [device.phy], MAX_PHYS
jb .mii_loop
 
DEBUGF 1, "No PHY found!\n"
 
or eax, -1
ret
 
.got_phy:
DEBUGF 1, "Found PHY at 0x%x\n", [device.phy]:4
 
.no_mii:
 
;-----------------------------------------------
 
call read_mac
 
lea esi, [device.mac]
lea edi, [device.phys_addr]
movsd
movsw
 
call init_ring
 
mov edx, [device.io_addr] ; init ring destroys edx
 
lea eax, [device.private]
GetRealAddr
push eax
and eax, 0xffff
mov ecx, 1
call [device.write_csr]
pop eax
shr eax, 16
mov ecx, 2
call [device.write_csr]
 
mov ecx, 4
mov eax, 0x0915
call [device.write_csr]
 
; Set the interrupt mask
mov ecx, CSR_IMR
mov eax, IMR
call [device.write_csr]
 
; Initialise the device
xor ecx, ecx
mov eax, CSR_INIT
call [device.write_csr]
 
mov esi, 100
; xor ecx, ecx
@@:
call [device.read_csr]
test ax, CSR_IDONE
jnz @f
 
dec esi
jnz @r
DEBUGF 1,"Initialize timeout!\n"
@@:
 
; Start the device and enable interrupts
xor ecx, ecx
mov eax, CSR_START + CSR_INTEN
call [device.write_csr]
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
; get link status
mov [device.state], ETH_LINK_UNKOWN
 
call check_media
 
DEBUGF 1,"reset complete\n"
xor eax, eax
ret
 
 
align 4
init_ring:
 
DEBUGF 1,"init ring\n"
 
lea edi, [device.rx_ring]
mov eax, edi
GetRealAddr
mov [device.rx_ring_phys], eax
mov ecx, RX_RING_SIZE
.rx_init:
push ecx
stdcall KernelAlloc, PKT_BUF_SZ
pop ecx
mov [edi + descriptor.virtual], eax
GetRealAddr
mov [edi + descriptor.base], eax
mov [edi + descriptor.length], - PKT_BUF_SZ
mov [edi + descriptor.status], RXSTAT_OWN
mov dword [edi + descriptor.msg_length], 0 ; also clears misc field
add edi, descriptor.size
dec ecx
jnz .rx_init
 
lea edi, [device.tx_ring]
mov eax, edi
GetRealAddr
mov [device.tx_ring_phys], eax
mov ecx, TX_RING_SIZE
.tx_init:
mov [edi + descriptor.status], 0
add edi, descriptor.size
dec ecx
jnz .tx_init
 
mov [device.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
 
mov [device.cur_tx], 0
mov [device.last_tx], 0
mov [device.cur_rx], 0
 
ret
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
transmit:
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
DEBUGF 1,"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 .nospace ; packet is too long
cmp dword [esp+8], 60
jb .nospace ; packet is too short
 
; check descriptor
lea edi, [device.tx_ring]
movzx eax, [device.cur_tx]
shl eax, 4
add edi, eax
 
test [edi + descriptor.status], TXCTL_OWN
jnz .nospace
; descriptor is free, use it
mov eax, [esp+4]
mov [edi + descriptor.virtual], eax
GetRealAddr
mov [edi + descriptor.base], eax
; set length
mov eax, [esp+8]
neg eax
mov [edi + descriptor.length], ax
; put to transfer queue
mov [edi + descriptor.status], TXCTL_OWN + TXCTL_STP + TXCTL_ENP
 
; trigger an immediate send
mov edx, [device.io_addr]
xor ecx, ecx ; CSR0
call [device.read_csr]
or eax, CSR_TX
call [device.write_csr]
 
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
inc [device.cur_tx]
and [device.cur_tx], TX_RING_SIZE - 1
DEBUGF 2," - Packet Sent! "
 
; Update stats
inc [device.packets_tx]
mov eax, [esp+8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
.finish:
DEBUGF 2," - Done!\n"
xor eax, eax
ret 8
 
.nospace:
DEBUGF 1, 'ERROR: no free transmit descriptors\n'
stdcall KernelFree, [esp+4]
or eax, -1
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 edx, [device.io_addr]
push ecx
xor ecx, ecx ; CSR0
call [device.read_csr] ; get IRQ reason
call [device.write_csr] ; write it back to ACK
pop ecx
and ax, CSR_RINT or CSR_TINT
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\n", ebx, eax:2
 
push ax
test ax, CSR_RINT
jz .not_receive
 
push ebx
.rx_loop:
pop ebx
movzx eax, [device.cur_rx]
shl eax, 4
lea edi, [device.rx_ring]
add edi, eax ; edi now points to current rx ring entry
 
mov ax, [edi + descriptor.status]
DEBUGF 1,"RX packet status: %x\n", eax:4
 
test ax, RXSTAT_OWN ; If this bit is set, the controller OWN's the packet, if not, we do
jnz .not_receive
 
test ax, RXSTAT_ENP
jz .not_receive
 
test ax, RXSTAT_STP
jz .not_receive
 
movzx ecx, [edi + descriptor.msg_length] ; get packet length in ecx
sub ecx, 4 ;
 
; Set pointers for ETH_input
push ebx
 
push .rx_loop ; return address
push ecx ; packet size
push [edi + descriptor.virtual] ; packet address
 
; Update stats
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
inc [device.packets_rx]
 
; now allocate a new buffer
stdcall KernelAlloc, PKT_BUF_SZ ; Allocate a buffer for the next packet
mov [edi + descriptor.virtual], eax ; set virtual address
GetRealAddr
mov [edi + descriptor.base], eax ; and real address
 
; mov word [edi + descriptor.length], - PKT_BUF_SZ
mov [edi + descriptor.status], RXSTAT_OWN ; give it back to PCnet controller
 
inc [device.cur_rx] ; set next receive descriptor
and [device.cur_rx], RX_RING_SIZE - 1
 
jmp Eth_input
 
.not_receive:
pop ax
 
test ax, CSR_TINT
jz .not_transmit
 
.tx_loop:
lea edi, [device.tx_ring]
movzx eax, [device.last_tx]
shl eax, 4
add edi, eax
 
test [edi + descriptor.status], TXCTL_OWN
jnz .not_transmit
 
mov eax, [edi + descriptor.virtual]
test eax, eax
jz .not_transmit
 
mov [edi + descriptor.virtual], 0
 
DEBUGF 1,"Removing packet %x from memory\n", eax
 
stdcall KernelFree, eax
 
inc [device.last_tx]
and [device.last_tx], TX_RING_SIZE - 1
jmp .tx_loop
 
.not_transmit:
pop edi esi ebx
xor eax, eax
inc eax
 
ret
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Write MAC address ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
write_mac: ; in: mac pushed onto stack (as 3 words)
 
DEBUGF 1,"Writing MAC: %x-%x-%x-%x-%x-%x",[esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
 
mov edx, [device.io_addr]
add dx, 2
xor eax, eax
 
mov ecx, CSR_PAR0
@@:
pop ax
call [device.write_csr]
DEBUGF 1,"."
inc ecx
cmp ecx, CSR_PAR2
jb @r
 
DEBUGF 1,"\n"
 
; Notice this procedure does not ret, but continues to read_mac instead.
 
;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Read MAC address ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;
align 4
read_mac:
DEBUGF 1,"Reading MAC"
 
mov edx, [device.io_addr]
add dx, 6
@@:
dec dx
dec dx
in ax, dx
push ax
DEBUGF 1,"."
cmp edx, [device.io_addr]
ja @r
 
DEBUGF 1," %x-%x-%x-%x-%x-%x\n",[esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
 
lea edi, [device.mac]
pop ax
stosw
pop ax
stosw
pop ax
stosw
 
ret
 
align 4
switch_to_wio:
 
DEBUGF 1,"Switching to 16-bit mode\n"
 
mov [device.read_csr], wio_read_csr
mov [device.write_csr], wio_write_csr
mov [device.read_bcr], wio_read_bcr
mov [device.write_bcr], wio_write_bcr
mov [device.read_rap], wio_read_rap
mov [device.write_rap], wio_write_rap
mov [device.sw_reset], wio_reset
 
ret
 
align 4
switch_to_dwio:
 
DEBUGF 1,"Switching to 32-bit mode\n"
 
mov [device.read_csr], dwio_read_csr
mov [device.write_csr], dwio_write_csr
mov [device.read_bcr], dwio_read_bcr
mov [device.write_bcr], dwio_write_bcr
mov [device.read_rap], dwio_read_rap
mov [device.write_rap], dwio_write_rap
mov [device.sw_reset], dwio_reset
 
ret
 
 
; ecx - index
; return:
; eax - data
align 4
wio_read_csr:
 
add edx, WIO_RAP
mov ax, cx
out dx, ax
add edx, WIO_RDP - WIO_RAP
in ax, dx
and eax, 0xffff
sub edx, WIO_RDP
 
ret
 
 
; eax - data
; ecx - index
align 4
wio_write_csr:
 
add edx, WIO_RAP
xchg eax, ecx
out dx, ax
xchg eax, ecx
add edx, WIO_RDP - WIO_RAP
out dx, ax
sub edx, WIO_RDP
 
ret
 
 
; ecx - index
; return:
; eax - data
align 4
wio_read_bcr:
 
add edx, WIO_RAP
mov ax, cx
out dx, ax
add edx, WIO_BDP - WIO_RAP
in ax, dx
and eax, 0xffff
sub edx, WIO_BDP
 
ret
 
 
; eax - data
; ecx - index
align 4
wio_write_bcr:
 
add edx, WIO_RAP
xchg eax, ecx
out dx, ax
xchg eax, ecx
add edx, WIO_BDP - WIO_RAP
out dx, ax
sub edx, WIO_BDP
 
ret
 
align 4
wio_read_rap:
 
add edx, WIO_RAP
in ax, dx
and eax, 0xffff
sub edx, WIO_RAP
 
ret
 
; eax - val
align 4
wio_write_rap:
 
add edx, WIO_RAP
out dx, ax
sub edx, WIO_RAP
 
ret
 
align 4
wio_reset:
 
push eax
add edx, WIO_RESET
in ax, dx
pop eax
sub edx, WIO_RESET
 
ret
 
 
 
; ecx - index
; return:
; eax - data
align 4
dwio_read_csr:
 
add edx, DWIO_RAP
mov eax, ecx
out dx, eax
add edx, DWIO_RDP - DWIO_RAP
in eax, dx
and eax, 0xffff
sub edx, DWIO_RDP
 
ret
 
 
; ecx - index
; eax - data
align 4
dwio_write_csr:
 
add edx, DWIO_RAP
xchg eax, ecx
out dx, eax
add edx, DWIO_RDP - DWIO_RAP
xchg eax, ecx
out dx, eax
sub edx, DWIO_RDP
 
ret
 
; ecx - index
; return:
; eax - data
align 4
dwio_read_bcr:
 
add edx, DWIO_RAP
mov eax, ecx
out dx, eax
add edx, DWIO_BDP - DWIO_RAP
in eax, dx
and eax, 0xffff
sub edx, DWIO_BDP
 
ret
 
 
; ecx - index
; eax - data
align 4
dwio_write_bcr:
 
add edx, DWIO_RAP
xchg eax, ecx
out dx, eax
add edx, DWIO_BDP - DWIO_RAP
xchg eax, ecx
out dx, eax
sub edx, DWIO_BDP
 
ret
 
align 4
dwio_read_rap:
 
add edx, DWIO_RAP
in eax, dx
and eax, 0xffff
sub edx, DWIO_RAP
 
ret
 
 
; eax - val
align 4
dwio_write_rap:
 
add edx, DWIO_RAP
out dx, eax
sub edx, DWIO_RAP
 
ret
 
align 4
dwio_reset:
 
push eax
add edx, DWIO_RESET
in eax, dx
pop eax
sub edx, DWIO_RESET
 
ret
 
 
align 4
mdio_read:
 
and ecx, 0x1f
mov ax, [device.phy]
and ax, 0x1f
shl ax, 5
or ax, cx
 
mov ecx, BCR_MIIADDR
call [device.write_bcr]
 
mov ecx, BCR_MIIDATA
call [device.read_bcr]
 
ret
 
 
align 4
mdio_write:
 
push eax
and ecx, 0x1f
mov ax, [device.phy]
and ax, 0x1f
shl ax, 5
or ax, cx
 
mov ecx, BCR_MIIADDR
call [device.write_bcr]
 
pop eax
mov ecx, BCR_MIIDATA
call [device.write_bcr]
 
ret
 
 
align 4
check_media:
 
DEBUGF 1, "check_media\n"
 
test [device.mii], 1
jnz mii_link_ok
 
mov ecx, BCR_LED0
call [device.read_bcr]
cmp eax, 0xc0
 
DEBUGF 1, "link status=0x%x\n", ax
 
ret
 
 
 
; End of code
 
align 4 ; Place all initialised data here
 
devices dd 0
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
my_service db 'PCnet',0 ; max 16 chars include zero
 
device_l2 db "PCnet/PCI 79C970",0
device_l4 db "PCnet/PCI II 79C970A",0
device_l5 db "PCnet/FAST 79C971",0
device_l6 db "PCnet/FAST+ 79C972",0
device_l7 db "PCnet/FAST III 79C973",0
device_l8 db "PCnet/Home 79C978",0
device_l9 db "PCnet/FAST III 79C975",0
 
options_mapping:
dd PORT_ASEL ; 0 Auto-select
dd PORT_AUI ; 1 BNC/AUI
dd PORT_AUI ; 2 AUI/BNC
dd PORT_ASEL ; 3 not supported
dd PORT_10BT or PORT_FD ; 4 10baseT-FD
dd PORT_ASEL ; 5 not supported
dd PORT_ASEL ; 6 not supported
dd PORT_ASEL ; 7 not supported
dd PORT_ASEL ; 8 not supported
dd PORT_MII ; 9 MII 10baseT
dd PORT_MII or PORT_FD ; 10 MII 10baseT-FD
dd PORT_MII ; 11 MII (autosel)
dd PORT_10BT ; 12 10BaseT
dd PORT_MII or PORT_100 ; 13 MII 100BaseTx
dd PORT_MII or PORT_100 or PORT_FD ; 14 MII 100BaseTx-FD
dd PORT_ASEL ; 15 not supported
 
include_debug_strings ; All data wich FDO uses will be included here
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/ethernet/rhine.asm
0,0 → 1,1679
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; rhine.asm ;;
;; ;;
;; Ethernet driver for Kolibri OS ;;
;; ;;
;; This driver is based on the via-rhine driver from ;;
;; the etherboot 5.0.6 project. The copyright statement is ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; Rewritten in flat assembler by Asper (asper.85@mail.ru) ;;
;; and hidnplayr (hidnplayr@gmail.com) ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 2
 
TX_RING_SIZE = 4
RX_RING_SIZE = 4
 
; max time out delay time
W_MAX_TIMEOUT = 0x0FFF
 
; Size of the in-memory receive ring.
RX_BUF_LEN_IDX = 3 ; 0==8K, 1==16K, 2==32K, 3==64K
RX_BUF_LEN = (8192 shl RX_BUF_LEN_IDX)
 
; PCI Tuning Parameters
; Threshold is bytes transferred to chip before transmission starts.
TX_FIFO_THRESH = 256 ; In bytes, rounded down to 32 byte units.
 
; The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024.
RX_FIFO_THRESH = 4 ; Rx buffer level before first PCI xfer.
RX_DMA_BURST = 4 ; Maximum PCI burst, '4' is 256 bytes
TX_DMA_BURST = 4
 
 
include '../proc32.inc'
include '../imports.inc'
include '../fdo.inc'
include '../netdrv.inc'
 
public START
public service_proc
public version
 
 
;**************************************************************************
; VIA Rhine Register Definitions
;**************************************************************************
byPAR0 = 0x00
byRCR = 0x06
byTCR = 0x07
byCR0 = 0x08
byCR1 = 0x09
byISR0 = 0x0c
byISR1 = 0x0d
byIMR0 = 0x0e
byIMR1 = 0x0f
byMAR0 = 0x10
byMAR1 = 0x11
byMAR2 = 0x12
byMAR3 = 0x13
byMAR4 = 0x14
byMAR5 = 0x15
byMAR6 = 0x16
byMAR7 = 0x17
dwCurrentRxDescAddr = 0x18
dwCurrentTxDescAddr = 0x1c
dwCurrentRDSE0 = 0x20
dwCurrentRDSE1 = 0x24
dwCurrentRDSE2 = 0x28
dwCurrentRDSE3 = 0x2c
dwNextRDSE0 = 0x30
dwNextRDSE1 = 0x34
dwNextRDSE2 = 0x38
dwNextRDSE3 = 0x3c
dwCurrentTDSE0 = 0x40
dwCurrentTDSE1 = 0x44
dwCurrentTDSE2 = 0x48
dwCurrentTDSE3 = 0x4c
dwNextTDSE0 = 0x50
dwNextTDSE1 = 0x54
dwNextTDSE2 = 0x58
dwNextTDSE3 = 0x5c
dwCurrRxDMAPtr = 0x60
dwCurrTxDMAPtr = 0x64
byMPHY = 0x6c
byMIISR = 0x6d
byBCR0 = 0x6e
byBCR1 = 0x6f
byMIICR = 0x70
byMIIAD = 0x71
wMIIDATA = 0x72
byEECSR = 0x74
byTEST = 0x75
byGPIO = 0x76
byCFGA = 0x78
byCFGB = 0x79
byCFGC = 0x7a
byCFGD = 0x7b
wTallyCntMPA = 0x7c
wTallyCntCRC = 0x7d
bySTICKHW = 0x83
byWOLcrClr = 0xA4
byWOLcgClr = 0xA7
byPwrcsrClr = 0xAC
 
;--------------------- Exioaddr Definitions -------------------------
 
; Bits in the RCR register
RCR_RRFT2 = 0x80
RCR_RRFT1 = 0x40
RCR_RRFT0 = 0x20
RCR_PROM = 0x10
RCR_AB = 0x08
RCR_AM = 0x04
RCR_AR = 0x02
RCR_SEP = 0x01
; Bits in the TCR register
TCR_RTSF = 0x80
TCR_RTFT1 = 0x40
TCR_RTFT0 = 0x20
TCR_OFSET = 0x08
TCR_LB1 = 0x04 ; loopback[1]
TCR_LB0 = 0x02 ; loopback[0]
; Bits in the CR0 register
CR0_RDMD = 0x40 ; rx descriptor polling demand
CR0_TDMD = 0x20 ; tx descriptor polling demand
CR0_TXON = 0x10
CR0_RXON = 0x08
CR0_STOP = 0x04 ; stop NIC, default = 1
CR0_STRT = 0x02 ; start NIC
CR0_INIT = 0x01 ; start init process
; Bits in the CR1 register
CR1_SFRST = 0x80 ; software reset
CR1_RDMD1 = 0x40 ; RDMD1
CR1_TDMD1 = 0x20 ; TDMD1
CR1_KEYPAG = 0x10 ; turn on par/key
CR1_DPOLL = 0x08 ; disable rx/tx auto polling
CR1_FDX = 0x04 ; full duplex mode
CR1_ETEN = 0x02 ; early tx mode
CR1_EREN = 0x01 ; early rx mode
; Bits in the CR register
CR_RDMD = 0x0040 ; rx descriptor polling demand
CR_TDMD = 0x0020 ; tx descriptor polling demand
CR_TXON = 0x0010
CR_RXON = 0x0008
CR_STOP = 0x0004 ; stop NIC, default = 1
CR_STRT = 0x0002 ; start NIC
CR_INIT = 0x0001 ; start init process
CR_SFRST = 0x8000 ; software reset
CR_RDMD1 = 0x4000 ; RDMD1
CR_TDMD1 = 0x2000 ; TDMD1
CR_KEYPAG = 0x1000 ; turn on par/key
CR_DPOLL = 0x0800 ; disable rx/tx auto polling
CR_FDX = 0x0400 ; full duplex mode
CR_ETEN = 0x0200 ; early tx mode
CR_EREN = 0x0100 ; early rx mode
; Bits in the IMR0 register
IMR0_CNTM = 0x80
IMR0_BEM = 0x40
IMR0_RUM = 0x20
IMR0_TUM = 0x10
IMR0_TXEM = 0x08
IMR0_RXEM = 0x04
IMR0_PTXM = 0x02
IMR0_PRXM = 0x01
; define imrshadow
IMRShadow = 0x5AFF
; Bits in the IMR1 register
IMR1_INITM = 0x80
IMR1_SRCM = 0x40
IMR1_NBFM = 0x10
IMR1_PRAIM = 0x08
IMR1_RES0M = 0x04
IMR1_ETM = 0x02
IMR1_ERM = 0x01
; Bits in the ISR register
ISR_INITI = 0x8000
ISR_SRCI = 0x4000
ISR_ABTI = 0x2000
ISR_NORBF = 0x1000
ISR_PKTRA = 0x0800
ISR_RES0 = 0x0400
ISR_ETI = 0x0200
ISR_ERI = 0x0100
ISR_CNT = 0x0080
ISR_BE = 0x0040
ISR_RU = 0x0020
ISR_TU = 0x0010
ISR_TXE = 0x0008
ISR_RXE = 0x0004
ISR_PTX = 0x0002
ISR_PRX = 0x0001
; Bits in the ISR0 register
ISR0_CNT = 0x80
ISR0_BE = 0x40
ISR0_RU = 0x20
ISR0_TU = 0x10
ISR0_TXE = 0x08
ISR0_RXE = 0x04
ISR0_PTX = 0x02
ISR0_PRX = 0x01
; Bits in the ISR1 register
ISR1_INITI = 0x80
ISR1_SRCI = 0x40
ISR1_NORBF = 0x10
ISR1_PKTRA = 0x08
ISR1_ETI = 0x02
ISR1_ERI = 0x01
; ISR ABNORMAL CONDITION
ISR_ABNORMAL = ISR_BE+ISR_RU+ISR_TU+ISR_CNT+ISR_NORBF+ISR_PKTRA
; Bits in the MIISR register
MIISR_MIIERR = 0x08
MIISR_MRERR = 0x04
MIISR_LNKFL = 0x02
MIISR_SPEED = 0x01
; Bits in the MIICR register
MIICR_MAUTO = 0x80
MIICR_RCMD = 0x40
MIICR_WCMD = 0x20
MIICR_MDPM = 0x10
MIICR_MOUT = 0x08
MIICR_MDO = 0x04
MIICR_MDI = 0x02
MIICR_MDC = 0x01
; Bits in the EECSR register
EECSR_EEPR = 0x80 ; eeprom programed status, 73h means programed
EECSR_EMBP = 0x40 ; eeprom embeded programming
EECSR_AUTOLD = 0x20 ; eeprom content reload
EECSR_DPM = 0x10 ; eeprom direct programming
EECSR_CS = 0x08 ; eeprom CS pin
EECSR_SK = 0x04 ; eeprom SK pin
EECSR_DI = 0x02 ; eeprom DI pin
EECSR_DO = 0x01 ; eeprom DO pin
; Bits in the BCR0 register
BCR0_CRFT2 = 0x20
BCR0_CRFT1 = 0x10
BCR0_CRFT0 = 0x08
BCR0_DMAL2 = 0x04
BCR0_DMAL1 = 0x02
BCR0_DMAL0 = 0x01
; Bits in the BCR1 register
BCR1_CTSF = 0x20
BCR1_CTFT1 = 0x10
BCR1_CTFT0 = 0x08
BCR1_POT2 = 0x04
BCR1_POT1 = 0x02
BCR1_POT0 = 0x01
; Bits in the CFGA register
CFGA_EELOAD = 0x80 ; enable eeprom embeded and direct programming
CFGA_JUMPER = 0x40
CFGA_MTGPIO = 0x08
CFGA_T10EN = 0x02
CFGA_AUTO = 0x01
; Bits in the CFGB register
CFGB_PD = 0x80
CFGB_POLEN = 0x02
CFGB_LNKEN = 0x01
; Bits in the CFGC register
CFGC_M10TIO = 0x80
CFGC_M10POL = 0x40
CFGC_PHY1 = 0x20
CFGC_PHY0 = 0x10
CFGC_BTSEL = 0x08
CFGC_BPS2 = 0x04 ; bootrom select[2]
CFGC_BPS1 = 0x02 ; bootrom select[1]
CFGC_BPS0 = 0x01 ; bootrom select[0]
; Bits in the CFGD register
CFGD_GPIOEN = 0x80
CFGD_DIAG = 0x40
CFGD_MAGIC = 0x10
CFGD_RANDOM = 0x08
CFGD_CFDX = 0x04
CFGD_CEREN = 0x02
CFGD_CETEN = 0x01
; Bits in RSR
RSR_RERR = 0x00000001
RSR_CRC = 0x00000002
RSR_FAE = 0x00000004
RSR_FOV = 0x00000008
RSR_LONG = 0x00000010
RSR_RUNT = 0x00000020
RSR_SERR = 0x00000040
RSR_BUFF = 0x00000080
RSR_EDP = 0x00000100
RSR_STP = 0x00000200
RSR_CHN = 0x00000400
RSR_PHY = 0x00000800
RSR_BAR = 0x00001000
RSR_MAR = 0x00002000
RSR_RXOK = 0x00008000
RSR_ABNORMAL = RSR_RERR+RSR_LONG+RSR_RUNT
; Bits in TSR
TSR_NCR0 = 0x00000001
TSR_NCR1 = 0x00000002
TSR_NCR2 = 0x00000004
TSR_NCR3 = 0x00000008
TSR_COLS = 0x00000010
TSR_CDH = 0x00000080
TSR_ABT = 0x00000100
TSR_OWC = 0x00000200
TSR_CRS = 0x00000400
TSR_UDF = 0x00000800
TSR_TBUFF = 0x00001000
TSR_SERR = 0x00002000
TSR_JAB = 0x00004000
TSR_TERR = 0x00008000
TSR_ABNORMAL = TSR_TERR+TSR_OWC+TSR_ABT+TSR_JAB+TSR_CRS
TSR_OWN_BIT = 0x80000000
 
CB_DELAY_LOOP_WAIT = 10 ; 10ms
; enabled mask value of irq
W_IMR_MASK_VALUE = 0x1BFF ; initial value of IMR
 
; Ethernet address filter type
PKT_TYPE_DIRECTED = 0x0001 ; obsolete, directed address is always accepted
PKT_TYPE_MULTICAST = 0x0002
PKT_TYPE_ALL_MULTICAST = 0x0004
PKT_TYPE_BROADCAST = 0x0008
PKT_TYPE_PROMISCUOUS = 0x0020
PKT_TYPE_LONG = 0x2000
PKT_TYPE_RUNT = 0x4000
PKT_TYPE_ERROR = 0x8000 ; accept error packets, e.g. CRC error
 
; Loopback mode
 
NIC_LB_NONE = 0x00
NIC_LB_INTERNAL = 0x01
NIC_LB_PHY = 0x02 ; MII or Internal-10BaseT loopback
 
PKT_BUF_SZ = 1536 ; Size of each temporary Rx buffer.
 
PCI_REG_MODE3 = 0x53
MODE3_MIION = 0x04 ; in PCI_REG_MOD3 OF PCI space
 
; VIA Rhine revisions
VT86C100A = 0x00
VTunknown0 = 0x20
VT6102 = 0x40
VT8231 = 0x50 ; Integrated MAC
VT8233 = 0x60 ; Integrated MAC
VT8235 = 0x74 ; Integrated MAC
VT8237 = 0x78 ; Integrated MAC
VTunknown1 = 0x7C
VT6105 = 0x80
VT6105_B0 = 0x83
VT6105L = 0x8A
VT6107 = 0x8C
VTunknown2 = 0x8E
VT6105M = 0x90
 
; Rx status bits
RX_SBITS_RERR = 1 shl 0
RX_SBITS_CRC_ERROR = 1 shl 1
RX_SBITS_FAE = 1 shl 2
RX_SBITS_FOV = 1 shl 3
RX_SBITS_TOOLONG = 1 shl 4
RX_SBITS_RUNT = 1 shl 5
RX_SBITS_SERR = 1 shl 6
RX_SBITS_BUFF = 1 shl 7
RX_SBITS_EDP = 1 shl 8
RX_SBITS_STP = 1 shl 9
RX_SBITS_CHN = 1 shl 10
RX_SBITS_PHY = 1 shl 11
RX_SBITS_BAR = 1 shl 12
RX_SBITS_MAR = 1 shl 13
RX_SBITS_RESERVED_1 = 1 shl 14
RX_SBITS_RXOK = 1 shl 15
RX_SBITS_FRAME_LENGTH = 0x7FF shl 16
RX_SBITS_RESERVED_2 = 0xF shl 27
RX_SBITS_OWN_BIT = 1 shl 31
 
; Rx control bits
RX_CBITS_RX_BUF_SIZE = 0x7FF
RX_CBITS_EXTEND_RX_BUF_SIZE = 0xF shl 11
RX_CBITS_RESERVED_1 = 0x1FFFF shl 15
 
; Tx status bits
TX_SBITS_NCR0 = 1 shl 0
TX_SBITS_NCR1 = 1 shl 1
TX_SBITS_NCR2 = 1 shl 2
TX_SBITS_NCR3 = 1 shl 3
TX_SBITS_COLS = 1 shl 4
TX_SBITS_RESERVED_1 = 1 shl 5
TX_SBITS_CDH = 1 shl 7
TX_SBITS_ABT = 1 shl 8
TX_SBITS_OWC = 1 shl 9
TX_SBITS_CRS = 1 shl 10
TX_SBITS_UDF = 1 shl 11
TX_SBITS_TBUFF = 1 shl 12
TX_SBITS_SERR = 1 shl 13
TX_SBITS_JAB = 1 shl 14
TX_SBITS_TERR = 1 shl 15
TX_SBITS_RESERVED_2 = 0x7FFF shl 16
TX_SBITS_OWN_BIT = 1 shl 31
 
; Tx control bits
TX_CBITS_TX_BUF_SIZE = 0x7FF
TX_CBITS_EXTEND_TX_BUF_SIZE = 0xF shl 11
TX_CBITS_CHN = 1 shl 15
TX_CBITS_CRC = 1 shl 16
TX_CBITS_RESERVED_1 = 0xF shl 17
TX_CBITS_STP = 1 shl 21
TX_CBITS_EDP = 1 shl 22
TX_CBITS_IC = 1 shl 23
TX_CBITS_RESERVED_2 = 0xFF shl 24
 
 
 
; Offsets to the device registers.
StationAddr = 0x00
RxConfig = 0x06
TxConfig = 0x07
ChipCmd = 0x08
IntrStatus = 0x0C
IntrEnable = 0x0E
MulticastFilter0 = 0x10
MulticastFilter1 = 0x14
RxRingPtr = 0x18
TxRingPtr = 0x1C
GFIFOTest = 0x54
MIIPhyAddr = 0x6C
MIIStatus = 0x6D
PCIBusConfig = 0x6E
MIICmd = 0x70
MIIRegAddr = 0x71
MIIData = 0x72
MACRegEEcsr = 0x74
ConfigA = 0x78
ConfigB = 0x79
ConfigC = 0x7A
ConfigD = 0x7B
RxMissed = 0x7C
RxCRCErrs = 0x7E
MiscCmd = 0x81
StickyHW = 0x83
IntrStatus2 = 0x84
WOLcrClr = 0xA4
WOLcgClr = 0xA7
PwrcsrClr = 0xAC
 
; Bits in the interrupt status/mask registers.
IntrRxDone = 0x0001
IntrRxErr = 0x0004
IntrRxEmpty = 0x0020
IntrTxDone = 0x0002
IntrTxError = 0x0008
IntrTxUnderrun = 0x0010
IntrPCIErr = 0x0040
IntrStatsMax = 0x0080
IntrRxEarly = 0x0100
IntrRxOverflow = 0x0400
IntrRxDropped = 0x0800
IntrRxNoBuf = 0x1000
IntrTxAborted = 0x2000
IntrLinkChange = 0x4000
IntrRxWakeUp = 0x8000
IntrNormalSummary = 0x0003
IntrAbnormalSummary = 0xC260
IntrTxDescRace = 0x080000 ; mapped from IntrStatus2
IntrTxErrSummary = 0x082218
 
DEFAULT_INTR = (IntrRxDone or IntrRxErr or IntrRxEmpty or IntrRxOverflow or IntrRxDropped or IntrRxNoBuf)
 
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.io_addr dd ?
.pci_dev dd ?
.pci_bus dd ?
.revision db ?
.irq_line db ?
.chip_id dw ?
 
.cur_rx dw ?
.cur_tx dw ?
.last_tx dw ?
 
rb 0x100-(($ - device) and 0xff) ; align 256
.tx_ring rb tx_head.sizeof*TX_RING_SIZE
 
rb 0x100-(($ - device) and 0xff) ; align 256
.rx_ring rb rx_head.sizeof*RX_RING_SIZE
 
.size = $ - device
 
end virtual
 
virtual at 0
rx_head:
.status dd ?
.control dd ?
.buff_addr dd ? ; address
.next_desc dd ? ;
 
.buff_addr_virt dd ?
rd 3 ; alignment
.sizeof:
end virtual
 
 
virtual at 0
tx_head:
.status dd ?
.control dd ?
.buff_addr dd ? ; address
.next_desc dd ? ;
 
.buff_addr_virt dd ?
rd 3 ; alignment
.sizeof:
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 @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
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, device.size, .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 io addres of the PCI device
 
PCI_find_io
 
; We've found the io 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.io_addr]:4
 
; Ok, the eth_device structure is ready, let's probe the device
;;; cli
 
call probe ; this function will output in eax
test eax, eax
jnz .err_sti ; 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
;;; sti
 
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_sti:
sti
 
.err:
stdcall KernelFree, ebx
 
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
 
 
probe:
 
mov eax, [device.io_addr]
DEBUGF 1, "Probing card at 0x%x\n", eax
 
; make the card a bus master
PCI_make_bus_master
 
; get device id
stdcall PciRead16, [device.pci_bus], [device.pci_dev], PCI_DEVICE_ID
mov [device.chip_id], ax
 
; get revision id.
PCI_find_rev
 
movzx eax, [device.revision]
DEBUGF 1, "Card revision = 0x%x\n", eax
 
; D-Link provided reset code (with comment additions)
cmp al, 0x40
jb .below_x40
 
mov ax, [device.chip_id]
DEBUGF 1, "Enabling Sticky Bit Workaround for Chip_id: 0x%x\n", ax
 
; clear sticky bit before reset & read ethernet address
set_io 0
set_io bySTICKHW
in al, dx
and al, 0xFC
out dx, al
 
; (bits written are cleared?)
; disable force PME-enable
set_io byWOLcgClr
mov al, 0x80
out dx, al
 
; disable power-event config bit
mov al, 0xFF
out dx, al
 
; clear power status (undocumented in vt6102 docs?)
set_io byPwrcsrClr
out dx, al
 
.below_x40:
 
; Reset the chip to erase previous misconfiguration.
set_io 0
set_io byCR0
mov ax, CR_SFRST
out dx, ax
 
; if vt3043 delay after reset
cmp [device.revision], 0x40
jae @f
mov esi, 2000 ; 2000ms
call Sleep
@@:
 
; polling till software reset complete
mov ecx, W_MAX_TIMEOUT
.poll_again:
in ax, dx
test ax, CR_SFRST
jz @f
loop .poll_again
DEBUGF 1, "Soft reset timeout!\n"
@@:
 
; issue AUTOLoad in EECSR to reload eeprom
set_io byEECSR
mov al, 0x20
out dx, al
 
; if vt3065 delay after reset
cmp [device.revision], 0x40
jb .not_vt3065
 
; delay 8ms to let MAC stable
mov esi, 8 ; 8ms
call Sleep
 
; for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA
; turned on. it makes MAC receive magic packet
; automatically. So, we turn it off. (D-Link)
 
set_io byCFGA
in al, dx
and al, 0xFE
out dx, al
 
; turn on bit2 in PCI configuration register 0x53 , only for 3065
stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REG_MODE3
or al, MODE3_MIION
stdcall PciWrite8, [device.pci_bus], [device.pci_dev], PCI_REG_MODE3, eax
.not_vt3065:
 
; back off algorithm, disable the right-most 4-bit off CFGD
set_io 0
set_io byCFGD
in al, dx
and al, not (CFGD_RANDOM or CFGD_CFDX or CFGD_CEREN or CFGD_CETEN)
out dx, al
 
; reload eeprom
call reload_eeprom
 
; read MAC
call read_mac
 
; restart MII auto-negotiation
stdcall WriteMII, 0, 1 shl 9, 1
 
DEBUGF 1, "Analyzing Media type, this may take several seconds"
 
mov ecx, 5
.read_again:
DEBUGF 1, "."
mov esi, 1
call Sleep
 
stdcall ReadMII, 1
test eax, 0x0020
jnz .read_done
loop .read_again
DEBUGF 1, "timeout!\n"
.read_done:
DEBUGF 1, " OK\n"
 
if DEBUG
 
set_io 0
set_io 0x6C
in al, dx
and eax, 0xFF
DEBUGF 1, "MII : Address %x\n", ax
 
stdcall ReadMII, 1
DEBUGF 1, "status 0x%x\n", ax
 
stdcall ReadMII, 4
DEBUGF 1, "advertising 0x%x\n", ax
 
stdcall ReadMII, 5
DEBUGF 1, "link 0x%x\n", ax
 
end if
 
; query MII to know LineSpeed, duplex mode
set_io 0
set_io MIIStatus
in al, dx
test al, MIISR_SPEED
jz .100mbps
DEBUGF 1, "Linespeed=10Mbs\n"
jmp @f
 
.100mbps:
DEBUGF 1, "Linespeed=100Mbs\n"
@@:
 
call QueryAuto
 
test eax, 1
jz .halfduplex
 
DEBUGF 1, "Fullduplex\n"
set_io 0
set_io byCR0
mov ax, CR_FDX
out dx, ax
jmp @f
 
.halfduplex:
DEBUGF 1, "Halfduplex\n"
@@:
 
; set MII 10 FULL ON, only apply in vt3043
cmp [device.chip_id], 0x3043
jne @f
stdcall WriteMII, 0x17, 1 shl 1, 1
@@:
 
; turn on MII link change
set_io 0
set_io byMIICR
in al, dx
and al, 0x7F
out dx, al
push eax
 
call MIIDelay
 
set_io byMIIAD
mov al, 0x41
out dx, al
 
call MIIDelay
 
pop eax
or al, 0x80
set_io byMIICR
out dx, al
 
;**************************************************************************;
;* ETH_RESET - Reset adapter *;
;**************************************************************************;
 
reset:
 
DEBUGF 1, "reset\n"
 
; attach int handler
 
movzx eax, [device.irq_line]
DEBUGF 2,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
test eax, eax
jnz @f
DEBUGF 2,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
; Soft reset the chip.
set_io 0
set_io byCR0
mov ax, CR_SFRST
out dx, ax
 
call MIIDelay
 
; Initialize rings
call init_ring
 
; Setup Multicast
call set_rx_mode
 
; set TCR RCR threshold to store and forward
set_io 0
set_io byBCR0
mov al, 0x3E
out dx, al
 
set_io byBCR1
mov al, 0x38
out dx, al
 
set_io byRCR
mov al, 0x2C
out dx, al
 
set_io byTCR
mov al, 0x60
out dx, al
 
; Set Fulldupex
 
call QueryAuto
test eax, eax ; full duplex?
jz @f
 
set_io 0
set_io byCFGD
mov al, CFGD_CFDX
out dx, al
 
set_io byCR0
mov ax, CR_FDX
out dx, ax
@@:
 
; ENABLE interrupts
set_io 0
set_io byIMR0
mov ax, DEFAULT_INTR
out dx, ax
 
; KICK NIC to WORK
 
set_io byCR0
in ax, dx
and ax, not CR_STOP
or ax, CR_STRT or CR_TXON or CR_RXON or CR_DPOLL
out dx, ax
 
; 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
 
; say reset was successfull
xor eax, eax
ret
 
 
 
align 4
unload:
 
call reset
push eax edx
DEBUGF 1, "rhine disable\n"
 
; Switch to loopback mode to avoid hardware races.
set_io 0
set_io byTCR
mov al, 0x61
out dx, al
 
; Stop the chip's Tx and Rx processes.
set_io byCR0
mov ax, CR_STOP
out dx, ax
pop edx eax
 
ret
 
 
 
 
align 4
reload_eeprom:
 
DEBUGF 1, "Reload eeprom\n"
 
set_io 0
set_io byEECSR
mov al, 0x20
out dx, al
; Typically 2 cycles to reload.
mov ecx, 150
.reload:
in al, dx
test al, 0x20
jz @f
loop .reload
DEBUGF 1, "Reload timeout!\n"
@@:
 
ret
 
; Initialize the Rx and Tx rings, along with various 'dev' bits.
align 4
init_ring:
 
DEBUGF 1, "Init ring\n"
 
lea edi, [device.rx_ring]
mov eax, edi
GetRealAddr
mov esi, eax
push esi
mov ecx, RX_RING_SIZE
.rx_init:
add esi, rx_head.sizeof
mov [edi + rx_head.status], RX_SBITS_OWN_BIT
mov [edi + rx_head.control], PKT_BUF_SZ
push ecx
stdcall KernelAlloc, PKT_BUF_SZ
pop ecx
mov [edi + rx_head.buff_addr_virt], eax
GetRealAddr
mov [edi + rx_head.buff_addr], eax ; buffer ptr
mov [edi + rx_head.next_desc], esi ; next head
add edi, rx_head.sizeof
dec ecx
jnz .rx_init
pop [edi - rx_head.sizeof + rx_head.next_desc] ; Mark the last entry as wrapping the ring.
 
 
lea edi, [device.tx_ring]
mov eax, edi
GetRealAddr
mov esi, eax
push esi
mov ecx, TX_RING_SIZE
.tx_init:
add esi, tx_head.sizeof
mov [edi + tx_head.status], 0
mov [edi + tx_head.control], 0x00E08000
mov [edi + tx_head.buff_addr], 0
mov [edi + tx_head.next_desc], esi
mov [edi + tx_head.buff_addr_virt], 0
add edi, tx_head.sizeof
dec ecx
jnz .tx_init
pop [edi - tx_head.sizeof + tx_head.next_desc] ; Mark the last entry as wrapping the ring.
 
; write Descriptors to MAC
lea eax, [device.rx_ring]
GetRealAddr
set_io 0
set_io dwCurrentRxDescAddr
out dx, eax
 
lea eax, [device.tx_ring]
GetRealAddr
set_io dwCurrentTxDescAddr
out dx, eax
 
xor eax, eax
mov [device.cur_rx], ax
mov [device.cur_tx], ax
mov [device.last_tx], ax
 
ret
 
 
align 4
QueryAuto:
 
DEBUGF 1, "Query Auto\n"
 
push ecx
stdcall ReadMII, 0x04 ; advertised
mov ecx, eax
stdcall ReadMII, 0x05
and ecx, eax
 
xor eax, eax
test ecx, 0x100
jnz .one
 
and ecx, 0x1C0
cmp ecx, 0x40
jne .zero
.one:
inc eax
DEBUGF 1, "AutoNego OK!\n"
.zero:
pop ecx
 
ret
 
 
proc ReadMII stdcall, byMIIIndex:dword
 
; DEBUGF 1, "ReadMII Index=%x\n", [byMIIIndex]
 
push esi ebx ecx edx
 
set_io 0
set_io byMIIAD
in al, dx
mov bl, al
 
set_io byMIICR
in al, dx
mov bh, al
and al, 0x7F
out dx, al
 
call MIIDelay
 
mov al, byte [byMIIIndex]
set_io byMIIAD
out dx, al
 
call MIIDelay
 
set_io byMIICR
in al, dx
or al, 0x40
out dx, al
 
mov ecx, 200
.read_again:
in al, dx
test al, 0x40
jz @f
 
mov esi, 10
call Sleep
dec ecx
jnz .read_again
DEBUGF 1, "\nReadMII timeout!\n"
@@:
 
call MIIDelay
 
set_io byMIIAD
in ax, dx
 
push eax
mov ax, bx
set_io byMIIAD
out dx, al
 
shr ax, 8
set_io byMIICR
out dx, al
 
call MIIDelay
 
pop eax
and eax, 0xFFFF
rol ax, 8 ;;;;; I dont know how or why but it seems needed...
 
pop edx ecx ebx esi
ret
endp
 
proc WriteMII stdcall, byMIISetByte:dword, byMIISetBit:dword, byMIIOP:dword
 
; DEBUGF 1, "WriteMII SetByte=%x SetBit=%x OP=%x\n", [byMIISetByte], [byMIISetBit], [byMIIOP]
 
push ebx eax ecx edx
 
set_io 0
set_io byMIIAD
in al, dx
mov bl, al
 
set_io byMIICR
in al, dx
mov bh, al
and al, 0x7F
out dx, al
 
call MIIDelay
 
mov al, byte [byMIISetByte]
set_io byMIIAD
out dx, al
 
call MIIDelay
 
set_io byMIICR
in al, dx
or al, 0x40
out dx, al
 
mov ecx, 200
.read_again0:
in al, dx
test al, 0x40
jz .done
 
mov esi, 10
call Sleep
dec ecx
jnz .read_again0
DEBUGF 1, "WriteMII timeout 1\n"
.done:
 
call MIIDelay
 
set_io wMIIDATA
in ax, dx
 
mov ecx, [byMIISetBit]
rol cx, 8 ;;;;;;;;;;;;;;;;; CHECKME
 
cmp byte [byMIIOP], 0
jne @f
not ecx
and ax, cx
jmp .end_mascarad
@@:
or ax, cx
.end_mascarad:
 
set_io wMIIDATA
out dx, ax
 
call MIIDelay
 
set_io byMIICR
in al, dx
or al, 0x20
out dx, al
 
mov ecx, 200
.read_again1:
in al, dx
test al, 0x20
jz @f
 
mov esi, 10
call Sleep
dec ecx
jnz .read_again1
DEBUGF 1, "WriteMII timeout 2\n"
@@:
 
call MIIDelay
 
mov ax, bx
and al, 0x7F
set_io byMIIAD
out dx, al
 
shr ax, 8
set_io byMIICR
out dx, al
 
call MIIDelay
 
pop edx ecx eax ebx
ret
endp
 
 
align 4
MIIDelay:
 
mov ecx, 0x7FFF
@@:
in al, 0x61
in al, 0x61
in al, 0x61
in al, 0x61
loop @b
 
ret
 
 
align 4
set_rx_mode:
 
DEBUGF 1, "Set RX mode\n"
 
; ! IFF_PROMISC
mov eax, 0xffffffff
set_io 0
set_io byMAR0
out dx, eax
 
set_io byMAR4
out dx, eax
 
set_io byRCR
mov al, 0x6C ;rx_mode = 0x0C;
out dx, al ;outb(0x60 /* thresh */ | rx_mode, byRCR );
 
ret
 
 
 
 
 
; Beware of PCI posted writes
macro IOSYNC
{
set_io StationAddr
in al, dx
}
 
 
 
align 4
read_mac:
 
DEBUGF 1, "Ethernet Address: "
 
lea edi, [device.mac]
set_io 0
set_io byPAR0
mov ecx, 6
.next:
in al, dx
stosb
DEBUGF 1, "-%x", al
inc edx
dec ecx
jnz .next
DEBUGF 1, "\n"
 
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
 
movzx eax, [device.cur_tx]
mov ecx, tx_head.sizeof
mul ecx
lea edi, [device.tx_ring]
add edi, eax
 
cmp [edi + tx_head.buff_addr_virt], 0
jne .fail
 
mov eax, [esp+4]
mov [edi + tx_head.buff_addr_virt], eax
GetRealAddr
mov [edi + tx_head.buff_addr], eax
mov ecx, [esp+8]
and ecx, TX_CBITS_TX_BUF_SIZE
or ecx, 0x00E08000
mov [edi + tx_head.control], ecx
or [edi + tx_head.status], TX_SBITS_OWN_BIT
 
set_io 0
set_io byCR1
in al, dx
or al, CR1_TDMD1
out dx, al
 
inc [device.cur_tx]
and [device.cur_tx], TX_RING_SIZE-1
 
;outw(IMRShadow,byIMR0); ;
 
; Update stats
inc [device.packets_tx]
mov ecx, [esp+8] ;;;;;
add dword [device.bytes_tx], ecx
adc dword [device.bytes_tx + 4], 0
 
ret 8
 
.fail:
DEBUGF 1, "Failed!\n"
 
ret 8
 
 
 
 
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_handler:
 
push ebx esi edi
 
DEBUGF 1,"\n%s int ", 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]
 
set_io 0
set_io IntrStatus
in ax, dx
out dx, ax ; send it back to ACK
test ax, ax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
pop edi esi ebx
xor eax, eax
 
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
 
 
 
.got_it:
 
DEBUGF 1, "status=0x%x\n", ax
 
push ax
 
test ax, IntrRxDone
jz .not_RX
 
push ebx
.more_RX:
pop ebx
 
; Get the current descripter pointer
 
movzx eax, [device.cur_rx]
mov ecx, rx_head.sizeof
mul ecx
lea edi, [device.rx_ring]
add edi, eax
 
; Check it's status
 
test [edi + rx_head.status], RX_SBITS_OWN_BIT
jnz .not_bit_own
 
DEBUGF 1, "Packet status = 0x%x\n", [edi + rx_head.status]
 
; TODO: check error bits
 
; get length
 
mov ecx, [edi + rx_head.status]
and ecx, RX_SBITS_FRAME_LENGTH
shr ecx, 16
sub ecx, 4 ; We dont want CRC
 
; Update stats
 
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
inc [device.packets_rx]
 
; Push packet size and pointer, kernel will need it..
 
push ebx
push .more_RX ; return ptr
 
push ecx ; full packet size
push [edi + rx_head.buff_addr_virt]
 
; reset the RX descriptor
 
push edi
stdcall KernelAlloc, PKT_BUF_SZ
pop edi
mov [edi + rx_head.buff_addr_virt], eax
GetRealAddr
mov [edi + rx_head.buff_addr], eax
mov [edi + rx_head.status], RX_SBITS_OWN_BIT
 
; Use next descriptor next time
 
inc [device.cur_rx]
and [device.cur_rx], RX_RING_SIZE - 1
 
; At last, send packet to kernel
 
jmp Eth_input
 
.not_bit_own:
.not_RX:
 
pop ax
 
test ax, IntrTxDone
jz .not_TX
 
.loop_tx:
movzx eax, [device.last_tx]
mov ecx, tx_head.sizeof
mul ecx
lea edi, [device.tx_ring]
add edi, eax
 
test [edi + tx_head.status], TX_SBITS_OWN_BIT
jnz .not_TX
 
cmp [edi + tx_head.buff_addr_virt], 0
je .not_TX
 
DEBUGF 1,"Freeing buffer 0x%x\n", [edi + tx_head.buff_addr_virt]
 
push [edi + tx_head.buff_addr_virt]
mov [edi + tx_head.buff_addr_virt], 0
call KernelFree
 
inc [device.last_tx]
and [device.last_tx], TX_RING_SIZE - 1
 
jmp .loop_tx
 
.not_TX:
 
; On Rhine-II, Bit 3 indicates Tx descriptor write-back race.
if 0
cmp [device.chip_id], 0x3065 ;if (tp->chip_id == 0x3065)
jne @f
push ax
xor eax, eax
set_io IntrStatus2
in al, dx ; intr_status |= inb(nic->ioaddr + IntrStatus2) << 16;
shl eax, 16
pop ax
@@:
end if
 
if 0
 
; Acknowledge all of the current interrupt sources ASAP.
xor ecx, ecx
test eax, IntrTxDescRace
jz @f
set_io 0
set_io IntrStatus2
push ax
mov al, 0x08
out dx, al
pop ax
@@:
set_io 0
set_io IntrStatus
out dx, ax
IOSYNC
 
end if
 
pop edi esi ebx
xor eax, eax
inc eax
 
ret
 
 
 
 
 
; End of code
 
section '.data' data readable writable align 16 ; place all uninitialized data here
align 4 ; Place all initialised data here
 
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'RHINE',0 ; max 16 chars including zero
 
devicelist:
dd 0x30431106, rhine_3043;, RHINE_IOTYPE, RHINE_I_IOSIZE, CanHaveMII or ReqTxAlign or HasV1TxStat
dd 0x61001106, rhine_6100;, RHINE_IOTYPE, RHINE_I_IOSIZE, CanHaveMII or ReqTxAlign or HasV1TxStat
dd 0x30651106, rhine_6102;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL
dd 0x31061106, rhine_6105;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL
; Duplicate entry, with 'M' features enabled.
dd 0x31061106, rhine_6105;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL or HasIPChecksum or HasVLAN
dd 0x30531106, rhine_3053;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL
dd 0
 
rhine_3043 db "VIA VT3043 Rhine", 0
rhine_6100 db "VIA VT86C100A Rhine", 0
rhine_6102 db "VIA VT6102 Rhine-II", 0
rhine_6105 db "VIA VT6105LOM Rhine-III (3106)", 0
rhine_3053 db "VIA VT6105M Rhine-III (3053 prototype)", 0
 
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
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/ethernet/sis900.asm
0,0 → 1,1222
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Ethernet driver for KolibriOS ;;
;; This is an adaptation of MenuetOS driver with minimal changes. ;;
;; Changes were made by CleverMouse. Original copyright follows. ;;
;; ;;
;; This driver is based on the SIS900 driver from ;;
;; the etherboot 5.0.6 project. The copyright statement is ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; remaining parts Copyright 2004 Jason Delozier, ;;
;; cordata51@hotmail.com ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;; Updates: ;;
;; Revision Look up table and SIS635 Mac Address by Jarek Pelczar ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
 
NUM_RX_DESC = 4 ; Number of RX descriptors
NUM_TX_DESC = 4 ; Number of TX descriptors
RX_BUFF_SZ = 1520 ; Buffer size for each Rx buffer
TX_BUFF_SZ = 1516 ; Buffer size for each Tx buffer
MAX_ETH_FRAME_SIZE = 1516
 
API_VERSION = 0x01000100
DRIVER_VERSION = 5
 
MAX_DEVICES = 16
 
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 2
 
DSIZE = 0x00000fff
CRC_SIZE = 4
RFADDR_shift = 16
 
; If you are having problems sending/receiving packet try changing the
; Max DMA Burst, Possible settings are as follows:
;
; 0x00000000 = 512 bytes
; 0x00100000 = 4 bytes
; 0x00200000 = 8 bytes
; 0x00300000 = 16 bytes
; 0x00400000 = 32 bytes
; 0x00500000 = 64 bytes
; 0x00600000 = 128 bytes
; 0x00700000 = 256 bytes
 
RX_DMA = 0x00600000
TX_DMA = 0x00600000
 
;-------------------------------------------------------------------------------------------------
; Symbolic offsets to registers.
cr = 0x0 ; Command Register
cfg = 0x4 ; Configuration Register
mear = 0x8 ; EEPROM Access Register
ptscr = 0xc ; PCI Test Control Register
isr = 0x10 ; Interrupt Status Register
imr = 0x14 ; Interrupt Mask Register
ier = 0x18 ; Interrupt Enable Register
epar = 0x18 ; Enhanced PHY Access Register
txdp = 0x20 ; Transmit Descriptor Pointer Register
txcfg = 0x24 ; Transmit Configuration Register
rxdp = 0x30 ; Receive Descriptor Pointer Register
rxcfg = 0x34 ; Receive Configuration Register
flctrl = 0x38 ; Flow Control Register
rxlen = 0x3c ; Receive Packet Length Register
rfcr = 0x48 ; Receive Filter Control Register
rfdr = 0x4C ; Receive Filter Data Register
pmctrl = 0xB0 ; Power Management Control Register
pmer = 0xB4 ; Power Management Wake-up Event Register
 
; Command Register Bits
RELOAD = 0x00000400
ACCESSMODE = 0x00000200
RESET = 0x00000100
SWI = 0x00000080
RxRESET = 0x00000020
TxRESET = 0x00000010
RxDIS = 0x00000008
RxENA = 0x00000004
TxDIS = 0x00000002
TxENA = 0x00000001
 
; Configuration Register Bits
DESCRFMT = 0x00000100 ; 7016 specific
REQALG = 0x00000080
SB = 0x00000040
POW = 0x00000020
EXD = 0x00000010
PESEL = 0x00000008
LPM = 0x00000004
BEM = 0x00000001
RND_CNT = 0x00000400
FAIR_BACKOFF = 0x00000200
EDB_MASTER_EN = 0x00002000
 
; Eeprom Access Reigster Bits
MDC = 0x00000040
MDDIR = 0x00000020
MDIO = 0x00000010 ; 7016 specific
EECS = 0x00000008
EECLK = 0x00000004
EEDO = 0x00000002
EEDI = 0x00000001
 
; TX Configuration Register Bits
ATP = 0x10000000 ; Automatic Transmit Padding
MLB = 0x20000000 ; Mac Loopback Enable
HBI = 0x40000000 ; HeartBeat Ignore (Req for full-dup)
CSI = 0x80000000 ; CarrierSenseIgnore (Req for full-du
 
; RX Configuration Register Bits
AJAB = 0x08000000 ;
ATX = 0x10000000 ; Accept Transmit Packets
ARP = 0x40000000 ; accept runt packets (<64bytes)
AEP = 0x80000000 ; accept error packets
 
; Interrupt Register Bits
WKEVT = 0x10000000
TxPAUSEEND = 0x08000000
TxPAUSE = 0x04000000
TxRCMP = 0x02000000 ; Transmit Reset Complete
RxRCMP = 0x01000000 ; Receive Reset Complete
DPERR = 0x00800000
SSERR = 0x00400000
RMABT = 0x00200000
RTABT = 0x00100000
RxSOVR = 0x00010000
HIBERR = 0x00008000
SWINT = 0x00001000
MIBINT = 0x00000800
TxURN = 0x00000400
TxIDLE = 0x00000200
TxERR = 0x00000100
TxDESC = 0x00000080
TxOK = 0x00000040
RxORN = 0x00000020
RxIDLE = 0x00000010
RxEARLY = 0x00000008
RxERR = 0x00000004
RxDESC = 0x00000002
RxOK = 0x00000001
 
; Interrupt Enable Register Bits
IE = RxOK + TxOK
 
; Revision ID
SIS900B_900_REV = 0x03
SIS630A_900_REV = 0x80
SIS630E_900_REV = 0x81
SIS630S_900_REV = 0x82
SIS630EA1_900_REV = 0x83
SIS630ET_900_REV = 0x84
SIS635A_900_REV = 0x90
SIS900_960_REV = 0x91
 
; Receive Filter Control Register Bits
RFEN = 0x80000000 ; enable
RFAAB = 0x40000000 ; accept all broadcasts
RFAAM = 0x20000000 ; accept all multicasts
RFAAP = 0x10000000 ; accept all packets
 
; Reveive Filter Data Mask
RFDAT = 0x0000FFFF
 
; Eeprom Address
EEPROMSignature = 0x00
EEPROMVendorID = 0x02
EEPROMDeviceID = 0x03
EEPROMMACAddr = 0x08
EEPROMChecksum = 0x0b
 
; The EEPROM commands include the alway-set leading bit.
EEread = 0x0180
EEwrite = 0x0140
EEerase = 0x01C0
EEwriteEnable = 0x0130
EEwriteDisable = 0x0100
EEeraseAll = 0x0120
EEwriteAll = 0x0110
EEaddrMask = 0x013F
EEcmdShift = 16
 
; For SiS962 or SiS963, request the eeprom software access
EEREQ = 0x00000400
EEDONE = 0x00000200
EEGNT = 0x00000100
 
 
include '../proc32.inc'
include '../imports.inc'
include '../fdo.inc'
include '../netdrv.inc'
 
public START
public version
 
 
virtual at ebx
device:
 
ETH_DEVICE
 
.io_addr dd ?
.pci_bus dd ?
.pci_dev dd ?
.irq_line db ?
.cur_rx db ?
.cur_tx db ?
.last_tx db ?
.pci_revision db ?
.table_entries db ?
rb 2 ; alignment
 
.txd rd (4 * NUM_TX_DESC)
.rxd rd (4 * NUM_RX_DESC)
 
.size = $ - device
 
end virtual
 
macro ee_delay {
push eax
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
pop eax
}
 
 
section '.flat' code readable align 16
 
; Driver entry point - register our service when the driver is loading.
; TODO: add needed operations when unloading
START:
cmp dword [esp+4], 1
jne .exit
stdcall RegService, my_service, service_proc
ret 4
.exit:
xor eax, eax
ret 4
 
; Service procedure for the driver - handle all I/O requests for the driver.
; Currently handled requests are: SRV_GETVERSION = 0 and SRV_HOOK = 1.
service_proc:
; 1. Get parameter from the stack: [esp+4] is the first parameter,
; pointer to IOCTL structure.
mov edx, [esp+4] ; edx -> IOCTL
; 2. Get request code and select a handler for the code.
mov eax, [IOCTL.io_code]
test eax, eax ; check for SRV_GETVERSION
jnz @f
; 3. This is SRV_GETVERSION request, no input, 4 bytes output, API_VERSION.
; 3a. Output size must be at least 4 bytes.
cmp [IOCTL.out_size], 4
jb .fail
; 3b. Write result to the output buffer.
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
; 3c. Return success.
xor eax, eax
ret 4
@@:
dec eax ; check for SRV_HOOK
jnz .fail
; 4. This is SRV_HOOK request, input defines the device to hook, no output.
; 4a. The driver works only with PCI devices,
; so input must be at least 3 bytes long.
cmp [IOCTL.inp_size], 3
jb .fail
; 4b. First byte of input is bus type, 1 stands for PCI.
mov eax, [IOCTL.input]
cmp byte [eax], 1
jne .fail
; 4c. Second and third bytes of the input define the device: bus and dev.
; Word in bx holds both bytes.
mov bx, [eax+1]
; 4d. Check if the device was already hooked,
; scan through the list of known devices.
; 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 @f
cmp ah, byte[device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
loop .nextdevice
; 4e. This device doesn't have its own eth_device structure yet, let's create one
.firstdevice:
; 4f. Check that we have place for new device.
cmp [devices], MAX_DEVICES
jae .fail
; 4g. Allocate memory for device descriptor and receive+transmit buffers.
; 4h. Zero the structure.
allocate_and_clear ebx, device.size, .fail
; 4i. Save PCI coordinates
mov eax, [IOCTL.input]
movzx ecx, byte[eax+1]
mov [device.pci_bus], ecx
movzx ecx, byte[eax+2]
mov [device.pci_dev], ecx
; 4j. 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
 
; 4k. Now, it's time to find the base io addres of the PCI device
; TODO: implement check if bus and dev exist on this machine
 
; Now, it's time to find the base io addres of the PCI device
PCI_find_io
 
; We've found the io address, find IRQ now
PCI_find_irq
 
; 4m. Add new device to the list (required for int_handler).
mov eax, [devices]
mov [device_list+4*eax], ebx
inc [devices]
 
; 4m. Ok, the eth_device structure is ready, let's probe the device
call probe
test eax, eax
jnz .destroy
; 4n. If device was successfully initialized, register it for the kernel.
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
cmp eax, -1
je .destroy
 
ret 4
 
; 5. If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
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
ret 4
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
dec [devices]
; todo: reset device into virgin state
 
.err:
stdcall KernelFree, ebx
 
.fail:
xor eax, eax
ret 4
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
unload:
; TODO: (in this particular order)
;
; - Stop the device
; - Detach int handler
; - Remove device from local list
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
 
or eax,-1
 
ret
 
;***************************************************************************
;
; probe
;
; checks the card and enables it
;
; TODO: probe mii transceivers
;
;***************************************************************************
align 4
probe:
DEBUGF 1, "Probe\n"
 
; wake up device CHECKME
stdcall PciWrite8, [device.pci_bus], [device.pci_dev], 0x40, 0
 
PCI_make_bus_master
 
PCI_adjust_latency 64
 
; Get Card Revision
stdcall PciRead8, [device.pci_bus], [device.pci_dev], 0x08
mov [device.pci_revision], al ; save the revision for later use
 
; Look up through the specific_table
mov esi, specific_table
.tableloop:
cmp dword [esi], 0 ; Check if we reached end of the list
je .notsupported
cmp al, [esi] ; Check if revision is OK
je .ok
add esi, 12 ; Advance to next entry
jmp .tableloop
 
.ok:
 
call dword[esi + 4] ; "get MAC" function
 
; Set table entries
mov [device.table_entries], 16
cmp [device.pci_revision], SIS635A_900_REV
jae @f
cmp [device.pci_revision], SIS900B_900_REV
je @f
mov [device.table_entries], 8
@@:
 
; TODO: Probe for mii transceiver
 
jmp reset
 
.notsupported:
DEBUGF 1, "Device not supported\n"
or eax, -1
 
ret
 
reset:
 
DEBUGF 1, "reset\n"
 
movzx eax, [device.irq_line]
stdcall AttachIntHandler, eax, int_handler, 0
 
;--------------------------------------------
; Disable Interrupts and reset Receive Filter
 
set_io 0
set_io ier
xor eax, eax
out dx, eax
 
set_io imr
out dx, eax
 
set_io rfcr
out dx, eax
 
;-----------
; Reset Card
 
set_io cr
in eax, dx ; Get current Command Register
or eax, RESET + RxRESET + TxRESET ; set flags
out dx, eax ; Write new Command Register
 
;----------
; Wait loop
 
set_io isr
mov ecx, 1000
.loop:
dec ecx
jz .fail
in eax, dx ; read interrupt status
test eax, TxRCMP + RxRCMP
jz .loop
DEBUGF 1, "status=%x\n", eax
 
;------------------------------------------------------
; Set Configuration Register depending on Card Revision
 
set_io cfg
mov eax, PESEL ; Configuration Register Bit
cmp [device.pci_revision], SIS635A_900_REV
je .match
cmp [device.pci_revision], SIS900B_900_REV ; Check card revision
jne .done
.match: ; Revision match
or eax, RND_CNT ; Configuration Register Bit
.done:
out dx, eax
 
DEBUGF 1, "Initialising RX Filter\n"
 
; Get Receive Filter Control Register
set_io rfcr
in eax, dx
push eax
 
; disable packet filtering before setting filter
and eax, not RFEN
out dx, eax
 
; load MAC addr to filter data register
xor ecx, ecx
.macloop:
mov eax, ecx
set_io 0
set_io rfcr
shl eax, 16 ; high word of eax tells card which mac byte to write
out dx, eax ;
set_io rfdr
mov ax, word [device.mac + ecx*2] ; Get Mac ID word
out dx, ax ; Send Mac ID
inc cl ; send next word
cmp cl, 3 ; more to send?
jne .macloop
 
; enable packet filtering
pop eax ; old register value
set_io rfcr
or eax, RFEN ; enable filtering
out dx, eax ; set register
 
DEBUGF 1, "Initialising TX Descriptors\n"
 
mov ecx, NUM_TX_DESC
lea esi, [device.txd]
.txdescloop:
lea eax, [esi + 16] ; next ptr
GetRealAddr
mov dword [esi], eax ; link to next desc
mov dword [esi + 4], 0 ; status field
mov dword [esi + 8], 0 ; ptr to buffer
add esi, 16
dec ecx
jnz .txdescloop
 
lea eax, [device.txd]
GetRealAddr
mov dword [esi - 16], eax ; correct last descriptor link ptr
 
set_io txdp ; TX Descriptor Pointer
; lea eax, [device.txd]
; GetRealAddr
out dx, eax
 
mov [device.cur_tx], 0 ; Set current tx descriptor to 0
mov [device.last_tx], 0
 
DEBUGF 1, "Initialising RX Descriptors\n"
 
mov ecx, NUM_RX_DESC
lea esi, [device.rxd]
.rxdescloop:
lea eax, [esi + 16] ; next ptr
GetRealAddr
mov dword [esi], eax
mov dword [esi + 4], RX_BUFF_SZ ; size
 
push ecx esi
stdcall KernelAlloc, RX_BUFF_SZ
pop esi ecx
test eax, eax
jz .fail
mov dword [esi + 12], eax ; address
GetRealAddr
mov dword [esi + 8], eax ; real address
add esi, 16
dec ecx
jnz .rxdescloop
 
lea eax, [device.rxd]
GetRealAddr
mov dword [esi - 16], eax ; correct last descriptor link ptr
 
set_io 0
set_io rxdp
; lea eax, [device.rxd]
; GetRealAddr
out dx, eax
 
mov [device.cur_rx], 0 ; Set current rx descriptor to 0
 
DEBUGF 1, "setting RX mode\n"
 
xor cl, cl
.rxfilterloop:
set_io 0
set_io rfcr ; Receive Filter Control Reg offset
mov eax, 4 ; determine table entry
add al, cl
shl eax, 16
out dx, eax ; tell card which entry to modify
 
set_io rfdr ; Receive Filter Control Reg offset
mov eax, 0xffff ; entry value
out dx, ax ; write value to table in card
 
inc cl ; next entry
cmp cl, [device.table_entries]
jb .rxfilterloop
 
set_io rfcr ; Receive Filter Control Register offset
mov eax, RFAAB + RFAAM + RFAAP + RFEN
out dx, eax
 
set_io rxcfg ; Receive Config Register offset
mov eax, ATX + RX_DMA + 2 ; 0x2 : RX Drain Threshold = 8*8=64 bytes
out dx, eax
 
DEBUGF 1, "setting TX mode\n"
 
set_io txcfg ; Transmit config Register offset
mov eax, ATP + HBI + CSI + TX_DMA + 0x120
; TX Fill threshold = 0x100
; TX Drain Threshold = 0x20
out dx, eax
 
DEBUGF 1, "Enabling interrupts\n"
 
set_io imr
mov eax, IE ; Interrupt enable mask
out dx, eax
 
set_io cr
in eax, dx
or eax, RxENA ; Enable Receive
out dx, eax
 
set_io ier ; Interrupt enable
mov eax, 1
out dx, eax
 
mov [device.mtu], 1514
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
xor eax, eax
ret
 
.fail:
DEBUGF 1, "Resetting device failed\n"
or eax, -1
 
ret
 
 
;***************************************************************************
;
; SIS960_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
;
; SiS962 or SiS963 model, use EEPROM to store MAC address.
; EEPROM is shared by LAN and 1394.
; When access EEPROM, send EEREQ signal to hardware first, and wait for EEGNT.
; If EEGNT is ON, EEPROM is permitted to be accessed by LAN, otherwise is not.
; After MAC address is read from EEPROM, send
; EEDONE signal to refuse EEPROM access by LAN.
; The EEPROM map of SiS962 or SiS963 is different to SiS900.
; The signature field in SiS962 or SiS963 spec is meaningless.
;
; Return 0 is EAX = failure
;
;***************************************************************************
align 4
SIS960_get_mac_addr:
DEBUGF 1, "SIS960 - get mac: "
 
;-------------------------------
; Send Request for eeprom access
 
set_io 0
set_io mear ; Eeprom access register
mov eax, EEREQ ; Request access to eeprom
out dx, eax ; Send request
 
;-----------------------------------------------------
; Loop 4000 times and if access not granted, error out
 
mov ecx, 4000
.loop:
in eax, dx ; get eeprom status
test eax, EEGNT ; see if eeprom access granted flag is set
jnz .got_access ; if it is, go access the eeprom
loop .loop ; else keep waiting
 
DEBUGF 1, "Access to EEprom failed!\n", 0
 
set_io mear ; Eeprom access register
mov eax, EEDONE ; tell eeprom we are done
out dx, eax
 
or eax, -1 ; error
ret
 
.got_access:
 
;------------------------------------------
; EEprom access granted, read MAC from card
 
; zero based so 3-16 bit reads will take place
 
mov ecx, 2
.read_loop:
mov eax, EEPROMMACAddr ; Base Mac Address
add eax, ecx ; Current Mac Byte Offset
push ecx
call read_eeprom ; try to read 16 bits
pop ecx
mov word [device.mac+ecx*2], ax ; save 16 bits to the MAC ID varible
dec ecx ; one less word to read
jns .read_loop ; if more read more
mov eax, 1 ; return non-zero indicating success
 
DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
;-------------------------------------
; Tell EEPROM We are Done Accessing It
 
.done:
set_io 0
set_io mear ; Eeprom access register
mov eax, EEDONE ; tell eeprom we are done
out dx, eax
 
xor eax, eax ; ok
ret
 
 
 
 
;***************************************************************************
;
; get_mac_addr: - Get MAC address for stand alone SiS900 model
;
; Older SiS900 and friends, use EEPROM to store MAC address.
;
;***************************************************************************
align 4
SIS900_get_mac_addr:
DEBUGF 1, "SIS900 - get mac: "
 
;------------------------------------
; check to see if we have sane EEPROM
 
mov eax, EEPROMSignature ; Base Eeprom Signature
call read_eeprom ; try to read 16 bits
cmp ax, 0xffff
je .err
test ax, ax
je .err
 
;-----------
; Read MacID
 
; zero based so 3-16 bit reads will take place
 
mov ecx, 2
.loop:
mov eax, EEPROMMACAddr ; Base Mac Address
add eax, ecx ; Current Mac Byte Offset
push ecx
call read_eeprom ; try to read 16 bits
pop ecx
mov word [device.mac+ecx*2], ax ; save 16 bits to the MAC ID storage
dec ecx ; one less word to read
jns .loop ; if more read more
 
DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
xor eax, eax
ret
 
 
.err:
DEBUGF 1, "Access to EEprom failed!\n", 0
 
or eax, -1
ret
 
 
;***************************************************************************
;
; Get_Mac_SIS635_900_REV: - Get MAC address for model 635
;
;***************************************************************************
align 4
Get_Mac_SIS635_900_REV:
DEBUGF 1, "SIS635 - get mac: "
 
set_io 0
set_io rfcr
in eax, dx
mov esi, eax
 
set_io cr
or eax, RELOAD
out dx, eax
 
xor eax, eax
out dx, eax
 
;-----------------------------------------------
; Disable packet filtering before setting filter
 
set_io rfcr
mov eax, esi
and eax, not RFEN
out dx, eax
 
;---------------------------------
; Load MAC to filter data register
 
xor ecx, ecx
lea edi, [device.mac]
.loop:
set_io 0
set_io rfcr
mov eax, ecx
shl eax, RFADDR_shift
out dx, eax
 
set_io rfdr
in ax, dx
stosw
inc ecx
cmp ecx, 3
jb .loop
 
;------------------------
; Enable packet filtering
 
set_io rfcr
mov eax, esi
or eax, RFEN
out dx, eax
 
DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
xor eax, eax
ret
 
;***************************************************************************
;
; read_eeprom
;
; reads and returns a given location from EEPROM
;
; IN: si = addr
; OUT: ax = data
;
;***************************************************************************
align 4
read_eeprom:
 
set_io 0
set_io mear
 
xor eax, eax ; start send
out dx, eax
ee_delay
 
or eax, EECLK
out dx, eax
ee_delay
 
;------------------------------------
; Send the read command
 
or esi, EEread
mov ecx, 1 shl 9
 
.loop:
mov eax, EECS
test esi, ecx
jz @f
or eax, EEDI
@@:
out dx, eax
ee_delay
 
or eax, EECLK
out dx, eax
ee_delay
 
shr esi, 1
jnc .loop
 
mov eax, EECS
out dx, eax
ee_delay
 
;------------------------
; Read 16-bits of data in
 
xor esi, esi
mov cx, 16
.loop2:
mov eax, EECS
out dx, eax
ee_delay
 
or eax, EECLK
out dx, eax
ee_delay
 
in eax, dx
shl esi, 1
test eax, EEDO
jz @f
inc esi
@@:
loop .loop2
 
;----------------------------
; Terminate the EEPROM access
 
xor eax, eax
out dx, eax
ee_delay
 
mov eax, EECLK
out dx, eax
ee_delay
 
movzx eax, si
 
ret
 
 
 
align 4
write_mac:
DEBUGF 1,'Setting MAC is not supported for SIS900 card.\n'
add esp, 6
ret
 
 
 
 
;***************************************************************************
; Function
; transmit
; Description
; Transmits a packet of data via the ethernet card
; buffer pointer in [esp+4]
; size of buffer in [esp+8]
; pointer to device structure in ebx
;
;***************************************************************************
align 4
transmit:
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
mov eax, [esp+4]
DEBUGF 1,"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], MAX_ETH_FRAME_SIZE
ja .error
cmp dword [esp + 8], 60
jb .error
 
movzx ecx, [device.cur_tx]
shl ecx, 4 ; *16
lea ecx, [device.txd + ecx]
 
test dword [ecx + 4], 0x80000000 ; card owns descriptor ?
jnz .error
 
mov eax, [esp + 4]
mov dword [ecx + 12], eax
GetRealAddr
mov dword [ecx + 8], eax ; buffer address
 
mov eax, [esp + 8]
and eax, DSIZE
or eax, 0x80000000 ; card owns descriptor
mov dword [ecx + 4], eax ; status field
 
set_io 0
set_io cr
in eax, dx
or eax, TxENA ; Enable the transmit state machine
out dx, eax
 
inc [device.cur_tx]
and [device.cur_tx], NUM_TX_DESC-1
 
; update stats
mov ecx, [esp + 8]
inc [device.packets_tx]
add dword [device.bytes_tx], ecx
adc dword [device.bytes_tx + 4], 0
 
.finish:
DEBUGF 1,"Packet sent!\n"
xor eax, eax
ret 8
 
.error:
DEBUGF 1,"ERROR!\n"
stdcall KernelFree, [esp+4]
or eax, -1
ret 8
 
 
;***************************************************************************
;
; int_handler
;
; handles received IRQs, which signal received packets
;
; Currently only supports one descriptor per packet, if packet is fragmented
; between multiple descriptors you will lose part of the packet
;
;***************************************************************************
 
align 4
int_handler:
 
push ebx esi edi
 
DEBUGF 1,"\n%s int\n", my_service
 
; find pointer of device which made IRQ occur
 
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
set_io 0
set_io isr
in eax, dx ; note that this clears all interrupts
test ax, IE
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, ax
 
test ax, RxOK
jz .no_rx_
 
push ax
 
.rx_loop:
 
;-----------
; Get Status
movzx eax, [device.cur_rx] ; find current descriptor
shl eax, 4 ; * 16
mov ecx, dword[device.rxd + eax + 4] ; get receive status
 
;-------------------------------------------
; Check RX_Status to see if packet is waiting
test ecx, 0x80000000
jz .no_rx
 
;----------------------------------------------
; There is a packet waiting check it for errors
test ecx, 0x67C0000 ; see if there are any errors
jnz .error_status
 
;---------------------
; Check size of packet
and ecx, DSIZE ; get packet size minus CRC
sub ecx, CRC_SIZE ; make sure packet contains data
jbe .error_size
 
; update statistics
inc dword [device.packets_rx]
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
 
push ebx
push .return
push ecx ; packet size
pushd [device.rxd + eax + 12] ; packet ptr
DEBUGF 1, "Packet received OK\n"
jmp Eth_input
.return:
pop ebx
 
; Reset status, allow ethernet card access to descriptor
stdcall KernelAlloc, RX_BUFF_SZ
test eax, eax
jz .fail
movzx ecx, [device.cur_rx]
shl ecx, 4 ; *16
lea ecx, [device.rxd + ecx]
mov dword [ecx + 12], eax
GetRealAddr
mov dword [ecx + 8], eax
mov dword [ecx + 4], RX_BUFF_SZ
 
inc [device.cur_rx] ; get next descriptor
and [device.cur_rx], NUM_RX_DESC-1 ; only 4 descriptors 0-3
 
jmp .rx_loop
 
.no_rx:
set_io 0
set_io cr
in eax, dx
or eax, RxENA ; Re-Enable the Receive state machine
out dx, eax
 
pop ax
 
.no_rx_:
test ax, TxOK
jz .no_tx
 
DEBUGF 1, "TX ok!\n"
 
.tx_loop:
movzx ecx, [device.last_tx]
shl ecx, 4 ; *16
lea ecx, [device.txd + ecx]
 
test dword [ecx + 4], 0x80000000 ; card owns descr
jnz .no_tx
cmp dword [ecx + 12], 0
je .no_tx
 
DEBUGF 1, "Freeing packet = %x\n", [ecx + 12]:8
push dword [ecx + 12]
mov dword [ecx + 12], 0
call KernelFree
 
inc [device.last_tx]
and [device.last_tx], NUM_TX_DESC-1
jmp .tx_loop
 
.no_tx:
.fail:
pop edi esi ebx
xor eax, eax
inc eax
 
ret
 
ret
 
.error_status:
DEBUGF 1, "Packet error: %x\n", ecx
jmp .fail
 
.error_size:
DEBUGF 1, "Packet too large/small\n"
jmp .fail
 
 
 
 
 
; End of code
 
align 4 ; Place all initialised data here
 
devices dd 0
 
specific_table:
; dd SIS630A_900_REV, Get_Mac_SIS630A_900_REV, 0
; dd SIS630E_900_REV, Get_Mac_SIS630E_900_REV, 0
dd SIS630S_900_REV, Get_Mac_SIS635_900_REV, 0
dd SIS630EA1_900_REV, Get_Mac_SIS635_900_REV, 0
dd SIS630ET_900_REV, Get_Mac_SIS635_900_REV, 0 ;SIS630ET_900_REV_SpecialFN
dd SIS635A_900_REV, Get_Mac_SIS635_900_REV, 0
dd SIS900_960_REV, SIS960_get_mac_addr, 0
dd SIS900B_900_REV, SIS900_get_mac_addr, 0
dd 0 ; end of list
 
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'SIS900',0 ; max 16 chars include zero
 
include_debug_strings ; All data wich FDO uses will be included here
 
section '.data' data readable writable align 16; place all uninitialized data place here
 
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/fdo.inc
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
}
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/imports.inc
1,151 → 1,102
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; all exported kernel functions and data
 
if used RegService
extrn RegService
macro kernel_export [name]{
forward
if used name
if DEBUG
display 'uses: ',`name,#13,#10
end if
if used GetService
extrn GetService
extrn name
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
}
; all exported kernel functions and data
 
if used PciApi
extrn PciApi
end if
if used PciRead32
extrn PciRead32
end if
if used PciRead8
extrn PciRead8
end if
if used PciWrite8
extrn PciWrite8
end if
 
if used AllocPage
extrn AllocPage
end if
if used AllocPages
extrn AllocPages
end if
if used FreePage
extrn FreePage
end if
if used MapPage
extrn MapPage
end if
if used MapSpace
extrn MapSpace
end if
if used GetPgAddr
extrn GetPgAddr
end if
if used CommitPages
extrn CommitPages
end if
if used ReleasePages
extrn ReleasePages
end if
 
if used AllocKernelSpace
extrn AllocKernelSpace
end if
if used FreeKernelSpace
extrn FreeKernelSpace
end if
if used KernelAlloc
extrn KernelAlloc
end if
if used KernelFree
extrn KernelFree
end if
if used UserAlloc
extrn UserAlloc
end if
if used UserFree
extrn UserFree
end if
if used Kmalloc
extrn Kmalloc
end if
if used Kfree
extrn Kfree
end if
 
if used CreateObject
extrn CreateObject
end if
if used DestroyObject
extrn DestroyObject
end if
if used CreateEvent
extrn CreateEvent
end if
if used RaiseEvent
extrn RaiseEvent
end if
if used WaitEvent
extrn WaitEvent
end if
if used DestroyEvent
extrn DestroyEvent
end if
if used ClearEvent
extrn ClearEvent
end if
 
if used LoadCursor
extrn LoadCursor
end if
if used SetHwCursor
extrn SetHwCursor
end if
if used HwCursorRestore
extrn HwCursorRestore
end if
if used HwCursorCreate
extrn HwCursorCreate
end if
 
if used SysMsgBoardStr
extrn SysMsgBoardStr
end if
if used GetCurrentTask
extrn GetCurrentTask
end if
if used LoadFile
extrn LoadFile
end if
if used SendEvent
extrn SendEvent
end if
if used SetMouseData
extrn SetMouseData
end if
if used Sleep
extrn Sleep
end if
if used GetTimerTicks
extrn GetTimerTicks
end if
if used LFBAddress
extrn LFBAddress
end if
 
kernel_export \
RegService,\
GetService,\
ServiceHandler,\
AttachIntHandler,\
GetIntHandler,\
FpuSave,\
FpuRestore,\
ReservePortArea,\
Boot_Log,\
\
MutexInit,\
MutexLock,\
MutexUnlock,\
\
PciApi,\
PciRead32,\
PciRead16,\
PciRead8,\
PciWrite8,\
PciWrite16,\
PciWrite32,\
\
AllocPage,\
AllocPages,\
FreePage,\
MapPage,\
MapSpace,\
MapIoMem,\
GetPgAddr,\
CommitPages,\
ReleasePages,\
\
AllocKernelSpace,\
FreeKernelSpace,\
KernelAlloc,\
KernelFree,\
UserAlloc,\
UserFree,\
Kmalloc,\
Kfree,\
CreateRingBuffer,\
\
GetPid,\
CreateObject,\
DestroyObject,\
CreateEvent,\
RaiseEvent,\
WaitEvent,\
DestroyEvent,\
ClearEvent,\
\
LoadCursor,\
SelectHwCursor,\
SetHwCursor,\
HwCursorRestore,\
HwCursorCreate,\
\
SysMsgBoardStr,\
SysMsgBoardChar,\
GetCurrentTask,\
LoadFile,\
SendEvent,\
SetMouseData,\
Sleep,\
GetTimerTicks,\
\
strncat,\
strncpy,\
strncmp,\
strnlen,\
strchr,\
strrchr,\
\
LFBAddress,\
GetDisplay,\
SetScreen,\
\
NetRegDev,\
NetUnRegDev,\
NetPtrToNum,\
NetLinkChanged,\
Eth_input,\
IPv4_input
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/mii.inc
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
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/netdrv.inc
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
 
}
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/pci.inc
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:
 
}
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/proc32.inc
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/struct.inc
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 \} }
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/branches/net/applications/downloader/downloader.asm
0,0 → 1,1201
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2009-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; downloader.asm - HTTP client for KolibriOS ;;
;; ;;
;; Based on HTTPC.asm for menuetos by ville turjanmaa ;;
;; ;;
;; Programmers: Barsuk, Clevermouse, Marat Zakiyanov, ;;
;; Kirill Lipatov, dunkaist, HidnPlayr ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
URLMAXLEN = 1024
primary_buffer_size = 4096
 
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
format binary as ""
 
use32
org 0x0
 
db 'MENUET01' ; header
dd 0x01 ; header version
dd START ; entry point
dd IM_END ; image size
dd I_END ; required memory
dd I_END ; esp
dd params ; I_PARAM
dd 0x0 ; I_Path
 
include '../macros.inc'
include '../proc32.inc'
include '../network.inc'
include '../../../../../programs/develop/libraries/box_lib/trunk/box_lib.mac'
include '../dll.inc'
include '../debug-fdo.inc'
 
START:
 
mcall 68, 11 ; init heap so we can allocate memory dynamically
 
mcall 40, EV_STACK
 
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
 
; prepare webAddr area
 
mov al, ' '
mov edi, webAddr
mov ecx, URLMAXLEN
rep stosb
xor eax, eax
stosb
 
; prepare document area
mov al, '/'
mov edi, document
stosb
mov al, ' '
mov ecx, URLMAXLEN-1
rep stosb
 
call load_settings
cmp byte[params], 0
je prepare_event ;red
 
; we have an url
mov edi, document_user
mov al, ' '
mov ecx, URLMAXLEN
rep stosb
mov esi, params
mov edi, document_user
 
; copy untill space or 0
.copy_param:
mov al, [esi]
test al, al
jz .done
 
cmp al, ' '
jz .done_inc
 
mov [edi], al
inc esi
inc edi
jmp .copy_param
 
.done_inc:
 
; url is followed by shared memory name.
inc esi
.done:
mov [shared_name], esi
 
mov ah, 22 ; strange way to tell that socket should be opened...
call socket_commands
 
jmp still
 
prepare_event:
; Report events
; Stack 8 + defaults
mcall 40, 10100111b
 
red: ; redraw
call draw_window
 
still:
mcall 23, 1 ; wait here for event
cmp eax, 1 ; redraw request ?
je red
 
cmp eax, 2 ; key in buffer ?
je key
 
cmp eax, 3 ; button in buffer ?
je button
cmp eax, 6 ; mouse in buffer ?
je mouse
 
; Get the web page data from the remote server
cmp eax, 8
jne still
 
call read_incoming_data
 
cmp [status], 4
je .no_send
 
mov [onoff], 1
call send_request
 
.no_send:
call print_status
 
cmp [prev_status], 4
jne no_close
cmp [status], 4 ; connection closed by server
jbe no_close ; respond to connection close command
; draw page
call read_incoming_data
mcall close, [socketnum]
mov [onoff], 0
 
no_close:
jmp still
 
key:
mcall 2 ; read key
 
stdcall [edit_box_key], dword edit1
 
shr eax, 8
cmp eax, 13
je retkey
jmp still
 
button:
 
mcall 17 ; get id
cmp ah, 26
je save
cmp ah, 1 ; button id=1 ?
jne noclose
; DEBUGF 1, "Closing socket before exit...\n"
 
close_end_exit:
 
exit:
or eax, -1 ; close this program
mcall
mouse:
stdcall [edit_box_mouse], edit1
jmp still
 
save:
DEBUGF 1, "file saved\n"
mcall 70, fileinfo
 
mov ecx, [sc.work_text]
or ecx, 0x80000000
mcall 4, <10, 93>, , download_complete
 
jmp still
 
noclose:
cmp ah, 31
jne noup
sub [display_from], 20
jmp still
 
noup:
cmp ah, 32
jne nourl
add [display_from], 20
jmp still
 
 
retkey:
mov ah, 22 ; start load
 
nourl:
call socket_commands ; opens or closes the connection
jmp still
 
 
;****************************************************************************
; Function
; send_request
;
; Description
; Transmits the GET request to the server.
; This is done as GET then URL then HTTP/1.1', 13, 10, 13, 10 in 3 packets
;
;****************************************************************************
send_request:
pusha
mov esi, string0
mov edi, request
movsd
; If proxy is used, make absolute URI - prepend http://<host>
cmp byte[proxyAddr], 0
jz .noproxy
mov dword[edi], 'http'
mov byte[edi+4], ':'
mov word[edi+5], '//'
add edi, 7
mov esi, webAddr
 
.copy_host_loop:
lodsb
cmp al, ' '
jz .noproxy
stosb
jmp .copy_host_loop
 
.noproxy:
xor edx, edx ; 0
 
.next_edx:
; Determine the length of the url to send in the GET request
mov al, [edx+document]
cmp al, ' '
je .document_done
mov [edi], al
inc edi
inc edx
jmp .next_edx
 
.document_done:
mov esi, stringh
mov ecx, stringh_end-stringh
rep movsb
xor edx, edx ; 0
 
.webaddr_next:
mov al, [webAddr + edx]
cmp al, ' '
je .webaddr_done
mov [edi], al
inc edi
inc edx
jmp .webaddr_next
 
.webaddr_done:
cmp byte[proxyUser], 0
jz @f
call append_proxy_auth_header
@@:
mov esi, connclose
mov ecx, connclose_end-connclose
rep movsb
 
pusha
mov eax, 63
mov ebx, 1
mov edx, request
@@:
mov cl, [edx]
cmp edx, edi
jz @f
mcall
inc edx
jmp @b
@@:
popa
 
mov esi, edi
sub esi, request ; length
xor edi, edi ; flags
;;;;now write \r\nConnection: Close \r\n\r\n
mcall send, [socketnum], request ;' HTTP/1.1 .. '
popa
ret
 
;****************************************************************************
; Function
; print_status
;
; Description
; displays the socket/data received status information
;
;****************************************************************************
print_status:
pusha
mcall 26, 9
cmp eax, [nextupdate]
jb status_return
 
add eax, 25
mov [nextupdate], eax
 
mov ecx, [winys]
shl ecx, 16
add ecx, -18 shl 16 + 10
mcall 13, <5, 100>, , 0xffffff
 
mov edx, 12 shl 16 - 18
add edx, [winys]
xor esi, esi
mcall 47, <3, 0>, [status], ,
 
mov edx, 40 shl 16 - 18
add edx, [winys]
mcall , <6, 0>, [pos]
 
status_return:
popa
ret
 
;****************************************************************************
; Function
; read_incoming_data
;
; Description
; receive the web page from the server, storing it without processing
;
;****************************************************************************
read_incoming_data:
cmp [onoff], 1
je .rid
ret
 
.rid:
push esi
push edi
DEBUGF 1, "rid\n"
 
.read:
mcall recv, [socketnum], primary_buf, primary_buffer_size, 0
inc eax ; -1 = error (socket closed?)
jz .no_more_data
dec eax ; 0 bytes...
jz .read
mov edi, [pos]
add [pos], eax
push eax
mcall 68, 20, [pos], [buf_ptr]
mov [buf_ptr], eax
add edi, eax
mov esi, primary_buf
pop ecx ; number of recently read bytes
lea edx, [ecx - 3]
rep movsb
.no_more_data:
 
; mov [status], 4 ; connection closed by server
 
call parse_result
mov ecx, [shared_name]
test ecx, ecx
jz @f
cmp [ecx], byte 0
jnz save_in_shared
@@:
 
mcall 70, fileinfo
mov ecx, [sc.work_text]
or ecx, 0x80000000
mcall 4, <10, 93>, , download_complete
DEBUGF 1, "file saved\n"
 
pop edi
pop esi
 
; if called from command line, then exit
cmp byte[params], 0
jne exit
 
ret
save_in_shared:
 
mov esi, 1 ; SHM_OPEN+SHM_WRITE
mcall 68, 22
test eax, eax
jz save_in_shared_done
 
sub edx, 4
jbe save_in_shared_done
 
mov ecx, [final_size]
cmp ecx, edx
jb @f
 
mov ecx, edx
@@:
mov [eax], ecx
lea edi, [eax+4]
mov esi, [final_buffer]
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
 
save_in_shared_done:
pop edi
pop esi
jmp exit
; this function cuts header, and removes chunk sizes if doc is chunked
; in: buf_ptr, pos; out: buf_ptr, pos.
parse_result:
; close socket
mcall close, [socketnum]
DEBUGF 1, "close socketnum: 0x%x\n", eax
mov edi, [buf_ptr]
mov edx, [pos]
mov [buf_size], edx
; mcall 70, fileinfo_tmp
DEBUGF 1, "pos = 0x%x\n", edx
 
; first, find end of headers
.next_byte:
cmp dword[edi], 0x0d0a0d0a ; ìíå ëåíü ÷èòàòü ñòàíäàðò, ïóñòü áóäóò îáà âàðèàíòà
je .end_of_headers
cmp dword[edi], 0x0a0d0a0d
je .end_of_headers
inc edi
dec edx
jne .next_byte
; no end of headers. it's an error. let client see all those headers.
ret
 
.end_of_headers:
; here we look at headers and search content-length or transfer-encoding headers
; DEBUGF 1, "eoh\n"
 
sub edi, [buf_ptr]
add edi, 4
mov [body_pos], edi ; store position where document body starts
mov [is_chunked], 0
; find content-length in headers
; not good method, but should work for 'Content-Length:'
mov esi, [buf_ptr]
mov edi, s_contentlength
mov ebx, [body_pos]
xor edx, edx ; 0
.cl_next:
mov al, [esi]
cmp al, [edi + edx]
jne .cl_fail
inc edx
cmp edx, len_contentlength
je .cl_found
jmp .cl_incr
.cl_fail:
xor edx, edx ; 0
.cl_incr:
inc esi
dec ebx
je .cl_error
jmp .cl_next
.cl_error:
; DEBUGF 1, "content-length not found\n"
 
; find 'chunked'
; äà, ÿ êîïèðóþ êîä, ýòî óæàñíî, íî ìíå õî÷åòñÿ, ÷òîáû ïîñêîðåå çàðàáîòàëî
; à òàì óæ îòðåôàêòîðþ
mov esi, [buf_ptr]
mov edi, s_chunked
mov ebx, [body_pos]
xor edx, edx ; 0
 
.ch_next:
mov al, [esi]
cmp al, [edi + edx]
jne .ch_fail
inc edx
cmp edx, len_chunked
je .ch_found
jmp .ch_incr
 
.ch_fail:
xor edx, edx ; 0
 
.ch_incr:
inc esi
dec ebx
je .ch_error
jmp .ch_next
 
.ch_error:
; if neither of the 2 headers is found, it's an error
; DEBUGF 1, "transfer-encoding: chunked not found\n"
mov eax, [pos]
sub eax, [body_pos]
jmp .write_final_size
 
.ch_found:
mov [is_chunked], 1
mov eax, [body_pos]
add eax, [buf_ptr]
sub eax, 2
mov [prev_chunk_end], eax
jmp parse_chunks
.cl_found:
call read_number ; eax = number from *esi
 
.write_final_size:
mov [final_size], eax ; if this works, i will b very happy...
mov ebx, [pos] ; we well check if it is right
sub ebx, [body_pos]
 
; everything is ok, so we return
mov eax, [body_pos]
mov ebx, [buf_ptr]
add ebx, eax
mov [final_buffer], ebx
; mov ebx, [pos]
; sub ebx, eax
; mov [final_size], ebx
ret
parse_chunks:
; DEBUGF 1, "parse chunks\n"
; we have to look through the data and remove sizes of chunks we see
; 1. read size of next chunk
; 2. if 0, it's end. if not, continue.
; 3. make a good buffer and copy a chunk there
xor eax, eax
mov [final_buffer], eax ; 0
mov [final_size], eax ; 0
.read_size:
mov eax, [prev_chunk_end]
mov ebx, eax
sub ebx, [buf_ptr]
mov edx, eax
; DEBUGF 1, "rs "
cmp ebx, [pos]
jae chunks_end ; not good
call read_hex ; in: eax=pointer to text. out:eax=hex number, ebx=end of text.
cmp eax, 0
jz chunks_end
 
add ebx, 1
mov edx, ebx ; edx = size of size of chunk
add ebx, eax
mov [prev_chunk_end], ebx
; DEBUGF 1, "sz "
 
; do copying: from buf_ptr+edx to final_buffer+prev_final_size count eax
; realloc final buffer
push eax
push edx
push dword [final_size]
add [final_size], eax
mcall 68, 20, [final_size], [final_buffer]
mov [final_buffer], eax
; DEBUGF 1, "re "
pop edi
pop esi
pop ecx
; add [pos], ecx
add edi, [final_buffer]
; DEBUGF 1, "cp "
 
rep movsb
jmp .read_size
chunks_end:
; free old buffer
DEBUGF 1, "chunks end\n"
 
mcall 68, 13, [buf_ptr]
; done!
ret
 
; reads content-length from [edi+ecx], result in eax
read_number:
push ebx
xor eax, eax
xor ebx, ebx
 
.next:
mov bl, [esi]
 
cmp bl, '0'
jb .not_number
cmp bl, '9'
ja .not_number
sub bl, '0'
shl eax, 1
lea eax, [eax + eax * 4] ; eax *= 10
add eax, ebx
 
.not_number:
cmp bl, 13
je .done
inc esi
jmp .next
 
.done:
pop ebx
ret
; reads hex from eax, result in eax, end of text in ebx
read_hex:
add eax, 2
mov ebx, eax
mov eax, [ebx]
mov [deba], eax
 
xor eax, eax
xor ecx, ecx
.next:
mov cl, [ebx]
inc ebx
cmp cl, 0x0d
jz .done
 
or cl, 0x20
sub cl, '0'
jb .bad
 
cmp cl, 0x9
jbe .adding
 
sub cl, 'a'-'0'-10
cmp cl, 0x0a
jb .bad
 
cmp cl, 0x0f
ja .bad
 
.adding:
shl eax, 4
or eax, ecx
; jmp .not_number
;.bad:
.bad:
jmp .next
.done:
 
ret
 
;****************************************************************************
; Function
; socket_commands
;
; Description
; opens or closes the socket
;
;****************************************************************************
socket_commands:
cmp ah, 22 ; open socket
jne tst3
 
DEBUGF 1, "opening socket\n"
 
; Clear all page memory
xor eax, eax
mov [prev_chunk_end], eax ; 0
cmp [buf_ptr], eax ; 0
jz no_free
 
mcall 68, 13, [buf_ptr] ; free buffer
 
no_free:
xor eax, eax
mov [buf_size], eax ; 0
; Parse the entered url
call parse_url
 
mov edx, 80
cmp byte [proxyAddr], 0
jz @f
mov eax, [proxyPort]
xchg al, ah
mov [server_port], ax
@@:
 
mcall socket, AF_INET4, SOCK_STREAM, 0
mov [socketnum], eax
mcall connect, [socketnum], sockaddr1, 18
mov [pagexs], 80
push eax
xor eax, eax ; 0
mov [pos], eax
mov [pagex], eax
mov [pagey], eax
mov [command_on_off], eax
mov [is_body], eax
pop eax
ret
 
tst3:
cmp ah, 24 ; close socket
jne no_24
 
mcall close, [socketnum]
no_24:
ret
 
;****************************************************************************
; Function
; parse_url
;
; Description
; parses the full url typed in by the user into a web address ( that
; can be turned into an IP address by DNS ) and the page to display
; DNS will be used to translate the web address into an IP address, if
; needed.
; url is at document_user and will be space terminated.
; web address goes to webAddr and is space terminated.
; ip address goes to server_ip
; page goes to document and is space terminated.
;
; Supported formats:
; <protocol://>address<page>
; <protocol> is optional, removed and ignored - only http supported
; <address> is required. It can be an ip address or web address
; <page> is optional and must start with a leading / character
;
;****************************************************************************
parse_url:
; First, reset destination variables
mov al, ' '
mov edi, document
mov ecx, URLMAXLEN
rep stosb
mov edi, webAddr
mov ecx, URLMAXLEN
rep stosb
 
mov al, '/'
mov [document], al
 
mov esi, document_user
; remove any leading protocol text
mov ecx, URLMAXLEN
mov ax, '//'
 
pu_000:
cmp [esi], byte ' ' ; end of text?
je pu_002 ; yep, so not found
cmp [esi], ax
je pu_001 ; Found it, so esi+2 is start
inc esi
loop pu_000
 
pu_002:
; not found, so reset esi to start
mov esi, document_user-2
 
pu_001:
add esi, 2
mov ebx, esi ; save address of start of web address
mov edi, document_user + URLMAXLEN ; end of string
; look for page delimiter - it's a '/' character
pu_003:
cmp [esi], byte ' ' ; end of text?
je pu_004 ; yep, so none found
cmp esi, edi ; end of string?
je pu_004 ; yep, so none found
cmp [esi], byte '/' ; delimiter?
je pu_005 ; yep - process it
inc esi
jmp pu_003
 
pu_005:
; copy page to document address
; esi = delimiter
push esi
mov ecx, edi ; end of document_user
mov edi, document
 
pu_006:
movsb
cmp esi, ecx
je pu_007 ; end of string?
cmp [esi], byte ' ' ; end of text
; je pu_007 ; äçåí-àññåìáëåð
; jmp pu_006 ; íå íàäî ïëîäèòü ñóùíîñòè ïî íàïðàñíó
jne pu_006
 
pu_007:
pop esi ; point esi to '/' delimiter
 
pu_004:
; copy web address to webAddr
; start in ebx, end in esi-1
mov ecx, esi
mov esi, ebx
mov edi, webAddr
 
pu_008:
movsb
cmp esi, ecx
; je pu_009 ; äçåí-àññåìáëåð
; jmp pu_008 ; íå íàäî ïëîäèòü ñóùíîñòè ïî íàïðàñíó
jne pu_008
 
pu_009:
; For debugging, display resulting strings
DEBUGF 1, "%s", document_user
DEBUGF 1, "%s", webAddr
DEBUGF 1, "%s", document
 
; Look up the ip address, or was it specified?
mov al, [proxyAddr]
cmp al, 0
jnz pu_015
mov al, [webAddr]
pu_015:
cmp al, '0'
jb pu_010 ; Resolve address
cmp al, '9'
ja pu_010 ; Resolve address
 
DEBUGF 1, "GotIP\n"
 
; Convert address
; If proxy is given, get proxy address instead of server
mov esi, proxyAddr-1
cmp byte[esi+1], 0
jne pu_020
mov esi, webAddr-1
 
pu_020:
mov edi, server_ip
xor eax, eax
 
ip1:
inc esi
cmp [esi], byte '0'
jb ip2
cmp [esi], byte '9'
ja ip2
imul eax, 10
movzx ebx, byte [esi]
sub ebx, 48
add eax, ebx
jmp ip1
 
ip2:
mov [edi], al
xor eax, eax
inc edi
cmp edi, server_ip+3
jbe ip1
jmp pu_011
 
pu_010:
DEBUGF 1, "Resolving...\n"
 
; resolve name
push esp ; reserve stack place
push esp ; fourth parameter
push 0 ; third parameter
push 0 ; second parameter
push webAddr
call [getaddrinfo]
pop esi
; test for error
test eax, eax
; jnz .fail_dns
 
; fill in ip in sockstruct
mov eax, [esi + addrinfo.ai_addr]
mov eax, [eax + sockaddr_in.sin_addr]
mov [server_ip], eax
 
 
DEBUGF 1, "Resolved\n"
 
pu_011:
 
ret
 
;***************************************************************************
; Function
; load_settings
;
; Description
; Load settings from configuration file network.ini
;
;***************************************************************************
load_settings:
 
invoke ini.get_str, inifile, sec_proxy, key_proxy, proxyAddr, 256, proxyAddr
invoke ini.get_int, inifile, sec_proxy, key_proxyport, 80
mov [proxyPort], eax
invoke ini.get_str, inifile, sec_proxy, key_user, proxyUser, 256, proxyUser
invoke ini.get_str, inifile, sec_proxy, key_password, proxyPassword, 256, proxyPassword
 
ret
 
;***************************************************************************
; Function
; append_proxy_auth_header
;
; Description
; Append header to HTTP request for proxy authentification
;
;***************************************************************************
append_proxy_auth_header:
mov esi, proxy_auth_basic
mov ecx, proxy_auth_basic_end - proxy_auth_basic
rep movsb
; base64-encode string <user>:<password>
mov esi, proxyUser
 
apah000:
lodsb
test al, al
jz apah001
call encode_base64_byte
jmp apah000
 
apah001:
mov al, ':'
call encode_base64_byte
mov esi, proxyPassword
 
apah002:
lodsb
test al, al
jz apah003
call encode_base64_byte
jmp apah002
 
apah003:
call encode_base64_final
ret
 
encode_base64_byte:
inc ecx
shl edx, 8
mov dl, al
cmp ecx, 3
je ebb001
ret
 
ebb001:
shl edx, 8
inc ecx
 
ebb002:
rol edx, 6
xor eax, eax
xchg al, dl
mov al, [base64_table+eax]
stosb
loop ebb002
ret
 
encode_base64_final:
mov al, 0
test ecx, ecx
jz ebf000
call encode_base64_byte
test ecx, ecx
jz ebf001
call encode_base64_byte
mov byte [edi-2], '='
 
ebf001:
mov byte [edi-1], '='
 
ebf000:
ret
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
draw_window:
 
mcall 12, 1
 
mcall 48, 3, sc, 40 ;get system colors
 
mov edx, [sc.work]
or edx, 0x34000000
mcall 0, <50, 370>, <350, 140>, , 0, title ;draw window
mov ecx, [sc.work_text]
or ecx, 80000000h
mcall 4, <14, 14>, , type_pls ;"URL:"
 
edit_boxes_set_sys_color edit1, editboxes_end, sc
stdcall [edit_box_draw], edit1
 
; RELOAD
mcall 8, <90, 68>, <54, 16>, 22, [sc.work_button]
; STOP
mcall , <166, 50>, <54, 16>, 24
; SAVE
mcall , <224, 54>, , 26
; BUTTON TEXT
mov ecx, [sc.work_button_text]
or ecx, 80000000h
mcall 4, <102, 59>, , button_text
 
mcall 12, 2 ; end window redraw
ret
;-----------------------------------------------------------------------------
; Data area
;-----------------------------------------------------------------------------
align 4
@IMPORT:
 
library libini, 'libini.obj', \
box_lib, 'box_lib.obj', \
network, 'network.obj'
 
import libini, \
ini.get_str, 'ini_get_str', \
ini.get_int, 'ini_get_int'
 
import box_lib, \
edit_box_draw, 'edit_box', \
edit_box_key, 'edit_box_key', \
edit_box_mouse, 'edit_box_mouse'
 
import network,\
getaddrinfo, 'getaddrinfo',\
freeaddrinfo, 'freeaddrinfo',\
inet_ntoa, 'inet_ntoa'
 
;---------------------------------------------------------------------
fileinfo dd 2, 0, 0
final_size dd 0
final_buffer dd 0
db '/rd/1/.download', 0
body_pos dd 0
 
buf_size dd 0
buf_ptr dd 0
 
deba dd 0
db 0
 
;---------------------------------------------------------------------
 
mouse_dd dd 0
edit1 edit_box 295, 48, 10, 0xffffff, 0xff, 0x80ff, 0, 0x8000, URLMAXLEN, document_user, mouse_dd, ed_focus+ed_always_focus, 7, 7
editboxes_end:
 
;---------------------------------------------------------------------
 
include_debug_strings
 
;---------------------------------------------------------------------
 
type_pls db 'URL:', 0
button_text db 'DOWNLOAD STOP RESAVE', 0
download_complete db 'File saved as /rd/1/.download', 0
display_from dd 20
pos dd 0
pagex dd 0
pagey dd 0
pagexs dd 80
command_on_off dd 0
text_type db 1
com2 dd 0
script dd 0
socketnum dd 0
 
addr dd 0
ya dd 0
len dd 0
 
title db 'HTTP Downloader', 0
 
;---------------------------------------------------------------------
s_contentlength db 'Content-Length:'
len_contentlength = 15
 
s_chunked db 'Transfer-Encoding: chunked'
len_chunked = $ - s_chunked
 
is_body dd 0 ; 0 if headers, 1 if content
is_chunked dd 0
prev_chunk_end dd 0
cur_chunk_size dd 0
 
string0: db 'GET '
 
stringh db ' HTTP/1.1', 13, 10, 'Host: '
stringh_end:
proxy_auth_basic db 13, 10, 'Proxy-Authorization: Basic '
proxy_auth_basic_end:
connclose db 13, 10, 'User-Agent: Kolibrios Downloader', 13, 10, 'Connection: Close', 13, 10, 13, 10
connclose_end:
 
base64_table db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
db '0123456789+/'
 
inifile db '/sys/network.ini', 0
 
sec_proxy:
key_proxy db 'proxy', 0
key_proxyport db 'port', 0
key_user db 'user', 0
key_password db 'password', 0
 
sockaddr1:
dw AF_INET4
server_port dw 0x5000 ; 80
server_ip dd 0
rb 10
 
proxyPort dd 80
 
shared_name dd 0
 
status dd 0x0
prev_status dd 0x0
 
onoff dd 0x0
 
nextupdate dd 0
winys dd 400
 
;---------------------------------------------------------------------
document_user db 'http://', 0
;---------------------------------------------------------------------
IM_END:
;---------------------------------------------------------------------
rb URLMAXLEN-(IM_END - document_user)
;---------------------------------------------------------------------
sc system_colors
;---------------------------------------------------------------------
align 4
document rb URLMAXLEN
;---------------------------------------------------------------------
align 4
webAddr rb URLMAXLEN+1
;---------------------------------------------------------------------
 
align 4
primary_buf rb primary_buffer_size
 
params rb 1024
 
request rb 256
 
proxyAddr rb 256
proxyUser rb 256
proxyPassword rb 256
 
rb 4096 ; stack
 
I_END:
 
 
 
/kernel/branches/net/applications/ftpc/ftpc.asm
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:
/kernel/branches/net/applications/ftpc/servercommands.inc
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
/kernel/branches/net/applications/ftpc/usercommands.inc
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
/kernel/branches/net/applications/ircc/window.inc
78,6 → 78,21
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
/kernel/branches/net/applications/libio.inc
78,7 → 78,7
FileSizeHigh dd ?
ends
ends
FileName rb 252
FileName rb 264
ends
 
struct FileInfoW
94,7 → 94,7
FileSizeHigh dd ?
ends
ends
FileName rw 260
FileName rw 264
ends
 
virtual at 0
109,4 → 109,5
FA_LABEL = 00001000b
FA_FOLDER = 00010000b
FA_ARCHIVED = 00100000b
FA_ANY = 00111111b
FA_NORMAL = 01000000b
FA_ANY = 01111111b
/kernel/branches/net/data32.inc
500,4 → 500,5
BiosDiskCaches rb 80h*(cache_ide1-cache_ide0)
BiosDiskPartitions rd 80h
 
tetten:
IncludeUGlobals
/kernel/branches/net/gui/event.inc
527,7 → 527,7
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)
/kernel/branches/net/kernel.asm
77,11 → 77,12
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
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
/kernel/trunk/const.inc
399,7 → 399,8
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
 
/kernel/trunk/core/conf_lib.inc
72,54 → 72,7
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'
/kernel/trunk/core/exports.inc
101,6 → 101,12
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
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
/kernel/trunk/core/syscall.inc
112,11 → 112,11
 
align 4
servetable:
dd socket ; 53-Socket interface
dd 0
dd 0
dd 0
dd 0
dd 0
dd file_system ; 58-Common file system interface
dd 0
dd 0
182,8 → 182,8
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
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
 
/kernel/trunk/gui/event.inc
515,8 → 515,8
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
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)
/kernel/trunk/kernel.asm
77,7 → 77,7
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
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
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
 
2029,6 → 2017,13
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]
test eax, eax
2155,6 → 2150,12
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
; restore default cursor before killing
5366,28 → 5367,6
 
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
;------------------------------------------------------------------------------
/kernel/trunk/network/ip.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/eth_drv/drivers/pcnet32.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/eth_drv/drivers/forcedeth.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/eth_drv/drivers/rtl8029.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/eth_drv/drivers/i8255x.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/eth_drv/drivers/rtl8139.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/eth_drv/drivers/sis900.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/eth_drv/drivers/rtl8169.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/eth_drv/drivers/r6040.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/kernel/trunk/network/eth_drv/drivers/3c59x.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/eth_drv/drivers
Property changes:
Deleted: svn:ignore
-*.mnt
-lang.inc
-*.bat
-out.txt
-scin*
-*.obj
/kernel/trunk/network/eth_drv/pci.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/eth_drv/ethernet.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/eth_drv/arp.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/eth_drv
Property changes:
Deleted: svn:ignore
-*.mnt
-lang.inc
-*.bat
-out.txt
-scin*
-*.obj
/kernel/trunk/network/ARP.inc
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
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/trunk/network/IPv4.inc
0,0 → 1,1019
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; IPv4.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: 3515 $
 
MAX_FRAGMENTS = 64
 
struct IPv4_header
 
VersionAndIHL db ? ; Version[0-3 bits] and IHL(header length)[4-7 bits]
TypeOfService db ? ; precedence [7-5] minimize delay [4], maximize throughput [3], maximize riliability [2] minimize momentary cost [1] and zero [0]
TotalLength dw ?
Identification dw ?
FlagsAndFragmentOffset dw ? ; Flags[0-2] and FragmentOffset[3-15]
TimeToLive db ? ;
Protocol db ?
HeaderChecksum dw ?
SourceAddress dd ?
DestinationAddress dd ?
 
ends
 
struct FRAGMENT_slot
 
ttl dw ? ; Time to live for this entry, 0 for empty slot's
id dw ? ; Identification field from IP header
SrcIP dd ? ; .. from IP header
DstIP dd ? ; .. from IP header
ptr dd ? ; Pointer to first packet
 
ends
 
struct FRAGMENT_entry ; This structure will replace the ethernet header in fragmented ip packets
 
PrevPtr dd ? ; Pointer to previous fragment entry (-1 for first packet)
NextPtr dd ? ; Pointer to next fragment entry (-1 for last packet)
Owner dd ? ; Pointer to structure of driver
rb 2 ; to match ethernet header size ;;; FIXME
; Ip header begins here (we will need the IP header to re-construct the complete packet)
ends
 
 
align 4
uglobal
 
IP_LIST rd MAX_NET_DEVICES
SUBNET_LIST rd MAX_NET_DEVICES
DNS_LIST rd MAX_NET_DEVICES
GATEWAY_LIST rd MAX_NET_DEVICES
BROADCAST_LIST rd MAX_NET_DEVICES
 
IP_packets_tx rd MAX_NET_DEVICES
IP_packets_rx rd MAX_NET_DEVICES
IP_packets_dumped rd MAX_NET_DEVICES
 
FRAGMENT_LIST rb MAX_FRAGMENTS * sizeof.FRAGMENT_slot
endg
 
 
;-----------------------------------------------------------------
;
; IPv4_init
;
; This function resets all IP variables
;
;-----------------------------------------------------------------
macro IPv4_init {
 
xor eax, eax
mov edi, IP_LIST
mov ecx, 7*MAX_NET_DEVICES + (sizeof.FRAGMENT_slot*MAX_FRAGMENTS)/4
rep stosd
 
}
 
 
;-----------------------------------------------------------------
;
; Decrease TimeToLive of all fragment slots
;
;-----------------------------------------------------------------
macro IPv4_decrease_fragment_ttls {
 
local .loop, .next
 
mov esi, FRAGMENT_LIST
mov ecx, MAX_FRAGMENTS
.loop:
cmp [esi + FRAGMENT_slot.ttl], 0
je .next
dec [esi + FRAGMENT_slot.ttl]
jz .died
.next:
add esi, sizeof.FRAGMENT_slot
dec ecx
jnz .loop
jmp .done
 
.died:
DEBUGF 2,"IPv4 Fragment slot timed-out!\n"
;;; TODO: clear all entry's of timed-out slot
jmp .next
 
.done:
}
 
 
 
macro IPv4_checksum ptr {
 
; This is the fast procedure to create or check an IP header without options
; To create a new checksum, the checksum field must be set to 0 before computation
; To check an existing checksum, leave the checksum as is, and it will be 0 after this procedure, if it was correct
 
push ebx
xor ebx, ebx
add bl, [ptr+1]
adc bh, [ptr+0]
 
adc bl, [ptr+3]
adc bh, [ptr+2]
 
adc bl, [ptr+5]
adc bh, [ptr+4]
 
adc bl, [ptr+7]
adc bh, [ptr+6]
 
adc bl, [ptr+9]
adc bh, [ptr+8]
 
; we skip 11th and 12th byte, they are the checksum bytes and should be 0 for re-calculation
 
adc bl, [ptr+13]
adc bh, [ptr+12]
 
adc bl, [ptr+15]
adc bh, [ptr+14]
 
adc bl, [ptr+17]
adc bh, [ptr+16]
 
adc bl, [ptr+19]
adc bh, [ptr+18]
 
adc ebx, 0
 
push ecx
mov ecx, ebx
shr ecx, 16
and ebx, 0xffff
add ebx, ecx
 
mov ecx, ebx
shr ecx, 16
add ebx, ecx
 
not bx
jnz .not_zero
dec bx
.not_zero:
xchg bl, bh
pop ecx
 
neg word [ptr+10] ; zero will stay zero so we just get the checksum
add word [ptr+10], bx ; , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
pop ebx
 
}
 
 
 
;-----------------------------------------------------------------
;
; IPv4_input:
;
; Will check if IPv4 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 IPv4 header in edx
; size of IPv4 packet in ecx
; OUT: /
;
;-----------------------------------------------------------------
align 4
IPv4_input: ; TODO: add IPv4 raw sockets support
 
DEBUGF 2,"IPv4_input, packet from: %u.%u.%u.%u ",\
[edx + IPv4_header.SourceAddress + 0]:1,[edx + IPv4_header.SourceAddress + 1]:1,\
[edx + IPv4_header.SourceAddress + 2]:1,[edx + IPv4_header.SourceAddress + 3]:1
DEBUGF 2,"to: %u.%u.%u.%u\n",\
[edx + IPv4_header.DestinationAddress + 0]:1,[edx + IPv4_header.DestinationAddress + 1]:1,\
[edx + IPv4_header.DestinationAddress + 2]:1,[edx + IPv4_header.DestinationAddress + 3]:1
 
;-------------------------------
; re-calculate the checksum
 
IPv4_checksum edx
jnz .dump ; if checksum isn't valid then dump packet
 
DEBUGF 1,"IPv4_input: Checksum ok\n"
 
;-----------------------------------
; Check if destination IP is correct
 
call NET_ptr_to_num
shl edi, 2
 
; check if it matches local ip (Using RFC1122 strong end system model)
 
mov eax, [edx + IPv4_header.DestinationAddress]
cmp eax, [IP_LIST + edi]
je .ip_ok
 
; check for broadcast (IP or (not SUBNET))
 
cmp eax, [BROADCAST_LIST + edi]
je .ip_ok
 
; or a special broadcast (255.255.255.255)
 
cmp eax, 0xffffffff
je .ip_ok
 
; maybe it's a multicast (224.0.0.0/4)
 
and eax, 0x0fffffff
cmp eax, 224
je .ip_ok
 
; or a loopback address (127.0.0.0/8)
 
and eax, 0x00ffffff
cmp eax, 127
je .ip_ok
 
; or it's just not meant for us.. :(
 
DEBUGF 2,"IPv4_input: Destination address does not match!\n"
jmp .dump
 
;------------------------
; Now we can update stats
 
.ip_ok:
inc [IP_packets_rx + edi]
 
;----------------------------------
; Check if the packet is fragmented
 
test [edx + IPv4_header.FlagsAndFragmentOffset], 1 shl 5 ; Is 'more fragments' flag set ?
jnz .has_fragments ; If so, we definately have a fragmented packet
 
test [edx + IPv4_header.FlagsAndFragmentOffset], 0xff1f ; If flag is not set, but there is a fragment offset, the packet is last in series of fragmented packets
jnz .is_last_fragment
 
;-------------------------------------------------------------------
; No, it's just a regular IP packet, pass it to the higher protocols
 
.handle_it: ; We reach here if packet hasnt been fragmented, or when it already has been re-constructed
 
movzx esi, [edx + IPv4_header.VersionAndIHL] ; Calculate Header length by using IHL field
and esi, 0x0000000f ;
shl esi, 2 ;
 
movzx ecx, [edx + IPv4_header.TotalLength] ; Calculate length of encapsulated Packet
xchg cl, ch ;
sub ecx, esi ;
 
lea edi, [edx + IPv4_header.SourceAddress] ; make edi ptr to source and dest IPv4 address
mov al, [edx + IPv4_header.Protocol]
add esi, edx ; make esi ptr to data
 
cmp al, IP_PROTO_TCP
je TCP_input
 
cmp al, IP_PROTO_UDP
je UDP_input
 
cmp al, IP_PROTO_ICMP
je ICMP_input
 
DEBUGF 2,"IPv4_input: unknown protocol %u\n", al
 
.dump:
DEBUGF 1,"IPv4_input: dumping\n"
inc [IP_packets_dumped] ; FIXME: use correct interface
call kernel_free
add esp, 4 ; pop (balance stack)
ret
 
 
;---------------------------
; Fragmented packet handler
 
 
.has_fragments:
movzx eax, [edx + IPv4_header.FlagsAndFragmentOffset]
xchg al, ah
shl ax, 3
 
DEBUGF 1,"IPv4_input: fragmented packet offset=%u id=%x\n", ax, [edx + IPv4_header.Identification]:4
 
test ax, ax ; Is this the first packet of the fragment?
jz .is_first_fragment
 
 
;-------------------------------------------------------
; We have a fragmented IP packet, but it's not the first
 
DEBUGF 1,"IPv4_input: Middle fragment packet received!\n"
 
call IPv4_find_fragment_slot
cmp esi, -1
je .dump
 
mov [esi + FRAGMENT_slot.ttl], 15 ; Reset the ttl
mov esi, [esi + FRAGMENT_slot.ptr]
or edi, -1
.find_last_entry: ; The following routine will try to find the last entry
cmp edi, [esi + FRAGMENT_entry.PrevPtr]
jne .destroy_slot ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
mov edi, esi
mov esi, [esi + FRAGMENT_entry.NextPtr]
cmp esi, -1
jne .find_last_entry
; We found the last entry (pointer is now in edi)
; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure
 
pop eax ; pointer to packet
mov [edi + FRAGMENT_entry.NextPtr], eax ; update pointer of previous entry to the new entry
mov [eax + FRAGMENT_entry.NextPtr], -1
mov [eax + FRAGMENT_entry.PrevPtr], edi
mov [eax + FRAGMENT_entry.Owner], ebx
 
add esp, 4
ret
 
 
;------------------------------------
; We have received the first fragment
 
.is_first_fragment:
DEBUGF 1,"IPv4_input: First fragment packet received!\n"
; try to locate a free slot..
mov ecx, MAX_FRAGMENTS
mov esi, FRAGMENT_LIST
.find_free_slot:
cmp word [esi + FRAGMENT_slot.ttl], 0
je .found_free_slot
add esi, sizeof.FRAGMENT_slot
loop .find_free_slot
jmp .dump ; If no free slot was found, dump the packet
 
.found_free_slot: ; We found a free slot, let's fill in the FRAGMENT_slot structure
mov [esi + FRAGMENT_slot.ttl], 15 ; RFC recommends 15 secs as ttl
mov ax, [edx + IPv4_header.Identification]
mov [esi + FRAGMENT_slot.id], ax
mov eax, [edx + IPv4_header.SourceAddress]
mov [esi + FRAGMENT_slot.SrcIP], eax
mov eax, [edx + IPv4_header.DestinationAddress]
mov [esi + FRAGMENT_slot.DstIP], eax
pop eax
mov [esi + FRAGMENT_slot.ptr], eax
; Now, replace ethernet header in original buffer with a FRAGMENT_entry structure
mov [eax + FRAGMENT_entry.NextPtr], -1
mov [eax + FRAGMENT_entry.PrevPtr], -1
mov [eax + FRAGMENT_entry.Owner], ebx
 
add esp, 4 ; balance stack and exit
ret
 
 
;-----------------------------------
; We have received the last fragment
 
.is_last_fragment:
DEBUGF 1,"IPv4_input: Last fragment packet received!\n"
 
call IPv4_find_fragment_slot
cmp esi, -1
je .dump
 
mov esi, [esi + FRAGMENT_slot.ptr] ; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer
push esi
xor eax, eax
or edi, -1
 
.count_bytes:
cmp [esi + FRAGMENT_entry.PrevPtr], edi
jne .destroy_slot_pop ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
mov cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.TotalLength] ; Add total length
xchg cl, ch
DEBUGF 1,"IPv4_input: Packet size=%u\n", cx
add ax, cx
movzx cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL] ; Sub Header length
and cx, 0x000F
shl cx, 2
DEBUGF 1,"IPv4_input: Header size=%u\n", cx
sub ax, cx
mov edi, esi
mov esi, [esi + FRAGMENT_entry.NextPtr]
cmp esi, -1
jne .count_bytes
 
mov esi, [esp+4]
mov [edi + FRAGMENT_entry.NextPtr], esi ; Add this packet to the chain, this simplifies the following code
mov [esi + FRAGMENT_entry.NextPtr], -1
mov [esi + FRAGMENT_entry.PrevPtr], edi
mov [esi + FRAGMENT_entry.Owner], ebx
 
mov cx, [edx + IPv4_header.TotalLength] ; Note: This time we dont substract Header length
xchg cl, ch
DEBUGF 1,"IPv4_input: Packet size=%u\n", cx
add ax, cx
DEBUGF 1,"IPv4_input: Total Received data size=%u\n", eax
 
push eax
mov ax, [edx + IPv4_header.FlagsAndFragmentOffset]
xchg al, ah
shl ax, 3
add cx, ax
pop eax
DEBUGF 1,"IPv4_input: Total Fragment size=%u\n", ecx
 
cmp ax, cx
jne .destroy_slot_pop
 
push eax
push eax
call kernel_alloc
test eax, eax
je .destroy_slot_pop ; If we dont have enough space to allocate the buffer, discard all packets in slot
mov edx, [esp+4] ; Get pointer to first fragment entry back in edx
 
.rebuild_packet_loop:
movzx ecx, [edx + sizeof.FRAGMENT_entry + IPv4_header.FlagsAndFragmentOffset] ; Calculate the fragment offset
xchg cl, ch ; intel byte order
shl cx, 3 ; multiply by 8 and clear first 3 bits
DEBUGF 1,"IPv4_input: Fragment offset=%u\n", cx
 
lea edi, [eax + ecx] ; Notice that edi will be equal to eax for first fragment
movzx ebx, [edx + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL] ; Find header size (in ebx) of fragment
and bx, 0x000F ;
shl bx, 2 ;
 
lea esi, [edx + sizeof.FRAGMENT_entry] ; Set esi to the correct begin of fragment
movzx ecx, [edx + sizeof.FRAGMENT_entry + IPv4_header.TotalLength] ; Calculate total length of fragment
xchg cl, ch ; intel byte order
 
cmp edi, eax ; Is this packet the first fragment ?
je .first_fragment
sub cx, bx ; If not, dont copy the header
add esi, ebx ;
.first_fragment:
 
push cx ; First copy dword-wise, then byte-wise
shr cx, 2 ;
rep movsd ;
pop cx ;
and cx, 3 ;
rep movsb ;
 
push eax
push edx ; Push pointer to fragment onto stack
mov ebx, [edx + FRAGMENT_entry.Owner] ; we need to remeber the owner, in case this is the last packet
mov edx, [edx + FRAGMENT_entry.NextPtr] ; Set edx to the next pointer
call kernel_free ; free the previous fragment buffer (this uses the value from stack)
pop eax
cmp edx, -1 ; Check if it is last fragment in chain
jne .rebuild_packet_loop
 
pop ecx
xchg cl, ch
mov edx, eax
mov [edx + IPv4_header.TotalLength], cx
add esp, 8
xchg cl, ch
push ecx
 
push eax
jmp .handle_it ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr
 
.destroy_slot_pop:
add esp, 4
.destroy_slot:
DEBUGF 1,"IPv4_input: Destroy fragment slot!\n"
; TODO!
jmp .dump
 
 
 
 
 
;-----------------------------------------------------------------
;
; find fragment slot
;
; IN: pointer to fragmented packet in edx
; OUT: pointer to slot in esi, -1 on error
;
;-----------------------------------------------------------------
align 4
IPv4_find_fragment_slot:
 
;;; TODO: the RFC says we should check protocol number too
 
push eax ebx ecx edx
mov ax, [edx + IPv4_header.Identification]
mov ecx, MAX_FRAGMENTS
mov esi, FRAGMENT_LIST
mov ebx, [edx + IPv4_header.SourceAddress]
mov edx, [edx + IPv4_header.DestinationAddress]
.find_slot:
cmp [esi + FRAGMENT_slot.id], ax
jne .try_next
cmp [esi + FRAGMENT_slot.SrcIP], ebx
jne .try_next
cmp [esi + FRAGMENT_slot.DstIP], edx
je .found_slot
.try_next:
add esi, sizeof.FRAGMENT_slot
loop .find_slot
 
or esi, -1
.found_slot:
pop edx ecx ebx eax
ret
 
 
;------------------------------------------------------------------
;
; IPv4_output
;
; IN: eax = dest ip
; ebx = output device ptr/0 for automatic choice
; ecx = data length
; edx = source ip
; di = TTL shl 8 + protocol
;
; OUT: eax = pointer to buffer start
; ebx = pointer to device struct (needed for sending procedure)
; ecx = unchanged (packet size of embedded data)
; edx = size of complete buffer
; edi = pointer to start of data (0 on error)
;
;------------------------------------------------------------------
align 4
IPv4_output:
 
DEBUGF 1,"IPv4_output: size=%u\n", ecx
 
cmp ecx, 65500 ; Max IPv4 packet size
ja .too_large
 
push ecx eax edx di
 
cmp eax, 1 shl 24 + 127
je .loopback
 
call IPv4_route ; outputs device number in edi, dest ip in eax
call ARP_IP_to_MAC
test eax, 0xffff0000 ; error bits
jnz .arp_error
push ebx ; push the mac onto the stack
push ax
 
inc [IP_packets_tx + edi] ; update stats
 
mov ebx, [NET_DRV_LIST + edi]
lea eax, [ebx + ETH_DEVICE.mac]
mov edx, esp
mov ecx, [esp + 10 + 6]
add ecx, sizeof.IPv4_header
mov di, ETHER_IPv4
call ETH_output
jz .eth_error
add esp, 6 ; pop the mac out of the stack
 
.continue:
xchg cl, ch ; internet byte order
mov [edi + IPv4_header.VersionAndIHL], 0x45 ; IPv4, normal length (no Optional header)
mov [edi + IPv4_header.TypeOfService], 0 ; nothing special, just plain ip packet
mov [edi + IPv4_header.TotalLength], cx
mov [edi + IPv4_header.Identification], 0 ; fragment id: FIXME
mov [edi + IPv4_header.FlagsAndFragmentOffset], 0
pop word [edi + IPv4_header.TimeToLive] ; ttl shl 8 + protocol
; [edi + IPv4_header.Protocol]
mov [edi + IPv4_header.HeaderChecksum], 0
popd [edi + IPv4_header.SourceAddress]
popd [edi + IPv4_header.DestinationAddress]
 
pop ecx
 
IPv4_checksum edi
add edi, sizeof.IPv4_header
DEBUGF 2,"IPv4_output: success!\n"
ret
 
.eth_error:
DEBUGF 2,"IPv4_output: ethernet error\n"
add esp, 3*4+2+6
xor edi, edi
ret
 
.arp_error:
DEBUGF 2,"IPv4_output: ARP error=%x\n", eax
add esp, 3*4+2
xor edi, edi
ret
 
.too_large:
DEBUGF 2,"IPv4_output: Packet too large!\n"
xor edi, edi
ret
 
.loopback:
mov dword [esp + 2], eax
add ecx, sizeof.IPv4_header
mov di, ETHER_IPv4
call LOOP_output
jmp .continue
 
 
 
 
;------------------------------------------------------------------
;
; IPv4_output_raw
;
; IN: eax = socket ptr
; ecx = data length
; esi = data ptr
;
; OUT: /
;
;------------------------------------------------------------------
align 4
IPv4_output_raw:
 
DEBUGF 1,"IPv4_output_raw: size=%u ptr=%x socket=%x\n", ecx, esi, eax
 
cmp ecx, 1480 ;;;;; FIXME
ja .too_large
 
sub esp, 8
push esi eax
 
call IPv4_route
call ARP_IP_to_MAC
 
test eax, 0xffff0000 ; error bits
jnz .arp_error
 
push ebx ; push the mac
push ax
 
inc [IP_packets_tx + edi]
mov ebx, [NET_DRV_LIST + edi]
lea eax, [ebx + ETH_DEVICE.mac]
mov edx, esp
mov ecx, [esp + 6 + 4]
add ecx, sizeof.IPv4_header
mov di, ETHER_IPv4
call ETH_output
jz .error
 
add esp, 6 ; pop the mac
 
mov dword[esp+4+4], edx
mov dword[esp+4+4+4], eax
 
pop eax esi
;; todo: check socket options if we should add header, or just compute checksum
 
push edi ecx
rep movsb
pop ecx edi
 
; [edi + IPv4_header.VersionAndIHL] ; IPv4, normal length (no Optional header)
; [edi + IPv4_header.TypeOfService] ; nothing special, just plain ip packet
; [edi + IPv4_header.TotalLength]
; [edi + IPv4_header.TotalLength] ; internet byte order
; [edi + IPv4_header.FlagsAndFragmentOffset]
 
mov [edi + IPv4_header.HeaderChecksum], 0
 
; [edi + IPv4_header.TimeToLive] ; ttl shl 8 + protocol
; [edi + IPv4_header.Protocol]
; [edi + IPv4_header.Identification] ; fragment id
; [edi + IPv4_header.SourceAddress]
; [edi + IPv4_header.DestinationAddress]
 
IPv4_checksum edi ;;;; todo: checksum for IP packet with options!
add edi, sizeof.IPv4_header
DEBUGF 2,"IPv4_output_raw: device=%x\n", ebx
call [ebx + NET_DEVICE.transmit]
ret
 
.error:
add esp, 6
.arp_error:
add esp, 8+4+4
.too_large:
DEBUGF 2,"IPv4_output_raw: Failed\n"
sub edi, edi
ret
 
 
;--------------------------------------------------------
;
;
; IN: dword [esp] = pointer to buffer containing ipv4 packet to be fragmented
; dword [esp+4] = buffer size
; esi = pointer to ip header in that buffer
; ecx = max size of fragments
;
; OUT: /
;
;--------------------------------------------------------
 
align 4
IPv4_fragment:
 
DEBUGF 1,"IPv4_fragment\n"
 
and ecx, not 111b ; align 4
 
cmp ecx, sizeof.IPv4_header + 8 ; must be able to put at least 8 bytes
jb .err2
 
push esi ecx
mov eax, [esi + IPv4_header.DestinationAddress]
call ARP_IP_to_MAC
pop ecx esi
cmp eax, -1
jz .err2
 
push ebx
push ax
 
mov ebx, [NET_DRV_LIST]
lea eax, [ebx + ETH_DEVICE.mac]
push eax
 
 
push esi ; ptr to ip header
sub ecx, sizeof.IPv4_header ; substract header size
push ecx ; max data size
push dword 0 ; offset
 
.new_fragment:
DEBUGF 1,"Ipv4_fragment: new fragment"
 
 
mov eax, [esp + 3*4]
lea ebx, [esp + 4*4]
mov di , ETHER_IPv4
call ETH_output
 
cmp edi, -1
jz .err
 
; copy header
mov esi, [esp + 2*4]
mov ecx, 5 ; 5 dwords: TODO: use IHL field of the header!
rep movsd
 
; copy data
mov esi, [esp + 2*4]
add esi, sizeof.IPv4_header
add esi, [esp] ; offset
 
mov ecx, [esp + 1*4]
DEBUGF 1,"IPv4_fragment: copying %u bytes\n", ecx
rep movsb
 
; now, correct header
mov ecx, [esp + 1*4]
add ecx, sizeof.IPv4_header
xchg cl, ch
mov [edi + IPv4_header.TotalLength], cx
 
mov ecx, [esp] ; offset
xchg cl, ch
 
; cmp dword[esp + 4*4], 0 ; last fragment?;<<<<<<
; je .last_fragment
or cx, 1 shl 2 ; more fragments
; .last_fragment:
mov [edi + IPv4_header.FlagsAndFragmentOffset], cx
 
mov [edi + IPv4_header.HeaderChecksum], 0
 
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<< send the packet
mov ecx, [esp + 1*4]
 
push edx eax
IPv4_checksum edi
 
call [ebx + NET_DEVICE.transmit]
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 
mov ecx, [esp+4]
add [esp], ecx
 
mov ecx, [esp+3*4+6+4] ; ptr to begin of buff
add ecx, [esp+3*4+6+4+4] ; buff size
sub ecx, [esp+2*4] ; ptr to ip header
add ecx, [esp] ; offset
 
DEBUGF 1,"Ipv4_fragment: %u bytes remaining\n", ecx
 
cmp ecx, [esp+1*4]
jae .new_fragment
 
mov [esp+4], ecx ; set fragment size to remaining packet size
jmp .new_fragment
 
.err:
DEBUGF 1,"Ipv4_fragment: failed\n"
.done:
add esp, 12 + 4 + 6
.err2:
DEBUGF 1,"Ipv4_fragment: dumping\n"
call kernel_free
add esp, 4
 
ret
 
 
 
;---------------------------------------------------------------------------
;
; IPv4_route
;
; IN: eax = Destination IP
; OUT: edi = device id * 4
; eax = ip of gateway if nescessary, unchanged otherwise
;
;---------------------------------------------------------------------------
align 4
IPv4_route:
 
cmp eax, 0xffffffff
je .broadcast
 
xor edi, edi
mov ecx, MAX_NET_DEVICES
.loop:
mov ebx, [IP_LIST+edi]
and ebx, [SUBNET_LIST+edi]
jz .next
mov edx, eax
and edx, [SUBNET_LIST+edi]
 
cmp ebx, edx
je .found_it
.next:
add edi, 4
dec ecx
jnz .loop
 
.invalid:
xor edi, edi ; if none found, use device 0 as default
mov eax, [GATEWAY_LIST]
 
.found_it:
DEBUGF 1,"IPv4_dest_to_dev: %u\n", edi
ret
 
.broadcast:
xor edi, edi
ret
 
 
 
;---------------------------------------------------------------------------
;
; IPv4_get_frgmnt_num
;
; IN: /
; OUT: fragment number in ax
;
;---------------------------------------------------------------------------
align 4
IPv4_get_frgmnt_num:
xor ax, ax ;;; TODO: replace this with real code
 
ret
 
 
;---------------------------------------------------------------------------
;
; IPv4_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
IPv4_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, [IP_packets_tx + eax]
ret
 
.packets_rx:
mov eax, [IP_packets_rx + eax]
ret
 
.read_ip:
mov eax, [IP_LIST + eax]
ret
 
.write_ip:
mov [IP_LIST + eax], ecx
mov edi, eax ; device number, we'll need it for ARP
 
; pre-calculate the local broadcast address
mov ebx, [SUBNET_LIST + eax]
not ebx
or ebx, ecx
mov [BROADCAST_LIST + eax], ebx
 
mov eax, ecx
call ARP_output_request ; now send a gratuitous ARP
 
call NET_send_event
xor eax, eax
ret
 
.read_dns:
mov eax, [DNS_LIST + eax]
ret
 
.write_dns:
mov [DNS_LIST + eax], ecx
call NET_send_event
xor eax, eax
ret
 
.read_subnet:
mov eax, [SUBNET_LIST + eax]
ret
 
.write_subnet:
mov [SUBNET_LIST + eax], ecx
 
; pre-calculate the local broadcast address
mov ebx, [IP_LIST + eax]
not ecx
or ecx, ebx
mov [BROADCAST_LIST + eax], ecx
 
call NET_send_event
xor eax, eax
ret
 
.read_gateway:
mov eax, [GATEWAY_LIST + eax]
ret
 
.write_gateway:
mov [GATEWAY_LIST + eax], ecx
 
call NET_send_event
xor eax, eax
ret
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/trunk/network/IPv6.inc
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
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/trunk/network/PPPoE.inc
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
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/trunk/network/ethernet.inc
0,0 → 1,233
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ETHERNET.INC ;;
;; ;;
;; Ethernet network layer for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 3346 $
 
ETH_FRAME_MINIMUM = 60
 
struct ETH_header
 
DstMAC dp ? ; destination MAC-address
SrcMAC dp ? ; source MAC-address
Type dw ? ; type of the upper-layer protocol
 
ends
 
struct ETH_DEVICE NET_DEVICE
 
mac dp ?
 
ends
 
align 4
iglobal
 
ETH_BROADCAST dp 0xffffffffffff
endg
 
;-----------------------------------------------------------------
;
; ETH_input
;
; This function is called by ethernet drivers,
; It pushes the received ethernet packets onto the eth_in_queue
;
; IN: [esp] = Pointer to buffer
; [esp+4] = size of buffer
; ebx = pointer to eth_device
; OUT: /
;
;-----------------------------------------------------------------
align 4
ETH_input:
mov eax, [esp]
mov ecx, [esp+4]
 
DEBUGF 1,"ETH_input: size=%u\n", ecx
cmp ecx, ETH_FRAME_MINIMUM
jb .dump
sub ecx, sizeof.ETH_header
 
lea edx, [eax + sizeof.ETH_header]
mov ax, [eax + ETH_header.Type]
 
cmp ax, ETHER_IPv4
je IPv4_input
 
cmp ax, ETHER_ARP
je ARP_input
 
cmp ax, ETHER_IPv6
je IPv6_input
 
cmp ax, ETHER_PPP_DISCOVERY
je PPPoE_discovery_input
 
cmp ax, ETHER_PPP_SESSION
je PPPoE_session_input
 
DEBUGF 2,"ETH_input: Unknown packet type=%x\n", ax
 
.dump:
DEBUGF 2,"ETH_input: dumping\n"
call kernel_free
add esp, 4
ret
 
;-----------------------------------------------------------------
;
; ETH_output
;
; IN: eax = pointer to source mac
; ebx = device ptr
; ecx = packet size
; edx = pointer to destination mac
; di = protocol
;
; OUT: edi = 0 on error, pointer to buffer otherwise
; eax = buffer start
; ebx = to device structure
; ecx = unchanged (packet size of embedded data)
; edx = size of complete buffer
;
;-----------------------------------------------------------------
align 4
ETH_output:
 
DEBUGF 1,"ETH_output: size=%u device=%x\n", ecx, ebx
 
cmp ecx, [ebx + NET_DEVICE.mtu]
ja .exit
 
push ecx
push di eax edx
 
add ecx, sizeof.ETH_header
stdcall kernel_alloc, ecx
test eax, eax
jz .out_of_ram
mov edi, eax
 
pop esi
movsd
movsw
pop esi
movsd
movsw
pop ax
stosw
 
lea eax, [edi - sizeof.ETH_header] ; Set eax to buffer start
pop ecx
lea edx, [ecx + sizeof.ETH_header] ; Set edx to complete buffer size
 
cmp edx, ETH_FRAME_MINIMUM
jbe .adjust_size
.done:
DEBUGF 1,"ETH_output: ptr=%x size=%u\n", eax, edx
ret
 
.adjust_size:
mov edx, ETH_FRAME_MINIMUM
test edx, edx ; clear zero flag
jmp .done
 
.out_of_ram:
DEBUGF 2,"ETH_output: Out of ram!\n"
add esp, 4+4+2+4
sub edi, edi
ret
 
.exit:
DEBUGF 2,"ETH_output: Packet too large!\n"
sub edi, edi
ret
 
 
 
;-----------------------------------------------------------------
;
; ETH_API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;-----------------------------------------------------------------
align 4
ETH_api:
 
cmp bh, MAX_NET_DEVICES
ja .error
movzx eax, bh
mov eax, dword [NET_DRV_LIST + 4*eax]
cmp [eax + NET_DEVICE.type], NET_TYPE_ETH
jne .error
 
and ebx, 0xff
cmp ebx, .number
ja .error
jmp dword [.table + 4*ebx]
 
.table:
dd .packets_tx ; 0
dd .packets_rx ; 1
dd .bytes_tx ; 2
dd .bytes_rx ; 3
dd .read_mac ; 4
dd .state ; 5
.number = ($ - .table) / 4 - 1
 
.error:
or eax, -1
ret
 
.packets_tx:
mov eax, [eax + NET_DEVICE.packets_tx]
 
ret
 
.packets_rx:
mov eax, [eax + NET_DEVICE.packets_rx]
ret
 
.bytes_tx:
mov ebx, dword [eax + NET_DEVICE.bytes_tx + 4]
mov eax, dword [eax + NET_DEVICE.bytes_tx]
mov [esp+20+4], ebx ; TODO: fix this ugly code
ret
 
.bytes_rx:
mov ebx, dword [eax + NET_DEVICE.bytes_rx + 4]
mov eax, dword [eax + NET_DEVICE.bytes_rx]
mov [esp+20+4], ebx ; TODO: fix this ugly code
ret
 
 
.read_mac:
movzx ebx, word [eax + ETH_DEVICE.mac]
mov eax, dword [eax + ETH_DEVICE.mac + 2]
mov [esp+20+4], ebx ; TODO: fix this ugly code
ret
 
.state:
mov eax, [eax + NET_DEVICE.state]
ret
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/trunk/network/icmp.inc
1,193 → 1,431
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ICMP.INC ;;
;; ;;
;; Internet Control Message Protocol ( RFC 792 ) ;;
;; Part of the tcp/ip network stack for KolibriOS ;;
;; ;;
;; Last revision: 11.11.2006 ;;
;; Based on the work of [Johnny_B] and [smb] ;;
;; ;;
;; This file contains the following: ;;
;; icmp_rx - processes ICMP-packets received by the IP layer ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Changes history: ;;
;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;;
;; 11.11.2006 - [Johnny_B] and [smb] ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; Current status: ;;
;; This implemetation of ICMP proto supports message of ECHO type.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
$Revision: 2924 $
 
struc ICMP_PACKET
{ .Type db ? ;+00
.Code db ? ;+01
.Checksum dw ? ;+02
.Identifier dw ? ;+04
.SequenceNumber dw ? ;+06
.Data db ? ;+08
}
; ICMP types & codes
 
virtual at 0
ICMP_PACKET ICMP_PACKET
end virtual
ICMP_ECHOREPLY = 0 ; echo reply message
 
ICMP_UNREACH = 3
ICMP_UNREACH_NET = 0 ; bad net
ICMP_UNREACH_HOST = 1 ; bad host
ICMP_UNREACH_PROTOCOL = 2 ; bad protocol
ICMP_UNREACH_PORT = 3 ; bad port
ICMP_UNREACH_NEEDFRAG = 4 ; IP_DF caused drop
ICMP_UNREACH_SRCFAIL = 5 ; src route failed
ICMP_UNREACH_NET_UNKNOWN = 6 ; unknown net
ICMP_UNREACH_HOST_UNKNOWN = 7 ; unknown host
ICMP_UNREACH_ISOLATED = 8 ; src host isolated
ICMP_UNREACH_NET_PROHIB = 9 ; prohibited access
ICMP_UNREACH_HOST_PROHIB = 10 ; ditto
ICMP_UNREACH_TOSNET = 11 ; bad tos for net
ICMP_UNREACH_TOSHOST = 12 ; bad tos for host
ICMP_UNREACH_FILTER_PROHIB = 13 ; admin prohib
ICMP_UNREACH_HOST_PRECEDENCE = 14 ; host prec vio.
ICMP_UNREACH_PRECEDENCE_CUTOFF = 15 ; prec cutoff
 
; Example:
; ECHO message format
ICMP_SOURCEQUENCH = 4 ; Packet lost, slow down
 
ICMP_REDIRECT = 5 ; shorter route, codes:
ICMP_REDIRECT_NET = 0 ; for network
ICMP_REDIRECT_HOST = 1 ; for host
ICMP_REDIRECT_TOSNET = 2 ; for tos and net
ICMP_REDIRECT_TOSHOST = 3 ; for tos and host
 
ICMP_ALTHOSTADDR = 6 ; alternate host address
ICMP_ECHO = 8 ; echo service
ICMP_ROUTERADVERT = 9 ; router advertisement
ICMP_ROUTERADVERT_NORMAL = 0 ; normal advertisement
ICMP_ROUTERADVERT_NOROUTE_COMMON= 16 ; selective routing
 
ICMP_ROUTERSOLICIT = 10 ; router solicitation
ICMP_TIMXCEED = 11 ; time exceeded, code:
ICMP_TIMXCEED_INTRANS = 0 ; ttl==0 in transit
ICMP_TIMXCEED_REASS = 1 ; ttl==0 in reass
 
ICMP_PARAMPROB = 12 ; ip header bad
ICMP_PARAMPROB_ERRATPTR = 0 ; error at param ptr
ICMP_PARAMPROB_OPTABSENT = 1 ; req. opt. absent
ICMP_PARAMPROB_LENGTH = 2 ; bad length
 
ICMP_TSTAMP = 13 ; timestamp request
ICMP_TSTAMPREPLY = 14 ; timestamp reply
ICMP_IREQ = 15 ; information request
ICMP_IREQREPLY = 16 ; information reply
ICMP_MASKREQ = 17 ; address mask request
ICMP_MASKREPLY = 18 ; address mask reply
ICMP_TRACEROUTE = 30 ; traceroute
ICMP_DATACONVERR = 31 ; data conversion error
ICMP_MOBILE_REDIRECT = 32 ; mobile host redirect
ICMP_IPV6_WHEREAREYOU = 33 ; IPv6 where-are-you
ICMP_IPV6_IAMHERE = 34 ; IPv6 i-am-here
ICMP_MOBILE_REGREQUEST = 35 ; mobile registration req
ICMP_MOBILE_REGREPLY = 36 ; mobile registreation reply
ICMP_SKIP = 39 ; SKIP
 
ICMP_PHOTURIS = 40 ; Photuris
ICMP_PHOTURIS_UNKNOWN_INDEX = 1 ; unknown sec index
ICMP_PHOTURIS_AUTH_FAILED = 2 ; auth failed
ICMP_PHOTURIS_DECRYPT_FAILED = 3 ; decrypt failed
 
 
 
struct ICMP_header
 
Type db ?
Code db ?
Checksum dw ?
Identifier dw ?
SequenceNumber dw ?
 
ends
 
 
align 4
uglobal
ICMP_PACKETS_TX rd MAX_NET_DEVICES
ICMP_PACKETS_RX rd MAX_NET_DEVICES
endg
 
 
 
;-----------------------------------------------------------------
;
; ICMP_init
;
; 0 1 2 3
; 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | Type | Code | Checksum |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | Identifier | Sequence Number |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | Data ...
; +-+-+-+-+-
;
;-----------------------------------------------------------------
 
macro ICMP_init {
 
xor eax, eax
mov edi, ICMP_PACKETS_TX
mov ecx, 2*MAX_NET_DEVICES
rep stosd
 
}
 
 
;-----------------------------------------------------------------
;
; ICMP types & codes, RFC 792 and FreeBSD's ICMP sources
; ICMP_input:
;
; This procedure will send reply's to ICMP echo's
; and insert packets into sockets when needed
;
; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
; ebx = pointer to device struct
; ecx = ICMP Packet size
; esi = ptr to ICMP Packet data
; edi = ptr to ipv4 source and dest address
;
; OUT: /
;
;-----------------------------------------------------------------
align 4
ICMP_input:
 
ICMP_ECHOREPLY equ 0 ; echo reply message
DEBUGF 1,"ICMP_input:\n"
 
ICMP_UNREACH equ 3
ICMP_UNREACH_NET equ 0 ; bad net
ICMP_UNREACH_HOST equ 1 ; bad host
ICMP_UNREACH_PROTOCOL equ 2 ; bad protocol
ICMP_UNREACH_PORT equ 3 ; bad port
ICMP_UNREACH_NEEDFRAG equ 4 ; IP_DF caused drop
ICMP_UNREACH_SRCFAIL equ 5 ; src route failed
ICMP_UNREACH_NET_UNKNOWN equ 6 ; unknown net
ICMP_UNREACH_HOST_UNKNOWN equ 7 ; unknown host
ICMP_UNREACH_ISOLATED equ 8 ; src host isolated
ICMP_UNREACH_NET_PROHIB equ 9 ; prohibited access
ICMP_UNREACH_HOST_PROHIB equ 10 ; ditto
ICMP_UNREACH_TOSNET equ 11 ; bad tos for net
ICMP_UNREACH_TOSHOST equ 12 ; bad tos for host
ICMP_UNREACH_FILTER_PROHIB equ 13 ; admin prohib
ICMP_UNREACH_HOST_PRECEDENCE equ 14 ; host prec vio.
ICMP_UNREACH_PRECEDENCE_CUTOFF equ 15 ; prec cutoff
; First, check the checksum (altough some implementations ignore it)
 
ICMP_SOURCEQUENCH equ 4 ; packet lost, slow down
push esi ecx
push [esi + ICMP_header.Checksum]
mov [esi + ICMP_header.Checksum], 0
xor edx, edx
call checksum_1
call checksum_2
pop si
cmp dx, si
pop ecx edx
jne .checksum_mismatch
 
ICMP_REDIRECT equ 5 ; shorter route, codes:
ICMP_REDIRECT_NET equ 0 ; for network
ICMP_REDIRECT_HOST equ 1 ; for host
ICMP_REDIRECT_TOSNET equ 2 ; for tos and net
ICMP_REDIRECT_TOSHOST equ 3 ; for tos and host
cmp [edx + ICMP_header.Type], ICMP_ECHO ; Is this an echo request?
jne .check_sockets
 
ICMP_ALTHOSTADDR equ 6 ; alternate host address
ICMP_ECHO equ 8 ; echo service
ICMP_ROUTERADVERT equ 9 ; router advertisement
ICMP_ROUTERADVERT_NORMAL equ 0 ; normal advertisement
ICMP_ROUTERADVERT_NOROUTE_COMMON equ 16 ; selective routing
; We well re-use the packet so we can create the response as fast as possible
; Notice: this only works on pure ethernet
 
ICMP_ROUTERSOLICIT equ 10 ; router solicitation
ICMP_TIMXCEED equ 11 ; time exceeded, code:
ICMP_TIMXCEED_INTRANS equ 0 ; ttl==0 in transit
ICMP_TIMXCEED_REASS equ 1 ; ttl==0 in reass
DEBUGF 1,"got echo request\n"
mov [edx + ICMP_header.Type], ICMP_ECHOREPLY ; Change Packet type to reply
 
ICMP_PARAMPROB equ 12 ; ip header bad
ICMP_PARAMPROB_ERRATPTR equ 0 ; error at param ptr
ICMP_PARAMPROB_OPTABSENT equ 1 ; req. opt. absent
ICMP_PARAMPROB_LENGTH equ 2 ; bad length
mov esi, [esp] ; Start of buffer
 
ICMP_TSTAMP equ 13 ; timestamp request
ICMP_TSTAMPREPLY equ 14 ; timestamp reply
ICMP_IREQ equ 15 ; information request
ICMP_IREQREPLY equ 16 ; information reply
ICMP_MASKREQ equ 17 ; address mask request
ICMP_MASKREPLY equ 18 ; address mask reply
ICMP_TRACEROUTE equ 30 ; traceroute
ICMP_DATACONVERR equ 31 ; data conversion error
ICMP_MOBILE_REDIRECT equ 32 ; mobile host redirect
ICMP_IPV6_WHEREAREYOU equ 33 ; IPv6 where-are-you
ICMP_IPV6_IAMHERE equ 34 ; IPv6 i-am-here
ICMP_MOBILE_REGREQUEST equ 35 ; mobile registration req
ICMP_MOBILE_REGREPLY equ 36 ; mobile registreation reply
ICMP_SKIP equ 39 ; SKIP
cmp dword[edi + 4], 1 shl 24 + 127
je .loopback
 
ICMP_PHOTURIS equ 40 ; Photuris
ICMP_PHOTURIS_UNKNOWN_INDEX equ 1 ; unknown sec index
ICMP_PHOTURIS_AUTH_FAILED equ 2 ; auth failed
ICMP_PHOTURIS_DECRYPT_FAILED equ 3 ; decrypt failed
; Update stats (and validate device ptr)
call NET_ptr_to_num
cmp edi,-1
je .dump
inc [ICMP_PACKETS_RX + 4*edi]
inc [ICMP_PACKETS_TX + 4*edi]
 
; exchange dest and source address in IP header
; exchange dest and source MAC in ETH header
push dword [esi + ETH_header.DstMAC]
push dword [esi + ETH_header.SrcMAC]
pop dword [esi + ETH_header.DstMAC]
pop dword [esi + ETH_header.SrcMAC]
push word [esi + ETH_header.DstMAC + 4]
push word [esi + ETH_header.SrcMAC + 4]
pop word [esi + ETH_header.DstMAC + 4]
pop word [esi + ETH_header.SrcMAC + 4]
add esi, sizeof.ETH_header-2
 
;***************************************************************************
; Function
; icmp_rx [by Johnny_B]
.loopback:
add esi, 2
push [esi + IPv4_header.SourceAddress]
push [esi + IPv4_header.DestinationAddress]
pop [esi + IPv4_header.SourceAddress]
pop [esi + IPv4_header.DestinationAddress]
 
; Recalculate ip header checksum
movzx ecx, [esi + IPv4_header.VersionAndIHL] ; Calculate IP Header length by using IHL field
and ecx, 0x0f
shl cx, 2
mov edi, ecx ; IP header length
mov eax, edx ; ICMP packet start addr
 
push esi ; Calculate the IP checksum
xor edx, edx ;
call checksum_1 ;
call checksum_2 ;
pop esi ;
mov [esi + IPv4_header.HeaderChecksum], dx ;
 
; Recalculate ICMP CheckSum
movzx ecx, [esi + IPv4_header.TotalLength] ; Find length of IP Packet
xchg ch, cl ;
sub ecx, edi ; IP packet length - IP header length = ICMP packet length
 
mov esi, eax ; Calculate ICMP checksum
xor edx, edx ;
call checksum_1 ;
call checksum_2 ;
mov [eax + ICMP_header.Checksum], dx ;
 
; Transmit the packet (notice that packet ptr and packet size have been on stack since start of the procedure!)
call [ebx + NET_DEVICE.transmit]
ret
 
 
 
 
.check_sockets:
; Look for an open ICMP socket
 
mov esi, [edi] ; ipv4 source address
mov eax, net_sockets
.try_more:
; mov , [edx + ICMP_header.Identifier]
.next_socket:
mov eax, [eax + SOCKET.NextPtr]
or eax, eax
jz .dump
 
cmp [eax + SOCKET.Domain], AF_INET4
jne .next_socket
 
cmp [eax + SOCKET.Protocol], IP_PROTO_ICMP
jne .next_socket
 
cmp [eax + IP_SOCKET.RemoteIP], esi
jne .next_socket
 
; cmp [eax + ICMP_SOCKET.Identifier],
; jne .next_socket
 
; call IPv4_dest_to_dev
; cmp edi,-1
; je .dump
; inc [ICMP_PACKETS_RX+edi]
 
DEBUGF 1,"socket=%x\n", eax
 
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
 
mov esi, edx
jmp SOCKET_input
 
 
.checksum_mismatch:
DEBUGF 1,"checksum mismatch\n"
 
.dump:
DEBUGF 1,"ICMP_input: dumping\n"
 
call kernel_free
add esp, 4 ; pop (balance stack)
 
ret
 
 
;-----------------------------------------------------------------
;
; Description
; ICMP protocol handler
; This is a kernel function, called by ip_rx
; ICMP_output
;
; IN:
; buffer_number - # of IP-buffer. This buffer must be reused or marked as empty afterwards
; IPPacketBase - IP_PACKET base address
; IPHeaderLength - Header length of IP_PACKET
; IN: eax = dest ip
; ebx = source ip
; ecx = data length
; dh = type
; dl = code
; esi = data offset
; edi = identifier shl 16 + sequence number
;
; OUT:
; EAX=not defined
;-----------------------------------------------------------------
align 4
ICMP_output:
 
DEBUGF 1,"Creating ICMP Packet\n"
 
push esi edi dx
 
mov edx, [eax + IP_SOCKET.LocalIP]
mov eax, [eax + IP_SOCKET.RemoteIP]
add ecx, sizeof.ICMP_header
mov di, IP_PROTO_ICMP SHL 8 + 128 ; TTL
call IPv4_output
jz .exit
 
DEBUGF 1,"full icmp packet size: %u\n", edx
 
pop word [edi + ICMP_header.Type] ; Write both type and code bytes at once
pop dword [edi + ICMP_header.Identifier] ; identifier and sequence number
mov [edi + ICMP_header.Checksum], 0
 
push ebx ecx edx
mov esi, edi
xor edx, edx
call checksum_1
call checksum_2
mov [edi + ICMP_header.Checksum], dx
pop edx ecx ebx esi
 
sub ecx, sizeof.ICMP_header
add edi, sizeof.ICMP_header
push cx
shr cx, 2
rep movsd
pop cx
and cx, 3
rep movsb
 
sub edi, edx ;;; TODO: find a better way to remember start of packet
push edx edi
DEBUGF 1,"Sending ICMP Packet\n"
call [ebx + NET_DEVICE.transmit]
ret
.exit:
DEBUGF 1,"Creating ICMP Packet failed\n"
add esp, 2*4 + 2
ret
 
 
 
 
;-----------------------------------------------------------------
;
; All used registers will be saved
; ICMP_output
;
;***************************************************************************
proc icmp_rx stdcall uses ebx esi edi,\
buffer_number:DWORD,IPPacketBase:DWORD,IPHeaderLength:DWORD
; IN: eax = socket ptr
; ecx = data length
; esi = data offset
;
;-----------------------------------------------------------------
align 4
ICMP_output_raw:
 
mov esi, [IPPacketBase];esi=IP_PACKET base address
mov edi, esi
add edi, [IPHeaderLength];edi=ICMP_PACKET base address
DEBUGF 1,"Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
 
cmp byte[edi + ICMP_PACKET.Type], ICMP_ECHO; Is this an echo request? discard if not
jz .icmp_echo
push edx
 
mov eax, [buffer_number]
call freeBuff
jmp .exit
mov di, IP_PROTO_ICMP SHL 8 + 128 ; TTL
mov edx, [eax + IP_SOCKET.LocalIP]
mov eax, [eax + IP_SOCKET.RemoteIP]
call IPv4_output
jz .exit
 
.icmp_echo:
pop esi
push edx
push eax
 
; swap the source and destination addresses
mov ecx, [esi + IP_PACKET.DestinationAddress]
mov ebx, [esi + IP_PACKET.SourceAddress]
mov [esi + IP_PACKET.DestinationAddress], ebx
mov [esi + IP_PACKET.SourceAddress], ecx
push edi ecx
DEBUGF 1,"copying %u bytes from %x to %x\n", ecx, esi, edi
rep movsb
pop ecx edi
 
; recalculate the IP header checksum
mov eax, [IPHeaderLength]
stdcall checksum_jb, esi, eax;buf_ptr,buf_size
mov [edi + ICMP_header.Checksum], 0
 
mov byte[esi + IP_PACKET.HeaderChecksum], ah
mov byte[esi + IP_PACKET.HeaderChecksum + 1], al ; ?? correct byte order?
mov esi, edi
xor edx, edx
call checksum_1
call checksum_2
mov [edi + ICMP_header.Checksum], dx
 
mov byte[edi + ICMP_PACKET.Type], ICMP_ECHOREPLY; change the request to a response
mov word[edi + ICMP_PACKET.Checksum], 0; clear ICMP checksum prior to re-calc
DEBUGF 1,"Sending ICMP Packet\n"
call [ebx + NET_DEVICE.transmit]
ret
.exit:
DEBUGF 1,"Creating ICMP Packet failed\n"
add esp, 4
ret
 
; Calculate the length of the ICMP data ( IP payload)
xor eax, eax
mov ah, byte[esi + IP_PACKET.TotalLength]
mov al, byte[esi + IP_PACKET.TotalLength + 1]
sub ax, word[IPHeaderLength];ax=ICMP-packet length
 
stdcall checksum_jb, edi, eax;buf_ptr,buf_size
 
mov byte[edi + ICMP_PACKET.Checksum], ah
mov byte[edi + ICMP_PACKET.Checksum + 1], al
 
; Queue packet for transmission
mov ebx, [buffer_number]
mov eax, NET1OUT_QUEUE
call queue
;-----------------------------------------------------------------
;
; ICMP_API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;-----------------------------------------------------------------
align 4
ICMP_api:
 
.exit:
movzx eax, bh
shl eax, 2
 
test bl, bl
jz .packets_tx ; 0
dec bl
jz .packets_rx ; 1
 
.error:
mov eax, -1
ret
endp
 
.packets_tx:
mov eax, [ICMP_PACKETS_TX + eax]
ret
 
.packets_rx:
mov eax, [ICMP_PACKETS_RX + eax]
ret
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/loopback.inc
0,0 → 1,126
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; loopback.inc ;;
;; ;;
;; LoopBack device for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 2891 $
 
iglobal
 
LOOPBACK_DEVICE:
.type dd NET_TYPE_LOOPBACK
.mtu dd 4096
.name dd .namestr
 
.unload dd .dummy_fn
.reset dd .dummy_fn
.transmit dd LOOP_input
 
.bytes_tx dq 0
.bytes_rx dq 0
.packets_tx dd 0
.packets_rx dd 0
 
.namestr db 'loopback', 0
 
.dummy_fn:
ret
 
endg
 
;-----------------------------------------------------------------
;
; LOOP_input
;
; IN: [esp+4] = Pointer to buffer
; [esp+8] = size of buffer
;
; OUT: /
;
;-----------------------------------------------------------------
align 4
LOOP_input:
pop ebx
pop eax
pop ecx
 
push ebx
push ecx
push eax
 
DEBUGF 1,"LOOP_input: size=%u\n", ecx
lea edx, [eax + 2]
mov ax, word[eax]
mov ebx, LOOPBACK_DEVICE
 
cmp ax, ETHER_IPv4
je IPv4_input
 
DEBUGF 2,"LOOP_input: Unknown packet type=%x\n", ax
 
.dump:
DEBUGF 2,"LOOP_input: dumping\n"
call kernel_free
add esp, 4
ret
 
;-----------------------------------------------------------------
;
; LOOP_output
;
; IN:
; ecx = packet size
; di = protocol
;
; OUT: edi = 0 on error, pointer to buffer otherwise
; eax = buffer start
; ebx = to device structure
; ecx = unchanged (packet size of embedded data)
; edx = size of complete buffer
;
;-----------------------------------------------------------------
align 4
LOOP_output:
 
DEBUGF 1,"LOOP_output\n"
 
push ecx
push di
 
add ecx, 2
cmp ecx, [LOOPBACK_DEVICE.mtu]
ja .out_of_ram
stdcall kernel_alloc, ecx
test eax, eax
jz .out_of_ram
mov edi, eax
pop ax
stosw
 
lea eax, [edi - 2] ; Set eax to buffer start
pop ecx
lea edx, [ecx + 2] ; Set edx to complete buffer size
mov ebx, LOOPBACK_DEVICE
 
.done:
DEBUGF 2,"LOOP_output: ptr=%x size=%u\n", eax, edx
ret
 
.out_of_ram:
DEBUGF 2,"LOOP_output: failed\n"
add esp, 2+4
sub edi, edi
ret
 
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/trunk/network/queue.inc
1,229 → 1,100
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; queue.inc ;;
;; ;;
;; QUEUE.INC ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Buffer queue management for Menuet OS TCP/IP Stack ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
$Revision: 2305 $
 
 
;*******************************************************************
; Interface
; The Queues implemented by these macros form a ring-buffer.
; The data to these queue's always looks like this:
;
; queueInit Configures the queues to empty
; dequeue Removes a buffer pointer from a queue
; queue Inserts a buffer pointer into a queue
; freeBuff Adds the buffer pointer to the list of free buffers
; queueSize Returns the number of entries in a queue
;
; The various defines for queue names can be found in stack.inc
;
;*******************************************************************
; At top, you have the queue struct, wich has the size (number of currently queued packets, read and write pointers.
; This struct is followed by a number of slots wich you can read and write to using the macros.
; How these slots look like is up to you to chose, normally they should have at least a pointer to where the real data is.
; (you can see some examples below)
 
 
;***************************************************************************
; Function
; freeBuff
;
; Description
; Adds a buffer number to the beginning of the free list.
; buffer number in eax ( ms word zeroed )
; all other registers preserved
; This always works, so no error returned
;***************************************************************************
;uglobal
; freeBuff_cnt dd ?
;endg
freeBuff:
; inc [freeBuff_cnt]
; DEBUGF 1, "K : freeBuff (%u)\n", [freeBuff_cnt]
push ebx
push ecx
mov ebx, queues + EMPTY_QUEUE * 2
cli ; Ensure that another process does not interfer
mov cx, [ebx]
mov [ebx], ax
mov [queueList + eax * 2], cx
sti
pop ecx
pop ebx
struct queue
 
ret
size dd ? ; number of queued packets in this queue
w_ptr dd ? ; current writing pointer in queue
r_ptr dd ? ; current reading pointer
 
ends
 
;***************************************************************************
; Function
; queueSize
;
; Description
; Counts the number of entries in a queue
; queue number in ebx ( ms word zeroed )
; Queue size returned in eax
; This always works, so no error returned
;***************************************************************************
queueSize:
xor eax, eax
shl ebx, 1
add ebx, queues
movzx ecx, word [ebx]
cmp cx, NO_BUFFER
je qs_exit
; The following macros share these inputs:
 
qs_001:
inc eax
shl ecx, 1
add ecx, queueList
movzx ecx, word [ecx]
cmp cx, NO_BUFFER
je qs_exit
jmp qs_001
; ptr = pointer to where the queue data is located
; size = number of slots/entrys in the queue
; entry_size = size of one slot, in bytes
; failaddr = the address where macro will jump to when there is no data in the queue
 
qs_exit:
ret
; additionally, add_to_queue requires you to set esi to the data wich you want to queue
; get_from_queue on the other hand will return a pointer in esi, to the entry you're interessed in
; PS: macros WILL destroy ecx and edi
 
macro add_to_queue ptr, size, entry_size, failaddr {
 
;***************************************************************************
; Function
; queue
;
; Description
; Adds a buffer number to the *end* of a queue
; This is quite quick because these queues will be short
; queue number in eax ( ms word zeroed )
; buffer number in ebx ( ms word zeroed )
; all other registers preserved
; This always works, so no error returned
;***************************************************************************
;uglobal
; queue_cnt dd ?
;endg
queue:
; inc [queue_cnt]
; DEBUGF 1, "K : queue (%u)\n", [queue_cnt]
push ebx
shl ebx, 1
add ebx, queueList ; eax now holds address of queue entry
mov [ebx], word NO_BUFFER; This buffer will be the last
cmp [ptr + queue.size], size ; Check if queue isnt full
jae failaddr
 
cli
shl eax, 1
add eax, queues ; eax now holds address of queue
movzx ebx, word [eax]
inc [ptr + queue.size] ; if not full, queue one more
 
cmp bx, NO_BUFFER
jne qu_001
mov edi, [ptr + queue.w_ptr] ; Current write pointer (FIFO!)
mov ecx, entry_size/4 ; Write the queue entry
rep movsd ;
 
pop ebx
; The list is empty, so add this to the head
mov [eax], bx
jmp qu_exit
lea ecx, [size*entry_size+ptr+sizeof.queue]
cmp edi, ecx ; entry size
jb .no_wrap
 
qu_001:
; Find the last entry
shl ebx, 1
add ebx, queueList
mov eax, ebx
movzx ebx, word [ebx]
cmp bx, NO_BUFFER
jne qu_001
sub edi, size*entry_size
 
mov ebx, eax
pop eax
mov [ebx], ax
.no_wrap:
mov [ptr + queue.w_ptr], edi
 
qu_exit:
sti
ret
}
 
 
 
;***************************************************************************
; Function
; dequeue
;
; Description
; removes a buffer number from the head of a queue
; This is fast, as it unlinks the first entry in the list
; queue number in eax ( ms word zeroed )
; buffer number returned in eax ( ms word zeroed )
; all other registers preserved
;
;***************************************************************************
;uglobal
; dequeue_cnt dd ?
;endg
dequeue:
push ebx
shl eax, 1
add eax, queues ; eax now holds address of queue
mov ebx, eax
cli
movzx eax, word [eax]
cmp ax, NO_BUFFER
je dq_exit
; inc [dequeue_cnt]
; DEBUGF 1, "K : dequeue (%u)\n", [dequeue_cnt]
push eax
shl eax, 1
add eax, queueList ; eax now holds address of queue entry
mov ax, [eax]
mov [ebx], ax
pop eax
macro get_from_queue ptr, size, entry_size, failaddr {
 
dq_exit:
sti
pop ebx
ret
cmp [ptr + queue.size], 0 ; any packets queued?
je failaddr
 
dec [ptr + queue.size] ; if so, dequeue one
 
;***************************************************************************
; Function
; queueInit
;
; Description
; Initialises the queues to empty, and creates the free queue
; list.
;
;***************************************************************************
queueInit:
mov esi, queues
mov ecx, NUMQUEUES
mov ax, NO_BUFFER
mov esi, [ptr + queue.r_ptr]
push esi
 
qi001:
mov [esi], ax
inc esi
inc esi
loop qi001
add esi, entry_size
 
mov esi, queues + ( 2 * EMPTY_QUEUE )
lea ecx, [size*entry_size+ptr+sizeof.queue]
cmp esi, ecx ; entry size
jb .no_wrap
 
; Initialise empty queue list
sub esi, size*entry_size
 
xor ax, ax
mov [esi], ax
.no_wrap:
mov dword [ptr + queue.r_ptr], esi
 
mov ecx, NUMQUEUEENTRIES - 1
mov esi, queueList
pop esi
 
qi002:
inc ax
mov [esi], ax
inc esi
inc esi
loop qi002
}
 
mov ax, NO_BUFFER
mov [esi], ax
macro init_queue ptr {
 
ret
mov [ptr + queue.size] , 0
lea edi, [ptr + sizeof.queue]
mov [ptr + queue.w_ptr], edi
mov [ptr + queue.r_ptr], edi
}
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/socket.inc
1,1129 → 1,2284
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; SOCKET.INC ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
;; ;;
;; Sockets constants, structures and functions ;;
;; Written by hidnplayr@kolibrios.org, ;;
;; and Clevermouse. ;;
;; ;;
;; This file contains the following: ;;
;; is_localport_unused ;;
;; get_free_socket ;;
;; socket_open ;;
;; socket_open_tcp ;;
;; socket_close ;;
;; socket_close_tcp ;;
;; socket_poll ;;
;; socket_status ;;
;; socket_read ;;
;; socket_write ;;
;; socket_write_tcp ;;
;; Based on code by mike.dld ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; Changes history: ;;
;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;;
;; 11.11.2006 - [Johnny_B] and [smb] ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
$Revision: 3514 $
 
; socket data structure
 
struct SOCKET
 
NextPtr dd ? ; pointer to next socket in list
PrevPtr dd ? ; pointer to previous socket in list
NextPtr dd ? ; pointer to next socket in list
Number dd ? ; socket number (unique within single process)
PID dd ? ; application process id
LocalIP dd ? ; local IP address
LocalPort dw ? ; local port
RemoteIP dd ? ; remote IP address
RemotePort dw ? ; remote port
OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state)
OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state)
rxDataCount dd ? ; rx data count
TCBState dd ? ; TCB state
TCBTimer dd ? ; TCB timer (seconds)
ISS dd ? ; initial send sequence
IRS dd ? ; initial receive sequence
SND_UNA dd ? ; sequence number of unack'ed sent packets
SND_NXT dd ? ; bext send sequence number to use
Number dd ? ; socket number
 
mutex MUTEX
 
PID dd ? ; process ID
TID dd ? ; thread ID
Domain dd ? ; INET/LOCAL/..
Type dd ? ; RAW/STREAM/DGRAP
Protocol dd ? ; ICMP/IPv4/ARP/TCP/UDP
errorcode dd ?
device dd ? ; driver pointer, socket pointer if it's an LOCAL socket
 
options dd ?
state dd ?
backlog dw ? ; how many incoming connections that can be queued
 
snd_proc dd ?
rcv_proc dd ?
 
ends
 
struct IP_SOCKET SOCKET
 
LocalIP rd 4 ; network byte order
RemoteIP rd 4 ; network byte order
 
ends
 
struct TCP_SOCKET IP_SOCKET
 
LocalPort dw ? ; network byte order
RemotePort dw ? ; network byte order
 
t_state dd ? ; TCB state
t_rxtshift db ?
rb 3 ; align
t_rxtcur dd ?
t_dupacks dd ?
t_maxseg dd ?
t_force dd ?
t_flags dd ?
 
;---------------
; RFC783 page 21
 
; send sequence
SND_UNA dd ? ; sequence number of unack'ed sent Packets
SND_NXT dd ? ; next send sequence number to use
SND_UP dd ? ; urgent pointer
SND_WL1 dd ? ; window minus one
SND_WL2 dd ? ;
ISS dd ? ; initial send sequence number
SND_WND dd ? ; send window
 
; receive sequence
RCV_WND dd ? ; receive window
RCV_NXT dd ? ; next receive sequence number to use
RCV_WND dd ? ; receive window
SEG_LEN dd ? ; segment length
SEG_WND dd ? ; segment window
wndsizeTimer dd ? ; window size timer
mutex MUTEX ; lock mutex
rxData dd ? ; receive data buffer here
RCV_UP dd ? ; urgent pointer
IRS dd ? ; initial receive sequence number
 
;---------------------
; Additional variables
 
; receive variables
RCV_ADV dd ?
 
; retransmit variables
SND_MAX dd ?
 
; congestion control
SND_CWND dd ?
SND_SSTHRESH dd ?
 
;----------------------
; Transmit timing stuff
t_idle dd ?
t_rtt dd ?
t_rtseq dd ?
t_srtt dd ?
t_rttvar dd ?
t_rttmin dd ?
max_sndwnd dd ?
 
;-----------------
; Out-of-band data
t_oobflags dd ?
t_iobc dd ?
t_softerror dd ?
 
 
;---------
; RFC 1323 ; the order of next 4 elements may not change
 
SND_SCALE db ?
RCV_SCALE db ?
requested_s_scale db ?
request_r_scale db ?
 
ts_recent dd ? ; a copy of the most-recent valid timestamp from the other end
ts_recent_age dd ?
last_ack_sent dd ?
 
 
;-------
; Timers
timer_retransmission dd ? ; rexmt
timer_persist dd ?
timer_keepalive dd ? ; keepalive/syn timeout
timer_timed_wait dd ? ; also used as 2msl timer
 
; extra
 
ts_ecr dd ? ; timestamp echo reply
ts_val dd ?
 
seg_next dd ? ; re-assembly queue
 
temp_bits db ?
rb 3 ; align
 
ends
 
; TCP opening modes
SOCKET_PASSIVE = 0
SOCKET_ACTIVE = 1
struct UDP_SOCKET IP_SOCKET
 
; socket types
SOCK_STREAM = 1
SOCK_DGRAM = 2
LocalPort dw ? ; network byte order
RemotePort dw ? ; network byte order
firstpacket db ?
 
; pointer to bitmap of free ports (1=free, 0=used)
ends
 
 
struct ICMP_SOCKET IP_SOCKET
 
Identifier dw ?
 
ends
 
 
struct RING_BUFFER
 
mutex MUTEX
start_ptr dd ? ; Pointer to start of buffer
end_ptr dd ? ; pointer to end of buffer
read_ptr dd ? ; Read pointer
write_ptr dd ? ; Write pointer
size dd ? ; Number of bytes buffered
 
ends
 
struct STREAM_SOCKET TCP_SOCKET
 
rcv RING_BUFFER
snd RING_BUFFER
 
ends
 
struct socket_queue_entry
 
data_ptr dd ?
buf_ptr dd ?
data_size dd ?
 
ends
 
 
SOCKETBUFFSIZE = 4096 ; in bytes
 
SOCKET_QUEUE_SIZE = 10 ; maximum number of incoming packets queued for 1 socket
; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
SOCKET_QUEUE_LOCATION = (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*sizeof.socket_queue_entry - sizeof.queue)
 
uglobal
align 4
network_free_ports dd ?
net_sockets rd 4
last_socket_num dd ?
last_UDP_port dw ? ; These values give the number of the last used ephemeral port
last_TCP_port dw ? ;
endg
 
iglobal
 
;-----------------------------------------------------------------
;
; SOCKET_init
;
;-----------------------------------------------------------------
macro SOCKET_init {
 
xor eax, eax
mov edi, net_sockets
mov ecx, 5
rep stosd
 
@@:
pseudo_random eax
cmp ax, MIN_EPHEMERAL_PORT
jb @r
cmp ax, MAX_EPHEMERAL_PORT
ja @r
xchg al, ah
mov [last_UDP_port], ax
 
@@:
pseudo_random eax
cmp ax, MIN_EPHEMERAL_PORT
jb @r
cmp ax, MAX_EPHEMERAL_PORT
ja @r
xchg al, ah
mov [last_TCP_port], ax
 
}
 
;-----------------------------------------------------------------
;
; Socket API (function 74)
;
;-----------------------------------------------------------------
align 4
network_free_hint dd 1024/8
endg
sys_socket:
 
;; Allocate memory for socket data and put new socket into the list
; Newly created socket is initialized with calling PID and number and
; put into beginning of list (which is a fastest way).
cmp ebx, 255
jz SOCKET_debug
 
cmp ebx, .number
ja s_error
jmp dword [.table + 4*ebx]
 
.table:
dd SOCKET_open ; 0
dd SOCKET_close ; 1
dd SOCKET_bind ; 2
dd SOCKET_listen ; 3
dd SOCKET_connect ; 4
dd SOCKET_accept ; 5
dd SOCKET_send ; 6
dd SOCKET_receive ; 7
dd SOCKET_set_opt ; 8
dd SOCKET_get_opt ; 9
dd SOCKET_pair ; 10
.number = ($ - .table) / 4 - 1
 
s_error:
DEBUGF 2,"SOCKET: error\n"
mov dword [esp+32], -1
 
ret
 
;-----------------------------------------------------------------
;
; @return socket structure address in EAX
;;
proc net_socket_alloc stdcall uses ebx ecx edx edi
stdcall kernel_alloc, SOCKETBUFFSIZE
DEBUGF 1, "K : net_socket_alloc (0x%x)\n", eax
; check if we can allocate needed amount of memory
or eax, eax
jz .exit
; SOCKET_open
;
; IN: domain in ecx
; type in edx
; protocol in esi
; OUT: eax is socket num, -1 on error
;
;-----------------------------------------------------------------
align 4
SOCKET_open:
 
; zero-initialize allocated memory
DEBUGF 2,"SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi
 
push ecx edx esi
call SOCKET_alloc
pop esi edx ecx
jz s_error
 
mov [esp+32], edi ; return socketnumber
DEBUGF 2,"socknum=%u\n", edi
 
; push edx
; and edx, SO_NONBLOCK
or [eax + SOCKET.options], SO_NONBLOCK ;edx
; pop edx
; and edx, not SO_NONBLOCK
 
mov [eax + SOCKET.Domain], ecx
mov [eax + SOCKET.Type], edx
mov [eax + SOCKET.Protocol], esi
 
cmp ecx, AF_INET4
jne .no_inet4
 
cmp edx, SOCK_DGRAM
je .udp
 
cmp edx, SOCK_STREAM
je .tcp
 
cmp edx, SOCK_RAW
je .raw
 
.no_inet4:
cmp ecx, AF_PPP
jne .no_ppp
 
cmp esi, PPP_PROTO_ETHERNET
je .pppoe
 
.no_ppp:
DEBUGF 2,"Unknown socket family/protocol\n"
ret
 
align 4
.raw:
test esi, esi ; IP_PROTO_IP
jz .ip
 
cmp esi, IP_PROTO_ICMP
je .icmp
 
cmp esi, IP_PROTO_UDP
je .udp
 
cmp esi, IP_PROTO_TCP
je .tcp
 
ret
 
align 4
.udp:
mov [eax + SOCKET.Protocol], IP_PROTO_UDP
mov [eax + SOCKET.snd_proc], SOCKET_send_udp
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
ret
 
align 4
.tcp:
mov [eax + SOCKET.Protocol], IP_PROTO_TCP
mov [eax + SOCKET.snd_proc], SOCKET_send_tcp
mov [eax + SOCKET.rcv_proc], SOCKET_receive_stream
 
TCP_init_socket eax
ret
 
 
align 4
.ip:
mov [eax + SOCKET.snd_proc], SOCKET_send_ip
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
ret
 
 
align 4
.icmp:
mov [eax + SOCKET.snd_proc], SOCKET_send_icmp
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
ret
 
align 4
.pppoe:
push eax
mov edi, eax
mov ecx, SOCKETBUFFSIZE / 4
cld
xor eax, eax
rep stosd
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue
pop eax
 
mov [eax + SOCKET.snd_proc], SOCKET_send_pppoe
mov [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
ret
 
 
;-----------------------------------------------------------------
;
; SOCKET_bind
;
; IN: socket number in ecx
; pointer to sockaddr struct in edx
; length of that struct in esi
; OUT: 0 on success
;
;-----------------------------------------------------------------
align 4
SOCKET_bind:
 
DEBUGF 2,"SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
 
call SOCKET_num_to_ptr
jz s_error
 
cmp esi, 2
jb s_error
 
cmp word [edx], AF_INET4
je .af_inet4
 
cmp word [edx], AF_LOCAL
je .af_local
 
jmp s_error
 
.af_local:
; TODO: write code here
 
mov dword [esp+32], 0
ret
 
.af_inet4:
 
cmp esi, 6
jb s_error
 
cmp [eax + SOCKET.Protocol], IP_PROTO_UDP
je .udp
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
je .tcp
 
jmp s_error
 
.tcp:
.udp:
 
mov ebx, [edx + 4] ; First, fill in the IP
test ebx, ebx ; If IP is 0, use default
jnz @f
mov ebx, [NET_DEFAULT]
mov ebx, [IP_LIST + 4*ebx]
@@:
mov [eax + IP_SOCKET.LocalIP], ebx
 
mov bx, [edx + 2] ; Now fill in the local port if it's still available
call SOCKET_check_port
jz s_error ; ZF is set by socket_check_port, on error
 
DEBUGF 1,"SOCKET_bind: local ip=%u.%u.%u.%u\n",\
[eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
[eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
 
mov dword [esp+32], 0
ret
 
 
 
 
;-----------------------------------------------------------------
;
; SOCKET_connect
;
; IN: socket number in ecx
; pointer to sockaddr struct in edx
; length of that struct in esi
; OUT: 0 on success
;
;-----------------------------------------------------------------
align 4
SOCKET_connect:
 
DEBUGF 2,"SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
 
call SOCKET_num_to_ptr
jz s_error
 
cmp esi, 8
jb s_error
 
cmp word [edx], AF_INET4
je .af_inet4
 
jmp s_error
 
.af_inet4:
cmp [eax + IP_SOCKET.LocalIP], 0
jne @f
push [IP_LIST] ; FIXME
pop [eax + IP_SOCKET.LocalIP]
@@:
 
cmp [eax + SOCKET.Protocol], IP_PROTO_UDP
je .udp
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
je .tcp
 
cmp [eax + SOCKET.Protocol], IP_PROTO_IP
je .ip
 
cmp [eax + SOCKET.Protocol], IP_PROTO_ICMP
je .ip
 
jmp s_error
 
align 4
.udp:
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
 
pushw [edx + 2]
pop [eax + UDP_SOCKET.RemotePort]
 
pushd [edx + 4]
pop [eax + IP_SOCKET.RemoteIP]
 
cmp [eax + UDP_SOCKET.LocalPort], 0
jne @f
call SOCKET_find_port
@@:
 
mov [eax + UDP_SOCKET.firstpacket], 0
 
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue
pop eax
 
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
 
mov dword [esp+32], 0
ret
 
align 4
.tcp:
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
 
pushw [edx + 2]
pop [eax + TCP_SOCKET.RemotePort]
 
pushd [edx + 4]
pop [eax + IP_SOCKET.RemoteIP]
 
cmp [eax + TCP_SOCKET.LocalPort], 0
jne @f
call SOCKET_find_port
@@:
 
mov [eax + TCP_SOCKET.timer_persist], 0
mov [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT
 
push [TCP_sequence_num]
add [TCP_sequence_num], 6400
pop [eax + TCP_SOCKET.ISS]
mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init
 
 
TCP_sendseqinit eax
 
; mov [ebx + TCP_SOCKET.timer_retransmission], ;; todo: create macro to set retransmission timer
 
mov ebx, eax
lea ecx, [eax+SOCKET.mutex]
call mutex_init
 
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_create
 
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_create
 
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
popa
 
mov eax, ebx
call TCP_output
 
; add socket to the list by changing pointers
mov ebx, net_sockets
push [ebx + SOCKET.NextPtr]
mov [ebx + SOCKET.NextPtr], eax
mov [eax + SOCKET.PrevPtr], ebx
pop ebx
mov [eax + SOCKET.NextPtr], ebx
or ebx, ebx
;;; TODO: wait for successfull connection if blocking socket
 
mov dword [esp+32], 0
ret
 
align 4
.ip:
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
 
pushd [edx + 4]
pop [eax + IP_SOCKET.RemoteIP]
 
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up data receiving queue
pop eax
 
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
 
mov dword [esp+32], 0
ret
 
 
;-----------------------------------------------------------------
;
; SOCKET_listen
;
; IN: socket number in ecx
; backlog in edx
; OUT: eax is socket num, -1 on error
;
;-----------------------------------------------------------------
align 4
SOCKET_listen:
 
DEBUGF 2,"SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
 
call SOCKET_num_to_ptr
jz s_error
 
cmp [eax + SOCKET.Domain], AF_INET4
jne s_error
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
jne s_error
 
cmp [eax + TCP_SOCKET.LocalPort], 0
je s_error
 
cmp [eax + IP_SOCKET.LocalIP], 0
jne @f
push [IP_LIST]
pop [eax + IP_SOCKET.LocalIP]
@@:
 
cmp edx, MAX_backlog
jbe @f
mov edx, MAX_backlog
@@:
 
mov [eax + SOCKET.backlog], dx
or [eax + SOCKET.options], SO_ACCEPTCON
mov [eax + TCP_SOCKET.t_state], TCPS_LISTEN
mov [eax + TCP_SOCKET.timer_keepalive], 0 ; disable keepalive timer
 
push eax
init_queue (eax + SOCKET_QUEUE_LOCATION) ; Set up sockets queue
pop eax
 
mov dword [esp+32], 0
 
ret
 
 
;-----------------------------------------------------------------
;
; SOCKET_accept
;
; IN: socket number in ecx
; addr in edx
; addrlen in esi
; OUT: eax is socket num, -1 on error
;
;-----------------------------------------------------------------
align 4
SOCKET_accept:
 
DEBUGF 2,"SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
 
call SOCKET_num_to_ptr
jz s_error
 
test [eax + SOCKET.options], SO_ACCEPTCON
jz s_error
 
cmp [eax + SOCKET.Domain], AF_INET4
jne s_error
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
jne s_error
 
.loop:
get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .block
 
; Ok, we got a socket ptr
mov eax, [esi]
 
; Change thread ID to that of the current thread
mov ebx, [TASK_BASE]
mov ebx, [ebx + TASKDATA.pid]
mov [eax + SOCKET.TID], ebx
 
; Convert it to a socket number
call SOCKET_ptr_to_num
jz s_error
; and return it to caller
mov [esp+32], eax
ret
 
.block:
test [eax + SOCKET.options], SO_NONBLOCK
jnz s_error
 
call SOCKET_block
jmp .loop
 
;-----------------------------------------------------------------
;
; SOCKET_close
;
; IN: socket number in ecx
; OUT: eax is socket num, -1 on error
;
;-----------------------------------------------------------------
align 4
SOCKET_close:
 
DEBUGF 2,"SOCKET_close: socknum=%u\n", ecx
 
call SOCKET_num_to_ptr
jz s_error
 
mov dword [esp+32], 0 ; The socket exists, so we will succeed in closing it.
 
.socket:
or [eax + SOCKET.options], SO_NONBLOCK ; Mark the socket as non blocking, we dont want it to block any longer!
 
test [eax + SOCKET.state], SS_BLOCKED ; Is the socket still in blocked state?
jz @f
mov [ebx + SOCKET.PrevPtr], eax
call SOCKET_notify.unblock ; Unblock it.
@@:
 
@@: ; set socket owner PID to the one of calling process
cmp [eax + SOCKET.Domain], AF_INET4
jne .free
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
je .tcp
 
.free:
call SOCKET_free
ret
 
.tcp:
cmp [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED ; state must be LISTEN, SYN_SENT or CLOSED
jb .free
 
call TCP_usrclosed
call TCP_output ;;;; Fixme: is this nescessary??
 
ret
 
 
;-----------------------------------------------------------------
;
; SOCKET_receive
;
; IN: socket number in ecx
; addr to buffer in edx
; length of buffer in esi
; flags in edi
; OUT: eax is number of bytes copied, -1 on error
;
;-----------------------------------------------------------------
align 4
SOCKET_receive:
 
DEBUGF 2,"SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
 
call SOCKET_num_to_ptr
jz s_error
 
jmp [eax + SOCKET.rcv_proc]
 
 
align 4
SOCKET_receive_dgram:
 
DEBUGF 1,"SOCKET_receive: DGRAM\n"
 
mov ebx, esi
mov edi, edx ; addr to buffer
 
.loop:
get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .block ; destroys esi and ecx
 
mov ecx, [esi + socket_queue_entry.data_size]
DEBUGF 1,"SOCKET_receive: %u bytes data\n", ecx
 
cmp ecx, ebx
ja .too_small
 
push [esi + socket_queue_entry.buf_ptr] ; save the buffer addr so we can clear it later
mov esi, [esi + socket_queue_entry.data_ptr]
DEBUGF 1,"SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
mov [esp+32+4], ecx ; return number of bytes copied
 
; copy the data
shr ecx, 1
jnc .nb
movsb
.nb:
shr ecx, 1
jnc .nw
movsw
.nw:
test ecx, ecx
jz .nd
rep movsd
.nd:
 
call kernel_free ; remove the packet
ret
 
.too_small:
 
DEBUGF 2,"SOCKET_receive: Buffer too small\n"
jmp s_error
 
.block:
test [eax + SOCKET.options], SO_NONBLOCK
jnz s_error
 
call SOCKET_block
jmp .loop
 
 
align 4
SOCKET_receive_local:
 
; does this socket have a PID yet?
cmp [eax + SOCKET.PID], 0
jne @f
 
; Change PID to that of current process
mov ebx, [TASK_BASE]
mov ebx, [ebx + TASKDATA.pid]
mov [eax + SOCKET.PID], ebx
mov [eax + SOCKET.TID], ebx ; currently TID = PID in kolibrios :(
@@:
 
; find first free socket number and use it
;mov edx, ebx
mov ebx, net_sockets
xor ecx, ecx
.next_socket_number:
inc ecx
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .last_socket_number
cmp [ebx + SOCKET.Number], ecx
jne .next_socket
;cmp [ebx + SOCKET.PID], edx
;jne .next_socket
mov ebx, net_sockets
jmp .next_socket_number
mov [eax + SOCKET.rcv_proc], SOCKET_receive_stream
 
.last_socket_number:
mov [eax + SOCKET.Number], ecx
align 4
SOCKET_receive_stream:
 
.exit:
DEBUGF 1,"SOCKET_receive: STREAM\n"
 
mov ebx, edi
mov ecx, esi
mov edi, edx
xor edx, edx
 
test ebx, MSG_DONTWAIT
jnz .dontwait
.loop:
cmp [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
je .block
.dontwait:
test ebx, MSG_PEEK
jnz .peek
 
add eax, STREAM_SOCKET.rcv
call SOCKET_ring_read
call SOCKET_ring_free
 
mov [esp+32], ecx ; return number of bytes copied
ret
endp
 
;; Free socket data memory and pop socket off the list
.peek:
mov ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
mov [esp+32], ecx ; return number of bytes available
ret
 
.block:
test [eax + SOCKET.options], SO_NONBLOCK
jnz .return0
 
call SOCKET_block
jmp .loop
 
.return0:
xor ecx, ecx
mov [esp+32], ecx
ret
 
 
;-----------------------------------------------------------------
;
; @param sockAddr is a socket structure address
;;
proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD
mov eax, [sockAddr]
DEBUGF 1, "K : net_socket_free (0x%x)\n", eax
; check if we got something similar to socket structure address
or eax, eax
jz .error
; SOCKET_send
;
;
; IN: socket number in ecx
; pointer to data in edx
; datalength in esi
; flags in edi
; OUT: -1 on error
;
;-----------------------------------------------------------------
align 4
SOCKET_send:
 
; make sure sockAddr is one of the socket addresses in the list
mov ebx, net_sockets
;mov ecx, [TASK_BASE]
;mov ecx, [ecx + TASKDATA.pid]
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .error
cmp ebx, eax
jne .next_socket
;cmp [ebx + SOCKET.PID], ecx
;jne .next_socket
DEBUGF 2,"SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
 
; okay, we found the correct one
; mark local port as unused
movzx ebx, [eax + SOCKET.LocalPort]
call SOCKET_num_to_ptr
jz s_error
 
mov ecx, esi
mov esi, edx
 
jmp [eax + SOCKET.snd_proc]
 
 
align 4
SOCKET_send_udp:
 
DEBUGF 1,"SOCKET_send: UDP\n"
 
mov [esp+32], ecx
call UDP_output
cmp eax, -1
je s_error
ret
 
 
align 4
SOCKET_send_tcp:
 
DEBUGF 1,"SOCKET_send: TCP\n"
 
push eax
mov eax, [network_free_ports]
xchg bl, bh
lock bts [eax], ebx
add eax, STREAM_SOCKET.snd
call SOCKET_ring_write
pop eax
; remove it from the list first, changing pointers
mov ebx, [eax + SOCKET.NextPtr]
mov eax, [eax + SOCKET.PrevPtr]
mov [eax + SOCKET.NextPtr], ebx
or ebx, ebx
jz @f
mov [ebx + SOCKET.PrevPtr], eax
 
@@: ; and finally free the memory structure used
stdcall kernel_free, [sockAddr]
mov [esp+32], ecx
 
call TCP_output
ret
 
.error:
DEBUGF 1, "K : failed\n"
 
align 4
SOCKET_send_ip:
 
DEBUGF 1,"SOCKET_send: IPv4\n"
 
mov [esp+32], ecx
call IPv4_output_raw
cmp eax, -1
je s_error
ret
endp
 
;; Get socket structure address by its number
; Scan through sockets list to find the socket with specified number.
; This proc uses SOCKET.PID indirectly to check if socket is owned by
; calling process.
 
align 4
SOCKET_send_icmp:
 
DEBUGF 1,"SOCKET_send: ICMP\n"
 
mov [esp+32], ecx
call ICMP_output_raw
cmp eax, -1
je s_error
ret
 
 
align 4
SOCKET_send_pppoe:
 
DEBUGF 1,"SOCKET_send: PPPoE\n"
 
mov [esp+32], ecx
mov ebx, [eax + SOCKET.device]
 
call PPPoE_discovery_output
cmp eax, -1
je s_error
ret
 
 
 
align 4
SOCKET_send_local:
 
; does this socket have a PID yet?
cmp [eax + SOCKET.PID], 0
jne @f
 
; Change PID to that of current process
mov ebx, [TASK_BASE]
mov ebx, [ebx + TASKDATA.pid]
mov [eax + SOCKET.PID], ebx
mov [eax + SOCKET.TID], ebx ; currently TID = PID in kolibrios :(
@@:
mov [eax + SOCKET.snd_proc], SOCKET_send_local_
 
align 4
SOCKET_send_local_:
 
DEBUGF 1,"SOCKET_send: LOCAL\n"
 
; get the other side's socket and check if it still exists
mov eax, [eax + SOCKET.device]
call SOCKET_check
jz s_error
 
; allright, shove in the data!
push eax
add eax, STREAM_SOCKET.rcv
call SOCKET_ring_write
pop eax
 
; return the number of written bytes (or errorcode) to application
mov [esp+32], ecx
 
; and notify the other end
call SOCKET_notify
 
ret
 
 
;-----------------------------------------------------------------
;
; @param sockNum is a socket number
; @return socket structure address or 0 (not found) in EAX
;;
proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD
mov eax, [sockNum]
; check if we got something similar to socket number
or eax, eax
jz .error
; SOCKET_get_options
;
; IN: ecx = socket number
; edx = pointer to the options:
; dd level, optname, optval, optlen
; OUT: -1 on error
;
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
; TODO: find best way to notify that send()'ed data were acknowledged
; Also pseudo-optname -3 is valid and returns socket state, one of TCPS_*.
;
;-----------------------------------------------------------------
align 4
SOCKET_get_opt:
 
; scan through sockets list
mov ebx, net_sockets
;mov ecx, [TASK_BASE]
;mov ecx, [ecx + TASKDATA.pid]
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .error
cmp [ebx + SOCKET.Number], eax
jne .next_socket
;cmp [ebx + SOCKET.PID], ecx
;jne .next_socket
DEBUGF 2,"SOCKET_get_opt\n"
 
; okay, we found the correct one
mov eax, ebx
call SOCKET_num_to_ptr
jz s_error
 
cmp dword [edx], IP_PROTO_TCP
jne s_error
cmp dword [edx+4], -2
je @f
cmp dword [edx+4], -3
jne s_error
@@:
; mov eax, [edx+12]
; test eax, eax
; jz .fail
; cmp dword [eax], 4
; mov dword [eax], 4
; jb .fail
; stdcall net_socket_num_to_addr, ecx
; test eax, eax
; jz .fail
; ; todo: check that eax is really TCP socket
; mov ecx, [eax + TCP_SOCKET.last_ack_number]
; cmp dword [edx+4], -2
; jz @f
; mov ecx, [eax + TCP_SOCKET.state]
@@:
mov eax, [edx+8]
test eax, eax
jz @f
mov [eax], ecx
@@:
mov dword [esp+32], 0
ret
 
.error:
xor eax, eax
 
 
;-----------------------------------------------------------------
;
; SOCKET_set_options
;
; IN: ecx = socket number
; edx = pointer to the options:
; dd level, optname, optlen, optval
; OUT: -1 on error
;
;-----------------------------------------------------------------
align 4
SOCKET_set_opt:
 
DEBUGF 2,"SOCKET_set_opt\n"
 
call SOCKET_num_to_ptr
jz s_error
 
cmp dword [edx], SOL_SOCKET
jne s_error
 
cmp dword [edx+4], SO_BINDTODEVICE
je .bind
 
cmp dword [edx+4], SO_BLOCK
je .block
 
jmp s_error
 
.bind:
cmp dword [edx+8], 0
je .unbind
 
movzx edx, byte [edx + 9]
cmp edx, MAX_NET_DEVICES
ja s_error
 
mov edx, [NET_DRV_LIST + 4*edx]
test edx, edx
jz s_error
mov [eax + SOCKET.device], edx
 
DEBUGF 1,"SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
 
mov dword [esp+32], 0 ; success!
ret
endp
 
;; Get socket number by its structure address
; Scan through sockets list to find the socket with specified address.
; This proc uses SOCKET.PID indirectly to check if socket is owned by
; calling process.
.unbind:
mov [eax + SOCKET.device], 0
 
mov dword [esp+32], 0 ; success!
ret
 
.block:
cmp dword [edx+8], 0
je .unblock
 
and [eax + SOCKET.options], not SO_NONBLOCK
 
mov dword [esp+32], 0 ; success!
ret
 
.unblock:
or [eax + SOCKET.options], SO_NONBLOCK
 
mov dword [esp+32], 0 ; success!
ret
 
 
 
;-----------------------------------------------------------------
;
; @param sockAddr is a socket structure address
; @return socket number (SOCKET.Number) or 0 (not found) in EAX
;;
proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD
mov eax, [sockAddr]
; check if we got something similar to socket structure address
or eax, eax
jz .error
; SOCKET_pair
;
; Allocates a pair of linked LOCAL domain sockets
;
; IN: /
; OUT: eax is socket1 num, -1 on error
; ebx is socket2 num
;
;-----------------------------------------------------------------
align 4
SOCKET_pair:
 
; scan through sockets list
mov ebx, net_sockets
;mov ecx, [TASK_BASE]
;mov ecx, [ecx + TASKDATA.pid]
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
DEBUGF 2,"SOCKET_pair\n"
 
call SOCKET_alloc
jz s_error
mov [esp+32], edi ; application's eax
 
mov [eax + SOCKET.Domain], AF_LOCAL
mov [eax + SOCKET.Type], SOCK_STREAM
mov [eax + SOCKET.Protocol], 0 ;;; CHECKME
mov [eax + SOCKET.snd_proc], SOCKET_send_local
mov [eax + SOCKET.rcv_proc], SOCKET_receive_local
mov [eax + SOCKET.PID], 0
mov ebx, eax
 
call SOCKET_alloc
jz .error
cmp ebx, eax
jne .next_socket
;cmp [ebx + SOCKET.PID], ecx
;jne .next_socket
mov [esp+24], edi ; application's ebx
 
; okay, we found the correct one
mov eax, [ebx + SOCKET.Number]
mov [eax + SOCKET.Domain], AF_LOCAL
mov [eax + SOCKET.Type], SOCK_STREAM
mov [eax + SOCKET.Protocol], 0 ;;; CHECKME
mov [eax + SOCKET.snd_proc], SOCKET_send_local
mov [eax + SOCKET.rcv_proc], SOCKET_receive_local
mov [eax + SOCKET.PID], 0
 
; Link the two sockets to eachother
mov [eax + SOCKET.device], ebx
mov [ebx + SOCKET.device], eax
 
lea eax, [eax + STREAM_SOCKET.rcv]
call SOCKET_ring_create
 
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_create
pop eax
 
ret
 
.error:
xor eax, eax
ret
endp
mov eax, ebx
call SOCKET_free
jmp s_error
 
;; [53.9] Check if local port is used by any socket in the system.
; Scan through sockets list, checking SOCKET.LocalPort.
; Useful when you want a to generate a unique local port number.
; This proc doesn't guarantee that after calling it and trying to use
; the port reported being free in calls to socket_open/socket_open_tcp it'll
; still be free or otherwise it'll still be used if reported being in use.
 
 
;-----------------------------------------------------------------
;
; @param BX is a port number
; @return 1 (port is free) or 0 (port is in use) in EAX
;;
proc is_localport_unused stdcall
movzx ebx, bx
mov eax, [network_free_ports]
bt [eax], ebx
setc al
movzx eax, al
; SOCKET_debug
;
; Copies socket variables to application buffer
;
; IN: ecx = socket number
; edx = pointer to buffer
;
; OUT: -1 on error
;-----------------------------------------------------------------
align 4
SOCKET_debug:
 
DEBUGF 1,"SOCKET_debug\n"
 
mov edi, edx
 
test ecx, ecx
jz .returnall
 
call SOCKET_num_to_ptr
jz s_error
 
mov esi, eax
mov ecx, SOCKETBUFFSIZE/4
rep movsd
 
mov dword [esp+32], 0
ret
endp
 
;======================================
set_local_port:
;--------------------------------------
;? Set local port in socket structure.
;--------------------------------------
;> eax -> struct SOCKET
;> bx = local port, or 0 if the kernel must select it itself
;--------------------------------------
;< CF set on error / cleared on success
;< [eax+SOCKET.LocalPort] filled on success
;======================================
; 0. Prepare: save registers, make eax point to ports table, expand port to ebx.
push eax ecx
mov eax, [network_free_ports]
movzx ebx, bx
; 1. Test, whether the kernel should choose port itself. If no, proceed to 5.
.returnall:
mov ebx, net_sockets
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
test ebx, ebx
jnz .given
; 2. Yes, it should. Set ecx = limit of table, eax = start value
lea ecx, [eax+0x10000/8]
add eax, [network_free_hint]
; 3. First scan loop: from free hint to end of table.
.scan1:
; 3a. For each dword, find bit set to 1
bsf ebx, [eax]
jz .next1
; 3b. If such bit has been found, atomically test again and clear it.
lock btr [eax], ebx
; 3c. If the bit was still set (usual case), we have found and reserved one port.
; Proceed to 6.
jc .found
; 3d. Otherwise, someone has reserved it between bsf and btr, so retry search.
jmp .scan1
.next1:
; 3e. All bits are cleared, so advance to next dword.
add eax, 4
; 3f. Check limit and continue loop.
cmp eax, ecx
jb .scan1
; 4. Second scan loop: from port 1024 (start of non-system ports) to free hint.
mov eax, [network_free_ports]
mov ecx, eax
add ecx, [network_free_hint]
add eax, 1024/8
; 4a. Test whether there is something to scan.
cmp eax, ecx
jae .fail
; 4b. Enter the loop, the process is same as for 3.
.scan2:
bsf ebx, [eax]
jz .next2
lock btr [eax], ebx
jc .found
jmp .scan2
.next2:
add eax, 4
cmp eax, ecx
jb .scan2
; 4c. None found. Fail.
.fail:
pop ecx eax
stc
jz .done
mov eax, [ebx + SOCKET.Number]
stosd
jmp .next_socket
.done:
xor eax, eax
stosd
 
mov dword [esp+32], 0
ret
; 5. No, the kernel should reserve selected port.
.given:
; 5a. Atomically test old value and clear bit.
lock btr [eax], ebx
; 5b. If the bit was set, reservation is successful. Proceed to 8.
jc .set
; 5c. Otherwise, fail.
jmp .fail
.found:
; 6. We have found the bit set to 1, convert the position to port number.
sub eax, [network_free_ports]
lea ebx, [ebx+eax*8]
; 7. Update free hint.
add eax, 4
cmp eax, 65536/8
jb @f
mov eax, 1024/8
@@:
mov [network_free_hint], eax
.set:
; 8. Restore eax, set SOCKET.LocalPort and return.
pop ecx eax
xchg bl, bh ; Intel -> network byte order
mov [eax + SOCKET.LocalPort], bx
clc
ret
 
;; [53.0] Open DGRAM socket (connectionless, unreliable)
 
;-----------------------------------------------------------------
;
; @param BX is local port number
; @param CX is remote port number
; @param EDX is remote IP address
; @return socket number or -1 (error) in EAX
;;
proc socket_open stdcall
call net_socket_alloc
or eax, eax
jz .error
; SOCKET_find_port
;
; Fills in the local port number for TCP and UDP sockets
; This procedure always works because the number of sockets is
; limited to a smaller number then the number of possible ports
;
; IN: eax = socket pointer
; OUT: /
;
;-----------------------------------------------------------------
align 4
SOCKET_find_port:
 
DEBUGF 1, "K : socket_open (0x%x)\n", eax
DEBUGF 2,"SOCKET_find_port\n"
 
push eax
push ebx esi ecx
 
call set_local_port
jc .error.free
xchg ch, cl
mov [eax + SOCKET.RemotePort], cx
mov ebx, [stack_ip]
mov [eax + SOCKET.LocalIP], ebx
mov [eax + SOCKET.RemoteIP], edx
cmp [eax + SOCKET.Protocol], IP_PROTO_UDP
je .udp
 
;pop eax ; Get the socket number back, so we can return it
stdcall net_socket_addr_to_num
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
je .tcp
 
pop ecx esi ebx
ret
 
.error.free:
stdcall net_socket_free;, eax
.udp:
mov bx, [last_UDP_port]
call .findit
mov [last_UDP_port], bx
 
.error:
DEBUGF 1, "K : socket_open (fail)\n"
or eax, -1
pop ecx esi ebx
ret
endp
 
;; [53.5] Open STREAM socket (connection-based, sequenced, reliable, two-way)
.tcp:
mov bx, [last_TCP_port]
call .findit
mov [last_TCP_port], bx
 
pop ecx esi ebx
ret
 
 
.restart:
mov bx, MIN_EPHEMERAL_PORT_N
.findit:
cmp bx, MAX_EPHEMERAL_PORT_N
je .restart
 
add bh, 1
adc bl, 0
 
call SOCKET_check_port
jz .findit
ret
 
 
 
;-----------------------------------------------------------------
;
; @param BX is local port number
; @param CX is remote port number
; @param EDX is remote IP address
; @param ESI is open mode (SOCKET_ACTIVE, SOCKET_PASSIVE)
; @return socket number or -1 (error) in EAX
;;
proc socket_open_tcp stdcall
local sockAddr dd ?
; SOCKET_check_port (to be used with AF_INET only!)
;
; Checks if a local port number is unused
; If the proposed port number is unused, it is filled in in the socket structure
;
; IN: eax = socket ptr (to find out if its a TCP/UDP socket)
; bx = proposed socket number (network byte order)
;
; OUT: ZF = set on error
;
;-----------------------------------------------------------------
align 4
SOCKET_check_port:
 
cmp esi, SOCKET_PASSIVE
jne .skip_port_check
DEBUGF 2,"SOCKET_check_port: "
 
push ebx
mov eax, ebx
xchg al, ah
mov ebx, net_sockets
mov ecx, [eax + SOCKET.Protocol]
mov edx, [eax + IP_SOCKET.LocalIP]
mov esi, net_sockets
 
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .last_socket
cmp [ebx + SOCKET.TCBState], TCB_LISTEN
mov esi, [esi + SOCKET.NextPtr]
or esi, esi
jz .port_ok
 
cmp [esi + SOCKET.Protocol], ecx
jne .next_socket
cmp [ebx + SOCKET.LocalPort], ax
 
cmp [esi + IP_SOCKET.LocalIP], edx
jne .next_socket
 
xchg al, ah
DEBUGF 1, "K : error: port %u is listened by 0x%x\n", ax, ebx
pop ebx
jmp .error
cmp [esi + UDP_SOCKET.LocalPort], bx
jne .next_socket
 
.last_socket:
pop ebx
DEBUGF 2,"local port %x already in use\n", bx ; FIXME: find a way to print big endian values with debugf
ret
 
.skip_port_check:
call net_socket_alloc
or eax, eax
jz .error
.port_ok:
DEBUGF 2,"local port %x is free\n", bx ; FIXME: find a way to print big endian values with debugf
mov [eax + UDP_SOCKET.LocalPort], bx
or bx, bx ; clear the zero-flag
ret
 
DEBUGF 1, "K : socket_open_tcp (0x%x)\n", eax
 
mov [sockAddr], eax
 
; TODO - check this works!
;mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer.
;-----------------------------------------------------------------
;
; SOCKET_input
;
; Updates a (stateless) socket with received data
;
; Note: the mutex should already be set !
;
; IN: eax = socket ptr
; ecx = data size
; esi = ptr to data
; [esp] = ptr to buf
; [esp + 4] = buf size
;
; OUT: /
;
;-----------------------------------------------------------------
align 4
SOCKET_input:
 
call set_local_port
jc .error.free
xchg ch, cl
mov [eax + SOCKET.RemotePort], cx
mov [eax + SOCKET.OrigRemotePort], cx
mov ebx, [stack_ip]
mov [eax + SOCKET.LocalIP], ebx
mov [eax + SOCKET.RemoteIP], edx
mov [eax + SOCKET.OrigRemoteIP], edx
DEBUGF 2,"SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
 
mov ebx, TCB_LISTEN
cmp esi, SOCKET_PASSIVE
je @f
mov ebx, TCB_SYN_SENT
@@:
mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB
mov [esp+4], ecx
push esi
mov esi, esp
 
cmp ebx, TCB_LISTEN
je .exit
add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
 
; Now, if we are in active mode, then we have to send a SYN to the specified remote port
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je .exit
DEBUGF 1,"SOCKET_input: success\n"
add esp, sizeof.socket_queue_entry
 
push eax
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
popa
 
mov bl, TH_SYN
xor ecx, ecx
stdcall build_tcp_packet, [sockAddr]
jmp SOCKET_notify
 
mov eax, NET1OUT_QUEUE
mov edx, [stack_ip]
mov ecx, [sockAddr]
cmp edx, [ecx + SOCKET.RemoteIP]
jne .not_local
mov eax, IPIN_QUEUE
.full:
DEBUGF 2,"SOCKET_input: socket %x is full!\n", eax
 
.not_local:
; Send it.
pop ebx
call queue
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
popa
 
mov esi, [sockAddr]
call kernel_free
add esp, 8
 
; increment SND.NXT in socket
add esi, SOCKET.SND_NXT
call inc_inet_esi
 
.exit:
; Get the socket number back, so we can return it
stdcall net_socket_addr_to_num, [sockAddr]
ret
 
.error.free:
stdcall net_socket_free, eax
 
.error:
DEBUGF 1, "K : socket_open_tcp (fail)\n"
or eax, -1
;--------------------------
;
; eax = ptr to ring struct (just a buffer of the right size)
;
align 4
SOCKET_ring_create:
 
push esi
mov esi, eax
 
push edx
stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
pop edx
 
DEBUGF 1,"SOCKET_ring_created: %x\n", eax
 
pusha
lea ecx, [esi + RING_BUFFER.mutex]
call mutex_init
popa
 
mov [esi + RING_BUFFER.start_ptr], eax
mov [esi + RING_BUFFER.write_ptr], eax
mov [esi + RING_BUFFER.read_ptr], eax
mov [esi + RING_BUFFER.size], 0
add eax, SOCKET_MAXDATA
mov [esi + RING_BUFFER.end_ptr], eax
mov eax, esi
pop esi
 
ret
endp
 
;; [53.1] Close DGRAM socket
;-----------------------------------------------------------------
;
; @param EBX is socket number
; @return 0 (closed successfully) or -1 (error) in EAX
;;
proc socket_close stdcall
DEBUGF 1, "K : socket_close (0x%x)\n", ebx
stdcall net_socket_num_to_addr, ebx
or eax, eax
jz .error
; SOCKET_ring_write
;
; Adds data to a stream socket, and updates write pointer and size
;
; IN: eax = ptr to ring struct
; ecx = data size
; esi = ptr to data
;
; OUT: ecx = number of bytes stored
;
;-----------------------------------------------------------------
align 4
SOCKET_ring_write:
 
stdcall net_socket_free, eax
DEBUGF 1,"SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
 
xor eax, eax
ret
; lock mutex
pusha
lea ecx, [eax + RING_BUFFER.mutex]
call mutex_lock ; TODO: check what registers this function actually destroys
popa
 
.error:
DEBUGF 1, "K : socket_close (fail)\n"
or eax, -1
; calculate available size
mov edi, SOCKET_MAXDATA
sub edi, [eax + RING_BUFFER.size] ; available buffer size in edi
cmp ecx, edi
jbe .copy
mov ecx, edi
.copy:
mov edi, [eax + RING_BUFFER.write_ptr]
DEBUGF 2,"SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
 
; update write ptr
push edi
add edi, ecx
cmp edi, [eax + RING_BUFFER.end_ptr]
jb @f
sub edi, SOCKET_MAXDATA ; WRAP
@@:
mov [eax + RING_BUFFER.write_ptr], edi
pop edi
 
; update size
add [eax + RING_BUFFER.size], ecx
 
; copy the data
push ecx
shr ecx, 1
jnc .nb
movsb
.nb:
shr ecx, 1
jnc .nw
movsw
.nw:
test ecx, ecx
jz .nd
rep movsd
.nd:
pop ecx
 
; unlock mutex
push eax ecx
lea ecx, [eax + RING_BUFFER.mutex]
call mutex_unlock ; TODO: check what registers this function actually destroys
pop ecx eax
 
ret
endp
 
;; [53.8] Close STREAM socket
; Closing TCP sockets takes time, so when you get successful return code
; from this function doesn't always mean that socket is actually closed.
;-----------------------------------------------------------------
;
; @param EBX is socket number
; @return 0 (closed successfully) or -1 (error) in EAX
;;
proc socket_close_tcp stdcall
local sockAddr dd ?
; SOCKET_ring_read
;
; IN: eax = ring struct ptr
; ecx = bytes to read
; edx = offset
; edi = ptr to buffer start
;
; OUT: eax = unchanged
; ecx = number of bytes read (0 on error)
; edx = destroyed
; esi = destroyed
; edi = ptr to buffer end
;
;-----------------------------------------------------------------
align 4
SOCKET_ring_read:
 
DEBUGF 1, "K : socket_close_tcp (0x%x)\n", ebx
; first, remove any resend entries
DEBUGF 1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
 
pusha
lea ecx, [eax + RING_BUFFER.mutex]
call mutex_lock ; TODO: check what registers this function actually destroys
popa
 
mov esi, resendQ
mov ecx, 0
mov esi, [eax + RING_BUFFER.read_ptr]
add esi, edx ; esi = start_ptr + offset
 
.next_resendq:
cmp ecx, NUMRESENDENTRIES
je .last_resendq ; None left
cmp [esi + 4], ebx
je @f ; found one
inc ecx
add esi, 8
jmp .next_resendq
neg edx
add edx, [eax + RING_BUFFER.size] ; edx = snd.size - offset
jle .no_data_at_all
 
@@:
mov dword[esi + 4], 0
inc ecx
add esi, 8
jmp .next_resendq
pusha
lea ecx, [eax + RING_BUFFER.mutex]
call mutex_unlock ; TODO: check what registers this function actually destroys
popa
 
.last_resendq:
cmp ecx, edx
ja .less_data
 
.copy:
DEBUGF 2,"SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
push ecx
shr ecx, 1
jnc .nb
movsb
.nb:
shr ecx, 1
jnc .nw
movsw
.nw:
test ecx, ecx
jz .nd
rep movsd
.nd:
pop ecx
ret
 
.no_data_at_all:
pusha
lea ecx, [eax + RING_BUFFER.mutex]
call mutex_unlock ; TODO: check what registers this function actually destroys
popa
 
stdcall net_socket_num_to_addr, ebx
or eax, eax
jz .error
DEBUGF 1,"SOCKET_ring_read: no data at all!\n"
xor ecx, ecx
ret
 
mov ebx, eax
mov [sockAddr], eax
.less_data:
mov ecx, edx
jmp .copy
 
cmp [ebx + SOCKET.TCBState], TCB_LISTEN
je .destroy_tcb
cmp [ebx + SOCKET.TCBState], TCB_SYN_SENT
je .destroy_tcb
cmp [ebx + SOCKET.TCBState], TCB_CLOSED
je .destroy_tcb
 
; Now construct the response, and queue for sending by IP
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je .error
;-----------------------------------------------------------------
;
; SOCKET_ring_free
;
; Free's some bytes from the ringbuffer
;
; IN: eax = ptr to ring struct
; ecx = data size
;
; OUT: ecx = number of bytes free-ed
;
;-----------------------------------------------------------------
align 4
SOCKET_ring_free:
 
DEBUGF 1,"SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
 
push eax ecx
lea ecx, [eax + RING_BUFFER.mutex]
call mutex_lock ; TODO: check what registers this function actually destroys
pop ecx eax
 
sub [eax + RING_BUFFER.size], ecx
jb .error
add [eax + RING_BUFFER.read_ptr], ecx
 
mov edx, [eax + RING_BUFFER.end_ptr]
cmp [eax + RING_BUFFER.read_ptr], edx
jb @f
sub [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA
@@:
 
push eax ecx
lea ecx, [eax + RING_BUFFER.mutex] ; TODO: check what registers this function actually destroys
call mutex_unlock
pop ecx eax
 
ret
 
.error: ; we could free all available bytes, but that would be stupid, i guess..
DEBUGF 1,"SOCKET_ring_free: buffer=%x error!\n", eax
add [eax + RING_BUFFER.size], ecx
 
push eax
lea ecx, [eax + RING_BUFFER.mutex]
call mutex_unlock ; TODO: check what registers this function actually destroys
pop eax
 
mov bl, TH_FIN+TH_ACK
xor ecx, ecx
xor esi, esi
stdcall build_tcp_packet, [sockAddr]
ret
 
mov ebx, [sockAddr]
; increament SND.NXT in socket
lea esi, [ebx + SOCKET.SND_NXT]
call inc_inet_esi
 
; Get the socket state
mov eax, [ebx + SOCKET.TCBState]
cmp eax, TCB_SYN_RECEIVED
je .fin_wait_1
cmp eax, TCB_ESTABLISHED
je .fin_wait_1
;-----------------------------------------------------------------
;
; SOCKET_block
;
; Suspends the thread attached to a socket
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
align 4
SOCKET_block:
 
; assume CLOSE WAIT
; Send a fin, then enter last-ack state
mov [ebx + SOCKET.TCBState], TCB_LAST_ACK
jmp .send
DEBUGF 1,"SOCKET_block: %x\n", eax
 
.fin_wait_1:
; Send a fin, then enter finwait2 state
mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1
pushf
cli
 
.send:
mov eax, NET1OUT_QUEUE
mov edx, [stack_ip]
mov ecx, [sockAddr]
cmp edx, [ecx + SOCKET.RemoteIP]
jne .not_local
mov eax, IPIN_QUEUE
; Set the 'socket is blocked' flag
or [eax + SOCKET.state], SS_BLOCKED
 
.not_local:
; Send it.
pop ebx
call queue
jmp .exit
; Suspend the thread
push edx
mov edx, [TASK_BASE]
mov [edx + TASKDATA.state], 1 ; Suspended
 
.destroy_tcb:
; Remember the thread ID so we can wake it up again
mov edx, [edx + TASKDATA.pid]
DEBUGF 1,"SOCKET_block: suspending thread: %u\n", edx
mov [eax + SOCKET.TID], edx
pop edx
 
; Clear the socket variables
stdcall net_socket_free, ebx
call change_task
popf
 
.exit:
xor eax, eax
ret
DEBUGF 1,"SOCKET_block: continueing\n"
 
.error:
DEBUGF 1, "K : socket_close_tcp (fail)\n"
or eax, -1
ret
endp
 
;; [53.2] Poll socket
 
;-----------------------------------------------------------------
;
; @param EBX is socket number
; @return count or bytes in rx buffer or 0 (error) in EAX
;;
proc socket_poll stdcall
; DEBUGF 1, "socket_poll(0x%x)\n", ebx
stdcall net_socket_num_to_addr, ebx
or eax, eax
; SOCKET_notify
;
; notify's the owner of a socket that something happened
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
align 4
SOCKET_notify:
 
DEBUGF 1,"SOCKET_notify: %x\n", eax
 
call SOCKET_check
jz .error
 
mov eax, [eax + SOCKET.rxDataCount]
ret
test [eax + SOCKET.state], SS_BLOCKED
jnz .unblock
 
.error:
xor eax, eax
ret
endp
test [eax + SOCKET.options], SO_NONBLOCK
jz .error
 
;; [53.6] Get socket TCB state
;
; @param EBX is socket number
; @return socket TCB state or 0 (error) in EAX
;;
proc socket_status stdcall
;; DEBUGF 1, "socket_status(0x%x)\n", ebx
stdcall net_socket_num_to_addr, ebx
or eax, eax
push eax ecx esi
 
; socket exists and is of non blocking type.
; We'll try to flag an event to the thread
 
mov eax, [eax + SOCKET.TID]
test eax, eax
jz .done
mov ecx, 1
mov esi, TASK_DATA + TASKDATA.pid
 
.next_pid:
cmp [esi], eax
je .found_pid
inc ecx
add esi, 0x20
cmp ecx, [TASK_COUNT]
jbe .next_pid
; PID not found, TODO: close socket!
jmp .done
 
.found_pid:
shl ecx, 8
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
 
DEBUGF 1,"SOCKET_notify: Raised a network event!\n"
 
jmp .done
 
.unblock:
push eax ecx esi
; Clear the 'socket is blocked' flag
and [eax + SOCKET.state], not SS_BLOCKED
 
; Find the thread's TASK_DATA
mov eax, [eax + SOCKET.TID]
test eax, eax
jz .error
xor ecx, ecx
inc ecx
mov esi, TASK_DATA
.next:
cmp [esi + TASKDATA.pid], eax
je .found
inc ecx
add esi, 0x20
cmp ecx, [TASK_COUNT]
jbe .next
jmp .error
.found:
 
mov eax, [eax + SOCKET.TCBState]
ret
; Run the thread
mov [esi + TASKDATA.state], 0 ; Running
DEBUGF 1,"SOCKET_notify: Unblocked socket!\n"
 
.done:
pop esi ecx eax
 
.error:
xor eax, eax
ret
endp
 
;; [53.3] Get one byte from rx buffer
; This function can return 0 in two cases: if there's one byte read and
; non left, and if an error occured. Behavior should be changed and function
; shouldn't be used for now. Consider using [53.11] instead.
 
;--------------------------------------------------------------------
;
; @param EBX is socket number
; @return number of bytes left in rx buffer or 0 (error) in EAX
; @return byte read in BL
;;
proc socket_read stdcall
; DEBUGF 1, "socket_read(0x%x)\n", ebx
stdcall net_socket_num_to_addr, ebx
; SOCKET_alloc
;
; Allocate memory for socket data and put new socket into the list
; Newly created socket is initialized with calling PID and number and
; put into beginning of list (which is a fastest way).
;
; IN: /
; OUT: eax = 0 on error, socket ptr otherwise
; edi = socket number
; ZF = cleared on error
;
;--------------------------------------------------------------------
align 4
SOCKET_alloc:
 
push ebx
 
stdcall kernel_alloc, SOCKETBUFFSIZE
DEBUGF 1, "SOCKET_alloc: ptr=%x\n", eax
or eax, eax
jz .error
jz .exit
 
mov ebx, eax
; zero-initialize allocated memory
push eax
mov edi, eax
mov ecx, SOCKETBUFFSIZE / 4
xor eax, eax
rep stosd
pop eax
 
; set send-and receive procedures to return -1
mov [eax + SOCKET.snd_proc], s_error
mov [eax + SOCKET.rcv_proc], s_error
 
; find first free socket number and use it
mov edi, [last_socket_num]
.next_socket_number:
inc edi
jz .next_socket_number ; avoid socket nr 0
cmp edi, -1
je .next_socket_number ; avoid socket nr -1
mov ebx, net_sockets
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
test ebx, ebx
jz .last_socket
 
cmp [ebx + SOCKET.Number], edi
jne .next_socket
jmp .next_socket_number
 
.last_socket:
mov [last_socket_num], edi
mov [eax + SOCKET.Number], edi
DEBUGF 1, "SOCKET_alloc: number=%u\n", edi
 
; Fill in PID
mov ebx, [TASK_BASE]
mov ebx, [ebx + TASKDATA.pid]
mov [eax + SOCKET.PID], ebx
mov [eax + SOCKET.TID], ebx ; currently TID = PID in kolibrios :(
 
; init mutex
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
call mutex_init
popa
 
mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes
test eax, eax
jz .error_release
; add socket to the list by re-arranging some pointers
mov ebx, [net_sockets + SOCKET.NextPtr]
 
dec eax
mov esi, ebx ; esi is address of socket
mov [ebx + SOCKET.rxDataCount], eax ; store new count
movzx eax, byte[ebx + SOCKET.rxData] ; get the byte
mov [eax + SOCKET.PrevPtr], net_sockets
mov [eax + SOCKET.NextPtr], ebx
 
mov ecx, SOCKETBUFFSIZE - SOCKET.rxData - 1
lea edi, [esi + SOCKET.rxData]
lea esi, [edi + 1]
cld
push ecx
shr ecx, 2
rep movsd
pop ecx
and ecx, 3
rep movsb
test ebx, ebx
jz @f
 
pusha
lea ecx, [ebx + SOCKET.mutex]
mov ebx, eax
call mutex_unlock
mov eax, ebx
ret
call mutex_lock
popa
 
.error_release:
mov [ebx + SOCKET.PrevPtr], eax
 
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
.error:
xor ebx, ebx
xor eax, eax
popa
@@:
 
mov [net_sockets + SOCKET.NextPtr], eax
or eax, eax ; used to clear zero flag
.exit:
pop ebx
 
ret
endp
 
;; [53.11] Get specified number of bytes from rx buffer
; Number of bytes in rx buffer can be less than requested size. In this case,
; only available number of bytes is read.
; This function can return 0 in two cases: if there's no data to read, and if
; an error occured. Behavior should be changed.
 
;----------------------------------------------------
;
; @param EBX is socket number
; @param ECX is pointer to application buffer
; @param EDX is application buffer size (number of bytes to read)
; @return number of bytes read or 0 (error) in EAX
;;
proc socket_read_packet stdcall
; DEBUGF 1, "socket_read_packet(0x%x)\n", ebx
stdcall net_socket_num_to_addr, ebx ; get real socket address
or eax, eax
; SOCKET_free
;
; Free socket data memory and remove socket from the list
;
; IN: eax = socket ptr
; OUT: /
;
;----------------------------------------------------
align 4
SOCKET_free:
 
DEBUGF 1, "SOCKET_free: %x\n", eax
 
call SOCKET_check
jz .error
 
mov ebx, eax
push ebx
 
push ecx edx
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
pop edx ecx
popa
 
mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes
test eax, eax ; if count of bytes is zero..
jz .exit ; exit function (eax will be zero)
cmp [eax + SOCKET.Domain], AF_INET4
jnz .no_tcp
 
test edx, edx ; if buffer size is zero, copy all data
jz .copy_all_bytes
cmp edx, eax ; if buffer size is larger then the bytes of data, copy all data
jge .copy_all_bytes
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
jnz .no_tcp
 
sub eax, edx ; store new count (data bytes in buffer - bytes we're about to copy)
mov [ebx + SOCKET.rxDataCount], eax ;
push eax
mov eax, edx ; number of bytes we want to copy must be in eax
call .start_copy ; copy to the application
 
mov esi, ebx ; now we're going to copy the remaining bytes to the beginning
add esi, SOCKET.rxData ; we dont need to copy the header
mov edi, esi ; edi is where we're going to copy to
add esi, edx ; esi is from where we copy
pop ecx ; count of bytes we have left
push ecx ; push it again so we can re-use it later
shr ecx, 2 ; divide eax by 4
cld
rep movsd ; copy all full dwords
pop ecx
and ecx, 3
rep movsb ; copy remaining bytes
 
.exit:
lea ecx, [ebx + SOCKET.mutex]
mov ebx, eax
call mutex_unlock
stdcall kernel_free, [ebx + STREAM_SOCKET.rcv.start_ptr]
stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
mov eax, ebx
ret ; at last, exit
.no_tcp:
 
push eax ; this will be passed to kernel_free
mov ebx, [eax + SOCKET.NextPtr]
mov eax, [eax + SOCKET.PrevPtr]
 
DEBUGF 1, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
 
test eax, eax
jz @f
mov [eax + SOCKET.NextPtr], ebx
@@:
 
test ebx, ebx
jz @f
mov [ebx + SOCKET.PrevPtr], eax
@@:
 
call kernel_free
pop ebx
 
DEBUGF 1, "SOCKET_free: success!\n"
 
.error:
xor eax, eax
ret
 
.copy_all_bytes:
xor esi, esi
mov [ebx + SOCKET.rxDataCount], esi ; store new count (zero)
call .start_copy
lea ecx, [ebx + SOCKET.mutex]
mov ebx, eax
call mutex_unlock
mov eax, ebx
ret
;------------------------------------
;
; SOCKET_fork
;
; Create a child socket
;
; IN: socket nr in ebx
; OUT: child socket nr in eax
;
;-----------------------------------
align 4
SOCKET_fork:
 
.start_copy:
mov edi, ecx
mov esi, ebx
add esi, SOCKET.rxData ; we dont need to copy the header
mov ecx, eax ; eax is count of bytes
push ecx
shr ecx, 2 ; divide eax by 4
cld ; copy all full dwords
DEBUGF 1,"SOCKET_fork: %x\n", ebx
 
; Exit if backlog queue is full
mov eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
cmp ax, [ebx + SOCKET.backlog]
jae .fail
 
; Allocate new socket
push ebx
call SOCKET_alloc
pop ebx
jz .fail
 
push eax
mov esi, esp
add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
pop eax
 
; Copy structure from current socket to new
; We start at PID to preserve the socket num, and the 2 pointers at beginning of socket
lea esi, [ebx + SOCKET.PID]
lea edi, [eax + SOCKET.PID]
mov ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
rep movsd
pop ecx
and ecx, 3
rep movsb ; copy the rest bytes
retn ; exit, or go back to shift remaining bytes if any
endp
 
;; [53.4] Send data through DGRAM socket
and [eax + SOCKET.options], not SO_ACCEPTCON
 
ret
 
.fail2:
add esp, 4+4+4
.fail:
DEBUGF 1,"SOCKET_fork: failed\n"
xor eax, eax
ret
 
 
;---------------------------------------------------
;
; @param EBX is socket number
; @param ECX is application data size (number of bytes to send)
; @param EDX is pointer to application data buffer
; @return 0 (sent successfully) or -1 (error) in EAX
;;
proc socket_write stdcall
; DEBUGF 1, "socket_write(0x%x)\n", ebx
stdcall net_socket_num_to_addr, ebx ; get real socket address
; SOCKET_num_to_ptr
;
; Get socket structure address by its number
;
; IN: ecx = socket number
; OUT: eax = 0 on error, socket ptr otherwise
; ZF = set on error
;
;---------------------------------------------------
align 4
SOCKET_num_to_ptr:
 
DEBUGF 1,"SOCKET_num_to_ptr: num=%u ", ecx
 
mov eax, net_sockets
 
.next_socket:
mov eax, [eax + SOCKET.NextPtr]
or eax, eax
jz .error
cmp [eax + SOCKET.Number], ecx
jne .next_socket
 
mov ebx, eax
test eax, eax
 
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je .error
DEBUGF 1,"ptr=%x\n", eax
ret
 
; Save the queue entry number
push eax
.error:
DEBUGF 1,"not found\n", eax
ret
 
; save the pointers to the data buffer & size
push edx
push ecx
 
; convert buffer pointer eax to the absolute address
mov ecx, IPBUFFSIZE
mul ecx
add eax, IPbuffs
;---------------------------------------------------
;
; SOCKET_ptr_to_num
;
; Get socket number by its address
;
; IN: eax = socket ptr
; OUT: eax = 0 on error, socket num otherwise
; ZF = set on error
;
;---------------------------------------------------
align 4
SOCKET_ptr_to_num:
 
mov edx, eax
DEBUGF 1,"SOCKET_ptr_to_num: ptr=%x ", eax
 
; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
call SOCKET_check
jz .error
 
; Fill in the IP header (some data is in the socket descriptor)
mov eax, [ebx + SOCKET.LocalIP]
mov [edx + IP_PACKET.SourceAddress], eax
mov eax, [ebx + SOCKET.RemoteIP]
mov [edx + IP_PACKET.DestinationAddress], eax
mov eax, [eax + SOCKET.Number]
 
mov [edx + IP_PACKET.VersionAndIHL], 0x45
mov [edx + IP_PACKET.TypeOfService], 0
DEBUGF 1,"num=%u\n", eax
ret
 
pop eax ; Get the UDP data length
push eax
.error:
DEBUGF 1,"not found\n", eax
ret
 
add eax, 20 + 8 ; add IP header and UDP header lengths
xchg al, ah
mov [edx + IP_PACKET.TotalLength], ax
xor eax, eax
mov [edx + IP_PACKET.Identification], ax
mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040
mov [edx + IP_PACKET.TimeToLive], 0x20
mov [edx + IP_PACKET.Protocol], PROTOCOL_UDP
 
; Checksum left unfilled
mov [edx + IP_PACKET.HeaderChecksum], ax
;---------------------------------------------------
;
; SOCKET_check
;
; checks if the given value is really a socket ptr
;
; IN: eax = socket ptr
; OUT: eax = 0 on error, unchanged otherwise
; ZF = set on error
;
;---------------------------------------------------
align 4
SOCKET_check:
 
; Fill in the UDP header (some data is in the socket descriptor)
mov ax, [ebx + SOCKET.LocalPort]
mov [edx + 20 + UDP_PACKET.SourcePort], ax
DEBUGF 1,"SOCKET_check: %x\n", eax
 
mov ax, [ebx + SOCKET.RemotePort]
mov [edx + 20 + UDP_PACKET.DestinationPort], ax
push ebx
mov ebx, net_sockets
 
pop eax
push eax
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .done
cmp ebx, eax
jnz .next_socket
 
add eax, 8
xchg al, ah
mov [edx + 20 + UDP_PACKET.Length], ax
.done:
mov eax, ebx
test eax, eax
pop ebx
 
; Checksum left unfilled
xor eax, eax
mov [edx + 20 + UDP_PACKET.Checksum], ax
ret
 
pop ecx ; count of bytes to send
mov ebx, ecx ; need the length later
pop eax ; get callers ptr to data to send
 
; Get the address of the callers data
mov edi, [TASK_BASE]
add edi, TASKDATA.mem_start
add eax, [edi]
mov esi, eax
 
mov edi, edx
add edi, 28
cld
rep movsb ; copy the data across
;---------------------------------------------------
;
; SOCKET_check_owner
;
; checks if the caller application owns the socket
;
; IN: eax = socket ptr
; OUT: ZF = true/false
;
;---------------------------------------------------
align 4
SOCKET_check_owner:
 
; we have edx as IPbuffer ptr.
; Fill in the UDP checksum
; First, fill in pseudoheader
mov eax, [edx + IP_PACKET.SourceAddress]
mov [pseudoHeader], eax
mov eax, [edx + IP_PACKET.DestinationAddress]
mov [pseudoHeader + 4], eax
mov word[pseudoHeader + 8], PROTOCOL_UDP shl 8 + 0 ; 0 + protocol
add ebx, 8
mov eax, ebx
xchg al, ah
mov [pseudoHeader + 10], ax
DEBUGF 1,"SOCKET_check_owner: %x\n", eax
 
mov eax, pseudoHeader
mov [checkAdd1], eax
mov [checkSize1], word 12
mov eax, edx
add eax, 20
mov [checkAdd2], eax
mov eax, ebx
mov [checkSize2], ax ; was eax!! mjh 8/7/02
push ebx
mov ebx, [TASK_BASE]
mov ebx, [ebx + TASKDATA.pid]
cmp [eax + SOCKET.PID], ebx
pop ebx
 
call checksum
ret
 
; store it in the UDP checksum ( in the correct order! )
mov ax, [checkResult]
 
; If the UDP checksum computes to 0, we must make it 0xffff
; (0 is reserved for 'not used')
test ax, ax
jnz @f
mov ax, 0xffff
 
@@:
xchg al, ah
mov [edx + 20 + UDP_PACKET.Checksum], ax
 
; Fill in the IP header checksum
GET_IHL ecx,edx ; get IP-Header length
stdcall checksum_jb, edx, ecx; buf_ptr, buf_size
xchg al, ah
mov [edx + IP_PACKET.HeaderChecksum], ax
;------------------------------------------------------
;
; SOCKET_process_end
;
; Kernel calls this function when a certain process ends
; This function will check if the process had any open sockets
; And update them accordingly
;
; IN: edx = pid
; OUT: /
;
;------------------------------------------------------
align 4
SOCKET_process_end:
 
; Check destination IP address.
; If it is the local host IP, route it back to IP_RX
DEBUGF 1, "SOCKET_process_end: %x\n", edx
 
pop ebx
push ebx
mov ebx, net_sockets
 
mov eax, NET1OUT_QUEUE
mov ecx, [edx + SOCKET.RemoteIP]
mov edx, [stack_ip]
cmp edx, ecx
jne .not_local
mov eax, IPIN_QUEUE
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
.next_socket_test:
test ebx, ebx
jz .done
 
.not_local:
; Send it.
call queue
cmp [ebx + SOCKET.PID], edx
jne .next_socket
 
xor eax, eax
ret
DEBUGF 1, "SOCKET_process_end: killing socket %x\n", ebx
 
.error:
or eax, -1
mov [ebx + SOCKET.PID], 0
mov eax, ebx
mov ebx, [ebx + SOCKET.NextPtr]
pusha
call SOCKET_close.socket
popa
jmp .next_socket_test
 
.done:
pop ebx
 
ret
endp
 
;; [53.7] Send data through STREAM socket
 
 
 
;-----------------------------------------------------------------
;
; @param EBX is socket number
; @param ECX is application data size (number of bytes to send)
; @param EDX is pointer to application data buffer
; @return 0 (sent successfully) or -1 (error) in EAX
;;
proc socket_write_tcp stdcall
local sockAddr dd ?
; SOCKET_is_connecting
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
 
; DEBUGF 1, "socket_write_tcp(0x%x)\n", ebx
stdcall net_socket_num_to_addr, ebx
or eax, eax
jz .error
align 4
SOCKET_is_connecting:
 
mov ebx, eax
mov [sockAddr], ebx
DEBUGF 1,"SOCKET_is_connecting: %x\n", eax
 
; If the sockets window timer is nonzero, do not queue packet
cmp [ebx + SOCKET.wndsizeTimer], 0
jne .error
and [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
or [eax + SOCKET.options], SS_ISCONNECTING
 
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je .error
jmp SOCKET_notify
 
push eax
 
; Get the address of the callers data
mov edi, [TASK_BASE]
add edi, TASKDATA.mem_start
add edx, [edi]
mov esi, edx
 
pop eax
push eax
;-----------------------------------------------------------------
;
; SOCKET_is_connected
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
 
push ecx
mov bl, TH_ACK
stdcall build_tcp_packet, [sockAddr]
pop ecx
align 4
SOCKET_is_connected:
 
; Check destination IP address.
; If it is the local host IP, route it back to IP_RX
DEBUGF 1,"SOCKET_is_connected: %x\n", eax
 
pop ebx
push ecx
and [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
or [eax + SOCKET.options], SS_ISCONNECTED
 
mov eax, NET1OUT_QUEUE
mov edx, [stack_ip]
mov ecx, [sockAddr]
cmp edx, [ecx + SOCKET.RemoteIP]
jne .not_local
mov eax, IPIN_QUEUE
jmp SOCKET_notify
 
.not_local:
pop ecx
push ebx ; save ipbuffer number
 
call queue
 
mov esi, [sockAddr]
 
; increament SND.NXT in socket
; Amount to increment by is in ecx
add esi, SOCKET.SND_NXT
call add_inet_esi
;-----------------------------------------------------------------
;
; SOCKET_is_disconnecting
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
 
pop ebx
align 4
SOCKET_is_disconnecting:
 
; Copy the IP buffer to a resend queue
; If there isn't one, dont worry about it for now
mov esi, resendQ
mov ecx, 0
DEBUGF 1,"SOCKET_is_disconnecting: %x\n", eax
 
.next_resendq:
cmp ecx, NUMRESENDENTRIES
je .exit ; None found
cmp dword[esi + 4], 0
je @f ; found one
inc ecx
add esi, 8
jmp .next_resendq
and [eax + SOCKET.options], not (SS_ISCONNECTING)
or [eax + SOCKET.options], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
 
@@:
push ebx
jmp SOCKET_notify
 
; OK, we have a buffer descriptor ptr in esi.
; resend entry # in ecx
; Populate it
; socket #
; retries count
; retry time
; fill IP buffer associated with this descriptor
 
stdcall net_socket_addr_to_num, [sockAddr]
mov [esi + 4], eax
mov byte[esi + 1], TCP_RETRIES
mov word[esi + 2], TCP_TIMEOUT
 
inc ecx
; Now get buffer location, and copy buffer across. argh! more copying,,
mov edi, resendBuffer - IPBUFFSIZE
;-----------------------------------------------------------------
;
; SOCKET_is_disconnected
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
 
@@:
add edi, IPBUFFSIZE
loop @b
align 4
SOCKET_is_disconnected:
 
; we have dest buffer location in edi
pop eax
; convert source buffer pointer eax to the absolute address
mov ecx, IPBUFFSIZE
mul ecx
add eax, IPbuffs
mov esi, eax
DEBUGF 1,"SOCKET_is_disconnected: %x\n", eax
 
; do copy
mov ecx, IPBUFFSIZE
cld
rep movsb
and [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
or [eax + SOCKET.options], SS_CANTRCVMORE + SS_CANTSENDMORE
 
.exit:
xor eax, eax
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
je .tcp
 
cmp [eax + SOCKET.Protocol], IP_PROTO_UDP
je .udp
 
jmp SOCKET_notify
 
.tcp:
.udp:
mov [eax + UDP_SOCKET.LocalPort], 0 ; UDP and TCP structs store localport at the same offset
mov [eax + UDP_SOCKET.RemotePort], 0
 
jmp SOCKET_notify
 
 
;-----------------------------------------------------------------
;
; SOCKET_cant_recv_more
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
 
align 4
SOCKET_cant_recv_more:
 
DEBUGF 1,"SOCKET_cant_recv_more: %x\n", eax
 
or [eax + SOCKET.options], SS_CANTRCVMORE
 
ret
 
.error:
or eax, -1
ret
endp
 
 
;-----------------------------------------------------------------
;
; SOCKET_cant_send_more
;
; IN: eax = socket ptr
; OUT: /
;
;-----------------------------------------------------------------
 
align 4
SOCKET_cant_send_more:
 
DEBUGF 1,"SOCKET_cant_send_more: %x\n", eax
 
or [eax + SOCKET.options], SS_CANTSENDMORE
 
ret
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/stack.inc
1,918 → 1,789
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; STACK.INC ;;
;; ;;
;; TCP/IP stack for Menuet OS ;;
;; TCP/IP stack for KolibriOS ;;
;; ;;
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; See file COPYING for details ;;
;; Some parts of code are based on the work of: ;;
;; Mike Hibbett (menuetos network stack) ;;
;; Eugen Brasoveanu (solar os network stack and drivers) ;;
;; mike.dld (kolibrios socket code) ;;
;; ;;
;; Version 0.7 ;;
;; Added a timer per socket to allow delays when rx window ;;
;; gets below 1KB ;;
;; TCP part is based on 4.4BSD ;;
;; ;;
;;10.01.2007 Bugfix for checksum function from Paolo Franchetti ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
$Revision: 3523 $
 
 
;*******************************************************************
; Interface
; The interfaces defined in ETHERNET.INC plus:
; stack_init
; stack_handler
; app_stack_handler
; app_socket_handler
; checksum
;
;*******************************************************************
 
uglobal
StackCounters:
dumped_rx_count dd 0
arp_tx_count:
dd 0
arp_rx_count:
dd 0
ip_rx_count:
dd 0
ip_tx_count:
dd 0
net_10ms dd ?
net_tmr_count dw ?
endg
 
; socket buffers
SOCKETBUFFSIZE equ 4096 ; state + config + buffer.
SOCKETHEADERSIZE equ SOCKET.rxData ; thus 4096 - SOCKETHEADERSIZE bytes data
MAX_NET_DEVICES = 16
ARP_BLOCK = 1 ; true or false
 
;NUM_SOCKETS equ 16 ; Number of open sockets supported. Was 20
MIN_EPHEMERAL_PORT = 49152
MIN_EPHEMERAL_PORT_N = 0x00C0 ; same in Network byte order (FIXME)
MAX_EPHEMERAL_PORT = 61000
MAX_EPHEMERAL_PORT_N = 0x48EE ; same in Network byte order (FIXME)
 
; IPBUFF status values
BUFF_EMPTY equ 0
BUFF_RX_FULL equ 1
BUFF_ALLOCATED equ 2
BUFF_TX_FULL equ 3
; Ethernet protocol numbers
ETHER_ARP = 0x0608
ETHER_IPv4 = 0x0008
ETHER_IPv6 = 0xDD86
ETHER_PPP_DISCOVERY = 0x6388
ETHER_PPP_SESSION = 0x6488
 
NUM_IPBUFFERS equ 20 ; buffers allocated for TX/RX
; PPP protocol numbers
PPP_IPv4 = 0x2100
PPP_IPV6 = 0x5780
 
NUMQUEUES equ 4
;Protocol family
AF_UNSPEC = 0
AF_LOCAL = 1
AF_INET4 = 2
AF_INET6 = 10
AF_PPP = 777
 
EMPTY_QUEUE equ 0
IPIN_QUEUE equ 1
IPOUT_QUEUE equ 2
NET1OUT_QUEUE equ 3
; Internet protocol numbers
IP_PROTO_IP = 0
IP_PROTO_ICMP = 1
IP_PROTO_TCP = 6
IP_PROTO_UDP = 17
 
NO_BUFFER equ 0xFFFF
IPBUFFSIZE equ 1500 ; MTU of an ethernet packet
NUMQUEUEENTRIES equ NUM_IPBUFFERS
NUMRESENDENTRIES equ 18 ; Buffers for TCP resend packets
; PPP protocol number
PPP_PROTO_ETHERNET = 666
 
; These are the 0x40 function codes for application access to the stack
STACK_DRIVER_STATUS equ 52
SOCKET_INTERFACE equ 53
; Socket types
SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3
 
; Socket options
SO_ACCEPTCON = 1 shl 0
SO_BROADCAST = 1 shl 1
SO_DEBUG = 1 shl 2
SO_DONTROUTE = 1 shl 3
SO_KEEPALIVE = 1 shl 4
SO_OOBINLINE = 1 shl 5
SO_REUSEADDR = 1 shl 6
SO_REUSEPORT = 1 shl 7
SO_USELOOPBACK = 1 shl 8
SO_BINDTODEVICE = 1 shl 9
 
; 128KB allocated for the stack and network driver buffers and other
; data requirements
;stack_data_start equ 0x700000
;eth_data_start equ 0x700000
;stack_data equ 0x704000
;stack_data_end equ 0x71ffff
SO_BLOCK = 1 shl 10 ; TO BE REMOVED
SO_NONBLOCK = 1 shl 31
 
; 32 bit word
stack_config equ stack_data
; Socket flags for user calls
MSG_PEEK = 0x02
MSG_DONTWAIT = 0x40
 
; 32 bit word - IP Address in network format
stack_ip equ stack_data + 4
; Socket level
SOL_SOCKET = 0
 
; 1 byte. 0 == inactive, 1 = active
ethernet_active equ stack_data + 9
 
; Socket States
SS_NOFDREF = 0x0001 ; no file table ref any more
SS_ISCONNECTED = 0x0002 ; socket connected to a peer
SS_ISCONNECTING = 0x0004 ; in process of connecting to peer
SS_ISDISCONNECTING = 0x0008 ; in process of disconnecting
SS_CANTSENDMORE = 0x0010 ; can't send more data to peer
SS_CANTRCVMORE = 0x0020 ; can't receive more data from peer
SS_RCVATMARK = 0x0040 ; at mark on input
SS_ISABORTING = 0x0080 ; aborting fd references - close()
SS_RESTARTSYS = 0x0100 ; restart blocked system calls
SS_ISDISCONNECTED = 0x0800 ; socket disconnected from peer
 
; TODO :: empty memory area
SS_ASYNC = 0x0100 ; async i/o notify
SS_ISCONFIRMING = 0x0200 ; deciding to accept connection req
SS_MORETOCOME = 0x0400
 
; Address of selected socket
;sktAddr equ stack_data + 32
; Parameter to checksum routine - data ptr
checkAdd1 equ stack_data + 36
; Parameter to checksum routine - 2nd data ptr
checkAdd2 equ stack_data + 40
; Parameter to checksum routine - data size
checkSize1 equ stack_data + 44
; Parameter to checksum routine - 2nd data size
checkSize2 equ stack_data + 46
; result of checksum routine
checkResult equ stack_data + 48
SS_BLOCKED = 0x8000
 
; holds the TCP/UDP pseudo header. SA|DA|0|prot|UDP len|
pseudoHeader equ stack_data + 50
 
; receive and transmit IP buffer allocation
;sockets equ stack_data + 62
Next_free2 equ stack_data + 62;Next_free2 equ sockets + (SOCKETBUFFSIZE * NUM_SOCKETS)
; 1560 byte buffer for rx / tx ethernet packets
Ether_buffer equ Next_free2
Next_free3 equ Ether_buffer + 1518
last_1sTick equ Next_free3
IPbuffs equ Next_free3 + 1
queues equ IPbuffs + ( NUM_IPBUFFERS * IPBUFFSIZE )
queueList equ queues + (2 * NUMQUEUES)
last_1hsTick equ queueList + ( 2 * NUMQUEUEENTRIES )
SOCKET_MAXDATA = 4096*32 ; must be 4096*(power of 2) where 'power of 2' is at least 8
 
;resendQ equ queueList + ( 2 * NUMQUEUEENTRIES )
;resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP
; equ resendBuffer + ( IPBUFFSIZE * NUMRESENDENTRIES )
; Network driver types
NET_TYPE_LOOPBACK = 0
NET_TYPE_ETH = 1
NET_TYPE_SLIP = 2
 
MAX_backlog = 20 ; maximum backlog for stream sockets
 
; Error Codes
ENOBUFS = 55
ECONNREFUSED = 61
ECONNRESET = 52
ETIMEDOUT = 60
ECONNABORTED = 53
 
;resendQ equ 0x770000
;resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP ; XTODO: validate size
resendBuffer equ resendQ + ( 8 * NUMRESENDENTRIES ) ; for TCP
; Api protocol numbers
API_ETH = 0
API_IPv4 = 1
API_ICMP = 2
API_UDP = 3
API_TCP = 4
API_ARP = 5
API_PPPOE = 6
API_IPv6 = 7
 
HWACC_TCP_IPv4 = 1 shl 0
 
uglobal
net_sockets rd 2
endg
struct NET_DEVICE
 
; simple macro for memory set operation
macro _memset_dw adr,value,amount
{
mov edi, adr
mov ecx, amount
if value = 0
xor eax, eax
else
mov eax, value
end if
cld
rep stosd
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 (offload engines)
 
ends
 
 
; Exactly as it says..
macro pseudo_random reg {
add reg, [esp]
rol reg, 5
xor reg, [timer_ticks]
; add reg, [CPU_FREQ]
imul reg, 214013
xor reg, 0xdeadbeef
rol reg, 9
}
 
; Network to Hardware byte order (dword)
macro ntohd reg {
 
; Below, the main network layer source code is included
;
rol word reg, 8
rol dword reg, 16
rol word reg , 8
 
}
 
; Network to Hardware byte order (word)
macro ntohw reg {
 
rol word reg, 8
 
}
 
 
include "queue.inc"
include "eth_drv/ethernet.inc"
include "ip.inc"
 
include "loopback.inc"
include "ethernet.inc"
 
include "PPPoE.inc"
 
include "ARP.inc"
include "IPv4.inc"
include "IPv6.inc"
 
include "icmp.inc"
include "udp.inc"
include "tcp.inc"
 
include "socket.inc"
 
;***************************************************************************
; Function
 
 
align 4
uglobal
 
NET_RUNNING dd ?
NET_DEFAULT dd ?
NET_DRV_LIST rd MAX_NET_DEVICES
 
endg
 
 
;-----------------------------------------------------------------
;
; stack_init
;
; Description
; Clear all allocated memory to zero. This ensures that
; on startup, the stack is inactive, and consumes no resources
; This is a kernel function, called prior to the OS main loop
; in set_variables
; This function calls all network init procedures
;
;***************************************************************************
 
; IN: /
; OUT: /
;
;-----------------------------------------------------------------
align 4
stack_init:
; Init two address spaces with default values
_memset_dw stack_data_start, 0, 0x20000/4
_memset_dw resendQ, 0, NUMRESENDENTRIES * 2
 
mov [net_sockets], 0
mov [net_sockets + 4], 0
; Init the network drivers list
xor eax, eax
mov edi, NET_RUNNING
mov ecx, (MAX_NET_DEVICES + 2)
rep stosd
 
; Queries initialization
call queueInit
PPPoE_init
 
; The following block sets up the 1s timer
mov al, 0x0
out 0x70, al
in al, 0x71
mov [last_1sTick], al
IPv4_init
; IPv6_init
ICMP_init
 
ARP_init
UDP_init
TCP_init
 
SOCKET_init
 
mov [net_tmr_count], 0
 
ret
 
 
 
; Wakeup every tick.
proc stack_handler_has_work?
 
mov eax, [timer_ticks]
cmp eax, [last_1hsTick]
cmp eax, [net_10ms]
 
ret
endp
 
 
;***************************************************************************
; Function
;-----------------------------------------------------------------
;
; stack_handler
;
; Description
; The kernel loop routine for the stack
; This is a kernel function, called in the main loop
; This function is called in kernel loop
;
;***************************************************************************
; IN: /
; OUT: /
;
;-----------------------------------------------------------------
align 4
stack_handler:
 
call ethernet_driver
call ip_rx
; Test for 10ms tick
mov eax, [timer_ticks]
cmp eax, [net_10ms]
je .exit
mov [net_10ms], eax
 
cmp [NET_RUNNING], 0
je .exit
 
; Test for 10ms tick, call tcp timer
mov eax, [timer_ticks];[0xfdf0]
cmp eax, [last_1hsTick]
je sh_001
test [net_10ms], 0x0f ; 160ms
jnz .exit
 
mov [last_1hsTick], eax
call tcp_tx_handler
TCP_timer_160ms
 
sh_001:
test [net_10ms], 0x3f ; 640ms
jnz .exit
 
; Test for 1 second event, call 1s timer functions
mov al, 0x0;second
out 0x70, al
in al, 0x71
cmp al, [last_1sTick]
je sh_exit
TCP_timer_640ms
ARP_decrease_entry_ttls
IPv4_decrease_fragment_ttls
 
mov [last_1sTick], al
.exit:
ret
 
stdcall arp_table_manager, ARP_TABLE_TIMER, 0, 0
call tcp_tcb_handler
 
sh_exit:
ret
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Checksum [by Johnny_B]
;; IN:
;; buf_ptr=POINTER to buffer
;; buf_size=SIZE of buffer
;; OUT:
;; AX=16-bit checksum
;; Saves all used registers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc checksum_jb stdcall uses ebx esi ecx,\
buf_ptr:DWORD, buf_size:DWORD
align 4
NET_link_changed:
 
xor eax, eax
xor ebx, ebx;accumulator
mov esi, dword[buf_ptr]
mov ecx, dword[buf_size]
shr ecx, 1; ecx=ecx/2
jnc @f ; if CF==0 then size is even number
mov bh, byte[esi + ecx*2]
@@:
cld
DEBUGF 1,"NET_link_changed device=0x%x status=0x%x\n", ebx, [ebx + NET_DEVICE.state]
 
align 4
NET_send_event:
 
DEBUGF 1,"NET_send_event\n"
 
; Send event to all applications
push edi ecx
mov edi, SLOT_BASE
mov ecx, [TASK_COUNT]
.loop:
lodsw ;eax=word[esi],esi=esi+2
xchg ah, al;cause must be a net byte-order
add ebx, eax
add edi, 256
or [edi + APPDATA.event_mask], EVENT_NETWORK2
loop .loop
pop ecx edi
 
mov eax, ebx
shr eax, 16
add ax, bx
not ax
 
ret
endp
 
;***************************************************************************
; Function
; checksum
 
 
;-----------------------------------------------------------------
;
; Description
; checkAdd1,checkAdd2, checkSize1, checkSize2, checkResult
; Dont break anything; Most registers are used by the caller
; This code is derived from the 'C' source, cksum.c, in the book
; Internetworking with TCP/IP Volume II by D.E. Comer
; NET_add_device:
;
;***************************************************************************
; This function is called by the network drivers,
; to register each running NIC to the kernel
;
; IN: Pointer to device structure in ebx
; OUT: Device num in eax, -1 on error
;
;-----------------------------------------------------------------
align 4
NET_add_device:
 
DEBUGF 1,"NET_Add_Device: %x\n", ebx ;;; TODO: use mutex to lock net device list
 
checksum:
pusha
mov eax, [checkAdd1]
xor edx, edx ; edx is the accumulative checksum
xor ebx, ebx
mov cx, [checkSize1]
shr cx, 1
jz cs1_1
cmp [NET_RUNNING], MAX_NET_DEVICES
jae .error
 
cs1:
mov bh, [eax]
mov bl, [eax + 1]
;----------------------------------
; Check if device is already listed
mov eax, ebx
mov ecx, MAX_NET_DEVICES ; We need to check whole list because a device may be removed without re-organizing list
mov edi, NET_DRV_LIST
 
add eax, 2
add edx, ebx
repne scasd ; See if device is already in the list
jz .error
 
loopw cs1
;----------------------------
; Find empty slot in the list
xor eax, eax
mov ecx, MAX_NET_DEVICES
mov edi, NET_DRV_LIST
 
cs1_1:
and word [checkSize1], 0x01
jz cs_test2
repne scasd
jnz .error
 
mov bh, [eax]
xor bl, bl
sub edi, 4
 
add edx, ebx
;-----------------------------
; Add device to the found slot
mov [edi], ebx ; add device to list
 
cs_test2:
mov cx, [checkSize2]
cmp cx, 0
jz cs_exit ; Finished if no 2nd buffer
mov eax, edi ; Calculate device number in eax
sub eax, NET_DRV_LIST
shr eax, 2
 
mov eax, [checkAdd2]
inc [NET_RUNNING] ; Indicate that one more network device is up and running
 
shr cx, 1
jz cs2_1
cmp eax, 1 ; If it's the first network device, try to set it as default
jne @f
push eax
call NET_set_default
pop eax
@@:
 
cs2:
mov bh, [eax]
mov bl, [eax + 1]
call NET_send_event
 
add eax, 2
add edx, ebx
DEBUGF 1,"Device number: %u\n", eax
ret
 
loopw cs2
 
cs2_1:
and word [checkSize2], 0x01
jz cs_exit
 
mov bh, [eax]
xor bl, bl
 
add edx, ebx
 
cs_exit:
mov ebx, edx
 
shr ebx, 16
and edx, 0xffff
add edx, ebx
mov eax, edx
shr eax, 16
add edx, eax
not dx
 
mov [checkResult], dx
popa
.error:
or eax, -1
DEBUGF 2,"Adding network device failed\n"
ret
 
 
 
 
;***************************************************************************
; Function
; app_stack_handler
;-----------------------------------------------------------------
;
; Description
; This is an application service, called by int 0x40, function 52
; It provides application access to the network interface layer
; NET_set_default
;
;***************************************************************************
iglobal
; API to set the default interface
;
; IN: Device num in eax
; OUT: Device num in eax, -1 on error
;
;-----------------------------------------------------------------
align 4
f52call:
dd app_stack_handler.00
dd app_stack_handler.01
dd app_stack_handler.02
dd app_stack_handler.03
dd app_stack_handler.fail ;04
dd app_stack_handler.fail ;05
dd stack_insert_packet ;app_stack_handler.06
dd app_stack_handler.fail ;07
dd stack_get_packet ;app_stack_handler.08
dd app_stack_handler.09
dd app_stack_handler.10
dd app_stack_handler.11
dd app_stack_handler.12
dd app_stack_handler.13
dd app_stack_handler.14
dd app_stack_handler.15
endg
app_stack_handler:
;in ebx,ecx
;out eax
cmp ebx, 15
ja .fail ;if more than 15 then exit
NET_set_default:
 
jmp dword [f52call+ebx*4]
DEBUGF 1,"NET_set_default: device=%x\n", eax
 
cmp eax, MAX_NET_DEVICES
jae .error
 
.00:
; Read the configuration word
mov eax, [stack_config]
cmp [NET_DRV_LIST+eax*4], 0
je .error
 
mov [NET_DEFAULT], eax
 
DEBUGF 1,"NET_set_default: succes\n"
ret
 
.01:
; read the IP address
mov eax, [stack_ip]
.error:
or eax, -1
DEBUGF 1,"NET_set_default: failed\n"
ret
 
.02:
; write the configuration word
mov [stack_config], ecx
 
; <Slip shouldn't be active anyway - thats an operational issue.>
; If ethernet now enabled, probe for the card, reset it and empty
; the packet buffer
; If all successfull, enable the card.
; If ethernet now disabled, set it as disabled. Should really
; empty the tcpip data area too.
;-----------------------------------------------------------------
;
; NET_Remove_Device:
;
; This function is called by etwork drivers,
; to unregister network devices from the kernel
;
; IN: Pointer to device structure in ebx
; OUT: eax: -1 on error
;
;-----------------------------------------------------------------
align 4
NET_remove_device:
 
; ethernet interface is '3' in ls 7 bits
and cl, 0x7f
cmp cl, 3
je ash_eth_enable
; Ethernet isn't enabled, so make sure that the card is disabled
mov [ethernet_active], byte 0
ret
cmp [NET_RUNNING], 0
je .error
 
.03:
; write the IP Address
mov [stack_ip], ecx
ret
;old functions was deleted
;.06:
; Insert an IP packet into the stacks received packet queue
; call stack_insert_packet
; ret
cmp [NET_DRV_LIST], ebx
jne @f
mov [NET_DRV_LIST], 0
cmp [NET_RUNNING], 1
je @f
; there are still active devices, find one and make it default
xor eax, eax
mov ecx, MAX_NET_DEVICES
mov edi, NET_DRV_LIST
repe scasd
je @f
shr edi, 2
dec edi
mov [NET_DEFAULT], edi
@@:
 
; Test for any packets queued for transmission over the network
;----------------------------
; Find the driver in the list
 
;.08:
; call stack_get_packet
; Extract a packet queued for transmission by the network
; ret
mov eax, ebx
mov ecx, MAX_NET_DEVICES
mov edi, NET_DRV_LIST+4
 
.09:
; read the gateway IP address
mov eax, [gateway_ip]
ret
repne scasd
jnz .error
 
.10:
; read the subnet mask
mov eax, [subnet_mask]
ret
.11:
; write the gateway IP Address
mov [gateway_ip], ecx
ret
;------------------------
; Remove it from the list
 
.12:
; write the subnet mask
mov [subnet_mask], ecx
ret
xor eax, eax
mov dword [edi-4], eax
 
.13:
; read the dns
mov eax, [dns_ip]
ret
call NET_send_event
 
.14:
; write the dns IP Address
mov [dns_ip], ecx
dec [NET_RUNNING]
ret
 
.15:
;<added by Frank Sommer>
; in ecx we need 4 to read the last 2 bytes
; or we need 0 to read the first 4 bytes
cmp ecx, 4
ja .param_error
 
; read MAC, returned (in mirrored byte order) in eax
mov eax, [node_addr + ecx]
.error:
or eax, -1
ret
 
.param_error:
or eax, -1 ; params not accepted
ret
 
.16:
; 0 -> arp_probe
; 1 -> arp_announce
; 2 -> arp_responce (not supported yet)
test ecx, ecx
je a_probe
 
dec ebx
jz a_ann ; arp announce
.fail:
or eax, -1
ret
;-----------------------------------------------------------------
;
; NET_ptr_to_num
;
; IN: ebx = ptr to device struct
; OUT: edi = -1 on error, device number otherwise
;
;-----------------------------------------------------------------
align 4
NET_ptr_to_num:
push ecx
 
; cmp ebx,2
; jne a_resp ; arp response
mov ecx, MAX_NET_DEVICES
mov edi, NET_DRV_LIST
 
; arp probe, sender IP must be set to 0.0.0.0, target IP is set to address being probed
; ecx: pointer to target MAC, MAC should set to 0 by application
; edx: target IP
a_probe:
push dword [stack_ip]
.loop:
cmp ebx, [edi]
jz .found
add edi, 4
dec ecx
jnz .loop
 
mov edx, [stack_ip]
and [stack_ip], dword 0
mov esi, ecx ; pointer to target MAC address
call arp_request
; repnz scasd could work too if eax is used instead of ebx!
 
pop dword [stack_ip]
ret
or edi, -1
 
; arp announce, sender IP must be set to target IP
; ecx: pointer to target MAC
a_ann:
mov edx, [stack_ip]
mov esi, ecx ; pointer to target MAC address
call arp_request
pop ecx
ret
 
.17:
;</added by Frank Sommer>
; modified by [smb]
.found:
sub edi, NET_DRV_LIST
shr edi, 2
 
;<added by Johnny_B>
; ARPTable manager interface
;see "proc arp_table_manager" for more details
stdcall arp_table_manager, ecx, edx, esi;Opcode,Index,Extra
pop ecx
ret
;</added by Johnny_B>
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ash_eth_enable:
; Probe for the card. This will reset it and enable the interface
; if found
call eth_probe
test eax, eax
jz ash_eth_done ; Abort if no hardware found
 
mov [ethernet_active], byte 1
ash_eth_done:
ret
;***************************************************************************
; Function
; app_socket_handler
;-----------------------------------------------------------------
;
; Description
; This is an application service, called by int 0x40, function 53
; It provides application access to stack socket services
; such as opening sockets
; checksum_1
;
;***************************************************************************
iglobal
; This is the first of two functions needed to calculate a checksum.
;
; IN: edx = start offset for semi-checksum
; esi = pointer to data
; ecx = data size
; OUT: edx = semi-checksum
;
;
; Code was optimized by diamond
;
;-----------------------------------------------------------------
align 4
f53call:
dd socket_open ;00
dd socket_close ;01
dd socket_poll ;02
dd socket_read ;03
dd socket_write ;04
dd socket_open_tcp ;05
dd socket_status ;06
dd socket_write_tcp ;07
dd socket_close_tcp ;08
dd is_localport_unused ;09
dd app_socket_handler.10
dd socket_read_packet ;11
endg
checksum_1:
 
app_socket_handler:
;in ebx,ecx,edx,wsi
;out eax
cmp eax, 255
je stack_internal_status
shr ecx, 1
pushf
jz .no_2
 
cmp eax, 11
ja .fail ;if more than 15 then exit
shr ecx, 1
pushf
jz .no_4
 
jmp dword [f53call+eax*4]
shr ecx, 1
pushf
jz .no_8
 
.10:
mov eax, dword[drvr_cable]
test eax, eax
jnz @f ; if function is not implented, return -1
or al, -1
ret
@@:
jmp dword[drvr_cable]
.loop:
add dl, [esi+1]
adc dh, [esi+0]
 
.fail:
or eax, -1
ret
uglobal
ARPTmp:
times 14 db 0
endg
adc dl, [esi+3]
adc dh, [esi+2]
 
;***************************************************************************
; Function
; stack_internal_status
;
; Description
; Returns information about the internal status of the stack
; This is only useful for debugging
; It works with the ethernet driver
; sub function in ebx
; return requested data in eax
;
;***************************************************************************
; This sub function allows access to debugging information on the stack
; ecx holds the request:
; 100 : return length of empty queue
; 101 : return length of IPOUT QUEUE
; 102 : return length of IPIN QUEUE
; 103 : return length of NET1OUT QUEUE
; 200 : return # of ARP entries
; 201 : return size of ARP table ( max # entries )
; 202 : select ARP table entry #
; 203 : return IP of selected table entry
; 204 : return High 4 bytes of MAC address of selected table entry
; 205 : return low 2 bytes of MAC address of selected table entry
; 206 : return status word of selected table entry
; 207 : return Time to live of selected table entry
adc dl, [esi+5]
adc dh, [esi+4]
 
adc dl, [esi+7]
adc dh, [esi+6]
 
; 2 : return number of IP packets received
; 3 : return number of packets transmitted
; 4 : return number of received packets dumped
; 5 : return number of arp packets received
; 6 : return status of packet driver
; ( 0 == not active, FFFFFFFF = successful )
adc edx, 0
add esi, 8
 
dec ecx
jnz .loop
 
stack_internal_status:
cmp ebx, 100
jnz notsis100
adc edx, 0
 
; 100 : return length of EMPTY QUEUE
mov ebx, EMPTY_QUEUE
call queueSize
ret
.no_8:
popf
jnc .no_4
 
notsis100:
cmp ebx, 101
jnz notsis101
add dl, [esi+1]
adc dh, [esi+0]
 
; 101 : return length of IPOUT QUEUE
mov ebx, IPOUT_QUEUE
call queueSize
ret
adc dl, [esi+3]
adc dh, [esi+2]
 
notsis101:
cmp ebx, 102
jnz notsis102
adc edx, 0
add esi, 4
 
; 102 : return length of IPIN QUEUE
mov ebx, IPIN_QUEUE
call queueSize
ret
.no_4:
popf
jnc .no_2
 
notsis102:
cmp ebx, 103
jnz notsis103
add dl, [esi+1]
adc dh, [esi+0]
 
; 103 : return length of NET1OUT QUEUE
mov ebx, NET1OUT_QUEUE
call queueSize
ret
adc edx, 0
inc esi
inc esi
 
notsis103:
cmp ebx, 200
jnz notsis200
.no_2:
popf
jnc .end
 
; 200 : return num entries in arp table
movzx eax, byte [NumARP]
add dh, [esi+0]
adc edx, 0
.end:
ret
 
notsis200:
cmp ebx, 201
jnz notsis201
;-----------------------------------------------------------------
;
; checksum_2
;
; This function calculates the final ip/tcp/udp checksum for you
;
; IN: edx = semi-checksum
; OUT: dx = checksum (in INET byte order)
;
;-----------------------------------------------------------------
align 4
checksum_2:
 
; 201 : return arp table size
mov eax, 20; ARP_TABLE_SIZE
ret
mov ecx, edx
shr ecx, 16
and edx, 0xffff
add edx, ecx
 
notsis201:
cmp ebx, 202
jnz notsis202
mov ecx, edx
shr ecx, 16
add dx, cx
test dx, dx ; it seems that ZF is not set when CF is set :(
not dx
jnz .not_zero
dec dx
.not_zero:
xchg dl, dh
 
; 202 - read the requested table entry
; into a temporary buffer
; ecx holds the entry number
DEBUGF 1,"Checksum: %x\n", dx
 
mov eax, ecx
mov ecx, 14; ARP_ENTRY_SIZE
mul ecx
 
mov ecx, [eax + ARPTable]
mov [ARPTmp], ecx
mov ecx, [eax + ARPTable+4]
mov [ARPTmp+4], ecx
mov ecx, [eax + ARPTable+8]
mov [ARPTmp+8], ecx
mov cx, [eax + ARPTable+12]
mov [ARPTmp+12], cx
ret
 
notsis202:
cmp ebx, 203
jnz notsis203
 
; 203 - return IP address
mov eax, [ARPTmp]
ret
 
notsis203:
cmp ebx, 204
jnz notsis204
;----------------------------------------------------------------
;
; System function to work with network devices (75)
;
;----------------------------------------------------------------
align 4
sys_network: ; FIXME: make default device easily accessible
 
; 204 - return MAC high dword
mov eax, [ARPTmp+4]
ret
cmp ebx, -1
jne @f
 
notsis204:
cmp ebx, 205
jnz notsis205
mov eax, [NET_RUNNING]
jmp .return
 
; 205 - return MAC ls word
movzx eax, word [ARPTmp+8]
ret
@@:
cmp bh, MAX_NET_DEVICES ; Check if device number exists
jae .doesnt_exist
 
notsis205:
cmp ebx, 206
jnz notsis206
mov esi, ebx
and esi, 0x0000ff00
shr esi, 6
 
; 206 - return status word
movzx eax, word [ARPTmp+10]
ret
cmp dword [esi + NET_DRV_LIST], 0 ; check if driver is running
je .doesnt_exist
 
notsis206:
cmp ebx, 207
jnz notsis207
mov eax, [esi + NET_DRV_LIST]
 
; 207 - return ttl word
movzx eax, word [ARPTmp+12]
ret
and ebx, 0x000000ff
cmp ebx, .number
ja .doesnt_exist
jmp dword [.table + 4*ebx]
 
notsis207:
cmp ebx, 2
jnz notsis2
.table:
dd .get_type ; 0
dd .get_dev_name ; 1
dd .reset ; 2
dd .stop ; 3
dd .get_ptr ; 4
dd .get_drv_name ; 5
dd .set_default ; 6
.number = ($ - .table) / 4 - 1
 
; 2 : return number of IP packets received
mov eax, [ip_rx_count]
ret
.get_type: ; 0 = Get device type (ethernet/token ring/...)
 
notsis2:
cmp ebx, 3
jnz notsis3
mov eax, [eax + NET_DEVICE.type]
jmp .return
 
; 3 : return number of packets transmitted
mov eax, [ip_tx_count]
ret
 
notsis3:
cmp ebx, 4
jnz notsis4
.get_dev_name: ; 1 = Get device name
 
; 4 : return number of received packets dumped
mov eax, [dumped_rx_count]
ret
mov esi, [eax + NET_DEVICE.name]
mov edi, ecx
 
notsis4:
cmp ebx, 5
jnz notsis5
mov ecx, 64/4 ; max length
rep movsd
 
; 5 : return number of arp packets received
mov eax, [arp_rx_count]
ret
xor eax, eax
jmp .return
 
notsis5:
cmp ebx, 6
jnz notsis6
.reset: ; 2 = Reset the device
 
; 6 : return status of packet driver
; ( 0 == not active, FFFFFFFF = successful )
mov eax, [eth_status]
ret
call [eax + NET_DEVICE.reset]
jmp .return
 
notsis6:
xor eax, eax
ret
.stop: ; 3 = Stop driver for this device
 
call [eax + NET_DEVICE.unload]
jmp .return
 
 
;***************************************************************************
; Function
; stack_get_packet
;
; Description
; extracts an IP packet from the NET1 output queue
; and sends the data to the calling process
; pointer to data in edx
; returns number of bytes read in eax
;
;***************************************************************************
stack_get_packet:
; Look for a buffer to tx
mov eax, NET1OUT_QUEUE
call dequeue
cmp ax, NO_BUFFER
je sgp_non_exit ; Exit if no buffer available
.get_ptr: ; 4 = Get driver pointer
 
push eax ; Save buffer number for freeing at end
jmp .return
 
push edx
; convert buffer pointer eax to the absolute address
mov ecx, IPBUFFSIZE
mul ecx
add eax, IPbuffs
pop edx
 
push eax ; save address of IP data
; Get the address of the callers data
mov edi, [TASK_BASE]
add edi, TASKDATA.mem_start
add edx, [edi]
mov edi, edx
pop eax
.get_drv_name: ; 5 = Get driver name
 
mov ecx, 1500 ; should get the actual number of bytes to write
mov esi, eax
cld
rep movsb ; copy the data across
xor eax, eax
jmp .return
 
; And finally, return the buffer to the free queue
pop eax
call freeBuff
 
mov eax, 1500
ret
.set_default: ; 6 = Set default device
 
sgp_non_exit:
xor eax, eax
call NET_set_default
jmp .return
 
.doesnt_exist:
mov eax, -1
 
.return:
mov [esp+32], eax
ret
 
 
 
;***************************************************************************
; Function
; stack_insert_packet
;----------------------------------------------------------------
;
; Description
; writes an IP packet into the stacks receive queue
; # of bytes to write in ecx
; pointer to data in edx
; returns 0 in eax ok, -1 == failed
; System function to work with protocols (76)
;
;***************************************************************************
stack_insert_packet:
;----------------------------------------------------------------
align 4
sys_protocols:
cmp bh, MAX_NET_DEVICES ; Check if device number exists
jae .doesnt_exist
 
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je sip_err_exit
mov esi, ebx
and esi, 0x0000ff00
shr esi, 6 ; now we have the device num * 4 in esi
cmp [esi + NET_DRV_LIST], 0 ; check if driver is running
je .doesnt_exist
 
push eax
push .return ; return address (we will be using jumps instead of calls)
 
; save the pointers to the data buffer & size
push edx
push ecx
mov eax, ebx ; set ax to protocol number
shr eax, 16 ;
 
; convert buffer pointer eax to the absolute address
mov ecx, IPBUFFSIZE
mul ecx
add eax, IPbuffs
cmp ax, API_ETH
je ETH_api
 
mov edx, eax
cmp ax, API_IPv4
je IPv4_api
 
; So, edx holds the IPbuffer ptr
cmp ax, API_ICMP
je ICMP_api
 
pop ecx ; count of bytes to send
mov ebx, ecx ; need the length later
pop eax ; get callers ptr to data to send
cmp ax, API_UDP
je UDP_api
 
; Get the address of the callers data
mov edi, [TASK_BASE]
add edi, TASKDATA.mem_start
add eax, [edi]
mov esi, eax
cmp ax, API_TCP
je TCP_api
 
mov edi, edx
cld
rep movsb ; copy the data across
cmp ax, API_ARP
je ARP_api
 
pop ebx
cmp ax, API_PPPOE
je PPPoE_api
 
mov eax, IPIN_QUEUE
call queue
cmp ax, API_IPv6
je IPv6_api
 
inc dword [ip_rx_count]
add esp, 4 ; if we reached here, no function was called, so we need to balance stack
 
mov eax, 0
ret
.doesnt_exist:
mov eax, -1
 
sip_err_exit:
mov eax, 0xFFFFFFFF
.return:
mov [esp+28+4], eax ; return eax value to the program
ret
 
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/tcp.inc
1,1176 → 1,224
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; TCP.INC ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
;; ;;
;; TCP Processes for Menuet OS TCP/IP stack ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;;
;; Based on the code of 4.4BSD ;;
;; ;;
;; See file COPYING for details ;;
;; v0.6 : Added reset handling in the established state ;;
;; Added a timer per socket to allow delays when ;;
;; rx window gets below 1KB ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
$Revision: 3406 $
 
; Socket states
TCPS_CLOSED = 0
TCPS_LISTEN = 1
TCPS_SYN_SENT = 2
TCPS_SYN_RECEIVED = 3
TCPS_ESTABLISHED = 4
TCPS_CLOSE_WAIT = 5
TCPS_FIN_WAIT_1 = 6
TCPS_CLOSING = 7
TCPS_LAST_ACK = 8
TCPS_FIN_WAIT_2 = 9
TCPS_TIMED_WAIT = 10
 
; TCP TCB states
TCB_LISTEN equ 1
TCB_SYN_SENT equ 2
TCB_SYN_RECEIVED equ 3
TCB_ESTABLISHED equ 4
TCB_FIN_WAIT_1 equ 5
TCB_FIN_WAIT_2 equ 6
TCB_CLOSE_WAIT equ 7
TCB_CLOSING equ 8
TCB_LAST_ACK equ 9
TCB_TIMED_WAIT equ 10
TCB_CLOSED equ 11
; Socket Flags
TF_ACKNOW = 1 shl 0 ; ack peer immediately
TF_DELACK = 1 shl 1 ; ack, but try to delay it
TF_NODELAY = 1 shl 2 ; don't delay packets to coalesce
TF_NOOPT = 1 shl 3 ; don't use tcp options
TF_SENTFIN = 1 shl 4 ; have sent FIN
TF_REQ_SCALE = 1 shl 5 ; have/will request window scaling
TF_RCVD_SCALE = 1 shl 6 ; other side has requested scaling
TF_REQ_TSTMP = 1 shl 7 ; have/will request timestamps
TF_RCVD_TSTMP = 1 shl 8 ; a timestamp was received in SYN
TF_SACK_PERMIT = 1 shl 9 ; other side said I could SACK
 
TH_FIN = 0x01
TH_SYN = 0x02
TH_RST = 0x04
TH_PUSH = 0x08
TH_ACK = 0x10
TH_URG = 0x20
; Segment flags
TH_FIN = 1 shl 0
TH_SYN = 1 shl 1
TH_RST = 1 shl 2
TH_PUSH = 1 shl 3
TH_ACK = 1 shl 4
TH_URG = 1 shl 5
 
TWOMSL equ 10 ; # of secs to wait before closing socket
; Segment header options
TCP_OPT_EOL = 0 ; End of option list.
TCP_OPT_NOP = 1 ; No-Operation.
TCP_OPT_MAXSEG = 2 ; Maximum Segment Size.
TCP_OPT_WINDOW = 3 ; window scale
TCP_OPT_SACK_PERMIT = 4 ; Selective Acknowledgement
TCP_OPT_SACK = 5
TCP_OPT_TIMESTAMP = 8
 
TCP_RETRIES equ 5 ; Number of times to resend a packet
TCP_TIMEOUT equ 20 ; resend if not replied to in x hs
; Fundamental timer values
TCP_time_MSL = 47 ; max segment lifetime (30s)
TCP_time_re_min = 2 ; min retransmission (1,28s)
TCP_time_re_max = 100 ; max retransmission (64s)
TCP_time_pers_min = 8 ; min persist (5,12s)
TCP_time_pers_max = 94 ; max persist (60,16s)
TCP_time_keep_init = 118 ; connection establishment (75,52s)
TCP_time_keep_idle = 4608 ; idle time before 1st probe (2h)
TCP_time_keep_interval = 118 ; between probes when no response (75,52s)
TCP_time_rtt_default = 5 ; default Round Trip Time (3,2s)
TCP_time_srtt_default = 0 ;
TCP_time_max_idle = 8*TCP_time_keep_interval ; FIXME
 
;*******************************************************************
; Interface
;
; tcp_tx_handler Handles the TCP transmit queue
; tcp_rx The protocol handler for received data
; buildTCPPacket fills in the packet headers and data
; tcpStateMachine Main state machine for received TCP packets
; tcp_tcb_handler 1s timer, to erase tcb's in TIME_WAIT state
;
;*******************************************************************
; timer constants
TCP_max_rxtshift = 12 ; max retransmissions waiting for ACK
TCP_max_keepcnt = 8 ; max keepalive probes
 
 
; TCP Payload ( Data field in IP datagram )
;
; 0 1 2 3
; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;20 | Source Port | Destination Port |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;24 | Sequence Number |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;28 | Acknowledgment Number |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;32 | Data | |U|A|P|R|S|F| |
; | Offset| Reserved |R|C|S|S|Y|I| Window |
; | | |G|K|H|T|N|N| |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;36 | Checksum | Urgent Pointer |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;40 | Options | Padding |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | data
TCP_max_winshift = 14
TCP_max_win = 65535
 
TCP_re_xmit_thresh = 3
 
struc TCP_PACKET
{ .SourcePort dw ? ;+00
.DestinationPort dw ? ;+02
.SequenceNumber dd ? ;+04
.AckNumber dd ? ;+08
.DataOffset db ? ;+12 - DataOffset[0-3 bits] and Reserved[4-7]
.Flags db ? ;+13 - Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
.Window dw ? ;+14
.Checksum dw ? ;+16
.UrgentPointer dw ? ;+18
.Options rb 3 ;+20
.Padding db ? ;+23
.Data db ? ;+24
}
TCP_mss_default = 1480 ; default max segment size
 
virtual at 0
TCP_PACKET TCP_PACKET
end virtual
; smoothed round trip time and estimated variance are stored as fixed point numbers,
; shifted by the value below.
; With these scales, srtt has 3 bits to the right of the binary point, and thus an "alpha"
; of .875. rttvar has 2 bits to the right and thus "alpha" of 0.75
TCP_RTT_SHIFT = 3
TCP_RTTVAR_SHIFT = 2
 
; bits used by tcp_input and tcp_output
TCP_BIT_NEEDOUTPUT = 1 shl 0
TCP_BIT_TIMESTAMP = 1 shl 1
TCP_BIT_DROPSOCKET = 1 shl 2
 
TCP_BIT_SENDALOT = 1 shl 0
 
;***************************************************************************
; Function
; tcp_tcb_handler
;
; Description
; Handles sockets in the timewait state, closing them
; when the TCB timer expires
;
;***************************************************************************
TCP_PAWS_IDLE = 24*24*60*60*100 ; 24 days, in 1/100 seconds
 
proc tcp_tcb_handler stdcall uses ebx
; scan through all the sockets, decrementing active timers
TCP_QUEUE_SIZE = 50
 
mov ebx, net_sockets
struct TCP_header
 
cmp [ebx + SOCKET.NextPtr], 0
je .exit
;DEBUGF 1, "K : sockets:\n"
SourcePort dw ?
DestinationPort dw ?
SequenceNumber dd ?
AckNumber dd ?
DataOffset db ? ; DataOffset[0-3 bits] and Reserved[4-7]
Flags db ? ; Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
Window dw ?
Checksum dw ?
UrgentPointer dw ?
 
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .exit
ends
 
;DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState]
struct TCP_queue_entry
 
cmp [ebx + SOCKET.TCBTimer], 0
jne .decrement_tcb
cmp [ebx + SOCKET.wndsizeTimer], 0
jne .decrement_wnd
jmp .next_socket
ip_ptr dd ?
segment_ptr dd ?
segment_size dd ?
device_ptr dd ?
 
.decrement_tcb:
; decrement it, delete socket if TCB timer = 0 & socket in timewait state
dec [ebx + SOCKET.TCBTimer]
jnz .next_socket
buffer_ptr dd ?
timestamp dd ?
 
cmp [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
jne .next_socket
ends
 
push [ebx + SOCKET.PrevPtr]
stdcall net_socket_free, ebx
pop ebx
jmp .next_socket
align 4
uglobal
TCP_segments_tx rd MAX_NET_DEVICES
TCP_segments_rx rd MAX_NET_DEVICES
TCP_segments_missed rd MAX_NET_DEVICES
TCP_segments_dumped rd MAX_NET_DEVICES
; TCP_bytes_rx rq MAX_NET_DEVICES
; TCP_bytes_tx rq MAX_NET_DEVICES
TCP_sequence_num dd ?
TCP_queue rd TCP_QUEUE_SIZE*sizeof.TCP_queue_entry/4
TCP_input_event dd ?
endg
 
.decrement_wnd:
; TODO - prove it works!
dec [ebx + SOCKET.wndsizeTimer]
jmp .next_socket
 
.exit:
ret
endp
 
 
;***************************************************************************
; Function
; tcp_tx_handler
;-----------------------------------------------------------------
;
; Description
; Handles queued TCP data
; This is a kernel function, called by stack_handler
; TCP_init
;
;***************************************************************************
; This function resets all TCP variables
;
;-----------------------------------------------------------------
macro TCP_init {
 
proc tcp_tx_handler stdcall
; decrement all resend buffers timers. If they
; expire, queue them for sending, and restart the timer.
; If the retries counter reach 0, delete the entry
xor eax, eax
mov edi, TCP_segments_tx
mov ecx, (6*MAX_NET_DEVICES)
rep stosd
 
mov esi, resendQ
mov ecx, 0
pseudo_random eax
mov [TCP_sequence_num], eax
 
.next_resendq:
cmp ecx, NUMRESENDENTRIES
je .exit ; None left
cmp dword[esi + 4], 0
jne @f ; found one
inc ecx
add esi, 8
jmp .next_resendq
init_queue TCP_queue
 
@@: ; we have one. decrement it's timer by 1
dec word[esi + 2]
jz @f
inc ecx
add esi, 8
jmp .next_resendq ; Timer not zero, so move on
 
@@:
xor ebx, ebx
; restart timer, and decrement retries
; After the first resend, back of on next, by a factor of 5
mov [esi + 2], word TCP_TIMEOUT * 5
dec byte[esi + 1]
jnz @f
 
; retries now 0, so delete from queue
xchg [esi + 4], ebx
 
@@: ; resend packet
pushad
 
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
jne .tth004z
 
; TODO - try again in 10ms.
test ebx, ebx
jnz @f
mov [esi + 4], ebx
 
@@: ; Mark it to expire in 10ms - 1 tick
mov byte[esi + 1], 1
mov word[esi + 2], 1
jmp .tth005
 
.tth004z:
; we have a buffer # in ax
push eax ecx
mov ecx, IPBUFFSIZE
mul ecx
add eax, IPbuffs
 
; we have the buffer address in eax
mov edi, eax
pop ecx
; Now get buffer location, and copy buffer across. argh! more copying,,
imul esi, ecx, IPBUFFSIZE
add esi, resendBuffer
 
; we have resend buffer location in esi
mov ecx, IPBUFFSIZE
 
; copy data across
push edi
cld
rep movsb
pop edi
 
; queue packet
mov eax, NET1OUT_QUEUE
mov edx, [stack_ip]
cmp edx, [edi + IP_PACKET.DestinationAddress]
jne .not_local
mov eax, IPIN_QUEUE
 
.not_local:
push 1
pop ebx
call queue
mov ecx, TCP_process_input
call new_sys_threads
 
.tth005:
popad
}
 
inc ecx
add esi, 8
jmp .next_resendq
 
.exit:
ret
endp
include 'tcp_timer.inc'
include 'tcp_subr.inc'
include 'tcp_usreq.inc'
include 'tcp_input.inc'
include 'tcp_output.inc'
 
 
;***************************************************************************
; Function
; tcp_rx
;---------------------------------------------------------------------------
;
; Description
; TCP protocol handler
; This is a kernel function, called by ip_rx
; IP buffer address given in edx
; IP buffer number in eax
; Free up (or re-use) IP buffer when finished
; TCP_API
;
;***************************************************************************
 
proc tcp_rx stdcall uses ebx
; The process is as follows.
; Look for a socket with matching remote IP, remote port, local port
; if not found, then
; look for remote IP + local port match ( where sockets remote port = 0)
; if not found, then
; look for a socket where local socket port == IP packets remote port
; where sockets remote port, remote IP = 0
; discard if not found
; Call sockets tcbStateMachine, with pointer to packet.
; the state machine will not delete the packet, so do that here.
 
push eax
 
; Look for a socket where
; IP Packet TCP Destination Port = local Port
; IP Packet SA = Remote IP
; IP Packet TCP Source Port = remote Port
 
mov ebx, net_sockets
 
.next_socket.1:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .next_socket.1.exit
 
; DEBUGF 1, "K : tcp_rx - 1.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4
 
mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr
cmp [ebx + SOCKET.LocalPort], ax ; get the dest. port from the TCP hdr
jne .next_socket.1 ; different - try next socket
 
; DEBUGF 1, "K : tcp_rx - 1.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP]
 
mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr
cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP
jne .next_socket.1 ; different - try next socket
 
; DEBUGF 1, "K : tcp_rx - 1.sport: %x - %x\n", [edx + 20 + TCP_PACKET.SourcePort]:4, [ebx + SOCKET.RemotePort]:4
 
mov ax, [edx + 20 + TCP_PACKET.SourcePort] ; get the source port from the TCP hdr
cmp [ebx + SOCKET.RemotePort], ax ; compare with socket's remote port
jne .next_socket.1 ; different - try next socket
 
; We have a complete match - use this socket
jmp .change_state
 
.next_socket.1.exit:
 
; If we got here, there was no match
; Look for a socket where
; IP Packet TCP Destination Port = local Port
; IP Packet SA = Remote IP
; socket remote Port = 0
 
mov ebx, net_sockets
 
.next_socket.2:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .next_socket.2.exit
 
; DEBUGF 1, "K : tcp_rx - 2.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4
 
mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr
cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port
jne .next_socket.2 ; different - try next socket
 
; DEBUGF 1, "K : tcp_rx - 2.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP]
 
mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr
cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP
jne .next_socket.2 ; different - try next socket
 
; DEBUGF 1, "K : tcp_rx - 2.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4
 
cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0
jne .next_socket.2 ; different - try next socket
 
; We have a complete match - use this socket
jmp .change_state
 
.next_socket.2.exit:
 
; If we got here, there was no match
; Look for a socket where
; IP Packet TCP Destination Port = local Port
; socket Remote IP = 0
; socket remote Port = 0
 
mov ebx, net_sockets
 
.next_socket.3:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .next_socket.3.exit
 
; DEBUGF 1, "K : tcp_rx - 3.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4
 
mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get destination port from the TCP hdr
cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port
jne .next_socket.3 ; different - try next socket
 
; DEBUGF 1, "K : tcp_rx - 3.addr: 00000000 - %x\n", [ebx + SOCKET.RemoteIP]
 
cmp [ebx + SOCKET.RemoteIP], 0 ; only match a socket remote IP of 0
jne .next_socket.3 ; different - try next socket
 
; DEBUGF 1, "K : tcp_rx - 3.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4
 
cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0
jne .next_socket.3 ; different - try next socket
 
; We have a complete match - use this socket
jmp .change_state
 
.next_socket.3.exit:
 
; If we got here, we need to reject the packet
 
DEBUGF 1, "K : tcp_rx - dumped\n"
DEBUGF 1, "K : --------: %x-%x-%x (flags: %x)\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [edx + IP_PACKET.SourceAddress], [edx + 20 + TCP_PACKET.SourcePort]:4, [edx + 20 + TCP_PACKET.Flags]:2
 
inc [dumped_rx_count]
jmp .exit
 
.change_state:
 
; We have a valid socket/TCB, so call the TCB State Machine for that skt.
; socket is pointed to by ebx
; IP packet is pointed to by edx
; IP buffer number is on stack ( it will be popped at the end)
 
stdcall tcpStateMachine, ebx
 
.exit:
pop eax
call freeBuff
ret
endp
 
 
;***************************************************************************
; Function
; buildTCPPacket
; This function is called by system function 76
;
; Description
; builds an IP Packet with TCP data fully populated for transmission
; You may destroy any and all registers
; TCP control flags specified in bl
; This TCB is in [sktAddr]
; User data pointed to by esi
; Data length in ecx
; Transmit buffer number in eax
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
;***************************************************************************
 
proc build_tcp_packet stdcall, sockAddr:DWORD
push ecx ; Save data length
 
; convert buffer pointer eax to the absolute address
mov ecx, IPBUFFSIZE
mul ecx
add eax, IPbuffs
 
mov edx, eax
 
mov [edx + 20 + TCP_PACKET.Flags], bl ; TCP flags
 
mov ebx, [sockAddr]
 
; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
 
; Fill in the IP header ( some data is in the socket descriptor)
mov eax, [ebx + SOCKET.LocalIP]
mov [edx + IP_PACKET.SourceAddress], eax
mov eax, [ebx + SOCKET.RemoteIP]
mov [edx + IP_PACKET.DestinationAddress], eax
 
mov [edx + IP_PACKET.VersionAndIHL], 0x45
mov [edx + IP_PACKET.TypeOfService], 0
 
pop eax ; Get the TCP data length
push eax
 
add eax, 20 + 20 ; add IP header and TCP header lengths
rol ax, 8
mov [edx + IP_PACKET.TotalLength], ax
mov [edx + IP_PACKET.Identification], 0
mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040
mov [edx + IP_PACKET.TimeToLive], 0x20
mov [edx + IP_PACKET.Protocol], PROTOCOL_TCP
 
; Checksum left unfilled
mov [edx + IP_PACKET.HeaderChecksum], 0
 
; Fill in the TCP header (some data is in the socket descriptor)
mov ax, [ebx + SOCKET.LocalPort]
mov [edx + 20 + TCP_PACKET.SourcePort], ax ; Local Port
 
mov ax, [ebx + SOCKET.RemotePort]
mov [edx + 20 + TCP_PACKET.DestinationPort], ax ; desitination Port
 
; Checksum left unfilled
mov [edx + 20 + TCP_PACKET.Checksum], 0
 
; sequence number
mov eax, [ebx + SOCKET.SND_NXT]
mov [edx + 20 + TCP_PACKET.SequenceNumber], eax
 
; ack number
mov eax, [ebx + SOCKET.RCV_NXT]
mov [edx + 20 + TCP_PACKET.AckNumber], eax
 
; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size)
; 768 bytes seems better
mov [edx + 20 + TCP_PACKET.Window], 0x0003
 
; Urgent pointer (0)
mov [edx + 20 + TCP_PACKET.UrgentPointer], 0
 
; data offset ( 0x50 )
mov [edx + 20 + TCP_PACKET.DataOffset], 0x50
 
pop ecx ; count of bytes to send
mov ebx, ecx ; need the length later
 
cmp ebx, 0
jz @f
 
mov edi, edx
add edi, 40
cld
rep movsb ; copy the data across
 
@@: ; we have edx as IPbuffer ptr.
; Fill in the TCP checksum
; First, fill in pseudoheader
mov eax, [edx + IP_PACKET.SourceAddress]
mov [pseudoHeader], eax
mov eax, [edx + IP_PACKET.DestinationAddress]
mov [pseudoHeader + 4], eax
mov word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0
add ebx, 20
mov [pseudoHeader + 10], bh
mov [pseudoHeader + 11], bl
 
mov eax, pseudoHeader
mov [checkAdd1], eax
mov word[checkSize1], 12
mov eax, edx
add eax, 20
mov [checkAdd2], eax
mov eax, ebx
mov [checkSize2], ax
 
call checksum
 
; store it in the TCP checksum ( in the correct order! )
mov ax, [checkResult]
rol ax, 8
mov [edx + 20 + TCP_PACKET.Checksum], ax
 
; Fill in the IP header checksum
GET_IHL eax, edx ; get IP-Header length
stdcall checksum_jb, edx, eax ; buf_ptr, buf_size
rol ax, 8
mov [edx + IP_PACKET.HeaderChecksum], ax
 
ret
endp
 
 
; Increments the 32 bit value pointed to by esi in internet order
proc inc_inet_esi stdcall
push eax
mov eax, [esi]
bswap eax
inc eax
bswap eax
mov [esi], eax
pop eax
ret
endp
 
 
; Increments the 32 bit value pointed to by esi in internet order
; by the value in ecx
proc add_inet_esi stdcall
push eax
mov eax, [esi]
bswap eax
add eax, ecx
bswap eax
mov [esi], eax
pop eax
ret
endp
 
 
iglobal
TCBStateHandler dd \
stateTCB_LISTEN, \
stateTCB_SYN_SENT, \
stateTCB_SYN_RECEIVED, \
stateTCB_ESTABLISHED, \
stateTCB_FIN_WAIT_1, \
stateTCB_FIN_WAIT_2, \
stateTCB_CLOSE_WAIT, \
stateTCB_CLOSING, \
stateTCB_LAST_ACK, \
stateTCB_TIME_WAIT, \
stateTCB_CLOSED
endg
 
 
;***************************************************************************
; Function
; tcpStateMachine
; OUT:
;
; Description
; TCP state machine
; This is a kernel function, called by tcp_rx
;
; IP buffer address given in edx
; Socket/TCB address in ebx
;
; The IP buffer will be released by the caller
;***************************************************************************
;---------------------------------------------------------------------------
align 4
TCP_api:
 
proc tcpStateMachine stdcall, sockAddr:DWORD
; as a packet has been received, update the TCB timer
mov [ebx + SOCKET.TCBTimer], TWOMSL
movzx eax, bh
shl eax, 2
 
; If the received packet has an ACK bit set,
; remove any packets in the resend queue that this
; received packet acknowledges
pushad
test [edx + 20 + TCP_PACKET.Flags], TH_ACK
jz .call_handler ; No ACK, so no data yet
test bl, bl
jz .packets_tx ; 0
dec bl
jz .packets_rx ; 1
dec bl
jz .packets_missed ; 2
dec bl
jz .packets_dumped ; 3
 
; get skt number in eax
stdcall net_socket_addr_to_num, ebx
 
; The ack number is in [edx + 28], inet format
; skt in eax
 
mov esi, resendQ
xor ecx, ecx
 
.next_resendq:
cmp ecx, NUMRESENDENTRIES
je .call_handler ; None left
cmp [esi + 4], eax
je @f ; found one
inc ecx
add esi, 8
jmp .next_resendq
 
@@: ; Can we delete this buffer?
 
; If yes, goto @@. No, goto .next_resendq
; Get packet data address
 
push ecx
; Now get buffer location, and copy buffer across. argh! more copying,,
imul edi, ecx, IPBUFFSIZE
add edi, resendBuffer
 
; we have dest buffer location in edi. incoming packet in edx.
; Get this packets sequence number
; preserve al, ecx, esi, edx
mov ecx, [edi + 20 + TCP_PACKET.SequenceNumber]
bswap ecx
movzx ebx, word[edi + 2]
xchg bl, bh
sub ebx, 40
add ecx, ebx ; ecx is now seq# of last byte +1, intel format
 
; get recievd ack #, in intel format
mov ebx, [edx + 20 + TCP_PACKET.AckNumber]
bswap ebx
 
cmp ebx, ecx ; Finally. ecx = rx'ed ack. ebx = last byte in que
; DANGER! need to handle case that we have just
; passed the 2**32, and wrapped round!
pop ecx
jae @f ; if rx > old, delete old
 
inc ecx
add esi, 8
jmp .next_resendq
 
@@:
mov dword[esi + 4], 0
inc ecx
add esi, 8
jmp .next_resendq
 
.call_handler:
popad
 
; Call handler for given TCB state
 
mov eax, [ebx + SOCKET.TCBState]
cmp eax, TCB_LISTEN
jb .exit
cmp eax, TCB_CLOSED
ja .exit
 
stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr]
 
.exit:
.error:
mov eax, -1
ret
endp
 
;***************************************************************************
; Function
; signal_network_event
;
; Description
; Signals about network event to socket owner
; This is a kernel function, called from TCP handler
;
; Socket/TCB address in ebx
;***************************************************************************
proc signal_network_event
push ecx esi eax
mov eax, [ebx + SOCKET.PID]
mov ecx, 1
mov esi, TASK_DATA + TASKDATA.pid
 
.next_pid:
cmp [esi], eax
je .found_pid
inc ecx
add esi, 0x20
cmp ecx, [TASK_COUNT]
jbe .next_pid
 
.found_pid:
shl ecx, 8
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event
pop eax esi ecx
.packets_tx:
mov eax, [TCP_segments_tx + eax]
ret
endp
 
proc stateTCB_LISTEN stdcall, sockAddr:DWORD
; In this case, we are expecting a SYN packet
; For now, if the packet is a SYN, process it, and send a response
; If not, ignore it
 
; Look at control flags
test [edx + 20 + TCP_PACKET.Flags], TH_SYN
jz .exit
 
; We have a SYN. update the socket with this IP packets details,
; And send a response
 
mov eax, [edx + IP_PACKET.SourceAddress]
mov [ebx + SOCKET.RemoteIP], eax
mov ax, [edx + 20 + TCP_PACKET.SourcePort]
mov [ebx + SOCKET.RemotePort], ax
mov eax, [edx + 20 + TCP_PACKET.SequenceNumber]
mov [ebx + SOCKET.IRS], eax
mov [ebx + SOCKET.RCV_NXT], eax
lea esi, [ebx + SOCKET.RCV_NXT]
call inc_inet_esi ; RCV.NXT
mov eax, [ebx + SOCKET.ISS]
mov [ebx + SOCKET.SND_NXT], eax
 
; Now construct the response, and queue for sending by IP
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je .exit
 
push ebx
push eax
mov bl, TH_SYN + TH_ACK
xor ecx, ecx
xor esi, esi
stdcall build_tcp_packet, [sockAddr]
 
mov eax, NET1OUT_QUEUE
mov edx, [stack_ip]
mov ecx, [sockAddr]
cmp edx, [ecx + SOCKET.RemoteIP]
jne .not_local
mov eax, IPIN_QUEUE
 
.not_local:
; Send it.
pop ebx
call queue
 
pop ebx
mov esi, [sockAddr]
mov [esi + SOCKET.TCBState], TCB_SYN_RECEIVED
call signal_network_event
 
; increment SND.NXT in socket
add esi, SOCKET.SND_NXT
call inc_inet_esi
 
.exit:
.packets_rx:
mov eax, [TCP_segments_rx + eax]
ret
endp
 
 
proc stateTCB_SYN_SENT stdcall, sockAddr:DWORD
; We are awaiting an ACK to our SYN, with a SYM
; Look at control flags - expecting an ACK
 
mov al, [edx + 20 + TCP_PACKET.Flags]
and al, TH_SYN + TH_ACK
cmp al, TH_SYN + TH_ACK
je .syn_ack
 
test al, TH_SYN
jz .exit
 
mov [ebx + SOCKET.TCBState], TCB_SYN_RECEIVED
push TH_SYN + TH_ACK
jmp .send
 
.syn_ack:
mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED
push TH_ACK
 
.send:
call signal_network_event
; Store the recv.nxt field
mov eax, [edx + 20 + TCP_PACKET.SequenceNumber]
 
; Update our recv.nxt field
mov [ebx + SOCKET.RCV_NXT], eax
lea esi, [ebx + SOCKET.RCV_NXT]
call inc_inet_esi
 
; Send an ACK
; Now construct the response, and queue for sending by IP
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
pop ebx
je .exit
 
push eax
 
xor ecx, ecx
xor esi, esi
stdcall build_tcp_packet, [sockAddr]
 
mov eax, NET1OUT_QUEUE
mov edx, [stack_ip]
mov ecx, [sockAddr]
cmp edx, [ecx + SOCKET.RemoteIP]
jne .not_local
mov eax, IPIN_QUEUE
 
.not_local:
; Send it.
pop ebx
call queue
 
.exit:
.packets_missed:
mov eax, [TCP_segments_missed + eax]
ret
endp
 
 
proc stateTCB_SYN_RECEIVED stdcall, sockAddr:DWORD
; In this case, we are expecting an ACK packet
; For now, if the packet is an ACK, process it,
; If not, ignore it
 
test [edx + 20 + TCP_PACKET.Flags], TH_RST
jz .check_ack
 
push [ebx + SOCKET.OrigRemotePort] [ebx + SOCKET.OrigRemoteIP]
pop [ebx + SOCKET.RemoteIP] [ebx + SOCKET.RemotePort]
 
mov [ebx + SOCKET.TCBState], TCB_LISTEN
jmp .signal
 
.check_ack:
; Look at control flags - expecting an ACK
test [edx + 20 + TCP_PACKET.Flags], TH_ACK
jz .exit
 
mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED
.signal:
call signal_network_event
 
.exit:
.packets_dumped:
mov eax, [TCP_segments_dumped + eax]
ret
endp
 
 
proc stateTCB_ESTABLISHED stdcall, sockAddr:DWORD
; Here we are expecting data, or a request to close
; OR both...
 
; Ignore all packets with sequnce number other than next expected
 
; recv.nxt is in dword [edx+24], in inet format
; recv seq is in [sktAddr]+56, in inet format
; just do a comparision
mov eax, [ebx + SOCKET.RCV_NXT]
cmp eax, [edx + 20 + TCP_PACKET.SequenceNumber]
jne .exit
 
; Did we receive a FIN or RST?
test [edx + 20 + TCP_PACKET.Flags], TH_FIN+TH_RST
jz .check_ack
 
; It was a fin or reset.
 
; Remove resend entries from the queue - I dont want to send any more data
pushad
 
; get skt #
stdcall net_socket_addr_to_num, ebx
 
mov esi, resendQ
mov ecx, 0
 
.next_resendq:
cmp ecx, NUMRESENDENTRIES
je .last_resendq ; None left
cmp [esi + 4], eax
je @f ; found one
inc ecx
add esi, 8
jmp .next_resendq
 
@@:
mov dword[esi + 4], 0
inc ecx
add esi, 8
jmp .next_resendq
 
.last_resendq:
popad
 
@@: ; Send an ACK to that fin, and enter closewait state
 
mov [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT
test [edx + 20 + TCP_PACKET.Flags], TH_RST
je @f
mov [ebx + SOCKET.TCBState], TCB_CLOSED
@@:
call signal_network_event
lea esi, [ebx + SOCKET.RCV_NXT]
mov eax, [esi] ; save original
call inc_inet_esi
;; jmp ste_ack - NO, there may be data
 
.check_ack:
; Check that we received an ACK
test [edx + 20 + TCP_PACKET.Flags], TH_ACK
jz .exit
 
; TODO - done, I think!
; First, look at the incoming window. If this is less than or equal to 1024,
; Set the socket window timer to 1. This will stop an additional packets being queued.
; ** I may need to tweak this value, since I do not know how many packets are already queued
mov cx, [edx + 20 + TCP_PACKET.Window]
xchg cl, ch
cmp cx, 1024
ja @f
 
mov [ebx + SOCKET.wndsizeTimer], 1
 
@@: ; OK, here is the deal
 
 
; Read the data bytes, store in socket buffer
movzx ecx, [edx + IP_PACKET.TotalLength]
xchg cl, ch
sub ecx, 40 ; Discard 40 bytes of header
ja .data ; Read data, if any
 
; If we had received a fin, we need to ACK it.
cmp [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT
je .ack
jmp .exit
 
.data:
push ecx
push ecx edx
lea ecx, [ebx+SOCKET.mutex]
call mutex_lock
pop edx ecx
 
push ebx
mov eax, [ebx + SOCKET.rxDataCount]
add eax, ecx
cmp eax, SOCKETBUFFSIZE - SOCKETHEADERSIZE
ja .overflow
 
mov [ebx + SOCKET.rxDataCount], eax ; increment the count of bytes in buffer
 
; point to the location to store the data
lea edi, [ebx + eax + SOCKETHEADERSIZE]
sub edi, ecx
 
add edx, 40 ; edx now points to the data
mov esi, edx
 
cld
rep movsb ; copy the data across
 
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
 
; flag an event to the application
pop ebx
call signal_network_event
 
pop ecx
 
; Update our recv.nxt field
lea esi, [ebx + SOCKET.RCV_NXT]
call add_inet_esi
 
.ack:
; Send an ACK
; Now construct the response, and queue for sending by IP
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je .exit
 
push eax
 
mov bl, TH_ACK
xor ecx, ecx
xor esi, esi
stdcall build_tcp_packet, [sockAddr]
 
mov eax, NET1OUT_QUEUE
 
mov edx, [stack_ip]
mov ecx, [sockAddr]
cmp edx, [ecx + SOCKET.RemoteIP]
jne .not_local
mov eax, IPIN_QUEUE
 
.not_local:
; Send it.
pop ebx
call queue
 
.exit:
ret
.overflow:
; no place in buffer
; so simply restore stack and exit
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
pop eax ecx
ret
endp
 
 
proc stateTCB_FIN_WAIT_1 stdcall, sockAddr:DWORD
; We can either receive an ACK of a fin, or a fin
mov al, [edx + 20 + TCP_PACKET.Flags]
and al, TH_FIN + TH_ACK
 
cmp al, TH_ACK
jne @f
 
; It was an ACK
mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_2
jmp .exit
 
@@:
mov [ebx + SOCKET.TCBState], TCB_CLOSING
cmp al, TH_FIN
je @f
mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
 
@@:
lea esi, [ebx + SOCKET.RCV_NXT]
call inc_inet_esi
 
; Send an ACK
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je .exit
 
push eax
 
mov bl, TH_ACK
xor ecx, ecx
xor esi, esi
stdcall build_tcp_packet, [sockAddr]
 
mov eax, NET1OUT_QUEUE
mov edx, [stack_ip]
mov ecx, [sockAddr]
cmp edx, [ecx + SOCKET.RemoteIP]
jne .not_local
mov eax, IPIN_QUEUE
 
.not_local:
; Send it.
pop ebx
call queue
 
.exit:
ret
endp
 
 
proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD
test [edx + 20 + TCP_PACKET.Flags], TH_FIN
jz .exit
 
; Change state, as we have a fin
mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
 
lea esi, [ebx + SOCKET.RCV_NXT]
call inc_inet_esi
 
; Send an ACK
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je .exit
 
push eax
 
mov bl, TH_ACK
xor ecx, ecx
xor esi, esi
stdcall build_tcp_packet, [sockAddr]
 
mov eax, NET1OUT_QUEUE
mov edx, [stack_ip]
mov ecx, [sockAddr]
cmp edx, [ecx + SOCKET.RemoteIP]
jne .not_local
mov eax, IPIN_QUEUE
 
.not_local:
; Send it.
pop ebx
call queue
 
.exit:
ret
endp
 
 
proc stateTCB_CLOSE_WAIT stdcall, sockAddr:DWORD
; Intentionally left empty
; socket_close_tcp handles this
ret
endp
 
 
proc stateTCB_CLOSING stdcall, sockAddr:DWORD
; We can either receive an ACK of a fin, or a fin
test [edx + 20 + TCP_PACKET.Flags], TH_ACK
jz .exit
 
mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
 
.exit:
ret
endp
 
 
proc stateTCB_LAST_ACK stdcall, sockAddr:DWORD
; Look at control flags - expecting an ACK
test [edx + 20 + TCP_PACKET.Flags], TH_ACK
jz .exit
 
; delete the socket
stdcall net_socket_free, ebx
 
.exit:
ret
endp
 
 
proc stateTCB_TIME_WAIT stdcall, sockAddr:DWORD
ret
endp
 
 
proc stateTCB_CLOSED stdcall, sockAddr:DWORD
ret
endp
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/trunk/network/tcp_input.inc
0,0 → 1,1663
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Based on the code of 4.4BSD ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 3407 $
 
;-----------------------------------------------------------------
;
; TCP_input:
;
; Add a segment to the incoming TCP queue
;
; IN: [esp] = ptr to buffer
; [esp+4] = buffer size (dont care)
; ebx = ptr to device struct
; ecx = segment size
; esi = ptr to TCP segment
; edi = ptr to ipv4 source address, followed by ipv4 dest address
;
; OUT: /
;
;-----------------------------------------------------------------
 
align 4
TCP_input:
 
; record the current time
mov eax, [timer_ticks] ; in 1/100 seconds
mov [esp + 4], eax
 
push ebx ecx esi edi ; mind the order
mov esi, esp
 
pushf
cli
add_to_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .fail
popf
 
add esp, sizeof.TCP_queue_entry
 
xor edx, edx
mov eax, [TCP_input_event]
mov ebx, [eax + EVENT.id]
xor esi, esi
call raise_event
 
ret
 
.fail:
popf
DEBUGF 2, "TCP incoming queue is full, discarding packet!\n"
 
inc [TCP_segments_missed] ; FIXME: use correct interface
 
add esp, sizeof.TCP_queue_entry - 8
call kernel_free
add esp, 4
 
ret
 
 
 
 
align 4
TCP_process_input:
 
xor esi, esi
mov ecx, MANUAL_DESTROY
call create_event
mov [TCP_input_event], eax
 
.wait:
mov eax, [TCP_input_event]
mov ebx, [eax + EVENT.id]
call wait_event
 
.loop:
get_from_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .wait
 
push [esi + TCP_queue_entry.timestamp]
push [esi + TCP_queue_entry.buffer_ptr]
 
mov ebx, [esi + TCP_queue_entry.device_ptr]
mov ecx, [esi + TCP_queue_entry.segment_size]
mov edi, [esi + TCP_queue_entry.ip_ptr] ; ptr to ipv4 source address, followed by ipv4 destination address
mov esi, [esi + TCP_queue_entry.segment_ptr] ; change esi last
 
DEBUGF 1,"TCP_input: size=%u time=%d\n", ecx, [timer_ticks]
 
mov edx, esi
 
cmp ebx, LOOPBACK_DEVICE
je .checksum_ok
 
; re-calculate the checksum (if not already done by hw)
; test [ebx + NET_DEVICE.hwacc], HWACC_TCP_IPv4_IN
; jnz .checksum_ok
 
push ecx esi
pushw [esi + TCP_header.Checksum]
mov [esi + TCP_header.Checksum], 0
TCP_checksum (edi), (edi+4)
pop cx ; previous checksum
cmp cx, dx
pop edx ecx
jne .drop_no_socket
.checksum_ok:
 
; Verify the data offset
and [edx + TCP_header.DataOffset], 0xf0 ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
shr [edx + TCP_header.DataOffset], 2
cmp [edx + TCP_header.DataOffset], sizeof.TCP_header ; Now see if it's at least the size of a standard TCP header
jb .drop_no_socket ; If not, drop the packet
 
movzx eax, [edx + TCP_header.DataOffset]
sub ecx, eax ; substract TCP header size from total segment size
jb .drop_no_socket ; If total segment size is less then the advertised header size, drop packet
DEBUGF 1,"TCP_input: %u bytes of data\n", ecx
 
;-------------------------------------------
; Convert Big-endian values to little endian
 
ntohd [edx + TCP_header.SequenceNumber]
ntohd [edx + TCP_header.AckNumber]
 
ntohw [edx + TCP_header.Window]
ntohw [edx + TCP_header.UrgentPointer]
 
;------------------------
; Find the socket pointer
 
; IP Packet TCP Destination Port = local Port
; (IP Packet SenderAddress = Remote IP) OR (Remote IP = 0)
; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0)
 
.findpcb:
mov ebx, net_sockets
mov si, [edx + TCP_header.DestinationPort]
 
.socket_loop:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .respond_seg_reset
 
cmp [ebx + SOCKET.Domain], AF_INET4
jne .socket_loop
 
cmp [ebx + SOCKET.Protocol], IP_PROTO_TCP
jne .socket_loop
 
cmp [ebx + TCP_SOCKET.LocalPort], si
jne .socket_loop
 
mov eax, [ebx + IP_SOCKET.RemoteIP]
cmp eax, [edi] ; Ipv4 source address
je @f
test eax, eax
jnz .socket_loop
@@:
 
mov ax, [ebx + TCP_SOCKET.RemotePort]
cmp [edx + TCP_header.SourcePort], ax
je .found_socket
test ax, ax
jnz .socket_loop
.found_socket: ; ebx now contains the socketpointer
DEBUGF 1,"TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2
 
;-------------
; update stats
 
inc [TCP_segments_rx] ; FIXME: correct interface?
 
;----------------------------
; Check if socket isnt closed
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
je .drop_no_socket
 
;----------------
; Lock the socket
 
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_lock
popa
 
DEBUGF 1,"TCP_input: socket locked\n"
 
;---------------------------
; disable all temporary bits
 
mov [ebx + TCP_SOCKET.temp_bits], 0
 
;---------------------------------------
; unscale the window into a 32 bit value
 
movzx eax, [edx + TCP_header.Window]
push ecx
mov cl, [ebx + TCP_SOCKET.SND_SCALE]
shl eax, cl
mov dword [edx + TCP_header.Window], eax ; word after window is checksum, we dont need checksum anymore
pop ecx
 
;---------------------------------------
; Are we accepting incoming connections?
 
test [ebx + SOCKET.options], SO_ACCEPTCON
jz .no_accept
 
DEBUGF 1,"TCP_input: Accepting new connection\n"
 
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
popa
 
push ecx edx esi edi ;;;
call SOCKET_fork
pop edi esi edx ecx
 
test eax, eax
jz .drop_no_socket
 
mov ebx, eax
 
mov [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET ;;; FIXME: should we take over bits from previous socket?
 
push dword [edi + 4] ; Ipv4 destination addres
pop [ebx + IP_SOCKET.LocalIP]
 
push [edx + TCP_header.DestinationPort]
pop [ebx + TCP_SOCKET.LocalPort]
 
mov [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
.no_accept:
 
 
;-------------------------------------
; Reset idle timer and keepalive timer
 
mov [ebx + TCP_SOCKET.t_idle], 0
mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_idle
 
;--------------------
; Process TCP options
 
push ecx
 
movzx ecx, [edx + TCP_header.DataOffset]
cmp ecx, sizeof.TCP_header ; Does header contain any options?
je .no_options
 
DEBUGF 1,"TCP_input: Segment has options\n"
 
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
;;; cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
;;; jz .not_uni_xfer ; also no header prediction
 
add ecx, edx
lea esi, [edx + sizeof.TCP_header]
 
.opt_loop:
cmp esi, ecx ; are we scanning outside of header?
jae .no_options
lodsb
cmp al, TCP_OPT_EOL ; end of option list?
je .no_options
cmp al, TCP_OPT_NOP
je .opt_loop
cmp al, TCP_OPT_MAXSEG
je .opt_maxseg
cmp al, TCP_OPT_WINDOW
je .opt_window
cmp al, TCP_OPT_SACK_PERMIT
je .opt_sack_permit
; cmp al, TCP_OPT_SACK
; je .opt_sack
cmp al, TCP_OPT_TIMESTAMP
je .opt_timestamp
DEBUGF 1,"TCP_input: unknown option:%u\n", al
jmp .no_options ; If we reach here, some unknown options were received, skip them all!
 
.opt_maxseg:
lodsb
cmp al, 4
jne .no_options ; error occured, ignore all options!
 
test [edx + TCP_header.Flags], TH_SYN
jz @f
 
lodsw
rol ax, 8
DEBUGF 1,"TCP_input: Maxseg=%u\n", ax
call TCP_mss
@@:
jmp .opt_loop
 
 
.opt_window:
lodsb
cmp al, 3
jne .no_options
 
test [edx + TCP_header.Flags], TH_SYN
jz @f
 
DEBUGF 1,"TCP_input: Got window scale option\n"
or [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
 
lodsb
mov [ebx + TCP_SOCKET.SND_SCALE], al
;;;;; TODO
 
@@:
jmp .opt_loop
 
 
.opt_sack_permit:
lodsb
cmp al, 2
jne .no_options
 
test [edx + TCP_header.Flags], TH_SYN
jz @f
 
DEBUGF 1,"TCP_input: Selective Acknowledgement permitted\n"
or [ebx + TCP_SOCKET.t_flags], TF_SACK_PERMIT
 
@@:
jmp .opt_loop
 
 
.opt_timestamp:
lodsb
cmp al, 10 ; length must be 10
jne .no_options
 
DEBUGF 1,"TCP_input: Got timestamp option\n"
 
test [edx + TCP_header.Flags], TH_SYN
jz @f
or [ebx + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
@@:
 
lodsd
mov [ebx + TCP_SOCKET.ts_val], eax
lodsd ; timestamp echo reply
mov [ebx + TCP_SOCKET.ts_ecr], eax
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
 
; Since we have a timestamp, lets do the paws test right away!
 
test [edx + TCP_header.Flags], TH_RST
jnz .no_paws
 
mov eax, [ebx + TCP_SOCKET.ts_recent]
test eax, eax
jz .no_paws
cmp eax, [ebx + TCP_SOCKET.ts_val]
jge .no_paws
 
DEBUGF 1,"TCP_input: PAWS: detected an old segment\n"
 
mov eax, [esp+4+4] ; tcp_now
sub eax, [ebx + TCP_SOCKET.ts_recent_age]
 
pop ecx
cmp eax, TCP_PAWS_IDLE
jle .drop_after_ack ; TODO: update stats
push ecx
 
mov [ebx + TCP_SOCKET.ts_recent], 0 ; timestamp was invalid, fix it.
.no_paws:
jmp .opt_loop
 
.no_options:
 
pop ecx
 
;-----------------------------------------------------------------------
; Time to do some header prediction (Original Principle by Van Jacobson)
 
; There are two common cases for an uni-directional data transfer.
;
; General rule: the packets has no control flags, is in-sequence,
; window width didnt change and we're not retransmitting.
;
; Second rules:
; - If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
; In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
;
; - If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
; If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
jnz .not_uni_xfer
 
test [edx + TCP_header.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
jnz .not_uni_xfer
 
test [edx + TCP_header.Flags], TH_ACK
jz .not_uni_xfer
 
mov eax, [edx + TCP_header.SequenceNumber]
cmp eax, [ebx + TCP_SOCKET.RCV_NXT]
jne .not_uni_xfer
 
mov eax, dword [edx + TCP_header.Window]
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jne .not_uni_xfer
 
mov eax, [ebx + TCP_SOCKET.SND_NXT]
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
jne .not_uni_xfer
 
;---------------------------------------
; check if we are sender in the uni-xfer
 
; If the following 4 conditions are all true, this segment is a pure ACK.
;
; - The segment contains no data.
test ecx, ecx
jnz .not_sender
 
; - The congestion window is greater than or equal to the current send window.
; This test is true only if the window is fully open, that is, the connection is not in the middle of slow start or congestion avoidance.
mov eax, [ebx + TCP_SOCKET.SND_CWND]
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jb .not_uni_xfer
 
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
ja .not_uni_xfer
 
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
sub eax, [ebx + TCP_SOCKET.SND_UNA]
jbe .not_uni_xfer
 
DEBUGF 1,"TCP_input: Header prediction: we are sender\n"
 
;---------------------------------
; Packet is a pure ACK, process it
 
; Delete acknowledged bytes from send buffer
pusha
mov ecx, eax
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_free
popa
 
; Update RTT estimators
 
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
jz .no_timestamp_rtt
mov eax, [esp + 4] ; timestamp when this segment was received
sub eax, [ebx + TCP_SOCKET.ts_ecr]
inc eax
call TCP_xmit_timer
jmp .rtt_done
 
.no_timestamp_rtt:
cmp [ebx + TCP_SOCKET.t_rtt], 0
je .rtt_done
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.t_rtseq]
jbe .rtt_done
mov eax, [ebx + TCP_SOCKET.t_rtt]
call TCP_xmit_timer
 
.rtt_done:
 
; update window pointers
mov eax, [edx + TCP_header.AckNumber]
mov [ebx + TCP_SOCKET.SND_UNA], eax
 
; Stop retransmit timer
mov [ebx + TCP_SOCKET.timer_retransmission], 0
 
; Unlock the socket
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
popa
 
; Awaken waiting processes
mov eax, ebx
call SOCKET_notify
 
; Generate more output
call TCP_output
 
jmp .drop_no_socket
 
;-------------------------------------------------
; maybe we are the receiver in the uni-xfer then..
 
.not_sender:
; - The amount of data in the segment is greater than 0 (data count is in ecx)
 
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_UNA]
jne .not_uni_xfer
 
; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
 
;;; TODO
 
; jnz .not_uni_xfer
 
; Complete processing of received data
 
DEBUGF 1,"TCP_input: Header prediction: we are receiving %u bytes\n", ecx
 
add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied
 
movzx esi, [edx + TCP_header.DataOffset]
add esi, edx
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_write ; Add the data to the socket buffer
 
mov eax, ebx
call SOCKET_notify
 
or [ebx + TCP_SOCKET.t_flags], TF_DELACK ; Set delayed ack flag
 
jmp .drop
 
;--------------------------------------------------
; Header prediction failed, do it the slow way
 
.not_uni_xfer:
 
DEBUGF 1,"TCP_input: Header prediction failed\n"
 
; Calculate receive window size
 
push edx
mov eax, SOCKETBUFFSIZE
sub eax, [ebx + STREAM_SOCKET.rcv.size]
mov edx, [ebx + TCP_SOCKET.RCV_ADV]
sub edx, [ebx + TCP_SOCKET.RCV_NXT]
cmp eax, edx
jg @f
mov eax, edx
@@:
DEBUGF 1,"Receive window size=%d\n", eax
mov [ebx + TCP_SOCKET.RCV_WND], eax
pop edx
 
; If we are in listen or syn_sent state, go to that specific code right away
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
je .LISTEN
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT
je .SYN_SENT
 
;----------------------------
; trim any data not in window
 
; check for duplicate data at beginning of segment (635)
 
mov eax, [ebx + TCP_SOCKET.RCV_NXT]
sub eax, [edx + TCP_header.SequenceNumber]
jle .no_duplicate
 
DEBUGF 1,"TCP_input: %u bytes duplicate data!\n", eax
 
test [edx + TCP_header.Flags], TH_SYN
jz .no_dup_syn
 
DEBUGF 1,"TCP_input: got duplicate syn\n"
 
and [edx + TCP_header.Flags], not (TH_SYN)
inc [edx + TCP_header.SequenceNumber]
 
cmp [edx + TCP_header.UrgentPointer], 1
jbe @f
dec [edx + TCP_header.UrgentPointer]
jmp .dup_syn
@@:
and [edx + TCP_header.Flags], not (TH_URG)
.dup_syn:
dec eax
.no_dup_syn:
 
; Check for entire duplicate segment (646)
cmp eax, ecx ; eax holds number of bytes to drop, ecx is data size
jb .duplicate
jnz @f
test [edx + TCP_header.Flags], TH_FIN
jnz .duplicate
@@:
 
; Any valid FIN must be to the left of the window.
; At this point the FIN must be out of sequence or a duplicate, drop it
and [edx + TCP_header.Flags], not TH_FIN
 
; send an ACK and resynchronize and drop any data.
; But keep on processing for RST or ACK
DEBUGF 1, "616\n"
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
mov eax, ecx
;TODO: update stats
 
;-----------------------------------------------
; Remove duplicate data and update urgent offset
 
.duplicate:
;;; TODO: 677
add [edx + TCP_header.SequenceNumber], eax
sub ecx, eax
 
sub [edx + TCP_header.UrgentPointer], ax
jg @f
and [edx + TCP_header.Flags], not (TH_URG)
mov [edx + TCP_header.UrgentPointer], 0
@@:
 
;--------------------------------------------------
; Handle data that arrives after process terminates (687)
 
.no_duplicate:
cmp [ebx + SOCKET.PID], 0
jne .not_terminated
cmp [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
jbe .not_terminated
test ecx, ecx
jz .not_terminated
 
mov eax, ebx
call TCP_close
;;;TODO: update stats
jmp .respond_seg_reset
 
;----------------------------------------
; Remove data beyond right edge of window (700-736)
 
.not_terminated:
mov eax, [edx + TCP_header.SequenceNumber]
add eax, ecx
sub eax, [ebx + TCP_SOCKET.RCV_NXT]
sub eax, [ebx + TCP_SOCKET.RCV_WND] ; eax now holds the number of bytes to drop
jle .no_excess_data
 
DEBUGF 1,"%d bytes beyond right edge of window\n", eax
 
;;; TODO: update stats
cmp eax, ecx
jl .dont_drop_all
; If a new connection request is received while in TIME_WAIT, drop the old connection and start over,
; if the sequence numbers are above the previous ones
 
test [edx + TCP_header.Flags], TH_SYN
jz .no_new_request
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
jne .no_new_request
; mov edx, [ebx + TCP_SOCKET.RCV_NXT]
; cmp edx, [edx + TCP_header.SequenceNumber]
; add edx, 64000 ; TCP_ISSINCR FIXME
mov eax, ebx
call TCP_close
jmp .findpcb ; FIXME: skip code for unscaling window, ...
.no_new_request:
 
; If window is closed can only take segments at window edge, and have to drop data and PUSH from
; incoming segments. Continue processing, but remember to ACK. Otherwise drop segment and ACK
 
cmp [ebx + TCP_SOCKET.RCV_WND], 0
jne .drop_after_ack
mov eax, [edx + TCP_header.SequenceNumber]
cmp eax, [ebx + TCP_SOCKET.RCV_NXT]
jne .drop_after_ack
 
DEBUGF 1, "690\n"
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
;;; TODO: update stats
jmp .no_excess_data
.dont_drop_all:
;;; TODO: update stats
;;; TODO: 733
 
sub ecx, eax
and [ebx + TCP_SOCKET.t_flags], not (TH_PUSH or TH_FIN)
.no_excess_data:
 
;-----------------
; Record timestamp (737-746)
 
; If last ACK falls within this segments sequence numbers, record its timestamp
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
jz .no_timestamp
mov eax, [ebx + TCP_SOCKET.last_ack_sent]
sub eax, [edx + TCP_header.SequenceNumber]
jb .no_timestamp
test [ebx + TCP_header.Flags], TH_SYN or TH_FIN ; syn and fin occupy one byte
jz @f
dec eax
@@:
sub eax, ecx
jae .no_timestamp
 
DEBUGF 1,"Recording timestamp\n"
 
mov eax, [esp + 4] ; tcp_now
mov [ebx + TCP_SOCKET.ts_recent_age], eax
mov eax, [ebx + TCP_SOCKET.ts_val]
mov [ebx + TCP_SOCKET.ts_recent], eax
.no_timestamp:
 
;------------------
; Process RST flags
 
test [edx + TCP_header.Flags], TH_RST
jz .no_rst
 
DEBUGF 1,"TCP_input: Got an RST flag\n"
 
mov eax, [ebx + TCP_SOCKET.t_state]
shl eax, 2
jmp dword [eax + .rst_sw_list]
 
.rst_sw_list:
dd .no_rst ; TCPS_CLOSED
dd .no_rst ; TCPS_LISTEN
dd .no_rst ; TCPS_SYN_SENT
dd .econnrefused ; TCPS_SYN_RECEIVED
dd .econnreset ; TCPS_ESTABLISHED
dd .econnreset ; TCPS_CLOSE_WAIT
dd .econnreset ; TCPS_FIN_WAIT_1
dd .rst_close ; TCPS_CLOSING
dd .rst_close ; TCPS_LAST_ACK
dd .econnreset ; TCPS_FIN_WAIT_2
dd .rst_close ; TCPS_TIMED_WAIT
 
.econnrefused:
DEBUGF 1,"TCP_input: Connection refused\n"
 
mov [ebx + SOCKET.errorcode], ECONNREFUSED
jmp .close
 
.econnreset:
DEBUGF 1,"TCP_input: Connection reset\n"
 
mov [ebx + SOCKET.errorcode], ECONNRESET
 
.close:
DEBUGF 1,"TCP_input: Closing connection\n"
 
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
;;; TODO: update stats (tcp drops)
mov eax, ebx
call TCP_close
jmp .drop_no_socket
 
.rst_close:
DEBUGF 1,"TCP_input: Closing with reset\n"
 
mov eax, ebx
call TCP_close
jmp .drop_no_socket
 
.no_rst:
 
;--------------------------------------
; handle SYN-full and ACK-less segments
 
test [edx + TCP_header.Flags], TH_SYN
jz .not_syn_full
 
mov eax, ebx
mov ebx, ECONNRESET
call TCP_drop
jmp .drop_with_reset
.not_syn_full:
 
;---------------
; ACK processing
 
test [edx + TCP_header.Flags], TH_ACK
jz .drop
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
jb .ack_processed ; states: closed, listen, syn_sent
ja .no_syn_rcv ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait
 
DEBUGF 1,"TCP_input: state=syn_received\n"
 
mov eax, [edx + TCP_header.AckNumber]
cmp [ebx + TCP_SOCKET.SND_UNA], eax
ja .drop_with_reset
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
ja .drop_with_reset
 
;;; TODO: update stats
 
mov eax, ebx
call SOCKET_is_connected
mov [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
 
; Do window scaling?
 
test [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
jz @f
test [ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
jz @f
 
push word [ebx + TCP_SOCKET.requested_s_scale] ; Set send and receive scale factors to the received values
pop word [ebx + TCP_SOCKET.SND_SCALE]
@@:
 
;;; TODO: call TCP_reassemble
 
mov eax, [edx + TCP_header.SequenceNumber]
dec eax
mov [ebx + TCP_SOCKET.SND_WL1], eax
 
.no_syn_rcv:
 
;-------------------------
; check for duplicate ACKs
 
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_UNA]
ja .not_dup_ack
 
test ecx, ecx
jnz .reset_dupacks
 
mov eax, dword [edx + TCP_header.Window]
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jne .reset_dupacks
 
DEBUGF 1,"TCP_input: Processing duplicate ACK\n"
 
; If we have outstanding data, other than a window probe, this is a completely duplicate ACK
; (window info didnt change) The ACK is the biggest we've seen and we've seen exactly our rexmt threshold of them,
; assume a packet has been dropped and retransmit it. Kludge snd_nxt & the congestion window so we send only this one packet.
 
cmp [ebx + TCP_SOCKET.timer_retransmission], 0 ;;;; FIXME
jg @f
 
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_UNA]
je .dup_ack
 
@@:
mov [ebx + TCP_SOCKET.t_dupacks], 0
jmp .not_dup_ack
 
.dup_ack:
inc [ebx + TCP_SOCKET.t_dupacks]
cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
jne .no_re_xmit
 
push [ebx + TCP_SOCKET.SND_NXT] ; >>>>
 
mov eax, [ebx + TCP_SOCKET.SND_WND]
cmp eax, [ebx + TCP_SOCKET.SND_CWND]
cmova eax, [ebx + TCP_SOCKET.SND_CWND]
shr eax, 1
push edx
xor edx, edx
div [ebx + TCP_SOCKET.t_maxseg]
cmp eax, 2
ja @f
xor eax, eax
mov al, 2
@@:
mul [ebx + TCP_SOCKET.t_maxseg]
pop edx
mov [ebx + TCP_SOCKET.SND_SSTHRESH], eax
 
mov [ebx + TCP_SOCKET.timer_retransmission], 0 ; turn off retransmission timer
mov [ebx + TCP_SOCKET.t_rtt], 0
mov eax, [edx + TCP_header.AckNumber]
mov [ebx + TCP_SOCKET.SND_NXT], eax
mov eax, [ebx + TCP_SOCKET.t_maxseg]
mov [ebx + TCP_SOCKET.SND_CWND], eax
 
; Unlock the socket
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
 
; retransmit missing segment
mov eax, [esp]
call TCP_output
 
; Lock the socket again
mov ecx, [esp]
add ecx, SOCKET.mutex
call mutex_lock
pop ebx
 
; Continue processing
xor edx, edx
mov eax, [ebx + TCP_SOCKET.t_maxseg]
mul [ebx + TCP_SOCKET.t_dupacks]
add eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
mov [ebx + TCP_SOCKET.SND_CWND], eax
 
pop eax ; <<<<
cmp eax, [ebx + TCP_SOCKET.SND_NXT]
jb @f
mov [ebx + TCP_SOCKET.SND_NXT], eax
@@:
 
jmp .drop
 
 
.no_re_xmit:
jbe .not_dup_ack
 
DEBUGF 1,"TCP_input: Increasing congestion window\n"
 
mov eax, [ebx + TCP_SOCKET.t_maxseg]
add [ebx + TCP_SOCKET.SND_CWND], eax
 
; Unlock the socket
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
 
; retransmit missing segment
mov eax, [esp]
call TCP_output
 
; Lock the socket again
mov ecx, [esp]
add ecx, SOCKET.mutex
call mutex_lock
pop ebx
 
jmp .drop
 
 
.not_dup_ack:
 
;-------------------------------------------------
; If the congestion window was inflated to account
; for the other side's cached packets, retract it
 
mov eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
cmp eax, [ebx + TCP_SOCKET.SND_CWND]
ja @f
cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
jbe @f
mov [ebx + TCP_SOCKET.SND_CWND], eax
@@:
 
mov [ebx + TCP_SOCKET.t_dupacks], 0
 
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
jbe @f
 
;;; TODO: update stats
jmp .drop_after_ack
 
@@:
 
mov edi, [edx + TCP_header.AckNumber]
sub edi, [ebx + TCP_SOCKET.SND_UNA] ; now we got the number of acked bytes in edi
 
;;; TODO: update stats
 
DEBUGF 1,"TCP_input: acceptable ACK for %u bytes\n", edi
 
;------------------------------------------
; RTT measurements and retransmission timer (912-926)
 
; If we have a timestamp, update smoothed RTT
 
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
jz .timestamp_not_present
mov eax, [esp+4]
sub eax, [ebx + TCP_SOCKET.ts_ecr]
inc eax
call TCP_xmit_timer
jmp .rtt_done_
 
; If no timestamp but transmit timer is running and timed sequence number was acked,
; update smoothed RTT. Since we now have an RTT measurement, cancel the timer backoff
; (Phil Karn's retransmit algo)
; Recompute the initial retransmit timer
 
.timestamp_not_present:
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.t_rtseq]
jbe .rtt_done_
mov eax, [ebx + TCP_SOCKET.t_rtt]
test eax, eax
jz .rtt_done_
call TCP_xmit_timer
 
.rtt_done_:
 
; If all outstanding data is acked, stop retransmit timer and remember to restart (more output or persist)
; If there is more data to be acked, restart retransmit timer, using current (possible backed-off) value.
 
mov eax, [ebx + TCP_SOCKET.SND_MAX]
cmp eax, [edx + TCP_header.AckNumber]
jne .more_data
mov [ebx + TCP_SOCKET.timer_retransmission], 0
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
jmp .no_restart
.more_data:
cmp [ebx + TCP_SOCKET.timer_persist], 0
jne .no_restart
 
mov eax, [ebx + TCP_SOCKET.t_rxtcur]
mov [ebx + TCP_SOCKET.timer_retransmission], eax
 
.no_restart:
 
 
;-------------------------------------------
; Open congestion window in response to ACKs
 
mov esi, [ebx + TCP_SOCKET.SND_CWND]
mov eax, [ebx + TCP_SOCKET.t_maxseg]
 
cmp esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
jbe @f
push edx
push eax
mul eax
div esi
pop edx
shr edx, 3
add eax, edx
pop edx
@@:
 
add esi, eax
 
push ecx
mov cl, [ebx + TCP_SOCKET.SND_SCALE]
mov eax, TCP_max_win
shl eax, cl
pop ecx
 
cmp esi, eax
cmova esi, eax
mov [ebx + TCP_SOCKET.SND_CWND], esi
 
;------------------------------------------
; Remove acknowledged data from send buffer
 
cmp edi, [ebx + STREAM_SOCKET.snd.size]
jbe .finiacked
 
push ecx edx ebx
mov ecx, [ebx + STREAM_SOCKET.snd.size]
lea eax, [ebx + STREAM_SOCKET.snd]
sub [ebx + TCP_SOCKET.SND_WND], ecx
call SOCKET_ring_free
pop ebx edx ecx
 
DEBUGF 1,"TCP_input: our FIN is acked\n"
stc
 
jmp .wakeup
 
.finiacked:
 
push ecx edx ebx
mov ecx, edi
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_free
pop ebx
sub [ebx + TCP_SOCKET.SND_WND], ecx
pop edx ecx
 
DEBUGF 1,"TCP_input: our FIN is not acked\n"
clc
 
;----------------------------------------
; Wake up process waiting on send buffer
 
.wakeup:
 
pushf ; Keep the flags (Carry flag)
mov eax, ebx
call SOCKET_notify
 
; Update TCPS
 
mov eax, [edx + TCP_header.AckNumber]
mov [ebx + TCP_SOCKET.SND_UNA], eax
cmp eax, [ebx + TCP_SOCKET.SND_NXT]
jb @f
mov [ebx + TCP_SOCKET.SND_NXT], eax
@@:
 
popf
 
; General ACK handling complete
; Now do the state-specific ones
; Carry flag is set when our FIN is acked
 
mov eax, [ebx + TCP_SOCKET.t_state]
jmp dword [eax*4 + .ACK_sw_list]
 
.ACK_sw_list:
dd .ack_processed ; TCPS_CLOSED
dd .ack_processed ; TCPS_LISTEN
dd .ack_processed ; TCPS_SYN_SENT
dd .ack_processed ; TCPS_SYN_RECEIVED
dd .ack_processed ; TCPS_ESTABLISHED
dd .ack_processed ; TCPS_CLOSE_WAIT
dd .ack_fw1 ; TCPS_FIN_WAIT_1
dd .ack_c ; TCPS_CLOSING
dd .ack_la ; TCPS_LAST_ACK
dd .ack_processed ; TCPS_FIN_WAIT_2
dd .ack_tw ; TCPS_TIMED_WAIT
 
 
.ack_fw1:
jnc .ack_processed
 
test [ebx + SOCKET.state], SS_CANTRCVMORE
jnz @f
mov eax, ebx
call SOCKET_is_disconnected
mov [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle
@@:
mov [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
jmp .ack_processed
 
.ack_c:
jnc .ack_processed
 
mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
mov eax, ebx
call TCP_cancel_timers
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
mov eax, ebx
call SOCKET_is_disconnected
jmp .ack_processed
 
.ack_la:
jnc .ack_processed
 
mov eax, ebx
call TCP_disconnect
jmp .drop
 
.ack_tw:
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
jmp .drop_after_ack
 
.reset_dupacks: ; We got a new ACK, reset duplicate ACK counter
mov [ebx + TCP_SOCKET.t_dupacks], 0
jmp .ack_processed
 
;-------
; LISTEN
 
align 4
.LISTEN:
 
DEBUGF 1,"TCP_input: state=listen\n"
 
test [edx + TCP_header.Flags], TH_RST
jnz .drop
 
test [edx + TCP_header.Flags], TH_ACK
jnz .drop_with_reset
 
test [edx + TCP_header.Flags], TH_SYN
jz .drop
 
;;; TODO: check if it's a broadcast or multicast, and drop if so
 
push dword [edi] ; Ipv4 source addres
pop [ebx + IP_SOCKET.RemoteIP]
 
push [edx + TCP_header.SourcePort]
pop [ebx + TCP_SOCKET.RemotePort]
 
push [edx + TCP_header.SequenceNumber]
pop [ebx + TCP_SOCKET.IRS]
 
mov eax, [TCP_sequence_num]
add [TCP_sequence_num], 64000 / 2
mov [ebx + TCP_SOCKET.ISS], eax
mov [ebx + TCP_SOCKET.SND_NXT], eax
 
TCP_sendseqinit ebx
TCP_rcvseqinit ebx
 
mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
mov [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval ;;;; macro
 
lea eax, [ebx + STREAM_SOCKET.snd]
call SOCKET_ring_create
 
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_create
 
and [ebx + TCP_SOCKET.temp_bits], not TCP_BIT_DROPSOCKET
 
;;; call SOCKET_notify_owner
 
jmp .trim_then_step6
 
;------------
; Active Open
 
align 4
.SYN_SENT:
 
DEBUGF 1,"TCP_input: state=syn_sent\n"
 
test [edx + TCP_header.Flags], TH_ACK
jz @f
 
mov eax, [edx + TCP_header.AckNumber]
cmp eax, [ebx + TCP_SOCKET.ISS]
jbe .drop_with_reset
 
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
ja .drop_with_reset
@@:
 
test [edx + TCP_header.Flags], TH_RST
jz @f
 
test [edx + TCP_header.Flags], TH_ACK
jz .drop
 
mov eax, ebx
mov ebx, ECONNREFUSED
call TCP_drop
 
jmp .drop
@@:
 
test [edx + TCP_header.Flags], TH_SYN
jz .drop
 
; at this point, segment seems to be valid
 
test [edx + TCP_header.Flags], TH_ACK
jz .no_syn_ack
 
; now, process received SYN in response to an active open
 
mov eax, [edx + TCP_header.AckNumber]
mov [ebx + TCP_SOCKET.SND_UNA], eax
cmp eax, [ebx + TCP_SOCKET.SND_NXT]
jbe @f
mov [ebx + TCP_SOCKET.SND_NXT], eax
@@:
 
.no_syn_ack:
mov [ebx + TCP_SOCKET.timer_retransmission], 0 ; disable retransmission
 
push [edx + TCP_header.SequenceNumber]
pop [ebx + TCP_SOCKET.IRS]
 
TCP_rcvseqinit ebx
 
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
 
mov eax, [ebx + TCP_SOCKET.SND_UNA]
cmp eax, [ebx + TCP_SOCKET.ISS]
jbe .simultaneous_open
 
test [edx + TCP_header.Flags], TH_ACK
jz .simultaneous_open
 
DEBUGF 1,"TCP_input: active open\n"
 
;;; TODO: update stats
 
; set socket state to connected
mov [ebx + SOCKET.state], SS_ISCONNECTED
mov [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
 
; Do window scaling on this connection ?
mov eax, [ebx + TCP_SOCKET.t_flags]
and eax, TF_REQ_SCALE or TF_RCVD_SCALE
cmp eax, TF_REQ_SCALE or TF_RCVD_SCALE
jne .no_scaling
 
mov ax, word [ebx + TCP_SOCKET.requested_s_scale]
mov word [ebx + TCP_SOCKET.SND_SCALE], ax
.no_scaling:
 
;;; TODO: reassemble packets queue
 
mov eax, [ebx + TCP_SOCKET.t_rtt]
test eax, eax
je .trim_then_step6
call TCP_xmit_timer
jmp .trim_then_step6
 
.simultaneous_open:
 
DEBUGF 1,"TCP_input: simultaneous open\n"
; We have received a syn but no ACK, so we are having a simultaneous open..
mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
 
;-------------------------------------
; Common processing for receipt of SYN
 
.trim_then_step6:
 
inc [edx + TCP_header.SequenceNumber]
 
;;; TODO: Drop any received data that follows receive window (590)
 
mov eax, [edx + TCP_header.SequenceNumber]
mov [ebx + TCP_SOCKET.RCV_UP], eax
dec eax
mov [ebx + TCP_SOCKET.SND_WL1], eax
 
;-------
; step 6
 
.ack_processed:
 
DEBUGF 1,"TCP_input: ACK processed\n"
 
;----------------------------------------------
; check if we need to update window information
 
test [edx + TCP_header.Flags], TH_ACK
jz .no_window_update
 
mov eax, [ebx + TCP_SOCKET.SND_WL1]
cmp eax, [edx + TCP_header.SequenceNumber]
jb .update_window
ja @f
 
mov eax, [ebx + TCP_SOCKET.SND_WL2]
cmp eax, [edx + TCP_header.AckNumber]
jb .update_window
ja .no_window_update
@@:
 
mov eax, dword [edx + TCP_header.Window]
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jbe .no_window_update
 
.update_window:
 
;;; TODO: update stats (Keep track of pure window updates)
 
mov eax, dword [edx + TCP_header.Window]
cmp eax, [ebx + TCP_SOCKET.max_sndwnd]
jbe @f
mov [ebx + TCP_SOCKET.max_sndwnd], eax
@@:
mov [ebx + TCP_SOCKET.SND_WND], eax
 
DEBUGF 1,"TCP_input: Updating window to %u\n", eax
 
push [edx + TCP_header.SequenceNumber]
pop [ebx + TCP_SOCKET.SND_WL1]
 
push [edx + TCP_header.AckNumber]
pop [ebx + TCP_SOCKET.SND_WL2]
 
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
 
.no_window_update:
 
;-----------------
; process URG flag
 
test [edx + TCP_header.Flags], TH_URG
jz .not_urgent
 
cmp [edx + TCP_header.UrgentPointer], 0
jz .not_urgent
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
je .not_urgent
 
; Ignore bogus urgent offsets
 
movzx eax, [edx + TCP_header.UrgentPointer]
add eax, [ebx + STREAM_SOCKET.rcv.size]
cmp eax, SOCKET_MAXDATA
jbe .not_urgent
 
mov [edx + TCP_header.UrgentPointer], 0
and [edx + TCP_header.Flags], not (TH_URG)
jmp .do_data
 
.not_urgent:
 
; processing of received urgent pointer
 
;;; TODO (1051-1093)
 
 
;---------------------------------------
; process the data in the segment (1094)
 
.do_data:
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
jae .final_processing
 
test [edx + TCP_header.Flags], TH_FIN
jnz @f
 
test ecx, ecx
jnz .final_processing
@@:
 
 
; The segment is in order?
mov eax, [edx + TCP_header.SequenceNumber]
cmp eax, [ebx + TCP_SOCKET.RCV_NXT]
jne .out_of_order
 
; The reassembly queue is empty?
cmp [ebx + TCP_SOCKET.seg_next], 0
jne .out_of_order
 
; The connection is established?
cmp [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
jne .out_of_order
 
; Ok, lets do this.. Set delayed ACK flag and copy data into socket buffer
or [ebx + TCP_SOCKET.t_flags], TF_DELACK
 
pusha
movzx esi, [edx + TCP_header.DataOffset]
add esi, edx
lea eax, [ebx + STREAM_SOCKET.rcv]
call SOCKET_ring_write ; Add the data to the socket buffer
add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied
popa
 
; Wake up the sleeping process
mov eax, ebx
call SOCKET_notify
 
jmp .data_done
 
.out_of_order:
 
; Uh-oh, some data is out of order, lets call TCP reassemble for help
 
call TCP_reassemble
 
DEBUGF 1, "1470\n"
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
 
.data_done:
 
;---------------
; FIN processing
 
test [edx + TCP_header.Flags], TH_FIN
jz .final_processing
 
DEBUGF 1,"TCP_input: Processing FIN\n"
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
jae .not_first_fin
 
DEBUGF 1,"TCP_input: First FIN for this connection\n"
 
mov eax, ebx
call SOCKET_cant_recv_more
 
mov [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
inc [ebx + TCP_SOCKET.RCV_NXT]
 
.not_first_fin:
mov eax, [ebx + TCP_SOCKET.t_state]
shl eax, 2
jmp dword [eax + .FIN_sw_list]
 
.FIN_sw_list:
dd .final_processing ; TCPS_CLOSED
dd .final_processing ; TCPS_LISTEN
dd .final_processing ; TCPS_SYN_SENT
dd .fin_syn_est ; TCPS_SYN_RECEIVED
dd .fin_syn_est ; TCPS_ESTABLISHED
dd .final_processing ; TCPS_CLOSE_WAIT
dd .fin_wait1 ; TCPS_FIN_WAIT_1
dd .final_processing ; TCPS_CLOSING
dd .final_processing ; TCPS_LAST_ACK
dd .fin_wait2 ; TCPS_FIN_WAIT_2
dd .fin_timed ; TCPS_TIMED_WAIT
 
.fin_syn_est:
 
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
jmp .final_processing
 
.fin_wait1:
 
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
jmp .final_processing
 
.fin_wait2:
 
mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
mov eax, ebx
call TCP_cancel_timers
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
call SOCKET_is_disconnected
jmp .final_processing
 
.fin_timed:
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
jmp .final_processing
 
 
.drop_after_ack:
DEBUGF 1,"TCP_input: Drop after ACK\n"
 
push edx ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
pop eax edx
 
test [edx + TCP_header.Flags], TH_RST
jnz .dumpit
 
or [eax + TCP_SOCKET.t_flags], TF_ACKNOW
jmp .need_output
 
.drop_with_reset:
DEBUGF 1,"TCP_input: Drop with reset\n"
 
push ebx edx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
pop edx ebx
 
test [edx + TCP_header.Flags], TH_RST
jnz .dumpit
 
;;; if its a multicast/broadcast, also drop
 
test [edx + TCP_header.Flags], TH_ACK
jnz .respond_ack
 
test [edx + TCP_header.Flags], TH_SYN
jnz .respond_syn
jmp .dumpit
 
;-----------------
; Final processing
 
.final_processing:
DEBUGF 1,"TCP_input: Final processing\n"
 
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
pop eax
 
test [eax + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
jnz .need_output
 
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW
jz .dumpit
DEBUGF 1,"TCP_input: ACK now!\n"
 
.need_output:
DEBUGF 1,"TCP_input: need output\n"
call TCP_output
 
.dumpit:
DEBUGF 1,"TCP_input: dumping\n"
 
call kernel_free
add esp, 4
jmp .loop
 
;---------
; Respond
 
.respond_ack:
push ebx
mov cl, TH_RST
call TCP_respond
pop ebx
jmp .destroy_new_socket
 
.respond_syn:
push ebx
mov cl, TH_RST + TH_ACK
call TCP_respond
pop ebx
jmp .destroy_new_socket
 
.respond_seg_reset:
test [edx + TCP_header.Flags], TH_RST
jnz .drop_no_socket
 
;;; TODO: if its a multicast/broadcast, also drop
 
test [edx + TCP_header.Flags], TH_ACK
jnz .respond_seg_ack
 
test [edx + TCP_header.Flags], TH_SYN
jnz .respond_seg_syn
 
jmp .drop_no_socket
 
.respond_seg_ack:
mov cl, TH_RST
call TCP_respond_segment
jmp .drop_no_socket
 
.respond_seg_syn:
mov cl, TH_RST + TH_ACK
call TCP_respond_segment
jmp .drop_no_socket
 
;-----
; Drop
 
.drop:
DEBUGF 1,"TCP_input: Dropping segment\n"
 
pusha
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
popa
 
.destroy_new_socket:
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET
jz .drop_no_socket
 
mov eax, ebx
call SOCKET_free
 
.drop_no_socket:
DEBUGF 1,"TCP_input: Drop (no socket)\n"
 
call kernel_free
add esp, 4
jmp .loop
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/trunk/network/tcp_output.inc
0,0 → 1,621
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Based on the code of 4.4BSD ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 3289 $
 
;-----------------------------------------------------------------
;
; TCP_output
;
; IN: eax = socket pointer
;
; OUT: /
;
;-----------------------------------------------------------------
align 4
TCP_output:
 
DEBUGF 1,"TCP_output: socket=%x\n", eax
 
push eax
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
pop eax
 
; We'll detect the length of the data to be transmitted, and flags to be used
; If there is some data, or any critical controls to send (SYN / RST), then transmit
; Otherwise, investigate further
 
mov ebx, [eax + TCP_SOCKET.SND_MAX]
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
jbe .not_idle
 
mov ebx, [eax + TCP_SOCKET.t_idle]
cmp ebx, [eax + TCP_SOCKET.t_rxtcur]
jbe .not_idle
 
; We have been idle for a while and no ACKS are expected to clock out any data we send..
; Slow start to get ack "clock" running again.
 
mov ebx, [eax + TCP_SOCKET.t_maxseg]
mov [eax + TCP_SOCKET.SND_CWND], ebx
 
.not_idle:
.again:
mov [eax + TCP_SOCKET.temp_bits], 0
 
mov ebx, [eax + TCP_SOCKET.SND_NXT] ; calculate offset (71)
sub ebx, [eax + TCP_SOCKET.SND_UNA] ;
 
mov ecx, [eax + TCP_SOCKET.SND_WND] ; determine window
cmp ecx, [eax + TCP_SOCKET.SND_CWND] ;
jb @f ;
mov ecx, [eax + TCP_SOCKET.SND_CWND] ;
@@: ;
 
call TCP_outflags ; flags in dl
 
;------------------------
; data being forced out ?
 
; If in persist timeout with window of 0, send 1 byte.
; Otherwise, if window is small but nonzero, and timer expired,
; we will send what we can and go to transmit state
 
cmp [eax + TCP_SOCKET.t_force], 0
je .no_force
 
DEBUGF 1,"TCP_output: forcing data out\n"
 
test ecx, ecx
jnz .no_zero_window
 
cmp ebx, [eax + STREAM_SOCKET.snd.size]
jae @f
 
and dl, not (TH_FIN)
 
@@:
inc ecx
jmp .no_force
 
.no_zero_window:
mov [eax + TCP_SOCKET.timer_persist], 0
mov [eax + TCP_SOCKET.t_rxtshift], 0
 
.no_force:
 
;--------------------------------
; Calculate how much data to send (106)
 
mov esi, [eax + STREAM_SOCKET.snd.size]
cmp esi, ecx
jb @f
mov esi, ecx
@@:
sub esi, ebx
 
 
;------------------------
; check for window shrink (107)
 
; If FIN has been set, but not ACKed, but we havent been called to retransmit, esi will be -1
; Otherwise, window shrank after we sent into it.
 
jae .not_persist
 
; enter persist state
xor esi, esi
 
; If window shrank to 0
test ecx, ecx
jnz @f
 
; cancel pending retransmit
mov [eax + TCP_SOCKET.timer_retransmission], 0
 
; pull SND_NXT back to (closed) window, We will enter persist state below.
push [eax + TCP_SOCKET.SND_UNA]
pop [eax + TCP_SOCKET.SND_NXT]
@@:
 
; If window didn't close completely, just wait for an ACK
 
.not_persist:
 
;---------------------------
; Send one segment at a time (124)
 
cmp esi, [eax + TCP_SOCKET.t_maxseg]
jbe @f
 
mov esi, [eax + TCP_SOCKET.t_maxseg]
or [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT
@@:
 
;--------------------------------------------
; Turn of FIN flag if send buffer not emptied (128)
 
mov edi, [eax + TCP_SOCKET.SND_NXT]
add edi, esi
sub edi, [eax + TCP_SOCKET.SND_UNA]
cmp edi, [eax + STREAM_SOCKET.snd.size]
jae @f
and dl, not (TH_FIN)
 
@@:
 
;-------------------------------
; calculate window advertisement (130)
 
mov ecx, SOCKET_MAXDATA
sub ecx, [eax + STREAM_SOCKET.rcv.size]
 
;------------------------------
; Sender silly window avoidance (131)
 
test esi, esi
jz .len_zero
 
cmp esi, [eax + TCP_SOCKET.t_maxseg]
je TCP_send
 
add ebx, esi ; offset + length
cmp ebx, [eax + STREAM_SOCKET.snd.size]
jb @f
 
test [eax + TCP_SOCKET.t_flags], TF_NODELAY
jnz TCP_send
 
mov ebx, [eax + TCP_SOCKET.SND_MAX]
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
je TCP_send
@@:
 
test [eax + TCP_SOCKET.t_force], -1 ;;;
jnz TCP_send
 
mov ebx, [eax + TCP_SOCKET.max_sndwnd]
shr ebx, 1
cmp esi, ebx
jae TCP_send
 
mov ebx, [eax + TCP_SOCKET.SND_NXT]
cmp ebx, [eax + TCP_SOCKET.SND_MAX]
jb TCP_send
 
.len_zero:
 
;----------------------------------------
; Check if a window update should be sent (154)
 
DEBUGF 1,"TCP_output: window=%d\n", ecx
 
; Compare available window to amount of window known to peer (as advertised window less next expected input)
; If the difference is at least two max size segments, or at least 50% of the maximum possible window,
; Then we want to send a window update to the peer.
 
test ecx, ecx
jz .no_window
 
push ecx
mov cl, [eax + TCP_SOCKET.RCV_SCALE]
mov ebx, TCP_max_win
shl ebx, cl
pop ecx
cmp ebx, ecx
jb @f
mov ebx, ecx
@@:
sub ebx, [eax + TCP_SOCKET.RCV_ADV]
add ebx, [eax + TCP_SOCKET.RCV_NXT]
 
mov edi, [eax + TCP_SOCKET.t_maxseg]
shl edi, 1
 
; cmp ebx, edi
; jae TCP_send
 
; cmp ebx, [eax + TCP_SOCKET.] ;;; TODO: check with receive buffer high water mark
; jae TCP_send
 
.no_window:
 
;--------------------------
; Should a segment be sent? (174)
 
DEBUGF 1,"TCP_output: 174\n"
 
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW ; we need to ACK
jnz TCP_send
 
test dl, TH_SYN + TH_RST ; we need to send a SYN or RST
jnz TCP_send
 
mov ebx, [eax + TCP_SOCKET.SND_UP] ; when urgent pointer is beyond start of send bufer
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
ja TCP_send
 
test dl, TH_FIN
jz .enter_persist ; no reason to send, enter persist state
 
; FIN was set, only send if not already sent, or on retransmit
 
test [eax + TCP_SOCKET.t_flags], TF_SENTFIN
jz TCP_send
 
mov ebx, [eax + TCP_SOCKET.SND_NXT]
cmp ebx, [eax + TCP_SOCKET.SND_UNA]
je TCP_send
 
;--------------------
; Enter persist state (191)
 
.enter_persist:
 
cmp [eax + STREAM_SOCKET.snd.size], 0 ; Data ready to send?
jne @f
cmp [eax + TCP_SOCKET.timer_retransmission], 0
jne @f
cmp [eax + TCP_SOCKET.timer_persist], 0 ; Persist timer already expired?
jne @f
 
DEBUGF 1,"TCP_output: Entering persist state\n"
 
mov [eax + TCP_SOCKET.t_rxtshift], 0
call TCP_set_persist
@@:
 
;----------------------------
; No reason to send a segment (219)
 
DEBUGF 1,"TCP_output: No reason to send a segment\n"
 
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
popa
 
; Fixme: returnvalue?
 
ret
 
 
 
 
 
 
 
 
 
;-----------------------------------------------
;
; Send a segment (222)
;
; eax = socket pointer
; esi = data len
; dl = flags
;
;-----------------------------------------------
align 4
TCP_send:
 
DEBUGF 1,"TCP_send: socket=%x length=%u flags=%x\n", eax, esi, dl
 
push eax ; save socket ptr
push esi ; and data length too
mov edi, sizeof.TCP_header ; edi will contain headersize
 
;------------------------------------
; Send options with first SYN segment
 
test dl, TH_SYN
jz .options_done
 
push [eax + TCP_SOCKET.ISS]
pop [eax + TCP_SOCKET.SND_NXT]
 
test [eax + TCP_SOCKET.t_flags], TF_NOOPT
jnz .options_done
 
mov ecx, 1460 ;;;; FIXME: use routing blablabla to determine MSS
or ecx, TCP_OPT_MAXSEG shl 24 + 4 shl 16
bswap ecx
push ecx
add di, 4
 
DEBUGF 1,"TCP_send: added maxseg option\n"
 
test [eax + TCP_SOCKET.t_flags], TF_REQ_SCALE
jz .no_scale
 
test dl, TH_ACK
jz .scale_opt
 
test [eax + TCP_SOCKET.t_flags], TF_RCVD_SCALE
jz .no_scale
 
.scale_opt:
mov cl, [eax + TCP_SOCKET.request_r_scale]
mov ch, TCP_OPT_NOP
pushw cx
pushw TCP_OPT_WINDOW + 3 shl 8
add di, 4
 
DEBUGF 1,"TCP_send: added scale option\n"
 
.no_scale:
.no_syn:
 
;------------------------------------
; Make the timestamp option if needed
 
test [eax + TCP_SOCKET.t_flags], TF_REQ_TSTMP
jz .no_timestamp
 
test dl, TH_RST
jnz .no_timestamp
 
test dl, TH_ACK
jz .timestamp
 
test [eax + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
jz .no_timestamp
 
.timestamp:
pushd 0
pushd [timer_ticks]
pushd TCP_OPT_NOP + TCP_OPT_NOP shl 8 + TCP_OPT_TIMESTAMP shl 16 + 10 shl 24
add di, 12
 
DEBUGF 1,"TCP_send: added timestamp\n"
 
.no_timestamp:
 
; <Add additional options here>
 
.options_done:
 
; eax = socket ptr
; edx = flags
; edi = header size
; esi = data len
 
;---------------------------------------------
; check if we dont exceed the max segment size (270)
 
add esi, edi ; total TCP segment size
cmp esi, [eax + TCP_SOCKET.t_maxseg]
jbe .no_overflow
 
mov esi, [eax + TCP_SOCKET.t_maxseg]
or [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT
.no_overflow:
 
;-----------------------------------------------------------------
; Start by pushing all TCP header values in reverse order on stack
; (essentially, creating the tcp header on the stack!)
 
pushw 0 ; .UrgentPointer dw ?
pushw 0 ; .Checksum dw ?
pushw 0x00a0 ; .Window dw ? ;;;;;;; FIXME (370)
shl edi, 2 ; .DataOffset db ? only 4 left-most bits
shl dx, 8
or dx, di ; .Flags db ?
pushw dx
shr edi, 2 ; .DataOffset db ?
 
push [eax + TCP_SOCKET.RCV_NXT] ; .AckNumber dd ?
ntohd [esp]
 
push [eax + TCP_SOCKET.SND_NXT] ; .SequenceNumber dd ?
ntohd [esp]
 
push [eax + TCP_SOCKET.RemotePort] ; .DestinationPort dw ?
push [eax + TCP_SOCKET.LocalPort] ; .SourcePort dw ?
 
push edi ; header size
 
;---------------------
; Create the IP packet
 
mov ecx, esi
 
mov ebx, [eax + SOCKET.device]
mov edx, [eax + IP_SOCKET.LocalIP] ; source ip
mov eax, [eax + IP_SOCKET.RemoteIP] ; dest ip
mov di, IP_PROTO_TCP shl 8 + 128
call IPv4_output
jz .ip_error
 
;-----------------------------------------
; Move TCP header from stack to TCP packet
 
push ecx
mov ecx, [esp + 4]
lea esi, [esp + 8]
shr ecx, 2 ; count is in bytes, we will work with dwords
rep movsd
pop ecx ; full TCP packet size
 
pop esi ; headersize
add esp, esi ; remove it from stack
 
push edx ; packet size for send proc
push eax ; packet ptr for send proc
 
mov edx, edi ; begin of data
sub edx, esi ; begin of packet (edi = begin of data)
push ecx
sub ecx, esi ; data size
 
;--------------
; Copy the data
 
; eax = ptr to ring struct
; ecx = buffer size
; edi = ptr to buffer
 
mov eax, [esp + 16] ; get socket ptr
 
push edx
push [eax + TCP_SOCKET.SND_NXT] ; we'll need this for timing the transmission
test ecx, ecx
jz .nodata
mov edx, [eax + TCP_SOCKET.SND_NXT]
add [eax + TCP_SOCKET.SND_NXT], ecx ; update sequence number <<< CHECKME
sub edx, [eax + TCP_SOCKET.SND_UNA] ; offset
add eax, STREAM_SOCKET.snd
call SOCKET_ring_read
.nodata:
pop edi
pop esi ; begin of data
pop ecx ; full packet size
mov eax, [esp + 12] ; socket ptr
 
;----------------------------------
; initialize retransmit timer (400)
 
;TODO: check t_force and persist
 
test [esi + TCP_header.Flags], TH_SYN + TH_FIN ; syn and fin take a sequence number
jz @f
inc [eax + TCP_SOCKET.SND_NXT]
test [esi + TCP_header.Flags], TH_FIN
jz @f
or [eax + TCP_SOCKET.t_flags], TF_SENTFIN ; if we sent a fin, set the sentfin flag
@@:
 
mov edx, [eax + TCP_SOCKET.SND_NXT]
cmp edx, [eax + TCP_SOCKET.SND_MAX] ; is this a retransmission?
jbe @f
mov [eax + TCP_SOCKET.SND_MAX], edx ; [eax + TCP_SOCKET.SND_NXT] from before we updated it
 
cmp [eax + TCP_SOCKET.t_rtt], 0 ; are we currently timing anything?
je @f
mov [eax + TCP_SOCKET.t_rtt], 1 ; nope, start transmission timer
mov [eax + TCP_SOCKET.t_rtseq], edi
;TODO: update stats
@@:
 
; set retransmission timer if not already set, and not doing an ACK or keepalive probe
 
cmp [eax + TCP_SOCKET.timer_retransmission], 0 ;;;; FIXME
ja .retransmit_set
 
cmp edx, [eax + TCP_SOCKET.SND_UNA] ; edx is still [eax + TCP_SOCKET.SND_NXT]
je .retransmit_set
 
mov edx, [eax + TCP_SOCKET.t_rxtcur]
mov [eax + TCP_SOCKET.timer_retransmission], edx
 
cmp [eax + TCP_SOCKET.timer_persist], 0
jne .retransmit_set
mov [eax + TCP_SOCKET.timer_persist], 0
mov [eax + TCP_SOCKET.t_rxtshift], 0
 
.retransmit_set:
 
;--------------------
; Create the checksum
 
TCP_checksum (eax + IP_SOCKET.LocalIP), (eax + IP_SOCKET.RemoteIP)
mov [esi + TCP_header.Checksum], dx
 
;----------------
; Send the packet
 
DEBUGF 1,"TCP_send: Sending with device %x\n", ebx
call [ebx + NET_DEVICE.transmit]
jnz .send_error
 
;---------------
; Ok, data sent!
 
pop ecx
pop eax
 
inc [TCP_segments_tx] ; FIXME: correct interface?
 
; update advertised receive window
test ecx, ecx
jz @f
add ecx, [eax + TCP_SOCKET.RCV_NXT]
cmp ecx, [eax + TCP_SOCKET.RCV_ADV]
jbe @f
mov [eax + TCP_SOCKET.RCV_ADV], ecx
@@:
 
; update last ack sent
push [eax + TCP_SOCKET.RCV_NXT]
pop [eax + TCP_SOCKET.last_ack_sent]
 
; and flags
and [eax + TCP_SOCKET.t_flags], not (TF_ACKNOW + TF_DELACK)
 
;--------------
; unlock socket
 
push eax
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
pop eax
 
;-----------------------------
; Check if we need more output
 
test [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT
jnz TCP_output.again
 
DEBUGF 1,"TCP_send: success!\n"
 
xor eax, eax
ret
 
 
.ip_error:
pop ecx
add esp, ecx
add esp, 4
pop eax
 
mov [eax + TCP_SOCKET.timer_retransmission], TCP_time_re_min
 
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
 
DEBUGF 1,"TCP_send: IP error\n"
 
or eax, -1
ret
 
 
.send_error:
add esp, 8
 
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
 
DEBUGF 1,"TCP_send: sending failed\n"
 
or eax, -2
ret
 
 
 
 
 
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/trunk/network/tcp_subr.inc
0,0 → 1,546
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Based on the code of 4.4BSD ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 3514 $
 
align 4
iglobal
TCP_backoff db 0,1,2,3,4,5,6,6,6,6,6,6,6
endg
 
macro TCP_checksum IP1, IP2 {
 
;-------------
; Pseudoheader
 
; protocol type
mov edx, IP_PROTO_TCP
 
; source address
add dl, byte [IP1+1]
adc dh, byte [IP1+0]
adc dl, byte [IP1+3]
adc dh, byte [IP1+2]
 
; destination address
adc dl, byte [IP2+1]
adc dh, byte [IP2+0]
adc dl, byte [IP2+3]
adc dh, byte [IP2+2]
 
; size
adc dl, cl
adc dh, ch
 
adc edx, 0
 
;---------------------
; Real header and data
 
push esi
call checksum_1
call checksum_2
pop esi
 
} ; returns in dx only
 
 
 
 
macro TCP_sendseqinit ptr {
 
push edi ;;;; i dont like this static use of edi
mov edi, [ptr + TCP_SOCKET.ISS]
mov [ptr + TCP_SOCKET.SND_UP], edi
mov [ptr + TCP_SOCKET.SND_MAX], edi
mov [ptr + TCP_SOCKET.SND_NXT], edi
mov [ptr + TCP_SOCKET.SND_UNA], edi
pop edi
 
}
 
 
 
macro TCP_rcvseqinit ptr {
 
push edi
mov edi, [ptr + TCP_SOCKET.IRS]
inc edi
mov [ptr + TCP_SOCKET.RCV_NXT], edi
mov [ptr + TCP_SOCKET.RCV_ADV], edi
pop edi
 
}
 
 
 
macro TCP_init_socket socket {
 
mov [socket + TCP_SOCKET.t_maxseg], TCP_mss_default
mov [socket + TCP_SOCKET.t_flags], TF_REQ_SCALE or TF_REQ_TSTMP
 
mov [socket + TCP_SOCKET.t_srtt], TCP_time_srtt_default
mov [socket + TCP_SOCKET.t_rttvar], TCP_time_rtt_default * 4
mov [socket + TCP_SOCKET.t_rttmin], TCP_time_re_min
;;; TODO: TCP_time_rangeset
 
mov [socket + TCP_SOCKET.SND_CWND], TCP_max_win shl TCP_max_winshift
mov [socket + TCP_SOCKET.SND_SSTHRESH], TCP_max_win shl TCP_max_winshift
 
 
}
 
 
;---------------------------
;
; TCP_pull_out_of_band
;
; IN: eax =
; ebx = socket ptr
; edx = tcp packet ptr
;
; OUT: /
;
;---------------------------
 
align 4
TCP_pull_out_of_band:
 
DEBUGF 1,"TCP_pull_out_of_band\n"
 
;;;; 1282-1305
 
ret
 
 
 
 
 
 
 
 
;-------------------------
;
; TCP_drop
;
; IN: eax = socket ptr
; ebx = error number
;
; OUT: eax = socket ptr
;
;-------------------------
align 4
TCP_drop:
 
DEBUGF 1,"TCP_drop: %x\n", eax
 
cmp [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
jb .no_syn_received
 
mov [eax + TCP_SOCKET.t_state], TCPS_CLOSED
 
call TCP_output
 
;;; TODO: update stats
 
jmp TCP_close
 
.no_syn_received:
 
;;; TODO: update stats
 
;;; TODO: check if error code is "Connection timed out' and handle accordingly
 
mov [eax + SOCKET.errorcode], ebx
 
 
 
 
 
 
 
 
;-------------------------
;
; TCP_close
;
; IN: eax = socket ptr
; OUT: eax = socket ptr
;
;-------------------------
align 4
TCP_close:
 
DEBUGF 1,"TCP_close: %x\n", eax
 
;;; TODO: update RTT and mean deviation
;;; TODO: update slow start threshold
 
call SOCKET_is_disconnected
call SOCKET_free
 
ret
 
 
 
 
;-------------------------
;
; TCP_outflags
;
; IN: eax = socket ptr
;
; OUT: edx = flags
;
;-------------------------
align 4
TCP_outflags:
 
mov edx, [eax + TCP_SOCKET.t_state]
movzx edx, byte [edx + .flaglist]
 
DEBUGF 1,"TCP_outflags: socket=%x flags=%x\n", eax, dl
 
ret
 
.flaglist:
 
db TH_RST + TH_ACK ; TCPS_CLOSED
db 0 ; TCPS_LISTEN
db TH_SYN ; TCPS_SYN_SENT
db TH_SYN + TH_ACK ; TCPS_SYN_RECEIVED
db TH_ACK ; TCPS_ESTABLISHED
db TH_ACK ; TCPS_CLOSE_WAIT
db TH_FIN + TH_ACK ; TCPS_FIN_WAIT_1
db TH_FIN + TH_ACK ; TCPS_CLOSING
db TH_FIN + TH_ACK ; TCPS_LAST_ACK
db TH_ACK ; TCPS_FIN_WAIT_2
db TH_ACK ; TCPS_TIMED_WAIT
 
 
 
 
 
 
;---------------------------------------
;
; The fast way to send an ACK/RST/keepalive segment
;
; TCP_respond
;
; IN: ebx = socket ptr
; cl = flags
;
;--------------------------------------
align 4
TCP_respond:
 
DEBUGF 1,"TCP_respond_socket: socket=%x flags=%x\n", ebx, cl
 
;---------------------
; Create the IP packet
 
push cx ebx
mov eax, [ebx + IP_SOCKET.RemoteIP]
mov edx, [ebx + IP_SOCKET.LocalIP]
mov ecx, sizeof.TCP_header
mov di, IP_PROTO_TCP shl 8 + 128
call IPv4_output
test edi, edi
jz .error
pop esi cx
push edx eax
 
;-----------------------------------------------
; Fill in the TCP header by using the socket ptr
 
mov ax, [esi + TCP_SOCKET.LocalPort]
stosw
mov ax, [esi + TCP_SOCKET.RemotePort]
stosw
mov eax, [esi + TCP_SOCKET.SND_NXT]
bswap eax
stosd
mov eax, [esi + TCP_SOCKET.RCV_NXT]
bswap eax
stosd
mov al, 0x50 ; Dataoffset: 20 bytes (TCP_header.DataOffset)
stosb
mov al, cl
stosb
; mov ax, [esi + TCP_SOCKET.RCV_WND]
; rol ax, 8
mov ax, 0x00a0 ;;;;;;; FIXME
stosw ; window
xor eax, eax
stosd ; checksum + urgentpointer
 
;---------------------
; Fill in the checksum
 
.checksum:
sub edi, sizeof.TCP_header
mov ecx, sizeof.TCP_header
xchg esi, edi
TCP_checksum (edi + IP_SOCKET.LocalIP), (edi + IP_SOCKET.RemoteIP)
mov [esi+TCP_header.Checksum], dx
 
;--------------------
; And send the segment
 
call [ebx + NET_DEVICE.transmit]
ret
 
.error:
DEBUGF 1,"TCP_respond_socket: failed\n"
add esp, 2 + 4
 
ret
 
 
 
 
 
 
 
 
;-------------------------
; TCP_respond_segment:
;
; IN: edx = segment ptr (a previously received segment)
; edi = ptr to dest and src IPv4 addresses
; cl = flags
 
align 4
TCP_respond_segment:
 
DEBUGF 1,"TCP_respond_segment: frame=%x flags=%x\n", edx, cl
 
;---------------------
; Create the IP packet
 
push cx edx
mov ebx, [edi + 4]
mov eax, [edi]
mov ecx, sizeof.TCP_header
mov di, IP_PROTO_TCP shl 8 + 128
call IPv4_output
jz .error
pop esi cx
 
push edx eax
 
;---------------------------------------------------
; Fill in the TCP header by using a received segment
 
mov ax, [esi + TCP_header.DestinationPort]
stosw
mov ax, [esi + TCP_header.SourcePort]
stosw
mov eax, [esi + TCP_header.AckNumber]
bswap eax
stosd
xor eax, eax
stosd
mov al, 0x50 ; Dataoffset: 20 bytes (sizeof.TCP_header/4 shl 4)
stosb
mov al, cl
stosb
mov ax, 1280
rol ax, 8
stosw ; window
xor eax, eax
stosd ; checksum + urgentpointer
 
;---------------------
; Fill in the checksum
 
lea esi, [edi - sizeof.TCP_header]
mov ecx, sizeof.TCP_header
TCP_checksum (esi - sizeof.IPv4_header + IPv4_header.DestinationAddress),\ ; FIXME
(esi - sizeof.IPv4_header + IPv4_header.SourceAddress)
mov [esi + TCP_header.Checksum], dx
 
;--------------------
; And send the segment
 
call [ebx + NET_DEVICE.transmit]
ret
 
.error:
DEBUGF 1,"TCP_respond_segment: failed\n"
add esp, 2+4
 
ret
 
 
macro TCPT_RANGESET timer, value, min, max {
 
local .min
local .max
local .done
 
cmp value, min
jb .min
cmp value, max
ja .max
 
mov timer, value
jmp .done
 
.min:
mov timer, value
jmp .done
 
.max:
mov timer, value
jmp .done
 
.done:
}
 
 
align 4
TCP_set_persist:
 
DEBUGF 1,"TCP_set_persist\n"
 
; First, check if retransmit timer is not set, retransmit and persist are mutually exclusive
 
cmp [eax + TCP_SOCKET.timer_retransmission], 0
ja @f
 
; calculate RTO
push ebx
mov ebx, [eax + TCP_SOCKET.t_srtt]
shr ebx, 2
add ebx, [eax + TCP_SOCKET.t_rttvar]
shr ebx, 1
 
mov cl, [eax + TCP_SOCKET.t_rxtshift]
shl ebx, cl
 
; Start/restart persistance timer.
 
TCPT_RANGESET [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max
 
pop ebx
 
cmp [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift
jae @f
inc [eax + TCP_SOCKET.t_rxtshift]
@@:
 
ret
 
 
 
; eax = rtt
; ebx = socket ptr
 
align 4
TCP_xmit_timer:
 
DEBUGF 1,"TCP_xmit_timer: socket=%x rtt=%d0ms\n", ebx, eax
 
;TODO: update stats
 
cmp [ebx + TCP_SOCKET.t_rtt], 0
je .no_rtt_yet
 
; srtt is stored as a fixed point with 3 bits after the binary point.
; The following magic is equivalent of the smoothing algorithm in rfc793 with an alpha of .875
; (srtt = rtt/8 + srtt*7/8 in fixed point)
; Adjust rtt to origin 0.
 
push ecx
mov ecx, [ebx + TCP_SOCKET.t_srtt]
shr ecx, TCP_RTT_SHIFT
sub eax, ecx
dec eax
pop ecx
 
add [ebx + TCP_SOCKET.t_srtt], eax
ja @f
mov [ebx + TCP_SOCKET.t_srtt], 1
@@:
 
; We accumulate a smoothed rtt variance (actually, a smoothed mean difference),
; then set the retransmit timer to smoothed rtt + 4 times the smoothed variance.
; rttvar is stored as fixed point with 2 bits after the binary point.
; The following is equivalent to rfc793 smoothing with an alpha of .75
; (rttvar = rttvar*3/4 + delta/4) (delta = eax)
 
; get abs(eax)
push edx
cdq
xor eax, edx
sub eax, edx
 
mov edx, [ebx + TCP_SOCKET.t_rttvar]
shr edx, TCP_RTTVAR_SHIFT
sub eax, edx
pop edx
 
add [ebx + TCP_SOCKET.t_rttvar], eax
ja @f
mov [ebx + TCP_SOCKET.t_rttvar], 1
@@:
ret
 
 
.no_rtt_yet:
 
push ecx
mov ecx, eax
shl ecx, TCP_RTT_SHIFT
mov [ebx + TCP_SOCKET.t_srtt], ecx
 
shl eax, TCP_RTTVAR_SHIFT - 1
mov [ebx + TCP_SOCKET.t_rttvar], eax
pop ecx
 
ret
 
 
 
 
; eax = max segment size
; ebx = socket ptr
align 4
TCP_mss:
 
cmp eax, 1420 ; FIXME
jbe @f
mov eax, 1420
@@:
mov [ebx + TCP_SOCKET.t_maxseg], eax
 
 
ret
 
 
 
 
; ebx = socket ptr
; edx = segment ptr
align 4
TCP_reassemble:
 
 
 
ret
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/trunk/network/tcp_timer.inc
0,0 → 1,168
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Based on the code of 4.4BSD ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 3143 $
 
;----------------------
; 160 ms timer
;----------------------
macro TCP_timer_160ms {
 
local .loop
local .exit
 
mov ebx, net_sockets
.loop:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .exit
 
cmp [ebx + SOCKET.Domain], AF_INET4
jne .loop
 
cmp [ebx + SOCKET.Protocol], IP_PROTO_TCP
jne .loop
 
test [ebx + TCP_SOCKET.t_flags], TF_DELACK
jz .loop
and [ebx + TCP_SOCKET.t_flags], not (TF_DELACK)
 
push ebx
mov cl, TH_ACK
call TCP_respond
; and [ebx + TCP_SOCKET.t_flags], TF_ACKNOW ;;
; mov eax, ebx ;;
; call TCP_output ;;
pop ebx
 
jmp .loop
 
.exit:
 
}
 
 
;----------------------
; 640 ms timer
;----------------------
macro TCP_timer_640ms {
 
local .loop
local .exit
 
; Update TCP sequence number
 
add [TCP_sequence_num], 64000
 
; scan through all the active TCP sockets, decrementing ALL timers
; timers do not have the chance to wrap because the keepalive timer will kill the socket when it expires
 
mov eax, net_sockets
.loop:
mov eax, [eax + SOCKET.NextPtr]
.check_only:
or eax, eax
jz .exit
 
cmp [eax + SOCKET.Domain], AF_INET4
jne .loop
 
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
jne .loop
 
inc [eax + TCP_SOCKET.t_idle]
dec [eax + TCP_SOCKET.timer_retransmission]
jnz .check_more2
 
DEBUGF 1,"socket %x: Retransmission timer expired\n", eax
 
push eax
call TCP_output
pop eax
 
.check_more2:
dec [eax + TCP_SOCKET.timer_keepalive]
jnz .check_more3
 
DEBUGF 1,"socket %x: Keepalive expired\n", eax
 
cmp [eax + TCP_SOCKET.state], TCPS_ESTABLISHED
ja .dont_kill
 
push eax
call TCP_disconnect
pop eax
jmp .loop
 
.dont_kill:
test [eax + SOCKET.options], SO_KEEPALIVE
jz .reset_keepalive
 
push eax
mov ebx, eax
xor cl, cl
call TCP_respond ; send keepalive
pop eax
mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
jmp .check_more3
 
.reset_keepalive:
mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_idle
 
.check_more3:
dec [eax + TCP_SOCKET.timer_timed_wait]
jnz .check_more5
 
DEBUGF 1,"socket %x: 2MSL timer expired\n", eax
 
.check_more5:
dec [eax + TCP_SOCKET.timer_persist]
jnz .loop
 
DEBUGF 1,"socket %x: persist timer expired\n", eax
 
call TCP_set_persist
mov [eax + TCP_SOCKET.t_force], 1
push eax
call TCP_output
pop eax
mov [eax + TCP_SOCKET.t_force], 0
 
jmp .loop
.exit:
 
}
 
 
 
; eax = socket
 
TCP_cancel_timers:
 
push eax edi
 
lea edi, [eax + TCP_SOCKET.timer_retransmission]
xor eax, eax
stosd
stosd
stosd
stosd
stosd
 
pop edi eax
 
 
ret
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/trunk/network/tcp_usreq.inc
0,0 → 1,102
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Part of the TCP/IP network stack for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; Based on the code of 4.4BSD ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
;-------------------------
;
; TCP_usrclose
;
; Move connection to next state, based on process close.
;
; IN: eax = socket ptr
;
;-------------------------
align 4
TCP_usrclosed:
 
DEBUGF 1,"TCP_usrclosed: %x\n", eax
 
push ebx
mov ebx, [eax + TCP_SOCKET.t_state]
mov ebx, dword [.switch + ebx*4]
jmp ebx
 
.switch:
 
dd .close ; TCPS_CLOSED
dd .close ; TCPS_LISTEN
dd .close ; TCPS_SYN_SENT
dd .wait1 ; TCPS_SYN_RECEIVED
dd .wait1 ; TCPS_ESTABLISHED
dd .last_ack ; TCPS_CLOSE_WAIT
dd .ret ; TCPS_FIN_WAIT_1
dd .ret ; TCPS_CLOSING
dd .ret ; TCPS_LAST_ACK
dd .disc ; TCPS_FIN_WAIT_2
dd .disc ; TCPS_TIMED_WAIT
 
 
.close:
mov [eax + TCP_SOCKET.t_state], TCPS_CLOSED
call TCP_close
pop ebx
ret
 
.wait1:
mov [eax + TCP_SOCKET.t_state], TCPS_FIN_WAIT_1
; TODO: set timer?
pop ebx
ret
 
.last_ack:
mov [eax + TCP_SOCKET.t_state], TCPS_LAST_ACK
pop ebx
ret
 
.disc:
call SOCKET_is_disconnected
; TODO: set timer?
.ret:
pop ebx
ret
 
 
 
 
;-------------------------
;
; TCP_disconnect
;
; IN: eax = socket ptr
; OUT: eax = socket ptr
;
;-------------------------
align 4
TCP_disconnect:
 
DEBUGF 1,"TCP_disconnect: %x\n", eax
 
cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
jb TCP_close
 
 
; TODO: implement LINGER ?
 
call SOCKET_is_disconnecting
call TCP_usrclosed
call TCP_output
 
ret
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/kernel/trunk/network/udp.inc
1,153 → 1,325
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; UDP.INC ;;
;; ;;
;; UDP Processes for Menuet OS TCP/IP stack ;;
;; Part of the tcp/ip network stack for KolibriOS ;;
;; ;;
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; See file COPYING for details ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
$Revision: 2995 $
 
 
;*******************************************************************
; Interface
;
; udp_rx Handles received IP packets with the UDP protocol
;
;*******************************************************************
struct UDP_header
 
SourcePort dw ?
DestinationPort dw ?
Length dw ? ; Length of (UDP Header + Data)
Checksum dw ?
 
ends
 
 
align 4
uglobal
UDP_PACKETS_TX rd MAX_NET_DEVICES
UDP_PACKETS_RX rd MAX_NET_DEVICES
endg
 
 
;-----------------------------------------------------------------
;
; UDP Payload ( Data field in IP datagram )
; UDP_init
;
; 0 1 2 3
; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
; This function resets all UDP variables
;
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | Source Port | Destination Port |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | Length ( UDP Header + Data ) | Checksum |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
; | UDP Data |
; +-+-+-.......... -+
;
;-----------------------------------------------------------------
macro UDP_init {
 
struc UDP_PACKET
{ .SourcePort dw ? ;+00
.DestinationPort dw ? ;+02
.Length dw ? ;+04 - Length of (UDP Header + Data)
.Checksum dw ? ;+06
.Data db ? ;+08
xor eax, eax
mov edi, UDP_PACKETS_TX
mov ecx, 2*MAX_NET_DEVICES
rep stosd
}
 
virtual at 0
UDP_PACKET UDP_PACKET
end virtual
 
macro UDP_checksum IP1, IP2 { ; esi = ptr to udp packet, ecx = packet size, destroys: ecx, edx
 
;***************************************************************************
; Function
; udp_rx [by Johnny_B]
; Pseudoheader
mov edx, IP_PROTO_UDP
 
add dl, [IP1+1]
adc dh, [IP1+0]
adc dl, [IP1+3]
adc dh, [IP1+2]
 
adc dl, [IP2+1]
adc dh, [IP2+0]
adc dl, [IP2+3]
adc dh, [IP2+2]
 
adc dl, cl ; byte[esi+UDP_header.Length+1]
adc dh, ch ; byte[esi+UDP_header.Length+0]
 
; Done with pseudoheader, now do real header
adc dl, byte[esi+UDP_header.SourcePort+1]
adc dh, byte[esi+UDP_header.SourcePort+0]
 
adc dl, byte[esi+UDP_header.DestinationPort+1]
adc dh, byte[esi+UDP_header.DestinationPort+0]
 
adc dl, byte[esi+UDP_header.Length+1]
adc dh, byte[esi+UDP_header.Length+0]
 
adc edx, 0
 
; Done with header, now do data
push esi
movzx ecx, [esi+UDP_header.Length]
rol cx , 8
sub cx , sizeof.UDP_header
add esi, sizeof.UDP_header
 
call checksum_1
call checksum_2
pop esi
 
add [esi+UDP_header.Checksum], dx ; this final instruction will set or clear ZF :)
 
}
 
 
;-----------------------------------------------------------------
;
; Description
; UDP protocol handler
; This is a kernel function, called by ip_rx
; IP buffer address given in edx
; IP buffer number in eax
; Free up (or re-use) IP buffer when finished
; UDP_input:
;
;***************************************************************************
; Called by IPv4_input,
; this procedure will inject the udp data diagrams in the application sockets.
;
; IN: [esp] = Pointer to buffer
; [esp+4] = size of buffer
; ebx = ptr to device struct
; ecx = UDP Packet size
; esi = ptr to UDP header
; edi = ptr to ipv4 source and dest address
;
; OUT: /
;
;-----------------------------------------------------------------
align 4
UDP_input:
 
proc udp_rx stdcall
push eax
DEBUGF 1,"UDP_input: size=%u\n", ecx
 
; First validate the header & checksum. Discard buffer if error
; First validate, checksum
 
neg [esi + UDP_header.Checksum] ; substract checksum from 0
jz .no_checksum ; if checksum is zero, it is considered valid
 
; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct
 
UDP_checksum (edi), (edi+4)
jnz .checksum_mismatch
 
.no_checksum:
DEBUGF 1,"UDP_input: checksum ok\n"
 
; Convert length to little endian
 
rol [esi + UDP_header.Length], 8
 
; Look for a socket where
; IP Packet UDP Destination Port = local Port
; IP Packet SA = Remote IP
 
mov ax, [edx + 20 + UDP_PACKET.DestinationPort] ; get the local port from
; the IP packet's UDP header
mov cx, [esi + UDP_header.SourcePort]
mov dx, [esi + UDP_header.DestinationPort]
mov edi, [edi + 4] ; ipv4 source address
mov eax, net_sockets
 
mov ebx, net_sockets
 
.next_socket:
mov ebx, [ebx + SOCKET.NextPtr]
or ebx, ebx
jz .exit ; No match, so exit
cmp [ebx + SOCKET.LocalPort], ax ; ax will hold the 'wrong' value,
; but the comparision is correct
jne .next_socket ; Return back if no match
mov eax, [eax + SOCKET.NextPtr]
or eax, eax
jz .dump
 
; For dhcp, we must allow any remote server to respond.
; I will accept the first incoming response to be the one
; I bind to, if the socket is opened with a destination IP address of
; 255.255.255.255
cmp [ebx + SOCKET.RemoteIP], 0xffffffff
je @f
cmp [eax + SOCKET.Domain], AF_INET4
jne .next_socket
 
mov eax, [edx + IP_PACKET.SourceAddress] ; get the Source address from the IP packet
cmp [ebx + SOCKET.RemoteIP], eax
jne .exit ; Quit if the source IP is not valid
cmp [eax + SOCKET.Protocol], IP_PROTO_UDP
jne .next_socket
 
@@: ; OK - we have a valid UDP packet for this socket.
; First, update the sockets remote port number with the incoming msg
; - it will have changed
; from the original ( 69 normally ) to allow further connects
mov ax, [edx + 20 + UDP_PACKET.SourcePort] ; get the UDP source port
; ( was 69, now new )
mov [ebx + SOCKET.RemotePort], ax
cmp [eax + UDP_SOCKET.LocalPort], dx
jne .next_socket
 
; Now, copy data to socket. We have socket address as [eax + sockets].
; We have IP packet in edx
DEBUGF 1,"UDP_input: socket=%x\n", eax
 
; get # of bytes in ecx
movzx ecx, [edx + IP_PACKET.TotalLength] ; total length of IP packet. Subtract
xchg cl, ch ; 20 + 8 gives data length
sub ecx, 28
;;; TODO: when packet is processed, check more sockets!
 
mov eax, [ebx + SOCKET.rxDataCount] ; get # of bytes already in buffer
add [ebx + SOCKET.rxDataCount], ecx ; increment the count of bytes in buffer
; cmp [eax + IP_SOCKET.RemoteIP], 0xffffffff
; je @f
; cmp [eax + IP_SOCKET.RemoteIP], edi
; jne .next_socket
; @@:
;
; FIXME: UDP should check remote IP, but not under all circumstances!
 
; ecx has count, edx points to data
cmp [eax + UDP_SOCKET.firstpacket], 0
je .updateport
 
add edx, 28 ; edx now points to the data
lea edi, [ebx + eax + SOCKETHEADERSIZE]
mov esi, edx
cmp [eax + UDP_SOCKET.RemotePort], cx
jne .dump
 
cld
rep movsb ; copy the data across
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
 
; flag an event to the application
mov eax, [ebx + SOCKET.PID] ; get socket owner PID
mov ecx, 1
mov esi, TASK_DATA + TASKDATA.pid
.updatesock:
inc [UDP_PACKETS_RX] ; Fixme: correct interface?
 
.next_pid:
cmp [esi], eax
je .found_pid
inc ecx
add esi, 0x20
cmp ecx, [TASK_COUNT]
jbe .next_pid
movzx ecx, [esi + UDP_header.Length]
sub ecx, sizeof.UDP_header
add esi, sizeof.UDP_header
 
jmp .exit
jmp SOCKET_input
 
.found_pid:
shl ecx, 8
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event
.updateport:
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
 
.exit:
pop eax
call freeBuff ; Discard the packet
DEBUGF 1,"UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf
mov [eax + UDP_SOCKET.RemotePort], cx
inc [eax + UDP_SOCKET.firstpacket]
 
jmp .updatesock
 
 
.checksum_mismatch:
DEBUGF 2,"UDP_input: checksum mismatch\n"
 
.dump:
call kernel_free
add esp, 4 ; pop (balance stack)
DEBUGF 2,"UDP_input: dumping\n"
 
ret
endp
 
 
 
 
;-----------------------------------------------------------------
;
; UDP_output
;
; IN: eax = socket pointer
; ecx = number of bytes to send
; esi = pointer to data
;
;-----------------------------------------------------------------
 
align 4
UDP_output:
 
DEBUGF 1,"UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi
 
mov dx, [eax + UDP_SOCKET.RemotePort]
DEBUGF 1,"UDP_output: remote port=%x, ", dx ; FIXME: find a way to print big endian values with debugf
rol edx, 16
mov dx, [eax + UDP_SOCKET.LocalPort]
DEBUGF 1,"local port=%x\n", dx
 
sub esp, 8 ; Data ptr and data size will be placed here
push edx esi
mov ebx, [eax + SOCKET.device]
mov edx, [eax + IP_SOCKET.LocalIP]
mov eax, [eax + IP_SOCKET.RemoteIP]
mov di, IP_PROTO_UDP shl 8 + 128
add ecx, sizeof.UDP_header
call IPv4_output
jz .fail
mov [esp + 8], eax ; pointer to buffer start
mov [esp + 8 + 4], edx ; buffer size
 
mov [edi + UDP_header.Length], cx
rol [edi + UDP_header.Length], 8
 
pop esi
push edi ecx
sub ecx, sizeof.UDP_header
add edi, sizeof.UDP_header
shr ecx, 2
rep movsd
mov ecx, [esp]
and ecx, 3
rep movsb
pop ecx edi
 
pop dword [edi + UDP_header.SourcePort]
 
; Checksum
mov esi, edi
mov [edi + UDP_header.Checksum], 0
UDP_checksum (edi-4), (edi-8) ; FIXME: IPv4 packet could have options..
 
DEBUGF 1,"UDP_output: sending with device %x\n", ebx
call [ebx + NET_DEVICE.transmit]
test eax, eax
jnz @f
inc [UDP_PACKETS_TX] ; FIXME: correct device?
@@:
 
ret
 
.fail:
DEBUGF 1,"UDP_output: failed\n"
add esp, 4+4+8
or eax, -1
ret
 
 
 
;---------------------------------------------------------------------------
;
; UDP_API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;---------------------------------------------------------------------------
 
align 4
UDP_api:
 
movzx eax, bh
shl eax, 2
 
test bl, bl
jz .packets_tx ; 0
dec bl
jz .packets_rx ; 1
 
.error:
mov eax, -1
ret
 
.packets_tx:
mov eax, [UDP_PACKETS_TX + eax]
ret
 
.packets_rx:
mov eax, [UDP_PACKETS_RX + eax]
ret
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/programs/develop/libraries/network/network.asm
28,8 → 28,8
mov [mem.realloc], ecx
mov [dll.load], edx
mov [DNSrequestID], 1
stdcall edx, @IMPORT
ret 4
xor eax, eax
ret
 
;;===========================================================================;;
;; in_addr_t __stdcall inet_addr(__in const char* hostname); ;;
257,7 → 257,7
ret
 
struct __gai_reqdata
socket dd ?
socketnum dd ?
; external code should not look on rest of this structure,
; it is internal for getaddrinfo_start/process/abort
reqid dw ? ; DNS request ID
279,7 → 279,7
;;---------------------------------------------------------------------------;;
;> first parameter (optional) = host name ;;
;> second parameter (optional) = service name (decimal number for now) ;;
;> third parameter (optional) = hints for socket type ;;
;> third parameter (optional) = hints for socketnum type ;;
;> fourth parameter = pointer to result (head of L1-list) ;;
;;---------------------------------------------------------------------------;;
;< eax = 0 on success / one of EAI_ codes on error ;;
425,14 → 425,14
jecxz @f
cmp [ecx+addrinfo.ai_family], edi
jz @f
cmp [ecx+addrinfo.ai_family], PF_INET
cmp [ecx+addrinfo.ai_family], AF_INET4
jnz .ret
@@:
; 1e. Valid combinations for ai_socktype/ai_protocol: 0/0 for any or
; SOCK_STREAM/IPPROTO_TCP, SOCK_DGRAM/IPPROTO_UDP
; (raw sockets are not yet supported by the kernel)
; (raw socketnums are not yet supported by the kernel)
xor edx, edx ; assume 0=any if no hints
jecxz .socket_type_ok
jecxz .socketnum_type_ok
mov edx, [ecx+addrinfo.ai_socktype]
mov esi, [ecx+addrinfo.ai_protocol]
; 1f. Test for ai_socktype=0 and ai_protocol=0.
439,16 → 439,16
test edx, edx
jnz .check_socktype
test esi, esi
jz .socket_type_ok
jz .socketnum_type_ok
; 1g. ai_socktype=0, ai_protocol is nonzero.
push EAI_SERVICE
pop eax
inc edx ; edx = SOCK_STREAM
cmp esi, IPPROTO_TCP
jz .socket_type_ok
jz .socketnum_type_ok
inc edx ; edx = SOCK_DGRAM
cmp esi, IPPROTO_UDP
jz .socket_type_ok
jz .socketnum_type_ok
.ret:
; Restore saved registers, destroy stack frame and return.
mov esp, ebp
464,16 → 464,16
cmp edx, SOCK_DGRAM
jnz .ret
test esi, esi
jz .socket_type_ok
jz .socketnum_type_ok
cmp esi, IPPROTO_UDP
jz .socket_type_ok
jz .socketnum_type_ok
jmp .ret
.check_tcp:
test esi, esi
jz .socket_type_ok
jz .socketnum_type_ok
cmp esi, IPPROTO_TCP
jnz .ret
.socket_type_ok:
.socketnum_type_ok:
mov [ebx+__gai_reqdata.socktype], dl
; 2. Resolve service.
; 2a. If no name is given, remember value -1.
513,7 → 513,7
; 3. Process host name.
mov esi, [.hostname]
; 3a. If hostname is not given,
; use localhost for active sockets and INADDR_ANY for passive sockets.
; use localhost for active socketnums and INADDR_ANY for passive socketnums.
mov eax, 0x0100007F ; 127.0.0.1 in network byte order
test byte [ebx+__gai_reqdata.flags], AI_PASSIVE
jz @f
675,25 → 675,43
mov eax, 0x01000100
stosd
; 7. Get DNS server address.
mcall 52, 13
xchg esi, eax ; put server address to esi
; 8. Open UDP socket to DNS server, port 53.
mcall 53, 0, 0, 53
mcall 76, API_IPv4 + 4 ; protocol IP=0, device number=0, function=get DNS address
cmp eax, -1
je .ret.dnserr
mov esi, eax ; put server address to esi
; 8. Open UDP socketnum to DNS server, port 53.
; 8a. Create new socketnum.
mcall 75, 0, AF_INET4, SOCK_DGRAM
cmp eax, -1 ; error?
jz .ret.dnserr
xchg ecx, eax ; put socket handle to ecx
mov ecx, eax ; put socketnum handle to ecx
; 8b. Create sockaddr structure on the stack.
push 0
push 0 ; sin_zero
push esi ; sin_addr
push AF_INET4 + (53 shl 24)
; sin_family and sin_port in network byte order
; 8c. Connect.
mcall 75, 4, , esp, sizeof.sockaddr_in
; 8d. Restore the stack, undo 8b.
add esp, esi
; 8e. Check result.
cmp eax, -1
jz .ret.close
; 9. Send DNS request packet.
sub edi, esp ; get packet length
mcall 53, 4, , edi, esp
mov esi, edi
xor edi, edi
mcall 75, 6, , esp
cmp eax, -1
jz .ret.close
mov eax, [.reqdata]
mov [eax+__gai_reqdata.socket], ecx
mov [eax+__gai_reqdata.socketnum], ecx
push -1
pop eax ; return status: more processing required
jmp .ret.dns
.ret.close:
mcall 53, 1
mcall 75, 1
.ret.dnserr:
push EAI_AGAIN
pop eax
741,9 → 759,11
push ebx esi edi
mov edi, [.reqdata]
; 2. Read UDP datagram.
mov ecx, [edi+__gai_reqdata.socket]
mcall 53, 11, , , 512
; 3. Ignore events for other sockets (return if no data read)
mov ecx, [edi+__gai_reqdata.socketnum]
push edi
mcall 75, 7, , , 512, 0
pop edi
; 3. Ignore events for other socketnums (return if no data read)
test eax, eax
jz .ret.more_processing_required
; 4. Sanity check: discard too short packets.
898,11 → 918,11
@@:
pop eax
.ret.close:
; 15. Close socket.
; 15. Close socketnum.
push eax
mov ecx, [.reqdata]
mov ecx, [ecx+__gai_reqdata.socket]
mcall 53, 1
mov ecx, [ecx+__gai_reqdata.socketnum]
mcall 75, 1
pop eax
; 16. Restore used registers, destroy stack frame and return.
.ret:
1150,13 → 1170,12
; 4. Fill struct addrinfo.
mov eax, [ebx+__gai_reqdata.flags]
mov [edi+addrinfo.ai_flags], eax
mov byte [edi+addrinfo.ai_family], PF_INET
mov byte [edi+addrinfo.ai_family], AF_INET4
mov byte [edi+addrinfo.ai_addrlen], sizeof.sockaddr_in
lea ecx, [edi+sizeof.addrinfo]
mov [edi+addrinfo.ai_addr], ecx
; 5. Fill struct sockaddr_in.
mov byte [ecx+sockaddr_in.sin_len], sizeof.sockaddr_in
mov byte [ecx+sockaddr_in.sin_family], PF_INET
mov byte [ecx+sockaddr_in.sin_family], AF_INET4
pop eax
mov [ecx+sockaddr_in.sin_addr], eax
; 6. Append new item to the list.
1170,7 → 1189,7
ret
 
.set_socktype:
; Set ai_socktype and ai_protocol fields by given socket type.
; Set ai_socktype and ai_protocol fields by given socketnum type.
mov byte [edi+addrinfo.ai_socktype], cl
dec cl
jnz .set_udp
1185,7 → 1204,7
; Just copy port from input __gai_reqdata to output addrinfo.
push edx
mov edx, [ebx+__gai_reqdata.service]
xchg dl, dh ; convert to network byte order
xchg dl, dh ; convert to network byte order ;;;;; CHECKME
mov [edi+sizeof.addrinfo+sockaddr_in.sin_port], dx
pop edx
ret
1200,10 → 1219,10
;;===========================================================================;;
; 0. Save used registers for __stdcall.
push ebx
; 1. Allocated resources: only socket, so close it and return.
; 1. Allocated resources: only socketnum, so close it and return.
mov eax, [esp+8]
mov ecx, [eax+__gai_reqdata.socket]
mcall 53, 1
mov ecx, [eax+__gai_reqdata.socketnum]
mcall 75, 1
; 2. Restore used registers and return.
pop ebx
ret 4
1264,16 → 1283,6
getaddrinfo_abort , 'getaddrinfo_abort' , \
freeaddrinfo , 'freeaddrinfo'
 
; import from libini
align 4
@IMPORT:
 
library libini, 'libini.obj'
import libini, \
ini.get_str, 'ini_get_str', \
ini.get_int, 'ini_get_int'
 
 
section '.data' data readable writable align 16
; uninitialized data
mem.alloc dd ?
/programs/develop/libraries/network/network.inc
1,22 → 1,27
; Socket types
SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3 ; not supported by the kernel
SOCK_RAW = 3
 
; Socket options
SO_NONBLOCK = 1 shl 31
 
; IP protocols
IPPROTO_IP = 0
IPPROTO_ICMP = 1 ; not supported by the kernel
IPPROTO_ICMP = 1
IPPROTO_TCP = 6
IPPROTO_UDP = 17
 
; Address families
AF_UNSPEC = 0
AF_INET = 2 ; IPv4
;AF_INET6 = 28 ; IPv6 (not supported)
AF_LOCAL = 1
AF_INET4 = 2 ; IPv4
AF_INET6 = 28 ; IPv6 (not supported yet)
 
PF_UNSPEC = AF_UNSPEC
PF_INET = AF_INET
;PF_INET6 = AF_INET6
PF_LOCAL = AF_LOCAL
PF_INET4 = AF_INET4
PF_INET6 = AF_INET6
 
; Flags for addrinfo
AI_PASSIVE = 1
28,9 → 33,17
; internal definition
AI_SUPPORTED = 0x40F
 
; for system function 76
API_ETH = 0 shl 16
API_IPv4 = 1 shl 16
API_ICMP = 2 shl 16
API_UDP = 3 shl 16
API_TCP = 4 shl 16
API_ARP = 5 shl 16
API_PPPOE = 6 shl 16
 
struct sockaddr_in
sin_len db ? ; uint8_t
sin_family db ? ; sa_family_t
sin_family dw ? ; sa_family_t
sin_port dw ? ; in_port_t
sin_addr dd ? ; struct in_addr
sin_zero rb 8 ; zero
59,3 → 72,23
EAI_BADHINTS = 12
EAI_PROTOCOL = 13
EAI_OVERFLOW = 14
 
socket fix 75, 0
close fix 75, 1
bind fix 75, 2
listen fix 75, 3
connect fix 75, 4
accept fix 75, 5
send fix 75, 6
recv fix 75, 7
setsockopt fix 75, 8
getsockopt fix 75, 9
socketpair fix 75, 10
 
 
struct ARP_entry
IP dd ?
MAC dp ?
status dw ?
TTL dw ?
ends
/programs/network/smtps/trunk/smtps.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/smtps/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/smtps/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/remote/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/remote/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/remote/trunk/remote.asm
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/stackcfg/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/stackcfg/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/stackcfg/trunk/readme.txt
File deleted
\ No newline at end of file
/programs/network/stackcfg/trunk/stackcfg.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/ethstat/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/ethstat/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/ethstat/trunk/ethstat.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/arpstat/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/arpstat/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/arpstat/trunk/arpstat.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/browser/browser.asm
File deleted
/programs/network/browser/build.bat
File deleted
Property changes:
Deleted: svn:executable
-*
\ No newline at end of property
/programs/network/browser/build.sh
File deleted
Property changes:
Deleted: svn:executable
-*
\ No newline at end of property
/programs/network/rccc/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/rccc/trunk/rccc.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/rccc/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/rccs/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/rccs/trunk/rccs.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/rccs/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/mp3s/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/mp3s/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/mp3s/trunk/mp3s.asm
File deleted
/programs/network/terminal/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/terminal/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/terminal/trunk/terminal.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/ym/trunk/ym.asm
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/ym/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/ym/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/chess/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/chess/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/chess/trunk/chess.bmp
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/programs/network/chess/trunk/chess.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/popc/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/popc/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/popc/trunk/popc.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/local/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/local/trunk/local.asm
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/local/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/VNCclient/logon.inc
File deleted
/programs/network/VNCclient/ETH.INC
File deleted
/programs/network/VNCclient/thread.inc
File deleted
\ No newline at end of file
/programs/network/VNCclient/copyrect.inc
File deleted
\ No newline at end of file
/programs/network/VNCclient/fdo.inc
File deleted
/programs/network/VNCclient/raw.inc
File deleted
/programs/network/VNCclient/VNCclient.asm
File deleted
/programs/network/VNCclient/build.bat
File deleted
\ No newline at end of file
/programs/network/nntpc/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/nntpc/trunk/nntpc.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/nntpc/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/tftpa/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/tftpa/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/tftpa/trunk/tftpa.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/ppp/trunk/ppp.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/ppp/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/ppp/trunk/chat.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/ppp/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/downloader/trunk/build.bat
File deleted
\ No newline at end of file
/programs/network/downloader/trunk/build.sh
File deleted
/programs/network/downloader/trunk/downloader.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/https/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/https/trunk/https.asm
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/https/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/dhcp/trunk/dhcp.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/dhcp/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/dhcp/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/airc/trunk/airc.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/airc/trunk/fdo.inc
File deleted
/programs/network/airc/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/airc/trunk/eth.inc
File deleted
/programs/network/airc/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/ipc/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/ipc/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/ipc/trunk/ipc.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/icq/trunk/ki.cfg
File deleted
/programs/network/icq/trunk/parser.inc
File deleted
/programs/network/icq/trunk/ssi.inc
File deleted
/programs/network/icq/trunk/editbox.inc
File deleted
\ No newline at end of file
/programs/network/icq/trunk/comp.inc
File deleted
/programs/network/icq/trunk/cmdipc.inc
File deleted
/programs/network/icq/trunk/build_ru.bat
File deleted
/programs/network/icq/trunk/README.TXT
File deleted
/programs/network/icq/trunk/dialogs1.inc
File deleted
/programs/network/icq/trunk/config.inc
File deleted
/programs/network/icq/trunk/proc32.inc
File deleted
/programs/network/icq/trunk/ki.asm
File deleted
/programs/network/icq/trunk/icons.inc
File deleted
\ No newline at end of file
/programs/network/icq/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/icq/trunk/SSI_INFO.txt
File deleted
\ No newline at end of file
/programs/network/icq/trunk/lang.inc
File deleted
/programs/network/icq/trunk/2000.inc
File deleted
/programs/network/icq/trunk/macros.inc
File deleted
/programs/network/icq/trunk/struct.inc
File deleted
/programs/network/icq/trunk/parser_data.inc
File deleted
/programs/network/icq/trunk/editbox.mac
File deleted
\ No newline at end of file
/programs/network/icq/trunk/dos2win.inc
File deleted
/programs/network/icq/trunk/st_red.bmp
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Deleted: svn:mime-type
-application/octet-stream
\ No newline at end of property
/programs/network/icq/trunk/STDCALL.INC
File deleted
\ No newline at end of file
/programs/network/icq/trunk/ssi_data.inc
File deleted
\ No newline at end of file
/programs/network/icq/trunk/comp_data.inc
File deleted
\ No newline at end of file
/programs/network/icq/trunk
Property changes:
Deleted: tsvn:logminsize
-5
\ No newline at end of property
/programs/network/icq
Property changes:
Deleted: tsvn:logminsize
-5
\ No newline at end of property
/programs/network/dnsr/trunk/dnsr.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/dnsr/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/dnsr/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/ftps/trunk/FTPS.ASM
File deleted
/programs/network/ftps/trunk/build.bat
File deleted
/programs/network/netsendc/trunk/netsendc.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/netsendc/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/netsendc/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/netsends/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/netsends/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/netsends/trunk/netsends.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/arpcfg/arpcfg.asm
0,0 → 1,156
;
; ARPmanager for KolibriOS
;
; hidnplayr@gmail.com
;
 
format binary as ""
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd IM_END ; size of image
dd (I_END+0x100) ; memory for app
dd (I_END+0x100) ; esp
dd 0x0 , 0x0 ; I_Param , I_Icon
 
include '../macros.inc'
purge mov, add, sub
include '../struct.inc'
include '../network.inc'
 
START:
 
redraw:
 
mcall 12, 1
mcall 0, 100 shl 16 + 520, 100 shl 16 + 240, 0x34bcbcbc, , str_name
mcall 4, 25 shl 16 + 31, 0x80000000, str_legend
mcall 12, 2
 
draw_stats:
 
mov edx, 50 shl 16 + 50
mov [last], 0
 
.loop:
mcall 76, API_ARP + 3, [last],,, arp_buf
cmp eax, -1
je mainloop
 
mcall 4, edx, 0x80000000, str_entry
mov edx, ebx
 
mov eax, 47
mov ebx, 0x00030000
mov esi, 0x40000000
mov edi, 0x00bcbcbc
xor ecx, ecx
 
mov cl, byte[arp_buf.IP+0]
mcall
 
mov cl, byte[arp_buf.IP+1]
add edx, 24 shl 16
mcall
 
mov cl, byte[arp_buf.IP+2]
add edx, 24 shl 16
mcall
 
mov cl, byte[arp_buf.IP+3]
add edx, 24 shl 16
mcall
 
 
mov ebx, 0x00020100
mov cl, byte[arp_buf.MAC+0]
add edx, 36 shl 16
mcall
 
mov cl, byte[arp_buf.MAC+1]
add edx, 18 shl 16
mcall
 
mov cl, byte[arp_buf.MAC+2]
add edx, 18 shl 16
mcall
 
mov cl, byte[arp_buf.MAC+3]
add edx, 18 shl 16
mcall
 
mov cl, byte[arp_buf.MAC+4]
add edx, 18 shl 16
mcall
 
mov cl, byte[arp_buf.MAC+5]
add edx, 18 shl 16
mcall
 
mov ebx, 0x00040000
mov cx, [arp_buf.status]
add edx, 30 shl 16
mcall
 
mov cx, [arp_buf.TTL]
add edx, 60 shl 16
mcall
 
add dx, 20
rol edx, 16
mov dx, 50
rol edx, 16
inc [last]
 
jmp .loop
 
 
mainloop:
 
mcall 23,50 ; wait for event with timeout (0,5 s)
 
cmp eax, 1
je redraw
cmp eax, 2
je key
cmp eax, 3
je button
 
jmp draw_stats
 
 
key:
mcall 2
jmp mainloop
 
 
button: ; button
mcall 17 ; get id
cmp ah, 1
je exit
jmp redraw
 
exit:
mcall -1
 
 
 
; DATA AREA
 
str_name db 'ARP manager', 0
str_legend db '# IP-address MAC-address Status TTL', 0
str_entry db ' . . . - - - - - s', 0
 
IM_END:
 
last dd ?
arp_buf ARP_entry
 
I_END:
 
 
/programs/network/arpcfg
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network/config.inc
0,0 → 1,0
__CPU_type fix p5
/programs/network/debug-fdo.inc
0,0 → 1,422
;
; 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
else if _hex in <ax,bx,cx,dx,si,di,bp,sp>
if ~_hex eq ax
movzx eax,_hex
end if
shl eax,16
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
shl eax,24
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
mov edx,8
end if
call fdo_debug_outhex
popad
popf
}
 
;-----------------------------------------------------------------------------
 
debug_func fdo_debug_outchar
debug_beginf
pushad
mov cl,al
mov ebx,1
mov eax,63
mcall
popad
ret
debug_endf
 
debug_func fdo_debug_outstr
debug_beginf
mov eax,63
mov ebx,1
.l1: dec esi
js .l2
mov cl,[edx]
or cl,cl
jz .l2
mcall
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
}
/programs/network/dll.inc
0,0 → 1,160
;-----------------------------------------------------------------------------
proc mem.Alloc size ;/////////////////////////////////////////////////////////
;-----------------------------------------------------------------------------
push ebx ecx
mov eax,[size]
lea ecx,[eax+4+4095]
and ecx, not 4095
mcall 68,12
test eax, eax
jz @f
add ecx,-4
mov [eax],ecx
add eax,4
@@:
pop ecx ebx
ret
endp
 
;-----------------------------------------------------------------------------
proc mem.ReAlloc mptr,size;///////////////////////////////////////////////////
;-----------------------------------------------------------------------------
push ebx ecx esi edi eax
mov eax,[mptr]
mov ebx,[size]
or eax,eax
jz @f
lea ecx,[ebx+4+4095]
and ecx,not 4095
add ecx,-4
cmp ecx,[eax-4]
je .exit
@@: mov eax,ebx
call mem.Alloc
xchg eax,[esp]
or eax,eax
jz .exit
mov esi,eax
xchg eax,[esp]
mov edi,eax
mov ecx,[esi-4]
cmp ecx,[edi-4]
jbe @f
mov ecx,[edi-4]
@@: add ecx,3
shr ecx,2
cld
rep movsd
xchg eax,[esp]
call mem.Free
.exit:
pop eax edi esi ecx ebx
ret
endp
 
;-----------------------------------------------------------------------------
proc mem.Free mptr ;//////////////////////////////////////////////////////////
;-----------------------------------------------------------------------------
mov eax,[mptr]
or eax,eax
jz @f
push ebx ecx
lea ecx,[eax-4]
mcall 68,13
pop ecx ebx
@@: ret
endp
 
 
proc dll.Load, import_table:dword
mov esi,[import_table]
.next_lib: mov edx,[esi]
or edx,edx
jz .exit
push esi
mov esi,[esi+4]
mov edi,s_libdir.fname
@@: lodsb
stosb
or al,al
jnz @b
mcall 68,19,s_libdir
or eax,eax
jz .fail
stdcall dll.Link,eax,edx
stdcall dll.Init,[eax+4]
pop esi
add esi,8
jmp .next_lib
.exit: xor eax,eax
ret
.fail: add esp,4
xor eax,eax
inc eax
ret
endp
 
proc dll.Link, exp:dword,imp:dword
push eax
mov esi,[imp]
test esi,esi
jz .done
.next: lodsd
test eax,eax
jz .done
stdcall dll.GetProcAddress,[exp],eax
or eax,eax
jz @f
mov [esi-4],eax
jmp .next
@@: mov dword[esp],0
.done: pop eax
ret
endp
 
proc dll.Init, dllentry:dword
pushad
mov eax,mem.Alloc
mov ebx,mem.Free
mov ecx,mem.ReAlloc
mov edx,dll.Load
stdcall [dllentry]
popad
ret
endp
 
proc dll.GetProcAddress, exp:dword,sz_name:dword
mov edx,[exp]
xor eax,eax
.next: or edx,edx
jz .end
cmp dword[edx],0
jz .end
stdcall strcmp,[edx],[sz_name]
test eax,eax
jz .ok
add edx,8
jmp .next
.ok: mov eax,[edx+4]
.end: ret
endp
 
proc strcmp, str1:dword,str2:dword
push esi edi
mov esi,[str1]
mov edi,[str2]
xor eax,eax
@@: lodsb
scasb
jne .fail
or al,al
jnz @b
jmp .ok
.fail: or eax,-1
.ok: pop edi esi
ret
endp
 
s_libdir:
db '/sys/lib/'
.fname rb 32
/programs/network/ftpd/commands.inc
0,0 → 1,1135
 
 
struct thread_data
rb 1024
stack rb 0
 
home_dir rb 1024 ; home directory in wich the user is locked, asciiz
work_dir rb 1024 ; working directory, must at all times begin and end with a '/', asciiz
fpath rb 1024*3 ; file path, combination of home_dir, work_dir and filename
; Will also be used to temporarily store username
 
type db ? ; ASCII/EBDIC/IMAGE/..
mode db ? ; active/passive
socketnum dd ? ; Commands socket
state dd ? ; disconnected/logging in/logged in/..
passivesocknum dd ? ; when in passive mode, this is the listening socket
datasocketnum dd ? ; socket used for data transfers
permissions dd ? ; read/write/execute/....
buffer_ptr dd ?
pid dd ? ; Process id of the current thread
 
datasock sockaddr_in
 
buffer rb BUFFERSIZE
ends
 
;------------------------------------------------
; parse_cmd
;
; Internal function wich uses the 'commands'
; table to call an appropriate cmd_xx function.
;
; input: esi = ptr to ascii commands
; ecx = number of bytes input
; ebp = pointer to thread_data structure
;
; output: none
;
;------------------------------------------------
align 4
parse_cmd: ; esi must point to command
 
cmp byte [esi], 0x20 ; skip all leading characters
ja .ok
inc esi
dec ecx
cmp ecx, 3
jb .error
jmp parse_cmd
.ok:
cmp byte [esi+3], 0x20
ja @f
mov byte [esi+3], 0
@@:
 
mov eax, [esi]
and eax, not 0x20202020 ; convert to upper case
mov edi, commands ; list of commands to scan
.scanloop:
cmp eax, [edi]
je .got_it
 
add edi, 5*4
cmp byte [edi], 0
jne .scanloop
 
.error:
cmp [ebp + thread_data.state], STATE_ACTIVE
jb login_first
sendFTP "500 Unsupported command"
ret
 
.got_it:
mov eax, [ebp + thread_data.state]
jmp dword [edi + 4 + eax]
 
 
align 4
iglobal
commands: ; all commands must be in uppercase
 
dd 'ABOR', login_first, login_first, login_first, cmdABOR
; dd 'ACCT', login_first, login_first, login_first, cmd_ACCT
; dd 'APPE', login_first, login_first, login_first, cmd_APPE
dd 'CDUP', login_first, login_first, login_first, cmdCDUP
dd 'CWD', login_first, login_first, login_first, cmdCWD
dd 'DELE', login_first, login_first, login_first, cmdDELE
; dd 'HELP', login_first, login_first, login_first, cmd_HELP
dd 'LIST', login_first, login_first, login_first, cmdLIST
; dd 'MDTM', login_first, login_first, login_first, cmd_MDTM
; dd 'MKD', login_first, login_first, login_first, cmd_MKD
; dd 'MODE', login_first, login_first, login_first, cmd_MODE
dd 'NLST', login_first, login_first, login_first, cmdNLST
dd 'NOOP', login_first, login_first, login_first, cmdNOOP
dd 'PASS', cmdPASS.0, cmdPASS , cmdPASS.2, cmdPASS.3
dd 'PASV', login_first, login_first, login_first, cmdPASV
dd 'PORT', login_first, login_first, login_first, cmdPORT
dd 'PWD', login_first, login_first, login_first, cmdPWD
dd 'QUIT', cmdQUIT, cmdQUIT, cmdQUIT, cmdQUIT
; dd 'REIN', login_first, login_first, login_first, cmd_REIN
; dd 'REST', login_first, login_first, login_first, cmd_REST
dd 'RETR', login_first, login_first, login_first, cmdRETR
; dd 'RMD', login_first, login_first, login_first, cmd_RMD
; dd 'RNFR', login_first, login_first, login_first, cmd_RNFR
; dd 'RNTO', login_first, login_first, login_first, cmd_RNTO
; dd 'SITE', login_first, login_first, login_first, cmd_SITE
; dd 'SIZE', login_first, login_first, login_first, cmd_SIZE
; dd 'STAT', login_first, login_first, login_first, cmd_STAT
dd 'STOR', login_first, login_first, login_first, cmdSTOR
; dd 'STOU', login_first, login_first, login_first, cmd_STOU
; dd 'STRU', login_first, login_first, login_first, cmd_STRU
dd 'SYST', login_first, login_first, login_first, cmdSYST
dd 'TYPE', login_first, login_first, login_first, cmdTYPE
dd 'USER', cmdUSER, cmdUSER, cmdUSER, cmdUSER.2
db 0 ; end marker
endg
 
align 4
login_first:
sendFTP "530 Please login with USER and PASS"
ret
 
align 4
permission_denied:
sendFTP "550 Permission denied"
ret
 
align 4
socketerror:
invoke con_set_flags, 0x0c
invoke con_write_asciiz, str_sockerr
invoke con_set_flags, 0x07
 
sendFTP "425 Can't open data connection"
ret
 
align 4
abort_transfer:
and [ebp + thread_data.permissions], not ABORT
mov [ebp + thread_data.mode], MODE_NOTREADY
invoke file.close, ebx
mcall close, [ebp + thread_data.datasocketnum]
 
sendFTP "530 Transfer aborted"
ret
 
align 4
ip_to_dword: ; esi = ptr to str, cl = separator ('.', ',')
 
call ascii_to_byte
mov bl, al
cmp byte [esi], cl
jne .err
inc esi
 
call ascii_to_byte
mov bh, al
cmp byte [esi], cl
jne .err
inc esi
 
shl ebx, 16
 
call ascii_to_byte
mov bl, al
cmp byte [esi], cl
jne .err
inc esi
 
call ascii_to_byte
mov bh, al
 
ror ebx, 16
ret
 
.err:
xor ebx, ebx
ret
 
align 4 ; esi = ptr to str, output in eax
ascii_to_byte:
 
xor eax, eax
push ebx
 
.loop:
movzx ebx, byte[esi]
sub bl, '0'
jb .done
cmp bl, 9
ja .done
lea eax, [eax*4 + eax] ;
shl eax, 1 ; eax = eax * 10
add eax, ebx
inc esi
 
jmp .loop
 
.done:
pop ebx
ret
 
align 4
dword_to_ascii: ; edi = ptr where to write, eax is number
 
push edx ebx ecx
mov ebx, 10
xor ecx, ecx
 
@@:
xor edx, edx
div ebx
add edx, '0'
pushw dx
inc ecx
test eax, eax
jnz @r
 
@@:
popw ax
stosb
dec ecx
jnz @r
 
pop ecx ebx edx
ret
 
align 4
create_path: ; combine home_dir and work_dir strings into fpath
 
lea edi, [ebp + thread_data.fpath]
lea esi, [ebp + thread_data.home_dir]
mov ecx, 1024
.loop1:
lodsb
cmp al, 0x20
jb .next
stosb
loop .loop1
.next:
 
cmp byte[edi-1], '/'
jne @f
dec edi
@@:
 
lea esi, [ebp + thread_data.work_dir]
mov ecx, 1024
.loop2:
lodsb
cmp al, 0x20
jb .done
stosb
loop .loop2
 
.done:
xor al, al
stosb
ret
 
 
align 4
nextpasvport:
 
inc [pasv_port]
 
mov ax, [pasv_port]
cmp ax, [pasv_start]
jb .restart
cmp ax, [pasv_end]
ja .restart
 
ret
 
.restart:
pushw [pasv_start]
popw [pasv_port]
 
ret
 
 
align 4
open_datasock:
 
cmp [ebp + thread_data.mode], MODE_PASSIVE_OK
je .start
 
; If we are in active mode, it's time to open a data socket..
cmp [ebp + thread_data.mode], MODE_ACTIVE
jne .not_active
mov ecx, [ebp + thread_data.datasocketnum]
lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock
mcall connect
cmp eax, -1
jne .start
 
.socketerror:
add esp, 4
jmp socketerror
 
; If we are still in passive_wait, it's time we accept an incomming call..
.not_active:
cmp [ebp + thread_data.mode], MODE_PASSIVE_WAIT
jne .socketerror
 
.try_now:
mov ecx, [ebp + thread_data.passivesocknum]
lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock
mcall accept
cmp eax, -1
jne .pasv_ok
mov [ebp + thread_data.mode], MODE_PASSIVE_FAILED ; assume that we will fail
mcall 23, 200
mcall accept
cmp eax, -1
je .socketerror
.pasv_ok:
mov [ebp + thread_data.datasocketnum], eax
mov [ebp + thread_data.mode], MODE_PASSIVE_OK
mcall close ; [ebp + thread_data.passivesocknum]
mov [ebp + thread_data.passivesocknum], -1
invoke con_write_asciiz, str_datasock
 
.start:
ret
 
 
;------------------------------------------------
; "ABOR"
;
; This command aborts the current filetransfer.
;
;------------------------------------------------
align 4
cmdABOR:
 
or [ebp + thread_data.permissions], ABORT
sendFTP "250 Command succesul"
ret
 
;------------------------------------------------
; "CDUP"
;
; Change the directory to move up one level.
;
;------------------------------------------------
align 4
cmdCDUP:
 
test [ebp + thread_data.permissions], PERMISSION_CD
jz permission_denied
 
cmp byte [ebp + thread_data.work_dir+1], 0 ; are we in "/" ?
je .done ; if so, we cant go up..
 
; find the end of asciiz string work_dir
mov ecx, 1024
xor al, al
lea edi, [ebp + thread_data.work_dir]
repne scasb
; return 2 characters (right before last /)
sub edi, 3
; and now search backwards, for a '/'
mov al,'/'
neg ecx
add ecx, 1024
std
repne scasb
cld
; terminate the string here
mov byte[edi+2], 0
 
.done:
; Print the new working dir on the console
lea eax, [ebp + thread_data.work_dir]
invoke con_write_asciiz, eax
invoke con_write_asciiz, str_newline
 
sendFTP "250 Command succesul"
ret
 
;------------------------------------------------
; "CWD"
;
; Change Working Directory.
;
;------------------------------------------------
align 4
cmdCWD:
 
test [ebp + thread_data.permissions], PERMISSION_CD
jz permission_denied
 
; do we have enough parameters?
sub ecx, 4
jbe .err
 
; get ready to copy the path
add esi, 4
mov ecx, 1024
lea edi, [ebp + thread_data.work_dir]
 
; if received dir starts with '/', we will simply copy it
; If not, we will append the current path with the received path.
cmp byte [esi], '/'
je .copyloop
 
; Find the end of work_dir string.
xor al, al
.find_zero:
repne scasb
dec edi
 
; and now append work_dir with received string
mov ecx, 1024
 
; scan for end byte, or '.'
.copyloop:
lodsb
cmp al, 0x20
jb .done
;;; cmp al, '.' ; '..' means we must go up one dir TODO
;;; je .up
stosb
loop .copyloop
 
; now, now make sure it ends with '/', 0
.done:
cmp byte [edi-1], '/'
je @f
mov byte [edi], '/'
inc edi
@@:
mov byte [edi], 0
 
; Print the new working dir on the console
lea eax, [ebp + thread_data.work_dir]
invoke con_write_asciiz, eax
invoke con_write_asciiz, str_newline
 
sendFTP "250 Command succesful"
ret
 
.err:
sendFTP "550 Directory does not exist"
ret
 
;------------------------------------------------
; "DELE"
;
; Delete a file from the server.
;
;------------------------------------------------
align 4
cmdDELE:
 
test [ebp + thread_data.permissions], PERMISSION_DELETE
jz permission_denied
 
ret
 
;------------------------------------------------
; "LIST"
;
; List the files in the current working directory.
;
;------------------------------------------------
align 4
cmdLIST:
 
test [ebp + thread_data.permissions], PERMISSION_EXEC
jz permission_denied
 
call open_datasock
 
; Create fpath from home_dir and work_dir
call create_path
 
lea ebx, [ebp + thread_data.fpath]
invoke con_write_asciiz, ebx
invoke con_write_asciiz, str_newline
 
; Start the search
invoke file.find.first, ebx, str_mask, FA_READONLY+FA_FOLDER+FA_ARCHIVED;+FA_NORMAL
test eax, eax
jz .nosuchdir
 
lea edi, [ebp + thread_data.buffer]
.parse_file:
test eax, eax ; did we find a file?
jz .done
mov ebx, eax ; yes, save the descripter in ebx
 
; first, convert the attributes
test [ebx + FileInfoA.Attributes], FA_FOLDER
jnz .folder
 
test [ebx + FileInfoA.Attributes], FA_READONLY
jnz .readonly
 
mov eax, '-rw-'
stosd
jmp .attr
 
.folder:
mov eax, 'drwx'
stosd
jmp .attr
 
.readonly:
mov eax, '-r--'
stosd
 
.attr:
mov eax, 'rw-r'
stosd
mov ax, 'w-'
stosw
mov al, ' '
stosb
 
; now..
mov ax, '1 '
stosw
 
; now write owner, everything is owned by FTP, woohoo!
mov eax, 'FTP '
stosd
stosd
 
; now the filesize in ascii
mov eax, [ebx + FileInfoA.FileSizeLow]
call dword_to_ascii
mov al, ' '
stosb
 
; then date (month/day/year)
movzx eax, [ebx + FileInfoA.DateModify + FileDateTime.month]
cmp eax, 12
ja @f
mov eax, [months - 4 + 4*eax]
stosd
@@:
 
movzx eax, [ebx + FileInfoA.DateModify + FileDateTime.day]
call dword_to_ascii
mov al, ' '
stosb
 
movzx eax, [ebx + FileInfoA.DateModify + FileDateTime.year]
call dword_to_ascii
mov al, ' '
stosb
 
; and last but not least, filename
lea esi, [ebx + FileInfoA.FileName]
mov ecx, 264
.nameloop:
lodsb
test al, al
jz .namedone
stosb
loop .nameloop
 
; insert a cr lf
.namedone:
mov ax, 0x0a0d
stosw
 
test [ebp + thread_data.permissions], ABORT ; Did we receive ABOR command from client?
jnz abort_transfer
 
; check next file
invoke file.find.next, ebx
jmp .parse_file
 
; close file desc
.done:
invoke file.find.close, ebx ; ebx is descriptor of last file, eax will be -1 !!
 
; append the string with a 0
xor al, al
stosb
 
; Warn the client we're about to send the data
push edi
sendFTP "150 Here it comes.."
pop esi
 
; and send it to the client
mov ecx, [ebp + thread_data.datasocketnum] ; socket num
lea edx, [ebp + thread_data.buffer] ; buffer ptr
sub esi, edx ; length
xor edi, edi ; flags
mcall send
 
; close the data socket..
mov [ebp + thread_data.mode], MODE_NOTREADY
mcall close, [ebp + thread_data.datasocketnum]
 
sendFTP "226 Transfer OK"
ret
 
.nosuchdir:
sendFTP "550 Directory does not exist"
ret
 
;------------------------------------------------
; "NLST"
;
; List the filenames of the files in the current working directory.
;
;------------------------------------------------
align 4
cmdNLST:
 
test [ebp + thread_data.permissions], PERMISSION_EXEC
jz permission_denied
 
; TODO: same as list but simpler output format
 
ret
 
;------------------------------------------------
; "NOOP"
;
; No operation, just keep the connection alive.
;
;------------------------------------------------
align 4
cmdNOOP:
 
sendFTP "200 Command OK"
ret
 
;------------------------------------------------
; "PASS"
;
; Second phase of login process, client provides password.
;
;------------------------------------------------
align 4
cmdPASS:
 
; read the password from users.ini
lea edi, [ebp + thread_data.buffer + 512] ; temp pass
lea ebx, [ebp + thread_data.fpath] ; temp username
invoke ini.get_str, path2, ebx, str_pass, edi, 512, str_infinity
test eax, eax ; unable to read password? fail!
jnz .incorrect
cmp dword [edi], -1 ; no key, section or file found.. fail!
je .incorrect
cmp byte [edi], 0 ; zero password? ok!
je .ok
 
add esi, 5
sub ecx, 5
jbe .incorrect ; no password given? but hey, we need one! fail..
 
; compare with received password
repe cmpsb
cmp byte [esi-1], 0x20 ; printeable characters left?
jae .incorrect
cmp byte [edi-1], 0
jne .incorrect
 
.ok:
invoke ini.get_int, path2, ebx, str_mode, 0
mov [ebp + thread_data.permissions], eax
 
invoke con_write_asciiz, str_pass_ok
mov [ebp + thread_data.state], STATE_ACTIVE
sendFTP "230 You are now logged in"
ret
 
.2:
.incorrect:
invoke con_write_asciiz, str_pass_err
mov [ebp + thread_data.state], STATE_CONNECTED ; reset state
sendFTP "530 Login incorrect"
ret
 
.0:
sendFTP "503 Login with USER first"
ret
 
.3:
sendFTP "230 Already logged in"
ret
 
;------------------------------------------------
; "PASV"
;
; Initiate a passive dataconnection.
;
;------------------------------------------------
align 4
cmdPASV:
 
; cmp [ebp + thread_data.passivesocknum], -1
; je @f
; mcall close, [ebp + thread_data.passivesocknum] ; if there is still a socket open, close it
; @@:
 
; Open a new TCP socket
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
je socketerror
mov [ebp + thread_data.passivesocknum], eax
 
; Bind it to a known local port
mov [ebp + thread_data.datasock.sin_family], AF_INET4
mov [ebp + thread_data.datasock.sin_addr], 0
 
mov ecx, eax ; passivesocketnum
lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock
 
.next_port: ; TODO: break the endless loop
call nextpasvport
mov ax, [pasv_port]
xchg al, ah
mov [ebp + thread_data.datasock.sin_port], ax
 
mcall bind
cmp eax, -1
je .next_port
 
; And set it to listen!
mcall listen, , 1
cmp eax, -1
je socketerror
 
; Tell our thread we are ready to accept incoming calls
mov [ebp + thread_data.mode], MODE_PASSIVE_WAIT
 
; Now tell the client where to connect to in this format:
; 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
; where a1.a2.a3.a4 is the IP address and p1*256+p2 is the port number.
 
; '227 ('
lea edi, [ebp + thread_data.buffer]
mov eax, '227 '
stosd
mov al, '('
stosb
; ip
movzx eax, byte [serverip]
call dword_to_ascii
mov al, ','
stosb
movzx eax, byte [serverip+1]
call dword_to_ascii
mov al, ','
stosb
movzx eax, byte [serverip+2]
call dword_to_ascii
mov al, ','
stosb
movzx eax, byte [serverip+3]
call dword_to_ascii
mov al, ','
stosb
; port
movzx eax, byte [ebp + thread_data.datasock.sin_port]
call dword_to_ascii
mov al, ','
stosb
movzx eax, byte [ebp + thread_data.datasock.sin_port+1]
call dword_to_ascii
; ')', 13, 10, 0
mov eax, ')' + 0x000a0d00
stosd
 
lea esi, [edi - thread_data.buffer]
sub esi, ebp
mov ecx, [ebp + thread_data.socketnum]
lea edx, [ebp + thread_data.buffer]
xor edi, edi
mcall send
 
ret
 
;------------------------------------------------
; "PWD"
;
; Print the current working directory.
;
;------------------------------------------------
align 4
cmdPWD:
 
mov dword [ebp + thread_data.buffer], '257 '
mov byte [ebp + thread_data.buffer+4], '"'
 
lea edi, [ebp + thread_data.buffer+5]
lea esi, [ebp + thread_data.work_dir]
mov ecx, 1024
.loop:
lodsb
or al, al
jz .ok
stosb
dec ecx
jnz .loop
 
.ok:
mov dword [edi], '"' + 0x000a0d00 ; '"',13,10,0
lea esi, [edi - thread_data.buffer + 4]
sub esi, ebp
mov ecx, [ebp + thread_data.socketnum]
lea edx, [ebp + thread_data.buffer]
xor edi, edi
mcall send
 
; Print the new working dir on the console
lea eax, [ebp + thread_data.work_dir]
invoke con_write_asciiz, eax
invoke con_write_asciiz, str_newline
 
ret
 
;------------------------------------------------
; "PORT"
;
; Initiate an active dataconnection.
;
;------------------------------------------------
align 4
cmdPORT:
 
; PORT a1,a2,a3,a4,p1,p2
; IP address a1.a2.a3.a4, port p1*256+p2
 
; Convert the IP
lea esi, [esi+5]
mov cl, ','
call ip_to_dword
; And put it in datasock
mov [ebp + thread_data.datasock.sin_addr], ebx
 
; Now the same with portnumber
inc esi
call ascii_to_byte
mov byte[ebp + thread_data.datasock.sin_port], al
inc esi
call ascii_to_byte
mov byte[ebp + thread_data.datasock.sin_port+1], al
 
; We will open the socket, but do not connect yet!
mov [ebp + thread_data.datasock.sin_family], AF_INET4
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
je socketerror
 
mov [ebp + thread_data.datasocketnum], eax
mov [ebp + thread_data.mode], MODE_ACTIVE
 
sendFTP "225 Data connection open"
ret
 
;------------------------------------------------
; "QUIT"
;
; Close the connection with client.
;
;------------------------------------------------
align 4
cmdQUIT:
 
sendFTP "221 Bye!"
mcall close, [ebp + thread_data.datasocketnum]
mcall close, [ebp + thread_data.socketnum]
 
add esp, 4 ; get rid of call return address
jmp thread_exit ; now close this thread
 
 
;------------------------------------------------
; "RETR"
;
; Retrieve a file from the ftp server.
;
;------------------------------------------------
align 4
cmdRETR:
 
test [ebp + thread_data.permissions], PERMISSION_READ
jz permission_denied
 
cmp ecx, 1024 + 5
jae .cannot_open
 
sub ecx, 5
jb .cannot_open
 
call open_datasock
 
call create_path
dec edi
lea esi, [ebp + thread_data.buffer + 5]
mov ecx, 1024
cmp byte [esi], '/'
jne .loop
inc esi
.loop:
lodsb
cmp al, 0x20
jl .done
stosb
loop .loop
.done:
xor al, al
stosb
 
lea ebx, [ebp + thread_data.fpath]
invoke con_write_asciiz, ebx
invoke con_write_asciiz, str_newline
 
invoke file.open, ebx, O_READ
test eax, eax
jz .cannot_open
 
push eax
sendFTP "150 Here it comes.."
pop ebx
 
.read_more:
test [ebp + thread_data.permissions], ABORT
jnz abort_transfer
 
lea eax, [ebp + thread_data.buffer] ; FIXME: use another buffer!! if we receive something on control connection now, we screw up!
invoke file.read, ebx, eax, BUFFERSIZE
cmp eax, -1
je .cannot_open ; FIXME: this is not the correct error
 
invoke con_write_asciiz, str2
 
push eax ebx
mov esi, eax
mov ecx, [ebp + thread_data.datasocketnum]
lea edx, [ebp + thread_data.buffer]
xor edi, edi
mcall send
pop ebx ecx
cmp eax, -1
je socketerror ; FIXME: not the correct error
 
; cmp eax, ecx
; jne not_all_byes_sent ; TODO
 
cmp ecx, BUFFERSIZE
je .read_more
 
invoke file.close, ebx
 
invoke con_write_asciiz, str2b
 
mov [ebp + thread_data.mode], MODE_NOTREADY
mcall close, [ebp + thread_data.datasocketnum]
 
sendFTP "226 Transfer OK, closing connection"
ret
 
.cannot_open:
invoke con_set_flags, 0x0c
invoke con_write_asciiz, str_notfound
invoke con_set_flags, 0x07
 
sendFTP "550 No such file"
ret
 
 
 
;------------------------------------------------
; "STOR"
;
; Store a file on the server.
;
;------------------------------------------------
align 4
cmdSTOR:
 
test [ebp + thread_data.permissions], PERMISSION_WRITE
jz permission_denied
 
 
;;;;
test [ebp + thread_data.permissions], ABORT
jnz abort_transfer
 
;;;;
 
ret
 
;------------------------------------------------
; "SYST"
;
; Send information about the system.
;
;------------------------------------------------
align 4
cmdSYST:
 
sendFTP "215 UNIX type: L8"
ret
 
;------------------------------------------------
; "TYPE"
;
; Choose the file transfer type.
;
;------------------------------------------------
align 4
cmdTYPE:
 
cmp ecx, 6
jb parse_cmd.error
 
mov al, byte[esi+5]
and al, not 0x20
 
cmp al, 'A'
je .ascii
cmp al, 'E'
je .ebdic
cmp al, 'I'
je .image
cmp al, 'L'
je .local
 
jmp parse_cmd.error
 
.ascii:
mov [ebp + thread_data.type], TYPE_ASCII
jmp .subtype
 
.ebdic:
mov [ebp + thread_data.type], TYPE_EBDIC
 
.subtype:
cmp ecx, 8
jb .non_print
 
mov al, byte[esi+7]
and al, not 0x20
 
cmp al, 'N'
je .non_print
cmp al, 'T'
je .telnet
cmp al, 'C'
je .asacc
cmp al, 0x20
jb .non_print
 
jmp parse_cmd.error
 
.non_print:
or [ebp + thread_data.type], TYPE_NP
jmp .ok
 
.telnet:
or [ebp + thread_data.type], TYPE_TELNET
jmp .ok
 
.asacc:
or [ebp + thread_data.type], TYPE_ASA
jmp .ok
 
.image:
mov [ebp + thread_data.type], TYPE_IMAGE
jmp .ok
 
.local:
cmp ecx, 8
jb parse_cmd.error
 
mov al, byte[esi+7]
sub al, '0'
jb parse_cmd.error ; FIXME: this is not the correct errormessage
cmp al, 9
ja parse_cmd.error ; FIXME
or al, TYPE_LOCAL
mov [ebp + thread_data.type], al
 
.ok:
sendFTP "200 Command ok"
ret
 
;------------------------------------------------
; "USER"
;
; Login to the server, step one of two. ;;; TODO: prevent buffer overflow!
;
;------------------------------------------------
align 4
cmdUSER:
 
lea esi, [esi + 5]
lea edi, [ebp + thread_data.fpath] ; temp buffer for username
.loop:
lodsb
stosb
cmp al, 0x20
jae .loop
mov byte [edi-1], 0
 
lea esi, [ebp + thread_data.fpath]
lea eax, [ebp + thread_data.home_dir]
invoke ini.get_str, path2, esi, str_home, eax, 1024, str_infinity
cmp eax, -1
je .login_fail
cmp dword [esi], -1
je .login_fail
 
mov word [ebp + thread_data.work_dir], "/" ; "/", 0
 
invoke con_write_asciiz, str_logged_in
mov [ebp + thread_data.state], STATE_LOGIN
.sendstr:
sendFTP "331 Please specify the password"
ret
 
.login_fail:
invoke con_write_asciiz, str_pass_err
mov [ebp + thread_data.state], STATE_LOGIN_FAIL
jmp .sendstr
 
align 4
.2:
sendFTP "530 Can't change to another user"
ret
/programs/network/ftpd/ftpd.asm
0,0 → 1,455
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ftpd.asm - FTP Daemon for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
DEBUG = 0 ; if set to one, program will run in a single thread
 
BUFFERSIZE = 8192
 
; using multiple's of 4
STATE_CONNECTED = 0*4
STATE_LOGIN = 1*4
STATE_LOGIN_FAIL = 2*4 ; When an invalid username was given
STATE_ACTIVE = 3*4
 
TYPE_UNDEF = 0
 
TYPE_ASCII = 00000100b
TYPE_EBDIC = 00001000b
; subtypes for ascii & ebdic (np = default)
TYPE_NP = 00000001b ; non printable
TYPE_TELNET = 00000010b
TYPE_ASA = 00000011b
 
TYPE_IMAGE = 01000000b ; binary data
TYPE_LOCAL = 10000000b ; bits per byte must be specified
; lower 4 bits will hold this value
MODE_NOTREADY = 0
MODE_ACTIVE = 1
MODE_PASSIVE_WAIT = 2
MODE_PASSIVE_OK = 3
MODE_PASSIVE_FAILED = 4
 
PERMISSION_EXEC = 1b ; LIST
PERMISSION_READ = 10b
PERMISSION_WRITE = 100b
PERMISSION_DELETE = 1000b
PERMISSION_CD = 10000b ; Change Directory
 
ABORT = 1 shl 31
 
format binary as ""
 
use32
 
org 0x0
 
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem+0x1000 ; required memory
dd mem+0x1000 ; stack pointer
dd params ; parameters
dd path ; path
 
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
include '../struct.inc'
include '../libio.inc'
 
include '../network.inc'
 
macro sendFTP str {
local string, length
xor edi, edi
mcall send, [ebp + thread_data.socketnum], string, length
 
iglobal
string db str, 13, 10
length = $ - string
\}
}
 
include 'commands.inc'
 
start:
mcall 68, 11 ; init heap
mcall 40, 1 shl 7 ; we only want network events
 
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
 
; find path to main settings file (ftpd.ini)
mov edi, path ; Calculate the length of zero-terminated string
xor al, al
mov ecx, 1024
repne scasb
dec edi
mov esi, str_ini ; append it with '.ini', 0
movsd
movsb
 
; now create the second path (users.ini)
std
mov al, '/'
repne scasb
lea ecx, [edi - path + 2]
cld
mov esi, path
mov edi, path2
rep movsb
mov esi, str_users
movsd
movsd
movsw
 
; initialize console
invoke con_start, 1
invoke con_init, -1, -1, -1, -1, title
 
; get settings from ini
invoke ini.get_str, path, str_ftpd, str_ip, ini_buf, 16, 0
mov esi, ini_buf
mov cl, '.'
call ip_to_dword
mov [serverip], ebx
 
invoke ini.get_int, path, str_ftpd, str_port, 21
xchg al, ah
mov [sockaddr1.port], ax
 
xchg al, ah
invoke con_printf, str1, eax
add esp, 8
 
; open listening socket
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
je sock_err
mov [socketnum], eax
 
invoke con_write_asciiz, str2
 
; mcall setsockopt, [socketnum], SOL_SOCKET, SO_REUSEADDR, &yes,
; cmp eax, -1
; je opt_err
 
mcall bind, [socketnum], sockaddr1, sockaddr1.length
cmp eax, -1
je bind_err
 
invoke con_write_asciiz, str2
 
invoke ini.get_int, path, str_ftpd, str_conn, 1 ; Backlog (max connections)
mov edx, eax
 
invoke con_write_asciiz, str2
 
mcall listen, [socketnum]
cmp eax, -1
je listen_err
 
invoke con_write_asciiz, str2b
 
invoke ini.get_int, path, str_pasv, str_start, 2000
mov [pasv_start], ax
invoke ini.get_int, path, str_pasv, str_end, 5000
mov [pasv_end], ax
 
mov [alive], 1
 
mainloop:
mcall 23, 100 ; Wait here for incoming connections on the base socket (socketnum)
; One second timeout, we will use this to check if console is still working
 
test eax, eax ; network event?
jz .checkconsole
 
if DEBUG
jmp threadstart
else
mcall 51, 1, threadstart, 0 ; Start a new thread for every incoming connection
; NOTE: upon initialisation of the thread, stack will not be available!
end if
jmp mainloop
 
.checkconsole:
 
invoke con_get_flags ; Is console still running?
test eax, 0x0200
jz mainloop
mcall close, [socketnum] ; kill the listening socket
mov [alive], 0
mcall -1 ; and exit
 
diff16 "threadstart", 0, $
 
threadstart:
;;; mcall 68, 11 ; init heap
mcall 68, 12, sizeof.thread_data ; allocate the thread data struct
test eax, eax
je exit
 
lea esp, [eax + thread_data.stack] ; init stack
mov ebp, eax
 
mcall 40, 1 shl 7 ; we only want network events for this thread
 
lea ebx, [ebp + thread_data.buffer] ; get information about the current process
or ecx, -1
mcall 9
mov eax, dword [ebp + thread_data.buffer + 30] ; PID is at offset 30
mov [ebp + thread_data.pid], eax
 
invoke con_set_flags, 0x03
invoke con_printf, str8, [ebp + thread_data.pid] ; print on the console that we have created the new thread successfully
add esp, 8 ; balance stack
invoke con_set_flags, 0x07
 
mcall accept, [socketnum], sockaddr1, sockaddr1.length ; time to accept the awaiting connection..
cmp eax, -1
je thread_exit
mov [ebp + thread_data.socketnum], eax
 
if DEBUG
mcall close, [socketnum] ; close the listening socket
end if
 
mov [ebp + thread_data.state], STATE_CONNECTED
mov [ebp + thread_data.permissions], 0
mov [ebp + thread_data.mode], MODE_NOTREADY
lea eax, [ebp + thread_data.buffer]
mov [ebp + thread_data.buffer_ptr], eax
mov [ebp + thread_data.passivesocknum], -1
 
sendFTP "220 Welcome to KolibriOS FTP daemon"
 
diff16 "threadloop", 0, $
threadloop:
; Check if our socket is still connected
mcall send, [ebp + thread_data.socketnum], 0, 0 ; Try to send zero bytes, if socket is closed, this will return -1
cmp eax, -1
je thread_exit
 
cmp [alive], 0 ; Did main thread take a run for it?
je thread_exit
 
mcall 10 ; Wait for network event
 
cmp [ebp + thread_data.mode], MODE_PASSIVE_WAIT
jne .not_passive
mov ecx, [ebp + thread_data.passivesocknum]
lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock
mcall accept
cmp eax, -1
je .not_passive
mov [ebp + thread_data.datasocketnum], eax
mov [ebp + thread_data.mode], MODE_PASSIVE_OK
mcall close ; [ebp + thread_data.passivesocknum]
mov [ebp + thread_data.passivesocknum], -1
 
invoke con_write_asciiz, str_datasock
.not_passive:
 
mov ecx, [ebp + thread_data.socketnum]
mov edx, [ebp + thread_data.buffer_ptr]
mov esi, sizeof.thread_data.buffer ;;; FIXME
mcall recv
inc eax ; error? (-1)
jz threadloop
dec eax ; 0 bytes read?
jz threadloop
 
mov edi, [ebp + thread_data.buffer_ptr]
add [ebp + thread_data.buffer_ptr], eax
 
; Check if we received a newline character, if not, wait for more data
mov ecx, eax
mov al, 13
repne scasb
jne threadloop
 
; We got a command!
mov byte [edi + 1], 0 ; append string with zero byte
lea esi, [ebp + thread_data.buffer]
mov ecx, [ebp + thread_data.buffer_ptr]
sub ecx, esi
mov [ebp + thread_data.buffer_ptr], esi ; reset buffer ptr
 
invoke con_set_flags, 0x02 ; print received data to console (in green color)
invoke con_write_asciiz, str_newline
invoke con_write_asciiz, esi
invoke con_set_flags, 0x07
 
push threadloop
jmp parse_cmd
 
listen_err:
invoke con_set_flags, 0x0c ; print errors in red
invoke con_write_asciiz, str3
jmp done
 
bind_err:
invoke con_set_flags, 0x0c ; print errors in red
invoke con_write_asciiz, str4
jmp done
 
sock_err:
invoke con_set_flags, 0x0c ; print errors in red
invoke con_write_asciiz, str6
jmp done
 
done:
invoke con_exit, 0
exit:
mcall -1
 
 
thread_exit:
invoke con_set_flags, 0x03 ; print thread info in blue
invoke con_printf, str_bye, [ebp + thread_data.pid] ; print on the console that we are about to kill the thread
add esp, 8 ; balance stack
mcall 68, 13, ebp ; free the memory
mcall -1 ; and kill the thread
 
 
; initialized data
 
title db 'KolibriOS FTP daemon 0.1', 0
str1 db 'Starting FTP daemon on port %u.', 0
str2 db '.', 0
str2b db ' OK!',10,0
str3 db 'Listen error',10,0
str4 db 10,'ERROR: local port is already in use.',10,0
;str5 db 'Setsockopt error.',10,10,0
str6 db 'ERROR: Could not open socket.',10,0
str7 db 'Got data!',10,10,0
str8 db 10,'Thread %d created',10,0
str_bye db 10,'Thread %d killed',10,0
 
str_logged_in db 'Login ok',10,0
str_pass_ok db 'Password ok',10,0
str_pass_err db 'Password/Username incorrect',10,0
str_pwd db 'Current directory is "%s"\n',0
str_err2 db 'ERROR: cannot open the directory.',10,0
str_datasock db 'Passive data socket connected.',10,0
str_notfound db 'ERROR: file not found.',10,0
str_sockerr db 'ERROR: socket error.',10,0
 
str_newline db 10, 0
str_mask db '*', 0
str_infinity db 0xff, 0xff, 0xff, 0xff, 0
 
months dd 'Jan '
dd 'Feb '
dd 'Mar '
dd 'Apr '
dd 'May '
dd 'Jun '
dd 'Jul '
dd 'Aug '
dd 'Sep '
dd 'Oct '
dd 'Nov '
dd 'Dec '
 
str_users db 'users'
str_ini db '.ini', 0
str_port db 'port', 0
str_ftpd db 'ftpd', 0
str_conn db 'conn', 0
str_ip db 'ip', 0
str_pass db 'pass', 0
str_home db 'home', 0
str_mode db 'mode', 0
str_pasv db 'pasv', 0
str_start db 'start', 0
str_end db 'end', 0
 
 
sockaddr1:
dw AF_INET4
.port dw 0
.ip dd 0
rb 10
.length = $ - sockaddr1
 
; import
 
align 4
@IMPORT:
 
diff16 "import", 0, $
 
library console, 'console.obj',\
libini, 'libini.obj', \
libio, 'libio.obj'
 
import console,\
con_start, 'START',\
con_init, 'con_init',\
con_write_asciiz, 'con_write_asciiz',\
con_exit, 'con_exit',\
con_gets, 'con_gets',\
con_cls, 'con_cls',\
con_printf, 'con_printf',\
con_getch2, 'con_getch2',\
con_set_cursor_pos, 'con_set_cursor_pos',\
con_set_flags, 'con_set_flags',\
con_get_flags, 'con_get_flags'
 
import libini,\
ini.get_str, 'ini_get_str',\
ini.get_int, 'ini_get_int'
 
import libio,\
file.size, 'file_size',\
file.open, 'file_open',\
file.read, 'file_read',\
file.close, 'file_close',\
file.find.first, 'file_find_first',\
file.find.next, 'file_find_next',\
file.find.close, 'file_find_close'
 
 
IncludeIGlobals
 
 
i_end:
 
diff16 "i_end", 0, $
 
; uninitialised data
 
socketnum dd ?
path rb 1024
path2 rb 1024
params rb 1024
serverip dd ?
pasv_start dw ?
pasv_end dw ?
pasv_port dw ?
 
ini_buf rb 3*4+3+1
 
alive db ?
 
mem:
 
 
/programs/network/ftpd/ftpd.ini
0,0 → 1,8
[ftpd]
port=21
conn=10
ip=127.0.0.1
 
[pasv]
start=2000
end=5000
/programs/network/ftpd/users.ini
0,0 → 1,20
; Access modes
;
; List = 1
; Read = 2
; Write = 4
; Delete = 8
; Change directory = 16
 
 
[anonymous]
; leavy pass empty to disable it
pass=
home=/rd/1/
mode=3
 
[test]
pass=1234
home=/rd/1/
mode=31
 
/programs/network/ftpd
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network/icmp/icmp.inc
0,0 → 1,77
; ICMP types & codes
 
ICMP_ECHOREPLY equ 0 ; echo reply message
 
ICMP_UNREACH equ 3
ICMP_UNREACH_NET equ 0 ; bad net
ICMP_UNREACH_HOST equ 1 ; bad host
ICMP_UNREACH_PROTOCOL equ 2 ; bad protocol
ICMP_UNREACH_PORT equ 3 ; bad port
ICMP_UNREACH_NEEDFRAG equ 4 ; IP_DF caused drop
ICMP_UNREACH_SRCFAIL equ 5 ; src route failed
ICMP_UNREACH_NET_UNKNOWN equ 6 ; unknown net
ICMP_UNREACH_HOST_UNKNOWN equ 7 ; unknown host
ICMP_UNREACH_ISOLATED equ 8 ; src host isolated
ICMP_UNREACH_NET_PROHIB equ 9 ; prohibited access
ICMP_UNREACH_HOST_PROHIB equ 10 ; ditto
ICMP_UNREACH_TOSNET equ 11 ; bad tos for net
ICMP_UNREACH_TOSHOST equ 12 ; bad tos for host
ICMP_UNREACH_FILTER_PROHIB equ 13 ; admin prohib
ICMP_UNREACH_HOST_PRECEDENCE equ 14 ; host prec vio.
ICMP_UNREACH_PRECEDENCE_CUTOFF equ 15 ; prec cutoff
 
ICMP_SOURCEQUENCH equ 4 ; Packet lost, slow down
 
ICMP_REDIRECT equ 5 ; shorter route, codes:
ICMP_REDIRECT_NET equ 0 ; for network
ICMP_REDIRECT_HOST equ 1 ; for host
ICMP_REDIRECT_TOSNET equ 2 ; for tos and net
ICMP_REDIRECT_TOSHOST equ 3 ; for tos and host
 
ICMP_ALTHOSTADDR equ 6 ; alternate host address
ICMP_ECHO equ 8 ; echo service
ICMP_ROUTERADVERT equ 9 ; router advertisement
ICMP_ROUTERADVERT_NORMAL equ 0 ; normal advertisement
ICMP_ROUTERADVERT_NOROUTE_COMMON equ 16 ; selective routing
 
ICMP_ROUTERSOLICIT equ 10 ; router solicitation
ICMP_TIMXCEED equ 11 ; time exceeded, code:
ICMP_TIMXCEED_INTRANS equ 0 ; ttl==0 in transit
ICMP_TIMXCEED_REASS equ 1 ; ttl==0 in reass
 
ICMP_PARAMPROB equ 12 ; ip header bad
ICMP_PARAMPROB_ERRATPTR equ 0 ; error at param ptr
ICMP_PARAMPROB_OPTABSENT equ 1 ; req. opt. absent
ICMP_PARAMPROB_LENGTH equ 2 ; bad length
 
ICMP_TSTAMP equ 13 ; timestamp request
ICMP_TSTAMPREPLY equ 14 ; timestamp reply
ICMP_IREQ equ 15 ; information request
ICMP_IREQREPLY equ 16 ; information reply
ICMP_MASKREQ equ 17 ; address mask request
ICMP_MASKREPLY equ 18 ; address mask reply
ICMP_TRACEROUTE equ 30 ; traceroute
ICMP_DATACONVERR equ 31 ; data conversion error
ICMP_MOBILE_REDIRECT equ 32 ; mobile host redirect
ICMP_IPV6_WHEREAREYOU equ 33 ; IPv6 where-are-you
ICMP_IPV6_IAMHERE equ 34 ; IPv6 i-am-here
ICMP_MOBILE_REGREQUEST equ 35 ; mobile registration req
ICMP_MOBILE_REGREPLY equ 36 ; mobile registreation reply
ICMP_SKIP equ 39 ; SKIP
 
ICMP_PHOTURIS equ 40 ; Photuris
ICMP_PHOTURIS_UNKNOWN_INDEX equ 1 ; unknown sec index
ICMP_PHOTURIS_AUTH_FAILED equ 2 ; auth failed
ICMP_PHOTURIS_DECRYPT_FAILED equ 3 ; decrypt failed
 
 
 
virtual at 0
ICMP_Packet:
.Type db ?
.Code db ?
.Checksum dw ?
.Identifier dw ?
.SequenceNumber dw ?
.Data:
end virtual
/programs/network/icmp/ping.asm
0,0 → 1,256
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ping.asm - ICMP echo client for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
format binary as ""
 
use32
org 0x0
 
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd I_END ; initialized size
dd mem ; required memory
dd mem ; stack pointer
dd s ; parameters
dd 0 ; path
 
 
BUFFERSIZE equ 1500
; useful includes
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
include '../network.inc'
 
include 'icmp.inc'
 
 
start:
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
; initialize console
push 1
call [con_start]
push title
push 25
push 80
push 25
push 80
call [con_init]
; main loop
cmp byte[s], 0
jne resolve
main:
; write prompt
push str2
call [con_write_asciiz]
; read string
mov esi, s
push 256
push esi
call [con_gets]
; check for exit
test eax, eax
jz done
cmp byte [esi], 10
jz done
; delete terminating '\n'
push esi
@@:
lodsb
test al, al
jnz @b
mov byte [esi-2], al
pop esi
 
resolve:
; resolve name
push esp ; reserve stack place
push esp ; fourth parameter
push 0 ; third parameter
push 0 ; second parameter
push s ; first parameter
call [getaddrinfo]
pop esi
; test for error
test eax, eax
jnz fail
 
; convert IP address to decimal notation
mov eax, [esi+addrinfo.ai_addr]
mov eax, [eax+sockaddr_in.sin_addr]
mov [sockaddr1.ip], eax
push eax
call [inet_ntoa]
; write result
mov [ip_ptr], eax
 
push eax
 
; free allocated memory
push esi
call [freeaddrinfo]
 
push str4
call [con_write_asciiz]
 
mcall socket, AF_INET4, SOCK_RAW, IPPROTO_ICMP
cmp eax, -1
jz fail2
mov [socketnum], eax
 
mcall connect, [socketnum], sockaddr1, 18
 
mcall 40, 1 shl 7 ; + 7
; call [con_cls]
 
mov [count], 4
 
mainloop:
push str3
call [con_write_asciiz]
push [ip_ptr]
call [con_write_asciiz]
 
mcall 26,9
mov [time_reference], eax
mcall send, [socketnum], icmp_packet, icmp_packet.length, 0
 
mcall 23, 300 ; 3 seconds time-out
mcall 26,9
neg [time_reference]
add [time_reference], eax
 
mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, 0
cmp eax, -1
je .no_response
 
; validate the packet
lea esi, [buffer_ptr + ICMP_Packet.Data]
mov edi, icmp_packet.data
mov ecx, 32/4
repe cmpsd
jne .miscomp
 
push [time_reference]
push str7
call [con_printf]
 
jmp continue
 
.miscomp:
sub edi, icmp_packet.data
push edi
push str9
call [con_printf]
jmp continue
 
.no_response:
push str8
call [con_write_asciiz]
 
continue:
dec [count]
jz done
mcall 5, 100 ; wait a second
inc [icmp_packet.id]
jmp mainloop
 
 
 
done:
push str10
call [con_write_asciiz]
call [con_getch2]
push 1
call [con_exit]
exit:
mcall -1
 
fail:
push str5
call [con_write_asciiz]
jmp done
fail2:
push str6
call [con_write_asciiz]
jmp done
 
 
; data
title db 'ICMP - echo client',0
str2 db '> ',0
str3 db 'Ping to ',0
str4 db 10,0
str5 db 'Name resolution failed.',10,0
str6 db 'Could not open socket',10,0
str7 db ' time= %u0ms',10,0
str8 db ' timeout!',10,0
str9 db ' miscompare at offset %u',10,0
str10 db 10,'Press any key to exit',0
 
sockaddr1:
dw AF_INET4
.port dw 0
.ip dd 0
rb 10
 
time_reference dd ?
ip_ptr dd ?
count dd ?
 
 
; import
align 4
@IMPORT:
 
library network, 'network.obj', console, 'console.obj'
import network, \
getaddrinfo, 'getaddrinfo', \
freeaddrinfo, 'freeaddrinfo', \
inet_ntoa, 'inet_ntoa'
 
import console, \
con_start, 'START', \
con_init, 'con_init', \
con_write_asciiz, 'con_write_asciiz', \
con_printf, 'con_printf', \
con_exit, 'con_exit', \
con_gets, 'con_gets',\
con_cls, 'con_cls',\
con_getch2, 'con_getch2',\
con_set_cursor_pos, 'con_set_cursor_pos'
 
socketnum dd ?
 
icmp_packet: db 8 ; type
db 0 ; code
dw 0 ;
.id dw 0x0000 ; identifier
.seq dw 0x0001 ; sequence number
.data db 'abcdefghijklmnopqrstuvwxyz012345678'
.length = $ - icmp_packet
 
I_END:
 
buffer_ptr rb BUFFERSIZE
 
s rb 1024
rb 4096 ; stack
mem:
/programs/network/icmp
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network/ircc/encodings.inc
0,0 → 1,317
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
get_next_byte:
; Load next byte from the packet, translating to cp866 if necessary
; At input esi = pointer to data, edx = limit of data
; Output is either (translated) byte in al with CF set or CF cleared.
mov eax, [encoding]
jmp [get_byte_table+eax*4]
 
get_byte_cp866:
cmp esi, edx
jae .nothing
lodsb
.nothing:
ret
 
get_byte_cp1251:
cmp esi, edx
jae .nothing
lodsb
cmp al, 0x80
jb @f
and eax, 0x7F
mov al, [cp1251_table+eax]
@@:
stc
.nothing:
ret
 
get_byte_utf8:
; UTF8 decoding is slightly complicated.
; One character can occupy one or more bytes.
; The boundary in packets theoretically can be anywhere in data,
; so this procedure keeps internal state between calls and handles
; one byte at a time, looping until character is read or packet is over.
; Globally, there are two distinct tasks: decode byte sequence to unicode char
; and convert this unicode char to our base encoding (that is cp866).
; 1. Check that there are data.
cmp esi, edx
jae .nothing
; 2. Load byte.
lodsb
movzx ecx, al
; 3. Bytes in an UTF8 sequence can be of any of three types.
; If most significant bit is cleared, sequence is one byte and usual ASCII char.
; First byte of a sequence must be 11xxxxxx, other bytes are 10yyyyyy.
and al, 0xC0
jns .single_byte
jp .first_byte
; 4. This byte is not first in UTF8 sequence.
; 4a. Check that the sequence was started. If no, it is invalid byte
; and we simply ignore it.
cmp [utf8_bytes_rest], 0
jz get_byte_utf8
; 4b. Otherwise, it is really next byte and it gives some more bits of char.
mov eax, [utf8_char]
shl eax, 6
lea eax, [eax+ecx-0x80]
; 4c. Decrement number of bytes rest in the sequence.
; If it goes to zero, character is read, so return it.
dec [utf8_bytes_rest]
jz .got_char
mov [utf8_char], eax
jmp get_byte_utf8
; 5. If the byte is first in UTF8 sequence, calculate the number of leading 1s
; - it equals total number of bytes in the sequence; some other bits rest for
; leading bits in the character.
.first_byte:
mov eax, -1
@@:
inc eax
add cl, cl
js @b
mov [utf8_bytes_rest], eax
xchg eax, ecx
inc ecx
shr al, cl
mov [utf8_char], eax
jmp get_byte_utf8
; 6. If the byte is ASCII char, it is the character.
.single_byte:
xchg eax, ecx
.got_char:
; We got the character, now abandon a possible sequence in progress.
and [utf8_bytes_rest], 0
; Now second task. The unicode character is in eax, and now we shall convert it
; to cp866.
cmp eax, 0x80
jb .done
; 0x410-0x43F -> 0x80-0xAF, 0x440-0x44F -> 0xE0-0xEF, 0x401 -> 0xF0, 0x451 -> 0xF1
cmp eax, 0x401
jz .YO
cmp eax, 0x451
jz .yo
cmp eax, 0x410
jb .unrecognized
cmp eax, 0x440
jb .part1
cmp eax, 0x450
jae .unrecognized
sub al, (0x40-0xE0) and 0xFF
ret
.part1:
sub al, 0x10-0x80
.nothing:
.done:
ret
.unrecognized:
mov al, '?'
stc
ret
.YO:
mov al, 0xF0
stc
ret
.yo:
mov al, 0xF1
stc
ret
 
 
 
print_character:
 
pusha
 
cmp bl, 13 ; line beginning
jne nobol
 
mov ecx, [pos]
inc ecx
boll1:
dec ecx
mov eax, ecx
xor edx, edx
mov ebx, [textbox_width]
div ebx
test edx, edx
jnz boll1
mov [pos], ecx
jmp newdata
nobol:
 
cmp bl, 10 ; line down
jne nolf
 
addx1:
inc [pos]
mov eax, [pos]
xor edx, edx
mov ecx, [textbox_width]
div ecx
test edx, edx
jnz addx1
mov eax, [pos]
jmp cm1
nolf:
no_lf_ret:
 
 
cmp bl, 15 ; character
jbe newdata
 
mov eax, [irc_data]
shl eax, 8
mov al, bl
mov [irc_data], eax
 
mov eax, [pos]
;---- draw data
pusha
 
and ebx, 0xff
add eax, [text_start]
mov [eax], bl
 
popa
;---- draw data
 
mov eax, [pos]
inc eax
cm1:
mov ebx, [scroll+4]
imul ebx, [textbox_width]
cmp eax, ebx
jb noeaxz
 
mov esi, [text_start]
add esi, [textbox_width]
 
mov edi, [text_start]
mov ecx, ebx
rep movsb
 
mov esi, [text_start]
mov ecx, [textbox_width]
imul ecx, 61
add esi, ecx
 
mov edi, [text_start]
mov ecx, [textbox_width]
imul ecx, 60
add edi, ecx
mov ecx, ebx
rep movsb
 
mov eax, ebx
sub eax, [textbox_width]
noeaxz:
mov [pos], eax
 
newdata:
mov eax, [window_print]
or [eax + window.flags], FLAG_UPDATED
 
popa
ret
 
 
 
recode_to_cp866:
rep movsb
ret
 
recode_to_cp1251:
xor eax, eax
jecxz .nothing
.loop:
lodsb
cmp al,0x80
jb @f
mov al, [cp866_table-0x80+eax]
@@: stosb
loop .loop
.nothing:
ret
 
recode_to_utf8:
jecxz .nothing
.loop:
lodsb
cmp al, 0x80
jb .single_byte
and eax, 0x7F
mov ax, [utf8_table+eax*2]
stosw
loop .loop
ret
.single_byte:
stosb
loop .loop
.nothing:
ret
 
recode:
mov eax, [encoding]
jmp [recode_proc+eax*4]
 
 
 
encoding dd UTF8
recode_proc dd recode_to_cp866, recode_to_cp1251, recode_to_utf8
get_byte_table dd get_byte_cp866, get_byte_cp1251, get_byte_utf8
 
 
cp1251_table:
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; 8
db '?','?','?','?','?',$F9,'?','?' , '?','?','?','?','?','?','?','?' ; 9
db '?',$F6,$F7,'?',$FD,'?','?','?' , $F0,'?',$F2,'?','?','?','?',$F4 ; A
db $F8,'?','?','?','?','?','?',$FA , $F1,$FC,$F3,'?','?','?','?',$F5 ; B
db $80,$81,$82,$83,$84,$85,$86,$87 , $88,$89,$8A,$8B,$8C,$8D,$8E,$8F ; C
db $90,$91,$92,$93,$94,$95,$96,$97 , $98,$99,$9A,$9B,$9C,$9D,$9E,$9F ; D
db $A0,$A1,$A2,$A3,$A4,$A5,$A6,$A7 , $A8,$A9,$AA,$AB,$AC,$AD,$AE,$AF ; E
db $E0,$E1,$E2,$E3,$E4,$E5,$E6,$E7 , $E8,$E9,$EA,$EB,$EC,$ED,$EE,$EF ; F
 
; 0 1 2 3 4 5 6 7 8 9 A B C D E F
 
utf8_table:
times 80h dw 0x98C3 ; default placeholder
 
; 0x80-0xAF -> 0x90D0-0xBFD0
repeat 0x30
store byte 0xD0 at utf8_table+2*(%-1)
store byte 0x90+%-1 at utf8_table+2*%-1
end repeat
 
; 0xE0-0xEF -> 0x80D1-0x8FD1
repeat 0x10
store byte 0xD1 at utf8_table+2*(0xE0-0x80+%-1)
store byte 0x80+%-1 at utf8_table+2*(0xE0-0x80+%)-1
end repeat
 
; 0xF0 -> 0x81D0, 0xF1 -> 0x91D1
store dword 0x91D181D0 at utf8_table+2*(0xF0-0x80)
 
cp866_table:
db $C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7 , $C8,$C9,$CA,$CB,$CC,$CD,$CE,$CF ; 8
db $D0,$D1,$D2,$D3,$D4,$D5,$D6,$D7 , $D8,$D9,$DA,$DB,$DC,$DD,$DE,$DF ; 9
db $E0,$E1,$E2,$E3,$E4,$E5,$E6,$E7 , $E8,$E9,$EA,$EB,$EC,$ED,$EE,$EF ; A
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; B
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; C
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; D
db $F0,$F1,$F2,$F3,$F4,$F5,$F6,$F7 , $F8,$F9,$FA,$FB,$FC,$FD,$FE,$FF ; E
db $A8,$B8,$AA,$BA,$AF,$BF,$A1,$A2 , $B0,$95,$B7,'?',$B9,$A4,'?','?' ; F
 
; 0 1 2 3 4 5 6 7 8 9 A B C D E F
 
/programs/network/ircc/gui.inc
0,0 → 1,316
draw_window:
 
pusha
 
mcall 9, thread_info, -1 ; get current window size
mov eax, dword[thread_info+42] ; window xsize
mov ebx, dword[thread_info+46] ; ysize
mov edx, dword[thread_info+62] ; work area xsize
mov esi, dword[thread_info+66] ; ysize
sub eax, edx
sub ebx, esi
 
cmp edx, WIN_MIN_X
jae .x_ok
mov edx, WIN_MIN_X
.x_ok:
mov [xsize], edx
add edx, eax
 
cmp esi, WIN_MIN_Y
jae .y_ok
mov esi, WIN_MIN_Y
.y_ok:
mov [ysize], esi
add esi, ebx
mcall 67, -1, -1 ; set the new sizes
 
mcall 12, 1
xor eax, eax ; draw window
mov ebx, WIN_MIN_X
mov ecx, WIN_MIN_Y
mov edx, [colors.work]
add edx, 0x33000000
mov edi, str_programname
mcall
mcall 12, 2 ;; when do we actually need this??
 
mov ebx, [xsize]
mov ecx, [ysize]
sub cx, 15 ;;;;
push cx
shl ecx, 16
pop cx
mov edx, [colors.work_graph]
mcall 38 ; draw line
 
mov ecx, TOP_Y SHL 16 + TOP_Y
mcall
 
mov edi, [window_open]
cmp [edi + window.type], WINDOWTYPE_CHANNEL
jne .not_channel
 
; draw a vertical separator line
mov ebx, [xsize]
sub ebx, USERLIST_X + SCROLLBAR_WIDTH + 3
push bx
shl ebx, 16
pop bx
mov ecx, [ysize]
add ecx, TOP_Y SHL 16 -(15) ;;;;
mcall
 
call redraw_channel_list
 
.not_channel:
mov edx, [edi + window.data_ptr]
add edx, window_data.text
call draw_channel_text
 
; editbox
 
mov eax, [ysize]
sub eax, 12 ;;;;;;
mov [edit1.top], eax
 
mov eax, [xsize]
mov [edit1.width], eax
 
push dword edit1
call [edit_box_draw]
 
; tabs
 
call draw_windownames
 
popa
ret
 
 
 
redraw_channel_list:
 
; First, calculate scrollbar
 
mov ebx, [window_open]
mov eax, [ebx + window.users] ; number of users in the open window
mov [scroll1.max_area], eax
 
mov eax, [ysize]
sub eax, TOP_Y + 15 ;;;;
push eax
mov [scroll1.y_size], ax
 
mov eax, [xsize]
sub eax, SCROLLBAR_WIDTH
mov [scroll1.x_pos], ax
 
pop eax ; scrollbar height
xor edx, edx
mov ecx, 10
div ecx
mov [scroll1.cur_area], eax
 
; Do we need a scrollbar?
cmp eax, [scroll1.max_area]
jae .noscroll
 
; Is the current position greater then the max position?
cmp eax, [scroll1.position]
ja @f
mov [scroll1.position], eax
@@:
 
; OK, draw the scrollbar
mov [scroll1.all_redraw], 1
 
push dword scroll1
call [scrollbar_v_draw]
 
jmp print_channel_list
 
.noscroll:
mov [scroll1.position], 0
 
 
 
print_channel_list:
 
pusha
; Now, draw the usernames themselves
 
; first, draw an invisible button
mov ebx, [xsize]
sub ebx, USERLIST_X + SCROLLBAR_WIDTH
shl ebx, 16
push ebx
mov bx, USERLIST_X
mov ecx, [ysize]
add ecx, TEXT_Y shl 16 - (TEXT_Y + 15) ;;;;; + 10???
push ecx ebx
mov edx, 50 + 1 shl 29 + 1 shl 30
mcall 8
 
; now draw rectangle to clear the names
pop ebx ecx
mov edx, [colors.work]
mcall 13
 
; now draw the names according with scrollbar position and window size
mov eax, [scroll1.position]
xor edx, edx
mov ecx, MAX_NICK_LEN
mul ecx
mov edx, eax
mov eax, [window_open]
mov ebp, [eax + window.selected]
add edx, [eax + window.data_ptr]
sub ebp, [scroll1.position]
add edx, window_data.names
 
pop ebx
mov bx, TEXT_Y
mov ecx, [colors.work_text]
or ecx, 0x80000000 ; ASCIIZ string
mov eax, 4 ; draw text
 
mov edi, [ysize] ; Calculate how many names will fit on screen
sub edi, TEXT_Y + 15 ;+ 10 ;;;;;
.loop:
cmp byte[edx], 0 ; end of list?
je .done
 
dec ebp ; is this name selected?
jnz .nothighlight
; yes, highlight it
pusha
mov cx, bx
mov bx, USERLIST_X
shl ecx, 16
mov cx, 10 - 1
mov edx, 0x00000055 ; blue!
mcall 13
popa
 
mov ecx, 0x8000ffff ; cyan!
mcall
 
mov ecx, [colors.work_text]
or ecx, 0x80000000 ; ASCIIZ string
jmp .next
 
.nothighlight:
mcall
 
.next:
add edx, MAX_NICK_LEN ; next name
add ebx, 10 ; height distance between lines
sub edi, 10
ja .loop
 
.done:
popa
 
ret
 
 
 
 
draw_channel_text:
 
pusha
 
mov eax, 4 ; draw text
mov ebx, TEXT_X shl 16 + TEXT_Y
mov ecx, 12 ; 12 lines max ?
mov esi, [textbox_width]
 
.dct:
pusha
mov cx, bx
shl ecx, 16
mov cx, 9 ; character height
mov eax, 13 ; draw rectangle
mov ebx, TEXT_X shl 16
mov bx, word[textbox_width]
imul bx, 6 ; character width
mov edx, [colors.work]
mcall
popa
 
push ecx
mov ecx, [colors.work_text]
cmp word[edx], '* '
jne .no_red
mov ecx, 0x00aa0000
jmp .draw
.no_red:
 
cmp word[edx], '**'
jne .no_light_blue
cmp byte[edx+2], '*'
jne .no_light_blue
mov ecx, 0x000000aa
jmp .draw
.no_light_blue:
 
cmp byte[edx], '#'
jne .no_blue
mov ecx, 0x0000aa00
; jmp .draw
.no_blue:
 
.draw:
mcall
add edx, [textbox_width]
add ebx, 10 ; height distance between lines
 
pop ecx
loop .dct
 
popa
ret
 
 
 
draw_windownames:
 
mov eax, 8
mov ebx, 5 shl 16 + 120
mov ecx, 12 shl 16 + 12
mov edx, WINDOW_BTN_START
mov edi, windows
.more_btn:
mov esi, [colors.work_button]
cmp [window_open], edi
jne @f
not esi
and esi, 0x00ffffff
@@:
mcall
inc edx
add ebx, 125 shl 16
add edi, sizeof.window
cmp [edi + window.data_ptr], 0
jne .more_btn
 
mov eax, 4
mov ebx, 10 shl 16 + 15
mov ecx, [colors.work_button_text]
or ecx, 0x80000000 ; ASCIIZ string
lea edx, [windows + window.name]
mov esi, MAX_WINDOWS
.more:
mcall
add edx, sizeof.window
cmp byte[edx], 0
je .enough
add ebx, 125 shl 16
dec esi
jnz .more
.enough:
 
ret
 
 
/programs/network/ircc/ircc.asm
0,0 → 1,476
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; IRC client for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org, ;;
;; text encoder/decoder by Clevermouse. ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
version equ '0.1'
 
; connection status
STATUS_DISCONNECTED = 0
STATUS_RESOLVING = 1
STATUS_CONNECTING = 2
STATUS_CONNECTED = 3
 
; window flags
FLAG_UPDATED = 1 shl 0
FLAG_CLOSE = 1 shl 1
FLAG_RECEIVING_NAMES = 1 shl 2
 
; window types
WINDOWTYPE_SERVER = 0
WINDOWTYPE_CHANNEL = 1
WINDOWTYPE_CHAT = 2
WINDOWTYPE_LIST = 3
WINDOWTYPE_DCC = 4
 
; supported encodings
CP866 = 0
CP1251 = 1
UTF8 = 2
 
; settings
USERCMD_MAX_SIZE = 400
 
WIN_MIN_X = 600
WIN_MIN_Y = 165
 
TEXT_X = 5
TEXT_Y = 30
 
TOP_Y = 25
 
MAX_WINDOWS = 20
MAX_USERS = 4096
 
MAX_NICK_LEN = 32
MAX_REAL_LEN = 32 ; realname
MAX_SERVER_NAME = 256
 
MAX_CHANNEL_LEN = 40
MAX_CHANNELS = 37
 
MAX_COMMAND_LEN = 512
 
TIMESTAMP = 3 ; 3 = hh:mm:ss, 2 = hh:mm, 0 = no timestamp
 
MAX_WINDOWNAME_LEN = 256
 
WINDOW_BTN_START = 100
 
SCROLLBAR_WIDTH = 12
 
USERLIST_X = 98
 
 
format binary as ""
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 1 ; header version
dd START ; program start
dd I_END ; program image size
dd IM_END+2048 ; required amount of memory
dd IM_END+2048
dd param
dd path
 
include "../macros.inc"
include "../proc32.inc"
include "../dll.inc"
include "../network.inc"
include "../struct.inc"
include '../../../../../programs/develop/libraries/box_lib/trunk/box_lib.mac'
 
struct window
data_ptr dd ? ; zero if not used
flags db ?
type db ?
name rb MAX_WINDOWNAME_LEN
users dd ?
users_scroll dd ?
selected dd ? ; selected user, 0 if none selected
ends
 
struct window_data
text rb 120*60
title rb 256
names rb MAX_NICK_LEN * MAX_USERS
usertext rb 256
usertextlen dd ?
ends
 
include "encodings.inc"
include "window.inc" ; also contains text print routines
include "serverparser.inc"
include "userparser.inc"
include "socket.inc"
include "gui.inc"
include "users.inc"
 
 
START:
 
mcall 68, 11 ; init heap so we can allocate memory dynamically
 
; wanted events
mcall 40, EVM_REDRAW + EVM_KEY + EVM_BUTTON + EVM_STACK + EVM_MOUSE
 
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
 
; find path to main settings file (ircc.ini)
mov edi, path ; Calculate the length of zero-terminated string
xor al, al
mov ecx, 1024
repne scasb
dec edi
mov eax, '.ini'
stosd
xor al, al
stosb
 
; Fill the window buffer with zeros
mov edi, windows
mov ecx, (sizeof.window*MAX_WINDOWS+3)/4
xor eax, eax
rep stosd
 
; clear command area too
mov edi, servercommand
mov ecx, 600/4
rep stosd
 
; allocate window data block
call window_create
mov ebx, windows
mov [ebx + window.data_ptr], eax
mov [ebx + window.flags], 0
mov [ebx + window.type], WINDOWTYPE_SERVER
add eax, window_data.text
mov [text_start], eax
 
call window_refresh
 
; get system colors
mcall 48, 3, colors, 40
 
; set edit box and scrollbar colors
mov eax, [colors.work]
mov [scroll1.bg_color], eax
 
mov eax, [colors.work_button]
mov [scroll1.front_color], eax
 
mov eax, [colors.work_text]
mov [scroll1.line_color], eax
 
; get settings from ini
invoke ini.get_str, path, str_user, str_nick, user_nick, MAX_NICK_LEN, default_nick
invoke ini.get_str, path, str_user, str_real, user_real_name, MAX_REAL_LEN, default_real
 
; Welcome user
mov esi, str_welcome
call print_text2
 
call draw_window ;;; FIXME (gui is not correctly drawn first time)
 
redraw:
call draw_window
 
still:
 
; wait here for event
mcall 10
 
dec eax
jz redraw
 
dec eax
jz main_window_key
 
dec eax
jz button
 
cmp al, 3
je mouse
 
call process_network_event
 
mov edx, [window_open]
test [edx + window.flags], FLAG_UPDATED
jz .no_update
and [edx + window.flags], not FLAG_UPDATED
mov edx, [edx + window.data_ptr]
add edx, window_data.text
call draw_channel_text
.no_update:
call print_channel_list
 
jmp still
 
button:
 
mcall 17 ; get id
shr eax, 8
 
cmp ax, 1 ; close program
je exit
 
cmp ax, 50
jne @f
 
mcall 37, 1 ; Get mouse position
sub ax, TEXT_Y
mov bl, 10
div bl
and eax, 0x000000ff
inc eax
add eax, [scroll1.position]
mov ebx, [window_open]
mov [ebx + window.selected], eax
 
call print_channel_list
 
jmp still
 
@@:
sub ax, WINDOW_BTN_START
jb exit
 
cmp ax, MAX_WINDOWS
ja exit
 
mov dx, sizeof.window
mul dx
shl edx, 16
mov dx, ax
add edx, windows
cmp [edx + window.data_ptr], 0
je exit
mov [window_open], edx
call window_refresh
call draw_window
 
jmp still
exit:
mcall -1
 
 
 
main_window_key:
 
mcall 2
 
push dword edit1
call [edit_box_key]
 
cmp ah, 13 ; enter
jne no_send2
 
call user_parser
 
mov [edit1.size], 0
mov [edit1.pos], 0
 
push dword edit1
call [edit_box_draw]
 
mov edx, [window_open]
mov edx, [edx + window.data_ptr]
add edx, window_data.text
call draw_channel_text
 
jmp still
no_send2:
 
jmp still
 
mouse:
push dword edit1
call [edit_box_mouse]
 
; TODO: check if scrollbar is active
push [scroll1.position]
push dword scroll1
call [scrollbar_v_mouse]
pop eax
cmp eax, [scroll1.position] ; did the scrollbar move?
je @f
call print_channel_list
@@:
 
jmp still
 
 
; DATA AREA
 
encoding_text:
db 'CP866 '
db 'CP1251'
db 'UTF-8 '
encoding_text_len = 6
 
action_header db '*** ', 0
action_header_short db '* ', 0
ctcp_header db '-> [',0
ctcp_version db '] VERSION',10,0
ctcp_ping db '] PING',10,0
ctcp_time db '] TIME',10,0
has_left_channel db ' has left ', 0
joins_channel db ' has joined ', 0
is_now_known_as db ' is now known as ', 0
has_quit_irc db ' has quit IRC', 10, 0
sets_mode db ' sets mode ', 0
kicked db ' is kicked from ', 0
str_talking db 'Now talking in ',0
str_topic db 'Topic is ',0
str_setby db 'Set by ',0
 
str_version db 'VERSION '
str_programname db 'KolibriOS IRC client ', version, 0
 
str_user db 'user', 0
str_nick db 'nick', 0
str_real db 'realname', 0
str_email db 'email', 0
 
default_nick db 'kolibri_user', 0
default_real db 'Kolibri User', 0
 
str_welcome db 10
db ' ______________________ __ __ __',10
db '| \______ \_ ___ \ ____ | | |__| ____ _____/ |_',10
db '| || _/ \ \/ _/ ___\| | | |/ __ \ / \ __\',10
db '| || | \ \____ \ \___| |_| \ ___/| | \ |',10
db '|___||____|_ /\______ / \___ >____/__|\___ >___| /__|',10
db ' \/ \/ \/ \/ \/',10
db 10
db 'Welcome to IRC client ',version,' for KolibriOS',10
db 10
db 'Type /help for help',10,0
 
str_nickchange db 'Nickname is now ',0
str_realchange db 'Real name is now ',0
str_dotnewline db '.',10, 0
str_newline db 10, 0
str_connecting db 10,'* Connecting to ',0
str_help db 10,'following commands are available:',10
db 10
db '/nick <nick> : change nickname to <nick>',10
db '/real <real name> : change real name to <real name>',10
db '/server <address> : connect to server <address>',10
db '/code <code> : change codepage to cp866, cp1251, or utf8',10,0
 
str_1 db ' -',0
str_2 db '- ',0
 
str_sockerr db 'Socket Error',10,0
str_dnserr db 'Unable to resolve hostname.',10,0
str_refused db 'Connection refused',10,0
 
sockaddr1:
dw AF_INET4
.port dw 0x0b1a ; 6667
.ip dd 0
rb 10
 
 
status dd STATUS_DISCONNECTED
 
text_start dd ? ; pointer to current textbox data
irc_data dd 0x0 ; encoder
textbox_width dd 80 ; in characters, not pixels ;)
pos dd 66 * 11 ; encoder
 
window_open dd windows
window_print dd windows
 
scroll dd 1
dd 12
 
align 4
@IMPORT:
 
library network, 'network.obj',\
libini, 'libini.obj',\
boxlib, 'box_lib.obj'
 
import network,\
getaddrinfo, 'getaddrinfo',\
freeaddrinfo, 'freeaddrinfo',\
inet_ntoa, 'inet_ntoa'
 
import libini,\
ini.get_str, 'ini_get_str',\
ini.get_int, 'ini_get_int'
 
import boxlib,\
edit_box_draw ,'edit_box' ,\
edit_box_key ,'edit_box_key' ,\
edit_box_mouse ,'edit_box_mouse' ,\
scrollbar_v_draw ,'scrollbar_v_draw' ,\
scrollbar_v_mouse,'scrollbar_v_mouse'
 
 
usercommand db '/server chat.freenode.net', 0
rb MAX_COMMAND_LEN
 
I_END:
 
; width, left, top
edit1 edit_box 0, 0, 0, 0xffffff, 0x6f9480, 0, 0, 0, USERCMD_MAX_SIZE, usercommand, mouse_dd, ed_focus, 25, 25
; xsize, xpos, ysize, ypos, max, cur, pos, bgcol, frcol, linecol
scroll1 scrollbar SCROLLBAR_WIDTH, 300, 150, TOP_Y, 10, 100, 0, 0, 0, 0, 0, 1
scroll2 scrollbar SCROLLBAR_WIDTH, 300, 150, TOP_Y, 10, 100, 0, 0, 0, 0, 0, 1
 
main_PID dd ? ; identifier of main thread
utf8_bytes_rest dd ? ; bytes rest in current UTF8 sequence
utf8_char dd ? ; first bits of current UTF8 character
gai_reqdata rb 32 ; buffer for getaddrinfo_start/process
ip_list dd ? ; will be filled as pointer to addrinfo list
packetbuf rb 1024 ; buffer for packets to server
path rb 1024
param rb 1024
 
socketnum dd ?
 
servercommand rb 600
 
thread_info rb 1024
xsize dd ?
ysize dd ?
 
colors system_colors
 
irc_server_name rb MAX_SERVER_NAME
 
user_nick rb MAX_NICK_LEN
user_real_name rb MAX_REAL_LEN
 
windows rb MAX_WINDOWS*sizeof.window
 
mouse_dd dd ?
 
IM_END:
 
 
 
 
 
 
 
/programs/network/ircc/ircc.ini
0,0 → 1,8
[user]
nick = kolibri_user
realname = tetten
 
[colors]
action1 = 0x000000aa
action2 = 0x0000aa00
action3 = 0x00aa0000
/programs/network/ircc/serverparser.inc
0,0 → 1,928
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
server_parser:
 
mov esi, servercommand
 
cmp byte [esi], ':'
jne .parse
 
.spaceloop:
lodsb
test al, al
jz .fail
cmp al, ' '
jne .spaceloop
 
.parse:
mov eax, [esi]
or eax, 0x20202020
mov edi, server_commands
mov ecx, server_commands.number
 
.loop:
scasd
je .got_cmd
add edi, 4
dec ecx
jnz .loop
 
.fail:
ret
 
.got_cmd:
jmp dword[edi]
 
 
server_commands:
 
dd '322 ', cmd_322 ; RPL_LIST
dd '323 ', cmd_323 ; RPL_LISTEND
dd '328 ', cmd_328
dd '332 ', cmd_topic
dd '333 ', cmd_333 ; nickname and time of topic
dd '353 ', cmd_353 ; name reply
dd '366 ', cmd_366 ; end of names list
dd '372 ', cmd_372 ; motd
dd '375 ', cmd_375 ; start of motd
dd '376 ', cmd_376 ; end of motd
dd '421 ', cmd_421 ; unknown command
dd 'join', cmd_join
dd 'kick', cmd_kick
dd 'mode', cmd_mode
dd 'nick', cmd_nick
dd 'part', cmd_part
dd 'ping', cmd_ping
dd 'priv', cmd_privmsg
dd 'quit', cmd_quit
dd 'noti', cmd_notice
 
.number = ($ - server_commands) / 8
 
 
align 4
compare_to_nick:
 
push esi
mov ecx, MAX_NICK_LEN
mov esi, user_nick
.loop:
lodsb
cmp al, ' '
jbe .done
cmp al, 'a'
jb .ok
cmp al, 'z'
ja .ok
sub al, 0x20
.ok:
 
mov bl, byte[edi]
cmp bl, 'a'
jb .ok2
cmp bl, 'z'
ja .ok2
sub bl, 0x20
.ok2:
cmp bl, al
jne .not_equal
inc edi
dec ecx
jnz .loop
 
.done:
xor eax, eax
pop esi
ret
 
.not_equal:
or eax, -1
pop esi
ret
 
align 4
skip_nick:
 
; First: skip the NICK (maybe we should verify it?)
.nick:
lodsb
cmp al, ' '
je .skip
cmp al, ':'
je .skip
jmp .nick
 
; skip all leading spaces and semicolons
.skip:
lodsb
cmp al, ' '
je .skip
cmp al, ':'
je .skip
dec esi
 
ret
 
 
align 4
find_window: ; esi is ptr to windowname
 
push esi
 
mov edi, esi
call compare_to_nick
jne .nochat
 
mov esi, servercommand+1
.nochat:
 
; now search for window in list
mov ebx, windows
mov [window_print], ebx ; set first window (server window) as default output window
.scanloop:
cmp [ebx + window.data_ptr], 0
je .create_it
push esi
lea edi, [ebx + window.name]
mov ecx, MAX_WINDOWNAME_LEN
repe cmpsb
pop esi
cmp byte[edi-1], 0
je .got_it
add ebx, sizeof.window
; TODO: check buffer limits ?
jmp .scanloop
 
; create channel window - search for empty slot
.create_it:
mov ebx, windows
mov ecx, MAX_WINDOWS
.scanloop2:
cmp [ebx + window.data_ptr], 0
je .free_found
add ebx, sizeof.window
dec ecx
jnz .scanloop2
; Error: no more available windows!
jmp .just_skip
 
.free_found:
push ebx
call window_create
pop ebx
test eax, eax
jz .just_skip
mov [ebx + window.data_ptr], eax
mov [ebx + window.type], WINDOWTYPE_CHAT
mov [ebx + window.flags], 0
 
call window_set_name
 
mov [window_open], ebx
mov [window_print], ebx
call window_refresh
 
call draw_windownames
jmp .just_skip
 
; found it!
.got_it:
mov [window_print], ebx
call window_refresh
 
.just_skip:
pop esi
.skip1:
; skip text
lodsb
test al, al
jz .quit
cmp al, ' '
jne .skip1
dec esi
; now skip trailing spaces and semicolons
.skip2:
lodsb
test al, al
jz .quit
cmp al, ' '
je .skip2
cmp al, ':'
je .skip2
dec esi
 
.quit:
ret
 
 
 
 
 
 
cmd_328:
cmd_421:
cmd_372:
cmd_375:
cmd_376:
add esi, 4
jmp cmd_notice.loop
 
cmd_notice:
 
cmp byte[servercommand], ':'
jne .gogogo
 
mov byte [esi-1], 0
push esi
mov esi, str_1
call print_text2
mov esi, servercommand+1
call print_text2
mov esi, str_2
call print_text2
pop esi
 
.gogogo:
add esi, 6
 
.loop:
inc esi
cmp byte [esi], 0
je .fail
cmp byte [esi], ' '
jne .loop
 
.loop2:
inc esi
cmp byte [esi], 0
je .fail
cmp byte [esi], ' '
je .loop2
cmp byte [esi], ':'
je .loop2
 
call print_text2
mov esi, str_newline
call print_text2
 
.fail:
 
ret
 
 
 
cmd_ping:
 
; Just change PING to PONG
mov dword[esi], 'PONG'
 
; Find the end of the command
lea edi, [esi + 5]
xor al, al
repne scasb
 
; Now send it back
mov edx, esi
mov esi, edi
mov word [esi], 0x0d0a
inc esi
inc esi
sub esi, edx
mcall send, [socketnum], , , 0
 
ret
 
 
 
cmd_privmsg:
 
add esi, 8 ; skip 'PRIVMSG '
call find_window ; esi now points to end of destination name
 
cmp byte[esi], 1
je cmd_ctcp
 
cmp dword[esi], 'ACTI' ; Action?
je .action
 
; nope, just plain old privmsg
if TIMESTAMP
call print_timestamp
end if
 
push esi
mov bl, '<'
call print_character
 
mov eax, servercommand+1
mov dl, '!'
call print_text
 
mov bl, '>'
call print_character
 
mov bl, ' '
call print_character
 
pop esi
call print_text2
 
mov bl, 10
call print_character
 
.fail:
ret
 
.action:
add esi, 8
push esi
if TIMESTAMP
call print_timestamp
end if
 
mov esi, action_header_short
call print_text2
 
mov eax, servercommand+1
mov dl, ' '
call print_text
 
mov bl, ' '
call print_character
 
pop esi
call print_text2
 
mov bl, 10
call print_character
 
ret
 
cmd_ctcp:
inc esi
 
cmp dword[esi], 'VERS'
je .version
 
cmp dword[esi], 'TIME'
je .time
 
cmp dword[esi], 'PING'
je .ping
 
ret
 
.time:
mov byte [esi+4], ' '
lea edi, [esi+5]
 
; TODO: add system date (fn 29) in human readable format
 
mcall 3 ; get system time
 
mov ecx, 3
.timeloop:
mov bl, al
shr al, 4
add al, '0'
stosb
 
mov al, bl
and al, 0x0f
add al, '0'
stosb
 
dec ecx
jz .timedone
 
mov al, ':'
stosb
shr eax, 8
jmp .timeloop
 
.timedone:
xor al, al
stosb
call ctcp_reply
 
if TIMESTAMP
call print_timestamp
end if
 
mov esi, ctcp_header
call print_text2
 
mov esi, servercommand+1
call print_text2
 
mov esi, ctcp_time
call print_text2
 
ret
 
.version:
mov esi, str_version
call ctcp_reply
 
if TIMESTAMP
call print_timestamp
end if
 
mov esi, ctcp_header
call print_text2
 
mov esi, servercommand+1
call print_text2
 
mov esi, ctcp_version
call print_text2
 
ret
 
.ping:
call ctcp_reply
 
if TIMESTAMP
call print_timestamp
end if
 
mov esi, ctcp_header
call print_text2
 
mov esi, servercommand+1
call print_text2
 
mov esi, ctcp_ping
call print_text2
 
ret
 
 
 
ctcp_reply:
 
push esi
 
mov dword [usercommand], 'NOTI'
mov dword [usercommand+4], 'CE '
 
mov esi, servercommand+1
mov edi, usercommand+7
.nickloop:
lodsb
cmp al, '!'
je .done
cmp al, ' '
je .done
test al, al
je .fail
stosb
jmp .nickloop
.done:
mov byte [esi-1], 0
mov ax, ' :'
stosw
mov al, 1
stosb
 
pop esi
.replyloop:
lodsb
cmp al, 1
jbe .done2
stosb
jmp .replyloop
.done2:
 
mov al, 1
stosb
mov ax, 0x0a0d
stosw
 
lea esi, [edi - usercommand]
mcall send, [socketnum], usercommand, , 0
.fail:
ret
 
 
 
cmd_part:
add esi, 5 ; skip 'PART '
push esi
call skip_nick
call find_window
pop esi
 
; Is it me who parted?
mov edi, servercommand+1
call compare_to_nick
jne .dont_close
 
; yes, close the window
mov edi, [window_print]
mov [edi + window.flags], FLAG_UPDATED + FLAG_CLOSE
 
ret
 
; somebody else parted, just print message
.dont_close:
push esi
mov esi, action_header
call print_text2
 
mov eax, servercommand+1
mov dl, '!'
mov cl, ' '
call print_text
 
mov esi, has_left_channel
call print_text2
 
pop esi
call print_text2
 
mov esi, str_newline
call print_text2
 
mov ebx, [window_print]
mov esi, servercommand+1
call user_remove
 
ret
 
 
 
cmd_join:
add esi, 5 ; skip 'JOIN '
 
; compare nick: did we join a channel?
mov edi, servercommand+1
call compare_to_nick
jne .no_new_window
 
; create channel window - search for empty slot
mov ebx, windows
mov ecx, MAX_WINDOWS
.loop:
cmp [ebx + window.data_ptr], 0
je .free_found
add ebx, sizeof.window
dec ecx
jnz .loop
; Error: no more available windows!! ;;;;; TODO
.fail:
ret
 
.free_found:
push ebx
call window_create
pop ebx
test eax, eax
jz .fail
mov [ebx + window.data_ptr], eax
mov [ebx + window.type], WINDOWTYPE_CHANNEL
mov [ebx + window.flags], 0
 
call window_set_name
 
mov [window_open], ebx
mov [window_print], ebx
call window_refresh
 
push esi
mov esi, action_header
call print_text2
 
mov esi, str_talking
call print_text2
 
pop eax
mov dl, ' '
call print_text
 
mov esi, str_dotnewline
call print_text2
 
call draw_window
 
ret
 
.no_new_window:
push esi
call find_window
 
mov esi, action_header
call print_text2
 
mov eax, servercommand+1
mov dl, '!'
call print_text
 
mov esi, joins_channel
call print_text2
 
pop esi
call print_text2
 
mov esi, str_newline
call print_text2
 
mov ebx, [window_print]
mov esi, servercommand+1
call user_add
 
ret
 
 
 
 
cmd_nick:
; NOTE: This command applies to a user, and thus has no specific channel
add esi, 5 ; skip 'NICK '
 
cmp byte[esi], ':' ; TODO: skip all spaces and semicolons?
jne @f
inc esi
@@:
 
; Change the nick in the current userlist. TODO: check other channels too!
push esi
mov ebx, [window_print]
 
mov esi, servercommand+1
call user_remove
 
mov esi, [esp]
call user_add
 
call redraw_channel_list
 
; Is it me who changed nick?
mov edi, servercommand+1
call compare_to_nick
pop esi
jne .not_me
 
mov ecx, MAX_NICK_LEN-1
push esi
.copyloop:
lodsb
test al, al
jz .copydone
cmp al, ' '
je .copydone
stosb
dec ecx
jnz .copyloop
.copydone:
xor al, al
stosb
pop esi
.not_me:
 
; Now print a message on the current channel
push esi
mov esi, action_header_short
call print_text2
 
mov eax, servercommand+1
mov dl, '!'
call print_text
 
mov esi, is_now_known_as
call print_text2
 
pop esi
call print_text2
 
mov esi, str_newline
call print_text2
 
ret
 
 
 
 
cmd_kick:
add esi, 5 ; skip 'KICK '
; Is it me who got kicked?
mov edi, servercommand+1
call compare_to_nick
jne .not_me
 
; TODO: mark channel as disconnected
 
.not_me:
; find the channel user has been kicked from
push esi
call skip_nick
call find_window
 
mov esi, action_header_short
call print_text2
 
mov eax, servercommand+1
mov dl, '!'
call print_text
 
mov esi, kicked
call print_text2
 
pop esi
call print_text2
 
mov esi, str_newline
call print_text2
 
mov ebx, [window_print]
mov esi, servercommand+1
call user_remove
 
ret
 
 
 
cmd_quit:
; NOTE: This command applies to a user, and thus has no specific channel
 
mov esi, action_header
call print_text2
 
mov eax, servercommand+1
mov dl, '!'
call print_text
 
mov esi, has_quit_irc
call print_text2
 
; TODO: check other channels on same server too!
mov ebx, [window_print]
mov esi, servercommand+1
call user_remove
 
ret
 
 
 
cmd_mode:
 
add esi, 5 ; skip 'MODE '
 
push esi
mov esi, action_header_short
call print_text2
 
mov eax, servercommand+1
mov dl, ' '
call print_text
 
mov esi, sets_mode
call print_text2
 
pop esi
call print_text2
 
mov esi, str_newline
call print_text2
 
;;; TODO: change username if needed
 
ret
 
 
cmd_353: ; channel usernames reply
 
add esi, 4 ; skip '353 '
call skip_nick
inc esi ; channel type '*', '=' or '@'
inc esi ; ' '
call find_window
 
; now find window ptr and check if this is the first 353 message
mov ebx, [window_print]
test [ebx + window.flags], FLAG_RECEIVING_NAMES
jnz .add
 
or [ebx + window.flags], FLAG_RECEIVING_NAMES
; mov [ebx + window.users], 0
; TODO: remove all users?
 
.add:
push esi
call user_add
pop esi
 
.namesloop:
lodsb
test al, al
jz .done
cmp al, ' ' ; names list is separated with spaces
jne .namesloop
jmp .add
 
.done:
call redraw_channel_list
 
ret
 
 
 
 
 
cmd_366: ; channel usernames end
 
add esi, 4 ; skip '366 '
call skip_nick
call find_window
 
mov ebx, [window_print]
and [ebx + window.flags], not FLAG_RECEIVING_NAMES
 
ret
 
 
 
 
cmd_topic:
 
add esi, 4 ; skip '332 '
call skip_nick
call find_window
 
push esi
mov esi, action_header
call print_text2
 
mov esi, str_topic
call print_text2
 
pop esi
call print_text2
 
mov esi, str_newline
call print_text2
 
ret
 
 
cmd_333:
 
add esi, 4 ; skip '333 '
call skip_nick ;;;;
call find_window
 
; mov ecx, 2 ; number of spaces to find ;;; CHECKME
; .loop:
; lodsb
; test al, al
; je .fail
; cmp al, ' '
; jne .loop
; dec ecx
; jnz .loop ; find some more spaces
 
push esi
mov esi, action_header
call print_text2
 
mov esi, str_setby
call print_text2
 
; pop esi
; call print_text2
 
pop eax
mov dl, '!'
call print_text
 
mov esi, str_newline
call print_text2
 
.fail:
ret
 
cmd_322:
add esi, 4
 
call skip_nick
 
call print_text2
 
mov esi, str_newline
call print_text2
 
ret
 
cmd_323:
 
ret
/programs/network/ircc/socket.inc
0,0 → 1,242
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
socket_connect:
 
; cmp [status], STATUS_CONNECTED ; TODO
; je disconnect
 
; ignore if status is not "disconnected"
cmp [status], STATUS_DISCONNECTED
jne .nothing
 
mov esi, str_connecting
call print_text2
mov esi, irc_server_name
call print_text2
mov esi, str_dotnewline
call print_text2
 
; update status
inc [status] ; was STATUS_DISCONNECTED, now STATUS_RESOLVING
 
; resolve name
push esp ; reserve stack place
push esp ; fourth parameter
push 0 ; third parameter
push 0 ; second parameter
push irc_server_name
call [getaddrinfo]
pop esi
; test for error
test eax, eax
jnz .fail_dns
 
; fill in ip in sockstruct
mov eax, [esi + addrinfo.ai_addr]
mov eax, [eax + sockaddr_in.sin_addr]
mov [sockaddr1.ip], eax
 
; free allocated memory
push esi
call [freeaddrinfo]
 
; update status
inc [status]
 
; connect
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
jz .fail
mov [socketnum], eax
 
mcall connect, [socketnum], sockaddr1, 18
cmp eax, -1
jz .fail_refused
 
.nothing:
ret
 
.fail:
mov [status], STATUS_DISCONNECTED
 
mov esi, str_sockerr
call print_text2
 
ret
 
.fail_dns:
mov [status], STATUS_DISCONNECTED
 
mov esi, str_dnserr
call print_text2
 
ret
 
.fail_refused:
mov [status], STATUS_DISCONNECTED
 
mov esi, str_refused
call print_text2
 
ret
 
 
 
socket_write_userinfo:
 
; create packet in packetbuf
mov edi, packetbuf
 
mov eax, 'NICK'
stosd
mov al, ' '
stosb
mov esi, user_nick
mov ecx, MAX_NICK_LEN
.loop:
lodsb
test al, al
jz .done
stosb
dec ecx
jnz .loop
.done:
mov ax, 0x0d0a
stosw
 
mov eax, 'USER'
stosd
mov al, ' '
stosb
mov esi, user_nick
mov ecx, MAX_NICK_LEN
.loop2:
lodsb
test al, al
jz .done2
stosb
dec ecx
jnz .loop2
.done2:
mov eax, ' 8 *'
stosd
mov ax, ' :'
stosw
mov al, ' '
stosb
mov esi, user_real_name
mov ecx, MAX_REAL_LEN
.loop3:
lodsb
test al, al
jz .done3
stosb
dec ecx
jnz .loop3
.done3:
mov ax, 0x0d0a
stosw
 
lea esi, [edi - packetbuf]
mcall send, [socketnum], packetbuf, , 0
 
ret
 
 
 
 
process_network_event:
; values for status: 0, 1, 2, 3
mov eax, [status]
dec eax
; 0 = STATUS_DISCONNECTED - do nothing
; (ignore network events if we are disconnected from network)
js .nothing
; 1 = STATUS_RESOLVING
jz .nothing
; 2 = STATUS_CONNECTING
dec eax
jz .connecting
; 3 = STATUS_CONNECTED
jmp .connected
 
.nothing:
ret
 
.connecting:
call socket_write_userinfo
 
; The connection has been established, change status from "connecting" to "connected".
inc [status]
 
.connected:
call read_incoming_data
ret
 
 
disconnect:
 
cmp [status], STATUS_DISCONNECTED
je .nothing
 
mcall close, [socketnum]
 
mov [status], STATUS_DISCONNECTED
 
.nothing:
ret
 
 
 
read_incoming_data:
 
pusha
 
; TODO: read more data if we receive one full packet
 
.nextpacket:
mcall recv, [socketnum], packetbuf, 1024 ; read a packet
inc eax ; check if we got one
jz .done
dec eax
jz .done
 
; ok we have data, now feed it to the recoder
 
lea edx, [packetbuf + eax] ; edx = end pointer
mov esi, packetbuf ; esi = start pointer
.nextcommand:
mov edi, servercommand
.byteloop:
call get_next_byte ; reads byte from [esi] to al
jnc .nextpacket ; if CF is set, we need more data
cmp al, 10
je .got_command
cmp al, 13
je .got_command
stosb
jmp .byteloop
 
; we have a command, call the serverparser
 
.got_command:
mov byte[edi], 0 ; mark the end of the command
push esi edx
call server_parser
pop edx esi
jmp .nextcommand
 
.done:
popa
 
ret
/programs/network/ircc/userparser.inc
0,0 → 1,318
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
user_parser:
 
mov eax, [edit1.size]
mov word [usercommand + eax], 0x0a0d ; terminate the line
 
cmp byte[usercommand], '/' ; is it a server command ?
je server_command
 
; Ignore data commands when not connected.
cmp [status], STATUS_CONNECTED
jne sdts_ret
 
; Ok, we said something, print it to our textbox
 
; TODO: dont send if it's a server window?
 
push [window_open] ; print to the current window
pop [window_print]
call window_refresh
 
if TIMESTAMP
call print_timestamp
end if
 
mov bl, '<'
call print_character
 
mov esi, user_nick
call print_text2
 
mov bl,'>'
call print_character
mov bl,' '
call print_character
 
mov eax, [edit1.size]
mov byte[usercommand + eax],0
 
mov esi, usercommand
call print_text2
 
mov bl, 10
call print_character
 
; and now send it to the server
 
mov dword[packetbuf], 'priv'
mov dword[packetbuf+4], 'msg '
 
mov esi, [window_open]
add esi, window.name
mov edi, packetbuf+8
mov ecx, MAX_WINDOWNAME_LEN
.loop:
lodsb
test al, al
jz .done
stosb
dec ecx
jnz .loop
.done:
 
mov ax, ' :'
stosw
 
mov esi, usercommand
mov ecx, [edit1.size]
inc ecx
call recode
 
mov al, 10
stosb
 
lea esi, [edi - packetbuf]
mcall send, [socketnum], packetbuf, , 0
 
sdts_ret:
 
ret
 
 
 
user_commands:
dd 'nick', cmd_usr_nick
dd 'real', cmd_usr_real
dd 'serv', cmd_usr_server
dd 'help', cmd_usr_help
dd 'code', cmd_usr_code
; TODO: All other commands require a connection to the server.
dd 'quer', cmd_usr_quer
dd 'quit', cmd_usr_quit
 
.number = ($ - user_commands) / 8
 
 
 
server_command:
 
mov eax, dword[usercommand+1]
or eax, 0x20202020
 
mov edi, user_commands
mov ecx, user_commands.number
.loop:
scasd
je .got_cmd
add edi, 4
dec ecx
jnz .loop
jmp cmd_usr_send ; If none of the previous commands, just send to server
 
.got_cmd:
jmp dword[edi]
 
 
 
 
 
cmd_usr_quit:
 
cmp [edit1.size], 5
je .ok
jb cmd_usr_send
cmp byte[usercommand+5], ' '
jne cmd_usr_send
 
.ok:
call cmd_usr_send
 
mcall close, [socketnum]
 
mov ecx, MAX_WINDOWS
mov edi, windows
.loop:
mov [edi + window.flags], FLAG_CLOSE
add edi, sizeof.window
dec ecx
jnz .loop
 
ret
 
 
 
 
cmd_usr_nick:
 
cmp [edit1.size], 5
je .justprint
cmp byte[usercommand+5], ' '
jne cmd_usr_send
 
mov ecx, MAX_NICK_LEN
mov esi, usercommand+6
mov edi, user_nick
.loop:
lodsb
cmp al, 13
je .done
stosb
dec ecx
jnz .loop
.done:
xor al, al
stosb
 
cmp [socketnum], 0
je .justprint
 
lea esi, [edi - usercommand]
mcall send, [socketnum], usercommand+1, , 0
 
.justprint:
mov esi, str_nickchange
call print_text2
mov esi, user_nick
call print_text2
mov esi, str_dotnewline
call print_text2
 
ret
 
 
 
cmd_usr_real:
 
cmp byte[usercommand+5], ' '
jne cmd_usr_send
 
mov ecx, MAX_REAL_LEN
mov esi, usercommand+6
mov edi, user_real_name
.loop:
lodsb
cmp al, 13
je .done
stosb
dec ecx
jnz .loop
.done:
xor al, al
stosb
 
mov esi, str_realchange
call print_text2
mov esi, user_real_name
call print_text2
mov esi, str_dotnewline
call print_text2
 
ret
 
 
 
cmd_usr_server:
 
mov eax, dword[usercommand+5] ; check for 'er ', we only checked 'serv'
or eax, 0x00002020
and eax, 0x00ffffff
cmp eax, 'er '
jne cmd_usr_send
 
mov ecx, [edit1.size] ; ok now set the address
sub ecx, 8
 
mov esi, usercommand+8
push esi
mov edi, irc_server_name
rep movsb
xor al, al
stosb
pop esi
 
; set it also in window name
mov ebx, [window_print]
call window_set_name
 
; now connect
call socket_connect
 
ret
 
 
cmd_usr_quer:
 
mov ecx, MAX_WINDOWS
mov ebx, windows
.loop:
cmp [ebx + window.data_ptr], 0
je .found
add ebx, sizeof.window
dec ecx
jnz .loop
 
; error: no available channels ! FIXME
 
ret
 
 
.found:
call window_create
test eax, eax
jz .error
mov [ebx + window.data_ptr], eax
 
mov esi, usercommand+7
call window_set_name
 
mov [ebx + window.type], WINDOWTYPE_CHAT
mov [ebx + window.flags], 0
 
.error:
 
ret
 
 
 
cmd_usr_help:
 
mov esi, str_help
call print_text2
 
ret
 
 
 
cmd_usr_code:
 
; TODO
 
ret
 
 
 
cmd_usr_send:
 
mov esi, usercommand+1
mov ecx, [edit1.size]
inc ecx
mov edi, packetbuf
call recode
 
lea esi, [edi - packetbuf]
mcall send, [socketnum], packetbuf, , 0
 
ret
 
/programs/network/ircc/users.inc
0,0 → 1,164
 
 
; esi is ptr to nick
; ebx is ptr to window
align 4
user_add:
 
cmp [ebx + window.users], MAX_USERS
jae fail
 
mov edi, [ebx + window.data_ptr]
add edi, window_data.names
mov ebp, [ebx + window.users]
inc ebp ; CHECKME
 
push esi edi
.restart:
mov ecx, MAX_NICK_LEN
.loop1:
lodsb
cmp al, '@'
jne @f
mov al, ' ' ; give @ highest priority
@@:
cmp al, 'A'
jb @f
cmp al, 'Z'
ja @f
add al, 'a' - 'A' ; convert to lowercase
@@:
dec ecx
jz .got_it
 
.loop2:
mov dl, [edi]
cmp dl, 0
je .got_it
cmp dl, '@'
jne @f
mov dl, ' ' ; give @ highest priority
@@:
cmp dl, 'A'
jb @f
cmp dl, 'Z'
ja @f
add dl, 'a' - 'A' ; convert to lowercase
@@:
cmp al, dl
jb .got_it
je .check_next
 
pop edi esi
add edi, MAX_NICK_LEN
push esi edi
 
dec ebp
jnz .restart
 
.check_next:
inc edi
jmp .loop1
 
.got_it:
pop edi esi
 
; OK, insert it here..
 
; mov all trailing usernames by MAX_NICK_LEN bytes
push esi edi
mov esi, [ebx + window.data_ptr]
add esi, window_data.names + MAX_NICK_LEN * (MAX_USERS - 1)
 
mov ecx, esi
sub ecx, edi
add ecx, MAX_NICK_LEN
shr ecx, 2
lea edi, [esi + MAX_NICK_LEN]
std
rep movsd
cld
pop edi esi
 
; Now insert our new username
mov ecx, MAX_NICK_LEN-1
.fill:
lodsb
cmp al, ' '
je .done
cmp al, '!'
je .done
stosb
loop .fill
.done:
xor al, al
stosb
 
inc [ebx + window.users]
 
ret
 
 
 
 
 
; esi is ptr to nick
; ebx is ptr to window
align 4
user_remove:
 
call user_find
jz fail
 
lea esi, [edi + MAX_NICK_LEN]
mov ecx, [ebx + window.data_ptr]
add ecx, window_data.names + MAX_NICK_LEN * MAX_USERS
sub ecx, esi
shr ecx, 2
rep movsd
 
dec [ebx + window.users]
xor eax, eax
 
ret
 
 
 
; IN:
; esi is ptr to nick
; ebx is ptr to window
; OUT:
; edi is ptr to nick in userlist
align 4
user_find:
 
mov eax, [ebx + window.users]
test eax, eax
jz fail
mov edi, [ebx + window.data_ptr]
add edi, window_data.names
 
.loop:
push esi edi
mov ecx, MAX_NICK_LEN
repe cmpsb
cmp byte[edi-1], 0
je .got_it
; TODO: check byte[esi] too!
pop edi esi
add edi, MAX_NICK_LEN
dec eax
jnz .loop
jmp fail
 
.got_it:
pop edi esi
test edi, edi ; to clear zero flag
 
ret
 
 
fail:
 
xor edi, edi
ret
/programs/network/ircc/window.inc
0,0 → 1,167
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
window_create:
 
; allocate the window data block
mcall 68, 12, sizeof.window_data
test eax, eax
jz .fail
 
; fill it with all zeros
push eax
mov edi, eax
mov ecx, (sizeof.window_data+3)/4
xor eax, eax
rep stosd
pop eax
 
.fail:
ret
 
 
window_set_name: ; esi = ptr to name, ebx = window ptr
 
pusha
 
; Skip heading spaces
.spaceloop:
cmp byte[esi], ' '
jne .done
inc esi
jmp .spaceloop
.done:
 
; Now copy it
lea edi, [ebx + window.name]
mov ecx, MAX_WINDOWNAME_LEN
.loop:
lodsb
cmp al, 0x21
jbe .addzero
stosb
dec ecx
jnz .loop
.addzero:
xor al, al
stosb
 
call draw_windownames ; redraw it
 
popa
 
ret
 
 
 
window_refresh:
 
; set the correct buffer pointers ; FIXME: what is it good for?
mov eax, [textbox_width] ;
imul eax, 11 ;
mov [pos], eax ;
 
mov eax, [window_print]
mov eax, [eax + window.data_ptr]
add eax, window_data.text
mov [text_start], eax
 
ret
 
 
window_updated:
 
mov edi, [window_print]
test [edi + window.flags], FLAG_UPDATED
jnz .skip
 
or [edi + window.flags], FLAG_UPDATED
 
; now play a sound :)
 
.skip:
 
ret
 
 
print_text: ; eax = start ptr
; dl = end char
pusha
ptr2:
mov bl, [eax]
 
cmp bl, dl
je ptr_ret
cmp bl, 0
je ptr_ret
call print_character
 
inc eax
jmp ptr2
 
ptr_ret:
popa
ret
 
 
print_text2: ; esi = ptr to ASCIIZ string
 
pusha
.loop:
lodsb
test al, al
jz .done
mov bl, al
call print_character
jmp .loop
 
.done:
popa
ret
 
 
if TIMESTAMP
print_timestamp:
 
pusha
mcall 3 ; get system time
 
mov bl, '['
call print_character
mov ecx, TIMESTAMP
.loop:
mov bl, al
shr bl, 4
add bl, '0'
call print_character
 
mov bl, al
and bl, 0x0f
add bl, '0'
call print_character
 
dec ecx
jz .done
 
mov bl, ':'
call print_character
shr eax, 8
jmp .loop
.done:
mov bl, ']'
call print_character
mov bl, ' '
call print_character
 
popa
ret
end if
/programs/network/ircc
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network/libio.inc
0,0 → 1,113
;;================================================================================================;;
;;//// libio.inc //// (c) mike.dld, 2007-2008 ////////////////////////////////////////////////////;;
;;================================================================================================;;
;; ;;
;; This file is part of Common development libraries (Libs-Dev). ;;
;; ;;
;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
;; of the License, or (at your option) any later version. ;;
;; ;;
;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;;
;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;
;; Lesser General Public License for more details. ;;
;; ;;
;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;;
;; If not, see <http://www.gnu.org/licenses/>. ;;
;; ;;
;;================================================================================================;;
 
 
O_BINARY = 00000000b
O_READ = 00000001b
O_WRITE = 00000010b
O_CREATE = 00000100b
O_SHARE = 00001000b
O_TEXT = 00010000b
 
SEEK_SET = 0
SEEK_CUR = 1
SEEK_END = 2
 
struct FileDateTime
union
time dd ?
struct
sec db ?
min db ?
hour db ?
ends
ends
union
date dd ?
struct
day db ?
month db ?
year dw ?
ends
ends
ends
 
struct FileInfoBlock
Function dd ?
Position dd ?
Flags dd ?
Count dd ?
Buffer dd ?
db ?
FileName dd ?
ends
 
struct FileInfoHeader
Version dd ?
FilesRead dd ?
FilesCount dd ?
rd 5
ends
 
struct FileInfoA
Attributes dd ?
Flags dd ?
DateCreate FileDateTime
DateAccess FileDateTime
DateModify FileDateTime
union
FileSize dq ?
struct
FileSizeLow dd ?
FileSizeHigh dd ?
ends
ends
FileName rb 264
ends
 
struct FileInfoW
Attributes dd ?
Flags dd ?
DateCreate FileDateTime
DateAccess FileDateTime
DateModify FileDateTime
union
FileSize dq ?
struct
FileSizeLow dd ?
FileSizeHigh dd ?
ends
ends
FileName rw 264
ends
 
virtual at 0
FileInfo FileInfoA
FileInfo fix FileInfoA
sizeof.FileInfo fix sizeof.FileInfoA
end virtual
 
FA_READONLY = 00000001b
FA_HIDDEN = 00000010b
FA_SYSTEM = 00000100b
FA_LABEL = 00001000b
FA_FOLDER = 00010000b
FA_ARCHIVED = 00100000b
FA_NORMAL = 01000000b
FA_ANY = 01111111b
/programs/network/macros.inc
0,0 → 1,588
@^ fix macro comment {
^@ fix }
 
; -------------------------
macro library [lname,fname]
{
forward
dd __#lname#_library_table__,__#lname#_library_name__
common
dd 0
forward
align 4
__#lname#_library_name__ db fname,0
}
 
macro import lname,[name,sname]
{
common
align 4
__#lname#_library_table__:
forward
if used name
name dd __#name#_import_name__
end if
common
dd 0
forward
if used name
align 4
__#name#_import_name__ db sname,0
end if
}
 
macro export [name,sname]
{
forward
dd __#name#_export_name__,name
common
dd 0
forward
align 4
__#name#_export_name__ db sname,0
}
; -------------------------
 
macro m2m dest,src {
push src
pop dest
}
 
 
macro iglobal {
IGlobals equ IGlobals,
macro __IGlobalBlock { }
macro uglobal {
UGlobals equ UGlobals,
macro __UGlobalBlock { }
 
endg fix } ; Use endg for ending iglobal and uglobal blocks.
 
 
macro IncludeIGlobals{
macro IGlobals dummy,[n] \{ __IGlobalBlock
purge __IGlobalBlock \}
match I, IGlobals \{ I \} }
 
macro IncludeUGlobals{
macro UGlobals dummy,[n] \{
\common
\local begin, size
begin = $
virtual at $
\forward
__UGlobalBlock
purge __UGlobalBlock
\common
size = $ - begin
end virtual
rb size
\}
match U, UGlobals \{ U \} }
 
uglobal
endg
iglobal
endg
 
 
; new application structure
macro meos_app_start
{
use32
org 0x0
 
db 'MENUET01'
dd 0x01
dd __start
dd __end
dd __memory
dd __stack
 
if used __params & ~defined __params
dd __params
else
dd 0x0
end if
 
dd 0x0
}
MEOS_APP_START fix meos_app_start
 
macro code
{
__start:
}
CODE fix code
 
macro data
{
__data:
IncludeIGlobals
}
DATA fix data
 
macro udata
{
if used __params & ~defined __params
__params:
db 0
__end:
rb 255
else
__end:
end if
__udata:
IncludeUGlobals
}
UDATA fix udata
 
macro meos_app_end
{
align 32
rb 2048
__stack:
__memory:
}
MEOS_APP_END fix meos_app_end
 
 
; macro for defining multiline text data
struc mstr [sstring]
{
forward
local ssize
virtual at 0
db sstring
ssize = $
end virtual
dd ssize
db sstring
common
dd -1
}
 
; macro for defining multiline text data
struc mls [sstring]
{
forward
local ssize
virtual at 0
db sstring ; mod
ssize = $
end virtual
db ssize
db sstring
common
db -1 ; mod
}
 
 
 
; strings
macro sz name,[data] { ; from MFAR [mike.dld]
common
if used name
name db data
.size = $-name
end if
}
 
macro lsz name,[lng,data] { ; from MFAR [mike.dld]
common
if used name
label name
forward
if lang eq lng
db data
end if
common
.size = $-name
end if
}
 
macro szc name,elsz,[data] { ; from MFAR [mike.dld]
common
local s,m
m = 0
if used name
label name
forward
virtual at 0
db data
s = $
end virtual
d#elsz s
if m < s
m = s
end if
db data
common
.size = $-name
.maxl = m
end if
}
 
macro lszc name,elsz,[lng,data] { ; from MFAR [mike.dld]
common
local s,m,c
m = 0
c = 0
if used name
label name
forward
if lang eq lng
virtual at 0
db data
s = $
end virtual
d#elsz s
if m < s
m = s
end if
db data
c = c+1
end if
common
.size = $-name
.maxl = m
.count = c
end if
}
 
 
; easy system call macro
macro mpack dest, hsrc, lsrc
{
if (hsrc eqtype 0) & (lsrc eqtype 0)
mov dest, (hsrc) shl 16 + lsrc
else
if (hsrc eqtype 0) & (~lsrc eqtype 0)
mov dest, (hsrc) shl 16
add dest, lsrc
else
mov dest, hsrc
shl dest, 16
add dest, lsrc
end if
end if
}
 
macro __mov reg,a,b { ; mike.dld
if (~a eq)&(~b eq)
mpack reg,a,b
else if (~a eq)&(b eq)
mov reg,a
end if
}
 
 
include 'config.inc'
;__CPU_type equ p5
SYSENTER_VAR equ 0
 
macro mcall a,b,c,d,e,f { ; mike.dld, updated by Ghost for Fast System Calls
local ..ret_point
__mov eax,a
__mov ebx,b
__mov ecx,c
__mov edx,d
__mov esi,e
__mov edi,f
 
if __CPU_type eq p5
int 0x40
else
if __CPU_type eq p6
push ebp
mov ebp, esp
push ..ret_point ; it may be 2 or 5 byte
sysenter
..ret_point:
pop edx
pop ecx
 
else
if __CPU_type eq k6
push ecx
syscall
pop ecx
else
display 'ERROR : unknown CPU type (set to p5)', 10, 13
__CPU_type equ p5
int 0x40
end if
end if
end if
}
 
 
; -------------------------
macro header a,[b] {
common
use32
org 0
db 'MENUET',a
forward
if b eq
dd 0
else
dd b
end if }
macro section name { align 16
label name }
macro func name {
if ~used name
display 'FUNC NOT USED: ',`name,13,10
else
align 4
name:
;diff16 `name,0,name
;pushad
;pushfd
;dps `name
;newline
;mcall 5,1
;popfd
;popad
}
macro endf { end if }
 
macro diff16 title,l1,l2
{
local s,d
s = l2-l1
display title,': 0x'
repeat 8
d = '0' + s shr ((8-%) shl 2) and $0F
if d > '9'
d = d + 'A'-'9'-1
end if
display d
end repeat
display 13,10
}
 
macro diff10 title,l1,l2
{
local s,d,z,m
s = l2-l1
z = 0
m = 1000000000
display title,': '
repeat 10
d = '0' + s / m
s = s - (s/m)*m
m = m / 10
if d <> '0'
z = 1
end if
if z <> 0
display d
end if
end repeat
display 13,10
}
 
; optimize the code for size
__regs fix <eax,ebx,ecx,edx,esi,edi,ebp,esp>
 
macro add arg1,arg2
{
if (arg2 eqtype 0)
if (arg2) = 1
inc arg1
else
add arg1,arg2
end if
else
add arg1,arg2
end if
}
 
macro sub arg1,arg2
{
if (arg2 eqtype 0)
if (arg2) = 1
dec arg1
else
sub arg1,arg2
end if
else
sub arg1,arg2
end if
}
 
macro mov arg1,arg2
{
if (arg1 in __regs) & ((arg2 eqtype 0) | (arg2 eqtype '0'))
if (arg2) = 0
xor arg1,arg1
else if (arg2) = 1
xor arg1,arg1
inc arg1
else if (arg2) = -1
or arg1,-1
else if (arg2) > -128 & (arg2) < 128
push arg2
pop arg1
else
mov arg1,arg2
end if
else
mov arg1,arg2
end if
}
 
 
macro RGB [a] {
common
match (r=,g=,b),a \{
\dd ((r) shl 16) or ((g) shl 8) or (b)
\}
}
 
 
struc POINT _t,_dx,_dy {
.x _t _dx
.y _t _dy
}
 
; structure definition helper
include 'struct.inc'
 
struct RECT
left dd ?
top dd ?
right dd ?
bottom dd ?
ends
 
struct BOX
left dd ?
top dd ?
width dd ?
height dd ?
ends
 
; structures used in MeOS
struct process_information
cpu_usage dd ? ; +0
window_stack_position dw ? ; +4
window_stack_value dw ? ; +6
dw ? ; +8
process_name rb 12 ; +10
memory_start dd ? ; +22
used_memory dd ? ; +26
PID dd ? ; +30
box BOX ; +34
slot_state dw ? ; +50
dw ? ; +52
client_box BOX ; +54
wnd_state db ? ; +70
rb (1024-71)
ends
 
struct system_colors
frame dd ?
grab dd ?
grab_button dd ?
grab_button_text dd ?
grab_text dd ?
work dd ?
work_button dd ?
work_button_text dd ?
work_text dd ?
work_graph dd ?
ends
 
struct FILEDATE
Second db ?
Minute db ?
Hour db ?
db ?
Day db ?
Month db ?
Year dw ?
ends
 
struct FILEINFO
Attributes dd ?
IsUnicode db ?
db 3 dup(?)
DateCreate FILEDATE
DateAccess FILEDATE
DateModify FILEDATE
Size dq ?
ends
 
 
if __CPU_type eq p5 ; CMOVcc isnt supported on the P5
 
cmove fix cmovz
macro cmovz reg1, reg2 {
 
local .jumpaddr
 
jnz .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
cmovne fix cmovnz
macro cmovnz reg1, reg2 {
 
local .jumpaddr
 
jz .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
macro cmovg reg1, reg2 {
 
local .jumpaddr
 
jle .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
macro cmovl reg1, reg2 {
 
local .jumpaddr
 
jge .jumpaddr
mov reg1, reg2
.jumpaddr:
}
 
end if
 
; constants
 
; events
EV_IDLE = 0
EV_TIMER = 0
EV_REDRAW = 1
EV_KEY = 2
EV_BUTTON = 3
EV_EXIT = 4
EV_BACKGROUND = 5
EV_MOUSE = 6
EV_IPC = 7
EV_STACK = 8
 
; event mask bits for function 40
EVM_REDRAW = 1b
EVM_KEY = 10b
EVM_BUTTON = 100b
EVM_EXIT = 1000b
EVM_BACKGROUND = 10000b
EVM_MOUSE = 100000b
EVM_IPC = 1000000b
EVM_STACK = 10000000b
EVM_DEBUG = 100000000b
EVM_STACK2 = 1000000000b
/programs/network/netcfg/drivers.inc
0,0 → 1,198
driverlist:
db 'RTL8139',0
dd 0x813910ec
dd 0x813810ec
dd 0x12111113
dd 0x13601500
dd 0x13604033
dd 0x13001186
dd 0x13401186
dd 0xab0613d1
dd 0xa1171259
dd 0xa11e1259
dd 0xab0614ea
dd 0xab0714ea
dd 0x123411db
dd 0x91301432
dd 0x101202ac
dd 0x0106018a
dd 0x1211126c
dd 0x81391743
dd 0x8139021b
dd 0x0 ; end
 
db 'RTL8029',0
dd 0x802910ec
dd 0x0
 
db 'I8255X',0
dd 0x12098086
dd 0x10298086
dd 0x12298086
dd 0x10308086
dd 0x24498086
dd 0x0
 
db 'RTL8169',0
dd 0x816810ec
dd 0x816910ec
dd 0x011616ec
dd 0x43001186
dd 0x813610ec
dd 0x0
 
db '3C59X',0
dd 0x590010b7
dd 0x592010b7
dd 0x597010b7
dd 0x595010b7
dd 0x595110b7
dd 0x595210b7
dd 0x900010b7
dd 0x900110b7
dd 0x900410b7
dd 0x900510b7
dd 0x900610b7
dd 0x900A10b7
dd 0x905010b7
dd 0x905110b7
dd 0x905510b7
dd 0x905810b7
dd 0x905A10b7
dd 0x920010b7
dd 0x980010b7
dd 0x980510b7
dd 0x764610b7
dd 0x505510b7
dd 0x605510b7
dd 0x605610b7
dd 0x5b5710b7
dd 0x505710b7
dd 0x515710b7
dd 0x525710b7
dd 0x656010b7
dd 0x656210b7
dd 0x656410b7
dd 0x450010b7
dd 0x0
 
db 'SIS900',0
dd 0x09001039
dd 0x70161039
dd 0x0
 
db 'PCNET32',0
dd 0x20001022
dd 0x26251022
dd 0x20011022
dd 0x0
 
db 'FORCEDETH',0
dd 0x006610de
dd 0x01c310de
dd 0x00D610de
dd 0x008610de
dd 0x008c10de
dd 0x00e610de
dd 0x00df10de
dd 0x005610de
dd 0x005710de
dd 0x003710de
dd 0x003810de
dd 0x026810de
dd 0x026910de
dd 0x037210de
dd 0x037310de
dd 0x03e510de
dd 0x03e610de
dd 0x03ee10de
dd 0x03ef10de
dd 0x045010de
dd 0x045110de
dd 0x045210de
dd 0x045310de
dd 0x054c10de
dd 0x054d10de
dd 0x054e10de
dd 0x054f10de
dd 0x07dc10de
dd 0x07dd10de
dd 0x07de10de
dd 0x07df10de
dd 0x076010de
dd 0x076110de
dd 0x076210de
dd 0x076310de
dd 0x0ab010de
dd 0x0ab110de
dd 0x0ab210de
dd 0x0ab310de
dd 0x0d7d10de
dd 0x0
 
db 'MTD80X',0
dd 0x08031516
dd 0x08001516
dd 0x08911516
dd 0x0
 
db 'dec21x4x',0
dd 0x00091011
dd 0x00191011
dd 0x09851317
dd 0x0
 
db 'R6040',0
dd 0x604017F3
dd 0x0
 
db 'i8254x',0
dd 0x10008086 ; 82542 (Fiber)
dd 0x10018086 ; 82543GC (Fiber)
dd 0x10048086 ; 82543GC (Copper)
dd 0x10088086 ; 82544EI (Copper)
dd 0x10098086 ; 82544EI (Fiber)
dd 0x100A8086 ; 82540EM
dd 0x100C8086 ; 82544GC (Copper)
dd 0x100D8086 ; 82544GC (LOM)
dd 0x100E8086 ; 82540EM
dd 0x100F8086 ; 82545EM (Copper)
dd 0x10108086 ; 82546EB (Copper)
dd 0x10118086 ; 82545EM (Fiber)
dd 0x10128086 ; 82546EB (Fiber)
dd 0x10138086 ; 82541EI
dd 0x10148086 ; 82541ER
dd 0x10158086 ; 82540EM (LOM)
dd 0x10168086 ; 82540EP (Mobile)
dd 0x10178086 ; 82540EP
dd 0x10188086 ; 82541EI
dd 0x10198086 ; 82547EI
dd 0x101a8086 ; 82547EI (Mobile)
dd 0x101d8086 ; 82546EB
dd 0x101e8086 ; 82540EP (Mobile)
dd 0x10268086 ; 82545GM
dd 0x10278086 ; 82545GM
dd 0x10288086 ; 82545GM
dd 0x105b8086 ; 82546GB (Copper)
dd 0x10758086 ; 82547GI
dd 0x10768086 ; 82541GI
dd 0x10778086 ; 82541GI
dd 0x10788086 ; 82541ER
dd 0x10798086 ; 82546GB
dd 0x107a8086 ; 82546GB
dd 0x107b8086 ; 82546GB
dd 0x107c8086 ; 82541PI
dd 0x10b58086 ; 82546GB (Copper)
dd 0x11078086 ; 82544EI
dd 0x11128086 ; 82544GC
dd 0x0
 
db 'RHINE', 0 ; VIA Rhine
dd 0x30431106
dd 0x61001106
dd 0x30651106
dd 0x31061106
dd 0x30531106
dd 0x0
 
dd 0x0 ; driverlist end
/programs/network/netcfg/netcfg.asm
0,0 → 1,548
;
; Netcfg v1.02
;
; Application to load network drivers in KolibriOS
;
; By hidnplayr
;
 
format binary as ""
 
use32
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd IM_END ; size of image
dd (I_END+0x100) ; memory for app
dd (I_END+0x100) ; esp
dd param, 0x0 ; I_Param , I_Icon
 
type_ethernet equ 1
 
include '../macros.inc'
 
START:
; first, check boot parameters
 
cmp byte[param], 0
je .noparams
 
mcall 40, 0
 
push .exit
cmp byte[param], 'A' ; A for All
je Get_PCI_Info
 
cmp byte[param], 'F' ; F for First
je Get_PCI_Info
 
ret
 
.exit:
mcall -1
 
.noparams:
call draw_window
 
still:
mcall 10 ; wait here for event
dec eax ; redraw request ?
jz red
dec eax ; key in buffer ?
jz key
dec eax ; button in buffer ?
jz button
jmp still
 
red: ; redraw
mcall 9, Proc_Info, -1 ; window redraw requested so get new window coordinates and size
mov eax, [Proc_Info.box.left]; store the window coordinates into the Form Structure
mov [Form + 2], ax ; x start position
mov eax, [Proc_Info.box.top];
mov [Form + 6], ax ; ystart position
mov eax, [Proc_Info.box.width] ;
mov [Form], ax ; window width
mov eax, [Proc_Info.box.height] ;
mov [Form + 4] ,ax ; window height
call draw_window ; go redraw window now
jmp still
 
key: ; key
mcall 2 ; just read it and ignore
jmp still
button: ; button
mcall 17 ; get id
 
cmp ah, 1 ; button id = 1 ?
jne @f
exit: mcall -1 ; close this program
@@:
cmp eax,0x0000ff00
jg load_drv
 
cmp ah, 4
je hook
 
cmp ah, 5
je reset
 
cmp ah, 6
je unload
 
jmp still
 
 
load_drv:
shr eax, 16
mov word [selected], ax
 
mov bl , 6 ; get a dword
mov bh , ah ; bus
mov ch , al ; dev
mov cl , 0 ; offset to device/vendor id
mcall 62 ; get ID's
 
mov word [PCI_Vendor], ax
shr eax, 16
mov word [PCI_Device], ax
call get_drv_ptr
 
mov ecx, eax
mcall 68, 16
 
mov [IOCTL.handle], eax
 
call draw_window
 
cmp [IOCTL.handle], 0
jne still
 
mcall 4, 20 shl 16 + 30, 1 shl 31 + 0x00ff0000 , load_error
 
jmp still
 
 
hook:
mov ax , [selected]
test ax , ax
jz still
 
mov [hardwareinfo.pci_dev], al
mov [hardwareinfo.pci_bus], ah
 
mov [IOCTL.io_code], 1 ; SRV_HOOK
mov [IOCTL.inp_size], 3
mov [IOCTL.input], hardwareinfo
mov [IOCTL.out_size], 0
mov [IOCTL.output], 0
 
mcall 68, 17, IOCTL
 
mov byte[drivernumber], al
 
jmp still
 
reset:
movzx ebx, byte[drivernumber]
mcall 74,,2
 
jmp still
 
unload:
movzx ebx, byte[drivernumber]
mcall 74,,3
 
jmp still
 
draw_window:
mcall 12, 1 ; start of draw
mcall 0, dword [Form], dword [Form + 4], 0x13ffffff, 0x805080d0, title
 
call Get_PCI_Info ; get pci version and last bus, scan for and draw each pci device
 
cmp edx, 20 shl 16 + 110
je .nonefound
 
mcall 4, 20 shl 16 + 100, 1 shl 31 + 0x00000000 , caption
 
cmp [selected], 0
jz .done
cmp [IOCTL.handle] ,0
jz .done
 
mcall 8, 18 shl 16 + 100, 35 shl 16 + 18, 4, 0x00007f00
mcall ,, 55 shl 16 + 18, 5, 0x0000007f
mcall ,, 75 shl 16 + 18, 6, 0x007f0000
 
mcall 4, 33 shl 16 + 42, 1 shl 31 + 0x00ffffff , btn_start
mcall , 33 shl 16 + 62, , btn_reset
mcall , 36 shl 16 + 82, , btn_stop
 
jmp .done
 
.nonefound:
mcall 4, 20 shl 16 + 30, 1 shl 31 + 0x00ff0000 , nonefound
.done:
mcall 12, 2 ; end of draw
ret
 
 
 
 
 
;------------------------------------------------------------------
;* Gets the PCI Version and Last Bus
Get_PCI_Info:
mcall 62, 0
mov word [PCI_Version], ax
mcall 62, 1
mov byte [PCI_LastBus], al
;----------------------------------------------------------
;* Get all devices on PCI Bus
mov edx, 20 shl 16 + 110 ; set start write position
cmp al , 0xff ; 0xFF means no pci bus found
jne Pci_Exists ;
ret ; if no bus then leave
Pci_Exists:
mov byte [V_Bus], 0 ; reset varibles
mov byte [V_Dev], 0 ;
Start_Enum:
mov bl , 6 ; get a dword
mov bh , byte [V_Bus] ; bus of pci device
mov ch , byte [V_Dev] ; device number/function
mov cl , 0 ; offset to device/vendor id
mcall 62 ; get ID's
 
cmp ax, 0 ; Vendor ID should not be 0 or 0xFFFF
je nextDev ; check next device if nothing exists here
cmp ax, 0xffff ;
je nextDev ;
 
mov word [PCI_Vendor], ax ; There is a device here, save the ID's
shr eax, 16 ;
mov word [PCI_Device], ax ;
mov bl , 4 ; Read config byte
mov bh , byte [V_Bus] ; Bus #
mov ch , byte [V_Dev] ; Device # on bus
mov cl , 0x08 ; Register to read (Get Revision)
mcall 62 ; Read it
mov byte [PCI_Rev], al ; Save it
mov cl , 0x0b ; Register to read (Get class)
mcall 62 ; Read it
mov byte [PCI_Class], al ; Save it
mov cl , 0x0a ; Register to read (Get Subclass)
mcall 62 ; Read it
mov byte [PCI_SubClass], al ; Save it
mov cl , 0x09 ; Register to read (Get Interface)
mcall 62 ; Read it
mov [PCI_Interface], al ; Save it
mov cl , 0x3c ; Register to read (Get IRQ)
@@: mcall 62 ; Read it
mov [PCI_IRQ], al ; Save it
 
; cmp byte [PCI_Class], 0 ; device from before class codes
; je @f
 
cmp byte [PCI_Class], 2 ; network controller
jne nextDev
; @@:
 
cmp byte[param], 0
jne load_and_start
 
mov cl, 0x0e
mcall 62
push eax
call Print_New_Device ; print device info to screen
pop eax
test al, al
js nextDev
 
nextdev2:
test byte [V_Dev], 7
jnz nextDev
or byte [V_Dev], 7
 
nextDev:
inc [V_Dev] ; lower 3 bits are the function number
 
jnz Start_Enum ; jump until we reach zero
mov byte [V_Dev], 0 ; reset device number
inc byte [V_Bus] ; next bus
mov al , byte [PCI_LastBus] ; get last bus
cmp byte [V_Bus], al ; was it last bus
jbe Start_Enum ; if not jump to keep searching
ret
 
 
 
load_and_start:
 
call get_drv_ptr
cmp eax, lbl_none
je .next
 
mov ecx, eax
mcall 68, 16
test eax, eax
jz .next
mov [IOCTL.handle], eax
 
mov al, [V_Dev]
mov [hardwareinfo.pci_dev], al
mov al, [V_Bus]
mov [hardwareinfo.pci_bus], al
 
mov [IOCTL.io_code], 1 ; SRV_HOOK
mov [IOCTL.inp_size], 3
mov [IOCTL.input], hardwareinfo
mov [IOCTL.out_size], 0
mov [IOCTL.output], 0
 
mcall 68, 17, IOCTL
 
.next:
cmp byte[param], 'A'
je nextdev2
jmp exit
 
 
 
;------------------------------------------------------------------
;* Print device info to screen
Print_New_Device:
 
push edx ; Magic ! (to print a button...)
 
mov ebx, 18 shl 16
mov bx , [Form]
sub bx , 36
 
mov cx , dx
dec cx
shl ecx, 16
add ecx, 9
 
movzx edx, byte [V_Bus]
shl dx , 8
mov dl , byte [V_Dev]
 
mov esi, 0x0000c0ff ; color: yellow if selected, blue otherwise
cmp word [selected], dx
jne @f
mov esi, 0x00c0c000
@@:
 
shl edx, 8
or dl , 0xff
 
mcall 8
pop edx
 
xor esi, esi ; Color of text
movzx ecx, word [PCI_Vendor] ; number to be written
mcall 47, 0x00040100 ; Write Vendor ID
 
add edx, (4*6+18) shl 16
movzx ecx, word [PCI_Device] ; get Vendor ID
mcall ; Draw Vendor ID to Window
 
add edx, (4*6+18) shl 16
movzx ecx, byte [V_Bus] ; get bus number
mcall ,0x00020100 ; draw bus number to screen
 
add edx, (2*6+18) shl 16
movzx ecx, byte [V_Dev] ; get device number
shr ecx, 3 ; device number is bits 3-7
mcall ; Draw device Number To Window
 
add edx, (2*6+18) shl 16
movzx ecx, byte [PCI_Rev] ; get revision number
mcall ; Draw Revision to screen
 
add edx, (2*6+18) shl 16
movzx ecx, [PCI_IRQ]
cmp cl , 0x0f ; IRQ must be between 0 and 15
ja @f
mcall
@@:
;
;Write Names
movzx ebx, dx ; Set y position
or ebx, 230 shl 16 ; set Xposition
 
;------------------------------------------------------------------
; Prints the Vendor's Name based on Vendor ID
;------------------------------------------------------------------
mov edx, VendorsTab
mov cx , word[PCI_Vendor]
.fn: mov ax , [edx]
add edx, 6
test ax , ax
jz .find
cmp ax , cx
jne .fn
.find: mov edx, [edx - 4]
mcall 4,, 0x80000000 ; lets print the vendor Name
 
;------------------------------------------------------------------
; Get description based on Class/Subclass
;------------------------------------------------------------------
mov eax, dword [PCI_Class]
and eax, 0xffffff
xor edx, edx
xor esi, esi
.fnc: inc esi
mov ecx, [Classes + esi * 8 - 8]
cmp cx , 0xffff
je .endfc
cmp cx , ax
jne .fnc
test ecx, 0xff000000
jz @f
mov edx, [Classes + esi * 8 - 4]
jmp .fnc
@@: cmp eax, ecx
jne .fnc
xor edx, edx
.endfc: test edx, edx
jnz @f
mov edx, [Classes + esi * 8 - 4]
@@:
add ebx, 288 shl 16
mcall 4,, 0x80000000,, 32 ; draw the text
movzx edx, bx ; get y coordinate
add edx, 0x0014000A ; add 10 to y coordinate and set x coordinate to 20
 
;------------------------------------------------------------------
; Print Driver Name
;------------------------------------------------------------------
push edx
add ebx, 120 shl 16
push ebx
 
call get_drv_ptr
mov edx, eax
pop ebx
mcall 4,,0x80000000 ; lets print the vendor Name
pop edx
ret
 
get_drv_ptr:
mov eax, driverlist ; eax will be the pointer to latest driver title
mov ebx, driverlist ; ebx is the current pointer
mov ecx, dword[PCI_Vendor] ; the device/vendor id of we want to find
 
driverloop:
inc ebx
 
cmp byte[ebx],0
jne driverloop
 
inc ebx ; the device/vendor id list for the driver eax is pointing to starts here.
 
deviceloop:
cmp dword[ebx],0
je nextdriver
 
cmp dword[ebx],ecx
je driverfound
 
add ebx,4
jmp deviceloop
 
nextdriver:
add ebx,4
 
cmp dword[ebx],0
je nodriver
 
mov eax,ebx
jmp driverloop
 
nodriver:
mov eax, lbl_none ; lets print the vendor Name
ret
 
driverfound:
ret
 
include 'vendors.inc'
include 'drivers.inc'
 
 
;------------------------------------------------------------------
; DATA AREA
 
 
DATA
 
 
Form: dw 800 ; window width (no more, special for 800x600)
dw 100 ; window x start
dw 220 ; window height
dw 100 ; window y start
 
title db 'Network Driver Control Center', 0
 
caption db 'Vendor Device Bus Dev Rev IRQ Company Description DRIVER',0
nonefound db 'No compatible devices were found!',0
btn_start db 'Start device',0
btn_reset db 'Reset device',0
btn_stop db 'Stop device',0
lbl_none db 'none',0
load_error db 'Could not load driver!',0
 
hardwareinfo:
.type db 1 ; pci
.pci_bus db ?
.pci_dev db ?
 
 
IM_END:
 
;------------------------------------------------------------------
; UNINITIALIZED DATA AREA
 
 
IOCTL:
.handle dd ?
.io_code dd ?
.input dd ?
.inp_size dd ?
.output dd ?
.out_size dd ?
 
drivernumber db ?
MAC dp ?
 
 
type db ?
selected dw ?
V_Bus db ?
V_Dev db ?
PCI_Version dw ?
PCI_LastBus db ?
PCI_Vendor dw ?
PCI_Device dw ?
PCI_Bus db ?
PCI_Dev db ?
PCI_Rev db ?
; don`t change order!!!
PCI_Class db ?
PCI_SubClass db ?
PCI_Interface db ?
PCI_IRQ db ?
 
Proc_Info process_information
 
param rb 1024
 
 
I_END:
/programs/network/netcfg/vendors.inc
0,0 → 1,1072
; AUTHOR: Victor Alberto Gil Hancco Laquita <vhanla@gmail.com>
; This list might content mistakes, plz report it
; There are 865 Lists of Vendors' Names
; Date: 8/14/2005
;
; maybe this list is outdated...
; (the source was from 2004 list)
 
; changed 11/05/2006: + 3 vendors and no more label 'PREVIOUSVERSIONLIST'
; so the total quantity of vendors is 875 now (changes by Sergey Kuzmin)
 
; changed 16/08/2006: + 122 vendors
; so the total quantity of vendors is 987 now (changes by Sergey Kuzmin)
 
; changed ??/04/2007:
; size optimezed
; total quantity of vendors is 997 now (changes by Mihailov Ilia)
 
 
macro VendorID a,b { ; by mike.dld
dw a
dd _vtmp#a
\iglobal
_vtmp#a db b
db 0
\};endg
}
 
macro ClassID a,b,c,d {
db a
db b
local tt
 
if c eq
db 0
db 1
tt = 'x'
else
db c
db 0
tt = c
end if
dd _ctmp#a#b#tt
\iglobal
_ctmp#a#b#tt db d
db 0
\};endg
}
 
;--------------------------------------
VendorsTab:
VendorID 0x0033, 'PARADYNE CORP.'
VendorID 0x003D, 'Lockheed Martin Corp'
VendorID 0x0100, 'NCIPHER CORP. LTD'
VendorID 0x0675, 'DYNALINK'
VendorID 0x0571, 'BERKOM'
VendorID 0x0A89, 'BREA TECHNOLOGIES INC'
VendorID 0x0E11, 'COMPAQ COMPUTER CORP.'
VendorID 0x1000, 'SYMBIOS LOGIC INC/LSI Logic'
VendorID 0x1001, 'KOLTER ELECTRONIC'
VendorID 0x1002, 'ATI TECHNOLOGIES INC'
VendorID 0x1003, 'ULSI'
VendorID 0x1004, 'VLSI TECHNOLOGY INC'
VendorID 0x1005, 'ADL'
VendorID 0x100B, 'NATIONAL SEMICONDUCTOR CORPORATION'
VendorID 0x100C, 'Tseng Labs'
VendorID 0x100E, 'Weitek'
VendorID 0x1010, 'VIDEO LOGIC LTD'
VendorID 0x1011, 'Digital Equipment Corporation'
VendorID 0x1013, 'Cirrus Logic'
VendorID 0x1014, 'IBM'
VendorID 0x1017, 'Spea Software AG'
VendorID 0x1018, 'UNISYS CORPORATION'
VendorID 0x1019, 'ELITEGROUP COMPUTER SYS'
VendorID 0x101A, 'NCR Corporation'
VendorID 0x101E, 'AMERICAN MEGATRENDS'
VendorID 0x1020, 'HITACHI COMPUTER PRODUCTS'
VendorID 0x1021, 'OKI ELECTRIC INDUSTRY CO. LTD.'
VendorID 0x1022, 'Advanced Micro Devices'
VendorID 0x1023, 'TRIDENT MICROSYSTEMS'
VendorID 0x1025, 'Acer Incorporated'
VendorID 0x1028, 'DELL COMPUTER CORPORATION'
VendorID 0x102A, 'LSI LOGIC CORPORATION'
VendorID 0x102B, 'MATROX GRAPHICS'
VendorID 0x102C, 'Asiliant (Chips And Technologies)'
VendorID 0x102D, 'Wyse Technologies'
VendorID 0x102F, 'TOSHIBA AMERICA'
VendorID 0x1031, 'miro Computer Products AG'
VendorID 0x1033, 'NEC CORPORATION'
VendorID 0x1036, 'Future Domain'
VendorID 0x1038, 'AMP'
VendorID 0x1039, 'SILICON INTEGRATED SYSTEMS'
VendorID 0x103C, 'Hewlett-Packard Company'
VendorID 0x103F, 'SYNOPSYS/LOGIC MODELING GROUP'
VendorID 0x1042, 'Micron Electronics'
VendorID 0x1043, 'ASUSTEK COMPUTER'
VendorID 0x1044, 'DISTRIBUTED PROCESSING TECHNOLOGY'
VendorID 0x1045, 'OPTI INC.'
VendorID 0x1048, 'ELSA AG'
VendorID 0x1049, 'FOUNTAIN TECHNOLOGIES'
VendorID 0x104A, 'STMicroelectronics'
VendorID 0x104B, 'BusLogic'
VendorID 0x104C, 'TEXAS INSTRUMENTS'
VendorID 0x104D, 'SONY CORPORATION'
VendorID 0x104E, 'Oak Technology'
VendorID 0x104F, 'Co-Time Computer Ltd.'
VendorID 0x1050, 'WINBOND ELECTRONICS CORP'
VendorID 0x1051, 'Anigma Corp.'
VendorID 0x1054, 'HITACHI'
VendorID 0x1055, 'Standard Microsystems Corp.'
VendorID 0x1057, 'Motorola'
VendorID 0x1058, 'ETRI'
VendorID 0x1059, 'TEKNOR INDUSTRIAL COMPUTERS INC'
VendorID 0x105A, 'PROMISE TECHNOLOGY'
VendorID 0x105B, 'FOXCONN INTERNATIONAL INC'
VendorID 0x105D, 'NUMBER 9 VISUAL TECHNOLOGY'
VendorID 0x105F, 'INFOTRONIC AMERICA INC'
VendorID 0x1060, 'United Microelectronics'
VendorID 0x1061, '8x8 Inc.'
VendorID 0x1063, 'OCEAN MANUFACTURING LTD'
VendorID 0x1064, 'ALCATEL'
VendorID 0x1065, 'Texas Microsystems'
VendorID 0x1066, 'Picopower Technology'
VendorID 0x1067, 'MITSUBISHI ELECTRIC AMERICA'
VendorID 0x1068, 'DIVERSIFIED TECHNOLOGY'
VendorID 0x1069, 'MYLEX CORPORATION'
VendorID 0x106B, 'APPLE COMPUTER INC.'
VendorID 0x106C, 'Hyundai Electronics America'
VendorID 0x106D, 'SEQUENT COMPUTER SYSTEMS'
VendorID 0x1070, 'DAEWOO TELECOM LTD'
VendorID 0x1071, 'MITAC'
VendorID 0x1073, 'YAMAHA CORPORATION'
VendorID 0x1074, 'Nexgen Microsystems'
VendorID 0x1076, 'Chaintech Comp.'
VendorID 0x1077, 'QLOGIC Corporation'
VendorID 0x1078, 'Cyrix Corporation'
VendorID 0x1079, 'I-BUS'
VendorID 0x107B, 'GATEWAY 2000'
VendorID 0x107D, 'Leadtek Research'
VendorID 0x107E, 'INTERPHASE CORPORATION'
VendorID 0x107F, 'Data Technology Corporation'
VendorID 0x1080, 'Cypress Semiconductor'
VendorID 0x1081, 'Radius Inc.'
VendorID 0x1083, 'Forex Computer Corporation'
VendorID 0x1085, 'Tulip Computers International BV'
VendorID 0x1087, 'Cache Computer'
VendorID 0x108A, 'SBS Operations'
VendorID 0x108D, 'OLICOM'
VendorID 0x108E, 'Sun Microsystems'
VendorID 0x1091, 'Intergraph Corporation'
VendorID 0x1092, 'Diamond Computer Systems'
VendorID 0x1093, 'National Instruments'
VendorID 0x1095, 'SILICON IMAGE (WAS CMD TECHNOLOGY INC)'
VendorID 0x1096, 'ALACRON'
VendorID 0x1097, 'APPIAN Graphics/ETMA'
VendorID 0x1098, 'Quantum Designs Ltd.'
VendorID 0x109A, 'PACKARD BELL NEC'
VendorID 0x109E, 'BROOKTREE CORPORATION'
VendorID 0x109F, 'TRIGEM COMPUTER INC.'
VendorID 0x10A0, 'MEIDENSHA CORPORATION'
VendorID 0x10A2, 'QUANTUM EFFECT DESIGN'
VendorID 0x10A4, 'Globe Manufacturing Sales'
VendorID 0x10A8, 'Sierra Semiconductor'
VendorID 0x10A9, 'SILICON GRAPHICS'
VendorID 0x10AC, 'HONEYWELL IAC'
VendorID 0x10AD, 'Winbond Systems Labs'
VendorID 0x10AF, 'MICRO COMPUTER SYSTEMS INC'
VendorID 0x10B5, 'PLX TECHNOLOGY.'
VendorID 0x10B6, 'MADGE NETWORKS'
VendorID 0x10B7, '3COM Corp, Networking Division'
VendorID 0x10B8, 'Standard Microsystems Corporation'
VendorID 0x10B9, 'ACER LABS Incorp.'
VendorID 0x10BA, 'MITSUBISHI ELECTRIC CORP.'
VendorID 0x10BD, 'Surecom Technology'
VendorID 0x10C2, 'AUSPEX SYSTEMS INC.'
VendorID 0x10C3, 'Samsung Semiconductors'
VendorID 0x10C4, 'Award Software International Inc.'
VendorID 0x10C8, 'NEOMAGIC CORPORATION'
VendorID 0x10CA, 'FUJITSU MICROELECTRONIC'
VendorID 0x10CB, 'OMRON CORPORATION'
VendorID 0x10CD, 'ADVANCED SYSTEM PRODUCTS'
VendorID 0x10CF, 'FUJITSU LIMITED'
VendorID 0x10D1, 'FUTUREPLUS SYSTEMS CORP.'
VendorID 0x10D2, 'MOLEX INCORPORATED'
VendorID 0x10D9, 'Macronix International Co. Ltd.'
VendorID 0x10DB, 'ROHM LSI SYSTEMS'
VendorID 0x10DC, 'CERN-European Lab. for Particle Physics'
VendorID 0x10DD, 'EVANS & SUTHERLAND'
VendorID 0x10DE, 'NVIDIA CORPORATION'
VendorID 0x10DF, 'EMULEX CORPORATION'
VendorID 0x10E1, 'TEKRAM TECHNOLOGY CO.LTD.'
VendorID 0x10E3, 'TUNDRA SEMICONDUCTOR CORP'
VendorID 0x10E5, 'MICRO INDUSTRIES CORPORATION'
VendorID 0x10E8, 'Applied Micro Circuits Corp.'
VendorID 0x10EA, 'Tvia, Inc.'
VendorID 0x10EB, 'Artist Graphics'
VendorID 0x10EC, 'REALTEK SEMICONDUCTOR CORP.'
VendorID 0x10ED, 'Ascii Corporation'
VendorID 0x10EE, 'XILINX'
VendorID 0x10EF, 'Racore Computer Products'
VendorID 0x10F0, 'Curtiss-Wright Controls Embedded Computing'
VendorID 0x10F1, 'TYAN COMPUTER'
VendorID 0x10F4, 'S-Mos Systems'
VendorID 0x10F5, 'NKK CORPORATION'
VendorID 0x10F6, 'Creative Electronic Systems SA'
VendorID 0x10FA, 'Truevision'
VendorID 0x10FB, 'Thesys Microelectronics'
VendorID 0x10FC, 'I-O DATA DEVICE'
VendorID 0x10FE, 'FAST MULTIMEDIA AG'
VendorID 0x1101, 'INITIO CORPORATION'
VendorID 0x1102, 'Creative Labs'
VendorID 0x1105, 'SIGMA DESIGNS'
VendorID 0x1106, 'VIA TECHNOLOGIES'
VendorID 0x1107, 'ASCEND COMMUNICATIONS/Stratus Computer'
VendorID 0x1108, 'Proteon Inc.'
VendorID 0x1109, 'Adaptec/Cogent Data Technologies Inc'
VendorID 0x110A, 'SIEMENS PC SYSTEME GMBH'
VendorID 0x110B, 'Chromatic Research Inc'
VendorID 0x1111, 'SANTA CRUZ OPERATION'
VendorID 0x1112, 'Osicom Technologies Inc.'
VendorID 0x1113, 'ACCTON TECHNOLOGY'
VendorID 0x1114, 'Atmel Corp.'
VendorID 0x1116, 'Media 100, Inc.'
VendorID 0x1117, 'Datacube Inc.'
VendorID 0x1118, 'FCI ELECTRONICS'
VendorID 0x1119, 'ICP-VORTEX COMPUTERSYSTEM GMBH'
VendorID 0x111A, 'EFFICIENT NETWORKS'
VendorID 0x111C, 'Tricord Systems Inc.'
VendorID 0x111D, 'INTEGRATED DEVICE TECH'
VendorID 0x111F, 'Precision Digital Images'
VendorID 0x1120, 'EMC CORPORATION'
VendorID 0x1127, 'FORE SYSTEMS INC'
VendorID 0x112A, 'HERMES ELECTRONICS COMPANY'
VendorID 0x112E, 'Infomedia'
VendorID 0x112F, 'IMAGING TECHNOLOGY'
VendorID 0x1131, 'PHILIPS SEMICONDUCTORS'
VendorID 0x1132, 'MITEL CORP'
VendorID 0x1133, 'Eicon Networks Corporation'
VendorID 0x1134, 'MERCURY COMPUTER SYSTEMS'
VendorID 0x1135, 'FUJI XEROX CO LTD'
VendorID 0x1136, 'MOMENTUM DATA SYSTEMS'
VendorID 0x1137, 'CISCO SYSTEMS INC'
VendorID 0x1138, 'ZIATECH CORPORATION'
VendorID 0x113C, 'CYCLONE MICROSYSTEMS.'
VendorID 0x113E, 'SANYO ELECTRIC CO-Information Systems Division'
VendorID 0x113F, 'Equinox Systems'
VendorID 0x1141, 'CREST MICROSYSTEM INC.'
VendorID 0x1142, 'Alliance Semiconductor CA - USA'
VendorID 0x1144, 'Cincinnati Milacron'
VendorID 0x1145, 'WORKBIT CORPORATION'
VendorID 0x1146, 'FORCE COMPUTERS GMBH'
VendorID 0x1147, 'Interface Corp'
VendorID 0x1148, 'SYSKONNECT/Marvell'
VendorID 0x114A, 'VMIC'
VendorID 0x114C, 'ANNABOOKS'
VendorID 0x114F, 'DIGI INTERNATIONAL'
VendorID 0x1154, 'MELCO INC'
VendorID 0x1155, 'Pine Technology Ltd'
VendorID 0x1158, 'Voarx R&D Inc'
VendorID 0x1159, 'Mutech'
VendorID 0x115C, 'PHOTRON LTD.'
VendorID 0x115D, 'XIRCOM'
VendorID 0x1161, 'PFU LIMITED'
VendorID 0x1163, 'RENDITION'
VendorID 0x1165, 'Imagraph Corporation'
VendorID 0x1166, 'Reliance Computer Corp./ServerWorks'
VendorID 0x1169, 'Centre f/Dev. of Adv. Computing'
VendorID 0x116A, 'Polaris Communications'
VendorID 0x116E, 'ELECTRONICS FOR IMAGING'
VendorID 0x1170, 'INVENTEC CORPORATION'
VendorID 0x1171, 'BLUE WAVE SYSTEMS'
VendorID 0x1172, 'ALTERA CORPORATION'
VendorID 0x1176, 'SBE'
VendorID 0x1178, 'Alfa Inc'
VendorID 0x1179, 'TOSHIBA AMERICA INFO SYSTEMS'
VendorID 0x117B, 'GCE-8320B'
VendorID 0x117E, 'T/R Systems'
VendorID 0x1180, 'RICOH CO LTD'
VendorID 0x1185, 'Dataworld'
VendorID 0x1186, 'D-LINK SYSTEM INC'
VendorID 0x1187, 'ADVANCED TECHNOLOGY LABORATORIES'
VendorID 0x1189, 'MATSUSHITA ELECTIC INDUSTRIAL CO LTD'
VendorID 0x118B, 'PLATYPUS TECHNOLOGY PTY LTD'
VendorID 0x118C, 'Corollary Inc'
VendorID 0x118D, 'BitFlow Inc'
VendorID 0x118E, 'Hermstedt AG'
VendorID 0x1190, 'Tripace'
VendorID 0x1191, 'ACARD TECHNOLOGY'
VendorID 0x1193, 'ZeitNet'
VendorID 0x1195, 'RATOC SYSTEMS INC'
VendorID 0x1197, 'Gage Applied Technologies'
VendorID 0x1199, 'Attachmate Corp.'
VendorID 0x119A, 'MINDSHARE.'
VendorID 0x119B, 'Omega Micro Inc.'
VendorID 0x119D, 'BUG.'
VendorID 0x119E, 'FUJITSU MICROELECTRONICS LTD.'
VendorID 0x119F, 'BULL HN INFORMATION SYSTEMS'
VendorID 0x11A1, 'HAMAMATSU PHOTONICS K.K.'
VendorID 0x11A8, 'Systech Corp.'
VendorID 0x11A9, 'InnoSys Inc.'
VendorID 0x11AA, 'ACTEL'
VendorID 0x11AB, 'GALILEO TECHNOLOGY LTD/Marvell Semiconductor, Inc.'
VendorID 0x11AD, 'LITE-ON COMMUNICATIONS INC'
VendorID 0x11AE, 'SCITEX CORPORATION'
VendorID 0x11AF, 'AVID TECHNOLOGY INC'
VendorID 0x11B0, 'V3 SEMICONDUCTOR INC./Quicklogic Corp'
VendorID 0x11B2, 'EASTMAN KODAK'
VendorID 0x11B3, 'BARR SYSTEMS INC.'
VendorID 0x11B5, 'Radstone Technology Ltd.'
VendorID 0x11B8, 'Xpoint Technologies Inc'
VendorID 0x11B9, 'Pathlight Technology Inc.'
VendorID 0x11BC, 'Network Peripherals Inc'
VendorID 0x11BD, 'Pinnacle Systems Inc.'
VendorID 0x11BF, 'ASTRODESIGN'
VendorID 0x11C1, 'AGERE/LUCENT'
VendorID 0x11C6, 'DAINIPPON SCREEN MFG. CO. LTD'
VendorID 0x11C8, 'DOLPHIN INTERCONNECT SOLUTIONS AS'
VendorID 0x11C9, 'MAGMA'
VendorID 0x11CA, 'LSI SYSTEMS'
VendorID 0x11CB, 'SPECIALIX INTERNATIONAL LTD'
VendorID 0x11CE, 'NETACCESS/Primary Rate Inc'
VendorID 0x11D0, 'LOCKHEED MARTIN-Electronics & Communications'
VendorID 0x11D1, 'AuraVision Corporation'
VendorID 0x11D2, 'INTERCOM INC.'
VendorID 0x11D4, 'Analog Devices, Inc.'
VendorID 0x11D5, 'IKON CORPORATION/Tahoma Technology'
VendorID 0x11D9, 'TOSHIBA TEC CORPORATION'
VendorID 0x11DA, 'NOVELL'
VendorID 0x11DB, 'Sega Enterprises Ltd'
VendorID 0x11DE, 'Zoran Corporation'
VendorID 0x11DF, 'NEW WAVE PDG'
VendorID 0x11E3, 'QUICKLOGIC CORPORATION'
VendorID 0x11EC, 'CORECO INC'
VendorID 0x11EE, 'DOME IMAGING SYSTEMS INC'
VendorID 0x11F0, 'Compu-Shack GmbH'
VendorID 0x11F4, 'Kinetic Systems Corporation'
VendorID 0x11F6, 'Powermatic Data Systems Ltd'
VendorID 0x11F8, 'PMC-SIERRA INC'
VendorID 0x11FE, 'Comtrol Corp'
VendorID 0x1202, 'Network General Corp'
VendorID 0x1203, 'AGFA CORPORATION'
VendorID 0x1206, 'AMDAHL CORPORATION'
VendorID 0x1208, 'Parsytec GmbH'
VendorID 0x1209, 'Sci Systems Inc'
VendorID 0x120E, 'Cyclades Corporation'
VendorID 0x120F, 'ESSENTIAL COMMUNICATIONS'
VendorID 0x1214, 'PERFORMANCE TECHNOLOGIES.'
VendorID 0x1216, 'PURUP-EskoFot A/S'
VendorID 0x1217, 'O2MICRO.'
VendorID 0x121A, '3DFX INTERACTIVE'
VendorID 0x121B, 'VIRATA LTD'
VendorID 0x1220, 'Ariel Corporation'
VendorID 0x1221, 'CONTEC CO. LTD'
VendorID 0x1223, 'ARTESYN COMMUNICATIONS PRODUCTS INC'
VendorID 0x1224, 'Interactive Images'
VendorID 0x1227, 'TECH-SOURCE'
VendorID 0x122C, 'SICAN GMBH'
VendorID 0x122D, 'Aztech System Ltd'
VendorID 0x1232, 'MARCONI COMMUNICATIONS LTD'
VendorID 0x1236, 'Sigma Designs, Inc'
VendorID 0x124C, 'Solitron Technologies Inc.'
VendorID 0x124D, 'Stallion Technologies'
VendorID 0x124F, 'Infortrend Technology Inc'
VendorID 0x1256, 'Perceptive Solutions Inc.'
VendorID 0x1258, 'Gilbarco Inc.'
VendorID 0x125B, 'Asix Electronics Corp.'
VendorID 0x1266, 'Microdyne Corp.'
VendorID 0x1267, 'S.A. Telecommunications'
VendorID 0x1361, 'SOLITON SYSTEMS K.K.'
VendorID 0x123C, 'CENTURY SYSTEMS.'
VendorID 0x123D, 'Engineering Design Team Inc.'
VendorID 0x123F, 'C-CUBE MICROSYSTEMS'
VendorID 0x1242, 'JAYCOR NETWORKS INC./JNI Corporation'
VendorID 0x1244, 'AVM AUDIOVISUELLES MKTG & COMPUTER SYSTEM GMBH'
VendorID 0x124B, 'SBS TECHNOLOGIES'
VendorID 0x1250, 'Hitachi Microcomputer System Ltd.'
VendorID 0x1253, 'GUZIK TECHNICAL ENTERPRISES'
VendorID 0x1255, 'OPTIBASE LTD'
VendorID 0x1259, 'ALLIED TELESYN INTERNATIONAL'
VendorID 0x125C, 'AURORA TECHNOLOGIES.'
VendorID 0x125D, 'ESS TECHNOLOGY, INC.'
VendorID 0x125F, 'CONCURRENT TECHNOLOGIES'
VendorID 0x1260, 'INTERSIL CORP'
VendorID 0x1261, 'MATSUSHITA-KOTOBUKI ELECTRONICS'
VendorID 0x1264, 'AVAL NAGASAKI CORPORATION'
VendorID 0x1268, 'TEKTRONIX'
VendorID 0x126C, 'Nortel Networks Corp.'
VendorID 0x126D, 'SPLASH TECHNOLOGY.'
VendorID 0x126E, 'SUMITOMO METAL INDUSTRIES'
VendorID 0x126F, 'SILICON MOTION.'
VendorID 0x1270, 'OLYMPUS OPTICAL CO. LTD.'
VendorID 0x1274, 'Creative Labs (was Ensoniq, Malvern)'
VendorID 0x1275, 'NETWORK APPLIANCE CORPORATION'
VendorID 0x1278, 'Transtech Parallel Systems'
VendorID 0x1279, 'TRANSMETA CORPORATION'
VendorID 0x127A, 'CONEXANT, ROCKWELL'
VendorID 0x127D, 'VELA RESEARCH LP'
VendorID 0x127F, 'FUJIFILM'
VendorID 0x1281, 'YOKOGAWA ELECTRIC CORPORATION'
VendorID 0x1283, 'Integrated Technology Express Inc.'
VendorID 0x1286, 'MAZET GMBH'
VendorID 0x128B, 'TRANSWITCH CORPORATION'
VendorID 0x128D, 'G2 Networks Inc.'
VendorID 0x128F, 'TATENO DENNOU.'
VendorID 0x1290, 'TOSHIBA PERSONAL COMPUTER SYSTEM CORP.'
VendorID 0x1291, 'NCS COMPUTER ITALIA SRL'
VendorID 0x1292, 'TRITECH MICROELECTRONICS INC'
VendorID 0x1297, 'SHUTTLE COMPUTER'
VendorID 0x1299, 'KNOWLEDGE TECHNOLOGY LAB.'
VendorID 0x129A, 'VMETRO Inc.'
VendorID 0x129E, 'VICTOR COMPANY OF JAPAN'
VendorID 0x12A0, 'ALLEN- BRADLEY COMPANY'
VendorID 0x12A3, 'Lucent Technologies AMR'
VendorID 0x12A7, 'AMO GMBH'
VendorID 0x12A9, 'XIOTECH CORPORATION'
VendorID 0x12AB, 'YUAN YUAN ENTERPRISE CO. LTD.'
VendorID 0x12AE, 'Alteon Networks Inc.'
VendorID 0x12B6, 'NATURAL MICROSYSTEMS'
VendorID 0x12B7, 'COGNEX MODULAR VISION SYSTEMS DIV.-ACUMEN INC.'
VendorID 0x12B9, '3Com Corp, Modem Division'
VendorID 0x12BC, 'ARRAY MICROSYSTEMS'
VendorID 0x12BE, 'ANCHOR CHIPS INC.'
VendorID 0x12BF, 'Fujifilm Microdevices'
VendorID 0x12C0, 'INFIMED'
VendorID 0x12C3, 'Holtek Microelectronics Inc.'
VendorID 0x12C4, 'Connect Tech Inc'
VendorID 0x12C6, 'Mitan Corporation'
VendorID 0x12C7, 'Dialogic Corp'
VendorID 0x12CA, 'Integrated Computing Engines'
VendorID 0x12CD, 'Aims Lab'
VendorID 0x12D2, 'NVIDIA (WAS: STB,SGS THOMPSON)'
VendorID 0x12D3, 'GE VINGMED ULTRASOUND AS'
VendorID 0x12D4, 'COMVERSE NETWORKS SYSTEM & Ulticom, Inc.'
VendorID 0x12D5, 'Equator Technologies'
VendorID 0x12D6, 'Analogic Corp'
VendorID 0x12D8, 'PERICOM SEMICONDUCTOR'
VendorID 0x12D9, 'Aculab PLC'
VendorID 0x12DA, 'True Time Inc.'
VendorID 0x12DE, 'Rainbow Technologies'
VendorID 0x12DF, 'SBS Technologies Inc'
VendorID 0x12E0, 'Chase Research PLC'
VendorID 0x12E2, 'Datum Inc. Bancomm-Timing Division'
VendorID 0x12E4, 'Brooktrout Technology Inc'
VendorID 0x12E7, 'Sebring Systems'
VendorID 0x12EA, 'Real Vision'
VendorID 0x12EB, 'Aureal Semiconductor'
VendorID 0x12EC, '3A'
VendorID 0x12F0, 'PENTEK'
VendorID 0x12F7, 'COGNEX INC.'
VendorID 0x12FB, 'Spectrum Signal Processing'
VendorID 0x12FC, 'CAPITAL EQUIPMENT CORP'
VendorID 0x12FE, 'ESD Electronic System Design GmbH'
VendorID 0x1304, 'Juniper Networks Inc.'
VendorID 0x1307, 'Computer Boards'
VendorID 0x1308, 'LEVEL ONE COMMUNICATIONS/Jato Technologies Inc.'
VendorID 0x130A, 'Mitsubishi Electric MicroComputer'
VendorID 0x130B, 'Colorgraphic Communications Corp'
VendorID 0x130F, 'Advanet Inc'
VendorID 0x1310, 'GESPAC'
VendorID 0x1313, 'YASKAWA ELECTRIC CO.'
VendorID 0x1316, 'TERADYNE INC.'
VendorID 0x1317, 'ADMTEK INC'
VendorID 0x1318, 'Packet Engines Inc.'
VendorID 0x1319, 'ForteMedia'
VendorID 0x131F, 'SIIG Inc'
VendorID 0x1325, 'SALIX TECHNOLOGIES INC'
VendorID 0x1326, 'SeaChange International'
VendorID 0x1331, 'RadiSys Corp.'
VendorID 0x133D, 'PRISA NETWORKS'
VendorID 0x133F, 'SCM MICROSYSTEMS'
VendorID 0x1342, 'PROMAX SYSTEMS INC'
VendorID 0x1344, 'MICRON TECHNOLOGY INC'
VendorID 0x134A, 'Domex'
VendorID 0x134B, 'ARK RESEARCH CORP.'
VendorID 0x134C, 'CHORI JOHO SYSTEM CO. LTD'
VendorID 0x134D, 'PC-TEL INC'
VendorID 0x135A, 'BRAIN BOXES LIMITED'
VendorID 0x135C, 'QUATECH INC'
VendorID 0x135E, 'SEALEVEL SYSTEMS INC'
VendorID 0x135F, 'I-DATA INTERNATIONAL A-S'
VendorID 0x1360, 'MEINBERG FUNKUHREN'
VendorID 0x1363, 'PHOENIX TECHNOLOGIES LTD'
VendorID 0x1365, 'HYPERCOPE'
VendorID 0x1367, 'HITACHI ZOSEN CORPORATION'
VendorID 0x1368, 'SKYWARE CORPORATION'
VendorID 0x1369, 'DIGIGRAM'
VendorID 0x136B, 'KAWASAKI STEEL CORPORATION'
VendorID 0x136C, 'ADTEK SYSTEM SCIENCE CO LTD'
VendorID 0x1375, 'BOEING-SUNNYVALE'
VendorID 0x1376, 'LAN Media Corporation'
VendorID 0x1377, 'ELECTRONIC EQUIPMENT PRODUCTION & DISTRIBUTION'
VendorID 0x137A, 'MARK OF THE UNICORN INC'
VendorID 0x137B, 'PPT VISION'
VendorID 0x137C, 'IWATSU ELECTRIC CO LTD'
VendorID 0x137D, 'DYNACHIP CORPORATION'
VendorID 0x1380, 'SANRITZ AUTOMATION CO LTC'
VendorID 0x1381, 'BRAINS CO. LTD'
VendorID 0x1383, 'CONTROLNET INC'
VendorID 0x1384, 'STELLAR SEMICONDUCTOR INC'
VendorID 0x1385, 'NETGEAR'
VendorID 0x1387, 'SYSTRAN CORP'
VendorID 0x1388, 'HITACHI INFORMATION TECHNOLOGY CO LTD'
VendorID 0x1389, 'APPLICOM INTERNATIONAL'
VendorID 0x138A, 'SITERA'
VendorID 0x138B, 'TOKIMEC INC'
VendorID 0x138E, 'BASLER GMBH'
VendorID 0x138F, 'PATAPSCO DESIGNS INC'
VendorID 0x1393, 'MOXA TECHNOLOGIES CO LTD'
VendorID 0x1394, 'LEVEL ONE COMMUNICATIONS'
VendorID 0x1395, 'AMBICOM INC'
VendorID 0x1396, 'CIPHER SYSTEMS INC'
VendorID 0x1397, 'COLOGNE CHIP DESIGNS GMBH'
VendorID 0x1398, 'CLARION CO. LTD'
VendorID 0x1399, 'RIOS SYSTEMS CO LTD'
VendorID 0x139A, 'ALACRITECH INC'
VendorID 0x139C, 'QUANTUM 3D INC'
VendorID 0x139D, 'XSTREAMS PLC/ EPL LIMITED'
VendorID 0x139E, 'ECHOSTAR DATA NETWORKS'
VendorID 0x139F, 'AETHRA S.R.L.'
VendorID 0x13A0, 'CRYSTAL GROUP INC'
VendorID 0x13A1, 'KAWASAKI HEAVY INDUSTRIES LTD'
VendorID 0x13A2, 'OSITECH COMMUNICATIONS INC'
VendorID 0x13A4, 'RASCOM INC'
VendorID 0x13A7, 'TELES AG'
VendorID 0x13A8, 'EXAR CORP.'
VendorID 0x13A9, 'SIEMENS MEDICAL SYSTEMS'
VendorID 0x13AA, 'NORTEL NETWORKS-BWA DIVISION'
VendorID 0x13AF, 'T.SQWARE'
VendorID 0x13B1, 'TAMURA CORPORATION'
VendorID 0x13B4, 'WELLBEAN CO INC'
VendorID 0x13B5, 'ARM Ltd'
VendorID 0x13B6, 'DLoG GMBH'
VendorID 0x13B8, 'NOKIA TELECOMMUNICATIONS OY'
VendorID 0x13BD, 'SHARP CORPORATION'
VendorID 0x13BF, 'SHAREWAVE INC'
VendorID 0x13C0, 'Microgate Corp.'
VendorID 0x13C1, '3ware Inc.'
VendorID 0x13C2, 'TECHNOTREND SYSTEMTECHNIK GMBH'
VendorID 0x13C3, 'JANZ COMPUTER AG'
VendorID 0x13C6, 'CONDOR ENGINEERING INC'
VendorID 0x13C7, 'BLUE CHIP TECHNOLOGY LTD'
VendorID 0x13CA, 'IOMEGA CORPORATION'
VendorID 0x13CC, 'METHEUS CORPORATION'
VendorID 0x13CF, 'STUDIO AUDIO & VIDEO LTD'
VendorID 0x13D0, 'B2C2'
VendorID 0x13D1, 'ABOCOM SYSTEMS'
VendorID 0x13D2, 'SHARK MULTIMEDIA INC'
VendorID 0x13D3, 'IMC NETWORKS'
VendorID 0x13D4, 'GRAPHICS MICROSYSTEMS INC'
VendorID 0x13D6, 'K.I. TECHNOLOGY CO LTD'
VendorID 0x13D7, 'TOSHIBA ENGINEERING CORPORATION'
VendorID 0x13D8, 'PHOBOS CORPORATION'
VendorID 0x13D9, 'APEX INC'
VendorID 0x13DC, 'NETBOOST CORPORATION'
VendorID 0x13DE, 'ABB ROBOTICS PRODUCTS'
VendorID 0x13DF, 'E-TECH INC'
VendorID 0x13E0, 'GVC CORPORATION'
VendorID 0x13E3, 'NEST INC'
VendorID 0x13E4, 'CALCULEX INC'
VendorID 0x13E5, 'TELESOFT DESIGN LTD'
VendorID 0x13E9, 'INTRASERVER TECHNOLOGY INC'
VendorID 0x13EA, 'DALLAS SEMICONDUCTOR'
VendorID 0x13F0, 'SUNDANCE TECHNOLOGY INC'
VendorID 0x13F1, 'OCE-TECHNOLOGIES B.V.'
VendorID 0x13F2, 'FORD MICROELECTRONICS INC'
VendorID 0x13F4, 'TROIKA NETWORKS INC'
VendorID 0x13F6, 'C-MEDIA ELECTRONICS INC'
VendorID 0x13F9, 'NTT ADVANCED TECHNOLOGY CORP.'
VendorID 0x13FB, 'AYDIN CORP'
VendorID 0x13FD, 'MICRO SCIENCE INC'
VendorID 0x1400, 'ARTX INC'
VendorID 0x1402, 'Meilhaus Electronic GmbH Germany'
VendorID 0x1404, 'FUNDAMENTAL SOFTWARE INC'
VendorID 0x1406, 'OCE PRINTING SYSTEMS GmbH'
VendorID 0x1407, 'LAVA COMPUTER MFG INC'
VendorID 0x1408, 'ALOKA CO. LTD'
VendorID 0x140A, 'DSP RESEARCH INC'
VendorID 0x140B, 'RAMIX INC'
VendorID 0x140D, 'MATSUSHITA ELECTRIC WORKS LTD'
VendorID 0x1412, 'ICEnsemble'
VendorID 0x1413, 'ADDONICS'
VendorID 0x1415, 'OXFORD SEMICONDUCTOR LTD'
VendorID 0x1418, 'KYUSHU ELECTRONICS SYSTEMS INC'
VendorID 0x1419, 'EXCEL SWITCHING CORP'
VendorID 0x141B, 'ZOOM TELEPHONICS INC'
VendorID 0x141E, 'FANUC LTD'
VendorID 0x1420, 'PSION DACOM PLC'
VendorID 0x1428, 'EDEC CO LTD'
VendorID 0x1429, 'UNEX TECHNOLOGY CORP'
VendorID 0x142A, 'KINGMAX TECHNOLOGY INC'
VendorID 0x142B, 'RADIOLAN'
VendorID 0x142C, 'MINTON OPTIC INDUSTRY CO LTD'
VendorID 0x142D, 'PIXSTREAM INC'
VendorID 0x1430, 'ITT AEROSPACE/COMMUNICATIONS DIVISION'
VendorID 0x1433, 'ELTEC ELEKTRONIK GMBH'
VendorID 0x1436, 'CIS TECHNOLOGY INC'
VendorID 0x1437, 'NISSIN INC CO'
VendorID 0x1438, 'ATMEL-DREAM'
VendorID 0x143F, 'LIGHTWELL CO LTD-ZAX DIVISION'
VendorID 0x1441, 'AGIE SA'
VendorID 0x1445, 'LOGICAL CO LTD'
VendorID 0x1446, 'GRAPHIN CO. LTD'
VendorID 0x1447, 'AIM GMBH'
VendorID 0x144A, 'ADLINK Technology Inc'
VendorID 0x144B, 'LORONIX INFORMATION SYSTEMS INC'
VendorID 0x144D, 'SAMSUNG ELECTRONICS CO LTD'
VendorID 0x1450, 'OCTAVE COMMUNICATIONS IND.'
VendorID 0x1451, 'SP3D CHIP DESIGN GMBH'
VendorID 0x1453, 'MYCOM INC'
VendorID 0x1455, 'LOGIC PLUS PLUS INC'
VendorID 0x1458, 'GIGA-BYTE TECHNOLOGY'
VendorID 0x145C, 'CRYPTEK'
VendorID 0x145F, 'BALDOR ELECTRIC COMPANY'
VendorID 0x1460, 'DYNARC INC'
VendorID 0x1461, 'AVERMEDIA Tech.'
VendorID 0x1462, 'MICRO-STAR INTERNATIONAL CO LTD'
VendorID 0x1463, 'FAST CORPORATION'
VendorID 0x1464, 'INTERACTIVE CIRCUITS & SYSTEMS LTD'
VendorID 0x1465, 'GN NETTEST TELECOM DIV.'
VendorID 0x1468, 'AMBIT MICROSYSTEMS CORP.'
VendorID 0x1469, 'CLEVELAND MOTION CONTROLS'
VendorID 0x146C, 'RUBY TECH CORP.'
VendorID 0x146D, 'TACHYON'
VendorID 0x146E, 'WILLIAMS ELECTRONICS GAMES.'
VendorID 0x1471, 'INTEGRATED TELECOM EXPRESS INC'
VendorID 0x1473, 'ZAPEX TECHNOLOGIES INC'
VendorID 0x1474, 'DOUG CARSON & ASSOCIATES'
VendorID 0x1477, 'NET INSIGHT'
VendorID 0x1478, 'DIATREND CORPORATION'
VendorID 0x147B, 'ABIT Computer'
VendorID 0x147F, 'NIHON UNISYS'
VendorID 0x1482, 'ISYTEC-Integrierte Systemtechnik Gmbh'
VendorID 0x1483, 'LABWAY COPORATION'
VendorID 0x1485, 'ERMA-ELECTRONIC GMBH'
VendorID 0x1489, 'KYE SYSTEMS CORPORATION'
VendorID 0x148A, 'OPTO 22'
VendorID 0x148B, 'INNOMEDIALOGIC INC.'
VendorID 0x148E, 'OSI PLUS CORPORATION'
VendorID 0x148F, 'PLANT EQUIPMENT.'
VendorID 0x1490, 'TC LABS PTY LTD.'
VendorID 0x1493, 'MAKER COMMUNICATIONS'
VendorID 0x1495, 'TOKAI COMMUNICATIONS INDUSTRY CO. LTD'
VendorID 0x1496, 'JOYTECH COMPUTER CO. LTD.'
VendorID 0x1497, 'SMA REGELSYSTEME GMBH'
VendorID 0x1499, 'EMTEC CO. LTD'
VendorID 0x149A, 'ANDOR TECHNOLOGY LTD'
VendorID 0x149B, 'SEIKO INSTRUMENTS INC'
VendorID 0x149C, 'OVISLINK CORP.'
VendorID 0x149D, 'NEWTEK INC'
VendorID 0x149E, 'MAPLETREE NETWORKS INC.'
VendorID 0x149F, 'LECTRON CO LTD'
VendorID 0x14A0, 'SOFTING GMBH'
VendorID 0x14A1, 'SYSTEMBASE CO LTD'
VendorID 0x14A2, 'MILLENNIUM ENGINEERING INC'
VendorID 0x14A3, 'MAVERICK NETWORKS'
VendorID 0x14A4, 'GVC/BCM ADVANCED RESEARCH'
VendorID 0x14A5, 'XIONICS DOCUMENT TECHNOLOGIES INC.'
VendorID 0x14A6, 'INOVA COMPUTERS GMBH & CO KG'
VendorID 0x14A8, 'FEATRON TECHNOLOGIES CORPORATION'
VendorID 0x14A9, 'HIVERTEC INC.'
VendorID 0x14AB, 'MENTOR GRAPHICS CORP.'
VendorID 0x14AC, 'NOVAWEB TECHNOLOGIES INC'
VendorID 0x14AD, 'TIME SPACE RADIO AB'
VendorID 0x14AE, 'CTI PET Systems'
VendorID 0x14AF, 'GUILLEMOT CORPORATION'
VendorID 0x14B0, 'BST COMMUNICATION TECHNOLOGY LTD'
VendorID 0x14B1, 'NEXTCOM K.K.'
VendorID 0x14B2, 'ENNOVATE NETWORKS INC'
VendorID 0x14B3, 'XPEED INC.'
VendorID 0x14B4, 'PHILIPS BUSINESS ELECTRONICS B.V.'
VendorID 0x14B5, 'CREAMWARE GMBH'
VendorID 0x14B6, 'QUANTUM DATA CORP.'
VendorID 0x14B7, 'PROXIM INC'
VendorID 0x14B8, 'TECHSOFT TECHNOLOGY CO LTD'
VendorID 0x14B9, 'AIRONET WIRELESS COMMUNICATIONS'
VendorID 0x14BA, 'INTERNIX INC.'
VendorID 0x14BB, 'SEMTECH CORPORATION'
VendorID 0x14BC, 'GLOBESPAN SEMICONDUCTOR INC.'
VendorID 0x14BD, 'CARDIO CONTROL N.V.'
VendorID 0x14BE, 'L3 COMMUNICATIONS'
VendorID 0x14BF, 'SPIDER COMMUNICATIONS INC.'
VendorID 0x14C0, 'COMPAL ELECTRONICS INC'
VendorID 0x14C1, 'MYRICOM INC.'
VendorID 0x14C2, 'DTK COMPUTER'
VendorID 0x14C3, 'MEDIATEK CORP.'
VendorID 0x14C4, 'IWASAKI INFORMATION SYSTEMS CO LTD'
VendorID 0x14C5, 'ABB AUTOMATION PRODUCTS'
VendorID 0x14C6, 'DATA RACE INC'
VendorID 0x14C7, 'MODULAR TECHNOLOY HOLDINGS LTD'
VendorID 0x14C8, 'TURBOCOMM TECH. INC.'
VendorID 0x14C9, 'ODIN TELESYSTEMS INC'
VendorID 0x14CA, 'PE LOGIC CORP.'
VendorID 0x14CB, 'Billionton Systems Inc./Cadmus Micro Inc.'
VendorID 0x14CC, 'NAKAYO TELECOMMUNICATIONS INC'
VendorID 0x14CD, 'UNIVERSAL SCIENTIFIC IND'
VendorID 0x14CE, 'WHISTLE COMMUNICATIONS'
VendorID 0x14CF, 'TEK MICROSYSTEMS INC.'
VendorID 0x14D0, 'ERICSSON AXE R & D'
VendorID 0x14D1, 'COMPUTER HI-TECH CO LTD'
VendorID 0x14D2, 'TITAN ELECTRONICS INC'
VendorID 0x14D3, 'CIRTECH (UK) LTD'
VendorID 0x14D4, 'PANACOM TECHNOLOGY CORP'
VendorID 0x14D5, 'NITSUKO CORPORATION'
VendorID 0x14D6, 'ACCUSYS'
VendorID 0x14D7, 'HIRAKAWA HEWTECH CORP'
VendorID 0x14D8, 'HOPF ELEKTRONIK GMBH'
VendorID 0x14D9, 'ALPHA PROCESSOR INC'
VendorID 0x14DA, 'NATIONAL AEROSPACE LABORATORIES'
VendorID 0x14DB, 'AVLAB TECHNOLOGY INC'
VendorID 0x14DC, 'AMPLICON LIVELINE LTD'
VendorID 0x14DD, 'IMODL INC.'
VendorID 0x14DE, 'APPLIED INTEGRATION CORPORATION'
VendorID 0x14DF, 'BASIS COMMUNICATIONS CORP'
VendorID 0x14E1, 'INVERTEX'
VendorID 0x14E2, 'INFOLIBRIA'
VendorID 0x14E3, 'AMTELCO'
VendorID 0x14E4, 'BROADCOM CORPORATION'
VendorID 0x14E5, 'PIXELFUSION LTD'
VendorID 0x14E6, 'SHINING TECHNOLOGY INC'
VendorID 0x14E7, '3CX'
VendorID 0x14E8, 'RAYCER INC'
VendorID 0x14E9, 'GARNETS SYSTEM CO LTD'
VendorID 0x14EA, 'PLANEX COMMUNICATIONS INC'
VendorID 0x14EB, 'SEIKO EPSON CORPORATION'
VendorID 0x14EC, 'ACQIRIS'
VendorID 0x14ED, 'DATAKINETICS LTD'
VendorID 0x14EE, 'MASPRO KENKOH CORP'
VendorID 0x14EF, 'CARRY COMPUTER ENG. CO LTD'
VendorID 0x14F0, 'CANON RESEACH CENTRE FRANCE'
VendorID 0x14F1, 'Conexant Systems, Inc'
VendorID 0x14F2, 'Mobility Electronics, Inc.'
VendorID 0x14F3, 'BROADLOGIC'
VendorID 0x14F4, 'TOKYO ELECTRONIC INDUSTRY CO LTD'
VendorID 0x14F5, 'SOPAC LTD'
VendorID 0x14F6, 'COYOTE TECHNOLOGIES LLC'
VendorID 0x14F7, 'WOLF TECHNOLOGY INC'
VendorID 0x14F8, 'AUDIOCODES INC'
VendorID 0x14F9, 'AG COMMUNICATIONS'
VendorID 0x14FA, 'WAVETEK WANDEL & GOLTERMANN'
VendorID 0x14FB, 'TRANSAS MARINE (UK) LTD'
VendorID 0x14FC, 'QUADRICS SUPERCOMPUTERS WORLD'
VendorID 0x14FD, 'JAPAN COMPUTER INDUSTRY INC.'
VendorID 0x14FE, 'ARCHTEK TELECOM CORP.'
VendorID 0x14FF, 'TWINHEAD INTERNATIONAL CORP'
VendorID 0x1500, 'LANTECH COMPUTER COMPANY'
VendorID 0x1501, 'BANKSOFT CANADA LTD'
VendorID 0x1502, 'MITSUBISHI ELECTRIC LOGISTICS SUPPORT CO'
VendorID 0x1503, 'KAWASAKI LSI USA INC'
VendorID 0x1504, 'KAISER ELECTRONICS'
VendorID 0x1505, 'ITA INGENIEURBURO FUR TESTAUFGABEN GMBH'
VendorID 0x1506, 'CHAMELEON SYSTEMS INC'
VendorID 0x1507, 'HTEC LTD'
VendorID 0x1508, 'HONDA CONNECTORS/MHOTRONICS INC'
VendorID 0x1509, 'FIRST INTERNATIONAL COMPUTER INC'
VendorID 0x150A, 'FORVUS RESEARCH INC'
VendorID 0x150B, 'YAMASHITA SYSTEMS CORP'
VendorID 0x150C, 'KYOPAL CO LTD'
VendorID 0x150D, 'WARPSPPED INC'
VendorID 0x150E, 'C-PORT CORPORATION'
VendorID 0x150F, 'INTEC GMBH'
VendorID 0x1510, 'BEHAVIOR TECH COMPUTER CORP'
VendorID 0x1511, 'CENTILLIUM TECHNOLOGY CORP'
VendorID 0x1512, 'ROSUN TECHNOLOGIES INC'
VendorID 0x1513, 'RAYCHEM'
VendorID 0x1514, 'TFL LAN INC'
VendorID 0x1515, 'ICS ADVENT'
VendorID 0x1516, 'MYSON TECHNOLOGY INC'
VendorID 0x1517, 'ECHOTEK CORPORATION'
VendorID 0x1518, 'PEP MODULAR COMPUTERS GMBH'
VendorID 0x1519, 'TELEFON AKTIEBOLAGET LM Ericsson'
VendorID 0x151A, 'GLOBETEK INC'
VendorID 0x151B, 'COMBOX LTD'
VendorID 0x151C, 'DIGITAL AUDIO LABS INC'
VendorID 0x151D, 'FUJITSU COMPUTER PRODUCTS OF AMERICA'
VendorID 0x151E, 'MATRIX CORP.'
VendorID 0x151F, 'TOPIC SEMICONDUCTOR CORP'
VendorID 0x1520, 'CHAPLET SYSTEM INC'
VendorID 0x1521, 'BELL CORPORATION'
VendorID 0x1522, 'MAINPINE LIMITED'
VendorID 0x1523, 'MUSIC SEMICONDUCTORS'
VendorID 0x1524, 'ENE TECHNOLOGY INC'
VendorID 0x1525, 'IMPACT TECHNOLOGIES'
VendorID 0x1526, 'ISS'
VendorID 0x1527, 'SOLECTRON'
VendorID 0x1528, 'ACKSYS'
VendorID 0x1529, 'AMERICAN MICROSYSTEMS INC'
VendorID 0x152A, 'QUICKTURN DESIGN SYSTEMS'
VendorID 0x152B, 'FLYTECH TECHNOLOGY CO LTD'
VendorID 0x152C, 'MACRAIGOR SYSTEMS LLC'
VendorID 0x152D, 'QUANTA COMPUTER INC'
VendorID 0x152E, 'MELEC INC'
VendorID 0x152F, 'PHILIPS-CRYPTO'
VendorID 0x1530, 'ACQIS TECHNOLOGY'
VendorID 0x1531, 'CHRYON CORP.'
VendorID 0x1532, 'ECHELON CORPORATION'
VendorID 0x1533, 'BALTIMORE'
VendorID 0x1534, 'ROAD CORPORATION'
VendorID 0x1535, 'EVERGREEN TECHNOLOGIES INC'
VendorID 0x1537, 'DATALEX COMMUNCATIONS'
VendorID 0x1538, 'ARALION INC.'
VendorID 0x1539, 'ATELIER INFORMATIQUES et ELECTRONIQUE ETUDES S.A.'
VendorID 0x153A, 'ONO SOKKI'
VendorID 0x153B, 'TERRATEC ELECTRONIC GMBH'
VendorID 0x153C, 'ANTAL ELECTRONIC'
VendorID 0x153D, 'FILANET CORPORATION'
VendorID 0x153E, 'TECHWELL INC'
VendorID 0x153F, 'MIPS DENMARK'
VendorID 0x1540, 'PROVIDEO MULTIMEDIA CO LTD'
VendorID 0x1541, 'TELOSITY INC.'
VendorID 0x1542, 'VIVID TECHNOLOGY INC'
VendorID 0x1543, 'SILICON LABORATORIES'
VendorID 0x1544, 'DCM DATA SYSTEMS'
VendorID 0x1545, 'VISIONTEK'
VendorID 0x1546, 'IOI TECHNOLOGY CORP.'
VendorID 0x1547, 'MITUTOYO CORPORATION'
VendorID 0x1548, 'JET PROPULSION LABORATORY'
VendorID 0x1549, 'INTERCONNECT SYSTEMS SOLUTIONS'
VendorID 0x154A, 'MAX TECHNOLOGIES INC.'
VendorID 0x154B, 'COMPUTEX CO LTD'
VendorID 0x154C, 'VISUAL TECHNOLOGY INC.'
VendorID 0x154D, 'PAN INTERNATIONAL INDUSTRIAL CORP'
VendorID 0x154E, 'SERVOTEST LTD'
VendorID 0x154F, 'STRATABEAM TECHNOLOGY'
VendorID 0x1550, 'OPEN NETWORK CO LTD'
VendorID 0x1551, 'SMART ELECTRONIC DEVELOPMENT GMBH'
VendorID 0x1552, 'RACAL AIRTECH LTD'
VendorID 0x1553, 'CHICONY ELECTRONICS CO LTD'
VendorID 0x1554, 'PROLINK MICROSYSTEMS CORP.'
VendorID 0x1555, 'GESYTEC GMBH'
VendorID 0x1556, 'PLD APPLICATIONS'
VendorID 0x1557, 'MEDIASTAR CO. LTD'
VendorID 0x1558, 'CLEVO/KAPOK COMPUTER'
VendorID 0x1559, 'SI LOGIC LTD'
VendorID 0x155A, 'INNOMEDIA INC'
VendorID 0x155B, 'PROTAC INTERNATIONAL CORP'
VendorID 0x155C, 'CEMAX-ICON INC'
VendorID 0x155D, 'MAC SYSTEM CO LTD'
VendorID 0x155E, 'LP ELEKTRONIK GMBH/KUKA Controls GmbH'
VendorID 0x155F, 'PERLE SYSTEMS LIMITED'
VendorID 0x1560, 'TERAYON COMMUNICATIONS SYSTEMS'
VendorID 0x1561, 'VIEWGRAPHICS INC'
VendorID 0x1562, 'Symbol Technologies, Inc.'
VendorID 0x1563, 'A-TREND'
VendorID 0x1564, 'YAMAKATSU ELECTRONICS INDUSTRY CO LTD'
VendorID 0x1565, 'BIOSTAR MICROTECH INT CORP'
VendorID 0x1566, 'ARDENT TECHNOLOGIES INC'
VendorID 0x1567, 'JUNGSOFT'
VendorID 0x1568, 'DDK ELECTRONICS INC'
VendorID 0x1569, 'PALIT MICROSYSTEMS INC'
VendorID 0x156A, 'AVTEC SYSTEMS'
VendorID 0x156B, '2WIRE'
VendorID 0x156C, 'VIDAC ELECTRONICS GMBH'
VendorID 0x156D, 'ALPHA-TOP CORP'
VendorID 0x156E, 'ALFA INC'
VendorID 0x156F, 'M-SYSTEMS FLASH DISK PIONEERS LTD'
VendorID 0x1570, 'LECROY CORPORATION'
VendorID 0x1571, 'CONTEMPORARY CONTROLS'
VendorID 0x1572, 'OTIS ELEVATOR COMPANY'
VendorID 0x1573, 'LATTICE-VANTIS'
VendorID 0x1574, 'FAIRCHILD SEMICONDUCTOR'
VendorID 0x1575, 'VOLTAIRE ADVANCED DATA SECURITY LTD'
VendorID 0x1576, 'VIEWCAST COM'
VendorID 0x1578, 'HITT'
VendorID 0x1579, 'DUAL TECHNOLOGY CORPORATION'
VendorID 0x157A, 'JAPAN ELECRONICS IND. INC'
VendorID 0x157B, 'STAR MULTIMEDIA CORP.'
VendorID 0x157C, 'EUROSOFT (UK) LTD'
VendorID 0x157D, 'GEMFLEX NETWORKS'
VendorID 0x157E, 'TRANSITION NETWORKS'
VendorID 0x157F, 'PX INSTRUMENTS TECHNOLOGY LTD'
VendorID 0x1580, 'PRIMEX AEROSPACE CO.'
VendorID 0x1581, 'SEH COMPUTERTECHNIK GMBH'
VendorID 0x1582, 'CYTEC CORPORATION'
VendorID 0x1583, 'INET TECHNOLOGIES INC'
VendorID 0x1584, 'UNIWILL COMPUTER CORP'
VendorID 0x1585, 'LOGITRON'
VendorID 0x1586, 'LANCAST INC'
VendorID 0x1587, 'KONICA CORPORATION'
VendorID 0x1588, 'SOLIDUM SYSTEMS CORP'
VendorID 0x1589, 'ATLANTEK MICROSYSTEMS PTY LTD'
VendorID 0x158A, 'DIGALOG SYSTEMS INC'
VendorID 0x158B, 'ALLIED DATA TECHNOLOGIES'
VendorID 0x158C, 'HITACHI SEMICONDUCTOR & DEVICES SALES CO LTD'
VendorID 0x158D, 'POINT MULTIMEDIA SYSTEMS'
VendorID 0x158E, 'LARA TECHNOLOGY INC'
VendorID 0x158F, 'DITECT COOP'
VendorID 0x1590, '3PARDATA'
VendorID 0x1591, 'ARN'
VendorID 0x1592, 'SYBA TECH LIMITED'
VendorID 0x1593, 'BOPS INC'
VendorID 0x1594, 'NETGAME LTD'
VendorID 0x1595, 'DIVA SYSTEMS CORP.'
VendorID 0x1596, 'FOLSOM RESEARCH INC'
VendorID 0x1597, 'MEMEC DESIGN SERVICES'
VendorID 0x1598, 'GRANITE MICROSYSTEMS'
VendorID 0x1599, 'DELTA ELECTRONICS INC'
VendorID 0x159A, 'GENERAL INSTRUMENT'
VendorID 0x159B, 'FARADAY TECHNOLOGY CORP'
VendorID 0x159C, 'STRATUS COMPUTER SYSTEMS'
VendorID 0x159D, 'NINGBO HARRISON ELECTRONICS CO LTD'
VendorID 0x159E, 'A-MAX TECHNOLOGY'
VendorID 0x159F, 'GALEA NETWORK SECURITY'
VendorID 0x15A0, 'COMPUMASTER SRL'
VendorID 0x15A1, 'GEOCAST NETWORK SYSTEMS INC'
VendorID 0x15A2, 'CATALYST ENTERPRISES INC'
VendorID 0x15A3, 'ITALTEL'
VendorID 0x15A4, 'X-NET OY'
VendorID 0x15A5, 'TOYOTA MACS INC'
VendorID 0x15A6, 'SUNLIGHT ULTRASOUND TECHNOLOGIES LTD'
VendorID 0x15A7, 'SSE TELECOM INC'
VendorID 0x15A8, 'SHANGHAI COMMUNICATIONS TECHNOLOGIES CENTER'
VendorID 0x15AA, 'MORETON BAY'
VendorID 0x15AB, 'BLUESTEEL NETWORKS INC'
VendorID 0x15AC, 'NORTH ATLANTIC INSTRUMENTS'
VendorID 0x15AD, 'VMware Inc.'
VendorID 0x15AE, 'AMERSHAM PHARMACIA BIOTECH'
VendorID 0x15B0, 'ZOLTRIX INTERNATIONAL LIMITED'
VendorID 0x15B1, 'SOURCE TECHNOLOGY INC'
VendorID 0x15B2, 'MOSAID TECHNOLOGIES INC.'
VendorID 0x15B3, 'MELLANOX TECHNOLOGY'
VendorID 0x15B4, 'CCI/TRIAD'
VendorID 0x15B5, 'CIMETRICS INC'
VendorID 0x15B6, 'TEXAS MEMORY SYSTEMS INC'
VendorID 0x15B7, 'SANDISK CORP.'
VendorID 0x15B8, 'ADDI-DATA GMBH'
VendorID 0x15B9, 'MAESTRO DIGITAL COMMUNICATIONS'
VendorID 0x15BA, 'IMPACCT TECHNOLOGY CORP'
VendorID 0x15BB, 'PORTWELL INC'
VendorID 0x15BC, 'AGILENT TECHNOLOGIES'
VendorID 0x15BD, 'DFI INC.'
VendorID 0x15BE, 'SOLA ELECTRONICS'
VendorID 0x15BF, 'HIGH TECH COMPUTER CORP (HTC)'
VendorID 0x15C0, 'BVM LIMITED'
VendorID 0x15C1, 'QUANTEL'
VendorID 0x15C2, 'NEWER TECHNOLOGY INC'
VendorID 0x15C3, 'TAIWAN MYCOMP CO LTD'
VendorID 0x15C4, 'EVSX'
VendorID 0x15C5, 'PROCOMP INFORMATICS LTD'
VendorID 0x15C6, 'TECHNICAL UNIVERSITY OF BUDAPEST'
VendorID 0x15C7, 'TATEYAMA SYSTEM LABORATORY CO LTD'
VendorID 0x15C8, 'PENTA MEDIA CO. LTD'
VendorID 0x15C9, 'SEROME TECHNOLOGY INC'
VendorID 0x15CA, 'BITBOYS OY'
VendorID 0x15CB, 'AG ELECTRONICS LTD'
VendorID 0x15CC, 'HOTRAIL INC.'
VendorID 0x15CD, 'DREAMTECH CO LTD'
VendorID 0x15CE, 'GENRAD INC.'
VendorID 0x15CF, 'HILSCHER GMBH'
VendorID 0x15D1, 'INFINEON TECHNOLOGIES AG'
VendorID 0x15D2, 'FIC (FIRST INTERNATIONAL COMPUTER INC)'
VendorID 0x15D3, 'NDS TECHNOLOGIES ISRAEL LTD'
VendorID 0x15D4, 'IWILL CORPORATION'
VendorID 0x15D5, 'TATUNG CO.'
VendorID 0x15D6, 'ENTRIDIA CORPORATION'
VendorID 0x15D7, 'Rockwell-Collins Inc'
VendorID 0x15D8, 'CYBERNETICS TECHNOLOGY CO LTD'
VendorID 0x15D9, 'SUPER MICRO COMPUTER INC'
VendorID 0x15DA, 'CYBERFIRM INC.'
VendorID 0x15DB, 'APPLIED COMPUTING SYSTEMS INC.'
VendorID 0x15DC, 'LITRONIC INC'
VendorID 0x15DD, 'SIGMATEL INC.'
VendorID 0x15DE, 'MALLEABLE TECHNOLOGIES INC'
VendorID 0x15DF, 'INFINILINK CORP.'
VendorID 0x15E0, 'CACHEFLOW INC'
VendorID 0x15E1, 'VOICE TECHNOLOGIES GROUP INC'
VendorID 0x15E2, 'QUICKNET TECHNOLOGIES INC'
VendorID 0x15E3, 'NETWORTH TECHNOLOGIES INC'
VendorID 0x15E4, 'VSN SYSTEMEN BV'
VendorID 0x15E5, 'VALLEY TECHNOLOGIES INC'
VendorID 0x15E6, 'AGERE INC.'
VendorID 0x15E7, 'GET ENGINEERING CORP.'
VendorID 0x15E8, 'NATIONAL DATACOMM CORP.'
VendorID 0x15E9, 'PACIFIC DIGITAL CORP.'
VendorID 0x15EA, 'TOKYO DENSHI SEKEI K.K.'
VendorID 0x15EB, 'DRSEARCH GMBH'
VendorID 0x15EC, 'BECKHOFF GMBH'
VendorID 0x15ED, 'MACROLINK INC'
VendorID 0x15EE, 'IN WIN DEVELOPMENT INC.'
VendorID 0x15EF, 'INTELLIGENT PARADIGM INC'
VendorID 0x15F0, 'B-TREE SYSTEMS INC'
VendorID 0x15F1, 'TIMES N SYSTEMS INC'
VendorID 0x15F2, 'DIAGNOSTIC INSTRUMENTS INC'
VendorID 0x15F3, 'DIGITMEDIA CORP.'
VendorID 0x15F4, 'VALUESOFT'
VendorID 0x15F5, 'POWER MICRO RESEARCH'
VendorID 0x15F6, 'EXTREME PACKET DEVICE INC'
VendorID 0x15F7, 'BANCTEC'
VendorID 0x15F8, 'KOGA ELECTRONICS CO'
VendorID 0x15F9, 'ZENITH ELECTRONICS CORPORATION'
VendorID 0x15FA, 'J P AXZAM CORPORATION'
VendorID 0x15FB, 'ZILOG INC.'
VendorID 0x15FC, 'TECHSAN ELECTRONICS CO LTD'
VendorID 0x15FD, 'N-CUBED.NET'
VendorID 0x15FE, 'KINPO ELECTRONICS INC'
VendorID 0x15FF, 'FASTPOINT TECHNOLOGIES INC.'
VendorID 0x1600, 'NORTHROP GRUMMAN-CANADA LTD'
VendorID 0x1601, 'TENTA TECHNOLOGY'
VendorID 0x1602, 'PROSYS-TEC INC.'
VendorID 0x1603, 'NOKIA WIRELESS BUSINESS COMMUNICATIONS'
VendorID 0x1604, 'CENTRAL SYSTEM RESEARCH CO LTD'
VendorID 0x1605, 'PAIRGAIN TECHNOLOGIES'
VendorID 0x1606, 'EUROPOP AG'
VendorID 0x1607, 'LAVA SEMICONDUCTOR MANUFACTURING INC.'
VendorID 0x1608, 'AUTOMATED WAGERING INTERNATIONAL'
VendorID 0x1609, 'SCIEMETRIC INSTRUMENTS INC'
VendorID 0x166D, 'Broadcom -SiByte'
VendorID 0x168C, 'Atheros Communications Inc.'
VendorID 0x1695, 'EPOX Computer Co'
VendorID 0x17F2, 'ALBATRON Corp.'
VendorID 0x1813, 'AMBIENT TECHNOLOGIES INC'
VendorID 0x1849, 'ASROCK Inc'
VendorID 0x1B13, 'Jaton Corp'
VendorID 0x2001, 'TEMPORAL RESEARCH LTD'
VendorID 0x270F, 'CHAINTECH COMPUTER CO. LTD'
VendorID 0x3388, 'HINT CORP'
VendorID 0x3411, 'QUANTUM DESIGNS (H.K.) INC.'
VendorID 0x4005, 'AVANCE LOGIC INC'
VendorID 0x4033, 'DELTA NETWORKS INC'
VendorID 0x416C, 'ALADDIN KNOWLEDGE SYSTEMS'
VendorID 0x4444, 'CONEXANT (WAS ICOMPRESION INC.)'
VendorID 0x4943, 'GROWTH NETWORKS'
VendorID 0x4CA1, 'SEANIX TECHNOLOGY INC'
VendorID 0x4D51, 'MEDIAQ INC.'
VendorID 0x4D54, 'MICROTECHNICA CO LTD'
VendorID 0x5136, 'S S TECHNOLOGIES'
VendorID 0x5333, 'S3 Graphics Co., Ltd.'
VendorID 0x544C, 'TERALOGIC INC'
VendorID 0x5555, 'GENROCO INC'
VendorID 0x6409, 'LOGITEC CORP.'
VendorID 0x6666, 'DECISION COMPUTER INTERNATIONAL CO.'
VendorID 0x8086, 'Intel Corp.'
VendorID 0x8888, 'SILICON MAGIC CORP.'
VendorID 0x8E0E, 'COMPUTONE CORPORATION'
VendorID 0x9004, 'Adaptec Inc'
VendorID 0x919A, 'GIGAPIXEL CORP'
VendorID 0x9412, 'HOLTEK'
VendorID 0x9699, 'OMNI MEDIA TECHNOLOGY INC.'
VendorID 0x9710, 'NetMos'
VendorID 0xA0A0, 'AOPEN INC.'
VendorID 0xA259, 'HEWLETT PACKARD'
VendorID 0xAC1E, 'DIGITAL RECEIVER TECHNOLOGY INC'
VendorID 0xC0DE, 'MOTOROLA'
VendorID 0xC0FE, 'MOTION ENGINEERING.'
VendorID 0xCA50, 'VARIAN AUSTRIALIA PTY LTD'
VendorID 0xCAFE, 'CHRYSALIS-ITS'
VendorID 0xCCCC, 'CATAPULT COMMUNICATIONS'
VendorID 0xD4D4, 'DY4 Systems Inc/Curtiss-Wright Controls Embed. Com'
VendorID 0xE159, 'TigerJet'
VendorID 0xE4BF, 'EKF ELEKTRONIK GMBH'
VendorID 0xEA01, 'EAGLE TECHNOLOGY'
VendorID 0xFA57, 'FAST SEARCH & TRANSFER ASA'
VendorID 0xFEDA, 'EPIGRAM INC'
VendorID 0, 'Unknown' ; <- terminator
 
;--------------------------------------
Classes:
; Class, Subclass, [Interface], Name
ClassID 2, 0, , 'Ethernet'
ClassID 2, 1, , 'Token Ring'
ClassID 2, 2, , 'FDDI'
ClassID 2, 3, , 'ATM'
ClassID 2, 4, , 'ISDN'
ClassID 2, 5, , 'WorldFip'
ClassID 2, 6, , 'PICMG 2.14'
ClassID 2, 0x80, , 'misc'
 
ClassID 0x0d, 0x20, , 'Wlan (802.11a)'
ClassID 0x0d, 0x21, , 'Wlan (802.11b)'
 
 
ClassID 0xff, 0xff, , 'Unknown' ; <- terminator
/programs/network/netcfg
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network/netstat/netstat.asm
0,0 → 1,614
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; netstat.asm - Network Status Tool for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format binary as ""
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image
dd (I_END+0x100) ; memory for app
dd (I_END+0x100) ; esp
dd I_PARAM , 0x0 ; I_Param , I_Icon
 
include '..\macros.inc'
include '..\network.inc'
 
START:
mcall 40, EVM_REDRAW + EVM_BUTTON + EVM_STACK2
 
redraw:
mcall 12, 1
mcall 0, 100 shl 16 + 600, 100 shl 16 + 240, 0x34bcbcbc, , name ; draw window
 
call draw_interfaces
 
mov edx, 101
mov esi, 0x00aaaaff
mov edi, 0x00aaffff
 
cmp dl, [mode]
cmove esi, edi
mcall 8, 25 shl 16 + 65, 25 shl 16 + 20
 
.morebuttons:
inc edx
add ebx, 75 shl 16
mov esi, 0x00aaaaff
 
cmp dl, [mode]
cmove esi, edi
mcall
 
cmp edx, 105
jle .morebuttons
 
mcall 4, 28 shl 16 + 31, 0x80000000, modes
 
cmp [mode], 101
jne .no_eth
 
mcall 4, 20 shl 16 + 75, 0x80000000, str_packets_tx
add ebx, 18
mov edx, str_packets_rx
mcall
add ebx, 18
mov edx, str_bytes_tx
mcall
add ebx, 18
mov edx, str_bytes_rx
mcall
add ebx, 18
mov edx, str_MAC
mcall
add ebx, 18
mov edx, str_link
mcall
 
mov ebx, API_ETH + 4
mov bh, [device]
mcall 76
push eax
push bx
 
mov edx, 135 shl 16 + 75 + 4*18
call draw_mac
jmp end_of_draw
 
.no_eth:
 
cmp [mode], 102
jne .no_ip
 
mcall 4, 20 shl 16 + 75, 0x80000000, str_packets_tx
add ebx, 18
mov edx, str_packets_rx
mcall
add ebx, 18
mov edx, str_ip
mcall
add ebx, 18
mov edx, str_dns
mcall
add ebx, 18
mov edx, str_subnet
mcall
add ebx, 18
mov edx, str_gateway
mcall
 
 
mov ebx, API_IPv4 + 8
mov bh, [device]
mcall 76
push eax
 
dec bl
dec bl
mcall 76
push eax
 
dec bl
dec bl
mcall 76
push eax
 
dec bl
dec bl
mcall 76
push eax
 
mov edx, 135 shl 16 + 75 + 2*18
call draw_ip
 
add edx, 18
call draw_ip
 
add edx, 18
call draw_ip
 
add edx, 18
call draw_ip
 
jmp end_of_draw
 
.no_ip:
 
cmp [mode], 103
jne .no_arp
 
mcall 4, 20 shl 16 + 75, 0x80000000, str_packets_tx
add ebx, 18
mov edx, str_packets_rx
mcall
add ebx, 18
mov edx, str_arp
mcall
add ebx, 18
mov edx, str_conflicts
mcall
 
jmp end_of_draw
 
.no_arp:
 
mcall 4, 20 shl 16 + 75, 0x80000000, str_packets_tx
 
add ebx, 18
mov edx, str_packets_rx
mcall
 
cmp [mode], 106
jne end_of_draw
 
add ebx, 18
mov edx, str_missed
mcall
 
add ebx, 18
mov edx, str_dumped
mcall
 
 
 
end_of_draw:
mcall 12, 2
 
draw_stats:
 
cmp [mode], 101
jne not_101
 
mov ebx, API_ETH
mov bh, [device]
@@:
push ebx
mcall 76
pop ebx
push eax
inc bl
cmp bl, 3
jbe @r
inc bl
mcall 76
push eax
 
mov ebx, 0x000a0000
pop ecx
mov edx, 135 shl 16 + 75 + 5*18
mov esi, 0x40000000
mov edi, 0x00bcbcbc
mcall 47
 
sub edx, 18*2
pop ecx
mcall
 
sub edx, 18
pop ecx
mcall
 
sub edx, 18
pop ecx
mcall
 
sub edx, 18
pop ecx
mcall
 
jmp mainloop
 
 
not_101:
 
cmp [mode], 102
jne not_102
 
mov ebx, API_IPv4
mov bh, [device]
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
 
mov ebx, 0x000a0000
pop ecx
mov edx, 135 shl 16 + 75 + 18
mov esi, 0x40000000
mov edi, 0x00bcbcbc
mcall 47
 
sub edx, 18
pop ecx
mcall
 
jmp mainloop
 
 
not_102:
 
cmp [mode], 103
jne not_103
 
mov ebx, API_ARP
mov bh, [device]
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
mov bl, 7
push ebx
mcall 76
pop ebx
push eax
 
mov ebx, 0x000a0000
pop ecx
mov edx, 135 shl 16 + 75 + 3*18
mov esi, 0x40000000
mov edi, 0x00bcbcbc
mcall 47
 
sub edx, 18
pop ecx
mcall
 
sub edx, 18
pop ecx
mcall
 
sub edx, 18
pop ecx
mcall
 
jmp mainloop
 
not_103:
 
cmp [mode], 104
jne not_104
 
mov ebx, API_ICMP
mov bh, [device]
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
mov ebx, 0x000a0000
pop ecx
mov edx, 135 shl 16 + 75 + 18
mov esi, 0x40000000
mov edi, 0x00bcbcbc
mcall 47
 
sub edx, 18
pop ecx
mcall
 
jmp mainloop
 
not_104:
 
cmp [mode], 105
jne not_105
 
mov ebx, API_UDP
mov bh, [device]
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
mov ebx, 0x000a0000
pop ecx
mov edx, 135 shl 16 + 75 + 18
mov esi, 0x40000000
mov edi, 0x00bcbcbc
mcall 47
 
sub edx, 18
pop ecx
mcall
 
jmp mainloop
 
not_105:
 
cmp [mode], 106
jne not_106
 
mov ebx, API_TCP
mov bh, [device]
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
inc bl
push ebx
mcall 76
pop ebx
push eax
 
mov ebx, 0x000a0000
pop ecx
mov edx, 135 shl 16 + 75 + 18*3
mov esi, 0x40000000
mov edi, 0x00bcbcbc
mcall 47
 
sub edx, 18
pop ecx
mcall
 
sub edx, 18
pop ecx
mcall
 
sub edx, 18
pop ecx
mcall
 
jmp mainloop
 
not_106:
 
mainloop:
 
mcall 23, 50 ; wait for event with timeout (0,5 s)
 
cmp eax, 1
je redraw
cmp eax, 3
je button
cmp eax, 11
je redraw
 
jmp draw_stats
 
button: ; button
mcall 17 ; get id
cmp ah, 1
je exit
cmp ah, 0
je .interface
mov [mode], ah
jmp redraw
 
.interface:
shr eax, 16
mov [device], al
jmp redraw
 
exit:
mcall -1
 
 
 
draw_mac:
 
mov eax, 47
mov ebx, 0x00020100
mov esi, 0x40000000
mov edi, 0x00bcbcbc
 
mov cl, [esp+4]
mcall
 
mov cl, [esp+4+1]
add edx, 15 shl 16
mcall
 
mov cl, [esp+4+2]
add edx, 15 shl 16
mcall
 
mov cl, [esp+4+3]
add edx, 15 shl 16
mcall
 
mov cl, [esp+4+4]
add edx, 15 shl 16
mcall
 
mov cl, [esp+4+5]
add edx, 15 shl 16
mcall
 
sub edx, 5*15 shl 16
 
ret 6
 
 
draw_ip:
 
mov eax, 47
mov ebx, 0x00030000
mov esi, 0x40000000
mov edi, 0x00bcbcbc
 
xor ecx, ecx
 
mov cl, [esp+4]
mcall
 
mov cl, [esp+4+1]
add edx, 30 shl 16
mcall
 
mov cl, [esp+4+2]
add edx, 30 shl 16
mcall
 
mov cl, [esp+4+3]
add edx, 30 shl 16
mcall
 
sub edx, 3*30 shl 16
ret 4
 
 
draw_interfaces:
 
mov [.btnpos], 8 shl 16 + 20
mov [.txtpos], 490 shl 16 + 15
 
mcall 74, -1 ; get number of active network devices
mov ecx, eax
 
xor ebx, ebx ; get device type
.loop:
mcall 74
cmp eax, 1 ; ethernet?
je .hit
inc bh
jb .loop ; tried all 256?
ret
 
 
.hit:
push ecx ebx
movzx edx, bh
shl edx, 8
mov esi, 0x00aaaaff
cmp bh, [device]
cmove esi, 0x00aaffff
mcall 8, 485 shl 16 + 100, [.btnpos]
mov ebx, [esp]
inc bl
mov ecx, namebuf
mov edx, namebuf
mcall 74 ; get device name
cmp eax, -1
jne @f
mov edx, str_unknown
@@:
mcall 4, [.txtpos], 0x80000000 ; print the name
pop ebx ecx
 
inc bh
 
add [.btnpos], 25 shl 16
add [.txtpos], 25
 
dec ecx
jnz .loop
 
ret
 
.btnpos dd ?
.txtpos dd ?
 
 
 
 
; DATA AREA
 
name db 'Netstat', 0
mode db 101
device db 0
modes db 'Ethernet IPv4 ARP ICMP UDP TCP', 0
 
str_packets_tx db 'Packets sent:', 0
str_packets_rx db 'Packets received:', 0
str_bytes_tx db 'Bytes sent:', 0
str_bytes_rx db 'Bytes received:', 0
str_MAC db 'MAC address:', 0
str_ip db 'IP address:', 0
str_dns db 'DNS address:', 0
str_subnet db 'Subnet mask:', 0
str_gateway db 'Standard gateway:', 0
str_arp db 'ARP entrys:', 0
str_conflicts db 'ARP conflicts:', 0
str_unknown db 'unknown', 0
str_missed db 'Packets missed:',0
str_dumped db 'Packets dumped:',0
str_link db 'Link state:',0
 
namebuf rb 64
 
I_PARAM rb 1024
 
I_END:
 
 
/programs/network/netstat
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network/network.inc
0,0 → 1,94
; Socket types
SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3
 
; Socket options
SO_NONBLOCK = 1 shl 31
 
; IP protocols
IPPROTO_IP = 0
IPPROTO_ICMP = 1
IPPROTO_TCP = 6
IPPROTO_UDP = 17
 
; Address families
AF_UNSPEC = 0
AF_LOCAL = 1
AF_INET4 = 2 ; IPv4
AF_INET6 = 28 ; IPv6 (not supported yet)
 
PF_UNSPEC = AF_UNSPEC
PF_LOCAL = AF_LOCAL
PF_INET4 = AF_INET4
PF_INET6 = AF_INET6
 
; Flags for addrinfo
AI_PASSIVE = 1
AI_CANONNAME = 2
AI_NUMERICHOST = 4
AI_NUMERICSERV = 8
AI_ADDRCONFIG = 0x400
 
; internal definition
AI_SUPPORTED = 0x40F
 
; for system function 76
API_ETH = 0 shl 16
API_IPv4 = 1 shl 16
API_ICMP = 2 shl 16
API_UDP = 3 shl 16
API_TCP = 4 shl 16
API_ARP = 5 shl 16
API_PPPOE = 6 shl 16
 
struct sockaddr_in
sin_family dw ? ; sa_family_t
sin_port dw ? ; in_port_t
sin_addr dd ? ; struct in_addr
sin_zero rb 8 ; zero
ends
 
struct addrinfo
ai_flags dd ? ; bitmask of AI_*
ai_family dd ? ; PF_*
ai_socktype dd ? ; SOCK_*
ai_protocol dd ? ; 0 or IPPROTO_*
ai_addrlen dd ? ; length of ai_addr
ai_canonname dd ? ; char*
ai_addr dd ? ; struct sockaddr*
ai_next dd ? ; struct addrinfo*
ends
 
EAI_ADDRFAMILY = 1
EAI_AGAIN = 2
EAI_BADFLAGS = 3
EAI_FAIL = 4
EAI_FAMILY = 5
EAI_MEMORY = 6
EAI_NONAME = 8
EAI_SERVICE = 9
EAI_SOCKTYPE = 10
EAI_BADHINTS = 12
EAI_PROTOCOL = 13
EAI_OVERFLOW = 14
 
socket fix 75, 0
close fix 75, 1
bind fix 75, 2
listen fix 75, 3
connect fix 75, 4
accept fix 75, 5
send fix 75, 6
recv fix 75, 7
setsockopt fix 75, 8
getsockopt fix 75, 9
socketpair fix 75, 10
 
 
struct ARP_entry
IP dd ?
MAC dp ?
status dw ?
TTL dw ?
ends
/programs/network/nslookup/nslookup.asm
0,0 → 1,136
format binary as ""
 
use32
; standard header
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem ; required memory
dd mem ; stack pointer
dd 0 ; parameters
dd 0 ; path
 
; useful includes
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
 
include '../network.inc'
 
; entry point
start:
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
; initialize console
push 1
call [con_start]
push title
push -1
push -1
push -1
push -1
call [con_init]
; main loop
main:
; write prompt
push str1
call [con_write_asciiz]
; read string
mov esi, s
push 256
push esi
call [con_gets]
; check for exit
test eax, eax
jz done
cmp byte [esi], 10
jz done
; delete terminating '\n'
push esi
@@:
lodsb
test al, al
jnz @b
mov byte [esi-2], al
pop esi
; resolve name
push esp ; reserve stack place
push esp ; fourth parameter
push 0 ; third parameter
push 0 ; second parameter
push esi ; first parameter
call [getaddrinfo]
pop esi
; test for error
test eax, eax
jnz fail
; write results
push str2
call [con_write_asciiz]
mov edi, esi
addrloop:
; before all subsequent addresses print comma
cmp edi, esi
jz @f
push str3
call [con_write_asciiz]
@@:
; convert IP address to decimal notation
mov eax, [edi+addrinfo.ai_addr]
pushd [eax+sockaddr_in.sin_addr]
call [inet_ntoa]
; write result
push eax
call [con_write_asciiz]
; advance to next item
mov edi, [edi+addrinfo.ai_next]
test edi, edi
jnz addrloop
; free allocated memory
push esi
call [freeaddrinfo]
; write newline and continue main loop
push str4
@@:
call [con_write_asciiz]
jmp main
fail:
push str5
jmp @b
done:
push 1
call [con_exit]
exit:
mcall -1
 
; data
title db 'Names resolver',0
str1 db 'Host name to resolve: ',0
str2 db 'IP address(es): ',0
str3 db ', ',0
str4 db 10,0
str5 db 'Name resolution failed.',10,0
; 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'
i_end:
s rb 256
align 4
rb 4096 ; stack
mem:
/programs/network/nslookup
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network/pppoe/pppoe.asm
0,0 → 1,362
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; pppoe.asm - PPPoE dialer for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format binary as ""
 
use32
 
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem ; required memory
dd mem ; stack pointer
dd 0 ; parameters
dd 0 ; path
 
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
include '../network.inc'
include '../struct.inc'
 
; Ethernet protocol numbers
ETHER_PPP_DISCOVERY = 0x6388
ETHER_PPP_SESSION = 0x6488
 
; PPP protocol numbers
PPP_LCP = 0x21c0 ; Link Configure Protocol
PPP_CBCP = 0x29c0 ; CallBack Control Protocol
PPP_PAP = 0x23c0 ; Password Authenication Protocol packet
PPP_CHAP = 0x23c2 ; Challenge Handshake Authentication Protocol
PPP_IPCP = 0x2180 ; Internet Protocol Configure Protocol (maybe this should be in kernel?)
PPP_CCP = 0xfd80 ; Compression Configure Protocol
 
; PPP Active Discovery...
PPPoE_PADI = 0x09 ; .. Initiation
PPPoE_PADO = 0x07 ; .. Offer
PPPoE_PADR = 0x19 ; .. Request
PPPoE_PADS = 0x65 ; .. Session-confirmation
PPPoE_PADT = 0xa7 ; .. Terminate
 
TAG_EOL = 0x0000
TAG_SERVICE_NAME= 0x0101
TAG_AC_NAME = 0x0201
TAG_HOST_UNIQ = 0x0301
TAG_AC_COOKIE = 0x0401
 
LCP_config_request = 1
LCP_config_ack = 2
LCP_config_nak = 3
LCP_config_reject = 4
LCP_terminate_request = 5
LCP_terminate_ack = 6
LCP_code_reject = 7
LCP_protocol_reject = 8
LCP_echo_request = 9
LCP_echo_reply = 10
LCP_discard_request = 11
 
struct ETH_frame
DestMac dp ?
SrcMac dp ?
Type dw ?
ends
 
struct PPPoE_frame ETH_frame
VersionAndType db ?
Code db ?
SessionID dw ?
Length dw ? ; Length of payload, does NOT include the length PPPoE header.
Payload rb 0
ends
 
struct PPP_frame PPPoE_frame
Protocol dw ?
ends
 
struct LCP_frame PPP_frame
LCP_Code db ?
LCP_Identifier db ?
LCP_Length dw ?
LCP_Data rb 0
ends
 
; entry point
start:
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
; initialize console
push 1
call [con_start]
push title
push 25
push 80
push 25
push 80
call [con_init]
 
main:
mcall 40, 1 shl 7
 
call [con_cls]
; Welcome user
push str1
call [con_write_asciiz]
 
mcall socket, 777, 3, 666
mov [socketnum], eax
mcall send, [socketnum], PADI, PADI.length, 0
 
mainloop:
mcall 10
 
call [con_get_flags]
test eax, 0x200 ; con window closed?
jnz close_conn
 
mcall recv, [socketnum], buffer, 4096
cmp eax, sizeof.PPPoE_frame
jb mainloop
 
cmp word [buffer + ETH_frame.Type], ETHER_PPP_SESSION
je SESSION_input
 
cmp word [buffer + ETH_frame.Type], ETHER_PPP_DISCOVERY
jne mainloop
 
cmp [buffer + PPPoE_frame.Code], PPPoE_PADO
je pado
 
cmp [buffer + PPPoE_frame.Code], PPPoE_PADS
je pads
 
cmp [buffer + PPPoE_frame.Code], PPPoE_PADT
je padt
 
jmp mainloop
 
pado:
 
push str2
call [con_write_asciiz]
 
lea esi, [buffer + ETH_frame.SrcMac] ; source mac -> dest mac
lea edi, [buffer + ETH_frame.DestMac]
movsw
movsd
 
mov byte [buffer + PPPoE_frame.Code], PPPoE_PADR ; change packet type to PADR
 
mov al, byte [buffer + PPPoE_frame.Length + 1] ; get packet size
mov ah, byte [buffer + PPPoE_frame.Length + 0]
movzx esi, ax
add esi, sizeof.PPPoE_frame
mcall send, [socketnum], buffer, , 0 ; now send it!
 
jmp mainloop
 
 
pads:
 
push str3
call [con_write_asciiz]
 
mov edx, dword [buffer + ETH_frame.SrcMac] ; source mac -> dest mac
mov si, word [buffer + ETH_frame.SrcMac + 4]
mov dword [PADT.mac], edx
mov word [PADT.mac + 4], si
 
mov cx, word [buffer + PPPoE_frame.SessionID] ; and Session ID
mov [PADT.sid], cx
 
mcall 76, API_PPPOE + 0 ; Start PPPoE session
 
jmp mainloop
 
padt:
 
push str4
call [con_write_asciiz]
 
mcall 76, API_PPPOE + 1 ; Stop PPPoE session
 
exit:
mcall close, [socketnum]
mcall -1
 
 
close_conn:
 
mcall send, [socketnum], PADT, PADT.length, 0
jmp exit
 
 
SESSION_input:
 
mov ax, word[buffer + PPP_frame.Protocol]
 
cmp ax, PPP_LCP
je LCP_input
 
cmp ax, PPP_CBCP
je CBCP_input
 
cmp ax, PPP_PAP
je PAP_input
 
cmp ax, PPP_CHAP
je CHAP_input
 
cmp ax, PPP_IPCP
je IPCP_input
 
cmp ax, PPP_CCP
je CCP_input
 
jmp mainloop
 
 
 
LCP_input:
 
stdcall con_write_asciiz, str_lcp
 
cmp [buffer + LCP_frame.LCP_Code], LCP_echo_request
je .echo
 
.dump:
jmp mainloop
 
.echo:
mov [buffer + LCP_frame.LCP_Code], LCP_echo_reply
 
lea esi, [buffer + ETH_frame.SrcMac] ; source mac -> dest mac
lea edi, [buffer + ETH_frame.DestMac]
movsw
movsd
 
mov esi, eax
mcall send, [socketnum], buffer, , 0 ; now send it back!
 
jmp mainloop
 
CBCP_input:
 
stdcall con_write_asciiz, str_cbcp
 
jmp mainloop
 
PAP_input:
 
stdcall con_write_asciiz, str_pap
 
jmp mainloop
 
CHAP_input:
 
stdcall con_write_asciiz, str_chap
 
jmp mainloop
 
IPCP_input:
 
stdcall con_write_asciiz, str_ipcp
 
jmp mainloop
 
CCP_input:
 
stdcall con_write_asciiz, str_ccp
 
jmp mainloop
 
; data
title db 'PPPoE',0
str1 db 'Sending PADI',13,10,0
str2 db 'Got PADO',13,10,'Sending PADR',13,10,0
str3 db 'Got PADS',13,10,'starting PPPoE session',13,10,0
str4 db 'Got PADT - connection terminated by Access Concentrator',13,10,0
str_lcp db 'Got LCP packet',13,10,0
str_cbcp db 'got CBCP packet',13,10,0
str_pap db 'got PAP packet',13,10,0
str_chap db 'got CHAP packet',13,10,0
str_ipcp db 'got IPCP packet',13,10,0
str_ccp db 'got CCP packet',13,10,0
 
 
PADI:
dp 0xffffffffffff ; dest mac: broadcast
dp 0 ; source mac (overwritten by kernel)
dw ETHER_PPP_DISCOVERY ; type
 
db 0x11 ; Version and Type
db PPPoE_PADI ; Code
dw 0 ; session ID
dw 20 shl 8 ; Payload Length
 
dw TAG_SERVICE_NAME ; tag
dw 0x0000 ; length
 
dw TAG_HOST_UNIQ ; tag
dw 0x0c00 ; length = 12 bytes
 
dd 0xdead ; some random id
dd 0xbeef
dd 0x1337
 
.length = $ - PADI
 
PADT:
 
.mac dp 0 ; Dest mac, to be filled in
dp 0 ; source mac (overwritten by kernel)
dw ETHER_PPP_DISCOVERY ; Type
 
db 0x11 ; Version and Type
db PPPoE_PADT ; Code: terminate connection
.sid dw 0 ; session id, to be filled in
dw 0 ; PAyload length = 0
 
.length = $ - PADT
 
 
; import
align 4
@IMPORT:
 
library console, 'console.obj'
import console, \
con_start, 'START', \
con_init, 'con_init', \
con_write_asciiz, 'con_write_asciiz', \
con_exit, 'con_exit', \
con_gets, 'con_gets',\
con_cls, 'con_cls',\
con_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:
 
socketnum dd ?
 
buffer rb 4096
rb 4096 ; stack
mem:
/programs/network/pppoe
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network/proc32.inc
0,0 → 1,270
 
; 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
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 def \\{ match . type,def> \\\{ deflocal@proc .,label,<type \\\} \\}
struc db [val] \\{ \common deflocal@proc .,db,val \\}
struc du [val] \\{ \common deflocal@proc .,du,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,du,dw,dp,dd,dt,dq
restruc rb,rw,rp,rd,rt,rq
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
match =label,def \{ ..tmp equ \}
match tmp,..tmp \{ ..var def val \}
match ,..tmp \{ label ..var 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 }
/programs/network/socketdbg/socket.inc
0,0 → 1,164
struct LHEAD
next dd ? ;next object in list
prev dd ? ;prev object in list
ends
 
struct MUTEX
lhead LHEAD
count dd ?
ends
 
 
struct SOCKET
 
NextPtr dd ? ; pointer to next socket in list
PrevPtr dd ? ; pointer to previous socket in list
Number dd ? ; socket number
 
mutex MUTEX
 
PID dd ? ; application process id
Domain dd ? ; INET/UNIX/..
Type dd ? ; RAW/STREAM/DGRAP
Protocol dd ? ; ICMP/IPv4/ARP/TCP/UDP
errorcode dd ?
device dd ?
 
options dd ?
state dd ?
backlog dw ? ; how many incomming connections that can be queued
 
snd_proc dd ?
rcv_proc dd ?
 
ends
 
struct IP_SOCKET SOCKET
 
LocalIP rd 4 ; network byte order
RemoteIP rd 4 ; network byte order
 
ends
 
struct TCP_SOCKET IP_SOCKET
 
LocalPort dw ? ; network byte order
RemotePort dw ? ; network byte order
 
t_state dd ? ; TCB state
t_rxtshift db ?
rb 3 ; align
t_rxtcur dd ?
t_dupacks dd ?
t_maxseg dd ?
t_force dd ?
t_flags dd ?
 
;---------------
; RFC783 page 21
 
; send sequence
SND_UNA dd ? ; sequence number of unack'ed sent Packets
SND_NXT dd ? ; next send sequence number to use
SND_UP dd ? ; urgent pointer
SND_WL1 dd ? ; window minus one
SND_WL2 dd ? ;
ISS dd ? ; initial send sequence number
SND_WND dd ? ; send window
 
; receive sequence
RCV_WND dd ? ; receive window
RCV_NXT dd ? ; next receive sequence number to use
RCV_UP dd ? ; urgent pointer
IRS dd ? ; initial receive sequence number
 
;---------------------
; Additional variables
 
; receive variables
RCV_ADV dd ?
 
; retransmit variables
SND_MAX dd ?
 
; congestion control
SND_CWND dd ?
SND_SSTHRESH dd ?
 
;----------------------
; Transmit timing stuff
t_idle dd ?
t_rtt dd ?
t_rtseq dd ?
t_srtt dd ?
t_rttvar dd ?
t_rttmin dd ?
max_sndwnd dd ?
 
;-----------------
; Out-of-band data
t_oobflags dd ?
t_iobc dd ?
t_softerror dd ?
 
 
;---------
; RFC 1323 ; the order of next 4 elements may not change
 
SND_SCALE db ?
RCV_SCALE db ?
requested_s_scale db ?
request_r_scale db ?
 
ts_recent dd ? ; a copy of the most-recent valid timestamp from the other end
ts_recent_age dd ?
last_ack_sent dd ?
 
 
;-------
; Timers
timer_retransmission dd ? ; rexmt
timer_persist dd ?
timer_keepalive dd ? ; keepalive/syn timeout
timer_timed_wait dd ? ; also used as 2msl timer
 
; extra
 
ts_ecr dd ? ; timestamp echo reply
ts_val dd ?
temp_bits db ?
 
ends
 
struct UDP_SOCKET IP_SOCKET
 
LocalPort dw ? ; network byte order
RemotePort dw ? ; network byte order
firstpacket db ?
 
ends
 
 
struct ICMP_SOCKET IP_SOCKET
 
Identifier dw ?
 
ends
 
 
struct RING_BUFFER
 
start_ptr dd ? ; Pointer to start of buffer
end_ptr dd ? ; pointer to end of buffer
read_ptr dd ? ; Read pointer
write_ptr dd ? ; Write pointer
size dd ? ; Number of bytes buffered
 
ends
 
struct STREAM_SOCKET TCP_SOCKET
 
rcv RING_BUFFER
snd RING_BUFFER
 
ends
/programs/network/socketdbg/socketdbg.asm
0,0 → 1,100
format binary as ""
 
use32
; standard header
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem ; required memory
dd mem ; stack pointer
dd 0 ; parameters
dd 0 ; path
 
; useful includes
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
 
include '../struct.inc'
 
include 'socket.inc'
 
; entry point
start:
mcall 40, 0 ; we dont want any events
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
; initialize console
push 1
call [con_start]
push title
push -1
push -1
push -1
push -1
call [con_init]
; main loop
main:
mcall 75, 255, 0, socket_list ; get current socket list
 
call [con_cls]
 
mov esi, socket_list
.loop:
lodsd
test eax, eax
jz .done
 
mov ecx, eax
mcall 75, 255, , socket_buf
 
pushd [socket_buf + SOCKET.state]
pushd [socket_buf + SOCKET.PID]
pushd [socket_buf + SOCKET.Number]
push str_sock
call [con_printf]
add esp, 4
 
jmp .loop
 
.done:
 
mcall 23, 50
 
jmp main
 
 
push 0
call [con_exit]
exit:
mcall -1
 
; data
title db 'Socket debugger', 0
 
str_sock db 'Socket=%d PID=%d state=%d', 10, 0
 
; import
align 4
@IMPORT:
 
library console, 'console.obj'
 
import console, \
con_start, 'START', \
con_init, 'con_init', \
con_cls, 'con_cls', \
con_exit, 'con_exit', \
con_printf, 'con_printf'
i_end:
 
socket_list rd 4096
socket_buf rd 4096
 
align 4
rb 4096 ; stack
mem:
/programs/network/socketdbg
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network/struct.inc
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 \} }
/programs/network/synergyc/synergyc.asm
0,0 → 1,384
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Synergyc.asm - Synergy client for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format binary as ""
 
use32
org 0x0
 
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem+0x1000 ; required memory
dd mem+0x1000 ; stack pointer
dd 0 ; parameters
dd path ; path
 
__DEBUG__ equ 1 ; enable/disable
__DEBUG_LEVEL__ equ 1 ; 1 = all, 2 = errors
 
 
BUFFERSIZE equ 1024
DEFAULTPORT equ 24800
 
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
 
include '../network.inc'
 
start:
 
cld
mov edi, path ; Calculate the length of zero-terminated string
xor al, al
mov ecx, 1024
repne scasb
dec edi
mov esi, filename ; append the path with '.ini'
movsd
movsb
 
mcall 68, 11
 
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
 
push 1
call [con_start]
 
push title
push 25
push 80
push 25
push 80
call [con_init]
 
push path
call [con_write_asciiz]
 
push newline
call [con_write_asciiz]
 
push newline
call [con_write_asciiz]
 
invoke ini.get_str, path, str_remote, str_ip, buffer_ptr, 16, 0
test eax, eax
jnz error
 
invoke ini.get_int, path, str_remote, str_port, DEFAULTPORT
xchg al, ah
mov [sockaddr1.port], ax
 
push str1
call [con_write_asciiz]
 
push buffer_ptr
call [con_write_asciiz]
 
push newline
call [con_write_asciiz]
 
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
je error
 
mov [socketnum], eax
 
push buffer_ptr ; hostname
call [inet_addr]
cmp eax, -1
je error
mov [sockaddr1.ip], eax
 
mcall connect, [socketnum], sockaddr1, 18
 
push str7
call [con_write_asciiz]
 
mcall 40, 1 shl 7; + 7
 
login:
call wait_for_data
 
push buffer_ptr + 4
call [con_write_asciiz]
 
cmp dword [buffer_ptr], 11 shl 24
jne login
cmp dword [buffer_ptr + 4], 'Syne'
jne login
cmp word [buffer_ptr + 8], 'rg'
jne login
cmp byte [buffer_ptr + 10], 'y'
jne login
 
push str2
call [con_write_asciiz]
 
lea edi, [buffer_ptr + 11 + 4 + 4]
invoke ini.get_str, path, str_local, str_name, edi, 255, 0
xor al , al
mov ecx, 256
repne scasb
sub edi, buffer_ptr + 1 + 4
mov esi, edi
bswap edi
mov dword [buffer_ptr], edi
mov edi, esi
sub edi, 11 + 4
bswap edi
mov dword [buffer_ptr + 11 + 4], edi
add esi, 4
 
mcall send, [socketnum], buffer_ptr, , 0
 
mainloop:
call wait_for_data
mov edi, buffer_ptr
 
.command:
push eax edi
 
cmp dword [edi + 4], 'QINF' ; query screen info
je .qinf
 
cmp dword [edi + 4], 'CALV' ; alive ?
je .calv
 
cmp dword [edi + 4], 'CINN' ; mouse moved into screen
je .cinn
 
cmp dword [edi + 4], 'DCLP' ; Clipboard event
je .dclp
 
cmp dword [edi + 4], 'DMMV' ; Mouse moved
je .dmmv
 
cmp dword [edi + 4], 'COUT' ; leave screen
je .cout
 
cmp dword [edi + 4], 'DMDN' ; mouse button down
je .dmdn
 
cmp dword [edi + 4], 'DMUP' ; mouse button released
je .dmup
 
cmp dword [edi + 4], 'CNOP' ; no operation
je .next
 
cmp dword [edi + 4], 'CIAK' ; resolution changed?
je .ciak
 
push str3
call [con_write_asciiz]
 
mov byte[edi+8],0
add edi, 4
push edi
call [con_write_asciiz]
 
push newline
call [con_write_asciiz]
 
.next:
pop edi eax
 
mov ecx, dword [edi]
bswap ecx
add ecx, 4
sub eax, ecx
jle mainloop
add edi, ecx
jmp .command
 
 
.qinf:
mcall 14 ; get screen info
add eax, 0x00010001
bswap eax
mov dword [screeninfo.size], eax
mcall send, [socketnum], screeninfo, screeninfo.length, 0 ; send client name
jmp .next
 
 
.calv:
mcall send, [socketnum], calv, calv.length, 0 ; looks like ping-pong event
jmp .next
 
 
.cinn:
mov edx, [edi + 8]
bswap edx
mcall 18, 19, 4
; ignore sequence number and modify key mask for now
push str6
call [con_write_asciiz]
jmp .next
 
.dclp:
 
jmp .next
 
.dmmv:
mov edx, [edi + 8]
bswap edx
mcall 18, 19, 4
mcall send, [socketnum], cnop, cnop.length, 0 ; reply with NOP
push str4
call [con_write_asciiz]
jmp .next
 
.cout:
jmp .next
 
.dmdn:
movzx eax, byte [edi + 8]
or [mousestate], eax
mcall 18, 19, 5, [mousestate]
mcall send, [socketnum], cnop, cnop.length, 0 ; reply with NOP
push str5
call [con_write_asciiz]
jmp .next
 
.dmup:
movzx eax, byte [edi + 8]
not eax
and [mousestate], eax
mcall 18, 19, 5, [mousestate]
mcall send, [socketnum], cnop, cnop.length, 0 ; reply with NOP
push str5
call [con_write_asciiz]
jmp .next
 
.ciak:
jmp .next
 
error:
push str_err
call [con_write_asciiz]
 
call [con_gets]
 
push 1
call [con_exit]
 
mcall close, [socketnum]
exit:
 
mcall -1
 
 
wait_for_data:
mcall 10 ; wait for data
 
mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, 0
cmp eax, -1
je wait_for_data
 
cmp eax, 8
jl wait_for_data
 
ret
 
 
 
; data
title db 'Synergy client',0
str1 db 'Connecting to: ',0
str7 db 'Connected!',13,10,0
str2 db 13,10,'Handshake received',13,10,0
str3 db 'Unsupported command: ',0
newline db 13,10,0
str4 db 'mouse moved',13,10,0
str5 db 'mouse buttons changed',13,10,0
str6 db 'Enter screen',13,10,0
str_err db 'Error occured !',13,10,'Press any key to quit',0
 
screeninfo:
dd (screeninfo.length - 4) shl 24
db 'DINF'
dw 0 ; coordinate of leftmost pixel
dw 0 ; coordiante of topmost pixel
.size:
dw 0 ; width
dw 0 ; height
 
dw 0 ; size of warp zone
 
dw 0xb88b ; x position of the mouse on the secondary screen (no idea what it means)
dw 0xbcfb ; y position of the mouse on the secondary screen
.length = $ - screeninfo
 
calv:
dd (4) shl 24
db 'CALV'
.length = $ - calv + 8 ; also send cnop
 
cnop:
dd (4) shl 24
db 'CNOP'
.length = $ - cnop
 
mousestate dd 0
 
 
sockaddr1:
dw AF_INET4
.port dw 0
.ip dd 192 + 168 shl 8 + 1 shl 16 + 115 shl 24
rb 10
 
filename db '.ini', 0
str_local db 'local', 0
str_name db 'name', 0
str_remote db 'remote', 0
str_port db 'port', 0
str_ip db 'ip', 0
 
; import
align 16
@IMPORT:
 
library console, 'console.obj',\
network, 'network.obj',\
libini, 'libini.obj'
 
import network,\
inet_addr, 'inet_addr'
 
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'
 
import libini,\
ini.get_str, 'ini_get_str',\
ini.get_int, 'ini_get_int'
 
align 4
i_end:
socketnum dd ?
buffer_ptr rb BUFFERSIZE
path rb 4096 ; stack
mem:
/programs/network/synergyc/synergyc.ini
0,0 → 1,6
[local]
name = karaboeia
 
[remote]
ip = 192.168.1.115
port = 24800
/programs/network/synergyc
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network/tcpserv/tcpserv.asm
0,0 → 1,168
format binary as ""
 
use32
; standard header
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem ; required memory
dd mem ; stack pointer
dd 0 ; parameters
dd 0 ; path
 
 
BUFFERSIZE equ 1500
; useful includes
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
 
include '../network.inc'
 
; entry point
start:
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
 
; initialize console
push 1
call [con_start]
push title
push 25
push 80
push 25
push 80
call [con_init]
 
mcall 40, 1 shl 7 ; we only want network events
 
push str1
call [con_write_asciiz]
 
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
je sock_err
 
mov [socketnum], eax
 
;; mcall setsockopt, [socketnum], SOL_SOCKET, SO_REUSEADDR, &yes,
;; cmp eax, -1
;; je opt_err
 
mcall bind, [socketnum], sockaddr1, sockaddr1.length
cmp eax, -1
je bind_err
 
mcall listen, [socketnum], 10 ; Backlog = 10
cmp eax, -1
je listen_err
 
push str2
call [con_write_asciiz]
 
mcall 10
 
mcall accept, [socketnum], sockaddr1, sockaddr1.length
cmp eax, -1
je acpt_err
 
mov [socketnum2], eax
 
;; mcall close, [socketnum]
 
mcall send, [socketnum2], hello, hello.length
 
.loop:
mcall 10
 
mcall recv, [socketnum2], buffer, buffer.length
cmp eax, -1
je .loop
 
mov byte [buffer + eax], 0
 
push buffer
call [con_write_asciiz]
 
jmp .loop
 
acpt_err:
push str8
call [con_write_asciiz]
jmp done
 
listen_err:
push str3
call [con_write_asciiz]
jmp done
 
bind_err:
push str4
call [con_write_asciiz]
jmp done
 
sock_err:
push str6
call [con_write_asciiz]
jmp done
 
done:
call [con_getch2]
push 1
call [con_exit]
exit:
mcall -1
 
 
 
; data
title db 'TCP stream server - test',0
str1 db 'Opening socket',10, 0
str2 db 'Listening for incoming connections...',10,0
str3 db 'Listen error',10,10,0
str4 db 'Bind error',10,10,0
str5 db 'Setsockopt error.',10,10,0
str6 db 'Could not open socket',10,10,0
str7 db 'Got data!',10,10,0
str8 db 'Error accepting connection',10,10,0
 
hello db 'Hello world!',0
.length = $ - hello
 
sockaddr1:
dw AF_INET4
.port dw 0x1700 ; 23
.ip dd 0
rb 10
.length = $ - sockaddr1
 
; import
align 4
@IMPORT:
 
library console, 'console.obj'
 
import console, \
con_start, 'START', \
con_init, 'con_init', \
con_write_asciiz, 'con_write_asciiz', \
con_exit, 'con_exit', \
con_gets, 'con_gets',\
con_cls, 'con_cls',\
con_printf, 'con_printf',\
con_getch2, 'con_getch2',\
con_set_cursor_pos, 'con_set_cursor_pos'
i_end:
 
socketnum dd ?
socketnum2 dd ?
buffer rb BUFFERSIZE
.length = BUFFERSIZE
 
align 4
rb 4096 ; stack
mem:
/programs/network/tcpserv
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network/telnet/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/telnet/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/telnet/trunk/telnet.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/telnet/telnet.asm
0,0 → 1,305
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2012. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; telnet.asm - Telnet client for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format binary as ""
 
__DEBUG__ equ 0
__DEBUG_LEVEL__ equ 1
BUFFERSIZE equ 4096
 
use32
; standard header
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem ; required memory
dd mem ; stack pointer
dd s ; parameters
dd 0 ; path
 
include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
include '../debug-fdo.inc'
include '../network.inc'
 
; entry point
start:
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
; initialize console
push 1
call [con_start]
push title
push 25
push 80
push 25
push 80
call [con_init]
 
; 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 ; + 7
call [con_cls]
 
mcall 18, 7
push eax
mcall 51, 1, thread, mem - 2048
pop ecx
mcall 18, 3
 
mainloop:
DEBUGF 1, 'TELNET: Waiting for events\n'
mcall 10
DEBUGF 1, 'TELNET: EVENT %x !\n', eax
 
call [con_get_flags]
test eax, 0x200 ; con window closed?
jnz exit
 
mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, 0
cmp eax, -1
je mainloop
 
DEBUGF 1, 'TELNET: got %u bytes of data !\n', eax
 
mov esi, buffer_ptr
lea edi, [esi + eax]
mov byte [edi], 0
 
.scan_cmd:
cmp byte [esi], 0xff ; Interpret As Command
jne .no_cmd
; TODO: parse options, for now, we will reply with 'WONT' to everything
mov byte [esi + 1], 252 ; WONT
add esi, 3 ; a command is always 3 bytes
jmp .scan_cmd
.no_cmd:
 
cmp esi, buffer_ptr
je .print_loop
 
DEBUGF 1, 'TELNET: sending data\n'
 
push esi edi
sub esi, buffer_ptr
mcall send, [socketnum], buffer_ptr, , 0
pop edi esi
 
.print_loop:
DEBUGF 1, 'TELNET: printloop\n'
cmp esi, edi
jae mainloop
 
cmp byte [esi], 0x1b ; escape character
jne .print_byte
inc esi
 
cmp word [esi], 0x485b ; move cursor to beginning
jne @f
inc esi
inc esi
 
DEBUGF 1, 'TELNET: resetting cursor \n'
 
push 0
push 0
call [con_set_cursor_pos]
jmp .print_loop
 
@@:
inc esi
inc esi
jmp .print_loop
 
.print_byte:
push dword 1
push esi ; next string to print
inc esi
call [con_write_string]
jmp .print_loop
 
 
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
 
 
 
thread:
mcall 40, 0
.loop:
call [con_getch2]
mov byte [send_data], al
mcall send, [socketnum], send_data, 1
 
call [con_get_flags]
test eax, 0x200 ; con window closed?
jz .loop
mcall -1
 
; data
title db 'Telnet',0
str1 db 'Telnet for KolibriOS v0.11',10,10,'Please enter URL of telnet server (for example: towel.blinkenlights.nl)',10,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,'Could not open socket.',10,0
str8 db ' (',0
str9 db ')',10,0
str10 db 'Push any key to continue.',0
 
sockaddr1:
dw AF_INET4
.port dw 0x1700 ; 23
.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:
 
socketnum dd ?
buffer_ptr rb BUFFERSIZE+1
send_data rb 100
 
s rb 1024
rb 4096 ; stack
mem:
/programs/network/tftpc/trunk/build_en.bat
File deleted
\ No newline at end of file
/programs/network/tftpc/trunk/build_ru.bat
File deleted
\ No newline at end of file
/programs/network/tftpc/trunk/tftpc.asm
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/programs/network/tftpc/tftpc.asm
0,0 → 1,566
format binary as ""
 
use32
org 0x0
 
db 'MENUET01'
dd 0x1
dd START
dd I_END
dd IM_END
dd IM_END
dd 0, 0
 
include '../proc32.inc'
include '../macros.inc'
include '../libio.inc'
include '../dll.inc'
include '../../../../../programs/develop/libraries/box_lib/trunk/box_lib.mac'
 
include '../network.inc'
 
 
filebuffer_size equ 4*4096 ; 16kb (dont try to change it yet..)
TIMEOUT equ 100
buffer_len equ 1500
 
AF_INET4 equ 2
IP_PROTO_UDP equ 17
 
opcode_rrq equ 1
opcode_wrq equ 2
opcode_data equ 3
opcode_ack equ 4
opcode_error equ 5
 
; read/write request packet
;
; 2 bytes string 1 byte string 1 byte
; ------------------------------------------------
; | Opcode | Filename | 0 | Mode | 0 |
; ------------------------------------------------
 
; data packet
;
; 2 bytes 2 bytes n bytes
; ----------------------------------
; | Opcode | Block # | Data |
; ----------------------------------
 
; acknowledgement packet
;
; 2 bytes 2 bytes
; ---------------------
; | Opcode | Block # |
; ---------------------
 
; error packet
;
; 2 bytes 2 bytes string 1 byte
; ----------------------------------------
; | Opcode | ErrorCode | ErrMsg | 0 |
; ----------------------------------------
 
 
START:
 
mcall 68, 11
 
stdcall dll.Load, @IMPORT
or eax, eax
jnz exit
 
stop_transfer:
mcall 40, 00100111b
 
red_win:
call draw_window
 
align 4
still:
mcall 10
 
dec eax
jz red_win
 
dec eax
jz key
 
dec eax
jz button
 
push dword edit1
call [edit_box_mouse]
 
push dword edit2
call [edit_box_mouse]
 
push dword edit3
call [edit_box_mouse]
 
push dword edit4
call [edit_box_mouse]
 
push dword Option_boxs1
call [option_box_mouse]
 
push dword Option_boxs2
call [option_box_mouse]
 
jmp still
 
button:
mcall 17
 
cmp ah,0x10
je start_transfer
 
 
test ah , ah
jz still
 
exit: mcall -1
key:
mcall 2
 
push dword edit1
call [edit_box_key]
 
push dword edit2
call [edit_box_key]
 
push dword edit3
call [edit_box_key]
 
push dword edit4
call [edit_box_key]
 
jmp still
 
 
align 4
draw_window:
mcall 12,1
mcall 0, (50*65536+400), (30*65536+180), 0x34AABBCC, 0x085080DD, str_title
 
mcall 4, 35*65536+10, 0x80000000, str_server
 
mov ebx, 5*65536+30
mov edx, str_source
mcall
 
mov ebx, 11*65536+50
mov edx, str_destination
mcall
 
mov ebx, 47*65536+72
mov edx, str_mode
mcall
 
mov ebx, 160*65536+72
mov edx, str_method
mcall
 
mov ebx, 270*65536+72
mov edx, str_blocksize
mcall
 
push dword edit1
call [edit_box_draw]
 
push dword edit2
call [edit_box_draw]
 
push dword edit3
call [edit_box_draw]
 
push dword edit4
call [edit_box_draw]
 
push dword Option_boxs1
call [option_box_draw]
 
push dword Option_boxs2
call [option_box_draw]
 
mcall 8,210*65536+170, 105*65536+16,0x00000010,0x085080DD
 
mcall 4,260*65536+110, 0x80000000, str_transfer
 
mcall 38,10*65536+380, 130*65536+130,0x00000000
 
mcall 4,350*65536+137, 0x80000000, str_kb_s
 
mcall 47,1 shl 31 + 7 shl 16 + 1,kbps,305*65536+137,0x00000000
 
mcall 4,50*65536+137, 0x80000000, str_complete
 
mcall 47,1 shl 31 + 3 shl 16 + 1,done,25*65536+137,0x00000000
 
mcall 12,2
 
ret
 
 
 
 
 
start_transfer:
 
; first, resolve the hostname
 
push esp ; reserve stack place
 
push esp ; fourth parameter
push 0 ; third parameter
push 0 ; second parameter
push dword SRV ; first parameter
call [getaddrinfo]
 
pop esi
 
; test for error
test eax, eax
jnz still
 
mov esi, [esi]
mov esi, [esi + sockaddr_in.sin_addr]
mov dword [IP], esi
 
mcall socket, AF_INET4, SOCK_DGRAM, 0 ; socket_open
cmp eax, -1
je still
 
mov [socketnum], eax
 
mcall connect, [socketnum], sockaddr, sockaddr_len ; socket_connect
cmp eax, -1
je still
 
mov word [I_END], opcode_rrq
cmp [option_group2],op3
je @f
mov word [I_END], opcode_wrq
@@:
 
xor al , al
mov edi, remote_addr
mov ecx, 250
repnz scasb
sub edi, remote_addr-1
mov ecx, edi
mov edi, I_END+2
mov esi, remote_addr
rep movsb
 
cmp [option_group1], op1
je .ascii
 
mov esi, octet
movsd
movsb
 
jmp .send_request
 
.ascii:
 
mov esi, netascii
movsd
movsd
 
.send_request:
 
xor al, al
stosb
 
sub edi, I_END
mov esi, edi
mcall send, [socketnum], I_END
 
mcall 40, 10000101b
 
mov [last_ack], 0
 
 
 
 
 
 
receive_data_loop:
 
mcall 23, TIMEOUT
 
dec eax
jz .red
 
dec eax
jz .key
 
 
mcall recv, [socketnum], buffer, buffer_len, 0 ; receive data
 
cmp word[buffer], opcode_data
jne .error
 
mov bx, [last_ack]
cmp word [buffer + 2], bx
jne .packet_got_lost
inc [last_ack]
 
cmp eax, 4+512
je .continue
 
; last packet, or something else
.error:
 
.packet_got_lost:
 
 
 
.continue:
 
mov word[buffer], opcode_ack ; send ack
mcall send, [socketnum], buffer, 4, 0
 
jmp receive_data_loop
 
.red:
 
call draw_window
 
jmp receive_data_loop
 
 
.key:
mcall 2
cmp ah, 2
jz exit
 
; close socket ?
 
jmp receive_data_loop
 
 
 
 
 
 
;--------------------------------
 
 
send_:
 
invoke file_open, local_addr, O_READ
or eax, eax
jz .exit
mov [fh], eax
 
stdcall mem.Alloc, filebuffer_size
or eax, eax
jz .exit
mov [fb], eax
 
mov [last_ack], 0
mov [fo], 0
 
.read_chunk:
 
invoke file_seek, [fh], [fo], SEEK_END
cmp eax, -1
je .exit
invoke file_read, [fh], [fb], filebuffer_size
cmp eax, -1
je .exit
add [fo], filebuffer_size
cmp eax, filebuffer_size
je .packet
 
; ijhidfhfdsndsfqk
 
.packet:
 
movzx esi, [last_ack]
and esi, 0x000000001f ; last five bits BUFFER SIZE MUST BE 16 kb for this to work !!!
shl esi, 9 ; = * 512
add esi, [fb]
mov edi, buffer
mov ax, opcode_data
stosw
mov ax, [last_ack]
stosw
mov ecx, 512/4
rep movsd
 
mcall send, [socketnum], buffer, 4+512, 0 ; send data
 
 
.loop:
 
mcall 23, TIMEOUT
 
dec eax
jz .red
 
dec eax
jz .key
 
mcall recv, [socketnum], buffer, buffer_len, 0 ; receive ack
 
cmp word[buffer], opcode_ack
jne .exit
 
mov ax, [last_ack]
cmp word[buffer+2], ax
jne .packet
inc [last_ack]
test [last_ack],0x001f
jz .read_chunk
jmp .packet
 
 
.red:
 
call draw_window
 
jmp .loop
 
 
.key:
mcall 2
cmp ah, 2
jz exit
 
; close socket ?
 
jmp .loop
 
.exit:
invoke file_close, [fh]
jmp still
 
 
 
 
 
;-------------------------
; DATA
 
socketnum dd 0
kbps dd 0
done dd 0
 
sockaddr:
dw AF_INET4
dw 0x4500 ; 69
IP db 192,168,1,115
sockaddr_len = $ - sockaddr
 
align 16
@IMPORT:
 
library box_lib , 'box_lib.obj', \
io_lib , 'libio.obj', \
network , 'network.obj'
 
import box_lib ,\
edit_box_draw ,'edit_box' ,\
edit_box_key ,'edit_box_key' ,\
edit_box_mouse ,'edit_box_mouse' ,\
version_ed ,'version_ed' ,\
init_checkbox ,'init_checkbox2' ,\
check_box_draw ,'check_box_draw2' ,\
check_box_mouse ,'check_box_mouse2' ,\
version_ch ,'version_ch2' ,\
option_box_draw ,'option_box_draw' ,\
option_box_mouse ,'option_box_mouse' ,\
version_op ,'version_op'
 
import io_lib ,\
file_find_first , 'file_find_first' ,\
file_find_next , 'file_find_next' ,\
file_find_close , 'file_find_close' ,\
file_size , 'file_size' ,\
file_open , 'file_open' ,\
file_read , 'file_read' ,\
file_write , 'file_write' ,\
file_seek , 'file_seek' ,\
file_tell , 'file_tell' ,\
file_eof? , 'file_iseof' ,\
file_seteof , 'file_seteof' ,\
file_truncate , 'file_truncate' ,\
file_close , 'file_close'
 
import network ,\
inet_ntoa , 'inet_ntoa' ,\
getaddrinfo , 'getaddrinfo' ,\
freeaddrinfo , 'freeaddrinfo'
 
 
edit1 edit_box 300,80,5 ,0xffffff,0x6f9480,0,0,0,99 ,SRV,mouse_dd,ed_focus, 11,11
edit2 edit_box 300,80,25,0xffffff,0x6a9480,0,0,0,99 ,remote_addr,mouse_dd,ed_figure_only, 5,5
edit3 edit_box 300,80,45,0xffffff,0x6a9480,0,0,0,99 ,local_addr,mouse_dd,ed_figure_only, 27,27
edit4 edit_box 40,340,68,0xffffff,0x6a9480,0,0,0,5 ,BLK,mouse_dd,ed_figure_only, 3,3
 
op1 option_box option_group1,80,68,6,12,0xffffff,0,0,netascii,octet-netascii
op2 option_box option_group1,80,85,6,12,0xFFFFFF,0,0,octet,get-octet
 
op3 option_box option_group2,210,68,6,12,0xffffff,0,0,get,put-get
op4 option_box option_group2,210,85,6,12,0xFFFFFF,0,0,put,BLK-put
 
option_group1 dd op1
option_group2 dd op3
Option_boxs1 dd op1,op2,0
Option_boxs2 dd op3,op4,0
 
str_title db 'TFTP client for KolibriOS',0
str_server db 'Server:',0
str_source db 'Remote file:',0
str_destination db 'Local file:',0
str_mode db 'Mode:',0
str_method db 'Method:',0
str_blocksize db 'Blocksize:',0
str_kb_s db 'kb/s',0
str_complete db '% complete',0
str_transfer db 'Transfer',0
 
str_error:
._0 db 'Not defined, see error message (if any).',0
._1 db 'File not found.',0
._2 db 'Access violation.',0
._3 db 'Disk full or allocation exceeded.',0
._4 db 'Illegal TFTP operation.',0
._5 db 'Unknown transfer ID.',0
._6 db 'File already exists.',0
._7 db 'No such user.',0
 
 
netascii db 'NetASCII'
octet db 'Octet'
get db 'GET'
put db 'PUT'
 
BLK db "512",0,0,0
 
last_ack dw ?
 
fh dd ? ; file handle
fo dd ? ; file offset
fb dd ? ; file buffer
 
SRV db "192.168.1.115",0
rb (SRV + 256 - $)
 
remote_addr db "IMG00",0
rb (remote_addr + 256 - $)
 
local_addr db "/hd0/1/KolibriOS/kernel.mnt",0
rb (local_addr + 256 - $)
 
I_END:
mouse_dd dd ?
buffer:
rb buffer_len
 
rb 0x1000 ; stack
 
IM_END:
/programs/network/vncc/logon.inc
0,0 → 1,257
red_logon:
call draw_window_logon ; at first, draw the window
 
still_logon: ; main cycle of application begins here
mov eax,10 ; wait here for event
mcall
 
checkevent_logon: ; Check what event was called _logon: this will be used to return from textbox focus
 
dec eax ; redraw request ?
jz red_logon
dec eax ; key in buffer ?
jz key_logon
dec eax ; button in buffer ?
jz button_logon
 
jmp still_logon
 
key_logon: ; key event handler
mov al,2 ; eax was zero so will now be 2
mcall ; just read it and ignore
 
cmp ah,13
jne still_logon ; return to main loop
 
ret ; enter key was pressed => return to logon
 
button_logon: ; eax was zero so will now be 17
mov al,17 ; get id
mcall
 
cmp ah,1 ; close ?
jz close_logon
cmp ah,2 ; logon ?
je connect_logon
cmp ah,5 ; first ?
jz dstbtn_logon
 
srcbtn_logon:
mov dword[addr],first
jmp rk_logon
 
dstbtn_logon:
mov dword[addr],second
 
rk_logon:
mov edi,[addr] ; load the address of the string
xor al,al ; mov al,0 ; the symbol we will search for
mov ecx,STRLEN+1 ; length of the string (+1)
cld ; search forward
repne scasb ; do search now
inc ecx ; we've found a zero or ecx became 0
mov eax,STRLEN+1
sub eax,ecx ; eax = address of <0> character
mov [temp],eax ; position
 
cmp dword[addr],dword second
jne @f
mov dword [passlen],eax
@@:
 
call print_text_logon
 
mov edi,[addr] ; address of string
add edi,[temp] ; cursor position
 
.waitev_logon:
mov eax,10 ; wait for event
mcall
cmp eax,2 ; button presed ?
jne checkevent_logon ; a key is pressed or redraw is nessesary, goto checkevent
mcall ; eax = 2, read button
shr eax,8
cmp eax,8
jnz .nobs_logon ; BACKSPACE
cmp edi,[addr]
jz .waitev_logon
dec edi
mov byte[edi],0
 
cmp dword[addr],second
jne @f
dec [passlen]
@@:
 
call print_text_logon
jmp .waitev_logon
.nobs_logon:
cmp eax,13 ; ENTER
je still_logon
cmp eax,192
jne .noclear_logon
xor al,al
mov edi,[addr]
mov ecx,STRLEN
rep stosb
mov edi,[addr]
call print_text_logon
jmp .waitev_logon
 
.noclear_logon:
mov [edi],al
 
cmp dword[addr],second
jne @f
inc [passlen]
@@:
 
call print_text_logon
 
inc edi
mov esi,[addr]
add esi,STRLEN
cmp esi,edi
jnz .waitev_logon
 
jmp still_logon
 
 
; print strings (source & destination)
print_text_logon:
pusha
 
mov eax, 8
mov ebx, 105*65536+200
mov ecx, 31*65536+13
mov edx, 4
mov esi, 0xEBEBEB
mcall
 
cmp byte[mode],0
je @f
 
mov ecx, 49*65536+12
inc edx
mcall
 
@@:
mov eax, 4 ; function 4 _logon: write text to window
mov ebx, 107*65536+34 ; [x start] *65536 + [y start]
xor ecx, ecx ; color of text RRGGBB
mov edx, first ; pointer to text beginning
mov esi, STRLEN ; text length
mcall
 
cmp byte[mode],0
je dont_draw_pass
 
add ebx,16
mov edi,[passlen]
 
@@:
cmp edi,0
jle dont_draw_pass
 
dec edi
mov edx, passchar
mov esi, 1
mcall
add ebx,6*65536
jmp @r
 
dont_draw_pass:
 
popa
ret
 
close_logon:
or eax,-1
mcall
 
connect_logon:
ret
 
draw_window_logon:
 
mcall 12, 1 ; start window draw
pusha
; DRAW WINDOW
xor eax, eax ; function 0 _logon: define and draw window
mov ebx, 160*65536+330 ; [x start] *65536 + [x size]
mov ecx, 160*65536+100 ; [y start] *65536 + [y size]
mov edx, 0x13DDDDDD ; color of work area RRGGBB
mov edi, title ; WINDOW LABEL
mcall
 
mov eax, 8 ; LOGON BUTTON
mov ebx, 220*65536+85
mov ecx, 63*65536+16
mov edx, 2
mov esi, 0xCCCCCC
mcall
 
call print_text_logon
cmp byte[mode], 0
je servermode_
 
mov eax, 4 ; function 4 write text to window
mov ebx, 25*65536+33 ; [x start] *65536 + [y start]
xor ecx, ecx
mov edx, userstr ; pointer to text beginning
mov esi, passstr-userstr ; text length
mcall
 
add bl,19
mov edx, passstr ; pointer to text beginning
mov esi, connectstr-passstr ; text length
mcall
 
jmp drawtherest_
 
servermode_:
 
mov eax, 4 ; function 4 write text to window
mov ebx, 25*65536+33 ; [x start] *65536 + [y start]
xor ecx, ecx
mov edx, serverstr ; pointer to text beginning
mov esi, userstr-serverstr ; text length
mcall
 
drawtherest_:
 
mov ebx, 240*65536+67 ; [x start] *65536 + [y start]
mov edx, connectstr ; pointer to text beginning
mov esi, connect_e-connectstr ; text length
mcall
 
popa
inc ebx
mcall
 
ret
 
 
; DATA AREA
title db 'Kolibrios VNC client by HIDNPLAYR',0
 
first: db '192.168.1.5'
rb STRLEN
second: rb STRLEN
 
passchar db '*'
passlen dd 0
 
addr dd 0
temp dd 0
mode db 0 ; 0 = connection details, 1 = authentication
 
serverstr: db 'server:'
userstr: db 'username:'
passstr: db 'password:'
connectstr: db 'connect !'
connect_e:
 
I_END_logon:
/programs/network/vncc/raw.inc
0,0 → 1,153
encoding_raw:
DEBUGF 1,'RAW\n'
 
mov ax,[frame.y] ;
mov bx,[screen.width] ;
mul bx ;
shl edx,16 ;
mov dx,ax ; [screen.width]*[frame.y]
movzx eax,[frame.x]
add edx,eax ; [screen.width]*[frame.y]+[frame.x]
 
mov eax,3 ;
mul edx ; ([screen.width]*[frame.y]+[frame.x])*3
 
add eax,framebuffer_data ;
push eax ; framebuffer_data+([screen.width]*[frame.y]+[frame.x])*3
 
mov ax,[frame.width] ;
mov bx,3 ;
mul bx ;
shl edx,16 ;
mov dx,ax ; [frame.width]*3
 
pop eax ;
add edx,eax ; framebuffer_data+([screen.width]*[frame.y]+[frame.x])*3+[frame.width]*3
push eax ;
push edx ;
 
mov ax,[frame.height] ;
dec ax ;
mov bx,3 ;
mul bx ;
mov bx,[screen.width] ;
mul bx ;
shl edx,16 ;
mov dx,ax ;
mov ecx,edx ;
pop edx ;
add ecx,edx ; mov ecx,edx+([frame.height]-1)*[screen.width]*3
pop ebx
 
.pixelloop32:
cmp ebx,ecx
jge next_rectangle
 
; add esi,2 ; 32 bit code RAW - OK
; mov al,[esi] ;
; mov [ebx],al ;
; inc ebx ;
; dec esi ;
; ;
; mov al,[esi] ;
; mov [ebx],al ;
; inc ebx ;
; dec esi ;
; ;
; mov al,[esi] ;
; mov [ebx],al ;
; inc ebx ;
; add esi,4 ;
 
; push ecx ; 16 bit code RAW
; mov cl,51
;
; mov ax,[esi] ;
; xchg al,ah
; and al,00011111b ;
; xchg al,ah
; mul cl
; mov [ebx],al ;
; inc ebx ;
;
; mov ax,[esi] ;
; xchg al,ah
; shr ax,5 ;
; xchg al,ah
; and al,00011111b ;
; mul cl
; mov [ebx],al ;
; inc ebx ;
;
; mov ax,[esi] ;
; xchg al,ah
; shr ax,10 ;
; and al,00011111b ;
; mul cl
; mov [ebx],al ;
; inc ebx ;
;
; inc esi ;
; inc esi ;
; pop ecx
 
push ecx ; 8 bit code RAW - OK
mov cl,85 ;
;
mov al,[esi] ;
shr al,4 ;
and al,3 ;
mul cl ;
mov [ebx],al ;
inc ebx ;
;
mov al,[esi] ;
shr al,2 ;
and al,3 ;
mul cl ;
mov [ebx],al ;
inc ebx ;
;
mov al,[esi] ;
and al,3 ;
mul cl ;
mov byte[ebx],al ;
inc ebx ;
inc esi ;
pop ecx ;
 
 
cmp ebx,edx
jl .pixelloop32
 
push edx
push ebx
mov ax,[screen.width]
mov bx,3
mul bx
shl edx,16
mov dx,ax
mov eax,edx
pop ebx
pop edx
 
add ebx,eax ; eax = [screen.width]*3
add edx,eax
 
push edx
push ebx
mov ax,[frame.width]
mov bx,3
mul bx
shl edx,16
mov dx,ax
mov eax,edx
pop ebx
pop edx
 
sub ebx,eax ; eax = [frame.width]*3
 
jmp .pixelloop32
 
 
 
/programs/network/vncc/structs.inc
0,0 → 1,22
 
struct pixel_format
bpp db ?
depth db ?
big_endian db ?
true_color db ?
red_max dw ?
green_max dw ?
blue_max dw ?
red_shift db ?
green_shift db ?
blue_shift db ?
padding rb 3
ends
 
struct framebuffer
width dw ?
height dw ?
pixelformat pixel_format
name_length dd ?
name rb 256
ends
/programs/network/vncc/thread.inc
0,0 → 1,239
 
thread_start:
 
DEBUGF 1, 'I am the thread!\n'
 
mcall 40, 1 shl 7
 
; resolve name
push esp ; reserve stack place
invoke getaddrinfo, first, 0, 0, esp
pop esi
; test for error
test eax, eax
jnz exit
 
mov eax, [esi+addrinfo.ai_addr]
mov eax, [eax+sockaddr_in.sin_addr]
mov [sockaddr1.ip], eax
 
; DEBUGF 1, 'Connecting to %u.%u.%u.%u:%u\n', \
; [server_ip]:1, [server_ip+1]:1, \
; [server_ip+2]:1, [server_ip+3]:1, \
; [server_port]:2
 
mcall socket, AF_INET4, SOCK_STREAM, 0
mov [socketnum], eax
mcall connect, [socketnum], sockaddr1, 18
 
call wait_for_data
 
cmp dword [receive_buffer], 'RFB '
jne no_rfb
DEBUGF 1, 'received: %s\n', receive_buffer
mcall send, [socketnum], handshake, 12, 0
DEBUGF 1, 'Sending handshake: protocol version\n'
 
call wait_for_data
 
cmp dword [receive_buffer], 0x00000000
je invalid_security
 
cmp dword [receive_buffer], 0x01000000
je no_security
 
cmp dword [receive_buffer], 0x02000000
je vnc_security
 
jmp exit
 
vnc_security:
mov byte[mode], 1
call red_logon
 
no_security:
mcall send, [socketnum], shared, 1, 0
DEBUGF 1, 'Sending handshake: shared session?\n'
 
mcall 23, 100*TIMEOUT
 
call wait_for_data ; now the server should send init message
 
DEBUGF 1, 'Serverinit: bpp: %u depth: %u bigendian: %u truecolor: %u\n', \
[receive_buffer+framebuffer.pixelformat.bpp]:1, \
[receive_buffer+framebuffer.pixelformat.depth]:1, \
[receive_buffer+framebuffer.pixelformat.big_endian]:1, \
[receive_buffer+framebuffer.pixelformat.true_color]:1
 
mov eax, dword [receive_buffer]
mov dword [fbur.width], eax
bswap eax
mov dword [screen], eax
 
mcall send, [socketnum], pixel_format8, 20, 0
DEBUGF 1, 'Sending pixel format\n'
call read_data
 
; eth.write_tcp [socket],8,encodings
; DEBUGF 1,'Sending encoding info\n'
; call read_data
 
mov byte [thread_ready], 1
 
request_rfb:
mov [fbur.inc], 2
mcall send, [socketnum], fbur, 10, 0
 
thread_loop:
mcall 23, 100
 
call read_data ; Read the data into the buffer
 
; cmp eax, 2
; jb mainloop
 
DEBUGF 1,'Data received, %u bytes\n', eax
 
cmp byte [receive_buffer],0
je framebufferupdate
 
cmp byte [receive_buffer],1
je setcolourmapentries
 
cmp byte [receive_buffer],2
je bell
 
cmp byte [receive_buffer],3
je servercuttext
 
jmp thread_loop
 
align 4
framebufferupdate:
 
mov ax, word [receive_buffer+2]
xchg al, ah
mov di, ax
DEBUGF 1, 'Framebufferupdate: %u frames\n', di
mov esi, receive_buffer+4
jmp rectangle_loop
 
 
next_rectangle:
call drawbuffer
 
dec di
test di, di
jz request_rfb
 
rectangle_loop:
 
mov edx, [esi]
bswap edx
mov ebx, edx
shr edx, 16
mov [frame.x], dx
mov [frame.y], bx
add esi, 4
mov ecx, [esi]
bswap ecx
mov eax, ecx
shr ecx, 16
mov [frame.width], cx
mov [frame.height], ax
add esi, 4
mov eax, [esi]
add esi, 4
 
mov ebx, esi
sub ebx, receive_buffer+12
DEBUGF 1, 'frame: width=%u height=%u x=%u y=%u offset:%u encoding:',\
[frame.width]:2, [frame.height]:2, [frame.x]:2, [frame.y]:2, ebx
 
cmp eax, 0
je encoding_raw
; cmp eax, 1
; je encoding_copyrect
cmp eax, 2
je encoding_RRE
cmp eax, 5
je encoding_hextile
cmp eax, 16
je encoding_ZRLE
 
mov ebx, esi
sub ebx, receive_buffer+8
DEBUGF 1, '\nunknown encoding: %u (offset %u)\n', eax, ebx
jmp bell
jmp thread_loop
 
encoding_RRE:
 
DEBUGF 1, 'RRE\n'
 
jmp next_rectangle
 
encoding_hextile:
 
DEBUGF 1, 'hextile\n'
 
jmp next_rectangle
 
encoding_ZRLE:
 
DEBUGF 1, 'ZRLE\n'
 
jmp next_rectangle
 
setcolourmapentries:
 
DEBUGF 1, 'Server sent SetColourMapEntries message\n'
 
jmp thread_loop
 
 
bell:
mcall 55, 55, , , beep
 
jmp thread_loop
 
 
servercuttext:
 
DEBUGF 1, 'Server cut text\n'
 
jmp thread_loop
 
 
read_data:
 
mov [datapointer], receive_buffer
.loop:
mcall 23, 100*TIMEOUT
mcall recv, [socketnum], [datapointer], 4096, 0
cmp eax, -1
je .done
 
add [datapointer], eax
 
cmp eax, 4096
je .loop
 
.done:
mov eax, [datapointer]
sub eax, receive_buffer
ret
 
 
 
wait_for_data:
 
mcall 23, 500
mcall recv, [socketnum], receive_buffer, 4096, 0
cmp eax, -1
je wait_for_data
test eax, eax
jz wait_for_data
 
ret
 
/programs/network/vncc/vncc.asm
0,0 → 1,283
;
;
; VNC Client for kolibrios by hidnplayr
;
; hidnplayr@gmail.com
;
 
format binary as ""
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image
dd IM_END ; memory for app
dd IM_END ; esp
dd 0x0 , 0x0 ; I_Param , I_Path
 
__DEBUG__ equ 1
__DEBUG_LEVEL__ equ 1
 
STRLEN = 64 ; password and server max length
xpos = 4 ; coordinates of image
ypos = 22 ;
 
TIMEOUT = 5 ; timeout in seconds
 
include '../macros.inc'
include '../debug-fdo.inc'
include '../proc32.inc'
include '../dll.inc'
include '../struct.inc'
include '../network.inc'
 
include 'structs.inc'
include 'logon.inc'
include 'raw.inc'
include 'thread.inc'
 
START:
 
mcall 68, 11 ; init heap
 
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
 
call red_logon
 
mcall 40, 0 ; no events
mcall 67, 0, 0, 0, 0 ; resize the window (hide it)
mcall 51, 1, thread_start, thread_stack
 
DEBUGF 1,'Thread created: %u\n', eax
 
@@:
mcall 5, 10
cmp byte [thread_ready], 0
je @r
 
mcall 40, 100111b ; mouse, button, key, redraw
 
 
mov edx, dword [screen]
movzx esi, dx
shr edx, 16
add edx, 2*xpos
add esi, ypos+xpos
mcall 67, 10, 10 ; resize the window
 
mainloop:
mcall 23, 50 ; wait for event, 0,5s timeout
 
dec eax
jz redraw
 
dec eax
jz key
 
dec eax
jz button
 
sub eax, 3
jz mouse
 
jmp mainloop
 
key:
 
DEBUGF 1,'Sending key event\n'
 
mcall 2
mov byte [keyevent.key+3], ah
 
mcall send, [socketnum], keyevent, 8, 0
jmp mainloop
 
mouse:
 
DEBUGF 1,'Sending mouse event\n'
 
mcall 37, 1 ; get mouse pos
sub eax, xpos shl 16 + ypos
bswap eax
mov [pointerevent.x], ax
shr eax, 16
mov [pointerevent.y], ax
 
mcall 37, 2 ; get mouse buttons
test al, 00000010b ; test if right button was pressed (bit 1 in kolibri)
jz @f
add al, 00000010b ; in RFB protocol it is bit 2, so if we add bit 2 again, we'll get bit 3 and bit 1 will remain the same
@@:
mov [pointerevent.mask],al
 
mcall send, [socketnum], pointerevent, 6, 0
jmp mainloop
 
redraw:
 
DEBUGF 1,'Drawing window\n'
 
mcall 12, 1
 
mov ebx, dword[screen]
movzx ecx, bx
shr ebx, 16
mov edx, 0x74ffffff
mov edi, name
mcall 0 ; draw window
 
call drawbuffer
 
mcall 12, 2
 
jmp mainloop
 
drawbuffer:
 
mcall 7, framebuffer_data, dword[screen], 0
ret
 
 
button:
mcall 17 ; get id
 
exit:
DEBUGF 1, 'Closing time!\n'
mcall close, [socketnum]
mcall -1
 
no_rfb:
DEBUGF 1, 'This is no vnc server!\n'
jmp exit
 
invalid_security:
DEBUGF 1, 'Security error: %s\n', receive_buffer+5
jmp exit
 
 
; DATA AREA
 
include_debug_strings ; ALWAYS present in data section
 
handshake db 'RFB 003.003', 10
shared db 0
beep db 0x85,0x25,0x85,0x40,0
 
pixel_format32 db 0 ; setPixelformat
rb 3 ; padding
.bpp db 32 ; bits per pixel
.depth db 32 ; depth
.big_endian db 0 ; big-endian flag
.true_color db 1 ; true-colour flag
.red_max db 0,255 ; red-max
.green_max db 0,255 ; green-max
.blue_max db 0,255 ; blue-max
.red_shif db 0 ; red-shift
.green_shift db 8 ; green-shift
.blue_shift db 16 ; blue-shift
rb 3 ; padding
 
pixel_format16 db 0 ; setPixelformat
rb 3 ; padding
.bpp db 16 ; bits per pixel
.depth db 15 ; depth
.big_endian db 0 ; big-endian flag
.true_color db 1 ; true-colour flag
.red_max db 0,31 ; red-max
.green_max db 0,31 ; green-max
.blue_max db 0,31 ; blue-max
.red_shif db 0 ; red-shift
.green_shift db 5 ; green-shift
.blue_shift db 10 ; blue-shift
rb 3 ; padding
 
pixel_format8 db 0 ; setPixelformat
rb 3 ; padding
.bpp db 8 ; bits per pixel
.depth db 6 ; depth
.big_endian db 0 ; big-endian flag
.true_color db 1 ; true-colour flag
.red_max db 0,3 ; red-max
.green_max db 0,3 ; green-max
.blue_max db 0,3 ; blue-max
.red_shif db 0 ; red-shift
.green_shift db 2 ; green-shift
.blue_shift db 4 ; blue-shift
rb 3 ; padding
 
encodings db 2 ; setEncodings
rb 1 ; padding
db 1,0 ; number of encodings
db 0,0,0,0 ; raw encoding (DWORD, Big endian order)
db 1,0,0,0 ; Copyrect encoding
 
fbur db 3 ; frame buffer update request
.inc db 0 ; incremental
.x dw 0
.y dw 0
.width dw 0
.height dw 0
 
keyevent db 4 ; keyevent
.down db 0 ; down-flag
dw 0 ; padding
.key dd 0 ; key
 
pointerevent db 5 ; pointerevent
.mask db 0 ; button-mask
.x dw 0 ; x-position
.y dw 0 ; y-position
 
 
sockaddr1:
dw AF_INET4
.port dw 0x0c17 ; 5900
.ip dd 0
rb 10
 
thread_ready db 0
; import
align 4
@IMPORT:
 
library network, 'network.obj'
import network, \
getaddrinfo, 'getaddrinfo', \
freeaddrinfo, 'freeaddrinfo', \
inet_ntoa, 'inet_ntoa'
 
name db 'VNC client', 0
 
I_END:
 
socketnum dd ?
datapointer dd ?
 
frame:
.width dw ?
.height dw ?
.x dw ?
.y dw ?
 
screen:
.height dw ?
.width dw ?
 
receive_buffer rb 5*1024*1024 ; 5 mb buffer for received data (incoming frbupdate etc)
framebuffer_data rb 1024*768*3 ; framebuffer
 
 
rb 0x1000
thread_stack:
 
rb 0x1000
IM_END:
 
 
/programs/network/vncc
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network/zeroconf/trunk/zeroconf.asm
File deleted
/programs/network/zeroconf/trunk/debug-fdo.inc
File deleted
/programs/network/zeroconf/trunk/build.bat
File deleted
\ No newline at end of file
/programs/network/zeroconf/trunk/dhcp.inc
File deleted
/programs/network/zeroconf/trunk/ETH.INC
File deleted
/programs/network/zeroconf/trunk/zeroconf.ini
File deleted
\ No newline at end of file
/programs/network/zeroconf/trunk
Property changes:
Deleted: tsvn:logminsize
-5
\ No newline at end of property
/programs/network/zeroconf/dhcp.inc
0,0 → 1,263
;Name Number Length Meaning
 
dhcp_pad_option equ 0 ; 0 None
dhcp_end_option equ 255 ; 0 None
dhcp_subnet_mask equ 1 ; 4 Subnet Mask Value
dhcp_time_offset equ 2 ; 4 Time Offset in Seconds from UTC
dhcp_router equ 3 ; N×4 Router addresses
dhcp_time_server equ 4 ; N×4 Timeserver addresses
dhcp_name_server equ 5 ; N×4 IEN-116 Server addresses
dhcp_domain_server equ 6 ; N×4 DNS Server addresses
dhcp_log_server equ 7 ; N×4 Logging Server addresses
dhcp_quotes_server equ 8 ; N×4 Quotes Server addresses
dhcp_lpr_server equ 9 ; N×4 Printer Server addresses
dhcp_impress_server equ 10 ; N×4 Impress Server addresses
dhcp_rlp_server equ 11 ; N×4 N RLP Server addresses
dhcp_hostname equ 12 ; N Hostname string
dhcp_boot_file_size equ 13 ; 2 Size of boot file in 512-octet blocks
dhcp_merit_dump_file equ 14 ; N Client to dump and name the file to dump it to
dhcp_domain_name equ 15 ; N The DNS domain name of the client
dhcp_swap_server equ 16 ; 4 Swap Server address
dhcp_root_path equ 17 ; N Path name for root disk
dhcp_extension_file equ 18 ; N Path name for more BOOTP info
 
;IP Layer Parameters per Host
 
dhcp_forward equ 19 ; 1 Enable/Disable IP Forwarding
dhcp_srcrte equ 20 ; 1 Enable/Disable Non-Local Source Routing
dhcp_policy equ 21 ; N×8 Non-Local Source Routing Policy Filters
dhcp_mag_dg_assembly equ 22 ; 2 Max Datagram Reassembly Size
dhcp_default_ip_tll equ 23 ; 1 Default IP Time to Live
dhcp_mtu_timeout equ 24 ; 4 Path MTU Aging Timeout
dhcp_mtu_plateau equ 25 ; N×2 Path MTU Plateau Table
 
;IP Layer Parameters per Interface
 
dhcp_mtu_interface equ 26 ; 2 Interface MTU Size
dhcp_mtu_subnet equ 27 ; 1 All Subnets are Local
dhcp_broadcast_address equ 28 ; 4 Broadcast Address
dhcp_mask_discovery equ 29 ; 1 Perform Mask Discovery
dhcp_mask_supplier equ 30 ; 1 Provide Mask to Others
dhcp_router_discovery equ 31 ; 1 Perform Router Discovery
dhcp_router_request equ 32 ; 4 Router Solicitation Address
dhcp_static_route equ 33 ; N×8 Static Routing Table
 
;Link Layer Parameters per Interface
 
dhcp_trailers equ 34 ; 1 Trailer Encapsulation
dhcp_arp_timeout equ 35 ; 4 ARP Cache Timeout
dhcp_ethernet equ 36 ; 1 Ethernet Encapsulation
 
;TCP Parameters
 
dhcp_default_tcp_tll equ 37 ; 1 Default TCP Time to Live
dhcp_keepalive_time equ 38 ; 4 TCP Keepalive Interval
dhcp_keepalive_data equ 39 ; 1 TCP Keepalive Garbage
 
;Application and Service Parameters
 
dhcp_nis_domain equ 40 ; N NIS Domain Name
dhcp_nis_servers equ 41 ; N×4 NIS Server Addresses
dhcp_ntp_servers equ 42 ; N×4 NTP Server Addresses
dhcp_vendor_specific equ 43 ; N Vendor Specific Information
dhcp_netbios_name_srv equ 44 ; N×4 NETBIOS Name Servers
dhcp_netbios_dist_srv equ 45 ; N×4 NETBIOS Datagram Distribution
dhcp_netbios_node_type equ 46 ; 1 NETBIOS Node Type
dhcp_netbios_scope equ 47 ; N NETBIOS Scope
dhcp_x_window_font equ 48 ; N×4 X Window Font Server
dhcp_x_window_manager equ 49 ; N×4 X Window Display Manager
dhcp_nis_domain_name equ 64 ; N NIS+ v3 Client Domain Name
dhcp_nis_server_addr equ 65 ; N×4 NIS+ v3 Server Addresses
dhcp_home_agent_addrs equ 68 ; N×4 Mobile IP Home Agent Addresses
dhcp_smtp_server equ 69 ; N×4 Simple Mail Server Addresses
dhcp_pop3_server equ 70 ; N×4 Post Office Server Addresses
dhcp_nntp_server equ 71 ; N×4 Network News Server Addresses
dhcp_www_server equ 72 ; N×4 WWW Server Addresses
dhcp_finger_server equ 73 ; N×4 Finger Server Addresses
dhcp_irc_server equ 74 ; N×4 Chat Server Addresses
dhcp_streettalk_server equ 75 ; N×4 StreetTalk Server Addresses
dhcp_stda_server equ 76 ; N×4 ST Directory Assist. Addresses
 
;DHCP Extensions
 
dhcp_address_request equ 50 ; 4 Requested IP Address
dhcp_address_time equ 51 ; 4 IP Address Lease Time
dhcp_option_overload equ 52 ; 1 Overload "sname" or "file"
dhcp_msg_type equ 53 ; 1 DHCP Message Type
dhcp_dhcp_server_id equ 54 ; 4 DHCP Server Identification
dhcp_parameter_list equ 55 ; N Parameter Request List
dhcp_dhcp_message equ 56 ; N DHCP Error Message
dhcp_dhcp_max_msg_size equ 57 ; 2 DHCP Maximum Message Size
dhcp_renewal_time equ 58 ; 4 DHCP Renewal (T1) Time
dhcp_rebinding_time equ 59 ; 4 DHCP Rebinding (T2) Time
dhcp_class_id equ 60 ; N Vendor Class Identifier
dhcp_client_id equ 61 ; N Client Identifier
dhcp_server_name equ 66 ; N TFTP Server Name
dhcp_bootfile_name equ 67 ; N Boot File Name
 
;Newer extensions
 
dhcp_netware_ip_domain equ 62 ; N Netware/IP Domain Name
dhcp_netware_ip_option equ 63 ; N Netware/IP sub Options
dhcp_user_class equ 77 ; N User Class Information
dhcp_directory_agent equ 78 ; N directory agent information
dhcp_service_scope equ 79 ; N service location agent scope
dhcp_rapid_commit equ 80 ; 0 Rapid Commit
dhcp_client_fqdn equ 81 ; N Fully Qualified Domain Name
dhcp_relay_agent_info equ 82 ; N Relay Agent Information, RFC 3046
dhcp_isns equ 83 ; N Internet Storage Name Service
; 84 REMOVED/Unassigned
dhcp_nds_servers equ 85 ; N Novell Directory Services
dhcp_nds_tree_name equ 86 ; N Novell Directory Services
dhcp_nds_conext equ 87 ; N Novell Directory Services
dhcp_bcmcs equ 88 ; Controller Domain Name list
dhcp_bcmcs equ 89 ; Controller IPv4 address option
dhcp_authentication equ 90 ; N Authentication
; 91 REMOVED/Unassigned
; 92 REMOVED/Unassigned
dhcp_client_system equ 93 ; N Client System Architecture
dhcp_client_ndi equ 94 ; N Client Network Device Interface
dhcp_ldap equ 95 ; N Lightweight Directory Access Protocol
; 96 REMOVED/Unassigned
dhcp_uuid_guid equ 97 ; N UUID/GUID-based Client Identifier
dchp_user_auth equ 98 ; N Open Group's User Authentication
; 99 REMOVED/Unassigned
; 100 REMOVED/Unassigned
; 101 REMOVED/Unassigned
; 102 REMOVED/Unassigned
; 103 REMOVED/Unassigned
; 104 REMOVED/Unassigned
; 105 REMOVED/Unassigned
; 106 REMOVED/Unassigned
; 107 REMOVED/Unassigned
; 108 REMOVED/Unassigned
; 109 REMOVED/Unassigned
; 110 REMOVED/Unassigned
; 111 REMOVED/Unassigned
dhcp_netinfo_address equ 112 ; N NetInfo Parent Server Address
dhcp_netinfo_tag equ 113 ; N NetInfo Parent Server Tag
dhcp_url equ 114 ; N URL
; 115 REMOVED/Unassigned
dhcp_auto_config equ 116 ; N DHCP Auto-Configuration
dhcp_ns_search equ 117 ; N Name Service Search
dhcp_subnet_selection equ 118 ; 4 Subnet Selection Option
dhcp_domain_search equ 119 ; N DNS domain search list
dhcp_sip_servers equ 120 ; N SIP Servers DHCP Option
dhcp_cl_static_route equ 121 ; N Classless Static Route Option
dhcp_ccc equ 122 ; N CableLabs Client Configuration
dhcp_geoconf equ 123 ; 16 GeoConf Option
dhcp_v_i_vendor_class equ 124 ; Vendor-Identifying Vendor Class
dhcp_v_i_vendor_spec equ 125 ; Vendor-Identifying Vendor-Specific
; 126 REMOVED/Unassigned
; 127 REMOVED/Unassigned
dhcp_pxe equ 128 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_etherboot_sign equ 128 ; Etherboot signature. 6 bytes: E4:45:74:68:00:00
dhcp_docsis equ 128 ; DOCSIS "full security" server IP address
dhcp_tftp_server_ip equ 128 ; TFTP Server IP address (for IP Phone software load)
dhcp_pxe equ 129 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_kernel_options equ 129 ; Kernel options. Variable length string
dhcp_call_server_ip equ 129 ; Call Server IP address
dhcp_pxe equ 130 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_ethernet_interface equ 130 ; Ethernet interface. Variable length string.
dhcp_siscrimination equ 130 ; Discrimination string (to identify vendor)
dhcp_pxe equ 131 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_remote_stat_server equ 131 ; Remote statistics server IP address
dhcp_pxe equ 132 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_802.1p equ 132 ; 802.1P VLAN ID
dhcp_pxe equ 133 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_802.1q equ 133 ; 802.1Q L2 Priority
dhcp_pxe equ 134 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_diffserv equ 134 ; Diffserv Code Point
dhcp_pxe equ 135 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_http_proxy_psa equ 135 ; HTTP Proxy for phone-specific applications
; 136 REMOVED/Unassigned
; 137 REMOVED/Unassigned
; 138 REMOVED/Unassigned
; 139 REMOVED/Unassigned
; 140 REMOVED/Unassigned
; 141 REMOVED/Unassigned
; 142 REMOVED/Unassigned
; 143 REMOVED/Unassigned
; 144 REMOVED/Unassigned
; 145 REMOVED/Unassigned
; 146 REMOVED/Unassigned
; 147 REMOVED/Unassigned
; 148 REMOVED/Unassigned
; 149 REMOVED/Unassigned
dhcp_tftp_server_addr equ 150 ; TFTP server address (Tentatively Assigned - 23 June 2005)
dhcp_etherboot equ 150 ; Etherboot
dhcp_grub_conf_path equ 150 ; GRUB configuration path name
; 151 REMOVED/Unassigned
; 152 REMOVED/Unassigned
; 153 REMOVED/Unassigned
; 154 REMOVED/Unassigned
; 155 REMOVED/Unassigned
; 156 REMOVED/Unassigned
; 157 REMOVED/Unassigned
; 158 REMOVED/Unassigned
; 159 REMOVED/Unassigned
; 160 REMOVED/Unassigned
; 161 REMOVED/Unassigned
; 162 REMOVED/Unassigned
; 163 REMOVED/Unassigned
; 164 REMOVED/Unassigned
; 165 REMOVED/Unassigned
; 166 REMOVED/Unassigned
; 167 REMOVED/Unassigned
; 168 REMOVED/Unassigned
; 169 REMOVED/Unassigned
; 170 REMOVED/Unassigned
; 171 REMOVED/Unassigned
; 172 REMOVED/Unassigned
; 173 REMOVED/Unassigned
; 174 REMOVED/Unassigned
dhcp_etherboot equ 175 ; Etherboot (Tentatively Assigned - 23 June 2005)
dhcp_ip_telephone equ 176 ; IP Telephone (Tentatively Assigned - 23 June 2005)
dhcp_etherboot equ 177 ; Etherboot (Tentatively Assigned - 23 June 2005)
dhcp_packetcable equ 177 ; PacketCable and CableHome (replaced by 122)
; 178 REMOVED/Unassigned
; 179 REMOVED/Unassigned
; 180 REMOVED/Unassigned
; 181 REMOVED/Unassigned
; 182 REMOVED/Unassigned
; 183 REMOVED/Unassigned
; 184 REMOVED/Unassigned
; 185 REMOVED/Unassigned
; 186 REMOVED/Unassigned
; 187 REMOVED/Unassigned
; 188 REMOVED/Unassigned
; 189 REMOVED/Unassigned
; 190 REMOVED/Unassigned
; 191 REMOVED/Unassigned
; 192 REMOVED/Unassigned
; 193 REMOVED/Unassigned
; 194 REMOVED/Unassigned
; 195 REMOVED/Unassigned
; 196 REMOVED/Unassigned
; 197 REMOVED/Unassigned
; 198 REMOVED/Unassigned
; 199 REMOVED/Unassigned
; 200 REMOVED/Unassigned
; 201 REMOVED/Unassigned
; 202 REMOVED/Unassigned
; 203 REMOVED/Unassigned
; 204 REMOVED/Unassigned
; 205 REMOVED/Unassigned
; 206 REMOVED/Unassigned
; 207 REMOVED/Unassigned
dhcp_pxelinux.magic equ 208 ; pxelinux.magic (string) = F1:00:74:7E (241.0.116.126) (Tentatively Assigned - 23 June 2005)
dhcp_pxelinux.conffile equ 209 ; pxelinux.configfile (text) (Tentatively Assigned - 23 June 2005)
dhcp_pxelinux.path equ 210 ; pxelinux.pathprefix (text) (Tentatively Assigned - 23 June 2005)
dhcp_pxelinux.reboot equ 211 ; pxelinux.reboottime (unsigned integer 32 bits) (Tentatively Assigned - 23 June 2005)
; 212 REMOVED/Unassigned
; 213 REMOVED/Unassigned
; 214 REMOVED/Unassigned
; 215 REMOVED/Unassigned
; 216 REMOVED/Unassigned
; 217 REMOVED/Unassigned
; 218 REMOVED/Unassigned
; 219 REMOVED/Unassigned
dhcp_subnet_aloc equ 220 ; Subnet Allocation Option (Tentatively Assigned - 23 June 2005)
dhcp_virtual_subnet equ 221 ; Virtual Subnet Selection Option (Tentatively Assigned - 23 June 2005)
; 222 REMOVED/Unassigned
; 223 REMOVED/Unassigned
/programs/network/zeroconf/zeroconf.asm
0,0 → 1,620
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; zeroconfig.asm - Zeroconfig service for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; Some code contributed by Derpenguin ;;
;; ;;
;; DHCP code is based on that by Mike Hibbet ;;
; (DHCP client for menuetos) ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format binary as ""
 
use32
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd IM_END ; size of image
dd (I_END+0x100) ; memory for app
dd (I_END+0x100) ; esp
dd 0, 0 ; I_Param, I_Path
 
; CONFIGURATION
 
TIMEOUT = 60 ; in seconds
BUFFER = 1024 ; in bytes
__DEBUG__ = 1 ; enable/disable
__DEBUG_LEVEL__ = 1 ; 1 = all, 2 = errors
 
; CONFIGURATION FOR LINK-LOCAL
 
PROBE_WAIT = 1 ; second (initial random delay)
PROBE_MIN = 1 ; second (minimum delay till repeated probe)
PROBE_MAX = 2 ; seconds (maximum delay till repeated probe)
PROBE_NUM = 3 ; (number of probe packets)
 
ANNOUNCE_NUM = 2 ; (number of announcement packets)
ANNOUNCE_INTERVAL = 2 ; seconds (time between announcement packets)
ANNOUNCE_WAIT = 2 ; seconds (delay before announcing)
 
MAX_CONFLICTS = 10 ; (max conflicts before rate limiting)
 
RATE_LIMIT_INTERVAL = 60 ; seconds (delay between successive attempts)
 
DEFEND_INTERVAL = 10 ; seconds (min. wait between defensive ARPs)
 
 
include '../proc32.inc'
include '../macros.inc'
include '../debug-fdo.inc'
include '../network.inc'
include 'dhcp.inc'
include '../dll.inc'
 
 
Ip2dword:
push edx
 
; This code validates if the query is an IP containing 4 numbers and 3 dots
 
xor al, al ; make al (dot count) zero
 
@@:
cmp byte[edx],'0' ; check if this byte is a number, if not jump to no_IP
jl no_IP ;
cmp byte[edx],'9' ;
jg no_IP ;
 
inc edx ; the byte was a number, so lets check the next byte
 
cmp byte[edx],0 ; is this byte zero? (have we reached end of query?)
jz @f ; jump to next @@ then
cmp byte[edx],':'
jz @f
 
cmp byte[edx],'.' ; is this byte a dot?
jne @r ; if not, jump to previous @@
 
inc al ; the byte was a dot so increment al(dot count)
inc edx ; next byte
jmp @r ; lets check for numbers again (jump to previous @@)
 
@@: ; we reach this when end of query reached
cmp al,3 ; check if there where 3 dots
jnz no_IP ; if not, jump to no_IP
 
; The following code will convert this IP into a dword and output it in eax
; If there is also a port number specified, this will be returned in ebx, otherwise ebx is -1
 
pop esi ; edx (query address) was pushed onto stack and is now popped in esi
 
xor edx, edx ; result
xor eax, eax ; current character
xor ebx, ebx ; current byte
 
.outer_loop:
shl edx, 8
add edx, ebx
xor ebx, ebx
.inner_loop:
lodsb
test eax, eax
jz .finish
cmp al, '.'
jz .outer_loop
sub eax, '0'
imul ebx, 10
add ebx, eax
jmp .inner_loop
.finish:
shl edx, 8
add edx, ebx
 
bswap edx ; we want little endian order
 
ret
 
no_IP:
pop edx
xor edx, edx
 
ret
 
 
 
 
 
 
START:
mcall 40, EVM_STACK2
 
DEBUGF 1,">Zero-config service loaded\n"
 
.wait:
mcall 76, API_ETH + 4 ; get MAC of ethernet interface 0
cmp eax, -1
jne .start
 
mcall 10
jmp .wait
 
.start:
mov word[MAC], bx
mov dword[MAC+2], eax
DEBUGF 1,"->MAC: %x-%x-%x-%x-%x-%x\n", [MAC+0]:2, [MAC+1]:2, [MAC+2]:2, [MAC+3]:2, [MAC+4]:2, [MAC+5]:2
 
mcall 40, EVM_STACK
 
mcall 68, 11
 
stdcall dll.Load,@IMPORT
or eax, eax
jnz try_dhcp
 
invoke ini.get_str, path, str_ipconfig, str_type, inibuf, 16, 0
 
cmp dword[inibuf], 'stat'
jne try_dhcp
 
invoke ini.get_str, path, str_ipconfig, str_ip, inibuf, 16, 0
mov edx, inibuf
call Ip2dword
mcall 76, API_IPv4 + 3, edx
 
invoke ini.get_str, path, str_ipconfig, str_gateway, inibuf, 16, 0
mov edx, inibuf
call Ip2dword
mcall 76, API_IPv4 + 9, edx
 
invoke ini.get_str, path, str_ipconfig, str_dns, inibuf, 16, 0
mov edx, inibuf
call Ip2dword
mcall 76, API_IPv4 + 5, edx
 
invoke ini.get_str, path, str_ipconfig, str_subnet, inibuf, 16, 0
mov edx, inibuf
call Ip2dword
mcall 76, API_IPv4 + 7, edx
 
 
mcall -1
 
 
try_dhcp:
 
DEBUGF 1,"->Trying DHCP\n"
 
mcall 75, 0, AF_INET4, SOCK_DGRAM, 0 ; open socket (parameters: domain, type, reserved)
cmp eax, -1
je error
mov [socketNum], eax
 
DEBUGF 1,"->Socket %x opened\n", eax
 
mcall 75, 2, [socketNum], sockaddr1, 18 ; bind socket to local port 68
cmp eax, -1
je error
 
DEBUGF 1,"->Socket Bound to local port 68\n"
 
mcall 75, 4, [socketNum], sockaddr2, 18 ; connect to 255.255.255.255 on port 67
cmp eax, -1
je error
 
DEBUGF 1,"->Connected to 255.255.255.255 on port 67\n"
 
mov [dhcpMsgType], 0x01 ; DHCP discover
mov [dhcpLease], esi ; esi is still -1 (-1 = forever)
 
mcall 26, 9 ; Get system time
imul eax, 100
mov [currTime], eax
 
build_request: ; Creates a DHCP request packet.
 
DEBUGF 1,"->Building request\n"
 
stdcall mem.Alloc, BUFFER
mov [dhcpMsg], eax
test eax, eax
jz dhcp_error
 
;;; todo: skip this bullcrap
 
mov edi, eax
mov ecx, BUFFER
xor eax, eax
rep stosb
 
;; todo: put this in a buffer instead of writing bytes and words!
 
mov edx, [dhcpMsg]
 
; Boot protocol legacy
mov [edx], byte 0x01 ; Boot request
mov [edx+1], byte 0x01 ; Ethernet
mov [edx+2], byte 0x06 ; Ethernet h/w len
mov [edx+4], dword 0x11223344 ; xid ;;;;;;;
mov eax, [currTime]
mov [edx+8], eax ; secs, our uptime
mov [edx+10], byte 0x80 ; broadcast flag set
mov eax, dword [MAC] ; first 4 bytes of MAC
mov [edx+28],dword eax
mov ax, word [MAC+4] ; last 2 bytes of MAC
mov [edx+32],word ax
 
; DHCP extension
mov [edx+236], dword 0x63538263 ; magic cookie
mov [edx+240], word 0x0135 ; option DHCP msg type
mov al, [dhcpMsgType]
mov [edx+240+2], al
mov [edx+240+3], word 0x0433 ; option Lease time = infinity
mov eax, [dhcpLease]
mov [edx+240+5], eax
mov [edx+240+9], word 0x0432 ; option requested IP address
mov eax, [dhcp.ip]
mov [edx+240+11], eax
mov [edx+240+15], word 0x0437 ; option request list
mov [edx+240+17], dword 0x0f060301
 
cmp [dhcpMsgType], byte 0x01 ; Check which msg we are sending
jne request_options
 
mov [edx+240+21], byte 0xff ; "Discover" options
 
mov [dhcpMsgLen], dword 262 ; end of options marker
jmp send_dhcpmsg
 
request_options:
mov [edx+240+21], word 0x0436 ; server IP
mov eax, [dhcpServerIP]
mov [edx+240+23], eax
 
mov [edx+240+27], byte 0xff ; end of options marker
 
mov [dhcpMsgLen], dword 268
 
send_dhcpmsg:
mcall 75, 6, [socketNum], [dhcpMsg], [dhcpMsgLen] ; write to socket ( send broadcast request )
 
mov eax, [dhcpMsg] ; Setup the DHCP buffer to receive response
mov [dhcpMsgLen], eax ; Used as a pointer to the data
 
mcall 23, TIMEOUT*10 ; wait for data
 
read_data: ; we have data - this will be the response
mcall 75, 7, [socketNum], [dhcpMsg], BUFFER ; read data from socket
 
DEBUGF 1,"->%d bytes received\n", eax
 
cmp eax, -1
je dhcp_error
 
mov [dhcpMsgLen], eax
 
; depending on which msg we sent, handle the response
; accordingly.
; If the response is to a dhcp discover, then:
; 1) If response is DHCP OFFER then
; 1.1) record server IP, lease time & IP address.
; 1.2) send a request packet
; If the response is to a dhcp request, then:
; 1) If the response is DHCP ACK then
; 1.1) extract the DNS & subnet fields. Set them in the stack
 
cmp [dhcpMsgType], 0x01 ; did we send a discover?
je discover
 
cmp [dhcpMsgType], 0x03 ; did we send a request?
je request
 
call dhcp_end ; we should never reach here ;)
jmp exit
 
discover:
call parse_response
 
cmp [dhcpMsgType], 0x02 ; Was the response an offer?
je send_request
 
call dhcp_end
jmp link_local
 
send_request:
mov [dhcpMsgType], 0x03 ; make it a request
jmp build_request
 
request:
call parse_response
 
cmp [dhcpMsgType], 0x05 ; Was the response an ACK? It should be
jne read_data ; NO - read next packets
 
call dhcp_end
 
mcall 76, API_IPv4 + 3, [dhcp.ip] ; ip
mcall 76, API_IPv4 + 5, [dhcp.dns] ; dns
mcall 76, API_IPv4 + 7, [dhcp.subnet] ; subnet
mcall 76, API_IPv4 + 9, [dhcp.gateway] ; gateway
 
jmp exit
 
dhcp_end:
mcall close, [socketNum]
stdcall mem.Free, [dhcpMsg]
 
ret
 
;***************************************************************************
; Function
; parseResponse
;
; Description
; extracts the fields ( client IP address and options ) from
; a DHCP response
; The values go into
; dhcpMsgType,dhcpLease,dhcpClientIP,dhcpServerIP,
; dhcpDNSIP, dhcpSubnet
; The message is stored in dhcpMsg
;
;***************************************************************************
parse_response:
 
DEBUGF 1,"Data received, parsing response\n"
mov edx, [dhcpMsg]
 
push dword [edx+16]
pop [dhcp.ip]
DEBUGF 1,"Client: %u.%u.%u.%u\n", [edx+16]:1, [edx+17]:1, [edx+18]:1, [edx+19]:1
 
; TODO: check if there really are options
 
mov al, 240 ; Point to first option
movzx ecx, al
 
.next_option:
add edx, ecx
 
mov al, [edx] ; get message identifier
 
cmp al, 0xff ; End of options?
je .done
 
cmp al, 0
je .pad
 
; TODO: check if we still are inside the buffer
 
inc edx
movzx ecx, byte [edx] ; get data length
inc edx ; point to data
 
cmp al, dhcp_msg_type ; Msg type is a single byte option
je .msgtype
 
cmp al, dhcp_dhcp_server_id
je .server
 
cmp al, dhcp_address_time
je .lease
 
cmp al, dhcp_subnet_mask
je .subnet
 
cmp al, dhcp_router
je .router
 
cmp al, dhcp_domain_server
je .dns
 
DEBUGF 1,"Unsupported DHCP option: %u\n", al
 
jmp .next_option
 
.pad:
xor ecx, ecx
inc ecx
jmp .next_option
 
.msgtype:
mov al, [edx]
mov [dhcpMsgType], al
 
DEBUGF 1,"DHCP Msg type: %u\n", al
jmp .next_option ; Get next option
 
.server:
mov eax, [edx]
mov [dhcpServerIP], eax
DEBUGF 1,"Server: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
jmp .next_option
 
.lease:
pusha
mov eax,[edx]
bswap eax
mov [dhcpLease],eax
DEBUGF 1,"lease: %d\n",eax
popa
jmp .next_option
 
.subnet:
push dword [edx]
pop [dhcp.subnet]
DEBUGF 1,"Subnet: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
jmp .next_option
 
.router:
push dword [edx]
pop [dhcp.gateway]
DEBUGF 1,"Gateway: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
jmp .next_option
 
.dns:
push dword [edx]
pop [dhcp.dns]
DEBUGF 1,"DNS: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
jmp .next_option
 
.done:
ret
 
 
 
dhcp_error:
call dhcp_end
 
link_local:
call random
mov cx, ax
shl ecx, 16
mov cx, 0xfea9 ; IP 169.254.0.0 link local net, see RFC3927
mcall 76, API_IPv4 + 3, ecx ; mask is 255.255.0.0
DEBUGF 1,"Link Local IP assinged: 169.254.%u.%u\n", [generator+0]:1, [generator+1]:1
mcall 76, API_IPv4 + 7, 0xffff
mcall 76, API_IPv4 + 9, 0x0
mcall 76, API_IPv4 + 5, 0x0
 
mcall 5, PROBE_WAIT*100
 
xor esi, esi
probe_loop:
call random ; create a pseudo random number in eax (seeded by MAC)
 
cmp al, PROBE_MIN*100 ; check if al is bigger then PROBE_MIN
jae @f ; all ok
add al, (PROBE_MAX-PROBE_MIN)*100 ; al is too small
@@:
 
cmp al, PROBE_MAX*100
jbe @f
sub al, (PROBE_MAX-PROBE_MIN)*100
@@:
 
movzx ebx,al
DEBUGF 1,"Waiting %u0ms\n",ebx
mcall 5
 
DEBUGF 1,"Sending Probe\n"
mcall 76, API_ARP + 6
inc esi
 
cmp esi, PROBE_NUM
jb probe_loop
 
; now we wait further ANNOUNCE_WAIT seconds and send ANNOUNCE_NUM ARP announces. If any other host has assingned
; IP within this time, we should create another adress, that have to be done later
 
DEBUGF 1,"Waiting %us\n", ANNOUNCE_WAIT
mcall 5, ANNOUNCE_WAIT*100
xor esi, esi
announce_loop:
 
DEBUGF 1,"Sending Announce\n"
mcall 76, API_ARP + 6
 
inc esi
cmp esi,ANNOUNCE_NUM
je @f
 
DEBUGF 1,"Waiting %us\n", ANNOUNCE_INTERVAL
mcall 5, ANNOUNCE_INTERVAL*100
jmp announce_loop
@@:
 
 
error:
DEBUGF 1,"Socket error\n"
exit: ; we should, instead of closing, detect ARP conflicts and detect if cable keeps connected ;)
mcall -1
 
 
random: ; Pseudo random actually
 
mov eax, [generator]
add eax, -43ab45b5h
ror eax, 1
bswap eax
xor eax, dword[MAC]
ror eax, 1
xor eax, dword[MAC+2]
mov [generator], eax
 
ret
 
; DATA AREA
 
align 16
@IMPORT:
 
library \
libini,'libini.obj'
 
import libini, \
ini.get_str,'ini_get_str'
 
include_debug_strings
 
str_ip db 'ip', 0
str_subnet db 'subnet', 0
str_gateway db 'gateway', 0
str_dns db 'dns', 0
str_ipconfig db 'ipconfig', 0
str_type db 'type', 0
 
 
sockaddr1:
 
dw AF_INET4
dw 68 shl 8 ; local port
dd 0 ; local IP
 
rb 10
 
 
sockaddr2:
 
dw AF_INET4
dw 67 shl 8 ; destination port
dd -1 ; destination IP
 
rb 10
 
path db '/sys/network.ini'
 
IM_END:
 
inibuf rb 16
 
dhcpMsgType db ?
dhcpLease dd ?
dhcpServerIP dd ?
 
dhcp:
.ip dd ?
.subnet dd ?
.dns dd ?
.gateway dd ?
 
 
dhcpMsgLen dd ?
socketNum dd ?
 
MAC dp ?
 
currTime dd ?
generator dd ?
 
dhcpMsg dd ?
 
I_END:
/programs/network/zeroconf
Property changes:
Deleted: tsvn:logminsize
-5
\ No newline at end of property
/programs/network_old/browser/browser.asm
0,0 → 1,321
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; BROWSER for KolibriOS ;
; ;
; Compile with FASM ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; It's a work in progress but I (esevece) commit it, because if I don't continue developing it someone can continue.
; Please, keep the code clean
 
; The header
use32 ; Tell compiler to use 32 bit instructions
org 0x0 ; the base address of code, always 0x0
db 'MENUET01'
dd 0x01
dd START
dd I_END
dd 0x100000
dd 0x7fff0
dd 0, 0
; The code area
;include 'macros.inc'
START: ; start of execution
call draw_window ; draw the window
; After the window is drawn, it's practical to have the main loop.
; Events are distributed from here.
event_wait:
mov eax, 10 ; function 10 : wait until event
int 0x40 ; event type is returned in eax
cmp eax, 1 ; Event redraw request ?
je redraw ; Expl.: there has been activity on screen and
; parts of the applications has to be redrawn.
cmp eax, 2 ; Event key in buffer ?
je key ; Expl.: User has pressed a key while the
; app is at the top of the window stack.
cmp eax, 3 ; Event button in buffer ?
je button ; Expl.: User has pressed one of the
; applications buttons.
jmp event_wait
; The next section reads the event and processes data.
redraw: ; Redraw event handler
call draw_window ; We call the window_draw function and
jmp event_wait ; jump back to event_wait
key: ; Keypress event handler
mov eax, 2 ; The key is returned in ah. The key must be
int 0x40 ; read and cleared from the system queue.
jmp event_wait ; Just read the key, ignore it and jump to event_wait.
button: ; Buttonpress event handler
mov eax,17 ; The button number defined in window_draw
int 0x40 ; is returned to ah.
cmp ah,1 ; button id=1 ?
jne noclose
mov eax,-1 ; Function -1 : close this program
int 0x40
noclose:
cmp ah, 2 ; call fetch_thread
jne no_fetch_thread
call fetch_thread
jmp event_wait ; This is for ignored events, useful at development
no_fetch_thread:
jmp event_wait
 
; FETCHER
FETCH:
mov ecx, 1000
get_free_port:
inc ecx
mov eax, 53
mov ebx, 9
int 0x40
cmp eax, 0 ; is port used?
jz get_free_port
open_socket:
mov eax, 53
mov ebx, 5
mov edx, 80
mov esi, 0x0417042E ; 46.4.23.4 (kolibrios.org), only for try
mov edi, 1
int 0x40
mov [socket], eax
cmp [socket], -1 ; error?
jne status_socket
ret
status_socket:
mov eax, 53
mov ebx, 6
mov ecx, [socket]
int 0x40
cmp eax, 4 ; connected?
jne status_socket
send_request:
.concat_request:
mov edi, request
mov ebx, 0 ; request_length
mov esi, request_first_line
._first_line:
movsb
inc ebx ; request_length
cmp byte [edi], 0
jne ._first_line
mov esi, request_second_line
._second_line:
movsb
inc ebx ; request_length
cmp byte [edi], 0
jne ._second_line
mov esi, host
._second_line_host:
movsb
inc ebx ; request_length
cmp byte [edi], 0
jne ._second_line_host
mov esi, request_third_line
._third_line:
movsb
inc ebx ; request_length
cmp byte [edi], 0
jne ._third_line
mov [request_length], ebx
.write_to_socket:
mov eax, 53
mov ebx, 7
mov ecx, [socket]
mov edx, [request_length]
mov esi, request
int 0x40
cmp eax, -1 ; error?
je .write_to_socket
.poll_socket:
mov eax, 53
mov ebx, 2
mov ecx, [socket]
int 0x40
cmp eax, 0
jne .read_socket
; only for test purposes
mov eax, 63
mov ebx, 1
mov cl, 's'
int 0x40
.status_socket:
mov eax, 53
mov ebx, 6
mov ecx, [socket]
int 0x40
cmp eax, 4
jne end_of_request
.read_socket:
mov eax, 53
mov ebx, 11
mov ecx, [socket]
mov edx, [buffer]
mov esi, 4096
int 0x40
; only for test purposes
mov eax, 63
mov ebx, 1
mov cl, 'p'
int 0x40
jmp .poll_socket
end_of_request:
.close_socket:
mov eax, 53
mov ebx, 8
mov ecx, [socket]
int 0x40
; only for test purposes
mov eax, 63
mov ebx, 1
mov cl, 'b'
int 0x40
jmp terminate_thread
fetch_thread:
cmp [thread_id], 0
jne terminate_thread
mov eax, 51
mov ebx, 1
mov ecx, FETCH
mov edx, [thread_stack]
int 0x40
jmp event_wait
 
no_new_thread:
ret
 
terminate_thread:
mov eax, 18
mov ebx, 18
mov ecx, [thread_id]
int 0x40
cmp eax, 0
jne terminate_thread
mov [thread_id], 0
ret
thread_stack dd 0x80000
thread_id dd 0x0
 
; *********************************************
; ****** WINDOW DEFINITIONS AND DRAW ********
; *********************************************
;
; The static window parts are drawn in this function. The window canvas can
; be accessed later from any parts of this code (thread) for displaying
; processes or recorded data, for example.
;
; The static parts *must* be placed within the fn 12 , ebx = 1 and ebx = 2.
draw_window:
mov eax, 12 ; function 12: tell os about windowdraw
mov ebx, 1 ; 1, start of draw
int 0x40
mov eax, 0 ; function 0 : define and draw window
mov ebx, 100 * 65536 + 300 ; [x start] *65536 + [x size]
mov ecx, 100 * 65536 + 120 ; [y start] *65536 + [y size]
mov edx, 0x14ffffff ; color of work area RRGGBB
; 0x02000000 = window type 4 (fixed size, skinned window)
mov esi, 0x808899ff ; color of grab bar RRGGBB
; 0x80000000 = color glide
mov edi, title
int 0x40
; Fetch button
mov eax, 8
mov ebx, 25 * 65536 + 128
mov ecx, 88 * 65536 + 20
mov edx, 2
mov esi, 0x6677cc
int 0x40
mov ebx, 25 * 65536 + 35 ; draw info text with function 4
mov ecx, 0x224466
mov edx, text
mov esi, 40
mov eax, 4
.newline: ; text from the DATA AREA
int 0x40
add ebx, 10
add edx, 40
cmp byte[edx], 0
jne .newline
mov eax, 12 ; function 12:tell os about windowdraw
mov ebx, 2 ; 2, end of draw
int 0x40
ret
; *********************************************
; ************* DATA AREA *****************
; *********************************************
;
; Data can be freely mixed with code to any parts of the image.
; Only the header information is required at the beginning of the image.
text db "It look's like you have just compiled "
db "your first program for KolibriOS. "
db " "
db "Congratulations! ", 0
title db "KolibriOS Browser", 0
 
socket dd 0
socket_status dd 0
server_ip db 046,004,023,004
server_port db 0,0
request_first_line db 'GET / HTTP/1.1',0
request_second_line db 13,10,'Host: ',0
request_third_line db 13,10,'Connection: close',13,10,13,10,0
request db 0
request_length dd 0
host db 'kolibrios.org',0
buffer dd 0
I_END:
; The area after I_END is free for use as the application memory,
; just avoid the stack.
;
; Application memory structure, according to the used header, 1 Mb.
;
; 0x00000 - Start of compiled image
; I_END - End of compiled image
;
; + Free for use in the application
;
; 0x7ff00 - Start of stack area
; 0x7fff0 - End of stack area - defined in the header
;
; + Free for use in the application
;
; 0xFFFFF - End of freely useable memory - defined in the header
;
; All of the the areas can be modified within the application with a
; direct reference.
; For example, mov [0x80000],byte 1 moves a byte above the stack area.
/programs/network_old/browser/build.bat
0,0 → 1,6
@erase lang.inc
@echo lang fix en >lang.inc
@fasm browser.asm browser
@kpack browser
@erase lang.inc
@pause
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/programs/network_old/browser/build.sh
0,0 → 1,13
#!/bin/bash
# This script does for linux the same as build.bat for DOS,
# it compiles the KoOS kernel, hopefully ;-)
 
echo "lang fix en"
echo "lang fix en" > lang.inc
fasm -m 16384 browser.asm browser
rm -f lang.inc
exit 0
 
 
 
 
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/programs/network_old/airc/trunk/airc.asm
0,0 → 1,2864
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; IRC CLIENT for KolibriOS ;;
;; ;;
;; License: GPL / See file COPYING for details ;;
;; Copyright 2004 (c) Ville Turjanmaa ;;
;; Copyright 2009 (c) CleverMouse ;;
;; ;;
;; Compile with FASM for Kolibri ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
version equ '0.6'
 
 
;__DEBUG__ equ 1
;__DEBUG_LEVEL__ equ 1
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; required os
dd START ; program start
dd initialized_size ; program image size
dd 0x100000 ; required amount of memory
dd 0x100000
dd 0,0
 
include "../../../macros.inc"
include "../../../proc32.inc"
include "../../../develop/libraries/network/network.inc"
include "../../../dll.inc"
;include "fdo.inc"
include "eth.inc"
include "lang.inc"
 
; connection statuses
STATUS_DISCONNECTED = 0 ; disconnected
STATUS_RESOLVING = 1 ; resolving server name
STATUS_CONNECTING = 2 ; connecting to server
STATUS_CONNECTED = 3 ; connected
; where to display status
STATUS_X = 25 + 22*6
STATUS_Y = 183 + 7*12
 
; supported encodings
CP866 = 0
CP1251 = 1
UTF8 = 2
; where to display encoding
ENCODING_X = 25 + 15*6
ENCODING_Y = 183 + 3*12
 
def_server_name db 'chat.freenode.net',0 ; default server name
 
user_nick dd 12 ; length
db 'kolibri_user ' ; string
user_nick_max = $ - user_nick - 4
 
user_real_name dd 14 ; length
db 'KolibriOS User ' ; string
user_real_name_max = $ - user_real_name - 4
 
 
START: ; start of execution
 
stdcall dll.Load, @IMPORT
test eax,eax
jnz exit
 
mov eax,40
mov ebx,11000111b
mcall
mcall 60, 1, ipcbuf, ipcbuf.size
mcall 9, 0xe0000, -1
mov eax,[ebx+process_information.PID]
mov [main_PID],eax
 
mov esi, def_server_name
mov edi, irc_server_name
@@:
lodsb
stosb
test al, al
jnz @b
 
mov edi,I_END
mov ecx,60*120
mov al,32
cld
rep stosb
 
mov eax,[rxs]
imul eax,11
mov [pos],eax
 
mov ebp,0
mov edx,I_END
 
redraw: ; redraw
call draw_window ; at first, draw the window
 
still:
 
mov eax,10 ; wait here for event
mcall
 
dec eax ; redraw
je redraw
dec eax ; key
je main_window_key
dec eax ; button
je button
cmp al,4
jz ipc
 
call process_network_event
 
cmp [I_END+120*60],byte 1
jne no_main_update
mov [I_END+120*60],byte 0
mov edx,I_END
call draw_channel_text
no_main_update:
 
call print_channel_list
 
jmp still
 
button: ; button
 
mov eax,17 ; get id
mcall
 
cmp ah,1 ; close program
jne noclose
exit:
or eax,-1
mcall
noclose:
cmp ah,21
jne no_change_encoding
cmp byte[edx-1],0
jnz still
mov eax,[encoding]
inc eax
mov edx,msgbox_struct
mov byte[edx],al
mov byte[edx-1],1 ; msgbox is running
push mb_stack
push edx
call [mb_create]
push msgbox_func_array
call [mb_setfunctions]
jmp still
no_change_encoding:
 
call socket_commands
 
jmp still
 
ipc:
mov edx,msgbox_struct
cmp byte[edx-1],0
jz @f
mov byte[edx-1],0
mov al,[edx]
dec eax
mov byte[encoding],al
call update_encoding
jmp ipc_done
@@:
call process_command
ipc_done:
mov dword [ipcbuf+4], 8
jmp still
 
main_window_key:
 
mov eax,2
mcall
 
shr eax,8
 
cmp eax,8
jne no_bks2
cmp [xpos],0
je still
dec [xpos]
call print_entry
jmp still
no_bks2:
 
cmp eax,20
jbe no_character2
mov ebx,[xpos]
mov [send_string+ebx],al
inc [xpos]
cmp [xpos],80
jb noxposdec
mov [xpos],79
noxposdec:
call print_entry
jmp still
no_character2:
 
cmp eax,13
jne no_send2
cmp [xpos],0
je no_send2
cmp [send_string],byte '/' ; server command
jne no_send2
call process_command
jmp still
no_send2:
 
jmp still
 
 
socket_commands:
 
cmp ah,22 ; connect
jnz tst3
 
; ignore if status is not "disconnected"
cmp [status], STATUS_DISCONNECTED
jnz .nothing
 
; start name resolving
inc [status] ; was STATUS_DISCONNECTED, now STATUS_RESOLVING
push gai_reqdata
push ip_list
push 0
push 0
push irc_server_name
call [getaddrinfo_start]
test eax, eax
jns getaddrinfo_done
call update_status
.nothing:
ret
 
tst3:
 
 
cmp ah,23 ; write userinfo
jnz tst4
 
; ignore if status is not "connected"
cmp [status], STATUS_CONNECTED
jnz .nothing
 
; create packet in packetbuf
mov edi, packetbuf
mov edx, edi
mov esi, string0
mov ecx, string0l-string0
rep movsb
mov esi, user_real_name+4
mov ecx, [esi-4]
rep movsb
mov al, 13
stosb
mov al, 10
stosb
mov esi, string1
mov ecx, string1l-string1
rep movsb
mov esi, user_nick+4
mov ecx, [esi-4]
rep movsb
mov al, 13
stosb
mov al, 10
stosb
; send packet
xchg edx, edi
sub edx, edi
mov esi, edi
mcall 53, 7, [socket]
.nothing:
ret
 
tst4:
 
 
cmp ah,24 ; close socket
jz disconnect
no_24:
 
 
ret
 
getaddrinfo_done:
; The address resolving is done.
; If eax is zero, address is resolved, otherwise there was some problems.
test eax, eax
jz .good
.disconnect:
; Change status to "disconnected" and return.
and [status], 0
call update_status
ret
.good:
; We got a list of IP addresses. Try to connect to first of them.
mov eax, [ip_list]
mov esi, [eax + addrinfo.ai_addr]
mov esi, [esi + sockaddr_in.sin_addr]
push eax
call [freeaddrinfo]
mcall 53, 5, 0, 6667, , 1
cmp eax, -1
jz .disconnect
; Socket has been opened. Save handle and change status to "connecting".
mov [socket], eax
inc [status] ; was STATUS_RESOLVING, now STATUS_CONNECTING
call update_status
ret
 
process_network_event:
; values for status: 0, 1, 2, 3
mov eax, [status]
dec eax
; 0 = STATUS_DISCONNECTED - do nothing
; (ignore network events if we are disconnected from network)
js .nothing
; 1 = STATUS_RESOLVING
jz .resolving
; 2 = STATUS_CONNECTING
dec eax
jz .connecting
; 3 = STATUS_CONNECTED
jmp .connected
.resolving:
; We are inside address resolving. Let the network library work.
push ip_list
push gai_reqdata
call [getaddrinfo_process]
; Negative returned value means that the resolving is not yet finished,
; and we continue the loop without status change.
; Zero and positive values are handled by getaddrinfo_done.
test eax, eax
jns getaddrinfo_done
.nothing:
ret
.connecting:
; We are connecting to the server, and socket status has changed.
mcall 53, 6, [socket]
; Possible values for status: SYN_SENT=2, SYN_RECEIVED=3, ESTABLISHED=4, CLOSE_WAIT=7
; First two mean that we are still connecting, and we must continue wait loop
; without status change.
; Last means that server has immediately closed the connection,
; and status becomes "disconnected".
cmp eax, 4
jb .nothing
jz .established
and [status], 0
call update_status
; close socket
mcall 53, 8
ret
.established:
; The connection has been established, change status from "connecting" to "connected".
inc [status]
call update_status
; Fall through to .connected, because some data can be already in buffer.
.connected:
call read_incoming_data
; Handle closing socket by the server.
mcall 53, 6, [socket]
cmp eax, 4
jnz disconnect
ret
 
disconnect:
; Release all allocated resources.
; Exact actions depend on current status.
mov eax, [status]
dec eax
; 0 = STATUS_DISCONNECTED - do nothing
js .nothing
; 1 = STATUS_RESOLVING
jz .resolving
; 2 = STATUS_CONNECTING, 3 = STATUS_CONNECTED
; In both cases we should close the socket.
mcall 53, 8, [socket]
jmp .disconnected
.resolving:
; Let the network library handle abort of resolving process.
push gai_reqdata
call [getaddrinfo_abort]
.disconnected:
; In all cases, set status to "disconnected".
and [status], 0
call update_status
.nothing:
ret
 
msgbox_notify:
inc byte [msgbox_running]
mcall 60,2,[main_PID],0,1
ret
 
print_channel_list:
 
pusha
 
mov eax,13
mov ebx,415*65536+6*13
mov ecx,27*65536+12*10
mov edx,0xffffff
mcall
 
mov eax,4
mov ebx,415*65536+27
mov ecx,[index_list_1]
mov edx,channel_list+32
newch:
movzx esi,byte [edx+31]
and esi,0x1f
mcall
add edx,32
add ebx,12
cmp edx,channel_list+32*10
jbe newch
 
no_channel_list:
 
popa
 
ret
 
 
print_user_list:
 
pusha
 
newtry:
 
mov edx,ebp
imul edx,120*80
add edx,120*60+8+I_END
cmp [edx],byte 1
je nonp
 
mov edx,ebp
imul edx,120*80
add edx,120*70+I_END
mov edi,edx
 
mov eax,[edx-8]
mov ebx,[edx-4]
add ebx,edx
sub ebx,3
inc eax
dec edx
newnss:
inc edx
dec eax
jz startuu
asdf:
cmp [edx],word ' '
jne nodouble
inc edx
nodouble:
cmp [edx],byte ' '
je newnss
inc edx
cmp edx,ebx
jbe asdf
dec dword [edi-8]
 
popa
ret
 
startuu:
 
cmp [edx],byte ' '
jne startpr
inc edx
startpr:
 
pusha
mov eax,13
mov ebx,415*65536+6*13
mov ecx,27*65536+12*10
mov edx,0xffffff
mcall
popa
 
mov eax,4
mov ebx,415*65536+27
 
mov ebp,0
newuser:
 
mov esi,0
newusers:
cmp [edx+esi],byte ' '
je do_print
inc esi
cmp esi,20
jbe newusers
do_print:
 
mov ecx,[index_list_1]
cmp [edx],byte '@'
jne no_op
mov ecx,[index_list_2]
no_op:
 
mcall
 
inc ebp
cmp ebp,10
je nonp
 
add ebx,12
 
add edx,esi
 
inc edx
cmp [edx],byte ' '
jne newuser
inc edx
jmp newuser
 
nonp:
 
popa
 
ret
 
 
start_user_list_at dd 0x0
 
recode_to_cp866:
rep movsb
ret
 
recode_to_cp1251:
xor eax, eax
jecxz .nothing
.loop:
lodsb
cmp al,0x80
jb @f
mov al,[cp866_table-0x80+eax]
@@: stosb
loop .loop
.nothing:
ret
 
recode_to_utf8:
jecxz .nothing
.loop:
lodsb
cmp al, 0x80
jb .single_byte
and eax, 0x7F
mov ax, [utf8_table+eax*2]
stosw
loop .loop
ret
.single_byte:
stosb
loop .loop
.nothing:
ret
 
recode:
mov eax, [encoding]
jmp [recode_proc+eax*4]
 
process_command:
 
pusha
 
mov eax,[xpos]
mov [send_string+eax+0],byte 13
mov [send_string+eax+1],byte 10
 
mov eax,[rxs]
imul eax,11
mov [pos],eax
mov eax,[send_to_channel]
imul eax,120*80
add eax,I_END
mov [text_start],eax
 
cmp [send_string],byte '/' ; server command
je server_command
 
; Ignore data commands when not connected.
cmp [status], STATUS_CONNECTED
jnz sdts_ret
 
mov bl,13
call print_character
mov bl,10
call print_character
mov bl,'<'
call print_character
 
mov esi,user_nick+4
mov ecx,[user_nick]
newnp:
mov bl,[esi]
call print_character
inc esi
loop newnp
 
mov bl,'>'
call print_character
mov bl,' '
call print_character
 
mov ecx,[xpos]
mov esi,send_string
newcw:
mov bl,[esi]
call print_character
inc esi
loop newcw
 
mov eax,dword [send_to_channel]
shl eax,5
add eax,channel_list
mov esi,eax
 
mov edi,send_string_header+8
movzx ecx,byte [eax+31]
cld
rep movsb
 
mov [edi],word ' :'
 
mov esi, send_string_header
mov ecx,10
movzx ebx,byte [eax+31]
add ecx,ebx
 
mov edi, packetbuf
rep movsb
 
mov esi,send_string
mov ecx,[xpos]
inc ecx
 
call recode
 
mov esi, packetbuf
mov edx, edi
sub edx, esi
mcall 53, 7, [socket]
 
mov [xpos], 0
jmp sdts_ret
 
server_command:
 
cmp [send_string+1],dword 'anic'
jne no_set_nick
 
mov ecx,[xpos]
sub ecx,7
cmp ecx,user_nick_max
jb @f
mov ecx,user_nick_max
@@:
mov [user_nick],ecx
 
mov esi,send_string+7
mov edi,user_nick+4
cld
rep movsb
 
pusha
mov edi,text+70*1+15
mov al,32
mov ecx,15
cld
rep stosb
popa
 
mov esi,user_nick+4
mov edi,text+70*1+15
mov ecx,[esi-4]
cld
rep movsb
 
mov [xpos],0
call draw_window
 
popa
ret
 
no_set_nick:
 
cmp [send_string+1],dword 'area'
jne no_set_real_name
 
mov ecx,[xpos]
sub ecx,7
cmp ecx,user_real_name_max
jb @f
mov ecx,user_real_name_max
@@:
mov [user_real_name],ecx
 
mov esi,send_string+7
mov edi,user_real_name+4
cld
rep movsb
 
pusha
mov edi,text+70*0+15
mov al,32
mov ecx,15
cld
rep stosb
popa
 
mov esi,user_real_name+4
mov edi,text+70*0+15
mov ecx,[esi-4]
rep movsb
 
mov [xpos],0
call draw_window
 
popa
ret
 
no_set_real_name:
 
cmp [send_string+1],dword 'aser'
jne no_set_server
 
mov ecx,[xpos]
sub ecx,7
 
mov esi,send_string+7
mov edi,irc_server_name
rep movsb
mov al,0
stosb
 
pusha
mov edi,text+70*2+15
mov al,32
mov ecx,15
cld
rep stosb
popa
 
mov ecx,[xpos]
sub ecx,7
mov esi,send_string+7
mov edi,text+70*2+15
rep movsb
 
mov [xpos],0
call draw_window
 
popa
ret
 
no_set_server:
 
; All other commands require a connection to the server.
cmp [status], STATUS_CONNECTED
jnz sdts_ret
 
 
cmp [send_string+1],dword 'quer'
jne no_query_create
 
mov edi,I_END+120*80
mov eax,1 ; create channel window - search for empty slot
newse2:
mov ebx,eax
shl ebx,5
cmp dword [channel_list+ebx],dword ' '
je free_found2
add edi,120*80
inc eax
cmp eax,[max_windows]
jb newse2
 
free_found2:
 
mov edx,send_string+7
 
mov ecx,[xpos]
sub ecx,7
mov [channel_list+ebx+31],cl
 
call create_channel_name
 
push edi
push eax
mov [edi+120*60+8],byte 1 ; query window
mov al,32
mov ecx,120*60
cld
rep stosb
pop eax
pop edi
 
; eax has the free position
; mov [thread_screen],edi
call create_channel_window
 
mov [xpos],0
 
popa
ret
 
no_query_create:
 
 
mov esi, send_string+1
mov ecx, [xpos]
inc ecx
mov edi, packetbuf
call recode
mov esi, packetbuf
mov edx, edi
sub edx, esi
 
mov eax, 53 ; write server command
mov ebx, 7
mov ecx, [socket]
mcall
 
send_done:
 
mov [xpos],0
 
cmp [send_string+1],dword 'quit'
jne no_quit_server
mov eax,5
mov ebx,200
mcall
 
mov eax, 53 ; close socket
mov ebx, 8
mov ecx, [socket]
mcall
 
mov ecx,[max_windows]
mov edi,I_END
newclose:
mov [edi+120*60+4],byte 1
call notify_channel_thread
add edi,120*80
loop newclose
 
popa
ret
 
no_quit_server:
 
sdts_ret:
 
popa
ret
 
get_next_byte:
; Load next byte from the packet, translating to cp866 if necessary
; At input esi = pointer to data, edx = limit of data
; Output is either (translated) byte in al with CF set or CF cleared.
mov eax, [encoding]
jmp [get_byte_table+eax*4]
 
get_byte_cp866:
cmp esi, edx
jae .nothing
lodsb
.nothing:
ret
 
get_byte_cp1251:
cmp esi, edx
jae .nothing
lodsb
cmp al, 0x80
jb @f
and eax, 0x7F
mov al, [cp1251_table+eax]
@@:
stc
.nothing:
ret
 
get_byte_utf8:
; UTF8 decoding is slightly complicated.
; One character can occupy one or more bytes.
; The boundary in packets theoretically can be anywhere in data,
; so this procedure keeps internal state between calls and handles
; one byte at a time, looping until character is read or packet is over.
; Globally, there are two distinct tasks: decode byte sequence to unicode char
; and convert this unicode char to our base encoding (that is cp866).
; 1. Check that there are data.
cmp esi, edx
jae .nothing
; 2. Load byte.
lodsb
movzx ecx, al
; 3. Bytes in an UTF8 sequence can be of any of three types.
; If most significant bit is cleared, sequence is one byte and usual ASCII char.
; First byte of a sequence must be 11xxxxxx, other bytes are 10yyyyyy.
and al, 0xC0
jns .single_byte
jp .first_byte
; 4. This byte is not first in UTF8 sequence.
; 4a. Check that the sequence was started. If no, it is invalid byte
; and we simply ignore it.
cmp [utf8_bytes_rest], 0
jz get_byte_utf8
; 4b. Otherwise, it is really next byte and it gives some more bits of char.
mov eax, [utf8_char]
shl eax, 6
lea eax, [eax+ecx-0x80]
; 4c. Decrement number of bytes rest in the sequence.
; If it goes to zero, character is read, so return it.
dec [utf8_bytes_rest]
jz .got_char
mov [utf8_char], eax
jmp get_byte_utf8
; 5. If the byte is first in UTF8 sequence, calculate the number of leading 1s
; - it equals total number of bytes in the sequence; some other bits rest for
; leading bits in the character.
.first_byte:
mov eax, -1
@@:
inc eax
add cl, cl
js @b
mov [utf8_bytes_rest], eax
xchg eax, ecx
inc ecx
shr al, cl
mov [utf8_char], eax
jmp get_byte_utf8
; 6. If the byte is ASCII char, it is the character.
.single_byte:
xchg eax, ecx
.got_char:
; We got the character, now abandon a possible sequence in progress.
and [utf8_bytes_rest], 0
; Now second task. The unicode character is in eax, and now we shall convert it
; to cp866.
cmp eax, 0x80
jb .done
; 0x410-0x43F -> 0x80-0xAF, 0x440-0x44F -> 0xE0-0xEF, 0x401 -> 0xF0, 0x451 -> 0xF1
cmp eax, 0x401
jz .YO
cmp eax, 0x451
jz .yo
cmp eax, 0x410
jb .unrecognized
cmp eax, 0x440
jb .part1
cmp eax, 0x450
jae .unrecognized
sub al, (0x40-0xE0) and 0xFF
ret
.part1:
sub al, 0x10-0x80
.nothing:
.done:
ret
.unrecognized:
mov al, '?'
stc
ret
.YO:
mov al, 0xF0
stc
ret
.yo:
mov al, 0xF1
stc
ret
 
read_incoming_data:
pusha
.packetloop:
.nextpacket:
mcall 53, 11, [socket], packetbuf, 1024
test eax, eax
jz .nothing
mov esi, edx ; esi = pointer to data
add edx, eax ; edx = limit of data
.byteloop:
call get_next_byte
jnc .nextpacket
cmp al, 10
jne .no_start_command
mov [cmd], 1
.no_start_command:
cmp al, 13
jne .no_end_command
mov ebx, [cmd]
mov byte [ebx+command-2], 0
call analyze_command
mov edi, command
mov ecx, 250
xor eax, eax
rep stosb
mov [cmd], eax
mov al, 13
.no_end_command:
mov ebx, [cmd]
cmp ebx, 512
jge @f
mov [ebx+command-2], al
inc [cmd]
@@:
jmp .byteloop
.nothing:
popa
ret
 
 
create_channel_name:
 
pusha
 
search_first_letter:
cmp [edx],byte ' '
jne first_letter_found
inc edx
jmp search_first_letter
first_letter_found:
 
mov esi,edx
mov edi,channel_list
add edi,ebx
mov ecx,30
xor eax,eax
newcase:
mov al,[esi]
cmp eax,'a'
jb nocdec
cmp eax,'z'
jg nocdec
sub al,97-65
nocdec:
mov [edi],al
inc esi
inc edi
loop newcase
 
popa
 
ret
 
 
create_channel_window:
 
pusha
 
mov [cursor_on_off],0
 
; mov [thread_nro],eax
 
mov edx,[thread_stack]
sub edx,8
mov [edx],eax
mov [edx+4],edi
mov eax,51
mov ebx,1
mov ecx,channel_thread
mcall
mov [edi+120*60+12], eax
 
add [thread_stack],0x4000
; add [thread_screen],120*80
 
popa
 
ret
 
 
print_entry:
 
pusha
 
mov eax,13
mov ebx,8*65536+6*80
mov ecx,151*65536+13
mov edx,0xffffff
mcall
 
mov eax,4
mov ebx,8*65536+154
mov ecx,0x000000
mov edx,send_string
mov esi,[xpos]
mcall
 
popa
 
; Fall through to draw_cursor.
; ret
 
draw_cursor:
 
pusha
 
mov eax,9
mov ebx,0xe0000
mov ecx,-1
mcall
 
cmp ax,word [0xe0000+4]
setnz dl
movzx edx,dl
neg edx
and edx,0xffffff
; jne no_blink
 
; call print_entry
 
mov ebx,[xpos]
imul ebx,6
add ebx,8
mov cx,bx
shl ebx,16
mov bx,cx
mov ecx,151*65536+163
mov eax,38
mcall
 
popa
 
ret
 
; no_blink:
;
; mov eax,13
; mov ebx,8*65536+6*60
; mov ecx,151*65536+13
; mov edx,0xffffff
; mcall
 
popa
 
ret
 
 
 
 
 
set_channel:
 
pusha
 
; UPPER / LOWER CASE CHECK
 
mov esi,eax
mov edi,channel_temp
mov ecx,40
xor eax,eax
newcase2:
mov al,[esi]
cmp eax,'#'
jb newcase_over2
cmp eax,'a'
jb nocdec2
cmp eax,'z'
jg nocdec2
sub al,97-65
nocdec2:
mov [edi],al
inc esi
inc edi
loop newcase2
newcase_over2:
sub edi,channel_temp
mov [channel_temp_length],edi
 
mov eax,channel_temp
 
mov [text_start],I_END+120*80
mov ebx,channel_list+32
mov eax,[eax]
 
mov edx,[channel_temp_length]
 
stcl1:
cmp dl,[ebx+31]
jne notfound
 
pusha
xor eax,eax
xor edx,edx
mov ecx,0
stc4:
mov dl,[ebx+ecx]
mov al,[channel_temp+ecx]
cmp eax,edx
jne notfound2
inc ecx
cmp ecx,[channel_temp_length]
jb stc4
popa
 
jmp found
 
notfound2:
popa
 
notfound:
add [text_start],120*80
add ebx,32
cmp ebx,channel_list+19*32
jb stcl1
 
mov [text_start],I_END
 
found:
 
popa
 
ret
 
 
channel_temp: times 100 db 0
channel_temp_length dd 0x0
 
 
 
print_nick:
 
pusha
 
mov eax,command+1
mov dl,'!'
call print_text
 
popa
ret
 
 
analyze_command:
 
pusha
 
mov [text_start],I_END
mov ecx,[rxs]
imul ecx,11
mov [pos],ecx
 
; mov bl,13
; call print_character
; mov bl,10
; call print_character
 
; mov ecx,[cmd]
; sub ecx,2
; mov esi,command+0
; newcmdc:
; mov bl,[esi]
; call print_character
; inc esi
; loop newcmdc
 
mov edx,I_END
; call draw_channel_text
 
; cmp [cmd],20
; jge cmd_len_ok
;
; mov [cmd],0
;
; popa
; ret
 
 
cmd_len_ok:
 
cmp [command],dword 'PING' ; ping response
jne no_ping_responce
 
call print_command_to_main
 
mov [command],dword 'PONG'
 
call print_command_to_main
 
mov eax,4
mov ebx,100*65536+3
mov ecx,0xffffff
mov edx,command
mov esi,[cmd]
mov [command+esi-1],word '**'
; mcall
 
mov eax,53
mov ebx,7
mov ecx,[socket]
mov edx,[cmd]
mov esi,command
mov word [esi+edx-2], 0x0a0d
mcall
 
popa
ret
 
no_ping_responce:
 
mov eax,[rxs]
imul eax,11
mov [pos],eax
 
mov [command],byte '<'
 
mov eax,command
mov ecx,100
new_blank:
cmp [eax],byte ' '
je bl_found
inc eax
loop new_blank
mov eax,50
bl_found:
 
inc eax
mov [command_position],eax
 
mov esi,eax
mov edi,irc_command
mov ecx,8
cld
rep movsb
 
 
cmp [irc_command],'PRIV' ; message to channel
jne no_privmsg
 
; compare nick
 
mov eax,[command_position]
add eax,8
call compare_to_nick
cmp [cresult],0
jne no_query_msg
mov eax,command+1
no_query_msg:
call set_channel
 
mov ecx,100 ; [cmd]
mov eax,command+10
acl3:
cmp [eax],byte ':'
je acl4
inc eax
loop acl3
mov eax,10
acl4:
inc eax
 
cmp [eax+1],dword 'ACTI'
jne no_action
push eax
mov eax,action_header_short
mov dl,0
call print_text
mov eax,command+1
mov dl,'!'
call print_text
mov bl,' '
call print_character
pop eax
add eax,8
mov dl,0
call print_text
call notify_channel_thread
popa
ret
 
no_action:
 
push eax
mov bl,10
call print_character
mov eax,command
mov dl,'!'
call print_text
mov bl,'>'
call print_character
mov bl,' '
call print_character
pop eax
 
mov dl,0
call print_text
call notify_channel_thread
 
popa
ret
 
no_privmsg:
 
 
cmp [irc_command],'PART' ; channel leave
jne no_part
 
; compare nick
 
mov eax,command+1
call compare_to_nick
cmp [cresult],0
jne no_close_window
 
mov eax,[command_position]
add eax,5
call set_channel
 
mov edi,[text_start]
mov [edi+120*60+4],byte 1
call notify_channel_thread
 
popa
ret
 
no_close_window:
 
mov eax,[command_position]
add eax,5
call set_channel
 
mov eax,action_header_red
mov dl,0
call print_text
mov eax,command+1
mov dl,'!'
mov cl,' '
call print_text
mov eax,has_left_channel
mov dl,0
call print_text
mov eax,[command_position]
add eax,5
mov dl,' '
call print_text
call notify_channel_thread
 
popa
ret
 
no_part:
 
 
cmp [irc_command],'JOIN' ; channel join
jne no_join
 
; compare nick
 
mov eax,command+1
call compare_to_nick
cmp [cresult],0
jne no_new_window
 
mov edi,I_END+120*80
mov eax,1 ; create channel window - search for empty slot
newse:
mov ebx,eax
shl ebx,5
cmp dword [channel_list+ebx],dword ' '
je free_found
add edi,120*80
inc eax
cmp eax,[max_windows]
jb newse
 
free_found:
 
mov edx,[command_position]
add edx,6
 
push eax
push edx
mov ecx,0
finde:
inc ecx
inc edx
movzx eax,byte [edx]
cmp eax,'#'
jge finde
mov [channel_list+ebx+31],cl
pop edx
pop eax
 
call create_channel_name
 
push edi
push eax
mov [edi+120*60+8],byte 0 ; channel window
mov al,32
mov ecx,120*60
cld
rep stosb
pop eax
pop edi
 
; eax has the free position
; mov [thread_screen],edi
call create_channel_window
 
no_new_window:
 
mov eax,[command_position]
add eax,6
call set_channel
 
mov eax,action_header_blue
mov dl,0
call print_text
mov eax,command+1
mov dl,'!'
mov cl,' '
call print_text
 
mov eax,joins_channel
mov dl,0
call print_text
 
mov eax,[command_position]
add eax,6
mov dl,0
call print_text
call notify_channel_thread
 
popa
ret
 
no_join:
 
 
cmp [irc_command],'NICK' ; nick change
jne no_nick_change
 
add [command_position], 6
; test for change of my nick
mov esi, command+1
mov edi, user_nick+4
mov ecx, [edi-4]
repz cmpsb
jnz .notmy
cmp byte [esi], '!'
jnz .notmy
; yes, this is my nick, set to new
mov esi, [command_position]
or ecx, -1
mov edi, esi
xor eax, eax
repnz scasb
not ecx
dec ecx
cmp ecx, user_nick_max
jb @f
mov ecx, user_nick_max
@@:
mov edi, user_nick+4
mov [edi-4], ecx
rep movsb
 
mov edi, text+70*1+15
mov al, ' '
mov cl, 15
push edi
rep stosb
pop edi
mov esi, user_nick+4
mov ecx, [esi-4]
cmp ecx, 15
jb @f
mov ecx, 15
@@:
rep movsb
mov [xpos], 0
call draw_window
.notmy:
; replace nick in all lists of users
mov ebx, I_END + 120*70
.channels:
mov esi, ebx
mov edx, [esi-4]
add edx, esi
.nicks:
mov edi, command+1
cmp byte [esi], '@'
jnz @f
inc esi
@@:
cmp esi, edx
jae .srcdone
lodsb
cmp al, ' '
jz .srcdone
scasb
jz @b
@@:
cmp esi, edx
jae .nextchannel
lodsb
cmp al, ' '
jnz @b
.nextnick:
cmp esi, edx
jae .nextchannel
lodsb
cmp al, ' '
jz .nextnick
dec esi
jmp .nicks
.srcdone:
cmp byte [edi], '!'
jnz .nextnick
; here we have esi -> end of nick which must be replaced to [command_position]+6
lea edx, [edi-command-1]
sub esi, edx
or ecx, -1
xor eax, eax
mov edi, [command_position]
repnz scasb
not ecx
dec ecx
push ecx
cmp ecx, edx
jb .decrease
jz .copy
.increase:
; new nick is longer than the old
push esi
lea edi, [ebx+120*10]
lea esi, [edi+edx]
sub esi, ecx
mov ecx, esi
sub ecx, [esp]
dec esi
dec edi
std
rep movsb
cld
pop esi
jmp .copy
.decrease:
; new nick is shorter than the old
push esi
lea edi, [esi+ecx]
add esi, edx
lea ecx, [ebx+120*10]
sub ecx, edi
rep movsb
pop esi
.copy:
; copy nick
mov edi, esi
dec edi
mov esi, [command_position]
pop ecx
sub edx, ecx
sub [ebx-4], edx
rep movsb
mov al, ' '
stosb
.nextchannel:
add ebx, 120*80
cmp ebx, I_END + 120*70 + 120*80*19
jb .channels
 
mov [text_start],I_END
add [text_start],120*80
 
new_all_channels3:
 
mov eax,action_header_short
mov dl,0
call print_text
mov eax,command+1
mov dl,'!'
call print_text
mov eax,is_now_known_as
mov dl,0
call print_text
mov eax,[command_position]
mov dl,0
call print_text
call notify_channel_thread
 
add [text_start],120*80
cmp [text_start],I_END+120*80*20
jb new_all_channels3
 
popa
ret
 
no_nick_change:
 
 
cmp [irc_command],'KICK' ; kick
jne no_kick
 
mov [text_start],I_END
add [text_start],120*80
 
mov eax,[command_position]
add eax,5
call set_channel
 
; new_all_channels4:
 
mov eax,action_header_short
mov dl,0
call print_text
mov eax,command+1
mov dl,'!'
call print_text
mov eax,kicked
mov dl,0
call print_text
mov eax,[command_position]
add eax,5
mov dl,0
call print_text
call notify_channel_thread
 
; add [text_start],120*80
; cmp [text_start],I_END+120*80*20
; jb new_all_channels4
 
popa
ret
 
no_kick:
 
 
 
 
cmp [irc_command],'QUIT' ; irc quit
jne no_quit
 
mov [text_start],I_END
add [text_start],120*80
 
new_all_channels2:
 
mov eax,action_header_red
mov dl,0
call print_text
mov eax,command+1
mov dl,'!'
call print_text
mov eax,has_quit_irc
mov dl,0
call print_text
call notify_channel_thread
 
add [text_start],120*80
cmp [text_start],I_END+120*80*20
jb new_all_channels2
 
popa
ret
 
no_quit:
 
 
cmp [irc_command],dword 'MODE' ; channel mode change
jne no_mode
 
mov [text_start],I_END
add [text_start],120*80
 
mov eax,[command_position]
add eax,5
call set_channel
 
new_all_channels:
 
mov eax,action_header_short
mov dl,0
call print_text
 
call print_nick
 
mov eax,sets_mode
mov dl,0
call print_text
 
mov eax,[command_position]
add eax,5
mov dl,0
call print_text
call notify_channel_thread
 
; add [text_start],120*80
; cmp [text_start],I_END+120*80*20
; jb new_all_channels
 
popa
ret
 
no_mode:
 
 
cmp [irc_command],dword '353 ' ; channel user names
jne no_user_list
 
mov eax,[command_position]
finde2:
inc eax
cmp [eax],byte '#'
jne finde2
call set_channel
 
finde3:
inc eax
cmp [eax],byte ':'
jne finde3
 
pusha
cmp [user_list_pos],0
jne no_clear_user_list
mov edi,[text_start]
add edi,120*70
mov [edi-8],dword 0
mov [edi-4],dword 0
mov al,32
mov ecx,1200
cld
rep stosb
no_clear_user_list:
popa
 
push eax
 
mov esi,eax
inc esi
mov edi,[text_start]
add edi,120*70
add edi,[user_list_pos]
mov edx,edi
mov ecx,command
add ecx,[cmd]
sub ecx,[esp]
sub ecx,3
and ecx,0xfff
cld
rep movsb
 
pop eax
mov ebx,command
add ebx,[cmd]
sub ebx,eax
sub ebx,2
mov [edx+ebx-1],dword ' '
 
add [user_list_pos],ebx
 
mov eax,[user_list_pos]
mov ebx,[text_start]
add ebx,120*70
mov [ebx-4],eax
call notify_channel_thread
 
popa
ret
 
user_list_pos dd 0x0
 
no_user_list:
 
 
cmp [irc_command],dword '366 ' ; channel user names end
jne no_user_list_end
 
mov [user_list_pos],0
 
popa
ret
 
no_user_list_end:
 
mov [command],byte '-'
call print_command_to_main
 
popa
 
ret
 
 
cresult db 0
 
compare_to_nick:
 
; input : eax = start of compare
; output : [cresult] = 0 if match, [cresult]=1 if no match
 
 
pusha
 
mov esi,eax
mov edi,0
 
new_nick_compare:
 
mov bl,byte [esi]
mov cl,byte [user_nick+4+edi]
 
cmp bl,cl
jne nonickm
 
add esi,1
add edi,1
 
cmp edi,[user_nick]
jb new_nick_compare
 
movzx eax,byte [esi]
cmp eax,40
jge nonickm
 
popa
mov [cresult],0
ret
 
nonickm:
 
popa
mov [cresult],1
ret
 
 
 
 
 
print_command_to_main:
 
pusha
 
mov [text_start],I_END
mov ecx,[rxs]
imul ecx,11
mov [pos],ecx
 
mov bl,13
call print_character
mov bl,10
call print_character
 
mov ecx,[cmd]
sub ecx,2
mov esi,command
newcmdc2:
mov bl,[esi]
call print_character
inc esi
loop newcmdc2
 
mov edx,I_END
call draw_channel_text
 
popa
 
ret
 
 
 
 
print_text:
 
pusha
 
mov ecx,command-2
add ecx,[cmd]
 
ptr2:
mov bl,[eax]
cmp bl,dl
je ptr_ret
cmp bl,0
je ptr_ret
call print_character
inc eax
cmp eax,ecx
jbe ptr2
 
ptr_ret:
 
mov eax,[text_start]
mov [eax+120*60],byte 1
 
popa
ret
 
 
cp1251_table:
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; 8
db '?','?','?','?','?',$F9,'?','?' , '?','?','?','?','?','?','?','?' ; 9
db '?',$F6,$F7,'?',$FD,'?','?','?' , $F0,'?',$F2,'?','?','?','?',$F4 ; A
db $F8,'?','?','?','?','?','?',$FA , $F1,$FC,$F3,'?','?','?','?',$F5 ; B
db $80,$81,$82,$83,$84,$85,$86,$87 , $88,$89,$8A,$8B,$8C,$8D,$8E,$8F ; C
db $90,$91,$92,$93,$94,$95,$96,$97 , $98,$99,$9A,$9B,$9C,$9D,$9E,$9F ; D
db $A0,$A1,$A2,$A3,$A4,$A5,$A6,$A7 , $A8,$A9,$AA,$AB,$AC,$AD,$AE,$AF ; E
db $E0,$E1,$E2,$E3,$E4,$E5,$E6,$E7 , $E8,$E9,$EA,$EB,$EC,$ED,$EE,$EF ; F
 
; 0 1 2 3 4 5 6 7 8 9 A B C D E F
 
utf8_table:
times 80h dw 0x98C3 ; default placeholder
; 0x80-0xAF -> 0x90D0-0xBFD0
repeat 0x30
store byte 0xD0 at utf8_table+2*(%-1)
store byte 0x90+%-1 at utf8_table+2*%-1
end repeat
; 0xE0-0xEF -> 0x80D1-0x8FD1
repeat 0x10
store byte 0xD1 at utf8_table+2*(0xE0-0x80+%-1)
store byte 0x80+%-1 at utf8_table+2*(0xE0-0x80+%)-1
end repeat
; 0xF0 -> 0x81D0, 0xF1 -> 0x91D1
store dword 0x91D181D0 at utf8_table+2*(0xF0-0x80)
 
cp866_table:
db $C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7 , $C8,$C9,$CA,$CB,$CC,$CD,$CE,$CF ; 8
db $D0,$D1,$D2,$D3,$D4,$D5,$D6,$D7 , $D8,$D9,$DA,$DB,$DC,$DD,$DE,$DF ; 9
db $E0,$E1,$E2,$E3,$E4,$E5,$E6,$E7 , $E8,$E9,$EA,$EB,$EC,$ED,$EE,$EF ; A
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; B
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; C
db '?','?','?','?','?','?','?','?' , '?','?','?','?','?','?','?','?' ; D
db $F0,$F1,$F2,$F3,$F4,$F5,$F6,$F7 , $F8,$F9,$FA,$FB,$FC,$FD,$FE,$FF ; E
db $A8,$B8,$AA,$BA,$AF,$BF,$A1,$A2 , $B0,$95,$B7,'?',$B9,$A4,'?','?' ; F
 
; 0 1 2 3 4 5 6 7 8 9 A B C D E F
 
print_character:
 
pusha
 
cmp bl,13 ; line beginning
jne nobol
mov ecx,[pos]
add ecx,1
boll1:
sub ecx,1
mov eax,ecx
xor edx,edx
mov ebx,[rxs]
div ebx
cmp edx,0
jne boll1
mov [pos],ecx
jmp newdata
nobol:
 
cmp bl,10 ; line down
jne nolf
addx1:
add [pos],dword 1
mov eax,[pos]
xor edx,edx
mov ecx,[rxs]
div ecx
cmp edx,0
jnz addx1
mov eax,[pos]
jmp cm1
nolf:
no_lf_ret:
 
 
cmp bl,15 ; character
jbe newdata
 
mov eax,[irc_data]
shl eax,8
mov al,bl
mov [irc_data],eax
 
mov eax,[pos]
call draw_data
 
mov eax,[pos]
add eax,1
cm1:
mov ebx,[scroll+4]
imul ebx,[rxs]
cmp eax,ebx
jb noeaxz
 
mov esi,[text_start]
add esi,[rxs]
 
mov edi,[text_start]
mov ecx,ebx
cld
rep movsb
 
mov esi,[text_start]
mov ecx,[rxs]
imul ecx,61
add esi,ecx
 
mov edi,[text_start]
mov ecx,[rxs]
imul ecx,60
add edi,ecx
mov ecx,ebx
cld
rep movsb
 
mov eax,ebx
sub eax,[rxs]
noeaxz:
mov [pos],eax
 
newdata:
 
mov eax,[text_start]
mov [eax+120*60],byte 1
 
popa
ret
 
notify_channel_thread:
pusha
mov eax, [text_start]
mov ecx, [eax+120*60+12]
mcall 60, 2, , 0, 1
popa
ret
 
 
draw_data:
 
pusha
 
and ebx,0xff
add eax,[text_start]
mov [eax],bl
 
popa
ret
 
 
 
draw_window:
 
pusha
 
mov eax,12
mov ebx,1
mcall
 
xor eax,eax ; draw window
mov ebx,5*65536+499
mov ecx,5*65536+381
mov edx,[wcolor]
add edx,0x14ffffff
mov edi,title
mcall
 
mov eax,8 ; button: change encoding
mov ebx,(ENCODING_X-2)*65536+38
mov ecx,(ENCODING_Y-2)*65536+12
mov edx,21
mov esi,[main_button]
mcall
 
; mov eax,8 ; button: open socket
mov ebx,43*65536+22
mov ecx,241*65536+10
; mov edx,22
inc edx
mcall
 
;mov eax,8 ; button: send userinfo
mov ebx,180*65536+22
mov ecx,241*65536+10
; mov edx,23
inc edx
mcall
 
;mov eax,8 ; button: close socket
mov ebx,317*65536+22
mov ecx,241*65536+10
; mov edx,24
inc edx
mcall
 
mov eax,38 ; line
mov ebx,5*65536+494
mov ecx,148*65536+148
mov edx,[main_line]
mcall
add ecx,1*65536+1
 
mov eax,38 ; line
mov ebx,5*65536+494
mov ecx,166*65536+166
mcall
add ecx,1*65536+1
 
mov eax,38 ; line
mov ebx,410*65536+410
mov ecx,22*65536+148
mcall
add ebx,1*65536+1
 
mov ebx,25*65536+183 ; info text
mov ecx,0x000000
mov edx,text
mov esi,70
newline:
mov eax,4
mcall
add ebx,12
add edx,70
cmp [edx],byte 'x'
jne newline
 
mov edx,I_END ; text from server
call draw_channel_text
 
call print_entry
 
mov eax,12
mov ebx,2
mcall
 
popa
 
ret
 
update_status:
pusha
mov esi, [status]
mov edi, text + 7*70 + 22
mov ecx, status_text_len
push ecx
imul esi, ecx
add esi, status_text
mov edx, edi
rep movsb
pop esi
mcall 4, STATUS_X*65536+STATUS_Y, 0x40000000, , , 0xFFFFFF
popa
ret
 
update_encoding:
pusha
mov edx, 21
mcall 8 ; delete button
mov esi, [main_button]
mcall , <(ENCODING_X-2),38>, <(ENCODING_Y-2),12> ; recreate it
mov esi, [encoding]
mov edi, text + 3*70 + 15
mov ecx, encoding_text_len
push ecx
imul esi, ecx
add esi, encoding_text
mov edx, edi
rep movsb
pop esi
mcall 4, ENCODING_X*65536+ENCODING_Y, 0
popa
ret
 
main_line dd 0x000000
main_button dd 0x6565cc
 
if lang eq ru
text:
db ' ‚ è¥ ¨¬ï : KolibriOS User - ¬¥­ï©â¥ â ª: /areal Jill User '
db ' ¨ª : kolibri_user - ¬¥­ï©â¥ â ª: /anick Jill '
db ' ‘¥à¢¥à : freenode.net - ¬¥­ï©â¥ â ª: /aserv irc.by '
db ' Š®¤¨à®¢ª  : UTF-8 '
db ' '
db ' 1) Connect 2) Send userinfo 3) Disconnect '
db ' '
db ' ‘â âãá ᮥ¤¨­¥­¨ï: ­¥ ᮥ¤¨­¥­® '
db ' '
db ' Š®¬ ­¤ë, ¤®áâã¯­ë¥ ¯®á«¥ ãáâ ­®¢ª¨ ᮥ¤¨­¥­¨ï: '
db ' '
db ' /join #ChannelName - ­ ¯à¨¬¥à: /join #kolibrios '
db ' /part #ChannelName - ­ ¯à¨¬¥à: /part #windows '
db ' /query Nickname - ­ ¯à¨¬¥à: /query Mary '
db ' /quit - ®ª¨­ãâì á¥à¢¥à ¨ § ªàëâì ᮪¥â '
db 'x' ; <- END MARKER, DONT DELETE
 
status_text:
db '­¥ ᮥ¤¨­¥­® '
db '¯®«ãç î ¨¬ï á¥à¢¥à ... '
db 'ᮥ¤¨­¥­¨¥... '
db 'ᮥ¤¨­¥­® '
status_text_len = 24
 
encoding_text:
db 'CP866 '
db 'CP1251'
db 'UTF-8 '
encoding_text_len = 6
 
else
text:
db ' Real name : KolibriOS User - change with eg /areal Jill User '
db ' Nick : kolibri_user - change with eg /anick Jill '
db ' Server : freenode.net - change with eg /aserv irc.by '
db ' Encoding : UTF-8 '
db ' '
db ' 1) Connect 2) Send userinfo 3) Disconnect '
db ' '
db ' Connection status: disconnected '
db ' '
db ' Commands after established connection: '
db ' '
db ' /join #ChannelName - eg /join #kolibrios '
db ' /part #ChannelName - eg /part #windows '
db ' /query Nickname - eg /query Mary '
db ' /quit - Quit server and Close socket '
db 'x' ; <- END MARKER, DONT DELETE
 
status_text:
db 'disconnected '
db 'resolving server name...'
db 'connecting... '
db 'connected '
status_text_len = 24
 
encoding_text:
db 'CP866 '
db 'CP1251'
db 'UTF-8 '
encoding_text_len = 6
end if
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; CHANNEL THREADS
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
 
channel_thread:
 
; mov ebp,[thread_nro]
pop ebp
pop edx
 
mov eax,ebp
shl eax,14
add eax,0x80000
mov esp,eax
 
; mov edi,ebp ; clear thread memory
; imul edi,120*80
; add edi,I_END
; mov ecx,120*80
; mov al,32
; cld
; rep stosb
 
; Create IPC buffer in the stack.
push eax
push eax
push eax
push 8
push 0
mov ecx, esp
push edx
mcall 60, 1, , 20
pop edx
mcall 40, 1100111b
 
; mov edx,[thread_screen]
 
thread_redraw:
call thread_draw_window
call draw_channel_text
call print_user_list
call print_entry
 
w_t:
 
mov esi,ebp
imul esi,120*80
add esi,I_END
cmp [esi+120*60+4],byte 1
jne no_channel_leave
mov [esi+120*60+4],byte 0
mov edi,ebp
shl edi,5
mov dword [channel_list+edi],dword ' '
mov byte [channel_list+edi+31],byte 1
mov eax,-1
mcall
no_channel_leave:
 
mcall 10
dec eax
jz thread_redraw
dec eax
jz thread_key
dec eax
jz thread_end
cmp al,4
jz thread_ipc
call check_mouse
jmp w_t
thread_end:
mov eax,17
mcall
mov eax,ebp
imul eax,120*80
add eax,I_END
cmp [eax+120*60+8],byte 0 ; channel window
je not_close
mov eax,ebp
shl eax,5
add eax,channel_list
mov [eax],dword ' '
mov [eax+31],byte 1
mov eax,-1
mcall
not_close:
mov [text_start],eax
mov eax,nocl
newcc:
mov bl,[eax]
call print_character
inc eax
cmp [eax],byte 0
jne newcc
call draw_channel_text
jmp w_t
nocl: db 13,10,'To exit channel, use PART or QUIT command.',0
thread_ipc:
mov byte [esp+4], 8 ; erase message from IPC buffer
no_end:
 
cmp [edx+120*60],byte 1
jne no_update
mov [edx+120*60],byte 0
call draw_channel_text
no_update:
 
call print_user_list
 
nopri2:
 
jmp w_t
 
 
 
check_mouse:
 
pusha
 
mov eax,37
mov ebx,1
mcall
 
mov ebx,eax
shr eax,16
and ebx,0xffff
 
cmp eax,420
jb no_mouse
cmp eax,494
jg no_mouse
 
cmp ebx,145
jg no_mouse
cmp ebx,23
jb no_mouse
 
 
cmp ebx,100
jb no_plus
mov eax,ebp
imul eax,120*80
add eax,120*70+I_END
inc dword [eax-8]
call print_user_list
mov eax,5
mov ebx,8
mcall
jmp no_mouse
no_plus:
 
cmp ebx,80
jg no_mouse
mov eax,ebp
imul eax,120*80
add eax,120*70+I_END
cmp dword [eax-8],dword 0
je no_mouse
dec dword [eax-8]
call print_user_list
mov eax,5
mov ebx,8
mcall
 
no_minus:
 
no_mouse:
 
popa
 
ret
 
 
 
 
thread_key:
 
mov eax,2
mcall
 
shr eax,8
 
cmp eax,8
jne no_bks
cmp [xpos],0
je w_t
dec [xpos]
call print_entry
jmp w_t
no_bks:
 
cmp eax,20
jbe no_character
mov ebx,[xpos]
mov [send_string+ebx],al
inc [xpos]
cmp [xpos],80
jb xpok
mov [xpos],79
xpok:
call print_entry
jmp w_t
no_character:
 
cmp eax,13
jne no_send
cmp [xpos],0
je no_send
mov dword [send_to_channel],ebp
pusha
mcall 60,2,[main_PID],0,1
wait_for_sending:
mov eax,5
mov ebx,1
mcall
cmp dword [ipcbuf+4],8
jne wait_for_sending
popa
call draw_channel_text
call print_entry
jmp w_t
no_send:
 
jmp w_t
 
 
 
 
 
 
draw_channel_text:
 
pusha
 
mov eax,4
mov ebx,10*65536+26
mov ecx,12
mov esi,[rxs]
dct:
pusha
mov cx,bx
shl ecx,16
mov cx,9
mov eax,13
mov ebx,10*65536
mov bx,word [rxs]
imul bx,6
mov edx,0xffffff
mcall
popa
push ecx
mov eax,4
mov ecx,0
cmp [edx],word '* '
jne no_red
mov ecx,0x0000ff
no_red:
cmp [edx],word '**'
jne no_light_blue
cmp [edx+2],byte '*'
jne no_light_blue
mov ecx,0x0000ff
no_light_blue:
cmp [edx],byte '#'
jne no_blue
mov ecx,0x0000ff
no_blue:
mcall
add edx,[rxs]
add ebx,10
pop ecx
loop dct
 
popa
ret
 
 
 
 
 
thread_draw_window:
 
pusha
 
mov eax,12
mov ebx,1
mcall
 
mov ebx,ebp ; draw window
shl ebx,16+4
xor eax,eax
mov ecx,ebx
mov bx,499
mov cx,170
 
mov edx,[wcolor]
add edx,0x03ffffff
mov esi,0x80555599
mov edi,0x00ffffff
 
mcall
 
mov eax,ebp ; label
add eax,48
mov [labelc+14],al
mov eax,ebp
shl eax,5
add eax,channel_list
mov esi,eax
mov edi,labelc+17
movzx ecx,byte [eax+31]
cld
rep movsb
 
mov esi,17 ; print label
movzx ebx,byte [eax+31]
add esi,ebx
mov eax,4
mov ebx,9*65536+8
mov ecx,0x00ffffff
mov edx,labelc
mcall
 
mov eax,38 ; line
mov ebx,5*65536+494
mov ecx,148*65536+148
mov edx,[channel_line_sun]
mcall
add ecx,1*65536+1
mov edx,[channel_line_shadow]
mcall
 
 
;mov eax,38 ; line
mov ebx,410*65536+410
mov ecx,22*65536+148
mov edx,[channel_line_sun]
mcall
add ebx,1*65536+1
mov edx,[channel_line_shadow]
mcall
 
mov eax,12
mov ebx,2
mcall
 
popa
 
ret
 
 
; DATA AREA
 
socket dd 0x0
 
bgc dd 0x000000
dd 0x000000
dd 0x00ff00
dd 0x0000ff
dd 0x005500
dd 0xff00ff
dd 0x00ffff
dd 0x770077
 
tc dd 0xffffff
dd 0xff00ff
dd 0xffffff
dd 0xffffff
dd 0xffffff
dd 0xffffff
dd 0xffffff
dd 0xffffff
 
channel_line_sun dd 0x9999ff
channel_line_shadow dd 0x666699
 
cursor_on_off dd 0x0
 
max_windows dd 20
 
thread_stack dd 0x9fff0
;thread_nro dd 1
;thread_screen dd I_END+120*80*1
 
action_header_blue db 10,'*** ',0
action_header_red db 10,'*** ',0
 
action_header_short db 10,'* ',0
 
has_left_channel db ' has left ',0
joins_channel db ' has joined ',0
is_now_known_as db ' is now known as ',0
has_quit_irc db ' has quit IRC',0
sets_mode db ' sets mode ',0
kicked db ' kicked from ',0
 
index_list_1 dd 0x0000bb
index_list_2 dd 0x0000ff
 
posx dd 0x0
incoming_pos dd 0x0
incoming_string: times 128 db 0
 
pos dd 0x0
 
text_start dd I_END
irc_data dd 0x0
print db 0x0
cmd dd 0x0
rxs dd 66
 
res: db 0,0
command: times 600 db 0x0
 
nick dd 0,0,0
irc_command dd 0,0
 
command_position dd 0x0
counter dd 0
send_to_server db 0
 
channel_list: times 32*20 db 32
send_to_channel dd 0x0
 
send_string_header: db 'privmsg #eax :'
times 100 db 0x0
 
send_string: times 100 db 0x0
xpos dd 0
 
string0: db 'USER guest ser1 ser2 :'
string0l:
string1: db 'nick '
string1l:
 
attribute dd 0
scroll dd 1
dd 12
 
numtext db ' '
 
wcolor dd 0x000000
 
labelc db 'AIRC - WINDOW X: #xxx '
title db 'IRC client ',version,0
 
ipcbuf:
dd 0
dd 8
dd ?
dd ?
db ?
.size = $
 
align 4
@IMPORT:
 
library network, 'network.obj', msgbox, 'msgbox.obj'
import network, \
getaddrinfo_start, 'getaddrinfo_start', \
getaddrinfo_process, 'getaddrinfo_process', \
getaddrinfo_abort, 'getaddrinfo_abort', \
freeaddrinfo, 'freeaddrinfo'
import msgbox, mb_create, 'mb_create', mb_setfunctions, 'mb_setfunctions'
 
msgbox_running db ? ; must be the byte before msgbox_struct
; look to the handler of button 21
msgbox_struct:
.default:
dw ? ; default button, will be filled with current encoding
db 'Encoding',0
db 'Select encoding for all messages:',0
db 'CP866',0
db 'CP1251',0
db 'UTF-8',0
db 0
 
align 4
status dd STATUS_DISCONNECTED
encoding dd UTF8
recode_proc dd recode_to_cp866, recode_to_cp1251, recode_to_utf8
get_byte_table dd get_byte_cp866, get_byte_cp1251, get_byte_utf8
msgbox_func_array:
times 3 dd msgbox_notify
initialized_size:
 
main_PID dd ? ; identifier of main thread
utf8_bytes_rest dd ? ; bytes rest in current UTF8 sequence
utf8_char dd ? ; first bits of current UTF8 character
gai_reqdata rb 32 ; buffer for getaddrinfo_start/process
ip_list dd ? ; will be filled as pointer to addrinfo list
irc_server_name rb 256 ; buffer for irc_server_name
packetbuf rb 1024 ; buffer for packets to server
mb_stack rb 1024 ; stack for messagebox thread
 
;;
;; Channel data at I_END
;;
;; 120*80 * channel window (1+)
;;
;; At Size
;;
;; 00 , 120*60 window text 120 characters per row
;; 120*60 , 1 text is updated
;; 120*60+4 , 1 close yourself
;; 120*60+8 , 1 0 = channel window : 1 = private chat
;; 120*60+12 , 4 identifier of the thread
;; 120*61 , 256 channel name
;; 120*61+254 , 254 channel entry text from user
;; 120*61+255 , 1 length of entry text
;; 120*69+248 , 4 display names from n:th name
;; 120*69+252 , 4 length of names string
;; 120*70 , 1200 names separated with space
;;
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/airc/trunk/eth.inc
0,0 → 1,670
;
; ETH.INC
;
; made by hidnplayr (hidnplayr@gmail.com) for KolibriOS and DEX4U
;
; The given code before every macro is only a simple example
;
; Change the OS value to DEX4U or MEOS
;
; HISTORY
;
; v1.0: 18 august 2006
;
 
MEOS equ 1 ; Dont change these !
DEX4U equ 2 ;
 
OS equ MEOS ; Change these instead ;)
TIMEOUT equ 60 ; timeout for DNS request
BUFFER equ 512 ; Buffer size for DNS
 
macro int1 {
if OS eq MEOS
mcall
else if OS eq DEX4U
int 0x52
end if
}
 
macro int2 {
if OS eq MEOS
mcall
else if OS eq DEX4U
int 0x53
end if
}
 
macro mov arg1,arg2 {
 
if arg1 eq arg2
else
mov arg1,arg2
end if
 
}
 
; eth.get_IP eax
;
; gets the current IP that is defined in Stack (return in eax in this example)
macro eth.get_IP IP {
if OS eq MEOS
mov eax,52
end if
mov ebx,1
int1
 
mov IP ,eax
}
 
; eth.get_GATEWAY eax
;
; gets the current GATEWAY that is defined in Stack (return in eax in this example)
macro eth.get_GATEWAY GATEWAY {
if OS eq MEOS
mov eax,52
end if
mov ebx,9
int1
move GATEWAY ,eax
}
 
; eth.get_SUBNET eax
;
; gets the current SUBNET that is defined in Stack (return in eax in this example)
macro eth.get_SUBNET SUBNET {
if OS eq MEOS
mov eax,52
end if
mov ebx,10
int1
mov SUBNET ,eax
}
 
; eth.get_DNS eax
;
; gets the current DNS that is defined in Stack (return in eax in this example)
macro eth.get_DNS DNS {
if OS eq MEOS
mov eax,52
end if
mov ebx,13
int1
mov DNS ,eax
}
 
; eth.set_IP eax
;
; set a new IP in stack (input in eax in this example)
macro eth.set_IP IP {
mov ecx,IP
if OS eq MEOS
mov eax,52
end if
mov ebx,3
int1
}
 
; eth.set_GATEWAY eax
;
; set a new GATEWAY in stack (input in eax in this example)
macro eth.set_GATEWAY GATEWAY {
mov ecx,GATEWAY
if OS eq MEOS
mov eax,52
end if
mov ebx,11
int1
}
 
; eth.set_SUBNET eax
;
; set a new SUBNET in stack (input in eax in this example)
macro eth.set_SUBNET SUBNET {
mov ecx,SUBNET
if OS eq MEOS
mov eax,52
end if
mov ebx,12
int1
}
 
; eth.set_DNS eax
;
; set a new DNS in stack (input in eax in this example)
macro eth.set_DNS DNS {
mov ecx,DNS
if OS eq MEOS
mov eax,52
end if
mov ebx,14
int1
}
 
; eth.open eax,80,ebx,[socket]
;
; open a socket on local port in eax to port 80 on server on ebx
; the socketnumber will be returned in [socket] (dword)
macro eth.open local,remote,ip,socket {
mov ecx, local
mov edx, remote
mov esi, ip
if OS eq MEOS
mov eax,53
end if
mov ebx, 0
int2
 
mov socket,eax
}
 
; eth.close [socket]
;
; closes socket on socketnumber [socket]
macro eth.close socket {
mov ecx, socket
if OS eq MEOS
mov eax,53
end if
mov ebx, 1
int2
}
 
; eth.poll [socket],eax
;
; polls [socket] for data
; eax = 0 when there is data
macro eth.poll socket,result {
mov ecx, socket
if OS eq MEOS
mov eax,53
end if
mov ebx, 2
int2
 
mov result, eax
}
 
; eth.read_byte [socket], bl
;
; reads a byte from the socket and returns in bl
macro eth.read_byte socket, result {
mov ecx, socket
if OS eq MEOS
mov eax,53
end if
mov ebx, 3
int2
 
mov result,bl
}
 
; eth.write [socket],12,msg
; msg db 'hello world!'
;
; send message msg to socket
macro eth.write socket,length,msg {
mov ecx, socket
mov edx, length
mov esi, msg
if OS eq MEOS
mov eax,53
end if
mov ebx, 4
int2
}
 
; eth.open_tcp 80,80,eax,0,[socket]
;
; opens a tcp socket on port 80 to port 80 on IP eax with passive open
; returns socket number in eax
macro eth.open_tcp local,remote,ip,passive,socket {
 
pusha
mov ecx, local
mov edx, remote
mov esi, ip
mov edi, passive ; 0 = PASSIVE open
if OS eq MEOS
mov eax,53
end if
mov ebx, 5
int2
popa
 
mov socket,eax
}
 
; eth.socket_status [socket],eax
;
; returns socket status in eax
macro eth.socket_status socket,result {
mov ecx, socket
if OS eq MEOS
mov eax,53
end if
mov ebx, 6
int2
 
mov result,eax
}
 
; eth.write_tcp [socket],12,msg
;
; msg db 'hello world!'
;
; send message to TCP socket
macro eth.write_tcp socket,length,msg {
mov ecx, socket
mov edx, length
mov esi, msg
if OS eq MEOS
mov eax,53
end if
mov ebx, 7
int2
}
 
; eth.close_tcp [socket]
;
; closes tcp socket [socket]
macro eth.close_tcp socket {
mov ecx, socket
if OS eq MEOS
mov eax,53
end if
mov ebx, 8
int2
}
 
; eth.check_port 165,eax
;
; checks if port 165 is used
; return is 0 when port is free
macro eth.check_port port,result {
if OS eq MEOS
mov eax,53
end if
mov ebx, 9
mov ecx, port
int2
 
mov result,eax
}
 
; eth.status eax
;
; returns socket status in eax
macro eth.status status {
if OS eq MEOS
mov eax,53
end if
mov ebx, 255
mov ecx, 6
int2
 
mov status,eax
}
 
; eth.search 165,edx
;
; searches a free local port starting from 166 (165 + 1 !)
; returns in edx
macro eth.search_port port,result {
mov edx,port
@@:
inc edx
eth.check_port edx,eax
cmp eax,0
je @r
mov result,edx
}
 
; eth.read_data [socket],buffer,512
; buffer rb 512
; socket dd ?
;
; reads data from socket into a buffer, stops when there is no more data or buffer is full.
macro eth.read_data socket,dest,endptr,bufferl {
 
mov eax, dest
mov endptr, eax
 
; we have data - this will be the response
@@:
mov eax,endptr
cmp eax,bufferl
jg @f
 
mov eax, 53
mov ebx, 3
mov ecx, socket
mcall ; read byte - block (high byte)
 
; Store the data in the response buffer
mov eax, endptr
mov [eax], bl
inc dword endptr
 
mov eax, 53
mov ebx, 2
mov ecx, socket
mcall ; any more data?
 
cmp eax, 0
jne @r ; yes, so get it
@@:
 
}
 
; eth.wait_for_data [socket],60,abort
; eth.read_data ....
; abort:
;
; Waits for data with timeout
 
macro eth.wait_for_data socket,TIMEOUT,abort {
 
mov edx,TIMEOUT
 
@@:
eth.poll socket,eax
 
cmp eax,0
jne @f
 
dec edx
jz abort
 
if OS eq MEOS
mov eax,5 ; wait here for event
mov ebx,100
mcall
else if OS eq DEX4U
mov ax,18
call [SetDelay]
call dword[stack_handler]
end if
 
jmp @r
@@:
 
}
 
 
; The function 'resolve' resolves the address in edx and puts the resulting IP in eax.
; When the input is an IP-adress, the function will output this IP in eax.
; If something goes wrong, the result in eax should be 0
;
; example:
;
; resolve query1,IP
; resolve '192.168.0.1',IP
; resolve query2,IP
;
; query1 db 'www.google.com',0
; query2 db '49.78.84.45',0
; IP dd ?
 
macro resolve query,result {
 
if query eqtype 0
mov edx,query
else
local ..string, ..label
jmp ..label
..string db query,0
..label:
mov edx,..string
end if
 
call __resolve
 
mov result,eax
 
}
 
if used __resolve
 
__resolve:
 
;DEBUGF 1,'Resolving started\n'
 
 
; This code validates if the query is an IP containing 4 numbers and 3 dots
 
 
push edx ; push edx (query address) onto stack
xor al, al ; make al (dot count) zero
 
@@:
cmp byte[edx],'0' ; check if this byte is a number, if not jump to no_IP
jl no_IP ;
cmp byte[edx],'9' ;
jg no_IP ;
 
inc edx ; the byte was a number, so lets check the next byte
 
cmp byte[edx],0 ; is this byte zero? (have we reached end of query?)
jz @f ; jump to next @@ then
 
cmp byte[edx],'.' ; is this byte a dot?
jne @r ; if not, jump to previous @@
 
inc al ; the byte was a dot so increment al(dot count)
inc edx ; next byte
jmp @r ; lets check for numbers again (jump to previous @@)
 
@@: ; we reach this when end of query reached
cmp al,3 ; check if there where 3 dots
jnz no_IP ; if not, jump to no_IP (this is where the DNS will take over)
 
; The following code should convert this IP into a dword and output it in eax
 
pop esi ; edx (query address) was pushed onto stack and is now popped in esi
 
xor edx, edx ; result
xor eax, eax ; current character
xor ebx, ebx ; current byte
 
.outer_loop:
shl edx, 8
add edx, ebx
xor ebx, ebx
.inner_loop:
lodsb
test eax, eax
jz .finish
cmp al, '.'
jz .outer_loop
sub eax, '0'
imul ebx, 10
add ebx, eax
jmp .inner_loop
.finish:
shl edx, 8
add edx, ebx
 
bswap edx
mov eax, edx
 
;DEBUGF 1,'The query was an IP: %x.%x.%x.%x\n',dh,dl,al,ah
 
ret
 
 
no_IP:
 
pop edx
 
; The query is not an IP address, we will send the query to a DNS server and hope for answer ;)
 
;DEBUGF 1,'The query is no ip, Building request string from:%u\n',edx
 
; Build the request string
mov eax, 0x00010100
mov [dnsMsg], eax
mov eax, 0x00000100
mov [dnsMsg+4], eax
mov eax, 0x00000000
mov [dnsMsg+8], eax
 
; domain name goes in at dnsMsg+12
mov esi, dnsMsg + 12 ; location of label length
mov edi, dnsMsg + 13 ; label start
mov ecx, 12 ; total string length so far
 
td002:
mov [esi], byte 0
inc ecx
 
td0021:
mov al, [edx]
 
cmp al, 0
je td001 ; we have finished the string translation
 
cmp al, '.'
je td004 ; we have finished the label
 
inc byte [esi]
inc ecx
mov [edi], al
inc edi
inc edx
jmp td0021
 
td004:
mov esi, edi
inc edi
inc edx
jmp td002
 
; write label len + label text
td001:
mov [edi], byte 0
inc ecx
inc edi
mov [edi], dword 0x01000100
add ecx, 4
 
mov [dnsMsgLen], ecx ; We'll need the length of the message when we send it
; Now, lets send this and wait for an answer
 
eth.search_port 1024,edx ; Find a free port starting from 1025 and store in edx
eth.get_DNS esi ; Read DNS IP from stack into esi
eth.open edx,53,esi,[socketNum] ; First, open socket
; DEBUGF 1,'Socket opened: %u (port %u)\n',[socketNum],ecx
eth.write [socketNum],[dnsMsgLen],dnsMsg ; Write to socket ( request DNS lookup )
; DEBUGF 1,'Data written, length:%u offset:%u\n',[dnsMsgLen],dnsMsg
; DEBUGF 1,'Waiting for data: (timeout is %us)\n',TIMEOUT
eth.wait_for_data [socketNum],TIMEOUT,no_data; Now, we wait for data from remote
eth.read_data [socketNum],dnsMsg,[dnsMsgLen],dnsMsg+BUFFER ; Read the data into the buffer
; DEBUGF 1,'Data received, offset:%u buffer size:%u length:%u\n',dnsMsg,BUFFER,esi-dnsMsg
eth.close [socketNum] ; We're done, close the socket
; DEBUGF 1,'Closed Socket\n'
 
; Now parse the message to get the host IP. Man, this is complicated. It's described in RFC 1035
; 1) Validate that we have an answer with > 0 responses
; 2) Find the answer record with TYPE 0001 ( host IP )
; 3) Finally, copy the IP address to the display
; Note: The response is in dnsMsg, the end of the buffer is pointed to by [dnsMsgLen]
 
mov esi, dnsMsg
 
mov al, [esi+2] ; Is this a response to my question?
and al, 0x80
cmp al, 0x80
jne abort
 
;DEBUGF 1,'It was a response to my question\n'
 
mov al, [esi+3] ; Were there any errors?
and al, 0x0F
cmp al, 0x00
jne abort
 
;DEBUGF 1,'There were no errorst\n'
 
mov ax, [esi+6] ; Is there ( at least 1 ) answer?
cmp ax, 0x00
je abort
 
; Header validated. Scan through and get my answer
add esi, 12 ; Skip to the question field
call skipName ; Skip through the question field
add esi, 4 ; skip past the questions qtype, qclass
 
ctr002z:
; Now at the answer. There may be several answers, find the right one ( TYPE = 0x0001 )
call skipName
mov ax, [esi]
cmp ax, 0x0100 ; Is this the IP address answer?
jne ctr002c
add esi, 10 ; Yes! Point eax to the first byte of the IP address
mov eax,[esi]
 
;DEBUGF 1,'Found First Byte of IP\n'
 
ret
 
 
ctr002c: ; Skip through the answer, move to the next
add esi, 8
movzx eax, byte [esi+1]
mov ah, [esi]
add esi, eax
add esi, 2
 
cmp esi, [dnsMsgLen] ; Have we reached the end of the msg? This is an error condition, should not happen
jl ctr002z ; Check next answer
 
abort:
;DEBUGF 1,'Something went wrong, aborting\n'
xor eax,eax
 
ret
 
 
skipName:
; Increment esi to the first byte past the name field
; Names may use compressed labels. Normally do.
; RFC 1035 page 30 gives details
mov al, [esi]
cmp al, 0
je sn_exit
and al, 0xc0
cmp al, 0xc0
je sn001
 
movzx eax, byte [esi]
inc eax
add esi, eax
jmp skipName
 
sn001:
add esi, 2 ; A pointer is always at the end
ret
 
sn_exit:
inc esi
ret
 
no_data:
eth.close [socketNum]
xor eax,eax
 
ret
 
dnsMsgLen: dd 0
socketNum: dd 0xFFFF
 
if ~defined dnsMsg
dnsMsg: rb BUFFER
end if
 
end if
 
 
 
 
/programs/network_old/airc/trunk/fdo.inc
0,0 → 1,343
;
; Formatted Debug Output (FDO)
; Copyright (c) 2005-2006, mike.dld
; Created: 2005-01-29, Changed: 2006-07-20
;
; 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
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
call fdo_debug_outstr
else
mov edx,_str
call fdo_debug_outstr
end if
popad
popf
}
 
macro DEBUGD _sign,_dec {
pushf
pushad
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
local tp
tp equ 0
match _num[_arg],_dec \{
if _num = 1
if _sign = 1
movsx eax,byte[_arg]
else
movzx eax,byte[_arg]
end if
else if _num = 2
if _sign = 1
movsx eax,word[_arg]
else
movzx eax,word[_arg]
end if
else
mov eax,dword[_arg]
end if
tp equ 1
\}
match =0 [_arg],tp _dec \{
mov eax,dword[_arg]
\}
sub esp,4*8+4
end if
mov cl,_sign
call fdo_debug_outdec
popad
popf
}
 
macro DEBUGH _sign,_hex {
pushf
pushad
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
shl eax,16
mov edx,4
else if _hex in <al,ah,bl,bh,cl,ch,dl,dh>
if ~_hex eq al
movzx eax,_hex
end if
shl eax,24
mov edx,2
end if
else if _hex eqtype 0
mov eax,_hex
mov edx,8
else
add esp,4*8+4
local tp
tp equ 0
match _num[_arg],_hex \{
mov eax,dword[_arg]
mov edx,_num
tp equ 1
\}
match =0 [_arg],tp _hex \{
mov eax,dword[_arg]
mov edx,8
\}
sub esp,4*8+4
end if
call fdo_debug_outhex
popad
popf
}
 
;-----------------------------------------------------------------------------
 
debug_func fdo_debug_outchar
debug_beginf
pushad
mov cl,al
mov ebx,1
mov eax,63
mcall
popad
ret
debug_endf
 
debug_func fdo_debug_outstr
debug_beginf
mov eax,63
mov ebx,1
.l1: mov cl,[edx]
or cl,cl
jz .l2
mcall
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
}
/programs/network_old/airc/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm airc.asm airc
@erase lang.inc
@pause
/programs/network_old/airc/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm airc.asm airc
@erase lang.inc
@pause
/programs/network_old/downloader/trunk/downloader.asm
0,0 → 1,1634
; version: 0.6 - 0.62
; last update: 04/06/2012
; written by: Lipatov Kirill aka Leency
; changes: removed old code
; added edit_box
; using system colors
; indicates file saving
; download by pressing Enter
;-----------------------------------------------------------
; version: 0.5
; date: 07/10/2010
; written by: Marat Zakiyanov aka Mario79, aka Mario
; changes: reducing the size of the binary code,
; program uses far less memory while running
; (>0x7000, the old version used >0x100000),
; process only net event at start with parameter
;-----------------------------------------------------------
; version: 0.3 -0.4
; written by: CleverMouse
;
;-----------------------------------------------------------
; wget 0.2 by barsuk
; based on Menuet Httpc
 
 
;TODO
;downloading status indication in window
 
 
; Enabling debugging puts stuff to the debug board
DEBUGGING_ENABLED equ 1
DEBUGGING_DISABLED equ 0
DEBUGGING_STATE equ DEBUGGING_ENABLED
 
use32
org 0x0
db 'MENUET01' ; header
dd 0x01 ; header version
dd START ; entry point
dd IM_END ; image size
dd I_END ;0x100000 ; required memory
dd stacktop ; esp
dd params ; I_PARAM
dd 0x0 ; I_Path
 
include 'lang.inc'
include '../../../macros.inc'
include '../../../proc32.inc'
include '../../../develop/libraries/box_lib/load_lib.mac'
include '../../../develop/libraries/box_lib/trunk/box_lib.mac'
include '../../../dll.inc'
include '../../../debug.inc'
 
URLMAXLEN equ 256 ; maximum length of url string
 
primary_buffer_size equ 4096
 
sc system_colors
 
@use_library
 
; Memory usage
; webpage headers at buf_headers
 
START: ; start of execution
;dps <"Program started",13,10>
; prepare webAddr area
load_libraries l_libs_start,l_libs_end
mov ebp,lib_0
cmp dword [ebp+ll_struc_size-4],0
jz @f
mcall -1 ;exit not correct
@@:
 
mov al,' '
mov edi,webAddr
mov ecx,URLMAXLEN
cld
rep stosb
xor eax,eax
stosb
; prepare document area
mov al,'/'
mov edi,document
cld
stosb
mov al,' '
mov ecx,URLMAXLEN-1
rep stosb
 
; create local heap
mcall 68,11
 
call load_settings
cmp [params],byte 0
jz prepare_event ;red
 
 
mcall 40, 10000000b ; only net event!!!
 
; we have an url
mov edi,document_user
mov al,' '
mov ecx,URLMAXLEN
rep stosb
mov esi,params
mov edi,document_user
 
.copy_param:
mov al,[esi]
cmp al,0
jz .done
 
cmp al,' '
jz .done_inc
 
mov [edi],al
inc esi
inc edi
jmp .copy_param
 
.done_inc:
; url is followed by shared memory name.
inc esi
.done:
mov [shared_name],esi
 
mov ah,22 ; strange way to tell that socket should be opened...
call socket_commands
 
jmp still
 
prepare_event:
; Report events
; Stack 8 + defaults
mcall 40,10100111b
 
red: ; redraw
call draw_window
 
still:
mcall 23,1 ; wait here for event
cmp eax,1 ; redraw request ?
je red
 
cmp eax,2 ; key in buffer ?
je key
 
cmp eax,3 ; button in buffer ?
je button
cmp eax,6 ; mouse in buffer ?
je mouse
 
 
; Get the web page data from the remote server
call read_incoming_data
mov eax,[status]
mov [prev_status],eax
mcall 53,6,[socket]
mov [status],eax
 
cmp [prev_status],4
jge no_send
 
cmp [status],4
jne no_send
 
mov [onoff],1
call send_request
 
no_send:
call print_status
 
cmp [prev_status],4
jne no_close
cmp [status],4 ; connection closed by server
jbe no_close ; respond to connection close command
; draw page
call read_incoming_data
mcall 53,8,[socket]
mov [onoff],0
 
no_close:
jmp still
 
key:
mcall 2 ; read key
 
stdcall [edit_box_key], dword edit1
 
shr eax,8
cmp eax,13
je retkey
jmp still
 
button:
 
mcall 17 ; get id
cmp ah,26
je save
cmp ah,1 ; button id=1 ?
jne noclose
; dps "Closing socket before exit... "
 
close_end_exit:
 
;dpd eax
;dps <13,10>
 
exit:
or eax,-1 ; close this program
mcall
mouse:
stdcall [edit_box_mouse], edit1
jmp still
 
save:
dps "file saved"
newline
mcall 70,fileinfo
 
mov ecx,[sc.work_text]
or ecx,80000000h
mcall 4,<10,93>,,download_complete
 
;pregs
jmp still
 
noclose:
cmp ah,31
jne noup
sub [display_from],20
jmp still
 
noup:
cmp ah,32
jne nourl
add [display_from],20
jmp still
 
 
retkey:
mov ah,22 ; start load
 
nourl:
call socket_commands ; opens or closes the connection
jmp still
 
;****************************************************************************
; Function
; send_request
;
; Description
; Transmits the GET request to the server.
; This is done as GET then URL then HTTP/1.1',13,10,13,10 in 3 packets
;
;****************************************************************************
send_request:
pusha
mov esi,string0
mov edi,request
movsd
; If proxy is used, make absolute URI - prepend http://<host>
cmp [proxyAddr],byte 0
jz .noproxy
mov dword [edi],'http'
mov [edi+4],byte ':'
mov [edi+5],word '//'
add edi,7
mov esi,webAddr
 
.copy_host_loop:
lodsb
cmp al,' '
jz .noproxy
stosb
jmp .copy_host_loop
 
.noproxy:
xor edx,edx ; 0
 
.next_edx:
; Determine the length of the url to send in the GET request
mov al,[edx+document]
cmp al,' '
je .document_done
mov [edi],al
inc edi
inc edx
jmp .next_edx
 
.document_done:
mov esi,stringh
mov ecx,stringh_end-stringh
rep movsb
xor edx,edx ; 0
 
.webaddr_next:
mov al,[webAddr + edx]
cmp al,' '
je .webaddr_done
mov [edi],al
inc edi
inc edx
jmp .webaddr_next
 
.webaddr_done:
cmp [proxyUser],byte 0
jz @f
call append_proxy_auth_header
@@:
mov esi,connclose
mov ecx,connclose_end-connclose
rep movsb
 
pusha
mov eax,63
mov ebx,1
mov edx,request
@@:
mov cl,[edx]
cmp edx,edi
jz @f
mcall
inc edx
jmp @b
@@:
popa
 
mov edx,edi
sub edx,request
;;;;now write \r\nConnection: Close \r\n\r\n
mcall 53,7,[socket],,request ;' HTTP/1.1 .. '
popa
ret
 
;****************************************************************************
; Function
; print_status
;
; Description
; displays the socket/data received status information
;
;****************************************************************************
print_status:
pusha
mcall 26,9
cmp eax,[nextupdate]
jb status_return
 
add eax,25
mov [nextupdate],eax
 
mov ecx,[winys]
shl ecx,16
add ecx,-18*65536+10
mcall 13,<5,100>,,0xffffff
 
mov edx,12*65536-18
add edx,[winys]
xor esi,esi
mcall 47,<3,0>,[status],,
 
mov edx,40*65536-18
add edx,[winys]
mcall ,<6,0>,[pos]
 
status_return:
popa
ret
 
;****************************************************************************
; Function
; read_incoming_data
;
; Description
; receive the web page from the server, storing it without processing
;
;****************************************************************************
read_incoming_data:
cmp [onoff],1
je rid
ret
 
rid:
push esi
push edi
dps "rid"
newline
 
newbyteread:
;call print_status
mcall 53,2,[socket]
cmp eax,0
je no_more_data
 
mcall 53,11,[socket],primary_buf,primary_buffer_size
;dps "part "
;dph eax
;newline
mov edi,[pos]
add [pos],eax
push eax
mcall 68,20,[pos],[buf_ptr]
mov [buf_ptr],eax
add edi,eax
mov esi,primary_buf
pop ecx ; number of recently read bytes
lea edx,[ecx - 3]
rep movsb
no_more_data:
mcall 53,6,[socket]
cmp eax,4
jne no_more_data.finish
jmp newbyteread
 
.finish:
;dps "finish "
;pregs
call parse_result
mov ecx,[shared_name]
test ecx, ecx
jz @f
cmp [ecx],byte 0
jnz save_in_shared
@@:
 
mcall 70,fileinfo
mov ecx,[sc.work_text]
or ecx,80000000h
mcall 4,<10,93>,,download_complete
dps "file saved"
newline
;pregs
; jmp close_end_exit
pop edi
pop esi
; if called from command line, then exit
cmp [params],byte 0
jnz exit
ret
save_in_shared:
mov esi,1 ; SHM_OPEN+SHM_WRITE
mcall 68,22
test eax,eax
jz save_in_shared_done
 
sub edx,4
jbe save_in_shared_done
 
mov ecx,[final_size]
cmp ecx,edx
jb @f
 
mov ecx,edx
@@:
mov [eax],ecx
lea edi,[eax+4]
mov esi,[final_buffer]
mov edx,ecx
shr ecx,2
rep movsd
mov ecx,edx
and ecx,3
rep movsb
 
save_in_shared_done:
pop edi
pop esi
jmp exit
; this function cuts header, and removes chunk sizes if doc is chunked
; in: buf_ptr, pos; out: buf_ptr, pos.
parse_result:
; close socket
mcall 53,8,[socket]
dps "close socket: "
dph eax
newline
mov edi,[buf_ptr]
mov edx,[pos]
mov [buf_size],edx
; mcall 70,fileinfo_tmp
dps "pos = "
dph edx
newline
 
; first, find end of headers
.next_byte:
cmp [edi],dword 0x0d0a0d0a ; ìíå ëåíü ÷èòàòü ñòàíäàðò, ïóñòü áóäóò îáà âàðèàíòà
je .end_of_headers
cmp [edi],dword 0x0a0d0a0d
je .end_of_headers
inc edi
dec edx
jne .next_byte
; no end of headers. it's an error. let client see all those headers.
ret
 
.end_of_headers:
; here we look at headers and search content-length or transfer-encoding headers
;dps "eoh "
;newline
sub edi,[buf_ptr]
add edi,4
mov [body_pos],edi ; store position where document body starts
mov [is_chunked],0
; find content-length in headers
; not good method, but should work for 'Content-Length:'
mov esi,[buf_ptr]
mov edi,s_contentlength
mov ebx,[body_pos]
xor edx,edx ; 0
.cl_next:
mov al,[esi]
cmp al,[edi + edx]
jne .cl_fail
inc edx
cmp edx,len_contentlength
je .cl_found
jmp .cl_incr
.cl_fail:
xor edx,edx ; 0
.cl_incr:
inc esi
dec ebx
je .cl_error
jmp .cl_next
.cl_error:
;pregs
;newline
;dph esi
;dps " content-length not found "
; find 'chunked'
; äà, ÿ êîïèðóþ êîä, ýòî óæàñíî, íî ìíå õî÷åòñÿ, ÷òîáû ïîñêîðåå çàðàáîòàëî
; à òàì óæ îòðåôàêòîðþ
mov esi,[buf_ptr]
mov edi,s_chunked
mov ebx,[body_pos]
xor edx,edx ; 0
 
.ch_next:
mov al,[esi]
cmp al,[edi + edx]
jne .ch_fail
inc edx
cmp edx,len_chunked
je .ch_found
jmp .ch_incr
 
.ch_fail:
xor edx,edx ; 0
 
.ch_incr:
inc esi
dec ebx
je .ch_error
jmp .ch_next
 
.ch_error:
; if neither of the 2 headers is found, it's an error
;dps "transfer-encoding: chunked not found "
mov eax,[pos]
sub eax,[body_pos]
jmp .write_final_size
 
.ch_found:
mov [is_chunked],1
mov eax,[body_pos]
add eax,[buf_ptr]
sub eax,2
mov [prev_chunk_end],eax
jmp parse_chunks
.cl_found:
call read_number ; eax = number from *esi
 
.write_final_size:
mov [final_size],eax ; if this works, i will b very happy...
mov ebx,[pos] ; we well check if it is right
sub ebx,[body_pos]
 
;dps "check cl eax==ebx "
;pregs
 
; everything is ok, so we return
mov eax,[body_pos]
mov ebx,[buf_ptr]
add ebx,eax
mov [final_buffer],ebx
; mov ebx,[pos]
; sub ebx,eax
; mov [final_size],ebx
ret
parse_chunks:
;dps "parse chunks"
;newline
; we have to look through the data and remove sizes of chunks we see
; 1. read size of next chunk
; 2. if 0, it's end. if not, continue.
; 3. make a good buffer and copy a chunk there
xor eax,eax
mov [final_buffer],eax ; 0
mov [final_size],eax ; 0
.read_size:
mov eax,[prev_chunk_end]
mov ebx,eax
sub ebx,[buf_ptr]
mov edx,eax
;dps "rs "
;pregs
cmp ebx,[pos]
jae chunks_end ; not good
call read_hex ; in: eax=pointer to text. out:eax=hex number,ebx=end of text.
cmp eax,0
jz chunks_end
 
add ebx,1
mov edx,ebx ; edx = size of size of chunk
add ebx,eax
mov [prev_chunk_end],ebx
;dps "sz "
;pregs
; do copying: from buf_ptr+edx to final_buffer+prev_final_size count eax
; realloc final buffer
push eax
push edx
push dword [final_size]
add [final_size],eax
mcall 68,20,[final_size],[final_buffer]
mov [final_buffer],eax
;dps "re "
;pregs
pop edi
pop esi
pop ecx
; add [pos],ecx
add edi,[final_buffer]
;dps "cp "
;pregs
rep movsb
jmp .read_size
chunks_end:
; free old buffer
dps "chunks end"
newline
mcall 68,13,[buf_ptr]
; done!
ret
 
; reads content-length from [edi+ecx], result in eax
read_number:
push ebx
xor eax,eax
xor ebx,ebx
 
.next:
mov bl,[esi]
;dph ebx
cmp bl,'0'
jb .not_number
cmp bl,'9'
ja .not_number
sub bl,'0'
shl eax,1
lea eax,[eax + eax * 4] ; eax *= 10
add eax,ebx
 
.not_number:
cmp bl,13
jz .done
inc esi
jmp .next
 
.done:
pop ebx
;newline
;dps "strtoint eax "
;pregs
ret
; reads hex from eax,result in eax,end of text in ebx
read_hex:
add eax,2
mov ebx,eax
mov eax,[ebx]
mov [deba],eax
; pushf
; pushad
; mov edx,deba
; call debug_outstr
; popad
; popf
xor eax,eax
xor ecx,ecx
.next:
mov cl,[ebx]
inc ebx
cmp cl,0x0d
jz .done
;dph ebx
or cl,0x20
sub cl,'0'
jb .bad
 
cmp cl,0x9
jbe .adding
 
sub cl,'a'-'0'-10
cmp cl,0x0a
jb .bad
 
cmp cl,0x0f
ja .bad
 
.adding:
shl eax,4
or eax,ecx
; jmp .not_number
;.bad:
.bad:
jmp .next
.done:
;newline
;dps "hextoint eax "
;pregs
ret
 
;****************************************************************************
; Function
; socket_commands
;
; Description
; opens or closes the socket
;
;****************************************************************************
socket_commands:
cmp ah,22 ; open socket
jnz tst3
 
dps "opening socket"
newline
; Clear all page memory
xor eax,eax
mov [prev_chunk_end],eax ; 0
cmp [buf_ptr],eax ; 0
jz no_free
 
mcall 68,13,[buf_ptr] ; free buffer
 
no_free:
xor eax,eax
mov [buf_size],eax ; 0
; Parse the entered url
call parse_url
; Get a free port number
mov ecx,1000 ; local port starting at 1000
 
getlp1:
inc ecx
push ecx
mcall 53,9
pop ecx
cmp eax,0 ; is this local port in use?
jz getlp1 ; yes - so try next
 
mov edx,80
cmp [proxyAddr],byte 0
jz sc000
mov edx,[proxyPort]
sc000:
mcall 53,5,,,[server_ip],1
mov [socket],eax
mov [pagexs],80
push eax
xor eax,eax ; 0
mov [pos],eax
mov [pagex],eax
mov [pagey],eax
mov [command_on_off],eax
mov [is_body],eax
pop eax
ret
 
tst3:
cmp ah,24 ; close socket
jnz no_24
 
mcall 53,8,[socket]
no_24:
ret
 
;****************************************************************************
; Function
; parse_url
;
; Description
; parses the full url typed in by the user into a web address ( that
; can be turned into an IP address by DNS ) and the page to display
; DNS will be used to translate the web address into an IP address, if
; needed.
; url is at document_user and will be space terminated.
; web address goes to webAddr and is space terminated.
; ip address goes to server_ip
; page goes to document and is space terminated.
;
; Supported formats:
; <protocol://>address<page>
; <protocol> is optional, removed and ignored - only http supported
; <address> is required. It can be an ip address or web address
; <page> is optional and must start with a leading / character
;
;****************************************************************************
parse_url:
; First, reset destination variables
cld
mov al,' '
mov edi,document
mov ecx,URLMAXLEN
rep stosb
mov edi,webAddr
mov ecx,URLMAXLEN
rep stosb
 
mov al,'/'
mov [document],al
 
mov esi,document_user
; remove any leading protocol text
mov ecx,URLMAXLEN
mov ax,'//'
 
pu_000:
cmp [esi],byte ' ' ; end of text?
je pu_002 ; yep, so not found
cmp [esi],ax
je pu_001 ; Found it, so esi+2 is start
inc esi
loop pu_000
 
pu_002:
; not found, so reset esi to start
mov esi,document_user-2
 
pu_001:
add esi,2
mov ebx,esi ; save address of start of web address
mov edi,document_user + URLMAXLEN ; end of string
; look for page delimiter - it's a '/' character
pu_003:
cmp [esi],byte ' ' ; end of text?
je pu_004 ; yep, so none found
cmp esi,edi ; end of string?
je pu_004 ; yep, so none found
cmp [esi],byte '/' ; delimiter?
je pu_005 ; yep - process it
inc esi
jmp pu_003
 
pu_005:
; copy page to document address
; esi = delimiter
push esi
mov ecx,edi ; end of document_user
mov edi,document
cld
 
pu_006:
movsb
cmp esi,ecx
je pu_007 ; end of string?
cmp [esi],byte ' ' ; end of text
; je pu_007 ; äçåí-àññåìáëåð
; jmp pu_006 ; íå íàäî ïëîäèòü ñóùíîñòè ïî íàïðàñíó
jne pu_006
 
pu_007:
pop esi ; point esi to '/' delimiter
 
pu_004:
; copy web address to webAddr
; start in ebx,end in esi-1
mov ecx,esi
mov esi,ebx
mov edi,webAddr
cld
 
pu_008:
movsb
cmp esi,ecx
; je pu_009 ; äçåí-àññåìáëåð
; jmp pu_008 ; íå íàäî ïëîäèòü ñóùíîñòè ïî íàïðàñíó
jne pu_008
 
pu_009:
; For debugging, display resulting strings
if DEBUGGING_STATE = DEBUGGING_ENABLED
mov esi,document_user
call debug_print_string
mov esi,webAddr
call debug_print_string
mov esi,document
call debug_print_string
end if
; Look up the ip address, or was it specified?
mov al,[proxyAddr]
cmp al,0
jnz pu_015
mov al,[webAddr]
pu_015:
cmp al,'0'
jb pu_010 ; Resolve address
cmp al,'9'
ja pu_010 ; Resolve address
 
if DEBUGGING_STATE = DEBUGGING_ENABLED
mov esi,str2 ; print gotip
call debug_print_string
end if
; Convert address
; If proxy is given, get proxy address instead of server
mov esi,proxyAddr-1
cmp byte [esi+1],0
jnz pu_020
mov esi,webAddr-1
 
pu_020:
mov edi,server_ip
xor eax,eax
 
ip1:
inc esi
cmp [esi],byte '0'
jb ip2
cmp [esi],byte '9'
jg ip2
imul eax,10
movzx ebx,byte [esi]
sub ebx,48
add eax,ebx
jmp ip1
 
ip2:
mov [edi],al
xor eax,eax
inc edi
cmp edi,server_ip+3
jbe ip1
jmp pu_011
 
pu_010:
if DEBUGGING_STATE = DEBUGGING_ENABLED
mov esi,str1 ; print resolving
call debug_print_string
end if
; Resolve Address
call translateData ; Convert domain & DNS IP address
call resolveDomain ; get ip address
 
if DEBUGGING_STATE = DEBUGGING_ENABLED
mov esi,str3
call debug_print_string
end if
 
pu_011:
; Done
ret
 
;***************************************************************************
; Function
; translateData
;
; Description
; Coverts the domain name and DNS IP address typed in by the user into
; a format suitable for the IP layer.
;
; The ename, in query, is converted and stored in dnsMsg
;
;***************************************************************************
translateData:
; first, get the IP address of the DNS server
; Then, build up the request string.
 
; Build the request string
mov eax,0x00010100
mov [dnsMsg],eax
mov eax,0x00000100
mov [dnsMsg+4],eax
mov eax,0x00000000
mov [dnsMsg+8],eax
; domain name goes in at dnsMsg+12
mov esi,dnsMsg +12 ;location of label length
mov edi,dnsMsg + 13 ;label start
mov edx,proxyAddr
cmp byte [edx],0
jnz td000
mov edx,webAddr
 
td000:
mov ecx,12 ; total string length so far
 
td002:
mov [esi],byte 0
inc ecx
 
td0021:
mov al,[edx]
cmp al,' '
je td001 ; we have finished the string translation
 
cmp al,0
je td001
 
cmp al,'.' ; we have finished the label
je td004
 
inc byte [esi]
inc ecx
mov [edi],al
inc edi
inc edx
jmp td0021
 
td004:
mov esi,edi
inc edi
inc edx
jmp td002
 
; write label len + label text
td001:
mov [edi],byte 0
inc ecx
inc edi
mov [edi],dword 0x01000100
add ecx,4
mov [dnsMsgLen],ecx
ret
 
;***************************************************************************
; Function
; resolveDomain
;
; Description
; Sends a question to the dns server
; works out the IP address from the response from the DNS server
;
;***************************************************************************
resolveDomain:
; Get a free port number
mov ecx,1000 ; local port starting at 1000
getlp:
inc ecx
push ecx
mcall 53,9
pop ecx
cmp eax,0 ; is this local port in use?
jz getlp ; yes - so try next
 
; Get DNS IP
mcall 52,13
mov esi,eax
; First, open socket
mov edx,53 ; remote port - dns
; mov esi,dword [dns_ip]
xor ebx,ebx ; 0
mcall 53
mov [socketNum],eax
; write to socket ( request DNS lookup )
mcall 53,4,[socketNum],[dnsMsgLen],dnsMsg
; Setup the DNS response buffer
mov eax,dnsMsg
mov [dnsMsgLen],eax
; now, we wait for
; UI redraw
; UI close
; or data from remote
 
ctr001:
mcall 10 ; wait here for event
cmp eax,1 ; redraw request ?
je ctr003
 
cmp eax,2 ; key in buffer ?
je ctr004
 
cmp eax,3 ; button in buffer ?
je ctr005
; Any data in the UDP receive buffer?
mcall 53,2,[socketNum]
cmp eax,0
je ctr001
 
; we have data - this will be the response
ctr002:
mcall 53,3,[socketNum] ; read byte - block (high byte)
; Store the data in the response buffer
mov eax,[dnsMsgLen]
mov [eax],bl
inc dword [dnsMsgLen]
 
mcall 53,2,[socketNum] ; any more data?
cmp eax,0
jne ctr002 ; yes, so get it
 
; close socket
mcall 53,1,[socketNum]
mov [socketNum],dword 0xFFFF
; Now parse the message to get the host IP
; Man, this is complicated. It's described in
; RFC 1035
if DEBUGGING_STATE = DEBUGGING_ENABLED
mov esi,str4
call debug_print_string
end if
 
; 1) Validate that we have an answer with > 0 responses
; 2) Find the answer record with TYPE 0001 ( host IP )
; 3) Finally, copy the IP address to the display
; Note: The response is in dnsMsg
; The end of the buffer is pointed to by [dnsMsgLen]
 
; Clear the IP address text
mov [server_ip],dword 0
mov esi,dnsMsg
; Is this a response to my question?
mov al,[esi+2]
and al,0x80
cmp al,0x80
jne ctr002a
; Were there any errors?
mov al,[esi+3]
and al,0x0F
cmp al,0x00
jne ctr002a
; Is there ( at least 1 ) answer?
mov ax,[esi+6]
cmp ax,0x00
je ctr002a
; Header valdated. Scan through and get my answer
if DEBUGGING_STATE = DEBUGGING_ENABLED
pusha
mov esi,str4
call debug_print_string
popa
end if
add esi,12 ; Skip to the question field
; Skip through the question field
call skipName
add esi,4 ; skip past the questions qtype, qclass
 
ctr002z:
; Now at the answer. There may be several answers,
; find the right one ( TYPE = 0x0001 )
call skipName
mov ax,[esi]
cmp ax,0x0100 ; Is this the IP address answer?
jne ctr002c
; Yes! Point esi to the first byte of the IP address
add esi,10
mov eax,[esi]
mov [server_ip],eax
ret
 
ctr002c: ; Skip through the answer, move to the next
add esi,8
movzx eax,byte [esi+1]
mov ah,[esi]
add esi,eax
add esi,2
; Have we reached the end of the msg?
; This is an error condition, should not happen
cmp esi,[dnsMsgLen]
jl ctr002z ; Check next answer
jmp ctr002a ; abort
 
ctr002a:
jmp ctr001
 
ctr003: ; redraw
call draw_window
jmp ctr001
 
ctr004: ; key
mcall 2 ; just read it and ignore
jmp ctr001
 
ctr005: ; button
mcall 17 ; get id
mov dl,ah
 
; close socket
mcall 53,1,[socketNum]
cmp dl,1
je exit
 
mov [socketNum],dword 0xFFFF
mov [server_ip],dword 0
ret
 
;***************************************************************************
; Function
; skipName
;
; Description
; Increment esi to the first byte past the name field
; Names may use compressed labels. Normally do.
; RFC 1035 page 30 gives details
;
;***************************************************************************
skipName:
mov al,[esi]
cmp al,0
je sn_exit
and al,0xc0
cmp al,0xc0
je sn001
 
movzx eax,byte [esi]
inc eax
add esi,eax
jmp skipName
 
sn001:
add esi,2 ; A pointer is always at the end
ret
 
sn_exit:
inc esi
ret
 
;***************************************************************************
; Function
; load_settings
;
; Description
; Load settings from configuration file network.ini
;
;***************************************************************************
load_settings:
stdcall dll.Load,@IMPORT
test eax,eax
jnz ls001
invoke ini.get_str,inifile,sec_proxy,key_proxy,proxyAddr,256,proxyAddr
invoke ini.get_int,inifile,sec_proxy,key_proxyport,80
mov [proxyPort],eax
invoke ini.get_str,inifile,sec_proxy,key_user, proxyUser,256,proxyUser
invoke ini.get_str,inifile,sec_proxy,key_password,proxyPassword,256,proxyPassword
ls001:
ret
 
;***************************************************************************
; Function
; append_proxy_auth_header
;
; Description
; Append header to HTTP request for proxy authentification
;
;***************************************************************************
append_proxy_auth_header:
mov esi,proxy_auth_basic
mov ecx,proxy_auth_basic_end - proxy_auth_basic
rep movsb
; base64-encode string <user>:<password>
mov esi,proxyUser
 
apah000:
lodsb
test al,al
jz apah001
call encode_base64_byte
jmp apah000
 
apah001:
mov al,':'
call encode_base64_byte
mov esi,proxyPassword
 
apah002:
lodsb
test al,al
jz apah003
call encode_base64_byte
jmp apah002
 
apah003:
call encode_base64_final
ret
 
encode_base64_byte:
inc ecx
shl edx,8
mov dl,al
cmp ecx,3
je ebb001
ret
 
ebb001:
shl edx,8
inc ecx
 
ebb002:
rol edx,6
xor eax,eax
xchg al,dl
mov al,[base64_table+eax]
stosb
loop ebb002
ret
 
encode_base64_final:
mov al,0
test ecx,ecx
jz ebf000
call encode_base64_byte
test ecx,ecx
jz ebf001
call encode_base64_byte
mov byte [edi-2],'='
 
ebf001:
mov byte [edi-1],'='
 
ebf000:
ret
 
if DEBUGGING_STATE = DEBUGGING_ENABLED
 
;****************************************************************************
; Function
; debug_print_string
;
; Description
; prints a string to the debug board, in quotes
;
; esi holds ptr to msg to display, which is space or 0 terminated
;
; Nothing preserved; I'm assuming a pusha/popa is done before calling
;
;****************************************************************************
debug_print_string:
push esi
mov cl,'"'
mcall 63,1
pop esi
 
dps_000:
mov cl,[esi]
cmp cl,0
je dps_exit
 
cmp cl,' '
je dps_exit
jmp dps_001
 
dps_exit:
mov cl,'"'
mcall 63,1
mov cl,13
mcall
mov cl,10
mcall
ret
 
dps_001:
push esi
mcall 63,1
pop esi
inc esi
jmp dps_000
end if
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
draw_window:
 
; cmp [params],byte 0
; jz .noret
 
;.noret:
 
mcall 12,1
 
mcall 48,3,sc,40 ;get system colors
 
mov edx,[sc.work]
or edx,0x34000000
mcall 0,<50,370>,<350,140>,,0,title ;draw window
mov ecx,[sc.work_text]
or ecx,80000000h
mcall 4, <14,14>, ,type_pls ;"URL:"
 
;mov ecx,[winys]
;shl ecx,16
;add ecx,[winys]
;sub ecx,26*65536+26
;mcall 38,<5,545>
edit_boxes_set_sys_color edit1,editboxes_end,sc
stdcall [edit_box_draw], edit1
 
; RELOAD
mcall 8,<90,68>,<54,16>,22,[sc.work_button]
; STOP
mcall ,<166,50>,<54,16>,24
; SAVE
mcall ,<224,54>,,26
; BUTTON TEXT
mov ecx,[sc.work_button_text]
or ecx,80000000h
mcall 4,<102,59>,,button_text
 
mcall 12,2 ; end window redraw
ret
;-----------------------------------------------------------------------------
; Data area
;-----------------------------------------------------------------------------
align 4
@IMPORT:
 
library libini,'libini.obj'
 
import libini, \
ini.get_str,'ini_get_str', \
ini.get_int,'ini_get_int'
 
;---------------------------------------------------------------------
fileinfo dd 2,0,0
final_size dd 0
final_buffer dd 0
db '/rd/1/.download',0
body_pos dd 0
 
;fileinfo_tmp dd 2,0,0
buf_size dd 0
buf_ptr dd 0
; db '/rd/1/1',0
 
deba dd 0
db 0
;---------------------------------------------------------------------
if DEBUGGING_STATE = DEBUGGING_ENABLED
str1: db "Resolving...",0
str3: db "Resolved",0
str2: db "GotIP",0
str4: db "GotResponse",0
end if
;---------------------------------------------------------------------
;Leency editbox
mouse_dd dd 0
edit1 edit_box 295, 48, 10, 0xffffff, 0xff, 0x80ff, 0, 0x8000, URLMAXLEN, document_user, mouse_dd, ed_focus+ed_always_focus,7,7
editboxes_end:
 
head_f_i: head_f_l db 'System error',0
system_dir_0 db '/sys/lib/'
lib_name_0 db 'box_lib.obj',0
err_msg_found_lib_0 db '¥ ­ ©¤¥­  ¡¨¡«¨®â¥ª  ',39,'box_lib.obj',39,0
err_msg_import_0 db 'Žè¨¡ª  ¯à¨ ¨¬¯®à⥠¡¨¡«¨®â¥ª¨ ',39,'box_lib',39,0
 
l_libs_start:
lib_0 l_libs lib_name_0, sys_path, library_path, system_dir_0,\
err_msg_found_lib_0,head_f_l,import_box_lib,err_msg_import_0,head_f_i
l_libs_end:
 
align 4
import_box_lib:
;dd sz_init1
edit_box_draw dd sz_edit_box_draw
edit_box_key dd sz_edit_box_key
edit_box_mouse dd sz_edit_box_mouse
;edit_box_set_text dd sz_edit_box_set_text
dd 0,0
;sz_init1 db 'lib_init',0
sz_edit_box_draw db 'edit_box',0
sz_edit_box_key db 'edit_box_key',0
sz_edit_box_mouse db 'edit_box_mouse',0
;sz_edit_box_set_text db 'edit_box_set_text',0
 
sys_path rb 4096
library_path rb 4096
;---------------------------------------------------------------------
 
type_pls db 'URL:',0
button_text db 'DOWNLOAD STOP RESAVE',0
download_complete db 'File saved as /rd/1/.download',0
display_from dd 20
pos dd 0x0
pagex dd 0x0
pagey dd 0x0
pagexs dd 80
command_on_off dd 0x0
text_type db 1
com2 dd 0x0
script dd 0x0
socket dd 0x0
 
addr dd 0x0
ya dd 0x0
len dd 0x00
 
title db 'Network Downloader',0
 
server_ip: db 207,44,212,20
;dns_ip: db 194,145,128,1
;---------------------------------------------------------------------
;webAddr:
;times URLMAXLEN db ' '
;db 0
 
;document: db '/'
;times URLMAXLEN-1 db ' '
;---------------------------------------------------------------------
s_contentlength db 'Content-Length:'
len_contentlength = 15
 
s_chunked db 'Transfer-Encoding: chunked'
len_chunked = $ - s_chunked
 
is_body dd 0 ; 0 if headers, 1 if content
is_chunked dd 0
prev_chunk_end dd 0
cur_chunk_size dd 0
 
string0: db 'GET '
 
stringh: db ' HTTP/1.1',13,10,'Host: '
stringh_end:
proxy_auth_basic: db 13,10,'Proxy-Authorization: Basic '
proxy_auth_basic_end:
connclose: db 13,10,'User-Agent: Kolibrios Downloader',13,10,'Connection: Close',13,10,13,10
connclose_end:
 
base64_table db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
db '0123456789+/'
 
inifile db '/sys/network/zeroconf.ini',0
 
sec_proxy:
key_proxy db 'proxy',0
key_proxyport db 'port',0
key_user db 'user',0
key_password db 'password',0
 
 
proxyPort dd 80
 
shared_name dd 0
 
;yandex: db 'menuetos.net'
;yandex_end:
 
status dd 0x0
prev_status dd 0x0
 
onoff dd 0x0
 
nextupdate: dd 0
winys: dd 400
 
dnsMsgLen: dd 0
socketNum: dd 0xFFFF
;---------------------------------------------------------------------
document_user db 'http://',0
;---------------------------------------------------------------------
IM_END:
rb URLMAXLEN-(IM_END - document_user)
;---------------------------------------------------------------------
align 4
document:
rb URLMAXLEN
;---------------------------------------------------------------------
align 4
webAddr:
rb URLMAXLEN+1
;---------------------------------------------------------------------
align 4
primary_buf:
rb primary_buffer_size
;---------------------------------------------------------------------
align 4
params: ; db 1024 dup(0)
rb 1024
;---------------------------------------------------------------------
align 4
request: ; db 256 dup(0)
rb 256
;---------------------------------------------------------------------
align 4
proxyAddr: ; db 256 dup(0)
rb 256
;---------------------------------------------------------------------
align 4
proxyUser: ; db 256 dup(0)
rb 256
;---------------------------------------------------------------------
align 4
proxyPassword: ; db 256 dup(0)
rb 256
;---------------------------------------------------------------------
align 4
dnsMsg:
rb 4096
; rb 0x100000
;---------------------------------------------------------------------
align 4
rb 4096
stacktop:
;---------------------------------------------------------------------
I_END:
;---------------------------------------------------------------------
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/downloader/trunk/build.bat
0,0 → 1,6
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm downloader.asm downloader
@kpack downloader
@erase lang.inc
@pause
/programs/network_old/downloader/trunk/build.sh
0,0 → 1,13
#!/bin/bash
# This script does for linux the same as build.bat for DOS,
# it compiles the KoOS kernel, hopefully ;-)
 
echo "lang fix ru"
echo "lang fix ru" > lang.inc
fasm -m 16384 downloader.asm downloader
rm -f lang.inc
exit 0
 
 
 
 
/programs/network_old/zeroconf/trunk/zeroconf.asm
0,0 → 1,492
; Zero-config
; v 1.4
;
; DHCP code is based on that by Mike Hibbet (DHCP client for menuetos)
;
; Written by HidnPlayr & Derpenguin
 
use32
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd IM_END ; size of image
dd I_END ; memory for app
dd I_END ; esp
dd 0x0 , path ; I_Param , I_Icon
 
; CONFIGURATION
 
 
TIMEOUT equ 60 ; in seconds
BUFFER equ 1024 ; in bytes
__DEBUG__ equ 1 ; enable/disable
__DEBUG_LEVEL__ equ 1 ; 1 = all, 2 = errors
 
; CONFIGURATION FOR LINK-LOCAL
 
PROBE_WAIT equ 1 ; second (initial random delay)
PROBE_MIN equ 1 ; second (minimum delay till repeated probe)
PROBE_MAX equ 2 ; seconds (maximum delay till repeated probe)
PROBE_NUM equ 3 ; (number of probe packets)
 
ANNOUNCE_NUM equ 2 ; (number of announcement packets)
ANNOUNCE_INTERVAL equ 2 ; seconds (time between announcement packets)
ANNOUNCE_WAIT equ 2 ; seconds (delay before announcing)
 
MAX_CONFLICTS equ 10 ; (max conflicts before rate limiting)
 
RATE_LIMIT_INTERVAL equ 60 ; seconds (delay between successive attempts)
 
DEFEND_INTERVAL equ 10 ; seconds (min. wait between defensive ARPs)
 
include '../../../proc32.inc'
include '../../../macros.inc'
include 'ETH.INC'
include 'debug-fdo.inc'
include 'dhcp.inc'
include '../../../dll.inc'
 
START: ; start of execution
 
mcall 40, 0
 
eth.set_network_drv 0x00000383
 
DEBUGF 1,"Zero-config service:\n"
 
eth.status eax ; Read the Stack status
test eax,eax ; if eax is zero, no driver was found
jnz @f
DEBUGF 1,"No Card found!\n"
jmp close
 
@@:
DEBUGF 1,"Detected card: %x\n",eax
@@:
eth.check_cable eax
test al,al
jnz @f
DEBUGF 1,"Cable disconnected!\n"
mcall 5, 500 ; loop until cable is connected (check every 5 sec)
jmp @r
 
@@:
eth.read_mac MAC
DEBUGF 1,"MAC: %x-%x-%x-%x-%x-%x\n",[MAC]:2,[MAC+1]:2,[MAC+2]:2,[MAC+3]:2,[MAC+4]:2,[MAC+5]:2
 
cld
mov edi, path ; Calculate the length of zero-terminated string
xor al , al
mov ecx, 1024
repnz scas byte[es:edi]
dec edi
 
mov esi, filename
mov ecx, 5
rep movsb
 
mcall 68,11
 
stdcall dll.Load,@IMPORT
or eax,eax
jnz skip_ini
 
 
invoke ini.get_str, path, str_ipconfig, str_type, inibuf, 16, 0
 
mov eax,dword[inibuf]
 
cmp eax,'stat'
jne skip_ini
 
invoke ini.get_str, path, str_ipconfig, str_ip, inibuf, 16, 0
mov edx, inibuf
call Ip2dword
eth.set_IP edx
 
invoke ini.get_str, path, str_ipconfig, str_gateway, inibuf, 16, 0
mov edx, inibuf
call Ip2dword
eth.set_GATEWAY edx
 
invoke ini.get_str, path, str_ipconfig, str_dns, inibuf, 16, 0
mov edx, inibuf
call Ip2dword
eth.set_DNS edx
 
invoke ini.get_str, path, str_ipconfig, str_subnet, inibuf, 16, 0
mov edx, inibuf
call Ip2dword
eth.set_SUBNET edx
 
 
mcall -1
 
 
skip_ini:
 
eth.check_port 68,eax ; Check if port 68 is available
cmp eax,1
je @f
 
DEBUGF 1,"Port 68 is already in use!\n"
jmp close
 
@@:
eth.open_udp 68,67,-1,[socketNum] ; open socket (local,remote,ip,socket)
; Setup the first msg we will send
mov byte [dhcpMsgType], 0x01 ; DHCP discover
mov dword [dhcpLease], esi ; esi is still -1 (-1 = forever)
 
mcall 26, 9
imul eax,100
mov [currTime],eax
 
buildRequest: ; Creates a DHCP request packet.
stdcall mem.Alloc, BUFFER
mov [dhcpMsg], eax
test eax,eax
jz apipa
 
 
mov edi, eax
mov ecx,BUFFER
xor eax,eax
cld
rep stosb
 
mov edx,[dhcpMsg]
 
mov [edx], byte 0x01 ; Boot request
mov [edx+1], byte 0x01 ; Ethernet
mov [edx+2], byte 0x06 ; Ethernet h/w len
mov [edx+4], dword 0x11223344 ; xid
mov eax,[currTime]
mov [edx+8], eax ; secs, our uptime
mov [edx+10], byte 0x80 ; broadcast flag set
mov eax, dword [MAC] ; first 4 bytes of MAC
mov [edx+28],dword eax
mov ax, word [MAC+4] ; last 2 bytes of MAC
mov [edx+32],word ax
mov [edx+236], dword 0x63538263 ; magic number
mov [edx+240], word 0x0135 ; option DHCP msg type
mov al, [dhcpMsgType]
mov [edx+240+2], al
mov [edx+240+3], word 0x0433 ; option Lease time = infinity
mov eax, [dhcpLease]
mov [edx+240+5], eax
mov [edx+240+9], word 0x0432 ; option requested IP address
mov eax, [dhcpClientIP]
mov [edx+240+11], eax
mov [edx+240+15], word 0x0437 ; option request list
mov [edx+240+17], dword 0x0f060301
 
cmp [dhcpMsgType], byte 0x01 ; Check which msg we are sending
jne request_options
 
mov [edx+240+21], byte 0xff ; "Discover" options
 
mov [dhcpMsgLen], dword 262 ; end of options marker
jmp send_request
 
request_options:
mov [edx+240+21], word 0x0436 ; server IP
mov eax, [dhcpServerIP]
mov [edx+240+23], eax
 
mov [edx+240+27], byte 0xff ; end of options marker
 
mov [dhcpMsgLen], dword 268
 
send_request:
eth.write_udp [socketNum],[dhcpMsgLen],[dhcpMsg] ; write to socket ( send broadcast request )
 
mov eax, [dhcpMsg] ; Setup the DHCP buffer to receive response
mov [dhcpMsgLen], eax ; Used as a pointer to the data
 
mov eax,23 ; wait here for event (data from remote)
mov ebx,TIMEOUT*10
mcall
 
eth.poll [socketNum]
 
test eax,eax
jnz read_data
 
DEBUGF 2,"Timeout!\n"
eth.close_udp [socketNum]
jmp apipa ; no server found, lets try zeroconf
 
 
read_data: ; we have data - this will be the response
eth.read_packet [socketNum], [dhcpMsg], BUFFER
mov [dhcpMsgLen], eax
eth.close_udp [socketNum]
 
; depending on which msg we sent, handle the response
; accordingly.
; If the response is to a dhcp discover, then:
; 1) If response is DHCP OFFER then
; 1.1) record server IP, lease time & IP address.
; 1.2) send a request packet
; If the response is to a dhcp request, then:
; 1) If the response is DHCP ACK then
; 1.1) extract the DNS & subnet fields. Set them in the stack
 
cmp [dhcpMsgType], byte 0x01 ; did we send a discover?
je discover
cmp [dhcpMsgType], byte 0x03 ; did we send a request?
je request
 
jmp close ; really unknown, what we did
 
discover:
call parseResponse
 
cmp [dhcpMsgType], byte 0x02 ; Was the response an offer?
jne apipa ; NO - so we do zeroconf
mov [dhcpMsgType], byte 0x03 ; DHCP request
jmp buildRequest
 
request:
call parseResponse
 
cmp [dhcpMsgType], byte 0x05 ; Was the response an ACK? It should be
jne apipa ; NO - so we do zeroconf
 
jmp close
 
;***************************************************************************
; Function
; parseResponse
;
; Description
; extracts the fields ( client IP address and options ) from
; a DHCP response
; The values go into
; dhcpMsgType,dhcpLease,dhcpClientIP,dhcpServerIP,
; dhcpDNSIP, dhcpSubnet
; The message is stored in dhcpMsg
;
;***************************************************************************
parseResponse:
DEBUGF 1,"Data received, parsing response\n"
mov edx, [dhcpMsg]
 
pusha
eth.set_IP [edx+16]
mov eax,[edx]
mov [dhcpClientIP],eax
DEBUGF 1,"Client: %u.%u.%u.%u\n",[edx+16]:1,[edx+17]:1,[edx+18]:1,[edx+19]:1
popa
 
add edx, 240 ; Point to first option
xor ecx, ecx
 
next_option:
add edx, ecx
pr001:
mov al, [edx]
cmp al, 0xff ; End of options?
je pr_exit
 
cmp al, dhcp_msg_type ; Msg type is a single byte option
jne @f
 
mov al, [edx+2]
mov [dhcpMsgType], al
add edx, 3
jmp pr001 ; Get next option
 
@@:
inc edx
movzx ecx, byte [edx]
inc edx ; point to data
 
cmp al, dhcp_dhcp_server_id ; server ip
jne @f
mov eax, [edx]
mov [dhcpServerIP], eax
DEBUGF 1,"Server: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
jmp next_option
 
@@:
cmp al, dhcp_address_time
jne @f
 
pusha
mov eax,[edx]
bswap eax
mov [dhcpLease],eax
DEBUGF 1,"lease: %d\n",eax
popa
 
jmp next_option
 
@@:
cmp al, dhcp_subnet_mask
jne @f
 
pusha
eth.set_SUBNET [edx]
DEBUGF 1,"Subnet: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
popa
 
jmp next_option
 
@@:
cmp al, dhcp_router
jne @f
 
pusha
eth.set_GATEWAY [edx]
DEBUGF 1,"Gateway: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
popa
 
jmp next_option
 
 
@@:
cmp al, dhcp_domain_server
jne next_option
 
pusha
eth.set_DNS [edx]
DEBUGF 1,"DNS: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
popa
 
jmp next_option
 
pr_exit:
 
; DEBUGF 1,"Sending ARP announce\n"
; eth.ARP_ANNOUNCE [dhcpClientIP] ; send an ARP announce packet
 
jmp close
 
apipa:
stdcall mem.Free, [dhcpMsg]
 
link_local:
call random
mov ecx,0xfea9 ; IP 169.254.0.0 link local net, see RFC3927
mov cx,ax
eth.set_IP ecx ; mask is 255.255.0.0
DEBUGF 1,"Link Local IP assigned: 169.254.%u.%u\n",[generator+2]:1,[generator+3]:1
eth.set_SUBNET 0xffff
eth.set_GATEWAY 0x0
eth.set_DNS 0x0
 
mcall 5, PROBE_WAIT*100
 
xor esi,esi
probe_loop:
call random ; create a pseudo random number in eax (seeded by MAC)
 
cmp al,PROBE_MIN*100 ; check if al is bigger then PROBE_MIN
jge @f ; all ok
add al,(PROBE_MAX-PROBE_MIN)*100 ; al is too small
@@:
 
cmp al,PROBE_MAX*100
jle @f
sub al,(PROBE_MAX-PROBE_MIN)*100
@@:
 
movzx ebx,al
DEBUGF 1,"Waiting %u0ms\n",ebx
mcall 5
 
DEBUGF 1,"Sending Probe\n"
; eth.ARP_PROBE MAC
inc esi
 
cmp esi,PROBE_NUM
jl probe_loop
 
; now we wait further ANNOUNCE_WAIT seconds and send ANNOUNCE_NUM ARP announces. If any other host has assigned
; IP within this time, we should create another adress, that have to be done later
 
DEBUGF 1,"Waiting %us\n",ANNOUNCE_WAIT
mcall 5, ANNOUNCE_WAIT*100
xor esi,esi
announce_loop:
 
DEBUGF 1,"Sending Announce\n"
; eth.ARP_ANNOUNCE MAC
 
inc esi
cmp esi,ANNOUNCE_NUM
je @f
 
DEBUGF 1,"Waiting %us\n",ANNOUNCE_INTERVAL
mcall 5, ANNOUNCE_INTERVAL*100
jmp announce_loop
@@:
; we should, instead of closing, detect ARP conflicts and detect if cable keeps connected ;)
 
close:
mcall -1
 
 
random: ; Pseudo random actually
 
mov eax,[generator]
add eax,-43ab45b5h
ror eax,1
bswap eax
xor eax,dword[MAC]
ror eax,1
xor eax,dword[MAC+2]
mov [generator],eax
 
ret
 
; DATA AREA
 
align 16
@IMPORT:
 
library \
libini,'libini.obj'
 
import libini, \
ini.get_str,'ini_get_str'
 
include_debug_strings
 
filename db '.ini',0
str_ip db 'ip',0
str_subnet db 'subnet',0
str_gateway db 'gateway',0
str_dns db 'dns',0
str_ipconfig db 'ipconfig',0
str_type db 'type',0
 
 
IM_END:
 
inibuf rb 16
 
dhcpClientIP dd ?
dhcpMsgType db ?
dhcpLease dd ?
dhcpServerIP dd ?
 
dhcpMsgLen dd ?
socketNum dd ?
 
MAC dp ?
currTime dd ?
renewTime dd ?
generator dd ?
 
dhcpMsg dd ?
 
I_END_2:
 
path rb 1024+5
 
I_END:
/programs/network_old/zeroconf/trunk/build.bat
0,0 → 1,2
@fasm zeroconf.asm zeroconf
@pause
/programs/network_old/zeroconf/trunk/ETH.INC
0,0 → 1,413
;
; ETH.INC
;
; made by hidnplayr (hidnplayr@kolibrios.org) for KolibriOS
;
; The given code before every macro is only a simple example
;
;
; HISTORY
;
; v1.0: august 2006 original release
; v1.1: december 2006 bugfixes and improvements
; v1.2: february 2007 more bugfixes and improvements
 
macro mov arg1,arg2 {
if arg1 eq arg2
else
mov arg1,arg2
end if
}
 
TCB_LISTEN = 1
TCB_SYN_SENT = 2
TCB_SYN_RECEIVED = 3
TCB_ESTABLISHED = 4
TCB_FIN_WAIT_1 = 5
TCB_FIN_WAIT_2 = 6
TCB_CLOSE_WAIT = 7
TCB_CLOSING = 8
TCB_LAST_ASK = 9
TCB_TIME_WAIT = 10
TCB_CLOSED = 11
 
PASSIVE = 0
ACTIVE = 1
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
macro eth.get_IP IP {
mov ebx,1
mov eax,52
mcall
 
mov IP ,eax
}
 
macro eth.get_GATEWAY GATEWAY {
mov ebx,9
mov eax,52
mcall
mov GATEWAY ,eax
}
 
macro eth.get_SUBNET SUBNET {
mov ebx,10
mov eax,52
mcall
mov SUBNET ,eax
}
 
macro eth.get_DNS DNS {
mov ebx,13
mov eax,52
mcall
mov DNS ,eax
}
 
macro eth.set_IP IP {
mov ecx,IP
mov ebx,3
mov eax,52
mcall
}
 
macro eth.set_GATEWAY GATEWAY {
mov ecx,GATEWAY
mov ebx,11
mov eax,52
mcall
}
 
macro eth.set_SUBNET SUBNET {
mov ecx,SUBNET
mov ebx,12
mov eax,52
mcall
}
 
macro eth.set_DNS DNS {
mov ecx,DNS
mov ebx,14
mov eax,52
mcall
}
 
macro eth.set_network_drv conf {
mov ecx,conf
mov ebx,2
mov eax,52
mcall
}
 
macro eth.open_udp local,remote,ip,socket {
mov ecx, local
mov edx, remote
mov esi, ip
mov ebx, 0
mov eax, 53
mcall
 
mov socket,eax
}
 
macro eth.close_udp socket {
mov ecx, socket
mov ebx, 1
mov eax, 53
mcall
}
 
macro eth.poll socket {
mov ecx, socket
mov ebx, 2
mov eax, 53
mcall
}
 
macro eth.read_byte socket, result {
mov ecx, socket
mov ebx, 3
mov eax, 53
mcall
 
mov result,bl
}
 
macro eth.read_packet socket, result, buffersize {
mov esi, buffersize
mov edx, result
mov ecx, socket
mov ebx, 11
mov eax, 53
mcall
}
 
macro eth.write_udp socket,length,msg,verify {
mov ecx, socket
mov edx, length
mov esi, msg
mov ebx, 4
mov eax, 53
mcall
 
if verify eq 1
call verifysend
end if
 
}
 
verifysend:
test eax,eax
jnz @f
ret
@@:
pusha
mov eax,5
mov ebx,100
mcall
popa
mcall
ret
 
macro eth.open_tcp local,remote,ip,passive,socket {
 
mov ecx, local
mov edx, remote
mov esi, ip
mov edi, passive ; 0 = PASSIVE open
mov ebx, 5
mov eax, 53
mcall
 
mov socket,eax
}
 
macro eth.socket_status socket,result {
mov ecx, socket
mov ebx, 6
mov eax, 53
mcall
 
mov result,eax
}
 
macro eth.write_tcp socket,length,msg,verify {
mov ecx, socket
mov edx, length
mov esi, msg
mov ebx, 7
mov eax, 53
mcall
 
if verify eq 1
call verifysend
end if
}
 
macro eth.read_mac mac {
mov eax, 52
mov ebx, 15
xor ecx, ecx
pusha
mcall
mov dword[mac],eax
popa
add cl, 4
mcall
mov word[mac+4],ax
 
}
 
macro eth.close_tcp socket {
mov ecx, socket
mov ebx, 8
mov eax, 53
mcall
}
 
macro eth.check_port port,result {
mov ecx, port
mov ebx, 9
mov eax, 53
mcall
 
mov result,eax
}
 
macro eth.check_cable result {
mov ebx, 10
mov eax, 53
mcall
 
mov result,eax
}
 
macro eth.status status {
mov ebx, 255
mov ecx, 6
mov eax, 53
mcall
 
mov status,eax
}
 
macro eth.search_port port,result {
mov edx,port
@@:
inc edx
eth.check_port edx,eax
cmp eax,0
je @r
mov result,edx
}
 
macro eth.ARP_PROBE address{
 
mov edx,address
mov eax,52
mov ebx,16
xor ecx,ecx
mcall
 
}
 
 
macro eth.ARP_ANNOUNCE address{
 
mov edx,address
mov eax,52
mov ebx,16
xor ecx,ecx
inc ecx
mcall
 
}
 
macro eth.read_data socket,dest,endptr,bufferl {
local .getdata,.loop,.end
mov eax, dest
mov endptr, eax
 
.getdata:
cmp endptr, bufferl
jg .end
 
eth.read_packet socket, endptr, 0
add endptr,eax
 
test eax, eax
jnz .getdata
 
xor edx, edx
.loop:
eth.poll socket
 
test eax, eax
jnz .getdata
 
mov eax,5
mov ebx,1
mcall
 
inc edx
cmp edx,30
jl .loop
 
.end:
}
 
macro eth.wait_for_data socket,TIMEOUT,abort {
mov edx,TIMEOUT
 
@@:
eth.poll socket
 
cmp eax,0
jne @f
 
dec edx
jz abort
 
mov eax,5 ; wait here for event
mov ebx,10
mcall
 
jmp @r
@@:
 
}
 
 
 
Ip2dword:
push edx
 
; This code validates if the query is an IP containing 4 numbers and 3 dots
 
xor al, al ; make al (dot count) zero
 
@@:
cmp byte[edx],'0' ; check if this byte is a number, if not jump to no_IP
jl no_IP ;
cmp byte[edx],'9' ;
jg no_IP ;
 
inc edx ; the byte was a number, so lets check the next byte
 
cmp byte[edx],0 ; is this byte zero? (have we reached end of query?)
jz @f ; jump to next @@ then
cmp byte[edx],':'
jz @f
 
cmp byte[edx],'.' ; is this byte a dot?
jne @r ; if not, jump to previous @@
 
inc al ; the byte was a dot so increment al(dot count)
inc edx ; next byte
jmp @r ; lets check for numbers again (jump to previous @@)
 
@@: ; we reach this when end of query reached
cmp al,3 ; check if there where 3 dots
jnz no_IP ; if not, jump to no_IP
 
; The following code will convert this IP into a dword and output it in eax
; If there is also a port number specified, this will be returned in ebx, otherwise ebx is -1
 
pop esi ; edx (query address) was pushed onto stack and is now popped in esi
 
xor edx, edx ; result
xor eax, eax ; current character
xor ebx, ebx ; current byte
 
.outer_loop:
shl edx, 8
add edx, ebx
xor ebx, ebx
.inner_loop:
lodsb
test eax, eax
jz .finish
cmp al, '.'
jz .outer_loop
sub eax, '0'
imul ebx, 10
add ebx, eax
jmp .inner_loop
.finish:
shl edx, 8
add edx, ebx
 
bswap edx ; we want little endian order
 
ret
 
no_IP:
pop edx
xor edx, edx
 
ret
 
 
 
 
/programs/network_old/zeroconf/trunk/debug-fdo.inc
0,0 → 1,422
;
; 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
else if _hex in <ax,bx,cx,dx,si,di,bp,sp>
if ~_hex eq ax
movzx eax,_hex
end if
shl eax,16
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
shl eax,24
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
mov edx,8
end if
call fdo_debug_outhex
popad
popf
}
 
;-----------------------------------------------------------------------------
 
debug_func fdo_debug_outchar
debug_beginf
pushad
mov cl,al
mov ebx,1
mov eax,63
mcall
popad
ret
debug_endf
 
debug_func fdo_debug_outstr
debug_beginf
mov eax,63
mov ebx,1
.l1: dec esi
js .l2
mov cl,[edx]
or cl,cl
jz .l2
mcall
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
}
/programs/network_old/zeroconf/trunk/dhcp.inc
0,0 → 1,263
;Name Number Length Meaning
 
dhcp_pad_option equ 0 ; 0 None
dhcp_end_option equ 255 ; 0 None
dhcp_subnet_mask equ 1 ; 4 Subnet Mask Value
dhcp_time_offset equ 2 ; 4 Time Offset in Seconds from UTC
dhcp_router equ 3 ; N×4 Router addresses
dhcp_time_server equ 4 ; N×4 Timeserver addresses
dhcp_name_server equ 5 ; N×4 IEN-116 Server addresses
dhcp_domain_server equ 6 ; N×4 DNS Server addresses
dhcp_log_server equ 7 ; N×4 Logging Server addresses
dhcp_quotes_server equ 8 ; N×4 Quotes Server addresses
dhcp_lpr_server equ 9 ; N×4 Printer Server addresses
dhcp_impress_server equ 10 ; N×4 Impress Server addresses
dhcp_rlp_server equ 11 ; N×4 N RLP Server addresses
dhcp_hostname equ 12 ; N Hostname string
dhcp_boot_file_size equ 13 ; 2 Size of boot file in 512-octet blocks
dhcp_merit_dump_file equ 14 ; N Client to dump and name the file to dump it to
dhcp_domain_name equ 15 ; N The DNS domain name of the client
dhcp_swap_server equ 16 ; 4 Swap Server address
dhcp_root_path equ 17 ; N Path name for root disk
dhcp_extension_file equ 18 ; N Path name for more BOOTP info
 
;IP Layer Parameters per Host
 
dhcp_forward equ 19 ; 1 Enable/Disable IP Forwarding
dhcp_srcrte equ 20 ; 1 Enable/Disable Non-Local Source Routing
dhcp_policy equ 21 ; N×8 Non-Local Source Routing Policy Filters
dhcp_mag_dg_assembly equ 22 ; 2 Max Datagram Reassembly Size
dhcp_default_ip_tll equ 23 ; 1 Default IP Time to Live
dhcp_mtu_timeout equ 24 ; 4 Path MTU Aging Timeout
dhcp_mtu_plateau equ 25 ; N×2 Path MTU Plateau Table
 
;IP Layer Parameters per Interface
 
dhcp_mtu_interface equ 26 ; 2 Interface MTU Size
dhcp_mtu_subnet equ 27 ; 1 All Subnets are Local
dhcp_broadcast_address equ 28 ; 4 Broadcast Address
dhcp_mask_discovery equ 29 ; 1 Perform Mask Discovery
dhcp_mask_supplier equ 30 ; 1 Provide Mask to Others
dhcp_router_discovery equ 31 ; 1 Perform Router Discovery
dhcp_router_request equ 32 ; 4 Router Solicitation Address
dhcp_static_route equ 33 ; N×8 Static Routing Table
 
;Link Layer Parameters per Interface
 
dhcp_trailers equ 34 ; 1 Trailer Encapsulation
dhcp_arp_timeout equ 35 ; 4 ARP Cache Timeout
dhcp_ethernet equ 36 ; 1 Ethernet Encapsulation
 
;TCP Parameters
 
dhcp_default_tcp_tll equ 37 ; 1 Default TCP Time to Live
dhcp_keepalive_time equ 38 ; 4 TCP Keepalive Interval
dhcp_keepalive_data equ 39 ; 1 TCP Keepalive Garbage
 
;Application and Service Parameters
 
dhcp_nis_domain equ 40 ; N NIS Domain Name
dhcp_nis_servers equ 41 ; N×4 NIS Server Addresses
dhcp_ntp_servers equ 42 ; N×4 NTP Server Addresses
dhcp_vendor_specific equ 43 ; N Vendor Specific Information
dhcp_netbios_name_srv equ 44 ; N×4 NETBIOS Name Servers
dhcp_netbios_dist_srv equ 45 ; N×4 NETBIOS Datagram Distribution
dhcp_netbios_node_type equ 46 ; 1 NETBIOS Node Type
dhcp_netbios_scope equ 47 ; N NETBIOS Scope
dhcp_x_window_font equ 48 ; N×4 X Window Font Server
dhcp_x_window_manager equ 49 ; N×4 X Window Display Manager
dhcp_nis_domain_name equ 64 ; N NIS+ v3 Client Domain Name
dhcp_nis_server_addr equ 65 ; N×4 NIS+ v3 Server Addresses
dhcp_home_agent_addrs equ 68 ; N×4 Mobile IP Home Agent Addresses
dhcp_smtp_server equ 69 ; N×4 Simple Mail Server Addresses
dhcp_pop3_server equ 70 ; N×4 Post Office Server Addresses
dhcp_nntp_server equ 71 ; N×4 Network News Server Addresses
dhcp_www_server equ 72 ; N×4 WWW Server Addresses
dhcp_finger_server equ 73 ; N×4 Finger Server Addresses
dhcp_irc_server equ 74 ; N×4 Chat Server Addresses
dhcp_streettalk_server equ 75 ; N×4 StreetTalk Server Addresses
dhcp_stda_server equ 76 ; N×4 ST Directory Assist. Addresses
 
;DHCP Extensions
 
dhcp_address_request equ 50 ; 4 Requested IP Address
dhcp_address_time equ 51 ; 4 IP Address Lease Time
dhcp_option_overload equ 52 ; 1 Overload "sname" or "file"
dhcp_msg_type equ 53 ; 1 DHCP Message Type
dhcp_dhcp_server_id equ 54 ; 4 DHCP Server Identification
dhcp_parameter_list equ 55 ; N Parameter Request List
dhcp_dhcp_message equ 56 ; N DHCP Error Message
dhcp_dhcp_max_msg_size equ 57 ; 2 DHCP Maximum Message Size
dhcp_renewal_time equ 58 ; 4 DHCP Renewal (T1) Time
dhcp_rebinding_time equ 59 ; 4 DHCP Rebinding (T2) Time
dhcp_class_id equ 60 ; N Vendor Class Identifier
dhcp_client_id equ 61 ; N Client Identifier
dhcp_server_name equ 66 ; N TFTP Server Name
dhcp_bootfile_name equ 67 ; N Boot File Name
 
;Newer extensions
 
dhcp_netware_ip_domain equ 62 ; N Netware/IP Domain Name
dhcp_netware_ip_option equ 63 ; N Netware/IP sub Options
dhcp_user_class equ 77 ; N User Class Information
dhcp_directory_agent equ 78 ; N directory agent information
dhcp_service_scope equ 79 ; N service location agent scope
dhcp_rapid_commit equ 80 ; 0 Rapid Commit
dhcp_client_fqdn equ 81 ; N Fully Qualified Domain Name
dhcp_relay_agent_info equ 82 ; N Relay Agent Information, RFC 3046
dhcp_isns equ 83 ; N Internet Storage Name Service
; 84 REMOVED/Unassigned
dhcp_nds_servers equ 85 ; N Novell Directory Services
dhcp_nds_tree_name equ 86 ; N Novell Directory Services
dhcp_nds_conext equ 87 ; N Novell Directory Services
dhcp_bcmcs equ 88 ; Controller Domain Name list
dhcp_bcmcs equ 89 ; Controller IPv4 address option
dhcp_authentication equ 90 ; N Authentication
; 91 REMOVED/Unassigned
; 92 REMOVED/Unassigned
dhcp_client_system equ 93 ; N Client System Architecture
dhcp_client_ndi equ 94 ; N Client Network Device Interface
dhcp_ldap equ 95 ; N Lightweight Directory Access Protocol
; 96 REMOVED/Unassigned
dhcp_uuid_guid equ 97 ; N UUID/GUID-based Client Identifier
dchp_user_auth equ 98 ; N Open Group's User Authentication
; 99 REMOVED/Unassigned
; 100 REMOVED/Unassigned
; 101 REMOVED/Unassigned
; 102 REMOVED/Unassigned
; 103 REMOVED/Unassigned
; 104 REMOVED/Unassigned
; 105 REMOVED/Unassigned
; 106 REMOVED/Unassigned
; 107 REMOVED/Unassigned
; 108 REMOVED/Unassigned
; 109 REMOVED/Unassigned
; 110 REMOVED/Unassigned
; 111 REMOVED/Unassigned
dhcp_netinfo_address equ 112 ; N NetInfo Parent Server Address
dhcp_netinfo_tag equ 113 ; N NetInfo Parent Server Tag
dhcp_url equ 114 ; N URL
; 115 REMOVED/Unassigned
dhcp_auto_config equ 116 ; N DHCP Auto-Configuration
dhcp_ns_search equ 117 ; N Name Service Search
dhcp_subnet_selection equ 118 ; 4 Subnet Selection Option
dhcp_domain_search equ 119 ; N DNS domain search list
dhcp_sip_servers equ 120 ; N SIP Servers DHCP Option
dhcp_cl_static_route equ 121 ; N Classless Static Route Option
dhcp_ccc equ 122 ; N CableLabs Client Configuration
dhcp_geoconf equ 123 ; 16 GeoConf Option
dhcp_v_i_vendor_class equ 124 ; Vendor-Identifying Vendor Class
dhcp_v_i_vendor_spec equ 125 ; Vendor-Identifying Vendor-Specific
; 126 REMOVED/Unassigned
; 127 REMOVED/Unassigned
dhcp_pxe equ 128 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_etherboot_sign equ 128 ; Etherboot signature. 6 bytes: E4:45:74:68:00:00
dhcp_docsis equ 128 ; DOCSIS "full security" server IP address
dhcp_tftp_server_ip equ 128 ; TFTP Server IP address (for IP Phone software load)
dhcp_pxe equ 129 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_kernel_options equ 129 ; Kernel options. Variable length string
dhcp_call_server_ip equ 129 ; Call Server IP address
dhcp_pxe equ 130 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_ethernet_interface equ 130 ; Ethernet interface. Variable length string.
dhcp_siscrimination equ 130 ; Discrimination string (to identify vendor)
dhcp_pxe equ 131 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_remote_stat_server equ 131 ; Remote statistics server IP address
dhcp_pxe equ 132 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_802.1p equ 132 ; 802.1P VLAN ID
dhcp_pxe equ 133 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_802.1q equ 133 ; 802.1Q L2 Priority
dhcp_pxe equ 134 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_diffserv equ 134 ; Diffserv Code Point
dhcp_pxe equ 135 ; PXE - undefined (vendor specific) (Tentatively Assigned - 23 June 2005)
dhcp_http_proxy_psa equ 135 ; HTTP Proxy for phone-specific applications
; 136 REMOVED/Unassigned
; 137 REMOVED/Unassigned
; 138 REMOVED/Unassigned
; 139 REMOVED/Unassigned
; 140 REMOVED/Unassigned
; 141 REMOVED/Unassigned
; 142 REMOVED/Unassigned
; 143 REMOVED/Unassigned
; 144 REMOVED/Unassigned
; 145 REMOVED/Unassigned
; 146 REMOVED/Unassigned
; 147 REMOVED/Unassigned
; 148 REMOVED/Unassigned
; 149 REMOVED/Unassigned
dhcp_tftp_server_addr equ 150 ; TFTP server address (Tentatively Assigned - 23 June 2005)
dhcp_etherboot equ 150 ; Etherboot
dhcp_grub_conf_path equ 150 ; GRUB configuration path name
; 151 REMOVED/Unassigned
; 152 REMOVED/Unassigned
; 153 REMOVED/Unassigned
; 154 REMOVED/Unassigned
; 155 REMOVED/Unassigned
; 156 REMOVED/Unassigned
; 157 REMOVED/Unassigned
; 158 REMOVED/Unassigned
; 159 REMOVED/Unassigned
; 160 REMOVED/Unassigned
; 161 REMOVED/Unassigned
; 162 REMOVED/Unassigned
; 163 REMOVED/Unassigned
; 164 REMOVED/Unassigned
; 165 REMOVED/Unassigned
; 166 REMOVED/Unassigned
; 167 REMOVED/Unassigned
; 168 REMOVED/Unassigned
; 169 REMOVED/Unassigned
; 170 REMOVED/Unassigned
; 171 REMOVED/Unassigned
; 172 REMOVED/Unassigned
; 173 REMOVED/Unassigned
; 174 REMOVED/Unassigned
dhcp_etherboot equ 175 ; Etherboot (Tentatively Assigned - 23 June 2005)
dhcp_ip_telephone equ 176 ; IP Telephone (Tentatively Assigned - 23 June 2005)
dhcp_etherboot equ 177 ; Etherboot (Tentatively Assigned - 23 June 2005)
dhcp_packetcable equ 177 ; PacketCable and CableHome (replaced by 122)
; 178 REMOVED/Unassigned
; 179 REMOVED/Unassigned
; 180 REMOVED/Unassigned
; 181 REMOVED/Unassigned
; 182 REMOVED/Unassigned
; 183 REMOVED/Unassigned
; 184 REMOVED/Unassigned
; 185 REMOVED/Unassigned
; 186 REMOVED/Unassigned
; 187 REMOVED/Unassigned
; 188 REMOVED/Unassigned
; 189 REMOVED/Unassigned
; 190 REMOVED/Unassigned
; 191 REMOVED/Unassigned
; 192 REMOVED/Unassigned
; 193 REMOVED/Unassigned
; 194 REMOVED/Unassigned
; 195 REMOVED/Unassigned
; 196 REMOVED/Unassigned
; 197 REMOVED/Unassigned
; 198 REMOVED/Unassigned
; 199 REMOVED/Unassigned
; 200 REMOVED/Unassigned
; 201 REMOVED/Unassigned
; 202 REMOVED/Unassigned
; 203 REMOVED/Unassigned
; 204 REMOVED/Unassigned
; 205 REMOVED/Unassigned
; 206 REMOVED/Unassigned
; 207 REMOVED/Unassigned
dhcp_pxelinux.magic equ 208 ; pxelinux.magic (string) = F1:00:74:7E (241.0.116.126) (Tentatively Assigned - 23 June 2005)
dhcp_pxelinux.conffile equ 209 ; pxelinux.configfile (text) (Tentatively Assigned - 23 June 2005)
dhcp_pxelinux.path equ 210 ; pxelinux.pathprefix (text) (Tentatively Assigned - 23 June 2005)
dhcp_pxelinux.reboot equ 211 ; pxelinux.reboottime (unsigned integer 32 bits) (Tentatively Assigned - 23 June 2005)
; 212 REMOVED/Unassigned
; 213 REMOVED/Unassigned
; 214 REMOVED/Unassigned
; 215 REMOVED/Unassigned
; 216 REMOVED/Unassigned
; 217 REMOVED/Unassigned
; 218 REMOVED/Unassigned
; 219 REMOVED/Unassigned
dhcp_subnet_aloc equ 220 ; Subnet Allocation Option (Tentatively Assigned - 23 June 2005)
dhcp_virtual_subnet equ 221 ; Virtual Subnet Selection Option (Tentatively Assigned - 23 June 2005)
; 222 REMOVED/Unassigned
; 223 REMOVED/Unassigned
/programs/network_old/zeroconf/trunk/zeroconf.ini
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 = static
ip = 192.168.1.150
gateway = 192.168.1.1
dns = 192.168.1.1
subnet = 255.255.255.0
/programs/network_old/zeroconf/trunk
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network_old/zeroconf
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network_old/icq/trunk/cmdipc.inc
0,0 → 1,221
include "MACROS.INC"
 
initipc:
mov eax,9
mov ebx,prc
mov ecx,-1
int 0x40
 
mov ecx,eax
loop1:
push ecx
 
mov eax,9
mov ebx,prc
int 0x40
 
cmp word [prc+10],'CM'
jne no_cmd
cmp byte [prc+12],'D'
jne no_cmd
 
mov ebx,[prc+30]
mov dword [cmdpid],ebx
 
mov dword [cmdnumb],ecx
 
no_cmd:
pop ecx
loop loop1
 
cmp dword [cmdpid],0
jne no_exit
 
jmp exit
 
no_exit:
mov eax,60
mov ebx,2
mov ecx,dword [cmdpid]
mov edx,printf
mov esi,4
int 0x40
 
call initcmd
 
waitcmdinit:
mov eax,40
mov ebx,01000000b
int 0x40
 
mov eax,23
mov ebx,100
int 0x40
 
cmp eax,7
je cmd_ok
 
jmp exit
 
cmd_ok:
cmp byte [ipcb+16],'.'
jne exit
 
mov eax,18
mov ebx,3
mov ecx,dword [cmdnumb]
int 0x40
 
ret
 
pause1:
mov eax,5
mov ebx,1
int 0x40
ret
 
exit:
mov eax,-1
int 0x40
 
cls:
mov eax,60
mov ebx,2
mov ecx,dword [cmdpid]
mov edx,ipccls
mov esi,4
int 0x40
 
call pause1
 
ret
 
print:
mov ecx,84
loopprt:
mov edi,stripc
add edi,ecx
mov esi,fill_symbol
movsb
 
loop loopprt
 
cld
mov ecx,4
mov edi,stripc
mov esi,printf
rep movsb
 
cld
mov edx,79
sub edx,eax
mov ecx,79
sub ecx,edx
mov edi,stripc+4
mov esi,ebx
rep movsb
 
mov eax,60
mov ebx,2
mov ecx,dword [cmdpid]
mov edx,stripc
mov esi,84
int 0x40
 
call pause1
 
ret
 
eol:
mov eax,60
mov ebx,2
mov ecx,dword [cmdpid]
mov edx,ipceol
mov esi,4
int 0x40
 
call pause1
 
ret
 
initcmd:
mov eax,60
mov ebx,2
mov ecx,dword [cmdpid]
mov edx,ipckey
mov esi,4
int 0x40
 
mov eax,60
mov ebx,1
mov ecx,ipcb
mov edx,28
int 0x40
 
cld
mov ecx,28
mov edi,ipcb
mov esi,ipcc
rep movsb
 
ret
 
getkey:
call initcmd
 
waitagain:
mov eax,40
mov ebx,01000000b
int 0x40
 
mov eax,10
int 0x40
 
cmp eax,7
jne waitagain
 
mov edi,key
mov esi,ipcb+16
movsb
 
ret
 
endipc:
mov eax,60
mov ebx,2
mov ecx,dword [cmdpid]
mov edx,ipcend
mov esi,4
int 0x40
 
jmp exit
 
cmdpid dd 0
cmdnumb dd 0
 
printf db '~ppp'
ipceol db '~lll'
ipcend db '~eee'
ipccls db '~ccc'
ipckey db '~kkk'
 
key db 0
 
ipcb:
db 0
db 0,0,0
dd 8
times 20 db 0
 
ipcc:
db 0
db 0,0,0
dd 8
times 20 db 0
 
stripc: times 84 db 0
 
fill_symbol db 0
 
prc: times 52 db 0
 
/programs/network_old/icq/trunk/editbox.inc
0,0 → 1,275
; SEE YOU File FAQ.txt and HISTORY. Good Like!
;;;;;;;;;;;;;;;;;;
include 'editbox.mac' ;¬ ªà®á ª®â®àë© ¤®«¦¥­ ®¡«¥£ç¨âì ¦¨§­ì :) ᯥ樠«ì­® ¤«ï editbox
;;;;;;;;;;;;;;;;;;
macro use_edit_box procinfo,scr_h,scr_w
{
edit_box:
ed_width equ [edi] ;è¨à¨­  ª®¬¯®­¥­â 
ed_left equ [edi+4] ;¯®«®¦¥­¨¥ ¯® ®á¨ å
ed_top equ [edi+8] ;¯®«®¦¥­¨¥ ¯® ®á¨ ã
ed_color equ [edi+12] ;梥â ä®­  ª®¬¯®­¥­â 
shift_color equ [edi+16] ;=0x6a9480
ed_focus_border_color equ [edi+20] ;梥â à ¬ª¨ ª®¬¯®­¥­â 
ed_blur_border_color equ [edi+24] ;梥⠭¥  ªâ¨¢­®£® ª®¬¯®­¥­â 
ed_text_color equ [edi+28] ;梥â ⥪áâ 
ed_max equ [edi+32] ;ª®«-¢® ᨬ¢®«®¢ ª®â®àë¥ ¬®¦­® ¬ ªá¨¬ «ì­® ¢¢¥áâ¨
ed_text equ [edi+36] ;㪠§ â¥«ì ­  ¡ãä¥à
ed_flags equ [edi+40] ;ä« £¨
ed_size equ [edi+42] ;ª®«-¢® ᨬ¢®«®¢
ed_pos equ [edi+46] ;¯®§¨æ¨ï ªãàá®à 
ed_offset equ [edi+50] ;ᬥ饭¨¥
cl_curs_x equ [edi+54] ;¯à¥¤ë¤ã饥 ª®®à¤¨­ â  ªãàá®à  ¯® å
cl_curs_y equ [edi+58] ;¯à¥¤ë¤ã饥 ª®®à¤¨­ â  ªãàá®à  ¯® ã
ed_shift_pos equ [edi+62] ;¯®«®¦¥­¨¥ ªãàá®à 
ed_shift_pos_old equ [edi+66] ;áâ à®¥ ¯®«®¦¥­¨¥ ªãàá®à 
;==========================================================
;=== ¯à®æ¥¤ãà  ¯à®à¨á®¢ª¨ =================================
;==========================================================
.draw:
pusha
;--- à¨á㥬 à ¬ªã ---
call .draw_border ; ”ã­ªæ¨ï áâ ¡¨«ì­ 
.draw_bg_cursor_text:
;--- ¨§¬¥­ï¥¬ ᬥ饭¨¥, ¥á«¨ ­ ¤® ---
call .check_offset ;¢ëç¨á«¥­¨¥ ¯®§¨æ¨¨ ªãàá®à  áâ ¡¨«ì­ 
;--- à¨á㥬 ¢­ãâ७­îî ®¡« áâì ---
call .draw_bg ;­ à¨á®¢ âì ¯àאַ㣮«ì­¨ª à ¡®ç¥© ®¡« áâ¨
;---- à¨á㥬 ¢ë¤¥«¥­¨¥, ¯® shift ¥á«¨ ¥áâì
call .draw_shift
.draw_cursor_text:
;--- à¨á㥬 ªãàá®à ---
;--- ¬®¦¥â ¥£® ­¥ ­ ¤® à¨á®¢ âì ----
test word ed_flags,ed_focus
je @f
call .draw_cursor
@@:
call .draw_text
;;;;;;;;;;;;;;;;;;;;;;;;;;
;Ž¡é¨© ¢ë室 ¨§ editbox ¤«ï ¢á¥å ä㭪権 ¨ ¯®áâ ®¡à ¡®â稪®¢
;;;;;;;;;;;;;;;;;;;;;;;;;;
.editbox_exit:
edit_ex
;==========================================================
;=== ®¡à ¡®âª  ª« ¢¨ âãàë =================================
;==========================================================
.key:
pusha
test word ed_flags,ed_focus ; ¥á«¨ ­¥ ¢ 䮪ãá¥, ¢ë室¨¬
je .editbox_exit
;à®¢¥àª  ­ ¦ â shift ?
call .check_shift
;----------------------------------------------------------
;--- ¯à®¢¥à塞, çâ® ­ ¦ â® --------------------------------
;----------------------------------------------------------
use_key_process backspase,delete,left,right,home,end,insert
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;‡ £«ã誠 ­  ®¡à ¡®âªã ª« ¢¨è ¢¢¥àå ¨ ¢­¨§ â.¥. ¯à¨ ®¡­ à㦥­¨¨ íâ¨å ª®¤®¢ ¯à®¨á室¨â ¢ë室 ¨§ ®¡à ¡®â稪 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_key_no_process up,down,esc
;--- ­ ¦ â  ¤àã£ ï ª« ¢¨è  ---
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;à®¢¥àª  ãáâ ­®¢«¥­ «¨ ä« £ ¯à¨ ª®â®à®¬ ­ã¦­® ¢ë¢®¤¨âì ⮫쪮 æ¨äàë ¢ ­ã¦­®¬ ¡®ªá¥ ¥á«¨ â ª®©­¥®¡å®¤¨¬®á⨠­¥â ­ã¦­® § ª®¬¥­â¨à®¢ âì ¬ ªà®á
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_key_figures_only
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;¯à®¢¥àª  ­  shift ¡ë« «¨ ­ ¦ â
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
are_key_shift_press
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ¯à®¢¥à塞, ­ å®¤¨âáï «¨ ªãàá®à ¢ ª®­æ¥ + ¤ «ì­¥©è ï ®¡à ¡®âª 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
are_key_cur_end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Ž¡à ¡®âª  ª« ¢¨è insert,delete.backspase,home,end,left,right
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_work_key
;==========================================================
;=== ®¡à ¡®âª  ¬ëè¨ =======================================
;==========================================================
.mouse:
pusha
;debug
;----------------------------------------------------------
;--- ¯®«ãç ¥¬ á®áâ®ï­¨¥ ª­®¯®ª ¬ëè¨ -----------------------
;----------------------------------------------------------
mcall 37,2
;----------------------------------------------------------
;--- ¯à®¢¥à塞 á®áâ®ï­¨¥ ----------------------------------
;----------------------------------------------------------
test eax,1
jnz .mouse_left_button
and word ed_flags,ed_mouse_on_off
xor ebx,ebx
mov dword [mouse_flag],ebx
jmp .editbox_exit
.mouse_left_button:
;----------------------------------------------------------
;--- ¡«®ª¨à®¢ª  ®â 䮪ãá¨à®¢ª¨ ¢ ¤àã£¨å ¡®ªá å ¯à¨ ¯®¯ ¤ ­¨¨ ­  ­¨å ªãàá®à 
;----------------------------------------------------------
mov eax,dword [mouse_flag]
test eax,eax
jz @f
cmp eax,edi
je @f
jmp ._blur
;----------------------------------------------------------
;--- ¯®«ãç ¥¬ ª®®à¤¨­ âë ¬ëè¨ ®â­®á¨â¥«ì­® 0 â.¥ ¢á¥© ®¡« á⨠íªà ­ 
;----------------------------------------------------------
@@: mcall 37,0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;”ã­ªæ¨ï ®¡à ¡®âª¨ ¬ë誨 ¯®«ã祭¨¥ ª®®à¤¨­ â ¨ ¯à®¢¥àª  ¨å + ¢ë¤¥«¥­¨ï
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_work_mause scr_h,scr_w
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Ž¡é¨¥ ä㭪樨 ®¡à ¡®âª¨
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_general_func
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;”㭪樨 ¤«ï à ¡®âë á key
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_key_func
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;”㭪樨 ¤«ï à ¡®âë á mouse
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_mouse_func scr_w
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Bit mask from editbox
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ed_figure_only= 1000000000000000b ;®¤­¨ ᨬ¢®«ë
ed_always_focus= 100000000000000b
ed_focus= 10b ;䮪ãá ¯à¨«®¦¥­¨ï
ed_shift_on= 1000b ;¥á«¨ ­¥ ãáâ ­®¢«¥­ -§­ ç¨â ¢¯¥à¢ë¥ ­ ¦ â shift,¥á«¨ ¡ë« ãáâ ­®¢«¥­, §­ ç¨â ¬ë 㦥 çâ® - â® ¤¥« «¨ 㤥ন¢ ï shift
ed_shift_on_off=1111111111110111b
ed_shift= 100b ;¢ª«îç ¥âáï ¯à¨ ­ ¦ â¨¨ ­  shift â.¥. ¥á«¨ ­ ¦¨¬ î
ed_shift_off= 1111111111111011b
ed_shift_bac= 10000b ;¡¨â ¤«ï ®ç¨á⪨ ¢ë¤¥«¥­®£® shift â.¥. ¯à¨ ãáâ ­®¢ª¥ £®¢®à¨â çâ® ¥áâì ¢ë¤¥«¥­¨¥
ed_shift_bac_cl=1111111111101111b ;®ç¨á⪠ ¯à¨ 㤠«¥­¨¨ ¢ë¤¥«¥­¨ï
ed_shift_cl= 1111111111100011b
ed_shift_mcl= 1111111111111011b
ed_left_fl= 100000b
ed_right_fl= 1111111111011111b
ed_offset_fl= 1000000b
ed_offset_cl= 1111111110111111b
ed_insert= 10000000b
ed_insert_cl= 1111111101111111b
ed_mouse_on = 100000000b
ed_mous_adn_b= 100011000b
ed_mouse_on_off=1111111011111111b
ed_height=14 ; ¢ëá®â 
macro draw_edit_boxes start,_end,use_f9,procinfo
{
if use_f9 eq
else
mcall 9,procinfo,-1
end if
mov edi,start
mov ecx,((_end-start)/ed_struc_size)
@@:
call edit_box.draw
add edi,ed_struc_size
loop @b
}
 
macro mouse_edit_boxes start,_end
{
mov edi,start
mov ecx,((_end-start)/ed_struc_size)
@@:
call edit_box.mouse
add edi,ed_struc_size
loop @b
}
 
macro key_edit_boxes start,end
{
mov edi,start
mov ecx,((end-start)/ed_struc_size)
@@:
call edit_box.key
add edi,ed_struc_size
loop @b
}
ed_struc_size=70
struc edit_box width,left,top,color,shift_color,focus_border_color,\
blur_border_color,text_color,max,text,flags,size,pos
{
.width dd width
.left dd left
.top dd top
.color dd color
.shift_color dd shift_color
.focus_border_color dd focus_border_color
.blur_border_color dd blur_border_color
.text_color dd text_color
.max dd max
.text dd text
.flags dw flags+0
.size dd size+0
.pos dd pos+0
.offset dd 0
.cl_curs_x dd 0
.cl_curs_y dd 0
.shift dd 0
.shift_old dd 0
}
 
 
macro edit_boxes_set_sys_color start,end,color_table
{
mov edi,start
mov ecx,((end-start)/ed_struc_size)
mov esi,color_table
@@:
mov eax,[esi+36]
mov ebx,[esi+20]
mov ed_focus_border_color,eax
shr bh,1
shr bl,1
shr ah,1
shr al,1
add ah,bh
add al,bl
ror eax,16
ror ebx,16
shr bl,1
shr al,1
add al,bl
ror eax,16
mov ed_blur_border_color,eax
add edi,ed_struc_size
loop @b
}
 
macro draw_edit_box ed_ptr,use_f9,procinfo
{
if use_f9 eq
else
mcall 9,procinfo,-1
end if
mov edi,ed_ptr
call edit_box.draw
}
 
macro mouse_edit_box ed_ptr
{
mov edi,ed_ptr
call edit_box.mouse
}
 
macro key_edit_box ed_ptr
{
mov edi,ed_ptr
call edit_box.key
}
macro default_box ed_ptr
{
pusha
; xor eax,eax
; mov ed_shift_pos,eax
; mov ed_shift_pos_old,eax
and word ed_flags,ed_shift_cl
; mov ed_offset,eax
popa
}
/programs/network_old/icq/trunk/ki.asm
0,0 → 1,4046
; compiler: FASM 1.67.21
; name: ICQ client for Kolibri
; version: 0.1.30
; written by: LV
; e-mail: lv4evil@yandex.ru
 
 
include "lang.inc"
include "macros.inc"
;purge mov
;include "ASCL9/ascl.inc"
;include "../../../debug.inc"
include "editbox.inc"
 
MEOS_APP_START
 
;include "../../../debug.inc"
include "2000.inc"
include "comp.inc"
;include "fsio.inc"
include "dos2win.inc"
include "parser.inc"
include "ssi.inc"
 
use_edit_box procinfo,22,5
 
;
; …᫨ == 0, ª®¤ ¤«ï ¨á¯®«ì§®¢ ­¨ï ª®­â ªâ «¨áâ 
; ­  á¥à¢¥à¥ ­¥  áᥬ¡«¨àã¥âáï
;
USE_SSI = 1
;
;
 
CODE
;mov eax, 40
;mov ebx, 47h
;int 40h
 
;
; ‡ £à㧪  ª®­ä¨£®¢
;
 
mov eax, fname
call parseconf
;
; ‚뢮¤ § £à㦥­­®© ¨­ä®à¬ æ¨¨
;
 
mov eax, cfg_message
xor ebx, ebx
call writemsg
 
call showcfg
 
;call loaduin
call draw_window ; at first create and draw the window
;call buttonbox
 
wait_event: ; main cycle
;mov eax, 23
;mov ebx, 20
;int 0x40
mcall 23,20
 
cmp eax, 1 ; if event == 1
je redraw ; jump to redraw handler
cmp eax, 2 ; else if event == 2
je key ; jump to key handler
cmp eax, 3 ; else if event == 3
je button ; jump to button handler
;
; †¤¥¬ ¤ ­­ëå
;
mcall 53,2,[socket]
cmp eax, 0
jnz read_socket
 
mouse_edit_box inputbox
;
; …᫨ ¥áâì ᮥ¤¨­¥­¨¥ á á¥à¢¥à®¬, ¯®áë« ¥¬ ¯ ª¥âë - ¯®¤â¢¥¦¤¥­¨ï ª ¦¤ë¥ 60 á
; ­¥ âॡã¥âáï
; call sendkeep
jmp wait_event ; else return to the start of main cycle
 
 
redraw: ; redraw event handler
call draw_window
jmp wait_event
 
 
key: ; get key code
mcall 2
 
cmp ah, 0Dh ; à®¡¥« - ®â¯à ¢¨âì á®®¡é¥­¨¥
jz send
 
 
key_edit_box inputbox
 
jmp wait_event
 
 
button: ; button event handler
;mov eax, 17 ; get button identifier
;int 0x40
mcall 17
 
cmp ah, 2
jz connect
 
cmp ah, 3
jz disconnect
 
cmp ah, 4
jz send
 
;
; à®¢¥à塞, ­¥ ­ ¦ â  «¨ ª­®¯ª  ¢ Š‹
; 100 <ID <= 100+UINS
cmp ah, UINS+100
jnc @f
cmp ah, 100
jc @f
;
;  ¦ â 
;
sub ah, 100
mov [curruser], ah
;
; ‚뢮¤¨¬ áâà®çªã, ª®¬ã
;
shr eax, 8
and eax, 000000FFh
push eax
mov eax, CUSER
call strlen
mov ecx, eax
mov eax, CUSER
mov ebx, buff
call strcpy
pop eax
mov ebx, NAME_LEN
imul ebx, eax
lea eax, [names + ebx]
mov [buff + ecx], ' ' ; à®¡¥«
lea ebx, [buff + ecx + 1]
mov ecx, NAME_LEN
;debug
push ebx
mov ebx, NAME_LEN
call print_mem
pop ebx
;
call strcpy
mov eax, buff
xor ebx, ebx
call writemsg
 
 
 
 
@@:
cmp ah, 1
jne wait_event ; return if button id != 1
 
; exit application
mcall -1
 
 
draw_window:
; start drawing
mcall 12,1
 
mcall 0,(100*65536+700),(100*65536+500),0x14ffffff,0,head
 
draw_edit_box inputbox
 
rect 10, 30, 500, 450, 0
 
draw_button 600, 460, 60, 15, 2, 'CONNECT'
;draw_button 600, 460, 60, 15, 3, 'Disconnect'
draw_button 530, 460, 60, 15, 4, 'SEND'
 
call printbuff
call buttonbox
 
;
; Image
;
;mov eax, 7
;mov ebx, redicq
;mov ecx, 15*65536+15
;mov edx, 100*65536+100
;int 40h
 
 
 
; finish drawing
mcall 12,2
 
ret
 
;
; ‘®¥¤¨­¥­¨¥
;
connect:
lea eax, [vtable + vartable.icqip]
call ip_parser
call htonl
data_debug 'IP:', eax
 
;mov eax, ICQ_IP
mov ebx, ICQ_PORT
call srv_connect
 
 
jmp wait_event
 
 
;
;
;
disconnect:
mov ecx, [socket]
call closesocket
 
jmp wait_event
 
 
;
;
;
send:
;
; Ž¯à¥¤¥«ï¥¬, ­¥ ᬥ­¥­ «¨ ⥪ã騩 “ˆ
;
; „«ï ᬥ­ë ¨á¯®«ì§ã¥âáï / ¢ ­ ç «¥ áâப¨ ¨ ­®¬¥à 㨭 
; ¯® ¯®à浪ã. …᫨ ¤«¨­  > 2 ᨬ¢®«®¢, áç¨â ¥âáï, çâ® ¯¥à¥¤ ­
; á ¬ 㨭 - ¤«ï ®â¯à ¢ª¨ á®®¡é¥­¨© ࠬ, ª®â®àëå ­¥â ¢ Š‹
;
mov al, [inputbuff]
cmp al, '/'
jnz sd_message
; ‘¬¥­  㨭 
;mov al, [inputbuff+2]
;cmp al, 20h
;jz sd_use_kl
mov al, [inputbuff+3]
cmp al, 20h ; à®¡¥«
jz sd_use_kl
;
; ˆé¥¬ ¯¥à¢ë© ¯à®¡¥«, ¨¬ ¤®«¦¥­ § ª®­ç¨âìáï 㨭
;
xor ecx, ecx
sd_loop:
mov al, [inputbuff+ecx]
cmp al, 20h
jz sd_space
cmp al, 0
jz wait_event
inc ecx
jmp sd_loop
 
sd_space:
;
; ‡ ¬¥­ï¥¬ ¯à®¡¥« ­  0, ®âáë« ¥¬ á®®¡é¥­¨¥
mov [inputbuff+ecx], byte 0
lea ebx, [inputbuff+1]
lea eax, [inputbuff+ecx+1]
call sendmsg
mov ebx, 0000FFh
call writemsg
jmp wait_event
 
 
 
sd_use_kl:
lea eax, [inputbuff+1]
mov [inputbuff+3], byte 0
call ascitoint
lea eax, [eax-1] ; ’.ª. ¢ Š‹ ®âáç¥â á 0
mov [curruser], al
 
sd_message:
;
; ‘®®¡é¥­¨¥
movzx eax, [curruser]
mov ebx, UIN_LEN
imul ebx, eax
lea ebx, [uins+ebx]
mov al, [inputbuff]
cmp al, '/'
jz @f
mov eax, inputbuff
jmp sd_send
@@:
;mov al, [inputbuff+2]
;cmp al, ' '
;jz @f
lea eax, [inputbuff+4]
;jmp sd_send
;@@: lea eax, [inputbuff+3]
sd_send:
call sendmsg
mov ebx, 0000FFh
call writemsg
 
 
jmp wait_event
 
 
;
; …áâì ¯à¨­ïâë¥ ¤ ­­ë¥
;
read_socket:
pushf
pushad
;write_debug 'Some data in socket'
;
; à®¢¥à塞, ­¥ ¡ë« «¨ ¯®«ã祭 § £®«®¢®ª ®â¤¥«ì­® ®â ¤ ­­ëå
; ¢ ¯à¥¤ë¤ã饬 横«¥
;
cmp [hrf], 1
jz rs_head_recived
 
rs_check_sock:
;mov eax, 53
;mov ebx, 2
;mov ecx, [socket]
;int 40h
mcall 53,2,[socket]
cmp eax, 6 ; Flap head size
jc r_end
;
; à¨­¨¬ ¥¬ § £®«®¢®ª
;
xor edx, edx
 
;mov ecx, [socket]
rs_loop:
;mov eax, 53
;mov ebx, 3
;int 40h
mcall 53,3,[socket]
 
mov [mbuff+edx], bl
inc edx
cmp edx, 6
 
jnz rs_loop
;
; ‡ ¯®«­ï¥¬ § £®«®¢®ª
;
;xor eax, eax
 
;
; ‡ £®«®¢®ª ¯à¨­ïâ!
;
mov [hrf], 1
 
mov bl, [mbuff]
mov [rflap.bId], bl
 
mov bl, [mbuff+1]
mov [rflap.bCh], bl
 
mov bh, [mbuff+2]
mov bl, [mbuff+3]
mov [rflap.wSn], bx
 
mov bh, [mbuff+4]
mov bl, [mbuff+5]
mov [rflap.wDs], bx
 
;
; à¨­¨¬ ¥¬ ¤ ­­ë¥
;
;xor edx, edx
cmp [rflap.bId], 2Ah
jnz rs_flap_error
;
; à®¢¥à塞, ¯®«ãç¥­ë «¨ ¤ ­­ë¥
;
rs_head_recived:
 
;mov eax, 53
;mov ebx, 2
;mov ecx, [socket]
;int 40h
mcall 53,2,[socket]
 
cmp ax, [rflap.wDs] ;  §¬¥à ¤ ­­ëå
jc r_end
;
;
mov ax, [rflap.wDs]
;
; à®¢¥à塞 à §¬¥à ¤ ­­ëå
;
cmp ax, MBUFF_SIZE+1
jnc rs_big_flap
 
xor esi, esi
mov esi, eax
xor edx, edx
 
;mov ecx, [socket]
 
rs_data_loop:
cmp edx, esi
jz rs_data_end
 
;mov eax, 53
;mov ebx, 3
;int 40h
mcall 53,3,[socket]
mov [mbuff+edx], bl
inc edx
jmp rs_data_loop
 
;
; „ ­­ë¥ ¯à¨­ïâë
;
rs_data_end:
mov [hrf], 0
;write_debug 'Some data recived'
;
;
;
cmp [login], 0
jz rs_login
call main_loop
;
; …áâì á¬ëá« ¯à®¢¥à¨âì ᮪¥â ­  ­ «¨ç¨¥ á«¥¤ãî饣® § £®«®¢ª 
;
;jmp r_end
jmp rs_check_sock
 
 
rs_login:
call srv_login
;write_debug 'Exited srv_login'
;jmp r_end
jmp rs_check_sock
 
rs_flap_error:
write_debug 'Invalid Flap'
;
; FLAP.id ­¥¢¥à­ë©. ­ã¦­® § ªàëâì ᮪¥â
;
 
mov ecx, [socket]
;call closesocket
jmp r_end
 
;
; ‘«¨èª®¬ ¡®«ì让 ¯ ª¥â!
;
rs_big_flap:
 
write_debug 'Too BIG FLAP Recived'
mov [hrf], 0
 
;mov ecx, [socket]
mov ax, [rflap.wDs]
xor esi, esi
mov esi, eax
xor edx, edx
 
rs_data_loop2:
cmp edx, esi
jz r_end
 
;mov eax, 53
;mov ebx, 3
;int 40h
mcall 53,3,[socket]
;mov [mbuff+edx], bl
inc edx
jmp rs_data_loop2
 
 
 
 
 
r_end:
popad
popf
jmp wait_event
 
; ‘®¥¤¨­¥­¨¥ á á¥à¢¥à®¬, ¢®§¢à é ¥â ¢ eax - åí­¤« ᮪¥â 
; ¯¥à¥¤ ¥¬ ¢ ¥ å IP  ¤à¥á á¥à¢¥à 
; ¢ ebx - ¯®àâ
srv_connect:
push ecx
push edx
push esi
push edi
push ebx
mov esi, eax ; IP - ¢ esi
; find free port
mov ecx, 1000 ; Ž¯à¥¤¥«ï¥¬ «®ª «ì­ë© ¯®àâ, ­ ç¨­ ¥¬ á 1000
 
getlp:
inc ecx
push ecx
;mov eax, 53
;mov ebx, 9
;int 0x40
mcall 53,9,ecx
pop ecx
cmp eax, 0 ; íâ®â «®ª «ì­ë© ¯®à⠨ᯮ«ì§ã¥âáï?
jz getlp ; ¤  - ¯à®¤®«¦ ¥¬ ¯¥à¥¡¨à âì
;OK ecx = port number
;Open Socket
;mov eax, 53
;mov ebx, 5
xor edx, edx
;mov dx, ICQ_PORT
pop edx
;mov esi,ICQ_IP
;mov edi, 1;SOCKET_ACTIVE
 
;int 40h
mcall 53, 5, ecx, edx, esi, 1
;
mov [socket], eax
 
;
; †¤¥¬ ãáâ ­®¢ª¨ ᮥ¤¨¥­¨ï
mov ecx, eax
srv_loop:
 
;mov eax, 5
;mov ebx, 50
;int 40h
mcall 5, 50
 
 
;mov eax, 53
;mov ebx, 6
;int 40h
mcall 53, 6, ecx
cmp eax, TCB_ESTABLISHED
jz fin
cmp eax, 11
jae c_end
;
;inc [timer]
;cmp [timer], 50
;jz srv_err
jmp srv_loop
 
 
 
;srv_err:
;mov [timer], word 0
;cmp eax,-1
;jnz fin
;delay 100
write_debug 'CONNECTION FAILED' ;®¤ª«î祭¨¥ ­¥ 㤠«®áì
jmp c_end
;connrcted:
;CONNECTED
fin:
write_debug 'Connected!!!!'
c_end:
pop edi
pop esi
pop edx
pop ecx
;pop ebx
ret
 
;
; --> ecx socket handle
;
srv_login:
pushf
push eax
push ebx
;push ecx
push edx
 
;
; Ž¯à¥¤¥«ï¥¬ ⨯ ¯®«ã祭­ëå ¤ ­­ëå
;
movzx eax, [rflap.bCh]
cmp eax, 01
jz s_new_connection
cmp eax, 04
jz s_cookie ; cookie
jmp l_flap_err
 
s_new_connection:
;
; à®¢¥à塞 ¯®«ã祭­ë© ¯ ª¥â
;
movzx eax, [rflap.wDs]
cmp eax, 4
jnz l_len_err
mov eax, dword [mbuff]
cmp eax, 01000000h ; 00 00 00 01
jnz l_data_err
;
;”®à¬¨à㥬 ¯ ª¥â ¤«ï ᮥ¤¨­¥­¨ï
;
;mov [flap.bId], FLAP_ID
mov [flap.bCh], NEW_CONNECTION
;mov eax, 26
;mov ebx, 9
;int 40h
mcall 26, 9
mov [seq], ax
 
mov [flap.wSn], ax ; Sequence number
;mov [buff],0
;mov [buff+1],0
;mov [buff+2],0
mov dword [buff], 0x01000000 ;login Protokol version 00 00 00 01
;mov[buff+4],0
mov word [buff+4], 0x0100; TLV.TYPE = UIN 00 01
 
lea eax, [vtable + vartable.uin]
call strlen
mov [buff+6], ah
mov [buff+7], al ; Length of UIN
mov edx, eax
add edx, 7 ; ¢ edx ¤«¨­  § ¯®«­¥­­®£® ¡ãä¥à 
mov ecx, eax ;„«¨­  áâப¨
 
lea eax, [vtable + vartable.uin]
lea ebx, [buff+8] ; + à §¬¥à ¤ ­­ëå ¢ ¡ãä¥à¥ + 1
 
call strcpy
 
lea eax, [vtable + vartable.pass]
call roast
mov [buff+edx+2], 2 ; TLV.TYPE - rosted password
call strlen
mov [buff+edx+4], al
mov [buff+edx+3], ah ; Length of pass
 
add edx, 4
mov ebx, buff
add ebx, edx ; ­ §­ ç¥­¨¥
add edx, eax ; ‘®å࠭塞 ¢ EDX ¤«¨­ã § ¯®«­¥­­®£® ¡ãä­à 
mov ecx, eax ; „«¨­  áâப¨
lea eax, [vtable + vartable.pass] ; ˆáâ®ç­¨ª
inc ebx
call strcpy
mov [buff+edx+2], 3 ; TLV.TYPE - client id string
mov eax, ID_STRING
call strlen
mov [buff+edx+4], al
mov [buff+edx+3], ah
 
add edx, 4
mov ecx, eax
mov ebx, buff
add ebx, edx
add edx, eax
inc ebx
mov eax, ID_STRING
call strcpy
 
xor eax, eax
 
mov [buff+edx+2], 016h ; TLV.TYPE - Client id
mov [buff+edx+4], 2
mov ax, ID_NUM
call htons
mov word [buff+edx+5], ax
add edx, 6
 
mov [buff+edx+2], 017h ; Client major version
mov [buff+edx+4], 2
mov ax, MAJOR
call htons
mov word [buff+edx+5], ax
add edx, 6
 
mov [buff+edx+2], 018h ; Client minor version
mov [buff+edx+4], 2
mov ax, MINOR
call htons
mov word [buff+edx+5], ax
add edx, 6
 
mov [buff+edx+2], 019h ; Client lesser version
mov [buff+edx+4], 2
mov ax, LESSER
call htons
mov word [buff+edx+5], ax
add edx, 6
 
mov [buff+edx+2], 01Ah ; Client build number
mov [buff+edx+4], 2
mov ax, BUILD
call htons
mov word [buff+edx+5], ax
add edx, 6
mov [buff+edx+2], 014h ; Client distribution number
mov [buff+edx+4], 4
mov eax, DISTR
call htonl
mov dword [buff+edx+5], eax
add edx, 8
 
mov [buff+edx+2], 0Fh ; Client language
mov eax, CL_LANG
call strlen
mov word [buff+edx+4], ax
add edx, 4
mov ecx, eax
mov ebx, buff
add ebx, edx
inc ebx
add edx, eax
mov eax, CL_LANG
call strcpy
 
mov [buff+edx+2], 0Eh ; Client country
mov eax, CL_COUNTRY
call strlen
mov word [buff+edx+4], ax
add edx, 4
mov ecx, eax
mov ebx, buff
add ebx, edx
inc ebx
add edx, eax
mov eax, CL_COUNTRY
call strcpy
;write_debug 'Connect attemption'
; mov eax, ICQ_IP
; call srv_connect
; cmp eax, -1 ; ®¤ª«î祭¨¥ ­¥ 㤠«®áì
; jz l_fin
; mov ecx, eax
; mov eax, rflap
; mov ebx, lbuff
; call recvflap
; cmp eax, -1
; jz l_flap_err
; cmp [rflap.bCh], 01 ; AUTH channel
; jnz l_ch_err
; cmp eax, 4
; jnz l_len_err
; cmp dword [lbuff+3], dword 1
; jnz l_data_err
 
mov ecx, [socket]
inc dx
mov [flap.wDs], dx ; Data size
mov eax, flap
mov ebx, buff
call sendflap
cmp eax, 0
jnz l_fin ; ¥ãᯥå
jmp l_end
 
s_cookie:
;mov eax, rflap
;mov ebx, buff
;call recvflap
;cmp eax, -1
;jz l_flap_err
;cmp [rflap.bCh], 4
;jnz l_ch_err
 
;write_debug 'UIN'
xor ebx, ebx
 
uin_loop:
xor eax, eax
mov ax, word [mbuff+ebx]
cmp ax, 0100h ; 00 01 TLV.Type UIN
jz l_uin_ok ; ’¥¯¥àì á¥à¢¥à ¯¥à¥¤ ¥â ¥é¥ ¤ ­­ë¥ ¯à¨ ᮥ¤¨­¥­¨¨,   ¯®â®¬ ®¯ïâì
add ebx, 5 ; â®â ¦¥ TLV 1 (­®¢ë© ä®à¬ â ¯ ª¥ªâ )
cmp ebx, 5
ja l_tlvt_err
jmp uin_loop
 
 
 
 
 
l_uin_ok:
mov eax, ebx
xor ebx, ebx
mov bl, [mbuff+eax+3] ;
mov bh, [mbuff+eax+2] ; „«¨­  ¤ ­­ëå
;
; UIN ®ª  ­¥ ¯à®¢¥àï¥âáï
;
 
lea ebx, [ebx+eax+4]
mov ax, word [mbuff+ebx]
cmp ax, 0500h ; 00 05 Bos address
jz l_all_ok
cmp ax, 0400h ; UIN incorrect
jz l_uin_err
cmp ax, 0800h
jz l_pass_err
jmp l_tlvt_err
;
; ¥á«¨ ­¥¢¥à­ë© UIN/ ¯ à®«ì, ¯®«ãç ¥¬ TLV.TYPE 4/8
;
 
l_all_ok:
xor ecx, ecx
mov cl, [mbuff+ebx+3] ;length
mov ch, [mbuff+ebx+2] ;
lea eax, [mbuff+ebx+4]
push ebx
mov ebx, bos_address
call strcpy
pop ebx
add ebx, ecx
lea ebx, [ebx+4] ;  §¬¥à § £®«®¢ª 
;
; cookie
;
;write_debug 'Login Cookie'
 
xor eax, eax
mov ax, word [mbuff+ebx]
cmp ax, 0600h ; TLV.Type cookie
jnz l_tlvt_err
mov cl, [mbuff+ebx+3] ;
mov ch, [mbuff+ebx+2] ; Length
mov [cookie_len], cx
lea eax, [mbuff+ebx+4]
push ebx
mov ebx, srv_cookie
call strcpy
pop ebx
;
; ‘®¥¤¨­ï¥¬áï á BOS
;
;call srv_disconnect
mov ecx, [socket]
write_debug 'Closing socket'
;call closesocket
;
;
;
;FIXME!!!
;‡ ª®¬¬¥­â®à®¢ ­® ¨§-§  ¯à®¡«¥¬ë á á¥â¥¢ë¬ á⥪®¬
;§ ªàë⨥ ᮪¥â  § ¢¥è¨¢ ¥â á¨á⥬ã
;mcall 53, 8, ecx
 
 
mov eax, bos_address
call ip_parser
call htonl
data_debug 'BOS Address: ', eax
data_debug 'BOS Port: ', ebx
mov [bos_ip], eax
mov [bos_port], ebx
call srv_connect
mov [login], 1 ; ‘®¥¤¨­¥­¨¥ á ®á­®¢­ë¬ á¥à¢¥à®¬ ãáâ ­®¢«¥­®
;mov [socket], eax
 
jmp l_end
;
;
;
l_pass_err:
write_debug 'PASSWORD INVALID'
jmp l_fin
 
l_uin_err:
write_debug 'UIN INVALID'
jmp l_fin
 
l_data_err:
write_debug 'LOGIN DATA MISMATCH'
jmp l_fin
 
l_len_err:
write_debug 'RECIVED DATA LENGTH MISMATCH'
jmp l_fin
 
l_tlvt_err:
write_debug 'TLV TYPE MISMATCH'
jmp l_fin
 
l_ch_err:
write_debug 'FLAP CHANNEL MISMATCH'
jmp l_fin
 
l_flap_err:
write_debug 'FLAP ID MISMATCH / RECIVE ERROR'
 
l_fin:
 
;
; ¥®¡å®¤¨¬® § ªàëâì ᮪¥â
;
;call srv_disconnect
call closesocket
l_end:
pop edx
;pop ecx
pop ebx
pop eax
popf
ret
 
;
; Length of string
; input eax = offset string
; output eax = strlen
;
strlen:
push ebx
push ecx
pushf
xor ebx, ebx
xor ecx, ecx
 
loop_s:
mov cl, [eax+ebx]
cmp ecx,0
jz nl
inc ebx
jmp loop_s
 
nl:
mov eax, ebx
popf
pop ecx
pop ebx
ret
 
;
; Roasting password
; EAX = offset password
;
 
roast:
pushf
push ecx
push ebx
 
xor ecx, ecx
xor ebx, ebx
 
loop_r:
mov bl, [eax+ecx] ;‘¨¬¢®« ¨§ ¬ áᨢ  ¯ à®«ï
cmp bl, 0 ;Š®­¥æ áâப¨
jz r_fin
xor bl, [ROASTING_ARRAY+ecx]
mov [eax+ecx], bl
inc ecx
jmp loop_r
 
r_fin:
pop ebx
pop ecx
popf
ret
 
 
;
;Copy string of bytes
;‚ EAX =  ¤à¥á ¨á室­®© áâப¨
;‚ EBX =  ¤à¥á ­ §­ ç¥­¨ï
;‚ ECX = ¤«¨­  áâப¨
;
strcpy:
pushf
push esi
push edi
push ecx
 
cld ;Ž¡à ¡ â뢠¥¬ áâப㠮⠭ ç «  ª ª®­æã
mov esi, eax
mov edi, ebx
 
rep movsb
 
pop ecx
pop edi
pop esi
popf
ret
 
 
;
; Œ ªà®á ¤«ï áà ¢­¥­¨ï áâப
;
macro strcmp first, second, len
{
push ecx
push esi
push edi
 
mov ecx, len
mov esi, first
mov edi, second
repe cmpsb
 
pop edi
pop esi
pop ecx
 
}
 
 
;
; ‡ ¯®«­ï¥â ¡ãä¥à, ¯®  ¤à¥áã ¢ ebx
; ¤ ­­ë¬¨, ¯®  ¤à¥áã eax, ¢
; cx - ’¨¯ TLV
; dx - ¤«¨­  ¤ ­­ëå
;
;
 
tlvstr:
;pushf
push edx
push ecx
push ebx
 
mov [ebx], ch ; Type
mov [ebx+1], cl
 
mov [ebx+2], dh ; Length
mov [ebx+3], dl
lea ebx, [ebx+4]
; EBX = offset of destination
mov ecx, edx
 
call strcpy
 
pop ebx
pop ecx
pop edx
;popf
ret
 
;
; eax - 㪠§ â¥«ì ­  FLAP_head
; ebx - 㪠§ â¥«ì ­  ¬ áᨢ, § ¯®«­¥­­ë© ¤ ­­ë¬¨
; ecx - 奭¤« ᮪¥â 
;
; ‚ eax ¢®§¢à é ¥â १ã«ìâ â § ¯¨á¨ ¢ ᮪¥â
;
sendflap:
pushf
push edx
;push ecx
push esi
push ebx
push ecx
 
xor edx, edx
 
mov dl, [eax] ; ID byte
mov [sbuff], dl
 
mov dl, [eax+1] ; FLAP channel
mov [sbuff+1], dl
 
mov dl, [eax+2] ; FLAP datagramm seq number
mov [sbuff+3], dl ; ¬¥­ï¥¬ ¬¥áâ ¬¨ ¡ ©âë ¤«ï ¯¥à¥¤ ç¨ ¯® á¥â¨
mov dl, [eax+3]
mov [sbuff+2], dl
 
mov dl, [eax+4] ; FLAP data size
mov [sbuff+5], dl
mov dl, [eax+5]
mov [sbuff+4], dl
mov dx, word [eax+4]
 
xchg ecx, edx ; ecx - size edx - handle
mov eax, ebx ; data
mov ebx, sbuff ; dest
add ebx, 6 ; + header size
call strcpy
 
xchg ecx, edx ; ecx - handle, edx - data size
 
s_wait:
;mov eax, 53 ; à®¢¥à塞 á®áâ®ï­¨¥ ᮪¥â . …᫨ ᮥ¤¨¥­¨¥
;mov ebx, 6 ; ãáâ ­®¢«¥­® - ¯®áë« ¥¬ ¡ãä¥à, ¥á«¨ ᮪¥â § ªàëâ, ã室¨¬
;int 40h
mcall 53, 6, ecx
cmp eax, TCB_ESTABLISHED ; ãáâ ­®¢«¥­®
jz s_est
cmp eax, TCB_CLOSED
jz s_fin
cmp eax, 12 ; “ ¬¥­ï â ª®¥ ¡ë«®, ª®£¤  ᮥ¤¨­¥­¨¥ ãáâ ­ ¢«¨¢ «®áì á ¯ãáâ®â®© :-)
jnc s_fin ;
 
;mov eax, 5
;mov ebx, 1
;int 40h ; †¤¥¬
mcall 5, 1
jmp s_wait
 
 
s_est:
;mov eax, 53
;mov ebx, 7 ; ¯¨á âì ¢ ᮪¥â
add edx, 6 ; + size of header
;mov esi, sbuff ; data
;int 40h
mcall 53, 7, ecx, edx, sbuff
s_fin:
pop ecx
pop ebx
pop esi
;pop ecx
pop edx
popf
ret
 
 
;
; eax - 㪠§ â¥«ì ­  ¡ãä¥à
; ebx - §­ ç¥­¨¥, ª®â®àë¬ ­¥®¡å®¤¨¬® § â®«­¨âì. ˆá¯®«ì§ã¥âáï ⮫쪮 bl
; ecx - à §¬¥à
;
 
memset:
pushf
push edi
push eax
push ebx
push ecx
 
cld
mov edi, eax
mov eax, ebx
rep stosb
 
pop ecx
pop ebx
pop eax
pop edi
popf
ret
 
;
;  àᨬ TLV
; <-- ¢ eax  ¤à¥á TLV
; <-- ¢ ebx  ¤à¥á ¡ãä¥à , ª®â®àë© ­ã¦­® § ¯®«­¨âì
; --> ¢ ebx ¤«¨­  ¯®«ã祭­ëå ¤ ­­ëå
; --> ¢ eax ⨯ TLV
;
 
tlvpar:
pushf
;push esi
;push edi
push ecx
xor ecx, ecx
 
mov cl, [eax+3] ;TLV.Length
mov ch, [eax+2]
call strcpy
 
xor eax, eax
mov al, [ebx+1] ;TLV.Type
mov ah, [ebx]
mov ebx, ecx
 
 
pop ecx
;pop edi
;pop esi
popf
ret
 
;
; <-- ECX - 奭¤« ᮪¥â , ª®â®àë© ­ã¦­® § ªàëâì
; --> ECX - ¥§ã«ìâ â (¥­ ¤¥¦­®)
;
closesocket:
push eax
;push ebx
 
;mov eax, 53
;mov ebx, 8
;int 40h
mcall 53, 8, ecx
mov ecx, eax
 
;pop ebx
pop eax
ret
 
;
; ecx <-- 奭¤« ᮪¥â 
;
;
 
srv_disconnect:
pushf
push eax
push ebx
mov [flap.bId], FLAP_ID
mov [flap.bCh], 4 ;Disconnect
xor eax, eax
mov ax, [seq]
mov [flap.wSn], ax
mov [flap.wDs], 0
mov eax, flap
mov ebx, buff
call sendflap
 
 
pop ebx
pop eax
popf
ret
 
;
; <-- eax [bos_address]
; --> eax = IP ADDRESS
; --> ebx = port number
;
par_buff db 9 dup 0
 
ip_parser:
pushf
push ecx
push edx
push esi
push edi
 
xor ecx, ecx
;xor eax, eax
mov ebx, eax
xor edx, edx
xor esi, esi
xor edi, edi
ip_loop:
xor eax, eax
;xor edx, edx
mov al, [ebx+ecx]
cmp al, '.'
jz ip_dot
cmp al, 0
jz ip_end_str
cmp al, ':'
jz ip_colon
;sub al, 30h
;cmp al, 9
;ja ip_err ; ¥ æ¨äà 
mov [par_buff+edx], al
inc ecx
inc edx
jmp ip_loop
 
ip_dot:
;xor eax, eax
mov [par_buff+edx], 0 ; Š®­¥æ áâப¨
mov eax, par_buff
call ascitoint
 
;data_debug 'Debug eax: ', eax
 
cmp ecx, 0 ; ¥ ¬®¦¥â ­ ç¨­ âìáï á â®çª¨
jz ip_err
shl esi, 8 ; ‘¤¢¨£ ¥¬ ¯à¥¤ë¤ã騩 ¡ ©â
add esi, eax
inc ecx
xor edx, edx ; ‘ç¥â稪 ¡ãä¥à  = 0
jmp ip_loop
 
 
ip_colon: ; : ‚ áâப¥  ¤à¥á 
inc edi ; ë«® :
jmp ip_dot
ip_end_str:
cmp edi, 1
jz @f
; : ¥ ¡ë«®
mov [par_buff+edx], 0 ; Š®­¥æ áâப¨
mov eax, par_buff
call ascitoint
shl esi, 8 ; ‘¤¢¨£ ¥¬ ¯à¥¤ë¤ã騩 ¡ ©â
add esi, eax
;mov eax, esi ; IP ¢ 16 à¨ç­®© ä®à¬¥
xor ebx, ebx ; ®¬¥à  ¯®àâ  ­¥â
jmp ip_end
 
@@: ; ë«® :
mov [par_buff+edx], 0
mov eax, par_buff
call ascitoint
mov ebx, eax
jmp ip_end
 
ip_err:
xor esi, esi
 
ip_end:
mov eax, esi
 
pop edi
pop esi
pop edx
pop ecx
popf
ret
 
;
; <-- eax 㪠§ â¥«ì ­  asci
; --> eax int
;
ascitoint:
pushf
push ebx
push ecx
push edx
push esi
push edi
 
xor ebx, ebx
xor ecx, ecx
xor edx, edx
;xor esi, esi
xor edi, edi
ati_loop:
mov bl, [eax+ecx]
cmp bl, 0 ; Š®­¥æ áâப¨
jz ati_str_end
cmp bl, 39h
ja ati_err ; ¥ æ¨äà 
cmp bl, 30h
jb ati_err
 
inc ecx
jmp ati_loop
 
ati_str_end: ; ‚ ecx ¤«¨­  áâப¨
;dec ecx ; “áâ ­®¢¨¬ ­  ¯®á«¥¤­¨© ᨬ¢®«
add eax, ecx ; “ª § â¥«ì ­  áâபã + „«¨­  áâப¨
dec eax
ati_loop2:
cmp edx, ecx
jz ati_all
push eax
sub eax, edx ; ‚ëç¥áâì áç¥â稪
movzx ebx, byte [eax] ; ‚ bl ᨬ¢®«
;pop eax
sub bl, 30h ; ‚ëç¨á«ï¥¬ 10â¨ç­ãî æ¨äàã
 
;push eax
mov eax, ebx ; ‚ eax - æ¨äà 
mov ebx, 10 ; Œ­®¦¨â¥«ì
 
xor esi, esi
 
ati_mul:
 
cmp esi, edx ; “¬­®¦ ¥¬ ­  10 n à §
jz ati_mul_end
;push eax
;mov eax, ebx
imul eax, ebx
;mov ebx, eax
;pop eax
inc esi
jmp ati_mul
 
 
ati_mul_end:
mov ebx, eax ; ‚ ebx ¢ëç¨á«¥­­®¥ ç¨á«®
pop eax
 
add edi, ebx
inc edx
jmp ati_loop2
 
ati_all:
mov eax, edi
jmp ati_end
 
ati_err:
 
;ati_str_end:
xor eax, eax
 
ati_end:
pop edi
pop esi
pop edx
pop ecx
pop ebx
popf
ret
 
;
;
; <-- ecx 奭¤« ᮪¥â 
; <-- eax 㪠§ â¥«ì ­  áâàãªâãàã SNAC_head
; <-- ebx 㪠§ â¥«ì ­  ¤ ­­ë¥
; <-- edx à §¬¥à ¤ ­­ëå
; --> eax १ã«ìâ â § ¯¨á¨ ¢ ᮪¥â
;
 
snac_buff db 1024 dup 0
 
sendsnac:
pushf
push esi
push edi
push ebx
push edx
;xor ebx, ebx
mov esi, ecx ; 奭¤« ᮪¥â 
mov edi, ebx ; “ª § â¥«ì ­  ¤ ­­ë¥
 
xor ebx, ebx
mov bl, [eax] ;
mov [snac_buff+1], bl ; Family ID
mov bl, [eax+1] ; Š®­¢¥àâ¨àã¥âáï ¢ BigEndian
mov [snac_buff], bl ;
 
mov bl, [eax+2] ;
mov [snac_buff+3], bl ; Subtype ID
mov bl, [eax+3] ;
mov [snac_buff+2], bl ;
mov bl, [eax+4] ;
mov [snac_buff+5], bl ;
mov bl, [eax+5] ; Flags
mov [snac_buff+4], bl ;
 
mov bl, [eax+6] ;
mov [snac_buff+9], bl ;
mov bl, [eax+7] ;
mov [snac_buff+8], bl ;
mov bl, [eax+8] ; Reqest ID
mov [snac_buff+7], bl ;
mov bl, [eax+9] ;
mov [snac_buff+6], bl ;
 
lea ebx, [snac_buff+10]
mov eax, edi ; “ª § â¥«ì ­  ¤ ­­ë¥
;add ebx, 10 ; + à §¬¥à § £®«®¢ª  SNAC
mov ecx, edx ; à §¬¥à ¤ ­­ëå
call strcpy
 
 
mov ecx, esi ; •¥­¤« ᮪¥â 
mov [flap.bId], FLAP_ID
mov [flap.bCh], 2 ; Š ­ « ¤«ï ¯®á뫪¨ SNAC
xor ebx, ebx
inc [seq] ; seq “¢¥«¨ç¨¢ ¥âáï ­  1 ¯à¨ ª ¦¤®© ¯®á뫪¥
mov bx, [seq]
mov [flap.wSn], bx
add edx, 10 ; à §¬¥à ¤ ­­ëå + à §¬¥à § £®«®¢ª  SNAC
mov [flap.wDs], dx
mov eax, flap
mov ebx, snac_buff
call sendflap
 
pop edx
pop ebx
pop edi
pop esi
popf
ret
 
 
 
; Ž¡à ¡®âª  ¢á¥å ¯ ªâ®¢, ¯à¨å®¤ïé¨å ®â á¥à¢¥à 
; ECX <-- •¥­¤« ᮪¥â 
;
;
;
;
;
main_loop:
pushf
;push eax
;push ebx
;push edx
pushad
 
mov ecx, [socket]
;
; ¦¤¥¬ ¯ ª¥â
;
;m_loop:
;mov eax, 53
;mov ebx, 2
;int 40h
;cmp eax, 6 ; à §¬¥à § £®«® ª  FLAP
;jnc recived ; >=
;
; “室¨¬
;
;jmp m_fin
;mov eax, 5
;mov ebx, 5
;int 40h
;jmp m_loop
;
; ¥áâì ¯ ª¥â
;
;recived:
;mov eax, rflap
;mov ebx, rbuff
;call recvflap
;
; Ž¯à¥¤¥«ï¥¬ ⨯ ¯à¨­ï⮣® FLAP
;
xor ebx, ebx
mov bl, [rflap.bCh]
cmp bl, 1 ; “áâ ­®¢ª  ᮥ¤¨­¥­¨ï
jz m_login
cmp bl, 2
jz m_snac ; ®«ã祭 SNAC
cmp bl, 3
jz m_flap_err ; FLAP-level error
cmp bl, 4
jz m_close_conn ; ‡ ªàë⨥ ᮥ¤¨­¥­¨ï
cmp bl, 5
jz m_keep_alive ;
;
; Ž¡à ¡®âª  à áᮥ¤¨­¥­¨ï
;
m_close_conn:
write_debug 'Another Computer Use YOUR UIN!'
call srv_disconnect
call closesocket
jmp m_fin
;
; ®¡à ¡®âª  ᮥ¤¨­¥­¨ï
;
m_login:
;
; ¯à®¢¥à塞 ¢¥àá¨î ¯à®â®ª®« 
;
xor eax, eax
mov al, [mbuff+3]
cmp eax, 1
jnz m_login_other ; ¥ ¯®¤å®¤¨â
 
 
;
; £¥­¥à¨à㥬 á«ãç ©­ë© seq
; „«ï í⮣® ¡¥à¥¬ ¢à¥¬ï, ¯à®è¥¤è¥¥ á ¬®¬¥­â  § ¯ã᪠ á¨á⥬ë
;
;mov eax, 26
;mov ebx, 9
;int 40h
mcall 26, 9
mov [seq], ax
;
; Žâ¤ ¥¬ á¥à¢¥àã cookie
;
mov [flap.bCh], 1
mov [flap.wSn], ax
xor eax, eax
mov ax, [cookie_len]
add eax, 8 ; TLV len + protocol version len
mov [flap.wDs], ax
mov dword [buff], 01000000h ; 00 00 00 01 ®¬¥à ¯à®â®ª®« 
mov word [buff+4], 0600h ; 00 06 TLV.Type
 
mov ax, [cookie_len]
mov [buff+6], ah ;
mov [buff+7], al ; TLV.Length
 
mov edx, ecx ; edx <-- socket handle
 
mov ecx, eax ; ecx <-- cookie len
mov eax, srv_cookie ; Src
lea ebx, [buff+8]
call strcpy
mov ecx, edx ; ecx <-- socket handle
mov eax, flap
mov ebx, buff
call sendflap
jmp m_fin
 
m_login_other:
jmp m_fin
 
;
; Š ª ®¡à ¡®â âì ®è¨¡ªã, ï ­¥ §­ î
;
m_flap_err:
jmp m_fin
 
;
; ®ª  ­¥ ®¡à ¡ â뢠¥âáï
;
m_keep_alive:
jmp m_fin
 
 
;
; ®«ã祭 SNAC
;  á¯®§­ ¥¬ ¥£® ⨯
;
m_snac:
mov eax, rsnac
mov ebx, mbuff
call snacpar
xor ebx, ebx
xor edx, edx
mov bx, [rsnac.wFid]
mov dx, [rsnac.wSid]
 
cmp bx, 1
jz m_snac_1 ;Generic service controls
cmp bx, 2
jz m_snac_2 ;Location services
cmp bx, 3
jz m_snac_3 ;Buddy List management service
cmp bx, 4
jz m_snac_4 ;ICBM (messages) service
cmp bx, 9
jz m_snac_9 ;Privacy management service
cmp bx, 015h
jz m_snac_15 ;ICQ specific extensions service
cmp bx, 013h
jz m_snac_13 ;Server Side Information (SSI) service
jmp m_other_snac
;
; FAMILY 1
;
m_snac_1:
cmp dx, 7
jz m_snac_1_7
cmp dx, 3
jz m_snac_1_3
cmp dx, 018h
jz m_snac_1_18
cmp dx, 01Fh
jz m_snac_1_f
cmp dx, 13h
jz m_snac_13
cmp dx, 1
jz m_snac_1_1
jmp m_snac_1_other
;
; Rate limits information response
;
m_snac_1_7: ; Žâ¢¥ç ¥¬
mov [ssnac.wFid], 1 ; Family
mov [ssnac.wSid], 8 ; Subtype
mov [ssnac.dRi], 8
mov word [buff], 0100h ; 0001
mov word [buff+2], 0200h ; 0002
mov word [buff+4], 0300h ; 0003
mov word [buff+6], 0400h ; 0004
mov word [buff+8], 0500h ; 0005
mov eax, ssnac
mov ebx, buff
mov edx, 10 ;  §¬¥à ¤ ­­ëå
call sendsnac
;
; Client ask server location service limitations
;
mov [ssnac.wFid], 2 ; Family
mov [ssnac.wSid], 2 ; Subtype
mov [ssnac.dRi], 2
mov eax, ssnac
mov ebx, buff
xor edx, edx
call sendsnac
 
jmp m_fin
 
;
; Server supported snac families list
;
m_snac_1_3:
;
; Server sends supported services list
;
 
;
; SNAC(01,17)
; Client ask for services version numbers
;
mov [ssnac.wFid], 1 ; Family
mov [ssnac.wSid], 17h ; Subtype
mov [ssnac.dRi], 17h
;
; ‘¯¨á®ª á¥à¢¨á®¢, ª®â®àë¥ ­ ¬ ­ã¦­ë
;
; xx xx word family number #1
; xx xx word family version
; ... ... ...
;
 
;
; ®¯à ¢¨« ¨§ ¤ ¬¯  &RQ
;
mov word [buff], 0100h ; 0001
mov word [buff+2], 0300h ; 0003
 
mov word [buff+4], 1300h ; 0013
mov word [buff+6], 0200h ; 0002
 
mov word [buff+8], 0200h ; 0002
mov word [buff+10], 0100h ; 0001
 
mov word [buff+12], 0300h ; 0002
mov word [buff+14], 0100h ; 0001
 
mov word [buff+16], 1500h ; 0015
mov word [buff+18], 0100h ; 0001
 
mov word [buff+20], 0400h ; 0004
mov word [buff+22], 0100h ; 0001
 
mov word [buff+24], 0600h ; 0006
mov word [buff+26], 0100h ; 0001
 
mov word [buff+28], 0900h ; 0009
mov word [buff+30], 0100h ; 0001
 
mov word [buff+32], 1300h ; 0013
mov word [buff+34], 0400h ; 0004
 
mov word [buff+36], 1500h ; 0015
mov word [buff+38], 0400h ; 0004
 
mov word [buff+40], 1000h ; 0010
mov word [buff+42], 0100h ; 0001
 
 
 
mov eax, ssnac
mov ebx, buff
mov edx, 44
call sendsnac
 
jmp m_fin
 
 
;
; Server services versions
;
m_snac_1_18:
;
; Ž¡à ¡®âª¨ ¯®ª  ­¥â
;
 
;
; Client ask server for rate limits info
; SNAC(01,06)
;
mov [ssnac.wFid], 1 ; Family
mov [ssnac.wSid], 6 ; Subtype
mov [ssnac.dRi], 6
mov eax, ssnac
mov ebx, buff
xor edx, edx
call sendsnac
 
 
 
jmp m_fin
 
;
; Requested online info response
;
m_snac_1_f:
;
;’ãâ ¤®«¦­  ¡ëâì ­ è  ¨­ä®à¬ æ¨ï, ¯®ª  ®¡à ¡®âª¨ ­¥â
;
 
 
jmp m_fin
 
;
; Message of the day (MOTD)
;
m_snac_1_13:
;
; ¥ç¥£® ®¡à ¡ â뢠âì :-))
;
jmp m_fin
 
;
; ‘®®¡é¥­¨¥ ®¡ ®è¨¡ª¥
;
 
m_snac_1_1:
xor eax, eax
mov ax, word [mbuff+10]
call ntohs
data_debug 'SERVER SEND ERROR #', eax
 
 
jmp m_fin
 
 
m_snac_1_other:
data_debug 'Unknown SNAC Family 1 recived, type ', edx
jmp m_fin
 
 
 
;
; Family 2
;
m_snac_2:
cmp dx, 3
jz m_snac_2_3
jmp m_snac_2_other
;
; Server replies via location service limitations
;
m_snac_2_3:
;
; Ž¡à ¡®âª¨ ¯®ª  ­¥â
;
 
;
; ¯®áë« ¥¬ capabilities / profile
;
mov [ssnac.wFid], 2 ; Family
mov [ssnac.wSid], 4 ; Subtype
mov [ssnac.dRi], 4
 
;mov eax, CAPABILITIES
;mov ebx, buff
;push ecx
;mov ecx, 5 ; TLV.Type(0x05) - CLSID values
;mov edx, C_LEN
;call tlvstr
;pop ecx
mov word [buff], 0500h ; 00 05
mov eax, C_LEN
call htons
mov word [buff+2], ax
 
 
 
push ecx
 
mov eax, CAPABILITIES
lea ebx, [buff+4]
mov ecx, C_LEN
call strcpy
 
pop ecx
 
 
mov eax, ssnac
mov ebx, buff
mov edx, C_LEN+4 ; „«¨­  ¤ ­­ëå+à §¬¥à § £®«®¢ª  TLV
call sendsnac
 
;
; § ¯à è¨¢ ¥¬ server BLM service limitations
;
mov [ssnac.wFid], 3 ; Family
mov [ssnac.wSid], 2 ; Subtype
mov [ssnac.dRi], 2
mov eax, ssnac
mov ebx, buff
xor edx, edx
call sendsnac
 
 
jmp m_fin
 
m_snac_2_other:
write_debug 'Unknown SNAC Family 2 Recived'
jmp m_fin
 
 
 
;
; FAMILY 3
;
m_snac_3:
cmp dx, 3
jz m_snac_3_3
cmp dx, 0Bh
jz m_snac_3_b
cmp dx, 0Ch
jz m_snac_3_c
jmp m_snac_3_other
 
;
; Server replies via BLM service limitations
;
m_snac_3_3:
;
; Ž¡à ¡®âª¨ ¯®ª  ­¥â
;
 
;
; Client ask server for ICBM service parameters
;
mov [ssnac.wFid], 4 ; Family
mov [ssnac.wSid], 4 ; Subtype
mov [ssnac.dRi], 4 ; request-id
mov eax, ssnac
mov ebx, buff
xor edx, edx
call sendsnac
 
 
 
jmp m_fin
 
;
; User online notification
;
m_snac_3_b:
;
; ˆ§ ¢á¥© ¨­ä®à¬ æ¨¨ ¯®ª  ­ã¦¥­ ⮫쪮 áâ âãá
;
xor edx, edx ; ‘ç¥â稪 - ­®¬¥à UIN ¢ ¬ áᨢ¥
xor ecx, ecx
xor eax, eax
cld ; ‚ ­ ¯à ¢«¥­¨¨ 㢥«¨ç¥­¨ï  ¤à¥á®¢
 
dec edx
m_snac_3_b_loop:
inc edx
cmp edx, UINS
jnc m_snac_3_b_end ;>=
 
mov cl, [mbuff+10] ; „«¨­  “ˆ
mov eax, ecx
mov edi, UIN_LEN
imul edi, edx
lea edi, [uins+edi]
lea esi, [mbuff+11]
repe cmpsb
jnz m_snac_3_b_loop
;
; UIN Ž¯à¥¤¥«¥­
;
 
;
;  ©â¨ TLV á® áâ âãᮬ
; á®åà ­ïâì edx
 
xor esi, esi ; ‘ç¥â稪 TLV
 
xor ecx, ecx
mov ch, byte [mbuff + eax + 13] ; Š®«-¢® TLV ¢ 楯®çª¥
mov cl, byte [mbuff + eax + 14] ;
 
lea eax, [eax + 10 + 5] ; eax 㪠§ â¥«ì ­  楯®çªã TLV
lea eax, [mbuff + eax] ;
 
 
m_snac_3_b_next_tlv:
cmp esi, ecx
jz m_snac_3_b_endchain
 
 
xor ebx, ebx
mov bh, [eax] ;
mov bl, [eax + 1] ; TLV.Type
 
data_debug 'TLV type', ebx
 
cmp ebx, 0x06 ;TLV.Type(0x06) - user status
jz m_snac_3_b_status
 
;
;  §¡¨à ¥¬ 楯®çªã ¤ «ìè¥
;
 
get_next_tlv
inc esi
jmp m_snac_3_b_next_tlv
 
 
 
; FIXME ¥®¯â¨¬ «ì­® - ª®¤ ¡ã¤¥â 㤠«¥­
;
;lea ecx, [eax+10+11] ; +sizeof SNAC_head + offset #2 TLV
;mov ax, word [mbuff+ecx] ;#2 TLV.Type
;cmp ax, 0C00h ;dc info (optional)
;jz m_snac_3_b_dc
;cmp ax, 0A00h ;external ip address
;jz m_snac_3_b_extip
;jmp m_snac_3_b_bad_tlv
 
;m_snac_3_b_dc:
;
; à®¯ã᪠¥¬ íâ®â TLV
;
;lea ecx, [ecx+41]
;m_snac_3_b_extip:
;
; ˆ íâ®â :-)
;lea ecx, [ecx+8]
;mov ax, word [mbuff+ecx]
;cmp ax, 0600h ;TLV.Type(0x0A) - external ip address
;jz m_snac_3_b_status
;jmp m_snac_3_b_bad_tlv
;
;
 
 
m_snac_3_b_status:
;
; áâ âãá
;
mov ecx, eax
mov eax, dword [ecx + 4]
;mov eax, dword [mbuff+ecx+4]
call ntohl
;mov ebx, 4
;imul ebx, edx
;mov [stats+ebx], eax
mov ecx, eax
mov ebx, NAME_LEN
imul ebx, edx
lea ebx, [names+ebx]
mov eax, edx
call loadbb
jmp m_fin
 
 
m_snac_3_b_bad_tlv:
write_debug 'TLV Type Mismatch in SNAC(3,b)'
jmp m_fin
 
m_snac_3_b_end:
write_debug 'UIN not in local Contact List'
jmp m_fin
 
m_snac_3_b_endchain:
jmp m_fin
 
 
 
m_snac_3_c:
;
; User offline notification
;
xor edx, edx
xor ecx, ecx
 
dec edx
m_snac_3_c_loop:
inc edx
cmp edx, UINS
jnc m_snac_3_b_end ;>=
 
mov cl, [mbuff+10] ; „«¨­  “ˆ
mov edi, UIN_LEN
imul edi ,edx
lea edi, [uins+edi]
lea esi, [mbuff+11]
repe cmpsb
jnz m_snac_3_c_loop
;
; UIN Ž¯à¥¤¥«¥­
;
;mov eax, -1
;mov ebx, 4
;imul ebx, edx
;mov [stats+ebx], eax
mov ecx, -1
mov ebx, NAME_LEN
imul ebx, edx
lea ebx, [names+ebx]
mov eax, edx
call loadbb
jmp m_fin
 
 
 
 
 
 
m_snac_3_other:
write_debug 'Unknown SNAC Family 3 Recived'
jmp m_fin
 
 
;
; FAMILY 4
;
m_snac_4:
cmp dx, 5
jz m_snac_4_5
cmp dx, 7
jz m_snac_4_7
jmp m_snac_4_other
 
;
; Server sends ICBM service parameters to client
;
m_snac_4_5:
;
; Ž¡à ¡®âª¨ ¯®ª  ­¥â
;
 
;
; Client change default ICBM parameters command
;
mov [ssnac.wFid], 4 ; Family
mov [ssnac.wSid], 2 ; Subtype
mov [ssnac.dRi], 2 ; request-id
 
mov eax, ICBM_PARAMS
mov ebx, buff
push ecx
mov ecx, ICBMP_LEN
call strcpy
pop ecx
 
mov eax, ssnac
mov ebx, buff
mov edx, ICBMP_LEN
call sendsnac
 
;
; Client ask server PRM service limitations
;
mov [ssnac.wFid], 9 ; Family
mov [ssnac.wSid], 2 ; Subtype
mov [ssnac.dRi], 2 ; request-id
mov eax, ssnac
mov ebx, buff
xor edx, edx
call sendsnac
 
 
jmp m_fin
 
;
; Message for client from server
;
m_snac_4_7:
;
; Ž¯à¥¤¥«ï¥¬ ⨯ á®®¡é¥­¨ï ¯® ¯®«î message channel
;
xor eax, eax
mov ax, word [mbuff+10+8] ; +10 - à §¬¥à SNAC
; +8 ᬥ饭¨¥ ¤® message channel
cmp ax, 0100h ; 00 01
jz m_snac_ch1
cmp ax, 0200h
jz m_snac_ch2
cmp ax, 0400h
jz m_snac_ch4
jmp m_ch_other
;
; channel 1 plain text
;
m_snac_ch1:
;
; ’.ª ¢ ®ç¥à¥¤­®© à § ®¯¨á ­¨¥ ¯à®â®ª®«  ­¥ ᮢ¯ ¤ ¥â á ॠ«ì­®áâìî
; à §¡¨à ¥¬ ¢á¥ TLV ¯® ¯®à浪ã
 
mov eax, dword [mbuff+10] ; cookie
mov [msg_cookie1], eax
mov eax, dword [mbuff+10+4]
mov [msg_cookie2], eax ; ˆá¯®«ì§ãîâáï ¤«ï ¯®â¢¥à¦¤¥­¨ï ¯à¨¥¬  á®®¡é¥­¨©
 
mov al, [mbuff+10+10] ; Sender UIN length
mov [ui.bUinLength], al
 
push ecx
movzx ecx, al
 
lea eax, [mbuff+10+11] ; UIN string
lea ebx, [ui.bUin] ; Dest
call strcpy
 
lea ecx, [ecx+10+15] ; ¯¥à¢ë© TLV
 
m_snac_ch1_loop:
 
movzx eax, word [mbuff+ecx]
cmp eax, 0100h ;TLV.Type(0x01) - user class
jz m_snac_ch1_1
cmp eax, 0600h ;TLV.Type(0x06) - user status
jz m_snac_ch1_6
cmp eax, 0800h ; Unknown type
jz m_snac_ch1_8
cmp eax, 0500h ; Unknown type
jz m_snac_ch1_5
cmp eax, 0F00h ; TLV.Type(0x0f) - user idle time
jz m_snac_ch1_f
cmp eax, 0300h ; TLV.Type(0x03) - account creation time
jz m_snac_ch1_3
cmp eax, 0400h ; TLV.Type(0x04) - automated response flag
jz m_snac_ch1_4
cmp eax, 0200h ; TLV.Type(0x02) - message data
jz m_snac_ch1_mess
jmp m_snac_msg_tlv_err
 
;
; ‚®§¬®¦­®, ¤®¯®«­¨â¥«ì­ ï ¨¨ä®à¬ æ¨ï ¡ã¤¥â ®¡à ¡ â뢠âìáï
; ­® ¯®ª  ­¥â
 
m_snac_ch1_1:
movzx eax, word [mbuff+ecx+2] ; TLV.Length
call ntohs
lea ecx, [eax+ecx+4]
jmp m_snac_ch1_loop
 
m_snac_ch1_6:
 
mov eax, dword [mbuff+ecx+4] ; User status
call ntohl
mov [ui.dUserStatus], eax
 
 
movzx eax, word [mbuff+ecx+2] ; TLV.Length
call ntohs
lea ecx, [eax+ecx+4]
;
;
jmp m_snac_ch1_loop
 
m_snac_ch1_8:
movzx eax, word [mbuff+ecx+2] ; TLV.Length
call ntohs
lea ecx, [eax+ecx+4]
jmp m_snac_ch1_loop
 
m_snac_ch1_5:
movzx eax, word [mbuff+ecx+2] ; TLV.Length
call ntohs
lea ecx, [eax+ecx+4]
jmp m_snac_ch1_loop
 
m_snac_ch1_f:
movzx eax, word [mbuff+ecx+2] ; TLV.Length
call ntohs
lea ecx, [eax+ecx+4]
jmp m_snac_ch1_loop
 
m_snac_ch1_3:
movzx eax, word [mbuff+ecx+2] ; TLV.Length
call ntohs
lea ecx, [eax+ecx+4]
jmp m_snac_ch1_loop
 
 
m_snac_ch1_4:
;movzx eax, word [buff+ecx+2] ; TLV.Length
lea ecx, [ecx+4]
jmp m_snac_ch1_loop
 
 
 
m_snac_ch1_mess:
;
;
movzx eax, word [mbuff+ecx+4] ;
cmp eax, 0105h ; 05 fragment identifier (array of required capabilities)
jnz m_snac_ch1_fr_err ; 01 fragment version
 
movzx eax, word [mbuff+ecx+6] ; Length
call ntohs
 
lea ecx, [ecx+eax+8] ; à®¯ã᪠¥¬ byte array of required capabilities (1 - text)
 
movzx eax, word [mbuff+ecx] ; fragment identifier (message text)
cmp eax, 0101h ; fragment version
jnz m_snac_ch1_fr_err
 
movzx eax, word [mbuff+ecx+2] ; TLV Length
call ntohs
xchg eax, ecx
 
lea eax, [eax+8] ;  ç «® ⥪á⮢®£® á®®¡é¥­¨ï
lea ecx, [ecx-4] ; - sizeof Message charset number, Message charset subset
 
push eax
push ecx
 
;
; ‚뢮¤¨¬ Message From UIN
;
 
mov eax, MESS
call strlen
mov ecx, eax
 
mov eax, MESS
mov ebx, buff
call strcpy
 
lea ebx, [ebx + ecx]
 
;
; ¥¯«®å® ¡ë«® ¡ë ¢ë¢¥á⨠­¥ UIN   Nickname, ¥á«¨ ®­ ¥áâì ¢ ª®­â ªâ «¨áâ¥
;
xor esi, esi ; ‘ç¥â稪
 
m_snac_ch1_next_uin:
 
cmp esi, UINS
jz m_snac_ch1_notfound
 
mov edx, UIN_LEN
imul edx, esi
 
lea edx, [uins + edx]
movzx ecx, byte [ui.bUinLength]
strcmp edx, ui.bUin, ecx
jz m_snac_ch1_uin
 
inc esi
jmp m_snac_ch1_next_uin
 
 
;
; ®¤å®¤ï騩 UIN ¥áâì ¢ ª®­â ªâ-«¨áâ¥
;
m_snac_ch1_uin:
 
mov edx, NAME_LEN
imul edx, esi
 
lea edx, [names + edx]
mov eax, edx
 
 
call strlen
mov ecx, eax
 
mov eax, edx
call strcpy
 
jmp m_snac_ch1_msgfrom
 
 
;
; …᫨ ¯®¤å®¤ï饣® UIN ­¥â ¢ ª®­â ªâ-«¨áâ¥
;
m_snac_ch1_notfound:
lea eax, [ui.bUin]
movzx ecx, byte [ui.bUinLength]
call strcpy
 
;
; ‚뢮¤ á®®¡é¥­¨ï "®â ª®£®"
;
m_snac_ch1_msgfrom:
 
mov [ebx + ecx], byte 0
 
mov eax, buff
xor ebx, ebx
 
call writemsg
;
; ‘ ¬® á®®¡é¥­¨¥
;
 
pop ecx
pop eax
lea eax, [mbuff+eax]
 
mov ebx, buff
call strcpy
mov [ebx+ecx], byte 0
mov eax, buff
call win2dos
mov ebx, 00FF0000h
call writemsg
 
;
; ®¤â¢¥à¦¤ ¥¬ ¯à¨¥¬
;
 
pop ecx
;
; ®ª  ­¥ ॠ«¨§®¢ ­®, â.ª. ­¥ ¬®£ã ­ ©â¨ ª«¨¥­â, ª®â®àë© íâ® ¨á¯®«ì§ã¥â :-)
;
 
jmp m_fin
 
m_snac_msg_tlv_err:
write_debug 'TLV TYPE MISMATCH'
pop ecx
jmp m_fin
 
m_snac_ch1_fr_err:
write_debug 'UNKNOWN FRAGMENT IDENTIFIER OR FRAGMENT VERSION'
 
;m_snac_ch1_end:
pop ecx
 
jmp m_fin
 
;
; Channel 2 message format (rtf messages, rendezvous)
;
m_snac_ch2:
;
; ®â¯à ¢¨¬ á®®¡é¥­¨¥, çâ® ª ­ « ­¥ ¯®¤¤¥à¦¨¢ ¥âáï
; ­ã¦­ë ªãª¨ ¨ 㨭
mov eax, dword [mbuff+10]
mov [msg_cookie1], eax
mov eax, dword [mbuff+10+4]
mov [msg_cookie2], eax
 
mov al, [mbuff+10+10] ; Sender UIN length
mov [ui.bUinLength], al
 
push ecx
movzx ecx, al
 
lea eax, [mbuff+10+11] ; UIN string
lea ebx, [ui.bUin] ; Dest
call strcpy
 
 
mov [ssnac.wFid], 4 ; Family
mov [ssnac.wSid], 0Bh ; Subtype
mov [ssnac.dRi], 0Bh
 
mov eax, [msg_cookie1]
mov dword [buff], eax
mov eax, [msg_cookie2]
mov dword [buff+4], eax
mov word [buff+8], 0200h ; Channel 2
 
mov al, [ui.bUinLength]
mov [buff+10], al
lea eax, [ui.bUin]
lea ebx, [buff+11]
call strcpy
lea ecx, [ecx+11]
 
mov word [buff+ecx], 0100h ; reason code (1 - unsupported channel, 2 - busted payload, 3 - channel specific)
mov edx, ecx
 
pop ecx
mov eax, ssnac
mov ebx, buff
call sendsnac
 
 
jmp m_fin
 
;
; Channel 4 message format (typed old-style messages)
;
m_snac_ch4:
 
 
 
m_ch_other:
write_debug 'Unknown message channel'
 
jmp m_fin
 
 
m_snac_4_other:
write_debug 'Unknown SNAC Family 4 recived'
jmp m_fin
 
 
 
;
; FAMILY 9
;
m_snac_9:
cmp dx, 3
jz m_snac_9_3
jmp m_snac_9_other
 
;
; Server sends PRM service limitations to client
;
m_snac_9_3:
;
; Ž¡à ¡®âª¨ ¯®ª  ­¥â
;
if USE_SSI <> 0
 
;
; ‡ ¯à®á Š‹ á á¥à¢¥à 
;
 
;
; Request contact list (first time)
;
mov [ssnac.wFid], 13h ; Family
mov [ssnac.wSid], 04h ; Subtype
mov [ssnac.dRi], 04h ; request-id
 
mov eax, ssnac
mov ebx, buff
xor edx, edx
call sendsnac
 
 
else
 
 
; Žâª«î祭®, ⪠­¥ ¯®¤¤¥à¦¨¢ ¥âáï SIQ
;
 
;
; Client ask server for SSI service limitations
;
;mov [ssnac.wFid], 13h ; Family
;mov [ssnac.wSid], 2 ; Subtype
;mov [ssnac.dRi], 2 ; request-id
;mov eax, ssnac
;mov ebx, buff
;xor edx, edx
;call sendsnac
 
;
; ¯®á«¥¤­ïï áâ ¤¨ï ᮥ¤¨­¥­¨ï
;
 
;
; ‡ ¯à è¨¢ ¥¬ á¢®î ¨­ä®à¬ æ¨î
;
mov [ssnac.wFid], 1 ; Family
mov [ssnac.wSid], 0Eh ; Subtype
mov [ssnac.dRi], 0Eh ; request-id
 
mov eax, ssnac
mov ebx, buff
xor edx, edx ; TLV head len
call sendsnac
 
 
;
; Client sends its DC info and status to server
;
mov [ssnac.wFid], 1 ; Family
mov [ssnac.wSid], 1Eh ; Subtype
mov [ssnac.dRi], 1Eh ; request-id
 
mov [buff], 0 ; TLV type 06
mov [buff+1], 6h ;
mov [buff+2], 0 ; TLV data length
mov [buff+3], 4 ;
;
;
mov ax, STATUS_DCDISABLED ; DC disabled
call htons
mov word [buff+4], ax
mov ax, STATUS_ONLINE
mov [status], ax
mov word [buff+6], ax
 
mov eax, ssnac
mov ebx, buff
mov edx, 8 ; TLV head len+ data len
call sendsnac
 
 
;
; ‚ë£à㦠¥¬ ­  á¥à¢¥à Š‹
;
call uploadkl
 
;
; ‚ë£à㦠¥¬ ¨­¢¨§¨¡« «¨áâ, ¯®ª  ¯ãá⮩
;
mov [ssnac.wFid], 9 ; Family
mov [ssnac.wSid], 7 ; Subtype
mov [ssnac.dRi], 7
 
mov eax, ssnac
mov ebx, buff
xor edx, edx
call sendsnac
 
;
; ‚ &RQ …áâì ¯ ª¥â ãáâ ­®¢ª¨ à §à¥è¥­¨©. ï ¨á¯®«ì§ãî ¥£® ¡¥§ ¨§¬¥­¥­¨ï
; â.ª. ­¥ §­ î, çâ® ®­ ᮤ¥à¦¨â
; - ¢®§¬®¦­®, ¡ã¤ã ¨á¯®«ì§®¢ âì ¯®§¤­¥¥
 
;mov [ssnac.wFid], 15 ; Family
;mov [ssnac.wSid], 2 ; Subtype
;mov [ssnac.dRi], 2
 
;mov word [buff], 0100h ; 00 01 encapsulated META_DATA
;mov word [buff+2], 1000h ; 00 10 Len
;mov word [buff+4], 000Eh ; LE Len
;mov word [buff+10], 07D0h ; META_DATA_REQ
 
 
;mov eax, UIN
;call ascitoint
;mov dword [buff+6], eax
 
;mov word [buff+12], 0102h ; request sequence number (incrementing)
;mov word [buff+14], 0424h ; META_SET_PERMS_USERINFO
;mov [buff+16], 1 ; authorization (1-required, 0-not required)
;mov [buff+17], byte 0 ; webaware (0-no, 1-yes)
;mov [buff+18], 1 ; dc_perms (0-any, 1-contact, 2-authorization)
;mov [buff+19], 0 ;unknown
 
;mov eax, ssnac
;mov ebx, buff
;mov edx, 20
 
 
;
; Client READY command
;
mov [ssnac.wFid], 1 ; Family
mov [ssnac.wSid], 2 ; Subtype
mov [ssnac.dRi], 2 ; request-id
 
mov eax, FAMILY_ARR
mov ebx, buff
push ecx
mov ecx, FA_LEN
call strcpy
pop ecx
 
mov eax, ssnac
mov ebx, buff
mov edx, FA_LEN
call sendsnac
 
 
;
; ‡ ¯à è¨¢ ¥¬ offline á®®¡é¥­¨ï
;
mov [ssnac.wFid], 15h ; Family
mov [ssnac.wSid], 2 ; Subtype
mov [ssnac.dRi], 2 ; request-id
 
mov word [buff], 0100h ; TLV type 01
mov word [buff+2], 0A00h ; 00 0a „«¨­ 
mov word [buff+4], 0008h ; 08 00
lea eax, [vtable + vartable.uin]
call ascitoint
mov dword [buff+6], eax
 
mov word [buff+10], 003Ch ; 3C 00 - ‡ ¯à®á ­  ®ää« ©­®¢ë¥ á®®¡é¥­¨ï
mov word [buff+12], 0002 ; 02 00 - request sequence number
mov edx, 14 ; Ž¡é¨© à §¬¥à ¤ ­­ëå ¢ ¡ãä¥à¥
 
mov eax, ssnac
mov ebx, buff
call sendsnac
 
 
;
; ‡ ¯à è¨¢ ¥¬ ¨­ä®à¬ æ¨î ¢á¥å UIN
;
call getinfo
;
; § ¢¥à襭® ᮥ¤¨­¥­¨¥
;
mov [login], 2
 
 
end if ; USE_SSI = 0
 
jmp m_fin
 
m_snac_9_other:
write_debug 'Unknown SNAC Family 9 Recived'
jmp m_fin
 
 
;
; FAMILY 13
;
m_snac_13:
cmp dx, 3
jz m_snac_13_3
cmp dx, 6
jz m_snac_13_6
cmp dx, 0fh
jz m_snac_13_F
 
jmp m_snac_13_other
 
;
; Server sends SSI service limitations to client
;
m_snac_13_3:
;
; Ž¡à ¡®âª¨ ¯®ª  ­¥â
;
 
;
; SNAC(13,05) Client check if its local SSI copy is up-to-date
;
mov [ssnac.wFid], 13h ; Family
mov [ssnac.wSid], 5 ; Subtype
mov [ssnac.dRi], 5 ; request-id
mov eax, ssnac
;
;
;
mov [buff], 03Dh ;
mov [buff+1], 0E7h ; modification date/time of client local SSI copy
mov [buff+2], 48h ;
mov [buff+3], 17h ;
;
;
mov [buff+4], 00 ;
mov [buff+5], 00h ; number of items in client local SSI copy
mov ebx, buff
mov edx, 5
call sendsnac
 
jmp m_fin
 
 
;
; Server contact list reply
;
m_snac_13_6:
 
lea eax, [mbuff+10] ; ‚ eax § £à㦠¥¬  ¤à¥á ¯à¨¥¬­®£® ¡ãä¥à + à §¬¥à § £®«®¢ª  snac
 
call ssi_process_data ; Ž¡à ¡®âª  ¯ ª¥â  á Š‹
 
;
; €ªâ¨¢¨à㥬 SSI
;
 
mov [ssnac.wFid], 13h ; Family
mov [ssnac.wSid], 7 ; Subtype
mov [ssnac.dRi], 7 ; request-id
mov eax, ssnac
mov ebx, buff
xor edx, edx
call sendsnac
 
 
;
; ¯®á«¥¤­ïï áâ ¤¨ï ᮥ¤¨­¥­¨ï
;
 
;
; ‡ ¯à è¨¢ ¥¬ á¢®î ¨­ä®à¬ æ¨î
;
mov [ssnac.wFid], 1 ; Family
mov [ssnac.wSid], 0Eh ; Subtype
mov [ssnac.dRi], 0Eh ; request-id
 
mov eax, ssnac
mov ebx, buff
xor edx, edx ; TLV head len
call sendsnac
 
 
;
; Client sends its DC info and status to server
;
mov [ssnac.wFid], 1 ; Family
mov [ssnac.wSid], 1Eh ; Subtype
mov [ssnac.dRi], 1Eh ; request-id
 
mov [buff], 0 ; TLV type 06
mov [buff+1], 6h ;
mov [buff+2], 0 ; TLV data length
mov [buff+3], 4 ;
;
;
mov ax, STATUS_DCDISABLED ; DC disabled
call htons
mov word [buff+4], ax
mov ax, STATUS_ONLINE
mov [status], ax
mov word [buff+6], ax
 
mov eax, ssnac
mov ebx, buff
mov edx, 8 ; TLV head len+ data len
call sendsnac
 
 
;
; ‚ë£à㦠¥¬ ­  á¥à¢¥à Š‹
; FIXME ‚®§¬®¦­®, §¤¥áì ­¥ ­ã¦­  íâ  äã­ªæ¨ï
;call uploadkl
 
;
; ‚ë£à㦠¥¬ ¨­¢¨§¨¡« «¨áâ, ¯®ª  ¯ãá⮩
;
;mov [ssnac.wFid], 9 ; Family
;mov [ssnac.wSid], 7 ; Subtype
;mov [ssnac.dRi], 7
 
;mov eax, ssnac
;mov ebx, buff
;xor edx, edx
;call sendsnac
 
;
; ‚ &RQ …áâì ¯ ª¥â ãáâ ­®¢ª¨ à §à¥è¥­¨©. ï ¨á¯®«ì§ãî ¥£® ¡¥§ ¨§¬¥­¥­¨ï
; â.ª. ­¥ §­ î, çâ® ®­ ᮤ¥à¦¨â
; - ¢®§¬®¦­®, ¡ã¤ã ¨á¯®«ì§®¢ âì ¯®§¤­¥¥
 
;mov [ssnac.wFid], 15 ; Family
;mov [ssnac.wSid], 2 ; Subtype
;mov [ssnac.dRi], 2
 
;mov word [buff], 0100h ; 00 01 encapsulated META_DATA
;mov word [buff+2], 1000h ; 00 10 Len
;mov word [buff+4], 000Eh ; LE Len
;mov word [buff+10], 07D0h ; META_DATA_REQ
 
 
;mov eax, UIN
;call ascitoint
;mov dword [buff+6], eax
 
;mov word [buff+12], 0102h ; request sequence number (incrementing)
;mov word [buff+14], 0424h ; META_SET_PERMS_USERINFO
;mov [buff+16], 1 ; authorization (1-required, 0-not required)
;mov [buff+17], byte 0 ; webaware (0-no, 1-yes)
;mov [buff+18], 1 ; dc_perms (0-any, 1-contact, 2-authorization)
;mov [buff+19], 0 ;unknown
 
;mov eax, ssnac
;mov ebx, buff
;mov edx, 20
 
 
;
; Client READY command
;
mov [ssnac.wFid], 1 ; Family
mov [ssnac.wSid], 2 ; Subtype
mov [ssnac.dRi], 2 ; request-id
 
mov eax, FAMILY_ARR
mov ebx, buff
push ecx
mov ecx, FA_LEN
call strcpy
pop ecx
 
mov eax, ssnac
mov ebx, buff
mov edx, FA_LEN
call sendsnac
 
 
;
; ‡ ¯à è¨¢ ¥¬ offline á®®¡é¥­¨ï
;
mov [ssnac.wFid], 15h ; Family
mov [ssnac.wSid], 2 ; Subtype
mov [ssnac.dRi], 2 ; request-id
 
mov word [buff], 0100h ; TLV type 01
mov word [buff+2], 0A00h ; 00 0a „«¨­ 
mov word [buff+4], 0008h ; 08 00
lea eax, [vtable + vartable.uin]
call ascitoint
mov dword [buff+6], eax
 
mov word [buff+10], 003Ch ; 3C 00 - ‡ ¯à®á ­  ®ää« ©­®¢ë¥ á®®¡é¥­¨ï
mov word [buff+12], 0002 ; 02 00 - request sequence number
mov edx, 14 ; Ž¡é¨© à §¬¥à ¤ ­­ëå ¢ ¡ãä¥à¥
 
mov eax, ssnac
mov ebx, buff
call sendsnac
 
 
;
; ‡ ¯à è¨¢ ¥¬ ¨­ä®à¬ æ¨î ¢á¥å UIN
; FIXME ‚®§¬®¦­®, §¤¥áì ­¥ ­ã¦­  íâ  äã­ªæ¨ï
;call getinfo
;
; § ¢¥à襭® ᮥ¤¨­¥­¨¥
;
mov [login], 2
 
 
jmp m_fin
 
 
 
 
;
; Server tell client its local copy up-to-date
;
m_snac_13_F:
;
; Ž¡à ¡®âª¨ ­¥â
;
 
;
; Client activates server SSI data
;
mov [ssnac.wFid], 13h ; Family
mov [ssnac.wSid], 7 ; Subtype
mov [ssnac.dRi], 7 ; request-id
mov eax, ssnac
mov ebx, buff
xor edx, edx
call sendsnac
 
;
; ¯®á«¥¤­ïï áâ ¤¨ï ᮥ¤¨­¥­¨ï
;
 
;
; Client sends its DC info and status to server
;
mov [ssnac.wFid], 1 ; Family
mov [ssnac.wSid], 1Eh ; Subtype
mov [ssnac.dRi], 1Eh ; request-id
 
mov [buff], 0 ; TLV type 06
mov [buff+1], 6h ;
mov [buff+2], 0 ; TLV data length
mov [buff+3], 4 ;
;
;
mov ax, STATUS_DCDISABLED ; DC disabled
call htons
mov word [buff+4], ax
;
;
mov ax, [status]
mov word [buff+6], ax
 
mov eax, ssnac
mov ebx, buff
mov edx, 8 ; TLV head len+ data len
call sendsnac
 
;
; Client READY command
;
mov [ssnac.wFid], 1 ; Family
mov [ssnac.wSid], 2 ; Subtype
mov [ssnac.dRi], 2 ; request-id
 
mov eax, FAMILY_ARR
mov ebx, buff
push ecx
mov ecx, FA_LEN
call strcpy
pop ecx
 
mov eax, ssnac
mov ebx, buff
mov edx, FA_LEN
call sendsnac
 
 
;
; ‡ ¯à è¨¢ ¥¬ offline á®®¡é¥­¨ï
;
mov [ssnac.wFid], 15h ; Family
mov [ssnac.wSid], 2 ; Subtype
mov [ssnac.dRi], 2 ; request-id
 
mov word [buff], 0100h ; TLV type 01
mov word [buff+2], 0A00h ; 00 0a „«¨­ 
mov word [buff+4], 0008h ; 08 00
lea eax, [vtable + vartable.uin]
call ascitoint
mov dword [buff+6], eax
 
mov [buff+10], 003Ch ; 3C 00 - ‡ ¯à®á ­  ®ää« ©­®¢ë¥ á®®¡é¥­¨ï
mov [buff+12], 0002 ; 02 00 - request sequence number
mov edx, 14 ; Ž¡é¨© à §¬¥à ¤ ­­ëå ¢ ¡ãä¥à¥
 
mov eax, ssnac
mov ebx, buff
call sendsnac
 
 
 
jmp m_fin
 
m_snac_13_other:
write_debug 'Unknown SNAC Family 13 Recived'
jmp m_fin
 
 
 
 
;
; Family 15
;
 
m_snac_15:
cmp dx, 3
jz m_snac_15_3
jmp m_snac_15_other
 
 
;
; Server sends message #N
;
m_snac_15_3:
;
; Ž¯à¥¤¥«ï¥¬ ¯®¤â¨¯ ¯à¨­ï⮣® ¯ ª¥â 
;
 
;write_debug 'SNAC 15, 3'
 
xor eax, eax
mov ax, word [mbuff+10] ; + SNAC.head size
cmp ax, 0100h ; 00 01 TLV type
jnz m_snac_tlv_err
 
mov ax, word [mbuff+10+10]
cmp ax, 0041h ; Offline Message
jz m_snac_offline_mes
cmp ax, 0042h ; End messages
jz m_snac_offline_end
cmp ax, 07DAh
jz m_snac_meta_data
 
 
write_debug 'Unknown Subtype SNAC (15,3)'
jmp m_fin
 
m_snac_offline_mes:
mov eax, MESS ;
call strlen ; ‚뢮¤¨¬ áâபã á á®®¡é¥­¨¥¬ ® ®â¯à ¢¨â¥«¥ ¨ ¢à¥¬¥­¨ ®â¯à ¢ª¨
push ecx ;
mov ecx, eax ;
mov eax, MESS
mov ebx, buff
call strcpy
 
mov eax, dword [mbuff+14+10] ; Sender UIN
lea ebx, [buff+ecx] ; ®á«¥ áâà®çª¨ ® á®®¡é¥­¨¨
call int2strd
 
lea ebx, [ebx+eax]
mov [ebx], byte ' '
inc ebx
 
; + „«¨­  UIN
movzx eax, byte [mbuff+21+10] ; Day
call int2strd
 
lea ebx, [ebx+eax]
mov [ebx], byte '.'
inc ebx
 
movzx eax, byte [mbuff+20+10] ;Mounth
call int2strd
 
lea ebx, [ebx+eax]
mov [ebx], byte ' '
inc ebx
 
movzx eax, [mbuff+22+10] ; Hour
call int2strd
 
lea ebx, [ebx+eax]
mov [ebx], byte ':'
inc ebx
 
movzx eax, [mbuff+23+10] ; Minute
call int2strd
 
lea ebx, [ebx+eax]
;mov [ebx], byte ' '
;inc ebx
 
mov [ebx], byte 0 ; Str end
mov eax, buff
xor ebx, ebx
 
call writemsg
 
movzx ecx, word [mbuff+26+10] ; „«¨­  á®®®¡é¥­¨ï
lea eax, [mbuff+28+10]
mov ebx, buff
call strcpy
 
mov [ebx+ecx], byte 0
 
mov eax, buff
call win2dos ;¯¥à¥ª®¤¨à㥬
 
mov ebx, 00FF0000h ;–¢¥â
 
call writemsg
 
 
pop ecx
 
jmp m_fin
 
 
m_snac_offline_end:
;
; “¤ «ï¥¬ á®®¡é¥­¨ï ­  á¥à¢¥à¥
;
mov [ssnac.wFid], 15h ; Family
mov [ssnac.wSid], 2 ; Subtype
mov [ssnac.dRi], 0602h ; request-id
 
mov word [buff], 0100h ; 00 01 TLV.Type(1) - encapsulated META_DATA1
mov word [buff+2], 0A00h ; 00 0A TLV.Length
mov word [buff+4], 0008h ; 08 00 data chunk size (TLV.Length-2)
lea eax, [vtable + vartable.uin]
call ascitoint
mov dword [buff+6], eax ; xx xx xx xx (LE) client uin
mov word [buff+10], 003Eh ; 3E 00 (LE) data type: delete offline msgs request cmd
mov word [buff+12], 0007h ; xx xx (LE) request sequence number
 
mov edx, 14 ;  §¬¥à ¤ ­­ëå
mov eax, ssnac
mov ebx, buff
call sendsnac
 
 
 
jmp m_fin
 
;
; Žâ¢¥â ­  § ¯à®á ® ¯®«ì§®¢ â¥«ïå
;
m_snac_meta_data:
;
; Ž¯à¥¤¥«ï¥¬ ®ç¥à¥¤­®© ¯®¤â¨¯ :-)
;
mov ax, word [mbuff+10+14]
cmp ax, 0104h ;data subtype: META_SHORT_USERINFO
jz m_snac_short_userinfo
cmp ax, 00C8h
jz m_snac_basic_userinfo ;data subtype: META_BASIC_USERINFO
write_debug 'Unknown META DATA subtype'
jmp m_fin
 
 
 
m_snac_short_userinfo:
;
; ˆ§ ¢á¥© ¨­ä®à¬ æ¨¨ ¯®ª  ­ã¦¥­ ⮫쪮 ­¨ª
;
mov al, [mbuff+10+16]
cmp al, 0Ah ;success byte
jnz m_fin
 
movzx eax, word [mbuff+10+12] ;request sequence number
;
; ‚ § ¯à®á¥ ï ¨á¯®«ì§®¢ « ¯®à浪®¢ë© ­®¬¥à î§¥à  ¢ Š‹
lea ebx, [mbuff+10+19] ;nickname string
; „«¨­  áâப¨ ­¥ ­ã¦­ , â.ª. áâப  Null-Terminated
;Ž¯à¥¤¥«ï¥¬ áâ âãá
mov ecx, 4
imul ecx, eax
mov ecx, [stats+ecx]
 
call loadbb
 
 
 
jmp m_fin
 
;
; ⪠SIQ ­  § ¯à®á ª®à®âª®© ¨­äë ®â¢¥ç ¥â
; ¯ ª¥â®¬ ¡ §®¢®© ¨­ä®à¬ æ¨¨, ॠ«¨§ãî ¯®ª  ⮫쪮 ¥£®
;
m_snac_basic_userinfo:
mov al, [mbuff+10+16]
cmp al, 0Ah ;success byte
jnz m_fin
 
movzx eax, word [mbuff+10+12] ;request sequence number
;
; ‚ § ¯à®á¥ ï ¨á¯®«ì§®¢ « ¯®à浪®¢ë© ­®¬¥à î§¥à  ¢ Š‹
lea ebx, [mbuff+10+19] ;nickname string
; „«¨­  áâப¨ ­¥ ­ã¦­ , â.ª. áâப  Null-Terminated
;Ž¯à¥¤¥«ï¥¬ áâ âãá
mov ecx, 4
imul ecx, eax
mov ecx, [stats+ecx]
 
call loadbb
 
 
jmp m_fin
 
m_snac_tlv_err:
write_debug 'TLV TYPE MISMATCH'
 
jmp m_fin
 
m_snac_15_other:
 
write_debug 'Unknown SNAC Family 15 Recived'
 
jmp m_fin
 
 
m_other_snac:
write_debug 'Unknown SNAC recived'
jmp m_fin
 
 
 
m_fin:
;pop edx
;pop ebx
;pop eax
popad
popf
ret
 
; „«ï ¯¥à¥¢®¤  DWORD ¨§ Little Endian ¢ Big Endian
; ¨ ­ ®¡®à®â :-)
; <--EAX DWORD
; -->EAX
;
ntohl:
htonl:
;pushf
push ebx
;push ecx
 
xor ebx, ebx
 
mov bl, ah
mov bh, al
shl ebx, 16
shr eax, 16
mov bl, ah
mov bh, al
mov eax, ebx
 
;pop ecx
pop ebx
;popf
ret
 
 
; „«ï ¯¥à¥¢®¤  WORD ¨§ Little Endian ¢ Big Endian
; <--AX WORD
; -->AX WORD
;
 
ntohs:
htons:
;pushf
push ebx
 
xor ebx, ebx
mov bl, ah
mov bh, al
mov eax, ebx
 
pop ebx
;popf
ret
 
;
; ¯ àá¨â SNAC
; <--EAX 㪠§ â¥«ì ­  SNAC_head
; <--EBX 㪠§ â¥«ì ­  ¡ãää¥à
; -->EAX 㪠§ â¥«ì ­ ç «® ¤ ­­ëå = buffer+sizeof SNAC_head
;
;
snacpar:
pushf
push ecx
;push edx
 
mov cl, [ebx+1] ; Family (service) id number ¬« ¤è¨© ¡ ©â
mov ch, [ebx] ; áâ à訩
mov word [eax], cx
 
mov cl, [ebx+3] ; Family subtype id number
mov ch, [ebx+2] ;
mov word [eax+2], cx
 
mov cl, [ebx+5] ; SNAC flags
mov ch, [ebx+4] ;
mov word [eax+4], cx ;
mov cl, [ebx+7] ;
mov ch, [ebx+6] ;
mov word [eax+8], cx ; SNAC request id
mov cl, [ebx+8] ;
mov ch, [ebx+7] ;
mov word [eax+6], cx ;
add ebx, 10 ; §¬¥à § £®«®¢ª 
mov eax, ebx
 
 
;pop edx
pop ecx
popf
ret
 
;
; ¯ àá¨â userinfo block
; FIXIT
;
 
; userinfopar:
; pushf
;
;
;
;
;
;
; popf
; ret
 
;
; ¯®á뫪  á®®¡é¥­¨ï
; [eax] <-- ⥪áâ®¢ë© ¡ãä¥à \
; [ebx] <-- UIN / Null-terminated
 
sendmsg:
pushf
pushad
push eax
push ebx
 
mov [ssnac.wFid], 4h ; Family
mov [ssnac.wSid], 6 ; Subtype
mov [ssnac.dRi], 106h ; request-id
;
; ®«ãç ¥¬ ¢à¥¬ï á § ¯ã᪠ á¨á⥬ë, ¤«ï cookie
;
;mov eax, 26
;mov ebx, 9
;int 40h
mcall 26, 9
 
mov dword [buff], eax ; Cookie 1
mov dword [buff+4], eax ; Cookie 2
 
mov word [buff+8], 0100h ; Message channel 00 01
 
 
pop ebx
mov eax, ebx
call strlen
 
mov [buff+10], al
mov ecx, eax
mov eax, ebx
lea ebx, [buff+11]
call strcpy
lea ecx, [ecx+11]
 
mov word [buff+ecx], 0200h ; TLV.Type(0x02) - message data
;push ecx ;
; TLV.Length
 
mov word [buff+ecx+4], 0105h ; 05 01 01 - fragment version, 05 - fragment identifier
mov word [buff+ecx+6], 0100h ; data length
mov [buff+ecx+8], 01 ; byte array of required capabilities (1 - text)
 
mov [buff+ecx+9], 01 ; fragment identifier (text message)
mov [buff+ecx+10], 01 ; fragment version
 
pop ebx
mov eax, ebx
call strlen
mov edx, eax
lea eax, [eax+4] ; „«¨­  á®®¡é¥­¨ï + Message charset number+ Message language number
call htons
mov word [buff+ecx+11], ax
 
mov eax, edx
lea eax, [eax+13] ; + ¤«¨­  á«ã¦¥¡­ëå ¤ ­­ëå
call htons
mov word [buff+ecx+2], ax
 
 
mov word [buff+ecx+13], 0700h ; Message charset number
mov word [buff+ecx+15], 0300h ; Message language number
 
mov eax, ecx
mov ecx, edx ; Len
lea edx, [eax+17]
 
mov eax, ebx ;Source
lea ebx, [buff+edx] ;Dest
call strcpy
lea ecx, [ecx+edx] ; +String length
mov [buff+ecx], byte 0
mov eax, ebx
call dos2win
 
 
mov word [buff+ecx], 0600h ; TLV.Type(0x06) - store message if recipient offline
mov word [buff+ecx+2], 0 ; TLV.Length
 
lea edx, [ecx+4] ; +TLV_head length
mov eax, ssnac
mov ebx, buff
mov ecx, [socket]
call sendsnac
 
 
popad
popf
ret
 
;
; ‡ ¯à®á ¨­ä®à¬ æ¨¨ UIN®¢
;
getinfo:
pushad
pushf
;
; SNAC (15,2) - Meta information request
;
 
mov [ssnac.wFid], 15h ; Family
mov [ssnac.wSid], 2 ; Subtype
mov [ssnac.dRi], 702h ; request-id
 
mov word [buff], 0100h ;TLV.Type(1) - encapsulated META_DATA
mov word [buff+2], 1000h ; 00 10 TLV.Length
mov word [buff+4], 000Eh ; (LE) data chunk size (TLV.Length-2)
lea eax, [vtable + vartable.uin]
call ascitoint
mov dword [buff+6], eax ;(LE) request owner uin
mov word [buff+10], 07D0h ;data type: META_DATA_REQ
;mov word [buff+12], 0008h ; request sequence number <<<-- Œ®¦¥â ¬¥­ïâìáï FIXIT
mov word [buff+14], 04BAh ; data subtype: META_SHORTINFO_REQUEST
 
mov ecx, [socket]
mov edx, 20
 
xor esi, esi ; ‘ç¥â稪
xor eax, eax
 
gi_loop:
mov ebx, esi
mov word [buff+12], bx ; request sequence number
mov ebx, UIN_LEN
imul ebx, esi
mov al, [uins+ebx]
cmp al, 0
jz gi_end
 
lea eax, [uins+ebx]
call ascitoint
mov dword [buff+16], eax
 
mov eax, ssnac
mov ebx, buff
call sendsnac
inc esi
cmp esi, UINS
jnc gi_end
jmp gi_loop
 
 
 
 
 
 
gi_end:
popf
popad
ret
 
;
; ‡ £à㦠¥¬ «®ª «ì­ë© Š‹ ­  á¥à¢¥à ¤«ï ¯®«ã祭¨ï áâ âãá  î§¥à®¢
;
uploadkl:
pushf
pushad
;
; Add buddy(s) to contact list
;
mov [ssnac.wFid], 3 ; Family
mov [ssnac.wSid], 4 ; Subtype
mov [ssnac.dRi], 4 ; request-id
 
xor esi, esi ; ‘ç¥â稪
xor edx, edx ; ‡ ¯®«­¥­® ¡ ©â
 
ukk_loop:
mov ebx, UIN_LEN
imul ebx, esi
mov al, [uins+ebx]
cmp al, 0
jz ukk_end
lea eax, [uins+ebx]
call strlen
mov [buff+edx], al
inc edx
 
mov ecx, eax
lea eax, [uins+ebx] ; Source
lea ebx, [buff+edx]
call strcpy
add edx, ecx
inc esi
cmp esi, UINS
jz ukk_end
jmp ukk_loop
 
 
 
 
ukk_end:
mov eax, ssnac
mov ebx, buff
mov ecx, [socket]
call sendsnac
 
popad
popf
ret
 
;
;
;
sendkeep:
pushf
pushad
cmp [login], 2
jnz @f
mov ax, [timer]
cmp ax, 300 ;60 c
jb @f
mov [timer], 0
mov [flap.bId], FLAP_ID
mov [flap.bCh], 5 ;Keep alive
mov [flap.wDs], 0
inc [seq]
mov ax, [seq]
mov [flap.wSn], ax
mov eax, flap
mov ebx, buff
mov ecx, [socket]
call sendflap
 
 
@@:
popad
popf
ret
 
;
; ”ã­ªæ¨ï ¤«ï ãáâ ­®¢ª¨ áâ âãá 
; áâ âãá ¢ ¯¥à¥¬¥­­®© status
setstatus:
push eax
push ebx
push edx
;
; Client sends its DC info and status to server
;
mov [ssnac.wFid], 1 ; Family
mov [ssnac.wSid], 1Eh ; Subtype
mov [ssnac.dRi], 1Eh ; request-id
 
mov [buff], 0 ; TLV type 06
mov [buff+1], 6h ;
mov [buff+2], 0 ; TLV data length
mov [buff+3], 4 ;
;
;
mov ax, STATUS_DCDISABLED ; DC disabled
call htons
mov word [buff+4], ax
;
;
mov ax, [status]
mov word [buff+6], ax
 
mov eax, ssnac
mov ebx, buff
mov edx, 8 ; TLV head len+ data len
call sendsnac
 
pop edx
pop ebx
pop eax
ret
 
 
;
; Œ ªà®á ¯à®¯ã᪠¥â ¢á¥ ¯à®¡¥«ë ¢ áâப¥ ¤®
; 1 £® §­ ç é¥£® ᨬ¢®« 
; eax - 㪠§ â¥«ì ­  null-terminated áâபã
 
macro skip_spaces {
local ..sp_end, ..sp_loop
 
push ebx
push ecx
 
xor ebx, ebx
xor ecx, ecx
 
..sp_loop:
 
mov bl, [eax + ecx]
cmp bl, 0x20
jnz ..sp_end
 
 
inc ecx
jmp ..sp_loop
 
 
 
..sp_end:
lea eax, [eax + ecx]
 
pop ecx
pop ebx
}
 
 
 
 
 
;
; Ž¡à ¡®âª  ª®¬ ­¤
; ‚ ¥ax ¯¥à¥¤ ¥âáï 㪠§ â¥«ì ­  áâபã. Š®¬ ­¤  ¨  à£ã¬¥­âë à §¤¥«¥­ë ¯à®¡¥«®¬
; ª®¬ ­¤  ­ ç¨­ ¥âáï á /
; ¢ eax - १ã«ìâ â ¢ë¯®«­¥­¨ï ª®¬ ­¤ë, -1 ª®¬ ­¤  ­¥ áãé¥áâ¢ã¥â, 0 ®ª, ¤à㣨¥ § ¢¨áï⠮⠪®¬ ­¤ë
 
cmd:
push ebx
push ecx
push edi
push esi
 
;
; à®¢¥à¨âì ¯¥à¢ë© ᨬ¢®«
;
xor ebx, ebx
mov bl, [eax]
cmp bl, '/'
jnz cmd_end
 
;
;  §¤¥«¥­¨¥ ¯® 1© ¡ãª¢¥ ª®¬ ­¤ë
;
mov bl, [eax + 1]
 
cmp bl, 'c'
jz cmd_c
 
cmp bl, 'e'
jz cmd_e
 
cmp bl, 's'
jz cmd_s
 
jmp cmd_no
 
cmd_c:
 
cmd_e:
 
lea ebx, [eax + 1]
strcmp ebx, str_exit, str_exit.len
jz cmd_exit
 
jmp cmd_no
 
 
 
 
cmd_s:
 
lea ebx, [eax + 1]
strcmp ebx, str_status, str_status.len
jz cmd_status
jmp cmd_no
 
 
 
cmd_exit:
 
 
cmd_status:
;
; ãáâ ­®¢¨âì áâ âãá ¨ ¯®á« âì ¯ ª¥â ᬥ­ë áâ âãá 
;
lea eax, [eax + 1 + str_status.len]
skip_spaces
 
strcmp eax, str_online, str_online.len
jz cmd_st_online
 
strcmp eax, str_away, str_away.len
jz cmd_st_away
 
strcmp eax, str_na, str_na.len
jz cmd_st_na
 
strcmp eax, str_dnd, str_dnd.len
jz cmd_st_dnd
 
strcmp eax, str_bisy, str_bisy.len
jz cmd_st_bisy
 
strcmp eax, str_free4chat, str_free4chat.len
jz cmd_st_free4chat
 
;
; ‘â âãá ­¥ ®¯à¥¤¥«¥­.
; ‚뢥á⨠ᮮ¡é¥­¨¥ ® ¤®áâ㯭ëå áâ âãá å
;
mov eax, str_status_message
xor ebx, ebx
call writemsg
 
jmp cmd_end
 
 
cmd_st_online:
 
cmd_st_away:
 
cmd_st_na:
 
cmd_st_dnd:
 
cmd_st_bisy:
 
cmd_st_free4chat:
 
 
cmd_no:
 
cmd_end:
pop esi
pop edi
pop ecx
pop ebx
 
ret
 
 
 
 
; <--- initialised data --->
DATA
include "parser_data.inc"
include "ssi_data.inc"
include "comp_data.inc"
 
 
head db 'KI',0
 
 
;
MESS db 'Message from ', 0
CUSER db 'Current user: ', 0
 
;
; ‘¯¨á®ª IP á¥à¢¥à®¢ ICQ
 
;205.188.153.121
;icq_ip db '64.12.200.089',0
;icq_ip db '64.12.161.185',0
;icq_ip db '205.188.179.233',0
 
;
flap FLAP_head
rflap FLAP_head
;
ssnac SNAC_head ; ¤«ï ¯¥à¥¤ ç¨ SNAC
rsnac SNAC_head ; ¤«ï ¯à¨­ï⮣® SNAC
;
ui UI_head ; User info
;
procinfo process_information
;
;UIN db '362820484',0
;PASS db 'test',0
ID_STRING db 'ICQ Inc. - Product of ICQ (TM).2000b.4.65.1.3281.85',0
;ID_STRING db 'ICQ Inc. - Product of ICQ (TM).2001b.5.17.1.3642.85',0
 
 
;CAPABILITIES db 0x09, 0x46, 0x13, 0x49, 0x4C, 0x7F, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00,\
;0x97, 0xB1, 0x27, 0x51, 0x24, 0x3C, 0x43, 0x34, 0xAD, 0x22, 0xD6, 0xAB, 0xF7, 0x3F, 0x14, 0x92,\
CAPABILITIES db 0x2E, 0x7A, 0x64, 0x75, 0xFA, 0xDF, 0x4D, 0xC8, 0x88, 0x6F, 0xEA, 0x35, 0x95, 0xFD, 0xB6, 0xDF,\
'KOLIBRI KI(cq)',0,0
;0x09, 0x46, 0x13, 0x44, 0x4C, 0x7F, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00
 
; 1 áâப 
; {09461349-4C7F-11D1-8222-444553540000}
; Client supports channel 2 extended, TLV(0x2711) based messages. Currently used only by ICQ clients.
;ICQ clients and clones use this GUID as message format sign. Trillian client use another GUID
; in channel 2 messages to implement its own message format (trillian doesn't use TLV(x2711) in SecureIM channel 2 messages!).
;
; 2 áâப 
; {97B12751-243C-4334-AD22-D6ABF73F1492}
; Client supports RTF messages. This capability currently used by ICQ service and ICQ clients.
;
; 4 áâப 
; {0946134E-4C7F-11D1-8222-444553540000}
; Client supports UTF-8 messages. This capability currently used by AIM service and AIM clients
;
 
 
 
;
; From &RQ
;
 
;CAPABILITIES db 0x09, 0x46, 0x13, 0x49, 0x4C, 0x7F, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45,\ ;...P.F.IL.T‚"DE
; 0x53, 0x54, 0x00, 0x00, 0x09, 0x46, 0x13, 0x44, 0x4C, 0x7F, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45,\ ;ST...F.DL.T‚"DE
; 0x53, 0x54, 0x00, 0x00, 0x09, 0x46, 0x13, 0x4E, 0x4C, 0x7F, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45,\ ;ST...F.NL.T‚"DE
; 0x53, 0x54, 0x00, 0x00, 0x09, 0x46, 0x00, 0x00, 0x4C, 0x7F, 0x11, 0xD1, 0x82, 0x22, 0x44, 0x45,\ ;ST...F..L.T‚"DE
; 0x53, 0x54, 0x00, 0x00, 0x26, 0x52, 0x51, 0x69, 0x6E, 0x73, 0x69, 0x64, 0x65, 0x02, 0x07, 0x09,\ ;ST..&RQinside...
; 0x00, 0x00, 0x00, 0x00
 
 
C_LEN = 32
;C_LEN = 80
ICBM_PARAMS db 0, 0, 0, 0, 0, 0Bh, 01Fh, 040h, 3, 0E7h, 3, 0E7h, 0, 0, 0, 0
ICBMP_LEN = 16 ; ^^^ from &RQ
 
 
;
; from &rq
;
FAMILY_ARR db 0x00, 0x01, 0x00, 0x03, 0x01, 0x10, 0x04, 0x7B, 0x00, 0x13, 0x00, 0x02, 0x01, 0x10, 0x04, 0x7B,\
0x00, 0x02, 0x00, 0x01, 0x01, 0x01, 0x04, 0x7B, 0x00, 0x03, 0x00, 0x01, 0x01, 0x10, 0x04, 0x7B,\
0x00, 0x15, 0x00, 0x01, 0x01, 0x10, 0x04, 0x7B, 0x00, 0x04, 0x00, 0x01, 0x01, 0x10, 0x04, 0x7B,\
0x00, 0x06, 0x00, 0x01, 0x01, 0x10, 0x04, 0x7B, 0x00, 0x09, 0x00, 0x01, 0x01, 0x10, 0x04, 0x7B,\
0x00, 0x0A, 0x00, 0x01, 0x01, 0x10, 0x04, 0x7B, 0x00, 0x10, 0x00, 0x01, 0x00, 0x10, 0x06, 0x6A
 
;
;
;
 
FA_LEN = 50h
;
;
;
ID_NUM = 010Ah
MAJOR = 05h
;MAJOR = 04h
;MINOR = 041h
MINOR = 011h
LESSER = 01h
;BUILD = 0CD1h
BUILD = 0E3Ah
DISTR = 055h
;
;
 
TCB_ESTABLISHED = 4
TCB_CLOSED = 11
;
CL_LANG db 'en',0
CL_COUNTRY db 'us',0
 
sbuff db 1024 dup 0 ; ãä¥à ¤«ï ¯¥à¥¤ ç¨ ¨á¯®«ì§ã¥âáï ¢­ãâਠsendflap
 
;recived db 0 ; à¨­ïâ® ¤ ­­ëå ¨§ ⥫  ¯ ª¥â 
 
;rbuff db 1024 dup 0 ; à¨¥¬­ë© ¡ãä¥à
tbuff db 512 dup 0 ; „«ï TLV
srv_cookie db 512 dup 0 ; Šãª¨ ¤«ï  ¢â®à¨§ æ¨¨
bos_address db 128 dup 0 ; €¤à¥á BOS á¥à¢¥à 
cookie_len dw 0 ; „«¨­  ªãª¨
seq dw 0 ; Sequence number
bos_ip dd 0
bos_port dd 0
status dw 0 ; status
 
mbuff db 2048 dup 0 ; „«ï ¯à¨¥¬ 
MBUFF_SIZE = 2048
 
hrf db 0 ; ”« £ ¯à¨¥¬  § £®«®¢ª 
 
mouse_flag dd 0
socket dd 0
login db 0
 
msg_cookie1 dd 0 ; ˆá¯®«ì§ãîâáï ¤«ï ¯®â¢¥à¦¤¥­¨ï ¯à¨¥¬  á®®¡é¥­¨©
msg_cookie2 dd 0 ;
 
curruser db 0 ; ⥪ã騩 ¯®«ì§®¢ â¥«ì, ª®â®à®¬ã ¡ã¤ãâ ®â¯à ¢«ïâìáï á®®¡é¥­¨ï
; - ®¬¥à ¢ Š‹ ¯® ¯®à浪ã
 
 
timer dw 0
 
;ltest db "ADMIN",0
buff db 1024 dup 0
; lbuff db 8 dup 0 ; „«ï 1 ¯ ª¥â  ®â á¥à¢¥à 
 
;
; ‘âப¨ ª®¬ ­¤ ¤«ï áà ¢­¥­¨ï
;
str_status db 'status '
str_status.len = $ - str_status
str_exit db 'exit '
str_exit.len = $ - str_exit
;
; ‘âப¨ áâ âãᮢ ¤«ï áà ¢­¥­¨ï
;
str_away db 'away'
str_away.len = $ - str_away
 
str_dnd db 'dnd'
str_dnd.len = $ - str_dnd
 
str_bisy db 'bisy'
str_bisy.len = $ - str_bisy
 
str_na db 'na'
str_na.len = $ - str_na
 
str_online db 'online'
str_online.len = $ - str_online
 
str_free4chat db 'free4chat'
str_free4chat.len = $ - str_free4chat
 
str_status_message db '„®áâã¯­ë¥ áâ âãáë: away, bisy, na, dnd, online, free4chat',0
 
 
;
;
;
 
cfg_message db 'Config:',0
 
;
; EDITBOXES
;
inputbuff:
rb 512
 
inputbox edit_box 490,10,460,0xffffff,0x6a9480,0,0xAABBCC,0,511,inputbuff,ed_focus,0,0
 
 
; <--- uninitialised data --->
UDATA
 
 
MEOS_APP_END
; <--- end of MenuetOS application --->
/programs/network_old/icq/trunk/lang.inc
0,0 → 1,0
lang fix en
/programs/network_old/icq/trunk/README.TXT
0,0 → 1,37
v 0.01
 
 
Âåðñèÿ òåñòîâàÿ, ïîýòîìó ìíîãî íåäîðàáîòîê
è âûâîäÿòñÿ îòëàäî÷íûå ñîîáùåíèÿ
 
Ïîääåðæèâàåòñÿ:
* Ñåðâåðíûé ÊË
* ïåðåäà÷à/ïðèåì ñîîáùåíèé plain-text
* Ïåðåêîäèðîâêà CP866<->CP1251
* Ïðèåì offline ñîîáùåíèé
* Îòïðàâêà ñîîáùåíèÿ ïîëüçîâàòåëþ íå â êîíòàêò-ëèñòå
/UIN Ñîîáùåíèå
 
Íåäîðàáîòêè: Ìíîãî :-)
* Îòêëþ÷åíî çàêðûòèå ñîêåòîâ - ÿäðî âèñíåò, ïðè
ïîïûòêå çàêðûòü ñîêåò
 
* Âñå ñîîáùåíèÿ îò ðàçíûõ þçåðîâ â îäíîì ïîëå âûâîäà
* Íåëüçÿ ñìåíèòü ñòàòóñ
* Íåëüçÿ îòêëþ÷èòñÿ, îïÿòü æå èç-çà çàêðûòèÿ ñîêåòîâ
* Íå ïîääåðæèâàåòñÿ UTF-8 è RTF ñîîáùåíèÿ
* Èç èíôîðìàöèè î þçåðå äîñòóïåí òîëüêî íèê
* editbox èíîãäà âåäåò ñåáÿ ñòðàííî :-)
* ..........
 
 
 
Âûðàæàþ áëàãîäàðíîñòü âñåì ðàçðàáîò÷èêàì OS Kolibri
çà ïðåêðàñíûå èíñòðóìåíòû è äîêóìåíòàöèþ, áåç êîòîðîé ÿ áû
íè÷åãî íå íàïèñàë :-), à òàêæå ïðîåêòó iserverd.khstu.ru,
ñåðâåð è îïèñàíèÿ ïðîòîêîëîâ êîòîðîãî ÿ èñïîëüçîâàë.
 
 
 
åñëè ó âàñ åñòü êàêèå-íèáóäü ïðåäëîæåíèÿ, ïðèñûëàéòå íà lv4evil@yandex.ru
 
/programs/network_old/icq/trunk/SSI_INFO.txt
0,0 → 1,56
00 00 08 00 07 36 32 31 38 38 39 37 0A 1E 43 18 .....6218897..C.
^^ byte Version number of SSI protocol (currently 0x00)
^^ ^^ word Number of items in this snac
^^ ^^ word Length of the item name
^^ ^^ ^^ ^^ ^^ ^^ ^^ string Item name string
^^ ^^ word Group ID#
^^ ^^ word Item ID#
 
 
 
00 00 00 0A 01 31 00 06 46 75 6E 42 6F 6F 00 09 .....1..FunBoo..
^^ ^^ word Type of item flag (see list bellow)
^^ ^^ word Length of the additional data
^^ ^^ word TLV.Type (TLV #1)
^^ ^^ word TLV.Length
^^ ^^ ^^ ^^ ^^ ^^ TLV.Value
 
 
 
 
 
 
31 37 36 33 33 33 30 37 38 17 B7 2A 18 00 00 00 176333078..*....
09 01 31 00 05 45 2E 53 2E 56 00 07 36 32 31 38 ..1..E.S.V..6218
38 39 38 23 8C 12 A1 00 00 00 09 01 31 00 05 74 898#........1..t
68 6F 72 64 00 07 46 72 69 65 6E 64 73 7F ED 00 hord..Friends...
00 00 01 00 00 00 0A 43 6F 2D 57 6F 72 6B 65 72 .......Co-Worker
73 55 7F 00 00 00 01 00 00 00 07 36 32 31 38 38 sU.........62188
39 35 23 8C 08 80 00 00 00 0D 01 31 00 09 52 65 95#........1..Re
67 72 65 73 73 6F 72 00 07 36 32 35 31 37 32 33 gressor..6251723
23 8C 05 83 00 00 00 0D 01 31 00 05 47 68 6F 73 #........1..Ghos
74 00 66 00 00 00 07 36 32 31 33 39 34 39 23 8C t.f....6213949#.
26 9A 00 00 00 0D 01 31 00 05 6D 69 63 6B 79 00 &......1..micky.
66 00 00 3B B7 4B 7D
 
 
 
 
 
0x0000 Buddy record (name: uin for ICQ and screenname for AIM)
0x0001 Group record
0x0002 Permit record ("Allow" list in AIM, and "Visible" list in ICQ)
0x0003 Deny record ("Block" list in AIM, and "Invisible" list in ICQ)
0x0004 Permit/deny settings or/and bitmask of the AIM classes
0x0005 Presence info (if others can see your idle status, etc)
0x0009 Unknown. ICQ2k shortcut bar items ?
0x000E Ignore list record.
0x000F Last update date (name: "LastUpdateDate").
0x0010 Non-ICQ contact (to send SMS). Name: 1#EXT, 2#EXT, etc
0x0013 Item that contain roster import time (name: "Import time")
0x0014 Own icon (avatar) info. Name is an avatar id number as text
 
 
 
 
[TLV(0x0131), itype 0x00, size XX] - This stores the name that the contact should show up as in the contact list. It should initially be set to the contact's nick name, and can be changed to anything by the client.
/programs/network_old/icq/trunk/STDCALL.INC
0,0 → 1,151
..Open = 0
 
; When some procedure is not finished with 'endp' macro,
; "Unexpected end of file" error, occur without any info, where is error.
; in this case, comment followind 2 rows and uncomment next two.
; proc_used and endp_used are optimized versions of the macroses.
; proc_debug and endp_debug are debug versions. When you use debug
; versions, error message will show you where is missing 'endp'.
;
; Don't forget to recompile with *_used versions, to get optimised
; binary with all not used procedure excluded.
 
macro RestoreEx [name]
{
macro rstr#name _% RESTORE name %_
macro rstr _% %_
rstr#name
purge rstr,rstr#name
}
 
_% fix {
%_ fix }
restore fix RestoreEx
 
 
proc fix proc_used
endp fix endp_used
;proc fix proc_debug
;endp fix endp_debug
 
macro proc_used name,[arg] { ; define procedure
common
proc_args fix arg
; if ~ used name
; if ~..ShowSkipped eq OFF
; display 1,'Procedure skiped: ',`name, $0d, $0a
; end if
; else
if used name
name:
virtual at ebp+8
if ~ arg eq
forward
local ..arg
..arg dd ?
arg equ ..arg
common
end if
..ret = $ - (ebp+8)
end virtual
local ..dynamic_data,..dynamic_size
dynamic_data equ ..dynamic_data
dynamic_size equ ..dynamic_size
virtual at ebp - dynamic_size
dynamic_data:
}
 
 
macro proc_debug name,[arg] { ; define procedure
common
proc_args fix arg
if ..Open > 0
Error! Missing 'endp' before procedure `name
end if
 
..Open = ..Open+1
 
name:
virtual at ebp+8
if ~ arg eq
forward
local ..arg
..arg dd ?
arg equ ..arg
common
end if
..ret = $ - (ebp+8)
end virtual
local ..dynamic_data,..dynamic_size
dynamic_data equ ..dynamic_data
dynamic_size equ ..dynamic_size
virtual at ebp - dynamic_size
dynamic_data:
}
 
 
 
macro begin { ; begin procedure instructions
; continue from "proc" macro.
; align 4
rb (4 - ($ - dynamic_data) and 11b) and 11b ; align the stack at dword.
dynamic_size = $ - dynamic_data
end virtual
 
if (dynamic_size = 0)
if ..ret <> 0
push ebp ; smaller is dynamic_size = 0
mov ebp, esp
end if
else
enter dynamic_size, 0
end if
}
 
 
macro return { ; return from procedure
; continue from "enter" macro.
if ..ret <> 0
leave
ret ..ret
else
if dynamic_size <> 0
leave
end if
ret
end if
}
 
 
macro endp_used {
restore proc_args
end if
}
 
macro endp_debug {
restore proc_args
..Open = ..Open - 1
}
 
 
macro _reversepusharg [arg] {
reverse
pushd arg
}
 
 
macro stdcall proc,[arg] { ; call procedure
common
if ~ arg eq
_reversepusharg arg
end if
call proc
}
 
 
macro invoke proc,[arg] { ; invoke procedure (indirect)
common
stdcall [proc],arg
}
 
;end of file
/programs/network_old/icq/trunk/build_ru.bat
0,0 → 1,2
@fasm ki.asm ki
 
/programs/network_old/icq/trunk/comp.inc
0,0 → 1,972
;
; ­ à¨á®¢ âì ¯àאַ㣮«ì­¨ª
; x1,y1 ---------|
; | |
; | |
; |-------------x2,y2
;
macro rect x1, y1, x2, y2, color
{
pushad
 
;mov edx, color
; ------------
;mov eax, 38
mov ebx, x1
shl ebx, 16
add ebx, x2
mov ecx, y1
shl ecx, 16
add ecx, y1
;int 40h
mcall 38, ebx, ecx, color
 
; ------------
;mov eax, 38
mov ebx, x1
shl ebx, 16
add ebx, x2
mov ecx, y2
shl ecx, 16
add ecx, y2
;int 40h
mcall 38, ebx, ecx, color
; |
; |
; |
;mov eax, 38
mov ebx, x1
shl ebx, 16
add ebx, x1
mov ecx, y1
shl ecx, 16
add ecx, y2
;int 40h
mcall 38, ebx, ecx, color
; |
; |
; |
;mov eax, 38
mov ebx, x2
shl ebx, 16
add ebx, x2
mov ecx, y1
shl ecx, 16
add ecx, y2
;int 40h
mcall 38, ebx, ecx, color
popad
}
 
;
; ‚뢮¤ ­  íªà ­ ¡ãä¥à  á® áâப ¬¨
;
 
scbuff db 80*41 dup 0
; 60 - ¤«¨­  áâப¨
; 41 - ª®«¨ç¥á⢮ áâப
;
ind db 0 ; ’¥ªã騩 ¨­¤¥ªá
;
;
x_s dw 15 ; Š®®à¤¨­ âë «¥¢®£® ¢¥àå­¥£® 㣫  FIXIT
y_s dw 38 ;
 
; ‚ëá®â  áâப¨
SH = 10
xlen dw 80 ; ¤«¨­  áâப¨
;ylen dw 128 ; ª®«¨ç¥á⢮ áâப
ylen dw 40
 
;®á«¥¤­¨¥ 4 ¡ ©â  ¢ áâப¥ ®¡®§­ ç îâ 梥â
 
printbuff:
pushad
 
;
;  à¨á㥬 ¡¥«ë© ¯àאַ㣮«ì­¨ª
;
;mov eax, 13
;mov ebx, 15*65536+480
;mov ecx, 31*65536+418
;mov edx, 0FFFFFFh
;int 40h
mcall 13, (15 * 65536 + 480), (31 * 65536 + 418), 0x00FFFFFF
 
 
 
xor ecx, ecx ; ‘ç¥â稪
;xor eax, eax
xor ebx, ebx
;xor edx, edx
 
pb_loop:
xor edx, edx
xor eax, eax
mov dl, [ind] ; ˆ­¤¥ªá
mov ax, [ylen]
;mul edx
cmp ecx, eax
ja pr_end
;
;
add edx, ecx ;à¨¡ ¢¨¬ áç¥â稪
xor eax, eax
mov ax, [ylen]
cmp edx, eax ;ˆ­¤¥ªá ¬¥­ìè¥ ª®«¨ç¥á⢠ áâப
jna @f ;<=
sub edx, eax ;…᫨ ¡®«ìè¥, áç¨â ¥¬ á ­ ç « 
dec edx
@@:
;
mov bx, [x_s] ; Š®®à¤¨­ â  X
shl ebx, 16 ;
push ecx
mov eax, SH ; ‚ëç¨á«ï¥¬ ¬¥á⮯®«®¦¥­¨¥ áâப¨
imul eax, ecx ;
;mov ecx, eax
;xor eax, eax
 
;mov ax , [x_s]
xor ecx, ecx
mov cx, [y_s]
add ecx, eax
add ebx, ecx ; Š®®à¤¨­ â  Y
;
xor eax, eax
mov ax, [xlen] ;¤«¨­  áâப¨
imul edx, eax ;“¬­®¦ ¥¬ áç¥â稪 ­  ¤«¨­ã áâப¨, ¯®«ãç ¥¬ ᬥ饭¨¥ ®â­®á¨â¥«ì­® ­ ç «  ¡ãä¥à 
;mov edx, eax
add edx, scbuff
 
xor eax, eax
mov ax, [xlen]
sub eax, 4
xor ecx, ecx
mov ecx, dword [edx+eax] ; ®á«¥¤­¨¥ 4  ©â  á 梥⮬
or ecx, 0x80000000 ; ‚뢮¤¨âì ASCIIZ
;mov eax, 4
;mov esi, -1 ; For Menuet
;int 40h
mcall 4, ebx, ecx, edx
pop ecx
inc ecx
jmp pb_loop
 
 
pr_end:
popad
ret
 
;
; Žâ« ¤®ç­ë¥ á®®¡é¥­¨ï
;
macro write_debug str
{
local ..string, ..label, ..end, ..loop, ..fin, ..n_inc
jmp ..label
 
..string db str, 0
 
..label:
pushad
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
 
mov bl, [ind]
mov ax, [xlen]
imul ebx, eax
add ebx, scbuff
 
;
; —¥à­ë© 梥⠢뢮¤ 
;
mov edx, ebx
lea edx, [edx+eax]
sub edx, 4 ;4 ¡ ©â  á 梥⮬
mov dword [edx], dword 0
xor edx, edx
 
..loop:
mov dl, [..string+ecx]
cmp dl, 0
jz ..end
mov [ebx+ecx], dl
inc ecx
jmp ..loop
..end:
mov [ebx+ecx], dl
xor ebx, ebx
mov bl, [ind]
cmp bx, [ylen]
jz ..n_inc
inc bl
jmp ..fin
..n_inc:
xor bl, bl
 
..fin:
mov [ind], bl
call printbuff
;call draw_window
popad
}
 
;
; Š­®¯ª 
;
macro draw_button x, y, xlen, ylen, id, str
{
pushad
local ..string, ..label
jmp ..label
..string db str, 0
 
..label:
mcall 8, (x*65536+xlen), (y*65536+ylen), id, 0x4466aa
 
mcall 4, ((x+5)*65536+y+ylen/2-3), 0x80FFFFFF, ..string
 
popad
}
 
;
; Žâ« ¤®ç­ë© ¢ë¢®¤ ¤ ­­ëå
;
macro data_debug str, rg
{
pushad
local ..string, ..end, ..loop, ..strend, ..fin, ..label, ..n_inc
jmp ..label
..string db str, 20h, 0, 0, 0, 0, 0, 0, 0, 0, 0
..strend:
 
..label:
;xor eax, eax
;xor ebx, ebx
xor ecx, ecx
xor edx, edx
 
mov eax, rg
lea ebx, [..strend-9]
call int2str
 
xor eax, eax
xor ebx, ebx
 
mov bl, [ind]
mov ax, [xlen]
imul ebx, eax
add ebx, scbuff
 
;
; —¥à­ë© 梥⠢뢮¤ 
;
mov edx, ebx
lea edx, [edx+eax]
sub edx, 4 ;4 ¡ ©â  á 梥⮬
mov dword [edx], dword 0
xor edx, edx
 
..loop:
mov dl, [..string+ecx]
cmp dl, 0
jz ..end
mov [ebx+ecx], dl
inc ecx
jmp ..loop
..end:
mov [ebx+ecx], dl
xor ebx, ebx
mov bl, [ind]
cmp bx, [ylen]
jz ..n_inc
inc bl
jmp ..fin
..n_inc:
xor bl, bl
 
..fin:
mov [ind], bl
 
 
 
call printbuff
;call draw_window
 
popad
}
 
; <--EAX
; -->[ebx]
;
int2str:
pushf
;push ebx
push ecx
push edx
push esi
 
;xor ebx, ebx
xor ecx, ecx
 
i_loop:
mov edx, eax
push ecx
shl ecx, 2
mov esi, 28
sub esi, ecx
mov ecx, esi
shr edx, cl
pop ecx
and dl, 0fh ;Žâ¤¥«¨âì ¬« ¤è¨¥ 4 ¡¨â 
cmp dl, 0Ah ;ãª¢ 
jnc @f
or dl, 0x30
jmp i_n1
 
@@:
sub dl, 9
or dl, 0x40
i_n1:
mov [ebx+ecx], dl
inc ecx
cmp ecx, 8
jnz i_loop
 
pop esi
pop edx
pop ecx
;pop ebx
popf
ret
 
 
 
;
; „«ï ¢ë¢®¤  á®®¡é¥­¨©
; [eax] <-- null-terminated string
; ebx <-- color
;
writemsg:
pushad
xor edi, edi
 
wm_loop:
xor esi, esi ; …᫨ 1 - ¥áâì ¥é¥ á¨¬¢®«ë ¢ áâப¥
lea eax, [eax+edi]
 
push ebx
push eax
 
xor eax, eax
xor ebx, ebx
 
 
mov bl, [ind]
mov ax, [xlen]
imul ebx, eax
add ebx, scbuff
 
 
 
 
;
;  §¡¨¢ ¥¬ áâபã á®®¡é¥­¨ï ­  ­¥áª®«ìª® áâப ¯® xlen-4 (â.ª ¢ ª®­æ¥ ¤¢®©­®¥ á«®¢® - 梥â áâப¨)
;
 
 
pop eax
mov edx, eax
call strlen
 
movzx ecx, [xlen]
cmp eax, ecx
jc @f ;<
 
movzx edi, [xlen]
lea edi, [edi-4]
 
mov ecx, eax
inc esi
 
 
@@:
 
mov eax, edx
call strcpy
 
mov [ebx+ecx], byte 0x00
 
xor eax, eax
mov ax, [xlen]
sub eax, 4
pop ecx
mov dword [ebx+eax], ecx ; ®á«¥¤­¨¥ 4  ©â  á 梥⮬
 
 
xor eax, eax
mov al, [ind]
cmp ax, [ylen]
jz @f
inc al
jmp ..fin
@@:
xor al, al
 
..fin:
mov [ind], al
mov ebx, ecx ; 梥â
mov eax, edx ; 㪠§ â¥«ì ­  áâபã
 
cmp esi, 0
jnz wm_loop
 
call printbuff
 
popad
ret
 
;
;
 
 
 
; <--EAX ¥à¥¢®¤ ¨§ 16 ¢ 10 ä®à¬ã
; -->[ebx] áâப 
; --> eax ¤«¨­ 
int2strd:
pushf
;push ebx
push ecx
push edx
push esi
;push edi
 
;xor ebx, ebx
xor ecx, ecx
mov esi, 10
 
id_loop:
xor edx, edx
div esi
 
and dl, 0fh ;Žâ¤¥«¨âì ¬« ¤è¨¥ 4 ¡¨â 
or dl, 0x30
mov [ebx+ecx], dl
cmp eax, 10
inc ecx
jnc id_loop
 
and al, 0fh ;Žâ¤¥«¨âì ¬« ¤è¨¥ 4 ¡¨â 
or al, 0x30
 
mov [ebx+ecx], al
;mov [ebx+ecx+1], byte 0
inc ecx
mov eax, ecx
; ¯¥à¥¢¥à­ãâì ¯®«ã祭­ãî áâபã
;
;xor edx, edx
 
;mov esi, 2
;div esi
shr eax, 1
 
xor edx, edx
 
id_loop2:
cmp eax, 0
jz id_end
 
 
mov dl, [ebx+eax-1]
lea esi, [ebx+ecx]
sub esi, eax
mov dh, [esi]
 
mov [ebx+eax-1], dh
mov [esi], dl
 
dec eax
jmp id_loop2
 
 
 
 
id_end:
mov eax, ecx
 
;pop edi
pop esi
pop edx
pop ecx
;pop ebx
popf
ret
 
;
;
;
x_bb dw 550 ; Š®®à¤¨­ âë «¥¢®£® ¢¥àå­¥£® 㣫 
y_bb dw 30 ;
;
bb_width dw 100 ; ˜¨à¨­  ª­®¯®ª
bb_height dw 12 ; ¢ëá®â  ª­®¯®ª
;
bb_dist dw 6 ;  ááâ®ï­¨¥ ¬¥¦¤ã ª­®¯ª ¬¨
 
; ˆ¤¥­â¨ä¨ª â®àë ª­®¯®ª ­ ç¨­ ï á 100
;
; „«ï Š‹
;
;
buttonbox:
pushad
pushf
xor ecx, ecx
xor eax, eax
xor ebx, ebx
 
bb_loop:
 
; à®¢¥à塞 ¯¥à¢ë© ¡ ©â 㨭 , ¥á«¨ 0, ª­®¯ªã à¨á®¢ âì ­¥ ­ ¤®
;mov ebx, NAME_LEN
;imul ebx, ecx
 
;mov al, [names+ebx]
;cmp al, 0
;jz bb_end
 
mov ebx, UIN_LEN
imul ebx, ecx
 
mov al, [uins + ebx]
cmp al, 0
jz bb_end
 
 
 
 
; à¨á㥬 ª­®¯ªã
; –¢¥â § ¢¨á¨â ®â áâ âãá  UIN
mov ebx, 4
imul ebx, ecx
mov eax, [stats+ebx] ; ‚ áâ à襬 á«®¢¥ ¤®¯®«­¨â¥«ì­ë© áâ âãá
cmp ax, -1
jz bb_offline
cmp ax, 1
jz bb_away
cmp ax, 2
jz bb_dnd
cmp ax, 4
jz bb_na
cmp ax, 10h
jz bb_bisy
cmp ax, 20h
jz bb_free4chat
cmp ax, 100h
jz bb_invis
; Online
mov esi, 0x4466AA
jmp bb_dr
 
bb_offline:
mov esi, 0xBEBEBE
jmp bb_dr
 
bb_away:
mov esi, 0x14dcc3
jmp bb_dr
 
bb_dnd:
mov esi, 0x14dcc3
jmp bb_dr
 
bb_na:
mov esi, 0x14dcc3
jmp bb_dr
 
bb_bisy:
mov esi, 0x14dcc3
jmp bb_dr
 
bb_free4chat:
mov esi, 0x2233FF
jmp bb_dr
 
bb_invis:
mov esi, 0xD0D0D0
 
bb_dr:
 
mov bx, [x_bb]
shl ebx, 16
mov bx, [bb_width]
;push ecx
mov edx, ecx
lea edx, [edx+100] ; ID
mov edi, ecx
mov cx, [y_bb]
movzx eax, [bb_height]
add ax, [bb_dist]
imul eax, edi
add ecx, eax
shl ecx, 16
mov cx, [bb_height]
mov eax, 8
int 40h
;
;  ¤¯¨áì ­  ª­®¯ª¥
;
add ebx, 50000h ; ‘¬¥é¥­¨¥ ®â «¥¢®£® ªà ï
shr ecx, 16
movzx eax, [bb_height]
shr eax, 1 ; /2
sub eax, 3 ; ᬥ饭¨¥ ¢¢¥àå ®â 業âà 
add ecx, eax ; + ¯®«®¢¨­  à §¬¥à  ª­®¯ª¨
mov bx, cx
mov ecx, 0x80FFFFFF ; –¢¥â
mov edx, names
mov esi, NAME_LEN
imul esi, edi
add edx, esi
;mov esi, -1
mov eax, 4
int 40h
 
mov ecx, edi
inc ecx
cmp ecx, UINS
ja bb_end
jmp bb_loop
 
 
bb_end:
popf
popad
ret
;
; Œ áᨢ á UIN
;
UIN_LEN = 11 ; „«¨­ 
UINS = 22 ; Š®«¨ç¥á⢮
;
uins db UIN_LEN*UINS dup 0
;
; ¬ áᨢ á® áâ âãá ¬¨
;
stats dd UINS dup -1
;
; Œ áᨢ á ¨¬¥­ ¬¨
;
NAME_LEN = 30
 
names db NAME_LEN*UINS dup 0
 
;
;
U1 db '405577261',0
U2 db '455395049',0
U3 db '488118046',0
;
; ‡ £à㧪  ¬ áᨢ  UIN
;
; FIXME ¡ã¤¥â 㤠«¥­ 
loaduin:
pushad
mov eax, U1
mov ebx, uins
mov ecx, 9
call strcpy
 
mov ebx, names
call strcpy
 
mov eax, U2
mov ebx, uins+UIN_LEN
mov ecx, 9
call strcpy
 
mov ebx, names+NAME_LEN
call strcpy
 
mov eax, U3
mov ebx, uins+UIN_LEN*2
mov ecx, 9
call strcpy
 
mov ebx, names+NAME_LEN*2
call strcpy
 
 
popad
ret
 
;
; ”ã­ªæ¨ï ¤«ï § £à㧪¨ Š‹ ­¨ª ¬¨ ¨ áâ âãá ¬¨
; eax <-- ®¬¥à 㨭  ¯® ¯®à浪㠢 ¬ áᨢ¥ uins, ­ ç¨­ ï á 0
; [ebx] <-- 㪠§ â¥«ì ­  null-terminated áâபã á ­®¢ë¬ ¨¬¥­¥¬
; ecx <-- ®¢ë© áâ âãá
;
loadbb:
pushad
pushf
;
; à®¢¥à塞 ­®¬¥à
;
cmp eax, UINS
jnc loadbb_end ;>=
 
 
;
; “¤ «ï¥¬ ª­®¯ªã
;
push ecx
push ebx
push eax
 
lea edx, [eax+100]
or edx, 0x80000000
mov eax, 8
int 40h
 
;
; ‘®å࠭塞 ­®¢ë© áâ âãá ¢ ¬ áᨢ¥ áâ âãᮢ
;
pop eax
mov edx, 4 ; DWORD
imul edx, eax
mov [stats+edx], ecx
;
; ‘®å࠭塞 ­®¢®¥ ¨¬ï
;
mov edi, eax ; edi <-- Uin number
pop eax ; <-- offset of string
mov ebx, eax
call strlen
mov ecx, eax ; Len
 
 
mov eax, ebx ;Source
mov edx, NAME_LEN
imul edx, edi
lea ebx, [names+edx] ; Dest
call strcpy
mov [names+edx+ecx], byte 0
 
xchg edi, eax ; eax - áç¥â¨ª, edi - 㪠§ â¥«ì ­  áâபã
pop ecx
push edi
; à¨á㥬 ª­®¯ªã
; –¢¥â § ¢¨á¨â ®â áâ âãá  UIN
cmp cx, -1
jz l_offline
cmp cx, 1
jz l_away
cmp cx, 2
jz l_dnd
cmp cx, 4
jz l_na
cmp cx, 10h
jz l_bisy
cmp cx, 20h
jz l_free4chat
cmp cx, 100h
jz l_invis
; Online
mov esi, 0x4466AA
jmp l_dr
 
l_offline:
mov esi, 0xBEBEBE
jmp l_dr
 
l_away:
mov esi, 0x14dcc3
jmp l_dr
 
l_dnd:
mov esi, 0x14dcc3
jmp l_dr
 
l_na:
mov esi, 0x14dcc3
jmp l_dr
 
l_bisy:
mov esi, 0x14dcc3
jmp l_dr
 
l_free4chat:
mov esi, 0x2233FF
jmp l_dr
 
l_invis:
mov esi, 0xD0D0D0
 
l_dr:
 
mov bx, [x_bb]
shl ebx, 16
mov bx, [bb_width]
;push ecx
mov edx, eax
lea edx, [edx+100] ; ID
mov edi, eax
mov cx, [y_bb]
movzx eax, [bb_height]
add ax, [bb_dist]
imul eax, edi
add ecx, eax
shl ecx, 16
mov cx, [bb_height]
mov eax, 8
int 40h
;
;  ¤¯¨áì ­  ª­®¯ª¥
;
add ebx, 50000h ; ‘¬¥é¥­¨¥ ®â «¥¢®£® ªà ï
shr ecx, 16
movzx eax, [bb_height]
shr eax, 1 ; /2
sub eax, 3 ; ᬥ饭¨¥ ¢¢¥àå ®â 業âà 
add ecx, eax ; + ¯®«®¢¨­  à §¬¥à  ª­®¯ª¨
mov bx, cx
mov ecx, 0x80FFFFFF ; –¢¥â
pop edx
mov esi, -1
mov eax, 4
int 40h
 
 
 
loadbb_end:
 
popf
popad
ret
 
;
;
; Žâ« ¤®ç­ ï äã­ªæ¨ï - ¢ë¢®¤¨â ®¡« áâì ¯ ¬ïâ¨
; EAX - 㪠§ â¥«ì ­  ®¡« áâì
; EBX - ª®«¨ç¥á⢮ ¡ ©â
;
 
print_mem:
push eax
push ebx
push ecx
push edx
push esi
 
xor ecx, ecx
xor esi, esi
 
 
pm_loop:
cmp ecx, ebx
jz pm_exit
 
 
mov dl, [eax + ecx]
shr dl, 4 ;‘¤¢¨­ãâì ­  4 à §à鸞 ¢¯à ¢®
 
cmp dl, 0x0A
jnb pm_chars
 
or dl, 0x30
jmp pm_write
 
pm_chars:
add dl, 0x37
 
pm_write:
mov [membuff + esi], dl
inc esi
;
;
 
mov dl, [eax + ecx]
and dl, 0x0F
 
cmp dl, 0x0A
jnb pm_chars2
 
or dl, 0x30
jmp pm_write2
 
pm_chars2:
add dl, 0x37
 
pm_write2:
mov [membuff + esi], dl
inc esi
 
 
mov [membuff + esi], 0x20
inc esi
 
cmp esi, MEMBUFF_SIZE - 2
jb pm_nwrite
;
; ¢ë¢¥á⨠¡ãä¥à
mov [membuff + esi], byte 0
 
push eax
push ebx
 
mov eax, membuff
xor ebx, ebx
xor esi, esi
 
call writemsg
 
pop ebx
pop eax
 
pm_nwrite:
 
inc ecx
jmp pm_loop
 
 
 
pm_exit:
 
mov [membuff + esi], byte 0
 
 
mov eax, membuff
xor ebx, ebx
xor esi, esi
 
call writemsg
 
pop esi
pop edx
pop ecx
pop ebx
pop eax
ret
/programs/network_old/icq/trunk/comp_data.inc
0,0 → 1,3
MEMBUFF_SIZE = (16 * 3 + 1)
 
membuff db MEMBUFF_SIZE dup 0
/programs/network_old/icq/trunk/config.inc
0,0 → 1,0
__CPU_type fix p5
/programs/network_old/icq/trunk/dialogs1.inc
0,0 → 1,597
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; DIALOGS1.INC ;
; ;
; COMPILE WITH FASM for MENUET ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
menus dd 3 ; number of menus
m_x dd 0x5 ; x start
m_y dd 20 ; y start
m_xs dd 290 ; x size
m_ys dd 14 ; y size
g_stack dd 0xf000 ; thread stack - required
 
 
menu:; AB C D E F G
 
db '*D FILE +Save File +Load File +- +Quit '
db '*B EDIT +Copy +Paste '
db '*B HELP +Setup +About.. '
db '@' ; end mark
 
; A : Data type '*' -> New menu , '+' -> menu selection
; B : Number of selections in menu (A+)
; C : Menu header text
; D-G : Menu selection text
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; DATA BELOW IS FOR DIALOGS1.INC INTERNALS
 
menu_action dd '----'
 
window_on db 0
 
g_n dd -1
g_x dd 0x0
g_t dd 0x0
g_1 dd 0x0
g_l dd 0x0
closet db 0
 
table: times 1024 db 0
 
last_mouse dd 0x0
 
mo_x dd 0x0
mo_y dd 0x0
 
 
check_mouse:
 
pusha
 
cmp [window_on],1
je no_open
 
mov eax,37
mov ebx,2
int 0x40
 
cmp [window_on],0
jne openw2
 
cmp eax,0
je no_open
 
openw2:
 
waitformouse:
 
mov eax,23
mov ebx,2
int 0x40
 
cmp eax,0
jne no_open
 
mov eax,37
mov ebx,2
int 0x40
 
cmp eax,0
jne waitformouse
 
 
mov eax,37
mov ebx,1
int 0x40
 
mov esi,eax
 
shr eax,16
xor edx,edx
mov ebx,50
div ebx
mov edx,eax
cmp edx,[g_n]
je no_open
cmp edx,[menus]
jge no_open
mov eax,esi
 
and eax,0xffff
 
mov ebx,[m_y]
cmp eax,ebx
jbe no_open
add ebx,[m_ys]
cmp eax,ebx
jge no_open
 
cmp [window_on],0
je noww
 
mov [closet],1
mov ecx,100
waitm:
mov eax,5
mov ebx,1
int 0x40
dec ecx
jz no_open
cmp [window_on],0
jne waitm
noww:
 
mov eax,edx
jmp cll
 
no_open:
 
mov [last_mouse],esi
 
popa
 
ret
 
cll:
 
mov [window_on],2
 
mov [g_n],eax
mov [g_x],96
mov [g_t],0
mov [g_1],1
 
mov eax,9
mov ebx,table
mov ecx,-1
int 0x40
 
mov eax,[table+34]
mov [mo_x],eax
mov eax,[table+38]
mov [mo_y],eax
 
mov eax,51
mov ebx,1
mov ecx,alert_entry
mov edx,[g_stack]
int 0x40
 
mov [esp+28],dword 0 ; clear button entry
 
mov [menu_action],'MD '
 
check_gr:
 
popa
 
ret
 
 
draw_menu:
 
mov eax,9
mov ebx,table
mov ecx,-1
int 0x40
 
cmp [table+46],dword 30
jb drmr
 
mov eax,13 ; white background
mov ebx,[m_x]
shl ebx,16
add ebx,[m_xs]
inc ebx
mov ecx,[m_y]
shl ecx,16
add ecx,[m_ys]
mov edx,0xf0f8ff
int 0x40
 
mov eax,38 ; egde lines
mov ebx,[m_x]
shl ebx,16
add ebx,[m_x]
add ebx,[m_xs]
mov ecx,[m_y]
shl ecx,16
add ecx,[m_y]
mov edx,0x000000
int 0x40
mov eax,38
mov ecx,[m_y]
add ecx,[m_ys]
shl ecx,16
add ecx,[m_y]
add ecx,[m_ys]
int 0x40
 
mov esi,menu-1
mov edi,[m_x]
mov ebp,1
new_menu:
inc esi
 
cmp [esi],byte '*'
jne drmnl1
push esi
mov eax,4
mov ebx,edi
shl ebx,16
add ebx,[m_y]
add ebx,0x00050004
mov ecx,0x000000
mov edx,esi
add edx,3
mov esi,12
int 0x40 ; draw text
pop esi
add esi,2
add edi,50
inc ebp
 
drmnl1:
cmp [esi],byte '@'
jne new_menu
 
drmr:
 
ret
 
alert_box:
 
; eax : x size - min 200
; ebx : pointer to ASCIIZ - max 128 character text
; ecx : button 1 id ( OK or YES )
; edx : button 2 id or zero ( NO )
 
 
cmp [window_on],0
jne alert_box_return
 
mov [window_on],1
 
cmp eax,100
jg size_ok
mov eax,100
size_ok:
 
mov [g_x],eax
mov [g_t],ebx
mov [g_1],ecx
 
mov ecx,0
new_search:
cmp [ebx],byte 0
je found_len
inc ebx
inc ecx
cmp ecx,128
jbe new_search
found_len:
mov [g_l],ecx
 
mov eax,51
mov ebx,1
mov ecx,alert_entry
mov edx,[g_stack]
int 0x40
 
mov [menu_action],'MA '
 
alert_box_return:
 
ret
 
alert_entry:
 
call alert_draw_window
 
alert_still:
 
mov eax,23 ; wait here for event
mov ebx,1
int 0x40
 
cmp eax,1 ; redraw request ?
je alert_red
cmp eax,2 ; key in buffer ?
je alert_key
cmp eax,3 ; button in buffer ?
je alert_button
 
cmp [closet],0
jne ccc
 
mov eax,9
mov ebx,table
mov ecx,-1
int 0x40
 
cmp ax,[table+4]
je no_close
ccc:
mov [closet],0
mov [g_n],-1
mov [menu_action],'----'
mov [window_on],0
mov eax,-1
int 0x40
no_close:
 
jmp alert_still
 
alert_red: ; redraw
call alert_draw_window
jmp alert_still
 
alert_key: ; key
mov eax,2 ; just read it and ignore
int 0x40
jmp alert_still
 
alert_button: ; button
mov eax,17 ; get id
int 0x40
 
shr eax,8
cmp eax,3
jg no_action1
dec eax
shl eax,2
mov eax,dword [eax+rtext]
mov [menu_action],eax
jmp action_done
no_action1:
sub eax,16
add eax,65
shl eax,8
mov ebx,[g_n]
add ebx,65
add eax,ebx
mov [menu_action],eax
 
action_done:
 
mov [closet],0
mov [g_n],-1
mov [window_on],0
mov eax,-1 ; close this program
int 0x40
 
rtext db 'NO YES OK '
 
jmp alert_still
 
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
 
alert_draw_window:
 
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
int 0x40
 
cmp [window_on],2
jne no_win_type_2
 
mov edx,menu-1
mov ecx,[g_n]
add ecx,1
find_menu:
inc edx
cmp [edx],byte '*'
je menu_loop
jmp find_menu
menu_loop:
loop find_menu
movzx ebp,byte [edx+1]
sub ebp,64
push edx
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,[g_n]
imul ebx,50
add ebx,[mo_x]
add ebx,[m_x]
shl ebx,16
add ebx,[g_x]
mov ecx,[mo_y]
add ecx,[m_y]
add ecx,[m_ys]
shl ecx,16
mov edx,14
imul edx,ebp
add edx,7
add ecx,edx
mov edx,0x00ffffff ; color of work area RRGGBB,8->color gl
mov esi,0x00ffffff ; color of grab bar RRGGBB,8->color gl
mov edi,0x000000cc ; color of frames RRGGBB
int 0x40
 
pop edx
 
mov ebx,5*65536+7 ; draw info text with function 4
mov ecx,0x10000000
mov esi,12
mov ebp,16
no_d_found:
inc edx
cmp [edx],byte '*'
je d_drawed
cmp [edx],byte '@'
je d_drawed
cmp [edx],byte '+'
jne no_d_found
inc edx
pusha ; draw button
mov eax,8
mov ecx,ebx
mov ebx,[g_x]
add ebx,0x0000fffe
shl ecx,16
add ecx,0xfffc0000+14
mov edx,0x40000000
add edx,ebp
mov esi,0
int 0x40
popa
mov eax,4 ; draw text
int 0x40
inc ebp
add ebx,14
jmp no_d_found
d_drawed:
 
no_win_type_2:
 
 
cmp [window_on],1
jne no_win_1
 
mov eax,14 ; to middle of screen
int 0x40
mov ecx,eax
and ecx,0xffff
shr ecx,1
shr eax,1
mov ebx,[g_x]
shr ebx,1
shl ebx,16
sub eax,ebx
mov ebx,eax
 
mov eax,0 ; function 0 : define and draw window
mov bx,word [g_x]
sub ecx,80
shl ecx,16
mov cx,110 ; [y start] *65536 + [y size]
mov edx,0x02ffffff ; color of work area RRGGBB,8->color gl
mov esi,0x80d05050 ; color of grab bar RRGGBB,8->color gl
mov edi,0x00d05050 ; color of frames RRGGBB
int 0x40
 
 
mov eax,4 ; label
mov ebx,8*65536+8
mov ecx,0x10ddeeff
mov edx,alert_labelt1
mov esi,alert_label1len-alert_labelt1
int 0x40
 
mov eax,4
mov ebx,10*65536+43
mov ecx,0x10000000
mov edx,[g_t]
mov esi,[g_l]
int 0x40
 
cmp [g_1],1
jne gadgets_no_1
 
mov eax,8
mov ebx,[g_x]
sub ebx,100
shr ebx,1
shl ebx,16
add ebx,30*65536+40
mov ecx,75*65536+16
mov edx,3
mov esi,0x446688
int 0x40
 
mov eax,4
mov ebx,[g_x]
sub ebx,100
shr ebx,1
shl ebx,16
add ebx,31*65536+80
mov ecx,0x10ffffff
mov edx,alert_t2
mov esi,alert_t2len-alert_t2
int 0x40
 
gadgets_no_1:
 
cmp [g_1],2
jne gadgets_no_2
 
mov eax,8
mov ebx,[g_x]
sub ebx,100
shr ebx,1
shl ebx,16
add ebx,0*65536+40
mov ecx,75*65536+16
mov edx,1
mov esi,0x446688
int 0x40
 
mov eax,8
mov ebx,[g_x]
sub ebx,100
shr ebx,1
shl ebx,16
add ebx,57*65536+40
mov ecx,75*65536+16
mov edx,2
mov esi,0x446688
int 0x40
 
mov eax,4
mov ebx,[g_x]
sub ebx,100
shr ebx,1
shl ebx,16
add ebx,1*65536+80
mov ecx,0x10ffffff
mov edx,alert_t1
mov esi,alert_t1len-alert_t1
int 0x40
 
gadgets_no_2:
 
no_win_1:
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
int 0x40
 
ret
 
 
; DATA AREA
 
 
alert_t1:
db ' No Yes'
alert_t1len:
 
 
alert_t2:
db ' OK'
alert_t2len:
 
 
alert_labelt1:
db 'ALERT'
alert_label1len:
 
 
 
 
 
 
 
 
/programs/network_old/icq/trunk/dos2win.inc
0,0 → 1,121
;
;
CP866 db '€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯àáâãäåæçèéêëìíîï'
 
;
; ¥à¥ª®¤¨à®¢ª  ¨§ cp1251 ¢ cp866
;
; [eax] <-- Null-terminated string
;
 
win2dos:
pushad
pushf
 
xor ebx, ebx
xor ecx, ecx
;xor edx, edx
 
w2d_loop:
mov bl, [eax+ecx]
cmp bl, 0
jz w2d_end
cmp bl, 0A8h ; ð
jz w2d_yo1
cmp bl, 0B8h ; ñ
jz w2d_yo2
cmp bl, 0C0h ; ãááª ï ¡ãª¢ 
jnc w2d_rchar
inc ecx
jmp w2d_loop
 
w2d_yo1:
mov [eax+ecx], byte 0F0h
inc ecx
jmp w2d_loop
 
w2d_yo2:
mov [eax+ecx], byte 0F1h
inc ecx
jmp w2d_loop
 
w2d_rchar:
sub bl, 0C0h
mov bl, [CP866+ebx]
mov [eax+ecx], bl
inc ecx
jmp w2d_loop
 
 
w2d_end:
 
popf
popad
ret
 
 
CP1251 db 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
 
;
; ¥à¥ª®¤¨à®¢ª  ¨§ CP866 ¢ CP1251
; [eax] <-- Null termainated string
;
 
dos2win:
pushf
pushad
 
xor ebx, ebx
xor ecx, ecx
 
dec ecx
 
d2w_loop:
inc ecx
mov bl, [eax+ecx]
cmp bl, 0
jz d2w_end
cmp bl, 80h
jnc d2w_rchar
;inc ecx
jmp d2w_loop
 
d2w_yo1:
mov byte [eax+ecx], 0A8h
;inc ecx
jmp d2w_loop
 
d2w_yo2:
mov byte [eax+ecx], 0B8h
;inc ecx
jmp d2w_loop
 
d2w_rchar:
cmp bl, 0B0h
jnc d2w_rchar2
sub bl, 80h
mov bl, [CP1251+ebx]
mov [eax+ecx], bl
jmp d2w_loop
 
d2w_rchar2:
cmp bl, 0E0h
jc d2w_loop
cmp bl, 0F0h
jz d2w_yo1
cmp bl, 0F1h
jz d2w_yo2
cmp bl, 0F2h
jnc d2w_loop
add bl, 10h
mov [eax+ecx], bl
jmp d2w_loop
 
 
d2w_end:
 
popad
popf
ret
/programs/network_old/icq/trunk/editbox.mac
0,0 → 1,1129
;Œ ªà®á ¤«ï ¢ë¢®¤  ®á­®¢­ëå ä㭪権 ª®â®àë¥ ¨á¯«ì§ãîâáï ¡®ªá®¬
macro use_general_func
{
;debug_func
;----------------------------------------------------------
;--- ¯à®æ¥¤ãà  ¯à®à¨á®¢ª¨ ¢ë¤¥«¥­®© ç á⨠-----------------
;----------------------------------------------------------
.draw_shift:
test word ed_flags,ed_shift_bac ;ãáâ ­®¢ª  ä« £ , ¢ë¤¥«¥­­®© ®¡« áâ¨
jz @f
mov ebp,shift_color
mov ebx,dword ed_shift_pos
call .sh_cl_
@@: ret
;----------------------------------------------------------
;--- ¯à®æ¥¤ãà  ¯à®à¨á®¢ª¨ ⥪áâ  --------------------------
;----------------------------------------------------------
.draw_text:
;--- ¢ëç¨á«ï¥¬, ᪮«ìª® ¯®¬¥é ¥âáï ᨬ¢®«®¢ ---
;--- çâ®¡ë ¬ãá®à ­¥ à¨á®¢ âì ---
call .get_n
mov esi,ed_size
mov ebx,ed_offset
sub esi,ebx
cmp eax,esi
jae @F
mov esi,eax ;çâ®¡ë ­¥ ¢ë室¨âì §  ¯à¥¤¥«ë íªà ­ 
;--- à¨á㥬 ⥪áâ ---
@@: mov eax,4
mov ebx,ed_left
mov edx,ed_offset
add ebx,2
shl ebx,16
add ebx,ed_top
mov ecx,ed_text_color
add ebx,4
add edx,ed_text
mcall
ret
;----------------------------------------------------------
;--- ¯à®æ¥¤ãà  ¯à®à¨á®¢ª¨ ä®­  ----------------------------
;¢å®¤­ë¥ ¤ ­­ë¥
;eax
;edx - color
;----------------------------------------------------------
;¢å®¤ ⮫쪮 梥â edx
.draw_bg:
mov ebx,ed_left
add ebx,1
mov edx,ed_color
shl ebx,16
add ebx,ed_width
sub ebx,1
.draw_bg_eax:
mov ecx,ed_top
mov eax,13
add ecx,1
shl ecx,16
add ecx,ed_height
dec ecx
mcall
ret
;----------------------------------------------------------
;--- ¯à®æ¥¤ãà  ¯®«ã祭¨ï ª®«¨ç¥á⢠ ᨬ¢®«®¢ ¢ ⥪ã饩 é¨à¨­¥ ª®¬¯®­¥­â 
;----------------------------------------------------------
.get_n:
mov eax,ed_width ;¯®«ã祬 è¨à¨­ã ª®¬¯®­¥­â 
xor edx,edx ;१ã«ìâ â à á¯®«®£ ¥âáï ¢ ¯ à¥ edx:eax ¢ eax - ®áâ â®ª
sub eax,4 ;¢ëç⨬ 4
mov ebx,6 ;§ £à㧬¨ ¤¥«¨â¥«ì
div ebx ;à §¬¤¥«¨¬ ­  6
ret
;----------------------------------------------------------
;--- ¯à®æ¥¤ãà  à¨á®¢ ­¨ï ªãàá®à  --------------------------
;----------------------------------------------------------
;¢å®¤­ë¥ ebp- 梥â
.clear_cursor:
mov edx,ebp
mov ebx,cl_curs_x
mov ecx,cl_curs_y
jmp .draw_curs
.draw_cursor:
mov edx,ed_text_color
mov ebx,ed_pos
mov ecx,ed_offset
sub ebx,ecx
 
lea ebx,[ebx*2+ebx]
shl ebx,1
;imul ebx,6
add ebx,ed_left
mov ecx,ed_top
inc ebx
add ecx,2
mov ebp,ebx
shl ebx,16
mov bx,bp
mov ebp,ecx
shl ecx,16
mov cx,bp
add ecx,ed_height-4
mov cl_curs_x,ebx
mov cl_curs_y,ecx
.draw_curs:
mcall 38
ret
;----------------------------------------------------------
;--- ¯à®æ¥¤ãà  à¨á®¢ ­¨ï à ¬ª¨ ----------------------------
;----------------------------------------------------------
.draw_border:
;--- 梥â à ¬ª¨ ---
test word ed_flags,ed_focus
mov edx,ed_focus_border_color
jne @f
mov edx,ed_blur_border_color
@@:
;--- ᢥàåã ---
mov eax,38
mov ebx,ed_left
mov ecx,ebx
shl ebx,16
mov bx,cx
add ebx,ed_width
mov ecx,ed_top
mov esi,ecx
shl ecx,16
mov cx,si
mcall
;--- á­¨§ã ---
mov esi,ecx
add ecx,ed_height
mov ebp,ecx
shl ecx,16
mov cx,bp
mcall
;--- á«¥¢  ---
mov cx,si
mov ebp,ebx
sub ebx,ed_width
mcall
;--- á¯à ¢  ---
mov ebx,ebp
shl ebx,16
mov bx,bp
mcall
ret
;----------------------------------------------------------
;--- ¯à®¢¥àª , § è¥« «¨ ªãàá®à §  £à ­¨æë ¨, ¥á«¨ ­ ¤®, ---
;--- ¨§¬¥­ï¥¬ ᬥ饭¨¥ ------------------------------------
;--- ¥á«¨ ᬥ饭¨¥ ¡ë«® ãáâ ­®¢ª  ä« £  ed_offset_cl ¨­ ç¥
; ¥á«¨ ­¨ç¥£® ­¥ ¨§¬¥­¨«®áì â® ¢ëáâ ¢«¥­¨¥ ed_offset_fl
; ¢ ®¡é¥© ¡¨â®¢®© ¬ àà¨æ¥ á®áâ®ï­¨ï ª®¬¯®­¥­â®¢ word ed_flags
;----------------------------------------------------------
.check_offset:
pusha
mov ecx,ed_pos
mov ebx,ed_offset
cmp ebx,ecx
ja .sub_8
 
push ebx
call .get_n ;¯®«ã稬 ª®«-¢® ᨬ¢®«®¢ ¢ ¯ à¥ ॣ¨áâ஢ edx:eax
pop ebx
mov edx,ebx
add edx,eax ;ed_offset+width editbox
inc edx ;­¥®¡å®¤¨¬® ¤«ï ­®¬ «ì­®£® ¯®«®¦¥­¨ï ªãàá®à  ¢ ªà ©­¥© «¥¢®© ¯®§¨æ¨¨
cmp edx,ecx
ja @f
 
mov edx,ed_size
cmp edx,ecx
je .add_end
 
sub edx,ecx
cmp edx,8
jbe .add_8
add ebx,8
jmp .chk_d
 
.sub_8: cmp ecx,0
je .sub_min
cmp ebx,8
jbe .sub_min
sub ebx,8 ;ebx=ed_offset
jmp .chk_d
.sub_min:
xor ebx,ebx
jmp .chk_d
 
.add_end:sub edx,eax
mov ebx,edx
jmp .chk_d
.add_8: add ebx,edx
.chk_d: mov ed_offset,ebx
call .draw_bg
and word ed_flags,ed_offset_cl
edit_ex
@@:
or word ed_flags,ed_offset_fl
edit_ex
}
 
macro use_key_func
{
;Ž¡à ¡®âª  Shift ¤«ï á­ïâ¨ï ¢ë¤¥«¥­¨ï ­¥¨§¢¥áâ­®© ®¡« áâ¨
.shift: ;;;;;;;SHIFT
test word ed_flags,ed_shift
je .f_exit
 
@@: mov ebp,shift_color
or word ed_flags,ed_shift_bac ;ãáâ ­®¢ª  ä« £ , ¢ë¤¥«¥­­®© ®¡« áâ¨
mov ebx,dword ed_shift_pos
call .sh_cl_
jmp .draw_cursor_text
;;;;;;;;;;;;;;;;;;;;;
.f_exit:call .check_offset
and word ed_flags,ed_shift_cl
call .enable_null
jmp .draw_cursor_text
.sh_cl_:
;;;;;;SHIFT end
;®¡à ¡®âª  ®ç¨á⪨, ¯à¨ «¥¢®¬ - ¯à ¢®¬ ¤¢¨¦¥­¨¨ ¢ë¤¥«¥­¨ï
;¤«ï ®¡à ¡®âª¨ á­ïâ¨ï ¢ë¤¥«¥­¨ï
;¢å®¤­ë¥ ¯ à ¬¥âàë ebp=color ebx=ed_shift_pos
mov eax,dword ed_pos
cmp eax,ebx
 
jae .sh_n
push eax ;¬¥­ì襥 ¢ eax
push ebx ;¡®«ì襥
jmp .sh_n1
;¥á«¨ ¨­ ç¥
.sh_n: push ebx
push eax
.sh_n1:
call .check_offset
call .get_n
mov edx,eax ;size of ed_box
mov ecx,ed_offset
add eax,ecx ;eax = w_off= ed_offset+width
mov edx,eax ;save
pop ebx ;¡®«ì襥
pop eax ;¬¥­ì襥
 
cmp eax,ecx ;áà ¢­¥­¨¥ á ¬¥­ì襣® á offset.
jae .f_f ;¥á«¨ ¡®«ìè¥
xor eax,eax
cmp edx,ebx ;cà ¢­¨¬ à §¬¥à w_off á ¡®«ì訬
jb @f
sub ebx,ecx
jmp .nxt_f
@@: mov ebx,edx
sub ebx,ecx
jmp .nxt_f
.f_f:
sub eax,ecx
cmp edx,ebx ;cà ¢­¨¬ à §¬¥à w_off á ¡®«ì訬
jle @f
sub ebx,ecx
sub ebx,eax
jmp .nxt_f
@@:
mov ebx,edx
sub ebx,ecx
sub ebx,eax
.nxt_f:
mov edx,ebx
lea ebx,[eax*2+eax]
shl ebx,1
add ebx,ed_left
inc ebx
shl ebx,16
lea ecx,[edx*2+edx]
shl ecx,1
mov bx,cx
inc ebx
mov edx,ebp;shift_color
 
call .draw_bg_eax
@@: call .enable_null
ret
;;;;;;;;;;;;;;;;;;;;;
;“áâ ­®¢ª - á­ï⨥ ¢ë¤¥«¥­¨ï ¢ ®¤¨­ ᨬ¢®«
;;;;;;;;;;;;;;;;;;;;;
.drw_sim:
mov eax,dword ed_pos
call .draw_rectangle ;­ à¨á®¢ âì ¯àאַ㣮«ì­¨ª á § ¤ ­­ë¬ 梥⮬
jmp @b
;;;;;;;;;;;;;;;;;;;;;
;”ãªæ¨ï ãáâ ­®¢ª¨ ¢ë¤¥«¥­¨ï ¯à¨ ¤¢¨¦¥­¨ï ¢«¥¢® ¨ ¢¯à ¢® ¨ ­ ¦ â¨¨ shift
;‹®£¨ª :
;;;;;;;;;;
.draw_wigwag:
;äã­ªæ¨ï ãáâ ­®¢ª¨ ¯¥à¥¬¥­­ëå
mov ebp,shift_color
call .clear_cursor
 
or word ed_flags,ed_shift_bac ;ãáâ ­®¢ª  ä« £ , ¢ë¤¥«¥­­®© ®¡« áâ¨
mov ebp,shift_color
mov eax,dword ed_pos
test word ed_flags,ed_left_fl
jz .low
jmp @f
;;;;;;;;;;
;”ãªæ¨ï 㤠«¥­¨ï ¢ë¤¥«¥­¨ï ¯à¨ ¤¢¨¦¥­¨ï ¢«¥¢® ¨ ¢¯à ¢® ¨ ­ ¦ â¨¨ shift
;‹®£¨ª :
;;;;;;;;;;
.draw_wigwag_cl:
;äã­ªæ¨ï ãáâ ­®¢ª¨ ¯¥à¥¬¥­­ëå
mov ebp,ed_color
call .clear_cursor
 
mov ebp,ed_color
mov eax,dword ed_pos
test word ed_flags,ed_left_fl
jz .low
@@: call .draw_rectangle ;­ à¨á®¢ âì ¯àאַ㣮«ì­¨ª § ªà è¨¢ ¥¬®© ®¡« áâ¨
ret
.low: dec eax
jmp @b
;¢å®¤­®© ¯ à ¬¥âà ebx - ed_pos
.sh_first_sh:
test word ed_flags,ed_shift
je @f
mov dword ed_shift_pos_old,ebx
test word ed_flags,ed_shift_on
jne @f
mov dword ed_shift_pos,ebx
or word ed_flags,ed_shift_on
@@: ret
;Ž¡à ¡®âª  ªà ©­¨å ¯®«®¦¥­¨© ¢ editbox ¯à¨ ­ ¦ â®¬ shift
;¯à®¨§¢®¤¨â á­ï⨥ ¢ë¤¥«¥­¨¥, ¥á«¨ ­¥â shift
;¨­ ç¥ ¢®®¡é¥ ¢ë室¨â
.sh_st_of:
test word ed_flags,ed_shift
jne @f
test word ed_flags,ed_shift_bac
je @f
mov ebp,ed_color
mov ebx,dword ed_shift_pos
call .sh_cl_ ;®ç¨á⪠ ¢ë¤¥«¥­®£® äà £¬¥­â 
and word ed_flags,ed_shift_cl ; ®ç¨á⪠ ®â ⮣® çâ® ã¡à «¨ ¢ë¤¥«¥­¨¥
jmp .draw_cursor_text
@@:
and word ed_flags,ed_shift_off
edit_ex
;¯à®¢¥àª  á®áâ®ï­¨ï shift ¡ë« «¨ ®­ ­ ¦ â à ­ìè¥?
.sh_enable:
test word ed_flags,ed_shift
jne .sh_ext_en ;­ à¨á®¢ âì § ªà è¥­ë© ¯àאַ㣮«ì­¨ª
 
test word ed_flags,ed_shift_bac
je @f
call .check_offset
 
mov ebp,ed_color
mov ebx,dword ed_shift_pos
call .sh_cl_ ;®ç¨á⪠ ¢ë¤¥«¥­®£® äà £¬¥­â 
call .draw_wigwag_cl
and word ed_flags,ed_shift_cl ; 1¢ à ­¥ ­ã¦­®
ret
 
@@: mov ebp,ed_color
call .clear_cursor
call .check_offset
ret
.sh_ext_en:
call .check_offset
test word ed_flags,ed_offset_fl
je @f
;¨á®¢ ­¨¥ § ªà è¥­ëå ¯àאַ㣮«ì­¨ª®¢ ¨ ®ç¨á⪠ ¨å
mov eax,dword ed_shift_pos
mov ebx,dword ed_pos
mov ecx,dword ed_shift_pos_old
;¯à®¢¥àª  ¨ à¨á®¢ ­¨¥ § ªà è¥­ëå ®¡« á⥩
cmp eax,ecx
je .1_shem
jb .smaller
cmp ecx,ebx
ja .1_shem
call .draw_wigwag_cl ;clear
jmp .sh_e_end
.smaller:
cmp ecx,ebx
jb .1_shem
call .draw_wigwag_cl ;clear
jmp .sh_e_end
;alike =
.1_shem: call .draw_wigwag
.sh_e_end: and word ed_flags,ed_shift_off
ret
@@: mov ebp,shift_color
mov ebx,dword ed_shift_pos
call .sh_cl_
jmp .sh_e_end
;äã­ªæ¨ï ¤«ï ®¡à ¡®âª¨ shift ¯à¨ ­ ¦ â¨¨ home and end
.sh_home_end:
mov ebp,ed_color
call .clear_cursor
test word ed_flags,ed_shift_bac
je @f
mov ebp,ed_color
mov ebx,dword ed_shift_pos_old
call .sh_cl_
 
@@: test word ed_flags,ed_shift
je .sh_exit_ ;¢ë©â¨
mov ebp,shift_color
mov ebx,dword ed_shift_pos
call .sh_cl_
or word ed_flags,ed_shift_bac ;ãáâ ­®¢ª  ä« £ , ¢ë¤¥«¥­­®© ®¡« áâ¨
jmp .sh_e_end
.sh_exit_: call .check_offset
ret
;äã­ªæ¨ï ¢­¥á¥­¨ï 0 ¯®  ¤à¥áã ed_size+1
.enable_null:
pusha
mov eax,ed_size
mov ebx,ed_text
test eax,eax
add eax,ebx
jne @f
inc eax
@@: xor ebx,ebx
mov [eax],bl
edit_ex
;- 㤠«¥­¨¥ ᨬ¢®« 
;‚室­ë¥ ¤ ­­ë¥ edx=ed_size;ecx=ed_pos
.del_char:
mov esi,ed_text
test word ed_flags,ed_shift_on
je @f
mov eax,dword ed_shift_pos
mov ebx,esi
cmp eax,ecx
jae .dh_n
 
mov ed_pos,eax ;çâ® ¡ë ­¥ ¡ë«® ã¡¥£ ­¨ï ªãàá®à 
mov ebp,ecx
sub ebp,eax
add ebx,eax ;eax ¬¥­ìè¥
sub edx,ecx
add esi,ecx
 
mov dword ed_shift_pos,ebp
jmp .del_ch_sh
;¥á«¨ ¨­ ç¥
.dh_n:
mov ebp,eax
sub ebp,ecx
add ebx,ecx
sub edx,eax
add esi,eax
mov dword ed_shift_pos,ebp
jmp .del_ch_sh
 
@@: add esi,ecx ;㪠§ â¥«ì + ᬥ饭¨¥ ª ॠ«ì­®¬ã ¡ãää¥àã
mov ebx,esi
inc esi
cld
 
sub edx,ecx
.del_ch_sh:
 
push edi
mov edi,ebx
@@:
lodsb
stosb
dec edx
jns @b
pop edi
ret
;¢ëç¨á«¨âì § ªà è¨¢ ¥¬ãî ®¡« áâì
;ᮣ« è¥­¨¥ ¢ ebp - ¯¥à¥¤ ¥âáï ed_size
.clear_bg:
call .get_n ;¯®«ãç¨âì à §¬¥à ¢ ᨬ¢®« å è¨à¨­ë ª®¬¯®­¥­â 
push eax
mov ebx,ed_offset
add eax,ebx ;eax = w_off= ed_offset+width
mov ebx,ebp ;ed_size
cmp eax,ebx
jb @f
mov eax,ed_pos
sub ebx,eax
mov ecx,ed_offset
sub eax,ecx
jmp .nxt
@@: mov ebx,ed_pos
push ebx
sub eax,ebx
mov ebx,eax ;It is don't optimal
pop eax ;ed_pos
mov ecx,ed_offset
sub eax,ecx
.nxt:
mov ebp,eax ;¯à®¢¥àª  ­  ¢ë室 § ªà è¨¢ ¥¬®© ®¡« á⨠§  ¯à¥¤¥«ë ¤«¨­ë
add ebp,ebx
pop edx
cmp ebp,edx
je @f
inc ebx
 
@@: mov edx,ebx
lea ebx,[eax*2+eax]
shl ebx,1
add ebx,ed_left
inc ebx
shl ebx,16
lea ecx,[edx*2+edx]
shl ecx,1
mov bx,cx
mov edx,ed_color
call .draw_bg_eax
ret
;;;;;;;;;;;;;;;;;;;
;;; Ž¡à ¡®âª  ¯à¨¬¨â¨¢®¢
;;;;;;;;;;;;;;;;;;;;
; à¨á®¢ âì ¯àאַ㣮«ì­¨ª, 梥⠯¥à¥¤ ¥âáï ¢ ebp
;¢å®¤­ë¥ ¯ à ¬¥âàë:
;eax=dword ed_pos
;ebp=-梥â ed_color or shift_color
.draw_rectangle:
mov ecx,dword ed_offset
sub eax,ecx
lea ebx,[eax*2+eax]
shl ebx,1
inc ebx
add ebx,ed_left
shl ebx,16
add ebx,6
mov edx,ebp
call .draw_bg_eax
ret
;;;;;;;;;;;;;;;;;;
;;à®¢¥àª  ­ ¦ â «¨ shift
;;;;;;;;;;;;;;;;;;
.check_shift:
pusha ;á®åà ­¨¬ ¢á¥ ॣ¨áâàë
mcall 66,3,1
test al,0x03
je @f
or word ed_flags,ed_shift ;ãáâ ­®¢¨¬ ä« £
@@:edit_ex
}
;¬ ªà®á ª« ¢¨è ­  ª®â®àë¥ ¯à®¨á室¨â ॠªæ¨ï
macro use_key_process backspase,delete,left,right,home,end,insert
{
if backspase eq
else
cmp ah,8
jz .backspace
end if
if delete eq
else
cmp ah,0xb6
jz .delete
end if
if left eq
else
cmp ah,176
jz .left
end if
if right eq
else
cmp ah,179
jz .right
end if
if home eq
else
cmp ah,180
jz .home
end if
if home eq
else
cmp ah,181
jz .end
end if
if insert eq
else
cmp ah,185 ;insert
jz .insert
end if
}
macro use_key_no_process up,down,esc
{
if up eq
else
cmp ah,177
jz .editbox_exit
end if
if down eq
else
cmp ah,178
jz .editbox_exit
end if
if esc eq
else
cmp ah,27 ;ESC - ª« ¢¨è  ))
jz .editbox_exit
end if
}
 
macro use_key_figures_only
{
test word ed_flags,ed_figure_only ; ⮫쪮 æ¨äàë ?
jz @f
cmp ah,'0'
jb .editbox_exit
cmp ah,'9'
ja .editbox_exit
@@:
}
macro are_key_shift_press
{
test word ed_flags,ed_shift_on
je @f
;‚室­ë¥ ¤ ­­ë¥ edx=ed_size;ecx=ed_pos
push eax
mov edx,ed_size
mov ecx, ed_pos
pusha
;;;;;;;;;;;;;;;;;;;;;
;clear input arrea
mov ebp,ed_color
mov ebx,dword ed_shift_pos
call .sh_cl_
mov ebp,ed_size
call .clear_bg
;;;;;;;;;;;;;;;;;;;;;
popa
call .del_char
;;;;
mov eax,dword ed_shift_pos
mov ebx,ed_size
sub ebx,eax
mov ed_size,ebx
pop eax
@@:
}
macro are_key_cur_end
{
mov ecx,ed_size
mov edx, ed_max
test word ed_flags,ed_insert
jne @f
cmp ecx,edx
jae .editbox_exit
@@: mov ebx, ed_pos
cmp ebx,edx
jl @f ; ¥á«¨ ¬¥­ìè¥ ¨«¨ à ¢­®
jmp .editbox_exit
 
@@: ; ᤢ¨£ ¥¬ ᨬ¢®«ë ¯®á«¥ ªãàá®à  ¢¯à ¢®
mov ecx,ed_size
push edi eax
mov ebp,edi
mov esi,ed_text ; “ª § â¥«ì ­  ¡ãä¥à
;ã¤¥¬ à ¡®â âì á® áâப®©
add esi,ecx ;add ed_size ¤®¡ ¢¨¬ max size
mov edi,esi
 
cmp ecx,ebx ;…᫨ ã ­ á ¯®§¨æ¨ï ªãàá®à  = ⥪ã饬ã à §¬¥àã ­ ¯¥ç â ­­ëå ᨬ¢®«®¢ â.¥. ªãàá®à á⮨⠢ ª®­æ¥
je .In_k
 
test word [ebp+40],ed_insert ;IF insert is enable â.ª. edi ¨§¬¥­¥­  ¤à¥á㥬 ç¥à¥§ ebp
jne .ins_v
;clear
pusha
mov edi,ebp
mov ebp,ed_size
call .clear_bg
popa
sub ecx,ebx ; ©¤¥¬ ª®«-¢® ᨬ¢®«®¢ ¤«ï ¯¥à¥¤¢¨¦¥­¨ï.
inc edi ;‘¬¥á⨬ ­ è¨ ᨬ¢®«ë ¢ ¯à ¢®
std
inc ecx
@@:
;--------
lodsb
stosb
;--------
loop @b
.In_k: cld
pop eax
mov al,ah
stosb
pop edi
; ¢áâ ¢«ï¥¬ ª®¤ ª« ¢¨è¨ â㤠, £¤¥ ªãàá®à
; 㢥«¨ç¨¢ ¥¬ §­ ç¥­¨¥ à §¬¥à  ¨ ¯®§¨æ¨¨
inc dword ed_size
inc dword ed_pos
call .draw_all2
jmp .shift
}
macro use_work_key
{
.insert: test word ed_flags,ed_insert ;not word ed_insert
je @f
and word ed_flags,ed_insert_cl
jmp .editbox_exit
@@:
or word ed_flags,ed_insert
jmp .editbox_exit
.ins_v:
dec dword [ebp+42];ed_size ;processing is insert
sub esi,ecx
add esi,ebx
mov edi,esi
;clear
pusha
mov edi,ebp
mov ebp,ed_pos
call .clear_bg
popa
jmp .In_k
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.delete:
mov edx,ed_size
mov ecx,ed_pos
cmp edx,ecx
jg .bac_del
test word ed_flags,ed_shift_on
jne .del_bac
edit_ex
.bac_del:
call .del_char
jmp .draw_all
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;--- ­ ¦ â  ª« ¢¨è  backspace ---
.backspace:
; ¯à®¢¥à塞, ªãàá®à ã «¥¢®£® ªà ï ?
mov ecx,ed_pos
test ecx,ecx
jnz .del_bac
test word ed_flags,ed_shift_on
jne .bac_del
 
edit_ex
.del_bac:
mov edx,ed_size
cmp edx,ecx ;if ed_pos=ed_size
je @f
dec ecx
call .del_char
@@: test word ed_flags,ed_shift_on
jne .bac_del
dec dword ed_pos
.draw_all:
push .shift;.draw_cursor_text;eax
 
test word ed_flags,ed_shift_on
je @f
mov eax,dword ed_shift_pos
mov ebx,ed_size
sub ebx,eax
mov ed_size,ebx
 
mov ebp,ed_color
call .clear_cursor
call .check_offset
call .draw_bg
ret
@@: dec dword ed_size
 
.draw_all2:
and word ed_flags,ed_shift_cl
mov ebp,ed_color
call .clear_cursor
call .check_offset
mov ebp,ed_size
call .clear_bg
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;--- ­ ¦ â  ª« ¢¨è  left ---
.left: mov ebx,ed_pos
test ebx,ebx
jz .sh_st_of
or word ed_flags,ed_left_fl
call .sh_first_sh
dec dword ed_pos
call .sh_enable
jmp .draw_cursor_text
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;--- ­ ¦ â  ª« ¢¨è  right ---
.right: mov ebx,ed_pos
cmp ebx,ed_size
je .sh_st_of
and word ed_flags,ed_right_fl
call .sh_first_sh
inc dword ed_pos
call .sh_enable
jmp .draw_cursor_text
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.home:
mov ebx,ed_pos
test ebx,ebx
jz .sh_st_of
call .sh_first_sh
xor eax,eax
mov ed_pos,eax
call .sh_home_end
jmp .draw_cursor_text
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.end:
mov ebx,ed_pos
cmp ebx,dword ed_size
je .sh_st_of
call .sh_first_sh
mov eax,ed_size
mov ed_pos,eax
call .sh_home_end
jmp .draw_cursor_text
}
 
macro use_mouse_func scr_w
{
;----------------------------------------------------------
;--- Ž¡à ¡®âª  .mouse_wigwag
;----------------------------------------------------------
.mouse_wigwag:
shr eax,16
or word ed_flags,ed_shift_bac+ed_shift_on+ed_shift
;;;;;;;;;;;;;;;;;;
;;¯à®æ¥¤ãà  ®¡à ¡®âª¨ ¯®«®¦¥­¨ï ¢ë¤¥«¥­­®£® ⥪áâ , ª®£¤  ¯à®¨á室¨â ¢ë室 §  ¯à¥¤¥«ë editbox
;;;;;;;;;;;;;;;;;;
mov ebx,[procinfo.box.left]
add ebx,ed_left
if scr_w eq
else
add ebx,dword scr_w
end if
cmp eax,ebx
jb .mleft
 
add ebx,ed_width
cmp eax,ebx
ja .mright
 
sub ebx,ed_width
 
xor edx,edx
sub eax,ebx ; ¢ëç⨬ ¨§ ª®®à¤¨­ â ¬ë誨 ¯® ®á¨ å ª®®à¤¨­ âë ¤® editbox ¯® ®á¨ å
mov ebx,6
div ebx
;;;;;;;;;;;;;;;;;;
;;¯à®æ¥¤ãà  ®¡à ¡®âª¨ ¯®«®¦¥­¨ï ¢ë¤¥«¥­­®£® ⥪áâ , ¢ ¯à¥¤¥« å ®¡« á⨠editbox
;;;;;;;;;;;;;;;;;;
;®«ã稫¨ ª®®à¤¨­ âë ¢ eax ¬ë誨, â.¥. ªã¤  ®­  ¯¥à¥¬¥á⨫ áì
;¨á®¢ ­¨¥ § ªà è¥­ëå ¯àאַ㣮«ì­¨ª®¢ ¨ ®ç¨á⪠ ¨å
add eax,ed_offset ;¤®¡ ¢¨¬ ᬥ饭¨¥
cmp eax,dword ed_size ;¥á«¨ ¢ë諨 §  ¯à¥¤¥«ë, â® ­¨ç¥£® ­¥ ¤¥« âì
ja .mwigvag
.mdraw:
mov dword ed_pos,eax ;á®åà ­¨¬ ­®¢®¥ §­ ç¥­¨¥
;¨á®¢ ­¨¥ § ªà è¥­ëå ¯àאַ㣮«ì­¨ª®¢ ¨ ®ç¨á⪠ ¨å
mov ecx,dword ed_shift_pos
mov ebx,dword ed_shift_pos_old
mov dword ed_shift_pos_old,eax ;¢­¥á¥¬ ­®¢®¥ §­ ç¥­¨¥ áâ à®© ¯®§¨æ¨¨ ªãàá®à 
;¯à®¢¥àª  ¨ à¨á®¢ ­¨¥ § ªà è¥­ëå ®¡« á⥩
cmp ecx,ebx ;¢ëïá­ï¥¬ ªã¤  ¡ë«® ¤¢¨¦¥­¨¥ ­  ®¤¨­ è £ ­ § ¤
je .m1_shem ;¤¢¨¦¥­¨ï ­¥ ¡ë«® à ­¥¥
jb .msmaller ;¤¢¨¦¥­¨¥ ¡ë«® ->
cmp ebx,eax ;¤¢¨¦¥­¨¥ ¡ë«® ¤® í⮣® <- ¨ âãâ ¬ë ¯à®¢¥à塞 ᥩç á ªã¤  ¤¢¨¦¥­¨¥ ¯à®¨á室¨â
ja .m1_shem ;¥á«¨ ¡ë«® ¤¢¨¦¥­¨¥ <- â® ­ã¦­® § ªà á¨âì ®¡« áâì
je .mwigvag ;¥á«¨ ¨§¬¥­¥­¨ï ­¥ ¡ë«®, â® ­¨ç¥£® ­¥ ¤¥« âì
mov ebp,ed_color ;âã⠭㦭® ®ç¨áâ¨âì ®¡« áâì c ed_pos ed_shift_pos_old
;¢å®¤­ë¥ ¯ à ¬¥âàë ebp=color ebx=ed_shift_pos
call .sh_cl_
jmp .mwigvag
.msmaller:
cmp ebx,eax
jb .m1_shem
mov ebp,ed_color
;¢å®¤­ë¥ ¯ à ¬¥âàë ebp=color ebx=ed_shift_pos
call .sh_cl_
jmp .mwigvag
;alike =
.m1_shem:
mov ebp,shift_color
;¢å®¤­ë¥ ¯ à ¬¥âàë ebp=color ebx=ed_shift_pos
mov ebx,ecx
call .sh_cl_
jmp .mwigvag
.mwigvag:
and word ed_flags,ed_shift_mcl
jmp .draw_cursor_text
; popa
; ret
.mleft:
mov eax,ed_pos
cmp eax,0
jbe .mwigvag
dec eax
call .check_offset
push eax
mov ebx,ed_shift_pos
mov ebp,shift_color
call .sh_cl_
pop eax
jmp .mdraw
.mright:
mov eax,ed_pos
mov ebx,ed_size
cmp eax,ebx
jae .mwigvag
inc eax
call .check_offset
mov ebx,ed_shift_pos
mov ebp,shift_color
push eax
call .sh_cl_
pop eax
jmp .mdraw
}
 
macro use_work_mause scr_h,scr_w
;----------------------------------------------------------
;--- € ­¥ 㤥ন¢ ¥¬ «¨ ¬ë ª« ¢¨èã ¬ë誨, ¯¥à¥¬¥é ï ªãàá®à, ¢® ¢á¥ à §­ë¥ áâ®à®­ë?
;----------------------------------------------------------
{
test word ed_flags,ed_mouse_on
jne .mouse_wigwag
;----------------------------------------------------------
;--- ¯à®¢¥à塞, ¯®¯ ¤ ¥â «¨ ªãàá®à ¢ edit box -------------
;----------------------------------------------------------
mov ebx,[procinfo.box.top]
add ebx,ed_top
if scr_h eq
else
add ebx,scr_h
end if
cmp ax,bx
jl ._blur;.mouse_end_no_focus
 
add ebx,ed_height
cmp ax,bx
jg ._blur;.mouse_end_no_focus
 
shr eax,16
 
mov ebx,[procinfo.box.left]
add ebx,ed_left
if scr_w eq
else
add ebx,scr_w
end if
cmp ax,bx
jl ._blur;.mouse_end_no_focus
 
add ebx,ed_width
cmp ax,bx
jg ._blur;.mouse_end_no_focus
;--- ¨§¬¥­ï¥¬ ¯®§¨æ¨î ªãàá®à  ---
push eax
mov ebp,ed_color
call .clear_cursor
pop eax
._mvpos:
mov ebx,dword [procinfo.box.left]
xor edx,edx
sub eax,ed_left
sub eax,ebx
if scr_w eq
else
add ebx,scr_w
sub eax,2
end if
mov ebx,6
div bx
add eax,ed_offset
cmp eax,ed_size
jna ._mshift
mov eax,ed_size
._mshift:
;;;;;;;
;;‘¥ªæ¨ï ®¡à ¡®âª¨ shift ¨ ¢ë¤¥«¥­¨ï ¯® shift
;;;;;;;
test word ed_flags,ed_shift_bac
je @f
mov ebp,dword ed_color
mov ebx,dword ed_shift_pos
push eax
call .sh_cl_
and word ed_flags,ed_shift_bac_cl
pop eax
@@:
test word ed_flags,ed_mouse_on
jne @f
mov dword ed_shift_pos,eax
or word ed_flags,ed_mouse_on
mov dword ed_pos,eax
mov dword [mouse_flag],edi ;ãáâ ­®¢¨¬ ¨¤¥­â¨ä¨ª â®à
bts word ed_flags,1 ;ãáâ ­®¢ª  䮪ãá 
jmp .m_sh
@@:
cmp eax,dword ed_shift_pos ;¥á«¨ ¯®§¨æ¨¨ ­¥ ¨§¬¥­¨«¨áì
je .editbox_exit
mov ed_pos,eax
mov ebp,dword shift_color
mov ebx,dword ed_shift_pos
call .sh_cl_
or word ed_flags,ed_mous_adn_b ;ãáâ ­®¢¨¬ ¡¨â çâ® ¬ë ¢ë¤¥«¨«¨ +shift_on +
.m_sh: call .draw_text
call .draw_cursor
;----------------------------------------------------------
;--- ¯à®æ¥¤ãà  ãáâ ­®¢ª¨ 䮪ãá  ---------------------------
;----------------------------------------------------------
jmp .drc
._blur:
test word ed_flags,ed_always_focus
jne .editbox_exit
btr word ed_flags,1 ; ¥á«¨ ­¥ ¢ 䮪ãá¥, ¢ë室¨¬
jnc .editbox_exit
 
mov ebp,ed_color
call .clear_cursor
.drc: call .draw_border
jmp .editbox_exit
}
 
 
; Œ ªà®á ¢ë室 
macro edit_ex
{
popa
ret
}
macro debug
{
;----------- ®â« ¤ª 
pushad
; mov dword [ed_buffer.2],0
; mov eax,edi
mov eax,dword [ed_buffer.2]
mov edi,ed_buffer.3
call .str
;à¨á®¢ ­¨¥ ä®­ 
mov eax,13
mov ebx,178*65536+70
mov ecx,28*65536+10
xor edx,edx
int 0x40
;¢ë¢®¤ §­ ç¥­¨ï ­  íªà ­
mov eax,4
mov ebx,180*65536+30
mov ecx,0x10DDBBCC
mov edx,ed_buffer.3
mov esi,8
int 0x40
popad
;----------- ®â« ¤ª 
}
macro debug_func
{
.str:
mov ecx,0x0a ;§ ¤ ¥âáï á¨á⥬  áç¨á«¥­¨ï ¨§¬¥­ïîâáï ॣ¨áâàë ebx,eax,ecx,edx ¢å®¤­ë¥ ¯ à ¬¥âàë eax - ç¨á«®
;¯à¥à¥¢®¤ ç¨á«  ¢ ASCII áâப㠢§®¤­ë¥ ¤ ­­ë¥ ecx=á¨á⥬  áç¨á«¥­ï edi  ¤à¥á ªã¤  § ¯¨á뢠âì, ¡ã¤¥¬ áâபã, ¯à¨ç¥¬ ª®­¥æ ¯¥à¥¬¥­­®©
cmp eax,ecx ;áà ¢­¨âì ¥á«¨ ¢ eax ¬¥­ìè¥ ç¥¬ ¢ ecx â® ¯¥à¥©â¨ ­  @@-1 â.¥. ­  pop eax
jb @f
xor edx,edx ;®ç¨áâ¨âì edx
div ecx ;à §¤¥«¨âì - ®áâ â®ª ¢ edx
push edx ;¯®«®¦¨âì ¢ á⥪
;dec edi ;ᬥ饭¨¥ ­¥®¡å®¤¨¬®¥ ¤«ï § ¯¨á¨ á ª®­æ  áâப¨
call .str;¯¥à¥©â¨ ­  á ¬ã ᥡï â.¥. ¢ë§¢ âì á ¬ã á¥¡ï ¨ â ª ¤® ⮣® ¬®¬¥­â  ¯®ª  ¢ eax ­¥ áâ ­¥â ¬¥­ìè¥ ç¥¬ ¢ ecx
pop eax
@@: ;cmp al,10 ;¯à®¢¥à¨âì ­¥ ¬¥­ìè¥ «¨ §­ ç¥­¨¥ ¢ al 祬 10 (¤«ï á¨á⥬ë áç¨á«¥­ï 10 ¤ ­­ ï ª®¬ ­¤  - «¨è­ ï))
;sbb al,$69 ;- ç¥áâ­® ¤ ­­ ï ¨­áâàãªæ¨ï ¬¥­ï § áâ ¢«ï¥â § ¤ã¬ âìáï â.¥. ï ­¥ §­ î ª ª íâ® à ¡®â ¥â
;das ;¯®á«¥ ¤ ­­®© ª®¬ ­¤ë ª ª ¡ë ¯à®¨á室¨â 㬥­ì襭¨¥ al ­  66h (¢ ª­¨£¥ ­ ¯¨á ­® ¤à㣮¥)
or al,0x30 ;¤ ­­ ï ª®¬ ­¤  ª®à®ç¥ 祬 ¤¢¥ ¢ëè¥
stosb ;§ ¯¨á âì í«¥¬¥­â ¨§ ॣ¨áâà  al ¢ ï祪㠯 ¬ï⨠es:edi
ret ;¢¥à­ãâìáï ç¥­ì ¨­â¥à¥á­ë© 室 â.ª. ¯®ª  ¢ á⥪¥ åà ­¨âìáï ª®«-¢® ¢ë§®¢®¢ â® á⮫쪮 à § ¬ë ¨ ¡ã¤¥¬ ¢ë§ë¢ âìáï
}
 
;;;;;;;;;;;;;;;
;For LibGui
;;;;;;;;;;;;;;;
macro srt_ed_libgui
{
ed_width equ [EditBox.ed_width] ;è¨à¨­  ª®¬¯®­¥­â 
ed_left equ [EditBox.ed_left] ;¯®«®¦¥­¨¥ ¯® ®á¨ å
ed_top equ [EditBox.ed_top] ;¯®«®¦¥­¨¥ ¯® ®á¨ ã
ed_color equ [EditBox.ed_color] ;梥â ä®­  ª®¬¯®­¥­â 
shift_color equ [EditBox.shift_color] ;=0x6a9480
ed_focus_border_color equ [EditBox.ed_focus_border_color] ;梥â à ¬ª¨ ª®¬¯®­¥­â 
ed_blur_border_color equ [EditBox.ed_blur_border_color] ;梥⠭¥  ªâ¨¢­®£® ª®¬¯®­¥­â 
ed_text_color equ [EditBox.ed_text_color] ;梥â ⥪áâ 
ed_max equ [EditBox.ed_max] ;ª®«-¢® ᨬ¢®«®¢ ª®â®àë¥ ¬®¦­® ¬ ªá¨¬ «ì­® ¢¢¥áâ¨
ed_text equ [EditBox.ed_text] ;㪠§ â¥«ì ­  ¡ãä¥à
ed_flags equ [EditBox.ed_flags] ;ä« £¨
ed_size equ [EditBox.ed_size] ;ª®«-¢® ᨬ¢®«®¢
ed_pos equ [EditBox.ed_poz] ;¯®§¨æ¨ï ªãàá®à 
ed_offset equ [EditBox.ed_offset] ;ᬥ饭¨¥
cl_curs_x equ [EditBox.cl_curs_x] ;¯à¥¤ë¤ã饥 ª®®à¤¨­ â  ªãàá®à  ¯® å
cl_curs_y equ [EditBox.cl_curs_y] ;¯à¥¤ë¤ã饥 ª®®à¤¨­ â  ªãàá®à  ¯® ã
ed_shift_pos equ [EditBox.ed_shift_pos] ;¯®«®¦¥­¨¥ ªãàá®à 
ed_shift_pos_old equ [EditBox.ed_shift_pos_old] ;áâ à®¥ ¯®«®¦¥­¨¥ ªãàá®à 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Bit mask from editbox
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ed_figure_only= 1000000000000000b ;®¤­¨ ᨬ¢®«ë
ed_always_focus= 100000000000000b
ed_focus= 10b ;䮪ãá ¯à¨«®¦¥­¨ï
ed_shift_on= 1000b ;¥á«¨ ­¥ ãáâ ­®¢«¥­ -§­ ç¨â ¢¯¥à¢ë¥ ­ ¦ â shift,¥á«¨ ¡ë« ãáâ ­®¢«¥­, §­ ç¨â ¬ë 㦥 çâ® - â® ¤¥« «¨ 㤥ন¢ ï shift
ed_shift_on_off=1111111111110111b
ed_shift= 100b ;¢ª«îç ¥âáï ¯à¨ ­ ¦ â¨¨ ­  shift â.¥. ¥á«¨ ­ ¦¨¬ î
ed_shift_off= 1111111111111011b
ed_shift_bac= 10000b ;¡¨â ¤«ï ®ç¨á⪨ ¢ë¤¥«¥­®£® shift â.¥. ¯à¨ ãáâ ­®¢ª¥ £®¢®à¨â çâ® ¥áâì ¢ë¤¥«¥­¨¥
ed_shift_bac_cl=1111111111101111b ;®ç¨á⪠ ¯à¨ 㤠«¥­¨¨ ¢ë¤¥«¥­¨ï
ed_shift_cl= 1111111111100011b
ed_shift_mcl= 1111111111111011b
ed_left_fl= 100000b
ed_right_fl= 1111111111011111b
ed_offset_fl= 1000000b
ed_offset_cl= 1111111110111111b
ed_insert= 10000000b
ed_insert_cl= 1111111101111111b
ed_mouse_on = 100000000b
ed_mous_adn_b= 100011000b
ed_mouse_on_off=1111111011111111b
ed_height=14 ; ¢ëá®â 
}
/programs/network_old/icq/trunk/icons.inc
0,0 → 1,64
 
 
 
redicq:
 
 
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,128,0,0,128,0,0,128,0,0,0,0,0
db 128,0,0,128,0,0,128
db 0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,128,0,0,179,0,0,179,0,0,179,0,0,128,0,0
db 179,0,0,179,0,0,179,0,0,128
db 0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,128,0,0,230,0,0,202,0,0,179,0,0,128,0,0
db 230,0,0,202,0,0,179,0,0,128
db 0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,128,0,0,128,0
db 0,128,0,0,179,0,0,202,0,0,230,0,0,128,0,0
db 230,0,0,202,0,0,179,0,0,128,0,0,128,0,0,128
db 0,0,0
db 0,0,128,0,0,179,0,0,179,0
db 0,179,0,0,128,0,0,230,0,0,230,0,0,128,0,0
db 230,0,0,230,0,0,128,0,0,179,0,0,179,0,0,179
db 0,0,128
db 0,0,128,0,0,179,0,0,202,0
db 0,202,0,0,230,0,0,128,0,0,230,0,0,128,0,0
db 230,0,0,128,0,0,230,0,0,202,0,0,202,0,0,179
db 0,0,128
db 0,0,128,0,0,179,0,0,230,0
db 0,230,0,0,230,0,0,230,0,0,128,0,255,255,0,0
db 128,0,0,230,0,0,230,0,0,230,0,0,230,0,0,179
db 0,0,128
db 0,0,0,0,0,128,0,0,128,0
db 0,128,0,0,128,0,0,128,0,255,255,0,255,255,0,255
db 255,0,0,128,0,0,128,0,0,128,0,0,128,0,0,128
db 0,0,0,0,0,128,0,0,179,0,0,179,0
db 0,179,0,0,179,0,0,179,0,0,128,0,255,255,0,0
db 128,0,0,179,0,0,179,0,0,179,0,0,179,0,0,179
db 0,0,128
db 0,0,128,0,0,202,0,0,202,0
db 0,202,0,0,202,0,0,128,0,0,179,0,0,128,0,0
db 179,0,0,128,0,0,230,0,0,202,0,0,202,0,0,179
db 0,0,128
db 0,0,128,0,0,230,0,0,230,0
db 0,230,0,0,128,0,0,202,0,0,179,0,0,128,0,0
db 230,0,0,179,0,0,128,0,0,230,0,0,230,0,0,179
db 0,0,128
db 0,0,0,0,0,128,0,0,128,0
db 0,128,0,0,230,0,0,202,0,0,179,0,0,128,0,0
db 230,0,0,202,0,0,179,0,0,128,0,0,128,0,0,128
db 0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,128,0,0,230,0,0,202,0,0,179,0,0,128,0,0
db 230,0,0,202,0,0,179,0,0,128
db 0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,128,0,0,230,0,0,230,0,0,179,0,0,128,0,0
db 230,0,0,230,0,0,179,0,0,128
db 0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,128,0,0,128,0,0,128,0,0,0,0,0
db 128,0,0,128,0,0,128,0,0,0,0,0,0,0,0,0
db 0,0,0
/programs/network_old/icq/trunk/ki.cfg
0,0 → 1,9
#
#
#
UIN="123456789"
PASS="PASS"
#
#
ICQIP="64.12.200.89"
#ICQIP="192.168.0.1"
/programs/network_old/icq/trunk/macros.inc
0,0 → 1,543
@^ fix macro comment {
^@ fix }
 
; -------------------------
macro library [lname,fname]
{
forward
dd __#lname#_library_table__,__#lname#_library_name__
common
dd 0
forward
align 4
__#lname#_library_name__ db fname,0
}
 
macro import lname,[name,sname]
{
common
align 4
__#lname#_library_table__:
forward
if used name
name dd __#name#_import_name__
end if
common
dd 0
forward
if used name
align 4
__#name#_import_name__ db sname,0
end if
}
 
macro export [name,sname]
{
forward
dd __#name#_export_name__,name
common
dd 0
forward
align 4
__#name#_export_name__ db sname,0
}
; -------------------------
 
macro m2m dest,src {
push src
pop dest
}
 
 
macro iglobal {
IGlobals equ IGlobals,
macro __IGlobalBlock { }
macro uglobal {
UGlobals equ UGlobals,
macro __UGlobalBlock { }
 
endg fix } ; Use endg for ending iglobal and uglobal blocks.
 
 
macro IncludeIGlobals{
macro IGlobals dummy,[n] \{ __IGlobalBlock
purge __IGlobalBlock \}
match I, IGlobals \{ I \} }
 
macro IncludeUGlobals{
macro UGlobals dummy,[n] \{
\common
\local begin, size
begin = $
virtual at $
\forward
__UGlobalBlock
purge __UGlobalBlock
\common
size = $ - begin
end virtual
rb size
\}
match U, UGlobals \{ U \} }
 
uglobal
endg
iglobal
endg
 
 
; new application structure
macro meos_app_start
{
use32
org 0x0
 
db 'MENUET01'
dd 0x01
dd __start
dd __end
dd __memory
dd __stack
 
if used __params & ~defined __params
dd __params
else
dd 0x0
end if
 
dd 0x0
}
MEOS_APP_START fix meos_app_start
 
macro code
{
__start:
}
CODE fix code
 
macro data
{
__data:
IncludeIGlobals
}
DATA fix data
 
macro udata
{
if used __params & ~defined __params
__params:
db 0
__end:
rb 255
else
__end:
end if
__udata:
IncludeUGlobals
}
UDATA fix udata
 
macro meos_app_end
{
align 32
rb 2048
__stack:
__memory:
}
MEOS_APP_END fix meos_app_end
 
 
; macro for defining multiline text data
struc mstr [sstring]
{
forward
local ssize
virtual at 0
db sstring
ssize = $
end virtual
dd ssize
db sstring
common
dd -1
}
 
; macro for defining multiline text data
struc mls [sstring]
{
forward
local ssize
virtual at 0
db sstring ; mod
ssize = $
end virtual
db ssize
db sstring
common
db -1 ; mod
}
 
 
 
; strings
macro sz name,[data] { ; from MFAR [mike.dld]
common
if used name
name db data
.size = $-name
end if
}
 
macro lsz name,[lng,data] { ; from MFAR [mike.dld]
common
if used name
label name
forward
if lang eq lng
db data
end if
common
.size = $-name
end if
}
 
macro szc name,elsz,[data] { ; from MFAR [mike.dld]
common
local s,m
m = 0
if used name
label name
forward
virtual at 0
db data
s = $
end virtual
d#elsz s
if m < s
m = s
end if
db data
common
.size = $-name
.maxl = m
end if
}
 
macro lszc name,elsz,[lng,data] { ; from MFAR [mike.dld]
common
local s,m,c
m = 0
c = 0
if used name
label name
forward
if lang eq lng
virtual at 0
db data
s = $
end virtual
d#elsz s
if m < s
m = s
end if
db data
c = c+1
end if
common
.size = $-name
.maxl = m
.count = c
end if
}
 
 
; easy system call macro
macro mpack dest, hsrc, lsrc
{
if (hsrc eqtype 0) & (lsrc eqtype 0)
mov dest, (hsrc) shl 16 + lsrc
else
if (hsrc eqtype 0) & (~lsrc eqtype 0)
mov dest, (hsrc) shl 16
add dest, lsrc
else
mov dest, hsrc
shl dest, 16
add dest, lsrc
end if
end if
}
 
macro __mov reg,a,b { ; mike.dld
if (~a eq)&(~b eq)
mpack reg,a,b
else if (~a eq)&(b eq)
mov reg,a
end if
}
 
 
include 'config.inc'
;__CPU_type equ p5
SYSENTER_VAR equ 0
 
macro mcall a,b,c,d,e,f { ; mike.dld, updated by Ghost for Fast System Calls
local ..ret_point
__mov eax,a
__mov ebx,b
__mov ecx,c
__mov edx,d
__mov esi,e
__mov edi,f
 
if __CPU_type eq p5
int 0x40
else
if __CPU_type eq p6
push ebp
mov ebp, esp
push ..ret_point ; it may be 2 or 5 byte
sysenter
..ret_point:
pop edx
pop ecx
 
else
if __CPU_type eq k6
push ecx
syscall
pop ecx
else
display 'ERROR : unknown CPU type (set to p5)', 10, 13
__CPU_type equ p5
int 0x40
end if
end if
end if
}
 
 
; -------------------------
macro header a,[b] {
common
use32
org 0
db 'MENUET',a
forward
if b eq
dd 0
else
dd b
end if }
macro section name { align 16
label name }
macro func name {
if ~used name
display 'FUNC NOT USED: ',`name,13,10
else
align 4
name:
;diff16 `name,0,name
;pushad
;pushfd
;dps `name
;newline
;mcall 5,1
;popfd
;popad
}
macro endf { end if }
 
macro diff16 title,l1,l2
{
local s,d
s = l2-l1
display title,': 0x'
repeat 8
d = '0' + s shr ((8-%) shl 2) and $0F
if d > '9'
d = d + 'A'-'9'-1
end if
display d
end repeat
display 13,10
}
 
macro diff10 title,l1,l2
{
local s,d,z,m
s = l2-l1
z = 0
m = 1000000000
display title,': '
repeat 10
d = '0' + s / m
s = s - (s/m)*m
m = m / 10
if d <> '0'
z = 1
end if
if z <> 0
display d
end if
end repeat
display 13,10
}
 
; optimize the code for size
__regs fix <eax,ebx,ecx,edx,esi,edi,ebp,esp>
 
macro add arg1,arg2
{
if (arg2 eqtype 0)
if (arg2) = 1
inc arg1
else
add arg1,arg2
end if
else
add arg1,arg2
end if
}
 
macro sub arg1,arg2
{
if (arg2 eqtype 0)
if (arg2) = 1
dec arg1
else
sub arg1,arg2
end if
else
sub arg1,arg2
end if
}
 
macro mov arg1,arg2
{
if (arg1 in __regs) & ((arg2 eqtype 0) | (arg2 eqtype '0'))
if (arg2) = 0
xor arg1,arg1
else if (arg2) = 1
xor arg1,arg1
inc arg1
else if (arg2) = -1
or arg1,-1
else if (arg2) > -128 & (arg2) < 128
push arg2
pop arg1
else
mov arg1,arg2
end if
else
mov arg1,arg2
end if
}
 
 
macro RGB [a] {
common
match (r=,g=,b),a \{
\dd ((r) shl 16) or ((g) shl 8) or (b)
\}
}
 
 
struc POINT _t,_dx,_dy {
.x _t _dx
.y _t _dy
}
 
; structure definition helper
include 'struct.inc'
 
struct RECT
left dd ?
top dd ?
right dd ?
bottom dd ?
ends
 
struct BOX
left dd ?
top dd ?
width dd ?
height dd ?
ends
 
; structures used in MeOS
struct process_information
cpu_usage dd ? ; +0
window_stack_position dw ? ; +4
window_stack_value dw ? ; +6
dw ? ; +8
process_name rb 12 ; +10
memory_start dd ? ; +22
used_memory dd ? ; +26
PID dd ? ; +30
box BOX ; +34
slot_state dw ? ; +50
dw ? ; +52
client_box BOX ; +54
wnd_state db ? ; +70
rb (1024-71)
ends
 
struct system_colors
frame dd ?
grab dd ?
grab_button dd ?
grab_button_text dd ?
grab_text dd ?
work dd ?
work_button dd ?
work_button_text dd ?
work_text dd ?
work_graph dd ?
ends
 
struct FILEDATE
Second db ?
Minute db ?
Hour db ?
db ?
Day db ?
Month db ?
Year dw ?
ends
 
struct FILEINFO
Attributes dd ?
IsUnicode db ?
db 3 dup(?)
DateCreate FILEDATE
DateAccess FILEDATE
DateModify FILEDATE
Size dq ?
ends
 
; constants
 
; events
EV_IDLE = 0
EV_TIMER = 0
EV_REDRAW = 1
EV_KEY = 2
EV_BUTTON = 3
EV_EXIT = 4
EV_BACKGROUND = 5
EV_MOUSE = 6
EV_IPC = 7
EV_STACK = 8
 
; event mask bits for function 40
EVM_REDRAW = 1b
EVM_KEY = 10b
EVM_BUTTON = 100b
EVM_EXIT = 1000b
EVM_BACKGROUND = 10000b
EVM_MOUSE = 100000b
EVM_IPC = 1000000b
EVM_STACK = 10000000b
/programs/network_old/icq/trunk/parser.inc
0,0 → 1,696
;
; ‘âàãªâãà  ¤«ï ä㭪樨 70
;
 
struc sinfo
{
.subfnc_name dd 0
.pos_in_file dd 0
.reserved dd 0
.bytes_to_read dd 0
.pbuffer dd 0
.null db 0
.pname dd 0
}
 
 
 
 
;
; â ¡«¨æë §­ ç¥­¨©
;
; +----+-------------+-----------------+
; | in | Variable | Variable |
; | de | name | string |
; | x | | |
; | | | |
; +----+-------------+-----------------+
; | | | |
; | | | |
; | 1 | UIN | 'XXXXX..XX',0 |
; | | | |
; +----+-------------+-----------------+
; | | |
;
; § £à㧪  int ¯®ª  ­¥ ॠ«¨§®¢ ­ 
;
; +----+-------------+-----------------+
; | in | Variable | Variable |
; | de | name | int |
; | x | | |
; | | | |
; +----+-------------+-----------------+
; | | | |
; | | | |
; | 1 | BUFFSIZE | XXXXXXXX |
; | | | |
; +----+-------------+-----------------+
; | | |
;
;
 
 
TABLE_SIZE equ 16
VNAME_LEN equ 8
VAR_LEN equ 16
 
;
; Ž¯¨á ­¨¥ â ¡«¨æë §­ ç¥­¨©
 
virtual at 0
vartable:
.uin db VAR_LEN dup ?
.pass db VAR_LEN dup ?
.icqip db VAR_LEN dup ?
 
 
end virtual
 
 
;
; Š®¤ë ®è¨¡®ª ä ©«®¢®© á¨á⥬ë
;
 
FIO_SUCCESS equ 0
FIO_UNSUPPORTED equ 2
FIO_UNKNOWNFS equ 3
FIO_FILENOTFOUND equ 5
FIO_EOF equ 6
FIO_BADPOINTER equ 7
FIO_DISKFULL equ 8
FIO_FATDAMAGED equ 9
FIO_DENIED equ 10
FIO_ERRORDEVICE equ 11
 
 
IOBUFF_SIZE equ 128
 
 
 
 
;
; ¬ ªà®á ¤«ï ¯®¨áª  í«¥¬¥­â  ¢ áâப¥
; ¢®§¢à é ¥â ¢ eax ­®¬¥à í«¥¬¥­â  ¨«¨ -1 ¥á«¨ ­¥ ­ ©¤¥­
macro findchar string, len, char
{
local ..fc_endstr, ..fc_end
 
push ebx
push ecx
push edi
 
 
mov edi, string
mov ecx, len
mov ebx, ecx
cld
mov al, char
repne scasb
jcxz ..fc_endstr
 
sub ebx, ecx ; ®¬¥à =
mov eax, ebx
jmp ..fc_end
 
..fc_endstr:
mov eax, -1
 
 
..fc_end:
pop edi
pop ecx
pop ebx
 
}
 
;
; Œ ªà®á ¤«ï ¯®¨áª  í«¥¬¥­â  áâப¨, ®â«¨ç î饣®áï ®â
; § ¤ ­­®£®
 
macro findother string, len, char
{
local ..fc_endstr, ..fc_end
 
push ebx
push ecx
push edi
 
 
mov edi, string
mov ecx, len
mov ebx, ecx
cld
mov al, char
repe scasb ; …᫨ ᨬ¢®« ­¥ char - ¢ë室¨¬
jcxz ..fc_endstr ; áâப  ¨§ char
 
sub ebx, ecx ; ¢ ebx - ­®¬¥à í«¥¬¥­â  ®â«¨ç­®£® ®â char
mov eax, ebx
jmp ..fc_end
 
..fc_endstr:
mov eax, -1
 
 
..fc_end:
pop edi
pop ecx
pop ebx
}
 
;
; Œ ªà®á ¤«ï ª®¯¨à®¢ ­¨ï áâப
;
macro mstrcpy from, to, leng
{
 
push ecx
push esi
push edi
 
mov ecx, leng
mov esi, from
mov edi, to
cld
rep movsb
 
pop edi
pop esi
pop ecx
 
}
 
 
;
; ˆ­¨æ¨ «¨§¨àã¥â â ¡«¨æë
;
 
; inittables:
;
;
; mstrcpy name1, nvtable, VNAME_LEN
; mstrcpy name2, (nvtable + NAME_LEN), VNAME_LEN
; mstrcpy name3, (nvtable + NAME_LEN * 2), VNAME_LEN
;
;
;
; ret
 
 
;
; § ¯®«­ï¥â â ¡«¨æë §­ ç¥­¨ï¬¨
; IN eax - ASCIIZ ¨¬ï ä ©« 
; OUT eax - १ã«ìâ â ç⥭¨ï
; ¥á«¨ १ã«ìâ â -1, ä®à¬ â ä ©«  ­¥¯à ¢¨«ì­ë©
;
parseconf:
push edi
push esi
;push eax
push ebx
push ecx
push edx
 
mov [strnum], dword 0
;
; à®ç¨â âì ¯®áâà®ç­® ª®­ä¨£
; ¥á«¨ áâப  ­ ç¨­ ¥âáï á ;, # - ª®¬¬¥­â à¨©
; ”®à¬ â UIN="1234567890"
; PASS="******" ¨ â.¤.
 
;
; ‘¡à®á ᬥ饭¨ï
mov [shift], dword 0
 
mov esi, eax
pc_still:
 
mov edx, esi
mov ecx, IOBUFF_SIZE
mov ebx, iobuff
 
call getstr
 
inc [strnum]
 
push eax
 
;
;à®¢¥àª  ¯®«ã祭­®© áâப¨
;
movzx eax, byte [iobuff]
 
test eax, eax
jz pc_next
 
cmp al, '#'
jz pc_next
 
cmp al, ';'
jz pc_next
 
;
;  ©â¨ ¨¬ï ¯¥à¥¬¥­­®©
;
findother iobuff, ebx, ' '
cmp eax, -1
jz pc_next
mov [stnpos], eax ;­ ç «® ¨¬¥­¨
 
;
; ­ ©â¨ =
;
mov ecx, ebx ; ˆáª âì ®â ­ ©¤¥­­®£® ᨬ¢®« 
sub ecx, eax ;
 
mov edi, iobuff
add edi, eax
 
findchar edi, ecx, '='
 
cmp eax, -1
jz pc_badformat
 
mov edi, [stnpos]
add eax, edi ; ¢ eax - ᬥ饭¨¥ ®â ­ ç «  áâப¨
mov [eqpos], eax
 
mov ecx, ebx
sub ecx, eax
 
;
; ¯à®¢¥à¨âì "
;
mov dl, [iobuff + eax]
cmp dl, '"'
jnz pc_badformat
;
; ­ ©â¨ § ªà뢠îéãî "
;
mov edi, iobuff
add edi, eax
 
inc edi
 
findchar edi, ecx, '"'
 
cmp eax, -1
jz pc_badformat
 
inc eax
 
mov edx, [eqpos]
add eax, edx
mov [edvpos], eax
 
;
; “áâ ­®¢¨âì §­ ç¥­¨¥
;
; „®¡ ¢¨âì § ¢¥àè î騥 0
 
mov eax, [stnpos]
dec eax
 
 
mov ebx, [eqpos]
mov ecx, ebx
dec ecx ; ª®«¨ç¥á⢮ ᨬ¢®«®¢ ¤® =
inc ebx ; à®¯ãáâ¨âì "
 
mov [iobuff + ecx], byte 0
 
mov edx, [edvpos]
dec edx
 
mov [iobuff + edx], byte 0
 
lea eax, [iobuff + eax]
lea ebx, [iobuff + ebx]
call setavar
 
jmp pc_next
 
 
 
 
pc_badformat:
pop eax
 
mov ebx, [strnum]
jmp pc_err
 
 
pc_next:
pop eax
 
cmp eax, FIO_EOF
jz pc_eof
cmp eax, FIO_SUCCESS
jnz pc_err
 
jmp pc_still
 
 
 
pc_eof:
pc_err:
pop edx
pop ecx
pop ebx
;pop eax
pop esi
pop edi
ret
 
; ®¨áª ¢ â ¡«¨æ¥ ¯¥à¥¬¥­­®© ¨ ãáâ ­®¢ª  ¥ñ §­ ç¥­¨ï
; IN eax - ­ §¢ ­¨¥ ¯¥à¥¬¥­­®© 㪠§ â¥«ì ­  ASCIIZ
; IN ebx - §­ ç¥­¨¥ ¯¥à¥¬¥­­®© 㪠§ â¥«ì ­  ASCIIZ
; OUT eax -१ã«ìâ â 0 = OK, -1 = ­¥â ¢ â ¡«¨æ¥ ¯¥à¥¬¥­­ëå
; OUT § ¯®«­ï¥â £«®¡ «ì­ãî â ¡«¨æã
setavar:
;push ebx
push ecx
push edx
push esi
push edi
push ebx
 
;
; Ž¯à¥¤¥«¨âì ¤«¨­ã áâப¨ - ­ §¢ ­¨¥ ¯¥à¥¬¥­­®©
;
mov edi, eax
push eax
 
mov ecx, VNAME_LEN
 
xor eax, eax ;ˆé¥¬ \0
cld
repne scasb
 
mov eax, VNAME_LEN
sub eax, ecx ; ‚ ecx - ®áâ â®ª ¤® ¬ ªá¨¬ «ì­®£® à §¬¥à  áâப¨
mov ebx, eax
 
 
pop eax
;
; ˆáª âì ¢ â ¡«¨æ¥ ¯®¤å®¤ï饥 ¨¬ï
;
xor edx, edx ;index
 
sv_next:
mov ecx, ebx
push eax
mov esi, eax
mov edi, nvtable
mov eax, edx
imul eax, VNAME_LEN ;offset
add edi, eax
pop eax
cld
repe cmpsb
jz sv_match
 
sv_inc:
inc edx
cmp edx, TABLE_SIZE
jae sv_fail
jmp sv_next
 
sv_match:
cmp ebx, VNAME_LEN ;‚ ebx - ¤«¨­  ¨á室­®© áâà®çª¨
jz sv_match2
 
push eax
mov edi, nvtable
mov eax, edx
imul eax, VNAME_LEN ;offset
add edi, eax
pop eax
 
cmp [edi + ebx], byte 0 ; …᫨ ¨¬ï ¢ â ¡«¨æ¥ ª®à®ç¥ ¬ ªá¨¬ «ì­®£®,
jnz sv_inc ; § ª ­ç¨¢ ¥âáï 0
 
sv_match2:
pop edi ;
push edi
;
; Ž¯à¥¤¥«ïâì ¤«¨­ã áâப¨ - ¯¥à¥¬¥­­ ï
;
xor eax, eax
mov ecx, VAR_LEN
cld
repne scasb
 
mov eax, VAR_LEN
sub eax, ecx
mov ecx, eax
mov ebx, eax
 
;
; Š®¯¨à®¢ âì ¯¥à¥¬¥­­ãî ¢ â ¡«¨æã
;
 
pop esi
push esi
 
mov eax, VAR_LEN
imul eax, edx
mov edi, vtable
add edi, eax
cld
rep movsb
 
;
; …᫨ áâப  ª®à®ç¥ ¯®«ï ¢ â ¡«¨æ¥, § ¯¨á âì ¢ ª®­¥æ 0
;
cmp ebx, VAR_LEN
jz sv_end
mov [edi + ebx], byte 0
 
 
 
sv_end:
xor eax, eax
jmp sv_fin
 
sv_fail:
mov eax, -1
 
sv_fin:
 
pop ebx
pop edi
pop esi
pop edx
pop ecx
;pop ebx
ret
 
 
 
 
 
;
; —⥭¨¥ ASCIIZ áâப¨ ¨§ ä ©« 
; IN ebx - 㪠§ â¥«ì ­  ¡ãä¥à
; ecx - à §¬¥à ¡ãä¥à 
; edx - 㪠§ â¥«ì ­  áâப㠨¬ï ä ©« 
; OUT ebx - ¤«¨­  áâப¨
; eax - १ã«ìâ â ç⥭¨ï
 
getstr:
;push eax
;push ebx
push ecx
push edx
push esi
 
;xor edx, edx
xor esi, esi
 
gs_read:
;
; ‡ ¯®«­ï¥¬ áâàãªâãàã
;
mov [finfo.subfnc_name], 0
mov eax, [shift]
mov [finfo.pos_in_file], eax
mov [finfo.bytes_to_read], ecx
mov [finfo.pbuffer], ebx
mov [finfo.pname], edx
 
push ebx
 
;
; —¨â¥¬
;
;mov eax, 70
;mov ebx, finfo
;int 40h
mcall 70, finfo
 
mov ecx, ebx ; ‚ ebx ª®«¨ç¥á⢮ ¯à®ç⥭­ëå ¡ ©â
 
pop ebx
 
;
; à®¢¥à¨âì १ã«ìâ â ç⥭¨ï - ¥á«¨ ­¥ EOF ¨ 0,
; ¢ë室¨¬
cmp eax, FIO_EOF
jz gs_loop
cmp eax, 0
jz gs_loop
 
jmp gs_ok
 
 
;
; Ž¡à ¡®âª  ¯®«ã祭­®£® ¡«®ª 
;
gs_loop:
mov dl, [ebx + esi]
cmp dl, 0Ah ;cr
jz gs_cr
inc esi
cmp esi, ecx
jnb gs_err
jmp gs_loop
 
gs_err:
;
; ‚ ¡ãä¥à¥ ­¥â ᨬ¢®«  ¯¥à¥­®á  áâப¨, â.¥. áâப  ᫨誮¬ ¤«¨­­ ï
; Žâ¡à á뢠¥¬ ¢á¥ ¤® ¡«¨¦ ©è¥£® ᨬ¢®«  ¯¥à¥­®á  áâப¨
; ¥á«¨ ª®­¥æ ä ©«  - ¢ë室¨¬
cmp eax, FIO_EOF
jz gs_endf
add [shift], ecx
jmp gs_read
 
 
gs_endf:
xor ebx, ebx
jmp gs_ok
 
gs_cr:
;
; ‘¡à®á¨âì १ã«ìâ â ç⥭¨ï
;
xor eax, eax
 
mov dl, [ebx + esi - 1]
cmp dl, 0Dh ;le
jz gs_le
 
mov [ebx + esi], byte 0
mov ebx, esi
 
 
inc esi
add [shift], esi
 
jmp gs_ok
 
gs_le:
mov [ebx + esi - 1], byte 0
mov [ebx + esi], byte 0
lea ebx, [esi - 1]
 
inc esi
add [shift], esi
 
gs_ok:
 
 
pop esi
pop edx
pop ecx
;pop ebx
;pop eax
ret
 
 
;
; ”ã­ªæ¨ï ¤«ï ¢ë¢®¤  § £à㦥­­®© ¨­äë
;
 
showcfg:
push eax
push ebx
push ecx
push edx
push edi
 
 
xor edx, edx ; áç¥â稪
 
sc_loop:
 
cmp edx, TABLE_SIZE
jnb sc_end
 
;
; ‘ª®¯¨à®¢ âì ¢ ¡ãä¥à ¨¬ï ¨ §­ ç¥­¨¥ ¯¥à¥¬¥­­®©
;
mov eax, VNAME_LEN
imul eax, edx
lea eax, [nvtable + eax]
 
mov cl, [eax]
cmp cl, byte 0
jz sc_next
 
push eax
call strlen
 
mov ecx, eax
pop eax
 
mov ebx, cfgbuff
 
call strcpy
 
mov [cfgbuff + ecx], ':'
 
lea ebx, [cfgbuff + ecx + 1]
 
mov eax, VAR_LEN
imul eax, edx
lea eax, [vtable + eax]
 
push eax
call strlen
 
mov ecx, eax
pop eax
 
call strcpy
 
mov [ebx + ecx], byte 0
 
mov eax, cfgbuff
xor ebx, ebx
call writemsg
 
sc_next:
 
inc edx
 
jmp sc_loop
 
 
 
sc_end:
pop edi
pop edx
pop ecx
pop ebx
pop eax
 
ret
 
/programs/network_old/icq/trunk/parser_data.inc
0,0 → 1,100
;
; „ ­­ë¥ ¤«ï parser.inc
;
;
 
 
 
 
 
;
; ¨¬ï ä ©« , ª®â®àë© ­ã¦­® ¯ àá¨âì
;
fname db '/sys/ki.cfg',0
 
;
; â ¡«¨æë §­ ç¥­¨©
;
; +----+-------------+-----------------+
; | in | Variable | Variable |
; | de | name | string |
; | x | | |
; | | | |
; +----+-------------+-----------------+
; | | | |
; | | | |
; | 1 | UIN | 'XXXXX..XX' |
; | | | |
; +----+-------------+-----------------+
; | | |
;
; § £à㧪  int ¯®ª  ­¥ ॠ«¨§®¢ ­ 
;
; +----+-------------+-----------------+
; | in | Variable | Variable |
; | de | name | int |
; | x | | |
; | | | |
; +----+-------------+-----------------+
; | | | |
; | | | |
; | 1 | BUFFSIZE | XXXXXXXX |
; | | | |
; +----+-------------+-----------------+
; | | |
;
;
 
 
 
;nvtable db (TABLE_SIZE * NAME_LEN) dup 0
vtable db (TABLE_SIZE * VAR_LEN) dup 0
 
finfo sinfo
 
;
; ‡ ¯®«­¨âì â ¡«¨æã ¨¬¥­ ¯¥à¥¬¥­­ëå
;
nvtable db 'UIN',(VNAME_LEN - 3) dup 0
db 'PASS',(VNAME_LEN - 4) dup 0
db 'ICQIP',(VNAME_LEN - 5) dup 0
db ((TABLE_SIZE - 3) * VNAME_LEN) dup 0
 
;
; ¤«ï ¨­¨æ¨ «¨§ æ¨¨ â ¡«¨æ
;
;
;
;name1 db 'UIN',(VNAME_LEN - 3) dup 0
;name2 db 'PASS',(VNAME_LEN - 4) dup 0
;name3 db 'ICQIP',(VNAME_LEN - 5) dup 0
 
 
;
; ãä¥à ¤«ï ¢¢®¤ /¢ë¢®¤ 
;
iobuff db IOBUFF_SIZE dup 0
;
; ‘¬¥é¥­¨¥ ¢ ä ©«¥
;
shift dd 0
 
;
; ¥à¥¬¥­­ë¥ ¤«ï åà ­¥­¨ï ­®¬¥à®¢
; ᨬ¢®«®¢ ­ ç «  ¨¬¥­¨ ¯¥à¥¬¥­­®©
; ª®­æ , à ¢­®, ª®­æ  §­ ç¥­¨ï
stnpos dd 0
ednpos dd 0
eqpos dd 0
edvpos dd 0
;
;®¬¥à áâப¨ ¤«ï ®¯à¥¤¥«¥­¨ï ®è¨¡®ç­ëå
;
strnum dd 0
 
;
; ãä¥à ¤«ï ¢ë¢®¤  § £à㦥­­®£® ª®­ä¨£ 
;
cfgbuff db (VAR_LEN + VNAME_LEN + 8) dup 0
cfgbuff.len = $ - cfgbuff
 
/programs/network_old/icq/trunk/proc32.inc
0,0 → 1,270
 
; 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
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 def \\{ match . type,def> \\\{ deflocal@proc .,label,<type \\\} \\}
struc db [val] \\{ \common deflocal@proc .,db,val \\}
struc du [val] \\{ \common deflocal@proc .,du,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,du,dw,dp,dd,dt,dq
restruc rb,rw,rp,rd,rt,rq
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
match =label,def \{ ..tmp equ \}
match tmp,..tmp \{ ..var def val \}
match ,..tmp \{ label ..var 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 }
/programs/network_old/icq/trunk/ssi.inc
0,0 → 1,413
;
;
; Ïîääåðæêà êîíòàêò ëèñòà íà ñåðâåðå
;
;
 
;
; Çàïîëíÿåò òàáëèöó ñ UIN
; è îïöèîíàëüíî òàáëèöû ñ èìåíåì è äîï. èíôîé
;
 
 
; Èç comp.inc äëÿ îòëàäêè
;
;
; Ìàññèâ ñ UIN
;
;UIN_LEN = 11 ; Äëèíà
;UINS = 15 ; Êîëè÷åñòâî
;
;uins db UIN_LEN*UINS dup 0
;
; ìàññèâ ñî ñòàòóñàìè
;
;stats dd UINS dup -1
;
; Ìàññèâ ñ èìåíàìè
;
;NAME_LEN = 30
 
;names db NAME_LEN*UINS dup 0
 
 
;
; Äîñòàåò èç item UIN
; eax <- óêàçàòåëü íà item
; Ïðîïóñêàåò ãðóïïû
;
ssi_get_uin:
push eax
push ebx
push ecx
push edx
 
;
; Ïðîâåðÿåì ItemID
;
xor ebx, ebx
mov bl, [eax + 1] ; Length of the item name
mov bh, [eax] ;
 
 
;push ebx
;mov ebx, 128
;call print_mem
 
;pop ebx
 
 
;; FIXIT Ðàçóìíåå ïðîâåðÿòü ôëàãè
;; Åñëè äëèíà ñòðîêè = 0
;; ïðîïóñêàåì item
;cmp ebx, 0
;jz ssi_get_end
 
;;
;;data_debug 'Item name len', ebx
 
;;+ñìåùåíèå äî ItemID
 
;;xor ecx, ecx
;;mov ch, [eax + ebx + 4]
;;mov cl, [eax + ebx + 5] ; Item ID#
 
;;cmp ecx, 0
;;jz ssi_get_end
 
;
; Ïðîâåðÿåì ôëàãè, îáðàáàòûâàåì òîëüêî çàïèñè UIN
;
xor ecx, ecx
mov ch, [eax + ebx + 6]
mov cl, [eax + ebx + 7]
 
cmp ecx, 0 ; 0x0000 Buddy record (name: uin for ICQ and screenname for AIM)
jz ssi_uin
 
; debug
;
 
lea eax, [eax + ebx + 6]
mov ebx, 2
call print_mem
 
 
jmp ssi_get_end
 
 
ssi_uin:
;
; Êîïèðóåì UIN â òàáëèöó
;
mov ecx, ebx ; Äëèíà ñòðîêè
lea eax, [eax + 2]
 
mov edx, [uin_ind]
cmp edx, UINS
jnb ssi_get_end ;Íåò ñâîáîäíîãî ìåñòà â òàáëèöå UIN
 
imul edx, UIN_LEN
mov ebx, uins
lea ebx, [ebx + edx]
 
call strcpy
 
inc [uin_ind]
 
;debug
;mov eax, ebx
;xor ebx, ebx
;call writemsg
 
 
;
ssi_get_end:
pop edx
pop ecx
pop ebx
pop eax
ret
 
 
;
; eax <- óêàçàòåëü íà item
; âîçâðàùàåò â eax óêàçàòåëü íà ñëåäóþùèé item
;
;
 
ssi_next_item:
 
push ebx
push ecx
 
xor ebx, ebx
mov bl, [eax + 1] ; äëèíà UIN
mov bh, [eax] ;
 
xor ecx, ecx
mov cl, [eax + ebx + 9] ; Äëèíà äîïîëíèòåëüíûõ äàííûõ
mov ch, [eax + ebx + 8] ;
 
add ebx, ecx
add ebx, 10 ;+Äëèíà çàãîëîâêà
 
lea eax, [eax + ebx]
 
 
pop ecx
pop ebx
ret
 
 
;
; eax <- óêàçàòåëü íà tlv
; âîçâðàùàåò â eax óêàçàòåëü íà ñëåä tlv
;
macro get_next_tlv {
push ebx
 
xor ebx, ebx
 
mov bl, [eax + 3]
mov bh, [eax + 2]
 
; + ðàçìåð çàãîëîâêà
lea ebx, [ebx + 4]
 
lea eax, [eax + ebx]
 
pop ebx
}
 
 
 
;
; Èùåò â additional èìÿ è äð. ñâåäåíèÿ
; eax <- óêàçàòåëü íà item
;
ssi_get_add:
push eax
push ebx
push ecx
push edx
push esi
 
 
;mov ebx, 128
;call print_mem
 
 
 
 
xor ebx, ebx
mov bl, [eax + 1] ; Length of the item name
mov bh, [eax] ;
 
;;cmp ebx, 0 ; Åñëè äëèíà èìåíè = 0
;;jz ssi_all_tlv ; Íåò ñìûñëà îáðàáàòûâàòü
 
 
;;+ñìåùåíèå äî ItemID
 
;;xor ecx, ecx
;;mov ch, [eax + ebx + 4]
;;mov cl, [eax + ebx + 5] ; Item ID#
;
;;cmp ecx, 0 ; Ãðóïïû ïîêà íå îáðàáàòûâàþòñÿ
;;jz ssi_all_tlv ;
;
; Ïðîâåðÿåì ôëàãè, îáðàáàòûâàåì òîëüêî çàïèñè UIN
;
xor ecx, ecx
mov ch, [eax + ebx + 6]
mov cl, [eax + ebx + 7]
cmp ecx, 0 ; 0x0000 Buddy record (name: uin for ICQ and screenname for AIM)
jnz ssi_all_tlv
 
xor edx, edx
mov dl, [eax + ebx + 9] ;
mov dh, [eax + ebx + 8] ; Length of the additional data
 
lea eax, [eax + ebx + 10] ; eax óêàçàòåëü íà ïåðâûé tlv
 
 
;FIXME : Iservd íå ïðèñûëàåò additional - ïîêà íå ìîãó îòëàäèòü
;debug
;push ebx
;mov ebx, edx
 
;data_debug 'length additional data', ebx
 
;call print_mem
;pop ebx
;
 
 
 
xor esi, esi
 
ssi_tlv_process:
cmp esi, edx ;
jnb ssi_all_tlv ; additional çàêîí÷èëîñü
 
xor ecx, ecx
mov cl, [eax + 3] ;
mov ch, [eax + 2] ; TLV.Length
 
xor ebx, ebx
mov bl, [eax + 1] ; TLV.Type
mov bh, [eax] ;
 
cmp bx, 0x0131 ;Èìÿ ïîëüçîâàòåëÿ
jz ssi_name
 
cmp bx, 0x0066 ;Îæèäàåì àâòîðèçàöèè
jz ssi_auth_wait
 
jmp ssi_next_tlv
 
 
ssi_auth_wait:
;
;
;
jmp ssi_next_tlv
 
 
ssi_name:
 
;
; Ñêîïèðîâàòü èìÿ â ìàññèâ
;
push eax
push ecx
 
mov ebx, [name_ind]
cmp ebx, UINS
jnb ssi_name_end ;Íåò ìåñòà â òàáëèöå
 
lea eax, [eax + 4] ;Óêàçàòåëü íà ñòðîêó (Ïðèáàâëÿåì ðàçìåð çàãîëîâêà TLV)
 
imul ebx, NAME_LEN
lea ebx, [names + ebx]
 
cmp ecx, NAME_LEN - 1 ; Åñëè èìÿ äëèííåå ïîëÿ â òàáëèöå
jna @f
 
mov ecx, NAME_LEN - 1
 
@@:
call strcpy
 
;; FIXIT
;; Ïåðåêîäèðîâêà èìåíè
;;
;;mov eax, ebx
;;call win2dos
 
;
;debug
;push eax
;push ebx
 
;mov eax, ebx
;xor ebx, ebx
;call writemsg
 
;pop ebx
;pop eax
;
;
inc [name_ind]
 
pop ecx
pop eax
 
 
 
ssi_next_tlv:
lea ecx, [ecx + 4] ; Äëèíà äàííûõ tlv + äëèíà çàãîëîâêà
add esi, ecx
 
get_next_tlv
jmp ssi_tlv_process
 
 
ssi_name_end:
pop ecx
pop eax
 
 
ssi_all_tlv:
 
 
pop esi
pop edx
pop ecx
pop ebx
pop eax
ret
 
;
;
; Îáðàáîòêà êîíòàêò ëèñòà, ïðèøåäøåãî îò ñåðâåðà
;
; â eax <- óêàçàòåëü íà äàííûå â ïàêåòå SNAC(13,06)
ssi_process_data:
push eax
push ebx
push ecx
push edx
 
;
; Ïðîâåðèòü âåðñèþ ïðîòîêîëà
;
xor ebx, ebx
mov bl, [eax]
cmp bl, 0
jnz ssi_bad_prot
;
;â ebx - êîëè÷åñòâî items
mov bl, [eax + 2]
mov bh, [eax + 1]
;
data_debug 'SSI items:', ebx
 
lea eax, [eax + 3] ; Óñòàíîâèòü eax íà ñïèñîê items
 
xor ecx, ecx ; Ñ÷åò÷èê items
 
 
ssi_next_uin:
cmp ecx, ebx
jnb ssi_all_items
 
 
call ssi_get_uin
 
call ssi_get_add
 
call ssi_next_item
 
inc ecx
jmp ssi_next_uin
 
 
 
ssi_bad_prot:
write_debug "ERR: SSI protocol version mismatch"
 
ssi_all_items:
 
pop edx
pop ecx
pop ebx
pop eax
ret
 
 
/programs/network_old/icq/trunk/ssi_data.inc
0,0 → 1,5
;
; Èíäåêñ â ìàññèâå UINS
;
uin_ind dd 0
name_ind dd 0
/programs/network_old/icq/trunk/st_red.bmp
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/programs/network_old/icq/trunk/struct.inc
0,0 → 1,180
 
; Macroinstructions for defining data structures
 
macro struct name
{ fields@struct equ name
match child parent, name \{ fields@struct equ child,fields@\#parent \}
sub@struct equ
struc db [val] \{ \common fields@struct equ fields@struct,.,db,<val> \}
struc dw [val] \{ \common fields@struct equ fields@struct,.,dw,<val> \}
struc du [val] \{ \common fields@struct equ fields@struct,.,du,<val> \}
struc dd [val] \{ \common fields@struct equ fields@struct,.,dd,<val> \}
struc dp [val] \{ \common fields@struct equ fields@struct,.,dp,<val> \}
struc dq [val] \{ \common fields@struct equ fields@struct,.,dq,<val> \}
struc dt [val] \{ \common fields@struct equ fields@struct,.,dt,<val> \}
struc rb count \{ fields@struct equ fields@struct,.,db,count dup (?) \}
struc rw count \{ fields@struct equ fields@struct,.,dw,count dup (?) \}
struc rd count \{ fields@struct equ fields@struct,.,dd,count dup (?) \}
struc rp count \{ fields@struct equ fields@struct,.,dp,count dup (?) \}
struc rq count \{ fields@struct equ fields@struct,.,dq,count dup (?) \}
struc rt count \{ fields@struct equ fields@struct,.,dt,count dup (?) \}
macro db [val] \{ \common \local anonymous
fields@struct equ fields@struct,anonymous,db,<val> \}
macro dw [val] \{ \common \local anonymous
fields@struct equ fields@struct,anonymous,dw,<val> \}
macro du [val] \{ \common \local anonymous
fields@struct equ fields@struct,anonymous,du,<val> \}
macro dd [val] \{ \common \local anonymous
fields@struct equ fields@struct,anonymous,dd,<val> \}
macro dp [val] \{ \common \local anonymous
fields@struct equ fields@struct,anonymous,dp,<val> \}
macro dq [val] \{ \common \local anonymous
fields@struct equ fields@struct,anonymous,dq,<val> \}
macro dt [val] \{ \common \local anonymous
fields@struct equ fields@struct,anonymous,dt,<val> \}
macro rb count \{ \local anonymous
fields@struct equ fields@struct,anonymous,db,count dup (?) \}
macro rw count \{ \local anonymous
fields@struct equ fields@struct,anonymous,dw,count dup (?) \}
macro rd count \{ \local anonymous
fields@struct equ fields@struct,anonymous,dd,count dup (?) \}
macro rp count \{ \local anonymous
fields@struct equ fields@struct,anonymous,dp,count dup (?) \}
macro rq count \{ \local anonymous
fields@struct equ fields@struct,anonymous,dq,count dup (?) \}
macro rt count \{ \local anonymous
fields@struct equ fields@struct,anonymous,dt,count dup (?) \}
macro union \{ fields@struct equ fields@struct,,union,<
sub@struct equ union \}
macro struct \{ fields@struct equ fields@struct,,substruct,<
sub@struct equ substruct \}
virtual at 0 }
 
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=,fields,fields@struct \\{ fields@struct equ
make@struct name,fields
fields@\\#name equ fields \\}
end virtual \}
match any, sub@struct \{ fields@struct equ fields@struct> \}
restore sub@struct }
 
macro make@struct name,[field,type,def]
{ common
if $
display 'Error: definition of ',`name,' contains illegal instructions.',0Dh,0Ah
err
end if
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
local list
list equ
forward
if ~ field eq .
name#field type def
sizeof.#name#field = $ - name#field
else
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 \\{
match any, fields@struct \\\{ fields@struct equ fields@struct,.,name,<values> \\\}
match , fields@struct \\\{ label .
forward
match , value \\\\{ field type def \\\\}
match any, value \\\\{ 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,name,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 0
forward
if ~ field eq .
virtual at 0
parent#field type def
sizeof.#parent#field = $ - parent#field
end virtual
if sizeof.#parent#field > $
rb sizeof.#parent#field - $
end if
else if sizeof.#type > $
rb sizeof.#type - $
end if
common
sizeof.#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 define@substruct parent,name,[field,type,def]
{ common
virtual at 0
forward
if ~ field eq .
parent#field type def
sizeof.#parent#field = $ - parent#field
else
rb sizeof.#type
end if
local value
common
sizeof.#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 \} }
/programs/network_old/icq/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm ki.asm ki
@erase lang.inc
@pause
/programs/network_old/icq/trunk/2000.inc
0,0 → 1,160
; constants
FLAP_HEAD_SIZE = 6
SNAC_HEAD_SIZE = 10
 
;AUTH_MESSAGE = 0008h
;USER_ADDED_MESS = 000Ch
;AUTH_REQ_MESS = 0006h
;URL_MESS = 0004h
;WEB_MESS = 000dh
;EMAIL_MESS = 000eh
;MASS_MESS_MASK = 8000h
;MRURL_MESS = 8004h
;NORM_MESS = 0001h
;MRNORM_MESS = 8001h
;CONTACT_MESS = 0013h
;MRCONTACT_MESS = 8013h
;
;
;
;CAP_PRECAP = "\x09\x46\x13"
;CAP_PRERTF = "\x97\xb1\x27"
;CAP_POSCAP = "\x4c\x7f\x11\xd1\x82\x22\x44\x45\x53\x54\x00\x00"
;CAP_POSRTF = "\x24\x3c\x43\x34\xad\x22\xd6\xab\xf7\x3f\x14\x92"
 
;
;Fingerprinting Capabilities
;
;CAP_M2001 = "\x2e\x7a\x64" "\x75" "\xfa\xdf\x4d\xc8\x88\x6f\xea\x35\x95\xfd\xb6\xdf"
;CAP_M2001_2 = "\xa0\xe9\x3f" "\x37" "\x4f\xe9\xd3\x11\xbc\xd2\x00\x04\xac\x96\xdd\x96"
;CAP_M2002 = "\x10\xcf\x40" "\xd1" "\x4f\xe9\xd3\x11\xbc\xd2\x00\x04\xac\x96\xdd\x96"
;CAP_MLITE = "\x56\x3f\xc8" "\x09" "\x0b\x6f\x41\xbd\x9f\x79\x42\x26\x09\xdf\xa2\xf3"
;CAP_SIMICQ = "\x97\xb1\x27" "\x51" "\x24\x3c\x43\x34\xad\x22\xd6\xab\xf7\x3f\x14\x48"
;CAP_MICQ = "mICQ \xa9 R.K. \x00\x00\x00\x00"
;CAP_TRILL_NORM = "\x97\xb1\x27" "\x51" "\x24\x3c\x43\x34\xad\x22\xd6\xab\xf7\x3f\x14\x09"
;CAP_TRILL_CRYPT= "\xf2\xe7\xc7" "\xf4" "\xfe\xad\x4d\xfb\xb2\x35\x36\x79\x8b\xdf\x00\x00"
;CAP_LICQ = "\x09\x49\x13"
 
;
;DC Packet Types
;
;PEER_INIT = 0ffh
;PEER_INITACK = 01h
;PEER_MSG = 02h
;PEER_INIT2 = 03h
;PEER_FILE_INIT = 00h
;PEER_FILE_INIT_ACK = 01h
;PEER_FILE_START = 02h
;PEER_FILE_START_ACK = 03h
;PEER_FILE_STOP = 04h
;PEER_FILE_SPEED = 05h
;PEER_FILE_DATA = 06h
 
 
ICQ_PORT = 5190
;
; FLAP transport
;
FLAP_ID = 02ah
 
struc FLAP_head
{
.bId db FLAP_ID ;id byte
.bCh db ? ;channel
.wSn dw ? ;seq number
.wDs dw ? ;data size
}
;
; Channels ID
;
 
NEW_CONNECTION = 01h
SNAC_DATA = 02h
FLAP_ERROR = 03h
CLOSE_CONNECTION = 04h
KEEP_ALIVE = 05h
 
;
; SNAC
;
struc SNAC_head
{
.wFid dw ?; Family id
.wSid dw ?; subtype id
.wDf dw ?; SNAC flags
.dRi dd ?; SNAC Request id
}
 
;
;
; Familes/SNACs list
;
 
GENERIC_SN = 0001h
LOCATION_SN = 0002h
BUDDY_LIST_SN = 0003h
ICBM_SN = 0004h
PRIVACY_SN = 0009h
BUDDY_ICONS_SN = 0010h
SSI_SN = 0013h
AUTH_REG_SN = 0017h
 
;
; TLV
;
struc TLV_head
{
.wTn dw ?; TLV type number
.wLv dw ?; TLV length value
}
 
;
; userinfo block
;
struc UI_head
{
.bUinLength db 0 ; UIN/screenname length
.bUin db 11 dup 0 ; string
.wWl dw 0 ; Warning level
.dUserClass dd 0
.dCreateTime dd 0
.dSignonTime dd 0
.wIdleTime dw 0
.dCreationTime dd 0
.dUserStatus dd 0
.dIpAddress dd 0
.dOnlineTime dd 0
 
}
 
;
;Roasting array
;
ROASTING_ARRAY db 0F3h, 026h, 081h, 0C4h, 039h, 086h, 0DBh, 092h, 071h, 0A3h, 0B9h, 0E6h, 053h, 07Ah, 095h, 07Ch
 
;
; Status flags
;
;
STATUS_WEBAWARE = 0x0001 ;Status webaware flag
STATUS_SHOWIP = 0x0002 ;Status show ip flag
STATUS_BIRTHDAY = 0x0008 ;User birthday flag
STATUS_WEBFRONT = 0x0020 ;User active webfront flag
STATUS_DCDISABLED = 0x0100 ;Direct connection not supported
STATUS_DCAUTH = 0x1000 ;Direct connection upon authorization
STATUS_DCCONT = 0x2000 ;DC only with contact users
 
;
; Status
;
 
STATUS_ONLINE = 0x0000 ;Status is online
STATUS_AWAY = 0x0001 ;Status is away
STATUS_DND = 0x0002 ;Status is no not disturb (DND)
STATUS_NA = 0x0004 ;Status is not available (N/A)
STATUS_OCCUPIED = 0x0010 ;Status is occupied (BISY)
STATUS_FREE4CHAT = 0x0020 ;Status is free for chat
STATUS_INVISIBLE = 0x0100 ;Status is invisible
 
 
/programs/network_old/icq/trunk
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network_old/icq
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property
/programs/network_old/ftps/trunk/FTPS.ASM
0,0 → 1,1724
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; FTPS
; FTP Server
;
; Compile with FASM for Menuet
;
 
; note: telnet == 23, ftp cmd == 21, data on 20
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 1 ; header version
dd START ; program start
dd I_END ; program image size
dd 0x170000 ; required amount of memory
dd 0x16FFF0 ; esp = 0x16FFF0
dd 0, 0 ; no params, no path
 
include '../../../macros.inc'
; Various states of client connection
USER_NONE equ 0 ; Awaiting a connection
USER_CONNECTED equ 1 ; User just connected, prompt given
USER_USERNAME equ 2 ; User given username
USER_LOGGED_IN equ 3 ; User given password
 
 
 
 
 
START: ; start of execution
; Clear the screen memory
mov eax, ' '
mov edi,text
mov ecx,80*30 /4
cld
rep stosd
 
call draw_window
 
; init the receive buffer pointer
mov [buffptr], buff
 
; Init FTP server state machine
mov [state], USER_NONE
 
; Open the listening socket
call connect
 
still:
; check connection status
mov eax,53
mov ebx,6 ; Get socket status
mov ecx,[CmdSocket]
mcall
 
mov ebx, [CmdSocketStatus]
mov [CmdSocketStatus], eax
 
cmp eax, ebx
je waitev
 
; If the socket closed by remote host, open it again.
cmp eax, 7
je con
 
; If socket closed by Reset, open it again
cmp eax, 11
je con
 
; If a user has just connected, start by outputting welcome msg
cmp eax, 4
jne noc
 
mov esi, loginStr0
mov edx, loginStr0_end - loginStr0
call outputStr
 
mov [state], USER_CONNECTED
jmp noc
 
 
con:
; Need to call disconnect, since a remote close does not fully
; close the socket
call disconnect
mov eax,5
mov ebx,10 ; Delay for 100ms
mcall
call connect
jmp noc
 
noc:
; Display the changed connected status
call draw_window
 
waitev:
mov eax,23 ; wait here for event
mov ebx,1 ; Delay for up to 1s
mcall
 
cmp eax,1 ; redraw request ?
je red
cmp eax,2 ; key in buffer ?
je key
cmp eax,3 ; button in buffer ?
je button
 
; any data from the socket?
 
mov eax, 53
mov ebx, 2 ; Get # of bytes in input queue
mov ecx, [CmdSocket]
mcall
test eax, eax
jz still
 
read_input:
mov eax, 53
mov ebx, 3 ; Get a byte from socket in bl
mov ecx, [CmdSocket]
mcall
 
call ftpRxCmdData ; process incoming ftp command
 
; Keep processing data until there is no more to process
mov eax, 53
mov ebx, 2 ; Get # of bytes in input queue
mov ecx, [CmdSocket]
mcall
cmp eax, 0
jne read_input
 
; Now redraw the text text field.
; Probably not required, since ftp requires no
; console i/o.
; Leave in for now, for debugging.
; (fall through to "red:")
; call draw_text
; jmp still
 
red: ; REDRAW WINDOW
call draw_window
jmp still
 
key: ; KEY
mov eax,2 ; get but ignore
mcall
jmp still
 
button:
mov eax,17
mcall
cmp ah,1
jne still
 
; Exit button pressed, so close socket and quit
mov eax,53
mov ebx,8
mov ecx,[CmdSocket]
mcall
 
; ... terminate program
or eax,-1
mcall
jmp still
 
 
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
draw_window:
pusha
 
mov eax,12
mov ebx,1
mcall
 
xor eax,eax ; DRAW WINDOW
mov ebx,100*65536+491 + 8 +15
mov ecx,100*65536+270 + 20 ; 20 for status bar
mov edx,0x14000000
mov edi,labelt
mcall
 
; draw status bar
mov eax, 13
mov ebx, 4*65536+484 + 8 +15
mov ecx, 270*65536 + 3
mov edx, 0x00557799
mcall
 
 
mov esi,contlen-contt ; display connected status
mov edx, contt
cmp [CmdSocketStatus], 4 ; 4 is connected
je pcon
mov esi,discontlen-discontt
mov edx, discontt
pcon:
 
mov eax,4 ; status text
mov ebx,380*65536+276
mov ecx,0x00ffffff
mcall
 
; Draw the text on the screen, clearing it first
; This can go when we loose debuggin info.
xor eax,eax
mov edi,text+80*30
mov ecx,80*30 /4
cld
rep stosd
 
call draw_text
 
mov eax,12
mov ebx,2
mcall
 
popa
 
ret
 
 
;***************************************************************************
; Function
; draw_text
;
; Description
; Updates the text on the screen. This is part of the debugging code
;
; Inputs
; Character to add in bl
;
;***************************************************************************
draw_text:
 
pusha
 
mov esi,text
mov eax,0
mov ebx,0
newletter:
mov cl,[esi]
cmp cl,[esi+30*80]
jz noletter
yesletter:
mov [esi+30*80],cl
 
; erase character
 
pusha
mov edx, 0 ; bg colour
mov ecx, ebx
add ecx, 26
shl ecx, 16
mov cx, 9
mov ebx, eax
add ebx, 6
shl ebx, 16
mov bx, 6
mov eax, 13
mcall
popa
 
; draw character
 
pusha
mov ecx, 0x00ffffff
push bx
mov ebx,eax
add ebx,6
shl ebx,16
pop bx
add bx,26
mov eax,4
mov edx,esi
mov esi,1
mcall
popa
 
noletter:
 
add esi,1
add eax,6
cmp eax,80*6
jb newletter
mov eax,0
add ebx,10
cmp ebx,24*10
jb newletter
 
popa
ret
 
 
 
;***************************************************************************
; Function
; ftpRxCmdData
;
; Description
; Prcoesses incoming command data, calling a handler for each command.
; Commands are built up in buff before being processed.
;
; Inputs
; Character to add in bl
;
;***************************************************************************
ftpRxCmdData:
; Quit if we are not connected
;( This case shouldn't be necessary, but be safe )
mov al, [state]
cmp al, USER_NONE
je frcd_exit
 
; Store the incoming character
mov esi, [buffptr]
mov [esi], bl
inc esi
mov [buffptr], esi
 
; For debugging, show the data coming in
pusha
call printChar
popa
 
; Do we have an end of line? (LF)
; if not, just exit
cmp bl, 0x0a
jne frcd_exit
 
; OK we have a complete command.
; Process, and send response
 
; There are a number of states involved in ftp,
; to do with logging in.
 
mov al, [state]
cmp al, USER_CONNECTED
jne fs001
 
; This should be the username
 
; TODO validate username
 
; OK, username accepted - ask for password
mov esi, loginStr1
mov edx, loginStr1_end - loginStr1
call outputStr
 
mov [state], USER_USERNAME
 
; init the receive buffer pointer
mov [buffptr], buff
 
jmp frcd_exit
 
fs001:
cmp al, USER_USERNAME
jne fs002
 
; This should be the password
 
; TODO validate password
 
; OK, password accepted - show they are logged in
mov esi, loginStr2
mov edx, loginStr2_end - loginStr2
call outputStr
 
mov [state], USER_LOGGED_IN
 
; init the receive buffer pointer
mov [buffptr], buff
 
jmp frcd_exit
 
fs002:
cmp al, USER_LOGGED_IN
jne fs003
 
; This should be a cmd
call findCmd
mov eax, [cmdPtr]
cmp eax, 0
 
je fs002b
 
call [cmdPtr]
 
fs002a:
; init the receive buffer pointer
mov [buffptr], buff
 
jmp frcd_exit
 
fs002b:
; an unsupported command was entered.
; Tell user that the command is not supported
 
mov esi, unsupStr
mov edx, unsupStr_end - unsupStr
call outputStr
 
jmp fs002a
 
fs003:
frcd_exit:
ret
 
 
 
;***************************************************************************
; Function
; outputStr
;
; Description
; Sends a string over the 'Command' socket
;
; Inputs
; String in esi
; Length in edx
;
;***************************************************************************
outputStr:
push esi
push edx
mov eax,53
mov ebx,7
mov ecx,[CmdSocket]
mcall
pop edx
pop esi
 
cmp eax, 0
je os_exit
 
; The TCP/IP transmit queue is full; Wait a bit, then retry
pusha
mov eax,5
mov ebx,1 ; Delay for up 10ms
mcall
popa
jmp outputStr
os_exit:
ret
 
 
 
;***************************************************************************
; Function
; outputDataStr
;
; Description
; Sends a string over the 'Data' socket
;
; Inputs
; String in esi
; Length in edx
;
;***************************************************************************
outputDataStr:
push esi
push edx
mov eax,53
mov ebx,7
mov ecx,[DataSocket]
mcall
pop edx
pop esi
 
cmp eax, 0
je ods_exit
 
; The TCP/IP transmit queue is full; Wait a bit, then retry
pusha
mov eax,5
mov ebx,1 ; Delay for up 10ms
mcall
popa
jmp outputDataStr
ods_exit:
ret
 
 
 
;***************************************************************************
; Function
; printChar
;
; Description
; Writes a character to the screen; Used to display the data coming
; in from the user. Really only useful for debugging.
;
; Inputs
; Character in bl
;
;***************************************************************************
printChar:
cmp bl,13 ; BEGINNING OF LINE
jne nobol
mov ecx,[pos]
add ecx,1
boll1:
sub ecx,1
mov eax,ecx
xor edx,edx
mov ebx,80
div ebx
cmp edx,0
jne boll1
mov [pos],ecx
jmp newdata
nobol:
 
cmp bl,10 ; LINE DOWN
jne nolf
addx1:
add [pos],dword 1
mov eax,[pos]
xor edx,edx
mov ecx,80
div ecx
cmp edx,0
jnz addx1
mov eax,[pos]
jmp cm1
nolf:
 
cmp bl,8 ; BACKSPACE
jne nobasp
mov eax,[pos]
dec eax
mov [pos],eax
mov [eax+text],byte 32
mov [eax+text+60*80],byte 0
jmp newdata
nobasp:
 
cmp bl,15 ; CHARACTER
jbe newdata
putcha:
mov eax,[pos]
mov [eax+text],bl
mov eax,[pos]
add eax,1
cm1:
mov ebx,[scroll+4]
imul ebx,80
cmp eax,ebx
jb noeaxz
mov esi,text+80
mov edi,text
mov ecx,ebx
cld
rep movsb
mov eax,ebx
sub eax,80
noeaxz:
mov [pos],eax
newdata:
ret
 
 
;***************************************************************************
; Function
; disconnect
;
; Description
; Closes the command socket
;
; Inputs
; None
;
;***************************************************************************
disconnect:
mov eax, 53 ; Stack Interface
mov ebx,8 ; Close TCP socket
mov ecx,[CmdSocket]
mcall
ret
 
 
 
;***************************************************************************
; Function
; disconnectData
;
; Description
; Closes the data socket
;
; Inputs
; None
;
;***************************************************************************
disconnectData:
; This delay would be better done by allowing the socket code
; to wait for all data to pass through the stack before closing
pusha
mov eax,5
mov ebx,10 ; Delay for 100ms
mcall
popa
 
mov eax, 53 ; Stack Interface
mov ebx,8 ; Close TCP socket
mov ecx,[DataSocket]
mcall
ret
 
 
 
 
;***************************************************************************
; Function
; connect
;
; Description
; Opens the command socket
;
; Inputs
; None
;
;***************************************************************************
connect:
pusha
 
mov eax, 53 ; Stack Interface
mov ebx, 5 ; Open TCP socket
mov esi, 0 ; No remote IP address
mov edx, 0 ; No remote port
mov ecx, 21 ; ftp command port id
mov edi, 0 ; passive open
mcall
mov [CmdSocket], eax
 
popa
 
ret
 
 
 
;***************************************************************************
; Function
; connectData
;
; Description
; Opens the data socket
;
; Inputs
; None
;
;***************************************************************************
connectData:
pusha
 
mov eax, 53 ; Stack Interface
mov ebx, 5 ; Open TCP socket
mov esi, [DataIP] ; remote IP address
mov edx, [DataPort] ; remote port
mov ecx, 0 ; ftp data port id
mov edi, 1 ; active open
mcall
mov [DataSocket], eax
 
popa
 
ret
 
 
 
 
;***************************************************************************
; Function
; findCmd
;
; Description
; Scans the command string for a valid command. The command string
; is in the global variable buff.
;
; Returns result in cmdPtr. This will be zero if none found
;
; Inputs
; None
;
;***************************************************************************
findCmd:
; Setup to return 'none' in cmdPtr, if we find no cmd
mov eax, 0
mov [cmdPtr], eax
cld
mov esi, buff
mov edi, CMDList
 
fc000:
cmp [edi], byte 0 ; Are we at the end of the CMDList?
je fc_exit
 
fc000a:
cmpsb
 
je fc_nextbyte
 
; Command is different - move to the next entry in cmd table
mov esi, buff
 
fc001:
; skip to the next command in the list
cmp [edi], byte 0
je fc002
inc edi
jmp fc001
fc002:
add edi, 5
jmp fc000
 
fc_nextbyte:
; Have we reached the end of the CMD text?
cmp [edi], byte 0
je fc_got ; Yes - so we have a match
jmp fc000a ; No - loop back
 
fc_got:
; Copy the function pointer for the selected command
inc edi
mov eax, [edi]
mov [cmdPtr], eax
 
fc_exit:
ret
 
 
 
;***************************************************************************
; Function
; decStr2Byte
;
; Description
; Converts the decimal string pointed to by esi to a byte
;
; Inputs
; string ptr in esi
;
; Outputs
; esi points to next character not in string
; eax holds result ( 0..255)
;
;***************************************************************************
decStr2Byte:
xor eax, eax
xor ebx, ebx
mov ecx, 3
 
dsb001:
mov bl, [esi]
 
cmp bl, '0'
jb dsb_exit
cmp bl, '9'
ja dsb_exit
 
imul eax, 10
add eax, ebx
sub eax, '0'
inc esi
loop dsb001
 
dsb_exit:
ret
 
 
 
;***************************************************************************
; Function
; parsePortStr
;
; Description
; Converts the parameters of the PORT command, and stores them in the
; appropriate variables.
;
; Inputs
; None ( string in global variable buff )
;
; Outputs
; None
;
;***************************************************************************
parsePortStr:
; skip past the PORT text to get the the parameters. The command format
; is
; PORT i,i,i,i,p,p,0x0d,0x0a
; where i and p are decimal byte values, high byte first.
xor eax, eax
mov [DataIP], eax
mov [DataPort], eax
mov esi, buff + 4 ; Start at first space character
 
pps001:
cmp [esi], byte ' ' ; Look for first non space character
jne pps002
inc esi
jmp pps001
 
pps002:
call decStr2Byte
add [DataIP], eax
ror dword [DataIP], 8
inc esi
call decStr2Byte
add [DataIP], eax
ror dword [DataIP], 8
inc esi
call decStr2Byte
add [DataIP], eax
ror dword [DataIP], 8
inc esi
call decStr2Byte
add [DataIP], eax
ror dword [DataIP], 8
inc esi
call decStr2Byte
add [DataPort], eax
shl [DataPort], 8
inc esi
call decStr2Byte
add [DataPort], eax
 
ret
 
 
 
;***************************************************************************
; Function
; sendDir
;
; Description
; Transmits the directory listing over the data connection.
; The data connection is already open.
;
; Inputs
; None
;
; Outputs
; None
;
;***************************************************************************
sendDir:
mov eax, text+0x4000
mov [fsize], eax
mov ebx, dirinfoblock
and dword [ebx+4], 0 ; start from zero block
sd001:
; Read the next DirBlocksPerCall (=16) blocks
mov eax, 70
mcall
; Did we read anything?
test eax, eax
jz @f
cmp eax, 6
jnz sd_exit
@@:
test ebx, ebx
jz sd_exit
; Parse these blocks. There could be up to 16 files specified
mov esi, text + 0x1300 + 0x20
sd002:
dec ebx
js sd004
push ebx
; OK, lets parse the entry. Ignore volume entries
test byte [esi], 8
jnz sd003
; Valid file or directory. Start to compose the string we will send
mov edi, dirStr
; If we have been called as a result of an NLST command, we only display
; the filename
cmp [buff], byte 'N'
jz sd006
 
mov [edi], byte '-'
test byte [esi], 10h
jz @f
mov [edi], byte 'd'
@@:
; Ok, now copy across the directory listing text that will be constant
; ( I dont bother looking at the read only or archive bits )
 
mov ebx, tmplStr
@@:
inc edi
mov al, [ebx]
test al, al
jz @f
mov [edi], al
inc ebx
jmp @b
@@:
; point to the last character of the string;
; We will write the file size here, backwards
push edi ; Remember where the string ends
 
dec edi
; eax holds the number
mov eax, [esi+32]
mov ebx, 10
@@:
xor edx, edx
div ebx
add dl, '0'
mov [edi], dl
dec edi
test eax, eax
jnz @b
 
pop edi
; now create the time & date fields
;timeStr: db ' Jan 1 2000 ',0
mov al, ' '
stosb
movzx eax, byte [esi+28+1]
mov eax, dword [months + (eax-1)*4]
stosd
mov al, byte [esi+28]
aam
test ah, ah
jz sd005a
xchg al, ah
add ax, '00'
jmp sd005b
sd005a:
add al, '0'
mov ah, ' '
sd005b:
stosw
mov al, ' '
mov ecx, 6
rep stosb
push edi
movzx eax, word [esi+28+2]
@@:
xor edx, edx
div ebx
add dl, '0'
mov [edi], dl
dec edi
test eax, eax
jnz @b
pop edi
inc edi
mov al, ' '
stosb
sd006:
; ** End of copying
 
; now copy the filename across
lea ebx, [esi+40]
@@:
mov al, [ebx]
inc ebx
test al, al
jz @f
stosb
jmp @b
@@:
terminate:
; Now terminate the line by putting CRLF sequence in
mov al, 0x0D
stosb
mov al, 0x0A
stosb
; Send the completed line to the user over data socket
push esi
push edi
mov esi, dirStr
mov ecx, edi
sub ecx, esi
mov edi, [fsize]
cld
rep movsb
mov [fsize], edi
cmp edi, text+0x4400
jb @f
mov esi, text+0x4000
mov edx, [fsize]
sub edx, esi
mov [fsize], esi
call outputDataStr
 
@@:
pop edi
pop esi
 
sd003: ; Move to next entry in the block
pop ebx
add esi, 304
jmp sd002
sd004:
mov ebx, dirinfoblock
add dword [ebx+4], DirBlocksPerCall
jmp sd001
 
sd_exit:
mov esi, text+0x4000
mov edx, [fsize]
sub edx, esi
call outputDataStr
ret
 
 
 
 
 
;***************************************************************************
; Function
; setupFilePath
;
; Description
; Copies the file name from the input request string into the
; file descriptor
;
; Inputs
; None
;
; Outputs
; None
;
;***************************************************************************
setupFilePath:
mov esi, buff + 4 ; Point to (1 before) first character of file
 
; Skip any trailing spaces or / character
sfp001:
inc esi
cmp [esi], byte ' '
je sfp001
cmp [esi], byte '/'
je sfp001
 
; esi points to start of filename.
cld
push esi
 
; Copy across the directory path '/'
; into the fileinfoblock
mov esi, dirpath
mov edi, filename
sfp003:
movsb
cmp [esi], byte 0
jne sfp003
mov al, '/'
stosb
pop esi
 
; Copy across the filename
sfp002:
movsb
cmp [esi], byte 0x0d
jne sfp002
mov [edi], byte 0
ret
 
 
 
 
;***************************************************************************
; Function
; sendFile
;
; Description
; Transmits the requested file over the open data socket
; The file to send is named in the buff string
;
; Inputs
; None
;
; Outputs
; None
;
;***************************************************************************
sendFile:
call setupFilePath
 
; init fileblock descriptor, for file read
mov ebx, fileinfoblock
and dword [ebx], 0 ; read cmd
and dword [ebx+4], 0 ; first block
mov dword [ebx+12], 0x400 ; block size
 
sf002a:
; now read the file..
mov eax,70
mcall
test eax, eax
jz @f
cmp eax, 6
jnz sf_exit
@@:
push eax
mov esi, text + 0x1300
mov edx, ebx
call outputDataStr
pop eax
test eax, eax
jnz sf_exit
; wait a bit
mov eax, 5
mov ebx, 1
mcall
mov ebx, fileinfoblock
add dword [ebx+4], edx
jmp sf002a
 
sf_exit:
ret
 
 
;***************************************************************************
; Function
; getFile
;
; Description
; Receives the specified file over the open data socket
; The file to receive is named in the buff string
;
; Inputs
; None
;
; Outputs
; None
;
;***************************************************************************
getFile:
call setupFilePath
 
; init fileblock descriptor, for file write
xor eax, eax
mov [fsize], eax ; Start filelength at 0
mov [fileinfoblock+4], eax ; set to 0
inc eax
inc eax
mov [fileinfoblock], eax ; write cmd
 
; Read data from the socket until the socket closes
; loop
; loop
; read byte from socket
; write byte to file buffer
; until no more bytes in socket
; sleep 100ms
; until socket no longer connected
; write file to ram
 
gf000:
mov eax, 53
mov ebx, 2 ; Get # of bytes in input queue
mov ecx, [DataSocket]
mcall
test eax, eax
je gf_sleep
 
mov eax, 53
mov ebx, 11 ; Get bytes from socket
mov ecx, [DataSocket]
mov edx, text + 0x1300
add edx, dword [fsize]
xor esi, esi
mcall ; returned data len in eax
add dword [fsize], eax
 
jmp gf000
 
gf_sleep:
; Check to see if socket closed...
mov eax,53
mov ebx,6 ; Get socket status
mov ecx,[DataSocket]
mcall
 
cmp eax, 7
jne gf001 ; still open, so just sleep a bit
 
; Finished, so write the file
mov eax, [fsize]
mov [fileinfoblock+12], eax
mov eax,70
mov ebx,fileinfoblock
mcall
 
ret ; Finished
 
gf001:
; wait a bit
mov eax,5
mov ebx,1 ; Delay for up 10ms
mcall
jmp gf000 ; try for more data
 
 
 
 
 
;***************************************************************************
; COMMAND HANDLERS FOLLOW
;
; These handlers implement the functionality of each supported FTP Command
;
;***************************************************************************
 
cmdPWD:
cld
mov edi, text+0x1300
 
mov esi, curdir_1
mov ecx, curdir_2-curdir_1
rep movsb
 
mov esi, [curdirptr]
cmp [esi], byte 0
jne cpwd_000
mov al, '/'
stosb
jmp cpwd_001
 
cpwd_000:
movsb
cmp [esi], byte 0
jne cpwd_000
 
cpwd_001:
mov esi, curdir_2
mov ecx, curdir_end-curdir_2
rep movsb
 
; OK, show the directory name text
mov esi, text+0x1300
mov edx, edi
sub edx, esi
call outputStr
 
ret
 
 
cmdCWD:
lea esi, [buff+4]
mov edi, [curdirptr]
mov ecx, -1
xor eax, eax
repne scasb
dec edi
cmp [esi], word '..'
je ccwd_002
test [esi], byte 0xE0
je ccwd_000
push edi
mov al, '/'
stosb
@@:
movsb
cmp [esi], byte 0xD
jne @b
xor al, al
stosb
 
mov eax, 70
mov ebx, dirinfoblock
and dword [ebx+4], 0
mcall
pop edi
test eax, eax
je @f
cmp eax, 6
jne ccwd_000
@@:
test ebx, ebx
je ccwd_000
mov esi, text + 0x1300 + 0x20
 
mov al, byte [esi]
and al, 0x18
cmp al, 0x10
jne ccwd_000
 
ccwd_ok:
; OK, show the directory name text
mov esi, chdir
mov edx, chdir_end - chdir
jmp ccwd_001
 
ccwd_002:
dec edi
cmp byte [edi], '/'
je ccwd_003
cmp edi, [curdirptr]
ja ccwd_002
jmp ccwd_ok
ccwd_003:
mov byte [edi], 0
jmp ccwd_ok
 
ccwd_000:
mov byte [edi], 0
; Tell user there is no such directory
mov esi, noFileStr
mov edx, noFileStr_end - noFileStr
 
ccwd_001:
call outputStr
 
ret
 
 
cmdQUIT:
; The remote end will do the close; We just
; say goodbye.
mov esi, byeStr
mov edx, byeStr_end - byeStr
call outputStr
ret
 
 
cmdABOR:
 
; Close port
call disconnectData
 
mov esi, abortStr
mov edx, abortStr_end - abortStr
call outputStr
 
ret
 
cmdPORT:
; TODO
; Copy the IP and port values to DataIP and DataPort
 
call parsePortStr
 
; Indicate the command was accepted
mov esi, cmdOKStr
mov edx, cmdOKStr_end - cmdOKStr
call outputStr
ret
 
cmdnoop:
; Indicate the command was accepted
mov esi, cmdOKStr
mov edx, cmdOKStr_end - cmdOKStr
call outputStr
ret
 
 
cmdTYPE:
; TODO
; Note the type field selected - reject if needed.
 
; Indicate the command was accepted
mov esi, cmdOKStr
mov edx, cmdOKStr_end - cmdOKStr
call outputStr
ret
 
cmdsyst:
; Indicate the system type
mov esi, systStr
mov edx, systStr_end - systStr
call outputStr
ret
 
 
cmdDELE:
call setupFilePath
 
mov ebx, fileinfoblock
mov dword [ebx], 8
and dword [ebx+4], 0
push dword [ebx+12]
push dword [ebx+16]
and dword [ebx+12], 0
and dword [ebx+16], 0
mov eax, 70
mcall
mov ebx, fileinfoblock
pop dword [ebx+16]
pop dword [ebx+12]
 
test eax, eax
jne cmdDele_err
 
mov esi, delokStr
mov edx, delokStr_end - delokStr
call outputStr
 
jmp cmdDele_exit
 
cmdDele_err:
mov esi, noFileStr
mov edx, noFileStr_end - noFileStr
call outputStr
 
 
cmdDele_exit:
ret
 
 
cmdNLST:
cmdLIST:
; Indicate the command was accepted
mov esi, startStr
mov edx, startStr_end - startStr
call outputStr
 
call connectData
 
; Wait for socket to establish
 
cl001:
; wait a bit
mov eax,5
mov ebx,10 ; Delay for up 100ms
mcall
 
; check connection status
mov eax,53
mov ebx,6 ; Get socket status
mov ecx,[DataSocket]
mcall
 
cmp eax, 4
jne cl001
 
; send directory listing
call sendDir
 
; Close port
call disconnectData
 
mov esi, endStr
mov edx, endStr_end - endStr
call outputStr
ret
 
cmdRETR:
; Indicate the command was accepted
mov esi, startStr
mov edx, startStr_end - startStr
call outputStr
 
call connectData
 
; Wait for socket to establish
 
cr001:
; wait a bit
mov eax,5
mov ebx,10 ; Delay for up 100ms
mcall
 
; check connection status
mov eax,53
mov ebx,6 ; Get socket status
mov ecx,[DataSocket]
mcall
 
cmp eax, 4
jne cr001
 
; send data to remote user
call sendFile
 
; Close port
call disconnectData
 
mov esi, endStr
mov edx, endStr_end - endStr
call outputStr
 
 
ret
 
 
cmdSTOR:
; Indicate the command was accepted
mov esi, storStr
mov edx, storStr_end - storStr
call outputStr
 
call connectData
 
; Wait for socket to establish
 
cs001:
; wait a bit
mov eax,5
mov ebx,10 ; Delay for up 100ms
mcall
 
; check connection status
mov eax,53
mov ebx,6 ; Get socket status
mov ecx,[DataSocket]
mcall
 
cmp eax, 4
je @f
cmp eax, 7
jne cs001
@@:
 
; get data file from remote user
call getFile
 
mov esi, endStr
mov edx, endStr_end - endStr
call outputStr
 
; Close port
call disconnectData
 
ret
 
 
 
; DATA AREA
 
; This is the list of supported commands, and the function to call
; The list end with a NULL.
CMDList:
db 'pwd',0
dd cmdPWD
 
db 'PWD',0
dd cmdPWD
 
db 'XPWD',0
dd cmdPWD
 
db 'xpwd',0
dd cmdPWD
 
db 'QUIT',0
dd cmdQUIT
 
db 'quit',0
dd cmdQUIT
 
db 'PORT',0
dd cmdPORT
 
db 'port',0
dd cmdPORT
 
db 'LIST',0
dd cmdLIST
 
db 'list',0
dd cmdLIST
 
db 'NLST',0
dd cmdNLST
 
db 'nlst',0
dd cmdNLST
 
db 'TYPE',0
dd cmdTYPE
 
db 'type',0
dd cmdTYPE
 
db 'syst',0
dd cmdsyst
 
db 'noop',0
dd cmdnoop
 
db 'CWD',0
dd cmdCWD
 
db 'cwd',0
dd cmdCWD
 
db 'RETR',0
dd cmdRETR
 
db 'retr',0
dd cmdRETR
 
db 'DELE',0
dd cmdDELE
 
db 'dele',0
dd cmdDELE
 
db 'stor',0
dd cmdSTOR
 
db 'STOR',0
dd cmdSTOR
 
db 'ABOR',0
dd cmdABOR
 
db 'abor',0
dd cmdABOR
 
db 0xff,0xf4,0xff,0xf2,'ABOR',0
dd cmdABOR
 
db 0
 
 
cmdPtr dd 0
CmdSocket dd 0x0
CmdSocketStatus dd 0x0
DataSocket dd 0x0
DataSocketStatus dd 0x0
DataPort dd 0x00
DataIP dd 0x00
pos dd 80 * 1
scroll dd 1
dd 24
 
labelt db 'FTP Server v0.1',0
contt db 'Connected'
contlen:
discontt db 'Disconnected'
discontlen:
 
cmdOKStr: db '200 Command OK',0x0d,0x0a
cmdOKStr_end:
 
loginStr0: db '220- Menuet FTP Server v0.1',0x0d,0x0a
db '220 Username and Password required',0x0d,0x0a
loginStr0_end:
 
loginStr1: db '331 Password now required',0x0d,0x0a
loginStr1_end:
 
loginStr2: db '230 You are now logged in.',0x0d,0x0a
loginStr2_end:
 
byeStr: db '221 Bye bye!',0x0d,0x0a
byeStr_end:
 
systStr: db '215 UNIX system type',0x0d,0x0a
systStr_end:
 
curdir_1: db '257 "'
curdir_2: db '"',0x0d,0x0a
curdir_end:
 
chdir: db '250 CWD command successful',0x0d,0x0a
chdir_end:
 
unsupStr: db '500 Unsupported command',0x0d,0x0a
unsupStr_end:
 
noFileStr: db '550 No such file',0x0d,0x0a
noFileStr_end:
 
delokStr: db '250 DELE command successful',0x0d,0x0a
delokStr_end:
 
startStr: db '150 Here it comes...',0x0d,0x0a
startStr_end:
 
storStr: db '150 Connecting for STOR',0x0d,0x0a
storStr_end:
 
endStr: db '226 Transfer OK, Closing connection',0x0d,0x0a
endStr_end:
 
abortStr: db '225 Abort successful',0x0d,0x0a
abortStr_end:
 
; This is the buffer used for building up a directory listing line
dirStr: times 128 db 0
 
; This is template string used in building up a directory listing line
tmplStr: db 'rw-rw-rw- 1 0 0 ',0
 
months:
dd 'Jan ','Feb ','Mar ','Apr ','May ','Jun '
dd 'Jul ','Aug ','Sep ','Oct ','Nov ','Dec '
 
fileinfoblock:
dd 0x00
dd 0x00
dd 0x00
dd 0x200 ; bytes to read
dd text + 0x1300 ; data area
filename: times 256 db 0
 
; The following lines define data for reading a directory block
DirBlocksPerCall = 16
dirinfoblock:
dd 1
dd 0x00
dd 0x00
dd DirBlocksPerCall
dd text + 0x1300 ; data area
; The 'filename' for a directory listing
dirpath: db '/sys'
times 252 db 0
curdirptr: dd dirpath+4
 
fsize: dd 0
 
state db 0
buffptr dd 0
buff: times 256 db 0 ; Could put this after iend
 
; Ram use at the end of the application:
; text : 2400 bytes for screen memory
; text + 0x1300 : file data area
text:
I_END:
/programs/network_old/ftps/trunk/build.bat
0,0 → 1,2
@fasm ftps.asm ftps
@pause
/programs/network_old/VNCclient/logon.inc
0,0 → 1,257
red_logon:
call draw_window_logon ; at first, draw the window
 
still_logon: ; main cycle of application begins here
mov eax,10 ; wait here for event
mcall
 
checkevent_logon: ; Check what event was called _logon: this will be used to return from textbox focus
 
dec eax ; redraw request ?
jz red_logon
dec eax ; key in buffer ?
jz key_logon
dec eax ; button in buffer ?
jz button_logon
 
jmp still_logon
 
key_logon: ; key event handler
mov al,2 ; eax was zero so will now be 2
mcall ; just read it and ignore
 
cmp ah,13
jne still_logon ; return to main loop
 
ret ; enter key was pressed => return to logon
 
button_logon: ; eax was zero so will now be 17
mov al,17 ; get id
mcall
 
cmp ah,1 ; close ?
jz close_logon
cmp ah,2 ; logon ?
je connect_logon
cmp ah,5 ; first ?
jz dstbtn_logon
 
srcbtn_logon:
mov dword[addr],first
jmp rk_logon
 
dstbtn_logon:
mov dword[addr],second
 
rk_logon:
mov edi,[addr] ; load the address of the string
xor al,al ; mov al,0 ; the symbol we will search for
mov ecx,STRLEN+1 ; length of the string (+1)
cld ; search forward
repne scasb ; do search now
inc ecx ; we've found a zero or ecx became 0
mov eax,STRLEN+1
sub eax,ecx ; eax = address of <0> character
mov [temp],eax ; position
 
cmp dword[addr],dword second
jne @f
mov dword [passlen],eax
@@:
 
call print_text_logon
 
mov edi,[addr] ; address of string
add edi,[temp] ; cursor position
 
.waitev_logon:
mov eax,10 ; wait for event
mcall
cmp eax,2 ; button presed ?
jne checkevent_logon ; a key is pressed or redraw is nessesary, goto checkevent
mcall ; eax = 2, read button
shr eax,8
cmp eax,8
jnz .nobs_logon ; BACKSPACE
cmp edi,[addr]
jz .waitev_logon
dec edi
mov byte[edi],0
 
cmp dword[addr],second
jne @f
dec [passlen]
@@:
 
call print_text_logon
jmp .waitev_logon
.nobs_logon:
cmp eax,13 ; ENTER
je still_logon
cmp eax,192
jne .noclear_logon
xor al,al
mov edi,[addr]
mov ecx,STRLEN
rep stosb
mov edi,[addr]
call print_text_logon
jmp .waitev_logon
 
.noclear_logon:
mov [edi],al
 
cmp dword[addr],second
jne @f
inc [passlen]
@@:
 
call print_text_logon
 
inc edi
mov esi,[addr]
add esi,STRLEN
cmp esi,edi
jnz .waitev_logon
 
jmp still_logon
 
 
; print strings (source & destination)
print_text_logon:
pusha
 
mov eax, 8
mov ebx, 105*65536+200
mov ecx, 31*65536+13
mov edx, 4
mov esi, 0xEBEBEB
mcall
 
cmp byte[mode],0
je @f
 
mov ecx, 49*65536+12
inc edx
mcall
 
@@:
mov eax, 4 ; function 4 _logon: write text to window
mov ebx, 107*65536+34 ; [x start] *65536 + [y start]
xor ecx, ecx ; color of text RRGGBB
mov edx, first ; pointer to text beginning
mov esi, STRLEN ; text length
mcall
 
cmp byte[mode],0
je dont_draw_pass
 
add ebx,16
mov edi,[passlen]
 
@@:
cmp edi,0
jle dont_draw_pass
 
dec edi
mov edx, passchar
mov esi, 1
mcall
add ebx,6*65536
jmp @r
 
dont_draw_pass:
 
popa
ret
 
close_logon:
or eax,-1
mcall
 
connect_logon:
ret
 
draw_window_logon:
 
mcall 12, 1 ; start window draw
pusha
; DRAW WINDOW
xor eax, eax ; function 0 _logon: define and draw window
mov ebx, 160*65536+330 ; [x start] *65536 + [x size]
mov ecx, 160*65536+100 ; [y start] *65536 + [y size]
mov edx, 0x13DDDDDD ; color of work area RRGGBB
mov edi, title ; WINDOW LABEL
mcall
 
mov eax, 8 ; LOGON BUTTON
mov ebx, 220*65536+85
mov ecx, 63*65536+16
mov edx, 2
mov esi, 0xCCCCCC
mcall
 
call print_text_logon
cmp byte[mode], 0
je servermode_
 
mov eax, 4 ; function 4 write text to window
mov ebx, 25*65536+33 ; [x start] *65536 + [y start]
xor ecx, ecx
mov edx, userstr ; pointer to text beginning
mov esi, passstr-userstr ; text length
mcall
 
add bl,19
mov edx, passstr ; pointer to text beginning
mov esi, connect-passstr ; text length
mcall
 
jmp drawtherest_
 
servermode_:
 
mov eax, 4 ; function 4 write text to window
mov ebx, 25*65536+33 ; [x start] *65536 + [y start]
xor ecx, ecx
mov edx, serverstr ; pointer to text beginning
mov esi, userstr-serverstr ; text length
mcall
 
drawtherest_:
 
mov ebx, 240*65536+67 ; [x start] *65536 + [y start]
mov edx, connect ; pointer to text beginning
mov esi, connect_e-connect ; text length
mcall
 
popa
inc ebx
mcall
 
ret
 
 
; DATA AREA
title db 'Kolibrios VNC client by HIDNPLAYR',0
 
first: db '192.168.1.5'
rb STRLEN
second: rb STRLEN
 
passchar db '*'
passlen dd 0
 
addr dd 0
temp dd 0
mode db 0 ; 0 = connection details, 1 = authentication
 
serverstr: db 'server:'
userstr: db 'username:'
passstr: db 'password:'
connect: db 'connect !'
connect_e:
 
I_END_logon:
/programs/network_old/VNCclient/VNCclient.asm
0,0 → 1,330
;
;
; VNC Client for kolibrios by hidnplayr
;
;
; WORK IN PROGRESS...
;
; FEEL FREE TO CONTRIBUTE !
;
; hidnplayr@gmail.com
;
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image
dd IM_END ; memory for app
dd IM_END ; esp
dd 0x0 , 0x0 ; I_Param , I_Icon
 
__DEBUG__ equ 1
__DEBUG_LEVEL__ equ 1
 
STRLEN = 64 ; password and server max length
xpos = 4 ; coordinates of image
ypos = 22 ;
 
TIMEOUT = 60 ; timeout in seconds
BUFFER = 1500 ; Buffer size for DNS
 
include '..\..\macros.inc'
include 'fdo.inc'
include 'ETH.INC'
include 'logon.inc'
include 'raw.inc'
include 'copyrect.inc'
include 'thread.inc'
 
START: ; start of execution
 
call red_logon
 
mov eax,40 ; Report events
mov ebx,00000000b ; Only Stack
mcall
 
mov eax,67 ; resize the window (hide it)
xor ebx,ebx
mov ecx,ebx
mov edx,ebx
mov esi,ebx
mcall
 
mov eax,51
mov ebx,1
mov ecx,thread_start
mov edx,thread_stack
mcall
 
DEBUGF 1,'Thread created: %u\n',eax
 
@@:
mov eax,5
mov ebx,10
mcall
 
cmp byte[thread_ready],0
je @r
 
mov eax,40 ; report events
mov ebx,100111b ; mouse, button, key, redraw
mcall
 
mov eax,67 ; resize the window
mov ebx,10
mov ecx,10
mov edx,dword[framebuffer]
bswap edx
movzx esi,dx
shr edx,16
add edx,2*xpos
add esi,ypos+xpos
mcall
 
mainloop:
eth.socket_status [socket],eax
cmp al,TCB_CLOSE_WAIT
je close
 
mov eax,23 ; wait for event with timeout
mov ebx,50 ; 0,5 s
mcall
 
cmp eax,1
je redraw
cmp eax,2 ; key
je key
cmp eax,3 ; button
je button
cmp eax,6 ; mouse
je mouse
 
call drawbuffer
 
jmp mainloop
 
key:
DEBUGF 1,'Sending key event\n'
 
mov eax,2
mcall
mov byte[keyevent.key+3],ah
 
eth.write_tcp [socket],8,keyevent
 
jmp mainloop
 
mouse:
DEBUGF 1,'Sending mouse event\n'
 
mov eax,37
mov ebx,1
mcall
 
sub eax,xpos*65536+ypos
bswap eax
mov word[pointerevent.x],ax
shr eax,16
mov word[pointerevent.y],ax
 
mov eax,37
mov ebx,2
mcall
 
test al,00000010b ; test if right button was pressed (bit 1 in kolibri)
jz @f
add al,00000010b ; in RFB protocol it is bit 2, so if we add bit 2 again, we'll get bit 3 and bit 1 will remain the same
@@:
 
mov byte[pointerevent.mask],al
 
eth.write_tcp [socket],6,pointerevent
 
jmp mainloop
 
redraw:
 
DEBUGF 1,'Drawing window\n'
 
mcall 12, 1
 
mov eax,0 ; draw window
mov ebx,dword[framebuffer]
bswap ebx
movzx ecx,bx
shr ebx,16
add ebx,2*xpos
add ecx,ypos+xpos
mov edx,0xffffff
mcall
 
mov eax,4 ; label
mov ebx,9*65536+8
mov ecx,0x10ffffff
mov edx,name
mov esi,[name_length]
bswap esi
mcall
 
call drawbuffer
 
mcall 12, 2
 
jmp mainloop
 
drawbuffer:
 
mov eax,7
mov ebx,framebuffer_data
mov ecx,dword[screen]
mov edx,xpos*65536+ypos
mcall
 
ret
 
 
button: ; button
mov eax,17 ; get id
mcall
 
close:
call read_data
; eth.close_tcp [socket] ; We're done, close the socket ;;; BUG WHEN CLOSING SOCKET !!
DEBUGF 1,'Socket closed\n'
 
mov eax,-1
mcall
 
no_rfb:
DEBUGF 1,'This is no vnc server!\n'
jmp close
 
invalid_security:
DEBUGF 1,'Security error: %s\n',receive_buffer+5
jmp close
 
 
; DATA AREA
 
include_debug_strings ; ALWAYS present in data section
 
handshake db 'RFB 003.003',0x0a
shared db 0
beep db 0x85,0x25,0x85,0x40,0
 
pixel_format32 db 0 ; setPixelformat
rb 3 ; padding
.bpp db 32 ; bits per pixel
.depth db 32 ; depth
.big_endian db 0 ; big-endian flag
.true_color db 1 ; true-colour flag
.red_max db 0,255 ; red-max
.green_max db 0,255 ; green-max
.blue_max db 0,255 ; blue-max
.red_shif db 0 ; red-shift
.green_shift db 8 ; green-shift
.blue_shift db 16 ; blue-shift
rb 3 ; padding
 
pixel_format16 db 0 ; setPixelformat
rb 3 ; padding
.bpp db 16 ; bits per pixel
.depth db 15 ; depth
.big_endian db 0 ; big-endian flag
.true_color db 1 ; true-colour flag
.red_max db 0,31 ; red-max
.green_max db 0,31 ; green-max
.blue_max db 0,31 ; blue-max
.red_shif db 0 ; red-shift
.green_shift db 5 ; green-shift
.blue_shift db 10 ; blue-shift
rb 3 ; padding
 
pixel_format8 db 0 ; setPixelformat
rb 3 ; padding
.bpp db 8 ; bits per pixel
.depth db 6 ; depth
.big_endian db 0 ; big-endian flag
.true_color db 1 ; true-colour flag
.red_max db 0,3 ; red-max
.green_max db 0,3 ; green-max
.blue_max db 0,3 ; blue-max
.red_shif db 0 ; red-shift
.green_shift db 2 ; green-shift
.blue_shift db 4 ; blue-shift
rb 3 ; padding
 
encodings db 2 ; setEncodings
rb 1 ; padding
db 1,0 ; number of encodings
db 0,0,0,0 ; raw encoding (DWORD, Big endian order)
db 1,0,0,0 ; Copyrect encoding
 
fbur db 3 ; frame buffer update request
.inc db 0 ; incremental
.x dw 0
.y dw 0
.width dw 0
.height dw 0
 
keyevent db 4 ; keyevent
.down db 0 ; down-flag
dw 0 ; padding
.key dd 0 ; key
 
pointerevent db 5 ; pointerevent
.mask db 0 ; button-mask
.x dw 0 ; x-position
.y dw 0 ; y-position
 
I_END:
 
framebuffer:
.width dw ?
.height dw ?
pixelformat:
.bpp db ?
.depth db ?
.big_endian db ?
.true_color db ?
.red_max dw ?
.green_max dw ?
.blue_max dw ?
.red_shift db ?
.green_shift db ?
.blue_shift db ?
.padding rb 3
name_length dd ?
name rb 256
 
server_ip dd 0
server_port dd 0
socket dd 0
datapointer dd 0
 
frame:
.width dw 0
.height dw 0
.x dw 0
.y dw 0
 
screen:
.height dw 0
.width dw 0
 
thread_ready db 0
 
dnsMsg:
receive_buffer rb 5*1024*1024 ; 5 mb buffer for received data (incoming frbupdate etc)
framebuffer_data rb 1024*768*3 ; framebuffer
 
thread_stack rb 0x1000
 
IM_END:
 
 
/programs/network_old/VNCclient/ETH.INC
0,0 → 1,671
;
; ETH.INC
;
; made by hidnplayr (hidnplayr@gmail.com) for KolibriOS
;
; The given code before every macro is only a simple example
;
;
; HISTORY
;
; v1.0: 18 august 2006 original release
; v1.1: december 2006 bugfixes and improvements
;
 
macro mov arg1,arg2 {
if arg1 eq arg2
else
mov arg1,arg2
end if
}
 
TCB_LISTEN = 1
TCB_SYN_SENT = 2
TCB_SYN_RECEIVED = 3
TCB_ESTABLISHED = 4
TCB_FIN_WAIT_1 = 5
TCB_FIN_WAIT_2 = 6
TCB_CLOSE_WAIT = 7
TCB_CLOSING = 8
TCB_LAST_ASK = 9
TCB_TIME_WAIT = 10
TCB_CLOSED = 11
 
PASSIVE = 0
ACTIVE = 1
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; eth.get_IP eax
;
; gets the current IP that is defined in Stack (return in eax in this example)
macro eth.get_IP IP {
mov ebx,1
mov eax,52
mcall
 
mov IP ,eax
}
 
; eth.get_GATEWAY eax
;
; gets the current GATEWAY that is defined in Stack (return in eax in this example)
macro eth.get_GATEWAY GATEWAY {
mov ebx,9
mov eax,52
mcall
move GATEWAY ,eax
}
 
; eth.get_SUBNET eax
;
; gets the current SUBNET that is defined in Stack (return in eax in this example)
macro eth.get_SUBNET SUBNET {
mov ebx,10
mov eax,52
mcall
mov SUBNET ,eax
}
 
; eth.get_DNS eax
;
; gets the current DNS that is defined in Stack (return in eax in this example)
macro eth.get_DNS DNS {
mov ebx,13
mov eax,52
mcall
mov DNS ,eax
}
 
; eth.set_IP eax
;
; set a new IP in stack (input in eax in this example)
macro eth.set_IP IP {
mov ecx,IP
mov ebx,3
mov eax,52
mcall
}
 
; eth.set_GATEWAY eax
;
; set a new GATEWAY in stack (input in eax in this example)
macro eth.set_GATEWAY GATEWAY {
mov ecx,GATEWAY
mov ebx,11
mov eax,52
mcall
}
 
; eth.set_SUBNET eax
;
; set a new SUBNET in stack (input in eax in this example)
macro eth.set_SUBNET SUBNET {
mov ecx,SUBNET
mov ebx,12
mov eax,52
mcall
}
 
; eth.set_DNS eax
;
; set a new DNS in stack (input in eax in this example)
macro eth.set_DNS DNS {
mov ecx,DNS
mov ebx,14
mov eax,52
mcall
}
 
; eth.open eax,80,ebx,[socket]
;
; open a socket on local port in eax to port 80 on server on ebx
; the socketnumber will be returned in [socket] (dword)
macro eth.open_udp local,remote,ip,socket {
mov ecx, local
mov edx, remote
mov esi, ip
mov ebx, 0
mov eax, 53
mcall
 
mov socket,eax
}
 
; eth.close [socket]
;
; closes socket on socketnumber [socket]
macro eth.close_udp socket {
mov ecx, socket
mov ebx, 1
mov eax, 53
mcall
}
 
; eth.poll [socket],eax
;
; polls [socket] for data
; eax = 0 when there is data
macro eth.poll socket {
mov ecx, socket
mov ebx, 2
mov eax, 53
mcall
}
 
; eth.read_byte [socket], bl
;
; reads a byte from the socket and returns in bl
macro eth.read_byte socket, result {
mov ecx, socket
mov ebx, 3
mov eax, 53
mcall
 
mov result,bl
}
 
; eth.read_byte [socket], bl
;
; reads a byte from the socket and returns in bl
macro eth.read_packet socket, result {
mov edx, result
mov ecx, socket
mov ebx, 10
mov eax, 53
mcall
}
 
; eth.write [socket],12,msg
; msg db 'hello world!'
;
; send message msg to socket
macro eth.write_udp socket,length,msg,verify {
mov ecx, socket
mov edx, length
mov esi, msg
mov ebx, 4
mov eax, 53
mcall
 
if verify eq 1
call verifysend
end if
 
}
 
verifysend:
test eax,eax
jnz @f
ret
@@:
pusha
mov eax,5
mov ebx,100
mcall
 
popa
mcall
ret
 
; eth.open_tcp 80,80,eax,0,[socket]
;
; opens a tcp socket on port 80 to port 80 on IP eax with passive open
; returns socket number in eax
macro eth.open_tcp local,remote,ip,passive,socket {
 
mov ecx, local
mov edx, remote
mov esi, ip
mov edi, passive ; 0 = PASSIVE open
mov ebx, 5
mov eax, 53
mcall
 
mov socket,eax
}
 
; eth.socket_status [socket],eax
;
; returns socket status in eax
macro eth.socket_status socket,result {
mov ecx, socket
mov ebx, 6
mov eax, 53
mcall
 
mov result,eax
}
 
; eth.write_tcp [socket],12,msg
;
; msg db 'hello world!'
;
; send message to TCP socket
macro eth.write_tcp socket,length,msg,verify {
mov ecx, socket
mov edx, length
mov esi, msg
mov ebx, 7
mov eax, 53
mcall
 
if verify eq 1
call verifysend
end if
}
 
; eth.close_tcp [socket]
;
; closes tcp socket [socket]
macro eth.close_tcp socket {
mov ecx, socket
mov ebx, 8
mov eax, 53
mcall
}
 
; eth.check_port 165,eax
;
; checks if port 165 is used
; return is 0 when port is free
macro eth.check_port port,result {
mov ecx, port
mov ebx, 9
mov eax, 53
mcall
 
mov result,eax
}
 
; eth.status eax
;
; returns socket status in eax
macro eth.status status {
mov ebx, 255
mov ecx, 6
mov eax, 53
mcall
 
mov status,eax
}
 
; eth.search 165,edx
;
; searches a free local port starting from 166 (165 + 1 !)
; returns in edx
macro eth.search_port port,result {
mov edx,port
@@:
inc edx
eth.check_port edx,eax
cmp eax,0
je @r
mov result,edx
}
 
 
 
; eth.read_data [socket],buffer,512
; buffer rb 512
; socket dd ?
;
; reads data from socket into a buffer, stops when there is no more data or buffer is full.
macro eth.read_data socket,dest,endptr,bufferl {
local .getdata,.loop,.end
mov eax, dest
mov endptr, eax
 
; we have data - this will be the response
.getdata:
mov eax,endptr
cmp eax,bufferl
jg .end
 
eth.read_byte socket,bl
 
; Store the data in the response buffer
mov eax, endptr
mov [eax], bl
inc dword endptr
 
eth.poll socket
 
cmp eax,0
jne .getdata ; yes, so get it
 
; now we are going to wait 30 times 10 ms (300ms)
 
mov edx,0
.loop:
mov eax,5
mov ebx,1
mcall
 
eth.poll socket
 
cmp eax, 0
jne .getdata ; yes, so get it
 
inc edx
cmp edx,100
jl .loop
 
.end:
 
}
 
; eth.wait_for_data [socket],60,abort
; eth.read_data ....
; abort:
;
; Waits for data with timeout
 
macro eth.wait_for_data socket,TIMEOUT,abort {
 
mov edx,TIMEOUT
 
@@:
eth.poll socket
 
cmp eax,0
jne @f
 
dec edx
jz abort
 
mov eax,5 ; wait here for event
mov ebx,10
mcall
 
jmp @r
@@:
 
}
 
 
; The function 'resolve' resolves the address in edx and puts the resulting IP in eax.
; When the input is an IP-adress, the function will output this IP in eax.
; If something goes wrong, the result in eax should be 0
;
; example:
;
; resolve query1,IP,PORT
; resolve '192.168.0.1',IP,PORT
; resolve query2,IP,PORT
;
; query1 db 'www.google.com',0
; query2 db '49.78.84.45',0
; IP dd ?
; PORT dd ?
 
macro resolve query,result {
 
if query eqtype 0
mov edx,query
else
local ..string, ..label
jmp ..label
..string db query,0
..label:
mov edx,..string
end if
 
call __resolve
 
mov result,eax
 
}
 
if used __resolve
 
__resolve:
 
if __DEBUG__ eq 1
DEBUGF 1,'Resolving started\n'
end if
 
; This code validates if the query is an IP containing 4 numbers and 3 dots
 
 
push edx ; push edx (query address) onto stack
xor al, al ; make al (dot count) zero
 
@@:
cmp byte[edx],'0' ; check if this byte is a number, if not jump to no_IP
jl no_IP ;
cmp byte[edx],'9' ;
jg no_IP ;
 
inc edx ; the byte was a number, so lets check the next byte
 
cmp byte[edx],0 ; is this byte zero? (have we reached end of query?)
jz @f ; jump to next @@ then
cmp byte[edx],':'
jz @f
 
cmp byte[edx],'.' ; is this byte a dot?
jne @r ; if not, jump to previous @@
 
inc al ; the byte was a dot so increment al(dot count)
inc edx ; next byte
jmp @r ; lets check for numbers again (jump to previous @@)
 
@@: ; we reach this when end of query reached
cmp al,3 ; check if there where 3 dots
jnz no_IP ; if not, jump to no_IP (this is where the DNS will take over)
 
; The following code will convert this IP into a dword and output it in eax
; If there is also a port number specified, this will be returned in ebx, otherwise ebx is -1
 
pop esi ; edx (query address) was pushed onto stack and is now popped in esi
 
xor edx, edx ; result
xor eax, eax ; current character
xor ebx, ebx ; current byte
 
.outer_loop:
shl edx, 8
add edx, ebx
xor ebx, ebx
.inner_loop:
lodsb
test eax, eax
jz .finish
cmp al, '.'
jz .outer_loop
sub eax, '0'
imul ebx, 10
add ebx, eax
jmp .inner_loop
.finish:
shl edx, 8
add edx, ebx
 
bswap edx ; we want little endian order
mov eax, edx
 
ret
 
 
no_IP:
 
pop edx
 
; The query is not an IP address, we will send the query to a DNS server and hope for answer ;)
if __DEBUG__ eq 1
DEBUGF 1,'The query is no ip, Building request string from:%u\n',edx
end if
 
; Build the request string
mov eax, 0x00010100
mov [dnsMsg], eax
mov eax, 0x00000100
mov [dnsMsg+4], eax
mov eax, 0x00000000
mov [dnsMsg+8], eax
 
; domain name goes in at dnsMsg+12
mov esi, dnsMsg + 12 ; location of label length
mov edi, dnsMsg + 13 ; label start
mov ecx, 12 ; total string length so far
 
td002:
mov [esi], byte 0
inc ecx
 
td0021:
mov al, [edx]
 
cmp al, 0
je td001 ; we have finished the string translation
 
cmp al, '.'
je td004 ; we have finished the label
 
inc byte [esi]
inc ecx
mov [edi], al
inc edi
inc edx
jmp td0021
 
td004:
mov esi, edi
inc edi
inc edx
jmp td002
 
; write label len + label text
td001:
mov [edi], byte 0
inc ecx
inc edi
mov [edi], dword 0x01000100
add ecx, 4
 
mov [dnsMsgLen], ecx ; We'll need the length of the message when we send it
; Now, lets send this and wait for an answer
 
eth.search_port 1024,edx ; Find a free port starting from 1025 and store in edx
eth.get_DNS esi ; Read DNS IP from stack into esi
eth.open_udp edx,53,esi,[socketNum] ; First, open socket
if __DEBUG__ eq 1
DEBUGF 1,'Socket opened: %u (port %u)\n',[socketNum],ecx
end if
eth.write_udp [socketNum],[dnsMsgLen],dnsMsg ; Write to socket ( request DNS lookup )
if __DEBUG__ eq 1
DEBUGF 1,'Data written, length:%u offset:%u\n',[dnsMsgLen],dnsMsg
DEBUGF 1,'Waiting for data: (timeout is %us)\n',TIMEOUT
end if
eth.wait_for_data [socketNum],TIMEOUT,abort ; Now, we wait for data from remote
eth.read_data [socketNum],dnsMsg,[dnsMsgLen],dnsMsg+BUFFER ; Read the data into the buffer
if __DEBUG__ eq 1
DEBUGF 1,'Data received, offset:%u buffer size:%u length:%u\n',dnsMsg,BUFFER,esi-dnsMsg
end if
eth.close_udp [socketNum] ; We're done, close the socket
if __DEBUG__ eq 1
DEBUGF 1,'Closed Socket\n'
end if
 
; Now parse the message to get the host IP. Man, this is complicated. It's described in RFC 1035
; 1) Validate that we have an answer with > 0 responses
; 2) Find the answer record with TYPE 0001 ( host IP )
; 3) Finally, copy the IP address to the display
; Note: The response is in dnsMsg, the end of the buffer is pointed to by [dnsMsgLen]
 
mov esi, dnsMsg
 
mov al, [esi+2] ; Is this a response to my question?
and al, 0x80
cmp al, 0x80
jne abort
if __DEBUG__ eq 1
DEBUGF 1,'It was a response to my question\n'
end if
 
mov al, [esi+3] ; Were there any errors?
and al, 0x0F
cmp al, 0x00
jne abort
 
if __DEBUG__ eq 1
DEBUGF 1,'There were no errors\n'
end if
 
mov ax, [esi+6] ; Is there ( at least 1 ) answer?
cmp ax, 0x00
je abort
 
; Header validated. Scan through and get my answer
add esi, 12 ; Skip to the question field
call skipName ; Skip through the question field
add esi, 4 ; skip past the questions qtype, qclass
 
ctr002z:
; Now at the answer. There may be several answers, find the right one ( TYPE = 0x0001 )
call skipName
mov ax, [esi]
cmp ax, 0x0100 ; Is this the IP address answer?
jne ctr002c
add esi, 10 ; Yes! Point eax to the first byte of the IP address
mov eax,[esi]
 
ret
 
 
ctr002c: ; Skip through the answer, move to the next
add esi, 8
movzx eax, byte [esi+1]
mov ah, [esi]
add esi, eax
add esi, 2
 
cmp esi, [dnsMsgLen] ; Have we reached the end of the msg? This is an error condition, should not happen
jl ctr002z ; Check next answer
 
abort:
if __DEBUG__ eq 1
DEBUGF 1,'Something went wrong, aborting\n'
end if
xor eax,eax
 
ret
 
 
skipName:
; Increment esi to the first byte past the name field
; Names may use compressed labels. Normally do.
; RFC 1035 page 30 gives details
mov al, [esi]
cmp al, 0
je sn_exit
and al, 0xc0
cmp al, 0xc0
je sn001
 
movzx eax, byte [esi]
inc eax
add esi, eax
jmp skipName
 
sn001:
add esi, 2 ; A pointer is always at the end
ret
 
sn_exit:
inc esi
ret
 
dnsMsgLen: dd 0
socketNum: dd 0xFFFF
 
if ~defined dnsMsg
dnsMsg: rb BUFFER
end if
 
end if
 
 
 
 
/programs/network_old/VNCclient/build.bat
0,0 → 1,2
@fasm VNCclient.asm VNCclient
@pause
/programs/network_old/VNCclient/fdo.inc
0,0 → 1,343
;
; Formatted Debug Output (FDO)
; Copyright (c) 2005-2006, mike.dld
; Created: 2005-01-29, Changed: 2006-07-20
;
; 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
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
call fdo_debug_outstr
else
mov edx,_str
call fdo_debug_outstr
end if
popad
popf
}
 
macro DEBUGD _sign,_dec {
pushf
pushad
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
local tp
tp equ 0
match _num[_arg],_dec \{
if _num = 1
if _sign = 1
movsx eax,byte[_arg]
else
movzx eax,byte[_arg]
end if
else if _num = 2
if _sign = 1
movsx eax,word[_arg]
else
movzx eax,word[_arg]
end if
else
mov eax,dword[_arg]
end if
tp equ 1
\}
match =0 [_arg],tp _dec \{
mov eax,dword[_arg]
\}
sub esp,4*8+4
end if
mov cl,_sign
call fdo_debug_outdec
popad
popf
}
 
macro DEBUGH _sign,_hex {
pushf
pushad
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
shl eax,16
mov edx,4
else if _hex in <al,ah,bl,bh,cl,ch,dl,dh>
if ~_hex eq al
movzx eax,_hex
end if
shl eax,24
mov edx,2
end if
else if _hex eqtype 0
mov eax,_hex
mov edx,8
else
add esp,4*8+4
local tp
tp equ 0
match _num[_arg],_hex \{
mov eax,dword[_arg]
mov edx,_num
tp equ 1
\}
match =0 [_arg],tp _hex \{
mov eax,dword[_arg]
mov edx,8
\}
sub esp,4*8+4
end if
call fdo_debug_outhex
popad
popf
}
 
;-----------------------------------------------------------------------------
 
debug_func fdo_debug_outchar
debug_beginf
pushad
mov cl,al
mov ebx,1
mov eax,63
mcall
popad
ret
debug_endf
 
debug_func fdo_debug_outstr
debug_beginf
mov eax,63
mov ebx,1
.l1: mov cl,[edx]
or cl,cl
jz .l2
mcall
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
}
/programs/network_old/VNCclient/thread.inc
0,0 → 1,188
thread_start:
DEBUGF 1,'I am the thread!\n'
 
mov eax,40 ; Report events
mov ebx,10000000b ; Only Stack
mcall
 
resolve first,[server_ip] ; the input window putted the server @ 'first', resolve it into a real ip
mov [server_port],5900 ; no port input for now, only standard port 5900
 
DEBUGF 1,'connecting to %u.%u.%u.%u:%u\n',1[server_ip],1[server_ip+1],1[server_ip+2],1[server_ip+3],4[server_port]
eth.search_port 1000,edx ; Find a free port starting from 1001 and store in edx
eth.open_tcp edx,[server_port],[server_ip],1,[socket] ; open socket
DEBUGF 1,'Socket opened: %u (port %u)\n',[socket],ecx
 
call read_data
cmp dword[receive_buffer+1],'RFB '
jne no_rfb
eth.write_tcp [socket],12,handshake
DEBUGF 1,'Sending handshake: protocol version\n'
 
call read_data
mov eax,receive_buffer+1
mov eax,[eax]
bswap eax
cmp eax,0
je invalid_security
cmp eax,1
je no_security
cmp eax,2
je vnc_security
 
jmp close
 
vnc_security:
mov byte[mode],1
call red_logon
 
no_security:
eth.write_tcp [socket],1,shared
DEBUGF 1,'Sending handshake: shared session?\n'
 
eth.wait_for_data [socket],TIMEOUT*10,close
eth.read_data [socket],framebuffer,[datapointer],IM_END-receive_buffer ; now the server should send init message
DEBUGF 1,'Serverinit: bpp:%u depth:%u bigendian:%u truecolor:%u\n',1[pixelformat.bpp],1[pixelformat.depth],1[pixelformat.big_endian],1[pixelformat.true_color]
mov eax,dword[framebuffer]
bswap eax
mov dword[screen],eax
 
eth.write_tcp [socket],20,pixel_format8
DEBUGF 1,'Sending pixel format\n'
call read_data
 
; eth.write_tcp [socket],8,encodings
; DEBUGF 1,'Sending encoding info\n'
; call read_data
 
mov eax,dword[framebuffer.width]
mov dword[fbur.width],eax
 
mov byte[thread_ready],1
 
request_rfb:
mov byte[fbur.inc],2 ;;;;;;;;
eth.write_tcp [socket],10,fbur ;;;;;;;;;
 
thread_loop:
eth.wait_for_data [socket],1000,thread_loop
 
call read_data ; Read the data into the buffer
 
mov eax,[datapointer] ; at least 2 bytes should be received
sub eax,receive_buffer
cmp eax,1
jle mainloop
 
DEBUGF 1,'Data received, %u bytes\n',eax
 
cmp byte[receive_buffer],0
je framebufferupdate
 
cmp byte[receive_buffer],1
je setcolourmapentries
 
cmp byte[receive_buffer],2
je bell
 
cmp byte[receive_buffer],3
je servercuttext
 
jmp thread_loop
 
 
framebufferupdate:
mov ax,word[receive_buffer+2]
xchg al,ah
mov di,ax
DEBUGF 1,'Framebufferupdate: %u frames\n',di
mov esi,receive_buffer+4
jmp rectangle_loop
 
next_rectangle:
call drawbuffer
 
dec di
test di,di
jz request_rfb
 
rectangle_loop:
mov edx,[esi]
bswap edx
mov ebx,edx
shr edx,16
mov [frame.x],dx
mov [frame.y],bx
add esi,4
mov ecx,[esi]
bswap ecx
mov eax,ecx
shr ecx,16
mov [frame.width],cx
mov [frame.height],ax
add esi,4
mov eax,[esi]
add esi,4
 
mov ebx,esi
sub ebx,receive_buffer+12
DEBUGF 1,'frame: width=%u height=%u x=%u y=%u offset:%u encoding:',2[frame.width],2[frame.height],2[frame.x],2[frame.y],ebx
 
cmp eax,0
je encoding_raw
cmp eax,1
je encoding_copyrect
cmp eax,2
je encoding_RRE
cmp eax,5
je encoding_hextile
cmp eax,16
je encoding_ZRLE
 
mov ebx,esi
sub ebx,receive_buffer+8
DEBUGF 1,'\nunknown encoding: %u (offset %u)\n',eax,ebx
jmp bell
jmp thread_loop
 
encoding_RRE:
DEBUGF 1,'RRE\n'
 
jmp next_rectangle
 
encoding_hextile:
DEBUGF 1,'hextile\n'
 
jmp next_rectangle
 
encoding_ZRLE:
DEBUGF 1,'ZRLE\n'
 
jmp next_rectangle
 
 
setcolourmapentries:
DEBUGF 1,'Server sended SetColourMapEntries message\n'
 
jmp thread_loop
 
 
bell:
mov eax,55
mov ebx,eax
mov esi,beep
mcall
 
jmp thread_loop
 
 
servercuttext:
DEBUGF 1,'Server cut text\n'
 
jmp thread_loop
 
 
 
read_data:
eth.read_data [socket],receive_buffer,[datapointer],IM_END-receive_buffer
ret
/programs/network_old/VNCclient/raw.inc
0,0 → 1,153
encoding_raw:
DEBUGF 1,'RAW\n'
 
mov ax,[frame.y] ;
mov bx,[screen.width] ;
mul bx ;
shl edx,16 ;
mov dx,ax ; [screen.width]*[frame.y]
movzx eax,[frame.x]
add edx,eax ; [screen.width]*[frame.y]+[frame.x]
 
mov eax,3 ;
mul edx ; ([screen.width]*[frame.y]+[frame.x])*3
 
add eax,framebuffer_data ;
push eax ; framebuffer_data+([screen.width]*[frame.y]+[frame.x])*3
 
mov ax,[frame.width] ;
mov bx,3 ;
mul bx ;
shl edx,16 ;
mov dx,ax ; [frame.width]*3
 
pop eax ;
add edx,eax ; framebuffer_data+([screen.width]*[frame.y]+[frame.x])*3+[frame.width]*3
push eax ;
push edx ;
 
mov ax,[frame.height] ;
dec ax ;
mov bx,3 ;
mul bx ;
mov bx,[screen.width] ;
mul bx ;
shl edx,16 ;
mov dx,ax ;
mov ecx,edx ;
pop edx ;
add ecx,edx ; mov ecx,edx+([frame.height]-1)*[screen.width]*3
pop ebx
 
.pixelloop32:
cmp ebx,ecx
jge next_rectangle
 
; add esi,2 ; 32 bit code RAW - OK
; mov al,[esi] ;
; mov [ebx],al ;
; inc ebx ;
; dec esi ;
; ;
; mov al,[esi] ;
; mov [ebx],al ;
; inc ebx ;
; dec esi ;
; ;
; mov al,[esi] ;
; mov [ebx],al ;
; inc ebx ;
; add esi,4 ;
 
; push ecx ; 16 bit code RAW
; mov cl,51
;
; mov ax,[esi] ;
; xchg al,ah
; and al,00011111b ;
; xchg al,ah
; mul cl
; mov [ebx],al ;
; inc ebx ;
;
; mov ax,[esi] ;
; xchg al,ah
; shr ax,5 ;
; xchg al,ah
; and al,00011111b ;
; mul cl
; mov [ebx],al ;
; inc ebx ;
;
; mov ax,[esi] ;
; xchg al,ah
; shr ax,10 ;
; and al,00011111b ;
; mul cl
; mov [ebx],al ;
; inc ebx ;
;
; inc esi ;
; inc esi ;
; pop ecx
 
push ecx ; 8 bit code RAW - OK
mov cl,85 ;
;
mov al,[esi] ;
shr al,4 ;
and al,3 ;
mul cl ;
mov [ebx],al ;
inc ebx ;
;
mov al,[esi] ;
shr al,2 ;
and al,3 ;
mul cl ;
mov [ebx],al ;
inc ebx ;
;
mov al,[esi] ;
and al,3 ;
mul cl ;
mov byte[ebx],al ;
inc ebx ;
inc esi ;
pop ecx ;
 
 
cmp ebx,edx
jl .pixelloop32
 
push edx
push ebx
mov ax,[screen.width]
mov bx,3
mul bx
shl edx,16
mov dx,ax
mov eax,edx
pop ebx
pop edx
 
add ebx,eax ; eax = [screen.width]*3
add edx,eax
 
push edx
push ebx
mov ax,[frame.width]
mov bx,3
mul bx
shl edx,16
mov dx,ax
mov eax,edx
pop ebx
pop edx
 
sub ebx,eax ; eax = [frame.width]*3
 
jmp .pixelloop32
 
 
 
/programs/network_old/VNCclient/copyrect.inc
0,0 → 1,5
encoding_copyrect:
DEBUGF 1,'FRAME: copyrect\n'
 
 
jmp next_rectangle
/programs/network_old/https/trunk/https.asm
0,0 → 1,1362
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Tiny HTTP Server v 0.5 for KolibriOS ;
; ;
; License GPL / See file COPYING for details. ;
; Copyright 2003 Ville Turjanmaa ;
; ;
; Compile with FASM for Menuet/KolibriOS ;
; ;
; Request /TinyStat for server statistics ;
; Request /TinyBoard for server message board ;
; ;
; Special version for KoOS by Hex && Heavyiron ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
appname equ 'Kolibri HTTP Server '
version equ '0.6'
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; required os
dd START ; program start
dd I_END ; program image size
dd 0x400000 ; required amount of memory
dd 0x20000
dd 0,0 ; reserved=no extended header
 
include "macros.inc"
 
; 0x0+ - program image
; 0x1ffff - stack
; 0x20000+ - message board
; 0x100000+ - requested file
 
filel:
dd 0
dd 0
dd 0
dd 50000
dd 0x20000
db '/sys/board.htm',0
 
files:
dd 2
dd 0
dd 0
dd 0
dd 0x20000
db '/sys/board.htm',0
 
 
START: ; start of execution
 
mov eax,70
mov ebx,filel
mcall
mov [board_size],ebx
cmp eax,0
je board_found
 
mov [board_size],board_end-board
mov esi,board
mov edi,0x20000
mov ecx,[board_size]
cld
rep movsb
 
board_found:
 
mov eax,70
mov ebx,files
mov ecx,[board_size]
mov [files+12],ecx
mcall
 
mov [status],-1
mov [last_status],-2
call clear_input
red:
call draw_window ; at first, draw the window
 
still:
 
call check_status
cmp [status],4
je start_transmission
 
cmp [status],0
jne nnn
cmp [server_active],1
jne nnn
call ops
nnn:
 
mov eax,5
mov ebx,1
mcall
 
mov eax,11
mcall
call check_events
 
jmp still
 
last_status dd 0x0
 
check_events:
 
cmp eax,1 ; redraw request ?
jz red
cmp eax,2 ; key in buffer ?
jz key
cmp eax,3 ; button in buffer ?
jz button
 
ret
 
key: ; Keys are not valid at this part of the
mov al,2 ; loop. Just read it and ignore
mcall
ret
 
button: ; button
 
mov al,17 ; get id
mcall
 
cmp ah,1 ; close
jnz tst2
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
mov eax,-1
mcall
tst2:
 
cmp ah,2 ; button id=2 ?
jnz tst3
; open socket
ops:
mov eax,53
mov ebx,5
mov ecx,80 ; local port # - http
mov edx,0 ; no remote port specified
mov esi,0 ; no remote ip specified
mov edi,0 ; PASSIVE open
mcall
mov [socket], eax
mov [posy],1
mov [posx],0
call check_for_incoming_data
call clear_input
call draw_data
mov [server_active],1
call check_status
ret
tst3:
cmp ah,4 ; button id=4 ?
jnz no4
mov [server_active],0
close_socket:
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
mov eax,5
mov ebx,2
mcall
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
 
cmp [server_active],1
jne no_re_open
mov eax,53
mov ebx,5
mov ecx,80 ; local port # - http
mov edx,0 ; no remote port specified
mov esi,0 ; no remote ip specified
mov edi,0 ; PASSIVE open
mcall
mov [socket], eax
no_re_open:
 
mov edi,input_text+256*15+1
mov [edi+2],dword ': :'
call set_time
mov edi,input_text+256*16+1
mov [edi+2],dword '. .'
call set_date
 
mov eax,[documents_served]
mov ecx,9
mov edi,input_text+256*15+12
call set_value
 
mov eax,[bytes_transferred]
mov ecx,9
mov edi,input_text+256*16+12
call set_value
 
call draw_data
 
mov esp,0x1ffff
jmp still
no4:
 
cmp ah,6 ; read directory
je read_string
 
ret
 
 
clear_input:
 
mov edi,input_text
mov eax,0
mov ecx,256*30
cld
rep stosb
 
ret
 
 
retries dd 50
 
start_transmission:
 
mov [posy],1
mov [posx],0
call clear_input
mov [retries],50
 
wait_for_data:
call check_for_incoming_data
cmp [input_text+256+1],dword 'GET '
je data_received
cmp [input_text+256+1],dword 'POST'
je data_received
mov eax,5
mov ebx,1
mcall
dec [retries]
jnz wait_for_data
jmp no_http_request
data_received:
 
mov eax,0x100000
mov ebx,0x2f0000 / 512
call read_file
 
call wait_for_empty_slot
call send_header
 
mov [filepos],0x100000
mov [fileadd],700
 
call check_status
call draw_data
 
newblock:
 
call wait_for_empty_slot
 
mov edx,[fileadd]
cmp edx,[file_left]
jbe file_size_ok
mov edx,[file_left]
file_size_ok:
sub [file_left],edx
 
; write to socket
mov eax,53
mov ebx,7
mov ecx,[socket]
mov esi,[filepos]
mcall
 
mov eax,esi
add eax,edx
sub eax,0x100000
call display_progress
 
mov edx,[fileadd]
add [filepos],edx
 
cmp [file_left],0
jg newblock
 
no_http_request:
 
jmp close_socket
 
 
filepos dd 0x100000
fileadd dd 0x1
filesize dd 0x0
file_left dd 0x0
 
 
wait_for_empty_slot:
 
pusha
 
wait_more:
 
mov eax,5
mov ebx,1
mcall
 
mov eax,11
mcall
call check_events
 
mov eax,53
mov ebx,255
mov ecx,103
mcall
 
cmp eax,0
je no_wait_more
 
jmp wait_more
 
no_wait_more:
 
popa
ret
 
 
 
 
display_progress:
 
pusha
 
mov edi,eax
 
mov eax,13
mov ebx,115*65536+8*6
mov ecx,178*65536+10
mov edx,0xffffff
mcall
 
mov eax,47
mov ebx,8*65536
mov ecx,edi
mov edx,115*65536+178
mov esi,0x000000
mcall
 
popa
ret
 
 
send_header:
 
pusha
 
mov eax,53 ; send response and file length
mov ebx,7
mov ecx,[socket]
mov edx,h_len-html_header
mov esi,html_header
mcall
 
mov eax,53 ; send file type
mov ebx,7
mov ecx,[socket]
mov edx,[type_len]
mov esi,[file_type]
mcall
 
popa
ret
 
fileinfo dd 0
dd 0
dd 0
dd 512
dd 0x100000
getf db '/sys/'
times 50 db 0
wanted_file: times 100 db 0
 
getflen dd 6
 
make_room:
 
pusha
 
mov edx,ecx
 
mov esi,0x20000
add esi,[board_size]
mov edi,esi
add edi,edx
mov ecx,[board_size]
sub ecx,board1-board
inc ecx
std
rep movsb
cld
 
popa
ret
 
 
from_i dd 0x0
from_len dd 0x0
 
message dd 0x0
message_len dd 0x0
 
read_file: ; start of execution
 
mov [fileinfo+16],eax
shl ebx, 9
mov [fileinfo+12],ebx
mov [file_type],unk
mov [type_len],unkl-unk
mov [filename+40*2+6],dword 'UNK '
 
cmp [input_text+256+1],dword 'POST'
je yes_new_message
 
cmp [input_text+256+11],dword 'oard' ; server board message
jne no_server_message_2
 
yes_new_message:
 
mov eax,70
mov ebx,filel
mcall
mov [board_size],ebx
 
cmp [input_text+256+1],dword 'POST'
jne no_new_message
 
mov edi,bsmt
call set_time
mov edi,bsmd
call set_date
 
call check_for_incoming_data
 
mov esi,input_text+256 ; from
newfroms:
inc esi
cmp esi,input_text+256*20
je no_server_message_2
cmp [esi],dword 'from'
jne newfroms
 
add esi,5
mov [from_i],esi
 
mov edx,0
name_new_len:
cmp [esi+edx],byte 13
je name_found_len
cmp [esi+edx],byte '&'
je name_found_len
cmp edx,1000
je name_found_len
inc edx
jmp name_new_len
 
name_found_len:
 
mov [from_len],edx
 
mov esi,input_text+256
newmessages:
inc esi
cmp esi,input_text+256*20
je no_server_message_2
cmp [esi],dword 'sage'
jne newmessages
 
add esi,5
mov [message],esi
 
mov edx,0
new_len:
inc edx
cmp [esi+edx],byte ' '
je found_len
cmp [esi+edx],byte 13
jbe found_len
cmp edx,input_text+5000
je found_len
jmp new_len
found_len:
mov [message_len],edx
 
 
mov edx,0
 
change_letters:
 
cmp [esi+edx],byte '+'
jne no_space
mov [esi+edx],byte ' '
no_space:
 
cmp [esi+edx+1],word '0D'
jne no_br
mov [esi+edx],dword '<br>'
mov [esi+edx+4],word ' '
no_br:
 
cmp [esi+edx],byte '%'
jne no_ascii
movzx eax,byte [esi+edx+2]
sub eax,48
cmp eax,9
jbe eax_ok
sub eax,7
eax_ok:
movzx ebx,byte [esi+edx+1]
sub ebx,48
cmp ebx,9
jbe ebx_ok
sub ebx,7
ebx_ok:
imul ebx,16
add ebx,eax
mov [esi+edx],bl
mov [esi+edx+1],word ''
add edx,2
no_ascii:
 
inc edx
cmp edx,[message_len]
jbe change_letters
 
 
mov edx,board1e-board1 + board2e-board2 + board3e-board3
add edx,[from_len]
add edx,[message_len]
 
add [board_size],edx
 
mov ecx,edx
call make_room
 
 
mov esi,board1 ; first part
mov edi,0x20000
add edi,board1-board
mov ecx,edx
cld
rep movsb
 
mov esi,[from_i] ; name
mov edi,0x20000
add edi,board1-board
add edi,board1e-board1
mov ecx,[from_len]
cld
rep movsb
 
mov esi,board2 ; middle part
mov edi,0x20000
add edi,board1-board + board1e-board1
add edi,[from_len]
mov ecx,board2e-board2
cld
rep movsb
 
mov esi,[message] ; message
mov edi,0x20000
add edi,board1-board + board1e-board1 + board2e-board2
add edi,[from_len]
mov ecx,[message_len]
cld
rep movsb
 
mov esi,board3 ; end part
mov edi,0x20000
add edi,board1-board + board1e-board1 + board2e-board2
add edi,[from_len]
add edi,[message_len]
mov ecx,board3e-board3
cld
rep movsb
 
inc [board_messages]
 
mov eax,[board_size]
mov [files+12],eax
 
mov eax,70
mov ebx,files
mcall
 
no_new_message:
mov esi,0x20000
mov edi,0x100000
mov ecx,[board_size]
cld
rep movsb
mov ebx,[board_size]
 
mov [file_type],htm
mov [type_len],html-htm
mov [filename+40*2+6],dword 'HTM '
 
jmp file_loaded
no_server_message_2:
 
cmp [input_text+256+9],dword 'ySta' ; server message
jne no_server_message_1
mov edi,smt
call set_time
mov edi,smd
call set_date
mov eax,[documents_served]
mov ecx,9
mov edi,sms+21
call set_value
mov eax,[bytes_transferred]
mov ecx,9
mov edi,smb+21
call set_value
mov eax,[board_messages]
mov ecx,9
mov edi,smm+21
call set_value
mov eax,[board_size]
mov ecx,9
mov edi,smz+21
call set_value
mov esi,sm
mov edi,0x100000
mov ecx,sme-sm
cld
rep movsb
mov ebx,sme-sm
 
mov [file_type],htm
mov [type_len],html-htm
mov [filename+40*2+6],dword 'HTM '
 
jmp file_loaded
no_server_message_1:
 
mov esi,input_text+256+6
cmp [input_text+256+1],dword 'GET '
jne no_new_let
mov edi,wanted_file
cld
new_let:
cmp [esi],byte ' '
je no_new_let
cmp edi,wanted_file+30
jge no_new_let
movsb
jmp new_let
no_new_let:
mov [edi+0],dword 0
mov [edi+4],dword 0
mov [edi+8],dword 0
 
cmp esi,input_text+256+6
jne no_index
mov edi,wanted_file
mov [edi+0],dword 'inde'
mov [edi+4],dword 'x.ht'
mov [edi+8],byte 'm'
mov [edi+9],byte 0
add edi,9
 
mov [file_type],htm
mov [type_len],html-htm
mov [filename+40*2+6],dword 'HTM '
 
jmp html_file
no_index:
 
cmp [edi-3],dword 'htm'+0
je htm_header
cmp [edi-3],dword 'HTM'+0
je htm_header
jmp no_htm_header
htm_header:
mov [file_type],htm
mov [type_len],html-htm
mov [filename+40*2+6],dword 'HTM '
jmp found_file_type
no_htm_header:
 
cmp [edi-3],dword 'png'+0
je png_header
cmp [edi-3],dword 'PNG'+0
je png_header
jmp no_png_header
png_header:
mov [file_type],png
mov [type_len],pngl-png
mov [filename+40*2+6],dword 'PNG '
jmp found_file_type
no_png_header:
 
cmp [edi-3],dword 'gif'+0
je gif_header
cmp [edi-3],dword 'GIF'+0
je gif_header
jmp no_gif_header
gif_header:
mov [file_type],gif
mov [type_len],gifl-gif
mov [filename+40*2+6],dword 'GIF '
jmp found_file_type
no_gif_header:
 
cmp [edi-3],dword 'jpg'+0
je jpg_header
cmp [edi-3],dword 'JPG'+0
je jpg_header
jmp no_jpg_header
jpg_header:
mov [file_type],jpg
mov [type_len],jpgl-jpg
mov [filename+40*2+6],dword 'JPG '
jmp found_file_type
no_jpg_header:
 
cmp [edi-3],dword 'asm'+0
je txt_header
cmp [edi-3],dword 'ASM'+0
je txt_header
cmp [edi-3],dword 'txt'+0
je txt_header
cmp [edi-3],dword 'TXT'+0
je txt_header
jmp no_txt_header
txt_header:
mov [file_type],txt
mov [type_len],txtl-txt
mov [filename+40*2+6],dword 'TXT '
jmp found_file_type
no_txt_header:
 
html_file:
 
found_file_type:
 
mov edi,getf
add edi,[getflen]
mov esi,wanted_file
mov ecx,40
cld
rep movsb
 
mov esi,getf
mov edi,filename
mov ecx,35
cld
rep movsb
 
mov [fileinfo+12],dword 1 ; file exists ?
mov eax,70
mov ebx,fileinfo
mcall
 
cmp eax,0 ; file not found - message
je file_found
mov edi,et
call set_time
mov edi,ed
call set_date
mov esi,fnf
mov edi,0x100000
mov ecx,fnfe-fnf
cld
rep movsb
mov ebx,fnfe-fnf
 
mov [file_type],htm
mov [type_len],html-htm
mov [filename+40*2+6],dword 'HTM '
 
jmp file_not_found
 
file_found:
 
mov [fileinfo+12],dword 0x2f0000 ; read all of file
mov eax,70
mov ebx,fileinfo
mcall
 
file_not_found:
file_loaded:
 
and ebx,0x3fffff
mov [filesize],ebx
mov [file_left],ebx
 
mov eax,ebx
mov edi,c_l+5
mov ebx,10
newl:
xor edx,edx
div ebx
mov ecx,edx
add cl,48
mov [edi],cl
dec edi
cmp edi,c_l
jge newl
 
mov esi,c_l
mov edi,filename+46
mov ecx,7
cld
rep movsb
 
inc [documents_served]
mov eax,[filesize]
add [bytes_transferred],eax
 
call draw_data
 
ret
 
 
set_value:
 
pusha
 
add edi,ecx
mov ebx,10
new_value:
xor edx,edx
div ebx
add dl,48
mov [edi],dl
dec edi
loop new_value
 
popa
ret
 
 
set_time:
 
pusha
 
mov eax,3
mcall
 
mov ecx,3
new_time_digit:
mov ebx,eax
and ebx,0xff
shl ebx,4
shr bl,4
add bx,48*256+48
mov [edi],bh
mov [edi+1],bl
add edi,3
shr eax,8
loop new_time_digit
 
popa
ret
 
 
 
set_date:
 
pusha
 
mov eax,29
mcall
 
mov ecx,3
add edi,6
new_date_digit:
mov ebx,eax
and ebx,0xff
shl ebx,4
shr bl,4
add bx,48*256+48
mov [edi],bh
mov [edi+1],bl
sub edi,3
shr eax,8
loop new_date_digit
 
popa
ret
 
 
 
check_for_incoming_data:
 
pusha
 
check:
 
mov eax, 53
mov ebx, 2
mov ecx, [socket]
mcall
 
cmp eax,0
je _ret_now
 
new_data:
 
mov eax,53
mov ebx,2
mov ecx,[socket]
mcall
 
cmp eax,0
je _ret
 
mov eax,53
mov ebx,3
mov ecx,[socket]
mcall
 
cmp bl,10
jne no_lf
inc [posy]
mov [posx],0
jmp new_data
no_lf:
 
cmp bl,20
jb new_data
 
inc [posx]
cmp [posy],20
jbe yok
mov [posy],1
yok:
 
mov eax,[posy]
imul eax,256
add eax,[posx]
 
mov [input_text+eax],bl
 
jmp new_data
 
_ret:
 
call draw_data
 
mov eax,5
mov ebx,1
cmp [input_text+256+1],dword 'POST'
jne no_ld
mov ebx,50
no_ld:
mcall
 
jmp check
 
_ret_now:
 
popa
ret
 
 
posy dd 1
posx dd 0
 
 
check_status:
 
pusha
 
mov eax,53
mov ebx,6
mov ecx,[socket]
mcall
 
cmp eax,[status]
je c_ret
mov [status],eax
add al,48
mov [text+12],al
call draw_data
c_ret:
 
popa
ret
 
 
addr dd 0x0
ya dd 0x0
 
filename2: times 100 db 32
 
read_string:
 
mov [addr],dword getf
mov [ya],dword 139
 
mov edi,[addr]
mov eax,0
mov ecx,30
cld
rep stosb
 
call print_text
 
mov edi,[addr]
 
f11:
mov eax,10
mcall
cmp eax,2
jne read_done
mov eax,2
mcall
shr eax,8
cmp eax,13
je read_done
cmp eax,8
jnz nobsl
cmp edi,[addr]
jz f11
sub edi,1
mov [edi],byte 32
call print_text
jmp f11
nobsl:
mov [edi],al
 
call print_text
 
add edi,1
mov esi,[addr]
add esi,30
cmp esi,edi
jnz f11
 
read_done:
 
push edi
 
mov ecx,40
mov eax,32
cld
rep stosb
 
call print_text
 
pop edi
sub edi,[addr]
mov [getflen],edi
 
mov esi,getf
mov edi,dirp+12
mov ecx,28
cld
rep movsb
 
jmp still
 
 
print_text:
 
pusha
 
mov eax,4
mov edx,[addr]
mov ebx,97*65536
add ebx,[ya]
mov ecx,0x40000000
mov esi,23
mov edi,0xffffff
mcall
 
popa
ret
 
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
 
draw_window:
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
 
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,100*65536+480 ; [x start] *65536 + [x size]
mov ecx,100*65536+215 ; [y start] *65536 + [y size]
mov edx,0x14ffffff ; color of work area RRGGBB
mov edi,title ; WINDOW LABEL
mcall
 
mov eax,8 ; function 8 : define and draw button
mov ebx,(40)*65536+20 ; [x start] *65536 + [x size]
mov ecx,59*65536+9 ; [y start] *65536 + [y size]
mov edx,2 ; button id
mov esi,0x66aa66 ; button color RRGGBB
mcall
 
; function 8 : define and draw button
mov ebx,(40)*65536+20 ; [x start] *65536 + [x size]
mov ecx,72*65536+9 ; [y start] *65536 + [y size]
mov edx,4 ; button id
mov esi,0xaa6666 ; button color RRGGBB
mcall
 
; Enter directory
mov ebx,(25)*65536+66
mov ecx,135*65536+15
mov edx,6
mov esi,0x3388dd
mcall
 
mov eax,38
mov ebx,240*65536+240
mov ecx,22*65536+210
mov edx,0x6699cc ; 002288
mcall
 
 
mov ebx,241*65536+241
mov ecx,22*65536+210
mov edx,0x336699 ; 002288
mcall
 
call draw_data
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
 
ret
 
 
draw_data:
 
pusha
 
mov ebx,25*65536+35 ; draw info text with function 4
mov ecx,0x000000
mov edx,text
mov esi,35
newline:
pusha
cmp ebx,25*65536+61
je now
cmp ebx,25*65536+74
je now
cmp ebx,25*65536+74+13*5
je now
mov ecx,ebx
mov bx,35*6
shl ecx,16
mov cx,9
mov edx,0xffffff
mov eax,13
mcall
now:
popa
mov eax,4
mcall
add ebx,13
add edx,40
cmp [edx],byte 'x'
jnz newline
 
mov [input_text+0],dword 'RECE'
mov [input_text+4],dword 'IVED'
mov [input_text+8],dword ': '
 
mov ebx,255*65536+35 ; draw info text with function 4
mov ecx,0x000000
mov edx,input_text
mov esi,35
mov edi,17
newline2:
pusha
mov ecx,ebx
mov bx,35*6
shl ecx,16
mov cx,9
mov eax,13
mov edx,0xffffff
mcall
popa
mov eax,4
mcall
add ebx,10
add edx,256
dec edi
jnz newline2
 
popa
 
ret
 
 
; DATA AREA
 
status dd 0x0
 
text:
db 'TCB status: x '
db ' '
db ' Activate server '
db ' Stop server '
db ' '
db 'Requests: /TinyStat -statistics '
db ' /TinyBoard -message board '
db ' '
dirp:
db ' Files: /sys/ '
db ' '
filename:
db ' '
db 'Size: ------- '
db 'Type: --- '
db 'x' ; <- END MARKER, DONT DELETE
 
 
html_header:
 
db 'HTTP/1.0 200 OK',13,10
db 'Server: KolibriOS HTTP Server',13,10
db 'Content-Length: '
c_l: db '000000',13,10
 
h_len:
 
fnf:
db '<body>'
db '<pre>'
db "HTTP-Ñåðâåð v ",version," äëÿ KolibriOS",13,10,13,10
db "<H1>Error <FONT color=red>404</FONT> - File not found</H1>",13,10,13,10
db "Äëÿ ïîëó÷åíèÿ ñòàòèñòèêè âûïîëíèòå çàïðîñ /TinyStat",13,10,13,10
et: db "xx:xx:xx",13,10
ed: db "xx.xx.xx",13,10
db "</pre></body>"
fnfe:
 
 
sm:
db '<body>'
db '<pre>'
db "HTTP-Ñåðâåð v ",version," äëÿ KolibriOS",13,10,13,10
db "Ñòàòèñòèêà: (ïîñëå äàííîãî çàïðîñà)",13,10,13,10
sms: db "- Äîêóìåíòîâ ïðèíÿòî: xxxxxxxxx",13,10
smb: db "- Áàéò ïåðåäàííî : xxxxxxxxx",13,10
db "- Ìåñòîíàõîæäåíèå : <a href=/TinyStat>Ñòàòèñòèêà</a>",13,10,13,10
db "Ãîñòåâàÿ:",13,10,13,10
smm: db "- Ñîîáùåíèé : xxxxxxxxx",13,10
smz: db "- Ðàçìåð â áàéòàõ : xxxxxxxxx",13,10
db "- Ìåñòîíàõîæäåíèå : <a href=/TinyBoard>Ãîñòåâàÿ</a>",13,10,13,10
smt: db "xx:xx:xx",13,10
smd: db "xx.xx.xx",13,10
db '</pre></body>'
sme:
 
documents_served dd 0x0
bytes_transferred dd 0x0
 
file_type dd 0
type_len dd 0
 
htm: db 'Content-Type: text/html',13,10,13,10
html:
txt: db 'Content-Type: text/plain',13,10,13,10
txtl:
png: db 'Content-Type: image/png',13,10,13,10
pngl:
gif: db 'Content-Type: image/gif',13,10,13,10
gifl:
jpg: db 'Content-Type: image/jpeg',13,10,13,10
jpgl:
unk: db 'Content-Type: unknown/unknown',13,10,13,10
unkl:
 
 
title db appname,version,0
 
socket dd 0x0
server_active db 0x0
 
board:
 
db "<HTML><HEAD><TITLE>INTKolibriOS - /Ãîñòåâàÿ/</TITLE></HEAD>",13,10
db "<BODY background=bgnd.gif BGCOLOR=#ffffff ALINK=black VLINK=black><br>",13,10
db "<center>",13,10
db "<TABLE CELLPADDING=10 CELLSPACING=0 BORDER=0 bgcolor=#ffffff width=600>"
db 13,10
db "<TR VALIGN=top><TD ALIGN=center bgcolor=F4F4F4>",13,10
db "<font size=4>Ãîñòåâàÿ ñåðâåðà INTKolibriOS</TD></TR></TABLE><br>",13,10
db "<TABLE CELLPADDING=14 CELLSPACING=2 BORDER=0 bgcolor=#ffffff width=600>"
db 13,10,13,10
 
board1:
 
db "<TR VALIGN=top>",13,10
db "<TD ALIGN=left width=80 bgcolor=F4F4F4><P>",13,10
db "<font size=3>",13,10
board1e:
db "Hex",13,10
board2:
db "</font>",13,10
db "<br><br><br>",13,10
db "<br><br><br><br>",13,10
bsmt:
db "15.23.45<br>",13,10
bsmd:
db "22.03.06",13,10
db "</P></TD>",13,10
db "<TD bgcolor=F4F4F4><P>",13,10
board2e:
db "Äîáðî ïîæàëîâàòü â ãîñòåâóþ ñåðâåðà INTKolibriOS! (-:<br>"
db 13,10
board3:
db "</P></TD></TR>",13,10,13,10
board3e:
 
boardadd:
 
db "</TABLE>",13,10
db "<br>",13,10
db "<TABLE CELLPADDING=14 CELLSPACING=3 BORDER=0 bgcolor=#ffffff width=600>"
db 13,10
db "<TR VALIGN=top>",13,10
db "<TD ALIGN=left bgcolor=F4F4F4><P>",13,10
db "<form method=Post Action=/TinyBoard>",13,10
db "Èìÿ: <br><input type=text name=from size=20 MAXLENGTH=20><br>",13,10
db "Ñîîáùåíèå: <br><textarea cols=60 rows=6 name=message></textarea><br>",13,10
db "<input type=Submit Value=' Îòïðàâèòü ñîîáùåíèå '></form>",13,10
db "</TD></TR>",13,10
db "</TABLE>",13,10
db "</BODY>",13,10
db "</HTML>",13,10
 
board_end:
 
board_size dd 0x0
board_messages dd 0x0
 
input_text:
 
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/https/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm https.asm https
@erase lang.inc
@pause
/programs/network_old/https/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm https.asm https
@erase lang.inc
@pause
/programs/network_old/stackcfg/trunk/stackcfg.asm
0,0 → 1,701
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Stack Configuration Tool ;
; ;
; Compile with FASM for Menuet ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
memsize = 100000h
org 0
PARAMS = memsize - 1024
 
use32
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image
dd memsize ; memory for app
dd memsize - 1024 ; esp
dd PARAMS , 0x0 ; I_Param , I_Icon
 
include 'lang.inc'
include '../../../macros.inc'
 
START: ; start of execution
 
read_stack_setup:
 
mov eax,52
mov ebx,0
mcall
mov [config],eax
 
mov eax,52
mov ebx,1
mcall
mov dword [ip_address],eax
 
mov eax,52
mov ebx,9
mcall
mov dword [gateway_ip],eax
 
mov eax,52
mov ebx,10
mcall
mov dword [subnet_mask],eax
 
mov eax,52
mov ebx,13
mcall
mov dword [dns_ip],eax
 
mov eax,[config] ; unwrap com IRQ
shr eax,8
and eax,0xf
mov [com_irq],eax
 
mov eax,[config] ; unwrap com PORT
shr eax,16
and eax,0xfff
mov [com_add],eax
 
mov eax,[config] ; unwrap IRQ
and eax,0xf
mov [interface],eax
 
mov eax,[config] ; unwrap com PORT
shr eax,7
and eax,1
mov [assigned],eax
 
red:
call draw_window ; at first, draw the window
 
still:
 
mov eax,10 ; wait here for event
mcall
 
cmp eax,1 ; redraw request ?
jz red
cmp eax,2 ; key in buffer ?
jnz button
 
key: ; key
; mov al,2 ; just read it and ignore
mcall
jmp still
 
button: ; button
mov al,17 ; get id
mcall
 
shr eax,8
 
dec eax ; button id=1 ?
jne noclose
or eax,-1 ; close this program
mcall
noclose:
 
dec eax
je read_stack_setup
 
dec eax
jne no_apply_stack_setup
call apply_stack_setup
jmp still
 
no_apply_stack_setup:
dec eax ; GET COM PORT
dec eax
jne no_read_comport
mov [string_x],272
mov [string_y],40
mov [string_length],3
call read_string
movzx eax,byte [string]
cmp eax,'A'
jb gcp1
sub eax,'A'-'9'-1
gcp1:
sub eax,48
shl eax,8
mov ebx,eax
movzx eax,byte [string+1]
cmp eax,'A'
jb gcp2
sub eax,'A'-'9'-1
gcp2:
sub eax,48
shl eax,4
add ebx,eax
movzx eax,byte [string+2]
cmp eax,'A'
jb gcp3
sub eax,'A'-'9'-1
gcp3:
sub eax,48
add ebx,eax
mov [com_add],ebx
jmp red
no_read_comport:
 
dec eax ; GET COM IRQ
jne no_read_comirq
mov [string_x],284
mov [string_y],50
mov [string_length],1
call read_string
movzx eax,byte [string]
cmp eax,'A'
jb gci1
sub eax,'A'-'9'-1
gci1:
sub eax,48
mov [com_irq],eax
jmp red
no_read_comirq:
 
dec eax ; GET IP
jne no_read_ip
mov [string_x],205
mov [string_y],80
mov [string_length],15
call read_string
mov esi,string-1
mov edi,ip_address
ip0:
xor eax,eax
ip1:
inc esi
cmp [esi],byte '0'
jb ip2
cmp [esi],byte '9'
jg ip2
imul eax,10
movzx ebx,byte [esi]
sub ebx,48
add eax,ebx
jmp ip1
ip2:
stosb
cmp edi,ip_address+3
jbe ip0
jmp red
no_read_ip:
 
dec eax ; set gateway ip
jne no_set_gateway
 
mov [string_x],205
mov [string_y],90
mov [string_length],15
call read_string
mov esi,string-1
mov edi,gateway_ip
gip0:
xor eax,eax
gip1:
inc esi
cmp [esi],byte '0'
jb gip2
cmp [esi],byte '9'
jg gip2
imul eax,10
movzx ebx,byte [esi]
sub ebx,48
add eax,ebx
jmp gip1
gip2:
stosb
cmp edi,gateway_ip+3
jbe gip0
jmp red
 
no_set_gateway:
 
dec eax
jne no_set_subnet
 
mov [string_x],205
mov [string_y],100
mov [string_length],15
call read_string
mov esi,string-1
mov edi,subnet_mask
sip0:
xor eax,eax
sip1:
inc esi
cmp [esi],byte '0'
jb sip2
cmp [esi],byte '9'
jg sip2
imul eax,10
movzx ebx,byte [esi]
sub ebx,48
add eax,ebx
jmp sip1
sip2:
stosb
cmp edi,subnet_mask+3
jbe sip0
jmp red
 
no_set_subnet:
dec eax
jne no_set_dns
 
mov [string_x],205
mov [string_y],110
mov [string_length],15
call read_string
mov esi,string-1
mov edi,dns_ip
dip0:
xor eax,eax
dip1:
inc esi
cmp [esi],byte '0'
jb dip2
cmp [esi],byte '9'
jg dip2
imul eax,10
movzx ebx,byte [esi]
sub ebx,48
add eax,ebx
jmp dip1
dip2:
stosb
cmp edi,dns_ip+3
jbe dip0
jmp red
 
no_set_dns:
 
dec eax
jb no_set_interface
cmp eax,14-11
ja no_set_interface
mov [interface],eax
jmp red
no_set_interface:
 
sub eax,21-11
jb no_ip_sf
cmp eax,22-21
ja no_ip_sf
xor eax,1
mov [assigned],eax
jmp red
no_ip_sf:
jmp still
 
apply_stack_setup:
 
mov eax,[com_irq]
shl eax,8
mov ebx,[com_add]
shl ebx,16
add eax,ebx
add eax,[interface]
mov ebx,[assigned]
shl ebx,7
add eax,ebx
mov [config],eax
 
mov eax,52
mov ebx,3
mov ecx,dword [ip_address]
mcall
 
mov eax,52
mov ebx,11
mov ecx,dword [gateway_ip]
mcall
 
mov eax,52
mov ebx,12
mov ecx,dword [subnet_mask]
mcall
 
mov eax,52
mov ebx,14
mov ecx,dword [dns_ip]
mcall
 
mov eax,52
mov ebx,2
mov ecx,[config]
mcall
 
ret
 
 
string_length dd 16
string_x dd 200
string_y dd 60
 
string db '________________'
 
 
read_string:
 
mov edi,string
mov eax,'_'
mov ecx,[string_length]
cld
rep stosb
call print_text
 
mov edi,string
f11:
mov eax,10
mcall
cmp eax,2
jne read_done
; mov eax,2
mcall
shr eax,8
cmp eax,13
je read_done
cmp eax,8
jnz nobsl
cmp edi,string
jz f11
sub edi,1
mov [edi],byte '_'
call print_text
jmp f11
nobsl:
cmp eax,dword 31
jbe f11
cmp eax,dword 95
jb keyok
sub eax,32
keyok:
mov [edi],al
call print_text
 
inc edi
mov esi,string
add esi,[string_length]
cmp esi,edi
jnz f11
 
read_done:
 
print_text:
 
pusha
 
mov eax,13
mov ebx,[string_x]
shl ebx,16
add ebx,[string_length]
imul bx,6
mov ecx,[string_y]
shl ecx,16
mov cx,8
mov edx,0xffffff
mcall
 
mov eax,4
mov ebx,[string_x]
shl ebx,16
add ebx,[string_y]
mov ecx,0x000000
mov edx,string
mov esi,[string_length]
mcall
 
popa
ret
 
 
 
 
 
 
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
 
draw_window:
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
 
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,100*65536+330 ; [x start] *65536 + [x size]
mov ecx,100*65536+157 ; [y start] *65536 + [y size]
mov edx,0x14ffffff ; color of work area RRGGBB,8->color gl
mov edi,title ; WINDOW LABEL
mcall
 
 
mov eax,8 ; BUTTON : READ SETUP
mov ebx,90*65536+65
mov ecx,127*65536+12
mov edx,2
mov esi,[button_color]
mcall
 
;mov eax,8 ; BUTTON : APPLY SETUP
mov ebx,163*65536+65
mov ecx,127*65536+12
mov edx,3
mcall
 
;mov eax,8 ; BUTTONS 11-14 : SELECT INTERFACE
mov ebx,29*65536+8
mov ecx,39*65536+8
mov edx,11
interface_select:
mcall
add ecx,10*65536
inc edx
cmp edx,11+4
jb interface_select
 
mov ebx,[interface] ; PRINT SELECTED INTERFACE 'X'
imul ebx,10
add ebx,31*65536+39
mov eax,4
mov ecx,0xffffff
mov edx,xx
mov esi,1
mcall
 
mov eax,8 ; BUTTONS 21-22 : SERVER / MANUAL IP
mov ebx,143*65536+8
mov ecx,69*65536+8
mov edx,21
mov esi,[button_color]
mcall
;mov eax,8
mov ebx,143*65536+8
mov ecx,79*65536+8
mov edx,22
mcall
mov ebx,[assigned] ; PRINT SELECTED SERVER/MANUAL 'X'
not ebx
and ebx,1
imul ebx,10
add ebx,145*65536+69
mov eax,4
mov ecx,0xffffff
mov edx,xx
mov esi,1
mcall
 
mov eax,47 ; COM ADDRESS
mov ebx,3*65536+1*256
mov ecx,[com_add]
mov edx,272*65536+40
mov esi,0x000000
mcall
 
;mov eax,47 ; COM IRQ
mov ebx,1*65536+1*256
mov ecx,[com_irq]
mov edx,(266+3*6)*65536+50
mov esi,0x000000
mcall
 
mov edi,ip_address
mov edx,205*65536+80
mov esi,0x000000
mov ebx,3*65536
ipdisplay:
;mov eax,47
movzx ecx,byte [edi]
mcall
add edx,6*4*65536
inc edi
cmp edi,ip_address+4
jb ipdisplay
 
mov edi,gateway_ip
mov edx,205*65536+90
mov esi,0x000000
mov ebx,3*65536
gipdisplay:
;mov eax,47
movzx ecx,byte [edi]
mcall
add edx,6*4*65536
inc edi
cmp edi,gateway_ip+4
jb gipdisplay
 
mov edi,subnet_mask
mov edx,205*65536+100
mov esi,0x000000
mov ebx,3*65536
sipdisplay:
;mov eax,47
movzx ecx,byte [edi]
mcall
add edx,6*4*65536
inc edi
cmp edi,subnet_mask+4
jb sipdisplay
 
mov edi,dns_ip
mov edx,205*65536+110
mov esi,0x000000
mov ebx,3*65536
dipdisplay:
;mov eax,47
movzx ecx,byte [edi]
mcall
add edx,6*4*65536
inc edi
cmp edi,dns_ip+4
jb dipdisplay
 
 
mov eax,8 ; BUTTON 5 : SET PORT
mov ebx,299*65536+8
mov ecx,39*65536+8
mov edx,5
mov esi,[button_color]
mcall
;mov eax,8 ; BUTTON 6 : SET IRQ
mov ecx,49*65536+8
inc edx
mcall
;mov eax,8 ; BUTTON 7 : SET IP
mov ecx,79*65536+8
inc edx
mcall
 
;mov eax,8 ; BUTTON 8 : SET gateway IP
mov ebx,299*65536+8
mov ecx,89*65536+8
inc edx
mcall
 
;mov eax,8 ; BUTTON 9 : SET subnet
mov ecx,99*65536+8
inc edx
mcall
 
;mov eax,8 ; BUTTON 10 : SET dns ip
mov ecx,109*65536+8
inc edx
mcall
 
mov ebx,31*65536+40 ; draw info text with function 4
mov edx,text
mov esi,49
mov eax,4
newline:
mov ecx,0x224466
cmp [edx],byte 'w'
jne nowhite
mov ecx,0xeeeeee
nowhite:
inc edx
mcall
add ebx,10
add edx,49
cmp [edx],byte 'x'
jne newline
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
 
ret
 
 
; DATA AREA
 
if lang eq ru
title db ' áâனª  á¥â¥¢®£® á⥪ ',0
text:
db ' ¥ ªâ¨¢­ë© Œ®¤¥¬ ­  Com-¯®àâã: 0x < '
db ' Slip à¥à뢠­¨¥ ¬®¤¥¬ : 0x < '
db ' PPP '
db ' „à ©¢¥à ¯ ª¥â®¢ IP ­ §­ ç ¥âáï á¥à¢¥à®¬ '
db ' (Ethernet) ”¨ªá.: . . . < '
db ' ˜«î§: . . . < '
db ' ®¤á¥âì: . . . < '
db ' DNS IP: . . . < '
db ' '
db 'w —¨â âì à¨¬¥­¨âì '
 
else if lang eq nl
title db 'Netwerk configuratie',0
text:
db ' Niet actief Modem Com Poort: 0x < '
db ' Slip Modem Com Irq: 0x < '
db ' PPP '
db ' Pakket Driver Door IP-server toegekend '
db ' (Ethernet) Vast IP: . . . < '
db ' Gateway: . . . < '
db ' Subnet: . . . < '
db ' DNS IP: . . . < '
db ' '
db 'w Vernieuw Toepassen '
 
else if lang eq ua
title db ' « èâ㢠­­ï ¬¥à¥¦i'
text:
db ' ¥ ªâ¨¢­¨© Œ®¤¥¬ ­  Com-¯®àâã 0x < '
db ' Slip Com-¯®àâ ¬®¤¥¬ : 0x < '
db ' PPP '
db ' „à ©¢¥à ¯ ª¥âi¢ IP ¯à¨§­ ç óâìáï á¥à¢¥à®¬ '
db ' (Ethernet) ”iªá.: . . . < '
db ' Œ àèàãâ: . . . < '
db ' Œ áª : . . . < '
db ' DNS IP . . . < '
db ' '
db 'w à®ç¨â â¨ ‡ áâ®á㢠⨠'
 
else
title db 'Stack configuration',0
text:
db ' Not active Modem Com Port: 0x < '
db ' Slip Modem Com Irq: 0x < '
db ' PPP '
db ' Packet Driver IP server assigned '
db ' (Ethernet) Fixed: . . . < '
db ' Gateway: . . . < '
db ' Subnet: . . . < '
db ' DNS IP: . . . < '
db ' '
db 'w READ APPLY '
end if
 
xx: db 'x' ;<- END MARKER, DONT DELETE
 
button_color dd 0x2254b9
 
 
 
ip_address dd ?
gateway_ip dd ?
subnet_mask dd ?
dns_ip dd ?
 
 
com_irq dd ? ; irq for slip/ppp
com_add dd ? ; com port address for slip/ppp
interface dd ? ; not active,slip,ppp,packet driver
assigned dd ? ; get ip from server
 
config dd ?
 
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/stackcfg/trunk/readme.txt
0,0 → 1,11
Ïðîãðàììà äëÿ íàñòðîéê ñåòåâûõ ïàðàìåòðîâ
28.10.06 Heavyiron
Äîáàâëåí ïàðàìåòð BOOT
Òåïåðü ìîæíî â èñõîäíèê âáèòü íóæíûå IP, ìàñêó, øëþç è DNS, ïåðåêîìïèëëèðîâàòü ïðîãðàììó è çàêèíóòü åå â àâòîçàãðóçêó. Ñëåäîâàòåëüíî ýòè íàñòðîéêè íå ïðèäåòñÿ êàæäûé ðàç âáèâàòü âðó÷íóþ.
 autorun.dat íåîáõîäèìî ïîìåñòèòü,íàïðèìåð, òàêóþ ñòðîêó:
/sys/stackcfg BOOT 30 # Set yor network settings,
íå çàáûâ ïðè ýòîì óâåëè÷èòü êîëè÷åñòâî çàïóñêàåìûõ ïðîãðàìì íà îäíó
â ñàìîì íà÷àëå ôàéëà autorun.dat.
 
TODO:
ñäåëàòü ÷òåíèå íàñòðîåê èç ôàéëà network.dat, ÷òîáû íå òðåáîâàëàñü ïåðåêîìïèëëÿöèÿ äëÿ èçìåíåíèÿ íàñòðîåê.
/programs/network_old/stackcfg/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm stackcfg.asm stackcfg
@erase lang.inc
@pause
/programs/network_old/stackcfg/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm stackcfg.asm stackcfg
@erase lang.inc
@pause
/programs/network_old/terminal/trunk/terminal.asm
0,0 → 1,727
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; TERMINAL
use32
org 0x0
db 'MENUET01' ; header
dd 0x01 ; header version
dd START ; entry point
dd I_END ; image size
dd I_END+0x10000 ; required memory
dd I_END+0x10000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Path
include 'lang.inc'
include '..\..\..\macros.inc'
START: ; start of execution
call draw_window
call set_variables
still:
mov eax,23 ; wait here for event
mov ebx,20
mcall
cmp eax,1 ; redraw request ?
je red
cmp eax,2 ; key in buffer ?
je key
cmp eax,3 ; button in buffer ?
je button
cmp eax,16+4
je read_input
jmp still
read_input:
mcall 42,4,text+120*80
test eax, eax
jle still
 
read_input_loop:
mov bl,[ecx]
inc ecx
push eax ecx
cmp bl,27 ; ESCAPE COMMAND
jne no_esc
call esc_command
jmp newdata
no_esc:
cmp bl,13 ; BEGINNING OF LINE
jne nobol
mov ecx,[pos]
add ecx,1
boll1:
sub ecx,1
mov eax,ecx
xor edx,edx
mov ebx,80
div ebx
cmp edx,0
jne boll1
mov [pos],ecx
jmp newdata
nobol:
cmp bl,10 ; LINE DOWN
jne nolf
addx1:
add [pos],dword 1
mov eax,[pos]
xor edx,edx
mov ecx,80
div ecx
cmp edx,0
jnz addx1
mov eax,[pos]
jmp cm1
nolf:
cmp bl,8 ; BACKSPACE
jne nobasp
mov eax,[pos]
dec eax
mov [pos],eax
mov [eax+text],byte 32
mov [eax+text+60*80],byte 0
jmp newdata
nobasp:
cmp bl,15 ; CHARACTER
jbe newdata
mov eax,[pos]
call draw_data
mov eax,[pos]
add eax,1
cm1:
mov ebx,[scroll+4]
imul ebx,80
cmp eax,ebx
jb noeaxz
mov esi,text+80
mov edi,text
mov ecx,ebx
cld
rep movsb
mov esi,text+80+60*80
mov edi,text+60*80
mov ecx,ebx
cld
rep movsb
mov eax,ebx
sub eax,80
noeaxz:
mov [pos],eax
newdata:
pop ecx eax
dec eax
jnz read_input_loop
call draw_text
jmp still
red: ; REDRAW WINDOW
call draw_window
jmp still
key: ; KEY
mov eax,2 ; send to modem
mcall
shr eax,8
cmp eax,178 ; ARROW KEYS
jne noaup
mov al,'A'
call arrow
jmp still
noaup:
cmp eax,177
jne noadown
mov al,'B'
call arrow
jmp still
noadown:
cmp eax,179
jne noaright
mov al,'C'
call arrow
jmp still
noaright:
cmp eax,176
jne noaleft
mov al,'D'
call arrow
jmp still
noaleft:
modem_out:
mov dx,0x3f8
out dx,al
jmp still
button: ; BUTTON
mov eax,17
mcall
cmp ah,1 ; CLOSE PROGRAM
jne noclose
mov eax,45 ; FREE IRQ
mov ebx,1
mov ecx,4
mcall
mov eax,46
mov ebx,1
mov ecx,0x3f0
mov edx,0x3ff
mcall
or eax,-1
mcall
noclose:
jmp still
arrow:
push eax
mov al,27
call to_modem
mov al,'['
call to_modem
pop eax
call to_modem
ret
to_modem:
pusha
mov dx,0x3f8
out dx,al
mov eax,5
mov ebx,5
mcall
popa
ret
draw_data:
pusha
cmp bl,0xe4 ; Á
jne noe4
mov bl,0xc1
noe4:
cmp bl,0xc4 ; É
jne noc4
mov bl,0xc9
noc4:
mov [eax+text],bl
mov bl,byte [attribute]
mov [eax+text+60*80],bl
popa
ret
irqtable:
dd 0x3f8 + 0x01000000 ; read port 0x3f8, byte
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
set_variables:
pusha
mov eax,46
mov ebx,0
mov ecx,0x3f0
mov edx,0x3ff
mcall
mov eax,45 ; reserve irq 4
mov ebx,0
mov ecx,4
mcall
mov eax,44
mov ebx,irqtable
mov ecx,4
mcall
; jmp noportint
mov dx,0x3f8+3
mov al,0x80
out dx,al
mov dx,0x3f8+1
mov al,0
out dx,al
mov dx,0x3f8+0
mov al,0x30 / 16
out dx,al
mov dx,0x3f8+3
mov al,3
out dx,al
mov dx,0x3f8+4
mov al,0xB
out dx,al
mov dx,0x3f8+1
mov al,1
out dx,al
noportint:
mov eax,40
mov ebx,0000000000010000b shl 16 + 111b
mcall
popa
ret
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
draw_window:
pusha
mov eax,12
mov ebx,1
mcall
mov eax,0 ; DRAW WINDOW
mov ebx,100*65536+491
mov ecx,100*65536+270
mov edx,0x13000000
mov edi,title
mcall
xor eax,eax
mov edi,text+80*30
mov ecx,80*30 /4
cld
rep stosd
call draw_text
mov eax,12
mov ebx,2
mcall
popa
ret
bgc dd 0x000000
dd 0x000000
dd 0x00ff00
dd 0x0000ff
dd 0x005500
dd 0xff00ff
dd 0x00ffff
dd 0x770077
tc dd 0xffffff
dd 0xff00ff
dd 0xffffff
dd 0xffffff
dd 0xffffff
dd 0xffffff
dd 0xffffff
dd 0xffffff
draw_text:
pusha
mov esi,text
mov eax,0
mov ebx,0
newletter:
mov cl,[esi]
mov dl,[esi+60*80]
cmp cl,[esi+30*80]
jne yesletter
cmp dl,[esi+90*80]
jne yesletter
jmp noletter
yesletter:
mov [esi+30*80],cl
mov [esi+90*80],dl
pusha
and edx,0xff
shl edx,2
add edx,bgc
mov edx,[edx]
mov ecx,ebx
add ecx,26
shl ecx,16
mov cx,9
mov ebx,eax
add ebx,6
shl ebx,16
mov bx,6
mov eax,13
mcall
popa
pusha
and edx,0xff
shl edx,2
add edx,tc
mov ecx,[edx]
push bx
mov ebx,eax
add ebx,6
shl ebx,16
pop bx
add bx,26
mov eax,4
mov edx,esi
mov esi,1
mcall
popa
noletter:
add esi,1
add eax,6
cmp eax,80*6
jb newletter
mov eax,0
add ebx,10
cmp ebx,24*10
jb newletter
popa
ret
esc_command:
mov eax,32
mov edi,esccmd
mov ecx,10
cld
rep stosb
mov edi,esccmd
newescc:
mov eax,42
mov ebx,4
mcall
cmp ecx,0
je escok
mov eax,5
mov ebx,1
mcall
jmp newescc
escok:
mov [edi],bl
add edi,1
cmp edi,esccmd+20
je dontunderstand
mov esi,escend
nec:
cmp bl,[esi]
jz com_ok
add esi,1
cmp [esi],byte 0
je newescc
jmp nec
com_ok:
call get_numbers
cmp bl,'H' ; SET CURSOR POSITION
jne no_cursor_position
cmp [escnumbers],0
jne ncp1
mov [pos],dword 0
jmp cmd_done
ncp1:
mov eax,[escnumbers]
dec eax
imul eax,80
add eax,[escnumbers+4]
dec eax
mov [pos],eax
jmp cmd_done
no_cursor_position:
cmp bl,'K' ; ERASE LINE
jne no_erase_end_of_line
cmp [escnumbers],0
jne no_end_line
mov ecx,[pos]
eeol:
mov [ecx+text],byte ' '
mov [ecx+text+60*80],byte 0
add ecx,1
xor edx,edx
mov eax,ecx
mov ebx,80
div ebx
cmp edx,0
jne eeol
jmp cmd_done
no_end_line:
cmp [escnumbers],1 ; BEGINNING OF LINE
jne no_beg_line
mov ecx,[pos]
ebol:
mov [ecx+text],byte ' '
mov [ecx+text+60*80],byte 0
sub ecx,1
xor edx,edx
mov eax,ecx
mov ebx,80
div ebx
cmp edx,0
jne ebol
mov [pos],ecx
jmp cmd_done
no_beg_line:
no_erase_end_of_line:
cmp bl,'J' ; ERASE TO END OF SCREEN
jne no_erase_to_end_of_screen
cmp [escnumbers],dword 0
jne no_erase_to_end_of_screen
mov ecx,[pos]
eteos:
mov [ecx+text],byte ' '
mov [ecx+text+60*80],byte 0
add ecx,1
cmp ecx,80*24+1
jb eteos
jmp cmd_done
no_erase_to_end_of_screen:
cmp bl,'r' ; SET SCROLL REGION
jne no_scroll_region
mov eax,[escnumbers]
dec eax
mov [scroll+0],eax
mov eax,[escnumbers+4]
mov [scroll+4],eax
jmp cmd_done
no_scroll_region:
cmp bl,'A' ; CURSOR UP
jne no_cursor_up
mov eax,[pos]
sub eax,80
mov [pos],eax
jmp cmd_done
no_cursor_up:
cmp bl,'C' ; CURSOR LEFT
jne no_cursor_left
mov eax,[pos]
mov ebx,[escnumbers]
sub eax,ebx
mov [pos],eax
call cmd_done
no_cursor_left:
cmp bl,'m' ; CHARACTER ATTRIBUTE
jne no_char_attribute
mov eax,[escnumbers]
mov [attribute],eax
jmp cmd_done
no_char_attribute:
cmp bl,'Z' ; TERMINAL TYPE
jne no_terminal_type
mov al,27
call to_modem
mov al,'?'
call to_modem
mov al,'1'
call to_modem
mov al,';'
call to_modem
mov al,'0'
call to_modem
mov al,'c'
call to_modem
jmp cmd_done
no_terminal_type:
dontunderstand:
cmd_done:
ret
draw_numbers:
pusha
mov eax,13
mov ebx,250*65536+100
mov ecx,8*65536+8
mov edx,0x000000
mcall
mov eax,[escnumbers]
xor edx,edx
mov ebx,10
div ebx
add eax,48
add edx,48
mov byte [numtext+0],al
mov byte [numtext+1],dl
mov eax,[escnumbers+4]
xor edx,edx
mov ebx,10
div ebx
add eax,48
add edx,48
mov [numtext+3],al
mov [numtext+4],dl
mov eax,4
mov ebx,250*65536+8
mov ecx,0xffffff
mov edx,numtext
mov esi,10
mcall
popa
ret
draw_event:
pusha
mov eax,13
mov ebx,150*65536+100
mov ecx,8*65536+8
mov edx,0xffffff
mcall
mov eax,4
mov ebx,150*65536+8
mov ecx,0x000000
mov edx,esccmd
mov esi,20
mcall
popa
ret
get_numbers:
pusha
mov [escnumbers+0],0
mov [escnumbers+4],0
mov [escnumbers+8],0
mov ecx,esccmd
cmp [ecx+1],byte '0'
jb gn_over
cmp [ecx+1],byte '9'
jg gn_over
mov edi,escnumbers
gn_new:
add ecx,1
movzx eax,byte [ecx]
sub eax,48
add ecx,1
cmp [ecx],byte '0'
jb gnl1
cmp [ecx],byte '9'
jg gnl1
mov ebx,10
xor edx,edx
mul ebx
movzx ebx,byte[ecx]
add eax,ebx
sub eax,48
add ecx,1
gnl1:
mov [edi],eax
add edi,4
cmp [ecx],byte ';'
je gn_new
gn_over:
popa
ret
; DATA AREA
pos dd 80*10
irc_data dd 0x0
print db 0x0
attribute dd 0
scroll dd 1
dd 24
numtext db ' '
esccmd dd 0,0,0,0,0,0,0,0,0,0,0,0,0
escend db 'ZrhlABCDHfDME=>NmKJgincoyq',0
escnumbers dd 0,0,0,0,0
wcolor dd 0x000000
title db 'TERMINAL FOR MODEM IN COM1 0.03',0
text:
db ' '
db ' '
db '*** A TELNET APPLICATION FOR HAYES COMPATIBLE MODEMS IN COM1 '
db ' '
db '*** USE HAYES COMMANDS TO CONNECT TO A SERVER '
db ' '
db '*** ATDT (PHONENUMBER) '
db ' '
db ' '
db ' '
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/terminal/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm terminal.asm terminal
@erase lang.inc
@pause
/programs/network_old/terminal/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm terminal.asm terminal
@erase lang.inc
@pause
/programs/network_old/tftpc/trunk/tftpc.asm
0,0 → 1,977
;
; TFTP Client
use32
org 0x0
db 'MENUET01' ; header
dd 0x01 ; header version
dd START ; entry point
dd I_END ; image size
dd I_END+0x10000 ; required memory
dd I_END+0x10000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Path
 
include 'lang.inc'
include '..\..\..\macros.inc'
START: ; start of execution
mov eax,40 ; Report events
mov ebx,10000111b ; Stack 8 + defaults
mcall
mov dword [prompt], p1
mov dword [promptlen], p1len - p1
 
red:
call draw_window ; at first, draw the window
still:
mov eax,10 ; wait here for event
mcall
cmp eax,1 ; redraw request ?
jz red
cmp eax,2 ; key in buffer ?
jz key
cmp eax,3 ; button in buffer ?
jz button
jmp still
 
key: ; Keys are not valid at this part of the
mov eax,2 ; loop. Just read it and ignore
mcall
jmp still
button: ; button
mov eax,17 ; get id
mcall
cmp ah,1 ; button id=1 ?
jnz noclose
; close socket before exiting
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
int 0x40
mov [socketNum], dword 0
or eax,-1 ; close this program
mcall
noclose:
cmp ah,2 ; copy file to local machine?
jnz nocopyl
mov dword [prompt], p5
mov dword [promptlen], p5len - p5
call draw_window ;
; Copy File from Remote Host to this machine
call translateData ; Convert Filename & IP address
mov edi, tftp_filename + 1
mov [edi], byte 0x01 ; setup tftp msg
call copyFromRemote
jmp still
nocopyl:
cmp ah,3 ; Copy file to host?
jnz nocopyh
mov dword [prompt], p5
mov dword [promptlen], p5len - p5
call draw_window ;
; Copy File from this machine to Remote Host
call translateData ; Convert Filename & IP address
mov edi, tftp_filename + 1
mov [edi], byte 0x02 ; setup tftp msg
call copyToRemote
jmp still
nocopyh:
cmp ah,4
jz f1
cmp ah,5
jz f2
jmp nof12
f1:
mov [addr],dword source
mov [ya],dword 35
jmp rk
f2:
mov [addr],dword destination
mov [ya],dword 35+16
rk:
mov ecx,15
mov edi,[addr]
mov al,' '
rep stosb
call print_text
mov edi,[addr]
f11:
mov eax,10
mcall
cmp eax,2
jz fbu
jmp still
fbu:
mov eax,2
mcall ; get key
shr eax,8
cmp eax,8
jnz nobs
cmp edi,[addr]
jz f11
sub edi,1
mov [edi],byte ' '
call print_text
jmp f11
nobs:
cmp eax,dword 31
jbe f11
cmp eax,dword 95
jb keyok
sub eax,32
keyok:
mov [edi],al
call print_text
add edi,1
mov esi,[addr]
add esi,15
cmp esi,edi
jnz f11
jmp still
print_text:
mov eax,13
mov ebx,103*65536+15*6
mov ecx,[ya]
shl ecx,16
mov cx,8
mov edx,0x224466
mcall
mov eax,4
mov ebx,103*65536
add ebx,[ya]
mov ecx,0xffffff
mov edx,[addr]
mov esi,15
mcall
ret
nof12:
jmp still
;***************************************************************************
; Function
; translateData
;
; Description
; Coverts the filename and IP address typed in by the user into
; a format suitable for the IP layer.
;
; The filename, in source, is converted and stored in tftp_filename
; The host ip, in destination, is converted and stored in tftp_IP
;
;***************************************************************************
translateData:
; first, build up the tftp command string. This includes the filename
; and the transfer protocol
; First, write 0,0
mov al, 0
mov edi, tftp_filename
mov [edi], al
inc edi
mov [edi], al
inc edi
; Now, write the file name itself, and null terminate it
mov ecx, 15
mov ah, ' '
mov esi, source
td001:
lodsb
stosb
cmp al, ah
loopnz td001
cmp al,ah ; Was the entire buffer full of characters?
jne td002
dec edi ; No - so remove ' ' character
td002:
mov [edi], byte 0
inc edi
mov [edi], byte 'O'
inc edi
mov [edi], byte 'C'
inc edi
mov [edi], byte 'T'
inc edi
mov [edi], byte 'E'
inc edi
mov [edi], byte 'T'
inc edi
mov [edi], byte 0
mov esi, tftp_filename
sub edi, esi
mov [tftp_len], edi
; Now, convert the typed IP address into a real address
; No validation is done on the number entered
; ip addresses must be typed in normally, eg
; 192.1.45.24
xor eax, eax
mov dh, 10
mov dl, al
mov [tftp_IP], eax
; 192.168.24.1 1.1.1.1 1. 9.2.3.
mov esi, destination
mov edi, tftp_IP
mov ecx, 4
td003:
lodsb
sub al, '0'
add dl, al
lodsb
cmp al, '.'
je ipNext
cmp al, ' '
je ipNext
mov dh, al
sub dh, '0'
mov al, 10
mul dl
add al, dh
mov dl, al
lodsb
cmp al, '.'
je ipNext
cmp al, ' '
je ipNext
mov dh, al
sub dh, '0'
mov al, 10
mul dl
add al, dh
mov dl, al
lodsb
ipNext:
mov [edi], dl
inc edi
mov dl, 0
loop td003
ret
;***************************************************************************
; Function
; copyFromRemote
;
; Description
;
;***************************************************************************
copyFromRemote:
xor eax, eax
mov [filesize], eax
mov eax, I_END + 512 ; This is the point where the file buffer is
mov [fileposition], eax
; Get a random # for the local socket port #
mov eax, 3
int 0x40
mov ecx, eax
shr ecx, 8 ; Set up the local port # with a random #
; open socket
mov eax, 53
mov ebx, 0
mov edx, 69 ; remote port
mov esi, [tftp_IP] ; remote IP ( in intenet format )
int 0x40
mov [socketNum], eax
; make sure there is no data in the socket - there shouldn't be..
cfr001:
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
int 0x40 ; read byte
mov eax, 53
mov ebx, 2
mov ecx, [socketNum]
int 0x40 ; any more data?
cmp eax, 0
jne cfr001 ; yes, so get it
; Now, request the file
mov eax, 53
mov ebx, 4
mov ecx, [socketNum]
mov edx, [tftp_len]
mov esi, tftp_filename
int 0x40
cfr002:
mov eax,10 ; wait here for event
mcall
cmp eax,1 ; redraw request ?
je cfr003
cmp eax,2 ; key in buffer ?
je cfr004
cmp eax,3 ; button in buffer ?
je cfr005
; Any data to fetch?
mov eax, 53
mov ebx, 2
mov ecx, [socketNum]
int 0x40
cmp eax, 0
je cfr002
push eax ; eax holds # chars
; Update the text on the display - once
mov eax, [prompt]
cmp eax, p3
je cfr008
mov dword [prompt], p3
mov dword [promptlen], p3len - p3
call draw_window ;
cfr008:
; we have data - this will be a tftp frame
; read first two bytes - opcode
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
int 0x40 ; read byte
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
int 0x40 ; read byte
pop eax
; bl holds tftp opcode. Can only be 3 (data) or 5 ( error )
cmp bl, 3
jne cfrerr
push eax
; do data stuff. Read block #. Read data. Send Ack.
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
int 0x40 ; read byte
mov [blockNumber], bl
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
int 0x40 ; read byte
mov [blockNumber+1], bl
cfr007:
mov eax, 53
mov ebx, 2
mov ecx, [socketNum]
mcall ; any more data?
cmp eax, 0
je no_more_data ; no
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
mcall ; read byte
mov esi, [fileposition]
mov [esi], bl
inc dword [fileposition]
inc dword [filesize]
jmp cfr007
no_more_data:
; write the block number into the ack
mov al, [blockNumber]
mov [ack + 2], al
mov al, [blockNumber+1]
mov [ack + 3], al
; send an 'ack'
mov eax, 53
mov ebx, 4
mov ecx, [socketNum]
mov edx, ackLen - ack
mov esi, ack
int 0x40
; If # of chars in the frame is less that 516,
; this frame is the last
pop eax
cmp eax, 516
je cfr002
; Write the file
mov ebx, writeinfo
lea esi, [ebx + 20]
@@:
lodsb
test al, al
jnz @b
@@:
dec esi
cmp byte [esi-1], ' '
jnz @b
mov byte [esi], 0
mcall 70, writeinfo
mov byte [esi], ' '
jmp cfrexit
cfrerr:
; simple implementation on error - just read all data, and return
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
int 0x40 ; read byte
mov eax, 53
mov ebx, 2
mov ecx, [socketNum]
int 0x40 ; any more data?
cmp eax, 0
jne cfrerr ; yes, so get it
jmp cfr006 ; close socket and close app
cfr003: ; redraw request
call draw_window
jmp cfr002
cfr004: ; key pressed
mov eax,2 ; just read it and ignore
mcall
jmp cfr002
cfr005: ; button
mov eax,17 ; get id
mcall
cmp ah,1 ; button id=1 ?
jne cfr002 ; If not, ignore.
cfr006:
; close socket
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
int 0x40
mov [socketNum], dword 0
mov eax,-1 ; close this program
mcall
jmp $
cfrexit:
; close socket
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
int 0x40
mov [socketNum], dword 0
mov dword [prompt], p4
mov dword [promptlen], p4len - p4
call draw_window ;
ret
;***************************************************************************
; Function
; copyToRemote
;
; Description
;
;***************************************************************************
copyToRemote:
mov eax,6 ; Read file from floppy (image)
mov ebx,source
mov ecx,0
mov edx,0xffffffff
mov esi,I_END + 512
int 0x40
cmp eax,0xffffffff
jnz filefound
mov dword [prompt], p6
mov dword [promptlen], p6len - p6
call draw_window ;
jmp ctr_exit
filefound:
mov [filesize], eax
; First, set up the file pointers
mov eax, 0x01000300
mov [blockBuffer], eax ; This makes sure our TFTP header is valid
mov eax, I_END + 512 ; This is the point where the file buffer is
mov [fileposition], eax
mov eax, [filesize]
cmp eax, 512
jb ctr000
mov eax, 512
ctr000:
mov [fileblocksize], ax
; Get a random # for the local socket port #
mov eax, 3
int 0x40
mov ecx, eax
shr ecx, 8 ; Set up the local port # with a random #
; First, open socket
mov eax, 53
mov ebx, 0
mov edx, 69 ; remote port
mov esi, [tftp_IP]
int 0x40
mov [socketNum], eax
; write to socket ( request write file )
mov eax, 53
mov ebx, 4
mov ecx, [socketNum]
mov edx, [tftp_len]
mov esi, tftp_filename
int 0x40
; now, we wait for
; UI redraw
; UI close
; or data from remote
ctr001:
mov eax,10 ; wait here for event
int 0x40
cmp eax,1 ; redraw request ?
je ctr003
cmp eax,2 ; key in buffer ?
je ctr004
cmp eax,3 ; button in buffer ?
je ctr005
; Any data in the UDP receive buffer?
mov eax, 53
mov ebx, 2
mov ecx, [socketNum]
int 0x40
cmp eax, 0
je ctr001
; Update the text on the display - once
mov eax, [prompt]
cmp eax, p2
je ctr002
mov dword [prompt], p2
mov dword [promptlen], p2len - p2
call draw_window ;
; we have data - this will be the ack
ctr002:
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
int 0x40 ; read byte - opcode
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
int 0x40 ; read byte - opcode
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
int 0x40 ; read byte - block (high byte)
mov [blockNumber], bl
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
int 0x40 ; read byte - block (low byte )
mov [blockNumber+1], bl
ctr0022:
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
int 0x40 ; read byte (shouldn't have worked)
mov eax, 53
mov ebx, 2
mov ecx, [socketNum]
int 0x40 ; any more data?
cmp eax, 0
jne ctr0022 ; yes, so get it, and dump it
; If the ack is 0, it is to the request
mov bx, [blockNumber]
cmp bx, 0
je txd
; now, the ack should be one more than the current field - otherwise, resend
cmp bx, [blockBuffer+2]
jne txre ; not the same, so send again
; update the block number
mov esi, blockBuffer + 3
mov al, [esi]
inc al
mov [esi], al
cmp al, 0
jne ctr008
dec esi
inc byte [esi]
ctr008:
; Move forward through the file
mov eax, [fileposition]
movzx ebx, word [fileblocksize]
add eax, ebx
mov [fileposition], eax
; new ..
; fs = 0 , fbs = 512 -> send with fbs = 0
cmp [filesize],0
jne no_special_end
cmp [fileblocksize],512
jne no_special_end
mov ax,0
jmp ctr006
no_special_end:
mov eax, [filesize]
cmp eax, 0
je ctr009
cmp eax, 512
jb ctr006
mov eax, 512
ctr006:
mov [fileblocksize], ax
txd:
; Readjust the file size variable ( before sending )
mov eax, [filesize]
movzx ebx, word [fileblocksize]
sub eax, ebx
mov [filesize], eax
txre:
; Copy the fragment of the file to the block buffer
movzx ecx, word [fileblocksize]
mov esi, [fileposition]
mov edi, I_END
cld
rep movsb
; send the file data
mov eax, 53
mov ebx, 4
mov ecx, [socketNum]
movzx edx, word [fileblocksize]
add edx, 4
mov esi, blockBuffer
int 0x40
jmp ctr001
ctr003: ; redraw
call draw_window
jmp ctr001
ctr004: ; key
mov eax,2 ; just read it and ignore
int 0x40
jmp ctr001
ctr005: ; button
mov eax,17 ; get id
int 0x40
cmp ah,1 ; button id=1 ?
jne ctr001
; close socket
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
int 0x40
mov [socketNum], dword 0
mov eax,-1 ; close this program
int 0x40
jmp $
ctr009:
; close socket
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
int 0x40
mov dword [prompt], p4
mov dword [promptlen], p4len - p4
call draw_window ;
ctr_exit:
ret
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
draw_window:
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,100*65536+230 ; [x start] *65536 + [x size]
mov ecx,100*65536+170 ; [y start] *65536 + [y size]
mov edx,0x14224466 ; color of work area RRGGBB
mov edi,title
mcall
mov eax,8 ; COPY BUTTON
mov ebx,20*65536+190
mov ecx,79*65536+15
mov edx,2
mov esi,0x557799
mcall
; mov eax,8 ; DELETE BUTTON
mov ebx,20*65536+190
mov ecx,111*65536+15
mov edx,3
mcall
; mov eax,8
; mov ebx,200*65536+10
mov ecx,34*65536+10
mov edx,4
mcall
; mov eax,8
; mov ebx,200*65536+10
mov ecx,50*65536+10
mov edx,5
mcall
; Copy the file name to the screen buffer
; file name is same length as IP address, to
; make the math easier later.
cld
mov esi,source
mov edi,text+13
mov ecx,15
rep movsb
; copy the IP address to the screen buffer
mov esi,destination
mov edi,text+40+13
mov ecx,15
rep movsb
; copy the prompt to the screen buffer
mov esi,[prompt]
mov edi,text+280
mov ecx,[promptlen]
rep movsb
; Re-draw the screen text
cld
mov eax,4
mov ebx,25*65536+35 ; draw info text with function 4
mov ecx,0xffffff
mov edx,text
mov esi,40
newline:
mcall
add ebx,16
add edx,40
cmp [edx],byte 'x'
jnz newline
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
ret
; DATA AREA
; file name: source
; file data: I_END + 512
; file size: [filesize]
writeinfo:
dd 2
dd 0
dd 0
filesize dd 0 ; The number of bytes written / left to write
dd I_END + 512
source db 'KERNEL.ASM ',0
destination db '192.168.1.23 '
tftp_filename: times 15 + 9 db 0
tftp_IP: dd 0
tftp_len: dd 0
addr dd 0x0
ya dd 0x0
fileposition dd 0 ; Points to the current point in the file
fileblocksize dw 0 ; The number of bytes to send in this frame
text:
db 'SOURCE FILE: xxxxxxxxxxxxxxx '
db 'HOST IP ADD: xxx.xxx.xxx.xxx '
db ' '
db ' COPY HOST -> LOCAL '
db ' '
db ' COPY LOCAL -> HOST '
db ' '
db ' '
db 'x' ; <- END MARKER, DONT DELETE
title db 'TFTP Client',0
prompt: dd 0
promptlen: dd 0
p1: db 'Waiting for Command'
p1len:
p2: db 'Sending File '
p2len:
p3: db 'Receiving File '
p3len:
p4: db 'Tranfer Complete '
p4len:
p5: db 'Contacting Host... '
p5len:
p6: db 'File not found. '
p6len:
ack:
db 00,04,0,1
ackLen:
socketNum:
dd 0
blockNumber:
dw 0
; This must be the last part of the file, because the blockBuffer
; continues at I_END.
blockBuffer:
db 00, 03, 00, 01
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/tftpc/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm tftpc.asm tftpc
@erase lang.inc
@pause
/programs/network_old/tftpc/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm tftpc.asm tftpc
@erase lang.inc
@pause
/programs/network_old/dnsr/trunk/dnsr.asm
0,0 → 1,785
;
; DNS Domain name -> IP lookup
;
; Compile with FASM for Menuet
;
 
 
; If you like, you camd change the DNS server default by changing the
; IP address in the dnsServer string.
 
 
; Enabling debugging puts the received response to the
; debug board
DEBUGGING_ENABLED equ 1
DEBUGGING_DISABLED equ 0
DEBUGGING_STATE equ DEBUGGING_DISABLED
 
 
use32
org 0x0
db 'MENUET01' ; header
dd 0x01 ; header version
dd START ; entry point
dd I_END ; image size
dd I_END+0x10000 ; required memory
dd I_END+0x10000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Path
 
include 'lang.inc'
include 'macros.inc'
 
START: ; start of execution
mov eax,40 ; Report events
mov ebx,10000111b ; Stack 8 + defaults
int 0x40
 
mov dword [prompt], p1
mov dword [promptlen], p1len - p1 ; 'waiting for command'
 
red:
call draw_window ; at first, draw the window
 
still:
mov eax,10 ; wait here for event
mcall
 
cmp eax,1 ; redraw request ?
jz red
cmp eax,2 ; key in buffer ?
jz key
cmp eax,3 ; button in buffer ?
jz button
 
jmp still
key: ; Keys are not valid at this part of the
mov eax,2 ; loop. Just read it and ignore
mcall
jmp still
 
button: ; button
mov eax,17 ; get id
mcall
 
cmp ah,1 ; button id=1 ?
jnz noclose
 
; close socket before exiting
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
mcall
 
mov eax,0xffffffff ; close this program
mcall
 
noclose:
cmp ah,3 ; Resolve address?
jnz noresolve
 
mov dword [prompt], p5
mov dword [promptlen], p5len - p5 ; display 'Resolving'
call draw_window
 
call translateData ; Convert domain & DNS IP address
 
call resolveDomain
 
jmp still
 
 
noresolve:
cmp ah,4
jz f1 ; Enter domain name
cmp ah,5
jz f2 ; enter DNS Server IP
jmp still
 
 
f1:
mov [addr],dword query
mov [ya],dword 35
jmp rk
 
f2:
mov [addr],dword dnsServer
mov [ya],dword 35+16
 
rk:
mov ecx,26
mov edi,[addr]
mov al,' '
rep stosb
 
call print_text
 
mov edi,[addr]
 
f11:
mov eax,10
mcall
cmp eax,2
jz fbu
jmp still
 
fbu:
mov eax,2
mcall ; get key
shr eax,8
cmp eax,8
jnz nobs
cmp edi,[addr]
jz f11
sub edi,1
mov [edi],byte ' '
call print_text
jmp f11
 
nobs:
cmp eax,dword 31
jbe f11
cmp eax,dword 95
jb keyok
sub eax,32
 
keyok:
mov [edi],al
 
call print_text
 
add edi,1
mov esi,[addr]
add esi,26
cmp esi,edi
jnz f11
 
jmp still
 
 
 
print_text:
mov eax,13
mov ebx,103*65536+26*6
mov ecx,[ya]
shl ecx,16
mov cx,8
mov edx,0x224466
mcall
 
mov eax,4
mov ebx,103*65536
add ebx,[ya]
mov ecx,0xffffff
mov edx,[addr]
mov esi,26
mcall
 
ret
 
 
 
;***************************************************************************
; Function
; translateData
;
; Description
; Coverts the domain name and DNS IP address typed in by the user into
; a format suitable for the IP layer.
;
; The ename, in query, is converted and stored in dnsMsg
; The DNS ip, in dnsServer, is converted and stored in dnsIP
;
;***************************************************************************
translateData:
 
; first, get the IP address of the DNS server
; Then, build up the request string.
 
xor eax, eax
mov dh, 10
mov dl, al
mov [dnsIP], eax
 
mov esi, dnsServer
mov edi, dnsIP
 
mov ecx, 4
 
td003:
lodsb
sub al, '0'
add dl, al
lodsb
cmp al, '.'
je ipNext
cmp al, ' '
je ipNext
mov dh, al
sub dh, '0'
mov al, 10
mul dl
add al, dh
mov dl, al
lodsb
cmp al, '.'
je ipNext
cmp al, ' '
je ipNext
mov dh, al
sub dh, '0'
mov al, 10
mul dl
add al, dh
mov dl, al
lodsb
 
ipNext:
mov [edi], dl
inc edi
mov dl, 0
loop td003
 
; Build the request string
 
 
mov eax, 0x00010100
mov [dnsMsg], eax
mov eax, 0x00000100
mov [dnsMsg+4], eax
mov eax, 0x00000000
mov [dnsMsg+8], eax
 
; domain name goes in at dnsMsg+12
mov esi, dnsMsg + 12 ; location of label length
mov edi, dnsMsg + 13 ; label start
mov edx, query
mov ecx, 12 ; total string length so far
 
td002:
mov [esi], byte 0
inc ecx
 
td0021:
mov al, [edx]
cmp al, ' '
je td001 ; we have finished the string translation
cmp al, '.' ; we have finished the label
je td004
 
inc byte [esi]
inc ecx
mov [edi], al
inc edi
inc edx
jmp td0021
 
td004:
mov esi, edi
inc edi
inc edx
jmp td002
 
 
 
; write label len + label text
 
td001:
mov [edi], byte 0
inc ecx
inc edi
mov [edi], dword 0x01000100
add ecx, 4
 
mov [dnsMsgLen], ecx
 
ret
 
 
 
 
 
;***************************************************************************
; Function
; resolveDomain
;
; Description
; Sends a question to the dns server
; works out the IP address from the response from the DNS server
;
;***************************************************************************
resolveDomain:
; Get a free port number
mov ecx, 1000 ; local port starting at 1000
getlp:
inc ecx
push ecx
mov eax, 53
mov ebx, 9
mcall
pop ecx
cmp eax, 0 ; is this local port in use?
jz getlp ; yes - so try next
 
; First, open socket
mov eax, 53
mov ebx, 0
mov edx, 53 ; remote port - dns
mov esi, [dnsIP]
mcall
 
mov [socketNum], eax
 
; write to socket ( request DNS lookup )
mov eax, 53
mov ebx, 4
mov ecx, [socketNum]
mov edx, [dnsMsgLen]
mov esi, dnsMsg
mcall
 
; Setup the DNS response buffer
 
mov eax, dnsMsg
mov [dnsMsgLen], eax
 
; now, we wait for
; UI redraw
; UI close
; or data from remote
 
ctr001:
mov eax,10 ; wait here for event
mcall
 
cmp eax,1 ; redraw request ?
je ctr003
cmp eax,2 ; key in buffer ?
je ctr004
cmp eax,3 ; button in buffer ?
je ctr005
 
 
; Any data in the UDP receive buffer?
mov eax, 53
mov ebx, 2
mov ecx, [socketNum]
mcall
 
cmp eax, 0
je ctr001
 
; we have data - this will be the response
ctr002:
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
mcall ; read byte - block (high byte)
 
; Store the data in the response buffer
mov eax, [dnsMsgLen]
mov [eax], bl
inc dword [dnsMsgLen]
 
 
if DEBUGGING_STATE = DEBUGGING_ENABLED
call debug_print_rx_ip
end if
 
mov eax, 53
mov ebx, 2
mov ecx, [socketNum]
mcall ; any more data?
 
cmp eax, 0
jne ctr002 ; yes, so get it
 
; close socket
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
mcall
 
mov [socketNum], dword 0xFFFF
 
; Now parse the message to get the host IP
; Man, this is complicated. It's described in
; RFC 1035
 
; 1) Validate that we have an answer with > 0 responses
; 2) Find the answer record with TYPE 0001 ( host IP )
; 3) Finally, copy the IP address to the display
; Note: The response is in dnsMsg
; The end of the buffer is pointed to by [dnsMsgLen]
 
; Clear the IP address text
mov [hostIP], dword 0
 
mov esi, dnsMsg
 
; Is this a response to my question?
mov al, [esi+2]
and al, 0x80
cmp al, 0x80
jne ctr002a
 
; Were there any errors?
mov al, [esi+3]
and al, 0x0F
cmp al, 0x00
jne ctr002a
 
; Is there ( at least 1 ) answer?
mov ax, [esi+6]
cmp ax, 0x00
je ctr002a
 
; Header validated. Scan through and get my answer
 
add esi, 12 ; Skip to the question field
 
; Skip through the question field
call skipName
add esi, 4 ; skip past the questions qtype, qclass
 
ctr002z:
; Now at the answer. There may be several answers,
; find the right one ( TYPE = 0x0001 )
call skipName
mov ax, [esi]
cmp ax, 0x0100 ; Is this the IP address answer?
jne ctr002c
 
; Yes! Point esi to the first byte of the IP address
add esi, 10
 
mov eax, [esi]
mov [hostIP], eax
jmp ctr002a ; And exit...
 
 
ctr002c: ; Skip through the answer, move to the next
add esi, 8
movzx eax, byte [esi+1]
mov ah, [esi]
add esi, eax
add esi, 2
 
; Have we reached the end of the msg?
; This is an error condition, should not happen
cmp esi, [dnsMsgLen]
jl ctr002z ; Check next answer
jmp ctr002a ; abort
 
 
ctr002a:
mov dword [prompt], p4 ; Display IP address
mov dword [promptlen], p4len - p4
call draw_window
 
jmp ctr001
 
ctr003: ; redraw
call draw_window
jmp ctr001
 
ctr004: ; key
mov eax,2 ; just read it and ignore
mcall
jmp ctr001
 
ctr005: ; button
mov eax,17 ; get id
mcall
 
; close socket
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
mcall
 
mov [socketNum], dword 0xFFFF
mov [hostIP], dword 0
 
mov dword [prompt], p1
mov dword [promptlen], p1len - p1 ; 'waiting for command'
 
call draw_window ; at first, draw the window
 
ret
 
 
 
;***************************************************************************
; Function
; skipName
;
; Description
; Increment esi to the first byte past the name field
; Names may use compressed labels. Normally do.
; RFC 1035 page 30 gives details
;
;***************************************************************************
skipName:
mov al, [esi]
cmp al, 0
je sn_exit
and al, 0xc0
cmp al, 0xc0
je sn001
 
movzx eax, byte [esi]
inc eax
add esi, eax
jmp skipName
 
sn001:
add esi, 2 ; A pointer is always at the end
ret
 
sn_exit:
inc esi
ret
 
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
 
draw_window:
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,100*65536+300 ; [x start] *65536 + [x size]
mov ecx,100*65536+140 ; [y start] *65536 + [y size]
mov edx,0x14224466 ; color of work area RRGGBB
mov edi,title ; WINDOW LABEL;
mcall
 
mov eax,8 ; Resolve
mov ebx,20*65536+190
mov ecx,79*65536+15
mov edx,3
mov esi,0x557799
mcall
 
;mov eax,8
mov ebx,270*65536+10
mov ecx,34*65536+10
inc edx
mcall
 
;mov eax,8
mov ebx,270*65536+10
mov ecx,50*65536+10
inc edx
mcall
 
; Copy the file name to the screen buffer
; file name is same length as IP address, to
; make the math easier later.
cld
mov esi,query
mov edi,text+13
mov ecx,26
rep movsb
 
 
; copy the IP address to the screen buffer
mov esi,dnsServer
mov edi,text+40+13
mov ecx,26
rep movsb
 
; copy the prompt to the screen buffer
mov esi,[prompt]
mov edi,text+200
mov ecx,[promptlen]
rep movsb
 
; Re-draw the screen text
cld
mov eax,4
mov ebx,25*65536+35 ; draw info text with function 4
mov ecx,0xffffff
mov edx,text
mov esi,40
newline:
mcall
add ebx,16
add edx,40
cmp [edx],byte 'x'
jnz newline
 
 
; Write the host IP, if we have one
mov eax, [hostIP]
cmp eax, 0
je dw001
 
; We have an IP address... display it
mov edi,hostIP
mov edx,97*65536+115
mov esi,0x00ffffff
mov ebx,3*65536
 
ipdisplay:
mov eax,47
movzx ecx,byte [edi]
mcall
add edx,6*4*65536
inc edi
cmp edi,hostIP+4
jb ipdisplay
 
dw001:
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
 
ret
 
 
if DEBUGGING_STATE = DEBUGGING_ENABLED
;****************************************************************************
; Function
; debug_print_string
;
; Description
; prints a string to the debug board
;
; esi holds ptr to msg to display
;
; Nothing preserved; I'm assuming a pusha/popa is done before calling
;
;****************************************************************************
debug_print_string:
mov cl, [esi]
cmp cl, 0
jnz dps_001
ret
 
dps_001:
mov eax,63
mov ebx, 1
push esi
mcall
 
inc word [ind]
mov ax, [ind]
and ax, 0x1f
cmp ax, 0
jne ds1
 
mov cl, 13
mov eax,63
mov ebx, 1
mcall
mov cl, 10
mov eax,63
mov ebx, 1
mcall
 
 
ds1:
pop esi
inc esi
jmp debug_print_string
 
 
ind: dw 0
; This is used for translating hex to ASCII for display or output
hexchars db '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
IP_STR db 'xx',0
 
 
debug_print_rx_ip:
pusha
mov edi, IP_STR
 
xor eax, eax
mov al, bl
shr al, 4
mov ah, [eax + hexchars]
mov [edi], ah
inc edi
 
xor eax, eax
mov al, bl
and al, 0x0f
mov ah, [eax + hexchars]
mov [edi], ah
mov esi, IP_STR
 
call debug_print_string
popa
ret
end if
 
 
; DATA AREA
 
addr dd 0x0
ya dd 0x0
 
text:
 
if lang eq ru
db 'ˆ¬ï å®áâ  : xxxxxxxxxxxxxxx '
db 'DNS á¥à¢¥à : xxx.xxx.xxx.xxx '
db ' '
db ' ®«ãç¨âì  ¤à¥á '
db ' '
db ' '
db 'x <- END MARKER, DONT DELETE '
 
else
db 'Host name : xxxxxxxxxxxxxxx '
db 'DNS server : xxx.xxx.xxx.xxx '
db ' '
db ' RESOLVE ADDRESS '
db ' '
db ' '
db 'x <- END MARKER, DONT DELETE '
end if
 
if lang eq ru
title db 'DNS Š«¨¥­â',0
 
else
title db 'DNS Client',0
end if
 
 
prompt: dd 0
promptlen: dd 0
 
 
if lang eq ru
p1: db '†¤ã ª®¬ ­¤ë '
p1len:
 
 
else
p1: db 'Waiting for Command '
p1len:
end if
 
p4: db 'IP Address: . . . '
p4len:
 
p5: db 'Resolving... '
p5len:
 
 
dnsServer db '194.145.128.1 ' ; iolfree.ie DNS
query db 'WWW.MENUETOS.NET '
 
hostIP: dd 0
dnsIP: dd 0
dnsMsgLen: dd 0
socketNum: dd 0xFFFF
dnsMsg:
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/dnsr/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm dnsr.asm dnsr
@erase lang.inc
@pause
/programs/network_old/dnsr/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm dnsr.asm dnsr
@erase lang.inc
@pause
/programs/network_old/netsendc/trunk/netsendc.asm
0,0 → 1,173
;
; NetSend(Client)
;
; €¢â®à: Hex
; ‘ ©â: www.mestack.narod.ru
;
; Ž¯¨á ­¨¥:
; à®£à ¬¬  ¤«ï ®¡¬¥­  á®®¡é¥­¨ï¬¨ ¢ á¥â¨.Š«¨¥­â᪠ï ç áâì.
;
; Compile with FASM for Menuet
; Š®¬¯¨«¨àã¥âáï FASM'®¬ ¤«ï Œ¥­ãí⠎‘
;
 
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 1 ; header version
dd START ; program start
dd I_END ; program image size
dd mem ; required amount of memory
dd mem ; stack pointer
dd 0, 0 ; param, icon
 
include 'lang.inc'
include 'macros.inc'
 
START: ; start of execution
 
mov eax,53 ; open socket
mov ebx,0
mov ecx,0x4000 ; local port
mov edx,0x5000 ; remote port
mov esi,dword [remote_ip] ; node IP
mcall
 
mov [socketNum], eax
 
red:
call draw_window ; at first, draw the window
 
still:
 
mov eax,10 ; wait here for event
mcall
 
dec eax
jz red
dec eax
jnz button
 
key:
mov al,2
mcall
jmp still
 
button:
mov al,17
mcall
 
dec ah ; button id=1 ?
jnz noclose
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
mcall
or eax,-1
mcall
noclose:
; it was not close button, so it must be send code button
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SEND CODE TO REMOTE ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
send_xcode:
 
mov eax,53 ; SEND CODE TO REMOTE
mov ebx,4
mov ecx,[socketNum]
mov edx,end_message-send_data
mov esi,send_data
mcall
 
jmp still
 
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
 
draw_window:
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
 
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,100*65536+250 ; [x start] *65536 + [x size]
mov ecx,60*65536+150 ; [y start] *65536 + [y size]
mov edx,0x14ffffff ; color of work area RRGGBB
mov edi,title ; WINDOW LABEL
mcall
 
 
mov eax,8 ; SEND MESSAGE
mov ebx,50*65536+145
mov ecx,47*65536+13
mov edx,2
mov esi,0x667788
mcall
 
mov eax,4
mov ebx,25*65536+50 ; draw info text with function 4
mov ecx,0x000000
mov edx,text
mov esi,40
newline:
mcall
add ebx,16
add edx,esi
cmp [edx],byte 'x'
jnz newline
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
 
ret
 
 
; DATA AREA
 
if lang eq ru
text:
db ' ®á« âì á®®¡é¥­¨¥ '
db ' '
db ' ‹®ª «ì­ë©  ¤à¥á : 192.168.0.1 '
db ' “¤ «ñ­­ë©  ¤à¥á : 192.168.0.2 '
db '’¥ªáâ ¨  ¤à¥á ¢ ª®­æ¥ ¨á室­¨ª  '
db 'x' ; <- END MARKER, DONT DELETE
else
text:
db ' Send message '
db ' '
db ' Local address : 192.168.0.1 '
db ' Remote address : 192.168.0.2 '
db 'Text and address in end of source '
db 'x' ; <- END MARKER, DONT DELETE
end if
 
title db 'NetSend(Client)',0
 
remote_ip db 192,168,1,2
 
send_data db 'à¨¢¥â,íâ® â¥áâ!Hello,this is a test!'
end_message:
 
 
I_END:
align 4
socketNum dd ?
 
rb 32 ; this is for stack
 
mem:
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/netsendc/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm netsendc.asm netsendc
@erase lang.inc
@pause
/programs/network_old/netsendc/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm netsendc.asm netsendc
@erase lang.inc
@pause
/programs/network_old/netsends/trunk/netsends.asm
0,0 → 1,186
;
; NetSend(Server)
;
; €¢â®à: Hex
; ‘ ©â: www.mestack.narod.ru
;
; Ž¯¨á ­¨¥:
; à®£à ¬¬  ¤«ï ®¡¬¥­  á®®¡é¥­¨ï¬¨ ¢ á¥â¨.‘¥à¢¥à­ ï ç áâì.
;
; Compile with FASM for Menuet
; Š®¬¯¨«¨àã¥âáï FASM'®¬ ¤«ï Œ¥­ãí⠎‘
;
 
use32
org 0x0
db 'MENUET01' ; header
dd 0x01 ; header version
dd START ; entry point
dd I_END ; image size
dd I_END+0x10000 ; required memory
dd I_END+0x10000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Path
 
include 'lang.inc'
include 'macros.inc'
remote_ip db 192,168,0,1
 
 
START: ; start of execution
 
mov eax, 53 ; open receiver socket
mov ebx, 0
mov ecx, 0x5000 ; local port
mov edx, 0xffff ; remote port
mov esi, dword [remote_ip] ; remote IP
mcall
mov [socketNum],eax
mov [0],eax ; save for remote code
 
red:
call draw_window ; at first, draw the window
 
still:
 
mov eax,23 ; wait here for event
mov ebx,1
mcall
 
cmp eax,1 ; redraw request ?
jz red
cmp eax,2 ; key in buffer ?
jz key
cmp eax,3 ; button in buffer ?
jz button
 
mov eax,53 ; data from cluster terminal ?
mov ebx,2
mov ecx,[socketNum]
mcall
 
cmp eax,0
jne data_arrived
 
jmp still
 
key:
mov eax,2
mcall
jmp still
 
button:
 
mov eax,53
mov ebx,1
mov ecx,[socketNum]
mcall
or eax,-1
mcall
 
 
data_arrived:
 
mov eax,5 ; wait a second for everything to arrive
mov ebx,10
mcall
 
mov edi,I_END
 
get_data:
 
mov eax,53
mov ebx,3
mov ecx,[socketNum]
mcall
 
mov [edi],bl
inc edi
 
mov eax,53
mov ebx,2
mov ecx,[socketNum]
mcall
 
cmp eax,0
jne get_data
 
mov eax,4
mov ebx,10*65536+60
add ebx,[y]
mov ecx,0x000000
mov edx,I_END
mov esi,100
mcall
 
add [y],10
 
jmp still
 
y dd 0x10
 
 
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
 
draw_window:
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
 
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,100*65536+300 ; [x start] *65536 + [x size]
mov ecx,100*65536+330 ; [y start] *65536 + [y size]
mov edx,0x14ffffff ; color of work area RRGGBB
mov edi,title ; WINDOW LABEL
mcall
 
 
; Re-draw the screen text
cld
mov eax,4
mov ebx,10*65536+30 ; draw info text with function 4
mov ecx,0x000000
mov edx,text
mov esi,40
newline:
mcall
add ebx,16
add edx,40
cmp [edx],byte 'x'
jnz newline
 
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
 
ret
 
 
; DATA AREA
 
if lang eq ru
text:
db '„ ­­ë©  ¤à¥á : 192.168.0.2 '
db 'à®á«ã訢 ¥¬ë© ¯®àâ : 0x5000 '
db 'à¨á« ­­ë¥ á®®¡é¥­¨ï: '
db 'x' ; <- END MARKER, DONT DELETE
else
text:
db 'This address : 192.168.0.2 '
db 'Used port : 0x5000 '
db 'Received messages: '
db 'x' ; <- END MARKER, DONT DELETE
end if
 
title db 'NetSend(Server)',0
 
socketNum dd 0x0
 
 
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/netsends/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm netsends.asm netsends
@erase lang.inc
@pause
/programs/network_old/netsends/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm netsends.asm netsends
@erase lang.inc
@pause
/programs/network_old/popc/trunk/popc.asm
0,0 → 1,1019
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; POP CLIENT for MenuetOS ;;
;; - Modified from IRC client ;;
;; ;;
;; License: GPL / See file COPYING for details ;;
;; Copyright 2002 (c) Ville Turjanmaa ;;
;; ;;
;; Compile with FASM for Menuet ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
include 'macros.inc'
version equ '0.1'
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; required os
dd START ; program start
dd I_END ; program image size
dd 0x200000 ; required amount of memory
dd 0xffff0
dd 0,0
 
START: ; start of execution
 
mov [file_start],0x100000
 
mov eax,70
mov ebx,filel
mcall
 
test eax,eax
jz @f
cmp eax,6
jnz notfound
@@:
add [file_start],ebx
notfound:
 
mov edi,I_END
mov ecx,60*120
mov al,32
cld
rep stosb
 
mov eax,[rxs]
imul eax,11
mov [pos],eax
 
mov ebp,0
mov edx,I_END
 
redraw: ; redraw
call draw_window ; at first, draw the window
 
still:
 
mov eax,5
mov ebx,1
mcall
 
mov eax,11 ; wait here for event
mcall
 
cmp eax,1 ; redraw
je redraw
cmp eax,2 ; key
je key
cmp eax,3 ; button
je button
 
cmp [I_END+120*60],byte 1
jne no_main_update
mov [I_END+120*60],byte 0
mov edx,I_END
call draw_server_data
no_main_update:
 
cmp [server_active],0
je noread
call read_incoming_data
noread:
 
call print_status
 
cmp [status],4
je send_request
 
jmp still
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Save the fetched mails
;;
 
 
save_file:
 
pusha
 
mov ebx,files
mov eax,[file_start]
sub eax,0x100000
mov [ebx+12],eax
 
mov eax,70
mcall
 
popa
 
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Send user id/passwd/mailrq
;;
 
 
send_request:
 
inc [mcounter]
 
cmp [mcounter],1000
jbe no_send
 
mov eax,[ccounter]
imul eax,32
add eax,getmail
mov esi,eax
 
inc [ccounter]
 
mov edx,32
 
cmp [ccounter],1
jne no1
mov edx,5+2
add edx,[l2]
no1:
 
cmp [ccounter],2
jne no2
mov edx,5+2
add edx,[l3]
no2:
 
mov eax,53
mov ebx,7
mov ecx,[socket]
mcall
mov [mcounter],0
 
cmp [esi],dword 'quit'
je close_fetch
 
 
no_send:
 
jmp still
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Close connection to server
;;
 
 
close_fetch:
 
mov eax,53
mov ebx,7
mov ecx,[socket]
mov edx,14
mov esi,quitc
mcall
mov [mcounter],0
 
mov eax,5
mov ebx,150
mcall
 
call read_incoming_data
 
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
 
mov eax,5
mov ebx,2
mcall
 
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
 
mov [server_active],0
 
jmp still
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; User input processing
;;
 
 
key:
 
mov eax,2
mcall
 
jmp still
 
 
button: ; button
 
mov eax,17 ; get id
mcall
 
cmp ah,60
jne no_open
mov eax, 70
mov ebx, tinypad_start
mcall
jmp still
no_open:
 
cmp ah,1 ; close program
jne noclose
mov eax,-1
mcall
noclose:
 
cmp ah,51
je read_string
cmp ah,52
je read_string
cmp ah,53
je read_string
 
call socket_commands
 
jmp still
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Socket open & close
;;
 
socket_commands:
 
cmp ah,22 ; open socket
jnz tst3
 
mov [server_active],1
 
mov [mcounter],900
mov [ccounter],0
 
mov eax,3
mcall
 
mov eax,3
mcall
mov ecx,eax
and ecx,0xffff
 
mov eax,53
mov ebx,5
mov edx,110
mov esi,dword [ip]
mov edi,1
mcall
mov [socket], eax
 
ret
tst3:
 
 
cmp ah,24 ; close socket
jnz no_24
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
mov [header_sent],0
mov [mail_rp],0
mov [server_active],0
 
ret
no_24:
 
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Display connection status
;;
 
old_status dd 0x0
 
print_status:
 
pusha
 
mov eax,53
mov ebx,6
mov ecx,[socket]
mcall
 
mov [status],eax
 
cmp eax,[old_status]
je nopr
 
mov [old_status],eax
 
push eax
 
mov eax,13
mov ebx,200*65536+30
mov ecx,160*65536+10
mov edx,0xffffff
mcall
 
pop ecx
 
cmp [server_active],1
jne nopr
 
mov eax,47
mov ebx,3*65536
mov edx,200*65536+160
mov esi,0x000000
mcall
 
nopr:
 
popa
 
ret
 
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Read data from server
;;
 
 
read_incoming_data:
 
pusha
 
read_new_byte:
 
call read_incoming_byte
cmp ecx,-1
je no_data_in_buffer
 
mov eax,[file_start]
mov [eax],bl
inc [file_start]
 
cmp bl,10
jne no_start_command
mov [cmd],1
no_start_command:
 
cmp bl,13
jne no_end_command
mov eax,[cmd]
mov [eax+command-2],byte 0
call save_file
call analyze_data
mov edi,command
mov ecx,250
mov eax,0
cld
rep stosb
mov [cmd],0
no_end_command:
 
mov eax,[cmd]
cmp eax,250
jge still
 
mov [eax+command-2],bl
inc [cmd]
 
jmp read_new_byte
 
no_data_in_buffer:
 
popa
 
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Read user input for ip/user/passwd
;;
 
 
read_string:
 
shr eax,8
sub eax,51
mov ebx,eax
imul eax,12
add eax,181
 
mov [len],ebx
shl [len],2
add [len],l1
 
imul ebx,50
add ebx,input1
 
mov [addr],ebx
mov [ya],eax
 
mov edi,[addr]
mov eax,0
mov ecx,30
cld
rep stosb
 
call print_input_text
 
mov edi,[addr]
 
f11:
mov eax,10
mcall
cmp eax,2
jne read_done
mov eax,2
mcall
shr eax,8
cmp eax,13
je read_done
cmp eax,8
jnz nobsl
cmp edi,[addr]
jz f11
sub edi,1
mov [edi],byte 32
call print_text
jmp f11
nobsl:
mov [edi],al
 
call print_input_text
 
add edi,1
mov esi,[addr]
add esi,30
cmp esi,edi
jnz f11
 
read_done:
 
push edi
 
mov ecx,40
mov eax,32
cld
rep stosb
 
call print_input_text
 
pop edi
sub edi,[addr]
mov eax,[len]
mov [eax],edi
 
cmp [len],l1
jne noip
mov esi,input1
mov edi,ip_text+15
mov ecx,16
cld
rep movsb
call ip_set
noip:
 
cmp [len],l2
jne nol2
mov esi,input2
mov edi,l2_text+15
mov ecx,22
cld
rep movsb
mov esi,input2
mov edi,getmail+5
mov ecx,[l2]
cld
rep movsb
mov al,13
stosb
mov al,10
stosb
nol2:
 
cmp [len],l3
jne nol3
mov esi,input3
mov edi,getmail+32+5
mov ecx,[l3]
cld
rep movsb
mov al,13
stosb
mov al,10
stosb
nol3:
 
call draw_window
 
jmp still
 
 
 
print_input_text:
 
pusha
 
mov eax,13
mov ebx,95*65536+23*6
mov ecx,[ya]
shl ecx,16
mov cx,9
mov edx,0xffffff
mcall
 
cmp [len],l3
je noprt
 
mov eax,4
mov edx,[addr]
mov ebx,95*65536
add ebx,[ya]
mov ecx,0x000000
mov esi,23
mcall
 
noprt:
 
popa
ret
 
 
ip_set:
 
mov esi,input1-1
mov edi,ip
xor eax,eax
ip1:
inc esi
cmp [esi],byte '0'
jb ip2
cmp [esi],byte '9'
jg ip2
imul eax,10
movzx ebx,byte [esi]
sub ebx,48
add eax,ebx
jmp ip1
ip2:
mov [edi],al
xor eax,eax
inc edi
cmp edi,ip+3
jbe ip1
ret
no_read_ip:
 
ret
 
 
analyze_data:
 
pusha
 
mov [text_start],I_END
mov ecx,[rxs]
imul ecx,11
mov [pos],ecx
 
mov bl,13
call print_character
mov bl,10
call print_character
 
cmp [cmd],2
jbe nott
mov ecx,[cmd]
sub ecx,2
mov esi,command+0
newcmdc:
mov bl,[esi]
call print_character
inc esi
loop newcmdc
 
nott:
 
mov edx,I_END
call draw_server_data
 
cmd_len_ok:
 
cmp [command],dword '-ERR'
je close_fetch
 
cmp [command],word '+O'
jne nook
mov [mcounter],990
nook:
 
popa
 
ret
 
 
 
draw_data:
 
push eax
 
add eax,[text_start]
mov [eax],bl
 
pop eax
ret
 
 
 
print_text:
 
pusha
 
mov ecx,command-2
add ecx,[cmd]
 
ptr2:
mov bl,[eax]
cmp bl,dl
je ptr_ret
cmp bl,0
je ptr_ret
call print_character
inc eax
cmp eax,ecx
jbe ptr2
 
ptr_ret:
 
mov eax,[text_start]
mov [eax+120*60],byte 1
 
popa
ret
 
 
 
print_character:
 
pusha
 
cmp bl,13 ; line beginning
jne nobol
mov ecx,[pos]
add ecx,1
boll1:
sub ecx,1
mov eax,ecx
xor edx,edx
mov ebx,[rxs]
div ebx
cmp edx,0
jne boll1
mov [pos],ecx
jmp newdata
nobol:
 
cmp bl,10 ; line down
jne nolf
addx1:
add [pos],dword 1
mov eax,[pos]
xor edx,edx
mov ecx,[rxs]
div ecx
cmp edx,0
jnz addx1
mov eax,[pos]
jmp cm1
nolf:
no_lf_ret:
 
 
cmp bl,15 ; character
jbe newdata
 
mov eax,[irc_data]
shl eax,8
mov al,bl
mov [irc_data],eax
 
mov eax,[pos]
call draw_data
 
mov eax,[pos]
add eax,1
cm1:
mov ebx,[scroll+4]
imul ebx,[rxs]
cmp eax,ebx
jb noeaxz
 
mov esi,[text_start]
add esi,[rxs]
 
mov edi,[text_start]
mov ecx,ebx
cld
rep movsb
 
mov esi,[text_start]
mov ecx,[rxs]
imul ecx,61
add esi,ecx
 
mov edi,[text_start]
mov ecx,[rxs]
imul ecx,60
add edi,ecx
mov ecx,ebx
cld
rep movsb
 
mov eax,ebx
sub eax,[rxs]
noeaxz:
mov [pos],eax
 
newdata:
 
mov eax,[text_start]
mov [eax+120*60],byte 1
 
popa
ret
 
 
 
read_incoming_byte:
 
mov eax, 53
mov ebx, 2
mov ecx, [socket]
mcall
 
mov ecx,-1
 
cmp eax,0
je no_more_data
 
mov eax, 53
mov ebx, 3
mov ecx, [socket]
mcall
 
mov ecx,0
 
no_more_data:
 
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Window definitions
;;
 
 
 
draw_window:
 
pusha
 
mov eax,12
mov ebx,1
mcall
 
mov eax,0 ; draw window
mov ebx,5*65536+435
mov ecx,5*65536+232
mov edx,0x14ffffff
mov edi,labelt
mcall
 
mov [old_status],300
 
mov eax,8 ; button: open socket
mov ebx,23*65536+22
mov ecx,155*65536+10
mov edx,22
mov esi,0x44cc44
mcall
 
; mov eax,8 ; button: close socket
mov ebx,295*65536+22
mov ecx,155*65536+10
mov edx,24
mov esi,0xcc4444
mcall
 
; mov eax,8 ; button: text entries
mov ebx,243*65536+8
mov ecx,180*65536+8
mov edx,51
mov esi,0x4488dd
newi:
mcall
inc edx
add ecx,12*65536
cmp edx,53
jbe newi
 
; mov eax,8 ; open inbox
mov ebx,295*65536+102
mov ecx,190*65536+14
mov edx,60
mov esi,0x5577dd
mcall
 
mov eax,38 ; line
mov ebx,5*65536+430
mov ecx,114*65536+114
mov edx,0x000000
mcall
 
mov ebx,5*65536+133 ; info text
mov ecx,0x000000
mov edx,text
mov esi,70
newline:
mov eax,4
mcall
add ebx,12
add edx,70
cmp [edx],byte 'x'
jne newline
 
mov edx,I_END ; text from server
call draw_server_data
 
mov eax,12
mov ebx,2
mcall
 
popa
 
ret
 
 
draw_server_data:
 
pusha
 
mov eax,4
mov ebx,10*65536+26
mov ecx,8
mov esi,[rxs]
dct:
pusha
mov ecx,ebx
shl ecx,16
mov cl,9
mov eax,13
mov ebx,10*65536
mov bx,word [rxs]
imul bx,6
mov edx,0xffffff
mcall
popa
push ecx
mov eax,4
mov ecx,0
mcall
add edx,[rxs]
add ebx,10
pop ecx
loop dct
 
popa
ret
 
 
 
text:
 
db ' Incoming mails are written to /rd/1/popc.txt '
db ' '
db ' Check for mail. Force close '
db ' '
ip_text:
db ' Server IP : 192.168.1.200 < '
l2_text:
db ' User : < Open popc.txt '
l3_text:
db ' Password : (not shown) < '
 
db 'x' ; <- END MARKER, DONT DELETE
 
file_start dd 0x100000
 
; max size is 0x100000 bytes, read to/write from 0x100000
files:
dd 2,0,0,?,0x100000
db 0
dd pr
filel:
dd 0,0,0,0x100000,0x100000
pr db '/sys/popc.txt',0
 
ip db 192,168,1,200
 
socket dd 0x0
 
posx dd 0x0
incoming_pos dd 0x0
incoming_string: times 128 db 0
pos dd 0x0
 
text_start dd I_END
print db 0x0
cmd dd 0x0
rxs dd 66
 
res: db 0,0
command: times 256 db 0x0
 
command_position dd 0
counter dd 0
 
numtext db ' '
labelt db 'POP client v ',version,0
scroll: dd 1,8
 
tinypad_start:
dd 7
dd 0
dd pr
dd 0
dd 0
db '/sys/TINYPAD',0
 
getmail:
db 'user xyz ',13,10
db 'pass xyz ',13,10
db 'retr 1 ',13,10
db 'retr 2 ',13,10
db 'retr 3 ',13,10
db 'retr 4 ',13,10
db 'retr 5 ',13,10
db 'retr 6 ',13,10
db 'retr 7 ',13,10
db 'retr 8 ',13,10
db 'retr 9 ',13,10
 
quitc:
db 'quit ',13,10
 
mcounter dd 900
ccounter dd 0
 
ld db 13,10
 
server_active db 0
 
header_sent db 0
 
close_connection dd 0x0
 
mail_rp dd 0
 
irc_data dd 0x0
addr dd 0x0
ya dd 0x0
len dd 0x0
 
input1: times 50 db 32
input2: times 50 db 32
input3: times 50 db 32
 
l1 dd 0
l2 dd 3
l3 dd 3
 
status dd 0x0
 
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/popc/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm popc.asm popc
@erase lang.inc
@pause
/programs/network_old/popc/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm popc.asm popc
@erase lang.inc
@pause
/programs/network_old/telnet/trunk/telnet.asm
0,0 → 1,793
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; TERMINAL
;
; Compile with FASM for Menuet
;
 
use32
org 0x0
db 'MENUET01' ; header
dd 0x01 ; header version
dd START ; entry point
dd I_END ; image size
dd I_END+0x10000 ; required memory
dd I_END+0x10000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Path
 
 
include 'lang.inc'
include 'macros.inc'
 
START: ; start of execution
 
; Clear the screen memory
mov eax, ' '
mov edi,text
mov ecx,80*30 /4
cld
rep stosd
 
 
call draw_window
 
 
still:
; check connection status
mov eax,53
mov ebx,6
mov ecx,[socket]
mcall
 
mov ebx, [socket_status]
mov [socket_status], eax
 
cmp eax, ebx
je waitev
 
red:
call draw_window
 
waitev:
mov eax,23 ; wait here for event
mov ebx,20
mcall
 
cmp eax,1 ; redraw request ?
je red
cmp eax,2 ; key in buffer ?
je key
cmp eax,3 ; button in buffer ?
je button
 
; any data from the socket?
 
mov eax, 53
mov ebx, 2
mov ecx, [socket]
mcall
cmp eax, 0
jne read_input
 
jmp still
 
 
read_input:
 
push ecx
mov eax, 53
mov ebx, 3
mov ecx, [socket]
mcall
pop ecx
 
call handle_data
 
push ecx
mov eax, 53
mov ebx, 2
mov ecx, [socket]
mcall
pop ecx
cmp eax, 0
 
 
jne read_input
call draw_text
jmp still
 
 
 
handle_data:
; Telnet servers will want to negotiate options about our terminal window
; just reject them all.
; Telnet options start with the byte 0xff and are 3 bytes long.
 
mov al, [telnetstate]
cmp al, 0
je state0
cmp al, 1
je state1
cmp al, 2
je state2
jmp hd001
 
state0:
cmp bl, 255
jne hd001
mov al, 1
mov [telnetstate], al
ret
 
state1:
mov al, 2
mov [telnetstate], al
ret
 
state2:
mov al, 0
mov [telnetstate], al
mov [telnetrep+2], bl
 
mov edx, 3
mov eax,53
mov ebx,7
mov ecx,[socket]
mov esi, telnetrep
mcall
ret
 
hd001:
cmp bl,13 ; BEGINNING OF LINE
jne nobol
mov ecx,[pos]
add ecx,1
boll1:
sub ecx,1
mov eax,ecx
xor edx,edx
mov ebx,80
div ebx
cmp edx,0
jne boll1
mov [pos],ecx
jmp newdata
nobol:
 
cmp bl,10 ; LINE DOWN
jne nolf
addx1:
add [pos],dword 1
mov eax,[pos]
xor edx,edx
mov ecx,80
div ecx
cmp edx,0
jnz addx1
mov eax,[pos]
jmp cm1
nolf:
 
cmp bl,8 ; BACKSPACE
jne nobasp
mov eax,[pos]
dec eax
mov [pos],eax
mov [eax+text],byte 32
mov [eax+text+60*80],byte 0
jmp newdata
nobasp:
 
cmp bl,15 ; CHARACTER
jbe newdata
mov eax,[pos]
mov [eax+text],bl
mov eax,[pos]
add eax,1
cm1:
mov ebx,[scroll+4]
imul ebx,80
cmp eax,ebx
jb noeaxz
mov esi,text+80
mov edi,text
mov ecx,ebx
cld
rep movsb
mov eax,ebx
sub eax,80
noeaxz:
mov [pos],eax
newdata:
ret
 
key: ; KEY
mov eax,2 ; send to modem
mcall
 
mov ebx, [socket_status]
cmp ebx, 4 ; connection open?
jne still ; no, so ignore key
 
shr eax,8
cmp eax,178 ; ARROW KEYS
jne noaup
mov al,'A'
call arrow
jmp still
noaup:
cmp eax,177
jne noadown
mov al,'B'
call arrow
jmp still
noadown:
cmp eax,179
jne noaright
mov al,'C'
call arrow
jmp still
noaright:
cmp eax,176
jne noaleft
mov al,'D'
call arrow
jmp still
noaleft:
modem_out:
 
call to_modem
 
jmp still
 
button: ; BUTTON
mov eax,17
mcall
cmp ah,1 ; CLOSE PROGRAM
jne noclose
 
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
 
or eax,-1
mcall
noclose:
cmp ah, 2 ; Set IP
jne notip
 
mov [string_x], dword 78
mov [string_y], dword 276
mov [string_length], dword 15
call read_string
mov esi,string-1
mov edi,ip_address
xor eax,eax
ip1:
inc esi
cmp [esi],byte '0'
jb ip2
cmp [esi],byte '9'
jg ip2
imul eax,10
movzx ebx,byte [esi]
sub ebx,48
add eax,ebx
jmp ip1
ip2:
mov [edi],al
xor eax,eax
inc edi
cmp edi,ip_address+3
jbe ip1
call draw_window
 
 
jmp still
 
notip:
cmp ah, 3 ; set port
jne notport
 
mov [string_x], dword 215
mov [string_y], dword 276
mov [string_length], dword 4
call read_string
mov esi,string-1
mov edi,port
xor eax,eax
ip11:
inc esi
cmp [esi],byte '0'
jb ip21
cmp [esi],byte '9'
jg ip21
imul eax,10
movzx ebx,byte [esi]
sub ebx,48
add eax,ebx
jmp ip11
ip21:
mov [edi],al
inc edi
mov [edi],ah
call draw_window
 
 
jmp still
 
notport:
cmp ah, 4 ; connect
jne notcon
 
mov eax, [socket_status]
cmp eax, 4
je still
call connect
 
jmp still
 
notcon:
cmp ah,5 ; disconnect
jne notdiscon
 
call disconnect
jmp still
 
notdiscon: ; Echo Toggle
cmp ah, 6
jne still
 
mov al, [echo]
not al
mov [echo], al
 
call draw_window
jmp still
 
arrow:
 
push eax
mov al,27
call to_modem
mov al,'['
call to_modem
pop eax
call to_modem
 
ret
 
 
to_modem:
pusha
push ax
mov [tx_buff], al
mov edx, 1
cmp al, 13
jne tm_000
mov edx, 2
tm_000:
mov eax,53
mov ebx,7
mov ecx,[socket]
mov esi, tx_buff
mcall
pop bx
mov al, [echo]
cmp al, 0
je tm_001
 
push bx
call handle_data
pop bx
 
cmp bl, 13
jne tm_002
 
mov bl, 10
call handle_data
 
tm_002:
call draw_text
 
tm_001:
popa
ret
 
 
 
disconnect:
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
ret
 
 
 
connect:
pusha
 
mov ecx, 1000 ; local port starting at 1000
 
getlp:
inc ecx
push ecx
mov eax, 53
mov ebx, 9
mcall
pop ecx
cmp eax, 0 ; is this local port in use?
jz getlp ; yes - so try next
 
mov eax,53
mov ebx,5
mov dl, [ip_address + 3]
shl edx, 8
mov dl, [ip_address + 2]
shl edx, 8
mov dl, [ip_address + 1]
shl edx, 8
mov dl, [ip_address]
mov esi, edx
movzx edx, word [port] ; telnet port id
mov edi,1 ; active open
mcall
mov [socket], eax
 
popa
 
ret
 
 
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
 
draw_window:
 
pusha
 
mov eax,12
mov ebx,1
mcall
 
xor eax,eax ; DRAW WINDOW
mov ebx,100*65536+491 + 8 +15
mov ecx,100*65536+270 + 20 ; 20 for status bar
mov edx,0x14000000
mov edi,title
mcall
 
; draw status bar
mov eax, 13
mov ebx, 4*65536+484 + 8 +15
mov ecx, 270*65536 + 3
mov edx, 0x00557799
mcall
 
mov eax,8 ; BUTTON 2: SET IP
mov ebx,4*65536+70
mov ecx,273*65536+12
mov esi, 0x00557799
mov edx,2
mcall
 
mov eax,4 ; Button text
mov ebx,6*65536+276
mov ecx,0x00ffffff
mov edx,setipt
mov esi,setiplen-setipt
mcall
 
 
mov eax,47
mov edi,ip_address ; display IP address
mov edx,78*65536+276
mov esi,0x00ffffff
mov ebx,3*65536
ipdisplay:
movzx ecx,byte [edi]
mcall
add edx,6*4*65536
inc edi
cmp edi,ip_address+4
jb ipdisplay
 
mov eax,8 ; BUTTON 3: SET PORT
mov ebx,173*65536+38
mov ecx,273*65536+12
mov edx,3
mov esi, 0x00557799
mcall
 
mov eax,4 ; Button text
mov ebx,178*65536+276
mov ecx,0x00ffffff
mov edx,setportt
mov esi,setportlen-setportt
mcall
 
 
mov edx,216*65536+276 ; display port
mov esi,0x00ffffff
mov ebx,4*65536
mov eax,47
movzx ecx,word [port]
mcall
 
mov eax,8 ; BUTTON 4: Connect
mov ebx,250*65536+50
mov ecx,273*65536+12
mov esi, 0x00557799
mov edx,4
mcall
 
mov eax,4 ; Button text
mov ebx,255*65536+276
mov ecx,0x00ffffff
mov edx,cont
mov esi,conlen-cont
mcall
 
 
mov eax,8 ; BUTTON 5: disconnect
mov ebx,303*65536+70
mov ecx,273*65536+12
mov edx,5
mov esi, 0x00557799
mcall
 
 
mov eax,4 ; Button text
mov ebx,307*65536+276
mov ecx,0x00ffffff
mov edx,dist
mov esi,dislen-dist
mcall
 
 
mov esi,contlen-contt ; display connected status
mov edx, contt
mov eax, [socket_status]
cmp eax, 4 ; 4 is connected
je pcon
mov esi,discontlen-discontt
mov edx, discontt
pcon:
 
mov eax,4 ; status text
mov ebx,380*65536+276
mov ecx,0x00ffffff
mcall
 
 
mov eax,8 ; BUTTON 6: echo
mov ebx,460*65536+50
mov ecx,273*65536+12
mov edx,6
mov esi, 0x00557799
mcall
 
mov edx,echot
mov esi,echolen-echot
mov al, [echo]
cmp al, 0
jne peo
mov edx,echoot
mov esi,echoolen-echoot
 
peo:
mov eax,4 ; Button text
mov ebx,463*65536+276
mov ecx,0x00ffffff
mcall
 
 
xor eax,eax
mov edi,text+80*30
mov ecx,80*30 /4
cld
rep stosd
 
call draw_text
 
mov eax,12
mov ebx,2
mcall
 
popa
 
ret
 
 
draw_text:
 
pusha
 
mov esi,text
mov eax,0
mov ebx,0
newletter:
mov cl,[esi]
cmp cl,[esi+30*80]
jne yesletter
jmp noletter
yesletter:
mov [esi+30*80],cl
 
; erase character
 
pusha
mov edx, 0 ; bg colour
mov ecx, ebx
add ecx, 26
shl ecx, 16
mov cx, 9
mov ebx, eax
add ebx, 6
shl ebx, 16
mov bx, 6
mov eax, 13
mcall
popa
 
; draw character
 
pusha
mov ecx, 0x00ffffff
push bx
mov ebx,eax
add ebx,6
shl ebx,16
pop bx
add bx,26
mov eax,4
mov edx,esi
mov esi,1
mcall
popa
 
noletter:
 
add esi,1
add eax,6
cmp eax,80*6
jb newletter
mov eax,0
add ebx,10
cmp ebx,24*10
jb newletter
 
popa
ret
 
 
read_string:
 
mov edi,string
mov eax,'_'
mov ecx,[string_length]
inc ecx
cld
rep stosb
call print_text
 
mov edi,string
f11:
mov eax,10
mcall
cmp eax,2
jne read_done
mov eax,2
mcall
shr eax,8
cmp eax,13
je read_done
cmp eax,8
jnz nobsl
cmp edi,string
jz f11
sub edi,1
mov [edi],byte '_'
call print_text
jmp f11
nobsl:
cmp eax,dword 31
jbe f11
cmp eax,dword 95
jb keyok
sub eax,32
keyok:
mov [edi],al
call print_text
 
inc edi
mov esi,string
add esi,[string_length]
cmp esi,edi
jnz f11
 
read_done:
 
call print_text
 
ret
 
 
print_text:
 
pusha
 
mov eax,13
mov ebx,[string_x]
shl ebx,16
add ebx,[string_length]
imul bx,6
mov ecx,[string_y]
shl ecx,16
mov cx,8
mov edx,0x00000000
mcall
 
mov eax,4
mov ebx,[string_x]
shl ebx,16
add ebx,[string_y]
mov ecx,0x00ffffff
mov edx,string
mov esi,[string_length]
mcall
 
popa
ret
 
 
 
 
; DATA AREA
 
telnetrep db 0xff,0xfc,0x00
telnetstate db 0
 
string_length dd 16
string_x dd 200
string_y dd 60
 
string db '________________'
 
tx_buff db 0, 10
ip_address db 001,002,003,004
port db 0,0
echo db 0
socket dd 0x0
socket_status dd 0x0
pos dd 80 * 1
scroll dd 1
dd 24
wcolor dd 0x000000
title db 'Telnet v0.1',0
setipt db 'IP Address: . . .'
setiplen:
setportt db 'Port:'
setportlen:
cont db 'Connect'
conlen:
dist db 'Disconnect'
dislen:
contt db 'Connected'
contlen:
discontt db 'Disconnected'
discontlen:
echot db 'Echo On'
echolen:
echoot db 'Echo Off'
echoolen:
 
 
 
text:
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/telnet/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm telnet.asm telnet
@erase lang.inc
@pause
/programs/network_old/telnet/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm telnet.asm telnet
@erase lang.inc
@pause
/programs/network_old/arpstat/trunk/arpstat.asm
0,0 → 1,416
;
; ARP Status Monitor
;
; Compile with FASM for Menuet
;
; This program displays the ARP table, and it's settings
use32
org 0x0
db 'MENUET00' ; 8 byte id
dd 38 ; required os
dd START ; program start
dd I_END ; program image size
dd 0x100000 ; required amount of memory
dd 0x00000000 ; reserved=no extended header
include 'lang.inc'
include '..\..\..\macros.inc'
purge mov ; decrease kpack'ed size
START: ; start of execution
call draw_window ; at first, draw the window
still:
mov eax,23 ; wait here for event
mov ebx,200 ; Time out after 2s
mcall
cmp eax,1 ; redraw request ?
jz red
cmp eax,2 ; key in buffer ?
jz key
cmp eax,3 ; button in buffer ?
jz button
; read the stack status data, and write it to the screen buffer
 
mov eax, 53
mov ebx, 255
mov ecx, 200
mcall
 
push eax
mov ebx, text + 24
call printhex
 
mov eax, 53
mov ebx, 255
mov ecx, 201
mcall
mov ebx, text + 64
call printhex
; Fill the table with blanks
mov edi, text + 160
doBlank:
mov esi, blank
mov ecx, 40
rep movsb
 
cmp edi, text + 560
jne doBlank
pop ecx ; The number of entries
mov ebx, text+ 160 +1 ; the position for the first IP address line
xor edx, edx ; edx is index into the ARP table
 
cmp ecx, 10
jle show_entries
mov ecx, 10
; The following code is not very efficient; Sorry about that.
; ARPSTAT is a debugging tool, so I didn't want to put much effort in
show_entries:
; Ecx now holds the number of entries to populate.
; Ebx holds the place to put the data
; edx is a counter
cmp ecx, 0
je red
push ecx
push edx
push ebx
 
; select the arp table entry (in edx)
mov eax, 53
mov ebx, 255
mov ecx, 202
mcall
; Read the IP address
mov eax, 53
mov ebx, 255
mov ecx, 203
mcall
; IP in eax. Get the address to put it back
pop ebx
push ebx
call writeDecimal ; Extract 1 byte from eax, store it in string
add ebx, 4
shr eax, 8
call writeDecimal ; Extract 1 byte from eax, store it in string
add ebx, 4
shr eax, 8
call writeDecimal ; Extract 1 byte from eax, store it in string
add ebx, 4
shr eax, 8
call writeDecimal ; Extract 1 byte from eax, store it in string
 
add ebx, 4
; Now display the 6 byte MAC
push ebx
mov eax, 53
mov ebx, 255
mov ecx, 204
mcall
pop ebx
mov ecx, eax
 
shr eax, 4
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
shr eax, 12
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
shr eax, 8
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
shr eax, 20
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
shr eax, 16
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
shr eax, 28
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
shr eax, 24
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
 
push ebx
mov eax, 53
mov ebx, 255
mov ecx, 205
mcall
pop ebx
mov ecx, eax
 
shr eax, 4
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
shr eax, 12
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
shr eax, 8
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
 
; Now display the stat field
inc ebx
inc ebx
push ebx
mov eax, 53
mov ebx, 255
mov ecx, 206
mcall
pop ebx
mov ecx, eax
 
shr eax, 4
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
shr eax, 12
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
shr eax, 8
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
; Now display the TTL field (this is intel word format)
inc ebx
inc ebx
push ebx
mov eax, 53
mov ebx, 255
mov ecx, 207
mcall
pop ebx
mov ecx, eax
 
shr eax, 12
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
shr eax, 8
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
shr eax, 4
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
inc ebx
mov eax, ecx
and eax, 0x0f
mov al, [eax + hextable]
mov [ebx], al
 
pop ebx
add ebx, 40
pop edx
inc edx
pop ecx
dec ecx
jmp show_entries
 
red: ; redraw
call draw_window
jmp still
key: ; Keys are not valid at this part of the
mov eax,2 ; loop. Just read it and ignore
mcall
jmp still
button: ; button
mov eax,17 ; get id
mcall
cmp ah,1 ; button id=1 ?
jnz still
 
mov eax,0xffffffff ; close this program
mcall
 
 
writeDecimal:
pusha
and eax, 0xff
mov dl, 100
div dl
movzx ecx, ah
add al, '0'
mov [ebx], al
inc ebx
mov eax, ecx
mov dl, 10
div dl
add ax, '00'
mov [ebx], ax
popa
ret
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
draw_window:
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,100*65536+280 ; [x start] *65536 + [x size]
mov ecx,100*65536+270 ; [y start] *65536 + [y size]
mov edx,0x14224466 ; color of work area RRGGBB
mov edi,title ; WINDOW LABEL
mcall
; Re-draw the screen text
cld
mov eax,4
mov ebx,25*65536+35 ; draw info text with function 4
mov ecx,0xffffff
mov edx,text
mov esi,40
newline:
mcall
add ebx,16
add edx,esi
cmp [edx],byte 'x'
jnz newline
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
ret
; Taken from PS.ASM
printhex:
; number in eax
; print to ebx
; xlat from hextable
pusha
mov esi, ebx
add esi, 8
mov ebx, hextable
mov ecx, 8
phex_loop:
mov edx, eax
and eax, 15
xlatb
mov [esi], al
mov eax, edx
shr eax, 4
dec esi
loop phex_loop
popa
ret
; DATA AREA
text:
db ' Number of ARP entries: xxxxxxxx '
db ' Maximum # of entries : xxxxxxxx '
db ' '
db ' IP Address MAC Stat TTL '
db ' xxx.xxx.xxx.xxx xxxxxxxxxxxx xxxx xxxx '
db ' xxx.xxx.xxx.xxx xxxxxxxxxxxx xxxx xxxx '
db ' xxx.xxx.xxx.xxx xxxxxxxxxxxx xxxx xxxx '
db ' xxx.xxx.xxx.xxx xxxxxxxxxxxx xxxx xxxx '
db ' xxx.xxx.xxx.xxx xxxxxxxxxxxx xxxx xxxx '
db ' xxx.xxx.xxx.xxx xxxxxxxxxxxx xxxx xxxx '
db ' xxx.xxx.xxx.xxx xxxxxxxxxxxx xxxx xxxx '
db ' xxx.xxx.xxx.xxx xxxxxxxxxxxx xxxx xxxx '
db ' xxx.xxx.xxx.xxx xxxxxxxxxxxx xxxx xxxx '
db ' xxx.xxx.xxx.xxx xxxxxxxxxxxx xxxx xxxx '
db 'x' ; <- END MARKER, DONT DELETE
 
blank:
db ' xxx.xxx.xxx.xxx xxxxxxxxxxxx xxxx xxxx '
 
title db 'ARP Table ( First 10 Entries )',0
hextable db '0123456789ABCDEF'
 
 
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/arpstat/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm arpstat.asm arpstat
@erase lang.inc
@pause
/programs/network_old/arpstat/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm arpstat.asm arpstat
@erase lang.inc
@pause
/programs/network_old/chess/trunk/chess.asm
0,0 → 1,1301
;
; CHESS CLIENT for CHESSCLUB.COM (VT)
;
; Compile with FASM for Menuet
;
 
appname equ 'Chess Client for Chessclub.com '
version equ '0.2'
 
use32
org 0x0
db 'MENUET01' ; header
dd 0x01 ; header version
dd START ; entry point
dd I_END ; image size
dd 0x100000 ; required memory
dd 0x100000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Path
 
include 'lang.inc'
include '..\..\..\macros.inc'
 
pawn_color:
 
dd 0x000000
dd 0x222222
dd 0x444444
dd 0xf0f0f0
dd 0xc0c0c0
dd 0xa0a0a0
dd 0xa0a0a0
dd 0x707070
dd 0xb0b0b0
dd 0xc0c0c0
dd 0xd0d0d0
dd 0xd8d8d8
dd 0xe0e0e0
dd 0xe8e8e8
dd 0x00ff00
dd 0xffffff
 
 
 
texts equ board_old+80*30
 
text equ texts+80*32*4
 
 
START: ; start of execution
 
mov esi,chess_bmp
mov edi,0x10000+18*3
 
mov ebx,0
mov ecx,0
 
newp:
 
xor eax,eax
mov al,[esi]
and al,0xf0
shr al,4
shl eax,2
mov eax,[pawn_color+eax]
mov [edi+0],eax
 
xor eax,eax
mov al,[esi]
and al,0x0f
shl eax,2
mov eax,[pawn_color+eax]
mov [edi+3],eax
 
add edi,6
add esi,1
 
inc ebx
cmp ebx,23
jbe newp
 
sub edi,12
 
mov ebx,0
 
inc ecx
cmp ecx,279
jb newp
 
; Clear the screen memory
mov eax, ' '
mov edi,text
mov ecx,80*30 /4
cld
rep stosd
 
 
call draw_window
 
still:
 
call check_for_board
 
call board_changed
 
call draw_board
 
; check connection status
mov eax,53
mov ebx,6
mov ecx,[socket]
mcall
 
mov ebx, [socket_status]
mov [socket_status], eax
 
cmp eax, ebx
je waitev
 
call display_status
 
waitev:
mov eax,23 ; wait here for event
mov ebx,20
mcall
 
cmp eax,1 ; redraw request ?
je red
cmp eax,2 ; key in buffer ?
je key
cmp eax,3 ; button in buffer ?
je button
 
; any data from the socket?
 
mov eax, 53
mov ebx, 2
mov ecx, [socket]
mcall
cmp eax, 0
jne read_input
 
jmp still
 
 
read_input:
 
push ecx
mov eax, 53
mov ebx, 3
mov ecx, [socket]
mcall
pop ecx
 
call handle_data
 
push ecx
mov eax, 53
mov ebx, 2
mov ecx, [socket]
mcall
pop ecx
cmp eax, 0
 
 
jne read_input
call draw_text
jmp still
 
 
 
check_for_board:
 
pusha
 
mov esi,text-80
news:
add esi,80
cmp esi,text+80*10
je board_not_found
cmp [esi+12],dword '----'
je cfb1
jmp news
cfb1:
cmp [esi+16*80+12],dword '----'
je cfb2
jmp news
cfb2:
cmp [esi+2*80+12],dword '+---'
jne news
 
cmp [esi+4*80+12],dword '+---'
jne news
 
board_found:
 
mov edi,chess_board
mov ecx,80*18
cld
rep movsb
 
board_not_found:
 
popa
 
ret
 
 
yst dd 150
textx equ 10
ysts equ 410
 
boardx dd 45
boardy dd 45
 
boardxs dd 44
boardys dd 44
 
conx equ 420
cony equ 118
 
dconx equ 420
dcony equ 148
 
statusx equ 420
statusy equ 178
 
 
drsq:
 
push eax ebx
 
mov ecx,ebx
mov ebx,eax
 
mov eax,ebx
add eax,ecx
 
imul ebx,[boardxs]
add ebx,[boardx]
shl ebx,16
imul ecx,[boardys]
add ecx,[boardy]
shl ecx,16
 
add ebx,[boardxs]
add ecx,[boardys]
 
mov edx,[sq_black]
test eax,1
jnz dbl22
mov edx,[sq_white]
dbl22:
 
mov eax,13
mcall
 
pop ebx eax
 
ret
 
 
 
draw_pawn:
 
; edi,0 ; white / black
; esi,0 ; from position 2 , 20 square
; eax,2 ; board x
; ebx,0 ; board y
 
pusha
 
call drsq
 
cmp esi,20
jne no_sqd
 
popa
ret
 
no_sqd:
 
imul eax,[boardxs]
imul ebx,[boardys]
 
add eax,[boardx]
add ebx,[boardy]
 
imul esi,44*45*3
add esi,0x10000+18*3
 
mov ecx,43
 
dp0:
 
pusha
 
mov ecx,44
 
ldp1:
 
pusha
 
mov ecx,ebx
mov ebx,eax
 
mov edx,[esi]
and edx,0xffffff
mov eax,1
cmp edx,0x00ff00
je nowp
cmp edi,1
jne nobl
shr edx,1
and edx,0x7f7f7f
nobl:
mcall
nowp:
 
popa
 
add esi,3
add eax,1
 
dec ecx
jnz ldp1
 
popa
 
add ebx,1
add esi,3*44
 
dec ecx
jnz dp0
 
popa
 
ret
 
 
board_changed:
 
pusha
 
mov eax,0
mov esi,chess_board
bcl1:
add eax,[esi]
add esi,4
cmp esi,chess_board+19*80
jb bcl1
 
cmp eax,[checksum]
je bcl2
mov [changed],1
bcl2:
mov [checksum],eax
 
popa
 
ret
 
 
 
checksum dd 0
 
changed db 1
 
draw_board:
 
pusha
 
cmp [changed],1
jne no_change_in_board
 
mov [changed],0
 
mov eax,0
mov ebx,0
scan_board:
 
push eax ebx
 
mov esi,ebx
imul esi,2
imul esi,80
add esi,80
 
imul eax,4
add eax,10
 
add esi,eax
 
movzx edx,word [chess_board+esi]
cmp dx,[board_old+esi]
je empty_slot
 
mov ecx,13
newseek2:
mov edi,ecx
imul edi,8
sub edi,8
cmp dx,[edi+nappulat]
je foundnappula2
loop newseek2
 
jmp empty_slot
 
foundnappula2:
 
mov esi,[edi+nappulat+4]
mov edi,0
cmp dl,'*'
jne nnbb
mov edi,1
nnbb:
mov eax,[esp+4]
mov ebx,[esp]
call draw_pawn
 
empty_slot:
 
pop ebx eax
 
inc eax
cmp eax,8
jb scan_board
mov eax,0
inc ebx
cmp ebx,8
jb scan_board
 
mov esi,chess_board
mov edi,board_old
mov ecx,80*19
cld
rep movsb
 
mov eax,13
mov ebx,[boardx]
sub ebx,14
shl ebx,16
add ebx,8
mov ecx,[boardy]
shl ecx,16
add ecx,46*8
mov edx,[wcolor]
mcall
 
mov eax,4 ; numbers at left
mov ebx,[boardx]
sub ebx,14
shl ebx,16
add ebx,[boardy]
add ebx,18
mov ecx,[tcolor]
mov edx,chess_board+80+5
mov esi,3
db1:
mcall
add edx,80*2
add ebx,[boardxs]
cmp edx,chess_board+80*16
jb db1
 
mov eax,13
mov ebx,[boardx]
shl ebx,16
add ebx,8*46
mov ecx,[boardys]
imul ecx,8
add ecx,[boardy]
add ecx,8
shl ecx,16
add ecx,10
mov edx,[wcolor]
mcall
 
mov eax,4 ; letters at bottom
mov ebx,[boardx]
add ebx,3
shl ebx,16
mov bx,word [boardys]
imul bx,8
add ebx,[boardy]
add ebx,8
mov ecx,[tcolor]
mov edx,chess_board+80*17+8
mov esi,4
db3:
mcall
mov edi,[boardxs]
shl edi,16
add ebx,edi
add edx,4
cmp edx,chess_board+80*17+8+4*8
jb db3
 
; print player times
 
mov edi,74
cmp [chess_board+80+5],byte '1'
jne nowww2
mov edi,371
nowww2:
 
mov eax,13
mov ebx,(conx)*65536+100
mov ecx,edi
shl ecx,16
add ecx,10
mov edx,[wcolor]
mcall
 
mov eax,4
mov ebx,(conx)*65536
add ebx,edi
mov ecx,[tcolor]
mov edx,chess_board+80*7+59-1
mov esi,20
mcall
 
mov edi,74
cmp [chess_board+80+5],byte '1'
je nowww
mov edi,371
nowww:
 
mov eax,13
mov ebx,(conx)*65536+100
mov ecx,edi
shl ecx,16
add ecx,10
mov edx,[wcolor]
mcall
 
mov eax,4
mov ebx,(conx)*65536
add ebx,edi
mov ecx,[tcolor]
mov edx,chess_board+80*9+59-1
mov esi,20
mcall
 
; move #
 
mov eax,13
mov ebx,conx*65536+120
mov ecx,200*65536+10
mov edx,[wcolor]
mcall
 
mov eax,4
mov ebx,conx*65536
add ebx,200
mov ecx,[tcolor]
mov edx,chess_board+80*1+46
mov esi,30
mcall
 
no_change_in_board:
 
popa
 
ret
 
 
handle_data:
; Telnet servers will want to negotiate options about our terminal window
; just reject them all.
; Telnet options start with the byte 0xff and are 3 bytes long.
 
mov al, [telnetstate]
cmp al, 0
je state0
cmp al, 1
je state1
cmp al, 2
je state2
jmp hd001
 
state0:
cmp bl, 255
jne hd001
mov al, 1
mov [telnetstate], al
ret
 
state1:
mov al, 2
mov [telnetstate], al
ret
 
state2:
mov al, 0
mov [telnetstate], al
mov [telnetrep+2], bl
 
mov edx, 3
mov eax,53
mov ebx,7
mov ecx,[socket]
mov esi, telnetrep
mcall
ret
 
hd001:
cmp bl,13 ; BEGINNING OF LINE
jne nobol
mov ecx,[pos]
add ecx,1
boll1:
sub ecx,1
mov eax,ecx
xor edx,edx
mov ebx,80
div ebx
cmp edx,0
jne boll1
mov [pos],ecx
 
call check_for_board
 
jmp newdata
nobol:
 
cmp bl,10 ; LINE DOWN
jne nolf
addx1:
add [pos],dword 1
mov eax,[pos]
xor edx,edx
mov ecx,80
div ecx
cmp edx,0
jnz addx1
mov eax,[pos]
jmp cm1
nolf:
 
cmp bl,9 ; TAB
jne notab
add [pos],dword 8
jmp newdata
notab:
 
cmp bl,8 ; BACKSPACE
jne nobasp
mov eax,[pos]
dec eax
mov [pos],eax
mov [eax+text],byte 32
mov [eax+text+60*80],byte 0
jmp newdata
nobasp:
 
cmp bl,15 ; CHARACTER
jbe newdata
mov eax,[pos]
mov [eax+text],bl
mov eax,[pos]
add eax,1
cm1:
mov ebx,[scroll+4]
imul ebx,80
cmp eax,ebx
jb noeaxz
mov esi,text+80
mov edi,text
mov ecx,ebx
cld
rep movsb
mov eax,ebx
sub eax,80
noeaxz:
mov [pos],eax
newdata:
ret
 
 
red: ; REDRAW WINDOW
call draw_window
jmp still
 
key: ; KEY
mov eax,2 ; send to modem
mcall
 
mov ebx, [socket_status]
cmp ebx, 4 ; connection open?
jne still ; no, so ignore key
 
shr eax,8
cmp eax,178 ; ARROW KEYS
jne noaup
mov al,'A'
call arrow
jmp still
noaup:
cmp eax,177
jne noadown
mov al,'B'
call arrow
jmp still
noadown:
cmp eax,179
jne noaright
mov al,'C'
call arrow
jmp still
noaright:
cmp eax,176
jne noaleft
mov al,'D'
call arrow
jmp still
noaleft:
modem_out:
 
call to_modem
 
jmp still
 
button: ; BUTTON
mov eax,17
mcall
cmp ah,1 ; CLOSE PROGRAM
jne noclose
 
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
 
mov eax,-1
mcall
noclose:
 
cmp ah, 4 ; connect
jne notcon
 
mov eax, [socket_status]
cmp eax, 4
je still
call connect
 
jmp still
 
notcon:
cmp ah,5 ; disconnect
jne notdiscon
 
call disconnect
jmp still
 
notdiscon:
 
jmp still
 
arrow:
 
push eax
mov al,27
call to_modem
mov al,'['
call to_modem
pop eax
call to_modem
 
ret
 
 
to_modem:
pusha
push ax
mov [tx_buff], al
mov edx, 1
cmp al, 13
jne tm_000
mov edx, 2
tm_000:
mov eax,53
mov ebx,7
mov ecx,[socket]
mov esi, tx_buff
mcall
pop bx
mov al, [echo]
cmp al, 0
je tm_001
 
push bx
call handle_data
pop bx
 
cmp bl, 13
jne tm_002
 
mov bl, 10
call handle_data
 
tm_002:
call draw_text
 
tm_001:
popa
ret
 
 
 
disconnect:
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
ret
 
 
 
connect:
pusha
 
mov ecx, 1000 ; local port starting at 1000
 
getlp:
inc ecx
push ecx
mov eax, 53
mov ebx, 9
mcall
pop ecx
cmp eax, 0 ; is this local port in use?
jz getlp ; yes - so try next
 
mov eax,53
mov ebx,5
mov dl, [ip_address + 3]
shl edx, 8
mov dl, [ip_address + 2]
shl edx, 8
mov dl, [ip_address + 1]
shl edx, 8
mov dl, [ip_address]
mov esi, edx
movzx edx, word [port] ; telnet port id
mov edi,1 ; active open
mcall
mov [socket], eax
 
popa
 
ret
 
 
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
 
draw_window:
 
pusha
 
mov eax,12
mov ebx,1
mcall
 
mov eax,14
mcall
 
mov ebx,eax
mov ecx,eax
 
shr ebx,16
and ebx,0xffff
and ecx,0xffff
 
shr ebx,1
shr ecx,1
 
sub ebx,275
sub ecx,235
 
shl ebx,16
shl ecx,16
 
mov eax,0 ; DRAW WINDOW
mov bx,550
mov cx,470
mov edx,[wcolor]
add edx,0x14000000
mov edi,title
mcall
 
call display_status
 
mov eax,8 ; BUTTON 4: Connect
mov ebx,conx*65536+80
mov ecx,cony*65536+15
mov esi,[wbutton]
mov edx,4
mcall
mov eax,4 ; Button text
mov ebx,(conx+4)*65536+cony+4
mov ecx,0xffffff
mov edx,cont
mov esi,conlen-cont
mcall
 
 
mov eax,8 ; BUTTON 5: disconnect
mov ebx,dconx*65536+80
mov ecx,dcony*65536+15
mov edx,5
mov esi,[wbutton]
mcall
mov eax,4 ; Button text
mov ebx,(dconx+4)*65536+dcony+4
mov ecx,0x00ffffff
mov edx,dist
mov esi,dislen-dist
mcall
 
 
xor eax,eax
mov edi,text+80*30
mov ecx,80*30 /4
cld
rep stosd
 
call draw_text
 
mov [changed],1
 
mov edi,board_old
mov ecx,80*19
mov al,0
cld
rep stosb
 
mov eax,4
mov ebx,conx*65536+52
mov ecx,[tcolor]
mov edx,quick_start
mov esi,30
 
prqs:
 
mcall
add ebx,10
add edx,30
cmp [edx],byte 'x'
jne prqs
 
mov eax,12
mov ebx,2
mcall
 
popa
 
ret
 
 
display_status:
 
pusha
 
; draw status bar
mov eax, 13
mov ebx, statusx*65536+80
mov ecx, statusy*65536 + 16
mov edx, [wcolor]
mcall
 
mov esi,contlen-contt ; display connected status
mov edx, contt
mov eax, [socket_status]
cmp eax, 4 ; 4 is connected
je pcon
mov esi,discontlen-discontt
mov edx, discontt
pcon:
mov eax,4 ; status text
mov ebx,statusx*65536+statusy+2
mov ecx,[tcolor]
mcall
 
popa
ret
 
 
nappulat:
 
dd '*P ',5
dd '*K ',3
dd '*Q ',4
dd '*R ',0
dd '*N ',1
dd '*B ',2
 
dd ' ',20
 
dd 'P ',5
dd 'K ',3
dd 'Q ',4
dd 'R ',0
dd 'N ',1
dd 'B ',2
 
 
row dd 0x0
col dd 0x0
 
 
 
draw_text:
 
mov esi,text+80*24
mov edi,texts+80*3
 
dtl1:
 
cmp [esi],dword 'logi'
je add_text
cmp [esi],dword 'aics'
je add_text
cmp [esi],dword 'You '
je add_text
cmp [esi],dword 'Your'
je add_text
cmp [esi],dword 'Game'
je add_text
cmp [esi],dword 'Ille'
je add_text
cmp [esi],dword 'No s'
je add_text
 
sub esi,80
cmp esi,text
jge dtl1
 
dtl2:
 
mov eax,13
mov ebx,10*65536+532
mov ecx,420*65536+40
mov edx,[wtcom]
mcall
 
mov eax,4
mov ebx,10*65536+420
mov ecx,[wtxt]
mov edx,texts
mov esi,80
 
dtl3:
 
mcall
add edx,80
add ebx,10
cmp edx,texts+4*80
jb dtl3
 
ret
 
add_text:
 
pusha
 
cld
mov ecx,80
rep movsb
 
popa
 
 
sub esi,80
sub edi,80
 
cmp edi,texts
jb dtl2
 
jmp dtl1
 
 
read_string:
 
mov edi,string
mov eax,'_'
mov ecx,[string_length]
inc ecx
cld
rep stosb
call print_text
 
mov edi,string
f11:
mov eax,10
mcall
cmp eax,2
jne read_done
mov eax,2
mcall
shr eax,8
cmp eax,13
je read_done
cmp eax,8
jnz nobsl
cmp edi,string
jz f11
sub edi,1
mov [edi],byte '_'
call print_text
jmp f11
nobsl:
cmp eax,dword 31
jbe f11
cmp eax,dword 95
jb keyok
sub eax,32
keyok:
mov [edi],al
call print_text
 
inc edi
mov esi,string
add esi,[string_length]
cmp esi,edi
jnz f11
 
read_done:
 
call print_text
 
ret
 
 
print_text:
 
pusha
 
mov eax,13
mov ebx,[string_x]
shl ebx,16
add ebx,[string_length]
imul bx,6
mov ecx,[string_y]
shl ecx,16
mov cx,8
mov edx,[wcolor]
mcall
 
mov eax,4
mov ebx,[string_x]
shl ebx,16
add ebx,[string_y]
mov ecx,[tcolor]
mov edx,string
mov esi,[string_length]
mcall
 
popa
ret
 
 
 
 
; DATA AREA
 
telnetrep db 0xff,0xfc,0x00
telnetstate db 0
 
string_length dd 16
string_x dd 200
string_y dd 60
 
string db '________________'
 
tx_buff db 0, 10
ip_address db 204,178,125,65
port dw 5051 ; 0,0
echo db 1
socket dd 0x0
socket_status dd 0x0
pos dd 80 * 22
scroll dd 1
dd 24
 
wbutton dd 0x336688
 
wtcom dd 0x336688 ; 0x666666
wtxt dd 0xffffff
 
wcolor dd 0xe0e0e0
tcolor dd 0x000000
 
sq_black dd 0x336688 ; 666666
sq_white dd 0xffffff
 
title db appname,version,0
 
setipt db ' . . .'
setiplen:
setportt db ' '
setportlen:
cont db 'Connect'
conlen:
dist db 'Disconnect'
dislen:
contt db 'Connected'
contlen:
discontt db 'Disconnected'
discontlen:
echot db 'Echo On'
echolen:
echoot db 'Echo Off'
echoolen:
 
quick_start:
 
db '( OPPONENT ) '
 
times 16 db ' 1'
 
db 'Quick start: '
db ' '
db '1 Connect '
db '2 login: "guest" '
db '3 aics% "seek 10 0" '
db ' (for a player) '
db ' (wait) '
db '4 Play eg. "e7e5" '
db ' or "d2d4" '
db '5 aics% "resign" '
db ' (quit game) '
db '6 Disconnect '
 
times 5 db ' '
 
db '( YOU ) '
 
db 'x'
 
 
chess_board:
 
times 80 db 0
 
db ' 8 *R *N *B *Q *K *B *N *R'
db ' '
 
times 80 db 0
 
db ' 7 *P *P *P *P *P *P *P *P'
db ' '
 
times 80 db 0
 
db ' 6 '
db ' '
 
times 80 db 0
 
db ' 5 '
db ' '
 
times 80 db 0
 
db ' 4 '
db ' '
 
times 80 db 0
 
db ' 3 '
db ' '
 
times 80 db 0
 
db ' 2 P P P P P P P P '
db ' '
 
times 80 db 0
 
db ' 1 R N B Q K B N R '
db ' '
 
times 80 db 0
 
db ' a b c d e f g h '
db ' '
 
 
times 80*20 db 0
 
chess_bmp:
file 'chess.bmp':22*3+4+24*2
 
board_old:
 
 
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/chess/trunk/chess.bmp
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/programs/network_old/chess/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm chess.asm chess
@erase lang.inc
@pause
/programs/network_old/chess/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm chess.asm chess
@erase lang.inc
@pause
/programs/network_old/dhcp/trunk/dhcp.asm
0,0 → 1,582
;
; DHCP Client
;
; Compile with FASM for Menuet
;
 
include 'lang.inc'
include '..\..\..\macros.inc'
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image
dd I_END+0x8000 ; memory for app
dd I_END+0x8000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Icon
 
 
START: ; start of execution
mov eax,40 ; Report events
mov ebx,10000111b ; Stack 8 + defaults
int 0x40
 
red: ; redraw
call draw_window ; at first, draw the window
 
still:
mov eax,10 ; wait here for event
mcall
 
cmp eax,1 ; redraw request ?
jz red
cmp eax,2 ; key in buffer ?
jz key
cmp eax,3 ; button in buffer ?
jz button
 
jmp still
key: ; Keys are not valid at this part of the
mov eax,2 ; loop. Just read it and ignore
mcall
jmp still
 
button: ; button
mov eax,17 ; get id
mcall
 
cmp ah,1 ; button id=1 ?
jnz noclose
 
; close socket before exiting
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
mcall
 
mov eax,0xffffffff ; close this program
mcall
 
noclose:
cmp ah,3 ; Resolve address?
jnz still
 
call draw_window
 
call contactDHCPServer
 
jmp still
 
 
;***************************************************************************
; Function
; parseResponse
;
; Description
; extracts the fields ( client IP address and options ) from
; a DHCP response
; The values go into
; dhcpMsgType,dhcpLease,dhcpClientIP,dhcpServerIP,
; dhcpDNSIP, dhcpSubnet
; The message is stored in dhcpMsg
;
;***************************************************************************
parseResponse:
mov edx, dhcpMsg
 
mov eax, [edx+16]
mov [dhcpClientIP], eax
 
; Scan options
 
add edx, 240 ; Point to first option
 
pr001:
; Get option id
mov al, [edx]
cmp al, 0xff ; End of options?
je pr_exit
 
cmp al, 53 ; Msg type is a single byte option
jne pr002
 
mov al, [edx+2]
mov [dhcpMsgType], al
add edx, 3
jmp pr001 ; Get next option
 
pr002:
; All other (accepted) options are 4 bytes in length
inc edx
movzx ecx, byte [edx]
inc edx ; point to data
 
cmp al, 54 ; server id
jne pr0021
mov eax, [edx] ; All options are 4 bytes, so get it
mov [dhcpServerIP], eax
jmp pr003
 
pr0021:
cmp al, 51 ; lease
jne pr0022
mov eax, [edx] ; All options are 4 bytes, so get it
mov [dhcpLease], eax
jmp pr003
 
pr0022:
cmp al, 1 ; subnet mask
jne pr0023
mov eax, [edx] ; All options are 4 bytes, so get it
mov [dhcpSubnet], eax
jmp pr003
 
pr0023:
cmp al, 6 ; dns ip
jne pr0024
mov eax, [edx] ; All options are 4 bytes, so get it
mov [dhcpDNSIP], eax
 
pr0024:
cmp al, 3 ; gateway ip
jne pr003
mov eax, [edx] ; All options are 4 bytes, so get it
mov [dhcpGateway], eax
 
pr003:
add edx, ecx
jmp pr001
 
pr_exit:
ret
 
 
;***************************************************************************
; Function
; buildRequest
;
; Description
; Creates a DHCP request packet.
;
;***************************************************************************
buildRequest:
; Clear dhcpMsg to all zeros
xor eax,eax
mov edi,dhcpMsg
mov ecx,512
cld
rep stosb
 
mov edx, dhcpMsg
 
mov [edx], byte 0x01 ; Boot request
mov [edx+1], byte 0x01 ; Ethernet
mov [edx+2], byte 0x06 ; Ethernet h/w len
mov [edx+4], dword 0x11223344 ; xid
mov [edx+10], byte 0x80 ; broadcast flag set
mov [edx+236], dword 0x63538263 ; magic number
 
; option DHCP msg type
mov [edx+240], word 0x0135
mov al, [dhcpMsgType]
mov [edx+240+2], al
 
; option Lease time = infinity
mov [edx+240+3], word 0x0433
mov eax, [dhcpLease]
mov [edx+240+5], eax
 
; option requested IP address
mov [edx+240+9], word 0x0432
mov eax, [dhcpClientIP]
mov [edx+240+11], eax
 
; option request list
mov [edx+240+15], word 0x0437
mov [edx+240+17], dword 0x0f060301
 
; Check which msg we are sending
cmp [dhcpMsgType], byte 0x01
jne br001
 
; "Discover" options
; end of options marker
mov [edx+240+21], byte 0xff
 
mov [dhcpMsgLen], dword 262
jmp br_exit
 
br001:
; "Request" options
 
; server IP
mov [edx+240+21], word 0x0436
mov eax, [dhcpServerIP]
mov [edx+240+23], eax
 
; end of options marker
mov [edx+240+27], byte 0xff
 
mov [dhcpMsgLen], dword 268
 
br_exit:
ret
 
 
 
;***************************************************************************
; Function
; contactDHCPServer
;
; Description
; negotiates settings with a DHCP server
;
;***************************************************************************
contactDHCPServer:
; First, open socket
mov eax, 53
mov ebx, 0
mov ecx, 68 ; local port dhcp client
mov edx, 67 ; remote port - dhcp server
mov esi, 0xffffffff ; broadcast
mcall
 
mov [socketNum], eax
 
; Setup the first msg we will send
mov [dhcpMsgType], byte 0x01 ; DHCP discover
mov [dhcpLease], dword 0xffffffff
mov [dhcpClientIP], dword 0
mov [dhcpServerIP], dword 0
 
call buildRequest
 
ctr000:
; write to socket ( send broadcast request )
mov eax, 53
mov ebx, 4
mov ecx, [socketNum]
mov edx, [dhcpMsgLen]
mov esi, dhcpMsg
mcall
 
; Setup the DHCP buffer to receive response
 
mov eax, dhcpMsg
mov [dhcpMsgLen], eax ; Used as a pointer to the data
 
; now, we wait for
; UI redraw
; UI close
; or data from remote
 
ctr001:
mov eax,10 ; wait here for event
mcall
 
cmp eax,1 ; redraw request ?
je ctr003
cmp eax,2 ; key in buffer ?
je ctr004
cmp eax,3 ; button in buffer ?
je ctr005
 
 
; Any data in the UDP receive buffer?
mov eax, 53
mov ebx, 2
mov ecx, [socketNum]
mcall
 
cmp eax, 0
je ctr001
 
; we have data - this will be the response
ctr002:
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
mcall ; read byte - block (high byte)
 
; Store the data in the response buffer
mov eax, [dhcpMsgLen]
mov [eax], bl
inc dword [dhcpMsgLen]
 
mov eax, 53
mov ebx, 2
mov ecx, [socketNum]
mcall ; any more data?
 
cmp eax, 0
jne ctr002 ; yes, so get it
 
; depending on which msg we sent, handle the response
; accordingly.
; If the response is to a dhcp discover, then:
; 1) If response is DHCP OFFER then
; 1.1) record server IP, lease time & IP address.
; 1.2) send a request packet
; 2) else exit ( display error )
; If the response is to a dhcp request, then:
; 1) If the response is DHCP ACK then
; 1.1) extract the DNS & subnet fields. Set them in the stack
; 2) else exit ( display error )
 
 
cmp [dhcpMsgType], byte 0x01 ; did we send a discover?
je ctr007
cmp [dhcpMsgType], byte 0x03 ; did we send a request?
je ctr008
 
; should never get here - we only send discover or request
jmp ctr006
 
ctr007:
call parseResponse
 
; Was the response an offer? It should be
cmp [dhcpMsgType], byte 0x02
jne ctr006 ; NO - so quit
 
; send request
mov [dhcpMsgType], byte 0x03 ; DHCP request
call buildRequest
jmp ctr000
 
ctr008:
call parseResponse
 
; Was the response an ACK? It should be
cmp [dhcpMsgType], byte 0x05
jne ctr006 ; NO - so quit
 
; Set or display addresses here...
 
ctr006:
; close socket
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
mcall
 
mov [socketNum], dword 0xFFFF
 
call draw_window
 
jmp ctr001
 
ctr003: ; redraw
call draw_window
jmp ctr001
 
ctr004: ; key
mov eax,2 ; just read it and ignore
mcall
jmp ctr001
 
ctr005: ; button
mov eax,17 ; get id
mcall
 
; close socket
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
mcall
 
mov [socketNum], dword 0xFFFF
 
call draw_window ; at first, draw the window
 
ret
 
 
 
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
 
; Pass in the IP address in edi
; row to display in [ya]
drawIP:
; mov edi,hostIP
mov ecx, edi
add ecx, 4
mov edx,[ya]
add edx, 97*65536
mov esi,0x00ffffff
mov ebx,3*65536
 
ipdisplay:
mov eax,47
push ecx
movzx ecx,byte [edi]
mcall
pop ecx
add edx,6*4*65536
inc edi
cmp edi,ecx
jb ipdisplay
ret
 
 
drawDHMS:
 
mov eax,[edi]
bswap eax
 
mov esi,dhms
mov ecx,16
mov edi,text+40*4+12
cmp eax,0xffffffff
jne nforever
mov esi,forever
cld
rep movsb
ret
nforever:
cld
rep movsb
 
mov ecx,28
xor edx,edx
mov ebx,60
div ebx
call displayDHMS
xor edx,edx
div ebx
call displayDHMS
xor edx,edx
mov ebx,24
div ebx
call displayDHMS
mov edx,eax
call displayDHMS
 
ret
 
 
displayDHMS:
 
pusha
mov eax,47
mov ebx,3*65536
mov edx,ecx
imul edx,6
shl edx,16
add edx,1*65536+99
mov ecx,[esp+20]
mov esi,0xffffff
mcall
popa
sub ecx,4
ret
 
 
draw_window:
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,100*65536+300 ; [x start] *65536 + [x size]
mov ecx,100*65536+156 ; [y start] *65536 + [y size]
mov edx,0x14224466 ; color of work area RRGGBB
mov edi,title ; WINDOW LABEL
mcall
mov eax,8 ; Resolve
mov ebx,20*65536+90
mov ecx,127*65536+15
mov edx,3
mov esi,0x557799
mcall
 
; Pass in the IP address in edi
; row to display in [ya]
mov edi, dhcpClientIP
mov eax, 35
mov [ya], eax
call drawIP
mov edi, dhcpGateway
mov eax, 35 + 16
mov [ya], eax
call drawIP
mov edi, dhcpSubnet
mov eax, 35 + 32
mov [ya], eax
call drawIP
mov edi, dhcpDNSIP
mov eax, 35 + 48
mov [ya], eax
call drawIP
mov edi, dhcpLease
call drawDHMS
 
; Re-draw the screen text
cld
mov eax,4
mov ebx,25*65536+35 ; draw info text with function 4
mov ecx,0xffffff
mov edx,text
mov esi,40
newline:
mcall
add ebx,16
add edx,40
cmp [edx],byte 'x'
jnz newline
 
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
 
ret
 
 
 
; DATA AREA
 
ya dd 0x0
 
text:
db 'Client IP : . . . '
db 'Gateway IP: . . . '
db 'Subnet : . . . '
db 'DNS IP : . . . '
db 'Lease Time: d h m s '
db ' '
db ' SEND REQUEST '
db 'x <- END MARKER, DONT DELETE '
 
 
dhms db ' d h m s'
forever db 'Forever '
 
title db 'DHCP Client Test',0
 
dhcpMsgType: db 0
dhcpLease: dd 0
dhcpClientIP: dd 0
dhcpServerIP: dd 0
dhcpDNSIP: dd 0
dhcpSubnet: dd 0
dhcpGateway: dd 0
 
dhcpMsgLen: dd 0
socketNum: dd 0xFFFF
dhcpMsg:
I_END:
 
 
 
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/dhcp/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm dhcp.asm dhcp
@erase lang.inc
@pause
/programs/network_old/dhcp/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm dhcp.asm dhcp
@erase lang.inc
@pause
/programs/network_old/ethstat/trunk/ethstat.asm
0,0 → 1,218
;
; Stack Status Monitor
;
; Compile with FASM for Menuet
;
use32
org 0x0
db 'MENUET01' ; header
dd 0x01 ; header version
dd START ; entry point
dd I_END ; image size
dd I_END+0x10000 ; required memory
dd I_END+0x10000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Path
include 'lang.inc'
include '..\..\..\macros.inc'
START: ; start of execution
 
call draw_window ; at first, draw the window
still:
mov eax,23 ; wait here for event
mov ebx,200 ; Time out after 2s
mcall
cmp eax,1 ; redraw request ?
jz red
cmp eax,2 ; key in buffer ?
jz key
cmp eax,3 ; button in buffer ?
jz button
; read the stack status data, and write it to the screen buffer
mov eax, 53
mov ebx, 255
mov ecx, 6
mcall
mov ebx, text + 24
call printhex
mov eax, 53
mov ebx, 255
mov ecx, 2
mcall
mov ebx, text + 107
call printhex
mov eax, 53
mov ebx, 255
mov ecx, 5
mcall
mov ebx, text + 107 + 40
call printhex
mov eax, 53
mov ebx, 255
mov ecx, 4
mcall
mov ebx, text + 107 + 80
call printhex
mov eax, 53
mov ebx, 255
mov ecx, 100
mcall
mov ebx, text + 258
call printhex
mov eax, 53
mov ebx, 255
mov ecx, 101
mcall
mov ebx, text + 258 + 40
call printhex
mov eax, 53
mov ebx, 255
mov ecx, 102
mcall
mov ebx, text + 258 + 80
call printhex
mov eax, 53
mov ebx, 255
mov ecx, 103
mcall
mov ebx, text + 258 + 120
call printhex
red: ; redraw
call draw_window
jmp still
key: ; Keys are not valid at this part of the
mov eax,2 ; loop. Just read it and ignore
mcall
jmp still
button: ; button
mov eax,17 ; get id
mcall
cmp ah,1 ; button id=1 ?
jnz still
or eax,-1 ; close this program
mcall
jmp still
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
draw_window:
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
; DRAW WINDOW
xor eax,eax ; function 0 : define and draw window
mov ebx,100*65536+260 ; [x start] *65536 + [x size]
mov ecx,100*65536+205 ; [y start] *65536 + [y size]
mov edx,0x14224466 ; color of work area RRGGBB
mov edi,title ; WINDOW LABEL
mcall
; Re-draw the screen text
cld
mov eax,4
mov ebx,25*65536+35 ; draw info text with function 4
mov ecx,0xffffff
mov edx,text
mov esi,40
newline:
mcall
add ebx,16
add edx,40
cmp [edx],byte 'x'
jnz newline
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
ret
; Taken from PS.ASM
printhex:
; number in eax
; print to ebx
; xlat from hextable
pusha
mov esi, ebx
add esi, 8
mov ebx, hextable
mov ecx, 8
phex_loop:
mov edx, eax
and eax, 15
xlatb
mov [esi], al
mov eax, edx
shr eax, 4
dec esi
loop phex_loop
popa
ret
; DATA AREA
text:
db ' Ethernet card status : xxxxxxxx '
db ' '
db ' IP packets received : xxxxxxxx '
db ' ARP packets received : xxxxxxxx '
db ' Dumped received packets : xxxxxxxx '
db ' '
db ' EMPTY QUEUE : xxxxxxxx '
db ' IPOUT QUEUE : xxxxxxxx '
db ' IPIN QUEUE : xxxxxxxx '
db ' NET1OUT QUEUE : xxxxxxxx '
db 'x <- END MARKER, DONT DELETE '
title db 'Stack Status',0
hextable db '0123456789ABCDEF'
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/ethstat/trunk/build_en.bat
0,0 → 1,4
@erase lang.inc
@echo lang fix en >lang.inc
@fasm ethstat.asm ethstat
@pause
/programs/network_old/ethstat/trunk/build_ru.bat
0,0 → 1,4
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm ethstat.asm ethstat
@pause
/programs/network_old/ipc/trunk/ipc.asm
0,0 → 1,412
;
; Example for Inter Process Communication
;
; Compile with FASM for Menuet
;
include 'lang.inc'
include '..\..\..\macros.inc'
 
use32
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image
dd 0x60000 ; memory for app
dd 0x60000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Icon
 
START: ; start of execution
 
 
mov eax,60 ; IPC
mov ebx,1 ; define receive area
mov ecx,received_messages ; pointer to start
mov edx,1000 ; size of area
mcall
 
mov eax,40 ; WANTED EVENTS
mov ebx,01000111b ; IPC 7 + defaults
mcall
 
mov [received_messages+8],dword 0*256+0
mov [received_messages+12],dword 0
 
red:
call draw_window ; at first, draw the window
 
still:
 
mov eax,23 ; wait here for event
mov ebx,50
mcall
 
cmp eax,1 ; redraw request ?
je red
cmp eax,2 ; key in buffer ?
je key
cmp eax,3 ; button in buffer ?
je button
 
cmp eax,7 ; IPC ?
jne no_ipc
call display_ipc_messages
jmp still
no_ipc:
 
jmp still
 
key: ; key
mov eax,2 ; just read it and ignore
mcall
jmp still
 
button: ; button
mov eax,17 ; get id
mcall
 
cmp ah,1 ; button id=1 ?
jne noclose
mov eax,-1 ; close this program
mcall
noclose:
 
cmp ah,2
jne no_read
call read_string
 
movzx eax,byte [message]
sub eax,48
imul eax,10
movzx ebx,byte [message+1]
add eax,ebx
sub eax,48
imul eax,10
movzx ebx,byte [message+2]
add eax,ebx
sub eax,48
imul eax,10
movzx ebx,byte [message+3]
add eax,ebx
sub eax,48
 
mov [PID],eax
 
mov eax,60 ; IPC
mov ebx,2 ; send message
mov ecx,[PID]
mov edx,message+4
mov esi,20;[message_size]
mcall
 
jmp still
no_read:
 
 
cmp ah,3
jne no_messages_pop ; pop the first out
call ipc_message_pop
jmp still
no_messages_pop:
 
jmp still
 
 
ipc_message_pop:
 
pusha
 
cmp [received_messages+4],dword 8
je already_empty
 
mov [received_messages],byte 1 ; lock the area
 
push dword [received_messages+4]
 
mov ecx,[received_messages+12]
 
sub [received_messages+4],ecx
sub [received_messages+4],dword 8
 
mov edi,received_messages+8
mov esi,edi
add esi,ecx
add esi,8
 
pop ecx
 
cld
rep movsb
 
call display_ipc_messages
 
mov [received_messages],byte 0 ; free the area
 
already_empty:
 
popa
ret
 
 
 
display_ipc_messages:
 
pusha
 
mov eax,13
mov ebx,25*65536+245
mov ecx,105*65536+90
mov edx,0xdddddd
mcall
 
cmp [received_messages+4],dword 8 ; empty list
je ipma1
 
mov ebx,25*65536+105 ; draw info text with function 4
mov ecx,0x224466
mov edx,received_messages+8
mov esi,40
mov [counter],0
newline2:
pusha
mov ecx,[edx]
and ecx,0xfff
mov edx,ebx
mov eax,47
mov ebx,4*65536
mov esi,0xff0000
mcall
popa
pusha
mov esi,20
add edx,8
add ebx,30*65536
mov eax,4
mcall
popa
 
add ebx,10
mov edi,[edx+4]
add edi,8
and edi,0xfff
add edx,edi
 
mov edi,[received_messages+4]
add edi,received_messages
cmp edx,edi
jge ipma1
 
inc [counter]
cmp [counter],8
jbe newline2
 
ipma1:
 
popa
ret
 
 
counter dd 0x0
 
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
 
draw_window:
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
 
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,100*65536+290 ; [x start] *65536 + [x size]
mov ecx,100*65536+220 ; [y start] *65536 + [y size]
mov edx,0x14ffffff ; color of work area RRGGBB,8->color gl
mov edi,title ; WINDOW LABEL
mcall
 
mov eax,9
mov ebx,process_info
mov ecx,-1
mcall
 
mov eax,47
mov ebx,4*65536
mov ecx,[process_info+30]
mov edx,180*65536+35
mov esi,0x000000
mcall
 
mov eax,8 ; MESSAGE
mov ebx,25*65536+87
mov ecx,50*65536+16
mov edx,2
mov esi,0x5588dd
mcall
 
;mov eax,8 ; POP
mov ebx,216*65536+53
mov ecx,80*65536+16
mov edx,3
mcall
 
mov eax,4
mov ebx,25*65536+35 ; draw info text with function 4
mov ecx,0x224466
mov edx,text
mov esi,40
newline:
mcall
add ebx,10
add edx,40
cmp [edx],byte 'x'
jne newline
 
call display_ipc_messages
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
 
ret
 
 
 
 
read_string:
 
pusha
 
mov [addr],dword message
mov [ya],55
mov [xa],120
 
mov ecx,20
mov edi,[addr]
mov al,' '
cld
rep stosb
 
call print_text
 
mov edi,[addr]
 
f11:
mov eax,10
mcall
cmp eax,2
jz fbu
 
exit_readkey:
 
popa
ret
 
fbu:
mov eax,2
mcall ; get key
shr eax,8
 
cmp eax,13
je exit_readkey
 
cmp eax,8
jnz nobs
cmp edi,[addr]
jz f11
dec edi
mov [edi],byte ' '
call print_text
jmp f11
nobs:
 
cmp eax,31
jbe f11
cmp eax,95
jb keyok
sub eax,32
keyok:
mov [edi],al
 
call print_text
 
inc edi
mov esi,[addr]
add esi,20
cmp esi,edi
jnz f11
 
popa
ret
 
 
 
print_text:
 
mov eax,13
mov ebx,[xa]
shl ebx,16
add ebx,25*6
mov ecx,[ya]
shl ecx,16
mov cx,8
mov edx,0xffffff
mcall
 
mov eax,4
mov ebx,[xa]
shl ebx,16
add ebx,[ya]
mov ecx,0x000000
mov edx,[addr]
mov esi,25
mcall
 
ret
 
 
 
 
 
 
; DATA AREA
 
ya dd 0x0
xa dd 0x0
addr dd 0x0
 
text:
db 'PROCESS ID FOR THIS APP : '
db ' '
db ' PID:MESSAGE 0130 EXAMPLE MESSAGE '
db ' '
db ' '
db 'RECEIVED: POP '
db 'x' ; <- END MARKER, DONT DELETE
 
 
title db 'IPC - START AT LEAST 2',0
 
I_END:
 
PID: dd 0x0
message_size: dd 20
 
received_messages:
 
db 0 ; lock byte
db 0,0,0 ; reserved
dd 8 ; pointer to free msg position from received_messages
 
; Sender PID
; Msg length
; Msg data
 
rb 0x1000
message: times 70 db ?
process_info: times 256 dd ?
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/ipc/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm ipc.asm ipc
@erase lang.inc
@pause
/programs/network_old/ipc/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm ipc.asm ipc
@erase lang.inc
@pause
/programs/network_old/local/trunk/local.asm
0,0 → 1,507
;
; Remote processing example (local node)
;
; Compile with FASM for Menuet
;
use32
org 0x0
db 'MENUET01' ; header
dd 0x01 ; header version
dd START ; entry point
dd I_END ; image size
dd I_END+0x10000 ; required memory
dd I_END+0x10000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Path
 
include 'lang.inc'
include '..\..\..\macros.inc'
START: ; start of execution
mov eax,53 ; open socket
mov ebx,0
mov ecx,0x2000 ; local port
mov edx,0x3000 ; remote port
mov esi,dword [host_ip] ; node IP
mcall
mov [socketNum], eax
 
red:
call draw_window ; at first, draw the window
still:
mov eax,23 ; wait here for event
mov ebx,1
mcall
cmp eax,1 ; redraw request ?
jz red
cmp eax,2 ; key in buffer ?
jz key
cmp eax,3 ; button in buffer ?
jz button
mov eax, 53 ; get data
mov ebx, 2
mov ecx, [socketNum]
mcall
cmp eax, 0
jne read
jmp still
key:
mov eax,2
mcall
jmp still
button:
mov eax,17
mcall
cmp ah,1 ; button id=1 ?
jnz noclose
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
mcall
mov eax,-1
mcall
noclose:
cmp ah,2 ; SEND CODE ?
je send_xcode
cmp ah,3 ; LEFT COORDINATES ?
jne no_left
mov [picture_position],0
mov dword [send_data+15],dword STARTX
mov dword [send_data+19],dword 4
mov esi,send_data
mov edi,I_END
mov ecx,23
cld
rep movsb
mov [I_END+23],dword -20
mov eax,53
mov ebx,4
mov ecx,[socketNum]
mov edx,23 + 4
mov esi,I_END
mcall
jmp still
no_left:
cmp ah,4 ; RIGHT COORDINATES ?
jne no_right
mov [picture_position],128
mov dword [send_data+15],dword STARTX
mov dword [send_data+19],dword 4
mov esi,send_data
mov edi,I_END
mov ecx,23
cld
rep movsb
mov [I_END+23],dword -20 + 128
mov eax,53
mov ebx,4
mov ecx,[socketNum]
mov edx,23 + 4
mov esi,I_END
mcall
jmp still
no_right:
cmp ah,5 ; SEND EXECUTE ?
je send_execute
jmp still
xx dd 0
yy dd 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SEND CODE TO REMOTE ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
send_xcode:
mov dword [send_data+15],dword 0x80000
mov dword [send_data+19],dword remote_code_end - remote_code_start
mov esi,send_data ; header
mov edi,I_END
mov ecx,23
cld
rep movsb
mov esi,remote_code ; remote_code_start ; data
mov edi,I_END+23
mov ecx,remote_code_end - remote_code_start
cld
rep movsb
mov eax,53 ; SEND CODE TO REMOTE
mov ebx,4
mov ecx,[socketNum]
mov edx,23 + remote_code_end - remote_code_start
mov esi,I_END
mcall
jmp still
send_execute:
mov dword [execute+15],dword draw_fractal
mov eax,53 ; START EXECUTE AT REMOTE
mov ebx,4
mov ecx,[socketNum]
mov edx,19
mov esi,execute
mcall
mov edi,3
jmp still
;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; READ ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;
read:
cfr007:
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
mcall ; read byte
shl edx,8
mov dl,bl
dec edi
jnz cok
mov edi,3
and edx,0xffffff
mov eax,1
mov ebx,[xx]
mov ecx,[yy]
add ebx,15
add ecx,35
add ebx,[picture_position]
mcall
inc [xx]
cmp [xx],dword 128
jb cok
mov [xx],0
inc [yy]
cmp [yy],dword 128
jb cok
mov [yy],0
cok:
mov eax, 53
mov ebx, 2
mov ecx, [socketNum]
mcall ; any more data?
cmp eax, 0
jne cfr007 ; yes, so get it
jmp still
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
draw_window:
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,100*65536+286 ; [x start] *65536 + [x size]
mov ecx,60*65536+330 ; [y start] *65536 + [y size]
mov edx,0x04ffffff ; color of work area RRGGBB
mov edi,title ; WINDOW LABEL
mcall
mov eax,8 ; SEND CODE
mov ebx,60*65536+160
mov ecx,181*65536+13
mov edx,2
mov esi,0x667788
mcall
;mov eax,8 ; LEFT
mov ebx,60*65536+75
mov ecx,197*65536+13
mov edx,3
mcall
;mov eax,8 ; RIGHT
mov ebx,148*65536+72
mov ecx,197*65536+13
mov edx,4
mcall
;mov eax,8 ; SEND EXECUTE
mov ebx,60*65536+160
mov ecx,213*65536+13
mov edx,5
mcall
cld
mov eax,4
mov ebx,25*65536+185 ; draw info text with function 4
mov ecx,0x000000
mov edx,text
mov esi,40
newline:
mcall
add ebx,16
add edx,40
cmp [edx],byte 'x'
jnz newline
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
ret
; DATA AREA
text:
db ' 1) SEND CODE '
db ' 2) LEFT RIGHT '
db " 3) SEND 'EXECUTE' "
db ' '
db ' LOCAL : 192.168.1.26 '
db ' REMOTE : 192.168.1.22 '
db ' REMOTE CODE AT THE END OF THIS FILE '
db 'x' ;<- END MARKER, DONT DELETE
title db 'CLUSTER LOCAL',0
socketNum dd 0x0
host_ip db 192,168,1,22
picture_position dd 0x0
send_data db 'MenuetRemote00' ; 00 header ; -> remote port 0x3000
db 1 ; 14 send
dd 0x0 ; 15 position
dd 0x0 ; 19 size
; 23
execute db 'MenuetRemote00' ; 00 header ; -> remote port 0x3000
db 2 ; 14 execute
dd 0x0 ; 15 position
; 19
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; REMOTE CODE ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
remote_code:
org 0x80000
remote_code_start:
PIXWIDTH equ 129
PIXHEIGHT equ 129
ZOOMLIMIT equ 13
DELTA equ 200
THRESHOLD equ 7
STARTSCALE equ 6
CHAR_COLOR equ 0fh
STARTX dd -20
STARTY dd 10
scaleaddy dd 60
scaleaddx dd 100
draw_fractal:
pusha
movzx ebp,word [STARTX]
movzx edi,word [STARTY]
mov cx, PIXHEIGHT ; height of screen in pixels
sub di,cx ; adjust our Y offset
@@CalcRow:
push cx
mov cx, PIXWIDTH -1 ; width of screen in pixels
sub bp,cx ;
@@CalcPixel:
push cx ; save the column counter on stack
xor cx, cx ; clear out color loop counter
xor bx, bx ; zero i coefficient
xor dx, dx ; zero j coefficient
@@CycleColors:
push dx ; save j value for later
mov ax, bx ; ax = i
sub ax, dx ; ax = i - j
add dx, bx ; dx = i + j
stc ; one additional shift, please
call Shifty ; ax = ((i+j)*(i-j)) shifted right
pop dx ; retrieve our saved value for j
add ax,bp ; account for base offset...
cmp ah,THRESHOLD ; Q: is i &gt; THRESHOLD * 256?
xchg bx,ax ; now swap new i with old i
jg @@draw ; Y: draw this pixel
clc ; no additional shifts here, please
call Shifty ; now dx:ax = old i * j
xchg dx,ax ;
add dx,di ; account for base offset...
inc cl ; increment color
jnz @@CycleColors ; keep going until we're done
@@draw:
xchg ax, cx ; mov color into al
pop cx ; retrieve our column counter
pop dx ; fetch row (column already in cx)
push dx ; must leave a copy on the stack
xor bx,bx ; write to video page zero
call store_pixel
inc bp
loop @@CalcPixel
inc di
pop cx
loop @@CalcRow
call return_data
popa
ret
Shifty:
push cx
db 0b1h
scale db STARTSCALE
adc cl,0
imul dx
xchg ax,dx
shl eax,16
xchg ax,dx
shr eax,cl
pop cx
ret
pixel_pos: dd data_area
store_pixel:
pusha
mov ebx,[pixel_pos]
shl eax,3
and eax,0xff
mov [ebx],eax
add dword [pixel_pos],dword 3
popa
ret
return_data:
mov ecx,128 * 128/16
mov esi,data_area
sd:
pusha
mov eax,53 ; use the socket provided by host
mov ebx,4
mov ecx,[0]
mov edx,3*16
mcall
mov eax,5
mov ebx,1
mcall
popa
add esi,3*16
loop sd
ret
data_area:
remote_code_end:
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/local/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm local.asm local
@erase lang.inc
@pause
/programs/network_old/local/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm local.asm local
@erase lang.inc
@pause
/programs/network_old/mp3s/trunk/mp3s.asm
0,0 → 1,782
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Tiny MP3 Shoutcast Server v0.1 (vt) ;
; ;
; Compile with FASM for Menuet ;
; ;
; Listening to port 8008 ;
; Connect with eg: 192.168.1.22:8008 ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
version equ '0.3'
 
use32
org 0x0
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; program start
dd I_END ; program image size
dd 0x80000 ; memory usage
dd 0x20000 ; stack
dd 0,0
 
include 'lang.inc'
include '..\..\..\macros.inc'
 
; 0x0+ program image
; 0x1ffff stack
; 0x20000 work area for file read
; 0x40000+ file send buffer ( 100 kb )
 
 
START: ; start of execution
 
mov [status],0
call clear_input
call draw_window ; at first, draw the window
 
still:
 
mov eax,23 ; wait here for event
mov ebx,2
mcall
 
call check_events
 
call check_connection_status
 
cmp [status],4
je start_transmission
 
jmp still
 
 
check_events:
 
cmp eax,1 ; redraw request ?
jz red
cmp eax,2 ; key in buffer ?
jz key
cmp eax,3 ; button in buffer ?
jz button
 
ret
 
red: ; redraw
call draw_window
ret
 
key:
mov eax,2 ; Just read it and ignore
mcall
ret
 
button: ; button
 
mov eax,17 ; get id
mcall
 
cmp ah,1 ; close
jne no_close
mov eax,-1
mcall
no_close:
 
cmp ah,2 ; button id=2 ?
jnz tst3
; open socket
mov eax,53
mov ebx,5
mov ecx,8008 ; local port # - http
mov edx,0 ; no remote port specified
mov esi,0 ; no remote ip specified
mov edi,0 ; PASSIVE open
mcall
mov [socket], eax
mov [posy],1
mov [posx],0
mov [read_on],1
call check_for_incoming_data
call draw_window
ret
tst3:
 
cmp ah,4
je close_socket
cmp ah,6
je close_socket
jmp no_socket_close
close_socket:
mov edx,eax
; Close socket
mov eax, 53
mov ebx, 8
mov ecx, [socket]
mcall
mov esp,0x1fff0
cmp dh,6
je read_string
jmp still
no_socket_close:
 
cmp ah,9
jne no_bps_add
add [bps],8*1000
call draw_window
ret
no_bps_add:
 
cmp ah,8
jne no_bps_sub
sub [bps],8*1000
call draw_window
ret
no_bps_sub:
 
 
ret
 
 
clear_input:
 
mov edi,input_text
mov eax,0
mov ecx,60*40
cld
rep stosb
 
ret
 
 
read_string:
 
mov [addr],dword filename
mov [ya],dword 95
 
mov edi,[addr]
mov eax,32
mov ecx,30
cld
rep stosb
 
call print_text
 
mov edi,[addr]
 
f11:
mov eax,10
mcall
cmp eax,2
jne read_done
mov eax,2
mcall
shr eax,8
cmp eax,13
je read_done
cmp eax,8
jnz nobsl
cmp edi,[addr]
jz f11
sub edi,1
mov [edi],byte 32
call print_text
jmp f11
nobsl:
cmp eax,dword 31
jbe f11
cmp eax,dword 95
jb keyok
sub eax,32
keyok:
mov [edi],al
 
call print_text
 
add edi,1
mov esi,[addr]
add esi,30
cmp esi,edi
jnz f11
 
read_done:
 
mov ecx,40
mov eax,0
cld
rep movsb
 
call print_text
 
jmp still
 
 
print_text:
 
pusha
 
mov eax,13
mov ebx,56*65536+30*6
mov ecx,[ya]
shl ecx,16
mov cx,8
mov edx,0xffffff
mcall
 
mov eax,4
mov edx,[addr]
mov ebx,56*65536
add ebx,[ya]
mov ecx,0x000000
mov esi,30
mcall
 
popa
ret
 
 
wait_for dd 0x0
 
transmission_start dd 0x0
sentbytes dd 0x0
 
start_transmission:
 
call clear_input
 
mov eax,5
mov ebx,50
mcall
 
call check_for_incoming_data
call draw_window
 
call send_header
 
mov [fileinfo+4],dword 0 ; start from beginning
mov [read_to],0x40000
mov [playpos],0x40000
 
mov ecx,1024 / 512
 
new_buffer:
 
mov eax,[read_to]
mov ebx,1
call read_file
 
loop new_buffer
 
 
newpart:
 
call check_connection_status
call draw_window
 
mov eax,26
mov ebx,9
mcall
mov [transmission_start],eax
mov [sentbytes],0
 
newblock:
 
mov eax,[read_to]
mov ebx,2
call read_file
 
wait_more:
 
mov eax,26
mov ebx,9
mcall
 
cmp eax,[wait_for]
jge nomw
 
mov eax,5
mov ebx,1
mcall
 
jmp wait_more
 
nomw:
 
add eax,2
mov [wait_for],eax
 
mov eax,11
mcall
call check_events
 
mov eax,53
mov ebx,255
mov ecx,103
mcall
 
cmp eax,0
jne wait_more
 
; write to socket
mov eax,53
mov ebx,7
mov ecx,[socket]
mov edx,[playadd]
mov esi,[playpos]
mcall
 
add [sentbytes],edx
 
mov esi,[playpos]
add esi,[playadd]
mov edi,0x40000
mov ecx,110000 / 4
cld
rep movsd
 
mov eax,[playadd]
sub [read_to],eax
 
call check_for_incoming_data
call show_progress
call check_rate
 
mov eax, 53
mov ebx, 6
mov ecx, [socket]
mcall
cmp eax,4
jne end_stream
 
cmp [read_to],0x40000
jge newblock
 
end_stream:
 
; Close socket
 
mov eax, 53
mov ebx, 8
mov ecx, [socket]
mcall
 
mov eax,5
mov ebx,5
mcall
 
; Open socket
 
mov eax,53
mov ebx,5
mov ecx,8008 ; local port # - http
mov edx,0 ; no remote port specified
mov esi,0 ; no remote ip specified
mov edi,0 ; PASSIVE open
mcall
mov [socket], eax
mov [posy],1
mov [posx],0
mov [read_on],0
 
call draw_window
 
jmp still
 
 
check_rate:
 
pusha
 
mov eax,[bps]
xor edx,edx
mov ebx,8*100
div ebx
shl eax,1
mov [playadd],eax
 
mov eax,26
mov ebx,9
mcall
 
sub eax,[transmission_start]
shr eax,1
 
imul eax,[playadd]
 
mov edx,0x00dd00
 
cmp [sentbytes],eax
jge sendok
 
sub eax,20000
cmp [sentbytes],eax ; a long buffer underrun correction
jge no_buffer_overrun ; actually leads to overrun
mov [sentbytes],eax
no_buffer_overrun:
 
add [playadd],150
mov edx,0xdd0000
 
sendok:
 
mov eax,13
mov ebx,320*65536+10
mov ecx,105*65536+10
mcall
 
mov eax,47
mov ebx,4*65536
mov ecx,[playadd]
mov edx,322*65536+106
mov esi,0x000000
; mcall
 
popa
 
ret
 
 
show_progress:
 
pusha
 
mov eax,13
mov ebx,236*65536+10*6
mov ecx,107*65536+8
mov edx,0xffffff
mcall
 
mov ecx,[fileinfo+4]
imul ecx,512
 
mov eax,47 ; file read
mov ebx,9*65536
mov edx,236*65536+107
mov esi,0x000000
mcall
 
popa
ret
 
 
playpos dd 0x100000
playadd dd 256000 / 8 / 100
 
 
send_header:
 
pusha
 
mov [playpos],0x40000
 
mov esi,fileinfo+5*4
mov edi,transname
mov ecx,30
cld
rep movsb
 
mov eax, 53
mov ebx, 7
mov ecx, [socket]
mov edx, headere-headers
mov esi, headers
mcall
 
popa
ret
 
 
read_file:
 
cmp [read_to],0x40000+2000
jg cache_ok
mov [read_on],1
cache_ok:
 
cmp [read_to],0x40000+95500
jg no_read_1
 
mov [fileinfo+12],eax
mov [fileinfo+8],ebx
 
mov eax,58
mov ebx,fileinfo
mcall
 
cmp eax,0
jne no_read_1
 
mov eax,[fileinfo+8]
add [fileinfo+4],eax
 
add [read_to],512*2
 
ret
 
no_read_1:
 
mov [read_on],0
 
ret
 
 
 
check_for_incoming_data:
 
pusha
 
mov eax, 53
mov ebx, 2
mov ecx, [socket]
mcall
 
cmp eax,0
je _ret_now
 
new_data:
 
mov eax, 53
mov ebx, 2
mov ecx, [socket]
mcall
 
cmp eax,0
je _ret
 
mov eax,53
mov ebx,3
mov ecx,[socket]
mcall
 
cmp bl,10
jne no_lf
inc [posy]
mov [posx],0
jmp new_data
no_lf:
 
cmp bl,20
jb new_data
 
inc [posx]
cmp [posx],60
jbe xok
inc [posy]
mov [posx],0
xok:
 
cmp [posy],12
jbe yok
mov [posy],1
yok:
 
mov eax,[posy]
imul eax,60
add eax,[posx]
 
mov [input_text+eax],bl
 
jmp new_data
 
_ret:
 
; call draw_window
 
_ret_now:
 
popa
ret
 
 
 
check_connection_status:
 
pusha
 
mov eax, 53
mov ebx, 6
mov ecx, [socket]
mcall
 
cmp eax,[status]
je .ccs_ret
mov [status],eax
add eax,48
mov [text+20],al
call draw_window
.ccs_ret:
 
popa
ret
 
 
 
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
 
draw_window:
 
pusha
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
 
mov eax,0 ; Draw Window
mov ebx,50*65536+410
mov ecx,100*65536+141
mov edx,0x14ffffff
mov edi,title
mcall
 
mov eax,8 ; Start server
mov ebx,(25)*65536+21
mov ecx,57*65536+10
mov edx,2
mov esi,0x409040
mcall ; Stop server
; mov eax,8
mov ebx,(25)*65536+21
mov ecx,69*65536+10
mov edx,4
mov esi,0x904040
mcall
 
mov esi,0x3366d0
 
; mov eax,8 ; Enter filename
mov ebx,(25)*65536+21
mov ecx,93*65536+10
mov edx,6
mcall
; mov eax,8 ; Decrease transfer rate
mov ebx,(25)*65536+10
mov ecx,105*65536+10
; mov edx,8
mcall
; mov eax,8 ; Increase transfer rate
mov ebx,(36)*65536+10
mov ecx,105*65536+10
mov edx,9
mcall
 
mov ebx,10*65536+35 ; draw info text
mov ecx,0x00000000
mov edx,text
mov esi,40
newline:
mov eax,4
mcall
add ebx,12
add edx,40
cmp [edx],byte 'x'
jnz newline
 
mov eax,4 ; Filename
mov ebx,56*65536+95
mov ecx,0x000000
mov edx,filename
mov esi,30
mcall
 
mov eax,[bps]
xor edx,edx
mov ebx,1000
div ebx
mov ecx,eax
 
mov eax,47
mov ebx,3*65536
mov edx,58*65536+107
mov esi,0x00000000
mcall
 
mov [input_text+0],dword 'RECE'
mov [input_text+4],dword 'IVED'
mov [input_text+8],dword ': '
 
mov ebx,230*65536+35 ; draw info text
mov ecx,0x00000000
mov edx,input_text
mov esi,28
mov edi,7
newline2:
mov eax,4
mcall
add ebx,10
add edx,60
dec edi
jnz newline2
 
mov eax,38
mov ebx,210*65536+210
mov ecx,22*65536+136
mov edx,0x6699cc ; 002288
mcall
 
mov eax,38
mov ebx,211*65536+211
mov ecx,22*65536+136
mov edx,0x336699 ; 002288
mcall
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
 
popa
 
ret
 
 
 
; DATA AREA
 
text:
db ' TCB status: 0 '
db ' '
db ' Activate - port 8008 '
db ' Stop server '
db ' '
db ' > '
db ' < > Kbps '
db 'x'; <- END MARKER, DONT DELETE
 
headers:
 
db 'ICY 200 OK',13,10
db 'icy-notice1:This stream requires Winamp or xmms',13,10
db 'icy-url:http://www.menuetos.org',13,10
db 'icy-pub: 1',13,10
db 'icy-name: Menuet Mp3 Shoutcast Radio ',version,' - '
transname:
db ' ',13,10,13,10
 
headere:
 
title db 'MP3 shoutcast server ',version,0
 
socket dd 0
status dd 0
 
posy dd 1
posx dd 0
 
read_on db 1
read_to dd 0
 
addr dd 0
ya dd 0
 
bps dd 128*1000
 
fileinfo: dd 0,0,0,0,0x20000
filename: db '/sys/MENUET.MP3',0
times 50 db 0
 
input_text:
 
I_END:
/programs/network_old/mp3s/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm mp3s.asm mp3s
@erase lang.inc
@pause
/programs/network_old/mp3s/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm mp3s.asm mp3s
@erase lang.inc
@pause
/programs/network_old/ppp/trunk/ppp.asm
0,0 → 1,2238
;
; PPP.ASM
;
; Compile with FASM for Menuet
; This program dials into an ISP and establishes a PPP connection
;
; Version 11 26th January 2004
;
; This code is a port of the PPP dialer program by Microchip, from
; their application note AN724
; It has been ported by Mike Hibbett mikeh@oceanfree.net for Menuet
;
; 26/1/04 - Mike Hibbett - added support for com port selected by
; stackcfg
; 2/5/03 - Shrirang - Added Abort Strings To sendwait to get out early
; if modem sends abort strings like NO CARRIER etc.
;
; The original copyright statement follows
;//////////////////////////////////////////////////////////////////////////
;//
;//PING.C version 1.10 July 29/99 (C)opyright by Microchip Technology Inc
;//
;//////////////////////////////////////////////////////////////////////////
 
FALSE equ 0
TRUE equ 1
DEBUG_OUTPUT equ TRUE ; If FALSE, not debugging info outputted
DEBUG_PPP_OUTPUT equ TRUE ; write PPP status msgs to debug board?
DEBUG_PORT2_OUTPUT equ TRUE ; write debug data also to com2
 
 
BAUD_9600 equ 12
BAUD_57600 equ 2
; The next line sets the baud rate of the connection to the modem
BAUDRATE equ BAUD_57600
 
 
LINE_END equ 0x0D ; End of input data character
 
 
; Defines for Internet constants
REQ equ 1 ; Request options list for PPP negotiations
PPP_ACK equ 2 ; Acknowledge options list for PPP negotiations
PPP_NAK equ 3 ; Not acknowledged options list for PPP neg
REJ equ 4 ; Reject options list for PPP negotiations
TERM equ 5 ; Termination packet for LCP to close connectio
LCP_ECHO_REQ equ 9
LCP_ECHO_REP equ 10
IP equ 0x0021 ; Internet Protocol packet
IPCP equ 0x8021 ; Internet Protocol Configure Protocol packet
CCP equ 0x80FD ; Compression Configure Protocol packet
LCP equ 0xC021 ; Link Configure Protocol packet
PAP equ 0xC023 ; Password Authenication Protocol packet
 
 
MaxRx equ 1500
MaxTx equ 1500
 
 
 
 
use32
org 0x0
db 'MENUET01' ; header
dd 0x01 ; header version
dd STARTAPP ; entry point
dd I_END ; image size
dd I_END+0x10000 ; required memory
dd I_END+0x10000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Path
 
 
include "lang.inc"
include "..\..\..\macros.inc"
include "chat.inc" ; Hosts modem chatting routine
 
 
STARTAPP:
; mov eax, 0x3f8
; mov [comport], eax
; mov eax, 4
; mov [comirq], eax
 
; Get the com port & IRQ to use from the kernel stack config option
 
mov eax, 52 ; Stack Interface
mov ebx, 0 ; read configuration word
mcall
mov ecx, eax
shr ecx, 16 ; get the port address
mov [comport], ecx
shr eax, 8
and eax, 0x000000FF ; get the irq
mov [comirq], eax
 
 
mov eax, [comport]
add eax, 0x01000000
mov [irqtable], eax
 
 
call enable_port
 
appdsp:
mov eax, welcomep
mov [prompt], eax ; set up prompt to display
mov al, [welcomep_len]
mov [prompt_len], al
 
red:
call draw_window ; at first, draw the window
 
apploop:
mov eax, 23 ; wait here for event
mov ebx, 20
mcall
 
cmp eax, 1 ; redraw request ?
je red
cmp eax, 2 ; key in buffer ?
je key
cmp eax, 3 ; button in buffer ?
je button
mov ebx, [comirq]
add ebx, 16
cmp eax, ebx
je flush_input ; Dont want serial data yet
jmp apploop
 
key: ; key - ignore
mov eax, 2 ; just read it
mcall
jmp apploop
 
button: ; button
mov eax, 17 ; get id
mcall
 
cmp ah, 1 ; close program ?
jne noclose
 
mov esi, hangupWait
mov edi, hangupSend
mov edx, 1000 ; Allow sendwait 10s
call sendwait
 
call disable_port
 
or eax, -1 ; close this program
mcall
jmp apploop
 
noclose:
cmp ah, 2 ; Dial Button pressed?
jne apploop
 
mov eax, conp
mov [prompt], eax ; set up prompt to display
mov al,[conp_len]
mov [prompt_len], al
call draw_window
 
jmp dialloop ; connect to the host
 
 
; Data received, so get it, and throw it away at this point
flush_input:
mov eax,42
mov ebx, [comirq]
mcall
 
mov eax,11 ; This will return 0 most of the time
mcall
mov ebx, [comirq]
add ebx, 16
cmp eax, ebx
je flush_input
jmp apploop
 
 
dialloop:
call modem_chat ; Try chatting with the modem
 
cmp eax, 1 ; Did it work? ( = 1)
jne appdsp
 
; OK, we are now connected.
 
mov eax, pppOnp
mov [prompt], eax ; set up prompt to display
mov al,[pppOnp_len]
mov [prompt_len], al
call draw_window
 
mov eax, 23
mov ebx, 100
mcall ; wait for 1s to display message
 
call PPPStateMachine ; This is the main code
 
jmp appdsp
 
 
 
 
;****************************************************************************
; Function
; PPPStateMachine
;
; Description
; Handles PPP link establishment
;
;****************************************************************************
PPPStateMachine:
; Start the timer
xor eax, eax
call settimer
 
PPPLoop:
 
mov eax, 11 ; check event
mcall
cmp eax, 3
jne PPPLred
; button pressed
mov eax, 17 ; get id
mcall
 
 
mov eax, hangp
mov [prompt], eax ; set up prompt to display
mov al,[hangp_len]
mov [prompt_len], al
call draw_window
 
mov esi, hangupWait
mov edi, hangupSend
mov edx, 1000 ; Allow sendwait 10s
call sendwait
 
call disable_port
mov eax, -1 ; close this program
mcall
jmp PPPLoop
 
PPPLred:
cmp eax, 1 ; redraw request ?
jne PPPLoop0
 
call draw_window
jmp PPPLoop
 
PPPLoop0:
mov ebx, [comirq]
add ebx, 16
cmp eax, ebx
jne ppp_002 ; check for tx to send
 
 
; we have data in the rx buffer, get it
 
mov eax, 42
mov ebx, [comirq] ; ecx will return 0 =data read, 1 =no data
mcall ; or 2 =not irq owner
 
inc dword [rxbytes]
 
cmp bl, 0x7E
jne ppp_001a
 
mov eax, [rx_ptr]
cmp eax, 0
jz ppp_001
mov eax, [checksum1]
cmp eax, 0xf0b8
jne ppp_001
 
 
movzx eax, byte [rx_str + 3]
mov ah, [rx_str + 2]
mov [packet], eax
 
ppp_001:
mov eax, [extended]
and eax, 0x7e
mov [extended], eax
xor eax, eax
mov [rx_ptr], eax
 
mov eax, 0xffff
mov [checksum1], eax
jmp ppp_003
 
ppp_001a:
cmp bl, 0x7D
jne ppp_001b
 
mov eax, [extended]
or eax, 0x01
mov [extended], eax
jmp ppp_003
 
ppp_001b:
mov eax, [extended]
test eax, 0x01
jz ppp_001c
 
xor bl, 0x20
and eax, 0xFE
mov [extended], eax
 
ppp_001c:
mov edx, [rx_ptr]
cmp edx, 0
jnz ppp_001d
cmp bl, 0xff
je ppp_001d
 
mov [rx_str + edx], byte 0xff
inc edx
 
ppp_001d:
cmp edx, 1
jnz ppp_001e
cmp bl, 0x03
je ppp_001e
 
mov [rx_str + edx], byte 0x03
inc edx
 
ppp_001e:
cmp edx, 2
jnz ppp_001f
test bl, 0x01
jz ppp_001f
 
mov [rx_str + edx], byte 0
inc edx
 
ppp_001f:
mov [rx_str + edx], bl
inc edx
mov [rx_ptr], edx
 
cmp edx, MaxRx
jle ppp_001g
mov edx, MaxRx
mov [rx_ptr], edx
 
ppp_001g:
; do checksum calc
mov eax, [checksum1]
xor bh, bh
xor ax, bx
call calc
mov ebx, [checksum1]
and ebx, 0xffff
shr ebx, 8
xor eax, ebx
mov [checksum1], eax
jmp ppp_003
 
ppp_002:
mov eax, [tx_end]
cmp eax, 0
jz ppp_003
 
mov ebx, [tx_ptr]
mov cl, [tx_str + ebx]
 
cmp ebx, eax
jne ppp_002a
mov [tx_end], dword 0
mov cl, '~'
jmp ppp_002d
 
ppp_002a:
mov eax, [extended]
and eax, 0x02
jz ppp_002b
 
xor cl, 0x20
mov eax, [extended]
and eax, 0xFD
mov [extended], eax
inc [tx_ptr]
jmp ppp_002d
 
ppp_002b:
cmp cl, 0x20
jl ppp_002b1
cmp cl, 0x7d
je ppp_002b1
cmp cl, 0x7e
je ppp_002b1
jmp ppp_002c
 
ppp_002b1:
mov eax, [extended]
or eax, 0x02
mov [extended], eax
mov cl, 0x7d
jmp ppp_002d
 
ppp_002c:
mov eax, [tx_ptr]
cmp eax, 0
jnz ppp_002c1
mov cl, '~'
 
ppp_002c1:
inc [tx_ptr]
 
ppp_002d:
; Test for tx ready.
 
push ecx
 
wait_txd2:
mov eax,43
mov ecx, [comport]
add ecx, 0x80000000 + 5
mcall
and bl, 0x40
cmp bl, 0
jz wait_txd2 ; loop until free
 
pop ebx
 
 
; send the character
 
inc dword [txbytes]
 
mov ecx, [comport]
mov eax, 43
mcall
 
ppp_003:
mov eax, [packet]
cmp eax, LCP
jne ppp_004
 
mov al, [rx_str + 4]
cmp al, REQ
jne ppp_003b
 
; Debugging output to debug board
pusha
mov esi, RX_LCP_REQ
call debug_output
popa
 
mov eax, [state]
and eax, 0xfd
mov [state], eax
 
mov ebx, 0xc6
push eax
call TestOptions
pop eax
cmp edx, 0
jz ppp_003g
 
cmp edx, 1
jle ppp_003h
 
mov edx, PPP_ACK
cmp eax, 3
jge ppp_003i
 
or eax, 0x02
mov [state], eax
jmp ppp_003i
 
ppp_003h:
mov bl, 0xc0
mov [rx_str + 10], bl
mov edx, PPP_NAK
jmp ppp_003i
 
ppp_003g:
mov edx, REJ
 
ppp_003i:
 
mov ebx, LCP
mov ecx, edx
movzx edx, byte [rx_str + 5]
mov esi, rx_str + 7
call MakePacket
 
mov eax, 0
call settimer
jmp ppp_003a
 
ppp_003b:
cmp al, PPP_ACK
jne ppp_003c
 
; Debugging output to debug board
pusha
mov esi, RX_LCP_ACK
call debug_output
popa
 
mov eax, [number]
cmp al, [rx_str+5]
jne ppp_003a
 
mov eax, [state]
cmp eax, 3
jge ppp_003a
or eax, 0x01
mov [state], eax
jmp ppp_003a
 
ppp_003c:
cmp al, PPP_NAK
jne ppp_003d
 
; Debugging output to debug board
pusha
mov esi, RX_LCP_NAK
call debug_output
popa
 
mov eax, [state]
and eax, 0xfe
mov [state], eax
jmp ppp_003a
 
ppp_003d:
cmp al, REJ
jne ppp_003e
 
; Debugging output to debug board
pusha
mov esi, RX_LCP_REJ
call debug_output
popa
 
mov eax, [state]
and eax, 0xfe
mov [state], eax
jmp ppp_003a
 
ppp_003e:
cmp al, TERM
jne ppp_003j
jmp ppp_003a
 
ppp_003j:
cmp al, LCP_ECHO_REQ
jne ppp_003a
 
; Debugging output to debug board
pusha
mov esi, RX_LCP_ECHO_REQ
call debug_output
popa
 
mov al, 0
mov [rx_str+8],al
mov [rx_str+9],al
mov [rx_str+10],al
mov [rx_str+11],al
 
mov ebx, LCP
mov ecx, LCP_ECHO_REP
movzx edx, byte [rx_str + 5]
mov esi, rx_str + 7
call MakePacket
 
ppp_003a:
mov eax, [state]
cmp eax, 3
jne ppp_013
 
mov eax, 4
mov [state], eax
 
jmp ppp_013
 
 
ppp_004:
cmp eax, PAP
jne ppp_005
 
mov al, [rx_str + 4]
cmp al, PPP_ACK
jne ppp_013
 
; Debugging output to debug board
pusha
mov esi, RX_PAP_ACK
call debug_output
popa
 
mov eax, 5
mov [state],eax
jmp ppp_013
 
ppp_005:
cmp eax, IPCP
jne ppp_006
 
mov al, [rx_str + 4]
cmp al, REQ
jne ppp_005a
 
; Debugging output to debug board
pusha
mov esi, RX_IPCP_REQ
call debug_output
popa
 
mov ebx, 0x04
call TestOptions
cmp edx, 0
jz ppp_005b
mov ecx, PPP_ACK
mov eax, 6
mov [state], eax
jmp ppp_005c
ppp_005b:
mov ecx, REJ
 
ppp_005c:
mov ebx, IPCP
movzx edx, byte [rx_str + 5]
mov esi, rx_str + 7
call MakePacket
jmp ppp_013
 
ppp_005a:
cmp al, PPP_ACK
jne ppp_005d
 
; Debugging output to debug board
pusha
mov esi, RX_IPCP_ACK
call debug_output
popa
 
mov al, [rx_str + 5]
mov ecx, [number]
cmp al, cl
jne ppp_013
 
mov eax, 7
mov [state], eax
mov eax, 5800
call settimer
 
mov eax, IPOnp
mov [prompt], eax ; set up prompt to display
mov al,[IPOnp_len]
mov [prompt_len], al
call draw_window
 
jmp ppp_013
 
ppp_005d:
cmp al, PPP_NAK
jne ppp_005e
 
; Debugging output to debug board
pusha
mov esi, RX_IPCP_NAK
call debug_output
popa
 
mov al, [rx_str + 10]
mov [addr1], al
mov al, [rx_str + 11]
mov [addr2], al
mov al, [rx_str + 12]
mov [addr3], al
mov al, [rx_str + 13]
mov [addr4], al
 
pusha
call draw_window
 
mov eax,52
mov ebx,3
mov cl, [addr4]
shl ecx, 8
mov cl, [addr3]
shl ecx, 8
mov cl, [addr2]
shl ecx, 8
mov cl, [addr1]
mcall ; Set the stacks IP address
 
popa
 
mov ebx, IPCP ;; added 28/4/03
mov ecx, REQ
movzx edx, byte [rx_str + 5]
mov esi, rx_str + 7
call MakePacket
jmp ppp_013
 
ppp_005e:
cmp al, REJ
jne ppp_005f
jmp ppp_013
 
ppp_005f:
cmp al, TERM
jne ppp_013
jmp ppp_013
 
ppp_006:
cmp eax, IP
jne ppp_007
 
 
;;
;;
;;
;; This is where we will pass the IP packet up to the stack
;;
;;
;;
mov eax, 52
mov ebx, 6
mov edx, 1500 ; this should be exact amount
mov esi, rx_str + 4
mcall
 
; Debugging output to debug board
pusha
mov esi, RX_IP
call debug_output
popa
 
jmp ppp_013
 
ppp_007:
cmp eax, CCP
jne ppp_008
 
mov al, [rx_str + 4]
cmp al, REQ
jne ppp_013
 
; Debugging output to debug board
pusha
mov esi, RX_CCP_REQ
call debug_output
popa
 
mov ebx, 0x04
call TestOptions
cmp edx, 0
jz ppp_007b
mov ecx, PPP_ACK
jmp ppp_007c
ppp_007b:
mov ecx, REJ
 
ppp_007c:
mov ebx, CCP
movzx edx, byte [rx_str + 5]
mov esi, rx_str + 7
call MakePacket
 
jmp ppp_013
 
ppp_008:
cmp eax, 0
jz ppp_009
 
jmp ppp_013
 
ppp_009:
mov eax, [tx_end]
cmp eax, 0
jnz ppp_010
call gettimer
cmp eax, 100
jle ppp_010
 
mov eax, [state]
cmp eax, 0
je ppp_009a
cmp eax, 2
jne ppp_010
 
ppp_009a:
 
; Debugging output to debug board
pusha
mov esi, TX_LCP_REQ
call debug_output
popa
 
inc [number]
mov eax, 0
call settimer
 
mov ebx, LCP
mov ecx, REQ
mov edx, [number]
mov esi, LCPREQStr
call MakePacket
 
jmp ppp_013
 
ppp_010:
mov eax, [tx_end]
cmp eax, 0
jnz ppp_011
call gettimer
cmp eax, 100
jle ppp_011
mov eax, [state]
cmp eax, 4
jne ppp_011
mov eax, 0
call settimer
inc [number]
 
; Debugging output to debug board
pusha
mov esi, TX_PAP_REQ
call debug_output
popa
 
mov ebx, PAP
mov ecx, REQ
mov edx, [number]
mov esi, PAPREQStr
call MakePacket
 
jmp ppp_013
 
ppp_011:
mov eax, [tx_end]
cmp eax, 0
jnz ppp_012
call gettimer
cmp eax, 100
jle ppp_012
mov eax, [state]
cmp eax, 6
jne ppp_012
inc [number]
mov eax, 0
call settimer
 
; Debugging output to debug board
pusha
mov esi, TX_IPCP_REQ
call debug_output
popa
 
mov ebx, IPCP
mov ecx, REQ
mov edx, [number]
mov esi, IPCPREQStr
call MakePacket
 
jmp ppp_013
 
ppp_012:
mov eax, [tx_end]
cmp eax, 0
jnz ppp_013
mov eax, [state]
cmp eax, 7
jne ppp_013
 
; 10ms Delay suggested by Ville
mov eax,23 ; over here
mov ebx,1
mcall
 
 
 
call gettimer
cmp eax, 200
jle ppp_012a
 
; every 2s, when things are quiet, redraw window
call draw_window_limited
 
mov eax, 0
call settimer
 
ppp_012a:
 
mov eax, 52
mov ebx, 8
mov esi, ip_buff
mcall
 
cmp eax, 0
je ppp_013
 
call MakeIPPacket
 
; Debugging output to debug board
pusha
mov esi, TX_IP
call debug_output
popa
 
ppp_013:
mov eax, [packet]
cmp eax, 0
jz PPPLoop
 
mov eax, 0
mov [packet], eax
 
mov edi, rx_str
mov ecx, MaxRx + 1
rep stosb
jmp PPPLoop
 
 
 
;****************************************************************************
; Function
; calc
;
; Description
; Adds a character to the CRC checksum
; byte in lsb of eax
;
;
;****************************************************************************
calc:
and eax, 0xFF
push ecx
mov ecx, 8
calc_001:
test al, 0x01
jz calc_002
shr eax, 1
xor eax, 0x8408
and eax, 0xffff
jmp calc_003
calc_002:
shr eax, 1
calc_003:
loop calc_001
pop ecx
ret
 
 
;****************************************************************************
; Function
; add2tx
;
; Description
; Adds a character into the tx buffer
; byte in low byte of eax
;
;
;****************************************************************************
add2tx:
pusha
mov esi, tx_str
add esi, [tx_ptr]
inc [tx_ptr]
mov [esi], al ; Save byte in buffer
mov ecx, [checksum2]
and eax, 0xff
xor eax, ecx
call calc
shr ecx, 8
and ecx, 0xff
xor eax, ecx
mov [checksum2], eax
popa
ret
 
 
 
;****************************************************************************
; Function
; MakeIPPacket
;
; Description
; Creates a PPP packet for transmission to the host from the
; IP packet extracted from the stack
;
; IP data is in ip_buff
;
;****************************************************************************
MakeIPPacket:
mov [tx_ptr], dword 1
mov edi, tx_str
mov [edi], byte ' '
mov eax, 0xffff
mov [checksum2], eax
mov al, 0xff
call add2tx
mov al, 3
call add2tx
mov al, IP / 256
call add2tx
mov al, IP
call add2tx
 
movzx ecx, byte [ip_buff + 3]
mov ch, byte [ip_buff + 2]
 
mov esi, ip_buff
 
mip001:
mov al, byte [esi]
call add2tx
inc esi
loop mip001
 
mov eax, [checksum2]
not eax
call add2tx
shr eax, 8
call add2tx
 
mov eax, [tx_ptr]
mov [tx_end], eax
xor eax, eax
mov [tx_ptr], eax
ret
 
 
;****************************************************************************
; Function
; MakePacket
;
; Description
; Creates a PPP packet for transmission to the host
;
; Packet type in ebx
; Code is in ecx
; num is in edx
; str is pointed to by esi
;
;****************************************************************************
MakePacket:
mov [tx_ptr], dword 1
mov edi, tx_str
mov [edi], byte ' '
mov eax, 0xffff
mov [checksum2], eax
mov al, 0xff
call add2tx
mov al, 3
call add2tx
mov al, bh ; packet/256
call add2tx
mov al, bl ; packet&255
call add2tx
 
cmp ebx, IP ; is packet type IP?
jne mp_001 ; No - its a lower layer packet
 
; Do IP packet assembly
 
jmp mp_002
 
mp_001:
; Do PPP layer packet assembly
mov al, cl
call add2tx
mov al, dl
call add2tx
mov al, 0
call add2tx
 
movzx ecx, byte [esi] ; length = *str - 3
sub ecx, 3
 
mp_002: ; Now copy the data acros
mov al, byte [esi]
call add2tx
inc esi
loop mp_002
 
mov eax, [checksum2]
not eax
call add2tx
shr eax, 8
call add2tx
 
mov eax, [tx_ptr]
mov [tx_end], eax
xor eax, eax
mov [tx_ptr], eax
ret
 
 
;****************************************************************************
; Function
; TestOptions
;
; Description
; Test a PPP packets options fields for valid entries
;
; option ebx
;
; Returns result in edx, but may also modify rx_str
;
;****************************************************************************
TestOptions:
mov esi, 8 ; ptr1
mov edi, 8 ; ptr2
mov edx, 3 ; edx is the return value
movzx ecx, byte [rx_str + 7]
add ecx, 4 ; ecx is size
cmp ecx, MaxRx
jle to_001
mov ecx, MaxRx
to_001:
cmp esi, ecx
jge to_002
mov al, byte [esi + rx_str]
cmp al, 3
jne to_001a
mov al, byte [esi + rx_str + 2]
cmp al, 0x80
je to_001a
; bug fix for chap authenticate reject below
mov al, byte [esi + rx_str + 2]
cmp al, 0xc2
jne to_001a
and edx, 0xfd
to_001a:
push ecx
mov cl, [esi + rx_str]
dec cl
mov eax, 1
shl eax, cl
and eax, ebx
and eax, 0xffff
pop ecx
cmp eax, 0
jnz to_001b
xor edx,edx
to_001b:
movzx eax, byte [esi+rx_str+1]
add esi, eax
jmp to_001
to_002:
; if (!(pass&2))...
test edx, 2
jnz to_exit
test edx, 1
jz to_002a
mov ebx, 0xFFFB
to_002a:
mov esi, 8
to_002b: ; for loop
cmp esi, ecx
jge to_003
 
push ecx
mov cl, [esi + rx_str]
dec cl
mov eax, 1
shl eax, cl
and eax, ebx
and eax, 0xffff
pop ecx
cmp eax, 0
jnz to_002c
movzx edx, byte [esi+rx_str+1]
to_002d:
cmp esi, ecx
jge to_002b
cmp edx, 0
jz to_002b
mov al, [esi + rx_str]
mov [edi + rx_str], al
inc esi
inc edi
dec edx
jmp to_002d
to_002c:
movzx eax, byte [esi+rx_str+1]
add esi, eax
jmp to_002b ; end of for loop
to_003:
mov eax, edi
sub al, 4
mov [rx_str+7], al
xor edx, edx
cmp ebx, 0xfffb
jne to_exit
inc edx
to_exit:
; Return value in EDX
ret
 
 
 
;***************************************************************************
; Function
; disable_port
;
; Description;
; Releases this applications use of the com port
;
;***************************************************************************
disable_port:
if DEBUG_PORT2_OUTPUT = TRUE
mov eax, 46 ; free port area
mov ebx, 1
 
mov ecx, 0x2f8
and ecx, 0xFF0
mov edx, ecx
or edx, 0x00F
mcall
end if
 
mov eax, 45 ; free irq 4
mov ebx, 1
mov ecx, [comirq]
mcall
 
mov eax, 46 ; free port area
mov ebx, 1
 
mov ecx, [comport]
and ecx, 0xFF0
mov edx, ecx
or edx, 0x00F
mcall
ret
 
 
 
;***************************************************************************
; Function
; enable_port
;
; Description;
; Takes control of the com port, defining the IRQ table and initialising
; the uart chip.
;
;***************************************************************************
enable_port:
pusha
if DEBUG_PORT2_OUTPUT = TRUE
mov eax, 46
mov ebx, 0
mov ecx, 0x2f8
and ecx, 0xFF0
mov edx, ecx
or edx, 0x00F
mcall ; reseve port memory to this process
 
mov eax, 45 ; reserve irq 3
mov ebx, 0
mov ecx, 3
mcall
 
 
mov ecx, 0x2f8 ; data format register
add ecx, 3
mov bl, 0x80 ; enable access to divisor latch
mov eax, 43 ; send data to device - com port setup
mcall
 
mov ecx, 0x2f8 ; interrupt enable register
inc ecx
mov bl, 0 ; No interruts enabled
mov eax, 43 ; send data to device (modem)
mcall
 
mov ecx, 0x2f8 ; Divisor latch LSB
mov bl, BAUDRATE ; set baud rate
mov eax, 43 ; send data to device (modem)
mcall
 
mov ecx, 0x2f8 ; Data format register
add ecx, 3
mov bl, 3 ; 8 data bits
mov eax, 43 ; send data to device (modem)
mcall
 
mov ecx, 0x2f8 ; Modem control register
add ecx, 4 ; ** bl must be 0x0b for modem to dial!
mov bl, 0x0b ; 0x08 -> out2 enabled. No handshaking.
; 0xb -> out2 enabled, RTS/DTR enabled
mov eax, 43 ; send data to device (modem)
mcall
 
; mov ecx, 0x2f8 ; interrupt enable register
; inc ecx
; mov bl, 1 ; rx data interrupt enabled, othrs not
; mov eax, 43 ; send data to device (modem)
; mcall
 
end if
 
mov eax, 46
mov ebx, 0
mov ecx, [comport]
and ecx, 0xFF0
mov edx, ecx
or edx, 0x00F
mcall ; reseve port memory to this process
 
mov eax, 45 ; reserve irq 4
mov ebx, 0
mov ecx, [comirq]
mcall
 
mov eax, 44 ; setup irq table
mov ebx, irqtable
mov ecx, [comirq]
mcall
 
mov ecx, [comport] ; data format register
add ecx, 3
mov bl, 0x80 ; enable access to divisor latch
mov eax, 43 ; send data to device - com port setup
mcall
 
mov ecx, [comport] ; interrupt enable register
inc ecx
mov bl, 0 ; No interruts enabled
mov eax, 43 ; send data to device (modem)
mcall
 
mov ecx, [comport] ; Divisor latch LSB
mov bl, BAUDRATE ; set baud rate
mov eax, 43 ; send data to device (modem)
mcall
 
mov ecx, [comport] ; Data format register
add ecx, 3
mov bl, 3 ; 8 data bits
mov eax, 43 ; send data to device (modem)
mcall
 
mov ecx, [comport] ; Modem control register
add ecx, 4 ; ** bl must be 0x0b for modem to dial!
mov bl, 0x0b ; 0x08 -> out2 enabled. No handshaking.
; 0xb -> out2 enabled, RTS/DTR enabled
mov eax, 43 ; send data to device (modem)
mcall
 
mov ecx, [comport] ; interrupt enable register
inc ecx
mov bl, 1 ; rx data interrupt enabled, othrs not
mov eax, 43 ; send data to device (modem)
mcall
 
mov ecx, [comirq]
add ecx, 16
mov ebx, 1
shl ebx, cl
add ebx, 111b
mov eax,40 ; enable irq 4 data
mcall
 
popa
ret
 
 
 
;**************************************************************************
; Function
; draw_window
;
; Description;
; Normal window definition and text layout for application
;**************************************************************************
draw_window:
mov eax, 12 ; function 12:tell os about windowdraw
mov ebx, 1 ; 1, start of draw
mcall
; DRAW WINDOW
mov eax, 0 ; function 0 : define and draw window
mov ebx, 100*65536+250 ; [x start] *65536 + [x size]
mov ecx, 100*65536+150 ; [y start] *65536 + [y size]
mov edx,0x14224466 ; color of work area RRGGBB
mov edi,title ; color of frames RRGGBB
mcall
 
; DIAL BUTTON
mov eax, 8 ; function 8 : define and draw button
mov ebx, (50)*65536+40 ; [x start] *65536 + [x size]
mov ecx, 130*65536+12 ; [y start] *65536 + [y size]
mov edx, 2 ; button id
mov esi, 0x5599cc ; button color RRGGBB
mcall
 
mov ebx, 55*65536+133 ; Draw button text
mov ecx, 0x00FFFFFF
mov edx, button1_text
xor eax, eax
mov al, [button1_text_len]
mov esi, eax
mov eax, 4
mcall
; DISCONNECT BUTTON
mov eax, 8 ; function 8 : define and draw button
mov ebx, (150)*65536+65 ; [x start] *65536 + [x size]
mov ecx, 130*65536+12 ; [y start] *65536 + [y size]
mov edx, 3 ; button id
mov esi, 0x5599cc ; button color RRGGBB
mcall
 
mov ebx, 155*65536+133 ; Draw button text
mov ecx, 0x00FFFFFF
mov edx, button3_text
xor eax, eax
mov al, [button3_text_len]
mov esi, eax
mov eax, 4
mcall
 
mov ebx, 5*65536+40 ; draw info text with function 4
mov ecx, 0x00FFFFFF
mov edx, [prompt]
xor eax, eax
mov al, [prompt_len]
mov esi, eax
mov eax, 4
mcall
 
; Draw IP address
mov edx, 10*65536+60
mov esi, 0x00FFFFFF
mov ebx, 0x00030000
movzx ecx, byte [addr1]
mov eax, 47
mcall
mov edx, 31*65536+60
mov esi, 0x00FFFFFF
mov ebx, 0x00030000
movzx ecx, byte [addr2]
mov eax, 47
mcall
mov edx, 52*65536+60
mov esi, 0x00FFFFFF
mov ebx, 0x00030000
movzx ecx, byte [addr3]
mov eax, 47
mcall
mov edx, 73*65536+60
mov esi, 0x00FFFFFF
mov ebx, 0x00030000
movzx ecx, byte [addr4]
mov eax, 47
mcall
 
; Status byte
mov edx, 100*65536+60
mov esi, 0x00FFFFFF
mov ebx, 0x00010000
movzx ecx, byte [state]
mov eax, 47
mcall
 
; bytes sent / received
mov eax, 4 ; function 4 : write text to window
mov ebx, 10*65536+80 ; [x start] *65536 + [y start]
mov ecx, 0x00ffffff ; color of text RRGGBB
mov edx, txmsg ; pointer to text beginning
mov esi, txmsglen-txmsg ; text length
mcall
 
mov eax, 4 ; function 4 : write text to window
mov ebx, 10*65536+100 ; [x start] *65536 + [y start]
mov ecx, 0x00ffffff ; color of text RRGGBB
mov edx, rxmsg ; pointer to text beginning
mov esi, rxmsglen-rxmsg ; text length
mcall
 
call draw_window_limited
 
mov eax, 12 ; end of redraw
mov ebx, 2
mcall
 
ret
 
 
 
draw_window_limited:
mov eax,13
mov ebx,80*65536+10*6
mov ecx,80*65536+10
mov edx,0x03224466
mcall
mov ecx,100*65536+10
mcall
 
mov ebx, 0x000A0000
mov ecx, [txbytes]
mov esi, 0x00ffffff ; color of text RRGGBB
mov eax, 47 ; function 47 : write number to window
mov edx, 80*65536+80 ; [x start] *65536 + [y start]
mcall
 
mov ebx, 0x000A0000
mov ecx, [rxbytes]
mov esi, 0x00ffffff ; color of text RRGGBB
mov eax, 47 ; function 47 : write number to window
mov edx, 80*65536+100 ; [x start] *65536 + [y start]
mcall
ret
 
 
;****************************************************************************
; Function
; settimer
;
; Description
; sets the general purpose timer to a given value in eax
; All times are in 1/100s
;
;
;****************************************************************************
settimer:
push eax
mov eax, 26
mov ebx, 9
mcall ; get 100th second counter
pop ebx
sub eax, ebx ; This could have some funny side effecs if PPP
; called within ebx seconds of startup
mov [timerValue], eax
ret
 
 
;****************************************************************************
; Function
; gettimer
;
; Description
; gets the general purpose timer count in eax
; All times are in 1/100s
;
;
;****************************************************************************
gettimer:
mov eax, 26
mov ebx, 9
mcall ; get 100th second counter
 
sub eax, [timerValue]
ret
 
 
 
 
;****************************************************************************
; Function
; sendwait
;
; Description
; Sends a command string to the modem, then waits for a defined rsp
;
; esi points to string to wait for
; edi points to string to send
; edx holds wait time, in ms
;
; Returns 1 if OK or 0 if timeout occurred
;
;****************************************************************************
sendwait:
mov [sendwaitTime], edx
 
; Shrirang 2/5/03
mov byte [abortcnt], 0 ; reset the abort counter
;--!
 
; Start the timer
xor eax, eax
call settimer
 
; Check for incoming data
 
xor edx, edx
xor eax, eax
 
sw_001:
push eax
push edx
 
; Has connection timer expired?
call gettimer
cmp eax, [sendwaitTime]
jl sw_000
 
pop edx
pop eax
 
xor eax, eax
 
jmp sw_exit ; Exit indicating an error ( timeout )
 
sw_000:
; any data from modem?
 
mov eax,11 ; This will return 0 most of the time
mcall
mov ecx, eax
pop edx
pop eax
 
 
cmp ecx, 1 ; redraw request ?
je red1
cmp ecx, 3 ; button in buffer ?
je button1
mov ebx, [comirq]
add ebx, 16
cmp ecx,ebx
jne sw_002
jmp sw_000a
 
red1:
pusha
call draw_window
popa
push eax
push edx
 
jmp sw_000
 
button1:
mov eax, 0
jmp sw_exit
 
sw_000a:
; there was data, so get it
 
push edx
push eax
mov eax,42
mov ebx, [comirq]
mcall
pop eax
pop edx
 
 
; Shrirang 2/5/03
; Now that the expected response is not got we check if we
; got the abort part, before we reset the fsm
 
cmp bl, 0x0d ; AT commands normally start and end with \r\n
je checkabort
 
cmp bl, 0x0a
je checkabort
 
push eax
xor eax, eax
mov al, [abortcnt]
mov byte [abortres+eax], bl ; update abort response
inc byte [abortcnt]
pop eax
 
jmp noabort
 
 
checkabort :
 
cmp byte [abortcnt], 2 ; if we got valid abort this cannot happen!
jbe noabortflush
 
push eax
push esi
push edi
push ecx
 
mov esi, abortres
mov edi, aborts
xor ecx, ecx
mov cl, byte [abortcnt]
call scanaborts ; scan 'em
 
pop ecx
pop edi
pop esi
 
and eax, eax
jz noabortdec
 
pop eax
xor eax, eax
jmp sw_exit
 
noabortdec:
 
pop eax
 
noabortflush:
 
mov byte [abortcnt], 0
 
noabort:
 
;--!
 
cmp [esi+edx], bl
je sw_003
 
 
xor edx, edx
 
; Added 28/4/03
cmp [esi+edx], bl
je sw_003
 
jmp sw_001
 
sw_003: ; They are the same
inc edx
cmp [esi+edx], byte 0
jne sw_001
 
 
xor eax, eax
inc eax
jmp sw_exit
 
sw_002:
; Test for data to send to modem
cmp [ edi + eax ], byte 0
je sw_001
 
; Is it a '|' character?
cmp [ edi + eax ], byte '|'
jne sw_004
 
push eax
call gettimer
cmp eax, 100
pop eax
jl sw_001
 
; restart the timer
push eax
xor eax, eax
call settimer
pop eax
 
; Move to next character
inc eax
jmp sw_001
 
 
sw_004:
push edx
push eax
 
; restart the timer
xor eax, eax
call settimer
 
; Test for tx ready.
; OR, wait then send
push edi
mov eax, 5
mov ebx, 1
mcall ; 10ms delay
pop edi
 
; send the character
pop eax
mov bl, [edi + eax]
 
mov ecx, [comport]
inc eax
push eax
mov eax, 43
mcall
 
pop eax
pop edx
 
cmp [ edi + eax ], byte 0
jne sw_001
 
cmp [ esi + edx ], byte 0
jne sw_001
 
xor eax, eax
inc eax
 
sw_exit:
; return success (1) or failure (0) in eax
ret
 
 
 
 
if DEBUG_OUTPUT = TRUE
 
;****************************************************************************
; Function
; debug_output
;
; Description
; prints a description of the PPP protocol's data exchanges to the
; debug board
;
; esi holds ptr to msg to display
;
; Nothing preserved; I'm assuming a pusha/popa is done before calling
;
;****************************************************************************
debug_output:
cmp esi, RX_IP
jne do_001
 
call debug_print_string
 
call debug_print_rx_ip
 
mov esi, IP_DATA1
call debug_print_string
mov esi, CRLF
call debug_print_string
mov esi, IP_DATA2
call debug_print_string
ret
 
do_001:
cmp esi, TX_IP
jne do_002
 
call debug_print_string
 
call debug_print_tx_ip
 
mov esi, IP_DATA1
call debug_print_string
mov esi, CRLF
call debug_print_string
mov esi, IP_DATA2
call debug_print_string
ret
 
do_002:
; Print PPP protocol information
if DEBUG_PPP_OUTPUT = TRUE
call debug_print_string
mov esi, CRLF
call debug_print_string
end if
ret
 
 
 
txCom2:
push ecx
 
wait_txd2t:
mov eax,43
mov ecx,0x80000000 + 0x2f8 + 5
mcall
and bl, 0x40
cmp bl, 0
jz wait_txd2t ; loop until free
 
pop ebx
 
 
; send the character
 
mov ecx, 0x2f8
mov eax, 43
mcall
ret
 
 
;****************************************************************************
; Function
; debug_print_string
;
; Description
; prints a string to the debug board
;
; esi holds ptr to msg to display
;
; Nothing preserved; I'm assuming a pusha/popa is done before calling
;
;****************************************************************************
debug_print_string:
mov cl, [esi]
cmp cl, 0
jnz dps_001
ret
 
dps_001:
if DEBUG_PORT2_OUTPUT = TRUE
pusha
call txCom2
popa
end if
mov eax,63
mov ebx, 1
push esi
mcall
pop esi
inc esi
jmp debug_print_string
 
 
; This is used for translating hex to ASCII for display or output
hexchars db '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
 
IP_DATA1 db 'TCP From: xxxxxxxx To: xxxxxxxx SrcP: xxxx DestP: xxxx',0
IP_DATA2 db 'Seq: xxxxxxxx Ack: xxxxxxxx Flags: xx dataLen: xxxx',13,10,0
 
 
 
debug_print_rx_ip:
mov esi, rx_str + 4 ; The ip buffer address start
 
mov edi, IP_DATA1
 
cmp [esi+9], byte 1
jne rnICMP
mov eax,'ICMP'
jmp drp
rnICMP:
cmp [esi+9], byte 6
jne rnTCP
mov eax,'TCP '
jmp drp
rnTCP:
cmp [esi+9], byte 17
jne rnUDP
mov eax,'UDP '
jmp drp
rnUDP:
 
drp:
mov [edi], eax
 
call fillData
 
ret
 
 
debug_print_tx_ip:
mov esi, ip_buff ; The ip buffer address start
 
mov edi, IP_DATA1
 
cmp [esi+9], byte 1
jne tnICMP
mov eax,'ICMP'
jmp dtp
tnICMP:
cmp [esi+9], byte 6
jne tnTCP
mov eax,'TCP '
jmp dtp
tnTCP:
cmp [esi+9], byte 17
jne tnUDP
mov eax,'UDP '
jmp dtp
tnUDP:
 
dtp:
mov [edi], eax
 
call fillData
 
ret
 
 
fillData:
; Display from IP
mov cl, [esi+12]
mov edx, 11
call wbyte ; byte in cl, dest in edi+edx
mov cl, [esi+13]
mov edx, 13
call wbyte ; byte in cl, dest in edi+edx
mov cl, [esi+14]
mov edx, 15
call wbyte ; byte in cl, dest in edi+edx
mov cl, [esi+15]
mov edx, 17
call wbyte ; byte in cl, dest in edi+edx
 
; Display to IP
mov cl, [esi+16]
mov edx, 24
call wbyte ; byte in cl, dest in edi+edx
mov cl, [esi+17]
mov edx, 26
call wbyte ; byte in cl, dest in edi+edx
mov cl, [esi+18]
mov edx, 28
call wbyte ; byte in cl, dest in edi+edx
mov cl, [esi+19]
mov edx, 30
call wbyte ; byte in cl, dest in edi+edx
 
; Only display extra data for TCP
cmp [esi+9], byte 6 ; TCP?
je nTCP
 
; display source port
mov [edi+32], byte 0
mov edi, IP_DATA2
mov [edi], byte 0
ret
 
nTCP:
mov [edi+32], byte ' '
 
mov cl, [esi+20]
mov edx, 39
call wbyte ; byte in cl, dest in edi+edx
mov cl, [esi+21]
mov edx, 41
call wbyte ; byte in cl, dest in edi+edx
 
mov cl, [esi+22]
mov edx, 51
call wbyte ; byte in cl, dest in edi+edx
mov cl, [esi+23]
mov edx, 53
call wbyte ; byte in cl, dest in edi+edx
 
 
mov edi, IP_DATA2
mov [edi], byte 'S'
 
mov cl, [esi+24]
mov edx, 5
call wbyte ; byte in cl, dest in edi+edx
mov cl, [esi+25]
mov edx, 7
call wbyte ; byte in cl, dest in edi+edx
mov cl, [esi+26]
mov edx, 9
call wbyte ; byte in cl, dest in edi+edx
mov cl, [esi+27]
mov edx, 11
call wbyte ; byte in cl, dest in edi+edx
 
mov cl, [esi+28]
mov edx, 19
call wbyte ; byte in cl, dest in edi+edx
mov cl, [esi+29]
mov edx, 21
call wbyte ; byte in cl, dest in edi+edx
mov cl, [esi+30]
mov edx, 23
call wbyte ; byte in cl, dest in edi+edx
mov cl, [esi+31]
mov edx, 25
call wbyte ; byte in cl, dest in edi+edx
 
mov cl, [esi+33]
and cl, 0x3F
mov edx, 35
call wbyte ; byte in cl, dest in edi+edx
 
; Display the size of the received packet
mov dh, [esi + 2]
mov dl, [esi + 3]
sub dx, 40
mov cl, dh
mov edx, 48
call wbyte ; byte in cl, dest in edi+edx
mov dh, [esi + 2]
mov dl, [esi + 3]
sub dx, 40
mov cl, dl
mov edx, 50
call wbyte ; byte in cl, dest in edi+edx
 
 
ret
 
 
wbyte: ; byte in cl, dest in edi+edx, edi unchanged
xor eax, eax
mov al, cl
shr al, 4
mov bl, [eax + hexchars]
mov [edi+edx], bl
inc edx
mov al, cl
and al, 0x0f
mov bl, [eax + hexchars]
mov [edi+edx], bl
ret
 
else
debug_output:
ret
end if
 
; DATA AREA
 
 
; debug msgs
RX_IP db 'R: ',0
TX_IP db 'T: ',0
CRLF db 13,10,0
RX_LCP_REQ db 'RX_LCP_REQ',0
RX_LCP_ACK db 'RX_LCP_ACK',0
RX_LCP_NAK db 'RX_LCP_NAK',0
RX_LCP_REJ db 'RX_LCP_REJ',0
RX_LCP_ECHO_REQ db 'RX_LCP_ECHO_REQ',0
RX_PAP_ACK db 'RX_PAP_ACK',0
RX_IPCP_REQ db 'RX_IPCP_REQ',0
RX_IPCP_ACK db 'RX_IPCP_ACK',0
RX_IPCP_NAK db 'RX_IPCP_NAK ( IP Address assigned )',0
RX_CCP_REQ db 'RX_CCP_REQ',0
TX_LCP_REQ db 'TX_LCP_REQ',0
TX_PAP_REQ db 'TX_PAP_REQ',0
TX_IPCP_REQ db 'TX_IPCP_REQ',0
 
 
; Labels for GUI buttons
button1_text db 'DIAL'
button1_text_len db 4
button3_text db 'DISCONNECT'
button3_text_len db 10
 
comport dd 0
comirq dd 0
 
; Pointer to prompt shown to user
prompt dd 0
prompt_len db 0
 
; Application Title
title db 'PPP Dialer',0
 
txmsg: db 'Tx bytes :'
txmsglen:
rxmsg: db 'Rx bytes :'
rxmsglen:
 
timerValue dd 0
sendwaitTime dd 0
 
 
; Prompts displayed to the user
welcomep db 'Select an option below, see ppp.txt'
welcomep_len db 35
 
dialfp db 'Connect Failed...'
dialfp_len db 17
 
connectedp db 'Connected to Host'
connectedp_len db 17
 
conp db 'Connecting to Host'
conp_len db 18
 
pppOnp db 'PPP Started'
pppOnp_len db 11
 
IPOnp db 'IP Link established'
IPOnp_len db 19
 
discp db 'Disconnected from Host'
discp_len db 22
 
hangp db 'Hanging up Modem......'
hangp_len db 22
 
PPPconSend db 0x7e,0xff,0x7d,0x23,0x08,0x08,0x08,0x08,0
PPPconWait db '~~',0
hangupWait db 'ATZ',0
hangupSend db '|||+++|||',10,13,'ATH',10,13,'|ATZ',10,13,0
 
; Shrirang 2/5/03
 
abortres: times(50) db 0
abortcnt db 0
 
;--!
 
LCPREQStr db 0x0e,0x02,0x06,0x00, 0x0a, 0x00, 0x00, 0x07, 0x02, 0x08, 0x02
PAPREQStr db 14, 4, 'free', 4, 'free'
IPCPREQStr db 10, 3, 6, 0, 0, 0, 0
 
irqtable: dd 0x3f8 + 0x01000000 ; read port 0x3f8, byte
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
checksum1 dd 0
checksum2 dd 0
packet dd 0
state dd 0
extended dd 0
number dd 0
tx_end dd 0
tx_ptr dd 0
rx_ptr dd 0
addr1 db 0
addr2 db 0
addr3 db 0
addr4 db 0
rxbytes dd 0
txbytes dd 0
 
 
; End of application code and data marker
 
I_END:
 
rx_str: rb MaxRx + 1
tx_str: rb MaxTx + 1
ip_buff: rb 1500
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/ppp/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm ppp.asm ppp
@erase lang.inc
@pause
/programs/network_old/ppp/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm ppp.asm ppp
@erase lang.inc
@pause
/programs/network_old/ppp/trunk/chat.inc
0,0 → 1,188
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; CHAT.INC ;;
;; ;;
;; Modem Chat Initiator for PPP Dialer ;;
;; ;;
;; Version 3 2nd May 2003 ;;
;; ;;
;; Copyright 2002 Shrirang Bhagwat, b_shrirang@hotmail.com ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;; 2/5/03 - Shrirang - Added Abort Strings For sendwait ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Request And Response Chat Strings
; Following Data Structure is used for Request Response Chatting
; with the modem, for each request there is an expected response
; chatreq <-> chatres, 0 (NULL) is delimeter for 1 string
; '`' is delimiter for the section, modify according to your
; modem dialing scheme; in future MenuetOS might provide a graphical
; client to generate this kind of data structure and the PAP packet
; for username and password!
; Aborts strings are used to get outta sendwait early...
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; REQUESTS
chatreq db 'ATH',13,0 ; 0 (NULL) is required by sendwait
db 'ATZ',13,0
db 'ATM1',13,0
db 'ATX1',13,0 ; My Modem doesn't connect without this
; db 'ATDT;',13,0
db 'ATDT phonenumber',13,0
db '`' ; <- End Marker
 
; RESPONSES
chatres db 'OK',0
db 'OK',0
db 'OK',0
db 'OK',0
; db 'OK',0
db 'CONNECT',0
db '`' ; <- End Marker
 
; ABORTS
aborts db 'ERROR',0
db 'NO CARRIER',0
db 'NO DIALTONE',0
db 'BUSY',0
db 'LINE IN USE',0
db 'NO ANSWER',0
db '`' ; <- End Marker
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; modem_chat - chats with the modem to initiate a connection
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
modem_chat:
 
push edi
push esi
push edx
 
mov edi, chatreq ; init everytime, safe, stateless
mov esi, chatres
 
chat_now:
 
cmp byte [esi], '`' ; are we done?
je chatover
 
mov edx, 6000 ; strings like "atdt;" take long on my modem
call sendwait
 
and eax, eax
jz timeoutoccured
 
updatereq:
 
inc edi
cmp byte [edi], '`'
je updateres
 
cmp byte [edi], 0
jne updatereq
 
inc edi
 
updateres:
 
inc esi
cmp byte [esi], '`'
je chatover
 
cmp byte [esi], 0
jne updateres
 
inc esi
 
jmp chat_now
 
 
chatover:
 
xor eax, eax ; SUCCESS!
inc eax
 
pop edx
pop esi
pop edi
 
ret
 
timeoutoccured:
 
xor eax, eax ; FAIL!
 
pop edx
pop esi
pop edi
 
ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; scanaborts - scans the response from modem for abort srings
; ESI - Response from modem
; EDI - Pointer to Abort Table
; ECX - Response Length
; Returns 1 if abort detected, 0 otherwise
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
scanaborts:
 
push esi
push edi
push ecx
 
checkit:
 
push esi
repe cmpsb ; any abort matches?
je abortdetected
pop esi
 
 
updatetbl:
 
inc edi
cmp byte [edi], '`'
je noabortfound
 
cmp byte [edi], 0
jne updatetbl
 
inc edi
 
jmp checkit
 
abortdetected:
 
pop esi
pop ecx
pop edi
pop esi
 
xor eax, eax ; SUCCESS!
inc eax
ret
 
noabortfound :
 
pop ecx
pop edi
pop esi
 
 
xor eax, eax ; FAILED!
ret
 
 
 
 
 
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/rccc/trunk/rccc.asm
0,0 → 1,308
;
; Remote Control Center(Client)
;
; €¢â®à: Hex
; ‘ ©â: www.mestack.narod.ru
;
; Ž¯¨á ­¨¥:
; à®£à ¬¬ , ¯à¥¤­ §­ ç¥­­ ï ¤«ï ã¯à ¢«¥­¨ï 㤠«ñ­­ë¬ ª®¬¯ìîâ¥à®¬.Š«¨¥­â᪠ï
; ç áâì.
;
; Compile with FASM for Menuet
; Š®¬¯¨«¨àã¥âáï FASM'®¬ ¤«ï Œ¥­ãí⠎‘
;
 
 
use32
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image
dd 0x5000 ; memory for app
dd 0x5000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Icon
 
include 'lang.inc'
include '..\..\..\macros.inc'
 
START: ; start of execution
 
mov eax,53 ; open socket
mov ebx,0
mov ecx,0x6000 ; local port
mov edx,0x6100 ; remote port
mov esi,dword [remote_ip] ; remote IP
mcall
 
mov [socket], eax
 
mov eax,53 ; send connect code
mov ebx,4
mov ecx,[socket]
mov edx,1
mov esi,connect
mcall
 
red:
call draw_window ; at first, draw the window
 
still:
 
mov eax,23 ; wait here for event
mov ebx,1
mcall
 
cmp eax,1 ; redraw request ?
jz red
cmp eax,2 ; key in buffer ?
jz key
cmp eax,3 ; button in buffer ?
jz button
 
jmp still
key:
mov eax,2
mcall
jmp still
 
button:
mov eax,17
mcall
 
cmp ah,1 ; button id=1 ?
jnz noclose
mov eax, 53
mov ebx, 1
mov ecx, [socket]
mcall
or eax,-1
mcall
noclose:
 
cmp ah,2 ; SEND SHUTDOWN COMMAND?
je send_shutdown
 
cmp ah,3 ; SEND REBOOT COMMAND?
je send_reboot
 
cmp ah,4 ; SEND SAVEFI COMMAND?
je send_savefi
 
cmp ah,5 ; SEND SAVEHI COMMAND?
je send_savehi
 
cmp ah,6 ; SEND HOTREBOOT COMMAND?
je send_hotreboot
 
cmp ah,7 ; SEND EXIT COMMAND?
je send_exit
 
jmp still
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SEND COMMANDS TO SERVER ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
send_shutdown:
 
mov eax,53 ; SEND CODE TO REMOTE
mov ebx,4
mov ecx,[socket]
mov edx,1
mov esi,sen_shutdown
mcall
 
jmp still
 
send_reboot:
 
mov eax,53 ; SEND CODE TO REMOTE
mov ebx,4
mov ecx,[socket]
mov edx,1
mov esi,sen_reboot
mcall
 
jmp still
 
send_savefi:
 
mov eax,53 ; SEND CODE TO REMOTE
mov ebx,4
mov ecx,[socket]
mov edx,1
mov esi,sen_savefi
mcall
 
jmp still
 
send_savehi:
 
mov eax,53 ; SEND CODE TO REMOTE
mov ebx,4
mov ecx,[socket]
mov edx,1
mov esi,sen_savehi
mcall
 
jmp still
 
send_hotreboot:
 
mov eax,53 ; SEND CODE TO REMOTE
mov ebx,4
mov ecx,[socket]
mov edx,1
mov esi,sen_hotreboot
mcall
 
jmp still
 
send_exit:
 
mov eax,53 ; SEND CODE TO REMOTE
mov ebx,4
mov ecx,[socket]
mov edx,1
mov esi,sen_exit
mcall
 
jmp still
 
get_data:
 
mov eax,53
mov ebx,3
mov ecx,[socket]
mcall
 
mov [edi],bl
inc edi
 
mov eax,53
mov ebx,2
mov ecx,[socket]
mcall
 
cmp eax,0
jne get_data
 
mov eax,4
mov ebx,30*65536+30
mov ecx,0x000000
mov edx,I_END
mov esi,15
mcall
 
jmp still
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
 
draw_window:
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
 
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,100*65536+250 ; [x start] *65536 + [x size]
mov ecx,60*65536+280 ; [y start] *65536 + [y size]
mov edx,0x14ffffff ; color of work area RRGGBB
mov edi,title ; WINDOW LABEL
mcall
 
mov eax,8 ; CONTROL BUTTONS
mov ebx,25*65536+9
mov ecx,113*65536+9
mov edx,2
mov esi,0x667788
newbut:
mcall
add ecx,16*65536
inc edx
cmp edx,8
jb newbut
 
cld
mov eax,4
mov ebx,25*65536+50 ; draw info text with function 4
mov ecx,0x000000
mov edx,text
mov esi,40
newline:
mcall
add ebx,16
add edx,40
cmp [edx],byte 'x'
jnz newline
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
 
ret
 
 
; DATA AREA
 
 
text:
if lang eq ru
db ' ‚६ï á¥à¢¥à : '
db ' '
db ' Œ¥­î ã¯à ¢«¥­¨ï á¥à¢¥à®¬: '
db ' '
db ' - ‚몫îç¨âì '
db ' - ¥à¥§ £à㧨âì '
db ' - ‘®åà ­¨âì ä«®¯¯¨-¨¬¥¤¦ '
db ' - ‘®åà ­¨âì ¨¬¥¤¦ †. ¤¨áª  '
db ' - ƒ®àï稩 à¥áâ àâ ï¤à  '
db ' - ‡ ªàë⨥ á¥à¢¥à­®© ç á⨠'
db ' '
db ' ‹®ª «ì­ë©  ¤à¥á : 192.168.0.1 '
db ' “¤ «ñ­­ë©  ¤à¥á : 192.168.0.2 '
db '€¤à¥á á¥à¢¥à  - ¢ ª®­æ¥ ¨á室­¨ª  '
db 'x' ; <- END MARKER, DONT DELETE
 
else
db ' On server: '
db ' '
db ' Server control menu: '
db ' '
db ' - Shutdown '
db ' - Reboot '
db ' - Save ramdisk image to floppy '
db ' - Save ramdisk image to hard disk '
db ' - Kernel restart '
db ' - Close server part '
db ' '
db ' Local address : 192.168.0.1 '
db ' Remote address : 192.168.0.2 '
db 'Address of server is in end of source '
db 'x' ; <- END MARKER, DONT DELETE
end if
 
title db 'Remote Control Center(Client)',0
 
 
socket dd 0x0
 
remote_ip db 192,168,0,2
 
sen_shutdown db 'S'
sen_reboot db 'R'
sen_savefi db 'F'
sen_savehi db 'H'
sen_hotreboot db 'O'
sen_exit db 'E'
connect db 'C'
 
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/rccc/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm rccc.asm rccc
@erase lang.inc
@pause
/programs/network_old/rccc/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm rccc.asm rccc
@erase lang.inc
@pause
/programs/network_old/rccs/trunk/rccs.asm
0,0 → 1,341
;
; Remote Control Center(Server)
;
; €¢â®à: Hex
; ‘ ©â: www.mestack.narod.ru
;
; Ž¯¨á ­¨¥:
; à®£à ¬¬ , ¯à¥¤­ §­ ç¥­­ ï ¤«ï ã¯à ¢«¥­¨ï 㤠«ñ­­ë¬ ª®¬¯ìîâ¥à®¬.‘¥à¢¥à­ ï
; ç áâì.
;
; Compile with FASM for Menuet
; Š®¬¯¨«¨àã¥âáï FASM'®¬ ¤«ï Œ¥­ãí⠎‘
;
use32
org 0x0
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image
dd 0x5000 ; memory for app
dd 0x5000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Icon
include 'lang.inc'
include '..\..\..\macros.inc'
remote_ip db 192,168,0,1
START: ; start of execution
mov eax, 53 ; open receiver socket
mov ebx, 0
mov ecx, 0x6100 ; local port
mov edx, 0x6000 ; remote port
mov esi, dword [remote_ip] ; remote IP
mcall
mov [socket],eax
mov [0],eax ; save for remote code
 
red:
call draw_window ; at first, draw the window
still:
mov eax,23 ; wait here for event
mov ebx,1
mcall
cmp eax,1 ; redraw request ?
jz red
cmp eax,2 ; key in buffer ?
jz key
cmp eax,3 ; button in buffer ?
jz button
mov eax,53 ; data from cluster terminal ?
mov ebx,2
mov ecx,[socket]
mcall
cmp eax,0
jne data_arrived
jmp still
key:
mov eax,2
mcall
jmp still
button:
mov eax,53
mov ebx,1
mov ecx,[socket]
mcall
or eax,-1
mcall
data_arrived:
mov eax,5 ; wait a second for everything to arrive
mov ebx,10
mcall
mov edi,I_END
get_data:
mov eax,53
mov ebx,3
mov ecx,[socket]
mcall
mov [edi],bl
inc edi
mov eax,53
mov ebx,2
mov ecx,[socket]
mcall
cmp eax,0
jne get_data
cmp byte [I_END],'C' ;Connect ?
jne no_con
mov eax,4
mov ebx,10*65536+60
add ebx,[y]
mov ecx,0x000000
mov edx,inp_con
mov esi,inp_con.len
mcall
add [y],10
 
jmp still
 
no_con:
cmp byte [I_END],'S' ; Shutdown ?
jne no_shut
mov eax,4
mov ebx,10*65536+60
add ebx,[y]
mov ecx,0x000000
mov edx,inp_shut
mov esi,inp_shut.len
mcall
add [y],10
 
mov eax,18
mov ebx,9
mov ecx,2
mcall
 
jmp still
 
no_shut:
cmp byte [I_END],'R' ; Reboot ?
jne no_reb
mov eax,4
mov ebx,10*65536+60
add ebx,[y]
mov ecx,0x000000
mov edx,inp_reb
mov esi,inp_reb.len
mcall
add [y],10
 
mov eax,18
mov ebx,9
mov ecx,3
mcall
jmp still
 
no_reb:
cmp byte [I_END],'F' ; Save image on floppi ?
jne no_savefi
mov eax,4
mov ebx,10*65536+60
add ebx,[y]
mov ecx,0x000000
mov edx,inp_savefi
mov esi,inp_savefi.len
mcall
add [y],10
 
mov eax,18
mov ebx,9
mov ecx,1
mcall
jmp still
 
no_savefi:
cmp byte [I_END],'H' ; Save image on hard disk ?
jne no_savehi
mov eax,4
mov ebx,10*65536+60
add ebx,[y]
mov ecx,0x000000
mov edx,inp_savehi
mov esi,inp_savehi.len
mcall
add [y],10
 
mov eax,18
mov ebx,6
mov ecx,2
mcall
 
jmp still
 
no_savehi:
cmp byte [I_END],'O' ; Hot reboot ?
jne no_hotreb
mov eax,4
mov ebx,10*65536+60
add ebx,[y]
mov ecx,0x000000
mov edx,inp_hotreb
mov esi,inp_hotreb.len
mcall
add [y],10
 
mov eax,18
mov ebx,9
mov ecx,4
mcall
jmp still
 
no_hotreb:
cmp byte [I_END],'E' ; Unload server ?
jne no_com
mov eax,4
mov ebx,10*65536+60
add ebx,[y]
mov ecx,0x000000
mov edx,inp_exit
mov esi,inp_exit.len
mcall
add [y],10
call button
jmp still
 
no_com:
mov eax,4
mov ebx,10*65536+60
add ebx,[y]
mov ecx,0x000000
mov edx,inp_com
mov esi,inp_com.len
mcall
add [y],10
 
jmp still
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
draw_window:
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,100*65536+300 ; [x start] *65536 + [x size]
mov ecx,100*65536+330 ; [y start] *65536 + [y size]
mov edx,0x14ffffff ; color of work area RRGGBB
mov edi,title ; WINDOW LABEL
mcall
; Re-draw the screen text
cld
mov eax,4
mov ebx,10*65536+30 ; draw info text with function 4
mov ecx,0x000000
mov edx,text
mov esi,40
newline:
mcall
add ebx,16
add edx,40
cmp [edx],byte 'x'
jnz newline
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
ret
; DATA AREA
text:
if lang eq ru
db '„ ­­ë©  ¤à¥á : 192.168.0.2 '
db 'à®á«ã訢 ¥¬ë© ¯®àâ : 0x6100 '
db '‘®áâ®ï­¨¥: '
db 'x' ; <- END MARKER, DONT DELETE
else
db 'This address : 192.168.0.2 '
db 'Used port : 0x6100 '
db 'Status: '
db 'x' ; <- END MARKER, DONT DELETE
end if
title db 'Remote Control Center(Server)',0
socket dd 0x0
y dd 0x10
sysclock dd 0x0
 
if lang eq ru
inp_con db '‚­¨¬ ­¨¥, ¯®¤ª«î稫áï ª«¨¥­â!'
.len = $-inp_con
inp_shut db 'ˆ¤ñ⠮⪫î祭¨¥ á¨á⥬ë...'
.len = $-inp_shut
inp_reb db 'ˆ¤ñâ ¯¥à¥§ £à㧪 ...'
.len = $-inp_reb
inp_savefi db '‘®å࠭塞 ¨¬¥¤¦ ­  ¤¨áª¥âã...'
.len = $-inp_savefi
inp_savehi db '‘®å࠭塞 ¨¬¥¤¦ ­  †. ¤¨áª...'
.len = $-inp_savehi
inp_hotreb db 'ˆ¤ñâ £®àï稩 à¥áâ àâ ï¤à ...'
.len = $-inp_hotreb
inp_exit db '‚ë室 ¨§ ¯à®£à ¬¬ë...'
.len = $-inp_exit
inp_com db '¥®¯®§­ ­­ ï ª®¬¬ ­¤ !'
.len = $-inp_com
else
inp_con db 'Note, client has been connected!'
.len = $-inp_con
inp_shut db 'Turn off in progress...'
.len = $-inp_shut
inp_reb db 'Reboot in progress...'
.len = $-inp_reb
inp_savefi db 'Saving image to floppy...'
.len = $-inp_savefi
inp_savehi db 'Saving image to hard disk...'
.len = $-inp_savehi
inp_hotreb db 'Kernel restart in progress...'
.len = $-inp_hotreb
inp_exit db 'Exiting from program...'
.len = $-inp_exit
inp_com db 'Unknown command!'
.len = $-inp_com
end if
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/rccs/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm rccs.asm rccs
@erase lang.inc
@pause
/programs/network_old/rccs/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm rccs.asm rccs
@erase lang.inc
@pause
/programs/network_old/remote/trunk/remote.asm
0,0 → 1,208
;
; Remote processing example (remote node) - vt
;
; Compile with FASM for Menuet
;
use32
org 0x0
db 'MENUET01' ; header
dd 0x01 ; header version
dd START ; entry point
dd I_END ; image size
dd I_END+0x10000 ; required memory
dd I_END+0x10000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Path
include 'lang.inc'
include '..\..\..\macros.inc'
remote_ip db 192,168,1,26
START: ; start of execution
mov eax, 53 ; open receiver socket
mov ebx, 0
mov ecx, 0x3000 ; local port
mov edx, 0xffff ; remote port
mov esi, dword [remote_ip] ; remote IP
mcall
mov [socketNum],eax
mov [0],eax ; save for remote code
 
red:
call draw_window ; at first, draw the window
still:
mov eax,23 ; wait here for event
mov ebx,1
mcall
cmp eax,1 ; redraw request ?
jz red
cmp eax,2 ; key in buffer ?
jz key
cmp eax,3 ; button in buffer ?
jz button
mov eax,53 ; data from cluster terminal ?
mov ebx,2
mov ecx,[socketNum]
mcall
cmp eax,0
jne data_arrived
jmp still
key:
mov eax,2
mcall
jmp still
button:
mov eax,53
mov ebx,1
mov ecx,[socketNum]
mcall
or eax,-1
mcall
data_arrived:
mov eax,5 ; wait a second for everything to arrive
mov ebx,10
mcall
mov edi,I_END
get_data:
mov eax,53
mov ebx,3
mov ecx,[socketNum]
mcall
mov [edi],bl
inc edi
mov eax,53
mov ebx,2
mov ecx,[socketNum]
mcall
cmp eax,0
jne get_data
add byte [I_END+14],48
mov eax,4
mov ebx,10*65536+50
add ebx,[y]
mov ecx,0x000000
mov edx,I_END
mov esi,23
mcall
add [y],10
cmp byte [I_END+14],'1' ; DATA PACKET ?
jne no_packet
mov esi,I_END+23
mov edi,[I_END+15]
mov ecx,[I_END+19]
cld
rep movsb
jmp still
no_packet:
cmp byte [I_END+14],'2' ; EXECUTE ?
jne no_execute
mov eax,[I_END+15]
call eax
jmp still
no_execute:
jmp still
y dd 0x10
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
draw_window:
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,100*65536+286 ; [x start] *65536 + [x size]
mov ecx,100*65536+330 ; [y start] *65536 + [y size]
mov edx,0x14ffffff ; color of work area RRGGBB
mov edi,title ; WINDOW LABEL
mcall
; Re-draw the screen text
cld
mov eax,4
mov ebx,10*65536+30 ; draw info text with function 4
mov ecx,0x000000
mov edx,text
mov esi,40
newline:
mcall
add ebx,16
add edx,40
cmp [edx],byte 'x'
jnz newline
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
ret
; DATA AREA
text:
db 'THIS NODE : 192.168.1.22 '
db 'LISTENING TO PORT : 0x3000 '
db 'x' ;<- END MARKER, DONT DELETE
title db 'CLUSTER REMOTE',0
socketNum dd 0x0
send_data db 'MenuetRemote00' ; 00 header ; -> remote port 0x3000
db 1 ; 14 send
dd 0x0 ; 15 position
dd 0x0 ; 19 size
; 23
execute db 'MenuetRemote00' ; 00 header ; -> remote port 0x3000
db 2 ; 14 execute
dd 0x0 ; 15 position
; 19
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/remote/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm remote.asm remote
@erase lang.inc
@pause
/programs/network_old/remote/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm remote.asm remote
@erase lang.inc
@pause
/programs/network_old/tftpa/trunk/tftpa.asm
0,0 → 1,725
;
; TFTP Wave Player
;
; Compile with FASM for Menuet
;
;
; 12.7.2002 - Audio system calls by VT
;
use32
org 0x0
db 'MENUET01' ; header
dd 0x01 ; header version
dd START ; entry point
dd I_END ; image size
dd I_END+0x10000 ; required memory
dd I_END+0x10000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Path
 
include 'lang.inc'
include '..\..\..\macros.inc'
delay dd 145
wait_for dd 0x0
START: ; start of execution
mov dword [prompt], p9
mov dword [promptlen], p9len - p9
 
red:
call draw_window ; at first, draw the window
still:
mov eax,10 ; wait here for event
mcall
cmp eax,1 ; redraw request ?
jz red
cmp eax,2 ; key in buffer ?
jz key
cmp eax,3 ; button in buffer ?
jz button
jmp still
key: ; Keys are not valid at this part of the
mov eax,2 ; loop. Just read it and ignore
mcall
jmp still
button: ; button
mov eax,17 ; get id
mcall
cmp ah,1 ; button id=1 ?
jnz noclose
; close socket before exiting
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
mcall
mov [socketNum], dword 0
or eax,-1 ; close this program
mcall
noclose:
cmp ah,2 ; copy file to local machine?
jnz nocopyl
mov dword [prompt], p5
mov dword [promptlen], p5len - p5
call draw_window ;
; Copy File from Remote Host to this machine
call translateData ; Convert Filename & IP address
mov edi, tftp_filename + 1
mov [edi], byte 0x01 ; setup tftp msg
call copyFromRemote
jmp still
nocopyl:
cmp ah,4
jz f1
cmp ah,5
jz f2
jmp nof12
f1:
mov [addr],dword source
mov [ya],dword 35
jmp rk
f2:
mov [addr],dword destination
mov [ya],dword 35+16
rk:
mov ecx,15
mov edi,[addr]
mov al,' '
rep stosb
call print_text
mov edi,[addr]
f11:
mov eax,10
mcall
cmp eax,2
jz fbu
jmp still
fbu:
mov eax,2
mcall ; get key
shr eax,8
cmp eax,8
jnz nobs
cmp edi,[addr]
jz f11
sub edi,1
mov [edi],byte ' '
call print_text
jmp f11
nobs:
cmp eax,dword 31
jbe f11
cmp eax,dword 95
jb keyok
sub eax,32
keyok:
mov [edi],al
call print_text
add edi,1
mov esi,[addr]
add esi,15
cmp esi,edi
jnz f11
jmp still
print_text:
mov eax,13
mov ebx,103*65536+15*6
mov ecx,[ya]
shl ecx,16
mov cx,8
mov edx,0x224466
mcall
mov eax,4
mov ebx,103*65536
add ebx,[ya]
mov ecx,0xffffff
mov edx,[addr]
mov esi,15
mcall
ret
nof12:
jmp still
;***************************************************************************
; Function
; translateData
;
; Description
; Coverts the filename and IP address typed in by the user into
; a format suitable for the IP layer.
;
; The filename, in source, is converted and stored in tftp_filename
; The host ip, in destination, is converted and stored in tftp_IP
;
;***************************************************************************
translateData:
; first, build up the tftp command string. This includes the filename
; and the transfer protocol
; First, write 0,0
mov al, 0
mov edi, tftp_filename
mov [edi], al
inc edi
mov [edi], al
inc edi
; Now, write the file name itself, and null terminate it
mov ecx, 15
mov ah, ' '
mov esi, source
td001:
lodsb
stosb
cmp al, ah
loopnz td001
cmp al,ah ; Was the entire buffer full of characters?
jne td002
dec edi ; No - so remove ' ' character
td002:
mov [edi], byte 0
inc edi
mov [edi], byte 'O'
inc edi
mov [edi], byte 'C'
inc edi
mov [edi], byte 'T'
inc edi
mov [edi], byte 'E'
inc edi
mov [edi], byte 'T'
inc edi
mov [edi], byte 0
mov esi, tftp_filename
sub edi, esi
mov [tftp_len], edi
; Now, convert the typed IP address into a real address
; No validation is done on the number entered
; ip addresses must be typed in normally, eg
; 192.1.45.24
xor eax, eax
mov dh, 10
mov dl, al
mov [tftp_IP], eax
; 192.168.24.1 1.1.1.1 1. 9.2.3.
mov esi, destination
mov edi, tftp_IP
mov ecx, 4
td003:
lodsb
sub al, '0'
add dl, al
lodsb
cmp al, '.'
je ipNext
cmp al, ' '
je ipNext
mov dh, al
sub dh, '0'
mov al, 10
mul dl
add al, dh
mov dl, al
lodsb
cmp al, '.'
je ipNext
cmp al, ' '
je ipNext
mov dh, al
sub dh, '0'
mov al, 10
mul dl
add al, dh
mov dl, al
lodsb
ipNext:
mov [edi], dl
inc edi
mov dl, 0
loop td003
ret
;***************************************************************************
; Function
; copyFromRemote
;
; Description
;
;***************************************************************************
copyFromRemote:
mov eax,0x20000-512
mov [fileposition], eax
; Get a random # for the local socket port #
mov eax, 3
mcall
mov ecx, eax
shr ecx, 8 ; Set up the local port # with a random #
; open socket
mov eax, 53
mov ebx, 0
mov edx, 69 ; remote port
mov esi, [tftp_IP] ; remote IP ( in intenet format )
mcall
mov [socketNum], eax
; make sure there is no data in the socket - there shouldn't be..
cfr001:
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
mcall ; read byte
mov eax, 53
mov ebx, 2
mov ecx, [socketNum]
mcall ; any more data?
cmp eax, 0
jne cfr001 ; yes, so get it
; Now, request the file
mov eax, 53
mov ebx, 4
mov ecx, [socketNum]
mov edx, [tftp_len]
mov esi, tftp_filename
mcall
cfr002:
mov eax,23 ; wait here for event
mov ebx,1 ; Time out after 10ms
mcall
cmp eax,1 ; redraw request ?
je cfr003
cmp eax,2 ; key in buffer ?
je cfr004
cmp eax,3 ; button in buffer ?
je cfr005
; Any data to fetch?
mov eax, 53
mov ebx, 2
mov ecx, [socketNum]
mcall
cmp eax, 0
je cfr002
push eax ; eax holds # chars
; Update the text on the display - once
mov eax, [prompt]
cmp eax, p3
je cfr008
mov dword [prompt], p3
mov dword [promptlen], p3len - p3
call draw_window ;
cfr008:
; we have data - this will be a tftp frame
; read first two bytes - opcode
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
mcall ; read byte
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
mcall ; read byte
pop eax
; bl holds tftp opcode. Can only be 3 (data) or 5 ( error )
cmp bl, 3
jne cfrerr
push eax
; do data stuff. Read block #. Read data. Send Ack.
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
mcall ; read byte
mov [blockNumber], bl
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
mcall ; read byte
mov [blockNumber+1], bl
cfr007:
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
mcall ; read byte
mov esi, [fileposition]
mov [esi], bl
mov [esi+1],bl
add dword [fileposition],2
mov eax, 53
mov ebx, 2
mov ecx, [socketNum]
mcall ; any more data?
cmp eax, 0
jne cfr007 ; yes, so get it
cmp [fileposition],0x20000+0xffff
jb get_more_stream
wait_more:
mov eax,5 ; wait for correct timer position
; to trigger new play block
mov ebx,1
mcall
mov eax,26
mov ebx,9
mcall
cmp eax,[wait_for]
jb wait_more
add eax,[delay]
mov [wait_for],eax
mov esi,0x20000
mov edi,0x10000
mov ecx,65536
cld
rep movsb
mov eax,55
mov ebx,0
mov ecx,0x10000
mcall
mov eax,55
mov ebx,1
mcall
mov [fileposition],0x20000
get_more_stream:
; write the block number into the ack
mov al, [blockNumber]
mov [ack + 2], al
mov al, [blockNumber+1]
mov [ack + 3], al
; send an 'ack'
mov eax, 53
mov ebx, 4
mov ecx, [socketNum]
mov edx, ackLen - ack
mov esi, ack
mcall
; If # of chars in the frame is less that 516,
; this frame is the last
pop eax
cmp eax, 516
je cfr002
; Write the file
mov eax, 33
mov ebx, source
mov edx, [filesize]
mov ecx, I_END + 512
mov esi, 0
mcall
jmp cfrexit
cfrerr:
; simple implementation on error - just read all data, and return
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
mcall ; read byte
mov eax, 53
mov ebx, 2
mov ecx, [socketNum]
mcall ; any more data?
cmp eax, 0
jne cfrerr ; yes, so get it
jmp cfr006 ; close socket and close app
cfr003: ; redraw request
call draw_window
jmp cfr002
cfr004: ; key pressed
mov eax,2 ; just read it and ignore
mcall
jmp cfr002
cfr005: ; button
mov eax,17 ; get id
mcall
cmp ah,1 ; button id=1 ?
jne cfr002 ; If not, ignore.
cfr006:
; close socket
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
mcall
mov [socketNum], dword 0
mov eax,-1 ; close this program
mcall
jmp $
cfrexit:
; close socket
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
mcall
mov [socketNum], dword 0
mov dword [prompt], p4
mov dword [promptlen], p4len - p4
call draw_window ;
ret
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
draw_window:
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,100*65536+230 ; [x start] *65536 + [x size]
mov ecx,100*65536+170 ; [y start] *65536 + [y size]
mov edx,0x14224466 ; color of work area RRGGBB
mov edi,title
mcall
mov eax,8 ; DELETE BUTTON
mov ebx,20*65536+190
mov ecx,111*65536+15
mov edx,2
mov esi,0x557799
mcall
mov ebx,200*65536+10
mov ecx,34*65536+10
mov edx,4
mcall
mov ecx,50*65536+10
mov edx,5
mcall
; Copy the file name to the screen buffer
; file name is same length as IP address, to
; make the math easier later.
cld
mov esi,source
mov edi,text+13
mov ecx,15
rep movsb
; copy the IP address to the screen buffer
mov esi,destination
mov edi,text+40+13
mov ecx,15
rep movsb
; copy the prompt to the screen buffer
mov esi,[prompt]
mov edi,text+280
mov ecx,[promptlen]
rep movsb
; Re-draw the screen text
cld
mov eax,4
mov ebx,25*65536+35 ; draw info text with function 4
mov ecx,0xffffff
mov edx,text
mov esi,40
newline:
mcall
add ebx,16
add edx,40
cmp [edx],byte 'x'
jnz newline
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
ret
; DATA AREA
source db 'HEAT8M22.WAV '
destination db '192.168.1.24 '
tftp_filename: times 15 + 9 db 0
tftp_IP: dd 0
tftp_len: dd 0
addr dd 0x0
ya dd 0x0
fileposition dd 0 ; Points to the current point in the file
filesize dd 0 ; The number of bytes written / left to write
fileblocksize dw 0 ; The number of bytes to send in this frame
text:
db 'SOURCE FILE: xxxxxxxxxxxxxxx '
db 'HOST IP ADD: xxx.xxx.xxx.xxx '
db ' '
db 'WAVE FORMAT: 8 BIT,MONO,22050HZ '
db ' '
db ' SERVER -> PLAY FILE '
db ' '
db ' '
db 'x' ; <- END MARKER, DONT DELETE
title db 'TFTP Wave Player',0
prompt: dd 0
promptlen: dd 0
p1: db 'Waiting for Command '
p1len:
p9: db 'Define SB with setup'
p9len:
p2: db 'Sending File '
p2len:
p3: db 'Playing File '
p3len:
p4: db 'Complete '
p4len:
p5: db 'Contacting Host... '
p5len:
p6: db 'File not found. '
p6len:
ack:
db 00,04,0,1
ackLen:
socketNum:
dd 0
blockNumber:
dw 0
; This must be the last part of the file, because the blockBuffer
; continues at I_END.
blockBuffer:
db 00, 03, 00, 01
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/tftpa/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm tftpa.asm tftpa
@erase lang.inc
@pause
/programs/network_old/tftpa/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm tftpa.asm tftpa
@erase lang.inc
@pause
/programs/network_old/ym/trunk/ym.asm
0,0 → 1,1069
; Yahoo Messanger for MenuetOS
; Compile with FASM for Menuet
;B+ System header
use32
org 0x0
db 'MENUET01' ; header
dd 0x01 ; header version
dd START ; entry point
dd I_END ; image size
dd I_END+0x10000 ; required memory
dd I_END+0x10000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Path
 
;E:.
include 'lang.inc'
include '..\..\..\macros.inc'
;B+ Definitions
v_sp equ 330
h_sp equ 400
fr_sp equ 120
line_wid equ 45
fr_max_lines equ 17
;memory
sys_colors equ I_END
text_zone equ sys_colors+4*10
;friend_zone equ text_zone+45*25 ;uncom
;friend_zone+32*fr_max_lines
;E:.
START:
;B+ Main execution
 
mov ebx,3
mov ecx,sys_colors
mov edx,10*4
mov eax,48
mcall
call clear_text
red:
call draw_window
still:
mov ebx,50
mov eax,23
mcall
cmp eax,1
je red
cmp eax,2
je key
cmp eax,3
je button
call check_message
jmp still
key:
mov eax,2
mcall
cmp [is_connect],0
je still
call send_key_string
jmp still
button:
mov eax,17
mcall
cmp ah,1
jne noclose
or eax,-1
mcall
jmp $
noclose:
;B+ Check friend
cmp ah,2
jb .no_friend
cmp ah,100
ja .no_friend
;pressed number
sub ah,2
shr ax,8
;find real name
mov [friend_p],friend_zone
mov edi,0
.next:
push [friend_p]
call test_friend
jc .group
inc edi
.group:
cmp di,ax
pop ebx
jbe .next
inc ebx
;exact place
mov ecx,[friend_p]
sub ecx,ebx
dec ecx
;Insert in send
cmp al,10
jb .good
add al,'A'-'0'-10
.good:
add al,'0'
mov [view_text+1],al
;Clear old a. friend
pusha
mov ebx,(h_sp-140) shl 16 + 132
mov ecx,(v_sp-53) shl 16 + 10
mov edx,[sys_colors+4*5]
mov eax,13
mcall
popa
;show item
mov [f_name_b],ebx
mov [f_name_l],ecx
call show_a_friend
jmp still
.no_friend:
;E:.
;B+ Check User / Password
cmp ah,103
je input_username
cmp ah,104
je input_password
;E:.
;B+ Connect / Dis...
cmp ah,101
je yahoo_c
cmp ah,102
je yahoo_d
;E:.
jmp still
;E:.
draw_window:
;B+ Draw window
mov ebx,1
mov eax,12
mcall
xor eax,eax ;DRAW WINDOW
mov ebx,150*65536+h_sp
mov ecx,100*65536+v_sp
mov edx,[sys_colors+4*5]
or edx,0x14000000
mov edi,title
mcall
 
;B+ Friend panel
mov ebx,(h_sp-fr_sp) shl 16 + 3
mov ecx,20 shl 16 + v_sp-31 -56
mov edx,[sys_colors+4*9]
mov eax,13
mcall
call show_friends
;E:.
;B+ Input panel
mov ebx,5 shl 16 + h_sp-9
mov ecx,(v_sp-31 -33-3) shl 16 + 3
mov edx,[sys_colors+4*9]
mov eax,13
mcall
mov ebx,(h_sp-(fr_sp-12)*8/6) shl 16 + 4
mov ecx,(v_sp-31-33) shl 16 + 30
mcall
mov ebx,(h_sp-8) shl 16 + 4
mcall
call show_a_friend
call show_string
;E:.
;B+ Login panel
mov ebx,5 shl 16 + h_sp-9
mov ecx,(v_sp-35) shl 16 + 31
mov edx,[sys_colors+4*9]
mov eax,13
mcall
mov ebx,(5+2+8+(user_txt_end-user_txt)*6) shl 16 + 6*15+7
mov ecx,(v_sp-32) shl 16 + 12
mov edx,[sys_colors+4*5]
mcall
mov ebx,(171+2+8+(psw_txt_end-psw_txt)*6) shl 16 + 6*23+7
mov ecx,(v_sp-32) shl 16 + 12
mcall
;connect button
mov ebx,(h_sp-128) shl 16 + (con_txt_end-con_txt)*6 + 7
mov ecx,(v_sp-18) shl 16 + 12
mov edx,101
mov esi,[sys_colors+4*6]
mov eax,8
mcall
;disconnect button
shl ebx,16
add ebx,(h_sp-128+3) shl 16 + (dis_txt_end-dis_txt)*6 + 7
mov edx,102
mcall
;user button
mov ebx,8 shl 16 + (user_txt_end-user_txt)*6 + 5
mov ecx,(v_sp-18-15) shl 16 + 12
mov edx,103
mcall
;password button
mov ebx,174 shl 16 + (psw_txt_end-psw_txt)*6 + 5
mov edx,104
mcall
;login text
mov ebx,11 shl 16 + v_sp-15
mov ecx,[sys_colors+4*7]
mov edx,login_txt
mov esi,login_txt_end-login_txt
mov eax,4
mcall
;user text
mov ebx,11 shl 16 + v_sp-15-15
mov edx,user_txt
mov esi,user_txt_end-user_txt
mcall
;password text
mov ebx,(174+5) shl 16 + v_sp-15-15
mov edx,psw_txt
mov esi,psw_txt_end-psw_txt
mcall
;connect text
mov ebx,(h_sp-128+5) shl 16 + v_sp-15
mov edx,con_txt
mov esi,con_txt_end-con_txt
mcall
;disconnect text
add ebx,((con_txt_end-con_txt)*6+8 + 3) shl 16
mov edx,dis_txt
mov esi,dis_txt_end-dis_txt
mcall
call show_username
call show_password
;E:.
call show_text
mov ebx,2
mov eax,12
mcall
ret
;E:.
show_friends:
;B+ Show friend list
cmp [last_friend_place],friend_zone
jne .yes_show
ret
.yes_show:
;show button
mov ebx,(h_sp-fr_sp+5) shl 16 + 10
mov ecx,(20+3) shl 16 + 10
mov edx,2
mov esi,[sys_colors+4*6]
mov eax,8
mov edi,0
mov [friend_p],friend_zone
.next_button:
call test_friend
jc .no_b
mcall
inc edx
.no_b:
inc edi
add ecx,15 shl 16
cmp edi,[last_friend_line]
jne .next_button
;show numbers
mov [digit],'0'-1
mov ebx,(h_sp-fr_sp+8) shl 16 + (20+3)+2
;mov ecx,[sys_colors+4*7]
mov edx,digit
mov esi,1
mov eax,4
mov edi,0
mov [friend_p],friend_zone
push edx
.next_digit:
mov edx,[friend_p]
call test_friend
cmp [edx],byte 1
je .no_item
inc [digit]
cmp [digit],'9'+1
jne .good
mov [digit],'A'
.good:
;add ebx,1 shl 16
cmp [edx],byte 2
mov edx,[esp]
mov ecx,[sys_colors+4*6]
call hi_light
jne .no_online
mov ecx,[sys_colors+4*7]
;mcall
;or ecx,0x10000000
.no_online:
;sub ebx,1 shl 16
mcall
;and ecx,not 0x10000000
.no_item:
add ebx,15
inc edi
cmp edi,[last_friend_line]
jne .next_digit
add esp,4
;show names
mov ebx,(h_sp-fr_sp+8 + 10) shl 16 + (20+3)+2
mov ecx,[sys_colors+4*8]
mov eax,4
mov edi,0
mov [friend_p],friend_zone
mov esi,4
.next_name:
mov edx,[friend_p]
call test_friend
mov esi,[friend_p]
inc edx
sub esi,edx
and ebx,0xffff
or ebx,(h_sp-fr_sp+8 + 10) shl 16
cmp [edx-1],byte 1
jne .no_group
sub ebx,12 shl 16
.no_group:
mcall
add ebx,15
inc edi
cmp edi,[last_friend_line]
jne .next_name
ret
.p db 16 ;>
digit db '0'
;last_friend_line dd 0x0 ;uncom
test_friend:
push eax
mov eax,[friend_p]
clc
cmp [eax],byte 1
jne .no_hide
stc
.no_hide:
pushf
.next:
inc [friend_p]
mov eax,[friend_p]
cmp [eax],byte 0
jne .next
inc [friend_p]
popf
pop eax
ret
friend_p dd 0x0
hi_light:
pushf
add ecx,0x400000
test ecx,0xb00000
jnz .no_red_plus
sub ecx,0x400000
.no_red_plus:
add ecx,0x004000
test ecx,0x00b000
jnz .no_green_plus
sub ecx,0x008000
.no_green_plus:
add ecx,0x000040 ;80
test ecx,0x0000b0 ;80
jnz .no_blue_plus
sub ecx,0x000040 ;100
.no_blue_plus:
popf
ret
;E:.
;B+ Message text op.
clear_text:
mov edi,text_zone
mov ecx,45*26
mov al,0
cld
rep stosb
ret
show_text:
mov ebx,7 shl 16 + (20+3) ;+ 2
mov ecx,[sys_colors+4*8]
mov edx,text_zone+45
mov esi,45
mov eax,4
mov edi,0
.next_line:
cmp [edx-1],byte 0
jne .shift
mcall
.next:
add ebx,10
add edx,45
inc edi
cmp edi,24
jne .next_line
ret
.shift:
add ebx,3 shl 16
mcall
sub ebx,3 shl 16
jmp .next
scroll_text:
pusha
;move text
mov edi,text_zone
mov esi,edi
add esi,line_wid
mov ecx,line_wid*24
cld
rep movsb
;clear last line
mov ecx,line_wid
mov al,0
rep stosb
;clear zone
mov ebx,7 shl 16 + line_wid*6+2
mov ecx,(25-2) shl 16 + 24*10-2 +2
mov edx,[sys_colors+4*5]
mov eax,13
mcall
;show text
call show_text
popa
ret
show_message:
;ebx - begin
;ecx - length
mov eax,[.m_p]
add eax,ecx
.test:
cmp eax,text_zone+line_wid*25-1
jb .good1
call scroll_text
sub eax,line_wid
sub [.m_p],line_wid
jmp .test
.good1:
cmp [.m_p],text_zone+line_wid
jae .good2
add ebx,line_wid
add [.m_p],line_wid
sub ecx,line_wid
jmp .good1
.good2:
;
push ecx
mov esi,ebx
mov edi,[.m_p]
cld
rep movsb
pop ecx
;find v place
mov eax,[.m_p]
sub eax,text_zone+line_wid
mov ebx,line_wid
xor edx,edx
div ebx
xor edx,edx
mov ebx,10
mul ebx
mov ebx,eax
;show line
add ebx,7 shl 16 + 23 ;+2
mov ecx,[sys_colors+4*8]
mov edx,[.m_p]
mov esi,line_wid
mov eax,4
mcall
add ebx,3 shl 16
.next_line:
add ebx,10
add edx,line_wid
cmp [edx-1],byte 0
je .good3
mcall
jmp .next_line
.good3:
mov [.m_p],edx
ret
.m_p dd text_zone+45
;E:.
;B+ Show current people
show_a_friend:
mov ebx,(h_sp-137) shl 16 + v_sp-52
mov ecx,[sys_colors+4*8]
or ecx,0x10000000
mov edx,[f_name_b]
mov esi,[f_name_l]
mov eax,4
mcall
ret
f_name_b dd fnb
f_name_l dd 10
fnb:
db 'yahoo_help'
;E:.
;B+ Input strings
send_key_string:
;B+ Test active keys
cmp ah,13
je send_text
cmp ah,27
je clear_input_text
cmp ah,8
je .backs_text
;E:.
mov [.this_c],ah
cmp [.c_pl],123
jne .show
ret
.show:
;save char
mov ebx,[.c_pl]
mov [in_text+ebx],ah
inc [.c_pl]
;show char
mov ebx,[.xy]
mov ecx,[sys_colors+4*8]
mov edx,.this_c
mov esi,1
mov eax,4
mcall
;
cmp [.c_pl],41
je .new_line
cmp [.c_pl],82
je .new_line
add [.xy],6 shl 16
call show_cursor
ret
;;;
.new_line:
and [.xy],0x0000ffff
add [.xy],9 shl 16 + 9
call show_cursor
ret
.this_c db ' '
.c_pl dd 0x0
.xy dd 7 shl 16 + v_sp-62
;B+ Special keys - action
.backs_text:
;
cmp [.c_pl],0
jne .yes_back
ret
.yes_back:
cmp [.c_pl],41
je .back_line
add [.xy],2 shl 16
cmp [.c_pl],82
je .back_line
sub [.xy],2 shl 16
.next:
;
sub [.xy],6 shl 16
dec [.c_pl]
mov eax,[.c_pl]
mov bl,[in_text+eax]
mov [.this_c],bl
mov ebx,[.xy]
mov ecx,[sys_colors+4*5]
mov edx,.this_c
mov esi,1
mov eax,4
mcall
mov ebx,[.c_pl]
mov [in_text+ebx],byte 0
jmp show_cursor
;
.back_line:
;and [.xy],0x0000ffff
sub [.xy],9
add [.xy],(253-9) shl 16
jmp .next
send_text:
;show text to message board
mov ebx,view_text
mov ecx,[send_key_string.c_pl]
add ecx,3
call show_message
;send message to internet
;call internet_send
clear_input_text:
;prepare new message
;; clear memory
mov edi,in_text
mov ecx,255/4
xor eax,eax
cld
rep stosd
;; clear zone
mov ebx,5 shl 16 + h_sp-140-9
mov ecx,(v_sp-31 -33) shl 16 + 29
mov edx,[sys_colors+4*5]
mov eax,13
mcall
;; move cursor
mov ebx,7 shl 16 + v_sp-62
mov [send_key_string.xy],ebx
mov [show_cursor.old_xy],ebx
;; clear place
xor ebx,ebx
mov [send_key_string.c_pl],ebx
; call show_cursor
; ret
;E:.
show_cursor:
;login text
; mov ebx,4 shl 16 + v_sp-64
mov ebx,[.old_xy]
sub ebx,3 shl 16 + 2
mov ecx,[sys_colors+4*5]
mov edx,curs
mov esi,1
mov eax,4
mcall
add ebx,4
mcall
mov ebx,[send_key_string.xy]
mov [.old_xy],ebx
sub ebx,3 shl 16 + 2
mov ecx,0xffffff;[sys_colors+4*8]
mcall
add ebx,4
mcall
ret
.old_xy dd 7 shl 16 + v_sp-62
curs db '|'
show_string:
mov ebx,7 shl 16 + v_sp-62
mov ecx,[sys_colors+4*8]
mov edx,in_text
mov esi,41
mov eax,4
mcall
add ebx,2 shl 16 + 9
add edx,41
mcall
add ebx,9
add edx,41
mcall
call show_cursor
ret
view_text db 16,'?',16
in_text: times 255 db 0
;E:.
;B+ Friends...
add_friend:
;ebx - begin
; [ebx]=1 - Group name
; [ebx]=2 - Active user
; [ebx]=other - Non active user
;ecx - length
cmp [last_friend_line],fr_max_lines-1
je .no_more
test ecx,not 31
jnz .no_more ; very long id name
inc [last_friend_line]
mov esi,ebx
mov edi,[last_friend_place]
inc ecx
add [last_friend_place],ecx
dec ecx
cld
rep movsb
mov al,0
stosb
stosb
.no_more:
ret
last_friend_place dd fr_e ;del
;last_friend_place dd friend_zone ;uncom
find_friend:
push ebx ecx
mov edx,friend_zone
mov esi,0
mov edi,[last_friend_line]
; inc edi ;? uncom ?
.next_name:
cmp [edx],byte 1
je .no_find ;Group
inc edx
dec ecx
.next:
mov al,[edx]
mov ah,[ebx]
cmp ah,al
jne .no_find
inc edx
inc ebx
dec ecx
jne .next
cmp [edx],byte 0
jne .no_find
;find
mov eax,esi
cmp esi,9
ja .letter
add al,'0'
ret
.letter:
add al,'A'-10
ret
.no_find:
cmp [edx],byte 0
je .go_next
inc edx
jmp .no_find
.go_next:
dec edi
je .noting
mov ebx,[esp+4]
mov ecx,[esp]
inc esi
jmp .next_name
.noting:
mov al,'!'
pop ecx ebx
ret
;E:.
;B+ Connect / Disconnect
yahoo_c:
call connect
cmp eax,0
jne still ;not connected
mov [is_connect],0x1
jmp still
yahoo_d:
cmp [is_connect],0x0
je .noting
call disconnect
;
;stop connection
mov [is_connect],0x0
;
;clear text
mov ah,27
call send_key_string
;
;clear friends
; mov [last_friend_line],0x0 ;uncom
; mov [last_friend_place],friend_zone ;uncom
;
;set dafaut friend
mov [f_name_b],fnb
mov [f_name_l],10
mov [view_text+1],'?'
call draw_window
.noting:
jmp still
is_connect dd 0x0
;E:.
;B+ Load username / password
input_username:
mov edi,username
mov [edi],byte '_'
inc edi
mov ecx,16-1
cld
rep stosb
mov [.unp],username
.next:
call show_username
;get enen
mov eax,10
mcall
cmp eax,1
je .end
cmp eax,3
je .end
;key
mov eax,2
mcall
cmp ah,13
je .end
cmp ah,8
jne .no_back
cmp [.unp],username
je .next
dec [.unp]
mov ebx,[.unp]
mov [ebx],byte '_'
mov [ebx+1],byte 0
jmp .next
.no_back:
cmp [.unp],username+16
je .next
cmp ah,'0'
jb .bad
mov ebx,[.unp]
mov [ebx],ah
mov [ebx+1],byte '_'
inc [.unp]
.bad:
jmp .next
.end:
;del cursor
mov ebx,[.unp]
mov [ebx],byte 0
call show_username
;clear password
mov [password],byte 0
;hide password
mov ebx,(2+41*6) shl 16 + v_sp-15-15
mov ecx,[sys_colors+4*5]
mov edx,f_password
mov esi,4
mov eax,4
mcall
jmp still
.unp dd username
show_username:
;hide
mov ebx,(4+12*6-1) shl 16 + 16*6+1
mov ecx,(v_sp-15-15) shl 16 + 9
mov edx,[sys_colors+4*5]
mov eax,13
mcall
;show
mov ebx,(4+12*6) shl 16 + v_sp-15-15
mov ecx,[sys_colors+4*8]
mov edx,username
mov esi,16
mov eax,4
mcall
ret
username: times (16+1) db 0
input_password:
;clear
mov edi,password
mov ecx,24
mov al,0
cld
rep stosb
mov [.unp],password
;hide password
mov ebx,(2+41*6) shl 16 + v_sp-15-15
mov ecx,[sys_colors+4*5]
mov edx,f_password
mov esi,4
mov eax,4
mcall
.next:
;get enen
mov eax,10
mcall
cmp eax,1
je still
cmp eax,3
je still
;key
mov eax,2
mcall
cmp [.unp],password+24
je .no_next
cmp ah,13
jne .no_still
.no_next:
call show_password
jmp still
.no_still:
mov ebx,[.unp]
mov [ebx],ah
inc [.unp]
jmp .next
.unp dd password
show_password:
cmp [password],byte 0
je .end
mov ebx,(2+41*6) shl 16 + v_sp-15-15
mov ecx,[sys_colors+4*8]
mov edx,f_password
mov esi,4
mov eax,4
mcall
.end:
ret
f_password db '####'
password: times (24+1) db 0
;E:.
;B+ INTERNET
;Functions:
;call add_friend
; ebx+1 - pointer to name
; [ebx]=1 - Group name
; [ebx]=2 - Active user
; [ebx]=other - Non active user
; ecx - length
;
;call show_message
; ebx - begin of string
; ecx - length
; -----
; NOTE Use format:
; (<char>) <message>
; where:
; <char> - friend user char
; <message> - message from friend
;
;call find_friend
; ebx - begin of name
; ecx - length
; ret:
; al - friend user char
; -----
; NOTE currenly don't show message if al='!'
;Variables
;usernave (zero terminated)
;password (zero terminated)
;f_name_b - current friend user (to send)
;f_name_l - ^ length
;Memory
; (friend_zone+32*fr_max_lines) < addr: [addr] - free
connect:
;conect to yahoo
;return 0 if OK
;return <>0 if some other event (sys.func.23)
mov eax,0
ret
disconnect:
;disconnect
ret
check_message:
;test receive messages
ret
;E:.
;B+ Test data ;del
friend_zone: ;del
db 1,'First:',0 ;del
db 2,'hahaha',0 ;del
db 3,'second',0 ;del
db 3,'menuetos',0 ;del
db 1,'Treti:',0 ;del
db 2,'fourth',0 ;del
fr_e db 0 ;del
;del
times 200 db 0 ;del
;del
last_friend_line dd 0x6 ;del
 
title db 'Messenger (Yahoo Compatible)',0
;User / Password
login_txt db 'STATUS: SESSION: ___.___.___.___'
;VISIBLE
;HIDDEN
login_txt_end:
user_txt db 'USER ID ->'
user_txt_end:
psw_txt db 'PASSWORD ->'
psw_txt_end:
con_txt db 'CONNECT'
con_txt_end:
dis_txt db 'DISCONNECT'
dis_txt_end:
;E:.
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/ym/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm ym.asm ym
@erase lang.inc
@pause
/programs/network_old/ym/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm ym.asm ym
@erase lang.inc
@pause
/programs/network_old/smtps/trunk/smtps.asm
0,0 → 1,828
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SMTP server for MenuetOS ;;
;; ;;
;; License: GPL / See file COPYING for details ;;
;; Copyright 2002 (c) Ville Turjanmaa ;;
;; ;;
;; Compile with FASM for Menuet ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
version equ '0.1'
 
use32
 
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; required os
dd START ; program start
dd I_END ; program image size
dd 0x200000 ; required amount of memory
dd 0xffff0
dd 0,0
 
include '..\..\..\macros.inc'
 
save_file:
 
; cmp [file_start],0x100000+10
; jbe nosub
; sub [file_start],8
; nosub:
 
mov eax,[file_start]
sub eax,0x100000
mov ebx,files
mov [ebx+12],eax
 
mov eax,70
mcall
 
ret
 
 
START: ; start of execution
 
mov [file_start],0x100000
 
mov eax,70
mov ebx,filel
mcall
 
test eax,eax
jz @f
cmp eax,6
jnz notfound
@@:
add [file_start],ebx
notfound:
 
 
mov edi,I_END
mov ecx,60*120
mov al,32
cld
rep stosb
 
mov eax,[rxs]
imul eax,11
mov [pos],eax
 
mov ebp,0
mov edx,I_END
 
redraw:
call draw_window ; at first, draw the window
 
still:
 
inc [cursor_on_off]
 
mov eax,5
mov ebx,1
mcall
 
mov eax,11 ; wait here for event
mcall
 
cmp eax,1 ; redraw
je redraw
cmp eax,2 ; key
je key
cmp eax,3 ; button
je button
 
cmp [I_END+120*60],byte 1
jne no_main_update
mov [I_END+120*60],byte 0
mov edx,I_END
call draw_channel_text
no_main_update:
 
cmp [server_active],0
je noread
cmp [status],4
jne noread
call read_incoming_data
inc [close_connection]
cmp [close_connection],15*100
jbe noread
 
call yq
 
noread:
 
call print_status
 
cmp [status],4
je check_header
 
jmp still
 
 
check_header:
 
cmp [header_sent],1
je still
 
mov eax,53
mov ebx,7
mov ecx,[socket]
mov edx,6
mov esi,r220
mcall
mov [header_sent],1
 
jmp still
 
 
button: ; button
 
mov eax,17 ; get id
mcall
 
cmp ah,1 ; close program
jne noclose
or eax,-1
mcall
noclose:
 
call socket_commands
 
jmp still
 
 
old_status dd 0x0
 
print_status:
 
pusha
 
mov eax,53
mov ebx,6
mov ecx,[socket]
mcall
 
mov [status],eax
 
cmp eax,[old_status]
je no_print
 
mov [old_status],eax
 
push eax
 
mov eax,13
mov ebx,360*65536+30
mov ecx,151*65536+10
mov edx,0xffffff
mcall
 
pop ecx
mov eax,47
mov ebx,3*65536
mov edx,360*65536+151
mov esi,0x000000
 
cmp [server_active],0
je no_print
 
mcall
 
no_print:
 
popa
 
ret
 
 
socket_commands:
 
cmp ah,22 ; open socket
jnz tst3
mov eax,3
mcall
 
mov [server_active],1
 
mov eax,53
mov ebx,5
mov ecx,25 ; local port # - http
mov edx,0 ; no remote port specified
mov esi,0 ; no remote ip specified
mov edi,0 ; PASSIVE open
mcall
mov [socket], eax
 
ret
tst3:
 
 
cmp ah,24 ; close socket
jnz no_24
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
mov [header_sent],0
mov [mail_rp],0
mov [server_active],0
 
ret
no_24:
 
 
ret
 
 
 
key:
 
mov eax,2
mcall
 
jmp still
 
 
 
read_incoming_data:
 
pusha
 
read_new_byte:
 
call read_incoming_byte
cmp ecx,-1
je no_data_in_buffer
 
mov eax,[file_start]
mov [eax],bl
inc [file_start]
 
cmp bl,10
jne no_start_command
mov [cmd],1
no_start_command:
 
cmp bl,13
jne no_end_command
mov eax,[cmd]
mov [eax+command-2],byte 0
call analyze_command
mov edi,command
mov ecx,250
mov eax,0
cld
rep stosb
mov [cmd],0
no_end_command:
 
mov eax,[cmd]
cmp eax,250
jge still
 
mov [eax+command-2],bl
inc [cmd]
 
jmp read_new_byte
 
no_data_in_buffer:
 
popa
 
ret
 
 
 
 
 
analyze_command:
 
pusha
 
mov [text_start],I_END
mov ecx,[rxs]
imul ecx,11
mov [pos],ecx
 
mov bl,13
call print_character
mov bl,10
call print_character
 
cmp [cmd],2
jbe nott
mov ecx,[cmd]
sub ecx,2
mov esi,command+0
newcmdc:
mov bl,[esi]
call print_character
inc esi
loop newcmdc
 
nott:
 
mov edx,I_END
call draw_channel_text
 
cmd_len_ok:
 
cmp [command],dword 'data'
je datacom
cmp [command],dword 'DATA'
je datacom
cmp [command],dword 'Data'
je datacom
jmp nodatacom
datacom:
inc [mail_rp]
mov eax,53
mov ebx,7
mov ecx,[socket]
mov edx,6
mov esi,r354
mcall
mov [cmd],0
popa
ret
 
nodatacom:
 
cmp [mail_rp],0
jne nomrp0
mov eax,53
mov ebx,7
mov ecx,[socket]
mov edx,6
mov esi,r250
mcall
mov [cmd],0
popa
ret
nomrp0:
 
 
 
cmp [command],dword 'QUIT'
je yesquit
cmp [command],dword 'Quit'
je yesquit
cmp [command],dword 'quit'
je yesquit
jmp noquit
yq:
pusha
 
yesquit:
 
mov [close_connection],0
 
mov eax,53
mov ebx,7
mov ecx,[socket]
mov edx,6
mov esi,r221
mcall
mov [cmd],0
 
mov eax,5
mov ebx,5
mcall
 
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
 
mov eax,5
mov ebx,5
mcall
 
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
 
mov [header_sent],0
mov [mail_rp],0
 
call save_file
 
mov eax,5
mov ebx,20
mcall
 
mov eax,53
mov ebx,5
mov ecx,25 ; local port # - http
mov edx,0 ; no remote port specified
mov esi,0 ; no remote ip specified
mov edi,0 ; PASSIVE open
mcall
mov [socket], eax
 
popa
ret
noquit:
 
 
 
cmp [command],byte '.'
jne nodot
mov eax,53
mov ebx,7
mov ecx,[socket]
mov edx,6
mov esi,r250
mcall
mov [cmd],0
popa
ret
nodot:
 
popa
ret
 
 
r250 db '250 ',13,10
r221 db '221 ',13,10
r220 db '220 ',13,10
r354 db '354 ',13,10
 
 
 
draw_data:
 
pusha
 
add eax,[text_start]
mov [eax],bl
 
popa
ret
 
 
 
 
print_text:
 
pusha
 
mov ecx,command-2
add ecx,[cmd]
 
ptr2:
mov bl,[eax]
cmp bl,dl
je ptr_ret
cmp bl,0
je ptr_ret
call print_character
inc eax
cmp eax,ecx
jbe ptr2
 
ptr_ret:
 
mov eax,[text_start]
mov [eax+120*60],byte 1
 
popa
ret
 
 
 
print_character:
 
pusha
 
cmp bl,13 ; line beginning
jne nobol
mov ecx,[pos]
add ecx,1
boll1:
sub ecx,1
mov eax,ecx
xor edx,edx
mov ebx,[rxs]
div ebx
cmp edx,0
jne boll1
mov [pos],ecx
jmp newdata
nobol:
 
cmp bl,10 ; line down
jne nolf
addx1:
add [pos],dword 1
mov eax,[pos]
xor edx,edx
mov ecx,[rxs]
div ecx
cmp edx,0
jnz addx1
mov eax,[pos]
jmp cm1
nolf:
no_lf_ret:
 
 
cmp bl,15 ; character
jbe newdata
 
mov eax,[irc_data]
shl eax,8
mov al,bl
mov [irc_data],eax
 
mov eax,[pos]
call draw_data
 
mov eax,[pos]
add eax,1
cm1:
mov ebx,[scroll+4]
imul ebx,[rxs]
cmp eax,ebx
jb noeaxz
 
mov esi,[text_start]
add esi,[rxs]
 
mov edi,[text_start]
mov ecx,ebx
cld
rep movsb
 
mov esi,[text_start]
mov ecx,[rxs]
imul ecx,61
add esi,ecx
 
mov edi,[text_start]
mov ecx,[rxs]
imul ecx,60
add edi,ecx
mov ecx,ebx
cld
rep movsb
 
mov eax,ebx
sub eax,[rxs]
noeaxz:
mov [pos],eax
 
newdata:
 
mov eax,[text_start]
mov [eax+120*60],byte 1
 
popa
ret
 
 
 
read_incoming_byte:
 
mov eax, 53
mov ebx, 2
mov ecx, [socket]
mcall
 
mov ecx,-1
 
cmp eax,0
je no_more_data
 
mov eax, 53
mov ebx, 3
mov ecx, [socket]
mcall
 
mov ecx,0
 
no_more_data:
 
ret
 
 
 
draw_window:
 
pusha
 
mov eax,12
mov ebx,1
mcall
 
mov [old_status],300
 
mov eax,0 ; draw window
mov ebx,5*65536+400
mov ecx,5*65536+200
mov edx,0x13ffffff
mov edi,title
mcall
 
mov eax,8 ; button: open socket
mov ebx,23*65536+22
mov ecx,169*65536+10
mov edx,22
mov esi,0x55aa55
mcall
 
; mov eax,8 ; button: close socket
mov ebx,265*65536+22
mov edx,24
mov esi,0xaa5555
mcall
 
mov eax,38 ; line
mov ebx,5*65536+395
mov ecx,108*65536+108
mov edx,0x000000
mcall
 
mov eax,4
mov ebx,5*65536+123 ; info text
mov ecx,0x000000
mov edx,text
mov esi,70
newline:
mcall
add ebx,12
add edx,70
cmp [edx],byte 'x'
jne newline
 
mov edx,I_END ; text from server
call draw_channel_text
 
mov eax,12
mov ebx,2
mcall
 
popa
 
ret
 
 
 
 
 
draw_channel_text:
 
pusha
 
mov eax,4
mov ebx,10*65536+26
mov ecx,[scroll+4]
mov esi,[rxs]
dct:
pusha
mov cx,bx
shl ecx,16
mov cx,9
mov eax,13
mov ebx,10*65536
mov bx,word [rxs]
imul bx,6
mov edx,0xffffff
mcall
popa
push ecx
mov eax,4
mov ecx,0
cmp [edx],word '* '
jne no_red
mov ecx,0xff0000
no_red:
cmp [edx],word '**'
jne no_light_blue
cmp [edx+2],byte '*'
jne no_light_blue
mov ecx,0x0000ff
no_light_blue:
cmp [edx],byte '#'
jne no_blue
mov ecx,0x00ff00
no_blue:
mcall
add edx,[rxs]
add ebx,10
pop ecx
loop dct
 
popa
ret
 
 
 
text:
 
db ' Incoming mails are written to /sys/smtps.txt '
db ' The file can be fetched with TinyServer and a Html-browser. '
db ' Timeout is set to 15 seconds. '
db ' '
db ' Open SMTP server port 25 Close SMTP '
db 'x' ; <- END MARKER, DONT DELETE
 
 
irc_server_ip db 192,168,1,1
 
file_start dd 0x100000
 
files:
dd 2,0,0,?,0x100000
db '/sys/smtps.txt',0
filel:
dd 0,0,0,0x100000,0x100000
db '/sys/smtps.txt',0
 
 
server_active dd 0
 
status dd 0x0
header_sent db 0
 
channel_temp: times 100 db 0
channel_temp_length dd 0x0
 
close_connection dd 0x0
 
mail_rp dd 0
 
socket dd 0x0
 
bgc dd 0x000000
dd 0x000000
dd 0x00ff00
dd 0x0000ff
dd 0x005500
dd 0xff00ff
dd 0x00ffff
dd 0x770077
 
tc dd 0xffffff
dd 0xff00ff
dd 0xffffff
dd 0xffffff
dd 0xffffff
dd 0xffffff
dd 0xffffff
dd 0xffffff
 
cursor_on_off dd 0x0
 
max_windows dd 20
 
thread_stack dd 0x9fff0
thread_nro dd 1
thread_screen dd I_END+120*80*1
 
action_header_blue db 10,'*** ',0
action_header_red db 10,'*** ',0
 
action_header_short db 10,'* ',0
 
posx dd 0x0
incoming_pos dd 0x0
incoming_string: times 128 db 0
 
pos dd 0x0
 
text_start dd I_END
irc_data dd 0x0
print db 0x0
cmd dd 0x0
rxs dd 56
 
res: db 0,0
command: times 256 db 0x0
 
nick dd 0,0,0
irc_command dd 0,0
 
command_position dd 0x0
counter dd 0
send_to_server db 0
 
channel_list: times 32*20 db 32
send_to_channel dd 0x0
 
send_string: times 100 db 0x0
 
xpos dd 0
attribute dd 0
scroll dd 1
dd 8
 
numtext db ' '
 
title db 'Tiny SMTP email server v ',version,0
 
I_END:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/network_old/smtps/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm smtps.asm smtps
@erase lang.inc
@pause
/programs/network_old/smtps/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm smtps.asm smtps
@erase lang.inc
@pause
/programs/network_old/nntpc/trunk/build_en.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix en >lang.inc
@fasm nntpc.asm nntpc
@erase lang.inc
@pause
/programs/network_old/nntpc/trunk/build_ru.bat
0,0 → 1,5
@erase lang.inc
@echo lang fix ru >lang.inc
@fasm nntpc.asm nntpc
@erase lang.inc
@pause
/programs/network_old/nntpc/trunk/nntpc.asm
0,0 → 1,911
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; NNTP CLIENT v 0.1
;;
;; (C) Ville Turjanmaa
;;
 
version equ '0.1'
 
include "lang.inc"
include "..\..\..\macros.inc"
 
use32
org 0x0
 
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image
dd 0x80000 ; memory for app
dd 0x80000 ; esp
dd 0x0 , 0x0 ; I_Param , I_Icon
 
 
connect_state db 0,0,'Disconnected'
db 1,3,'Trying.. '
db 4,4,'Connected '
db 5,9,'Closing.. '
 
prev_state dd -1
 
space dd 0x0
 
text_start dd 0x0
 
text_current dd 0x0
 
status dd 0x0
 
server_ip db 192,168,0,96
 
socket dd 0x0
 
xpos dd 0x0
ypos dd 0x0
 
;;
 
group db 'GROUP alt.test',13,10
db ' '
 
grouplen dd 16
 
stat db 'STAT '
 
statlen dd 0x0
 
article db 'ARTICLE',13,10
articlelen:
 
;;
 
quit db 'QUIT',13,10
quitlen:
 
xwait dd 0x0
ywait dd 0x0
 
article_n dd 0x0
article_l dd 0x0
 
article_start dd 0x0
article_last dd 0x0
article_all dd 0x0
 
article_fetch dd 0x0
 
xpost dd 0x0
 
edisave dd 0x0
 
 
connection_status:
 
pusha
 
mov eax,53
mov ebx,6
mov ecx,[socket]
mcall
 
cmp eax,[prev_state]
je no_cos
 
mov [prev_state],eax
 
mov eax,13
mov ebx,435*65536+12*6
mov ecx,42*65536+10
mov edx,0xffffff
mcall
 
mov ecx,-14
mov eax,[prev_state]
 
next_test:
 
add ecx,14
 
cmp ecx,14*4
je no_cos
 
cmp al,[connect_state+ecx+0]
jb next_test
cmp al,[connect_state+ecx+1]
jg next_test
 
mov edx,ecx
add edx,2
add edx,connect_state
 
mov eax,4
mov ebx,435*65536+42
mov ecx,0x000000
mov esi,12
mcall
 
no_cos:
 
popa
 
ret
 
 
 
text_input:
 
pusha
mov ecx,25
mov eax,32
cld
rep stosb
popa
 
mov [edisave],edi
 
ti0:
 
mov [edi],byte ' '
call draw_entries
 
mov eax,10
mcall
 
cmp eax,2
jne no_more_text
 
mov eax,2
mcall
 
cmp ah,8
jne no_bg
cmp edi,[edisave]
je ti0
dec edi
jmp ti0
no_bg:
 
cmp ah,13
je no_more_text
 
mov [edi],ah
inc edi
 
call draw_entries
 
jmp ti0
 
no_more_text:
 
mov [xpost],edi
 
ret
 
 
convert_text_to_ip:
 
pusha
 
mov edi,server_ip
mov esi,text+10
mov eax,0
mov edx,[xpost]
newsip:
cmp [esi],byte '.'
je sipn
cmp esi,edx
jge sipn
movzx ebx,byte [esi]
inc esi
imul eax,10
sub ebx,48
add eax,ebx
jmp newsip
sipn:
mov [edi],al
xor eax,eax
inc esi
cmp esi,text+50
jg sipnn
inc edi
cmp edi,server_ip+3
jbe newsip
sipnn:
 
popa
 
ret
 
 
send_group:
 
mov eax,53
mov ebx,7
mov ecx,[socket]
mov edx,[grouplen]
mov esi,group
mcall
mov [status],3
call clear_text
call save_coordinates
 
ret
 
 
convert_number_to_text:
 
pusha
 
mov eax,[esi]
mov ecx,0
newch:
inc ecx
xor edx,edx
mov ebx,10
div ebx
cmp eax,0
jne newch
 
add edi,ecx
dec edi
mov [article_l],ecx
 
mov eax,[esi]
newdiv:
xor edx,edx
mov ebx,10
div ebx
add edx,48
mov [edi],dl
dec edi
loop newdiv
 
popa
 
ret
 
 
convert_text_to_number:
 
pusha
 
mov edx,0
newdigit:
movzx eax,byte [esi]
cmp eax,'0'
jb cend
cmp eax,'9'
jg cend
imul edx,10
add edx,eax
sub edx,48
inc esi
jmp newdigit
cend:
mov [edi],edx
popa
 
ret
 
 
clear_text:
 
mov [text_start],0
mov [xpos],0
mov [ypos],0
mov [xwait],0
mov [ywait],0
mov edi,nntp_text
mov ecx,0x50000
mov eax,32
cld
rep stosb
ret
 
 
state_machine_write:
 
 
cmp [status],2
jne no_22
call send_group
ret
no_22:
 
cmp [status],4
jne no_4
mov eax,53
mov ebx,7
mov ecx,[socket]
mov edx,[statlen] ; -stat
mov esi,stat
mcall
mov [status],5
call save_coordinates
ret
no_4:
 
cmp [status],6
jne no_6
mov eax,53
mov ebx,7
mov ecx,[socket]
mov edx,articlelen-article
mov esi,article
mcall
mov [status],7
call save_coordinates
ret
no_6:
 
 
ret
 
save_coordinates:
 
mov eax,[xpos]
mov ebx,[ypos]
mov [xwait],eax
mov [ywait],ebx
 
ret
 
 
state_machine_read:
 
cmp [status],1
jne no_1
mov eax,'200 '
call wait_for_string
ret
no_1:
 
cmp [status],3 ;; responce to group
jne no_3
mov eax,'211 '
call wait_for_string
ret
no_3:
 
cmp [status],5 ;; responce to stat
jne no_5
mov eax,'223 '
call wait_for_string
ret
no_5:
 
;; after 'article' request - no wait
 
cmp [status],9
jne no_9
mov eax,'222 '
call wait_for_string
ret
no_9:
 
 
 
ret
 
 
 
wait_for_string:
 
mov ecx,[ywait]
imul ecx,80
add ecx,[xwait]
 
mov ecx,[nntp_text+ecx]
 
cmp eax,ecx
jne no_match
 
cmp [status],3
jne no_stat_ret
 
mov esi,[ywait]
imul esi,80
add esi,[xwait]
 
new32s:
inc esi
movzx eax,byte [esi+nntp_text]
cmp eax,47
jge new32s
new32s2:
inc esi
movzx eax,byte [esi+nntp_text]
cmp eax,47
jge new32s2
inc esi
add esi,nntp_text
; mov [esi-1],byte '.'
 
mov edi,article_n
call convert_text_to_number
mov eax,[article_n]
mov [article_start],eax
 
new32s3:
inc esi
movzx eax,byte [esi]
cmp eax,47
jge new32s3
inc esi
 
mov edi,article_last
call convert_text_to_number
 
mov eax,[text_current]
add [article_n],eax
 
mov esi,article_n
mov edi,nntp_text+71
call convert_number_to_text
 
mov esi,article_n
mov edi,stat+5
call convert_number_to_text
 
mov eax,[article_l]
mov [stat+5+eax],byte 13
mov [stat+6+eax],byte 10
add eax,5+2
mov [statlen],eax
 
pusha
mov edi,text+10+66*2
mov ecx,25
mov eax,32
cld
rep stosb
mov esi,text_current
mov edi,text+10+66*2
call convert_number_to_text
mov eax,32
mov ecx,20
mov edi,text+10+66*3
cld
rep stosb
mov eax,[article_last]
sub eax,[article_start]
mov [article_all],eax
mov esi,article_all
mov edi,text+10+66*3
call convert_number_to_text
call draw_entries
popa
 
call draw_text
 
no_stat_ret:
 
inc [status]
 
mov eax,5
mov ebx,10
mcall
 
call check_for_incoming_data
 
no_match:
 
ret
 
 
 
START: ; start of execution
 
mov eax,40
mov ebx,10000111b
mcall
 
call clear_text
 
call draw_window
 
still:
 
call state_machine_write
call state_machine_read
 
mov eax,23 ; wait here for event
mov ebx,5
mcall
 
cmp eax,1 ; redraw request ?
je red
cmp eax,2 ; key in buffer ?
je key
cmp eax,3 ; button in buffer ?
je button
 
call check_for_incoming_data
 
call connection_status
 
jmp still
 
red: ; redraw
call draw_window
jmp still
 
key: ; key
mov eax,2 ; just read it and ignore
mcall
 
cmp ah,' '
jne no_space
mov eax,[space]
dec eax
add [text_start],eax
call draw_text
jmp still
no_space:
 
cmp ah,177
jne no_plus
inc [text_start]
call draw_text
jmp still
no_plus:
 
cmp ah,178
jne no_minus
cmp [text_start],0
je no_minus
dec [text_start]
call draw_text
jmp still
no_minus:
 
cmp ah,179
jne no_next
inc [text_current]
call send_group
jmp still
no_next:
 
cmp ah,176
jne no_prev
cmp [text_current],0
je still
dec [text_current]
call send_group
jmp still
no_prev:
 
jmp still
 
 
button: ; button
mov eax,17 ; get id
mcall
 
shr eax,8
 
cmp eax,11
jne no_11
mov edi,text+10
call text_input
call convert_text_to_ip
jmp still
no_11:
 
cmp eax,12
jne no_12
mov edi,text+66+10
call text_input
mov esi,text+66+10
mov edi,group+6
mov ecx,[xpost]
sub ecx,text+66+10
mov eax,ecx
cld
rep movsb
mov [group+6+eax],byte 13
mov [group+7+eax],byte 10
add eax,6+2
mov [grouplen],eax
mov [text_current],0
jmp still
no_12:
 
cmp eax,13
jne no_13
mov edi,text+10+66*2
call text_input
mov esi,text+10+66*2
mov edi,text_current
call convert_text_to_number
call send_group
jmp still
no_13:
 
 
cmp eax,14
jne no_start
call clear_text
mov eax,3
mcall
mov ecx,eax
mov eax,53
mov ebx,5
mov edx,119
mov esi,dword [server_ip]
mov edi,1
mcall
mov [socket],eax
mov [status],1
jmp still
no_start:
 
cmp eax,15
jne no_end
mov eax,53
mov ebx,7
mov ecx,[socket]
mov edx,quitlen-quit
mov esi,quit
mcall
mov eax,5
mov ebx,10
mcall
call check_for_incoming_data
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
mov eax,5
mov ebx,5
mcall
mov eax,53
mov ebx,8
mov ecx,[socket]
mcall
mov [status],0
jmp still
no_end:
 
cmp eax,1 ; button id=1 ?
jne noclose
mov eax,-1 ; close this program
mcall
noclose:
 
jmp still
 
 
check_for_incoming_data:
 
cmp [status],0
jne go_on
ret
go_on:
 
mov eax,53
mov ebx,2
mov ecx,[socket]
mcall
 
cmp eax,0
je ch_ret
 
mov eax,53
mov ebx,3
mov ecx,[socket]
mcall
 
and ebx,0xff
 
cmp ebx,13
jb no_print
 
cmp bl,13
jne char
mov [xpos],0
inc [ypos]
jmp no_print
char:
 
cmp ebx,128
jbe char_ok
mov ebx,'?'
char_ok:
 
mov ecx,[ypos]
imul ecx,80
add ecx,[xpos]
mov [nntp_text+ecx],bl
cmp [xpos],78
jg noxinc
inc [xpos]
noxinc:
 
no_print:
 
mov eax,53
mov ebx,2
mov ecx,[socket]
mcall
 
cmp eax,0
jne check_for_incoming_data
 
call draw_text
 
ch_ret:
 
ret
 
 
 
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
 
 
draw_window:
 
pusha
 
mov [prev_state],-1
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
mcall
 
; DRAW WINDOW
mov eax,0 ; function 0 : define and draw window
mov ebx,100*65536+520 ; [x start] *65536 + [x size]
mov ecx,5*65536+470 ; [y start] *65536 + [y size]
mov edx,0x13ffffff ; color of work area RRGGBB,8->color gl
mov edi,title ; WINDOW LABEL
mcall
 
mov eax,38
mov ebx,5*65536+515
mov ecx,101*65536+101
mov edx,0x99bbff
mcall
mov ecx,102*65536+102
mov edx,0x3366aa
mcall
 
 
mov eax,8
mov ebx,238*65536+8
mov ecx,30*65536+8
mov edx,11
mov esi,0x88aadd
mcall
mov ecx,41*65536+8
mov edx,12
mcall
mov ecx,52*65536+8
mov edx,13
mcall
 
mov ebx,265*65536+75
mov ecx,39*65536+13
mov edx,14
mcall
mov ebx,351*65536+75
mov edx,15
mcall
 
call draw_entries
 
call draw_text
 
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,2 ; 2, end of draw
mcall
 
popa
 
ret
 
 
draw_entries:
 
pusha
 
mov eax,13
mov ebx,30*65536+200
mov ecx,30*65536+44
mov edx,0xffffff
mcall
 
mov eax,4
mov ebx,30*65536+31 ; draw info text with function 4
mov ecx,0x000000
mov edx,text
mov esi,66
mov edi,6
newline2:
mcall
add ebx,11
add edx,66
dec edi
jnz newline2
 
popa
 
ret
 
 
draw_text:
 
pusha
 
mov eax,9
mov ebx,0x70000
mov ecx,-1
mcall
 
mov eax,[0x70000+46]
cmp eax,150
jbe dtret
 
sub eax,111
mov ebx,10
xor edx,edx
div ebx
mov edi,eax
dec edi
 
mov [space],edi
mov eax,4
mov ebx,20*65536+111 ; draw info text with function 4
mov ecx,0x000000
mov edx,[text_start]
imul edx,80
add edx,nntp_text
mov esi,80
newline:
pusha
mov ecx,ebx
shl ecx,16
mov eax,13
mov ebx,20*65536+80*6
mov cx,10
mov edx,0xffffff
mcall
popa
 
mcall
add ebx,10
add edx,80
dec edi
jnz newline
 
dtret:
 
popa
 
ret
 
 
; DATA AREA
 
text:
db 'NNTP IP : 192.168.0.96 < '
db 'Group : alt.test < Connect Disconnect '
db 'Article : 0 < '
db 'Art.max : ? '
db ' '
db 'Arrow left/rigth: fetch prev/next - Arrow up/down & space: scroll '
 
textl:
 
 
title db 'NNTP client v',version,0
 
nntp_text:
 
db 'a'
 
I_END: ;;;
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property