Subversion Repositories Kolibri OS

Rev

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

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