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#include    <sun_sas.h>
30
31/*
32 * Retrieves the attributes for a specified port of an adapter
33 */
34HBA_STATUS
35Sun_sasGetAdapterPortAttributes(HBA_HANDLE handle, HBA_UINT32 port,
36    PSMHBA_PORTATTRIBUTES attributes)
37{
38	const char		ROUTINE[] = "Sun_sasGetAdapterPortAttributes";
39	HBA_STATUS		status;
40	struct sun_sas_hba	*hba_ptr;
41	struct sun_sas_port	*hba_port_ptr;
42	int			index;
43
44	/* Validate the arguments */
45	if ((attributes == NULL) ||
46	    (attributes->PortSpecificAttribute.SASPort == NULL)) {
47		log(LOG_DEBUG, ROUTINE, "NULL attributes");
48		return (HBA_STATUS_ERROR_ARG);
49	}
50
51	lock(&all_hbas_lock);
52	index = RetrieveIndex(handle);
53	lock(&open_handles_lock);
54	hba_ptr = RetrieveHandle(index);
55	if (hba_ptr == NULL) {
56		log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx", handle);
57		unlock(&open_handles_lock);
58		unlock(&all_hbas_lock);
59		return (HBA_STATUS_ERROR_INVALID_HANDLE);
60	}
61
62	/* Check for stale data */
63	status = verifyAdapter(hba_ptr);
64	if (status != HBA_STATUS_OK) {
65		log(LOG_DEBUG, ROUTINE, "Verify Adapter failed");
66		unlock(&open_handles_lock);
67		unlock(&all_hbas_lock);
68		return (status);
69	}
70
71	if (hba_ptr->first_port == NULL) {
72		/* This is probably an internal failure of the library */
73		if (hba_ptr->device_path[0] != '\0') {
74			log(LOG_DEBUG, ROUTINE, "Internal failure:  Adapter "
75			    "%s contains no port data", hba_ptr->device_path);
76		} else {
77			log(LOG_DEBUG, ROUTINE, "Internal failure:  Adapter at"
78			    " index %d contains no port data", hba_ptr->index);
79		}
80		unlock(&open_handles_lock);
81		unlock(&all_hbas_lock);
82		return (HBA_STATUS_ERROR);
83	}
84	for (hba_port_ptr = hba_ptr->first_port;
85	    hba_port_ptr != NULL; hba_port_ptr = hba_port_ptr->next) {
86		if (hba_port_ptr->index == port) {
87			break;
88		}
89	}
90	if (hba_port_ptr == NULL || hba_port_ptr->index != port) {
91		log(LOG_DEBUG, ROUTINE,
92		    "Invalid port index %d for handle %08lx.",
93		    port, handle);
94		unlock(&open_handles_lock);
95		unlock(&all_hbas_lock);
96		return (HBA_STATUS_ERROR_ILLEGAL_INDEX);
97	}
98
99	attributes->PortType =  hba_port_ptr->port_attributes.PortType;
100	attributes->PortState =  hba_port_ptr->port_attributes.PortState;
101	(void) strlcpy(attributes->OSDeviceName,
102	    hba_port_ptr->port_attributes.OSDeviceName,
103	    sizeof (attributes->OSDeviceName));
104	(void) memcpy(attributes->PortSpecificAttribute.SASPort,
105	    hba_port_ptr->port_attributes.PortSpecificAttribute.SASPort,
106	    sizeof (struct SMHBA_SAS_Port));
107
108	unlock(&open_handles_lock);
109	unlock(&all_hbas_lock);
110
111	return (HBA_STATUS_OK);
112}
113