1321936Shselasky/*
2321936Shselasky * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
3321936Shselasky *
4321936Shselasky * This software is available to you under a choice of one of two
5321936Shselasky * licenses.  You may choose to be licensed under the terms of the GNU
6321936Shselasky * General Public License (GPL) Version 2, available from the file
7321936Shselasky * COPYING in the main directory of this source tree, or the
8321936Shselasky * OpenIB.org BSD license below:
9321936Shselasky *
10321936Shselasky *     Redistribution and use in source and binary forms, with or
11321936Shselasky *     without modification, are permitted provided that the following
12321936Shselasky *     conditions are met:
13321936Shselasky *
14321936Shselasky *      - Redistributions of source code must retain the above
15321936Shselasky *        copyright notice, this list of conditions and the following
16321936Shselasky *        disclaimer.
17321936Shselasky *
18321936Shselasky *      - Redistributions in binary form must reproduce the above
19321936Shselasky *        copyright notice, this list of conditions and the following
20321936Shselasky *        disclaimer in the documentation and/or other materials
21321936Shselasky *        provided with the distribution.
22321936Shselasky *
23321936Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24321936Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25321936Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26321936Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27321936Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28321936Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29321936Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30321936Shselasky * SOFTWARE.
31321936Shselasky *
32321936Shselasky */
33321936Shselasky
34321936Shselasky#if HAVE_CONFIG_H
35321936Shselasky#  include <config.h>
36321936Shselasky#endif				/* HAVE_CONFIG_H */
37321936Shselasky
38321936Shselasky#include <stdio.h>
39321936Shselasky#include <stdlib.h>
40321936Shselasky#include <string.h>
41321936Shselasky#include <errno.h>
42321936Shselasky
43321936Shselasky#include <infiniband/umad.h>
44321936Shselasky#include <infiniband/mad.h>
45321936Shselasky
46321936Shselasky#include "mad_internal.h"
47321936Shselasky
48321936Shselasky#undef DEBUG
49321936Shselasky#define DEBUG	if (ibdebug)	IBWARN
50321936Shselasky
51321936Shselaskystatic int mgmt_class_vers(int mgmt_class)
52321936Shselasky{
53321936Shselasky	if ((mgmt_class >= IB_VENDOR_RANGE1_START_CLASS &&
54321936Shselasky	     mgmt_class <= IB_VENDOR_RANGE1_END_CLASS) ||
55321936Shselasky	    (mgmt_class >= IB_VENDOR_RANGE2_START_CLASS &&
56321936Shselasky	     mgmt_class <= IB_VENDOR_RANGE2_END_CLASS))
57321936Shselasky		return 1;
58321936Shselasky
59321936Shselasky	switch (mgmt_class) {
60321936Shselasky	case IB_SMI_CLASS:
61321936Shselasky	case IB_SMI_DIRECT_CLASS:
62321936Shselasky		return 1;
63321936Shselasky	case IB_SA_CLASS:
64321936Shselasky		return 2;
65321936Shselasky	case IB_PERFORMANCE_CLASS:
66321936Shselasky		return 1;
67321936Shselasky	case IB_DEVICE_MGMT_CLASS:
68321936Shselasky		return 1;
69321936Shselasky	case IB_CC_CLASS:
70321936Shselasky		return 2;
71321936Shselasky	case IB_BOARD_MGMT_CLASS:
72321936Shselasky		return 1;
73321936Shselasky	}
74321936Shselasky
75321936Shselasky	return 0;
76321936Shselasky}
77321936Shselasky
78321936Shselaskyint mad_class_agent(int mgmt)
79321936Shselasky{
80321936Shselasky	if (mgmt < 1 || mgmt >= MAX_CLASS)
81321936Shselasky		return -1;
82321936Shselasky	return ibmp->class_agents[mgmt];
83321936Shselasky}
84321936Shselasky
85321936Shselaskyint mad_register_port_client(int port_id, int mgmt, uint8_t rmpp_version)
86321936Shselasky{
87321936Shselasky	int vers, agent;
88321936Shselasky
89321936Shselasky	if ((vers = mgmt_class_vers(mgmt)) <= 0) {
90321936Shselasky		DEBUG("Unknown class %d mgmt_class", mgmt);
91321936Shselasky		return -1;
92321936Shselasky	}
93321936Shselasky
94321936Shselasky	agent = umad_register(port_id, mgmt, vers, rmpp_version, 0);
95321936Shselasky	if (agent < 0)
96321936Shselasky		DEBUG("Can't register agent for class %d", mgmt);
97321936Shselasky
98321936Shselasky	return agent;
99321936Shselasky}
100321936Shselasky
101321936Shselaskyint mad_register_client(int mgmt, uint8_t rmpp_version)
102321936Shselasky{
103321936Shselasky	return mad_register_client_via(mgmt, rmpp_version, ibmp);
104321936Shselasky}
105321936Shselasky
106321936Shselaskyint mad_register_client_via(int mgmt, uint8_t rmpp_version,
107321936Shselasky			    struct ibmad_port *srcport)
108321936Shselasky{
109321936Shselasky	int agent;
110321936Shselasky
111321936Shselasky	if (!srcport)
112321936Shselasky		return -1;
113321936Shselasky
114321936Shselasky	agent = mad_register_port_client(mad_rpc_portid(srcport), mgmt,
115321936Shselasky					 rmpp_version);
116321936Shselasky	if (agent < 0)
117321936Shselasky		return agent;
118321936Shselasky
119321936Shselasky	srcport->class_agents[mgmt] = agent;
120321936Shselasky	return 0;
121321936Shselasky}
122321936Shselasky
123321936Shselaskyint mad_register_server(int mgmt, uint8_t rmpp_version,
124321936Shselasky			long method_mask[], uint32_t class_oui)
125321936Shselasky{
126321936Shselasky	return mad_register_server_via(mgmt, rmpp_version, method_mask,
127321936Shselasky				       class_oui, ibmp);
128321936Shselasky}
129321936Shselasky
130321936Shselaskyint mad_register_server_via(int mgmt, uint8_t rmpp_version,
131321936Shselasky			    long method_mask[], uint32_t class_oui,
132321936Shselasky			    struct ibmad_port *srcport)
133321936Shselasky{
134321936Shselasky	long class_method_mask[16 / sizeof(long)];
135321936Shselasky	uint8_t oui[3];
136321936Shselasky	int agent, vers;
137321936Shselasky
138321936Shselasky	if (method_mask)
139321936Shselasky		memcpy(class_method_mask, method_mask,
140321936Shselasky		       sizeof class_method_mask);
141321936Shselasky	else
142321936Shselasky		memset(class_method_mask, 0xff, sizeof(class_method_mask));
143321936Shselasky
144321936Shselasky	if (!srcport)
145321936Shselasky		return -1;
146321936Shselasky
147321936Shselasky	if (srcport->class_agents[mgmt] >= 0) {
148321936Shselasky		DEBUG("Class 0x%x already registered %d",
149321936Shselasky		      mgmt, srcport->class_agents[mgmt]);
150321936Shselasky		return -1;
151321936Shselasky	}
152321936Shselasky	if ((vers = mgmt_class_vers(mgmt)) <= 0) {
153321936Shselasky		DEBUG("Unknown class 0x%x mgmt_class", mgmt);
154321936Shselasky		return -1;
155321936Shselasky	}
156321936Shselasky	if (mgmt >= IB_VENDOR_RANGE2_START_CLASS &&
157321936Shselasky	    mgmt <= IB_VENDOR_RANGE2_END_CLASS) {
158321936Shselasky		oui[0] = (class_oui >> 16) & 0xff;
159321936Shselasky		oui[1] = (class_oui >> 8) & 0xff;
160321936Shselasky		oui[2] = class_oui & 0xff;
161321936Shselasky		if ((agent =
162321936Shselasky		     umad_register_oui(srcport->port_id, mgmt, rmpp_version,
163321936Shselasky				       oui, class_method_mask)) < 0) {
164321936Shselasky			DEBUG("Can't register agent for class %d", mgmt);
165321936Shselasky			return -1;
166321936Shselasky		}
167321936Shselasky	} else
168321936Shselasky	    if ((agent =
169321936Shselasky		 umad_register(srcport->port_id, mgmt, vers, rmpp_version,
170321936Shselasky			       class_method_mask)) < 0) {
171321936Shselasky		DEBUG("Can't register agent for class %d", mgmt);
172321936Shselasky		return -1;
173321936Shselasky	}
174321936Shselasky
175321936Shselasky	srcport->class_agents[mgmt] = agent;
176321936Shselasky
177321936Shselasky	return agent;
178321936Shselasky}
179