Subversion Repositories Kolibri OS

Rev

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