Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
4467 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved.    ;;
3545 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  MTD80x driver for KolibriOS                                    ;;
7
;;                                                                 ;;
8
;;  Based on mtd80x.c from the etherboot project                   ;;
9
;;                                                                 ;;
10
;;  Written by hidnplayr@kolibrios.org                             ;;
11
;;                                                                 ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
13
;;             Version 2, June 1991                                ;;
14
;;                                                                 ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
17
format MS COFF
18
 
19
        API_VERSION             = 0x01000100
20
        DRIVER_VERSION          = 5
21
 
22
        MAX_DEVICES             = 16
23
 
24
        DEBUG                   = 1
25
        __DEBUG__               = 1
26
        __DEBUG_LEVEL__         = 2
27
 
28
        NUM_TX_DESC             = 4
29
        NUM_RX_DESC             = 4
30
 
4467 hidnplayr 31
include '../struct.inc'
32
include '../macros.inc'
3545 hidnplayr 33
include '../proc32.inc'
34
include '../imports.inc'
35
include '../fdo.inc'
36
include '../netdrv.inc'
37
 
38
public START
39
public service_proc
40
public version
41
 
42
 
43
; for different PHY
44
 
45
    MysonPHY            = 1
46
    AhdocPHY            = 2
47
    SeeqPHY             = 3
48
    MarvellPHY          = 4
49
    Myson981            = 5
50
    LevelOnePHY         = 6
51
    OtherPHY            = 10
52
 
53
; Offsets to the Command and Status Registers.
54
 
55
    PAR0                = 0x0           ; physical address 0-3
56
    PAR1                = 0x04          ; physical address 4-5
57
    MAR0                = 0x08          ; multicast address 0-3
58
    MAR1                = 0x0C          ; multicast address 4-7
59
    FAR0                = 0x10          ; flow-control address 0-3
60
    FAR1                = 0x14          ; flow-control address 4-5
61
    TCRRCR              = 0x18          ; receive & transmit configuration
62
    BCR                 = 0x1C          ; bus command
63
    TXPDR               = 0x20          ; transmit polling demand
64
    RXPDR               = 0x24          ; receive polling demand
65
    RXCWP               = 0x28          ; receive current word pointer
66
    TXLBA               = 0x2C          ; transmit list base address
67
    RXLBA               = 0x30          ; receive list base address
68
    ISR                 = 0x34          ; interrupt status
69
    IMR                 = 0x38          ; interrupt mask
70
    FTH                 = 0x3C          ; flow control high/low threshold
71
    MANAGEMENT          = 0x40          ; bootrom/eeprom and mii management
72
    TALLY               = 0x44          ; tally counters for crc and mpa
73
    TSR                 = 0x48          ; tally counter for transmit status
74
    BMCRSR              = 0x4c          ; basic mode control and status
75
    PHYIDENTIFIER       = 0x50          ; phy identifier
76
    ANARANLPAR          = 0x54          ; auto-negotiation advertisement and link partner ability
77
    ANEROCR             = 0x58          ; auto-negotiation expansion and pci conf.
78
    BPREMRPSR           = 0x5c          ; bypass & receive error mask and phy status
79
 
80
; Bits in the interrupt status/enable registers.
81
 
82
    RFCON               = 0x00020000    ; receive flow control xon packet
83
    RFCOFF              = 0x00010000    ; receive flow control xoff packet
84
    LSCStatus           = 0x00008000    ; link status change
85
    ANCStatus           = 0x00004000    ; autonegotiation completed
86
    FBE                 = 0x00002000    ; fatal bus error
87
    FBEMask             = 0x00001800    ; mask bit12-11
88
    ParityErr           = 0x00000000    ; parity error
89
    TargetErr           = 0x00001000    ; target abort
90
    MasterErr           = 0x00000800    ; master error
91
    TUNF                = 0x00000400    ; transmit underflow
92
    ROVF                = 0x00000200    ; receive overflow
93
    ETI                 = 0x00000100    ; transmit early int
94
    ERI                 = 0x00000080    ; receive early int
95
    CNTOVF              = 0x00000040    ; counter overflow
96
    RBU                 = 0x00000020    ; receive buffer unavailable
97
    TBU                 = 0x00000010    ; transmit buffer unavilable
98
    TI                  = 0x00000008    ; transmit interrupt
99
    RI                  = 0x00000004    ; receive interrupt
100
    RxErr               = 0x00000002    ; receive error
101
 
102
; Bits in the NetworkConfig register.
103
 
104
    RxModeMask          = 0xe0
105
    AcceptAllPhys       = 0x80          ; promiscuous mode
106
    AcceptBroadcast     = 0x40          ; accept broadcast
107
    AcceptMulticast     = 0x20          ; accept mutlicast
108
    AcceptRunt          = 0x08          ; receive runt pkt
109
    ALP                 = 0x04          ; receive long pkt
110
    AcceptErr           = 0x02          ; receive error pkt
111
 
112
    AcceptMyPhys        = 0x00000000
113
    RxEnable            = 0x00000001
114
    RxFlowCtrl          = 0x00002000
115
    TxEnable            = 0x00040000
116
    TxModeFDX           = 0x00100000
117
    TxThreshold         = 0x00e00000
118
 
119
    PS1000              = 0x00010000
120
    PS10                = 0x00080000
121
    FD                  = 0x00100000
122
 
123
 
124
; Bits in network_desc.status
125
 
126
    RXOWN               = 0x80000000    ; own bit
127
    FLNGMASK            = 0x0fff0000    ; frame length
128
    FLNGShift           = 16
129
    MARSTATUS           = 0x00004000    ; multicast address received
130
    BARSTATUS           = 0x00002000    ; broadcast address received
131
    PHYSTATUS           = 0x00001000    ; physical address received
132
    RXFSD               = 0x00000800    ; first descriptor
133
    RXLSD               = 0x00000400    ; last descriptor
134
    ErrorSummary        = 0x80          ; error summary
135
    RUNT                = 0x40          ; runt packet received
136
    LONG                = 0x20          ; long packet received
137
    FAE                 = 0x10          ; frame align error
138
    CRC                 = 0x08          ; crc error
139
    RXER                = 0x04          ; receive error
140
 
141
; rx_desc_control_bits
142
 
143
    RXIC                = 0x00800000    ; interrupt control
144
    RBSShift            = 0
145
 
146
; tx_desc_status_bits
147
 
148
    TXOWN               = 0x80000000    ; own bit
149
    JABTO               = 0x00004000    ; jabber timeout
150
    CSL                 = 0x00002000    ; carrier sense lost
151
    LC                  = 0x00001000    ; late collision
152
    EC                  = 0x00000800    ; excessive collision
153
    UDF                 = 0x00000400    ; fifo underflow
154
    DFR                 = 0x00000200    ; deferred
155
    HF                  = 0x00000100    ; heartbeat fail
156
    NCRMask             = 0x000000ff    ; collision retry count
157
    NCRShift            = 0
158
 
159
; tx_desc_control_bits
160
 
161
    TXIC                = 0x80000000    ; interrupt control
162
    ETIControl          = 0x40000000    ; early transmit interrupt
163
    TXLD                = 0x20000000    ; last descriptor
164
    TXFD                = 0x10000000    ; first descriptor
165
    CRCEnable           = 0x08000000    ; crc control
166
    PADEnable           = 0x04000000    ; padding control
167
    RetryTxLC           = 0x02000000    ; retry late collision
168
    PKTSMask            = 0x3ff800      ; packet size bit21-11
169
    PKTSShift           = 11
170
    TBSMask             = 0x000007ff    ; transmit buffer bit 10-0
171
    TBSShift            = 0
172
 
173
; BootROM/EEPROM/MII Management Register
174
 
175
    MASK_MIIR_MII_READ  = 0x00000000
176
    MASK_MIIR_MII_WRITE = 0x00000008
177
    MASK_MIIR_MII_MDO   = 0x00000004
178
    MASK_MIIR_MII_MDI   = 0x00000002
179
    MASK_MIIR_MII_MDC   = 0x00000001
180
 
181
; ST+OP+PHYAD+REGAD+TA
182
 
183
    OP_READ             = 0x6000        ; ST:01+OP:10+PHYAD+REGAD+TA:Z0
184
    OP_WRITE            = 0x5002        ; ST:01+OP:01+PHYAD+REGAD+TA:10
185
 
186
; -------------------------------------------------------------------------
187
;      Constants for Myson PHY
188
; -------------------------------------------------------------------------
189
 
190
    MysonPHYID          = 0xd0000302
191
    MysonPHYID0         = 0x0302
192
    StatusRegister      = 18
193
    SPEED100            = 0x0400        ; bit10
194
    FULLMODE            = 0x0800        ; bit11
195
 
196
; -------------------------------------------------------------------------
197
;      Constants for Seeq 80225 PHY
198
; -------------------------------------------------------------------------
199
 
200
    SeeqPHYID0          = 0x0016
201
    MIIRegister18       = 18
202
    SPD_DET_100         = 0x80
203
    DPLX_DET_FULL       = 0x40
204
 
205
; -------------------------------------------------------------------------
206
;      Constants for Ahdoc 101 PHY
207
; -------------------------------------------------------------------------
208
 
209
    AhdocPHYID0         = 0x0022
210
    DiagnosticReg       = 18
211
    DPLX_FULL           = 0x0800
212
    Speed_100           = 0x0400
213
 
214
; --------------------------------------------------------------------------
215
;      Constants
216
; --------------------------------------------------------------------------
217
 
218
    MarvellPHYID0               = 0x0141
219
    LevelOnePHYID0              = 0x0013
220
 
221
    MII1000BaseTControlReg      = 9
222
    MII1000BaseTStatusReg       = 10
223
    SpecificReg                 = 17
224
 
225
; for 1000BaseT Control Register
226
 
227
    PHYAbletoPerform1000FullDuplex = 0x0200
228
    PHYAbletoPerform1000HalfDuplex = 0x0100
229
    PHY1000AbilityMask             = 0x300
230
 
231
; for phy specific status register, marvell phy.
232
 
233
    SpeedMask      = 0x0c000
234
    Speed_1000M    = 0x08000
235
    Speed_100M     = 0x4000
236
    Speed_10M      = 0
237
    Full_Duplex    = 0x2000
238
 
239
; for phy specific status register, levelone phy
240
 
241
    LXT1000_100M   = 0x08000
242
    LXT1000_1000M  = 0x0c000
243
    LXT1000_Full   = 0x200
244
 
245
; for PHY
246
 
247
    LinkIsUp       = 0x0004
248
    LinkIsUp2      = 0x00040000
249
 
250
 
251
 
252
virtual at 0
253
 
254
        mtd_desc:
255
        .status                 dd ?
256
        .control                dd ?
257
        .buffer                 dd ?
258
        .next_desc              dd ?
259
 
260
        .next_desc_logical      dd ?
261
        .skbuff                 dd ?
262
 
263
        .reserved1              dd ?
264
        .reserved2              dd ?
265
 
266
        .size = $
267
 
268
end virtual
269
 
270
 
271
virtual at ebx
272
 
273
        device:
274
 
275
        ETH_DEVICE
276
 
277
        .tx_desc        rb NUM_TX_DESC*mtd_desc.size
278
        .rx_desc        rb NUM_RX_DESC*mtd_desc.size
279
 
280
        .io_addr        dd ?
281
        .pci_bus        dd ?
282
        .pci_dev        dd ?
283
        .irq_line       db ?
284
        .dev_id         dw ?
285
 
286
        .flags          dd ?
287
 
288
        .crvalue        dd ?
289
        .bcrvalue       dd ?
290
 
291
        .cur_rx         dd ?
292
        .cur_tx         dd ?
293
 
294
; These values are keep track of the transceiver/media in use.
295
 
296
        .linkok         dd ?
297
        .line_speed     dd ?
298
        .duplexmode     dd ?
299
        .default_port   dd ?
300
        .PHYType        dd ?
301
 
302
; MII transceiver section.
303
 
304
        .mii_cnt        dd ?    ; MII device addresses.
305
        .phys           db ?    ; MII device addresses.
306
 
307
        device_size = $ - device
308
 
309
end virtual
310
 
311
 
312
 
313
section '.flat' code readable align 16
314
 
315
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
316
;;                        ;;
317
;; proc START             ;;
318
;;                        ;;
319
;; (standard driver proc) ;;
320
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
321
 
322
align 4
323
proc START stdcall, state:dword
324
 
325
        cmp [state], 1
326
        jne .exit
327
 
328
  .entry:
329
 
4470 hidnplayr 330
        DEBUGF  2,"Loading driver\n"
3545 hidnplayr 331
        stdcall RegService, my_service, service_proc
332
        ret
333
 
334
  .fail:
335
  .exit:
336
        xor eax, eax
337
        ret
338
 
339
endp
340
 
341
 
342
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
343
;;                        ;;
344
;; proc SERVICE_PROC      ;;
345
;;                        ;;
346
;; (standard driver proc) ;;
347
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
348
 
349
align 4
350
proc service_proc stdcall, ioctl:dword
351
 
352
        mov     edx, [ioctl]
4470 hidnplayr 353
        mov     eax, [edx + IOCTL.io_code]
3545 hidnplayr 354
 
355
;------------------------------------------------------
356
 
357
        cmp     eax, 0 ;SRV_GETVERSION
358
        jne     @F
359
 
4470 hidnplayr 360
        cmp     [edx + IOCTL.out_size], 4
3545 hidnplayr 361
        jb      .fail
4470 hidnplayr 362
        mov     eax, [edx + IOCTL.output]
3545 hidnplayr 363
        mov     [eax], dword API_VERSION
364
 
365
        xor     eax, eax
366
        ret
367
 
368
;------------------------------------------------------
369
  @@:
370
        cmp     eax, 1 ;SRV_HOOK
371
        jne     .fail
372
 
4470 hidnplayr 373
        cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
3545 hidnplayr 374
        jb      .fail
375
 
4470 hidnplayr 376
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 377
        cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
378
        jne     .fail                                   ; other types arent supported for this card yet
379
 
380
; check if the device is already listed
381
 
382
        mov     esi, device_list
383
        mov     ecx, [devices]
384
        test    ecx, ecx
385
        jz      .firstdevice
386
 
4470 hidnplayr 387
;        mov     eax, [edx + IOCTL.input]                ; get the pci bus and device numbers
388
        mov     ax, [eax+1]                             ;
3545 hidnplayr 389
  .nextdevice:
390
        mov     ebx, [esi]
391
        cmp     al, byte[device.pci_bus]
392
        jne     @f
393
        cmp     ah, byte[device.pci_dev]
394
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
395
       @@:
396
        add     esi, 4
397
        loop    .nextdevice
398
 
399
 
400
; This device doesnt have its own eth_device structure yet, lets create one
401
  .firstdevice:
402
        cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
403
        jae     .fail
404
 
405
        allocate_and_clear ebx, device_size, .fail
406
 
407
; Fill in the direct call addresses into the struct
408
 
409
        mov     [device.reset], reset
410
        mov     [device.transmit], transmit
411
        mov     [device.unload], unload
412
        mov     [device.name], my_service
413
 
414
; save the pci bus and device numbers
415
 
4470 hidnplayr 416
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 417
        movzx   ecx, byte[eax+1]
418
        mov     [device.pci_bus], ecx
419
        movzx   ecx, byte[eax+2]
420
        mov     [device.pci_dev], ecx
421
 
422
; Now, it's time to find the base io addres of the PCI device
423
 
424
        PCI_find_io
425
 
426
; We've found the io address, find IRQ now
427
 
428
        PCI_find_irq
429
 
430
        DEBUGF  2,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
431
        [device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:8
432
 
433
; Ok, the eth_device structure is ready, let's probe the device
434
; Because initialization fires IRQ, IRQ handler must be aware of this device
435
        mov     eax, [devices]                                          ; Add the device structure to our device list
436
        mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
437
        inc     [devices]                                               ;
438
 
439
        call    probe                                                   ; this function will output in eax
440
        test    eax, eax
441
        jnz     .err2                                                   ; If an error occured, exit
442
 
443
        mov     [device.type], NET_TYPE_ETH
444
        call    NetRegDev
445
 
446
        cmp     eax, -1
447
        je      .destroy
448
 
449
        ret
450
 
451
; If the device was already loaded, find the device number and return it in eax
452
 
453
  .find_devicenum:
454
        DEBUGF  2,"Trying to find device number of already registered device\n"
455
        call    NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
456
                                                                        ; into a device number in edi
457
        mov     eax, edi                                                ; Application wants it in eax instead
458
        DEBUGF  2,"Kernel says: %u\n", eax
459
        ret
460
 
461
; If an error occured, remove all allocated data and exit (returning -1 in eax)
462
 
463
  .destroy:
464
        ; todo: reset device into virgin state
465
 
466
  .err2:
467
        dec     [devices]
468
  .err:
469
        DEBUGF  2,"removing device structure\n"
470
        stdcall KernelFree, ebx
471
  .fail:
472
        or      eax, -1
473
        ret
474
 
475
;------------------------------------------------------
476
endp
477
 
478
 
479
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
480
;;                                                                        ;;
481
;;        Actual Hardware dependent code starts here                      ;;
482
;;                                                                        ;;
483
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
484
 
485
 
486
 
487
align 4
488
unload:
489
        ; TODO: (in this particular order)
490
        ;
491
        ; - Stop the device
492
 
493
;    /* Disable Tx Rx*/
494
;    outl( mtdx.crvalue & (~TxEnable) & (~RxEnable), mtdx.ioaddr + TCRRCR );
495
;
496
;    /* Reset the chip to erase previous misconfiguration. */
497
;    mtd_reset(nic);
498
 
499
        ; - Detach int handler
500
        ; - Remove device from local list (device_list)
501
        ; - call unregister function in kernel
502
        ; - Remove all allocated structures and buffers the card used
503
 
504
        or      eax,-1
505
 
506
ret
507
 
508
 
509
;-------
510
;
511
; PROBE
512
;
513
;-------
514
align 4
515
probe:
516
 
4470 hidnplayr 517
        DEBUGF  2,"Probing device\n"
3545 hidnplayr 518
 
519
        PCI_make_bus_master
520
 
521
        stdcall PciRead32, [device.pci_bus], [device.pci_dev], 0
522
 
523
        cmp     ax, 0x1516
524
        jne     .notfound
525
        shr     eax, 16
526
        mov     [device.dev_id], ax
527
 
528
        cmp     ax, 0x0800
529
        je      .has_mii_xcvr
530
 
531
        cmp     ax, 0x0803
532
        je      .has_chip_xcvr
533
 
534
        cmp     ax, 0x0891
535
        je      .has_mii_xcvr
536
 
537
  .notfound:
538
        DEBUGF  1,"Device not supported!\n"
539
        xor     eax, eax
540
        dec     eax
541
        ret
542
 
543
  .has_chip_xcvr:
544
        DEBUGF  1,"Device has chip xcvr\n"
545
 
546
        jmp     .xcvr_set
547
 
548
  .has_mii_xcvr:
549
        DEBUGF  1,"Device has mii xcvr\n"
550
 
551
  .xcvr_set:
552
 
553
        call    read_mac
554
 
555
; Reset the chip to erase previous misconfiguration.
556
 
557
        set_io  0
558
        set_io  BCR
559
        xor     eax, eax
560
        inc     eax
561
        out     dx, eax
562
 
563
; find the connected MII xcvrs
564
 
565
        cmp     [device.dev_id], 0x0803
566
        je      .is_803
567
 
568
;        int     phy, phy_idx =   0;
569
;
570
;        for (phy =   1; phy < 32 && phy_idx < 1; phy++) {
571
;            int mii_status =   mdio_read(nic, phy, 1);
572
;
573
;            if (mii_status !=   0xffff && mii_status !=   0x0000) {
574
;                mtdx.phys[phy_idx] =   phy;
575
;
576
;                DBG ( "%s: MII PHY found at address %d, status "
577
;                      "0x%4.4x.\n", mtdx.nic_name, phy, mii_status );
578
;                /* get phy type */
579
;                {
580
;                    unsigned int data;
581
;
582
;                    data =   mdio_read(nic, mtdx.phys[phy_idx], 2);
583
;                    if (data equ=   SeeqPHYID0)
584
;                        mtdx.PHYType =   SeeqPHY;
585
;                    else if (data equ=   AhdocPHYID0)
586
;                        mtdx.PHYType =   AhdocPHY;
587
;                    else if (data equ=   MarvellPHYID0)
588
;                        mtdx.PHYType =   MarvellPHY;
589
;                    else if (data equ=   MysonPHYID0)
590
;                        mtdx.PHYType =   Myson981;
591
;                    else if (data equ=   LevelOnePHYID0)
592
;                        mtdx.PHYType =   LevelOnePHY;
593
;                    else
594
;                        mtdx.PHYType =   OtherPHY;
595
;                }
596
;                phy_idx++;
597
;            }
598
;        }
599
;
600
;        mtdx.mii_cnt =   phy_idx;
601
;        if (phy_idx equ=   0) {
602
;            printf("%s: MII PHY not found -- this device may "
603
;                   "not operate correctly.\n", mtdx.nic_name);
604
;        }
605
 
606
        jmp     .no_803
607
 
608
  .is_803:
609
 
610
        mov     [device.phys], 32
611
 
612
; get phy type
613
        set_io  0
614
        set_io  PHYIDENTIFIER
615
        in      eax, dx
616
 
617
        cmp     eax, MysonPHYID
618
        jne     @f
619
 
620
        mov     [device.PHYType], MysonPHY
621
        DEBUGF  1,"MysonPHY\n"
622
        jmp     .no_803
623
 
624
       @@:
625
        mov     [device.PHYType], OtherPHY
626
        DEBUGF  1,"OtherPHY\n"
627
 
628
  .no_803:
629
 
630
;-------
631
;
632
; RESET
633
;
634
;-------
635
align 4
636
reset:
637
 
4470 hidnplayr 638
        DEBUGF  1,"Resetting\n"
3545 hidnplayr 639
 
640
;--------------------------------
641
; insert irq handler on given irq
642
 
643
        movzx   eax, [device.irq_line]
644
        DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
645
        stdcall AttachIntHandler, eax, int_handler, dword 0
646
        test    eax, eax
647
        jnz     @f
4470 hidnplayr 648
        DEBUGF  1,"Could not attach int handler!\n"
3545 hidnplayr 649
;        or      eax, -1
650
;        ret
651
  @@:
652
 
653
; Reset the chip to erase previous misconfiguration.
654
 
655
        set_io  0
656
        set_io  BCR
657
        xor     eax, eax
658
        inc     eax
659
        out     dx, eax
660
 
661
        call    init_ring
662
 
663
; Initialize other registers.
664
; Configure the PCI bus bursts and FIFO thresholds.
665
 
666
        mov     [device.bcrvalue], 0x10 ; little-endian, 8 burst length
667
        mov     [device.crvalue], 0xa00 ; 128 burst length
668
 
669
        cmp     [device.dev_id], 0x891
670
        jne     @f
671
        or      [device.bcrvalue], 0x200       ; set PROG bit
672
        or      [device.crvalue], 0x02000000   ; set enhanced bit
673
       @@:
674
 
675
        or      [device.crvalue], RxEnable + TxThreshold + TxEnable
676
 
677
        call    set_rx_mode
678
 
679
        set_io  0
680
        set_io  BCR
681
        mov     eax, [device.bcrvalue]
682
        out     dx, eax
683
 
684
        set_io  TCRRCR
685
        mov     eax, [device.crvalue]
686
        out     dx, eax
687
 
688
        call    getlinkstatus
689
        call    getlinktype
690
 
691
; Restart Rx engine if stopped.
692
 
693
        set_io  0
694
        set_io  RXPDR
695
        xor     eax, eax
696
        out     dx, eax
697
 
698
; Enable interrupts
699
 
700
        set_io  0
701
        set_io  ISR
702
        mov     eax, (FBE or TUNF or CNTOVF or RBU or TI or RI)
703
        out     dx, eax
704
 
705
        set_io  IMR
706
;        mov     eax, (FBE or TUNF or CNTOVF or RBU or TI or RI)
707
        out     dx, eax
708
 
709
; clear packet/byte counters
710
 
711
        xor     eax, eax
712
        lea     edi, [device.bytes_tx]
713
        mov     ecx, 6
714
        rep     stosd
715
 
716
        mov     [device.mtu], 1514
717
 
718
; Set link state to unknown
719
        mov     [device.state], ETH_LINK_UNKOWN
720
 
721
        xor     eax, eax
722
        ret
723
 
724
 
725
 
726
 
727
align 4
728
init_ring:
729
 
730
        DEBUGF  1,"initializing rx and tx ring\n"
731
 
732
; Initialize all Rx descriptors
733
 
734
        lea     esi, [device.rx_desc]
735
        mov     [device.cur_rx], esi
736
        mov     ecx, NUM_RX_DESC
737
  .rx_desc_loop:
738
        mov     [esi + mtd_desc.status], RXOWN
739
        mov     [esi + mtd_desc.control], 1536 shl RBSShift
740
 
741
        lea     eax, [esi + mtd_desc.size]
742
        mov     [esi + mtd_desc.next_desc_logical], eax
743
        push    ecx esi
744
        GetRealAddr
745
        mov     [esi + mtd_desc.next_desc], eax
746
 
747
        stdcall KernelAlloc, 1536
748
        pop     esi
749
        push    esi
750
        mov     [esi + mtd_desc.skbuff], eax
751
        call    GetPgAddr
752
        pop     esi ecx
753
        mov     [esi + mtd_desc.buffer], eax
754
 
755
        add     esi, mtd_desc.size
756
        loop    .rx_desc_loop
757
 
758
; Mark the last entry as wrapping the ring.
759
 
760
        lea     eax, [device.rx_desc]
761
        mov     [esi - mtd_desc.size + mtd_desc.next_desc_logical], eax
762
        push    esi
763
        GetRealAddr
764
        pop     esi
765
        mov     [esi - mtd_desc.size + mtd_desc.next_desc], eax
766
 
767
        set_io  0
768
        set_io  RXLBA
769
        out     dx, eax
770
 
771
; Initialize all Tx descriptors
772
 
773
        lea     esi, [device.tx_desc]
774
        mov     [device.cur_tx], esi
775
        mov     ecx, NUM_TX_DESC
776
  .tx_desc_loop:
777
        mov     [esi + mtd_desc.status], 0
778
 
779
        lea     eax, [esi + mtd_desc.size]
780
        mov     [esi + mtd_desc.next_desc_logical], eax
781
        push    ecx esi
782
        GetRealAddr
783
        pop     esi ecx
784
        mov     [esi + mtd_desc.next_desc], eax
785
 
786
        add     esi, mtd_desc.size
787
        loop    .tx_desc_loop
788
 
789
; Mark the last entry as wrapping the ring.
790
 
791
        lea     eax, [device.tx_desc]
792
        mov     [esi - mtd_desc.size + mtd_desc.next_desc_logical], eax
793
        push    esi
794
        GetRealAddr
795
        pop     esi
796
        mov     [esi - mtd_desc.size + mtd_desc.next_desc], eax
797
 
798
        set_io  0
799
        set_io  TXLBA
800
        out     dx, eax
801
 
802
        ret
803
 
804
 
805
align 4
806
set_rx_mode:
807
 
808
        DEBUGF  1,"Setting RX mode\n"
809
 
810
; Too many to match, or accept all multicasts.
811
 
812
        set_io  0
813
        set_io  MAR0
814
        xor     eax, eax
815
        not     eax
816
        out     dx, eax
817
        set_io  MAR1
818
        out     dx, eax
819
 
820
        and     [device.crvalue], not (RxModeMask)
821
        or      [device.crvalue], AcceptBroadcast + AcceptMulticast + AcceptMyPhys
822
 
823
        ret
824
 
825
 
826
align 4
827
getlinkstatus:
828
 
829
        DEBUGF  1,"Getting link status\n"
830
 
831
        mov     [device.linkok], 0
832
 
833
        cmp     [device.PHYType], MysonPHY
834
        jne     .no_myson_phy
835
 
836
        set_io  0
837
        set_io  BMCRSR
838
        mov     ecx, 1000
839
  .loop1:
840
        in      eax, dx
841
        test    eax, LinkIsUp2
842
        jnz     .link_ok
843
 
844
        push    ecx edx ebx
845
        mov     esi, 10
846
        call    Sleep
847
        pop     ebx edx ecx
848
        loop    .loop1
849
 
850
        ret
851
 
852
  .no_myson_phy:
853
 
854
;        for (i =   0; i < DelayTime; ++i) {
855
;            if (mdio_read(nic, mtdx.phys[0], MII_BMSR) & BMSR_LSTATUS) {
856
;                mtdx.linkok =   1;
857
;                return;
858
;            }
859
;            m80x_delay(100);
860
 
861
        ret
862
 
863
  .link_ok:
864
        DEBUGF  1,"Link is up\n"
865
        inc     [device.linkok]
866
        ret
867
 
868
 
869
 
870
 
871
align 4
872
getlinktype:
873
 
874
        DEBUGF  1,"Getting link type\n"
875
 
876
        cmp     [device.PHYType], MysonPHY
877
        jne     .no_myson_phy
878
 
879
        DEBUGF  1,"myson PHY\n"
880
 
881
        set_io  0
882
        set_io  TCRRCR
883
        in      eax, dx
884
 
885
        mov     [device.duplexmode], 1  ; 1 =   half duplex
886
        test    eax, FD
887
        jne     @f
888
        DEBUGF  1,"full duplex\n"
889
        inc     [device.duplexmode]     ; 2 =   full duplex
890
       @@:
891
 
892
        mov     [device.line_speed], 1  ; 1 =   10M
893
        test    eax, PS10
894
        jne     @f
895
        DEBUGF  1,"100mbit\n"
896
        inc     [device.line_speed]     ; 2 =   100M
897
       @@:
898
 
899
        ret
900
 
901
  .no_myson_phy:
902
 
903
        DEBUGF  1,"no myson phy\n"
904
 
905
;        if (mtdx.PHYType equ=   SeeqPHY) { /* this PHY is SEEQ 80225 */
906
;            unsigned int data;
907
;
908
;            data =   mdio_read(dev, mtdx.phys[0], MIIRegister18);
909
;            if (data & SPD_DET_100)
910
;                mtdx.line_speed =   2; /* 100M */
911
;            else
912
;                mtdx.line_speed =   1; /* 10M */
913
;            if (data & DPLX_DET_FULL)
914
;                mtdx.duplexmode =   2; /* full duplex mode */
915
;            else
916
;                mtdx.duplexmode =   1; /* half duplex mode */
917
;        } else if (mtdx.PHYType equ=   AhdocPHY) {
918
;            unsigned int data;
919
;
920
;            data =   mdio_read(dev, mtdx.phys[0], DiagnosticReg);
921
;            if (data & Speed_100)
922
;                mtdx.line_speed =   2; /* 100M */
923
;            else
924
;                mtdx.line_speed =   1; /* 10M */
925
;            if (data & DPLX_FULL)
926
;                mtdx.duplexmode =   2; /* full duplex mode */
927
;            else
928
;                mtdx.duplexmode =   1; /* half duplex mode */
929
;        }
930
;        else if (mtdx.PHYType equ=   MarvellPHY) {
931
;            unsigned int data;
932
;
933
;            data =   mdio_read(dev, mtdx.phys[0], SpecificReg);
934
;            if (data & Full_Duplex)
935
;                mtdx.duplexmode =   2; /* full duplex mode */
936
;            else
937
;                mtdx.duplexmode =   1; /* half duplex mode */
938
;            data &=   SpeedMask;
939
;            if (data equ=   Speed_1000M)
940
;                mtdx.line_speed =   3; /* 1000M */
941
;            else if (data equ=   Speed_100M)
942
;                mtdx.line_speed =   2; /* 100M */
943
;            else
944
;                mtdx.line_speed =   1; /* 10M */
945
;        }
946
;        else if (mtdx.PHYType equ=   Myson981) {
947
;            unsigned int data;
948
;
949
;            data =   mdio_read(dev, mtdx.phys[0], StatusRegister);
950
;
951
;            if (data & SPEED100)
952
;                mtdx.line_speed =   2;
953
;            else
954
;                mtdx.line_speed =   1;
955
;
956
;            if (data & FULLMODE)
957
;                mtdx.duplexmode =   2;
958
;            else
959
;                mtdx.duplexmode =   1;
960
;        }
961
;        else if (mtdx.PHYType equ=   LevelOnePHY) {
962
;            unsigned int data;
963
;
964
;            data =   mdio_read(dev, mtdx.phys[0], SpecificReg);
965
;            if (data & LXT1000_Full)
966
;                mtdx.duplexmode =   2; /* full duplex mode */
967
;            else
968
;                mtdx.duplexmode =   1; /* half duplex mode */
969
;            data &=   SpeedMask;
970
;            if (data equ=   LXT1000_1000M)
971
;                mtdx.line_speed =   3; /* 1000M */
972
;            else if (data equ=   LXT1000_100M)
973
;                mtdx.line_speed =   2; /* 100M */
974
;            else
975
 ;               mtdx.line_speed =   1; /* 10M */
976
  ;      }
977
 
978
;        // chage crvalue
979
;        // mtdx.crvalue&equ(~PS10)&(~FD);
980
;        mtdx.crvalue &=   (~PS10) & (~FD) & (~PS1000);
981
;        if (mtdx.line_speed equ=   1)
982
;            mtdx.crvalue |=   PS10;
983
;        else if (mtdx.line_speed equ=   3)
984
;            mtdx.crvalue |=   PS1000;
985
;        if (mtdx.duplexmode equ=   2)
986
;            mtdx.crvalue |=   FD;
987
;
988
 
989
        ret
990
 
991
 
992
 
993
 
994
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
995
;;                                         ;;
996
;; Transmit                                ;;
997
;;                                         ;;
998
;; In: buffer pointer in [esp+4]           ;;
999
;;     size of buffer in [esp+8]           ;;
1000
;;     pointer to device structure in ebx  ;;
1001
;;                                         ;;
1002
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1003
 
1004
align 4
1005
transmit:
1006
 
1007
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
1008
        mov     eax, [esp+4]
1009
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
1010
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
1011
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
1012
        [eax+13]:2,[eax+12]:2
1013
 
1014
        cmp     dword [esp+8], 1514
1015
        ja      .fail
1016
 
1017
        mov     esi, [device.cur_tx]
1018
        push    [esi + mtd_desc.next_desc_logical]
1019
        pop     [device.cur_tx]
1020
 
1021
        ; todo: check if descriptor is not owned by the device!
1022
 
1023
        mov     eax, [esp + 4]
1024
        mov     [esi + mtd_desc.skbuff], eax
1025
        GetRealAddr
1026
        mov     [esi + mtd_desc.buffer], eax
1027
 
1028
        mov     eax, [esp + 8]
1029
        shl     eax, PKTSShift               ; packet size
1030
        or      eax, TXLD + TXFD + CRCEnable + PADEnable + TXIC + 1536 shl TBSShift ; buffer size
1031
        mov     [esi + mtd_desc.control], eax
1032
 
1033
        mov     [esi + mtd_desc.status], TXOWN
1034
 
1035
;-------------
1036
; Update stats
1037
 
1038
        inc     [device.packets_tx]
1039
        mov     eax, [esp+8]
1040
        add     dword [device.bytes_tx], eax
1041
        adc     dword [device.bytes_tx + 4], 0
1042
 
1043
; Point to transmit descriptor
1044
 
1045
        set_io  0
1046
        set_io  TXLBA
1047
        mov     eax, esi
1048
        GetRealAddr
1049
        out     dx, eax
1050
 
1051
;        set_io  TCRRCR
1052
;        mov     eax, [device.crvalue]
1053
;        out     dx, eax
1054
 
1055
; Wake the potentially-idle transmit channel.
1056
 
1057
        set_io  TXPDR           ; TX Poll
1058
        xor     eax, eax
1059
        out     dx, eax
1060
 
1061
        DEBUGF  1,"transmit ok\n"
1062
        xor     eax, eax
1063
        ret     8
1064
 
1065
  .fail:
1066
        DEBUGF  1,"transmit failed\n"
4334 hidnplayr 1067
        stdcall KernelFree, [esp + 4]
3545 hidnplayr 1068
        or      eax, -1
1069
        ret     8
1070
 
1071
 
1072
 
1073
align 4
1074
read_mac:
1075
 
1076
        set_io  0
1077
        set_io  PAR0
1078
        lea     edi, [device.mac]
1079
        insd
1080
        stosd
1081
        set_io  PAR1
1082
        insw
1083
        stosw
1084
 
1085
        DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
1086
        [device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
1087
 
1088
        ret
1089
 
1090
align 4
1091
write_mac:
1092
 
1093
        ret
1094
 
1095
 
1096
 
1097
;;;;;;;;;;;;;;;;;;;;;;;
1098
;;                   ;;
1099
;; Interrupt handler ;;
1100
;;                   ;;
1101
;;;;;;;;;;;;;;;;;;;;;;;
1102
 
1103
align 4
1104
int_handler:
1105
 
1106
        push    ebx esi edi
1107
 
4470 hidnplayr 1108
        DEBUGF  1,"int\n"
3545 hidnplayr 1109
 
1110
; find pointer of device wich made IRQ occur
1111
 
1112
        mov     ecx, [devices]
1113
        test    ecx, ecx
1114
        jz      .nothing
1115
        mov     esi, device_list
1116
  .nextdevice:
1117
        mov     ebx, [esi]
1118
 
1119
        set_io  0
1120
        set_io  ISR
1121
        in      eax, dx
1122
        out     dx, eax                                 ; send it back to ACK
1123
        test    eax, eax
1124
        jnz     .got_it
1125
  .continue:
1126
        add     esi, 4
1127
        dec     ecx
1128
        jnz     .nextdevice
1129
  .nothing:
1130
        pop     edi esi ebx
1131
        xor     eax, eax
1132
 
1133
        ret                                             ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
1134
 
1135
  .got_it:
1136
 
4470 hidnplayr 1137
        DEBUGF  1,"Device: %x Status: %x\n", ebx, ax
3545 hidnplayr 1138
 
1139
        test    ax, RI  ; receive interrupt
1140
        jz      .no_rx
1141
 
1142
        DEBUGF  1,"Receive interrupt\n"
1143
  .rx:
1144
        push    ax
1145
 
1146
  .rx_loop:
1147
        mov     esi, [device.cur_rx]
1148
 
1149
        test    [esi + mtd_desc.status], RXOWN
1150
        jnz     .fail_rx
1151
 
1152
        push    .rx_complete
1153
 
1154
        mov     ecx, [esi + mtd_desc.status]
1155
        shr     ecx, FLNGShift
1156
        sub     ecx, 4                  ; we dont need CRC
1157
        push    ecx
1158
 
1159
;-------------
1160
; Update stats
1161
 
1162
        add     dword [device.bytes_rx], ecx
1163
        adc     dword [device.bytes_rx + 4], 0
1164
        inc     dword [device.packets_rx]
1165
 
1166
 
1167
        push    [esi + mtd_desc.skbuff]
1168
 
1169
        jmp     Eth_input
1170
 
1171
  .rx_complete:
1172
        mov     esi, [device.cur_rx]
1173
 
1174
        mov     [esi + mtd_desc.control], 1536 shl RBSShift
1175
 
1176
        stdcall KernelAlloc, 1536
1177
        mov     [esi + mtd_desc.skbuff], eax
1178
        call    GetPgAddr
1179
        mov     [esi + mtd_desc.buffer], eax
1180
 
1181
        mov     [esi + mtd_desc.status], RXOWN
1182
 
1183
        mov     eax, [esi + mtd_desc.next_desc_logical]
1184
        mov     [device.cur_rx], eax
1185
 
1186
        jmp     .rx_loop
1187
;
1188
;    while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
1189
;    {
1190
;        mtdx.cur_rx->status = RXOWN;
1191
;        mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
1192
;    }
1193
;
1194
;    /* Restart Rx engine if stopped. */
1195
;    outl(0, mtdx.ioaddr + RXPDR);
1196
 
1197
  .fail_rx:
1198
        DEBUGF  1,"RX failed\n"
1199
 
1200
        pop     ax
1201
  .no_rx:
1202
 
1203
        test    ax, TI ; transmit interrupt
1204
        jz      .no_tx
1205
 
1206
        DEBUGF  1,"Transmit interrupt\n"
1207
        push    ax
1208
 
1209
        lea     esi, [device.tx_desc]
1210
        mov     ecx, NUM_TX_DESC
1211
  .tx_loop:
1212
 
1213
        test    [esi + mtd_desc.status], TXOWN
1214
        jnz     .skip_this_one
1215
 
1216
        mov     eax, [esi + mtd_desc.skbuff]
1217
        test    eax, eax
1218
        je      .skip_this_one
1219
 
1220
        mov     [esi + mtd_desc.skbuff], 0
1221
 
1222
        DEBUGF  1,"freeing buffer:%x\n", eax
1223
        stdcall KernelFree, eax
1224
 
1225
  .skip_this_one:
1226
        mov     esi, [esi + mtd_desc.next_desc_logical]
1227
        loop    .tx_loop
1228
 
1229
        pop     ax
1230
 
1231
  .no_tx:
1232
 
1233
        test    ax, TBU
1234
        jz      .no_tbu
1235
 
1236
        DEBUGF  1,"Transmit buffer unavailable!\n"
1237
 
1238
  .no_tbu:
1239
 
1240
  .fail:
1241
        pop     edi esi ebx
1242
        xor     eax, eax
1243
        inc     eax
1244
 
1245
        ret
1246
 
1247
 
1248
; End of code
1249
 
1250
align 4                                         ; Place all initialised data here
1251
 
1252
devices       dd 0
1253
version       dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
1254
my_service    db 'mtd80x',0                    ; max 16 chars include zero
1255
 
1256
 
1257
;   0x1516, 0x0800, "MTD800", "Myson MTD800"
1258
;   0x1516, 0x0803, "MTD803", "Surecom EP-320X"
1259
;   0x1516, 0x0891, "MTD891", "Myson MTD891"
1260
 
1261
 
1262
include_debug_strings                           ; All data wich FDO uses will be included here
1263
 
1264
section '.data' data readable writable align 16 ; place all uninitialized data place here
1265
 
1266
device_list rd MAX_DEVICES                     ; This list contains all pointers to device structures the driver is handling
1267