/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 > 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 |