9279d14135cdfbbff68ccd84fd2298871b082722
1 /*
2 * Copyright (c) 2020, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /**
33 * \file sciserver.c
34 *
35 * \brief File containing the Sciserver driver APIs.
36 *
37 */
39 /* ========================================================================== */
40 /* Include Files */
41 /* ========================================================================== */
43 #include <string.h>
44 #include <ti/csl/csl_types.h>
45 #include <ti/csl/hw_types.h>
46 #include <ti/csl/csl_sec_proxy.h>
47 #include <ti/drv/sciclient/sciserver.h>
48 #include <sciserver_secproxyConfigData.h>
49 #include <sciserver_secproxyTransfer.h>
50 #include <sciserver_hwiData.h>
51 #include <ti/drv/sciclient/src/sciclient/sciclient_priv.h>
53 /* Set VERBOSE to 1 for trace information on message routing */
54 #define VERBOSE 0
56 #if VERBOSE
57 #include <ti/drv/uart/UART_stdio.h>
58 #define Sciserver_printf UART_printf
59 #else
60 #define Sciserver_printf(...)
61 #endif
63 /* ========================================================================== */
64 /* Macros & Typedefs */
65 /* ========================================================================== */
67 /* ========================================================================== */
68 /* Structure Declarations */
69 /* ========================================================================== */
71 /** \brief Sciserver Internal Structure */
72 typedef struct {
73 uint8_t ctrlState;
74 /**< Ctrl State of the Sciserver */
75 uint8_t processState;
76 /**< Processing State of the Sciserver */
77 uint8_t initDone;
78 /**< Initialization Done State */
79 } Sciserver_InternalState_t ;
81 /* ========================================================================== */
82 /* Function Declarations */
83 /* ========================================================================== */
85 static int32_t Sciserver_MsgVerifyHost(uint32_t *msg, uint8_t known_host);
86 static int32_t Sciserver_UserProcessMsg(uint32_t *msg_recv,
87 int32_t *pRespMsgSize,
88 uint8_t hw_host);
90 static void Sciserver_TisciMsgClearFlags(struct tisci_header *hdr);
91 static int32_t Sciserver_TisciMsgResponse(uint8_t response_host,
92 uint32_t *response,
93 uint32_t size);
94 static void Sciserver_SetMsgHostId(uint32_t *msg, uint8_t hostId);
95 /* ========================================================================== */
96 /* Global Variables */
97 /* ========================================================================== */
99 /** Global state of the Sciserver */
100 static Sciserver_InternalState_t gSciserverState = {
101 SCISERVER_CTRL_CMD_HALT,
102 SCISERVER_PROCESS_STATE_WAIT,
103 SCISERVER_INIT_NOT_DONE
104 };
107 /* ========================================================================== */
108 /* Function Definitions */
109 /* ========================================================================== */
111 int32_t Sciserver_initPrms_Init(Sciserver_CfgPrms_t *pPrms)
112 {
113 int32_t ret = CSL_PASS;
115 return ret;
116 }
118 int32_t Sciserver_init(Sciserver_CfgPrms_t *pPrms)
119 {
120 int32_t ret = CSL_PASS;
122 if (gSciserverState.initDone == SCISERVER_INIT_NOT_DONE)
123 {
124 if (pPrms == NULL)
125 {
126 ret = CSL_EBADARGS;
127 }
128 if (CSL_PASS == ret)
129 {
130 gSciserverState.ctrlState = SCISERVER_CTRL_CMD_HALT;
131 gSciserverState.processState = SCISERVER_PROCESS_STATE_WAIT;
132 gSciserverState.initDone = SCISERVER_INIT_DONE;
133 }
134 }
135 else
136 {
137 ret = CSL_EFAIL;
138 }
139 return ret;
140 }
142 int32_t Sciserver_deinit()
143 {
144 int32_t ret = CSL_PASS;
146 if (gSciserverState.initDone == SCISERVER_INIT_DONE)
147 {
148 if (CSL_PASS == ret)
149 {
150 gSciserverState.ctrlState = SCISERVER_CTRL_CMD_HALT;
151 gSciserverState.processState = SCISERVER_PROCESS_STATE_WAIT;
152 gSciserverState.initDone = SCISERVER_INIT_NOT_DONE;
153 }
154 }
155 else
156 {
157 ret = CSL_EFAIL;
158 }
159 return ret;
160 }
162 void Sciserver_setCtrlState (uint8_t state)
163 {
164 gSciserverState.ctrlState = state;
165 }
167 uint8_t Sciserver_getCtrlState ()
168 {
169 return gSciserverState.ctrlState;
170 }
172 void Sciserver_setProcessState (uint8_t state)
173 {
174 gSciserverState.processState = state;
175 }
177 uint8_t Sciserver_getProcessState ()
178 {
179 return gSciserverState.processState;
180 }
182 int32_t Sciserver_interruptHandler(Sciserver_hwiData *uhd, bool* soft_error)
183 {
184 int32_t ret = CSL_PASS;
185 uint32_t msg_words;
186 uint32_t hw_host = 0U;
188 *soft_error = false;
189 if (ret == CSL_PASS)
190 {
191 (void) memset(uhd->hw_msg_buffer, 0, SCISERVER_HW_QUEUE_SIZE);
192 msg_words = ((uint32_t) SCISERVER_HW_QUEUE_SIZE + 3U) / 4U;
193 ret = Sciserver_SproxyMsgRead(uhd->hw_msg_queue_id,
194 uhd->hw_msg_buffer,
195 msg_words);
196 }
198 if (ret == CSL_PASS)
199 {
200 ret = Sciserver_SproxyMsgGetSenderHostId(uhd->hw_msg_queue_id,
201 &hw_host);
202 }
204 if (ret == CSL_PASS) {
205 /*
206 * We must ensure that the incoming message hdr host field
207 * matches the host ID returned to us from the messaging
208 * hardware, otherwise this may be a spoofed message. If
209 * message appears to be spoofed, send a nak and then
210 * move on to the next one.
211 */
212 ret = Sciserver_MsgVerifyHost(uhd->hw_msg_buffer, (uint8_t) hw_host);
213 if (ret != CSL_PASS) {
214 /*
215 * It is ok to continue after this but flag
216 * the invalid message so that the queue is cleared
217 * and we can ignore this message and move on.
218 */
219 *soft_error = true;
220 }
221 }
223 if (ret == CSL_PASS)
224 {
225 uhd->user_msg_data->host = hw_host;
226 uhd->user_msg_data->is_pending = true;
227 ret = Sciserver_SproxyMsgAck(uhd->hw_msg_queue_id);
228 }
229 else
230 {
231 Sciserver_SproxyMsgAck(uhd->hw_msg_queue_id);
232 }
233 return ret;
234 }
236 int32_t Sciserver_processtask(Sciserver_taskData *utd)
237 {
238 int32_t ret = CSL_PASS;
239 uint8_t i;
240 /* the host ID that the response message is sent to */
241 uint8_t respHost;
242 /* the response message size */
243 int32_t respMsgSize;
244 /* the response message pointer */
245 uint32_t *respMsg;
246 /* the response message header pointer. Same as respMsg */
247 struct tisci_header *respMsgHeader;
249 for (i = 0; i < SCISERVER_SECPROXY_INSTANCE_COUNT; i++)
250 {
251 utd->state->current_buffer_idx++;
252 if (utd->state->current_buffer_idx >= SCISERVER_SECPROXY_INSTANCE_COUNT)
253 {
254 utd->state->current_buffer_idx = 0;
255 }
257 if (utd->user_msg_data[utd->state->current_buffer_idx]->is_pending == true)
258 {
259 utd->state->state = SCISERVER_TASK_PROCESSING_USER_MSG;
260 break;
261 }
262 }
264 if (utd->state->state == SCISERVER_TASK_PROCESSING_USER_MSG)
265 {
266 ret = Sciserver_UserProcessMsg(
267 utd->hw_msg_buffer_list[utd->state->current_buffer_idx],
268 &respMsgSize,
269 utd->user_msg_data[utd->state->current_buffer_idx]->host);
270 respMsg = utd->hw_msg_buffer_list[utd->state->current_buffer_idx];
271 respMsgHeader = (struct tisci_header *) respMsg;
272 }
273 else
274 {
275 ret = CSL_EFAIL;
276 }
278 if (ret == CSL_PASS)
279 {
280 Sciclient_TisciMsgSetAckResp(respMsgHeader);
281 }
282 else if ((respMsgHeader->flags & TISCI_MSG_FLAG_AOP) != 0)
283 {
284 Sciserver_TisciMsgClearFlags(respMsgHeader);
285 Sciclient_TisciMsgSetNakResp(respMsgHeader);
286 }
288 respHost = utd->user_msg_data[utd->state->current_buffer_idx]->host;
289 if (respHost == TISCI_HOST_ID_DMSC2DM)
290 {
291 /* DMSC2DM is processed by DM. Need to update response message value
292 * so the host verification on TIFS can succeed */
293 Sciserver_SetMsgHostId(respMsg, TISCI_HOST_ID_DM);
294 }
296 ret = Sciserver_TisciMsgResponse(respHost, respMsg, respMsgSize);
298 if (ret == CSL_PASS)
299 {
300 utd->user_msg_data[utd->state->current_buffer_idx]->is_pending = false;
301 }
303 utd->state->state = SCISERVER_TASK_PENDING;
305 return ret;
306 }
308 /* -------------------------------------------------------------------------- */
309 /* Internal Function Definitions */
310 /* -------------------------------------------------------------------------- */
312 static int32_t Sciserver_MsgVerifyHost(uint32_t *msg, uint8_t known_host)
313 {
314 int32_t ret = CSL_PASS;
315 struct tisci_header *hdr = (struct tisci_header *) msg;
317 if (hdr == NULL) {
318 ret = CSL_EFAIL;
319 }
321 if (ret == CSL_PASS) { if (hdr->host != known_host) {
322 /*
323 * We check the header against the queue id to verify that the host
324 * has not spoofed the request. The special case is when a message
325 * is sent via the forwarded DMSC2DM queue, then by design the
326 * header host does not match the host assigned to the queue. We
327 * rely on the host id from the message header to allow us to
328 * process the message on behalf of the host who made the original
329 * request.
330 */
331 if (known_host != TISCI_HOST_ID_DMSC2DM) {
332 ret = CSL_EFAIL;
333 }
334 }
335 }
337 return ret;
338 }
341 static void Sciserver_TisciMsgClearFlags(struct tisci_header *hdr)
342 {
343 hdr->flags = 0;
344 }
346 static int32_t Sciserver_TisciMsgResponse(uint8_t response_host,
347 uint32_t *response,
348 uint32_t size)
349 {
350 uint16_t sproxy_conf_id;
351 uint32_t msg_words;
352 int32_t ret = CSL_PASS;
354 /*
355 * We calculate words here without a check because we rely on the
356 * underlying HW implementation to validate sanity of size value that
357 * is passed.
358 */
359 msg_words = (size + 3U) / 4U;
361 ret = Sciserver_SproxyGetResponseConfId(response_host,
362 &sproxy_conf_id);
364 if (ret == CSL_PASS) {
365 ret = Sciserver_SproxyMsgSend(sproxy_conf_id, response,
366 msg_words);
367 }
369 if (ret == 0) {
370 ret = Sciserver_SproxyMsgFinish(sproxy_conf_id);
371 }
373 return ret;
374 }
376 static void Sciserver_SetMsgHostId(uint32_t *msg, uint8_t hostId)
377 {
378 struct tisci_header *hdr = (struct tisci_header *) msg;
379 hdr->host = hostId;
380 }
382 int32_t Sciserver_ProcessForwardedMessage(uint32_t *msg_recv,
383 int32_t reqMsgSize,
384 int32_t respMsgSize)
385 {
386 int32_t ret = CSL_EFAIL;
387 Sciclient_ReqPrm_t reqPrm;
388 Sciclient_RespPrm_t respPrm;
389 struct tisci_header *hdr = (struct tisci_header *) msg_recv;
390 uint8_t reqSeq;
391 uint32_t reqMsgBuffer[14] = {0};
392 uint32_t respMsgBuffer[14] = {0};
394 /* Store the request sequence value */
395 reqSeq = hdr->seq;
397 memcpy(reqMsgBuffer, msg_recv, reqMsgSize);
399 reqPrm.messageType = hdr->type;
400 reqPrm.flags = TISCI_MSG_FLAG_AOP;
401 reqPrm.pReqPayload = (const uint8_t *)reqMsgBuffer;
402 reqPrm.reqPayloadSize = reqMsgSize;
403 reqPrm.timeout = SCICLIENT_SERVICE_WAIT_FOREVER;
405 /*
406 * If here, the message is intended to be forwarded to another service
407 * provider.
408 */
409 reqPrm.forwardStatus = SCISERVER_FORWARD_MSG;
411 respPrm.flags = 0;
412 respPrm.pRespPayload = (uint8_t *) respMsgBuffer;
413 respPrm.respPayloadSize = respMsgSize;
415 ret = Sciclient_service(&reqPrm, &respPrm);
417 if ((CSL_PASS == ret) && (respPrm.flags == TISCI_MSG_FLAG_ACK))
418 {
419 Sciserver_printf("Sciserver: forward success type=%d\n", hdr->type);
420 memcpy(msg_recv, respMsgBuffer, respMsgSize);
422 /* Must restore the seq field. When forwarded message is processed by
423 * TIFS, the returned message would have incorrect sequence value */
424 hdr->seq = reqSeq;
425 }
426 else
427 {
428 Sciserver_printf("Sciserver: forward failed type=%d, flag=%d\n",
429 hdr->type, respPrm.flags);
430 ret = CSL_EFAIL;
431 }
433 return ret;
434 }
436 static int32_t Sciserver_UserProcessMsg(uint32_t *msg_recv,
437 int32_t *pRespMsgSize,
438 uint8_t hw_host_id)
439 {
440 int32_t ret = CSL_PASS;
441 struct tisci_header *hdr = (struct tisci_header *) msg_recv;
442 int32_t isRmMsg = 0, isPmMsg = 0, isFwdMsg = 0;
443 int32_t reqMsgSize;
444 int32_t respMsgSize;
446 Sciserver_printf("type = 0x%x, host = %d\n", hdr->type, hw_host_id);
448 switch (hdr->type)
449 {
450 case TISCI_MSG_VERSION:
451 isFwdMsg = 1;
452 reqMsgSize = sizeof(struct tisci_msg_version_req);
453 respMsgSize = sizeof(struct tisci_msg_version_resp);
454 break;
455 /* Start of RM messages */
456 case TISCI_MSG_BOARD_CONFIG_RM:
457 isRmMsg = 1;
458 respMsgSize = sizeof(struct tisci_msg_board_config_rm_resp);
459 break;
460 case TISCI_MSG_RM_GET_RESOURCE_RANGE:
461 isRmMsg = 1;
462 respMsgSize = sizeof(struct tisci_msg_rm_get_resource_range_resp);
463 break;
464 case TISCI_MSG_RM_IRQ_SET:
465 isRmMsg = 1;
466 isFwdMsg = 1;
467 reqMsgSize = sizeof(struct tisci_msg_rm_irq_set_req);
468 respMsgSize = sizeof(struct tisci_msg_rm_irq_set_resp);
469 break;
470 case TISCI_MSG_RM_IRQ_RELEASE:
471 isRmMsg = 1;
472 isFwdMsg = 1;
473 reqMsgSize = sizeof(struct tisci_msg_rm_irq_release_req);
474 respMsgSize = sizeof(struct tisci_msg_rm_irq_release_resp);
475 break;
476 case TISCI_MSG_RM_RING_CFG:
477 isRmMsg = 1;
478 isFwdMsg = 1;
479 reqMsgSize = sizeof(struct tisci_msg_rm_ring_cfg_req);
480 respMsgSize = sizeof(struct tisci_msg_rm_ring_cfg_resp);
481 break;
482 case TISCI_MSG_RM_RING_MON_CFG:
483 isRmMsg = 1;
484 isFwdMsg = 1;
485 reqMsgSize = sizeof(struct tisci_msg_rm_ring_mon_cfg_req);
486 respMsgSize = sizeof(struct tisci_msg_rm_ring_mon_cfg_resp);
487 break;
488 case TISCI_MSG_RM_UDMAP_TX_CH_CFG:
489 isRmMsg = 1;
490 isFwdMsg = 1;
491 reqMsgSize = sizeof(struct tisci_msg_rm_udmap_tx_ch_cfg_req);
492 respMsgSize = sizeof(struct tisci_msg_rm_udmap_tx_ch_cfg_resp);
493 break;
494 case TISCI_MSG_RM_UDMAP_RX_CH_CFG:
495 isRmMsg = 1;
496 isFwdMsg = 1;
497 reqMsgSize = sizeof(struct tisci_msg_rm_udmap_rx_ch_cfg_req);
498 respMsgSize = sizeof(struct tisci_msg_rm_udmap_rx_ch_cfg_resp);
499 break;
500 case TISCI_MSG_RM_UDMAP_FLOW_CFG:
501 isRmMsg = 1;
502 respMsgSize = sizeof(struct tisci_msg_rm_udmap_flow_cfg_resp);
503 break;
504 case TISCI_MSG_RM_UDMAP_FLOW_SIZE_THRESH_CFG:
505 isRmMsg = 1;
506 respMsgSize = sizeof(struct tisci_msg_rm_udmap_flow_size_thresh_cfg_resp);
507 break;
508 case TISCI_MSG_RM_UDMAP_FLOW_DELEGATE:
509 isRmMsg = 1;
510 respMsgSize = sizeof(struct tisci_msg_rm_udmap_flow_delegate_resp);
511 break;
512 case TISCI_MSG_RM_UDMAP_GCFG_CFG:
513 isRmMsg = 1;
514 respMsgSize = sizeof(struct tisci_msg_rm_udmap_gcfg_cfg_resp);
515 break;
516 case TISCI_MSG_RM_PSIL_PAIR:
517 isFwdMsg = 1;
518 reqMsgSize = sizeof(struct tisci_msg_rm_psil_pair_req);
519 respMsgSize = sizeof(struct tisci_msg_rm_psil_pair_resp);
520 break;
521 case TISCI_MSG_RM_PSIL_UNPAIR:
522 isFwdMsg = 1;
523 reqMsgSize = sizeof(struct tisci_msg_rm_psil_unpair_req);
524 respMsgSize = sizeof(struct tisci_msg_rm_psil_unpair_resp);
525 break;
526 case TISCI_MSG_RM_PSIL_READ:
527 isFwdMsg = 1;
528 reqMsgSize = sizeof(struct tisci_msg_rm_psil_read_req);
529 respMsgSize = sizeof(struct tisci_msg_rm_psil_read_resp);
530 break;
531 case TISCI_MSG_RM_PSIL_WRITE:
532 isFwdMsg = 1;
533 reqMsgSize = sizeof(struct tisci_msg_rm_psil_write_req);
534 respMsgSize = sizeof(struct tisci_msg_rm_psil_write_resp);
535 break;
536 case TISCI_MSG_RM_PROXY_CFG:
537 isFwdMsg = 1;
538 reqMsgSize = sizeof(struct tisci_msg_rm_proxy_cfg_req);
539 respMsgSize = sizeof(struct tisci_msg_rm_proxy_cfg_resp);
540 break;
541 /* Start of PM messages */
542 case TISCI_MSG_BOARD_CONFIG_PM:
543 isPmMsg = 1;
544 respMsgSize = sizeof(struct tisci_msg_board_config_pm_resp);
545 break;
546 case TISCI_MSG_SET_CLOCK:
547 isPmMsg = 1;
548 respMsgSize = sizeof(struct tisci_msg_set_clock_resp);
549 break;
550 case TISCI_MSG_GET_CLOCK:
551 isPmMsg = 1;
552 respMsgSize = sizeof(struct tisci_msg_get_clock_resp);
553 break;
554 case TISCI_MSG_SET_CLOCK_PARENT:
555 isPmMsg = 1;
556 respMsgSize = sizeof(struct tisci_msg_set_clock_parent_resp);
557 break;
558 case TISCI_MSG_GET_CLOCK_PARENT:
559 isPmMsg = 1;
560 respMsgSize = sizeof(struct tisci_msg_get_clock_parent_resp);
561 break;
562 case TISCI_MSG_GET_NUM_CLOCK_PARENTS:
563 isPmMsg = 1;
564 respMsgSize = sizeof(struct tisci_msg_get_num_clock_parents_resp);
565 break;
566 case TISCI_MSG_SET_FREQ:
567 isPmMsg = 1;
568 respMsgSize = sizeof(struct tisci_msg_set_freq_resp);
569 break;
570 case TISCI_MSG_QUERY_FREQ:
571 isPmMsg = 1;
572 respMsgSize = sizeof(struct tisci_msg_query_freq_resp);
573 break;
574 case TISCI_MSG_GET_FREQ:
575 isPmMsg = 1;
576 respMsgSize = sizeof(struct tisci_msg_get_freq_resp);
577 break;
578 case TISCI_MSG_SET_DEVICE:
579 isPmMsg = 1;
580 respMsgSize = sizeof(struct tisci_msg_set_device_resp);
581 break;
582 case TISCI_MSG_GET_DEVICE:
583 isPmMsg = 1;
584 respMsgSize = sizeof(struct tisci_msg_get_device_resp);
585 break;
586 case TISCI_MSG_SET_DEVICE_RESETS:
587 isPmMsg = 1;
588 respMsgSize = sizeof(struct tisci_msg_set_device_resets_resp);
589 break;
590 case TISCI_MSG_SYS_RESET:
591 isPmMsg = 1;
592 respMsgSize = sizeof(struct tisci_msg_sys_reset_resp);
593 break;
595 default:
596 isRmMsg = 0;
597 isPmMsg = 0;
598 isFwdMsg = 1;
600 /* Forward the full message size */
601 reqMsgSize = SCISERVER_HW_QUEUE_SIZE;
602 respMsgSize = SCISERVER_HW_QUEUE_SIZE;
603 break;
604 }
606 switch (hdr->type)
607 {
608 case TISCI_MSG_RM_IRQ_SET:
609 case TISCI_MSG_RM_RING_CFG:
610 case TISCI_MSG_RM_RING_MON_CFG:
611 case TISCI_MSG_RM_UDMAP_TX_CH_CFG:
612 case TISCI_MSG_RM_UDMAP_RX_CH_CFG:
613 case TISCI_MSG_RM_PROXY_CFG:
614 if (hw_host_id == TISCI_HOST_ID_DMSC2DM)
615 {
616 Sciserver_printf("Skip forward: type = %d\n", hdr->type);
617 isFwdMsg = 0;
618 isRmMsg = 1;
619 }
620 break;
621 }
623 if (isRmMsg)
624 {
625 ret = Sciclient_ProcessRmMessage(msg_recv);
626 }
628 if (isPmMsg)
629 {
630 ret = Sciclient_ProcessPmMessage(0, msg_recv);
631 }
633 if (isFwdMsg)
634 {
635 ret = Sciserver_ProcessForwardedMessage(msg_recv,
636 reqMsgSize, respMsgSize);
637 }
639 *pRespMsgSize = respMsgSize;
641 return ret;
642 }