Subversion Repositories Kolibri OS

Rev

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 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_id         dw ?
  514.  
  515.         cur_rx          dw ?
  516.         cur_tx          dw ?
  517.         last_tx         dw ?
  518.  
  519.         rb 0x100 - ($ and 0xff) ; align 256
  520.         tx_ring         rb sizeof.tx_head*TX_RING_SIZE
  521.  
  522.         rb 0x100 - ($ and 0xff) ; align 256
  523.         rx_ring         rb sizeof.rx_head*RX_RING_SIZE
  524.  
  525. ends
  526.  
  527.  
  528. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  529. ;;                        ;;
  530. ;; proc START             ;;
  531. ;;                        ;;
  532. ;; (standard driver proc) ;;
  533. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  534.  
  535. proc START c, reason:dword, cmdline:dword
  536.  
  537.         cmp     [reason], DRV_ENTRY
  538.         jne     .fail
  539.  
  540.         DEBUGF  1,"Loading driver\n"
  541.         invoke  RegService, my_service, service_proc
  542.         ret
  543.  
  544.   .fail:
  545.         xor     eax, eax
  546.         ret
  547.  
  548. endp
  549.  
  550.  
  551. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  552. ;;                        ;;
  553. ;; proc SERVICE_PROC      ;;
  554. ;;                        ;;
  555. ;; (standard driver proc) ;;
  556. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  557.  
  558. proc service_proc stdcall, ioctl:dword
  559.  
  560.         mov     edx, [ioctl]
  561.         mov     eax, [edx + IOCTL.io_code]
  562.  
  563. ;------------------------------------------------------
  564.  
  565.         cmp     eax, 0 ;SRV_GETVERSION
  566.         jne     @F
  567.  
  568.         cmp     [edx + IOCTL.out_size], 4
  569.         jb      .fail
  570.         mov     eax, [edx + IOCTL.output]
  571.         mov     [eax], dword API_VERSION
  572.  
  573.         xor     eax, eax
  574.         ret
  575.  
  576. ;------------------------------------------------------
  577.   @@:
  578.         cmp     eax, 1 ;SRV_HOOK
  579.         jne     .fail
  580.  
  581.         cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
  582.         jb      .fail
  583.  
  584.         mov     eax, [edx + IOCTL.input]
  585.         cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
  586.         jne     .fail                                   ; other types aren't supported for this card yet
  587.  
  588. ; check if the device is already listed
  589.  
  590.         mov     esi, device_list
  591.         mov     ecx, [devices]
  592.         test    ecx, ecx
  593.         jz      .firstdevice
  594.  
  595. ;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
  596.         mov     ax, [eax+1]                             ;
  597.   .nextdevice:
  598.         mov     ebx, [esi]
  599.         cmp     al, byte[ebx + device.pci_bus]
  600.         jne     @f
  601.         cmp     ah, byte[ebx + device.pci_dev]
  602.         je      .find_devicenum                         ; Device is already loaded, let's find it's device number
  603.        @@:
  604.         add     esi, 4
  605.         loop    .nextdevice
  606.  
  607.  
  608. ; This device doesn't have its own eth_device structure yet, lets create one
  609.   .firstdevice:
  610.         cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
  611.         jae     .fail
  612.  
  613.         allocate_and_clear ebx, sizeof.device, .fail    ; Allocate the buffer for device structure
  614.  
  615. ; Fill in the direct call addresses into the struct
  616.  
  617.         mov     [ebx + device.reset], reset
  618.         mov     [ebx + device.transmit], transmit
  619.         mov     [ebx + device.unload], unload
  620.         mov     [ebx + device.name], my_service
  621.  
  622. ; save the pci bus and device numbers
  623.  
  624.         mov     eax, [edx + IOCTL.input]
  625.         movzx   ecx, byte[eax+1]
  626.         mov     [ebx + device.pci_bus], ecx
  627.         movzx   ecx, byte[eax+2]
  628.         mov     [ebx + device.pci_dev], ecx
  629.  
  630. ; Now, it's time to find the base io address of the PCI device
  631.  
  632.         stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
  633.         mov     [ebx + device.io_addr], eax
  634.  
  635. ; We've found the io address, find IRQ now
  636.  
  637.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
  638.         mov     [ebx + device.irq_line], al
  639.  
  640.         DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
  641.         [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:4
  642.  
  643. ; Ok, the eth_device structure is ready, let's probe the device
  644.         call    probe                                                   ; this function will output in eax
  645.         test    eax, eax
  646.         jnz     .err                                                    ; If an error occurred, exit
  647.  
  648.         mov     eax, [devices]                                          ; Add the device structure to our device list
  649.         mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
  650.         inc     [devices]                                               ;
  651.  
  652.         mov     [ebx + device.type], NET_TYPE_ETH
  653.         invoke  NetRegDev
  654.  
  655.         cmp     eax, -1
  656.         je      .destroy
  657.  
  658.         ret
  659.  
  660. ; If the device was already loaded, find the device number and return it in eax
  661.  
  662.   .find_devicenum:
  663.         DEBUGF  1,"Trying to find device number of already registered device\n"
  664.         invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
  665.                                                                         ; into a device number in edi
  666.         mov     eax, edi                                                ; Application wants it in eax instead
  667.         DEBUGF  1,"Kernel says: %u\n", eax
  668.         ret
  669.  
  670. ; If an error occurred, remove all allocated data and exit (returning -1 in eax)
  671.  
  672.   .destroy:
  673.         ; todo: reset device into virgin state
  674.  
  675.   .err:
  676.         invoke  KernelFree, ebx
  677.  
  678.   .fail:
  679.         or      eax, -1
  680.         ret
  681.  
  682. ;------------------------------------------------------
  683. endp
  684.  
  685.  
  686. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  687. ;;                                                                        ;;
  688. ;;        Actual Hardware dependent code starts here                      ;;
  689. ;;                                                                        ;;
  690. ;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
  691.  
  692.  
  693. ;-------
  694. ;
  695. ; PROBE
  696. ;
  697. ;-------
  698. probe:
  699.  
  700.         DEBUGF  1, "Probing\n"
  701.  
  702.  
  703. ; Make the device a bus master
  704.         invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
  705.         or      al, PCI_CMD_MASTER
  706.         invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
  707.  
  708. ; get device id
  709.         invoke  PciRead16, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.device_id
  710.         mov     [ebx + device.chip_id], ax
  711.  
  712.         mov     esi, chiplist
  713.   .loop:
  714.         cmp     word[esi+2], ax
  715.         je      .got_it
  716.         add     esi, 8
  717.         cmp     esi, chiplist + 6*8
  718.         jbe     .loop
  719.         DEBUGF  2, "Unknown chip: 0x%x, continuing anyway\n", ax
  720.         jmp     .done
  721.   .got_it:
  722.         mov     eax, dword[esi+4]
  723.         mov     [ebx + device.name], eax
  724.         DEBUGF  1, "Chip type = %s\n", eax
  725.   .done:
  726.  
  727. ; get revision id.
  728.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.revision_id
  729.         mov     [ebx + device.revision], al
  730.  
  731.         movzx   eax, [ebx + device.revision]
  732.         DEBUGF  1, "Card revision = 0x%x\n", eax
  733.  
  734. ; D-Link provided reset code (with comment additions)
  735.         cmp     al, 0x40
  736.         jb      .below_x40
  737.  
  738.         mov     ax, [ebx + device.chip_id]
  739.         DEBUGF  1, "Enabling Sticky Bit Workaround for Chip_id: 0x%x\n", ax
  740.  
  741.         ; clear sticky bit before reset & read ethernet address
  742.         set_io  [ebx + device.io_addr], 0
  743.         set_io  [ebx + device.io_addr], bySTICKHW
  744.         in      al, dx
  745.         and     al, 0xFC
  746.         out     dx, al
  747.  
  748.         ; (bits written are cleared?)
  749.         ; disable force PME-enable
  750.         set_io  [ebx + device.io_addr], byWOLcgClr
  751.         mov     al, 0x80
  752.         out     dx, al
  753.  
  754.         ; disable power-event config bit
  755.         mov     al, 0xFF
  756.         out     dx, al
  757.  
  758.         ; clear power status (undocumented in vt6102 docs?)
  759.         set_io  [ebx + device.io_addr], byPwrcsrClr
  760.         out     dx, al
  761.  
  762.   .below_x40:
  763.  
  764. ; Reset the chip to erase previous misconfiguration.
  765.         set_io  [ebx + device.io_addr], 0
  766.         set_io  [ebx + device.io_addr], byCR0
  767.         mov     ax, CR_SFRST
  768.         out     dx, ax
  769.  
  770. ; if vt3043 delay after reset
  771.         cmp     [ebx + device.revision], 0x40
  772.         jae     @f
  773.         mov     esi, 200 ; 2000ms
  774.         invoke  Sleep
  775.    @@:
  776.  
  777. ; polling till software reset complete
  778.         mov     ecx, W_MAX_TIMEOUT
  779.    .poll_again:
  780.         in      ax, dx
  781.         test    ax, CR_SFRST
  782.         jz      @f
  783.         loop    .poll_again
  784.         DEBUGF  1, "Soft reset timeout!\n"
  785.    @@:
  786.  
  787. ; issue AUTOLoad in EECSR to reload eeprom
  788.         set_io  [ebx + device.io_addr], byEECSR
  789.         mov     al, 0x20
  790.         out     dx, al
  791.  
  792. ; if vt3065 delay after reset
  793.         cmp     [ebx + device.revision], 0x40
  794.         jb      .not_vt3065
  795.  
  796.         ; delay 10ms to let MAC stable
  797.         mov     esi, 1 ; 10ms
  798.         invoke  Sleep
  799.  
  800.         ; for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA
  801.         ; turned on.  it makes MAC receive magic packet
  802.         ; automatically. So, we turn it off. (D-Link)
  803.  
  804.         set_io  [ebx + device.io_addr], byCFGA
  805.         in      al, dx
  806.         and     al, 0xFE
  807.         out     dx, al
  808.  
  809.         ; turn on bit2 in PCI configuration register 0x53 , only for 3065
  810.         invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_REG_MODE3
  811.         or      al, MODE3_MIION
  812.         invoke  PciWrite8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_REG_MODE3, eax
  813.   .not_vt3065:
  814.  
  815. ; back off algorithm, disable the right-most 4-bit off CFGD
  816.         set_io  [ebx + device.io_addr], 0
  817.         set_io  [ebx + device.io_addr], byCFGD
  818.         in      al, dx
  819.         and     al, not (CFGD_RANDOM or CFGD_CFDX or CFGD_CEREN or CFGD_CETEN)
  820.         out     dx, al
  821.  
  822. ; reload eeprom
  823.         call    reload_eeprom
  824.  
  825. ; read MAC
  826.         call    read_mac
  827.  
  828. ; restart MII auto-negotiation
  829.         stdcall WriteMII, 0, 1 shl 9, 1
  830.  
  831.         DEBUGF  1, "Analyzing Media type, this may take several seconds"
  832.  
  833.         mov     ecx, 5
  834.      .read_again:
  835.         mov     esi, 1
  836.         invoke  Sleep
  837.  
  838.         stdcall ReadMII, 1
  839.         test    eax, 0x0020
  840.         jnz     .read_done
  841.         loop    .read_again
  842.         DEBUGF  1, "timeout!\n"
  843.      .read_done:
  844.         DEBUGF  1, "OK\n"
  845.  
  846. if 0
  847.  
  848.         set_io  [ebx + device.io_addr], 0
  849.         set_io  [ebx + device.io_addr], 0x6C
  850.         in      al, dx
  851.         and     eax, 0xFF
  852.         DEBUGF  1, "MII : Address %x\n", ax
  853.  
  854.         stdcall ReadMII, 1
  855.         DEBUGF  1, "status 0x%x\n", ax
  856.  
  857.         stdcall ReadMII, 4
  858.         DEBUGF  1, "advertising 0x%x\n", ax
  859.  
  860.         stdcall ReadMII, 5
  861.         DEBUGF  1, "link 0x%x\n", ax
  862.  
  863. end if
  864.  
  865. ; query MII to know LineSpeed, duplex mode
  866.         set_io  [ebx + device.io_addr], 0
  867.         set_io  [ebx + device.io_addr], MIIStatus
  868.         in      al, dx
  869.         test    al, MIISR_SPEED
  870.         jz      .100mbps
  871.         DEBUGF  1, "Linespeed=10Mbs\n"
  872.         jmp     @f
  873.  
  874.     .100mbps:
  875.         DEBUGF  1, "Linespeed=100Mbs\n"
  876.     @@:
  877.  
  878.         call    QueryAuto
  879.  
  880.         test    eax, 1
  881.         jz      .halfduplex
  882.  
  883.         DEBUGF  1, "Fullduplex\n"
  884.         set_io  [ebx + device.io_addr], 0
  885.         set_io  [ebx + device.io_addr], byCR0
  886.         mov     ax, CR_FDX
  887.         out     dx, ax
  888.         jmp     @f
  889.  
  890.     .halfduplex:
  891.         DEBUGF  1, "Halfduplex\n"
  892.     @@:
  893.  
  894. ; set MII 10 FULL ON, only apply in vt3043
  895.         cmp     [ebx + device.chip_id], 0x3043
  896.         jne     @f
  897.         stdcall WriteMII, 0x17, 1 shl 1, 1
  898.     @@:
  899.  
  900. ; turn on MII link change
  901.         set_io  [ebx + device.io_addr], 0
  902.         set_io  [ebx + device.io_addr], byMIICR
  903.         in      al, dx
  904.         and     al, 0x7F
  905.         out     dx, al
  906.         push    eax
  907.  
  908.         call    MIIDelay
  909.  
  910.         set_io  [ebx + device.io_addr], byMIIAD
  911.         mov     al, 0x41
  912.         out     dx, al
  913.  
  914.         call    MIIDelay
  915.  
  916.         pop     eax
  917.         or      al, 0x80
  918.         set_io  [ebx + device.io_addr], byMIICR
  919.         out     dx, al
  920.  
  921. ;**************************************************************************;
  922. ;* ETH_RESET - Reset adapter                                              *;
  923. ;**************************************************************************;
  924.  
  925. reset:
  926.  
  927.         DEBUGF  1, "reset\n"
  928.  
  929. ; attach int handler
  930.         movzx   eax, [ebx + device.irq_line]
  931.         DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
  932.         invoke  AttachIntHandler, eax, int_handler, ebx
  933.         test    eax, eax
  934.         jz      .err
  935.  
  936. ; Soft reset the chip.
  937.         set_io  [ebx + device.io_addr], 0
  938.         set_io  [ebx + device.io_addr], byCR0
  939.         mov     ax, CR_SFRST
  940.         out     dx, ax
  941.  
  942.         call    MIIDelay
  943.  
  944. ; Initialize rings
  945.         call    init_ring
  946.         test    eax, eax
  947.         jnz     .err
  948.  
  949. ; Set Multicast
  950.         call    set_rx_mode
  951.  
  952. ; set TCR RCR threshold to store and forward
  953.         set_io  [ebx + device.io_addr], 0
  954.         set_io  [ebx + device.io_addr], byBCR0
  955.         mov     al, 0x3E
  956.         out     dx, al
  957.  
  958.         set_io  [ebx + device.io_addr], byBCR1
  959.         mov     al, 0x38
  960.         out     dx, al
  961.  
  962.         set_io  [ebx + device.io_addr], byRCR
  963.         mov     al, 0x2C
  964.         out     dx, al
  965.  
  966.         set_io  [ebx + device.io_addr], byTCR
  967.         mov     al, 0x60
  968.         out     dx, al
  969.  
  970. ; Set Fulldupex
  971.         call    QueryAuto
  972.         test    eax, eax        ; full duplex?
  973.         jz      @f
  974.  
  975.         set_io  [ebx + device.io_addr], 0
  976.         set_io  [ebx + device.io_addr], byCFGD
  977.         mov     al, CFGD_CFDX
  978.         out     dx, al
  979.  
  980.         set_io  [ebx + device.io_addr], byCR0
  981.         mov     ax, CR_FDX
  982.         out     dx, ax
  983.     @@:
  984.  
  985. ; ENABLE interrupts
  986.         set_io  [ebx + device.io_addr], 0
  987.         set_io  [ebx + device.io_addr], byIMR0
  988.         mov     ax, DEFAULT_INTR
  989.         out     dx, ax
  990.  
  991. ; KICK NIC to WORK
  992.  
  993.         set_io  [ebx + device.io_addr], byCR0
  994.         in      ax, dx
  995.         and     ax, not CR_STOP
  996.         or      ax, CR_STRT or CR_TXON or CR_RXON or CR_DPOLL
  997.         out     dx, ax
  998.  
  999. ; Set the mtu, kernel will be able to send now
  1000.         mov     [ebx + device.mtu], 1514
  1001.  
  1002. ; Set link state to unknown
  1003.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  1004.  
  1005. ; say reset was successful
  1006.         xor     eax, eax
  1007.         ret
  1008.  
  1009.   .err:
  1010.         DEBUGF  2,"Error!\n"
  1011.         or      eax, -1
  1012.         ret
  1013.  
  1014.  
  1015.  
  1016. align 4
  1017. unload:
  1018.  
  1019.         call    reset
  1020.         push    eax edx
  1021.         DEBUGF  1, "rhine disable\n"
  1022.  
  1023.         ; Switch to loopback mode to avoid hardware races.
  1024.         set_io  [ebx + device.io_addr], 0
  1025.         set_io  [ebx + device.io_addr], byTCR
  1026.         mov     al, 0x61
  1027.         out     dx, al
  1028.  
  1029.         ; Stop the chip's Tx and Rx processes.
  1030.         set_io  [ebx + device.io_addr], byCR0
  1031.         mov     ax, CR_STOP
  1032.         out     dx, ax
  1033.         pop     edx eax
  1034.  
  1035.         ret
  1036.  
  1037.  
  1038.  
  1039.  
  1040. align 4
  1041. reload_eeprom:
  1042.  
  1043.         DEBUGF  1, "Reload eeprom\n"
  1044.  
  1045.         set_io  [ebx + device.io_addr], 0
  1046.         set_io  [ebx + device.io_addr], byEECSR
  1047.         mov     al, 0x20
  1048.         out     dx, al
  1049.         ; Typically 2 cycles to reload.
  1050.         mov     ecx, 150
  1051.   .reload:
  1052.         in      al, dx
  1053.         test    al, 0x20
  1054.         jz      @f
  1055.         loop    .reload
  1056.         DEBUGF  2, "Reload eeprom: timeout!\n"
  1057.   @@:
  1058.  
  1059.         ret
  1060.  
  1061.  
  1062.  
  1063. ; Initialize the Rx and Tx rings, along with various 'dev' bits.
  1064. align 4
  1065. init_ring:
  1066.  
  1067.         DEBUGF  1, "Init ring\n"
  1068.  
  1069.         lea     edi, [ebx + device.rx_ring]
  1070.         mov     eax, edi
  1071.         invoke  GetPhysAddr
  1072.         mov     esi, eax
  1073.         push    esi
  1074.         mov     ecx, RX_RING_SIZE
  1075.    .rx_init:
  1076.         add     esi, sizeof.rx_head
  1077.         mov     [edi + rx_head.status], RX_SBITS_OWN_BIT
  1078.         mov     [edi + rx_head.control], PKT_BUF_SZ
  1079.         push    ecx
  1080.         invoke  NetAlloc, PKT_BUF_SZ+NET_BUFF.data
  1081.         pop     ecx
  1082.         test    eax, eax
  1083.         jz      .out_of_mem
  1084.         mov     [edi + rx_head.buff_addr_virt], eax
  1085.         invoke  GetPhysAddr
  1086.         add     eax, NET_BUFF.data
  1087.         mov     [edi + rx_head.buff_addr], eax                        ; buffer ptr
  1088.         mov     [edi + rx_head.next_desc], esi                        ; next head
  1089.         add     edi, sizeof.rx_head
  1090.         dec     ecx
  1091.         jnz     .rx_init
  1092.         pop     [edi - sizeof.rx_head + rx_head.next_desc]            ; Mark the last entry as wrapping the ring.
  1093.  
  1094.  
  1095.         lea     edi, [ebx + device.tx_ring]
  1096.         mov     eax, edi
  1097.         invoke  GetPhysAddr
  1098.         mov     esi, eax
  1099.         push    esi
  1100.         mov     ecx, TX_RING_SIZE
  1101.    .tx_init:
  1102.         add     esi, sizeof.tx_head
  1103.         mov     [edi + tx_head.status], 0
  1104.         mov     [edi + tx_head.control], 0x00E08000
  1105.         mov     [edi + tx_head.buff_addr], 0
  1106.         mov     [edi + tx_head.next_desc], esi
  1107.         mov     [edi + tx_head.buff_addr_virt], 0
  1108.         add     edi, sizeof.tx_head
  1109.         dec     ecx
  1110.         jnz     .tx_init
  1111.         pop     [edi - sizeof.tx_head + tx_head.next_desc]              ; Mark the last entry as wrapping the ring.
  1112.  
  1113. ; write Descriptors to MAC
  1114.         lea     eax, [ebx + device.rx_ring]
  1115.         invoke  GetPhysAddr
  1116.         set_io  [ebx + device.io_addr], 0
  1117.         set_io  [ebx + device.io_addr], dwCurrentRxDescAddr
  1118.         out     dx, eax
  1119.  
  1120.         lea     eax, [ebx + device.tx_ring]
  1121.         invoke  GetPhysAddr
  1122.         set_io  [ebx + device.io_addr], dwCurrentTxDescAddr
  1123.         out     dx, eax
  1124.  
  1125.         xor     eax, eax
  1126.         mov     [ebx + device.cur_rx], ax
  1127.         mov     [ebx + device.cur_tx], ax
  1128.         mov     [ebx + device.last_tx], ax
  1129.  
  1130.         xor     eax, eax
  1131.         ret
  1132.  
  1133.   .out_of_mem:
  1134.         add     esp, 4
  1135.         or      eax, -1
  1136.         ret
  1137.  
  1138.  
  1139. align 4
  1140. QueryAuto:
  1141.  
  1142.         DEBUGF  1, "Query Auto\n"
  1143.  
  1144.         push    ecx
  1145.         stdcall ReadMII, 0x04   ; advertised
  1146.         mov     ecx, eax
  1147.         stdcall ReadMII, 0x05
  1148.         and     ecx, eax
  1149.  
  1150.         xor     eax, eax
  1151.         test    ecx, 0x100
  1152.         jnz     .one
  1153.  
  1154.         and     ecx, 0x1C0
  1155.         cmp     ecx, 0x40
  1156.         jne     .zero
  1157.    .one:
  1158.         inc     eax
  1159.         DEBUGF  1, "AutoNego OK!\n"
  1160.    .zero:
  1161.         pop     ecx
  1162.  
  1163.         ret
  1164.  
  1165.  
  1166. proc    ReadMII stdcall, byMIIIndex:dword
  1167.  
  1168. ;        DEBUGF  1, "ReadMII Index=%x\n", [byMIIIndex]
  1169.  
  1170.         push    esi ebx ecx edx
  1171.  
  1172.         set_io  [ebx + device.io_addr], 0
  1173.         set_io  [ebx + device.io_addr], byMIIAD
  1174.         in      al, dx
  1175.         mov     bl, al
  1176.  
  1177.         set_io  [ebx + device.io_addr], byMIICR
  1178.         in      al, dx
  1179.         mov     bh, al
  1180.         and     al, 0x7F
  1181.         out     dx, al
  1182.  
  1183.         call    MIIDelay
  1184.  
  1185.         mov     al, byte [byMIIIndex]
  1186.         set_io  [ebx + device.io_addr], byMIIAD
  1187.         out     dx, al
  1188.  
  1189.         call    MIIDelay
  1190.  
  1191.         set_io  [ebx + device.io_addr], byMIICR
  1192.         in      al, dx
  1193.         or      al, 0x40
  1194.         out     dx, al
  1195.  
  1196.         mov     ecx, 200
  1197.   .read_again:
  1198.         in      al, dx
  1199.         test    al, 0x40
  1200.         jz      @f
  1201.  
  1202.         mov     esi, 10
  1203.         invoke  Sleep
  1204.         dec     ecx
  1205.         jnz     .read_again
  1206.         DEBUGF  2, "ReadMII: timeout!\n"
  1207.   @@:
  1208.  
  1209.         call    MIIDelay
  1210.  
  1211.         set_io  [ebx + device.io_addr], byMIIAD
  1212.         in      ax, dx
  1213.  
  1214.         push    eax
  1215.         mov     ax, bx
  1216.         set_io  [ebx + device.io_addr], byMIIAD
  1217.         out     dx, al
  1218.  
  1219.         shr     ax, 8
  1220.         set_io  [ebx + device.io_addr], byMIICR
  1221.         out     dx, al
  1222.  
  1223.         call    MIIDelay
  1224.  
  1225.         pop     eax
  1226.         and     eax, 0xFFFF
  1227.         rol     ax, 8
  1228.  
  1229.         pop     edx ecx ebx esi
  1230.         ret
  1231. endp
  1232.  
  1233.  
  1234.  
  1235. proc    WriteMII stdcall, byMIISetByte:dword, byMIISetBit:dword, byMIIOP:dword
  1236.  
  1237. ;        DEBUGF  1, "WriteMII SetByte=%x SetBit=%x OP=%x\n", [byMIISetByte], [byMIISetBit], [byMIIOP]
  1238.  
  1239.         push    ebx eax ecx edx
  1240.  
  1241.         set_io  [ebx + device.io_addr], 0
  1242.         set_io  [ebx + device.io_addr], byMIIAD
  1243.         in      al, dx
  1244.         mov     bl, al
  1245.  
  1246.         set_io  [ebx + device.io_addr], byMIICR
  1247.         in      al, dx
  1248.         mov     bh, al
  1249.         and     al, 0x7F
  1250.         out     dx, al
  1251.  
  1252.         call    MIIDelay
  1253.  
  1254.         mov     al, byte [byMIISetByte]
  1255.         set_io  [ebx + device.io_addr], byMIIAD
  1256.         out     dx, al
  1257.  
  1258.         call    MIIDelay
  1259.  
  1260.         set_io  [ebx + device.io_addr], byMIICR
  1261.         in      al, dx
  1262.         or      al, 0x40
  1263.         out     dx, al
  1264.  
  1265.         mov     ecx, 200
  1266.   .read_again0:
  1267.         in      al, dx
  1268.         test    al, 0x40
  1269.         jz      .done
  1270.  
  1271.         mov     esi, 10
  1272.         invoke  Sleep
  1273.         dec     ecx
  1274.         jnz     .read_again0
  1275.         DEBUGF  2, "WriteMII: timeout (1)\n"
  1276.   .done:
  1277.  
  1278.         call    MIIDelay
  1279.  
  1280.         set_io  [ebx + device.io_addr], wMIIDATA
  1281.         in      ax, dx
  1282.  
  1283.         mov     ecx, [byMIISetBit]
  1284.         rol     cx, 8
  1285.  
  1286.         cmp     byte [byMIIOP], 0
  1287.         jne     @f
  1288.         not     ecx
  1289.         and     ax, cx
  1290.         jmp     .end_mascarad
  1291.      @@:
  1292.         or      ax, cx
  1293.      .end_mascarad:
  1294.  
  1295.         set_io  [ebx + device.io_addr], wMIIDATA
  1296.         out     dx, ax
  1297.  
  1298.         call    MIIDelay
  1299.  
  1300.         set_io  [ebx + device.io_addr], byMIICR
  1301.         in      al, dx
  1302.         or      al, 0x20
  1303.         out     dx, al
  1304.  
  1305.         mov     ecx, 200
  1306.     .read_again1:
  1307.         in      al, dx
  1308.         test    al, 0x20
  1309.         jz      @f
  1310.  
  1311.         mov     esi, 10
  1312.         invoke  Sleep
  1313.         dec     ecx
  1314.         jnz     .read_again1
  1315.         DEBUGF  2, "WriteMII timeout (2)\n"
  1316.     @@:
  1317.  
  1318.         call    MIIDelay
  1319.  
  1320.         mov     ax, bx
  1321.         and     al, 0x7F
  1322.         set_io  [ebx + device.io_addr], byMIIAD
  1323.         out     dx, al
  1324.  
  1325.         shr     ax, 8
  1326.         set_io  [ebx + device.io_addr], byMIICR
  1327.         out     dx, al
  1328.  
  1329.         call    MIIDelay
  1330.  
  1331.         pop     edx ecx eax ebx
  1332.         ret
  1333. endp
  1334.  
  1335.  
  1336. align 4
  1337. MIIDelay:
  1338.  
  1339.         mov     ecx, 0x7FFF
  1340.     @@:
  1341.         in      al, 0x61
  1342.         in      al, 0x61
  1343.         in      al, 0x61
  1344.         in      al, 0x61
  1345.         loop    @b
  1346.  
  1347.         ret
  1348.  
  1349.  
  1350. align 4
  1351. set_rx_mode:
  1352.  
  1353.         DEBUGF  1, "Set RX mode\n"
  1354.  
  1355.         ; ! IFF_PROMISC
  1356.         mov     eax, 0xffffffff
  1357.         set_io  [ebx + device.io_addr], 0
  1358.         set_io  [ebx + device.io_addr], byMAR0
  1359.         out     dx, eax
  1360.  
  1361.         set_io  [ebx + device.io_addr], byMAR4
  1362.         out     dx, eax
  1363.  
  1364.         set_io  [ebx + device.io_addr], byRCR
  1365.         mov     al, 0x6C                ; thresh or rx_mode
  1366.         out     dx, al
  1367.  
  1368.         ret
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374. ; Beware of PCI posted writes
  1375. macro IOSYNC
  1376. {
  1377.         set_io  [ebx + device.io_addr], StationAddr
  1378.         in      al, dx
  1379. }
  1380.  
  1381.  
  1382.  
  1383. align 4
  1384. read_mac:
  1385.  
  1386.         lea     edi, [ebx + device.mac]
  1387.         set_io  [ebx + device.io_addr], 0
  1388.         set_io  [ebx + device.io_addr], byPAR0
  1389.         mov     ecx, 6
  1390.   .next:
  1391.         in      al, dx
  1392.         stosb
  1393.         inc     edx
  1394.         dec     ecx
  1395.         jnz     .next
  1396.  
  1397.         DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n", \
  1398.         [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
  1399.  
  1400.  
  1401.         ret
  1402.  
  1403.  
  1404. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1405. ;;                                         ;;
  1406. ;; Transmit                                ;;
  1407. ;;                                         ;;
  1408. ;; In: buffer pointer in [esp+4]           ;;
  1409. ;;     pointer to device structure in ebx  ;;
  1410. ;; Out: eax = 0 on success                 ;;
  1411. ;;                                         ;;
  1412. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1413. align 16
  1414. proc transmit stdcall bufferptr
  1415.  
  1416.         spin_lock_irqsave
  1417.  
  1418.         mov     esi, [bufferptr]
  1419.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
  1420.         lea     eax, [esi + NET_BUFF.data]
  1421.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  1422.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  1423.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  1424.         [eax+13]:2,[eax+12]:2
  1425.  
  1426.         cmp     [esi + NET_BUFF.length], 1514
  1427.         ja      .error
  1428.         cmp     [esi + NET_BUFF.length], 60
  1429.         jb      .error
  1430.  
  1431. ; Program the descriptor
  1432.         movzx   eax, [ebx + device.cur_tx]
  1433.         mov     ecx, sizeof.tx_head
  1434.         mul     ecx
  1435.         lea     edi, [ebx + device.tx_ring]
  1436.         add     edi, eax
  1437.  
  1438.         cmp     [edi + tx_head.buff_addr_virt], 0
  1439.         jne     .overrun
  1440.  
  1441.         mov     eax, esi
  1442.         mov     [edi + tx_head.buff_addr_virt], eax
  1443.         add     eax, [eax + NET_BUFF.offset]
  1444.         invoke  GetPhysAddr
  1445.         mov     [edi + tx_head.buff_addr], eax
  1446.         mov     ecx, [esi + NET_BUFF.length]
  1447.         and     ecx, TX_CBITS_TX_BUF_SIZE
  1448.         or      ecx,  0x00E08000
  1449.         mov     [edi + tx_head.control], ecx
  1450.         or      [edi + tx_head.status], TX_SBITS_OWN_BIT
  1451.  
  1452.         set_io  [ebx + device.io_addr], 0
  1453.         set_io  [ebx + device.io_addr], byCR1
  1454.         in      al, dx
  1455.         or      al, CR1_TDMD1
  1456.         out     dx, al
  1457.  
  1458.         inc     [ebx + device.cur_tx]
  1459.         and     [ebx + device.cur_tx], TX_RING_SIZE-1
  1460.  
  1461.         ;outw(IMRShadow,byIMR0); ;
  1462.  
  1463. ; Update stats
  1464.         inc     [ebx + device.packets_tx]
  1465.         mov     ecx, [esi + NET_BUFF.length]
  1466.         add     dword [ebx + device.bytes_tx], ecx
  1467.         adc     dword [ebx + device.bytes_tx + 4], 0
  1468.  
  1469.         spin_unlock_irqrestore
  1470.         xor     eax, eax
  1471.         ret
  1472.  
  1473.   .error:
  1474.         DEBUGF  2, "TX packet error\n"
  1475.         inc     [ebx + device.packets_tx_err]
  1476.         invoke  NetFree, [bufferptr]
  1477.  
  1478.         spin_unlock_irqrestore
  1479.         or      eax, -1
  1480.         ret
  1481.  
  1482.   .overrun:
  1483.         DEBUGF  2, "TX overrun\n"
  1484.         inc     [ebx + device.packets_tx_ovr]
  1485.         invoke  NetFree, [bufferptr]
  1486.  
  1487.         spin_unlock_irqrestore
  1488.         or      eax, -1
  1489.         ret
  1490.  
  1491.  
  1492. endp
  1493.  
  1494.  
  1495.  
  1496. ;;;;;;;;;;;;;;;;;;;;;;;
  1497. ;;                   ;;
  1498. ;; Interrupt handler ;;
  1499. ;;                   ;;
  1500. ;;;;;;;;;;;;;;;;;;;;;;;
  1501. align 16
  1502. int_handler:
  1503.  
  1504.         push    ebx esi edi
  1505.  
  1506.         mov     ebx, [esp+4*4]
  1507.         DEBUGF  1,"INT for 0x%x\n", ebx
  1508.  
  1509.         set_io  [ebx + device.io_addr], 0
  1510.         set_io  [ebx + device.io_addr], IntrStatus
  1511.         in      ax, dx
  1512.         test    ax, ax
  1513.         jz      .nothing
  1514.  
  1515.         out     dx, ax          ; ACK interrupt
  1516.         DEBUGF  1, "Status=0x%x\n", ax
  1517.  
  1518.         push    ax
  1519.  
  1520.         test    ax, IntrRxDone
  1521.         jz      .not_RX
  1522.  
  1523.         push    ebx
  1524.   .more_RX:
  1525.         pop     ebx
  1526.  
  1527. ; Get the current descriptor pointer
  1528.         movzx   eax, [ebx + device.cur_rx]
  1529.         mov     ecx, sizeof.rx_head
  1530.         mul     ecx
  1531.         lea     edi, [ebx + device.rx_ring]
  1532.         add     edi, eax
  1533.  
  1534. ; Check it's status
  1535.         test    [edi + rx_head.status], RX_SBITS_OWN_BIT
  1536.         jnz     .not_RX
  1537.  
  1538.         DEBUGF  1, "Packet status = 0x%x\n", [edi + rx_head.status]
  1539.  
  1540. ; TODO: check error bits
  1541.  
  1542. ; get length
  1543.         mov     ecx, [edi + rx_head.status]
  1544.         and     ecx, RX_SBITS_FRAME_LENGTH
  1545.         shr     ecx, 16
  1546.         sub     ecx, 4                          ; We dont want CRC
  1547.  
  1548. ; Update stats
  1549.         add     dword [ebx + device.bytes_rx], ecx
  1550.         adc     dword [ebx + device.bytes_rx + 4], 0
  1551.         inc     [ebx + device.packets_rx]
  1552.  
  1553. ; Push packet pointer, kernel will need it..
  1554.         push    ebx
  1555.         push    .more_RX                        ; return ptr
  1556.         mov     eax, [edi + rx_head.buff_addr_virt]
  1557.         push    eax
  1558.         mov     [eax + NET_BUFF.length], ecx
  1559.         mov     [eax + NET_BUFF.device], ebx
  1560.         mov     [eax + NET_BUFF.offset], NET_BUFF.data
  1561.  
  1562. ; reset the RX descriptor
  1563.         push    edi
  1564.         invoke  NetAlloc, PKT_BUF_SZ+NET_BUFF.data
  1565.         pop     edi
  1566.         mov     [edi + rx_head.buff_addr_virt], eax
  1567.         invoke  GetPhysAddr
  1568.         add     eax, NET_BUFF.data
  1569.         mov     [edi + rx_head.buff_addr], eax
  1570.         mov     [edi + rx_head.status], RX_SBITS_OWN_BIT
  1571.  
  1572. ; Use next descriptor next time
  1573.         inc     [ebx + device.cur_rx]
  1574.         and     [ebx + device.cur_rx], RX_RING_SIZE - 1
  1575.  
  1576. ; At last, send packet to kernel
  1577.         jmp     [EthInput]
  1578.  
  1579.   .not_RX:
  1580.         pop     ax
  1581.  
  1582.         test    ax, IntrTxDone
  1583.         jz      .not_TX
  1584.  
  1585.       .loop_tx:
  1586.         movzx   eax, [ebx + device.last_tx]
  1587.         mov     ecx, sizeof.tx_head
  1588.         mul     ecx
  1589.         lea     edi, [ebx + device.tx_ring]
  1590.         add     edi, eax
  1591.  
  1592.         test    [edi + tx_head.status], TX_SBITS_OWN_BIT
  1593.         jnz     .not_TX
  1594.  
  1595.         cmp     [edi + tx_head.buff_addr_virt], 0
  1596.         je      .not_TX
  1597.  
  1598.         DEBUGF  1,"Freeing buffer 0x%x\n", [edi + tx_head.buff_addr_virt]
  1599.  
  1600.         push    [edi + tx_head.buff_addr_virt]
  1601.         mov     [edi + tx_head.buff_addr_virt], 0
  1602.         invoke  NetFree
  1603.  
  1604.         inc     [ebx + device.last_tx]
  1605.         and     [ebx + device.last_tx], TX_RING_SIZE - 1
  1606.  
  1607.         jmp     .loop_tx
  1608.  
  1609.   .not_TX:
  1610.  
  1611.         ; On Rhine-II, Bit 3 indicates Tx descriptor write-back race.
  1612. if 0
  1613.         cmp     [ebx + device.chip_id], 0x3065
  1614.         jne     @f
  1615.         push    ax
  1616.         xor     eax, eax
  1617.         set_io  [ebx + device.io_addr], IntrStatus2
  1618.         in      al, dx
  1619.         shl     eax, 16
  1620.         pop     ax
  1621.     @@:
  1622. end if
  1623.  
  1624. if 0
  1625.  
  1626.         ; Acknowledge all of the current interrupt sources ASAP.
  1627.         xor     ecx, ecx
  1628.         test    eax, IntrTxDescRace
  1629.         jz      @f
  1630.         set_io  [ebx + device.io_addr], 0
  1631.         set_io  [ebx + device.io_addr], IntrStatus2
  1632.         push    ax
  1633.         mov     al, 0x08
  1634.         out     dx, al
  1635.         pop     ax
  1636.     @@:
  1637.         set_io  [ebx + device.io_addr], 0
  1638.         set_io  [ebx + device.io_addr], IntrStatus
  1639.         out     dx, ax
  1640.         IOSYNC
  1641.  
  1642. end if
  1643.  
  1644.         pop     edi esi ebx
  1645.         xor     eax, eax
  1646.         inc     eax
  1647.  
  1648.         ret
  1649.  
  1650.   .nothing:
  1651.         pop     edi esi ebx
  1652.         xor     eax, eax
  1653.  
  1654.         ret
  1655.  
  1656.  
  1657.  
  1658.  
  1659. ; End of code
  1660.  
  1661. data fixups
  1662. end data
  1663.  
  1664. include '../peimport.inc'
  1665.  
  1666. my_service      db 'RHINE',0                    ; max 16 chars including zero
  1667.  
  1668. chiplist:
  1669.                 dd 0x30431106, rhine_3043;, RHINE_IOTYPE, RHINE_I_IOSIZE, CanHaveMII or ReqTxAlign or HasV1TxStat
  1670.                 dd 0x61001106, rhine_6100;, RHINE_IOTYPE, RHINE_I_IOSIZE, CanHaveMII or ReqTxAlign or HasV1TxStat
  1671.                 dd 0x30651106, rhine_6102;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL
  1672.                 dd 0x31061106, rhine_6105;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL
  1673. ; Duplicate entry, with 'M' features enabled.
  1674. ;                dd 0x31061106, rhine_6105;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL or HasIPChecksum or HasVLAN
  1675.                 dd 0x30531106, rhine_3053;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL
  1676.                 dd 0
  1677.  
  1678. rhine_3043      db "VIA VT3043 Rhine", 0
  1679. rhine_6100      db "VIA VT86C100A Rhine", 0
  1680. rhine_6102      db "VIA VT6102 Rhine-II", 0
  1681. rhine_6105      db "VIA VT6105LOM Rhine-III (3106)", 0
  1682. rhine_3053      db "VIA VT6105M Rhine-III (3053 prototype)", 0
  1683.  
  1684. include_debug_strings                           ; All data which FDO uses will be included here
  1685.  
  1686. align 4
  1687. devices         dd 0
  1688. device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
  1689.  
  1690.