Subversion Repositories Kolibri OS

Rev

Rev 9569 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7809 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
9146 hidnplayr 3
;; Copyright (C) KolibriOS team 2018-2021. All rights reserved.    ;;
7809 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  AR81XX driver for KolibriOS                                    ;;
7
;;                                                                 ;;
8
;;  based on alx driver from TI-OpenLink                           ;;
9
;;                                                                 ;;
7827 hidnplayr 10
;;  Written by hidnplayr (hidnplayr@gmail.com)                     ;;
7809 hidnplayr 11
;;                                                                 ;;
7827 hidnplayr 12
;;  Thanks to: floppy121 for kindly providing me with the hardware ;;
13
;;              that made the development of this driver possible. ;;
14
;;                                                                 ;;
7809 hidnplayr 15
;;          GNU GENERAL PUBLIC LICENSE                             ;;
16
;;             Version 2, June 1991                                ;;
17
;;                                                                 ;;
18
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
19
 
20
format PE DLL native
21
entry START
22
 
23
        CURRENT_API             = 0x0200
24
        COMPATIBLE_API          = 0x0100
25
        API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
26
 
9146 hidnplayr 27
; configureable area
7809 hidnplayr 28
 
9146 hidnplayr 29
        MAX_DEVICES             = 16    ; Maximum number of devices this driver may handle
7809 hidnplayr 30
 
9146 hidnplayr 31
        __DEBUG__               = 1     ; 1 = on, 0 = off
32
        __DEBUG_LEVEL__         = 2     ; 1 = verbose, 2 = errors only
7809 hidnplayr 33
 
9146 hidnplayr 34
        TX_RING_SIZE            = 128   ; Number of packets in send ring buffer
35
        RX_RING_SIZE            = 128   ; Number of packets in receive ring buffer
36
 
7809 hidnplayr 37
        RX_BUFFER_SIZE          = 1536
38
 
39
        SMB_TIMER               = 400
9146 hidnplayr 40
        IMT                     = 200                   ; IRQ Modulo Timer
41
        ITH_TPD                 = TX_RING_SIZE / 3      ; Interrupt Threshold TPD
7809 hidnplayr 42
 
9146 hidnplayr 43
; end configureable area
44
 
7809 hidnplayr 45
section '.flat' readable writable executable
46
 
47
include '../proc32.inc'
48
include '../struct.inc'
49
include '../macros.inc'
50
include '../fdo.inc'
51
include '../netdrv.inc'
52
 
53
include 'ar81xx.inc'
54
 
9146 hidnplayr 55
if (bsr TX_RING_SIZE)>(bsf TX_RING_SIZE)
56
  display 'TX_RING_SIZE must be a power of two'
57
  err
58
end if
59
 
60
if (bsr RX_RING_SIZE)>(bsf RX_RING_SIZE)
61
  display 'RX_RING_SIZE must be a power of two'
62
  err
63
end if
64
 
7809 hidnplayr 65
; Transmit Packet Descriptor
66
struct alx_tpd
67
        length          dw ?
68
        vlan_tag        dw ?
69
        word1           dd ?
70
        addr_l          dd ?
71
        addr_h          dd ?
72
ends
73
 
74
; Receive Return Descriptor
75
struct alx_rrd
76
        word0           dd ?    ; IP payload cksum + number of RFDs + start index of RFD-ring
77
        rss_hash        dd ?
78
        word2           dd ?    ; VLAN tag + Protocol ID + RSS Q num + RSS Hash algorithm
79
        word3           dd ?    ; Packet length + status
80
ends
81
 
82
; Receive Free Descriptor
83
struct alx_rfd
84
        addr_l          dd ?
85
        addr_h          dd ?
86
ends
87
 
88
struct  device          ETH_DEVICE
89
 
90
        io_addr         dd ?
91
        pci_bus         dd ?
92
        pci_dev         dd ?
7827 hidnplayr 93
        pci_vid         dw ?    ; Vendor ID
94
        pci_did         dw ?    ; Device ID
7809 hidnplayr 95
        irq_line        dd ?
96
        pci_rev         dd ?
97
        chip_rev        dd ?
98
        mmio_addr       dd ?
99
 
100
        max_dma_chnl    dd ?
101
 
102
        int_mask        dd ?
103
        rx_ctrl         dd ?
104
 
105
        rxq_read_idx            dd ?
106
        rxq_write_idx           dd ?
107
;        rxq_rrd_read_idx        dd ?
108
        txq_read_idx            dd ?
109
        txq_write_idx           dd ?
110
 
111
        rb 0x100 - ($ and 0xff) ; align 256
112
        tpd_ring        rb ((TX_RING_SIZE*sizeof.alx_tpd+16) and 0xfffffff0)
113
        rrd_ring        rb ((RX_RING_SIZE*sizeof.alx_rrd+16) and 0xfffffff0)
114
        rfd_ring        rb ((RX_RING_SIZE*sizeof.alx_rfd+16) and 0xfffffff0)
115
        tpd_ring_virt   rd TX_RING_SIZE
116
        rfd_ring_virt   rd RX_RING_SIZE
117
 
118
ends
119
 
120
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
121
;;                        ;;
122
;; proc START             ;;
123
;;                        ;;
124
;; (standard driver proc) ;;
125
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
126
 
127
proc START c, reason:dword, cmdline:dword
128
 
129
        cmp     [reason], DRV_ENTRY
130
        jne     .fail
131
 
132
        DEBUGF  2,"Loading driver\n"
133
        invoke  RegService, my_service, service_proc
134
        ret
135
 
136
  .fail:
137
        xor     eax, eax
138
        ret
139
 
140
endp
141
 
142
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
143
;;                        ;;
144
;; proc SERVICE_PROC      ;;
145
;;                        ;;
146
;; (standard driver proc) ;;
147
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
148
 
149
proc service_proc stdcall, ioctl:dword
150
 
151
        mov     edx, [ioctl]
152
        mov     eax, [edx + IOCTL.io_code]
153
 
154
;------------------------------------------------------
155
 
156
        cmp     eax, 0 ;SRV_GETVERSION
157
        jne     @F
158
 
159
        cmp     [edx + IOCTL.out_size], 4
160
        jb      .fail
161
        mov     eax, [edx + IOCTL.output]
162
        mov     [eax], dword API_VERSION
163
 
164
        xor     eax, eax
165
        ret
166
 
167
;------------------------------------------------------
168
  @@:
169
        cmp     eax, 1 ;SRV_HOOK
170
        jne     .fail
171
 
172
        cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
173
        jb      .fail
174
 
175
        mov     eax, [edx + IOCTL.input]
176
        cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
177
        jne     .fail                                   ; other types arent supported for this card yet
178
 
179
; check if the device is already listed
180
 
181
        mov     esi, device_list
182
        mov     ecx, [devices]
183
        test    ecx, ecx
184
        jz      .firstdevice
185
 
186
;        mov     eax, [edx + IOCTL.input]               ; get the pci bus and device numbers
187
        mov     ax , [eax+1]                            ;
188
  .nextdevice:
189
        mov     ebx, [esi]
190
        cmp     al, byte[ebx + device.pci_bus]
191
        jne     @f
192
        cmp     ah, byte[ebx + device.pci_dev]
193
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
194
       @@:
195
        add     esi, 4
196
        loop    .nextdevice
197
 
198
; This device doesnt have its own eth_device structure yet, lets create one
199
  .firstdevice:
200
        cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
201
        jae     .fail
202
 
203
        allocate_and_clear ebx, sizeof.device, .fail    ; Allocate the buffer for device structure
204
 
205
; Fill in the direct call addresses into the struct
206
 
207
        mov     [ebx + device.reset], reset
208
        mov     [ebx + device.transmit], transmit
209
        mov     [ebx + device.unload], unload
210
        mov     [ebx + device.name], my_service
211
 
212
; save the pci bus and device numbers
213
 
214
        mov     eax, [edx + IOCTL.input]
215
        movzx   ecx, byte[eax+1]
216
        mov     [ebx + device.pci_bus], ecx
217
        movzx   ecx, byte[eax+2]
218
        mov     [ebx + device.pci_dev], ecx
219
 
220
; Now, it's time to find the base mmio addres of the PCI device
221
 
222
        stdcall PCI_find_mmio, [ebx + device.pci_bus], [ebx + device.pci_dev] ; returns in eax
223
        test    eax, eax
224
        jz      .destroy
225
 
226
; Create virtual mapping of the physical memory
227
 
228
        invoke  MapIoMem, eax, 10000h, PG_SW+PG_NOCACHE
229
        mov     [ebx + device.mmio_addr], eax
230
 
231
; We've found the mmio address, find IRQ now
232
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
233
        and     eax, 0xff
234
        mov     [ebx + device.irq_line], eax
235
 
236
        DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
237
        [ebx + device.pci_dev]:1, [ebx + device.pci_bus]:1, [ebx + device.irq_line]:1, [ebx + device.mmio_addr]:8
238
 
239
; Ok, the eth_device structure is ready, let's probe the device
240
 
241
        mov     eax, [devices]                                          ; Add the device structure to our device list
242
        mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
243
        inc     [devices]                                               ;
244
 
245
        call    probe                                                   ; this function will output in eax
246
        test    eax, eax
247
        jnz     .err2
248
 
249
        DEBUGF  2,"Initialised OK\n"
250
 
251
        mov     [ebx + device.type], NET_TYPE_ETH
252
        invoke  NetRegDev
253
 
254
        cmp     eax, -1
255
        je      .destroy
256
 
257
        ret
258
 
259
; If the device was already loaded, find the device number and return it in eax
260
 
261
  .find_devicenum:
262
        DEBUGF  2,"Trying to find device number of already registered device\n"
263
        invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
264
                                                                        ; into a device number in edi
265
        mov     eax, edi                                                ; Application wants it in eax instead
266
        DEBUGF  2,"Kernel says: %u\n", eax
267
        ret
268
 
269
; If an error occured, remove all allocated data and exit (returning -1 in eax)
270
 
271
  .destroy:
272
        ; todo: reset device into virgin state
273
 
274
  .err2:
275
        dec     [devices]
276
  .err:
277
        invoke  KernelFree, ebx
278
  .fail:
279
        DEBUGF  2, "Failed to load\n"
280
        or      eax, -1
281
        ret
282
 
283
;------------------------------------------------------
284
endp
285
 
286
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
287
;;                                                                        ;;
288
;;        Actual Hardware dependent code starts here                      ;;
289
;;                                                                        ;;
290
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
291
 
292
align 4
293
unload:
294
        ; TODO: (in this particular order)
295
        ;
296
        ; - Stop the device
297
        ; - Detach int handler
298
        ; - Remove device from local list (device_list)
299
        ; - call unregister function in kernel
300
        ; - Remove all allocated structures and buffers the card used
301
 
302
        or      eax, -1
303
        ret
304
 
305
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
306
;;
307
;;  probe: enables the device (if it really is AR81XX)
308
;;
309
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
310
 
311
align 4
312
probe:
313
        DEBUGF  1,"Probing\n"
314
 
315
; Make the device a bus master
9146 hidnplayr 316
        invoke  PciRead16, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.command
7809 hidnplayr 317
        or      al, PCI_CMD_MASTER + PCI_CMD_MMIO + PCI_CMD_PIO
318
        and     ax, not(PCI_CMD_INTX_DISABLE)
9146 hidnplayr 319
        invoke  PciWrite16, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.command, eax
7809 hidnplayr 320
 
9146 hidnplayr 321
; get device ID
9750 hidnplayr 322
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.vendor_id
323
        mov     dword[ebx + device.pci_vid], eax
7827 hidnplayr 324
 
325
        mov     esi, chiplist
326
  .loop:
9750 hidnplayr 327
        cmp     dword[esi], eax
7827 hidnplayr 328
        je      .got_it
329
        add     esi, 8
9750 hidnplayr 330
        cmp     dword[esi], 0
331
        jne     .loop
332
        DEBUGF  2, "Unknown chip: 0x%x, continuing anyway\n", eax
333
        mov     [ebx + device.name], my_service
7827 hidnplayr 334
        jmp     .done
335
  .got_it:
336
        mov     eax, dword[esi+4]
337
        mov     [ebx + device.name], eax
338
        DEBUGF  1, "Chip type = %s\n", eax
339
  .done:
340
 
9146 hidnplayr 341
; get revision ID
342
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.revision_id
7809 hidnplayr 343
        and     eax, 0xff
9146 hidnplayr 344
        DEBUGF  1,"PCI Revision: %u\n", eax
7809 hidnplayr 345
        mov     [ebx + device.pci_rev], eax
346
        shr     al, ALX_PCI_REVID_SHIFT
347
        mov     [ebx + device.chip_rev], eax
9146 hidnplayr 348
        DEBUGF  1,"ALX Revision: %u\n", eax
7809 hidnplayr 349
 
9146 hidnplayr 350
        stdcall alx_reset_pcie
7809 hidnplayr 351
 
352
        mov     ecx, (ALX_PMCTRL_L0S_EN or ALX_PMCTRL_L1_EN or ALX_PMCTRL_ASPM_FCEN)
9146 hidnplayr 353
        stdcall alx_enable_aspm
7809 hidnplayr 354
 
9146 hidnplayr 355
        stdcall alx_reset_phy
7809 hidnplayr 356
 
9146 hidnplayr 357
        stdcall alx_reset_mac
7809 hidnplayr 358
 
9146 hidnplayr 359
; Setup link to put it in a known good starting state
360
        stdcall alx_write_phy_reg, ALX_MII_DBG_ADDR, 0
7809 hidnplayr 361
 
9146 hidnplayr 362
        mov     esi, [ebx + device.mmio_addr]
363
        mov     eax, dword[esi + ALX_DRV]
364
 
365
        stdcall alx_write_phy_reg, MII_ADVERTISE, ADVERTISE_CSMA or ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or ADVERTISE_PAUSE_CAP
366
 
367
        xor     eax, eax
368
        test    [ebx + device.pci_did], 1       ;;; FIXME: is gigabit device?
369
        jz      @f
370
        mov     eax, ADVERTISE_1000XFULL
371
  @@:
372
        stdcall alx_write_phy_reg, MII_CTRL1000, eax
373
 
374
        stdcall alx_write_phy_reg, MII_BMCR, BMCR_RESET or BMCR_ANENABLE or BMCR_ANRESTART
375
 
376
        stdcall alx_get_perm_macaddr
377
 
7809 hidnplayr 378
align 4
379
reset:
380
 
381
        DEBUGF  1,"Resetting\n"
382
 
383
; alx init_sw
384
 
9146 hidnplayr 385
        stdcall alx_identify_hw
7809 hidnplayr 386
 
387
        mov     [ebx + device.int_mask], ALX_ISR_MISC
388
        mov     [ebx + device.rx_ctrl], ALX_MAC_CTRL_WOLSPED_SWEN or ALX_MAC_CTRL_MHASH_ALG_HI5B or ALX_MAC_CTRL_BRD_EN or ALX_MAC_CTRL_PCRCE or ALX_MAC_CTRL_CRCE or ALX_MAC_CTRL_RXFC_EN or ALX_MAC_CTRL_TXFC_EN or (7 shl ALX_MAC_CTRL_PRMBLEN_SHIFT)
389
 
9146 hidnplayr 390
        stdcall alx_alloc_rings
7809 hidnplayr 391
 
9146 hidnplayr 392
        stdcall alx_configure
7809 hidnplayr 393
 
9146 hidnplayr 394
        stdcall alx_request_irq
7809 hidnplayr 395
 
396
; attach interrupt handler
397
 
398
        mov     eax, [ebx + device.irq_line]
399
        DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
400
        invoke  AttachIntHandler, eax, int_handler, ebx
401
        test    eax, eax
402
        jnz     @f
403
        DEBUGF  2,"Could not attach int handler!\n"
404
        or      eax, -1
405
        ret
406
  @@:
407
 
408
; Clear old interrupts
409
        mov     edi, [ebx + device.mmio_addr]
410
        mov     eax, not ALX_ISR_DIS
411
        mov     [edi + ALX_ISR], eax
412
 
9146 hidnplayr 413
        stdcall alx_irq_enable
7809 hidnplayr 414
 
9146 hidnplayr 415
; Set the MTU, kernel will be able to send now
7809 hidnplayr 416
        mov     [ebx + device.mtu], 1514
417
 
9146 hidnplayr 418
        stdcall alx_check_link
7809 hidnplayr 419
 
420
        DEBUGF  1,"Reset ok\n"
421
        xor     eax, eax
422
        ret
423
 
424
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
425
;;                                         ;;
426
;; Transmit                                ;;
427
;;                                         ;;
428
;; In: pointer to device structure in ebx  ;;
9146 hidnplayr 429
;; Out: eax = 0 on success                 ;;
7809 hidnplayr 430
;;                                         ;;
431
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9146 hidnplayr 432
align 16
7809 hidnplayr 433
proc transmit stdcall bufferptr
434
 
9146 hidnplayr 435
        spin_lock_irqsave
7809 hidnplayr 436
 
437
        mov     esi, [bufferptr]
438
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
439
        lea     eax, [esi + NET_BUFF.data]
440
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
441
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
442
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
443
        [eax+13]:2,[eax+12]:2
444
 
445
        cmp     [esi + NET_BUFF.length], 1514
9146 hidnplayr 446
        ja      .error
7809 hidnplayr 447
        cmp     [esi + NET_BUFF.length], 60
9146 hidnplayr 448
        jb      .error
7809 hidnplayr 449
 
450
; Program the descriptor
451
        mov     edi, [ebx + device.txq_write_idx]
452
        DEBUGF  1, "Using TPD: %u\n", edi
9146 hidnplayr 453
        cmp     dword[ebx + device.tpd_ring_virt + edi*4], 0
454
        jne     .overrun
7809 hidnplayr 455
        mov     dword[ebx + device.tpd_ring_virt + edi*4], esi
456
        shl     edi, 4
457
        lea     edi, [ebx + device.tpd_ring + edi]
458
        mov     eax, esi
459
        add     eax, [esi + NET_BUFF.offset]
460
        invoke  GetPhysAddr
461
        mov     [edi + alx_tpd.addr_l], eax
462
        mov     [edi + alx_tpd.addr_h], 0
463
 
464
        mov     ecx, [esi + NET_BUFF.length]
465
        mov     [edi + alx_tpd.length], cx
466
 
467
        mov     [edi + alx_tpd.word1], 1 shl TPD_EOP_SHIFT
468
 
469
; Update Producer Index
470
        mov     eax, [ebx + device.txq_write_idx]
471
        inc     eax
472
        and     eax, TX_RING_SIZE - 1
473
        mov     [ebx + device.txq_write_idx], eax
474
 
475
        mov     edi, [ebx + device.mmio_addr]
476
        mov     word[edi + ALX_TPD_PRI0_PIDX], ax
477
 
478
; Update stats
479
        inc     [ebx + device.packets_tx]
480
        mov     eax, [esi + NET_BUFF.length]
481
        add     dword[ebx + device.bytes_tx], eax
482
        adc     dword[ebx + device.bytes_tx + 4], 0
483
 
9147 hidnplayr 484
        spin_unlock_irqrestore
7809 hidnplayr 485
        xor     eax, eax
486
        ret
487
 
9146 hidnplayr 488
  .error:
489
        DEBUGF  2, "TX packet error\n"
490
        inc     [ebx + device.packets_tx_err]
7809 hidnplayr 491
        invoke  NetFree, [bufferptr]
9146 hidnplayr 492
 
493
        spin_unlock_irqrestore
7809 hidnplayr 494
        or      eax, -1
495
        ret
496
 
9146 hidnplayr 497
  .overrun:
498
        DEBUGF  2, "TX overrun\n"
499
        inc     [ebx + device.packets_tx_ovr]
500
        invoke  NetFree, [bufferptr]
7809 hidnplayr 501
 
9146 hidnplayr 502
        spin_unlock_irqrestore
503
        or      eax, -1
504
        ret
7809 hidnplayr 505
 
9146 hidnplayr 506
endp
7809 hidnplayr 507
 
508
;;;;;;;;;;;;;;;;;;;;;;;
509
;;                   ;;
510
;; Interrupt handler ;;
511
;;                   ;;
512
;;;;;;;;;;;;;;;;;;;;;;;
9146 hidnplayr 513
align 16
7809 hidnplayr 514
int_handler:
515
 
516
        push    ebx esi edi
517
 
9146 hidnplayr 518
        mov     ebx, [esp+4*4]
519
        DEBUGF  1,"INT for 0x%x\n", ebx
7809 hidnplayr 520
 
9146 hidnplayr 521
; TODO? if we are paranoid, we can check that the value from ebx is present in the current device_list
7809 hidnplayr 522
 
523
        mov     edi, [ebx + device.mmio_addr]
524
        mov     eax, [edi + ALX_ISR]
525
        test    eax, eax
9146 hidnplayr 526
        jz      .nothing
7809 hidnplayr 527
 
528
        or      eax, ALX_ISR_DIS
529
        mov     [edi + ALX_ISR], eax    ; ACK interrupt
9146 hidnplayr 530
        DEBUGF  1,"Status: %x\n", eax
7809 hidnplayr 531
 
532
        test    eax, ALX_ISR_TX_Q0
533
        jz      .no_tx
534
        DEBUGF  1,"TX interrupt\n"
535
        pusha
9146 hidnplayr 536
        stdcall alx_clean_tx_irq
7809 hidnplayr 537
        popa
538
  .no_tx:
539
 
540
        test    eax, ALX_ISR_RX_Q0
541
        jz      .no_rx
542
        DEBUGF  1,"RX interrupt\n"
543
        pusha
9146 hidnplayr 544
        stdcall alx_clean_rx_irq
7809 hidnplayr 545
        popa
546
 
547
  .no_rx:
548
        test    eax, ALX_ISR_PHY
549
        jz      .no_phy
550
        DEBUGF  1,"PHY interrupt\n"
551
        pusha
552
; TODO: queue link check and disable this interrupt cause meanwhile??
9146 hidnplayr 553
        stdcall alx_check_link
7809 hidnplayr 554
        popa
555
 
556
  .no_phy:
557
        mov     dword[edi + ALX_ISR], 0
558
        pop     edi esi ebx
9146 hidnplayr 559
        xor     eax, eax
560
        inc     eax
561
 
7809 hidnplayr 562
        ret
563
 
9146 hidnplayr 564
  .nothing:
565
        pop     edi esi ebx
566
        xor     eax, eax
7809 hidnplayr 567
 
9146 hidnplayr 568
        ret
7809 hidnplayr 569
 
9146 hidnplayr 570
proc alx_identify_hw stdcall
571
 
572
        cmp     [ebx + device.pci_did], ALX_DEV_ID_AR8131
573
        je      .alc
574
 
7809 hidnplayr 575
        cmp     [ebx + device.chip_rev], ALX_REV_C0
576
        ja      .einval
577
 
578
        mov     [ebx + device.max_dma_chnl], 2
579
        cmp     [ebx + device.chip_rev], ALX_REV_B0
9146 hidnplayr 580
        jb      @f
7809 hidnplayr 581
        mov     [ebx + device.max_dma_chnl], 4
582
  @@:
583
        xor     eax, eax
584
        ret
585
 
586
  .einval:
7827 hidnplayr 587
        DEBUGF  1, "Invalid revision 0x%x\n", [ebx + device.chip_rev]
588
 
7809 hidnplayr 589
        xor     eax, eax
590
        dec     eax
591
        ret
592
 
9146 hidnplayr 593
  .alc:
594
        mov     [ebx + device.max_dma_chnl], 2
595
        xor     eax, eax
596
        ret
7809 hidnplayr 597
 
9146 hidnplayr 598
endp
7809 hidnplayr 599
 
9146 hidnplayr 600
proc udelay stdcall microseconds
7809 hidnplayr 601
 
9146 hidnplayr 602
; FIXME
603
 
604
        push    esi ecx edx
605
        xor     esi, esi
606
        inc     esi
607
        invoke  Sleep
608
        pop     edx ecx esi
609
 
610
        ret
611
 
612
endp
613
 
614
proc alx_reset_pcie stdcall
615
 
616
        DEBUGF  1,"alx_reset_pcie\n"
617
 
618
; Make the device a bus master
619
        invoke  PciRead16, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
620
        or      al, PCI_CMD_MASTER or PCI_CMD_MMIO or PCI_CMD_PIO
621
        and     ax, not(PCI_CMD_INTX_DISABLE)
622
        invoke  PciWrite16, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
623
 
624
; Clear any powersaving setting
625
        invoke  PciWrite16, [ebx + device.pci_bus], [ebx + device.pci_dev], 0x44, 0x0000        ;; FIXME
626
 
627
; Mask some pcie error bits
628
        mov     esi, [ebx + device.mmio_addr]
629
        mov     eax, [esi + ALX_UE_SVRT]
630
        and     eax, not(ALX_UE_SVRT_DLPROTERR or ALX_UE_SVRT_FCPROTERR)
631
        mov     [esi + ALX_UE_SVRT], eax
632
 
633
; pclk
634
        mov     eax, [esi + ALX_MASTER]
635
        or      eax, ALX_MASTER_WAKEN_25M
636
        and     eax, not (ALX_MASTER_PCLKSEL_SRDS)
637
        cmp     [ebx + device.chip_rev], ALX_REV_A1
638
        ja      @f
639
        test    [ebx + device.pci_rev], ALX_PCI_REVID_WITH_CR
640
        jz      @f
641
        or      eax, ALX_MASTER_PCLKSEL_SRDS
642
  @@:
643
        mov     [esi + ALX_MASTER], eax
644
 
645
        xor     eax, eax
646
        ret
647
 
648
endp
649
 
650
proc alx_clean_tx_irq stdcall
651
 
7809 hidnplayr 652
        mov     eax, [ebx + device.txq_read_idx]
653
        movzx   ecx, word[edi + ALX_TPD_PRI0_CIDX]
654
 
655
  .loop:
656
        cmp     eax, ecx
657
        je      .done
658
 
659
        DEBUGF  1,"Cleaning TX desc %u buffer 0x%x\n", eax, [ebx + device.tpd_ring_virt + eax*4]
660
        push    eax ecx
661
        invoke  NetFree, [ebx + device.tpd_ring_virt + eax*4]
662
        pop     ecx eax
9146 hidnplayr 663
        mov     [ebx + device.tpd_ring_virt + eax*4], 0
7809 hidnplayr 664
 
665
        inc     eax
666
        and     eax, TX_RING_SIZE-1
667
        jmp     .loop
668
  .done:
669
        mov     [ebx + device.txq_read_idx], eax
670
 
671
        ret
672
 
9146 hidnplayr 673
endp
7809 hidnplayr 674
 
9146 hidnplayr 675
proc alx_clean_rx_irq stdcall
7809 hidnplayr 676
 
677
        mov     ecx, [ebx + device.rxq_read_idx]
678
  .loop:
679
        shl     ecx, 2
680
        lea     esi, [ebx + device.rrd_ring + ecx*4]
681
        test    [esi + alx_rrd.word3], 1 shl RRD_UPDATED_SHIFT
682
        jz      .done
683
        and     [esi + alx_rrd.word3], not(1 shl RRD_UPDATED_SHIFT)
684
        DEBUGF  1,"RRD=%u updated\n", [ebx + device.rxq_read_idx]
685
 
686
        mov     eax, [esi + alx_rrd.word0]
687
        shr     eax, RRD_SI_SHIFT
688
        and     eax, RRD_SI_MASK
689
        cmp     eax, [ebx + device.rxq_read_idx]
690
;        jne     .error
691
        DEBUGF  1,"RFD=%u\n", eax
692
 
693
        mov     eax, [esi + alx_rrd.word0]
694
        shr     eax, RRD_NOR_SHIFT
695
        and     eax, RRD_NOR_MASK
696
        cmp     eax, 1
697
;        jne     .error
698
 
699
        mov     eax, [esi + alx_rrd.word3]
700
;        shr     eax, RRD_PKTLEN_SHIFT
701
        and     eax, RRD_PKTLEN_MASK
702
        sub     eax, 4                          ;;;;;
703
        mov     edx, [ebx + device.rfd_ring_virt + ecx]
704
        DEBUGF  1,"Received %u bytes in buffer 0x%x\n", eax, edx
705
 
706
        mov     [edx + NET_BUFF.length], eax
707
        mov     [edx + NET_BUFF.device], ebx
708
        mov     [edx + NET_BUFF.offset], NET_BUFF.data
709
 
710
; Update stats
711
        add     dword[ebx + device.bytes_rx], eax
712
        adc     dword[ebx + device.bytes_rx + 4], 0
713
        inc     [ebx + device.packets_rx]
714
 
715
; Allocate new descriptor
716
        push    esi ecx edx
717
        invoke  NetAlloc, RX_BUFFER_SIZE+NET_BUFF.data
718
        pop     edx ecx esi
719
        test    eax, eax
9146 hidnplayr 720
        jz      .rx_overrun
7809 hidnplayr 721
        mov     [ebx + device.rfd_ring_virt + ecx], eax
722
        add     eax, NET_BUFF.data
723
        invoke  GetPhysAddr
724
        mov     dword[ebx + device.rfd_ring + ecx*2], eax
725
 
726
        push    ecx ebx
727
        push    .retaddr
728
        push    edx
729
        jmp     [EthInput]
730
  .retaddr:
731
        pop     ebx ecx
732
 
733
        shr     ecx, 2
734
        inc     ecx
735
        and     ecx, RX_RING_SIZE-1
736
        jmp     .loop
737
 
9146 hidnplayr 738
  .rx_overrun:
739
        DEBUGF  2,"RX FIFO overrun\n"
740
        inc     [ebx + device.packets_rx_ovr]
741
        shr     ecx, 2
742
        inc     ecx
743
        and     ecx, RX_RING_SIZE-1
744
        jmp     .loop
745
 
7809 hidnplayr 746
  .done:
747
        shr     ecx, 2
748
        mov     [ebx + device.rxq_read_idx], ecx
749
 
750
; Update producer index
751
        mov     esi, [ebx + device.mmio_addr]
752
        mov     [esi + ALX_RFD_PIDX], cx
753
 
754
        ret
755
 
9146 hidnplayr 756
endp
7809 hidnplayr 757
 
9146 hidnplayr 758
; IN: ecx = additional bit flags (ALX_PMCTRL_L0S_EN, ALX_PMCTRL_L1_EN, ALX_PMCTRL_ASPM_FCEN)
759
proc alx_enable_aspm stdcall
7809 hidnplayr 760
 
761
        DEBUGF  1,"alx_enable_aspm (0x%x)\n", ecx
762
 
763
        mov     esi, [ebx + device.mmio_addr]
764
 
9146 hidnplayr 765
        cmp     [ebx + device.pci_did], ALX_DEV_ID_AR8131
766
        je      .alc_l1c
7809 hidnplayr 767
 
768
        cmp     [ebx + device.chip_rev], ALX_REV_A1
769
        ja      @f
9146 hidnplayr 770
        test    [ebx + device.pci_rev], ALX_PCI_REVID_WITH_CR
7809 hidnplayr 771
        jz      @f
9146 hidnplayr 772
        or      ecx, ALX_PMCTRL_L1_SRDS_EN or ALX_PMCTRL_L1_SRDSPLL_EN
7809 hidnplayr 773
  @@:
774
 
9146 hidnplayr 775
        mov     eax, dword[esi + ALX_PMCTRL]
776
        and     eax, not((ALX_PMCTRL_LCKDET_TIMER_MASK shl ALX_PMCTRL_LCKDET_TIMER_SHIFT) or \
777
                         (ALX_PMCTRL_L1REQ_TO_MASK shl ALX_PMCTRL_L1REQ_TO_SHIFT) or \
778
                         (ALX_PMCTRL_L1_TIMER_MASK shl ALX_PMCTRL_L1_TIMER_SHIFT) or \
779
                         ALX_PMCTRL_L1_SRDS_EN or \
780
                         ALX_PMCTRL_L1_SRDSPLL_EN or \
781
                         ALX_PMCTRL_L1_BUFSRX_EN or \
782
                         ALX_PMCTRL_SADLY_EN or \
783
                         ALX_PMCTRL_HOTRST_WTEN or \
784
                         ALX_PMCTRL_L0S_EN or \
785
                         ALX_PMCTRL_L1_EN or \
786
                         ALX_PMCTRL_ASPM_FCEN or \
787
                         ALX_PMCTRL_TXL1_AFTER_L0S or \
788
                         ALX_PMCTRL_RXL1_AFTER_L0S)
789
        or      eax, (ALX_PMCTRL_LCKDET_TIMER_DEF shl ALX_PMCTRL_LCKDET_TIMER_SHIFT) or \
790
                     (ALX_PMCTRL_RCVR_WT_1US or ALX_PMCTRL_L1_CLKSW_EN or ALX_PMCTRL_L1_SRDSRX_PWD) or \
791
                     (ALX_PMCTRL_L1REG_TO_DEF shl ALX_PMCTRL_L1REQ_TO_SHIFT) or \
792
                     (ALX_PMCTRL_L1_TIMER_16US shl ALX_PMCTRL_L1_TIMER_SHIFT)
7809 hidnplayr 793
        or      eax, ecx
794
        mov     dword[esi + ALX_PMCTRL], eax
795
 
796
        ret
797
 
9146 hidnplayr 798
  .alc_l1c:
7809 hidnplayr 799
 
9146 hidnplayr 800
        DEBUGF  1, "aspm for L1C\n"
801
 
802
        mov     esi, [ebx + device.mmio_addr]
803
        mov     eax, dword[esi + ALX_PMCTRL]
804
 
805
        and     eax, not(ALX_PMCTRL_L0S_EN or ALX_PMCTRL_L1_EN or ALX_PMCTRL_ASPM_FCEN)
806
        or      eax, (ALX_PMCTRL_LCKDET_TIMER_DEF shl ALX_PMCTRL_LCKDET_TIMER_SHIFT) ;\
807
                ;     or (0 shl ALX_PMCTRL_L1_TIMER_SHIFT)
808
 
809
        or      eax, ecx
810
 
811
;;; FIXME if(linkon)
812
 
813
        or      eax, (ALX_PMCTRL_L1_SRDS_EN or ALX_PMCTRL_L1_SRDSPLL_EN or ALX_PMCTRL_L1_BUFSRX_EN)
814
        and     eax, not(ALX_PMCTRL_L1_SRDSRX_PWD or ALX_PMCTRL_L1_CLKSW_EN or ALX_PMCTRL_L0S_EN or ALX_PMCTRL_L1_EN)
815
 
816
;;
817
 
818
        mov     dword[esi + ALX_PMCTRL], eax
819
 
820
        ret
821
 
822
endp
823
 
824
proc alx_reset_mac stdcall
825
 
7809 hidnplayr 826
        DEBUGF  1, "reset mac\n"
827
 
828
; disable all interrupts, RXQ/TXQ
829
        mov     esi, [ebx + device.mmio_addr]
830
        mov     dword[esi + ALX_MSIX_MASK], 0xffffffff
831
        mov     dword[esi + ALX_IMR], 0x0
832
        mov     dword[esi + ALX_ISR], ALX_ISR_DIS
833
 
9146 hidnplayr 834
        stdcall alx_stop_mac
7809 hidnplayr 835
 
836
; mac reset workaround
837
        mov     dword[esi + ALX_RFD_PIDX], 1
838
 
9146 hidnplayr 839
; disable l0s/l1 before MAC reset on some chips
7809 hidnplayr 840
        cmp     [ebx + device.chip_rev], ALX_REV_A1
841
        ja      @f
9146 hidnplayr 842
        test    [ebx + device.pci_rev], ALX_PCI_REVID_WITH_CR
7809 hidnplayr 843
        jz      @f
844
        mov     eax, [esi + ALX_PMCTRL]
845
        mov     edx, eax
9146 hidnplayr 846
        test    eax, ALX_PMCTRL_L1_EN or ALX_PMCTRL_L0S_EN
847
        jz      @f
7809 hidnplayr 848
        and     eax, not(ALX_PMCTRL_L1_EN or ALX_PMCTRL_L0S_EN)
849
        mov     [esi + ALX_PMCTRL], eax
850
  @@:
851
 
9146 hidnplayr 852
; reset whole MAC safely
7809 hidnplayr 853
        mov     eax, [esi + ALX_MASTER]
9146 hidnplayr 854
        or      eax, ALX_MASTER_DMA_MAC_RST or ALX_MASTER_OOB_DIS
7809 hidnplayr 855
        mov     [esi + ALX_MASTER], eax
856
 
857
; make sure it's real idle
9146 hidnplayr 858
        stdcall udelay, 10
7809 hidnplayr 859
 
9146 hidnplayr 860
        mov     ecx, ALX_DMA_MAC_RST_TO ; timeout
7809 hidnplayr 861
  .loop1:
862
        mov     eax, dword[esi + ALX_RFD_PIDX]
863
        test    eax, eax
864
        jz      @f
9146 hidnplayr 865
 
866
        stdcall udelay, 10
867
 
7809 hidnplayr 868
        dec     ecx
869
        jnz     .loop1
870
        jmp     .error
871
  @@:
9146 hidnplayr 872
 
7809 hidnplayr 873
  .loop2:
874
        mov     eax, dword[esi + ALX_MASTER]
875
        test    eax, ALX_MASTER_DMA_MAC_RST
876
        jz      @f
9146 hidnplayr 877
 
878
        stdcall udelay, 10
879
 
7809 hidnplayr 880
        dec     ecx
881
        jnz     .loop2
882
        jmp     .error
883
  @@:
884
 
885
; restore l0s/l1
886
        cmp     [ebx + device.chip_rev], ALX_REV_A1
887
        ja      @f
9146 hidnplayr 888
        test    [ebx + device.pci_rev], ALX_PCI_REVID_WITH_CR
7809 hidnplayr 889
        jz      @f
890
        or      eax, ALX_MASTER_PCLKSEL_SRDS
891
        mov     [esi + ALX_MASTER], eax
892
        mov     [esi + ALX_PMCTRL], edx
893
  @@:
894
 
9146 hidnplayr 895
        stdcall alx_reset_osc
7809 hidnplayr 896
 
897
; clear Internal OSC settings, switching OSC by hw itself, disable isolate for rev A devices
898
 
899
        mov     eax, [esi + ALX_MISC3]
900
        and     eax, not (ALX_MISC3_25M_BY_SW)
901
        or      eax, ALX_MISC3_25M_NOTO_INTNL
902
        mov     [esi + ALX_MISC3], eax
903
 
904
        mov     eax, [esi + ALX_MISC]
905
        and     eax, not (ALX_MISC_INTNLOSC_OPEN)
906
 
907
        cmp     [ebx + device.chip_rev], ALX_REV_A1
908
        ja      @f
909
        and     eax, not ALX_MISC_ISO_EN
910
  @@:
911
        mov     [esi + ALX_MISC], eax
912
 
9146 hidnplayr 913
        stdcall udelay, 20
7809 hidnplayr 914
 
915
; driver control speed/duplex, hash-alg
916
        mov     eax, [ebx + device.rx_ctrl]
917
        mov     [esi + ALX_MAC_CTRL], eax
918
 
9146 hidnplayr 919
; clk sw
7809 hidnplayr 920
        mov     eax, dword[esi + ALX_SERDES]
921
        or      eax, ALX_SERDES_MACCLK_SLWDWN or ALX_SERDES_PHYCLK_SLWDWN
922
        mov     dword[esi + ALX_SERDES], eax
923
 
924
        DEBUGF  1, "OK\n"
925
        xor     eax, eax
926
        ret
927
 
928
  .error:
929
        DEBUGF  1, "error\n"
930
        xor     eax, eax
931
        dec     eax
932
        ret
933
 
9146 hidnplayr 934
endp
7809 hidnplayr 935
 
9146 hidnplayr 936
proc alx_reset_phy stdcall
7809 hidnplayr 937
 
938
        DEBUGF  1, "Reset phy\n"
939
 
940
        mov     esi, [ebx + device.mmio_addr]
941
 
9146 hidnplayr 942
        mov     eax, dword [esi + ALX_PHY_CTRL]
943
        DEBUGF 1, "read ALX_PHY_CTRL = %x\n", eax
944
        and     eax, not (ALX_PHY_CTRL_DSPRST_OUT or ALX_PHY_CTRL_IDDQ or ALX_PHY_CTRL_GATE_25M or ALX_PHY_CTRL_POWER_DOWN or ALX_PHY_CTRL_CLS)
945
        or      eax, ALX_PHY_CTRL_RST_ANALOG
946
        or      eax, ALX_PHY_CTRL_HIB_PULSE or ALX_PHY_CTRL_HIB_EN ; assume pws is enabled
7809 hidnplayr 947
 
9146 hidnplayr 948
        DEBUGF 1, "write ALX_PHY_CTRL = %x\n", eax
949
        mov     [esi + ALX_PHY_CTRL], eax
950
 
951
        stdcall udelay, 5
952
 
953
        or      eax, ALX_PHY_CTRL_DSPRST_OUT
954
        mov     [esi + ALX_PHY_CTRL], eax
955
 
956
        stdcall udelay, 10
957
 
958
        or      eax, ALX_PHY_CTRL_DSPRST_OUT
959
        DEBUGF 1, "write ALX_PHY_CTRL = %x\n", eax
960
        mov     dword [esi + ALX_PHY_CTRL], eax
961
 
962
        stdcall udelay, 800
963
 
964
; PHY power saving & hibernate
965
        stdcall alx_write_phy_dbg, ALX_MIIDBG_LEGCYPS, ALX_LEGCYPS_DEF
966
        stdcall alx_write_phy_dbg, ALX_MIIDBG_SYSMODCTRL, ALX_SYSMODCTRL_IECHOADJ_DEF
967
        stdcall alx_write_phy_ext, ALX_MIIEXT_PCS, ALX_MIIEXT_VDRVBIAS, ALX_VDRVBIAS_DEF
968
 
969
; EEE advertisement
970
        mov     eax, [esi + ALX_LPI_CTRL]
971
        and     eax, not (ALX_LPI_CTRL_EN)
972
        mov     [esi + ALX_LPI_CTRL], eax
973
        stdcall alx_write_phy_ext, ALX_MIIEXT_ANEG, ALX_MIIEXT_LOCAL_EEEADV, 0
974
 
975
; PHY power saving
976
        stdcall alx_write_phy_dbg, ALX_MIIDBG_TST10BTCFG, ALX_TST10BTCFG_DEF
977
        stdcall alx_write_phy_dbg, ALX_MIIDBG_SRDSYSMOD, ALX_SRDSYSMOD_DEF
978
        stdcall alx_write_phy_dbg, ALX_MIIDBG_TST100BTCFG, ALX_TST100BTCFG_DEF
979
        stdcall alx_write_phy_dbg, ALX_MIIDBG_ANACTRL, ALX_ANACTRL_DEF
980
        stdcall alx_read_phy_dbg, ALX_MIIDBG_GREENCFG2
981
        and     eax, not ALX_GREENCFG2_GATE_DFSE_EN
982
        stdcall alx_write_phy_dbg, ALX_MIIDBG_GREENCFG2, eax
983
; rtl8139c, 120m issue */
984
        stdcall alx_write_phy_ext, ALX_MIIEXT_ANEG, ALX_MIIEXT_NLP78, ALX_MIIEXT_NLP78_120M_DEF
985
        stdcall alx_write_phy_ext, ALX_MIIEXT_ANEG, ALX_MIIEXT_S3DIG10, ALX_MIIEXT_S3DIG10_DEF
986
 
987
; TODO: link patch ?
988
 
989
; set PHY interrupt mask
990
        stdcall alx_read_phy_reg, ALX_MII_IER
7809 hidnplayr 991
        or      eax, ALX_IER_LINK_UP or ALX_IER_LINK_DOWN
9146 hidnplayr 992
        stdcall alx_write_phy_reg, ALX_MII_IER , eax
7809 hidnplayr 993
 
994
        DEBUGF  1, "OK\n"
995
        xor     eax, eax
996
        ret
997
 
998
  .error:
999
        DEBUGF  1, "error\n"
1000
        xor     eax, eax
1001
        dec     eax
1002
        ret
1003
 
9146 hidnplayr 1004
endp
7809 hidnplayr 1005
 
9146 hidnplayr 1006
proc alx_set_macaddr stdcall
7809 hidnplayr 1007
 
9146 hidnplayr 1008
        mov     esi, [ebx + device.mmio_addr]
7809 hidnplayr 1009
 
9146 hidnplayr 1010
        mov     eax, dword[ebx + device.mac+2]
1011
        bswap   eax
1012
        mov     [esi + ALX_STAD0], eax
1013
        mov     ax, word[ebx + device.mac]
1014
        xchg    al, ah
1015
        mov     [esi + ALX_STAD1], ax
7809 hidnplayr 1016
 
9146 hidnplayr 1017
 
1018
        ret
1019
endp
1020
 
1021
proc alx_enable_osc stdcall
1022
 
7809 hidnplayr 1023
        mov     esi, [ebx + device.mmio_addr]
1024
 
9146 hidnplayr 1025
; rising edge
1026
        mov     eax, dword[esi + ALX_MISC]
1027
        and     eax, not ALX_MISC_INTNLOSC_OPEN
1028
        mov     dword[esi + ALX_MISC], eax
1029
        or      eax, ALX_MISC_INTNLOSC_OPEN
1030
        mov     dword[esi + ALX_MISC], eax
1031
 
1032
        ret
1033
 
1034
endp
1035
 
1036
proc alx_reset_osc stdcall
1037
 
1038
        mov     esi, [ebx + device.mmio_addr]
1039
 
7809 hidnplayr 1040
; clear Internal OSC settings, switching OSC by hw itself
1041
        mov     eax, dword[esi + ALX_MISC3]
1042
        and     eax, not ALX_MISC3_25M_BY_SW
1043
        or      eax, ALX_MISC3_25M_NOTO_INTNL
1044
        mov     dword[esi + ALX_MISC3], eax
1045
 
1046
; clk from chipset may be unstable 1s after de-assert of
1047
; PERST, driver need re-calibrate before enter Sleep for WoL
1048
        mov     eax, dword[esi + ALX_MISC]
1049
        cmp     [ebx + device.chip_rev], ALX_REV_B0
9146 hidnplayr 1050
        jb      .rev_A
7809 hidnplayr 1051
 
1052
; restore over current protection def-val, this val could be reset by MAC-RST
1053
        and     eax, not (ALX_MISC_PSW_OCP_MASK shl ALX_MISC_PSW_OCP_SHIFT)
1054
        or      eax, ALX_MISC_PSW_OCP_DEF shl ALX_MISC_PSW_OCP_SHIFT
1055
; a 0->1 change will update the internal val of osc
1056
        and     eax, not ALX_MISC_INTNLOSC_OPEN
1057
        mov     dword[esi + ALX_MISC], eax
1058
        or      eax, ALX_MISC_INTNLOSC_OPEN
1059
        mov     dword[esi + ALX_MISC], eax
1060
 
1061
; hw will automatically dis OSC after cab
1062
        mov     eax, dword[esi + ALX_MSIC2]
1063
        and     eax, not ALX_MSIC2_CALB_START
1064
        mov     dword[esi + ALX_MSIC2], eax
1065
        or      eax, ALX_MSIC2_CALB_START
1066
        mov     dword[esi + ALX_MSIC2], eax
1067
 
9146 hidnplayr 1068
        stdcall udelay, 20
7809 hidnplayr 1069
 
1070
        ret
1071
 
9146 hidnplayr 1072
  .rev_A:
7809 hidnplayr 1073
 
1074
;  disable isolate for rev A devices
9146 hidnplayr 1075
        and     eax, not (ALX_MISC_ISO_EN)
7809 hidnplayr 1076
        or      eax, ALX_MISC_INTNLOSC_OPEN
1077
        mov     dword[esi + ALX_MISC], eax
1078
        and     eax, not ALX_MISC_INTNLOSC_OPEN
1079
        mov     dword[esi + ALX_MISC], eax
1080
 
9146 hidnplayr 1081
        stdcall udelay, 20
7809 hidnplayr 1082
 
1083
        ret
1084
 
9146 hidnplayr 1085
endp
7809 hidnplayr 1086
 
9146 hidnplayr 1087
proc alx_read_macaddr stdcall
1088
 
7809 hidnplayr 1089
        mov     esi, [ebx + device.mmio_addr]
1090
        mov     eax, dword[esi + ALX_STAD0]
1091
        bswap   eax
1092
        mov     dword[ebx + device.mac + 2], eax
1093
        mov     ax, word[esi + ALX_STAD1]
1094
        xchg    al, ah
1095
        mov     word[ebx + device.mac], ax
1096
 
1097
        DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
1098
        [ebx + device.mac+0]:2, [ebx + device.mac+1]:2, [ebx + device.mac+2]:2, [ebx + device.mac+3]:2, [ebx + device.mac+4]:2, [ebx + device.mac+5]:2
1099
 
1100
; check if it is a valid MAC
1101
        cmp     dword[ebx + device.mac], 0x0
1102
        jne     @f
1103
        cmp     word[ebx + device.mac + 4], 0x0
1104
        je      .invalid
1105
  @@:
1106
        cmp     dword[ebx + device.mac], 0xffffffff
1107
        jne     @f
1108
        cmp     word[ebx + device.mac + 4], 0xffff
1109
        je      .invalid
1110
  @@:
9146 hidnplayr 1111
        test    byte[ebx + device.mac + 5], 0x01        ; Multicast
1112
        jnz     .invalid
1113
  @@:
7809 hidnplayr 1114
        xor     eax, eax
1115
        ret
1116
 
1117
  .invalid:
7827 hidnplayr 1118
        DEBUGF  1, "Invalid MAC!\n"
7809 hidnplayr 1119
        xor     eax, eax
1120
        inc     eax
1121
        ret
1122
 
9146 hidnplayr 1123
endp
7809 hidnplayr 1124
 
9146 hidnplayr 1125
proc alx_get_perm_macaddr stdcall
7809 hidnplayr 1126
 
1127
; try to get it from register first
9146 hidnplayr 1128
        stdcall alx_read_macaddr
7809 hidnplayr 1129
        test    eax, eax
1130
        jz      .done
1131
 
1132
; try to load from efuse
1133
        mov     esi, [ebx + device.mmio_addr]
1134
        mov     ecx, ALX_SLD_MAX_TO
1135
  .loop1:
1136
        mov     eax, dword[esi + ALX_SLD]
1137
        test    eax, ALX_SLD_STAT or ALX_SLD_START
1138
        jz      @f
1139
 
1140
        dec     ecx
1141
        jz      .error
1142
 
1143
        push    esi ecx
1144
        xor     esi, esi
1145
        inc     esi
1146
        invoke  Sleep
1147
        pop     ecx esi
1148
        jmp     .loop1
1149
  @@:
1150
        or      eax, ALX_SLD_START
1151
        mov     dword[esi + ALX_SLD], eax
1152
 
1153
        mov     ecx, ALX_SLD_MAX_TO
1154
  .loop2:
1155
        mov     eax, dword[esi + ALX_SLD]
1156
        test    eax, ALX_SLD_START
1157
        jz      @f
1158
 
1159
        dec     ecx
1160
        jz      .error
1161
 
1162
        push    esi ecx
1163
        xor     esi, esi
1164
        inc     esi
1165
        invoke  Sleep
1166
        pop     ecx esi
1167
        jmp     .loop2
1168
  @@:
1169
 
9146 hidnplayr 1170
        stdcall alx_read_macaddr
7809 hidnplayr 1171
        test    eax, eax
1172
        jz      .done
1173
 
1174
; try to load from flash/eeprom (if present)
1175
        set_io  [ebx + device.io_addr], 0
1176
        set_io  [ebx + device.io_addr], ALX_EFLD
1177
        in      eax, dx
1178
        test    eax, ALX_EFLD_F_EXIST or ALX_EFLD_E_EXIST
1179
        jz      .error
1180
 
1181
        mov     ecx, ALX_SLD_MAX_TO
1182
  .loop3:
1183
        in      eax, dx
1184
        test    eax, ALX_EFLD_STAT or ALX_EFLD_START
1185
        jz      @f
1186
 
1187
        dec     ecx
1188
        jz      .error
1189
 
1190
        push    esi edx ecx
1191
        xor     esi, esi
1192
        inc     esi
1193
        invoke  Sleep
1194
        pop     ecx edx esi
1195
        jmp     .loop3
1196
  @@:
1197
        or      eax, ALX_EFLD_START
1198
        out     dx, eax
1199
 
1200
        mov     ecx, ALX_SLD_MAX_TO
1201
  .loop4:
1202
        in      eax, dx
1203
        test    eax, ALX_EFLD_START
1204
        jz      @f
1205
 
1206
        dec     ecx
1207
        jz      .error
1208
 
1209
        push    esi edx ecx
1210
        xor     esi, esi
1211
        inc     esi
1212
        invoke  Sleep
1213
        pop     ecx edx esi
1214
        jmp     .loop4
1215
  @@:
1216
 
9146 hidnplayr 1217
        stdcall alx_read_macaddr
7809 hidnplayr 1218
        test    eax, eax
1219
        jz      .done
1220
 
1221
  .error:
1222
        DEBUGF  1, "error obtaining MAC\n"
1223
        xor     eax, eax
1224
        dec     eax
1225
        ret
1226
 
1227
  .done:
1228
        DEBUGF  1, "MAC OK\n"
1229
        xor     eax, eax
1230
        ret
1231
 
9146 hidnplayr 1232
endp
7809 hidnplayr 1233
 
9146 hidnplayr 1234
proc alx_stop_mac stdcall
1235
 
7809 hidnplayr 1236
        DEBUGF  1,"alx_stop_mac\n"
1237
 
1238
        mov     esi, [ebx + device.mmio_addr]
1239
 
1240
        mov     eax, dword[esi + ALX_RXQ0]
1241
        and     eax, not ALX_RXQ0_EN
1242
        mov     dword[esi + ALX_RXQ0], eax
1243
 
1244
        mov     eax, dword[esi + ALX_TXQ0]
1245
        and     eax, not ALX_TXQ0_EN
1246
        mov     dword[esi + ALX_TXQ0], eax
1247
 
9146 hidnplayr 1248
        stdcall udelay, 40
7809 hidnplayr 1249
 
1250
        mov     eax, [ebx + device.rx_ctrl]
1251
        and     eax, not(ALX_MAC_CTRL_TX_EN or ALX_MAC_CTRL_RX_EN)
1252
        mov     [ebx + device.rx_ctrl], eax
1253
        mov     [esi + ALX_MAC_CTRL], eax
1254
 
1255
        mov     ecx, ALX_DMA_MAC_RST_TO
1256
  .loop:
1257
        mov     eax, [esi + ALX_MAC_STS]
1258
        test    eax, ALX_MAC_STS_IDLE
1259
        jz      .done
1260
 
9146 hidnplayr 1261
        stdcall udelay, 10
7809 hidnplayr 1262
 
1263
        dec     ecx
1264
        jnz     .loop
1265
 
1266
        DEBUGF  1,"alx_stop_mac timeout!\n"
1267
        xor     eax, eax
1268
        dec     eax
1269
        ret
1270
 
1271
  .done:
1272
        DEBUGF  1,"alx_stop_mac ok\n"
1273
        xor     eax, eax
1274
        ret
1275
 
9146 hidnplayr 1276
endp
7809 hidnplayr 1277
 
9146 hidnplayr 1278
proc alx_start_mac stdcall
7809 hidnplayr 1279
 
1280
        DEBUGF  1,"alx_start_mac\n"
1281
 
1282
        mov     esi, [ebx + device.mmio_addr]
1283
 
1284
        mov     eax, dword[esi + ALX_RXQ0]
1285
        or      eax, ALX_RXQ0_EN
1286
        mov     dword[esi + ALX_RXQ0], eax
1287
 
1288
        mov     eax, dword[esi + ALX_TXQ0]
1289
        or      eax, ALX_TXQ0_EN
1290
        mov     dword[esi + ALX_TXQ0], eax
1291
 
1292
        mov     eax, [ebx + device.rx_ctrl]
1293
        or      eax, ALX_MAC_CTRL_TX_EN or ALX_MAC_CTRL_RX_EN
1294
        and     eax, not ALX_MAC_CTRL_FULLD
9146 hidnplayr 1295
        test    [ebx + device.state], ETH_LINK_FULL_DUPLEX
1296
        jz      .no_fd
7809 hidnplayr 1297
        or      eax, ALX_MAC_CTRL_FULLD
9146 hidnplayr 1298
  .no_fd:
7809 hidnplayr 1299
        and     eax, not (ALX_MAC_CTRL_SPEED_MASK shl ALX_MAC_CTRL_SPEED_SHIFT)
9146 hidnplayr 1300
        mov     ecx, [ebx + device.state]
1301
        and     ecx, ETH_LINK_SPEED_MASK
1302
        cmp     ecx, ETH_LINK_SPEED_1G
1303
        jne      .10_100
7809 hidnplayr 1304
        or      eax, (ALX_MAC_CTRL_SPEED_1000 shl ALX_MAC_CTRL_SPEED_SHIFT)
9146 hidnplayr 1305
        jmp     .done
7809 hidnplayr 1306
 
1307
  .10_100:
1308
        or      eax, (ALX_MAC_CTRL_SPEED_10_100 shl ALX_MAC_CTRL_SPEED_SHIFT)
1309
 
9146 hidnplayr 1310
  .done:
1311
        DEBUGF  1,"mac ctrl=0x%x\n", eax
7809 hidnplayr 1312
        mov     [ebx + device.rx_ctrl], eax
1313
        mov     [esi + ALX_MAC_CTRL], eax
1314
 
1315
        ret
1316
 
9146 hidnplayr 1317
endp
7809 hidnplayr 1318
 
9146 hidnplayr 1319
proc alx_init_ring_ptrs stdcall
7809 hidnplayr 1320
 
1321
        DEBUGF  1,"alx_init_ring_ptrs\n"
1322
 
1323
        mov     esi, [ebx + device.mmio_addr]
1324
 
1325
; Receive descriptors
1326
        mov     [ebx + device.rxq_read_idx], 0
1327
        mov     [ebx + device.rxq_write_idx], 0
1328
;        mov     [ebx + device.rxq_rrd_read_idx], 0
1329
 
1330
        mov     dword[esi + ALX_RX_BASE_ADDR_HI], 0
1331
 
1332
        lea     eax, [ebx + device.rrd_ring]
1333
        invoke  GetPhysAddr
1334
        mov     dword[esi + ALX_RRD_ADDR_LO], eax
1335
        mov     dword[esi + ALX_RRD_RING_SZ], RX_RING_SIZE
1336
 
1337
        lea     eax, [ebx + device.rfd_ring]
1338
        invoke  GetPhysAddr
1339
        mov     dword[esi + ALX_RFD_ADDR_LO], eax
1340
        mov     dword[esi + ALX_RFD_RING_SZ], RX_RING_SIZE
1341
        mov     dword[esi + ALX_RFD_BUF_SZ], RX_BUFFER_SIZE
1342
 
1343
; Transmit descriptors
1344
        mov     [ebx + device.txq_read_idx], 0
1345
        mov     [ebx + device.txq_write_idx], 0
1346
 
1347
        mov     dword[esi + ALX_TX_BASE_ADDR_HI], 0
1348
 
1349
        lea     eax, [ebx + device.tpd_ring]
1350
        invoke  GetPhysAddr
1351
        mov     dword[esi + ALX_TPD_PRI0_ADDR_LO], eax
1352
        mov     dword[esi + ALX_TPD_RING_SZ], TX_RING_SIZE
1353
 
1354
; Load these pointers into the chip
1355
        mov     dword[esi + ALX_SRAM9], ALX_SRAM_LOAD_PTR
1356
 
1357
        xor     eax, eax
1358
 
1359
        ret
1360
 
9146 hidnplayr 1361
endp
7809 hidnplayr 1362
 
9146 hidnplayr 1363
proc alx_alloc_rings stdcall
7809 hidnplayr 1364
 
1365
        DEBUGF  1,"alx_alloc_rings\n"
1366
 
1367
        and     [ebx + device.int_mask], not ALX_ISR_ALL_QUEUES
1368
        or      [ebx + device.int_mask], ALX_ISR_TX_Q0 or ALX_ISR_RX_Q0
9146 hidnplayr 1369
        stdcall alx_reinit_rings
7809 hidnplayr 1370
 
1371
        ret
1372
 
9146 hidnplayr 1373
endp
7809 hidnplayr 1374
 
9146 hidnplayr 1375
proc alx_reinit_rings stdcall
7809 hidnplayr 1376
 
1377
        DEBUGF  1,"alx_reinit_rings\n"
1378
 
9146 hidnplayr 1379
        stdcall alx_free_rx_ring
1380
        stdcall alx_init_ring_ptrs
1381
        stdcall alx_refill_rx_ring
7809 hidnplayr 1382
 
1383
        ret
1384
 
9146 hidnplayr 1385
endp
7809 hidnplayr 1386
 
9146 hidnplayr 1387
proc alx_refill_rx_ring stdcall
7809 hidnplayr 1388
 
1389
        DEBUGF  1,"alx_refill_rx_ring\n"
1390
 
1391
        mov     ecx, [ebx + device.rxq_write_idx]
1392
  .loop:
1393
        cmp     dword[ebx + device.rfd_ring+ecx*sizeof.alx_rfd + alx_rfd.addr_l], 0
1394
        jne     .done
1395
 
1396
        invoke  NetAlloc, NET_BUFF.data+RX_BUFFER_SIZE
1397
        test    eax, eax
1398
        jz      .done
1399
        mov     [ebx + device.rfd_ring_virt + ecx*4], eax
1400
        add     eax, NET_BUFF.data
1401
        invoke  GetPhysAddr
1402
        mov     dword[ebx + device.rfd_ring+ecx*sizeof.alx_rfd + alx_rfd.addr_l], eax
1403
        mov     dword[ebx + device.rfd_ring+ecx*sizeof.alx_rfd + alx_rfd.addr_h], 0
1404
 
1405
        mov     eax, ecx
1406
        inc     ecx
1407
        and     ecx, RX_RING_SIZE - 1
1408
 
1409
        cmp     ecx, [ebx + device.rxq_read_idx]
1410
        jne     .loop
1411
 
1412
        mov     ecx, eax
1413
 
1414
  .done:
1415
        cmp     ecx, [ebx + device.rxq_write_idx]
1416
        je      .none
1417
 
1418
        mov     [ebx + device.rxq_write_idx], ecx
1419
        mov     esi, [ebx + device.mmio_addr]
1420
        mov     [esi + ALX_RFD_PIDX], cx
1421
 
1422
  .none:
1423
        xor     eax, eax
1424
 
1425
        ret
1426
 
9146 hidnplayr 1427
endp
7809 hidnplayr 1428
 
9146 hidnplayr 1429
proc alx_free_rx_ring stdcall
7809 hidnplayr 1430
 
1431
        DEBUGF  1,"alx_free_rx_ring\n"
1432
 
1433
        xor     ecx, ecx
1434
  .loop:
1435
        mov     eax, [ebx + device.rfd_ring_virt + ecx*4]
1436
        test    eax, eax
1437
        jz      .next
1438
 
1439
        invoke  NetFree, eax
1440
 
1441
        xor     eax, eax
1442
        mov     dword[ebx + device.rfd_ring+ecx*sizeof.alx_rfd + alx_rfd.addr_l], eax
1443
        mov     dword[ebx + device.rfd_ring+ecx*sizeof.alx_rfd + alx_rfd.addr_h], eax
1444
        mov     [ebx + device.rfd_ring_virt + ecx*4], eax
1445
 
1446
  .next:
1447
        inc     ecx
1448
        cmp     ecx, RX_RING_SIZE
1449
        jb      .loop
1450
 
1451
        ret
1452
 
9146 hidnplayr 1453
endp
7809 hidnplayr 1454
 
9146 hidnplayr 1455
proc alx_configure stdcall
7809 hidnplayr 1456
 
1457
        DEBUGF  1,"alx_configure\n"
1458
 
9146 hidnplayr 1459
        stdcall alx_configure_basic
1460
        stdcall alx_disable_rss
1461
        call    alx_set_rx_mode
7809 hidnplayr 1462
 
1463
        mov     esi, [ebx + device.mmio_addr]
1464
        mov     eax, [ebx + device.rx_ctrl]
1465
        mov     [esi + ALX_MAC_CTRL], eax
1466
 
1467
        xor     eax, eax
1468
        ret
1469
 
9146 hidnplayr 1470
endp
7809 hidnplayr 1471
 
9146 hidnplayr 1472
proc alx_irq_enable stdcall
7809 hidnplayr 1473
 
1474
        DEBUGF  1,"alx_irq_enable\n"
1475
 
1476
        mov     esi, [ebx + device.mmio_addr]
1477
        mov     dword[esi + ALX_ISR], 0
1478
        mov     eax, [ebx + device.int_mask]
1479
        mov     [esi + ALX_IMR], eax
1480
 
9146 hidnplayr 1481
        stdcall alx_post_write
7809 hidnplayr 1482
 
1483
        ret
1484
 
9146 hidnplayr 1485
endp
7809 hidnplayr 1486
 
9146 hidnplayr 1487
proc alx_irq_disable stdcall
1488
 
7809 hidnplayr 1489
        DEBUGF  1,"alx_irq_disable\n"
1490
 
1491
        mov     esi, [ebx + device.mmio_addr]
1492
        mov     dword[esi + ALX_ISR], ALX_ISR_DIS
1493
        mov     dword[esi + ALX_IMR], 0
1494
 
9146 hidnplayr 1495
        stdcall alx_post_write
7809 hidnplayr 1496
 
1497
        ret
1498
 
9146 hidnplayr 1499
endp
7809 hidnplayr 1500
 
9146 hidnplayr 1501
proc alx_post_write stdcall
7809 hidnplayr 1502
 
1503
        push    eax
1504
        mov     esi, [ebx + device.mmio_addr]
1505
        mov     eax, [esi]
1506
        pop     eax
1507
 
1508
        ret
1509
 
9146 hidnplayr 1510
endp
7809 hidnplayr 1511
 
9146 hidnplayr 1512
proc alx_configure_basic stdcall
7809 hidnplayr 1513
 
1514
        DEBUGF  1,"alx_configure_basic\n"
1515
 
1516
        mov     esi, [ebx + device.mmio_addr]
1517
 
9146 hidnplayr 1518
        stdcall alx_set_macaddr
7809 hidnplayr 1519
 
1520
        mov     dword[esi + ALX_CLK_GATE], ALX_CLK_GATE_ALL
1521
 
1522
; idle timeout to switch clk_125M
1523
        cmp     [ebx + device.chip_rev], ALX_REV_B0
1524
        jb      @f
1525
        mov     dword[esi + ALX_IDLE_DECISN_TIMER], ALX_IDLE_DECISN_TIMER_DEF
1526
  @@:
1527
 
1528
        mov     dword[esi + ALX_SMB_TIMER], SMB_TIMER * 500
1529
 
9146 hidnplayr 1530
; Interrupt moderation
7809 hidnplayr 1531
        mov     eax, [esi + ALX_MASTER]
1532
        or      eax, ALX_MASTER_IRQMOD2_EN or ALX_MASTER_IRQMOD1_EN or ALX_MASTER_SYSALVTIMER_EN
1533
        mov     [esi + ALX_MASTER], eax
1534
 
9146 hidnplayr 1535
; Set interupt moderator timer (max interupts per second)
1536
        mov     dword[esi + ALX_IRQ_MODU_TIMER], ((IMT) shl ALX_IRQ_MODU_TIMER1_SHIFT) or ((IMT / 2) shl ALX_IRQ_MODU_TIMER2_SHIFT)
7809 hidnplayr 1537
 
9146 hidnplayr 1538
; Interrupt re-trigger timeout
7809 hidnplayr 1539
        mov     dword[esi + ALX_INT_RETRIG], ALX_INT_RETRIG_TO
1540
 
1541
; tpd threshold to trig int
1542
        mov     dword[esi + ALX_TINT_TPD_THRSHLD], ITH_TPD
1543
        mov     dword[esi + ALX_TINT_TIMER], IMT
1544
 
1545
        mov     dword[esi + ALX_MTU], RX_BUFFER_SIZE + 8 ;;;;
1546
 
1547
        mov     dword[esi + ALX_TXQ1], (((RX_BUFFER_SIZE + 8 + 7) shr 3) or ALX_TXQ1_ERRLGPKT_DROP_EN)
1548
 
1549
; rxq, flow control
1550
 
1551
; TODO set ALX_RXQ2
1552
 
1553
; RXQ0
1554
        mov     eax, (ALX_RXQ0_NUM_RFD_PREF_DEF shl ALX_RXQ0_NUM_RFD_PREF_SHIFT) \
1555
                or (ALX_RXQ0_RSS_MODE_DIS shl ALX_RXQ0_RSS_MODE_SHIFT) \
1556
                or (ALX_RXQ0_IDT_TBL_SIZE_DEF shl ALX_RXQ0_IDT_TBL_SIZE_SHIFT) \
1557
                or ALX_RXQ0_RSS_HSTYP_ALL or ALX_RXQ0_RSS_HASH_EN or ALX_RXQ0_IPV6_PARSE_EN
1558
 
7827 hidnplayr 1559
        test    [ebx + device.pci_did], 1       ;;; FIXME: is gigabit device?
7809 hidnplayr 1560
        jz      @f
1561
        or      eax, ALX_RXQ0_ASPM_THRESH_100M shl ALX_RXQ0_ASPM_THRESH_SHIFT
1562
  @@:
9146 hidnplayr 1563
        mov     [esi + ALX_RXQ0], eax
7809 hidnplayr 1564
 
9146 hidnplayr 1565
; DMA
1566
        max_payload equ 2               ;;;; FIXME
7809 hidnplayr 1567
 
9146 hidnplayr 1568
        mov     eax, [esi + ALX_DMA]            ; Read and ignore?
1569
        ; Pre-B0 devices have 2 DMA channels
1570
        mov     eax, (ALX_DMA_RORDER_MODE_OUT shl ALX_DMA_RORDER_MODE_SHIFT) \
1571
                or ALX_DMA_RREQ_PRI_DATA \
1572
                or (max_payload shl ALX_DMA_RREQ_BLEN_SHIFT) \
1573
                or (ALX_DMA_WDLY_CNT_DEF shl ALX_DMA_WDLY_CNT_SHIFT ) \
1574
                or (ALX_DMA_RDLY_CNT_DEF shl ALX_DMA_RDLY_CNT_SHIFT ) \
1575
                or ((2-1) shl ALX_DMA_RCHNL_SEL_SHIFT)
7809 hidnplayr 1576
 
9146 hidnplayr 1577
        cmp     [ebx + device.chip_rev], ALX_REV_B0
1578
        jb      @f
1579
        ; B0 and newer have 4 DMA channels
1580
        mov     eax, (ALX_DMA_RORDER_MODE_OUT shl ALX_DMA_RORDER_MODE_SHIFT) \
1581
                or ALX_DMA_RREQ_PRI_DATA \
1582
                or (max_payload shl ALX_DMA_RREQ_BLEN_SHIFT) \
1583
                or (ALX_DMA_WDLY_CNT_DEF shl ALX_DMA_WDLY_CNT_SHIFT ) \
1584
                or (ALX_DMA_RDLY_CNT_DEF shl ALX_DMA_RDLY_CNT_SHIFT ) \
1585
                or ((4-1) shl ALX_DMA_RCHNL_SEL_SHIFT)
1586
  @@:
1587
        mov     [esi + ALX_DMA], eax
1588
 
7809 hidnplayr 1589
; default multi-tx-q weights
1590
        mov      eax, (ALX_WRR_PRI_RESTRICT_NONE shl ALX_WRR_PRI_SHIFT) \
1591
                 or (4 shl ALX_WRR_PRI0_SHIFT) \
1592
                 or (4 shl ALX_WRR_PRI1_SHIFT) \
1593
                 or (4 shl ALX_WRR_PRI2_SHIFT) \
1594
                 or (4 shl ALX_WRR_PRI3_SHIFT)
1595
        mov      [esi + ALX_WRR], eax
1596
 
1597
        ret
1598
 
9146 hidnplayr 1599
endp
7809 hidnplayr 1600
 
9146 hidnplayr 1601
proc alx_disable_rss stdcall
7809 hidnplayr 1602
 
1603
        DEBUGF  1,"alx_disable_rss\n"
1604
 
1605
        mov     esi, [ebx + device.mmio_addr]
1606
 
1607
        mov     eax, [esi + ALX_RXQ0]
1608
        and     eax, not (ALX_RXQ0_RSS_HASH_EN)
1609
        mov     [esi + ALX_RXQ0] , eax
1610
 
1611
        ret
1612
 
9146 hidnplayr 1613
endp
7809 hidnplayr 1614
 
9146 hidnplayr 1615
proc alx_set_rx_mode stdcall
1616
 
7809 hidnplayr 1617
        DEBUGF  1,"__alx_set_rx_mode\n"
1618
 
1619
        mov     esi, [ebx + device.mmio_addr]
1620
 
9146 hidnplayr 1621
; TODO: proper multicast
1622
 
7809 hidnplayr 1623
;        if (!(netdev->flags & IFF_ALLMULTI)) {
1624
;                netdev_for_each_mc_addr(ha, netdev)
1625
;                        alx_add_mc_addr(hw, ha->addr, mc_hash);
1626
;
1627
;                alx_write_mem32(hw, ALX_HASH_TBL0, mc_hash[0]);
1628
;                alx_write_mem32(hw, ALX_HASH_TBL1, mc_hash[1]);
1629
;        }
1630
 
1631
        mov     eax, [ebx + device.rx_ctrl]
9146 hidnplayr 1632
        or      eax, ALX_MAC_CTRL_PROMISC_EN or ALX_MAC_CTRL_MULTIALL_EN        ; FIXME: dont force promiscous mode..
7809 hidnplayr 1633
        mov     [ebx + device.rx_ctrl], eax
1634
        mov     dword[esi + ALX_MAC_CTRL], eax
1635
 
1636
        ret
1637
 
9146 hidnplayr 1638
endp
7809 hidnplayr 1639
 
9146 hidnplayr 1640
proc alx_check_link stdcall
7809 hidnplayr 1641
 
9146 hidnplayr 1642
        stdcall alx_clear_phy_intr
7809 hidnplayr 1643
 
1644
        mov     edx, [ebx + device.state]
1645
 
9146 hidnplayr 1646
        stdcall alx_get_phy_link
7809 hidnplayr 1647
        cmp     eax, 0
1648
        jl      .reset
1649
 
1650
        mov     esi, [ebx + device.mmio_addr]
1651
 
1652
        spin_lock_irqsave
1653
        or      [ebx + device.int_mask], ALX_ISR_PHY
1654
        mov     eax, [ebx + device.int_mask]
1655
        mov     [esi + ALX_IMR], eax
1656
        spin_unlock_irqrestore
1657
 
1658
        cmp     edx, [ebx + device.state]
1659
        je      .no_change
1660
 
1661
        cmp     [ebx + device.state], ETH_LINK_DOWN
1662
        je      .link_down
1663
 
9146 hidnplayr 1664
        stdcall alx_post_phy_link
7809 hidnplayr 1665
        mov     ecx, (ALX_PMCTRL_L0S_EN or ALX_PMCTRL_L1_EN or ALX_PMCTRL_ASPM_FCEN)
9146 hidnplayr 1666
        stdcall alx_enable_aspm
1667
        stdcall alx_start_mac
7809 hidnplayr 1668
 
1669
        invoke  NetLinkChanged
1670
 
1671
        ret
1672
 
1673
  .no_change:
1674
        DEBUGF  1, "link state unchanged\n"
1675
 
1676
        ret
1677
 
1678
  .link_down:
1679
; Link is now down
1680
 
9146 hidnplayr 1681
        stdcall alx_reset_mac
7809 hidnplayr 1682
        test    eax, eax
1683
        jnz     .reset
1684
 
9146 hidnplayr 1685
        stdcall alx_irq_disable
7809 hidnplayr 1686
 
1687
; MAC reset causes all HW settings to be lost, restore all
9146 hidnplayr 1688
        stdcall alx_reinit_rings
7809 hidnplayr 1689
        test    eax, eax
1690
        jnz     .reset
1691
 
9146 hidnplayr 1692
        stdcall alx_configure
7809 hidnplayr 1693
        mov     ecx, (ALX_PMCTRL_L1_EN or ALX_PMCTRL_ASPM_FCEN)
9146 hidnplayr 1694
        stdcall alx_enable_aspm
1695
        stdcall alx_post_phy_link
1696
        stdcall alx_irq_enable
7809 hidnplayr 1697
 
1698
        invoke  NetLinkChanged
1699
 
1700
        ret
1701
 
1702
  .reset:
9146 hidnplayr 1703
        DEBUGF  1, "alx_schedule_reset\n"
1704
;;;        stdcall alx_schedule_reset
7809 hidnplayr 1705
 
1706
        ret
1707
 
9146 hidnplayr 1708
endp
7809 hidnplayr 1709
 
9146 hidnplayr 1710
proc alx_post_phy_link stdcall
7809 hidnplayr 1711
 
9146 hidnplayr 1712
        DEBUGF  1, "alx_post_phy_link\n"
1713
 
7809 hidnplayr 1714
        cmp     [ebx + device.chip_rev], ALX_REV_B0
1715
        ja      .done
1716
 
1717
        cmp     [ebx + device.state], ETH_LINK_UNKNOWN
1718
        jae     @f
1719
 
9146 hidnplayr 1720
; TODO: vendor hocus-pocus to tune the PHY according the detected cable length
1721
        stdcall alx_write_phy_dbg, ALX_MIIDBG_AZ_ANADECT, ALX_AZ_ANADECT_DEF
1722
        stdcall alx_read_phy_ext, ALX_MIIEXT_AFE, ALX_MIIEXT_ANEG
1723
        and     eax, not (ALX_AFE_10BT_100M_TH)
1724
        stdcall alx_write_phy_ext, ALX_MIIEXT_AFE, ALX_MIIEXT_ANEG, eax
7809 hidnplayr 1725
 
1726
        ret
1727
  @@:
1728
 
1729
  .done:
1730
 
1731
        ret
1732
 
9146 hidnplayr 1733
endp
7809 hidnplayr 1734
 
9146 hidnplayr 1735
proc alx_clear_phy_intr stdcall
7809 hidnplayr 1736
 
9146 hidnplayr 1737
        DEBUGF  1,"alx_clear_phy_intr\n"
1738
        stdcall alx_read_phy_reg, ALX_MII_ISR
7809 hidnplayr 1739
 
1740
        ret
1741
 
9146 hidnplayr 1742
endp
7809 hidnplayr 1743
 
9146 hidnplayr 1744
proc alx_get_phy_link stdcall
7809 hidnplayr 1745
 
1746
        DEBUGF  1,"alx_get_phy_link\n"
1747
 
9146 hidnplayr 1748
        stdcall alx_read_phy_reg, MII_BMSR
1749
        stdcall alx_read_phy_reg, MII_BMSR
7809 hidnplayr 1750
 
1751
        mov     [ebx + device.state], ETH_LINK_DOWN
1752
 
1753
        test    ax, BMSR_LSTATUS
1754
        jnz     @f
1755
        DEBUGF  1,"link is down\n"
1756
        xor     eax, eax
1757
        ret
1758
  @@:
9146 hidnplayr 1759
        stdcall alx_read_phy_reg, ALX_MII_GIGA_PSSR
7809 hidnplayr 1760
        test    ax, ALX_GIGA_PSSR_SPD_DPLX_RESOLVED
1761
        jz      .wrong_speed
1762
 
1763
        DEBUGF  1,"link is up\n"
1764
 
1765
        test    ax, ALX_GIGA_PSSR_DPLX
1766
        jz      @f
9146 hidnplayr 1767
        or      [ebx + device.state], ETH_LINK_FULL_DUPLEX
7809 hidnplayr 1768
        DEBUGF  1,"full duplex\n"
1769
  @@:
1770
 
1771
        and     ax, ALX_GIGA_PSSR_SPEED
1772
        cmp     ax, ALX_GIGA_PSSR_1000MBS
1773
        jne     @f
9146 hidnplayr 1774
        or      [ebx + device.state], ETH_LINK_SPEED_1G
7809 hidnplayr 1775
        DEBUGF  1,"1 gigabit\n"
1776
        ret
1777
 
1778
  @@:
1779
        cmp     ax, ALX_GIGA_PSSR_100MBS
1780
        jne     @f
9146 hidnplayr 1781
        or      [ebx + device.state], ETH_LINK_SPEED_100M
1782
        DEBUGF  1,"100 Mbit\n"
7809 hidnplayr 1783
        ret
1784
 
1785
  @@:
1786
        cmp     ax, ALX_GIGA_PSSR_10MBS
1787
        jne     @f
9146 hidnplayr 1788
        or      [ebx + device.state], ETH_LINK_SPEED_10M
1789
        DEBUGF  1,"10 Mbit\n"
7809 hidnplayr 1790
        ret
1791
 
1792
  @@:
1793
        mov     [ebx + device.state], ETH_LINK_UNKNOWN
1794
        DEBUGF  1,"speed unknown\n"
1795
        ret
1796
 
1797
  .wrong_speed:
1798
        DEBUGF  1,"wrong speed\n"
1799
        xor     eax, eax
1800
        dec     eax
1801
        ret
1802
 
9146 hidnplayr 1803
endp
7809 hidnplayr 1804
 
9146 hidnplayr 1805
proc alx_read_phy_reg stdcall, reg:dword
7809 hidnplayr 1806
 
9146 hidnplayr 1807
; FIXME: fixed clock
7809 hidnplayr 1808
 
9146 hidnplayr 1809
        DEBUGF  1,"alx_read_phy_reg reg=0x%x\n", [reg]:4
7809 hidnplayr 1810
 
1811
        mov     esi, [ebx + device.mmio_addr]
1812
 
1813
        mov     eax, [reg]
1814
        shl     eax, ALX_MDIO_REG_SHIFT
1815
        or      eax, ALX_MDIO_SPRES_PRMBL or (ALX_MDIO_CLK_SEL_25MD4 shl ALX_MDIO_CLK_SEL_SHIFT) or ALX_MDIO_START or ALX_MDIO_OP_READ
1816
        mov     dword[esi + ALX_MDIO], eax
1817
 
1818
        mov     ecx, ALX_MDIO_MAX_AC_TO
1819
  .loop:
1820
        mov     eax, dword[esi + ALX_MDIO]
1821
        test    eax, ALX_MDIO_BUSY
1822
        jz      .ready
1823
 
9146 hidnplayr 1824
        stdcall udelay, 10
7809 hidnplayr 1825
 
1826
        dec     ecx
1827
        jnz     .loop
1828
 
9146 hidnplayr 1829
        DEBUGF  1,"alx_read_phy_reg read timeout!\n"
7809 hidnplayr 1830
        xor     eax, eax
1831
        dec     eax
1832
        ret
1833
 
1834
  .ready:
1835
;        shr     eax, ALX_MDIO_DATA_SHIFT
1836
        and     eax, ALX_MDIO_DATA_MASK
1837
 
9146 hidnplayr 1838
        DEBUGF  1,"alx_read_phy_reg data=0x%x\n", eax:4
7809 hidnplayr 1839
 
1840
        ret
1841
 
1842
endp
1843
 
9146 hidnplayr 1844
proc  alx_read_phy_ext stdcall, dev:dword, reg:dword
7809 hidnplayr 1845
 
9146 hidnplayr 1846
; FIXME: fixed clock
7809 hidnplayr 1847
 
9146 hidnplayr 1848
        DEBUGF  1,"alx_read_phy_ext dev=0x%x reg=0x%x\n", [dev]:4, [reg]:4
7809 hidnplayr 1849
 
9146 hidnplayr 1850
        mov     esi, [ebx + device.mmio_addr]
7809 hidnplayr 1851
 
9146 hidnplayr 1852
        mov     eax, [dev]
1853
        shl     eax, ALX_MDIO_EXTN_DEVAD_SHIFT
1854
        mov     ax, word[reg]
1855
;        shl     eax, ALX_MDIO_EXTN_REG_SHIFT
1856
        mov     dword[esi + ALX_MDIO_EXTN], eax
7809 hidnplayr 1857
 
9146 hidnplayr 1858
        mov     eax, ALX_MDIO_SPRES_PRMBL or (ALX_MDIO_CLK_SEL_25MD4 shl ALX_MDIO_CLK_SEL_SHIFT) or ALX_MDIO_START or ALX_MDIO_OP_READ or ALX_MDIO_MODE_EXT
1859
        mov     dword[esi + ALX_MDIO], eax
7809 hidnplayr 1860
 
9146 hidnplayr 1861
        mov     ecx, ALX_MDIO_MAX_AC_TO
1862
  .loop:
1863
        mov     eax, dword[esi + ALX_MDIO]
1864
        test    eax, ALX_MDIO_BUSY
1865
        jz      .ready
1866
 
1867
        stdcall udelay, 10
1868
 
1869
        dec     ecx
1870
        jnz     .loop
1871
 
1872
        DEBUGF  1,"alx_read_phy_ext read timeout!\n"
1873
        xor     eax, eax
1874
        dec     eax
1875
        ret
1876
 
1877
  .ready:
1878
;        shr     eax, ALX_MDIO_DATA_SHIFT
1879
        and     eax, ALX_MDIO_DATA_MASK
1880
 
1881
        DEBUGF  1,"alx_read_phy_ext data=0x%x\n", eax:4
1882
 
1883
        ret
1884
 
1885
endp
1886
 
1887
proc  alx_write_phy_reg stdcall, reg:dword, val:dword
1888
 
1889
; FIXME: fixed clock
1890
 
1891
        DEBUGF  1,"alx_write_phy_reg reg=0x%x data=0x%x\n", [reg]:4, [val]:4
1892
 
7809 hidnplayr 1893
        mov     esi, [ebx + device.mmio_addr]
1894
 
1895
        mov     eax, [reg]
1896
        shl     eax, ALX_MDIO_REG_SHIFT
1897
        mov     ax, word[val]                   ; data must be in 16 lower bits :)
1898
        or      eax, ALX_MDIO_SPRES_PRMBL or (ALX_MDIO_CLK_SEL_25MD4 shl ALX_MDIO_CLK_SEL_SHIFT) or ALX_MDIO_START
1899
        mov     dword[esi + ALX_MDIO], eax
1900
 
1901
        mov     ecx, ALX_MDIO_MAX_AC_TO
1902
  .loop:
1903
        mov     eax, dword[esi + ALX_MDIO]
1904
        test    eax, ALX_MDIO_BUSY
1905
        jz      .ready
1906
 
9146 hidnplayr 1907
        stdcall udelay, 10
7809 hidnplayr 1908
 
1909
        dec     ecx
1910
        jnz     .loop
1911
 
9146 hidnplayr 1912
        DEBUGF  1,"alx_write_phy_reg timeout!\n"
7809 hidnplayr 1913
        xor     eax, eax
1914
        dec     eax
1915
        ret
1916
 
1917
  .ready:
9146 hidnplayr 1918
        DEBUGF  1,"alx_write_phy_reg OK\n"
7809 hidnplayr 1919
        xor     eax, eax
1920
 
1921
        ret
1922
endp
1923
 
9146 hidnplayr 1924
proc  alx_write_phy_dbg stdcall, reg:dword, val:dword
1925
 
1926
        DEBUGF  1,"alx_write_phy_dbg\n"
1927
 
1928
        stdcall alx_write_phy_reg, ALX_MII_DBG_ADDR, [reg]
1929
        test    eax, eax
1930
        jnz     @f
1931
        stdcall alx_write_phy_reg, ALX_MII_DBG_DATA, [val]
1932
 
1933
        ret
1934
  @@:
1935
        DEBUGF  1,"alx_write_phy_dbg ERROR\n"
1936
 
1937
        ret
1938
 
1939
endp
1940
 
1941
proc  alx_read_phy_dbg stdcall, reg:dword
1942
 
1943
        DEBUGF  1,"alx_read_phy_dbg\n"
1944
 
1945
        stdcall alx_write_phy_reg, ALX_MII_DBG_ADDR, [reg]
1946
        test    eax, eax
1947
        jnz     @f
1948
        stdcall alx_read_phy_reg, ALX_MII_DBG_DATA
1949
 
1950
        ret
1951
  @@:
1952
        DEBUGF  1,"alx_read_phy_dbg ERROR\n"
1953
 
1954
        ret
1955
 
1956
endp
1957
 
1958
proc  alx_write_phy_ext stdcall, dev:dword, reg:dword, val:dword
1959
 
1960
; FIXME: fixed clock
1961
 
1962
        DEBUGF  1,"alx_write_phy_ext dev=0x%x reg=0x%x, data=0x%x\n", [dev]:4, [reg]:4, [val]:4
1963
 
1964
        mov     esi, [ebx + device.mmio_addr]
1965
 
1966
        mov     eax, [dev]
1967
        shl     eax, ALX_MDIO_EXTN_DEVAD_SHIFT
1968
        mov     ax, word[reg]
1969
;        shl     eax, ALX_MDIO_EXTN_REG_SHIFT
1970
        mov     dword[esi + ALX_MDIO_EXTN], eax
1971
 
1972
        movzx   eax, word[val]                   ; data must be in 16 lower bits :)
1973
        or      eax, ALX_MDIO_SPRES_PRMBL or (ALX_MDIO_CLK_SEL_25MD4 shl ALX_MDIO_CLK_SEL_SHIFT) or ALX_MDIO_START or ALX_MDIO_MODE_EXT
1974
        mov     dword[esi + ALX_MDIO], eax
1975
 
1976
        mov     ecx, ALX_MDIO_MAX_AC_TO
1977
  .loop:
1978
        mov     eax, dword[esi + ALX_MDIO]
1979
        test    eax, ALX_MDIO_BUSY
1980
        jz      .ready
1981
 
1982
        stdcall udelay, 10
1983
 
1984
        dec     ecx
1985
        jnz     .loop
1986
 
1987
        DEBUGF  1,"alx_write_phy_ext timeout!\n"
1988
        xor     eax, eax
1989
        dec     eax
1990
        ret
1991
 
1992
  .ready:
1993
        DEBUGF  1,"alx_write_phy_ext OK\n"
1994
        xor     eax, eax
1995
 
1996
        ret
1997
endp
1998
 
7809 hidnplayr 1999
alx_request_irq:
2000
 
2001
        DEBUGF  1,"Request IRQ\n"
2002
 
2003
        mov     esi, [ebx + device.mmio_addr]
2004
 
2005
; Only legacy interrupts supported for now.
2006
        mov     dword[esi + ALX_MSI_RETRANS_TIMER], 0
2007
 
2008
        ret
2009
 
2010
; End of code
2011
 
2012
data fixups
2013
end data
2014
 
2015
include '../peimport.inc'
2016
 
2017
my_service      db 'AR81XX',0                    ; max 16 chars include zero
2018
 
7827 hidnplayr 2019
chiplist:
2020
                dd (ALX_DEV_ID_AR8131 shl 16) or ALX_VEN_ID, ar8131_sz
9150 hidnplayr 2021
                dd (ALX_DEV_ID_AR8132 shl 16) or ALX_VEN_ID, ar8132_sz
2022
                dd (ALX_DEV_ID_AR8151_1 shl 16) or ALX_VEN_ID, ar8151_1_sz
2023
                dd (ALX_DEV_ID_AR8151_2 shl 16) or ALX_VEN_ID, ar8151_2_sz
2024
                dd (ALX_DEV_ID_AR8152_1 shl 16) or ALX_VEN_ID, ar8152_1_sz
2025
                dd (ALX_DEV_ID_AR8152_2 shl 16) or ALX_VEN_ID, ar8152_2_sz
7827 hidnplayr 2026
                dd (ALX_DEV_ID_AR8161 shl 16) or ALX_VEN_ID, ar8161_sz
9150 hidnplayr 2027
                dd (ALX_DEV_ID_E2200 shl 16) or ALX_VEN_ID, e2200_sz
2028
                dd (ALX_DEV_ID_E2400 shl 16) or ALX_VEN_ID, e2400_sz
2029
                dd (ALX_DEV_ID_E2500 shl 16) or ALX_VEN_ID, e2500_sz
7827 hidnplayr 2030
                dd (ALX_DEV_ID_AR8162 shl 16) or ALX_VEN_ID, ar8162_sz
2031
                dd (ALX_DEV_ID_AR8171 shl 16) or ALX_VEN_ID, ar8171_sz
2032
                dd (ALX_DEV_ID_AR8172 shl 16) or ALX_VEN_ID, ar8172_sz
2033
                dd 0
2034
 
2035
ar8131_sz       db "AR8131", 0
9150 hidnplayr 2036
ar8132_sz       db "AR8132", 0
2037
ar8151_1_sz     db "AR8151 rev1", 0
2038
ar8151_2_sz     db "AR8151 rev2", 0
2039
ar8152_1_sz     db "AR8152 rev1", 0
2040
ar8152_2_sz     db "AR8152 rev2", 0
7827 hidnplayr 2041
ar8161_sz       db "AR8161", 0
2042
ar8162_sz       db "AR8162", 0
2043
ar8171_sz       db "QCA8171", 0
2044
ar8172_sz       db "QCA8172", 0
2045
e2200_sz        db "Killer E2200", 0
2046
e2400_sz        db "Killer E2400", 0
2047
e2500_sz        db "Killer E2500", 0
2048
 
7809 hidnplayr 2049
include_debug_strings
2050
 
2051
align 4
2052
devices         dd 0
2053
device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
2054