Subversion Repositories Kolibri OS

Rev

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