Subversion Repositories Kolibri OS

Rev

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

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