Subversion Repositories Kolibri OS

Rev

Rev 2 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ha 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;;  STACK.INC                                                      ;;
4
;;                                                                 ;;
5
;;  TCP/IP stack for Menuet OS                                     ;;
6
;;                                                                 ;;
7
;;  Version 0.7  4th July 2004                                     ;;
8
;;                                                                 ;;
9
;;  Copyright 2002 Mike Hibbett, mikeh@oceanfree.net               ;;
10
;;                                                                 ;;
11
;;  See file COPYING for details                                   ;;
12
;;                                                                 ;;
13
;; Version 0.7                                                     ;;
14
;;         Added a timer per socket to allow delays when rx window ;;
15
;;         gets below 1KB                                          ;;
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
 
18
 
19
;*******************************************************************
20
;   Interface
21
;      The interfaces defined in ETHERNET.INC plus:
22
;      stack_init
23
;      stack_handler
24
;      app_stack_handler
25
;      app_socket_handler
26
;      checksum
27
;
28
;*******************************************************************
29
 
30
 
31
 
32
;
33
;   IP Packet after reception - Normal IP packet format
34
;
35
;    0                   1                   2                   3
36
;    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
37
;
38
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39
;0  |Version|  IHL  |Type of Service|       Total Length            |
40
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41
;4  |         Identification        |Flags|      Fragment Offset    |
42
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43
;8  |  Time to Live |    Protocol   |         Header Checksum       |
44
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45
;12 |                       Source Address                          |
46
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47
;16 |                    Destination Address                        |
48
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49
;   |      Data                                                     |
50
;   +-+-+-..........                                               -+
51
 
52
 
53
;   TCP Payload ( Data field in IP datagram )
54
;
55
;    0                   1                   2                   3
56
;    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
57
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58
;20 |          Source Port          |       Destination Port        |
59
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60
;24 |                        Sequence Number                        |
61
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62
;28 |                    Acknowledgment Number                      |
63
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64
;32 |  Data |           |U|A|P|R|S|F|                               |
65
;   | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
66
;   |       |           |G|K|H|T|N|N|                               |
67
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68
;36 |           Checksum            |         Urgent Pointer        |
69
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70
;40 |                    Options                    |    Padding    |
71
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72
;   |                             data
73
 
74
 
75
;
76
;   UDP Payload ( Data field in IP datagram )
77
;
78
;    0                   1                   2                   3
79
;    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
80
;
81
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
82
;   |       Source Port             |      Destination Port         |
83
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
84
;   | Length ( UDP Header + Data )  |           Checksum            |
85
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86
;   |       UDP Data                                                |
87
;   +-+-+-..........                                               -+
88
;
89
 
90
 
91
;
92
;  Socket Descriptor + Buffer
93
;
94
;    0                   1                   2                   3
95
;    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
96
;
97
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
98
;   |                    Status ( of this buffer )                  |
99
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100
;   |  Application Process ID                                       |
101
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102
;   |                  Local IP Address                             |
103
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104
;   | Local IP Port                 | Unused ( set to 0 )           |
105
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106
;   |                  Remote IP Address                            |
107
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108
;   | Remote IP Port                | Unused ( set to 0 )           |
109
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110
; 24|   Rx Data Count                                   INTEL format|
111
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
112
; 28|                 TCB STATE                         INTEL format|
113
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
114
; 32|   TCB Timer (seconds)                             INTEL format|
115
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
116
; 36| ISS (Inital Sequence # used by this connection )   INET format|
117
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
118
; 40| IRS ( Inital Receive Sequence # )                  INET format|
119
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
120
; 44| SND.UNA  Seq # of unack'ed sent packets            INET format|
121
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122
; 48| SND.NXT  Next send seq # to use                    INET format|
123
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
124
; 52| SND.WND  Send window                               INET format|
125
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
126
; 56| RCV.NXT  Next expected receive sequence #          INET format|
127
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
128
; 60| RCV.WND  Receive window                            INET format|
129
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
130
; 64| SEG.LEN  Segment length                           INTEL format|
131
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
132
; 68| SEG.WND  Segment window                           INTEL format|
133
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
134
; 72| Retransmit queue # NOW WINDOW SIZE TIMER          INTEL format|
135
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
136
; 76|       RX Data                                                 |
137
;   +-+-+-..........                                               -+
138
 
139
 
140
 
141
; IP protocol numbers
142
PROTOCOL_ICMP     equ      1
143
PROTOCOL_TCP      equ      6
144
PROTOCOL_UDP      equ      17
145
 
146
 
147
; TIPBUFF status values
148
BUFF_EMPTY         equ     0
149
BUFF_RX_FULL       equ     1
150
BUFF_ALLOCATED     equ     2
151
BUFF_TX_FULL       equ     3
152
 
153
NUM_IPBUFFERS      equ     20    ; buffers allocated for TX/RX
154
 
155
SOCK_EMPTY         equ     0        ; socket not in use
156
SOCK_OPEN          equ     1        ; open issued, but no data sent
157
 
158
; TCP opening modes
159
SOCKET_PASSIVE     equ     0
160
SOCKET_ACTIVE      equ     1
161
 
162
; TCP TCB states
163
TCB_LISTEN         equ        1
164
TCB_SYN_SENT       equ        2
165
TCB_SYN_RECEIVED   equ        3
166
TCB_ESTABLISHED    equ        4
167
TCB_FIN_WAIT_1     equ        5
168
TCB_FIN_WAIT_2     equ        6
169
TCB_CLOSE_WAIT     equ        7
170
TCB_CLOSING        equ        8
171
TCB_LAST_ACK       equ        9
172
TCB_TIME_WAIT      equ        10
173
TCB_CLOSED         equ        11
174
 
175
TWOMSL              equ     10      ; # of secs to wait before closing socket
176
 
177
; socket buffers
178
SOCKETBUFFSIZE     equ        4096  ; state + config + buffer.
179
SOCKETHEADERSIZE   equ        76    ; thus 4096 - SOCKETHEADERSIZE bytes data
180
 
181
NUM_SOCKETS        equ        16    ; Number of open sockets supported. Was 20
182
 
183
 
184
NUMQUEUES          equ        4
185
EMPTY_QUEUE        equ        0
186
IPIN_QUEUE         equ        1
187
IPOUT_QUEUE        equ        2
188
NET1OUT_QUEUE      equ        3
189
 
190
NO_BUFFER          equ        0xFFFF
191
IPBUFFSIZE         equ        1500                ; MTU of an ethernet packet
192
NUMQUEUEENTRIES    equ        NUM_IPBUFFERS
193
NUMRESENDENTRIES    equ         18              ; Buffers for TCP resend packets
194
TCP_RETRIES         equ         5               ; Number of times to resend a packet
195
TCP_TIMEOUT         equ         10              ; resend if not replied to in x hs
196
 
197
; These are the 0x40 function codes for application access to the stack
198
STACK_DRIVER_STATUS  equ   52
199
SOCKET_INTERFACE     equ   53
200
 
201
 
202
; 128KB allocated for the stack and network driver buffers and other
203
; data requirements
204
stack_data_start     equ   0x700000
205
eth_data_start       equ   0x700000
206
stack_data           equ   0x704000
207
stack_data_end       equ   0x71ffff
208
 
209
; 32 bit word
210
stack_config         equ   stack_data
211
; 32 bit word - IP Address in network format
212
stack_ip             equ   stack_data + 4
213
; 1 byte. 0 == inactive, 1 = active
214
slip_active          equ   stack_data + 8       ; no longer used
215
; 1 byte. 0 == inactive, 1 = active
216
ethernet_active      equ   stack_data + 9
217
unused               equ   stack_data + 10
218
;  word. Buffer number, -1 if none
219
rx_buff_ptr          equ   stack_data + 12
220
; dword. Buffer number, -1 if none
221
tx_buff_ptr          equ   stack_data + 16
222
; byte.
223
slip_rx_state        equ   stack_data + 20      ; no longer used
224
; byte
225
slip_tx_state        equ   stack_data + 21      ; no longer used
226
; dword. Index into data
227
rx_data_ptr          equ   stack_data + 22
228
; dword. Index into data
229
tx_data_ptr          equ   stack_data + 26
230
; word. Count of bytes to send
231
tx_msg_len           equ   stack_data + 30
232
; Address of selected socket
233
sktAddr              equ   stack_data + 32
234
; Parameter to checksum routine - data ptr
235
checkAdd1            equ   stack_data + 36
236
; Parameter to checksum routine - 2nd data ptr
237
checkAdd2            equ   stack_data + 40
238
; Parameter to checksum routine - data size
239
checkSize1           equ   stack_data + 44
240
; Parameter to checksum routine - 2nd data size
241
checkSize2           equ   stack_data + 46
242
; result of checksum routine
243
checkResult          equ   stack_data + 48
244
 
245
; holds the TCP/UDP pseudo header. SA|DA|0|prot|UDP len|
246
pseudoHeader         equ   stack_data + 50
247
 
248
; receive and transmit IP buffer allocation
249
sockets              equ   stack_data + 62
250
Next_free2           equ   sockets + (SOCKETBUFFSIZE * NUM_SOCKETS)
251
; 1560 byte buffer for rx / tx ethernet packets
252
Ether_buffer         equ   Next_free2
253
Next_free3           equ   Ether_buffer + 1560
254
last_1sTick          equ   Next_free3
255
IPbuffs              equ   Next_free3 + 1
256
queues               equ   IPbuffs + ( NUM_IPBUFFERS * IPBUFFSIZE )
257
queueList            equ   queues + (2 * NUMQUEUES)
258
last_1hsTick         equ   queueList + ( 2 * NUMQUEUEENTRIES )
259
 
260
;resendQ              equ   queueList + ( 2 * NUMQUEUEENTRIES )
261
;resendBuffer         equ    resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP
262
;                    equ    resendBuffer + ( IPBUFFSIZE * NUMRESENDENTRIES )
263
 
264
 
265
 
266
resendQ             equ     0x770000
267
resendBuffer        equ     resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP
268
 
269
 
270
;***************************************************************************
271
;   Function
272
;      stack_init
273
;
274
;   Description
275
;      Clear all allocated memory to zero. This ensures that
276
;       on startup, the stack is inactive, and consumes no resources
277
;       This is a kernel function, called prior to the OS main loop
278
;       in set_variables
279
;
280
;***************************************************************************
281
stack_init:
282
    xor     eax,eax
283
    mov     edi,stack_data_start
284
    mov     ecx,0x20000 / 4  ; Assume that we have 128KB of data
285
    cld
286
    rep     stosd
287
 
288
    ; Initialise TCP resend queue data structures
289
    mov     eax, 0xFFFFFFFF
290
    mov     edi, resendQ
291
    mov     ecx, NUMRESENDENTRIES  ; 1 dword per entry
292
    cld
293
    rep     stosd
294
 
295
 
296
    mov     eax, 0xFFFFFFFF
297
    mov     [rx_buff_ptr], eax
298
    mov     [tx_buff_ptr], eax
299
 
300
    ; Put in some defaults : slip, 0x3f8, 4, ip=192.168.1.22
301
    ; Saves me entering them each boot up when debugging
302
    mov     eax, 0x03f80401
303
    mov     [stack_config], eax
304
    mov     eax, 0xc801a8c0
305
    mov     [stack_ip], eax
306
 
307
    call    queueInit
308
 
309
    ; The following block sets up the 1s timer
310
    mov     al,0x0
311
    out     0x70,al
312
    in      al,0x71
313
    mov     [last_1sTick], al
314
 
315
    ret
316
 
317
 
318
 
319
;***************************************************************************
320
;   Function
321
;      stack_handler
322
;
323
;   Description
324
;       The kernel loop routine for the stack
325
;       This is a kernel function, called in the main loop
326
;
327
;***************************************************************************
328
stack_handler:
329
 
330
    call    ethernet_driver
331
    call    ip_rx
332
 
333
 
334
    ; Test for 10ms tick, call tcp timer
335
    mov     eax, [timer_ticks] ;[0xfdf0]
336
    cmp     eax, [last_1hsTick]
337
    je      sh_001
338
 
339
    mov     [last_1hsTick], eax
340
    call    tcp_tx_handler
341
 
342
sh_001:
343
 
344
    ; Test for 1 second event, call 1s timer functions
345
    mov     al,0x0   ;second
346
    out     0x70,al
347
    in      al,0x71
348
    cmp     al, [last_1sTick]
349
    je      sh_exit
350
 
351
    mov     [last_1sTick], al
352
 
353
    call    arp_timer
354
    call    tcp_tcb_handler
355
 
356
sh_exit:
357
    ret
358
 
359
 
360
 
361
 
362
;***************************************************************************
363
;   Function
364
;      is_localport_unused
365
;
366
;   Description
367
;         scans through all the active sockets , looking to see if the
368
;      port number specified in bx is in use as a localport number.
369
;      This is useful when you want a to generate a unique local port
370
;      number.
371
;          On return, eax = 1 for free, 0 for in use
372
;
373
;***************************************************************************
374
is_localport_unused:
375
    mov     al, bh
376
    mov     ah, bl
377
    mov     bx, ax
378
 
379
    mov     edx, SOCKETBUFFSIZE * NUM_SOCKETS
380
    mov     ecx, NUM_SOCKETS
381
    mov     eax, 0                    ; Assume the return value is 'in use'
382
 
383
ilu1:
384
    sub     edx, SOCKETBUFFSIZE
385
    cmp     [edx + sockets + 12], bx
386
    loopnz  ilu1                  ; Return back if the socket is occupied
387
 
388
    jz      ilu_exit
389
    inc     eax                         ; return port not in use
390
 
391
ilu_exit:
392
    ret
393
 
394
 
395
 
396
;***************************************************************************
397
;   Function
398
;      get_free_socket
399
;
400
;   Description
401
;
402
;***************************************************************************
403
get_free_socket:
404
    push    ecx
405
    mov     eax, SOCKETBUFFSIZE * NUM_SOCKETS
406
    mov     ecx, NUM_SOCKETS
407
 
408
gfs1:
409
    sub     eax, SOCKETBUFFSIZE
410
    cmp     [eax + sockets], dword SOCK_EMPTY
411
    loopnz  gfs1                  ; Return back if the socket is occupied
412
    mov     eax, ecx
413
    pop     ecx
414
    jz      gfs_exit
415
    mov     eax, 0xFFFFFFFF
416
 
417
gfs_exit:
418
    ret
419
 
420
 
421
 
422
;***************************************************************************
423
;   Function
424
;      checksum
425
;
426
;   Description
427
;       checkAdd1,checkAdd2, checkSize1, checkSize2, checkResult
428
;       Dont break anything; Most registers are used by the caller
429
;       This code is derived from the 'C' source, cksum.c, in the book
430
;       Internetworking with TCP/IP Volume II by D.E. Comer
431
;
432
;***************************************************************************
433
checksum:
434
    pusha
435
 
436
    xor     edx, edx                  ; edx is the accumulative checksum
437
    xor     ebx, ebx
438
    mov     cx, [checkSize1]
439
    shr     cx, 1
440
    jz      cs1_1
441
 
442
    mov     eax, [checkAdd1]
443
 
444
cs1:
445
    mov     bh, [eax]
446
    mov     bl, [eax + 1]
447
 
448
    add     eax, 2
449
    add     edx, ebx
450
 
451
    loopw   cs1
452
 
453
cs1_1:
454
    and     word [checkSize1], 0x01
455
    jz      cs_test2
456
 
457
    mov     bh, [eax]
458
    xor     bl, bl
459
 
460
    add     edx, ebx
461
 
462
cs_test2:
463
    mov     cx, [checkSize2]
464
    cmp     cx, 0
465
    jz      cs_exit                     ; Finished if no 2nd buffer
466
 
467
    shr     cx, 1
468
    jz      cs2_1
469
 
470
    mov     eax, [checkAdd2]
471
 
472
cs2:
473
    mov     bh, [eax]
474
    mov     bl, [eax + 1]
475
 
476
    add     eax, 2
477
    add     edx, ebx
478
 
479
    loopw   cs2
480
 
481
cs2_1:
482
    and     word [checkSize2], 0x01
483
    jz      cs_exit
484
 
485
    mov     bh, [eax]
486
    xor     bl, bl
487
 
488
    add     edx, ebx
489
 
490
cs_exit:
491
    mov     ebx, edx
492
 
493
    shr     ebx, 16
494
    and     edx, 0xffff
495
    add     edx, ebx
496
    mov     eax, edx
497
    shr     eax, 16
498
    add     edx, eax
499
    not     dx
500
 
501
    mov     [checkResult], dx
502
    popa
503
    ret
504
 
505
 
506
 
507
 
508
;***************************************************************************
509
;   Function
510
;      app_stack_handler
511
;
512
;   Description
513
;       This is an application service, called by int 0x40 fn 52
514
;       It provides application access to the network interface layer
515
;
516
;***************************************************************************
517
app_stack_handler:
518
    cmp     eax, 0
519
    jnz     not0
520
    ; Read the configuartion word
521
    mov     eax, [stack_config]
522
    ret
523
 
524
not0:
525
    cmp     eax, 1
526
    jnz     not1
527
    ; read the IP address
528
 
529
    mov     eax, [stack_ip]
530
    ret
531
 
532
not1:
533
    cmp     eax, 2
534
    jnz     not2
535
 
536
    ; write the configuration word
537
    mov     [stack_config], ebx
538
 
539
    ; 
540
    ; If ethernet now enabled, probe for the card, reset it and empty
541
    ; the packet buffer
542
    ; If all successfull, enable the card.
543
    ; If ethernet now disabled, set it as disabled. Should really
544
    ; empty the tcpip data area too.
545
 
546
    ; ethernet interface is '3' in ls 7 bits
547
    and     bl, 0x7f
548
    cmp     bl, 3
549
 
550
    je       ash_eth_enable
551
    ; Ethernet isn't enabled, so make sure that the card is disabled
552
    mov     [ethernet_active], byte 0
553
 
554
    ret
555
 
556
ash_eth_enable:
557
    ; Probe for the card. This will reset it and enable the interface
558
    ; if found
559
    call    eth_probe
560
    cmp     eax, 0
561
    je      ash_eth_done            ; Abort if no hardware found
562
 
563
    mov     [ethernet_active], byte 1
564
 
565
ash_eth_done:
566
    ret
567
 
568
not2:
569
    cmp     eax, 3
570
    jnz     not3
571
    ; write the IP Address
572
    mov     [stack_ip], ebx
573
    ret
574
 
575
not3:
576
    cmp     eax, 4
577
    jnz     not4
578
    ; Enabled the slip driver on the comm port
579
    ; slip removed
580
    ret
581
 
582
not4:
583
    cmp     eax, 5
584
    jnz     not5
585
    ; Disable the slip driver on the comm port
586
    ; slip removed
587
 
588
not5:
589
    cmp     eax, 6
590
    jnz     not6
591
 
592
    ; Insert an IP packet into the stacks received packet queue
593
    call    stack_insert_packet
594
    ret
595
 
596
not6:
597
    cmp     eax, 7
598
    jnz     not7
599
 
600
    ; Test for any packets queued for transmission over the network
601
 
602
not7:
603
    cmp     eax, 8
604
    jnz     not8
605
 
606
    call    stack_get_packet
607
    ; Extract a packet queued for transmission by the network
608
    ret
609
 
610
not8:
611
    cmp     eax, 9
612
    jnz     not9
613
 
614
    ; read the gateway IP address
615
 
616
    mov     eax, [gateway_ip]
617
    ret
618
 
619
not9:
620
    cmp     eax, 10
621
    jnz     not10
622
 
623
    ; read the subnet mask
624
 
625
    mov     eax, [subnet_mask]
626
    ret
627
 
628
not10:
629
    cmp     eax, 11
630
    jnz     not11
631
 
632
    ; write the gateway IP Address
633
    mov     [gateway_ip], ebx
634
 
635
    ret
636
 
637
not11:
638
    cmp     eax, 12
639
    jnz     not12
640
 
641
    ; write the subnet mask
642
    mov     [subnet_mask], ebx
643
 
644
 
645
not12:
646
    cmp     eax, 13
647
    jnz     not13
648
 
649
    ; read the dns
650
 
651
    mov     eax, [dns_ip]
652
    ret
653
 
654
not13:
655
    cmp     eax, 14
656
    jnz     stack_driver_end
657
 
658
    ; write the dns IP Address
659
    mov     [dns_ip], ebx
660
 
661
    ret
662
 
663
stack_driver_end:
664
    ret
665
 
666
 
667
 
668
;***************************************************************************
669
;   Function
670
;      app_socket_handler
671
;
672
;   Description
673
;       This is an application service, called by int 0x40
674
;       It provides application access to stack socket services
675
;       such as opening sockets
676
;
677
;***************************************************************************
678
app_socket_handler:
679
    cmp     eax, 0
680
    jnz     nots0
681
 
682
    call    socket_open
683
    ret
684
 
685
nots0:
686
    cmp     eax, 1
687
    jnz     nots1
688
 
689
    call    socket_close
690
    ret
691
 
692
nots1:
693
    cmp     eax, 2
694
    jnz     nots2
695
 
696
    call    socket_poll
697
    ret
698
 
699
nots2:
700
    cmp     eax, 3
701
    jnz     nots3
702
 
703
    call    socket_read
704
    ret
705
 
706
nots3:
707
    cmp     eax, 4
708
    jnz     nots4
709
 
710
    call    socket_write
711
    ret
712
 
713
nots4:
714
    cmp     eax, 5
715
    jnz     nots5
716
 
717
    call    socket_open_tcp
718
    ret
719
 
720
nots5:
721
    cmp     eax, 6
722
    jnz     nots6
723
 
724
    call    socket_status
725
    ret
726
 
727
nots6:
728
    cmp     eax, 7
729
    jnz     nots7
730
 
731
    call    socket_write_tcp
732
    ret
733
 
734
nots7:
735
    cmp     eax, 8
736
    jnz     nots8
737
 
738
    call    socket_close_tcp
739
    ret
740
 
741
nots8:
742
    cmp     eax, 9
743
    jnz     nots9
744
 
745
    call    is_localport_unused
746
    ret
747
 
748
nots9:
749
    cmp     eax, 254
750
    jnz     notdump
751
 
752
    ret
753
 
754
notdump:
755
    cmp     eax, 255
756
    jnz     notsdebug
757
 
758
    ; This sub function allows access to debugging information on the stack
759
    ; ebx holds the request:
760
    ;  100 : return length of empty queue
761
    ;  101 : return length of IPOUT QUEUE
762
    ;  102 : return length of IPIN QUEUE
763
    ;  103 : return length of NET1OUT QUEUE
764
    ; 200 : return # of ARP entries
765
    ; 201 : return size of ARP table ( max # entries )
766
    ; 202 : select ARP table entry #
767
    ; 203 : return IP of selected table entry
768
    ; 204 : return High 4 bytes of MAC address of selected table entry
769
    ; 205 : return low  2 bytes of MAC address of selected table entry
770
    ; 206 : return status word of selected table entry
771
    ; 207 : return Time to live of selected table entry
772
 
773
 
774
    ;  2 : return number of IP packets received
775
    ;  3 : return number of packets transmitted
776
    ;  4 : return number of received packets dumped
777
    ;  5 : return number of arp packets received
778
    ;  6 : return status of packet driver
779
    ;      ( 0 == not active, FFFFFFFF = successful )
780
 
781
    call    stack_internal_status
782
    ret
783
 
784
notsdebug:
785
    ; Invalid Option
786
    ret
787
 
788
 
789
uglobal
790
  ARPTmp:
791
  times 14 db 0
792
endg
793
 
794
;***************************************************************************
795
;   Function
796
;      stack_internal_status
797
;
798
;   Description
799
;       Returns information about the internal status of the stack
800
;       This is only useful for debugging
801
;       It works with the ethernet driver
802
;       sub function in ebx
803
;       return requested data in eax
804
;
805
;***************************************************************************
806
stack_internal_status:
807
    cmp     ebx, 100
808
    jnz     notsis100
809
 
810
    ;  100 : return length of EMPTY QUEUE
811
    mov     ebx, EMPTY_QUEUE
812
    call    queueSize
813
    ret
814
 
815
notsis100:
816
    cmp     ebx, 101
817
    jnz     notsis101
818
 
819
    ;  101 : return length of IPOUT QUEUE
820
    mov     ebx, IPOUT_QUEUE
821
    call    queueSize
822
    ret
823
 
824
notsis101:
825
    cmp     ebx, 102
826
    jnz     notsis102
827
 
828
    ;  102 : return length of IPIN QUEUE
829
    mov     ebx, IPIN_QUEUE
830
    call    queueSize
831
    ret
832
 
833
notsis102:
834
    cmp     ebx, 103
835
    jnz     notsis103
836
 
837
    ;  103 : return length of NET1OUT QUEUE
838
    mov     ebx, NET1OUT_QUEUE
839
    call    queueSize
840
    ret
841
 
842
notsis103:
843
    cmp     ebx, 200
844
    jnz     notsis200
845
 
846
    ; 200 : return num entries in arp table
847
    movzx   eax, byte [NumARP]
848
    ret
849
 
850
notsis200:
851
    cmp     ebx, 201
852
    jnz     notsis201
853
 
854
    ; 201 : return arp table size
855
    mov     eax, 20 ; ARP_TABLE_SIZE
856
    ret
857
 
858
notsis201:
859
    cmp     ebx, 202
860
    jnz     notsis202
861
 
862
    ; 202 - read the requested table entry
863
    ; into a temporary buffer
864
    ; ecx holds the entry number
865
 
866
    mov     eax, ecx
867
    mov     ecx, 14 ; ARP_ENTRY_SIZE
868
    mul     ecx
869
 
870
    mov     ecx, [eax + ARPTable]
871
    mov     [ARPTmp], ecx
872
    mov     ecx, [eax + ARPTable+4]
873
    mov     [ARPTmp+4], ecx
874
    mov     ecx, [eax + ARPTable+8]
875
    mov     [ARPTmp+8], ecx
876
    mov     cx, [eax + ARPTable+12]
877
    mov     [ARPTmp+12], cx
878
    ret
879
 
880
notsis202:
881
    cmp     ebx, 203
882
    jnz     notsis203
883
 
884
    ; 203 - return IP address
885
    mov     eax, [ARPTmp]
886
    ret
887
 
888
notsis203:
889
    cmp     ebx, 204
890
    jnz     notsis204
891
 
892
    ; 204 - return MAC high dword
893
    mov     eax, [ARPTmp+4]
894
    ret
895
 
896
notsis204:
897
    cmp     ebx, 205
898
    jnz     notsis205
899
 
900
    ; 205 - return MAC ls word
901
    movzx   eax, word [ARPTmp+8]
902
    ret
903
 
904
notsis205:
905
    cmp     ebx, 206
906
    jnz     notsis206
907
 
908
    ; 206 - return status word
909
    movzx   eax, word [ARPTmp+10]
910
    ret
911
 
912
notsis206:
913
    cmp     ebx, 207
914
    jnz     notsis207
915
 
916
    ; 207 - return ttl word
917
    movzx   eax, word [ARPTmp+12]
918
    ret
919
 
920
notsis207:
921
    cmp     ebx, 2
922
    jnz     notsis2
923
 
924
    ;  2 : return number of IP packets received
925
    mov     eax, [ip_rx_count]
926
    ret
927
 
928
notsis2:
929
    cmp     ebx, 3
930
    jnz     notsis3
931
 
932
    ;  3 : return number of packets transmitted
933
    mov     eax, [ip_tx_count]
934
    ret
935
 
936
notsis3:
937
    cmp     ebx, 4
938
    jnz     notsis4
939
 
940
    ;  4 : return number of received packets dumped
941
    mov     eax, [dumped_rx_count]
942
    ret
943
 
944
notsis4:
945
    cmp     ebx, 5
946
    jnz     notsis5
947
 
948
    ;  5 : return number of arp packets received
949
    mov     eax, [arp_rx_count]
950
    ret
951
 
952
notsis5:
953
    cmp     ebx, 6
954
    jnz     notsis6
955
 
956
    ;  6 : return status of packet driver
957
    ;  ( 0 == not active, FFFFFFFF = successful )
958
    mov     eax, [eth_status]
959
    ret
960
 
961
notsis6:
962
    xor     eax, eax
963
    ret
964
 
965
 
966
 
967
;***************************************************************************
968
;   Function
969
;      stack_get_packet
970
;
971
;   Description
972
;       extracts an IP packet from the NET1 output queue
973
;       and sends the data to the calling process
974
;       pointer to data in edx
975
;       returns number of bytes read in eax
976
;
977
;***************************************************************************
978
stack_get_packet:
979
    ; Look for a buffer to tx
980
    mov     eax, NET1OUT_QUEUE
981
    call    dequeue
982
    cmp     ax, NO_BUFFER
983
    je      sgp_non_exit            ; Exit if no buffer available
984
 
985
    push    eax                     ; Save buffer number for freeing at end
986
 
987
    push    edx
988
    ; convert buffer pointer eax to the absolute address
989
    mov     ecx, IPBUFFSIZE
990
    mul     ecx
991
    add     eax, IPbuffs
992
    pop     edx
993
 
994
    push    eax                     ; save address of IP data
995
 
996
    ; Get the address of the callers data
997
    mov     edi,[0x3010]
115 poddubny 998
    add     edi,TASKDATA.mem_start
1 ha 999
    add     edx,[edi]
1000
    mov     edi, edx
1001
 
1002
    pop     eax
1003
 
1004
    mov     ecx, 1500           ; should get the actual number of bytes to write
1005
    mov     esi, eax
1006
    cld
1007
    rep     movsb               ; copy the data across
1008
 
1009
    ; And finally, return the buffer to the free queue
1010
    pop     eax
1011
    call    freeBuff
1012
 
1013
    mov     eax, 1500
1014
    ret
1015
 
1016
sgp_non_exit:
1017
    xor     eax, eax
1018
    ret
1019
 
1020
 
1021
 
1022
;***************************************************************************
1023
;   Function
1024
;      stack_insert_packet
1025
;
1026
;   Description
1027
;       writes an IP packet into the stacks receive queue
1028
;       # of bytes to write in ecx
1029
;       pointer to data in edx
1030
;       returns 0 in eax ok, -1 == failed
1031
;
1032
;***************************************************************************
1033
stack_insert_packet:
1034
 
1035
    mov     eax, EMPTY_QUEUE
1036
    call    dequeue
1037
    cmp     ax, NO_BUFFER
1038
    je      sip_err_exit
1039
 
1040
    push    eax
1041
 
1042
    ; save the pointers to the data buffer & size
1043
    push    edx
1044
    push    ecx
1045
 
1046
    ; convert buffer pointer eax to the absolute address
1047
    mov     ecx, IPBUFFSIZE
1048
    mul     ecx
1049
    add     eax, IPbuffs
1050
 
1051
    mov     edx, eax
1052
 
1053
    ; So, edx holds the IPbuffer ptr
1054
 
1055
    pop     ecx                     ; count of bytes to send
1056
    mov     ebx, ecx                ; need the length later
1057
    pop     eax                     ; get callers ptr to data to send
1058
 
1059
    ; Get the address of the callers data
1060
    mov     edi,[0x3010]
115 poddubny 1061
    add     edi,TASKDATA.mem_start
1 ha 1062
    add     eax,[edi]
1063
    mov     esi, eax
1064
 
1065
    mov     edi, edx
1066
    cld
1067
    rep     movsb               ; copy the data across
1068
 
1069
    pop     ebx
1070
 
1071
    mov     eax, IPIN_QUEUE
1072
    call    queue
1073
 
1074
    inc     dword [ip_rx_count]
1075
 
1076
    mov     eax, 0
1077
    ret
1078
 
1079
sip_err_exit:
1080
    mov     eax, 0xFFFFFFFF
1081
    ret
1082
 
1083
 
1084
 
1085
;***************************************************************************
1086
;   Function
1087
;      socket_open
1088
;
1089
;   Description
1090
;       find a free socket
1091
;       local port in ebx
1092
;       remote port in ecx
1093
;       remote ip in edx
1094
;       return socket # in eax, -1 if none available
1095
;
1096
;***************************************************************************
1097
socket_open:
1098
    call    get_free_socket
1099
 
1100
    cmp     eax, 0xFFFFFFFF
1101
    jz      so_exit
1102
 
1103
    ; ax holds the socket number that is free. Get real address
1104
    push    eax
1105
    shl     eax, 12
1106
    add     eax, sockets
1107
 
1108
    mov     [eax], dword SOCK_OPEN
1109
 
1110
    mov     [eax + 12], byte bh      ; Local port ( LS 16 bits )
1111
    mov     [eax + 13], byte bl      ; Local port ( LS 16 bits )
1112
    mov     ebx, [stack_ip]
1113
    mov     [eax + 8], ebx         ; Local IP
1114
    mov     [eax + 20], ch         ; Remote Port ( LS 16 bits )
1115
    mov     [eax + 21], cl         ; Remote Port ( LS 16 bits )
1116
    mov     [eax + 16], edx         ; Remote IP ( in Internet order )
1117
    mov     [eax + 24], dword 0      ; recieved data count
1118
 
1119
    mov     esi, [0x3010]
115 poddubny 1120
    mov     ebx, [esi+TASKDATA.pid]
1 ha 1121
    mov     [eax + 4], ebx         ; save the process ID
1122
    pop     eax      ; Get the socket number back, so we can return it
1123
 
1124
so_exit:
1125
    ret
1126
 
1127
 
1128
 
1129
;***************************************************************************
1130
;   Function
1131
;      socket_open_tcp
1132
;
1133
;   Description
1134
;       Opens a TCP socket in PASSIVE or ACTIVE mode
1135
;       find a free socket
1136
;       local port in ebx ( intel format )
1137
;       remote port in ecx ( intel format )
1138
;       remote ip in edx ( in Internet byte order )
1139
;       Socket open mode in esi  ( SOCKET_PASSIVE or SOCKET_ACTIVE )
1140
;       return socket # in eax, -1 if none available
1141
;
1142
;***************************************************************************
1143
socket_open_tcp:
1144
    call    get_free_socket
1145
 
1146
    cmp     eax, 0xFFFFFFFF
1147
    jz      so_exit
1148
 
1149
    ; ax holds the socket number that is free. Get real address
1150
    push    eax
1151
    shl     eax, 12
1152
    add     eax, sockets
1153
 
1154
    mov     [sktAddr], eax
1155
    mov     [eax], dword SOCK_OPEN
1156
 
1157
    ; TODO - check this works!
1158
    mov     [eax + 72], dword 0     ; Reset the window timer.
1159
 
1160
    mov     [eax + 12], byte bh      ; Local port ( LS 16 bits )
1161
    mov     [eax + 13], byte bl      ; Local port ( LS 16 bits )
1162
    mov     ebx, [stack_ip]
1163
    mov     [eax + 8], ebx         ; Local IP
1164
    mov     [eax + 20], ch         ; Remote Port ( LS 16 bits )
1165
    mov     [eax + 21], cl         ; Remote Port ( LS 16 bits )
1166
    mov     [eax + 16], edx         ; Remote IP ( in Internet order )
1167
    mov     [eax + 24], dword 0      ; recieved data count
1168
 
1169
    ; Now fill in TCB state
1170
    mov     ebx, TCB_LISTEN
1171
    cmp     esi, SOCKET_PASSIVE
1172
    jz      sot_001
1173
    mov     ebx, TCB_SYN_SENT
1174
 
1175
sot_001:
1176
    mov     [eax + 28], ebx            ; Indicate the state of the TCB
1177
 
1178
    mov     esi, [0x3010]
115 poddubny 1179
    mov     ecx, [esi+TASKDATA.pid]
1 ha 1180
    mov     [eax + 4], ecx         ; save the process ID
1181
 
1182
    cmp     ebx, TCB_LISTEN
1183
    je      sot_done
1184
 
1185
    ; Now, if we are in active mode, then we have to send a SYN to the specified remote port
1186
 
1187
 
1188
    mov     eax, EMPTY_QUEUE
1189
    call    dequeue
1190
    cmp     ax, NO_BUFFER
1191
    je      sot_done
1192
 
1193
    push    eax
1194
 
1195
    mov     bl, 0x02        ; SYN
1196
    mov     ecx, 0
1197
 
1198
    call    buildTCPPacket
1199
 
1200
    mov     eax, NET1OUT_QUEUE
1201
 
1202
    mov     edx, [stack_ip]
1203
    mov     ecx, [ sktAddr ]
1204
    mov     ecx, [ ecx + 16 ]
1205
    cmp     edx, ecx
1206
    jne     sot_notlocal
1207
    mov     eax, IPIN_QUEUE
1208
 
1209
sot_notlocal:
1210
       ; Send it.
1211
    pop     ebx
1212
    call    queue
1213
 
1214
    mov     esi, [sktAddr]
1215
 
1216
    ; increment SND.NXT in socket
1217
    add     esi, 48
1218
    call    inc_inet_esi
1219
 
1220
sot_done:
1221
    pop     eax      ; Get the socket number back, so we can return it
1222
 
1223
sot_exit:
1224
    ret
1225
 
1226
 
1227
 
1228
;***************************************************************************
1229
;   Function
1230
;      socket_close
1231
;
1232
;   Description
1233
;       socket # in ebx
1234
;       returns 0 for ok, -1 for socket not open (fail)
1235
;
1236
;***************************************************************************
1237
socket_close:
1238
    shl     ebx, 12
1239
    add     ebx, sockets
1240
    mov     eax, 0xFFFFFFFF         ; assume this operation will fail..
1241
    cmp     [ebx], dword SOCK_EMPTY
1242
    jz      sc_exit
1243
 
1244
    ; Clear the socket varaibles
1245
    xor     eax, eax
1246
    mov     edi,ebx
1247
    mov     ecx,SOCKETHEADERSIZE
1248
    cld
1249
    rep     stosb
1250
 
1251
sc_exit:
1252
    ret
1253
 
1254
 
1255
 
1256
;***************************************************************************
1257
;   Function
1258
;      socket_close_tcp
1259
;
1260
;   Description
1261
;       socket # in ebx
1262
;       returns 0 for ok, -1 for socket not open (fail)
1263
;
1264
;***************************************************************************
1265
socket_close_tcp:
1266
    ; first, remove any resend entries
1267
    pusha
1268
 
1269
    mov     esi, resendQ
1270
    mov     ecx, 0
1271
 
1272
sct001:
1273
    cmp     ecx, NUMRESENDENTRIES
1274
    je      sct003              ; None left
1275
    cmp     [esi], bl
1276
    je      sct002              ; found one
1277
    inc     ecx
1278
    add     esi, 4
1279
    jmp     sct001
1280
 
1281
sct002:
1282
    dec     dword [arp_rx_count] ; ************ TEST ONLY!
1283
 
1284
    mov     [esi], byte 0xFF
1285
    jmp     sct001
1286
 
1287
sct003:
1288
    popa
1289
 
1290
    shl     ebx, 12
1291
    add     ebx, sockets
1292
    mov     [sktAddr], ebx
1293
    mov     eax, 0xFFFFFFFF         ; assume this operation will fail..
1294
    cmp     [ebx], dword SOCK_EMPTY
1295
    jz      sct_exit
1296
 
1297
    ; Now construct the response, and queue for sending by IP
1298
    mov     eax, EMPTY_QUEUE
1299
    call    dequeue
1300
    cmp     ax, NO_BUFFER
1301
    je      stl_exit
1302
 
1303
    push    eax
1304
 
1305
    mov     bl, 0x11        ; FIN + ACK
1306
    mov     ecx, 0
1307
    mov     esi, 0
1308
 
1309
    call    buildTCPPacket
1310
 
1311
    mov     ebx, [sktAddr]
1312
 
1313
    ; increament SND.NXT in socket
1314
    mov     esi, 48
1315
    add     esi, ebx
1316
    call    inc_inet_esi
1317
 
1318
 
1319
    ; Get the socket state
1320
    mov     eax, [ebx + 28]
1321
    cmp     eax, TCB_LISTEN
1322
    je      destroyTCB
1323
    cmp     eax, TCB_SYN_SENT
1324
    je      destroyTCB
1325
    cmp     eax, TCB_SYN_RECEIVED
1326
    je      sct_finwait1
1327
    cmp     eax, TCB_ESTABLISHED
1328
    je      sct_finwait1
1329
 
1330
    ; assume CLOSE WAIT
1331
    ; Send a fin, then enter last-ack state
1332
    mov     eax, TCB_LAST_ACK
1333
    mov     [ebx + 28], eax
1334
    xor     eax, eax
1335
    jmp     sct_send
1336
 
1337
sct_finwait1:
1338
    ; Send a fin, then enter finwait2 state
1339
    mov     eax, TCB_FIN_WAIT_1
1340
    mov     [ebx + 28], eax
1341
    xor     eax, eax
1342
 
1343
sct_send:
1344
    mov     eax, NET1OUT_QUEUE
1345
 
1346
    mov     edx, [stack_ip]
1347
    mov     ecx, [ sktAddr ]
1348
    mov     ecx, [ ecx + 16 ]
1349
    cmp     edx, ecx
1350
    jne     sct_notlocal
1351
    mov     eax, IPIN_QUEUE
1352
 
1353
sct_notlocal:
1354
       ; Send it.
1355
    pop     ebx
1356
    call    queue
1357
    jmp     sct_exit
1358
 
1359
destroyTCB:
1360
    pop     eax
1361
    ; Clear the socket varaibles
1362
    xor     eax, eax
1363
    mov     edi,ebx
1364
    mov     ecx,SOCKETHEADERSIZE
1365
    cld
1366
    rep     stosb
1367
 
1368
sct_exit:
1369
    ret
1370
 
1371
 
1372
 
1373
;***************************************************************************
1374
;   Function
1375
;      socket_poll
1376
;
1377
;   Description
1378
;       socket # in ebx
1379
;       returns count in eax.
1380
;
1381
;***************************************************************************
1382
socket_poll:
1383
    shl     ebx, 12
1384
    add     ebx, sockets
1385
    mov     eax, [ebx + 24]
1386
 
1387
    ret
1388
 
1389
 
1390
 
1391
;***************************************************************************
1392
;   Function
1393
;      socket_status
1394
;
1395
;   Description
1396
;       socket # in ebx
1397
;       returns TCB state in eax.
1398
;
1399
;***************************************************************************
1400
socket_status:
1401
    shl     ebx, 12
1402
    add     ebx, sockets
1403
    mov     eax, [ebx + 28]
1404
 
1405
    ret
1406
 
1407
 
1408
 
1409
;***************************************************************************
1410
;   Function
1411
;      socket_read
1412
;
1413
;   Description
1414
;       socket # in ebx
1415
;       returns # of bytes remaining in eax, data in bl
1416
;
1417
;***************************************************************************
1418
socket_read:
1419
    shl     ebx, 12
1420
    add     ebx, sockets
1421
    mov     eax, [ebx + 24]         ; get count of bytes
1422
    mov     ecx,1
1423
    test    eax, eax
1424
    jz      sr2
1425
 
1426
    dec     eax
1427
    mov     esi, ebx            ; esi is address of socket
1428
    mov     [ebx + 24], eax         ; store new count
1429
    movzx   ebx, byte [ebx + SOCKETHEADERSIZE]  ; get the byte
1430
    add     esi, SOCKETHEADERSIZE
1431
    mov     edi, esi
1432
    inc     esi
1433
 
1434
    mov     ecx, (SOCKETBUFFSIZE - SOCKETHEADERSIZE) / 4
1435
    cld
1436
    rep     movsd
1437
    xor     ecx, ecx
1438
 
1439
sr1:
1440
    jmp     sor_exit
1441
 
1442
sr2:
1443
    xor     bl, bl
1444
 
1445
sor_exit:
1446
    ret
1447
 
1448
 
1449
 
1450
;***************************************************************************
1451
;   Function
1452
;      socket_write
1453
;
1454
;   Description
1455
;       socket in ebx
1456
;       # of bytes to write in ecx
1457
;       pointer to data in edx
1458
;       returns 0 in eax ok, -1 == failed ( invalid socket, or
1459
;       could not queue IP packet )
1460
;
1461
;***************************************************************************
1462
socket_write:
1463
    ; First, find the address of the socket descriptor
1464
    shl     ebx, 12
1465
    add     ebx, sockets         ; ebx = address of actual socket
1466
 
1467
    mov     eax, 0xFFFFFFFF
1468
    ; If the socket is invalid, return with an error code
1469
    cmp     [ebx], dword SOCK_EMPTY
1470
    je      sw_exit
1471
 
1472
 
1473
    mov     eax, EMPTY_QUEUE
1474
    call    dequeue
1475
    cmp     ax, NO_BUFFER
1476
    je      sw_exit
1477
 
1478
    ; Save the queue entry number
1479
    push    eax
1480
 
1481
    ; save the pointers to the data buffer & size
1482
    push    edx
1483
    push    ecx
1484
 
1485
    ; convert buffer pointer eax to the absolute address
1486
    mov     ecx, IPBUFFSIZE
1487
    mul     ecx
1488
    add     eax, IPbuffs
1489
 
1490
    mov     edx, eax
1491
 
1492
    ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
1493
 
1494
    ; Fill in the IP header ( some data is in the socket descriptor)
1495
    mov     eax, [ebx + 8]
1496
    mov     [edx + 12], eax      ; source IP
1497
    mov     eax, [ebx + 16]
1498
    mov     [edx + 16], eax      ; Destination IP
1499
 
1500
    mov     al, 0x45
1501
    mov     [edx], al         ; Version, IHL
1502
    xor     al, al
1503
    mov     [edx + 1], al     ; Type of service
1504
 
1505
    pop     eax                   ; Get the UDP data length
1506
    push    eax
1507
 
1508
    add     eax, 20 + 8           ; add IP header and UDP header lengths
1509
    mov     [edx + 2], ah
1510
    mov     [edx + 3], al
1511
    xor     al, al
1512
    mov     [edx + 4], al
1513
    mov     [edx + 5], al
1514
    mov     al, 0x40
1515
    mov     [edx + 6], al
1516
    xor     al, al
1517
    mov     [edx + 7], al
1518
    mov     al, 0x20
1519
    mov     [edx + 8], al
1520
    mov     al, 17
1521
    mov     [edx + 9], al
1522
 
1523
    ; Checksum left unfilled
1524
    xor     ax, ax
1525
    mov     [edx + 10], ax
1526
 
1527
    ; Fill in the UDP header ( some data is in the socket descriptor)
1528
    mov     ax, [ebx + 12]
1529
    mov     [edx + 20], ax
1530
 
1531
    mov     ax, [ebx + 20]
1532
    mov     [edx + 20 + 2], ax
1533
 
1534
    pop     eax
1535
    push    eax
1536
 
1537
    add     eax, 8
1538
    mov     [edx + 20 + 4], ah
1539
    mov     [edx + 20 + 5], al
1540
 
1541
    ; Checksum left unfilled
1542
    xor     ax, ax
1543
    mov     [edx + 20 + 6], ax
1544
 
1545
    pop     ecx                  ; count of bytes to send
1546
    mov     ebx, ecx            ; need the length later
1547
    pop     eax                  ; get callers ptr to data to send
1548
 
1549
    ; Get the address of the callers data
1550
    mov     edi,[0x3010]
115 poddubny 1551
    add     edi,TASKDATA.mem_start
1 ha 1552
    add     eax,[edi]
1553
    mov     esi, eax
1554
 
1555
    mov     edi, edx
1556
    add     edi, 28
1557
    cld
1558
    rep     movsb               ; copy the data across
1559
 
1560
    ; we have edx as IPbuffer ptr.
1561
    ; Fill in the UDP checksum
1562
    ; First, fill in pseudoheader
1563
    mov     eax, [edx + 12]
1564
    mov     [pseudoHeader], eax
1565
    mov     eax, [edx + 16]
1566
    mov     [pseudoHeader+4], eax
1567
    mov     ax, 0x1100            ; 0 + protocol
1568
    mov     [pseudoHeader+8], ax
1569
    add     ebx, 8
1570
    mov     eax, ebx
1571
    mov     [pseudoHeader+10], ah
1572
    mov     [pseudoHeader+11], al
1573
 
1574
    mov     eax, pseudoHeader
1575
    mov     [checkAdd1], eax
1576
    mov     [checkSize1], word 12
1577
    mov     eax, edx
1578
    add     eax, 20
1579
    mov     [checkAdd2], eax
1580
    mov     eax, ebx
1581
    mov     [checkSize2], ax      ; was eax!! mjh 8/7/02
1582
 
1583
    call    checksum
1584
 
1585
    ; store it in the UDP checksum ( in the correct order! )
1586
    mov     ax, [checkResult]
1587
 
1588
    ; If the UDP checksum computes to 0, we must make it 0xffff
1589
    ; (0 is reserved for 'not used')
1590
    cmp     ax, 0
1591
    jne     sw_001
1592
    mov     ax, 0xffff
1593
 
1594
sw_001:
1595
    mov     [edx + 20 + 6], ah
1596
    mov     [edx + 20 + 7], al
1597
 
1598
    ; Fill in the IP header checksum
1599
    mov     eax, edx
1600
    mov     [checkAdd1], eax
1601
    mov     [checkSize1], word 20
1602
    mov     [checkAdd2], dword 0
1603
    mov     [checkSize2], word 0
1604
 
1605
    call    checksum
1606
 
1607
    mov     ax, [checkResult]
1608
    mov     [edx + 10], ah
1609
    mov     [edx + 11], al
1610
 
1611
    ; Check destination IP address.
1612
    ; If it is the local host IP, route it back to IP_RX
1613
 
1614
    pop     ebx
1615
    mov     eax, NET1OUT_QUEUE
1616
 
1617
    mov     ecx, [ edx + 16]
1618
    mov     edx, [stack_ip]
1619
    cmp     edx, ecx
1620
    jne     sw_notlocal
1621
    mov     eax, IPIN_QUEUE
1622
 
1623
sw_notlocal:
1624
    ; Send it.
1625
    call    queue
1626
 
1627
    xor     eax, eax
1628
 
1629
sw_exit:
1630
    ret
1631
 
1632
 
1633
 
1634
;***************************************************************************
1635
;   Function
1636
;      socket_write_tcp
1637
;
1638
;   Description
1639
;       socket in ebx
1640
;       # of bytes to write in ecx
1641
;       pointer to data in edx
1642
;       returns 0 in eax ok, -1 == failed ( invalid socket, or
1643
;       could not queue IP packet )
1644
;
1645
;***************************************************************************
1646
socket_write_tcp:
1647
    ; First, find the address of the socket descriptor
1648
    shl     ebx, 12
1649
    add     ebx, sockets         ; ebx = address of actual socket
1650
 
1651
    mov     [sktAddr], ebx
1652
 
1653
    mov     eax, 0xFFFFFFFF
1654
    ; If the socket is invalid, return with an error code
1655
    cmp     [ebx], dword SOCK_EMPTY
1656
    je      swt_exit
1657
 
1658
    ; If the sockets window timer is nonzero, do not queue packet
1659
    ; TODO - done
1660
    cmp     [ebx + 72], dword 0
1661
    jne     swt_exit
1662
 
1663
    mov     eax, EMPTY_QUEUE
1664
    call    dequeue
1665
    cmp     ax, NO_BUFFER
1666
    je      swt_exit
1667
 
1668
    push    eax
1669
 
1670
    mov     bl, 0x10        ; ACK
1671
 
1672
    ; Get the address of the callers data
1673
    mov     edi,[0x3010]
115 poddubny 1674
    add     edi,TASKDATA.mem_start
1 ha 1675
    add     edx,[edi]
1676
    mov     esi, edx
1677
 
1678
    pop     eax
1679
    push    eax
1680
 
1681
    push    ecx
1682
    call    buildTCPPacket
1683
    pop     ecx
1684
 
1685
    ; Check destination IP address.
1686
    ; If it is the local host IP, route it back to IP_RX
1687
 
1688
    pop     ebx
1689
    push    ecx
1690
    mov     eax, NET1OUT_QUEUE
1691
 
1692
    mov     edx, [stack_ip]
1693
    mov     ecx, [ sktAddr ]
1694
    mov     ecx, [ ecx + 16 ]
1695
    cmp     edx, ecx
1696
    jne     swt_notlocal
1697
    mov     eax, IPIN_QUEUE
1698
 
1699
swt_notlocal:
1700
    pop     ecx
1701
 
1702
    push    ebx                 ; save ipbuffer number
1703
 
1704
    call    queue
1705
 
1706
    mov     esi, [sktAddr]
1707
 
1708
    ; increament SND.NXT in socket
1709
    ; Amount to increment by is in ecx
1710
    add     esi, 48
1711
    call    add_inet_esi
1712
 
1713
    pop     ebx
1714
 
1715
    ; Copy the IP buffer to a resend queue
1716
    ; If there isn't one, dont worry about it for now
1717
    mov     esi, resendQ
1718
    mov     ecx, 0
1719
 
1720
swt003:
1721
    cmp     ecx, NUMRESENDENTRIES
1722
    je      swt001              ; None found
1723
    cmp     [esi], byte 0xFF
1724
    je      swt002              ; found one
1725
    inc     ecx
1726
    add     esi, 4
1727
    jmp     swt003
1728
 
1729
swt002:
1730
    push    ebx
1731
 
1732
    ; OK, we have a buffer descriptor ptr in esi.
1733
    ; resend entry # in ecx
1734
    ;  Populate it
1735
    ;  socket #
1736
    ;  retries count
1737
    ;  retry time
1738
    ;  fill IP buffer associated with this descriptor
1739
 
1740
    mov     eax, [sktAddr]
1741
    sub     eax, sockets
1742
    shr     eax, 12             ; get skt #
1743
    mov     [esi], al
1744
    mov     [esi + 1], byte TCP_RETRIES
1745
    mov     [esi + 2], word TCP_TIMEOUT
1746
 
1747
    inc     ecx
1748
    ; Now get buffer location, and copy buffer across. argh! more copying,,
1749
    mov     edi, resendBuffer - IPBUFFSIZE
1750
swt002a:
1751
    add     edi, IPBUFFSIZE
1752
    loop    swt002a
1753
 
1754
    ; we have dest buffer location in edi
1755
    pop     eax
1756
    ; convert source buffer pointer eax to the absolute address
1757
    mov     ecx, IPBUFFSIZE
1758
    mul     ecx
1759
    add     eax, IPbuffs
1760
    mov     esi, eax
1761
 
1762
    ; do copy
1763
    mov     ecx, IPBUFFSIZE
1764
    cld
1765
    rep     movsb
1766
 
1767
    inc     dword [arp_rx_count] ; ************ TEST ONLY!
1768
 
1769
swt001:
1770
    xor     eax, eax
1771
 
1772
swt_exit:
1773
    ret
1774
 
1775
 
1776
 
1777
; Below, the main network layer source code is included
1778
;
1779
 
1780
include "queue.inc"
1781
include "ip.inc"
1782
include "tcp.inc"
1783
include "udp.inc"
1784
include "eth_drv/ethernet.inc"