Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | 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
 
871
	; Soft reset the chip
872
	set_io	0
873
	set_io	REG_ChipCmd
874
	mov	al, CMD_Reset
875
	out	dx, al
876
 
877
	; Check that the chip has finished the reset
878
	mov	ecx, 1000
879
	set_io	REG_ChipCmd
880
    @@: in	al, dx
881
	test	al, CMD_Reset
882
	jz	@f
883
	udelay	10
884
	loop	@b
885
    @@:
886
 
887
	set_io	REG_Cfg9346
888
	mov	al, CFG_9346_Unlock
889
	out	dx, al
890
 
891
	set_io	REG_ChipCmd
892
	mov	al, CMD_TxEnb or CMD_RxEnb
893
	out	dx, al
894
 
895
	set_io	REG_ETThReg
896
	mov	al, ETTh
897
	out	dx, al
898
 
899
	; For gigabit rtl8169
900
	set_io	REG_RxMaxSize
901
	mov	ax, RxPacketMaxSize
902
	out	dx, ax
903
 
904
	; Set Rx Config register
905
	set_io	REG_RxConfig
906
	in	ax, dx
907
	mov	ecx, [tpc.chipset]
908
	and	eax, [rtl_chip_info + ecx * 8 + 4] ; RxConfigMask
909
	or	eax, rx_config
910
	out	dx, eax
911
 
912
	; Set DMA burst size and Interframe Gap Time
913
	set_io	REG_TxConfig
914
	mov	eax, (TX_DMA_BURST shl TXC_DMAShift) or (InterFrameGap shl TXC_InterFrameGapShift)
915
	out	dx, eax
916
 
917
	set_io	REG_CPlusCmd
918
	in	ax, dx
919
	out	dx, ax
920
 
921
	in	ax, dx
922
	or	ax, 1 shl 3
923
	cmp	[tpc.mcfg], MCFG_METHOD_02
924
	jne	@f
925
	cmp	[tpc.mcfg], MCFG_METHOD_03
926
	jne	@f
927
	or	ax,1 shl 14
928
	DEBUGF	1,"Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14\n"
929
	jmp	.set
930
    @@:
931
	DEBUGF	1," Set MAC Reg C+CR Offset 0xE0: bit-3\n"
932
  .set:
933
	set_io	REG_CPlusCmd
934
	out	dx, ax
935
 
936
	set_io	0xE2
937
;        mov     ax, 0x1517
938
;        out     dx, ax
939
;        mov     ax, 0x152a
940
;        out     dx, ax
941
;        mov     ax, 0x282a
942
;        out     dx, ax
943
	xor	ax, ax
944
	out	dx, ax
945
 
946
	xor	eax, eax
947
	mov	[tpc.cur_rx], eax
948
	lea	eax, [tx_ring]
949
	GetRealAddr
950
	set_io	REG_TxDescStartAddr
951
	out	dx, eax
952
 
953
	lea	eax, [rx_ring]
954
	GetRealAddr
955
	set_io	REG_RxDescStartAddr
956
	out	dx, eax
957
 
958
	set_io	REG_Cfg9346
959
	mov	al, CFG_9346_Lock
960
	out	dx, al
961
 
962
	udelay	10
963
 
964
	xor	eax, eax
965
	set_io	REG_RxMissed
966
	out	dx, eax
967
 
968
	call	set_rx_mode
969
 
970
	; no early-rx interrupts
971
	set_io	REG_MultiIntr
972
	in	ax, dx
973
	and	ax, 0xF000
974
	out	dx, ax
975
 
976
	; set interrupt mask
977
	set_io	REG_IntrMask
978
	mov	ax, intr_mask
979
	out	dx, ax
980
 
981
	xor	eax, eax
982
	ret
983
 
984
 
985
align 4
986
read_mac:
987
 
988
	set_io	0
989
	set_io	REG_MAC0
990
	xor	ecx, ecx
991
	lea	esi, [device.mac]
992
	mov	ecx, MAC_ADDR_LEN
993
 
994
	; Get MAC address. FIXME: read EEPROM
995
    @@: in	al, dx
996
	stosb
997
	inc	edx
998
	loop	@r
999
 
1000
	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
1001
 
1002
	ret
1003
 
1004
align 4
1005
write_mac:
1006
 
1007
	ret	6
1008
 
1009
 
1010
 
1011
 
1012
 
1013
;***************************************************************************
1014
;   Function
1015
;      transmit
1016
;   Description
1017
;      Transmits a packet of data via the ethernet card
1018
;
1019
;   Destroyed registers
1020
;      eax, edx, esi, edi
1021
;
1022
;***************************************************************************
1023
align 4
1024
transmit:
1025
 
1026
	DEBUGF	1,"Transmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
1027
	mov	eax, [esp+4]
1028
	DEBUGF	1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
1029
	[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
1030
	[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
1031
	[eax+13]:2,[eax+12]:2
1032
 
1033
	cmp	dword [esp+8], MAX_ETH_FRAME_SIZE
1034
	ja	.fail
1035
 
1036
;----------------------------------
1037
; Find currentTX descriptor address
1038
 
1039
	mov	eax, tx_desc.size
1040
	mul	[tpc.cur_tx]
1041
	lea	esi, [eax + tx_ring]
1042
 
1043
;---------------------------
1044
; Program the packet pointer
1045
 
1046
	mov	eax, [esp]
1047
	mov	[esi + tx_desc.buf_Haddr], eax
1048
	GetRealAddr
1049
	mov	[esi + tx_desc.buf_addr], eax
1050
 
1051
;------------------------
1052
; Program the packet size
1053
 
1054
	mov	eax, [esp + 4]
1055
    @@: or	eax, DSB_OWNbit or DSB_FSbit or DSB_LSbit
1056
	cmp	[tpc.cur_tx], NUM_TX_DESC - 1
1057
	jne	@f
1058
	or	eax, DSB_EORbit
1059
    @@: mov	[esi + tx_desc.status], eax
1060
 
1061
;----------------------------------------
1062
; Set the polling bit (start transmission
1063
 
1064
	set_io	0
1065
	set_io	REG_TxPoll
1066
	mov	al, 0x40     ; set polling bit
1067
	out	dx, al
1068
 
1069
;-----------------------
1070
; Update TX descriptor
1071
 
1072
	inc	[tpc.cur_tx]
1073
	and	[tpc.cur_tx], NUM_TX_DESC - 1
1074
 
1075
	ret	8
1076
 
1077
  .fail:
1078
	DEBUGF	1,"transmit failed\n"
1079
	or	eax, -1
1080
	stdcall KernelFree, [esp+4]
1081
	ret	8
1082
 
1083
 
1084
;;;DSB_OWNbit
1085
 
1086
 
1087
;;;;;;;;;;;;;;;;;;;;;;;
1088
;;                   ;;
1089
;; Interrupt handler ;;
1090
;;                   ;;
1091
;;;;;;;;;;;;;;;;;;;;;;;
1092
 
1093
align 4
1094
int_handler:
1095
 
1096
	DEBUGF	1,"IRQ %x ",eax:2
1097
 
1098
; find pointer of device wich made IRQ occur
1099
 
1100
	mov	ecx, [devices]
1101
	test	ecx, ecx
1102
	jz	.fail
1103
	mov	esi, device_list
1104
  .nextdevice:
1105
	mov	ebx, dword [esi]
1106
 
1107
	set_io	REG_IntrStatus
1108
	in	ax, dx
1109
 
1110
	test	ax, ax
1111
	jnz	.got_it
1112
 
1113
  .continue:
1114
	add	esi, 4
1115
	dec	ecx
1116
	jnz	.nextdevice
1117
 
1118
	ret						; If no device was found, abort (The irq was probably for a device, not registered to this driver)
1119
 
1120
  .got_it:
1121
	DEBUGF	1,"IntrStatus = 0x%x\n",ax
1122
 
1123
	cmp	ax, 0xFFFF	; if so, hardware is no longer present
1124
	je	.fail
1125
 
1126
;--------
1127
; Receive
1128
 
1129
	test	ax, ISB_RxOK
1130
	jz	.no_rx
1131
 
1132
	push	ax
1133
 
1134
	mov	eax, rx_desc.size
1135
	mul	[tpc.cur_rx]
1136
	lea	esi, [eax + rx_ring]
1137
 
1138
	DEBUGF	1,"RxDesc.status = 0x%x\n", [esi + rx_desc.status]
1139
 
1140
	test	[esi + rx_desc.status], DSB_OWNbit
1141
	jnz	.rx_return
1142
 
1143
	DEBUGF	1,"tpc.cur_rx = %u\n", [tpc.cur_rx]
1144
 
1145
	test	eax, SD_RxRES
1146
	jnz	.rx_return	;;;;; RX error!
1147
 
1148
	push	.rx_return
1149
	and	eax, 0x00001FFF
1150
	add	eax, -4 			; we dont need CRC
1151
	push	eax
1152
	DEBUGF	1,"data length = %u\n", ax
1153
 
1154
	push	[esi + rx_desc.buf_Haddr]
1155
 
1156
;---------------
1157
; re set OWN bit
1158
 
1159
	mov	eax, DSB_OWNbit or RX_BUF_SIZE
1160
	cmp	[tpc.cur_rx], NUM_RX_DESC - 1
1161
	jne	@f
1162
	or	eax, DSB_EORbit
1163
    @@: mov	[esi + rx_desc.status], eax
1164
 
1165
;----------------------
1166
; Allocate a new buffer
1167
 
1168
	stdcall KernelAlloc, RX_BUF_SIZE
1169
	mov	[esi + rx_desc.buf_Haddr], eax
1170
	GetRealAddr
1171
	sub	[esi + rx_desc.buf_addr], eax
1172
 
1173
;--------------
1174
; Update rx ptr
1175
 
1176
	inc	[tpc.cur_rx]
1177
	and	[tpc.cur_rx], NUM_RX_DESC - 1
1178
 
1179
	jmp	EthReceiver
1180
  .rx_return:
1181
 
1182
	pop	ax
1183
  .no_rx:
1184
 
1185
;---------
1186
; Transmit
1187
 
1188
	test	ax, ISB_TxOK
1189
	jz	.no_tx
1190
	push	ax
1191
 
1192
	DEBUGF	1,"TX ok!\n"
1193
	; TODO: free buffers
1194
 
1195
	pop	ax
1196
  .no_tx:
1197
 
1198
;-------
1199
; Finish
1200
 
1201
	set_io	0
1202
	set_io	REG_IntrStatus
1203
	out	dx, ax			; ACK all interrupts
1204
 
1205
  .fail:
1206
	ret
1207
 
1208
 
1209
 
1210
 
1211
 
1212
 
1213
 
1214
 
1215
 
1216
; End of code
1217
align 4 					; Place all initialised data here
1218
 
1219
devices       dd 0
1220
version       dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
1221
my_service    db 'RTL8169',0			; max 16 chars include zero
1222
 
1223
include_debug_strings				; All data wich FDO uses will be included here
1224
 
1225
rtl_chip_info dd \
1226
  MCFG_METHOD_01, 0xff7e1880, \ ; RTL8169
1227
  MCFG_METHOD_02, 0xff7e1880, \ ; RTL8169s/8110s
1228
  MCFG_METHOD_03, 0xff7e1880, \ ; RTL8169s/8110s
1229
  MCFG_METHOD_04, 0xff7e1880, \ ; RTL8169sb/8110sb
1230
  MCFG_METHOD_05, 0xff7e1880, \ ; RTL8169sc/8110sc
1231
  MCFG_METHOD_11, 0xff7e1880, \ ; RTL8168b/8111b   // PCI-E
1232
  MCFG_METHOD_12, 0xff7e1880, \ ; RTL8168b/8111b   // PCI-E
1233
  MCFG_METHOD_13, 0xff7e1880, \ ; RTL8101e         // PCI-E 8139
1234
  MCFG_METHOD_14, 0xff7e1880, \ ; RTL8100e         // PCI-E 8139
1235
  MCFG_METHOD_15, 0xff7e1880	; RTL8100e         // PCI-E 8139
1236
 
1237
mac_info dd \
1238
  0x38800000, MCFG_METHOD_15, \
1239
  0x38000000, MCFG_METHOD_12, \
1240
  0x34000000, MCFG_METHOD_13, \
1241
  0x30800000, MCFG_METHOD_14, \
1242
  0x30000000, MCFG_METHOD_11, \
1243
  0x18000000, MCFG_METHOD_05, \
1244
  0x10000000, MCFG_METHOD_04, \
1245
  0x04000000, MCFG_METHOD_03, \
1246
  0x00800000, MCFG_METHOD_02, \
1247
  0x00000000, MCFG_METHOD_01	; catch-all
1248
 
1249
section '.data' data readable writable align 16 ; place all uninitialized data place here
1250
 
1251
device_list rd MAX_DEVICES		       ; This list contains all pointers to device structures the driver is handling
1252