Subversion Repositories Kolibri OS

Rev

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

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