103831d35Sstevel /*
203831d35Sstevel  * CDDL HEADER START
303831d35Sstevel  *
403831d35Sstevel  * The contents of this file are subject to the terms of the
503831d35Sstevel  * Common Development and Distribution License, Version 1.0 only
603831d35Sstevel  * (the "License").  You may not use this file except in compliance
703831d35Sstevel  * with the License.
803831d35Sstevel  *
903831d35Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1003831d35Sstevel  * or http://www.opensolaris.org/os/licensing.
1103831d35Sstevel  * See the License for the specific language governing permissions
1203831d35Sstevel  * and limitations under the License.
1303831d35Sstevel  *
1403831d35Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
1503831d35Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1603831d35Sstevel  * If applicable, add the following below this CDDL HEADER, with the
1703831d35Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
1803831d35Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
1903831d35Sstevel  *
2003831d35Sstevel  * CDDL HEADER END
2103831d35Sstevel  */
2203831d35Sstevel /*
2303831d35Sstevel  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
2403831d35Sstevel  * Use is subject to license terms.
2503831d35Sstevel  */
2603831d35Sstevel 
2703831d35Sstevel /*
2803831d35Sstevel  * smq.c: to provide a message queue system for scadm functions (used in the
2903831d35Sstevel  * firmware download context where BP messages, received from the service
3003831d35Sstevel  * processor, are stored in the message queue)
3103831d35Sstevel  *
3203831d35Sstevel  * these routines come from the libxposix library
3303831d35Sstevel  */
3403831d35Sstevel 
3503831d35Sstevel #include <sys/types.h>
3603831d35Sstevel #include <time.h>
3703831d35Sstevel 
3803831d35Sstevel #include "xsem.h"
3903831d35Sstevel #include "smq.h"
4003831d35Sstevel 
4103831d35Sstevel 
4203831d35Sstevel #define	SMQ_VALID_SMQ		0x0000003b
4303831d35Sstevel #define	SMQ_VALID_SMQ_MASK	0x000000FF
4403831d35Sstevel 
4503831d35Sstevel 
4603831d35Sstevel int
smq_init(smq_t * smq,smq_msg_t * msgbuffer,int depth)4703831d35Sstevel smq_init(smq_t *smq, smq_msg_t *msgbuffer, int depth)
4803831d35Sstevel {
4903831d35Sstevel 	/* allocate local semaphore initialized to 0 */
5003831d35Sstevel 	if (xsem_init(&smq->smq_msgAvail, 0, 0) != 0)
5103831d35Sstevel 		return (SMQ_ERROR);
5203831d35Sstevel 
5303831d35Sstevel 	smq->smq_control	= SMQ_VALID_SMQ;
5403831d35Sstevel 	smq->smq_msgBuffer	= msgbuffer;
5503831d35Sstevel 	smq->smq_head		= msgbuffer;
5603831d35Sstevel 	smq->smq_tail		= msgbuffer;
5703831d35Sstevel 	smq->smq_count		= 0;
5803831d35Sstevel 	smq->smq_depth		= depth;
5903831d35Sstevel 
6003831d35Sstevel 	return (0);
6103831d35Sstevel }
6203831d35Sstevel 
6303831d35Sstevel 
6403831d35Sstevel int
smq_destroy(smq_t * smq)6503831d35Sstevel smq_destroy(smq_t *smq)
6603831d35Sstevel {
6703831d35Sstevel 	if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ)
6803831d35Sstevel 		return (SMQ_INVALID);
6903831d35Sstevel 
7003831d35Sstevel 	smq->smq_control = 0;
7103831d35Sstevel 	(void) xsem_destroy(&smq->smq_msgAvail);
7203831d35Sstevel 
7303831d35Sstevel 	return (0);
7403831d35Sstevel }
7503831d35Sstevel 
7603831d35Sstevel 
7703831d35Sstevel int
smq_receive(smq_t * smq,smq_msg_t * msg)7803831d35Sstevel smq_receive(smq_t *smq, smq_msg_t *msg)
7903831d35Sstevel {
8003831d35Sstevel 	if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ)
8103831d35Sstevel 		return (SMQ_INVALID);
8203831d35Sstevel 
8303831d35Sstevel 	/* Wait for message */
8403831d35Sstevel 	(void) xsem_wait(&smq->smq_msgAvail);
8503831d35Sstevel 
8603831d35Sstevel 	if (smq->smq_count == 0)
8703831d35Sstevel 		return (SMQ_ERROR);
8803831d35Sstevel 
8903831d35Sstevel 	/* Copy messaged into queue */
9003831d35Sstevel 	*msg = *smq->smq_head;
9103831d35Sstevel 
92*2bc98732SRichard Lowe 	smq->smq_head++;
9303831d35Sstevel 	if ((unsigned long)smq->smq_head > ((unsigned long)smq->smq_msgBuffer +
9403831d35Sstevel 	    (unsigned long)(smq->smq_depth * sizeof (smq_msg_t)))) {
9503831d35Sstevel 		smq->smq_head = smq->smq_msgBuffer;
9603831d35Sstevel 	}
9703831d35Sstevel 	smq->smq_count--;
9803831d35Sstevel 
9903831d35Sstevel 	return (0);
10003831d35Sstevel }
10103831d35Sstevel 
10203831d35Sstevel 
10303831d35Sstevel int
smq_send(smq_t * smq,smq_msg_t * msg)10403831d35Sstevel smq_send(smq_t *smq, smq_msg_t *msg)
10503831d35Sstevel {
10603831d35Sstevel 	if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ)
10703831d35Sstevel 		return (SMQ_INVALID);
10803831d35Sstevel 
10903831d35Sstevel 	if (smq->smq_count == smq->smq_depth)
11003831d35Sstevel 		return (SMQ_FULL);
11103831d35Sstevel 
11203831d35Sstevel 	/* Copy messaged into queue */
11303831d35Sstevel 	*smq->smq_tail = *msg;
11403831d35Sstevel 
115*2bc98732SRichard Lowe 	smq->smq_tail++;
11603831d35Sstevel 	if ((unsigned long)smq->smq_tail > ((unsigned long)smq->smq_msgBuffer +
11703831d35Sstevel 	    (unsigned long)(smq->smq_depth * sizeof (smq_msg_t)))) {
11803831d35Sstevel 		smq->smq_tail = smq->smq_msgBuffer;
11903831d35Sstevel 	}
12003831d35Sstevel 
12103831d35Sstevel 	smq->smq_count++;
12203831d35Sstevel 	(void) xsem_post(&smq->smq_msgAvail);
12303831d35Sstevel 
12403831d35Sstevel 	return (0);
12503831d35Sstevel }
12603831d35Sstevel 
12703831d35Sstevel 
12803831d35Sstevel int
smq_pendingmsgs(smq_t * smq,int * num)12903831d35Sstevel smq_pendingmsgs(smq_t *smq, int *num)
13003831d35Sstevel {
13103831d35Sstevel 	if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ)
13203831d35Sstevel 		return (SMQ_INVALID);
13303831d35Sstevel 
13403831d35Sstevel 	*num = smq->smq_count;
13503831d35Sstevel 
13603831d35Sstevel 	return (0);
13703831d35Sstevel }
13803831d35Sstevel 
13903831d35Sstevel 
14003831d35Sstevel int
smq_depth(smq_t * smq,int * depth)14103831d35Sstevel smq_depth(smq_t *smq, int *depth)
14203831d35Sstevel {
14303831d35Sstevel 	if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ)
14403831d35Sstevel 		return (SMQ_INVALID);
14503831d35Sstevel 
14603831d35Sstevel 	*depth = smq->smq_depth;
14703831d35Sstevel 
14803831d35Sstevel 	return (0);
14903831d35Sstevel }
15003831d35Sstevel 
15103831d35Sstevel 
15203831d35Sstevel int
smq_xreceive(smq_t * smq,timestruc_t * timeout,smq_msg_t * msg)15303831d35Sstevel smq_xreceive(smq_t *smq, timestruc_t *timeout, smq_msg_t *msg)
15403831d35Sstevel {
15503831d35Sstevel 	int Status;
15603831d35Sstevel 
15703831d35Sstevel 
15803831d35Sstevel 	if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ)
15903831d35Sstevel 		return (SMQ_INVALID);
16003831d35Sstevel 
16103831d35Sstevel 	/* Wait for message */
16203831d35Sstevel 	if ((Status = xsem_xwait(&smq->smq_msgAvail, 1, timeout)) == XSEM_ETIME)
16303831d35Sstevel 		return (SMQ_ETIME);
16403831d35Sstevel 
16503831d35Sstevel 	if (Status != 0)
16603831d35Sstevel 		return (SMQ_ERROR);
16703831d35Sstevel 
16803831d35Sstevel 	if (smq->smq_count == 0)
16903831d35Sstevel 		return (SMQ_ERROR);
17003831d35Sstevel 
17103831d35Sstevel 	/* Copy messaged into queue */
17203831d35Sstevel 	*msg = *smq->smq_head;
17303831d35Sstevel 
174*2bc98732SRichard Lowe 	smq->smq_head++;
17503831d35Sstevel 	if ((unsigned long)smq->smq_head > ((unsigned long)smq->smq_msgBuffer +
17603831d35Sstevel 	    (unsigned long)(smq->smq_depth * sizeof (smq_msg_t)))) {
17703831d35Sstevel 		smq->smq_head = smq->smq_msgBuffer;
17803831d35Sstevel 	}
17903831d35Sstevel 	smq->smq_count--;
18003831d35Sstevel 
18103831d35Sstevel 
18203831d35Sstevel 	return (0);
18303831d35Sstevel }
184