Subversion Repositories Kolibri OS

Rev

Rev 5182 | 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
;;                                                                 ;;
5363 yogev_ezra 3
;; Copyright (C) KolibriOS team 2004-2015. 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'
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
585
        stdcall PCI_find_mmio32, [ebx + device.pci_bus], [ebx + device.pci_dev] ; returns in eax
586
        DEBUGF 1,"mmio_addr= 0x%x\n", eax
587
 
588
; Create virtual mapping of the physical memory
589
        invoke  MapIoMem, eax, 10000h, PG_SW + PG_NOCACHE
3545 hidnplayr 590
        test    eax, eax
591
        jz      fail
4998 hidnplayr 592
        mov     [ebx + device.mmio_addr], eax
593
        DEBUGF 1,"mapped mmio_addr= 0x%x\n", eax
3545 hidnplayr 594
 
4998 hidnplayr 595
; Read PCI vendor/device ID
596
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.vendor_id
597
        mov     dword[ebx + device.vendor_id], eax
598
        DEBUGF 1,"vendor = 0x%x\n", [ebx + device.vendor_id]:4
599
        DEBUGF 1,"device = 0x%x\n", [ebx + device.device_id]:4
3545 hidnplayr 600
 
601
;-------------------------------------
602
; handle different descriptor versions
4998 hidnplayr 603
        mov     [ebx + device.desc_ver], DESC_VER_1
604
        mov     ax, [ebx + device.device_id]
605
        cmp     ax, PCI_DEVICE_ID_NVIDIA_NVENET_1
3545 hidnplayr 606
        je      .ver1
4998 hidnplayr 607
        cmp     ax, PCI_DEVICE_ID_NVIDIA_NVENET_2
3545 hidnplayr 608
        je      .ver1
4998 hidnplayr 609
        cmp     ax, PCI_DEVICE_ID_NVIDIA_NVENET_3
3545 hidnplayr 610
        je      .ver1
4998 hidnplayr 611
        mov     [ebx + device.desc_ver], DESC_VER_2
3545 hidnplayr 612
  .ver1:
613
 
614
        call    read_mac
615
 
616
        ; disable WOL
617
        mov     [WakeUpFlags], 0
4998 hidnplayr 618
        mov     [ebx + device.wolenabled], 0
3545 hidnplayr 619
 
4998 hidnplayr 620
        mov     [ebx + device.txflags], (NV_TX2_LASTPACKET or NV_TX2_VALID)
621
        cmp     [ebx + device.desc_ver], DESC_VER_1
3545 hidnplayr 622
        jne     @f
4998 hidnplayr 623
        mov     [ebx + device.txflags], (NV_TX_LASTPACKET or NV_TX_VALID)
3545 hidnplayr 624
      @@:
625
 
626
; BEGIN of switch (pci->dev_id)
627
 
4998 hidnplayr 628
        cmp     [ebx + device.device_id], 0x01C3
629
        jne     .not_0x01c3
3545 hidnplayr 630
        ; nforce
4998 hidnplayr 631
        mov     [ebx + device.irqmask], (IRQMASK_WANTED_2 or IRQ_TIMER)         ;;; Was 0
3545 hidnplayr 632
        jmp     .find_phy
4998 hidnplayr 633
  .not_0x01c3:
3545 hidnplayr 634
 
4998 hidnplayr 635
        cmp     [ebx + device.device_id], 0x0066
3545 hidnplayr 636
        je      @f
4998 hidnplayr 637
        cmp     [ebx + device.device_id], 0x00D6
638
        jne     .not_0x0066
3545 hidnplayr 639
  @@:
4998 hidnplayr 640
        mov     [ebx + device.irqmask], (IRQMASK_WANTED_2 or IRQ_TIMER)         ;;;; was 0
641
        cmp     [ebx + device.desc_ver], DESC_VER_1
3545 hidnplayr 642
        jne     @f
4998 hidnplayr 643
        or      [ebx + device.txflags], NV_TX_LASTPACKET1
3545 hidnplayr 644
        jmp     .find_phy
645
  @@:
4998 hidnplayr 646
        or      [ebx + device.txflags], NV_TX2_LASTPACKET1
3545 hidnplayr 647
        jmp     .find_phy
4998 hidnplayr 648
  .not_0x0066:
3545 hidnplayr 649
 
4998 hidnplayr 650
        cmp     [ebx + device.device_id], 0x0086
3545 hidnplayr 651
        je      @f
4998 hidnplayr 652
        cmp     [ebx + device.device_id], 0x008c
3545 hidnplayr 653
        je      @f
4998 hidnplayr 654
        cmp     [ebx + device.device_id], 0x00e6
3545 hidnplayr 655
        je      @f
4998 hidnplayr 656
        cmp     [ebx + device.device_id], 0x00df
3545 hidnplayr 657
        je      @f
4998 hidnplayr 658
        cmp     [ebx + device.device_id], 0x0056
3545 hidnplayr 659
        je      @f
4998 hidnplayr 660
        cmp     [ebx + device.device_id], 0x0057
3545 hidnplayr 661
        je      @f
4998 hidnplayr 662
        cmp     [ebx + device.device_id], 0x0037
3545 hidnplayr 663
        je      @f
4998 hidnplayr 664
        cmp     [ebx + device.device_id], 0x0038
665
        jne     .not_0x0086
3545 hidnplayr 666
 
667
      @@:
4998 hidnplayr 668
        mov     [ebx + device.irqmask], (IRQMASK_WANTED_2 or IRQ_TIMER) ;;; was 0
3545 hidnplayr 669
 
4998 hidnplayr 670
        cmp     [ebx + device.desc_ver], DESC_VER_1
3545 hidnplayr 671
        jne     @f
4998 hidnplayr 672
        or      [ebx + device.txflags], NV_TX_LASTPACKET1
3545 hidnplayr 673
        jmp     .find_phy
674
       @@:
4998 hidnplayr 675
        or      [ebx + device.txflags], NV_TX2_LASTPACKET1
3545 hidnplayr 676
        jmp     .find_phy
4998 hidnplayr 677
  .not_0x0086:
3545 hidnplayr 678
 
679
;       cmp     word [device_id], 0x0268
680
;       je      @f
681
;       cmp     word [device_id], 0x0269
682
;       je      @f
683
;       cmp     word [device_id], 0x0372
684
;       je      @f
685
;       cmp     word [device_id], 0x0373
686
;       je      @f
687
;       jmp     .default_switch
688
;@@:
4998 hidnplayr 689
        cmp     [ebx + device.device_id], 0x0268
3545 hidnplayr 690
        jb      .undefined
691
 
692
; Get device revision
4998 hidnplayr 693
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.revision_id
694
        mov     edi, [ebx + device.mmio_addr]   ;;;;;
3545 hidnplayr 695
 
696
; take phy and nic out of low power mode
697
        mov     ecx, [PowerState2]
698
        and     ecx, not POWERSTATE2_POWERUP_MASK
4998 hidnplayr 699
        cmp     [ebx + device.device_id], PCI_DEVICE_ID_NVIDIA_NVENET_12
700
        je      @f
701
        cmp     [ebx + device.device_id], PCI_DEVICE_ID_NVIDIA_NVENET_13
702
        jne     .set_powerstate
703
  @@:
3545 hidnplayr 704
        cmp     al, 0xA3
4998 hidnplayr 705
        jb      .set_powerstate
3545 hidnplayr 706
        or      ecx, POWERSTATE2_POWERUP_REV_A3
4998 hidnplayr 707
  .set_powerstate:
3545 hidnplayr 708
        mov     [PowerState2], ecx
709
 
710
        ; DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ
4998 hidnplayr 711
        mov     [ebx + device.irqmask], (IRQMASK_WANTED_2 or IRQ_TIMER)         ; was 0
3545 hidnplayr 712
 
4998 hidnplayr 713
        mov     [ebx + device.needs_mac_reset], 1
714
        cmp     [ebx + device.desc_ver], DESC_VER_1
3545 hidnplayr 715
        jne     @f
4998 hidnplayr 716
        or      [ebx + device.txflags], NV_TX_LASTPACKET1
3545 hidnplayr 717
        jmp     .find_phy
4998 hidnplayr 718
 
3545 hidnplayr 719
       @@:
4998 hidnplayr 720
        cmp     [ebx + device.desc_ver], DESC_VER_2
3545 hidnplayr 721
        jne     .undefined
4998 hidnplayr 722
        or      [ebx + device.txflags], NV_TX2_LASTPACKET1
3545 hidnplayr 723
        jmp     .find_phy
724
 
725
  .undefined:
4998 hidnplayr 726
        DEBUGF  2,"Your card was undefined in this driver.\n"
727
        or      eax, -1
728
        ret
3545 hidnplayr 729
 
730
; Find a suitable phy
731
; Start with address 1 to 31, then do 0, then fail
732
 
733
  .find_phy:
734
        xor     edx, edx
735
  .phy_loop:
736
        inc     edx
737
        and     edx, 0x1f       ; phyaddr = i & 0x1f
738
        mov     eax, MII_PHYSID1
739
        mov     ecx, MII_READ
740
        call    mii_rw          ; EDX - addr, EAX - miireg, ECX - value
741
 
4998 hidnplayr 742
        cmp     eax, 0x0000ffff
3545 hidnplayr 743
        je      .try_next
4998 hidnplayr 744
        test    eax, 0x80000000
745
        jnz     .try_next
3545 hidnplayr 746
        mov     esi, eax
747
 
748
        mov     eax, MII_PHYSID2
749
        mov     ecx, MII_READ
750
        call    mii_rw
751
 
4998 hidnplayr 752
        cmp     eax, 0x0000ffff
3545 hidnplayr 753
        je      .try_next
4998 hidnplayr 754
        test    eax, 0x80000000
755
        jnz     .try_next
3545 hidnplayr 756
        jmp     .got_it
757
 
758
  .try_next:
759
        test    edx, edx
760
        jnz     .phy_loop
761
 
762
        ; PHY in isolate mode? No phy attached and user wants to test loopback?
763
        ; Very odd, but can be correct.
764
 
4998 hidnplayr 765
        DEBUGF  2,"Could not find a valid PHY.\n"
3545 hidnplayr 766
        jmp     .no_phy
767
 
768
  .got_it:
769
        and     esi, PHYID1_OUI_MASK
770
        shl     esi, PHYID1_OUI_SHFT
771
        and     eax, PHYID2_OUI_MASK
772
        shr     eax, PHYID2_OUI_SHFT
4998 hidnplayr 773
        or      eax, esi
3545 hidnplayr 774
 
4998 hidnplayr 775
        mov     [ebx + device.phyaddr], edx
776
        mov     [ebx + device.phy_oui], eax
3545 hidnplayr 777
 
4998 hidnplayr 778
        DEBUGF 1,"Found PHY with OUI:0x%x at address:0x%x\n", eax, edx
3545 hidnplayr 779
 
780
        call    phy_init
781
 
782
  .no_phy:
783
 
4998 hidnplayr 784
        cmp     [ebx + device.needs_mac_reset], 0
3545 hidnplayr 785
        je      @f
786
        call    mac_reset
787
  @@:
788
 
789
;***************************************************************************
790
;   Function
791
;      reset
792
;   Description
793
;      Place the chip (ie, the ethernet card) into a virgin state
794
;      No inputs
795
;      All registers destroyed
796
;
797
;***************************************************************************
798
reset:
799
 
800
        DEBUGF  1,"Resetting\n"
801
 
4998 hidnplayr 802
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
3545 hidnplayr 803
        movzx   eax, al
4998 hidnplayr 804
        invoke  AttachIntHandler, eax, int_handler, ebx
3545 hidnplayr 805
        test    eax, eax
806
        jnz     @f
4998 hidnplayr 807
        DEBUGF  2,"Could not attach int handler!\n"
808
        or      eax, -1
809
        ret
3545 hidnplayr 810
       @@:
811
 
812
; erase previous misconfiguration
813
 
4998 hidnplayr 814
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 815
        mov     [MulticastAddrA], MCASTADDRA_FORCE
816
        mov     [MulticastAddrB], 0
817
        mov     [MulticastMaskA], 0
818
        mov     [MulticastMaskB], 0
819
        mov     [PacketFilterFlags], 0
820
        mov     [TransmitterControl], 0
821
        mov     [ReceiverControl], 0
822
        mov     [AdapterControl], 0
823
 
824
; initialize descriptor rings
825
 
826
        call    init_ring
827
 
828
        mov     [LinkSpeed], 0
829
        mov     [UnknownTransmitterReg], 0
830
 
831
        call    txrx_reset
4998 hidnplayr 832
 
3545 hidnplayr 833
        mov     [UnknownSetupReg6], 0
4998 hidnplayr 834
        mov     [ebx + device.in_shutdown], 0
3545 hidnplayr 835
 
836
; give hw rings
837
 
4998 hidnplayr 838
        lea     eax, [ebx + device.rx_ring]
839
        invoke  GetPhysAddr
3545 hidnplayr 840
        mov     [RxRingPhysAddr], eax
841
 
4998 hidnplayr 842
        lea     eax, [ebx + device.tx_ring]
843
        invoke  GetPhysAddr
3545 hidnplayr 844
        mov     [TxRingPhysAddr], eax
845
 
846
        mov     [RingSizes], (((RX_RING - 1) shl RINGSZ_RXSHIFT) + ((TX_RING - 1) shl RINGSZ_TXSHIFT))
847
 
848
;
849
 
4998 hidnplayr 850
        mov     [ebx + device.linkspeed], (LINKSPEED_FORCE or LINKSPEED_10)
851
        mov     [ebx + device.duplex], 0
3545 hidnplayr 852
        mov     [LinkSpeed], (LINKSPEED_FORCE or LINKSPEED_10)
853
        mov     [UnknownSetupReg3], UNKSETUP3_VAL1
854
 
4998 hidnplayr 855
        mov     eax, [ebx + device.desc_ver]
3545 hidnplayr 856
        mov     [TxRxControl], eax
857
        call    pci_push
858
        or      eax, TXRXCTL_BIT1
859
        mov     [TxRxControl], eax
860
 
861
        stdcall reg_delay, UnknownSetupReg5-edi, UNKSETUP5_BIT31, UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, 0
862
 
863
        mov     [UnknownSetupReg4], 0
864
        mov     [MIIStatus], MIISTAT_MASK2
865
 
866
;
867
 
868
        mov     [Misc1], (MISC1_FORCE or MISC1_HD)
869
 
870
        mov     eax, [TransmitterStatus]
871
        mov     [TransmitterStatus], eax
872
 
873
        mov     [PacketFilterFlags], PFF_ALWAYS
874
 
875
        mov     [OffloadConfig], OFFLOAD_NORMAL
876
 
877
        mov     eax, [ReceiverStatus]
878
        mov     [ReceiverStatus], eax
879
 
880
; set random seed
881
        push    ebx
4998 hidnplayr 882
        invoke  GetTimerTicks   ; bad idea, driver is started at system startup in 90% of cases..
3545 hidnplayr 883
        pop     ebx
884
 
4998 hidnplayr 885
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 886
 
887
        and     eax, RNDSEED_MASK
888
        or      eax, RNDSEED_FORCE
889
        mov     [RandomSeed], eax
890
 
891
        mov     [UnknownSetupReg1], UNKSETUP1_VAL
892
        mov     [UnknownSetupReg2], UNKSETUP2_VAL
893
        mov     [PollingInterval], POLL_DEFAULT
894
        mov     [UnknownSetupReg6], UNKSETUP6_VAL
895
 
4998 hidnplayr 896
        mov     eax, [ebx + device.phyaddr]
3545 hidnplayr 897
        shl     eax, ADAPTCTL_PHYSHIFT
898
        or      eax, (ADAPTCTL_PHYVALID or ADAPTCTL_RUNNING)
899
        mov     [AdapterControl], eax
900
 
901
        mov     [MIISpeed], (MIISPEED_BIT8 or MIIDELAY)
902
        mov     [UnknownSetupReg4], UNKSETUP4_VAL
903
        mov     [WakeUpFlags], WAKEUPFLAGS_VAL
904
 
905
        or      [PowerState], POWERSTATE_POWEREDUP
906
        call    pci_push
907
 
908
        mov     esi, 10
4998 hidnplayr 909
        invoke  Sleep
3545 hidnplayr 910
 
911
        or      [PowerState], POWERSTATE_VALID
912
        mov     [IrqMask], 0
913
 
914
;;;     ; ??? Mask RX interrupts
915
        mov      [IrqMask], IRQ_RX_ALL + IRQ_TX_ALL
916
;;;     ; ??? Mask TX interrupts
917
;;;     mov      [IrqMask], IRQ_TX_ALL
918
;;;     ; ??? Mask OTHER interrupts
919
;;;     mov      [IrqMask], IRQ_OTHER_ALL
920
        call    pci_push
921
 
922
        mov     [MIIStatus], MIISTAT_MASK2
923
        mov     [IrqStatus], IRQSTAT_MASK
924
        call    pci_push
925
 
926
        mov     [MulticastAddrA], MCASTADDRA_FORCE
927
        mov     [MulticastAddrB], 0
928
        mov     [MulticastMaskA], 0
929
        mov     [MulticastMaskB], 0
930
 
931
        mov     [PacketFilterFlags], (PFF_ALWAYS or PFF_MYADDR)
932
 
933
        call    set_multicast
934
 
935
        ; One manual link speed update: Interrupts are enabled, future link
936
        ; speed changes cause interrupts and are handled by nv_link_irq().
937
 
938
        mov     eax, [MIIStatus]
939
        mov     [MIIStatus], MIISTAT_MASK
940
        DEBUGF  1,"startup: got 0x%x\n", eax
941
 
942
        call    update_linkspeed
943
 
944
        mov     [TransmitterControl], XMITCTL_START       ; start TX
945
        call    pci_push
946
 
4998 hidnplayr 947
        mov     [ebx + device.nocable], 0
3545 hidnplayr 948
        test    eax, eax
949
        jnz     .return
950
        DEBUGF  1,"no link during initialization.\n"
4998 hidnplayr 951
        mov     [ebx + device.nocable], 1
3545 hidnplayr 952
 
953
  .return:
954
        xor     eax, eax        ; Indicate that we have successfully reset the card
4998 hidnplayr 955
        mov     [ebx + device.mtu], 1514 ;;; FIXME
3545 hidnplayr 956
        ret
957
 
958
 
959
fail:
960
        or      eax, -1
961
        ret
962
 
963
;--------------------------------------------------------
964
;
965
; MII_RW
966
;
967
; read/write a register on the PHY.
968
; Caller must guarantee serialization
4998 hidnplayr 969
; Input:  EAX - miireg, EDX - phy addr, ECX - value to write (or -1 to read)
970
; Output: EAX - retval (lower 16 bits)
3545 hidnplayr 971
;
972
;--------------------------------------------------------
973
 
974
mii_rw:
975
 
976
        DEBUGF  1,"mii_rw: 0x%x to reg %d at PHY %d\n", ecx, eax, edx
977
 
978
        push    edx
979
 
4998 hidnplayr 980
        mov     edi, [ebx + device.mmio_addr]
981
 
982
; Check if MII interface is busy
3545 hidnplayr 983
        mov     [MIIStatus], MIISTAT_MASK
4998 hidnplayr 984
       @@:
3545 hidnplayr 985
        test    [MIIControl], MIICTL_INUSE
986
        jz      @f
987
        mov     [MIIControl], MIICTL_INUSE
988
 
4998 hidnplayr 989
        DEBUGF  1,"mii_rw: in use!\n"
990
        pusha
3545 hidnplayr 991
        mov     esi, NV_MIIBUSY_DELAY
4998 hidnplayr 992
        invoke  Sleep
993
        popa
994
        jmp     @r
3545 hidnplayr 995
       @@:
996
 
4998 hidnplayr 997
; Set the address we want to access
3545 hidnplayr 998
        shl     edx, MIICTL_ADDRSHIFT
999
        or      edx, eax
1000
 
4998 hidnplayr 1001
        ; When writing, write the data first.
3545 hidnplayr 1002
        cmp     ecx, MII_READ
1003
        je      @f
1004
        mov     [MIIData], ecx
1005
        or      edx, MIICTL_WRITE
1006
       @@:
4998 hidnplayr 1007
 
3545 hidnplayr 1008
        mov     [MIIControl], edx
1009
 
4998 hidnplayr 1010
; Wait for read/write to complete
3545 hidnplayr 1011
        stdcall reg_delay, MIIControl-edi, MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, 0
1012
 
1013
        test    eax, eax
1014
        jz      @f
1015
        DEBUGF  1,"mii_rw timed out.\n"
1016
        or      eax, -1
1017
        jmp     .return
4998 hidnplayr 1018
 
3545 hidnplayr 1019
       @@:
1020
        cmp     ecx, MII_READ
4998 hidnplayr 1021
        je      .read
3545 hidnplayr 1022
; it was a write operation - fewer failures are detectable
1023
        DEBUGF  1,"mii_rw write: ok\n"
1024
        xor     eax, eax
1025
        jmp     .return
1026
 
4998 hidnplayr 1027
  .read:
3545 hidnplayr 1028
        mov     eax, [MIIStatus]
1029
        test    eax, MIISTAT_ERROR
1030
        jz      @f
1031
        DEBUGF  1,"mii read: failed.\n"
1032
        or      eax, -1
1033
        jmp     .return
4998 hidnplayr 1034
 
3545 hidnplayr 1035
       @@:
1036
        mov     eax, [MIIData]
1037
        DEBUGF  1,"mii read: 0x%x.\n", eax
1038
 
1039
  .return:
1040
        pop     edx
1041
        ret
1042
 
1043
 
1044
 
1045
 
1046
 
1047
; Input:  offset:word, mask:dword, target:dword, delay:word, delaymax:word, msg:dword
1048
; Output: EAX - 0|1
1049
 
1050
proc    reg_delay, offset:dword, mask:dword, target:dword, delay:dword, delaymax:dword, msg:dword
1051
 
1052
;        DEBUGF  1,"reg_delay\n"
1053
 
1054
        push    esi
1055
        call    pci_push
1056
 
1057
  .loop:
1058
        mov     esi, [delay]
4998 hidnplayr 1059
        invoke  Sleep
3545 hidnplayr 1060
        mov     eax, [delaymax]
1061
        sub     eax, [delay]
1062
        mov     [delaymax], eax
1063
 
1064
        cmp     eax, 0
1065
        jl      .fail
1066
 
1067
        mov     eax, [offset]
1068
        mov     eax, [edi + eax]
1069
        and     eax, [mask]
1070
        cmp     eax, [target]
1071
        jne     .loop
1072
 
1073
        pop     esi
1074
        xor     eax, eax
1075
        ret
1076
 
1077
  .fail:
1078
        pop     esi
1079
        xor     eax, eax
1080
        inc     eax
1081
        ret
1082
 
1083
endp
1084
 
1085
 
1086
 
1087
 
1088
 
1089
; Input:  none
1090
; Output: EAX - result (0 = OK, other = error)
1091
phy_init:
1092
 
1093
        push    ebx ecx
1094
 
1095
        ; set advertise register
4998 hidnplayr 1096
        mov     edx, [ebx + device.phyaddr]
3545 hidnplayr 1097
        mov     eax, MII_ADVERTISE
1098
        mov     ecx, MII_READ
1099
        call    mii_rw
1100
 
1101
        or      eax, (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or 0x800 or 0x400)
1102
 
1103
        mov     ecx, eax
1104
        mov     eax, MII_ADVERTISE
1105
        call    mii_rw
1106
 
1107
        test    eax, eax
1108
        jz      @f
1109
 
4998 hidnplayr 1110
        DEBUGF  2,"phy write to advertise failed.\n"
3545 hidnplayr 1111
 
1112
        mov     eax, PHY_ERROR
1113
        jmp     .return
1114
       @@:
1115
 
1116
        ; get phy interface type
4998 hidnplayr 1117
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 1118
        mov     eax, [PhyInterface]
1119
        DEBUGF  1,"phy interface type = 0x%x\n", eax:8
1120
 
1121
        ; see if gigabit phy
1122
        mov     eax, MII_BMSR
1123
        mov     ecx, MII_READ
1124
        call    mii_rw
1125
 
1126
        test    eax, PHY_GIGABIT
1127
        jnz     .gigabit
4998 hidnplayr 1128
        mov     [ebx + device.gigabit], 0
3545 hidnplayr 1129
        jmp     .next_if
1130
 
1131
  .gigabit:
4998 hidnplayr 1132
        mov     [ebx + device.gigabit], PHY_GIGABIT
3545 hidnplayr 1133
 
5182 hidnplayr 1134
        mov     eax, MII_CTRL1000
3545 hidnplayr 1135
        mov     ecx, MII_READ
1136
        call    mii_rw
1137
 
1138
        and     eax, (not ADVERTISE_1000HALF)
1139
 
1140
        test    [PhyInterface], PHY_RGMII
1141
        jz      @f
1142
        or      eax, ADVERTISE_1000FULL
1143
        jmp     .next
1144
       @@:
1145
 
1146
        and     eax, (not ADVERTISE_1000FULL)
1147
 
1148
  .next:
1149
        mov     ecx, eax
5182 hidnplayr 1150
        mov     eax, MII_CTRL1000
3545 hidnplayr 1151
        call    mii_rw
1152
 
1153
        test    eax, eax
1154
        jz      .next_if
1155
 
4998 hidnplayr 1156
        DEBUGF  2,"phy init failed.\n"
3545 hidnplayr 1157
 
1158
        mov     eax, PHY_ERROR
1159
        jmp     .return
1160
 
1161
  .next_if:
1162
 
1163
        call    phy_reset
1164
        test    eax, eax
1165
        jz      @f
1166
 
4998 hidnplayr 1167
        DEBUGF  2,"phy reset failed.\n"
3545 hidnplayr 1168
 
1169
        mov     eax, PHY_ERROR
1170
        jmp     .return
1171
       @@:
1172
 
1173
        ; phy vendor specific configuration
4998 hidnplayr 1174
        cmp     [ebx + device.phy_oui], PHY_OUI_CICADA
3545 hidnplayr 1175
        jne     .next_if2
1176
        test    [PhyInterface], PHY_RGMII
1177
        jz      .next_if2
1178
 
1179
        mov     eax, MII_RESV1
1180
        mov     ecx, MII_READ
1181
        call    mii_rw
1182
 
1183
        and     eax, (not (PHY_INIT1 or PHY_INIT2))
1184
        or      eax, (PHY_INIT3 or PHY_INIT4)
1185
        mov     ecx, eax
1186
        mov     eax, MII_RESV1
1187
        call    mii_rw
1188
 
1189
        test    eax, eax
1190
        jz      @f
1191
 
4998 hidnplayr 1192
        DEBUGF  2,"phy init failed.\n"
3545 hidnplayr 1193
 
1194
        mov     eax, PHY_ERROR
1195
        jmp     .return
1196
       @@:
1197
 
1198
        mov     eax, MII_NCONFIG
1199
        mov     ecx, MII_READ
1200
        call    mii_rw
1201
 
1202
        or      eax, PHY_INIT5
1203
        mov     ecx, eax
1204
        mov     eax, MII_NCONFIG
1205
        call    mii_rw
1206
        test    eax, eax
1207
        jz      .next_if2
1208
 
4998 hidnplayr 1209
        DEBUGF  2,"phy init failed.\n"
3545 hidnplayr 1210
 
1211
        mov     eax, PHY_ERROR
1212
        jmp     .return
1213
 
1214
 
1215
 
1216
  .next_if2:
1217
 
4998 hidnplayr 1218
        cmp     [ebx + device.phy_oui], PHY_OUI_CICADA
3545 hidnplayr 1219
        jne     .restart
1220
 
1221
        mov     eax, MII_SREVISION
1222
        mov     ecx, MII_READ
1223
        call    mii_rw
1224
 
1225
        or      eax, PHY_INIT6
1226
        mov     ecx, eax
1227
        mov     eax, MII_SREVISION
1228
        call    mii_rw
1229
        test    eax, eax
1230
        jz      .restart
1231
 
4998 hidnplayr 1232
        DEBUGF  2,"phy init failed.\n"
3545 hidnplayr 1233
 
1234
        jmp     .return
1235
 
1236
  .restart:
1237
        ; restart auto negotiation
1238
 
1239
        mov     eax, MII_BMCR
1240
        mov     ecx, MII_READ
1241
        call    mii_rw
1242
 
1243
        or      eax, (BMCR_ANRESTART or BMCR_ANENABLE)
1244
        mov     ecx, eax
1245
        mov     eax, MII_BMCR
1246
        call    mii_rw
1247
        test    eax, eax
1248
        jz      .ok
1249
 
1250
        mov     eax, PHY_ERROR
1251
        jmp     .return
1252
 
1253
  .ok:
1254
        xor     eax, eax
1255
  .return:
1256
        pop     ecx ebx
1257
 
1258
        ret
1259
 
1260
 
1261
; Input:  none
1262
; Output: EAX - result (0 = OK, other = error)
1263
phy_reset:
1264
 
1265
        DEBUGF  1,"phy_reset\n"
1266
 
1267
        push    ebx ecx edx
1268
 
4998 hidnplayr 1269
        mov     edx, [ebx + device.phyaddr]
3545 hidnplayr 1270
        mov     eax, MII_BMCR
1271
        mov     ecx, MII_READ
1272
        call    mii_rw
1273
 
1274
        or      eax, BMCR_RESET
1275
        push    eax
1276
        mov     ecx, eax
1277
        mov     eax, MII_BMCR
1278
        call    mii_rw
1279
 
1280
        test    eax, eax
1281
        jz      @f
1282
 
1283
        pop     eax
1284
        mov     eax, 0xffffffff
1285
        jmp     .return
1286
       @@:
1287
 
1288
        pop     eax
1289
 
1290
        mov     esi, 500
4998 hidnplayr 1291
        invoke  Sleep
3545 hidnplayr 1292
 
1293
        ; must wait till reset is deasserted
1294
        mov     esi, 100        ; FIXME: 100 tries seem excessive
1295
  .while_loop:
1296
        test    eax, BMCR_RESET
1297
        jz      .while_loop_exit
1298
 
1299
        push    esi
1300
        mov     esi, 10
4998 hidnplayr 1301
        invoke  Sleep
3545 hidnplayr 1302
        pop     esi
1303
 
1304
        mov     eax, MII_BMCR
1305
        mov     ecx, MII_READ
1306
        call    mii_rw
1307
 
1308
        dec     esi
1309
        jnz     .while_loop
1310
 
1311
        mov     eax, 0xffffffff
1312
        jmp     .return
1313
 
1314
  .while_loop_exit:
1315
        xor     eax, eax
1316
  .return:
1317
        pop     edx ecx ebx
1318
 
1319
        ret
1320
 
1321
 
1322
align 4
1323
pci_push:
1324
 
1325
        push    eax
1326
        mov     eax, [edi]
1327
        pop     eax
1328
 
1329
        ret
1330
 
1331
 
1332
 
1333
 
1334
align 4
1335
mac_reset:
1336
 
1337
        push    esi edi
1338
 
1339
        DEBUGF  1,"mac_reset.\n"
1340
 
4998 hidnplayr 1341
        mov     edi, [ebx + device.mmio_addr]
1342
        mov     eax, [ebx + device.desc_ver]
3545 hidnplayr 1343
        or      eax, (TXRXCTL_BIT2 or TXRXCTL_RESET)
1344
        mov     [TxRxControl], eax
1345
        call    pci_push
1346
 
1347
        mov     [MacReset], MAC_RESET_ASSERT
1348
        call    pci_push
1349
 
1350
        mov     esi, NV_MAC_RESET_DELAY
4998 hidnplayr 1351
        invoke  Sleep
3545 hidnplayr 1352
 
1353
        mov     [MacReset], 0
1354
        call    pci_push
1355
 
1356
        mov     esi, NV_MAC_RESET_DELAY
4998 hidnplayr 1357
        invoke  Sleep
3545 hidnplayr 1358
 
4998 hidnplayr 1359
        mov     eax, [ebx + device.desc_ver]
3545 hidnplayr 1360
        or      eax, TXRXCTL_BIT2
1361
        mov     [TxRxControl], eax
1362
        call    pci_push
1363
 
1364
        pop     edi esi
1365
 
1366
        ret
1367
 
1368
 
1369
 
1370
align 4
1371
init_ring:
1372
 
1373
        DEBUGF  1,"init rings\n"
1374
        push    eax esi ecx
1375
 
4998 hidnplayr 1376
        mov     [ebx + device.cur_tx], 0
1377
        mov     [ebx + device.last_tx], 0
3545 hidnplayr 1378
 
1379
        mov     ecx, TX_RING
4998 hidnplayr 1380
        lea     esi, [ebx + device.tx_ring]
3545 hidnplayr 1381
  .tx_loop:
1382
        mov     [esi + TxDesc.FlagLen], 0
4998 hidnplayr 1383
        mov     [esi + TxDesc.PacketBuffer], 0
3545 hidnplayr 1384
        add     esi, sizeof.TxDesc
1385
        dec     ecx
1386
        jnz     .tx_loop
1387
 
1388
 
4998 hidnplayr 1389
        mov     [ebx + device.cur_rx], 0
1390
 
3545 hidnplayr 1391
        mov     ecx, RX_RING
4998 hidnplayr 1392
        lea     esi, [ebx + device.rx_ring]
3545 hidnplayr 1393
  .rx_loop:
1394
        push    ecx esi
4998 hidnplayr 1395
        invoke  KernelAlloc, 4096 shl RBLEN             ; push/pop esi not needed, but just in case...
3545 hidnplayr 1396
        pop     esi
1397
        mov     [esi + RX_RING*sizeof.RxDesc], eax
4998 hidnplayr 1398
        invoke  GetPhysAddr
3545 hidnplayr 1399
        mov     [esi + RxDesc.PacketBuffer], eax
1400
        mov     [esi + RxDesc.FlagLen], (4096 shl RBLEN or NV_RX_AVAIL)
1401
        add     esi, sizeof.RxDesc
1402
        pop     ecx
1403
        dec     ecx
1404
        jnz     .rx_loop
1405
 
1406
        pop     ecx esi eax
1407
 
1408
        ret
1409
 
1410
 
1411
 
1412
 
1413
 
1414
; Input:  none
1415
; Output: none
1416
align 4
1417
txrx_reset:
1418
 
1419
        push    eax esi
1420
 
4998 hidnplayr 1421
        DEBUGF  1,"txrx_reset\n"
3545 hidnplayr 1422
 
4998 hidnplayr 1423
        mov     edi, [ebx + device.mmio_addr]
1424
        mov     eax, [ebx + device.desc_ver]
3545 hidnplayr 1425
        or      eax, (TXRXCTL_BIT2 or TXRXCTL_RESET)
1426
        mov     [TxRxControl], eax
1427
        call    pci_push
1428
 
1429
        mov     esi, NV_TXRX_RESET_DELAY
4998 hidnplayr 1430
        invoke  Sleep
3545 hidnplayr 1431
 
4998 hidnplayr 1432
        mov     eax, [ebx + device.desc_ver]
3545 hidnplayr 1433
        or      eax, TXRXCTL_BIT2
1434
        mov     [TxRxControl], eax
1435
        call    pci_push
1436
 
1437
        pop     esi eax
1438
 
1439
        ret
1440
 
1441
 
1442
 
1443
 
1444
 
1445
; Input:  none
1446
; Output: none
1447
set_multicast:
1448
 
1449
        ; u32 addr[2];
1450
        ; u32 mask[2];
1451
        ; u32 pff;
1452
        ; u32 alwaysOff[2];
1453
        ; u32 alwaysOn[2];
1454
        ;
1455
        ; memset(addr, 0, sizeof(addr));
1456
        ; memset(mask, 0, sizeof(mask));
1457
        ;
1458
        ; pff = PFF_MYADDR;
1459
        ;
1460
        ; alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0;
1461
        ;
1462
        ; addr[0] = alwaysOn[0];
1463
        ; addr[1] = alwaysOn[1];
1464
        ; mask[0] = alwaysOn[0] | alwaysOff[0];
1465
        ; mask[1] = alwaysOn[1] | alwaysOff[1];
1466
        ;
1467
        ; addr[0] |= MCASTADDRA_FORCE;
1468
        ; pff |= PFF_ALWAYS;
1469
 
1470
        call    stop_rx
1471
 
4998 hidnplayr 1472
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 1473
        mov     [MulticastAddrA], MCASTADDRA_FORCE
1474
 
1475
        mov     [MulticastAddrB], 0
1476
        mov     [MulticastMaskA], 0
1477
        mov     [MulticastMaskB], 0
1478
        mov     [PacketFilterFlags], (PFF_MYADDR or PFF_ALWAYS)
1479
 
1480
        call    start_rx
1481
 
1482
        ret
1483
 
1484
 
1485
 
1486
 
1487
 
1488
; Input:  none
1489
; Output: none
1490
start_rx:
1491
 
1492
        push    edi
1493
 
1494
        DEBUGF  1,"start_rx\n"
1495
 
1496
        ; Already running? Stop it.
4998 hidnplayr 1497
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 1498
        mov     eax, [ReceiverControl]
1499
        test    eax, RCVCTL_START
1500
        jz      @f
1501
        mov     [ReceiverControl], 0
1502
        call    pci_push
1503
       @@:
1504
 
4998 hidnplayr 1505
        mov     eax, [ebx + device.linkspeed]
3545 hidnplayr 1506
        mov     [LinkSpeed], eax
1507
        call    pci_push
1508
 
1509
        mov     [ReceiverControl], RCVCTL_START
1510
        call    pci_push
1511
 
1512
        pop     edi
1513
 
1514
        ret
1515
 
1516
 
1517
 
1518
 
1519
; Input:  none
1520
; Output: none
1521
stop_rx:
1522
 
1523
        push    esi edi
1524
 
4998 hidnplayr 1525
        DEBUGF  1,"stop_rx.\n"
3545 hidnplayr 1526
 
4998 hidnplayr 1527
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 1528
        mov     [ReceiverControl], 0
1529
 
1530
        push    ebx edx edi
1531
        stdcall reg_delay, ReceiverStatus-edi, RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, 0
1532
        pop     edi edx ebx
1533
 
1534
        mov     esi, NV_RXSTOP_DELAY2
4998 hidnplayr 1535
        invoke  Sleep
3545 hidnplayr 1536
 
1537
        mov     [LinkSpeed], 0
1538
 
1539
        pop     edi esi
1540
 
1541
        ret
1542
 
1543
 
1544
 
1545
 
1546
; Input:  none
1547
; Output: EAX
1548
update_linkspeed:
1549
 
1550
        DEBUGF  1,"update linkspeed\n"
1551
 
1552
; BMSR_LSTATUS is latched, read it twice: we want the current value.
1553
 
4998 hidnplayr 1554
        mov     edx, [ebx + device.phyaddr]
3545 hidnplayr 1555
        mov     eax, MII_BMSR
1556
        mov     ecx, MII_READ
1557
        call    mii_rw
1558
 
1559
        mov     eax, MII_BMSR
1560
        mov     ecx, MII_READ
1561
        call    mii_rw
1562
 
4998 hidnplayr 1563
        test    ax, BMSR_LSTATUS               ; Link up?
1564
        jz      .no_link
3545 hidnplayr 1565
 
4998 hidnplayr 1566
        DEBUGF  1,"link is up\n"
1567
 
1568
        test    ax, BMSR_ANEGCOMPLETE          ; still in autonegotiation?
3545 hidnplayr 1569
        jz      .10mbit_hd
1570
 
4998 hidnplayr 1571
        DEBUGF  1,"autonegotiation is complete\n"
1572
 
1573
        cmp     [ebx + device.gigabit], PHY_GIGABIT
3545 hidnplayr 1574
        jne     .no_gigabit
1575
 
4998 hidnplayr 1576
        ;mov     edx, [ebx + device.phyaddr]
5182 hidnplayr 1577
        mov     eax, MII_CTRL1000
3545 hidnplayr 1578
        mov     ecx, MII_READ
1579
        call    mii_rw
1580
        push    eax
1581
 
4998 hidnplayr 1582
        ;mov     edx, [ebx + device.phyaddr]
5182 hidnplayr 1583
        mov     eax, MII_STAT1000
3545 hidnplayr 1584
        mov     ecx, MII_READ
1585
        call    mii_rw
1586
        pop     ecx
1587
 
1588
        test    eax, LPA_1000FULL
1589
        jz      .no_gigabit
1590
        test    ecx, ADVERTISE_1000FULL
1591
        jz      .no_gigabit
1592
 
1593
        DEBUGF  1,"update_linkspeed: GBit ethernet detected.\n"
4998 hidnplayr 1594
        mov     [ebx + device.state], ETH_LINK_1G
3545 hidnplayr 1595
        mov     ecx, (LINKSPEED_FORCE or LINKSPEED_1000)
1596
        xor     eax, eax
1597
        inc     eax
1598
        jmp     set_speed
1599
  .no_gigabit:
1600
 
4998 hidnplayr 1601
        ;mov     edx, [ebx + device.phyaddr]
3545 hidnplayr 1602
        mov     eax, MII_ADVERTISE
1603
        mov     ecx, MII_READ
1604
        call    mii_rw        ; adv = eax
1605
        push    eax
1606
 
4998 hidnplayr 1607
        ;mov     edx, [ebx + device.phyaddr]
3545 hidnplayr 1608
        mov     eax, MII_LPA
1609
        mov     ecx, MII_READ
1610
        call    mii_rw        ; lpa = eax
1611
        pop     ecx
1612
 
4998 hidnplayr 1613
        DEBUGF  1,"PHY advertises 0x%x, lpa 0x%x\n", cx, ax
3545 hidnplayr 1614
        and     eax, ecx                ; FIXME: handle parallel detection properly, handle gigabit ethernet
1615
 
1616
        test    eax, LPA_100FULL
1617
        jz      @f
1618
        DEBUGF  1,"update_linkspeed: 100 mbit full duplex\n"
4998 hidnplayr 1619
        mov     [ebx + device.state], ETH_LINK_100M + ETH_LINK_FD
3545 hidnplayr 1620
        mov     ecx, (LINKSPEED_FORCE or LINKSPEED_100)
1621
        xor     eax, eax
1622
        inc     eax
1623
        jmp     set_speed
1624
       @@:
1625
 
1626
        test    eax, LPA_100HALF
1627
        jz      @f
1628
        DEBUGF  1,"update_linkspeed: 100 mbit half duplex\n"
4998 hidnplayr 1629
        mov     [ebx + device.state], ETH_LINK_100M
3545 hidnplayr 1630
        mov     ecx, (LINKSPEED_FORCE or LINKSPEED_100)
1631
        xor     eax, eax
1632
        jmp     set_speed
1633
       @@:
1634
 
1635
        test    eax, LPA_10FULL
1636
        jz      @f
1637
        DEBUGF  1,"update_linkspeed: 10 mbit full duplex\n"
4998 hidnplayr 1638
        mov     [ebx + device.state], ETH_LINK_10M + ETH_LINK_FD
3545 hidnplayr 1639
        mov     ecx, (LINKSPEED_FORCE or LINKSPEED_10)
1640
        xor     eax, eax
1641
        inc     eax
1642
        jmp     set_speed
1643
       @@:
1644
 
1645
  .10mbit_hd:
1646
        DEBUGF  1,"update_linkspeed: 10 mbit half duplex\n"
4998 hidnplayr 1647
        mov     [ebx + device.state], ETH_LINK_10M
3545 hidnplayr 1648
        mov     ecx, (LINKSPEED_FORCE or LINKSPEED_10)
1649
        xor     eax, eax
1650
        jmp     set_speed
1651
 
4998 hidnplayr 1652
  .no_link:
1653
        DEBUGF  1,"update_linkspeed: link is down\n"
1654
        mov     [ebx + device.state], ETH_LINK_DOWN
1655
        mov     ecx, (LINKSPEED_FORCE or LINKSPEED_10)
1656
        xor     eax, eax
1657
        jmp     set_speed
3545 hidnplayr 1658
 
4998 hidnplayr 1659
 
3545 hidnplayr 1660
align 4
1661
set_speed:
1662
 
4998 hidnplayr 1663
        cmp     eax, [ebx + device.duplex]
3545 hidnplayr 1664
        jne     .update
4998 hidnplayr 1665
        cmp     ecx, [ebx + device.linkspeed]
3545 hidnplayr 1666
        jne     .update
1667
 
1668
        ret
1669
 
1670
  .update:
4998 hidnplayr 1671
        DEBUGF  1,"update_linkspeed: changing link to 0x%x/XD.\n", ecx
3545 hidnplayr 1672
 
4998 hidnplayr 1673
        mov     [ebx + device.duplex], eax
1674
        mov     [ebx + device.linkspeed], ecx
3545 hidnplayr 1675
 
4998 hidnplayr 1676
        cmp     [ebx + device.gigabit], PHY_GIGABIT
3545 hidnplayr 1677
        jne     .no_gigabit
1678
 
4998 hidnplayr 1679
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 1680
        mov     eax, [RandomSeed]
1681
 
1682
        and     eax, not (0x3FF00)
1683
        mov     ecx, eax                ; phyreg = ecx
1684
 
4998 hidnplayr 1685
        mov     eax, [ebx + device.linkspeed]
3545 hidnplayr 1686
        and     eax, 0xFFF
1687
        cmp     eax, LINKSPEED_10
1688
        jne     @f
1689
        or      ecx, RNDSEED_FORCE3
1690
        jmp     .end_if4
1691
       @@:
1692
 
1693
        cmp     eax, LINKSPEED_100
1694
        jne     @f
1695
        or      ecx, RNDSEED_FORCE2
1696
        jmp     .end_if4
1697
       @@:
1698
 
1699
        cmp     eax, LINKSPEED_1000
1700
        jne     .end_if4
1701
        or      ecx, RNDSEED_FORCE
1702
  .end_if4:
1703
        mov     [RandomSeed], ecx
1704
  .no_gigabit:
1705
 
1706
        mov     ecx, [PhyInterface]
1707
        and     ecx, not (PHY_HALF or PHY_100 or PHY_1000)
1708
 
4998 hidnplayr 1709
        cmp     [ebx + device.duplex], 0
3545 hidnplayr 1710
        jne     @f
1711
        or      ecx, PHY_HALF
1712
       @@:
1713
 
4998 hidnplayr 1714
        mov     eax, [ebx + device.linkspeed]
3545 hidnplayr 1715
        and     eax, 0xFFF
1716
        cmp     eax, LINKSPEED_100
1717
        jne     @f
1718
        or      ecx, PHY_100
1719
        jmp     .end_if5
1720
       @@:
1721
 
1722
        cmp     eax, LINKSPEED_1000
1723
        jne     .end_if5
1724
        or      ecx, PHY_1000
1725
 
1726
  .end_if5:
1727
        mov     [PhyInterface], ecx
1728
 
4998 hidnplayr 1729
        cmp     [ebx + device.duplex], 0
3545 hidnplayr 1730
        je      @f
1731
        xor     ecx, ecx
1732
        jmp     .next
1733
       @@:
1734
 
1735
        mov     ecx, MISC1_HD
1736
  .next:
1737
        or      ecx, MISC1_FORCE
1738
        mov     [Misc1], ecx
1739
 
1740
        call    pci_push
1741
 
4998 hidnplayr 1742
        mov     eax, [ebx + device.linkspeed]
3545 hidnplayr 1743
        mov     [LinkSpeed], eax
1744
 
1745
        call    pci_push
1746
 
1747
        ret
1748
 
1749
 
1750
 
1751
 
1752
 
1753
 
1754
align 4
1755
read_mac:
1756
 
4998 hidnplayr 1757
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 1758
        mov     eax, [MacAddrA]
1759
        mov     ecx, [MacAddrB]
1760
 
4998 hidnplayr 1761
        mov     dword [ebx + device.mac], eax
1762
        mov     word [ebx + device.mac + 4], cx
3545 hidnplayr 1763
 
4998 hidnplayr 1764
        cmp     [ebx + device.device_id], 0x03E5
3545 hidnplayr 1765
        jae     @f
1766
        bswap   eax
1767
        xchg    cl, ch
4998 hidnplayr 1768
        mov     dword [ebx + device.mac + 2], eax
1769
        mov     word [ebx + device.mac], cx
3545 hidnplayr 1770
       @@:
1771
 
4470 hidnplayr 1772
        DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n", \
4998 hidnplayr 1773
        [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 1774
 
1775
        ret
1776
 
1777
 
1778
 
1779
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1780
;;                                         ;;
1781
;; Transmit                                ;;
1782
;;                                         ;;
1783
;; In: buffer pointer in [esp+4]           ;;
1784
;;     size of buffer in [esp+8]           ;;
1785
;;     pointer to device structure in ebx  ;;
1786
;;                                         ;;
1787
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4998 hidnplayr 1788
 
1789
proc transmit stdcall bufferptr, buffersize
1790
 
1791
        pushf
1792
        cli
1793
 
1794
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [buffersize]
1795
        mov     eax, [bufferptr]
1796
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
3545 hidnplayr 1797
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
1798
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
1799
        [eax+13]:2,[eax+12]:2
1800
 
4998 hidnplayr 1801
        cmp     [buffersize], 1514
3545 hidnplayr 1802
        ja      .fail
4998 hidnplayr 1803
        cmp     [buffersize], 60
3545 hidnplayr 1804
        jb      .fail
1805
 
1806
; get the descriptor address
4998 hidnplayr 1807
        mov     eax, [ebx + device.cur_tx]
1808
        shl     eax, 3                                  ; TX descriptor is 8 bytes.
1809
        lea     esi, [ebx + device.tx_ring + eax]
1810
 
1811
        mov     eax, [bufferptr]
3545 hidnplayr 1812
        mov     [esi + TX_RING*sizeof.TxDesc], eax
4998 hidnplayr 1813
        invoke  GetPhysAddr                             ; Does not change esi/ebx :)
3545 hidnplayr 1814
        mov     [esi + TxDesc.PacketBuffer], eax
1815
 
4998 hidnplayr 1816
        mov     eax, [buffersize]
1817
        or      eax, [ebx + device.txflags]
3545 hidnplayr 1818
        mov     [esi + TxDesc.FlagLen], eax
1819
 
4998 hidnplayr 1820
        mov     edi, [ebx + device.mmio_addr]
1821
        mov     eax, [ebx + device.desc_ver]
3545 hidnplayr 1822
        or      eax, TXRXCTL_KICK
1823
        mov     [TxRxControl], eax
1824
 
1825
        call    pci_push
1826
 
4998 hidnplayr 1827
        inc     [ebx + device.cur_tx]
1828
        and     [ebx + device.cur_tx], (TX_RING-1)
3545 hidnplayr 1829
 
1830
; Update stats
4998 hidnplayr 1831
        inc     [ebx + device.packets_tx]
1832
        mov     eax, [buffersize]
1833
        add     dword[ebx + device.bytes_tx], eax
1834
        adc     dword[ebx + device.bytes_tx + 4], 0
3545 hidnplayr 1835
 
5127 hidnplayr 1836
        popf
3545 hidnplayr 1837
        xor     eax, eax
4998 hidnplayr 1838
        ret
3545 hidnplayr 1839
 
1840
  .fail:
4998 hidnplayr 1841
        DEBUGF  2,"Send failed\n"
1842
        invoke  KernelFree, [bufferptr]
1843
        popf
4334 hidnplayr 1844
        or      eax, -1
4998 hidnplayr 1845
        ret
3545 hidnplayr 1846
 
4998 hidnplayr 1847
endp
3545 hidnplayr 1848
 
1849
 
1850
 
1851
 
1852
 
4998 hidnplayr 1853
 
3545 hidnplayr 1854
; Interrupt handler
1855
align 4
1856
int_handler:
1857
 
1858
        push    ebx esi edi
1859
 
4998 hidnplayr 1860
        DEBUGF  1,"INT\n"
3545 hidnplayr 1861
 
1862
;-------------------------------------------
1863
; Find pointer of device wich made IRQ occur
1864
 
1865
        mov     esi, device_list
1866
        mov     ecx, [devices]
1867
        test    ecx, ecx
1868
        jz      .fail
1869
  .nextdevice:
1870
        mov     ebx, dword [esi]
1871
        add     esi, 4
1872
 
4998 hidnplayr 1873
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 1874
        mov     eax, [IrqStatus]
1875
        test    eax, eax
1876
        jnz     .got_it
1877
        dec     ecx
1878
        jnz     .nextdevice
1879
  .nothing:
1880
        pop     edi esi ebx
1881
        xor     eax, eax
1882
 
1883
        ret
1884
 
1885
  .got_it:
1886
        mov     [IrqStatus], eax
4998 hidnplayr 1887
        DEBUGF  1,"IrqStatus = %x\n", eax
3545 hidnplayr 1888
 
4998 hidnplayr 1889
        test    eax, IRQ_RX ;+ IRQ_TIMER ;;;;
3545 hidnplayr 1890
        jz      .no_rx
1891
 
4998 hidnplayr 1892
        push    ebx
1893
  .more_rx:
1894
        pop     ebx
1895
        mov     eax, [ebx + device.cur_rx]
3545 hidnplayr 1896
        mov     cx, sizeof.RxDesc
1897
        mul     cx
4998 hidnplayr 1898
        lea     esi, [ebx + device.rx_ring + eax]
3545 hidnplayr 1899
        mov     eax, [esi + RxDesc.FlagLen]
1900
 
1901
        test    eax, NV_RX_AVAIL        ; still owned by hardware
4998 hidnplayr 1902
        jnz     .no_rx
3545 hidnplayr 1903
 
4998 hidnplayr 1904
        cmp     [ebx + device.desc_ver], DESC_VER_1
3545 hidnplayr 1905
        jne     @f
1906
        test    eax, NV_RX_DESCRIPTORVALID
4998 hidnplayr 1907
        jz      .no_rx
3545 hidnplayr 1908
        jmp     .next
1909
  @@:
1910
        test    eax, NV_RX2_DESCRIPTORVALID
4998 hidnplayr 1911
        jz      .no_rx
3545 hidnplayr 1912
 
1913
  .next:
4998 hidnplayr 1914
        cmp     dword[ebx + device.desc_ver], DESC_VER_1
3545 hidnplayr 1915
        jne     @f
1916
        and     eax, LEN_MASK_V1
1917
        jmp     .next2
1918
   @@:
1919
        and     eax, LEN_MASK_V2
4998 hidnplayr 1920
 
3545 hidnplayr 1921
  .next2:
4998 hidnplayr 1922
        DEBUGF  1,"Received %u bytes\n", eax
3545 hidnplayr 1923
 
4998 hidnplayr 1924
        ; Update stats
1925
        add     dword[ebx + device.bytes_rx], eax
1926
        adc     dword[ebx + device.bytes_rx + 4], 0
1927
        inc     dword[ebx + device.packets_rx]
3545 hidnplayr 1928
 
4998 hidnplayr 1929
        ; Prepare to give packet to kernel
1930
        push    ebx
1931
        push    .more_rx
3545 hidnplayr 1932
 
4998 hidnplayr 1933
        push    eax
1934
        push    dword[esi + RX_RING*sizeof.RxDesc]
1935
        DEBUGF  1,"packet ptr=0x%x\n", [esi + RX_RING*sizeof.RxDesc]
3545 hidnplayr 1936
 
4998 hidnplayr 1937
        ; Allocate new buffer for this descriptor
1938
        invoke  KernelAlloc, 4096 shl RBLEN
3545 hidnplayr 1939
        mov     [esi + RX_RING*sizeof.RxDesc], eax
4998 hidnplayr 1940
        invoke  GetPhysAddr
3545 hidnplayr 1941
        mov     [esi + RxDesc.PacketBuffer], eax
1942
        mov     [esi + RxDesc.FlagLen], (4096 shl RBLEN or NV_RX_AVAIL)
1943
 
4998 hidnplayr 1944
        ; update current RX descriptor
1945
        inc     [ebx + device.cur_rx]
1946
        and     [ebx + device.cur_rx], (RX_RING-1)
3545 hidnplayr 1947
 
4998 hidnplayr 1948
        jmp     [Eth_input]
3545 hidnplayr 1949
 
1950
  .no_rx:
1951
        test    eax, IRQ_RX_ERROR
1952
        jz      .no_rx_err
1953
 
1954
        push    eax
1955
        DEBUGF  2,"RX error!\n"
1956
 
4998 hidnplayr 1957
        mov     eax, [ebx + device.cur_rx]
3545 hidnplayr 1958
        mov     cx, sizeof.RxDesc
1959
        mul     cx
4998 hidnplayr 1960
        lea     esi, [ebx + device.rx_ring + eax]
3545 hidnplayr 1961
        mov     eax, [esi + RxDesc.FlagLen]
1962
 
4998 hidnplayr 1963
        DEBUGF  1,"Flaglen=%x\n", eax
3545 hidnplayr 1964
 
4998 hidnplayr 1965
        ; TODO: allocate new buff ?
3545 hidnplayr 1966
        pop     eax
1967
 
1968
  .no_rx_err:
4998 hidnplayr 1969
        test    eax, IRQ_TX_ERROR
1970
        jz      .no_tx_err
1971
 
1972
        DEBUGF  2,"TX error!\n"
1973
        ; TODO
1974
 
1975
  .no_tx_err:
3545 hidnplayr 1976
        test    eax, IRQ_LINK
1977
        jz      .no_link
1978
 
1979
        push    eax
1980
        call    update_linkspeed
1981
        pop     eax
1982
 
1983
  .no_link:
4998 hidnplayr 1984
        test    eax, IRQ_TX_OK
1985
        jz      .no_tx
1986
 
1987
        DEBUGF  1, "TX completed\n"
1988
      .loop_tx:
1989
        mov     esi, [ebx + device.last_tx]
1990
        shl     esi, 3                                  ; TX descriptor is 8 bytes.
1991
        lea     esi, [ebx + device.tx_ring + esi]
1992
 
1993
        DEBUGF  1,"Flaglen = 0x%x\n", [esi + TxDesc.FlagLen]
1994
        test    [esi + TxDesc.FlagLen], NV_TX_VALID
1995
        jnz     .no_tx
1996
        cmp     dword[esi + TX_RING*sizeof.TxDesc], 0
1997
        je      .no_tx
1998
 
1999
        DEBUGF  1,"Freeing buffer 0x%x\n", [esi + TX_RING*sizeof.TxDesc]:8
2000
        push    dword[esi + TX_RING*sizeof.TxDesc]
2001
        mov     dword[esi + TX_RING*sizeof.TxDesc], 0
2002
        invoke  KernelFree
2003
 
2004
        inc     [ebx + device.last_tx]
2005
        and     [ebx + device.last_tx], TX_RING - 1
2006
 
2007
        jmp     .loop_tx
2008
 
2009
  .no_tx:
3545 hidnplayr 2010
  .fail:
2011
        pop     edi esi ebx
2012
        xor     eax, eax
2013
        inc     eax
2014
 
2015
        ret
2016
 
2017
 
4998 hidnplayr 2018
; End of code
3545 hidnplayr 2019
 
4998 hidnplayr 2020
data fixups
2021
end data
3545 hidnplayr 2022
 
4998 hidnplayr 2023
include '../peimport.inc'
3545 hidnplayr 2024
 
2025
my_service      db 'FORCEDETH',0                ; max 16 chars include zero
2026
 
4998 hidnplayr 2027
include_debug_strings
3545 hidnplayr 2028
 
4998 hidnplayr 2029
align 4
2030
devices         dd 0
3545 hidnplayr 2031
device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
4998 hidnplayr 2032