Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1171 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
1763 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved.    ;;
1171 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  STACK.INC                                                      ;;
7
;;                                                                 ;;
1763 hidnplayr 8
;;  TCP/IP stack for KolibriOS                                     ;;
1171 hidnplayr 9
;;                                                                 ;;
10
;;    Written by hidnplayr@kolibrios.org                           ;;
11
;;                                                                 ;;
1763 hidnplayr 12
;;     Some parts of code are based on the work of:                ;;
13
;;      Mike Hibbett (menuetos network stack)                      ;;
14
;;      Eugen Brasoveanu (solar os network stack and drivers)      ;;
15
;;      mike.dld (kolibrios socket code)                           ;;
1171 hidnplayr 16
;;                                                                 ;;
1763 hidnplayr 17
;;     TCP part is based on 4.4BSD                                 ;;
18
;;                                                                 ;;
1171 hidnplayr 19
;;          GNU GENERAL PUBLIC LICENSE                             ;;
20
;;             Version 2, June 1991                                ;;
21
;;                                                                 ;;
22
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1159 hidnplayr 23
 
1206 hidnplayr 24
$Revision: 1774 $
1159 hidnplayr 25
 
1763 hidnplayr 26
__DEBUG_LEVEL_OLD__	equ __DEBUG_LEVEL__	; use seperate debug level for network part of kernel
27
__DEBUG_LEVEL__ 	equ 1
1473 hidnplayr 28
 
1159 hidnplayr 29
uglobal
1763 hidnplayr 30
	net_10ms	dd ?
31
	net_tmr_count	dw ?
1159 hidnplayr 32
endg
33
 
1259 hidnplayr 34
MAX_NET_DEVICES 	equ 16
1159 hidnplayr 35
 
1763 hidnplayr 36
MIN_EPHEMERAL_PORT	equ 49152
37
MAX_EPHEMERAL_PORT	equ 61000
1159 hidnplayr 38
 
1514 hidnplayr 39
; Ethernet protocol numbers
1519 hidnplayr 40
ETHER_ARP		equ 0x0608
1733 hidnplayr 41
ETHER_IPv4		equ 0x0008
1519 hidnplayr 42
ETHER_PPP_DISCOVERY	equ 0x6388
43
ETHER_PPP_SESSION	equ 0x6488
1185 hidnplayr 44
 
1514 hidnplayr 45
;Protocol family
1774 hidnplayr 46
AF_UNSPEC		equ 0
47
AF_UNIX 		equ 1
48
AF_INET4		equ 2
49
AF_INET6		equ 10
1159 hidnplayr 50
 
1514 hidnplayr 51
; Internet protocol numbers
1774 hidnplayr 52
IP_PROTO_IP		equ 0
53
IP_PROTO_ICMP		equ 1
54
IP_PROTO_TCP		equ 6
55
IP_PROTO_UDP		equ 17
1159 hidnplayr 56
 
1200 hidnplayr 57
; Socket types
1774 hidnplayr 58
SOCK_STREAM		equ 1
59
SOCK_DGRAM		equ 2
60
SOCK_RAW		equ 3
1200 hidnplayr 61
 
1514 hidnplayr 62
; Socket options
1774 hidnplayr 63
SO_ACCEPTCON		equ 1
1159 hidnplayr 64
 
1773 hidnplayr 65
; Socket States
1774 hidnplayr 66
SS_NOFDREF		equ 0x001	; no file table ref any more
67
SS_ISCONNECTED		equ 0x002	; socket connected to a peer
68
SS_ISCONNECTING 	equ 0x004	; in process of connecting to peer
69
SS_ISDISCONNECTING	equ 0x008	; in process of disconnecting
70
SS_CANTSENDMORE 	equ 0x010	; can't send more data to peer
71
SS_CANTRCVMORE		equ 0x020	; can't receive more data from peer
72
SS_RCVATMARK		equ 0x040	; at mark on input
73
SS_ISABORTING		equ 0x080	; aborting fd references - close()
74
SS_RESTARTSYS		equ 0x100	; restart blocked system calls
75
SS_ISDISCONNECTED	equ 0x800	; socket disconnected from peer
1773 hidnplayr 76
 
1774 hidnplayr 77
SS_ASYNC		equ 0x100	; async i/o notify
78
SS_ISCONFIRMING 	equ 0x200	; deciding to accept connection req
79
SS_MORETOCOME		equ 0x400
1773 hidnplayr 80
 
81
 
1774 hidnplayr 82
SOCKET_MAXDATA		equ 4096*32	; must be 4096*(power of 2) where 'power of 2' is at least 8
1254 hidnplayr 83
 
1514 hidnplayr 84
; Network driver types
1774 hidnplayr 85
NET_TYPE_ETH		equ 1
86
NET_TYPE_SLIP		equ 2
1254 hidnplayr 87
 
1774 hidnplayr 88
MAX_backlog		equ 20		; maximum backlog for stream sockets
1254 hidnplayr 89
 
1716 hidnplayr 90
; Error Codes
1774 hidnplayr 91
ENOBUFS 		equ 55
92
ECONNREFUSED		equ 61
93
ECONNRESET		equ 52
94
ETIMEDOUT		equ 60
95
ECONNABORTED		equ 53
1529 hidnplayr 96
 
1716 hidnplayr 97
 
98
 
1514 hidnplayr 99
virtual at 0
1254 hidnplayr 100
 
1514 hidnplayr 101
	NET_DEVICE:
1519 hidnplayr 102
 
103
	.type		dd ?	; Type field
104
	.mtu		dd ?	; Maximal Transmission Unit
105
	.name		dd ?	; Ptr to 0 terminated string
106
 
107
	.unload 	dd ?	; Ptrs to driver functions
108
	.reset		dd ?	;
109
	.transmit	dd ?	;
110
 
111
	.bytes_tx	dq ?	; Statistics, updated by the driver
112
	.bytes_rx	dq ?	;
113
	.packets_tx	dd ?	;
114
	.packets_rx	dd ?	;
115
 
1763 hidnplayr 116
;       .hwacc          dd ?    ; bitmask stating available hardware accelerations (offload engines)
1529 hidnplayr 117
 
1514 hidnplayr 118
	.end:
1254 hidnplayr 119
 
1514 hidnplayr 120
end virtual
1254 hidnplayr 121
 
122
 
1514 hidnplayr 123
; Exactly as it says..
1318 hidnplayr 124
macro pseudo_random reg {
125
	add	reg, [esp]
126
	rol	reg, 5
127
	xor	reg, [timer_ticks]
1529 hidnplayr 128
	add	reg, [CPU_FREQ]
1318 hidnplayr 129
	imul	reg, 214013
130
	xor	reg, 0xdeadbeef
131
	rol	reg, 9
1514 hidnplayr 132
}
1318 hidnplayr 133
 
1543 hidnplayr 134
macro ntohd reg {
1318 hidnplayr 135
 
1514 hidnplayr 136
	rol	word reg, 8
137
	rol	dword reg, 16
1529 hidnplayr 138
	rol	word reg , 8
1514 hidnplayr 139
 
1318 hidnplayr 140
}
141
 
1543 hidnplayr 142
macro ntohw reg {
1514 hidnplayr 143
 
144
	rol	word reg, 8
145
 
146
}
147
 
1159 hidnplayr 148
include "queue.inc"
1514 hidnplayr 149
 
150
include "ethernet.inc"
1719 hidnplayr 151
 
1514 hidnplayr 152
;include "slip.inc"
1719 hidnplayr 153
;include "pppoe.inc"
1514 hidnplayr 154
 
1187 hidnplayr 155
include "ARP.inc"
156
include "IPv4.inc"
1514 hidnplayr 157
 
158
include "icmp.inc"
159
include "udp.inc"
1249 hidnplayr 160
include "tcp.inc"
1159 hidnplayr 161
 
1514 hidnplayr 162
include "socket.inc"
163
 
164
 
165
 
166
align 4
167
uglobal
168
 
169
	NET_RUNNING	dd  ?
170
	NET_DRV_LIST	rd  MAX_NET_DEVICES
171
 
172
endg
173
 
174
 
1257 hidnplayr 175
;-----------------------------------------------------------------
1159 hidnplayr 176
;
177
; stack_init
178
;
179
;  This function calls all network init procedures
180
;
181
;  IN:  /
182
;  OUT: /
183
;
1257 hidnplayr 184
;-----------------------------------------------------------------
1159 hidnplayr 185
align 4
186
stack_init:
187
 
1514 hidnplayr 188
; Init the network drivers list
189
	xor	eax, eax
190
	mov	edi, NET_RUNNING
191
	mov	ecx, MAX_NET_DEVICES + 1
192
	rep	stosd
193
 
1529 hidnplayr 194
	ETH_init
195
;        SLIP_init
196
;        PPPOE_init
1514 hidnplayr 197
 
1529 hidnplayr 198
	IPv4_init
199
	ICMP_init
1514 hidnplayr 200
 
1529 hidnplayr 201
	ARP_init
202
	UDP_init
203
	TCP_init
1514 hidnplayr 204
 
1529 hidnplayr 205
	SOCKET_init
1514 hidnplayr 206
 
207
	mov	[net_tmr_count], 0
1159 hidnplayr 208
 
209
	ret
210
 
211
 
1257 hidnplayr 212
;-----------------------------------------------------------------
1159 hidnplayr 213
;
214
; stack_handler
215
;
1514 hidnplayr 216
;  This function is called in kernel loop
1159 hidnplayr 217
;
218
;  IN:  /
219
;  OUT: /
220
;
1257 hidnplayr 221
;-----------------------------------------------------------------
1159 hidnplayr 222
align 4
223
stack_handler:
224
 
1514 hidnplayr 225
	cmp	[NET_RUNNING], 0
1257 hidnplayr 226
	je	.exit
1159 hidnplayr 227
 
1318 hidnplayr 228
	; Test for 10ms tick
1257 hidnplayr 229
	mov	eax, [timer_ticks]
1514 hidnplayr 230
	cmp	eax, [net_10ms]
1257 hidnplayr 231
	je	.exit
1514 hidnplayr 232
	mov	[net_10ms], eax
1159 hidnplayr 233
 
1519 hidnplayr 234
	test	[net_10ms], 0x0f	; 160ms
235
	jnz	.exit
1249 hidnplayr 236
 
1529 hidnplayr 237
	TCP_timer_160ms
1159 hidnplayr 238
 
1519 hidnplayr 239
	test	[net_10ms], 0x3f	; 640ms
240
	jnz	.exit
241
 
1529 hidnplayr 242
	TCP_timer_640ms
243
	ARP_decrease_entry_ttls
244
	IPv4_decrease_fragment_ttls
1159 hidnplayr 245
 
246
  .exit:
1257 hidnplayr 247
	ret
1159 hidnplayr 248
 
249
 
1514 hidnplayr 250
 
1249 hidnplayr 251
;-----------------------------------------------------------------
252
;
1774 hidnplayr 253
; NET_add_Device:
1514 hidnplayr 254
;
255
;  This function is called by the network drivers,
256
;  to register each running NIC to the kernel
257
;
258
;  IN:  Pointer to device structure in ebx
259
;  OUT: Device num in eax, -1 on error
260
;
261
;-----------------------------------------------------------------
262
align 4
263
NET_add_device:
264
 
265
	DEBUGF	1,"NET_Add_Device: %x\n", ebx
266
 
267
	mov	eax, [NET_RUNNING]
268
	cmp	eax, MAX_NET_DEVICES
269
	jge	.error
270
 
271
;----------------------------------
272
; Check if device is already listed
273
	mov	eax, ebx
274
	mov	ecx, MAX_NET_DEVICES	  ; We need to check whole list because a device may be removed without re-organizing list
275
	mov	edi, NET_DRV_LIST
276
 
277
	repne	scasd			  ; See if device is already in the list
278
	jz	.error
279
 
280
;----------------------------
281
; Find empty slot in the list
282
	xor	eax, eax
283
	mov	ecx, MAX_NET_DEVICES
284
	mov	edi, NET_DRV_LIST
285
 
286
	repne	scasd
287
	jnz	.error
288
 
289
	sub	edi, 4
290
 
291
	cmp	[ebx + NET_DEVICE.type], NET_TYPE_ETH
292
	je	.ethernet
293
 
294
	cmp	[ebx + NET_DEVICE.type], NET_TYPE_SLIP
295
	je	.slip
296
 
297
	DEBUGF	1,"Unknown network device type: %u\n", [ebx + NET_DEVICE.type]
298
	jmp	.error
299
 
300
  .ethernet:
1529 hidnplayr 301
	DEBUGF	1,"Trying to add an ethernet device\n"
1514 hidnplayr 302
 
303
	inc	[ETH_RUNNING]		  ; Indicate that one more ethernet device is up and running
304
	jmp	.add_it
305
 
306
  .slip:
1529 hidnplayr 307
	DEBUGF	1,"Trying to add a slip device\n"
1514 hidnplayr 308
	;;;;
309
	jmp	.error
310
 
311
 
312
  .add_it:
313
 
314
;-----------------------------
315
; Add device to the found slot
316
	mov	[edi], ebx		  ; add device to list
317
 
318
	sub	edi, NET_DRV_LIST	  ; Calculate device number in eax
319
	mov	eax, edi		  ;
320
	shr	eax, 2
321
 
322
	inc	[NET_RUNNING]		  ; Indicate that one more network device is up and running
323
 
324
	DEBUGF	1,"Device number: %u\n",eax
325
	ret
326
 
327
  .error:
328
	or	eax, -1
329
	DEBUGF	2,"Adding network device failed\n"
330
	ret
331
 
332
 
333
 
334
;-----------------------------------------------------------------
335
;
336
; NET_Remove_Device:
337
;
338
;  This function is called by etwork drivers,
339
;  to unregister network devices from the kernel
340
;
341
;  IN:  Pointer to device structure in ebx
342
;  OUT: eax: -1 on error
343
;
344
;-----------------------------------------------------------------
345
align 4
346
NET_remove_device:
347
 
348
	cmp	[NET_RUNNING], 0
349
	je	.error
350
 
351
;----------------------------
352
; Find the driver in the list
353
 
354
	mov	eax, ebx
355
	mov	ecx, MAX_NET_DEVICES
356
	mov	edi, NET_DRV_LIST
357
 
358
	repne	scasd
359
	jnz	.error
360
 
361
;------------------------
362
; Remove it from the list
363
 
364
	xor	eax, eax
365
	mov	dword [edi-4], eax
366
 
367
	dec	[NET_RUNNING]
368
	ret
369
 
370
  .error:
371
	or	eax, -1
372
	ret
373
 
374
 
375
 
376
;-----------------------------------------------------------------
377
;
378
; NET_ptr_to_num
379
;
380
; IN:  ebx = ptr to device struct
381
; OUT: edi = -1 on error, device number otherwise
382
;
383
;-----------------------------------------------------------------
384
align 4
385
NET_ptr_to_num:
386
	push	ecx
387
 
388
	mov	ecx, MAX_NET_DEVICES
389
	mov	edi, NET_DRV_LIST
390
 
391
  .loop:
392
	cmp	ebx, [edi]
393
	jz	.found
394
	add	edi, 4
395
	dec	ecx
396
	jnz	.loop
397
 
398
	; repnz  scasd could work too if eax is used instead of ebx!
399
 
400
	or	edi, -1
401
 
402
	pop	ecx
403
	ret
404
 
405
  .found:
406
	sub	edi, NET_DRV_LIST
407
	shr	edi, 2
408
 
409
	pop	ecx
410
	ret
411
 
412
;-----------------------------------------------------------------
413
;
1249 hidnplayr 414
; checksum_1
415
;
1482 hidnplayr 416
;  This is the first of two functions needed to calculate a checksum.
1249 hidnplayr 417
;
1473 hidnplayr 418
;  IN:  edx = start offset for semi-checksum
1249 hidnplayr 419
;       esi = pointer to data
420
;       ecx = data size
421
;  OUT: edx = semi-checksum
422
;
1473 hidnplayr 423
;
424
; Code was optimized by diamond
425
;
1249 hidnplayr 426
;-----------------------------------------------------------------
427
align 4
428
checksum_1:
1159 hidnplayr 429
 
1249 hidnplayr 430
	shr	ecx, 1
431
	pushf
1473 hidnplayr 432
	jz	.no_2
1159 hidnplayr 433
 
1473 hidnplayr 434
	shr	ecx, 1
435
	pushf
436
	jz	.no_4
437
 
438
	shr	ecx, 1
439
	pushf
440
	jz	.no_8
441
 
442
  .loop:
443
	add	dl, [esi+1]
444
	adc	dh, [esi+0]
445
 
446
	adc	dl, [esi+3]
447
	adc	dh, [esi+2]
448
 
449
	adc	dl, [esi+5]
450
	adc	dh, [esi+4]
451
 
452
	adc	dl, [esi+7]
453
	adc	dh, [esi+6]
454
 
455
	adc	edx, 0
456
	add	esi, 8
457
 
458
	dec	ecx
459
	jnz	.loop
460
 
461
	adc	edx, 0
462
 
463
  .no_8:
1249 hidnplayr 464
	popf
1473 hidnplayr 465
	jnc	.no_4
466
 
467
	add	dl, [esi+1]
468
	adc	dh, [esi+0]
469
 
470
	adc	dl, [esi+3]
471
	adc	dh, [esi+2]
472
 
473
	adc	edx, 0
474
	add	esi, 4
475
 
476
  .no_4:
477
	popf
478
	jnc	.no_2
479
 
480
	add	dl, [esi+1]
481
	adc	dh, [esi+0]
482
 
483
	adc	edx, 0
1483 hidnplayr 484
	inc	esi
485
	inc	esi
1473 hidnplayr 486
 
487
  .no_2:
488
	popf
1249 hidnplayr 489
	jnc	.end
1159 hidnplayr 490
 
1473 hidnplayr 491
	add	dh, [esi+0]
1251 clevermous 492
	adc	edx, 0
1473 hidnplayr 493
  .end:
494
	ret
1159 hidnplayr 495
 
1249 hidnplayr 496
;-----------------------------------------------------------------
497
;
498
; checksum_2
499
;
500
;  This function calculates the final ip/tcp/udp checksum for you
501
;
502
;  IN:  edx = semi-checksum
503
;  OUT: dx = checksum (in INET byte order)
504
;
505
;-----------------------------------------------------------------
506
align 4
507
checksum_2:
508
 
509
	mov	ecx, edx
510
	shr	ecx, 16
511
	and	edx, 0xffff
512
	add	edx, ecx
513
 
1482 hidnplayr 514
	mov	ecx, edx
515
	shr	ecx, 16
1529 hidnplayr 516
	add	dx, cx
517
	test	dx, dx		; it seems that ZF is not set when CF is set :(
1249 hidnplayr 518
	not	dx
519
	jnz	.not_zero
520
	dec	dx
521
  .not_zero:
522
	xchg	dl, dh
523
 
1529 hidnplayr 524
	DEBUGF 1,"Checksum: %x\n", dx
1249 hidnplayr 525
 
526
	ret
527
 
528
 
529
 
1159 hidnplayr 530
;----------------------------------------------------------------
531
;
1171 hidnplayr 532
;  System function to work with network devices (73)
1159 hidnplayr 533
;
534
;----------------------------------------------------------------
535
align 4
536
sys_network:
537
 
1196 hidnplayr 538
	cmp	ebx, -1
539
	jne	@f
540
 
1514 hidnplayr 541
	mov	eax, [NET_RUNNING]
1196 hidnplayr 542
	jmp	.return
543
 
544
   @@:
1159 hidnplayr 545
	cmp	bh, MAX_NET_DEVICES		 ; Check if device number exists
546
	jge	.doesnt_exist
547
 
548
	mov	esi, ebx
549
	and	esi, 0x0000ff00
550
	shr	esi, 6
551
 
1514 hidnplayr 552
	cmp	dword [esi + NET_DRV_LIST], 0 ; check if driver is running
1159 hidnplayr 553
	je	.doesnt_exist
554
 
1514 hidnplayr 555
	test	bl, bl			 ; 0 = Get device type (ethernet/token ring/...)
1159 hidnplayr 556
	jnz	@f
1514 hidnplayr 557
 
1192 hidnplayr 558
	xor	eax, eax
559
	jmp	.return
1159 hidnplayr 560
 
561
 
562
  @@:
563
	dec	bl			; 1 = Get device name
564
	jnz	@f
565
 
1514 hidnplayr 566
	mov	esi, [esi + NET_DRV_LIST]
1519 hidnplayr 567
	mov	esi, [esi + NET_DEVICE.name]
1159 hidnplayr 568
	mov	edi, ecx
569
 
570
	mov	ecx, 64 ; max length
571
	repnz	movsb
572
 
1192 hidnplayr 573
	xor	eax, eax
574
	jmp	.return
1159 hidnplayr 575
 
1192 hidnplayr 576
  @@:
1159 hidnplayr 577
 
1192 hidnplayr 578
	dec	bl			; 2 = Reset the device
579
	jnz	@f
580
 
1514 hidnplayr 581
	mov	esi, [esi + NET_DRV_LIST]
1519 hidnplayr 582
	call	[esi + NET_DEVICE.reset]
1192 hidnplayr 583
	jmp	.return
584
 
1159 hidnplayr 585
  @@:
1192 hidnplayr 586
 
587
	dec	bl			; 3 = Stop driver for this device
588
	jnz	@f
589
 
1514 hidnplayr 590
	mov	esi, [esi + NET_DRV_LIST]
1519 hidnplayr 591
	call	[esi + NET_DEVICE.unload]
1192 hidnplayr 592
	jmp	.return
593
 
594
  @@:
1249 hidnplayr 595
	dec	bl			; 4 = Get driver pointer
596
	jnz	@f
1192 hidnplayr 597
 
1249 hidnplayr 598
	; ..;
599
 
600
 
601
  @@:
602
;  ...                                   ; 5 Get driver name
603
 
1159 hidnplayr 604
  .doesnt_exist:
605
	DEBUGF	1,"sys_network: invalid device/function specified!\n"
606
	mov	eax, -1
607
 
1192 hidnplayr 608
  .return:
609
	mov	[esp+28+4], eax
1159 hidnplayr 610
	ret
611
 
612
 
613
;----------------------------------------------------------------
614
;
1514 hidnplayr 615
;  System function to work with protocols  (75)
1159 hidnplayr 616
;
617
;----------------------------------------------------------------
618
align 4
619
sys_protocols:
620
	cmp	bh, MAX_NET_DEVICES		; Check if device number exists
621
	jge	.doesnt_exist
622
 
623
	mov	esi, ebx
624
	and	esi, 0x0000ff00
1514 hidnplayr 625
	shr	esi, 6				; now we have the device num * 4 in esi
626
	cmp	dword [esi + NET_DRV_LIST], 0	; check if driver is running
1159 hidnplayr 627
	je	.doesnt_exist
628
 
629
	push	.return 			; return address (we will be using jumps instead of calls)
630
 
631
	mov	eax, ebx			; set ax to protocol number
632
	shr	eax, 16 			;
633
 
634
	cmp	ax , IP_PROTO_IP
635
	je	IPv4_API
636
 
637
	cmp	ax , IP_PROTO_ICMP
638
	je	ICMP_API
639
 
640
	cmp	ax , IP_PROTO_UDP
641
	je	UDP_API
642
 
1171 hidnplayr 643
	cmp	ax , IP_PROTO_TCP
1254 hidnplayr 644
	je	TCP_API
1159 hidnplayr 645
 
1171 hidnplayr 646
	cmp	ax , ETHER_ARP
1159 hidnplayr 647
	je	ARP_API
648
 
1519 hidnplayr 649
	cmp	ax , 1337  ;;;;;
1159 hidnplayr 650
	je	ETH_API
651
 
1171 hidnplayr 652
	add	esp, 4				 ; if we reached here, no function was called, so we need to balance stack
1159 hidnplayr 653
 
654
  .doesnt_exist:
1519 hidnplayr 655
	DEBUGF	1,"sys_protocols: protocol %u doesnt exist on device %u!\n", ax, bh
1159 hidnplayr 656
	mov	eax, -1
657
 
658
  .return:
1171 hidnplayr 659
	mov	[esp+28+4], eax
1257 hidnplayr 660
	ret
1473 hidnplayr 661
 
662
 
663
__DEBUG_LEVEL__ equ __DEBUG_LEVEL_OLD__