Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  R6040 driver for KolibriOS                                     ;;
7
;;                                                                 ;;
8
;;  based on R6040.c from linux                                    ;;
9
;;                                                                 ;;
10
;;    Written by Asper (asper.85@mail.ru)                          ;;
11
;;            and hidnplayr (hidnplayr@gmail.com)                  ;;
12
;;                                                                 ;;
13
;;          GNU GENERAL PUBLIC LICENSE                             ;;
14
;;             Version 2, June 1991                                ;;
15
;;                                                                 ;;
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
 
18
 
19
 
20
;********************************************************************
21
;   Interface
22
;      r6040_reset
23
;      r6040_probe
24
;      r6040_poll
25
;      r6040_transmit
26
;
27
;      These functions are referenced in ethernet.inc
28
;
29
;********************************************************************
30
 
31
;; A few user-configurable values.
32
 
33
TX_RING_SIZE    equ 4
34
RX_RING_SIZE    equ 4
35
 
36
; ethernet address length
37
ETH_ALEN        equ 6
38
ETH_HLEN        equ (2 * ETH_ALEN + 2)
39
ETH_ZLEN        equ     60      ; 60 + 4bytes auto payload for
40
                                ; mininmum 64bytes frame length
41
; system timer frequency
42
HZ              equ 1000
43
 
44
; max time out delay time
45
W_MAX_TIMEOUT   equ 0x0FFF
46
 
47
;; Size of the in-memory receive ring.
48
RX_BUF_LEN_IDX  equ 3       ;; 0==8K, 1==16K, 2==32K, 3==64K
49
RX_BUF_LEN      equ (8192 << RX_BUF_LEN_IDX)
50
 
51
;-; Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4).
52
;-TX_BUF_SIZE     equ 1536
53
;-RX_BUF_SIZE     equ 1536
54
 
55
;; PCI Tuning Parameters
56
;   Threshold is bytes transferred to chip before transmission starts.
57
TX_FIFO_THRESH  equ 256     ;; In bytes, rounded down to 32 byte units.
58
 
59
;; The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024.
60
RX_FIFO_THRESH  equ 4       ;; Rx buffer level before first PCI xfer.
61
RX_DMA_BURST    equ 4       ;; Maximum PCI burst, '4' is 256 bytes
62
TX_DMA_BURST    equ 4
63
 
64
;; Operational parameters that usually are not changed.
65
PHY1_ADDR       equ 1       ;For MAC1
66
PHY2_ADDR       equ 3       ;For MAC2
67
PHY_MODE        equ 0x3100  ;PHY CHIP Register 0
68
PHY_CAP         equ 0x01E1  ;PHY CHIP Register 4
69
 
70
;; Time in jiffies before concluding the transmitter is hung.
71
TX_TIMEOUT      equ ((6000*HZ)/1000)
72
 
73
R6040_IO_SIZE   equ 256     ; RDC MAC I/O Size
74
MAX_MAC         equ 2       ; MAX RDC MAC
75
 
76
;**************************************************************************
77
; RDC R6040 Register Definitions
78
;**************************************************************************
79
MCR0            equ 0x00    ;Control register 0
80
MCR1            equ 0x01    ;Control register 1
81
MAC_RST         equ 0x0001  ;Reset the MAC
82
MBCR            equ 0x08    ;Bus control
83
MT_ICR          equ 0x0C    ;TX interrupt control
84
MR_ICR          equ 0x10    ;RX interrupt control
85
MTPR            equ 0x14    ;TX poll command register
86
MR_BSR          equ 0x18    ;RX buffer size
87
MR_DCR          equ 0x1A    ;RX descriptor control
88
MLSR            equ 0x1C    ;Last status
89
MMDIO           equ 0x20    ;MDIO control register
90
MDIO_WRITE      equ 0x4000  ;MDIO write
91
MDIO_READ       equ 0x2000  ;MDIO read
92
MMRD            equ 0x24    ;MDIO read data register
93
MMWD            equ 0x28    ;MDIO write data register
94
MTD_SA0         equ 0x2C    ;TX descriptor start address 0
95
MTD_SA1         equ 0x30    ;TX descriptor start address 1
96
MRD_SA0         equ 0x34    ;RX descriptor start address 0
97
MRD_SA1         equ 0x38    ;RX descriptor start address 1
98
MISR            equ 0x3C    ;Status register
99
MIER            equ 0x40    ;INT enable register
100
MSK_INT         equ 0x0000  ;Mask off interrupts
101
RX_FINISH       equ 0x0001  ;RX finished
102
RX_NO_DESC      equ 0x0002  ;No RX descriptor available
103
RX_FIFO_FULL    equ 0x0004  ;RX FIFO full
104
RX_EARLY        equ 0x0008  ;RX early
105
TX_FINISH       equ 0x0010  ;TX finished
106
TX_EARLY        equ 0x0080  ;TX early
107
EVENT_OVRFL     equ 0x0100  ;Event counter overflow
108
LINK_CHANGED    equ 0x0200  ;PHY link changed
109
ME_CISR         equ 0x44    ;Event counter INT status
110
ME_CIER         equ 0x48    ;Event counter INT enable
111
MR_CNT          equ 0x50    ;Successfully received packet counter
112
ME_CNT0         equ 0x52    ;Event counter 0
113
ME_CNT1         equ 0x54    ;Event counter 1
114
ME_CNT2         equ 0x56    ;Event counter 2
115
ME_CNT3         equ 0x58    ;Event counter 3
116
MT_CNT          equ 0x5A    ;Successfully transmit packet counter
117
ME_CNT4         equ 0x5C    ;Event counter 4
118
MP_CNT          equ 0x5E    ;Pause frame counter register
119
MAR0            equ 0x60    ;Hash table 0
120
MAR1            equ 0x62    ;Hash table 1
121
MAR2            equ 0x64    ;Hash table 2
122
MAR3            equ 0x66    ;Hash table 3
123
MID_0L          equ 0x68    ;Multicast address MID0 Low
124
MID_0M          equ 0x6A    ;Multicast address MID0 Medium
125
MID_0H          equ 0x6C    ;Multicast address MID0 High
126
MID_1L          equ 0x70    ;MID1 Low
127
MID_1M          equ 0x72    ;MID1 Medium
128
MID_1H          equ 0x74    ;MID1 High
129
MID_2L          equ 0x78    ;MID2 Low
130
MID_2M          equ 0x7A    ;MID2 Medium
131
MID_2H          equ 0x7C    ;MID2 High
132
MID_3L          equ 0x80    ;MID3 Low
133
MID_3M          equ 0x82    ;MID3 Medium
134
MID_3H          equ 0x84    ;MID3 High
135
PHY_CC          equ 0x88    ;PHY status change configuration register
136
PHY_ST          equ 0x8A    ;PHY status register
137
MAC_SM          equ 0xAC    ;MAC status machine
138
MAC_ID          equ 0xBE    ;Identifier register
139
 
140
MAX_BUF_SIZE    equ 0x600   ;1536
141
 
142
MBCR_DEFAULT    equ 0x012A  ;MAC Bus Control Register
143
MCAST_MAX       equ 3       ;Max number multicast addresses to filter
144
 
145
;Descriptor status
146
DSC_OWNER_MAC   equ 0x8000  ;MAC is the owner of this descriptor
147
DSC_RX_OK       equ 0x4000  ;RX was successfull
148
DSC_RX_ERR      equ 0x0800  ;RX PHY error
149
DSC_RX_ERR_DRI  equ 0x0400  ;RX dribble packet
150
DSC_RX_ERR_BUF  equ 0x0200  ;RX length exceeds buffer size
151
DSC_RX_ERR_LONG equ 0x0100  ;RX length > maximum packet length
152
DSC_RX_ERR_RUNT equ 0x0080  ;RX packet length < 64 byte
153
DSC_RX_ERR_CRC  equ 0x0040  ;RX CRC error
154
DSC_RX_BCAST    equ 0x0020  ;RX broadcast (no error)
155
DSC_RX_MCAST    equ 0x0010  ;RX multicast (no error)
156
DSC_RX_MCH_HIT  equ 0x0008  ;RX multicast hit in hash table (no error)
157
DSC_RX_MIDH_HIT equ 0x0004  ;RX MID table hit (no error)
158
DSC_RX_IDX_MID_MASK  equ 3  ;RX mask for the index of matched MIDx
159
 
160
;PHY settings
161
ICPLUS_PHY_ID   equ 0x0243
162
 
163
RX_INTS         equ RX_FIFO_FULL or RX_NO_DESC or RX_FINISH
164
TX_INTS         equ TX_FINISH
165
INT_MASK        equ RX_INTS or TX_INTS
166
 
167
 
168
r6040_txb     equ (eth_data_start)
169
r6040_rxb     equ ((r6040_txb+(MAX_BUF_SIZE*TX_RING_SIZE)+32) and 0xfffffff0)
170
r6040_tx_ring equ ((r6040_rxb+(MAX_BUF_SIZE*RX_RING_SIZE)+32) and 0xfffffff0)
171
r6040_rx_ring equ ((r6040_tx_ring+(r6040_x_head.sizeof*TX_RING_SIZE)+32) and 0xfffffff0)
172
 
173
virtual at ((r6040_rx_ring+(r6040_x_head.sizeof*RX_RING_SIZE)+32) and 0xfffffff0)
174
r6040_private:
175
  .rx_ring                dd ?
176
  .tx_ring                dd ?
177
  .cur_rx                 dw ?
178
  .cur_tx                 dw ?
179
  .phy_addr               dw ?
180
  .phy_mode               dw ?
181
  .mcr0                   dw ?
182
  .mcr1                   dw ?
183
  .switch_sig             dw ?
184
end virtual
185
 
186
virtual at 0
187
r6040_x_head:
188
  .status         dw ?   ;0-1
189
  .len            dw ?   ;2-3
190
  .buf            dd ?   ;4-7
191
  .ndesc          dd ?   ;8-B
192
  .rev1           dd ?   ;C-F
193
  .vbufp          dd ?   ;10-13
194
  .vndescp        dd ?   ;14-17
195
  .skb_ptr        dd ?   ;18-1B
196
  .rev2           dd ?   ;1C-1F
197
  .sizeof:
198
end virtual
199
 
200
 
201
 
202
; Read a word data from PHY Chip
203
proc  r6040_phy_read stdcall, phy_addr:dword, reg:dword
204
        push    ecx edx
205
        mov     eax, [phy_addr]
206
        shl     eax, 8
207
        add     eax, [reg]
208
        add     eax, MDIO_READ
209
        mov     edx, [io_addr]
210
        add     edx, MMDIO
211
        out     dx, ax
212
        ;Wait for the read bit to be cleared.
213
        mov     ecx, 2048 ;limit
214
        xor     eax, eax
215
  .read:
216
        in      ax, dx
217
        test    ax, MDIO_READ
218
        jz      @f
219
        dec     ecx
220
        test    ecx, ecx
221
        jnz     .read
222
  @@:
223
        mov     edx, [io_addr]
224
        add     edx, MMRD
225
        in      ax, dx
226
        and     eax, 0xFFFF
227
        pop     edx ecx
228
        ret
229
endp
230
 
231
; Write a word data to PHY Chip
232
proc  r6040_phy_write stdcall, phy_addr:dword, reg:dword, val:dword
233
        push    eax ecx edx
234
        mov     eax, [val]
235
        mov     edx, [io_addr]
236
        add     edx, MMWD
237
        out     dx, ax
238
        ;Write the command to the MDIO bus
239
        mov     eax, [phy_addr]
240
        shl     eax, 8
241
        add     eax, [reg]
242
        add     eax, MDIO_WRITE
243
        mov     edx, [io_addr]
244
        add     edx, MMDIO
245
        out     dx, ax
246
        ;Wait for the write bit to be cleared.
247
        mov     ecx, 2048 ;limit
248
        xor     eax, eax
249
  .write:
250
        in      ax, dx
251
        test    ax, MDIO_WRITE
252
        jz      @f
253
        dec     ecx
254
        test    ecx, ecx
255
        jnz     .write
256
  @@:
257
        pop     edx ecx eax
258
        ret
259
endp
260
 
261
macro r6040_mdio_write reg, val {
262
        stdcall r6040_phy_read, [io_addr], [r6040_private.phy_addr], reg
263
}
264
 
265
macro r6040_mdio_write reg, val {
266
        stdcall r6040_phy_write, [io_addr], [r6040_private.phy_addr], reg, val
267
}
268
 
269
 
270
proc r6040_init_ring_desc stdcall, desc_ring:dword, size:dword
271
        push    eax ecx esi
272
        mov     ecx, [size]
273
        test    ecx, ecx
274
        jz      .out
275
 
276
        mov     esi, [desc_ring]
277
        mov     eax, esi
278
    .next_desc:
279
        add     eax, r6040_x_head.sizeof - OS_BASE
280
        mov     [esi+r6040_x_head.ndesc], eax
281
        add     eax, OS_BASE
282
        mov     [esi+r6040_x_head.vndescp], eax
283
        mov     esi, eax
284
        dec     ecx
285
        jnz     .next_desc
286
 
287
        sub     esi, r6040_x_head.sizeof
288
        mov     eax, [desc_ring]
289
        mov     [esi+r6040_x_head.vndescp], eax
290
        sub     eax, OS_BASE
291
        mov     [esi+r6040_x_head.ndesc], eax
292
    .out:
293
        pop     esi ecx eax
294
        ret
295
endp
296
 
297
 
298
 
299
 
300
r6040_init_rxbufs:
301
 
302
        stdcall r6040_init_ring_desc, r6040_rx_ring, RX_RING_SIZE
303
 
304
        ; Allocate skbs for the rx descriptors
305
        mov     esi, r6040_rx_ring
306
        mov     ebx, r6040_rxb
307
        mov     ecx, RX_RING_SIZE
308
        mov     eax, r6040_rx_ring
309
    .next_desc:
310
        mov     [esi+r6040_x_head.skb_ptr], ebx
311
        mov     [esi+r6040_x_head.buf], ebx
312
        sub     [esi+r6040_x_head.buf], OS_BASE
313
        mov     [esi+r6040_x_head.status], DSC_OWNER_MAC
314
 
315
        mov     eax, [esi+r6040_x_head.vndescp]
316
        mov     esi, eax
317
 
318
        add     ebx, MAX_BUF_SIZE
319
        dec     ecx
320
        jnz     .next_desc
321
 
322
        xor     eax, eax
323
    .out:
324
 
325
        ret
326
 
327
 
328
r6040_probe:
329
 
330
        DEBUGF  1, "Probing r6040\n"
331
 
332
        call    adjust_pci_device
333
 
334
 
335
        ; If PHY status change register is still set to zero
336
        ; it means the bootloader didn't initialize it
337
        mov     edx, [io_addr]
338
        add     edx, PHY_CC
339
        in      ax, dx
340
        test    ax, ax
341
        jnz     @f
342
        mov     eax, 0x9F07
343
        out     dx, ax
344
     @@:
345
        ; Set MAC address
346
        mov     ecx, 3
347
        mov     edi, node_addr
348
        mov     edx, [io_addr]
349
        add     edx, MID_0L
350
     .mac:
351
        in      ax, dx
352
        stosw
353
        add     edx, 2
354
        dec     ecx
355
        jnz     .mac
356
        ; Some bootloaders/BIOSes do not initialize
357
        ; MAC address, warn about that
358
        and     eax, 0xFF
359
        or      eax, [node_addr]
360
        test    eax, eax
361
        jnz     @f
362
        DEBUGF  1, "K : MAC address not initialized\n" ;, generating random"
363
        ;Asper: Add here generate function call!
364
        ;       Temporary workaround: init by constant adress
365
        mov     dword [node_addr], 0x00006000
366
        mov     word [node_addr+4], 0x0001
367
     @@:
368
        ; Init RDC private data
369
        mov     [r6040_private.mcr0], 0x1002
370
        ;mov     [r6040_private.phy_addr], 1 ; Asper: Only one network card is supported now.
371
        mov     [r6040_private.switch_sig], 0
372
 
373
        ; Check the vendor ID on the PHY, if 0xFFFF assume none attached
374
        stdcall r6040_phy_read, 1, 2
375
        cmp     ax, 0xFFFF
376
        jne     @f
377
        DEBUGF  1, "K : Failed to detect an attached PHY\n" ;, generating random"
378
        mov     eax, -1
379
        ret
380
     @@:
381
 
382
        ; Set MAC address
383
        call    r6040_mac_address
384
 
385
 
386
        ; Initialize and alloc RX/TX buffers
387
        stdcall r6040_init_ring_desc, r6040_tx_ring, TX_RING_SIZE
388
        call    r6040_init_rxbufs ;r6040_alloc_rxbufs
389
        test    eax, eax
390
        jnz     .out
391
 
392
        ; Read the PHY ID
393
        mov     [r6040_private.phy_mode], 0x8000
394
        stdcall r6040_phy_read, 0, 2
395
        mov     [r6040_private.switch_sig], ax
396
        cmp     ax, ICPLUS_PHY_ID
397
        jne     @f
398
        stdcall r6040_phy_write, 29, 31, 0x175C ; Enable registers
399
        jmp     .phy_readen
400
      @@:
401
 
402
        ; PHY Mode Check
403
        movzx   eax, [r6040_private.phy_addr]
404
        stdcall r6040_phy_write, eax, 4, PHY_CAP
405
        stdcall r6040_phy_write, eax, 0, PHY_MODE
406
;      if PHY_MODE = 0x3100
407
        call    r6040_phy_mode_chk
408
        mov     [r6040_private.phy_mode], ax
409
        jmp     .phy_readen
410
;      end if
411
;      if not (PHY_MODE and 0x0100)
412
        mov     [r6040_private.phy_mode], 0
413
;      end if
414
      .phy_readen:
415
 
416
        ; Set duplex mode
417
        mov     ax, [r6040_private.phy_mode]
418
        or      [r6040_private.mcr0], ax
419
 
420
        ; improve performance (by RDC guys)
421
        stdcall r6040_phy_read, 30, 17
422
        or      ax, 0x4000
423
        stdcall r6040_phy_write, 30, 17, eax
424
 
425
        stdcall r6040_phy_read, 30, 17
426
        xor     ax, -1
427
        or      ax, 0x2000
428
        xor     ax, -1
429
        stdcall r6040_phy_write, 30, 17, eax
430
 
431
        stdcall r6040_phy_write, 0, 19, 0x0000
432
        stdcall r6040_phy_write, 0, 30, 0x01F0
433
 
434
        ; Initialize all Mac registers
435
        call    r6040_reset
436
 
437
        xor     eax, eax
438
      .out:
439
        ret
440
 
441
 
442
 
443
 
444
 
445
 
446
align 4
447
r6040_reset:
448
 
449
        DEBUGF  1, "Resetting r6040\n"
450
 
451
        push    eax ecx edx
452
        ; Mask off Interrupt
453
        mov     eax, MSK_INT
454
        mov     edx, [io_addr]
455
        add     edx, MIER
456
        out     dx, ax
457
 
458
        ;Reset RDC MAC
459
        mov     eax, MAC_RST
460
        mov     edx, [io_addr]
461
        add     edx, MCR1
462
        out     dx, ax
463
 
464
        mov     ecx, 2048 ;limit
465
  .read:
466
        in      ax, dx
467
        test    ax, 0x1
468
        jnz     @f
469
        dec     ecx
470
        test    ecx, ecx
471
        jnz     .read
472
  @@:
473
        ;Reset internal state machine
474
        mov     ax, 2
475
        mov     edx, [io_addr]
476
        add     edx, MAC_SM
477
        out     dx, ax
478
        xor     ax, ax
479
        out     dx, ax
480
        mov     esi, 5
481
        call    delay_ms
482
 
483
        ;MAC Bus Control Register
484
        mov     ax, MBCR_DEFAULT
485
        mov     edx, [io_addr]
486
        add     edx, MBCR
487
        out     dx, ax
488
 
489
        ;Buffer Size Register
490
        mov     ax, MAX_BUF_SIZE
491
        mov     edx, [io_addr]
492
        add     edx, MR_BSR
493
        out     dx, ax
494
 
495
        ;Write TX ring start address
496
        mov     eax, r6040_tx_ring - OS_BASE  ;Asper: Maybe we can just write dword? Hidnplayr: better use word, as described in datasheet.
497
        mov     edx, [io_addr]
498
        add     edx, MTD_SA0
499
        out     dx, ax
500
        shr     eax, 16
501
        add     edx, MTD_SA1 - MTD_SA0
502
        out     dx, ax
503
 
504
        ;Write RX ring start address
505
        mov     eax, r6040_rx_ring - OS_BASE  ;Asper: Maybe we can just write dword?
506
        mov     edx, [io_addr]
507
        add     edx, MRD_SA0
508
        out     dx, ax
509
        shr     eax, 16
510
        add     edx, MRD_SA1 - MRD_SA0
511
        out     dx, ax
512
 
513
        ;Set interrupt waiting time and packet numbers
514
        xor     ax, ax
515
        mov     edx, [io_addr]
516
        add     edx, MT_ICR
517
        out     dx, ax
518
 
519
        ;Asper: ~ Disable ints ;Enable interrupts
520
        ;mov     ax, MSK_INT ;INT_MASK  ;Asper ~
521
        ;mov     edx, [io_addr]
522
        ;add     edx, MIER
523
        ;out     dx, ax
524
 
525
        ;Enable TX and RX
526
        mov     ax, [r6040_private.mcr0]
527
        or      ax, 0x0002
528
        mov     edx, [io_addr]
529
        out     dx, ax
530
 
531
        ;Let TX poll the descriptors
532
        ;we may got called by r6040_tx_timeout which has left
533
        ;some unset tx buffers
534
        xor     ax, ax
535
        inc     ax
536
        mov     edx, [io_addr]
537
        add     edx, MTPR
538
        out     dx, ax
539
 
540
        pop     edx ecx eax
541
 
542
        DEBUGF  1, "reset ok!\n"
543
 
544
        ; Indicate that we have successfully reset the card
545
        mov     eax, [pci_data]
546
        mov     [eth_status], eax
547
        ret
548
 
549
 
550
 
551
proc r6040_tx_timeout
552
        push    eax edx
553
        ;...
554
        inc     [stats.tx_errors]
555
        ;Reset MAC and re-init all registers
556
        call    r6040_init_mac_regs
557
        pop     edx eax
558
        ret
559
endp
560
 
561
proc  r6040_get_stats
562
        push    eax edx
563
        mov     edx, [io_addr]
564
        add     edx, ME_CNT1
565
        in      al, dx
566
        add     [stats.rx_crc_errors], al
567
        mov     edx, [io_addr]
568
        add     edx, ME_CNT0
569
        in      al, dx
570
        add     [stats.multicast], al
571
        pop     edx eax
572
        ret
573
endp
574
 
575
;...
576
 
577
proc r6040_phy_mode_chk
578
        push    ebx
579
        ;PHY Link Status Check
580
        movzx   eax, [r6040_private.phy_addr]
581
        stdcall r6040_phy_read, eax, 1
582
        test    eax, 0x4
583
        jnz     @f
584
        mov     eax, 0x8000 ;Link Failed, full duplex
585
  @@:
586
        ;PHY Chip Auto-Negotiation Status
587
        movzx   eax, [r6040_private.phy_addr]
588
        stdcall r6040_phy_read, eax, 1
589
        test    eax, 0x0020
590
        jz      .force_mode
591
        ;Auto Negotuiation Mode
592
        movzx   eax, [r6040_private.phy_addr]
593
        stdcall r6040_phy_read, eax, 5
594
        mov     ebx, eax
595
        movzx   eax, [r6040_private.phy_addr]
596
        stdcall r6040_phy_read, eax, 4
597
        and     eax, ebx
598
        test    eax, 0x140
599
        jz      .ret_0
600
        jmp     .ret_0x8000
601
  .force_mode:
602
        ;Force Mode
603
        movzx   eax, [r6040_private.phy_addr]
604
        stdcall r6040_phy_read, eax, 0
605
        test    eax, 0x100
606
        jz      .ret_0
607
  .ret_0x8000:
608
        mov     eax, 0x8000
609
        pop     ebx
610
        ret
611
  .ret_0:
612
        xor     eax, eax
613
        pop     ebx
614
        ret
615
endp
616
 
617
 
618
 
619
;***************************************************************************
620
;   Function
621
;      r6040_rx
622
;   Description
623
;      polls card to see if there is a packet waiting
624
;
625
;  Currently only supports one descriptor per packet, if packet is fragmented
626
;  between multiple descriptors you will lose part of the packet
627
;***************************************************************************
628
r6040_poll:
629
        push    ebx ecx esi edi
630
 
631
        xor     eax, eax
632
        mov     [eth_rx_data_len], ax
633
 
634
        movzx   eax, [r6040_private.cur_rx]
635
        mov     ebx, eax
636
        shl     ebx, 5
637
 
638
        mov     cx, [ebx+r6040_rx_ring+r6040_x_head.status] ; Read the descriptor status
639
        test    cx, DSC_OWNER_MAC
640
        jnz     .out
641
 
642
        test    cx, DSC_RX_ERR  ; Global error status set
643
        jz      .no_dsc_rx_err
644
        ;...
645
        jmp     .out
646
 
647
    .no_dsc_rx_err:
648
        ; Packet successfully received
649
        movzx   ecx, [ebx+r6040_rx_ring+r6040_x_head.len]
650
        and     ecx, 0xFFF
651
        sub     ecx, 4    ; Do not count the CRC
652
        mov     [eth_rx_data_len], cx
653
        mov     esi, [ebx+r6040_rx_ring+r6040_x_head.skb_ptr]
654
 
655
        push    ecx
656
        shr     ecx, 2
657
        mov     edi, Ether_buffer
658
        cld
659
        rep movsd
660
        pop     ecx
661
        and     ecx, 3
662
        rep movsb
663
 
664
        or      [ebx+r6040_rx_ring+r6040_x_head.status], DSC_OWNER_MAC
665
 
666
        inc     [r6040_private.cur_rx]
667
        and     [r6040_private.cur_rx], RX_RING_SIZE-1
668
 
669
        xor     eax, eax
670
    .out:
671
        pop     edi esi ecx ebx
672
        ret
673
 
674
 
675
 
676
;***************************************************************************
677
;   Function
678
;      r6040_transmit
679
;   Description
680
;      Transmits a packet of data via the ethernet card
681
;         Pointer to 48 bit destination address in edi
682
;         Type of packet in bx
683
;         size of packet in ecx
684
;         pointer to packet data in esi
685
;
686
;***************************************************************************
687
r6040_transmit:
688
        cmp     ecx, MAX_BUF_SIZE
689
        jg      .out  ; packet is too long
690
 
691
        push    edi esi ebx ecx
692
 
693
        movzx   eax, [r6040_private.cur_tx]
694
        shl     eax, 5
695
 
696
;        DEBUGF  1,"R6040: TX buffer status: 0x%x, eax=%u\n", [eax + r6040_tx_ring + r6040_x_head.status]:4, eax
697
 
698
        test    [r6040_tx_ring + eax + r6040_x_head.status], 0x8000  ; check if buffer is available
699
        jz      .l3
700
 
701
        push    ecx esi
702
        mov     ecx, [timer_ticks]
703
        add     ecx, 100
704
     .l2:
705
        test    [r6040_tx_ring + eax + r6040_x_head.status], 0x8000
706
        jz      .l5
707
        cmp     ecx, [timer_ticks]
708
        jb      .l4
709
        mov     esi, 10
710
        call    delay_ms
711
        jmp     .l2
712
 
713
     .l4:
714
        pop     esi ecx
715
        DEBUGF  1,"R6040: Send timeout\n"
716
        jmp     .out
717
 
718
     .l5:
719
        pop     esi ecx
720
     .l3:
721
        push    eax
722
 
723
        mov     esi, edi
724
 
725
; point to the current tx buffer
726
        movzx   edi, [r6040_private.cur_tx]
727
        imul    edi, MAX_BUF_SIZE
728
        add     edi, r6040_txb
729
        lea     eax, [edi - OS_BASE]            ; real buffer address in eax
730
 
731
; copy destination address
732
        movsd
733
        movsw
734
; copy source address
735
        mov     esi, node_addr
736
        movsd
737
        movsw
738
; copy packet type
739
        mov     [edi], bx
740
        add     edi, 2
741
 
742
        mov     esi, [esp+8+4]
743
        mov     ecx, [esp+4]
744
; copy the packet data
745
        push    ecx
746
        shr     ecx, 2
747
        rep movsd
748
        pop     ecx
749
        and     ecx, 3
750
        rep movsb
751
 
752
        pop     edi
753
 
754
        mov     ecx, [esp]
755
        add     ecx, ETH_HLEN
756
        cmp     cx, ETH_ZLEN
757
        jae     @f
758
        mov     cx, ETH_ZLEN
759
    @@:
760
 
761
        mov     [r6040_tx_ring + edi + r6040_x_head.len], cx
762
        mov     [r6040_tx_ring + edi + r6040_x_head.buf], eax
763
        mov     [r6040_tx_ring + edi + r6040_x_head.status], 0x8000
764
 
765
        ; Trigger the MAC to check the TX descriptor
766
        mov     ax, 0x01
767
        mov     edx, [io_addr]
768
        add     edx, MTPR
769
        out     dx, ax
770
 
771
        inc     [r6040_private.cur_tx]
772
        and     [r6040_private.cur_tx], TX_RING_SIZE-1
773
        xor     eax, eax
774
 
775
        pop     ecx ebx esi edi
776
    .out:
777
        ret
778
 
779
 
780
 
781
r6040_mac_address:
782
        push    eax ecx edx esi edi
783
        ; MAC operation register
784
        mov     ax, 1
785
        mov     edx, [io_addr]
786
        add     edx, MCR1
787
        out     dx, ax
788
        ; Reset MAC
789
        mov     ax, 2
790
        mov     edx, [io_addr]
791
        add     edx, MAC_SM
792
        out     dx, ax
793
        ; Reset internal state machine
794
        xor     ax, ax
795
        out     dx, ax
796
        mov     esi, 5
797
        call    delay_ms
798
 
799
        ; Restore MAC Address
800
        mov     ecx, 3
801
        mov     edi, node_addr
802
        mov     edx, [io_addr]
803
        add     edx, MID_0L
804
     .mac:
805
        in      ax, dx
806
        stosw
807
        add     edx, 2
808
        dec     ecx
809
        jnz     .mac
810
 
811
        pop     edi esi edx ecx eax
812
        ret
813