1321936Shselasky/*
2321936Shselasky * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
3321936Shselasky * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4321936Shselasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5321936Shselasky *
6321936Shselasky * This software is available to you under a choice of one of two
7321936Shselasky * licenses.  You may choose to be licensed under the terms of the GNU
8321936Shselasky * General Public License (GPL) Version 2, available from the file
9321936Shselasky * COPYING in the main directory of this source tree, or the
10321936Shselasky * OpenIB.org BSD license below:
11321936Shselasky *
12321936Shselasky *     Redistribution and use in source and binary forms, with or
13321936Shselasky *     without modification, are permitted provided that the following
14321936Shselasky *     conditions are met:
15321936Shselasky *
16321936Shselasky *      - Redistributions of source code must retain the above
17321936Shselasky *        copyright notice, this list of conditions and the following
18321936Shselasky *        disclaimer.
19321936Shselasky *
20321936Shselasky *      - Redistributions in binary form must reproduce the above
21321936Shselasky *        copyright notice, this list of conditions and the following
22321936Shselasky *        disclaimer in the documentation and/or other materials
23321936Shselasky *        provided with the distribution.
24321936Shselasky *
25321936Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26321936Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27321936Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28321936Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29321936Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30321936Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31321936Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32321936Shselasky * SOFTWARE.
33321936Shselasky *
34321936Shselasky */
35321936Shselasky
36321936Shselasky#if HAVE_CONFIG_H
37321936Shselasky#  include <config.h>
38321936Shselasky#endif				/* HAVE_CONFIG_H */
39321936Shselasky
40321936Shselasky#include <stdlib.h>
41321936Shselasky#include <string.h>
42321936Shselasky#include <stdio.h>
43321936Shselasky#include <vendor/osm_vendor_mlx_sar.h>
44321936Shselasky
45321936Shselaskyib_api_status_t
46321936Shselaskyosmv_rmpp_sar_init(osmv_rmpp_sar_t * p_sar, void *p_arbt_mad,
47321936Shselasky		   uint32_t mad_size, boolean_t is_sa_mad)
48321936Shselasky{
49321936Shselasky	CL_ASSERT(p_sar);
50321936Shselasky	p_sar->p_arbt_mad = p_arbt_mad;
51321936Shselasky	if (is_sa_mad) {
52321936Shselasky		p_sar->data_len = mad_size - IB_SA_MAD_HDR_SIZE;
53321936Shselasky		p_sar->hdr_sz = IB_SA_MAD_HDR_SIZE;
54321936Shselasky		p_sar->data_sz = IB_SA_DATA_SIZE;
55321936Shselasky	} else {
56321936Shselasky		p_sar->data_len = mad_size - MAD_RMPP_HDR_SIZE;
57321936Shselasky		p_sar->hdr_sz = MAD_RMPP_HDR_SIZE;
58321936Shselasky		p_sar->data_sz = MAD_RMPP_DATA_SIZE;
59321936Shselasky	}
60321936Shselasky	return IB_SUCCESS;
61321936Shselasky}
62321936Shselasky
63321936Shselaskyvoid osmv_rmpp_sar_done(osmv_rmpp_sar_t * p_sar)
64321936Shselasky{
65321936Shselasky	p_sar->p_arbt_mad = NULL;
66321936Shselasky}
67321936Shselasky
68321936Shselasky/* the big mad should be with mad header, rmpp header ( &sa hdr) space */
69321936Shselaskyib_api_status_t
70321936Shselaskyosmv_rmpp_sar_get_mad_seg(IN osmv_rmpp_sar_t * p_sar,
71321936Shselasky			  IN uint32_t seg_idx, OUT void *p_buf)
72321936Shselasky{
73321936Shselasky	void *p_seg;
74321936Shselasky	uint32_t sz_left;
75321936Shselasky	uint32_t num_segs;
76321936Shselasky
77321936Shselasky	CL_ASSERT(p_sar);
78321936Shselasky
79321936Shselasky	num_segs = p_sar->data_len / p_sar->data_sz;
80321936Shselasky	if ((p_sar->data_len % p_sar->data_sz) > 0) {
81321936Shselasky		num_segs++;
82321936Shselasky	}
83321936Shselasky
84321936Shselasky	if ((seg_idx > num_segs) && (seg_idx != 1)) {
85321936Shselasky		return IB_NOT_FOUND;
86321936Shselasky	}
87321936Shselasky
88321936Shselasky	/* cleanup */
89321936Shselasky	memset(p_buf, 0, MAD_BLOCK_SIZE);
90321936Shselasky
91321936Shselasky	/* attach header */
92321936Shselasky	memcpy(p_buf, p_sar->p_arbt_mad, p_sar->hdr_sz);
93321936Shselasky
94321936Shselasky	/* fill data */
95321936Shselasky	p_seg =
96321936Shselasky	    (char *)p_sar->p_arbt_mad + p_sar->hdr_sz +
97321936Shselasky	    ((seg_idx - 1) * p_sar->data_sz);
98321936Shselasky	sz_left = p_sar->data_len - ((seg_idx - 1) * p_sar->data_sz);
99321936Shselasky	if (sz_left > p_sar->data_sz)
100321936Shselasky		memcpy((char *)p_buf + p_sar->hdr_sz, (char *)p_seg,
101321936Shselasky		       p_sar->data_sz);
102321936Shselasky	else
103321936Shselasky		memcpy((char *)p_buf + p_sar->hdr_sz, (char *)p_seg, sz_left);
104321936Shselasky
105321936Shselasky	return IB_SUCCESS;
106321936Shselasky}
107321936Shselasky
108321936Shselasky/* turns a list of mads to one big mad - including header */
109321936Shselasky/* ALSO - deallocates the list                              */
110321936Shselaskyib_api_status_t
111321936Shselaskyosmv_rmpp_sar_reassemble_arbt_mad(osmv_rmpp_sar_t * p_sar, cl_qlist_t * p_bufs)
112321936Shselasky{
113321936Shselasky	void *buf_tmp, *p_mad;
114321936Shselasky	cl_list_item_t *p_item;
115321936Shselasky	cl_list_obj_t *p_obj;
116321936Shselasky	uint32_t space_left = p_sar->data_len + p_sar->hdr_sz;
117321936Shselasky
118321936Shselasky	CL_ASSERT(p_sar);
119321936Shselasky	CL_ASSERT(FALSE == cl_is_qlist_empty(p_bufs));
120321936Shselasky
121321936Shselasky	/* attach header */
122321936Shselasky	p_mad = p_sar->p_arbt_mad;
123321936Shselasky	p_item = cl_qlist_head(p_bufs);
124321936Shselasky	p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
125321936Shselasky	buf_tmp = cl_qlist_obj(p_obj);
126321936Shselasky	memcpy(p_mad, buf_tmp, p_sar->hdr_sz);
127321936Shselasky	p_mad = (char *)p_mad + p_sar->hdr_sz;
128321936Shselasky	space_left -= p_sar->hdr_sz;
129321936Shselasky
130321936Shselasky	/* reassemble data */
131321936Shselasky	while (FALSE == cl_is_qlist_empty(p_bufs)) {
132321936Shselasky
133321936Shselasky		p_item = cl_qlist_remove_head(p_bufs);
134321936Shselasky		p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item);
135321936Shselasky		buf_tmp = cl_qlist_obj(p_obj);
136321936Shselasky
137321936Shselasky		if (FALSE == cl_is_qlist_empty(p_bufs)) {
138321936Shselasky			memcpy((char *)p_mad, (char *)buf_tmp + p_sar->hdr_sz,
139321936Shselasky			       p_sar->data_sz);
140321936Shselasky			p_mad = (char *)p_mad + p_sar->data_sz;
141321936Shselasky			space_left -= p_sar->data_sz;
142321936Shselasky		} else {
143321936Shselasky			/* the last mad on the list */
144321936Shselasky			memcpy((char *)p_mad, (char *)buf_tmp + p_sar->hdr_sz,
145321936Shselasky			       space_left);
146321936Shselasky			p_mad = (char *)p_mad + space_left;
147321936Shselasky		}
148321936Shselasky
149321936Shselasky		free(buf_tmp);
150321936Shselasky		free(p_obj);
151321936Shselasky	}
152321936Shselasky
153321936Shselasky	return IB_SUCCESS;
154321936Shselasky}
155