root/usr/src/uts/intel/io/dnet/dnet_mii.h
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * mii.h
 * Generic MII/PHY Support for MAC drivers.
 *
 * Copyrighted as an unpublished work. (c) Copyright 1997 Sun Microsystems, Inc.
 * All rights reserved.
 */

#ifndef _DNET_MII_H
#define _DNET_MII_H

/*
 * NOTES
 * All calls to MII functions are assumed to be serialized by the user.
 * In the case of the port monitor, which causes asynchronous callbacks,
 * you must pass the address of a mutex. MII aquires this before calling
 * the user callback, and releases it after the callback returns.
 *
 * All calls requiring a PHY address must be done AFTER calling
 * mii_init_phy() for that PHY, with the exception of mii_phyexists()
 *
 * mii_rsan() will not accept mii_wait_interrupt as a wait type. Its futile to
 * expect autonegotiation to happen fast enough. (You're better off using the
 * port monitor to tell you, asynchronously that the link has been
 * re-established than waiting at all.)
 */

/*
 * MII programming Interface types
 */

enum mii_phy_state {phy_state_unknown, phy_state_linkup, phy_state_linkdown};
enum mii_wait_type {mii_wait_none, mii_wait_user, mii_wait_interrupt};
typedef ushort_t (*mii_readfunc_t)(dev_info_t *, int phy, int reg);
typedef void (*mii_writefunc_t)(dev_info_t *, int phy, int reg, int value);
typedef void (*mii_linkfunc_t)(dev_info_t *, int phy, enum mii_phy_state state);

struct mii_info;        /* Private to MII! */
typedef struct mii_info *mii_handle_t;

/*
 * Entrypoints
 */

int mii_create(dev_info_t *, mii_writefunc_t, mii_readfunc_t, mii_handle_t *);
                        /* Initialise the PHY interface */

int mii_init_phy(mii_handle_t, int phy);
                        /* Initialise a PHY */

int mii_getspeed(mii_handle_t, int phy, int *speed, int *full_duplex);
                        /* Check operating speed of PHY */

int mii_probe_phy(mii_handle_t, int phy);
                        /* Check if PHY exists at an address */

int mii_rsan(mii_handle_t mac, int phy, enum mii_wait_type wait_type);
                                        /* Restart autonegotiation */

int mii_fixspeed(mii_handle_t, int phy, int speed, int fullduplex);
                        /* Fix speed and duplex mode of PHY (disable autoneg) */

int mii_autoneg_enab(mii_handle_t mac, int phy);
                        /* (re-)enable autonegotiation */

int mii_reset_phy(mii_handle_t, int phy, enum mii_wait_type wait_type);
                        /* Force PHY to reset itself */

int mii_disable_fullduplex(mii_handle_t, int phy);
                        /* Stop the PHY advertising full duplex capability */

int mii_linkup(mii_handle_t, int phy);
                        /* Check link status on a phy */

int mii_sync(mii_handle_t, int phy);
                        /* Sync API if something may have affected the PHY */

int mii_isolate(mii_handle_t, int phy);
                        /* Electrically isolate a PHY */

int mii_unisolate(mii_handle_t, int phy);
                        /* Unisolate */

int mii_dump_phy(mii_handle_t, int phy);
                        /* Dump register contents */

int mii_start_portmon(mii_handle_t mac, mii_linkfunc_t func, kmutex_t *lock);
                        /* Monitor initialised PHYs for link state changes */

int mii_stop_portmon(mii_handle_t mac);
                        /* Stop port monitor */

void mii_destroy(mii_handle_t mac);
                        /* Cleanup MII interface */

/*
 * Errorcodes
 */
#define MII_SUCCESS 0
#define MII_PHYPRESENT 1        /* PHY already exists at specified address */
#define MII_NOMEM 2             /* Not enough memory */
#define MII_PARAM 3             /* parameters passed are incorrect */
#define MII_NOTSUPPORTED 4      /* operation not supported by hardware. */
#define MII_STATE 5             /* The request is not valid at this time. */
#define MII_HARDFAIL 6          /* The hardware is not functioning correctly */
#define MII_TIMEOUT 7           /* Timeout waiting for operation to complete */
#define MII_PHYNOTPRESENT 8     /* There is no PHY at the specified address */

/* Vendor Specific functions */
typedef void (*phy_genfunc)(mii_handle_t, int phy);
typedef int (*phy_getspeedfunc)(mii_handle_t, int phy, int *speed, int *fd);

/* per-PHY information. */
struct phydata
{
        ulong_t id;                     /* ID from MII registers 2,3 */
        char *description;              /* Text description from ID */
        phy_genfunc phy_dump;           /* how to dump registers this make */
        phy_genfunc phy_postreset;      /* What to do after a reset (or init) */
        phy_getspeedfunc phy_getspeed;  /* how to find current speed */
        unsigned short control;         /* Bits that need to be written ...  */
                                        /* ...to control register */
        enum mii_phy_state state;       /* Current state of link at this PHY */
        int fix_speed;                  /* Speed fixed in conf file */
        int fix_duplex;
        /*
         * ^^NEEDSWORK: We can only fix speed for the driver, never mind a
         * particular PHY on a particular instance, but this is where this
         * belongs.
         */
};

typedef struct mii_info
{
        mii_readfunc_t mii_read;        /* How to read an MII register */
        mii_writefunc_t mii_write;      /* How to write an MII register */
        mii_linkfunc_t mii_linknotify;  /* What to do when link state changes */
        dev_info_t *mii_dip;            /* MAC's devinfo */
        timeout_id_t portmon_timer;     /* ID of timer for the port monitor */
        kmutex_t *lock;                 /* Lock to serialise mii calls */
        struct phydata *phys[32];       /* PHY Information indexed by address */
} mii_info_t;

#define OUI_NATIONAL_SEMICONDUCTOR 0x80017
#define NS_DP83840              0x00
#define MII_83840_ADDR          25
#define NS83840_ADDR_SPEED10    (1<<6)
#define NS83840_ADDR_CONSTAT    (1<<5)
#define NS83840_ADDR_ADDR       (0x1f<<0)

#define OUI_INTEL               0x0aa00
#define INTEL_82553_CSTEP       0x35    /* A and B steps are non-standard */
#define MII_82553_EX0           16
#define I82553_EX0_FDUPLEX      (1<<0)
#define I82553_EX0_100MB        (1<<1)
#define I82553_EX0_WAKE         (1<<2)
#define I82553_EX0_SQUELCH      (3<<3) /* 3:4 */
#define I82553_EX0_REVCNTR      (7<<5) /* 5:7 */
#define I82553_EX0_FRCFAIL      (1<<8)
#define I82553_EX0_TEST         (0x1f<<9) /* 13:9 */
#define I82553_EX0_LINKDIS      (1<<14)
#define I82553_EX0_JABDIS       (1<<15)

#define MII_82553_EX1
#define I82553_EX1_RESERVE      (0x1ff<<0) /* 0:8 */
#define I82553_EX1_CH2EOF       (1<<9)
#define I82553_EX1_MNCHSTR      (1<<10)
#define I82553_EX1_EOP          (1<<11)
#define I82553_EX1_BADCODE      (1<<12)
#define I82553_EX1_INVALCODE    (1<<13)
#define I82553_EX1_DCBALANCE    (1<<14)
#define I82553_EX1_PAIRSKEW     (1<<15)

#define INTEL_82555             0x15
#define INTEL_82562_EH          0x33
#define INTEL_82562_ET          0x32
#define INTEL_82562_EM          0x31

#define OUI_ICS                 0x57d
#define ICS_1890                2
#define ICS_1889                1
#define ICS_EXCTRL              16
#define ICS_EXCTRL_CMDOVRD      (1<<15)
#define ICS_EXCTRL_PHYADDR      (0x1f<<6)
#define ICS_EXCTRL_SCSTEST      (1<<5)
#define ICS_EXCTRL_INVECTEST    (1<<2)
#define ICS_EXCTRL_SCDISABLE    (1<<0)

#define ICS_QUICKPOLL           17
#define ICS_QUICKPOLL_100MB     (1<<15)
#define ICS_QUICKPOLL_FDUPLEX   (1<<14)
#define ICS_QUICKPOLL_ANPROG    (7<<11)
#define ICS_QUICKPOLL_RSE       (1<<10)
#define ICS_QUICKPOLL_PLLLOCK   (1<<9)
#define ICS_QUICKPOLL_FALSECD   (1<<8)
#define ICS_QUICKPOLL_SYMINVAL  (1<<7)
#define ICS_QUICKPOLL_SYMHALT   (1<<6)
#define ICS_QUICKPOLL_PREMEND   (1<<5)
#define ICS_QUICKPOLL_ANDONE    (1<<4)
#define ICS_QUICKPOLL_RESERVED  (1<<3)
#define ICS_QUICKPOLL_JABBER    (1<<2)
#define ICS_QUICKPOLL_REMFAULT  (1<<1)
#define ICS_QUICKPOLL_LINKSTAT  (1<<0)

#define ICS_10BASET             18
#define ICS_10BASET_REMJABBER   (1<<15)
#define ICS_10BASET_REVPOLARITY (1<<14)
#define ICS_10BASET_RESERVED    (0xff<<6)
#define ICS_10BASET_NOJABBER    (1<<5)
#define ICS_10BASET_NORMLOOP    (1<<4)
#define ICS_10BASET_NOAUTOPOLL  (1<<3)
#define ICS_10BASET_NOSQE       (1<<2)
#define ICS_10BASET_NOLINKLOSS  (1<<1)
#define ICS_10BASET_NOSQUELCH   (1<<0)

#define ICS_EXCTRL2             19
#define ICS_EXCTRL2_ISREPEATER  (1<<15)
#define ICS_EXCTRL2_SOFTPRI     (1<<14)
#define ICS_EXCTRL2_LPCANREMF   (1<<13)
#define ICS_EXCTRL2_RMFSXMITED  (1<<10)
#define ICS_EXCTRL2_ANPWRREMF   (1<<4)
#define ICS_EXCTRL2_10BASETQUAL (1<<2)
#define ICS_EXCTRL2_AUTOPWRDN   (1<<0)

#endif /* _DNET_MII_H */