Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2018. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  FORCEDETH.INC                                                  ;;
  7. ;;                                                                 ;;
  8. ;;  Ethernet driver for Kolibri OS                                 ;;
  9. ;;                                                                 ;;
  10. ;;  Driver for chips of NVIDIA nForce2                             ;;
  11. ;;  References:                                                    ;;
  12. ;;    forcedeth.c - linux driver (etherboot project)               ;;
  13. ;;    ethernet driver template by Mike Hibbett                     ;;
  14. ;;                                                                 ;;
  15. ;;  The copyright statement is                                     ;;
  16. ;;                                                                 ;;
  17. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  18. ;;             Version 2, June 1991                                ;;
  19. ;;                                                                 ;;
  20. ;;  Copyright 2008 shurf,                                          ;;
  21. ;;   cit.utc@gmail.com                                             ;;
  22. ;;                                                                 ;;
  23. ;;  See file COPYING for details                                   ;;
  24. ;;                                                                 ;;
  25. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  26.  
  27.  
  28. format PE DLL native
  29. entry START
  30.  
  31.         CURRENT_API             = 0x0200
  32.         COMPATIBLE_API          = 0x0100
  33.         API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
  34.  
  35.         MAX_DEVICES             = 16
  36.  
  37.         RBLEN                   = 0     ; Receive buffer size: 0=4K 1=8k 2=16k 3=32k 4=64k
  38.                                         ; FIXME: option 1 and 2 may allocate a non contiguous buffer causing data loss!
  39.  
  40.         DEBUG                   = 1
  41.         __DEBUG__               = 1
  42.         __DEBUG_LEVEL__         = 2
  43.  
  44.         RX_RING                 = 4
  45.         TX_RING                 = 4
  46.  
  47. section '.flat' readable writable executable
  48.  
  49. include '../proc32.inc'
  50. include '../struct.inc'
  51. include '../macros.inc'
  52. include '../fdo.inc'
  53. include '../netdrv.inc'
  54. include '../mii.inc'
  55.  
  56. ;**************************************************************************
  57. ; forcedeth Register Definitions
  58. ;**************************************************************************
  59.  
  60. PCI_DEVICE_ID_NVIDIA_NVENET_1   = 0x01c3
  61. PCI_DEVICE_ID_NVIDIA_NVENET_2   = 0x0066
  62. PCI_DEVICE_ID_NVIDIA_NVENET_4   = 0x0086
  63. PCI_DEVICE_ID_NVIDIA_NVENET_5   = 0x008c
  64. PCI_DEVICE_ID_NVIDIA_NVENET_3   = 0x00d6
  65. PCI_DEVICE_ID_NVIDIA_NVENET_7   = 0x00df
  66. PCI_DEVICE_ID_NVIDIA_NVENET_6   = 0x00e6
  67. PCI_DEVICE_ID_NVIDIA_NVENET_8   = 0x0056
  68. PCI_DEVICE_ID_NVIDIA_NVENET_9   = 0x0057
  69. PCI_DEVICE_ID_NVIDIA_NVENET_10  = 0x0037
  70. PCI_DEVICE_ID_NVIDIA_NVENET_11  = 0x0038
  71. PCI_DEVICE_ID_NVIDIA_NVENET_12  = 0x0268
  72. PCI_DEVICE_ID_NVIDIA_NVENET_13  = 0x0269
  73. PCI_DEVICE_ID_NVIDIA_NVENET_14  = 0x0372
  74. PCI_DEVICE_ID_NVIDIA_NVENET_15  = 0x0373
  75.  
  76. UNKSETUP1_VAL             = 0x16070f
  77. UNKSETUP2_VAL             = 0x16
  78. UNKSETUP3_VAL1            = 0x200010
  79. UNKSETUP4_VAL             = 8
  80. UNKSETUP5_BIT31           = (1 shl 31)
  81. UNKSETUP6_VAL             = 3
  82.  
  83. TXRXCTL_RXCHECK           = 0x0400
  84. MIISTAT_ERROR             = 0x0001
  85. MIISTAT_MASK              = 0x000f
  86. MIISTAT_MASK2             = 0x000f
  87. MIICTL_INUSE              = 0x08000
  88. MIICTL_WRITE              = 0x00400
  89. MIICTL_ADDRSHIFT          = 5
  90.  
  91. MIISPEED_BIT8             = (1 shl 8)
  92. MIIDELAY                  = 5
  93.  
  94. IRQ_RX_ERROR              = 0x0001
  95. IRQ_RX                    = 0x0002
  96. IRQ_RX_NOBUF              = 0x0004
  97. IRQ_TX_ERROR              = 0x0008
  98. IRQ_TX_OK                 = 0x0010
  99. IRQ_TIMER                 = 0x0020
  100. IRQ_LINK                  = 0x0040
  101. IRQ_RX_FORCED             = 0x0080
  102. IRQ_TX_FORCED             = 0x0100
  103. IRQ_RECOVER_ERROR         = 0x8200                                           ;
  104. IRQMASK_WANTED_2          = IRQ_TX_FORCED + IRQ_LINK + IRQ_RX_ERROR + IRQ_RX + IRQ_TX_OK + IRQ_TX_ERROR
  105.  
  106. IRQ_RX_ALL                = IRQ_RX_ERROR or IRQ_RX or IRQ_RX_NOBUF or IRQ_RX_FORCED
  107. IRQ_TX_ALL                = IRQ_TX_ERROR or IRQ_TX_OK or IRQ_TX_FORCED
  108. IRQ_OTHER                 = IRQ_LINK or IRQ_TIMER or IRQ_RECOVER_ERROR
  109.  
  110. IRQSTAT_MASK              = 0x1ff
  111.  
  112. TXRXCTL_KICK              = 0x0001
  113. TXRXCTL_BIT1              = 0x0002
  114. TXRXCTL_BIT2              = 0x0004
  115. TXRXCTL_IDLE              = 0x0008
  116. TXRXCTL_RESET             = 0x0010
  117. TXRXCTL_RXCHECK           = 0x0400
  118.  
  119. MCASTADDRA_FORCE          = 0x01
  120.  
  121. MAC_RESET_ASSERT          = 0x0F3
  122.  
  123. MISC1_HD                  = 0x02
  124. MISC1_FORCE               = 0x3b0f3c
  125.  
  126. PFF_ALWAYS                = 0x7F0008
  127. PFF_PROMISC               = 0x80
  128. PFF_MYADDR                = 0x20
  129.  
  130. OFFLOAD_HOMEPHY           = 0x601
  131. OFFLOAD_NORMAL            = 4096 shl RBLEN
  132.  
  133. RNDSEED_MASK              = 0x00ff
  134. RNDSEED_FORCE             = 0x7f00
  135. RNDSEED_FORCE2            = 0x2d00
  136. RNDSEED_FORCE3            = 0x7400
  137.  
  138. ; POLL_DEFAULT is the interval length of the timer source on the nic
  139. ; POLL_DEFAULT=97 would result in an interval length of 1 ms
  140. POLL_DEFAULT              = 970
  141.  
  142. ADAPTCTL_START            = 0x02
  143. ADAPTCTL_LINKUP           = 0x04
  144. ADAPTCTL_PHYVALID         = 0x40000
  145. ADAPTCTL_RUNNING          = 0x100000
  146. ADAPTCTL_PHYSHIFT         = 24
  147.  
  148. WAKEUPFLAGS_VAL           = 0x7770
  149.  
  150. POWERSTATE_POWEREDUP      = 0x8000
  151. POWERSTATE_VALID          = 0x0100
  152. POWERSTATE_MASK           = 0x0003
  153. POWERSTATE_D0             = 0x0000
  154. POWERSTATE_D1             = 0x0001
  155. POWERSTATE_D2             = 0x0002
  156. POWERSTATE_D3             = 0x0003
  157.  
  158. POWERSTATE2_POWERUP_MASK  = 0x0F11
  159. POWERSTATE2_POWERUP_REV_A3= 0x0001
  160.  
  161. RCVCTL_START              = 0x01
  162. RCVSTAT_BUSY              = 0x01
  163.  
  164. XMITCTL_START             = 0x01
  165.  
  166. LINKSPEED_FORCE           = 0x10000
  167. LINKSPEED_10              = 1000
  168. LINKSPEED_100             = 100
  169. LINKSPEED_1000            = 50
  170.  
  171. RINGSZ_TXSHIFT            = 0
  172. RINGSZ_RXSHIFT            = 16
  173.  
  174. LPA_1000FULL                    = 0x0800
  175.  
  176. ; Link partner ability register.
  177. LPA_SLCT                        = 0x001f  ; Same as advertise selector
  178. LPA_10HALF                      = 0x0020  ; Can do 10mbps half-duplex
  179. LPA_10FULL                      = 0x0040  ; Can do 10mbps full-duplex
  180. LPA_100HALF                     = 0x0080  ; Can do 100mbps half-duplex
  181. LPA_100FULL                     = 0x0100  ; Can do 100mbps full-duplex
  182. LPA_100BASE4                    = 0x0200  ; Can do 100mbps 4k packets
  183. LPA_RESV                        = 0x1c00  ; Unused...
  184. LPA_RFAULT                      = 0x2000  ; Link partner faulted
  185. LPA_LPACK                       = 0x4000  ; Link partner acked us
  186. LPA_NPAGE                       = 0x8000  ; Next page bit
  187.  
  188. MII_READ                        = (-1)
  189. MII_PHYSID1                     = 0x02    ; PHYS ID 1
  190. MII_PHYSID2                     = 0x03    ; PHYS ID 2
  191. MII_BMCR                        = 0x00    ; Basic mode control register
  192. MII_BMSR                        = 0x01    ; Basic mode status register
  193. MII_ADVERTISE                   = 0x04    ; Advertisement control reg
  194. MII_LPA                         = 0x05    ; Link partner ability reg
  195. MII_SREVISION                   = 0x16    ; Silicon revision
  196. MII_RESV1                       = 0x17    ; Reserved...
  197. MII_NCONFIG                     = 0x1c    ; Network interface config
  198.  
  199. ; PHY defines
  200. PHY_OUI_MARVELL                 = 0x5043
  201. PHY_OUI_CICADA                  = 0x03f1
  202. PHYID1_OUI_MASK                 = 0x03ff
  203. PHYID1_OUI_SHFT                 = 6
  204. PHYID2_OUI_MASK                 = 0xfc00
  205. PHYID2_OUI_SHFT                 = 10
  206. PHY_INIT1                       = 0x0f000
  207. PHY_INIT2                       = 0x0e00
  208. PHY_INIT3                       = 0x01000
  209. PHY_INIT4                       = 0x0200
  210. PHY_INIT5                       = 0x0004
  211. PHY_INIT6                       = 0x02000
  212. PHY_GIGABIT                     = 0x0100
  213.  
  214. PHY_TIMEOUT                     = 0x1
  215. PHY_ERROR                       = 0x2
  216.  
  217. PHY_100                         = 0x1
  218. PHY_1000                        = 0x2
  219. PHY_HALF                        = 0x100
  220.  
  221. PHY_RGMII                       = 0x10000000
  222.  
  223. ; desc_ver values:
  224. ; This field has two purposes:
  225. ; - Newer nics uses a different ring layout. The layout is selected by
  226. ;   comparing np->desc_ver with DESC_VER_xy.
  227. ; - It contains bits that are forced on when writing to TxRxControl.
  228. DESC_VER_1                      = 0x0
  229. DESC_VER_2                      = (0x02100 or TXRXCTL_RXCHECK)
  230.  
  231. NV_TX_LASTPACKET                = (1 shl 16)
  232. NV_TX_RETRYERROR                = (1 shl 19)
  233. NV_TX_LASTPACKET1               = (1 shl 24)
  234. NV_TX_DEFERRED                  = (1 shl 26)
  235. NV_TX_CARRIERLOST               = (1 shl 27)
  236. NV_TX_LATECOLLISION             = (1 shl 28)
  237. NV_TX_UNDERFLOW                 = (1 shl 29)
  238. NV_TX_ERROR                     = (1 shl 30)
  239. NV_TX_VALID                     = (1 shl 31)
  240.  
  241. NV_TX2_LASTPACKET               = (1 shl 29)
  242. NV_TX2_RETRYERROR               = (1 shl 18)
  243. NV_TX2_LASTPACKET1              = (1 shl 23)
  244. NV_TX2_DEFERRED                 = (1 shl 25)
  245. NV_TX2_CARRIERLOST              = (1 shl 26)
  246. NV_TX2_LATECOLLISION            = (1 shl 27)
  247. NV_TX2_UNDERFLOW                = (1 shl 28)
  248. ; error and valid are the same for both
  249. NV_TX2_ERROR                    = (1 shl 30)
  250. NV_TX2_VALID                    = (1 shl 31)
  251.  
  252. NV_RX_DESCRIPTORVALID           = (1 shl 16)
  253. NV_RX_AVAIL                     = (1 shl 31)
  254.  
  255. NV_RX2_DESCRIPTORVALID          = (1 shl 29)
  256.  
  257. FLAG_MASK_V1                    = 0xffff0000
  258. FLAG_MASK_V2                    = 0xffffc000
  259. LEN_MASK_V1                     = (0xffffffff xor FLAG_MASK_V1)
  260. LEN_MASK_V2                     = (0xffffffff xor FLAG_MASK_V2)
  261.  
  262. ; Miscelaneous hardware related defines:
  263. NV_PCI_REGSZ_VER1               = 0x270
  264. NV_PCI_REGSZ_VER2               = 0x604
  265. ; various timeout delays: all in usec
  266. NV_TXRX_RESET_DELAY             = 4
  267. NV_TXSTOP_DELAY1                = 10
  268. NV_TXSTOP_DELAY1MAX             = 500000
  269. NV_TXSTOP_DELAY2                = 100
  270. NV_RXSTOP_DELAY1                = 10
  271. NV_RXSTOP_DELAY1MAX             = 500000
  272. NV_RXSTOP_DELAY2                = 100
  273. NV_SETUP5_DELAY                 = 5
  274. NV_SETUP5_DELAYMAX              = 50000
  275. NV_POWERUP_DELAY                = 5
  276. NV_POWERUP_DELAYMAX             = 5000
  277. NV_MIIBUSY_DELAY                = 50
  278. NV_MIIPHY_DELAY                 = 10
  279. NV_MIIPHY_DELAYMAX              = 10000
  280. NV_MAC_RESET_DELAY              = 64
  281. NV_WAKEUPPATTERNS               = 5
  282. NV_WAKEUPMASKENTRIES            = 4
  283.  
  284. struct  TxDesc
  285.         PacketBuffer            dd ?
  286.         FlagLen                 dd ?
  287. ends
  288.  
  289. struct  RxDesc
  290.         PacketBuffer            dd ?
  291.         FlagLen                 dd ?
  292. ends
  293.  
  294. struct  device                  ETH_DEVICE
  295.  
  296.         pci_bus                 dd ?
  297.         pci_dev                 dd ?
  298.  
  299.         mmio_addr               dd ?
  300.         vendor_id               dw ?
  301.         device_id               dw ?
  302.         txflags                 dd ?
  303.         desc_ver                dd ?
  304.         irqmask                 dd ?
  305.         wolenabled              dd ?
  306.         in_shutdown             dd ?
  307.         cur_rx                  dd ?
  308.         cur_tx                  dd ?
  309.         last_tx                 dd ?
  310.         phyaddr                 dd ?
  311.         phy_oui                 dd ?
  312.         gigabit                 dd ?
  313.         needs_mac_reset         dd ?
  314.         linkspeed               dd ?
  315.         duplex                  dd ?
  316.         nocable                 dd ?
  317.  
  318.                                 rb 0x100 - ($ and 0xff)
  319.         tx_ring                 rd (TX_RING * sizeof.TxDesc) /4*2
  320.  
  321.                                 rb 0x100 - ($ and 0xff)
  322.         rx_ring                 rd (RX_RING * sizeof.RxDesc) /4*2
  323.  
  324. ends
  325.  
  326.  
  327.  
  328. virtual at edi
  329.         IrqStatus               dd ?
  330.         IrqMask                 dd ?
  331.         UnknownSetupReg6        dd ?
  332.         PollingInterval         dd ?
  333. end virtual
  334.  
  335. virtual at edi + 0x3c
  336.         MacReset                dd ?
  337. end virtual
  338.  
  339. virtual at edi + 0x80
  340.         Misc1                   dd ?
  341.         TransmitterControl      dd ?
  342.         TransmitterStatus       dd ?
  343.         PacketFilterFlags       dd ?
  344.         OffloadConfig           dd ?
  345.         ReceiverControl         dd ?
  346.         ReceiverStatus          dd ?
  347.         RandomSeed              dd ?
  348.         UnknownSetupReg1        dd ?
  349.         UnknownSetupReg2        dd ?
  350.         MacAddrA                dd ?
  351.         MacAddrB                dd ?
  352.         MulticastAddrA          dd ?
  353.         MulticastAddrB          dd ?
  354.         MulticastMaskA          dd ?
  355.         MulticastMaskB          dd ?
  356.         PhyInterface            dd ?
  357. end virtual
  358.  
  359. virtual at edi + 0x100
  360.         TxRingPhysAddr          dd ?
  361.         RxRingPhysAddr          dd ?
  362.         RingSizes               dd ?
  363.         UnknownTransmitterReg   dd ?
  364.         LinkSpeed               dd ?
  365. end virtual
  366.  
  367. virtual at edi + 0x130
  368.         UnknownSetupReg5        dd ?
  369. end virtual
  370.  
  371. virtual at edi + 0x13c
  372.         UnknownSetupReg3        dd ?
  373. end virtual
  374.  
  375. virtual at edi + 0x144
  376.         TxRxControl             dd ?
  377. end virtual
  378.  
  379. virtual at edi + 0x180
  380.         MIIStatus               dd ?
  381.         UnknownSetupReg4        dd ?
  382.         AdapterControl          dd ?
  383.         MIISpeed                dd ?
  384.         MIIControl              dd ?
  385.         MIIData                 dd ?
  386. end virtual
  387.  
  388. virtual at edi + 0x200
  389.         WakeUpFlags             dd ?
  390. end virtual
  391.  
  392. virtual at edi + 0x26c
  393.         PowerState              dd ?
  394. end virtual
  395.  
  396. virtual at edi + 0x600
  397.         PowerState2             dd ?
  398. end virtual
  399.  
  400.  
  401.  
  402. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  403. ;;                        ;;
  404. ;; proc START             ;;
  405. ;;                        ;;
  406. ;; (standard driver proc) ;;
  407. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  408.  
  409. proc START c, reason:dword, cmdline:dword
  410.  
  411.         cmp     [reason], DRV_ENTRY
  412.         jne     .fail
  413.  
  414.         DEBUGF  2,"Loading driver\n"
  415.         invoke  RegService, my_service, service_proc
  416.         ret
  417.  
  418.   .fail:
  419.         xor     eax, eax
  420.         ret
  421.  
  422. endp
  423.  
  424.  
  425. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  426. ;;                        ;;
  427. ;; proc SERVICE_PROC      ;;
  428. ;;                        ;;
  429. ;; (standard driver proc) ;;
  430. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  431.  
  432. proc service_proc stdcall, ioctl:dword
  433.  
  434.         mov     edx, [ioctl]
  435.         mov     eax, [edx + IOCTL.io_code]
  436.  
  437. ;------------------------------------------------------
  438.  
  439.         cmp     eax, 0 ;SRV_GETVERSION
  440.         jne     @F
  441.  
  442.         cmp     [edx + IOCTL.out_size], 4
  443.         jb      .fail
  444.         mov     eax, [edx + IOCTL.output]
  445.         mov     [eax], dword API_VERSION
  446.  
  447.         xor     eax, eax
  448.         ret
  449.  
  450. ;------------------------------------------------------
  451.   @@:
  452.         cmp     eax, 1 ;SRV_HOOK
  453.         jne     .fail
  454.  
  455.         cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
  456.         jb      .fail
  457.  
  458.         mov     eax, [edx + IOCTL.input]
  459.         cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
  460.         jne     .fail                                   ; other types arent supported for this card yet
  461.  
  462. ; check if the device is already listed
  463.  
  464.         mov     esi, device_list
  465.         mov     ecx, [devices]
  466.         test    ecx, ecx
  467.         jz      .firstdevice
  468.  
  469. ;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
  470.         mov     ax, [eax+1]
  471.   .nextdevice:
  472.         mov     ebx, [esi]
  473.         cmp     al, byte [ebx + device.pci_bus]               ; compare with pci and device num in device list (notice the usage of word instead of byte)
  474.         jne     @f
  475.         cmp     ah, byte [ebx + device.pci_dev]
  476.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  477.   @@:
  478.         add     esi, 4
  479.         loop    .nextdevice
  480.  
  481.  
  482. ; This device doesnt have its own eth_device structure yet, lets create one
  483.   .firstdevice:
  484.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  485.         jae     .fail
  486.  
  487.         allocate_and_clear ebx, sizeof.device, .fail      ; Allocate the buffer for device structure
  488.  
  489. ; Fill in the direct call addresses into the struct
  490.  
  491.         mov     [ebx + device.reset], reset
  492.         mov     [ebx + device.transmit], transmit
  493.         mov     [ebx + device.unload], .fail
  494.         mov     [ebx + device.name], my_service
  495.  
  496. ; save the pci bus and device numbers
  497.  
  498.         mov     eax, [edx + IOCTL.input]
  499.         movzx   ecx, byte [eax+1]
  500.         mov     [ebx + device.pci_bus], ecx
  501.         movzx   ecx, byte [eax+2]
  502.         mov     [ebx + device.pci_dev], ecx
  503.  
  504.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x\n", [ebx + device.pci_dev], [ebx + device.pci_bus]
  505.  
  506. ; Ok, the eth_device structure is ready, let's probe the device
  507.         call    probe                                                   ; this function will output in eax
  508.         test    eax, eax
  509.         jnz     .err                                                    ; If an error occured, exit
  510.  
  511.         mov     eax, [devices]                                          ; Add the device structure to our device list
  512.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  513.         inc     [devices]                                               ;
  514.  
  515.         mov     [ebx + device.type], NET_TYPE_ETH
  516.         invoke  NetRegDev
  517.  
  518.         cmp     eax, -1
  519.         je      .destroy
  520.  
  521.         ret
  522.  
  523. ; If the device was already loaded, find the device number and return it in eax
  524.  
  525.   .find_devicenum:
  526.         DEBUGF  1,"Trying to find device number of already registered device\n"
  527.         invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  528.                                                                         ; into a device number in edi
  529.         mov     eax, edi                                                ; Application wants it in eax instead
  530.         DEBUGF  1,"Kernel says: %u\n", eax
  531.         ret
  532.  
  533. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  534.  
  535.   .destroy:
  536.         ; todo: reset device into virgin state
  537.  
  538.   .err:
  539.         invoke  KernelFree, ebx
  540.   .fail:
  541.  
  542.         ret
  543.  
  544. ;------------------------------------------------------
  545. endp
  546.  
  547.  
  548. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  549. ;;                                                                        ;;
  550. ;;        Actual Hardware dependent code starts here                      ;;
  551. ;;                                                                        ;;
  552. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  553.  
  554.  
  555.  
  556.  
  557. ;***************************************************************************
  558. ;   Function
  559. ;      probe
  560. ;   Description
  561. ;      Searches for an ethernet card, enables it and clears the rx buffer
  562. ;
  563. ;***************************************************************************
  564. align 4
  565. probe:
  566.  
  567.         DEBUGF  1,"probe\n"
  568.  
  569.         mov     [ebx + device.needs_mac_reset], 0
  570.  
  571. ; Make the device a bus master and enable response in I/O space
  572.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
  573.         or      al, PCI_CMD_MASTER + PCI_CMD_PIO ; + PCI_CMD_MMIO
  574.         invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
  575.  
  576. ; Adjust PCI latency to be at least 32
  577.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.max_latency
  578.         cmp     al, 32
  579.         jae     @f
  580.         mov     al, 32
  581.         invoke  PciWrite8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.max_latency, eax
  582.   @@:
  583.  
  584. ; Now, it's time to find the base mmio addres of the PCI device
  585.         stdcall PCI_find_mmio, [ebx + device.pci_bus], [ebx + device.pci_dev] ; returns in eax
  586.         test    eax, eax
  587.         jnz     @f
  588.         DEBUGF 1, "No useable MMIO addresses found!\n"
  589.         dec     eax
  590.         ret
  591.   @@:
  592.         DEBUGF 1,"mmio_addr= 0x%x\n", eax
  593.  
  594. ; Create virtual mapping of the physical memory
  595.         invoke  MapIoMem, eax, 10000h, PG_SW + PG_NOCACHE
  596.         test    eax, eax
  597.         jz      fail
  598.         mov     [ebx + device.mmio_addr], eax
  599.         DEBUGF 1,"mapped mmio_addr= 0x%x\n", eax
  600.  
  601. ; Read PCI vendor/device ID
  602.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.vendor_id
  603.         mov     dword[ebx + device.vendor_id], eax
  604.         DEBUGF 1,"vendor = 0x%x\n", [ebx + device.vendor_id]:4
  605.         DEBUGF 1,"device = 0x%x\n", [ebx + device.device_id]:4
  606.  
  607. ;-------------------------------------
  608. ; handle different descriptor versions
  609.         mov     [ebx + device.desc_ver], DESC_VER_1
  610.         mov     ax, [ebx + device.device_id]
  611.         cmp     ax, PCI_DEVICE_ID_NVIDIA_NVENET_1
  612.         je      .ver1
  613.         cmp     ax, PCI_DEVICE_ID_NVIDIA_NVENET_2
  614.         je      .ver1
  615.         cmp     ax, PCI_DEVICE_ID_NVIDIA_NVENET_3
  616.         je      .ver1
  617.         mov     [ebx + device.desc_ver], DESC_VER_2
  618.   .ver1:
  619.  
  620.         call    read_mac
  621.  
  622.         ; disable WOL
  623.         mov     [WakeUpFlags], 0
  624.         mov     [ebx + device.wolenabled], 0
  625.        
  626.         mov     [ebx + device.txflags], (NV_TX2_LASTPACKET or NV_TX2_VALID)
  627.         cmp     [ebx + device.desc_ver], DESC_VER_1
  628.         jne     @f
  629.         mov     [ebx + device.txflags], (NV_TX_LASTPACKET or NV_TX_VALID)
  630.       @@:
  631.  
  632. ; BEGIN of switch (pci->dev_id)
  633.  
  634.         cmp     [ebx + device.device_id], 0x01C3
  635.         jne     .not_0x01c3
  636.         ; nforce
  637.         mov     [ebx + device.irqmask], (IRQMASK_WANTED_2 or IRQ_TIMER)         ;;; Was 0
  638.         jmp     .find_phy
  639.   .not_0x01c3:
  640.  
  641.         cmp     [ebx + device.device_id], 0x0066
  642.         je      @f
  643.         cmp     [ebx + device.device_id], 0x00D6
  644.         jne     .not_0x0066
  645.   @@:
  646.         mov     [ebx + device.irqmask], (IRQMASK_WANTED_2 or IRQ_TIMER)         ;;;; was 0
  647.         cmp     [ebx + device.desc_ver], DESC_VER_1
  648.         jne     @f
  649.         or      [ebx + device.txflags], NV_TX_LASTPACKET1
  650.         jmp     .find_phy
  651.   @@:
  652.         or      [ebx + device.txflags], NV_TX2_LASTPACKET1
  653.         jmp     .find_phy
  654.   .not_0x0066:
  655.  
  656.         cmp     [ebx + device.device_id], 0x0086
  657.         je      @f
  658.         cmp     [ebx + device.device_id], 0x008c
  659.         je      @f
  660.         cmp     [ebx + device.device_id], 0x00e6
  661.         je      @f
  662.         cmp     [ebx + device.device_id], 0x00df
  663.         je      @f
  664.         cmp     [ebx + device.device_id], 0x0056
  665.         je      @f
  666.         cmp     [ebx + device.device_id], 0x0057
  667.         je      @f
  668.         cmp     [ebx + device.device_id], 0x0037
  669.         je      @f
  670.         cmp     [ebx + device.device_id], 0x0038
  671.         jne     .not_0x0086
  672.  
  673.       @@:
  674.         mov     [ebx + device.irqmask], (IRQMASK_WANTED_2 or IRQ_TIMER) ;;; was 0
  675.  
  676.         cmp     [ebx + device.desc_ver], DESC_VER_1
  677.         jne     @f
  678.         or      [ebx + device.txflags], NV_TX_LASTPACKET1
  679.         jmp     .find_phy
  680.        @@:
  681.         or      [ebx + device.txflags], NV_TX2_LASTPACKET1
  682.         jmp     .find_phy
  683.   .not_0x0086:
  684.  
  685. ;       cmp     word [device_id], 0x0268
  686. ;       je      @f
  687. ;       cmp     word [device_id], 0x0269
  688. ;       je      @f
  689. ;       cmp     word [device_id], 0x0372
  690. ;       je      @f
  691. ;       cmp     word [device_id], 0x0373
  692. ;       je      @f
  693. ;       jmp     .default_switch
  694. ;@@:
  695.         cmp     [ebx + device.device_id], 0x0268
  696.         jb      .undefined
  697.  
  698. ; Get device revision
  699.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header.revision_id
  700.         mov     edi, [ebx + device.mmio_addr]   ;;;;;
  701.  
  702. ; take phy and nic out of low power mode
  703.         mov     ecx, [PowerState2]
  704.         and     ecx, not POWERSTATE2_POWERUP_MASK
  705.         cmp     [ebx + device.device_id], PCI_DEVICE_ID_NVIDIA_NVENET_12
  706.         je      @f
  707.         cmp     [ebx + device.device_id], PCI_DEVICE_ID_NVIDIA_NVENET_13
  708.         jne     .set_powerstate
  709.   @@:
  710.         cmp     al, 0xA3
  711.         jb      .set_powerstate
  712.         or      ecx, POWERSTATE2_POWERUP_REV_A3
  713.   .set_powerstate:
  714.         mov     [PowerState2], ecx
  715.  
  716.         ; DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ
  717.         mov     [ebx + device.irqmask], (IRQMASK_WANTED_2 or IRQ_TIMER)         ; was 0
  718.        
  719.         mov     [ebx + device.needs_mac_reset], 1
  720.         cmp     [ebx + device.desc_ver], DESC_VER_1
  721.         jne     @f
  722.         or      [ebx + device.txflags], NV_TX_LASTPACKET1
  723.         jmp     .find_phy
  724.  
  725.        @@:
  726.         cmp     [ebx + device.desc_ver], DESC_VER_2
  727.         jne     .undefined
  728.         or      [ebx + device.txflags], NV_TX2_LASTPACKET1
  729.         jmp     .find_phy
  730.  
  731.   .undefined:
  732.         DEBUGF  2,"Your card was undefined in this driver.\n"
  733.         or      eax, -1
  734.         ret
  735.  
  736. ; Find a suitable phy
  737. ; Start with address 1 to 31, then do 0, then fail
  738.  
  739.   .find_phy:
  740.         xor     edx, edx
  741.   .phy_loop:
  742.         inc     edx
  743.         and     edx, 0x1f       ; phyaddr = i & 0x1f
  744.         mov     eax, MII_PHYSID1
  745.         mov     ecx, MII_READ
  746.         call    mii_rw          ; EDX - addr, EAX - miireg, ECX - value
  747.  
  748.         cmp     eax, 0x0000ffff
  749.         je      .try_next
  750.         test    eax, 0x80000000
  751.         jnz     .try_next
  752.         mov     esi, eax
  753.  
  754.         mov     eax, MII_PHYSID2
  755.         mov     ecx, MII_READ
  756.         call    mii_rw
  757.  
  758.         cmp     eax, 0x0000ffff
  759.         je      .try_next
  760.         test    eax, 0x80000000
  761.         jnz     .try_next
  762.         jmp     .got_it
  763.  
  764.   .try_next:
  765.         test    edx, edx
  766.         jnz     .phy_loop
  767.  
  768.         ; PHY in isolate mode? No phy attached and user wants to test loopback?
  769.         ; Very odd, but can be correct.
  770.        
  771.         DEBUGF  2,"Could not find a valid PHY.\n"
  772.         jmp     .no_phy
  773.  
  774.   .got_it:
  775.         and     esi, PHYID1_OUI_MASK
  776.         shl     esi, PHYID1_OUI_SHFT
  777.         and     eax, PHYID2_OUI_MASK
  778.         shr     eax, PHYID2_OUI_SHFT
  779.         or      eax, esi
  780.  
  781.         mov     [ebx + device.phyaddr], edx
  782.         mov     [ebx + device.phy_oui], eax
  783.  
  784.         DEBUGF 1,"Found PHY with OUI:0x%x at address:0x%x\n", eax, edx
  785.  
  786.         call    phy_init
  787.  
  788.   .no_phy:
  789.  
  790.         cmp     [ebx + device.needs_mac_reset], 0
  791.         je      @f
  792.         call    mac_reset
  793.   @@:
  794.        
  795. ;***************************************************************************
  796. ;   Function
  797. ;      reset
  798. ;   Description
  799. ;      Place the chip (ie, the ethernet card) into a virgin state
  800. ;      No inputs
  801. ;      All registers destroyed
  802. ;
  803. ;***************************************************************************
  804. reset:
  805.  
  806.         DEBUGF  1,"Resetting\n"
  807.  
  808.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
  809.         movzx   eax, al
  810.         invoke  AttachIntHandler, eax, int_handler, ebx
  811.         test    eax, eax
  812.         jnz     @f
  813.         DEBUGF  2,"Could not attach int handler!\n"
  814.         or      eax, -1
  815.         ret
  816.        @@:
  817.  
  818. ; erase previous misconfiguration
  819.  
  820.         mov     edi, [ebx + device.mmio_addr]
  821.         mov     [MulticastAddrA], MCASTADDRA_FORCE
  822.         mov     [MulticastAddrB], 0
  823.         mov     [MulticastMaskA], 0
  824.         mov     [MulticastMaskB], 0
  825.         mov     [PacketFilterFlags], 0
  826.         mov     [TransmitterControl], 0
  827.         mov     [ReceiverControl], 0
  828.         mov     [AdapterControl], 0
  829.  
  830. ; initialize descriptor rings
  831.  
  832.         call    init_ring
  833.  
  834.         mov     [LinkSpeed], 0
  835.         mov     [UnknownTransmitterReg], 0
  836.  
  837.         call    txrx_reset
  838.  
  839.         mov     [UnknownSetupReg6], 0
  840.         mov     [ebx + device.in_shutdown], 0
  841.  
  842. ; give hw rings
  843.  
  844.         lea     eax, [ebx + device.rx_ring]
  845.         invoke  GetPhysAddr
  846.         mov     [RxRingPhysAddr], eax
  847.  
  848.         lea     eax, [ebx + device.tx_ring]
  849.         invoke  GetPhysAddr
  850.         mov     [TxRingPhysAddr], eax
  851.  
  852.         mov     [RingSizes], (((RX_RING - 1) shl RINGSZ_RXSHIFT) + ((TX_RING - 1) shl RINGSZ_TXSHIFT))
  853.  
  854. ;
  855.  
  856.         mov     [ebx + device.linkspeed], (LINKSPEED_FORCE or LINKSPEED_10)
  857.         mov     [ebx + device.duplex], 0
  858.         mov     [LinkSpeed], (LINKSPEED_FORCE or LINKSPEED_10)
  859.         mov     [UnknownSetupReg3], UNKSETUP3_VAL1
  860.  
  861.         mov     eax, [ebx + device.desc_ver]
  862.         mov     [TxRxControl], eax
  863.         call    pci_push
  864.         or      eax, TXRXCTL_BIT1
  865.         mov     [TxRxControl], eax
  866.  
  867.         stdcall reg_delay, UnknownSetupReg5-edi, UNKSETUP5_BIT31, UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, 0
  868.  
  869.         mov     [UnknownSetupReg4], 0
  870.         mov     [MIIStatus], MIISTAT_MASK2
  871.  
  872. ;
  873.        
  874.         mov     [Misc1], (MISC1_FORCE or MISC1_HD)
  875.  
  876.         mov     eax, [TransmitterStatus]
  877.         mov     [TransmitterStatus], eax
  878.  
  879.         mov     [PacketFilterFlags], PFF_ALWAYS
  880.  
  881.         mov     [OffloadConfig], OFFLOAD_NORMAL
  882.  
  883.         mov     eax, [ReceiverStatus]
  884.         mov     [ReceiverStatus], eax
  885.  
  886. ; set random seed
  887.         push    ebx
  888.         invoke  GetTimerTicks   ; bad idea, driver is started at system startup in 90% of cases..
  889.         pop     ebx
  890.  
  891.         mov     edi, [ebx + device.mmio_addr]
  892.  
  893.         and     eax, RNDSEED_MASK
  894.         or      eax, RNDSEED_FORCE
  895.         mov     [RandomSeed], eax
  896.  
  897.         mov     [UnknownSetupReg1], UNKSETUP1_VAL
  898.         mov     [UnknownSetupReg2], UNKSETUP2_VAL
  899.         mov     [PollingInterval], POLL_DEFAULT
  900.         mov     [UnknownSetupReg6], UNKSETUP6_VAL
  901.  
  902.         mov     eax, [ebx + device.phyaddr]
  903.         shl     eax, ADAPTCTL_PHYSHIFT
  904.         or      eax, (ADAPTCTL_PHYVALID or ADAPTCTL_RUNNING)
  905.         mov     [AdapterControl], eax
  906.  
  907.         mov     [MIISpeed], (MIISPEED_BIT8 or MIIDELAY)
  908.         mov     [UnknownSetupReg4], UNKSETUP4_VAL
  909.         mov     [WakeUpFlags], WAKEUPFLAGS_VAL
  910.        
  911.         or      [PowerState], POWERSTATE_POWEREDUP
  912.         call    pci_push
  913.  
  914.         mov     esi, 10
  915.         invoke  Sleep
  916.  
  917.         or      [PowerState], POWERSTATE_VALID
  918.         mov     [IrqMask], 0
  919.  
  920. ;;;     ; ??? Mask RX interrupts
  921.         mov      [IrqMask], IRQ_RX_ALL + IRQ_TX_ALL
  922. ;;;     ; ??? Mask TX interrupts
  923. ;;;     mov      [IrqMask], IRQ_TX_ALL
  924. ;;;     ; ??? Mask OTHER interrupts
  925. ;;;     mov      [IrqMask], IRQ_OTHER_ALL
  926.         call    pci_push
  927.  
  928.         mov     [MIIStatus], MIISTAT_MASK2
  929.         mov     [IrqStatus], IRQSTAT_MASK
  930.         call    pci_push
  931.  
  932.         mov     [MulticastAddrA], MCASTADDRA_FORCE
  933.         mov     [MulticastAddrB], 0
  934.         mov     [MulticastMaskA], 0
  935.         mov     [MulticastMaskB], 0
  936.  
  937.         mov     [PacketFilterFlags], (PFF_ALWAYS or PFF_MYADDR)
  938.  
  939.         call    set_multicast
  940.        
  941.         ; One manual link speed update: Interrupts are enabled, future link
  942.         ; speed changes cause interrupts and are handled by nv_link_irq().
  943.  
  944.         mov     eax, [MIIStatus]
  945.         mov     [MIIStatus], MIISTAT_MASK
  946.         DEBUGF  1,"startup: got 0x%x\n", eax
  947.  
  948.         call    update_linkspeed
  949.  
  950.         mov     [TransmitterControl], XMITCTL_START       ; start TX
  951.         call    pci_push
  952.  
  953.         mov     [ebx + device.nocable], 0
  954.         test    eax, eax
  955.         jnz     .return
  956.         DEBUGF  1,"no link during initialization.\n"
  957.         mov     [ebx + device.nocable], 1
  958.  
  959.   .return:
  960.         xor     eax, eax        ; Indicate that we have successfully reset the card
  961.         mov     [ebx + device.mtu], 1514 ;;; FIXME
  962.         ret
  963.  
  964.  
  965. fail:
  966.         or      eax, -1
  967.         ret
  968.  
  969. ;--------------------------------------------------------
  970. ;
  971. ; MII_RW
  972. ;
  973. ; read/write a register on the PHY.
  974. ; Caller must guarantee serialization
  975. ; Input:  EAX - miireg, EDX - phy addr, ECX - value to write (or -1 to read)
  976. ; Output: EAX - retval (lower 16 bits)
  977. ;
  978. ;--------------------------------------------------------
  979.  
  980. mii_rw:
  981.  
  982.         DEBUGF  1,"mii_rw: 0x%x to reg %d at PHY %d\n", ecx, eax, edx
  983.  
  984.         push    edx
  985.  
  986.         mov     edi, [ebx + device.mmio_addr]
  987.  
  988. ; Check if MII interface is busy
  989.         mov     [MIIStatus], MIISTAT_MASK
  990.        @@:
  991.         test    [MIIControl], MIICTL_INUSE
  992.         jz      @f
  993.         mov     [MIIControl], MIICTL_INUSE
  994.  
  995.         DEBUGF  1,"mii_rw: in use!\n"
  996.         pusha
  997.         mov     esi, NV_MIIBUSY_DELAY
  998.         invoke  Sleep
  999.         popa
  1000.         jmp     @r
  1001.        @@:
  1002.  
  1003. ; Set the address we want to access
  1004.         shl     edx, MIICTL_ADDRSHIFT
  1005.         or      edx, eax
  1006.  
  1007.         ; When writing, write the data first.
  1008.         cmp     ecx, MII_READ
  1009.         je      @f
  1010.         mov     [MIIData], ecx
  1011.         or      edx, MIICTL_WRITE
  1012.        @@:
  1013.  
  1014.         mov     [MIIControl], edx
  1015.  
  1016. ; Wait for read/write to complete
  1017.         stdcall reg_delay, MIIControl-edi, MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, 0
  1018.  
  1019.         test    eax, eax
  1020.         jz      @f
  1021.         DEBUGF  1,"mii_rw timed out.\n"
  1022.         or      eax, -1
  1023.         jmp     .return
  1024.  
  1025.        @@:
  1026.         cmp     ecx, MII_READ
  1027.         je      .read
  1028. ; it was a write operation - fewer failures are detectable
  1029.         DEBUGF  1,"mii_rw write: ok\n"
  1030.         xor     eax, eax
  1031.         jmp     .return
  1032.  
  1033.   .read:
  1034.         mov     eax, [MIIStatus]
  1035.         test    eax, MIISTAT_ERROR
  1036.         jz      @f
  1037.         DEBUGF  1,"mii read: failed.\n"
  1038.         or      eax, -1
  1039.         jmp     .return
  1040.  
  1041.        @@:
  1042.         mov     eax, [MIIData]
  1043.         DEBUGF  1,"mii read: 0x%x.\n", eax
  1044.  
  1045.   .return:
  1046.         pop     edx
  1047.         ret
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053. ; Input:  offset:word, mask:dword, target:dword, delay:word, delaymax:word, msg:dword
  1054. ; Output: EAX - 0|1
  1055.  
  1056. proc    reg_delay, offset:dword, mask:dword, target:dword, delay:dword, delaymax:dword, msg:dword
  1057.  
  1058. ;        DEBUGF  1,"reg_delay\n"
  1059.  
  1060.         push    esi
  1061.         call    pci_push
  1062.  
  1063.   .loop:
  1064.         mov     esi, [delay]
  1065.         invoke  Sleep
  1066.         mov     eax, [delaymax]
  1067.         sub     eax, [delay]
  1068.         mov     [delaymax], eax
  1069.  
  1070.         cmp     eax, 0
  1071.         jl      .fail
  1072.  
  1073.         mov     eax, [offset]
  1074.         mov     eax, [edi + eax]
  1075.         and     eax, [mask]
  1076.         cmp     eax, [target]
  1077.         jne     .loop
  1078.  
  1079.         pop     esi
  1080.         xor     eax, eax
  1081.         ret
  1082.  
  1083.   .fail:
  1084.         pop     esi
  1085.         xor     eax, eax
  1086.         inc     eax
  1087.         ret
  1088.  
  1089. endp
  1090.  
  1091.  
  1092.  
  1093.  
  1094.  
  1095. ; Input:  none
  1096. ; Output: EAX - result (0 = OK, other = error)
  1097. phy_init:
  1098.  
  1099.         push    ebx ecx
  1100.        
  1101.         ; set advertise register
  1102.         mov     edx, [ebx + device.phyaddr]
  1103.         mov     eax, MII_ADVERTISE
  1104.         mov     ecx, MII_READ
  1105.         call    mii_rw
  1106.  
  1107.         or      eax, (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or 0x800 or 0x400)
  1108.  
  1109.         mov     ecx, eax
  1110.         mov     eax, MII_ADVERTISE
  1111.         call    mii_rw
  1112.  
  1113.         test    eax, eax
  1114.         jz      @f
  1115.  
  1116.         DEBUGF  2,"phy write to advertise failed.\n"
  1117.  
  1118.         mov     eax, PHY_ERROR
  1119.         jmp     .return
  1120.        @@:
  1121.  
  1122.         ; get phy interface type
  1123.         mov     edi, [ebx + device.mmio_addr]
  1124.         mov     eax, [PhyInterface]
  1125.         DEBUGF  1,"phy interface type = 0x%x\n", eax:8
  1126.  
  1127.         ; see if gigabit phy
  1128.         mov     eax, MII_BMSR
  1129.         mov     ecx, MII_READ
  1130.         call    mii_rw
  1131.        
  1132.         test    eax, PHY_GIGABIT
  1133.         jnz     .gigabit
  1134.         mov     [ebx + device.gigabit], 0
  1135.         jmp     .next_if
  1136.  
  1137.   .gigabit:
  1138.         mov     [ebx + device.gigabit], PHY_GIGABIT
  1139.  
  1140.         mov     eax, MII_CTRL1000
  1141.         mov     ecx, MII_READ
  1142.         call    mii_rw
  1143.        
  1144.         and     eax, (not ADVERTISE_1000HALF)
  1145.  
  1146.         test    [PhyInterface], PHY_RGMII
  1147.         jz      @f
  1148.         or      eax, ADVERTISE_1000FULL
  1149.         jmp     .next
  1150.        @@:
  1151.  
  1152.         and     eax, (not ADVERTISE_1000FULL)
  1153.  
  1154.   .next:
  1155.         mov     ecx, eax
  1156.         mov     eax, MII_CTRL1000
  1157.         call    mii_rw
  1158.  
  1159.         test    eax, eax
  1160.         jz      .next_if
  1161.  
  1162.         DEBUGF  2,"phy init failed.\n"
  1163.  
  1164.         mov     eax, PHY_ERROR
  1165.         jmp     .return
  1166.  
  1167.   .next_if:
  1168.  
  1169.         call    phy_reset
  1170.         test    eax, eax
  1171.         jz      @f
  1172.  
  1173.         DEBUGF  2,"phy reset failed.\n"
  1174.  
  1175.         mov     eax, PHY_ERROR
  1176.         jmp     .return
  1177.        @@:
  1178.  
  1179.         ; phy vendor specific configuration
  1180.         cmp     [ebx + device.phy_oui], PHY_OUI_CICADA
  1181.         jne     .next_if2
  1182.         test    [PhyInterface], PHY_RGMII
  1183.         jz      .next_if2
  1184.  
  1185.         mov     eax, MII_RESV1
  1186.         mov     ecx, MII_READ
  1187.         call    mii_rw
  1188.  
  1189.         and     eax, (not (PHY_INIT1 or PHY_INIT2))
  1190.         or      eax, (PHY_INIT3 or PHY_INIT4)
  1191.         mov     ecx, eax
  1192.         mov     eax, MII_RESV1
  1193.         call    mii_rw
  1194.  
  1195.         test    eax, eax
  1196.         jz      @f
  1197.  
  1198.         DEBUGF  2,"phy init failed.\n"
  1199.  
  1200.         mov     eax, PHY_ERROR
  1201.         jmp     .return
  1202.        @@:
  1203.  
  1204.         mov     eax, MII_NCONFIG
  1205.         mov     ecx, MII_READ
  1206.         call    mii_rw
  1207.  
  1208.         or      eax, PHY_INIT5
  1209.         mov     ecx, eax
  1210.         mov     eax, MII_NCONFIG
  1211.         call    mii_rw
  1212.         test    eax, eax
  1213.         jz      .next_if2
  1214.  
  1215.         DEBUGF  2,"phy init failed.\n"
  1216.  
  1217.         mov     eax, PHY_ERROR
  1218.         jmp     .return
  1219.  
  1220.  
  1221.  
  1222.   .next_if2:
  1223.  
  1224.         cmp     [ebx + device.phy_oui], PHY_OUI_CICADA
  1225.         jne     .restart
  1226.        
  1227.         mov     eax, MII_SREVISION
  1228.         mov     ecx, MII_READ
  1229.         call    mii_rw
  1230.        
  1231.         or      eax, PHY_INIT6
  1232.         mov     ecx, eax
  1233.         mov     eax, MII_SREVISION
  1234.         call    mii_rw
  1235.         test    eax, eax
  1236.         jz      .restart
  1237.  
  1238.         DEBUGF  2,"phy init failed.\n"
  1239.  
  1240.         jmp     .return
  1241.  
  1242.   .restart:
  1243.         ; restart auto negotiation
  1244.  
  1245.         mov     eax, MII_BMCR
  1246.         mov     ecx, MII_READ
  1247.         call    mii_rw
  1248.  
  1249.         or      eax, (BMCR_ANRESTART or BMCR_ANENABLE)
  1250.         mov     ecx, eax
  1251.         mov     eax, MII_BMCR
  1252.         call    mii_rw
  1253.         test    eax, eax
  1254.         jz      .ok
  1255.  
  1256.         mov     eax, PHY_ERROR
  1257.         jmp     .return
  1258.  
  1259.   .ok:
  1260.         xor     eax, eax
  1261.   .return:
  1262.         pop     ecx ebx
  1263.  
  1264.         ret
  1265.  
  1266.  
  1267. ; Input:  none
  1268. ; Output: EAX - result (0 = OK, other = error)
  1269. phy_reset:
  1270.  
  1271.         DEBUGF  1,"phy_reset\n"
  1272.  
  1273.         push    ebx ecx edx
  1274.  
  1275.         mov     edx, [ebx + device.phyaddr]
  1276.         mov     eax, MII_BMCR
  1277.         mov     ecx, MII_READ
  1278.         call    mii_rw
  1279.  
  1280.         or      eax, BMCR_RESET
  1281.         push    eax
  1282.         mov     ecx, eax
  1283.         mov     eax, MII_BMCR
  1284.         call    mii_rw
  1285.  
  1286.         test    eax, eax
  1287.         jz      @f
  1288.  
  1289.         pop     eax
  1290.         mov     eax, 0xffffffff
  1291.         jmp     .return
  1292.        @@:
  1293.  
  1294.         pop     eax
  1295.  
  1296.         mov     esi, 500
  1297.         invoke  Sleep
  1298.  
  1299.         ; must wait till reset is deasserted
  1300.         mov     esi, 100        ; FIXME: 100 tries seem excessive
  1301.   .while_loop:
  1302.         test    eax, BMCR_RESET
  1303.         jz      .while_loop_exit
  1304.  
  1305.         push    esi
  1306.         mov     esi, 10
  1307.         invoke  Sleep
  1308.         pop     esi
  1309.  
  1310.         mov     eax, MII_BMCR
  1311.         mov     ecx, MII_READ
  1312.         call    mii_rw
  1313.  
  1314.         dec     esi
  1315.         jnz     .while_loop
  1316.  
  1317.         mov     eax, 0xffffffff
  1318.         jmp     .return
  1319.  
  1320.   .while_loop_exit:
  1321.         xor     eax, eax
  1322.   .return:
  1323.         pop     edx ecx ebx
  1324.  
  1325.         ret
  1326.  
  1327.  
  1328. align 4
  1329. pci_push:
  1330.  
  1331.         push    eax
  1332.         mov     eax, [edi]
  1333.         pop     eax
  1334.  
  1335.         ret
  1336.  
  1337.  
  1338.  
  1339.  
  1340. align 4
  1341. mac_reset:
  1342.  
  1343.         push    esi edi
  1344.  
  1345.         DEBUGF  1,"mac_reset.\n"
  1346.  
  1347.         mov     edi, [ebx + device.mmio_addr]
  1348.         mov     eax, [ebx + device.desc_ver]
  1349.         or      eax, (TXRXCTL_BIT2 or TXRXCTL_RESET)
  1350.         mov     [TxRxControl], eax
  1351.         call    pci_push
  1352.  
  1353.         mov     [MacReset], MAC_RESET_ASSERT
  1354.         call    pci_push
  1355.  
  1356.         mov     esi, NV_MAC_RESET_DELAY
  1357.         invoke  Sleep
  1358.  
  1359.         mov     [MacReset], 0
  1360.         call    pci_push
  1361.  
  1362.         mov     esi, NV_MAC_RESET_DELAY
  1363.         invoke  Sleep
  1364.  
  1365.         mov     eax, [ebx + device.desc_ver]
  1366.         or      eax, TXRXCTL_BIT2
  1367.         mov     [TxRxControl], eax
  1368.         call    pci_push
  1369.  
  1370.         pop     edi esi
  1371.  
  1372.         ret
  1373.  
  1374.  
  1375.  
  1376. align 4
  1377. init_ring:
  1378.  
  1379.         DEBUGF  1,"init rings\n"
  1380.         push    esi ecx
  1381.  
  1382.         mov     [ebx + device.cur_tx], 0
  1383.         mov     [ebx + device.last_tx], 0
  1384.  
  1385.         mov     ecx, TX_RING
  1386.         lea     esi, [ebx + device.tx_ring]
  1387.   .tx_loop:
  1388.         mov     [esi + TxDesc.FlagLen], 0
  1389.         mov     [esi + TxDesc.PacketBuffer], 0
  1390.         add     esi, sizeof.TxDesc
  1391.         dec     ecx
  1392.         jnz     .tx_loop
  1393.  
  1394.  
  1395.         mov     [ebx + device.cur_rx], 0
  1396.  
  1397.         mov     ecx, RX_RING
  1398.         lea     esi, [ebx + device.rx_ring]
  1399.   .rx_loop:
  1400.         push    ecx esi
  1401.         invoke  NetAlloc, (4096 shl RBLEN) + NET_BUFF.data             ; push/pop esi not needed, but just in case...
  1402.         pop     esi
  1403.         test    eax, eax
  1404.         jz      .out_of_mem
  1405.         mov     [esi + RX_RING*sizeof.RxDesc], eax
  1406.         invoke  GetPhysAddr
  1407.         add     eax, NET_BUFF.data
  1408.         mov     [esi + RxDesc.PacketBuffer], eax
  1409.         mov     [esi + RxDesc.FlagLen], (4096 shl RBLEN or NV_RX_AVAIL)
  1410.         add     esi, sizeof.RxDesc
  1411.         pop     ecx
  1412.         dec     ecx
  1413.         jnz     .rx_loop
  1414.        
  1415.         pop     ecx esi
  1416.  
  1417.         xor     eax, eax
  1418.         ret
  1419.  
  1420.   .out_of_mem:
  1421.         add     esp, 12
  1422.         or      eax, -1
  1423.         ret
  1424.  
  1425.  
  1426.  
  1427.  
  1428.  
  1429. ; Input:  none
  1430. ; Output: none
  1431. align 4
  1432. txrx_reset:
  1433.  
  1434.         push    eax esi
  1435.  
  1436.         DEBUGF  1,"txrx_reset\n"
  1437.  
  1438.         mov     edi, [ebx + device.mmio_addr]
  1439.         mov     eax, [ebx + device.desc_ver]
  1440.         or      eax, (TXRXCTL_BIT2 or TXRXCTL_RESET)
  1441.         mov     [TxRxControl], eax
  1442.         call    pci_push
  1443.  
  1444.         mov     esi, NV_TXRX_RESET_DELAY
  1445.         invoke  Sleep
  1446.  
  1447.         mov     eax, [ebx + device.desc_ver]
  1448.         or      eax, TXRXCTL_BIT2
  1449.         mov     [TxRxControl], eax
  1450.         call    pci_push
  1451.  
  1452.         pop     esi eax
  1453.  
  1454.         ret
  1455.  
  1456.  
  1457.  
  1458.  
  1459.  
  1460. ; Input:  none
  1461. ; Output: none
  1462. set_multicast:
  1463.  
  1464.         ; u32 addr[2];
  1465.         ; u32 mask[2];
  1466.         ; u32 pff;
  1467.         ; u32 alwaysOff[2];
  1468.         ; u32 alwaysOn[2];
  1469.         ;
  1470.         ; memset(addr, 0, sizeof(addr));
  1471.         ; memset(mask, 0, sizeof(mask));
  1472.         ;
  1473.         ; pff = PFF_MYADDR;
  1474.         ;
  1475.         ; alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0;
  1476.         ;
  1477.         ; addr[0] = alwaysOn[0];
  1478.         ; addr[1] = alwaysOn[1];
  1479.         ; mask[0] = alwaysOn[0] | alwaysOff[0];
  1480.         ; mask[1] = alwaysOn[1] | alwaysOff[1];
  1481.         ;
  1482.         ; addr[0] |= MCASTADDRA_FORCE;
  1483.         ; pff |= PFF_ALWAYS;
  1484.  
  1485.         call    stop_rx
  1486.  
  1487.         mov     edi, [ebx + device.mmio_addr]
  1488.         mov     [MulticastAddrA], MCASTADDRA_FORCE
  1489.  
  1490.         mov     [MulticastAddrB], 0
  1491.         mov     [MulticastMaskA], 0
  1492.         mov     [MulticastMaskB], 0
  1493.         mov     [PacketFilterFlags], (PFF_MYADDR or PFF_ALWAYS)
  1494.  
  1495.         call    start_rx
  1496.  
  1497.         ret
  1498.  
  1499.  
  1500.  
  1501.  
  1502.  
  1503. ; Input:  none
  1504. ; Output: none
  1505. start_rx:
  1506.  
  1507.         push    edi
  1508.  
  1509.         DEBUGF  1,"start_rx\n"
  1510.  
  1511.         ; Already running? Stop it.
  1512.         mov     edi, [ebx + device.mmio_addr]
  1513.         mov     eax, [ReceiverControl]
  1514.         test    eax, RCVCTL_START
  1515.         jz      @f
  1516.         mov     [ReceiverControl], 0
  1517.         call    pci_push
  1518.        @@:
  1519.  
  1520.         mov     eax, [ebx + device.linkspeed]
  1521.         mov     [LinkSpeed], eax
  1522.         call    pci_push
  1523.  
  1524.         mov     [ReceiverControl], RCVCTL_START
  1525.         call    pci_push
  1526.  
  1527.         pop     edi
  1528.  
  1529.         ret
  1530.  
  1531.  
  1532.  
  1533.  
  1534. ; Input:  none
  1535. ; Output: none
  1536. stop_rx:
  1537.  
  1538.         push    esi edi
  1539.  
  1540.         DEBUGF  1,"stop_rx.\n"
  1541.  
  1542.         mov     edi, [ebx + device.mmio_addr]
  1543.         mov     [ReceiverControl], 0
  1544.  
  1545.         push    ebx edx edi
  1546.         stdcall reg_delay, ReceiverStatus-edi, RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, 0
  1547.         pop     edi edx ebx
  1548.  
  1549.         mov     esi, NV_RXSTOP_DELAY2
  1550.         invoke  Sleep
  1551.  
  1552.         mov     [LinkSpeed], 0
  1553.  
  1554.         pop     edi esi
  1555.  
  1556.         ret
  1557.  
  1558.  
  1559.  
  1560.  
  1561. ; Input:  none
  1562. ; Output: EAX
  1563. update_linkspeed:
  1564.  
  1565.         DEBUGF  1,"update linkspeed\n"
  1566.  
  1567. ; BMSR_LSTATUS is latched, read it twice: we want the current value.
  1568.        
  1569.         mov     edx, [ebx + device.phyaddr]
  1570.         mov     eax, MII_BMSR
  1571.         mov     ecx, MII_READ
  1572.         call    mii_rw
  1573.  
  1574.         mov     eax, MII_BMSR
  1575.         mov     ecx, MII_READ
  1576.         call    mii_rw
  1577.        
  1578.         test    ax, BMSR_LSTATUS               ; Link up?
  1579.         jz      .no_link
  1580.  
  1581.         DEBUGF  1,"link is up\n"
  1582.  
  1583.         test    ax, BMSR_ANEGCOMPLETE          ; still in autonegotiation?
  1584.         jz      .10mbit_hd
  1585.  
  1586.         DEBUGF  1,"autonegotiation is complete\n"
  1587.  
  1588.         cmp     [ebx + device.gigabit], PHY_GIGABIT
  1589.         jne     .no_gigabit
  1590.  
  1591.         ;mov     edx, [ebx + device.phyaddr]
  1592.         mov     eax, MII_CTRL1000
  1593.         mov     ecx, MII_READ
  1594.         call    mii_rw
  1595.         push    eax
  1596.  
  1597.         ;mov     edx, [ebx + device.phyaddr]
  1598.         mov     eax, MII_STAT1000
  1599.         mov     ecx, MII_READ
  1600.         call    mii_rw
  1601.         pop     ecx
  1602.  
  1603.         test    eax, LPA_1000FULL
  1604.         jz      .no_gigabit
  1605.         test    ecx, ADVERTISE_1000FULL
  1606.         jz      .no_gigabit
  1607.  
  1608.         DEBUGF  1,"update_linkspeed: GBit ethernet detected.\n"
  1609.         mov     [ebx + device.state], ETH_LINK_1G
  1610.         mov     ecx, (LINKSPEED_FORCE or LINKSPEED_1000)
  1611.         xor     eax, eax
  1612.         inc     eax
  1613.         jmp     set_speed
  1614.   .no_gigabit:
  1615.  
  1616.         ;mov     edx, [ebx + device.phyaddr]
  1617.         mov     eax, MII_ADVERTISE
  1618.         mov     ecx, MII_READ
  1619.         call    mii_rw        ; adv = eax
  1620.         push    eax
  1621.  
  1622.         ;mov     edx, [ebx + device.phyaddr]
  1623.         mov     eax, MII_LPA
  1624.         mov     ecx, MII_READ
  1625.         call    mii_rw        ; lpa = eax
  1626.         pop     ecx
  1627.  
  1628.         DEBUGF  1,"PHY advertises 0x%x, lpa 0x%x\n", cx, ax
  1629.         and     eax, ecx                ; FIXME: handle parallel detection properly, handle gigabit ethernet
  1630.  
  1631.         test    eax, LPA_100FULL
  1632.         jz      @f
  1633.         DEBUGF  1,"update_linkspeed: 100 mbit full duplex\n"
  1634.         mov     [ebx + device.state], ETH_LINK_100M + ETH_LINK_FD
  1635.         mov     ecx, (LINKSPEED_FORCE or LINKSPEED_100)
  1636.         xor     eax, eax
  1637.         inc     eax
  1638.         jmp     set_speed
  1639.        @@:
  1640.  
  1641.         test    eax, LPA_100HALF
  1642.         jz      @f
  1643.         DEBUGF  1,"update_linkspeed: 100 mbit half duplex\n"
  1644.         mov     [ebx + device.state], ETH_LINK_100M
  1645.         mov     ecx, (LINKSPEED_FORCE or LINKSPEED_100)
  1646.         xor     eax, eax
  1647.         jmp     set_speed
  1648.        @@:
  1649.  
  1650.         test    eax, LPA_10FULL
  1651.         jz      @f
  1652.         DEBUGF  1,"update_linkspeed: 10 mbit full duplex\n"
  1653.         mov     [ebx + device.state], ETH_LINK_10M + ETH_LINK_FD
  1654.         mov     ecx, (LINKSPEED_FORCE or LINKSPEED_10)
  1655.         xor     eax, eax
  1656.         inc     eax
  1657.         jmp     set_speed
  1658.        @@:
  1659.  
  1660.   .10mbit_hd:
  1661.         DEBUGF  1,"update_linkspeed: 10 mbit half duplex\n"
  1662.         mov     [ebx + device.state], ETH_LINK_10M
  1663.         mov     ecx, (LINKSPEED_FORCE or LINKSPEED_10)
  1664.         xor     eax, eax
  1665.         jmp     set_speed
  1666.  
  1667.   .no_link:
  1668.         DEBUGF  1,"update_linkspeed: link is down\n"
  1669.         mov     [ebx + device.state], ETH_LINK_DOWN
  1670.         mov     ecx, (LINKSPEED_FORCE or LINKSPEED_10)
  1671.         xor     eax, eax
  1672.         jmp     set_speed
  1673.  
  1674.  
  1675. align 4
  1676. set_speed:
  1677.  
  1678.         cmp     eax, [ebx + device.duplex]
  1679.         jne     .update
  1680.         cmp     ecx, [ebx + device.linkspeed]
  1681.         jne     .update
  1682.  
  1683.         ret
  1684.  
  1685.   .update:
  1686.         DEBUGF  1,"update_linkspeed: changing link to 0x%x/XD.\n", ecx
  1687.        
  1688.         mov     [ebx + device.duplex], eax
  1689.         mov     [ebx + device.linkspeed], ecx
  1690.        
  1691.         cmp     [ebx + device.gigabit], PHY_GIGABIT
  1692.         jne     .no_gigabit
  1693.  
  1694.         mov     edi, [ebx + device.mmio_addr]
  1695.         mov     eax, [RandomSeed]
  1696.  
  1697.         and     eax, not (0x3FF00)
  1698.         mov     ecx, eax                ; phyreg = ecx
  1699.  
  1700.         mov     eax, [ebx + device.linkspeed]
  1701.         and     eax, 0xFFF
  1702.         cmp     eax, LINKSPEED_10
  1703.         jne     @f
  1704.         or      ecx, RNDSEED_FORCE3
  1705.         jmp     .end_if4
  1706.        @@:
  1707.  
  1708.         cmp     eax, LINKSPEED_100
  1709.         jne     @f
  1710.         or      ecx, RNDSEED_FORCE2
  1711.         jmp     .end_if4
  1712.        @@:
  1713.  
  1714.         cmp     eax, LINKSPEED_1000
  1715.         jne     .end_if4
  1716.         or      ecx, RNDSEED_FORCE
  1717.   .end_if4:
  1718.         mov     [RandomSeed], ecx
  1719.   .no_gigabit:
  1720.  
  1721.         mov     ecx, [PhyInterface]
  1722.         and     ecx, not (PHY_HALF or PHY_100 or PHY_1000)
  1723.  
  1724.         cmp     [ebx + device.duplex], 0
  1725.         jne     @f
  1726.         or      ecx, PHY_HALF
  1727.        @@:
  1728.  
  1729.         mov     eax, [ebx + device.linkspeed]
  1730.         and     eax, 0xFFF
  1731.         cmp     eax, LINKSPEED_100
  1732.         jne     @f
  1733.         or      ecx, PHY_100
  1734.         jmp     .end_if5
  1735.        @@:
  1736.  
  1737.         cmp     eax, LINKSPEED_1000
  1738.         jne     .end_if5
  1739.         or      ecx, PHY_1000
  1740.  
  1741.   .end_if5:
  1742.         mov     [PhyInterface], ecx
  1743.                
  1744.         cmp     [ebx + device.duplex], 0
  1745.         je      @f
  1746.         xor     ecx, ecx
  1747.         jmp     .next
  1748.        @@:
  1749.  
  1750.         mov     ecx, MISC1_HD
  1751.   .next:
  1752.         or      ecx, MISC1_FORCE
  1753.         mov     [Misc1], ecx
  1754.  
  1755.         call    pci_push
  1756.  
  1757.         mov     eax, [ebx + device.linkspeed]
  1758.         mov     [LinkSpeed], eax
  1759.  
  1760.         call    pci_push
  1761.  
  1762.         ret
  1763.  
  1764.  
  1765.  
  1766.  
  1767.  
  1768.  
  1769. align 4
  1770. read_mac:
  1771.  
  1772.         mov     edi, [ebx + device.mmio_addr]
  1773.         mov     eax, [MacAddrA]
  1774.         mov     ecx, [MacAddrB]
  1775.  
  1776.         mov     dword [ebx + device.mac], eax
  1777.         mov     word [ebx + device.mac + 4], cx
  1778.  
  1779.         cmp     [ebx + device.device_id], 0x03E5
  1780.         jae     @f
  1781.         bswap   eax
  1782.         xchg    cl, ch
  1783.         mov     dword [ebx + device.mac + 2], eax
  1784.         mov     word [ebx + device.mac], cx
  1785.        @@:
  1786.  
  1787.         DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n", \
  1788.         [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,[ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
  1789.  
  1790.         ret
  1791.  
  1792.  
  1793.  
  1794. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1795. ;;                                         ;;
  1796. ;; Transmit                                ;;
  1797. ;;                                         ;;
  1798. ;; In: buffer pointer in [esp+4]           ;;
  1799. ;;     pointer to device structure in ebx  ;;
  1800. ;;                                         ;;
  1801. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1802.  
  1803. proc transmit stdcall bufferptr
  1804.  
  1805.         pushf
  1806.         cli
  1807.  
  1808.         mov     esi, [bufferptr]
  1809.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
  1810.         lea     eax, [esi + NET_BUFF.data]
  1811.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  1812.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  1813.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  1814.         [eax+13]:2,[eax+12]:2
  1815.  
  1816.         cmp     [esi + NET_BUFF.length], 1514
  1817.         ja      .fail
  1818.         cmp     [esi + NET_BUFF.length], 60
  1819.         jb      .fail
  1820.  
  1821. ; get the descriptor address
  1822.         mov     eax, [ebx + device.cur_tx]
  1823.         shl     eax, 3                                  ; TX descriptor is 8 bytes.
  1824.         lea     edi, [ebx + device.tx_ring + eax]
  1825.  
  1826.         mov     eax, [bufferptr]
  1827.         mov     [edi + TX_RING*sizeof.TxDesc], eax
  1828.         add     eax, [eax + NET_BUFF.offset]
  1829.         invoke  GetPhysAddr                             ; Does not change esi/ebx :)
  1830.         mov     [edi + TxDesc.PacketBuffer], eax
  1831.  
  1832.         mov     ecx, [esi + NET_BUFF.length]
  1833.         or      ecx, [ebx + device.txflags]
  1834.         mov     [edi + TxDesc.FlagLen], ecx
  1835.  
  1836.         mov     edi, [ebx + device.mmio_addr]
  1837.         mov     eax, [ebx + device.desc_ver]
  1838.         or      eax, TXRXCTL_KICK
  1839.         mov     [TxRxControl], eax
  1840.  
  1841.         call    pci_push
  1842.  
  1843.         inc     [ebx + device.cur_tx]
  1844.         and     [ebx + device.cur_tx], (TX_RING-1)
  1845.  
  1846. ; Update stats
  1847.         inc     [ebx + device.packets_tx]
  1848.         add     dword[ebx + device.bytes_tx], ecx
  1849.         adc     dword[ebx + device.bytes_tx + 4], 0
  1850.  
  1851.         popf
  1852.         xor     eax, eax
  1853.         ret
  1854.  
  1855.   .fail:
  1856.         DEBUGF  2,"Send failed\n"
  1857.         invoke  NetFree, [bufferptr]
  1858.         popf
  1859.         or      eax, -1
  1860.         ret
  1861.  
  1862. endp
  1863.  
  1864.  
  1865.  
  1866.  
  1867.  
  1868.  
  1869. ; Interrupt handler
  1870. align 4
  1871. int_handler:
  1872.  
  1873.         push    ebx esi edi
  1874.  
  1875.         DEBUGF  1,"INT\n"
  1876.  
  1877. ;-------------------------------------------
  1878. ; Find pointer of device wich made IRQ occur
  1879.  
  1880.         mov     esi, device_list
  1881.         mov     ecx, [devices]
  1882.         test    ecx, ecx
  1883.         jz      .fail
  1884.   .nextdevice:
  1885.         mov     ebx, dword [esi]
  1886.         add     esi, 4
  1887.  
  1888.         mov     edi, [ebx + device.mmio_addr]
  1889.         mov     eax, [IrqStatus]
  1890.         test    eax, eax
  1891.         jnz     .got_it
  1892.         dec     ecx
  1893.         jnz     .nextdevice
  1894.   .nothing:
  1895.         pop     edi esi ebx
  1896.         xor     eax, eax
  1897.  
  1898.         ret
  1899.  
  1900.   .got_it:
  1901.         mov     [IrqStatus], eax
  1902.         DEBUGF  1,"IrqStatus = %x\n", eax
  1903.  
  1904.         test    eax, IRQ_RX ;+ IRQ_TIMER ;;;;
  1905.         jz      .no_rx
  1906.  
  1907.         push    ebx
  1908.   .more_rx:
  1909.         pop     ebx
  1910.         mov     eax, [ebx + device.cur_rx]
  1911.         mov     cx, sizeof.RxDesc
  1912.         mul     cx
  1913.         lea     esi, [ebx + device.rx_ring + eax]
  1914.         mov     ecx, [esi + RxDesc.FlagLen]
  1915.  
  1916.         test    ecx, NV_RX_AVAIL        ; still owned by hardware
  1917.         jnz     .no_rx
  1918.  
  1919.         cmp     [ebx + device.desc_ver], DESC_VER_1
  1920.         jne     @f
  1921.         test    ecx, NV_RX_DESCRIPTORVALID
  1922.         jz      .no_rx
  1923.         jmp     .next
  1924.   @@:
  1925.         test    ecx, NV_RX2_DESCRIPTORVALID
  1926.         jz      .no_rx
  1927.  
  1928.   .next:
  1929.         cmp     dword[ebx + device.desc_ver], DESC_VER_1
  1930.         jne     @f
  1931.         and     ecx, LEN_MASK_V1
  1932.         jmp     .next2
  1933.    @@:
  1934.         and     ecx, LEN_MASK_V2
  1935.  
  1936.   .next2:
  1937.         DEBUGF  1,"Received %u bytes\n", ecx
  1938.  
  1939.         ; Update stats
  1940.         add     dword[ebx + device.bytes_rx], ecx
  1941.         adc     dword[ebx + device.bytes_rx + 4], 0
  1942.         inc     dword[ebx + device.packets_rx]
  1943.  
  1944.         ; Prepare to give packet to kernel
  1945.         push    ebx
  1946.         push    .more_rx
  1947.  
  1948.         mov     eax, [esi + RX_RING*sizeof.RxDesc]
  1949.         push    eax
  1950.         mov     [eax + NET_BUFF.device], ebx
  1951.         mov     [eax + NET_BUFF.length], ecx
  1952.         mov     [eax + NET_BUFF.offset], NET_BUFF.data
  1953.         DEBUGF  1,"packet ptr=0x%x\n", [esi + RX_RING*sizeof.RxDesc]
  1954.  
  1955.         ; Allocate new buffer for this descriptor
  1956.         invoke  NetAlloc, (4096 shl RBLEN) + NET_BUFF.data
  1957.         mov     [esi + RX_RING*sizeof.RxDesc], eax
  1958.         invoke  GetPhysAddr
  1959.         add     eax, NET_BUFF.data
  1960.         mov     [esi + RxDesc.PacketBuffer], eax
  1961.         mov     [esi + RxDesc.FlagLen], (4096 shl RBLEN or NV_RX_AVAIL)
  1962.  
  1963.         ; update current RX descriptor
  1964.         inc     [ebx + device.cur_rx]
  1965.         and     [ebx + device.cur_rx], (RX_RING-1)
  1966.  
  1967.         jmp     [EthInput]
  1968.  
  1969.   .no_rx:
  1970.         test    eax, IRQ_RX_ERROR
  1971.         jz      .no_rx_err
  1972.  
  1973.         push    eax
  1974.         DEBUGF  2,"RX error!\n"
  1975.  
  1976.         mov     eax, [ebx + device.cur_rx]
  1977.         mov     cx, sizeof.RxDesc
  1978.         mul     cx
  1979.         lea     esi, [ebx + device.rx_ring + eax]
  1980.         mov     eax, [esi + RxDesc.FlagLen]
  1981.  
  1982.         DEBUGF  1,"Flaglen=%x\n", eax
  1983.  
  1984.         ; TODO: allocate new buff ?
  1985.         pop     eax
  1986.  
  1987.   .no_rx_err:
  1988.         test    eax, IRQ_TX_ERROR
  1989.         jz      .no_tx_err
  1990.  
  1991.         DEBUGF  2,"TX error!\n"
  1992.         ; TODO
  1993.  
  1994.   .no_tx_err:
  1995.         test    eax, IRQ_LINK
  1996.         jz      .no_link
  1997.  
  1998.         push    eax
  1999.         call    update_linkspeed
  2000.         pop     eax
  2001.  
  2002.   .no_link:
  2003.         test    eax, IRQ_TX_OK
  2004.         jz      .no_tx
  2005.  
  2006.         DEBUGF  1, "TX completed\n"
  2007.       .loop_tx:
  2008.         mov     esi, [ebx + device.last_tx]
  2009.         shl     esi, 3                                  ; TX descriptor is 8 bytes.
  2010.         lea     esi, [ebx + device.tx_ring + esi]
  2011.  
  2012.         DEBUGF  1,"Flaglen = 0x%x\n", [esi + TxDesc.FlagLen]
  2013.         test    [esi + TxDesc.FlagLen], NV_TX_VALID
  2014.         jnz     .no_tx
  2015.         cmp     dword[esi + TX_RING*sizeof.TxDesc], 0
  2016.         je      .no_tx
  2017.  
  2018.         DEBUGF  1,"Freeing buffer 0x%x\n", [esi + TX_RING*sizeof.TxDesc]:8
  2019.         push    dword[esi + TX_RING*sizeof.TxDesc]
  2020.         mov     dword[esi + TX_RING*sizeof.TxDesc], 0
  2021.         invoke  NetFree
  2022.  
  2023.         inc     [ebx + device.last_tx]
  2024.         and     [ebx + device.last_tx], TX_RING - 1
  2025.  
  2026.         jmp     .loop_tx
  2027.  
  2028.   .no_tx:
  2029.   .fail:
  2030.         pop     edi esi ebx
  2031.         xor     eax, eax
  2032.         inc     eax
  2033.  
  2034.         ret
  2035.  
  2036.  
  2037. ; End of code
  2038.  
  2039. data fixups
  2040. end data
  2041.  
  2042. include '../peimport.inc'
  2043.  
  2044. my_service      db 'FORCEDETH',0                ; max 16 chars include zero
  2045.  
  2046. include_debug_strings
  2047.  
  2048. align 4
  2049. devices         dd 0
  2050. device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
  2051.  
  2052.