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 }