Subversion Repositories Kolibri OS

Rev

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