Subversion Repositories Kolibri OS

Rev

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