Subversion Repositories Kolibri OS

Rev

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