Subversion Repositories Kolibri OS

Rev

Rev 3758 | Go to most recent revision | Details | Last modification | View Log | RSS feed

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