Subversion Repositories Kolibri OS

Rev

Rev 1889 | Blame | Compare with Previous | 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 2
  28.  
  29.         W_MAX_TIMEOUT           equ 0x0FFF      ; max time out delay time
  30.  
  31.         TX_TIMEOUT              equ 6000        ; Time before concluding the transmitter is hung, in ms
  32.  
  33.         TX_RING_SIZE            equ 4           ; RING sizes must be a power of 2
  34.         RX_RING_SIZE            equ 4
  35.  
  36.         RX_BUF_LEN_IDX          equ 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          equ 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          equ 4           ; Rx buffer level before first PCI xfer.
  45.         RX_DMA_BURST            equ 4           ; Maximum PCI burst, '4' is 256 bytes
  46.         TX_DMA_BURST            equ 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       equ 1       ;For MAC1
  62. PHY2_ADDR       equ 3       ;For MAC2
  63. PHY_MODE        equ 0x3100  ;PHY CHIP Register 0
  64. PHY_CAP         equ 0x01E1  ;PHY CHIP Register 4
  65.  
  66. ;**************************************************************************
  67. ; RDC R6040 Register Definitions
  68. ;**************************************************************************
  69. MCR0            equ 0x00    ;Control register 0
  70. MCR1            equ 0x01    ;Control register 1
  71. MAC_RST         equ 0x0001  ;Reset the MAC
  72. MBCR            equ 0x08    ;Bus control
  73. MT_ICR          equ 0x0C    ;TX interrupt control
  74. MR_ICR          equ 0x10    ;RX interrupt control
  75. MTPR            equ 0x14    ;TX poll command register
  76. MR_BSR          equ 0x18    ;RX buffer size
  77. MR_DCR          equ 0x1A    ;RX descriptor control
  78. MLSR            equ 0x1C    ;Last status
  79. MMDIO           equ 0x20    ;MDIO control register
  80. MDIO_WRITE      equ 0x4000  ;MDIO write
  81. MDIO_READ       equ 0x2000  ;MDIO read
  82. MMRD            equ 0x24    ;MDIO read data register
  83. MMWD            equ 0x28    ;MDIO write data register
  84. MTD_SA0         equ 0x2C    ;TX descriptor start address 0
  85. MTD_SA1         equ 0x30    ;TX descriptor start address 1
  86. MRD_SA0         equ 0x34    ;RX descriptor start address 0
  87. MRD_SA1         equ 0x38    ;RX descriptor start address 1
  88. MISR            equ 0x3C    ;Status register
  89. MIER            equ 0x40    ;INT enable register
  90. MSK_INT         equ 0x0000  ;Mask off interrupts
  91. RX_FINISH       equ 0x0001  ;RX finished
  92. RX_NO_DESC      equ 0x0002  ;No RX descriptor available
  93. RX_FIFO_FULL    equ 0x0004  ;RX FIFO full
  94. RX_EARLY        equ 0x0008  ;RX early
  95. TX_FINISH       equ 0x0010  ;TX finished
  96. TX_EARLY        equ 0x0080  ;TX early
  97. EVENT_OVRFL     equ 0x0100  ;Event counter overflow
  98. LINK_CHANGED    equ 0x0200  ;PHY link changed
  99. ME_CISR         equ 0x44    ;Event counter INT status
  100. ME_CIER         equ 0x48    ;Event counter INT enable
  101. MR_CNT          equ 0x50    ;Successfully received packet counter
  102. ME_CNT0         equ 0x52    ;Event counter 0
  103. ME_CNT1         equ 0x54    ;Event counter 1
  104. ME_CNT2         equ 0x56    ;Event counter 2
  105. ME_CNT3         equ 0x58    ;Event counter 3
  106. MT_CNT          equ 0x5A    ;Successfully transmit packet counter
  107. ME_CNT4         equ 0x5C    ;Event counter 4
  108. MP_CNT          equ 0x5E    ;Pause frame counter register
  109. MAR0            equ 0x60    ;Hash table 0
  110. MAR1            equ 0x62    ;Hash table 1
  111. MAR2            equ 0x64    ;Hash table 2
  112. MAR3            equ 0x66    ;Hash table 3
  113. MID_0L          equ 0x68    ;Multicast address MID0 Low
  114. MID_0M          equ 0x6A    ;Multicast address MID0 Medium
  115. MID_0H          equ 0x6C    ;Multicast address MID0 High
  116. MID_1L          equ 0x70    ;MID1 Low
  117. MID_1M          equ 0x72    ;MID1 Medium
  118. MID_1H          equ 0x74    ;MID1 High
  119. MID_2L          equ 0x78    ;MID2 Low
  120. MID_2M          equ 0x7A    ;MID2 Medium
  121. MID_2H          equ 0x7C    ;MID2 High
  122. MID_3L          equ 0x80    ;MID3 Low
  123. MID_3M          equ 0x82    ;MID3 Medium
  124. MID_3H          equ 0x84    ;MID3 High
  125. PHY_CC          equ 0x88    ;PHY status change configuration register
  126. PHY_ST          equ 0x8A    ;PHY status register
  127. MAC_SM          equ 0xAC    ;MAC status machine
  128. MAC_ID          equ 0xBE    ;Identifier register
  129.  
  130. MAX_BUF_SIZE    equ 0x600   ;1536
  131.  
  132. MBCR_DEFAULT    equ 0x012A  ;MAC Bus Control Register
  133. MCAST_MAX       equ 3       ;Max number multicast addresses to filter
  134.  
  135. ;Descriptor status
  136. DSC_OWNER_MAC   equ 0x8000  ;MAC is the owner of this descriptor
  137. DSC_RX_OK       equ 0x4000  ;RX was successfull
  138. DSC_RX_ERR      equ 0x0800  ;RX PHY error
  139. DSC_RX_ERR_DRI  equ 0x0400  ;RX dribble packet
  140. DSC_RX_ERR_BUF  equ 0x0200  ;RX length exceeds buffer size
  141. DSC_RX_ERR_LONG equ 0x0100  ;RX length > maximum packet length
  142. DSC_RX_ERR_RUNT equ 0x0080  ;RX packet length < 64 byte
  143. DSC_RX_ERR_CRC  equ 0x0040  ;RX CRC error
  144. DSC_RX_BCAST    equ 0x0020  ;RX broadcast (no error)
  145. DSC_RX_MCAST    equ 0x0010  ;RX multicast (no error)
  146. DSC_RX_MCH_HIT  equ 0x0008  ;RX multicast hit in hash table (no error)
  147. DSC_RX_MIDH_HIT equ 0x0004  ;RX MID table hit (no error)
  148. DSC_RX_IDX_MID_MASK equ 3  ;RX mask for the index of matched MIDx
  149.  
  150. ;PHY settings
  151. ICPLUS_PHY_ID   equ 0x0243
  152.  
  153. RX_INTS         equ RX_FIFO_FULL or RX_NO_DESC or RX_FINISH
  154. TX_INTS         equ TX_FINISH
  155. INT_MASK        equ 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         equ 256     ; RDC MAC I/O Size
  160. MAX_MAC         equ 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.         ret     8
  796.  
  797.   .wait_to_send:
  798.  
  799.         DEBUGF  2,"Waiting for TX buffer\n"
  800.  
  801.         call    GetTimerTicks           ; returns in eax
  802.         lea     edx, [eax + 100]
  803.      .l2:
  804.         test    [edi + x_head.status], DSC_OWNER_MAC
  805.         jz      .do_send
  806.         mov     esi, 10
  807.         call    Sleep
  808.         call    GetTimerTicks
  809.         cmp     edx, eax
  810.         jl      .l2
  811.  
  812.         DEBUGF  1,"Send timeout\n"
  813.         xor     eax, eax
  814.         dec     eax
  815.   .fail:
  816.         DEBUGF  1,"Send failed\n"
  817.         ret     8
  818.  
  819.  
  820.  
  821.  
  822.  
  823. ;;;;;;;;;;;;;;;;;;;;;;;
  824. ;;                   ;;
  825. ;; Interrupt handler ;;
  826. ;;                   ;;
  827. ;;;;;;;;;;;;;;;;;;;;;;;
  828. align 4
  829. int_handler:
  830.  
  831.         DEBUGF  2,"\nIRQ %x ", eax:2   ; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO
  832.  
  833. ; Find pointer of device wich made IRQ occur
  834.  
  835.         mov     esi, device_list
  836.         mov     ecx, [devices]
  837.         test    ecx, ecx
  838.         jz      .fail
  839.   .nextdevice:
  840.         mov     ebx, dword [esi]
  841.  
  842.         ; Find reason for IRQ
  843.  
  844.         set_io  0
  845.         set_io  MISR
  846.         in      ax, dx
  847.         out     dx, ax          ; send it back to ACK
  848.  
  849.         DEBUGF  2,"MISR=%x\n", eax:4
  850.  
  851.         ; Check if we are interessed in some of the reasons
  852.  
  853.         test    ax, INT_MASK
  854.         jnz     .got_it
  855.  
  856.         ; If not, try next device
  857.  
  858.         add     esi, 4
  859.         dec     ecx
  860.         jnz     .nextdevice
  861.  
  862.   .fail:                                ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
  863.         ret
  864.  
  865. ; At this point, test for all possible reasons, and handle accordingly
  866.  
  867.   .got_it:
  868.         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.         ; Push packet size and pointer, kernel will need it..
  901.  
  902.         push    ebx
  903.         push    .more_RX
  904.  
  905.         push    ecx
  906.         push    [edx + x_head.skb_ptr]
  907.  
  908.         DEBUGF  2,"packet ptr=0x%x\n", [edx + x_head.skb_ptr]
  909.  
  910.         ; reset the RX descriptor
  911.  
  912.         push    edx
  913.         stdcall KernelAlloc, MAX_BUF_SIZE
  914.         pop     edx
  915.         mov     [edx + x_head.skb_ptr], eax
  916.         GetRealAddr
  917.         mov     [edx + x_head.buf], eax
  918.         mov     [edx + x_head.status], DSC_OWNER_MAC
  919.  
  920.         ; Use next descriptor next time
  921.  
  922.         inc     [device.cur_rx]
  923.         and     [device.cur_rx], RX_RING_SIZE - 1
  924.  
  925.         ; At last, send packet to kernel
  926.  
  927.         jmp     EthReceiver
  928.  
  929.  
  930.   .no_RX:
  931.  
  932.         test    word [esp], TX_FINISH
  933.         jz      .no_TX
  934.  
  935.       .loop_tx:
  936.         movzx   edi, [device.last_tx]
  937.         shl     edi, 5
  938.         lea     edi, [device.tx_ring + edi]
  939.  
  940.         test    [edi + x_head.status], DSC_OWNER_MAC
  941.         jnz     .no_TX
  942.  
  943.         cmp     [edi + x_head.skb_ptr], 0
  944.         je      .no_TX
  945.  
  946.         DEBUGF  2,"Freeing buffer 0x%x\n", [edi + x_head.skb_ptr]
  947.  
  948.         push    [edi + x_head.skb_ptr]
  949.         mov     [edi + x_head.skb_ptr], 0
  950.         call    KernelFree
  951.  
  952.         inc     [device.last_tx]
  953.         and     [device.last_tx], TX_RING_SIZE - 1
  954.  
  955.         jmp     .loop_tx
  956.  
  957.   .no_TX:
  958.         pop     ax
  959.         ret
  960.  
  961.  
  962.  
  963.  
  964. align 4
  965. init_mac_regs:
  966.  
  967.         DEBUGF  2,"initializing MAC regs\n"
  968.  
  969.         ; MAC operation register
  970.         mov     ax, 1
  971.         set_io  0
  972.         set_io  MCR1
  973.         out     dx, ax
  974.         ; Reset MAC
  975.         mov     ax, 2
  976.         set_io  MAC_SM
  977.         out     dx, ax
  978.         ; Reset internal state machine
  979.         xor     ax, ax
  980.         out     dx, ax
  981.         mov     esi, 5
  982.         stdcall Sleep
  983.  
  984.         call    read_mac
  985.  
  986.         ret
  987.  
  988.  
  989.  
  990.  
  991. ; Read a word data from PHY Chip
  992.  
  993. align 4
  994. proc  phy_read stdcall, phy_addr:dword, reg:dword
  995.  
  996.         DEBUGF  2,"PHY read, addr=0x%x reg=0x%x\n", [phy_addr]:8, [reg]:8
  997.  
  998.         mov     eax, [phy_addr]
  999.         shl     eax, 8
  1000.         add     eax, [reg]
  1001.         add     eax, MDIO_READ
  1002.         set_io  0
  1003.         set_io  MMDIO
  1004.         out     dx, ax
  1005.  
  1006.         ;Wait for the read bit to be cleared.
  1007.         mov     ecx, 2048 ;limit
  1008.   .read:
  1009.         in      ax, dx
  1010.         test    ax, MDIO_READ
  1011.         jz      @f
  1012.         dec     ecx
  1013.         jnz     .read
  1014.   @@:
  1015.  
  1016.         set_io  MMRD
  1017.         in      ax, dx
  1018.         and     eax, 0xFFFF
  1019.  
  1020.         DEBUGF  2,"PHY read, val=0x%x\n", eax:4
  1021.  
  1022.         ret
  1023.  
  1024. endp
  1025.  
  1026.  
  1027.  
  1028.  
  1029. ; Write a word data to PHY Chip
  1030.  
  1031. align 4
  1032. proc  phy_write stdcall, phy_addr:dword, reg:dword, val:dword
  1033.  
  1034.         DEBUGF  2,"PHY write, addr=0x%x reg=0x%x val=0x%x\n", [phy_addr]:8, [reg]:8, [val]:8
  1035.  
  1036.         mov     eax, [val]
  1037.         set_io  0
  1038.         set_io  MMWD
  1039.         out     dx, ax
  1040.  
  1041.         ;Write the command to the MDIO bus
  1042.  
  1043.         mov     eax, [phy_addr]
  1044.         shl     eax, 8
  1045.         add     eax, [reg]
  1046.         add     eax, MDIO_WRITE
  1047.         set_io  MMDIO
  1048.         out     dx, ax
  1049.  
  1050.         ;Wait for the write bit to be cleared.
  1051.         mov     ecx, 2048 ;limit
  1052.   .write:
  1053.         in      ax, dx
  1054.         test    ax, MDIO_WRITE
  1055.         jz      @f
  1056.         dec     ecx
  1057.         jnz     .write
  1058.   @@:
  1059.  
  1060.         DEBUGF  2,"PHY write ok\n"
  1061.  
  1062.         ret
  1063. endp
  1064.  
  1065.  
  1066.  
  1067. align 4
  1068. read_mac:
  1069.  
  1070.         DEBUGF  2,"Reading MAC: "
  1071.  
  1072.         mov     cx, 3
  1073.         lea     edi, [device.mac]
  1074.         set_io  0
  1075.         set_io  MID_0L
  1076.      .mac:
  1077.         in      ax, dx
  1078.         stosw
  1079.         inc     dx
  1080.         inc     dx
  1081.         dec     cx
  1082.         jnz     .mac
  1083.  
  1084.         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
  1085.  
  1086.         ret
  1087.  
  1088.  
  1089.  
  1090.  
  1091. ; End of code
  1092.  
  1093. section '.data' data readable writable align 16 ; place all uninitialized data place here
  1094. align 4                                         ; Place all initialised data here
  1095.  
  1096. devices         dd 0
  1097. version         dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
  1098. my_service      db 'R6040',0                    ; max 16 chars include zero
  1099.  
  1100. include_debug_strings                           ; All data wich FDO uses will be included here
  1101.  
  1102. device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
  1103.  
  1104.