176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**************************************************************************
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*    mtd80x.c: Etherboot device driver for the mtd80x Ethernet chip.
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*    Written 2004-2004 by Erdem Güven <zuencap@yahoo.com>
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*    This program is free software; you can redistribute it and/or modify
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*    it under the terms of the GNU General Public License as published by
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*    the Free Software Foundation; either version 2 of the License, or
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*    (at your option) any later version.
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*    This program is distributed in the hope that it will be useful,
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*    but WITHOUT ANY WARRANTY; without even the implied warranty of
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*    GNU General Public License for more details.
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*    You should have received a copy of the GNU General Public License
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*    along with this program; if not, write to the Free Software
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*    Portions of this code based on:
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*               fealnx.c: A Linux device driver for the mtd80x Ethernet chip
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*               Written 1998-2000 by Donald Becker
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman***************************************************************************/
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2676d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( GPL2_OR_LATER );
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* to get some global routines like printf */
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "etherboot.h"
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* to get the interface to the body of the program */
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "nic.h"
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* to get the PCI support functions, if this is a PCI NIC */
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/pci.h>
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/ethernet.h>
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <mii.h>
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Condensed operations for readability. */
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define le32desc_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define get_unaligned(ptr) (*(ptr))
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Operational parameters that are set at compile time. */
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Keep the ring sizes a power of two for compile efficiency.           */
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* The compiler will convert <unsigned>'%'<2^N> into a bit mask.        */
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Making the Tx ring too large decreases the effectiveness of channel  */
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* bonding and packet priority.                                         */
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* There are no ill effects from too-large receive rings.               */
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define TX_RING_SIZE 2
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define TX_QUEUE_LEN 10 /* Limit ring entries actually used.  */
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define RX_RING_SIZE 4
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Operational parameters that usually are not changed. */
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Time in jiffies before concluding the transmitter is hung. */
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define HZ 100
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define TX_TIME_OUT   (6*HZ)
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Allocation size of Rx buffers with normal sized Ethernet frames.
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   Do not change this value without good reason.  This is not a limit,
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   but a way to keep a consistent allocation size among drivers.
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PKT_BUF_SZ 1536
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* for different PHY */
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum phy_type_flags {
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    MysonPHY = 1,
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    AhdocPHY = 2,
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    SeeqPHY = 3,
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    MarvellPHY = 4,
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    Myson981 = 5,
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    LevelOnePHY = 6,
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    OtherPHY = 10,
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* A chip capabilities table*/
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum chip_capability_flags {
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    HAS_MII_XCVR,
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    HAS_CHIP_XCVR,
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if 0 /* not used */
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct chip_info
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u16 dev_id;
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int flag;
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanmtd80x_chips[] = {
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                     {0x0800, HAS_MII_XCVR},
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                     {0x0803, HAS_CHIP_XCVR},
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                     {0x0891, HAS_MII_XCVR}
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                 };
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int chip_cnt = sizeof( mtd80x_chips ) / sizeof( struct chip_info );
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Offsets to the Command and Status Registers. */
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum mtd_offsets {
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    PAR0 = 0x0,        /* physical address 0-3 */
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    PAR1 = 0x04,        /* physical address 4-5 */
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    MAR0 = 0x08,        /* multicast address 0-3 */
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    MAR1 = 0x0C,        /* multicast address 4-7 */
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    FAR0 = 0x10,        /* flow-control address 0-3 */
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    FAR1 = 0x14,        /* flow-control address 4-5 */
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TCRRCR = 0x18,        /* receive & transmit configuration */
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    BCR = 0x1C,        /* bus command */
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TXPDR = 0x20,        /* transmit polling demand */
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RXPDR = 0x24,        /* receive polling demand */
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RXCWP = 0x28,        /* receive current word pointer */
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TXLBA = 0x2C,        /* transmit list base address */
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RXLBA = 0x30,        /* receive list base address */
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ISR = 0x34,        /* interrupt status */
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    IMR = 0x38,        /* interrupt mask */
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    FTH = 0x3C,        /* flow control high/low threshold */
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    MANAGEMENT = 0x40,    /* bootrom/eeprom and mii management */
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TALLY = 0x44,        /* tally counters for crc and mpa */
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TSR = 0x48,        /* tally counter for transmit status */
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    BMCRSR = 0x4c,        /* basic mode control and status */
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    PHYIDENTIFIER = 0x50,    /* phy identifier */
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ANARANLPAR = 0x54,    /* auto-negotiation advertisement and link
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                                                       partner ability */
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ANEROCR = 0x58,        /* auto-negotiation expansion and pci conf. */
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    BPREMRPSR = 0x5c,    /* bypass & receive error mask and phy status */
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Bits in the interrupt status/enable registers. */
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* The bits in the Intr Status/Enable registers, mostly interrupt sources. */
12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum intr_status_bits {
12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RFCON = 0x00020000, /* receive flow control xon packet */
13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RFCOFF = 0x00010000, /* receive flow control xoff packet */
13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    LSCStatus = 0x00008000, /* link status change */
13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ANCStatus = 0x00004000, /* autonegotiation completed */
13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    FBE = 0x00002000, /* fatal bus error */
13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    FBEMask = 0x00001800, /* mask bit12-11 */
13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ParityErr = 0x00000000, /* parity error */
13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TargetErr = 0x00001000, /* target abort */
13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    MasterErr = 0x00000800, /* master error */
13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TUNF = 0x00000400, /* transmit underflow */
13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ROVF = 0x00000200, /* receive overflow */
14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ETI = 0x00000100, /* transmit early int */
14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ERI = 0x00000080, /* receive early int */
14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    CNTOVF = 0x00000040, /* counter overflow */
14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RBU = 0x00000020, /* receive buffer unavailable */
14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TBU = 0x00000010, /* transmit buffer unavilable */
14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TI = 0x00000008, /* transmit interrupt */
14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RI = 0x00000004, /* receive interrupt */
14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RxErr = 0x00000002, /* receive error */
14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Bits in the NetworkConfig register. */
15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum rx_mode_bits {
15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RxModeMask   = 0xe0,
15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    AcceptAllPhys = 0x80,        /* promiscuous mode */
15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    AcceptBroadcast = 0x40,        /* accept broadcast */
15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    AcceptMulticast = 0x20,        /* accept mutlicast */
15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    AcceptRunt   = 0x08,        /* receive runt pkt */
15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ALP          = 0x04,        /* receive long pkt */
15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    AcceptErr    = 0x02,        /* receive error pkt */
15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    AcceptMyPhys = 0x00000000,
16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RxEnable     = 0x00000001,
16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RxFlowCtrl   = 0x00002000,
16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TxEnable     = 0x00040000,
16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TxModeFDX    = 0x00100000,
16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TxThreshold  = 0x00e00000,
16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    PS1000       = 0x00010000,
16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    PS10         = 0x00080000,
16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    FD           = 0x00100000,
17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Bits in network_desc.status */
17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum rx_desc_status_bits {
17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RXOWN = 0x80000000, /* own bit */
17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    FLNGMASK = 0x0fff0000, /* frame length */
17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    FLNGShift = 16,
17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    MARSTATUS = 0x00004000, /* multicast address received */
17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    BARSTATUS = 0x00002000, /* broadcast address received */
17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    PHYSTATUS = 0x00001000, /* physical address received */
18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RXFSD = 0x00000800, /* first descriptor */
18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RXLSD = 0x00000400, /* last descriptor */
18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ErrorSummary = 0x80, /* error summary */
18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RUNT = 0x40,  /* runt packet received */
18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    LONG = 0x20,  /* long packet received */
18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    FAE = 0x10,  /* frame align error */
18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    CRC = 0x08,  /* crc error */
18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RXER = 0x04,  /* receive error */
18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum rx_desc_control_bits {
19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RXIC = 0x00800000, /* interrupt control */
19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RBSShift = 0,
19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum tx_desc_status_bits {
19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TXOWN = 0x80000000, /* own bit */
19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    JABTO = 0x00004000, /* jabber timeout */
19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    CSL = 0x00002000, /* carrier sense lost */
19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    LC = 0x00001000, /* late collision */
20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    EC = 0x00000800, /* excessive collision */
20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    UDF = 0x00000400, /* fifo underflow */
20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    DFR = 0x00000200, /* deferred */
20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    HF = 0x00000100, /* heartbeat fail */
20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    NCRMask = 0x000000ff, /* collision retry count */
20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    NCRShift = 0,
20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanenum tx_desc_control_bits {
20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TXIC = 0x80000000, /* interrupt control */
21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ETIControl = 0x40000000, /* early transmit interrupt */
21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TXLD = 0x20000000, /* last descriptor */
21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TXFD = 0x10000000, /* first descriptor */
21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    CRCEnable = 0x08000000, /* crc control */
21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    PADEnable = 0x04000000, /* padding control */
21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    RetryTxLC = 0x02000000, /* retry late collision */
21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    PKTSMask = 0x3ff800, /* packet size bit21-11 */
21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    PKTSShift = 11,
21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TBSMask = 0x000007ff, /* transmit buffer bit 10-0 */
21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    TBSShift = 0,
22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* BootROM/EEPROM/MII Management Register */
22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MASK_MIIR_MII_READ       0x00000000
22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MASK_MIIR_MII_WRITE      0x00000008
22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MASK_MIIR_MII_MDO        0x00000004
22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MASK_MIIR_MII_MDI        0x00000002
22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MASK_MIIR_MII_MDC        0x00000001
22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ST+OP+PHYAD+REGAD+TA */
23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define OP_READ             0x6000 /* ST:01+OP:10+PHYAD+REGAD+TA:Z0 */
23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define OP_WRITE            0x5002 /* ST:01+OP:01+PHYAD+REGAD+TA:10 */
23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ------------------------------------------------------------------------- */
23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*      Constants for Myson PHY                                              */
23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ------------------------------------------------------------------------- */
23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MysonPHYID      0xd0000302
23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 89-7-27 add, (begin) */
23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MysonPHYID0     0x0302
23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define StatusRegister  18
24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define SPEED100        0x0400 // bit10
24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define FULLMODE        0x0800 // bit11
24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 89-7-27 add, (end) */
24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ------------------------------------------------------------------------- */
24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*      Constants for Seeq 80225 PHY                                         */
24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ------------------------------------------------------------------------- */
24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define SeeqPHYID0      0x0016
24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MIIRegister18   18
25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define SPD_DET_100     0x80
25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define DPLX_DET_FULL   0x40
25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ------------------------------------------------------------------------- */
25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*      Constants for Ahdoc 101 PHY                                          */
25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ------------------------------------------------------------------------- */
25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define AhdocPHYID0     0x0022
25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define DiagnosticReg   18
25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define DPLX_FULL       0x0800
26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define Speed_100       0x0400
26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 89/6/13 add, */
26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* -------------------------------------------------------------------------- */
26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*      Constants                                                             */
26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* -------------------------------------------------------------------------- */
26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MarvellPHYID0           0x0141
26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LevelOnePHYID0  0x0013
26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MII1000BaseTControlReg  9
27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MII1000BaseTStatusReg   10
27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define SpecificReg  17
27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* for 1000BaseT Control Register */
27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PHYAbletoPerform1000FullDuplex  0x0200
27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PHYAbletoPerform1000HalfDuplex  0x0100
27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PHY1000AbilityMask              0x300
27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// for phy specific status register, marvell phy.
27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define SpeedMask       0x0c000
28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define Speed_1000M     0x08000
28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define Speed_100M      0x4000
28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define Speed_10M       0
28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define Full_Duplex     0x2000
28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// 89/12/29 add, for phy specific status register, levelone phy, (begin)
28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LXT1000_100M    0x08000
28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LXT1000_1000M   0x0c000
28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LXT1000_Full    0x200
28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// 89/12/29 add, for phy specific status register, levelone phy, (end)
29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if 0
29276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* for 3-in-1 case */
29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PS10            0x00080000
29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define FD              0x00100000
29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PS1000          0x00010000
29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
29776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
29876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* for PHY */
29976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LinkIsUp        0x0004
30076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define LinkIsUp2 0x00040000
30176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
30276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Create a static buffer of size PKT_BUF_SZ for each
30376d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanRX and TX Descriptor.  All descriptors point to a
30476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpart of this buffer */
30576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct {
30676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	u8 txb[PKT_BUF_SZ * TX_RING_SIZE] __attribute__ ((aligned(8)));
30776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	u8 rxb[PKT_BUF_SZ * RX_RING_SIZE] __attribute__ ((aligned(8)));
30876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} mtd80x_bufs __shared;
30976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define txb mtd80x_bufs.txb
31076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define rxb mtd80x_bufs.rxb
31176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
31276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* The Tulip Rx and Tx buffer descriptors. */
31376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct mtd_desc
31476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
31576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    s32 status;
31676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    s32 control;
31776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u32 buffer;
31876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u32 next_desc;
31976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct mtd_desc *next_desc_logical;
32076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u8* skbuff;
32176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u32 reserved1;
32276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u32 reserved2;
32376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
32476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
32576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct mtd_private
32676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
32776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct mtd_desc rx_ring[RX_RING_SIZE];
32876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct mtd_desc tx_ring[TX_RING_SIZE];
32976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
33076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Frequently used values: keep some adjacent for cache effect. */
33176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int flags;
33276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct pci_dev *pci_dev;
33376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned long crvalue;
33476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned long bcrvalue;
33576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /*unsigned long imrvalue;*/
33676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct mtd_desc *cur_rx;
33776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct mtd_desc *lack_rxbuf;
33876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int really_rx_count;
33976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct mtd_desc *cur_tx;
34076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct mtd_desc *cur_tx_copy;
34176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int really_tx_count;
34276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int free_tx_count;
34376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned int rx_buf_sz; /* Based on MTU+slack. */
34476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
34576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* These values are keep track of the transceiver/media in use. */
34676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned int linkok;
34776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned int line_speed;
34876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned int duplexmode;
34976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned int default_port:
35076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    4; /* Last dev->if_port value. */
35176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned int PHYType;
35276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
35376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* MII transceiver section. */
35476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int mii_cnt;  /* MII device addresses. */
35576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned char phys[1]; /* MII device addresses. */
35676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
35776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /*other*/
35876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    const char *nic_name;
35976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int ioaddr;
36076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u16 dev_id;
36176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
36276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
36376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct mtd_private mtdx;
36476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
36576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int mdio_read(struct nic * , int phy_id, int location);
36676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void getlinktype(struct nic * );
36776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void getlinkstatus(struct nic * );
36876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void set_rx_mode(struct nic *);
36976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
37076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**************************************************************************
37176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *  init_ring - setup the tx and rx descriptors
37276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *************************************************************************/
37376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void init_ring(struct nic *nic __unused)
37476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
37576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int i;
37676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
37776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.cur_rx = &mtdx.rx_ring[0];
37876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
37976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.rx_buf_sz = PKT_BUF_SZ;
38076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /*mtdx.rx_head_desc = &mtdx.rx_ring[0];*/
38176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
38276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Initialize all Rx descriptors. */
38376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Fill in the Rx buffers.  Handle allocation failure gracefully. */
38476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    for (i = 0; i < RX_RING_SIZE; i++)
38576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
38676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        mtdx.rx_ring[i].status = RXOWN;
38776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        mtdx.rx_ring[i].control = mtdx.rx_buf_sz << RBSShift;
38876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        mtdx.rx_ring[i].next_desc = virt_to_le32desc(&mtdx.rx_ring[i+1]);
38976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        mtdx.rx_ring[i].next_desc_logical = &mtdx.rx_ring[i+1];
39076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        mtdx.rx_ring[i].buffer = virt_to_le32desc(&rxb[i * PKT_BUF_SZ]);
39176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        mtdx.rx_ring[i].skbuff = &rxb[i * PKT_BUF_SZ];
39276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
39376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Mark the last entry as wrapping the ring. */
39476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.rx_ring[i-1].next_desc = virt_to_le32desc(&mtdx.rx_ring[0]);
39576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.rx_ring[i-1].next_desc_logical = &mtdx.rx_ring[0];
39676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
39776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* We only use one transmit buffer, but two
39876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     * descriptors so transmit engines have somewhere
39976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     * to point should they feel the need */
40076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.tx_ring[0].status = 0x00000000;
40176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.tx_ring[0].buffer = virt_to_bus(&txb[0]);
40276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.tx_ring[0].next_desc = virt_to_le32desc(&mtdx.tx_ring[1]);
40376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
40476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* This descriptor is never used */
40576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.tx_ring[1].status = 0x00000000;
40676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.tx_ring[1].buffer = 0; /*virt_to_bus(&txb[1]); */
40776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.tx_ring[1].next_desc = virt_to_le32desc(&mtdx.tx_ring[0]);
40876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
40976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return;
41076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
41176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
41276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**************************************************************************
41376d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanRESET - Reset Adapter
41476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman***************************************************************************/
41576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void mtd_reset( struct nic *nic )
41676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
41776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Reset the chip to erase previous misconfiguration. */
41876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl(0x00000001, mtdx.ioaddr + BCR);
41976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
42076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    init_ring(nic);
42176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
42276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl(virt_to_bus(mtdx.rx_ring), mtdx.ioaddr + RXLBA);
42376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl(virt_to_bus(mtdx.tx_ring), mtdx.ioaddr + TXLBA);
42476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
42576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Initialize other registers. */
42676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Configure the PCI bus bursts and FIFO thresholds. */
42776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.bcrvalue = 0x10; /* little-endian, 8 burst length */
42876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.crvalue = 0xa00; /* rx 128 burst length */
42976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
43076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if ( mtdx.dev_id == 0x891 ) {
43176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		mtdx.bcrvalue |= 0x200;	/* set PROG bit */
43276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		mtdx.crvalue |= 0x02000000;	/* set enhanced bit */
43376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	}
43476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
43576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl( mtdx.bcrvalue, mtdx.ioaddr + BCR);
43676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
43776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Restart Rx engine if stopped. */
43876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl(0, mtdx.ioaddr + RXPDR);
43976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
44076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    getlinkstatus(nic);
44176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (mtdx.linkok)
44276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
44376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        static const char* texts[]={"half","full","10","100","1000"};
44476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        getlinktype(nic);
44576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        DBG ( "Link is OK : %s %s\n", texts[mtdx.duplexmode-1], texts[mtdx.line_speed+1] );
44676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } else
44776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
44876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        DBG ( "No link!!!\n" );
44976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
45076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
45176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.crvalue |= /*TxEnable |*/ RxEnable | TxThreshold;
45276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    set_rx_mode(nic);
45376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
45476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Clear interrupts by setting the interrupt mask. */
45576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl(FBE | TUNF | CNTOVF | RBU | TI | RI, mtdx.ioaddr + ISR);
45676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl( 0, mtdx.ioaddr + IMR);
45776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
45876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
45976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**************************************************************************
46076d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanPOLL - Wait for a frame
46176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman***************************************************************************/
46276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int mtd_poll(struct nic *nic, __unused int retrieve)
46376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
46476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    s32 rx_status = mtdx.cur_rx->status;
46576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int retval = 0;
46676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
46776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if( ( rx_status & RXOWN ) != 0 )
46876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
46976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return 0;
47076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
47176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
47276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (rx_status & ErrorSummary)
47376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    { /* there was a fatal error */
47476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        printf( "%s: Receive error, Rx status %8.8x, Error(s) %s%s%s\n",
47576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.nic_name, (unsigned int) rx_status,
47676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                (rx_status & (LONG | RUNT)) ? "length_error ":"",
47776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                (rx_status & RXER) ? "frame_error ":"",
47876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                (rx_status & CRC) ? "crc_error ":"" );
47976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        retval = 0;
48076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } else if( !((rx_status & RXFSD) && (rx_status & RXLSD)) )
48176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
48276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* this pkt is too long, over one rx buffer */
48376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        printf("Pkt is too long, over one rx buffer.\n");
48476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        retval = 0;
48576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } else
48676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    { /* this received pkt is ok */
48776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* Omit the four octet CRC from the length. */
48876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        short pkt_len = ((rx_status & FLNGMASK) >> FLNGShift) - 4;
48976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
49076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        DBG ( " netdev_rx() normal Rx pkt length %d"
49176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 	      " status %x.\n", pkt_len, (unsigned int) rx_status );
49276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
49376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        nic->packetlen = pkt_len;
49476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        memcpy(nic->packet, mtdx.cur_rx->skbuff, pkt_len);
49576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
49676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        retval = 1;
49776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
49876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
49976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
50076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
50176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        mtdx.cur_rx->status = RXOWN;
50276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
50376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
50476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
50576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Restart Rx engine if stopped. */
50676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl(0, mtdx.ioaddr + RXPDR);
50776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
50876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return retval;
50976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
51076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
51176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**************************************************************************
51276d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanTRANSMIT - Transmit a frame
51376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman***************************************************************************/
51476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void mtd_transmit(
51576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct nic *nic,
51676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    const char *dest,            /* Destination */
51776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned int type,            /* Type */
51876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned int size,            /* size */
51976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    const char *data)            /* Packet */
52076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
52176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u32 to;
52276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u32 tx_status;
52376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned int nstype = htons ( type );
52476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
52576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    memcpy( txb, dest, ETH_ALEN );
52676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    memcpy( txb + ETH_ALEN, nic->node_addr, ETH_ALEN );
52776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    memcpy( txb + 2 * ETH_ALEN, &nstype, 2 );
52876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    memcpy( txb + ETH_HLEN, data, size );
52976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
53076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    size += ETH_HLEN;
53176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    size &= 0x0FFF;
53276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    while( size < ETH_ZLEN )
53376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
53476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        txb[size++] = '\0';
53576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
53676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
53776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.tx_ring[0].control = TXLD | TXFD | CRCEnable | PADEnable;
53876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.tx_ring[0].control |= (size << PKTSShift); /* pkt size */
53976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.tx_ring[0].control |= (size << TBSShift); /* buffer size */
54076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.tx_ring[0].status = TXOWN;
54176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
54276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Point to transmit descriptor */
54376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl(virt_to_bus(mtdx.tx_ring), mtdx.ioaddr + TXLBA);
54476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Enable Tx */
54576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl( mtdx.crvalue | TxEnable, mtdx.ioaddr + TCRRCR);
54676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Wake the potentially-idle transmit channel. */
54776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl(0, mtdx.ioaddr + TXPDR);
54876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
54976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    to = currticks() + TX_TIME_OUT;
55076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    while(( mtdx.tx_ring[0].status & TXOWN) && (currticks() < to));
55176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
55276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Disable Tx */
55376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl( mtdx.crvalue & (~TxEnable), mtdx.ioaddr + TCRRCR);
55476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
55576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    tx_status = mtdx.tx_ring[0].status;
55676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (currticks() >= to){
55776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        DBG ( "TX Time Out" );
55876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } else if( tx_status & (CSL | LC | EC | UDF | HF)){
55976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        printf( "Transmit error: %8.8x %s %s %s %s %s\n",
56076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                (unsigned int) tx_status,
56176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                tx_status & EC ? "abort" : "",
56276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                tx_status & CSL ? "carrier" : "",
56376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                tx_status & LC ? "late" : "",
56476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                tx_status & UDF ? "fifo" : "",
56576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                tx_status & HF ? "heartbeat" : "" );
56676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
56776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
56876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /*hex_dump( txb, size );*/
56976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /*pause();*/
57076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
57176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    DBG ( "TRANSMIT\n" );
57276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
57376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
57476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**************************************************************************
57576d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanDISABLE - Turn off ethernet interface
57676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman***************************************************************************/
57776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void mtd_disable ( struct nic *nic ) {
57876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
57976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Disable Tx Rx*/
58076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl( mtdx.crvalue & (~TxEnable) & (~RxEnable), mtdx.ioaddr + TCRRCR );
58176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
58276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Reset the chip to erase previous misconfiguration. */
58376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtd_reset(nic);
58476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
58576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    DBG ( "DISABLE\n" );
58676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
58776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
58876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct nic_operations mtd_operations = {
58976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.connect	= dummy_connect,
59076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.poll		= mtd_poll,
59176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.transmit	= mtd_transmit,
59276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.irq		= dummy_irq,
59376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
59476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
59576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
59676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct pci_device_id mtd80x_nics[] = {
59776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        PCI_ROM(0x1516, 0x0800, "MTD800", "Myson MTD800", 0),
59876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        PCI_ROM(0x1516, 0x0803, "MTD803", "Surecom EP-320X", 0),
59976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        PCI_ROM(0x1516, 0x0891, "MTD891", "Myson MTD891", 0),
60076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
60176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
60276d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanPCI_DRIVER ( mtd80x_driver, mtd80x_nics, PCI_NO_CLASS );
60376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
60476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**************************************************************************
60576d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanPROBE - Look for an adapter, this routine's visible to the outside
60676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman***************************************************************************/
60776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
60876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int mtd_probe ( struct nic *nic, struct pci_device *pci ) {
60976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
61076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int i;
61176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
61276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (pci->ioaddr == 0)
61376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    return 0;
61476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
61576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    adjust_pci_device(pci);
61676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
61776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    nic->ioaddr = pci->ioaddr;
61876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    nic->irqno = 0;
61976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
62076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.nic_name = pci->driver_name;
62176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.dev_id = pci->device;
62276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.ioaddr = nic->ioaddr;
62376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
62476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* read ethernet id */
62576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    for (i = 0; i < 6; ++i)
62676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
62776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        nic->node_addr[i] = inb(mtdx.ioaddr + PAR0 + i);
62876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
62976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
63076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (memcmp(nic->node_addr, "\0\0\0\0\0\0", 6) == 0)
63176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
63276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return 0;
63376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
63476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
63576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    DBG ( "%s: ioaddr %4.4x MAC %s\n", mtdx.nic_name, mtdx.ioaddr, eth_ntoa ( nic->node_addr ) );
63676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
63776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Reset the chip to erase previous misconfiguration. */
63876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl(0x00000001, mtdx.ioaddr + BCR);
63976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
64076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* find the connected MII xcvrs */
64176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
64276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if( mtdx.dev_id != 0x803 )
64376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
64476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        int phy, phy_idx = 0;
64576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
64676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        for (phy = 1; phy < 32 && phy_idx < 1; phy++) {
64776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            int mii_status = mdio_read(nic, phy, 1);
64876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
64976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (mii_status != 0xffff && mii_status != 0x0000) {
65076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.phys[phy_idx] = phy;
65176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
65276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                DBG ( "%s: MII PHY found at address %d, status "
65376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		      "0x%4.4x.\n", mtdx.nic_name, phy, mii_status );
65476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                /* get phy type */
65576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                {
65676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                    unsigned int data;
65776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
65876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                    data = mdio_read(nic, mtdx.phys[phy_idx], 2);
65976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                    if (data == SeeqPHYID0)
66076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                        mtdx.PHYType = SeeqPHY;
66176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                    else if (data == AhdocPHYID0)
66276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                        mtdx.PHYType = AhdocPHY;
66376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                    else if (data == MarvellPHYID0)
66476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                        mtdx.PHYType = MarvellPHY;
66576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                    else if (data == MysonPHYID0)
66676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                        mtdx.PHYType = Myson981;
66776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                    else if (data == LevelOnePHYID0)
66876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                        mtdx.PHYType = LevelOnePHY;
66976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                    else
67076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                        mtdx.PHYType = OtherPHY;
67176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                }
67276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                phy_idx++;
67376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
67476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
67576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
67676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        mtdx.mii_cnt = phy_idx;
67776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (phy_idx == 0) {
67876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            printf("%s: MII PHY not found -- this device may "
67976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                   "not operate correctly.\n", mtdx.nic_name);
68076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
68176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } else {
68276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        mtdx.phys[0] = 32;
68376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* get phy type */
68476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (inl(mtdx.ioaddr + PHYIDENTIFIER) == MysonPHYID ) {
68576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            mtdx.PHYType = MysonPHY;
68676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            DBG ( "MysonPHY\n" );
68776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        } else {
68876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            mtdx.PHYType = OtherPHY;
68976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            DBG ( "OtherPHY\n" );
69076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
69176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
69276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
69376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    getlinkstatus(nic);
69476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if( !mtdx.linkok )
69576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
69676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        printf("No link!!!\n");
69776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return 0;
69876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
69976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
70076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtd_reset( nic );
70176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
70276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* point to NIC specific routines */
70376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    nic->nic_op	= &mtd_operations;
70476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 1;
70576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
70676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
70776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
70876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**************************************************************************/
70976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void set_rx_mode(struct nic *nic __unused)
71076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
71176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u32 mc_filter[2];                       /* Multicast hash filter */
71276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u32 rx_mode;
71376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
71476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Too many to match, or accept all multicasts. */
71576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mc_filter[1] = mc_filter[0] = ~0;
71676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
71776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
71876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl(mc_filter[0], mtdx.ioaddr + MAR0);
71976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl(mc_filter[1], mtdx.ioaddr + MAR1);
72076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
72176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.crvalue = ( mtdx.crvalue & ~RxModeMask ) | rx_mode;
72276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outb( mtdx.crvalue, mtdx.ioaddr + TCRRCR);
72376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
72476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**************************************************************************/
72576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic unsigned int m80x_read_tick(void)
72676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* function: Reads the Timer tick count register which decrements by 2 from  */
72776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*           65536 to 0 every 1/36.414 of a second. Each 2 decrements of the */
72876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*           count represents 838 nsec's.                                    */
72976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* input   : none.                                                           */
73076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* output  : none.                                                           */
73176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
73276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned char tmp;
73376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int value;
73476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
73576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outb((char) 0x06, 0x43); // Command 8254 to latch T0's count
73676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
73776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    // now read the count.
73876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    tmp = (unsigned char) inb(0x40);
73976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    value = ((int) tmp) << 8;
74076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    tmp = (unsigned char) inb(0x40);
74176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    value |= (((int) tmp) & 0xff);
74276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return (value);
74376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
74476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
74576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void m80x_delay(unsigned int interval)
74676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* function: to wait for a specified time.                                   */
74776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* input   : interval ... the specified time.                                */
74876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* output  : none.                                                           */
74976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
75076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned int interval1, interval2, i = 0;
75176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
75276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    interval1 = m80x_read_tick(); // get initial value
75376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    do
75476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
75576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        interval2 = m80x_read_tick();
75676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (interval1 < interval2)
75776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            interval1 += 65536;
75876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        ++i;
75976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } while (((interval1 - interval2) < (u16) interval) && (i < 65535));
76076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
76176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
76276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
76376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic u32 m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad)
76476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
76576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u32 miir;
76676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int i;
76776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned int mask, data;
76876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
76976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* enable MII output */
77076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    miir = (u32) inl(miiport);
77176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    miir &= 0xfffffff0;
77276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
77376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    miir |= MASK_MIIR_MII_WRITE + MASK_MIIR_MII_MDO;
77476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
77576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* send 32 1's preamble */
77676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    for (i = 0; i < 32; i++) {
77776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* low MDC; MDO is already high (miir) */
77876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        miir &= ~MASK_MIIR_MII_MDC;
77976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        outl(miir, miiport);
78076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
78176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* high MDC */
78276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        miir |= MASK_MIIR_MII_MDC;
78376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        outl(miir, miiport);
78476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
78576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
78676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* calculate ST+OP+PHYAD+REGAD+TA */
78776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    data = opcode | (phyad << 7) | (regad << 2);
78876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
78976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* sent out */
79076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mask = 0x8000;
79176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    while (mask) {
79276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* low MDC, prepare MDO */
79376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
79476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (mask & data)
79576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            miir |= MASK_MIIR_MII_MDO;
79676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
79776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        outl(miir, miiport);
79876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* high MDC */
79976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        miir |= MASK_MIIR_MII_MDC;
80076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        outl(miir, miiport);
80176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        m80x_delay(30);
80276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
80376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* next */
80476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        mask >>= 1;
80576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (mask == 0x2 && opcode == OP_READ)
80676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            miir &= ~MASK_MIIR_MII_WRITE;
80776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
80876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return miir;
80976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
81076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
81176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int mdio_read(struct nic *nic __unused, int phyad, int regad)
81276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
81376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    long miiport = mtdx.ioaddr + MANAGEMENT;
81476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u32 miir;
81576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned int mask, data;
81676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
81776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    miir = m80x_send_cmd_to_phy(miiport, OP_READ, phyad, regad);
81876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
81976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* read data */
82076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mask = 0x8000;
82176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    data = 0;
82276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    while (mask)
82376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
82476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* low MDC */
82576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        miir &= ~MASK_MIIR_MII_MDC;
82676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        outl(miir, miiport);
82776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
82876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* read MDI */
82976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        miir = inl(miiport);
83076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (miir & MASK_MIIR_MII_MDI)
83176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            data |= mask;
83276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
83376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* high MDC, and wait */
83476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        miir |= MASK_MIIR_MII_MDC;
83576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        outl(miir, miiport);
83676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        m80x_delay((int) 30);
83776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
83876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* next */
83976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        mask >>= 1;
84076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
84176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
84276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* low MDC */
84376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    miir &= ~MASK_MIIR_MII_MDC;
84476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl(miir, miiport);
84576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
84676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return data & 0xffff;
84776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
84876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
84976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if 0 /* not used */
85076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void mdio_write(struct nic *nic __unused, int phyad, int regad,
85176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		       int data)
85276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
85376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    long miiport = mtdx.ioaddr + MANAGEMENT;
85476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    u32 miir;
85576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned int mask;
85676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
85776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    miir = m80x_send_cmd_to_phy(miiport, OP_WRITE, phyad, regad);
85876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
85976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* write data */
86076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mask = 0x8000;
86176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    while (mask)
86276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
86376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* low MDC, prepare MDO */
86476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
86576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (mask & data)
86676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            miir |= MASK_MIIR_MII_MDO;
86776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        outl(miir, miiport);
86876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
86976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* high MDC */
87076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        miir |= MASK_MIIR_MII_MDC;
87176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        outl(miir, miiport);
87276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
87376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* next */
87476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        mask >>= 1;
87576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
87676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
87776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* low MDC */
87876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    miir &= ~MASK_MIIR_MII_MDC;
87976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    outl(miir, miiport);
88076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
88176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return;
88276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
88376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
88476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
88576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void getlinkstatus(struct nic *nic)
88676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* function: Routine will read MII Status Register to get link status.       */
88776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* input   : dev... pointer to the adapter block.                            */
88876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* output  : none.                                                           */
88976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
89076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned int i, DelayTime = 0x1000;
89176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
89276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mtdx.linkok = 0;
89376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
89476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (mtdx.PHYType == MysonPHY)
89576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
89676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        for (i = 0; i < DelayTime; ++i) {
89776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (inl(mtdx.ioaddr + BMCRSR) & LinkIsUp2) {
89876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.linkok = 1;
89976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                return;
90076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
90176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            // delay
90276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            m80x_delay(100);
90376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
90476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } else
90576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
90676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        for (i = 0; i < DelayTime; ++i) {
90776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (mdio_read(nic, mtdx.phys[0], MII_BMSR) & BMSR_LSTATUS) {
90876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.linkok = 1;
90976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                return;
91076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            }
91176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            // delay
91276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            m80x_delay(100);
91376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
91476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
91576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
91676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
91776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
91876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void getlinktype(struct nic *dev)
91976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
92076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (mtdx.PHYType == MysonPHY)
92176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    { /* 3-in-1 case */
92276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (inl(mtdx.ioaddr + TCRRCR) & FD)
92376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            mtdx.duplexmode = 2; /* full duplex */
92476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        else
92576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            mtdx.duplexmode = 1; /* half duplex */
92676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (inl(mtdx.ioaddr + TCRRCR) & PS10)
92776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            mtdx.line_speed = 1; /* 10M */
92876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        else
92976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            mtdx.line_speed = 2; /* 100M */
93076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } else
93176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    {
93276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (mtdx.PHYType == SeeqPHY) { /* this PHY is SEEQ 80225 */
93376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            unsigned int data;
93476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
93576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            data = mdio_read(dev, mtdx.phys[0], MIIRegister18);
93676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (data & SPD_DET_100)
93776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.line_speed = 2; /* 100M */
93876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
93976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.line_speed = 1; /* 10M */
94076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (data & DPLX_DET_FULL)
94176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.duplexmode = 2; /* full duplex mode */
94276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
94376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.duplexmode = 1; /* half duplex mode */
94476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        } else if (mtdx.PHYType == AhdocPHY) {
94576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            unsigned int data;
94676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
94776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            data = mdio_read(dev, mtdx.phys[0], DiagnosticReg);
94876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (data & Speed_100)
94976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.line_speed = 2; /* 100M */
95076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
95176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.line_speed = 1; /* 10M */
95276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (data & DPLX_FULL)
95376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.duplexmode = 2; /* full duplex mode */
95476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
95576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.duplexmode = 1; /* half duplex mode */
95676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
95776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* 89/6/13 add, (begin) */
95876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        else if (mtdx.PHYType == MarvellPHY) {
95976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            unsigned int data;
96076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
96176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            data = mdio_read(dev, mtdx.phys[0], SpecificReg);
96276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (data & Full_Duplex)
96376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.duplexmode = 2; /* full duplex mode */
96476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
96576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.duplexmode = 1; /* half duplex mode */
96676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            data &= SpeedMask;
96776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (data == Speed_1000M)
96876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.line_speed = 3; /* 1000M */
96976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else if (data == Speed_100M)
97076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.line_speed = 2; /* 100M */
97176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
97276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.line_speed = 1; /* 10M */
97376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
97476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* 89/6/13 add, (end) */
97576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* 89/7/27 add, (begin) */
97676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        else if (mtdx.PHYType == Myson981) {
97776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            unsigned int data;
97876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
97976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            data = mdio_read(dev, mtdx.phys[0], StatusRegister);
98076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
98176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (data & SPEED100)
98276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.line_speed = 2;
98376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
98476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.line_speed = 1;
98576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
98676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (data & FULLMODE)
98776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.duplexmode = 2;
98876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
98976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.duplexmode = 1;
99076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
99176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* 89/7/27 add, (end) */
99276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* 89/12/29 add */
99376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        else if (mtdx.PHYType == LevelOnePHY) {
99476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            unsigned int data;
99576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
99676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            data = mdio_read(dev, mtdx.phys[0], SpecificReg);
99776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (data & LXT1000_Full)
99876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.duplexmode = 2; /* full duplex mode */
99976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
100076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.duplexmode = 1; /* half duplex mode */
100176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            data &= SpeedMask;
100276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            if (data == LXT1000_1000M)
100376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.line_speed = 3; /* 1000M */
100476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else if (data == LXT1000_100M)
100576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.line_speed = 2; /* 100M */
100676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            else
100776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                mtdx.line_speed = 1; /* 10M */
100876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
100976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        // chage crvalue
101076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        // mtdx.crvalue&=(~PS10)&(~FD);
101176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        mtdx.crvalue &= (~PS10) & (~FD) & (~PS1000);
101276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (mtdx.line_speed == 1)
101376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            mtdx.crvalue |= PS10;
101476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        else if (mtdx.line_speed == 3)
101576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            mtdx.crvalue |= PS1000;
101676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (mtdx.duplexmode == 2)
101776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman            mtdx.crvalue |= FD;
101876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
101976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
102076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
102176d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanDRIVER ( "MTD80X", nic_driver, pci_driver, mtd80x_driver,
102276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 mtd_probe, mtd_disable );
1023