Subversion Repositories Kolibri OS

Rev

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

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