Subversion Repositories Kolibri OS

Rev

Rev 4334 | Go to most recent revision | Details | Last modification | View Log | RSS feed

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