Subversion Repositories Kolibri OS

Rev

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

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