Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. 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.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    = 1514
  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  2,"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.         DEBUGF  2,"Initialised OK\n"
  338.  
  339.         mov     [ebx + device.type], NET_TYPE_ETH
  340.         invoke  NetRegDev
  341.  
  342.         cmp     eax, -1
  343.         je      .destroy
  344.  
  345.         ret
  346.  
  347. ; If the device was already loaded, find the device number and return it in eax
  348.  
  349.   .find_devicenum:
  350.         DEBUGF  2,"Trying to find device number of already registered device\n"
  351.         invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  352.                                                                         ; into a device number in edi
  353.         mov     eax, edi                                                ; Application wants it in eax instead
  354.         DEBUGF  2,"Kernel says: %u\n", eax
  355.         ret
  356.  
  357. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  358.  
  359.   .destroy:
  360.         ; todo: reset device into virgin state
  361.  
  362.   .err2:
  363.         dec     [devices]
  364.   .err:
  365.         invoke  KernelFree, ebx
  366.   .fail:
  367.         DEBUGF  2, "Failed to load\n"
  368.         or      eax, -1
  369.         ret
  370.  
  371. ;------------------------------------------------------
  372. endp
  373.  
  374.  
  375. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  376. ;;                                                                        ;;
  377. ;;        Actual Hardware dependent code starts here                      ;;
  378. ;;                                                                        ;;
  379. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  380.  
  381.  
  382. ;mdio_read:
  383. ;        stdcall phy_read, [ebx + device.io_addr], [ebx + device.phy_addr], ecx
  384.  
  385. ;        ret
  386.  
  387. ;mdio_write:
  388. ;        stdcall phy_write, [ebx + device.io_addr], [ebx + device.phy_addr], ecx, eax
  389.  
  390. ;        ret
  391.  
  392.  
  393. align 4
  394. unload:
  395.         ; TODO: (in this particular order)
  396.         ;
  397.         ; - Stop the device
  398.         ; - Detach int handler
  399.         ; - Remove device from local list (device_list)
  400.         ; - call unregister function in kernel
  401.         ; - Remove all allocated structures and buffers the card used
  402.  
  403.         or      eax, -1
  404.         ret
  405.  
  406.  
  407. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  408. ;;
  409. ;;  probe: enables the device (if it really is R6040)
  410. ;;
  411. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  412.  
  413. align 4
  414. probe:
  415.         DEBUGF  1,"Probing\n"
  416.  
  417. ; Make the device a bus master
  418.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
  419.         or      al, PCI_CMD_MASTER
  420.         invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
  421.  
  422.         ; If PHY status change register is still set to zero
  423.         ; it means the bootloader didn't initialize it
  424.  
  425.         set_io  [ebx + device.io_addr], 0
  426.         set_io  [ebx + device.io_addr], PHY_CC
  427.         in      ax, dx
  428.         test    ax, ax
  429.         jnz     @f
  430.         mov     ax, 0x9F07
  431.         out     dx, ax
  432.   @@:
  433.  
  434.         call    read_mac
  435.  
  436.         ; Some bootloaders/BIOSes do not initialize MAC address, warn about that
  437.         and     eax, 0xFF
  438.         or      eax, dword [ebx + device.mac]
  439.         test    eax, eax
  440.         jnz     @f
  441.         DEBUGF  2, "MAC address not initialized!\n"
  442.  
  443.   @@:
  444.         ; Init RDC private data
  445.         mov     [ebx + device.mcr0], MCR0_XMTEN or MCR0_RCVEN
  446.         mov     [ebx + device.phy_addr], PHY1_ADDR
  447.         mov     [ebx + device.switch_sig], 0
  448.  
  449.         ; Check the vendor ID on the PHY, if 0xFFFF assume none attached
  450.         stdcall phy_read, [ebx + device.phy_addr], 2
  451.         cmp     ax, 0xFFFF
  452.         jne     @f
  453.         DEBUGF  2, "Failed to detect an attached PHY!\n"
  454.   .err:
  455.         mov     eax, -1
  456.         ret
  457.   @@:
  458.  
  459.         ; Set MAC address
  460.         call    init_mac_regs
  461.  
  462.         ; Initialize and alloc RX/TX buffers
  463.         call    init_txbufs
  464.         call    init_rxbufs
  465.         test    eax, eax
  466.         jnz     .err
  467.  
  468.         ; Read the PHY ID
  469.         mov     [ebx + device.phy_mode], MCR0_FD
  470.         stdcall phy_read, 0, 2
  471.         mov     [ebx + device.switch_sig], ax
  472.         cmp     ax, ICPLUS_PHY_ID
  473.         jne     @f
  474.         stdcall phy_write, 29, 31, 0x175C ; Enable registers
  475.         jmp     .phy_readen
  476.   @@:
  477.  
  478.         ; PHY Mode Check
  479.         stdcall phy_write, [ebx + device.phy_addr], 4, PHY_CAP
  480.         stdcall phy_write, [ebx + device.phy_addr], 0, PHY_MODE
  481.  
  482.       if PHY_MODE = 0x3100
  483.         call    phy_mode_chk
  484.         mov     [ebx + device.phy_mode], ax
  485.         jmp     .phy_readen
  486.       end if
  487.  
  488.       if not (PHY_MODE and 0x0100)
  489.         mov     [ebx + device.phy_mode], 0
  490.       end if
  491.  
  492.   .phy_readen:
  493.  
  494.         ; Set duplex mode
  495.         mov     ax, [ebx + device.phy_mode]
  496.         or      [ebx + device.mcr0], ax
  497.  
  498.         ; improve performance (by RDC guys)
  499.         stdcall phy_read, 30, 17
  500.         or      ax, 0x4000
  501.         stdcall phy_write, 30, 17, eax
  502.  
  503.         stdcall phy_read, 30, 17
  504.         and     ax, not 0x2000
  505.         stdcall phy_write, 30, 17, eax
  506.  
  507.         stdcall phy_write, 0, 19, 0x0000
  508.         stdcall phy_write, 0, 30, 0x01F0
  509.  
  510.         ; Initialize all Mac registers
  511.         call    init_mac_regs
  512.  
  513.  
  514. align 4
  515. reset:
  516.  
  517.         DEBUGF  1,"Resetting\n"
  518.  
  519.         ; Mask off Interrupt
  520.         xor     ax, ax
  521.         set_io  [ebx + device.io_addr], 0
  522.         set_io  [ebx + device.io_addr], MIER
  523.         out     dx, ax
  524.  
  525. ; attach int handler
  526.  
  527.         movzx   eax, [ebx + device.irq_line]
  528.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  529.         invoke  AttachIntHandler, eax, int_handler, ebx
  530.         test    eax, eax
  531.         jnz     @f
  532.         DEBUGF  2,"Could not attach int handler!\n"
  533.         or      eax, -1
  534.         ret
  535.   @@:
  536.  
  537.         ;Reset RDC MAC
  538.         mov     eax, MAC_RST
  539.         set_io  [ebx + device.io_addr], 0
  540.         set_io  [ebx + device.io_addr], MCR1
  541.         out     dx, ax
  542.  
  543.         mov     ecx, 2048 ;limit
  544.   .read:
  545.         in      ax, dx
  546.         test    ax, 0x1
  547.         jnz      @f
  548.         dec     ecx
  549.         test    ecx, ecx
  550.         jnz     .read
  551.   @@:
  552.         ;Reset internal state machine
  553.         mov     ax,  2
  554.         set_io  [ebx + device.io_addr], MAC_SM
  555.         out     dx, ax
  556.  
  557.         xor     ax, ax
  558.         out     dx, ax
  559.  
  560.         mov     esi, 5
  561.         invoke  Sleep
  562.  
  563.         ;MAC Bus Control Register
  564.         mov     ax, MBCR_DEFAULT
  565.         set_io  [ebx + device.io_addr], 0
  566.         set_io  [ebx + device.io_addr], MBCR
  567.         out     dx, ax
  568.  
  569.         ;Buffer Size Register
  570.         mov     ax, MAX_BUF_SIZE
  571.         set_io  [ebx + device.io_addr], MR_BSR
  572.         out     dx, ax
  573.  
  574.         ;Write TX ring start address
  575.         lea     eax, [ebx + device.tx_ring]
  576.         invoke  GetPhysAddr
  577.         set_io  [ebx + device.io_addr], MTD_SA0
  578.         out     dx, ax
  579.         shr     eax, 16
  580.         set_io  [ebx + device.io_addr], MTD_SA1
  581.         out     dx, ax
  582.  
  583.         ;Write RX ring start address
  584.         lea     eax, [ebx + device.rx_ring]
  585.         invoke  GetPhysAddr
  586.         set_io  [ebx + device.io_addr], MRD_SA0
  587.         out     dx, ax
  588.         shr     eax, 16
  589.         set_io  [ebx + device.io_addr], MRD_SA1
  590.         out     dx, ax
  591.  
  592.         ;Set interrupt waiting time and packet numbers
  593.         xor     ax, ax
  594.         set_io  [ebx + device.io_addr], MT_ICR
  595.         out     dx, ax
  596.  
  597.         ;Enable interrupts
  598.         mov     ax, INT_MASK
  599.         set_io  [ebx + device.io_addr], MIER
  600.         out     dx, ax
  601.  
  602.         ;Enable RX
  603.         mov     ax, [ebx + device.mcr0]
  604.         or      ax, MCR0_RCVEN
  605.         set_io  [ebx + device.io_addr], 0
  606.         out     dx, ax
  607.  
  608.         ;Let TX poll the descriptors
  609.         ;we may got called by tx_timeout which has left some unset tx buffers
  610.         xor     ax, ax
  611.         inc     ax
  612.         set_io  [ebx + device.io_addr], MTPR
  613.         out     dx, ax
  614.  
  615. ; Set the mtu, kernel will be able to send now
  616.         mov     [ebx + device.mtu], 1514
  617.  
  618. ; Set link state to unknown
  619.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  620.  
  621.         DEBUGF  1,"Reset ok\n"
  622.         xor     eax, eax
  623.         ret
  624.  
  625.  
  626.  
  627. align 4
  628. init_txbufs:
  629.  
  630.         DEBUGF  1,"Init TxBufs\n"
  631.  
  632.         lea     esi, [ebx + device.tx_ring]
  633.         lea     eax, [ebx + device.tx_ring + sizeof.x_head]
  634.         invoke  GetPhysAddr
  635.         mov     ecx, TX_RING_SIZE
  636.  
  637.   .next_desc:
  638.         mov     [esi + x_head.ndesc], eax
  639.         mov     [esi + x_head.skb_ptr], 0
  640.         mov     [esi + x_head.status], DSC_OWNER_MAC
  641.         add     eax, sizeof.x_head
  642.         add     esi, sizeof.x_head
  643.         dec     ecx
  644.         jnz     .next_desc
  645.  
  646.         lea     eax, [ebx + device.tx_ring]
  647.         invoke  GetPhysAddr
  648.         mov     dword[ebx + device.tx_ring + sizeof.x_head*(TX_RING_SIZE-1) + x_head.ndesc], eax
  649.  
  650.         ret
  651.  
  652.  
  653.  
  654. align 4
  655. init_rxbufs:
  656.  
  657.         DEBUGF  1,"Init RxBufs\n"
  658.  
  659.         lea     esi, [ebx + device.rx_ring]
  660.         lea     eax, [ebx + device.rx_ring + sizeof.x_head]
  661.         invoke  GetPhysAddr
  662.         mov     edx, eax
  663.         mov     ecx, RX_RING_SIZE
  664.  
  665.   .next_desc:
  666.         mov     [esi + x_head.ndesc], edx
  667.         push    esi ecx edx
  668.         invoke  NetAlloc, MAX_BUF_SIZE+NET_BUFF.data
  669.         pop     edx ecx esi
  670.         test    eax, eax
  671.         jz      .out_of_mem
  672.         mov     [esi + x_head.skb_ptr], eax
  673.         invoke  GetPhysAddr
  674.         add     eax, NET_BUFF.data
  675.         mov     [esi + x_head.buf], eax
  676.         mov     [esi + x_head.status], DSC_OWNER_MAC
  677.  
  678.         add     edx, sizeof.x_head
  679.         add     esi, sizeof.x_head
  680.         dec     ecx
  681.         jnz     .next_desc
  682.  
  683. ; complete the ring by linking the last to the first
  684.         lea     eax, [ebx + device.rx_ring]
  685.         invoke  GetPhysAddr
  686.         mov     dword[ebx + device.rx_ring + sizeof.x_head*(RX_RING_SIZE-1) + x_head.ndesc], eax
  687.  
  688.         xor     eax, eax
  689.         ret
  690.  
  691.   .out_of_mem:
  692.         or      eax, -1
  693.         ret
  694.  
  695.  
  696.  
  697. align 4
  698. phy_mode_chk:
  699.  
  700.         DEBUGF  1,"Checking PHY mode\n"
  701.  
  702.         ; PHY Link Status Check
  703.         stdcall phy_read, [ebx + device.phy_addr], MII_BMSR
  704.         test    ax, BMSR_LSTATUS
  705.         jz      .ret_0x8000
  706.  
  707.         ; PHY Chip Auto-Negotiation Status
  708.         test    ax, BMSR_ANEGCOMPLETE
  709.         jnz     .auto_nego
  710.  
  711.         ; Force Mode
  712.         stdcall phy_read, [ebx + device.phy_addr], MII_BMCR
  713.         test    ax, BMCR_FULLDPLX
  714.         jnz     .ret_0x8000
  715.  
  716.   .auto_nego:
  717.         ; Auto Negotiation Mode
  718.         stdcall phy_read, [ebx + device.phy_addr], MII_LPA
  719.         mov     cx, ax
  720.         stdcall phy_read, [ebx + device.phy_addr], MII_ADVERTISE
  721.         and     ax, cx
  722.         test    ax, ADVERTISE_10FULL + ADVERTISE_100FULL
  723.         jnz     .ret_0x8000
  724.  
  725.         xor     eax, eax
  726.         ret
  727.  
  728.   .ret_0x8000:
  729.         mov     eax, 0x8000
  730.         ret
  731.  
  732.  
  733.  
  734.  
  735.  
  736. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  737. ;;                                         ;;
  738. ;; Transmit                                ;;
  739. ;;                                         ;;
  740. ;; In: pointer to device structure in ebx  ;;
  741. ;;                                         ;;
  742. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  743.  
  744. proc transmit stdcall bufferptr
  745.  
  746.         pushf
  747.         cli
  748.  
  749.         mov     esi, [bufferptr]
  750.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
  751.         lea     eax, [esi + NET_BUFF.data]
  752.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  753.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  754.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  755.         [eax+13]:2,[eax+12]:2
  756.  
  757.         cmp     [esi + NET_BUFF.length], 1514
  758.         ja      .fail
  759.         cmp     [esi + NET_BUFF.length], 60
  760.         jb      .fail
  761.  
  762.         movzx   edi, [ebx + device.cur_tx]
  763.         shl     edi, 5
  764.         add     edi, ebx
  765.         add     edi, device.tx_ring
  766.  
  767.         DEBUGF  1,"TX buffer status: 0x%x\n", [edi + x_head.status]:4
  768.  
  769.         test    [edi + x_head.status], DSC_OWNER_MAC    ; check if buffer is available
  770.         jnz     .wait_to_send
  771.  
  772.   .do_send:
  773.         DEBUGF  1,"Sending now\n"
  774.  
  775.         mov     [edi + x_head.skb_ptr], esi
  776.         mov     eax, esi
  777.         add     eax, [eax + NET_BUFF.offset]
  778.         invoke  GetPhysAddr
  779.         mov     [edi + x_head.buf], eax
  780.         mov     ecx, [esi + NET_BUFF.length]
  781.         mov     [edi + x_head.len], cx
  782.         mov     [edi + x_head.status], DSC_OWNER_MAC
  783.  
  784.         ; Trigger the MAC to check the TX descriptor
  785.         mov     ax, 0x01
  786.         set_io  [ebx + device.io_addr], 0
  787.         set_io  [ebx + device.io_addr], MTPR
  788.         out     dx, ax
  789.  
  790.         inc     [ebx + device.cur_tx]
  791.         and     [ebx + device.cur_tx], TX_RING_SIZE - 1
  792.  
  793. ; Update stats
  794.         inc     [ebx + device.packets_tx]
  795.         mov     eax, [esi + NET_BUFF.length]
  796.         add     dword[ebx + device.bytes_tx], eax
  797.         adc     dword[ebx + device.bytes_tx + 4], 0
  798.  
  799.         popf
  800.         xor     eax, eax
  801.         ret
  802.  
  803.   .wait_to_send:
  804.         DEBUGF  1,"Waiting for TX buffer\n"
  805.         invoke  GetTimerTicks           ; returns in eax
  806.         lea     edx, [eax + 100]
  807.   .l2:
  808.         mov     esi, [bufferptr]
  809.         test    [edi + x_head.status], DSC_OWNER_MAC
  810.         jz      .do_send
  811.         popf
  812.         mov     esi, 10
  813.         invoke  Sleep
  814.         invoke  GetTimerTicks
  815.         pushf
  816.         cli
  817.         cmp     edx, eax
  818.         jb      .l2
  819.  
  820.         DEBUGF  2,"Send timeout\n"
  821.   .fail:
  822.         DEBUGF  2,"Send failed\n"
  823.         invoke  NetFree, [bufferptr]
  824.         popf
  825.         or      eax, -1
  826.         ret
  827.  
  828. endp
  829.  
  830.  
  831.  
  832. ;;;;;;;;;;;;;;;;;;;;;;;
  833. ;;                   ;;
  834. ;; Interrupt handler ;;
  835. ;;                   ;;
  836. ;;;;;;;;;;;;;;;;;;;;;;;
  837.  
  838. align 4
  839. int_handler:
  840.  
  841.         push    ebx esi edi
  842.  
  843.         DEBUGF  1,"int\n"
  844.  
  845. ; Find pointer of device wich made IRQ occur
  846.  
  847.         mov     ecx, [devices]
  848.         test    ecx, ecx
  849.         jz      .nothing
  850.         mov     esi, device_list
  851.   .nextdevice:
  852.         mov     ebx, [esi]
  853.  
  854.         set_io  [ebx + device.io_addr], 0
  855.         set_io  [ebx + device.io_addr], MISR
  856.         in      ax, dx
  857.         out     dx, ax                  ; send it back to ACK
  858.         test    ax, ax
  859.         jnz     .got_it
  860.   .continue:
  861.         add     esi, 4
  862.         dec     ecx
  863.         jnz     .nextdevice
  864.   .nothing:
  865.         pop     edi esi ebx
  866.         xor     eax, eax
  867.  
  868.         ret                             ; If no device was found, abort
  869.  
  870. ; At this point, test for all possible reasons, and handle accordingly
  871.  
  872.   .got_it:
  873.  
  874.         DEBUGF  1,"Device: %x Status: %x\n", ebx, ax
  875.  
  876.         push ax
  877.  
  878.         test    word[esp], RX_FINISH
  879.         jz      .no_RX
  880.  
  881.         push    ebx
  882.   .more_RX:
  883.         pop     ebx
  884.  
  885.         ; Find the current RX descriptor
  886.         movzx   edx, [ebx + device.cur_rx]
  887.         shl     edx, 5
  888.         lea     edx, [ebx + device.rx_ring + edx]
  889.  
  890.         ; Check the descriptor status
  891.         mov     cx, [edx + x_head.status]
  892.         test    cx, DSC_OWNER_MAC
  893.         jnz     .no_RX
  894.  
  895.         DEBUGF  1,"packet status=0x%x\n", cx
  896.  
  897.         test    cx, DSC_RX_ERR          ; Global error status set
  898.         jnz     .no_RX
  899.  
  900.         ; Packet successfully received
  901.         movzx   ecx, [edx + x_head.len]
  902.         and     ecx, 0xFFF
  903.         sub     ecx, 4                  ; Do not count the CRC
  904.  
  905.         DEBUGF  1,"packet ptr=0x%x size=%u\n", [edx + x_head.skb_ptr], ecx
  906.  
  907.         ; Update stats
  908.         add     dword[ebx + device.bytes_rx], ecx
  909.         adc     dword[ebx + device.bytes_rx + 4], 0
  910.         inc     dword[ebx + device.packets_rx]
  911.  
  912.         push    ebx
  913.         ; Push packet ptr and return addr for Eth_input
  914.         push    .more_RX
  915.         mov     eax, [edx + x_head.skb_ptr]
  916.         push    eax
  917.         mov     [eax + NET_BUFF.length], ecx
  918.         mov     [eax + NET_BUFF.device], ebx
  919.         mov     [eax + NET_BUFF.offset], NET_BUFF.data
  920.  
  921.         ; reset the RX descriptor (alloc new buffer)
  922.         push    edx
  923.         invoke  NetAlloc, MAX_BUF_SIZE+NET_BUFF.data
  924.         pop     edx
  925.         mov     [edx + x_head.skb_ptr], eax
  926.         invoke  GetPhysAddr
  927.         add     eax, NET_BUFF.data
  928.         mov     [edx + x_head.buf], eax
  929.         mov     [edx + x_head.status], DSC_OWNER_MAC
  930.  
  931.         ; Use next descriptor next time
  932.         inc     [ebx + device.cur_rx]
  933.         and     [ebx + device.cur_rx], RX_RING_SIZE - 1
  934.  
  935.         ; At last, send packet to kernel
  936.         jmp     [EthInput]
  937.  
  938.  
  939.   .no_RX:
  940.         test    word[esp], TX_FINISH
  941.         jz      .no_TX
  942.  
  943.   .loop_tx:
  944.         movzx   edi, [ebx + device.last_tx]
  945.         shl     edi, 5
  946.         lea     edi, [ebx + device.tx_ring + edi]
  947.  
  948.         test    [edi + x_head.status], DSC_OWNER_MAC
  949.         jnz     .no_TX
  950.  
  951.         cmp     [edi + x_head.skb_ptr], 0
  952.         je      .no_TX
  953.  
  954.         DEBUGF  1,"Freeing buffer 0x%x\n", [edi + x_head.skb_ptr]
  955.  
  956.         push    [edi + x_head.skb_ptr]
  957.         mov     [edi + x_head.skb_ptr], 0
  958.         invoke  NetFree
  959.  
  960.         inc     [ebx + device.last_tx]
  961.         and     [ebx + device.last_tx], TX_RING_SIZE - 1
  962.  
  963.         jmp     .loop_tx
  964.  
  965.   .no_TX:
  966.         test    word[esp], RX_NO_DESC
  967.         jz      .no_rxdesc
  968.  
  969.         DEBUGF  2, "No more RX descriptors!\n"
  970.  
  971.   .no_rxdesc:
  972.         test    word[esp], RX_FIFO_FULL
  973.         jz      .no_rxfifo
  974.  
  975.         DEBUGF  2, "RX FIFO full!\n"
  976.  
  977.   .no_rxfifo:
  978.         test    word[esp], RX_EARLY
  979.         jz      .no_rxearly
  980.  
  981.         DEBUGF  2, "RX early\n"
  982.  
  983.   .no_rxearly:
  984.         test    word[esp], TX_EARLY
  985.         jz      .no_txearly
  986.  
  987.         DEBUGF  2, "TX early\n"
  988.  
  989.   .no_txearly:
  990.         test    word[esp], EVENT_OVRFL
  991.         jz      .no_ovrfl
  992.  
  993.         DEBUGF  2, "Event counter overflow!\n"
  994.  
  995.   .no_ovrfl:
  996.         test    word[esp], LINK_CHANGED
  997.         jz      .no_link
  998.  
  999.         DEBUGF  2, "Link changed\n"
  1000.  
  1001.   .no_link:
  1002.         pop     ax
  1003.  
  1004.         pop     edi esi ebx
  1005.  
  1006.         ret
  1007.  
  1008.  
  1009.  
  1010.  
  1011. align 4
  1012. init_mac_regs:
  1013.  
  1014.         DEBUGF  1,"initializing MAC regs\n"
  1015.  
  1016.         ; MAC operation register
  1017.         mov     ax, 1
  1018.         set_io  [ebx + device.io_addr], 0
  1019.         set_io  [ebx + device.io_addr], MCR1
  1020.         out     dx, ax
  1021.         ; Reset MAC
  1022.         mov     ax, 2
  1023.         set_io  [ebx + device.io_addr], MAC_SM
  1024.         out     dx, ax
  1025.         ; Reset internal state machine
  1026.         xor     ax, ax
  1027.         out     dx, ax
  1028.         mov     esi, 5
  1029.         invoke  Sleep
  1030.  
  1031.         call    read_mac
  1032.  
  1033.         ret
  1034.  
  1035.  
  1036.  
  1037.  
  1038. ; Read a word data from PHY Chip
  1039.  
  1040. align 4
  1041. proc  phy_read stdcall, phy_addr:dword, reg:dword
  1042.  
  1043.         DEBUGF  1,"PHY read, addr=0x%x reg=0x%x\n", [phy_addr]:8, [reg]:8
  1044.  
  1045.         mov     eax, [phy_addr]
  1046.         shl     eax, 8
  1047.         add     eax, [reg]
  1048.         add     eax, MDIO_READ
  1049.         set_io  [ebx + device.io_addr], 0
  1050.         set_io  [ebx + device.io_addr], MMDIO
  1051.         out     dx, ax
  1052.  
  1053.         ;Wait for the read bit to be cleared.
  1054.         mov     ecx, 2048 ;limit
  1055.   .read:
  1056.         in      ax, dx
  1057.         test    ax, MDIO_READ
  1058.         jz      @f
  1059.         dec     ecx
  1060.         jnz     .read
  1061.   @@:
  1062.  
  1063.         set_io  [ebx + device.io_addr],   MMRD
  1064.         in      ax, dx
  1065.         and     eax, 0xFFFF
  1066.  
  1067.         DEBUGF  1,"PHY read, val=0x%x\n", eax:4
  1068.  
  1069.         ret
  1070.  
  1071. endp
  1072.  
  1073.  
  1074.  
  1075.  
  1076. ; Write a word data to PHY Chip
  1077.  
  1078. align 4
  1079. proc  phy_write stdcall, phy_addr:dword, reg:dword, val:dword
  1080.  
  1081.         DEBUGF  1,"PHY write, addr=0x%x reg=0x%x val=0x%x\n", \
  1082.         [phy_addr]:8, [reg]:8, [val]:8
  1083.  
  1084.         mov     eax, [val]
  1085.         set_io  [ebx + device.io_addr], 0
  1086.         set_io  [ebx + device.io_addr], MMWD
  1087.         out     dx, ax
  1088.  
  1089.         ;Write the command to the MDIO bus
  1090.         mov     eax, [phy_addr]
  1091.         shl     eax, 8
  1092.         add     eax, [reg]
  1093.         add     eax, MDIO_WRITE
  1094.         set_io  [ebx + device.io_addr], MMDIO
  1095.         out     dx, ax
  1096.  
  1097.         ;Wait for the write bit to be cleared.
  1098.         mov     ecx, 2048 ;limit
  1099.   .write:
  1100.         in      ax, dx
  1101.         test    ax, MDIO_WRITE
  1102.         jz      @f
  1103.         dec     ecx
  1104.         jnz     .write
  1105.   @@:
  1106.  
  1107.         DEBUGF  1,"PHY write ok\n"
  1108.  
  1109.         ret
  1110. endp
  1111.  
  1112.  
  1113.  
  1114. align 4
  1115. read_mac:
  1116.  
  1117.         DEBUGF  1,"Reading MAC:\n"
  1118.  
  1119.         mov     cx, 3
  1120.         lea     edi, [ebx + device.mac]
  1121.         set_io  [ebx + device.io_addr], 0
  1122.         set_io  [ebx + device.io_addr], MID_0L
  1123.   .loop:
  1124.         in      ax, dx
  1125.         stosw
  1126.         inc     dx
  1127.         inc     dx
  1128.         dec     cx
  1129.         jnz     .loop
  1130.  
  1131.         DEBUGF  1,"%x-%x-%x-%x-%x-%x\n",\
  1132.         [edi-6]:2, [edi-5]:2, [edi-4]:2, [edi-3]:2, [edi-2]:2, [edi-1]:2
  1133.  
  1134.         ret
  1135.  
  1136.  
  1137.  
  1138.  
  1139. ; End of code
  1140.  
  1141. data fixups
  1142. end data
  1143.  
  1144. include '../peimport.inc'
  1145.  
  1146. my_service      db 'R6040',0                    ; max 16 chars include zero
  1147.  
  1148. include_debug_strings
  1149.  
  1150. align 4
  1151. devices         dd 0
  1152. device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
  1153.  
  1154.