Subversion Repositories Kolibri OS

Rev

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

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