Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
2010 serge 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
 
2434 Serge 33
TX_RING_SIZE    equ 4
34
RX_RING_SIZE    equ 4
2010 serge 35
 
36
; ethernet address length
2434 Serge 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
2010 serge 41
; system timer frequency
2434 Serge 42
HZ              equ 1000
2010 serge 43
 
44
; max time out delay time
2434 Serge 45
W_MAX_TIMEOUT   equ 0x0FFF
2010 serge 46
 
47
;; Size of the in-memory receive ring.
2434 Serge 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)
2010 serge 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.
2434 Serge 57
TX_FIFO_THRESH  equ 256     ;; In bytes, rounded down to 32 byte units.
2010 serge 58
 
59
;; The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024.
2434 Serge 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
2010 serge 63
 
64
;; Operational parameters that usually are not changed.
2434 Serge 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
2010 serge 69
 
70
;; Time in jiffies before concluding the transmitter is hung.
2434 Serge 71
TX_TIMEOUT      equ ((6000*HZ)/1000)
2010 serge 72
 
2434 Serge 73
R6040_IO_SIZE   equ 256     ; RDC MAC I/O Size
74
MAX_MAC         equ 2       ; MAX RDC MAC
2010 serge 75
 
76
;**************************************************************************
77
; RDC R6040 Register Definitions
78
;**************************************************************************
2434 Serge 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
2010 serge 139
 
2434 Serge 140
MAX_BUF_SIZE    equ 0x600   ;1536
2010 serge 141
 
2434 Serge 142
MBCR_DEFAULT    equ 0x012A  ;MAC Bus Control Register
143
MCAST_MAX       equ 3       ;Max number multicast addresses to filter
2010 serge 144
 
145
;Descriptor status
2434 Serge 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
2010 serge 151
DSC_RX_ERR_LONG equ 0x0100  ;RX length > maximum packet length
152
DSC_RX_ERR_RUNT equ 0x0080  ;RX packet length < 64 byte
2434 Serge 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)
2010 serge 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
2434 Serge 161
ICPLUS_PHY_ID   equ 0x0243
2010 serge 162
 
2434 Serge 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
2010 serge 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:
2434 Serge 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 ?
2010 serge 184
end virtual
185
 
186
virtual at 0
187
r6040_x_head:
2434 Serge 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
2010 serge 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
2434 Serge 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
2010 serge 215
  .read:
2434 Serge 216
        in      ax, dx
217
        test    ax, MDIO_READ
218
        jz      @f
219
        dec     ecx
220
        test    ecx, ecx
221
        jnz     .read
2010 serge 222
  @@:
2434 Serge 223
        mov     edx, [io_addr]
224
        add     edx, MMRD
225
        in      ax, dx
226
        and     eax, 0xFFFF
227
        pop     edx ecx
228
        ret
2010 serge 229
endp
230
 
231
; Write a word data to PHY Chip
232
proc  r6040_phy_write stdcall, phy_addr:dword, reg:dword, val:dword
2434 Serge 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
2010 serge 249
  .write:
2434 Serge 250
        in      ax, dx
251
        test    ax, MDIO_WRITE
252
        jz      @f
253
        dec     ecx
254
        test    ecx, ecx
255
        jnz     .write
2010 serge 256
  @@:
2434 Serge 257
        pop     edx ecx eax
258
        ret
2010 serge 259
endp
260
 
261
macro r6040_mdio_write reg, val {
2434 Serge 262
        stdcall r6040_phy_read, [io_addr], [r6040_private.phy_addr], reg
2010 serge 263
}
264
 
265
macro r6040_mdio_write reg, val {
2434 Serge 266
        stdcall r6040_phy_write, [io_addr], [r6040_private.phy_addr], reg, val
2010 serge 267
}
268
 
269
 
270
proc r6040_init_ring_desc stdcall, desc_ring:dword, size:dword
2434 Serge 271
        push    eax ecx esi
272
        mov     ecx, [size]
273
        test    ecx, ecx
274
        jz      .out
2010 serge 275
 
2434 Serge 276
        mov     esi, [desc_ring]
277
        mov     eax, esi
2010 serge 278
    .next_desc:
2434 Serge 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
2010 serge 286
 
2434 Serge 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
2010 serge 292
    .out:
2434 Serge 293
        pop     esi ecx eax
294
        ret
2010 serge 295
endp
296
 
297
 
298
 
299
 
300
r6040_init_rxbufs:
301
 
2434 Serge 302
        stdcall r6040_init_ring_desc, r6040_rx_ring, RX_RING_SIZE
2010 serge 303
 
2434 Serge 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
2010 serge 309
    .next_desc:
2434 Serge 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
2010 serge 314
 
2434 Serge 315
        mov     eax, [esi+r6040_x_head.vndescp]
316
        mov     esi, eax
2010 serge 317
 
2434 Serge 318
        add     ebx, MAX_BUF_SIZE
319
        dec     ecx
320
        jnz     .next_desc
2010 serge 321
 
2434 Serge 322
        xor     eax, eax
2010 serge 323
    .out:
324
 
2434 Serge 325
        ret
2010 serge 326
 
327
 
328
r6040_probe:
329
 
2434 Serge 330
        DEBUGF  1, "Probing r6040\n"
2010 serge 331
 
2434 Serge 332
        call    adjust_pci_device
2010 serge 333
 
334
 
2434 Serge 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
2010 serge 344
     @@:
2434 Serge 345
        ; Set MAC address
346
        mov     ecx, 3
347
        mov     edi, node_addr
348
        mov     edx, [io_addr]
349
        add     edx, MID_0L
2010 serge 350
     .mac:
2434 Serge 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
2010 serge 367
     @@:
2434 Serge 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
2010 serge 372
 
2434 Serge 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
2010 serge 380
     @@:
381
 
2434 Serge 382
        ; Set MAC address
383
        call    r6040_mac_address
2010 serge 384
 
385
 
2434 Serge 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
2010 serge 391
 
2434 Serge 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
2010 serge 400
      @@:
401
 
2434 Serge 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
2010 serge 406
;      if PHY_MODE = 0x3100
2434 Serge 407
        call    r6040_phy_mode_chk
408
        mov     [r6040_private.phy_mode], ax
409
        jmp     .phy_readen
2010 serge 410
;      end if
411
;      if not (PHY_MODE and 0x0100)
2434 Serge 412
        mov     [r6040_private.phy_mode], 0
2010 serge 413
;      end if
414
      .phy_readen:
415
 
2434 Serge 416
        ; Set duplex mode
417
        mov     ax, [r6040_private.phy_mode]
418
        or      [r6040_private.mcr0], ax
2010 serge 419
 
2434 Serge 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
2010 serge 424
 
2434 Serge 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
2010 serge 430
 
2434 Serge 431
        stdcall r6040_phy_write, 0, 19, 0x0000
432
        stdcall r6040_phy_write, 0, 30, 0x01F0
2010 serge 433
 
2434 Serge 434
        ; Initialize all Mac registers
435
        call    r6040_reset
2010 serge 436
 
2434 Serge 437
        xor     eax, eax
2010 serge 438
      .out:
2434 Serge 439
        ret
2010 serge 440
 
441
 
442
 
443
 
444
 
445
 
446
align 4
447
r6040_reset:
448
 
2434 Serge 449
        DEBUGF  1, "Resetting r6040\n"
2010 serge 450
 
2434 Serge 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
2010 serge 457
 
2434 Serge 458
        ;Reset RDC MAC
459
        mov     eax, MAC_RST
460
        mov     edx, [io_addr]
461
        add     edx, MCR1
462
        out     dx, ax
2010 serge 463
 
2434 Serge 464
        mov     ecx, 2048 ;limit
2010 serge 465
  .read:
2434 Serge 466
        in      ax, dx
467
        test    ax, 0x1
468
        jnz     @f
469
        dec     ecx
470
        test    ecx, ecx
471
        jnz     .read
2010 serge 472
  @@:
2434 Serge 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
2010 serge 482
 
2434 Serge 483
        ;MAC Bus Control Register
484
        mov     ax, MBCR_DEFAULT
485
        mov     edx, [io_addr]
486
        add     edx, MBCR
487
        out     dx, ax
2010 serge 488
 
2434 Serge 489
        ;Buffer Size Register
490
        mov     ax, MAX_BUF_SIZE
491
        mov     edx, [io_addr]
492
        add     edx, MR_BSR
493
        out     dx, ax
2010 serge 494
 
2434 Serge 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
2010 serge 503
 
2434 Serge 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
2010 serge 512
 
2434 Serge 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
2010 serge 518
 
2434 Serge 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
2010 serge 524
 
2434 Serge 525
        ;Enable TX and RX
526
        mov     ax, [r6040_private.mcr0]
527
        or      ax, 0x0002
528
        mov     edx, [io_addr]
529
        out     dx, ax
2010 serge 530
 
2434 Serge 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
2010 serge 539
 
2434 Serge 540
        pop     edx ecx eax
2010 serge 541
 
2434 Serge 542
        DEBUGF  1, "reset ok!\n"
2010 serge 543
 
2434 Serge 544
        ; Indicate that we have successfully reset the card
545
        mov     eax, [pci_data]
546
        mov     [eth_status], eax
547
        ret
2010 serge 548
 
549
 
550
 
551
proc r6040_tx_timeout
2434 Serge 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
2010 serge 559
endp
560
 
561
proc  r6040_get_stats
2434 Serge 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
2010 serge 573
endp
574
 
575
;...
576
 
577
proc r6040_phy_mode_chk
2434 Serge 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
2010 serge 585
  @@:
2434 Serge 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
2010 serge 601
  .force_mode:
2434 Serge 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
2010 serge 607
  .ret_0x8000:
2434 Serge 608
        mov     eax, 0x8000
609
        pop     ebx
610
        ret
2010 serge 611
  .ret_0:
2434 Serge 612
        xor     eax, eax
613
        pop     ebx
614
        ret
2010 serge 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:
2434 Serge 629
        push    ebx ecx esi edi
2010 serge 630
 
2434 Serge 631
        xor     eax, eax
632
        mov     [eth_rx_data_len], ax
2010 serge 633
 
2434 Serge 634
        movzx   eax, [r6040_private.cur_rx]
635
        mov     ebx, eax
636
        shl     ebx, 5
2010 serge 637
 
2434 Serge 638
        mov     cx, [ebx+r6040_rx_ring+r6040_x_head.status] ; Read the descriptor status
639
        test    cx, DSC_OWNER_MAC
640
        jnz     .out
2010 serge 641
 
2434 Serge 642
        test    cx, DSC_RX_ERR  ; Global error status set
643
        jz      .no_dsc_rx_err
644
        ;...
645
        jmp     .out
2010 serge 646
 
647
    .no_dsc_rx_err:
2434 Serge 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]
2010 serge 654
 
2434 Serge 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
2010 serge 663
 
2434 Serge 664
        or      [ebx+r6040_rx_ring+r6040_x_head.status], DSC_OWNER_MAC
2010 serge 665
 
2434 Serge 666
        inc     [r6040_private.cur_rx]
667
        and     [r6040_private.cur_rx], RX_RING_SIZE-1
2010 serge 668
 
2434 Serge 669
        xor     eax, eax
2010 serge 670
    .out:
2434 Serge 671
        pop     edi esi ecx ebx
672
        ret
2010 serge 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:
2434 Serge 688
        cmp     ecx, MAX_BUF_SIZE
689
        jg      .out  ; packet is too long
2010 serge 690
 
2434 Serge 691
        push    edi esi ebx ecx
2010 serge 692
 
2434 Serge 693
        movzx   eax, [r6040_private.cur_tx]
694
        shl     eax, 5
2010 serge 695
 
696
;        DEBUGF  1,"R6040: TX buffer status: 0x%x, eax=%u\n", [eax + r6040_tx_ring + r6040_x_head.status]:4, eax
697
 
2434 Serge 698
        test    [r6040_tx_ring + eax + r6040_x_head.status], 0x8000  ; check if buffer is available
699
        jz      .l3
2010 serge 700
 
2434 Serge 701
        push    ecx esi
702
        mov     ecx, [timer_ticks]
703
        add     ecx, 100
2010 serge 704
     .l2:
2434 Serge 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
2010 serge 712
 
713
     .l4:
2434 Serge 714
        pop     esi ecx
715
        DEBUGF  1,"R6040: Send timeout\n"
716
        jmp     .out
2010 serge 717
 
718
     .l5:
2434 Serge 719
        pop     esi ecx
2010 serge 720
     .l3:
2434 Serge 721
        push    eax
2010 serge 722
 
2434 Serge 723
        mov     esi, edi
2010 serge 724
 
725
; point to the current tx buffer
2434 Serge 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
2010 serge 730
 
731
; copy destination address
2434 Serge 732
        movsd
733
        movsw
2010 serge 734
; copy source address
2434 Serge 735
        mov     esi, node_addr
736
        movsd
737
        movsw
2010 serge 738
; copy packet type
2434 Serge 739
        mov     [edi], bx
740
        add     edi, 2
2010 serge 741
 
2434 Serge 742
        mov     esi, [esp+8+4]
743
        mov     ecx, [esp+4]
2010 serge 744
; copy the packet data
2434 Serge 745
        push    ecx
746
        shr     ecx, 2
747
        rep movsd
748
        pop     ecx
749
        and     ecx, 3
750
        rep movsb
2010 serge 751
 
2434 Serge 752
        pop     edi
2010 serge 753
 
2434 Serge 754
        mov     ecx, [esp]
755
        add     ecx, ETH_HLEN
756
        cmp     cx, ETH_ZLEN
757
        jae     @f
758
        mov     cx, ETH_ZLEN
2010 serge 759
    @@:
760
 
2434 Serge 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
2010 serge 764
 
2434 Serge 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
2010 serge 770
 
2434 Serge 771
        inc     [r6040_private.cur_tx]
772
        and     [r6040_private.cur_tx], TX_RING_SIZE-1
773
        xor     eax, eax
2010 serge 774
 
2434 Serge 775
        pop     ecx ebx esi edi
2010 serge 776
    .out:
2434 Serge 777
        ret
2010 serge 778
 
779
 
780
 
781
r6040_mac_address:
2434 Serge 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
2010 serge 798
 
2434 Serge 799
        ; Restore MAC Address
800
        mov     ecx, 3
801
        mov     edi, node_addr
802
        mov     edx, [io_addr]
803
        add     edx, MID_0L
2010 serge 804
     .mac:
2434 Serge 805
        in      ax, dx
806
        stosw
807
        add     edx, 2
808
        dec     ecx
809
        jnz     .mac
2010 serge 810
 
2434 Serge 811
        pop     edi esi edx ecx eax
812
        ret
2010 serge 813