Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2010-2014. 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_pe.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              = 1536    ; Size of each temporary Rx buffer.
  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.         jnz     @f
  933.         DEBUGF  2,"Could not attach int handler!\n"
  934.         or      eax, -1
  935.         ret
  936.        @@:
  937.  
  938. ; Soft reset the chip.
  939.         set_io  [ebx + device.io_addr], 0
  940.         set_io  [ebx + device.io_addr], byCR0
  941.         mov     ax, CR_SFRST
  942.         out     dx, ax
  943.  
  944.         call    MIIDelay
  945.  
  946. ; Initialize rings
  947.         call    init_ring
  948.  
  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.  
  972.         call    QueryAuto
  973.         test    eax, eax        ; full duplex?
  974.         jz      @f
  975.  
  976.         set_io  [ebx + device.io_addr], 0
  977.         set_io  [ebx + device.io_addr], byCFGD
  978.         mov     al, CFGD_CFDX
  979.         out     dx, al
  980.  
  981.         set_io  [ebx + device.io_addr], byCR0
  982.         mov     ax, CR_FDX
  983.         out     dx, ax
  984.     @@:
  985.  
  986. ; ENABLE interrupts
  987.         set_io  [ebx + device.io_addr], 0
  988.         set_io  [ebx + device.io_addr], byIMR0
  989.         mov     ax, DEFAULT_INTR
  990.         out     dx, ax
  991.  
  992. ; KICK NIC to WORK
  993.  
  994.         set_io  [ebx + device.io_addr], byCR0
  995.         in      ax, dx
  996.         and     ax, not CR_STOP
  997.         or      ax, CR_STRT or CR_TXON or CR_RXON or CR_DPOLL
  998.         out     dx, ax
  999.  
  1000. ; Set the mtu, kernel will be able to send now
  1001.         mov     [ebx + device.mtu], 1514
  1002.  
  1003. ; Set link state to unknown
  1004.         mov     [ebx + device.state], ETH_LINK_UNKNOWN
  1005.  
  1006. ; say reset was successful
  1007.         xor     eax, eax
  1008.         ret
  1009.  
  1010.  
  1011.  
  1012. align 4
  1013. unload:
  1014.  
  1015.         call    reset
  1016.         push    eax edx
  1017.         DEBUGF  1, "rhine disable\n"
  1018.  
  1019.         ; Switch to loopback mode to avoid hardware races.
  1020.         set_io  [ebx + device.io_addr], 0
  1021.         set_io  [ebx + device.io_addr], byTCR
  1022.         mov     al, 0x61
  1023.         out     dx, al
  1024.  
  1025.         ; Stop the chip's Tx and Rx processes.
  1026.         set_io  [ebx + device.io_addr], byCR0
  1027.         mov     ax, CR_STOP
  1028.         out     dx, ax
  1029.         pop     edx eax
  1030.  
  1031.         ret
  1032.  
  1033.  
  1034.  
  1035.  
  1036. align 4
  1037. reload_eeprom:
  1038.  
  1039.         DEBUGF  1, "Reload eeprom\n"
  1040.  
  1041.         set_io  [ebx + device.io_addr], 0
  1042.         set_io  [ebx + device.io_addr], byEECSR
  1043.         mov     al, 0x20
  1044.         out     dx, al
  1045.         ; Typically 2 cycles to reload.
  1046.         mov     ecx, 150
  1047.   .reload:
  1048.         in      al, dx
  1049.         test    al, 0x20
  1050.         jz      @f
  1051.         loop    .reload
  1052.         DEBUGF  2, "Reload eeprom: timeout!\n"
  1053.   @@:
  1054.  
  1055.         ret
  1056.  
  1057.  
  1058.  
  1059. ; Initialize the Rx and Tx rings, along with various 'dev' bits.
  1060. align 4
  1061. init_ring:
  1062.  
  1063.         DEBUGF  1, "Init ring\n"
  1064.  
  1065.         lea     edi, [ebx + device.rx_ring]
  1066.         mov     eax, edi
  1067.         invoke  GetPhysAddr
  1068.         mov     esi, eax
  1069.         push    esi
  1070.         mov     ecx, RX_RING_SIZE
  1071.    .rx_init:
  1072.         add     esi, sizeof.rx_head
  1073.         mov     [edi + rx_head.status], RX_SBITS_OWN_BIT
  1074.         mov     [edi + rx_head.control], PKT_BUF_SZ
  1075.         push    ecx
  1076.         invoke  KernelAlloc, PKT_BUF_SZ
  1077.         pop     ecx
  1078.         mov     [edi + rx_head.buff_addr_virt], eax
  1079.         invoke  GetPhysAddr
  1080.         mov     [edi + rx_head.buff_addr], eax                        ; buffer ptr
  1081.         mov     [edi + rx_head.next_desc], esi                        ; next head
  1082.         add     edi, sizeof.rx_head
  1083.         dec     ecx
  1084.         jnz     .rx_init
  1085.         pop     [edi - sizeof.rx_head + rx_head.next_desc]            ; Mark the last entry as wrapping the ring.
  1086.  
  1087.  
  1088.         lea     edi, [ebx + device.tx_ring]
  1089.         mov     eax, edi
  1090.         invoke  GetPhysAddr
  1091.         mov     esi, eax
  1092.         push    esi
  1093.         mov     ecx, TX_RING_SIZE
  1094.    .tx_init:
  1095.         add     esi, sizeof.tx_head
  1096.         mov     [edi + tx_head.status], 0
  1097.         mov     [edi + tx_head.control], 0x00E08000
  1098.         mov     [edi + tx_head.buff_addr], 0
  1099.         mov     [edi + tx_head.next_desc], esi
  1100.         mov     [edi + tx_head.buff_addr_virt], 0
  1101.         add     edi, sizeof.tx_head
  1102.         dec     ecx
  1103.         jnz     .tx_init
  1104.         pop     [edi - sizeof.tx_head + tx_head.next_desc]              ; Mark the last entry as wrapping the ring.
  1105.  
  1106. ; write Descriptors to MAC
  1107.         lea     eax, [ebx + device.rx_ring]
  1108.         invoke  GetPhysAddr
  1109.         set_io  [ebx + device.io_addr], 0
  1110.         set_io  [ebx + device.io_addr], dwCurrentRxDescAddr
  1111.         out     dx, eax
  1112.  
  1113.         lea     eax, [ebx + device.tx_ring]
  1114.         invoke  GetPhysAddr
  1115.         set_io  [ebx + device.io_addr], dwCurrentTxDescAddr
  1116.         out     dx, eax
  1117.  
  1118.         xor     eax, eax
  1119.         mov     [ebx + device.cur_rx], ax
  1120.         mov     [ebx + device.cur_tx], ax
  1121.         mov     [ebx + device.last_tx], ax
  1122.  
  1123.         ret
  1124.  
  1125.  
  1126. align 4
  1127. QueryAuto:
  1128.  
  1129.         DEBUGF  1, "Query Auto\n"
  1130.  
  1131.         push    ecx
  1132.         stdcall ReadMII, 0x04   ; advertised
  1133.         mov     ecx, eax
  1134.         stdcall ReadMII, 0x05
  1135.         and     ecx, eax
  1136.  
  1137.         xor     eax, eax
  1138.         test    ecx, 0x100
  1139.         jnz     .one
  1140.  
  1141.         and     ecx, 0x1C0
  1142.         cmp     ecx, 0x40
  1143.         jne     .zero
  1144.    .one:
  1145.         inc     eax
  1146.         DEBUGF  1, "AutoNego OK!\n"
  1147.    .zero:
  1148.         pop     ecx
  1149.  
  1150.         ret
  1151.  
  1152.  
  1153. proc    ReadMII stdcall, byMIIIndex:dword
  1154.  
  1155. ;        DEBUGF  1, "ReadMII Index=%x\n", [byMIIIndex]
  1156.  
  1157.         push    esi ebx ecx edx
  1158.  
  1159.         set_io  [ebx + device.io_addr], 0
  1160.         set_io  [ebx + device.io_addr], byMIIAD
  1161.         in      al, dx
  1162.         mov     bl, al
  1163.  
  1164.         set_io  [ebx + device.io_addr], byMIICR
  1165.         in      al, dx
  1166.         mov     bh, al
  1167.         and     al, 0x7F
  1168.         out     dx, al
  1169.  
  1170.         call    MIIDelay
  1171.  
  1172.         mov     al, byte [byMIIIndex]
  1173.         set_io  [ebx + device.io_addr], byMIIAD
  1174.         out     dx, al
  1175.  
  1176.         call    MIIDelay
  1177.  
  1178.         set_io  [ebx + device.io_addr], byMIICR
  1179.         in      al, dx
  1180.         or      al, 0x40
  1181.         out     dx, al
  1182.  
  1183.         mov     ecx, 200
  1184.   .read_again:
  1185.         in      al, dx
  1186.         test    al, 0x40
  1187.         jz      @f
  1188.  
  1189.         mov     esi, 10
  1190.         invoke  Sleep
  1191.         dec     ecx
  1192.         jnz     .read_again
  1193.         DEBUGF  2, "ReadMII: timeout!\n"
  1194.   @@:
  1195.  
  1196.         call    MIIDelay
  1197.  
  1198.         set_io  [ebx + device.io_addr], byMIIAD
  1199.         in      ax, dx
  1200.  
  1201.         push    eax
  1202.         mov     ax, bx
  1203.         set_io  [ebx + device.io_addr], byMIIAD
  1204.         out     dx, al
  1205.  
  1206.         shr     ax, 8
  1207.         set_io  [ebx + device.io_addr], byMIICR
  1208.         out     dx, al
  1209.  
  1210.         call    MIIDelay
  1211.  
  1212.         pop     eax
  1213.         and     eax, 0xFFFF
  1214.         rol     ax, 8
  1215.  
  1216.         pop     edx ecx ebx esi
  1217.         ret
  1218. endp
  1219.  
  1220.  
  1221.  
  1222. proc    WriteMII stdcall, byMIISetByte:dword, byMIISetBit:dword, byMIIOP:dword
  1223.  
  1224. ;        DEBUGF  1, "WriteMII SetByte=%x SetBit=%x OP=%x\n", [byMIISetByte], [byMIISetBit], [byMIIOP]
  1225.  
  1226.         push    ebx eax ecx edx
  1227.  
  1228.         set_io  [ebx + device.io_addr], 0
  1229.         set_io  [ebx + device.io_addr], byMIIAD
  1230.         in      al, dx
  1231.         mov     bl, al
  1232.  
  1233.         set_io  [ebx + device.io_addr], byMIICR
  1234.         in      al, dx
  1235.         mov     bh, al
  1236.         and     al, 0x7F
  1237.         out     dx, al
  1238.  
  1239.         call    MIIDelay
  1240.  
  1241.         mov     al, byte [byMIISetByte]
  1242.         set_io  [ebx + device.io_addr], byMIIAD
  1243.         out     dx, al
  1244.  
  1245.         call    MIIDelay
  1246.  
  1247.         set_io  [ebx + device.io_addr], byMIICR
  1248.         in      al, dx
  1249.         or      al, 0x40
  1250.         out     dx, al
  1251.  
  1252.         mov     ecx, 200
  1253.   .read_again0:
  1254.         in      al, dx
  1255.         test    al, 0x40
  1256.         jz      .done
  1257.  
  1258.         mov     esi, 10
  1259.         invoke  Sleep
  1260.         dec     ecx
  1261.         jnz     .read_again0
  1262.         DEBUGF  2, "WriteMII: timeout (1)\n"
  1263.   .done:
  1264.  
  1265.         call    MIIDelay
  1266.  
  1267.         set_io  [ebx + device.io_addr], wMIIDATA
  1268.         in      ax, dx
  1269.  
  1270.         mov     ecx, [byMIISetBit]
  1271.         rol     cx, 8
  1272.  
  1273.         cmp     byte [byMIIOP], 0
  1274.         jne     @f
  1275.         not     ecx
  1276.         and     ax, cx
  1277.         jmp     .end_mascarad
  1278.      @@:
  1279.         or      ax, cx
  1280.      .end_mascarad:
  1281.  
  1282.         set_io  [ebx + device.io_addr], wMIIDATA
  1283.         out     dx, ax
  1284.  
  1285.         call    MIIDelay
  1286.  
  1287.         set_io  [ebx + device.io_addr], byMIICR
  1288.         in      al, dx
  1289.         or      al, 0x20
  1290.         out     dx, al
  1291.  
  1292.         mov     ecx, 200
  1293.     .read_again1:
  1294.         in      al, dx
  1295.         test    al, 0x20
  1296.         jz      @f
  1297.  
  1298.         mov     esi, 10
  1299.         invoke  Sleep
  1300.         dec     ecx
  1301.         jnz     .read_again1
  1302.         DEBUGF  2, "WriteMII timeout (2)\n"
  1303.     @@:
  1304.  
  1305.         call    MIIDelay
  1306.  
  1307.         mov     ax, bx
  1308.         and     al, 0x7F
  1309.         set_io  [ebx + device.io_addr], byMIIAD
  1310.         out     dx, al
  1311.  
  1312.         shr     ax, 8
  1313.         set_io  [ebx + device.io_addr], byMIICR
  1314.         out     dx, al
  1315.  
  1316.         call    MIIDelay
  1317.  
  1318.         pop     edx ecx eax ebx
  1319.         ret
  1320. endp
  1321.  
  1322.  
  1323. align 4
  1324. MIIDelay:
  1325.  
  1326.         mov     ecx, 0x7FFF
  1327.     @@:
  1328.         in      al, 0x61
  1329.         in      al, 0x61
  1330.         in      al, 0x61
  1331.         in      al, 0x61
  1332.         loop    @b
  1333.  
  1334.         ret
  1335.  
  1336.  
  1337. align 4
  1338. set_rx_mode:
  1339.  
  1340.         DEBUGF  1, "Set RX mode\n"
  1341.  
  1342.         ; ! IFF_PROMISC
  1343.         mov     eax, 0xffffffff
  1344.         set_io  [ebx + device.io_addr], 0
  1345.         set_io  [ebx + device.io_addr], byMAR0
  1346.         out     dx, eax
  1347.  
  1348.         set_io  [ebx + device.io_addr], byMAR4
  1349.         out     dx, eax
  1350.  
  1351.         set_io  [ebx + device.io_addr], byRCR
  1352.         mov     al, 0x6C                ;rx_mode = 0x0C;
  1353.         out     dx, al          ;outb(0x60 /* thresh */ | rx_mode, byRCR );
  1354.  
  1355.         ret
  1356.  
  1357.  
  1358.  
  1359.  
  1360.  
  1361. ; Beware of PCI posted writes
  1362. macro IOSYNC
  1363. {
  1364.         set_io  [ebx + device.io_addr], StationAddr
  1365.         in      al, dx
  1366. }
  1367.  
  1368.  
  1369.  
  1370. align 4
  1371. read_mac:
  1372.  
  1373.         lea     edi, [ebx + device.mac]
  1374.         set_io  [ebx + device.io_addr], 0
  1375.         set_io  [ebx + device.io_addr], byPAR0
  1376.         mov     ecx, 6
  1377.   .next:
  1378.         in      al, dx
  1379.         stosb
  1380.         inc     edx
  1381.         dec     ecx
  1382.         jnz     .next
  1383.  
  1384.         DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n", \
  1385.         [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
  1386.  
  1387.  
  1388.         ret
  1389.  
  1390.  
  1391. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1392. ;;                                         ;;
  1393. ;; Transmit                                ;;
  1394. ;;                                         ;;
  1395. ;; In: buffer pointer in [esp+4]           ;;
  1396. ;;     size of buffer in [esp+8]           ;;
  1397. ;;     pointer to device structure in ebx  ;;
  1398. ;;                                         ;;
  1399. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1400. align 4
  1401. proc transmit stdcall bufferptr, buffersize
  1402.  
  1403.         pushf
  1404.         cli
  1405.  
  1406.         DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [buffersize]
  1407.         mov     eax, [bufferptr]
  1408.         DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
  1409.         [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
  1410.         [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
  1411.         [eax+13]:2,[eax+12]:2
  1412.  
  1413.         cmp     [buffersize], 1514
  1414.         ja      .fail
  1415.         cmp     [buffersize], 60
  1416.         jb      .fail
  1417.  
  1418.         movzx   eax, [ebx + device.cur_tx]
  1419.         mov     ecx, sizeof.tx_head
  1420.         mul     ecx
  1421.         lea     edi, [ebx + device.tx_ring]
  1422.         add     edi, eax
  1423.  
  1424.         cmp     [edi + tx_head.buff_addr_virt], 0
  1425.         jne     .fail
  1426.  
  1427.         mov     eax, [bufferptr]
  1428.         mov     [edi + tx_head.buff_addr_virt], eax
  1429.         invoke  GetPhysAddr
  1430.         mov     [edi + tx_head.buff_addr], eax
  1431.         mov     ecx, [buffersize]
  1432.         and     ecx, TX_CBITS_TX_BUF_SIZE
  1433.         or      ecx,  0x00E08000
  1434.         mov     [edi + tx_head.control], ecx
  1435.         or      [edi + tx_head.status], TX_SBITS_OWN_BIT
  1436.  
  1437.         set_io  [ebx + device.io_addr], 0
  1438.         set_io  [ebx + device.io_addr], byCR1
  1439.         in      al, dx
  1440.         or      al, CR1_TDMD1
  1441.         out     dx, al
  1442.  
  1443.         inc     [ebx + device.cur_tx]
  1444.         and     [ebx + device.cur_tx], TX_RING_SIZE-1
  1445.  
  1446.         ;outw(IMRShadow,byIMR0); ;
  1447.  
  1448. ; Update stats
  1449.         inc     [ebx + device.packets_tx]
  1450.         mov     ecx, [buffersize]
  1451.         add     dword [ebx + device.bytes_tx], ecx
  1452.         adc     dword [ebx + device.bytes_tx + 4], 0
  1453.  
  1454.         DEBUGF  1,"Transmit OK\n"
  1455.         popf
  1456.         xor     eax, eax
  1457.         ret
  1458.  
  1459.   .fail:
  1460.         DEBUGF  2,"Transmit failed\n"
  1461.         invoke  KernelFree, [bufferptr]
  1462.         popf
  1463.         or      eax, -1
  1464.         ret
  1465.  
  1466. endp
  1467.  
  1468.  
  1469.  
  1470. ;;;;;;;;;;;;;;;;;;;;;;;
  1471. ;;                   ;;
  1472. ;; Interrupt handler ;;
  1473. ;;                   ;;
  1474. ;;;;;;;;;;;;;;;;;;;;;;;
  1475.  
  1476. align 4
  1477. int_handler:
  1478.  
  1479.         push    ebx esi edi
  1480.  
  1481.         DEBUGF  1,"INT\n"
  1482.  
  1483. ; Find pointer of device which made IRQ occur
  1484.  
  1485.         mov     ecx, [devices]
  1486.         test    ecx, ecx
  1487.         jz      .nothing
  1488.         mov     esi, device_list
  1489.   .nextdevice:
  1490.         mov     ebx, [esi]
  1491.  
  1492.         set_io  [ebx + device.io_addr], 0
  1493.         set_io  [ebx + device.io_addr], IntrStatus
  1494.         in      ax, dx
  1495.         out     dx, ax                  ; send it back to ACK
  1496.         test    ax, ax
  1497.         jnz     .got_it
  1498.   .continue:
  1499.         add     esi, 4
  1500.         dec     ecx
  1501.         jnz     .nextdevice
  1502.   .nothing:
  1503.         pop     edi esi ebx
  1504.         xor     eax, eax
  1505.  
  1506.         ret                             ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
  1507.  
  1508.  
  1509.  
  1510.   .got_it:
  1511.  
  1512.         DEBUGF  1, "status=0x%x\n", ax
  1513.  
  1514.         push    ax
  1515.  
  1516.         test    ax, IntrRxDone
  1517.         jz      .not_RX
  1518.  
  1519.         push    ebx
  1520.   .more_RX:
  1521.         pop     ebx
  1522.  
  1523. ; Get the current descriptor pointer
  1524.  
  1525.         movzx   eax, [ebx + device.cur_rx]
  1526.         mov     ecx, sizeof.rx_head
  1527.         mul     ecx
  1528.         lea     edi, [ebx + device.rx_ring]
  1529.         add     edi, eax
  1530.  
  1531. ; Check it's status
  1532.  
  1533.         test    [edi + rx_head.status], RX_SBITS_OWN_BIT
  1534.         jnz     .not_bit_own
  1535.  
  1536.         DEBUGF  1, "Packet status = 0x%x\n", [edi + rx_head.status]
  1537.  
  1538. ; TODO: check error bits
  1539.  
  1540. ; get length
  1541.  
  1542.         mov     ecx, [edi + rx_head.status]
  1543.         and     ecx, RX_SBITS_FRAME_LENGTH
  1544.         shr     ecx, 16
  1545.         sub     ecx, 4  ; We dont want CRC
  1546.  
  1547. ; Update stats
  1548.  
  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 size and pointer, kernel will need it..
  1554.  
  1555.         push    ebx
  1556.         push    .more_RX        ; return ptr
  1557.  
  1558.         push    ecx             ; full packet size
  1559.         push    [edi + rx_head.buff_addr_virt]
  1560.  
  1561. ; reset the RX descriptor
  1562.  
  1563.         push    edi
  1564.         invoke  KernelAlloc, PKT_BUF_SZ
  1565.         pop     edi
  1566.         mov     [edi + rx_head.buff_addr_virt], eax
  1567.         invoke  GetPhysAddr
  1568.         mov     [edi + rx_head.buff_addr], eax
  1569.         mov     [edi + rx_head.status], RX_SBITS_OWN_BIT
  1570.  
  1571. ; Use next descriptor next time
  1572.  
  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.  
  1578.         jmp     [Eth_input]
  1579.  
  1580.   .not_bit_own:
  1581.   .not_RX:
  1582.  
  1583.         pop     ax
  1584.  
  1585.         test    ax, IntrTxDone
  1586.         jz      .not_TX
  1587.  
  1588.       .loop_tx:
  1589.         movzx   eax, [ebx + device.last_tx]
  1590.         mov     ecx, sizeof.tx_head
  1591.         mul     ecx
  1592.         lea     edi, [ebx + device.tx_ring]
  1593.         add     edi, eax
  1594.  
  1595.         test    [edi + tx_head.status], TX_SBITS_OWN_BIT
  1596.         jnz     .not_TX
  1597.  
  1598.         cmp     [edi + tx_head.buff_addr_virt], 0
  1599.         je      .not_TX
  1600.  
  1601.         DEBUGF  1,"Freeing buffer 0x%x\n", [edi + tx_head.buff_addr_virt]
  1602.  
  1603.         push    [edi + tx_head.buff_addr_virt]
  1604.         mov     [edi + tx_head.buff_addr_virt], 0
  1605.         invoke  KernelFree
  1606.  
  1607.         inc     [ebx + device.last_tx]
  1608.         and     [ebx + device.last_tx], TX_RING_SIZE - 1
  1609.  
  1610.         jmp     .loop_tx
  1611.  
  1612.   .not_TX:
  1613.  
  1614.         ; On Rhine-II, Bit 3 indicates Tx descriptor write-back race.
  1615. if 0
  1616.         cmp     [ebx + device.chip_id], 0x3065 ;if (tp->chip_id == 0x3065)
  1617.         jne     @f
  1618.         push    ax
  1619.         xor     eax, eax
  1620.         set_io  [ebx + device.io_addr], IntrStatus2
  1621.         in      al, dx ;  intr_status |= inb(nic->ioaddr + IntrStatus2) << 16;
  1622.         shl     eax, 16
  1623.         pop     ax
  1624.     @@:
  1625. end if
  1626.  
  1627. if 0
  1628.  
  1629.         ; Acknowledge all of the current interrupt sources ASAP.
  1630.         xor     ecx, ecx
  1631.         test    eax, IntrTxDescRace
  1632.         jz      @f
  1633.         set_io  [ebx + device.io_addr], 0
  1634.         set_io  [ebx + device.io_addr], IntrStatus2
  1635.         push    ax
  1636.         mov     al, 0x08
  1637.         out     dx, al
  1638.         pop     ax
  1639.     @@:
  1640.         set_io  [ebx + device.io_addr], 0
  1641.         set_io  [ebx + device.io_addr], IntrStatus
  1642.         out     dx, ax
  1643.         IOSYNC
  1644.  
  1645. end if
  1646.  
  1647.         pop     edi esi ebx
  1648.         xor     eax, eax
  1649.         inc     eax
  1650.  
  1651.         ret
  1652.  
  1653.  
  1654.  
  1655.  
  1656.  
  1657. ; End of code
  1658.  
  1659. data fixups
  1660. end data
  1661.  
  1662. include '../peimport.inc'
  1663.  
  1664. my_service      db 'RHINE',0                    ; max 16 chars including zero
  1665.  
  1666. chiplist:
  1667.                 dd 0x30431106, rhine_3043;, RHINE_IOTYPE, RHINE_I_IOSIZE, CanHaveMII or ReqTxAlign or HasV1TxStat
  1668.                 dd 0x61001106, rhine_6100;, RHINE_IOTYPE, RHINE_I_IOSIZE, CanHaveMII or ReqTxAlign or HasV1TxStat
  1669.                 dd 0x30651106, rhine_6102;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL
  1670.                 dd 0x31061106, rhine_6105;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL
  1671. ; Duplicate entry, with 'M' features enabled.
  1672. ;                dd 0x31061106, rhine_6105;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL or HasIPChecksum or HasVLAN
  1673.                 dd 0x30531106, rhine_3053;, RHINE_IOTYPE, RHINEII_IOSIZE, CanHaveMII or HasWOL
  1674.                 dd 0
  1675.  
  1676. rhine_3043      db "VIA VT3043 Rhine", 0
  1677. rhine_6100      db "VIA VT86C100A Rhine", 0
  1678. rhine_6102      db "VIA VT6102 Rhine-II", 0
  1679. rhine_6105      db "VIA VT6105LOM Rhine-III (3106)", 0
  1680. rhine_3053      db "VIA VT6105M Rhine-III (3053 prototype)", 0
  1681.  
  1682. include_debug_strings                           ; All data which FDO uses will be included here
  1683.  
  1684. align 4
  1685. devices         dd 0
  1686. device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
  1687.  
  1688.