Subversion Repositories Kolibri OS

Rev

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