Subversion Repositories Kolibri OS

Rev

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

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