Subversion Repositories Kolibri OS

Rev

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

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