Subversion Repositories Kolibri OS

Rev

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