xref: /titanic_50/usr/src/cmd/scadm/sparc/mpxu/common/smq.c (revision c13de8f6a88563211bd4432ca11ca38ed3bf0fc0)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * smq.c: to provide a message queue system for scadm functions (used in the
31  * firmware download context where BP messages, received from the service
32  * processor, are stored in the message queue)
33  *
34  * these routines come from the libxposix library
35  */
36 
37 #include <sys/types.h>
38 #include <time.h>
39 
40 #include "xsem.h"
41 #include "smq.h"
42 
43 
44 #define	SMQ_VALID_SMQ		0x0000003b
45 #define	SMQ_VALID_SMQ_MASK	0x000000FF
46 
47 
48 int
49 smq_init(smq_t *smq, smq_msg_t *msgbuffer, int depth)
50 {
51 	/* allocate local semaphore initialized to 0 */
52 	if (xsem_init(&smq->smq_msgAvail, 0, 0) != 0)
53 		return (SMQ_ERROR);
54 
55 	smq->smq_control	= SMQ_VALID_SMQ;
56 	smq->smq_msgBuffer	= msgbuffer;
57 	smq->smq_head		= msgbuffer;
58 	smq->smq_tail		= msgbuffer;
59 	smq->smq_count		= 0;
60 	smq->smq_depth		= depth;
61 
62 	return (0);
63 }
64 
65 
66 int
67 smq_destroy(smq_t *smq)
68 {
69 	if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ)
70 		return (SMQ_INVALID);
71 
72 	smq->smq_control = 0;
73 	(void) xsem_destroy(&smq->smq_msgAvail);
74 
75 	return (0);
76 }
77 
78 
79 int
80 smq_receive(smq_t *smq, smq_msg_t *msg)
81 {
82 	if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ)
83 		return (SMQ_INVALID);
84 
85 	/* Wait for message */
86 	(void) xsem_wait(&smq->smq_msgAvail);
87 
88 	if (smq->smq_count == 0)
89 		return (SMQ_ERROR);
90 
91 	/* Copy messaged into queue */
92 	*msg = *smq->smq_head;
93 
94 	/* Increment Head */
95 	smq->smq_head = smq->smq_head++;
96 	if ((unsigned long)smq->smq_head > ((unsigned long)smq->smq_msgBuffer +
97 	    (unsigned long)(smq->smq_depth * sizeof (smq_msg_t)))) {
98 		smq->smq_head = smq->smq_msgBuffer;
99 	}
100 	smq->smq_count--;
101 
102 	return (0);
103 }
104 
105 
106 int
107 smq_send(smq_t *smq, smq_msg_t *msg)
108 {
109 	if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ)
110 		return (SMQ_INVALID);
111 
112 	if (smq->smq_count == smq->smq_depth)
113 		return (SMQ_FULL);
114 
115 	/* Copy messaged into queue */
116 	*smq->smq_tail = *msg;
117 
118 	/* Increment Tail */
119 	smq->smq_tail = smq->smq_tail++;
120 	if ((unsigned long)smq->smq_tail > ((unsigned long)smq->smq_msgBuffer +
121 	    (unsigned long)(smq->smq_depth * sizeof (smq_msg_t)))) {
122 		smq->smq_tail = smq->smq_msgBuffer;
123 	}
124 
125 	smq->smq_count++;
126 	(void) xsem_post(&smq->smq_msgAvail);
127 
128 	return (0);
129 }
130 
131 
132 int
133 smq_pendingmsgs(smq_t *smq, int *num)
134 {
135 	if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ)
136 		return (SMQ_INVALID);
137 
138 	*num = smq->smq_count;
139 
140 	return (0);
141 }
142 
143 
144 int
145 smq_depth(smq_t *smq, int *depth)
146 {
147 	if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ)
148 		return (SMQ_INVALID);
149 
150 	*depth = smq->smq_depth;
151 
152 	return (0);
153 }
154 
155 
156 int
157 smq_xreceive(smq_t *smq, timestruc_t *timeout, smq_msg_t *msg)
158 {
159 	int Status;
160 
161 
162 	if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ)
163 		return (SMQ_INVALID);
164 
165 	/* Wait for message */
166 	if ((Status = xsem_xwait(&smq->smq_msgAvail, 1, timeout)) == XSEM_ETIME)
167 		return (SMQ_ETIME);
168 
169 	if (Status != 0)
170 		return (SMQ_ERROR);
171 
172 	if (smq->smq_count == 0)
173 		return (SMQ_ERROR);
174 
175 	/* Copy messaged into queue */
176 	*msg = *smq->smq_head;
177 
178 	/* Increment Head */
179 	smq->smq_head = smq->smq_head++;
180 	if ((unsigned long)smq->smq_head > ((unsigned long)smq->smq_msgBuffer +
181 	    (unsigned long)(smq->smq_depth * sizeof (smq_msg_t)))) {
182 		smq->smq_head = smq->smq_msgBuffer;
183 	}
184 	smq->smq_count--;
185 
186 
187 	return (0);
188 }
189