Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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