1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 1999 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include "ghd.h"
28 
29 /*
30  * Round up all allocations so that we can guarantee
31  * long-long alignment.  This is the same alignment
32  * provided by kmem_alloc().
33  */
34 #define	ROUNDUP(x)	(((x) + 0x07) & ~0x07)
35 
36 /*
37  * Private wrapper for gcmd_t
38  */
39 typedef struct gw_gcmd_and_length {
40 	gcmd_t	gcmd;		/* this must be first */
41 	int	glen;		/* length includes HBA private area */
42 }gw_t;
43 
44 /*
45  * round up the size so the HBA private area is on a 8 byte boundary
46  */
47 #define	GW_PADDED_LENGTH	ROUNDUP(sizeof (gw_t))
48 
49 typedef struct gcmd_padded_wrapper {
50 	union {
51 		gw_t	gw;
52 		char	gw_pad[GW_PADDED_LENGTH];
53 
54 	} gwrap;
55 } gwrap_t;
56 
57 /*
58  * Allocate a gcmd_t wrapper and HBA private area
59  */
60 
61 gcmd_t *
ghd_gcmd_alloc(gtgt_t * gtgtp,int ccblen,int sleep)62 ghd_gcmd_alloc(gtgt_t	*gtgtp,
63 		int	ccblen,
64 		int	sleep)
65 {
66 	gwrap_t	*gwp;
67 	gcmd_t	*gcmdp;
68 	int	 gwrap_len;
69 
70 	ccblen = ROUNDUP(ccblen);
71 	gwrap_len = sizeof (gwrap_t) + ccblen;
72 	gwp = kmem_zalloc(gwrap_len, (sleep ? KM_SLEEP : KM_NOSLEEP));
73 	if (gwp == NULL) {
74 		ASSERT(sleep == FALSE);
75 		return (NULL);
76 	}
77 
78 	/* save the total length for the free function */
79 	gwp->gwrap.gw.glen = gwrap_len;
80 
81 	/*
82 	 * save the ptr to HBA private area and initialize all
83 	 * the gcmd_t members and save
84 	 */
85 	gcmdp = &gwp->gwrap.gw.gcmd;
86 	GHD_GCMD_INIT(gcmdp, (void *)(gwp + 1), gtgtp);
87 	return (gcmdp);
88 }
89 
90 
91 
92 /*
93  * Free the gcmd_t wrapper and HBA private area
94  */
95 
96 void
ghd_gcmd_free(gcmd_t * gcmdp)97 ghd_gcmd_free(gcmd_t *gcmdp)
98 {
99 	kmem_free(gcmdp, ((gw_t *)gcmdp)->glen);
100 }
101