Subversion Repositories Kolibri OS

Rev

Rev 1763 | 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: 1773 $
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
1254 hidnplayr 46
AF_UNSPEC	equ 0
1249 hidnplayr 47
AF_UNIX 	equ 1
1159 hidnplayr 48
AF_INET4	equ 2
1514 hidnplayr 49
AF_INET6	equ 10
1159 hidnplayr 50
 
1514 hidnplayr 51
; Internet protocol numbers
1159 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
56
 
1200 hidnplayr 57
; Socket types
1514 hidnplayr 58
SOCK_STREAM	equ 1
59
SOCK_DGRAM	equ 2
60
SOCK_RAW	equ 3
1200 hidnplayr 61
 
1514 hidnplayr 62
; Socket options
1529 hidnplayr 63
SO_ACCEPTCON	equ 1
1159 hidnplayr 64
 
1773 hidnplayr 65
; Socket States
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
76
 
77
SS_ASYNC		equ 0x100   ; async i/o notify
78
SS_ISCONFIRMING 	equ 0x200   ; deciding to accept connection req
79
SS_MORETOCOME		equ 0x400   ;
80
 
81
 
1529 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
85
NET_TYPE_ETH	equ 1
86
NET_TYPE_SLIP	equ 2
1254 hidnplayr 87
 
1543 hidnplayr 88
MAX_backlog	equ 20		; maximum backlog for stream sockets
1254 hidnplayr 89
 
1716 hidnplayr 90
; Error Codes
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
 
148
 
1529 hidnplayr 149
macro packet_to_debug { 	; set esi to packet you want to print, ecx to number of bytes
150
 
151
local	.loop
152
 
153
  .loop:
154
	lodsb
155
	DEBUGF	1,"%x ", eax:2
156
	loop	@r
157
 
158
}
159
 
160
 
1159 hidnplayr 161
include "queue.inc"
1514 hidnplayr 162
 
163
include "ethernet.inc"
1719 hidnplayr 164
 
1514 hidnplayr 165
;include "slip.inc"
1719 hidnplayr 166
;include "pppoe.inc"
1514 hidnplayr 167
 
1187 hidnplayr 168
include "ARP.inc"
169
include "IPv4.inc"
1514 hidnplayr 170
 
171
include "icmp.inc"
172
include "udp.inc"
1249 hidnplayr 173
include "tcp.inc"
1159 hidnplayr 174
 
1514 hidnplayr 175
include "socket.inc"
176
 
177
 
178
 
179
align 4
180
uglobal
181
 
182
	NET_RUNNING	dd  ?
183
	NET_DRV_LIST	rd  MAX_NET_DEVICES
184
 
185
endg
186
 
187
 
1257 hidnplayr 188
;-----------------------------------------------------------------
1159 hidnplayr 189
;
190
; stack_init
191
;
192
;  This function calls all network init procedures
193
;
194
;  IN:  /
195
;  OUT: /
196
;
1257 hidnplayr 197
;-----------------------------------------------------------------
1159 hidnplayr 198
align 4
199
stack_init:
200
 
1514 hidnplayr 201
; Init the network drivers list
202
	xor	eax, eax
203
	mov	edi, NET_RUNNING
204
	mov	ecx, MAX_NET_DEVICES + 1
205
	rep	stosd
206
 
1529 hidnplayr 207
	ETH_init
208
;        SLIP_init
209
;        PPPOE_init
1514 hidnplayr 210
 
1529 hidnplayr 211
	IPv4_init
212
	ICMP_init
1514 hidnplayr 213
 
1529 hidnplayr 214
	ARP_init
215
	UDP_init
216
	TCP_init
1514 hidnplayr 217
 
1529 hidnplayr 218
	SOCKET_init
1514 hidnplayr 219
 
220
	mov	[net_tmr_count], 0
1159 hidnplayr 221
 
222
	ret
223
 
224
 
1257 hidnplayr 225
;-----------------------------------------------------------------
1159 hidnplayr 226
;
227
; stack_handler
228
;
1514 hidnplayr 229
;  This function is called in kernel loop
1159 hidnplayr 230
;
231
;  IN:  /
232
;  OUT: /
233
;
1257 hidnplayr 234
;-----------------------------------------------------------------
1159 hidnplayr 235
align 4
236
stack_handler:
237
 
1514 hidnplayr 238
	cmp	[NET_RUNNING], 0
1257 hidnplayr 239
	je	.exit
1159 hidnplayr 240
 
1318 hidnplayr 241
	; Test for 10ms tick
1257 hidnplayr 242
	mov	eax, [timer_ticks]
1514 hidnplayr 243
	cmp	eax, [net_10ms]
1257 hidnplayr 244
	je	.exit
1514 hidnplayr 245
	mov	[net_10ms], eax
1159 hidnplayr 246
 
1519 hidnplayr 247
	test	[net_10ms], 0x0f	; 160ms
248
	jnz	.exit
1249 hidnplayr 249
 
1529 hidnplayr 250
	TCP_timer_160ms
1159 hidnplayr 251
 
1519 hidnplayr 252
	test	[net_10ms], 0x3f	; 640ms
253
	jnz	.exit
254
 
1529 hidnplayr 255
	TCP_timer_640ms
256
	ARP_decrease_entry_ttls
257
	IPv4_decrease_fragment_ttls
1159 hidnplayr 258
 
259
  .exit:
1257 hidnplayr 260
	ret
1159 hidnplayr 261
 
262
 
1514 hidnplayr 263
 
1249 hidnplayr 264
;-----------------------------------------------------------------
265
;
1514 hidnplayr 266
; NET_Add_Device:
267
;
268
;  This function is called by the network drivers,
269
;  to register each running NIC to the kernel
270
;
271
;  IN:  Pointer to device structure in ebx
272
;  OUT: Device num in eax, -1 on error
273
;
274
;-----------------------------------------------------------------
275
align 4
276
NET_add_device:
277
 
278
	DEBUGF	1,"NET_Add_Device: %x\n", ebx
279
 
280
	mov	eax, [NET_RUNNING]
281
	cmp	eax, MAX_NET_DEVICES
282
	jge	.error
283
 
284
;----------------------------------
285
; Check if device is already listed
286
	mov	eax, ebx
287
	mov	ecx, MAX_NET_DEVICES	  ; We need to check whole list because a device may be removed without re-organizing list
288
	mov	edi, NET_DRV_LIST
289
 
290
	repne	scasd			  ; See if device is already in the list
291
	jz	.error
292
 
293
;----------------------------
294
; Find empty slot in the list
295
	xor	eax, eax
296
	mov	ecx, MAX_NET_DEVICES
297
	mov	edi, NET_DRV_LIST
298
 
299
	repne	scasd
300
	jnz	.error
301
 
302
	sub	edi, 4
303
 
304
	cmp	[ebx + NET_DEVICE.type], NET_TYPE_ETH
305
	je	.ethernet
306
 
307
	cmp	[ebx + NET_DEVICE.type], NET_TYPE_SLIP
308
	je	.slip
309
 
310
	DEBUGF	1,"Unknown network device type: %u\n", [ebx + NET_DEVICE.type]
311
	jmp	.error
312
 
313
  .ethernet:
1529 hidnplayr 314
	DEBUGF	1,"Trying to add an ethernet device\n"
1514 hidnplayr 315
 
316
	inc	[ETH_RUNNING]		  ; Indicate that one more ethernet device is up and running
317
	jmp	.add_it
318
 
319
  .slip:
1529 hidnplayr 320
	DEBUGF	1,"Trying to add a slip device\n"
1514 hidnplayr 321
	;;;;
322
	jmp	.error
323
 
324
 
325
  .add_it:
326
 
327
;-----------------------------
328
; Add device to the found slot
329
	mov	[edi], ebx		  ; add device to list
330
 
331
	sub	edi, NET_DRV_LIST	  ; Calculate device number in eax
332
	mov	eax, edi		  ;
333
	shr	eax, 2
334
 
335
	inc	[NET_RUNNING]		  ; Indicate that one more network device is up and running
336
 
337
	DEBUGF	1,"Device number: %u\n",eax
338
	ret
339
 
340
  .error:
341
	or	eax, -1
342
	DEBUGF	2,"Adding network device failed\n"
343
	ret
344
 
345
 
346
 
347
;-----------------------------------------------------------------
348
;
349
; NET_Remove_Device:
350
;
351
;  This function is called by etwork drivers,
352
;  to unregister network devices from the kernel
353
;
354
;  IN:  Pointer to device structure in ebx
355
;  OUT: eax: -1 on error
356
;
357
;-----------------------------------------------------------------
358
align 4
359
NET_remove_device:
360
 
361
	cmp	[NET_RUNNING], 0
362
	je	.error
363
 
364
;----------------------------
365
; Find the driver in the list
366
 
367
	mov	eax, ebx
368
	mov	ecx, MAX_NET_DEVICES
369
	mov	edi, NET_DRV_LIST
370
 
371
	repne	scasd
372
	jnz	.error
373
 
374
;------------------------
375
; Remove it from the list
376
 
377
	xor	eax, eax
378
	mov	dword [edi-4], eax
379
 
380
	dec	[NET_RUNNING]
381
	ret
382
 
383
  .error:
384
	or	eax, -1
385
	ret
386
 
387
 
388
 
389
;-----------------------------------------------------------------
390
;
391
; NET_ptr_to_num
392
;
393
; IN:  ebx = ptr to device struct
394
; OUT: edi = -1 on error, device number otherwise
395
;
396
;-----------------------------------------------------------------
397
align 4
398
NET_ptr_to_num:
399
	push	ecx
400
 
401
	mov	ecx, MAX_NET_DEVICES
402
	mov	edi, NET_DRV_LIST
403
 
404
  .loop:
405
	cmp	ebx, [edi]
406
	jz	.found
407
	add	edi, 4
408
	dec	ecx
409
	jnz	.loop
410
 
411
	; repnz  scasd could work too if eax is used instead of ebx!
412
 
413
	or	edi, -1
414
 
415
	pop	ecx
416
	ret
417
 
418
  .found:
419
	sub	edi, NET_DRV_LIST
420
	shr	edi, 2
421
 
422
	pop	ecx
423
	ret
424
 
425
;-----------------------------------------------------------------
426
;
1249 hidnplayr 427
; checksum_1
428
;
1482 hidnplayr 429
;  This is the first of two functions needed to calculate a checksum.
1249 hidnplayr 430
;
1473 hidnplayr 431
;  IN:  edx = start offset for semi-checksum
1249 hidnplayr 432
;       esi = pointer to data
433
;       ecx = data size
434
;  OUT: edx = semi-checksum
435
;
1473 hidnplayr 436
;
437
; Code was optimized by diamond
438
;
1249 hidnplayr 439
;-----------------------------------------------------------------
440
align 4
441
checksum_1:
1159 hidnplayr 442
 
1249 hidnplayr 443
	shr	ecx, 1
444
	pushf
1473 hidnplayr 445
	jz	.no_2
1159 hidnplayr 446
 
1473 hidnplayr 447
	shr	ecx, 1
448
	pushf
449
	jz	.no_4
450
 
451
	shr	ecx, 1
452
	pushf
453
	jz	.no_8
454
 
455
  .loop:
456
	add	dl, [esi+1]
457
	adc	dh, [esi+0]
458
 
459
	adc	dl, [esi+3]
460
	adc	dh, [esi+2]
461
 
462
	adc	dl, [esi+5]
463
	adc	dh, [esi+4]
464
 
465
	adc	dl, [esi+7]
466
	adc	dh, [esi+6]
467
 
468
	adc	edx, 0
469
	add	esi, 8
470
 
471
	dec	ecx
472
	jnz	.loop
473
 
474
	adc	edx, 0
475
 
476
  .no_8:
1249 hidnplayr 477
	popf
1473 hidnplayr 478
	jnc	.no_4
479
 
480
	add	dl, [esi+1]
481
	adc	dh, [esi+0]
482
 
483
	adc	dl, [esi+3]
484
	adc	dh, [esi+2]
485
 
486
	adc	edx, 0
487
	add	esi, 4
488
 
489
  .no_4:
490
	popf
491
	jnc	.no_2
492
 
493
	add	dl, [esi+1]
494
	adc	dh, [esi+0]
495
 
496
	adc	edx, 0
1483 hidnplayr 497
	inc	esi
498
	inc	esi
1473 hidnplayr 499
 
500
  .no_2:
501
	popf
1249 hidnplayr 502
	jnc	.end
1159 hidnplayr 503
 
1473 hidnplayr 504
	add	dh, [esi+0]
1251 clevermous 505
	adc	edx, 0
1473 hidnplayr 506
  .end:
507
	ret
1159 hidnplayr 508
 
1249 hidnplayr 509
;-----------------------------------------------------------------
510
;
511
; checksum_2
512
;
513
;  This function calculates the final ip/tcp/udp checksum for you
514
;
515
;  IN:  edx = semi-checksum
516
;  OUT: dx = checksum (in INET byte order)
517
;
518
;-----------------------------------------------------------------
519
align 4
520
checksum_2:
521
 
522
	mov	ecx, edx
523
	shr	ecx, 16
524
	and	edx, 0xffff
525
	add	edx, ecx
526
 
1482 hidnplayr 527
	mov	ecx, edx
528
	shr	ecx, 16
1529 hidnplayr 529
	add	dx, cx
530
	test	dx, dx		; it seems that ZF is not set when CF is set :(
1249 hidnplayr 531
	not	dx
532
	jnz	.not_zero
533
	dec	dx
534
  .not_zero:
535
	xchg	dl, dh
536
 
1529 hidnplayr 537
	DEBUGF 1,"Checksum: %x\n", dx
1249 hidnplayr 538
 
539
	ret
540
 
541
 
542
 
1159 hidnplayr 543
;----------------------------------------------------------------
544
;
1171 hidnplayr 545
;  System function to work with network devices (73)
1159 hidnplayr 546
;
547
;----------------------------------------------------------------
548
align 4
549
sys_network:
550
 
1196 hidnplayr 551
	cmp	ebx, -1
552
	jne	@f
553
 
1514 hidnplayr 554
	mov	eax, [NET_RUNNING]
1196 hidnplayr 555
	jmp	.return
556
 
557
   @@:
1159 hidnplayr 558
	cmp	bh, MAX_NET_DEVICES		 ; Check if device number exists
559
	jge	.doesnt_exist
560
 
561
	mov	esi, ebx
562
	and	esi, 0x0000ff00
563
	shr	esi, 6
564
 
1514 hidnplayr 565
	cmp	dword [esi + NET_DRV_LIST], 0 ; check if driver is running
1159 hidnplayr 566
	je	.doesnt_exist
567
 
1514 hidnplayr 568
	test	bl, bl			 ; 0 = Get device type (ethernet/token ring/...)
1159 hidnplayr 569
	jnz	@f
1514 hidnplayr 570
 
1192 hidnplayr 571
	xor	eax, eax
572
	jmp	.return
1159 hidnplayr 573
 
574
 
575
  @@:
576
	dec	bl			; 1 = Get device name
577
	jnz	@f
578
 
1514 hidnplayr 579
	mov	esi, [esi + NET_DRV_LIST]
1519 hidnplayr 580
	mov	esi, [esi + NET_DEVICE.name]
1159 hidnplayr 581
	mov	edi, ecx
582
 
583
	mov	ecx, 64 ; max length
584
	repnz	movsb
585
 
1192 hidnplayr 586
	xor	eax, eax
587
	jmp	.return
1159 hidnplayr 588
 
1192 hidnplayr 589
  @@:
1159 hidnplayr 590
 
1192 hidnplayr 591
	dec	bl			; 2 = Reset the device
592
	jnz	@f
593
 
1514 hidnplayr 594
	mov	esi, [esi + NET_DRV_LIST]
1519 hidnplayr 595
	call	[esi + NET_DEVICE.reset]
1192 hidnplayr 596
	jmp	.return
597
 
1159 hidnplayr 598
  @@:
1192 hidnplayr 599
 
600
	dec	bl			; 3 = Stop driver for this device
601
	jnz	@f
602
 
1514 hidnplayr 603
	mov	esi, [esi + NET_DRV_LIST]
1519 hidnplayr 604
	call	[esi + NET_DEVICE.unload]
1192 hidnplayr 605
	jmp	.return
606
 
607
  @@:
1249 hidnplayr 608
	dec	bl			; 4 = Get driver pointer
609
	jnz	@f
1192 hidnplayr 610
 
1249 hidnplayr 611
	; ..;
612
 
613
 
614
  @@:
615
;  ...                                   ; 5 Get driver name
616
 
1159 hidnplayr 617
  .doesnt_exist:
618
	DEBUGF	1,"sys_network: invalid device/function specified!\n"
619
	mov	eax, -1
620
 
1192 hidnplayr 621
  .return:
622
	mov	[esp+28+4], eax
1159 hidnplayr 623
	ret
624
 
625
 
626
;----------------------------------------------------------------
627
;
1514 hidnplayr 628
;  System function to work with protocols  (75)
1159 hidnplayr 629
;
630
;----------------------------------------------------------------
631
align 4
632
sys_protocols:
633
	cmp	bh, MAX_NET_DEVICES		; Check if device number exists
634
	jge	.doesnt_exist
635
 
636
	mov	esi, ebx
637
	and	esi, 0x0000ff00
1514 hidnplayr 638
	shr	esi, 6				; now we have the device num * 4 in esi
639
	cmp	dword [esi + NET_DRV_LIST], 0	; check if driver is running
1159 hidnplayr 640
	je	.doesnt_exist
641
 
642
	push	.return 			; return address (we will be using jumps instead of calls)
643
 
644
	mov	eax, ebx			; set ax to protocol number
645
	shr	eax, 16 			;
646
 
647
	cmp	ax , IP_PROTO_IP
648
	je	IPv4_API
649
 
650
	cmp	ax , IP_PROTO_ICMP
651
	je	ICMP_API
652
 
653
	cmp	ax , IP_PROTO_UDP
654
	je	UDP_API
655
 
1171 hidnplayr 656
	cmp	ax , IP_PROTO_TCP
1254 hidnplayr 657
	je	TCP_API
1159 hidnplayr 658
 
1171 hidnplayr 659
	cmp	ax , ETHER_ARP
1159 hidnplayr 660
	je	ARP_API
661
 
1519 hidnplayr 662
	cmp	ax , 1337  ;;;;;
1159 hidnplayr 663
	je	ETH_API
664
 
1171 hidnplayr 665
	add	esp, 4				 ; if we reached here, no function was called, so we need to balance stack
1159 hidnplayr 666
 
667
  .doesnt_exist:
1519 hidnplayr 668
	DEBUGF	1,"sys_protocols: protocol %u doesnt exist on device %u!\n", ax, bh
1159 hidnplayr 669
	mov	eax, -1
670
 
671
  .return:
1171 hidnplayr 672
	mov	[esp+28+4], eax
1257 hidnplayr 673
	ret
1473 hidnplayr 674
 
675
 
676
__DEBUG_LEVEL__ equ __DEBUG_LEVEL_OLD__