Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
866 shurf 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  FORCEDETH.INC                                                  ;;
7
;;                                                                 ;;
8
;;  Ethernet driver for Kolibri OS                                 ;;
9
;;                                                                 ;;
10
;;  Version 0.1  24 June 2008 - 23 Sep 2008                        ;;
11
;;                                                                 ;;
12
;;  Driver for chips of NVIDIA nForce2                             ;;
13
;;  References:                                                    ;;
14
;;    forcedeth.c - linux driver (etherboot project)               ;;
15
;;    ethernet driver template by Mike Hibbett                     ;;
16
;;                                                                 ;;
17
;;  The copyright statement is                                     ;;
18
;;                                                                 ;;
19
;;          GNU GENERAL PUBLIC LICENSE                             ;;
20
;;             Version 2, June 1991                                ;;
21
;;                                                                 ;;
22
;;  Copyright 2008 shurf,                                          ;;
23
;;   cit.utc@gmail.com                                             ;;
24
;;                                                                 ;;
25
;;  See file COPYING for details                                   ;;
26
;;                                                                 ;;
27
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
28
 
29
$Revision: 867 $
30
 
31
;********************************************************************
32
;   Interface
33
;      forcedeth_reset
34
;      forcedeth_probe
35
;      forcedeth_poll
36
;      forcedeth_transmit
37
;      forcedeth_cable
38
;
39
;********************************************************************
40
 
41
;**************************************************************************
42
; forcedeth Register Definitions
43
;**************************************************************************
44
 
45
PCI_REG_COMMAND			equ	0x04	; command register
46
 
47
PCI_COMMAND_IO			equ	0x01	; Enable response in I/O space
48
PCI_COMMAND_MASTER		equ	0x04	; Enable bus mastering
49
PCI_LATENCY_TIMER		equ	0x0d	; 8 bits
50
 
51
PCI_VENDOR_ID			equ	0x00	; 16 bit
52
PCI_REVISION_ID			equ	0x08    ; 8 bits
53
 
54
PCI_BASE_ADDRESS_0		equ	0x10	; 32 bits
55
PCI_BASE_ADDRESS_1		equ	0x14	; 32 bits
56
PCI_BASE_ADDRESS_2		equ	0x18	; 32 bits
57
PCI_BASE_ADDRESS_3		equ	0x1c	; 32 bits
58
PCI_BASE_ADDRESS_4		equ	0x20	; 32 bits
59
PCI_BASE_ADDRESS_5		equ	0x24	; 32 bits
60
 
61
PCI_BASE_ADDRESS_SPACE_IO	equ	0x01
62
PCI_BASE_ADDRESS_IO_MASK	equ	(not 0x03)
63
PCI_BASE_ADDRESS_MEM_MASK	equ	(not 0x0f)
64
 
65
PCI_BASE_ADDRESS_MEM_TYPE_MASK	equ	0x06
66
PCI_BASE_ADDRESS_MEM_TYPE_32	equ	0x00	; 32 bit address
67
PCI_BASE_ADDRESS_MEM_TYPE_1M	equ	0x02	; Below 1M [obsolete]
68
PCI_BASE_ADDRESS_MEM_TYPE_64	equ	0x04	; 64 bit address
69
 
70
; NIC specific static variables go here
71
PCI_DEVICE_ID_NVIDIA_NVENET_1	equ	0x01c3
72
PCI_DEVICE_ID_NVIDIA_NVENET_2	equ	0x0066
73
PCI_DEVICE_ID_NVIDIA_NVENET_4	equ	0x0086
74
PCI_DEVICE_ID_NVIDIA_NVENET_5	equ	0x008c
75
PCI_DEVICE_ID_NVIDIA_NVENET_3	equ	0x00d6
76
PCI_DEVICE_ID_NVIDIA_NVENET_7	equ	0x00df
77
PCI_DEVICE_ID_NVIDIA_NVENET_6	equ	0x00e6
78
PCI_DEVICE_ID_NVIDIA_NVENET_8	equ	0x0056
79
PCI_DEVICE_ID_NVIDIA_NVENET_9	equ	0x0057
80
PCI_DEVICE_ID_NVIDIA_NVENET_10	equ	0x0037
81
PCI_DEVICE_ID_NVIDIA_NVENET_11	equ	0x0038
82
PCI_DEVICE_ID_NVIDIA_NVENET_12	equ	0x0268
83
PCI_DEVICE_ID_NVIDIA_NVENET_13	equ	0x0269
84
PCI_DEVICE_ID_NVIDIA_NVENET_14	equ	0x0372
85
PCI_DEVICE_ID_NVIDIA_NVENET_15	equ	0x0373
86
 
87
ETH_DATA_LEN			equ	1500
88
 
89
; rx/tx mac addr + type + vlan + align + slack
90
RX_NIC_BUFSIZE			equ	(ETH_DATA_LEN + 64)
91
; even more slack
92
RX_ALLOC_BUFSIZE		equ	(ETH_DATA_LEN + 128)
93
 
94
NvRegIrqStatus			equ	0x00
95
NvRegIrqMask			equ	0x04
96
NvRegUnknownSetupReg6		equ	0x08
97
NvRegPollingInterval		equ	0x0c
98
NvRegMacReset			equ	0x3c
99
NvRegMisc1			equ	0x80
100
NvRegTransmitterControl		equ	0x84
101
NvRegTransmitterStatus		equ	0x88
102
NvRegPacketFilterFlags		equ	0x8c
103
NvRegOffloadConfig		equ	0x90
104
NvRegReceiverControl		equ	0x94
105
NvRegReceiverStatus		equ	0x98
106
NvRegRandomSeed			equ	0x9c
107
NvRegUnknownSetupReg1		equ	0xA0
108
NvRegUnknownSetupReg2		equ	0xA4
109
NvRegMacAddrA			equ	0xA8	; MAC address low
110
NvRegMacAddrB			equ	0xAC	; MAC address high
111
NvRegMulticastAddrA		equ	0xB0
112
NvRegMulticastAddrB		equ	0xB4
113
NvRegMulticastMaskA		equ	0xB8
114
NvRegMulticastMaskB		equ	0xBC
115
NvRegPhyInterface		equ	0xC0
116
NvRegTxRingPhysAddr		equ	0x100
117
NvRegRxRingPhysAddr		equ	0x104
118
NvRegRingSizes			equ	0x108
119
NvRegUnknownTransmitterReg	equ	0x10c
120
NvRegLinkSpeed			equ	0x110
121
NvRegUnknownSetupReg5		equ	0x130
122
NvRegUnknownSetupReg3		equ	0x13c
123
NvRegTxRxControl		equ	0x144
124
NvRegMIIStatus			equ	0x180
125
NvRegUnknownSetupReg4		equ	0x184
126
NvRegAdapterControl		equ	0x188
127
NvRegMIISpeed			equ	0x18c
128
NvRegMIIControl			equ	0x190
129
NvRegMIIData			equ	0x194
130
NvRegWakeUpFlags		equ	0x200
131
NvRegPowerState			equ	0x26c
132
NvRegPowerState2		equ	0x600
133
 
134
NVREG_UNKSETUP1_VAL		equ	0x16070f
135
NVREG_UNKSETUP2_VAL		equ	0x16
136
NVREG_UNKSETUP3_VAL1		equ	0x200010
137
NVREG_UNKSETUP4_VAL		equ	8
138
NVREG_UNKSETUP5_BIT31		equ	(1 shl 31)
139
NVREG_UNKSETUP6_VAL		equ	3
140
 
141
NVREG_TXRXCTL_RXCHECK		equ	0x0400
142
NVREG_MIISTAT_ERROR             equ	0x0001
143
NVREG_MIISTAT_MASK		equ	0x000f
144
NVREG_MIISTAT_MASK2		equ	0x000f
145
NVREG_MIICTL_INUSE		equ	0x08000
146
NVREG_MIICTL_WRITE		equ	0x00400
147
NVREG_MIICTL_ADDRSHIFT		equ	5
148
 
149
NVREG_MIISPEED_BIT8		equ	(1 shl 8)
150
NVREG_MIIDELAY			equ	5
151
 
152
NVREG_IRQ_RX_ERROR		equ	0x0001
153
NVREG_IRQ_RX			equ	0x0002
154
NVREG_IRQ_RX_NOBUF		equ	0x0004
155
NVREG_IRQ_LINK			equ	0x0040
156
NVREG_IRQ_TIMER			equ	0x0020
157
NVREG_IRQMASK_WANTED_2		equ	0x0147
158
 
159
NVREG_IRQ_RX_ALL		equ	(NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF)
160
NVREG_IRQ_TX_ALL		equ	0	; ???????????
161
NVREG_IRQ_OTHER_ALL		equ	(NVREG_IRQ_LINK or NVREG_IRQ_TIMER)
162
 
163
NVREG_IRQSTAT_MASK		equ	0x1ff
164
 
165
NVREG_TXRXCTL_KICK		equ	0x0001
166
NVREG_TXRXCTL_BIT1		equ	0x0002
167
NVREG_TXRXCTL_BIT2		equ	0x0004
168
NVREG_TXRXCTL_IDLE		equ	0x0008
169
NVREG_TXRXCTL_RESET		equ	0x0010
170
NVREG_TXRXCTL_RXCHECK		equ	0x0400
171
 
172
NVREG_MCASTADDRA_FORCE		equ	0x01
173
 
174
NVREG_MAC_RESET_ASSERT		equ	0x0F3
175
 
176
NVREG_MISC1_HD			equ	0x02
177
NVREG_MISC1_FORCE		equ	0x3b0f3c
178
 
179
NVREG_PFF_ALWAYS		equ	0x7F0008
180
NVREG_PFF_PROMISC		equ	0x80
181
NVREG_PFF_MYADDR		equ	0x20
182
 
183
NVREG_OFFLOAD_HOMEPHY		equ	0x601
184
NVREG_OFFLOAD_NORMAL		equ	RX_NIC_BUFSIZE
185
 
186
NVREG_RNDSEED_MASK		equ	0x00ff
187
NVREG_RNDSEED_FORCE		equ	0x7f00
188
NVREG_RNDSEED_FORCE2		equ	0x2d00
189
NVREG_RNDSEED_FORCE3		equ	0x7400
190
 
191
; NVREG_POLL_DEFAULT is the interval length of the timer source on the nic
192
; NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms
193
NVREG_POLL_DEFAULT		equ	970
194
 
195
NVREG_ADAPTCTL_START		equ	0x02
196
NVREG_ADAPTCTL_LINKUP		equ	0x04
197
NVREG_ADAPTCTL_PHYVALID		equ	0x40000
198
NVREG_ADAPTCTL_RUNNING		equ	0x100000
199
NVREG_ADAPTCTL_PHYSHIFT		equ	24
200
 
201
NVREG_WAKEUPFLAGS_VAL		equ	0x7770
202
 
203
NVREG_POWERSTATE_POWEREDUP	equ	0x8000
204
NVREG_POWERSTATE_VALID		equ	0x0100
205
NVREG_POWERSTATE_MASK		equ	0x0003
206
NVREG_POWERSTATE_D0		equ	0x0000
207
NVREG_POWERSTATE_D1		equ	0x0001
208
NVREG_POWERSTATE_D2		equ	0x0002
209
NVREG_POWERSTATE_D3		equ	0x0003
210
 
211
NVREG_POWERSTATE2_POWERUP_MASK	equ	0x0F11
212
NVREG_POWERSTATE2_POWERUP_REV_A3 equ	0x0001
213
 
214
NVREG_RCVCTL_START		equ	0x01
215
NVREG_RCVSTAT_BUSY		equ	0x01
216
 
217
NVREG_XMITCTL_START		equ	0x01
218
 
219
NVREG_LINKSPEED_FORCE		equ	0x10000
220
NVREG_LINKSPEED_10		equ	1000
221
NVREG_LINKSPEED_100		equ	100
222
NVREG_LINKSPEED_1000		equ	50
223
 
224
NVREG_RINGSZ_TXSHIFT		equ	0
225
NVREG_RINGSZ_RXSHIFT		equ	16
226
 
227
LPA_1000FULL			equ	0x0800
228
 
229
; Link partner ability register.
230
LPA_SLCT			equ	0x001f  ; Same as advertise selector
231
LPA_10HALF			equ	0x0020  ; Can do 10mbps half-duplex
232
LPA_10FULL			equ	0x0040  ; Can do 10mbps full-duplex
233
LPA_100HALF			equ	0x0080  ; Can do 100mbps half-duplex
234
LPA_100FULL			equ	0x0100  ; Can do 100mbps full-duplex
235
LPA_100BASE4			equ	0x0200  ; Can do 100mbps 4k packets
236
LPA_RESV			equ	0x1c00  ; Unused...
237
LPA_RFAULT			equ	0x2000  ; Link partner faulted
238
LPA_LPACK			equ	0x4000  ; Link partner acked us
239
LPA_NPAGE			equ	0x8000  ; Next page bit
240
 
241
MII_READ			equ	(-1)
242
MII_PHYSID1			equ	0x02	; PHYS ID 1
243
MII_PHYSID2			equ	0x03	; PHYS ID 2
244
MII_BMCR			equ	0x00	; Basic mode control register
245
MII_BMSR			equ	0x01	; Basic mode status register
246
MII_ADVERTISE			equ	0x04	; Advertisement control reg
247
MII_LPA				equ	0x05	; Link partner ability reg
248
MII_SREVISION			equ	0x16	; Silicon revision
249
MII_RESV1			equ	0x17	; Reserved...
250
MII_NCONFIG			equ	0x1c	; Network interface config
251
 
252
; PHY defines
253
PHY_OUI_MARVELL			equ	0x5043
254
PHY_OUI_CICADA			equ	0x03f1
255
PHYID1_OUI_MASK			equ	0x03ff
256
PHYID1_OUI_SHFT			equ	6
257
PHYID2_OUI_MASK			equ	0xfc00
258
PHYID2_OUI_SHFT			equ	10
259
PHY_INIT1			equ	0x0f000
260
PHY_INIT2			equ	0x0e00
261
PHY_INIT3			equ	0x01000
262
PHY_INIT4			equ	0x0200
263
PHY_INIT5			equ	0x0004
264
PHY_INIT6			equ	0x02000
265
PHY_GIGABIT			equ	0x0100
266
 
267
PHY_TIMEOUT			equ	0x1
268
PHY_ERROR			equ	0x2
269
 
270
PHY_100				equ	0x1
271
PHY_1000			equ	0x2
272
PHY_HALF			equ	0x100
273
 
274
PHY_RGMII			equ	0x10000000
275
 
276
; desc_ver values:
277
; This field has two purposes:
278
; - Newer nics uses a different ring layout. The layout is selected by
279
;   comparing np->desc_ver with DESC_VER_xy.
280
; - It contains bits that are forced on when writing to NvRegTxRxControl.
281
DESC_VER_1			equ	0x0
282
DESC_VER_2			equ	(0x02100 or NVREG_TXRXCTL_RXCHECK)
283
 
284
MAC_ADDR_LEN			equ	6
285
 
286
NV_TX_LASTPACKET		equ	(1 shl 16)
287
NV_TX_RETRYERROR		equ	(1 shl 19)
288
NV_TX_LASTPACKET1		equ	(1 shl 24)
289
NV_TX_DEFERRED			equ	(1 shl 26)
290
NV_TX_CARRIERLOST		equ	(1 shl 27)
291
NV_TX_LATECOLLISION		equ	(1 shl 28)
292
NV_TX_UNDERFLOW			equ	(1 shl 29)
293
NV_TX_ERROR			equ	(1 shl 30)
294
NV_TX_VALID			equ	(1 shl 31)
295
 
296
NV_TX2_LASTPACKET		equ	(1 shl 29)
297
NV_TX2_RETRYERROR		equ	(1 shl 18)
298
NV_TX2_LASTPACKET1		equ	(1 shl 23)
299
NV_TX2_DEFERRED			equ	(1 shl 25)
300
NV_TX2_CARRIERLOST		equ	(1 shl 26)
301
NV_TX2_LATECOLLISION		equ	(1 shl 27)
302
NV_TX2_UNDERFLOW		equ	(1 shl 28)
303
; error and valid are the same for both
304
NV_TX2_ERROR			equ	(1 shl 30)
305
NV_TX2_VALID			equ	(1 shl 31)
306
 
307
NV_RX_DESCRIPTORVALID		equ	(1 shl 16)
308
NV_RX_AVAIL			equ	(1 shl 31)
309
 
310
NV_RX2_DESCRIPTORVALID		equ	(1 shl 29)
311
 
312
RX_RING				equ	4
313
TX_RING				equ	2
314
 
315
FLAG_MASK_V1			equ	0xffff0000
316
FLAG_MASK_V2			equ	0xffffc000
317
LEN_MASK_V1			equ	(0xffffffff xor FLAG_MASK_V1)
318
LEN_MASK_V2			equ	(0xffffffff xor FLAG_MASK_V2)
319
 
320
; Miscelaneous hardware related defines:
321
NV_PCI_REGSZ_VER1		equ	0x270
322
NV_PCI_REGSZ_VER2		equ	0x604
323
; various timeout delays: all in usec
324
NV_TXRX_RESET_DELAY		equ	4
325
NV_TXSTOP_DELAY1		equ	10
326
NV_TXSTOP_DELAY1MAX		equ	500000
327
NV_TXSTOP_DELAY2		equ	100
328
NV_RXSTOP_DELAY1		equ	10
329
NV_RXSTOP_DELAY1MAX		equ	500000
330
NV_RXSTOP_DELAY2		equ	100
331
NV_SETUP5_DELAY			equ	5
332
NV_SETUP5_DELAYMAX		equ	50000
333
NV_POWERUP_DELAY		equ	5
334
NV_POWERUP_DELAYMAX		equ	5000
335
NV_MIIBUSY_DELAY		equ	50
336
NV_MIIPHY_DELAY			equ	10
337
NV_MIIPHY_DELAYMAX		equ	10000
338
NV_MAC_RESET_DELAY		equ	64
339
NV_WAKEUPPATTERNS		equ	5
340
NV_WAKEUPMASKENTRIES		equ	4
341
 
342
; Advertisement control register.
343
ADVERTISE_SLCT			equ	0x001f	; Selector bits
344
ADVERTISE_CSMA			equ	0x0001	; Only selector supported
345
ADVERTISE_10HALF		equ	0x0020	; Try for 10mbps half-duplex
346
ADVERTISE_10FULL		equ	0x0040	; Try for 10mbps full-duplex
347
ADVERTISE_100HALF		equ	0x0080	; Try for 100mbps half-duplex
348
ADVERTISE_100FULL		equ	0x0100	; Try for 100mbps full-duplex
349
ADVERTISE_100BASE4		equ	0x0200	; Try for 100mbps 4k packets
350
ADVERTISE_RESV			equ	0x1c00	; Unused...
351
ADVERTISE_RFAULT		equ	0x2000	; Say we can detect faults
352
ADVERTISE_LPACK			equ	0x4000	; Ack link partners response
353
ADVERTISE_NPAGE			equ	0x8000	; Next page bit
354
 
355
ADVERTISE_FULL			equ	(ADVERTISE_100FULL or ADVERTISE_10FULL or ADVERTISE_CSMA)
356
ADVERTISE_ALL			equ	(ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL)
357
 
358
MII_1000BT_CR			equ	0x09
359
MII_1000BT_SR			equ	0x0a
360
ADVERTISE_1000FULL		equ	0x0200
361
ADVERTISE_1000HALF		equ	0x0100
362
 
363
BMCR_ANRESTART			equ	0x0200	; Auto negotiation restart
364
BMCR_ANENABLE			equ	0x1000	; Enable auto negotiation
365
BMCR_SPEED100			equ	0x2000	; Select 100Mbps
366
BMCR_LOOPBACK			equ	0x4000	; TXD loopback bits
367
BMCR_RESET			equ	0x8000	; Reset the DP83840
368
 
369
; Basic mode status register.
370
BMSR_ERCAP			equ	0x0001  ; Ext-reg capability
371
BMSR_JCD			equ	0x0002  ; Jabber detected
372
BMSR_LSTATUS			equ	0x0004  ; Link status
373
BMSR_ANEGCAPABLE		equ	0x0008  ; Able to do auto-negotiation
374
BMSR_RFAULT			equ	0x0010  ; Remote fault detected
375
BMSR_ANEGCOMPLETE		equ	0x0020  ; Auto-negotiation complete
376
BMSR_RESV			equ	0x07c0  ; Unused...
377
BMSR_10HALF			equ	0x0800  ; Can do 10mbps, half-duplex
378
BMSR_10FULL			equ	0x1000  ; Can do 10mbps, full-duplex
379
BMSR_100HALF			equ	0x2000  ; Can do 100mbps, half-duplex
380
BMSR_100FULL			equ	0x4000  ; Can do 100mbps, full-duplex
381
BMSR_100BASE4			equ	0x8000  ; Can do 100mbps, 4k packets
382
 
383
ETH_ALEN			equ	6
384
ETH_HLEN			equ	(2 * ETH_ALEN + 2)
385
ETH_ZLEN			equ	60	; 60 + 4bytes auto payload for
386
						; mininmum 64bytes frame length
387
 
388
uglobal
389
forcedeth_mmio_addr	dd 0	; memory map physical address
390
forcedeth_mmio_size	dd 0	; size of memory bar
391
forcedeth_vendor_id	dw 0	; Vendor ID
392
forcedeth_device_id	dw 0	; Device ID
393
forcedeth_orig_mac0	dd 0	; MAC
394
forcedeth_orig_mac1	dd 0	; MAC
395
forcedeth_mapio_addr	dd 0	; mapped IO address
396
forcedeth_txflags	dd 0	;
397
forcedeth_desc_ver	dd 0	;
398
forcedeth_irqmask	dd 0	; IRQ-mask
399
forcedeth_wolenabled	dd 0	; WOL
400
forcedeth_in_shutdown	dd 0	;
401
forcedeth_cur_rx	dd 0	;
402
forcedeth_refill_rx	dd 0	;
403
forcedeth_phyaddr	dd 0	;
404
forcedeth_phy_oui	dd 0	;
405
forcedeth_gigabit	dd 0	;
406
forcedeth_needs_mac_reset dd 0	;
407
forcedeth_linkspeed	dd 0	;
408
forcedeth_duplex	dd 0	;
409
forcedeth_next_tx	dd 0	; next TX descriptor number
410
forcedeth_nic_tx	dd 0	; ??? d'nt used ???
411
forcedeth_packetlen	dd 0	;
412
forcedeth_nocable	dd 0	; no cable present
413
endg
414
 
415
struc	forcedeth_TxDesc {
416
	.PacketBuffer	dd ?
417
	.FlagLen	dd ?
418
}
419
virtual	at 0
420
	forcedeth_TxDesc forcedeth_TxDesc
421
	sizeof.forcedeth_TxDesc = $ - forcedeth_TxDesc
422
end virtual
423
 
424
struc	forcedeth_RxDesc {
425
	.PacketBuffer	dd ?
426
	.FlagLen	dd ?
427
}
428
virtual	at 0
429
	forcedeth_RxDesc forcedeth_RxDesc
430
	sizeof.forcedeth_RxDesc = $ - forcedeth_RxDesc
431
end virtual
432
 
433
virtual at eth_data_start
434
	; Define the TX Descriptor
435
	align	256
436
	forcedeth_tx_ring	rb	TX_RING * sizeof.forcedeth_TxDesc
437
	; Create a static buffer of size RX_BUF_SZ for each
438
	; TX Descriptor.  All descriptors point to a
439
	; part of this buffer
440
	align	256
441
	forcedeth_txb	rb	TX_RING * RX_NIC_BUFSIZE
442
 
443
	; Define the RX Descriptor
444
	align	256
445
	forcedeth_rx_ring	rb	RX_RING * sizeof.forcedeth_RxDesc
446
	; Create a static buffer of size RX_BUF_SZ for each
447
	; RX Descriptor.  All descriptors point to a
448
	; part of this buffer
449
	align	256
450
	forcedeth_rxb	rb	RX_RING * RX_NIC_BUFSIZE
451
end virtual
452
 
453
 
454
;***************************************************************************
455
;   Function
456
;      forcedeth_reset
457
;   Description
458
;      Place the chip (ie, the ethernet card) into a virgin state
459
;      No inputs
460
;      All registers destroyed
461
;
462
;***************************************************************************
463
forcedeth_reset:
464
 
465
	; 1) erase previous misconfiguration
466
	; 4.1-1: stop adapter: ignored, 4.3 seems to be overkill
467
 
468
	; writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA)
469
	mov	edi, dword [forcedeth_mapio_addr]
470
	mov	dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE
471
 
472
	; writel(0, base + NvRegMulticastAddrB)
473
	mov	dword [edi+NvRegMulticastAddrB], 0
474
 
475
	; writel(0, base + NvRegMulticastMaskA)
476
	mov	dword [edi+NvRegMulticastMaskA], 0
477
 
478
	; writel(0, base + NvRegMulticastMaskB)
479
	mov	dword [edi+NvRegMulticastMaskB], 0
480
 
481
	; writel(0, base + NvRegPacketFilterFlags)
482
	mov	dword [edi+NvRegPacketFilterFlags], 0
483
 
484
	; writel(0, base + NvRegTransmitterControl)
485
	mov	dword [edi+NvRegTransmitterControl], 0
486
 
487
	; writel(0, base + NvRegReceiverControl)
488
	mov	dword [edi+NvRegReceiverControl], 0
489
 
490
	; writel(0, base + NvRegAdapterControl)
491
	mov	dword [edi+NvRegAdapterControl], 0
492
 
493
 
494
	; 2) initialize descriptor rings
495
	; init_ring(nic)
496
	call	forcedeth_init_ring
497
 
498
	; writel(0, base + NvRegLinkSpeed)
499
	mov	dword [edi+NvRegLinkSpeed], 0
500
 
501
	; writel(0, base + NvRegUnknownTransmitterReg)
502
	mov	dword [edi+NvRegUnknownTransmitterReg], 0
503
 
504
	; txrx_reset(nic)
505
	call	forcedeth_txrx_reset
506
 
507
	; writel(0, base + NvRegUnknownSetupReg6)
508
	mov	dword [edi+NvRegUnknownSetupReg6], 0
509
 
510
	; np->in_shutdown = 0
511
	mov	dword [forcedeth_in_shutdown], 0
512
 
513
 
514
	; 3) set mac address
515
	; writel(mac[0], base + NvRegMacAddrA)
516
	mov	eax, dword [forcedeth_orig_mac0]
517
	mov	dword [edi+NvRegMacAddrA], eax
518
 
519
	; writel(mac[1], base + NvRegMacAddrB)
520
	mov	eax, dword [forcedeth_orig_mac1]
521
	mov	dword [edi+NvRegMacAddrB], eax
522
 
523
 
524
	; 4) give hw rings
525
	; writel((u32) virt_to_le32desc(&rx_ring[0]), base + NvRegRxRingPhysAddr)
526
	mov	eax, forcedeth_rx_ring
527
 
528
;DEBUGF 1," K : FORCEDETH: rx_ring at 0x%x\n", eax
529
 
530
	sub	eax, OS_BASE	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
531
	mov	dword [edi+NvRegRxRingPhysAddr], eax
532
 
533
	; writel((u32) virt_to_le32desc(&tx_ring[0]), base + NvRegTxRingPhysAddr)
534
	mov	eax, forcedeth_tx_ring
535
	sub	eax, OS_BASE	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
536
	mov	dword [edi+NvRegTxRingPhysAddr], eax
537
 
538
	; writel(((RX_RING - 1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING - 1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes)
539
	mov	dword [edi+NvRegRingSizes], (((RX_RING - 1) shl NVREG_RINGSZ_RXSHIFT) + ((TX_RING - 1) shl NVREG_RINGSZ_TXSHIFT))
540
 
541
	; 5) continue setup
542
	; np->linkspeed = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
543
	mov	dword [forcedeth_linkspeed], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
544
 
545
	; np->duplex = 0
546
	mov	dword [forcedeth_duplex], 0
547
 
548
	; writel(np->linkspeed, base + NvRegLinkSpeed)
549
	mov	dword [edi+NvRegLinkSpeed], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
550
 
551
	; writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3)
552
	mov	dword [edi+NvRegUnknownSetupReg3], NVREG_UNKSETUP3_VAL1
553
 
554
	; writel(np->desc_ver, base + NvRegTxRxControl)
555
	mov	eax, dword [forcedeth_desc_ver]
556
	mov	dword [edi+NvRegTxRxControl], eax
557
 
558
	; pci_push(base)
559
	call	forcedeth_pci_push
560
 
561
	; writel(NVREG_TXRXCTL_BIT1 | np->desc_ver, base + NvRegTxRxControl)
562
	or	eax, NVREG_TXRXCTL_BIT1
563
	mov	dword [edi+NvRegTxRxControl], eax
564
 
565
	; reg_delay(NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, "open: SetupReg5, Bit 31 remained off\n")
566
	push	ebx edx edi	;;;;;;;;;;;;;;;;;;;;;;
567
	stdcall forcedeth_reg_delay,NvRegUnknownSetupReg5,NVREG_UNKSETUP5_BIT31,NVREG_UNKSETUP5_BIT31,NV_SETUP5_DELAY,NV_SETUP5_DELAYMAX,0
568
	pop	edi edx ebx	;;;;;;;;;;;;;;;;;;;;;;
569
 
570
	; writel(0, base + NvRegUnknownSetupReg4)
571
	mov	dword [edi+NvRegUnknownSetupReg4], 0
572
 
573
	; writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus)
574
	mov	dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK2
575
 
576
 
577
	; printf("%d-Mbs Link, %s-Duplex\n", np->linkspeed & NVREG_LINKSPEED_10 ? 10 : 100, np->duplex ? "Full" : "Half")
578
;;;;;;;;;;; DEBUGF
579
 
580
	; 6) continue setup
581
 
582
	; writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1)
583
	mov	dword [edi+NvRegMisc1], (NVREG_MISC1_FORCE or NVREG_MISC1_HD)
584
 
585
	; writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus)
586
	mov	eax, dword [edi+NvRegTransmitterStatus]
587
	mov	dword [edi+NvRegTransmitterStatus], eax
588
 
589
	; writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags)
590
	mov	dword [edi+NvRegPacketFilterFlags], NVREG_PFF_ALWAYS
591
 
592
	; writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig)
593
	mov	dword [edi+NvRegOffloadConfig], NVREG_OFFLOAD_NORMAL
594
 
595
	; writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus)
596
	mov	eax, dword [edi+NvRegReceiverStatus]
597
	mov	dword [edi+NvRegReceiverStatus], eax
598
 
599
	; Get a random number
600
	; i = random()
601
	push	edi
602
	stdcall	sys_clock	; eax = 0x00SSMMHH (current system time)
603
	pop	edi
604
 
605
	; writel(NVREG_RNDSEED_FORCE | (i & NVREG_RNDSEED_MASK), base + NvRegRandomSeed)
606
	and	eax, NVREG_RNDSEED_MASK
607
	or	eax, NVREG_RNDSEED_FORCE
608
	mov	dword [edi+NvRegRandomSeed], eax
609
 
610
	; writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1)
611
	mov	dword [edi+NvRegUnknownSetupReg1], NVREG_UNKSETUP1_VAL
612
 
613
	; writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2)
614
	mov	dword [edi+NvRegUnknownSetupReg2], NVREG_UNKSETUP2_VAL
615
 
616
	; writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval)
617
	mov	dword [edi+NvRegPollingInterval], NVREG_POLL_DEFAULT
618
 
619
	; writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6)
620
	mov	dword [edi+NvRegUnknownSetupReg6], NVREG_UNKSETUP6_VAL
621
 
622
	; writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT) | NVREG_ADAPTCTL_PHYVALID | NVREG_ADAPTCTL_RUNNING,
623
	; base + NvRegAdapterControl)
624
	mov	eax, dword [forcedeth_phyaddr]
625
	shl	eax, NVREG_ADAPTCTL_PHYSHIFT
626
	or	eax, (NVREG_ADAPTCTL_PHYVALID or NVREG_ADAPTCTL_RUNNING)
627
	mov	dword [edi+NvRegAdapterControl], eax
628
 
629
	; writel(NVREG_MIISPEED_BIT8 | NVREG_MIIDELAY, base + NvRegMIISpeed)
630
	mov	dword [edi+NvRegMIISpeed], (NVREG_MIISPEED_BIT8 or NVREG_MIIDELAY)
631
 
632
	; writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4)
633
	mov	dword [edi+NvRegUnknownSetupReg4], NVREG_UNKSETUP4_VAL
634
 
635
	; writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags)
636
	mov	dword [edi+NvRegWakeUpFlags], NVREG_WAKEUPFLAGS_VAL
637
 
638
	; i = readl(base + NvRegPowerState)
639
	mov	eax, dword [edi+NvRegPowerState]
640
 
641
	; if ((i & NVREG_POWERSTATE_POWEREDUP) == 0)
642
	test	eax, NVREG_POWERSTATE_POWEREDUP
643
	jnz	@f
644
	; writel(NVREG_POWERSTATE_POWEREDUP | i, base + NvRegPowerState)
645
	or	eax, NVREG_POWERSTATE_POWEREDUP
646
	mov	dword [edi+NvRegPowerState], eax
647
 
648
@@:
649
 
650
	; pci_push(base)
651
	call	forcedeth_pci_push
652
 
653
	; nv_udelay(10)
654
	mov	esi, 10
655
	call	forcedeth_nv_udelay
656
 
657
	; writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState)
658
	mov	eax, dword [edi+NvRegPowerState]
659
	or	eax, NVREG_POWERSTATE_VALID
660
	mov	dword [edi+NvRegPowerState], eax
661
 
662
	; ??? disable all interrupts ???
663
	; writel(0, base + NvRegIrqMask)
664
	mov	dword [edi+NvRegIrqMask], 0
665
 
666
;;;	; ??? Mask RX interrupts
667
;;;	mov	dword [edi+NvRegIrqMask], NVREG_IRQ_RX_ALL
668
;;;	; ??? Mask TX interrupts
669
;;;	;mov	dword [edi+NvRegIrqMask], NVREG_IRQ_TX_ALL
670
;;;	; ??? Mask OTHER interrupts
671
;;;	mov	dword [edi+NvRegIrqMask], NVREG_IRQ_OTHER_ALL
672
 
673
	; pci_push(base)
674
	call	forcedeth_pci_push
675
 
676
	; writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus)
677
	mov	dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK2
678
 
679
	; writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus)
680
	mov	dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK
681
 
682
	; pci_push(base)
683
	call	forcedeth_pci_push
684
 
685
 
686
	; writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA)
687
	mov	dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE
688
 
689
	; writel(0, base + NvRegMulticastAddrB)
690
	mov	dword [edi+NvRegMulticastAddrB], 0
691
 
692
	; writel(0, base + NvRegMulticastMaskA)
693
	mov	dword [edi+NvRegMulticastMaskA], 0
694
 
695
	; writel(0, base + NvRegMulticastMaskB)
696
	mov	dword [edi+NvRegMulticastMaskB], 0
697
 
698
	; writel(NVREG_PFF_ALWAYS | NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags)
699
	mov	dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_ALWAYS or NVREG_PFF_MYADDR)
700
 
701
	; set_multicast(nic)
702
	call	forcedeth_set_multicast
703
 
704
	; One manual link speed update: Interrupts are enabled, future link
705
	; speed changes cause interrupts and are handled by nv_link_irq().
706
 
707
	; miistat = readl(base + NvRegMIIStatus)
708
	mov	eax, dword [edi+NvRegMIIStatus]
709
 
710
	; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
711
	mov	dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK
712
 
713
	; dprintf(("startup: got 0x%hX.\n", miistat));
714
;;;	DEBUGF 1," K : FORCEDETH: startup: got 0x%x\n", eax
715
 
716
 
717
	; ret = update_linkspeed(nic)
718
	call	forcedeth_update_linkspeed
719
	push	eax
720
 
721
	; start_tx(nic)
722
	call	forcedeth_start_tx
723
 
724
	pop	eax
725
 
726
;        if (ret) {
727
;                //Start Connection netif_carrier_on(dev);
728
;        } else {
729
;                printf("no link during initialization.\n");
730
;        }
731
 
732
	;*** added by shurf (21.09.2008)
733
	mov	dword [forcedeth_nocable], 0
734
	;***
735
 
736
	test	eax, eax
737
	jnz	.return
738
	DEBUGF 1," K : FORCEDETH: no link during initialization.\n"
739
 
740
	;*** added by shurf (21.09.2008)
741
	mov	dword [forcedeth_nocable], 1
742
	;***
743
 
744
.return:
745
 
746
; Indicate that we have successfully reset the card
747
        mov     eax, dword [pci_data]
748
        mov     dword [eth_status], eax
749
	ret
750
 
751
 
752
 
753
;***************************************************************************
754
;   Function
755
;      forcedeth_probe
756
;   Description
757
;      Searches for an ethernet card, enables it and clears the rx buffer
758
;      If a card was found, it enables the ethernet -> TCPIP link
759
;
760
;***************************************************************************
761
forcedeth_probe:
762
 
763
;	DEBUGF 1," K : FORCEDETH: 0x%x 0x%x, 0x%x\n", [io_addr]:8,[pci_bus]:2,[pci_dev]:2
764
 
765
	mov	dword [forcedeth_needs_mac_reset], 0
766
 
767
; BEGIN of adjust_pci_device()
768
	; read word from PCI-device
769
	mov 	al, 1	;;;;;;;;;;;;;;2
770
	mov	bh, [pci_dev]
771
	mov	ah, [pci_bus]
772
	mov	bl, PCI_REG_COMMAND
773
	call	pci_read_reg
774
	mov	bx, ax			; new command
775
	or	bx, PCI_COMMAND_MASTER
776
	or	bx, PCI_COMMAND_IO
777
	cmp	bx, ax
778
	je	@f
779
	; Enabling PCI-device (make card as bus master)
780
	DEBUGF 1," K : FORCEDETH: Updating PCI command 0x%x->0x%x\n", ax, bx
781
	mov	cx, bx
782
	mov	al, 1	;;;;;;;;;;;;2
783
	mov	bh, [pci_dev]
784
	mov	ah, [pci_bus]
785
	mov	bl, PCI_REG_COMMAND
786
	call	pci_write_reg
787
 
788
	; Check latency settings
789
@@:
790
	; Get current latency settings from Latency timer register (byte)
791
	mov	al, 0	;;;;;;;;;1
792
	mov	bh, [pci_dev]
793
	mov	ah, [pci_bus]
794
	mov	bl, PCI_LATENCY_TIMER
795
	call	pci_read_reg
796
 
797
	; see if its at least 32
798
	cmp	al, 32
799
	jge	@f
800
	; set latency to 32
801
        DEBUGF 1, "K : FORCEDETH: PCI latency timer (CFLT) is unreasonably low at %d.\n", al
802
        DEBUGF 1, "K : FORCEDETH: Setting to 32 clocks.\n"
803
	mov	cl, 32
804
	mov	al, 0	;;;;;;;1
805
	mov	bh, [pci_dev]
806
	mov	ah, [pci_bus]
807
	mov	bl, PCI_LATENCY_TIMER
808
	call	pci_write_reg
809
; END of adjust_pci_device()
810
 
811
@@:
812
; BEGIN of pci_bar_start (addr = pci_bar_start(pci, PCI_BASE_ADDRESS_0))
813
	mov	al, 2	; dword
814
	mov	bh, [pci_dev]
815
	mov	ah, [pci_bus]
816
	mov	bl, PCI_BASE_ADDRESS_0
817
	call	pci_read_reg
818
	test	eax, PCI_BASE_ADDRESS_SPACE_IO
819
	jz	@f
820
	and	eax, PCI_BASE_ADDRESS_IO_MASK
821
	jmp	.next
822
@@:	push	eax
823
	and	eax, PCI_BASE_ADDRESS_MEM_TYPE_MASK
824
	cmp	eax, PCI_BASE_ADDRESS_MEM_TYPE_64
825
	jne	.not64
826
	mov	al, 2	; dword
827
	mov	bh, [pci_dev]
828
	mov	ah, [pci_bus]
829
	mov	bl, PCI_BASE_ADDRESS_0 + 4
830
	call	pci_read_reg
831
	or	eax, eax
832
	jz	.not64
833
	DEBUGF  1,"K : FORCEDETH: pci_bar_start: Unhandled 64bit BAR\n"
834
	or	eax, -1
835
	jmp	.next
836
.not64:
837
	pop	eax
838
	and	eax, PCI_BASE_ADDRESS_MEM_MASK
839
.next:
840
; END of pci_bar_start
841
; addr = eax
842
	mov	dword [forcedeth_mmio_addr], eax
843
 
844
 
845
; BEGIN of pci_bar_size (sz = pci_bar_size(pci, PCI_BASE_ADDRESS_0))
846
 
847
	; Save original bar
848
	mov	al, 2	; dword
849
	mov	bh, [pci_dev]
850
	mov	ah, [pci_bus]
851
	mov	bl, PCI_BASE_ADDRESS_0
852
	call	pci_read_reg
853
	mov	dword [forcedeth_tmp_start], eax
854
	; Compute which bits can be set
855
	; (ecx - value to write)
856
	mov	al, 2	; dword
857
	mov	bh, [pci_dev]
858
	mov	ah, [pci_bus]
859
	mov	bl, PCI_BASE_ADDRESS_0
860
	mov	ecx, (not 0)
861
	call	pci_write_reg
862
	mov	al, 2	; dword
863
	mov	bh, [pci_dev]
864
	mov	ah, [pci_bus]
865
	mov	bl, PCI_BASE_ADDRESS_0
866
	call	pci_read_reg
867
	push	eax
868
	; Restore the original size
869
	mov	al, 2	; dword
870
	mov	bh, [pci_dev]
871
	mov	ah, [pci_bus]
872
	mov	bl, PCI_BASE_ADDRESS_0
873
	mov	ecx, dword [forcedeth_tmp_start]
874
	call	pci_write_reg
875
	; Find the significant bits
876
	pop	eax
877
	test	dword [forcedeth_tmp_start], PCI_BASE_ADDRESS_SPACE_IO
878
	jz	@f
879
	and	eax, PCI_BASE_ADDRESS_IO_MASK
880
	jmp	.next2
881
@@:	and	eax, PCI_BASE_ADDRESS_MEM_MASK
882
.next2:
883
	; Find the lowest bit set
884
	mov	ecx, eax
885
	sub	eax, 1
886
	not	eax
887
	and	ecx, eax
888
 
889
; END of pci_bar_start
890
	mov	dword [forcedeth_mmio_size], ecx
891
 
892
	DEBUGF 1," K : FORCEDETH: mmio_addr= 0x%x [mmio_size= 0x%x]\n", [forcedeth_mmio_addr]:8, [forcedeth_mmio_size]:8
893
 
894
	; Get Vendor and Device ID
895
	mov 	al, 2
896
	mov	bh, [pci_dev]
897
	mov	ah, [pci_bus]
898
	mov	bl, PCI_VENDOR_ID
899
	call	pci_read_reg
900
	mov	word [forcedeth_vendor_id], ax
901
	shr	eax, 16
902
	mov	word [forcedeth_device_id], ax
903
 
904
	DEBUGF 1," K : FORCEDETH: vendor_id= 0x%x device_id= 0x%x\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4
905
 
906
	; handle different descriptor versions
907
	mov	eax, dword [forcedeth_device_id]
908
	cmp	eax, PCI_DEVICE_ID_NVIDIA_NVENET_1
909
	je	.ver1
910
	cmp	eax, PCI_DEVICE_ID_NVIDIA_NVENET_2
911
	je	.ver1
912
	cmp	eax, PCI_DEVICE_ID_NVIDIA_NVENET_3
913
	je	.ver1
914
	mov	dword [forcedeth_desc_ver], DESC_VER_2
915
	jmp	@f
916
.ver1:	mov	dword [forcedeth_desc_ver], DESC_VER_1
917
@@:
918
	; read the mac address
919
	; map memory
920
	stdcall map_io_mem, [forcedeth_mmio_addr], [forcedeth_mmio_size], (PG_SW+PG_NOCACHE)
921
	test eax, eax
922
	jz .fail
923
 
924
	mov	dword [forcedeth_mapio_addr], eax
925
	mov	edi, eax
926
	mov	eax, dword [edi+NvRegMacAddrA]
927
	mov	dword [forcedeth_orig_mac0], eax
928
	mov	eax, dword [edi+NvRegMacAddrB]
929
	mov	dword [forcedeth_orig_mac1], eax
930
 
931
	; save MAC-address to global variable node_addr
932
	mov	ecx, MAC_ADDR_LEN
933
	xor	ebx, ebx
934
	mov	edx, forcedeth_orig_mac0
935
	add	edx, (MAC_ADDR_LEN-1)
936
@@:	mov	al, byte [edx]
937
	mov	byte [node_addr+ebx], al
938
	inc	ebx
939
	dec	edx
940
	loop	@b
941
 
942
;	DEBUGF 1," K : FORCEDETH: orig_mac0= 0x%x\n", [forcedeth_orig_mac0]:8
943
;	DEBUGF 1," K : FORCEDETH: orig_mac1= 0x%x\n", [forcedeth_orig_mac1]:8
944
	DEBUGF 1," K : FORCEDETH: MAC = %x-%x-%x-%x-%x-%x\n", [node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2,
945
 
946
	; disable WOL
947
	mov	edi, dword [forcedeth_mapio_addr]
948
	mov	dword [edi+NvRegWakeUpFlags], 0
949
	mov	dword [forcedeth_wolenabled], 0
950
 
951
	mov	dword [forcedeth_txflags], (NV_TX2_LASTPACKET or NV_TX2_VALID)
952
	cmp	dword [forcedeth_desc_ver], DESC_VER_1
953
	jne	@f
954
	mov	dword [forcedeth_txflags], (NV_TX_LASTPACKET or NV_TX_VALID)
955
@@:
956
 
957
; BEGIN of switch (pci->dev_id)
958
 
959
	cmp	word [forcedeth_device_id], 0x01C3
960
	jne	.next_0x0066
961
	; nforce
962
	mov	dword [forcedeth_irqmask], 0	;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
963
	jmp	.end_switch
964
 
965
.next_0x0066:
966
	cmp	word [forcedeth_device_id], 0x0066
967
	je	@f
968
	cmp	word [forcedeth_device_id], 0x00D6
969
	je	@f
970
	jmp	.next_0x0086
971
@@:
972
	mov	dword [forcedeth_irqmask], 0	;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
973
	cmp	dword [forcedeth_desc_ver], DESC_VER_1
974
	jne	@f
975
	or	dword [forcedeth_txflags], NV_TX_LASTPACKET1
976
	jmp	.end_switch
977
@@:	or	dword [forcedeth_txflags], NV_TX2_LASTPACKET1
978
	jmp	.end_switch
979
 
980
.next_0x0086:
981
	cmp	word [forcedeth_device_id], 0x0086
982
	je	@f
983
	cmp	word [forcedeth_device_id], 0x008c
984
	je	@f
985
	cmp	word [forcedeth_device_id], 0x00e6
986
	je	@f
987
	cmp	word [forcedeth_device_id], 0x00df
988
	je	@f
989
	cmp	word [forcedeth_device_id], 0x0056
990
	je	@f
991
	cmp	word [forcedeth_device_id], 0x0057
992
	je	@f
993
	cmp	word [forcedeth_device_id], 0x0037
994
	je	@f
995
	cmp	word [forcedeth_device_id], 0x0038
996
	je	@f
997
	jmp	.next_0x0268
998
@@:
999
	; np->irqmask = NVREG_IRQMASK_WANTED_2;
1000
	; np->irqmask |= NVREG_IRQ_TIMER;
1001
	mov	dword [forcedeth_irqmask], 0	;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
1002
 
1003
	; if (np->desc_ver == DESC_VER_1)
1004
	cmp	dword [forcedeth_desc_ver], DESC_VER_1
1005
	jne	@f
1006
	;  np->tx_flags |= NV_TX_LASTPACKET1;
1007
	or	dword [forcedeth_txflags], NV_TX_LASTPACKET1
1008
	jmp	.end_switch
1009
	; else
1010
@@:
1011
	;  np->tx_flags |= NV_TX2_LASTPACKET1;
1012
	or	dword [forcedeth_txflags], NV_TX2_LASTPACKET1
1013
 
1014
	; break;
1015
	jmp	.end_switch
1016
 
1017
.next_0x0268:
1018
	cmp	word [forcedeth_device_id], 0x0268
1019
	je	@f
1020
	cmp	word [forcedeth_device_id], 0x0269
1021
	je	@f
1022
	cmp	word [forcedeth_device_id], 0x0372
1023
	je	@f
1024
	cmp	word [forcedeth_device_id], 0x0373
1025
	je	@f
1026
	jmp	.default_switch
1027
@@:
1028
	; pci_read_config_byte(pci, PCI_REVISION_ID, &revision_id);
1029
	mov	al, 0	; byte
1030
	mov	bh, [pci_dev]
1031
	mov	ah, [pci_bus]
1032
	mov	bl, PCI_REVISION_ID
1033
	call	pci_read_reg
1034
	mov	ecx, eax	; cl = revision_id
1035
 
1036
	; take phy and nic out of low power mode
1037
	; powerstate = readl(base + NvRegPowerState2);
1038
	mov	edi, dword [forcedeth_mapio_addr]
1039
	mov	eax, dword [edi+NvRegPowerState2]	; eax = powerstate
1040
 
1041
	; powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK;
1042
	and	eax, not NVREG_POWERSTATE2_POWERUP_MASK
1043
 
1044
	; if ((pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_12||pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_13)&&revision_id>=0xA3)
1045
	cmp	dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_12
1046
	je	@f
1047
	cmp	dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_13
1048
	je	@f
1049
	jmp	.end_if
1050
@@:
1051
	cmp	cl, 0xA3
1052
	jl	.end_if
1053
	;     powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3;
1054
	or	eax, NVREG_POWERSTATE2_POWERUP_REV_A3
1055
 
1056
.end_if:
1057
 
1058
	; writel(powerstate, base + NvRegPowerState2);
1059
	mov	dword [edi+NvRegPowerState2], eax
1060
 
1061
	; //DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ
1062
	; np->irqmask = NVREG_IRQMASK_WANTED_2;
1063
	; np->irqmask |= NVREG_IRQ_TIMER;
1064
	mov	dword [forcedeth_irqmask], 0	;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
1065
 
1066
	; needs_mac_reset = 1;
1067
	mov	dword [forcedeth_needs_mac_reset], 1
1068
 
1069
	; if (np->desc_ver == DESC_VER_1)
1070
	cmp	dword [forcedeth_desc_ver], DESC_VER_1
1071
	jne	@f
1072
	;   np->tx_flags |= NV_TX_LASTPACKET1;
1073
	or	dword [forcedeth_txflags], NV_TX_LASTPACKET1
1074
	jmp	.end_if2
1075
@@:
1076
	; else
1077
	;   np->tx_flags |= NV_TX2_LASTPACKET1;
1078
	or	dword [forcedeth_txflags], NV_TX2_LASTPACKET1
1079
 
1080
.end_if2:
1081
	; break;
1082
	jmp	.end_switch
1083
 
1084
.default_switch:
1085
	DEBUGF 1," K : FORCEDETH: Your card was undefined in this driver.\n"
1086
	DEBUGF 1," K : FORCEDETH: Review driver_data in Kolibri driver and send a patch\n"
1087
 
1088
.end_switch:
1089
 
1090
; END of switch (pci->dev_id)
1091
 
1092
 
1093
	; Find a suitable phy
1094
	mov	dword [forcedeth_tmp_i], 1
1095
.for_loop:
1096
	; for (i = 1; i <= 32; i++)
1097
	; phyaddr = i & 0x1f
1098
	mov	ebx, dword [forcedeth_tmp_i]
1099
	and	ebx, 0x1f
1100
 
1101
	; id1 = mii_rw(phyaddr, MII_PHYSID1, MII_READ)
1102
        ;EBX - addr, EAX - miireg, ECX - value
1103
	mov	eax, MII_PHYSID1
1104
	mov	ecx, MII_READ
1105
	call	forcedeth_mii_rw	; id1 = eax
1106
 
1107
	; if (id1 < 0 || id1 == 0xffff)
1108
	cmp	eax, 0xffffffff
1109
	je	.continue_for
1110
	test	eax, 0x80000000
1111
	jnz	.continue_for
1112
	mov	dword [forcedeth_tmp_id1], eax
1113
 
1114
	; id2 = mii_rw(nic, phyaddr, MII_PHYSID2, MII_READ)
1115
	mov	eax, MII_PHYSID2
1116
	mov	ecx, MII_READ
1117
	call	forcedeth_mii_rw	; id2 = eax
1118
 
1119
	; if (id2 < 0 || id2 == 0xffff)
1120
	cmp	eax, 0xffffffff
1121
	je	.continue_for
1122
	test	eax, 0x80000000
1123
	jnz	.continue_for
1124
	mov	dword [forcedeth_tmp_id2], eax
1125
 
1126
	jmp	.break_for
1127
.continue_for:
1128
	inc	dword [forcedeth_tmp_i]
1129
	cmp	dword [forcedeth_tmp_i], 32
1130
	jle	.for_loop
1131
	jmp	.end_for
1132
 
1133
.break_for:
1134
 
1135
;;;;	DEBUGF 1," K : FORCEDETH: id1=0x%x id2=0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8
1136
 
1137
	; id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT
1138
	mov	eax, dword [forcedeth_tmp_id1]
1139
	and	eax, PHYID1_OUI_MASK
1140
	shl	eax, PHYID1_OUI_SHFT
1141
	mov	dword [forcedeth_tmp_id1], eax
1142
 
1143
	; id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT
1144
	mov	eax, dword [forcedeth_tmp_id2]
1145
	and	eax, PHYID2_OUI_MASK
1146
	shr	eax, PHYID2_OUI_SHFT
1147
	mov	dword [forcedeth_tmp_id2], eax
1148
 
1149
	DEBUGF 1," K : FORCEDETH: Found PHY  0x%x:0x%x at address 0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8, ebx
1150
 
1151
	; np->phyaddr = phyaddr;
1152
	mov	dword [forcedeth_phyaddr], ebx
1153
 
1154
	; np->phy_oui = id1 | id2;
1155
	mov	eax, dword [forcedeth_tmp_id1]
1156
	or	eax, dword [forcedeth_tmp_id2]
1157
	mov	dword [forcedeth_phy_oui], eax
1158
 
1159
.end_for:
1160
 
1161
	; if (i == 33)
1162
	cmp	dword [forcedeth_tmp_i], 33
1163
	jne	@f
1164
	; PHY in isolate mode? No phy attached and user wants to
1165
	; test loopback? Very odd, but can be correct.
1166
 
1167
	DEBUGF 1," K : FORCEDETH: Could not find a valid PHY.\n"
1168
 
1169
	jmp	.next3
1170
 
1171
@@:
1172
 
1173
	; if (i != 33)
1174
	; reset it
1175
	call	forcedeth_phy_init
1176
 
1177
.next3:
1178
 
1179
;        dprintf(("%s: forcedeth.c: subsystem: %hX:%hX bound to %s\n",
1180
;                 pci->name, pci->vendor, pci->dev_id, pci->name));
1181
	DEBUGF 1," K : FORCEDETH: subsystem: 0x%x:0x%x bound to forcedeth\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4
1182
 
1183
 
1184
;        if(needs_mac_reset) mac_reset(nic);
1185
	cmp	dword [forcedeth_needs_mac_reset], 0
1186
	je	@f
1187
	call	forcedeth_mac_reset
1188
 
1189
@@:
1190
 
1191
	; if(!forcedeth_reset(nic)) return 0; // no valid link
1192
	call	forcedeth_reset
1193
	test	eax, eax
1194
	jnz	@f
1195
	mov	eax, 0
1196
	jmp	.return
1197
 
1198
@@:
1199
 
1200
	; point to NIC specific routines
1201
	; dev->disable = forcedeth_disable;
1202
	; nic->poll = forcedeth_poll;
1203
	; nic->transmit = forcedeth_transmit;
1204
	; nic->irq = forcedeth_irq;
1205
	;;;;;;;;;stdcall attach_int_handler, 11, forcedeth_int_handler, 0
1206
 
1207
	; return 1
1208
	mov	eax, 1
1209
	jmp	.return
1210
 
1211
.fail:
1212
	mov	eax, 0
1213
 
1214
.return:
1215
	ret
1216
 
1217
uglobal
1218
forcedeth_tmp_start	dd ?
1219
forcedeth_tmp_reg	dd ?
1220
forcedeth_tmp_i		dd ?
1221
forcedeth_tmp_id1	dd ?
1222
forcedeth_tmp_id2	dd ?
1223
forcedeth_tmp_phyinterface	dd ?
1224
forcedeth_tmp_newls	dd ?
1225
forcedeth_tmp_newdup	dd ?
1226
forcedeth_tmp_retval	dd ?
1227
forcedeth_tmp_control_1000	dd ?
1228
forcedeth_tmp_lpa	dd ?
1229
forcedeth_tmp_adv	dd ?
1230
forcedeth_tmp_len	dd ?
1231
forcedeth_tmp_valid	dd ?
1232
forcedeth_tmp_nr	dd ?
1233
forcedeth_tmp_ptxb	dd ?
1234
endg
1235
 
1236
;***************************************************************************
1237
; Function
1238
;    forcedeth_poll
1239
;
1240
; Description
1241
;    Polls the ethernet card for a received packet
1242
;    Received data, if any, ends up in Ether_buffer
1243
;
1244
;***************************************************************************
1245
forcedeth_poll:
1246
 
1247
	mov     word [eth_rx_data_len], 0
1248
 
1249
	; ????????????????????????????
1250
	; ??? Clear events? ???
1251
	mov	edi, dword [forcedeth_mapio_addr]
1252
	mov	dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK
1253
	; ????????????????????????????
1254
 
1255
.top:
1256
 
1257
	; i = np->cur_rx % RX_RING
1258
	mov	eax, dword [forcedeth_cur_rx]
1259
	and	eax, (RX_RING-1)
1260
	mov	dword [forcedeth_tmp_i], eax
1261
 
1262
	; Flags = le32_to_cpu(rx_ring[i].FlagLen)
1263
	; Flags = rx_ring[i].FlagLen
1264
	mov	cl, sizeof.forcedeth_RxDesc
1265
	mul	cl
1266
	add	eax, forcedeth_rx_ring
1267
	mov	ebx, eax
1268
	mov	eax, [ebx + forcedeth_RxDesc.FlagLen]
1269
 
1270
 
1271
	; if (Flags & NV_RX_AVAIL)
1272
	test	eax, NV_RX_AVAIL
1273
	;   return 0;       /* still owned by hardware, */
1274
	; still owned by hardware
1275
	jnz	.return0
1276
 
1277
;;;;;	DEBUGF	1,"poll: FlagLen = %x\n", eax
1278
 
1279
	; if (np->desc_ver == DESC_VER_1) {
1280
	cmp	dword [forcedeth_desc_ver], DESC_VER_1
1281
	jne	@f
1282
	;   if (!(Flags & NV_RX_DESCRIPTORVALID))
1283
	test	eax, NV_RX_DESCRIPTORVALID
1284
	;     return 0;
1285
	jz	.return0
1286
	jmp	.next
1287
	; } else {
1288
@@:
1289
	;   if (!(Flags & NV_RX2_DESCRIPTORVALID))
1290
	test	eax, NV_RX2_DESCRIPTORVALID
1291
	;     return 0;
1292
	jz	.return0
1293
	; }
1294
 
1295
.next:
1296
 
1297
	; len = nv_descr_getlength(&rx_ring[i], np->desc_ver)
1298
	; len = rx_ring[i].FlagLen & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2);
1299
	; eax = FlagLen
1300
	cmp	dword [forcedeth_desc_ver], DESC_VER_1
1301
	jne	@f
1302
	and	eax, LEN_MASK_V1
1303
	jmp	.next2
1304
@@:
1305
	and	eax, LEN_MASK_V2
1306
 
1307
.next2:
1308
 
1309
	; mov	dword [forcedeth_tmp_len], eax
1310
 
1311
	; valid = 1
1312
	mov	dword [forcedeth_tmp_valid], 1
1313
 
1314
	; got a valid packet - forward it to the network core
1315
	; nic->packetlen = len;
1316
	mov	dword [forcedeth_packetlen], eax
1317
	;
1318
	mov	word [eth_rx_data_len], ax
1319
;;;;;;;;;        DEBUGF	1,"poll: packet len = 0x%x\n", [forcedeth_packetlen]
1320
 
1321
 
1322
	; memcpy(nic->packet, rxb + (i * RX_NIC_BUFSIZE), nic->packetlen);
1323
	; Copy packet to system buffer (Ether_buffer)
1324
	;???? ecx = (len-4)
1325
	mov	ecx, eax
1326
	push	ecx
1327
	shr	ecx, 2
1328
 
1329
	; rxb + (i * RX_NIC_BUFSIZE)
1330
	mov	eax, dword [forcedeth_tmp_i]
1331
	mov	bx, RX_NIC_BUFSIZE
1332
	mul	bx
1333
	add	eax, forcedeth_rxb
1334
 
1335
	mov     esi, eax
1336
        mov     edi, Ether_buffer
1337
	cld		; set to increment
1338
	rep	movsd	; mov dword from [esi++] to [edi++]
1339
	pop	ecx
1340
	and	ecx, 3	; copy rest 1-3 bytes
1341
	rep	movsb
1342
 
1343
	; wmb();
1344
	; ???
1345
 
1346
	; np->cur_rx++;
1347
	inc	dword [forcedeth_cur_rx]
1348
 
1349
	; if (!valid)
1350
	cmp	dword [forcedeth_tmp_valid], 0
1351
	jne	@f
1352
	;   goto top;
1353
	jmp	.top
1354
@@:
1355
	; alloc_rx(nic);
1356
	call	forcedeth_alloc_rx
1357
 
1358
	; return 1;
1359
	jmp	.return1
1360
 
1361
;;;;;	DEBUGF	1,"K : FORCEDETH: poll: ...\n"
1362
 
1363
 
1364
.return0:
1365
	mov	eax, 0
1366
	jmp	.return
1367
.return1:
1368
	mov	eax, 1
1369
.return:
1370
	;;push	eax
1371
 
1372
	; ????????????????????????????????????????????????
1373
	; ????? clear interrupt mask/status
1374
	; read IRQ status
1375
	;;mov	edi, dword [forcedeth_mapio_addr]
1376
	;;mov	eax, dword [edi+NvRegIrqStatus]
1377
 
1378
	; clear events
1379
	;;and	eax, not (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF or NVREG_IRQ_LINK or NVREG_IRQ_TIMER)
1380
 
1381
	; write IRQ status
1382
	;;mov	dword [edi+NvRegIrqStatus], eax
1383
	; ????????????????????????????????????????????????
1384
 
1385
	;;pop	eax
1386
	ret
1387
 
1388
 
1389
;***************************************************************************
1390
;   Function
1391
;      forcedeth_transmit
1392
;
1393
;   Description
1394
;       Transmits a packet of data via the ethernet card
1395
;          Pointer to 48 bit destination address in edi
1396
;         Type of packet in bx
1397
;         size of packet in ecx
1398
;         pointer to packet data in esi
1399
;
1400
;***************************************************************************
1401
forcedeth_transmit:
1402
 
1403
	; send the packet to destination
1404
;pusha
1405
;DEBUGF	1,"K : FORCEDETH: transmit: packet type = 0x%x\n", ebx
1406
;DEBUGF	1,"K : FORCEDETH: transmit: packet len  = 0x%x\n", ecx
1407
;mov	eax, dword [edi]
1408
;DEBUGF	1,"K : FORCEDETH: transmit: dest adr    = 0x%x\n", eax
1409
;mov	eax, dword [edi+4]
1410
;DEBUGF	1,"K : FORCEDETH: transmit: dest adr2   = 0x%x\n", eax
1411
;mov	eax, dword [node_addr]
1412
;DEBUGF	1,"K : FORCEDETH: transmit: src  adr    = 0x%x\n", eax
1413
;mov	eax, dword [node_addr+4]
1414
;DEBUGF	1,"K : FORCEDETH: transmit: src adr2    = 0x%x\n", eax
1415
;popa
1416
 
1417
	; int nr = np->next_tx % TX_RING
1418
	mov	eax, dword [forcedeth_next_tx]
1419
	and	eax, (TX_RING-1)
1420
	mov	dword [forcedeth_tmp_nr], eax
1421
 
1422
	; point to the current txb incase multiple tx_rings are used
1423
	; ptxb = txb + (nr * RX_NIC_BUFSIZE)
1424
	push	ecx
1425
	mov	cx, RX_NIC_BUFSIZE
1426
	mul	cx	; AX*CX, result to DX:AX
1427
	add	eax, forcedeth_txb
1428
	mov	dword [forcedeth_tmp_ptxb], eax
1429
	push	esi
1430
	mov	esi, edi	; dst MAC
1431
	mov	edi, eax	; packet buffer
1432
	cld			; set to increment
1433
 
1434
	; copy the packet to ring buffer
1435
	; memcpy(ptxb, d, ETH_ALEN);      /* dst */
1436
	movsd
1437
	movsw
1438
 
1439
	; memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN);      /* src */
1440
	mov	esi, node_addr
1441
	movsd
1442
	movsw
1443
 
1444
	; nstype = htons((u16) t);        /* type */
1445
	; memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2);        /* type */
1446
	mov	word [edi], bx
1447
	add	edi, 2
1448
 
1449
	; memcpy(ptxb + ETH_HLEN, p, s);
1450
	pop	esi
1451
	pop	ecx
1452
	push	ecx
1453
	shr	ecx, 2		; count in dwords
1454
	rep	movsd		; copy dwords from [esi+=4] to [edi+=4]
1455
	pop	ecx
1456
	push	ecx
1457
	and	ecx, 3		; copy rest 1-3 bytes
1458
	rep	movsb		; copy bytess from [esi++] to [edi++]
1459
 
1460
 
1461
	; s += ETH_HLEN;
1462
	; while (s < ETH_ZLEN)    /* pad to min length */
1463
	;  ptxb[s++] = '\0';
1464
	; pad to min length
1465
	pop	ecx
1466
	add	ecx, ETH_HLEN
1467
	push	ecx		; header length + data length
1468
	cmp	ecx, ETH_ZLEN
1469
	jge	@f
1470
	mov	eax, ETH_ZLEN
1471
	sub	eax, ecx
1472
	xchg	eax, ecx
1473
	mov	al, 0
1474
	rep	stosb		; copy byte from al to [edi++]
1475
 
1476
@@:
1477
 
1478
	; tx_ring[nr].PacketBuffer = (u32) virt_to_le32desc(ptxb);
1479
	mov	eax, dword [forcedeth_tmp_nr]
1480
	mov	cl, sizeof.forcedeth_TxDesc
1481
	mul	cl
1482
	add	eax, forcedeth_tx_ring
1483
	mov	ebx, eax
1484
	mov	eax, dword [forcedeth_tmp_ptxb]
1485
	sub	eax, OS_BASE		;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1486
	mov	[ebx + forcedeth_TxDesc.PacketBuffer], eax
1487
 
1488
;DEBUGF	1,"K : FORCEDETH: transmit: PacketBuffer = 0x%x\n", eax
1489
;DEBUGF	1,"K : FORCEDETH: transmit: txflags = 0x%x\n", [forcedeth_txflags]:8
1490
 
1491
	; wmb();
1492
	; tx_ring[nr].FlagLen = cpu_to_le32((s - 1) | np->tx_flags);
1493
	pop	eax		; header length + data length
1494
	mov	ecx, dword [forcedeth_txflags]
1495
	or	eax, ecx
1496
	mov	[ebx + forcedeth_TxDesc.FlagLen], eax
1497
 
1498
	; writel(NVREG_TXRXCTL_KICK | np->desc_ver, base + NvRegTxRxControl);
1499
	mov	edi, dword [forcedeth_mapio_addr]
1500
	mov	eax, dword [forcedeth_desc_ver]
1501
	or	eax, NVREG_TXRXCTL_KICK
1502
	mov	dword [edi+NvRegTxRxControl], eax
1503
 
1504
	; pci_push(base);
1505
	call	forcedeth_pci_push
1506
 
1507
	; np->next_tx++
1508
	inc dword [forcedeth_next_tx]	; may be need to reset? Overflow?
1509
 
1510
	ret
1511
 
1512
;***************************************************************************
1513
;   Function
1514
;      forcedeth_cable
1515
;
1516
;   Description
1517
;	Return AL=0, if cable is not connected
1518
;	Returm AL=1, if cable is connected
1519
;
1520
;***************************************************************************
1521
forcedeth_cable:
1522
 
1523
	mov	al, 1
1524
	cmp	dword [forcedeth_nocable], 1
1525
	jne	.return
1526
	mov	al, 0
1527
 
1528
.return:
1529
	ret
1530
 
1531
;***************************************************************************
1532
 
1533
 
1534
; read/write a register on the PHY.
1535
; Caller must guarantee serialization
1536
; Input:  EAX - miireg, EBX - addr, ECX - value
1537
; Output: EAX - retval
1538
forcedeth_mii_rw:
1539
	push	ebx
1540
	push	eax	; save miireg
1541
	; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus)
1542
	mov	edi, dword [forcedeth_mapio_addr]
1543
	mov	dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK
1544
 
1545
	; reg = readl(base + NvRegMIIControl)
1546
	mov	eax, dword [edi+NvRegMIIControl]
1547
	test	eax, NVREG_MIICTL_INUSE
1548
	jz	@f
1549
	; writel(NVREG_MIICTL_INUSE, base + NvRegMIIControl)
1550
	mov	dword [edi+NvRegMIIControl], NVREG_MIICTL_INUSE
1551
	; nv_udelay(NV_MIIBUSY_DELAY)
1552
	mov	esi, NV_MIIBUSY_DELAY
1553
	call	forcedeth_nv_udelay
1554
@@:
1555
	; reg = (addr << NVREG_MIICTL_ADDRSHIFT) | miireg
1556
	pop	edx	; restore miireg
1557
	mov	eax, ebx
1558
	shl	eax, NVREG_MIICTL_ADDRSHIFT
1559
	or	eax, edx
1560
	mov	dword [forcedeth_tmp_reg], eax
1561
 
1562
	cmp	ecx, MII_READ
1563
	je	@f
1564
	; writel(value, base + NvRegMIIData)
1565
	mov	dword [edi+NvRegMIIData], ecx
1566
	; reg |= NVREG_MIICTL_WRITE
1567
	or	dword [forcedeth_tmp_reg], NVREG_MIICTL_WRITE
1568
@@:
1569
	; writel(reg, base + NvRegMIIControl)
1570
	mov	eax, dword [forcedeth_tmp_reg]
1571
	mov	dword [edi+NvRegMIIControl], eax
1572
 
1573
	push	ebx edx edi	;;;;;;;;;;;;;;;;;;;;;;
1574
 
1575
	; reg_delay(NvRegMIIControl, NVREG_MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL)
1576
	stdcall forcedeth_reg_delay,NvRegMIIControl,NVREG_MIICTL_INUSE,0,NV_MIIPHY_DELAY,NV_MIIPHY_DELAYMAX,0
1577
 
1578
	pop	edi edx ebx	;;;;;;;;;;;;;;;;;;;;;;
1579
 
1580
	test	eax, eax
1581
	jz	@f
1582
;;;;;;;;        DEBUGF	1,"K : FORCEDETH: mii_rw of reg %d at PHY %d timed out.\n", edx, ebx
1583
	mov	eax, 0xffffffff
1584
	jmp	.return
1585
@@:
1586
	cmp	ecx, MII_READ
1587
	je	@f
1588
	;it was a write operation - fewer failures are detectable
1589
;;;;;;;;        DEBUGF	1,"K : FORCEDETH: mii_rw wrote 0x%x to reg %d at PHY %d\n", ecx, edx, ebx
1590
	mov	eax, 0
1591
	jmp	.return
1592
@@:
1593
	; readl(base + NvRegMIIStatus)
1594
	mov	eax, dword [edi+NvRegMIIStatus]
1595
	test	eax, NVREG_MIISTAT_ERROR
1596
	jz	@f
1597
;;;;;;;;	DEBUGF	1,"K : FORCEDETH: mii_rw of reg %d at PHY %d failed.\n", edx, ebx
1598
	mov	eax, 0xffffffff
1599
	jmp	.return
1600
@@:
1601
	; retval = readl(base + NvRegMIIData)
1602
	mov	eax, dword [edi+NvRegMIIData]
1603
;;;;;;;;	DEBUGF	1,"K : FORCEDETH: mii_rw read from reg %d at PHY %d: 0x%x.\n", edx, ebx, eax
1604
.return:
1605
	pop	ebx
1606
	ret
1607
 
1608
 
1609
 
1610
; Input:  ESI - delay
1611
; Output: none
1612
forcedeth_nv_udelay:
1613
 
1614
	push	ebx
1615
	cmp	dword [forcedeth_in_shutdown], 0
1616
	jne	@f
1617
	call	forcedeth_udelay	; delay on ESI
1618
	jmp	.return
1619
@@:
1620
 
1621
.loop:
1622
	cmp	esi, 0
1623
	je	.return
1624
	; Don't allow an rx_ring overflow to happen
1625
	; while shutting down the NIC it will
1626
	; kill the receive function.
1627
 
1628
	call	forcedeth_drop_rx
1629
	mov	ebx, 3		; sleep = 3
1630
	cmp	ebx, esi	; if(sleep > delay)
1631
	jle	@f
1632
	mov	ebx, esi	; sleep = delay
1633
@@:
1634
	push	esi
1635
	mov	esi, ebx
1636
	; udelay(sleep)
1637
	call	forcedeth_udelay	; delay on ESI
1638
	pop	esi
1639
	sub	esi, ebx		; delay -= sleep
1640
	jmp	.loop
1641
 
1642
.return:
1643
	pop	ebx
1644
	ret
1645
 
1646
 
1647
; Input:  none
1648
; Output: none
1649
forcedeth_drop_rx:
1650
 
1651
	push	eax ebx ecx edi
1652
 
1653
	; events = readl(base + NvRegIrqStatus)
1654
	mov	edi, dword [forcedeth_mapio_addr]
1655
	mov	eax, dword [edi+NvRegIrqStatus]
1656
 
1657
	test	eax, eax
1658
	jz	@f
1659
	; writel(events, base + NvRegIrqStatus)
1660
	mov	dword [edi+NvRegIrqStatus], eax
1661
@@:
1662
	;if (!(events & (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF)))
1663
	test	eax, (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF)
1664
	jz	.return
1665
 
1666
.loop:
1667
	; i = np->cur_rx % RX_RING
1668
	mov	eax, dword [forcedeth_cur_rx]
1669
	and	eax, (RX_RING-1)
1670
	; //Flags = le32_to_cpu(rx_ring[i].FlagLen)
1671
	; Flags = rx_ring[i].FlagLen
1672
	mov	cl, sizeof.forcedeth_RxDesc
1673
	mul	cl
1674
	add	eax, forcedeth_rx_ring
1675
	mov	ebx, eax
1676
	mov	eax, [ebx + forcedeth_RxDesc.FlagLen]
1677
	; len = nv_descr_getlength(&rx_ring[i], np->desc_ver)
1678
	; > len = Flags & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2)
1679
	; ??? len don't used later !!! ???
1680
	; ...
1681
	test	eax, NV_RX_AVAIL
1682
	jnz	.return		; still owned by hardware,
1683
	; wmb()
1684
	; ??? may be empty function ???
1685
	; np->cur_rx++
1686
	inc	dword [forcedeth_cur_rx]
1687
	; alloc_rx(NULL)
1688
	call	forcedeth_alloc_rx
1689
.return:
1690
	pop	edi ecx ebx eax
1691
	ret
1692
 
1693
 
1694
; Fill rx ring entries.
1695
; Return 1 if the allocations for the skbs failed and the
1696
; rx engine is without Available descriptors
1697
; Input:  none
1698
; Output: none
1699
forcedeth_alloc_rx:
1700
 
1701
	push	eax ebx ecx edx
1702
	; refill_rx = np->refill_rx
1703
	mov	ecx, dword [forcedeth_refill_rx]
1704
.loop:
1705
	cmp	dword [forcedeth_cur_rx], ecx
1706
	je	.loop_end
1707
	; nr = refill_rx % RX_RING
1708
	mov	eax, ecx
1709
	and	eax, (RX_RING-1)	; nr
1710
	; rx_ring[nr].PacketBuffer = &rxb[nr * RX_NIC_BUFSIZE]
1711
	push	ecx
1712
	push	eax
1713
	mov	cl, sizeof.forcedeth_RxDesc
1714
	mul	cl
1715
	add	eax, forcedeth_rx_ring
1716
	mov	ebx, eax
1717
	pop	eax
1718
	mov	cx, RX_NIC_BUFSIZE
1719
	mul	cx
1720
	pop	ecx
1721
	add	eax, forcedeth_rxb
1722
	sub	eax, OS_BASE	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1723
	mov	[ebx + forcedeth_RxDesc.PacketBuffer], eax
1724
	; wmb()
1725
	; ...
1726
	; rx_ring[nr].FlagLen = RX_NIC_BUFSIZE | NV_RX_AVAIL
1727
	mov	[ebx + forcedeth_RxDesc.FlagLen], (RX_NIC_BUFSIZE or NV_RX_AVAIL)
1728
	inc	ecx
1729
	jmp	.loop
1730
 
1731
.loop_end:
1732
	; np->refill_rx = refill_rx
1733
	mov	[forcedeth_refill_rx], ecx
1734
.return:
1735
	pop	edx ecx ebx eax
1736
	ret
1737
 
1738
 
1739
; Delay in millisec
1740
; Input:  ESI - delay in ms
1741
; Output: none
1742
forcedeth_udelay:
1743
        call    delay_ms
1744
	ret
1745
 
1746
; Input:  offset:word, mask:dword, target:dword, delay:word, delaymax:word, msg:dword
1747
; Output: EAX - 0|1
1748
;;;;proc	forcedeth_reg_delay,offset:word,mask:dword,target:dword,delay:word,delaymax:word,msg:dword
1749
proc	forcedeth_reg_delay,offset:dword,mask:dword,target:dword,delay:dword,delaymax:dword,msg:dword
1750
 
1751
	push	ebx esi edi
1752
	; pci_push(base)
1753
	call	forcedeth_pci_push
1754
.loop:
1755
	; nv_udelay(delay)
1756
	mov	esi, dword [delay]
1757
	call	forcedeth_nv_udelay	; delay in esi
1758
	mov	eax, dword [delaymax]
1759
	sub	eax, dword [delay]
1760
	mov	dword [delaymax], eax
1761
	; if (delaymax < 0)
1762
	test	dword [delaymax], 0x80000000
1763
	jz	@f
1764
	; return 1
1765
	mov	eax, 1
1766
	jmp	.return
1767
@@:
1768
	; while ((readl(base + offset) & mask) != target)
1769
	mov	edi, dword [forcedeth_mapio_addr]
1770
	mov	ebx, dword [offset]
1771
	mov	eax, dword [edi+ebx]
1772
	and	eax, dword [mask]
1773
	cmp	eax, dword [target]
1774
	jne	.loop
1775
	xor	eax, eax
1776
.return:
1777
	pop	edi esi ebx
1778
	ret
1779
endp
1780
 
1781
 
1782
; Input:  none
1783
; Output: none
1784
forcedeth_pci_push:
1785
	push	eax edi
1786
	;force out pending posted writes
1787
	mov	edi, dword [forcedeth_mapio_addr]
1788
	mov	eax, dword [edi]
1789
	pop	edi eax
1790
	ret
1791
 
1792
 
1793
; Input:  none
1794
; Output: EAX - result (0 = OK, other = error)
1795
forcedeth_phy_init:
1796
 
1797
	push	ebx ecx
1798
 
1799
	; set advertise register
1800
	; reg = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ);
1801
        ; EBX - addr, EAX - miireg, ECX - value
1802
	mov	ebx, dword [forcedeth_phyaddr]
1803
	mov	eax, MII_ADVERTISE
1804
	mov	ecx, MII_READ
1805
	call	forcedeth_mii_rw	; reg = eax
1806
 
1807
	; reg |=
1808
	; (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF |
1809
	;  ADVERTISE_100FULL | 0x800 | 0x400);
1810
	or	eax, (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or 0x800 or 0x400)
1811
 
1812
	; if (mii_rw(nic, np->phyaddr, MII_ADVERTISE, reg))
1813
        ; EBX - addr, EAX - miireg, ECX - value
1814
	mov	ecx, eax	; reg
1815
	mov	eax, MII_ADVERTISE
1816
	call	forcedeth_mii_rw	; eax -> return
1817
 
1818
	test	eax, eax
1819
	jz	@f
1820
	; printf("phy write to advertise failed.\n");
1821
	DEBUGF 1," K : FORCEDETH: phy write to advertise failed.\n"
1822
 
1823
	; return PHY_ERROR;
1824
	mov	eax, PHY_ERROR
1825
	jmp	.return
1826
@@:
1827
	; get phy interface type
1828
	; phyinterface = readl(base + NvRegPhyInterface);
1829
	mov	edi, dword [forcedeth_mapio_addr]
1830
	mov	eax, dword [edi+NvRegPhyInterface]	; phyinterface = eax
1831
	mov	dword [forcedeth_tmp_phyinterface], eax
1832
 
1833
;;;;;;;;;;;;;;;;;;;;;;;;;
1834
DEBUGF 1," K : FORCEDETH: phy interface type = 0x%x\n", [forcedeth_tmp_phyinterface]:8
1835
;;;;;;;;;;;;;;;;;;;;;;;;;
1836
 
1837
	; see if gigabit phy
1838
	; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
1839
        ; EBX - addr, EAX - miireg, ECX - value
1840
	mov	eax, MII_BMSR
1841
	mov	ecx, MII_READ
1842
	call	forcedeth_mii_rw	; mii_status = eax
1843
 
1844
	; if (mii_status & PHY_GIGABIT)
1845
	test	eax, PHY_GIGABIT
1846
	jnz	.gigabit
1847
	; np->gigabit = 0;
1848
	mov	dword [forcedeth_gigabit], 0
1849
	jmp	.next_if
1850
 
1851
.gigabit:
1852
	; np->gigabit = PHY_GIGABIT;
1853
	mov	dword [forcedeth_gigabit], PHY_GIGABIT
1854
 
1855
	; mii_control_1000 =  mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ);
1856
        ; EBX - addr, EAX - miireg, ECX - value
1857
	mov	eax, MII_1000BT_CR
1858
	mov	ecx, MII_READ
1859
	call	forcedeth_mii_rw	; mii_control_1000 = eax
1860
 
1861
	; mii_control_1000 &= ~ADVERTISE_1000HALF;
1862
	and	eax, (not ADVERTISE_1000HALF)
1863
 
1864
	; if (phyinterface & PHY_RGMII)
1865
	test	dword [forcedeth_tmp_phyinterface], PHY_RGMII
1866
	jz	@f
1867
	; mii_control_1000 |= ADVERTISE_1000FULL
1868
	or	eax, ADVERTISE_1000FULL
1869
	jmp	.next
1870
@@:
1871
	; mii_control_1000 &= ~ADVERTISE_1000FULL
1872
	and	eax, (not ADVERTISE_1000FULL)
1873
 
1874
.next:
1875
	; if (mii_rw(nic, np->phyaddr, MII_1000BT_CR, mii_control_1000))
1876
        ; EBX - addr, EAX - miireg, ECX - value
1877
	mov	ecx, eax
1878
	mov	eax, MII_1000BT_CR
1879
	call	forcedeth_mii_rw	; eax -> return
1880
 
1881
	test	eax, eax
1882
	jz	.next_if
1883
 
1884
	; printf("phy init failed.\n");
1885
	DEBUGF 1," K : FORCEDETH: phy init failed.\n"
1886
 
1887
	; return PHY_ERROR;
1888
	mov	eax, PHY_ERROR
1889
	jmp	.return
1890
 
1891
.next_if:
1892
 
1893
	; reset the phy
1894
	; if (phy_reset(nic))
1895
	call	forcedeth_phy_reset
1896
	test	eax, eax
1897
	jz	@f
1898
	; printf("phy reset failed\n")
1899
	DEBUGF 1," K : FORCEDETH: phy reset failed.\n"
1900
	; return PHY_ERROR
1901
	mov	eax, PHY_ERROR
1902
	jmp	.return
1903
@@:
1904
 
1905
	; phy vendor specific configuration
1906
	; if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII))
1907
	cmp	dword [forcedeth_phy_oui], PHY_OUI_CICADA
1908
	jne	.next_if2
1909
	test	dword [forcedeth_tmp_phyinterface], PHY_RGMII
1910
	jz	.next_if2
1911
 
1912
	; phy_reserved = mii_rw(nic, np->phyaddr, MII_RESV1, MII_READ)
1913
        ; EBX - addr, EAX - miireg, ECX - value
1914
	mov	eax, MII_RESV1
1915
	mov	ecx, MII_READ
1916
	call	forcedeth_mii_rw	; phy_reserved = eax
1917
 
1918
	; phy_reserved &= ~(PHY_INIT1 | PHY_INIT2)
1919
	and	eax, (not (PHY_INIT1 or PHY_INIT2))
1920
	; phy_reserved |= (PHY_INIT3 | PHY_INIT4)
1921
	or	eax, (PHY_INIT3 or PHY_INIT4)
1922
 
1923
	; if (mii_rw(nic, np->phyaddr, MII_RESV1, phy_reserved))
1924
        ; EBX - addr, EAX - miireg, ECX - value
1925
	mov	ecx, eax
1926
	mov	eax, MII_RESV1
1927
	call	forcedeth_mii_rw	; eax -> return
1928
	test	eax, eax
1929
	jz	@f
1930
	; printf("phy init failed.\n")
1931
	DEBUGF 1," K : FORCEDETH: phy init failed.\n"
1932
	; return PHY_ERROR
1933
	mov	eax, PHY_ERROR
1934
	jmp	.return
1935
@@:
1936
	; phy_reserved = mii_rw(nic, np->phyaddr, MII_NCONFIG, MII_READ);
1937
        ; EBX - addr, EAX - miireg, ECX - value
1938
	mov	eax, MII_NCONFIG
1939
	mov	ecx, MII_READ
1940
	call	forcedeth_mii_rw	; phy_reserved = eax
1941
 
1942
	; phy_reserved |= PHY_INIT5
1943
	or	eax, PHY_INIT5
1944
 
1945
	; if (mii_rw(nic, np->phyaddr, MII_NCONFIG, phy_reserved))
1946
        ; EBX - addr, EAX - miireg, ECX - value
1947
	mov	ecx, eax
1948
	mov	eax, MII_NCONFIG
1949
	call	forcedeth_mii_rw	; eax -> return
1950
	test	eax, eax
1951
	jz	.next_if2
1952
	; printf("phy init failed.\n")
1953
	DEBUGF 1," K : FORCEDETH: phy init failed.\n"
1954
	; return PHY_ERROR
1955
	mov	eax, PHY_ERROR
1956
	jmp	.return
1957
 
1958
.next_if2:
1959
 
1960
	; if (np->phy_oui == PHY_OUI_CICADA)
1961
	cmp	dword [forcedeth_phy_oui], PHY_OUI_CICADA
1962
	jne	.restart
1963
 
1964
	; phy_reserved = mii_rw(nic, np->phyaddr, MII_SREVISION, MII_READ)
1965
        ; EBX - addr, EAX - miireg, ECX - value
1966
	mov	eax, MII_SREVISION
1967
	mov	ecx, MII_READ
1968
	call	forcedeth_mii_rw	; phy_reserved = eax
1969
 
1970
	; phy_reserved |= PHY_INIT6
1971
	or	eax, PHY_INIT6
1972
 
1973
	; if (mii_rw(nic, np->phyaddr, MII_SREVISION, phy_reserved))
1974
	mov	ecx, eax
1975
	mov	eax, MII_SREVISION
1976
	call	forcedeth_mii_rw	; eax -> return
1977
	test	eax, eax
1978
	jz	.restart
1979
	; printf("phy init failed.\n");
1980
	DEBUGF 1," K : FORCEDETH: phy init failed.\n"
1981
	; return PHY_ERROR;
1982
	jmp	.return
1983
 
1984
.restart:
1985
	; restart auto negotiation
1986
	; mii_control = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ)
1987
        ; EBX - addr, EAX - miireg, ECX - value
1988
	mov	eax, MII_BMCR
1989
	mov	ecx, MII_READ
1990
	call	forcedeth_mii_rw	; mii_control = eax
1991
 
1992
	; mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE)
1993
	or	eax, (BMCR_ANRESTART or BMCR_ANENABLE)
1994
 
1995
	; if (mii_rw(nic, np->phyaddr, MII_BMCR, mii_control))
1996
	mov	ecx, eax
1997
	mov	eax, MII_BMCR
1998
	call	forcedeth_mii_rw	; eax -> return
1999
	test	eax, eax
2000
	jz	.ok
2001
 
2002
	; return PHY_ERROR;
2003
	mov	eax, PHY_ERROR
2004
	jmp	.return
2005
 
2006
.ok:
2007
	mov	eax, 0
2008
.return:
2009
	pop	ecx ebx
2010
	ret
2011
 
2012
 
2013
; Input:  none
2014
; Output: EAX - result (0 = OK, other = error)
2015
forcedeth_phy_reset:
2016
 
2017
	push	ebx ecx edx
2018
 
2019
	; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ);
2020
        ; EBX - addr, EAX - miireg, ECX - value
2021
	mov	ebx, dword [forcedeth_phyaddr]
2022
	mov	eax, MII_BMCR
2023
	mov	ecx, MII_READ
2024
	call	forcedeth_mii_rw	; miicontrol = eax
2025
 
2026
	; miicontrol |= BMCR_RESET;
2027
	or	eax, BMCR_RESET
2028
	push	eax
2029
 
2030
	; if (mii_rw(nic, np->phyaddr, MII_BMCR, miicontrol))
2031
        ; EBX - addr, EAX - miireg, ECX - value
2032
	mov	ecx, eax
2033
	mov	eax, MII_BMCR
2034
	call	forcedeth_mii_rw	; miicontrol = eax
2035
 
2036
	test	eax, eax
2037
	jz	@f
2038
	pop	eax
2039
	mov	eax, 0xffffffff
2040
	jmp	.return
2041
@@:
2042
	pop	eax
2043
 
2044
	; wait for 500ms
2045
	; mdelay(500)
2046
	mov	esi, 500
2047
	call	forcedeth_udelay
2048
 
2049
	; must wait till reset is deasserted
2050
	; while (miicontrol & BMCR_RESET) {
2051
	mov	edx, 100
2052
.while_loop:
2053
	test	eax, BMCR_RESET
2054
	jz	.while_loop_exit
2055
 
2056
	; mdelay(10);
2057
	mov	esi, 10
2058
	call	forcedeth_udelay
2059
 
2060
	; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ);
2061
        ; EBX - addr, EAX - miireg, ECX - value
2062
	mov	eax, MII_BMCR
2063
	mov	ecx, MII_READ
2064
	call	forcedeth_mii_rw	; miicontrol = eax
2065
 
2066
	; FIXME: 100 tries seem excessive
2067
	; if (tries++ > 100)
2068
	dec	edx
2069
	jnz	.while_loop
2070
	; return -1;
2071
	mov	eax, 0xffffffff
2072
	jmp	.return
2073
.while_loop_exit:
2074
	; return 0
2075
	mov	eax, 0
2076
.return:
2077
	pop	edx ecx ebx
2078
	ret
2079
 
2080
; Input:  none
2081
; Output: none
2082
forcedeth_mac_reset:
2083
	push	esi edi
2084
 
2085
	; dprintf("mac_reset\n")
2086
	DEBUGF 1," K : FORCEDETH: mac_reset.\n"
2087
 
2088
	; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl)
2089
	mov	edi, dword [forcedeth_mapio_addr]
2090
	mov	eax, dword [forcedeth_desc_ver]
2091
	or	eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET)
2092
	mov	dword [edi+NvRegTxRxControl], eax
2093
 
2094
	; pci_push(base)
2095
	call	forcedeth_pci_push
2096
 
2097
	; writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset)
2098
	mov	dword [edi+NvRegMacReset], NVREG_MAC_RESET_ASSERT
2099
 
2100
	; pci_push(base)
2101
	call	forcedeth_pci_push
2102
 
2103
	; udelay(NV_MAC_RESET_DELAY)
2104
	mov	esi, NV_MAC_RESET_DELAY
2105
	call	forcedeth_nv_udelay
2106
 
2107
	; writel(0, base + NvRegMacReset)
2108
	mov	dword [edi+NvRegMacReset], 0
2109
 
2110
	; pci_push(base)
2111
	call	forcedeth_pci_push
2112
 
2113
	; udelay(NV_MAC_RESET_DELAY)
2114
	mov	esi, NV_MAC_RESET_DELAY
2115
	call	forcedeth_nv_udelay
2116
 
2117
	; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl)
2118
	mov	eax, dword [forcedeth_desc_ver]
2119
	or	eax, NVREG_TXRXCTL_BIT2
2120
	mov	dword [edi+NvRegTxRxControl], eax
2121
 
2122
	; pci_push(base)
2123
	call	forcedeth_pci_push
2124
 
2125
	pop	edi esi
2126
	ret
2127
 
2128
; Input:  none
2129
; Output: none
2130
forcedeth_init_ring:
2131
	push	eax ebx ecx
2132
 
2133
        ; np->next_tx = np->nic_tx = 0
2134
	mov	dword[forcedeth_next_tx], 0
2135
	mov	dword[forcedeth_nic_tx], 0
2136
 
2137
        ; for (i = 0; i < TX_RING; i++)
2138
	mov	ecx, TX_RING
2139
 
2140
.for_loop:
2141
        ;        tx_ring[i].FlagLen = 0;
2142
	mov	eax, ecx
2143
	dec	eax
2144
	mov	bl, sizeof.forcedeth_TxDesc
2145
	mul	bl
2146
	add	eax, forcedeth_tx_ring
2147
	mov	ebx, eax
2148
	mov	dword [ebx + forcedeth_TxDesc.FlagLen], 0
2149
	loop	.for_loop
2150
 
2151
        ; np->cur_rx = RX_RING;
2152
	mov	dword [forcedeth_cur_rx], RX_RING
2153
        ; np->refill_rx = 0;
2154
	mov	dword [forcedeth_refill_rx], 0
2155
 
2156
	;for (i = 0; i < RX_RING; i++)
2157
	mov	ecx, RX_RING
2158
 
2159
.for_loop2:
2160
        ;        rx_ring[i].FlagLen = 0;
2161
	mov	eax, ecx
2162
	dec	eax
2163
	mov	bl, sizeof.forcedeth_RxDesc
2164
	mul	bl
2165
	add	eax, forcedeth_rx_ring
2166
	mov	ebx, eax
2167
	mov	dword [ebx + forcedeth_RxDesc.FlagLen], 0
2168
	loop	.for_loop2
2169
 
2170
	; alloc_rx(nic);
2171
	call	forcedeth_alloc_rx
2172
 
2173
.return:
2174
	pop	ecx ebx eax
2175
	ret
2176
 
2177
; Input:  none
2178
; Output: none
2179
forcedeth_txrx_reset:
2180
	push	eax esi edi
2181
 
2182
	; dprintf(("txrx_reset\n"))
2183
	DEBUGF 1," K : FORCEDETH: txrx_reset.\n"
2184
 
2185
	; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl)
2186
	mov	edi, dword [forcedeth_mapio_addr]
2187
	mov	eax, dword [forcedeth_desc_ver]
2188
	or	eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET)
2189
	mov	dword [edi+NvRegTxRxControl], eax
2190
 
2191
	; pci_push(base)
2192
	call	forcedeth_pci_push
2193
 
2194
	; nv_udelay(NV_TXRX_RESET_DELAY)
2195
	mov	esi, NV_TXRX_RESET_DELAY
2196
	call	forcedeth_nv_udelay
2197
 
2198
	; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl)
2199
	mov	eax, dword [forcedeth_desc_ver]
2200
	or	eax, NVREG_TXRXCTL_BIT2
2201
	mov	dword [edi+NvRegTxRxControl], eax
2202
 
2203
	; pci_push(base)
2204
	call	forcedeth_pci_push
2205
 
2206
.return:
2207
	pop	edi esi eax
2208
	ret
2209
 
2210
; Input:  none
2211
; Output: none
2212
forcedeth_set_multicast:
2213
	push	edi
2214
 
2215
	; u32 addr[2];
2216
	; u32 mask[2];
2217
	; u32 pff;
2218
	; u32 alwaysOff[2];
2219
	; u32 alwaysOn[2];
2220
	;
2221
	; memset(addr, 0, sizeof(addr));
2222
	; memset(mask, 0, sizeof(mask));
2223
	;
2224
	; pff = NVREG_PFF_MYADDR;
2225
	;
2226
	; alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0;
2227
	;
2228
	; addr[0] = alwaysOn[0];
2229
	; addr[1] = alwaysOn[1];
2230
	; mask[0] = alwaysOn[0] | alwaysOff[0];
2231
	; mask[1] = alwaysOn[1] | alwaysOff[1];
2232
	;
2233
	; addr[0] |= NVREG_MCASTADDRA_FORCE;
2234
	; pff |= NVREG_PFF_ALWAYS;
2235
	; stop_rx();
2236
	call	forcedeth_stop_rx
2237
	; writel(addr[0], base + NvRegMulticastAddrA);
2238
	mov	edi, dword [forcedeth_mapio_addr]
2239
	mov	dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE
2240
	; writel(addr[1], base + NvRegMulticastAddrB);
2241
	mov	dword [edi+NvRegMulticastAddrB], 0
2242
	; writel(mask[0], base + NvRegMulticastMaskA);
2243
	mov	dword [edi+NvRegMulticastMaskA], 0
2244
	; writel(mask[1], base + NvRegMulticastMaskB);
2245
	mov	dword [edi+NvRegMulticastMaskB], 0
2246
	; writel(pff, base + NvRegPacketFilterFlags);
2247
	mov	dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_MYADDR or NVREG_PFF_ALWAYS)
2248
	; start_rx(nic);
2249
	call	forcedeth_start_rx
2250
 
2251
.return:
2252
	pop	edi
2253
	ret
2254
 
2255
; Input:  none
2256
; Output: none
2257
forcedeth_start_rx:
2258
	push	edi
2259
 
2260
	; dprintf(("start_rx\n"))
2261
	DEBUGF 1," K : FORCEDETH: start_rx.\n"
2262
 
2263
	; Already running? Stop it.
2264
	; if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) {
2265
	mov	edi, dword [forcedeth_mapio_addr]
2266
	mov	eax, dword [edi+NvRegReceiverControl]
2267
	test	eax, NVREG_RCVCTL_START
2268
	jz	@f
2269
	; writel(0, base + NvRegReceiverControl)
2270
	mov	dword [edi+NvRegReceiverControl], 0
2271
	; pci_push(base)
2272
	call	forcedeth_pci_push
2273
 
2274
@@:
2275
 
2276
	; writel(np->linkspeed, base + NvRegLinkSpeed);
2277
	mov	eax, dword [forcedeth_linkspeed]
2278
	mov	dword [edi+NvRegLinkSpeed], eax
2279
	; pci_push(base);
2280
	call	forcedeth_pci_push
2281
	; writel(NVREG_RCVCTL_START, base + NvRegReceiverControl);
2282
	mov	dword [edi+NvRegReceiverControl], NVREG_RCVCTL_START
2283
	; pci_push(base);
2284
	call	forcedeth_pci_push
2285
 
2286
.return:
2287
	pop	edi
2288
	ret
2289
 
2290
; Input:  none
2291
; Output: none
2292
forcedeth_stop_rx:
2293
	push	esi edi
2294
 
2295
	; dprintf(("stop_rx\n"))
2296
	DEBUGF 1," K : FORCEDETH: stop_rx.\n"
2297
 
2298
	; writel(0, base + NvRegReceiverControl)
2299
	mov	edi, dword [forcedeth_mapio_addr]
2300
	mov	dword [edi+NvRegReceiverControl], 0
2301
 
2302
	push	ebx edx edi	;;;;;;;;;;;;;;;;;;;;;;
2303
	; reg_delay(NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, "stop_rx: ReceiverStatus remained busy");
2304
	stdcall forcedeth_reg_delay,NvRegReceiverStatus,NVREG_RCVSTAT_BUSY,0,NV_RXSTOP_DELAY1,NV_RXSTOP_DELAY1MAX,0
2305
	pop	edi edx ebx	;;;;;;;;;;;;;;;;;;;;;;
2306
 
2307
 
2308
	; nv_udelay(NV_RXSTOP_DELAY2)
2309
	mov	esi, NV_RXSTOP_DELAY2
2310
	call	forcedeth_nv_udelay
2311
 
2312
	; writel(0, base + NvRegLinkSpeed)
2313
	mov	dword [edi+NvRegLinkSpeed], 0
2314
 
2315
.return:
2316
	pop	edi esi
2317
	ret
2318
 
2319
; Input:  none
2320
; Output: EAX
2321
forcedeth_update_linkspeed:
2322
	push	ebx ecx esi edi
2323
 
2324
	; BMSR_LSTATUS is latched, read it twice:
2325
	; we want the current value.
2326
 
2327
	; mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ)
2328
        ;EBX - addr, EAX - miireg, ECX - value
2329
	mov	ebx, dword [forcedeth_phyaddr]
2330
	mov	eax, MII_BMSR
2331
	mov	ecx, MII_READ
2332
	call	forcedeth_mii_rw
2333
 
2334
 
2335
	; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ)
2336
        ;EBX - addr, EAX - miireg, ECX - value
2337
	mov	ebx, dword [forcedeth_phyaddr]
2338
	mov	eax, MII_BMSR
2339
	mov	ecx, MII_READ
2340
	call	forcedeth_mii_rw	; mii_status = eax
2341
 
2342
	; yhlu
2343
 
2344
	; for(i=0;i<30;i++) {
2345
	mov	ecx, 30
2346
.for_loop:
2347
	push	ecx
2348
 
2349
	;  mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
2350
        ;EBX - addr, EAX - miireg, ECX - value
2351
	;mov	ebx, dword [forcedeth_phyaddr]
2352
	mov	eax, MII_BMSR
2353
	mov	ecx, MII_READ
2354
	call	forcedeth_mii_rw	; mii_status = eax
2355
 
2356
	;  if((mii_status & BMSR_LSTATUS) && (mii_status & BMSR_ANEGCOMPLETE)) break;
2357
	test	eax, BMSR_LSTATUS
2358
	jz	@f
2359
	test	eax, BMSR_ANEGCOMPLETE
2360
	jz	@f
2361
	; break
2362
	pop	ecx
2363
	jmp	.break
2364
 
2365
@@:
2366
 
2367
	;  mdelay(100);
2368
	push	eax	; ???
2369
	mov	esi, 100
2370
	call	forcedeth_udelay
2371
	pop	eax	; ???
2372
 
2373
	pop	ecx
2374
	loop	.for_loop
2375
 
2376
.break:
2377
 
2378
	; if (!(mii_status & BMSR_LSTATUS)) {
2379
	test	eax, BMSR_LSTATUS
2380
	jnz	@f
2381
 
2382
	; printf("no link detected by phy - falling back to 10HD.\n")
2383
	DEBUGF 1," K : FORCEDETH: update_linkspeed: no link detected by phy - falling back to 10HD.\n"
2384
 
2385
	; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
2386
	mov	dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
2387
 
2388
	; newdup = 0;
2389
	mov	dword [forcedeth_tmp_newdup], 0
2390
	; retval = 0;
2391
	mov	dword [forcedeth_tmp_retval], 0
2392
 
2393
	; goto set_speed;
2394
	jmp	.set_speed
2395
 
2396
@@:
2397
 
2398
	; check auto negotiation is complete
2399
	; if (!(mii_status & BMSR_ANEGCOMPLETE)) {
2400
	test	eax, BMSR_ANEGCOMPLETE
2401
	jnz	@f
2402
 
2403
	; still in autonegotiation - configure nic for 10 MBit HD and wait.
2404
	; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
2405
	mov	dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
2406
 
2407
	; newdup = 0
2408
	mov	dword [forcedeth_tmp_newdup], 0
2409
 
2410
	; retval = 0
2411
	mov	dword [forcedeth_tmp_retval], 0
2412
 
2413
	; printf("autoneg not completed - falling back to 10HD.\n")
2414
	DEBUGF 1," K : FORCEDETH: update_linkspeed: autoneg not completed - falling back to 10HD.\n"
2415
 
2416
	; goto set_speed
2417
	jmp	.set_speed
2418
 
2419
@@:
2420
 
2421
	; retval = 1
2422
	mov	dword [forcedeth_tmp_retval], 1
2423
 
2424
	; if (np->gigabit == PHY_GIGABIT) {
2425
	cmp	dword [forcedeth_gigabit], PHY_GIGABIT
2426
	jne	.end_if
2427
	; control_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ)
2428
        ;EBX - addr, EAX - miireg, ECX - value
2429
	;mov	ebx, dword [forcedeth_phyaddr]
2430
	mov	eax, MII_1000BT_CR
2431
	mov	ecx, MII_READ
2432
	call	forcedeth_mii_rw	; control_1000 = eax
2433
	mov	dword [forcedeth_tmp_control_1000], eax
2434
 
2435
	; status_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_SR, MII_READ)
2436
        ;EBX - addr, EAX - miireg, ECX - value
2437
	;mov	ebx, dword [forcedeth_phyaddr]
2438
	mov	eax, MII_1000BT_SR
2439
	mov	ecx, MII_READ
2440
	call	forcedeth_mii_rw	; status_1000 = eax
2441
	;mov	dword [forcedeth_tmp_status_1000], eax
2442
 
2443
	; if ((control_1000 & ADVERTISE_1000FULL) &&
2444
	;     (status_1000 & LPA_1000FULL)) {
2445
	test	eax, LPA_1000FULL
2446
	jz	.end_if
2447
	test    dword [forcedeth_tmp_control_1000], ADVERTISE_1000FULL
2448
	jz	.end_if
2449
 
2450
	; printf ("update_linkspeed: GBit ethernet detected.\n")
2451
	DEBUGF 1," K : FORCEDETH: update_linkspeed: GBit ethernet detected.\n"
2452
 
2453
	; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_1000
2454
	mov	dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_1000)
2455
 
2456
	; newdup = 1
2457
	mov	dword [forcedeth_tmp_newdup], 1
2458
 
2459
	; goto set_speed
2460
	jmp	.set_speed
2461
 
2462
.end_if:
2463
 
2464
	; adv = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ);
2465
        ;EBX - addr, EAX - miireg, ECX - value
2466
	;mov	ebx, dword [forcedeth_phyaddr]
2467
	mov	eax, MII_ADVERTISE
2468
	mov	ecx, MII_READ
2469
	call	forcedeth_mii_rw	; adv = eax
2470
	mov	dword [forcedeth_tmp_adv], eax
2471
 
2472
	; lpa = mii_rw(nic, np->phyaddr, MII_LPA, MII_READ);
2473
        ;EBX - addr, EAX - miireg, ECX - value
2474
	;mov	ebx, dword [forcedeth_phyaddr]
2475
	mov	eax, MII_LPA
2476
	mov	ecx, MII_READ
2477
	call	forcedeth_mii_rw	; lpa = eax
2478
	mov	dword [forcedeth_tmp_lpa], eax
2479
 
2480
	; dprintf(("update_linkspeed: PHY advertises 0x%hX, lpa 0x%hX.\n", adv, lpa));
2481
	DEBUGF 1," K : FORCEDETH: update_linkspeed: PHY advertises 0x%x, lpa 0x%x.\n", [forcedeth_tmp_adv]:8, [forcedeth_tmp_lpa]:8
2482
 
2483
	; FIXME: handle parallel detection properly, handle gigabit ethernet
2484
	; lpa = lpa & adv
2485
	mov	eax, dword [forcedeth_tmp_adv]
2486
	and	dword [forcedeth_tmp_lpa], eax
2487
 
2488
	mov	eax, dword [forcedeth_tmp_lpa]
2489
 
2490
	; if (lpa & LPA_100FULL) {
2491
	test	eax, LPA_100FULL
2492
	jz	@f
2493
	; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100
2494
	mov	dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100)
2495
	; newdup = 1
2496
	mov	dword [forcedeth_tmp_newdup], 1
2497
	jmp	.set_speed
2498
@@:
2499
	; } else if (lpa & LPA_100HALF) {
2500
	test	eax, LPA_100HALF
2501
	jz	@f
2502
	; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100
2503
	mov	dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100)
2504
	; newdup = 0
2505
	mov	dword [forcedeth_tmp_newdup], 0
2506
	jmp	.set_speed
2507
@@:
2508
	; } else if (lpa & LPA_10FULL) {
2509
	test	eax, LPA_10FULL
2510
	jz	@f
2511
	; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
2512
	mov	dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
2513
	; newdup = 1
2514
	mov	dword [forcedeth_tmp_newdup], 1
2515
	jmp	.set_speed
2516
@@:
2517
	; } else if (lpa & LPA_10HALF) {
2518
	test	eax, LPA_10HALF
2519
	;    newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
2520
	mov	dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
2521
	;    newdup = 0;
2522
	mov	dword [forcedeth_tmp_newdup], 0
2523
	jmp	.set_speed
2524
@@:
2525
	; } else {
2526
	; printf("bad ability %hX - falling back to 10HD.\n", lpa)
2527
	DEBUGF 1," K : FORCEDETH: update_linkspeed: bad ability 0x%x - falling back to 10HD.\n", eax
2528
 
2529
	; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
2530
	mov	dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
2531
	; newdup = 0
2532
	mov	dword [forcedeth_tmp_newdup], 0
2533
	; }
2534
 
2535
.set_speed:
2536
 
2537
	; if (np->duplex == newdup && np->linkspeed == newls)
2538
	mov	eax, dword [forcedeth_tmp_newdup]
2539
	cmp	eax, dword [forcedeth_duplex]
2540
	jne	.end_if2
2541
	mov	eax, dword [forcedeth_tmp_newls]
2542
	cmp	eax, dword [forcedeth_linkspeed]
2543
	jne	.end_if2
2544
	;    return retval;
2545
	jmp	.return
2546
 
2547
.end_if2:
2548
 
2549
	; dprintf(("changing link setting from %d/%s to %d/%s.\n",
2550
	;    np->linkspeed, np->duplex ? "Full-Duplex": "Half-Duplex", newls, newdup ? "Full-Duplex": "Half-Duplex"))
2551
	DEBUGF 1," K : FORCEDETH: update_linkspeed: changing link from %x/XD to %x/XD.\n", [forcedeth_linkspeed]:8, [forcedeth_tmp_newls]:8	; !!!!!!!!!!!!!!!!!!!!!!!!!!!!
2552
 
2553
	; np->duplex = newdup
2554
	mov	eax, dword [forcedeth_tmp_newdup]
2555
	mov	dword [forcedeth_duplex], eax
2556
 
2557
	; np->linkspeed = newls
2558
	mov	eax, [forcedeth_tmp_newls]
2559
	mov	dword [forcedeth_linkspeed], eax
2560
 
2561
	; if (np->gigabit == PHY_GIGABIT) {
2562
	cmp	dword [forcedeth_gigabit], PHY_GIGABIT
2563
	jne	.end_if3
2564
 
2565
	; phyreg = readl(base + NvRegRandomSeed);
2566
	mov	edi, dword [forcedeth_mapio_addr]
2567
	mov	eax, dword [edi+NvRegRandomSeed]
2568
 
2569
	; phyreg &= ~(0x3FF00);
2570
	and	eax, not (0x3FF00)
2571
	mov	ecx, eax		; phyreg = ecx
2572
 
2573
	; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10)
2574
	mov	eax, dword [forcedeth_linkspeed]
2575
	and	eax, 0xFFF
2576
	cmp	eax, NVREG_LINKSPEED_10
2577
	jne	@f
2578
	; phyreg |= NVREG_RNDSEED_FORCE3
2579
	or	ecx, NVREG_RNDSEED_FORCE3
2580
	jmp	.end_if4
2581
@@:
2582
	; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
2583
	cmp	eax, NVREG_LINKSPEED_100
2584
	jne	@f
2585
	; phyreg |= NVREG_RNDSEED_FORCE2
2586
	or	ecx, NVREG_RNDSEED_FORCE2
2587
	jmp	.end_if4
2588
@@:
2589
	; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
2590
	cmp	eax, NVREG_LINKSPEED_1000
2591
	jne	.end_if4
2592
	; phyreg |= NVREG_RNDSEED_FORCE
2593
	or	ecx, NVREG_RNDSEED_FORCE
2594
.end_if4:
2595
	; writel(phyreg, base + NvRegRandomSeed)
2596
	mov	dword [edi+NvRegRandomSeed], ecx
2597
 
2598
.end_if3:
2599
 
2600
	; phyreg = readl(base + NvRegPhyInterface)
2601
	mov	ecx, dword [edi+NvRegPhyInterface]
2602
 
2603
	; phyreg &= ~(PHY_HALF | PHY_100 | PHY_1000)
2604
	and	ecx, not (PHY_HALF or PHY_100 or PHY_1000)
2605
 
2606
	; if (np->duplex == 0)
2607
	cmp	dword [forcedeth_duplex], 0
2608
	jne	@f
2609
	; phyreg |= PHY_HALF
2610
	or	ecx, PHY_HALF
2611
@@:
2612
	; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
2613
	mov	eax, dword [forcedeth_linkspeed]
2614
	and	eax, 0xFFF
2615
	cmp	eax, NVREG_LINKSPEED_100
2616
	jne	@f
2617
	; phyreg |= PHY_100
2618
	or	ecx, PHY_100
2619
	jmp	.end_if5
2620
@@:
2621
	; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
2622
	cmp	eax, NVREG_LINKSPEED_1000
2623
	jne	.end_if5
2624
	; phyreg |= PHY_1000
2625
	or	ecx, PHY_1000
2626
 
2627
.end_if5:
2628
 
2629
	; writel(phyreg, base + NvRegPhyInterface)
2630
	mov	dword [edi+NvRegPhyInterface], ecx
2631
 
2632
	; writel(NVREG_MISC1_FORCE | (np->duplex ? 0 : NVREG_MISC1_HD), base + NvRegMisc1);
2633
	cmp	dword [forcedeth_duplex], 0
2634
	je	@f
2635
	mov	ecx, 0
2636
	jmp	.next
2637
@@:
2638
	mov	ecx, NVREG_MISC1_HD
2639
.next:
2640
	or	ecx, NVREG_MISC1_FORCE
2641
	mov	dword [edi+NvRegMisc1], ecx
2642
 
2643
	; pci_push(base)
2644
	call	forcedeth_pci_push
2645
 
2646
	; writel(np->linkspeed, base + NvRegLinkSpeed)
2647
	mov	eax, dword [forcedeth_linkspeed]
2648
	mov	dword [edi+NvRegLinkSpeed], eax
2649
 
2650
	; pci_push(base)
2651
	call	forcedeth_pci_push
2652
 
2653
.return:
2654
	; return retval
2655
	mov	eax, dword [forcedeth_tmp_retval]
2656
	pop	edi esi ecx ebx
2657
	ret
2658
 
2659
 
2660
; Input:  none
2661
; Output: none
2662
forcedeth_start_tx:
2663
	push	edi
2664
	; dprintf(("start_tx\n"))
2665
	DEBUGF 1," K : FORCEDETH: start_tx.\n"
2666
 
2667
	; writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl)
2668
	mov	edi, dword [forcedeth_mapio_addr]
2669
	mov	dword [edi+NvRegTransmitterControl], NVREG_XMITCTL_START
2670
 
2671
	; pci_push(base)
2672
	call	forcedeth_pci_push
2673
 
2674
.return:
2675
	pop	edi
2676
	ret
2677
 
2678
; Interrupt handler
2679
forcedeth_int_handler:
2680
	DEBUGF 1," K : FORCEDETH: interrupt handler.\n"
2681
 
2682
	ret
2683