Subversion Repositories Kolibri OS

Rev

Rev 5522 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2021. 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. ; TODO: test for RX-overrun
  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.         W_MAX_TIMEOUT           = 0x0FFF        ; max time out delay time
  33.  
  34.         TX_TIMEOUT              = 6000          ; Time before concluding the transmitter is hung, in ms
  35.  
  36.         TX_RING_SIZE            = 16            ; RING sizes must be a power of 2
  37.         RX_RING_SIZE            = 16
  38.  
  39.         RX_BUF_LEN_IDX          = 3             ; 0==8K, 1==16K, 2==32K, 3==64K
  40.  
  41. ; Threshold is bytes transferred to chip before transmission starts.
  42.  
  43.         TX_FIFO_THRESH          = 256           ; In bytes, rounded down to 32 byte units.
  44.  
  45. ; The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024.
  46.  
  47.         RX_FIFO_THRESH          = 4             ; Rx buffer level before first PCI xfer.
  48.         RX_DMA_BURST            = 4             ; Maximum PCI burst, '4' is 256 bytes
  49.         TX_DMA_BURST            = 4
  50.  
  51. section '.flat' readable writable executable
  52.  
  53. include '../proc32.inc'
  54. include '../struct.inc'
  55. include '../macros.inc'
  56. include '../fdo.inc'
  57. include '../netdrv.inc'
  58.  
  59. ; Operational parameters that usually are not changed.
  60.  
  61. PHY1_ADDR       = 1                     ; For MAC1
  62. PHY2_ADDR       = 3                     ; For MAC2
  63. PHY_MODE        = 0x3100                ; PHY CHIP Register 0
  64. PHY_CAP         = 0x01E1                ; PHY CHIP Register 4
  65.  
  66. ;**************************************************************************
  67. ; RDC R6040 Register Definitions
  68. ;**************************************************************************
  69.  
  70. MCR0            = 0x00                  ; Control register 0
  71. MCR0_RCVEN      = 0x0002                ; Receive enable
  72. MCR0_PROMISC    = 0x0020                ; Promiscuous mode
  73. MCR0_HASH_EN    = 0x0100                ; Enable multicast hash table function
  74. MCR0_XMTEN      = 0x1000                ; Transmission enable
  75. MCR0_FD         = 0x8000                ; Full/Half Duplex mode
  76.  
  77. MCR1            = 0x01                  ; Control register 1
  78. MAC_RST         = 0x0001                ; Reset the MAC
  79.  
  80. MBCR            = 0x08                  ; Bus control
  81. MT_ICR          = 0x0C                  ; TX interrupt control
  82. MR_ICR          = 0x10                  ; RX interrupt control
  83. MTPR            = 0x14                  ; TX poll command register
  84. MR_BSR          = 0x18                  ; RX buffer size
  85. MR_DCR          = 0x1A                  ; RX descriptor control
  86. MLSR            = 0x1C                  ; Last status
  87.  
  88. MMDIO           = 0x20                  ; MDIO control register
  89. MDIO_WRITE      = 0x4000                ; MDIO write
  90. MDIO_READ       = 0x2000                ; MDIO read
  91. MMRD            = 0x24                  ; MDIO read data register
  92. MMWD            = 0x28                  ; MDIO write data register
  93.  
  94. MTD_SA0         = 0x2C                  ; TX descriptor start address 0
  95. MTD_SA1         = 0x30                  ; TX descriptor start address 1
  96. MRD_SA0         = 0x34                  ; RX descriptor start address 0
  97. MRD_SA1         = 0x38                  ; RX descriptor start address 1
  98.  
  99. MISR            = 0x3C                  ; Status register
  100. MIER            = 0x40                  ; INT enable register
  101. MSK_INT         = 0x0000                ; Mask off interrupts
  102. RX_FINISH       = 0x0001                ; RX finished
  103. RX_NO_DESC      = 0x0002                ; No RX descriptor available
  104. RX_FIFO_FULL    = 0x0004                ; RX FIFO full
  105. RX_EARLY        = 0x0008                ; RX early
  106. TX_FINISH       = 0x0010                ; TX finished
  107. TX_EARLY        = 0x0080                ; TX early
  108. EVENT_OVRFL     = 0x0100                ; Event counter overflow
  109. LINK_CHANGED    = 0x0200                ; PHY link changed
  110.  
  111. ME_CISR         = 0x44                  ; Event counter INT status
  112. ME_CIER         = 0x48                  ; Event counter INT enable
  113. MR_CNT          = 0x50                  ; Successfully received packet counter
  114. ME_CNT0         = 0x52                  ; Event counter 0
  115. ME_CNT1         = 0x54                  ; Event counter 1
  116. ME_CNT2         = 0x56                  ; Event counter 2
  117. ME_CNT3         = 0x58                  ; Event counter 3
  118. MT_CNT          = 0x5A                  ; Successfully transmit packet counter
  119. ME_CNT4         = 0x5C                  ; Event counter 4
  120. MP_CNT          = 0x5E                  ; Pause frame counter register
  121. MAR0            = 0x60                  ; Hash table 0
  122. MAR1            = 0x62                  ; Hash table 1
  123. MAR2            = 0x64                  ; Hash table 2
  124. MAR3            = 0x66                  ; Hash table 3
  125. MID_0L          = 0x68                  ; Multicast address MID0 Low
  126. MID_0M          = 0x6A                  ; Multicast address MID0 Medium
  127. MID_0H          = 0x6C                  ; Multicast address MID0 High
  128. MID_1L          = 0x70                  ; MID1 Low
  129. MID_1M          = 0x72                  ; MID1 Medium
  130. MID_1H          = 0x74                  ; MID1 High
  131. MID_2L          = 0x78                  ; MID2 Low
  132. MID_2M          = 0x7A                  ; MID2 Medium
  133. MID_2H          = 0x7C                  ; MID2 High
  134. MID_3L          = 0x80                  ; MID3 Low
  135. MID_3M          = 0x82                  ; MID3 Medium
  136. MID_3H          = 0x84                  ; MID3 High
  137. PHY_CC          = 0x88                  ; PHY status change configuration register
  138. PHY_ST          = 0x8A                  ; PHY status register
  139. MAC_SM          = 0xAC                  ; MAC status machine
  140. MAC_ID          = 0xBE                  ; Identifier register
  141.  
  142. MAX_BUF_SIZE    = 1514
  143.  
  144. MBCR_DEFAULT    = 0x012A                ; MAC Bus Control Register
  145. MCAST_MAX       = 3                     ; Max number multicast addresses to filter
  146.  
  147. ;Descriptor status
  148. DSC_OWNER_MAC   = 0x8000                ; MAC is the owner of this descriptor
  149. DSC_RX_OK       = 0x4000                ; RX was successfull
  150. DSC_RX_ERR      = 0x0800                ; RX PHY error
  151. DSC_RX_ERR_DRI  = 0x0400                ; RX dribble packet
  152. DSC_RX_ERR_BUF  = 0x0200                ; RX length exceeds buffer size
  153. DSC_RX_ERR_LONG = 0x0100                ; RX length > maximum packet length
  154. DSC_RX_ERR_RUNT = 0x0080                ; RX packet length < 64 byte
  155. DSC_RX_ERR_CRC  = 0x0040                ; RX CRC error
  156. DSC_RX_BCAST    = 0x0020                ; RX broadcast (no error)
  157. DSC_RX_MCAST    = 0x0010                ; RX multicast (no error)
  158. DSC_RX_MCH_HIT  = 0x0008                ; RX multicast hit in hash table (no error)
  159. DSC_RX_MIDH_HIT = 0x0004                ; RX MID table hit (no error)
  160. DSC_RX_IDX_MID_MASK  = 3                ; RX mask for the index of matched MIDx
  161.  
  162. ;PHY settings
  163. ICPLUS_PHY_ID   = 0x0243
  164.  
  165. RX_INTS         = RX_FIFO_FULL or RX_NO_DESC or RX_FINISH
  166. TX_INTS         = TX_FINISH
  167. INT_MASK        = RX_INTS or TX_INTS
  168.  
  169. RX_BUF_LEN      equ (8192 << RX_BUF_LEN_IDX)    ; Size of the in-memory receive ring.
  170.  
  171. IO_SIZE         = 256       ; RDC MAC I/O Size
  172. MAX_MAC         = 2         ; MAX RDC MAC
  173.  
  174. struct  x_head
  175.  
  176.         status          dw ?   ;0-1
  177.         len             dw ?   ;2-3
  178.         buf             dd ?   ;4-7
  179.         ndesc           dd ?   ;8-B
  180.         rev1            dd ?   ;C-F
  181.         vbufp           dd ?   ;10-13
  182.         vndescp         dd ?   ;14-17
  183.         skb_ptr         dd ?   ;18-1B
  184.         rev2            dd ?   ;1C-1F
  185.  
  186. ends
  187.  
  188.  
  189. struct  device          ETH_DEVICE
  190.  
  191.         io_addr         dd ?
  192.         pci_bus         dd ?
  193.         pci_dev         dd ?
  194.         irq_line        db ?
  195.                         rb 3    ; align 4
  196.  
  197.         cur_rx          dw ?
  198.         cur_tx          dw ?
  199.         last_tx         dw ?
  200.         phy_addr        dd ?
  201.         phy_mode        dw ?
  202.         mcr0            dw ?
  203.         mcr1            dw ?
  204.         switch_sig      dw ?
  205.  
  206.         rb 0x100 - ($ and 0xff) ; align 256
  207.         tx_ring         rb ((TX_RING_SIZE*sizeof.x_head+32) and 0xfffffff0)
  208.         rx_ring         rb ((RX_RING_SIZE*sizeof.x_head+32) and 0xfffffff0)
  209.  
  210. ends
  211.  
  212.  
  213.  
  214. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  215. ;;                        ;;
  216. ;; proc START             ;;
  217. ;;                        ;;
  218. ;; (standard driver proc) ;;
  219. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  220.  
  221. proc START c, reason:dword, cmdline:dword
  222.  
  223.         cmp     [reason], DRV_ENTRY
  224.         jne     .fail
  225.  
  226.         DEBUGF  2,"Loading driver\n"
  227.         invoke  RegService, my_service, service_proc
  228.         ret
  229.  
  230.   .fail:
  231.         xor     eax, eax
  232.         ret
  233.  
  234. endp
  235.  
  236.  
  237. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  238. ;;                        ;;
  239. ;; proc SERVICE_PROC      ;;
  240. ;;                        ;;
  241. ;; (standard driver proc) ;;
  242. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  243.  
  244. proc service_proc stdcall, ioctl:dword
  245.  
  246.         mov     edx, [ioctl]
  247.         mov     eax, [edx + IOCTL.io_code]
  248.  
  249. ;------------------------------------------------------
  250.  
  251.         cmp     eax, 0 ;SRV_GETVERSION
  252.         jne     @F
  253.  
  254.         cmp     [edx + IOCTL.out_size], 4
  255.         jb      .fail
  256.         mov     eax, [edx + IOCTL.output]
  257.         mov     [eax], dword API_VERSION
  258.  
  259.         xor     eax, eax
  260.         ret
  261.  
  262. ;------------------------------------------------------
  263.   @@:
  264.         cmp     eax, 1 ;SRV_HOOK
  265.         jne     .fail
  266.  
  267.         cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
  268.         jb      .fail
  269.  
  270.         mov     eax, [edx + IOCTL.input]
  271.         cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
  272.         jne     .fail                                   ; other types arent supported for this card yet
  273.  
  274. ; check if the device is already listed
  275.  
  276.         mov     esi, device_list
  277.         mov     ecx, [devices]
  278.         test    ecx, ecx
  279.         jz      .firstdevice
  280.  
  281. ;        mov     eax, [edx + IOCTL.input]               ; get the pci bus and device numbers
  282.         mov     ax , [eax+1]                            ;
  283.   .nextdevice:
  284.         mov     ebx, [esi]
  285.         cmp     al, byte[ebx + device.pci_bus]
  286.         jne     @f
  287.         cmp     ah, byte[ebx + device.pci_dev]
  288.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  289.        @@:
  290.         add     esi, 4
  291.         loop    .nextdevice
  292.  
  293.  
  294. ; This device doesnt have its own eth_device structure yet, lets create one
  295.   .firstdevice:
  296.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  297.         jae     .fail
  298.  
  299.         allocate_and_clear ebx, sizeof.device, .fail    ; Allocate the buffer for device structure
  300.  
  301. ; Fill in the direct call addresses into the struct
  302.  
  303.         mov     [ebx + device.reset], reset
  304.         mov     [ebx + device.transmit], transmit
  305.         mov     [ebx + device.unload], unload
  306.         mov     [ebx + device.name], my_service
  307.  
  308. ; save the pci bus and device numbers
  309.  
  310.         mov     eax, [edx + IOCTL.input]
  311.         movzx   ecx, byte[eax+1]
  312.         mov     [ebx + device.pci_bus], ecx
  313.         movzx   ecx, byte[eax+2]
  314.         mov     [ebx + device.pci_dev], ecx
  315.  
  316. ; Now, it's time to find the base io addres of the PCI device
  317.  
  318.         stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
  319.         mov     [ebx + device.io_addr], eax
  320.  
  321. ; We've found the io address, find IRQ now
  322.  
  323.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
  324.         mov     [ebx + device.irq_line], al
  325.  
  326.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  327.         [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:8
  328.  
  329. ; Ok, the eth_device structure is ready, let's probe the device
  330.  
  331.         mov     eax, [devices]                                          ; Add the device structure to our device list
  332.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  333.         inc     [devices]                                               ;
  334.  
  335.         call    probe                                                   ; this function will output in eax
  336.         test    eax, eax
  337.         jnz     .err2
  338.  
  339.         DEBUGF  2,"Initialised OK\n"
  340.  
  341.         mov     [ebx + device.type], NET_TYPE_ETH
  342.         invoke  NetRegDev
  343.  
  344.         cmp     eax, -1
  345.         je      .destroy
  346.  
  347.         ret
  348.  
  349. ; If the device was already loaded, find the device number and return it in eax
  350.  
  351.   .find_devicenum:
  352.         DEBUGF  2,"Trying to find device number of already registered device\n"
  353.         invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  354.                                                                         ; into a device number in edi
  355.         mov     eax, edi                                                ; Application wants it in eax instead
  356.         DEBUGF  2,"Kernel says: %u\n", eax
  357.         ret
  358.  
  359. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  360.  
  361.   .destroy:
  362.         ; todo: reset device into virgin state
  363.  
  364.   .err2:
  365.         dec     [devices]
  366.   .err:
  367.         invoke  KernelFree, ebx
  368.   .fail:
  369.         DEBUGF  2, "Failed to load\n"
  370.         or      eax, -1
  371.         ret
  372.  
  373. ;------------------------------------------------------
  374. endp
  375.  
  376.  
  377. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  378. ;;                                                                        ;;
  379. ;;        Actual Hardware dependent code starts here                      ;;
  380. ;;                                                                        ;;
  381. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  382.  
  383.  
  384. align 4
  385. unload:
  386.         ; TODO: (in this particular order)
  387.         ;
  388.         ; - Stop the device
  389.         ; - Detach int handler
  390.         ; - Remove device from local list (device_list)
  391.         ; - call unregister function in kernel
  392.         ; - Remove all allocated structures and buffers the card used
  393.  
  394.         or      eax, -1
  395.         ret
  396.  
  397.  
  398. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  399. ;;
  400. ;;  probe: enables the device (if it really is R6040)
  401. ;;
  402. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  403.  
  404. align 4
  405. probe:
  406.         DEBUGF  1,"Probing\n"
  407.  
  408. ; Make the device a bus master
  409.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
  410.         or      al, PCI_CMD_MASTER
  411.         invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
  412.  
  413.         ; If PHY status change register is still set to zero
  414.         ; it means the bootloader didn't initialize it
  415.  
  416.         set_io  [ebx + device.io_addr], 0
  417.         set_io  [ebx + device.io_addr], PHY_CC
  418.         in      ax, dx
  419.         test    ax, ax
  420.         jnz     @f
  421.         mov     ax, 0x9F07
  422.         out     dx, ax
  423.   @@:
  424.  
  425.         call    read_mac
  426.  
  427.         ; Some bootloaders/BIOSes do not initialize MAC address, warn about that
  428.         and     eax, 0xFF
  429.         or      eax, dword [ebx + device.mac]
  430.         test    eax, eax
  431.         jnz     @f
  432.         DEBUGF  2, "MAC address not initialized!\n"
  433.  
  434.   @@:
  435.         ; Init RDC private data
  436.         mov     [ebx + device.mcr0], MCR0_XMTEN or MCR0_RCVEN
  437.         mov     [ebx + device.phy_addr], PHY1_ADDR
  438.         mov     [ebx + device.switch_sig], 0
  439.  
  440.         ; Check the vendor ID on the PHY, if 0xFFFF assume none attached
  441.         stdcall phy_read, [ebx + device.phy_addr], 2
  442.         cmp     ax, 0xFFFF
  443.         jne     @f
  444.         DEBUGF  2, "Failed to detect an attached PHY!\n"
  445.   .err:
  446.         mov     eax, -1
  447.         ret
  448.   @@:
  449.  
  450.         ; Set MAC address
  451.         call    init_mac_regs
  452.  
  453.         ; Initialize and alloc RX/TX buffers
  454.         call    init_txbufs
  455.         call    init_rxbufs
  456.         test    eax, eax
  457.         jnz     .err
  458.  
  459.         ; Read the PHY ID
  460.         mov     [ebx + device.phy_mode], MCR0_FD
  461.         stdcall phy_read, 0, 2
  462.         mov     [ebx + device.switch_sig], ax
  463.         cmp     ax, ICPLUS_PHY_ID
  464.         jne     @f
  465.         stdcall phy_write, 29, 31, 0x175C ; Enable registers
  466.         jmp     .phy_readen
  467.   @@:
  468.  
  469.         ; PHY Mode Check
  470.         stdcall phy_write, [ebx + device.phy_addr], 4, PHY_CAP
  471.         stdcall phy_write, [ebx + device.phy_addr], 0, PHY_MODE
  472.  
  473.       if PHY_MODE = 0x3100
  474.         call    phy_mode_chk
  475.         mov     [ebx + device.phy_mode], ax
  476.         jmp     .phy_readen
  477.       end if
  478.  
  479.       if not (PHY_MODE and 0x0100)
  480.         mov     [ebx + device.phy_mode], 0
  481.       end if
  482.  
  483.   .phy_readen:
  484.  
  485.         ; Set duplex mode
  486.         mov     ax, [ebx + device.phy_mode]
  487.         or      [ebx + device.mcr0], ax
  488.  
  489.         ; improve performance (by RDC guys)
  490.         stdcall phy_read, 30, 17
  491.         or      ax, 0x4000
  492.         stdcall phy_write, 30, 17, eax
  493.  
  494.         stdcall phy_read, 30, 17
  495.         and     ax, not 0x2000
  496.         stdcall phy_write, 30, 17, eax
  497.  
  498.         stdcall phy_write, 0, 19, 0x0000
  499.         stdcall phy_write, 0, 30, 0x01F0
  500.  
  501.         ; Initialize all Mac registers
  502.         call    init_mac_regs
  503.  
  504.  
  505. align 4
  506. reset:
  507.  
  508.         DEBUGF  1,"Resetting\n"
  509.  
  510.         ; Mask off Interrupt
  511.         xor     ax, ax
  512.         set_io  [ebx + device.io_addr], 0
  513.         set_io  [ebx + device.io_addr], MIER
  514.         out     dx, ax
  515.  
  516. ; attach int handler
  517.  
  518.         movzx   eax, [ebx + device.irq_line]
  519.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  520.         invoke  AttachIntHandler, eax, int_handler, ebx
  521.         test    eax, eax
  522.         jnz     @f
  523.         DEBUGF  2,"Could not attach int handler!\n"
  524.         or      eax, -1
  525.         ret
  526.   @@:
  527.  
  528.         ;Reset RDC MAC
  529.         mov     eax, MAC_RST
  530.         set_io  [ebx + device.io_addr], 0
  531.         set_io  [ebx + device.io_addr], MCR1
  532.         out     dx, ax
  533.  
  534.         mov     ecx, 2048 ;limit
  535.   .read:
  536.         in      ax, dx
  537.         test    ax, 0x1
  538.         jnz      @f
  539.         dec     ecx
  540.         test    ecx, ecx
  541.         jnz     .read
  542.   @@:
  543.         ;Reset internal state machine
  544.         mov     ax,  2
  545.         set_io  [ebx + device.io_addr], MAC_SM
  546.         out     dx, ax
  547.  
  548.         xor     ax, ax
  549.         out     dx, ax
  550.  
  551.         mov     esi, 5
  552.         invoke  Sleep
  553.  
  554.         ;MAC Bus Control Register
  555.         mov     ax, MBCR_DEFAULT
  556.         set_io  [ebx + device.io_addr], 0
  557.         set_io  [ebx + device.io_addr], MBCR
  558.         out     dx, ax
  559.  
  560.         ;Buffer Size Register
  561.         mov     ax, MAX_BUF_SIZE
  562.         set_io  [ebx + device.io_addr], MR_BSR
  563.         out     dx, ax
  564.  
  565.         ;Write TX ring start address
  566.         lea     eax, [ebx + device.tx_ring]
  567.         invoke  GetPhysAddr
  568.         set_io  [ebx + device.io_addr], MTD_SA0
  569.         out     dx, ax
  570.         shr     eax, 16
  571.         set_io  [ebx + device.io_addr], MTD_SA1
  572.         out     dx, ax
  573.  
  574.         ;Write RX ring start address
  575.         lea     eax, [ebx + device.rx_ring]
  576.         invoke  GetPhysAddr
  577.         set_io  [ebx + device.io_addr], MRD_SA0
  578.         out     dx, ax
  579.         shr     eax, 16
  580.         set_io  [ebx + device.io_addr], MRD_SA1
  581.         out     dx, ax
  582.  
  583.         ;Set interrupt waiting time and packet numbers
  584.         xor     ax, ax
  585.         set_io  [ebx + device.io_addr], MT_ICR
  586.         out     dx, ax
  587.  
  588.         ;Enable interrupts
  589.         mov     ax, INT_MASK
  590.         set_io  [ebx + device.io_addr], MIER
  591.         out     dx, ax
  592.  
  593.         ;Enable RX
  594.         mov     ax, [ebx + device.mcr0]
  595.         or      ax, MCR0_RCVEN
  596.         set_io  [ebx + device.io_addr], MCR0
  597.         out     dx, ax
  598.  
  599.         ;Let TX poll the descriptors
  600.         ;we may got called by tx_timeout which has left some unset tx buffers
  601.         xor     ax, ax
  602.         inc     ax
  603.         set_io  [ebx + device.io_addr], MTPR
  604.         out     dx, ax
  605.  
  606. ; Set the mtu, kernel will be able to send now
  607.         mov     [ebx + device.mtu], 1514
  608.  
  609. ; Set link state to unknown
  610.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  611.  
  612.         DEBUGF  1,"Reset ok\n"
  613.         xor     eax, eax
  614.         ret
  615.  
  616.  
  617.  
  618. align 4
  619. init_txbufs:
  620.  
  621.         DEBUGF  1,"Init TxBufs\n"
  622.  
  623.         lea     esi, [ebx + device.tx_ring]
  624.         lea     eax, [ebx + device.tx_ring + sizeof.x_head]
  625.         invoke  GetPhysAddr
  626.         mov     ecx, TX_RING_SIZE
  627.  
  628.   .next_desc:
  629.         mov     [esi + x_head.ndesc], eax
  630.         mov     [esi + x_head.skb_ptr], 0
  631.         mov     [esi + x_head.status], DSC_OWNER_MAC
  632.         add     eax, sizeof.x_head
  633.         add     esi, sizeof.x_head
  634.         dec     ecx
  635.         jnz     .next_desc
  636.  
  637.         lea     eax, [ebx + device.tx_ring]
  638.         invoke  GetPhysAddr
  639.         mov     dword[ebx + device.tx_ring + sizeof.x_head*(TX_RING_SIZE-1) + x_head.ndesc], eax
  640.  
  641.         ret
  642.  
  643.  
  644.  
  645. align 4
  646. init_rxbufs:
  647.  
  648.         DEBUGF  1,"Init RxBufs\n"
  649.  
  650.         lea     esi, [ebx + device.rx_ring]
  651.         lea     eax, [ebx + device.rx_ring + sizeof.x_head]
  652.         invoke  GetPhysAddr
  653.         mov     edx, eax
  654.         mov     ecx, RX_RING_SIZE
  655.  
  656.   .next_desc:
  657.         mov     [esi + x_head.ndesc], edx
  658.         push    esi ecx edx
  659.         invoke  NetAlloc, MAX_BUF_SIZE+NET_BUFF.data
  660.         pop     edx ecx esi
  661.         test    eax, eax
  662.         jz      .out_of_mem
  663.         mov     [esi + x_head.skb_ptr], eax
  664.         invoke  GetPhysAddr
  665.         add     eax, NET_BUFF.data
  666.         mov     [esi + x_head.buf], eax
  667.         mov     [esi + x_head.status], DSC_OWNER_MAC
  668.  
  669.         add     edx, sizeof.x_head
  670.         add     esi, sizeof.x_head
  671.         dec     ecx
  672.         jnz     .next_desc
  673.  
  674. ; complete the ring by linking the last to the first
  675.         lea     eax, [ebx + device.rx_ring]
  676.         invoke  GetPhysAddr
  677.         mov     dword[ebx + device.rx_ring + sizeof.x_head*(RX_RING_SIZE-1) + x_head.ndesc], eax
  678.  
  679.         xor     eax, eax
  680.         ret
  681.  
  682.   .out_of_mem:
  683.         or      eax, -1
  684.         ret
  685.  
  686.  
  687.  
  688. align 4
  689. phy_mode_chk:
  690.  
  691.         DEBUGF  1,"Checking PHY mode\n"
  692.  
  693.         ; PHY Link Status Check
  694.         stdcall phy_read, [ebx + device.phy_addr], MII_BMSR
  695.         test    ax, BMSR_LSTATUS
  696.         jz      .ret_0x8000
  697.  
  698.         ; PHY Chip Auto-Negotiation Status
  699.         test    ax, BMSR_ANEGCOMPLETE
  700.         jnz     .auto_nego
  701.  
  702.         ; Force Mode
  703.         stdcall phy_read, [ebx + device.phy_addr], MII_BMCR
  704.         test    ax, BMCR_FULLDPLX
  705.         jnz     .ret_0x8000
  706.  
  707.   .auto_nego:
  708.         ; Auto Negotiation Mode
  709.         stdcall phy_read, [ebx + device.phy_addr], MII_LPA
  710.         mov     cx, ax
  711.         stdcall phy_read, [ebx + device.phy_addr], MII_ADVERTISE
  712.         and     ax, cx
  713.         test    ax, ADVERTISE_10FULL + ADVERTISE_100FULL
  714.         jnz     .ret_0x8000
  715.  
  716.         xor     eax, eax
  717.         ret
  718.  
  719.   .ret_0x8000:
  720.         mov     eax, 0x8000
  721.         ret
  722.  
  723.  
  724.  
  725.  
  726.  
  727. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  728. ;;                                         ;;
  729. ;; Transmit                                ;;
  730. ;;                                         ;;
  731. ;; In: pointer to device structure in ebx  ;;
  732. ;; Out: eax = 0 on success                 ;;
  733. ;;                                         ;;
  734. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  735. align 16
  736. proc transmit stdcall bufferptr
  737.  
  738.         spin_lock_irqsave
  739.  
  740.         mov     esi, [bufferptr]
  741.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
  742.         lea     eax, [esi + NET_BUFF.data]
  743.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  744.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  745.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  746.         [eax+13]:2,[eax+12]:2
  747.  
  748.         cmp     [esi + NET_BUFF.length], 1514
  749.         ja      .error
  750.         cmp     [esi + NET_BUFF.length], 60
  751.         jb      .error
  752.  
  753.         movzx   edi, [ebx + device.cur_tx]
  754.         shl     edi, 5
  755.         add     edi, ebx
  756.         add     edi, device.tx_ring
  757.  
  758.         DEBUGF  1,"TX buffer status: 0x%x\n", [edi + x_head.status]:4
  759.  
  760.         test    [edi + x_head.status], DSC_OWNER_MAC    ; check if buffer is available
  761.         jnz     .overrun
  762.  
  763.         mov     [edi + x_head.skb_ptr], esi
  764.         mov     eax, esi
  765.         add     eax, [eax + NET_BUFF.offset]
  766.         invoke  GetPhysAddr
  767.         mov     [edi + x_head.buf], eax
  768.         mov     ecx, [esi + NET_BUFF.length]
  769.         mov     [edi + x_head.len], cx
  770.         mov     [edi + x_head.status], DSC_OWNER_MAC
  771.  
  772.         ; Trigger the MAC to check the TX descriptor
  773.         mov     ax, 0x01
  774.         set_io  [ebx + device.io_addr], 0
  775.         set_io  [ebx + device.io_addr], MTPR
  776.         out     dx, ax
  777.  
  778.         inc     [ebx + device.cur_tx]
  779.         and     [ebx + device.cur_tx], TX_RING_SIZE - 1
  780.  
  781. ; Update stats
  782.         inc     [ebx + device.packets_tx]
  783.         mov     eax, [esi + NET_BUFF.length]
  784.         add     dword[ebx + device.bytes_tx], eax
  785.         adc     dword[ebx + device.bytes_tx + 4], 0
  786.  
  787.         spin_unlock_irqrestore
  788.         xor     eax, eax
  789.         ret
  790.  
  791.   .error:
  792.         DEBUGF  2, "TX packet error\n"
  793.         inc     [ebx + device.packets_tx_err]
  794.         invoke  NetFree, [bufferptr]
  795.  
  796.         spin_unlock_irqrestore
  797.         or      eax, -1
  798.         ret
  799.  
  800.   .overrun:
  801.         DEBUGF  2, "TX overrun\n"
  802.         inc     [ebx + device.packets_tx_ovr]
  803.         invoke  NetFree, [bufferptr]
  804.  
  805.         spin_unlock_irqrestore
  806.         or      eax, -1
  807.         ret
  808.  
  809. endp
  810.  
  811.  
  812.  
  813. ;;;;;;;;;;;;;;;;;;;;;;;
  814. ;;                   ;;
  815. ;; Interrupt handler ;;
  816. ;;                   ;;
  817. ;;;;;;;;;;;;;;;;;;;;;;;
  818. align 16
  819. int_handler:
  820.  
  821.         push    ebx esi edi
  822.  
  823.         mov     ebx, [esp+4*4]
  824.         DEBUGF  1,"INT for 0x%x\n", ebx
  825.  
  826. ; TODO? if we are paranoid, we can check that the value from ebx is present in the current device_list
  827.  
  828.         set_io  [ebx + device.io_addr], 0
  829.         set_io  [ebx + device.io_addr], MISR
  830.         in      ax, dx
  831.         test    ax, ax
  832.         jz      .nothing
  833.  
  834.         out     dx, ax                  ; ACK interrupt
  835.         DEBUGF  1,"Status: %x\n", ax
  836.  
  837.         push ax
  838.  
  839.         test    word[esp], RX_FINISH
  840.         jz      .no_RX
  841.  
  842.         push    ebx
  843.   .more_RX:
  844.         pop     ebx
  845.  
  846.         ; Find the current RX descriptor
  847.         movzx   edx, [ebx + device.cur_rx]
  848.         shl     edx, 5
  849.         lea     edx, [ebx + device.rx_ring + edx]
  850.  
  851.         ; Check the descriptor status
  852.         mov     cx, [edx + x_head.status]
  853.         test    cx, DSC_OWNER_MAC
  854.         jnz     .no_RX
  855.  
  856.         DEBUGF  1,"packet status=0x%x\n", cx
  857.  
  858.         test    cx, DSC_RX_ERR          ; Global error status set
  859.         jnz     .no_RX
  860.  
  861.         ; Packet successfully received
  862.         movzx   ecx, [edx + x_head.len]
  863.         and     ecx, 0xFFF
  864.         sub     ecx, 4                  ; Do not count the CRC
  865.  
  866.         DEBUGF  1,"packet ptr=0x%x size=%u\n", [edx + x_head.skb_ptr], ecx
  867.  
  868.         ; Update stats
  869.         add     dword[ebx + device.bytes_rx], ecx
  870.         adc     dword[ebx + device.bytes_rx + 4], 0
  871.         inc     dword[ebx + device.packets_rx]
  872.  
  873.         push    ebx
  874.         ; Push packet ptr and return addr for Eth_input
  875.         push    .more_RX
  876.         mov     eax, [edx + x_head.skb_ptr]
  877.         push    eax
  878.         mov     [eax + NET_BUFF.length], ecx
  879.         mov     [eax + NET_BUFF.device], ebx
  880.         mov     [eax + NET_BUFF.offset], NET_BUFF.data
  881.  
  882.         ; reset the RX descriptor (alloc new buffer)
  883.         push    edx
  884.         invoke  NetAlloc, MAX_BUF_SIZE+NET_BUFF.data
  885.         pop     edx
  886.         mov     [edx + x_head.skb_ptr], eax
  887.         invoke  GetPhysAddr
  888.         add     eax, NET_BUFF.data
  889.         mov     [edx + x_head.buf], eax
  890.         mov     [edx + x_head.status], DSC_OWNER_MAC
  891.  
  892.         ; Use next descriptor next time
  893.         inc     [ebx + device.cur_rx]
  894.         and     [ebx + device.cur_rx], RX_RING_SIZE - 1
  895.  
  896.         ; At last, send packet to kernel
  897.         jmp     [EthInput]
  898.   .no_RX:
  899.  
  900.         test    word[esp], TX_FINISH
  901.         jz      .no_TX
  902.   .loop_tx:
  903.         movzx   edi, [ebx + device.last_tx]
  904.         shl     edi, 5
  905.         lea     edi, [ebx + device.tx_ring + edi]
  906.  
  907.         test    [edi + x_head.status], DSC_OWNER_MAC
  908.         jnz     .no_TX
  909.  
  910.         cmp     [edi + x_head.skb_ptr], 0
  911.         je      .no_TX
  912.  
  913.         DEBUGF  1,"Freeing buffer 0x%x\n", [edi + x_head.skb_ptr]
  914.  
  915.         push    [edi + x_head.skb_ptr]
  916.         mov     [edi + x_head.skb_ptr], 0
  917.         invoke  NetFree
  918.  
  919.         inc     [ebx + device.last_tx]
  920.         and     [ebx + device.last_tx], TX_RING_SIZE - 1
  921.  
  922.         jmp     .loop_tx
  923.   .no_TX:
  924.  
  925.         test    word[esp], RX_NO_DESC
  926.         jz      .no_rxdesc
  927.  
  928.         DEBUGF  2, "No more RX descriptors!\n"
  929.   .no_rxdesc:
  930.  
  931.         test    word[esp], RX_FIFO_FULL
  932.         jz      .no_rxfifo
  933.  
  934.         DEBUGF  2, "RX FIFO full!\n"
  935.   .no_rxfifo:
  936.  
  937.         test    word[esp], RX_EARLY
  938.         jz      .no_rxearly
  939.  
  940.         DEBUGF  2, "RX early\n"
  941.   .no_rxearly:
  942.  
  943.         test    word[esp], TX_EARLY
  944.         jz      .no_txearly
  945.  
  946.         DEBUGF  2, "TX early\n"
  947.   .no_txearly:
  948.  
  949.         test    word[esp], EVENT_OVRFL
  950.         jz      .no_ovrfl
  951.  
  952.         DEBUGF  2, "Event counter overflow!\n"
  953.   .no_ovrfl:
  954.  
  955.         test    word[esp], LINK_CHANGED
  956.         jz      .no_link
  957.  
  958.         DEBUGF  2, "Link changed\n"
  959.   .no_link:
  960.  
  961.         pop     ax
  962.  
  963.         pop     edi esi ebx
  964.         xor     eax, eax
  965.         inc     eax
  966.  
  967.         ret
  968.  
  969.   .nothing:
  970.         pop     edi esi ebx
  971.         xor     eax, eax
  972.  
  973.         ret
  974.  
  975.  
  976.  
  977.  
  978. align 4
  979. init_mac_regs:
  980.  
  981.         DEBUGF  1,"initializing MAC regs\n"
  982.  
  983.         ; MAC operation register
  984.         mov     ax, 1
  985.         set_io  [ebx + device.io_addr], 0
  986.         set_io  [ebx + device.io_addr], MCR1
  987.         out     dx, ax
  988.         ; Reset MAC
  989.         mov     ax, 2
  990.         set_io  [ebx + device.io_addr], MAC_SM
  991.         out     dx, ax
  992.         ; Reset internal state machine
  993.         xor     ax, ax
  994.         out     dx, ax
  995.         mov     esi, 5
  996.         invoke  Sleep
  997.  
  998.         call    read_mac
  999.  
  1000.         ret
  1001.  
  1002.  
  1003.  
  1004.  
  1005. ; Read a word data from PHY Chip
  1006.  
  1007. align 4
  1008. proc  phy_read stdcall, phy_addr:dword, reg:dword
  1009.  
  1010.         DEBUGF  1,"PHY read, addr=0x%x reg=0x%x\n", [phy_addr]:8, [reg]:8
  1011.  
  1012.         mov     eax, [phy_addr]
  1013.         shl     eax, 8
  1014.         add     eax, [reg]
  1015.         add     eax, MDIO_READ
  1016.         set_io  [ebx + device.io_addr], 0
  1017.         set_io  [ebx + device.io_addr], MMDIO
  1018.         out     dx, ax
  1019.  
  1020.         ;Wait for the read bit to be cleared.
  1021.         mov     ecx, 2048 ;limit
  1022.   .read:
  1023.         in      ax, dx
  1024.         test    ax, MDIO_READ
  1025.         jz      @f
  1026.         dec     ecx
  1027.         jnz     .read
  1028.   @@:
  1029.  
  1030.         set_io  [ebx + device.io_addr],   MMRD
  1031.         in      ax, dx
  1032.         and     eax, 0xFFFF
  1033.  
  1034.         DEBUGF  1,"PHY read, val=0x%x\n", eax:4
  1035.  
  1036.         ret
  1037.  
  1038. endp
  1039.  
  1040.  
  1041.  
  1042.  
  1043. ; Write a word data to PHY Chip
  1044.  
  1045. align 4
  1046. proc  phy_write stdcall, phy_addr:dword, reg:dword, val:dword
  1047.  
  1048.         DEBUGF  1,"PHY write, addr=0x%x reg=0x%x val=0x%x\n", \
  1049.         [phy_addr]:8, [reg]:8, [val]:8
  1050.  
  1051.         mov     eax, [val]
  1052.         set_io  [ebx + device.io_addr], 0
  1053.         set_io  [ebx + device.io_addr], MMWD
  1054.         out     dx, ax
  1055.  
  1056.         ;Write the command to the MDIO bus
  1057.         mov     eax, [phy_addr]
  1058.         shl     eax, 8
  1059.         add     eax, [reg]
  1060.         add     eax, MDIO_WRITE
  1061.         set_io  [ebx + device.io_addr], MMDIO
  1062.         out     dx, ax
  1063.  
  1064.         ;Wait for the write bit to be cleared.
  1065.         mov     ecx, 2048 ;limit
  1066.   .write:
  1067.         in      ax, dx
  1068.         test    ax, MDIO_WRITE
  1069.         jz      @f
  1070.         dec     ecx
  1071.         jnz     .write
  1072.   @@:
  1073.  
  1074.         DEBUGF  1,"PHY write ok\n"
  1075.  
  1076.         ret
  1077. endp
  1078.  
  1079.  
  1080.  
  1081. align 4
  1082. read_mac:
  1083.  
  1084.         DEBUGF  1,"Reading MAC:\n"
  1085.  
  1086.         mov     cx, 3
  1087.         lea     edi, [ebx + device.mac]
  1088.         set_io  [ebx + device.io_addr], 0
  1089.         set_io  [ebx + device.io_addr], MID_0L
  1090.   .loop:
  1091.         in      ax, dx
  1092.         stosw
  1093.         inc     dx
  1094.         inc     dx
  1095.         dec     cx
  1096.         jnz     .loop
  1097.  
  1098.         DEBUGF  1,"%x-%x-%x-%x-%x-%x\n",\
  1099.         [edi-6]:2, [edi-5]:2, [edi-4]:2, [edi-3]:2, [edi-2]:2, [edi-1]:2
  1100.  
  1101.         ret
  1102.  
  1103.  
  1104.  
  1105.  
  1106. ; End of code
  1107.  
  1108. data fixups
  1109. end data
  1110.  
  1111. include '../peimport.inc'
  1112.  
  1113. my_service      db 'R6040',0                    ; max 16 chars include zero
  1114.  
  1115. include_debug_strings
  1116.  
  1117. align 4
  1118. devices         dd 0
  1119. device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
  1120.  
  1121.