1/*
2 * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses.  You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 *     Redistribution and use in source and binary forms, with or
11 *     without modification, are permitted provided that the following
12 *     conditions are met:
13 *
14 *      - Redistributions of source code must retain the above
15 *        copyright notice, this list of conditions and the following
16 *        disclaimer.
17 *
18 *      - Redistributions in binary form must reproduce the above
19 *        copyright notice, this list of conditions and the following
20 *        disclaimer in the documentation and/or other materials
21 *        provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 *
32 */
33
34#if HAVE_CONFIG_H
35#  include <config.h>
36#endif				/* HAVE_CONFIG_H */
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <errno.h>
42
43#include <infiniband/umad.h>
44#include <infiniband/mad.h>
45
46#include "mad_internal.h"
47
48#undef DEBUG
49#define DEBUG	if (ibdebug)	IBWARN
50
51static int mgmt_class_vers(int mgmt_class)
52{
53	if ((mgmt_class >= IB_VENDOR_RANGE1_START_CLASS &&
54	     mgmt_class <= IB_VENDOR_RANGE1_END_CLASS) ||
55	    (mgmt_class >= IB_VENDOR_RANGE2_START_CLASS &&
56	     mgmt_class <= IB_VENDOR_RANGE2_END_CLASS))
57		return 1;
58
59	switch (mgmt_class) {
60	case IB_SMI_CLASS:
61	case IB_SMI_DIRECT_CLASS:
62		return 1;
63	case IB_SA_CLASS:
64		return 2;
65	case IB_PERFORMANCE_CLASS:
66		return 1;
67	case IB_DEVICE_MGMT_CLASS:
68		return 1;
69	case IB_CC_CLASS:
70		return 2;
71	case IB_BOARD_MGMT_CLASS:
72		return 1;
73	}
74
75	return 0;
76}
77
78int mad_class_agent(int mgmt)
79{
80	if (mgmt < 1 || mgmt >= MAX_CLASS)
81		return -1;
82	return ibmp->class_agents[mgmt];
83}
84
85int mad_register_port_client(int port_id, int mgmt, uint8_t rmpp_version)
86{
87	int vers, agent;
88
89	if ((vers = mgmt_class_vers(mgmt)) <= 0) {
90		DEBUG("Unknown class %d mgmt_class", mgmt);
91		return -1;
92	}
93
94	agent = umad_register(port_id, mgmt, vers, rmpp_version, 0);
95	if (agent < 0)
96		DEBUG("Can't register agent for class %d", mgmt);
97
98	return agent;
99}
100
101int mad_register_client(int mgmt, uint8_t rmpp_version)
102{
103	return mad_register_client_via(mgmt, rmpp_version, ibmp);
104}
105
106int mad_register_client_via(int mgmt, uint8_t rmpp_version,
107			    struct ibmad_port *srcport)
108{
109	int agent;
110
111	if (!srcport)
112		return -1;
113
114	agent = mad_register_port_client(mad_rpc_portid(srcport), mgmt,
115					 rmpp_version);
116	if (agent < 0)
117		return agent;
118
119	srcport->class_agents[mgmt] = agent;
120	return 0;
121}
122
123int mad_register_server(int mgmt, uint8_t rmpp_version,
124			long method_mask[], uint32_t class_oui)
125{
126	return mad_register_server_via(mgmt, rmpp_version, method_mask,
127				       class_oui, ibmp);
128}
129
130int mad_register_server_via(int mgmt, uint8_t rmpp_version,
131			    long method_mask[], uint32_t class_oui,
132			    struct ibmad_port *srcport)
133{
134	long class_method_mask[16 / sizeof(long)];
135	uint8_t oui[3];
136	int agent, vers;
137
138	if (method_mask)
139		memcpy(class_method_mask, method_mask,
140		       sizeof class_method_mask);
141	else
142		memset(class_method_mask, 0xff, sizeof(class_method_mask));
143
144	if (!srcport)
145		return -1;
146
147	if (srcport->class_agents[mgmt] >= 0) {
148		DEBUG("Class 0x%x already registered %d",
149		      mgmt, srcport->class_agents[mgmt]);
150		return -1;
151	}
152	if ((vers = mgmt_class_vers(mgmt)) <= 0) {
153		DEBUG("Unknown class 0x%x mgmt_class", mgmt);
154		return -1;
155	}
156	if (mgmt >= IB_VENDOR_RANGE2_START_CLASS &&
157	    mgmt <= IB_VENDOR_RANGE2_END_CLASS) {
158		oui[0] = (class_oui >> 16) & 0xff;
159		oui[1] = (class_oui >> 8) & 0xff;
160		oui[2] = class_oui & 0xff;
161		if ((agent =
162		     umad_register_oui(srcport->port_id, mgmt, rmpp_version,
163				       oui, class_method_mask)) < 0) {
164			DEBUG("Can't register agent for class %d", mgmt);
165			return -1;
166		}
167	} else
168	    if ((agent =
169		 umad_register(srcport->port_id, mgmt, vers, rmpp_version,
170			       class_method_mask)) < 0) {
171		DEBUG("Can't register agent for class %d", mgmt);
172		return -1;
173	}
174
175	srcport->class_agents[mgmt] = agent;
176
177	return agent;
178}
179