Subversion Repositories Kolibri OS

Rev

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

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