/* * 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 #include #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 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 */