Subversion Repositories Kolibri OS

Rev

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