1/*
2 * Copyright (c) 2004,2005 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 <unistd.h>
41#include <pthread.h>
42#include <sys/time.h>
43#include <string.h>
44#include <errno.h>
45
46#include <infiniband/umad.h>
47#include "mad.h"
48
49#undef DEBUG
50#define DEBUG	if (ibdebug)	IBWARN
51
52#define MAX_CLASS	256
53#define MAX_AGENTS	256
54
55static int class_agent[MAX_CLASS];
56static int agent_class[MAX_AGENTS];
57
58static int
59register_agent(int agent, int mclass)
60{
61	static int initialized;
62
63	if (!initialized) {
64		initialized++;
65		memset(class_agent, 0xff, sizeof class_agent);
66		memset(agent_class, 0xff, sizeof agent_class);
67	}
68
69	if (mclass < 0 || mclass >= MAX_CLASS ||
70	    agent < 0 || agent >= MAX_AGENTS) {
71		DEBUG("bad mgmt class %d or agent %d", mclass, agent);
72		return -1;
73	}
74
75	class_agent[mclass] = agent;
76	agent_class[agent] = mclass;
77
78	return 0;
79}
80
81static int
82mgmt_class_vers(int mgmt_class)
83{
84	if ((mgmt_class >= IB_VENDOR_RANGE1_START_CLASS &&
85	     mgmt_class <= IB_VENDOR_RANGE1_END_CLASS) ||
86	    (mgmt_class >= IB_VENDOR_RANGE2_START_CLASS &&
87	     mgmt_class <= IB_VENDOR_RANGE2_END_CLASS))
88		return 1;
89
90	switch(mgmt_class) {
91		case IB_SMI_CLASS:
92		case IB_SMI_DIRECT_CLASS:
93			return 1;
94		case IB_SA_CLASS:
95			return 2;
96		case IB_PERFORMANCE_CLASS:
97			return 1;
98		case IB_DEVICE_MGMT_CLASS:
99			return 1;
100		case IB_CC_CLASS:
101			return 2;
102	}
103
104	return 0;
105}
106
107int
108mad_class_agent(int mgmt)
109{
110	if (mgmt < 1 || mgmt > MAX_CLASS)
111		return -1;
112	return class_agent[mgmt];
113}
114
115int
116mad_agent_class(int agent)
117{
118	if (agent < 1 || agent > MAX_AGENTS)
119		return -1;
120	return agent_class[agent];
121}
122
123int
124mad_register_port_client(int port_id, int mgmt, uint8_t rmpp_version)
125{
126	int vers, agent;
127
128	if ((vers = mgmt_class_vers(mgmt)) <= 0) {
129		DEBUG("Unknown class %d mgmt_class", mgmt);
130		return -1;
131	}
132	if ((agent = umad_register(port_id, mgmt,
133				   vers, rmpp_version, 0)) < 0) {
134		DEBUG("Can't register agent for class %d", mgmt);
135		return -1;
136	}
137
138	if (mgmt < 0 || mgmt >= MAX_CLASS || agent >= MAX_AGENTS) {
139		DEBUG("bad mgmt class %d or agent %d", mgmt, agent);
140		return -1;
141	}
142
143	return agent;
144}
145
146int
147mad_register_client(int mgmt, uint8_t rmpp_version)
148{
149	int agent;
150
151	agent = mad_register_port_client(madrpc_portid(), mgmt, rmpp_version);
152	if (agent < 0)
153		return agent;
154
155	return register_agent(agent, mgmt);
156}
157
158int
159mad_register_server(int mgmt, uint8_t rmpp_version,
160		    long method_mask[], uint32_t class_oui)
161{
162	long class_method_mask[16/sizeof(long)];
163	uint8_t oui[3];
164	int agent, vers, mad_portid;
165
166	if (method_mask)
167		memcpy(class_method_mask, method_mask, sizeof class_method_mask);
168	else
169		memset(class_method_mask, 0xff, sizeof(class_method_mask));
170
171	if ((mad_portid = madrpc_portid()) < 0)
172		return -1;
173
174	if (class_agent[mgmt] >= 0) {
175		DEBUG("Class 0x%x already registered", mgmt);
176		return -1;
177	}
178	if ((vers = mgmt_class_vers(mgmt)) <= 0) {
179		DEBUG("Unknown class 0x%x mgmt_class", mgmt);
180		return -1;
181	}
182	if (mgmt >= IB_VENDOR_RANGE2_START_CLASS &&
183	    mgmt <= IB_VENDOR_RANGE2_END_CLASS) {
184		oui[0] = (class_oui >> 16) & 0xff;
185		oui[1] = (class_oui >> 8) & 0xff;
186		oui[2] = class_oui & 0xff;
187		if ((agent = umad_register_oui(mad_portid, mgmt, rmpp_version,
188					       oui, class_method_mask)) < 0) {
189			DEBUG("Can't register agent for class %d", mgmt);
190			return -1;
191		}
192	} else if ((agent = umad_register(mad_portid, mgmt, vers, rmpp_version,
193					  class_method_mask)) < 0) {
194		DEBUG("Can't register agent for class %d", mgmt);
195		return -1;
196	}
197
198	if (register_agent(agent, mgmt) < 0)
199		return -1;
200
201	return agent;
202}
203