Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
261 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                    ;;
1519 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved.       ;;
431 serge 4
;; Distributed under terms of the GNU General Public License          ;;
5
;;                                                                    ;;
1237 clevermous 6
;;  Ethernet driver for KolibriOS                                     ;;
7
;;  This is an adaptation of MenuetOS driver with minimal changes.    ;;
8
;;  Changes were made by CleverMouse. Original copyright follows.     ;;
261 hidnplayr 9
;;                                                                    ;;
10
;;  This driver is based on the SIS900 driver from                    ;;
11
;;  the etherboot 5.0.6 project. The copyright statement is           ;;
12
;;                                                                    ;;
13
;;          GNU GENERAL PUBLIC LICENSE                                ;;
14
;;             Version 2, June 1991                                   ;;
15
;;                                                                    ;;
16
;;  remaining parts Copyright 2004 Jason Delozier,                    ;;
17
;;   cordata51@hotmail.com                                            ;;
18
;;                                                                    ;;
19
;;  See file COPYING for details                                      ;;
20
;;                                                                    ;;
21
;;  Updates:                                                          ;;
22
;;    Revision Look up table and SIS635 Mac Address by Jarek Pelczar  ;;
23
;;                                                                    ;;
24
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
593 mikedld 25
 
1237 clevermous 26
format MS COFF
593 mikedld 27
 
1237 clevermous 28
	API_VERSION		equ 0x01000100
1519 hidnplayr 29
	DRIVER_VERSION		equ 5
1237 clevermous 30
 
1519 hidnplayr 31
	MAX_DEVICES		equ 16
32
 
1237 clevermous 33
	DEBUG			equ 1
34
	__DEBUG__		equ 1
35
	__DEBUG_LEVEL__ 	equ 1
36
 
37
include 'proc32.inc'
38
include 'imports.inc'
39
include 'fdo.inc'
1514 hidnplayr 40
include 'netdrv.inc'
1237 clevermous 41
 
42
public START
43
public version
44
 
1519 hidnplayr 45
NUM_RX_DESC		equ 4		;* Number of RX descriptors *
46
NUM_TX_DESC		equ 1		;* Number of TX descriptors *
47
RX_BUFF_SZ		equ 1520	;* Buffer size for each Rx buffer *
48
TX_BUFF_SZ		equ 1516	;* Buffer size for each Tx buffer *
49
MAX_ETH_FRAME_SIZE	equ 1516
1237 clevermous 50
 
1519 hidnplayr 51
virtual at ebx
1514 hidnplayr 52
	device:
53
 
54
	ETH_DEVICE
55
 
1519 hidnplayr 56
	.io_addr	dd ?
57
	.pci_bus	db ?
58
	.pci_dev	db ?
59
	.irq_line	db ?
60
	.cur_rx 	db ?
61
	.cur_tx 	db ?
62
	.last_tx	db ?
63
	.pci_revision	db ?
64
	.table_entries	db ?
1237 clevermous 65
 
1519 hidnplayr 66
			dw ? ; align 4
1237 clevermous 67
 
1519 hidnplayr 68
	.special_func	dd ?
1237 clevermous 69
 
1519 hidnplayr 70
	.txd		rd (4 * NUM_TX_DESC)
71
	.rxd		rd (4 * NUM_RX_DESC)
1237 clevermous 72
 
1519 hidnplayr 73
	.size = $ - device
1237 clevermous 74
 
1519 hidnplayr 75
end virtual
76
 
77
macro	ee_delay {
78
	push	eax
79
	in	eax, dx
80
	in	eax, dx
81
	in	eax, dx
82
	in	eax, dx
83
	in	eax, dx
84
	in	eax, dx
85
	in	eax, dx
86
	in	eax, dx
87
	in	eax, dx
88
	in	eax, dx
89
	pop	eax
90
}
91
 
92
 
1237 clevermous 93
section '.flat' code readable align 16
94
 
95
; Driver entry point - register our service when the driver is loading.
96
; TODO: add needed operations when unloading
97
START:
98
	cmp	dword [esp+4], 1
99
	jne	.exit
1254 hidnplayr 100
	stdcall RegService, my_service, service_proc
1237 clevermous 101
	ret	4
102
.exit:
103
	xor	eax, eax
104
	ret	4
105
 
106
; Service procedure for the driver - handle all I/O requests for the driver.
107
; Currently handled requests are: SRV_GETVERSION = 0 and SRV_HOOK = 1.
108
service_proc:
109
; 1. Get parameter from the stack: [esp+4] is the first parameter,
1254 hidnplayr 110
;       pointer to IOCTL structure.
1237 clevermous 111
	mov	edx, [esp+4]	; edx -> IOCTL
112
; 2. Get request code and select a handler for the code.
1519 hidnplayr 113
	mov	eax, [IOCTL.io_code]
1237 clevermous 114
	test	eax, eax	; check for SRV_GETVERSION
115
	jnz	@f
116
; 3. This is SRV_GETVERSION request, no input, 4 bytes output, API_VERSION.
117
; 3a. Output size must be at least 4 bytes.
1519 hidnplayr 118
	cmp	[IOCTL.out_size], 4
1237 clevermous 119
	jl	.fail
120
; 3b. Write result to the output buffer.
1519 hidnplayr 121
	mov	eax, [IOCTL.output]
1237 clevermous 122
	mov	[eax], dword API_VERSION
123
; 3c. Return success.
124
	xor	eax, eax
125
	ret	4
126
@@:
127
	dec	eax	; check for SRV_HOOK
128
	jnz	.fail
129
; 4. This is SRV_HOOK request, input defines the device to hook, no output.
130
; 4a. The driver works only with PCI devices,
1254 hidnplayr 131
;       so input must be at least 3 bytes long.
1519 hidnplayr 132
	cmp	[IOCTL.inp_size], 3
1237 clevermous 133
	jl	.fail
134
; 4b. First byte of input is bus type, 1 stands for PCI.
1519 hidnplayr 135
	mov	eax, [IOCTL.input]
1237 clevermous 136
	cmp	byte [eax], 1
137
	jne	.fail
138
; 4c. Second and third bytes of the input define the device: bus and dev.
1254 hidnplayr 139
;       Word in bx holds both bytes.
1237 clevermous 140
	mov	bx, [eax+1]
141
; 4d. Check if the device was already hooked,
1254 hidnplayr 142
;       scan through the list of known devices.
1519 hidnplayr 143
; check if the device is already listed
144
	mov	esi, device_list
145
	mov	ecx, [devices]
1237 clevermous 146
	test	ecx, ecx
147
	jz	.firstdevice
1519 hidnplayr 148
 
149
;        mov     eax, [IOCTL.input]                      ; get the pci bus and device numbers
150
	mov	ax , [eax+1]				;
1237 clevermous 151
  .nextdevice:
1519 hidnplayr 152
	mov	ebx, [esi]
153
	cmp	ax , word [device.pci_bus]		; compare with pci and device num in device list (notice the usage of word instead of byte)
154
	je	.find_devicenum 			; Device is already loaded, let's find it's device number
155
	add	esi, 4
1237 clevermous 156
	loop	.nextdevice
157
; 4e. This device doesn't have its own eth_device structure yet, let's create one
158
  .firstdevice:
159
; 4f. Check that we have place for new device.
1519 hidnplayr 160
	cmp	[devices], MAX_DEVICES
1237 clevermous 161
	jge	.fail
162
; 4g. Allocate memory for device descriptor and receive+transmit buffers.
1519 hidnplayr 163
	stdcall KernelAlloc, device.size
1237 clevermous 164
	test	eax, eax
165
	jz	.fail
166
; 4h. Zero the structure.
167
	mov	edi, eax
168
	mov	ecx, (device.size + 3) shr 2
169
	xor	eax, eax
170
	rep	stosd
1519 hidnplayr 171
; 4i. Save PCI coordinates
172
	mov	eax, [IOCTL.input]
173
	mov	cl , [eax+1]
174
	mov	[device.pci_bus], cl
175
	mov	cl , [eax+2]
176
	mov	[device.pci_dev], cl
1237 clevermous 177
; 4j. Fill in the direct call addresses into the struct.
1519 hidnplayr 178
; Note that get_MAC pointer is filled in initialization by probe.
179
	mov	[device.reset], init
180
	mov	[device.transmit], transmit
181
;       mov     [device.get_MAC], read_mac
182
	mov	[device.set_MAC], write_mac
183
	mov	[device.unload], unload
184
	mov	[device.name], my_service
1237 clevermous 185
 
186
; 4k. Now, it's time to find the base io addres of the PCI device
187
; TODO: implement check if bus and dev exist on this machine
188
 
1519 hidnplayr 189
; Now, it's time to find the base io addres of the PCI device
190
	find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
1237 clevermous 191
 
1519 hidnplayr 192
; We've found the io address, find IRQ now
193
	find_irq [device.pci_bus], [device.pci_dev], [device.irq_line]
1237 clevermous 194
 
195
; 4m. Add new device to the list (required for int_handler).
1519 hidnplayr 196
	mov	eax, [devices]
197
	mov	[device_list+4*eax], ebx
198
	inc	[devices]
1237 clevermous 199
 
200
; 4m. Ok, the eth_device structure is ready, let's probe the device
1519 hidnplayr 201
	call	probe
1237 clevermous 202
	test	eax, eax
203
	jnz	.destroy
204
; 4n. If device was successfully initialized, register it for the kernel.
205
 
1514 hidnplayr 206
	mov	[device.type], NET_TYPE_ETH
207
	call	NetRegDev
208
 
1237 clevermous 209
	cmp	eax, -1
210
	je	.destroy
211
 
212
	ret	4
213
 
214
; 5. If the device was already loaded, find the device number and return it in eax
215
 
216
  .find_devicenum:
217
	mov	ebx, eax
1514 hidnplayr 218
	call	NetPtrToNum						; This kernel procedure converts a pointer to device struct in ebx
1237 clevermous 219
									; into a device number in edi
220
	mov	eax, edi						; Application wants it in eax instead
221
	ret	4
222
 
223
; If an error occured, remove all allocated data and exit (returning -1 in eax)
224
 
225
  .destroy:
1519 hidnplayr 226
	dec	[devices]
1237 clevermous 227
	; todo: reset device into virgin state
228
 
229
  .err:
230
	stdcall KernelFree, ebx
231
 
232
 
233
  .fail:
234
	xor	eax, eax
235
	ret	4
236
 
237
 
238
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
239
;;                                                                        ;;
240
;;        Actual Hardware dependent code starts here                      ;;
241
;;                                                                        ;;
242
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
243
 
244
unload:
245
	; TODO: (in this particular order)
246
	;
247
	; - Stop the device
248
	; - Detach int handler
249
	; - Remove device from local list
250
	; - call unregister function in kernel
251
	; - Remove all allocated structures and buffers the card used
252
 
253
	or	eax,-1
254
 
255
ret
256
 
261 hidnplayr 257
;********************************************************************
258
;  Comments:
259
;    Known to work with the following SIS900 ethernet cards:
260
;      -  Device ID: 0x0900   Vendor ID: 0x1039   Revision: 0x91
261
;      -  Device ID: 0x0900   Vendor ID: 0x1039   Revision: 0x90
262
;
263
;    If your card is not listed, try it and let me know if it
264
;    functions properly and it will be aded to the list.  If not
265
;    we may be able to add support for it.
266
;
267
;  ToDo:
268
;     -  Enable MII interface for reading speed
269
;        and duplex settings.
1519 hidnplayr 270
;     -  Update receive routine to support packet fragmentation.
261 hidnplayr 271
;     -  Add additional support for other sis900 based cards
272
;
273
;********************************************************************
274
 
1519 hidnplayr 275
	ETH_ALEN	equ 6		; Size of Ethernet address
276
	ETH_HLEN	equ 14		; Size of ethernet header
277
	ETH_ZLEN	equ 60		; Minimum packet length
278
	DSIZE		equ 0x00000fff
279
	CRC_SIZE	equ 4
280
	RFADDR_shift	equ 16
261 hidnplayr 281
 
1519 hidnplayr 282
; Symbolic offsets to registers.
283
	cr		equ 0x0 	      ; Command Register
284
	cfg		equ 0x4       ; Configuration Register
285
	mear		equ 0x8       ; EEPROM Access Register
286
	ptscr		equ 0xc       ; PCI Test Control Register
287
	isr		equ 0x10      ; Interrupt Status Register
288
	imr		equ 0x14      ; Interrupt Mask Register
289
	ier		equ 0x18      ; Interrupt Enable Register
290
	epar		equ 0x18      ; Enhanced PHY Access Register
291
	txdp		equ 0x20      ; Transmit Descriptor Pointer Register
292
	txcfg		equ 0x24      ; Transmit Configuration Register
293
	rxdp		equ 0x30      ; Receive Descriptor Pointer Register
294
	rxcfg		equ 0x34      ; Receive Configuration Register
295
	flctrl		equ 0x38      ; Flow Control Register
296
	rxlen		equ 0x3c      ; Receive Packet Length Register
297
	rfcr		equ 0x48      ; Receive Filter Control Register
298
	rfdr		equ 0x4C      ; Receive Filter Data Register
299
	pmctrl		equ 0xB0      ; Power Management Control Register
300
	pmer		equ 0xB4      ; Power Management Wake-up Event Register
301
 
302
; Command Register Bits
303
	RELOAD		equ 0x00000400
304
	ACCESSMODE	equ 0x00000200
305
	RESET		equ 0x00000100
306
	SWI		equ 0x00000080
307
	RxRESET 	equ 0x00000020
308
	TxRESET 	equ 0x00000010
309
	RxDIS		equ 0x00000008
310
	RxENA		equ 0x00000004
311
	TxDIS		equ 0x00000002
312
	TxENA		equ 0x00000001
313
 
314
; Configuration Register Bits
315
	DESCRFMT	equ 0x00000100 ; 7016 specific
316
	REQALG		equ 0x00000080
317
	SB		equ 0x00000040
318
	POW		equ 0x00000020
319
	EXD		equ 0x00000010
320
	PESEL		equ 0x00000008
321
	LPM		equ 0x00000004
322
	BEM		equ 0x00000001
323
	RND_CNT 	equ 0x00000400
324
	FAIR_BACKOFF	equ 0x00000200
325
	EDB_MASTER_EN	equ 0x00002000
326
 
327
; Eeprom Access Reigster Bits
328
	MDC		equ 0x00000040
329
	MDDIR		equ 0x00000020
330
	MDIO		equ 0x00000010	; 7016 specific
331
	EECS		equ 0x00000008
332
	EECLK		equ 0x00000004
333
	EEDO		equ 0x00000002
334
	EEDI		equ 0x00000001
335
 
336
; TX Configuration Register Bits
337
	ATP		equ 0x10000000 ;Automatic Transmit Padding
338
	MLB		equ 0x20000000 ;Mac Loopback Enable
339
	HBI		equ 0x40000000 ;HeartBeat Ignore (Req for full-dup)
340
	CSI		equ 0x80000000 ;CarrierSenseIgnore (Req for full-du
341
 
342
; RX Configuration Register Bits
343
	AJAB		equ 0x08000000 ;
344
	ATX		equ 0x10000000 ;Accept Transmit Packets
345
	ARP		equ 0x40000000 ;accept runt packets (<64bytes)
346
	AEP		equ 0x80000000 ;accept error packets
347
 
348
; Interrupt Reigster Bits
349
	WKEVT		equ 0x10000000
350
	TxPAUSEEND	equ 0x08000000
351
	TxPAUSE 	equ 0x04000000
352
	TxRCMP		equ 0x02000000
353
	RxRCMP		equ 0x01000000
354
	DPERR		equ 0x00800000
355
	SSERR		equ 0x00400000
356
	RMABT		equ 0x00200000
357
	RTABT		equ 0x00100000
358
	RxSOVR		equ 0x00010000
359
	HIBERR		equ 0x00008000
360
	SWINT		equ 0x00001000
361
	MIBINT		equ 0x00000800
362
	TxURN		equ 0x00000400
363
	TxIDLE		equ 0x00000200
364
	TxERR		equ 0x00000100
365
	TxDESC		equ 0x00000080
366
	TxOK		equ 0x00000040
367
	RxORN		equ 0x00000020
368
	RxIDLE		equ 0x00000010
369
	RxEARLY 	equ 0x00000008
370
	RxERR		equ 0x00000004
371
	RxDESC		equ 0x00000002
372
	RxOK		equ 0x00000001
373
 
374
; Interrupt Enable Register Bits
375
	IE		equ RxOK + TxOK
376
 
377
; Revision ID
378
	SIS900B_900_REV 	equ 0x03
379
	SIS630A_900_REV 	equ 0x80
380
	SIS630E_900_REV 	equ 0x81
381
	SIS630S_900_REV 	equ 0x82
382
	SIS630EA1_900_REV	equ 0x83
383
	SIS630ET_900_REV	equ 0x84
384
	SIS635A_900_REV 	equ 0x90
385
	SIS900_960_REV		equ 0x91
386
 
387
; Receive Filter Control Register Bits
388
	RFEN		equ 0x80000000
389
	RFAAB		equ 0x40000000
390
	RFAAM		equ 0x20000000
391
	RFAAP		equ 0x10000000
392
	RFPromiscuous	equ 0x70000000
393
 
394
; Reveive Filter Data Mask
395
	RFDAT		equ 0x0000FFFF
396
 
397
; Eeprom Address
398
	EEPROMSignature equ 0x00
399
	EEPROMVendorID	equ 0x02
400
	EEPROMDeviceID	equ 0x03
401
	EEPROMMACAddr	equ 0x08
402
	EEPROMChecksum	equ 0x0b
403
 
261 hidnplayr 404
;The EEPROM commands include the alway-set leading bit.
1519 hidnplayr 405
	EEread		equ 0x0180
406
	EEwrite 	equ 0x0140
407
	EEerase 	equ 0x01C0
408
	EEwriteEnable	equ 0x0130
409
	EEwriteDisable	equ 0x0100
410
	EEeraseAll	equ 0x0120
411
	EEwriteAll	equ 0x0110
412
	EEaddrMask	equ 0x013F
413
	EEcmdShift	equ 16
414
 
261 hidnplayr 415
;For SiS962 or SiS963, request the eeprom software access
1519 hidnplayr 416
	EEREQ		equ 0x00000400
417
	EEDONE		equ 0x00000200
418
	EEGNT		equ 0x00000100
261 hidnplayr 419
 
1519 hidnplayr 420
 
261 hidnplayr 421
;***************************************************************************
1519 hidnplayr 422
;
423
; probe
424
;
425
; Searches for an ethernet card, enables it and clears the rx buffer
426
;
427
; TODO: probe mii transceivers
428
;
261 hidnplayr 429
;***************************************************************************
1519 hidnplayr 430
align 4
431
probe:
261 hidnplayr 432
 
1519 hidnplayr 433
	stdcall PciWrite8, dword [device.pci_bus], dword [device.pci_dev], 0x40, 0	; Wake Up Chip
434
 
435
	make_bus_master [device.pci_bus], [device.pci_dev]
436
 
437
; Get Card Revision
438
	stdcall PciRead8, dword [device.pci_bus], dword [device.pci_dev], 0x08
439
	mov	[pci_revision], al							; save the revision for later use
440
 
441
; Look up through the specific_table
442
	mov	esi, specific_table
443
  .loop:
444
	cmp	dword [esi], 0		     ; Check if we reached end of the list
445
	je	.error
446
	cmp	al, [esi]		     ; Check if revision is OK
447
	je	.ok
448
	add	esi, 12 		     ; Advance to next entry
449
	jmp	.loop
450
 
451
  .error:
452
	DEBUGF	1, "Device not supported!\n"
453
	or	eax, -1
454
	ret
455
 
456
; Find Get Mac Function
457
  .ok:
458
	mov	eax, [esi+4]		; Get pointer to "get MAC" function
459
	mov	[get_mac_func], eax
460
	mov	eax, [esi+8]		; Get pointer to special initialization fn
461
	mov	[special_func], eax
462
 
463
; Get MAC
464
	call	[get_mac_func]
465
 
466
; Call special initialization fn if requested
467
 
468
	cmp	[special_func],0
469
	je	@f
470
	call	[special_func]
471
       @@:
472
 
473
; Set table entries
474
 
475
	mov	 byte [table_entries], 16
476
	cmp	 [pci_revision], SIS635A_900_REV
477
	jae	 @f
478
	cmp	 [pci_revision], SIS900B_900_REV
479
	je	 @f
480
	mov	 byte [table_entries], 8
481
       @@:
482
 
483
; TODO: Probe for mii transceiver
484
 
485
 
261 hidnplayr 486
;***************************************************************************
487
;
1519 hidnplayr 488
; init
489
;
490
; resets the ethernet controller chip and various
261 hidnplayr 491
;    data structures required for sending and receiving packets.
492
;
493
;***************************************************************************
1519 hidnplayr 494
align 4
495
init:
496
 
497
	call reset
498
	call init_rxfilter
499
	call init_txd
500
	call init_rxd
501
	call set_rx_mode
502
	call set_tx_mode
503
	;call check_mode
504
 
1237 clevermous 505
; enable interrupts on packet receive
1519 hidnplayr 506
 
1237 clevermous 507
	xor	eax, eax
1519 hidnplayr 508
	inc	eax	; eax = 1 = RxOK
509
	set_io	0
510
	set_io	imr
1237 clevermous 511
	out	dx, eax
1519 hidnplayr 512
 
1237 clevermous 513
; globally enable interrupts
1519 hidnplayr 514
 
515
	set_io	ier
1254 hidnplayr 516
	out	dx, eax ; eax is still 1
1237 clevermous 517
	xor	eax, eax
261 hidnplayr 518
 
1519 hidnplayr 519
	mov	[device.mtu], 1514
520
 
521
	ret
522
 
261 hidnplayr 523
;***************************************************************************
524
;
1519 hidnplayr 525
; reset
526
;
527
; disables interrupts and soft resets the controller chip
528
;
261 hidnplayr 529
;***************************************************************************
1519 hidnplayr 530
align 4
531
reset:
532
	movzx	eax, [device.irq_line]
1254 hidnplayr 533
	stdcall AttachIntHandler, eax, int_handler, 0
261 hidnplayr 534
 
1519 hidnplayr 535
;--------------------------------------------
536
; Disable Interrupts and reset Receive Filter
537
 
538
	set_io	0
539
	set_io	ier
540
	xor	eax, eax
541
	out	dx, eax
542
 
543
	set_io	imr
544
	out	dx, eax
545
 
546
	set_io	rfcr
547
	out	dx, eax
548
 
549
;-----------
550
; Reset Card
551
 
552
	set_io	cr
553
	in	eax, dx 			; Get current Command Register
554
	or	eax, RESET + RxRESET + TxRESET	; set flags
555
	out	dx, eax 			; Write new Command Register
556
 
557
;----------
558
; Wait loop
559
 
560
	set_io	isr
561
	mov	ecx, 1000
562
  .loop:
563
	dec	ecx
564
	jz	.error
565
	in	eax, dx 			; move interrup status to eax
566
	cmp	eax, 0x03000000
567
	jne	.loop
568
 
569
;------------------------------------------------------
570
; Set Configuration Register depending on Card Revision
571
 
572
	set_io	cfg
573
	mov	eax, PESEL			; Configuration Register Bit
574
	cmp	[pci_revision], SIS635A_900_REV
575
	je	.match
576
	cmp	[pci_revision], SIS900B_900_REV ; Check card revision
577
	je	.match
578
	out	dx, eax 			; no revision match
579
	jmp	.done
580
 
581
  .match:					; Revision match
582
	or	eax, RND_CNT			; Configuration Register Bit
583
	out	dx, eax
584
 
585
  .done:
586
	xor	eax, eax
587
	ret
588
 
589
  .error:
590
	DEBUGF	1, "Reset failed!\n"
591
	or	eax, -1
592
	ret
593
 
594
 
261 hidnplayr 595
;***************************************************************************
596
;
1519 hidnplayr 597
; sis_init_rxfilter
261 hidnplayr 598
;
1519 hidnplayr 599
; sets receive filter address to our MAC address
261 hidnplayr 600
;
601
;***************************************************************************
1519 hidnplayr 602
align 4
603
init_rxfilter:
261 hidnplayr 604
 
1519 hidnplayr 605
;------------------------------------
606
; Get Receive Filter Control Register
607
 
608
	set_io	0
609
	set_io	rfcr
610
	in	eax, dx
611
	push	eax
612
 
613
;-----------------------------------------------
614
; disable packet filtering before setting filter
615
 
616
	and	eax, not RFEN
617
	out	dx, eax
618
 
619
;--------------------------------------
620
; load MAC addr to filter data register
621
 
622
	xor	ecx, ecx
623
RXINT_Mac_Write:	; high word of eax tells card which mac byte to write
624
	mov	eax, ecx
625
	set_io	0
626
	set_io	rfcr
627
	shl	eax, 16 					    ;
628
	out	dx, eax 					    ;
629
	set_io	rfdr
630
	mov	ax, word [device.mac+ecx*2]			    ; Get Mac ID word
631
	out	dx, ax						    ; Send Mac ID
632
	inc	cl						    ; send next word
633
	cmp	cl, 3						    ; more to send?
634
	jne	RXINT_Mac_Write
635
 
636
;------------------------
637
; enable packet filtering
638
 
639
	pop	eax				;old register value
640
	set_io	rfcr
641
	or	eax, RFEN    ;enable filtering
642
	out	dx, eax 	    ;set register
643
 
644
	ret
645
 
261 hidnplayr 646
;***************************************************************************
1519 hidnplayr 647
;
648
; init_txd
649
;
650
; initializes the Tx descriptor
651
;
261 hidnplayr 652
;***************************************************************************
1519 hidnplayr 653
align 4
654
init_txd:
261 hidnplayr 655
 
1519 hidnplayr 656
;-------------------------
657
; initialize TX descriptor
658
 
659
	mov	dword [device.txd], 0		; put link to next descriptor in link field
660
	mov	dword [device.txd+4], 0 	; clear status field
661
	mov	dword [device.txd+8], 0 	; ptr to buffer
662
 
663
;----------------------------------
664
; load Transmit Descriptor Register
665
 
666
	set_io	0
667
	set_io	txdp			; TX Descriptor Pointer
668
	lea	eax, [device.txd]
669
	GetRealAddr
670
	out	dx, eax 			    ; move the pointer
671
 
672
	ret
673
 
261 hidnplayr 674
;***************************************************************************
1519 hidnplayr 675
;
676
; init_rxd
677
;
678
; initializes the Rx descriptor ring
679
;
261 hidnplayr 680
;***************************************************************************
1519 hidnplayr 681
align 4
682
init_rxd:
261 hidnplayr 683
 
1519 hidnplayr 684
; init RX descriptors
685
	mov	ecx, NUM_RX_DESC
686
	lea	esi, [device.rxd]
687
 
688
  .loop:
689
	lea	eax, [esi + 16]
690
	GetRealAddr
691
	mov	dword [esi+0], eax
692
	mov	dword [esi+4], RX_BUFF_SZ
693
 
694
	stdcall KernelAlloc, RX_BUFF_SZ
695
	test	eax, eax
696
	jz	.fail
697
	mov	dword [esi+12], eax
698
	GetRealAddr
699
	mov	dword [esi+8], eax
700
	add	esi, 16
701
	loop	.loop
702
 
703
	lea	eax, [device.rxd]
704
	GetRealAddr
705
	mov	dword [esi - 16], eax	; correct last descriptor link ptr
706
 
707
; And output ptr to first desc, to device
708
 
709
	set_io	0
710
	set_io	rxdp
711
	out	dx, eax
712
 
713
	mov	[device.cur_rx], 0	; Set curent rx discriptor to 0
714
 
715
  .fail:	;;; TODO: abort instead!
716
	ret
717
 
718
 
261 hidnplayr 719
;***************************************************************************
1519 hidnplayr 720
;
721
; set_tx_mode
722
;
723
; sets the transmit mode to allow for full duplex
724
;
725
; If you are having problems transmitting packet try changing the
726
; Max DMA Burst, Possible settings are as follows:
727
;
728
; 0x00000000 = 512 bytes
729
; 0x00100000 = 4 bytes
730
; 0x00200000 = 8 bytes
731
; 0x00300000 = 16 bytes
732
; 0x00400000 = 32 bytes
733
; 0x00500000 = 64 bytes
734
; 0x00600000 = 128 bytes
735
; 0x00700000 = 256 bytes
736
;
261 hidnplayr 737
;***************************************************************************
1519 hidnplayr 738
align 4
739
set_tx_mode:
261 hidnplayr 740
 
1519 hidnplayr 741
	set_io	0
742
	set_io	cr
743
	in	eax, dx 			; Get current Command Register
744
	or	eax, TxENA			; Enable Receive
745
	out	dx, eax
746
 
747
	set_io	txcfg					; Transmit config Register offset
748
	mov	eax, ATP + HBI + CSI +0x00600120
749
	; allow automatic padding
750
	; allow heartbeat ignore
751
	; allow carrier sense ignore
752
	; Max DMA Burst (128 bytes)
753
	; TX Fill Threshold
754
	; TX Drain Threshold
755
	out	 dx, eax
756
 
757
	ret
758
 
261 hidnplayr 759
;***************************************************************************
1519 hidnplayr 760
;
761
; set_rx_mode
762
;
763
; sets the receive mode to accept all broadcast packets and packets
764
; with our MAC address, and reject all multicast packets.  Also allows
765
; full-duplex
766
;
767
; If you are having problems receiving packet try changing the
768
; Max DMA Burst, Possible settings are as follows:
769
;
770
; 0x00000000 = 512 bytes
771
; 0x00100000 = 4 bytes
772
; 0x00200000 = 8 bytes
773
; 0x00300000 = 16 bytes
774
; 0x00400000 = 32 bytes
775
; 0x00500000 = 64 bytes
776
; 0x00600000 = 128 bytes
777
; 0x00700000 = 256 bytes
778
;
261 hidnplayr 779
;***************************************************************************
1519 hidnplayr 780
align 4
781
set_rx_mode:
261 hidnplayr 782
 
1519 hidnplayr 783
;----------------------------------------------
784
; update Multicast Hash Table in Receive Filter
785
 
786
	xor	 cl, cl
787
  .loop:
788
	set_io	 0
789
	set_io	 rfcr			; Receive Filter Control Reg offset
790
	mov	 eax, 4 		; determine table entry
791
	add	 al, cl
792
	shl	 eax, 16
793
	out	 dx, eax		; tell card which entry to modify
794
 
795
	set_io	 rfdr			; Receive Filter Control Reg offset
796
	mov	 eax, 0xffff		; entry value
797
	out	 dx, ax 		; write value to table in card
798
 
799
	inc	 cl			; next entry
800
	cmp	 cl, [table_entries]
801
	jl	 .loop
802
 
803
;------------------------------------
804
; Set Receive Filter Control Register
805
 
806
	set_io	rfcr			; Receive Filter Control Register offset
807
	mov	eax, RFAAB + RFAAM + RFAAP + RFEN
808
	; accecpt all broadcast packets
809
	; accept all multicast packets
810
	; Accept all packets
811
	; enable receiver filter
812
	out	dx, eax
813
;----------------
814
; Enable Receiver
815
 
816
	set_io	cr
817
	in	eax, dx 		; Get current Command Register
818
	or	eax, RxENA		; Enable Receive
819
	out	dx, eax
820
 
821
;-------------------
822
; Configure Receiver
823
 
824
	set_io	rxcfg			; Receive Config Register offset
825
	mov	eax, ATX + 0x00600002
826
	; Accept Transmit Packets
827
	; (Req for full-duplex and PMD Loopback)
828
	; Max DMA Burst
829
	; RX Drain Threshold, 8X8 bytes or 64bytes
830
	out	 dx, eax
831
 
832
	ret
833
 
261 hidnplayr 834
;***************************************************************************
1519 hidnplayr 835
;
836
; SIS960_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
837
;
838
; SiS962 or SiS963 model, use EEPROM to store MAC address.
839
; EEPROM is shared by LAN and 1394.
840
; When access EEPROM, send EEREQ signal to hardware first, and wait for EEGNT.
841
; If EEGNT is ON, EEPROM is permitted to be accessed by LAN, otherwise is not.
842
; After MAC address is read from EEPROM, send
843
; EEDONE signal to refuse EEPROM access by LAN.
844
; The EEPROM map of SiS962 or SiS963 is different to SiS900.
845
; The signature field in SiS962 or SiS963 spec is meaningless.
846
;
847
; Return 0 is EAX = failure
848
;
261 hidnplayr 849
;***************************************************************************
1519 hidnplayr 850
align 4
261 hidnplayr 851
SIS960_get_mac_addr:
1519 hidnplayr 852
 
853
;-------------------------------
854
; Send Request for eeprom access
855
 
856
	set_io	0
857
	set_io	mear		; Eeprom access register
858
	mov	eax, EEREQ	; Request access to eeprom
859
	out	dx, eax 	; Send request
860
 
861
;-----------------------------------------------------
862
; Loop 4000 times and if access not granted, error out
863
 
864
	mov	ecx, 4000
865
  .loop:
866
	in	eax, dx 	; get eeprom status
867
	test	eax, EEGNT	; see if eeprom access granted flag is set
868
	jnz	.got_access	; if it is, go access the eeprom
869
	loop	.loop		; else keep waiting
870
 
871
	DEBUGF	1, "Access to EEprom failed!\n", 0
872
 
873
	set_io	mear		; Eeprom access register
874
	mov	eax, EEDONE	; tell eeprom we are done
875
	out	dx, eax
876
 
877
	or	eax, -1 	; error
878
	ret
879
 
880
  .got_access:
881
 
882
;------------------------------------------
883
; EEprom access granted, read MAC from card
884
 
261 hidnplayr 885
    ; zero based so 3-16 bit reads will take place
1519 hidnplayr 886
 
887
	mov	ecx, 2
888
  .read_loop:
889
	mov	eax, EEPROMMACAddr	; Base Mac Address
890
	add	eax, ecx		; Current Mac Byte Offset
891
	push	ecx
892
	call	read_eeprom		; try to read 16 bits
893
	pop	ecx
894
	mov	word [device.mac+ecx*2], ax	; save 16 bits to the MAC ID varible
895
	dec	ecx			; one less word to read
896
	jns	.read_loop		; if more read more
897
	mov	eax, 1			; return non-zero indicating success
898
 
899
	DEBUGF	2,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
900
 
901
;-------------------------------------
902
; Tell EEPROM We are Done Accessing It
903
 
904
  .done:
905
	set_io	0
906
	set_io	mear		; Eeprom access register
907
	mov	eax, EEDONE	; tell eeprom we are done
908
	out	dx, eax
909
 
910
	xor	eax, eax	; ok
911
	ret
912
 
913
 
914
 
915
 
261 hidnplayr 916
;***************************************************************************
1519 hidnplayr 917
;
918
; get_mac_addr: - Get MAC address for stand alone SiS900 model
919
;
920
; Older SiS900 and friends, use EEPROM to store MAC address.
921
;
261 hidnplayr 922
;***************************************************************************
1519 hidnplayr 923
align 4
924
get_mac_addr:
261 hidnplayr 925
 
1519 hidnplayr 926
;------------------------------------
927
; check to see if we have sane EEPROM
928
 
929
	mov	eax, EEPROMSignature  ; Base Eeprom Signature
930
	call	read_eeprom	      ; try to read 16 bits
931
	cmp	ax, 0xffff
932
	je	.err
933
	test	ax, ax
934
	je	.err
935
 
936
;-----------
937
; Read MacID
938
 
939
; zero based so 3-16 bit reads will take place
940
 
941
	mov	ecx, 2
942
  .loop:
943
	mov	eax, EEPROMMACAddr    ;Base Mac Address
944
	add	eax, ecx				 ;Current Mac Byte Offset
945
	push	ecx
946
	call	read_eeprom	      ;try to read 16 bits
947
	pop	ecx
948
	mov	word [device.mac+ecx*2], ax	   ;save 16 bits to the MAC ID storage
949
	dec	ecx			     ;one less word to read
950
	jns	mac_read_loop	      ;if more read more
951
 
952
	DEBUGF	2,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
953
 
954
	xor	eax, eax
955
	ret
956
 
957
 
958
  .err:
959
	DEBUGF	1, "Access to EEprom failed!\n", 0
960
 
961
	or	eax, -1
962
	ret
963
 
964
 
261 hidnplayr 965
;***************************************************************************
1519 hidnplayr 966
;
967
; Get_Mac_SIS635_900_REV: - Get MAC address for model 635
968
;
261 hidnplayr 969
;***************************************************************************
1519 hidnplayr 970
align 4
261 hidnplayr 971
Get_Mac_SIS635_900_REV:
1519 hidnplayr 972
 
973
	set_io	0
974
	set_io	rfcr
975
	in	eax, dx
976
	mov	edi, eax ; EDI=rfcrSave
977
 
978
	set_io	cr
979
	or	eax, RELOAD
980
	out	dx, eax
981
 
982
	xor	eax, eax
983
	out	dx, eax
984
 
985
;-----------------------------------------------
986
; Disable packet filtering before setting filter
987
 
988
	set_io	rfcr
989
	mov	eax, edi
990
	and	edi, not RFEN
991
	out	dx, eax
992
 
993
;---------------------------------
994
; Load MAC to filter data register
995
 
996
	mov	ecx, 3
997
	lea	edi, [device.mac]
998
  .loop:
999
	set_io	0
1000
	set_io	rfcr
1001
	mov	eax, ecx
1002
	shl	eax, RFADDR_shift
1003
	out	dx, eax
1004
 
1005
	set_io	rfdr
1006
	in	eax, dx
1007
	stosw
1008
	loop	.loop
1009
 
1010
;------------------------
1011
; Enable packet filtering
1012
 
1013
;        set_io  rfcr
1014
;        mov     eax, edi
1015
;        or      eax, RFEN
1016
;        out     dx, eax
1017
 
1018
	xor	eax, eax
1019
	ret
1020
 
261 hidnplayr 1021
;***************************************************************************
1022
;
1519 hidnplayr 1023
; read_eeprom
261 hidnplayr 1024
;
1519 hidnplayr 1025
; reads and returns a given location from EEPROM
261 hidnplayr 1026
;
1519 hidnplayr 1027
; IN:  si = addr
1028
; OUT: ax = data
261 hidnplayr 1029
;
1030
;***************************************************************************
1519 hidnplayr 1031
align 4
1032
read_eeprom:
261 hidnplayr 1033
 
1519 hidnplayr 1034
	set_io	0
1035
	set_io	mear
1036
 
1037
	xor	eax, eax	      ; start send
1038
	out	dx, eax
1039
	ee_delay
1040
 
1041
	or	eax, EECLK
1042
	out	dx, eax
1043
	ee_delay
1044
 
1045
;------------------------------------
1046
; Send the read command
1047
 
1048
	or	esi, EEread
1049
	mov	ecx, 1 shl 9
1050
 
1051
  .loop:
1052
	mov	eax, EECS
1053
	test	esi, ecx
1054
	jz	@f
1055
	or	eax, EEDI
1056
       @@:
1057
	out	dx, eax
1058
	ee_delay
1059
 
1060
	or	eax, EECLK
1061
	out	dx, eax
1062
	ee_delay
1063
 
1064
	shr	esi, 1
1065
	jnc	.loop
1066
 
1067
	mov	eax, EECS
1068
	out	dx, eax
1069
	ee_delay
1070
 
1071
;------------------------
1072
; Read 16-bits of data in
1073
 
1074
	xor	esi, esi
1075
	mov	cx, 16
1076
  .loop2:
1077
	mov	eax, EECS
1078
	out	dx, eax
1079
	ee_delay
1080
 
1081
	or	eax, EECLK
1082
	out	dx, eax
1083
	ee_delay
1084
 
1085
	in	eax, dx
1086
	shl	esi, 1
1087
	test	eax, EEDO
1088
	jz	@f
1089
	inc	esi
1090
       @@:
1091
	loop	.loop2
1092
 
1093
;----------------------------
1094
; Terminate the EEPROM access
1095
 
1096
	xor	eax, eax
1097
	out	dx, eax
1098
	ee_delay
1099
 
1100
	mov	eax, EECLK
1101
	out	dx, eax
1102
	ee_delay
1103
 
1104
	movzx	eax, si
1105
 
1106
	ret
1107
 
1108
 
1109
 
1110
align 4
1237 clevermous 1111
write_mac:
1112
	DEBUGF 1,'Setting MAC is not supported for SIS900 card.\n'
1113
	add	esp, 6
1114
	ret
1115
 
261 hidnplayr 1116
;***************************************************************************
1117
;
1519 hidnplayr 1118
; int_handler
1119
;
1120
; handles received IRQs, which signal received packets
1121
;
1122
; Currently only supports one descriptor per packet, if packet is fragmented
1123
; between multiple descriptors you will lose part of the packet
1124
;
261 hidnplayr 1125
;***************************************************************************
1519 hidnplayr 1126
align 4
1237 clevermous 1127
int_handler:
1128
; find pointer of device which made IRQ occur
1519 hidnplayr 1129
	mov	esi, device_list
1130
	mov	ecx, [devices]
1237 clevermous 1131
	test	ecx, ecx
1132
	jz	.nothing
1133
.nextdevice:
1134
	mov	ebx, [esi]
1519 hidnplayr 1135
	set_io	0
1136
	set_io	isr
1254 hidnplayr 1137
	in	eax, dx ; note that this clears all interrupts
1519 hidnplayr 1138
	test	ax, IE
1237 clevermous 1139
	jnz	.got_it
1140
	loop	.nextdevice
1141
.nothing:
1142
	ret
1143
.got_it:
1519 hidnplayr 1144
 
1145
	test	ax, RxOK
1146
	jz	.no_rx
1147
 
1148
	push	ax
1149
 
1150
;-----------
1151
; Get Status
1152
	movzx	eax, [device.cur_rx]		; find current discriptor
1153
	shl	eax, 4				; * 16
1154
	mov	ecx, dword[device.rxd+eax+4]	; get receive status
1155
 
1156
;-------------------------------------------
1157
; Check RX_Status to see if packet is waiting
1158
	test	ecx, 0x80000000
1159
	jnz	.is_packet
1160
	ret
1161
 
1162
;----------------------------------------------
1163
; There is a packet waiting check it for errors
1164
  .is_packet:
1165
	test	ecx, 0x67C0000			; see if there are any errors
1166
	jnz	.error_status
1167
 
1168
;---------------------
1169
; Check size of packet
1170
	and	ecx, DSIZE			; get packet size minus CRC
1171
	sub	ecx, CRC_SIZE			; make sure packet contains data
1172
	jle	.error_size
1173
 
1174
; update statistics
1175
	inc	dword [device.packets_rx]
1176
	add	dword [device.bytes_rx], ecx
1177
	adc	dword [device.bytes_rx+4], 0
1178
 
1179
	push	ebx
1180
	push	.return
1181
	push	ecx				; packet size
1182
	push	[device.rxd+eax+12]		; packet ptr
1183
	DEBUGF	1, "Packet received OK\n"
1184
	jmp	EthReceiver
1185
  .return:
1186
	pop	ebx
1187
 
1188
; Reset status, allow ethernet card access to descriptor
1189
	movzx	ecx, [device.cur_rx]
1190
	shl	ecx, 4				; *16
1191
	mov	ecx, [device.rxd+ecx]
1192
	stdcall KernelAlloc, RX_BUFF_SZ
1193
	test	eax, eax
1194
	jz	.fail
1195
	mov	dword [ecx+12], eax
1196
	GetRealAddr
1197
	mov	dword [ecx+8], eax
1198
	mov	dword [ecx+4], RX_BUFF_SZ
1199
 
1200
	inc	[device.cur_rx] 			 ; get next descriptor
1201
	and	[device.cur_rx], NUM_RX_DESC-1		 ; only 4 descriptors 0-3
1202
 
1203
; Enable Receiver
1204
	set_io	0
1205
	set_io	cr		; Command Register offset
1206
	in	eax, dx 	; Get current Command Register
1207
	or	eax, RxENA	; Enable Receiver
1208
	out	dx, eax
1209
 
1210
	pop	ax
1211
	jmp	.no_rx
1212
 
1213
  .error_status:
1214
 
1215
	DEBUGF	1, "Packet error: %x\n", ecx
1216
	jmp	.continue
1217
 
1218
  .error_size:
1219
 
1220
	DEBUGF	1, "Packet too large/small\n"
1221
	jmp	.continue
1222
 
1223
  .no_rx:
1224
	test	ax, TxOk
1225
	jz	.no_tx
1226
 
1227
	;;; TODO: free all unused buffers
1228
	stdcall   KernelFree, eax
1229
 
1230
  .no_tx:
1231
 
1232
	ret
1233
 
1234
 
1235
 
261 hidnplayr 1236
;***************************************************************************
1237
;   Function
1237 clevermous 1238
;      transmit
261 hidnplayr 1239
;   Description
1240
;      Transmits a packet of data via the ethernet card
1254 hidnplayr 1241
;         buffer pointer in [esp+4]
1242
;         size of buffer in [esp+8]
1237 clevermous 1243
;         pointer to device structure in ebx
261 hidnplayr 1244
;
1245
;      only one transmit descriptor is used
1246
;
1247
;***************************************************************************
1519 hidnplayr 1248
align 4
1237 clevermous 1249
transmit:
261 hidnplayr 1250
 
1519 hidnplayr 1251
	cmp	dword [esp+8], MAX_ETH_FRAME_SIZE
1252
	jg	transmit_finish
261 hidnplayr 1253
 
1519 hidnplayr 1254
	cmp	dword [esp+8], 60
1255
	jl	transmit_finish
1237 clevermous 1256
 
1519 hidnplayr 1257
	movzx	ecx, [device.cur_tx]
1258
	mov	ecx, [device.txd+ecx*16]
1259
 
1260
;; TODO: check if desc is empty (for example: check for eax, 0x6200000  at [ecx+4]
1261
;;; or: count number of available descriptors
1262
 
1263
	mov	eax, [esp+4]
1264
	mov	dword [ecx + 12], eax
1265
	GetRealAddr
1266
	mov	dword [ecx + 8], eax
1267
 
1268
	mov	eax, [esp+8]
1269
	and	eax, DSIZE
1270
	or	eax, 0x80000000 	; card owns descriptor
1271
	mov	dword [ecx + 4], eax
1272
 
1273
; update stats
1274
	inc	[device.packets_tx]
1275
	add	dword [device.bytes_tx], ecx
1276
	adc	dword [device.bytes_tx+4], 0
1277
 
1541 hidnplayr 1278
	ret	8
1519 hidnplayr 1279
 
1280
 
1237 clevermous 1281
; End of code
1282
 
1283
align 4 					; Place all initialised data here
1284
 
1519 hidnplayr 1285
devices 	dd 0
1237 clevermous 1286
 
1519 hidnplayr 1287
specific_table:
1237 clevermous 1288
;    dd SIS630A_900_REV,Get_Mac_SIS630A_900_REV,0
1289
;    dd SIS630E_900_REV,Get_Mac_SIS630E_900_REV,0
1290
    dd SIS630S_900_REV,Get_Mac_SIS635_900_REV,0
1291
    dd SIS630EA1_900_REV,Get_Mac_SIS635_900_REV,0
1292
    dd SIS630ET_900_REV,Get_Mac_SIS635_900_REV,0;SIS630ET_900_REV_SpecialFN
1293
    dd SIS635A_900_REV,Get_Mac_SIS635_900_REV,0
1294
    dd SIS900_960_REV,SIS960_get_mac_addr,0
1519 hidnplayr 1295
    dd SIS900B_900_REV,get_mac_addr,0
1296
    dd 0					; end of list
1237 clevermous 1297
 
1519 hidnplayr 1298
version 	dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
1299
my_service	db 'SIS900',0		       ; max 16 chars include zero
1237 clevermous 1300
 
1519 hidnplayr 1301
include_debug_strings			       ; All data wich FDO uses will be included here
1237 clevermous 1302
 
1519 hidnplayr 1303
section '.data' data readable writable align 16; place all uninitialized data place here
1237 clevermous 1304
 
1519 hidnplayr 1305
device_list	rd MAX_DEVICES		       ; This list contains all pointers to device structures the driver is handling
1237 clevermous 1306