libdlpi.c revision 3ab45760e29dbab3ec3197fc452899c4d4b1c4c4
0N/A * The contents of this file are subject to the terms of the 0N/A * Common Development and Distribution License (the "License"). 0N/A * You may not use this file except in compliance with the License. 0N/A * See the License for the specific language governing permissions 0N/A * and limitations under the License. 0N/A * When distributing Covered Code, include this CDDL HEADER in each 0N/A * If applicable, add the following below this CDDL HEADER, with the 0N/A * fields enclosed by brackets "[]" replaced with your own identifying 0N/A * information: Portions Copyright [yyyy] [name of copyright owner] 0N/A * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 0N/A * Use is subject to license terms. 0N/A#
pragma ident "%Z%%M% %I% %E% SMI" 0N/A * Data-Link Provider Interface (Version 2) 0N/A * Validate linkname, fail if logical unit number (lun) is specified, 0N/A * otherwise decompose the contents into ifsp. 0N/A /* Allocate a new dlpi_impl_t. */ 0N/A /* Copy linkname provided to the function. */ 0N/A /* Copy provider name. */ 0N/A * Special case: DLPI_SERIAL flag is set to indicate a synchronous 0N/A * serial line interface (see syncinit(1M), syncstat(1M), 0N/A * syncloop(1M)), which is not a DLPI link. 0N/A * We intentionally do not care if this request fails, as this 0N/A * indicates the underlying DLPI device does not support Native mode 0N/A * (pre-GLDV3 device drivers). 0N/A * NOTE: The opt argument must be zero and is reserved for future use to extend 0N/A * fields to the dlpi_info_t structure (see dlpi_info(3DLPI)). /* Set QoS range parameters to default unsupported value. */ /* Set QoS parameters to default unsupported value. */ /* Check and save QoS selection information, if any. */ /* Check and save QoS range information, if any. */ /* Check and save physical address and SAP information. */ /* Check and save broadcast address information, if any. */ /* Information retrieved from the handle. */ * This function parses 'linkname' and stores the 'provider' name and 'PPA'. * This function takes a provider name and a PPA and stores a full linkname * as 'linkname'. If 'provider' already is a full linkname 'provider' name * is stored in 'linkname'. * If 'sap' is DLPI_ANY_SAP, bind to SAP 2 on token ring, else 0 on * other interface types (SAP 0 has special significance on token ring). * Received a DLPI_BIND_ACK, now verify that the bound SAP * is equal to the SAP requested. Some DLPI MAC type may bind * to a different SAP than requested, in this case 'boundsap' * returns the actual bound SAP. For the case where 'boundsap' * is NULL and 'sap' is not DLPI_ANY_SAP, dlpi_bind fails. * This function is invoked by dlpi_enabmulti() or dlpi_disabmulti() and * This function is invoked by dlpi_promiscon() or dlpi_promiscoff(). Based * on the value of 'op', promiscuous mode is turned on/off at the specified /* Received DL_PHYS_ADDR_ACK, store the physical address and length. */ /* Set priority to default priority range. */ /* Use SAP value if specified otherwise use bound SAP value. */ * Since `daddrp' only has the link-layer destination address, * we must prepend or append the SAP (according to dli_sapbefore) * to make a full DLPI address. * If handle is in raw mode ignore everything except total message * If DLPI link provides source address, store source address in * 'saddrp' and source length in 'saddrlenp', else set saddrlenp to 0. * If destination address requested, check and save destination /* Register notification information. */ /* Insert notification node at head */ /* Walk the notifyentry list to find matching id. */ /* Delete node if callbacks are not being processed. */ * Returns DLPI style stored in the handle. * Note: This function is used for test purposes only. Do not remove without * fixing the DLPI testsuite. * This function attempts to open linkname under the following namespaces: * If open doesn't succeed and link doesn't exist (ENOENT), this function * returns DLPI_ENOLINK, otherwise returns DL_SYSERR. * On diskless boot, it's possible the /dev links have not yet * been created; fallback to /devices. When /dev links are * created on demand, this code can be removed. * Open a style 1 link. PPA is implicitly attached. * In order to support open of syntax like device[.module[.module...]] * where modules need to be pushed onto the device stream, open only * device name, otherwise open the full linkname. * Try to push modules (if any) onto the device stream. If I_PUSH * fails, we increment count of modules pushed (dli_mod_pushed) * expecting it is last module to be pushed and thus will be pushed * in i_dlpi_style2_open(). * Open a style 2 link. PPA must be explicitly attached. * If style 1 open failed, we need to determine how far it got and * finish up the open() call as a style 2 open. * If no modules were pushed (mod_pushed == 0), then we need to * open it as a style 2 link. * If the pushing of the last module failed, we need to * try pushing it as a style 2 module. Decrement dli_mod_pushed * count so it can be pushed onto the stream. * Otherwise we failed during the push of an intermediate module and * must fail out and close the link. /* Try and push modules (if any) onto the device stream. */ * Special case: DLPI_SERIAL flag (synchronous serial lines) is not a * DLPI link so attach and ignore rest. * Succeeded opening the link and verified it is style2. Now attach to * PPA only if DLPI_NOATTACH is not set. * Verify with DLPI that the link is the expected DLPI 'style' device, * dlpi_info sets the DLPI style in the DLPI handle. * Remove PPA from end of linkname. * Return DLPI_SUCCESS if found, else return DLPI_FAILURE. * For DLPI style 2 providers, an explicit attach of PPA is required. * Special case: DLPI_SERIAL flag (synchronous serial lines) * is not a DLPI link so ignore DLPI style. * Enable DLPI passive mode on a DLPI handle. We intentionally do not care * if this request fails, as this indicates the underlying DLPI device does * not support link aggregation (pre-GLDV3 device drivers), and thus will * see the expected behavior without failing with DL_SYSERR/EBUSY when issuing * DLPI primitives like DL_BIND_REQ. For further info see dlpi(7p). * Send a dlpi control message and/or data message on a stream. The inputs * dlpi_impl_t *dip: internal dlpi handle to open stream * const dlpi_msg_t *dlreqp: request message structure * void *databuf: data buffer * size_t datalen: data buffer len * int flags: flags to set for putmsg() * Returns DLPI_SUCCESS if putmsg() succeeds, otherwise DL_SYSERR on failure. * Get a DLPI control message and/or data message from a stream. The inputs * dlpi_impl_t *dip: internal dlpi handle * int msec: timeout to wait for message * dlpi_msg_t *dlreplyp: reply message structure, the message size * member on return stores actual size received * t_uscalar_t dlreqprim: requested primitive * t_uscalar_t dlreplyprim:acknowledged primitive in response to request * size_t dlreplyminsz: minimum size of acknowledged primitive size * void *databuf: data buffer * size_t *datalenp: data buffer len * size_t *totdatalenp: total data received. Greater than 'datalenp' if * actual data received is larger than 'databuf' * Function returns DLPI_SUCCESS if requested message is retrieved * otherwise returns error code or timeouts. If a notification arrives on * the stream the callback is notified. However, error returned during the * handling of notification is ignored as it would be confusing to actual caller * The supplied DLPI_CHUNKSIZE sized buffers are large enough * to retrieve all valid DLPI responses in one iteration. * If MORECTL or MOREDATA is set, we are not interested in the * remainder of the message. Temporary buffers are used to * drain the remainder of this message. * The special case we have to account for is if * a higher priority messages is enqueued whilst handling * this condition. We use a change in the flags parameter * returned by getmsg() to indicate the message has changed. * In the special case of higher priority * message received, the low priority message * received earlier is discarded, if no data * or control message is left. * Check if DL_NOTIFY_IND message received. If there is one, * notify the callback function(s) and continue processing the * If we were expecting a data message, and we got one, set * *datalenp. If we aren't waiting on a control message, then * If we were expecting a control message, and the message * we received is at least big enough to be a DLPI message, * then verify it's a reply to something we sent. If it * is a reply to something we sent, also verify its size. * Common routine invoked by all DLPI control routines. The inputs for this * dlpi_impl_t *dip: internal dlpi handle * const dlpi_msg_t *dlreqp: request message structure * dlpi_msg_t *dlreplyp: reply message structure * size_t dlreplyminsz: minimum size of reply primitive * int flags: flags to be set to send a message * message. However, if DLPI notification has been enabled via * dlpi_enabnotify(), DL_NOTIFY_IND messages are handled before handling * expected messages. Otherwise, any other unexpected asynchronous messages will /* Put the requested primitive on the stream. */ /* Retrieve acknowledged message for requested primitive. */ * If primitive is DL_ERROR_ACK, set errno. "bad LSAP selector",
/* DL_BADSAP 0x00 */ "DLSAP address in improper format or invalid",
/* DL_BADADDR 0x01 */ "improper permissions for request",
/* DL_ACCESS 0x02 */ "primitive issued in improper state",
/* DL_OUTSTATE 0x03 */ NULL,
/* DL_SYSERR 0x04 */ "sequence number not from outstanding DL_CONN_IND",
"user data exceeded provider limit",
/* DL_BADDATA 0x06 */ "requested service not supplied by provider",
/* DL_UNSUPPORTED 0x07 */ "specified PPA was invalid",
/* DL_BADPPA 0x08 */ "primitive received not known by provider",
/* DL_BADPRIM 0x09 */ "QoS parameters contained invalid values",
/* DL_BADQOSPARAM 0x0a */ "token used not an active stream",
/* DL_BADTOKEN 0x0c */ "attempted second bind with dl_max_conind",
/* DL_BOUND 0x0d */ "physical link initialization failed",
/* DL_INITFAILED 0x0e */ "provider couldn't allocate alternate address",
/* DL_NOADDR 0x0f */ "physical link not initialized",
/* DL_NOTINIT 0x10 */ "previous data unit could not be delivered",
/* DL_UNDELIVERABLE 0x11 */ "primitive is known but unsupported",
/* DL_NOTSUPPORTED 0x12 */ "limit exceeded",
/* DL_TOOMANY 0x13 */ "promiscuous mode not enabled",
/* DL_NOTENAB 0x14 */ "other streams for PPA in post-attached",
/* DL_BUSY 0x15 */ "automatic handling XID&TEST unsupported",
/* DL_NOAUTO 0x16 */ "automatic handling of XID unsupported",
/* DL_NOXIDAUTO 0x17 */ "automatic handling of TEST unsupported",
/* DL_NOTESTAUTO 0x18 */ "automatic handling of XID response",
/* DL_XIDAUTO 0x19 */ "automatic handling of TEST response",
/* DL_TESTAUTO 0x1a */ "pending outstanding connect indications" /* DL_PENDING 0x1b */ "DLPI operation succeeded",
/* DLPI_SUCCESS */ "invalid argument",
/* DLPI_EINVAL */ "invalid DLPI linkname",
/* DLPI_ELINKNAMEINVAL */ "DLPI link does not exist",
/* DLPI_ENOLINK */ "bad DLPI link",
/* DLPI_EBADLINK */ "invalid DLPI handle",
/* DLPI_EINHANDLE */ "DLPI operation timed out",
/* DLPI_ETIMEDOUT */ "unsupported DLPI version",
/* DLPI_EVERNOTSUP */ "unsupported DLPI connection mode",
/* DLPI_EMODENOTSUP */ "unavailable DLPI SAP",
/* DLPI_EUNAVAILSAP */ "DLPI operation failed",
/* DLPI_FAILURE */ "DLPI style-2 node reports style-1",
/* DLPI_ENOTSTYLE2 */ "bad DLPI message",
/* DLPI_EBADMSG */ "DLPI raw mode not supported",
/* DLPI_ERAWNOTSUP */ "DLPI notification not supported by link",
"invalid DLPI notification type",
/* DLPI_ENOTEINVAL */ "invalid DLPI notification id" /* DLPI_ENOTEIDINVAL */ * Each table entry comprises a DLPI/Private mactype and the description. {
DL_FC,
"Fiber Channel" },
return (
"Unknown MAC Type");
* Each table entry comprises a DLPI primitive and the maximum buffer * size needed, in bytes, for the DLPI message (see <sys/dlpi.h> for details). * Refers to the dlpi_primsizes[] table to return corresponding maximum * sap values vary in length and are in host byte order, build sap value * by writing saplen bytes, so that the sap value is left aligned. for (i =
saplen -
1; i >= 0; i--) {
for (i = 0; i <
saplen; i++) {
* Copy sap value to a buffer in host byte order. saplen is the number of * Fill notification payload and callback each registered functions. * Delete nodes if any was called while processing. /* Walk the notifyentry list to unregister marked entries. */ * Find registered notification. * Walk the list of notifications and deleted nodes marked to be deleted.