Subversion Repositories Kolibri OS

Rev

Rev 2010 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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.  
  814.