Subversion Repositories Kolibri OS

Rev

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

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