Subversion Repositories Kolibri OS

Rev

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

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