/kernel/branches/net/applications/netcfg/netcfg.asm |
---|
38,8 → 38,8 |
jne @f |
mcall -1 ; close this program |
@@: |
cmp eax,0x0000fe00 |
jg @f |
cmp eax,0x0000ff00 |
jg load_drv |
cmp ah, 4 |
je hook |
51,19 → 51,11 |
je unload |
jmp still |
@@: |
shr eax, 16 |
mov word [selected], ax |
call load_drv |
call draw_window |
jmp still |
load_drv: |
; mov ax , [selected] |
test ax , ax |
jz still |
shr eax, 16 |
mov word [selected], ax |
mov bl , 6 ; get a dword |
mov bh , ah ; bus |
81,8 → 73,16 |
mov [IOCTL.handle], eax |
ret |
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 |
101,26 → 101,24 |
mov byte[drivernumber], al |
jmp still |
reset: |
movzx ebx, byte[drivernumber] |
mcall 73,,2 |
ret |
jmp still |
unload: |
movzx ebx, byte[drivernumber] |
mcall 73,,3 |
ret |
jmp still |
draw_window: |
mcall 12, 1 ; start of draw |
mcall 0, dword [Form], dword [Form + 4], 0x13ffffff, 0x805080d0, title |
; mcall 73, 1, |
; mov ecx, eax |
; mcall 47, 1 shl 18, , 50 shl 16 + 10, 0x00000000 |
call Get_PCI_Info ; get pci version and last bus, scan for and draw each pci device |
cmp edx, 20 shl 16 + 110 |
128,9 → 126,10 |
mcall 4, 20 shl 16 + 100, 1 shl 31 + 0x00000000 , caption |
mov ax , [selected] |
test ax, ax |
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 |
379,8 → 378,8 |
driverfound: |
ret |
include 'VENDORS.INC' |
include 'DRIVERS.INC' |
include 'vendors.inc' |
include 'drivers.inc' |
;------------------------------------------------------------------ |
; DATA AREA |
DATA |
404,6 → 403,7 |
lbl_none db 'none',0 |
;lbl_unknown db 'unknown',0 |
;lbl_ethernet db 'ethernet',0 |
load_error db 'Could not load driver!',0 |
devicename db 'test' |
rb 64 |
/kernel/branches/net/applications/zeroconf/zeroconf.asm |
---|
42,14 → 42,11 |
DEFEND_INTERVAL equ 10 ; seconds (min. wait between defensive ARPs) |
AF_INET4 equ 2 ;;;;; |
IP_PROTO_UDP equ 17 |
include '../proc32.inc' |
include '../macros.inc' |
include '../debug-fdo.inc' |
197,22 → 194,22 |
invoke ini.get_str, path, str_ipconfig, str_ip, inibuf, 16, 0 |
mov edx, inibuf |
call Ip2dword |
mcall 73, 3, edx |
mcall 75, 3, edx |
invoke ini.get_str, path, str_ipconfig, str_gateway, inibuf, 16, 0 |
mov edx, inibuf |
call Ip2dword |
mcall 73, 9, edx |
mcall 75, 9, edx |
invoke ini.get_str, path, str_ipconfig, str_dns, inibuf, 16, 0 |
mov edx, inibuf |
call Ip2dword |
mcall 73, 7, edx |
mcall 75, 7, edx |
invoke ini.get_str, path, str_ipconfig, str_subnet, inibuf, 16, 0 |
mov edx, inibuf |
call Ip2dword |
mcall 73, 5, edx |
mcall 75, 5, edx |
mcall -1 |
478,11 → 475,11 |
call random |
mov ecx,0xfea9 ; IP 169.254.0.0 link local net, see RFC3927 |
mov cx,ax |
mcall 73, 3, ecx ; mask is 255.255.0.0 |
mcall 75, 3, ecx ; mask is 255.255.0.0 |
DEBUGF 1,"Link Local IP assinged: 169.254.%u.%u\n",[generator+2]:1,[generator+3]:1 |
mcall 73, 5, 0xffff |
mcall 73, 9, 0x0 |
mcall 73, 7, 0x0 |
mcall 75, 5, 0xffff |
mcall 75, 9, 0x0 |
mcall 75, 7, 0x0 |
mcall 5, PROBE_WAIT*100 |
559,7 → 556,7 |
libini,'libini.obj' |
import libini, \ |
ini.get_str,'ini.get_str' |
ini.get_str,'ini_get_str' |
include_debug_strings |
575,7 → 572,7 |
sockaddr1: |
dw AF_INET4 |
dw 68 ; local port |
dw 68 shl 8 ; local port |
dd 0 ; local IP |
rb 10 |
584,7 → 581,7 |
sockaddr2: |
dw AF_INET4 |
dw 67 ; destination port |
dw 67 shl 8 ; destination port |
dd -1 ; destination IP |
rb 10 |
/kernel/branches/net/drivers/pcnet32.asm |
---|
0,0 → 1,1637 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; Status: under construction ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;$Revision$ |
format MS COFF |
API_VERSION equ 0x01000100 |
DEBUG equ 1 |
__DEBUG__ equ 1 |
__DEBUG_LEVEL__ equ 1 |
MAX_PCNET equ 4 |
MAX_ETH_FRAME_SIZE equ 1514 |
include 'proc32.inc' |
include 'imports.inc' |
include 'fdo.inc' |
OS_BASE equ 0; |
new_app_base equ 0x60400000 |
PROC_BASE equ OS_BASE+0x0080000 |
public START |
public service_proc |
public version |
struc IOCTL { |
.handle dd ? |
.io_code dd ? |
.input dd ? |
.inp_size dd ? |
.output dd ? |
.out_size dd ? |
} |
virtual at 0 |
IOCTL IOCTL |
end virtual |
struc ETH_DEVICE { |
; pointers to procedures |
.unload dd ? |
.reset dd ? |
.transmit dd ? |
.set_MAC dd ? |
.get_MAC dd ? |
.set_mode dd ? |
.get_mode dd ? |
; status |
.bytes_tx dq ? |
.bytes_rx dq ? |
.packets_tx dd ? |
.packets_rx dd ? |
.mode dd ? ; This dword contains cable status (10mbit/100mbit, full/half duplex, auto negotiation or not,..) |
.name dd ? |
.mac dp ? |
; device specific |
.rx_buffer dd ? |
.tx_buffer dd ? |
.io_addr dd ? |
.irq_line db ? |
.pci_bus db ? |
.pci_dev db ? |
.private: |
.mode_ dw ? |
.tlen_rlen dw ? |
.reserved dw ? |
.filter dq ? |
.rx_ring dd ? |
.tx_ring dd ? |
.cur_rx db ? |
.cur_tx db ? |
.dirty_rx dd ? |
.dirty_tx dd ? |
.tx_full db ? |
.options dd ? |
.full_duplex db ? |
.chip_version dd ? |
.mii db ? |
.ltint db ? |
.dxsuflo db ? |
.fset db ? |
.fdx db ? |
.access_read_csr dd ? |
.access_write_csr dd ? |
.access_read_bcr dd ? |
.access_write_bcr dd ? |
.access_read_rap dd ? |
.access_write_rap dd ? |
.access_reset dd ? |
.size: |
} |
virtual at 0 |
device ETH_DEVICE |
end virtual |
struc buf_head { |
.base dd ? |
.length dw ? |
.status dw ? |
.misc dd ? |
.reserved dd ? |
.size: |
} |
virtual at 0 |
buf_head buf_head |
end virtual |
struc rx_desc_2 { ; Swstyle 2 |
.rbadr dd ? |
.status dd ? |
.rfrtag dd ? |
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ |
; |Address | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 |19-16|15-12|11-0 | |
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ |
; |CRDA+00h| RBADR[31:0] | |
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ |
; |CRDA+04h| OWN | ERR |FRAM |OFLO | CRC |BUFF | STP | ENP | BPE | PAM |LAFM | BAM | RES |1111 |BCNT | |
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ |
; |CRDA+08h| RES | RFRTAG[14:0] |0000 |MCNT | |
; +--------+-----+-----------------------------------------------------------------------+-----+-----+ |
; |CRDA+0Ch| USER SPACE | | | |
; +--------+-----------------------------------------------------------------------------+-----+-----+ |
} |
struc rx_desc_3 { ; Swstyle 3 |
.mcnt dd ? |
.status dd ? |
.rbadr dd ? |
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ |
; |Address | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 |22-16|15-12|11-0 | |
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ |
; |CRDA+00h| RES | RES | RES |0000 |MCNT | |
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ |
; |CRDA+04h| OWN | ERR |FRAM |OFLO | CRC |BUFF | STP | ENP | BPE | RES |1111 |BCNT | |
; +--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ |
; |CRDA+08h| RBADR[31:0] | |
; +--------+-----------------------------------------------------------------------+ |
; |CRDA+0Ch| USER SPACE | |
; +--------+-----------------------------------------------------------------------+ |
} |
virtual at 0 |
rx_desc rx_desc_2 |
end virtual |
; PCI Bus defines |
PCI_HEADER_TYPE equ 0x0e ;8 bit |
PCI_BASE_ADDRESS_0 equ 0x10 ;32 bit |
PCI_BASE_ADDRESS_5 equ 0x24 ;32 bits |
PCI_BASE_ADDRESS_SPACE_IO equ 0x01 |
PCI_VENDOR_ID equ 0x00 ;16 bit |
PCI_BASE_ADDRESS_IO_MASK equ 0xFFFFFFFC |
PCNET_PORT_AUI equ 0x00 |
PCNET_PORT_10BT equ 0x01 |
PCNET_PORT_GPSI equ 0x02 |
PCNET_PORT_MII equ 0x03 |
PCNET_PORT_PORTSEL equ 0x03 |
PCNET_PORT_ASEL equ 0x04 |
PCNET_PORT_100 equ 0x40 |
PCNET_PORT_FD equ 0x80 |
PCNET_DMA_MASK equ 0xffffffff |
PCNET_LOG_TX_BUFFERS equ 1 |
PCNET_LOG_RX_BUFFERS equ 2 |
PCNET_TX_RING_SIZE equ 4 |
PCNET_TX_RING_MOD_MASK equ (PCNET_TX_RING_SIZE-1) |
PCNET_TX_RING_LEN_BITS equ 0 |
PCNET_RX_RING_SIZE equ 4 |
PCNET_RX_RING_MOD_MASK equ (PCNET_RX_RING_SIZE-1) |
PCNET_RX_RING_LEN_BITS equ (PCNET_LOG_RX_BUFFERS shl 4) |
PCNET_PKT_BUF_SZ equ 1544 |
PCNET_PKT_BUF_SZ_NEG equ 0xf9f8 |
PCNET_WIO_RDP equ 0x10 |
PCNET_WIO_RAP equ 0x12 |
PCNET_WIO_RESET equ 0x14 |
PCNET_WIO_BDP equ 0x16 |
PCNET_DWIO_RDP equ 0x10 |
PCNET_DWIO_RAP equ 0x14 |
PCNET_DWIO_RESET equ 0x18 |
PCNET_DWIO_BDP equ 0x1C |
PCNET_TOTAL_SIZE equ 0x20 |
; CSR registers |
PCNET_CSR_CSR equ 0x00 |
PCNET_CSR_IAB0 equ 0x01 |
PCNET_CSR_IAB1 equ 0x02 |
PCNET_CSR_IMR equ 0x03 |
PCNET_CSR_TFEAT equ 0x04 |
PCNET_CSR_EXTCTL1 equ 0x05 |
PCNET_CSR_DTBLLEN equ 0x06 |
PCNET_CSR_EXTCTL2 equ 0x07 |
PCNET_CSR_MAR0 equ 0x08 |
PCNET_CSR_MAR1 equ 0x09 |
PCNET_CSR_MAR2 equ 0x0A |
PCNET_CSR_MAR3 equ 0x0B |
PCNET_CSR_PAR0 equ 0x0C |
PCNET_CSR_PAR1 equ 0x0D |
PCNET_CSR_PAR2 equ 0x0E |
PCNET_CSR_MODE equ 0x0F |
PCNET_CSR_RXADDR0 equ 0x18 |
PCNET_CSR_RXADDR1 equ 0x19 |
PCNET_CSR_TXADDR0 equ 0x1E |
PCNET_CSR_TXADDR1 equ 0x1F |
PCNET_CSR_TXPOLL equ 0x2F |
PCNET_CSR_RXPOLL equ 0x31 |
PCNET_CSR_RXRINGLEN equ 0x4C |
PCNET_CSR_TXRINGLEN equ 0x4E |
PCNET_CSR_DMACTL equ 0x50 |
PCNET_CSR_BUSTIMER equ 0x52 |
PCNET_CSR_MEMERRTIMEO equ 0x64 |
PCNET_CSR_ONNOWMISC equ 0x74 |
PCNET_CSR_ADVFEAT equ 0x7A |
PCNET_CSR_MACCFG equ 0x7D |
PCNET_CSR_CHIPID0 equ 0x58 |
PCNET_CSR_CHIPID1 equ 0x59 |
; Control and Status Register (CSR0) |
PCNET_CSR_INIT equ 1 shl 0 |
PCNET_CSR_START equ 1 shl 1 |
PCNET_CSR_STOP equ 1 shl 2 |
PCNET_CSR_TX equ 1 shl 3 |
PCNET_CSR_TXON equ 1 shl 4 |
PCNET_CSR_RXON equ 1 shl 5 |
PCNET_CSR_INTEN equ 1 shl 6 |
PCNET_CSR_INTR equ 1 shl 7 |
PCNET_CSR_IDONE equ 1 shl 8 |
PCNET_CSR_TINT equ 1 shl 9 |
PCNET_CSR_RINT equ 1 shl 10 |
PCNET_CSR_MERR equ 1 shl 11 |
PCNET_CSR_MISS equ 1 shl 12 |
PCNET_CSR_CERR equ 1 shl 13 |
; Interrupt masks and deferral control (CSR3) |
PCNET_IMR_BSWAP equ 0x0004 |
PCNET_IMR_ENMBA equ 0x0008 ; enable modified backoff alg |
PCNET_IMR_DXMT2PD equ 0x0010 |
PCNET_IMR_LAPPEN equ 0x0020 ; lookahead packet processing enb |
PCNET_IMR_DXSUFLO equ 0x0040 ; disable TX stop on underflow |
PCNET_IMR_IDONE equ 0x0100 |
PCNET_IMR_TINT equ 0x0200 |
PCNET_IMR_RINT equ 0x0400 |
PCNET_IMR_MERR equ 0x0800 |
PCNET_IMR_MISS equ 0x1000 |
PCNET_IMR equ PCNET_IMR_TINT+PCNET_IMR_RINT+PCNET_IMR_IDONE+PCNET_IMR_MERR+PCNET_IMR_MISS |
; Test and features control (CSR4) |
PCNET_TFEAT_TXSTRTMASK equ 0x0004 |
PCNET_TFEAT_TXSTRT equ 0x0008 |
PCNET_TFEAT_RXCCOFLOWM equ 0x0010 ; Rx collision counter oflow |
PCNET_TFEAT_RXCCOFLOW equ 0x0020 |
PCNET_TFEAT_UINT equ 0x0040 |
PCNET_TFEAT_UINTREQ equ 0x0080 |
PCNET_TFEAT_MISSOFLOWM equ 0x0100 |
PCNET_TFEAT_MISSOFLOW equ 0x0200 |
PCNET_TFEAT_STRIP_FCS equ 0x0400 |
PCNET_TFEAT_PAD_TX equ 0x0800 |
PCNET_TFEAT_TXDPOLL equ 0x1000 |
PCNET_TFEAT_DMAPLUS equ 0x4000 |
; Extended control and interrupt 1 (CSR5) |
PCNET_EXTCTL1_SPND equ 0x0001 ; suspend |
PCNET_EXTCTL1_MPMODE equ 0x0002 ; magic packet mode |
PCNET_EXTCTL1_MPENB equ 0x0004 ; magic packet enable |
PCNET_EXTCTL1_MPINTEN equ 0x0008 ; magic packet interrupt enable |
PCNET_EXTCTL1_MPINT equ 0x0010 ; magic packet interrupt |
PCNET_EXTCTL1_MPPLBA equ 0x0020 ; magic packet phys. logical bcast |
PCNET_EXTCTL1_EXDEFEN equ 0x0040 ; excessive deferral interrupt enb. |
PCNET_EXTCTL1_EXDEF equ 0x0080 ; excessive deferral interrupt |
PCNET_EXTCTL1_SINTEN equ 0x0400 ; system interrupt enable |
PCNET_EXTCTL1_SINT equ 0x0800 ; system interrupt |
PCNET_EXTCTL1_LTINTEN equ 0x4000 ; last TX interrupt enb |
PCNET_EXTCTL1_TXOKINTD equ 0x8000 ; TX OK interrupt disable |
; RX/TX descriptor len (CSR6) |
PCNET_DTBLLEN_RLEN equ 0x0F00 |
PCNET_DTBLLEN_TLEN equ 0xF000 |
; Extended control and interrupt 2 (CSR7) |
PCNET_EXTCTL2_MIIPDTINTE equ 0x0001 |
PCNET_EXTCTL2_MIIPDTINT equ 0x0002 |
PCNET_EXTCTL2_MCCIINTE equ 0x0004 |
PCNET_EXTCTL2_MCCIINT equ 0x0008 |
PCNET_EXTCTL2_MCCINTE equ 0x0010 |
PCNET_EXTCTL2_MCCINT equ 0x0020 |
PCNET_EXTCTL2_MAPINTE equ 0x0040 |
PCNET_EXTCTL2_MAPINT equ 0x0080 |
PCNET_EXTCTL2_MREINTE equ 0x0100 |
PCNET_EXTCTL2_MREINT equ 0x0200 |
PCNET_EXTCTL2_STINTE equ 0x0400 |
PCNET_EXTCTL2_STINT equ 0x0800 |
PCNET_EXTCTL2_RXDPOLL equ 0x1000 |
PCNET_EXTCTL2_RDMD equ 0x2000 |
PCNET_EXTCTL2_RXFRTG equ 0x4000 |
PCNET_EXTCTL2_FASTSPNDE equ 0x8000 |
; Mode (CSR15) |
PCNET_MODE_RXD equ 0x0001 ; RX disable |
PCNET_MODE_TXD equ 0x0002 ; TX disable |
PCNET_MODE_LOOP equ 0x0004 ; loopback enable |
PCNET_MODE_TXCRCD equ 0x0008 |
PCNET_MODE_FORCECOLL equ 0x0010 |
PCNET_MODE_RETRYD equ 0x0020 |
PCNET_MODE_INTLOOP equ 0x0040 |
PCNET_MODE_PORTSEL equ 0x0180 |
PCNET_MODE_RXVPAD equ 0x2000 |
PCNET_MODE_RXNOBROAD equ 0x4000 |
PCNET_MODE_PROMISC equ 0x8000 |
; BCR (Bus Control Registers) |
PCNET_BCR_MMRA equ 0x00 ; Master Mode Read Active |
PCNET_BCR_MMW equ 0x01 ; Master Mode Write Active |
PCNET_BCR_MISCCFG equ 0x02 |
PCNET_BCR_LED0 equ 0x04 |
PCNET_BCR_LED1 equ 0x05 |
PCNET_BCR_LED2 equ 0x06 |
PCNET_BCR_LED3 equ 0x07 |
PCNET_BCR_DUPLEX equ 0x09 |
PCNET_BCR_BUSCTL equ 0x12 |
PCNET_BCR_EECTL equ 0x13 |
PCNET_BCR_SSTYLE equ 0x14 |
PCNET_BCR_PCILAT equ 0x16 |
PCNET_BCR_PCISUBVENID equ 0x17 |
PCNET_BCR_PCISUBSYSID equ 0x18 |
PCNET_BCR_SRAMSIZE equ 0x19 |
PCNET_BCR_SRAMBOUND equ 0x1A |
PCNET_BCR_SRAMCTL equ 0x1B |
PCNET_BCR_MIICTL equ 0x20 |
PCNET_BCR_MIIADDR equ 0x21 |
PCNET_BCR_MIIDATA equ 0x22 |
PCNET_BCR_PCIVENID equ 0x23 |
PCNET_BCR_PCIPCAP equ 0x24 |
PCNET_BCR_DATA0 equ 0x25 |
PCNET_BCR_DATA1 equ 0x26 |
PCNET_BCR_DATA2 equ 0x27 |
PCNET_BCR_DATA3 equ 0x28 |
PCNET_BCR_DATA4 equ 0x29 |
PCNET_BCR_DATA5 equ 0x2A |
PCNET_BCR_DATA6 equ 0x2B |
PCNET_BCR_DATA7 equ 0x2C |
PCNET_BCR_ONNOWPAT0 equ 0x2D |
PCNET_BCR_ONNOWPAT1 equ 0x2E |
PCNET_BCR_ONNOWPAT2 equ 0x2F |
PCNET_BCR_PHYSEL equ 0x31 |
; RX status register |
PCNET_RXSTAT_BPE equ 0x0080 ; bus parity error |
PCNET_RXSTAT_ENP equ 0x0100 ; end of packet |
PCNET_RXSTAT_STP equ 0x0200 ; start of packet |
PCNET_RXSTAT_BUFF equ 0x0400 ; buffer error |
PCNET_RXSTAT_CRC equ 0x0800 ; CRC error |
PCNET_RXSTAT_OFLOW equ 0x1000 ; rx overrun |
PCNET_RXSTAT_FRAM equ 0x2000 ; framing error |
PCNET_RXSTAT_ERR equ 0x4000 ; error summary |
PCNET_RXSTAT_OWN equ 0x8000 |
; TX status register |
PCNET_TXSTAT_TRC equ 0x0000000F ; transmit retries |
PCNET_TXSTAT_RTRY equ 0x04000000 ; retry |
PCNET_TXSTAT_LCAR equ 0x08000000 ; lost carrier |
PCNET_TXSTAT_LCOL equ 0x10000000 ; late collision |
PCNET_TXSTAT_EXDEF equ 0x20000000 ; excessive deferrals |
PCNET_TXSTAT_UFLOW equ 0x40000000 ; transmit underrun |
PCNET_TXSTAT_BUFF equ 0x80000000 ; buffer error |
PCNET_TXCTL_OWN equ 0x80000000 |
PCNET_TXCTL_ERR equ 0x40000000 ; error summary |
PCNET_TXCTL_ADD_FCS equ 0x20000000 ; add FCS to pkt |
PCNET_TXCTL_MORE_LTINT equ 0x10000000 |
PCNET_TXCTL_ONE equ 0x08000000 |
PCNET_TXCTL_DEF equ 0x04000000 |
PCNET_TXCTL_STP equ 0x02000000 |
PCNET_TXCTL_ENP equ 0x01000000 |
PCNET_TXCTL_BPE equ 0x00800000 |
PCNET_TXCTL_MBO equ 0x0000F000 |
PCNET_TXCTL_BUFSZ equ 0x00000FFF |
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 PCnet driver\n" |
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, [ebx+IOCTL.io_code] |
;------------------------------------------------------ |
cmp eax, 0 ;SRV_GETVERSION |
jne @F |
cmp [edx+IOCTL.out_size], 4 |
jl .fail |
mov eax, [edx+IOCTL.output] |
mov [eax], dword API_VERSION |
xor eax, eax |
ret |
;------------------------------------------------------ |
@@: |
cmp eax, 1 ;SRV_HOOK |
jne .fail |
mov eax, [esp] |
cmp [edx + IOCTL.inp_size], 3 ; Data input must be at least 3 bytes |
jl .fail |
mov eax, [edx + 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, PCNET_LIST |
mov ecx, [PCNET_DEV] |
test ecx, ecx |
jz .firstdevice |
mov eax, [edx+IOCTL.input] ; get the pci bus and device numbers |
mov bx , [eax+1] ; |
.nextdevice: |
lodsd |
cmp bx , word [eax + device.pci_bus] ; compare with pci and device num in RTL8139 list (notice the usage of word instead of byte) |
je .find_devicenum ; Device is already loaded, let's find it's device number |
loop .nextdevice |
; This device doesnt have its own eth_device structure yet, lets create one |
.firstdevice: |
cmp [PCNET_DEV], MAX_PCNET ; First check if the driver can handle one more card |
jge .fail |
push edx |
stdcall KernelAlloc, 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 dword [ebx+device.reset], reset |
mov dword [ebx+device.transmit], transmit |
mov dword [ebx+device.get_MAC], read_mac |
mov dword [ebx+device.set_MAC], write_mac |
mov dword [ebx+device.unload], unload |
mov dword [ebx+device.name], my_service |
; save the pci bus and device numbers |
mov eax, [edx+IOCTL.input] |
mov cl , [eax+1] |
mov [ebx+device.pci_bus], cl |
mov cl , [eax+2] |
mov [ebx+device.pci_dev], cl |
; 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 |
mov edx, PCI_BASE_ADDRESS_0 |
.reg_check: |
movzx eax, byte [ebx+device.pci_bus] |
movzx ecx, byte [ebx+device.pci_dev] |
push edx ecx |
stdcall PciRead16, eax ,ecx ,edx |
pop ecx edx |
mov [ebx+device.io_addr], eax |
and eax, PCI_BASE_ADDRESS_IO_MASK |
test eax, eax |
jz .inc_reg |
mov eax, [ebx+device.io_addr] |
and eax, PCI_BASE_ADDRESS_SPACE_IO |
test eax, eax |
jz .inc_reg |
mov eax, [ebx+device.io_addr] |
and eax, PCI_BASE_ADDRESS_IO_MASK |
mov [ebx+device.io_addr], eax |
jmp .got_io |
.inc_reg: |
add edx, 4 |
cmp edx, PCI_BASE_ADDRESS_5 |
jbe .reg_check |
.got_io: |
; We've found the io address, find IRQ now |
movzx eax, byte [ebx+device.pci_bus] |
movzx ecx, byte [ebx+device.pci_dev] |
push ebx |
stdcall PciRead8, eax ,ecx ,0x3c ; 0x3c is the offset where irq can be found |
pop ebx |
mov byte [ebx+device.irq_line], al |
DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\ |
[ebx+device.pci_dev]:1,[ebx+device.pci_bus]:1,[ebx+device.irq_line]:1,[ebx+device.io_addr]:4 |
; Allocate the Receive buffer |
stdcall KernelAlloc, PCNET_RX_RING_SIZE * PCNET_PKT_BUF_SZ |
test eax, eax |
jz .err |
mov [ebx+device.rx_buffer], eax ; Save the address to it into the device struct |
; Allocate the Transmit Buffer |
stdcall KernelAlloc, PCNET_TX_RING_SIZE * PCNET_PKT_BUF_SZ |
test eax, eax |
jz .err |
mov [ebx+device.tx_buffer], eax |
; Allocate the RX Ring |
stdcall KernelAlloc, PCNET_RX_RING_SIZE * buf_head.size |
test eax, eax |
jz .err |
mov dword [ebx + device.rx_ring], eax |
; Allocate the TX ring |
stdcall KernelAlloc, PCNET_TX_RING_SIZE * buf_head.size |
test eax, eax |
jz .err |
mov dword [ebx + device.tx_ring], eax |
; fill in some of the structure variables |
call switch_to_wio |
mov edi, [ebx + device.rx_ring] |
mov ecx, PCNET_RX_RING_SIZE |
mov eax, [ebx + device.rx_buffer] |
call GetPgAddr |
.rx_init: |
mov [edi + buf_head.base], eax |
mov [edi + buf_head.length], PCNET_PKT_BUF_SZ_NEG |
mov [edi + buf_head.status], 0x8000 |
add eax, PCNET_PKT_BUF_SZ |
; inc eax |
add edi, buf_head.size |
loop .rx_init |
mov edi, [ebx + device.tx_ring] |
mov ecx, PCNET_TX_RING_SIZE |
.tx_init: |
mov [edi + buf_head.base], 0 |
mov [edi + buf_head.status], 0 |
add edi, buf_head.size |
loop .tx_init |
mov [ebx + device.tlen_rlen],(PCNET_TX_RING_LEN_BITS or PCNET_RX_RING_LEN_BITS) |
; 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, [PCNET_DEV] ; Add the device structure to our device list |
mov [PCNET_LIST+4*eax], ebx ; (IRQ handler uses this list to find device) |
inc [PCNET_DEV] ; |
call EthRegDev |
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" |
mov ebx, eax |
call EthStruc2Dev ; 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: |
DEBUGF 1,"Error, removing all data !\n" |
stdcall KernelFree, dword [ebx+device.rx_buffer] |
stdcall KernelFree, dword [ebx+device.tx_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 a PCnet device) |
;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
probe: |
mov edx, [ebx + 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, PCNET_WIO_RAP |
out dx , ax |
nop |
nop |
in ax , dx |
sub edx, PCNET_WIO_RAP |
cmp ax , 88 |
jne .try_dwio |
DEBUGF 1,"Using WIO\n" |
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, PCNET_DWIO_RAP |
mov eax, 88 |
out dx , eax |
nop |
nop |
in eax, dx |
sub edx, PCNET_DWIO_RAP |
and eax, 0xffff |
cmp eax, 88 |
jne .no_dev |
DEBUGF 1,"Using DWIO\n" |
call switch_to_dwio |
jmp .L1 |
.no_dev: |
DEBUGF 1,"PCnet device not found!\n" |
mov eax, 1 |
ret |
.L1: |
; TODO: remember to use WORD or DWORD operations |
;;; stdcall Sleep, 10 |
;--------------------------------------------- |
; Switch to dword operations |
; DEBUGF 1,"Switching to 32\n" |
; |
; mov ecx, PCNET_DWIO_RDP |
; mov eax, 0 |
; call wio_write_csr |
;--------------------------------------------- |
mov ecx, PCNET_CSR_CHIPID0 |
call [ebx + device.access_read_csr] |
mov esi, eax |
mov ecx, PCNET_CSR_CHIPID1 |
call [ebx + device.access_read_csr] |
shl eax, 16 |
or eax, esi |
mov ecx, eax |
and ecx, 0xfff |
cmp ecx, 3 |
jne .no_dev |
shr eax, 12 |
and eax, 0xffff |
mov [ebx + device.chip_version], eax |
DEBUGF 1,"chip version ok\n" |
mov [ebx + device.fdx], 0 |
mov [ebx + device.mii], 0 |
mov [ebx + device.fset], 0 |
mov [ebx + device.dxsuflo], 0 |
mov [ebx + device.ltint], 0 |
cmp eax, 0x2420 |
je .L2 |
cmp eax, 0x2430 |
je .L2 |
mov [ebx + device.fdx], 1 |
cmp eax, 0x2621 |
je .L4 |
cmp eax, 0x2623 |
je .L5 |
cmp eax, 0x2624 |
je .L6 |
cmp eax, 0x2625 |
je .L7 |
cmp eax, 0x2626 |
je .L8 |
cmp eax, 0x2627 |
je .L9 |
DEBUGF 1,"Invalid chip rev\n" |
jmp .no_dev |
.L2: |
mov [ebx + device.name], device_l2 |
jmp .L10 |
.L4: |
mov [ebx + device.name], device_l4 |
; mov [ebx + device.fdx], 1 |
jmp .L10 |
.L5: |
mov [ebx + device.name], device_l5 |
; mov [ebx + device.fdx], 1 |
mov [ebx + device.mii], 1 |
mov [ebx + device.fset], 1 |
mov [ebx + device.ltint], 1 |
jmp .L10 |
.L6: |
mov [ebx + device.name], device_l6 |
; mov [ebx + device.fdx], 1 |
mov [ebx + device.mii], 1 |
mov [ebx + device.fset], 1 |
jmp .L10 |
.L7: |
mov [ebx + device.name], device_l7 |
; mov [ebx + device.fdx], 1 |
mov [ebx + device.mii], 1 |
jmp .L10 |
.L8: |
mov [ebx + device.name], device_l8 |
; mov [ebx + device.fdx], 1 |
mov ecx, PCNET_CSR_RXPOLL |
call dword [ebx + device.access_read_bcr] |
call dword [ebx + device.access_write_bcr] |
jmp .L10 |
.L9: |
mov [ebx + device.name], device_l9 |
; mov [ebx + device.fdx], 1 |
mov [ebx + device.mii], 1 |
.L10: |
DEBUGF 1,"device name: %s\n",[ebx + device.name] |
cmp [ebx + device.fset], 1 |
jne .L11 |
mov ecx, PCNET_BCR_BUSCTL |
call [ebx + device.access_read_bcr] |
or eax, 0x800 |
call [ebx + device.access_write_bcr] |
mov ecx, PCNET_CSR_DMACTL |
call [ebx + device.access_read_csr] |
; and eax, 0xc00 |
; or eax, 0xc00 |
mov eax, 0xc00 |
call [ebx + device.access_write_csr] |
mov [ebx + device.dxsuflo],1 |
mov [ebx + device.ltint],1 |
.L11: |
push ebx |
call adjust_pci_device |
pop ebx |
DEBUGF 1,"PCI done\n" |
mov eax, PCNET_PORT_ASEL |
mov [ebx + device.options], eax |
mov [ebx + device.mode_], word 0x0003 |
mov [ebx + device.tlen_rlen], word (PCNET_TX_RING_LEN_BITS or PCNET_RX_RING_LEN_BITS) |
mov dword [ebx + device.filter], 0 |
mov dword [ebx + device.filter+4], 0 |
mov eax, PCNET_IMR |
mov ecx, PCNET_CSR_IMR ; Write interrupt mask |
call [ebx + device.access_write_csr] |
if 0 |
mov ecx, PCNET_BCR_SSTYLE ; Select Software style 2 TODO: freebsd driver uses style 3, why? |
mov eax, 2 |
call [ebx + device.access_write_bcr] |
; ------------ really nescessary??? ---------------- |
lea eax, [ebx + device.private] |
mov ecx, eax |
and ecx, 0xFFF ; KolibriOS PAGE SIZE |
call GetPgAddr |
add eax, ecx |
and eax, 0xffff |
mov ecx, PCNET_CSR_IAB0 |
call [ebx + device.access_write_csr] |
lea eax, [ebx + device.private] |
mov ecx, eax |
and ecx, 0xFFF ; KolibriOS PAGE SIZE |
call GetPgAddr |
add eax, ecx |
shr eax,16 |
mov ecx, PCNET_CSR_IAB1 |
call [ebx + device.access_write_csr] |
mov ecx, PCNET_CSR_CSR |
mov eax, 1 |
call [ebx + device.access_write_csr] |
; ------------------------------------------------ |
end if |
stdcall Sleep, 1 |
reset: |
; attach int handler |
movzx eax, [ebx+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, [ebx + device.io_addr] |
call [ebx + device.access_reset] |
; Switch pcnet32 to 32bit mode |
mov ecx, PCNET_BCR_SSTYLE |
mov eax, 2 |
call [ebx + device.access_write_bcr] |
; set/reset autoselect bit |
mov ecx, PCNET_BCR_MISCCFG |
call [ebx + device.access_read_bcr] |
and eax,not 2 |
test [ebx + device.options], PCNET_PORT_ASEL |
jz .L1 |
or eax, 2 |
.L1: |
call [ebx + device.access_write_bcr] |
; Handle full duplex setting |
cmp byte [ebx + device.full_duplex], 0 |
je .L2 |
mov ecx, PCNET_BCR_DUPLEX |
call [ebx + device.access_read_bcr] |
and eax, not 3 |
test [ebx + device.options], PCNET_PORT_FD |
jz .L3 |
or eax, 1 |
cmp [ebx + device.options], PCNET_PORT_FD or PCNET_PORT_AUI |
jne .L4 |
or eax, 2 |
jmp .L4 |
.L3: |
test [ebx + device.options], PCNET_PORT_ASEL |
jz .L4 |
cmp [ebx + device.chip_version], 0x2627 |
jne .L4 |
or eax, 3 |
.L4: |
mov ecx, PCNET_BCR_DUPLEX |
call [ebx + device.access_write_bcr] |
.L2: |
; set/reset GPSI bit in test register |
mov ecx, 124 |
call [ebx + device.access_read_csr] |
mov ecx, [ebx + device.options] |
and ecx, PCNET_PORT_PORTSEL |
cmp ecx, PCNET_PORT_GPSI |
jne .L5 |
or eax, 0x10 |
.L5: |
call [ebx + device.access_write_csr] |
cmp [ebx + device.mii], 0 |
je .L6 |
test [ebx + device.options], PCNET_PORT_ASEL |
jnz .L6 |
mov ecx, PCNET_BCR_MIICTL |
call [ebx + device.access_read_bcr] |
and eax,not 0x38 |
test [ebx + device.options], PCNET_PORT_FD |
jz .L7 |
or eax, 0x10 |
.L7: |
test [ebx + device.options], PCNET_PORT_100 |
jz .L8 |
or eax, 0x08 |
.L8: |
call [ebx + device.access_write_bcr] |
jmp .L9 |
.L6: |
test [ebx + device.options], PCNET_PORT_ASEL |
jz .L9 |
mov ecx, PCNET_BCR_MIICTL |
DEBUGF 1,"ASEL, enable auto-negotiation\n" |
call [ebx + device.access_read_bcr] |
and eax, not 0x98 |
or eax, 0x20 |
call [ebx + device.access_write_bcr] |
.L9: |
cmp [ebx + device.ltint],0 |
je .L10 |
mov ecx,5 |
call [ebx + device.access_read_csr] |
or eax,(1 shl 14) |
call [ebx + device.access_write_csr] |
.L10: |
mov eax,[ebx + device.options] |
and eax,PCNET_PORT_PORTSEL |
shl eax,7 |
mov [ebx + device.mode_],ax |
mov dword [ebx + device.filter], -1 |
mov dword [ebx + device.filter+4], -1 |
lea eax, [ebx + device.private] |
mov ecx, eax |
and ecx, 0xFFF ; KolibriOS PAGE SIZE |
call GetPgAddr |
add eax, ecx |
push eax |
and eax, 0xffff |
mov ecx, 1 |
call [ebx + device.access_write_csr] |
pop eax |
shr eax,16 |
mov ecx,2 |
call [ebx + device.access_write_csr] |
mov ecx,4 |
mov eax,0x0915 |
call [ebx + device.access_write_csr] |
mov ecx,0 |
mov eax,1 |
call [ebx + device.access_write_csr] |
mov [ebx + device.tx_full],0 |
mov [ebx + device.cur_rx],0 |
mov [ebx + device.cur_tx],0 |
mov [ebx + device.dirty_rx],0 |
mov [ebx + device.dirty_tx],0 |
mov ecx,100 |
.L11: |
push ecx |
xor ecx,ecx |
call [ebx + device.access_read_csr] |
pop ecx |
test ax,0x100 |
jnz .L12 |
loop .L11 |
.L12: |
DEBUGF 1,"hardware reset\n" |
xor ecx, ecx |
mov eax, 0x0002 |
call [ebx + device.access_write_csr] |
xor ecx, ecx |
call [ebx + device.access_read_csr] |
call read_mac |
xor ecx, ecx |
mov eax, PCNET_CSR_INTEN or PCNET_CSR_START |
call [ebx + device.access_write_csr] |
DEBUGF 1,"PCNET reset complete\n" |
xor eax, eax |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Transmit ;; |
;; ;; |
;; In: buffer pointer in [esp] ;; |
;; size of buffer in [esp+4] ;; |
;; pointer to device structure in ebx ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
transmit: |
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp],[esp+4] |
mov eax, [esp] |
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+4], 1514 |
jg .finish ; packet is too long |
cmp dword [esp+4], 60 |
jl .finish ; packet is too short |
; check descriptor |
DEBUGF 1,"Checking descriptor, " |
movzx eax, [ebx + device.cur_tx] |
mov edx, buf_head.size ;;PCNET_PKT_BUF_SZ |
mul dx |
mov edi, [ebx + device.tx_buffer] |
add edi, eax |
mov edx, [ebx + device.io_addr] |
mov ecx, [esp+4] |
neg cx ;;;; |
mov [edi + buf_head.length], cx |
mov [edi + buf_head.misc], 0 |
mov eax, [esp] |
mov ecx, eax |
and ecx, 0xfff |
call GetPgAddr |
add eax, ecx |
mov [edi + buf_head.base], eax |
mov [edi + buf_head.status], 0x8300 |
; trigger an immediate send |
mov ecx, 0 ; CSR0 |
call [ebx + device.access_read_csr] |
or eax, PCNET_CSR_TX |
call [ebx + device.access_write_csr] |
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ... |
inc [ebx + device.cur_tx] |
and [ebx + device.cur_tx], 3 |
DEBUGF 2," - Packet Sent! " |
.finish: |
DEBUGF 2," - Done!\n" |
;;; call KernelFree |
add esp, 4+4 ; pop (balance stack) |
ret |
;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Interrupt handler ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
int_handler: |
DEBUGF 1,"IRQ %x ",eax:2 ; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO |
; find pointer of device wich made IRQ occur |
mov esi, PCNET_LIST |
mov ecx, [PCNET_DEV] |
test ecx, ecx |
jz .abort |
.nextdevice: |
mov ebx, dword [esi] |
mov edx, [ebx + device.io_addr] ; get IRQ reason |
push ecx |
mov ecx, 0 ; CSR0 |
call [ebx + device.access_read_csr] |
pop ecx |
test ax , ax |
jnz .got_it |
add esi, 4 |
loop .nextdevice |
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver |
.got_it: |
;------------------------------------------------------- |
; Received packet ok? |
test ax, PCNET_CSR_RINT |
jz @f |
movzx eax, [ebx + device.cur_rx] |
; and eax, PCNET_RX_RING_MOD_MASK |
mov edi, eax |
imul esi, eax, PCNET_PKT_BUF_SZ ; |
add esi, [ebx + device.rx_buffer] ; esi now points to rx buffer |
shl edi, 4 ; desc * 16 (16 is size of one ring entry) |
add edi, [ebx + device.rx_ring] ; edi now points to current rx ring entry |
mov cx , [edi + buf_head.status] |
test cx , PCNET_RXSTAT_OWN ; If this bit is set, the controller OWN's the packet, if not, we do |
jnz .abort |
cmp cx , PCNET_RXSTAT_ENP |
jz .abort |
cmp cx , PCNET_RXSTAT_STP |
jz .abort |
movzx ecx, [ebx + buf_head.length] ; get packet length in ecx |
and ecx, 0xfff ; |
sub ecx, 4 ; |
stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into |
test eax, eax ; Test if we allocated succesfully |
jz .abort ; |
push ecx ; for eth_receiver |
push eax ; |
xchg edi, eax |
push ecx |
shr ecx, 2 |
cld |
rep movsd |
pop ecx |
and ecx, 3 |
rep movsb |
mov word [eax + buf_head.length], PCNET_PKT_BUF_SZ_NEG |
or word [eax + buf_head.status], PCNET_RXSTAT_OWN ; Set OWN bit back to 1 (controller may write to tx-buffer again now) |
inc [ebx + device.cur_rx] ; update descriptor |
and [ebx + device.cur_rx], 3 ; |
jmp EthReceiver ; Send the copied packet to kernel |
.abort: |
@@: |
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, [ebx + device.io_addr] |
add dx, 2 |
xor eax, eax |
mov ecx, PCNET_CSR_PAR0 |
@@: |
pop ax |
call [ebx + device.access_write_csr] |
DEBUGF 1,"." |
inc ecx |
cmp ecx, PCNET_CSR_PAR2 |
jl @r |
DEBUGF 1,"\n" |
; Notice this procedure does not ret, but continues to read_mac instead. |
;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Read MAC address ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;; |
read_mac: ; T- OK |
DEBUGF 1,"Reading MAC" |
mov edx, [ebx + device.io_addr] |
add dx, 6 |
@@: |
dec dx |
dec dx |
in ax, dx |
push ax |
DEBUGF 1,"." |
cmp edx, [ebx + device.io_addr] |
jg @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, [ebx + device.mac] |
pop ax |
stosw |
pop ax |
stosw |
pop ax |
stosw |
ret |
switch_to_wio: |
mov [ebx + device.access_read_csr], wio_read_csr |
mov [ebx + device.access_write_csr], wio_write_csr |
mov [ebx + device.access_read_bcr], wio_read_bcr |
mov [ebx + device.access_write_bcr], wio_write_bcr |
mov [ebx + device.access_read_rap], wio_read_rap |
mov [ebx + device.access_write_rap], wio_write_rap |
mov [ebx + device.access_reset], wio_reset |
ret |
switch_to_dwio: |
mov [ebx + device.access_read_csr], dwio_read_csr |
mov [ebx + device.access_write_csr], dwio_write_csr |
mov [ebx + device.access_read_bcr], dwio_read_bcr |
mov [ebx + device.access_write_bcr], dwio_write_bcr |
mov [ebx + device.access_read_rap], dwio_read_rap |
mov [ebx + device.access_write_rap], dwio_write_rap |
mov [ebx + device.access_reset], dwio_reset |
ret |
; ecx - index |
; return: |
; eax - data |
wio_read_csr: |
add edx, PCNET_WIO_RAP |
mov ax , cx |
out dx , ax |
add edx, PCNET_WIO_RDP - PCNET_WIO_RAP |
in ax , dx |
and eax, 0xffff |
sub edx, PCNET_WIO_RDP |
ret |
; eax - data |
; ecx - index |
wio_write_csr: |
add edx, PCNET_WIO_RAP |
xchg eax, ecx |
out dx , ax |
xchg eax, ecx |
add edx, PCNET_WIO_RDP - PCNET_WIO_RAP |
out dx , ax |
sub edx, PCNET_WIO_RDP |
ret |
; ecx - index |
; return: |
; eax - data |
wio_read_bcr: |
add edx, PCNET_WIO_RAP |
mov ax , cx |
out dx , ax |
add edx, PCNET_WIO_BDP - PCNET_WIO_RAP |
in ax , dx |
and eax, 0xffff |
sub edx, PCNET_WIO_BDP |
ret |
; eax - data |
; ecx - index |
wio_write_bcr: |
add edx, PCNET_WIO_RAP |
xchg eax, ecx |
out dx , ax |
xchg eax, ecx |
add edx, PCNET_WIO_BDP - PCNET_WIO_RAP |
out dx , ax |
sub edx, PCNET_WIO_BDP |
ret |
wio_read_rap: |
add edx, PCNET_WIO_RAP |
in ax , dx |
and eax, 0xffff |
sub edx, PCNET_WIO_RAP |
ret |
; eax - val |
wio_write_rap: |
add edx, PCNET_WIO_RAP |
out dx , ax |
sub edx, PCNET_WIO_RAP |
ret |
wio_reset: |
push eax |
add edx, PCNET_WIO_RESET |
in ax , dx |
pop eax |
sub edx, PCNET_WIO_RESET |
ret |
; ecx - index |
; return: |
; eax - data |
dwio_read_csr: |
add edx, PCNET_DWIO_RAP |
mov ecx, eax |
out dx , eax |
add edx, PCNET_DWIO_RDP - PCNET_DWIO_RAP |
in eax, dx |
and eax, 0xffff |
sub edx, PCNET_DWIO_RDP |
ret |
; ecx - index |
; eax - data |
dwio_write_csr: |
add edx, PCNET_DWIO_RAP |
xchg eax, ecx |
out dx , eax |
add edx, PCNET_DWIO_RDP - PCNET_DWIO_RAP |
xchg eax, ecx |
out dx , eax |
sub edx, PCNET_DWIO_RDP |
ret |
; ecx - index |
; return: |
; eax - data |
dwio_read_bcr: |
add edx, PCNET_DWIO_RAP |
mov ecx, eax |
out dx , eax |
add edx, PCNET_DWIO_BDP - PCNET_DWIO_RAP |
in eax, dx |
and eax, 0xffff |
sub edx, PCNET_DWIO_BDP |
ret |
; ecx - index |
; eax - data |
dwio_write_bcr: |
add edx, PCNET_DWIO_RAP |
xchg eax, ecx |
out dx , eax |
add edx, PCNET_DWIO_BDP - PCNET_DWIO_RAP |
xchg eax, ecx |
out dx , eax |
sub edx, PCNET_DWIO_BDP |
ret |
dwio_read_rap: |
add edx, PCNET_DWIO_RAP |
in eax, dx |
and eax, 0xffff |
sub edx, PCNET_DWIO_RAP |
ret |
; eax - val |
dwio_write_rap: |
add edx, PCNET_DWIO_RAP |
out dx , eax |
sub edx, PCNET_DWIO_RAP |
ret |
dwio_reset: |
push eax |
add edx, PCNET_DWIO_RESET |
in eax, dx |
pop eax |
sub edx, PCNET_DWIO_RESET |
ret |
adjust_pci_device: |
;*******Get current setting************************ |
movzx edx, byte [ebx + device.pci_dev] |
movzx ecx, byte [ebx + device.pci_bus] |
stdcall PciRead16, edx ,ecx ,0x04 |
; ;******see if its already set as bus master******** |
; and ax,5 |
; cmp ax,5 |
; je .Latency |
;******Make card a bus master******* |
or ax , 5 |
stdcall PciWrite16, edx ,ecx ,0x04, eax |
;******Check latency setting*********** |
.Latency: |
;*******Get current latency setting************************ |
; mov al, 1 ;read a byte |
; mov bh, [pci_dev] |
; mov ah, [pci_bus] |
; mov bl, 0x0D ;from Lantency Timer Register |
; call pci_read_reg |
;******see if its aat least 64 clocks******** |
; cmp ax,64 |
; jge PCNET_adjust_pci_device_Done |
;******Set latency to 32 clocks******* |
; mov cx, 64 ;value to write |
; mov bh, [pci_dev] |
; mov al, 1 ;write a byte |
; mov ah, [pci_bus] |
; mov bl, 0x0D ;to Lantency Timer Register |
; call pci_write_reg |
;******Check latency setting*********** |
.Done: |
ret |
; End of code |
align 4 ; Place all initialised data here |
PCNET_DEV 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 PCNET_PORT_ASEL ; 0 Auto-select |
dd PCNET_PORT_AUI ; 1 BNC/AUI |
dd PCNET_PORT_AUI ; 2 AUI/BNC |
dd PCNET_PORT_ASEL ; 3 not supported |
dd PCNET_PORT_10BT or PCNET_PORT_FD ; 4 10baseT-FD |
dd PCNET_PORT_ASEL ; 5 not supported |
dd PCNET_PORT_ASEL ; 6 not supported |
dd PCNET_PORT_ASEL ; 7 not supported |
dd PCNET_PORT_ASEL ; 8 not supported |
dd PCNET_PORT_MII ; 9 MII 10baseT |
dd PCNET_PORT_MII or PCNET_PORT_FD ; 10 MII 10baseT-FD |
dd PCNET_PORT_MII ; 11 MII (autosel) |
dd PCNET_PORT_10BT ; 12 10BaseT |
dd PCNET_PORT_MII or PCNET_PORT_100 ; 13 MII 100BaseTx |
dd PCNET_PORT_MII or PCNET_PORT_100 or PCNET_PORT_FD ; 14 MII 100BaseTx-FD |
dd PCNET_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 |
PCNET_LIST rd MAX_PCNET ; This list contains all pointers to device structures the driver is handling |
/kernel/branches/net/kernel.asm |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. |
;; PROGRAMMING: |
;; Ivan Poddubny |
;; Marat Zakiyanov (Mario79) |
/kernel/branches/net/network/ARP.inc |
---|
1,23 → 1,22 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ARP.INC ;; |
;; ;; |
;; Address Resolution Protocol ;; |
;; Part of the tcp/ip network stack for KolibriOS ;; |
;; ;; |
;; This file contains the following: ;; |
;; arp_table_manager - Manages an ARPTable ;; |
;; arp_request - Sends an ARP request on the ethernet ;; |
;; arp_handler - Called when an ARP packet is received ;; |
;; Based on the work of [Johnny_B] and [smb] ;; |
;; ;; |
;; Changes history: ;; |
;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;; |
;; 11.11.2006 - [Johnny_B] and [smb] ;; |
;; Written by hidnplayr@kolibrios.org ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision: 983 $ |
26,6 → 25,9 |
ARP_AWAITING_RESPONSE equ 2 |
ARP_RESPONSE_TIMEOUT equ 3 |
ARP_REQUEST_TTL = 20 ; in seconds |
ARP_ENTRY_TTL = 30 ; in seconds |
ETHER_ARP equ 0x0608 |
ARP_REQ_OPCODE equ 0x0100 ; request |
79,7 → 81,18 |
;----------------------------------------------------------------- |
; |
; ARP_init |
; |
; This function resets all ARP variables |
; |
; IN: / |
; OUT: / |
; |
;----------------------------------------------------------------- |
align 4 |
ARP_init: |
xor eax, eax |
93,176 → 106,24 |
ret |
;*************************************************************************** |
; Function |
; arp_table_manager [by Johnny_B] |
;----------------------------------------------------------------- |
; |
; Description |
; Does a most required operations with ARP-table |
; IN: |
; Operation: see Opcode's constants below |
; Index: Index of entry in the ARP-table |
; Extra: Extra parameter for some Opcodes |
; OUT: |
; EAX = Returned value depends on opcodes, more detailed see below |
; ARP_IP_to_MAC |
; |
;*************************************************************************** |
;Opcode's constants |
ARP_TABLE_ADD equ 1 |
ARP_TABLE_IP_TO_MAC equ 5 |
; This function resets all ARP variables |
; |
; IN: eax = IPv4 address |
; OUT: eax = -1 on error, else eax = first two bytes of mac |
; ( high 16 bits are zero) |
; ebx = last four bytes of mac ; TODO: special eax value for 'request send' |
; |
;----------------------------------------------------------------- |
;Index's constants |
EXTRA_IS_ARP_PACKET_PTR equ 0 ;if Extra contain pointer to ARP_Packet |
EXTRA_IS_ARP_ENTRY_PTR equ -1 ;if Extra contain pointer to ARP_ENTRY |
align 4 |
proc arp_table_manager stdcall uses ebx esi edi ecx edx, Opcode:DWORD,Index:DWORD,Extra:DWORD |
ARP_IP_to_MAC: |
mov ebx, ARPTable ;ARPTable base |
mov ecx, dword[NumARP] ;ARP-entries counter |
DEBUGF 1,"ARP_IP_to_MAC\n" |
mov eax, dword[Opcode] |
DEBUGF 1,"ARP table manager opcode:%u numARP:%u\n",eax,ecx |
cmp eax, ARP_TABLE_ADD |
je .add |
cmp eax, ARP_TABLE_IP_TO_MAC |
je .ip_to_mac |
jmp .exit ;if unknown opcode |
;;BEGIN ADD |
;;Description: it adds an entry in the table. If ARP-table already |
;; contains same IP, it will be updated. |
;;IN: Operation: ARP_TABLE_ADD |
;; Index: specifies what contains Extra-parameter |
;; Extra: if Index==EXTRA_IS_ARP_Packet_PTR, |
;; then Extra contains pointer to ARP_Packet, |
;; otherwise Extra contains pointer to ARP_ENTRY |
;;OUT: |
;; EAX=index of entry, that has been added |
;; |
.add: |
DEBUGF 1,"1" |
sub esp, ARP_ENTRY.size ;Allocate ARP_ENTRY_SIZE byte in stack |
mov esi, [Extra] ;pointer |
mov edi, [Index] ;opcode |
cmp edi, EXTRA_IS_ARP_PACKET_PTR |
je .ARP_Packet_to_entry ;if Extra contain ptr to ARP_Packet and we have to form arp-entry |
;else it contain ptr to arp-entry |
DEBUGF 1,"2" |
cld |
; esi already has been loaded |
mov edi, esp ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add) |
mov ecx,ARP_ENTRY.size/2 ;ARP_ENTRY_SIZE must be even number!!! |
rep movsw ;copy |
jmp .search |
.ARP_Packet_to_entry: |
DEBUGF 1,"3" |
mov edx, dword[esi + ARP_Packet.SenderIP] ;esi=base of ARP_Packet |
mov [esp + ARP_ENTRY.IP], edx |
cld |
lea esi, [esi + ARP_Packet.SenderMAC] |
lea edi, [esp + ARP_ENTRY.MAC] |
movsd |
movsw |
mov word[esp + ARP_ENTRY.Status], ARP_VALID_MAPPING ; specify the type - a valid entry |
mov word[esp + ARP_ENTRY.TTL], 0x0E10 ; = 1 hour |
.search: |
DEBUGF 1,"4" |
mov edx, dword[esp + ARP_ENTRY.IP] ;edx=IP-address, which we'll search |
mov ecx, dword[NumARP] ;ecx=ARP-entries counter |
jecxz .add_to_end ;if ARP-entries number == 0 |
imul eax, ecx, ARP_ENTRY.size ;eax=current table size(in bytes) |
@@: |
sub eax, ARP_ENTRY.size |
cmp dword[ebx + eax + ARP_ENTRY.IP], edx |
loopnz @b |
; jz .replace ; found, replace existing entry, ptr to it is in eax |
.add_to_end: |
; |
; DEBUGF 1,"5\n" |
; ;else add to end |
; or eax,-1 ;set eax=0xFFFFFFFF if adding is impossible |
; mov ecx, dword[NumARP] |
; cmp ecx, ARP_TABLE_SIZE |
; je .add_exit ;if arp-entries number is equal to arp-table maxsize |
; imul eax, dword[NumARP], ARP_ENTRY.size ;eax=ptr to end of ARPTable |
; inc dword [NumARP] ;increase ARP-entries counter |
; .replace: |
DEBUGF 1,"Updating ARP entry: %x-%x-%x-%x-%x-%x = %u.%u.%u.%u to slot:%u\n",\ |
[esp + ARP_ENTRY.MAC]:2,[esp + ARP_ENTRY.MAC+1]:2,[esp + ARP_ENTRY.MAC+2]:2,[esp + ARP_ENTRY.MAC+3]:2,[esp + ARP_ENTRY.MAC+4]:2,[esp + ARP_ENTRY.MAC+5]:2,\ |
[esp + ARP_ENTRY.IP]:1,[esp + ARP_ENTRY.IP+1]:1,[esp + ARP_ENTRY.IP+2]:1,[esp + ARP_ENTRY.IP+3]:1,eax |
cld |
mov esi, esp ;esp=base of ARP-entry, that will be added |
lea edi, [ebx + eax] ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add) |
mov ecx,ARP_ENTRY.size/2 ;ARP_ENTRY_SIZE must be even number!!! |
rep movsw |
mov ecx, ARP_ENTRY.size |
xor edx, edx ;"div" takes operand from EDX:EAX |
div ecx ;eax=index of entry, which has been added |
.add_exit: |
add esp, ARP_ENTRY.size ;free stack |
jmp .exit |
;;END ADD |
;;BEGIN IP_TO_MAC |
;;Description: it gets an IP from Index, scans each entry in the table and writes |
;; MAC, that relates to specified IP, into buffer specified in Extra. |
;; And if it cannot find an IP-address in the table, it does an ARP-request of that. |
;;IN: Operation: ARP_TABLE_IP_TO_MAC |
;; Index: IP that should be transformed into MAC |
;; Extra: pointer to buffer where will be written the MAC-address. |
;;OUT: |
;; EAX=ARP table entry status code. |
;; If EAX==ARP_NO_ENTRY, IP isn't found in the table and we have sent the request. |
;; If EAX==ARP_AWAITING_RESPONSE, we wait the response from remote system. |
;; If EAX==ARP_RESPONSE_TIMEOUT, remote system not responds too long. |
;; If EAX==ARP_VALID_MAPPING, all is ok, we've got a true MAC. |
;; |
;; If MAC will equal to a zero, in the buffer. It means, that IP-address was not yet |
;; resolved, or that doesn't exist. I recommend you, to do at most 3-5 calls of this |
;; function with 1sec delay. sure, only if it not return a valid MAC after a first call. |
;; |
.ip_to_mac: |
DEBUGF 1,"Trying to find MAC for %u.%u.%u.%u\n",[Index]:1,[Index+1]:1,[Index+2]:1,[Index+3]:1 |
xor eax, eax |
mov edi, dword[Extra] |
cld |
stosd |
stosw |
; first, check destination IP to see if it is on 'this' network. |
; The test is: |
; if ( destIP & subnet_mask == stack_ip & subnet_mask ) |
270,187 → 131,133 |
; else |
; destination is remote, so pass to gateway |
xor edx, edx ; TODO: find device num in edx |
;;; TODO: get device number ! (in edx) |
xor edx, edx |
mov ebx, [IP_LIST+edx] |
and ebx, [SUBNET_LIST+edx] |
mov ecx, eax |
and ecx, [SUBNET_LIST+edx] |
cmp ecx, ebx |
je .local |
mov eax, [Index] ;eax=required IP |
mov esi, eax |
and esi, [SUBNET_LIST+edx] |
mov ecx, [IP_LIST+edx] |
and ecx, [SUBNET_LIST+edx] |
cmp esi, ecx |
je @f ;if we and target IP are located in the same network |
mov eax, [GATEWAY_LIST+edx] |
mov [Index], eax |
DEBUGF 1,"IP is not on subnet, using %u.%u.%u.%u instead\n",[Index]:1,[Index+1]:1,[Index+2]:1,[Index+3]:1 |
@@: |
DEBUGF 1,"requested IP is not on subnet, using gateway\n" |
cmp dword[NumARP], 0 |
je .ip_to_mac_send_request ;if ARP-table not contain an entries, we have to request IP. |
;EAX will be containing a zero, it's equal to ARP_NO_ENTRY |
.local: |
; try to find it on the list |
mov ecx, [NumARP] |
jz .not_in_list |
mov esi, ARPTable + ARP_ENTRY.IP |
.scan_loop: |
scasd |
jz .found_it |
add esi, ARP_ENTRY.size - 4 |
loop .scan_loop |
.not_in_list: |
mov ecx, dword[NumARP] |
imul esi, ecx, ARP_ENTRY.size ;esi=current ARP-table size |
DEBUGF 1,"IP not found on list, preparing for ARP request\n" |
@@: |
sub esi, ARP_ENTRY.size |
cmp [ebx + esi + ARP_ENTRY.IP], eax ; ebx=ARPTable base |
loopnz @b ; Return back if non match |
jnz .ip_to_mac_send_request ; and request IP->MAC if none found in the table |
; if not, reserve an entry in list and send an ARP request packet |
; Return the entry status in eax |
movzx eax, word[ebx + esi + ARP_ENTRY.Status] |
push eax |
DEBUGF 1,"MAC found: %x-%x-%x-%x-%x-%x status:%x in slot:%u\n",\ |
[ebx + esi + ARP_ENTRY.MAC]:2,[ebx + esi + ARP_ENTRY.MAC+1]:2,[ebx + esi + ARP_ENTRY.MAC+2]:2,[ebx + esi + ARP_ENTRY.MAC+3]:2,[ebx + esi + ARP_ENTRY.MAC+4]:2,[ebx + esi + ARP_ENTRY.MAC+5]:2, ax, esi |
push word ARP_REQUEST_TTL |
push word ARP_AWAITING_RESPONSE |
push dword 0 |
push word 0 |
push eax |
call ARP_add_entry |
; esi holds index |
cld |
lea esi, [ebx + esi + ARP_ENTRY.MAC] |
mov edi, [Extra] ;edi=ptr to buffer for write MAC |
movsd |
movsw |
jmp .exit |
cmp eax, -1 |
je .full |
.ip_to_mac_send_request: |
;;; TODO: get device number ! (in edx) |
xor edx, edx |
mov edx, [ETH_DRV_LIST + 4*edx] |
lea ecx, [edx + ETH_DEVICE.mac] |
pop eax |
call ARP_create_request |
stdcall arp_request,[Index],[IP_LIST+edx],ecx ;TargetIP,SenderIP_ptr,SenderMAC_ptr |
mov eax, ARP_NO_ENTRY |
jmp .exit |
ret |
;;END IP_TO_MAC |
.found_it: |
DEBUGF 1,"Found MAC! (%u-%u-%u-%u-%u-%u)\n",[esi+0]:2,[esi+1]:2,[esi+2]:2,[esi+3]:2,[esi+4]:2,[esi+5]:2 |
movzx eax, word [esi] |
mov ebx, [esi+2] |
.exit: |
ret |
endp |
.full: |
add esp, 4 |
mov eax, -1 |
ret |
;*************************************************************************** |
; Function |
; arp_request [by Johnny_B] |
;--------------------------------------------------------------------------- |
; |
; Description |
; Sends an ARP request on the ethernet |
; IN: |
; TargetIP : requested IP address |
; SenderIP_ptr : POINTER to sender's IP address(our system's address) |
; SenderMAC_ptr : POINTER to sender's MAC address(our system's address) |
; OUT: |
; EAX=0 (if all is ok), otherwise EAX is not defined |
; ARP_create_packet |
; |
; EBX,ESI,EDI will be saved |
; IN: ip in eax |
; |
;*************************************************************************** |
proc arp_request stdcall uses ebx esi edi,\ |
TargetIP:DWORD, SenderIP_ptr:DWORD, SenderMAC_ptr:DWORD |
; OUT: / |
; |
;--------------------------------------------------------------------------- |
DEBUGF 1,"Create ARP request\n" |
align 4 |
ARP_create_request: |
stdcall kernel_alloc, 60 ; minimum eth packet size |
test eax, eax |
jz .exit |
DEBUGF 1,"Create ARP Packet\n" |
mov ebx, eax |
call IPv4_dest_to_dev |
mov word [ebx + ETH_FRAME.Data + ARP_Packet.HardwareType], 0x0100 ;Ethernet |
mov word [ebx + ETH_FRAME.Data + ARP_Packet.ProtocolType], 0x0008 ;IP |
mov byte [ebx + ETH_FRAME.Data + ARP_Packet.HardwareSize], 0x06 ;MAC-addr length |
mov byte [ebx + ETH_FRAME.Data + ARP_Packet.ProtocolSize], 0x04 ;IP-addr length |
mov word [ebx + ETH_FRAME.Data + ARP_Packet.Opcode], 0x0100 ;Request |
push eax ; DestIP |
mov eax, [IP_LIST+4*edi] ; senderIP |
push eax |
DEBUGF 1,"1" |
mov edi, [ETH_DRV_LIST + 4*edi] |
lea eax, [edi + ETH_DEVICE.mac] |
mov ebx, ETH_BROADCAST |
mov ecx, 60 ; minimum packet size |
mov edx, edi ;;; |
mov di , ETHER_ARP |
call ETH_create_Packet |
cmp edi, -1 |
je .exit |
cld |
mov esi, [SenderMAC_ptr] |
lea edi, [ebx + ETH_FRAME.Data + ARP_Packet.SenderMAC] ;Our MAC-addr |
movsd |
movsw |
mov word [edi + ARP_Packet.HardwareType], 0x0100 ;Ethernet |
mov word [edi + ARP_Packet.ProtocolType], 0x0008 ;IP |
mov byte [edi + ARP_Packet.HardwareSize], 6 ;MAC-addr length |
mov byte [edi + ARP_Packet.ProtocolSize], 4 ;IP-addr length |
mov word [edi + ARP_Packet.Opcode], ARP_REQ_OPCODE ;Request |
DEBUGF 1,"2" |
add edi, ARP_Packet.SenderMAC ; sendermac |
lea esi, [edx + ETH_DEVICE.mac] ; |
movsw ; |
movsd ; |
mov esi, [SenderIP_ptr] |
mov [ebx + ETH_FRAME.Data + ARP_Packet.SenderIP], esi ;Our IP-addr |
; movsd |
pop eax |
stosd ; |
DEBUGF 1,"3" |
xor eax, eax ; destmac |
movsw ; |
movsw ; |
lea edi, [ebx + ETH_FRAME.Data + ARP_Packet.TargetMAC] ; Required MAC-addr |
xor eax, eax |
stosd |
stosw |
pop eax |
movsd ; |
DEBUGF 1,"4" |
DEBUGF 1,"ARP Packet for device %x created successfully\n", edx |
lea edi, [ebx + ETH_FRAME.DstMAC] |
stosd |
stosw |
call esi |
DEBUGF 1,"5" |
inc [ARP_PACKETS_TX+4*edi] |
mov esi, [TargetIP] |
mov dword [ebx + ETH_FRAME.Data + ARP_Packet.TargetIP], esi ;Required IP-addr(we get it as function parameter) |
ret |
DEBUGF 1,"6" |
mov esi, [SenderMAC_ptr] |
lea edi, [ebx + ETH_FRAME.SrcMAC] |
movsd |
movsw |
DEBUGF 1,"7" |
mov ax , ETHER_ARP |
stosw |
DEBUGF 1,"8" |
;;; TODO: get device number in edx !! |
xor edx, edx |
shl edx, 2 |
inc [ARP_PACKETS_TX+edx] |
push dword .returnaddr |
push dword 60 |
push ebx |
mov ebx, [ETH_DRV_LIST + edx] |
jmp [ebx + ETH_DEVICE.transmit] |
.returnaddr: |
; Add an entry in the ARP table, awaiting response |
sub esp, ARP_ENTRY.size ;allocate memory for ARP-entry |
mov esi, dword[TargetIP] |
mov dword[esp + ARP_ENTRY.IP],esi |
lea edi, [esp + ARP_ENTRY.MAC] |
xor eax, eax |
stosd |
stosw |
mov word[esp + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE |
mov word[esp + ARP_ENTRY.TTL], 10 ; 10 seconds |
stdcall arp_table_manager,ARP_TABLE_ADD,EXTRA_IS_ARP_ENTRY_PTR,esp |
add esp, ARP_ENTRY.size ; free memory |
.exit: |
DEBUGF 1,"ARP request - end\n" |
add esp, 8 |
DEBUGF 1,"Create ARP Packet - failed\n" |
mov eax, -1 |
ret |
endp |
;--------------------------------------------------------------------------- |
; |
; ARP_decrease_entry_ttls |
512,7 → 319,82 |
ret |
;--------------------------------------------------------------------------- |
; |
; ARP_add_entry (or update) |
; |
; IN: arp entry in stack: esp .IP |
; esp+4 .MAC |
; esp+10 .Status |
; esp+12 .TTL |
; esp+14 |
; |
; OUT: eax = entry #, -1 on error |
; |
;--------------------------------------------------------------------------- |
; TODO: use a mutex |
align 4 |
ARP_add_entry: |
mov ecx, [NumARP] |
test ecx, ecx |
jz .add |
mov eax, dword[esp + ARP_ENTRY.MAC] |
mov bx , word[esp + ARP_ENTRY.MAC + 4] |
mov esi, ARPTable |
.loop: |
cmp dword [esi + ARP_ENTRY.MAC], eax |
jne .maybe_next |
cmp word [esi + ARP_ENTRY.MAC + 4], bx |
jne .maybe_next |
cmp dword[esi + ARP_ENTRY.TTL], 0xFFFF ; static entry |
jne .notstatic |
cmp dword[esp + ARP_ENTRY.TTL], 0xFFFF |
jne .exit |
.notstatic: |
mov ebx, [NumARP] |
xchg ebx, ecx |
sub ecx, ebx |
jmp .add |
.maybe_next: |
add esi, ARP_ENTRY.size |
loop .loop |
mov ecx, [NumARP] |
cmp ecx, ARP_TABLE_SIZE |
jge .full |
.add: |
push ecx |
imul ecx, ARP_ENTRY.size |
lea edi, [ecx + ARPTable] |
lea esi, [esp + 4] |
mov ecx, ARP_ENTRY.size/2 |
repz movsw |
inc [NumARP] |
pop eax |
.exit: |
add esp, 14 |
ret |
.full: |
mov eax, -1 |
jmp .exit |
;--------------------------------------------------------------------------- |
; |
; ARP_del_entry |
537,13 → 419,12 |
cld |
rep movsw |
dec dword[NumARP] ;decrease arp-entries counter |
dec [NumARP] ;decrease arp-entries counter |
ret |
;----------------------------------------------------- |
; |
; ARP_Handler: |
557,22 → 438,53 |
; OUT: / |
; |
;----------------------------------------------------- |
align 4 |
ARP_Handler: |
ARP_handler: |
DEBUGF 1,"ARP_Handler - start\n" |
cmp ecx, 28 |
jl .exit |
; Is this a REQUEST? |
; Is this a request for My Host IP |
; Yes - So construct a response message. |
; Send this message to the ethernet card for transmission |
cmp word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE ; Is this a reply packet? |
jne .maybe_request |
; push ebx edx |
stdcall arp_table_manager, ARP_TABLE_ADD, EXTRA_IS_ARP_PACKET_PTR, edx |
; pop edx ebx |
mov ecx, [NumARP] |
test ecx, ecx |
jz .exit |
mov eax, [esp] |
mov eax, [eax + ARP_Packet.SenderIP] |
mov esi, ARPTable+ARP_ENTRY.IP |
.loop: |
scasd |
jz .gotit |
add esi, ARP_ENTRY.size-4 |
loop .loop |
jmp .exit |
.gotit: |
cmp [esi-4+ARP_ENTRY.Status], 0x0300 ;if it is a static entry, dont touch it |
je .exit |
mov [esi-4+ARP_ENTRY.Status], ARP_VALID_MAPPING |
mov [esi+ARP_ENTRY.TTL-4], ARP_ENTRY_TTL |
mov ebx, [esp] |
mov eax, dword [ebx + ARP_Packet.SenderMAC] |
mov dword [esi+ARP_ENTRY.MAC-4], eax |
mov ax , word [ebx + ARP_Packet.SenderMAC + 4] |
mov word [esi+ARP_ENTRY.MAC-4+4], ax |
jmp .exit |
;------ |
.maybe_request: |
cmp word [edx + ARP_Packet.Opcode], ARP_REQ_OPCODE ; Is this a request packet? |
jne .exit |
591,10 → 503,8 |
push eax |
push edi |
; DEBUGF 1,"ETH_ARP_Handler - request for %u.%u.%u.%u\n",[edi+0]:1,[edi+1]:1,[edi+2]:1,[edi+3]:1 |
; OK, it is a request for one of our MAC addresses. Build the frame and send it |
; We can reuse the buffer. |
; We can reuse the buffer. (faster then using ARP_create_packet) |
cld |
lea esi, [edx + ARP_Packet.SenderMAC] |
623,8 → 533,8 |
lea esi, [edx + ARP_Packet.SenderMAC] |
movsd |
movsw |
mov ax , ETHER_ARP |
stosw |
; mov ax , ETHER_ARP |
; stosw |
jmp ETH_Sender ; And send it! |
672,7 → 582,6 |
jz .remove ; 5 |
dec bl |
.error: |
mov eax, -1 |
ret |
697,9 → 606,11 |
.write: |
; TODO: write code |
; call ARP_write_entry |
ret |
.remove: |
; TODO: write code |
mov esi, eax |
call ARP_del_entry |
ret |
/kernel/branches/net/network/IPv4.inc |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; IP.INC ;; |
85,7 → 85,9 |
or eax, -1 |
mov edi, BROADCAST |
mov ecx, 1+4*MAX_IP |
stosd |
xor eax, eax |
mov ecx, 4*MAX_IP |
rep stosd |
xor eax, eax |
116,7 → 118,7 |
;----------------------------------------------------------------- |
align 4 |
IPv4_Handler: |
IPv4_handler: |
DEBUGF 1,"IP_Handler - start\n" |
mov cx , [edx + IPv4_Packet.HeaderChecksum] |
186,13 → 188,13 |
pop edx ; Offset to data (tcp/udp/icmp/.. Packet) |
cmp al , IP_PROTO_TCP |
; je TCP_Handler |
; je TCP_handler |
cmp al , IP_PROTO_UDP |
je UDP_Handler |
je UDP_handler |
cmp al , IP_PROTO_ICMP |
je ICMP_Handler |
je ICMP_handler |
DEBUGF 1,"IP_Handler - unknown protocol:%u\n",al |
391,14 → 393,14 |
mov al , [edx + IPv4_Packet.Protocol] |
pop edx ; Offset to data (tcp/udp/icmp/.. Packet) |
; cmp al , IP_PROTO_TCP |
; je TCP_Handler |
cmp al , IP_PROTO_TCP |
; je TCP_handler |
cmp al , IP_PROTO_UDP |
je UDP_Handler |
je UDP_handler |
cmp al , IP_PROTO_ICMP |
je ICMP_Handler_fragments |
je ICMP_handler_fragments |
DEBUGF 1,"IP_Handler - unknown protocol:%u\n",al |
505,7 → 507,7 |
;;; TODO: create fragmented packets |
align 4 |
IPv4_create_Packet: |
IPv4_create_packet: |
DEBUGF 1,"Create IPv4 Packet\n" |
515,12 → 517,11 |
cmp eax, -1 |
je .broadcast ; If it is broadcast, just send |
push eax |
stdcall arp_table_manager, ARP_TABLE_IP_TO_MAC, eax, temp_dstmac ;opcode,IP,MAC_ptr - Get the MAC address. |
cmp eax, ARP_NO_ENTRY |
pop eax |
jne .send |
call ARP_IP_to_MAC |
cmp eax, -1 |
jne .found |
DEBUGF 1,"Create IPv4 Packet - ARP entry not found!\n" |
; TODO: QUEUE! |
528,9 → 529,15 |
ret |
.found: |
push ax |
push ebx |
jmp .send |
.broadcast: |
mov dword [temp_dstmac], -1 |
mov word [temp_dstmac+4], -1 |
push word -1 |
push dword -1 |
.send: |
539,9 → 546,10 |
inc [IP_PACKETS_TX+4*edi] |
mov edi, [ETH_DRV_LIST + 4*edi] |
lea eax, [edi + ETH_DEVICE.mac] |
mov ebx, temp_dstmac |
lea ebx, [esp+16] |
mov ecx, [esp+12] |
add ecx, IPv4_Packet.DataOrOptional |
mov edx, edi ;;; |
mov di , ETHER_IPv4 |
call ETH_create_Packet ; TODO: figure out a way to make this work with other protocols too |
cmp edi, -1 |
572,10 → 580,12 |
DEBUGF 1,"IPv4 Packet for device %x created successfully\n", edx |
add esp, 6 |
ret |
.exit: |
add esp, 16 |
add esp, 16+6 |
.exit_: |
DEBUGF 1,"Create IPv4 Packet - failed\n" |
or edi, -1 |
582,11 → 592,7 |
ret |
uglobal |
temp_dstmac dp ? ; TODO: place this in stack instead! |
endg |
;--------------------------------------------------------------------------- |
; |
; IPv4_dest_to_dev |
/kernel/branches/net/network/ethernet.inc |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ETHERNET.INC ;; |
46,6 → 46,12 |
align 4 |
iglobal |
ETH_BROADCAST dp 0xffffffffffff |
endg |
align 4 |
uglobal |
ETH_RUNNING dd ? |
230,7 → 236,7 |
;------------------------------------------------------------- |
align 4 |
ETH_Handler: |
ETH_handler: |
get_from_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, .gohome |
243,10 → 249,10 |
mov ax , [eax + ETH_FRAME.Type] |
cmp ax, ETHER_IPv4 |
je IPv4_Handler |
je IPv4_handler |
cmp ax, ETHER_ARP |
je ARP_Handler |
je ARP_handler |
DEBUGF 1,"Unknown ethernet packet type %x\n", ax |
377,19 → 383,15 |
pop ecx |
pop edx |
DEBUGF 1,"1" |
mov edi, eax |
pop esi |
movsd |
movsw |
DEBUGF 1,"2" |
pop esi |
movsd |
movsw |
DEBUGF 1,"3" |
pop ax |
stosw |
DEBUGF 1,"4" |
lea eax, [edi - ETH_FRAME.Data] ; Set eax to buffer start |
mov ebx, ecx ; Set ebx to complete buffer size |
/kernel/branches/net/network/icmp.inc |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ICMP.INC ;; |
146,7 → 146,7 |
;-------------------------------- |
align 4 |
ICMP_Handler: ;TODO: works only on pure ethernet right now ! |
ICMP_handler: ;TODO: works only on pure ethernet right now ! |
DEBUGF 1,"ICMP_Handler - start\n" |
cmp byte [edx + ICMP_Packet.Type], ICMP_ECHO ; Is this an echo request? |
318,7 → 318,7 |
;-------------------------------- |
align 4 |
ICMP_Handler_fragments: ; works only on pure ethernet right now ! |
ICMP_handler_fragments: ; works only on pure ethernet right now ! |
DEBUGF 1,"ICMP_Handler_fragments - start\n" |
345,7 → 345,7 |
shl edx, 16 |
mov dx , ICMP_ECHOREPLY shl 8 + 0 ; Type + Code |
call ICMP_create_Packet |
call ICMP_create_packet |
.dump: |
DEBUGF 1,"ICMP_Handler_fragments - end\n" |
372,7 → 372,7 |
;----------------------------------------------------------------- |
align 4 |
ICMP_create_Packet: |
ICMP_create_packet: |
DEBUGF 1,"Create ICMP Packet\n" |
382,7 → 382,7 |
mov di , IP_PROTO_ICMP |
shr edx, 16 |
call IPv4_create_Packet |
call IPv4_create_packet |
cmp edi, -1 |
je .exit |
/kernel/branches/net/network/queue.inc |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; queue.inc ;; |
/kernel/branches/net/network/socket.inc |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; SOCKET.INC ;; |
24,24 → 24,25 |
.PID dd ? ; application process id |
.Domain dd ? ; INET/UNIX/.. |
.Type dd ? ; RAW/UDP/TCP/... |
.Protocol dd ? ; ICMP/IPv4/ARP/ |
.LocalIP dd ? ; local IP address |
.RemoteIP dd ? ; remote IP address |
.LocalPort dw ? ; local port |
.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) |
.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 |
; .SND_WND dd ? ; send 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 |
.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 |
.SND_WND dd ? ; send 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 |
.lock dd ? ; lock mutex |
.backlog dw ? ; Backlog |
125,7 → 126,7 |
; |
; IN: domain in ecx |
; type in edx |
; set esi to zero, it is reserved for future use |
; protocol in esi |
; OUT: eax is socket num, -1 on error |
; |
;----------------------------------------------- |
139,6 → 140,7 |
mov [eax + SOCKET.Domain], ecx |
mov [eax + SOCKET.Type], edx |
mov [eax + SOCKET.Protocol], esi |
stdcall net_socket_addr_to_num, eax |
DEBUGF 1,", socketnumber: %u\n", eax |
154,7 → 156,6 |
; |
; SOCKET_bind |
; |
; |
; IN: socket number in ecx |
; pointer to sockaddr struct in edx |
; length of that struct in esi |
184,6 → 185,7 |
jl s_error |
mov bx, word [edx + 2] |
rol bx,8 ;;; |
DEBUGF 1,"local port: %u ",bx |
test bx, bx |
jnz .check_only |
280,6 → 282,7 |
.udp: |
mov bx , word [edx + 2] |
rol bx, 8 |
mov word [eax + SOCKET.RemotePort], bx |
DEBUGF 1,"remote port: %u ",bx |
735,12 → 738,13 |
mov ecx, esi |
mov esi, edx |
mov edx, dword [eax + SOCKET.LocalPort] ; load local port and remote port at once |
DEBUGF 1,"local port: %u, remote port:%u\n",[eax + SOCKET.LocalPort]:2, [eax + SOCKET.RemotePort]:2 |
bswap edx ;;; |
rol edx, 16 ;;; |
mov ebx, [eax + SOCKET.LocalIP] |
mov eax, [eax + SOCKET.RemoteIP] |
call UDP_create_Packet |
call UDP_create_packet |
mov [esp+32], eax |
ret |
765,7 → 769,7 |
add esi, ICMP_Packet.Data |
mov ebx, [eax + SOCKET.LocalIP] |
mov eax, [eax + SOCKET.RemoteIP] |
call ICMP_create_Packet |
call ICMP_create_packet |
mov [esp+32], eax |
ret |
/kernel/branches/net/network/stack.inc |
---|
110,7 → 110,7 |
cmp [ETH_RUNNING], 0 |
je .exit |
call ETH_Handler ; handle all queued ethernet packets |
call ETH_handler ; handle all queued ethernet packets |
call ETH_send_queued |
; Test for 10ms tick, call tcp timer |
188,6 → 188,13 |
align 4 |
sys_network: |
cmp ebx, -1 |
jne @f |
mov eax, [ETH_RUNNING] |
jmp .return |
@@: |
cmp bh, MAX_NET_DEVICES ; Check if device number exists |
jge .doesnt_exist |
200,7 → 207,7 |
test bl, bl ; 0 = Get device type (ethernet/token ring/...) |
jnz @f |
; todo |
xor eax, eax |
jmp .return |
/kernel/branches/net/network/tcp.inc |
---|
1,21 → 1,20 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; TCP.INC ;; |
;; ;; |
;; TCP 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 ;; |
;; 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: 1019 $ |
44,6 → 43,8 |
TCP_RETRIES equ 5 ; Number of times to resend a Packet |
TCP_TIMEOUT equ 10 ; resend if not replied to in x hs |
TCP_QUEUE_SIZE equ 16 |
struct TCP_Packet |
.SourcePort dw ? |
.DestinationPort dw ? |
59,17 → 60,59 |
.Data: |
ends |
align 4 |
uglobal |
TCP_PACKETS_TX rd MAX_IP |
TCP_PACKETS_RX rd MAX_IP |
;*************************************************************************** |
; Function |
TCP_IN_QUEUE rd 3*TCP_QUEUE_SIZE+3 |
TCP_OUT_QUEUE rd 3*TCP_QUEUE_SIZE+3 |
endg |
;----------------------------------------------------------------- |
; |
; TCP_init |
; |
; This function resets all TCP variables |
; |
; IN: / |
; OUT: / |
; |
;----------------------------------------------------------------- |
align 4 |
TCP_init: |
xor eax, eax |
mov edi, TCP_PACKETS_TX |
mov ecx, 2*MAX_IP |
rep stosd |
mov dword [TCP_IN_QUEUE], TCP_QUEUE_SIZE |
mov dword [TCP_IN_QUEUE+4], TCP_IN_QUEUE + queue.data |
mov dword [TCP_IN_QUEUE+8], TCP_IN_QUEUE + queue.data |
mov dword [TCP_OUT_QUEUE], TCP_QUEUE_SIZE |
mov dword [TCP_OUT_QUEUE+4], TCP_OUT_QUEUE + queue.data |
mov dword [TCP_OUT_QUEUE+8], TCP_OUT_QUEUE + queue.data |
ret |
;----------------------------------------------------------------- |
; |
; tcp_tcb_handler |
; |
; Description |
; Handles sockets in the timewait state, closing them |
; when the TCB timer expires |
; |
;*************************************************************************** |
;----------------------------------------------------------------- |
align 4 |
tcp_tcb_handler: |
; scan through all the sockets, decrementing active timers |
84,7 → 127,7 |
or ebx, ebx |
jz .exit |
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] |
; 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] |
cmp [ebx + SOCKET.TCBTimer], 0 |
jne .decrement_tcb |
124,7 → 167,8 |
; |
;*************************************************************************** |
proc tcp_tx_handler stdcall |
align 4 |
tcp_tx_handler: |
; 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 |
133,7 → 177,7 |
mov ecx, 0 |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
; cmp ecx, NUMRESENDENTRIES |
je .exit ; None left |
cmp dword[esi + 4], 0 |
jne @f ; found one |
162,9 → 206,9 |
@@: ; resend Packet |
pushad |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
; mov eax, EMPTY_QUEUE |
; call dequeue |
; cmp ax, NO_BUFFER |
jne .tth004z |
; TODO - try again in 10ms. |
179,21 → 223,21 |
.tth004z: |
; we have a buffer # in ax |
push eax ecx |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
; 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,, |
mov esi, resendBuffer |
@@: add esi, IPBUFFSIZE |
; mov esi, resendBuffer |
; @@: add esi, IPBUFFSIZE |
loop @b |
; we have resend buffer location in esi |
mov ecx, IPBUFFSIZE |
; mov ecx, IPBUFFSIZE |
; copy data across |
push edi |
202,15 → 246,15 |
pop edi |
; queue Packet |
mov eax, NET1OUT_QUEUE |
mov edx, [IP_LIST] |
cmp edx, [edi + IP_Packet.DestinationAddress] |
jne .not_local |
mov eax, IPIN_QUEUE |
; mov eax, NET1OUT_QUEUE |
; mov edx, [IP_LIST] |
; cmp edx, [edi + IP_Packet.DestinationAddress] |
; jne .not_local |
; mov eax, IPIN_QUEUE |
.not_local: |
pop ebx |
call queue |
; call queue |
.tth005: |
popad |
221,36 → 265,33 |
.exit: |
ret |
endp |
;*************************************************************************** |
; 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_Handler: |
; |
;*************************************************************************** |
; Called by IPv4_handler, |
; this procedure will inject the tcp data diagrams in the application sockets. |
; |
; IN: Pointer to buffer in [esp] |
; size of buffer in [esp+4] |
; pointer to device struct in ebx |
; TCP Packet size in ecx |
; pointer to TCP Packet data in edx |
; SourceAddres in esi |
; OUT: / |
; |
;----------------------------------------------------------------- |
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. |
TCP_Handler : |
push eax |
DEBUGF 1,"TCP_Handler\n" |
jmp .exit ;;;; |
; Look for a socket where |
; IP Packet TCP Destination Port = local Port |
; IP Packet SA = Remote IP |
265,19 → 306,19 |
; 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 |
mov ax, [edx + 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 |
mov eax, esi ;[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 |
mov ax, [edx + 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 |
301,14 → 342,14 |
; 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 |
mov ax, [edx + 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 |
; mov eax, esi ;[edx + IP_Packet.SourceAddress] ; get the source IP Addr from the IP hdr |
cmp [ebx + SOCKET.RemoteIP], esi ; 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 |
336,7 → 377,7 |
; 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 |
mov ax, [edx + 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 |
358,9 → 399,9 |
; 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 |
; 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] |
; inc [dumped_rx_count] |
jmp .exit |
.change_state: |
373,12 → 414,27 |
stdcall tcpStateMachine, ebx |
.exit: |
pop eax |
call freeBuff |
call kernel_free |
add esp, 4 ; pop (balance stack) |
ret |
endp |
;----------------------------------------------------------------- |
; |
; IN: eax = dest ip |
; ebx = source ip |
; ecx = data length |
; edx = remote port shl 16 + local port |
; esi = data offset |
; |
;----------------------------------------------------------------- |
TCP_create_Packet: |
DEBUGF 1,"Create TCP Packet\n" |
;*************************************************************************** |
; Function |
; buildTCPPacket |
394,30 → 450,31 |
; |
;*************************************************************************** |
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 |
add ecx, UDP_Packet.Data |
mov di , IP_PROTO_UDP |
mov edx, eax |
; dx = fragment id |
mov [edx + 20 + TCP_Packet.Flags], bl ; TCP flags |
call IPv4_create_Packet ; TODO: figure out a way to choose between IPv4 and IPv6 |
cmp edi, -1 |
je .exit |
mov ebx, [sockAddr] |
mov [edi + TCP_Packet.Flags], bl ; TCP flags |
; mov ebx, [sockAddr];---------------------------------------------------------- eof |
; 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 [edx + IP_Packet.SourceAddress], eax |
mov eax, [ebx + SOCKET.RemoteIP] |
mov [edx + IP_Packet.DestinationAddress], eax |
; mov [edx + IP_Packet.DestinationAddress], eax |
mov [edx + IP_Packet.VersionAndIHL], 0x45 |
mov [edx + IP_Packet.TypeOfService], 0 |
; mov [edx + IP_Packet.VersionAndIHL], 0x45 |
; mov [edx + IP_Packet.TypeOfService], 0 |
pop eax ; Get the TCP data length |
push eax |
424,14 → 481,14 |
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 |
; 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 |
; mov [edx + IP_Packet.HeaderChecksum], 0 |
; Fill in the TCP header (some data is in the socket descriptor) |
mov ax, [ebx + SOCKET.LocalPort] |
475,54 → 532,64 |
@@: ; 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, [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 |
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 |
; mov ax, [checkResult] |
; rol ax, 8 |
; mov [edx + 20 + TCP_Packet.Checksum], ax |
; Fill in the IP header checksum |
movzx eax, byte [edx + IP_Packet.VersionAndIHL] ; Calculate Header length by using IHL field |
and eax, 0x0000000F ; |
shl eax, 2 ; |
; movzx eax, byte [edx + IP_Packet.VersionAndIHL] ; Calculate Header length by using IHL field |
; and eax, 0x0000000F ; |
; shl eax, 2 ; |
; |
stdcall checksum_jb, edx, eax ; buf_ptr, buf_size |
rol ax, 8 |
mov [edx + IP_Packet.HeaderChecksum], ax |
; mov [edx + IP_Packet.HeaderChecksum], ax |
.exit: |
call kernel_free |
add esp, 4 ; pop (balance stack) |
ret |
endp |
;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 |
; push eax |
; mov eax, [esi] |
; bswap eax |
; inc eax |
; bswap eax |
; mov [esi], eax |
; pop eax |
; ret |
inc byte[esi+0] |
adc byte[esi+1],0 |
adc byte[esi+2],0 |
adc byte[esi+3],0 |
endp |
591,7 → 658,7 |
xor ecx, ecx |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
; cmp ecx, NUMRESENDENTRIES |
je .call_handler ; None left |
cmp [esi + 4], eax |
je @f ; found one |
606,8 → 673,8 |
push ecx |
; Now get buffer location, and copy buffer across. argh! more copying,, |
imul edi, ecx, IPBUFFSIZE |
add edi, resendBuffer |
; imul edi, ecx, IPBUFFSIZE |
; add edi, resendBuffer |
; we have dest buffer location in edi. incoming Packet in edx. |
; Get this Packets sequence number |
668,41 → 735,41 |
; 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 |
; 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 |
; mov eax, EMPTY_QUEUE |
; call dequeue |
; cmp ax, NO_BUFFER |
; je .exit |
push eax |
mov bl, TH_SYN + TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_Packet, [sockAddr] |
; stdcall build_tcp_Packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
; mov eax, NET1OUT_QUEUE |
;;; mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
; mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
;;; call queue |
mov esi, [sockAddr] |
mov [esi + SOCKET.TCBState], TCB_SYN_RECEIVED |
747,9 → 814,9 |
; Send an ACK |
; Now construct the response, and queue for sending by IP |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
; mov eax, EMPTY_QUEUE |
; call dequeue |
; cmp ax, NO_BUFFER |
pop ebx |
je .exit |
757,19 → 824,19 |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_Packet, [sockAddr] |
; stdcall build_tcp_Packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
; mov eax, NET1OUT_QUEUE |
;;; mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
; mov ecx, [sockAddr] |
; cmp edx, [ecx + SOCKET.RemoteIP] |
; jne .not_local |
; mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
;;; call queue |
.exit: |
ret |
822,13 → 889,13 |
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 |
; 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 |
881,7 → 948,7 |
; Read the data bytes, store in socket buffer |
movzx ecx, [edx + IP_Packet.TotalLength] |
; movzx ecx, [edx + IP_Packet.TotalLength] |
xchg cl, ch |
sub ecx, 40 ; Discard 40 bytes of header |
ja .data ; Read data, if any |
943,9 → 1010,9 |
.ack: |
; Send an ACK |
; Now construct the response, and queue for sending by IP |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
; mov eax, EMPTY_QUEUE |
; call dequeue |
; cmp ax, NO_BUFFER |
je .exit |
push eax |
953,20 → 1020,20 |
mov bl, TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_Packet, [sockAddr] |
; stdcall build_tcp_Packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
; mov eax, NET1OUT_QUEUE |
;;; mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
; mov ecx, [sockAddr] |
; cmp edx, [ecx + SOCKET.RemoteIP] |
; jne .not_local |
; mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
;;; call queue |
.exit: |
ret |
1000,9 → 1067,9 |
call inc_inet_esi |
; Send an ACK |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
; mov eax, EMPTY_QUEUE |
; call dequeue |
; cmp ax, NO_BUFFER |
je .exit |
push eax |
1010,19 → 1077,19 |
mov bl, TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_Packet, [sockAddr] |
; stdcall build_tcp_Packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
; mov eax, NET1OUT_QUEUE |
;;; mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
; mov ecx, [sockAddr] |
; cmp edx, [ecx + SOCKET.RemoteIP] |
; jne .not_local |
; mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
;;; call queue |
.exit: |
ret |
1040,10 → 1107,10 |
call inc_inet_esi |
; Send an ACK |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit |
; mov eax, EMPTY_QUEUE |
; call dequeue |
;; cmp ax, NO_BUFFER |
; je .exit |
push eax |
1050,19 → 1117,19 |
mov bl, TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_Packet, [sockAddr] |
; stdcall build_tcp_Packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
; mov eax, NET1OUT_QUEUE |
;;; mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
; mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
;;; call queue |
.exit: |
ret |
1119,8 → 1186,8 |
; @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 ? |
;proc socket_write_tcp stdcall |
;local sockAddr dd ? |
; DEBUGF 1, "socket_write_tcp(0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx |
1128,16 → 1195,16 |
jz .error |
mov ebx, eax |
mov [sockAddr], ebx |
; mov [sockAddr], ebx |
; If the sockets window timer is nonzero, do not queue Packet |
cmp [ebx + SOCKET.wndsizeTimer], 0 |
jne .error |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .error |
; mov eax, EMPTY_QUEUE |
; call dequeue |
; cmp ax, NO_BUFFER |
; je .error |
push eax |
1152,7 → 1219,7 |
push ecx |
mov bl, TH_ACK |
stdcall build_tcp_Packet, [sockAddr] |
; stdcall build_tcp_Packet, [sockAddr] |
pop ecx |
; Check destination IP address. |
1161,24 → 1228,24 |
pop ebx |
push ecx |
mov eax, NET1OUT_QUEUE |
; mov eax, NET1OUT_QUEUE |
;;; TODO: get device id in edx |
xor edx, edx |
shl edx, 2 |
mov edx, [IP_LIST+edx] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
; mov ecx, [sockAddr] |
; cmp edx, [ecx + SOCKET.RemoteIP] |
; jne .not_local |
; mov eax, IPIN_QUEUE |
.not_local: |
pop ecx |
push ebx ; save ipbuffer number |
call queue |
;;;; call queue |
mov esi, [sockAddr] |
; mov esi, [sockAddr] |
; increament SND.NXT in socket |
; Amount to increment by is in ecx |
1193,7 → 1260,7 |
mov ecx, 0 |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
; cmp ecx, NUMRESENDENTRIES |
je .exit ; None found |
cmp dword[esi + 4], 0 |
je @f ; found one |
1211,7 → 1278,7 |
; retry time |
; fill IP buffer associated with this descriptor |
stdcall net_socket_addr_to_num, [sockAddr] |
; stdcall net_socket_addr_to_num, [sockAddr] |
mov [esi + 4], eax |
mov byte[esi + 1], TCP_RETRIES |
mov word[esi + 2], TCP_TIMEOUT |
1218,21 → 1285,21 |
inc ecx |
; Now get buffer location, and copy buffer across. argh! more copying,, |
mov edi, resendBuffer - IPBUFFSIZE |
; mov edi, resendBuffer - IPBUFFSIZE |
@@: add edi, IPBUFFSIZE |
; @@: add edi, IPBUFFSIZE |
loop @b |
; 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 |
; mov ecx, IPBUFFSIZE |
; mul ecx |
; add eax, IPbuffs |
; mov esi, eax |
; do copy |
mov ecx, IPBUFFSIZE |
; mov ecx, IPBUFFSIZE |
; cld |
rep movsb |
1243,7 → 1310,7 |
.error: |
or eax, -1 |
ret |
endp |
;endp |
1262,10 → 1329,10 |
checksum: |
pusha |
mov eax, [checkAdd1] |
; mov eax, [checkAdd1] |
xor edx, edx ; edx is the accumulative checksum |
xor ebx, ebx |
mov cx, [checkSize1] |
; mov cx, [checkSize1] |
shr cx, 1 |
jz cs1_1 |
1279,7 → 1346,7 |
loopw cs1 |
cs1_1: |
and word [checkSize1], 0x01 |
; and word [checkSize1], 0x01 |
jz cs_test2 |
mov bh, [eax] |
1288,11 → 1355,11 |
add edx, ebx |
cs_test2: |
mov cx, [checkSize2] |
; mov cx, [checkSize2] |
cmp cx, 0 |
jz cs_exit ; Finished if no 2nd buffer |
mov eax, [checkAdd2] |
; mov eax, [checkAdd2] |
shr cx, 1 |
jz cs2_1 |
1307,7 → 1374,7 |
loopw cs2 |
cs2_1: |
and word [checkSize2], 0x01 |
; and word [checkSize2], 0x01 |
jz cs_exit |
mov bh, [eax] |
1326,21 → 1393,7 |
add edx, eax |
not dx |
mov [checkResult], dx |
; mov [checkResult], dx |
popa |
ret |
TCP_HANDLER: |
;;; TODO: write code here |
call kernel_free |
add esp, 4 ; pop (balance stack) |
ret |
/kernel/branches/net/network/udp.inc |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; UDP.INC ;; |
73,7 → 73,7 |
; |
;----------------------------------------------------------------- |
UDP_Handler: |
UDP_handler: |
DEBUGF 1,"UDP_Handler\n" |
; TODO: First validate the header & checksum. Discard buffer if error |
110,7 → 110,6 |
@@: |
DEBUGF 1,"Found valid UDP packet for socket %x\n", esi |
; sub ecx, UDP_Packet.Data ; get # of bytes in ecx |
; mov eax, ecx |
199,12 → 198,12 |
; IN: eax = dest ip |
; ebx = source ip |
; ecx = data length |
; edx = remote port shl 16 + local port |
; edx = remote port shl 16 + local port (both in INET order) |
; esi = data offset |
; |
;----------------------------------------------------------------- |
UDP_create_Packet: |
UDP_create_packet: |
DEBUGF 1,"Create UDP Packet\n" |
215,13 → 214,13 |
; dx = fragment id |
call IPv4_create_Packet ; TODO: figure out a way to choose between IPv4 and IPv6 |
call IPv4_create_packet ; TODO: figure out a way to choose between IPv4 and IPv6 |
cmp edi, -1 |
je .exit |
sub ecx , UDP_Packet.Data |
mov byte[edi + UDP_Packet.Length], ch |
mov byte[edi + UDP_Packet.Length+1], cl |
sub ecx , UDP_Packet.Data |
pop esi |
push edi |
235,8 → 234,8 |
pop edi |
pop ecx |
bswap ecx ; convert little endian - big endian |
rol ecx, 16 ; |
; bswap ecx ; convert little endian - big endian |
; rol ecx, 16 ; |
mov dword [edi + UDP_Packet.SourcePort], ecx ; notice: we write both port's at once |