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 /* 28 * smq.c: to provide a message queue system for scadm functions (used in the 29 * firmware download context where BP messages, received from the service 30 * processor, are stored in the message queue) 31 * 32 * these routines come from the libxposix library 33 */ 34 35 #include <sys/types.h> 36 #include <time.h> 37 38 #include "xsem.h" 39 #include "smq.h" 40 41 42 #define SMQ_VALID_SMQ 0x0000003b 43 #define SMQ_VALID_SMQ_MASK 0x000000FF 44 45 46 int 47 smq_init(smq_t *smq, smq_msg_t *msgbuffer, int depth) 48 { 49 /* allocate local semaphore initialized to 0 */ 50 if (xsem_init(&smq->smq_msgAvail, 0, 0) != 0) 51 return (SMQ_ERROR); 52 53 smq->smq_control = SMQ_VALID_SMQ; 54 smq->smq_msgBuffer = msgbuffer; 55 smq->smq_head = msgbuffer; 56 smq->smq_tail = msgbuffer; 57 smq->smq_count = 0; 58 smq->smq_depth = depth; 59 60 return (0); 61 } 62 63 64 int 65 smq_destroy(smq_t *smq) 66 { 67 if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ) 68 return (SMQ_INVALID); 69 70 smq->smq_control = 0; 71 (void) xsem_destroy(&smq->smq_msgAvail); 72 73 return (0); 74 } 75 76 77 int 78 smq_receive(smq_t *smq, smq_msg_t *msg) 79 { 80 if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ) 81 return (SMQ_INVALID); 82 83 /* Wait for message */ 84 (void) xsem_wait(&smq->smq_msgAvail); 85 86 if (smq->smq_count == 0) 87 return (SMQ_ERROR); 88 89 /* Copy messaged into queue */ 90 *msg = *smq->smq_head; 91 92 smq->smq_head++; 93 if ((unsigned long)smq->smq_head > ((unsigned long)smq->smq_msgBuffer + 94 (unsigned long)(smq->smq_depth * sizeof (smq_msg_t)))) { 95 smq->smq_head = smq->smq_msgBuffer; 96 } 97 smq->smq_count--; 98 99 return (0); 100 } 101 102 103 int 104 smq_send(smq_t *smq, smq_msg_t *msg) 105 { 106 if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ) 107 return (SMQ_INVALID); 108 109 if (smq->smq_count == smq->smq_depth) 110 return (SMQ_FULL); 111 112 /* Copy messaged into queue */ 113 *smq->smq_tail = *msg; 114 115 smq->smq_tail++; 116 if ((unsigned long)smq->smq_tail > ((unsigned long)smq->smq_msgBuffer + 117 (unsigned long)(smq->smq_depth * sizeof (smq_msg_t)))) { 118 smq->smq_tail = smq->smq_msgBuffer; 119 } 120 121 smq->smq_count++; 122 (void) xsem_post(&smq->smq_msgAvail); 123 124 return (0); 125 } 126 127 128 int 129 smq_pendingmsgs(smq_t *smq, int *num) 130 { 131 if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ) 132 return (SMQ_INVALID); 133 134 *num = smq->smq_count; 135 136 return (0); 137 } 138 139 140 int 141 smq_depth(smq_t *smq, int *depth) 142 { 143 if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ) 144 return (SMQ_INVALID); 145 146 *depth = smq->smq_depth; 147 148 return (0); 149 } 150 151 152 int 153 smq_xreceive(smq_t *smq, timestruc_t *timeout, smq_msg_t *msg) 154 { 155 int Status; 156 157 158 if ((smq->smq_control & SMQ_VALID_SMQ_MASK) != SMQ_VALID_SMQ) 159 return (SMQ_INVALID); 160 161 /* Wait for message */ 162 if ((Status = xsem_xwait(&smq->smq_msgAvail, 1, timeout)) == XSEM_ETIME) 163 return (SMQ_ETIME); 164 165 if (Status != 0) 166 return (SMQ_ERROR); 167 168 if (smq->smq_count == 0) 169 return (SMQ_ERROR); 170 171 /* Copy messaged into queue */ 172 *msg = *smq->smq_head; 173 174 smq->smq_head++; 175 if ((unsigned long)smq->smq_head > ((unsigned long)smq->smq_msgBuffer + 176 (unsigned long)(smq->smq_depth * sizeof (smq_msg_t)))) { 177 smq->smq_head = smq->smq_msgBuffer; 178 } 179 smq->smq_count--; 180 181 182 return (0); 183 } 184