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 }