Subversion Repositories Kolibri OS

Rev

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

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