mii.h revision bdb9230ac765cb7af3fc1f4119caf2c5720dceb3
/*
* 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.
*/
#ifndef _SYS_MII_H
#define _SYS_MII_H
#include <sys/mac_provider.h>
#include <sys/netlb.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* NOTES
*
* The device driver is required to protect its own registers. The
* MII common code will call MII entry points asynchronously, from a
* taskq, and holds an internal lock across such calls (except the
* notify entry point). Therefore, device drivers MUST NOT hold any
* locks across calls into the MII framework.
*
* If a device must be suspended (e.g. due to DDI_SUSPEND) the MII
* layer can be suspended by calling mii_stop(). After this point,
* the monitoring task will be suspended and the driver can be assured
* that MII will not interfere until restarted with mii_start().
*
* Note that monitoring is not started until mii_start() is called.
* The mii_start() function may be called multiple times. It performs
* an implicit reset of the MII bus and PHY.
*
* Once started, if not already done, a probe of the MII bus is done to
* find a suitable PHY. If no PHY is found, then you won't have any
* link! Once a suitable PHY is selected, any other PHYs are isolated and
* powered down. The device driver can cause MII to re-probe the bus for
* changes to the available PHYs by calling mii_probe(). Note that this
* will also cause a full reset of all PHYs.
*
* The mii_reset entry point, which is optional, is used to notify the
* driver when the MII layer has reset the device. This can allow
* certain drivers the opportunity to "fix up" things after reset.
* Note however, that when possible, it is better if the logic is
* encoded into a vendor specific PHY module.
*/
#ifdef _KERNEL
typedef struct mii_handle *mii_handle_t;
typedef struct mii_ops mii_ops_t;
struct mii_ops {
int mii_version;
uint16_t (*mii_read)(void *, uint8_t, uint8_t);
void (*mii_write)(void *, uint8_t, uint8_t, uint16_t);
void (*mii_notify)(void *, link_state_t);
void (*mii_reset)(void *);
};
#define MII_OPS_VERSION 0
/*
* Support routines.
*/
/*
* mii_alloc
*
* Allocate an MII handle. Called during driver's attach(9e)
* handling, this routine is valid in kernel context only.
*
* Arguments
*
* private A private state structure, provided back to
* entry points.
* dip The dev_info node for the MAC driver.
* ops Entry points into the MAC driver.
*
* Returns
* Handle to MII bus on success, NULL on failure.
*/
mii_handle_t mii_alloc(void *private, dev_info_t *dip, mii_ops_t *ops);
/*
* mii_alloc
*
* Allocate an MII handle. Called during driver's attach(9e)
* handling, this routine is valid in kernel context only. This
* routine is an alternative to mii_alloc() for use when the
* instance number (PPA) is not the same as the devinfo instance
* number, and hence needs to be overridden.
*
* Arguments
*
* private A private state structure, provided back to
* entry points.
* dip The dev_info node for the MAC driver.
* instance The instance (PPA) of the interface.
* ops Entry points into the MAC driver.
*
* Returns
* Handle to MII bus on success, NULL on failure.
*/
mii_handle_t mii_alloc_instance(void *private, dev_info_t *dip, int instance,
mii_ops_t *ops);
/*
* mii_free
*
* Free an MII handle and associated resources. Call from
* detach(9e) handling, this routine is valid in kernel context
* only.
*/
void mii_free(mii_handle_t mii);
/*
* mii_set_pauseable
*
* Lets the MII know if the MAC layer can support pause or
* asymetric pause capabilities. The MII layer will use this to
* determine what capabilities should be negotiated for (along
* with user preferences, of course.) If not called, the MII
* will assume the device has no support for flow control.
*
* Arguments
*
* mii MII handle.
* cap B_TRUE if the device supports symmetric of pause.
* asym B_TRUE if the device supports asymmetric pause.
*/
void mii_set_pauseable(mii_handle_t mii, boolean_t cap, boolean_t asym);
/*
* mii_reset
*
* Schedules a reset of the MII bus. Normally not needed, but
* can be used to perform a full master reset, including
* rescanning for PHYs. This function may be called in any
* context except high level interrupt context, but must be
* called without any locks held. The reset will probably not
* be complete until sometime after the call returns.
*
* Note that if mii_start has not been called, then the reset
* will not be performed until _after_ the MII is started.
*/
void mii_reset(mii_handle_t mii);
/*
* mii_start
*
* Starts monitoring of the MII bus. Normally this is called as
* a result of a driver's mac_start() entry point, but it may also
* be called when a PHY needs to be reset or during handling of
* DDI_RESUME. This function may be called in any context except
* high level interrupt context, but
* must be called without any locks held.
*/
void mii_start(mii_handle_t mii);
/*
* mii_stop
*
* Stops monitoring of the MII bus. Normally this is called as a
* result of a driver's mac_stop() entry point. As a side
* effect, also isolates and powers down any active PHY. On
* return, the MII layer is guaranteed not to be executing any
* code in the MII entry points. This function may be called in
* any context except high level interrupt context, but must be
* called without any locks held.
*/
void mii_stop(mii_handle_t mii);
/*
* mii_resume
*
* Starts monitoring of the MII bus. Normally this is called as
* a part of a driver's DDI_RESUME handling. This function may
* be called in any context except high level interrupt context,
* but must be called without any locks held.
*/
void mii_resume(mii_handle_t mii);
/*
* mii_suspend
*
* Suspends monitoring of the MII bus. Normally this is called
* as a part of a driver's DDI_SUSPEND handling. On return, the
* MII layer is guaranteed not to be executing any code in the
* MII entry points. This function may be called in any context
* except high level interrupt context, but must be called
* without any locks held.
*/
void mii_suspend(mii_handle_t mii);
/*
* mii_probe
*
* Used to reset the entire MII bus and probe for PHYs. This
* routine should be called if the driver has reason to believe that
* PHYs have changed. This is implicitly executed the first time
* monitoring is started on the MII bus, and normally need not be
* explicitly called. This function may be called in any context
* except high level interrupt context, but must be called
* without any locks held.
*/
void mii_probe(mii_handle_t mii);
/*
* mii_check
*
* Used to alert the MII layer that it should check for changes.
* This can be called by drivers in response to link status
* interrupts, for example, giving a quicker response to link
* status changes without waiting for the MII timer to expire.
* This function may be called in any context except high level
* interrupt context, but must be called without any locks held.
*/
void mii_check(mii_handle_t mii);
/*
* mii_get_addr
*
* Used to get the PHY address that is currently active for the MII
* bus. This function may be called in any context.
*
* Returns
*
* The PHY address (0-31) if a PHY is active on the MII bus. If
* no PHY is active, -1 is returned.
*/
int mii_get_addr(mii_handle_t mii);
/*
* mii_get_id
*
* Used to get the identifier of the active PHY. This function
* may be called in any context.
*
* Returns
*
* The PHY identifier register contents, encoded with the high
* order (PHYIDH) bits in the upper word and the low order bits
* in the lower word. If no PHY is active, the value -1 will be
* returned.
*/
uint32_t mii_get_id(mii_handle_t mii);
/*
* mii_get_speed
*
* Used to get the speed of the active PHY. This function may be
* called in any context.
*
* Returns
*
* The speed, in Mbps, if the active PHY has link (10, 100, or 1000),
* otherwise 0.
*/
int mii_get_speed(mii_handle_t mii);
/*
* mii_get_duplex
*
* Used to get the duplex of the active PHY. This function may
* be called in any context.
*
* Returns
*
* The duplex, if the active PHY has link (LINK_DUPLEX_FULL or
* LINK_DUPLEX_HALF), otherwise LINK_DUPLEX_UNKNOWN.
*/
link_duplex_t mii_get_duplex(mii_handle_t mii);
/*
* mii_get_state
*
* Used to get the state of the link on the active PHY. This
* function may be called in any context.
*
* Returns
*
* The link state (LINK_STATE_UP or LINK_STATE_DOWN), if known,
* otherwise LINK_STATE_UNKNOWN.
*/
link_state_t mii_get_state(mii_handle_t mii);
/*
* mii_get_flowctrl
*
* Used to get the state of the negotiated flow control on the
* active PHY. This function may be called in any context.
*
* Returns
*
* The flowctrl state (LINK_FLOWCTRL_NONE, LINK_FLOWCTRL_RX,
* LINK_FLOWCTRL_TX, or LINK_FLOWCTRL_BI.
*/
link_flowctrl_t mii_get_flowctrl(mii_handle_t mii);
/*
* mii_get_loopmodes
*
* This function is used to support the LB_GET_INFO_SIZE and
* LB_GET_INFO ioctls. It probably should not be used outside of
* that context. The modes supplied are supported by the MII/PHY.
* Drivers may wish to add modes for MAC internal loopbacks as well.
* See <sys/netlb.h> for more information.
*
* Note that the first item in the modes array will always be the
* mode to disable the MII/PHY loopback, and will have the value
* MII_LOOPBACK_NONE.
*
* Arguments
*
* mii MII handle.
* modes Location to receive an array of loopback modes.
* Drivers should ensure that enough room is available.
* There will never be more than MII_LOOPBACK_MAX modes
* returned. May be NULL, in which case no data will
* be returned to the caller.
*
* Returns
*
* Count of number of modes available, in no case larger than
* MII_LOOPBACK_MAX.
*/
int mii_get_loopmodes(mii_handle_t mii, lb_property_t *modes);
#define MII_LOOPBACK_MAX 16
#define MII_LOOPBACK_NONE 0
/*
* mii_set_loopback
*
* Sets the loopback mode, intended for use in support of the
* LB_SET_MODE ioctl. The mode value will be one of the values
* returned in the modes array (see mii_get_loopmodes), or the
* special value MII_LOOPBACK_NONE to return to normal operation.
*
* Arguments
*
* mii MII handle.
* mode New loopback mode number; MII_LOOPBACK_NONE indicates
* a return to normal operation.
*
* Returns
*
* Zero on success, or EINVAL if the mode is invalid or unsupported.
*/
int mii_set_loopback(mii_handle_t mii, uint32_t mode);
/*
* mii_get_loopback
*
* Queries the loopback mode, intended for use in support of the
* LB_GET_MODE ioctl, but may be useful in programming device
* settings that are sensitive to loopback setting.
*
* Returns
*
* The current mode number (one of the reported by
* mii_get_loopmodes), or the special value MII_LOOPBACK_NONE
* indicating that loopback is not in use.
*/
uint32_t mii_get_loopback(mii_handle_t mii);
/*
* mii_m_loop_ioctl
*
* Used to support the driver's mc_ioctl() for loopback ioctls.
* If the driver is going to use the loopback optons from the
* PHY, and isn't adding any MAC level loopback, then this function
* can handle the entire set of ioctls, removing yet more code from
* the driver. Ultimately, this is a very reasonable thing to do,
* since the PHY level loopback should exercise all of the same
* MAC level circuitry that a MAC internal loopback would do.
*
* Arguments
*
* mii MII handle.
* wq The write queue supplied to mc_ioctl().
* msg The mblk from the mc_ioctl (contains an iocblk).
*
* Returns
*
* B_TRUE if the ioctl was handled by the driver.
* B_FALSE if the ioctl was not handled, and may need to be
* handled by the driver.
*/
boolean_t mii_m_loop_ioctl(mii_handle_t mii, queue_t *wq, mblk_t *msg);
/*
* mii_m_getprop
*
* Used to support the driver's mc_getprop() mac callback,
* and only to be called from that function (and without any
* locks held). This routine will process all of the properties
* that are relevant to MII on behalf of the driver.
*
* Arguments
*
* mii MII handle.
* name Property name.
* id Property ID.
* flags Property flags (MAC_PROP_DEFAULT).
* sz Size of property in bytes.
* val Location to receive property value.
* perm Location to receive property permissions (either
* MAC_PROP_PERM_READ or MAC_PROP_PERM_RW).
*
* Returns
*
* 0 on successful handling of property.
* EINVAL if invalid arguments (e.g. a bad size) are supplied.
* ENOTSUP if the prooperty is not supported by MII or the PHY.
*/
int mii_m_getprop(mii_handle_t mii, const char *name, mac_prop_id_t id,
uint_t flags, uint_t sz, void *val, uint_t *perm);
/*
* mii_m_setprop
*
* Used to support the driver's mc_setprop() mac callback,
* and only to be called from that function (and without any
* locks held). This routine will process all of the properties
* that are relevant to MII on behalf of the driver. This will
* often result in the PHY being reset.
*
* Arguments
*
* mii MII handle.
* name Property name.
* id Property ID.
* sz Size of property in bytes.
* val Location of property value.
*
* Returns
*
* 0 on successful handling of property.
* EINVAL if invalid arguments (e.g. a bad size) are supplied.
* ENOTSUP if the prooperty is not supported by MII or the PHY,
* or if the property is read-only.
*/
int mii_m_setprop(mii_handle_t mii, const char *name, mac_prop_id_t id,
uint_t sz, const void *val);
/*
* mii_m_getstat
*
* Used to support the driver's mc_getstat() mac callback for
* statistic collection, and only to be called from that function
* (without any locks held). This routine will process all of
* the statistics that are relevant to MII on behalf of the
* driver.
*
* Arguments
*
* mii MII handle.
* stat Statistic number.
* val Location to receive statistic value.
*
* Returns
*
* 0 on successful handling of statistic.
* ENOTSUP if the statistic is not supported by MII.
*/
int mii_m_getstat(mii_handle_t mii, uint_t stat, uint64_t *val);
#endif /* _KERNEL */
#ifdef __cplusplus
}
#endif
#endif /* _SYS_MII_H */