Subversion Repositories Kolibri OS

Rev

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