Subversion Repositories Kolibri OS

Rev

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

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