Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | 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 ?
198
	.phy_addr	dw ?
199
	.phy_mode	dw ?
200
	.mcr0		dw ?
201
	.mcr1		dw ?
202
	.switch_sig	dw ?
203
 
204
	.pci_bus	db ?
205
	.pci_dev	db ?
206
	.irq_line	db ?
207
 
208
	rb 3		; dword alignment
209
 
210
	.tx_ring:	rb (((x_head.sizeof*TX_RING_SIZE)+32) and 0xfffffff0)
211
	.rx_ring:	rb (((x_head.sizeof*RX_RING_SIZE)+32) and 0xfffffff0)
212
 
213
	.size = $ - device
214
 
215
end virtual
216
 
217
 
218
 
219
section '.flat' code readable align 16
220
 
221
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
222
;;                        ;;
223
;; proc START             ;;
224
;;                        ;;
225
;; (standard driver proc) ;;
226
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
227
 
228
align 4
229
proc START stdcall, state:dword
230
 
231
	cmp [state], 1
232
	jne .exit
233
 
234
  .entry:
235
 
236
	DEBUGF	2,"Loading R6040 driver\n"
237
	stdcall RegService, my_service, service_proc
238
	ret
239
 
240
  .fail:
241
  .exit:
242
	xor eax, eax
243
	ret
244
 
245
endp
246
 
247
 
248
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
249
;;                        ;;
250
;; proc SERVICE_PROC      ;;
251
;;                        ;;
252
;; (standard driver proc) ;;
253
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
254
 
255
align 4
256
proc service_proc stdcall, ioctl:dword
257
 
258
	mov	edx, [ioctl]
259
	mov	eax, [IOCTL.io_code]
260
 
261
;------------------------------------------------------
262
 
263
	cmp	eax, 0 ;SRV_GETVERSION
264
	jne	@F
265
 
266
	cmp	[IOCTL.out_size], 4
267
	jl	.fail
268
	mov	eax, [IOCTL.output]
269
	mov	[eax], dword API_VERSION
270
 
271
	xor	eax, eax
272
	ret
273
 
274
;------------------------------------------------------
275
  @@:
276
	cmp	eax, 1 ;SRV_HOOK
277
	jne	.fail
278
 
279
	cmp	[IOCTL.inp_size], 3			; Data input must be at least 3 bytes
280
	jl	.fail
281
 
282
	mov	eax, [IOCTL.input]
283
	cmp	byte [eax], 1				; 1 means device number and bus number (pci) are given
284
	jne	.fail					; other types arent supported for this card yet
285
 
286
; check if the device is already listed
287
 
288
	mov	esi, device_list
289
	mov	ecx, [devices]
290
	test	ecx, ecx
291
	jz	.firstdevice
292
 
293
;        mov     eax, [IOCTL.input]                      ; get the pci bus and device numbers
294
	mov	ax , [eax+1]				;
295
  .nextdevice:
296
	mov	ebx, [esi]
297
	cmp	ax , word [device.pci_bus]		; compare with pci and device num in device list (notice the usage of word instead of byte)
298
	je	.find_devicenum 			; Device is already loaded, let's find it's device number
299
	add	esi, 4
300
	loop	.nextdevice
301
 
302
 
303
; This device doesnt have its own eth_device structure yet, lets create one
304
  .firstdevice:
305
	cmp	[devices], MAX_DEVICES			; First check if the driver can handle one more card
306
	jge	.fail
307
 
308
	allocate_and_clear ebx, device.size, .fail	; Allocate the buffer for device structure
309
 
310
; Fill in the direct call addresses into the struct
311
 
312
	mov	[device.reset], reset
313
	mov	[device.transmit], transmit
314
	mov	[device.get_MAC], read_mac
315
	mov	[device.set_MAC], .fail
316
	mov	[device.unload], unload
317
	mov	[device.name], my_service
318
 
319
; save the pci bus and device numbers
320
 
321
	mov	eax, [IOCTL.input]
322
	mov	cl , [eax+1]
323
	mov	[device.pci_bus], cl
324
	mov	cl , [eax+2]
325
	mov	[device.pci_dev], cl
326
 
327
; Now, it's time to find the base io addres of the PCI device
328
 
329
	find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
330
 
331
; We've found the io address, find IRQ now
332
 
333
	find_irq [device.pci_bus], [device.pci_dev], [device.irq_line]
334
 
335
	DEBUGF	2,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
336
	[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
337
 
338
; Ok, the eth_device structure is ready, let's probe the device
339
	cli
340
 
341
	call	probe							; this function will output in eax
342
	test	eax, eax
343
	jnz	.err_sti						; If an error occured, exit
344
 
345
	mov	eax, [devices]						; Add the device structure to our device list
346
	mov	[device_list+4*eax], ebx				; (IRQ handler uses this list to find device)
347
	inc	[devices]						;
348
 
349
	mov	[device.type], NET_TYPE_ETH
350
	call	NetRegDev
351
	sti
352
 
353
	cmp	eax, -1
354
	je	.destroy
355
 
356
	ret
357
 
358
; If the device was already loaded, find the device number and return it in eax
359
 
360
  .find_devicenum:
361
	DEBUGF	2,"Trying to find device number of already registered device\n"
362
	call	NetPtrToNum						; This kernel procedure converts a pointer to device struct in ebx
363
									; into a device number in edi
364
	mov	eax, edi						; Application wants it in eax instead
365
	DEBUGF	2,"Kernel says: %u\n", eax
366
	ret
367
 
368
; If an error occured, remove all allocated data and exit (returning -1 in eax)
369
 
370
  .destroy:
371
	; todo: reset device into virgin state
372
 
373
  .err_sti:
374
	sti
375
 
376
  .err:
377
	stdcall KernelFree, ebx
378
 
379
  .fail:
380
	or	eax, -1
381
	ret
382
 
383
;------------------------------------------------------
384
endp
385
 
386
 
387
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
388
;;                                                                        ;;
389
;;        Actual Hardware dependent code starts here                      ;;
390
;;                                                                        ;;
391
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
392
 
393
 
394
macro r6040_mdio_write reg, val {
395
	stdcall r6040_phy_read, [io_addr], [r6040_private.phy_addr], reg
396
}
397
 
398
macro r6040_mdio_write reg, val {
399
	stdcall r6040_phy_write, [io_addr], [r6040_private.phy_addr], reg, val
400
}
401
 
402
 
403
align 4
404
unload:
405
	; TODO: (in this particular order)
406
	;
407
	; - Stop the device
408
	; - Detach int handler
409
	; - Remove device from local list (RTL8139_LIST)
410
	; - call unregister function in kernel
411
	; - Remove all allocated structures and buffers the card used
412
 
413
	or	eax,-1
414
 
415
ret
416
 
417
 
418
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
419
;;
420
;;  probe: enables the device (if it really is RTL8139)
421
;;
422
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
423
 
424
align 4
425
probe:
426
	DEBUGF	2,"Probing R6040 device\n"
427
 
428
	make_bus_master [device.pci_bus], [device.pci_dev]
429
 
430
	; If PHY status change register is still set to zero
431
	; it means the bootloader didn't initialize it
432
 
433
	set_io	0
434
	set_io	PHY_CC
435
	in	ax, dx
436
	test	ax, ax
437
	jnz	@f
438
	mov	ax, 0x9F07
439
	out	dx, ax
440
     @@:
441
 
442
	call	read_mac
443
 
444
	; Some bootloaders/BIOSes do not initialize MAC address, warn about that
445
	and	eax, 0xFF
446
	or	eax, dword [device.mac]
447
	test	eax, eax
448
	jnz	@f
449
	DEBUGF	1, "MAC address not initialized\n" ;, generating random"
450
 
451
	;Asper: Add here generate function call!
452
	;       Temporary workaround: init by constant adress
453
 
454
	mov	dword [device.mac], 0x00006000
455
	mov	word [device.mac+4], 0x0001
456
     @@:
457
 
458
	; Init RDC private data
459
	mov	[device.mcr0], 0x1002
460
	;mov     [private.phy_addr], 1 ; Asper: Only one network card is supported now.
461
	mov	[device.switch_sig], 0
462
 
463
	; Check the vendor ID on the PHY, if 0xFFFF assume none attached
464
	stdcall phy_read, 1, 2
465
	cmp	ax, 0xFFFF
466
	jne	@f
467
	DEBUGF	1, "Failed to detect an attached PHY\n" ;, generating random"
468
	mov	eax, -1
469
	ret
470
     @@:
471
 
472
	; Set MAC address
473
	call	init_mac_regs
474
 
475
	; Initialize and alloc RX/TX buffers
476
	call	init_txbufs
477
	call	init_rxbufs
478
 
479
	; Read the PHY ID
480
	mov	[device.phy_mode], 0x8000
481
	stdcall phy_read, 0, 2
482
	mov	[device.switch_sig], ax
483
	cmp	ax, ICPLUS_PHY_ID
484
	jne	@f
485
	stdcall phy_write, 29, 31, 0x175C ; Enable registers
486
	jmp	.phy_readen
487
      @@:
488
 
489
	; PHY Mode Check
490
	movzx	eax, [device.phy_addr]
491
	stdcall phy_write, eax, 4, PHY_CAP
492
	stdcall phy_write, eax, 0, PHY_MODE
493
 
494
;      if PHY_MODE = 0x3100
495
	call	phy_mode_chk
496
	mov	[device.phy_mode], ax
497
	jmp	.phy_readen
498
;      end if
499
 
500
;      if not (PHY_MODE and 0x0100)
501
	mov	[device.phy_mode], 0
502
;      end if
503
      .phy_readen:
504
 
505
	; Set duplex mode
506
	mov	ax, [device.phy_mode]
507
	or	[device.mcr0], ax
508
 
509
	; improve performance (by RDC guys)
510
	stdcall phy_read, 30, 17
511
	or	ax, 0x4000
512
	stdcall phy_write, 30, 17, eax
513
 
514
	stdcall phy_read, 30, 17
515
	and	ax, not 0x2000
516
	stdcall phy_write, 30, 17, eax
517
 
518
	stdcall phy_write, 0, 19, 0x0000
519
	stdcall phy_write, 0, 30, 0x01F0
520
 
521
	; Initialize all Mac registers
522
	call	init_mac_regs
523
 
524
 
525
 
526
align 4
527
reset:
528
 
529
	DEBUGF	1,"Resetting R6040\n"
530
 
531
	; Mask off Interrupt
532
	xor	ax, ax
533
	set_io	0
534
	set_io	MIER
535
	out	dx, ax
536
 
537
 
538
; attach int handler
539
 
540
	movzx	eax, [device.irq_line]
541
	DEBUGF	1,"Attaching int handler to irq %x\n", eax:1
542
	stdcall AttachIntHandler, eax, int_handler, dword 0
543
	test	eax, eax
544
	jnz	@f
545
	DEBUGF	1,"\nCould not attach int handler!\n"
546
;        or      eax, -1
547
;        ret
548
       @@:
549
 
550
 
551
	;Reset RDC MAC
552
	mov	eax, MAC_RST
553
	set_io	0
554
	set_io	MCR1
555
	out	dx, ax
556
 
557
	mov	ecx, 2048 ;limit
558
  .read:
559
	in	ax, dx
560
	test	ax, 0x1
561
	jnz	 @f
562
	dec	ecx
563
	test	ecx, ecx
564
	jnz	.read
565
  @@:
566
	;Reset internal state machine
567
	mov	ax,  2
568
	set_io	MAC_SM
569
	out	dx, ax
570
 
571
	xor	ax, ax
572
	out	dx, ax
573
 
574
	mov	esi, 5
575
	stdcall Sleep
576
 
577
	;MAC Bus Control Register
578
	mov	ax, MBCR_DEFAULT
579
	set_io	0
580
	set_io	MBCR
581
	out	dx, ax
582
 
583
	;Buffer Size Register
584
	mov	ax, MAX_BUF_SIZE
585
	set_io	MR_BSR
586
	out	dx, ax
587
 
588
	;Write TX ring start address
589
	lea	eax, [device.tx_ring]
590
	GetRealAddr
591
	set_io	MTD_SA0
592
	out	dx, ax
593
	shr	eax, 16
594
	set_io	MTD_SA1
595
	out	dx, ax
596
 
597
	;Write RX ring start address
598
	lea	eax, [device.rx_ring]
599
	GetRealAddr
600
	set_io	MRD_SA0
601
	out	dx, ax
602
	shr	eax, 16
603
	set_io	MRD_SA1
604
	out	dx, ax
605
 
606
	;Set interrupt waiting time and packet numbers
607
	xor	ax, ax
608
	set_io	MT_ICR
609
	out	dx, ax
610
 
611
	;Enable interrupts
612
	mov	ax, INT_MASK
613
	set_io	MIER
614
	out	dx, ax
615
 
616
	;Enable TX and RX
617
	mov	ax, [device.mcr0]
618
	or	ax, 0x0002
619
	set_io	0
620
	out	dx, ax
621
 
622
	;Let TX poll the descriptors
623
	;we may got called by tx_timeout which has left
624
	;some unset tx buffers
625
	xor	ax, ax
626
	inc	ax
627
	set_io	0
628
	set_io	MTPR
629
	out	dx, ax
630
 
631
; Set the mtu, kernel will be able to send now
632
	mov	[device.mtu], 1514
633
 
634
	DEBUGF	1,"Reset ok\n"
635
	xor	eax, eax
636
 
637
	ret
638
 
639
 
640
 
641
align 4
642
init_txbufs:
643
 
644
	DEBUGF	1,"Init TxBufs\n"
645
 
646
	lea	esi, [device.tx_ring]
647
	lea	eax, [device.tx_ring + x_head.sizeof]
648
	GetRealAddr
649
	mov	ecx, TX_RING_SIZE
650
 
651
    .next_desc:
652
	mov	[esi + x_head.ndesc], eax
653
	mov	[esi + x_head.status], DSC_OWNER_MAC
654
 
655
	add	eax, x_head.sizeof
656
	add	esi, x_head.sizeof
657
 
658
	dec	ecx
659
	jnz	.next_desc
660
 
661
	lea	eax, [device.tx_ring]
662
	GetRealAddr
663
	mov	[device.tx_ring + x_head.sizeof*(TX_RING_SIZE - 1) + x_head.ndesc], eax
664
 
665
	DEBUGF	1,"ok\n"
666
 
667
	ret
668
 
669
 
670
 
671
align 4
672
init_rxbufs:
673
 
674
	DEBUGF	1,"Init RxBufs\n"
675
 
676
	lea	esi, [device.rx_ring]
677
	lea	eax, [device.rx_ring + x_head.sizeof]
678
	GetRealAddr
679
	mov	edx, eax
680
	mov	ecx, RX_RING_SIZE
681
 
682
    .next_desc:
683
	DEBUGF	1,"esi=0x%x, edx=0x%x, ", esi, edx
684
	mov	[esi + x_head.ndesc], edx
685
 
686
	push	esi ecx
687
	stdcall KernelAlloc, dword 2000
688
	pop	ecx esi
689
 
690
	DEBUGF	1,"eax=0x%x, ", eax
691
	mov	[esi + x_head.skb_ptr], eax
692
	GetRealAddr
693
	DEBUGF	1,"eax=0x%x\n", eax
694
	mov	[esi + x_head.buf], eax
695
	mov	[esi + x_head.status], DSC_OWNER_MAC
696
 
697
	add	edx, x_head.sizeof
698
	add	esi, x_head.sizeof
699
 
700
	dec	ecx
701
	jnz	.next_desc
702
 
703
	; complete the ring by linking the last to the first
704
 
705
	lea	eax, [device.rx_ring]
706
	GetRealAddr
707
	mov	[device.rx_ring + x_head.sizeof*(RX_RING_SIZE - 1) + x_head.ndesc], eax
708
 
709
	DEBUGF	1,"ok\n"
710
 
711
	ret
712
 
713
 
714
 
715
align 4
716
phy_mode_chk:
717
 
718
	DEBUGF	1,"Checking PHY mode\n"
719
 
720
	; PHY Link Status Check
721
	movzx	eax, [device.phy_addr]
722
	stdcall phy_read, eax, 1
723
	test	eax, 0x4
724
	jz	.ret_0x8000
725
 
726
;        jnz     @f
727
;        mov     eax, 0x8000             ; Link Failed, full duplex
728
;  @@:
729
 
730
	; PHY Chip Auto-Negotiation Status
731
	movzx	eax, [device.phy_addr]
732
	stdcall phy_read, eax, 1
733
	test	eax, 0x0020
734
	jnz	.auto_nego
735
 
736
	; Force Mode
737
	movzx	eax, [device.phy_addr]
738
	stdcall phy_read, eax, 0
739
	test	eax, 0x100
740
	jnz	.ret_0x8000
741
 
742
  .auto_nego:
743
	; Auto Negotiation Mode
744
	movzx	eax, [device.phy_addr]
745
	stdcall phy_read, eax, 5
746
	mov	ecx, eax
747
	movzx	eax, [device.phy_addr]
748
	stdcall phy_read, eax, 4
749
	and	eax, ecx
750
	test	eax, 0x140
751
	jnz	.ret_0x8000
752
 
753
	xor	eax, eax
754
	ret
755
 
756
  .ret_0x8000:
757
	mov	eax, 0x8000
758
	ret
759
 
760
 
761
 
762
 
763
 
764
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
765
;;                                         ;;
766
;; Transmit                                ;;
767
;;                                         ;;
768
;; In: buffer pointer in [esp+4]           ;;
769
;;     size of buffer in [esp+8]           ;;
770
;;     pointer to device structure in ebx  ;;
771
;;                                         ;;
772
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
773
align 4
774
transmit:
775
	DEBUGF	1,"\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
776
	mov	eax, [esp+4]
777
	DEBUGF	1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
778
	[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
779
	[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
780
	[eax+13]:2,[eax+12]:2
781
 
782
	cmp	dword [esp+8], 1514
783
	jg	.fail
784
	cmp	dword [esp+8], 60
785
	jl	.fail
786
 
787
	movzx	edi, [device.cur_tx]
788
	shl	edi, 5
789
	add	edi, ebx
790
	add	edi, device.tx_ring - ebx
791
 
792
	DEBUGF	1,"R6040: TX buffer status: 0x%x\n", [edi + x_head.status]:4
793
 
794
	test	[edi + x_head.status], 0x8000  ; check if buffer is available
795
	jnz	.wait_to_send
796
 
797
  .do_send:
798
 
799
	mov	eax, [esp+4]
800
	mov	[edi + x_head.skb_ptr], eax
801
	GetRealAddr
802
	mov	[edi + x_head.buf], eax
803
	mov	ecx, [esp+8]
804
	mov	[edi + x_head.len], cx
805
	mov	[edi + x_head.status], 0x8000
806
 
807
	; Trigger the MAC to check the TX descriptor
808
	mov	ax, 0x01
809
	set_io	0
810
	set_io	MTPR
811
	out	dx, ax
812
 
813
	inc	[device.cur_tx]
814
	and	[device.cur_tx], TX_RING_SIZE-1
815
	xor	eax, eax
816
 
817
	ret	8
818
 
819
  .wait_to_send:
820
 
821
;        mov     ecx, [timer_ticks]
822
;        add     ecx, 100
823
;     .l2:
824
;        test    [eax + x_head.status], 0x8000
825
;        jz      .do_send
826
;        mov     esi, 10
827
;        call    Sleep
828
;        cmp     ecx, [timer_ticks]
829
;        jl      .l2
830
 
831
	xor	eax, eax
832
	dec	eax
833
  .fail:
834
	DEBUGF	1,"R6040: Send timeout\n"
835
	ret	8
836
 
837
 
838
 
839
 
840
 
841
;;;;;;;;;;;;;;;;;;;;;;;
842
;;                   ;;
843
;; Interrupt handler ;;
844
;;                   ;;
845
;;;;;;;;;;;;;;;;;;;;;;;
846
align 4
847
int_handler:
848
 
849
	DEBUGF	1,"\nIRQ %x ", eax:2   ; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO
850
 
851
; Find pointer of device wich made IRQ occur
852
 
853
	mov	esi, device_list
854
	mov	ecx, [devices]
855
	test	ecx, ecx
856
	jz	.fail
857
  .nextdevice:
858
	mov	ebx, dword [esi]
859
 
860
	; Find reason for IRQ
861
 
862
	set_io	0
863
	set_io	MISR
864
	in	ax, dx
865
	out	dx, ax		; send it back to ACK
866
 
867
	DEBUGF	1,"MISR=%x\n", eax:4
868
 
869
	; Check if we are interessed in some of the reasons
870
 
871
	test	ax, INT_MASK
872
	jnz	.got_it
873
 
874
	; If not, try next device
875
 
876
	add	esi, 4
877
	dec	ecx
878
	jnz	.nextdevice
879
				; If no device was found, abort (The irq was probably for a device, not registered to this driver)
880
	ret
881
 
882
; At this point, test for all possible reasons, and handle accordingly
883
 
884
  .got_it:
885
 
886
	test	ax, RX_FINISH
887
	jz	.no_RX
888
 
889
	push	ebx
890
  .more_RX:
891
	pop	ebx
892
 
893
	; Find the current RX descriptor
894
 
895
	movzx	edx, [device.cur_rx]
896
	shl	edx, 5
897
	lea	edx, [device.rx_ring + edx]
898
 
899
	; Check the descriptor status
900
 
901
	mov	cx, [edx + x_head.status]
902
	test	cx, DSC_OWNER_MAC
903
	jnz	.no_RX
904
 
905
	DEBUGF	1,"packet status=0x%x\n", cx
906
 
907
	test	cx, DSC_RX_ERR		; Global error status set
908
	jnz	.no_RX
909
 
910
	; Packet successfully received
911
 
912
	movzx	ecx, [edx + x_head.len]
913
	and	ecx, 0xFFF
914
	sub	ecx, 4			; Do not count the CRC
915
 
916
	; Push packet size and pointer, kernel will need it..
917
 
918
	push	ebx
919
	push	.more_RX
920
 
921
	push	ecx
922
	push	[edx + x_head.skb_ptr]
923
 
924
	DEBUGF	1,"packet ptr=0x%x\n", [edx + x_head.skb_ptr]
925
 
926
	; reset the RX descriptor
927
 
928
	push	edx
929
	stdcall KernelAlloc, 2000
930
	pop	edx
931
	mov	[edx + x_head.skb_ptr], eax
932
	GetRealAddr
933
	mov	[edx + x_head.buf], eax
934
	mov	[edx + x_head.status], DSC_OWNER_MAC
935
 
936
	; Use next descriptor next time
937
 
938
	inc	[device.cur_rx]
939
	and	[device.cur_rx], RX_RING_SIZE - 1
940
 
941
	; At last, send packet to kernel
942
 
943
	jmp	EthReceiver
944
 
945
  .no_RX:
946
 
947
  .fail:
948
 
949
 
950
	ret
951
 
952
 
953
 
954
 
955
align 4
956
init_mac_regs:
957
 
958
	DEBUGF	1,"initializing MAC regs\n"
959
 
960
	; MAC operation register
961
	mov	ax, 1
962
	set_io	0
963
	set_io	MCR1
964
	out	dx, ax
965
	; Reset MAC
966
	mov	ax, 2
967
	set_io	MAC_SM
968
	out	dx, ax
969
	; Reset internal state machine
970
	xor	ax, ax
971
	out	dx, ax
972
	mov	esi, 5
973
	stdcall Sleep
974
 
975
	call	read_mac
976
 
977
	ret
978
 
979
 
980
 
981
 
982
; Read a word data from PHY Chip
983
 
984
align 4
985
proc  phy_read stdcall, phy_addr:dword, reg:dword
986
 
987
	DEBUGF	1,"PHY read, addr=0x%x reg=0x%x\n", [phy_addr]:8, [reg]:8
988
 
989
	mov	eax, [phy_addr]
990
	shl	eax, 8
991
	add	eax, [reg]
992
	add	eax, MDIO_READ
993
	set_io	0
994
	set_io	MMDIO
995
	out	dx, ax
996
 
997
	;Wait for the read bit to be cleared.
998
	mov	ecx, 2048 ;limit
999
  .read:
1000
	in	ax, dx
1001
	test	ax, MDIO_READ
1002
	jz	@f
1003
	dec	ecx
1004
	jnz	.read
1005
  @@:
1006
 
1007
	set_io	MMRD
1008
	in	ax, dx
1009
	and	eax, 0xFFFF
1010
 
1011
	DEBUGF	1,"PHY read, val=0x%x\n", eax:4
1012
 
1013
	ret
1014
 
1015
endp
1016
 
1017
 
1018
 
1019
 
1020
; Write a word data to PHY Chip
1021
 
1022
align 4
1023
proc  phy_write stdcall, phy_addr:dword, reg:dword, val:dword
1024
 
1025
	DEBUGF	1,"PHY write, addr=0x%x reg=0x%x val=0x%x\n", [phy_addr]:8, [reg]:8, [val]:8
1026
 
1027
	mov	eax, [val]
1028
	set_io	0
1029
	set_io	MMWD
1030
	out	dx, ax
1031
 
1032
	;Write the command to the MDIO bus
1033
 
1034
	mov	eax, [phy_addr]
1035
	shl	eax, 8
1036
	add	eax, [reg]
1037
	add	eax, MDIO_WRITE
1038
	set_io	MMDIO
1039
	out	dx, ax
1040
 
1041
	;Wait for the write bit to be cleared.
1042
	mov	ecx, 2048 ;limit
1043
  .write:
1044
	in	ax, dx
1045
	test	ax, MDIO_WRITE
1046
	jz	@f
1047
	dec	ecx
1048
	jnz	.write
1049
  @@:
1050
 
1051
	DEBUGF	1,"PHY write ok\n"
1052
 
1053
	ret
1054
endp
1055
 
1056
 
1057
 
1058
align 4
1059
read_mac:
1060
 
1061
	DEBUGF	2,"Reading MAC: "
1062
 
1063
	mov	cx, 3
1064
	lea	edi, [device.mac]
1065
	set_io	0
1066
	set_io	MID_0L
1067
     .mac:
1068
	in	ax, dx
1069
	stosw
1070
	inc	dx
1071
	inc	dx
1072
	dec	cx
1073
	jnz	.mac
1074
 
1075
	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
1076
 
1077
	ret
1078
 
1079
 
1080
 
1081
 
1082
; End of code
1083
 
1084
section '.data' data readable writable align 16 ; place all uninitialized data place here
1085
align 4 					; Place all initialised data here
1086
 
1087
devices 	dd 0
1088
version 	dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
1089
my_service	db 'R6040',0			; max 16 chars include zero
1090
 
1091
include_debug_strings				; All data wich FDO uses will be included here
1092
 
1093
device_list	rd MAX_DEVICES			; This list contains all pointers to device structures the driver is handling
1094