Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1554 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  RTL8169 driver for KolibriOS                                   ;;
7
;;                                                                 ;;
8
;;  Copyright 2007 mike.dld,                                       ;;
9
;;   mike.dld@gmail.com                                            ;;
10
;;                                                                 ;;
11
;;  Version 0.1  11 February 2007                                  ;;
12
;;  Version 0.2  3 August 2010 - port to net branch by hidnplayr   ;;
13
;;                                                                 ;;
14
;;  References:                                                    ;;
15
;;    r8169.c - linux driver (etherboot project)                   ;;
16
;;                                                                 ;;
17
;;          GNU GENERAL PUBLIC LICENSE                             ;;
18
;;             Version 2, June 1991                                ;;
19
;;                                                                 ;;
20
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
21
 
22
format MS COFF
23
 
24
	API_VERSION		equ 0x01000100
25
	DRIVER_VERSION		equ 5
26
 
27
	MAX_DEVICES		equ 16
28
 
29
	DEBUG			equ 1
30
	__DEBUG__		equ 1
31
	__DEBUG_LEVEL__ 	equ 1
32
 
33
	NUM_TX_DESC		equ 4
34
	NUM_RX_DESC		equ 4
35
 
36
include 'proc32.inc'
37
include 'imports.inc'
38
include 'fdo.inc'
39
include 'netdrv.inc'
40
 
41
public START
42
public service_proc
43
public version
44
 
45
 
46
	REG_MAC0	       equ 0x0 ; Ethernet hardware address
47
	REG_MAR0	       equ 0x8 ; Multicast filter
48
	REG_TxDescStartAddr    equ 0x20
49
	REG_TxHDescStartAddr   equ 0x28
50
	REG_FLASH	       equ 0x30
51
	REG_ERSR	       equ 0x36
52
	REG_ChipCmd	       equ 0x37
53
	REG_TxPoll	       equ 0x38
54
	REG_IntrMask	       equ 0x3C
55
	REG_IntrStatus	       equ 0x3E
56
	REG_TxConfig	       equ 0x40
57
	REG_RxConfig	       equ 0x44
58
	REG_RxMissed	       equ 0x4C
59
	REG_Cfg9346	       equ 0x50
60
	REG_Config0	       equ 0x51
61
	REG_Config1	       equ 0x52
62
	REG_Config2	       equ 0x53
63
	REG_Config3	       equ 0x54
64
	REG_Config4	       equ 0x55
65
	REG_Config5	       equ 0x56
66
	REG_MultiIntr	       equ 0x5C
67
	REG_PHYAR	       equ 0x60
68
	REG_TBICSR	       equ 0x64
69
	REG_TBI_ANAR	       equ 0x68
70
	REG_TBI_LPAR	       equ 0x6A
71
	REG_PHYstatus	       equ 0x6C
72
	REG_RxMaxSize	       equ 0xDA
73
	REG_CPlusCmd	       equ 0xE0
74
	REG_RxDescStartAddr    equ 0xE4
75
	REG_ETThReg	       equ 0xEC
76
	REG_FuncEvent	       equ 0xF0
77
	REG_FuncEventMask      equ 0xF4
78
	REG_FuncPresetState    equ 0xF8
79
	REG_FuncForceEvent     equ 0xFC
80
 
81
	; InterruptStatusBits
82
	ISB_SYSErr	       equ 0x8000
83
	ISB_PCSTimeout	       equ 0x4000
84
	ISB_SWInt	       equ 0x0100
85
	ISB_TxDescUnavail      equ 0x80
86
	ISB_RxFIFOOver	       equ 0x40
87
	ISB_LinkChg	       equ 0x20
88
	ISB_RxOverflow	       equ 0x10
89
	ISB_TxErr	       equ 0x08
90
	ISB_TxOK	       equ 0x04
91
	ISB_RxErr	       equ 0x02
92
	ISB_RxOK	       equ 0x01
93
 
94
	; RxStatusDesc
95
	SD_RxRES	       equ 0x00200000
96
	SD_RxCRC	       equ 0x00080000
97
	SD_RxRUNT	       equ 0x00100000
98
	SD_RxRWT	       equ 0x00400000
99
 
100
	; ChipCmdBits
101
	CMD_Reset	       equ 0x10
102
	CMD_RxEnb	       equ 0x08
103
	CMD_TxEnb	       equ 0x04
104
	CMD_RxBufEmpty	       equ 0x01
105
 
106
	; Cfg9346Bits
107
	CFG_9346_Lock	       equ 0x00
108
	CFG_9346_Unlock        equ 0xC0
109
 
110
	; rx_mode_bits
111
	RXM_AcceptErr	       equ 0x20
112
	RXM_AcceptRunt	       equ 0x10
113
	RXM_AcceptBroadcast    equ 0x08
114
	RXM_AcceptMulticast    equ 0x04
115
	RXM_AcceptMyPhys       equ 0x02
116
	RXM_AcceptAllPhys      equ 0x01
117
 
118
	; RxConfigBits
119
	RXC_FIFOShift	       equ 13
120
	RXC_DMAShift	       equ 8
121
 
122
	; TxConfigBits
123
	TXC_InterFrameGapShift equ 24
124
	TXC_DMAShift	       equ 8	; DMA burst value (0-7) is shift this many bits
125
 
126
	; PHYstatus
127
	PHYS_TBI_Enable        equ 0x80
128
	PHYS_TxFlowCtrl        equ 0x40
129
	PHYS_RxFlowCtrl        equ 0x20
130
	PHYS_1000bpsF	       equ 0x10
131
	PHYS_100bps	       equ 0x08
132
	PHYS_10bps	       equ 0x04
133
	PHYS_LinkStatus        equ 0x02
134
	PHYS_FullDup	       equ 0x01
135
 
136
	; GIGABIT_PHY_registers
137
	PHY_CTRL_REG	       equ 0
138
	PHY_STAT_REG	       equ 1
139
	PHY_AUTO_NEGO_REG      equ 4
140
	PHY_1000_CTRL_REG      equ 9
141
 
142
	; GIGABIT_PHY_REG_BIT
143
	PHY_Restart_Auto_Nego  equ 0x0200
144
	PHY_Enable_Auto_Nego   equ 0x1000
145
 
146
	; PHY_STAT_REG = 1;
147
	PHY_Auto_Neco_Comp     equ 0x0020
148
 
149
	; PHY_AUTO_NEGO_REG = 4;
150
	PHY_Cap_10_Half        equ 0x0020
151
	PHY_Cap_10_Full        equ 0x0040
152
	PHY_Cap_100_Half       equ 0x0080
153
	PHY_Cap_100_Full       equ 0x0100
154
 
155
	; PHY_1000_CTRL_REG = 9;
156
	PHY_Cap_1000_Full      equ 0x0200
157
	PHY_Cap_1000_Half      equ 0x0100
158
 
159
	PHY_Cap_PAUSE	       equ 0x0400
160
	PHY_Cap_ASYM_PAUSE     equ 0x0800
161
 
162
	PHY_Cap_Null	       equ 0x0
163
 
164
	; _MediaType
165
	MT_10_Half	       equ 0x01
166
	MT_10_Full	       equ 0x02
167
	MT_100_Half	       equ 0x04
168
	MT_100_Full	       equ 0x08
169
	MT_1000_Full	       equ 0x10
170
 
171
	; _TBICSRBit
172
	TBI_LinkOK	       equ 0x02000000
173
 
174
	; _DescStatusBit
175
	DSB_OWNbit	       equ 0x80000000
176
	DSB_EORbit	       equ 0x40000000
177
	DSB_FSbit	       equ 0x20000000
178
	DSB_LSbit	       equ 0x10000000
179
 
180
	RX_BUF_SIZE		equ 1536    ; Rx Buffer size
181
 
182
 
183
ETH_ALEN	       equ 6
184
ETH_HLEN	       equ (2 * ETH_ALEN + 2)
185
ETH_ZLEN	       equ 60 ; 60 + 4bytes auto payload for
186
				      ; mininmum 64bytes frame length
187
 
188
; MAC address length
189
MAC_ADDR_LEN	    equ 6
190
 
191
; max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4)
192
MAX_ETH_FRAME_SIZE  equ 1536
193
 
194
TX_FIFO_THRESH	    equ 256	; In bytes
195
 
196
RX_FIFO_THRESH	    equ 7	; 7 means NO threshold, Rx buffer level before first PCI xfer
197
RX_DMA_BURST	    equ 7	; Maximum PCI burst, '6' is 1024
198
TX_DMA_BURST	    equ 7	; Maximum PCI burst, '6' is 1024
199
ETTh		    equ 0x3F	; 0x3F means NO threshold
200
 
201
EarlyTxThld	    equ 0x3F	; 0x3F means NO early transmit
202
RxPacketMaxSize     equ 0x0800	; Maximum size supported is 16K-1
203
InterFrameGap	    equ 0x03	; 3 means InterFrameGap = the shortest one
204
 
205
HZ		    equ 1000
206
 
207
RTL_MIN_IO_SIZE     equ 0x80
208
TX_TIMEOUT	    equ (6*HZ)
209
 
210
TIMER_EXPIRE_TIME equ 100
211
 
212
ETH_HDR_LEN	    equ 14
213
DEFAULT_MTU	    equ 1500
214
DEFAULT_RX_BUF_LEN  equ 1536
215
 
216
 
217
;#ifdef JUMBO_FRAME_SUPPORT
218
;#define MAX_JUMBO_FRAME_MTU    ( 10000 )
219
;#define MAX_RX_SKBDATA_SIZE    ( MAX_JUMBO_FRAME_MTU + ETH_HDR_LEN )
220
;#else
221
MAX_RX_SKBDATA_SIZE equ 1600
222
;#endif                         //end #ifdef JUMBO_FRAME_SUPPORT
223
 
224
MCFG_METHOD_01	     equ 0x01
225
MCFG_METHOD_02	     equ 0x02
226
MCFG_METHOD_03	     equ 0x03
227
MCFG_METHOD_04	     equ 0x04
228
MCFG_METHOD_05	     equ 0x05
229
MCFG_METHOD_11	     equ 0x0b
230
MCFG_METHOD_12	     equ 0x0c
231
MCFG_METHOD_13	     equ 0x0d
232
MCFG_METHOD_14	     equ 0x0e
233
MCFG_METHOD_15	     equ 0x0f
234
 
235
PCFG_METHOD_1	    equ 0x01	; PHY Reg 0x03 bit0-3 == 0x0000
236
PCFG_METHOD_2	    equ 0x02	; PHY Reg 0x03 bit0-3 == 0x0001
237
PCFG_METHOD_3	    equ 0x03	; PHY Reg 0x03 bit0-3 == 0x0002
238
 
239
PCI_COMMAND_IO		equ 0x1   ; Enable response in I/O space
240
PCI_COMMAND_MEM 	equ 0x2   ; Enable response in mem space
241
PCI_COMMAND_MASTER	equ 0x4   ; Enable bus mastering
242
PCI_LATENCY_TIMER	equ 0x0d  ; 8 bits
243
PCI_COMMAND_SPECIAL	equ 0x8   ; Enable response to special cycles
244
PCI_COMMAND_INVALIDATE	equ 0x10  ; Use memory write and invalidate
245
PCI_COMMAND_VGA_PALETTE equ 0x20  ; Enable palette snooping
246
PCI_COMMAND_PARITY	equ 0x40  ; Enable parity checking
247
PCI_COMMAND_WAIT	equ 0x80  ; Enable address/data stepping
248
PCI_COMMAND_SERR	equ 0x100 ; Enable SERR
249
PCI_COMMAND_FAST_BACK	equ 0x200 ; Enable back-to-back writes
250
 
251
virtual at 0
252
  tx_desc:
253
  .status    dd ?
254
  .vlan_tag  dd ?
255
  .buf_addr  dd ?
256
  .buf_Haddr dd ?
257
  .size = $
258
end virtual
259
 
260
virtual at 0
261
  rx_desc:
262
  .status    dd ?
263
  .vlan_tag  dd ?
264
  .buf_addr  dd ?
265
  .buf_Haddr dd ?
266
  .size = $
267
end virtual
268
 
269
virtual at ebx
270
 
271
	device:
272
 
273
	ETH_DEVICE
274
 
275
	.io_addr	dd ?
276
	.pci_bus	db ?
277
	.pci_dev	db ?
278
	.irq_line	db ?
279
 
280
	tpc:
281
	.mmio_addr	dd ? ; memory map physical address
282
	.chipset	dd ?
283
	.pcfg		dd ?
284
	.mcfg		dd ?
285
	.cur_rx 	dd ? ; Index into the Rx descriptor buffer of next Rx pkt
286
	.cur_tx 	dd ? ; Index into the Tx descriptor buffer of next Rx pkt
287
	.TxDescArrays	dd ? ; Index of Tx Descriptor buffer
288
	.RxDescArrays	dd ? ; Index of Rx Descriptor buffer
289
	.TxDescArray	dd ? ; Index of 256-alignment Tx Descriptor buffer
290
	.RxDescArray	dd ? ; Index of 256-alignment Rx Descriptor buffer
291
 
292
	rb 255-(($ - ebx) and 255)		;        align 256
293
	tx_ring rb NUM_TX_DESC * tx_desc.size
294
 
295
	rb 255-(($ - ebx) and 255)		;        align 256
296
	rx_ring rb NUM_RX_DESC * rx_desc.size
297
 
298
	device_size = $ - device
299
 
300
end virtual
301
 
302
intr_mask = ISB_LinkChg or ISB_RxOverflow or ISB_RxFIFOOver or ISB_TxErr or ISB_TxOK or ISB_RxErr or ISB_RxOK
303
rx_config = (RX_FIFO_THRESH shl RXC_FIFOShift) or (RX_DMA_BURST shl RXC_DMAShift) or 0x0000000E
304
 
305
 
306
macro	udelay msec {
307
 
308
	push	esi
309
	mov	esi, msec
310
	call	Sleep
311
	pop	esi
312
 
313
}
314
 
315
macro	WRITE_GMII_REG	RegAddr, value {
316
 
317
	set_io	REG_PHYAR
318
	if	value eq ax
319
	and	eax, 0x0000ffff
320
	or	eax, 0x80000000 + (RegAddr shl 16)
321
	else
322
	mov	eax, 0x80000000 + (RegAddr shl 16) + value
323
	end if
324
	out	dx, eax
325
 
326
	call	PHY_WAIT
327
}
328
 
329
macro	READ_GMII_REG  RegAddr {
330
 
331
local	.error, .done
332
 
333
	mov	eax, RegAddr shl 16
334
	set_io	REG_PHYAR
335
	in	eax, dx
336
 
337
	call	PHY_WAIT
338
	jz	.error
339
 
340
	set_io	REG_PHYAR
341
	in	eax, dx
342
	and	eax, 0xFFFF
343
	jmp	.done
344
 
345
  .error:
346
	or	eax, -1
347
  .done:
348
}
349
 
350
align 4
351
PHY_WAIT:	; io addr must already be set to REG_PHYAR
352
 
353
	udelay	1	 ;;;1000
354
 
355
	push	ecx
356
	mov	ecx, 2000
357
	; Check if the RTL8169 has completed writing to the specified MII register
358
    @@:
359
	in	eax, dx
360
	test	eax, 0x80000000
361
	jz	.exit
362
	udelay	1	 ;;;100
363
	loop	@b
364
  .exit:
365
	pop	ecx
366
	ret
367
 
368
 
369
 
370
section '.flat' code readable align 16
371
 
372
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
373
;;                        ;;
374
;; proc START             ;;
375
;;                        ;;
376
;; (standard driver proc) ;;
377
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
378
 
379
align 4
380
proc START stdcall, state:dword
381
 
382
	cmp [state], 1
383
	jne .exit
384
 
385
  .entry:
386
 
387
	DEBUGF	2,"Loading rtl8169 driver\n"
388
	stdcall RegService, my_service, service_proc
389
	ret
390
 
391
  .fail:
392
  .exit:
393
	xor eax, eax
394
	ret
395
 
396
endp
397
 
398
 
399
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
400
;;                        ;;
401
;; proc SERVICE_PROC      ;;
402
;;                        ;;
403
;; (standard driver proc) ;;
404
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
405
 
406
align 4
407
proc service_proc stdcall, ioctl:dword
408
 
409
	mov	edx, [ioctl]
410
	mov	eax, [IOCTL.io_code]
411
 
412
;------------------------------------------------------
413
 
414
	cmp	eax, 0 ;SRV_GETVERSION
415
	jne	@F
416
 
417
	cmp	[IOCTL.out_size], 4
418
	jl	.fail
419
	mov	eax, [IOCTL.output]
420
	mov	[eax], dword API_VERSION
421
 
422
	xor	eax, eax
423
	ret
424
 
425
;------------------------------------------------------
426
  @@:
427
	cmp	eax, 1 ;SRV_HOOK
428
	jne	.fail
429
 
430
	cmp	[IOCTL.inp_size], 3			; Data input must be at least 3 bytes
431
	jl	.fail
432
 
433
	mov	eax, [IOCTL.input]
434
	cmp	byte [eax], 1				; 1 means device number and bus number (pci) are given
435
	jne	.fail					; other types arent supported for this card yet
436
 
437
; check if the device is already listed
438
 
439
	mov	esi, device_list
440
	mov	ecx, [devices]
441
	test	ecx, ecx
442
	jz	.firstdevice
443
 
444
;        mov     eax, [IOCTL.input]                     ; get the pci bus and device numbers
445
	mov	ax , [eax+1]				;
446
  .nextdevice:
447
	mov	ebx, [esi]
448
	cmp	ax , word [device.pci_bus]		; compare with pci and device num in device list (notice the usage of word instead of byte)
449
	je	.find_devicenum 			; Device is already loaded, let's find it's device number
450
	add	esi, 4
451
	loop	.nextdevice
452
 
453
 
454
; This device doesnt have its own eth_device structure yet, lets create one
455
  .firstdevice:
456
	cmp	[devices], MAX_DEVICES			; First check if the driver can handle one more card
457
	jge	.fail
458
 
459
	push	edx
460
	stdcall KernelAlloc, device_size		; Allocate the buffer for eth_device structure
461
	pop	edx
462
	test	eax, eax
463
	jz	.fail
464
	mov	ebx, eax				; ebx is always used as a pointer to the structure (in driver, but also in kernel code)
465
 
466
; Fill in the direct call addresses into the struct
467
 
468
	mov	[device.reset], reset
469
	mov	[device.transmit], transmit
470
	mov	[device.get_MAC], read_mac
471
	mov	[device.set_MAC], write_mac
472
	mov	[device.unload], unload
473
	mov	[device.name], my_service
474
 
475
; save the pci bus and device numbers
476
 
477
	mov	eax, [IOCTL.input]
478
	mov	cl , [eax+1]
479
	mov	[device.pci_bus], cl
480
	mov	cl , [eax+2]
481
	mov	[device.pci_dev], cl
482
 
483
; Now, it's time to find the base io addres of the PCI device
484
 
485
	find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
486
	mov	eax, [device.io_addr]
487
	mov	[tpc.mmio_addr], eax
488
 
489
; We've found the io address, find IRQ now
490
 
491
	find_irq [device.pci_bus], [device.pci_dev], [device.irq_line]
492
 
493
	DEBUGF	2,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
494
	[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:8
495
 
496
; Ok, the eth_device structure is ready, let's probe the device
497
; Because initialization fires IRQ, IRQ handler must be aware of this device
498
	mov	eax, [devices]						; Add the device structure to our device list
499
	mov	[device_list+4*eax], ebx				; (IRQ handler uses this list to find device)
500
	inc	[devices]						;
501
 
502
	call	probe							; this function will output in eax
503
	test	eax, eax
504
	jnz	.err2							; If an error occured, exit
505
 
506
 
507
	mov	[device.type], NET_TYPE_ETH
508
	call	NetRegDev
509
 
510
	cmp	eax, -1
511
	je	.destroy
512
 
513
	ret
514
 
515
; If the device was already loaded, find the device number and return it in eax
516
 
517
  .find_devicenum:
518
	DEBUGF	2,"Trying to find device number of already registered device\n"
519
	mov	ebx, eax
520
	call	NetPtrToNum						; This kernel procedure converts a pointer to device struct in ebx
521
									; into a device number in edi
522
	mov	eax, edi						; Application wants it in eax instead
523
	DEBUGF	2,"Kernel says: %u\n", eax
524
	ret
525
 
526
; If an error occured, remove all allocated data and exit (returning -1 in eax)
527
 
528
  .destroy:
529
	; todo: reset device into virgin state
530
 
531
  .err2:
532
	dec	[devices]
533
  .err:
534
	DEBUGF	2,"removing device structure\n"
535
	stdcall KernelFree, ebx
536
 
537
 
538
  .fail:
539
	or	eax, -1
540
	ret
541
 
542
;------------------------------------------------------
543
endp
544
 
545
 
546
align 4
547
unload:
548
 
549
	ret
550
 
551
 
552
align 4
553
init_board:
554
 
555
	DEBUGF	1,"init_board\n"
556
 
557
	make_bus_master [device.pci_bus], [device.pci_dev]
558
 
559
	; Soft reset the chip
560
	set_io	0
561
	set_io	REG_ChipCmd
562
	mov	al, CMD_Reset
563
	out	dx, al
564
 
565
	; Check that the chip has finished the reset
566
	mov	ecx, 1000
567
	set_io	REG_ChipCmd
568
    @@: in	al, dx
569
	test	al, CMD_Reset
570
	jz	@f
571
	udelay	10
572
	loop	@b
573
    @@:
574
	; identify config method
575
	set_io	REG_TxConfig
576
	in	eax, dx
577
	and	eax, 0x7c800000
578
	DEBUGF	1,"init_board: TxConfig & 0x7c800000 = 0x%x\n", eax
579
	mov	esi, mac_info-8
580
    @@: add	esi, 8
581
	mov	ecx, eax
582
	and	ecx, [esi]
583
	cmp	ecx, [esi]
584
	jne	@b
585
	mov	eax, [esi+4]
586
	mov	[tpc.mcfg], eax
587
 
588
	mov	[tpc.pcfg], PCFG_METHOD_3
589
	READ_GMII_REG 3
590
	and	al, 0x0f
591
	or	al, al
592
	jnz	@f
593
	mov	[tpc.pcfg], PCFG_METHOD_1
594
	jmp	.pconf
595
    @@: dec	al
596
	jnz	.pconf
597
	mov	[tpc.pcfg], PCFG_METHOD_2
598
  .pconf:
599
 
600
	; identify chip attached to board
601
	mov	ecx, 10
602
	mov	eax, [tpc.mcfg]
603
    @@: dec	ecx
604
	js	@f
605
	cmp	eax, [rtl_chip_info+ecx*8]
606
	jne	@b
607
	mov	[tpc.chipset], ecx
608
	jmp	.match
609
    @@:
610
	; if unknown chip, assume array element #0, original RTL-8169 in this case
611
	DEBUGF	1,"init_board: PCI device: unknown chip version, assuming RTL-8169\n"
612
	set_io	REG_TxConfig
613
	in	eax, dx
614
	DEBUGF	1,"init_board: PCI device: TxConfig = 0x%x\n", eax
615
 
616
	mov	[tpc.chipset],	0
617
 
618
	xor	eax, eax
619
	inc	eax
620
	ret
621
 
622
  .match:
623
	xor	eax,eax
624
	ret
625
 
626
 
627
 
628
;***************************************************************************
629
;   Function
630
;      probe
631
;   Description
632
;      Searches for an ethernet card, enables it and clears the rx buffer
633
;      If a card was found, it enables the ethernet -> TCPIP link
634
;   Destroyed registers
635
;      eax, ebx, ecx, edx
636
;
637
;***************************************************************************
638
align 4
639
probe:
640
 
641
	DEBUGF	1,"probe\n"
642
 
643
	call	init_board
644
 
645
	call	read_mac
646
 
647
	call	PHY_config
648
 
649
;       DEBUGF  1,"K :   Set MAC Reg C+CR Offset 0x82h = 0x01h\n"
650
	set_io	0
651
	set_io	0x82
652
	mov	al, 0x01
653
	out	dx, al
654
	cmp	[tpc.mcfg], MCFG_METHOD_03
655
	jae	@f
656
;       DEBUGF  1,"K :   Set PCI Latency=0x40\n"
657
;       stdcall pci_write_config_byte,PCI_LATENCY_TIMER,0x40
658
   @@:
659
	cmp	[tpc.mcfg], MCFG_METHOD_02
660
	jne	@f
661
;       DEBUGF  1,"K :   Set MAC Reg C+CR Offset 0x82h = 0x01h\n"
662
	set_io	0x82
663
	mov	al, 0x01
664
	out	dx, al
665
;       DEBUGF  1,"K :   Set PHY Reg 0x0bh = 0x00h\n"
666
	WRITE_GMII_REG 0x0b, 0x0000	 ; w 0x0b 15 0 0
667
    @@:
668
	; if TBI is not enabled
669
	set_io	0
670
	set_io	REG_PHYstatus
671
	in	al, dx
672
	test	al, PHYS_TBI_Enable
673
	jz	.tbi_dis
674
	READ_GMII_REG PHY_AUTO_NEGO_REG
675
 
676
	; enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged
677
	and	eax, 0x0C1F
678
	or	eax, PHY_Cap_10_Half or PHY_Cap_10_Full or PHY_Cap_100_Half or PHY_Cap_100_Full
679
	WRITE_GMII_REG PHY_AUTO_NEGO_REG, ax
680
 
681
	; enable 1000 Full Mode
682
	WRITE_GMII_REG PHY_1000_CTRL_REG, PHY_Cap_1000_Full or PHY_Cap_1000_Half ; rtl8168
683
 
684
	; Enable auto-negotiation and restart auto-nigotiation
685
	WRITE_GMII_REG PHY_CTRL_REG, PHY_Enable_Auto_Nego or PHY_Restart_Auto_Nego
686
 
687
	udelay	100
688
	mov	ecx, 10000
689
	; wait for auto-negotiation process
690
    @@: dec	ecx
691
	jz	@f
692
	READ_GMII_REG PHY_STAT_REG
693
	udelay	100
694
	test	eax, PHY_Auto_Neco_Comp
695
	jz	@b
696
	set_io	0
697
	set_io	REG_PHYstatus
698
	in	al, dx
699
	jmp	@f
700
  .tbi_dis:
701
	udelay	100
702
    @@:
703
 
704
 
705
;***************************************************************************
706
;   Function
707
;      rt8169_reset
708
;   Description
709
;      Place the chip (ie, the ethernet card) into a virgin state
710
;   Destroyed registers
711
;      eax, ebx, ecx, edx
712
;
713
;***************************************************************************
714
align 4
715
reset:
716
 
717
	DEBUGF	1,"reset\n"
718
 
719
	lea	eax, [tx_ring]
720
	mov	[tpc.TxDescArrays], eax
721
	mov	[tpc.TxDescArray], eax
722
 
723
	lea	eax, [rx_ring]
724
	mov	[tpc.RxDescArrays], eax
725
	mov	[tpc.RxDescArray], eax
726
 
727
	call	init_ring
728
	call	hw_start
729
 
730
	mov	[device.mtu], 1500
731
 
732
	xor	eax, eax
733
 
734
	ret
735
 
736
 
737
 
738
 
739
 
740
align 4
741
PHY_config:
742
 
743
	DEBUGF	1,"hw_PHY_config: priv.mcfg=%d, priv.pcfg=%d\n",[tpc.mcfg],[tpc.pcfg]
744
 
745
	cmp	[tpc.mcfg], MCFG_METHOD_04
746
	jne	.not_4
747
;       WRITE_GMII_REG 0x1F, 0x0001
748
;       WRITE_GMII_REG 0x1b, 0x841e
749
;       WRITE_GMII_REG 0x0e, 0x7bfb
750
;       WRITE_GMII_REG 0x09, 0x273a
751
	WRITE_GMII_REG 0x1F, 0x0002
752
	WRITE_GMII_REG 0x01, 0x90D0
753
	WRITE_GMII_REG 0x1F, 0x0000
754
	jmp	.exit
755
  .not_4:
756
	cmp	[tpc.mcfg], MCFG_METHOD_02
757
	je	@f
758
	cmp	[tpc.mcfg], MCFG_METHOD_03
759
	jne	.not_2_or_3
760
    @@: WRITE_GMII_REG 0x1F, 0x0001
761
	WRITE_GMII_REG 0x15, 0x1000
762
	WRITE_GMII_REG 0x18, 0x65C7
763
	WRITE_GMII_REG 0x04, 0x0000
764
	WRITE_GMII_REG 0x03, 0x00A1
765
	WRITE_GMII_REG 0x02, 0x0008
766
	WRITE_GMII_REG 0x01, 0x1020
767
	WRITE_GMII_REG 0x00, 0x1000
768
	WRITE_GMII_REG 0x04, 0x0800
769
	WRITE_GMII_REG 0x04, 0x0000
770
	WRITE_GMII_REG 0x04, 0x7000
771
	WRITE_GMII_REG 0x03, 0xFF41
772
	WRITE_GMII_REG 0x02, 0xDE60
773
	WRITE_GMII_REG 0x01, 0x0140
774
	WRITE_GMII_REG 0x00, 0x0077
775
	WRITE_GMII_REG 0x04, 0x7800
776
	WRITE_GMII_REG 0x04, 0x7000
777
	WRITE_GMII_REG 0x04, 0xA000
778
	WRITE_GMII_REG 0x03, 0xDF01
779
	WRITE_GMII_REG 0x02, 0xDF20
780
	WRITE_GMII_REG 0x01, 0xFF95
781
	WRITE_GMII_REG 0x00, 0xFA00
782
	WRITE_GMII_REG 0x04, 0xA800
783
	WRITE_GMII_REG 0x04, 0xA000
784
	WRITE_GMII_REG 0x04, 0xB000
785
	WRITE_GMII_REG 0x03, 0xFF41
786
	WRITE_GMII_REG 0x02, 0xDE20
787
	WRITE_GMII_REG 0x01, 0x0140
788
	WRITE_GMII_REG 0x00, 0x00BB
789
	WRITE_GMII_REG 0x04, 0xB800
790
	WRITE_GMII_REG 0x04, 0xB000
791
	WRITE_GMII_REG 0x04, 0xF000
792
	WRITE_GMII_REG 0x03, 0xDF01
793
	WRITE_GMII_REG 0x02, 0xDF20
794
	WRITE_GMII_REG 0x01, 0xFF95
795
	WRITE_GMII_REG 0x00, 0xBF00
796
	WRITE_GMII_REG 0x04, 0xF800
797
	WRITE_GMII_REG 0x04, 0xF000
798
	WRITE_GMII_REG 0x04, 0x0000
799
	WRITE_GMII_REG 0x1F, 0x0000
800
	WRITE_GMII_REG 0x0B, 0x0000
801
	jmp	.exit
802
  .not_2_or_3:
803
	DEBUGF	1,"tpc.mcfg=%d, discard hw PHY config\n", [tpc.mcfg]
804
  .exit:
805
	ret
806
 
807
 
808
 
809
align 4
810
set_rx_mode:
811
 
812
	DEBUGF	1,"set_rx_mode\n"
813
 
814
	; IFF_ALLMULTI
815
	; Too many to filter perfectly -- accept all multicasts
816
	set_io	0
817
	set_io	REG_RxConfig
818
	in	eax, dx
819
	mov	ecx, [tpc.chipset]
820
	and	eax, [rtl_chip_info + ecx * 8 + 4] ; RxConfigMask
821
	or	eax, rx_config or (RXM_AcceptBroadcast or RXM_AcceptMulticast or RXM_AcceptMyPhys)
822
	out	dx, eax
823
 
824
	; Multicast hash filter
825
	set_io	REG_MAR0 + 0
826
	or	eax, -1
827
	out	dx, eax
828
	set_io	REG_MAR0 + 4
829
	out	dx, eax
830
 
831
	ret
832
 
833
 
834
align 4
835
init_ring:
836
 
837
	DEBUGF	1,"init_ring\n"
838
 
839
	xor	eax, eax
840
	mov	[tpc.cur_rx], eax
841
	mov	[tpc.cur_tx], eax
842
 
843
	lea	edi, [tx_ring]
844
	mov	ecx, (NUM_TX_DESC * tx_desc.size) / 4
845
	rep	stosd
846
 
847
	lea	edi, [rx_ring]
848
	mov	ecx, (NUM_RX_DESC * rx_desc.size) / 4
849
	rep	stosd
850
 
851
	mov	edi, [tpc.RxDescArray]
852
	mov	ecx, NUM_RX_DESC
853
    @@:
854
	stdcall KernelAlloc, 2048
855
	mov	[edi + rx_desc.buf_Haddr], eax
856
	GetRealAddr
857
	mov	[edi + rx_desc.buf_addr], eax
858
	mov	[edi + rx_desc.status], DSB_OWNbit or RX_BUF_SIZE
859
	add	edi, rx_desc.size
860
	loop	@b
861
	or	[edi - rx_desc.size + rx_desc.status], DSB_EORbit
862
 
863
	ret
864
 
865
 
866
align 4
867
hw_start:
868
 
869
	DEBUGF	1,"hw_start\n"
870
 
1556 hidnplayr 871
; attach int handler
872
	movzx	eax, [device.irq_line]
873
	DEBUGF	1,"Attaching int handler to irq %x\n", eax:1
874
	stdcall AttachIntHandler, eax, int_handler, dword 0
875
 
1554 hidnplayr 876
	; Soft reset the chip
877
	set_io	0
878
	set_io	REG_ChipCmd
879
	mov	al, CMD_Reset
880
	out	dx, al
881
 
882
	; Check that the chip has finished the reset
883
	mov	ecx, 1000
884
	set_io	REG_ChipCmd
885
    @@: in	al, dx
886
	test	al, CMD_Reset
887
	jz	@f
888
	udelay	10
889
	loop	@b
890
    @@:
891
 
892
	set_io	REG_Cfg9346
893
	mov	al, CFG_9346_Unlock
894
	out	dx, al
895
 
896
	set_io	REG_ChipCmd
897
	mov	al, CMD_TxEnb or CMD_RxEnb
898
	out	dx, al
899
 
900
	set_io	REG_ETThReg
901
	mov	al, ETTh
902
	out	dx, al
903
 
904
	; For gigabit rtl8169
905
	set_io	REG_RxMaxSize
906
	mov	ax, RxPacketMaxSize
907
	out	dx, ax
908
 
909
	; Set Rx Config register
910
	set_io	REG_RxConfig
911
	in	ax, dx
912
	mov	ecx, [tpc.chipset]
913
	and	eax, [rtl_chip_info + ecx * 8 + 4] ; RxConfigMask
914
	or	eax, rx_config
915
	out	dx, eax
916
 
917
	; Set DMA burst size and Interframe Gap Time
918
	set_io	REG_TxConfig
919
	mov	eax, (TX_DMA_BURST shl TXC_DMAShift) or (InterFrameGap shl TXC_InterFrameGapShift)
920
	out	dx, eax
921
 
922
	set_io	REG_CPlusCmd
923
	in	ax, dx
924
	out	dx, ax
925
 
926
	in	ax, dx
927
	or	ax, 1 shl 3
928
	cmp	[tpc.mcfg], MCFG_METHOD_02
929
	jne	@f
930
	cmp	[tpc.mcfg], MCFG_METHOD_03
931
	jne	@f
932
	or	ax,1 shl 14
933
	DEBUGF	1,"Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14\n"
934
	jmp	.set
935
    @@:
936
	DEBUGF	1," Set MAC Reg C+CR Offset 0xE0: bit-3\n"
937
  .set:
938
	set_io	REG_CPlusCmd
939
	out	dx, ax
940
 
941
	set_io	0xE2
942
;        mov     ax, 0x1517
943
;        out     dx, ax
944
;        mov     ax, 0x152a
945
;        out     dx, ax
946
;        mov     ax, 0x282a
947
;        out     dx, ax
948
	xor	ax, ax
949
	out	dx, ax
950
 
951
	xor	eax, eax
952
	mov	[tpc.cur_rx], eax
953
	lea	eax, [tx_ring]
954
	GetRealAddr
955
	set_io	REG_TxDescStartAddr
956
	out	dx, eax
957
 
958
	lea	eax, [rx_ring]
959
	GetRealAddr
960
	set_io	REG_RxDescStartAddr
961
	out	dx, eax
962
 
963
	set_io	REG_Cfg9346
964
	mov	al, CFG_9346_Lock
965
	out	dx, al
966
 
967
	udelay	10
968
 
969
	xor	eax, eax
970
	set_io	REG_RxMissed
971
	out	dx, eax
972
 
973
	call	set_rx_mode
974
 
975
	; no early-rx interrupts
976
	set_io	REG_MultiIntr
977
	in	ax, dx
978
	and	ax, 0xF000
979
	out	dx, ax
980
 
981
	; set interrupt mask
982
	set_io	REG_IntrMask
983
	mov	ax, intr_mask
984
	out	dx, ax
985
 
986
	xor	eax, eax
987
	ret
988
 
989
 
990
align 4
991
read_mac:
992
 
993
	set_io	0
994
	set_io	REG_MAC0
995
	xor	ecx, ecx
996
	lea	esi, [device.mac]
997
	mov	ecx, MAC_ADDR_LEN
998
 
999
	; Get MAC address. FIXME: read EEPROM
1000
    @@: in	al, dx
1001
	stosb
1002
	inc	edx
1003
	loop	@r
1004
 
1005
	DEBUGF	1,"MAC = %x-%x-%x-%x-%x-%x\n",[device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
1006
 
1007
	ret
1008
 
1009
align 4
1010
write_mac:
1011
 
1012
	ret	6
1013
 
1014
 
1015
 
1016
 
1017
 
1018
;***************************************************************************
1019
;   Function
1020
;      transmit
1021
;   Description
1022
;      Transmits a packet of data via the ethernet card
1023
;
1024
;   Destroyed registers
1025
;      eax, edx, esi, edi
1026
;
1027
;***************************************************************************
1028
align 4
1029
transmit:
1030
 
1031
	DEBUGF	1,"Transmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
1032
	mov	eax, [esp+4]
1033
	DEBUGF	1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
1034
	[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
1035
	[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
1036
	[eax+13]:2,[eax+12]:2
1037
 
1038
	cmp	dword [esp+8], MAX_ETH_FRAME_SIZE
1039
	ja	.fail
1040
 
1041
;----------------------------------
1042
; Find currentTX descriptor address
1043
 
1044
	mov	eax, tx_desc.size
1045
	mul	[tpc.cur_tx]
1046
	lea	esi, [eax + tx_ring]
1047
 
1048
;---------------------------
1049
; Program the packet pointer
1050
 
1051
	mov	eax, [esp]
1052
	mov	[esi + tx_desc.buf_Haddr], eax
1053
	GetRealAddr
1054
	mov	[esi + tx_desc.buf_addr], eax
1055
 
1056
;------------------------
1057
; Program the packet size
1058
 
1059
	mov	eax, [esp + 4]
1060
    @@: or	eax, DSB_OWNbit or DSB_FSbit or DSB_LSbit
1061
	cmp	[tpc.cur_tx], NUM_TX_DESC - 1
1062
	jne	@f
1063
	or	eax, DSB_EORbit
1064
    @@: mov	[esi + tx_desc.status], eax
1065
 
1066
;----------------------------------------
1067
; Set the polling bit (start transmission
1068
 
1069
	set_io	0
1070
	set_io	REG_TxPoll
1071
	mov	al, 0x40     ; set polling bit
1072
	out	dx, al
1073
 
1074
;-----------------------
1075
; Update TX descriptor
1076
 
1077
	inc	[tpc.cur_tx]
1078
	and	[tpc.cur_tx], NUM_TX_DESC - 1
1079
 
1080
	ret	8
1081
 
1082
  .fail:
1083
	DEBUGF	1,"transmit failed\n"
1084
	or	eax, -1
1085
	stdcall KernelFree, [esp+4]
1086
	ret	8
1087
 
1088
 
1089
;;;DSB_OWNbit
1090
 
1091
 
1092
;;;;;;;;;;;;;;;;;;;;;;;
1093
;;                   ;;
1094
;; Interrupt handler ;;
1095
;;                   ;;
1096
;;;;;;;;;;;;;;;;;;;;;;;
1097
 
1098
align 4
1099
int_handler:
1100
 
1101
	DEBUGF	1,"IRQ %x ",eax:2
1102
 
1103
; find pointer of device wich made IRQ occur
1104
 
1105
	mov	ecx, [devices]
1106
	test	ecx, ecx
1107
	jz	.fail
1108
	mov	esi, device_list
1109
  .nextdevice:
1110
	mov	ebx, dword [esi]
1111
 
1112
	set_io	REG_IntrStatus
1113
	in	ax, dx
1114
 
1115
	test	ax, ax
1116
	jnz	.got_it
1117
 
1118
  .continue:
1119
	add	esi, 4
1120
	dec	ecx
1121
	jnz	.nextdevice
1122
 
1123
	ret						; If no device was found, abort (The irq was probably for a device, not registered to this driver)
1124
 
1125
  .got_it:
1126
	DEBUGF	1,"IntrStatus = 0x%x\n",ax
1127
 
1128
	cmp	ax, 0xFFFF	; if so, hardware is no longer present
1129
	je	.fail
1130
 
1131
;--------
1132
; Receive
1133
 
1134
	test	ax, ISB_RxOK
1135
	jz	.no_rx
1136
 
1137
	push	ax
1138
 
1139
	mov	eax, rx_desc.size
1140
	mul	[tpc.cur_rx]
1141
	lea	esi, [eax + rx_ring]
1142
 
1143
	DEBUGF	1,"RxDesc.status = 0x%x\n", [esi + rx_desc.status]
1144
 
1145
	test	[esi + rx_desc.status], DSB_OWNbit
1146
	jnz	.rx_return
1147
 
1148
	DEBUGF	1,"tpc.cur_rx = %u\n", [tpc.cur_rx]
1149
 
1150
	test	eax, SD_RxRES
1151
	jnz	.rx_return	;;;;; RX error!
1152
 
1153
	push	.rx_return
1154
	and	eax, 0x00001FFF
1155
	add	eax, -4 			; we dont need CRC
1156
	push	eax
1157
	DEBUGF	1,"data length = %u\n", ax
1158
 
1159
	push	[esi + rx_desc.buf_Haddr]
1160
 
1161
;---------------
1162
; re set OWN bit
1163
 
1164
	mov	eax, DSB_OWNbit or RX_BUF_SIZE
1165
	cmp	[tpc.cur_rx], NUM_RX_DESC - 1
1166
	jne	@f
1167
	or	eax, DSB_EORbit
1168
    @@: mov	[esi + rx_desc.status], eax
1169
 
1170
;----------------------
1171
; Allocate a new buffer
1172
 
1173
	stdcall KernelAlloc, RX_BUF_SIZE
1174
	mov	[esi + rx_desc.buf_Haddr], eax
1175
	GetRealAddr
1176
	sub	[esi + rx_desc.buf_addr], eax
1177
 
1178
;--------------
1179
; Update rx ptr
1180
 
1181
	inc	[tpc.cur_rx]
1182
	and	[tpc.cur_rx], NUM_RX_DESC - 1
1183
 
1184
	jmp	EthReceiver
1185
  .rx_return:
1186
 
1187
	pop	ax
1188
  .no_rx:
1189
 
1190
;---------
1191
; Transmit
1192
 
1193
	test	ax, ISB_TxOK
1194
	jz	.no_tx
1195
	push	ax
1196
 
1197
	DEBUGF	1,"TX ok!\n"
1198
	; TODO: free buffers
1199
 
1200
	pop	ax
1201
  .no_tx:
1202
 
1203
;-------
1204
; Finish
1205
 
1206
	set_io	0
1207
	set_io	REG_IntrStatus
1208
	out	dx, ax			; ACK all interrupts
1209
 
1210
  .fail:
1211
	ret
1212
 
1213
 
1214
 
1215
 
1216
 
1217
 
1218
 
1219
 
1220
 
1221
; End of code
1222
align 4 					; Place all initialised data here
1223
 
1224
devices       dd 0
1225
version       dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
1226
my_service    db 'RTL8169',0			; max 16 chars include zero
1227
 
1228
include_debug_strings				; All data wich FDO uses will be included here
1229
 
1230
rtl_chip_info dd \
1231
  MCFG_METHOD_01, 0xff7e1880, \ ; RTL8169
1232
  MCFG_METHOD_02, 0xff7e1880, \ ; RTL8169s/8110s
1233
  MCFG_METHOD_03, 0xff7e1880, \ ; RTL8169s/8110s
1234
  MCFG_METHOD_04, 0xff7e1880, \ ; RTL8169sb/8110sb
1235
  MCFG_METHOD_05, 0xff7e1880, \ ; RTL8169sc/8110sc
1236
  MCFG_METHOD_11, 0xff7e1880, \ ; RTL8168b/8111b   // PCI-E
1237
  MCFG_METHOD_12, 0xff7e1880, \ ; RTL8168b/8111b   // PCI-E
1238
  MCFG_METHOD_13, 0xff7e1880, \ ; RTL8101e         // PCI-E 8139
1239
  MCFG_METHOD_14, 0xff7e1880, \ ; RTL8100e         // PCI-E 8139
1240
  MCFG_METHOD_15, 0xff7e1880	; RTL8100e         // PCI-E 8139
1241
 
1242
mac_info dd \
1243
  0x38800000, MCFG_METHOD_15, \
1244
  0x38000000, MCFG_METHOD_12, \
1245
  0x34000000, MCFG_METHOD_13, \
1246
  0x30800000, MCFG_METHOD_14, \
1247
  0x30000000, MCFG_METHOD_11, \
1248
  0x18000000, MCFG_METHOD_05, \
1249
  0x10000000, MCFG_METHOD_04, \
1250
  0x04000000, MCFG_METHOD_03, \
1251
  0x00800000, MCFG_METHOD_02, \
1252
  0x00000000, MCFG_METHOD_01	; catch-all
1253
 
1254
section '.data' data readable writable align 16 ; place all uninitialized data place here
1255
 
1256
device_list rd MAX_DEVICES		       ; This list contains all pointers to device structures the driver is handling
1257