1219820Sjeff/*
2219820Sjeff * Copyright (c) 2004,2005 Voltaire Inc.  All rights reserved.
3219820Sjeff *
4219820Sjeff * This software is available to you under a choice of one of two
5219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
6219820Sjeff * General Public License (GPL) Version 2, available from the file
7219820Sjeff * COPYING in the main directory of this source tree, or the
8219820Sjeff * OpenIB.org BSD license below:
9219820Sjeff *
10219820Sjeff *     Redistribution and use in source and binary forms, with or
11219820Sjeff *     without modification, are permitted provided that the following
12219820Sjeff *     conditions are met:
13219820Sjeff *
14219820Sjeff *      - Redistributions of source code must retain the above
15219820Sjeff *        copyright notice, this list of conditions and the following
16219820Sjeff *        disclaimer.
17219820Sjeff *
18219820Sjeff *      - Redistributions in binary form must reproduce the above
19219820Sjeff *        copyright notice, this list of conditions and the following
20219820Sjeff *        disclaimer in the documentation and/or other materials
21219820Sjeff *        provided with the distribution.
22219820Sjeff *
23219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30219820Sjeff * SOFTWARE.
31219820Sjeff *
32219820Sjeff */
33219820Sjeff
34219820Sjeff#if HAVE_CONFIG_H
35219820Sjeff#  include <config.h>
36219820Sjeff#endif /* HAVE_CONFIG_H */
37219820Sjeff
38219820Sjeff#include <stdio.h>
39219820Sjeff#include <stdlib.h>
40219820Sjeff#include <unistd.h>
41219820Sjeff#include <pthread.h>
42219820Sjeff#include <sys/time.h>
43219820Sjeff#include <string.h>
44219820Sjeff#include <errno.h>
45219820Sjeff
46219820Sjeff#include <infiniband/umad.h>
47219820Sjeff#include "mad.h"
48219820Sjeff
49219820Sjeff#undef DEBUG
50219820Sjeff#define DEBUG	if (ibdebug)	IBWARN
51219820Sjeff
52219820Sjeff#define MAX_CLASS	256
53219820Sjeff#define MAX_AGENTS	256
54219820Sjeff
55219820Sjeffstatic int class_agent[MAX_CLASS];
56219820Sjeffstatic int agent_class[MAX_AGENTS];
57219820Sjeff
58219820Sjeffstatic int
59219820Sjeffregister_agent(int agent, int mclass)
60219820Sjeff{
61219820Sjeff	static int initialized;
62219820Sjeff
63219820Sjeff	if (!initialized) {
64219820Sjeff		initialized++;
65219820Sjeff		memset(class_agent, 0xff, sizeof class_agent);
66219820Sjeff		memset(agent_class, 0xff, sizeof agent_class);
67219820Sjeff	}
68219820Sjeff
69219820Sjeff	if (mclass < 0 || mclass >= MAX_CLASS ||
70219820Sjeff	    agent < 0 || agent >= MAX_AGENTS) {
71219820Sjeff		DEBUG("bad mgmt class %d or agent %d", mclass, agent);
72219820Sjeff		return -1;
73219820Sjeff	}
74219820Sjeff
75219820Sjeff	class_agent[mclass] = agent;
76219820Sjeff	agent_class[agent] = mclass;
77219820Sjeff
78219820Sjeff	return 0;
79219820Sjeff}
80219820Sjeff
81219820Sjeffstatic int
82219820Sjeffmgmt_class_vers(int mgmt_class)
83219820Sjeff{
84219820Sjeff	if ((mgmt_class >= IB_VENDOR_RANGE1_START_CLASS &&
85219820Sjeff	     mgmt_class <= IB_VENDOR_RANGE1_END_CLASS) ||
86219820Sjeff	    (mgmt_class >= IB_VENDOR_RANGE2_START_CLASS &&
87219820Sjeff	     mgmt_class <= IB_VENDOR_RANGE2_END_CLASS))
88219820Sjeff		return 1;
89219820Sjeff
90219820Sjeff	switch(mgmt_class) {
91219820Sjeff		case IB_SMI_CLASS:
92219820Sjeff		case IB_SMI_DIRECT_CLASS:
93219820Sjeff			return 1;
94219820Sjeff		case IB_SA_CLASS:
95219820Sjeff			return 2;
96219820Sjeff		case IB_PERFORMANCE_CLASS:
97219820Sjeff			return 1;
98219820Sjeff		case IB_DEVICE_MGMT_CLASS:
99219820Sjeff			return 1;
100219820Sjeff		case IB_CC_CLASS:
101219820Sjeff			return 2;
102219820Sjeff	}
103219820Sjeff
104219820Sjeff	return 0;
105219820Sjeff}
106219820Sjeff
107219820Sjeffint
108219820Sjeffmad_class_agent(int mgmt)
109219820Sjeff{
110219820Sjeff	if (mgmt < 1 || mgmt > MAX_CLASS)
111219820Sjeff		return -1;
112219820Sjeff	return class_agent[mgmt];
113219820Sjeff}
114219820Sjeff
115219820Sjeffint
116219820Sjeffmad_agent_class(int agent)
117219820Sjeff{
118219820Sjeff	if (agent < 1 || agent > MAX_AGENTS)
119219820Sjeff		return -1;
120219820Sjeff	return agent_class[agent];
121219820Sjeff}
122219820Sjeff
123219820Sjeffint
124219820Sjeffmad_register_port_client(int port_id, int mgmt, uint8_t rmpp_version)
125219820Sjeff{
126219820Sjeff	int vers, agent;
127219820Sjeff
128219820Sjeff	if ((vers = mgmt_class_vers(mgmt)) <= 0) {
129219820Sjeff		DEBUG("Unknown class %d mgmt_class", mgmt);
130219820Sjeff		return -1;
131219820Sjeff	}
132219820Sjeff	if ((agent = umad_register(port_id, mgmt,
133219820Sjeff				   vers, rmpp_version, 0)) < 0) {
134219820Sjeff		DEBUG("Can't register agent for class %d", mgmt);
135219820Sjeff		return -1;
136219820Sjeff	}
137219820Sjeff
138219820Sjeff	if (mgmt < 0 || mgmt >= MAX_CLASS || agent >= MAX_AGENTS) {
139219820Sjeff		DEBUG("bad mgmt class %d or agent %d", mgmt, agent);
140219820Sjeff		return -1;
141219820Sjeff	}
142219820Sjeff
143219820Sjeff	return agent;
144219820Sjeff}
145219820Sjeff
146219820Sjeffint
147219820Sjeffmad_register_client(int mgmt, uint8_t rmpp_version)
148219820Sjeff{
149219820Sjeff	int agent;
150219820Sjeff
151219820Sjeff	agent = mad_register_port_client(madrpc_portid(), mgmt, rmpp_version);
152219820Sjeff	if (agent < 0)
153219820Sjeff		return agent;
154219820Sjeff
155219820Sjeff	return register_agent(agent, mgmt);
156219820Sjeff}
157219820Sjeff
158219820Sjeffint
159219820Sjeffmad_register_server(int mgmt, uint8_t rmpp_version,
160219820Sjeff		    long method_mask[], uint32_t class_oui)
161219820Sjeff{
162219820Sjeff	long class_method_mask[16/sizeof(long)];
163219820Sjeff	uint8_t oui[3];
164219820Sjeff	int agent, vers, mad_portid;
165219820Sjeff
166219820Sjeff	if (method_mask)
167219820Sjeff		memcpy(class_method_mask, method_mask, sizeof class_method_mask);
168219820Sjeff	else
169219820Sjeff		memset(class_method_mask, 0xff, sizeof(class_method_mask));
170219820Sjeff
171219820Sjeff	if ((mad_portid = madrpc_portid()) < 0)
172219820Sjeff		return -1;
173219820Sjeff
174219820Sjeff	if (class_agent[mgmt] >= 0) {
175219820Sjeff		DEBUG("Class 0x%x already registered", mgmt);
176219820Sjeff		return -1;
177219820Sjeff	}
178219820Sjeff	if ((vers = mgmt_class_vers(mgmt)) <= 0) {
179219820Sjeff		DEBUG("Unknown class 0x%x mgmt_class", mgmt);
180219820Sjeff		return -1;
181219820Sjeff	}
182219820Sjeff	if (mgmt >= IB_VENDOR_RANGE2_START_CLASS &&
183219820Sjeff	    mgmt <= IB_VENDOR_RANGE2_END_CLASS) {
184219820Sjeff		oui[0] = (class_oui >> 16) & 0xff;
185219820Sjeff		oui[1] = (class_oui >> 8) & 0xff;
186219820Sjeff		oui[2] = class_oui & 0xff;
187219820Sjeff		if ((agent = umad_register_oui(mad_portid, mgmt, rmpp_version,
188219820Sjeff					       oui, class_method_mask)) < 0) {
189219820Sjeff			DEBUG("Can't register agent for class %d", mgmt);
190219820Sjeff			return -1;
191219820Sjeff		}
192219820Sjeff	} else if ((agent = umad_register(mad_portid, mgmt, vers, rmpp_version,
193219820Sjeff					  class_method_mask)) < 0) {
194219820Sjeff		DEBUG("Can't register agent for class %d", mgmt);
195219820Sjeff		return -1;
196219820Sjeff	}
197219820Sjeff
198219820Sjeff	if (register_agent(agent, mgmt) < 0)
199219820Sjeff		return -1;
200219820Sjeff
201219820Sjeff	return agent;
202219820Sjeff}
203