Subversion Repositories Kolibri OS

Rev

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

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