1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26/*
27 * Copyright 2019 Joyent, Inc.
28 */
29
30#include    <sun_sas.h>
31
32/*
33 * Retrieves the attributes for a specified port discovered in the network
34 */
35HBA_STATUS
36Sun_sasGetDiscoveredPortAttributes(HBA_HANDLE handle,
37    HBA_UINT32 port, HBA_UINT32 discoveredport,
38    SMHBA_PORTATTRIBUTES *attributes)
39{
40	const char		ROUTINE[] =
41	    "Sun_sasGetDiscoveredPortAttributes";
42	HBA_STATUS		status;
43	HBA_STATUS		ret = HBA_STATUS_OK;
44	struct sun_sas_hba	*hba_ptr;
45	struct sun_sas_port	*hba_port_ptr, *hba_disco_port;
46	int			index;
47
48	if (attributes == NULL) {
49		log(LOG_DEBUG, ROUTINE,
50		    "NULL attributes argument. Handle %08lx, port %d, "
51		    "discovered port %d", handle, port, discoveredport);
52		return (HBA_STATUS_ERROR_ARG);
53	}
54
55	lock(&all_hbas_lock);
56	index = RetrieveIndex(handle);
57	lock(&open_handles_lock);
58	hba_ptr = RetrieveHandle(index);
59	if (hba_ptr == NULL) {
60		log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx.", handle);
61		unlock(&open_handles_lock);
62		unlock(&all_hbas_lock);
63		return (HBA_STATUS_ERROR_INVALID_HANDLE);
64	}
65
66	/* Check for stale data */
67	status = verifyAdapter(hba_ptr);
68	if (status != HBA_STATUS_OK) {
69		log(LOG_DEBUG, ROUTINE, "Verify Adapter failed");
70		unlock(&open_handles_lock);
71		unlock(&all_hbas_lock);
72		return (status);
73	}
74
75
76	if (hba_ptr->first_port == NULL) {
77		/* This is probably an internal failure of the library */
78		if (hba_ptr->device_path[0] != '\0') {
79			log(LOG_DEBUG, ROUTINE, "Internal failure:  Adapter %s"
80			    " contains no port data", hba_ptr->device_path);
81		} else {
82			log(LOG_DEBUG, ROUTINE, "Internal failure:  Adapter at"
83			    " index %d contains no port data", hba_ptr->index);
84		}
85		unlock(&open_handles_lock);
86		unlock(&all_hbas_lock);
87		return (HBA_STATUS_ERROR);
88	}
89
90	for (hba_port_ptr = hba_ptr->first_port;
91	    hba_port_ptr != NULL; hba_port_ptr = hba_port_ptr->next) {
92		if (hba_port_ptr->index == port) {
93			break;
94		}
95	}
96
97	if (hba_port_ptr == NULL) {
98		log(LOG_DEBUG, ROUTINE,
99		    "Invalid port index %d for handle %08lx",
100		    port, handle);
101		unlock(&open_handles_lock);
102		unlock(&all_hbas_lock);
103		return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
104	}
105
106	/* check to make sure there are devices attached to this port */
107	if (hba_port_ptr->first_attached_port != NULL) {
108		for (hba_disco_port = hba_port_ptr->first_attached_port;
109		    hba_disco_port != NULL;
110		    hba_disco_port = hba_disco_port->next) {
111			if (hba_disco_port->index == discoveredport) {
112				break;
113			}
114		}
115		if (hba_disco_port == NULL) {
116			log(LOG_DEBUG, ROUTINE,
117			    "Invalid discovered port index %d for hba port "
118			    "index %d on handle %08lx.",
119			    discoveredport, port, handle);
120			ret = HBA_STATUS_ERROR_ILLEGAL_INDEX;
121		} else {
122			attributes->PortType =
123			    hba_disco_port->port_attributes.PortType;
124			attributes->PortState =
125			    hba_disco_port->port_attributes.PortState;
126			(void) strlcpy(attributes->OSDeviceName,
127			    hba_disco_port->port_attributes.OSDeviceName,
128			    sizeof (attributes->OSDeviceName));
129			(void) memcpy(attributes->PortSpecificAttribute.SASPort,
130			    hba_disco_port->port_attributes.\
131			    PortSpecificAttribute.SASPort,
132			    sizeof (struct SMHBA_SAS_Port));
133		}
134	} else {
135		/* No ports, so we can't possibly return anything */
136		log(LOG_DEBUG, ROUTINE,
137		    "No discovered port on HBA port index %d for handle %08lx",
138		    port, handle);
139		ret = HBA_STATUS_ERROR;
140	}
141	unlock(&open_handles_lock);
142	unlock(&all_hbas_lock);
143
144	return (ret);
145}
146