Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1886 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  R6040 driver for KolibriOS                                     ;;
7
;;                                                                 ;;
8
;;  based on R6040.c from linux                                    ;;
9
;;                                                                 ;;
10
;;    Written by Asper (asper.85@mail.ru)                          ;;
11
;;            and hidnplayr (hidnplayr@gmail.com)                  ;;
12
;;                                                                 ;;
13
;;          GNU GENERAL PUBLIC LICENSE                             ;;
14
;;             Version 2, June 1991                                ;;
15
;;                                                                 ;;
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
 
18
format MS COFF
19
 
20
	API_VERSION		equ 0x01000100
21
	DRIVER_VERSION		equ 5
22
 
23
	MAX_DEVICES		equ 16
24
 
25
	DEBUG			equ 1
26
	__DEBUG__		equ 1
1893 hidnplayr 27
	__DEBUG_LEVEL__ 	equ 2
1886 hidnplayr 28
 
1893 hidnplayr 29
	W_MAX_TIMEOUT		equ 0x0FFF	; max time out delay time
30
 
31
	TX_TIMEOUT		equ 6000	; Time before concluding the transmitter is hung, in ms
32
 
33
	TX_RING_SIZE		equ 4		; RING sizes must be a power of 2
1886 hidnplayr 34
	RX_RING_SIZE		equ 4
35
 
1893 hidnplayr 36
	RX_BUF_LEN_IDX		equ 3		; 0==8K, 1==16K, 2==32K, 3==64K
1886 hidnplayr 37
 
1893 hidnplayr 38
; Threshold is bytes transferred to chip before transmission starts.
39
 
40
	TX_FIFO_THRESH		equ 256 	; In bytes, rounded down to 32 byte units.
41
 
42
; The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024.
43
 
44
	RX_FIFO_THRESH		equ 4		; Rx buffer level before first PCI xfer.
45
	RX_DMA_BURST		equ 4		; Maximum PCI burst, '4' is 256 bytes
46
	TX_DMA_BURST		equ 4
47
 
48
 
49
 
1886 hidnplayr 50
include 'proc32.inc'
51
include 'imports.inc'
52
include 'fdo.inc'
53
include 'netdrv.inc'
54
 
55
public START
56
public service_proc
57
public version
58
 
1893 hidnplayr 59
; Operational parameters that usually are not changed.
1886 hidnplayr 60
 
61
PHY1_ADDR	equ 1	    ;For MAC1
62
PHY2_ADDR	equ 3	    ;For MAC2
63
PHY_MODE	equ 0x3100  ;PHY CHIP Register 0
64
PHY_CAP 	equ 0x01E1  ;PHY CHIP Register 4
65
 
66
;**************************************************************************
67
; RDC R6040 Register Definitions
68
;**************************************************************************
69
MCR0		equ 0x00    ;Control register 0
70
MCR1		equ 0x01    ;Control register 1
71
MAC_RST 	equ 0x0001  ;Reset the MAC
72
MBCR		equ 0x08    ;Bus control
73
MT_ICR		equ 0x0C    ;TX interrupt control
74
MR_ICR		equ 0x10    ;RX interrupt control
75
MTPR		equ 0x14    ;TX poll command register
76
MR_BSR		equ 0x18    ;RX buffer size
77
MR_DCR		equ 0x1A    ;RX descriptor control
78
MLSR		equ 0x1C    ;Last status
79
MMDIO		equ 0x20    ;MDIO control register
80
MDIO_WRITE	equ 0x4000  ;MDIO write
81
MDIO_READ	equ 0x2000  ;MDIO read
82
MMRD		equ 0x24    ;MDIO read data register
83
MMWD		equ 0x28    ;MDIO write data register
84
MTD_SA0 	equ 0x2C    ;TX descriptor start address 0
85
MTD_SA1 	equ 0x30    ;TX descriptor start address 1
86
MRD_SA0 	equ 0x34    ;RX descriptor start address 0
87
MRD_SA1 	equ 0x38    ;RX descriptor start address 1
88
MISR		equ 0x3C    ;Status register
89
MIER		equ 0x40    ;INT enable register
90
MSK_INT 	equ 0x0000  ;Mask off interrupts
91
RX_FINISH	equ 0x0001  ;RX finished
92
RX_NO_DESC	equ 0x0002  ;No RX descriptor available
93
RX_FIFO_FULL	equ 0x0004  ;RX FIFO full
94
RX_EARLY	equ 0x0008  ;RX early
95
TX_FINISH	equ 0x0010  ;TX finished
96
TX_EARLY	equ 0x0080  ;TX early
97
EVENT_OVRFL	equ 0x0100  ;Event counter overflow
98
LINK_CHANGED	equ 0x0200  ;PHY link changed
99
ME_CISR 	equ 0x44    ;Event counter INT status
100
ME_CIER 	equ 0x48    ;Event counter INT enable
101
MR_CNT		equ 0x50    ;Successfully received packet counter
102
ME_CNT0 	equ 0x52    ;Event counter 0
103
ME_CNT1 	equ 0x54    ;Event counter 1
104
ME_CNT2 	equ 0x56    ;Event counter 2
105
ME_CNT3 	equ 0x58    ;Event counter 3
106
MT_CNT		equ 0x5A    ;Successfully transmit packet counter
107
ME_CNT4 	equ 0x5C    ;Event counter 4
108
MP_CNT		equ 0x5E    ;Pause frame counter register
109
MAR0		equ 0x60    ;Hash table 0
110
MAR1		equ 0x62    ;Hash table 1
111
MAR2		equ 0x64    ;Hash table 2
112
MAR3		equ 0x66    ;Hash table 3
113
MID_0L		equ 0x68    ;Multicast address MID0 Low
114
MID_0M		equ 0x6A    ;Multicast address MID0 Medium
115
MID_0H		equ 0x6C    ;Multicast address MID0 High
116
MID_1L		equ 0x70    ;MID1 Low
117
MID_1M		equ 0x72    ;MID1 Medium
118
MID_1H		equ 0x74    ;MID1 High
119
MID_2L		equ 0x78    ;MID2 Low
120
MID_2M		equ 0x7A    ;MID2 Medium
121
MID_2H		equ 0x7C    ;MID2 High
122
MID_3L		equ 0x80    ;MID3 Low
123
MID_3M		equ 0x82    ;MID3 Medium
124
MID_3H		equ 0x84    ;MID3 High
125
PHY_CC		equ 0x88    ;PHY status change configuration register
126
PHY_ST		equ 0x8A    ;PHY status register
127
MAC_SM		equ 0xAC    ;MAC status machine
128
MAC_ID		equ 0xBE    ;Identifier register
1893 hidnplayr 129
 
1886 hidnplayr 130
MAX_BUF_SIZE	equ 0x600   ;1536
131
 
132
MBCR_DEFAULT	equ 0x012A  ;MAC Bus Control Register
133
MCAST_MAX	equ 3	    ;Max number multicast addresses to filter
134
 
135
;Descriptor status
136
DSC_OWNER_MAC	equ 0x8000  ;MAC is the owner of this descriptor
137
DSC_RX_OK	equ 0x4000  ;RX was successfull
138
DSC_RX_ERR	equ 0x0800  ;RX PHY error
139
DSC_RX_ERR_DRI	equ 0x0400  ;RX dribble packet
140
DSC_RX_ERR_BUF	equ 0x0200  ;RX length exceeds buffer size
141
DSC_RX_ERR_LONG equ 0x0100  ;RX length > maximum packet length
142
DSC_RX_ERR_RUNT equ 0x0080  ;RX packet length < 64 byte
143
DSC_RX_ERR_CRC	equ 0x0040  ;RX CRC error
144
DSC_RX_BCAST	equ 0x0020  ;RX broadcast (no error)
145
DSC_RX_MCAST	equ 0x0010  ;RX multicast (no error)
146
DSC_RX_MCH_HIT	equ 0x0008  ;RX multicast hit in hash table (no error)
147
DSC_RX_MIDH_HIT equ 0x0004  ;RX MID table hit (no error)
148
DSC_RX_IDX_MID_MASK  equ 3  ;RX mask for the index of matched MIDx
149
 
150
;PHY settings
151
ICPLUS_PHY_ID	equ 0x0243
152
 
153
RX_INTS 	equ RX_FIFO_FULL or RX_NO_DESC or RX_FINISH
154
TX_INTS 	equ TX_FINISH
155
INT_MASK	equ RX_INTS or TX_INTS
156
 
1893 hidnplayr 157
RX_BUF_LEN	equ (8192 << RX_BUF_LEN_IDX)	; Size of the in-memory receive ring.
1886 hidnplayr 158
 
1893 hidnplayr 159
IO_SIZE 	equ 256     ; RDC MAC I/O Size
160
MAX_MAC 	equ 2	    ; MAX RDC MAC
161
 
162
 
1886 hidnplayr 163
virtual at 0
164
x_head:
165
  .status	  dw ?	 ;0-1
166
  .len		  dw ?	 ;2-3
167
  .buf		  dd ?	 ;4-7
168
  .ndesc	  dd ?	 ;8-B
169
  .rev1 	  dd ?	 ;C-F
170
  .vbufp	  dd ?	 ;10-13
171
  .vndescp	  dd ?	 ;14-17
172
  .skb_ptr	  dd ?	 ;18-1B
173
  .rev2 	  dd ?	 ;1C-1F
174
  .sizeof:
175
end virtual
176
 
177
 
178
virtual at ebx
179
 
180
	device:
181
 
182
	ETH_DEVICE
183
 
184
	.io_addr	dd ?
185
 
186
	.cur_rx 	dw ?
187
	.cur_tx 	dw ?
1889 hidnplayr 188
	.last_tx	dw ?
1886 hidnplayr 189
	.phy_addr	dw ?
190
	.phy_mode	dw ?
191
	.mcr0		dw ?
192
	.mcr1		dw ?
193
	.switch_sig	dw ?
194
 
195
	.pci_bus	db ?
196
	.pci_dev	db ?
197
	.irq_line	db ?
198
 
1889 hidnplayr 199
	rb 1		; dword alignment
1886 hidnplayr 200
 
201
	.tx_ring:	rb (((x_head.sizeof*TX_RING_SIZE)+32) and 0xfffffff0)
202
	.rx_ring:	rb (((x_head.sizeof*RX_RING_SIZE)+32) and 0xfffffff0)
203
 
204
	.size = $ - device
205
 
206
end virtual
207
 
208
 
209
 
210
section '.flat' code readable align 16
211
 
212
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
213
;;                        ;;
214
;; proc START             ;;
215
;;                        ;;
216
;; (standard driver proc) ;;
217
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
218
 
219
align 4
220
proc START stdcall, state:dword
221
 
222
	cmp [state], 1
223
	jne .exit
224
 
225
  .entry:
226
 
227
	DEBUGF	2,"Loading R6040 driver\n"
228
	stdcall RegService, my_service, service_proc
229
	ret
230
 
231
  .fail:
232
  .exit:
233
	xor eax, eax
234
	ret
235
 
236
endp
237
 
238
 
239
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
240
;;                        ;;
241
;; proc SERVICE_PROC      ;;
242
;;                        ;;
243
;; (standard driver proc) ;;
244
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
245
 
246
align 4
247
proc service_proc stdcall, ioctl:dword
248
 
249
	mov	edx, [ioctl]
250
	mov	eax, [IOCTL.io_code]
251
 
252
;------------------------------------------------------
253
 
254
	cmp	eax, 0 ;SRV_GETVERSION
255
	jne	@F
256
 
257
	cmp	[IOCTL.out_size], 4
258
	jl	.fail
259
	mov	eax, [IOCTL.output]
260
	mov	[eax], dword API_VERSION
261
 
262
	xor	eax, eax
263
	ret
264
 
265
;------------------------------------------------------
266
  @@:
267
	cmp	eax, 1 ;SRV_HOOK
268
	jne	.fail
269
 
270
	cmp	[IOCTL.inp_size], 3			; Data input must be at least 3 bytes
271
	jl	.fail
272
 
273
	mov	eax, [IOCTL.input]
274
	cmp	byte [eax], 1				; 1 means device number and bus number (pci) are given
275
	jne	.fail					; other types arent supported for this card yet
276
 
277
; check if the device is already listed
278
 
279
	mov	esi, device_list
280
	mov	ecx, [devices]
281
	test	ecx, ecx
282
	jz	.firstdevice
283
 
284
;        mov     eax, [IOCTL.input]                      ; get the pci bus and device numbers
285
	mov	ax , [eax+1]				;
286
  .nextdevice:
287
	mov	ebx, [esi]
288
	cmp	ax , word [device.pci_bus]		; compare with pci and device num in device list (notice the usage of word instead of byte)
289
	je	.find_devicenum 			; Device is already loaded, let's find it's device number
290
	add	esi, 4
291
	loop	.nextdevice
292
 
293
 
294
; This device doesnt have its own eth_device structure yet, lets create one
295
  .firstdevice:
296
	cmp	[devices], MAX_DEVICES			; First check if the driver can handle one more card
297
	jge	.fail
298
 
299
	allocate_and_clear ebx, device.size, .fail	; Allocate the buffer for device structure
300
 
301
; Fill in the direct call addresses into the struct
302
 
303
	mov	[device.reset], reset
304
	mov	[device.transmit], transmit
305
	mov	[device.get_MAC], read_mac
306
	mov	[device.set_MAC], .fail
307
	mov	[device.unload], unload
308
	mov	[device.name], my_service
309
 
310
; save the pci bus and device numbers
311
 
312
	mov	eax, [IOCTL.input]
313
	mov	cl , [eax+1]
314
	mov	[device.pci_bus], cl
315
	mov	cl , [eax+2]
316
	mov	[device.pci_dev], cl
317
 
318
; Now, it's time to find the base io addres of the PCI device
319
 
320
	find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
321
 
322
; We've found the io address, find IRQ now
323
 
324
	find_irq [device.pci_bus], [device.pci_dev], [device.irq_line]
325
 
1893 hidnplayr 326
	DEBUGF	1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
1886 hidnplayr 327
	[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
328
 
329
; Ok, the eth_device structure is ready, let's probe the device
330
	cli
331
 
332
	call	probe							; this function will output in eax
333
	test	eax, eax
334
	jnz	.err_sti						; If an error occured, exit
335
 
336
	mov	eax, [devices]						; Add the device structure to our device list
337
	mov	[device_list+4*eax], ebx				; (IRQ handler uses this list to find device)
338
	inc	[devices]						;
339
 
340
	mov	[device.type], NET_TYPE_ETH
341
	call	NetRegDev
342
	sti
343
 
344
	cmp	eax, -1
345
	je	.destroy
346
 
347
	ret
348
 
349
; If the device was already loaded, find the device number and return it in eax
350
 
351
  .find_devicenum:
1893 hidnplayr 352
	DEBUGF	1,"Trying to find device number of already registered device\n"
1886 hidnplayr 353
	call	NetPtrToNum						; This kernel procedure converts a pointer to device struct in ebx
354
									; into a device number in edi
355
	mov	eax, edi						; Application wants it in eax instead
1893 hidnplayr 356
	DEBUGF	1,"Kernel says: %u\n", eax
1886 hidnplayr 357
	ret
358
 
359
; If an error occured, remove all allocated data and exit (returning -1 in eax)
360
 
361
  .destroy:
362
	; todo: reset device into virgin state
363
 
364
  .err_sti:
365
	sti
366
 
367
  .err:
368
	stdcall KernelFree, ebx
369
 
370
  .fail:
371
	or	eax, -1
372
	ret
373
 
374
;------------------------------------------------------
375
endp
376
 
377
 
378
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
379
;;                                                                        ;;
380
;;        Actual Hardware dependent code starts here                      ;;
381
;;                                                                        ;;
382
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
383
 
384
 
1893 hidnplayr 385
macro mdio_write reg, val {
386
	stdcall phy_read, [device.io_addr], [device.phy_addr], reg
1886 hidnplayr 387
}
388
 
1893 hidnplayr 389
macro mdio_write reg, val {
390
	stdcall phy_write, [device.io_addr], [devce.phy_addr], reg, val
1886 hidnplayr 391
}
392
 
393
 
394
align 4
395
unload:
396
	; TODO: (in this particular order)
397
	;
398
	; - Stop the device
399
	; - Detach int handler
400
	; - Remove device from local list (RTL8139_LIST)
401
	; - call unregister function in kernel
402
	; - Remove all allocated structures and buffers the card used
403
 
404
	or	eax,-1
405
 
406
ret
407
 
408
 
409
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
410
;;
411
;;  probe: enables the device (if it really is RTL8139)
412
;;
413
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
414
 
415
align 4
416
probe:
417
	DEBUGF	2,"Probing R6040 device\n"
418
 
419
	make_bus_master [device.pci_bus], [device.pci_dev]
420
 
421
	; If PHY status change register is still set to zero
422
	; it means the bootloader didn't initialize it
423
 
424
	set_io	0
425
	set_io	PHY_CC
426
	in	ax, dx
427
	test	ax, ax
428
	jnz	@f
429
	mov	ax, 0x9F07
430
	out	dx, ax
431
     @@:
432
 
433
	call	read_mac
434
 
435
	; Some bootloaders/BIOSes do not initialize MAC address, warn about that
436
	and	eax, 0xFF
437
	or	eax, dword [device.mac]
438
	test	eax, eax
439
	jnz	@f
1893 hidnplayr 440
	DEBUGF	2, "ERROR: MAC address not initialized!\n"
1886 hidnplayr 441
 
442
     @@:
443
	; Init RDC private data
444
	mov	[device.mcr0], 0x1002
445
	;mov     [private.phy_addr], 1 ; Asper: Only one network card is supported now.
446
	mov	[device.switch_sig], 0
447
 
448
	; Check the vendor ID on the PHY, if 0xFFFF assume none attached
449
	stdcall phy_read, 1, 2
450
	cmp	ax, 0xFFFF
451
	jne	@f
1893 hidnplayr 452
	DEBUGF	2, "Failed to detect an attached PHY\n" ;, generating random"
1886 hidnplayr 453
	mov	eax, -1
454
	ret
455
     @@:
456
 
457
	; Set MAC address
458
	call	init_mac_regs
459
 
460
	; Initialize and alloc RX/TX buffers
461
	call	init_txbufs
462
	call	init_rxbufs
463
 
464
	; Read the PHY ID
465
	mov	[device.phy_mode], 0x8000
466
	stdcall phy_read, 0, 2
467
	mov	[device.switch_sig], ax
468
	cmp	ax, ICPLUS_PHY_ID
469
	jne	@f
470
	stdcall phy_write, 29, 31, 0x175C ; Enable registers
471
	jmp	.phy_readen
472
      @@:
473
 
474
	; PHY Mode Check
475
	movzx	eax, [device.phy_addr]
476
	stdcall phy_write, eax, 4, PHY_CAP
477
	stdcall phy_write, eax, 0, PHY_MODE
478
 
1893 hidnplayr 479
      if PHY_MODE = 0x3100
1886 hidnplayr 480
	call	phy_mode_chk
481
	mov	[device.phy_mode], ax
482
	jmp	.phy_readen
1893 hidnplayr 483
      end if
1886 hidnplayr 484
 
1893 hidnplayr 485
      if not (PHY_MODE and 0x0100)
1886 hidnplayr 486
	mov	[device.phy_mode], 0
1893 hidnplayr 487
      end if
488
 
1886 hidnplayr 489
      .phy_readen:
490
 
491
	; Set duplex mode
492
	mov	ax, [device.phy_mode]
493
	or	[device.mcr0], ax
494
 
495
	; improve performance (by RDC guys)
496
	stdcall phy_read, 30, 17
497
	or	ax, 0x4000
498
	stdcall phy_write, 30, 17, eax
499
 
500
	stdcall phy_read, 30, 17
501
	and	ax, not 0x2000
502
	stdcall phy_write, 30, 17, eax
503
 
504
	stdcall phy_write, 0, 19, 0x0000
505
	stdcall phy_write, 0, 30, 0x01F0
506
 
507
	; Initialize all Mac registers
508
	call	init_mac_regs
509
 
510
 
511
 
512
align 4
513
reset:
514
 
1893 hidnplayr 515
	DEBUGF	2,"Resetting R6040\n"
1886 hidnplayr 516
 
517
	; Mask off Interrupt
518
	xor	ax, ax
519
	set_io	0
520
	set_io	MIER
521
	out	dx, ax
522
 
523
 
524
; attach int handler
525
 
526
	movzx	eax, [device.irq_line]
1893 hidnplayr 527
	DEBUGF	2,"Attaching int handler to irq %x\n", eax:1
1886 hidnplayr 528
	stdcall AttachIntHandler, eax, int_handler, dword 0
529
	test	eax, eax
530
	jnz	@f
1893 hidnplayr 531
	DEBUGF	2,"\nCould not attach int handler!\n"
1886 hidnplayr 532
;        or      eax, -1
533
;        ret
534
       @@:
535
 
536
 
537
	;Reset RDC MAC
538
	mov	eax, MAC_RST
539
	set_io	0
540
	set_io	MCR1
541
	out	dx, ax
542
 
543
	mov	ecx, 2048 ;limit
544
  .read:
545
	in	ax, dx
546
	test	ax, 0x1
547
	jnz	 @f
548
	dec	ecx
549
	test	ecx, ecx
550
	jnz	.read
551
  @@:
552
	;Reset internal state machine
553
	mov	ax,  2
554
	set_io	MAC_SM
555
	out	dx, ax
556
 
557
	xor	ax, ax
558
	out	dx, ax
559
 
560
	mov	esi, 5
561
	stdcall Sleep
562
 
563
	;MAC Bus Control Register
564
	mov	ax, MBCR_DEFAULT
565
	set_io	0
566
	set_io	MBCR
567
	out	dx, ax
568
 
569
	;Buffer Size Register
570
	mov	ax, MAX_BUF_SIZE
571
	set_io	MR_BSR
572
	out	dx, ax
573
 
574
	;Write TX ring start address
575
	lea	eax, [device.tx_ring]
576
	GetRealAddr
577
	set_io	MTD_SA0
578
	out	dx, ax
579
	shr	eax, 16
580
	set_io	MTD_SA1
581
	out	dx, ax
582
 
583
	;Write RX ring start address
584
	lea	eax, [device.rx_ring]
585
	GetRealAddr
586
	set_io	MRD_SA0
587
	out	dx, ax
588
	shr	eax, 16
589
	set_io	MRD_SA1
590
	out	dx, ax
591
 
592
	;Set interrupt waiting time and packet numbers
593
	xor	ax, ax
594
	set_io	MT_ICR
595
	out	dx, ax
596
 
597
	;Enable interrupts
598
	mov	ax, INT_MASK
599
	set_io	MIER
600
	out	dx, ax
601
 
602
	;Enable TX and RX
603
	mov	ax, [device.mcr0]
604
	or	ax, 0x0002
605
	set_io	0
606
	out	dx, ax
607
 
608
	;Let TX poll the descriptors
609
	;we may got called by tx_timeout which has left
610
	;some unset tx buffers
611
	xor	ax, ax
612
	inc	ax
613
	set_io	0
614
	set_io	MTPR
615
	out	dx, ax
616
 
617
; Set the mtu, kernel will be able to send now
618
	mov	[device.mtu], 1514
619
 
620
	DEBUGF	1,"Reset ok\n"
621
	xor	eax, eax
622
 
623
	ret
624
 
625
 
626
 
627
align 4
628
init_txbufs:
629
 
630
	DEBUGF	1,"Init TxBufs\n"
631
 
632
	lea	esi, [device.tx_ring]
633
	lea	eax, [device.tx_ring + x_head.sizeof]
634
	GetRealAddr
635
	mov	ecx, TX_RING_SIZE
636
 
637
    .next_desc:
638
	mov	[esi + x_head.ndesc], eax
1893 hidnplayr 639
	mov	[esi + x_head.skb_ptr], 0
1886 hidnplayr 640
	mov	[esi + x_head.status], DSC_OWNER_MAC
641
 
642
	add	eax, x_head.sizeof
643
	add	esi, x_head.sizeof
644
 
645
	dec	ecx
646
	jnz	.next_desc
647
 
648
	lea	eax, [device.tx_ring]
649
	GetRealAddr
650
	mov	[device.tx_ring + x_head.sizeof*(TX_RING_SIZE - 1) + x_head.ndesc], eax
651
 
652
	ret
653
 
654
 
655
 
656
align 4
657
init_rxbufs:
658
 
659
	DEBUGF	1,"Init RxBufs\n"
660
 
661
	lea	esi, [device.rx_ring]
662
	lea	eax, [device.rx_ring + x_head.sizeof]
663
	GetRealAddr
664
	mov	edx, eax
665
	mov	ecx, RX_RING_SIZE
666
 
667
    .next_desc:
1893 hidnplayr 668
	 mov	 [esi + x_head.ndesc], edx
1886 hidnplayr 669
 
670
	push	esi ecx
1893 hidnplayr 671
	stdcall KernelAlloc, MAX_BUF_SIZE
1886 hidnplayr 672
	pop	ecx esi
673
 
674
	mov	[esi + x_head.skb_ptr], eax
675
	GetRealAddr
676
	mov	[esi + x_head.buf], eax
677
	mov	[esi + x_head.status], DSC_OWNER_MAC
678
 
679
	add	edx, x_head.sizeof
680
	add	esi, x_head.sizeof
681
 
682
	dec	ecx
683
	jnz	.next_desc
684
 
685
	; complete the ring by linking the last to the first
686
 
687
	lea	eax, [device.rx_ring]
688
	GetRealAddr
689
	mov	[device.rx_ring + x_head.sizeof*(RX_RING_SIZE - 1) + x_head.ndesc], eax
690
 
691
	ret
692
 
693
 
694
 
695
align 4
696
phy_mode_chk:
697
 
698
	DEBUGF	1,"Checking PHY mode\n"
699
 
700
	; PHY Link Status Check
701
	movzx	eax, [device.phy_addr]
702
	stdcall phy_read, eax, 1
703
	test	eax, 0x4
704
	jz	.ret_0x8000
705
 
706
	; PHY Chip Auto-Negotiation Status
707
	movzx	eax, [device.phy_addr]
708
	stdcall phy_read, eax, 1
709
	test	eax, 0x0020
710
	jnz	.auto_nego
711
 
712
	; Force Mode
713
	movzx	eax, [device.phy_addr]
714
	stdcall phy_read, eax, 0
715
	test	eax, 0x100
716
	jnz	.ret_0x8000
717
 
718
  .auto_nego:
719
	; Auto Negotiation Mode
720
	movzx	eax, [device.phy_addr]
721
	stdcall phy_read, eax, 5
722
	mov	ecx, eax
723
	movzx	eax, [device.phy_addr]
724
	stdcall phy_read, eax, 4
725
	and	eax, ecx
726
	test	eax, 0x140
727
	jnz	.ret_0x8000
728
 
729
	xor	eax, eax
730
	ret
731
 
732
  .ret_0x8000:
733
	mov	eax, 0x8000
734
	ret
735
 
736
 
737
 
738
 
739
 
740
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
741
;;                                         ;;
742
;; Transmit                                ;;
743
;;                                         ;;
744
;; In: buffer pointer in [esp+4]           ;;
745
;;     size of buffer in [esp+8]           ;;
746
;;     pointer to device structure in ebx  ;;
747
;;                                         ;;
748
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
749
align 4
750
transmit:
1893 hidnplayr 751
	DEBUGF	2,"\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
1886 hidnplayr 752
	mov	eax, [esp+4]
1893 hidnplayr 753
	DEBUGF	2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
1886 hidnplayr 754
	[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
755
	[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
756
	[eax+13]:2,[eax+12]:2
757
 
758
	cmp	dword [esp+8], 1514
759
	jg	.fail
760
	cmp	dword [esp+8], 60
761
	jl	.fail
762
 
763
	movzx	edi, [device.cur_tx]
764
	shl	edi, 5
765
	add	edi, ebx
766
	add	edi, device.tx_ring - ebx
767
 
1893 hidnplayr 768
	DEBUGF	2,"TX buffer status: 0x%x\n", [edi + x_head.status]:4
1886 hidnplayr 769
 
1893 hidnplayr 770
	test	[edi + x_head.status], DSC_OWNER_MAC	; check if buffer is available
1886 hidnplayr 771
	jnz	.wait_to_send
772
 
773
  .do_send:
774
 
1893 hidnplayr 775
	DEBUGF	2,"Sending now\n"
776
 
1886 hidnplayr 777
	mov	eax, [esp+4]
778
	mov	[edi + x_head.skb_ptr], eax
779
	GetRealAddr
780
	mov	[edi + x_head.buf], eax
781
	mov	ecx, [esp+8]
782
	mov	[edi + x_head.len], cx
1893 hidnplayr 783
	mov	[edi + x_head.status], DSC_OWNER_MAC
1886 hidnplayr 784
 
785
	; Trigger the MAC to check the TX descriptor
786
	mov	ax, 0x01
787
	set_io	0
788
	set_io	MTPR
789
	out	dx, ax
790
 
791
	inc	[device.cur_tx]
1893 hidnplayr 792
	and	[device.cur_tx], TX_RING_SIZE - 1
1886 hidnplayr 793
	xor	eax, eax
794
 
795
	ret	8
796
 
797
  .wait_to_send:
798
 
1893 hidnplayr 799
	DEBUGF	2,"Waiting for TX buffer\n"
1886 hidnplayr 800
 
1893 hidnplayr 801
	call	GetTimerTicks		; returns in eax
802
	lea	edx, [eax + 100]
803
     .l2:
804
	test	[edi + x_head.status], DSC_OWNER_MAC
805
	jz	.do_send
806
	mov	esi, 10
807
	call	Sleep
808
	call	GetTimerTicks
809
	cmp	edx, eax
810
	jl	.l2
811
 
812
	DEBUGF	1,"Send timeout\n"
1886 hidnplayr 813
	xor	eax, eax
814
	dec	eax
815
  .fail:
1893 hidnplayr 816
	DEBUGF	1,"Send failed\n"
1886 hidnplayr 817
	ret	8
818
 
819
 
820
 
821
 
822
 
823
;;;;;;;;;;;;;;;;;;;;;;;
824
;;                   ;;
825
;; Interrupt handler ;;
826
;;                   ;;
827
;;;;;;;;;;;;;;;;;;;;;;;
828
align 4
829
int_handler:
830
 
1893 hidnplayr 831
	DEBUGF	2,"\nIRQ %x ", eax:2   ; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO
1886 hidnplayr 832
 
833
; Find pointer of device wich made IRQ occur
834
 
835
	mov	esi, device_list
836
	mov	ecx, [devices]
837
	test	ecx, ecx
838
	jz	.fail
839
  .nextdevice:
840
	mov	ebx, dword [esi]
841
 
842
	; Find reason for IRQ
843
 
844
	set_io	0
845
	set_io	MISR
846
	in	ax, dx
847
	out	dx, ax		; send it back to ACK
848
 
1893 hidnplayr 849
	DEBUGF	2,"MISR=%x\n", eax:4
1886 hidnplayr 850
 
851
	; Check if we are interessed in some of the reasons
852
 
853
	test	ax, INT_MASK
854
	jnz	.got_it
855
 
856
	; If not, try next device
857
 
858
	add	esi, 4
859
	dec	ecx
860
	jnz	.nextdevice
1889 hidnplayr 861
 
862
  .fail:				; If no device was found, abort (The irq was probably for a device, not registered to this driver)
1886 hidnplayr 863
	ret
864
 
865
; At this point, test for all possible reasons, and handle accordingly
866
 
867
  .got_it:
1889 hidnplayr 868
	push ax
1886 hidnplayr 869
 
1889 hidnplayr 870
	test	word [esp], RX_FINISH
1886 hidnplayr 871
	jz	.no_RX
872
 
873
	push	ebx
874
  .more_RX:
875
	pop	ebx
876
 
877
	; Find the current RX descriptor
878
 
879
	movzx	edx, [device.cur_rx]
880
	shl	edx, 5
881
	lea	edx, [device.rx_ring + edx]
882
 
883
	; Check the descriptor status
884
 
885
	mov	cx, [edx + x_head.status]
886
	test	cx, DSC_OWNER_MAC
887
	jnz	.no_RX
888
 
1893 hidnplayr 889
	DEBUGF	2,"packet status=0x%x\n", cx
1886 hidnplayr 890
 
891
	test	cx, DSC_RX_ERR		; Global error status set
892
	jnz	.no_RX
893
 
894
	; Packet successfully received
895
 
896
	movzx	ecx, [edx + x_head.len]
897
	and	ecx, 0xFFF
898
	sub	ecx, 4			; Do not count the CRC
899
 
900
	; Push packet size and pointer, kernel will need it..
901
 
902
	push	ebx
903
	push	.more_RX
904
 
905
	push	ecx
906
	push	[edx + x_head.skb_ptr]
907
 
1893 hidnplayr 908
	DEBUGF	2,"packet ptr=0x%x\n", [edx + x_head.skb_ptr]
1886 hidnplayr 909
 
910
	; reset the RX descriptor
911
 
912
	push	edx
1893 hidnplayr 913
	stdcall KernelAlloc, MAX_BUF_SIZE
1886 hidnplayr 914
	pop	edx
915
	mov	[edx + x_head.skb_ptr], eax
916
	GetRealAddr
917
	mov	[edx + x_head.buf], eax
918
	mov	[edx + x_head.status], DSC_OWNER_MAC
919
 
920
	; Use next descriptor next time
921
 
922
	inc	[device.cur_rx]
923
	and	[device.cur_rx], RX_RING_SIZE - 1
924
 
925
	; At last, send packet to kernel
926
 
927
	jmp	EthReceiver
928
 
1889 hidnplayr 929
 
1886 hidnplayr 930
  .no_RX:
931
 
1889 hidnplayr 932
	test	word [esp], TX_FINISH
933
	jz	.no_TX
1886 hidnplayr 934
 
1889 hidnplayr 935
      .loop_tx:
936
	movzx	edi, [device.last_tx]
937
	shl	edi, 5
938
	lea	edi, [device.tx_ring + edi]
1886 hidnplayr 939
 
1889 hidnplayr 940
	test	[edi + x_head.status], DSC_OWNER_MAC
1893 hidnplayr 941
	jnz	.no_TX
1889 hidnplayr 942
 
943
	cmp	[edi + x_head.skb_ptr], 0
1893 hidnplayr 944
	je	.no_TX
1889 hidnplayr 945
 
1893 hidnplayr 946
	DEBUGF	2,"Freeing buffer 0x%x\n", [edi + x_head.skb_ptr]
1889 hidnplayr 947
 
948
	push	[edi + x_head.skb_ptr]
1893 hidnplayr 949
	mov	[edi + x_head.skb_ptr], 0
1889 hidnplayr 950
	call	KernelFree
951
 
952
	inc	[device.last_tx]
953
	and	[device.last_tx], TX_RING_SIZE - 1
1893 hidnplayr 954
 
1889 hidnplayr 955
	jmp	.loop_tx
956
 
957
  .no_TX:
958
	pop	ax
1886 hidnplayr 959
	ret
960
 
961
 
962
 
963
 
964
align 4
965
init_mac_regs:
966
 
1893 hidnplayr 967
	DEBUGF	2,"initializing MAC regs\n"
1886 hidnplayr 968
 
969
	; MAC operation register
970
	mov	ax, 1
971
	set_io	0
972
	set_io	MCR1
973
	out	dx, ax
974
	; Reset MAC
975
	mov	ax, 2
976
	set_io	MAC_SM
977
	out	dx, ax
978
	; Reset internal state machine
979
	xor	ax, ax
980
	out	dx, ax
981
	mov	esi, 5
982
	stdcall Sleep
983
 
984
	call	read_mac
985
 
986
	ret
987
 
988
 
989
 
990
 
991
; Read a word data from PHY Chip
992
 
993
align 4
994
proc  phy_read stdcall, phy_addr:dword, reg:dword
995
 
1893 hidnplayr 996
	DEBUGF	2,"PHY read, addr=0x%x reg=0x%x\n", [phy_addr]:8, [reg]:8
1886 hidnplayr 997
 
998
	mov	eax, [phy_addr]
999
	shl	eax, 8
1000
	add	eax, [reg]
1001
	add	eax, MDIO_READ
1002
	set_io	0
1003
	set_io	MMDIO
1004
	out	dx, ax
1005
 
1006
	;Wait for the read bit to be cleared.
1007
	mov	ecx, 2048 ;limit
1008
  .read:
1009
	in	ax, dx
1010
	test	ax, MDIO_READ
1011
	jz	@f
1012
	dec	ecx
1013
	jnz	.read
1014
  @@:
1015
 
1016
	set_io	MMRD
1017
	in	ax, dx
1018
	and	eax, 0xFFFF
1019
 
1893 hidnplayr 1020
	DEBUGF	2,"PHY read, val=0x%x\n", eax:4
1886 hidnplayr 1021
 
1022
	ret
1023
 
1024
endp
1025
 
1026
 
1027
 
1028
 
1029
; Write a word data to PHY Chip
1030
 
1031
align 4
1032
proc  phy_write stdcall, phy_addr:dword, reg:dword, val:dword
1033
 
1893 hidnplayr 1034
	DEBUGF	2,"PHY write, addr=0x%x reg=0x%x val=0x%x\n", [phy_addr]:8, [reg]:8, [val]:8
1886 hidnplayr 1035
 
1036
	mov	eax, [val]
1037
	set_io	0
1038
	set_io	MMWD
1039
	out	dx, ax
1040
 
1041
	;Write the command to the MDIO bus
1042
 
1043
	mov	eax, [phy_addr]
1044
	shl	eax, 8
1045
	add	eax, [reg]
1046
	add	eax, MDIO_WRITE
1047
	set_io	MMDIO
1048
	out	dx, ax
1049
 
1050
	;Wait for the write bit to be cleared.
1051
	mov	ecx, 2048 ;limit
1052
  .write:
1053
	in	ax, dx
1054
	test	ax, MDIO_WRITE
1055
	jz	@f
1056
	dec	ecx
1057
	jnz	.write
1058
  @@:
1059
 
1893 hidnplayr 1060
	DEBUGF	2,"PHY write ok\n"
1886 hidnplayr 1061
 
1062
	ret
1063
endp
1064
 
1065
 
1066
 
1067
align 4
1068
read_mac:
1069
 
1070
	DEBUGF	2,"Reading MAC: "
1071
 
1072
	mov	cx, 3
1073
	lea	edi, [device.mac]
1074
	set_io	0
1075
	set_io	MID_0L
1076
     .mac:
1077
	in	ax, dx
1078
	stosw
1079
	inc	dx
1080
	inc	dx
1081
	dec	cx
1082
	jnz	.mac
1083
 
1084
	DEBUGF	2,"%x-%x-%x-%x-%x-%x\n",[edi-6]:2, [edi-5]:2, [edi-4]:2, [edi-3]:2, [edi-2]:2, [edi-1]:2
1085
 
1086
	ret
1087
 
1088
 
1089
 
1090
 
1091
; End of code
1092
 
1093
section '.data' data readable writable align 16 ; place all uninitialized data place here
1094
align 4 					; Place all initialised data here
1095
 
1096
devices 	dd 0
1097
version 	dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
1098
my_service	db 'R6040',0			; max 16 chars include zero
1099
 
1100
include_debug_strings				; All data wich FDO uses will be included here
1101
 
1102
device_list	rd MAX_DEVICES			; This list contains all pointers to device structures the driver is handling
1103