Subversion Repositories Kolibri OS

Rev

Rev 867 | 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: 1194 $
  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. @@:     push    eax
  823.         and     eax, PCI_BASE_ADDRESS_MEM_TYPE_MASK
  824.         cmp     eax, PCI_BASE_ADDRESS_MEM_TYPE_64
  825.         jne     .not64
  826.         mov     al, 2   ; dword
  827.         mov     bh, [pci_dev]
  828.         mov     ah, [pci_bus]
  829.         mov     bl, PCI_BASE_ADDRESS_0 + 4
  830.         call    pci_read_reg
  831.         or      eax, eax
  832.         jz      .not64
  833.         DEBUGF  1,"K : FORCEDETH: pci_bar_start: Unhandled 64bit BAR\n"
  834.         or      eax, -1
  835.         jmp     .next
  836. .not64:
  837.         pop     eax
  838.         and     eax, PCI_BASE_ADDRESS_MEM_MASK
  839. .next:
  840. ; END of pci_bar_start
  841. ; addr = eax
  842.         mov     dword [forcedeth_mmio_addr], eax
  843.  
  844.        
  845. ; BEGIN of pci_bar_size (sz = pci_bar_size(pci, PCI_BASE_ADDRESS_0))
  846.  
  847.         ; Save original bar
  848.         mov     al, 2   ; dword
  849.         mov     bh, [pci_dev]
  850.         mov     ah, [pci_bus]
  851.         mov     bl, PCI_BASE_ADDRESS_0
  852.         call    pci_read_reg
  853.         mov     dword [forcedeth_tmp_start], eax
  854.         ; Compute which bits can be set
  855.         ; (ecx - value to write)
  856.         mov     al, 2   ; dword
  857.         mov     bh, [pci_dev]
  858.         mov     ah, [pci_bus]
  859.         mov     bl, PCI_BASE_ADDRESS_0
  860.         mov     ecx, (not 0)
  861.         call    pci_write_reg
  862.         mov     al, 2   ; dword
  863.         mov     bh, [pci_dev]
  864.         mov     ah, [pci_bus]
  865.         mov     bl, PCI_BASE_ADDRESS_0
  866.         call    pci_read_reg
  867.         push    eax
  868.         ; Restore the original size
  869.         mov     al, 2   ; dword
  870.         mov     bh, [pci_dev]
  871.         mov     ah, [pci_bus]
  872.         mov     bl, PCI_BASE_ADDRESS_0
  873.         mov     ecx, dword [forcedeth_tmp_start]
  874.         call    pci_write_reg
  875.         ; Find the significant bits
  876.         pop     eax
  877.         test    dword [forcedeth_tmp_start], PCI_BASE_ADDRESS_SPACE_IO
  878.         jz      @f
  879.         and     eax, PCI_BASE_ADDRESS_IO_MASK
  880.         jmp     .next2
  881. @@:     and     eax, PCI_BASE_ADDRESS_MEM_MASK
  882. .next2:
  883.         ; Find the lowest bit set
  884.         mov     ecx, eax
  885.         sub     eax, 1
  886.         not     eax
  887.         and     ecx, eax
  888.  
  889. ; END of pci_bar_start
  890.         mov     dword [forcedeth_mmio_size], ecx
  891.  
  892.         DEBUGF 1," K : FORCEDETH: mmio_addr= 0x%x [mmio_size= 0x%x]\n", [forcedeth_mmio_addr]:8, [forcedeth_mmio_size]:8
  893.  
  894.         ; Get Vendor and Device ID
  895.         mov     al, 2
  896.         mov     bh, [pci_dev]
  897.         mov     ah, [pci_bus]
  898.         mov     bl, PCI_VENDOR_ID
  899.         call    pci_read_reg
  900.         mov     word [forcedeth_vendor_id], ax
  901.         shr     eax, 16
  902.         mov     word [forcedeth_device_id], ax
  903.  
  904.         DEBUGF 1," K : FORCEDETH: vendor_id= 0x%x device_id= 0x%x\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4
  905.  
  906.         ; handle different descriptor versions
  907.         mov     eax, dword [forcedeth_device_id]
  908.         cmp     eax, PCI_DEVICE_ID_NVIDIA_NVENET_1
  909.         je      .ver1
  910.         cmp     eax, PCI_DEVICE_ID_NVIDIA_NVENET_2
  911.         je      .ver1
  912.         cmp     eax, PCI_DEVICE_ID_NVIDIA_NVENET_3
  913.         je      .ver1
  914.         mov     dword [forcedeth_desc_ver], DESC_VER_2
  915.         jmp     @f
  916. .ver1:  mov     dword [forcedeth_desc_ver], DESC_VER_1
  917. @@:
  918.         ; read the mac address
  919.         ; map memory
  920.         stdcall map_io_mem, [forcedeth_mmio_addr], [forcedeth_mmio_size], (PG_SW+PG_NOCACHE)
  921.         test eax, eax
  922.         jz .fail
  923.  
  924.         mov     dword [forcedeth_mapio_addr], eax
  925.         mov     edi, eax
  926.         mov     eax, dword [edi+NvRegMacAddrA]
  927.         mov     dword [forcedeth_orig_mac0], eax
  928.         mov     edx, dword [edi+NvRegMacAddrB]
  929.         mov     dword [forcedeth_orig_mac1], edx
  930.  
  931.         ; save MAC-address to global variable node_addr
  932.         mov     dword [node_addr], eax
  933.         mov     word [node_addr+4], dx
  934.  
  935.         ; reverse if desired
  936.         cmp     word [forcedeth_device_id], 0x03E5
  937.         jae     .no_reverse_mac
  938.         mov     al, byte [node_addr]
  939.         xchg    al, byte [node_addr+5]
  940.         mov     byte [node_addr], al
  941.         mov     al, byte [node_addr+1]
  942.         xchg    al, byte [node_addr+4]
  943.         mov     byte [node_addr+4], al
  944.         mov     al, byte [node_addr+2]
  945.         xchg    al, byte [node_addr+3]
  946.         mov     byte [node_addr+3], al
  947. .no_reverse_mac:
  948.  
  949. ;       DEBUGF 1," K : FORCEDETH: orig_mac0= 0x%x\n", [forcedeth_orig_mac0]:8
  950. ;       DEBUGF 1," K : FORCEDETH: orig_mac1= 0x%x\n", [forcedeth_orig_mac1]:8
  951.         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,
  952.  
  953.         ; disable WOL
  954.         mov     edi, dword [forcedeth_mapio_addr]
  955.         mov     dword [edi+NvRegWakeUpFlags], 0
  956.         mov     dword [forcedeth_wolenabled], 0
  957.        
  958.         mov     dword [forcedeth_txflags], (NV_TX2_LASTPACKET or NV_TX2_VALID)
  959.         cmp     dword [forcedeth_desc_ver], DESC_VER_1
  960.         jne     @f
  961.         mov     dword [forcedeth_txflags], (NV_TX_LASTPACKET or NV_TX_VALID)
  962. @@:    
  963.  
  964. ; BEGIN of switch (pci->dev_id)
  965.  
  966.         cmp     word [forcedeth_device_id], 0x01C3
  967.         jne     .next_0x0066
  968.         ; nforce
  969.         mov     dword [forcedeth_irqmask], 0    ;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
  970.         jmp     .end_switch
  971.  
  972. .next_0x0066:
  973.         cmp     word [forcedeth_device_id], 0x0066
  974.         je      @f
  975.         cmp     word [forcedeth_device_id], 0x00D6
  976.         je      @f
  977.         jmp     .next_0x0086
  978. @@:    
  979.         mov     dword [forcedeth_irqmask], 0    ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
  980.         cmp     dword [forcedeth_desc_ver], DESC_VER_1
  981.         jne     @f
  982.         or      dword [forcedeth_txflags], NV_TX_LASTPACKET1
  983.         jmp     .end_switch
  984. @@:     or      dword [forcedeth_txflags], NV_TX2_LASTPACKET1
  985.         jmp     .end_switch
  986.  
  987. .next_0x0086:
  988.         cmp     word [forcedeth_device_id], 0x0086
  989.         je      @f
  990.         cmp     word [forcedeth_device_id], 0x008c
  991.         je      @f
  992.         cmp     word [forcedeth_device_id], 0x00e6
  993.         je      @f
  994.         cmp     word [forcedeth_device_id], 0x00df
  995.         je      @f
  996.         cmp     word [forcedeth_device_id], 0x0056
  997.         je      @f
  998.         cmp     word [forcedeth_device_id], 0x0057
  999.         je      @f
  1000.         cmp     word [forcedeth_device_id], 0x0037
  1001.         je      @f
  1002.         cmp     word [forcedeth_device_id], 0x0038
  1003.         je      @f
  1004.         jmp     .next_0x0268
  1005. @@:    
  1006.         ; np->irqmask = NVREG_IRQMASK_WANTED_2;
  1007.         ; np->irqmask |= NVREG_IRQ_TIMER;
  1008.         mov     dword [forcedeth_irqmask], 0    ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
  1009.  
  1010.         ; if (np->desc_ver == DESC_VER_1)
  1011.         cmp     dword [forcedeth_desc_ver], DESC_VER_1
  1012.         jne     @f
  1013.         ;  np->tx_flags |= NV_TX_LASTPACKET1;
  1014.         or      dword [forcedeth_txflags], NV_TX_LASTPACKET1
  1015.         jmp     .end_switch
  1016.         ; else
  1017. @@:
  1018.         ;  np->tx_flags |= NV_TX2_LASTPACKET1;
  1019.         or      dword [forcedeth_txflags], NV_TX2_LASTPACKET1
  1020.  
  1021.         ; break;
  1022.         jmp     .end_switch
  1023.  
  1024. .next_0x0268:
  1025. ;       cmp     word [forcedeth_device_id], 0x0268
  1026. ;       je      @f
  1027. ;       cmp     word [forcedeth_device_id], 0x0269
  1028. ;       je      @f
  1029. ;       cmp     word [forcedeth_device_id], 0x0372
  1030. ;       je      @f
  1031. ;       cmp     word [forcedeth_device_id], 0x0373
  1032. ;       je      @f
  1033. ;       jmp     .default_switch
  1034. ;@@:
  1035.         cmp     word [forcedeth_device_id], 0x0268
  1036.         jb      .default_switch
  1037.         ; pci_read_config_byte(pci, PCI_REVISION_ID, &revision_id);
  1038.         mov     al, 0   ; byte
  1039.         mov     bh, [pci_dev]
  1040.         mov     ah, [pci_bus]
  1041.         mov     bl, PCI_REVISION_ID
  1042.         call    pci_read_reg
  1043.         mov     ecx, eax        ; cl = revision_id
  1044.  
  1045.         ; take phy and nic out of low power mode
  1046.         ; powerstate = readl(base + NvRegPowerState2);
  1047.         mov     edi, dword [forcedeth_mapio_addr]
  1048.         mov     eax, dword [edi+NvRegPowerState2]       ; eax = powerstate
  1049.        
  1050.         ; powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK;
  1051.         and     eax, not NVREG_POWERSTATE2_POWERUP_MASK
  1052.        
  1053.         ; if ((pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_12||pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_13)&&revision_id>=0xA3)
  1054.         cmp     dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_12
  1055.         je      @f
  1056.         cmp     dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_13
  1057.         je      @f
  1058.         jmp     .end_if
  1059. @@:
  1060.         cmp     cl, 0xA3
  1061.         jl      .end_if
  1062.         ;     powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3;
  1063.         or      eax, NVREG_POWERSTATE2_POWERUP_REV_A3
  1064.  
  1065. .end_if:
  1066.  
  1067.         ; writel(powerstate, base + NvRegPowerState2);
  1068.         mov     dword [edi+NvRegPowerState2], eax
  1069.  
  1070.         ; //DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ
  1071.         ; np->irqmask = NVREG_IRQMASK_WANTED_2;
  1072.         ; np->irqmask |= NVREG_IRQ_TIMER;
  1073.         mov     dword [forcedeth_irqmask], 0    ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER)
  1074.        
  1075.         ; needs_mac_reset = 1;
  1076.         mov     dword [forcedeth_needs_mac_reset], 1
  1077.        
  1078.         ; if (np->desc_ver == DESC_VER_1)
  1079.         cmp     dword [forcedeth_desc_ver], DESC_VER_1
  1080.         jne     @f
  1081.         ;   np->tx_flags |= NV_TX_LASTPACKET1;
  1082.         or      dword [forcedeth_txflags], NV_TX_LASTPACKET1
  1083.         jmp     .end_if2
  1084. @@:
  1085.         ; else
  1086.         ;   np->tx_flags |= NV_TX2_LASTPACKET1;
  1087.         or      dword [forcedeth_txflags], NV_TX2_LASTPACKET1
  1088.  
  1089. .end_if2:
  1090.         ; break;
  1091.         jmp     .end_switch
  1092.  
  1093. .default_switch:
  1094.         DEBUGF 1," K : FORCEDETH: Your card was undefined in this driver.\n"
  1095.         DEBUGF 1," K : FORCEDETH: Review driver_data in Kolibri driver and send a patch\n"
  1096.  
  1097. .end_switch:
  1098.  
  1099. ; END of switch (pci->dev_id)
  1100.  
  1101.  
  1102.         ; Find a suitable phy
  1103.         mov     dword [forcedeth_tmp_i], 1
  1104. .for_loop:
  1105.         ; for (i = 1; i <= 32; i++)
  1106.         ; phyaddr = i & 0x1f
  1107.         mov     ebx, dword [forcedeth_tmp_i]
  1108.         and     ebx, 0x1f
  1109.  
  1110.         ; id1 = mii_rw(phyaddr, MII_PHYSID1, MII_READ)
  1111.         ;EBX - addr, EAX - miireg, ECX - value
  1112.         mov     eax, MII_PHYSID1
  1113.         mov     ecx, MII_READ
  1114.         call    forcedeth_mii_rw        ; id1 = eax
  1115.  
  1116.         ; if (id1 < 0 || id1 == 0xffff)
  1117.         cmp     eax, 0xffffffff
  1118.         je      .continue_for
  1119.         test    eax, 0x80000000
  1120.         jnz     .continue_for
  1121.         mov     dword [forcedeth_tmp_id1], eax
  1122.  
  1123.         ; id2 = mii_rw(nic, phyaddr, MII_PHYSID2, MII_READ)
  1124.         mov     eax, MII_PHYSID2
  1125.         mov     ecx, MII_READ
  1126.         call    forcedeth_mii_rw        ; id2 = eax
  1127.  
  1128.         ; if (id2 < 0 || id2 == 0xffff)
  1129.         cmp     eax, 0xffffffff
  1130.         je      .continue_for
  1131.         test    eax, 0x80000000
  1132.         jnz     .continue_for
  1133.         mov     dword [forcedeth_tmp_id2], eax
  1134.  
  1135.         jmp     .break_for
  1136. .continue_for:
  1137.         inc     dword [forcedeth_tmp_i]
  1138.         cmp     dword [forcedeth_tmp_i], 32
  1139.         jle     .for_loop
  1140.         jmp     .end_for
  1141.  
  1142. .break_for:
  1143.  
  1144. ;;;;    DEBUGF 1," K : FORCEDETH: id1=0x%x id2=0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8
  1145.  
  1146.         ; id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT
  1147.         mov     eax, dword [forcedeth_tmp_id1]
  1148.         and     eax, PHYID1_OUI_MASK
  1149.         shl     eax, PHYID1_OUI_SHFT
  1150.         mov     dword [forcedeth_tmp_id1], eax
  1151.  
  1152.         ; id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT
  1153.         mov     eax, dword [forcedeth_tmp_id2]
  1154.         and     eax, PHYID2_OUI_MASK
  1155.         shr     eax, PHYID2_OUI_SHFT
  1156.         mov     dword [forcedeth_tmp_id2], eax
  1157.  
  1158.         DEBUGF 1," K : FORCEDETH: Found PHY  0x%x:0x%x at address 0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8, ebx
  1159.  
  1160.         ; np->phyaddr = phyaddr;
  1161.         mov     dword [forcedeth_phyaddr], ebx
  1162.  
  1163.         ; np->phy_oui = id1 | id2;
  1164.         mov     eax, dword [forcedeth_tmp_id1]
  1165.         or      eax, dword [forcedeth_tmp_id2]
  1166.         mov     dword [forcedeth_phy_oui], eax
  1167.  
  1168. .end_for:
  1169.  
  1170.         ; if (i == 33)
  1171.         cmp     dword [forcedeth_tmp_i], 33
  1172.         jne     @f
  1173.         ; PHY in isolate mode? No phy attached and user wants to
  1174.         ; test loopback? Very odd, but can be correct.
  1175.        
  1176.         DEBUGF 1," K : FORCEDETH: Could not find a valid PHY.\n"
  1177.  
  1178.         jmp     .next3
  1179.  
  1180. @@:
  1181.  
  1182.         ; if (i != 33)
  1183.         ; reset it
  1184.         call    forcedeth_phy_init
  1185.  
  1186. .next3:
  1187.  
  1188. ;        dprintf(("%s: forcedeth.c: subsystem: %hX:%hX bound to %s\n",
  1189. ;                 pci->name, pci->vendor, pci->dev_id, pci->name));
  1190.         DEBUGF 1," K : FORCEDETH: subsystem: 0x%x:0x%x bound to forcedeth\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4
  1191.  
  1192.  
  1193. ;        if(needs_mac_reset) mac_reset(nic);
  1194.         cmp     dword [forcedeth_needs_mac_reset], 0
  1195.         je      @f
  1196.         call    forcedeth_mac_reset
  1197.  
  1198. @@:
  1199.        
  1200.         ; if(!forcedeth_reset(nic)) return 0; // no valid link
  1201.         call    forcedeth_reset
  1202.         test    eax, eax
  1203.         jnz     @f
  1204.         mov     eax, 0
  1205.         jmp     .return
  1206.  
  1207. @@:
  1208.  
  1209.         ; point to NIC specific routines
  1210.         ; dev->disable = forcedeth_disable;
  1211.         ; nic->poll = forcedeth_poll;
  1212.         ; nic->transmit = forcedeth_transmit;
  1213.         ; nic->irq = forcedeth_irq;
  1214.         ;;;;;;;;;stdcall attach_int_handler, 11, forcedeth_int_handler, 0
  1215.  
  1216.         ; return 1
  1217.         mov     eax, 1
  1218.         jmp     .return
  1219.  
  1220. .fail:
  1221.         mov     eax, 0
  1222.  
  1223. .return:
  1224.         ret
  1225.  
  1226. uglobal
  1227. forcedeth_tmp_start     dd ?
  1228. forcedeth_tmp_reg       dd ?
  1229. forcedeth_tmp_i         dd ?
  1230. forcedeth_tmp_id1       dd ?
  1231. forcedeth_tmp_id2       dd ?
  1232. forcedeth_tmp_phyinterface      dd ?
  1233. forcedeth_tmp_newls     dd ?
  1234. forcedeth_tmp_newdup    dd ?
  1235. forcedeth_tmp_retval    dd ?
  1236. forcedeth_tmp_control_1000      dd ?
  1237. forcedeth_tmp_lpa       dd ?
  1238. forcedeth_tmp_adv       dd ?
  1239. forcedeth_tmp_len       dd ?
  1240. forcedeth_tmp_valid     dd ?
  1241. forcedeth_tmp_nr        dd ?
  1242. forcedeth_tmp_ptxb      dd ?
  1243. endg
  1244.  
  1245. ;***************************************************************************
  1246. ; Function
  1247. ;    forcedeth_poll
  1248. ;
  1249. ; Description
  1250. ;    Polls the ethernet card for a received packet
  1251. ;    Received data, if any, ends up in Ether_buffer
  1252. ;
  1253. ;***************************************************************************
  1254. forcedeth_poll:
  1255.  
  1256.         mov     word [eth_rx_data_len], 0
  1257.  
  1258.         ; ????????????????????????????
  1259.         ; ??? Clear events? ???
  1260.         mov     edi, dword [forcedeth_mapio_addr]
  1261.         mov     dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK
  1262.         ; ????????????????????????????
  1263.  
  1264. .top:
  1265.  
  1266.         ; i = np->cur_rx % RX_RING
  1267.         mov     eax, dword [forcedeth_cur_rx]
  1268.         and     eax, (RX_RING-1)
  1269.         mov     dword [forcedeth_tmp_i], eax
  1270.  
  1271.         ; Flags = le32_to_cpu(rx_ring[i].FlagLen)
  1272.         ; Flags = rx_ring[i].FlagLen
  1273.         mov     cl, sizeof.forcedeth_RxDesc
  1274.         mul     cl
  1275.         add     eax, forcedeth_rx_ring
  1276.         mov     ebx, eax
  1277.         mov     eax, [ebx + forcedeth_RxDesc.FlagLen]
  1278.  
  1279.  
  1280.         ; if (Flags & NV_RX_AVAIL)
  1281.         test    eax, NV_RX_AVAIL
  1282.         ;   return 0;       /* still owned by hardware, */
  1283.         ; still owned by hardware
  1284.         jnz     .return0
  1285.  
  1286. ;;;;;   DEBUGF  1,"poll: FlagLen = %x\n", eax
  1287.  
  1288.         ; if (np->desc_ver == DESC_VER_1) {
  1289.         cmp     dword [forcedeth_desc_ver], DESC_VER_1
  1290.         jne     @f
  1291.         ;   if (!(Flags & NV_RX_DESCRIPTORVALID))
  1292.         test    eax, NV_RX_DESCRIPTORVALID
  1293.         ;     return 0;
  1294.         jz      .return0
  1295.         jmp     .next
  1296.         ; } else {
  1297. @@:
  1298.         ;   if (!(Flags & NV_RX2_DESCRIPTORVALID))
  1299.         test    eax, NV_RX2_DESCRIPTORVALID
  1300.         ;     return 0;
  1301.         jz      .return0
  1302.         ; }
  1303.        
  1304. .next:
  1305.  
  1306.         ; len = nv_descr_getlength(&rx_ring[i], np->desc_ver)
  1307.         ; len = rx_ring[i].FlagLen & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2);
  1308.         ; eax = FlagLen
  1309.         cmp     dword [forcedeth_desc_ver], DESC_VER_1
  1310.         jne     @f
  1311.         and     eax, LEN_MASK_V1
  1312.         jmp     .next2
  1313. @@:
  1314.         and     eax, LEN_MASK_V2
  1315.  
  1316. .next2:
  1317.  
  1318.         ; mov   dword [forcedeth_tmp_len], eax
  1319.  
  1320.         ; valid = 1
  1321.         mov     dword [forcedeth_tmp_valid], 1
  1322.                
  1323.         ; got a valid packet - forward it to the network core
  1324.         ; nic->packetlen = len;
  1325.         mov     dword [forcedeth_packetlen], eax
  1326.         ;
  1327.         mov     word [eth_rx_data_len], ax
  1328. ;;;;;;;;;        DEBUGF 1,"poll: packet len = 0x%x\n", [forcedeth_packetlen]
  1329.  
  1330.  
  1331.         ; memcpy(nic->packet, rxb + (i * RX_NIC_BUFSIZE), nic->packetlen);
  1332.         ; Copy packet to system buffer (Ether_buffer)
  1333.         ;???? ecx = (len-4)
  1334.         mov     ecx, eax
  1335.         push    ecx
  1336.         shr     ecx, 2
  1337.  
  1338.         ; rxb + (i * RX_NIC_BUFSIZE)
  1339.         mov     eax, dword [forcedeth_tmp_i]
  1340.         mov     bx, RX_NIC_BUFSIZE
  1341.         mul     bx
  1342.         add     eax, forcedeth_rxb
  1343.  
  1344.         mov     esi, eax
  1345.         mov     edi, Ether_buffer
  1346.         cld             ; set to increment
  1347.         rep     movsd   ; mov dword from [esi++] to [edi++]
  1348.         pop     ecx
  1349.         and     ecx, 3  ; copy rest 1-3 bytes
  1350.         rep     movsb
  1351.  
  1352.         ; wmb();
  1353.         ; ???
  1354.  
  1355.         ; np->cur_rx++;
  1356.         inc     dword [forcedeth_cur_rx]
  1357.  
  1358.         ; if (!valid)
  1359.         cmp     dword [forcedeth_tmp_valid], 0
  1360.         jne     @f
  1361.         ;   goto top;
  1362.         jmp     .top
  1363. @@:
  1364.         ; alloc_rx(nic);
  1365.         call    forcedeth_alloc_rx
  1366.  
  1367.         ; return 1;
  1368.         jmp     .return1
  1369.  
  1370. ;;;;;   DEBUGF  1,"K : FORCEDETH: poll: ...\n"
  1371.  
  1372.  
  1373. .return0:
  1374.         mov     eax, 0
  1375.         jmp     .return
  1376. .return1:
  1377.         mov     eax, 1
  1378. .return:
  1379.         ;;push  eax
  1380.  
  1381.         ; ????????????????????????????????????????????????
  1382.         ; ????? clear interrupt mask/status
  1383.         ; read IRQ status
  1384.         ;;mov   edi, dword [forcedeth_mapio_addr]
  1385.         ;;mov   eax, dword [edi+NvRegIrqStatus]
  1386.  
  1387.         ; clear events
  1388.         ;;and   eax, not (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF or NVREG_IRQ_LINK or NVREG_IRQ_TIMER)
  1389.  
  1390.         ; write IRQ status
  1391.         ;;mov   dword [edi+NvRegIrqStatus], eax
  1392.         ; ????????????????????????????????????????????????
  1393.  
  1394.         ;;pop   eax
  1395.         ret
  1396.  
  1397.  
  1398. ;***************************************************************************
  1399. ;   Function
  1400. ;      forcedeth_transmit
  1401. ;
  1402. ;   Description
  1403. ;       Transmits a packet of data via the ethernet card
  1404. ;          Pointer to 48 bit destination address in edi
  1405. ;         Type of packet in bx
  1406. ;         size of packet in ecx
  1407. ;         pointer to packet data in esi
  1408. ;
  1409. ;***************************************************************************
  1410. forcedeth_transmit:
  1411.  
  1412.         ; send the packet to destination
  1413. ;pusha
  1414. ;DEBUGF 1,"K : FORCEDETH: transmit: packet type = 0x%x\n", ebx
  1415. ;DEBUGF 1,"K : FORCEDETH: transmit: packet len  = 0x%x\n", ecx
  1416. ;mov    eax, dword [edi]
  1417. ;DEBUGF 1,"K : FORCEDETH: transmit: dest adr    = 0x%x\n", eax
  1418. ;mov    eax, dword [edi+4]
  1419. ;DEBUGF 1,"K : FORCEDETH: transmit: dest adr2   = 0x%x\n", eax
  1420. ;mov    eax, dword [node_addr]
  1421. ;DEBUGF 1,"K : FORCEDETH: transmit: src  adr    = 0x%x\n", eax
  1422. ;mov    eax, dword [node_addr+4]
  1423. ;DEBUGF 1,"K : FORCEDETH: transmit: src adr2    = 0x%x\n", eax
  1424. ;popa
  1425.  
  1426.         ; int nr = np->next_tx % TX_RING
  1427.         mov     eax, dword [forcedeth_next_tx]
  1428.         and     eax, (TX_RING-1)
  1429.         mov     dword [forcedeth_tmp_nr], eax
  1430.        
  1431.         ; point to the current txb incase multiple tx_rings are used
  1432.         ; ptxb = txb + (nr * RX_NIC_BUFSIZE)
  1433.         push    ecx
  1434.         mov     cx, RX_NIC_BUFSIZE
  1435.         mul     cx      ; AX*CX, result to DX:AX
  1436.         add     eax, forcedeth_txb
  1437.         mov     dword [forcedeth_tmp_ptxb], eax
  1438.         push    esi
  1439.         mov     esi, edi        ; dst MAC
  1440.         mov     edi, eax        ; packet buffer
  1441.         cld                     ; set to increment
  1442.        
  1443.         ; copy the packet to ring buffer
  1444.         ; memcpy(ptxb, d, ETH_ALEN);      /* dst */
  1445.         movsd
  1446.         movsw
  1447.        
  1448.         ; memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN);      /* src */
  1449.         mov     esi, node_addr
  1450.         movsd
  1451.         movsw
  1452.  
  1453.         ; nstype = htons((u16) t);        /* type */
  1454.         ; memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2);        /* type */
  1455.         mov     word [edi], bx
  1456.         add     edi, 2
  1457.        
  1458.         ; memcpy(ptxb + ETH_HLEN, p, s);
  1459.         pop     esi
  1460.         pop     ecx
  1461.         push    ecx
  1462.         shr     ecx, 2          ; count in dwords
  1463.         rep     movsd           ; copy dwords from [esi+=4] to [edi+=4]
  1464.         pop     ecx
  1465.         push    ecx
  1466.         and     ecx, 3          ; copy rest 1-3 bytes
  1467.         rep     movsb           ; copy bytess from [esi++] to [edi++]
  1468.  
  1469.  
  1470.         ; s += ETH_HLEN;
  1471.         ; while (s < ETH_ZLEN)    /* pad to min length */
  1472.         ;  ptxb[s++] = '\0';
  1473.         ; pad to min length
  1474.         pop     ecx
  1475.         add     ecx, ETH_HLEN
  1476.         push    ecx             ; header length + data length
  1477.         cmp     ecx, ETH_ZLEN
  1478.         jge     @f
  1479.         mov     eax, ETH_ZLEN
  1480.         sub     eax, ecx
  1481.         xchg    eax, ecx
  1482.         mov     al, 0
  1483.         rep     stosb           ; copy byte from al to [edi++]
  1484.  
  1485. @@:
  1486.  
  1487.         ; tx_ring[nr].PacketBuffer = (u32) virt_to_le32desc(ptxb);
  1488.         mov     eax, dword [forcedeth_tmp_nr]
  1489.         mov     cl, sizeof.forcedeth_TxDesc
  1490.         mul     cl
  1491.         add     eax, forcedeth_tx_ring
  1492.         mov     ebx, eax
  1493.         mov     eax, dword [forcedeth_tmp_ptxb]
  1494.         sub     eax, OS_BASE            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1495.         mov     [ebx + forcedeth_TxDesc.PacketBuffer], eax
  1496.  
  1497. ;DEBUGF 1,"K : FORCEDETH: transmit: PacketBuffer = 0x%x\n", eax
  1498. ;DEBUGF 1,"K : FORCEDETH: transmit: txflags = 0x%x\n", [forcedeth_txflags]:8
  1499.  
  1500.         ; wmb();
  1501.         ; tx_ring[nr].FlagLen = cpu_to_le32((s - 1) | np->tx_flags);
  1502.         pop     eax             ; header length + data length
  1503.         mov     ecx, dword [forcedeth_txflags]
  1504.         or      eax, ecx
  1505.         mov     [ebx + forcedeth_TxDesc.FlagLen], eax
  1506.  
  1507.         ; writel(NVREG_TXRXCTL_KICK | np->desc_ver, base + NvRegTxRxControl);
  1508.         mov     edi, dword [forcedeth_mapio_addr]
  1509.         mov     eax, dword [forcedeth_desc_ver]
  1510.         or      eax, NVREG_TXRXCTL_KICK
  1511.         mov     dword [edi+NvRegTxRxControl], eax
  1512.  
  1513.         ; pci_push(base);
  1514.         call    forcedeth_pci_push
  1515.  
  1516.         ; np->next_tx++
  1517.         inc dword [forcedeth_next_tx]   ; may be need to reset? Overflow?
  1518.  
  1519.         ret
  1520.  
  1521. ;***************************************************************************
  1522. ;   Function
  1523. ;      forcedeth_cable
  1524. ;
  1525. ;   Description
  1526. ;       Return AL=0, if cable is not connected
  1527. ;       Returm AL=1, if cable is connected
  1528. ;
  1529. ;***************************************************************************
  1530. forcedeth_cable:
  1531.  
  1532.         mov     al, 1
  1533.         cmp     dword [forcedeth_nocable], 1
  1534.         jne     .return
  1535.         mov     al, 0
  1536.  
  1537. .return:
  1538.         ret
  1539.  
  1540. ;***************************************************************************
  1541.        
  1542.        
  1543. ; read/write a register on the PHY.
  1544. ; Caller must guarantee serialization
  1545. ; Input:  EAX - miireg, EBX - addr, ECX - value
  1546. ; Output: EAX - retval
  1547. forcedeth_mii_rw:
  1548.         push    ebx
  1549.         push    eax     ; save miireg
  1550.         ; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus)
  1551.         mov     edi, dword [forcedeth_mapio_addr]
  1552.         mov     dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK
  1553.  
  1554.         ; reg = readl(base + NvRegMIIControl)
  1555.         mov     eax, dword [edi+NvRegMIIControl]
  1556.         test    eax, NVREG_MIICTL_INUSE
  1557.         jz      @f
  1558.         ; writel(NVREG_MIICTL_INUSE, base + NvRegMIIControl)
  1559.         mov     dword [edi+NvRegMIIControl], NVREG_MIICTL_INUSE
  1560.         ; nv_udelay(NV_MIIBUSY_DELAY)
  1561.         mov     esi, NV_MIIBUSY_DELAY
  1562.         call    forcedeth_nv_udelay
  1563. @@:
  1564.         ; reg = (addr << NVREG_MIICTL_ADDRSHIFT) | miireg
  1565.         pop     edx     ; restore miireg
  1566.         mov     eax, ebx
  1567.         shl     eax, NVREG_MIICTL_ADDRSHIFT
  1568.         or      eax, edx
  1569.         mov     dword [forcedeth_tmp_reg], eax
  1570.  
  1571.         cmp     ecx, MII_READ
  1572.         je      @f
  1573.         ; writel(value, base + NvRegMIIData)
  1574.         mov     dword [edi+NvRegMIIData], ecx
  1575.         ; reg |= NVREG_MIICTL_WRITE
  1576.         or      dword [forcedeth_tmp_reg], NVREG_MIICTL_WRITE
  1577. @@:
  1578.         ; writel(reg, base + NvRegMIIControl)
  1579.         mov     eax, dword [forcedeth_tmp_reg]
  1580.         mov     dword [edi+NvRegMIIControl], eax
  1581.  
  1582.         push    ebx edx edi     ;;;;;;;;;;;;;;;;;;;;;;
  1583.  
  1584.         ; reg_delay(NvRegMIIControl, NVREG_MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL)
  1585.         stdcall forcedeth_reg_delay,NvRegMIIControl,NVREG_MIICTL_INUSE,0,NV_MIIPHY_DELAY,NV_MIIPHY_DELAYMAX,0
  1586.  
  1587.         pop     edi edx ebx     ;;;;;;;;;;;;;;;;;;;;;;
  1588.  
  1589.         test    eax, eax
  1590.         jz      @f
  1591. ;;;;;;;;        DEBUGF  1,"K : FORCEDETH: mii_rw of reg %d at PHY %d timed out.\n", edx, ebx
  1592.         mov     eax, 0xffffffff
  1593.         jmp     .return
  1594. @@:
  1595.         cmp     ecx, MII_READ
  1596.         je      @f
  1597.         ;it was a write operation - fewer failures are detectable
  1598. ;;;;;;;;        DEBUGF  1,"K : FORCEDETH: mii_rw wrote 0x%x to reg %d at PHY %d\n", ecx, edx, ebx
  1599.         mov     eax, 0
  1600.         jmp     .return
  1601. @@:
  1602.         ; readl(base + NvRegMIIStatus)
  1603.         mov     eax, dword [edi+NvRegMIIStatus]
  1604.         test    eax, NVREG_MIISTAT_ERROR
  1605.         jz      @f
  1606. ;;;;;;;;        DEBUGF  1,"K : FORCEDETH: mii_rw of reg %d at PHY %d failed.\n", edx, ebx
  1607.         mov     eax, 0xffffffff
  1608.         jmp     .return
  1609. @@:
  1610.         ; retval = readl(base + NvRegMIIData)
  1611.         mov     eax, dword [edi+NvRegMIIData]
  1612. ;;;;;;;;        DEBUGF  1,"K : FORCEDETH: mii_rw read from reg %d at PHY %d: 0x%x.\n", edx, ebx, eax
  1613. .return:
  1614.         pop     ebx
  1615.         ret
  1616.  
  1617.  
  1618.  
  1619. ; Input:  ESI - delay
  1620. ; Output: none
  1621. forcedeth_nv_udelay:
  1622.  
  1623.         push    ebx
  1624.         cmp     dword [forcedeth_in_shutdown], 0
  1625.         jne     @f
  1626.         call    forcedeth_udelay        ; delay on ESI
  1627.         jmp     .return
  1628. @@:
  1629.        
  1630. .loop:
  1631.         cmp     esi, 0
  1632.         je      .return
  1633.         ; Don't allow an rx_ring overflow to happen
  1634.         ; while shutting down the NIC it will
  1635.         ; kill the receive function.
  1636.  
  1637.         call    forcedeth_drop_rx
  1638.         mov     ebx, 3          ; sleep = 3
  1639.         cmp     ebx, esi        ; if(sleep > delay)
  1640.         jle     @f
  1641.         mov     ebx, esi        ; sleep = delay
  1642. @@:
  1643.         push    esi
  1644.         mov     esi, ebx
  1645.         ; udelay(sleep)
  1646.         call    forcedeth_udelay        ; delay on ESI
  1647.         pop     esi
  1648.         sub     esi, ebx                ; delay -= sleep
  1649.         jmp     .loop
  1650.  
  1651. .return:
  1652.         pop     ebx
  1653.         ret
  1654.  
  1655.  
  1656. ; Input:  none
  1657. ; Output: none
  1658. forcedeth_drop_rx:
  1659.  
  1660.         push    eax ebx ecx edi
  1661.  
  1662.         ; events = readl(base + NvRegIrqStatus)
  1663.         mov     edi, dword [forcedeth_mapio_addr]
  1664.         mov     eax, dword [edi+NvRegIrqStatus]
  1665.  
  1666.         test    eax, eax
  1667.         jz      @f
  1668.         ; writel(events, base + NvRegIrqStatus)
  1669.         mov     dword [edi+NvRegIrqStatus], eax
  1670. @@:
  1671.         ;if (!(events & (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF)))
  1672.         test    eax, (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF)
  1673.         jz      .return
  1674.        
  1675. .loop: 
  1676.         ; i = np->cur_rx % RX_RING
  1677.         mov     eax, dword [forcedeth_cur_rx]
  1678.         and     eax, (RX_RING-1)
  1679.         ; //Flags = le32_to_cpu(rx_ring[i].FlagLen)
  1680.         ; Flags = rx_ring[i].FlagLen
  1681.         mov     cl, sizeof.forcedeth_RxDesc
  1682.         mul     cl
  1683.         add     eax, forcedeth_rx_ring
  1684.         mov     ebx, eax
  1685.         mov     eax, [ebx + forcedeth_RxDesc.FlagLen]
  1686.         ; len = nv_descr_getlength(&rx_ring[i], np->desc_ver)
  1687.         ; > len = Flags & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2)
  1688.         ; ??? len don't used later !!! ???
  1689.         ; ...
  1690.         test    eax, NV_RX_AVAIL
  1691.         jnz     .return         ; still owned by hardware,
  1692.         ; wmb()
  1693.         ; ??? may be empty function ???
  1694.         ; np->cur_rx++
  1695.         inc     dword [forcedeth_cur_rx]
  1696.         ; alloc_rx(NULL)
  1697.         call    forcedeth_alloc_rx
  1698. .return:       
  1699.         pop     edi ecx ebx eax
  1700.         ret
  1701.  
  1702.  
  1703. ; Fill rx ring entries.
  1704. ; Return 1 if the allocations for the skbs failed and the
  1705. ; rx engine is without Available descriptors
  1706. ; Input:  none
  1707. ; Output: none
  1708. forcedeth_alloc_rx:
  1709.  
  1710.         push    eax ebx ecx edx
  1711.         ; refill_rx = np->refill_rx
  1712.         mov     ecx, dword [forcedeth_refill_rx]
  1713. .loop:
  1714.         cmp     dword [forcedeth_cur_rx], ecx
  1715.         je      .loop_end
  1716.         ; nr = refill_rx % RX_RING
  1717.         mov     eax, ecx
  1718.         and     eax, (RX_RING-1)        ; nr
  1719.         ; rx_ring[nr].PacketBuffer = &rxb[nr * RX_NIC_BUFSIZE]
  1720.         push    ecx
  1721.         push    eax
  1722.         mov     cl, sizeof.forcedeth_RxDesc
  1723.         mul     cl
  1724.         add     eax, forcedeth_rx_ring
  1725.         mov     ebx, eax
  1726.         pop     eax
  1727.         mov     cx, RX_NIC_BUFSIZE
  1728.         mul     cx
  1729.         pop     ecx
  1730.         add     eax, forcedeth_rxb
  1731.         sub     eax, OS_BASE    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1732.         mov     [ebx + forcedeth_RxDesc.PacketBuffer], eax
  1733.         ; wmb()
  1734.         ; ...
  1735.         ; rx_ring[nr].FlagLen = RX_NIC_BUFSIZE | NV_RX_AVAIL
  1736.         mov     [ebx + forcedeth_RxDesc.FlagLen], (RX_NIC_BUFSIZE or NV_RX_AVAIL)
  1737.         inc     ecx
  1738.         jmp     .loop
  1739.        
  1740. .loop_end:
  1741.         ; np->refill_rx = refill_rx
  1742.         mov     [forcedeth_refill_rx], ecx
  1743. .return:
  1744.         pop     edx ecx ebx eax
  1745.         ret
  1746.  
  1747.  
  1748. ; Delay in millisec
  1749. ; Input:  ESI - delay in ms
  1750. ; Output: none
  1751. forcedeth_udelay:
  1752.         call    delay_ms
  1753.         ret
  1754.  
  1755. ; Input:  offset:word, mask:dword, target:dword, delay:word, delaymax:word, msg:dword
  1756. ; Output: EAX - 0|1
  1757. ;;;;proc        forcedeth_reg_delay,offset:word,mask:dword,target:dword,delay:word,delaymax:word,msg:dword
  1758. proc    forcedeth_reg_delay,offset:dword,mask:dword,target:dword,delay:dword,delaymax:dword,msg:dword
  1759.  
  1760.         push    ebx esi edi
  1761.         ; pci_push(base)
  1762.         call    forcedeth_pci_push
  1763. .loop:
  1764.         ; nv_udelay(delay)
  1765.         mov     esi, dword [delay]
  1766.         call    forcedeth_nv_udelay     ; delay in esi
  1767.         mov     eax, dword [delaymax]
  1768.         sub     eax, dword [delay]
  1769.         mov     dword [delaymax], eax
  1770.         ; if (delaymax < 0)
  1771.         test    dword [delaymax], 0x80000000
  1772.         jz      @f
  1773.         ; return 1
  1774.         mov     eax, 1
  1775.         jmp     .return
  1776. @@:
  1777.         ; while ((readl(base + offset) & mask) != target)
  1778.         mov     edi, dword [forcedeth_mapio_addr]
  1779.         mov     ebx, dword [offset]
  1780.         mov     eax, dword [edi+ebx]
  1781.         and     eax, dword [mask]
  1782.         cmp     eax, dword [target]
  1783.         jne     .loop
  1784.         xor     eax, eax
  1785. .return:
  1786.         pop     edi esi ebx
  1787.         ret
  1788. endp
  1789.  
  1790.  
  1791. ; Input:  none
  1792. ; Output: none
  1793. forcedeth_pci_push:
  1794.         push    eax edi
  1795.         ;force out pending posted writes
  1796.         mov     edi, dword [forcedeth_mapio_addr]
  1797.         mov     eax, dword [edi]
  1798.         pop     edi eax
  1799.         ret
  1800.  
  1801.  
  1802. ; Input:  none
  1803. ; Output: EAX - result (0 = OK, other = error)
  1804. forcedeth_phy_init:
  1805.  
  1806.         push    ebx ecx
  1807.        
  1808.         ; set advertise register
  1809.         ; reg = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ);
  1810.         ; EBX - addr, EAX - miireg, ECX - value
  1811.         mov     ebx, dword [forcedeth_phyaddr]
  1812.         mov     eax, MII_ADVERTISE
  1813.         mov     ecx, MII_READ
  1814.         call    forcedeth_mii_rw        ; reg = eax
  1815.  
  1816.         ; reg |=
  1817.         ; (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF |
  1818.         ;  ADVERTISE_100FULL | 0x800 | 0x400);
  1819.         or      eax, (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or 0x800 or 0x400)
  1820.  
  1821.         ; if (mii_rw(nic, np->phyaddr, MII_ADVERTISE, reg))
  1822.         ; EBX - addr, EAX - miireg, ECX - value
  1823.         mov     ecx, eax        ; reg
  1824.         mov     eax, MII_ADVERTISE
  1825.         call    forcedeth_mii_rw        ; eax -> return
  1826.  
  1827.         test    eax, eax
  1828.         jz      @f
  1829.         ; printf("phy write to advertise failed.\n");
  1830.         DEBUGF 1," K : FORCEDETH: phy write to advertise failed.\n"
  1831.  
  1832.         ; return PHY_ERROR;
  1833.         mov     eax, PHY_ERROR
  1834.         jmp     .return
  1835. @@:
  1836.         ; get phy interface type
  1837.         ; phyinterface = readl(base + NvRegPhyInterface);
  1838.         mov     edi, dword [forcedeth_mapio_addr]
  1839.         mov     eax, dword [edi+NvRegPhyInterface]      ; phyinterface = eax
  1840.         mov     dword [forcedeth_tmp_phyinterface], eax
  1841.  
  1842. ;;;;;;;;;;;;;;;;;;;;;;;;;
  1843. DEBUGF 1," K : FORCEDETH: phy interface type = 0x%x\n", [forcedeth_tmp_phyinterface]:8
  1844. ;;;;;;;;;;;;;;;;;;;;;;;;;
  1845.  
  1846.         ; see if gigabit phy
  1847.         ; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
  1848.         ; EBX - addr, EAX - miireg, ECX - value
  1849.         mov     eax, MII_BMSR
  1850.         mov     ecx, MII_READ
  1851.         call    forcedeth_mii_rw        ; mii_status = eax
  1852.        
  1853.         ; if (mii_status & PHY_GIGABIT)
  1854.         test    eax, PHY_GIGABIT
  1855.         jnz     .gigabit
  1856.         ; np->gigabit = 0;
  1857.         mov     dword [forcedeth_gigabit], 0
  1858.         jmp     .next_if
  1859.  
  1860. .gigabit:
  1861.         ; np->gigabit = PHY_GIGABIT;
  1862.         mov     dword [forcedeth_gigabit], PHY_GIGABIT
  1863.  
  1864.         ; mii_control_1000 =  mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ);
  1865.         ; EBX - addr, EAX - miireg, ECX - value
  1866.         mov     eax, MII_1000BT_CR
  1867.         mov     ecx, MII_READ
  1868.         call    forcedeth_mii_rw        ; mii_control_1000 = eax
  1869.        
  1870.         ; mii_control_1000 &= ~ADVERTISE_1000HALF;
  1871.         and     eax, (not ADVERTISE_1000HALF)
  1872.  
  1873.         ; if (phyinterface & PHY_RGMII)
  1874.         test    dword [forcedeth_tmp_phyinterface], PHY_RGMII
  1875.         jz      @f
  1876.         ; mii_control_1000 |= ADVERTISE_1000FULL
  1877.         or      eax, ADVERTISE_1000FULL
  1878.         jmp     .next
  1879. @@:
  1880.         ; mii_control_1000 &= ~ADVERTISE_1000FULL
  1881.         and     eax, (not ADVERTISE_1000FULL)
  1882.  
  1883. .next:
  1884.         ; if (mii_rw(nic, np->phyaddr, MII_1000BT_CR, mii_control_1000))
  1885.         ; EBX - addr, EAX - miireg, ECX - value
  1886.         mov     ecx, eax
  1887.         mov     eax, MII_1000BT_CR
  1888.         call    forcedeth_mii_rw        ; eax -> return
  1889.  
  1890.         test    eax, eax
  1891.         jz      .next_if
  1892.  
  1893.         ; printf("phy init failed.\n");
  1894.         DEBUGF 1," K : FORCEDETH: phy init failed.\n"
  1895.  
  1896.         ; return PHY_ERROR;
  1897.         mov     eax, PHY_ERROR
  1898.         jmp     .return
  1899.  
  1900. .next_if:
  1901.  
  1902.         ; reset the phy
  1903.         ; if (phy_reset(nic))
  1904.         call    forcedeth_phy_reset
  1905.         test    eax, eax
  1906.         jz      @f
  1907.         ; printf("phy reset failed\n")
  1908.         DEBUGF 1," K : FORCEDETH: phy reset failed.\n"
  1909.         ; return PHY_ERROR
  1910.         mov     eax, PHY_ERROR
  1911.         jmp     .return
  1912. @@:
  1913.  
  1914.         ; phy vendor specific configuration
  1915.         ; if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII))
  1916.         cmp     dword [forcedeth_phy_oui], PHY_OUI_CICADA
  1917.         jne     .next_if2
  1918.         test    dword [forcedeth_tmp_phyinterface], PHY_RGMII
  1919.         jz      .next_if2
  1920.  
  1921.         ; phy_reserved = mii_rw(nic, np->phyaddr, MII_RESV1, MII_READ)
  1922.         ; EBX - addr, EAX - miireg, ECX - value
  1923.         mov     eax, MII_RESV1
  1924.         mov     ecx, MII_READ
  1925.         call    forcedeth_mii_rw        ; phy_reserved = eax
  1926.        
  1927.         ; phy_reserved &= ~(PHY_INIT1 | PHY_INIT2)
  1928.         and     eax, (not (PHY_INIT1 or PHY_INIT2))
  1929.         ; phy_reserved |= (PHY_INIT3 | PHY_INIT4)
  1930.         or      eax, (PHY_INIT3 or PHY_INIT4)
  1931.        
  1932.         ; if (mii_rw(nic, np->phyaddr, MII_RESV1, phy_reserved))
  1933.         ; EBX - addr, EAX - miireg, ECX - value
  1934.         mov     ecx, eax
  1935.         mov     eax, MII_RESV1
  1936.         call    forcedeth_mii_rw        ; eax -> return
  1937.         test    eax, eax
  1938.         jz      @f
  1939.         ; printf("phy init failed.\n")
  1940.         DEBUGF 1," K : FORCEDETH: phy init failed.\n"
  1941.         ; return PHY_ERROR
  1942.         mov     eax, PHY_ERROR
  1943.         jmp     .return
  1944. @@:
  1945.         ; phy_reserved = mii_rw(nic, np->phyaddr, MII_NCONFIG, MII_READ);
  1946.         ; EBX - addr, EAX - miireg, ECX - value
  1947.         mov     eax, MII_NCONFIG
  1948.         mov     ecx, MII_READ
  1949.         call    forcedeth_mii_rw        ; phy_reserved = eax
  1950.  
  1951.         ; phy_reserved |= PHY_INIT5
  1952.         or      eax, PHY_INIT5
  1953.        
  1954.         ; if (mii_rw(nic, np->phyaddr, MII_NCONFIG, phy_reserved))
  1955.         ; EBX - addr, EAX - miireg, ECX - value
  1956.         mov     ecx, eax
  1957.         mov     eax, MII_NCONFIG
  1958.         call    forcedeth_mii_rw        ; eax -> return
  1959.         test    eax, eax
  1960.         jz      .next_if2
  1961.         ; printf("phy init failed.\n")
  1962.         DEBUGF 1," K : FORCEDETH: phy init failed.\n"
  1963.         ; return PHY_ERROR
  1964.         mov     eax, PHY_ERROR
  1965.         jmp     .return
  1966.  
  1967. .next_if2:
  1968.  
  1969.         ; if (np->phy_oui == PHY_OUI_CICADA)
  1970.         cmp     dword [forcedeth_phy_oui], PHY_OUI_CICADA
  1971.         jne     .restart
  1972.        
  1973.         ; phy_reserved = mii_rw(nic, np->phyaddr, MII_SREVISION, MII_READ)
  1974.         ; EBX - addr, EAX - miireg, ECX - value
  1975.         mov     eax, MII_SREVISION
  1976.         mov     ecx, MII_READ
  1977.         call    forcedeth_mii_rw        ; phy_reserved = eax
  1978.        
  1979.         ; phy_reserved |= PHY_INIT6
  1980.         or      eax, PHY_INIT6
  1981.        
  1982.         ; if (mii_rw(nic, np->phyaddr, MII_SREVISION, phy_reserved))
  1983.         mov     ecx, eax
  1984.         mov     eax, MII_SREVISION
  1985.         call    forcedeth_mii_rw        ; eax -> return
  1986.         test    eax, eax
  1987.         jz      .restart
  1988.         ; printf("phy init failed.\n");
  1989.         DEBUGF 1," K : FORCEDETH: phy init failed.\n"
  1990.         ; return PHY_ERROR;
  1991.         jmp     .return
  1992.  
  1993. .restart:
  1994.         ; restart auto negotiation
  1995.         ; mii_control = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ)
  1996.         ; EBX - addr, EAX - miireg, ECX - value
  1997.         mov     eax, MII_BMCR
  1998.         mov     ecx, MII_READ
  1999.         call    forcedeth_mii_rw        ; mii_control = eax
  2000.  
  2001.         ; mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE)
  2002.         or      eax, (BMCR_ANRESTART or BMCR_ANENABLE)
  2003.        
  2004.         ; if (mii_rw(nic, np->phyaddr, MII_BMCR, mii_control))
  2005.         mov     ecx, eax
  2006.         mov     eax, MII_BMCR
  2007.         call    forcedeth_mii_rw        ; eax -> return
  2008.         test    eax, eax
  2009.         jz      .ok
  2010.  
  2011.         ; return PHY_ERROR;
  2012.         mov     eax, PHY_ERROR
  2013.         jmp     .return
  2014.  
  2015. .ok:
  2016.         mov     eax, 0 
  2017. .return:
  2018.         pop     ecx ebx
  2019.         ret
  2020.  
  2021.  
  2022. ; Input:  none
  2023. ; Output: EAX - result (0 = OK, other = error)
  2024. forcedeth_phy_reset:
  2025.  
  2026.         push    ebx ecx edx
  2027.  
  2028.         ; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ);
  2029.         ; EBX - addr, EAX - miireg, ECX - value
  2030.         mov     ebx, dword [forcedeth_phyaddr]
  2031.         mov     eax, MII_BMCR
  2032.         mov     ecx, MII_READ
  2033.         call    forcedeth_mii_rw        ; miicontrol = eax
  2034.  
  2035.         ; miicontrol |= BMCR_RESET;
  2036.         or      eax, BMCR_RESET
  2037.         push    eax
  2038.  
  2039.         ; if (mii_rw(nic, np->phyaddr, MII_BMCR, miicontrol))
  2040.         ; EBX - addr, EAX - miireg, ECX - value
  2041.         mov     ecx, eax
  2042.         mov     eax, MII_BMCR
  2043.         call    forcedeth_mii_rw        ; miicontrol = eax
  2044.  
  2045.         test    eax, eax
  2046.         jz      @f
  2047.         pop     eax
  2048.         mov     eax, 0xffffffff
  2049.         jmp     .return
  2050. @@:
  2051.         pop     eax
  2052.  
  2053.         ; wait for 500ms
  2054.         ; mdelay(500)
  2055.         mov     esi, 500
  2056.         call    forcedeth_udelay
  2057.  
  2058.         ; must wait till reset is deasserted
  2059.         ; while (miicontrol & BMCR_RESET) {
  2060.         mov     edx, 100
  2061. .while_loop:
  2062.         test    eax, BMCR_RESET
  2063.         jz      .while_loop_exit
  2064.  
  2065.         ; mdelay(10);
  2066.         mov     esi, 10
  2067.         call    forcedeth_udelay
  2068.  
  2069.         ; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ);
  2070.         ; EBX - addr, EAX - miireg, ECX - value
  2071.         mov     eax, MII_BMCR
  2072.         mov     ecx, MII_READ
  2073.         call    forcedeth_mii_rw        ; miicontrol = eax
  2074.  
  2075.         ; FIXME: 100 tries seem excessive
  2076.         ; if (tries++ > 100)
  2077.         dec     edx
  2078.         jnz     .while_loop
  2079.         ; return -1;
  2080.         mov     eax, 0xffffffff
  2081.         jmp     .return
  2082. .while_loop_exit:
  2083.         ; return 0
  2084.         mov     eax, 0
  2085. .return:       
  2086.         pop     edx ecx ebx
  2087.         ret
  2088.  
  2089. ; Input:  none
  2090. ; Output: none
  2091. forcedeth_mac_reset:
  2092.         push    esi edi
  2093.  
  2094.         ; dprintf("mac_reset\n")
  2095.         DEBUGF 1," K : FORCEDETH: mac_reset.\n"
  2096.  
  2097.         ; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl)
  2098.         mov     edi, dword [forcedeth_mapio_addr]
  2099.         mov     eax, dword [forcedeth_desc_ver]
  2100.         or      eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET)
  2101.         mov     dword [edi+NvRegTxRxControl], eax
  2102.  
  2103.         ; pci_push(base)
  2104.         call    forcedeth_pci_push
  2105.        
  2106.         ; writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset)
  2107.         mov     dword [edi+NvRegMacReset], NVREG_MAC_RESET_ASSERT
  2108.  
  2109.         ; pci_push(base)
  2110.         call    forcedeth_pci_push
  2111.  
  2112.         ; udelay(NV_MAC_RESET_DELAY)
  2113.         mov     esi, NV_MAC_RESET_DELAY
  2114.         call    forcedeth_nv_udelay
  2115.  
  2116.         ; writel(0, base + NvRegMacReset)
  2117.         mov     dword [edi+NvRegMacReset], 0
  2118.  
  2119.         ; pci_push(base)
  2120.         call    forcedeth_pci_push
  2121.        
  2122.         ; udelay(NV_MAC_RESET_DELAY)
  2123.         mov     esi, NV_MAC_RESET_DELAY
  2124.         call    forcedeth_nv_udelay
  2125.  
  2126.         ; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl)
  2127.         mov     eax, dword [forcedeth_desc_ver]
  2128.         or      eax, NVREG_TXRXCTL_BIT2
  2129.         mov     dword [edi+NvRegTxRxControl], eax
  2130.        
  2131.         ; pci_push(base)
  2132.         call    forcedeth_pci_push
  2133.  
  2134.         pop     edi esi
  2135.         ret
  2136.  
  2137. ; Input:  none
  2138. ; Output: none
  2139. forcedeth_init_ring:
  2140.         push    eax ebx ecx
  2141.  
  2142.         ; np->next_tx = np->nic_tx = 0
  2143.         mov     dword[forcedeth_next_tx], 0
  2144.         mov     dword[forcedeth_nic_tx], 0
  2145.  
  2146.         ; for (i = 0; i < TX_RING; i++)
  2147.         mov     ecx, TX_RING
  2148.  
  2149. .for_loop:
  2150.         ;        tx_ring[i].FlagLen = 0;
  2151.         mov     eax, ecx
  2152.         dec     eax
  2153.         mov     bl, sizeof.forcedeth_TxDesc
  2154.         mul     bl
  2155.         add     eax, forcedeth_tx_ring
  2156.         mov     ebx, eax
  2157.         mov     dword [ebx + forcedeth_TxDesc.FlagLen], 0
  2158.         loop    .for_loop
  2159.  
  2160.         ; np->cur_rx = RX_RING;
  2161.         mov     dword [forcedeth_cur_rx], RX_RING
  2162.         ; np->refill_rx = 0;
  2163.         mov     dword [forcedeth_refill_rx], 0
  2164.        
  2165.         ;for (i = 0; i < RX_RING; i++)
  2166.         mov     ecx, RX_RING
  2167.  
  2168. .for_loop2:
  2169.         ;        rx_ring[i].FlagLen = 0;
  2170.         mov     eax, ecx
  2171.         dec     eax
  2172.         mov     bl, sizeof.forcedeth_RxDesc
  2173.         mul     bl
  2174.         add     eax, forcedeth_rx_ring
  2175.         mov     ebx, eax
  2176.         mov     dword [ebx + forcedeth_RxDesc.FlagLen], 0
  2177.         loop    .for_loop2
  2178.        
  2179.         ; alloc_rx(nic);
  2180.         call    forcedeth_alloc_rx
  2181.  
  2182. .return:
  2183.         pop     ecx ebx eax
  2184.         ret
  2185.  
  2186. ; Input:  none
  2187. ; Output: none
  2188. forcedeth_txrx_reset:
  2189.         push    eax esi edi
  2190.  
  2191.         ; dprintf(("txrx_reset\n"))
  2192.         DEBUGF 1," K : FORCEDETH: txrx_reset.\n"
  2193.  
  2194.         ; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl)
  2195.         mov     edi, dword [forcedeth_mapio_addr]
  2196.         mov     eax, dword [forcedeth_desc_ver]
  2197.         or      eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET)
  2198.         mov     dword [edi+NvRegTxRxControl], eax
  2199.  
  2200.         ; pci_push(base)
  2201.         call    forcedeth_pci_push
  2202.  
  2203.         ; nv_udelay(NV_TXRX_RESET_DELAY)
  2204.         mov     esi, NV_TXRX_RESET_DELAY
  2205.         call    forcedeth_nv_udelay
  2206.  
  2207.         ; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl)
  2208.         mov     eax, dword [forcedeth_desc_ver]
  2209.         or      eax, NVREG_TXRXCTL_BIT2
  2210.         mov     dword [edi+NvRegTxRxControl], eax
  2211.        
  2212.         ; pci_push(base)
  2213.         call    forcedeth_pci_push
  2214.  
  2215. .return:
  2216.         pop     edi esi eax
  2217.         ret
  2218.  
  2219. ; Input:  none
  2220. ; Output: none
  2221. forcedeth_set_multicast:
  2222.         push    edi
  2223.  
  2224.         ; u32 addr[2];
  2225.         ; u32 mask[2];
  2226.         ; u32 pff;
  2227.         ; u32 alwaysOff[2];
  2228.         ; u32 alwaysOn[2];
  2229.         ;
  2230.         ; memset(addr, 0, sizeof(addr));
  2231.         ; memset(mask, 0, sizeof(mask));
  2232.         ;
  2233.         ; pff = NVREG_PFF_MYADDR;
  2234.         ;
  2235.         ; alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0;
  2236.         ;
  2237.         ; addr[0] = alwaysOn[0];
  2238.         ; addr[1] = alwaysOn[1];
  2239.         ; mask[0] = alwaysOn[0] | alwaysOff[0];
  2240.         ; mask[1] = alwaysOn[1] | alwaysOff[1];
  2241.         ;
  2242.         ; addr[0] |= NVREG_MCASTADDRA_FORCE;
  2243.         ; pff |= NVREG_PFF_ALWAYS;
  2244.         ; stop_rx();
  2245.         call    forcedeth_stop_rx
  2246.         ; writel(addr[0], base + NvRegMulticastAddrA);
  2247.         mov     edi, dword [forcedeth_mapio_addr]
  2248.         mov     dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE
  2249.         ; writel(addr[1], base + NvRegMulticastAddrB);
  2250.         mov     dword [edi+NvRegMulticastAddrB], 0
  2251.         ; writel(mask[0], base + NvRegMulticastMaskA);
  2252.         mov     dword [edi+NvRegMulticastMaskA], 0
  2253.         ; writel(mask[1], base + NvRegMulticastMaskB);
  2254.         mov     dword [edi+NvRegMulticastMaskB], 0
  2255.         ; writel(pff, base + NvRegPacketFilterFlags);
  2256.         mov     dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_MYADDR or NVREG_PFF_ALWAYS)
  2257.         ; start_rx(nic);
  2258.         call    forcedeth_start_rx
  2259.  
  2260. .return:
  2261.         pop     edi
  2262.         ret
  2263.  
  2264. ; Input:  none
  2265. ; Output: none
  2266. forcedeth_start_rx:
  2267.         push    edi
  2268.  
  2269.         ; dprintf(("start_rx\n"))
  2270.         DEBUGF 1," K : FORCEDETH: start_rx.\n"
  2271.  
  2272.         ; Already running? Stop it.
  2273.         ; if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) {
  2274.         mov     edi, dword [forcedeth_mapio_addr]
  2275.         mov     eax, dword [edi+NvRegReceiverControl]
  2276.         test    eax, NVREG_RCVCTL_START
  2277.         jz      @f
  2278.         ; writel(0, base + NvRegReceiverControl)
  2279.         mov     dword [edi+NvRegReceiverControl], 0
  2280.         ; pci_push(base)
  2281.         call    forcedeth_pci_push
  2282.  
  2283. @@:
  2284.        
  2285.         ; writel(np->linkspeed, base + NvRegLinkSpeed);
  2286.         mov     eax, dword [forcedeth_linkspeed]
  2287.         mov     dword [edi+NvRegLinkSpeed], eax
  2288.         ; pci_push(base);
  2289.         call    forcedeth_pci_push
  2290.         ; writel(NVREG_RCVCTL_START, base + NvRegReceiverControl);
  2291.         mov     dword [edi+NvRegReceiverControl], NVREG_RCVCTL_START
  2292.         ; pci_push(base);
  2293.         call    forcedeth_pci_push
  2294.  
  2295. .return:
  2296.         pop     edi
  2297.         ret
  2298.  
  2299. ; Input:  none
  2300. ; Output: none
  2301. forcedeth_stop_rx:
  2302.         push    esi edi
  2303.  
  2304.         ; dprintf(("stop_rx\n"))
  2305.         DEBUGF 1," K : FORCEDETH: stop_rx.\n"
  2306.  
  2307.         ; writel(0, base + NvRegReceiverControl)
  2308.         mov     edi, dword [forcedeth_mapio_addr]
  2309.         mov     dword [edi+NvRegReceiverControl], 0
  2310.  
  2311.         push    ebx edx edi     ;;;;;;;;;;;;;;;;;;;;;;
  2312.         ; reg_delay(NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, "stop_rx: ReceiverStatus remained busy");
  2313.         stdcall forcedeth_reg_delay,NvRegReceiverStatus,NVREG_RCVSTAT_BUSY,0,NV_RXSTOP_DELAY1,NV_RXSTOP_DELAY1MAX,0
  2314.         pop     edi edx ebx     ;;;;;;;;;;;;;;;;;;;;;;
  2315.  
  2316.  
  2317.         ; nv_udelay(NV_RXSTOP_DELAY2)
  2318.         mov     esi, NV_RXSTOP_DELAY2
  2319.         call    forcedeth_nv_udelay
  2320.  
  2321.         ; writel(0, base + NvRegLinkSpeed)
  2322.         mov     dword [edi+NvRegLinkSpeed], 0
  2323.  
  2324. .return:
  2325.         pop     edi esi
  2326.         ret
  2327.  
  2328. ; Input:  none
  2329. ; Output: EAX
  2330. forcedeth_update_linkspeed:
  2331.         push    ebx ecx esi edi
  2332.  
  2333.         ; BMSR_LSTATUS is latched, read it twice:
  2334.         ; we want the current value.
  2335.        
  2336.         ; mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ)
  2337.         ;EBX - addr, EAX - miireg, ECX - value
  2338.         mov     ebx, dword [forcedeth_phyaddr]
  2339.         mov     eax, MII_BMSR
  2340.         mov     ecx, MII_READ
  2341.         call    forcedeth_mii_rw
  2342.  
  2343.  
  2344.         ; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ)
  2345.         ;EBX - addr, EAX - miireg, ECX - value
  2346.         mov     ebx, dword [forcedeth_phyaddr]
  2347.         mov     eax, MII_BMSR
  2348.         mov     ecx, MII_READ
  2349.         call    forcedeth_mii_rw        ; mii_status = eax
  2350.        
  2351.         ; yhlu
  2352.  
  2353.         ; for(i=0;i<30;i++) {
  2354.         mov     ecx, 30
  2355. .for_loop:
  2356.         push    ecx
  2357.  
  2358.         ;  mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
  2359.         ;EBX - addr, EAX - miireg, ECX - value
  2360.         ;mov    ebx, dword [forcedeth_phyaddr]
  2361.         mov     eax, MII_BMSR
  2362.         mov     ecx, MII_READ
  2363.         call    forcedeth_mii_rw        ; mii_status = eax
  2364.  
  2365.         ;  if((mii_status & BMSR_LSTATUS) && (mii_status & BMSR_ANEGCOMPLETE)) break;
  2366.         test    eax, BMSR_LSTATUS
  2367.         jz      @f
  2368.         test    eax, BMSR_ANEGCOMPLETE
  2369.         jz      @f
  2370.         ; break
  2371.         pop     ecx
  2372.         jmp     .break
  2373.        
  2374. @@:
  2375.  
  2376.         ;  mdelay(100);
  2377.         push    eax     ; ???
  2378.         mov     esi, 100
  2379.         call    forcedeth_udelay
  2380.         pop     eax     ; ???
  2381.  
  2382.         pop     ecx
  2383.         loop    .for_loop
  2384.  
  2385. .break:
  2386.  
  2387.         ; if (!(mii_status & BMSR_LSTATUS)) {
  2388.         test    eax, BMSR_LSTATUS
  2389.         jnz     @f
  2390.  
  2391.         ; printf("no link detected by phy - falling back to 10HD.\n")
  2392.         DEBUGF 1," K : FORCEDETH: update_linkspeed: no link detected by phy - falling back to 10HD.\n"
  2393.  
  2394.         ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
  2395.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
  2396.  
  2397.         ; newdup = 0;
  2398.         mov     dword [forcedeth_tmp_newdup], 0
  2399.         ; retval = 0;
  2400.         mov     dword [forcedeth_tmp_retval], 0
  2401.  
  2402.         ; goto set_speed;
  2403.         jmp     .set_speed
  2404.  
  2405. @@:
  2406.  
  2407.         ; check auto negotiation is complete
  2408.         ; if (!(mii_status & BMSR_ANEGCOMPLETE)) {
  2409.         test    eax, BMSR_ANEGCOMPLETE
  2410.         jnz     @f
  2411.  
  2412.         ; still in autonegotiation - configure nic for 10 MBit HD and wait.
  2413.         ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
  2414.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
  2415.  
  2416.         ; newdup = 0
  2417.         mov     dword [forcedeth_tmp_newdup], 0
  2418.  
  2419.         ; retval = 0
  2420.         mov     dword [forcedeth_tmp_retval], 0
  2421.  
  2422.         ; printf("autoneg not completed - falling back to 10HD.\n")
  2423.         DEBUGF 1," K : FORCEDETH: update_linkspeed: autoneg not completed - falling back to 10HD.\n"
  2424.  
  2425.         ; goto set_speed
  2426.         jmp     .set_speed
  2427.  
  2428. @@:
  2429.  
  2430.         ; retval = 1
  2431.         mov     dword [forcedeth_tmp_retval], 1
  2432.        
  2433.         ; if (np->gigabit == PHY_GIGABIT) {
  2434.         cmp     dword [forcedeth_gigabit], PHY_GIGABIT
  2435.         jne     .end_if
  2436.         ; control_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ)
  2437.         ;EBX - addr, EAX - miireg, ECX - value
  2438.         ;mov    ebx, dword [forcedeth_phyaddr]
  2439.         mov     eax, MII_1000BT_CR
  2440.         mov     ecx, MII_READ
  2441.         call    forcedeth_mii_rw        ; control_1000 = eax
  2442.         mov     dword [forcedeth_tmp_control_1000], eax
  2443.        
  2444.         ; status_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_SR, MII_READ)
  2445.         ;EBX - addr, EAX - miireg, ECX - value
  2446.         ;mov    ebx, dword [forcedeth_phyaddr]
  2447.         mov     eax, MII_1000BT_SR
  2448.         mov     ecx, MII_READ
  2449.         call    forcedeth_mii_rw        ; status_1000 = eax
  2450.         ;mov    dword [forcedeth_tmp_status_1000], eax
  2451.        
  2452.         ; if ((control_1000 & ADVERTISE_1000FULL) &&
  2453.         ;     (status_1000 & LPA_1000FULL)) {
  2454.         test    eax, LPA_1000FULL
  2455.         jz      .end_if
  2456.         test    dword [forcedeth_tmp_control_1000], ADVERTISE_1000FULL
  2457.         jz      .end_if
  2458.  
  2459.         ; printf ("update_linkspeed: GBit ethernet detected.\n")
  2460.         DEBUGF 1," K : FORCEDETH: update_linkspeed: GBit ethernet detected.\n"
  2461.  
  2462.         ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_1000
  2463.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_1000)
  2464.  
  2465.         ; newdup = 1
  2466.         mov     dword [forcedeth_tmp_newdup], 1
  2467.  
  2468.         ; goto set_speed
  2469.         jmp     .set_speed
  2470.  
  2471. .end_if:
  2472.  
  2473.         ; adv = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ);
  2474.         ;EBX - addr, EAX - miireg, ECX - value
  2475.         ;mov    ebx, dword [forcedeth_phyaddr]
  2476.         mov     eax, MII_ADVERTISE
  2477.         mov     ecx, MII_READ
  2478.         call    forcedeth_mii_rw        ; adv = eax
  2479.         mov     dword [forcedeth_tmp_adv], eax
  2480.  
  2481.         ; lpa = mii_rw(nic, np->phyaddr, MII_LPA, MII_READ);
  2482.         ;EBX - addr, EAX - miireg, ECX - value
  2483.         ;mov    ebx, dword [forcedeth_phyaddr]
  2484.         mov     eax, MII_LPA
  2485.         mov     ecx, MII_READ
  2486.         call    forcedeth_mii_rw        ; lpa = eax
  2487.         mov     dword [forcedeth_tmp_lpa], eax
  2488.  
  2489.         ; dprintf(("update_linkspeed: PHY advertises 0x%hX, lpa 0x%hX.\n", adv, lpa));
  2490.         DEBUGF 1," K : FORCEDETH: update_linkspeed: PHY advertises 0x%x, lpa 0x%x.\n", [forcedeth_tmp_adv]:8, [forcedeth_tmp_lpa]:8
  2491.  
  2492.         ; FIXME: handle parallel detection properly, handle gigabit ethernet
  2493.         ; lpa = lpa & adv
  2494.         mov     eax, dword [forcedeth_tmp_adv]
  2495.         and     dword [forcedeth_tmp_lpa], eax
  2496.  
  2497.         mov     eax, dword [forcedeth_tmp_lpa]
  2498.  
  2499.         ; if (lpa & LPA_100FULL) {
  2500.         test    eax, LPA_100FULL
  2501.         jz      @f
  2502.         ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100
  2503.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100)
  2504.         ; newdup = 1
  2505.         mov     dword [forcedeth_tmp_newdup], 1
  2506.         jmp     .set_speed
  2507. @@:
  2508.         ; } else if (lpa & LPA_100HALF) {
  2509.         test    eax, LPA_100HALF
  2510.         jz      @f
  2511.         ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100
  2512.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100)
  2513.         ; newdup = 0
  2514.         mov     dword [forcedeth_tmp_newdup], 0
  2515.         jmp     .set_speed
  2516. @@:
  2517.         ; } else if (lpa & LPA_10FULL) {
  2518.         test    eax, LPA_10FULL
  2519.         jz      @f
  2520.         ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
  2521.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
  2522.         ; newdup = 1
  2523.         mov     dword [forcedeth_tmp_newdup], 1
  2524.         jmp     .set_speed
  2525. @@:
  2526.         ; } else if (lpa & LPA_10HALF) {
  2527.         test    eax, LPA_10HALF
  2528.         ;    newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
  2529.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
  2530.         ;    newdup = 0;
  2531.         mov     dword [forcedeth_tmp_newdup], 0
  2532.         jmp     .set_speed
  2533. @@:
  2534.         ; } else {
  2535.         ; printf("bad ability %hX - falling back to 10HD.\n", lpa)
  2536.         DEBUGF 1," K : FORCEDETH: update_linkspeed: bad ability 0x%x - falling back to 10HD.\n", eax
  2537.  
  2538.         ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10
  2539.         mov     dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10)
  2540.         ; newdup = 0
  2541.         mov     dword [forcedeth_tmp_newdup], 0
  2542.         ; }
  2543.  
  2544. .set_speed:
  2545.  
  2546.         ; if (np->duplex == newdup && np->linkspeed == newls)
  2547.         mov     eax, dword [forcedeth_tmp_newdup]
  2548.         cmp     eax, dword [forcedeth_duplex]
  2549.         jne     .end_if2
  2550.         mov     eax, dword [forcedeth_tmp_newls]
  2551.         cmp     eax, dword [forcedeth_linkspeed]
  2552.         jne     .end_if2
  2553.         ;    return retval;
  2554.         jmp     .return
  2555.        
  2556. .end_if2:
  2557.        
  2558.         ; dprintf(("changing link setting from %d/%s to %d/%s.\n",
  2559.         ;    np->linkspeed, np->duplex ? "Full-Duplex": "Half-Duplex", newls, newdup ? "Full-Duplex": "Half-Duplex"))
  2560.         DEBUGF 1," K : FORCEDETH: update_linkspeed: changing link from %x/XD to %x/XD.\n", [forcedeth_linkspeed]:8, [forcedeth_tmp_newls]:8     ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2561.        
  2562.         ; np->duplex = newdup
  2563.         mov     eax, dword [forcedeth_tmp_newdup]
  2564.         mov     dword [forcedeth_duplex], eax
  2565.  
  2566.         ; np->linkspeed = newls
  2567.         mov     eax, [forcedeth_tmp_newls]
  2568.         mov     dword [forcedeth_linkspeed], eax
  2569.        
  2570.         ; if (np->gigabit == PHY_GIGABIT) {
  2571.         cmp     dword [forcedeth_gigabit], PHY_GIGABIT
  2572.         jne     .end_if3
  2573.  
  2574.         ; phyreg = readl(base + NvRegRandomSeed);
  2575.         mov     edi, dword [forcedeth_mapio_addr]
  2576.         mov     eax, dword [edi+NvRegRandomSeed]
  2577.  
  2578.         ; phyreg &= ~(0x3FF00);
  2579.         and     eax, not (0x3FF00)
  2580.         mov     ecx, eax                ; phyreg = ecx
  2581.  
  2582.         ; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10)
  2583.         mov     eax, dword [forcedeth_linkspeed]
  2584.         and     eax, 0xFFF
  2585.         cmp     eax, NVREG_LINKSPEED_10
  2586.         jne     @f
  2587.         ; phyreg |= NVREG_RNDSEED_FORCE3
  2588.         or      ecx, NVREG_RNDSEED_FORCE3
  2589.         jmp     .end_if4
  2590. @@:
  2591.         ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
  2592.         cmp     eax, NVREG_LINKSPEED_100
  2593.         jne     @f
  2594.         ; phyreg |= NVREG_RNDSEED_FORCE2
  2595.         or      ecx, NVREG_RNDSEED_FORCE2
  2596.         jmp     .end_if4
  2597. @@:
  2598.         ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
  2599.         cmp     eax, NVREG_LINKSPEED_1000
  2600.         jne     .end_if4
  2601.         ; phyreg |= NVREG_RNDSEED_FORCE
  2602.         or      ecx, NVREG_RNDSEED_FORCE
  2603. .end_if4:
  2604.         ; writel(phyreg, base + NvRegRandomSeed)
  2605.         mov     dword [edi+NvRegRandomSeed], ecx
  2606.  
  2607. .end_if3:
  2608.        
  2609.         ; phyreg = readl(base + NvRegPhyInterface)
  2610.         mov     ecx, dword [edi+NvRegPhyInterface]
  2611.  
  2612.         ; phyreg &= ~(PHY_HALF | PHY_100 | PHY_1000)
  2613.         and     ecx, not (PHY_HALF or PHY_100 or PHY_1000)
  2614.        
  2615.         ; if (np->duplex == 0)
  2616.         cmp     dword [forcedeth_duplex], 0
  2617.         jne     @f
  2618.         ; phyreg |= PHY_HALF
  2619.         or      ecx, PHY_HALF
  2620. @@:
  2621.         ; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
  2622.         mov     eax, dword [forcedeth_linkspeed]
  2623.         and     eax, 0xFFF
  2624.         cmp     eax, NVREG_LINKSPEED_100
  2625.         jne     @f
  2626.         ; phyreg |= PHY_100
  2627.         or      ecx, PHY_100
  2628.         jmp     .end_if5
  2629. @@:
  2630.         ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
  2631.         cmp     eax, NVREG_LINKSPEED_1000
  2632.         jne     .end_if5
  2633.         ; phyreg |= PHY_1000
  2634.         or      ecx, PHY_1000
  2635.  
  2636. .end_if5:
  2637.  
  2638.         ; writel(phyreg, base + NvRegPhyInterface)
  2639.         mov     dword [edi+NvRegPhyInterface], ecx
  2640.                
  2641.         ; writel(NVREG_MISC1_FORCE | (np->duplex ? 0 : NVREG_MISC1_HD), base + NvRegMisc1);
  2642.         cmp     dword [forcedeth_duplex], 0
  2643.         je      @f
  2644.         mov     ecx, 0
  2645.         jmp     .next
  2646. @@:
  2647.         mov     ecx, NVREG_MISC1_HD
  2648. .next:
  2649.         or      ecx, NVREG_MISC1_FORCE
  2650.         mov     dword [edi+NvRegMisc1], ecx
  2651.  
  2652.         ; pci_push(base)
  2653.         call    forcedeth_pci_push
  2654.  
  2655.         ; writel(np->linkspeed, base + NvRegLinkSpeed)
  2656.         mov     eax, dword [forcedeth_linkspeed]
  2657.         mov     dword [edi+NvRegLinkSpeed], eax
  2658.  
  2659.         ; pci_push(base)
  2660.         call    forcedeth_pci_push
  2661.  
  2662. .return:
  2663.         ; return retval
  2664.         mov     eax, dword [forcedeth_tmp_retval]
  2665.         pop     edi esi ecx ebx
  2666.         ret
  2667.  
  2668.        
  2669. ; Input:  none
  2670. ; Output: none
  2671. forcedeth_start_tx:
  2672.         push    edi
  2673.         ; dprintf(("start_tx\n"))
  2674.         DEBUGF 1," K : FORCEDETH: start_tx.\n"
  2675.  
  2676.         ; writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl)
  2677.         mov     edi, dword [forcedeth_mapio_addr]
  2678.         mov     dword [edi+NvRegTransmitterControl], NVREG_XMITCTL_START
  2679.  
  2680.         ; pci_push(base)
  2681.         call    forcedeth_pci_push
  2682.  
  2683. .return:
  2684.         pop     edi
  2685.         ret
  2686.  
  2687. ; Interrupt handler
  2688. forcedeth_int_handler:
  2689.         DEBUGF 1," K : FORCEDETH: interrupt handler.\n"
  2690.  
  2691.         ret
  2692.        
  2693.