Subversion Repositories Kolibri OS

Rev

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