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 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 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 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 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 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 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 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