Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
2434 Serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2465 Serge 3
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved.    ;;
2434 Serge 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: 2465 $
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
@@:
823
        push    eax
824
        and     eax, PCI_BASE_ADDRESS_MEM_TYPE_MASK
825
        cmp     eax, PCI_BASE_ADDRESS_MEM_TYPE_64
826
        jne     .not64
827
        mov     al, 2   ; dword
828
        mov     bh, [pci_dev]
829
        mov     ah, [pci_bus]
830
        mov     bl, PCI_BASE_ADDRESS_0 + 4
831
        call    pci_read_reg
832
        or      eax, eax
833
        jz      .not64
834
        DEBUGF  1,"K : FORCEDETH: pci_bar_start: Unhandled 64bit BAR\n"
835
        or      eax, -1
836
        jmp     .next
837
.not64:
838
        pop     eax
839
        and     eax, PCI_BASE_ADDRESS_MEM_MASK
840
.next:
841
; END of pci_bar_start
842
; addr = eax
843
        mov     dword [forcedeth_mmio_addr], eax
844
 
845
 
846
; BEGIN of pci_bar_size (sz = pci_bar_size(pci, PCI_BASE_ADDRESS_0))
847
 
848
        ; Save original bar
849
        mov     al, 2   ; dword
850
        mov     bh, [pci_dev]
851
        mov     ah, [pci_bus]
852
        mov     bl, PCI_BASE_ADDRESS_0
853
        call    pci_read_reg
854
        mov     dword [forcedeth_tmp_start], eax
855
        ; Compute which bits can be set
856
        ; (ecx - value to write)
857
        mov     al, 2   ; dword
858
        mov     bh, [pci_dev]
859
        mov     ah, [pci_bus]
860
        mov     bl, PCI_BASE_ADDRESS_0
861
        mov     ecx, (not 0)
862
        call    pci_write_reg
863
        mov     al, 2   ; dword
864
        mov     bh, [pci_dev]
865
        mov     ah, [pci_bus]
866
        mov     bl, PCI_BASE_ADDRESS_0
867
        call    pci_read_reg
868
        push    eax
869
        ; Restore the original size
870
        mov     al, 2   ; dword
871
        mov     bh, [pci_dev]
872
        mov     ah, [pci_bus]
873
        mov     bl, PCI_BASE_ADDRESS_0
874
        mov     ecx, dword [forcedeth_tmp_start]
875
        call    pci_write_reg
876
        ; Find the significant bits
877
        pop     eax
878
        test    dword [forcedeth_tmp_start], PCI_BASE_ADDRESS_SPACE_IO
879
        jz      @f
880
        and     eax, PCI_BASE_ADDRESS_IO_MASK
881
        jmp     .next2
882
@@:
883
        and     eax, PCI_BASE_ADDRESS_MEM_MASK
884
.next2:
885
        ; Find the lowest bit set
886
        mov     ecx, eax
887
        sub     eax, 1
888
        not     eax
889
        and     ecx, eax
890
 
891
; END of pci_bar_start
892
        mov     dword [forcedeth_mmio_size], ecx
893
 
894
        DEBUGF 1," K : FORCEDETH: mmio_addr= 0x%x [mmio_size= 0x%x]\n", [forcedeth_mmio_addr]:8, [forcedeth_mmio_size]:8
895
 
896
        ; Get Vendor and Device ID
897
        mov     al, 2
898
        mov     bh, [pci_dev]
899
        mov     ah, [pci_bus]
900
        mov     bl, PCI_VENDOR_ID
901
        call    pci_read_reg
902
        mov     word [forcedeth_vendor_id], ax
903
        shr     eax, 16
904
        mov     word [forcedeth_device_id], ax
905
 
906
        DEBUGF 1," K : FORCEDETH: vendor_id= 0x%x device_id= 0x%x\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4
907
 
908
        ; handle different descriptor versions
909
        mov     eax, dword [forcedeth_device_id]
910
        cmp     eax, PCI_DEVICE_ID_NVIDIA_NVENET_1
911
        je      .ver1
912
        cmp     eax, PCI_DEVICE_ID_NVIDIA_NVENET_2
913
        je      .ver1
914
        cmp     eax, PCI_DEVICE_ID_NVIDIA_NVENET_3
915
        je      .ver1
916
        mov     dword [forcedeth_desc_ver], DESC_VER_2
917
        jmp     @f
918
.ver1:
919
        mov     dword [forcedeth_desc_ver], DESC_VER_1
920
@@:
921
        ; read the mac address
922
        ; map memory
923
        stdcall map_io_mem, [forcedeth_mmio_addr], [forcedeth_mmio_size], (PG_SW+PG_NOCACHE)
924
        test    eax, eax
925
        jz      .fail
926
 
927
        mov     dword [forcedeth_mapio_addr], eax
928
        mov     edi, eax
929
        mov     eax, dword [edi+NvRegMacAddrA]
930
        mov     dword [forcedeth_orig_mac0], eax
931
        mov     edx, dword [edi+NvRegMacAddrB]
932
        mov     dword [forcedeth_orig_mac1], edx
933
 
934
        ; save MAC-address to global variable node_addr
935
        mov     dword [node_addr], eax
936
        mov     word [node_addr+4], dx
937
 
938
        ; reverse if desired
939
        cmp     word [forcedeth_device_id], 0x03E5
940
        jae     .no_reverse_mac
941
        mov     al, byte [node_addr]
942
        xchg    al, byte [node_addr+5]
943
        mov     byte [node_addr], al
944
        mov     al, byte [node_addr+1]
945
        xchg    al, byte [node_addr+4]
946
        mov     byte [node_addr+4], al
947
        mov     al, byte [node_addr+2]
948
        xchg    al, byte [node_addr+3]
949
        mov     byte [node_addr+3], al
950
.no_reverse_mac:
951
 
952
;       DEBUGF 1," K : FORCEDETH: orig_mac0= 0x%x\n", [forcedeth_orig_mac0]:8
953
;       DEBUGF 1," K : FORCEDETH: orig_mac1= 0x%x\n", [forcedeth_orig_mac1]:8
954
        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,
955
 
956
        ; disable WOL
957
        mov     edi, dword [forcedeth_mapio_addr]
958
        mov     dword [edi+NvRegWakeUpFlags], 0
959
        mov     dword [forcedeth_wolenabled], 0
960
 
961
        mov     dword [forcedeth_txflags], (NV_TX2_LASTPACKET or NV_TX2_VALID)
962
        cmp     dword [forcedeth_desc_ver], DESC_VER_1
963
        jne     @f
964
        mov     dword [forcedeth_txflags], (NV_TX_LASTPACKET or NV_TX_VALID)
965
@@:
966
 
967
; BEGIN of switch (pci->dev_id)
968
 
969
        cmp     word [forcedeth_device_id], 0x01C3
970
        jne     .next_0x0066
971
        ; nforce
972
        mov     dword [forcedeth_irqmask], 0    ;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
973
        jmp     .end_switch
974
 
975
.next_0x0066:
976
        cmp     word [forcedeth_device_id], 0x0066
977
        je      @f
978
        cmp     word [forcedeth_device_id], 0x00D6
979
        je      @f
980
        jmp     .next_0x0086
981
@@:
982
        mov     dword [forcedeth_irqmask], 0    ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
983
        cmp     dword [forcedeth_desc_ver], DESC_VER_1
984
        jne     @f
985
        or      dword [forcedeth_txflags], NV_TX_LASTPACKET1
986
        jmp     .end_switch
987
@@:
988
        or      dword [forcedeth_txflags], NV_TX2_LASTPACKET1
989
        jmp     .end_switch
990
 
991
.next_0x0086:
992
        cmp     word [forcedeth_device_id], 0x0086
993
        je      @f
994
        cmp     word [forcedeth_device_id], 0x008c
995
        je      @f
996
        cmp     word [forcedeth_device_id], 0x00e6
997
        je      @f
998
        cmp     word [forcedeth_device_id], 0x00df
999
        je      @f
1000
        cmp     word [forcedeth_device_id], 0x0056
1001
        je      @f
1002
        cmp     word [forcedeth_device_id], 0x0057
1003
        je      @f
1004
        cmp     word [forcedeth_device_id], 0x0037
1005
        je      @f
1006
        cmp     word [forcedeth_device_id], 0x0038
1007
        je      @f
1008
        jmp     .next_0x0268
1009
@@:
1010
        ; np->irqmask = NVREG_IRQMASK_WANTED_2;
1011
        ; np->irqmask |= NVREG_IRQ_TIMER;
1012
        mov     dword [forcedeth_irqmask], 0    ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
1013
 
1014
        ; if (np->desc_ver == DESC_VER_1)
1015
        cmp     dword [forcedeth_desc_ver], DESC_VER_1
1016
        jne     @f
1017
        ;  np->tx_flags |= NV_TX_LASTPACKET1;
1018
        or      dword [forcedeth_txflags], NV_TX_LASTPACKET1
1019
        jmp     .end_switch
1020
        ; else
1021
@@:
1022
        ;  np->tx_flags |= NV_TX2_LASTPACKET1;
1023
        or      dword [forcedeth_txflags], NV_TX2_LASTPACKET1
1024
 
1025
        ; break;
1026
        jmp     .end_switch
1027
 
1028
.next_0x0268:
1029
;       cmp     word [forcedeth_device_id], 0x0268
1030
;       je      @f
1031
;       cmp     word [forcedeth_device_id], 0x0269
1032
;       je      @f
1033
;       cmp     word [forcedeth_device_id], 0x0372
1034
;       je      @f
1035
;       cmp     word [forcedeth_device_id], 0x0373
1036
;       je      @f
1037
;       jmp     .default_switch
1038
;@@:
1039
        cmp     word [forcedeth_device_id], 0x0268
1040
        jb      .default_switch
1041
        ; pci_read_config_byte(pci, PCI_REVISION_ID, &revision_id);
1042
        mov     al, 0   ; byte
1043
        mov     bh, [pci_dev]
1044
        mov     ah, [pci_bus]
1045
        mov     bl, PCI_REVISION_ID
1046
        call    pci_read_reg
1047
        mov     ecx, eax        ; cl = revision_id
1048
 
1049
        ; take phy and nic out of low power mode
1050
        ; powerstate = readl(base + NvRegPowerState2);
1051
        mov     edi, dword [forcedeth_mapio_addr]
1052
        mov     eax, dword [edi+NvRegPowerState2]       ; eax = powerstate
1053
 
1054
        ; powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK;
1055
        and     eax, not NVREG_POWERSTATE2_POWERUP_MASK
1056
 
1057
        ; if ((pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_12||pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_13)&&revision_id>=0xA3)
1058
        cmp     dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_12
1059
        je      @f
1060
        cmp     dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_13
1061
        je      @f
1062
        jmp     .end_if
1063
@@:
1064
        cmp     cl, 0xA3
1065
        jl      .end_if
1066
        ;     powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3;
1067
        or      eax, NVREG_POWERSTATE2_POWERUP_REV_A3
1068
 
1069
.end_if:
1070
 
1071
        ; writel(powerstate, base + NvRegPowerState2);
1072
        mov     dword [edi+NvRegPowerState2], eax
1073
 
1074
        ; //DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ
1075
        ; np->irqmask = NVREG_IRQMASK_WANTED_2;
1076
        ; np->irqmask |= NVREG_IRQ_TIMER;
1077
        mov     dword [forcedeth_irqmask], 0    ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
1078
 
1079
        ; needs_mac_reset = 1;
1080
        mov     dword [forcedeth_needs_mac_reset], 1
1081
 
1082
        ; if (np->desc_ver == DESC_VER_1)
1083
        cmp     dword [forcedeth_desc_ver], DESC_VER_1
1084
        jne     @f
1085
        ;   np->tx_flags |= NV_TX_LASTPACKET1;
1086
        or      dword [forcedeth_txflags], NV_TX_LASTPACKET1
1087
        jmp     .end_if2
1088
@@:
1089
        ; else
1090
        ;   np->tx_flags |= NV_TX2_LASTPACKET1;
1091
        or      dword [forcedeth_txflags], NV_TX2_LASTPACKET1
1092
 
1093
.end_if2:
1094
        ; break;
1095
        jmp     .end_switch
1096
 
1097
.default_switch:
1098
        DEBUGF 1," K : FORCEDETH: Your card was undefined in this driver.\n"
1099
        DEBUGF 1," K : FORCEDETH: Review driver_data in Kolibri driver and send a patch\n"
1100
 
1101
.end_switch:
1102
 
1103
; END of switch (pci->dev_id)
1104
 
1105
 
1106
        ; Find a suitable phy
1107
        mov     dword [forcedeth_tmp_i], 1
1108
.for_loop:
1109
        ; for (i = 1; i <= 32; i++)
1110
        ; phyaddr = i & 0x1f
1111
        mov     ebx, dword [forcedeth_tmp_i]
1112
        and     ebx, 0x1f
1113
 
1114
        ; id1 = mii_rw(phyaddr, MII_PHYSID1, MII_READ)
1115
        ;EBX - addr, EAX - miireg, ECX - value
1116
        mov     eax, MII_PHYSID1
1117
        mov     ecx, MII_READ
1118
        call    forcedeth_mii_rw        ; id1 = eax
1119
 
1120
        ; if (id1 < 0 || id1 == 0xffff)
1121
        cmp     eax, 0xffffffff
1122
        je      .continue_for
1123
        test    eax, 0x80000000
1124
        jnz     .continue_for
1125
        mov     dword [forcedeth_tmp_id1], eax
1126
 
1127
        ; id2 = mii_rw(nic, phyaddr, MII_PHYSID2, MII_READ)
1128
        mov     eax, MII_PHYSID2
1129
        mov     ecx, MII_READ
1130
        call    forcedeth_mii_rw        ; id2 = eax
1131
 
1132
        ; if (id2 < 0 || id2 == 0xffff)
1133
        cmp     eax, 0xffffffff
1134
        je      .continue_for
1135
        test    eax, 0x80000000
1136
        jnz     .continue_for
1137
        mov     dword [forcedeth_tmp_id2], eax
1138
 
1139
        jmp     .break_for
1140
.continue_for:
1141
        inc     dword [forcedeth_tmp_i]
1142
        cmp     dword [forcedeth_tmp_i], 32
1143
        jle     .for_loop
1144
        jmp     .end_for
1145
 
1146
.break_for:
1147
 
1148
;;;;    DEBUGF 1," K : FORCEDETH: id1=0x%x id2=0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8
1149
 
1150
        ; id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT
1151
        mov     eax, dword [forcedeth_tmp_id1]
1152
        and     eax, PHYID1_OUI_MASK
1153
        shl     eax, PHYID1_OUI_SHFT
1154
        mov     dword [forcedeth_tmp_id1], eax
1155
 
1156
        ; id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT
1157
        mov     eax, dword [forcedeth_tmp_id2]
1158
        and     eax, PHYID2_OUI_MASK
1159
        shr     eax, PHYID2_OUI_SHFT
1160
        mov     dword [forcedeth_tmp_id2], eax
1161
 
1162
        DEBUGF 1," K : FORCEDETH: Found PHY  0x%x:0x%x at address 0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8, ebx
1163
 
1164
        ; np->phyaddr = phyaddr;
1165
        mov     dword [forcedeth_phyaddr], ebx
1166
 
1167
        ; np->phy_oui = id1 | id2;
1168
        mov     eax, dword [forcedeth_tmp_id1]
1169
        or      eax, dword [forcedeth_tmp_id2]
1170
        mov     dword [forcedeth_phy_oui], eax
1171
 
1172
.end_for:
1173
 
1174
        ; if (i == 33)
1175
        cmp     dword [forcedeth_tmp_i], 33
1176
        jne     @f
1177
        ; PHY in isolate mode? No phy attached and user wants to
1178
        ; test loopback? Very odd, but can be correct.
1179
 
1180
        DEBUGF 1," K : FORCEDETH: Could not find a valid PHY.\n"
1181
 
1182
        jmp     .next3
1183
 
1184
@@:
1185
 
1186
        ; if (i != 33)
1187
        ; reset it
1188
        call    forcedeth_phy_init
1189
 
1190
.next3:
1191
 
1192
;        dprintf(("%s: forcedeth.c: subsystem: %hX:%hX bound to %s\n",
1193
;                 pci->name, pci->vendor, pci->dev_id, pci->name));
1194
        DEBUGF 1," K : FORCEDETH: subsystem: 0x%x:0x%x bound to forcedeth\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4
1195
 
1196
 
1197
;        if(needs_mac_reset) mac_reset(nic);
1198
        cmp     dword [forcedeth_needs_mac_reset], 0
1199
        je      @f
1200
        call    forcedeth_mac_reset
1201
 
1202
@@:
1203
 
1204
        ; if(!forcedeth_reset(nic)) return 0; // no valid link
1205
        call    forcedeth_reset
1206
        test    eax, eax
1207
        jnz     @f
1208
        mov     eax, 0
1209
        jmp     .return
1210
 
1211
@@:
1212
 
1213
        ; point to NIC specific routines
1214
        ; dev->disable = forcedeth_disable;
1215
        ; nic->poll = forcedeth_poll;
1216
        ; nic->transmit = forcedeth_transmit;
1217
        ; nic->irq = forcedeth_irq;
1218
        ;;;;;;;;;stdcall attach_int_handler, 11, forcedeth_int_handler, 0
1219
 
1220
        ; return 1
1221
        mov     eax, 1
1222
        jmp     .return
1223
 
1224
.fail:
1225
        mov     eax, 0
1226
 
1227
.return:
1228
        ret
1229
 
1230
uglobal
1231
forcedeth_tmp_start     dd ?
1232
forcedeth_tmp_reg       dd ?
1233
forcedeth_tmp_i         dd ?
1234
forcedeth_tmp_id1       dd ?
1235
forcedeth_tmp_id2       dd ?
1236
forcedeth_tmp_phyinterface      dd ?
1237
forcedeth_tmp_newls     dd ?
1238
forcedeth_tmp_newdup    dd ?
1239
forcedeth_tmp_retval    dd ?
1240
forcedeth_tmp_control_1000      dd ?
1241
forcedeth_tmp_lpa       dd ?
1242
forcedeth_tmp_adv       dd ?
1243
forcedeth_tmp_len       dd ?
1244
forcedeth_tmp_valid     dd ?
1245
forcedeth_tmp_nr        dd ?
1246
forcedeth_tmp_ptxb      dd ?
1247
endg
1248
 
1249
;***************************************************************************
1250
; Function
1251
;    forcedeth_poll
1252
;
1253
; Description
1254
;    Polls the ethernet card for a received packet
1255
;    Received data, if any, ends up in Ether_buffer
1256
;
1257
;***************************************************************************
1258
forcedeth_poll:
1259
 
1260
        mov     word [eth_rx_data_len], 0
1261
 
1262
        ; ????????????????????????????
1263
        ; ??? Clear events? ???
1264
        mov     edi, dword [forcedeth_mapio_addr]
1265
        mov     dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK
1266
        ; ????????????????????????????
1267
 
1268
.top:
1269
 
1270
        ; i = np->cur_rx % RX_RING
1271
        mov     eax, dword [forcedeth_cur_rx]
1272
        and     eax, (RX_RING-1)
1273
        mov     dword [forcedeth_tmp_i], eax
1274
 
1275
        ; Flags = le32_to_cpu(rx_ring[i].FlagLen)
1276
        ; Flags = rx_ring[i].FlagLen
1277
        mov     cl, sizeof.forcedeth_RxDesc
1278
        mul     cl
1279
        add     eax, forcedeth_rx_ring
1280
        mov     ebx, eax
1281
        mov     eax, [ebx + forcedeth_RxDesc.FlagLen]
1282
 
1283
 
1284
        ; if (Flags & NV_RX_AVAIL)
1285
        test    eax, NV_RX_AVAIL
1286
        ;   return 0;       /* still owned by hardware, */
1287
        ; still owned by hardware
1288
        jnz     .return0
1289
 
1290
;;;;;   DEBUGF  1,"poll: FlagLen = %x\n", eax
1291
 
1292
        ; if (np->desc_ver == DESC_VER_1) {
1293
        cmp     dword [forcedeth_desc_ver], DESC_VER_1
1294
        jne     @f
1295
        ;   if (!(Flags & NV_RX_DESCRIPTORVALID))
1296
        test    eax, NV_RX_DESCRIPTORVALID
1297
        ;     return 0;
1298
        jz      .return0
1299
        jmp     .next
1300
        ; } else {
1301
@@:
1302
        ;   if (!(Flags & NV_RX2_DESCRIPTORVALID))
1303
        test    eax, NV_RX2_DESCRIPTORVALID
1304
        ;     return 0;
1305
        jz      .return0
1306
        ; }
1307
 
1308
.next:
1309
 
1310
        ; len = nv_descr_getlength(&rx_ring[i], np->desc_ver)
1311
        ; len = rx_ring[i].FlagLen & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2);
1312
        ; eax = FlagLen
1313
        cmp     dword [forcedeth_desc_ver], DESC_VER_1
1314
        jne     @f
1315
        and     eax, LEN_MASK_V1
1316
        jmp     .next2
1317
@@:
1318
        and     eax, LEN_MASK_V2
1319
 
1320
.next2:
1321
 
1322
        ; mov   dword [forcedeth_tmp_len], eax
1323
 
1324
        ; valid = 1
1325
        mov     dword [forcedeth_tmp_valid], 1
1326
 
1327
        ; got a valid packet - forward it to the network core
1328
        ; nic->packetlen = len;
1329
        mov     dword [forcedeth_packetlen], eax
1330
        ;
1331
        mov     word [eth_rx_data_len], ax
1332
;;;;;;;;;        DEBUGF 1,"poll: packet len = 0x%x\n", [forcedeth_packetlen]
1333
 
1334
 
1335
        ; memcpy(nic->packet, rxb + (i * RX_NIC_BUFSIZE), nic->packetlen);
1336
        ; Copy packet to system buffer (Ether_buffer)
1337
        ;???? ecx = (len-4)
1338
        mov     ecx, eax
1339
        push    ecx
1340
        shr     ecx, 2
1341
 
1342
        ; rxb + (i * RX_NIC_BUFSIZE)
1343
        mov     eax, dword [forcedeth_tmp_i]
1344
        mov     bx, RX_NIC_BUFSIZE
1345
        mul     bx
1346
        add     eax, forcedeth_rxb
1347
 
1348
        mov     esi, eax
1349
        mov     edi, Ether_buffer
1350
        cld             ; set to increment
1351
        rep movsd       ; mov dword from [esi++] to [edi++]
1352
        pop     ecx
1353
        and     ecx, 3  ; copy rest 1-3 bytes
1354
        rep movsb
1355
 
1356
        ; wmb();
1357
        ; ???
1358
 
1359
        ; np->cur_rx++;
1360
        inc     dword [forcedeth_cur_rx]
1361
 
1362
        ; if (!valid)
1363
        cmp     dword [forcedeth_tmp_valid], 0
1364
        jne     @f
1365
        ;   goto top;
1366
        jmp     .top
1367
@@:
1368
        ; alloc_rx(nic);
1369
        call    forcedeth_alloc_rx
1370
 
1371
        ; return 1;
1372
        jmp     .return1
1373
 
1374
;;;;;   DEBUGF  1,"K : FORCEDETH: poll: ...\n"
1375
 
1376
 
1377
.return0:
1378
        mov     eax, 0
1379
        jmp     .return
1380
.return1:
1381
        mov     eax, 1
1382
.return:
1383
        ;;push  eax
1384
 
1385
        ; ????????????????????????????????????????????????
1386
        ; ????? clear interrupt mask/status
1387
        ; read IRQ status
1388
        ;;mov   edi, dword [forcedeth_mapio_addr]
1389
        ;;mov   eax, dword [edi+NvRegIrqStatus]
1390
 
1391
        ; clear events
1392
        ;;and   eax, not (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF or NVREG_IRQ_LINK or NVREG_IRQ_TIMER)
1393
 
1394
        ; write IRQ status
1395
        ;;mov   dword [edi+NvRegIrqStatus], eax
1396
        ; ????????????????????????????????????????????????
1397
 
1398
        ;;pop   eax
1399
        ret
1400
 
1401
 
1402
;***************************************************************************
1403
;   Function
1404
;      forcedeth_transmit
1405
;
1406
;   Description
1407
;       Transmits a packet of data via the ethernet card
1408
;          Pointer to 48 bit destination address in edi
1409
;         Type of packet in bx
1410
;         size of packet in ecx
1411
;         pointer to packet data in esi
1412
;
1413
;***************************************************************************
1414
forcedeth_transmit:
1415
 
1416
        ; send the packet to destination
1417
;pusha
1418
;DEBUGF 1,"K : FORCEDETH: transmit: packet type = 0x%x\n", ebx
1419
;DEBUGF 1,"K : FORCEDETH: transmit: packet len  = 0x%x\n", ecx
1420
;mov    eax, dword [edi]
1421
;DEBUGF 1,"K : FORCEDETH: transmit: dest adr    = 0x%x\n", eax
1422
;mov    eax, dword [edi+4]
1423
;DEBUGF 1,"K : FORCEDETH: transmit: dest adr2   = 0x%x\n", eax
1424
;mov    eax, dword [node_addr]
1425
;DEBUGF 1,"K : FORCEDETH: transmit: src  adr    = 0x%x\n", eax
1426
;mov    eax, dword [node_addr+4]
1427
;DEBUGF 1,"K : FORCEDETH: transmit: src adr2    = 0x%x\n", eax
1428
;popa
1429
 
1430
        ; int nr = np->next_tx % TX_RING
1431
        mov     eax, dword [forcedeth_next_tx]
1432
        and     eax, (TX_RING-1)
1433
        mov     dword [forcedeth_tmp_nr], eax
1434
 
1435
        ; point to the current txb incase multiple tx_rings are used
1436
        ; ptxb = txb + (nr * RX_NIC_BUFSIZE)
1437
        push    ecx
1438
        mov     cx, RX_NIC_BUFSIZE
1439
        mul     cx      ; AX*CX, result to DX:AX
1440
        add     eax, forcedeth_txb
1441
        mov     dword [forcedeth_tmp_ptxb], eax
1442
        push    esi
1443
        mov     esi, edi        ; dst MAC
1444
        mov     edi, eax        ; packet buffer
1445
        cld                     ; set to increment
1446
 
1447
        ; copy the packet to ring buffer
1448
        ; memcpy(ptxb, d, ETH_ALEN);      /* dst */
1449
        movsd
1450
        movsw
1451
 
1452
        ; memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN);      /* src */
1453
        mov     esi, node_addr
1454
        movsd
1455
        movsw
1456
 
1457
        ; nstype = htons((u16) t);        /* type */
1458
        ; memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2);        /* type */
1459
        mov     word [edi], bx
1460
        add     edi, 2
1461
 
1462
        ; memcpy(ptxb + ETH_HLEN, p, s);
1463
        pop     esi
1464
        pop     ecx
1465
        push    ecx
1466
        shr     ecx, 2          ; count in dwords
1467
        rep movsd               ; copy dwords from [esi+=4] to [edi+=4]
1468
        pop     ecx
1469
        push    ecx
1470
        and     ecx, 3          ; copy rest 1-3 bytes
1471
        rep movsb               ; copy bytess from [esi++] to [edi++]
1472
 
1473
 
1474
        ; s += ETH_HLEN;
1475
        ; while (s < ETH_ZLEN)    /* pad to min length */
1476
        ;  ptxb[s++] = '\0';
1477
        ; pad to min length
1478
        pop     ecx
1479
        add     ecx, ETH_HLEN
1480
        push    ecx             ; header length + data length
1481
        cmp     ecx, ETH_ZLEN
1482
        jge     @f
1483
        mov     eax, ETH_ZLEN
1484
        sub     eax, ecx
1485
        xchg    eax, ecx
1486
        mov     al, 0
1487
        rep stosb               ; copy byte from al to [edi++]
1488
 
1489
@@:
1490
 
1491
        ; tx_ring[nr].PacketBuffer = (u32) virt_to_le32desc(ptxb);
1492
        mov     eax, dword [forcedeth_tmp_nr]
1493
        mov     cl, sizeof.forcedeth_TxDesc
1494
        mul     cl
1495
        add     eax, forcedeth_tx_ring
1496
        mov     ebx, eax
1497
        mov     eax, dword [forcedeth_tmp_ptxb]
1498
        sub     eax, OS_BASE            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1499
        mov     [ebx + forcedeth_TxDesc.PacketBuffer], eax
1500
 
1501
;DEBUGF 1,"K : FORCEDETH: transmit: PacketBuffer = 0x%x\n", eax
1502
;DEBUGF 1,"K : FORCEDETH: transmit: txflags = 0x%x\n", [forcedeth_txflags]:8
1503
 
1504
        ; wmb();
1505
        ; tx_ring[nr].FlagLen = cpu_to_le32((s - 1) | np->tx_flags);
1506
        pop     eax             ; header length + data length
1507
        mov     ecx, dword [forcedeth_txflags]
1508
        or      eax, ecx
1509
        mov     [ebx + forcedeth_TxDesc.FlagLen], eax
1510
 
1511
        ; writel(NVREG_TXRXCTL_KICK | np->desc_ver, base + NvRegTxRxControl);
1512
        mov     edi, dword [forcedeth_mapio_addr]
1513
        mov     eax, dword [forcedeth_desc_ver]
1514
        or      eax, NVREG_TXRXCTL_KICK
1515
        mov     dword [edi+NvRegTxRxControl], eax
1516
 
1517
        ; pci_push(base);
1518
        call    forcedeth_pci_push
1519
 
1520
        ; np->next_tx++
1521
        inc     dword [forcedeth_next_tx]; may be need to reset? Overflow?
1522
 
1523
        ret
1524
 
1525
;***************************************************************************
1526
;   Function
1527
;      forcedeth_cable
1528
;
1529
;   Description
1530
;       Return AL=0, if cable is not connected
1531
;       Returm AL=1, if cable is connected
1532
;
1533
;***************************************************************************
1534
forcedeth_cable:
1535
 
1536
        mov     al, 1
1537
        cmp     dword [forcedeth_nocable], 1
1538
        jne     .return
1539
        mov     al, 0
1540
 
1541
.return:
1542
        ret
1543
 
1544
;***************************************************************************
1545
 
1546
 
1547
; read/write a register on the PHY.
1548
; Caller must guarantee serialization
1549
; Input:  EAX - miireg, EBX - addr, ECX - value
1550
; Output: EAX - retval
1551
forcedeth_mii_rw:
1552
        push    ebx
1553
        push    eax     ; save miireg
1554
        ; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus)
1555
        mov     edi, dword [forcedeth_mapio_addr]
1556
        mov     dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK
1557
 
1558
        ; reg = readl(base + NvRegMIIControl)
1559
        mov     eax, dword [edi+NvRegMIIControl]
1560
        test    eax, NVREG_MIICTL_INUSE
1561
        jz      @f
1562
        ; writel(NVREG_MIICTL_INUSE, base + NvRegMIIControl)
1563
        mov     dword [edi+NvRegMIIControl], NVREG_MIICTL_INUSE
1564
        ; nv_udelay(NV_MIIBUSY_DELAY)
1565
        mov     esi, NV_MIIBUSY_DELAY
1566
        call    forcedeth_nv_udelay
1567
@@:
1568
        ; reg = (addr << NVREG_MIICTL_ADDRSHIFT) | miireg
1569
        pop     edx     ; restore miireg
1570
        mov     eax, ebx
1571
        shl     eax, NVREG_MIICTL_ADDRSHIFT
1572
        or      eax, edx
1573
        mov     dword [forcedeth_tmp_reg], eax
1574
 
1575
        cmp     ecx, MII_READ
1576
        je      @f
1577
        ; writel(value, base + NvRegMIIData)
1578
        mov     dword [edi+NvRegMIIData], ecx
1579
        ; reg |= NVREG_MIICTL_WRITE
1580
        or      dword [forcedeth_tmp_reg], NVREG_MIICTL_WRITE
1581
@@:
1582
        ; writel(reg, base + NvRegMIIControl)
1583
        mov     eax, dword [forcedeth_tmp_reg]
1584
        mov     dword [edi+NvRegMIIControl], eax
1585
 
1586
        push    ebx edx edi     ;;;;;;;;;;;;;;;;;;;;;;
1587
 
1588
        ; reg_delay(NvRegMIIControl, NVREG_MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL)
1589
        stdcall forcedeth_reg_delay, NvRegMIIControl, NVREG_MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, 0
1590
 
1591
        pop     edi edx ebx     ;;;;;;;;;;;;;;;;;;;;;;
1592
 
1593
        test    eax, eax
1594
        jz      @f
1595
;;;;;;;;        DEBUGF  1,"K : FORCEDETH: mii_rw of reg %d at PHY %d timed out.\n", edx, ebx
1596
        mov     eax, 0xffffffff
1597
        jmp     .return
1598
@@:
1599
        cmp     ecx, MII_READ
1600
        je      @f
1601
        ;it was a write operation - fewer failures are detectable
1602
;;;;;;;;        DEBUGF  1,"K : FORCEDETH: mii_rw wrote 0x%x to reg %d at PHY %d\n", ecx, edx, ebx
1603
        mov     eax, 0
1604
        jmp     .return
1605
@@:
1606
        ; readl(base + NvRegMIIStatus)
1607
        mov     eax, dword [edi+NvRegMIIStatus]
1608
        test    eax, NVREG_MIISTAT_ERROR
1609
        jz      @f
1610
;;;;;;;;        DEBUGF  1,"K : FORCEDETH: mii_rw of reg %d at PHY %d failed.\n", edx, ebx
1611
        mov     eax, 0xffffffff
1612
        jmp     .return
1613
@@:
1614
        ; retval = readl(base + NvRegMIIData)
1615
        mov     eax, dword [edi+NvRegMIIData]
1616
;;;;;;;;        DEBUGF  1,"K : FORCEDETH: mii_rw read from reg %d at PHY %d: 0x%x.\n", edx, ebx, eax
1617
.return:
1618
        pop     ebx
1619
        ret
1620
 
1621
 
1622
 
1623
; Input:  ESI - delay
1624
; Output: none
1625
forcedeth_nv_udelay:
1626
 
1627
        push    ebx
1628
        cmp     dword [forcedeth_in_shutdown], 0
1629
        jne     @f
1630
        call    forcedeth_udelay        ; delay on ESI
1631
        jmp     .return
1632
@@:
1633
 
1634
.loop:
1635
        cmp     esi, 0
1636
        je      .return
1637
        ; Don't allow an rx_ring overflow to happen
1638
        ; while shutting down the NIC it will
1639
        ; kill the receive function.
1640
 
1641
        call    forcedeth_drop_rx
1642
        mov     ebx, 3          ; sleep = 3
1643
        cmp     ebx, esi        ; if(sleep > delay)
1644
        jle     @f
1645
        mov     ebx, esi        ; sleep = delay
1646
@@:
1647
        push    esi
1648
        mov     esi, ebx
1649
        ; udelay(sleep)
1650
        call    forcedeth_udelay        ; delay on ESI
1651
        pop     esi
1652
        sub     esi, ebx                ; delay -= sleep
1653
        jmp     .loop
1654
 
1655
.return:
1656
        pop     ebx
1657
        ret
1658
 
1659
 
1660
; Input:  none
1661
; Output: none
1662
forcedeth_drop_rx:
1663
 
1664
        push    eax ebx ecx edi
1665
 
1666
        ; events = readl(base + NvRegIrqStatus)
1667
        mov     edi, dword [forcedeth_mapio_addr]
1668
        mov     eax, dword [edi+NvRegIrqStatus]
1669
 
1670
        test    eax, eax
1671
        jz      @f
1672
        ; writel(events, base + NvRegIrqStatus)
1673
        mov     dword [edi+NvRegIrqStatus], eax
1674
@@:
1675
        ;if (!(events & (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF)))
1676
        test    eax, (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF)
1677
        jz      .return
1678
 
1679
.loop:
1680
        ; i = np->cur_rx % RX_RING
1681
        mov     eax, dword [forcedeth_cur_rx]
1682
        and     eax, (RX_RING-1)
1683
        ; //Flags = le32_to_cpu(rx_ring[i].FlagLen)
1684
        ; Flags = rx_ring[i].FlagLen
1685
        mov     cl, sizeof.forcedeth_RxDesc
1686
        mul     cl
1687
        add     eax, forcedeth_rx_ring
1688
        mov     ebx, eax
1689
        mov     eax, [ebx + forcedeth_RxDesc.FlagLen]
1690
        ; len = nv_descr_getlength(&rx_ring[i], np->desc_ver)
1691
        ; > len = Flags & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2)
1692
        ; ??? len don't used later !!! ???
1693
        ; ...
1694
        test    eax, NV_RX_AVAIL
1695
        jnz     .return         ; still owned by hardware,
1696
        ; wmb()
1697
        ; ??? may be empty function ???
1698
        ; np->cur_rx++
1699
        inc     dword [forcedeth_cur_rx]
1700
        ; alloc_rx(NULL)
1701
        call    forcedeth_alloc_rx
1702
.return:
1703
        pop     edi ecx ebx eax
1704
        ret
1705
 
1706
 
1707
; Fill rx ring entries.
1708
; Return 1 if the allocations for the skbs failed and the
1709
; rx engine is without Available descriptors
1710
; Input:  none
1711
; Output: none
1712
forcedeth_alloc_rx:
1713
 
1714
        push    eax ebx ecx edx
1715
        ; refill_rx = np->refill_rx
1716
        mov     ecx, dword [forcedeth_refill_rx]
1717
.loop:
1718
        cmp     dword [forcedeth_cur_rx], ecx
1719
        je      .loop_end
1720
        ; nr = refill_rx % RX_RING
1721
        mov     eax, ecx
1722
        and     eax, (RX_RING-1)        ; nr
1723
        ; rx_ring[nr].PacketBuffer = &rxb[nr * RX_NIC_BUFSIZE]
1724
        push    ecx
1725
        push    eax
1726
        mov     cl, sizeof.forcedeth_RxDesc
1727
        mul     cl
1728
        add     eax, forcedeth_rx_ring
1729
        mov     ebx, eax
1730
        pop     eax
1731
        mov     cx, RX_NIC_BUFSIZE
1732
        mul     cx
1733
        pop     ecx
1734
        add     eax, forcedeth_rxb
1735
        sub     eax, OS_BASE    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1736
        mov     [ebx + forcedeth_RxDesc.PacketBuffer], eax
1737
        ; wmb()
1738
        ; ...
1739
        ; rx_ring[nr].FlagLen = RX_NIC_BUFSIZE | NV_RX_AVAIL
1740
        mov     [ebx + forcedeth_RxDesc.FlagLen], (RX_NIC_BUFSIZE or NV_RX_AVAIL)
1741
        inc     ecx
1742
        jmp     .loop
1743
 
1744
.loop_end:
1745
        ; np->refill_rx = refill_rx
1746
        mov     [forcedeth_refill_rx], ecx
1747
.return:
1748
        pop     edx ecx ebx eax
1749
        ret
1750
 
1751
 
1752
; Delay in millisec
1753
; Input:  ESI - delay in ms
1754
; Output: none
1755
forcedeth_udelay:
1756
        call    delay_ms
1757
        ret
1758
 
1759
; Input:  offset:word, mask:dword, target:dword, delay:word, delaymax:word, msg:dword
1760
; Output: EAX - 0|1
1761
;;;;proc        forcedeth_reg_delay,offset:word,mask:dword,target:dword,delay:word,delaymax:word,msg:dword
1762
proc    forcedeth_reg_delay,offset:dword,mask:dword,target:dword,delay:dword,delaymax:dword,msg:dword
1763
 
1764
        push    ebx esi edi
1765
        ; pci_push(base)
1766
        call    forcedeth_pci_push
1767
.loop:
1768
        ; nv_udelay(delay)
1769
        mov     esi, dword [delay]
1770
        call    forcedeth_nv_udelay     ; delay in esi
1771
        mov     eax, dword [delaymax]
1772
        sub     eax, dword [delay]
1773
        mov     dword [delaymax], eax
1774
        ; if (delaymax < 0)
1775
        test    dword [delaymax], 0x80000000
1776
        jz      @f
1777
        ; return 1
1778
        mov     eax, 1
1779
        jmp     .return
1780
@@:
1781
        ; while ((readl(base + offset) & mask) != target)
1782
        mov     edi, dword [forcedeth_mapio_addr]
1783
        mov     ebx, dword [offset]
1784
        mov     eax, dword [edi+ebx]
1785
        and     eax, dword [mask]
1786
        cmp     eax, dword [target]
1787
        jne     .loop
1788
        xor     eax, eax
1789
.return:
1790
        pop     edi esi ebx
1791
        ret
1792
endp
1793
 
1794
 
1795
; Input:  none
1796
; Output: none
1797
forcedeth_pci_push:
1798
        push    eax edi
1799
        ;force out pending posted writes
1800
        mov     edi, dword [forcedeth_mapio_addr]
1801
        mov     eax, dword [edi]
1802
        pop     edi eax
1803
        ret
1804
 
1805
 
1806
; Input:  none
1807
; Output: EAX - result (0 = OK, other = error)
1808
forcedeth_phy_init:
1809
 
1810
        push    ebx ecx
1811
 
1812
        ; set advertise register
1813
        ; reg = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ);
1814
        ; EBX - addr, EAX - miireg, ECX - value
1815
        mov     ebx, dword [forcedeth_phyaddr]
1816
        mov     eax, MII_ADVERTISE
1817
        mov     ecx, MII_READ
1818
        call    forcedeth_mii_rw        ; reg = eax
1819
 
1820
        ; reg |=
1821
        ; (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF |
1822
        ;  ADVERTISE_100FULL | 0x800 | 0x400);
1823
        or      eax, (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or 0x800 or 0x400)
1824
 
1825
        ; if (mii_rw(nic, np->phyaddr, MII_ADVERTISE, reg))
1826
        ; EBX - addr, EAX - miireg, ECX - value
1827
        mov     ecx, eax        ; reg
1828
        mov     eax, MII_ADVERTISE
1829
        call    forcedeth_mii_rw        ; eax -> return
1830
 
1831
        test    eax, eax
1832
        jz      @f
1833
        ; printf("phy write to advertise failed.\n");
1834
        DEBUGF 1," K : FORCEDETH: phy write to advertise failed.\n"
1835
 
1836
        ; return PHY_ERROR;
1837
        mov     eax, PHY_ERROR
1838
        jmp     .return
1839
@@:
1840
        ; get phy interface type
1841
        ; phyinterface = readl(base + NvRegPhyInterface);
1842
        mov     edi, dword [forcedeth_mapio_addr]
1843
        mov     eax, dword [edi+NvRegPhyInterface]      ; phyinterface = eax
1844
        mov     dword [forcedeth_tmp_phyinterface], eax
1845
 
1846
;;;;;;;;;;;;;;;;;;;;;;;;;
1847
DEBUGF 1," K : FORCEDETH: phy interface type = 0x%x\n", [forcedeth_tmp_phyinterface]:8
1848
;;;;;;;;;;;;;;;;;;;;;;;;;
1849
 
1850
        ; see if gigabit phy
1851
        ; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
1852
        ; EBX - addr, EAX - miireg, ECX - value
1853
        mov     eax, MII_BMSR
1854
        mov     ecx, MII_READ
1855
        call    forcedeth_mii_rw        ; mii_status = eax
1856
 
1857
        ; if (mii_status & PHY_GIGABIT)
1858
        test    eax, PHY_GIGABIT
1859
        jnz     .gigabit
1860
        ; np->gigabit = 0;
1861
        mov     dword [forcedeth_gigabit], 0
1862
        jmp     .next_if
1863
 
1864
.gigabit:
1865
        ; np->gigabit = PHY_GIGABIT;
1866
        mov     dword [forcedeth_gigabit], PHY_GIGABIT
1867
 
1868
        ; mii_control_1000 =  mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ);
1869
        ; EBX - addr, EAX - miireg, ECX - value
1870
        mov     eax, MII_1000BT_CR
1871
        mov     ecx, MII_READ
1872
        call    forcedeth_mii_rw        ; mii_control_1000 = eax
1873
 
1874
        ; mii_control_1000 &= ~ADVERTISE_1000HALF;
1875
        and     eax, (not ADVERTISE_1000HALF)
1876
 
1877
        ; if (phyinterface & PHY_RGMII)
1878
        test    dword [forcedeth_tmp_phyinterface], PHY_RGMII
1879
        jz      @f
1880
        ; mii_control_1000 |= ADVERTISE_1000FULL
1881
        or      eax, ADVERTISE_1000FULL
1882
        jmp     .next
1883
@@:
1884
        ; mii_control_1000 &= ~ADVERTISE_1000FULL
1885
        and     eax, (not ADVERTISE_1000FULL)
1886
 
1887
.next:
1888
        ; if (mii_rw(nic, np->phyaddr, MII_1000BT_CR, mii_control_1000))
1889
        ; EBX - addr, EAX - miireg, ECX - value
1890
        mov     ecx, eax
1891
        mov     eax, MII_1000BT_CR
1892
        call    forcedeth_mii_rw        ; eax -> return
1893
 
1894
        test    eax, eax
1895
        jz      .next_if
1896
 
1897
        ; printf("phy init failed.\n");
1898
        DEBUGF 1," K : FORCEDETH: phy init failed.\n"
1899
 
1900
        ; return PHY_ERROR;
1901
        mov     eax, PHY_ERROR
1902
        jmp     .return
1903
 
1904
.next_if:
1905
 
1906
        ; reset the phy
1907
        ; if (phy_reset(nic))
1908
        call    forcedeth_phy_reset
1909
        test    eax, eax
1910
        jz      @f
1911
        ; printf("phy reset failed\n")
1912
        DEBUGF 1," K : FORCEDETH: phy reset failed.\n"
1913
        ; return PHY_ERROR
1914
        mov     eax, PHY_ERROR
1915
        jmp     .return
1916
@@:
1917
 
1918
        ; phy vendor specific configuration
1919
        ; if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII))
1920
        cmp     dword [forcedeth_phy_oui], PHY_OUI_CICADA
1921
        jne     .next_if2
1922
        test    dword [forcedeth_tmp_phyinterface], PHY_RGMII
1923
        jz      .next_if2
1924
 
1925
        ; phy_reserved = mii_rw(nic, np->phyaddr, MII_RESV1, MII_READ)
1926
        ; EBX - addr, EAX - miireg, ECX - value
1927
        mov     eax, MII_RESV1
1928
        mov     ecx, MII_READ
1929
        call    forcedeth_mii_rw        ; phy_reserved = eax
1930
 
1931
        ; phy_reserved &= ~(PHY_INIT1 | PHY_INIT2)
1932
        and     eax, (not (PHY_INIT1 or PHY_INIT2))
1933
        ; phy_reserved |= (PHY_INIT3 | PHY_INIT4)
1934
        or      eax, (PHY_INIT3 or PHY_INIT4)
1935
 
1936
        ; if (mii_rw(nic, np->phyaddr, MII_RESV1, phy_reserved))
1937
        ; EBX - addr, EAX - miireg, ECX - value
1938
        mov     ecx, eax
1939
        mov     eax, MII_RESV1
1940
        call    forcedeth_mii_rw        ; eax -> return
1941
        test    eax, eax
1942
        jz      @f
1943
        ; printf("phy init failed.\n")
1944
        DEBUGF 1," K : FORCEDETH: phy init failed.\n"
1945
        ; return PHY_ERROR
1946
        mov     eax, PHY_ERROR
1947
        jmp     .return
1948
@@:
1949
        ; phy_reserved = mii_rw(nic, np->phyaddr, MII_NCONFIG, MII_READ);
1950
        ; EBX - addr, EAX - miireg, ECX - value
1951
        mov     eax, MII_NCONFIG
1952
        mov     ecx, MII_READ
1953
        call    forcedeth_mii_rw        ; phy_reserved = eax
1954
 
1955
        ; phy_reserved |= PHY_INIT5
1956
        or      eax, PHY_INIT5
1957
 
1958
        ; if (mii_rw(nic, np->phyaddr, MII_NCONFIG, phy_reserved))
1959
        ; EBX - addr, EAX - miireg, ECX - value
1960
        mov     ecx, eax
1961
        mov     eax, MII_NCONFIG
1962
        call    forcedeth_mii_rw        ; eax -> return
1963
        test    eax, eax
1964
        jz      .next_if2
1965
        ; printf("phy init failed.\n")
1966
        DEBUGF 1," K : FORCEDETH: phy init failed.\n"
1967
        ; return PHY_ERROR
1968
        mov     eax, PHY_ERROR
1969
        jmp     .return
1970
 
1971
.next_if2:
1972
 
1973
        ; if (np->phy_oui == PHY_OUI_CICADA)
1974
        cmp     dword [forcedeth_phy_oui], PHY_OUI_CICADA
1975
        jne     .restart
1976
 
1977
        ; phy_reserved = mii_rw(nic, np->phyaddr, MII_SREVISION, MII_READ)
1978
        ; EBX - addr, EAX - miireg, ECX - value
1979
        mov     eax, MII_SREVISION
1980
        mov     ecx, MII_READ
1981
        call    forcedeth_mii_rw        ; phy_reserved = eax
1982
 
1983
        ; phy_reserved |= PHY_INIT6
1984
        or      eax, PHY_INIT6
1985
 
1986
        ; if (mii_rw(nic, np->phyaddr, MII_SREVISION, phy_reserved))
1987
        mov     ecx, eax
1988
        mov     eax, MII_SREVISION
1989
        call    forcedeth_mii_rw        ; eax -> return
1990
        test    eax, eax
1991
        jz      .restart
1992
        ; printf("phy init failed.\n");
1993
        DEBUGF 1," K : FORCEDETH: phy init failed.\n"
1994
        ; return PHY_ERROR;
1995
        jmp     .return
1996
 
1997
.restart:
1998
        ; restart auto negotiation
1999
        ; mii_control = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ)
2000
        ; EBX - addr, EAX - miireg, ECX - value
2001
        mov     eax, MII_BMCR
2002
        mov     ecx, MII_READ
2003
        call    forcedeth_mii_rw        ; mii_control = eax
2004
 
2005
        ; mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE)
2006
        or      eax, (BMCR_ANRESTART or BMCR_ANENABLE)
2007
 
2008
        ; if (mii_rw(nic, np->phyaddr, MII_BMCR, mii_control))
2009
        mov     ecx, eax
2010
        mov     eax, MII_BMCR
2011
        call    forcedeth_mii_rw        ; eax -> return
2012
        test    eax, eax
2013
        jz      .ok
2014
 
2015
        ; return PHY_ERROR;
2016
        mov     eax, PHY_ERROR
2017
        jmp     .return
2018
 
2019
.ok:
2020
        mov     eax, 0
2021
.return:
2022
        pop     ecx ebx
2023
        ret
2024
 
2025
 
2026
; Input:  none
2027
; Output: EAX - result (0 = OK, other = error)
2028
forcedeth_phy_reset:
2029
 
2030
        push    ebx ecx edx
2031
 
2032
        ; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ);
2033
        ; EBX - addr, EAX - miireg, ECX - value
2034
        mov     ebx, dword [forcedeth_phyaddr]
2035
        mov     eax, MII_BMCR
2036
        mov     ecx, MII_READ
2037
        call    forcedeth_mii_rw        ; miicontrol = eax
2038
 
2039
        ; miicontrol |= BMCR_RESET;
2040
        or      eax, BMCR_RESET
2041
        push    eax
2042
 
2043
        ; if (mii_rw(nic, np->phyaddr, MII_BMCR, miicontrol))
2044
        ; EBX - addr, EAX - miireg, ECX - value
2045
        mov     ecx, eax
2046
        mov     eax, MII_BMCR
2047
        call    forcedeth_mii_rw        ; miicontrol = eax
2048
 
2049
        test    eax, eax
2050
        jz      @f
2051
        pop     eax
2052
        mov     eax, 0xffffffff
2053
        jmp     .return
2054
@@:
2055
        pop     eax
2056
 
2057
        ; wait for 500ms
2058
        ; mdelay(500)
2059
        mov     esi, 500
2060
        call    forcedeth_udelay
2061
 
2062
        ; must wait till reset is deasserted
2063
        ; while (miicontrol & BMCR_RESET) {
2064
        mov     edx, 100
2065
.while_loop:
2066
        test    eax, BMCR_RESET
2067
        jz      .while_loop_exit
2068
 
2069
        ; mdelay(10);
2070
        mov     esi, 10
2071
        call    forcedeth_udelay
2072
 
2073
        ; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ);
2074
        ; EBX - addr, EAX - miireg, ECX - value
2075
        mov     eax, MII_BMCR
2076
        mov     ecx, MII_READ
2077
        call    forcedeth_mii_rw        ; miicontrol = eax
2078
 
2079
        ; FIXME: 100 tries seem excessive
2080
        ; if (tries++ > 100)
2081
        dec     edx
2082
        jnz     .while_loop
2083
        ; return -1;
2084
        mov     eax, 0xffffffff
2085
        jmp     .return
2086
.while_loop_exit:
2087
        ; return 0
2088
        mov     eax, 0
2089
.return:
2090
        pop     edx ecx ebx
2091
        ret
2092
 
2093
; Input:  none
2094
; Output: none
2095
forcedeth_mac_reset:
2096
        push    esi edi
2097
 
2098
        ; dprintf("mac_reset\n")
2099
        DEBUGF 1," K : FORCEDETH: mac_reset.\n"
2100
 
2101
        ; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl)
2102
        mov     edi, dword [forcedeth_mapio_addr]
2103
        mov     eax, dword [forcedeth_desc_ver]
2104
        or      eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET)
2105
        mov     dword [edi+NvRegTxRxControl], eax
2106
 
2107
        ; pci_push(base)
2108
        call    forcedeth_pci_push
2109
 
2110
        ; writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset)
2111
        mov     dword [edi+NvRegMacReset], NVREG_MAC_RESET_ASSERT
2112
 
2113
        ; pci_push(base)
2114
        call    forcedeth_pci_push
2115
 
2116
        ; udelay(NV_MAC_RESET_DELAY)
2117
        mov     esi, NV_MAC_RESET_DELAY
2118
        call    forcedeth_nv_udelay
2119
 
2120
        ; writel(0, base + NvRegMacReset)
2121
        mov     dword [edi+NvRegMacReset], 0
2122
 
2123
        ; pci_push(base)
2124
        call    forcedeth_pci_push
2125
 
2126
        ; udelay(NV_MAC_RESET_DELAY)
2127
        mov     esi, NV_MAC_RESET_DELAY
2128
        call    forcedeth_nv_udelay
2129
 
2130
        ; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl)
2131
        mov     eax, dword [forcedeth_desc_ver]
2132
        or      eax, NVREG_TXRXCTL_BIT2
2133
        mov     dword [edi+NvRegTxRxControl], eax
2134
 
2135
        ; pci_push(base)
2136
        call    forcedeth_pci_push
2137
 
2138
        pop     edi esi
2139
        ret
2140
 
2141
; Input:  none
2142
; Output: none
2143
forcedeth_init_ring:
2144
        push    eax ebx ecx
2145
 
2146
        ; np->next_tx = np->nic_tx = 0
2147
        mov     dword[forcedeth_next_tx], 0
2148
        mov     dword[forcedeth_nic_tx], 0
2149
 
2150
        ; for (i = 0; i < TX_RING; i++)
2151
        mov     ecx, TX_RING
2152
 
2153
.for_loop:
2154
        ;        tx_ring[i].FlagLen = 0;
2155
        mov     eax, ecx
2156
        dec     eax
2157
        mov     bl, sizeof.forcedeth_TxDesc
2158
        mul     bl
2159
        add     eax, forcedeth_tx_ring
2160
        mov     ebx, eax
2161
        mov     dword [ebx + forcedeth_TxDesc.FlagLen], 0
2162
        loop    .for_loop
2163
 
2164
        ; np->cur_rx = RX_RING;
2165
        mov     dword [forcedeth_cur_rx], RX_RING
2166
        ; np->refill_rx = 0;
2167
        mov     dword [forcedeth_refill_rx], 0
2168
 
2169
        ;for (i = 0; i < RX_RING; i++)
2170
        mov     ecx, RX_RING
2171
 
2172
.for_loop2:
2173
        ;        rx_ring[i].FlagLen = 0;
2174
        mov     eax, ecx
2175
        dec     eax
2176
        mov     bl, sizeof.forcedeth_RxDesc
2177
        mul     bl
2178
        add     eax, forcedeth_rx_ring
2179
        mov     ebx, eax
2180
        mov     dword [ebx + forcedeth_RxDesc.FlagLen], 0
2181
        loop    .for_loop2
2182
 
2183
        ; alloc_rx(nic);
2184
        call    forcedeth_alloc_rx
2185
 
2186
.return:
2187
        pop     ecx ebx eax
2188
        ret
2189
 
2190
; Input:  none
2191
; Output: none
2192
forcedeth_txrx_reset:
2193
        push    eax esi edi
2194
 
2195
        ; dprintf(("txrx_reset\n"))
2196
        DEBUGF 1," K : FORCEDETH: txrx_reset.\n"
2197
 
2198
        ; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl)
2199
        mov     edi, dword [forcedeth_mapio_addr]
2200
        mov     eax, dword [forcedeth_desc_ver]
2201
        or      eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET)
2202
        mov     dword [edi+NvRegTxRxControl], eax
2203
 
2204
        ; pci_push(base)
2205
        call    forcedeth_pci_push
2206
 
2207
        ; nv_udelay(NV_TXRX_RESET_DELAY)
2208
        mov     esi, NV_TXRX_RESET_DELAY
2209
        call    forcedeth_nv_udelay
2210
 
2211
        ; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl)
2212
        mov     eax, dword [forcedeth_desc_ver]
2213
        or      eax, NVREG_TXRXCTL_BIT2
2214
        mov     dword [edi+NvRegTxRxControl], eax
2215
 
2216
        ; pci_push(base)
2217
        call    forcedeth_pci_push
2218
 
2219
.return:
2220
        pop     edi esi eax
2221
        ret
2222
 
2223
; Input:  none
2224
; Output: none
2225
forcedeth_set_multicast:
2226
        push    edi
2227
 
2228
        ; u32 addr[2];
2229
        ; u32 mask[2];
2230
        ; u32 pff;
2231
        ; u32 alwaysOff[2];
2232
        ; u32 alwaysOn[2];
2233
        ;
2234
        ; memset(addr, 0, sizeof(addr));
2235
        ; memset(mask, 0, sizeof(mask));
2236
        ;
2237
        ; pff = NVREG_PFF_MYADDR;
2238
        ;
2239
        ; alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0;
2240
        ;
2241
        ; addr[0] = alwaysOn[0];
2242
        ; addr[1] = alwaysOn[1];
2243
        ; mask[0] = alwaysOn[0] | alwaysOff[0];
2244
        ; mask[1] = alwaysOn[1] | alwaysOff[1];
2245
        ;
2246
        ; addr[0] |= NVREG_MCASTADDRA_FORCE;
2247
        ; pff |= NVREG_PFF_ALWAYS;
2248
        ; stop_rx();
2249
        call    forcedeth_stop_rx
2250
        ; writel(addr[0], base + NvRegMulticastAddrA);
2251
        mov     edi, dword [forcedeth_mapio_addr]
2252
        mov     dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE
2253
        ; writel(addr[1], base + NvRegMulticastAddrB);
2254
        mov     dword [edi+NvRegMulticastAddrB], 0
2255
        ; writel(mask[0], base + NvRegMulticastMaskA);
2256
        mov     dword [edi+NvRegMulticastMaskA], 0
2257
        ; writel(mask[1], base + NvRegMulticastMaskB);
2258
        mov     dword [edi+NvRegMulticastMaskB], 0
2259
        ; writel(pff, base + NvRegPacketFilterFlags);
2260
        mov     dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_MYADDR or NVREG_PFF_ALWAYS)
2261
        ; start_rx(nic);
2262
        call    forcedeth_start_rx
2263
 
2264
.return:
2265
        pop     edi
2266
        ret
2267
 
2268
; Input:  none
2269
; Output: none
2270
forcedeth_start_rx:
2271
        push    edi
2272
 
2273
        ; dprintf(("start_rx\n"))
2274
        DEBUGF 1," K : FORCEDETH: start_rx.\n"
2275
 
2276
        ; Already running? Stop it.
2277
        ; if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) {
2278
        mov     edi, dword [forcedeth_mapio_addr]
2279
        mov     eax, dword [edi+NvRegReceiverControl]
2280
        test    eax, NVREG_RCVCTL_START
2281
        jz      @f
2282
        ; writel(0, base + NvRegReceiverControl)
2283
        mov     dword [edi+NvRegReceiverControl], 0
2284
        ; pci_push(base)
2285
        call    forcedeth_pci_push
2286
 
2287
@@:
2288
 
2289
        ; writel(np->linkspeed, base + NvRegLinkSpeed);
2290
        mov     eax, dword [forcedeth_linkspeed]
2291
        mov     dword [edi+NvRegLinkSpeed], eax
2292
        ; pci_push(base);
2293
        call    forcedeth_pci_push
2294
        ; writel(NVREG_RCVCTL_START, base + NvRegReceiverControl);
2295
        mov     dword [edi+NvRegReceiverControl], NVREG_RCVCTL_START
2296
        ; pci_push(base);
2297
        call    forcedeth_pci_push
2298
 
2299
.return:
2300
        pop     edi
2301
        ret
2302
 
2303
; Input:  none
2304
; Output: none
2305
forcedeth_stop_rx:
2306
        push    esi edi
2307
 
2308
        ; dprintf(("stop_rx\n"))
2309
        DEBUGF 1," K : FORCEDETH: stop_rx.\n"
2310
 
2311
        ; writel(0, base + NvRegReceiverControl)
2312
        mov     edi, dword [forcedeth_mapio_addr]
2313
        mov     dword [edi+NvRegReceiverControl], 0
2314
 
2315
        push    ebx edx edi     ;;;;;;;;;;;;;;;;;;;;;;
2316
        ; reg_delay(NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, "stop_rx: ReceiverStatus remained busy");
2317
        stdcall forcedeth_reg_delay, NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, 0
2318
        pop     edi edx ebx     ;;;;;;;;;;;;;;;;;;;;;;
2319
 
2320
 
2321
        ; nv_udelay(NV_RXSTOP_DELAY2)
2322
        mov     esi, NV_RXSTOP_DELAY2
2323
        call    forcedeth_nv_udelay
2324
 
2325
        ; writel(0, base + NvRegLinkSpeed)
2326
        mov     dword [edi+NvRegLinkSpeed], 0
2327
 
2328
.return:
2329
        pop     edi esi
2330
        ret
2331
 
2332
; Input:  none
2333
; Output: EAX
2334
forcedeth_update_linkspeed:
2335
        push    ebx ecx esi edi
2336
 
2337
        ; BMSR_LSTATUS is latched, read it twice:
2338
        ; we want the current value.
2339
 
2340
        ; mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ)
2341
        ;EBX - addr, EAX - miireg, ECX - value
2342
        mov     ebx, dword [forcedeth_phyaddr]
2343
        mov     eax, MII_BMSR
2344
        mov     ecx, MII_READ
2345
        call    forcedeth_mii_rw
2346
 
2347
 
2348
        ; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ)
2349
        ;EBX - addr, EAX - miireg, ECX - value
2350
        mov     ebx, dword [forcedeth_phyaddr]
2351
        mov     eax, MII_BMSR
2352
        mov     ecx, MII_READ
2353
        call    forcedeth_mii_rw        ; mii_status = eax
2354
 
2355
        ; yhlu
2356
 
2357
        ; for(i=0;i<30;i++) {
2358
        mov     ecx, 30
2359
.for_loop:
2360
        push    ecx
2361
 
2362
        ;  mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
2363
        ;EBX - addr, EAX - miireg, ECX - value
2364
        ;mov    ebx, dword [forcedeth_phyaddr]
2365
        mov     eax, MII_BMSR
2366
        mov     ecx, MII_READ
2367
        call    forcedeth_mii_rw        ; mii_status = eax
2368
 
2369
        ;  if((mii_status & BMSR_LSTATUS) && (mii_status & BMSR_ANEGCOMPLETE)) break;
2370
        test    eax, BMSR_LSTATUS
2371
        jz      @f
2372
        test    eax, BMSR_ANEGCOMPLETE
2373
        jz      @f
2374
        ; break
2375
        pop     ecx
2376
        jmp     .break
2377
 
2378
@@:
2379
 
2380
        ;  mdelay(100);
2381
        push    eax     ; ???
2382
        mov     esi, 100
2383
        call    forcedeth_udelay
2384
        pop     eax     ; ???
2385
 
2386
        pop     ecx
2387
        loop    .for_loop
2388
 
2389
.break:
2390
 
2391
        ; if (!(mii_status & BMSR_LSTATUS)) {
2392
        test    eax, BMSR_LSTATUS
2393
        jnz     @f
2394
 
2395
        ; printf("no link detected by phy - falling back to 10HD.\n")
2396
        DEBUGF 1," K : FORCEDETH: update_linkspeed: no link detected by phy - falling back to 10HD.\n"
2397
 
2398
        ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
2399
        mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
2400
 
2401
        ; newdup = 0;
2402
        mov     dword [forcedeth_tmp_newdup], 0
2403
        ; retval = 0;
2404
        mov     dword [forcedeth_tmp_retval], 0
2405
 
2406
        ; goto set_speed;
2407
        jmp     .set_speed
2408
 
2409
@@:
2410
 
2411
        ; check auto negotiation is complete
2412
        ; if (!(mii_status & BMSR_ANEGCOMPLETE)) {
2413
        test    eax, BMSR_ANEGCOMPLETE
2414
        jnz     @f
2415
 
2416
        ; still in autonegotiation - configure nic for 10 MBit HD and wait.
2417
        ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
2418
        mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
2419
 
2420
        ; newdup = 0
2421
        mov     dword [forcedeth_tmp_newdup], 0
2422
 
2423
        ; retval = 0
2424
        mov     dword [forcedeth_tmp_retval], 0
2425
 
2426
        ; printf("autoneg not completed - falling back to 10HD.\n")
2427
        DEBUGF 1," K : FORCEDETH: update_linkspeed: autoneg not completed - falling back to 10HD.\n"
2428
 
2429
        ; goto set_speed
2430
        jmp     .set_speed
2431
 
2432
@@:
2433
 
2434
        ; retval = 1
2435
        mov     dword [forcedeth_tmp_retval], 1
2436
 
2437
        ; if (np->gigabit == PHY_GIGABIT) {
2438
        cmp     dword [forcedeth_gigabit], PHY_GIGABIT
2439
        jne     .end_if
2440
        ; control_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ)
2441
        ;EBX - addr, EAX - miireg, ECX - value
2442
        ;mov    ebx, dword [forcedeth_phyaddr]
2443
        mov     eax, MII_1000BT_CR
2444
        mov     ecx, MII_READ
2445
        call    forcedeth_mii_rw        ; control_1000 = eax
2446
        mov     dword [forcedeth_tmp_control_1000], eax
2447
 
2448
        ; status_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_SR, MII_READ)
2449
        ;EBX - addr, EAX - miireg, ECX - value
2450
        ;mov    ebx, dword [forcedeth_phyaddr]
2451
        mov     eax, MII_1000BT_SR
2452
        mov     ecx, MII_READ
2453
        call    forcedeth_mii_rw        ; status_1000 = eax
2454
        ;mov    dword [forcedeth_tmp_status_1000], eax
2455
 
2456
        ; if ((control_1000 & ADVERTISE_1000FULL) &&
2457
        ;     (status_1000 & LPA_1000FULL)) {
2458
        test    eax, LPA_1000FULL
2459
        jz      .end_if
2460
        test    dword [forcedeth_tmp_control_1000], ADVERTISE_1000FULL
2461
        jz      .end_if
2462
 
2463
        ; printf ("update_linkspeed: GBit ethernet detected.\n")
2464
        DEBUGF 1," K : FORCEDETH: update_linkspeed: GBit ethernet detected.\n"
2465
 
2466
        ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_1000
2467
        mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_1000)
2468
 
2469
        ; newdup = 1
2470
        mov     dword [forcedeth_tmp_newdup], 1
2471
 
2472
        ; goto set_speed
2473
        jmp     .set_speed
2474
 
2475
.end_if:
2476
 
2477
        ; adv = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ);
2478
        ;EBX - addr, EAX - miireg, ECX - value
2479
        ;mov    ebx, dword [forcedeth_phyaddr]
2480
        mov     eax, MII_ADVERTISE
2481
        mov     ecx, MII_READ
2482
        call    forcedeth_mii_rw        ; adv = eax
2483
        mov     dword [forcedeth_tmp_adv], eax
2484
 
2485
        ; lpa = mii_rw(nic, np->phyaddr, MII_LPA, MII_READ);
2486
        ;EBX - addr, EAX - miireg, ECX - value
2487
        ;mov    ebx, dword [forcedeth_phyaddr]
2488
        mov     eax, MII_LPA
2489
        mov     ecx, MII_READ
2490
        call    forcedeth_mii_rw        ; lpa = eax
2491
        mov     dword [forcedeth_tmp_lpa], eax
2492
 
2493
        ; dprintf(("update_linkspeed: PHY advertises 0x%hX, lpa 0x%hX.\n", adv, lpa));
2494
        DEBUGF 1," K : FORCEDETH: update_linkspeed: PHY advertises 0x%x, lpa 0x%x.\n", [forcedeth_tmp_adv]:8, [forcedeth_tmp_lpa]:8
2495
 
2496
        ; FIXME: handle parallel detection properly, handle gigabit ethernet
2497
        ; lpa = lpa & adv
2498
        mov     eax, dword [forcedeth_tmp_adv]
2499
        and     dword [forcedeth_tmp_lpa], eax
2500
 
2501
        mov     eax, dword [forcedeth_tmp_lpa]
2502
 
2503
        ; if (lpa & LPA_100FULL) {
2504
        test    eax, LPA_100FULL
2505
        jz      @f
2506
        ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100
2507
        mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100)
2508
        ; newdup = 1
2509
        mov     dword [forcedeth_tmp_newdup], 1
2510
        jmp     .set_speed
2511
@@:
2512
        ; } else if (lpa & LPA_100HALF) {
2513
        test    eax, LPA_100HALF
2514
        jz      @f
2515
        ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100
2516
        mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100)
2517
        ; newdup = 0
2518
        mov     dword [forcedeth_tmp_newdup], 0
2519
        jmp     .set_speed
2520
@@:
2521
        ; } else if (lpa & LPA_10FULL) {
2522
        test    eax, LPA_10FULL
2523
        jz      @f
2524
        ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
2525
        mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
2526
        ; newdup = 1
2527
        mov     dword [forcedeth_tmp_newdup], 1
2528
        jmp     .set_speed
2529
@@:
2530
        ; } else if (lpa & LPA_10HALF) {
2531
        test    eax, LPA_10HALF
2532
        ;    newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
2533
        mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
2534
        ;    newdup = 0;
2535
        mov     dword [forcedeth_tmp_newdup], 0
2536
        jmp     .set_speed
2537
@@:
2538
        ; } else {
2539
        ; printf("bad ability %hX - falling back to 10HD.\n", lpa)
2540
        DEBUGF 1," K : FORCEDETH: update_linkspeed: bad ability 0x%x - falling back to 10HD.\n", eax
2541
 
2542
        ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
2543
        mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
2544
        ; newdup = 0
2545
        mov     dword [forcedeth_tmp_newdup], 0
2546
        ; }
2547
 
2548
.set_speed:
2549
 
2550
        ; if (np->duplex == newdup && np->linkspeed == newls)
2551
        mov     eax, dword [forcedeth_tmp_newdup]
2552
        cmp     eax, dword [forcedeth_duplex]
2553
        jne     .end_if2
2554
        mov     eax, dword [forcedeth_tmp_newls]
2555
        cmp     eax, dword [forcedeth_linkspeed]
2556
        jne     .end_if2
2557
        ;    return retval;
2558
        jmp     .return
2559
 
2560
.end_if2:
2561
 
2562
        ; dprintf(("changing link setting from %d/%s to %d/%s.\n",
2563
        ;    np->linkspeed, np->duplex ? "Full-Duplex": "Half-Duplex", newls, newdup ? "Full-Duplex": "Half-Duplex"))
2564
        DEBUGF 1," K : FORCEDETH: update_linkspeed: changing link from %x/XD to %x/XD.\n", [forcedeth_linkspeed]:8, [forcedeth_tmp_newls]:8     ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!
2565
 
2566
        ; np->duplex = newdup
2567
        mov     eax, dword [forcedeth_tmp_newdup]
2568
        mov     dword [forcedeth_duplex], eax
2569
 
2570
        ; np->linkspeed = newls
2571
        mov     eax, [forcedeth_tmp_newls]
2572
        mov     dword [forcedeth_linkspeed], eax
2573
 
2574
        ; if (np->gigabit == PHY_GIGABIT) {
2575
        cmp     dword [forcedeth_gigabit], PHY_GIGABIT
2576
        jne     .end_if3
2577
 
2578
        ; phyreg = readl(base + NvRegRandomSeed);
2579
        mov     edi, dword [forcedeth_mapio_addr]
2580
        mov     eax, dword [edi+NvRegRandomSeed]
2581
 
2582
        ; phyreg &= ~(0x3FF00);
2583
        and     eax, not (0x3FF00)
2584
        mov     ecx, eax                ; phyreg = ecx
2585
 
2586
        ; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10)
2587
        mov     eax, dword [forcedeth_linkspeed]
2588
        and     eax, 0xFFF
2589
        cmp     eax, NVREG_LINKSPEED_10
2590
        jne     @f
2591
        ; phyreg |= NVREG_RNDSEED_FORCE3
2592
        or      ecx, NVREG_RNDSEED_FORCE3
2593
        jmp     .end_if4
2594
@@:
2595
        ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
2596
        cmp     eax, NVREG_LINKSPEED_100
2597
        jne     @f
2598
        ; phyreg |= NVREG_RNDSEED_FORCE2
2599
        or      ecx, NVREG_RNDSEED_FORCE2
2600
        jmp     .end_if4
2601
@@:
2602
        ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
2603
        cmp     eax, NVREG_LINKSPEED_1000
2604
        jne     .end_if4
2605
        ; phyreg |= NVREG_RNDSEED_FORCE
2606
        or      ecx, NVREG_RNDSEED_FORCE
2607
.end_if4:
2608
        ; writel(phyreg, base + NvRegRandomSeed)
2609
        mov     dword [edi+NvRegRandomSeed], ecx
2610
 
2611
.end_if3:
2612
 
2613
        ; phyreg = readl(base + NvRegPhyInterface)
2614
        mov     ecx, dword [edi+NvRegPhyInterface]
2615
 
2616
        ; phyreg &= ~(PHY_HALF | PHY_100 | PHY_1000)
2617
        and     ecx, not (PHY_HALF or PHY_100 or PHY_1000)
2618
 
2619
        ; if (np->duplex == 0)
2620
        cmp     dword [forcedeth_duplex], 0
2621
        jne     @f
2622
        ; phyreg |= PHY_HALF
2623
        or      ecx, PHY_HALF
2624
@@:
2625
        ; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
2626
        mov     eax, dword [forcedeth_linkspeed]
2627
        and     eax, 0xFFF
2628
        cmp     eax, NVREG_LINKSPEED_100
2629
        jne     @f
2630
        ; phyreg |= PHY_100
2631
        or      ecx, PHY_100
2632
        jmp     .end_if5
2633
@@:
2634
        ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
2635
        cmp     eax, NVREG_LINKSPEED_1000
2636
        jne     .end_if5
2637
        ; phyreg |= PHY_1000
2638
        or      ecx, PHY_1000
2639
 
2640
.end_if5:
2641
 
2642
        ; writel(phyreg, base + NvRegPhyInterface)
2643
        mov     dword [edi+NvRegPhyInterface], ecx
2644
 
2645
        ; writel(NVREG_MISC1_FORCE | (np->duplex ? 0 : NVREG_MISC1_HD), base + NvRegMisc1);
2646
        cmp     dword [forcedeth_duplex], 0
2647
        je      @f
2648
        mov     ecx, 0
2649
        jmp     .next
2650
@@:
2651
        mov     ecx, NVREG_MISC1_HD
2652
.next:
2653
        or      ecx, NVREG_MISC1_FORCE
2654
        mov     dword [edi+NvRegMisc1], ecx
2655
 
2656
        ; pci_push(base)
2657
        call    forcedeth_pci_push
2658
 
2659
        ; writel(np->linkspeed, base + NvRegLinkSpeed)
2660
        mov     eax, dword [forcedeth_linkspeed]
2661
        mov     dword [edi+NvRegLinkSpeed], eax
2662
 
2663
        ; pci_push(base)
2664
        call    forcedeth_pci_push
2665
 
2666
.return:
2667
        ; return retval
2668
        mov     eax, dword [forcedeth_tmp_retval]
2669
        pop     edi esi ecx ebx
2670
        ret
2671
 
2672
 
2673
; Input:  none
2674
; Output: none
2675
forcedeth_start_tx:
2676
        push    edi
2677
        ; dprintf(("start_tx\n"))
2678
        DEBUGF 1," K : FORCEDETH: start_tx.\n"
2679
 
2680
        ; writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl)
2681
        mov     edi, dword [forcedeth_mapio_addr]
2682
        mov     dword [edi+NvRegTransmitterControl], NVREG_XMITCTL_START
2683
 
2684
        ; pci_push(base)
2685
        call    forcedeth_pci_push
2686
 
2687
.return:
2688
        pop     edi
2689
        ret
2690
 
2691
; Interrupt handler
2692
forcedeth_int_handler:
2693
        DEBUGF 1," K : FORCEDETH: interrupt handler.\n"
2694
 
2695
        ret
2696