Subversion Repositories Kolibri OS

Rev

Rev 9157 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2010-2021. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  rhine.asm                                                      ;;
  7. ;;                                                                 ;;
  8. ;;  Ethernet driver for Kolibri OS                                 ;;
  9. ;;                                                                 ;;
  10. ;;  This driver is based on the via-rhine driver from              ;;
  11. ;;  the etherboot 5.0.6 project. The copyright statement is        ;;
  12. ;;                                                                 ;;
  13. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  14. ;;             Version 2, June 1991                                ;;
  15. ;;                                                                 ;;
  16. ;;    Rewritten in flat assembler by Asper (asper.85@mail.ru)      ;;
  17. ;;            and hidnplayr (hidnplayr@gmail.com)                  ;;
  18. ;;                                                                 ;;
  19. ;;  See file COPYING for details                                   ;;
  20. ;;                                                                 ;;
  21. ;;                                                                 ;;
  22. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  23.  
  24. ; TODO: test for RX-overrun
  25.  
  26. format PE DLL native
  27. entry START
  28.  
  29.         CURRENT_API             = 0x0200
  30.         COMPATIBLE_API          = 0x0100
  31.         API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
  32.  
  33.         MAX_DEVICES             = 16
  34.  
  35.         __DEBUG__               = 1
  36.         __DEBUG_LEVEL__         = 2     ; 1 = all, 2 = errors only
  37.  
  38.         TX_RING_SIZE            = 32
  39.         RX_RING_SIZE            = 32
  40.  
  41.         ; max time out delay time
  42.         W_MAX_TIMEOUT           = 0x0FFF
  43.  
  44.         ; Size of the in-memory receive ring.
  45.         RX_BUF_LEN_IDX          = 3     ; 0==8K, 1==16K, 2==32K, 3==64K
  46.  
  47.         ; PCI Tuning Parameters
  48.         ; Threshold is bytes transferred to chip before transmission starts.
  49.         TX_FIFO_THRESH          = 256   ; In bytes, rounded down to 32 byte units.
  50.  
  51.         ; The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024.
  52.         RX_FIFO_THRESH          = 4     ; Rx buffer level before first PCI transfer.
  53.         RX_DMA_BURST            = 4     ; Maximum PCI burst, '4' is 256 bytes
  54.         TX_DMA_BURST            = 4
  55.  
  56.  
  57. section '.flat' readable writable executable
  58.  
  59. include '../proc32.inc'
  60. include '../struct.inc'
  61. include '../macros.inc'
  62. include '../fdo.inc'
  63. include '../netdrv.inc'
  64.  
  65.  
  66. ;**************************************************************************
  67. ; VIA Rhine Register Definitions
  68. ;**************************************************************************
  69. byPAR0                          = 0x00
  70. byRCR                           = 0x06
  71. byTCR                           = 0x07
  72. byCR0                           = 0x08
  73. byCR1                           = 0x09
  74. byISR0                          = 0x0c
  75. byISR1                          = 0x0d
  76. byIMR0                          = 0x0e
  77. byIMR1                          = 0x0f
  78. byMAR0                          = 0x10
  79. byMAR1                          = 0x11
  80. byMAR2                          = 0x12
  81. byMAR3                          = 0x13
  82. byMAR4                          = 0x14
  83. byMAR5                          = 0x15
  84. byMAR6                          = 0x16
  85. byMAR7                          = 0x17
  86. dwCurrentRxDescAddr             = 0x18
  87. dwCurrentTxDescAddr             = 0x1c
  88. dwCurrentRDSE0                  = 0x20
  89. dwCurrentRDSE1                  = 0x24
  90. dwCurrentRDSE2                  = 0x28
  91. dwCurrentRDSE3                  = 0x2c
  92. dwNextRDSE0                     = 0x30
  93. dwNextRDSE1                     = 0x34
  94. dwNextRDSE2                     = 0x38
  95. dwNextRDSE3                     = 0x3c
  96. dwCurrentTDSE0                  = 0x40
  97. dwCurrentTDSE1                  = 0x44
  98. dwCurrentTDSE2                  = 0x48
  99. dwCurrentTDSE3                  = 0x4c
  100. dwNextTDSE0                     = 0x50
  101. dwNextTDSE1                     = 0x54
  102. dwNextTDSE2                     = 0x58
  103. dwNextTDSE3                     = 0x5c
  104. dwCurrRxDMAPtr                  = 0x60
  105. dwCurrTxDMAPtr                  = 0x64
  106. byMPHY                          = 0x6c
  107. byMIISR                         = 0x6d
  108. byBCR0                          = 0x6e
  109. byBCR1                          = 0x6f
  110. byMIICR                         = 0x70
  111. byMIIAD                         = 0x71
  112. wMIIDATA                        = 0x72
  113. byEECSR                         = 0x74
  114. byTEST                          = 0x75
  115. byGPIO                          = 0x76
  116. byCFGA                          = 0x78
  117. byCFGB                          = 0x79
  118. byCFGC                          = 0x7a
  119. byCFGD                          = 0x7b
  120. wTallyCntMPA                    = 0x7c
  121. wTallyCntCRC                    = 0x7d
  122. bySTICKHW                       = 0x83
  123. byWOLcrClr                      = 0xA4
  124. byWOLcgClr                      = 0xA7
  125. byPwrcsrClr                     = 0xAC
  126.  
  127. ;---------------------  Exioaddr Definitions -------------------------
  128.  
  129. ; Bits in the RCR register
  130. RCR_RRFT2               = 0x80
  131. RCR_RRFT1               = 0x40
  132. RCR_RRFT0               = 0x20
  133. RCR_PROM                = 0x10
  134. RCR_AB                  = 0x08
  135. RCR_AM                  = 0x04
  136. RCR_AR                  = 0x02
  137. RCR_SEP                 = 0x01
  138. ; Bits in the TCR register
  139. TCR_RTSF                = 0x80
  140. TCR_RTFT1               = 0x40
  141. TCR_RTFT0               = 0x20
  142. TCR_OFSET               = 0x08
  143. TCR_LB1                 = 0x04    ; loopback[1]
  144. TCR_LB0                 = 0x02    ; loopback[0]
  145. ; Bits in the CR0 register
  146. CR0_RDMD                = 0x40    ; rx descriptor polling demand
  147. CR0_TDMD                = 0x20    ; tx descriptor polling demand
  148. CR0_TXON                = 0x10
  149. CR0_RXON                = 0x08
  150. CR0_STOP                = 0x04    ; stop NIC, default = 1
  151. CR0_STRT                = 0x02    ; start NIC
  152. CR0_INIT                = 0x01    ; start init process
  153. ; Bits in the CR1 register
  154. CR1_SFRST               = 0x80    ; software reset
  155. CR1_RDMD1               = 0x40    ; RDMD1
  156. CR1_TDMD1               = 0x20    ; TDMD1
  157. CR1_KEYPAG              = 0x10    ; turn on par/key
  158. CR1_DPOLL               = 0x08    ; disable rx/tx auto polling
  159. CR1_FDX                 = 0x04    ; full duplex mode
  160. CR1_ETEN                = 0x02    ; early tx mode
  161. CR1_EREN                = 0x01    ; early rx mode
  162. ; Bits in the CR register
  163. CR_RDMD                 = 0x0040  ; rx descriptor polling demand
  164. CR_TDMD                 = 0x0020  ; tx descriptor polling demand
  165. CR_TXON                 = 0x0010
  166. CR_RXON                 = 0x0008
  167. CR_STOP                 = 0x0004  ; stop NIC, default = 1
  168. CR_STRT                 = 0x0002  ; start NIC
  169. CR_INIT                 = 0x0001  ; start init process
  170. CR_SFRST                = 0x8000  ; software reset
  171. CR_RDMD1                = 0x4000  ; RDMD1
  172. CR_TDMD1                = 0x2000  ; TDMD1
  173. CR_KEYPAG               = 0x1000  ; turn on par/key
  174. CR_DPOLL                = 0x0800  ; disable rx/tx auto polling
  175. CR_FDX                  = 0x0400  ; full duplex mode
  176. CR_ETEN                 = 0x0200  ; early tx mode
  177. CR_EREN                 = 0x0100  ; early rx mode
  178. ; Bits in the IMR0 register
  179. IMR0_CNTM               = 0x80
  180. IMR0_BEM                = 0x40
  181. IMR0_RUM                = 0x20
  182. IMR0_TUM                = 0x10
  183. IMR0_TXEM               = 0x08
  184. IMR0_RXEM               = 0x04
  185. IMR0_PTXM               = 0x02
  186. IMR0_PRXM               = 0x01
  187. ; define imrshadow
  188. IMRShadow               = 0x5AFF
  189. ; Bits in the IMR1 register
  190. IMR1_INITM              = 0x80
  191. IMR1_SRCM               = 0x40
  192. IMR1_NBFM               = 0x10
  193. IMR1_PRAIM              = 0x08
  194. IMR1_RES0M              = 0x04
  195. IMR1_ETM                = 0x02
  196. IMR1_ERM                = 0x01
  197. ; Bits in the ISR register
  198. ISR_INITI               = 0x8000
  199. ISR_SRCI                = 0x4000
  200. ISR_ABTI                = 0x2000
  201. ISR_NORBF               = 0x1000
  202. ISR_PKTRA               = 0x0800
  203. ISR_RES0                = 0x0400
  204. ISR_ETI                 = 0x0200
  205. ISR_ERI                 = 0x0100
  206. ISR_CNT                 = 0x0080
  207. ISR_BE                  = 0x0040
  208. ISR_RU                  = 0x0020
  209. ISR_TU                  = 0x0010
  210. ISR_TXE                 = 0x0008
  211. ISR_RXE                 = 0x0004
  212. ISR_PTX                 = 0x0002
  213. ISR_PRX                 = 0x0001
  214. ; Bits in the ISR0 register
  215. ISR0_CNT                = 0x80
  216. ISR0_BE                 = 0x40
  217. ISR0_RU                 = 0x20
  218. ISR0_TU                 = 0x10
  219. ISR0_TXE                = 0x08
  220. ISR0_RXE                = 0x04
  221. ISR0_PTX                = 0x02
  222. ISR0_PRX                = 0x01
  223. ; Bits in the ISR1 register
  224. ISR1_INITI              = 0x80
  225. ISR1_SRCI               = 0x40
  226. ISR1_NORBF              = 0x10
  227. ISR1_PKTRA              = 0x08
  228. ISR1_ETI                = 0x02
  229. ISR1_ERI                = 0x01
  230. ; ISR ABNORMAL CONDITION
  231. ISR_ABNORMAL            = ISR_BE+ISR_RU+ISR_TU+ISR_CNT+ISR_NORBF+ISR_PKTRA
  232. ; Bits in the MIISR register
  233. MIISR_MIIERR            = 0x08
  234. MIISR_MRERR             = 0x04
  235. MIISR_LNKFL             = 0x02
  236. MIISR_SPEED             = 0x01
  237. ; Bits in the MIICR register
  238. MIICR_MAUTO             = 0x80
  239. MIICR_RCMD              = 0x40
  240. MIICR_WCMD              = 0x20
  241. MIICR_MDPM              = 0x10
  242. MIICR_MOUT              = 0x08
  243. MIICR_MDO               = 0x04
  244. MIICR_MDI               = 0x02
  245. MIICR_MDC               = 0x01
  246. ; Bits in the EECSR register
  247. EECSR_EEPR              = 0x80    ; eeprom programmed status, 73h means programmed
  248. EECSR_EMBP              = 0x40    ; eeprom embedded programming
  249. EECSR_AUTOLD            = 0x20    ; eeprom content reload
  250. EECSR_DPM               = 0x10    ; eeprom direct programming
  251. EECSR_CS                = 0x08    ; eeprom CS pin
  252. EECSR_SK                = 0x04    ; eeprom SK pin
  253. EECSR_DI                = 0x02    ; eeprom DI pin
  254. EECSR_DO                = 0x01    ; eeprom DO pin
  255. ; Bits in the BCR0 register
  256. BCR0_CRFT2              = 0x20
  257. BCR0_CRFT1              = 0x10
  258. BCR0_CRFT0              = 0x08
  259. BCR0_DMAL2              = 0x04
  260. BCR0_DMAL1              = 0x02
  261. BCR0_DMAL0              = 0x01
  262. ; Bits in the BCR1 register
  263. BCR1_CTSF               = 0x20
  264. BCR1_CTFT1              = 0x10
  265. BCR1_CTFT0              = 0x08
  266. BCR1_POT2               = 0x04
  267. BCR1_POT1               = 0x02
  268. BCR1_POT0               = 0x01
  269. ; Bits in the CFGA register
  270. CFGA_EELOAD             = 0x80    ; enable eeprom embedded and direct programming
  271. CFGA_JUMPER             = 0x40
  272. CFGA_MTGPIO             = 0x08
  273. CFGA_T10EN              = 0x02
  274. CFGA_AUTO               = 0x01
  275. ; Bits in the CFGB register
  276. CFGB_PD                 = 0x80
  277. CFGB_POLEN              = 0x02
  278. CFGB_LNKEN              = 0x01
  279. ; Bits in the CFGC register
  280. CFGC_M10TIO             = 0x80
  281. CFGC_M10POL             = 0x40
  282. CFGC_PHY1               = 0x20
  283. CFGC_PHY0               = 0x10
  284. CFGC_BTSEL              = 0x08
  285. CFGC_BPS2               = 0x04    ; bootrom select[2]
  286. CFGC_BPS1               = 0x02    ; bootrom select[1]
  287. CFGC_BPS0               = 0x01    ; bootrom select[0]
  288. ; Bits in the CFGD register
  289. CFGD_GPIOEN             = 0x80
  290. CFGD_DIAG               = 0x40
  291. CFGD_MAGIC              = 0x10
  292. CFGD_RANDOM             = 0x08
  293. CFGD_CFDX               = 0x04
  294. CFGD_CEREN              = 0x02
  295. CFGD_CETEN              = 0x01
  296. ; Bits in RSR
  297. RSR_RERR                = 0x00000001
  298. RSR_CRC                 = 0x00000002
  299. RSR_FAE                 = 0x00000004
  300. RSR_FOV                 = 0x00000008
  301. RSR_LONG                = 0x00000010
  302. RSR_RUNT                = 0x00000020
  303. RSR_SERR                = 0x00000040
  304. RSR_BUFF                = 0x00000080
  305. RSR_EDP                 = 0x00000100
  306. RSR_STP                 = 0x00000200
  307. RSR_CHN                 = 0x00000400
  308. RSR_PHY                 = 0x00000800
  309. RSR_BAR                 = 0x00001000
  310. RSR_MAR                 = 0x00002000
  311. RSR_RXOK                = 0x00008000
  312. RSR_ABNORMAL            = RSR_RERR+RSR_LONG+RSR_RUNT
  313. ; Bits in TSR
  314. TSR_NCR0                = 0x00000001
  315. TSR_NCR1                = 0x00000002
  316. TSR_NCR2                = 0x00000004
  317. TSR_NCR3                = 0x00000008
  318. TSR_COLS                = 0x00000010
  319. TSR_CDH                 = 0x00000080
  320. TSR_ABT                 = 0x00000100
  321. TSR_OWC                 = 0x00000200
  322. TSR_CRS                 = 0x00000400
  323. TSR_UDF                 = 0x00000800
  324. TSR_TBUFF               = 0x00001000
  325. TSR_SERR                = 0x00002000
  326. TSR_JAB                 = 0x00004000
  327. TSR_TERR                = 0x00008000
  328. TSR_ABNORMAL            = TSR_TERR+TSR_OWC+TSR_ABT+TSR_JAB+TSR_CRS
  329. TSR_OWN_BIT             = 0x80000000
  330.  
  331. CB_DELAY_LOOP_WAIT      = 10      ; 10ms
  332. ; enabled mask value of irq
  333. W_IMR_MASK_VALUE        = 0x1BFF  ; initial value of IMR
  334.  
  335. ; Ethernet address filter type
  336. PKT_TYPE_DIRECTED       = 0x0001  ; obsolete, directed address is always accepted
  337. PKT_TYPE_MULTICAST      = 0x0002
  338. PKT_TYPE_ALL_MULTICAST  = 0x0004
  339. PKT_TYPE_BROADCAST      = 0x0008
  340. PKT_TYPE_PROMISCUOUS    = 0x0020
  341. PKT_TYPE_LONG           = 0x2000
  342. PKT_TYPE_RUNT           = 0x4000
  343. PKT_TYPE_ERROR          = 0x8000  ; accept error packets, e.g. CRC error
  344.  
  345. ; Loopback mode
  346.  
  347. NIC_LB_NONE             = 0x00
  348. NIC_LB_INTERNAL         = 0x01
  349. NIC_LB_PHY              = 0x02    ; MII or Internal-10BaseT loopback
  350.  
  351. PKT_BUF_SZ              = 1514
  352.  
  353. PCI_REG_MODE3           = 0x53
  354. MODE3_MIION             = 0x04    ; in PCI_REG_MOD3 OF PCI space
  355.  
  356. ; VIA Rhine revisions
  357. VT86C100A       = 0x00
  358. VTunknown0      = 0x20
  359. VT6102          = 0x40
  360. VT8231          = 0x50 ; Integrated MAC
  361. VT8233          = 0x60 ; Integrated MAC
  362. VT8235          = 0x74 ; Integrated MAC
  363. VT8237          = 0x78 ; Integrated MAC
  364. VTunknown1      = 0x7C
  365. VT6105          = 0x80
  366. VT6105_B0       = 0x83
  367. VT6105L         = 0x8A
  368. VT6107          = 0x8C
  369. VTunknown2      = 0x8E
  370. VT6105M         = 0x90
  371.  
  372. ; Rx status bits
  373. RX_SBITS_RERR                   = 1 shl 0
  374. RX_SBITS_CRC_ERROR              = 1 shl 1
  375. RX_SBITS_FAE                    = 1 shl 2
  376. RX_SBITS_FOV                    = 1 shl 3
  377. RX_SBITS_TOOLONG                = 1 shl 4
  378. RX_SBITS_RUNT                   = 1 shl 5
  379. RX_SBITS_SERR                   = 1 shl 6
  380. RX_SBITS_BUFF                   = 1 shl 7
  381. RX_SBITS_EDP                    = 1 shl 8
  382. RX_SBITS_STP                    = 1 shl 9
  383. RX_SBITS_CHN                    = 1 shl 10
  384. RX_SBITS_PHY                    = 1 shl 11
  385. RX_SBITS_BAR                    = 1 shl 12
  386. RX_SBITS_MAR                    = 1 shl 13
  387. RX_SBITS_RESERVED_1             = 1 shl 14
  388. RX_SBITS_RXOK                   = 1 shl 15
  389. RX_SBITS_FRAME_LENGTH           = 0x7FF shl 16
  390. RX_SBITS_RESERVED_2             = 0xF shl 27
  391. RX_SBITS_OWN_BIT                = 1 shl 31
  392.  
  393. ; Rx control bits
  394. RX_CBITS_RX_BUF_SIZE            = 0x7FF
  395. RX_CBITS_EXTEND_RX_BUF_SIZE     = 0xF shl 11
  396. RX_CBITS_RESERVED_1             = 0x1FFFF shl 15
  397.  
  398. ; Tx status bits
  399. TX_SBITS_NCR0                   = 1 shl 0
  400. TX_SBITS_NCR1                   = 1 shl 1
  401. TX_SBITS_NCR2                   = 1 shl 2
  402. TX_SBITS_NCR3                   = 1 shl 3
  403. TX_SBITS_COLS                   = 1 shl 4
  404. TX_SBITS_RESERVED_1             = 1 shl 5
  405. TX_SBITS_CDH                    = 1 shl 7
  406. TX_SBITS_ABT                    = 1 shl 8
  407. TX_SBITS_OWC                    = 1 shl 9
  408. TX_SBITS_CRS                    = 1 shl 10
  409. TX_SBITS_UDF                    = 1 shl 11
  410. TX_SBITS_TBUFF                  = 1 shl 12
  411. TX_SBITS_SERR                   = 1 shl 13
  412. TX_SBITS_JAB                    = 1 shl 14
  413. TX_SBITS_TERR                   = 1 shl 15
  414. TX_SBITS_RESERVED_2             = 0x7FFF shl 16
  415. TX_SBITS_OWN_BIT                = 1 shl 31
  416.  
  417. ; Tx control bits
  418. TX_CBITS_TX_BUF_SIZE            = 0x7FF
  419. TX_CBITS_EXTEND_TX_BUF_SIZE     = 0xF shl 11
  420. TX_CBITS_CHN                    = 1 shl 15
  421. TX_CBITS_CRC                    = 1 shl 16
  422. TX_CBITS_RESERVED_1             = 0xF shl 17
  423. TX_CBITS_STP                    = 1 shl 21
  424. TX_CBITS_EDP                    = 1 shl 22
  425. TX_CBITS_IC                     = 1 shl 23
  426. TX_CBITS_RESERVED_2             = 0xFF shl 24
  427.  
  428.  
  429.  
  430. ; Offsets to the device registers.
  431.         StationAddr             = 0x00
  432.         RxConfig                = 0x06
  433.         TxConfig                = 0x07
  434.         ChipCmd                 = 0x08
  435.         IntrStatus              = 0x0C
  436.         IntrEnable              = 0x0E
  437.         MulticastFilter0        = 0x10
  438.         MulticastFilter1        = 0x14
  439.         RxRingPtr               = 0x18
  440.         TxRingPtr               = 0x1C
  441.         GFIFOTest               = 0x54
  442.         MIIPhyAddr              = 0x6C
  443.         MIIStatus               = 0x6D
  444.         PCIBusConfig            = 0x6E
  445.         MIICmd                  = 0x70
  446.         MIIRegAddr              = 0x71
  447.         MIIData                 = 0x72
  448.         MACRegEEcsr             = 0x74
  449.         ConfigA                 = 0x78
  450.         ConfigB                 = 0x79
  451.         ConfigC                 = 0x7A
  452.         ConfigD                 = 0x7B
  453.         RxMissed                = 0x7C
  454.         RxCRCErrs               = 0x7E
  455.         MiscCmd                 = 0x81
  456.         StickyHW                = 0x83
  457.         IntrStatus2             = 0x84
  458.         WOLcrClr                = 0xA4
  459.         WOLcgClr                = 0xA7
  460.         PwrcsrClr               = 0xAC
  461.  
  462. ; Bits in the interrupt status/mask registers.
  463.         IntrRxDone              = 0x0001
  464.         IntrRxErr               = 0x0004
  465.         IntrRxEmpty             = 0x0020
  466.         IntrTxDone              = 0x0002
  467.         IntrTxError             = 0x0008
  468.         IntrTxUnderrun          = 0x0010
  469.         IntrPCIErr              = 0x0040
  470.         IntrStatsMax            = 0x0080
  471.         IntrRxEarly             = 0x0100
  472.         IntrRxOverflow          = 0x0400
  473.         IntrRxDropped           = 0x0800
  474.         IntrRxNoBuf             = 0x1000
  475.         IntrTxAborted           = 0x2000
  476.         IntrLinkChange          = 0x4000
  477.         IntrRxWakeUp            = 0x8000
  478.         IntrNormalSummary       = 0x0003
  479.         IntrAbnormalSummary     = 0xC260
  480.         IntrTxDescRace          = 0x080000        ; mapped from IntrStatus2
  481.         IntrTxErrSummary        = 0x082218
  482.  
  483.         DEFAULT_INTR            = (IntrRxDone or IntrRxErr or IntrRxEmpty or IntrRxOverflow or IntrRxDropped or IntrRxNoBuf)
  484.         RX_BUF_LEN              = (8192 shl RX_BUF_LEN_IDX)
  485.  
  486. struct  rx_head
  487.         status          dd ?
  488.         control         dd ?
  489.         buff_addr       dd ?    ; address
  490.         next_desc       dd ?    ;
  491.  
  492.         buff_addr_virt  dd ?
  493.                         rd 3    ; alignment
  494. ends
  495.  
  496. struct  tx_head
  497.         status          dd ?
  498.         control         dd ?
  499.         buff_addr       dd ?    ; address
  500.         next_desc       dd ?    ;
  501.  
  502.         buff_addr_virt  dd ?
  503.                         rd 3    ; alignment
  504. ends
  505.  
  506. struct  device          ETH_DEVICE
  507.  
  508.         io_addr         dd ?
  509.         pci_dev         dd ?
  510.         pci_bus         dd ?
  511.         revision        db ?
  512.         irq_line        db ?
  513.         chip_vid        dw ?
  514.         chip_did        dw ?
  515.  
  516.         cur_rx          dw ?
  517.         cur_tx          dw ?
  518.         last_tx         dw ?
  519.  
  520.         rb 0x100 - ($ and 0xff) ; align 256
  521.         tx_ring         rb sizeof.tx_head*TX_RING_SIZE
  522.  
  523.         rb 0x100 - ($ and 0xff) ; align 256
  524.         rx_ring         rb sizeof.rx_head*RX_RING_SIZE
  525.  
  526. ends
  527.  
  528.  
  529. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  530. ;;                        ;;
  531. ;; proc START             ;;
  532. ;;                        ;;
  533. ;; (standard driver proc) ;;
  534. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  535.  
  536. proc START c, reason:dword, cmdline:dword
  537.  
  538.         cmp     [reason], DRV_ENTRY
  539.         jne     .fail
  540.  
  541.         DEBUGF  1,"Loading driver\n"
  542.         invoke  RegService, my_service, service_proc
  543.         ret
  544.  
  545.   .fail:
  546.         xor     eax, eax
  547.         ret
  548.  
  549. endp
  550.  
  551.  
  552. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  553. ;;                        ;;
  554. ;; proc SERVICE_PROC      ;;
  555. ;;                        ;;
  556. ;; (standard driver proc) ;;
  557. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  558.  
  559. proc service_proc stdcall, ioctl:dword
  560.  
  561.         mov     edx, [ioctl]
  562.         mov     eax, [edx + IOCTL.io_code]
  563.  
  564. ;------------------------------------------------------
  565.  
  566.         cmp     eax, 0 ;SRV_GETVERSION
  567.         jne     @F
  568.  
  569.         cmp     [edx + IOCTL.out_size], 4
  570.         jb      .fail
  571.         mov     eax, [edx + IOCTL.output]
  572.         mov     [eax], dword API_VERSION
  573.  
  574.         xor     eax, eax
  575.         ret
  576.  
  577. ;------------------------------------------------------
  578.   @@:
  579.         cmp     eax, 1 ;SRV_HOOK
  580.         jne     .fail
  581.  
  582.         cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
  583.         jb      .fail
  584.  
  585.         mov     eax, [edx + IOCTL.input]
  586.         cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
  587.         jne     .fail                                   ; other types aren't supported for this card yet
  588.  
  589. ; check if the device is already listed
  590.  
  591.         mov     esi, device_list
  592.         mov     ecx, [devices]
  593.         test    ecx, ecx
  594.         jz      .firstdevice
  595.  
  596. ;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
  597.         mov     ax, [eax+1]                             ;
  598.   .nextdevice:
  599.         mov     ebx, [esi]
  600.         cmp     al, byte[ebx + device.pci_bus]
  601.         jne     @f
  602.         cmp     ah, byte[ebx + device.pci_dev]
  603.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  604.        @@:
  605.         add     esi, 4
  606.         loop    .nextdevice
  607.  
  608.  
  609. ; This device doesn't have its own eth_device structure yet, lets create one
  610.   .firstdevice:
  611.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  612.         jae     .fail
  613.  
  614.         allocate_and_clear ebx, sizeof.device, .fail    ; Allocate the buffer for device structure
  615.  
  616. ; Fill in the direct call addresses into the struct
  617.  
  618.         mov     [ebx + device.reset], reset
  619.         mov     [ebx + device.transmit], transmit
  620.         mov     [ebx + device.unload], unload
  621.         mov     [ebx + device.name], my_service
  622.  
  623. ; save the pci bus and device numbers
  624.  
  625.         mov     eax, [edx + IOCTL.input]
  626.         movzx   ecx, byte[eax+1]
  627.         mov     [ebx + device.pci_bus], ecx
  628.         movzx   ecx, byte[eax+2]
  629.         mov     [ebx + device.pci_dev], ecx
  630.  
  631. ; Now, it's time to find the base io address of the PCI device
  632.  
  633.         stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
  634.         mov     [ebx + device.io_addr], eax
  635.  
  636. ; We've found the io address, find IRQ now
  637.  
  638.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
  639.         mov     [ebx + device.irq_line], al
  640.  
  641.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  642.         [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:4
  643.  
  644. ; Ok, the eth_device structure is ready, let's probe the device
  645.         call    probe                                                   ; this function will output in eax
  646.         test    eax, eax
  647.         jnz     .err                                                    ; If an error occurred, exit
  648.  
  649.         mov     eax, [devices]                                          ; Add the device structure to our device list
  650.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  651.         inc     [devices]                                               ;
  652.  
  653.         mov     [ebx + device.type], NET_TYPE_ETH
  654.         invoke  NetRegDev
  655.  
  656.         cmp     eax, -1
  657.         je      .destroy
  658.  
  659.         ret
  660.  
  661. ; If the device was already loaded, find the device number and return it in eax
  662.  
  663.   .find_devicenum:
  664.         DEBUGF  1,"Trying to find device number of already registered device\n"
  665.         invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  666.                                                                         ; into a device number in edi
  667.         mov     eax, edi                                                ; Application wants it in eax instead
  668.         DEBUGF  1,"Kernel says: %u\n", eax
  669.         ret
  670.  
  671. ; If an error occurred, remove all allocated data and exit (returning -1 in eax)
  672.  
  673.   .destroy:
  674.         ; todo: reset device into virgin state
  675.  
  676.   .err:
  677.         invoke  KernelFree, ebx
  678.  
  679.   .fail:
  680.         or      eax, -1
  681.         ret
  682.  
  683. ;------------------------------------------------------
  684. endp
  685.  
  686.  
  687. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  688. ;;                                                                        ;;
  689. ;;        Actual Hardware dependent code starts here                      ;;
  690. ;;                                                                        ;;
  691. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  692.  
  693.  
  694. ;-------
  695. ;
  696. ; PROBE
  697. ;
  698. ;-------
  699. probe:
  700.  
  701.         DEBUGF  1, "Probing\n"
  702.  
  703.  
  704. ; Make the device a bus master
  705.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
  706.         or      al, PCI_CMD_MASTER
  707.         invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
  708.  
  709. ; get device id
  710.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.vendor_id
  711.         mov     dword[ebx + device.chip_vid], eax
  712.  
  713.         mov     esi, chiplist
  714.   .loop:
  715.         cmp     dword[esi], eax
  716.         je      .got_it
  717.         add     esi, 2*4
  718.         cmp     dword[esi], 0
  719.         jne     .loop
  720.         DEBUGF  2, "Unknown chip: 0x%x, continuing anyway\n", eax
  721.         mov     [ebx + device.name], my_service
  722.         jmp     .done
  723.   .got_it:
  724.         mov     eax, dword[esi+4]
  725.         mov     [ebx + device.name], eax
  726.         DEBUGF  1, "Chip type = %s\n", eax
  727.   .done:
  728.  
  729. ; get revision id.
  730.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.revision_id
  731.         mov     [ebx + device.revision], al
  732.  
  733.         movzx   eax, [ebx + device.revision]
  734.         DEBUGF  1, "Card revision = 0x%x\n", eax
  735.  
  736. ; D-Link provided reset code (with comment additions)
  737.         cmp     al, 0x40
  738.         jb      .below_x40
  739.  
  740.         mov     ax, [ebx + device.chip_did]
  741.         DEBUGF  1, "Enabling Sticky Bit Workaround for Chip_id: 0x%x\n", ax
  742.  
  743.         ; clear sticky bit before reset & read ethernet address
  744.         set_io  [ebx + device.io_addr], 0
  745.         set_io  [ebx + device.io_addr], bySTICKHW
  746.         in      al, dx
  747.         and     al, 0xFC
  748.         out     dx, al
  749.  
  750.         ; (bits written are cleared?)
  751.         ; disable force PME-enable
  752.         set_io  [ebx + device.io_addr], byWOLcgClr
  753.         mov     al, 0x80
  754.         out     dx, al
  755.  
  756.         ; disable power-event config bit
  757.         mov     al, 0xFF
  758.         out     dx, al
  759.  
  760.         ; clear power status (undocumented in vt6102 docs?)
  761.         set_io  [ebx + device.io_addr], byPwrcsrClr
  762.         out     dx, al
  763.  
  764.   .below_x40:
  765.  
  766. ; Reset the chip to erase previous misconfiguration.
  767.         set_io  [ebx + device.io_addr], 0
  768.         set_io  [ebx + device.io_addr], byCR0
  769.         mov     ax, CR_SFRST
  770.         out     dx, ax
  771.  
  772. ; if vt3043 delay after reset
  773.         cmp     [ebx + device.revision], 0x40
  774.         jae     @f
  775.         mov     esi, 200 ; 2000ms
  776.         invoke  Sleep
  777.    @@:
  778.  
  779. ; polling till software reset complete
  780.         mov     ecx, W_MAX_TIMEOUT
  781.    .poll_again:
  782.         in      ax, dx
  783.         test    ax, CR_SFRST
  784.         jz      @f
  785.         loop    .poll_again
  786.         DEBUGF  1, "Soft reset timeout!\n"
  787.    @@:
  788.  
  789. ; issue AUTOLoad in EECSR to reload eeprom
  790.         set_io  [ebx + device.io_addr], byEECSR
  791.         mov     al, 0x20
  792.         out     dx, al
  793.  
  794. ; if vt3065 delay after reset
  795.         cmp     [ebx + device.revision], 0x40
  796.         jb      .not_vt3065
  797.  
  798.         ; delay 10ms to let MAC stable
  799.         mov     esi, 1 ; 10ms
  800.         invoke  Sleep
  801.  
  802.         ; for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA
  803.         ; turned on.  it makes MAC receive magic packet
  804.         ; automatically. So, we turn it off. (D-Link)
  805.  
  806.         set_io  [ebx + device.io_addr], byCFGA
  807.         in      al, dx
  808.         and     al, 0xFE
  809.         out     dx, al
  810.  
  811.         ; turn on bit2 in PCI configuration register 0x53 , only for 3065
  812.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_REG_MODE3
  813.         or      al, MODE3_MIION
  814.         invoke  PciWrite8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_REG_MODE3, eax
  815.   .not_vt3065:
  816.  
  817. ; back off algorithm, disable the right-most 4-bit off CFGD
  818.         set_io  [ebx + device.io_addr], 0
  819.         set_io  [ebx + device.io_addr], byCFGD
  820.         in      al, dx
  821.         and     al, not (CFGD_RANDOM or CFGD_CFDX or CFGD_CEREN or CFGD_CETEN)
  822.         out     dx, al
  823.  
  824. ; reload eeprom
  825.         call    reload_eeprom
  826.  
  827. ; read MAC
  828.         call    read_mac
  829.  
  830. ; restart MII auto-negotiation
  831.         stdcall WriteMII, 0, 1 shl 9, 1
  832.  
  833.         DEBUGF  1, "Analyzing Media type, this may take several seconds"
  834.  
  835.         mov     ecx, 5
  836.      .read_again:
  837.         mov     esi, 1
  838.         invoke  Sleep
  839.  
  840.         stdcall ReadMII, 1
  841.         test    eax, 0x0020
  842.         jnz     .read_done
  843.         loop    .read_again
  844.         DEBUGF  1, "timeout!\n"
  845.      .read_done:
  846.         DEBUGF  1, "OK\n"
  847.  
  848. if 0
  849.  
  850.         set_io  [ebx + device.io_addr], 0
  851.         set_io  [ebx + device.io_addr], 0x6C
  852.         in      al, dx
  853.         and     eax, 0xFF
  854.         DEBUGF  1, "MII : Address %x\n", ax
  855.  
  856.         stdcall ReadMII, 1
  857.         DEBUGF  1, "status 0x%x\n", ax
  858.  
  859.         stdcall ReadMII, 4
  860.         DEBUGF  1, "advertising 0x%x\n", ax
  861.  
  862.         stdcall ReadMII, 5
  863.         DEBUGF  1, "link 0x%x\n", ax
  864.  
  865. end if
  866.  
  867. ; query MII to know LineSpeed, duplex mode
  868.         set_io  [ebx + device.io_addr], 0
  869.         set_io  [ebx + device.io_addr], MIIStatus
  870.         in      al, dx
  871.         test    al, MIISR_SPEED
  872.         jz      .100mbps
  873.         DEBUGF  1, "Linespeed=10Mbs\n"
  874.         jmp     @f
  875.  
  876.     .100mbps:
  877.         DEBUGF  1, "Linespeed=100Mbs\n"
  878.     @@:
  879.  
  880.         call    QueryAuto
  881.  
  882.         test    eax, 1
  883.         jz      .halfduplex
  884.  
  885.         DEBUGF  1, "Fullduplex\n"
  886.         set_io  [ebx + device.io_addr], 0
  887.         set_io  [ebx + device.io_addr], byCR0
  888.         mov     ax, CR_FDX
  889.         out     dx, ax
  890.         jmp     @f
  891.  
  892.     .halfduplex:
  893.         DEBUGF  1, "Halfduplex\n"
  894.     @@:
  895.  
  896. ; set MII 10 FULL ON, only apply in vt3043
  897.         cmp     [ebx + device.chip_did], 0x3043
  898.         jne     @f
  899.         stdcall WriteMII, 0x17, 1 shl 1, 1
  900.     @@:
  901.  
  902. ; turn on MII link change
  903.         set_io  [ebx + device.io_addr], 0
  904.         set_io  [ebx + device.io_addr], byMIICR
  905.         in      al, dx
  906.         and     al, 0x7F
  907.         out     dx, al
  908.         push    eax
  909.  
  910.         call    MIIDelay
  911.  
  912.         set_io  [ebx + device.io_addr], byMIIAD
  913.         mov     al, 0x41
  914.         out     dx, al
  915.  
  916.         call    MIIDelay
  917.  
  918.         pop     eax
  919.         or      al, 0x80
  920.         set_io  [ebx + device.io_addr], byMIICR
  921.         out     dx, al
  922.  
  923. ;**************************************************************************;
  924. ;* ETH_RESET - Reset adapter                                              *;
  925. ;**************************************************************************;
  926.  
  927. reset:
  928.  
  929.         DEBUGF  1, "reset\n"
  930.  
  931. ; attach int handler
  932.         movzx   eax, [ebx + device.irq_line]
  933.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  934.         invoke  AttachIntHandler, eax, int_handler, ebx
  935.         test    eax, eax
  936.         jz      .err
  937.  
  938. ; Soft reset the chip.
  939.         set_io  [ebx + device.io_addr], 0
  940.         set_io  [ebx + device.io_addr], byCR0
  941.         mov     ax, CR_SFRST
  942.         out     dx, ax
  943.  
  944.         call    MIIDelay
  945.  
  946. ; Initialize rings
  947.         call    init_ring
  948.         test    eax, eax
  949.         jnz     .err
  950.  
  951. ; Set Multicast
  952.         call    set_rx_mode
  953.  
  954. ; set TCR RCR threshold to store and forward
  955.         set_io  [ebx + device.io_addr], 0
  956.         set_io  [ebx + device.io_addr], byBCR0
  957.         mov     al, 0x3E
  958.         out     dx, al
  959.  
  960.         set_io  [ebx + device.io_addr], byBCR1
  961.         mov     al, 0x38
  962.         out     dx, al
  963.  
  964.         set_io  [ebx + device.io_addr], byRCR
  965.         mov     al, 0x2C
  966.         out     dx, al
  967.  
  968.         set_io  [ebx + device.io_addr], byTCR
  969.         mov     al, 0x60
  970.         out     dx, al
  971.  
  972. ; Set Fulldupex
  973.         call    QueryAuto
  974.         test    eax, eax        ; full duplex?
  975.         jz      @f
  976.  
  977.         set_io  [ebx + device.io_addr], 0
  978.         set_io  [ebx + device.io_addr], byCFGD
  979.         mov     al, CFGD_CFDX
  980.         out     dx, al
  981.  
  982.         set_io  [ebx + device.io_addr], byCR0
  983.         mov     ax, CR_FDX
  984.         out     dx, ax
  985.     @@:
  986.  
  987. ; ENABLE interrupts
  988.         set_io  [ebx + device.io_addr], 0
  989.         set_io  [ebx + device.io_addr], byIMR0
  990.         mov     ax, DEFAULT_INTR
  991.         out     dx, ax
  992.  
  993. ; KICK NIC to WORK
  994.  
  995.         set_io  [ebx + device.io_addr], byCR0
  996.         in      ax, dx
  997.         and     ax, not CR_STOP
  998.         or      ax, CR_STRT or CR_TXON or CR_RXON or CR_DPOLL
  999.         out     dx, ax
  1000.  
  1001. ; Set the mtu, kernel will be able to send now
  1002.         mov     [ebx + device.mtu], 1514
  1003.  
  1004. ; Set link state to unknown
  1005.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  1006.  
  1007. ; say reset was successful
  1008.         xor     eax, eax
  1009.         ret
  1010.  
  1011.   .err:
  1012.         DEBUGF  2,"Error!\n"
  1013.         or      eax, -1
  1014.         ret
  1015.  
  1016.  
  1017.  
  1018. align 4
  1019. unload:
  1020.  
  1021.         call    reset
  1022.         push    eax edx
  1023.         DEBUGF  1, "rhine disable\n"
  1024.  
  1025.         ; Switch to loopback mode to avoid hardware races.
  1026.         set_io  [ebx + device.io_addr], 0
  1027.         set_io  [ebx + device.io_addr], byTCR
  1028.         mov     al, 0x61
  1029.         out     dx, al
  1030.  
  1031.         ; Stop the chip's Tx and Rx processes.
  1032.         set_io  [ebx + device.io_addr], byCR0
  1033.         mov     ax, CR_STOP
  1034.         out     dx, ax
  1035.         pop     edx eax
  1036.  
  1037.         ret
  1038.  
  1039.  
  1040.  
  1041.  
  1042. align 4
  1043. reload_eeprom:
  1044.  
  1045.         DEBUGF  1, "Reload eeprom\n"
  1046.  
  1047.         set_io  [ebx + device.io_addr], 0
  1048.         set_io  [ebx + device.io_addr], byEECSR
  1049.         mov     al, 0x20
  1050.         out     dx, al
  1051.         ; Typically 2 cycles to reload.
  1052.         mov     ecx, 150
  1053.   .reload:
  1054.         in      al, dx
  1055.         test    al, 0x20
  1056.         jz      @f
  1057.         loop    .reload
  1058.         DEBUGF  2, "Reload eeprom: timeout!\n"
  1059.   @@:
  1060.  
  1061.         ret
  1062.  
  1063.  
  1064.  
  1065. ; Initialize the Rx and Tx rings, along with various 'dev' bits.
  1066. align 4
  1067. init_ring:
  1068.  
  1069.         DEBUGF  1, "Init ring\n"
  1070.  
  1071.         lea     edi, [ebx + device.rx_ring]
  1072.         mov     eax, edi
  1073.         invoke  GetPhysAddr
  1074.         mov     esi, eax
  1075.         push    esi
  1076.         mov     ecx, RX_RING_SIZE
  1077.    .rx_init:
  1078.         add     esi, sizeof.rx_head
  1079.         mov     [edi + rx_head.status], RX_SBITS_OWN_BIT
  1080.         mov     [edi + rx_head.control], PKT_BUF_SZ
  1081.         push    ecx
  1082.         invoke  NetAlloc, PKT_BUF_SZ+NET_BUFF.data
  1083.         pop     ecx
  1084.         test    eax, eax
  1085.         jz      .out_of_mem
  1086.         mov     [edi + rx_head.buff_addr_virt], eax
  1087.         invoke  GetPhysAddr
  1088.         add     eax, NET_BUFF.data
  1089.         mov     [edi + rx_head.buff_addr], eax                        ; buffer ptr
  1090.         mov     [edi + rx_head.next_desc], esi                        ; next head
  1091.         add     edi, sizeof.rx_head
  1092.         dec     ecx
  1093.         jnz     .rx_init
  1094.         pop     [edi - sizeof.rx_head + rx_head.next_desc]            ; Mark the last entry as wrapping the ring.
  1095.  
  1096.  
  1097.         lea     edi, [ebx + device.tx_ring]
  1098.         mov     eax, edi
  1099.         invoke  GetPhysAddr
  1100.         mov     esi, eax
  1101.         push    esi
  1102.         mov     ecx, TX_RING_SIZE
  1103.    .tx_init:
  1104.         add     esi, sizeof.tx_head
  1105.         mov     [edi + tx_head.status], 0
  1106.         mov     [edi + tx_head.control], 0x00E08000
  1107.         mov     [edi + tx_head.buff_addr], 0
  1108.         mov     [edi + tx_head.next_desc], esi
  1109.         mov     [edi + tx_head.buff_addr_virt], 0
  1110.         add     edi, sizeof.tx_head
  1111.         dec     ecx
  1112.         jnz     .tx_init
  1113.         pop     [edi - sizeof.tx_head + tx_head.next_desc]              ; Mark the last entry as wrapping the ring.
  1114.  
  1115. ; write Descriptors to MAC
  1116.         lea     eax, [ebx + device.rx_ring]
  1117.         invoke  GetPhysAddr
  1118.         set_io  [ebx + device.io_addr], 0
  1119.         set_io  [ebx + device.io_addr], dwCurrentRxDescAddr
  1120.         out     dx, eax
  1121.  
  1122.         lea     eax, [ebx + device.tx_ring]
  1123.         invoke  GetPhysAddr
  1124.         set_io  [ebx + device.io_addr], dwCurrentTxDescAddr
  1125.         out     dx, eax
  1126.  
  1127.         xor     eax, eax
  1128.         mov     [ebx + device.cur_rx], ax
  1129.         mov     [ebx + device.cur_tx], ax
  1130.         mov     [ebx + device.last_tx], ax
  1131.  
  1132.         xor     eax, eax
  1133.         ret
  1134.  
  1135.   .out_of_mem:
  1136.         add     esp, 4
  1137.         or      eax, -1
  1138.         ret
  1139.  
  1140.  
  1141. align 4
  1142. QueryAuto:
  1143.  
  1144.         DEBUGF  1, "Query Auto\n"
  1145.  
  1146.         push    ecx
  1147.         stdcall ReadMII, 0x04   ; advertised
  1148.         mov     ecx, eax
  1149.         stdcall ReadMII, 0x05
  1150.         and     ecx, eax
  1151.  
  1152.         xor     eax, eax
  1153.         test    ecx, 0x100
  1154.         jnz     .one
  1155.  
  1156.         and     ecx, 0x1C0
  1157.         cmp     ecx, 0x40
  1158.         jne     .zero
  1159.    .one:
  1160.         inc     eax
  1161.         DEBUGF  1, "AutoNego OK!\n"
  1162.    .zero:
  1163.         pop     ecx
  1164.  
  1165.         ret
  1166.  
  1167.  
  1168. proc    ReadMII stdcall, byMIIIndex:dword
  1169.  
  1170. ;        DEBUGF  1, "ReadMII Index=%x\n", [byMIIIndex]
  1171.  
  1172.         push    esi ebx ecx edx
  1173.  
  1174.         set_io  [ebx + device.io_addr], 0
  1175.         set_io  [ebx + device.io_addr], byMIIAD
  1176.         in      al, dx
  1177.         mov     bl, al
  1178.  
  1179.         set_io  [ebx + device.io_addr], byMIICR
  1180.         in      al, dx
  1181.         mov     bh, al
  1182.         and     al, 0x7F
  1183.         out     dx, al
  1184.  
  1185.         call    MIIDelay
  1186.  
  1187.         mov     al, byte [byMIIIndex]
  1188.         set_io  [ebx + device.io_addr], byMIIAD
  1189.         out     dx, al
  1190.  
  1191.         call    MIIDelay
  1192.  
  1193.         set_io  [ebx + device.io_addr], byMIICR
  1194.         in      al, dx
  1195.         or      al, 0x40
  1196.         out     dx, al
  1197.  
  1198.         mov     ecx, 200
  1199.   .read_again:
  1200.         in      al, dx
  1201.         test    al, 0x40
  1202.         jz      @f
  1203.  
  1204.         mov     esi, 10
  1205.         invoke  Sleep
  1206.         dec     ecx
  1207.         jnz     .read_again
  1208.         DEBUGF  2, "ReadMII: timeout!\n"
  1209.   @@:
  1210.  
  1211.         call    MIIDelay
  1212.  
  1213.         set_io  [ebx + device.io_addr], byMIIAD
  1214.         in      ax, dx
  1215.  
  1216.         push    eax
  1217.         mov     ax, bx
  1218.         set_io  [ebx + device.io_addr], byMIIAD
  1219.         out     dx, al
  1220.  
  1221.         shr     ax, 8
  1222.         set_io  [ebx + device.io_addr], byMIICR
  1223.         out     dx, al
  1224.  
  1225.         call    MIIDelay
  1226.  
  1227.         pop     eax
  1228.         and     eax, 0xFFFF
  1229.         rol     ax, 8
  1230.  
  1231.         pop     edx ecx ebx esi
  1232.         ret
  1233. endp
  1234.  
  1235.  
  1236.  
  1237. proc    WriteMII stdcall, byMIISetByte:dword, byMIISetBit:dword, byMIIOP:dword
  1238.  
  1239. ;        DEBUGF  1, "WriteMII SetByte=%x SetBit=%x OP=%x\n", [byMIISetByte], [byMIISetBit], [byMIIOP]
  1240.  
  1241.         push    ebx eax ecx edx
  1242.  
  1243.         set_io  [ebx + device.io_addr], 0
  1244.         set_io  [ebx + device.io_addr], byMIIAD
  1245.         in      al, dx
  1246.         mov     bl, al
  1247.  
  1248.         set_io  [ebx + device.io_addr], byMIICR
  1249.         in      al, dx
  1250.         mov     bh, al
  1251.         and     al, 0x7F
  1252.         out     dx, al
  1253.  
  1254.         call    MIIDelay
  1255.  
  1256.         mov     al, byte [byMIISetByte]
  1257.         set_io  [ebx + device.io_addr], byMIIAD
  1258.         out     dx, al
  1259.  
  1260.         call    MIIDelay
  1261.  
  1262.         set_io  [ebx + device.io_addr], byMIICR
  1263.         in      al, dx
  1264.         or      al, 0x40
  1265.         out     dx, al
  1266.  
  1267.         mov     ecx, 200
  1268.   .read_again0:
  1269.         in      al, dx
  1270.         test    al, 0x40
  1271.         jz      .done
  1272.  
  1273.         mov     esi, 10
  1274.         invoke  Sleep
  1275.         dec     ecx
  1276.         jnz     .read_again0
  1277.         DEBUGF  2, "WriteMII: timeout (1)\n"
  1278.   .done:
  1279.  
  1280.         call    MIIDelay
  1281.  
  1282.         set_io  [ebx + device.io_addr], wMIIDATA
  1283.         in      ax, dx
  1284.  
  1285.         mov     ecx, [byMIISetBit]
  1286.         rol     cx, 8
  1287.  
  1288.         cmp     byte [byMIIOP], 0
  1289.         jne     @f
  1290.         not     ecx
  1291.         and     ax, cx
  1292.         jmp     .end_mascarad
  1293.      @@:
  1294.         or      ax, cx
  1295.      .end_mascarad:
  1296.  
  1297.         set_io  [ebx + device.io_addr], wMIIDATA
  1298.         out     dx, ax
  1299.  
  1300.         call    MIIDelay
  1301.  
  1302.         set_io  [ebx + device.io_addr], byMIICR
  1303.         in      al, dx
  1304.         or      al, 0x20
  1305.         out     dx, al
  1306.  
  1307.         mov     ecx, 200
  1308.     .read_again1:
  1309.         in      al, dx
  1310.         test    al, 0x20
  1311.         jz      @f
  1312.  
  1313.         mov     esi, 10
  1314.         invoke  Sleep
  1315.         dec     ecx
  1316.         jnz     .read_again1
  1317.         DEBUGF  2, "WriteMII timeout (2)\n"
  1318.     @@:
  1319.  
  1320.         call    MIIDelay
  1321.  
  1322.         mov     ax, bx
  1323.         and     al, 0x7F
  1324.         set_io  [ebx + device.io_addr], byMIIAD
  1325.         out     dx, al
  1326.  
  1327.         shr     ax, 8
  1328.         set_io  [ebx + device.io_addr], byMIICR
  1329.         out     dx, al
  1330.  
  1331.         call    MIIDelay
  1332.  
  1333.         pop     edx ecx eax ebx
  1334.         ret
  1335. endp
  1336.  
  1337.  
  1338. align 4
  1339. MIIDelay:
  1340.  
  1341.         mov     ecx, 0x7FFF
  1342.     @@:
  1343.         in      al, 0x61
  1344.         in      al, 0x61
  1345.         in      al, 0x61
  1346.         in      al, 0x61
  1347.         loop    @b
  1348.  
  1349.         ret
  1350.  
  1351.  
  1352. align 4
  1353. set_rx_mode:
  1354.  
  1355.         DEBUGF  1, "Set RX mode\n"
  1356.  
  1357.         ; ! IFF_PROMISC
  1358.         mov     eax, 0xffffffff
  1359.         set_io  [ebx + device.io_addr], 0
  1360.         set_io  [ebx + device.io_addr], byMAR0
  1361.         out     dx, eax
  1362.  
  1363.         set_io  [ebx + device.io_addr], byMAR4
  1364.         out     dx, eax
  1365.  
  1366.         set_io  [ebx + device.io_addr], byRCR
  1367.         mov     al, 0x6C                ; thresh or rx_mode
  1368.         out     dx, al
  1369.  
  1370.         ret
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376. ; Beware of PCI posted writes
  1377. macro IOSYNC
  1378. {
  1379.         set_io  [ebx + device.io_addr], StationAddr
  1380.         in      al, dx
  1381. }
  1382.  
  1383.  
  1384.  
  1385. align 4
  1386. read_mac:
  1387.  
  1388.         lea     edi, [ebx + device.mac]
  1389.         set_io  [ebx + device.io_addr], 0
  1390.         set_io  [ebx + device.io_addr], byPAR0
  1391.         mov     ecx, 6
  1392.   .next:
  1393.         in      al, dx
  1394.         stosb
  1395.         inc     edx
  1396.         dec     ecx
  1397.         jnz     .next
  1398.  
  1399.         DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n", \
  1400.         [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
  1401.  
  1402.  
  1403.         ret
  1404.  
  1405.  
  1406. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1407. ;;                                         ;;
  1408. ;; Transmit                                ;;
  1409. ;;                                         ;;
  1410. ;; In: buffer pointer in [esp+4]           ;;
  1411. ;;     pointer to device structure in ebx  ;;
  1412. ;; Out: eax = 0 on success                 ;;
  1413. ;;                                         ;;
  1414. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1415. align 16
  1416. proc transmit stdcall bufferptr
  1417.  
  1418.         spin_lock_irqsave
  1419.  
  1420.         mov     esi, [bufferptr]
  1421.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
  1422.         lea     eax, [esi + NET_BUFF.data]
  1423.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  1424.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  1425.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  1426.         [eax+13]:2,[eax+12]:2
  1427.  
  1428.         cmp     [esi + NET_BUFF.length], 1514
  1429.         ja      .error
  1430.         cmp     [esi + NET_BUFF.length], 60
  1431.         jb      .error
  1432.  
  1433. ; Program the descriptor
  1434.         movzx   eax, [ebx + device.cur_tx]
  1435.         mov     ecx, sizeof.tx_head
  1436.         mul     ecx
  1437.         lea     edi, [ebx + device.tx_ring]
  1438.         add     edi, eax
  1439.  
  1440.         cmp     [edi + tx_head.buff_addr_virt], 0
  1441.         jne     .overrun
  1442.  
  1443.         mov     eax, esi
  1444.         mov     [edi + tx_head.buff_addr_virt], eax
  1445.         add     eax, [eax + NET_BUFF.offset]
  1446.         invoke  GetPhysAddr
  1447.         mov     [edi + tx_head.buff_addr], eax
  1448.         mov     ecx, [esi + NET_BUFF.length]
  1449.         and     ecx, TX_CBITS_TX_BUF_SIZE
  1450.         or      ecx,  0x00E08000
  1451.         mov     [edi + tx_head.control], ecx
  1452.         or      [edi + tx_head.status], TX_SBITS_OWN_BIT
  1453.  
  1454.         set_io  [ebx + device.io_addr], 0
  1455.         set_io  [ebx + device.io_addr], byCR1
  1456.         in      al, dx
  1457.         or      al, CR1_TDMD1
  1458.         out     dx, al
  1459.  
  1460.         inc     [ebx + device.cur_tx]
  1461.         and     [ebx + device.cur_tx], TX_RING_SIZE-1
  1462.  
  1463.         ;outw(IMRShadow,byIMR0); ;
  1464.  
  1465. ; Update stats
  1466.         inc     [ebx + device.packets_tx]
  1467.         mov     ecx, [esi + NET_BUFF.length]
  1468.         add     dword [ebx + device.bytes_tx], ecx
  1469.         adc     dword [ebx + device.bytes_tx + 4], 0
  1470.  
  1471.         spin_unlock_irqrestore
  1472.         xor     eax, eax
  1473.         ret
  1474.  
  1475.   .error:
  1476.         DEBUGF  2, "TX packet error\n"
  1477.         inc     [ebx + device.packets_tx_err]
  1478.         invoke  NetFree, [bufferptr]
  1479.  
  1480.         spin_unlock_irqrestore
  1481.         or      eax, -1
  1482.         ret
  1483.  
  1484.   .overrun:
  1485.         DEBUGF  2, "TX overrun\n"
  1486.         inc     [ebx + device.packets_tx_ovr]
  1487.         invoke  NetFree, [bufferptr]
  1488.  
  1489.         spin_unlock_irqrestore
  1490.         or      eax, -1
  1491.         ret
  1492.  
  1493.  
  1494. endp
  1495.  
  1496.  
  1497.  
  1498. ;;;;;;;;;;;;;;;;;;;;;;;
  1499. ;;                   ;;
  1500. ;; Interrupt handler ;;
  1501. ;;                   ;;
  1502. ;;;;;;;;;;;;;;;;;;;;;;;
  1503. align 16
  1504. int_handler:
  1505.  
  1506.         push    ebx esi edi
  1507.  
  1508.         mov     ebx, [esp+4*4]
  1509.         DEBUGF  1,"INT for 0x%x\n", ebx
  1510.  
  1511.         set_io  [ebx + device.io_addr], 0
  1512.         set_io  [ebx + device.io_addr], IntrStatus
  1513.         in      ax, dx
  1514.         test    ax, ax
  1515.         jz      .nothing
  1516.  
  1517.         out     dx, ax          ; ACK interrupt
  1518.         DEBUGF  1, "Status=0x%x\n", ax
  1519.  
  1520.         push    ax
  1521.  
  1522.         test    ax, IntrRxDone
  1523.         jz      .not_RX
  1524.  
  1525.         push    ebx
  1526.   .more_RX:
  1527.         pop     ebx
  1528.  
  1529. ; Get the current descriptor pointer
  1530.         movzx   eax, [ebx + device.cur_rx]
  1531.         mov     ecx, sizeof.rx_head
  1532.         mul     ecx
  1533.         lea     edi, [ebx + device.rx_ring]
  1534.         add     edi, eax
  1535.  
  1536. ; Check it's status
  1537.         test    [edi + rx_head.status], RX_SBITS_OWN_BIT
  1538.         jnz     .not_RX
  1539.  
  1540.         DEBUGF  1, "Packet status = 0x%x\n", [edi + rx_head.status]
  1541.  
  1542. ; TODO: check error bits
  1543.  
  1544. ; get length
  1545.         mov     ecx, [edi + rx_head.status]
  1546.         and     ecx, RX_SBITS_FRAME_LENGTH
  1547.         shr     ecx, 16
  1548.         sub     ecx, 4                          ; We dont want CRC
  1549.  
  1550. ; Update stats
  1551.         add     dword [ebx + device.bytes_rx], ecx
  1552.         adc     dword [ebx + device.bytes_rx + 4], 0
  1553.         inc     [ebx + device.packets_rx]
  1554.  
  1555. ; Push packet pointer, kernel will need it..
  1556.         push    ebx
  1557.         push    .more_RX                        ; return ptr
  1558.         mov     eax, [edi + rx_head.buff_addr_virt]
  1559.         push    eax
  1560.         mov     [eax + NET_BUFF.length], ecx
  1561.         mov     [eax + NET_BUFF.device], ebx
  1562.         mov     [eax + NET_BUFF.offset], NET_BUFF.data
  1563.  
  1564. ; reset the RX descriptor
  1565.         push    edi
  1566.         invoke  NetAlloc, PKT_BUF_SZ+NET_BUFF.data
  1567.         pop     edi
  1568.         mov     [edi + rx_head.buff_addr_virt], eax
  1569.         invoke  GetPhysAddr
  1570.         add     eax, NET_BUFF.data
  1571.         mov     [edi + rx_head.buff_addr], eax
  1572.         mov     [edi + rx_head.status], RX_SBITS_OWN_BIT
  1573.  
  1574. ; Use next descriptor next time
  1575.         inc     [ebx + device.cur_rx]
  1576.         and     [ebx + device.cur_rx], RX_RING_SIZE - 1
  1577.  
  1578. ; At last, send packet to kernel
  1579.         jmp     [EthInput]
  1580.  
  1581.   .not_RX:
  1582.         pop     ax
  1583.  
  1584.         test    ax, IntrTxDone
  1585.         jz      .not_TX
  1586.  
  1587.       .loop_tx:
  1588.         movzx   eax, [ebx + device.last_tx]
  1589.         mov     ecx, sizeof.tx_head
  1590.         mul     ecx
  1591.         lea     edi, [ebx + device.tx_ring]
  1592.         add     edi, eax
  1593.  
  1594.         test    [edi + tx_head.status], TX_SBITS_OWN_BIT
  1595.         jnz     .not_TX
  1596.  
  1597.         cmp     [edi + tx_head.buff_addr_virt], 0
  1598.         je      .not_TX
  1599.  
  1600.         DEBUGF  1,"Freeing buffer 0x%x\n", [edi + tx_head.buff_addr_virt]
  1601.  
  1602.         push    [edi + tx_head.buff_addr_virt]
  1603.         mov     [edi + tx_head.buff_addr_virt], 0
  1604.         invoke  NetFree
  1605.  
  1606.         inc     [ebx + device.last_tx]
  1607.         and     [ebx + device.last_tx], TX_RING_SIZE - 1
  1608.  
  1609.         jmp     .loop_tx
  1610.  
  1611.   .not_TX:
  1612.  
  1613.         ; On Rhine-II, Bit 3 indicates Tx descriptor write-back race.
  1614. if 0
  1615.         cmp     [ebx + device.chip_id], 0x3065
  1616.         jne     @f
  1617.         push    ax
  1618.         xor     eax, eax
  1619.         set_io  [ebx + device.io_addr], IntrStatus2
  1620.         in      al, dx
  1621.         shl     eax, 16
  1622.         pop     ax
  1623.     @@:
  1624. end if
  1625.  
  1626. if 0
  1627.  
  1628.         ; Acknowledge all of the current interrupt sources ASAP.
  1629.         xor     ecx, ecx
  1630.         test    eax, IntrTxDescRace
  1631.         jz      @f
  1632.         set_io  [ebx + device.io_addr], 0
  1633.         set_io  [ebx + device.io_addr], IntrStatus2
  1634.         push    ax
  1635.         mov     al, 0x08
  1636.         out     dx, al
  1637.         pop     ax
  1638.     @@:
  1639.         set_io  [ebx + device.io_addr], 0
  1640.         set_io  [ebx + device.io_addr], IntrStatus
  1641.         out     dx, ax
  1642.         IOSYNC
  1643.  
  1644. end if
  1645.  
  1646.         pop     edi esi ebx
  1647.         xor     eax, eax
  1648.         inc     eax
  1649.  
  1650.         ret
  1651.  
  1652.   .nothing:
  1653.         pop     edi esi ebx
  1654.         xor     eax, eax
  1655.  
  1656.         ret
  1657.  
  1658.  
  1659.  
  1660.  
  1661. ; End of code
  1662.  
  1663. data fixups
  1664. end data
  1665.  
  1666. include '../peimport.inc'
  1667.  
  1668. my_service      db 'RHINE',0                    ; max 16 chars including zero
  1669.  
  1670. chiplist:
  1671.                 dd 0x30431106, rhine_3043;, RHINE_IOTYPE, RHINE_I_IOSIZE, CanHaveMII or ReqTxAlign or HasV1TxStat
  1672.                 dd 0x61001106, rhine_6100;, RHINE_IOTYPE, RHINE_I_IOSIZE, CanHaveMII or ReqTxAlign or HasV1TxStat
  1673.                 dd 0x30651106, rhine_6102;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL
  1674.                 dd 0x31061106, rhine_6105;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL
  1675. ; Duplicate entry, with 'M' features enabled.
  1676. ;                dd 0x31061106, rhine_6105;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL or HasIPChecksum or HasVLAN
  1677.                 dd 0x30531106, rhine_3053;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL
  1678.                 dd 0
  1679.  
  1680. rhine_3043      db "VIA VT3043 Rhine", 0
  1681. rhine_6100      db "VIA VT86C100A Rhine", 0
  1682. rhine_6102      db "VIA VT6102 Rhine-II", 0
  1683. rhine_6105      db "VIA VT6105LOM Rhine-III (3106)", 0
  1684. rhine_3053      db "VIA VT6105M Rhine-III (3053 prototype)", 0
  1685.  
  1686. include_debug_strings                           ; All data which FDO uses will be included here
  1687.  
  1688. align 4
  1689. devices         dd 0
  1690. device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
  1691.  
  1692.