Subversion Repositories Kolibri OS

Rev

Rev 3155 | Blame | 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.get_MAC], read_mac
  309.         mov     [device.set_MAC], .fail
  310.         mov     [device.unload], unload
  311.         mov     [device.name], my_service
  312.  
  313. ; save the pci bus and device numbers
  314.  
  315.         mov     eax, [IOCTL.input]
  316.         movzx   ecx, byte[eax+1]
  317.         mov     [device.pci_bus], ecx
  318.         movzx   ecx, byte[eax+2]
  319.         mov     [device.pci_dev], ecx
  320.  
  321. ; Now, it's time to find the base io addres of the PCI device
  322.  
  323.         PCI_find_io
  324.  
  325. ; We've found the io address, find IRQ now
  326.  
  327.         PCI_find_irq
  328.  
  329.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  330.         [device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
  331.  
  332. ; Ok, the eth_device structure is ready, let's probe the device
  333.         cli
  334.  
  335.         call    probe                                                   ; this function will output in eax
  336.         test    eax, eax
  337.         jnz     .err_sti                                                ; If an error occured, exit
  338.  
  339.         mov     eax, [devices]                                          ; Add the device structure to our device list
  340.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  341.         inc     [devices]                                               ;
  342.  
  343.         mov     [device.type], NET_TYPE_ETH
  344.         call    NetRegDev
  345.         sti
  346.  
  347.         cmp     eax, -1
  348.         je      .destroy
  349.  
  350.         ret
  351.  
  352. ; If the device was already loaded, find the device number and return it in eax
  353.  
  354.   .find_devicenum:
  355.         DEBUGF  1,"Trying to find device number of already registered device\n"
  356.         call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  357.                                                                         ; into a device number in edi
  358.         mov     eax, edi                                                ; Application wants it in eax instead
  359.         DEBUGF  1,"Kernel says: %u\n", eax
  360.         ret
  361.  
  362. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  363.  
  364.   .destroy:
  365.         ; todo: reset device into virgin state
  366.  
  367.   .err_sti:
  368.         sti
  369.  
  370.   .err:
  371.         stdcall KernelFree, ebx
  372.  
  373.   .fail:
  374.         or      eax, -1
  375.         ret
  376.  
  377. ;------------------------------------------------------
  378. endp
  379.  
  380.  
  381. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  382. ;;                                                                        ;;
  383. ;;        Actual Hardware dependent code starts here                      ;;
  384. ;;                                                                        ;;
  385. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  386.  
  387.  
  388. macro mdio_write reg, val {
  389.         stdcall phy_read, [device.io_addr], [device.phy_addr], reg
  390. }
  391.  
  392. macro mdio_write reg, val {
  393.         stdcall phy_write, [device.io_addr], [devce.phy_addr], reg, val
  394. }
  395.  
  396.  
  397. align 4
  398. unload:
  399.         ; TODO: (in this particular order)
  400.         ;
  401.         ; - Stop the device
  402.         ; - Detach int handler
  403.         ; - Remove device from local list (RTL8139_LIST)
  404.         ; - call unregister function in kernel
  405.         ; - Remove all allocated structures and buffers the card used
  406.  
  407.         or      eax,-1
  408.  
  409. ret
  410.  
  411.  
  412. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  413. ;;
  414. ;;  probe: enables the device (if it really is RTL8139)
  415. ;;
  416. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  417.  
  418. align 4
  419. probe:
  420.         DEBUGF  2,"Probing R6040 device\n"
  421.  
  422.         PCI_make_bus_master
  423.  
  424.         ; If PHY status change register is still set to zero
  425.         ; it means the bootloader didn't initialize it
  426.  
  427.         set_io  0
  428.         set_io  PHY_CC
  429.         in      ax, dx
  430.         test    ax, ax
  431.         jnz     @f
  432.         mov     ax, 0x9F07
  433.         out     dx, ax
  434.      @@:
  435.  
  436.         call    read_mac
  437.  
  438.         ; Some bootloaders/BIOSes do not initialize MAC address, warn about that
  439.         and     eax, 0xFF
  440.         or      eax, dword [device.mac]
  441.         test    eax, eax
  442.         jnz     @f
  443.         DEBUGF  2, "ERROR: MAC address not initialized!\n"
  444.  
  445.      @@:
  446.         ; Init RDC private data
  447.         mov     [device.mcr0], 0x1002
  448.         ;mov     [private.phy_addr], 1 ; Asper: Only one network card is supported now.
  449.         mov     [device.switch_sig], 0
  450.  
  451.         ; Check the vendor ID on the PHY, if 0xFFFF assume none attached
  452.         stdcall phy_read, 1, 2
  453.         cmp     ax, 0xFFFF
  454.         jne     @f
  455.         DEBUGF  2, "Failed to detect an attached PHY\n" ;, generating random"
  456.         mov     eax, -1
  457.         ret
  458.      @@:
  459.  
  460.         ; Set MAC address
  461.         call    init_mac_regs
  462.  
  463.         ; Initialize and alloc RX/TX buffers
  464.         call    init_txbufs
  465.         call    init_rxbufs
  466.  
  467.         ; Read the PHY ID
  468.         mov     [device.phy_mode], 0x8000
  469.         stdcall phy_read, 0, 2
  470.         mov     [device.switch_sig], ax
  471.         cmp     ax, ICPLUS_PHY_ID
  472.         jne     @f
  473.         stdcall phy_write, 29, 31, 0x175C ; Enable registers
  474.         jmp     .phy_readen
  475.       @@:
  476.  
  477.         ; PHY Mode Check
  478.         movzx   eax, [device.phy_addr]
  479.         stdcall phy_write, eax, 4, PHY_CAP
  480.         stdcall phy_write, eax, 0, PHY_MODE
  481.  
  482.       if PHY_MODE = 0x3100
  483.         call    phy_mode_chk
  484.         mov     [device.phy_mode], ax
  485.         jmp     .phy_readen
  486.       end if
  487.  
  488.       if not (PHY_MODE and 0x0100)
  489.         mov     [device.phy_mode], 0
  490.       end if
  491.  
  492.       .phy_readen:
  493.  
  494.         ; Set duplex mode
  495.         mov     ax, [device.phy_mode]
  496.         or      [device.mcr0], ax
  497.  
  498.         ; improve performance (by RDC guys)
  499.         stdcall phy_read, 30, 17
  500.         or      ax, 0x4000
  501.         stdcall phy_write, 30, 17, eax
  502.  
  503.         stdcall phy_read, 30, 17
  504.         and     ax, not 0x2000
  505.         stdcall phy_write, 30, 17, eax
  506.  
  507.         stdcall phy_write, 0, 19, 0x0000
  508.         stdcall phy_write, 0, 30, 0x01F0
  509.  
  510.         ; Initialize all Mac registers
  511.         call    init_mac_regs
  512.  
  513.  
  514.  
  515. align 4
  516. reset:
  517.  
  518.         DEBUGF  2,"Resetting R6040\n"
  519.  
  520.         ; Mask off Interrupt
  521.         xor     ax, ax
  522.         set_io  0
  523.         set_io  MIER
  524.         out     dx, ax
  525.  
  526.  
  527. ; attach int handler
  528.  
  529.         movzx   eax, [device.irq_line]
  530.         DEBUGF  2,"Attaching int handler to irq %x\n", eax:1
  531.         stdcall AttachIntHandler, eax, int_handler, dword 0
  532.         test    eax, eax
  533.         jnz     @f
  534.         DEBUGF  2,"\nCould not attach int handler!\n"
  535. ;        or      eax, -1
  536. ;        ret
  537.        @@:
  538.  
  539.  
  540.         ;Reset RDC MAC
  541.         mov     eax, MAC_RST
  542.         set_io  0
  543.         set_io  MCR1
  544.         out     dx, ax
  545.  
  546.         mov     ecx, 2048 ;limit
  547.   .read:
  548.         in      ax, dx
  549.         test    ax, 0x1
  550.         jnz      @f
  551.         dec     ecx
  552.         test    ecx, ecx
  553.         jnz     .read
  554.   @@:
  555.         ;Reset internal state machine
  556.         mov     ax,  2
  557.         set_io  MAC_SM
  558.         out     dx, ax
  559.  
  560.         xor     ax, ax
  561.         out     dx, ax
  562.  
  563.         mov     esi, 5
  564.         stdcall Sleep
  565.  
  566.         ;MAC Bus Control Register
  567.         mov     ax, MBCR_DEFAULT
  568.         set_io  0
  569.         set_io  MBCR
  570.         out     dx, ax
  571.  
  572.         ;Buffer Size Register
  573.         mov     ax, MAX_BUF_SIZE
  574.         set_io  MR_BSR
  575.         out     dx, ax
  576.  
  577.         ;Write TX ring start address
  578.         lea     eax, [device.tx_ring]
  579.         GetRealAddr
  580.         set_io  MTD_SA0
  581.         out     dx, ax
  582.         shr     eax, 16
  583.         set_io  MTD_SA1
  584.         out     dx, ax
  585.  
  586.         ;Write RX ring start address
  587.         lea     eax, [device.rx_ring]
  588.         GetRealAddr
  589.         set_io  MRD_SA0
  590.         out     dx, ax
  591.         shr     eax, 16
  592.         set_io  MRD_SA1
  593.         out     dx, ax
  594.  
  595.         ;Set interrupt waiting time and packet numbers
  596.         xor     ax, ax
  597.         set_io  MT_ICR
  598.         out     dx, ax
  599.  
  600.         ;Enable interrupts
  601.         mov     ax, INT_MASK
  602.         set_io  MIER
  603.         out     dx, ax
  604.  
  605.         ;Enable TX and RX
  606.         mov     ax, [device.mcr0]
  607.         or      ax, 0x0002
  608.         set_io  0
  609.         out     dx, ax
  610.  
  611.         ;Let TX poll the descriptors
  612.         ;we may got called by tx_timeout which has left
  613.         ;some unset tx buffers
  614.         xor     ax, ax
  615.         inc     ax
  616.         set_io  0
  617.         set_io  MTPR
  618.         out     dx, ax
  619.  
  620. ; Set the mtu, kernel will be able to send now
  621.         mov     [device.mtu], 1514
  622.  
  623.         DEBUGF  1,"Reset ok\n"
  624.         xor     eax, eax
  625.  
  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.         DEBUGF  1,"\n%s int\n", my_service
  842.  
  843. ; Find pointer of device wich made IRQ occur
  844.  
  845.         mov     ecx, [devices]
  846.         test    ecx, ecx
  847.         jz      .nothing
  848.         mov     esi, device_list
  849.   .nextdevice:
  850.         mov     ebx, [esi]
  851.  
  852.         set_io  0
  853.         set_io  MISR
  854.         in      ax, dx
  855.         out     dx, ax                  ; send it back to ACK
  856.         test    ax, ax
  857.         jnz     .got_it
  858.   .continue:
  859.         add     esi, 4
  860.         dec     ecx
  861.         jnz     .nextdevice
  862.   .nothing:                             ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
  863.         ret
  864.  
  865. ; At this point, test for all possible reasons, and handle accordingly
  866.  
  867.   .got_it:
  868.  
  869.         DEBUGF  1,"Device: %x Status: %x ", ebx, ax
  870.  
  871.         push ax
  872.  
  873.         test    word [esp], RX_FINISH
  874.         jz      .no_RX
  875.  
  876.         push    ebx
  877.   .more_RX:
  878.         pop     ebx
  879.  
  880.         ; Find the current RX descriptor
  881.  
  882.         movzx   edx, [device.cur_rx]
  883.         shl     edx, 5
  884.         lea     edx, [device.rx_ring + edx]
  885.  
  886.         ; Check the descriptor status
  887.  
  888.         mov     cx, [edx + x_head.status]
  889.         test    cx, DSC_OWNER_MAC
  890.         jnz     .no_RX
  891.  
  892.         DEBUGF  2,"packet status=0x%x\n", cx
  893.  
  894.         test    cx, DSC_RX_ERR          ; Global error status set
  895.         jnz     .no_RX
  896.  
  897.         ; Packet successfully received
  898.  
  899.         movzx   ecx, [edx + x_head.len]
  900.         and     ecx, 0xFFF
  901.         sub     ecx, 4                  ; Do not count the CRC
  902.  
  903. ; Update stats
  904.         add     dword [device.bytes_rx], ecx
  905.         adc     dword [device.bytes_rx + 4], 0
  906.         inc     dword [device.packets_rx]
  907.  
  908.         ; Push packet size and pointer, kernel will need it..
  909.  
  910.         push    ebx
  911.         push    .more_RX
  912.  
  913.         push    ecx
  914.         push    [edx + x_head.skb_ptr]
  915.  
  916.         DEBUGF  2,"packet ptr=0x%x\n", [edx + x_head.skb_ptr]
  917.  
  918.         ; reset the RX descriptor
  919.  
  920.         push    edx
  921.         stdcall KernelAlloc, MAX_BUF_SIZE
  922.         pop     edx
  923.         mov     [edx + x_head.skb_ptr], eax
  924.         GetRealAddr
  925.         mov     [edx + x_head.buf], eax
  926.         mov     [edx + x_head.status], DSC_OWNER_MAC
  927.  
  928.         ; Use next descriptor next time
  929.  
  930.         inc     [device.cur_rx]
  931.         and     [device.cur_rx], RX_RING_SIZE - 1
  932.  
  933.         ; At last, send packet to kernel
  934.  
  935.         jmp     Eth_input
  936.  
  937.  
  938.   .no_RX:
  939.  
  940.         test    word [esp], TX_FINISH
  941.         jz      .no_TX
  942.  
  943.       .loop_tx:
  944.         movzx   edi, [device.last_tx]
  945.         shl     edi, 5
  946.         lea     edi, [device.tx_ring + edi]
  947.  
  948.         test    [edi + x_head.status], DSC_OWNER_MAC
  949.         jnz     .no_TX
  950.  
  951.         cmp     [edi + x_head.skb_ptr], 0
  952.         je      .no_TX
  953.  
  954.         DEBUGF  2,"Freeing buffer 0x%x\n", [edi + x_head.skb_ptr]
  955.  
  956.         push    [edi + x_head.skb_ptr]
  957.         mov     [edi + x_head.skb_ptr], 0
  958.         call    KernelFree
  959.  
  960.         inc     [device.last_tx]
  961.         and     [device.last_tx], TX_RING_SIZE - 1
  962.  
  963.         jmp     .loop_tx
  964.  
  965.   .no_TX:
  966.         pop     ax
  967.         ret
  968.  
  969.  
  970.  
  971.  
  972. align 4
  973. init_mac_regs:
  974.  
  975.         DEBUGF  2,"initializing MAC regs\n"
  976.  
  977.         ; MAC operation register
  978.         mov     ax, 1
  979.         set_io  0
  980.         set_io  MCR1
  981.         out     dx, ax
  982.         ; Reset MAC
  983.         mov     ax, 2
  984.         set_io  MAC_SM
  985.         out     dx, ax
  986.         ; Reset internal state machine
  987.         xor     ax, ax
  988.         out     dx, ax
  989.         mov     esi, 5
  990.         stdcall Sleep
  991.  
  992.         call    read_mac
  993.  
  994.         ret
  995.  
  996.  
  997.  
  998.  
  999. ; Read a word data from PHY Chip
  1000.  
  1001. align 4
  1002. proc  phy_read stdcall, phy_addr:dword, reg:dword
  1003.  
  1004.         DEBUGF  2,"PHY read, addr=0x%x reg=0x%x\n", [phy_addr]:8, [reg]:8
  1005.  
  1006.         mov     eax, [phy_addr]
  1007.         shl     eax, 8
  1008.         add     eax, [reg]
  1009.         add     eax, MDIO_READ
  1010.         set_io  0
  1011.         set_io  MMDIO
  1012.         out     dx, ax
  1013.  
  1014.         ;Wait for the read bit to be cleared.
  1015.         mov     ecx, 2048 ;limit
  1016.   .read:
  1017.         in      ax, dx
  1018.         test    ax, MDIO_READ
  1019.         jz      @f
  1020.         dec     ecx
  1021.         jnz     .read
  1022.   @@:
  1023.  
  1024.         set_io  MMRD
  1025.         in      ax, dx
  1026.         and     eax, 0xFFFF
  1027.  
  1028.         DEBUGF  2,"PHY read, val=0x%x\n", eax:4
  1029.  
  1030.         ret
  1031.  
  1032. endp
  1033.  
  1034.  
  1035.  
  1036.  
  1037. ; Write a word data to PHY Chip
  1038.  
  1039. align 4
  1040. proc  phy_write stdcall, phy_addr:dword, reg:dword, val:dword
  1041.  
  1042.         DEBUGF  2,"PHY write, addr=0x%x reg=0x%x val=0x%x\n", [phy_addr]:8, [reg]:8, [val]:8
  1043.  
  1044.         mov     eax, [val]
  1045.         set_io  0
  1046.         set_io  MMWD
  1047.         out     dx, ax
  1048.  
  1049.         ;Write the command to the MDIO bus
  1050.  
  1051.         mov     eax, [phy_addr]
  1052.         shl     eax, 8
  1053.         add     eax, [reg]
  1054.         add     eax, MDIO_WRITE
  1055.         set_io  MMDIO
  1056.         out     dx, ax
  1057.  
  1058.         ;Wait for the write bit to be cleared.
  1059.         mov     ecx, 2048 ;limit
  1060.   .write:
  1061.         in      ax, dx
  1062.         test    ax, MDIO_WRITE
  1063.         jz      @f
  1064.         dec     ecx
  1065.         jnz     .write
  1066.   @@:
  1067.  
  1068.         DEBUGF  2,"PHY write ok\n"
  1069.  
  1070.         ret
  1071. endp
  1072.  
  1073.  
  1074.  
  1075. align 4
  1076. read_mac:
  1077.  
  1078.         DEBUGF  2,"Reading MAC: "
  1079.  
  1080.         mov     cx, 3
  1081.         lea     edi, [device.mac]
  1082.         set_io  0
  1083.         set_io  MID_0L
  1084.      .mac:
  1085.         in      ax, dx
  1086.         stosw
  1087.         inc     dx
  1088.         inc     dx
  1089.         dec     cx
  1090.         jnz     .mac
  1091.  
  1092.         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
  1093.  
  1094.         ret
  1095.  
  1096.  
  1097.  
  1098.  
  1099. ; End of code
  1100.  
  1101. section '.data' data readable writable align 16 ; place all uninitialized data place here
  1102. align 4                                         ; Place all initialised data here
  1103.  
  1104. devices         dd 0
  1105. version         dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
  1106. my_service      db 'R6040',0                    ; max 16 chars include zero
  1107.  
  1108. include_debug_strings                           ; All data wich FDO uses will be included here
  1109.  
  1110. device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
  1111.  
  1112.