15b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* -*- Mode:C; c-basic-offset:4; -*- */
25b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
35b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
45b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  Tulip and clone Etherboot Driver
55b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
65b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  By Marty Connor (mdc@thinguin.org)
75b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  Copyright (C) 2001 Entity Cyber, Inc.
85b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
95b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  This software may be used and distributed according to the terms
105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  of the GNU Public License, incorporated herein by reference.
115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  As of April 2001 this driver should support most tulip cards that
135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  the Linux tulip driver supports because Donald Becker's Linux media
145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  detection code is now included.
155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  Based on Ken Yap's Tulip Etherboot Driver and Donald Becker's
175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  Linux Tulip Driver. Supports N-Way speed auto-configuration on
185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  MX98715, MX98715A and MX98725. Support inexpensive PCI 10/100 cards
195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  based on the Macronix MX987x5 chip, such as the SOHOware Fast
205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  model SFA110A, and the LinkSYS model LNE100TX. The NetGear
215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  model FA310X, based on the LC82C168 chip is supported.
225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  The TRENDnet TE100-PCIA NIC which uses a genuine Intel 21143-PD
235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  chipset is supported. Also, Davicom DM9102's.
245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  Documentation and source code used:
265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  Source for Etherboot driver at
275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  http://etherboot.sourceforge.net/
285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  MX98715A Data Sheet and MX98715A Application Note
295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  on http://www.macronix.com/  (PDF format files)
305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  Source for Linux tulip driver at
315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html
325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  Adapted by Ken Yap from
345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  FreeBSD netboot DEC 21143 driver
355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  Author: David Sharp
365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  date: Nov/98
375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  Some code fragments were taken from verious places, Ken Yap's
395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  etherboot, FreeBSD's if_de.c, and various Linux related files.
405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  DEC's manuals for the 21143 and SROM format were very helpful.
415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  The Linux de driver development page has a number of links to
425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  useful related information.  Have a look at:
435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/tulip-devel.html
445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project*/
455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Revision History                                                  */
485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  11 Apr 2001  mdc     [patch to etherboot 4.7.24]
525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     Major rewrite to include Linux tulip driver media detection
535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     code.  This driver should support a lot more cards now.
545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  16 Jul 2000  mdc     0.75b11
555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     Added support for ADMtek 0985 Centaur-P, a "Comet" tulip clone
565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     which is used on the LinkSYS LNE100TX v4.x cards.  We already
575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     support LNE100TX v2.0 cards, which use a different controller.
585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  04 Jul 2000   jam     ?
595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     Added test of status after receiving a packet from the card.
605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     Also uncommented the tulip_disable routine.  Stray packets
615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     seemed to be causing problems.
625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  27 Apr 2000   njl     ?
635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  29 Feb 2000   mdc     0.75b7
645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     Increased reset delay to 3 seconds because Macronix cards seem to
655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     need more reset time before card comes back to a usable state.
665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  26 Feb 2000   mdc     0.75b6
675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     Added a 1 second delay after initializing the transmitter because
685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     some cards seem to need the time or they drop the first packet
695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     transmitted.
705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  23 Feb 2000   mdc     0.75b5
715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     removed udelay code and used currticks() for more reliable delay
725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     code in reset pause and sanity timeouts.  Added function prototypes
735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     and TX debugging code.
745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  21 Feb 2000   mdc     patch to Etherboot 4.4.3
755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     Incorporated patches from Bob Edwards and Paul Mackerras of
765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     Linuxcare's OZLabs to deal with inefficiencies in tulip_transmit
775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     and udelay.  We now wait for packet transmission to complete
785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     (or sanity timeout).
795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  04 Feb 2000   Robert.Edwards@anu.edu.au patch to Etherboot 4.4.2
805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     patch to tulip.c that implements the automatic selection of the MII
815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     interface on cards using the Intel/DEC 21143 reference design, in
825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     particular, the TRENDnet TE100-PCIA NIC which uses a genuine Intel
835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     21143-PD chipset.
845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  11 Jan 2000   mdc     0.75b4
855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     Added support for NetGear FA310TX card based on the LC82C168
865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     chip.  This should also support Lite-On LC82C168 boards.
875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     Added simple MII support. Re-arranged code to better modularize
885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     initializations.
895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  04 Dec 1999   mdc     0.75b3
905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     Added preliminary support for LNE100TX PCI cards.  Should work for
915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     PNIC2 cards. No MII support, but single interface (RJ45) tulip
925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     cards seem to not care.
935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  03 Dec 1999   mdc     0.75b2
945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     Renamed from mx987x5 to tulip, merged in original tulip init code
955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     from tulip.c to support other tulip compatible cards.
965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  02 Dec 1999   mdc     0.75b1
975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     Released Beta MX987x5 Driver for code review and testing to netboot
985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     and thinguin mailing lists.
995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project*/
1005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
1035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Declarations                                                      */
1045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
1055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "etherboot.h"
1075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "nic.h"
1085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "pci.h"
1095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "cards.h"
1105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* User settable parameters */
1125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#undef   TULIP_DEBUG
1145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#undef   TULIP_DEBUG_WHERE
1155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int tulip_debug = 2;             /* 1 normal messages, 0 quiet .. 7 verbose. */
1165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define TX_TIME_OUT       2*TICKS_PER_SEC
1185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef unsigned char  u8;
1205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef   signed char  s8;
1215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef unsigned short u16;
1225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef   signed short s16;
1235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef unsigned int   u32;
1245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projecttypedef   signed int   s32;
1255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* helpful macros if on a big_endian machine for changing byte order.
1275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   not strictly needed on Intel */
1285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define le16_to_cpu(val) (val)
1295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define cpu_to_le32(val) (val)
1305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define get_unaligned(ptr) (*(ptr))
1315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
1325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define get_u16(ptr) (*(u16 *)(ptr))
1335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define virt_to_bus(x) ((unsigned long)x)
1345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define virt_to_le32desc(addr)  virt_to_bus(addr)
1355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define TULIP_IOTYPE  PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0
1375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define TULIP_SIZE 0x80
1385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* This is a mysterious value that can be written to CSR11 in the 21040 (only)
1405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   to support a pre-NWay full-duplex signaling mechanism using short frames.
1415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   No one knows what it should be, but if left at its default value some
1425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   10base2(!) packets trigger a full-duplex-request interrupt. */
1435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define FULL_DUPLEX_MAGIC       0x6969
1445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic const int csr0 = 0x01A00000 | 0x8000;
1465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*  The possible media types that can be set in options[] are: */
1485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MEDIA_MASK 31
1495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic const char * const medianame[32] = {
1505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    "10baseT", "10base2", "AUI", "100baseTx",
1515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    "10baseT-FDX", "100baseTx-FDX", "100baseT4", "100baseFx",
1525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    "100baseFx-FDX", "MII 10baseT", "MII 10baseT-FDX", "MII",
1535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FDX", "MII 100baseT4",
1545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    "MII 100baseFx-HDX", "MII 100baseFx-FDX", "Home-PNA 1Mbps", "Invalid-19",
1555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
1565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* This much match tulip_tbl[]!  Note 21142 == 21143. */
1585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectenum tulip_chips {
1595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3,
1605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    LC82C168, MX98713, MX98715, MX98725, AX88141, AX88140, PNIC2, COMET,
1615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    COMPEX9881, I21145, XIRCOM
1625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
1635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectenum pci_id_flags_bits {
1655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Set PCI command register bits before calling probe1(). */
1665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
1675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Read and map the single following PCI BAR. */
1685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    PCI_ADDR0=0<<4, PCI_ADDR1=1<<4, PCI_ADDR2=2<<4, PCI_ADDR3=3<<4,
1695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    PCI_ADDR_64BITS=0x100, PCI_NO_ACPI_WAKE=0x200, PCI_NO_MIN_LATENCY=0x400,
1705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    PCI_UNUSED_IRQ=0x800,
1715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
1725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct pci_id_info {
1745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    char *name;
1755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    struct match_info {
1765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        u32 pci, pci_mask, subsystem, subsystem_mask;
1775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        u32 revision, revision_mask;                            /* Only 8 bits. */
1785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    } id;
1795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    enum pci_id_flags_bits pci_flags;
1805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int io_size;                                /* Needed for I/O region check or ioremap(). */
1815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int drv_flags;                              /* Driver use, intended as capability flags. */
1825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
1835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic struct pci_id_info pci_id_tbl[] = {
1855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Digital DC21040 Tulip", { 0x00021011, 0xffffffff, 0, 0, 0, 0 },
1865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 0x80, DC21040 },
1875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Digital DC21041 Tulip", { 0x00141011, 0xffffffff, 0, 0, 0, 0 },
1885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 0x80, DC21041 },
1895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Digital DS21140A Tulip", { 0x00091011, 0xffffffff, 0,0, 0x20,0xf0 },
1905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 0x80, DC21140 },
1915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Digital DS21140 Tulip", { 0x00091011, 0xffffffff, 0, 0, 0, 0 },
1925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 0x80, DC21140 },
1935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Digital DS21143 Tulip", { 0x00191011, 0xffffffff, 0,0, 65,0xff },
1945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, TULIP_SIZE, DC21142 },
1955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Digital DS21142 Tulip", { 0x00191011, 0xffffffff, 0, 0, 0, 0 },
1965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, TULIP_SIZE, DC21142 },
1975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Kingston KNE110tx (PNIC)", { 0x000211AD, 0xffffffff, 0xf0022646, 0xffffffff, 0, 0 },
1985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 256, LC82C168 },
1995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Lite-On 82c168 PNIC", { 0x000211AD, 0xffffffff, 0, 0, 0, 0 },
2005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 256, LC82C168 },
2015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Macronix 98713 PMAC", { 0x051210d9, 0xffffffff, 0, 0, 0, 0 },
2025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 256, MX98713 },
2035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Macronix 98715 PMAC", { 0x053110d9, 0xffffffff, 0, 0, 0, 0 },
2045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 256, MX98715 },
2055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Macronix 98725 PMAC", { 0x053110d9, 0xffffffff, 0, 0, 0, 0 },
2065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 256, MX98725 },
2075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "ASIX AX88141", { 0x1400125B, 0xffffffff, 0,0, 0x10, 0xf0 },
2085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 128, AX88141 },
2095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "ASIX AX88140", { 0x1400125B, 0xffffffff, 0, 0, 0, 0 },
2105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 128, AX88140 },
2115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Lite-On LC82C115 PNIC-II", { 0xc11511AD, 0xffffffff, 0, 0, 0, 0 },
2125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 256, PNIC2 },
2135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "ADMtek AN981 Comet", { 0x09811317, 0xffffffff, 0, 0, 0, 0 },
2145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 256, COMET },
2155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "ADMtek Centaur-P", { 0x09851317, 0xffffffff, 0, 0, 0, 0 },
2165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 256, COMET },
2175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "ADMtek Centaur-C", { 0x19851317, 0xffffffff, 0, 0, 0, 0 },
2185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 256, COMET },
2195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Compex RL100-TX", { 0x988111F6, 0xffffffff, 0, 0, 0, 0 },
2205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 128, COMPEX9881 },
2215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Intel 21145 Tulip", { 0x00398086, 0xffffffff, 0, 0, 0, 0 },
2225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 128, I21145 },
2235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Xircom Tulip clone", { 0x0003115d, 0xffffffff, 0, 0, 0, 0 },
2245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 128, XIRCOM },
2255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Davicom DM9102", { 0x91021282, 0xffffffff, 0, 0, 0, 0 },
2265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 0x80, DC21140 },
2275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Davicom DM9100", { 0x91001282, 0xffffffff, 0, 0, 0, 0 },
2285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 0x80, DC21140 },
2295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Macronix mxic-98715 (EN1217)", { 0x12171113, 0xffffffff, 0, 0, 0, 0 },
2305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      TULIP_IOTYPE, 256, MX98715 },
2315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { 0, { 0, 0, 0, 0, 0, 0 }, 0, 0, 0 },
2325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
2335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectenum tbl_flag {
2355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    HAS_MII=1, HAS_MEDIA_TABLE=2, CSR12_IN_SROM=4, ALWAYS_CHECK_MII=8,
2365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    HAS_PWRDWN=0x10, MC_HASH_ONLY=0x20, /* Hash-only multicast filter. */
2375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    HAS_PNICNWAY=0x80, HAS_NWAY=0x40,   /* Uses internal NWay xcvr. */
2385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    HAS_INTR_MITIGATION=0x100, IS_ASIX=0x200, HAS_8023X=0x400,
2395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
2405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Note: this table must match  enum tulip_chips  above. */
2425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic struct tulip_chip_table {
2435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    char *chip_name;
2445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int flags;
2455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project} tulip_tbl[] = {
2465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Digital DC21040 Tulip", 0},
2475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Digital DC21041 Tulip", HAS_MEDIA_TABLE | HAS_NWAY },
2485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Digital DS21140 Tulip", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM },
2495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Digital DS21143 Tulip", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII
2505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      | HAS_PWRDWN | HAS_NWAY   | HAS_INTR_MITIGATION },
2515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Lite-On 82c168 PNIC", HAS_MII | HAS_PNICNWAY },
2525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Macronix 98713 PMAC", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM },
2535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Macronix 98715 PMAC", HAS_MEDIA_TABLE },
2545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Macronix 98725 PMAC", HAS_MEDIA_TABLE },
2555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "ASIX AX88140", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM
2565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      | MC_HASH_ONLY | IS_ASIX },
2575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "ASIX AX88141", HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY
2585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      | IS_ASIX },
2595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Lite-On PNIC-II", HAS_MII | HAS_NWAY | HAS_8023X },
2605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "ADMtek Comet", MC_HASH_ONLY },
2615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Compex 9881 PMAC",       HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM },
2625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Intel DS21145 Tulip", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII
2635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      | HAS_PWRDWN | HAS_NWAY },
2645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "Xircom tulip work-alike", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII
2655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      | HAS_PWRDWN | HAS_NWAY },
2665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { 0, 0 },
2675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
2685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* A full-duplex map for media types. */
2705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectenum MediaIs {
2715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8,
2725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    MediaIs100=16};
2735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic const char media_cap[32] =
2755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{0,0,0,16,  3,19,16,24,  27,4,7,5, 0,20,23,20, 20,31,0,0, };
2765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic u8 t21040_csr13[] = {2,0x0C,8,4,  4,0,0,0, 0,0,0,0, 4,0,0,0};
2775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* 21041 transceiver register settings: 10-T, 10-2, AUI, 10-T, 10T-FD */
2795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, };
2805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };
2815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
2825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic u16 t21142_csr13[] = { 0x0001, 0x0009, 0x0009, 0x0000, 0x0001, };
2845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, };
2855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
2865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Offsets to the Command and Status Registers, "CSRs".  All accesses
2885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   must be longword instructions and quadword aligned. */
2895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectenum tulip_offsets {
2905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    CSR0=0,     CSR1=0x08,  CSR2=0x10,  CSR3=0x18,  CSR4=0x20,  CSR5=0x28,
2915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    CSR6=0x30,  CSR7=0x38,  CSR8=0x40,  CSR9=0x48, CSR10=0x50, CSR11=0x58,
2925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x80, CSR20=0xA0
2935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
2945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* The bits in the CSR5 status registers, mostly interrupt sources. */
2965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectenum status_bits {
2975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    TimerInt=0x800, TPLnkFail=0x1000, TPLnkPass=0x10,
2985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    NormalIntr=0x10000, AbnormalIntr=0x8000,
2995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    RxJabber=0x200, RxDied=0x100, RxNoBuf=0x80, RxIntr=0x40,
3005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    TxFIFOUnderflow=0x20, TxJabber=0x08, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01,
3015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
3025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectenum desc_status_bits {
3045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    DescOwnded=0x80000000, RxDescFatalErr=0x8000, RxWholePkt=0x0300,
3055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
3065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct medialeaf {
3085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u8 type;
3095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u8 media;
3105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned char *leafdata;
3115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
3125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct mediatable {
3145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u16 defaultmedia;
3155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u8 leafcount, csr12dir;                             /* General purpose pin directions. */
3165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned has_mii:1, has_nonmii:1, has_reset:6;
3175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 csr15dir, csr15val;                             /* 21143 NWay setting. */
3185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    struct medialeaf mleaf[0];
3195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
3205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct mediainfo {
3225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    struct mediainfo *next;
3235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int info_type;
3245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int index;
3255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned char *info;
3265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
3275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* EEPROM Address width definitions */
3295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EEPROM_ADDRLEN 6
3305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EEPROM_SIZE    128              /* 2 << EEPROM_ADDRLEN */
3315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* The EEPROM commands include the alway-set leading bit. */
3335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EE_WRITE_CMD    (5 << addr_len)
3345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EE_READ_CMD     (6 << addr_len)
3355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EE_ERASE_CMD    (7 << addr_len)
3365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* EEPROM_Ctrl bits. */
3385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EE_SHIFT_CLK    0x02    /* EEPROM shift clock. */
3395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EE_CS           0x01    /* EEPROM chip select. */
3405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EE_DATA_WRITE   0x04    /* EEPROM chip data in. */
3415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EE_WRITE_0      0x01
3425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EE_WRITE_1      0x05
3435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EE_DATA_READ    0x08    /* EEPROM chip data out. */
3445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define EE_ENB          (0x4800 | EE_CS)
3455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Delay between EEPROM clock transitions.  Even at 33Mhz current PCI
3475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   implementations don't overrun the EEPROM clock.  We add a bus
3485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   turn-around to insure that this remains true.  */
3495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define eeprom_delay()  inl(ee_addr)
3505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Size of transmit and receive buffers */
3525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define BUFLEN 1536
3535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Ring-wrap flag in length field, use for last ring entry.
3555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   0x01000000 means chain on buffer2 address,
3565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   0x02000000 means use the ring start address in CSR2/3.
3575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   Note: Some work-alike chips do not function correctly in chained mode.
3585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   The ASIX chip works only in chained mode.
3595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   Thus we indicate ring mode, but always write the 'next' field for
3605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   chained mode as well. */
3615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DESC_RING_WRAP 0x02000000
3625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* transmit and receive descriptor format */
3645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct tulip_rx_desc {
3655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    volatile u32 status;
3665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 length;
3675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 buffer1, buffer2;
3685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
3695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct tulip_tx_desc {
3715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    volatile u32 status;
3725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 length;
3735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 buffer1, buffer2;
3745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
3755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
3775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Global Storage                                                    */
3785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
3795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic u32 ioaddr;
3815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Note: transmit and receive buffers must be longword aligned and
3835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   longword divisable */
3845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define TX_RING_SIZE	2
3865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic struct tulip_tx_desc tx_ring[TX_RING_SIZE] __attribute__ ((aligned(4)));
3875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef USE_LOWMEM_BUFFER
3895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define txb ((char *)0x10000 - BUFLEN)
3905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#else
3915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned char txb[BUFLEN] __attribute__ ((aligned(4)));
3925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
3935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define RX_RING_SIZE	4
3955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic struct tulip_rx_desc rx_ring[RX_RING_SIZE] __attribute__ ((aligned(4)));
3965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef USE_LOWMEM_BUFFER
3985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define rxb ((char *)0x10000 - RX_RING_SIZE * BUFLEN - BUFLEN)
3995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#else
4005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned char rxb[RX_RING_SIZE * BUFLEN] __attribute__ ((aligned(4)));
4015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
4025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic struct tulip_private {
4045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int cur_rx;
4055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int chip_id;                        /* index into tulip_tbl[]  */
4065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int pci_id_idx;                     /* index into pci_id_tbl[] */
4075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int revision;
4085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int flags;
4095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned short vendor_id;           /* PCI card vendor code */
4105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned short dev_id;              /* PCI card device code */
4115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned char ehdr[ETH_HLEN];       /* buffer for ethernet header */
4125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    const char *nic_name;
4135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned int csr0, csr6;            /* Current CSR0, CSR6 settings. */
4145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned int if_port;
4155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned int full_duplex;         /* Full-duplex operation requested. */
4165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned int full_duplex_lock;
4175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned int medialock;           /* Do not sense media type. */
4185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned int mediasense;          /* Media sensing in progress. */
4195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned int nway, nwayset;     /* 21143 internal NWay. */
4205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned int default_port;
4215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned char eeprom[EEPROM_SIZE];  /* Serial EEPROM contents. */
4225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u8 media_table_storage[(sizeof(struct mediatable) + 32*sizeof(struct medialeaf))];
4235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u16 sym_advertise, mii_advertise;   /* NWay to-advertise. */
4245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    struct mediatable *mtable;
4255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u16 lpar;                           /* 21143 Link partner ability. */
4265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u16 advertising[4];                 /* MII advertise, from SROM table. */
4275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    signed char phys[4], mii_cnt;       /* MII device addresses. */
4285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int cur_index;                      /* Current media index. */
4295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int saved_if_port;
4305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project} tpx;
4315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic struct tulip_private *tp;
4335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Known cards that have old-style EEPROMs.
4355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   Writing this table is described at
4365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   http://cesdis.gsfc.nasa.gov/linux/drivers/tulip-drivers/tulip-media.html */
4375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic struct fixups {
4385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    char *name;
4395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned char addr0, addr1, addr2;
4405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u16 newtable[32];                           /* Max length below. */
4415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project} eeprom_fixups[] = {
4425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
4435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                            0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
4445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f,
4455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                 0x0000, 0x009E, /* 10baseT */
4465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                 0x0004, 0x009E, /* 10baseT-FD */
4475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                 0x0903, 0x006D, /* 100baseTx */
4485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                 0x0905, 0x006D, /* 100baseTx-FD */ }},
4495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x063f,
4505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                   0x0107, 0x8021, /* 100baseFx */
4515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                   0x0108, 0x8021, /* 100baseFx-FD */
4525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                   0x0100, 0x009E, /* 10baseT */
4535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                   0x0104, 0x009E, /* 10baseT-FD */
4545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                   0x0103, 0x006D, /* 100baseTx */
4555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                   0x0105, 0x006D, /* 100baseTx-FD */ }},
4565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0513,
4575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                     0x1001, 0x009E, /* 10base2, CSR12 0x10*/
4585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                     0x0000, 0x009E, /* 10baseT */
4595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                     0x0004, 0x009E, /* 10baseT-FD */
4605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                     0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */
4615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                     0x0305, 0x006D, /* 100baseTx-FD CSR12 0x03 */}},
4625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x051F,
4635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                    0x1B01, 0x0000, /* 10base2,   CSR12 0x1B */
4645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                    0x0B00, 0x009E, /* 10baseT,   CSR12 0x0B */
4655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                    0x0B04, 0x009E, /* 10baseT-FD,CSR12 0x0B */
4665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                    0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */
4675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                    0x1B05, 0x006D, /* 100baseTx-FD CSR12 0x1B */
4685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }},
4695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {0, 0, 0, 0, {}}};
4705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic const char * block_name[] = {"21140 non-MII", "21140 MII PHY",
4725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                    "21142 Serial PHY", "21142 MII PHY", "21143 SYM PHY", "21143 reset method"};
4735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
4765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Function Prototypes                                               */
4775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
4785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int mdio_read(struct nic *nic, int phy_id, int location);
4795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void mdio_write(struct nic *nic, int phy_id, int location, int value);
4805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int read_eeprom(unsigned long ioaddr, int location, int addr_len);
4815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void parse_eeprom(struct nic *nic);
4825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct nic *tulip_probe(struct nic *nic, unsigned short *io_addrs,
4835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                        struct pci_device *pci);
4845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void tulip_init_ring(struct nic *nic);
4855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void tulip_reset(struct nic *nic);
4865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void tulip_transmit(struct nic *nic, const char *d, unsigned int t,
4875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                           unsigned int s, const char *p);
4885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int tulip_poll(struct nic *nic);
4895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void tulip_disable(struct nic *nic);
4905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void nway_start(struct nic *nic);
4915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void pnic_do_nway(struct nic *nic);
4925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void select_media(struct nic *nic, int startup);
4935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void init_media(struct nic *nic);
4945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void start_link(struct nic *nic);
4955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int tulip_check_duplex(struct nic *nic);
4965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void tulip_wait(unsigned int nticks);
4985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
5005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void whereami(const char *str);
5015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
5025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
5045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void tulip_more(void);
5055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
5065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
5095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Utility Routines                                                  */
5105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
5115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
5135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void whereami (const char *str)
5145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
5155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    printf("%s: %s\n", tp->nic_name, str);
5165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* sleep(2); */
5175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
5185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
5195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef  TULIP_DEBUG
5215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void tulip_more(void)
5225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
5235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    printf("\n\n-- more --");
5245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    while (!iskey())
5255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* wait */;
5265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    getchar();
5275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    printf("\n\n");
5285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
5295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* TULIP_DEBUG */
5305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void tulip_wait(unsigned int nticks)
5325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
5335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned int to = currticks() + nticks;
5345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    while (currticks() < to)
5355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* wait */ ;
5365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
5375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
5405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Media Descriptor Code                                             */
5415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
5425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* MII transceiver control section.
5445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   Read and write the MII registers using software-generated serial
5455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   MDIO protocol.  See the MII specifications or DP83840A data sheet
5465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   for details. */
5475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
5495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   met by back-to-back PCI I/O cycles, but we insert a delay to avoid
5505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   "overclocking" issues or future 66Mhz PCI. */
5515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define mdio_delay() inl(mdio_addr)
5525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Read and write the MII registers using software-generated serial
5545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   MDIO protocol.  It is just different enough from the EEPROM protocol
5555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   to not share code.  The maxium data clock rate is 2.5 Mhz. */
5565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MDIO_SHIFT_CLK  0x10000
5575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MDIO_DATA_WRITE0 0x00000
5585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MDIO_DATA_WRITE1 0x20000
5595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MDIO_ENB                0x00000         /* Ignore the 0x02000 databook setting. */
5605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MDIO_ENB_IN             0x40000
5615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MDIO_DATA_READ  0x80000
5625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* MII transceiver control section.
5645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   Read and write the MII registers using software-generated serial
5655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   MDIO protocol.  See the MII specifications or DP83840A data sheet
5665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   for details. */
5675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint mdio_read(struct nic *nic, int phy_id, int location)
5695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
5705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
5715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
5725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int retval = 0;
5735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    long mdio_addr = ioaddr + CSR9;
5745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
5765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("mdio_read\n");
5775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
5785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->chip_id == LC82C168) {
5805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int i = 1000;
5815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);
5825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	inl(ioaddr + 0xA0);
5835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	inl(ioaddr + 0xA0);
5845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	while (--i > 0)
5855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))
5865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return retval & 0xffff;
5875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	return 0xffff;
5885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
5895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->chip_id == COMET) {
5915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (phy_id == 1) {
5925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    if (location < 7)
5935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return inl(ioaddr + 0xB4 + (location<<2));
5945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    else if (location == 17)
5955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return inl(ioaddr + 0xD0);
5965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    else if (location >= 29 && location <= 31)
5975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return inl(ioaddr + 0xD4 + ((location-29)<<2));
5985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	return 0xffff;
6005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
6015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Establish sync by sending at least 32 logic ones. */
6035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 32; i >= 0; i--) {
6045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
6055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	mdio_delay();
6065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
6075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	mdio_delay();
6085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
6095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Shift the read command bits out. */
6105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 15; i >= 0; i--) {
6115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
6125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(MDIO_ENB | dataval, mdio_addr);
6145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	mdio_delay();
6155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
6165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	mdio_delay();
6175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
6185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Read the two transition, 16 data, and wire-idle bits. */
6195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 19; i > 0; i--) {
6205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(MDIO_ENB_IN, mdio_addr);
6215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	mdio_delay();
6225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
6235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
6245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	mdio_delay();
6255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
6265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return (retval>>1) & 0xffff;
6275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
6285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectvoid mdio_write(struct nic *nic, int phy_id, int location, int value)
6305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
6315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
6325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
6335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    long mdio_addr = ioaddr + CSR9;
6345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
6365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("mdio_write\n");
6375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
6385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->chip_id == LC82C168) {
6405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int i = 1000;
6415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(cmd, ioaddr + 0xA0);
6425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	do
6435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    if ( ! (inl(ioaddr + 0xA0) & 0x80000000))
6445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		break;
6455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	while (--i > 0);
6465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	return;
6475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
6485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->chip_id == COMET) {
6505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (phy_id != 1)
6515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    return;
6525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (location < 7)
6535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    outl(value, ioaddr + 0xB4 + (location<<2));
6545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else if (location == 17)
6555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    outl(value, ioaddr + 0xD0);
6565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else if (location >= 29 && location <= 31)
6575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    outl(value, ioaddr + 0xD4 + ((location-29)<<2));
6585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	return;
6595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
6605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Establish sync by sending 32 logic ones. */
6625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 32; i >= 0; i--) {
6635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
6645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	mdio_delay();
6655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
6665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	mdio_delay();
6675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
6685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Shift the command bits out. */
6695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 31; i >= 0; i--) {
6705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
6715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(MDIO_ENB | dataval, mdio_addr);
6725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	mdio_delay();
6735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
6745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	mdio_delay();
6755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
6765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Clear out extra bits. */
6775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 2; i > 0; i--) {
6785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(MDIO_ENB_IN, mdio_addr);
6795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	mdio_delay();
6805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
6815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	mdio_delay();
6825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
6835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
6845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
6875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* EEPROM Reading Code                                               */
6885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
6895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* EEPROM routines adapted from the Linux Tulip Code */
6905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Reading a serial EEPROM is a "bit" grungy, but we work our way
6915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   through:->.
6925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project*/
6935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int read_eeprom(unsigned long ioaddr, int location, int addr_len)
6945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
6955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
6965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned short retval = 0;
6975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    long ee_addr = ioaddr + CSR9;
6985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int read_cmd = location | EE_READ_CMD;
6995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
7015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("read_eeprom\n");
7025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
7035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(EE_ENB & ~EE_CS, ee_addr);
7055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(EE_ENB, ee_addr);
7065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Shift the read command bits out. */
7085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 4 + addr_len; i >= 0; i--) {
7095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
7105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(EE_ENB | dataval, ee_addr);
7115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        eeprom_delay();
7125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
7135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        eeprom_delay();
7145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
7155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(EE_ENB, ee_addr);
7165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 16; i > 0; i--) {
7185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
7195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        eeprom_delay();
7205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
7215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(EE_ENB, ee_addr);
7225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        eeprom_delay();
7235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
7245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Terminate the EEPROM access. */
7265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(EE_ENB & ~EE_CS, ee_addr);
7275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return retval;
7285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
7295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
7325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* EEPROM Parsing Code                                               */
7335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
7345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void parse_eeprom(struct nic *nic)
7355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
7365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned char *p, *ee_data = tp->eeprom;
7375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int new_advertise = 0;
7385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
7395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
7415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("parse_eeprom\n");
7425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
7435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->mtable = 0;
7455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Detect an old-style (SA only) EEPROM layout:
7465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       memcmp(ee_data, ee_data+16, 8). */
7475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 0; i < 8; i ++)
7485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (ee_data[i] != ee_data[16+i])
7495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            break;
7505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (i >= 8) {
7515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* Do a fix-up based on the vendor half of the station address. */
7525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (i = 0; eeprom_fixups[i].name; i++) {
7535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (nic->node_addr[0] == eeprom_fixups[i].addr0
7545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                &&  nic->node_addr[1] == eeprom_fixups[i].addr1
7555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                &&  nic->node_addr[2] == eeprom_fixups[i].addr2) {
7565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if (nic->node_addr[2] == 0xE8  &&  ee_data[0x1a] == 0x55)
7575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    i++;                /* An Accton EN1207, not an outlaw Maxtech. */
7585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                memcpy(ee_data + 26, eeprom_fixups[i].newtable,
7595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                       sizeof(eeprom_fixups[i].newtable));
7605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
7615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf("%s: Old format EEPROM on '%s' board.\n%s: Using substitute media control info.\n",
7625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                       tp->nic_name, eeprom_fixups[i].name, tp->nic_name);
7635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
7645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                break;
7655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            }
7665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
7675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
7685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
7695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("%s: Old style EEPROM with no media selection information.\n",
7705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   tp->nic_name);
7715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
7725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            return;
7735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
7745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
7755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (ee_data[19] > 1) {
7775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
7785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("%s:  Multiport cards (%d ports) may not work correctly.\n",
7795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project               tp->nic_name, ee_data[19]);
7805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
7815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
7825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    p = (void *)ee_data + ee_data[27];
7845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (ee_data[27] == 0) {             /* No valid media table. */
7865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
7875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tulip_debug > 1) {
7885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("%s:  No Valid Media Table. ee_data[27] = %hhX\n",
7895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   tp->nic_name, ee_data[27]);
7905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
7915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
7925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    } else if (tp->chip_id == DC21041) {
7935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        int media = get_u16(p);
7945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        int count = p[2];
7955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        p += 3;
7965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("%s: 21041 Media table, default media %hX (%s).\n",
7985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project               tp->nic_name, media,
7995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project               media & 0x0800 ? "Autosense" : medianame[media & 15]);
8005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (i = 0; i < count; i++) {
8015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            unsigned char media_block = *p++;
8025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            int media_code = media_block & MEDIA_MASK;
8035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (media_block & 0x40)
8045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                p += 6;
8055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            switch(media_code) {
8065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            case 0: new_advertise |= 0x0020; break;
8075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            case 4: new_advertise |= 0x0040; break;
8085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            }
8095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("%s:  21041 media #%d, %s.\n",
8105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   tp->nic_name, media_code, medianame[media_code]);
8115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
8125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    } else {
8135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        unsigned char csr12dir = 0;
8145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        int count;
8155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        struct mediatable *mtable;
8165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        u16 media = get_u16(p);
8175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        p += 2;
8195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tp->flags & CSR12_IN_SROM)
8205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            csr12dir = *p++;
8215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        count = *p++;
8225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->mtable = mtable = (struct mediatable *)&tp->media_table_storage[0];
8245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        mtable->defaultmedia = media;
8265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        mtable->leafcount = count;
8275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        mtable->csr12dir = csr12dir;
8285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
8295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        mtable->csr15dir = mtable->csr15val = 0;
8305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("%s:  EEPROM default media type %s.\n", tp->nic_name,
8325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project               media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]);
8335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (i = 0; i < count; i++) {
8355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            struct medialeaf *leaf = &mtable->mleaf[i];
8365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
8385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                leaf->type = 0;
8395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                leaf->media = p[0] & 0x3f;
8405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                leaf->leafdata = p;
8415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if ((p[2] & 0x61) == 0x01)      /* Bogus, but Znyx boards do it. */
8425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    mtable->has_mii = 1;
8435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                p += 4;
8445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            } else {
8455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                switch(leaf->type = p[1]) {
8465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                case 5:
8475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    mtable->has_reset = i;
8485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    leaf->media = p[2] & 0x0f;
8495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    break;
8505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                case 1: case 3:
8515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    mtable->has_mii = 1;
8525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    leaf->media = 11;
8535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    break;
8545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                case 2:
8555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    if ((p[2] & 0x3f) == 0) {
8565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                        u32 base15 = (p[2] & 0x40) ? get_u16(p + 7) : 0x0008;
8575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                        u16 *p1 = (u16 *)(p + (p[2] & 0x40 ? 9 : 3));
8585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                        mtable->csr15dir = (get_unaligned(p1 + 0)<<16) + base15;
8595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                        mtable->csr15val = (get_unaligned(p1 + 1)<<16) + base15;
8605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    }
8615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    /* Fall through. */
8625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                case 0: case 4:
8635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    mtable->has_nonmii = 1;
8645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    leaf->media = p[2] & MEDIA_MASK;
8655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    switch (leaf->media) {
8665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    case 0: new_advertise |= 0x0020; break;
8675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    case 4: new_advertise |= 0x0040; break;
8685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    case 3: new_advertise |= 0x0080; break;
8695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    case 5: new_advertise |= 0x0100; break;
8705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    case 6: new_advertise |= 0x0200; break;
8715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    }
8725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    break;
8735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                default:
8745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    leaf->media = 19;
8755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                }
8765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                leaf->leafdata = p + 2;
8775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                p += (p[0] & 0x3f) + 1;
8785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            }
8795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
8805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (tulip_debug > 1  &&  leaf->media == 11) {
8815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                unsigned char *bp = leaf->leafdata;
8825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf("%s:  MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %hhX %hhX.\n",
8835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                       tp->nic_name, bp[0], bp[1], bp[2 + bp[1]*2],
8845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                       bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);
8855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            }
8865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
8875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("%s:  Index #%d - Media %s (#%d) described "
8885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   "by a %s (%d) block.\n",
8895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   tp->nic_name, i, medianame[leaf->media], leaf->media,
8905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   leaf->type < 6 ? block_name[leaf->type] : "UNKNOWN",
8915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   leaf->type);
8925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
8935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (new_advertise)
8945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->sym_advertise = new_advertise;
8955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
8965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
8975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
9005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* tulip_init_ring - setup the tx and rx descriptors                */
9015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
9025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void tulip_init_ring(struct nic *nic)
9035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
9045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
9055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
9075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("tulip_init_ring\n");
9085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
9095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->cur_rx = 0;
9115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 0; i < RX_RING_SIZE; i++) {
9135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	rx_ring[i].status  = cpu_to_le32(0x80000000);
9145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	rx_ring[i].length  = cpu_to_le32(BUFLEN);
9155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	rx_ring[i].buffer1 = virt_to_le32desc(&rxb[i * BUFLEN]);
9165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	rx_ring[i].buffer2 = virt_to_le32desc(&rx_ring[i+1]);
9175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
9185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Mark the last entry as wrapping the ring. */
9195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    rx_ring[i-1].length    = cpu_to_le32(DESC_RING_WRAP | BUFLEN);
9205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    rx_ring[i-1].buffer2   = virt_to_le32desc(&rx_ring[0]);
9215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* We only use 1 transmit buffer, but we use 2 descriptors so
9235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       transmit engines have somewhere to point to if they feel the need */
9245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tx_ring[0].status  = 0x00000000;
9265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tx_ring[0].buffer1 = virt_to_le32desc(&txb[0]);
9275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tx_ring[0].buffer2 = virt_to_le32desc(&tx_ring[1]);
9285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* this descriptor should never get used, since it will never be owned
9305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       by the machine (status will always == 0) */
9315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tx_ring[1].status  = 0x00000000;
9325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tx_ring[1].buffer1 = virt_to_le32desc(&txb[0]);
9335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tx_ring[1].buffer2 = virt_to_le32desc(&tx_ring[0]);
9345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Mark the last entry as wrapping the ring, though this should never happen */
9365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tx_ring[1].length  = cpu_to_le32(DESC_RING_WRAP | BUFLEN);
9375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
9385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
9405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* eth_reset - Reset adapter                                         */
9415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
9425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void tulip_reset(struct nic *nic)
9435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
9445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
9455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned long to;
9465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 addr_low, addr_high;
9475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
9495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("tulip_reset\n");
9505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
9515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Stop Tx and RX */
9535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
9545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* On some chip revs we must set the MII/SYM port before the reset!? */
9565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->mii_cnt  ||  (tp->mtable  &&  tp->mtable->has_mii)) {
9575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(0x814C0000, ioaddr + CSR6);
9585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
9595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
9615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(0x00000001, ioaddr + CSR0);
9625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tulip_wait(1);
9635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* turn off reset and set cache align=16lword, burst=unlimit */
9655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(tp->csr0, ioaddr + CSR0);
9665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /*  Wait the specified 50 PCI cycles after a reset */
9685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tulip_wait(1);
9695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* set up transmit and receive descriptors */
9715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tulip_init_ring(nic);
9725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->chip_id == PNIC2) {
9745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        u32 addr_high = (nic->node_addr[1]<<8) + (nic->node_addr[0]<<0);
9755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* This address setting does not appear to impact chip operation?? */
9765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl((nic->node_addr[5]<<8) + nic->node_addr[4] +
9775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project             (nic->node_addr[3]<<24) + (nic->node_addr[2]<<16),
9785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project             ioaddr + 0xB0);
9795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(addr_high + (addr_high<<16), ioaddr + 0xB8);
9805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
9815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* MC_HASH_ONLY boards don't support setup packets */
9835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->flags & MC_HASH_ONLY) {
9845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        u32 addr_low = cpu_to_le32(get_unaligned((u32 *)nic->node_addr));
9855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(nic->node_addr+4)));
9865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* clear multicast hash filters and setup MAC address filters */
9885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (tp->flags & IS_ASIX) {
9895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0, ioaddr + CSR13);
9905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(addr_low,  ioaddr + CSR14);
9915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(1, ioaddr + CSR13);
9925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(addr_high, ioaddr + CSR14);
9935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    outl(2, ioaddr + CSR13);
9945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    outl(0, ioaddr + CSR14);
9955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    outl(3, ioaddr + CSR13);
9965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    outl(0, ioaddr + CSR14);
9975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	} else if (tp->chip_id == COMET) {
9985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(addr_low,  ioaddr + 0xA4);
9995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(addr_high, ioaddr + 0xA8);
10005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0, ioaddr + 0xAC);
10015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0, ioaddr + 0xB0);
10025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
10035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    } else {
10045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* for other boards we send a setup packet to initialize
10055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   the filters */
10065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	u32 tx_flags = 0x08000000 | 192;
10075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* construct perfect filter frame with mac address as first match
10095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   and broadcast address for all others */
10105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (i=0; i<192; i++)
10115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    txb[i] = 0xFF;
10125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	txb[0] = nic->node_addr[0];
10135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	txb[1] = nic->node_addr[1];
10145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	txb[4] = nic->node_addr[2];
10155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	txb[5] = nic->node_addr[3];
10165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	txb[8] = nic->node_addr[4];
10175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	txb[9] = nic->node_addr[5];
10185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	tx_ring[0].length  = cpu_to_le32(tx_flags);
10205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	tx_ring[0].buffer1 = virt_to_le32desc(&txb[0]);
10215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	tx_ring[0].status  = cpu_to_le32(0x80000000);
10225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
10235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Point to rx and tx descriptors */
10255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl((unsigned long)&rx_ring[0], ioaddr + CSR3);
10265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl((unsigned long)&tx_ring[0], ioaddr + CSR4);
10275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    init_media(nic);
10295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* set the chip's operating mode (but don't turn on xmit and recv yet) */
10315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl((tp->csr6 & ~0x00002002), ioaddr + CSR6);
10325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* send setup packet for cards that support it */
10345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (!(tp->flags & MC_HASH_ONLY)) {
10355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* enable transmit  wait for completion */
10365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(tp->csr6 | 0x00002000, ioaddr + CSR6);
10375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* immediate transmit demand */
10385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outl(0, ioaddr + CSR1);
10395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	to = currticks() + TX_TIME_OUT;
10415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	while ((tx_ring[0].status & 0x80000000) && (currticks() < to))
10425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    /* wait */ ;
10435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (currticks() >= to) {
10455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    printf ("%s: TX Setup Timeout.\n", tp->nic_name);
10465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
10475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
10485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->chip_id == LC82C168)
10505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	tulip_check_duplex(nic);
10515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* enable transmit and receive */
10535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(tp->csr6 | 0x00002002, ioaddr + CSR6);
10545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
10555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
10585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* eth_transmit - Transmit a frame                                   */
10595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
10605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void tulip_transmit(struct nic *nic, const char *d, unsigned int t,
10615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                           unsigned int s, const char *p)
10625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
10635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u16 nstype;
10645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 to;
10655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 csr6 = inl(ioaddr + CSR6);
10665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
10685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("tulip_transmit\n");
10695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
10705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Disable Tx */
10725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(csr6 & ~0x00002000, ioaddr + CSR6);
10735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    memcpy(txb, d, ETH_ALEN);
10755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
10765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    nstype = htons((u16) t);
10775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    memcpy(txb + 2 * ETH_ALEN, (u8 *)&nstype, 2);
10785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    memcpy(txb + ETH_HLEN, p, s);
10795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    s += ETH_HLEN;
10815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    s &= 0x0FFF;
10825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* pad to minimum packet size */
10845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    while (s < ETH_ZLEN)
10855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        txb[s++] = '\0';
10865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
10885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tulip_debug > 1)
10895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	printf("%s: sending %d bytes ethtype %hX\n", tp->nic_name, s, t);
10905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
10915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* setup the transmit descriptor */
10935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* 0x60000000 = no interrupt on completion */
10945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tx_ring[0].length = cpu_to_le32(0x60000000 | s);
10955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tx_ring[0].status = cpu_to_le32(0x80000000);
10965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Point to transmit descriptor */
10985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl((u32)&tx_ring[0], ioaddr + CSR4);
10995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Enable Tx */
11015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(csr6 | 0x00002000, ioaddr + CSR6);
11025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* immediate transmit demand */
11035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(0, ioaddr + CSR1);
11045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    to = currticks() + TX_TIME_OUT;
11065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    while ((tx_ring[0].status & 0x80000000) && (currticks() < to))
11075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* wait */ ;
11085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (currticks() >= to) {
11105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf ("TX Timeout!\n");
11115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
11125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Disable Tx */
11145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(csr6 & ~0x00002000, ioaddr + CSR6);
11155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
11165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
11185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* eth_poll - Wait for a frame                                       */
11195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
11205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int tulip_poll(struct nic *nic)
11215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
11225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
11245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("tulip_poll\n");
11255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
11265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* no packet waiting. packet still owned by NIC */
11285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (rx_ring[tp->cur_rx].status & 0x80000000)
11295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        return 0;
11305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
11325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("tulip_poll got one\n");
11335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
11345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    nic->packetlen = (rx_ring[tp->cur_rx].status & 0x3FFF0000) >> 16;
11365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* if we get a corrupted packet. throw it away and move on */
11385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (rx_ring[tp->cur_rx].status & 0x00008000) {
11395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* return the descriptor and buffer to receive ring */
11405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        rx_ring[tp->cur_rx].status = 0x80000000;
11415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	tp->cur_rx = (++tp->cur_rx) % RX_RING_SIZE;
11425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        return 0;
11435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
11445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* copy packet to working buffer */
11465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    memcpy(nic->packet, rxb + tp->cur_rx * BUFLEN, nic->packetlen);
11475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* return the descriptor and buffer to receive ring */
11495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    rx_ring[tp->cur_rx].status = 0x80000000;
11505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->cur_rx = (++tp->cur_rx) % RX_RING_SIZE;
11515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return 1;
11535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
11545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
11565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* eth_disable - Disable the interface                               */
11575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
11585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void tulip_disable(struct nic *nic)
11595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
11605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
11625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("tulip_disable\n");
11635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
11645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* disable interrupts */
11665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(0x00000000, ioaddr + CSR7);
11675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Stop the chip's Tx and Rx processes. */
11695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
11705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Clear the missed-packet counter. */
11725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    (volatile unsigned long)inl(ioaddr + CSR8);
11735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
11745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
11765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* eth_probe - Look for an adapter                                   */
11775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*********************************************************************/
11785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct nic *tulip_probe(struct nic *nic, unsigned short *io_addrs,
11795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                        struct pci_device *pci)
11805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
11815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 i, l1, l2;
11825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u8  chip_rev;
11835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u8 ee_data[EEPROM_SIZE];
11845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    unsigned short sum;
11855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int chip_idx;
11865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    static unsigned char last_phys_addr[ETH_ALEN] = {0x00, 'L', 'i', 'n', 'u', 'x'};
11875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (io_addrs == 0 || *io_addrs == 0)
11895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        return 0;
11905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    ioaddr         = *io_addrs;
11925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* point to private storage */
11945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp = &tpx;
11955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
11965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->vendor_id  = pci->vendor;
11975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->dev_id     = pci->dev_id;
11985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->nic_name   = pci->name;
11995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->if_port = 0;
12015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->default_port = 0;
12025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    adjust_pci_device(pci);
12045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* disable interrupts */
12065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(0x00000000, ioaddr + CSR7);
12075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Stop the chip's Tx and Rx processes. */
12095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
12105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Clear the missed-packet counter. */
12125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    (volatile unsigned long)inl(ioaddr + CSR8);
12135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    printf("\n");                /* so we start on a fresh line */
12155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
12165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("tulip_probe\n");
12175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
12185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
12205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tulip_debug > 1)
12215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	printf ("%s: Looking for Tulip Chip: Vendor=%hX  Device=%hX\n", tp->nic_name,
12225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		tp->vendor_id, tp->dev_id);
12235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
12245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Figure out which chip we're dealing with */
12265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    i = 0;
12275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    chip_idx = -1;
12285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    while (pci_id_tbl[i].name) {
12305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if ( (((u32) tp->dev_id << 16) | tp->vendor_id) ==
12315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project             (pci_id_tbl[i].id.pci & pci_id_tbl[i].id.pci_mask) ) {
12325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            chip_idx = pci_id_tbl[i].drv_flags;
12335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            break;
12345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
12355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        i++;
12365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
12375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (chip_idx == -1) {
12395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf ("%s: Unknown Tulip Chip: Vendor=%hX  Device=%hX\n", tp->nic_name,
12405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                tp->vendor_id, tp->dev_id);
12415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        return 0;
12425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
12435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->pci_id_idx = i;
12455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->flags = tulip_tbl[chip_idx].flags;
12465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
12485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tulip_debug > 1) {
12495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	printf ("%s: tp->pci_id_idx == %d,  name == %s\n", tp->nic_name,
12505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		tp->pci_id_idx, pci_id_tbl[tp->pci_id_idx].name);
12515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	printf ("%s: chip_idx == %d, name == %s\n", tp->nic_name, chip_idx,
12525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		tulip_tbl[chip_idx].chip_name);
12535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
12545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
12555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Bring the 21041/21143 out of sleep mode.
12575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       Caution: Snooze mode does not work with some boards! */
12585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->flags & HAS_PWRDWN)
12595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        pcibios_write_config_dword(pci->bus, pci->devfn, 0x40, 0x00000000);
12605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (inl(ioaddr + CSR5) == 0xFFFFFFFF) {
12625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("%s: The Tulip chip at %X is not functioning.\n",
12635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project               tp->nic_name, ioaddr);
12645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        return 0;
12655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
12665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    pcibios_read_config_byte(pci->bus, pci->devfn, PCI_REVISION, &chip_rev);
12685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    printf("%s: [chip: %s] rev %d at %hX\n", tp->nic_name,
12705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project           tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr);
12715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    printf("%s: Vendor=%hX  Device=%hX", tp->nic_name, tp->vendor_id, tp->dev_id);
12725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (chip_idx == DC21041  &&  inl(ioaddr + CSR9) & 0x8000) {
12745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf(" 21040 compatible mode.");
12755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        chip_idx = DC21040;
12765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
12775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    printf("\n");
12795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
12805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* The SROM/EEPROM interface varies dramatically. */
12815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    sum = 0;
12825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (chip_idx == DC21040) {
12835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0, ioaddr + CSR9);         /* Reset the pointer with a dummy write. */
12845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (i = 0; i < ETH_ALEN; i++) {
12855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            int value, boguscnt = 100000;
12865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            do
12875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                value = inl(ioaddr + CSR9);
12885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            while (value < 0  && --boguscnt > 0);
12895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            nic->node_addr[i] = value;
12905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            sum += value & 0xff;
12915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
12925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    } else if (chip_idx == LC82C168) {
12935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (i = 0; i < 3; i++) {
12945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            int value, boguscnt = 100000;
12955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x600 | i, ioaddr + 0x98);
12965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            do
12975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                value = inl(ioaddr + CSR9);
12985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            while (value < 0  && --boguscnt > 0);
12995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            put_unaligned(le16_to_cpu(value), ((u16*)nic->node_addr) + i);
13005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            sum += value & 0xffff;
13015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
13025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    } else if (chip_idx == COMET) {
13035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* No need to read the EEPROM. */
13045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        put_unaligned(inl(ioaddr + 0xA4), (u32 *)nic->node_addr);
13055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        put_unaligned(inl(ioaddr + 0xA8), (u16 *)(nic->node_addr + 4));
13065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (i = 0; i < ETH_ALEN; i ++)
13075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            sum += nic->node_addr[i];
13085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    } else {
13095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* A serial EEPROM interface, we read now and sort it out later. */
13105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        int sa_offset = 0;
13115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        int ee_addr_size = read_eeprom(ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;
13125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (i = 0; i < sizeof(ee_data)/2; i++)
13145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            ((u16 *)ee_data)[i] =
13155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                le16_to_cpu(read_eeprom(ioaddr, i, ee_addr_size));
13165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* DEC now has a specification (see Notes) but early board makers
13185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project           just put the address in the first EEPROM locations. */
13195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* This does  memcmp(eedata, eedata+16, 8) */
13205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (i = 0; i < 8; i ++)
13215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (ee_data[i] != ee_data[16+i])
13225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                sa_offset = 20;
13235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (ee_data[0] == 0xff  &&  ee_data[1] == 0xff &&  ee_data[2] == 0) {
13245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            sa_offset = 2;              /* Grrr, damn Matrox boards. */
13255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
13265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (i = 0; i < ETH_ALEN; i ++) {
13275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            nic->node_addr[i] = ee_data[i + sa_offset];
13285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            sum += ee_data[i + sa_offset];
13295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
13305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
13315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Lite-On boards have the address byte-swapped. */
13325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if ((nic->node_addr[0] == 0xA0  ||  nic->node_addr[0] == 0xC0)
13335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        &&  nic->node_addr[1] == 0x00)
13345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (i = 0; i < ETH_ALEN; i+=2) {
13355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            char tmp = nic->node_addr[i];
13365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            nic->node_addr[i] = nic->node_addr[i+1];
13375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            nic->node_addr[i+1] = tmp;
13385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
13395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (sum == 0  || sum == ETH_ALEN*0xff) {
13415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("%s: EEPROM not present!\n", tp->nic_name);
13425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (i = 0; i < ETH_ALEN-1; i++)
13435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            nic->node_addr[i] = last_phys_addr[i];
13445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        nic->node_addr[i] = last_phys_addr[i] + 1;
13455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
13465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 0; i < ETH_ALEN; i++)
13485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        last_phys_addr[i] = nic->node_addr[i];
13495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    printf("%s: %! at ioaddr %hX\n", tp->nic_name, nic->node_addr, ioaddr);
13515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->chip_id = chip_idx;
13535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->revision = chip_rev;
13545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->csr0 = csr0;
13555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles.
13575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       And the ASIX must have a burst limit or horrible things happen. */
13585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (chip_idx == DC21143  &&  chip_rev == 65)
13595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->csr0 &= ~0x01000000;
13605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    else if (tp->flags & IS_ASIX)
13615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->csr0 |= 0x2000;
13625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (media_cap[tp->default_port] & MediaIsMII) {
13645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };
13655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->mii_advertise = media2advert[tp->default_port - 9];
13665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->mii_advertise |= (tp->flags & HAS_8023X); /* Matching bits! */
13675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
13685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* This is logically part of the probe routine, but too complex
13705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       to write inline. */
13715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->flags & HAS_MEDIA_TABLE) {
13725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        memcpy(tp->eeprom, ee_data, sizeof(tp->eeprom));
13735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        parse_eeprom(nic);
13745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
13755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    start_link(nic);
13775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* reset the device and make ready for tx and rx of packets */
13795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tulip_reset(nic);
13805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    nic->reset    = tulip_reset;
13825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    nic->poll     = tulip_poll;
13835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    nic->transmit = tulip_transmit;
13845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    nic->disable  = tulip_disable;
13855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* give the board a chance to reset before returning */
13875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tulip_wait(4*TICKS_PER_SEC);
13885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return nic;
13905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
13915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void start_link(struct nic *nic)
13935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
13945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
13955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
13965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
13975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("start_link\n");
13985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
13995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
14005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if ((tp->flags & ALWAYS_CHECK_MII) ||
14015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        (tp->mtable  &&  tp->mtable->has_mii) ||
14025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        ( ! tp->mtable  &&  (tp->flags & HAS_MII))) {
14035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        unsigned int phy, phy_idx;
14045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tp->mtable  &&  tp->mtable->has_mii) {
14055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            for (i = 0; i < tp->mtable->leafcount; i++)
14065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if (tp->mtable->mleaf[i].media == 11) {
14075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    tp->cur_index = i;
14085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    tp->saved_if_port = tp->if_port;
14095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    select_media(nic, 2);
14105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    tp->if_port = tp->saved_if_port;
14115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    break;
14125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                }
14135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
14145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
14155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* Find the connected MII xcvrs. */
14165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
14175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project             phy++) {
14185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            int mii_status = mdio_read(nic, phy, 1);
14195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if ((mii_status & 0x8301) == 0x8001 ||
14205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                ((mii_status & 0x8000) == 0  && (mii_status & 0x7800) != 0)) {
14215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                int mii_reg0 = mdio_read(nic, phy, 0);
14225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                int mii_advert = mdio_read(nic, phy, 4);
14235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                int to_advert;
14245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
14255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if (tp->mii_advertise)
14265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    to_advert = tp->mii_advertise;
14275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                else if (tp->advertising[phy_idx])
14285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    to_advert = tp->advertising[phy_idx];
14295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                else                    /* Leave unchanged. */
14305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    tp->mii_advertise = to_advert = mii_advert;
14315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
14325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                tp->phys[phy_idx++] = phy;
14335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf("%s:  MII transceiver %d config %hX status %hX advertising %hX.\n",
14345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                       tp->nic_name, phy, mii_reg0, mii_status, mii_advert);
14355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                /* Fixup for DLink with miswired PHY. */
14365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if (mii_advert != to_advert) {
14375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    printf("%s:  Advertising %hX on PHY %d previously advertising %hX.\n",
14385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                           tp->nic_name, to_advert, phy, mii_advert);
14395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    mdio_write(nic, phy, 4, to_advert);
14405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                }
14415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                /* Enable autonegotiation: some boards default to off. */
14425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                mdio_write(nic, phy, 0, mii_reg0 |
14435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                           (tp->full_duplex ? 0x1100 : 0x1000) |
14445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                           (media_cap[tp->default_port]&MediaIs100 ? 0x2000:0));
14455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            }
14465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
14475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->mii_cnt = phy_idx;
14485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tp->mtable  &&  tp->mtable->has_mii  &&  phy_idx == 0) {
14495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("%s: ***WARNING***: No MII transceiver found!\n",
14505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   tp->nic_name);
14515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->phys[0] = 1;
14525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
14535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
14545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
14555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Reset the xcvr interface and turn on heartbeat. */
14565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    switch (tp->chip_id) {
14575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case DC21040:
14585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x00000000, ioaddr + CSR13);
14595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x00000004, ioaddr + CSR13);
14605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
14615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case DC21041:
14625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* This is nway_start(). */
14635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tp->sym_advertise == 0)
14645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->sym_advertise = 0x0061;
14655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x00000000, ioaddr + CSR13);
14665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0xFFFFFFFF, ioaddr + CSR14);
14675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */
14685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(inl(ioaddr + CSR6) | 0x0200, ioaddr + CSR6);
14695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x0000EF01, ioaddr + CSR13);
14705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
14715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case DC21140: default:
14725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tp->mtable)
14735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
14745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
14755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case DC21142:
14765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case PNIC2:
14775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tp->mii_cnt  ||  media_cap[tp->if_port] & MediaIsMII) {
14785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x82020000, ioaddr + CSR6);
14795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0000, ioaddr + CSR13);
14805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0000, ioaddr + CSR14);
14815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x820E0000, ioaddr + CSR6);
14825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        } else
14835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            nway_start(nic);
14845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
14855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case LC82C168:
14865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if ( ! tp->mii_cnt) {
14875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->nway = 1;
14885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->nwayset = 0;
14895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x00420000, ioaddr + CSR6);
14905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x30, ioaddr + CSR12);
14915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0001F078, ioaddr + 0xB8);
14925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */
14935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
14945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
14955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case MX98713: case COMPEX9881:
14965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x00000000, ioaddr + CSR6);
14975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */
14985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x00000001, ioaddr + CSR13);
14995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
15005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case MX98715: case MX98725:
15015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x01a80000, ioaddr + CSR6);
15025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0xFFFFFFFF, ioaddr + CSR14);
15035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x00001000, ioaddr + CSR12);
15045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
15055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case COMET:
15065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* No initialization necessary. */
15075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
15085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
15095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
15105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
15115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void nway_start(struct nic *nic)
15125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
15135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int csr14 = ((tp->sym_advertise & 0x0780) << 9)  |
15145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        ((tp->sym_advertise&0x0020)<<1) | 0xffbf;
15155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
15165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
15175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("nway_start\n");
15185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
15195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
15205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->if_port = 0;
15215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->nway = tp->mediasense = 1;
15225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->nwayset = tp->lpar = 0;
15235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->chip_id == PNIC2) {
15245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->csr6 = 0x01000000 | (tp->sym_advertise & 0x0040 ? 0x0200 : 0);
15255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        return;
15265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
15275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
15285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tulip_debug > 1)
15295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("%s: Restarting internal NWay autonegotiation, %X.\n",
15305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project               tp->nic_name, csr14);
15315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
15325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(0x0001, ioaddr + CSR13);
15335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(csr14, ioaddr + CSR14);
15345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->csr6 = 0x82420000 | (tp->sym_advertise & 0x0040 ? 0x0200 : 0);
15355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(tp->csr6, ioaddr + CSR6);
15365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->mtable  &&  tp->mtable->csr15dir) {
15375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(tp->mtable->csr15dir, ioaddr + CSR15);
15385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(tp->mtable->csr15val, ioaddr + CSR15);
15395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    } else if (tp->chip_id != PNIC2)
15405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outw(0x0008, ioaddr + CSR15);
15415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->chip_id == DC21041)                 /* Trigger NWAY. */
15425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0xEF01, ioaddr + CSR12);
15435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    else
15445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x1301, ioaddr + CSR12);
15455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
15465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
15475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void init_media(struct nic *nic)
15485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
15495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
15505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
15515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
15525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("init_media\n");
15535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
15545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
15555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->saved_if_port = tp->if_port;
15565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->if_port == 0)
15575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->if_port = tp->default_port;
15585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
15595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Allow selecting a default media. */
15605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    i = 0;
15615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->mtable == NULL)
15625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        goto media_picked;
15635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->if_port) {
15645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        int looking_for = media_cap[tp->if_port] & MediaIsMII ? 11 :
15655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            (tp->if_port == 12 ? 0 : tp->if_port);
15665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (i = 0; i < tp->mtable->leafcount; i++)
15675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (tp->mtable->mleaf[i].media == looking_for) {
15685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf("%s: Using user-specified media %s.\n",
15695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                       tp->nic_name, medianame[tp->if_port]);
15705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                goto media_picked;
15715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            }
15725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
15735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if ((tp->mtable->defaultmedia & 0x0800) == 0) {
15745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        int looking_for = tp->mtable->defaultmedia & 15;
15755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (i = 0; i < tp->mtable->leafcount; i++)
15765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (tp->mtable->mleaf[i].media == looking_for) {
15775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf("%s: Using EEPROM-set media %s.\n",
15785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                       tp->nic_name, medianame[looking_for]);
15795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                goto media_picked;
15805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            }
15815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
15825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Start sensing first non-full-duplex media. */
15835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = tp->mtable->leafcount - 1;
15845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project         (media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--)
15855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        ;
15865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project media_picked:
15875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
15885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->csr6 = 0;
15895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->cur_index = i;
15905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->nwayset = 0;
15915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
15925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tp->if_port) {
15935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tp->chip_id == DC21143  &&  media_cap[tp->if_port] & MediaIsMII) {
15945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            /* We must reset the media CSRs when we force-select MII mode. */
15955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0000, ioaddr + CSR13);
15965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0000, ioaddr + CSR14);
15975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0008, ioaddr + CSR15);
15985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
15995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        select_media(nic, 1);
16005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        return;
16015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
16025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    switch(tp->chip_id) {
16035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case DC21041:
16045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* tp->nway = 1;*/
16055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        nway_start(nic);
16065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
16075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case DC21142:
16085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tp->mii_cnt) {
16095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            select_media(nic, 1);
16105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
16115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (tulip_debug > 1)
16125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf("%s: Using MII transceiver %d, status %hX.\n",
16135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                       tp->nic_name, tp->phys[0], mdio_read(nic, tp->phys[0], 1));
16145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
16155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x82020000, ioaddr + CSR6);
16165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->csr6 = 0x820E0000;
16175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->if_port = 11;
16185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0000, ioaddr + CSR13);
16195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0000, ioaddr + CSR14);
16205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        } else
16215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            nway_start(nic);
16225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
16235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case PNIC2:
16245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        nway_start(nic);
16255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
16265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case LC82C168:
16275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tp->mii_cnt) {
16285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->if_port = 11;
16295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0);
16305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0001, ioaddr + CSR15);
16315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        } else if (inl(ioaddr + CSR5) & TPLnkPass)
16325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            pnic_do_nway(nic);
16335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        else {
16345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            /* Start with 10mbps to do autonegotiation. */
16355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x32, ioaddr + CSR12);
16365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->csr6 = 0x00420000;
16375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0001B078, ioaddr + 0xB8);
16385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0201B078, ioaddr + 0xB8);
16395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
16405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
16415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case MX98713: case COMPEX9881:
16425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->if_port = 0;
16435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0);
16445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
16455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
16465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case MX98715: case MX98725:
16475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* Provided by BOLO, Macronix - 12/10/1998. */
16485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->if_port = 0;
16495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->csr6 = 0x01a80200;
16505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
16515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0);
16525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
16535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case COMET:
16545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->if_port = 0;
16555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	tp->csr6 = 0x00040000;
16565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
16575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    case AX88140: case AX88141:
16585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100;
16595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        break;
16605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    default:
16615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        select_media(nic, 1);
16625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
16635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
16645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
16655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void pnic_do_nway(struct nic *nic)
16665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
16675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 phy_reg = inl(ioaddr + 0xB8);
16685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 new_csr6 = tp->csr6 & ~0x40C40200;
16695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
16705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
16715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("pnic_do_nway\n");
16725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
16735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
16745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (phy_reg & 0x78000000) { /* Ignore baseT4 */
16755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (phy_reg & 0x20000000)               tp->if_port = 5;
16765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        else if (phy_reg & 0x40000000)  tp->if_port = 3;
16775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        else if (phy_reg & 0x10000000)  tp->if_port = 4;
16785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        else if (phy_reg & 0x08000000)  tp->if_port = 0;
16795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->nwayset = 1;
16805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        new_csr6 = (tp->if_port & 1) ? 0x01860000 : 0x00420000;
16815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x32 | (tp->if_port & 1), ioaddr + CSR12);
16825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tp->if_port & 1)
16835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x1F868, ioaddr + 0xB8);
16845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (phy_reg & 0x30000000) {
16855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->full_duplex = 1;
16865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            new_csr6 |= 0x00000200;
16875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
16885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
16895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tulip_debug > 1)
16905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("%s: PNIC autonegotiated status %X, %s.\n",
16915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   tp->nic_name, phy_reg, medianame[tp->if_port]);
16925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
16935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tp->csr6 != new_csr6) {
16945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->csr6 = new_csr6;
16955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(tp->csr6 | 0x0002, ioaddr + CSR6);     /* Restart Tx */
16965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(tp->csr6 | 0x2002, ioaddr + CSR6);
16975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
16985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
16995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
17005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
17015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Set up the transceiver control registers for the selected media type. */
17025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void select_media(struct nic *nic, int startup)
17035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
17045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    struct mediatable *mtable = tp->mtable;
17055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 new_csr6;
17065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
17075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
17085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG_WHERE
17095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    whereami("select_media\n");
17105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
17115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
17125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (mtable) {
17135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index];
17145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        unsigned char *p = mleaf->leafdata;
17155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        switch (mleaf->type) {
17165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        case 0:                                 /* 21140 non-MII xcvr. */
17175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
17185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (tulip_debug > 1)
17195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf("%s: Using a 21140 non-MII transceiver"
17205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                       " with control setting %hhX.\n",
17215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                       tp->nic_name, p[1]);
17225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
17235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->if_port = p[0];
17245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (startup)
17255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
17265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(p[1], ioaddr + CSR12);
17275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18);
17285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            break;
17295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        case 2: case 4: {
17305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            u16 setup[5];
17315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            u32 csr13val, csr14val, csr15dir, csr15val;
17325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            for (i = 0; i < 5; i++)
17335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                setup[i] = get_u16(&p[i*2 + 1]);
17345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
17355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->if_port = p[0] & 15;
17365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (media_cap[tp->if_port] & MediaAlwaysFD)
17375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                tp->full_duplex = 1;
17385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
17395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (startup && mtable->has_reset) {
17405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset];
17415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                unsigned char *rst = rleaf->leafdata;
17425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
17435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if (tulip_debug > 1)
17445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    printf("%s: Resetting the transceiver.\n",
17455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                           tp->nic_name);
17465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
17475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                for (i = 0; i < rst[0]; i++)
17485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15);
17495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            }
17505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
17515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (tulip_debug > 1)
17525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf("%s: 21143 non-MII %s transceiver control "
17535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                       "%hX/%hX.\n",
17545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                       tp->nic_name, medianame[tp->if_port], setup[0], setup[1]);
17555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
17565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (p[0] & 0x40) {  /* SIA (CSR13-15) setup values are provided. */
17575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                csr13val = setup[0];
17585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                csr14val = setup[1];
17595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                csr15dir = (setup[3]<<16) | setup[2];
17605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                csr15val = (setup[4]<<16) | setup[2];
17615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outl(0, ioaddr + CSR13);
17625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outl(csr14val, ioaddr + CSR14);
17635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outl(csr15dir, ioaddr + CSR15); /* Direction */
17645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outl(csr15val, ioaddr + CSR15); /* Data */
17655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outl(csr13val, ioaddr + CSR13);
17665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            } else {
17675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                csr13val = 1;
17685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                csr14val = 0x0003FF7F;
17695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                csr15dir = (setup[0]<<16) | 0x0008;
17705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                csr15val = (setup[1]<<16) | 0x0008;
17715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if (tp->if_port <= 4)
17725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    csr14val = t21142_csr14[tp->if_port];
17735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if (startup) {
17745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    outl(0, ioaddr + CSR13);
17755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    outl(csr14val, ioaddr + CSR14);
17765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                }
17775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outl(csr15dir, ioaddr + CSR15); /* Direction */
17785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outl(csr15val, ioaddr + CSR15); /* Data */
17795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if (startup) outl(csr13val, ioaddr + CSR13);
17805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            }
17815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
17825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (tulip_debug > 1)
17835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf("%s:  Setting CSR15 to %X/%X.\n",
17845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                       tp->nic_name, csr15dir, csr15val);
17855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
17865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (mleaf->type == 4)
17875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18);
17885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            else
17895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                new_csr6 = 0x82420000;
17905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            break;
17915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
17925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        case 1: case 3: {
17935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            int phy_num = p[0];
17945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            int init_length = p[1];
17955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            u16 *misc_info;
17965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
17975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->if_port = 11;
17985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            new_csr6 = 0x020E0000;
17995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (mleaf->type == 3) {     /* 21142 */
18005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                u16 *init_sequence = (u16*)(p+2);
18015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                u16 *reset_sequence = &((u16*)(p+3))[init_length];
18025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                int reset_length = p[2 + init_length*2];
18035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                misc_info = reset_sequence + reset_length;
18045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if (startup)
18055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    for (i = 0; i < reset_length; i++)
18065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                        outl(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15);
18075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                for (i = 0; i < init_length; i++)
18085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    outl(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15);
18095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            } else {
18105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                u8 *init_sequence = p + 2;
18115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                u8 *reset_sequence = p + 3 + init_length;
18125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                int reset_length = p[2 + init_length];
18135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                misc_info = (u16*)(reset_sequence + reset_length);
18145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if (startup) {
18155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
18165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    for (i = 0; i < reset_length; i++)
18175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                        outl(reset_sequence[i], ioaddr + CSR12);
18185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                }
18195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                for (i = 0; i < init_length; i++)
18205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    outl(init_sequence[i], ioaddr + CSR12);
18215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            }
18225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->advertising[phy_num] = get_u16(&misc_info[1]) | 1;
18235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (startup < 2) {
18245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if (tp->mii_advertise == 0)
18255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    tp->mii_advertise = tp->advertising[phy_num];
18265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
18275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if (tulip_debug > 1)
18285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                    printf("%s:  Advertising %hX on MII %d.\n",
18295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                           tp->nic_name, tp->mii_advertise, tp->phys[phy_num]);
18305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
18315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                mdio_write(nic, tp->phys[phy_num], 4, tp->mii_advertise);
18325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            }
18335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            break;
18345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
18355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        default:
18365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("%s:  Invalid media table selection %d.\n",
18375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   tp->nic_name, mleaf->type);
18385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            new_csr6 = 0x020E0000;
18395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
18405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
18415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tulip_debug > 1)
18425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("%s: Using media type %s, CSR12 is %hhX.\n",
18435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   tp->nic_name, medianame[tp->if_port],
18445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   inl(ioaddr + CSR12) & 0xff);
18455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
18465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    } else if (tp->chip_id == DC21041) {
18475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        int port = tp->if_port <= 4 ? tp->if_port : 0;
18485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
18495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tulip_debug > 1)
18505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("%s: 21041 using media %s, CSR12 is %hX.\n",
18515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   tp->nic_name, medianame[port == 3 ? 12: port],
18525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   inl(ioaddr + CSR12));
18535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
18545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */
18555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(t21041_csr14[port], ioaddr + CSR14);
18565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(t21041_csr15[port], ioaddr + CSR15);
18575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(t21041_csr13[port], ioaddr + CSR13);
18585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        new_csr6 = 0x80020000;
18595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    } else if (tp->chip_id == LC82C168) {
18605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (startup && ! tp->medialock)
18615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->if_port = tp->mii_cnt ? 11 : 0;
18625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
18635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tulip_debug > 1)
18645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    printf("%s: PNIC PHY status is %hX, media %s.\n",
18655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   tp->nic_name, inl(ioaddr + 0xB8), medianame[tp->if_port]);
18665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
18675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tp->mii_cnt) {
18685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            new_csr6 = 0x810C0000;
18695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0001, ioaddr + CSR15);
18705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0201B07A, ioaddr + 0xB8);
18715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        } else if (startup) {
18725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            /* Start with 10mbps to do autonegotiation. */
18735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x32, ioaddr + CSR12);
18745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            new_csr6 = 0x00420000;
18755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0001B078, ioaddr + 0xB8);
18765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0201B078, ioaddr + 0xB8);
18775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        } else if (tp->if_port == 3  ||  tp->if_port == 5) {
18785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x33, ioaddr + CSR12);
18795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            new_csr6 = 0x01860000;
18805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            /* Trigger autonegotiation. */
18815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(startup ? 0x0201F868 : 0x0001F868, ioaddr + 0xB8);
18825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        } else {
18835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x32, ioaddr + CSR12);
18845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            new_csr6 = 0x00420000;
18855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x1F078, ioaddr + 0xB8);
18865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
18875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    } else if (tp->chip_id == DC21040) {                                        /* 21040 */
18885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* Turn on the xcvr interface. */
18895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        int csr12 = inl(ioaddr + CSR12);
18905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
18915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tulip_debug > 1)
18925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("%s: 21040 media type is %s, CSR12 is %hhX.\n",
18935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   tp->nic_name, medianame[tp->if_port], csr12);
18945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
18955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (media_cap[tp->if_port] & MediaAlwaysFD)
18965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->full_duplex = 1;
18975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        new_csr6 = 0x20000;
18985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* Set the full duplux match frame. */
18995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(FULL_DUPLEX_MAGIC, ioaddr + CSR11);
19005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */
19015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (t21040_csr13[tp->if_port] & 8) {
19025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0705, ioaddr + CSR14);
19035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0006, ioaddr + CSR15);
19045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        } else {
19055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0xffff, ioaddr + CSR14);
19065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            outl(0x0000, ioaddr + CSR15);
19075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
19085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0x8f01 | t21040_csr13[tp->if_port], ioaddr + CSR13);
19095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    } else {                                    /* Unknown chip type with no media table. */
19105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tp->default_port == 0)
19115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            tp->if_port = tp->mii_cnt ? 11 : 3;
19125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (media_cap[tp->if_port] & MediaIsMII) {
19135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            new_csr6 = 0x020E0000;
19145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        } else if (media_cap[tp->if_port] & MediaIsFx) {
19155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            new_csr6 = 0x028600000;
19165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        } else
19175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            new_csr6 = 0x038600000;
19185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
19195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tulip_debug > 1)
19205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("%s: No media description table, assuming "
19215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   "%s transceiver, CSR12 %hhX.\n",
19225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   tp->nic_name, medianame[tp->if_port],
19235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   inl(ioaddr + CSR12));
19245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
19255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
19265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
19275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0);
19285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return;
19295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
19305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
19315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
19325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  Check the MII negotiated duplex and change the CSR6 setting if
19335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  required.
19345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  Return 0 if everything is OK.
19355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  Return < 0 if the transceiver is missing or has no link beat.
19365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project*/
19375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int tulip_check_duplex(struct nic *nic)
19385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
19395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        unsigned int bmsr, lpa, negotiated, new_csr6;
19405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
19415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        bmsr = mdio_read(nic, tp->phys[0], 1);
19425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        lpa = mdio_read(nic, tp->phys[0], 5);
19435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
19445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
19455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tulip_debug > 1)
19465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf("%s: MII status %#x, Link partner report "
19475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                           "%#x.\n", tp->nic_name, bmsr, lpa);
19485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
19495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
19505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (bmsr == 0xffff)
19515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                return -2;
19525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if ((bmsr & 4) == 0) {
19535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                int new_bmsr = mdio_read(nic, tp->phys[0], 1);
19545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if ((new_bmsr & 4) == 0) {
19555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
19565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                        if (tulip_debug  > 1)
19575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                printf("%s: No link beat on the MII interface,"
19585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                           " status %#x.\n", tp->nic_name,
19595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                           new_bmsr);
19605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
19615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                        return -1;
19625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                }
19635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
19645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tp->full_duplex = lpa & 0x140;
19655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
19665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        new_csr6 = tp->csr6;
19675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        negotiated = lpa & tp->advertising[0];
19685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
19695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if(negotiated & 0x380) new_csr6 &= ~0x400000;
19705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        else                   new_csr6 |= 0x400000;
19715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (tp->full_duplex)   new_csr6 |= 0x200;
19725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        else                   new_csr6 &= ~0x200;
19735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
19745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (new_csr6 != tp->csr6) {
19755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                tp->csr6 = new_csr6;
19765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
19775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef TULIP_DEBUG
19785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if (tulip_debug > 0)
19795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                        printf("%s: Setting %s-duplex based on MII"
19805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                   "#%d link partner capability of %#x.\n",
19815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                   tp->nic_name,
19825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                   tp->full_duplex ? "full" : "half",
19835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                                   tp->phys[0], lpa);
19845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
19855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                return 1;
19865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
19875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
19885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        return 0;
19895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
1990