Subversion Repositories Kolibri OS

Rev

Rev 4470 | Rev 5074 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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