Subversion Repositories Kolibri OS

Rev

Rev 3545 | Rev 4467 | Go to most recent revision | Blame | Compare with Previous | 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__         = 2
  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.unload], .fail
  539.         mov     [device.name], my_service
  540.  
  541. ; save the pci bus and device numbers
  542.  
  543.         mov     eax, [IOCTL.input]
  544.         movzx   ecx, byte [eax+1]
  545.         mov     [device.pci_bus], ecx
  546.         movzx   ecx, byte [eax+2]
  547.         mov     [device.pci_dev], ecx
  548.  
  549.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x\n", [device.pci_dev], [device.pci_bus]
  550.  
  551. ; Ok, the eth_device structure is ready, let's probe the device
  552.         call    probe                                                   ; this function will output in eax
  553.         test    eax, eax
  554.         jnz     .err                                                    ; If an error occured, exit
  555.  
  556.         mov     eax, [devices]                                          ; Add the device structure to our device list
  557.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  558.         inc     [devices]                                               ;
  559.  
  560.         mov     [device.type], NET_TYPE_ETH
  561.         call    NetRegDev
  562.  
  563.         cmp     eax, -1
  564.         je      .destroy
  565.  
  566.         ret
  567.  
  568. ; If the device was already loaded, find the device number and return it in eax
  569.  
  570.   .find_devicenum:
  571.         DEBUGF  1,"Trying to find device number of already registered device\n"
  572.         call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  573.                                                                         ; into a device number in edi
  574.         mov     eax, edi                                                ; Application wants it in eax instead
  575.         DEBUGF  1,"Kernel says: %u\n", eax
  576.         ret
  577.  
  578. ; If an error occured, remove all allocated data and exit (returning -1 in eax)
  579.  
  580.   .destroy:
  581.         ; todo: reset device into virgin state
  582.  
  583.   .err:
  584.         stdcall KernelFree, ebx
  585.   .fail:
  586.  
  587.         ret
  588.  
  589. ;------------------------------------------------------
  590. endp
  591.  
  592.  
  593. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  594. ;;                                                                        ;;
  595. ;;        Actual Hardware dependent code starts here                      ;;
  596. ;;                                                                        ;;
  597. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  598.  
  599.  
  600.  
  601.  
  602. ;***************************************************************************
  603. ;   Function
  604. ;      probe
  605. ;   Description
  606. ;      Searches for an ethernet card, enables it and clears the rx buffer
  607. ;
  608. ;***************************************************************************
  609. align 4
  610. probe:
  611.  
  612.         DEBUGF  1,"probe\n"
  613.  
  614.         mov     [device.needs_mac_reset], 0
  615.  
  616.         PCI_make_bus_master
  617.         PCI_adjust_latency  32
  618.         PCI_find_mmio32
  619.  
  620.         DEBUGF 1,"mmio_addr= 0x%x\n", [device.mmio_addr]:8
  621.  
  622.         stdcall MapIoMem, [device.mmio_addr], 2048, (PG_SW + PG_NOCACHE)
  623.         test    eax, eax
  624.         jz      fail
  625.         mov     [device.mmio_addr], eax
  626.         mov     edi, eax
  627.  
  628.         DEBUGF 1,"mapped mmio_addr= 0x%x\n", [device.mmio_addr]:8
  629.  
  630. ;-------------------------------------
  631. ; handle different descriptor versions
  632.         mov     [device.desc_ver], DESC_VER_1
  633.         movzx   eax, [device.device_id]
  634.         cmp     eax, PCI_DEVICE_ID_NVIDIA_NVENET_1
  635.         je      .ver1
  636.         cmp     eax, PCI_DEVICE_ID_NVIDIA_NVENET_2
  637.         je      .ver1
  638.         cmp     eax, PCI_DEVICE_ID_NVIDIA_NVENET_3
  639.         je      .ver1
  640.         mov     [device.desc_ver], DESC_VER_2
  641.   .ver1:
  642.  
  643.         call    read_mac
  644.  
  645.         ; disable WOL
  646.         mov     [WakeUpFlags], 0
  647.         mov     [device.wolenabled], 0
  648.        
  649.         mov     [device.txflags], (NV_TX2_LASTPACKET or NV_TX2_VALID)
  650.         cmp     [device.desc_ver], DESC_VER_1
  651.         jne     @f
  652.         mov     [device.txflags], (NV_TX_LASTPACKET or NV_TX_VALID)
  653.       @@:
  654.  
  655. ; BEGIN of switch (pci->dev_id)
  656.  
  657.         cmp     [device.device_id], 0x01C3
  658.         jne     .next_0x0066
  659.         ; nforce
  660.         mov     [device.irqmask], 0    ;;;;;;;;;;;;;;;(IRQMASK_WANTED_2 or IRQ_TIMER)
  661.         jmp     .find_phy
  662.  
  663.   .next_0x0066:
  664.         cmp     [device.device_id], 0x0066
  665.         je      @f
  666.         cmp     [device.device_id], 0x00D6
  667.         je      @f
  668.         jmp     .next_0x0086
  669.   @@:
  670.         mov     [device.irqmask], 0    ;;;;;;;;;;;;;;;;(IRQMASK_WANTED_2 or IRQ_TIMER)
  671.         cmp     [device.desc_ver], DESC_VER_1
  672.         jne     @f
  673.         or      [device.txflags], NV_TX_LASTPACKET1
  674.         jmp     .find_phy
  675.   @@:
  676.         or      [device.txflags], NV_TX2_LASTPACKET1
  677.         jmp     .find_phy
  678.  
  679.   .next_0x0086:
  680.         cmp     [device.device_id], 0x0086
  681.         je      @f
  682.         cmp     [device.device_id], 0x008c
  683.         je      @f
  684.         cmp     [device.device_id], 0x00e6
  685.         je      @f
  686.         cmp     [device.device_id], 0x00df
  687.         je      @f
  688.         cmp     [device.device_id], 0x0056
  689.         je      @f
  690.         cmp     [device.device_id], 0x0057
  691.         je      @f
  692.         cmp     [device.device_id], 0x0037
  693.         je      @f
  694.         cmp     [device.device_id], 0x0038
  695.         je      @f
  696.         jmp     .find_phy
  697.  
  698.       @@:
  699.         mov     [device.irqmask], 0    ;;;;;;;;;;;;;;;;(IRQMASK_WANTED_2 or IRQ_TIMER)
  700.  
  701.         cmp     [device.desc_ver], DESC_VER_1
  702.         jne     @f
  703.         or      [device.txflags], NV_TX_LASTPACKET1
  704.         jmp     .find_phy
  705.        @@:
  706.         or      [device.txflags], NV_TX2_LASTPACKET1
  707.         jmp     .find_phy
  708.  
  709. .next_0x0268:
  710. ;       cmp     word [device_id], 0x0268
  711. ;       je      @f
  712. ;       cmp     word [device_id], 0x0269
  713. ;       je      @f
  714. ;       cmp     word [device_id], 0x0372
  715. ;       je      @f
  716. ;       cmp     word [device_id], 0x0373
  717. ;       je      @f
  718. ;       jmp     .default_switch
  719. ;@@:
  720.         cmp     [device.device_id], 0x0268
  721.         jb      .undefined
  722.  
  723. ; Get device revision
  724.  
  725.         stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REVISION_ID
  726.  
  727. ; take phy and nic out of low power mode
  728.         mov     ecx, [PowerState2]
  729.         and     ecx, not POWERSTATE2_POWERUP_MASK
  730.         cmp     [device.device_id], PCI_DEVICE_ID_NVIDIA_NVENET_12
  731.         jne     @f
  732.         cmp     [device.device_id], PCI_DEVICE_ID_NVIDIA_NVENET_13
  733.         jne     @f
  734.         cmp     al, 0xA3
  735.         jb      @f
  736.         or      ecx, POWERSTATE2_POWERUP_REV_A3
  737.        @@:
  738.         mov     [PowerState2], ecx
  739.  
  740.         ; DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ
  741.         mov     [device.irqmask], 0    ;;;;;;;;;;;;;;;;(IRQMASK_WANTED_2 or IRQ_TIMER)
  742.        
  743.         mov     [device.needs_mac_reset], 1
  744.         cmp     [device.desc_ver], DESC_VER_1
  745.         jne     @f
  746.         or      [device.txflags], NV_TX_LASTPACKET1
  747.         jmp     .find_phy
  748.        @@:
  749.         cmp     [device.desc_ver], DESC_VER_2
  750.         jne     .undefined
  751.         or      [device.txflags], NV_TX2_LASTPACKET1
  752.         jmp     .find_phy
  753.  
  754.   .undefined:
  755.         DEBUGF 1,"Your card was undefined in this driver.\n"
  756.         DEBUGF 1,"Review driver_data in Kolibri driver and send a patch\n"
  757.  
  758. ; Find a suitable phy
  759. ; Start with address 1 to 31, then do 0, then fail
  760.  
  761.   .find_phy:
  762.         xor     edx, edx
  763.   .phy_loop:
  764.         inc     edx
  765.         and     edx, 0x1f       ; phyaddr = i & 0x1f
  766.         mov     eax, MII_PHYSID1
  767.         mov     ecx, MII_READ
  768.         call    mii_rw          ; EDX - addr, EAX - miireg, ECX - value
  769.  
  770.         cmp     eax, 0xffff
  771.         je      .try_next
  772.         cmp     eax, 0
  773.         jl      .try_next
  774.         mov     esi, eax
  775.  
  776.         mov     eax, MII_PHYSID2
  777.         mov     ecx, MII_READ
  778.         call    mii_rw
  779.  
  780.         cmp     eax, 0xffff
  781.         je      .try_next
  782.         cmp     eax, 0
  783.         jl      .try_next
  784.         jmp     .got_it
  785.  
  786.   .try_next:
  787.         test    edx, edx
  788.         jnz     .phy_loop
  789.  
  790.         ; PHY in isolate mode? No phy attached and user wants to test loopback?
  791.         ; Very odd, but can be correct.
  792.        
  793.         DEBUGF 1,"Could not find a valid PHY.\n"
  794.         jmp     .no_phy
  795.  
  796.   .got_it:
  797.  
  798.         and     esi, PHYID1_OUI_MASK
  799.         shl     esi, PHYID1_OUI_SHFT
  800.  
  801.         and     eax, PHYID2_OUI_MASK
  802.         shr     eax, PHYID2_OUI_SHFT
  803.  
  804.         DEBUGF 1,"Found PHY 0x%x:0x%x at address 0x%x\n", esi:8, eax:8, edx
  805.  
  806.         mov     [device.phyaddr], edx
  807.         or      eax, esi
  808.         mov     [device.phy_oui], eax
  809.  
  810.         call    phy_init
  811.  
  812.   .no_phy:
  813.  
  814.         cmp     [device.needs_mac_reset], 0
  815.         je      @f
  816.         call    mac_reset
  817.   @@:
  818.        
  819. ;***************************************************************************
  820. ;   Function
  821. ;      reset
  822. ;   Description
  823. ;      Place the chip (ie, the ethernet card) into a virgin state
  824. ;      No inputs
  825. ;      All registers destroyed
  826. ;
  827. ;***************************************************************************
  828. reset:
  829.  
  830.         DEBUGF  1,"Resetting\n"
  831.  
  832.         stdcall PciRead8, [device.pci_bus], [device.pci_dev], PCI_REG_IRQ
  833.         movzx   eax, al
  834.         stdcall AttachIntHandler, eax, int_handler, dword 0
  835.         test    eax, eax
  836.         jnz     @f
  837.         DEBUGF  1,"\nCould not attach int handler!\n"
  838. ;        or      eax, -1
  839. ;        ret
  840.        @@:
  841.  
  842. ; erase previous misconfiguration
  843.  
  844.         mov     edi, [device.mmio_addr]
  845.         mov     [MulticastAddrA], MCASTADDRA_FORCE
  846.         mov     [MulticastAddrB], 0
  847.         mov     [MulticastMaskA], 0
  848.         mov     [MulticastMaskB], 0
  849.         mov     [PacketFilterFlags], 0
  850.         mov     [TransmitterControl], 0
  851.         mov     [ReceiverControl], 0
  852.         mov     [AdapterControl], 0
  853.  
  854. ; initialize descriptor rings
  855.  
  856.         call    init_ring
  857.  
  858.         mov     [LinkSpeed], 0
  859.         mov     [UnknownTransmitterReg], 0
  860.  
  861.         call    txrx_reset
  862.        
  863.         mov     [UnknownSetupReg6], 0
  864.         mov     [device.in_shutdown], 0
  865.  
  866. ; give hw rings
  867.  
  868.         lea     eax, [device.rx_ring]
  869.         GetRealAddr
  870.         mov     [RxRingPhysAddr], eax
  871.  
  872.         lea     eax, [device.tx_ring]
  873.         GetRealAddr
  874.         mov     [TxRingPhysAddr], eax
  875.  
  876.         mov     [RingSizes], (((RX_RING - 1) shl RINGSZ_RXSHIFT) + ((TX_RING - 1) shl RINGSZ_TXSHIFT))
  877.  
  878. ;
  879.  
  880.         mov     [device.linkspeed], (LINKSPEED_FORCE or LINKSPEED_10)
  881.         mov     [device.duplex], 0
  882.         mov     [LinkSpeed], (LINKSPEED_FORCE or LINKSPEED_10)
  883.         mov     [UnknownSetupReg3], UNKSETUP3_VAL1
  884.  
  885.         mov     eax, [device.desc_ver]
  886.         mov     [TxRxControl], eax
  887.         call    pci_push
  888.         or      eax, TXRXCTL_BIT1
  889.         mov     [TxRxControl], eax
  890.  
  891.         stdcall reg_delay, UnknownSetupReg5-edi, UNKSETUP5_BIT31, UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, 0
  892.  
  893.         mov     [UnknownSetupReg4], 0
  894.         mov     [MIIStatus], MIISTAT_MASK2
  895.  
  896. ;
  897.        
  898.         mov     [Misc1], (MISC1_FORCE or MISC1_HD)
  899.  
  900.         mov     eax, [TransmitterStatus]
  901.         mov     [TransmitterStatus], eax
  902.  
  903.         mov     [PacketFilterFlags], PFF_ALWAYS
  904.  
  905.         mov     [OffloadConfig], OFFLOAD_NORMAL
  906.  
  907.         mov     eax, [ReceiverStatus]
  908.         mov     [ReceiverStatus], eax
  909.  
  910. ; set random seed
  911.         push    ebx
  912.         stdcall GetTimerTicks   ; bad idea, driver is started at system startup in 90% of cases..
  913.         pop     ebx
  914.  
  915.         mov     edi, [device.mmio_addr]
  916.  
  917.         and     eax, RNDSEED_MASK
  918.         or      eax, RNDSEED_FORCE
  919.         mov     [RandomSeed], eax
  920.  
  921.         mov     [UnknownSetupReg1], UNKSETUP1_VAL
  922.         mov     [UnknownSetupReg2], UNKSETUP2_VAL
  923.         mov     [PollingInterval], POLL_DEFAULT
  924.         mov     [UnknownSetupReg6], UNKSETUP6_VAL
  925.  
  926.         mov     eax, [device.phyaddr]
  927.         shl     eax, ADAPTCTL_PHYSHIFT
  928.         or      eax, (ADAPTCTL_PHYVALID or ADAPTCTL_RUNNING)
  929.         mov     [AdapterControl], eax
  930.  
  931.         mov     [MIISpeed], (MIISPEED_BIT8 or MIIDELAY)
  932.         mov     [UnknownSetupReg4], UNKSETUP4_VAL
  933.         mov     [WakeUpFlags], WAKEUPFLAGS_VAL
  934.        
  935.         or      [PowerState], POWERSTATE_POWEREDUP
  936.         call    pci_push
  937.  
  938.         mov     esi, 10
  939.         call    Sleep
  940.  
  941.         or      [PowerState], POWERSTATE_VALID
  942.         mov     [IrqMask], 0
  943.  
  944. ;;;     ; ??? Mask RX interrupts
  945.         mov      [IrqMask], IRQ_RX_ALL + IRQ_TX_ALL
  946. ;;;     ; ??? Mask TX interrupts
  947. ;;;     mov      [IrqMask], IRQ_TX_ALL
  948. ;;;     ; ??? Mask OTHER interrupts
  949. ;;;     mov      [IrqMask], IRQ_OTHER_ALL
  950.         call    pci_push
  951.  
  952.         mov     [MIIStatus], MIISTAT_MASK2
  953.         mov     [IrqStatus], IRQSTAT_MASK
  954.         call    pci_push
  955.  
  956.         mov     [MulticastAddrA], MCASTADDRA_FORCE
  957.         mov     [MulticastAddrB], 0
  958.         mov     [MulticastMaskA], 0
  959.         mov     [MulticastMaskB], 0
  960.  
  961.         mov     [PacketFilterFlags], (PFF_ALWAYS or PFF_MYADDR)
  962.  
  963.         call    set_multicast
  964.        
  965.         ; One manual link speed update: Interrupts are enabled, future link
  966.         ; speed changes cause interrupts and are handled by nv_link_irq().
  967.  
  968.         mov     eax, [MIIStatus]
  969.         mov     [MIIStatus], MIISTAT_MASK
  970.         DEBUGF  1,"startup: got 0x%x\n", eax
  971.  
  972.         call    update_linkspeed
  973.  
  974.         mov     [TransmitterControl], XMITCTL_START       ; start TX
  975.         call    pci_push
  976.  
  977.         mov     [device.nocable], 0
  978.         test    eax, eax
  979.         jnz     .return
  980.         DEBUGF  1,"no link during initialization.\n"
  981.         mov     [device.nocable], 1
  982.  
  983.   .return:
  984.         xor     eax, eax        ; Indicate that we have successfully reset the card
  985.         mov     [device.mtu], 1514 ;;; FIXME
  986.  
  987. ; Set link state to unknown
  988.         mov     [device.state], ETH_LINK_UNKOWN
  989.  
  990.         ret
  991.  
  992.  
  993. fail:
  994.         or      eax, -1
  995.  
  996.         ret
  997.  
  998. ;--------------------------------------------------------
  999. ;
  1000. ; MII_RW
  1001. ;
  1002. ; read/write a register on the PHY.
  1003. ; Caller must guarantee serialization
  1004. ; Input:  EAX - miireg, EDX - addr, ECX - value
  1005. ; Output: EAX - retval
  1006. ;
  1007. ;--------------------------------------------------------
  1008.  
  1009. mii_rw:
  1010.  
  1011.         DEBUGF  1,"mii_rw: 0x%x to reg %d at PHY %d\n", ecx, eax, edx
  1012.  
  1013.         push    edx
  1014.  
  1015.         mov     edi, [device.mmio_addr]
  1016.         mov     [MIIStatus], MIISTAT_MASK
  1017.  
  1018.         test    [MIIControl], MIICTL_INUSE
  1019.         jz      @f
  1020.         mov     [MIIControl], MIICTL_INUSE
  1021.  
  1022.         mov     esi, NV_MIIBUSY_DELAY
  1023.         call    Sleep
  1024.        @@:
  1025.  
  1026.         shl     edx, MIICTL_ADDRSHIFT
  1027.         or      edx, eax
  1028.  
  1029.         cmp     ecx, MII_READ
  1030.         je      @f
  1031.  
  1032.         mov     [MIIData], ecx
  1033.         or      edx, MIICTL_WRITE
  1034.        @@:
  1035.         mov     [MIIControl], edx
  1036.  
  1037.         stdcall reg_delay, MIIControl-edi, MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, 0
  1038.  
  1039.         test    eax, eax
  1040.         jz      @f
  1041.         DEBUGF  1,"mii_rw timed out.\n"
  1042.         or      eax, -1
  1043.         jmp     .return
  1044.        @@:
  1045.  
  1046.         cmp     ecx, MII_READ
  1047.         je      @f
  1048. ; it was a write operation - fewer failures are detectable
  1049.         DEBUGF  1,"mii_rw write: ok\n"
  1050.         xor     eax, eax
  1051.         jmp     .return
  1052.        @@:
  1053.  
  1054.         mov     eax, [MIIStatus]
  1055.         test    eax, MIISTAT_ERROR
  1056.         jz      @f
  1057.         DEBUGF  1,"mii read: failed.\n"
  1058.         or      eax, -1
  1059.         jmp     .return
  1060.        @@:
  1061.  
  1062.         mov     eax, [MIIData]
  1063.         DEBUGF  1,"mii read: 0x%x.\n", eax
  1064.  
  1065.   .return:
  1066.         pop     edx
  1067.         ret
  1068.  
  1069.  
  1070.  
  1071.  
  1072.  
  1073. ; Input:  offset:word, mask:dword, target:dword, delay:word, delaymax:word, msg:dword
  1074. ; Output: EAX - 0|1
  1075.  
  1076. proc    reg_delay, offset:dword, mask:dword, target:dword, delay:dword, delaymax:dword, msg:dword
  1077.  
  1078. ;        DEBUGF  1,"reg_delay\n"
  1079.  
  1080.         push    esi
  1081.         call    pci_push
  1082.  
  1083.   .loop:
  1084.         mov     esi, [delay]
  1085.         call    Sleep
  1086.         mov     eax, [delaymax]
  1087.         sub     eax, [delay]
  1088.         mov     [delaymax], eax
  1089.  
  1090.         cmp     eax, 0
  1091.         jl      .fail
  1092.  
  1093.         mov     eax, [offset]
  1094.         mov     eax, [edi + eax]
  1095.         and     eax, [mask]
  1096.         cmp     eax, [target]
  1097.         jne     .loop
  1098.  
  1099.         pop     esi
  1100.         xor     eax, eax
  1101.         ret
  1102.  
  1103.   .fail:
  1104.         pop     esi
  1105.         xor     eax, eax
  1106.         inc     eax
  1107.         ret
  1108.  
  1109. endp
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115. ; Input:  none
  1116. ; Output: EAX - result (0 = OK, other = error)
  1117. phy_init:
  1118.  
  1119.         push    ebx ecx
  1120.        
  1121.         ; set advertise register
  1122.         mov     edx, [device.phyaddr]
  1123.         mov     eax, MII_ADVERTISE
  1124.         mov     ecx, MII_READ
  1125.         call    mii_rw
  1126.  
  1127.         or      eax, (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or 0x800 or 0x400)
  1128.  
  1129.         mov     ecx, eax
  1130.         mov     eax, MII_ADVERTISE
  1131.         call    mii_rw
  1132.  
  1133.         test    eax, eax
  1134.         jz      @f
  1135.  
  1136.         DEBUGF  1,"phy write to advertise failed.\n"
  1137.  
  1138.         mov     eax, PHY_ERROR
  1139.         jmp     .return
  1140.        @@:
  1141.  
  1142.         ; get phy interface type
  1143.         mov     edi, [device.mmio_addr]
  1144.         mov     eax, [PhyInterface]
  1145.         DEBUGF  1,"phy interface type = 0x%x\n", eax:8
  1146.  
  1147.         ; see if gigabit phy
  1148.         mov     eax, MII_BMSR
  1149.         mov     ecx, MII_READ
  1150.         call    mii_rw
  1151.        
  1152.         test    eax, PHY_GIGABIT
  1153.         jnz     .gigabit
  1154.         mov     [device.gigabit], 0
  1155.         jmp     .next_if
  1156.  
  1157.   .gigabit:
  1158.         mov     [device.gigabit], PHY_GIGABIT
  1159.  
  1160.         mov     eax, MII_1000BT_CR
  1161.         mov     ecx, MII_READ
  1162.         call    mii_rw
  1163.        
  1164.         and     eax, (not ADVERTISE_1000HALF)
  1165.  
  1166.         test    [PhyInterface], PHY_RGMII
  1167.         jz      @f
  1168.         or      eax, ADVERTISE_1000FULL
  1169.         jmp     .next
  1170.        @@:
  1171.  
  1172.         and     eax, (not ADVERTISE_1000FULL)
  1173.  
  1174.   .next:
  1175.         mov     ecx, eax
  1176.         mov     eax, MII_1000BT_CR
  1177.         call    mii_rw
  1178.  
  1179.         test    eax, eax
  1180.         jz      .next_if
  1181.  
  1182.         DEBUGF 1,"phy init failed.\n"
  1183.  
  1184.         mov     eax, PHY_ERROR
  1185.         jmp     .return
  1186.  
  1187.   .next_if:
  1188.  
  1189.         call    phy_reset
  1190.         test    eax, eax
  1191.         jz      @f
  1192.  
  1193.         DEBUGF 1,"phy reset failed.\n"
  1194.  
  1195.         mov     eax, PHY_ERROR
  1196.         jmp     .return
  1197.        @@:
  1198.  
  1199.         ; phy vendor specific configuration
  1200.         cmp     [device.phy_oui], PHY_OUI_CICADA
  1201.         jne     .next_if2
  1202.         test    [PhyInterface], PHY_RGMII
  1203.         jz      .next_if2
  1204.  
  1205.         mov     eax, MII_RESV1
  1206.         mov     ecx, MII_READ
  1207.         call    mii_rw
  1208.  
  1209.         and     eax, (not (PHY_INIT1 or PHY_INIT2))
  1210.         or      eax, (PHY_INIT3 or PHY_INIT4)
  1211.         mov     ecx, eax
  1212.         mov     eax, MII_RESV1
  1213.         call    mii_rw
  1214.  
  1215.         test    eax, eax
  1216.         jz      @f
  1217.  
  1218.         DEBUGF 1,"phy init failed.\n"
  1219.  
  1220.         mov     eax, PHY_ERROR
  1221.         jmp     .return
  1222.        @@:
  1223.  
  1224.         mov     eax, MII_NCONFIG
  1225.         mov     ecx, MII_READ
  1226.         call    mii_rw
  1227.  
  1228.         or      eax, PHY_INIT5
  1229.         mov     ecx, eax
  1230.         mov     eax, MII_NCONFIG
  1231.         call    mii_rw
  1232.         test    eax, eax
  1233.         jz      .next_if2
  1234.  
  1235.         DEBUGF 1,"phy init failed.\n"
  1236.  
  1237.         mov     eax, PHY_ERROR
  1238.         jmp     .return
  1239.  
  1240.  
  1241.  
  1242.   .next_if2:
  1243.  
  1244.         cmp     [device.phy_oui], PHY_OUI_CICADA
  1245.         jne     .restart
  1246.        
  1247.         mov     eax, MII_SREVISION
  1248.         mov     ecx, MII_READ
  1249.         call    mii_rw
  1250.        
  1251.         or      eax, PHY_INIT6
  1252.         mov     ecx, eax
  1253.         mov     eax, MII_SREVISION
  1254.         call    mii_rw
  1255.         test    eax, eax
  1256.         jz      .restart
  1257.  
  1258.         DEBUGF 1,"phy init failed.\n"
  1259.  
  1260.         jmp     .return
  1261.  
  1262.   .restart:
  1263.         ; restart auto negotiation
  1264.  
  1265.         mov     eax, MII_BMCR
  1266.         mov     ecx, MII_READ
  1267.         call    mii_rw
  1268.  
  1269.         or      eax, (BMCR_ANRESTART or BMCR_ANENABLE)
  1270.         mov     ecx, eax
  1271.         mov     eax, MII_BMCR
  1272.         call    mii_rw
  1273.         test    eax, eax
  1274.         jz      .ok
  1275.  
  1276.         mov     eax, PHY_ERROR
  1277.         jmp     .return
  1278.  
  1279.   .ok:
  1280.         xor     eax, eax
  1281.   .return:
  1282.         pop     ecx ebx
  1283.  
  1284.         ret
  1285.  
  1286.  
  1287. ; Input:  none
  1288. ; Output: EAX - result (0 = OK, other = error)
  1289. phy_reset:
  1290.  
  1291.         DEBUGF  1,"phy_reset\n"
  1292.  
  1293.         push    ebx ecx edx
  1294.  
  1295.         mov     edx, [device.phyaddr]
  1296.         mov     eax, MII_BMCR
  1297.         mov     ecx, MII_READ
  1298.         call    mii_rw
  1299.  
  1300.         or      eax, BMCR_RESET
  1301.         push    eax
  1302.         mov     ecx, eax
  1303.         mov     eax, MII_BMCR
  1304.         call    mii_rw
  1305.  
  1306.         test    eax, eax
  1307.         jz      @f
  1308.  
  1309.         pop     eax
  1310.         mov     eax, 0xffffffff
  1311.         jmp     .return
  1312.        @@:
  1313.  
  1314.         pop     eax
  1315.  
  1316.         mov     esi, 500
  1317.         call    Sleep
  1318.  
  1319.         ; must wait till reset is deasserted
  1320.         mov     esi, 100        ; FIXME: 100 tries seem excessive
  1321.   .while_loop:
  1322.         test    eax, BMCR_RESET
  1323.         jz      .while_loop_exit
  1324.  
  1325.         push    esi
  1326.         mov     esi, 10
  1327.         call    Sleep
  1328.         pop     esi
  1329.  
  1330.         mov     eax, MII_BMCR
  1331.         mov     ecx, MII_READ
  1332.         call    mii_rw
  1333.  
  1334.         dec     esi
  1335.         jnz     .while_loop
  1336.  
  1337.         mov     eax, 0xffffffff
  1338.         jmp     .return
  1339.  
  1340.   .while_loop_exit:
  1341.         xor     eax, eax
  1342.   .return:
  1343.         pop     edx ecx ebx
  1344.  
  1345.         ret
  1346.  
  1347.  
  1348. align 4
  1349. pci_push:
  1350.  
  1351.         push    eax
  1352.         mov     eax, [edi]
  1353.         pop     eax
  1354.  
  1355.         ret
  1356.  
  1357.  
  1358.  
  1359.  
  1360. align 4
  1361. mac_reset:
  1362.  
  1363.         push    esi edi
  1364.  
  1365.         DEBUGF  1,"mac_reset.\n"
  1366.  
  1367.         mov     edi, [device.mmio_addr]
  1368.         mov     eax, [device.desc_ver]
  1369.         or      eax, (TXRXCTL_BIT2 or TXRXCTL_RESET)
  1370.         mov     [TxRxControl], eax
  1371.         call    pci_push
  1372.  
  1373.         mov     [MacReset], MAC_RESET_ASSERT
  1374.         call    pci_push
  1375.  
  1376.         mov     esi, NV_MAC_RESET_DELAY
  1377.         call    Sleep
  1378.  
  1379.         mov     [MacReset], 0
  1380.         call    pci_push
  1381.  
  1382.         mov     esi, NV_MAC_RESET_DELAY
  1383.         call    Sleep
  1384.  
  1385.         mov     eax, [device.desc_ver]
  1386.         or      eax, TXRXCTL_BIT2
  1387.         mov     [TxRxControl], eax
  1388.         call    pci_push
  1389.  
  1390.         pop     edi esi
  1391.  
  1392.         ret
  1393.  
  1394.  
  1395.  
  1396.  
  1397.  
  1398. align 4
  1399. init_ring:
  1400.  
  1401.         DEBUGF  1,"init rings\n"
  1402.         push    eax esi ecx
  1403.  
  1404.         mov     [device.next_tx], 0
  1405.  
  1406.         mov     ecx, TX_RING
  1407.         lea     esi, [device.tx_ring]
  1408.   .tx_loop:
  1409.         mov     [esi + TxDesc.FlagLen], 0
  1410.         add     esi, sizeof.TxDesc
  1411.         dec     ecx
  1412.         jnz     .tx_loop
  1413.  
  1414.         mov     [device.cur_rx], 0
  1415.  
  1416.         mov     ecx, RX_RING
  1417.         lea     esi, [device.rx_ring]
  1418.   .rx_loop:
  1419.         push    ecx esi
  1420.         stdcall KernelAlloc, 4096 shl RBLEN             ; push/pop esi not needed, but just in case...
  1421.         pop     esi
  1422.         mov     [esi + RX_RING*sizeof.RxDesc], eax
  1423.         GetRealAddr
  1424.         mov     [esi + RxDesc.PacketBuffer], eax
  1425.         mov     [esi + RxDesc.FlagLen], (4096 shl RBLEN or NV_RX_AVAIL)
  1426.         add     esi, sizeof.RxDesc
  1427.         pop     ecx
  1428.         dec     ecx
  1429.         jnz     .rx_loop
  1430.        
  1431.         pop     ecx esi eax
  1432.  
  1433.         ret
  1434.  
  1435.  
  1436.  
  1437.  
  1438.  
  1439. ; Input:  none
  1440. ; Output: none
  1441. align 4
  1442. txrx_reset:
  1443.  
  1444.         push    eax esi
  1445.  
  1446.         DEBUGF 1,"txrx_reset\n"
  1447.  
  1448.         mov     edi, [device.mmio_addr]
  1449.         mov     eax, [device.desc_ver]
  1450.         or      eax, (TXRXCTL_BIT2 or TXRXCTL_RESET)
  1451.         mov     [TxRxControl], eax
  1452.         call    pci_push
  1453.  
  1454.         mov     esi, NV_TXRX_RESET_DELAY
  1455.         call    Sleep
  1456.  
  1457.         mov     eax, [device.desc_ver]
  1458.         or      eax, TXRXCTL_BIT2
  1459.         mov     [TxRxControl], eax
  1460.         call    pci_push
  1461.  
  1462.         pop     esi eax
  1463.  
  1464.         ret
  1465.  
  1466.  
  1467.  
  1468.  
  1469.  
  1470. ; Input:  none
  1471. ; Output: none
  1472. set_multicast:
  1473.  
  1474.         ; u32 addr[2];
  1475.         ; u32 mask[2];
  1476.         ; u32 pff;
  1477.         ; u32 alwaysOff[2];
  1478.         ; u32 alwaysOn[2];
  1479.         ;
  1480.         ; memset(addr, 0, sizeof(addr));
  1481.         ; memset(mask, 0, sizeof(mask));
  1482.         ;
  1483.         ; pff = PFF_MYADDR;
  1484.         ;
  1485.         ; alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0;
  1486.         ;
  1487.         ; addr[0] = alwaysOn[0];
  1488.         ; addr[1] = alwaysOn[1];
  1489.         ; mask[0] = alwaysOn[0] | alwaysOff[0];
  1490.         ; mask[1] = alwaysOn[1] | alwaysOff[1];
  1491.         ;
  1492.         ; addr[0] |= MCASTADDRA_FORCE;
  1493.         ; pff |= PFF_ALWAYS;
  1494.  
  1495.         call    stop_rx
  1496.  
  1497.         mov     edi, [device.mmio_addr]
  1498.         mov     [MulticastAddrA], MCASTADDRA_FORCE
  1499.  
  1500.         mov     [MulticastAddrB], 0
  1501.         mov     [MulticastMaskA], 0
  1502.         mov     [MulticastMaskB], 0
  1503.         mov     [PacketFilterFlags], (PFF_MYADDR or PFF_ALWAYS)
  1504.  
  1505.         call    start_rx
  1506.  
  1507.         ret
  1508.  
  1509.  
  1510.  
  1511.  
  1512.  
  1513. ; Input:  none
  1514. ; Output: none
  1515. start_rx:
  1516.  
  1517.         push    edi
  1518.  
  1519.         DEBUGF  1,"start_rx\n"
  1520.  
  1521.         ; Already running? Stop it.
  1522.         mov     edi, [device.mmio_addr]
  1523.         mov     eax, [ReceiverControl]
  1524.         test    eax, RCVCTL_START
  1525.         jz      @f
  1526.         mov     [ReceiverControl], 0
  1527.         call    pci_push
  1528.        @@:
  1529.  
  1530.         mov     eax, [device.linkspeed]
  1531.         mov     [LinkSpeed], eax
  1532.         call    pci_push
  1533.  
  1534.         mov     [ReceiverControl], RCVCTL_START
  1535.         call    pci_push
  1536.  
  1537.         pop     edi
  1538.  
  1539.         ret
  1540.  
  1541.  
  1542.  
  1543.  
  1544. ; Input:  none
  1545. ; Output: none
  1546. stop_rx:
  1547.  
  1548.         push    esi edi
  1549.  
  1550.         DEBUGF 1,"stop_rx.\n"
  1551.  
  1552.         mov     edi, [device.mmio_addr]
  1553.         mov     [ReceiverControl], 0
  1554.  
  1555.         push    ebx edx edi
  1556.         stdcall reg_delay, ReceiverStatus-edi, RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, 0
  1557.         pop     edi edx ebx
  1558.  
  1559.         mov     esi, NV_RXSTOP_DELAY2
  1560.         call    Sleep
  1561.  
  1562.         mov     [LinkSpeed], 0
  1563.  
  1564.         pop     edi esi
  1565.  
  1566.         ret
  1567.  
  1568.  
  1569.  
  1570.  
  1571. ; Input:  none
  1572. ; Output: EAX
  1573. update_linkspeed:
  1574.  
  1575.         DEBUGF  1,"update linkspeed\n"
  1576.  
  1577. ; BMSR_LSTATUS is latched, read it twice: we want the current value.
  1578.        
  1579.         mov     edx, [device.phyaddr]
  1580.         mov     eax, MII_BMSR
  1581.         mov     ecx, MII_READ
  1582.         call    mii_rw
  1583.  
  1584.         mov     eax, MII_BMSR
  1585.         mov     ecx, MII_READ
  1586.         call    mii_rw
  1587.        
  1588.         test    eax, BMSR_LSTATUS               ; Link up?
  1589.         jz      .10mbit_hd
  1590.  
  1591.         test    eax, BMSR_ANEGCOMPLETE          ; still in autonegotiation?
  1592.         jz      .10mbit_hd
  1593.  
  1594.         cmp     [device.gigabit], PHY_GIGABIT
  1595.         jne     .no_gigabit
  1596.  
  1597.         ;mov     edx, [device.phyaddr]
  1598.         mov     eax, MII_1000BT_CR
  1599.         mov     ecx, MII_READ
  1600.         call    mii_rw
  1601.         push    eax
  1602.  
  1603.         ;mov     edx, [device.phyaddr]
  1604.         mov     eax, MII_1000BT_SR
  1605.         mov     ecx, MII_READ
  1606.         call    mii_rw
  1607.         pop     ecx
  1608.  
  1609.         test    eax, LPA_1000FULL
  1610.         jz      .no_gigabit
  1611.         test    ecx, ADVERTISE_1000FULL
  1612.         jz      .no_gigabit
  1613.  
  1614.         DEBUGF  1,"update_linkspeed: GBit ethernet detected.\n"
  1615.         mov     ecx, (LINKSPEED_FORCE or LINKSPEED_1000)
  1616.         xor     eax, eax
  1617.         inc     eax
  1618.         jmp     set_speed
  1619.   .no_gigabit:
  1620.  
  1621.         ;mov     edx, [device.phyaddr]
  1622.         mov     eax, MII_ADVERTISE
  1623.         mov     ecx, MII_READ
  1624.         call    mii_rw        ; adv = eax
  1625.         push    eax
  1626.  
  1627.         ;mov     edx, [device.phyaddr]
  1628.         mov     eax, MII_LPA
  1629.         mov     ecx, MII_READ
  1630.         call    mii_rw        ; lpa = eax
  1631.         pop     ecx
  1632.  
  1633.         DEBUGF  1,"PHY advertises 0x%x, lpa 0x%x\n", ecx, eax
  1634.         and     eax, ecx                ; FIXME: handle parallel detection properly, handle gigabit ethernet
  1635.  
  1636.         test    eax, LPA_100FULL
  1637.         jz      @f
  1638.         DEBUGF  1,"update_linkspeed: 100 mbit full duplex\n"
  1639.         mov     ecx, (LINKSPEED_FORCE or LINKSPEED_100)
  1640.         xor     eax, eax
  1641.         inc     eax
  1642.         jmp     set_speed
  1643.        @@:
  1644.  
  1645.         test    eax, LPA_100HALF
  1646.         jz      @f
  1647.         DEBUGF  1,"update_linkspeed: 100 mbit half duplex\n"
  1648.         mov     ecx, (LINKSPEED_FORCE or LINKSPEED_100)
  1649.         xor     eax, eax
  1650.         jmp     set_speed
  1651.        @@:
  1652.  
  1653.         test    eax, LPA_10FULL
  1654.         jz      @f
  1655.         DEBUGF  1,"update_linkspeed: 10 mbit full duplex\n"
  1656.         mov     ecx, (LINKSPEED_FORCE or LINKSPEED_10)
  1657.         xor     eax, eax
  1658.         inc     eax
  1659.         jmp     set_speed
  1660.        @@:
  1661.  
  1662.   .10mbit_hd:
  1663.         DEBUGF  1,"update_linkspeed: 10 mbit half duplex\n"
  1664.         mov     ecx, (LINKSPEED_FORCE or LINKSPEED_10)
  1665.         xor     eax, eax
  1666.         jmp     set_speed
  1667.  
  1668.  
  1669. align 4
  1670. set_speed:
  1671.  
  1672.         cmp     eax, [device.duplex]
  1673.         jne     .update
  1674.         cmp     ecx, [device.linkspeed]
  1675.         jne     .update
  1676.  
  1677.         ret
  1678.  
  1679.   .update:
  1680.         DEBUGF 1,"update_linkspeed: changing link to 0x%x/XD.\n", ecx
  1681.        
  1682.         mov     [device.duplex], eax
  1683.         mov     [device.linkspeed], ecx
  1684.        
  1685.         cmp     [device.gigabit], PHY_GIGABIT
  1686.         jne     .no_gigabit
  1687.  
  1688.         mov     edi, [device.mmio_addr]
  1689.         mov     eax, [RandomSeed]
  1690.  
  1691.         and     eax, not (0x3FF00)
  1692.         mov     ecx, eax                ; phyreg = ecx
  1693.  
  1694.         mov     eax, [device.linkspeed]
  1695.         and     eax, 0xFFF
  1696.         cmp     eax, LINKSPEED_10
  1697.         jne     @f
  1698.         or      ecx, RNDSEED_FORCE3
  1699.         jmp     .end_if4
  1700.        @@:
  1701.  
  1702.         cmp     eax, LINKSPEED_100
  1703.         jne     @f
  1704.         or      ecx, RNDSEED_FORCE2
  1705.         jmp     .end_if4
  1706.        @@:
  1707.  
  1708.         cmp     eax, LINKSPEED_1000
  1709.         jne     .end_if4
  1710.         or      ecx, RNDSEED_FORCE
  1711.   .end_if4:
  1712.         mov     [RandomSeed], ecx
  1713.   .no_gigabit:
  1714.  
  1715.         mov     ecx, [PhyInterface]
  1716.         and     ecx, not (PHY_HALF or PHY_100 or PHY_1000)
  1717.  
  1718.         cmp     [device.duplex], 0
  1719.         jne     @f
  1720.         or      ecx, PHY_HALF
  1721.        @@:
  1722.  
  1723.         mov     eax, [device.linkspeed]
  1724.         and     eax, 0xFFF
  1725.         cmp     eax, LINKSPEED_100
  1726.         jne     @f
  1727.         or      ecx, PHY_100
  1728.         jmp     .end_if5
  1729.        @@:
  1730.  
  1731.         cmp     eax, LINKSPEED_1000
  1732.         jne     .end_if5
  1733.         or      ecx, PHY_1000
  1734.  
  1735.   .end_if5:
  1736.         mov     [PhyInterface], ecx
  1737.                
  1738.         cmp     [device.duplex], 0
  1739.         je      @f
  1740.         xor     ecx, ecx
  1741.         jmp     .next
  1742.        @@:
  1743.  
  1744.         mov     ecx, MISC1_HD
  1745.   .next:
  1746.         or      ecx, MISC1_FORCE
  1747.         mov     [Misc1], ecx
  1748.  
  1749.         call    pci_push
  1750.  
  1751.         mov     eax, [device.linkspeed]
  1752.         mov     [LinkSpeed], eax
  1753.  
  1754.         call    pci_push
  1755.  
  1756.         ret
  1757.  
  1758.  
  1759.  
  1760.  
  1761.  
  1762.  
  1763. align 4
  1764. read_mac:
  1765.  
  1766.         mov     edi, [device.mmio_addr]
  1767.  
  1768.         mov     eax, [MacAddrA]
  1769.         mov     ecx, [MacAddrB]
  1770.  
  1771.         mov     dword [device.mac], eax
  1772.         mov     word [device.mac + 4], cx
  1773.  
  1774.         cmp     [device.device_id], 0x03E5
  1775.         jae     @f
  1776.         bswap   eax
  1777.         xchg    cl, ch
  1778.         mov     dword [device.mac + 2], eax
  1779.         mov     word [device.mac], cx
  1780.        @@:
  1781.  
  1782.         DEBUGF 1,"MAC = %x-%x-%x-%x-%x-%x\n", \
  1783.         [device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
  1784.  
  1785.         ret
  1786.  
  1787.  
  1788.  
  1789. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1790. ;;                                         ;;
  1791. ;; Transmit                                ;;
  1792. ;;                                         ;;
  1793. ;; In: buffer pointer in [esp+4]           ;;
  1794. ;;     size of buffer in [esp+8]           ;;
  1795. ;;     pointer to device structure in ebx  ;;
  1796. ;;                                         ;;
  1797. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1798. align 4
  1799. transmit:
  1800.         DEBUGF  2,"\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
  1801.         mov     eax, [esp+4]
  1802.         DEBUGF  2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  1803.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  1804.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  1805.         [eax+13]:2,[eax+12]:2
  1806.  
  1807.         cmp     dword [esp + 8], 1514
  1808.         ja      .fail
  1809.         cmp     dword [esp + 8], 60
  1810.         jb      .fail
  1811.  
  1812. ; get the descriptor address
  1813.         mov     eax, [device.next_tx]
  1814.         mov     cl, sizeof.TxDesc
  1815.         mul     cl
  1816.         lea     esi, [device.tx_ring + eax]
  1817.         mov     eax, [esp + 4]
  1818.         mov     [esi + TX_RING*sizeof.TxDesc], eax
  1819.         GetRealAddr
  1820.         mov     [esi + TxDesc.PacketBuffer], eax
  1821.  
  1822.         mov     ecx, [esp + 8]
  1823.         or      ecx, [device.txflags]
  1824.         mov     [esi + TxDesc.FlagLen], eax
  1825.  
  1826.         mov     edi, [device.mmio_addr]
  1827.         mov     eax, [device.desc_ver]
  1828.         or      eax, TXRXCTL_KICK
  1829.         mov     [TxRxControl], eax
  1830.  
  1831.         call    pci_push
  1832.  
  1833.         inc     [device.next_tx]
  1834.         and     [device.next_tx], (TX_RING-1)
  1835.  
  1836. ; Update stats
  1837.         inc     [device.packets_tx]
  1838.         mov     eax, [esp + 8]
  1839.         add     dword [device.bytes_tx], eax
  1840.         adc     dword [device.bytes_tx + 4], 0
  1841.  
  1842.         xor     eax, eax
  1843.         ret     8
  1844.  
  1845.   .fail:
  1846.         stdcall KernelFree, [esp+4]
  1847.         or      eax, -1
  1848.         ret     8
  1849.  
  1850.  
  1851.  
  1852.  
  1853.  
  1854.  
  1855. ; Interrupt handler
  1856. align 4
  1857. int_handler:
  1858.  
  1859.         push    ebx esi edi
  1860.  
  1861.         DEBUGF  2,"\n%s INT\n", my_service
  1862.  
  1863. ;-------------------------------------------
  1864. ; Find pointer of device wich made IRQ occur
  1865.  
  1866.         mov     esi, device_list
  1867.         mov     ecx, [devices]
  1868.         test    ecx, ecx
  1869.         jz      .fail
  1870.   .nextdevice:
  1871.         mov     ebx, dword [esi]
  1872.         add     esi, 4
  1873.  
  1874.         mov     edi, [device.mmio_addr]
  1875.         mov     eax, [IrqStatus]
  1876.         test    eax, eax
  1877.         jnz     .got_it
  1878.         dec     ecx
  1879.         jnz     .nextdevice
  1880.   .nothing:
  1881.         pop     edi esi ebx
  1882.         xor     eax, eax
  1883.  
  1884.         ret
  1885.  
  1886.   .got_it:
  1887.         mov     [IrqStatus], eax
  1888.         DEBUGF  2,"IrqStatus = %x\n", eax
  1889.  
  1890.         test    eax, IRQ_RX
  1891.         jz      .no_rx
  1892.  
  1893.   .top:
  1894.         mov     eax, [device.cur_rx]
  1895.         mov     cx, sizeof.RxDesc
  1896.         mul     cx
  1897.         lea     esi, [device.rx_ring + eax]
  1898.         mov     eax, [esi + RxDesc.FlagLen]
  1899.  
  1900.         test    eax, NV_RX_AVAIL        ; still owned by hardware
  1901.         jnz     .return0
  1902.  
  1903.         cmp     [device.desc_ver], DESC_VER_1
  1904.         jne     @f
  1905.         test    eax, NV_RX_DESCRIPTORVALID
  1906.         jz      .return0
  1907.         jmp     .next
  1908.   @@:
  1909.         test    eax, NV_RX2_DESCRIPTORVALID
  1910.         jz      .return0
  1911.  
  1912.   .next:
  1913.  
  1914.         cmp     dword [device.desc_ver], DESC_VER_1
  1915.         jne     @f
  1916.         and     eax, LEN_MASK_V1
  1917.         jmp     .next2
  1918.    @@:
  1919.         and     eax, LEN_MASK_V2
  1920.   .next2:
  1921.  
  1922.         ; got a valid packet - forward it to the network core
  1923.         push    .top
  1924.         push    eax
  1925.         push    dword [esi + RX_RING*sizeof.RxDesc]
  1926.  
  1927.         inc     [device.cur_rx]
  1928.         and     [device.cur_rx], (RX_RING-1)
  1929.  
  1930. ; Allocate new buffer
  1931.  
  1932.         stdcall KernelAlloc, 4096 shl RBLEN
  1933.         mov     [esi + RX_RING*sizeof.RxDesc], eax
  1934.         GetRealAddr
  1935.         mov     [esi + RxDesc.PacketBuffer], eax
  1936.         mov     [esi + RxDesc.FlagLen], (4096 shl RBLEN or NV_RX_AVAIL)
  1937.  
  1938.         jmp     Eth_input
  1939.  
  1940.   .return0:
  1941.  
  1942.  
  1943.   .no_rx:
  1944.         test    eax, IRQ_RX_ERROR
  1945.         jz      .no_rx_err
  1946.  
  1947.         push    eax
  1948.         DEBUGF  2,"RX error!\n"
  1949.  
  1950.         mov     eax, [device.cur_rx]
  1951.         mov     cx, sizeof.RxDesc
  1952.         mul     cx
  1953.         lea     esi, [device.rx_ring + eax]
  1954.         mov     eax, [esi + RxDesc.FlagLen]
  1955.  
  1956.         DEBUGF  2,"Flaglen=%x\n", eax
  1957.  
  1958.         ; TODO: allocate new buff
  1959.         pop     eax
  1960.  
  1961.   .no_rx_err:
  1962.         test    eax, IRQ_LINK
  1963.         jz      .no_link
  1964.  
  1965.         push    eax
  1966.         call    update_linkspeed
  1967.         pop     eax
  1968.  
  1969.   .no_link:
  1970.   .fail:
  1971.  
  1972.         pop     edi esi ebx
  1973.         xor     eax, eax
  1974.         inc     eax
  1975.  
  1976.         ret
  1977.  
  1978.  
  1979.  
  1980.  
  1981. ; End of code
  1982.  
  1983. section '.data' data readable writable align 16 ; place all uninitialized data place here
  1984. align 4                                         ; Place all initialised data here
  1985.  
  1986. devices         dd 0
  1987. version         dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
  1988. my_service      db 'FORCEDETH',0                ; max 16 chars include zero
  1989.  
  1990. include_debug_strings                           ; All data wich FDO uses will be included here
  1991.  
  1992. device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
  1993.