Subversion Repositories Kolibri OS

Rev

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