Subversion Repositories Kolibri OS

Rev

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