Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
4467 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved.    ;;
3545 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  FORCEDETH.INC                                                  ;;
7
;;                                                                 ;;
8
;;  Ethernet driver for Kolibri OS                                 ;;
9
;;                                                                 ;;
10
;;  Driver for chips of NVIDIA nForce2                             ;;
11
;;  References:                                                    ;;
12
;;    forcedeth.c - linux driver (etherboot project)               ;;
13
;;    ethernet driver template by Mike Hibbett                     ;;
14
;;                                                                 ;;
15
;;  The copyright statement is                                     ;;
16
;;                                                                 ;;
17
;;          GNU GENERAL PUBLIC LICENSE                             ;;
18
;;             Version 2, June 1991                                ;;
19
;;                                                                 ;;
20
;;  Copyright 2008 shurf,                                          ;;
21
;;   cit.utc@gmail.com                                             ;;
22
;;                                                                 ;;
23
;;  See file COPYING for details                                   ;;
24
;;                                                                 ;;
25
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
26
 
27
 
4998 hidnplayr 28
format PE DLL native
29
entry START
3545 hidnplayr 30
 
4998 hidnplayr 31
        CURRENT_API             = 0x0200
32
        COMPATIBLE_API          = 0x0100
33
        API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
3545 hidnplayr 34
 
35
        MAX_DEVICES             = 16
36
 
37
        RBLEN                   = 0     ; Receive buffer size: 0=4K 1=8k 2=16k 3=32k 4=64k
38
                                        ; FIXME: option 1 and 2 will not allocate buffer correctly causing data loss!
39
 
40
        DEBUG                   = 1
41
        __DEBUG__               = 1
42
        __DEBUG_LEVEL__         = 2
43
 
44
        RX_RING                 = 4
45
        TX_RING                 = 4
46
 
4998 hidnplayr 47
section '.flat' readable writable executable
48
 
49
include '../proc32.inc'
4467 hidnplayr 50
include '../struct.inc'
51
include '../macros.inc'
3545 hidnplayr 52
include '../fdo.inc'
5074 hidnplayr 53
include '../netdrv.inc'
3545 hidnplayr 54
 
55
;**************************************************************************
56
; forcedeth Register Definitions
57
;**************************************************************************
58
 
59
PCI_DEVICE_ID_NVIDIA_NVENET_1   = 0x01c3
60
PCI_DEVICE_ID_NVIDIA_NVENET_2   = 0x0066
61
PCI_DEVICE_ID_NVIDIA_NVENET_4   = 0x0086
62
PCI_DEVICE_ID_NVIDIA_NVENET_5   = 0x008c
63
PCI_DEVICE_ID_NVIDIA_NVENET_3   = 0x00d6
64
PCI_DEVICE_ID_NVIDIA_NVENET_7   = 0x00df
65
PCI_DEVICE_ID_NVIDIA_NVENET_6   = 0x00e6
66
PCI_DEVICE_ID_NVIDIA_NVENET_8   = 0x0056
67
PCI_DEVICE_ID_NVIDIA_NVENET_9   = 0x0057
68
PCI_DEVICE_ID_NVIDIA_NVENET_10  = 0x0037
69
PCI_DEVICE_ID_NVIDIA_NVENET_11  = 0x0038
70
PCI_DEVICE_ID_NVIDIA_NVENET_12  = 0x0268
71
PCI_DEVICE_ID_NVIDIA_NVENET_13  = 0x0269
72
PCI_DEVICE_ID_NVIDIA_NVENET_14  = 0x0372
73
PCI_DEVICE_ID_NVIDIA_NVENET_15  = 0x0373
74
 
75
UNKSETUP1_VAL             = 0x16070f
76
UNKSETUP2_VAL             = 0x16
77
UNKSETUP3_VAL1            = 0x200010
78
UNKSETUP4_VAL             = 8
79
UNKSETUP5_BIT31           = (1 shl 31)
80
UNKSETUP6_VAL             = 3
81
 
82
TXRXCTL_RXCHECK           = 0x0400
83
MIISTAT_ERROR             = 0x0001
84
MIISTAT_MASK              = 0x000f
85
MIISTAT_MASK2             = 0x000f
86
MIICTL_INUSE              = 0x08000
87
MIICTL_WRITE              = 0x00400
88
MIICTL_ADDRSHIFT          = 5
89
 
90
MIISPEED_BIT8             = (1 shl 8)
91
MIIDELAY                  = 5
92
 
93
IRQ_RX_ERROR              = 0x0001
94
IRQ_RX                    = 0x0002
95
IRQ_RX_NOBUF              = 0x0004
4998 hidnplayr 96
IRQ_TX_ERROR              = 0x0008
97
IRQ_TX_OK                 = 0x0010
98
IRQ_TIMER                 = 0x0020
3545 hidnplayr 99
IRQ_LINK                  = 0x0040
4998 hidnplayr 100
IRQ_RX_FORCED             = 0x0080
101
IRQ_TX_FORCED             = 0x0100
102
IRQ_RECOVER_ERROR         = 0x8200                                           ;
103
IRQMASK_WANTED_2          = IRQ_TX_FORCED + IRQ_LINK + IRQ_RX_ERROR + IRQ_RX + IRQ_TX_OK + IRQ_TX_ERROR
3545 hidnplayr 104
 
4998 hidnplayr 105
IRQ_RX_ALL                = IRQ_RX_ERROR or IRQ_RX or IRQ_RX_NOBUF or IRQ_RX_FORCED
106
IRQ_TX_ALL                = IRQ_TX_ERROR or IRQ_TX_OK or IRQ_TX_FORCED
107
IRQ_OTHER                 = IRQ_LINK or IRQ_TIMER or IRQ_RECOVER_ERROR
3545 hidnplayr 108
 
109
IRQSTAT_MASK              = 0x1ff
110
 
111
TXRXCTL_KICK              = 0x0001
112
TXRXCTL_BIT1              = 0x0002
113
TXRXCTL_BIT2              = 0x0004
114
TXRXCTL_IDLE              = 0x0008
115
TXRXCTL_RESET             = 0x0010
116
TXRXCTL_RXCHECK           = 0x0400
117
 
118
MCASTADDRA_FORCE          = 0x01
119
 
120
MAC_RESET_ASSERT          = 0x0F3
121
 
122
MISC1_HD                  = 0x02
123
MISC1_FORCE               = 0x3b0f3c
124
 
125
PFF_ALWAYS                = 0x7F0008
126
PFF_PROMISC               = 0x80
127
PFF_MYADDR                = 0x20
128
 
129
OFFLOAD_HOMEPHY           = 0x601
130
OFFLOAD_NORMAL            = 4096 shl RBLEN
131
 
132
RNDSEED_MASK              = 0x00ff
133
RNDSEED_FORCE             = 0x7f00
134
RNDSEED_FORCE2            = 0x2d00
135
RNDSEED_FORCE3            = 0x7400
136
 
137
; POLL_DEFAULT is the interval length of the timer source on the nic
138
; POLL_DEFAULT=97 would result in an interval length of 1 ms
139
POLL_DEFAULT              = 970
140
 
141
ADAPTCTL_START            = 0x02
142
ADAPTCTL_LINKUP           = 0x04
143
ADAPTCTL_PHYVALID         = 0x40000
144
ADAPTCTL_RUNNING          = 0x100000
145
ADAPTCTL_PHYSHIFT         = 24
146
 
147
WAKEUPFLAGS_VAL           = 0x7770
148
 
149
POWERSTATE_POWEREDUP      = 0x8000
150
POWERSTATE_VALID          = 0x0100
151
POWERSTATE_MASK           = 0x0003
152
POWERSTATE_D0             = 0x0000
153
POWERSTATE_D1             = 0x0001
154
POWERSTATE_D2             = 0x0002
155
POWERSTATE_D3             = 0x0003
156
 
157
POWERSTATE2_POWERUP_MASK  = 0x0F11
158
POWERSTATE2_POWERUP_REV_A3= 0x0001
159
 
160
RCVCTL_START              = 0x01
161
RCVSTAT_BUSY              = 0x01
162
 
163
XMITCTL_START             = 0x01
164
 
165
LINKSPEED_FORCE           = 0x10000
166
LINKSPEED_10              = 1000
167
LINKSPEED_100             = 100
168
LINKSPEED_1000            = 50
169
 
170
RINGSZ_TXSHIFT            = 0
171
RINGSZ_RXSHIFT            = 16
172
 
173
LPA_1000FULL                    = 0x0800
174
 
175
; Link partner ability register.
176
LPA_SLCT                        = 0x001f  ; Same as advertise selector
177
LPA_10HALF                      = 0x0020  ; Can do 10mbps half-duplex
178
LPA_10FULL                      = 0x0040  ; Can do 10mbps full-duplex
179
LPA_100HALF                     = 0x0080  ; Can do 100mbps half-duplex
180
LPA_100FULL                     = 0x0100  ; Can do 100mbps full-duplex
181
LPA_100BASE4                    = 0x0200  ; Can do 100mbps 4k packets
182
LPA_RESV                        = 0x1c00  ; Unused...
183
LPA_RFAULT                      = 0x2000  ; Link partner faulted
184
LPA_LPACK                       = 0x4000  ; Link partner acked us
185
LPA_NPAGE                       = 0x8000  ; Next page bit
186
 
187
MII_READ                        = (-1)
188
MII_PHYSID1                     = 0x02    ; PHYS ID 1
189
MII_PHYSID2                     = 0x03    ; PHYS ID 2
190
MII_BMCR                        = 0x00    ; Basic mode control register
191
MII_BMSR                        = 0x01    ; Basic mode status register
192
MII_ADVERTISE                   = 0x04    ; Advertisement control reg
193
MII_LPA                         = 0x05    ; Link partner ability reg
194
MII_SREVISION                   = 0x16    ; Silicon revision
195
MII_RESV1                       = 0x17    ; Reserved...
196
MII_NCONFIG                     = 0x1c    ; Network interface config
197
 
198
; PHY defines
199
PHY_OUI_MARVELL                 = 0x5043
200
PHY_OUI_CICADA                  = 0x03f1
201
PHYID1_OUI_MASK                 = 0x03ff
202
PHYID1_OUI_SHFT                 = 6
203
PHYID2_OUI_MASK                 = 0xfc00
204
PHYID2_OUI_SHFT                 = 10
205
PHY_INIT1                       = 0x0f000
206
PHY_INIT2                       = 0x0e00
207
PHY_INIT3                       = 0x01000
208
PHY_INIT4                       = 0x0200
209
PHY_INIT5                       = 0x0004
210
PHY_INIT6                       = 0x02000
211
PHY_GIGABIT                     = 0x0100
212
 
213
PHY_TIMEOUT                     = 0x1
214
PHY_ERROR                       = 0x2
215
 
216
PHY_100                         = 0x1
217
PHY_1000                        = 0x2
218
PHY_HALF                        = 0x100
219
 
220
PHY_RGMII                       = 0x10000000
221
 
222
; desc_ver values:
223
; This field has two purposes:
224
; - Newer nics uses a different ring layout. The layout is selected by
225
;   comparing np->desc_ver with DESC_VER_xy.
226
; - It contains bits that are forced on when writing to TxRxControl.
227
DESC_VER_1                      = 0x0
228
DESC_VER_2                      = (0x02100 or TXRXCTL_RXCHECK)
229
 
230
NV_TX_LASTPACKET                = (1 shl 16)
231
NV_TX_RETRYERROR                = (1 shl 19)
232
NV_TX_LASTPACKET1               = (1 shl 24)
233
NV_TX_DEFERRED                  = (1 shl 26)
234
NV_TX_CARRIERLOST               = (1 shl 27)
235
NV_TX_LATECOLLISION             = (1 shl 28)
236
NV_TX_UNDERFLOW                 = (1 shl 29)
237
NV_TX_ERROR                     = (1 shl 30)
238
NV_TX_VALID                     = (1 shl 31)
239
 
240
NV_TX2_LASTPACKET               = (1 shl 29)
241
NV_TX2_RETRYERROR               = (1 shl 18)
242
NV_TX2_LASTPACKET1              = (1 shl 23)
243
NV_TX2_DEFERRED                 = (1 shl 25)
244
NV_TX2_CARRIERLOST              = (1 shl 26)
245
NV_TX2_LATECOLLISION            = (1 shl 27)
246
NV_TX2_UNDERFLOW                = (1 shl 28)
247
; error and valid are the same for both
248
NV_TX2_ERROR                    = (1 shl 30)
249
NV_TX2_VALID                    = (1 shl 31)
250
 
251
NV_RX_DESCRIPTORVALID           = (1 shl 16)
252
NV_RX_AVAIL                     = (1 shl 31)
253
 
254
NV_RX2_DESCRIPTORVALID          = (1 shl 29)
255
 
256
FLAG_MASK_V1                    = 0xffff0000
257
FLAG_MASK_V2                    = 0xffffc000
258
LEN_MASK_V1                     = (0xffffffff xor FLAG_MASK_V1)
259
LEN_MASK_V2                     = (0xffffffff xor FLAG_MASK_V2)
260
 
261
; Miscelaneous hardware related defines:
262
NV_PCI_REGSZ_VER1               = 0x270
263
NV_PCI_REGSZ_VER2               = 0x604
264
; various timeout delays: all in usec
265
NV_TXRX_RESET_DELAY             = 4
266
NV_TXSTOP_DELAY1                = 10
267
NV_TXSTOP_DELAY1MAX             = 500000
268
NV_TXSTOP_DELAY2                = 100
269
NV_RXSTOP_DELAY1                = 10
270
NV_RXSTOP_DELAY1MAX             = 500000
271
NV_RXSTOP_DELAY2                = 100
272
NV_SETUP5_DELAY                 = 5
273
NV_SETUP5_DELAYMAX              = 50000
274
NV_POWERUP_DELAY                = 5
275
NV_POWERUP_DELAYMAX             = 5000
276
NV_MIIBUSY_DELAY                = 50
277
NV_MIIPHY_DELAY                 = 10
278
NV_MIIPHY_DELAYMAX              = 10000
279
NV_MAC_RESET_DELAY              = 64
280
NV_WAKEUPPATTERNS               = 5
281
NV_WAKEUPMASKENTRIES            = 4
282
 
283
; Advertisement control register.
284
ADVERTISE_SLCT                  = 0x001f  ; Selector bits
285
ADVERTISE_CSMA                  = 0x0001  ; Only selector supported
286
ADVERTISE_10HALF                = 0x0020  ; Try for 10mbps half-duplex
287
ADVERTISE_10FULL                = 0x0040  ; Try for 10mbps full-duplex
288
ADVERTISE_100HALF               = 0x0080  ; Try for 100mbps half-duplex
289
ADVERTISE_100FULL               = 0x0100  ; Try for 100mbps full-duplex
290
ADVERTISE_100BASE4              = 0x0200  ; Try for 100mbps 4k packets
291
ADVERTISE_RESV                  = 0x1c00  ; Unused...
292
ADVERTISE_RFAULT                = 0x2000  ; Say we can detect faults
293
ADVERTISE_LPACK                 = 0x4000  ; Ack link partners response
294
ADVERTISE_NPAGE                 = 0x8000  ; Next page bit
295
 
296
ADVERTISE_FULL                  = (ADVERTISE_100FULL or ADVERTISE_10FULL or ADVERTISE_CSMA)
297
ADVERTISE_ALL                   = (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL)
298
 
299
MII_1000BT_CR                   = 0x09
300
MII_1000BT_SR                   = 0x0a
301
ADVERTISE_1000FULL              = 0x0200
302
ADVERTISE_1000HALF              = 0x0100
303
 
304
BMCR_ANRESTART                  = 0x0200  ; Auto negotiation restart
305
BMCR_ANENABLE                   = 0x1000  ; Enable auto negotiation
306
BMCR_SPEED100                   = 0x2000  ; Select 100Mbps
307
BMCR_LOOPBACK                   = 0x4000  ; TXD loopback bits
308
BMCR_RESET                      = 0x8000  ; Reset the DP83840
309
 
310
; Basic mode status register.
311
BMSR_ERCAP                      = 0x0001  ; Ext-reg capability
312
BMSR_JCD                        = 0x0002  ; Jabber detected
313
BMSR_LSTATUS                    = 0x0004  ; Link status
314
BMSR_ANEGCAPABLE                = 0x0008  ; Able to do auto-negotiation
315
BMSR_RFAULT                     = 0x0010  ; Remote fault detected
316
BMSR_ANEGCOMPLETE               = 0x0020  ; Auto-negotiation complete
317
BMSR_RESV                       = 0x07c0  ; Unused...
318
BMSR_10HALF                     = 0x0800  ; Can do 10mbps, half-duplex
319
BMSR_10FULL                     = 0x1000  ; Can do 10mbps, full-duplex
320
BMSR_100HALF                    = 0x2000  ; Can do 100mbps, half-duplex
321
BMSR_100FULL                    = 0x4000  ; Can do 100mbps, full-duplex
322
BMSR_100BASE4                   = 0x8000  ; Can do 100mbps, 4k packets
323
 
324
struct  TxDesc
325
        PacketBuffer            dd ?
326
        FlagLen                 dd ?
327
ends
328
 
329
struct  RxDesc
330
        PacketBuffer            dd ?
331
        FlagLen                 dd ?
332
ends
333
 
4998 hidnplayr 334
struct  device                  ETH_DEVICE
3545 hidnplayr 335
 
4998 hidnplayr 336
        pci_bus                 dd ?
337
        pci_dev                 dd ?
3545 hidnplayr 338
 
4998 hidnplayr 339
        mmio_addr               dd ?
340
        vendor_id               dw ?
341
        device_id               dw ?
342
        txflags                 dd ?
343
        desc_ver                dd ?
344
        irqmask                 dd ?
345
        wolenabled              dd ?
346
        in_shutdown             dd ?
347
        cur_rx                  dd ?
348
        cur_tx                  dd ?
349
        last_tx                 dd ?
350
        phyaddr                 dd ?
351
        phy_oui                 dd ?
352
        gigabit                 dd ?
353
        needs_mac_reset         dd ?
354
        linkspeed               dd ?
355
        duplex                  dd ?
356
        nocable                 dd ?
3545 hidnplayr 357
 
4998 hidnplayr 358
                                rb 0x100 - ($ and 0xff)
359
        tx_ring                 rd (TX_RING * sizeof.TxDesc) /4*2
3545 hidnplayr 360
 
4998 hidnplayr 361
                                rb 0x100 - ($ and 0xff)
362
        rx_ring                 rd (RX_RING * sizeof.RxDesc) /4*2
3545 hidnplayr 363
 
4998 hidnplayr 364
ends
3545 hidnplayr 365
 
366
 
367
 
368
virtual at edi
369
        IrqStatus               dd ?
370
        IrqMask                 dd ?
371
        UnknownSetupReg6        dd ?
372
        PollingInterval         dd ?
373
end virtual
374
 
375
virtual at edi + 0x3c
376
        MacReset                dd ?
377
end virtual
378
 
379
virtual at edi + 0x80
380
        Misc1                   dd ?
381
        TransmitterControl      dd ?
382
        TransmitterStatus       dd ?
383
        PacketFilterFlags       dd ?
384
        OffloadConfig           dd ?
385
        ReceiverControl         dd ?
386
        ReceiverStatus          dd ?
387
        RandomSeed              dd ?
388
        UnknownSetupReg1        dd ?
389
        UnknownSetupReg2        dd ?
390
        MacAddrA                dd ?
391
        MacAddrB                dd ?
392
        MulticastAddrA          dd ?
393
        MulticastAddrB          dd ?
394
        MulticastMaskA          dd ?
395
        MulticastMaskB          dd ?
396
        PhyInterface            dd ?
397
end virtual
398
 
399
virtual at edi + 0x100
400
        TxRingPhysAddr          dd ?
401
        RxRingPhysAddr          dd ?
402
        RingSizes               dd ?
403
        UnknownTransmitterReg   dd ?
404
        LinkSpeed               dd ?
405
end virtual
406
 
407
virtual at edi + 0x130
408
        UnknownSetupReg5        dd ?
409
end virtual
410
 
411
virtual at edi + 0x13c
412
        UnknownSetupReg3        dd ?
413
end virtual
414
 
415
virtual at edi + 0x144
416
        TxRxControl             dd ?
417
end virtual
418
 
419
virtual at edi + 0x180
420
        MIIStatus               dd ?
421
        UnknownSetupReg4        dd ?
422
        AdapterControl          dd ?
423
        MIISpeed                dd ?
424
        MIIControl              dd ?
425
        MIIData                 dd ?
426
end virtual
427
 
428
virtual at edi + 0x200
429
        WakeUpFlags             dd ?
430
end virtual
431
 
432
virtual at edi + 0x26c
433
        PowerState              dd ?
434
end virtual
435
 
436
virtual at edi + 0x600
437
        PowerState2             dd ?
438
end virtual
439
 
440
 
441
 
442
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
443
;;                        ;;
444
;; proc START             ;;
445
;;                        ;;
446
;; (standard driver proc) ;;
447
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
448
 
4998 hidnplayr 449
proc START c, reason:dword, cmdline:dword
3545 hidnplayr 450
 
4998 hidnplayr 451
        cmp     [reason], DRV_ENTRY
452
        jne     .fail
3545 hidnplayr 453
 
4470 hidnplayr 454
        DEBUGF  2,"Loading driver\n"
4998 hidnplayr 455
        invoke  RegService, my_service, service_proc
3545 hidnplayr 456
        ret
457
 
4998 hidnplayr 458
  .fail:
459
        xor     eax, eax
3545 hidnplayr 460
        ret
461
 
462
endp
463
 
464
 
465
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
466
;;                        ;;
467
;; proc SERVICE_PROC      ;;
468
;;                        ;;
469
;; (standard driver proc) ;;
470
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
471
 
472
proc service_proc stdcall, ioctl:dword
473
 
474
        mov     edx, [ioctl]
4470 hidnplayr 475
        mov     eax, [edx + IOCTL.io_code]
3545 hidnplayr 476
 
477
;------------------------------------------------------
478
 
479
        cmp     eax, 0 ;SRV_GETVERSION
480
        jne     @F
481
 
4470 hidnplayr 482
        cmp     [edx + IOCTL.out_size], 4
3545 hidnplayr 483
        jb      .fail
4470 hidnplayr 484
        mov     eax, [edx + IOCTL.output]
3545 hidnplayr 485
        mov     [eax], dword API_VERSION
486
 
487
        xor     eax, eax
488
        ret
489
 
490
;------------------------------------------------------
491
  @@:
492
        cmp     eax, 1 ;SRV_HOOK
493
        jne     .fail
494
 
4470 hidnplayr 495
        cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
3545 hidnplayr 496
        jb      .fail
497
 
4470 hidnplayr 498
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 499
        cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
500
        jne     .fail                                   ; other types arent supported for this card yet
501
 
502
; check if the device is already listed
503
 
504
        mov     esi, device_list
505
        mov     ecx, [devices]
506
        test    ecx, ecx
507
        jz      .firstdevice
508
 
4470 hidnplayr 509
;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
3545 hidnplayr 510
        mov     ax, [eax+1]
511
  .nextdevice:
512
        mov     ebx, [esi]
4998 hidnplayr 513
        cmp     al, byte [ebx + device.pci_bus]               ; compare with pci and device num in device list (notice the usage of word instead of byte)
3545 hidnplayr 514
        jne     @f
4998 hidnplayr 515
        cmp     ah, byte [ebx + device.pci_dev]
3545 hidnplayr 516
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
517
  @@:
518
        add     esi, 4
519
        loop    .nextdevice
520
 
521
 
522
; This device doesnt have its own eth_device structure yet, lets create one
523
  .firstdevice:
524
        cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
525
        jae     .fail
526
 
4998 hidnplayr 527
        allocate_and_clear ebx, sizeof.device, .fail      ; Allocate the buffer for device structure
3545 hidnplayr 528
 
529
; Fill in the direct call addresses into the struct
530
 
4998 hidnplayr 531
        mov     [ebx + device.reset], reset
532
        mov     [ebx + device.transmit], transmit
533
        mov     [ebx + device.unload], .fail
534
        mov     [ebx + device.name], my_service
3545 hidnplayr 535
 
536
; save the pci bus and device numbers
537
 
4470 hidnplayr 538
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 539
        movzx   ecx, byte [eax+1]
4998 hidnplayr 540
        mov     [ebx + device.pci_bus], ecx
3545 hidnplayr 541
        movzx   ecx, byte [eax+2]
4998 hidnplayr 542
        mov     [ebx + device.pci_dev], ecx
3545 hidnplayr 543
 
4998 hidnplayr 544
        DEBUGF  1,"Hooking into device, dev:%x, bus:%x\n", [ebx + device.pci_dev], [ebx + device.pci_bus]
3545 hidnplayr 545
 
546
; Ok, the eth_device structure is ready, let's probe the device
547
        call    probe                                                   ; this function will output in eax
548
        test    eax, eax
549
        jnz     .err                                                    ; If an error occured, exit
550
 
551
        mov     eax, [devices]                                          ; Add the device structure to our device list
552
        mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
553
        inc     [devices]                                               ;
554
 
4998 hidnplayr 555
        mov     [ebx + device.type], NET_TYPE_ETH
556
        invoke  NetRegDev
3545 hidnplayr 557
 
558
        cmp     eax, -1
559
        je      .destroy
560
 
561
        ret
562
 
563
; If the device was already loaded, find the device number and return it in eax
564
 
565
  .find_devicenum:
566
        DEBUGF  1,"Trying to find device number of already registered device\n"
4998 hidnplayr 567
        invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
3545 hidnplayr 568
                                                                        ; into a device number in edi
569
        mov     eax, edi                                                ; Application wants it in eax instead
570
        DEBUGF  1,"Kernel says: %u\n", eax
571
        ret
572
 
573
; If an error occured, remove all allocated data and exit (returning -1 in eax)
574
 
575
  .destroy:
576
        ; todo: reset device into virgin state
577
 
578
  .err:
4998 hidnplayr 579
        invoke  KernelFree, ebx
3545 hidnplayr 580
  .fail:
581
 
582
        ret
583
 
584
;------------------------------------------------------
585
endp
586
 
587
 
588
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
589
;;                                                                        ;;
590
;;        Actual Hardware dependent code starts here                      ;;
591
;;                                                                        ;;
592
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
593
 
594
 
595
 
596
 
597
;***************************************************************************
598
;   Function
599
;      probe
600
;   Description
601
;      Searches for an ethernet card, enables it and clears the rx buffer
602
;
603
;***************************************************************************
604
align 4
605
probe:
606
 
607
        DEBUGF  1,"probe\n"
608
 
4998 hidnplayr 609
        mov     [ebx + device.needs_mac_reset], 0
3545 hidnplayr 610
 
4998 hidnplayr 611
; Make the device a bus master and enable response in I/O space
612
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
613
        or      al, PCI_CMD_MASTER + PCI_CMD_PIO ; + PCI_CMD_MMIO
614
        invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
3545 hidnplayr 615
 
4998 hidnplayr 616
; Adjust PCI latency to be at least 32
617
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.max_latency
618
        cmp     al, 32
619
        jae     @f
620
        mov     al, 32
621
        invoke  PciWrite8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.max_latency, eax
622
  @@:
3545 hidnplayr 623
 
4998 hidnplayr 624
; Now, it's time to find the base mmio addres of the PCI device
625
        stdcall PCI_find_mmio32, [ebx + device.pci_bus], [ebx + device.pci_dev] ; returns in eax
626
        DEBUGF 1,"mmio_addr= 0x%x\n", eax
627
 
628
; Create virtual mapping of the physical memory
629
        invoke  MapIoMem, eax, 10000h, PG_SW + PG_NOCACHE
3545 hidnplayr 630
        test    eax, eax
631
        jz      fail
4998 hidnplayr 632
        mov     [ebx + device.mmio_addr], eax
633
        DEBUGF 1,"mapped mmio_addr= 0x%x\n", eax
3545 hidnplayr 634
 
4998 hidnplayr 635
; Read PCI vendor/device ID
636
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.vendor_id
637
        mov     dword[ebx + device.vendor_id], eax
638
        DEBUGF 1,"vendor = 0x%x\n", [ebx + device.vendor_id]:4
639
        DEBUGF 1,"device = 0x%x\n", [ebx + device.device_id]:4
3545 hidnplayr 640
 
641
;-------------------------------------
642
; handle different descriptor versions
4998 hidnplayr 643
        mov     [ebx + device.desc_ver], DESC_VER_1
644
        mov     ax, [ebx + device.device_id]
645
        cmp     ax, PCI_DEVICE_ID_NVIDIA_NVENET_1
3545 hidnplayr 646
        je      .ver1
4998 hidnplayr 647
        cmp     ax, PCI_DEVICE_ID_NVIDIA_NVENET_2
3545 hidnplayr 648
        je      .ver1
4998 hidnplayr 649
        cmp     ax, PCI_DEVICE_ID_NVIDIA_NVENET_3
3545 hidnplayr 650
        je      .ver1
4998 hidnplayr 651
        mov     [ebx + device.desc_ver], DESC_VER_2
3545 hidnplayr 652
  .ver1:
653
 
654
        call    read_mac
655
 
656
        ; disable WOL
657
        mov     [WakeUpFlags], 0
4998 hidnplayr 658
        mov     [ebx + device.wolenabled], 0
3545 hidnplayr 659
 
4998 hidnplayr 660
        mov     [ebx + device.txflags], (NV_TX2_LASTPACKET or NV_TX2_VALID)
661
        cmp     [ebx + device.desc_ver], DESC_VER_1
3545 hidnplayr 662
        jne     @f
4998 hidnplayr 663
        mov     [ebx + device.txflags], (NV_TX_LASTPACKET or NV_TX_VALID)
3545 hidnplayr 664
      @@:
665
 
666
; BEGIN of switch (pci->dev_id)
667
 
4998 hidnplayr 668
        cmp     [ebx + device.device_id], 0x01C3
669
        jne     .not_0x01c3
3545 hidnplayr 670
        ; nforce
4998 hidnplayr 671
        mov     [ebx + device.irqmask], (IRQMASK_WANTED_2 or IRQ_TIMER)         ;;; Was 0
3545 hidnplayr 672
        jmp     .find_phy
4998 hidnplayr 673
  .not_0x01c3:
3545 hidnplayr 674
 
4998 hidnplayr 675
        cmp     [ebx + device.device_id], 0x0066
3545 hidnplayr 676
        je      @f
4998 hidnplayr 677
        cmp     [ebx + device.device_id], 0x00D6
678
        jne     .not_0x0066
3545 hidnplayr 679
  @@:
4998 hidnplayr 680
        mov     [ebx + device.irqmask], (IRQMASK_WANTED_2 or IRQ_TIMER)         ;;;; was 0
681
        cmp     [ebx + device.desc_ver], DESC_VER_1
3545 hidnplayr 682
        jne     @f
4998 hidnplayr 683
        or      [ebx + device.txflags], NV_TX_LASTPACKET1
3545 hidnplayr 684
        jmp     .find_phy
685
  @@:
4998 hidnplayr 686
        or      [ebx + device.txflags], NV_TX2_LASTPACKET1
3545 hidnplayr 687
        jmp     .find_phy
4998 hidnplayr 688
  .not_0x0066:
3545 hidnplayr 689
 
4998 hidnplayr 690
        cmp     [ebx + device.device_id], 0x0086
3545 hidnplayr 691
        je      @f
4998 hidnplayr 692
        cmp     [ebx + device.device_id], 0x008c
3545 hidnplayr 693
        je      @f
4998 hidnplayr 694
        cmp     [ebx + device.device_id], 0x00e6
3545 hidnplayr 695
        je      @f
4998 hidnplayr 696
        cmp     [ebx + device.device_id], 0x00df
3545 hidnplayr 697
        je      @f
4998 hidnplayr 698
        cmp     [ebx + device.device_id], 0x0056
3545 hidnplayr 699
        je      @f
4998 hidnplayr 700
        cmp     [ebx + device.device_id], 0x0057
3545 hidnplayr 701
        je      @f
4998 hidnplayr 702
        cmp     [ebx + device.device_id], 0x0037
3545 hidnplayr 703
        je      @f
4998 hidnplayr 704
        cmp     [ebx + device.device_id], 0x0038
705
        jne     .not_0x0086
3545 hidnplayr 706
 
707
      @@:
4998 hidnplayr 708
        mov     [ebx + device.irqmask], (IRQMASK_WANTED_2 or IRQ_TIMER) ;;; was 0
3545 hidnplayr 709
 
4998 hidnplayr 710
        cmp     [ebx + device.desc_ver], DESC_VER_1
3545 hidnplayr 711
        jne     @f
4998 hidnplayr 712
        or      [ebx + device.txflags], NV_TX_LASTPACKET1
3545 hidnplayr 713
        jmp     .find_phy
714
       @@:
4998 hidnplayr 715
        or      [ebx + device.txflags], NV_TX2_LASTPACKET1
3545 hidnplayr 716
        jmp     .find_phy
4998 hidnplayr 717
  .not_0x0086:
3545 hidnplayr 718
 
719
;       cmp     word [device_id], 0x0268
720
;       je      @f
721
;       cmp     word [device_id], 0x0269
722
;       je      @f
723
;       cmp     word [device_id], 0x0372
724
;       je      @f
725
;       cmp     word [device_id], 0x0373
726
;       je      @f
727
;       jmp     .default_switch
728
;@@:
4998 hidnplayr 729
        cmp     [ebx + device.device_id], 0x0268
3545 hidnplayr 730
        jb      .undefined
731
 
732
; Get device revision
4998 hidnplayr 733
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.revision_id
734
        mov     edi, [ebx + device.mmio_addr]   ;;;;;
3545 hidnplayr 735
 
736
; take phy and nic out of low power mode
737
        mov     ecx, [PowerState2]
738
        and     ecx, not POWERSTATE2_POWERUP_MASK
4998 hidnplayr 739
        cmp     [ebx + device.device_id], PCI_DEVICE_ID_NVIDIA_NVENET_12
740
        je      @f
741
        cmp     [ebx + device.device_id], PCI_DEVICE_ID_NVIDIA_NVENET_13
742
        jne     .set_powerstate
743
  @@:
3545 hidnplayr 744
        cmp     al, 0xA3
4998 hidnplayr 745
        jb      .set_powerstate
3545 hidnplayr 746
        or      ecx, POWERSTATE2_POWERUP_REV_A3
4998 hidnplayr 747
  .set_powerstate:
3545 hidnplayr 748
        mov     [PowerState2], ecx
749
 
750
        ; DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ
4998 hidnplayr 751
        mov     [ebx + device.irqmask], (IRQMASK_WANTED_2 or IRQ_TIMER)         ; was 0
3545 hidnplayr 752
 
4998 hidnplayr 753
        mov     [ebx + device.needs_mac_reset], 1
754
        cmp     [ebx + device.desc_ver], DESC_VER_1
3545 hidnplayr 755
        jne     @f
4998 hidnplayr 756
        or      [ebx + device.txflags], NV_TX_LASTPACKET1
3545 hidnplayr 757
        jmp     .find_phy
4998 hidnplayr 758
 
3545 hidnplayr 759
       @@:
4998 hidnplayr 760
        cmp     [ebx + device.desc_ver], DESC_VER_2
3545 hidnplayr 761
        jne     .undefined
4998 hidnplayr 762
        or      [ebx + device.txflags], NV_TX2_LASTPACKET1
3545 hidnplayr 763
        jmp     .find_phy
764
 
765
  .undefined:
4998 hidnplayr 766
        DEBUGF  2,"Your card was undefined in this driver.\n"
767
        or      eax, -1
768
        ret
3545 hidnplayr 769
 
770
; Find a suitable phy
771
; Start with address 1 to 31, then do 0, then fail
772
 
773
  .find_phy:
774
        xor     edx, edx
775
  .phy_loop:
776
        inc     edx
777
        and     edx, 0x1f       ; phyaddr = i & 0x1f
778
        mov     eax, MII_PHYSID1
779
        mov     ecx, MII_READ
780
        call    mii_rw          ; EDX - addr, EAX - miireg, ECX - value
781
 
4998 hidnplayr 782
        cmp     eax, 0x0000ffff
3545 hidnplayr 783
        je      .try_next
4998 hidnplayr 784
        test    eax, 0x80000000
785
        jnz     .try_next
3545 hidnplayr 786
        mov     esi, eax
787
 
788
        mov     eax, MII_PHYSID2
789
        mov     ecx, MII_READ
790
        call    mii_rw
791
 
4998 hidnplayr 792
        cmp     eax, 0x0000ffff
3545 hidnplayr 793
        je      .try_next
4998 hidnplayr 794
        test    eax, 0x80000000
795
        jnz     .try_next
3545 hidnplayr 796
        jmp     .got_it
797
 
798
  .try_next:
799
        test    edx, edx
800
        jnz     .phy_loop
801
 
802
        ; PHY in isolate mode? No phy attached and user wants to test loopback?
803
        ; Very odd, but can be correct.
804
 
4998 hidnplayr 805
        DEBUGF  2,"Could not find a valid PHY.\n"
3545 hidnplayr 806
        jmp     .no_phy
807
 
808
  .got_it:
809
        and     esi, PHYID1_OUI_MASK
810
        shl     esi, PHYID1_OUI_SHFT
811
        and     eax, PHYID2_OUI_MASK
812
        shr     eax, PHYID2_OUI_SHFT
4998 hidnplayr 813
        or      eax, esi
3545 hidnplayr 814
 
4998 hidnplayr 815
        mov     [ebx + device.phyaddr], edx
816
        mov     [ebx + device.phy_oui], eax
3545 hidnplayr 817
 
4998 hidnplayr 818
        DEBUGF 1,"Found PHY with OUI:0x%x at address:0x%x\n", eax, edx
3545 hidnplayr 819
 
820
        call    phy_init
821
 
822
  .no_phy:
823
 
4998 hidnplayr 824
        cmp     [ebx + device.needs_mac_reset], 0
3545 hidnplayr 825
        je      @f
826
        call    mac_reset
827
  @@:
828
 
829
;***************************************************************************
830
;   Function
831
;      reset
832
;   Description
833
;      Place the chip (ie, the ethernet card) into a virgin state
834
;      No inputs
835
;      All registers destroyed
836
;
837
;***************************************************************************
838
reset:
839
 
840
        DEBUGF  1,"Resetting\n"
841
 
4998 hidnplayr 842
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
3545 hidnplayr 843
        movzx   eax, al
4998 hidnplayr 844
        invoke  AttachIntHandler, eax, int_handler, ebx
3545 hidnplayr 845
        test    eax, eax
846
        jnz     @f
4998 hidnplayr 847
        DEBUGF  2,"Could not attach int handler!\n"
848
        or      eax, -1
849
        ret
3545 hidnplayr 850
       @@:
851
 
852
; erase previous misconfiguration
853
 
4998 hidnplayr 854
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 855
        mov     [MulticastAddrA], MCASTADDRA_FORCE
856
        mov     [MulticastAddrB], 0
857
        mov     [MulticastMaskA], 0
858
        mov     [MulticastMaskB], 0
859
        mov     [PacketFilterFlags], 0
860
        mov     [TransmitterControl], 0
861
        mov     [ReceiverControl], 0
862
        mov     [AdapterControl], 0
863
 
864
; initialize descriptor rings
865
 
866
        call    init_ring
867
 
868
        mov     [LinkSpeed], 0
869
        mov     [UnknownTransmitterReg], 0
870
 
871
        call    txrx_reset
4998 hidnplayr 872
 
3545 hidnplayr 873
        mov     [UnknownSetupReg6], 0
4998 hidnplayr 874
        mov     [ebx + device.in_shutdown], 0
3545 hidnplayr 875
 
876
; give hw rings
877
 
4998 hidnplayr 878
        lea     eax, [ebx + device.rx_ring]
879
        invoke  GetPhysAddr
3545 hidnplayr 880
        mov     [RxRingPhysAddr], eax
881
 
4998 hidnplayr 882
        lea     eax, [ebx + device.tx_ring]
883
        invoke  GetPhysAddr
3545 hidnplayr 884
        mov     [TxRingPhysAddr], eax
885
 
886
        mov     [RingSizes], (((RX_RING - 1) shl RINGSZ_RXSHIFT) + ((TX_RING - 1) shl RINGSZ_TXSHIFT))
887
 
888
;
889
 
4998 hidnplayr 890
        mov     [ebx + device.linkspeed], (LINKSPEED_FORCE or LINKSPEED_10)
891
        mov     [ebx + device.duplex], 0
3545 hidnplayr 892
        mov     [LinkSpeed], (LINKSPEED_FORCE or LINKSPEED_10)
893
        mov     [UnknownSetupReg3], UNKSETUP3_VAL1
894
 
4998 hidnplayr 895
        mov     eax, [ebx + device.desc_ver]
3545 hidnplayr 896
        mov     [TxRxControl], eax
897
        call    pci_push
898
        or      eax, TXRXCTL_BIT1
899
        mov     [TxRxControl], eax
900
 
901
        stdcall reg_delay, UnknownSetupReg5-edi, UNKSETUP5_BIT31, UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, 0
902
 
903
        mov     [UnknownSetupReg4], 0
904
        mov     [MIIStatus], MIISTAT_MASK2
905
 
906
;
907
 
908
        mov     [Misc1], (MISC1_FORCE or MISC1_HD)
909
 
910
        mov     eax, [TransmitterStatus]
911
        mov     [TransmitterStatus], eax
912
 
913
        mov     [PacketFilterFlags], PFF_ALWAYS
914
 
915
        mov     [OffloadConfig], OFFLOAD_NORMAL
916
 
917
        mov     eax, [ReceiverStatus]
918
        mov     [ReceiverStatus], eax
919
 
920
; set random seed
921
        push    ebx
4998 hidnplayr 922
        invoke  GetTimerTicks   ; bad idea, driver is started at system startup in 90% of cases..
3545 hidnplayr 923
        pop     ebx
924
 
4998 hidnplayr 925
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 926
 
927
        and     eax, RNDSEED_MASK
928
        or      eax, RNDSEED_FORCE
929
        mov     [RandomSeed], eax
930
 
931
        mov     [UnknownSetupReg1], UNKSETUP1_VAL
932
        mov     [UnknownSetupReg2], UNKSETUP2_VAL
933
        mov     [PollingInterval], POLL_DEFAULT
934
        mov     [UnknownSetupReg6], UNKSETUP6_VAL
935
 
4998 hidnplayr 936
        mov     eax, [ebx + device.phyaddr]
3545 hidnplayr 937
        shl     eax, ADAPTCTL_PHYSHIFT
938
        or      eax, (ADAPTCTL_PHYVALID or ADAPTCTL_RUNNING)
939
        mov     [AdapterControl], eax
940
 
941
        mov     [MIISpeed], (MIISPEED_BIT8 or MIIDELAY)
942
        mov     [UnknownSetupReg4], UNKSETUP4_VAL
943
        mov     [WakeUpFlags], WAKEUPFLAGS_VAL
944
 
945
        or      [PowerState], POWERSTATE_POWEREDUP
946
        call    pci_push
947
 
948
        mov     esi, 10
4998 hidnplayr 949
        invoke  Sleep
3545 hidnplayr 950
 
951
        or      [PowerState], POWERSTATE_VALID
952
        mov     [IrqMask], 0
953
 
954
;;;     ; ??? Mask RX interrupts
955
        mov      [IrqMask], IRQ_RX_ALL + IRQ_TX_ALL
956
;;;     ; ??? Mask TX interrupts
957
;;;     mov      [IrqMask], IRQ_TX_ALL
958
;;;     ; ??? Mask OTHER interrupts
959
;;;     mov      [IrqMask], IRQ_OTHER_ALL
960
        call    pci_push
961
 
962
        mov     [MIIStatus], MIISTAT_MASK2
963
        mov     [IrqStatus], IRQSTAT_MASK
964
        call    pci_push
965
 
966
        mov     [MulticastAddrA], MCASTADDRA_FORCE
967
        mov     [MulticastAddrB], 0
968
        mov     [MulticastMaskA], 0
969
        mov     [MulticastMaskB], 0
970
 
971
        mov     [PacketFilterFlags], (PFF_ALWAYS or PFF_MYADDR)
972
 
973
        call    set_multicast
974
 
975
        ; One manual link speed update: Interrupts are enabled, future link
976
        ; speed changes cause interrupts and are handled by nv_link_irq().
977
 
978
        mov     eax, [MIIStatus]
979
        mov     [MIIStatus], MIISTAT_MASK
980
        DEBUGF  1,"startup: got 0x%x\n", eax
981
 
982
        call    update_linkspeed
983
 
984
        mov     [TransmitterControl], XMITCTL_START       ; start TX
985
        call    pci_push
986
 
4998 hidnplayr 987
        mov     [ebx + device.nocable], 0
3545 hidnplayr 988
        test    eax, eax
989
        jnz     .return
990
        DEBUGF  1,"no link during initialization.\n"
4998 hidnplayr 991
        mov     [ebx + device.nocable], 1
3545 hidnplayr 992
 
993
  .return:
994
        xor     eax, eax        ; Indicate that we have successfully reset the card
4998 hidnplayr 995
        mov     [ebx + device.mtu], 1514 ;;; FIXME
3545 hidnplayr 996
        ret
997
 
998
 
999
fail:
1000
        or      eax, -1
1001
        ret
1002
 
1003
;--------------------------------------------------------
1004
;
1005
; MII_RW
1006
;
1007
; read/write a register on the PHY.
1008
; Caller must guarantee serialization
4998 hidnplayr 1009
; Input:  EAX - miireg, EDX - phy addr, ECX - value to write (or -1 to read)
1010
; Output: EAX - retval (lower 16 bits)
3545 hidnplayr 1011
;
1012
;--------------------------------------------------------
1013
 
1014
mii_rw:
1015
 
1016
        DEBUGF  1,"mii_rw: 0x%x to reg %d at PHY %d\n", ecx, eax, edx
1017
 
1018
        push    edx
1019
 
4998 hidnplayr 1020
        mov     edi, [ebx + device.mmio_addr]
1021
 
1022
; Check if MII interface is busy
3545 hidnplayr 1023
        mov     [MIIStatus], MIISTAT_MASK
4998 hidnplayr 1024
       @@:
3545 hidnplayr 1025
        test    [MIIControl], MIICTL_INUSE
1026
        jz      @f
1027
        mov     [MIIControl], MIICTL_INUSE
1028
 
4998 hidnplayr 1029
        DEBUGF  1,"mii_rw: in use!\n"
1030
        pusha
3545 hidnplayr 1031
        mov     esi, NV_MIIBUSY_DELAY
4998 hidnplayr 1032
        invoke  Sleep
1033
        popa
1034
        jmp     @r
3545 hidnplayr 1035
       @@:
1036
 
4998 hidnplayr 1037
; Set the address we want to access
3545 hidnplayr 1038
        shl     edx, MIICTL_ADDRSHIFT
1039
        or      edx, eax
1040
 
4998 hidnplayr 1041
        ; When writing, write the data first.
3545 hidnplayr 1042
        cmp     ecx, MII_READ
1043
        je      @f
1044
        mov     [MIIData], ecx
1045
        or      edx, MIICTL_WRITE
1046
       @@:
4998 hidnplayr 1047
 
3545 hidnplayr 1048
        mov     [MIIControl], edx
1049
 
4998 hidnplayr 1050
; Wait for read/write to complete
3545 hidnplayr 1051
        stdcall reg_delay, MIIControl-edi, MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, 0
1052
 
1053
        test    eax, eax
1054
        jz      @f
1055
        DEBUGF  1,"mii_rw timed out.\n"
1056
        or      eax, -1
1057
        jmp     .return
4998 hidnplayr 1058
 
3545 hidnplayr 1059
       @@:
1060
        cmp     ecx, MII_READ
4998 hidnplayr 1061
        je      .read
3545 hidnplayr 1062
; it was a write operation - fewer failures are detectable
1063
        DEBUGF  1,"mii_rw write: ok\n"
1064
        xor     eax, eax
1065
        jmp     .return
1066
 
4998 hidnplayr 1067
  .read:
3545 hidnplayr 1068
        mov     eax, [MIIStatus]
1069
        test    eax, MIISTAT_ERROR
1070
        jz      @f
1071
        DEBUGF  1,"mii read: failed.\n"
1072
        or      eax, -1
1073
        jmp     .return
4998 hidnplayr 1074
 
3545 hidnplayr 1075
       @@:
1076
        mov     eax, [MIIData]
1077
        DEBUGF  1,"mii read: 0x%x.\n", eax
1078
 
1079
  .return:
1080
        pop     edx
1081
        ret
1082
 
1083
 
1084
 
1085
 
1086
 
1087
; Input:  offset:word, mask:dword, target:dword, delay:word, delaymax:word, msg:dword
1088
; Output: EAX - 0|1
1089
 
1090
proc    reg_delay, offset:dword, mask:dword, target:dword, delay:dword, delaymax:dword, msg:dword
1091
 
1092
;        DEBUGF  1,"reg_delay\n"
1093
 
1094
        push    esi
1095
        call    pci_push
1096
 
1097
  .loop:
1098
        mov     esi, [delay]
4998 hidnplayr 1099
        invoke  Sleep
3545 hidnplayr 1100
        mov     eax, [delaymax]
1101
        sub     eax, [delay]
1102
        mov     [delaymax], eax
1103
 
1104
        cmp     eax, 0
1105
        jl      .fail
1106
 
1107
        mov     eax, [offset]
1108
        mov     eax, [edi + eax]
1109
        and     eax, [mask]
1110
        cmp     eax, [target]
1111
        jne     .loop
1112
 
1113
        pop     esi
1114
        xor     eax, eax
1115
        ret
1116
 
1117
  .fail:
1118
        pop     esi
1119
        xor     eax, eax
1120
        inc     eax
1121
        ret
1122
 
1123
endp
1124
 
1125
 
1126
 
1127
 
1128
 
1129
; Input:  none
1130
; Output: EAX - result (0 = OK, other = error)
1131
phy_init:
1132
 
1133
        push    ebx ecx
1134
 
1135
        ; set advertise register
4998 hidnplayr 1136
        mov     edx, [ebx + device.phyaddr]
3545 hidnplayr 1137
        mov     eax, MII_ADVERTISE
1138
        mov     ecx, MII_READ
1139
        call    mii_rw
1140
 
1141
        or      eax, (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or 0x800 or 0x400)
1142
 
1143
        mov     ecx, eax
1144
        mov     eax, MII_ADVERTISE
1145
        call    mii_rw
1146
 
1147
        test    eax, eax
1148
        jz      @f
1149
 
4998 hidnplayr 1150
        DEBUGF  2,"phy write to advertise failed.\n"
3545 hidnplayr 1151
 
1152
        mov     eax, PHY_ERROR
1153
        jmp     .return
1154
       @@:
1155
 
1156
        ; get phy interface type
4998 hidnplayr 1157
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 1158
        mov     eax, [PhyInterface]
1159
        DEBUGF  1,"phy interface type = 0x%x\n", eax:8
1160
 
1161
        ; see if gigabit phy
1162
        mov     eax, MII_BMSR
1163
        mov     ecx, MII_READ
1164
        call    mii_rw
1165
 
1166
        test    eax, PHY_GIGABIT
1167
        jnz     .gigabit
4998 hidnplayr 1168
        mov     [ebx + device.gigabit], 0
3545 hidnplayr 1169
        jmp     .next_if
1170
 
1171
  .gigabit:
4998 hidnplayr 1172
        mov     [ebx + device.gigabit], PHY_GIGABIT
3545 hidnplayr 1173
 
1174
        mov     eax, MII_1000BT_CR
1175
        mov     ecx, MII_READ
1176
        call    mii_rw
1177
 
1178
        and     eax, (not ADVERTISE_1000HALF)
1179
 
1180
        test    [PhyInterface], PHY_RGMII
1181
        jz      @f
1182
        or      eax, ADVERTISE_1000FULL
1183
        jmp     .next
1184
       @@:
1185
 
1186
        and     eax, (not ADVERTISE_1000FULL)
1187
 
1188
  .next:
1189
        mov     ecx, eax
1190
        mov     eax, MII_1000BT_CR
1191
        call    mii_rw
1192
 
1193
        test    eax, eax
1194
        jz      .next_if
1195
 
4998 hidnplayr 1196
        DEBUGF  2,"phy init failed.\n"
3545 hidnplayr 1197
 
1198
        mov     eax, PHY_ERROR
1199
        jmp     .return
1200
 
1201
  .next_if:
1202
 
1203
        call    phy_reset
1204
        test    eax, eax
1205
        jz      @f
1206
 
4998 hidnplayr 1207
        DEBUGF  2,"phy reset failed.\n"
3545 hidnplayr 1208
 
1209
        mov     eax, PHY_ERROR
1210
        jmp     .return
1211
       @@:
1212
 
1213
        ; phy vendor specific configuration
4998 hidnplayr 1214
        cmp     [ebx + device.phy_oui], PHY_OUI_CICADA
3545 hidnplayr 1215
        jne     .next_if2
1216
        test    [PhyInterface], PHY_RGMII
1217
        jz      .next_if2
1218
 
1219
        mov     eax, MII_RESV1
1220
        mov     ecx, MII_READ
1221
        call    mii_rw
1222
 
1223
        and     eax, (not (PHY_INIT1 or PHY_INIT2))
1224
        or      eax, (PHY_INIT3 or PHY_INIT4)
1225
        mov     ecx, eax
1226
        mov     eax, MII_RESV1
1227
        call    mii_rw
1228
 
1229
        test    eax, eax
1230
        jz      @f
1231
 
4998 hidnplayr 1232
        DEBUGF  2,"phy init failed.\n"
3545 hidnplayr 1233
 
1234
        mov     eax, PHY_ERROR
1235
        jmp     .return
1236
       @@:
1237
 
1238
        mov     eax, MII_NCONFIG
1239
        mov     ecx, MII_READ
1240
        call    mii_rw
1241
 
1242
        or      eax, PHY_INIT5
1243
        mov     ecx, eax
1244
        mov     eax, MII_NCONFIG
1245
        call    mii_rw
1246
        test    eax, eax
1247
        jz      .next_if2
1248
 
4998 hidnplayr 1249
        DEBUGF  2,"phy init failed.\n"
3545 hidnplayr 1250
 
1251
        mov     eax, PHY_ERROR
1252
        jmp     .return
1253
 
1254
 
1255
 
1256
  .next_if2:
1257
 
4998 hidnplayr 1258
        cmp     [ebx + device.phy_oui], PHY_OUI_CICADA
3545 hidnplayr 1259
        jne     .restart
1260
 
1261
        mov     eax, MII_SREVISION
1262
        mov     ecx, MII_READ
1263
        call    mii_rw
1264
 
1265
        or      eax, PHY_INIT6
1266
        mov     ecx, eax
1267
        mov     eax, MII_SREVISION
1268
        call    mii_rw
1269
        test    eax, eax
1270
        jz      .restart
1271
 
4998 hidnplayr 1272
        DEBUGF  2,"phy init failed.\n"
3545 hidnplayr 1273
 
1274
        jmp     .return
1275
 
1276
  .restart:
1277
        ; restart auto negotiation
1278
 
1279
        mov     eax, MII_BMCR
1280
        mov     ecx, MII_READ
1281
        call    mii_rw
1282
 
1283
        or      eax, (BMCR_ANRESTART or BMCR_ANENABLE)
1284
        mov     ecx, eax
1285
        mov     eax, MII_BMCR
1286
        call    mii_rw
1287
        test    eax, eax
1288
        jz      .ok
1289
 
1290
        mov     eax, PHY_ERROR
1291
        jmp     .return
1292
 
1293
  .ok:
1294
        xor     eax, eax
1295
  .return:
1296
        pop     ecx ebx
1297
 
1298
        ret
1299
 
1300
 
1301
; Input:  none
1302
; Output: EAX - result (0 = OK, other = error)
1303
phy_reset:
1304
 
1305
        DEBUGF  1,"phy_reset\n"
1306
 
1307
        push    ebx ecx edx
1308
 
4998 hidnplayr 1309
        mov     edx, [ebx + device.phyaddr]
3545 hidnplayr 1310
        mov     eax, MII_BMCR
1311
        mov     ecx, MII_READ
1312
        call    mii_rw
1313
 
1314
        or      eax, BMCR_RESET
1315
        push    eax
1316
        mov     ecx, eax
1317
        mov     eax, MII_BMCR
1318
        call    mii_rw
1319
 
1320
        test    eax, eax
1321
        jz      @f
1322
 
1323
        pop     eax
1324
        mov     eax, 0xffffffff
1325
        jmp     .return
1326
       @@:
1327
 
1328
        pop     eax
1329
 
1330
        mov     esi, 500
4998 hidnplayr 1331
        invoke  Sleep
3545 hidnplayr 1332
 
1333
        ; must wait till reset is deasserted
1334
        mov     esi, 100        ; FIXME: 100 tries seem excessive
1335
  .while_loop:
1336
        test    eax, BMCR_RESET
1337
        jz      .while_loop_exit
1338
 
1339
        push    esi
1340
        mov     esi, 10
4998 hidnplayr 1341
        invoke  Sleep
3545 hidnplayr 1342
        pop     esi
1343
 
1344
        mov     eax, MII_BMCR
1345
        mov     ecx, MII_READ
1346
        call    mii_rw
1347
 
1348
        dec     esi
1349
        jnz     .while_loop
1350
 
1351
        mov     eax, 0xffffffff
1352
        jmp     .return
1353
 
1354
  .while_loop_exit:
1355
        xor     eax, eax
1356
  .return:
1357
        pop     edx ecx ebx
1358
 
1359
        ret
1360
 
1361
 
1362
align 4
1363
pci_push:
1364
 
1365
        push    eax
1366
        mov     eax, [edi]
1367
        pop     eax
1368
 
1369
        ret
1370
 
1371
 
1372
 
1373
 
1374
align 4
1375
mac_reset:
1376
 
1377
        push    esi edi
1378
 
1379
        DEBUGF  1,"mac_reset.\n"
1380
 
4998 hidnplayr 1381
        mov     edi, [ebx + device.mmio_addr]
1382
        mov     eax, [ebx + device.desc_ver]
3545 hidnplayr 1383
        or      eax, (TXRXCTL_BIT2 or TXRXCTL_RESET)
1384
        mov     [TxRxControl], eax
1385
        call    pci_push
1386
 
1387
        mov     [MacReset], MAC_RESET_ASSERT
1388
        call    pci_push
1389
 
1390
        mov     esi, NV_MAC_RESET_DELAY
4998 hidnplayr 1391
        invoke  Sleep
3545 hidnplayr 1392
 
1393
        mov     [MacReset], 0
1394
        call    pci_push
1395
 
1396
        mov     esi, NV_MAC_RESET_DELAY
4998 hidnplayr 1397
        invoke  Sleep
3545 hidnplayr 1398
 
4998 hidnplayr 1399
        mov     eax, [ebx + device.desc_ver]
3545 hidnplayr 1400
        or      eax, TXRXCTL_BIT2
1401
        mov     [TxRxControl], eax
1402
        call    pci_push
1403
 
1404
        pop     edi esi
1405
 
1406
        ret
1407
 
1408
 
1409
 
1410
align 4
1411
init_ring:
1412
 
1413
        DEBUGF  1,"init rings\n"
1414
        push    eax esi ecx
1415
 
4998 hidnplayr 1416
        mov     [ebx + device.cur_tx], 0
1417
        mov     [ebx + device.last_tx], 0
3545 hidnplayr 1418
 
1419
        mov     ecx, TX_RING
4998 hidnplayr 1420
        lea     esi, [ebx + device.tx_ring]
3545 hidnplayr 1421
  .tx_loop:
1422
        mov     [esi + TxDesc.FlagLen], 0
4998 hidnplayr 1423
        mov     [esi + TxDesc.PacketBuffer], 0
3545 hidnplayr 1424
        add     esi, sizeof.TxDesc
1425
        dec     ecx
1426
        jnz     .tx_loop
1427
 
1428
 
4998 hidnplayr 1429
        mov     [ebx + device.cur_rx], 0
1430
 
3545 hidnplayr 1431
        mov     ecx, RX_RING
4998 hidnplayr 1432
        lea     esi, [ebx + device.rx_ring]
3545 hidnplayr 1433
  .rx_loop:
1434
        push    ecx esi
4998 hidnplayr 1435
        invoke  KernelAlloc, 4096 shl RBLEN             ; push/pop esi not needed, but just in case...
3545 hidnplayr 1436
        pop     esi
1437
        mov     [esi + RX_RING*sizeof.RxDesc], eax
4998 hidnplayr 1438
        invoke  GetPhysAddr
3545 hidnplayr 1439
        mov     [esi + RxDesc.PacketBuffer], eax
1440
        mov     [esi + RxDesc.FlagLen], (4096 shl RBLEN or NV_RX_AVAIL)
1441
        add     esi, sizeof.RxDesc
1442
        pop     ecx
1443
        dec     ecx
1444
        jnz     .rx_loop
1445
 
1446
        pop     ecx esi eax
1447
 
1448
        ret
1449
 
1450
 
1451
 
1452
 
1453
 
1454
; Input:  none
1455
; Output: none
1456
align 4
1457
txrx_reset:
1458
 
1459
        push    eax esi
1460
 
4998 hidnplayr 1461
        DEBUGF  1,"txrx_reset\n"
3545 hidnplayr 1462
 
4998 hidnplayr 1463
        mov     edi, [ebx + device.mmio_addr]
1464
        mov     eax, [ebx + device.desc_ver]
3545 hidnplayr 1465
        or      eax, (TXRXCTL_BIT2 or TXRXCTL_RESET)
1466
        mov     [TxRxControl], eax
1467
        call    pci_push
1468
 
1469
        mov     esi, NV_TXRX_RESET_DELAY
4998 hidnplayr 1470
        invoke  Sleep
3545 hidnplayr 1471
 
4998 hidnplayr 1472
        mov     eax, [ebx + device.desc_ver]
3545 hidnplayr 1473
        or      eax, TXRXCTL_BIT2
1474
        mov     [TxRxControl], eax
1475
        call    pci_push
1476
 
1477
        pop     esi eax
1478
 
1479
        ret
1480
 
1481
 
1482
 
1483
 
1484
 
1485
; Input:  none
1486
; Output: none
1487
set_multicast:
1488
 
1489
        ; u32 addr[2];
1490
        ; u32 mask[2];
1491
        ; u32 pff;
1492
        ; u32 alwaysOff[2];
1493
        ; u32 alwaysOn[2];
1494
        ;
1495
        ; memset(addr, 0, sizeof(addr));
1496
        ; memset(mask, 0, sizeof(mask));
1497
        ;
1498
        ; pff = PFF_MYADDR;
1499
        ;
1500
        ; alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0;
1501
        ;
1502
        ; addr[0] = alwaysOn[0];
1503
        ; addr[1] = alwaysOn[1];
1504
        ; mask[0] = alwaysOn[0] | alwaysOff[0];
1505
        ; mask[1] = alwaysOn[1] | alwaysOff[1];
1506
        ;
1507
        ; addr[0] |= MCASTADDRA_FORCE;
1508
        ; pff |= PFF_ALWAYS;
1509
 
1510
        call    stop_rx
1511
 
4998 hidnplayr 1512
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 1513
        mov     [MulticastAddrA], MCASTADDRA_FORCE
1514
 
1515
        mov     [MulticastAddrB], 0
1516
        mov     [MulticastMaskA], 0
1517
        mov     [MulticastMaskB], 0
1518
        mov     [PacketFilterFlags], (PFF_MYADDR or PFF_ALWAYS)
1519
 
1520
        call    start_rx
1521
 
1522
        ret
1523
 
1524
 
1525
 
1526
 
1527
 
1528
; Input:  none
1529
; Output: none
1530
start_rx:
1531
 
1532
        push    edi
1533
 
1534
        DEBUGF  1,"start_rx\n"
1535
 
1536
        ; Already running? Stop it.
4998 hidnplayr 1537
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 1538
        mov     eax, [ReceiverControl]
1539
        test    eax, RCVCTL_START
1540
        jz      @f
1541
        mov     [ReceiverControl], 0
1542
        call    pci_push
1543
       @@:
1544
 
4998 hidnplayr 1545
        mov     eax, [ebx + device.linkspeed]
3545 hidnplayr 1546
        mov     [LinkSpeed], eax
1547
        call    pci_push
1548
 
1549
        mov     [ReceiverControl], RCVCTL_START
1550
        call    pci_push
1551
 
1552
        pop     edi
1553
 
1554
        ret
1555
 
1556
 
1557
 
1558
 
1559
; Input:  none
1560
; Output: none
1561
stop_rx:
1562
 
1563
        push    esi edi
1564
 
4998 hidnplayr 1565
        DEBUGF  1,"stop_rx.\n"
3545 hidnplayr 1566
 
4998 hidnplayr 1567
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 1568
        mov     [ReceiverControl], 0
1569
 
1570
        push    ebx edx edi
1571
        stdcall reg_delay, ReceiverStatus-edi, RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, 0
1572
        pop     edi edx ebx
1573
 
1574
        mov     esi, NV_RXSTOP_DELAY2
4998 hidnplayr 1575
        invoke  Sleep
3545 hidnplayr 1576
 
1577
        mov     [LinkSpeed], 0
1578
 
1579
        pop     edi esi
1580
 
1581
        ret
1582
 
1583
 
1584
 
1585
 
1586
; Input:  none
1587
; Output: EAX
1588
update_linkspeed:
1589
 
1590
        DEBUGF  1,"update linkspeed\n"
1591
 
1592
; BMSR_LSTATUS is latched, read it twice: we want the current value.
1593
 
4998 hidnplayr 1594
        mov     edx, [ebx + device.phyaddr]
3545 hidnplayr 1595
        mov     eax, MII_BMSR
1596
        mov     ecx, MII_READ
1597
        call    mii_rw
1598
 
1599
        mov     eax, MII_BMSR
1600
        mov     ecx, MII_READ
1601
        call    mii_rw
1602
 
4998 hidnplayr 1603
        test    ax, BMSR_LSTATUS               ; Link up?
1604
        jz      .no_link
3545 hidnplayr 1605
 
4998 hidnplayr 1606
        DEBUGF  1,"link is up\n"
1607
 
1608
        test    ax, BMSR_ANEGCOMPLETE          ; still in autonegotiation?
3545 hidnplayr 1609
        jz      .10mbit_hd
1610
 
4998 hidnplayr 1611
        DEBUGF  1,"autonegotiation is complete\n"
1612
 
1613
        cmp     [ebx + device.gigabit], PHY_GIGABIT
3545 hidnplayr 1614
        jne     .no_gigabit
1615
 
4998 hidnplayr 1616
        ;mov     edx, [ebx + device.phyaddr]
3545 hidnplayr 1617
        mov     eax, MII_1000BT_CR
1618
        mov     ecx, MII_READ
1619
        call    mii_rw
1620
        push    eax
1621
 
4998 hidnplayr 1622
        ;mov     edx, [ebx + device.phyaddr]
3545 hidnplayr 1623
        mov     eax, MII_1000BT_SR
1624
        mov     ecx, MII_READ
1625
        call    mii_rw
1626
        pop     ecx
1627
 
1628
        test    eax, LPA_1000FULL
1629
        jz      .no_gigabit
1630
        test    ecx, ADVERTISE_1000FULL
1631
        jz      .no_gigabit
1632
 
1633
        DEBUGF  1,"update_linkspeed: GBit ethernet detected.\n"
4998 hidnplayr 1634
        mov     [ebx + device.state], ETH_LINK_1G
3545 hidnplayr 1635
        mov     ecx, (LINKSPEED_FORCE or LINKSPEED_1000)
1636
        xor     eax, eax
1637
        inc     eax
1638
        jmp     set_speed
1639
  .no_gigabit:
1640
 
4998 hidnplayr 1641
        ;mov     edx, [ebx + device.phyaddr]
3545 hidnplayr 1642
        mov     eax, MII_ADVERTISE
1643
        mov     ecx, MII_READ
1644
        call    mii_rw        ; adv = eax
1645
        push    eax
1646
 
4998 hidnplayr 1647
        ;mov     edx, [ebx + device.phyaddr]
3545 hidnplayr 1648
        mov     eax, MII_LPA
1649
        mov     ecx, MII_READ
1650
        call    mii_rw        ; lpa = eax
1651
        pop     ecx
1652
 
4998 hidnplayr 1653
        DEBUGF  1,"PHY advertises 0x%x, lpa 0x%x\n", cx, ax
3545 hidnplayr 1654
        and     eax, ecx                ; FIXME: handle parallel detection properly, handle gigabit ethernet
1655
 
1656
        test    eax, LPA_100FULL
1657
        jz      @f
1658
        DEBUGF  1,"update_linkspeed: 100 mbit full duplex\n"
4998 hidnplayr 1659
        mov     [ebx + device.state], ETH_LINK_100M + ETH_LINK_FD
3545 hidnplayr 1660
        mov     ecx, (LINKSPEED_FORCE or LINKSPEED_100)
1661
        xor     eax, eax
1662
        inc     eax
1663
        jmp     set_speed
1664
       @@:
1665
 
1666
        test    eax, LPA_100HALF
1667
        jz      @f
1668
        DEBUGF  1,"update_linkspeed: 100 mbit half duplex\n"
4998 hidnplayr 1669
        mov     [ebx + device.state], ETH_LINK_100M
3545 hidnplayr 1670
        mov     ecx, (LINKSPEED_FORCE or LINKSPEED_100)
1671
        xor     eax, eax
1672
        jmp     set_speed
1673
       @@:
1674
 
1675
        test    eax, LPA_10FULL
1676
        jz      @f
1677
        DEBUGF  1,"update_linkspeed: 10 mbit full duplex\n"
4998 hidnplayr 1678
        mov     [ebx + device.state], ETH_LINK_10M + ETH_LINK_FD
3545 hidnplayr 1679
        mov     ecx, (LINKSPEED_FORCE or LINKSPEED_10)
1680
        xor     eax, eax
1681
        inc     eax
1682
        jmp     set_speed
1683
       @@:
1684
 
1685
  .10mbit_hd:
1686
        DEBUGF  1,"update_linkspeed: 10 mbit half duplex\n"
4998 hidnplayr 1687
        mov     [ebx + device.state], ETH_LINK_10M
3545 hidnplayr 1688
        mov     ecx, (LINKSPEED_FORCE or LINKSPEED_10)
1689
        xor     eax, eax
1690
        jmp     set_speed
1691
 
4998 hidnplayr 1692
  .no_link:
1693
        DEBUGF  1,"update_linkspeed: link is down\n"
1694
        mov     [ebx + device.state], ETH_LINK_DOWN
1695
        mov     ecx, (LINKSPEED_FORCE or LINKSPEED_10)
1696
        xor     eax, eax
1697
        jmp     set_speed
3545 hidnplayr 1698
 
4998 hidnplayr 1699
 
3545 hidnplayr 1700
align 4
1701
set_speed:
1702
 
4998 hidnplayr 1703
        cmp     eax, [ebx + device.duplex]
3545 hidnplayr 1704
        jne     .update
4998 hidnplayr 1705
        cmp     ecx, [ebx + device.linkspeed]
3545 hidnplayr 1706
        jne     .update
1707
 
1708
        ret
1709
 
1710
  .update:
4998 hidnplayr 1711
        DEBUGF  1,"update_linkspeed: changing link to 0x%x/XD.\n", ecx
3545 hidnplayr 1712
 
4998 hidnplayr 1713
        mov     [ebx + device.duplex], eax
1714
        mov     [ebx + device.linkspeed], ecx
3545 hidnplayr 1715
 
4998 hidnplayr 1716
        cmp     [ebx + device.gigabit], PHY_GIGABIT
3545 hidnplayr 1717
        jne     .no_gigabit
1718
 
4998 hidnplayr 1719
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 1720
        mov     eax, [RandomSeed]
1721
 
1722
        and     eax, not (0x3FF00)
1723
        mov     ecx, eax                ; phyreg = ecx
1724
 
4998 hidnplayr 1725
        mov     eax, [ebx + device.linkspeed]
3545 hidnplayr 1726
        and     eax, 0xFFF
1727
        cmp     eax, LINKSPEED_10
1728
        jne     @f
1729
        or      ecx, RNDSEED_FORCE3
1730
        jmp     .end_if4
1731
       @@:
1732
 
1733
        cmp     eax, LINKSPEED_100
1734
        jne     @f
1735
        or      ecx, RNDSEED_FORCE2
1736
        jmp     .end_if4
1737
       @@:
1738
 
1739
        cmp     eax, LINKSPEED_1000
1740
        jne     .end_if4
1741
        or      ecx, RNDSEED_FORCE
1742
  .end_if4:
1743
        mov     [RandomSeed], ecx
1744
  .no_gigabit:
1745
 
1746
        mov     ecx, [PhyInterface]
1747
        and     ecx, not (PHY_HALF or PHY_100 or PHY_1000)
1748
 
4998 hidnplayr 1749
        cmp     [ebx + device.duplex], 0
3545 hidnplayr 1750
        jne     @f
1751
        or      ecx, PHY_HALF
1752
       @@:
1753
 
4998 hidnplayr 1754
        mov     eax, [ebx + device.linkspeed]
3545 hidnplayr 1755
        and     eax, 0xFFF
1756
        cmp     eax, LINKSPEED_100
1757
        jne     @f
1758
        or      ecx, PHY_100
1759
        jmp     .end_if5
1760
       @@:
1761
 
1762
        cmp     eax, LINKSPEED_1000
1763
        jne     .end_if5
1764
        or      ecx, PHY_1000
1765
 
1766
  .end_if5:
1767
        mov     [PhyInterface], ecx
1768
 
4998 hidnplayr 1769
        cmp     [ebx + device.duplex], 0
3545 hidnplayr 1770
        je      @f
1771
        xor     ecx, ecx
1772
        jmp     .next
1773
       @@:
1774
 
1775
        mov     ecx, MISC1_HD
1776
  .next:
1777
        or      ecx, MISC1_FORCE
1778
        mov     [Misc1], ecx
1779
 
1780
        call    pci_push
1781
 
4998 hidnplayr 1782
        mov     eax, [ebx + device.linkspeed]
3545 hidnplayr 1783
        mov     [LinkSpeed], eax
1784
 
1785
        call    pci_push
1786
 
1787
        ret
1788
 
1789
 
1790
 
1791
 
1792
 
1793
 
1794
align 4
1795
read_mac:
1796
 
4998 hidnplayr 1797
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 1798
        mov     eax, [MacAddrA]
1799
        mov     ecx, [MacAddrB]
1800
 
4998 hidnplayr 1801
        mov     dword [ebx + device.mac], eax
1802
        mov     word [ebx + device.mac + 4], cx
3545 hidnplayr 1803
 
4998 hidnplayr 1804
        cmp     [ebx + device.device_id], 0x03E5
3545 hidnplayr 1805
        jae     @f
1806
        bswap   eax
1807
        xchg    cl, ch
4998 hidnplayr 1808
        mov     dword [ebx + device.mac + 2], eax
1809
        mov     word [ebx + device.mac], cx
3545 hidnplayr 1810
       @@:
1811
 
4470 hidnplayr 1812
        DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n", \
4998 hidnplayr 1813
        [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,[ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
3545 hidnplayr 1814
 
1815
        ret
1816
 
1817
 
1818
 
1819
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1820
;;                                         ;;
1821
;; Transmit                                ;;
1822
;;                                         ;;
1823
;; In: buffer pointer in [esp+4]           ;;
1824
;;     size of buffer in [esp+8]           ;;
1825
;;     pointer to device structure in ebx  ;;
1826
;;                                         ;;
1827
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4998 hidnplayr 1828
 
1829
proc transmit stdcall bufferptr, buffersize
1830
 
1831
        pushf
1832
        cli
1833
 
1834
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [buffersize]
1835
        mov     eax, [bufferptr]
1836
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
3545 hidnplayr 1837
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
1838
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
1839
        [eax+13]:2,[eax+12]:2
1840
 
4998 hidnplayr 1841
        cmp     [buffersize], 1514
3545 hidnplayr 1842
        ja      .fail
4998 hidnplayr 1843
        cmp     [buffersize], 60
3545 hidnplayr 1844
        jb      .fail
1845
 
1846
; get the descriptor address
4998 hidnplayr 1847
        mov     eax, [ebx + device.cur_tx]
1848
        shl     eax, 3                                  ; TX descriptor is 8 bytes.
1849
        lea     esi, [ebx + device.tx_ring + eax]
1850
 
1851
        mov     eax, [bufferptr]
3545 hidnplayr 1852
        mov     [esi + TX_RING*sizeof.TxDesc], eax
4998 hidnplayr 1853
        invoke  GetPhysAddr                             ; Does not change esi/ebx :)
3545 hidnplayr 1854
        mov     [esi + TxDesc.PacketBuffer], eax
1855
 
4998 hidnplayr 1856
        mov     eax, [buffersize]
1857
        or      eax, [ebx + device.txflags]
3545 hidnplayr 1858
        mov     [esi + TxDesc.FlagLen], eax
1859
 
4998 hidnplayr 1860
        mov     edi, [ebx + device.mmio_addr]
1861
        mov     eax, [ebx + device.desc_ver]
3545 hidnplayr 1862
        or      eax, TXRXCTL_KICK
1863
        mov     [TxRxControl], eax
1864
 
1865
        call    pci_push
1866
 
4998 hidnplayr 1867
        inc     [ebx + device.cur_tx]
1868
        and     [ebx + device.cur_tx], (TX_RING-1)
3545 hidnplayr 1869
 
1870
; Update stats
4998 hidnplayr 1871
        inc     [ebx + device.packets_tx]
1872
        mov     eax, [buffersize]
1873
        add     dword[ebx + device.bytes_tx], eax
1874
        adc     dword[ebx + device.bytes_tx + 4], 0
3545 hidnplayr 1875
 
5127 hidnplayr 1876
        popf
3545 hidnplayr 1877
        xor     eax, eax
4998 hidnplayr 1878
        ret
3545 hidnplayr 1879
 
1880
  .fail:
4998 hidnplayr 1881
        DEBUGF  2,"Send failed\n"
1882
        invoke  KernelFree, [bufferptr]
1883
        popf
4334 hidnplayr 1884
        or      eax, -1
4998 hidnplayr 1885
        ret
3545 hidnplayr 1886
 
4998 hidnplayr 1887
endp
3545 hidnplayr 1888
 
1889
 
1890
 
1891
 
1892
 
4998 hidnplayr 1893
 
3545 hidnplayr 1894
; Interrupt handler
1895
align 4
1896
int_handler:
1897
 
1898
        push    ebx esi edi
1899
 
4998 hidnplayr 1900
        DEBUGF  1,"INT\n"
3545 hidnplayr 1901
 
1902
;-------------------------------------------
1903
; Find pointer of device wich made IRQ occur
1904
 
1905
        mov     esi, device_list
1906
        mov     ecx, [devices]
1907
        test    ecx, ecx
1908
        jz      .fail
1909
  .nextdevice:
1910
        mov     ebx, dword [esi]
1911
        add     esi, 4
1912
 
4998 hidnplayr 1913
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 1914
        mov     eax, [IrqStatus]
1915
        test    eax, eax
1916
        jnz     .got_it
1917
        dec     ecx
1918
        jnz     .nextdevice
1919
  .nothing:
1920
        pop     edi esi ebx
1921
        xor     eax, eax
1922
 
1923
        ret
1924
 
1925
  .got_it:
1926
        mov     [IrqStatus], eax
4998 hidnplayr 1927
        DEBUGF  1,"IrqStatus = %x\n", eax
3545 hidnplayr 1928
 
4998 hidnplayr 1929
        test    eax, IRQ_RX ;+ IRQ_TIMER ;;;;
3545 hidnplayr 1930
        jz      .no_rx
1931
 
4998 hidnplayr 1932
        push    ebx
1933
  .more_rx:
1934
        pop     ebx
1935
        mov     eax, [ebx + device.cur_rx]
3545 hidnplayr 1936
        mov     cx, sizeof.RxDesc
1937
        mul     cx
4998 hidnplayr 1938
        lea     esi, [ebx + device.rx_ring + eax]
3545 hidnplayr 1939
        mov     eax, [esi + RxDesc.FlagLen]
1940
 
1941
        test    eax, NV_RX_AVAIL        ; still owned by hardware
4998 hidnplayr 1942
        jnz     .no_rx
3545 hidnplayr 1943
 
4998 hidnplayr 1944
        cmp     [ebx + device.desc_ver], DESC_VER_1
3545 hidnplayr 1945
        jne     @f
1946
        test    eax, NV_RX_DESCRIPTORVALID
4998 hidnplayr 1947
        jz      .no_rx
3545 hidnplayr 1948
        jmp     .next
1949
  @@:
1950
        test    eax, NV_RX2_DESCRIPTORVALID
4998 hidnplayr 1951
        jz      .no_rx
3545 hidnplayr 1952
 
1953
  .next:
4998 hidnplayr 1954
        cmp     dword[ebx + device.desc_ver], DESC_VER_1
3545 hidnplayr 1955
        jne     @f
1956
        and     eax, LEN_MASK_V1
1957
        jmp     .next2
1958
   @@:
1959
        and     eax, LEN_MASK_V2
4998 hidnplayr 1960
 
3545 hidnplayr 1961
  .next2:
4998 hidnplayr 1962
        DEBUGF  1,"Received %u bytes\n", eax
3545 hidnplayr 1963
 
4998 hidnplayr 1964
        ; Update stats
1965
        add     dword[ebx + device.bytes_rx], eax
1966
        adc     dword[ebx + device.bytes_rx + 4], 0
1967
        inc     dword[ebx + device.packets_rx]
3545 hidnplayr 1968
 
4998 hidnplayr 1969
        ; Prepare to give packet to kernel
1970
        push    ebx
1971
        push    .more_rx
3545 hidnplayr 1972
 
4998 hidnplayr 1973
        push    eax
1974
        push    dword[esi + RX_RING*sizeof.RxDesc]
1975
        DEBUGF  1,"packet ptr=0x%x\n", [esi + RX_RING*sizeof.RxDesc]
3545 hidnplayr 1976
 
4998 hidnplayr 1977
        ; Allocate new buffer for this descriptor
1978
        invoke  KernelAlloc, 4096 shl RBLEN
3545 hidnplayr 1979
        mov     [esi + RX_RING*sizeof.RxDesc], eax
4998 hidnplayr 1980
        invoke  GetPhysAddr
3545 hidnplayr 1981
        mov     [esi + RxDesc.PacketBuffer], eax
1982
        mov     [esi + RxDesc.FlagLen], (4096 shl RBLEN or NV_RX_AVAIL)
1983
 
4998 hidnplayr 1984
        ; update current RX descriptor
1985
        inc     [ebx + device.cur_rx]
1986
        and     [ebx + device.cur_rx], (RX_RING-1)
3545 hidnplayr 1987
 
4998 hidnplayr 1988
        jmp     [Eth_input]
3545 hidnplayr 1989
 
1990
  .no_rx:
1991
        test    eax, IRQ_RX_ERROR
1992
        jz      .no_rx_err
1993
 
1994
        push    eax
1995
        DEBUGF  2,"RX error!\n"
1996
 
4998 hidnplayr 1997
        mov     eax, [ebx + device.cur_rx]
3545 hidnplayr 1998
        mov     cx, sizeof.RxDesc
1999
        mul     cx
4998 hidnplayr 2000
        lea     esi, [ebx + device.rx_ring + eax]
3545 hidnplayr 2001
        mov     eax, [esi + RxDesc.FlagLen]
2002
 
4998 hidnplayr 2003
        DEBUGF  1,"Flaglen=%x\n", eax
3545 hidnplayr 2004
 
4998 hidnplayr 2005
        ; TODO: allocate new buff ?
3545 hidnplayr 2006
        pop     eax
2007
 
2008
  .no_rx_err:
4998 hidnplayr 2009
        test    eax, IRQ_TX_ERROR
2010
        jz      .no_tx_err
2011
 
2012
        DEBUGF  2,"TX error!\n"
2013
        ; TODO
2014
 
2015
  .no_tx_err:
3545 hidnplayr 2016
        test    eax, IRQ_LINK
2017
        jz      .no_link
2018
 
2019
        push    eax
2020
        call    update_linkspeed
2021
        pop     eax
2022
 
2023
  .no_link:
4998 hidnplayr 2024
        test    eax, IRQ_TX_OK
2025
        jz      .no_tx
2026
 
2027
        DEBUGF  1, "TX completed\n"
2028
      .loop_tx:
2029
        mov     esi, [ebx + device.last_tx]
2030
        shl     esi, 3                                  ; TX descriptor is 8 bytes.
2031
        lea     esi, [ebx + device.tx_ring + esi]
2032
 
2033
        DEBUGF  1,"Flaglen = 0x%x\n", [esi + TxDesc.FlagLen]
2034
        test    [esi + TxDesc.FlagLen], NV_TX_VALID
2035
        jnz     .no_tx
2036
        cmp     dword[esi + TX_RING*sizeof.TxDesc], 0
2037
        je      .no_tx
2038
 
2039
        DEBUGF  1,"Freeing buffer 0x%x\n", [esi + TX_RING*sizeof.TxDesc]:8
2040
        push    dword[esi + TX_RING*sizeof.TxDesc]
2041
        mov     dword[esi + TX_RING*sizeof.TxDesc], 0
2042
        invoke  KernelFree
2043
 
2044
        inc     [ebx + device.last_tx]
2045
        and     [ebx + device.last_tx], TX_RING - 1
2046
 
2047
        jmp     .loop_tx
2048
 
2049
  .no_tx:
3545 hidnplayr 2050
  .fail:
2051
        pop     edi esi ebx
2052
        xor     eax, eax
2053
        inc     eax
2054
 
2055
        ret
2056
 
2057
 
4998 hidnplayr 2058
; End of code
3545 hidnplayr 2059
 
4998 hidnplayr 2060
data fixups
2061
end data
3545 hidnplayr 2062
 
4998 hidnplayr 2063
include '../peimport.inc'
3545 hidnplayr 2064
 
2065
my_service      db 'FORCEDETH',0                ; max 16 chars include zero
2066
 
4998 hidnplayr 2067
include_debug_strings
3545 hidnplayr 2068
 
4998 hidnplayr 2069
align 4
2070
devices         dd 0
3545 hidnplayr 2071
device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
4998 hidnplayr 2072