Subversion Repositories Kolibri OS

Rev

Rev 2935 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2011. 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        db ?
  196.         .pci_dev        db ?
  197.         .irq_line       db ?
  198.  
  199.         rb 1            ; 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 R6040 driver\n"
  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.         jl      .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.         jl      .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     ax , word [device.pci_bus]              ; compare with pci and device num in device list (notice the usage of word instead of byte)
  289.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  290.         add     esi, 4
  291.         loop    .nextdevice
  292.  
  293.  
  294. ; This device doesnt have its own eth_device structure yet, lets create one
  295.   .firstdevice:
  296.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  297.         jge     .fail
  298.  
  299.         allocate_and_clear ebx, device.size, .fail      ; Allocate the buffer for device structure
  300.  
  301. ; Fill in the direct call addresses into the struct
  302.  
  303.         mov     [device.reset], reset
  304.         mov     [device.transmit], transmit
  305.         mov     [device.get_MAC], read_mac
  306.         mov     [device.set_MAC], .fail
  307.         mov     [device.unload], unload
  308.         mov     [device.name], my_service
  309.  
  310. ; save the pci bus and device numbers
  311.  
  312.         mov     eax, [IOCTL.input]
  313.         mov     cl , [eax+1]
  314.         mov     [device.pci_bus], cl
  315.         mov     cl , [eax+2]
  316.         mov     [device.pci_dev], cl
  317.  
  318. ; Now, it's time to find the base io addres of the PCI device
  319.  
  320.         find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
  321.  
  322. ; We've found the io address, find IRQ now
  323.  
  324.         find_irq [device.pci_bus], [device.pci_dev], [device.irq_line]
  325.  
  326.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  327.         [device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
  328.  
  329. ; Ok, the eth_device structure is ready, let's probe the device
  330.         cli
  331.  
  332.         call    probe                                                   ; this function will output in eax
  333.         test    eax, eax
  334.         jnz     .err_sti                                                ; If an error occured, exit
  335.  
  336.         mov     eax, [devices]                                          ; Add the device structure to our device list
  337.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  338.         inc     [devices]                                               ;
  339.  
  340.         mov     [device.type], NET_TYPE_ETH
  341.         call    NetRegDev
  342.         sti
  343.  
  344.         cmp     eax, -1
  345.         je      .destroy
  346.  
  347.         ret
  348.  
  349. ; If the device was already loaded, find the device number and return it in eax
  350.  
  351.   .find_devicenum:
  352.         DEBUGF  1,"Trying to find device number of already registered device\n"
  353.         call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  354.                                                                         ; into a device number in edi
  355.         mov     eax, edi                                                ; Application wants it in eax instead
  356.         DEBUGF  1,"Kernel says: %u\n", eax
  357.         ret
  358.  
  359. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  360.  
  361.   .destroy:
  362.         ; todo: reset device into virgin state
  363.  
  364.   .err_sti:
  365.         sti
  366.  
  367.   .err:
  368.         stdcall KernelFree, ebx
  369.  
  370.   .fail:
  371.         or      eax, -1
  372.         ret
  373.  
  374. ;------------------------------------------------------
  375. endp
  376.  
  377.  
  378. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  379. ;;                                                                        ;;
  380. ;;        Actual Hardware dependent code starts here                      ;;
  381. ;;                                                                        ;;
  382. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  383.  
  384.  
  385. macro mdio_write reg, val {
  386.         stdcall phy_read, [device.io_addr], [device.phy_addr], reg
  387. }
  388.  
  389. macro mdio_write reg, val {
  390.         stdcall phy_write, [device.io_addr], [devce.phy_addr], reg, val
  391. }
  392.  
  393.  
  394. align 4
  395. unload:
  396.         ; TODO: (in this particular order)
  397.         ;
  398.         ; - Stop the device
  399.         ; - Detach int handler
  400.         ; - Remove device from local list (RTL8139_LIST)
  401.         ; - call unregister function in kernel
  402.         ; - Remove all allocated structures and buffers the card used
  403.  
  404.         or      eax,-1
  405.  
  406. ret
  407.  
  408.  
  409. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  410. ;;
  411. ;;  probe: enables the device (if it really is RTL8139)
  412. ;;
  413. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  414.  
  415. align 4
  416. probe:
  417.         DEBUGF  2,"Probing R6040 device\n"
  418.  
  419.         make_bus_master [device.pci_bus], [device.pci_dev]
  420.  
  421.         ; If PHY status change register is still set to zero
  422.         ; it means the bootloader didn't initialize it
  423.  
  424.         set_io  0
  425.         set_io  PHY_CC
  426.         in      ax, dx
  427.         test    ax, ax
  428.         jnz     @f
  429.         mov     ax, 0x9F07
  430.         out     dx, ax
  431.      @@:
  432.  
  433.         call    read_mac
  434.  
  435.         ; Some bootloaders/BIOSes do not initialize MAC address, warn about that
  436.         and     eax, 0xFF
  437.         or      eax, dword [device.mac]
  438.         test    eax, eax
  439.         jnz     @f
  440.         DEBUGF  2, "ERROR: MAC address not initialized!\n"
  441.  
  442.      @@:
  443.         ; Init RDC private data
  444.         mov     [device.mcr0], 0x1002
  445.         ;mov     [private.phy_addr], 1 ; Asper: Only one network card is supported now.
  446.         mov     [device.switch_sig], 0
  447.  
  448.         ; Check the vendor ID on the PHY, if 0xFFFF assume none attached
  449.         stdcall phy_read, 1, 2
  450.         cmp     ax, 0xFFFF
  451.         jne     @f
  452.         DEBUGF  2, "Failed to detect an attached PHY\n" ;, generating random"
  453.         mov     eax, -1
  454.         ret
  455.      @@:
  456.  
  457.         ; Set MAC address
  458.         call    init_mac_regs
  459.  
  460.         ; Initialize and alloc RX/TX buffers
  461.         call    init_txbufs
  462.         call    init_rxbufs
  463.  
  464.         ; Read the PHY ID
  465.         mov     [device.phy_mode], 0x8000
  466.         stdcall phy_read, 0, 2
  467.         mov     [device.switch_sig], ax
  468.         cmp     ax, ICPLUS_PHY_ID
  469.         jne     @f
  470.         stdcall phy_write, 29, 31, 0x175C ; Enable registers
  471.         jmp     .phy_readen
  472.       @@:
  473.  
  474.         ; PHY Mode Check
  475.         movzx   eax, [device.phy_addr]
  476.         stdcall phy_write, eax, 4, PHY_CAP
  477.         stdcall phy_write, eax, 0, PHY_MODE
  478.  
  479.       if PHY_MODE = 0x3100
  480.         call    phy_mode_chk
  481.         mov     [device.phy_mode], ax
  482.         jmp     .phy_readen
  483.       end if
  484.  
  485.       if not (PHY_MODE and 0x0100)
  486.         mov     [device.phy_mode], 0
  487.       end if
  488.  
  489.       .phy_readen:
  490.  
  491.         ; Set duplex mode
  492.         mov     ax, [device.phy_mode]
  493.         or      [device.mcr0], ax
  494.  
  495.         ; improve performance (by RDC guys)
  496.         stdcall phy_read, 30, 17
  497.         or      ax, 0x4000
  498.         stdcall phy_write, 30, 17, eax
  499.  
  500.         stdcall phy_read, 30, 17
  501.         and     ax, not 0x2000
  502.         stdcall phy_write, 30, 17, eax
  503.  
  504.         stdcall phy_write, 0, 19, 0x0000
  505.         stdcall phy_write, 0, 30, 0x01F0
  506.  
  507.         ; Initialize all Mac registers
  508.         call    init_mac_regs
  509.  
  510.  
  511.  
  512. align 4
  513. reset:
  514.  
  515.         DEBUGF  2,"Resetting R6040\n"
  516.  
  517.         ; Mask off Interrupt
  518.         xor     ax, ax
  519.         set_io  0
  520.         set_io  MIER
  521.         out     dx, ax
  522.  
  523.  
  524. ; attach int handler
  525.  
  526.         movzx   eax, [device.irq_line]
  527.         DEBUGF  2,"Attaching int handler to irq %x\n", eax:1
  528.         stdcall AttachIntHandler, eax, int_handler, dword 0
  529.         test    eax, eax
  530.         jnz     @f
  531.         DEBUGF  2,"\nCould not attach int handler!\n"
  532. ;        or      eax, -1
  533. ;        ret
  534.        @@:
  535.  
  536.  
  537.         ;Reset RDC MAC
  538.         mov     eax, MAC_RST
  539.         set_io  0
  540.         set_io  MCR1
  541.         out     dx, ax
  542.  
  543.         mov     ecx, 2048 ;limit
  544.   .read:
  545.         in      ax, dx
  546.         test    ax, 0x1
  547.         jnz      @f
  548.         dec     ecx
  549.         test    ecx, ecx
  550.         jnz     .read
  551.   @@:
  552.         ;Reset internal state machine
  553.         mov     ax,  2
  554.         set_io  MAC_SM
  555.         out     dx, ax
  556.  
  557.         xor     ax, ax
  558.         out     dx, ax
  559.  
  560.         mov     esi, 5
  561.         stdcall Sleep
  562.  
  563.         ;MAC Bus Control Register
  564.         mov     ax, MBCR_DEFAULT
  565.         set_io  0
  566.         set_io  MBCR
  567.         out     dx, ax
  568.  
  569.         ;Buffer Size Register
  570.         mov     ax, MAX_BUF_SIZE
  571.         set_io  MR_BSR
  572.         out     dx, ax
  573.  
  574.         ;Write TX ring start address
  575.         lea     eax, [device.tx_ring]
  576.         GetRealAddr
  577.         set_io  MTD_SA0
  578.         out     dx, ax
  579.         shr     eax, 16
  580.         set_io  MTD_SA1
  581.         out     dx, ax
  582.  
  583.         ;Write RX ring start address
  584.         lea     eax, [device.rx_ring]
  585.         GetRealAddr
  586.         set_io  MRD_SA0
  587.         out     dx, ax
  588.         shr     eax, 16
  589.         set_io  MRD_SA1
  590.         out     dx, ax
  591.  
  592.         ;Set interrupt waiting time and packet numbers
  593.         xor     ax, ax
  594.         set_io  MT_ICR
  595.         out     dx, ax
  596.  
  597.         ;Enable interrupts
  598.         mov     ax, INT_MASK
  599.         set_io  MIER
  600.         out     dx, ax
  601.  
  602.         ;Enable TX and RX
  603.         mov     ax, [device.mcr0]
  604.         or      ax, 0x0002
  605.         set_io  0
  606.         out     dx, ax
  607.  
  608.         ;Let TX poll the descriptors
  609.         ;we may got called by tx_timeout which has left
  610.         ;some unset tx buffers
  611.         xor     ax, ax
  612.         inc     ax
  613.         set_io  0
  614.         set_io  MTPR
  615.         out     dx, ax
  616.  
  617. ; Set the mtu, kernel will be able to send now
  618.         mov     [device.mtu], 1514
  619.  
  620.         DEBUGF  1,"Reset ok\n"
  621.         xor     eax, eax
  622.  
  623.         ret
  624.  
  625.  
  626.  
  627. align 4
  628. init_txbufs:
  629.  
  630.         DEBUGF  1,"Init TxBufs\n"
  631.  
  632.         lea     esi, [device.tx_ring]
  633.         lea     eax, [device.tx_ring + x_head.sizeof]
  634.         GetRealAddr
  635.         mov     ecx, TX_RING_SIZE
  636.  
  637.     .next_desc:
  638.         mov     [esi + x_head.ndesc], eax
  639.         mov     [esi + x_head.skb_ptr], 0
  640.         mov     [esi + x_head.status], DSC_OWNER_MAC
  641.  
  642.         add     eax, x_head.sizeof
  643.         add     esi, x_head.sizeof
  644.  
  645.         dec     ecx
  646.         jnz     .next_desc
  647.  
  648.         lea     eax, [device.tx_ring]
  649.         GetRealAddr
  650.         mov     [device.tx_ring + x_head.sizeof*(TX_RING_SIZE - 1) + x_head.ndesc], eax
  651.  
  652.         ret
  653.  
  654.  
  655.  
  656. align 4
  657. init_rxbufs:
  658.  
  659.         DEBUGF  1,"Init RxBufs\n"
  660.  
  661.         lea     esi, [device.rx_ring]
  662.         lea     eax, [device.rx_ring + x_head.sizeof]
  663.         GetRealAddr
  664.         mov     edx, eax
  665.         mov     ecx, RX_RING_SIZE
  666.  
  667.     .next_desc:
  668.          mov     [esi + x_head.ndesc], edx
  669.  
  670.         push    esi ecx
  671.         stdcall KernelAlloc, MAX_BUF_SIZE
  672.         pop     ecx esi
  673.  
  674.         mov     [esi + x_head.skb_ptr], eax
  675.         GetRealAddr
  676.         mov     [esi + x_head.buf], eax
  677.         mov     [esi + x_head.status], DSC_OWNER_MAC
  678.  
  679.         add     edx, x_head.sizeof
  680.         add     esi, x_head.sizeof
  681.  
  682.         dec     ecx
  683.         jnz     .next_desc
  684.  
  685.         ; complete the ring by linking the last to the first
  686.  
  687.         lea     eax, [device.rx_ring]
  688.         GetRealAddr
  689.         mov     [device.rx_ring + x_head.sizeof*(RX_RING_SIZE - 1) + x_head.ndesc], eax
  690.  
  691.         ret
  692.  
  693.  
  694.  
  695. align 4
  696. phy_mode_chk:
  697.  
  698.         DEBUGF  1,"Checking PHY mode\n"
  699.  
  700.         ; PHY Link Status Check
  701.         movzx   eax, [device.phy_addr]
  702.         stdcall phy_read, eax, 1
  703.         test    eax, 0x4
  704.         jz      .ret_0x8000
  705.  
  706.         ; PHY Chip Auto-Negotiation Status
  707.         movzx   eax, [device.phy_addr]
  708.         stdcall phy_read, eax, 1
  709.         test    eax, 0x0020
  710.         jnz     .auto_nego
  711.  
  712.         ; Force Mode
  713.         movzx   eax, [device.phy_addr]
  714.         stdcall phy_read, eax, 0
  715.         test    eax, 0x100
  716.         jnz     .ret_0x8000
  717.  
  718.   .auto_nego:
  719.         ; Auto Negotiation Mode
  720.         movzx   eax, [device.phy_addr]
  721.         stdcall phy_read, eax, 5
  722.         mov     ecx, eax
  723.         movzx   eax, [device.phy_addr]
  724.         stdcall phy_read, eax, 4
  725.         and     eax, ecx
  726.         test    eax, 0x140
  727.         jnz     .ret_0x8000
  728.  
  729.         xor     eax, eax
  730.         ret
  731.  
  732.   .ret_0x8000:
  733.         mov     eax, 0x8000
  734.         ret
  735.  
  736.  
  737.  
  738.  
  739.  
  740. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  741. ;;                                         ;;
  742. ;; Transmit                                ;;
  743. ;;                                         ;;
  744. ;; In: buffer pointer in [esp+4]           ;;
  745. ;;     size of buffer in [esp+8]           ;;
  746. ;;     pointer to device structure in ebx  ;;
  747. ;;                                         ;;
  748. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  749. align 4
  750. transmit:
  751.         DEBUGF  2,"\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
  752.         mov     eax, [esp+4]
  753.         DEBUGF  2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  754.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  755.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  756.         [eax+13]:2,[eax+12]:2
  757.  
  758.         cmp     dword [esp+8], 1514
  759.         jg      .fail
  760.         cmp     dword [esp+8], 60
  761.         jl      .fail
  762.  
  763.         movzx   edi, [device.cur_tx]
  764.         shl     edi, 5
  765.         add     edi, ebx
  766.         add     edi, device.tx_ring - ebx
  767.  
  768.         DEBUGF  2,"TX buffer status: 0x%x\n", [edi + x_head.status]:4
  769.  
  770.         test    [edi + x_head.status], DSC_OWNER_MAC    ; check if buffer is available
  771.         jnz     .wait_to_send
  772.  
  773.   .do_send:
  774.  
  775.         DEBUGF  2,"Sending now\n"
  776.  
  777.         mov     eax, [esp+4]
  778.         mov     [edi + x_head.skb_ptr], eax
  779.         GetRealAddr
  780.         mov     [edi + x_head.buf], eax
  781.         mov     ecx, [esp+8]
  782.         mov     [edi + x_head.len], cx
  783.         mov     [edi + x_head.status], DSC_OWNER_MAC
  784.  
  785.         ; Trigger the MAC to check the TX descriptor
  786.         mov     ax, 0x01
  787.         set_io  0
  788.         set_io  MTPR
  789.         out     dx, ax
  790.  
  791.         inc     [device.cur_tx]
  792.         and     [device.cur_tx], TX_RING_SIZE - 1
  793.         xor     eax, eax
  794.  
  795. ; Update stats
  796.         inc     [device.packets_tx]
  797.         mov     eax, [esp+8]
  798.         add     dword [device.bytes_tx], eax
  799.         adc     dword [device.bytes_tx + 4], 0
  800.  
  801.         ret     8
  802.  
  803.   .wait_to_send:
  804.  
  805.         DEBUGF  2,"Waiting for TX buffer\n"
  806.  
  807.         call    GetTimerTicks           ; returns in eax
  808.         lea     edx, [eax + 100]
  809.      .l2:
  810.         test    [edi + x_head.status], DSC_OWNER_MAC
  811.         jz      .do_send
  812.         mov     esi, 10
  813.         call    Sleep
  814.         call    GetTimerTicks
  815.         cmp     edx, eax
  816.         jl      .l2
  817.  
  818.         DEBUGF  1,"Send timeout\n"
  819.         xor     eax, eax
  820.         dec     eax
  821.   .fail:
  822.         DEBUGF  1,"Send failed\n"
  823.         ret     8
  824.  
  825.  
  826.  
  827.  
  828.  
  829. ;;;;;;;;;;;;;;;;;;;;;;;
  830. ;;                   ;;
  831. ;; Interrupt handler ;;
  832. ;;                   ;;
  833. ;;;;;;;;;;;;;;;;;;;;;;;
  834.  
  835. align 4
  836. int_handler:
  837.  
  838.         DEBUGF  1,"\n%s int\n", my_service
  839.  
  840. ; Find pointer of device wich made IRQ occur
  841.  
  842.         mov     ecx, [devices]
  843.         test    ecx, ecx
  844.         jz      .nothing
  845.         mov     esi, device_list
  846.   .nextdevice:
  847.         mov     ebx, [esi]
  848.  
  849.         set_io  0
  850.         set_io  MISR
  851.         in      ax, dx
  852.         out     dx, ax                  ; send it back to ACK
  853.         test    ax, ax
  854.         jnz     .got_it
  855.   .continue:
  856.         add     esi, 4
  857.         dec     ecx
  858.         jnz     .nextdevice
  859.   .nothing:                             ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
  860.         ret
  861.  
  862. ; At this point, test for all possible reasons, and handle accordingly
  863.  
  864.   .got_it:
  865.  
  866.         DEBUGF  1,"Device: %x Status: %x ", ebx, ax
  867.  
  868.         push ax
  869.  
  870.         test    word [esp], RX_FINISH
  871.         jz      .no_RX
  872.  
  873.         push    ebx
  874.   .more_RX:
  875.         pop     ebx
  876.  
  877.         ; Find the current RX descriptor
  878.  
  879.         movzx   edx, [device.cur_rx]
  880.         shl     edx, 5
  881.         lea     edx, [device.rx_ring + edx]
  882.  
  883.         ; Check the descriptor status
  884.  
  885.         mov     cx, [edx + x_head.status]
  886.         test    cx, DSC_OWNER_MAC
  887.         jnz     .no_RX
  888.  
  889.         DEBUGF  2,"packet status=0x%x\n", cx
  890.  
  891.         test    cx, DSC_RX_ERR          ; Global error status set
  892.         jnz     .no_RX
  893.  
  894.         ; Packet successfully received
  895.  
  896.         movzx   ecx, [edx + x_head.len]
  897.         and     ecx, 0xFFF
  898.         sub     ecx, 4                  ; Do not count the CRC
  899.  
  900. ; Update stats
  901.         add     dword [device.bytes_rx], ecx
  902.         adc     dword [device.bytes_rx + 4], 0
  903.         inc     dword [device.packets_rx]
  904.  
  905.         ; Push packet size and pointer, kernel will need it..
  906.  
  907.         push    ebx
  908.         push    .more_RX
  909.  
  910.         push    ecx
  911.         push    [edx + x_head.skb_ptr]
  912.  
  913.         DEBUGF  2,"packet ptr=0x%x\n", [edx + x_head.skb_ptr]
  914.  
  915.         ; reset the RX descriptor
  916.  
  917.         push    edx
  918.         stdcall KernelAlloc, MAX_BUF_SIZE
  919.         pop     edx
  920.         mov     [edx + x_head.skb_ptr], eax
  921.         GetRealAddr
  922.         mov     [edx + x_head.buf], eax
  923.         mov     [edx + x_head.status], DSC_OWNER_MAC
  924.  
  925.         ; Use next descriptor next time
  926.  
  927.         inc     [device.cur_rx]
  928.         and     [device.cur_rx], RX_RING_SIZE - 1
  929.  
  930.         ; At last, send packet to kernel
  931.  
  932.         jmp     Eth_input
  933.  
  934.  
  935.   .no_RX:
  936.  
  937.         test    word [esp], TX_FINISH
  938.         jz      .no_TX
  939.  
  940.       .loop_tx:
  941.         movzx   edi, [device.last_tx]
  942.         shl     edi, 5
  943.         lea     edi, [device.tx_ring + edi]
  944.  
  945.         test    [edi + x_head.status], DSC_OWNER_MAC
  946.         jnz     .no_TX
  947.  
  948.         cmp     [edi + x_head.skb_ptr], 0
  949.         je      .no_TX
  950.  
  951.         DEBUGF  2,"Freeing buffer 0x%x\n", [edi + x_head.skb_ptr]
  952.  
  953.         push    [edi + x_head.skb_ptr]
  954.         mov     [edi + x_head.skb_ptr], 0
  955.         call    KernelFree
  956.  
  957.         inc     [device.last_tx]
  958.         and     [device.last_tx], TX_RING_SIZE - 1
  959.  
  960.         jmp     .loop_tx
  961.  
  962.   .no_TX:
  963.         pop     ax
  964.         ret
  965.  
  966.  
  967.  
  968.  
  969. align 4
  970. init_mac_regs:
  971.  
  972.         DEBUGF  2,"initializing MAC regs\n"
  973.  
  974.         ; MAC operation register
  975.         mov     ax, 1
  976.         set_io  0
  977.         set_io  MCR1
  978.         out     dx, ax
  979.         ; Reset MAC
  980.         mov     ax, 2
  981.         set_io  MAC_SM
  982.         out     dx, ax
  983.         ; Reset internal state machine
  984.         xor     ax, ax
  985.         out     dx, ax
  986.         mov     esi, 5
  987.         stdcall Sleep
  988.  
  989.         call    read_mac
  990.  
  991.         ret
  992.  
  993.  
  994.  
  995.  
  996. ; Read a word data from PHY Chip
  997.  
  998. align 4
  999. proc  phy_read stdcall, phy_addr:dword, reg:dword
  1000.  
  1001.         DEBUGF  2,"PHY read, addr=0x%x reg=0x%x\n", [phy_addr]:8, [reg]:8
  1002.  
  1003.         mov     eax, [phy_addr]
  1004.         shl     eax, 8
  1005.         add     eax, [reg]
  1006.         add     eax, MDIO_READ
  1007.         set_io  0
  1008.         set_io  MMDIO
  1009.         out     dx, ax
  1010.  
  1011.         ;Wait for the read bit to be cleared.
  1012.         mov     ecx, 2048 ;limit
  1013.   .read:
  1014.         in      ax, dx
  1015.         test    ax, MDIO_READ
  1016.         jz      @f
  1017.         dec     ecx
  1018.         jnz     .read
  1019.   @@:
  1020.  
  1021.         set_io  MMRD
  1022.         in      ax, dx
  1023.         and     eax, 0xFFFF
  1024.  
  1025.         DEBUGF  2,"PHY read, val=0x%x\n", eax:4
  1026.  
  1027.         ret
  1028.  
  1029. endp
  1030.  
  1031.  
  1032.  
  1033.  
  1034. ; Write a word data to PHY Chip
  1035.  
  1036. align 4
  1037. proc  phy_write stdcall, phy_addr:dword, reg:dword, val:dword
  1038.  
  1039.         DEBUGF  2,"PHY write, addr=0x%x reg=0x%x val=0x%x\n", [phy_addr]:8, [reg]:8, [val]:8
  1040.  
  1041.         mov     eax, [val]
  1042.         set_io  0
  1043.         set_io  MMWD
  1044.         out     dx, ax
  1045.  
  1046.         ;Write the command to the MDIO bus
  1047.  
  1048.         mov     eax, [phy_addr]
  1049.         shl     eax, 8
  1050.         add     eax, [reg]
  1051.         add     eax, MDIO_WRITE
  1052.         set_io  MMDIO
  1053.         out     dx, ax
  1054.  
  1055.         ;Wait for the write bit to be cleared.
  1056.         mov     ecx, 2048 ;limit
  1057.   .write:
  1058.         in      ax, dx
  1059.         test    ax, MDIO_WRITE
  1060.         jz      @f
  1061.         dec     ecx
  1062.         jnz     .write
  1063.   @@:
  1064.  
  1065.         DEBUGF  2,"PHY write ok\n"
  1066.  
  1067.         ret
  1068. endp
  1069.  
  1070.  
  1071.  
  1072. align 4
  1073. read_mac:
  1074.  
  1075.         DEBUGF  2,"Reading MAC: "
  1076.  
  1077.         mov     cx, 3
  1078.         lea     edi, [device.mac]
  1079.         set_io  0
  1080.         set_io  MID_0L
  1081.      .mac:
  1082.         in      ax, dx
  1083.         stosw
  1084.         inc     dx
  1085.         inc     dx
  1086.         dec     cx
  1087.         jnz     .mac
  1088.  
  1089.         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
  1090.  
  1091.         ret
  1092.  
  1093.  
  1094.  
  1095.  
  1096. ; End of code
  1097.  
  1098. section '.data' data readable writable align 16 ; place all uninitialized data place here
  1099. align 4                                         ; Place all initialised data here
  1100.  
  1101. devices         dd 0
  1102. version         dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
  1103. my_service      db 'R6040',0                    ; max 16 chars include zero
  1104.  
  1105. include_debug_strings                           ; All data wich FDO uses will be included here
  1106.  
  1107. device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
  1108.  
  1109.