Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2008. 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. ;;  Version 0.1  24 June 2008 - 23 Sep 2008                        ;;
  11. ;;                                                                 ;;
  12. ;;  Driver for chips of NVIDIA nForce2                             ;;
  13. ;;  References:                                                    ;;
  14. ;;    forcedeth.c - linux driver (etherboot project)               ;;
  15. ;;    ethernet driver template by Mike Hibbett                     ;;
  16. ;;                                                                 ;;
  17. ;;  The copyright statement is                                     ;;
  18. ;;                                                                 ;;
  19. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  20. ;;             Version 2, June 1991                                ;;
  21. ;;                                                                 ;;
  22. ;;  Copyright 2008 shurf,                                          ;;
  23. ;;   cit.utc@gmail.com                                             ;;
  24. ;;                                                                 ;;
  25. ;;  See file COPYING for details                                   ;;
  26. ;;                                                                 ;;
  27. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  28.  
  29. $Revision: 2288 $
  30.  
  31. ;********************************************************************
  32. ;   Interface
  33. ;      forcedeth_reset
  34. ;      forcedeth_probe
  35. ;      forcedeth_poll
  36. ;      forcedeth_transmit
  37. ;      forcedeth_cable
  38. ;
  39. ;********************************************************************
  40.  
  41. ;**************************************************************************
  42. ; forcedeth Register Definitions
  43. ;**************************************************************************
  44.  
  45. PCI_REG_COMMAND                 equ     0x04    ; command register
  46.  
  47. PCI_COMMAND_IO                  equ     0x01    ; Enable response in I/O space
  48. PCI_COMMAND_MASTER              equ     0x04    ; Enable bus mastering
  49. PCI_LATENCY_TIMER               equ     0x0d    ; 8 bits
  50.  
  51. PCI_VENDOR_ID                   equ     0x00    ; 16 bit
  52. PCI_REVISION_ID                 equ     0x08    ; 8 bits
  53.  
  54. PCI_BASE_ADDRESS_0              equ     0x10    ; 32 bits
  55. PCI_BASE_ADDRESS_1              equ     0x14    ; 32 bits
  56. PCI_BASE_ADDRESS_2              equ     0x18    ; 32 bits
  57. PCI_BASE_ADDRESS_3              equ     0x1c    ; 32 bits
  58. PCI_BASE_ADDRESS_4              equ     0x20    ; 32 bits
  59. PCI_BASE_ADDRESS_5              equ     0x24    ; 32 bits
  60.  
  61. PCI_BASE_ADDRESS_SPACE_IO       equ     0x01
  62. PCI_BASE_ADDRESS_IO_MASK        equ     (not 0x03)
  63. PCI_BASE_ADDRESS_MEM_MASK       equ     (not 0x0f)
  64.  
  65. PCI_BASE_ADDRESS_MEM_TYPE_MASK  equ     0x06
  66. PCI_BASE_ADDRESS_MEM_TYPE_32    equ     0x00    ; 32 bit address
  67. PCI_BASE_ADDRESS_MEM_TYPE_1M    equ     0x02    ; Below 1M [obsolete]
  68. PCI_BASE_ADDRESS_MEM_TYPE_64    equ     0x04    ; 64 bit address
  69.  
  70. ; NIC specific static variables go here
  71. PCI_DEVICE_ID_NVIDIA_NVENET_1   equ     0x01c3
  72. PCI_DEVICE_ID_NVIDIA_NVENET_2   equ     0x0066
  73. PCI_DEVICE_ID_NVIDIA_NVENET_4   equ     0x0086
  74. PCI_DEVICE_ID_NVIDIA_NVENET_5   equ     0x008c
  75. PCI_DEVICE_ID_NVIDIA_NVENET_3   equ     0x00d6
  76. PCI_DEVICE_ID_NVIDIA_NVENET_7   equ     0x00df
  77. PCI_DEVICE_ID_NVIDIA_NVENET_6   equ     0x00e6
  78. PCI_DEVICE_ID_NVIDIA_NVENET_8   equ     0x0056
  79. PCI_DEVICE_ID_NVIDIA_NVENET_9   equ     0x0057
  80. PCI_DEVICE_ID_NVIDIA_NVENET_10  equ     0x0037
  81. PCI_DEVICE_ID_NVIDIA_NVENET_11  equ     0x0038
  82. PCI_DEVICE_ID_NVIDIA_NVENET_12  equ     0x0268
  83. PCI_DEVICE_ID_NVIDIA_NVENET_13  equ     0x0269
  84. PCI_DEVICE_ID_NVIDIA_NVENET_14  equ     0x0372
  85. PCI_DEVICE_ID_NVIDIA_NVENET_15  equ     0x0373
  86.  
  87. ETH_DATA_LEN                    equ     1500
  88.  
  89. ; rx/tx mac addr + type + vlan + align + slack
  90. RX_NIC_BUFSIZE                  equ     (ETH_DATA_LEN + 64)
  91. ; even more slack
  92. RX_ALLOC_BUFSIZE                equ     (ETH_DATA_LEN + 128)
  93.  
  94. NvRegIrqStatus                  equ     0x00
  95. NvRegIrqMask                    equ     0x04
  96. NvRegUnknownSetupReg6           equ     0x08
  97. NvRegPollingInterval            equ     0x0c
  98. NvRegMacReset                   equ     0x3c
  99. NvRegMisc1                      equ     0x80
  100. NvRegTransmitterControl         equ     0x84
  101. NvRegTransmitterStatus          equ     0x88
  102. NvRegPacketFilterFlags          equ     0x8c
  103. NvRegOffloadConfig              equ     0x90
  104. NvRegReceiverControl            equ     0x94
  105. NvRegReceiverStatus             equ     0x98
  106. NvRegRandomSeed                 equ     0x9c
  107. NvRegUnknownSetupReg1           equ     0xA0
  108. NvRegUnknownSetupReg2           equ     0xA4
  109. NvRegMacAddrA                   equ     0xA8    ; MAC address low
  110. NvRegMacAddrB                   equ     0xAC    ; MAC address high
  111. NvRegMulticastAddrA             equ     0xB0
  112. NvRegMulticastAddrB             equ     0xB4
  113. NvRegMulticastMaskA             equ     0xB8
  114. NvRegMulticastMaskB             equ     0xBC
  115. NvRegPhyInterface               equ     0xC0                
  116. NvRegTxRingPhysAddr             equ     0x100
  117. NvRegRxRingPhysAddr             equ     0x104
  118. NvRegRingSizes                  equ     0x108
  119. NvRegUnknownTransmitterReg      equ     0x10c
  120. NvRegLinkSpeed                  equ     0x110
  121. NvRegUnknownSetupReg5           equ     0x130
  122. NvRegUnknownSetupReg3           equ     0x13c
  123. NvRegTxRxControl                equ     0x144
  124. NvRegMIIStatus                  equ     0x180
  125. NvRegUnknownSetupReg4           equ     0x184
  126. NvRegAdapterControl             equ     0x188
  127. NvRegMIISpeed                   equ     0x18c
  128. NvRegMIIControl                 equ     0x190
  129. NvRegMIIData                    equ     0x194
  130. NvRegWakeUpFlags                equ     0x200
  131. NvRegPowerState                 equ     0x26c
  132. NvRegPowerState2                equ     0x600
  133.  
  134. NVREG_UNKSETUP1_VAL             equ     0x16070f
  135. NVREG_UNKSETUP2_VAL             equ     0x16
  136. NVREG_UNKSETUP3_VAL1            equ     0x200010
  137. NVREG_UNKSETUP4_VAL             equ     8
  138. NVREG_UNKSETUP5_BIT31           equ     (1 shl 31)
  139. NVREG_UNKSETUP6_VAL             equ     3
  140.  
  141. NVREG_TXRXCTL_RXCHECK           equ     0x0400
  142. NVREG_MIISTAT_ERROR             equ     0x0001
  143. NVREG_MIISTAT_MASK              equ     0x000f
  144. NVREG_MIISTAT_MASK2             equ     0x000f
  145. NVREG_MIICTL_INUSE              equ     0x08000
  146. NVREG_MIICTL_WRITE              equ     0x00400
  147. NVREG_MIICTL_ADDRSHIFT          equ     5
  148.  
  149. NVREG_MIISPEED_BIT8             equ     (1 shl 8)
  150. NVREG_MIIDELAY                  equ     5
  151.  
  152. NVREG_IRQ_RX_ERROR              equ     0x0001
  153. NVREG_IRQ_RX                    equ     0x0002
  154. NVREG_IRQ_RX_NOBUF              equ     0x0004
  155. NVREG_IRQ_LINK                  equ     0x0040
  156. NVREG_IRQ_TIMER                 equ     0x0020
  157. NVREG_IRQMASK_WANTED_2          equ     0x0147
  158.  
  159. NVREG_IRQ_RX_ALL                equ     (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF)
  160. NVREG_IRQ_TX_ALL                equ     0       ; ???????????
  161. NVREG_IRQ_OTHER_ALL             equ     (NVREG_IRQ_LINK or NVREG_IRQ_TIMER)
  162.  
  163. NVREG_IRQSTAT_MASK              equ     0x1ff
  164.  
  165. NVREG_TXRXCTL_KICK              equ     0x0001
  166. NVREG_TXRXCTL_BIT1              equ     0x0002
  167. NVREG_TXRXCTL_BIT2              equ     0x0004
  168. NVREG_TXRXCTL_IDLE              equ     0x0008
  169. NVREG_TXRXCTL_RESET             equ     0x0010
  170. NVREG_TXRXCTL_RXCHECK           equ     0x0400
  171.  
  172. NVREG_MCASTADDRA_FORCE          equ     0x01
  173.  
  174. NVREG_MAC_RESET_ASSERT          equ     0x0F3
  175.  
  176. NVREG_MISC1_HD                  equ     0x02
  177. NVREG_MISC1_FORCE               equ     0x3b0f3c
  178.  
  179. NVREG_PFF_ALWAYS                equ     0x7F0008
  180. NVREG_PFF_PROMISC               equ     0x80
  181. NVREG_PFF_MYADDR                equ     0x20
  182.  
  183. NVREG_OFFLOAD_HOMEPHY           equ     0x601
  184. NVREG_OFFLOAD_NORMAL            equ     RX_NIC_BUFSIZE
  185.  
  186. NVREG_RNDSEED_MASK              equ     0x00ff
  187. NVREG_RNDSEED_FORCE             equ     0x7f00
  188. NVREG_RNDSEED_FORCE2            equ     0x2d00
  189. NVREG_RNDSEED_FORCE3            equ     0x7400
  190.  
  191. ; NVREG_POLL_DEFAULT is the interval length of the timer source on the nic
  192. ; NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms
  193. NVREG_POLL_DEFAULT              equ     970
  194.  
  195. NVREG_ADAPTCTL_START            equ     0x02
  196. NVREG_ADAPTCTL_LINKUP           equ     0x04
  197. NVREG_ADAPTCTL_PHYVALID         equ     0x40000
  198. NVREG_ADAPTCTL_RUNNING          equ     0x100000
  199. NVREG_ADAPTCTL_PHYSHIFT         equ     24
  200.  
  201. NVREG_WAKEUPFLAGS_VAL           equ     0x7770
  202.  
  203. NVREG_POWERSTATE_POWEREDUP      equ     0x8000
  204. NVREG_POWERSTATE_VALID          equ     0x0100
  205. NVREG_POWERSTATE_MASK           equ     0x0003
  206. NVREG_POWERSTATE_D0             equ     0x0000
  207. NVREG_POWERSTATE_D1             equ     0x0001
  208. NVREG_POWERSTATE_D2             equ     0x0002
  209. NVREG_POWERSTATE_D3             equ     0x0003
  210.  
  211. NVREG_POWERSTATE2_POWERUP_MASK  equ     0x0F11
  212. NVREG_POWERSTATE2_POWERUP_REV_A3 equ    0x0001
  213.  
  214. NVREG_RCVCTL_START              equ     0x01
  215. NVREG_RCVSTAT_BUSY              equ     0x01
  216.  
  217. NVREG_XMITCTL_START             equ     0x01
  218.  
  219. NVREG_LINKSPEED_FORCE           equ     0x10000
  220. NVREG_LINKSPEED_10              equ     1000
  221. NVREG_LINKSPEED_100             equ     100
  222. NVREG_LINKSPEED_1000            equ     50
  223.  
  224. NVREG_RINGSZ_TXSHIFT            equ     0
  225. NVREG_RINGSZ_RXSHIFT            equ     16
  226.  
  227. LPA_1000FULL                    equ     0x0800
  228.  
  229. ; Link partner ability register.
  230. LPA_SLCT                        equ     0x001f  ; Same as advertise selector
  231. LPA_10HALF                      equ     0x0020  ; Can do 10mbps half-duplex
  232. LPA_10FULL                      equ     0x0040  ; Can do 10mbps full-duplex
  233. LPA_100HALF                     equ     0x0080  ; Can do 100mbps half-duplex
  234. LPA_100FULL                     equ     0x0100  ; Can do 100mbps full-duplex
  235. LPA_100BASE4                    equ     0x0200  ; Can do 100mbps 4k packets
  236. LPA_RESV                        equ     0x1c00  ; Unused...
  237. LPA_RFAULT                      equ     0x2000  ; Link partner faulted
  238. LPA_LPACK                       equ     0x4000  ; Link partner acked us
  239. LPA_NPAGE                       equ     0x8000  ; Next page bit
  240.  
  241. MII_READ                        equ     (-1)
  242. MII_PHYSID1                     equ     0x02    ; PHYS ID 1
  243. MII_PHYSID2                     equ     0x03    ; PHYS ID 2
  244. MII_BMCR                        equ     0x00    ; Basic mode control register
  245. MII_BMSR                        equ     0x01    ; Basic mode status register
  246. MII_ADVERTISE                   equ     0x04    ; Advertisement control reg
  247. MII_LPA                         equ     0x05    ; Link partner ability reg
  248. MII_SREVISION                   equ     0x16    ; Silicon revision
  249. MII_RESV1                       equ     0x17    ; Reserved...
  250. MII_NCONFIG                     equ     0x1c    ; Network interface config
  251.  
  252. ; PHY defines
  253. PHY_OUI_MARVELL                 equ     0x5043
  254. PHY_OUI_CICADA                  equ     0x03f1
  255. PHYID1_OUI_MASK                 equ     0x03ff
  256. PHYID1_OUI_SHFT                 equ     6
  257. PHYID2_OUI_MASK                 equ     0xfc00
  258. PHYID2_OUI_SHFT                 equ     10
  259. PHY_INIT1                       equ     0x0f000
  260. PHY_INIT2                       equ     0x0e00
  261. PHY_INIT3                       equ     0x01000
  262. PHY_INIT4                       equ     0x0200
  263. PHY_INIT5                       equ     0x0004
  264. PHY_INIT6                       equ     0x02000
  265. PHY_GIGABIT                     equ     0x0100
  266.  
  267. PHY_TIMEOUT                     equ     0x1
  268. PHY_ERROR                       equ     0x2
  269.  
  270. PHY_100                         equ     0x1
  271. PHY_1000                        equ     0x2
  272. PHY_HALF                        equ     0x100
  273.  
  274. PHY_RGMII                       equ     0x10000000
  275.  
  276. ; desc_ver values:
  277. ; This field has two purposes:
  278. ; - Newer nics uses a different ring layout. The layout is selected by
  279. ;   comparing np->desc_ver with DESC_VER_xy.
  280. ; - It contains bits that are forced on when writing to NvRegTxRxControl.
  281. DESC_VER_1                      equ     0x0
  282. DESC_VER_2                      equ     (0x02100 or NVREG_TXRXCTL_RXCHECK)
  283.  
  284. MAC_ADDR_LEN                    equ     6
  285.  
  286. NV_TX_LASTPACKET                equ     (1 shl 16)
  287. NV_TX_RETRYERROR                equ     (1 shl 19)
  288. NV_TX_LASTPACKET1               equ     (1 shl 24)
  289. NV_TX_DEFERRED                  equ     (1 shl 26)
  290. NV_TX_CARRIERLOST               equ     (1 shl 27)
  291. NV_TX_LATECOLLISION             equ     (1 shl 28)
  292. NV_TX_UNDERFLOW                 equ     (1 shl 29)
  293. NV_TX_ERROR                     equ     (1 shl 30)
  294. NV_TX_VALID                     equ     (1 shl 31)
  295.  
  296. NV_TX2_LASTPACKET               equ     (1 shl 29)
  297. NV_TX2_RETRYERROR               equ     (1 shl 18)
  298. NV_TX2_LASTPACKET1              equ     (1 shl 23)
  299. NV_TX2_DEFERRED                 equ     (1 shl 25)
  300. NV_TX2_CARRIERLOST              equ     (1 shl 26)
  301. NV_TX2_LATECOLLISION            equ     (1 shl 27)
  302. NV_TX2_UNDERFLOW                equ     (1 shl 28)
  303. ; error and valid are the same for both
  304. NV_TX2_ERROR                    equ     (1 shl 30)
  305. NV_TX2_VALID                    equ     (1 shl 31)
  306.  
  307. NV_RX_DESCRIPTORVALID           equ     (1 shl 16)
  308. NV_RX_AVAIL                     equ     (1 shl 31)
  309.  
  310. NV_RX2_DESCRIPTORVALID          equ     (1 shl 29)
  311.  
  312. RX_RING                         equ     4
  313. TX_RING                         equ     2
  314.  
  315. FLAG_MASK_V1                    equ     0xffff0000
  316. FLAG_MASK_V2                    equ     0xffffc000
  317. LEN_MASK_V1                     equ     (0xffffffff xor FLAG_MASK_V1)
  318. LEN_MASK_V2                     equ     (0xffffffff xor FLAG_MASK_V2)
  319.  
  320. ; Miscelaneous hardware related defines:
  321. NV_PCI_REGSZ_VER1               equ     0x270
  322. NV_PCI_REGSZ_VER2               equ     0x604
  323. ; various timeout delays: all in usec
  324. NV_TXRX_RESET_DELAY             equ     4
  325. NV_TXSTOP_DELAY1                equ     10
  326. NV_TXSTOP_DELAY1MAX             equ     500000
  327. NV_TXSTOP_DELAY2                equ     100
  328. NV_RXSTOP_DELAY1                equ     10
  329. NV_RXSTOP_DELAY1MAX             equ     500000
  330. NV_RXSTOP_DELAY2                equ     100
  331. NV_SETUP5_DELAY                 equ     5
  332. NV_SETUP5_DELAYMAX              equ     50000
  333. NV_POWERUP_DELAY                equ     5
  334. NV_POWERUP_DELAYMAX             equ     5000
  335. NV_MIIBUSY_DELAY                equ     50
  336. NV_MIIPHY_DELAY                 equ     10
  337. NV_MIIPHY_DELAYMAX              equ     10000
  338. NV_MAC_RESET_DELAY              equ     64
  339. NV_WAKEUPPATTERNS               equ     5
  340. NV_WAKEUPMASKENTRIES            equ     4
  341.  
  342. ; Advertisement control register.
  343. ADVERTISE_SLCT                  equ     0x001f  ; Selector bits
  344. ADVERTISE_CSMA                  equ     0x0001  ; Only selector supported
  345. ADVERTISE_10HALF                equ     0x0020  ; Try for 10mbps half-duplex
  346. ADVERTISE_10FULL                equ     0x0040  ; Try for 10mbps full-duplex
  347. ADVERTISE_100HALF               equ     0x0080  ; Try for 100mbps half-duplex
  348. ADVERTISE_100FULL               equ     0x0100  ; Try for 100mbps full-duplex
  349. ADVERTISE_100BASE4              equ     0x0200  ; Try for 100mbps 4k packets
  350. ADVERTISE_RESV                  equ     0x1c00  ; Unused...
  351. ADVERTISE_RFAULT                equ     0x2000  ; Say we can detect faults
  352. ADVERTISE_LPACK                 equ     0x4000  ; Ack link partners response
  353. ADVERTISE_NPAGE                 equ     0x8000  ; Next page bit
  354.  
  355. ADVERTISE_FULL                  equ     (ADVERTISE_100FULL or ADVERTISE_10FULL or ADVERTISE_CSMA)
  356. ADVERTISE_ALL                   equ     (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL)
  357.  
  358. MII_1000BT_CR                   equ     0x09
  359. MII_1000BT_SR                   equ     0x0a
  360. ADVERTISE_1000FULL              equ     0x0200
  361. ADVERTISE_1000HALF              equ     0x0100
  362.  
  363. BMCR_ANRESTART                  equ     0x0200  ; Auto negotiation restart
  364. BMCR_ANENABLE                   equ     0x1000  ; Enable auto negotiation
  365. BMCR_SPEED100                   equ     0x2000  ; Select 100Mbps
  366. BMCR_LOOPBACK                   equ     0x4000  ; TXD loopback bits
  367. BMCR_RESET                      equ     0x8000  ; Reset the DP83840
  368.  
  369. ; Basic mode status register.
  370. BMSR_ERCAP                      equ     0x0001  ; Ext-reg capability
  371. BMSR_JCD                        equ     0x0002  ; Jabber detected
  372. BMSR_LSTATUS                    equ     0x0004  ; Link status
  373. BMSR_ANEGCAPABLE                equ     0x0008  ; Able to do auto-negotiation
  374. BMSR_RFAULT                     equ     0x0010  ; Remote fault detected
  375. BMSR_ANEGCOMPLETE               equ     0x0020  ; Auto-negotiation complete
  376. BMSR_RESV                       equ     0x07c0  ; Unused...
  377. BMSR_10HALF                     equ     0x0800  ; Can do 10mbps, half-duplex
  378. BMSR_10FULL                     equ     0x1000  ; Can do 10mbps, full-duplex
  379. BMSR_100HALF                    equ     0x2000  ; Can do 100mbps, half-duplex
  380. BMSR_100FULL                    equ     0x4000  ; Can do 100mbps, full-duplex
  381. BMSR_100BASE4                   equ     0x8000  ; Can do 100mbps, 4k packets
  382.  
  383. ETH_ALEN                        equ     6
  384. ETH_HLEN                        equ     (2 * ETH_ALEN + 2)
  385. ETH_ZLEN                        equ     60      ; 60 + 4bytes auto payload for
  386.                                                 ; mininmum 64bytes frame length
  387.  
  388. uglobal
  389. forcedeth_mmio_addr     dd 0    ; memory map physical address
  390. forcedeth_mmio_size     dd 0    ; size of memory bar
  391. forcedeth_vendor_id     dw 0    ; Vendor ID
  392. forcedeth_device_id     dw 0    ; Device ID
  393. forcedeth_orig_mac0     dd 0    ; MAC
  394. forcedeth_orig_mac1     dd 0    ; MAC
  395. forcedeth_mapio_addr    dd 0    ; mapped IO address
  396. forcedeth_txflags       dd 0    ;
  397. forcedeth_desc_ver      dd 0    ;
  398. forcedeth_irqmask       dd 0    ; IRQ-mask
  399. forcedeth_wolenabled    dd 0    ; WOL
  400. forcedeth_in_shutdown   dd 0    ;
  401. forcedeth_cur_rx        dd 0    ;
  402. forcedeth_refill_rx     dd 0    ;
  403. forcedeth_phyaddr       dd 0    ;
  404. forcedeth_phy_oui       dd 0    ;
  405. forcedeth_gigabit       dd 0    ;
  406. forcedeth_needs_mac_reset dd 0  ;
  407. forcedeth_linkspeed     dd 0    ;
  408. forcedeth_duplex        dd 0    ;
  409. forcedeth_next_tx       dd 0    ; next TX descriptor number
  410. forcedeth_nic_tx        dd 0    ; ??? d'nt used ???
  411. forcedeth_packetlen     dd 0    ;
  412. forcedeth_nocable       dd 0    ; no cable present
  413. endg
  414.  
  415. struc   forcedeth_TxDesc {
  416.         .PacketBuffer   dd ?
  417.         .FlagLen        dd ?
  418. }
  419. virtual at 0
  420.         forcedeth_TxDesc forcedeth_TxDesc
  421.         sizeof.forcedeth_TxDesc = $ - forcedeth_TxDesc
  422. end virtual
  423.  
  424. struc   forcedeth_RxDesc {
  425.         .PacketBuffer   dd ?
  426.         .FlagLen        dd ?
  427. }
  428. virtual at 0
  429.         forcedeth_RxDesc forcedeth_RxDesc
  430.         sizeof.forcedeth_RxDesc = $ - forcedeth_RxDesc
  431. end virtual
  432.  
  433. virtual at eth_data_start
  434.         ; Define the TX Descriptor
  435.         align   256
  436.         forcedeth_tx_ring       rb      TX_RING * sizeof.forcedeth_TxDesc
  437.         ; Create a static buffer of size RX_BUF_SZ for each
  438.         ; TX Descriptor.  All descriptors point to a
  439.         ; part of this buffer
  440.         align   256
  441.         forcedeth_txb   rb      TX_RING * RX_NIC_BUFSIZE
  442.        
  443.         ; Define the RX Descriptor
  444.         align   256
  445.         forcedeth_rx_ring       rb      RX_RING * sizeof.forcedeth_RxDesc
  446.         ; Create a static buffer of size RX_BUF_SZ for each
  447.         ; RX Descriptor.  All descriptors point to a
  448.         ; part of this buffer
  449.         align   256
  450.         forcedeth_rxb   rb      RX_RING * RX_NIC_BUFSIZE
  451. end virtual
  452.  
  453.  
  454. ;***************************************************************************
  455. ;   Function
  456. ;      forcedeth_reset
  457. ;   Description
  458. ;      Place the chip (ie, the ethernet card) into a virgin state
  459. ;      No inputs
  460. ;      All registers destroyed
  461. ;
  462. ;***************************************************************************
  463. forcedeth_reset:
  464.  
  465.         ; 1) erase previous misconfiguration
  466.         ; 4.1-1: stop adapter: ignored, 4.3 seems to be overkill
  467.  
  468.         ; writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA)
  469.         mov     edi, dword [forcedeth_mapio_addr]
  470.         mov     dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE
  471.  
  472.         ; writel(0, base + NvRegMulticastAddrB)
  473.         mov     dword [edi+NvRegMulticastAddrB], 0
  474.        
  475.         ; writel(0, base + NvRegMulticastMaskA)
  476.         mov     dword [edi+NvRegMulticastMaskA], 0
  477.        
  478.         ; writel(0, base + NvRegMulticastMaskB)
  479.         mov     dword [edi+NvRegMulticastMaskB], 0
  480.  
  481.         ; writel(0, base + NvRegPacketFilterFlags)
  482.         mov     dword [edi+NvRegPacketFilterFlags], 0
  483.        
  484.         ; writel(0, base + NvRegTransmitterControl)
  485.         mov     dword [edi+NvRegTransmitterControl], 0
  486.        
  487.         ; writel(0, base + NvRegReceiverControl)
  488.         mov     dword [edi+NvRegReceiverControl], 0
  489.  
  490.         ; writel(0, base + NvRegAdapterControl)
  491.         mov     dword [edi+NvRegAdapterControl], 0
  492.  
  493.  
  494.         ; 2) initialize descriptor rings
  495.         ; init_ring(nic)
  496.         call    forcedeth_init_ring
  497.  
  498.         ; writel(0, base + NvRegLinkSpeed)
  499.         mov     dword [edi+NvRegLinkSpeed], 0
  500.        
  501.         ; writel(0, base + NvRegUnknownTransmitterReg)
  502.         mov     dword [edi+NvRegUnknownTransmitterReg], 0
  503.  
  504.         ; txrx_reset(nic)
  505.         call    forcedeth_txrx_reset
  506.        
  507.         ; writel(0, base + NvRegUnknownSetupReg6)
  508.         mov     dword [edi+NvRegUnknownSetupReg6], 0
  509.  
  510.         ; np->in_shutdown = 0
  511.         mov     dword [forcedeth_in_shutdown], 0
  512.  
  513.  
  514.         ; 3) set mac address
  515.         ; writel(mac[0], base + NvRegMacAddrA)
  516.         mov     eax, dword [forcedeth_orig_mac0]
  517.         mov     dword [edi+NvRegMacAddrA], eax
  518.        
  519.         ; writel(mac[1], base + NvRegMacAddrB)
  520.         mov     eax, dword [forcedeth_orig_mac1]
  521.         mov     dword [edi+NvRegMacAddrB], eax
  522.  
  523.  
  524.         ; 4) give hw rings
  525.         ; writel((u32) virt_to_le32desc(&rx_ring[0]), base + NvRegRxRingPhysAddr)
  526.         mov     eax, forcedeth_rx_ring
  527.  
  528. ;DEBUGF 1," K : FORCEDETH: rx_ring at 0x%x\n", eax
  529.  
  530.         sub     eax, OS_BASE    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  531.         mov     dword [edi+NvRegRxRingPhysAddr], eax
  532.  
  533.         ; writel((u32) virt_to_le32desc(&tx_ring[0]), base + NvRegTxRingPhysAddr)
  534.         mov     eax, forcedeth_tx_ring
  535.         sub     eax, OS_BASE    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  536.         mov     dword [edi+NvRegTxRingPhysAddr], eax
  537.  
  538.         ; writel(((RX_RING - 1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING - 1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes)
  539.         mov     dword [edi+NvRegRingSizes], (((RX_RING - 1) shl NVREG_RINGSZ_RXSHIFT) + ((TX_RING - 1) shl NVREG_RINGSZ_TXSHIFT))
  540.  
  541.         ; 5) continue setup
  542.         ; np->linkspeed = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
  543.         mov     dword [forcedeth_linkspeed], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
  544.        
  545.         ; np->duplex = 0
  546.         mov     dword [forcedeth_duplex], 0
  547.  
  548.         ; writel(np->linkspeed, base + NvRegLinkSpeed)
  549.         mov     dword [edi+NvRegLinkSpeed], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
  550.  
  551.         ; writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3)
  552.         mov     dword [edi+NvRegUnknownSetupReg3], NVREG_UNKSETUP3_VAL1
  553.        
  554.         ; writel(np->desc_ver, base + NvRegTxRxControl)
  555.         mov     eax, dword [forcedeth_desc_ver]
  556.         mov     dword [edi+NvRegTxRxControl], eax
  557.        
  558.         ; pci_push(base)
  559.         call    forcedeth_pci_push
  560.        
  561.         ; writel(NVREG_TXRXCTL_BIT1 | np->desc_ver, base + NvRegTxRxControl)
  562.         or      eax, NVREG_TXRXCTL_BIT1
  563.         mov     dword [edi+NvRegTxRxControl], eax
  564.  
  565.         ; reg_delay(NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, "open: SetupReg5, Bit 31 remained off\n")
  566.         push    ebx edx edi     ;;;;;;;;;;;;;;;;;;;;;;
  567.         stdcall forcedeth_reg_delay, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, 0
  568.         pop     edi edx ebx     ;;;;;;;;;;;;;;;;;;;;;;
  569.  
  570.         ; writel(0, base + NvRegUnknownSetupReg4)
  571.         mov     dword [edi+NvRegUnknownSetupReg4], 0
  572.  
  573.         ; writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus)
  574.         mov     dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK2
  575.        
  576.  
  577.         ; printf("%d-Mbs Link, %s-Duplex\n", np->linkspeed & NVREG_LINKSPEED_10 ? 10 : 100, np->duplex ? "Full" : "Half")
  578. ;;;;;;;;;;; DEBUGF
  579.  
  580.         ; 6) continue setup
  581.        
  582.         ; writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1)
  583.         mov     dword [edi+NvRegMisc1], (NVREG_MISC1_FORCE or NVREG_MISC1_HD)
  584.        
  585.         ; writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus)
  586.         mov     eax, dword [edi+NvRegTransmitterStatus]
  587.         mov     dword [edi+NvRegTransmitterStatus], eax
  588.  
  589.         ; writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags)
  590.         mov     dword [edi+NvRegPacketFilterFlags], NVREG_PFF_ALWAYS
  591.  
  592.         ; writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig)
  593.         mov     dword [edi+NvRegOffloadConfig], NVREG_OFFLOAD_NORMAL
  594.  
  595.         ; writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus)
  596.         mov     eax, dword [edi+NvRegReceiverStatus]
  597.         mov     dword [edi+NvRegReceiverStatus], eax
  598.  
  599.         ; Get a random number
  600.         ; i = random()
  601.         push    edi
  602.         stdcall sys_clock       ; eax = 0x00SSMMHH (current system time)
  603.         pop     edi
  604.  
  605.         ; writel(NVREG_RNDSEED_FORCE | (i & NVREG_RNDSEED_MASK), base + NvRegRandomSeed)
  606.         and     eax, NVREG_RNDSEED_MASK
  607.         or      eax, NVREG_RNDSEED_FORCE
  608.         mov     dword [edi+NvRegRandomSeed], eax
  609.  
  610.         ; writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1)
  611.         mov     dword [edi+NvRegUnknownSetupReg1], NVREG_UNKSETUP1_VAL
  612.        
  613.         ; writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2)
  614.         mov     dword [edi+NvRegUnknownSetupReg2], NVREG_UNKSETUP2_VAL
  615.        
  616.         ; writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval)
  617.         mov     dword [edi+NvRegPollingInterval], NVREG_POLL_DEFAULT
  618.        
  619.         ; writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6)
  620.         mov     dword [edi+NvRegUnknownSetupReg6], NVREG_UNKSETUP6_VAL
  621.  
  622.         ; writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT) | NVREG_ADAPTCTL_PHYVALID | NVREG_ADAPTCTL_RUNNING,
  623.         ; base + NvRegAdapterControl)
  624.         mov     eax, dword [forcedeth_phyaddr]
  625.         shl     eax, NVREG_ADAPTCTL_PHYSHIFT
  626.         or      eax, (NVREG_ADAPTCTL_PHYVALID or NVREG_ADAPTCTL_RUNNING)
  627.         mov     dword [edi+NvRegAdapterControl], eax
  628.        
  629.         ; writel(NVREG_MIISPEED_BIT8 | NVREG_MIIDELAY, base + NvRegMIISpeed)
  630.         mov     dword [edi+NvRegMIISpeed], (NVREG_MIISPEED_BIT8 or NVREG_MIIDELAY)
  631.  
  632.         ; writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4)
  633.         mov     dword [edi+NvRegUnknownSetupReg4], NVREG_UNKSETUP4_VAL
  634.  
  635.         ; writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags)
  636.         mov     dword [edi+NvRegWakeUpFlags], NVREG_WAKEUPFLAGS_VAL
  637.        
  638.         ; i = readl(base + NvRegPowerState)
  639.         mov     eax, dword [edi+NvRegPowerState]
  640.  
  641.         ; if ((i & NVREG_POWERSTATE_POWEREDUP) == 0)
  642.         test    eax, NVREG_POWERSTATE_POWEREDUP
  643.         jnz     @f
  644.         ; writel(NVREG_POWERSTATE_POWEREDUP | i, base + NvRegPowerState)
  645.         or      eax, NVREG_POWERSTATE_POWEREDUP
  646.         mov     dword [edi+NvRegPowerState], eax
  647.  
  648. @@:
  649.  
  650.         ; pci_push(base)
  651.         call    forcedeth_pci_push
  652.  
  653.         ; nv_udelay(10)
  654.         mov     esi, 10
  655.         call    forcedeth_nv_udelay
  656.  
  657.         ; writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState)
  658.         mov     eax, dword [edi+NvRegPowerState]
  659.         or      eax, NVREG_POWERSTATE_VALID
  660.         mov     dword [edi+NvRegPowerState], eax
  661.  
  662.         ; ??? disable all interrupts ???
  663.         ; writel(0, base + NvRegIrqMask)
  664.         mov     dword [edi+NvRegIrqMask], 0
  665.  
  666. ;;;     ; ??? Mask RX interrupts
  667. ;;;     mov     dword [edi+NvRegIrqMask], NVREG_IRQ_RX_ALL
  668. ;;;     ; ??? Mask TX interrupts
  669. ;;;     ;mov    dword [edi+NvRegIrqMask], NVREG_IRQ_TX_ALL
  670. ;;;     ; ??? Mask OTHER interrupts
  671. ;;;     mov     dword [edi+NvRegIrqMask], NVREG_IRQ_OTHER_ALL
  672.        
  673.         ; pci_push(base)
  674.         call    forcedeth_pci_push
  675.  
  676.         ; writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus)
  677.         mov     dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK2
  678.  
  679.         ; writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus)
  680.         mov     dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK
  681.  
  682.         ; pci_push(base)
  683.         call    forcedeth_pci_push
  684.  
  685.  
  686.         ; writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA)
  687.         mov     dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE
  688.  
  689.         ; writel(0, base + NvRegMulticastAddrB)
  690.         mov     dword [edi+NvRegMulticastAddrB], 0
  691.  
  692.         ; writel(0, base + NvRegMulticastMaskA)
  693.         mov     dword [edi+NvRegMulticastMaskA], 0
  694.  
  695.         ; writel(0, base + NvRegMulticastMaskB)
  696.         mov     dword [edi+NvRegMulticastMaskB], 0
  697.  
  698.         ; writel(NVREG_PFF_ALWAYS | NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags)
  699.         mov     dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_ALWAYS or NVREG_PFF_MYADDR)
  700.  
  701.         ; set_multicast(nic)
  702.         call    forcedeth_set_multicast
  703.        
  704.         ; One manual link speed update: Interrupts are enabled, future link
  705.         ; speed changes cause interrupts and are handled by nv_link_irq().
  706.  
  707.         ; miistat = readl(base + NvRegMIIStatus)
  708.         mov     eax, dword [edi+NvRegMIIStatus]
  709.  
  710.         ; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
  711.         mov     dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK
  712.  
  713.         ; dprintf(("startup: got 0x%hX.\n", miistat));
  714. ;;;     DEBUGF 1," K : FORCEDETH: startup: got 0x%x\n", eax
  715.  
  716.  
  717.         ; ret = update_linkspeed(nic)
  718.         call    forcedeth_update_linkspeed
  719.         push    eax
  720.        
  721.         ; start_tx(nic)
  722.         call    forcedeth_start_tx
  723.  
  724.         pop     eax
  725.        
  726. ;        if (ret) {
  727. ;                //Start Connection netif_carrier_on(dev);
  728. ;        } else {
  729. ;                printf("no link during initialization.\n");
  730. ;        }
  731.  
  732.         ;*** added by shurf (21.09.2008)
  733.         mov     dword [forcedeth_nocable], 0
  734.         ;***
  735.  
  736.         test    eax, eax
  737.         jnz     .return
  738.         DEBUGF 1," K : FORCEDETH: no link during initialization.\n"
  739.  
  740.         ;*** added by shurf (21.09.2008)
  741.         mov     dword [forcedeth_nocable], 1
  742.         ;***
  743.  
  744. .return:
  745.  
  746. ; Indicate that we have successfully reset the card
  747.         mov     eax, dword [pci_data]
  748.         mov     dword [eth_status], eax
  749.         ret
  750.        
  751.  
  752.  
  753. ;***************************************************************************
  754. ;   Function
  755. ;      forcedeth_probe
  756. ;   Description
  757. ;      Searches for an ethernet card, enables it and clears the rx buffer
  758. ;      If a card was found, it enables the ethernet -> TCPIP link
  759. ;
  760. ;***************************************************************************
  761. forcedeth_probe:
  762.  
  763. ;       DEBUGF 1," K : FORCEDETH: 0x%x 0x%x, 0x%x\n", [io_addr]:8,[pci_bus]:2,[pci_dev]:2
  764.  
  765.         mov     dword [forcedeth_needs_mac_reset], 0
  766.  
  767. ; BEGIN of adjust_pci_device()
  768.         ; read word from PCI-device
  769.         mov     al, 1   ;;;;;;;;;;;;;;2
  770.         mov     bh, [pci_dev]
  771.         mov     ah, [pci_bus]
  772.         mov     bl, PCI_REG_COMMAND
  773.         call    pci_read_reg
  774.         mov     bx, ax                  ; new command
  775.         or      bx, PCI_COMMAND_MASTER
  776.         or      bx, PCI_COMMAND_IO
  777.         cmp     bx, ax
  778.         je      @f
  779.         ; Enabling PCI-device (make card as bus master)
  780.         DEBUGF 1," K : FORCEDETH: Updating PCI command 0x%x->0x%x\n", ax, bx
  781.         mov     cx, bx
  782.         mov     al, 1   ;;;;;;;;;;;;2
  783.         mov     bh, [pci_dev]
  784.         mov     ah, [pci_bus]
  785.         mov     bl, PCI_REG_COMMAND
  786.         call    pci_write_reg
  787.  
  788.         ; Check latency settings
  789. @@:
  790.         ; Get current latency settings from Latency timer register (byte)
  791.         mov     al, 0   ;;;;;;;;;1
  792.         mov     bh, [pci_dev]
  793.         mov     ah, [pci_bus]
  794.         mov     bl, PCI_LATENCY_TIMER
  795.         call    pci_read_reg
  796.  
  797.         ; see if its at least 32
  798.         cmp     al, 32
  799.         jge     @f
  800.         ; set latency to 32
  801.         DEBUGF 1, "K : FORCEDETH: PCI latency timer (CFLT) is unreasonably low at %d.\n", al
  802.         DEBUGF 1, "K : FORCEDETH: Setting to 32 clocks.\n"
  803.         mov     cl, 32
  804.         mov     al, 0   ;;;;;;;1
  805.         mov     bh, [pci_dev]
  806.         mov     ah, [pci_bus]
  807.         mov     bl, PCI_LATENCY_TIMER
  808.         call    pci_write_reg
  809. ; END of adjust_pci_device()
  810.  
  811. @@:
  812. ; BEGIN of pci_bar_start (addr = pci_bar_start(pci, PCI_BASE_ADDRESS_0))
  813.         mov     al, 2   ; dword
  814.         mov     bh, [pci_dev]
  815.         mov     ah, [pci_bus]
  816.         mov     bl, PCI_BASE_ADDRESS_0
  817.         call    pci_read_reg
  818.         test    eax, PCI_BASE_ADDRESS_SPACE_IO
  819.         jz      @f
  820.         and     eax, PCI_BASE_ADDRESS_IO_MASK
  821.         jmp     .next
  822. @@:
  823.         push    eax
  824.         and     eax, PCI_BASE_ADDRESS_MEM_TYPE_MASK
  825.         cmp     eax, PCI_BASE_ADDRESS_MEM_TYPE_64
  826.         jne     .not64
  827.         mov     al, 2   ; dword
  828.         mov     bh, [pci_dev]
  829.         mov     ah, [pci_bus]
  830.         mov     bl, PCI_BASE_ADDRESS_0 + 4
  831.         call    pci_read_reg
  832.         or      eax, eax
  833.         jz      .not64
  834.         DEBUGF  1,"K : FORCEDETH: pci_bar_start: Unhandled 64bit BAR\n"
  835.         or      eax, -1
  836.         jmp     .next
  837. .not64:
  838.         pop     eax
  839.         and     eax, PCI_BASE_ADDRESS_MEM_MASK
  840. .next:
  841. ; END of pci_bar_start
  842. ; addr = eax
  843.         mov     dword [forcedeth_mmio_addr], eax
  844.  
  845.        
  846. ; BEGIN of pci_bar_size (sz = pci_bar_size(pci, PCI_BASE_ADDRESS_0))
  847.  
  848.         ; Save original bar
  849.         mov     al, 2   ; dword
  850.         mov     bh, [pci_dev]
  851.         mov     ah, [pci_bus]
  852.         mov     bl, PCI_BASE_ADDRESS_0
  853.         call    pci_read_reg
  854.         mov     dword [forcedeth_tmp_start], eax
  855.         ; Compute which bits can be set
  856.         ; (ecx - value to write)
  857.         mov     al, 2   ; dword
  858.         mov     bh, [pci_dev]
  859.         mov     ah, [pci_bus]
  860.         mov     bl, PCI_BASE_ADDRESS_0
  861.         mov     ecx, (not 0)
  862.         call    pci_write_reg
  863.         mov     al, 2   ; dword
  864.         mov     bh, [pci_dev]
  865.         mov     ah, [pci_bus]
  866.         mov     bl, PCI_BASE_ADDRESS_0
  867.         call    pci_read_reg
  868.         push    eax
  869.         ; Restore the original size
  870.         mov     al, 2   ; dword
  871.         mov     bh, [pci_dev]
  872.         mov     ah, [pci_bus]
  873.         mov     bl, PCI_BASE_ADDRESS_0
  874.         mov     ecx, dword [forcedeth_tmp_start]
  875.         call    pci_write_reg
  876.         ; Find the significant bits
  877.         pop     eax
  878.         test    dword [forcedeth_tmp_start], PCI_BASE_ADDRESS_SPACE_IO
  879.         jz      @f
  880.         and     eax, PCI_BASE_ADDRESS_IO_MASK
  881.         jmp     .next2
  882. @@:
  883.         and     eax, PCI_BASE_ADDRESS_MEM_MASK
  884. .next2:
  885.         ; Find the lowest bit set
  886.         mov     ecx, eax
  887.         sub     eax, 1
  888.         not     eax
  889.         and     ecx, eax
  890.  
  891. ; END of pci_bar_start
  892.         mov     dword [forcedeth_mmio_size], ecx
  893.  
  894.         DEBUGF 1," K : FORCEDETH: mmio_addr= 0x%x [mmio_size= 0x%x]\n", [forcedeth_mmio_addr]:8, [forcedeth_mmio_size]:8
  895.  
  896.         ; Get Vendor and Device ID
  897.         mov     al, 2
  898.         mov     bh, [pci_dev]
  899.         mov     ah, [pci_bus]
  900.         mov     bl, PCI_VENDOR_ID
  901.         call    pci_read_reg
  902.         mov     word [forcedeth_vendor_id], ax
  903.         shr     eax, 16
  904.         mov     word [forcedeth_device_id], ax
  905.  
  906.         DEBUGF 1," K : FORCEDETH: vendor_id= 0x%x device_id= 0x%x\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4
  907.  
  908.         ; handle different descriptor versions
  909.         mov     eax, dword [forcedeth_device_id]
  910.         cmp     eax, PCI_DEVICE_ID_NVIDIA_NVENET_1
  911.         je      .ver1
  912.         cmp     eax, PCI_DEVICE_ID_NVIDIA_NVENET_2
  913.         je      .ver1
  914.         cmp     eax, PCI_DEVICE_ID_NVIDIA_NVENET_3
  915.         je      .ver1
  916.         mov     dword [forcedeth_desc_ver], DESC_VER_2
  917.         jmp     @f
  918. .ver1:
  919.         mov     dword [forcedeth_desc_ver], DESC_VER_1
  920. @@:
  921.         ; read the mac address
  922.         ; map memory
  923.         stdcall map_io_mem, [forcedeth_mmio_addr], [forcedeth_mmio_size], (PG_SW+PG_NOCACHE)
  924.         test    eax, eax
  925.         jz      .fail
  926.  
  927.         mov     dword [forcedeth_mapio_addr], eax
  928.         mov     edi, eax
  929.         mov     eax, dword [edi+NvRegMacAddrA]
  930.         mov     dword [forcedeth_orig_mac0], eax
  931.         mov     edx, dword [edi+NvRegMacAddrB]
  932.         mov     dword [forcedeth_orig_mac1], edx
  933.  
  934.         ; save MAC-address to global variable node_addr
  935.         mov     dword [node_addr], eax
  936.         mov     word [node_addr+4], dx
  937.  
  938.         ; reverse if desired
  939.         cmp     word [forcedeth_device_id], 0x03E5
  940.         jae     .no_reverse_mac
  941.         mov     al, byte [node_addr]
  942.         xchg    al, byte [node_addr+5]
  943.         mov     byte [node_addr], al
  944.         mov     al, byte [node_addr+1]
  945.         xchg    al, byte [node_addr+4]
  946.         mov     byte [node_addr+4], al
  947.         mov     al, byte [node_addr+2]
  948.         xchg    al, byte [node_addr+3]
  949.         mov     byte [node_addr+3], al
  950. .no_reverse_mac:
  951.  
  952. ;       DEBUGF 1," K : FORCEDETH: orig_mac0= 0x%x\n", [forcedeth_orig_mac0]:8
  953. ;       DEBUGF 1," K : FORCEDETH: orig_mac1= 0x%x\n", [forcedeth_orig_mac1]:8
  954.         DEBUGF 1," K : FORCEDETH: MAC = %x-%x-%x-%x-%x-%x\n", [node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2,
  955.  
  956.         ; disable WOL
  957.         mov     edi, dword [forcedeth_mapio_addr]
  958.         mov     dword [edi+NvRegWakeUpFlags], 0
  959.         mov     dword [forcedeth_wolenabled], 0
  960.        
  961.         mov     dword [forcedeth_txflags], (NV_TX2_LASTPACKET or NV_TX2_VALID)
  962.         cmp     dword [forcedeth_desc_ver], DESC_VER_1
  963.         jne     @f
  964.         mov     dword [forcedeth_txflags], (NV_TX_LASTPACKET or NV_TX_VALID)
  965. @@:    
  966.  
  967. ; BEGIN of switch (pci->dev_id)
  968.  
  969.         cmp     word [forcedeth_device_id], 0x01C3
  970.         jne     .next_0x0066
  971.         ; nforce
  972.         mov     dword [forcedeth_irqmask], 0    ;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
  973.         jmp     .end_switch
  974.  
  975. .next_0x0066:
  976.         cmp     word [forcedeth_device_id], 0x0066
  977.         je      @f
  978.         cmp     word [forcedeth_device_id], 0x00D6
  979.         je      @f
  980.         jmp     .next_0x0086
  981. @@:    
  982.         mov     dword [forcedeth_irqmask], 0    ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
  983.         cmp     dword [forcedeth_desc_ver], DESC_VER_1
  984.         jne     @f
  985.         or      dword [forcedeth_txflags], NV_TX_LASTPACKET1
  986.         jmp     .end_switch
  987. @@:
  988.         or      dword [forcedeth_txflags], NV_TX2_LASTPACKET1
  989.         jmp     .end_switch
  990.  
  991. .next_0x0086:
  992.         cmp     word [forcedeth_device_id], 0x0086
  993.         je      @f
  994.         cmp     word [forcedeth_device_id], 0x008c
  995.         je      @f
  996.         cmp     word [forcedeth_device_id], 0x00e6
  997.         je      @f
  998.         cmp     word [forcedeth_device_id], 0x00df
  999.         je      @f
  1000.         cmp     word [forcedeth_device_id], 0x0056
  1001.         je      @f
  1002.         cmp     word [forcedeth_device_id], 0x0057
  1003.         je      @f
  1004.         cmp     word [forcedeth_device_id], 0x0037
  1005.         je      @f
  1006.         cmp     word [forcedeth_device_id], 0x0038
  1007.         je      @f
  1008.         jmp     .next_0x0268
  1009. @@:    
  1010.         ; np->irqmask = NVREG_IRQMASK_WANTED_2;
  1011.         ; np->irqmask |= NVREG_IRQ_TIMER;
  1012.         mov     dword [forcedeth_irqmask], 0    ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
  1013.  
  1014.         ; if (np->desc_ver == DESC_VER_1)
  1015.         cmp     dword [forcedeth_desc_ver], DESC_VER_1
  1016.         jne     @f
  1017.         ;  np->tx_flags |= NV_TX_LASTPACKET1;
  1018.         or      dword [forcedeth_txflags], NV_TX_LASTPACKET1
  1019.         jmp     .end_switch
  1020.         ; else
  1021. @@:
  1022.         ;  np->tx_flags |= NV_TX2_LASTPACKET1;
  1023.         or      dword [forcedeth_txflags], NV_TX2_LASTPACKET1
  1024.  
  1025.         ; break;
  1026.         jmp     .end_switch
  1027.  
  1028. .next_0x0268:
  1029. ;       cmp     word [forcedeth_device_id], 0x0268
  1030. ;       je      @f
  1031. ;       cmp     word [forcedeth_device_id], 0x0269
  1032. ;       je      @f
  1033. ;       cmp     word [forcedeth_device_id], 0x0372
  1034. ;       je      @f
  1035. ;       cmp     word [forcedeth_device_id], 0x0373
  1036. ;       je      @f
  1037. ;       jmp     .default_switch
  1038. ;@@:
  1039.         cmp     word [forcedeth_device_id], 0x0268
  1040.         jb      .default_switch
  1041.         ; pci_read_config_byte(pci, PCI_REVISION_ID, &revision_id);
  1042.         mov     al, 0   ; byte
  1043.         mov     bh, [pci_dev]
  1044.         mov     ah, [pci_bus]
  1045.         mov     bl, PCI_REVISION_ID
  1046.         call    pci_read_reg
  1047.         mov     ecx, eax        ; cl = revision_id
  1048.  
  1049.         ; take phy and nic out of low power mode
  1050.         ; powerstate = readl(base + NvRegPowerState2);
  1051.         mov     edi, dword [forcedeth_mapio_addr]
  1052.         mov     eax, dword [edi+NvRegPowerState2]       ; eax = powerstate
  1053.        
  1054.         ; powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK;
  1055.         and     eax, not NVREG_POWERSTATE2_POWERUP_MASK
  1056.        
  1057.         ; if ((pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_12||pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_13)&&revision_id>=0xA3)
  1058.         cmp     dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_12
  1059.         je      @f
  1060.         cmp     dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_13
  1061.         je      @f
  1062.         jmp     .end_if
  1063. @@:
  1064.         cmp     cl, 0xA3
  1065.         jl      .end_if
  1066.         ;     powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3;
  1067.         or      eax, NVREG_POWERSTATE2_POWERUP_REV_A3
  1068.  
  1069. .end_if:
  1070.  
  1071.         ; writel(powerstate, base + NvRegPowerState2);
  1072.         mov     dword [edi+NvRegPowerState2], eax
  1073.  
  1074.         ; //DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ
  1075.         ; np->irqmask = NVREG_IRQMASK_WANTED_2;
  1076.         ; np->irqmask |= NVREG_IRQ_TIMER;
  1077.         mov     dword [forcedeth_irqmask], 0    ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
  1078.        
  1079.         ; needs_mac_reset = 1;
  1080.         mov     dword [forcedeth_needs_mac_reset], 1
  1081.        
  1082.         ; if (np->desc_ver == DESC_VER_1)
  1083.         cmp     dword [forcedeth_desc_ver], DESC_VER_1
  1084.         jne     @f
  1085.         ;   np->tx_flags |= NV_TX_LASTPACKET1;
  1086.         or      dword [forcedeth_txflags], NV_TX_LASTPACKET1
  1087.         jmp     .end_if2
  1088. @@:
  1089.         ; else
  1090.         ;   np->tx_flags |= NV_TX2_LASTPACKET1;
  1091.         or      dword [forcedeth_txflags], NV_TX2_LASTPACKET1
  1092.  
  1093. .end_if2:
  1094.         ; break;
  1095.         jmp     .end_switch
  1096.  
  1097. .default_switch:
  1098.         DEBUGF 1," K : FORCEDETH: Your card was undefined in this driver.\n"
  1099.         DEBUGF 1," K : FORCEDETH: Review driver_data in Kolibri driver and send a patch\n"
  1100.  
  1101. .end_switch:
  1102.  
  1103. ; END of switch (pci->dev_id)
  1104.  
  1105.  
  1106.         ; Find a suitable phy
  1107.         mov     dword [forcedeth_tmp_i], 1
  1108. .for_loop:
  1109.         ; for (i = 1; i <= 32; i++)
  1110.         ; phyaddr = i & 0x1f
  1111.         mov     ebx, dword [forcedeth_tmp_i]
  1112.         and     ebx, 0x1f
  1113.  
  1114.         ; id1 = mii_rw(phyaddr, MII_PHYSID1, MII_READ)
  1115.         ;EBX - addr, EAX - miireg, ECX - value
  1116.         mov     eax, MII_PHYSID1
  1117.         mov     ecx, MII_READ
  1118.         call    forcedeth_mii_rw        ; id1 = eax
  1119.  
  1120.         ; if (id1 < 0 || id1 == 0xffff)
  1121.         cmp     eax, 0xffffffff
  1122.         je      .continue_for
  1123.         test    eax, 0x80000000
  1124.         jnz     .continue_for
  1125.         mov     dword [forcedeth_tmp_id1], eax
  1126.  
  1127.         ; id2 = mii_rw(nic, phyaddr, MII_PHYSID2, MII_READ)
  1128.         mov     eax, MII_PHYSID2
  1129.         mov     ecx, MII_READ
  1130.         call    forcedeth_mii_rw        ; id2 = eax
  1131.  
  1132.         ; if (id2 < 0 || id2 == 0xffff)
  1133.         cmp     eax, 0xffffffff
  1134.         je      .continue_for
  1135.         test    eax, 0x80000000
  1136.         jnz     .continue_for
  1137.         mov     dword [forcedeth_tmp_id2], eax
  1138.  
  1139.         jmp     .break_for
  1140. .continue_for:
  1141.         inc     dword [forcedeth_tmp_i]
  1142.         cmp     dword [forcedeth_tmp_i], 32
  1143.         jle     .for_loop
  1144.         jmp     .end_for
  1145.  
  1146. .break_for:
  1147.  
  1148. ;;;;    DEBUGF 1," K : FORCEDETH: id1=0x%x id2=0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8
  1149.  
  1150.         ; id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT
  1151.         mov     eax, dword [forcedeth_tmp_id1]
  1152.         and     eax, PHYID1_OUI_MASK
  1153.         shl     eax, PHYID1_OUI_SHFT
  1154.         mov     dword [forcedeth_tmp_id1], eax
  1155.  
  1156.         ; id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT
  1157.         mov     eax, dword [forcedeth_tmp_id2]
  1158.         and     eax, PHYID2_OUI_MASK
  1159.         shr     eax, PHYID2_OUI_SHFT
  1160.         mov     dword [forcedeth_tmp_id2], eax
  1161.  
  1162.         DEBUGF 1," K : FORCEDETH: Found PHY  0x%x:0x%x at address 0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8, ebx
  1163.  
  1164.         ; np->phyaddr = phyaddr;
  1165.         mov     dword [forcedeth_phyaddr], ebx
  1166.  
  1167.         ; np->phy_oui = id1 | id2;
  1168.         mov     eax, dword [forcedeth_tmp_id1]
  1169.         or      eax, dword [forcedeth_tmp_id2]
  1170.         mov     dword [forcedeth_phy_oui], eax
  1171.  
  1172. .end_for:
  1173.  
  1174.         ; if (i == 33)
  1175.         cmp     dword [forcedeth_tmp_i], 33
  1176.         jne     @f
  1177.         ; PHY in isolate mode? No phy attached and user wants to
  1178.         ; test loopback? Very odd, but can be correct.
  1179.        
  1180.         DEBUGF 1," K : FORCEDETH: Could not find a valid PHY.\n"
  1181.  
  1182.         jmp     .next3
  1183.  
  1184. @@:
  1185.  
  1186.         ; if (i != 33)
  1187.         ; reset it
  1188.         call    forcedeth_phy_init
  1189.  
  1190. .next3:
  1191.  
  1192. ;        dprintf(("%s: forcedeth.c: subsystem: %hX:%hX bound to %s\n",
  1193. ;                 pci->name, pci->vendor, pci->dev_id, pci->name));
  1194.         DEBUGF 1," K : FORCEDETH: subsystem: 0x%x:0x%x bound to forcedeth\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4
  1195.  
  1196.  
  1197. ;        if(needs_mac_reset) mac_reset(nic);
  1198.         cmp     dword [forcedeth_needs_mac_reset], 0
  1199.         je      @f
  1200.         call    forcedeth_mac_reset
  1201.  
  1202. @@:
  1203.        
  1204.         ; if(!forcedeth_reset(nic)) return 0; // no valid link
  1205.         call    forcedeth_reset
  1206.         test    eax, eax
  1207.         jnz     @f
  1208.         mov     eax, 0
  1209.         jmp     .return
  1210.  
  1211. @@:
  1212.  
  1213.         ; point to NIC specific routines
  1214.         ; dev->disable = forcedeth_disable;
  1215.         ; nic->poll = forcedeth_poll;
  1216.         ; nic->transmit = forcedeth_transmit;
  1217.         ; nic->irq = forcedeth_irq;
  1218.         ;;;;;;;;;stdcall attach_int_handler, 11, forcedeth_int_handler, 0
  1219.  
  1220.         ; return 1
  1221.         mov     eax, 1
  1222.         jmp     .return
  1223.  
  1224. .fail:
  1225.         mov     eax, 0
  1226.  
  1227. .return:
  1228.         ret
  1229.  
  1230. uglobal
  1231. forcedeth_tmp_start     dd ?
  1232. forcedeth_tmp_reg       dd ?
  1233. forcedeth_tmp_i         dd ?
  1234. forcedeth_tmp_id1       dd ?
  1235. forcedeth_tmp_id2       dd ?
  1236. forcedeth_tmp_phyinterface      dd ?
  1237. forcedeth_tmp_newls     dd ?
  1238. forcedeth_tmp_newdup    dd ?
  1239. forcedeth_tmp_retval    dd ?
  1240. forcedeth_tmp_control_1000      dd ?
  1241. forcedeth_tmp_lpa       dd ?
  1242. forcedeth_tmp_adv       dd ?
  1243. forcedeth_tmp_len       dd ?
  1244. forcedeth_tmp_valid     dd ?
  1245. forcedeth_tmp_nr        dd ?
  1246. forcedeth_tmp_ptxb      dd ?
  1247. endg
  1248.  
  1249. ;***************************************************************************
  1250. ; Function
  1251. ;    forcedeth_poll
  1252. ;
  1253. ; Description
  1254. ;    Polls the ethernet card for a received packet
  1255. ;    Received data, if any, ends up in Ether_buffer
  1256. ;
  1257. ;***************************************************************************
  1258. forcedeth_poll:
  1259.  
  1260.         mov     word [eth_rx_data_len], 0
  1261.  
  1262.         ; ????????????????????????????
  1263.         ; ??? Clear events? ???
  1264.         mov     edi, dword [forcedeth_mapio_addr]
  1265.         mov     dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK
  1266.         ; ????????????????????????????
  1267.  
  1268. .top:
  1269.  
  1270.         ; i = np->cur_rx % RX_RING
  1271.         mov     eax, dword [forcedeth_cur_rx]
  1272.         and     eax, (RX_RING-1)
  1273.         mov     dword [forcedeth_tmp_i], eax
  1274.  
  1275.         ; Flags = le32_to_cpu(rx_ring[i].FlagLen)
  1276.         ; Flags = rx_ring[i].FlagLen
  1277.         mov     cl, sizeof.forcedeth_RxDesc
  1278.         mul     cl
  1279.         add     eax, forcedeth_rx_ring
  1280.         mov     ebx, eax
  1281.         mov     eax, [ebx + forcedeth_RxDesc.FlagLen]
  1282.  
  1283.  
  1284.         ; if (Flags & NV_RX_AVAIL)
  1285.         test    eax, NV_RX_AVAIL
  1286.         ;   return 0;       /* still owned by hardware, */
  1287.         ; still owned by hardware
  1288.         jnz     .return0
  1289.  
  1290. ;;;;;   DEBUGF  1,"poll: FlagLen = %x\n", eax
  1291.  
  1292.         ; if (np->desc_ver == DESC_VER_1) {
  1293.         cmp     dword [forcedeth_desc_ver], DESC_VER_1
  1294.         jne     @f
  1295.         ;   if (!(Flags & NV_RX_DESCRIPTORVALID))
  1296.         test    eax, NV_RX_DESCRIPTORVALID
  1297.         ;     return 0;
  1298.         jz      .return0
  1299.         jmp     .next
  1300.         ; } else {
  1301. @@:
  1302.         ;   if (!(Flags & NV_RX2_DESCRIPTORVALID))
  1303.         test    eax, NV_RX2_DESCRIPTORVALID
  1304.         ;     return 0;
  1305.         jz      .return0
  1306.         ; }
  1307.        
  1308. .next:
  1309.  
  1310.         ; len = nv_descr_getlength(&rx_ring[i], np->desc_ver)
  1311.         ; len = rx_ring[i].FlagLen & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2);
  1312.         ; eax = FlagLen
  1313.         cmp     dword [forcedeth_desc_ver], DESC_VER_1
  1314.         jne     @f
  1315.         and     eax, LEN_MASK_V1
  1316.         jmp     .next2
  1317. @@:
  1318.         and     eax, LEN_MASK_V2
  1319.  
  1320. .next2:
  1321.  
  1322.         ; mov   dword [forcedeth_tmp_len], eax
  1323.  
  1324.         ; valid = 1
  1325.         mov     dword [forcedeth_tmp_valid], 1
  1326.                
  1327.         ; got a valid packet - forward it to the network core
  1328.         ; nic->packetlen = len;
  1329.         mov     dword [forcedeth_packetlen], eax
  1330.         ;
  1331.         mov     word [eth_rx_data_len], ax
  1332. ;;;;;;;;;        DEBUGF 1,"poll: packet len = 0x%x\n", [forcedeth_packetlen]
  1333.  
  1334.  
  1335.         ; memcpy(nic->packet, rxb + (i * RX_NIC_BUFSIZE), nic->packetlen);
  1336.         ; Copy packet to system buffer (Ether_buffer)
  1337.         ;???? ecx = (len-4)
  1338.         mov     ecx, eax
  1339.         push    ecx
  1340.         shr     ecx, 2
  1341.  
  1342.         ; rxb + (i * RX_NIC_BUFSIZE)
  1343.         mov     eax, dword [forcedeth_tmp_i]
  1344.         mov     bx, RX_NIC_BUFSIZE
  1345.         mul     bx
  1346.         add     eax, forcedeth_rxb
  1347.  
  1348.         mov     esi, eax
  1349.         mov     edi, Ether_buffer
  1350.         cld             ; set to increment
  1351.         rep movsd       ; mov dword from [esi++] to [edi++]
  1352.         pop     ecx
  1353.         and     ecx, 3  ; copy rest 1-3 bytes
  1354.         rep movsb
  1355.  
  1356.         ; wmb();
  1357.         ; ???
  1358.  
  1359.         ; np->cur_rx++;
  1360.         inc     dword [forcedeth_cur_rx]
  1361.  
  1362.         ; if (!valid)
  1363.         cmp     dword [forcedeth_tmp_valid], 0
  1364.         jne     @f
  1365.         ;   goto top;
  1366.         jmp     .top
  1367. @@:
  1368.         ; alloc_rx(nic);
  1369.         call    forcedeth_alloc_rx
  1370.  
  1371.         ; return 1;
  1372.         jmp     .return1
  1373.  
  1374. ;;;;;   DEBUGF  1,"K : FORCEDETH: poll: ...\n"
  1375.  
  1376.  
  1377. .return0:
  1378.         mov     eax, 0
  1379.         jmp     .return
  1380. .return1:
  1381.         mov     eax, 1
  1382. .return:
  1383.         ;;push  eax
  1384.  
  1385.         ; ????????????????????????????????????????????????
  1386.         ; ????? clear interrupt mask/status
  1387.         ; read IRQ status
  1388.         ;;mov   edi, dword [forcedeth_mapio_addr]
  1389.         ;;mov   eax, dword [edi+NvRegIrqStatus]
  1390.  
  1391.         ; clear events
  1392.         ;;and   eax, not (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF or NVREG_IRQ_LINK or NVREG_IRQ_TIMER)
  1393.  
  1394.         ; write IRQ status
  1395.         ;;mov   dword [edi+NvRegIrqStatus], eax
  1396.         ; ????????????????????????????????????????????????
  1397.  
  1398.         ;;pop   eax
  1399.         ret
  1400.  
  1401.  
  1402. ;***************************************************************************
  1403. ;   Function
  1404. ;      forcedeth_transmit
  1405. ;
  1406. ;   Description
  1407. ;       Transmits a packet of data via the ethernet card
  1408. ;          Pointer to 48 bit destination address in edi
  1409. ;         Type of packet in bx
  1410. ;         size of packet in ecx
  1411. ;         pointer to packet data in esi
  1412. ;
  1413. ;***************************************************************************
  1414. forcedeth_transmit:
  1415.  
  1416.         ; send the packet to destination
  1417. ;pusha
  1418. ;DEBUGF 1,"K : FORCEDETH: transmit: packet type = 0x%x\n", ebx
  1419. ;DEBUGF 1,"K : FORCEDETH: transmit: packet len  = 0x%x\n", ecx
  1420. ;mov    eax, dword [edi]
  1421. ;DEBUGF 1,"K : FORCEDETH: transmit: dest adr    = 0x%x\n", eax
  1422. ;mov    eax, dword [edi+4]
  1423. ;DEBUGF 1,"K : FORCEDETH: transmit: dest adr2   = 0x%x\n", eax
  1424. ;mov    eax, dword [node_addr]
  1425. ;DEBUGF 1,"K : FORCEDETH: transmit: src  adr    = 0x%x\n", eax
  1426. ;mov    eax, dword [node_addr+4]
  1427. ;DEBUGF 1,"K : FORCEDETH: transmit: src adr2    = 0x%x\n", eax
  1428. ;popa
  1429.  
  1430.         ; int nr = np->next_tx % TX_RING
  1431.         mov     eax, dword [forcedeth_next_tx]
  1432.         and     eax, (TX_RING-1)
  1433.         mov     dword [forcedeth_tmp_nr], eax
  1434.        
  1435.         ; point to the current txb incase multiple tx_rings are used
  1436.         ; ptxb = txb + (nr * RX_NIC_BUFSIZE)
  1437.         push    ecx
  1438.         mov     cx, RX_NIC_BUFSIZE
  1439.         mul     cx      ; AX*CX, result to DX:AX
  1440.         add     eax, forcedeth_txb
  1441.         mov     dword [forcedeth_tmp_ptxb], eax
  1442.         push    esi
  1443.         mov     esi, edi        ; dst MAC
  1444.         mov     edi, eax        ; packet buffer
  1445.         cld                     ; set to increment
  1446.        
  1447.         ; copy the packet to ring buffer
  1448.         ; memcpy(ptxb, d, ETH_ALEN);      /* dst */
  1449.         movsd
  1450.         movsw
  1451.        
  1452.         ; memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN);      /* src */
  1453.         mov     esi, node_addr
  1454.         movsd
  1455.         movsw
  1456.  
  1457.         ; nstype = htons((u16) t);        /* type */
  1458.         ; memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2);        /* type */
  1459.         mov     word [edi], bx
  1460.         add     edi, 2
  1461.        
  1462.         ; memcpy(ptxb + ETH_HLEN, p, s);
  1463.         pop     esi
  1464.         pop     ecx
  1465.         push    ecx
  1466.         shr     ecx, 2          ; count in dwords
  1467.         rep movsd               ; copy dwords from [esi+=4] to [edi+=4]
  1468.         pop     ecx
  1469.         push    ecx
  1470.         and     ecx, 3          ; copy rest 1-3 bytes
  1471.         rep movsb               ; copy bytess from [esi++] to [edi++]
  1472.  
  1473.  
  1474.         ; s += ETH_HLEN;
  1475.         ; while (s < ETH_ZLEN)    /* pad to min length */
  1476.         ;  ptxb[s++] = '\0';
  1477.         ; pad to min length
  1478.         pop     ecx
  1479.         add     ecx, ETH_HLEN
  1480.         push    ecx             ; header length + data length
  1481.         cmp     ecx, ETH_ZLEN
  1482.         jge     @f
  1483.         mov     eax, ETH_ZLEN
  1484.         sub     eax, ecx
  1485.         xchg    eax, ecx
  1486.         mov     al, 0
  1487.         rep stosb               ; copy byte from al to [edi++]
  1488.  
  1489. @@:
  1490.  
  1491.         ; tx_ring[nr].PacketBuffer = (u32) virt_to_le32desc(ptxb);
  1492.         mov     eax, dword [forcedeth_tmp_nr]
  1493.         mov     cl, sizeof.forcedeth_TxDesc
  1494.         mul     cl
  1495.         add     eax, forcedeth_tx_ring
  1496.         mov     ebx, eax
  1497.         mov     eax, dword [forcedeth_tmp_ptxb]
  1498.         sub     eax, OS_BASE            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1499.         mov     [ebx + forcedeth_TxDesc.PacketBuffer], eax
  1500.  
  1501. ;DEBUGF 1,"K : FORCEDETH: transmit: PacketBuffer = 0x%x\n", eax
  1502. ;DEBUGF 1,"K : FORCEDETH: transmit: txflags = 0x%x\n", [forcedeth_txflags]:8
  1503.  
  1504.         ; wmb();
  1505.         ; tx_ring[nr].FlagLen = cpu_to_le32((s - 1) | np->tx_flags);
  1506.         pop     eax             ; header length + data length
  1507.         mov     ecx, dword [forcedeth_txflags]
  1508.         or      eax, ecx
  1509.         mov     [ebx + forcedeth_TxDesc.FlagLen], eax
  1510.  
  1511.         ; writel(NVREG_TXRXCTL_KICK | np->desc_ver, base + NvRegTxRxControl);
  1512.         mov     edi, dword [forcedeth_mapio_addr]
  1513.         mov     eax, dword [forcedeth_desc_ver]
  1514.         or      eax, NVREG_TXRXCTL_KICK
  1515.         mov     dword [edi+NvRegTxRxControl], eax
  1516.  
  1517.         ; pci_push(base);
  1518.         call    forcedeth_pci_push
  1519.  
  1520.         ; np->next_tx++
  1521.         inc     dword [forcedeth_next_tx]; may be need to reset? Overflow?
  1522.  
  1523.         ret
  1524.  
  1525. ;***************************************************************************
  1526. ;   Function
  1527. ;      forcedeth_cable
  1528. ;
  1529. ;   Description
  1530. ;       Return AL=0, if cable is not connected
  1531. ;       Returm AL=1, if cable is connected
  1532. ;
  1533. ;***************************************************************************
  1534. forcedeth_cable:
  1535.  
  1536.         mov     al, 1
  1537.         cmp     dword [forcedeth_nocable], 1
  1538.         jne     .return
  1539.         mov     al, 0
  1540.  
  1541. .return:
  1542.         ret
  1543.  
  1544. ;***************************************************************************
  1545.        
  1546.        
  1547. ; read/write a register on the PHY.
  1548. ; Caller must guarantee serialization
  1549. ; Input:  EAX - miireg, EBX - addr, ECX - value
  1550. ; Output: EAX - retval
  1551. forcedeth_mii_rw:
  1552.         push    ebx
  1553.         push    eax     ; save miireg
  1554.         ; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus)
  1555.         mov     edi, dword [forcedeth_mapio_addr]
  1556.         mov     dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK
  1557.  
  1558.         ; reg = readl(base + NvRegMIIControl)
  1559.         mov     eax, dword [edi+NvRegMIIControl]
  1560.         test    eax, NVREG_MIICTL_INUSE
  1561.         jz      @f
  1562.         ; writel(NVREG_MIICTL_INUSE, base + NvRegMIIControl)
  1563.         mov     dword [edi+NvRegMIIControl], NVREG_MIICTL_INUSE
  1564.         ; nv_udelay(NV_MIIBUSY_DELAY)
  1565.         mov     esi, NV_MIIBUSY_DELAY
  1566.         call    forcedeth_nv_udelay
  1567. @@:
  1568.         ; reg = (addr << NVREG_MIICTL_ADDRSHIFT) | miireg
  1569.         pop     edx     ; restore miireg
  1570.         mov     eax, ebx
  1571.         shl     eax, NVREG_MIICTL_ADDRSHIFT
  1572.         or      eax, edx
  1573.         mov     dword [forcedeth_tmp_reg], eax
  1574.  
  1575.         cmp     ecx, MII_READ
  1576.         je      @f
  1577.         ; writel(value, base + NvRegMIIData)
  1578.         mov     dword [edi+NvRegMIIData], ecx
  1579.         ; reg |= NVREG_MIICTL_WRITE
  1580.         or      dword [forcedeth_tmp_reg], NVREG_MIICTL_WRITE
  1581. @@:
  1582.         ; writel(reg, base + NvRegMIIControl)
  1583.         mov     eax, dword [forcedeth_tmp_reg]
  1584.         mov     dword [edi+NvRegMIIControl], eax
  1585.  
  1586.         push    ebx edx edi     ;;;;;;;;;;;;;;;;;;;;;;
  1587.  
  1588.         ; reg_delay(NvRegMIIControl, NVREG_MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL)
  1589.         stdcall forcedeth_reg_delay, NvRegMIIControl, NVREG_MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, 0
  1590.  
  1591.         pop     edi edx ebx     ;;;;;;;;;;;;;;;;;;;;;;
  1592.  
  1593.         test    eax, eax
  1594.         jz      @f
  1595. ;;;;;;;;        DEBUGF  1,"K : FORCEDETH: mii_rw of reg %d at PHY %d timed out.\n", edx, ebx
  1596.         mov     eax, 0xffffffff
  1597.         jmp     .return
  1598. @@:
  1599.         cmp     ecx, MII_READ
  1600.         je      @f
  1601.         ;it was a write operation - fewer failures are detectable
  1602. ;;;;;;;;        DEBUGF  1,"K : FORCEDETH: mii_rw wrote 0x%x to reg %d at PHY %d\n", ecx, edx, ebx
  1603.         mov     eax, 0
  1604.         jmp     .return
  1605. @@:
  1606.         ; readl(base + NvRegMIIStatus)
  1607.         mov     eax, dword [edi+NvRegMIIStatus]
  1608.         test    eax, NVREG_MIISTAT_ERROR
  1609.         jz      @f
  1610. ;;;;;;;;        DEBUGF  1,"K : FORCEDETH: mii_rw of reg %d at PHY %d failed.\n", edx, ebx
  1611.         mov     eax, 0xffffffff
  1612.         jmp     .return
  1613. @@:
  1614.         ; retval = readl(base + NvRegMIIData)
  1615.         mov     eax, dword [edi+NvRegMIIData]
  1616. ;;;;;;;;        DEBUGF  1,"K : FORCEDETH: mii_rw read from reg %d at PHY %d: 0x%x.\n", edx, ebx, eax
  1617. .return:
  1618.         pop     ebx
  1619.         ret
  1620.  
  1621.  
  1622.  
  1623. ; Input:  ESI - delay
  1624. ; Output: none
  1625. forcedeth_nv_udelay:
  1626.  
  1627.         push    ebx
  1628.         cmp     dword [forcedeth_in_shutdown], 0
  1629.         jne     @f
  1630.         call    forcedeth_udelay        ; delay on ESI
  1631.         jmp     .return
  1632. @@:
  1633.        
  1634. .loop:
  1635.         cmp     esi, 0
  1636.         je      .return
  1637.         ; Don't allow an rx_ring overflow to happen
  1638.         ; while shutting down the NIC it will
  1639.         ; kill the receive function.
  1640.  
  1641.         call    forcedeth_drop_rx
  1642.         mov     ebx, 3          ; sleep = 3
  1643.         cmp     ebx, esi        ; if(sleep > delay)
  1644.         jle     @f
  1645.         mov     ebx, esi        ; sleep = delay
  1646. @@:
  1647.         push    esi
  1648.         mov     esi, ebx
  1649.         ; udelay(sleep)
  1650.         call    forcedeth_udelay        ; delay on ESI
  1651.         pop     esi
  1652.         sub     esi, ebx                ; delay -= sleep
  1653.         jmp     .loop
  1654.  
  1655. .return:
  1656.         pop     ebx
  1657.         ret
  1658.  
  1659.  
  1660. ; Input:  none
  1661. ; Output: none
  1662. forcedeth_drop_rx:
  1663.  
  1664.         push    eax ebx ecx edi
  1665.  
  1666.         ; events = readl(base + NvRegIrqStatus)
  1667.         mov     edi, dword [forcedeth_mapio_addr]
  1668.         mov     eax, dword [edi+NvRegIrqStatus]
  1669.  
  1670.         test    eax, eax
  1671.         jz      @f
  1672.         ; writel(events, base + NvRegIrqStatus)
  1673.         mov     dword [edi+NvRegIrqStatus], eax
  1674. @@:
  1675.         ;if (!(events & (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF)))
  1676.         test    eax, (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF)
  1677.         jz      .return
  1678.        
  1679. .loop:  
  1680.         ; i = np->cur_rx % RX_RING
  1681.         mov     eax, dword [forcedeth_cur_rx]
  1682.         and     eax, (RX_RING-1)
  1683.         ; //Flags = le32_to_cpu(rx_ring[i].FlagLen)
  1684.         ; Flags = rx_ring[i].FlagLen
  1685.         mov     cl, sizeof.forcedeth_RxDesc
  1686.         mul     cl
  1687.         add     eax, forcedeth_rx_ring
  1688.         mov     ebx, eax
  1689.         mov     eax, [ebx + forcedeth_RxDesc.FlagLen]
  1690.         ; len = nv_descr_getlength(&rx_ring[i], np->desc_ver)
  1691.         ; > len = Flags & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2)
  1692.         ; ??? len don't used later !!! ???
  1693.         ; ...
  1694.         test    eax, NV_RX_AVAIL
  1695.         jnz     .return         ; still owned by hardware,
  1696.         ; wmb()
  1697.         ; ??? may be empty function ???
  1698.         ; np->cur_rx++
  1699.         inc     dword [forcedeth_cur_rx]
  1700.         ; alloc_rx(NULL)
  1701.         call    forcedeth_alloc_rx
  1702. .return:        
  1703.         pop     edi ecx ebx eax
  1704.         ret
  1705.  
  1706.  
  1707. ; Fill rx ring entries.
  1708. ; Return 1 if the allocations for the skbs failed and the
  1709. ; rx engine is without Available descriptors
  1710. ; Input:  none
  1711. ; Output: none
  1712. forcedeth_alloc_rx:
  1713.  
  1714.         push    eax ebx ecx edx
  1715.         ; refill_rx = np->refill_rx
  1716.         mov     ecx, dword [forcedeth_refill_rx]
  1717. .loop:
  1718.         cmp     dword [forcedeth_cur_rx], ecx
  1719.         je      .loop_end
  1720.         ; nr = refill_rx % RX_RING
  1721.         mov     eax, ecx
  1722.         and     eax, (RX_RING-1)        ; nr
  1723.         ; rx_ring[nr].PacketBuffer = &rxb[nr * RX_NIC_BUFSIZE]
  1724.         push    ecx
  1725.         push    eax
  1726.         mov     cl, sizeof.forcedeth_RxDesc
  1727.         mul     cl
  1728.         add     eax, forcedeth_rx_ring
  1729.         mov     ebx, eax
  1730.         pop     eax
  1731.         mov     cx, RX_NIC_BUFSIZE
  1732.         mul     cx
  1733.         pop     ecx
  1734.         add     eax, forcedeth_rxb
  1735.         sub     eax, OS_BASE    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1736.         mov     [ebx + forcedeth_RxDesc.PacketBuffer], eax
  1737.         ; wmb()
  1738.         ; ...
  1739.         ; rx_ring[nr].FlagLen = RX_NIC_BUFSIZE | NV_RX_AVAIL
  1740.         mov     [ebx + forcedeth_RxDesc.FlagLen], (RX_NIC_BUFSIZE or NV_RX_AVAIL)
  1741.         inc     ecx
  1742.         jmp     .loop
  1743.        
  1744. .loop_end:
  1745.         ; np->refill_rx = refill_rx
  1746.         mov     [forcedeth_refill_rx], ecx
  1747. .return:
  1748.         pop     edx ecx ebx eax
  1749.         ret
  1750.  
  1751.  
  1752. ; Delay in millisec
  1753. ; Input:  ESI - delay in ms
  1754. ; Output: none
  1755. forcedeth_udelay:
  1756.         call    delay_ms
  1757.         ret
  1758.  
  1759. ; Input:  offset:word, mask:dword, target:dword, delay:word, delaymax:word, msg:dword
  1760. ; Output: EAX - 0|1
  1761. ;;;;proc        forcedeth_reg_delay,offset:word,mask:dword,target:dword,delay:word,delaymax:word,msg:dword
  1762. proc    forcedeth_reg_delay,offset:dword,mask:dword,target:dword,delay:dword,delaymax:dword,msg:dword
  1763.  
  1764.         push    ebx esi edi
  1765.         ; pci_push(base)
  1766.         call    forcedeth_pci_push
  1767. .loop:
  1768.         ; nv_udelay(delay)
  1769.         mov     esi, dword [delay]
  1770.         call    forcedeth_nv_udelay     ; delay in esi
  1771.         mov     eax, dword [delaymax]
  1772.         sub     eax, dword [delay]
  1773.         mov     dword [delaymax], eax
  1774.         ; if (delaymax < 0)
  1775.         test    dword [delaymax], 0x80000000
  1776.         jz      @f
  1777.         ; return 1
  1778.         mov     eax, 1
  1779.         jmp     .return
  1780. @@:
  1781.         ; while ((readl(base + offset) & mask) != target)
  1782.         mov     edi, dword [forcedeth_mapio_addr]
  1783.         mov     ebx, dword [offset]
  1784.         mov     eax, dword [edi+ebx]
  1785.         and     eax, dword [mask]
  1786.         cmp     eax, dword [target]
  1787.         jne     .loop
  1788.         xor     eax, eax
  1789. .return:
  1790.         pop     edi esi ebx
  1791.         ret
  1792. endp
  1793.  
  1794.  
  1795. ; Input:  none
  1796. ; Output: none
  1797. forcedeth_pci_push:
  1798.         push    eax edi
  1799.         ;force out pending posted writes
  1800.         mov     edi, dword [forcedeth_mapio_addr]
  1801.         mov     eax, dword [edi]
  1802.         pop     edi eax
  1803.         ret
  1804.  
  1805.  
  1806. ; Input:  none
  1807. ; Output: EAX - result (0 = OK, other = error)
  1808. forcedeth_phy_init:
  1809.  
  1810.         push    ebx ecx
  1811.        
  1812.         ; set advertise register
  1813.         ; reg = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ);
  1814.         ; EBX - addr, EAX - miireg, ECX - value
  1815.         mov     ebx, dword [forcedeth_phyaddr]
  1816.         mov     eax, MII_ADVERTISE
  1817.         mov     ecx, MII_READ
  1818.         call    forcedeth_mii_rw        ; reg = eax
  1819.  
  1820.         ; reg |=
  1821.         ; (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF |
  1822.         ;  ADVERTISE_100FULL | 0x800 | 0x400);
  1823.         or      eax, (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or 0x800 or 0x400)
  1824.  
  1825.         ; if (mii_rw(nic, np->phyaddr, MII_ADVERTISE, reg))
  1826.         ; EBX - addr, EAX - miireg, ECX - value
  1827.         mov     ecx, eax        ; reg
  1828.         mov     eax, MII_ADVERTISE
  1829.         call    forcedeth_mii_rw        ; eax -> return
  1830.  
  1831.         test    eax, eax
  1832.         jz      @f
  1833.         ; printf("phy write to advertise failed.\n");
  1834.         DEBUGF 1," K : FORCEDETH: phy write to advertise failed.\n"
  1835.  
  1836.         ; return PHY_ERROR;
  1837.         mov     eax, PHY_ERROR
  1838.         jmp     .return
  1839. @@:
  1840.         ; get phy interface type
  1841.         ; phyinterface = readl(base + NvRegPhyInterface);
  1842.         mov     edi, dword [forcedeth_mapio_addr]
  1843.         mov     eax, dword [edi+NvRegPhyInterface]      ; phyinterface = eax
  1844.         mov     dword [forcedeth_tmp_phyinterface], eax
  1845.  
  1846. ;;;;;;;;;;;;;;;;;;;;;;;;;
  1847. DEBUGF 1," K : FORCEDETH: phy interface type = 0x%x\n", [forcedeth_tmp_phyinterface]:8
  1848. ;;;;;;;;;;;;;;;;;;;;;;;;;
  1849.  
  1850.         ; see if gigabit phy
  1851.         ; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
  1852.         ; EBX - addr, EAX - miireg, ECX - value
  1853.         mov     eax, MII_BMSR
  1854.         mov     ecx, MII_READ
  1855.         call    forcedeth_mii_rw        ; mii_status = eax
  1856.        
  1857.         ; if (mii_status & PHY_GIGABIT)
  1858.         test    eax, PHY_GIGABIT
  1859.         jnz     .gigabit
  1860.         ; np->gigabit = 0;
  1861.         mov     dword [forcedeth_gigabit], 0
  1862.         jmp     .next_if
  1863.  
  1864. .gigabit:
  1865.         ; np->gigabit = PHY_GIGABIT;
  1866.         mov     dword [forcedeth_gigabit], PHY_GIGABIT
  1867.  
  1868.         ; mii_control_1000 =  mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ);
  1869.         ; EBX - addr, EAX - miireg, ECX - value
  1870.         mov     eax, MII_1000BT_CR
  1871.         mov     ecx, MII_READ
  1872.         call    forcedeth_mii_rw        ; mii_control_1000 = eax
  1873.        
  1874.         ; mii_control_1000 &= ~ADVERTISE_1000HALF;
  1875.         and     eax, (not ADVERTISE_1000HALF)
  1876.  
  1877.         ; if (phyinterface & PHY_RGMII)
  1878.         test    dword [forcedeth_tmp_phyinterface], PHY_RGMII
  1879.         jz      @f
  1880.         ; mii_control_1000 |= ADVERTISE_1000FULL
  1881.         or      eax, ADVERTISE_1000FULL
  1882.         jmp     .next
  1883. @@:
  1884.         ; mii_control_1000 &= ~ADVERTISE_1000FULL
  1885.         and     eax, (not ADVERTISE_1000FULL)
  1886.  
  1887. .next:
  1888.         ; if (mii_rw(nic, np->phyaddr, MII_1000BT_CR, mii_control_1000))
  1889.         ; EBX - addr, EAX - miireg, ECX - value
  1890.         mov     ecx, eax
  1891.         mov     eax, MII_1000BT_CR
  1892.         call    forcedeth_mii_rw        ; eax -> return
  1893.  
  1894.         test    eax, eax
  1895.         jz      .next_if
  1896.  
  1897.         ; printf("phy init failed.\n");
  1898.         DEBUGF 1," K : FORCEDETH: phy init failed.\n"
  1899.  
  1900.         ; return PHY_ERROR;
  1901.         mov     eax, PHY_ERROR
  1902.         jmp     .return
  1903.  
  1904. .next_if:
  1905.  
  1906.         ; reset the phy
  1907.         ; if (phy_reset(nic))
  1908.         call    forcedeth_phy_reset
  1909.         test    eax, eax
  1910.         jz      @f
  1911.         ; printf("phy reset failed\n")
  1912.         DEBUGF 1," K : FORCEDETH: phy reset failed.\n"
  1913.         ; return PHY_ERROR
  1914.         mov     eax, PHY_ERROR
  1915.         jmp     .return
  1916. @@:
  1917.  
  1918.         ; phy vendor specific configuration
  1919.         ; if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII))
  1920.         cmp     dword [forcedeth_phy_oui], PHY_OUI_CICADA
  1921.         jne     .next_if2
  1922.         test    dword [forcedeth_tmp_phyinterface], PHY_RGMII
  1923.         jz      .next_if2
  1924.  
  1925.         ; phy_reserved = mii_rw(nic, np->phyaddr, MII_RESV1, MII_READ)
  1926.         ; EBX - addr, EAX - miireg, ECX - value
  1927.         mov     eax, MII_RESV1
  1928.         mov     ecx, MII_READ
  1929.         call    forcedeth_mii_rw        ; phy_reserved = eax
  1930.        
  1931.         ; phy_reserved &= ~(PHY_INIT1 | PHY_INIT2)
  1932.         and     eax, (not (PHY_INIT1 or PHY_INIT2))
  1933.         ; phy_reserved |= (PHY_INIT3 | PHY_INIT4)
  1934.         or      eax, (PHY_INIT3 or PHY_INIT4)
  1935.        
  1936.         ; if (mii_rw(nic, np->phyaddr, MII_RESV1, phy_reserved))
  1937.         ; EBX - addr, EAX - miireg, ECX - value
  1938.         mov     ecx, eax
  1939.         mov     eax, MII_RESV1
  1940.         call    forcedeth_mii_rw        ; eax -> return
  1941.         test    eax, eax
  1942.         jz      @f
  1943.         ; printf("phy init failed.\n")
  1944.         DEBUGF 1," K : FORCEDETH: phy init failed.\n"
  1945.         ; return PHY_ERROR
  1946.         mov     eax, PHY_ERROR
  1947.         jmp     .return
  1948. @@:
  1949.         ; phy_reserved = mii_rw(nic, np->phyaddr, MII_NCONFIG, MII_READ);
  1950.         ; EBX - addr, EAX - miireg, ECX - value
  1951.         mov     eax, MII_NCONFIG
  1952.         mov     ecx, MII_READ
  1953.         call    forcedeth_mii_rw        ; phy_reserved = eax
  1954.  
  1955.         ; phy_reserved |= PHY_INIT5
  1956.         or      eax, PHY_INIT5
  1957.        
  1958.         ; if (mii_rw(nic, np->phyaddr, MII_NCONFIG, phy_reserved))
  1959.         ; EBX - addr, EAX - miireg, ECX - value
  1960.         mov     ecx, eax
  1961.         mov     eax, MII_NCONFIG
  1962.         call    forcedeth_mii_rw        ; eax -> return
  1963.         test    eax, eax
  1964.         jz      .next_if2
  1965.         ; printf("phy init failed.\n")
  1966.         DEBUGF 1," K : FORCEDETH: phy init failed.\n"
  1967.         ; return PHY_ERROR
  1968.         mov     eax, PHY_ERROR
  1969.         jmp     .return
  1970.  
  1971. .next_if2:
  1972.  
  1973.         ; if (np->phy_oui == PHY_OUI_CICADA)
  1974.         cmp     dword [forcedeth_phy_oui], PHY_OUI_CICADA
  1975.         jne     .restart
  1976.        
  1977.         ; phy_reserved = mii_rw(nic, np->phyaddr, MII_SREVISION, MII_READ)
  1978.         ; EBX - addr, EAX - miireg, ECX - value
  1979.         mov     eax, MII_SREVISION
  1980.         mov     ecx, MII_READ
  1981.         call    forcedeth_mii_rw        ; phy_reserved = eax
  1982.        
  1983.         ; phy_reserved |= PHY_INIT6
  1984.         or      eax, PHY_INIT6
  1985.        
  1986.         ; if (mii_rw(nic, np->phyaddr, MII_SREVISION, phy_reserved))
  1987.         mov     ecx, eax
  1988.         mov     eax, MII_SREVISION
  1989.         call    forcedeth_mii_rw        ; eax -> return
  1990.         test    eax, eax
  1991.         jz      .restart
  1992.         ; printf("phy init failed.\n");
  1993.         DEBUGF 1," K : FORCEDETH: phy init failed.\n"
  1994.         ; return PHY_ERROR;
  1995.         jmp     .return
  1996.  
  1997. .restart:
  1998.         ; restart auto negotiation
  1999.         ; mii_control = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ)
  2000.         ; EBX - addr, EAX - miireg, ECX - value
  2001.         mov     eax, MII_BMCR
  2002.         mov     ecx, MII_READ
  2003.         call    forcedeth_mii_rw        ; mii_control = eax
  2004.  
  2005.         ; mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE)
  2006.         or      eax, (BMCR_ANRESTART or BMCR_ANENABLE)
  2007.        
  2008.         ; if (mii_rw(nic, np->phyaddr, MII_BMCR, mii_control))
  2009.         mov     ecx, eax
  2010.         mov     eax, MII_BMCR
  2011.         call    forcedeth_mii_rw        ; eax -> return
  2012.         test    eax, eax
  2013.         jz      .ok
  2014.  
  2015.         ; return PHY_ERROR;
  2016.         mov     eax, PHY_ERROR
  2017.         jmp     .return
  2018.  
  2019. .ok:
  2020.         mov     eax, 0
  2021. .return:
  2022.         pop     ecx ebx
  2023.         ret
  2024.  
  2025.  
  2026. ; Input:  none
  2027. ; Output: EAX - result (0 = OK, other = error)
  2028. forcedeth_phy_reset:
  2029.  
  2030.         push    ebx ecx edx
  2031.  
  2032.         ; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ);
  2033.         ; EBX - addr, EAX - miireg, ECX - value
  2034.         mov     ebx, dword [forcedeth_phyaddr]
  2035.         mov     eax, MII_BMCR
  2036.         mov     ecx, MII_READ
  2037.         call    forcedeth_mii_rw        ; miicontrol = eax
  2038.  
  2039.         ; miicontrol |= BMCR_RESET;
  2040.         or      eax, BMCR_RESET
  2041.         push    eax
  2042.  
  2043.         ; if (mii_rw(nic, np->phyaddr, MII_BMCR, miicontrol))
  2044.         ; EBX - addr, EAX - miireg, ECX - value
  2045.         mov     ecx, eax
  2046.         mov     eax, MII_BMCR
  2047.         call    forcedeth_mii_rw        ; miicontrol = eax
  2048.  
  2049.         test    eax, eax
  2050.         jz      @f
  2051.         pop     eax
  2052.         mov     eax, 0xffffffff
  2053.         jmp     .return
  2054. @@:
  2055.         pop     eax
  2056.  
  2057.         ; wait for 500ms
  2058.         ; mdelay(500)
  2059.         mov     esi, 500
  2060.         call    forcedeth_udelay
  2061.  
  2062.         ; must wait till reset is deasserted
  2063.         ; while (miicontrol & BMCR_RESET) {
  2064.         mov     edx, 100
  2065. .while_loop:
  2066.         test    eax, BMCR_RESET
  2067.         jz      .while_loop_exit
  2068.  
  2069.         ; mdelay(10);
  2070.         mov     esi, 10
  2071.         call    forcedeth_udelay
  2072.  
  2073.         ; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ);
  2074.         ; EBX - addr, EAX - miireg, ECX - value
  2075.         mov     eax, MII_BMCR
  2076.         mov     ecx, MII_READ
  2077.         call    forcedeth_mii_rw        ; miicontrol = eax
  2078.  
  2079.         ; FIXME: 100 tries seem excessive
  2080.         ; if (tries++ > 100)
  2081.         dec     edx
  2082.         jnz     .while_loop
  2083.         ; return -1;
  2084.         mov     eax, 0xffffffff
  2085.         jmp     .return
  2086. .while_loop_exit:
  2087.         ; return 0
  2088.         mov     eax, 0
  2089. .return:        
  2090.         pop     edx ecx ebx
  2091.         ret
  2092.  
  2093. ; Input:  none
  2094. ; Output: none
  2095. forcedeth_mac_reset:
  2096.         push    esi edi
  2097.  
  2098.         ; dprintf("mac_reset\n")
  2099.         DEBUGF 1," K : FORCEDETH: mac_reset.\n"
  2100.  
  2101.         ; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl)
  2102.         mov     edi, dword [forcedeth_mapio_addr]
  2103.         mov     eax, dword [forcedeth_desc_ver]
  2104.         or      eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET)
  2105.         mov     dword [edi+NvRegTxRxControl], eax
  2106.  
  2107.         ; pci_push(base)
  2108.         call    forcedeth_pci_push
  2109.        
  2110.         ; writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset)
  2111.         mov     dword [edi+NvRegMacReset], NVREG_MAC_RESET_ASSERT
  2112.  
  2113.         ; pci_push(base)
  2114.         call    forcedeth_pci_push
  2115.  
  2116.         ; udelay(NV_MAC_RESET_DELAY)
  2117.         mov     esi, NV_MAC_RESET_DELAY
  2118.         call    forcedeth_nv_udelay
  2119.  
  2120.         ; writel(0, base + NvRegMacReset)
  2121.         mov     dword [edi+NvRegMacReset], 0
  2122.  
  2123.         ; pci_push(base)
  2124.         call    forcedeth_pci_push
  2125.        
  2126.         ; udelay(NV_MAC_RESET_DELAY)
  2127.         mov     esi, NV_MAC_RESET_DELAY
  2128.         call    forcedeth_nv_udelay
  2129.  
  2130.         ; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl)
  2131.         mov     eax, dword [forcedeth_desc_ver]
  2132.         or      eax, NVREG_TXRXCTL_BIT2
  2133.         mov     dword [edi+NvRegTxRxControl], eax
  2134.        
  2135.         ; pci_push(base)
  2136.         call    forcedeth_pci_push
  2137.  
  2138.         pop     edi esi
  2139.         ret
  2140.  
  2141. ; Input:  none
  2142. ; Output: none
  2143. forcedeth_init_ring:
  2144.         push    eax ebx ecx
  2145.  
  2146.         ; np->next_tx = np->nic_tx = 0
  2147.         mov     dword[forcedeth_next_tx], 0
  2148.         mov     dword[forcedeth_nic_tx], 0
  2149.  
  2150.         ; for (i = 0; i < TX_RING; i++)
  2151.         mov     ecx, TX_RING
  2152.  
  2153. .for_loop:
  2154.         ;        tx_ring[i].FlagLen = 0;
  2155.         mov     eax, ecx
  2156.         dec     eax
  2157.         mov     bl, sizeof.forcedeth_TxDesc
  2158.         mul     bl
  2159.         add     eax, forcedeth_tx_ring
  2160.         mov     ebx, eax
  2161.         mov     dword [ebx + forcedeth_TxDesc.FlagLen], 0
  2162.         loop    .for_loop
  2163.  
  2164.         ; np->cur_rx = RX_RING;
  2165.         mov     dword [forcedeth_cur_rx], RX_RING
  2166.         ; np->refill_rx = 0;
  2167.         mov     dword [forcedeth_refill_rx], 0
  2168.        
  2169.         ;for (i = 0; i < RX_RING; i++)
  2170.         mov     ecx, RX_RING
  2171.  
  2172. .for_loop2:
  2173.         ;        rx_ring[i].FlagLen = 0;
  2174.         mov     eax, ecx
  2175.         dec     eax
  2176.         mov     bl, sizeof.forcedeth_RxDesc
  2177.         mul     bl
  2178.         add     eax, forcedeth_rx_ring
  2179.         mov     ebx, eax
  2180.         mov     dword [ebx + forcedeth_RxDesc.FlagLen], 0
  2181.         loop    .for_loop2
  2182.        
  2183.         ; alloc_rx(nic);
  2184.         call    forcedeth_alloc_rx
  2185.  
  2186. .return:
  2187.         pop     ecx ebx eax
  2188.         ret
  2189.  
  2190. ; Input:  none
  2191. ; Output: none
  2192. forcedeth_txrx_reset:
  2193.         push    eax esi edi
  2194.  
  2195.         ; dprintf(("txrx_reset\n"))
  2196.         DEBUGF 1," K : FORCEDETH: txrx_reset.\n"
  2197.  
  2198.         ; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl)
  2199.         mov     edi, dword [forcedeth_mapio_addr]
  2200.         mov     eax, dword [forcedeth_desc_ver]
  2201.         or      eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET)
  2202.         mov     dword [edi+NvRegTxRxControl], eax
  2203.  
  2204.         ; pci_push(base)
  2205.         call    forcedeth_pci_push
  2206.  
  2207.         ; nv_udelay(NV_TXRX_RESET_DELAY)
  2208.         mov     esi, NV_TXRX_RESET_DELAY
  2209.         call    forcedeth_nv_udelay
  2210.  
  2211.         ; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl)
  2212.         mov     eax, dword [forcedeth_desc_ver]
  2213.         or      eax, NVREG_TXRXCTL_BIT2
  2214.         mov     dword [edi+NvRegTxRxControl], eax
  2215.        
  2216.         ; pci_push(base)
  2217.         call    forcedeth_pci_push
  2218.  
  2219. .return:
  2220.         pop     edi esi eax
  2221.         ret
  2222.  
  2223. ; Input:  none
  2224. ; Output: none
  2225. forcedeth_set_multicast:
  2226.         push    edi
  2227.  
  2228.         ; u32 addr[2];
  2229.         ; u32 mask[2];
  2230.         ; u32 pff;
  2231.         ; u32 alwaysOff[2];
  2232.         ; u32 alwaysOn[2];
  2233.         ;
  2234.         ; memset(addr, 0, sizeof(addr));
  2235.         ; memset(mask, 0, sizeof(mask));
  2236.         ;
  2237.         ; pff = NVREG_PFF_MYADDR;
  2238.         ;
  2239.         ; alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0;
  2240.         ;
  2241.         ; addr[0] = alwaysOn[0];
  2242.         ; addr[1] = alwaysOn[1];
  2243.         ; mask[0] = alwaysOn[0] | alwaysOff[0];
  2244.         ; mask[1] = alwaysOn[1] | alwaysOff[1];
  2245.         ;
  2246.         ; addr[0] |= NVREG_MCASTADDRA_FORCE;
  2247.         ; pff |= NVREG_PFF_ALWAYS;
  2248.         ; stop_rx();
  2249.         call    forcedeth_stop_rx
  2250.         ; writel(addr[0], base + NvRegMulticastAddrA);
  2251.         mov     edi, dword [forcedeth_mapio_addr]
  2252.         mov     dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE
  2253.         ; writel(addr[1], base + NvRegMulticastAddrB);
  2254.         mov     dword [edi+NvRegMulticastAddrB], 0
  2255.         ; writel(mask[0], base + NvRegMulticastMaskA);
  2256.         mov     dword [edi+NvRegMulticastMaskA], 0
  2257.         ; writel(mask[1], base + NvRegMulticastMaskB);
  2258.         mov     dword [edi+NvRegMulticastMaskB], 0
  2259.         ; writel(pff, base + NvRegPacketFilterFlags);
  2260.         mov     dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_MYADDR or NVREG_PFF_ALWAYS)
  2261.         ; start_rx(nic);
  2262.         call    forcedeth_start_rx
  2263.  
  2264. .return:
  2265.         pop     edi
  2266.         ret
  2267.  
  2268. ; Input:  none
  2269. ; Output: none
  2270. forcedeth_start_rx:
  2271.         push    edi
  2272.  
  2273.         ; dprintf(("start_rx\n"))
  2274.         DEBUGF 1," K : FORCEDETH: start_rx.\n"
  2275.  
  2276.         ; Already running? Stop it.
  2277.         ; if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) {
  2278.         mov     edi, dword [forcedeth_mapio_addr]
  2279.         mov     eax, dword [edi+NvRegReceiverControl]
  2280.         test    eax, NVREG_RCVCTL_START
  2281.         jz      @f
  2282.         ; writel(0, base + NvRegReceiverControl)
  2283.         mov     dword [edi+NvRegReceiverControl], 0
  2284.         ; pci_push(base)
  2285.         call    forcedeth_pci_push
  2286.  
  2287. @@:
  2288.        
  2289.         ; writel(np->linkspeed, base + NvRegLinkSpeed);
  2290.         mov     eax, dword [forcedeth_linkspeed]
  2291.         mov     dword [edi+NvRegLinkSpeed], eax
  2292.         ; pci_push(base);
  2293.         call    forcedeth_pci_push
  2294.         ; writel(NVREG_RCVCTL_START, base + NvRegReceiverControl);
  2295.         mov     dword [edi+NvRegReceiverControl], NVREG_RCVCTL_START
  2296.         ; pci_push(base);
  2297.         call    forcedeth_pci_push
  2298.  
  2299. .return:
  2300.         pop     edi
  2301.         ret
  2302.  
  2303. ; Input:  none
  2304. ; Output: none
  2305. forcedeth_stop_rx:
  2306.         push    esi edi
  2307.  
  2308.         ; dprintf(("stop_rx\n"))
  2309.         DEBUGF 1," K : FORCEDETH: stop_rx.\n"
  2310.  
  2311.         ; writel(0, base + NvRegReceiverControl)
  2312.         mov     edi, dword [forcedeth_mapio_addr]
  2313.         mov     dword [edi+NvRegReceiverControl], 0
  2314.  
  2315.         push    ebx edx edi     ;;;;;;;;;;;;;;;;;;;;;;
  2316.         ; reg_delay(NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, "stop_rx: ReceiverStatus remained busy");
  2317.         stdcall forcedeth_reg_delay, NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, 0
  2318.         pop     edi edx ebx     ;;;;;;;;;;;;;;;;;;;;;;
  2319.  
  2320.  
  2321.         ; nv_udelay(NV_RXSTOP_DELAY2)
  2322.         mov     esi, NV_RXSTOP_DELAY2
  2323.         call    forcedeth_nv_udelay
  2324.  
  2325.         ; writel(0, base + NvRegLinkSpeed)
  2326.         mov     dword [edi+NvRegLinkSpeed], 0
  2327.  
  2328. .return:
  2329.         pop     edi esi
  2330.         ret
  2331.  
  2332. ; Input:  none
  2333. ; Output: EAX
  2334. forcedeth_update_linkspeed:
  2335.         push    ebx ecx esi edi
  2336.  
  2337.         ; BMSR_LSTATUS is latched, read it twice:
  2338.         ; we want the current value.
  2339.        
  2340.         ; mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ)
  2341.         ;EBX - addr, EAX - miireg, ECX - value
  2342.         mov     ebx, dword [forcedeth_phyaddr]
  2343.         mov     eax, MII_BMSR
  2344.         mov     ecx, MII_READ
  2345.         call    forcedeth_mii_rw
  2346.  
  2347.  
  2348.         ; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ)
  2349.         ;EBX - addr, EAX - miireg, ECX - value
  2350.         mov     ebx, dword [forcedeth_phyaddr]
  2351.         mov     eax, MII_BMSR
  2352.         mov     ecx, MII_READ
  2353.         call    forcedeth_mii_rw        ; mii_status = eax
  2354.        
  2355.         ; yhlu
  2356.  
  2357.         ; for(i=0;i<30;i++) {
  2358.         mov     ecx, 30
  2359. .for_loop:
  2360.         push    ecx
  2361.  
  2362.         ;  mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
  2363.         ;EBX - addr, EAX - miireg, ECX - value
  2364.         ;mov    ebx, dword [forcedeth_phyaddr]
  2365.         mov     eax, MII_BMSR
  2366.         mov     ecx, MII_READ
  2367.         call    forcedeth_mii_rw        ; mii_status = eax
  2368.  
  2369.         ;  if((mii_status & BMSR_LSTATUS) && (mii_status & BMSR_ANEGCOMPLETE)) break;
  2370.         test    eax, BMSR_LSTATUS
  2371.         jz      @f
  2372.         test    eax, BMSR_ANEGCOMPLETE
  2373.         jz      @f
  2374.         ; break
  2375.         pop     ecx
  2376.         jmp     .break
  2377.        
  2378. @@:
  2379.  
  2380.         ;  mdelay(100);
  2381.         push    eax     ; ???
  2382.         mov     esi, 100
  2383.         call    forcedeth_udelay
  2384.         pop     eax     ; ???
  2385.  
  2386.         pop     ecx
  2387.         loop    .for_loop
  2388.  
  2389. .break:
  2390.  
  2391.         ; if (!(mii_status & BMSR_LSTATUS)) {
  2392.         test    eax, BMSR_LSTATUS
  2393.         jnz     @f
  2394.  
  2395.         ; printf("no link detected by phy - falling back to 10HD.\n")
  2396.         DEBUGF 1," K : FORCEDETH: update_linkspeed: no link detected by phy - falling back to 10HD.\n"
  2397.  
  2398.         ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
  2399.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
  2400.  
  2401.         ; newdup = 0;
  2402.         mov     dword [forcedeth_tmp_newdup], 0
  2403.         ; retval = 0;
  2404.         mov     dword [forcedeth_tmp_retval], 0
  2405.  
  2406.         ; goto set_speed;
  2407.         jmp     .set_speed
  2408.  
  2409. @@:
  2410.  
  2411.         ; check auto negotiation is complete
  2412.         ; if (!(mii_status & BMSR_ANEGCOMPLETE)) {
  2413.         test    eax, BMSR_ANEGCOMPLETE
  2414.         jnz     @f
  2415.  
  2416.         ; still in autonegotiation - configure nic for 10 MBit HD and wait.
  2417.         ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
  2418.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
  2419.  
  2420.         ; newdup = 0
  2421.         mov     dword [forcedeth_tmp_newdup], 0
  2422.  
  2423.         ; retval = 0
  2424.         mov     dword [forcedeth_tmp_retval], 0
  2425.  
  2426.         ; printf("autoneg not completed - falling back to 10HD.\n")
  2427.         DEBUGF 1," K : FORCEDETH: update_linkspeed: autoneg not completed - falling back to 10HD.\n"
  2428.  
  2429.         ; goto set_speed
  2430.         jmp     .set_speed
  2431.  
  2432. @@:
  2433.  
  2434.         ; retval = 1
  2435.         mov     dword [forcedeth_tmp_retval], 1
  2436.        
  2437.         ; if (np->gigabit == PHY_GIGABIT) {
  2438.         cmp     dword [forcedeth_gigabit], PHY_GIGABIT
  2439.         jne     .end_if
  2440.         ; control_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ)
  2441.         ;EBX - addr, EAX - miireg, ECX - value
  2442.         ;mov    ebx, dword [forcedeth_phyaddr]
  2443.         mov     eax, MII_1000BT_CR
  2444.         mov     ecx, MII_READ
  2445.         call    forcedeth_mii_rw        ; control_1000 = eax
  2446.         mov     dword [forcedeth_tmp_control_1000], eax
  2447.        
  2448.         ; status_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_SR, MII_READ)
  2449.         ;EBX - addr, EAX - miireg, ECX - value
  2450.         ;mov    ebx, dword [forcedeth_phyaddr]
  2451.         mov     eax, MII_1000BT_SR
  2452.         mov     ecx, MII_READ
  2453.         call    forcedeth_mii_rw        ; status_1000 = eax
  2454.         ;mov    dword [forcedeth_tmp_status_1000], eax
  2455.        
  2456.         ; if ((control_1000 & ADVERTISE_1000FULL) &&
  2457.         ;     (status_1000 & LPA_1000FULL)) {
  2458.         test    eax, LPA_1000FULL
  2459.         jz      .end_if
  2460.         test    dword [forcedeth_tmp_control_1000], ADVERTISE_1000FULL
  2461.         jz      .end_if
  2462.  
  2463.         ; printf ("update_linkspeed: GBit ethernet detected.\n")
  2464.         DEBUGF 1," K : FORCEDETH: update_linkspeed: GBit ethernet detected.\n"
  2465.  
  2466.         ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_1000
  2467.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_1000)
  2468.  
  2469.         ; newdup = 1
  2470.         mov     dword [forcedeth_tmp_newdup], 1
  2471.  
  2472.         ; goto set_speed
  2473.         jmp     .set_speed
  2474.  
  2475. .end_if:
  2476.  
  2477.         ; adv = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ);
  2478.         ;EBX - addr, EAX - miireg, ECX - value
  2479.         ;mov    ebx, dword [forcedeth_phyaddr]
  2480.         mov     eax, MII_ADVERTISE
  2481.         mov     ecx, MII_READ
  2482.         call    forcedeth_mii_rw        ; adv = eax
  2483.         mov     dword [forcedeth_tmp_adv], eax
  2484.  
  2485.         ; lpa = mii_rw(nic, np->phyaddr, MII_LPA, MII_READ);
  2486.         ;EBX - addr, EAX - miireg, ECX - value
  2487.         ;mov    ebx, dword [forcedeth_phyaddr]
  2488.         mov     eax, MII_LPA
  2489.         mov     ecx, MII_READ
  2490.         call    forcedeth_mii_rw        ; lpa = eax
  2491.         mov     dword [forcedeth_tmp_lpa], eax
  2492.  
  2493.         ; dprintf(("update_linkspeed: PHY advertises 0x%hX, lpa 0x%hX.\n", adv, lpa));
  2494.         DEBUGF 1," K : FORCEDETH: update_linkspeed: PHY advertises 0x%x, lpa 0x%x.\n", [forcedeth_tmp_adv]:8, [forcedeth_tmp_lpa]:8
  2495.  
  2496.         ; FIXME: handle parallel detection properly, handle gigabit ethernet
  2497.         ; lpa = lpa & adv
  2498.         mov     eax, dword [forcedeth_tmp_adv]
  2499.         and     dword [forcedeth_tmp_lpa], eax
  2500.  
  2501.         mov     eax, dword [forcedeth_tmp_lpa]
  2502.  
  2503.         ; if (lpa & LPA_100FULL) {
  2504.         test    eax, LPA_100FULL
  2505.         jz      @f
  2506.         ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100
  2507.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100)
  2508.         ; newdup = 1
  2509.         mov     dword [forcedeth_tmp_newdup], 1
  2510.         jmp     .set_speed
  2511. @@:
  2512.         ; } else if (lpa & LPA_100HALF) {
  2513.         test    eax, LPA_100HALF
  2514.         jz      @f
  2515.         ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100
  2516.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100)
  2517.         ; newdup = 0
  2518.         mov     dword [forcedeth_tmp_newdup], 0
  2519.         jmp     .set_speed
  2520. @@:
  2521.         ; } else if (lpa & LPA_10FULL) {
  2522.         test    eax, LPA_10FULL
  2523.         jz      @f
  2524.         ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
  2525.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
  2526.         ; newdup = 1
  2527.         mov     dword [forcedeth_tmp_newdup], 1
  2528.         jmp     .set_speed
  2529. @@:
  2530.         ; } else if (lpa & LPA_10HALF) {
  2531.         test    eax, LPA_10HALF
  2532.         ;    newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
  2533.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
  2534.         ;    newdup = 0;
  2535.         mov     dword [forcedeth_tmp_newdup], 0
  2536.         jmp     .set_speed
  2537. @@:
  2538.         ; } else {
  2539.         ; printf("bad ability %hX - falling back to 10HD.\n", lpa)
  2540.         DEBUGF 1," K : FORCEDETH: update_linkspeed: bad ability 0x%x - falling back to 10HD.\n", eax
  2541.  
  2542.         ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
  2543.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
  2544.         ; newdup = 0
  2545.         mov     dword [forcedeth_tmp_newdup], 0
  2546.         ; }
  2547.  
  2548. .set_speed:
  2549.  
  2550.         ; if (np->duplex == newdup && np->linkspeed == newls)
  2551.         mov     eax, dword [forcedeth_tmp_newdup]
  2552.         cmp     eax, dword [forcedeth_duplex]
  2553.         jne     .end_if2
  2554.         mov     eax, dword [forcedeth_tmp_newls]
  2555.         cmp     eax, dword [forcedeth_linkspeed]
  2556.         jne     .end_if2
  2557.         ;    return retval;
  2558.         jmp     .return
  2559.        
  2560. .end_if2:
  2561.        
  2562.         ; dprintf(("changing link setting from %d/%s to %d/%s.\n",
  2563.         ;    np->linkspeed, np->duplex ? "Full-Duplex": "Half-Duplex", newls, newdup ? "Full-Duplex": "Half-Duplex"))
  2564.         DEBUGF 1," K : FORCEDETH: update_linkspeed: changing link from %x/XD to %x/XD.\n", [forcedeth_linkspeed]:8, [forcedeth_tmp_newls]:8     ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2565.        
  2566.         ; np->duplex = newdup
  2567.         mov     eax, dword [forcedeth_tmp_newdup]
  2568.         mov     dword [forcedeth_duplex], eax
  2569.  
  2570.         ; np->linkspeed = newls
  2571.         mov     eax, [forcedeth_tmp_newls]
  2572.         mov     dword [forcedeth_linkspeed], eax
  2573.        
  2574.         ; if (np->gigabit == PHY_GIGABIT) {
  2575.         cmp     dword [forcedeth_gigabit], PHY_GIGABIT
  2576.         jne     .end_if3
  2577.  
  2578.         ; phyreg = readl(base + NvRegRandomSeed);
  2579.         mov     edi, dword [forcedeth_mapio_addr]
  2580.         mov     eax, dword [edi+NvRegRandomSeed]
  2581.  
  2582.         ; phyreg &= ~(0x3FF00);
  2583.         and     eax, not (0x3FF00)
  2584.         mov     ecx, eax                ; phyreg = ecx
  2585.  
  2586.         ; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10)
  2587.         mov     eax, dword [forcedeth_linkspeed]
  2588.         and     eax, 0xFFF
  2589.         cmp     eax, NVREG_LINKSPEED_10
  2590.         jne     @f
  2591.         ; phyreg |= NVREG_RNDSEED_FORCE3
  2592.         or      ecx, NVREG_RNDSEED_FORCE3
  2593.         jmp     .end_if4
  2594. @@:
  2595.         ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
  2596.         cmp     eax, NVREG_LINKSPEED_100
  2597.         jne     @f
  2598.         ; phyreg |= NVREG_RNDSEED_FORCE2
  2599.         or      ecx, NVREG_RNDSEED_FORCE2
  2600.         jmp     .end_if4
  2601. @@:
  2602.         ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
  2603.         cmp     eax, NVREG_LINKSPEED_1000
  2604.         jne     .end_if4
  2605.         ; phyreg |= NVREG_RNDSEED_FORCE
  2606.         or      ecx, NVREG_RNDSEED_FORCE
  2607. .end_if4:
  2608.         ; writel(phyreg, base + NvRegRandomSeed)
  2609.         mov     dword [edi+NvRegRandomSeed], ecx
  2610.  
  2611. .end_if3:
  2612.        
  2613.         ; phyreg = readl(base + NvRegPhyInterface)
  2614.         mov     ecx, dword [edi+NvRegPhyInterface]
  2615.  
  2616.         ; phyreg &= ~(PHY_HALF | PHY_100 | PHY_1000)
  2617.         and     ecx, not (PHY_HALF or PHY_100 or PHY_1000)
  2618.        
  2619.         ; if (np->duplex == 0)
  2620.         cmp     dword [forcedeth_duplex], 0
  2621.         jne     @f
  2622.         ; phyreg |= PHY_HALF
  2623.         or      ecx, PHY_HALF
  2624. @@:
  2625.         ; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
  2626.         mov     eax, dword [forcedeth_linkspeed]
  2627.         and     eax, 0xFFF
  2628.         cmp     eax, NVREG_LINKSPEED_100
  2629.         jne     @f
  2630.         ; phyreg |= PHY_100
  2631.         or      ecx, PHY_100
  2632.         jmp     .end_if5
  2633. @@:
  2634.         ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
  2635.         cmp     eax, NVREG_LINKSPEED_1000
  2636.         jne     .end_if5
  2637.         ; phyreg |= PHY_1000
  2638.         or      ecx, PHY_1000
  2639.  
  2640. .end_if5:
  2641.  
  2642.         ; writel(phyreg, base + NvRegPhyInterface)
  2643.         mov     dword [edi+NvRegPhyInterface], ecx
  2644.                
  2645.         ; writel(NVREG_MISC1_FORCE | (np->duplex ? 0 : NVREG_MISC1_HD), base + NvRegMisc1);
  2646.         cmp     dword [forcedeth_duplex], 0
  2647.         je      @f
  2648.         mov     ecx, 0
  2649.         jmp     .next
  2650. @@:
  2651.         mov     ecx, NVREG_MISC1_HD
  2652. .next:
  2653.         or      ecx, NVREG_MISC1_FORCE
  2654.         mov     dword [edi+NvRegMisc1], ecx
  2655.  
  2656.         ; pci_push(base)
  2657.         call    forcedeth_pci_push
  2658.  
  2659.         ; writel(np->linkspeed, base + NvRegLinkSpeed)
  2660.         mov     eax, dword [forcedeth_linkspeed]
  2661.         mov     dword [edi+NvRegLinkSpeed], eax
  2662.  
  2663.         ; pci_push(base)
  2664.         call    forcedeth_pci_push
  2665.  
  2666. .return:
  2667.         ; return retval
  2668.         mov     eax, dword [forcedeth_tmp_retval]
  2669.         pop     edi esi ecx ebx
  2670.         ret
  2671.  
  2672.        
  2673. ; Input:  none
  2674. ; Output: none
  2675. forcedeth_start_tx:
  2676.         push    edi
  2677.         ; dprintf(("start_tx\n"))
  2678.         DEBUGF 1," K : FORCEDETH: start_tx.\n"
  2679.  
  2680.         ; writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl)
  2681.         mov     edi, dword [forcedeth_mapio_addr]
  2682.         mov     dword [edi+NvRegTransmitterControl], NVREG_XMITCTL_START
  2683.  
  2684.         ; pci_push(base)
  2685.         call    forcedeth_pci_push
  2686.  
  2687. .return:
  2688.         pop     edi
  2689.         ret
  2690.  
  2691. ; Interrupt handler
  2692. forcedeth_int_handler:
  2693.         DEBUGF 1," K : FORCEDETH: interrupt handler.\n"
  2694.  
  2695.         ret
  2696.        
  2697.