Subversion Repositories Kolibri OS

Rev

Rev 4470 | Rev 4580 | 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
 
4576 hidnplayr 28
        NUM_TX_DESC             = 6
29
        NUM_RX_DESC             = 12
3545 hidnplayr 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"
4576 hidnplayr 649
        or      eax, -1
650
        ret
3545 hidnplayr 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
 
4576 hidnplayr 666
        mov     [device.bcrvalue], 0x10         ; little-endian, 8 burst length
667
        mov     [device.crvalue], 0xa00         ; 128 burst length
3545 hidnplayr 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
4576 hidnplayr 702
        mov     eax, FBE or TUNF or CNTOVF or RBU or TI or RI
3545 hidnplayr 703
        out     dx, eax
704
        set_io  IMR
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
4576 hidnplayr 783
        mov     [esi + mtd_desc.skbuff], 0
3545 hidnplayr 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]
4576 hidnplayr 1016
 
1017
        test    [esi + mtd_desc.status], TXOWN
1018
        jnz     .fail
1019
 
3545 hidnplayr 1020
        push    [esi + mtd_desc.next_desc_logical]
1021
        pop     [device.cur_tx]
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]
4576 hidnplayr 1029
        mov     ecx, eax
3545 hidnplayr 1030
        shl     eax, PKTSShift               ; packet size
4576 hidnplayr 1031
        shl     ecx, TBSShift
1032
        or      eax, ecx
1033
        or      eax, TXIC + TXLD + TXFD + CRCEnable + PADEnable
3545 hidnplayr 1034
        mov     [esi + mtd_desc.control], eax
1035
        mov     [esi + mtd_desc.status], TXOWN
1036
 
1037
; Update stats
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
 
4576 hidnplayr 1043
; TX Poll
3545 hidnplayr 1044
        set_io  0
4576 hidnplayr 1045
        set_io  TXPDR
3545 hidnplayr 1046
        xor     eax, eax
1047
        out     dx, eax
1048
 
1049
        DEBUGF  1,"transmit ok\n"
1050
        xor     eax, eax
1051
        ret     8
1052
 
1053
  .fail:
1054
        DEBUGF  1,"transmit failed\n"
4334 hidnplayr 1055
        stdcall KernelFree, [esp + 4]
3545 hidnplayr 1056
        or      eax, -1
1057
        ret     8
1058
 
1059
 
1060
 
1061
align 4
1062
read_mac:
1063
 
1064
        set_io  0
1065
        set_io  PAR0
1066
        lea     edi, [device.mac]
1067
        insd
1068
        set_io  PAR1
1069
        insw
1070
        DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
1071
        [device.mac+0]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
1072
 
1073
        ret
1074
 
1075
align 4
1076
write_mac:
1077
 
1078
        ret
1079
 
1080
 
1081
 
1082
;;;;;;;;;;;;;;;;;;;;;;;
1083
;;                   ;;
1084
;; Interrupt handler ;;
1085
;;                   ;;
1086
;;;;;;;;;;;;;;;;;;;;;;;
1087
 
1088
align 4
1089
int_handler:
1090
 
1091
        push    ebx esi edi
1092
 
4576 hidnplayr 1093
        DEBUGF  1,"INT\n"
3545 hidnplayr 1094
 
1095
; find pointer of device wich made IRQ occur
1096
 
1097
        mov     ecx, [devices]
1098
        test    ecx, ecx
1099
        jz      .nothing
1100
        mov     esi, device_list
1101
  .nextdevice:
1102
        mov     ebx, [esi]
1103
 
1104
        set_io  0
1105
        set_io  ISR
1106
        in      eax, dx
1107
        out     dx, eax                                 ; send it back to ACK
1108
        test    eax, eax
1109
        jnz     .got_it
1110
  .continue:
1111
        add     esi, 4
1112
        dec     ecx
1113
        jnz     .nextdevice
1114
  .nothing:
1115
        pop     edi esi ebx
1116
        xor     eax, eax
1117
 
1118
        ret                                             ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
1119
 
1120
  .got_it:
1121
 
4470 hidnplayr 1122
        DEBUGF  1,"Device: %x Status: %x\n", ebx, ax
3545 hidnplayr 1123
 
1124
        test    ax, RI  ; receive interrupt
1125
        jz      .no_rx
1126
        push    ax
1127
  .rx_loop:
1128
        mov     esi, [device.cur_rx]
1129
        test    [esi + mtd_desc.status], RXOWN
1130
        jnz     .fail_rx
1131
 
4576 hidnplayr 1132
        push    ebx
3545 hidnplayr 1133
        push    .rx_complete
1134
 
1135
        mov     ecx, [esi + mtd_desc.status]
1136
        shr     ecx, FLNGShift
1137
        sub     ecx, 4                  ; we dont need CRC
1138
        push    ecx
4576 hidnplayr 1139
        DEBUGF  1,"Received %u bytes\n", ecx
3545 hidnplayr 1140
 
1141
; Update stats
4576 hidnplayr 1142
        add     dword[device.bytes_rx], ecx
1143
        adc     dword[device.bytes_rx + 4], 0
1144
        inc     [device.packets_rx]
3545 hidnplayr 1145
 
1146
        push    [esi + mtd_desc.skbuff]
1147
        jmp     Eth_input
1148
 
1149
  .rx_complete:
4576 hidnplayr 1150
        pop     ebx
3545 hidnplayr 1151
        mov     esi, [device.cur_rx]
1152
        mov     [esi + mtd_desc.control], 1536 shl RBSShift
4576 hidnplayr 1153
        push    esi
3545 hidnplayr 1154
        stdcall KernelAlloc, 1536
4576 hidnplayr 1155
        pop     esi
3545 hidnplayr 1156
        mov     [esi + mtd_desc.skbuff], eax
1157
        call    GetPgAddr
1158
        mov     [esi + mtd_desc.buffer], eax
1159
        mov     [esi + mtd_desc.status], RXOWN
1160
 
4576 hidnplayr 1161
        push    [esi + mtd_desc.next_desc_logical]
1162
        pop     [device.cur_rx]
3545 hidnplayr 1163
 
1164
        jmp     .rx_loop
1165
;
1166
;    while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
1167
;    {
1168
;        mtdx.cur_rx->status = RXOWN;
1169
;        mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
1170
;    }
1171
;
1172
;    /* Restart Rx engine if stopped. */
1173
;    outl(0, mtdx.ioaddr + RXPDR);
1174
 
1175
  .fail_rx:
4576 hidnplayr 1176
        DEBUGF  1,"RX done\n"
1177
        pop     ax
3545 hidnplayr 1178
 
1179
  .no_rx:
1180
        test    ax, TI ; transmit interrupt
1181
        jz      .no_tx
4576 hidnplayr 1182
        DEBUGF  1,"TX\n"
3545 hidnplayr 1183
        push    ax
1184
        lea     esi, [device.tx_desc]
1185
        mov     ecx, NUM_TX_DESC
1186
  .tx_loop:
1187
        test    [esi + mtd_desc.status], TXOWN
1188
        jnz     .skip_this_one
1189
        mov     eax, [esi + mtd_desc.skbuff]
1190
        test    eax, eax
1191
        je      .skip_this_one
1192
        mov     [esi + mtd_desc.skbuff], 0
4576 hidnplayr 1193
        DEBUGF  1,"freeing buffer: 0x%x\n", eax
3545 hidnplayr 1194
        stdcall KernelFree, eax
1195
  .skip_this_one:
1196
        mov     esi, [esi + mtd_desc.next_desc_logical]
1197
        loop    .tx_loop
1198
        pop     ax
1199
 
1200
  .no_tx:
4576 hidnplayr 1201
;        test    ax, TBU
1202
;        jz      .no_tbu
1203
;        DEBUGF  2,"Transmit buffer unavailable!\n"
1204
;  .no_tbu:
3545 hidnplayr 1205
 
1206
  .fail:
1207
        pop     edi esi ebx
1208
        xor     eax, eax
1209
        inc     eax
1210
 
1211
        ret
1212
 
1213
 
1214
; End of code
1215
 
1216
align 4                                         ; Place all initialised data here
1217
 
1218
devices       dd 0
1219
version       dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
1220
my_service    db 'mtd80x',0                    ; max 16 chars include zero
1221
 
1222
 
1223
;   0x1516, 0x0800, "MTD800", "Myson MTD800"
1224
;   0x1516, 0x0803, "MTD803", "Surecom EP-320X"
1225
;   0x1516, 0x0891, "MTD891", "Myson MTD891"
1226
 
1227
 
1228
include_debug_strings                           ; All data wich FDO uses will be included here
1229
 
1230
section '.data' data readable writable align 16 ; place all uninitialized data place here
1231
 
1232
device_list rd MAX_DEVICES                     ; This list contains all pointers to device structures the driver is handling
1233