Subversion Repositories Kolibri OS

Rev

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

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