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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 *
26 * implementation of the transport layer protocol (known as librsc protocol):
27 *
28 */
29
30 #pragma ident "%Z%%M% %I% %E% SMI"
31
32 /*
33 * Header files
34 */
35
36 #include <sys/conf.h>
37 #include <sys/cyclic.h>
38 #include <sys/membar.h>
39 #include <sys/modctl.h>
40 #include <sys/strlog.h>
41 #include <sys/sunddi.h>
42 #include <sys/ddi.h>
43 #include <sys/types.h>
44 #include <sys/rmc_comm_dp.h>
45 #include <sys/rmc_comm_dp_boot.h>
46 #include <sys/rmc_comm_drvintf.h>
47 #include <sys/rmc_comm.h>
48
49 #ifdef DEBUG_ERROR_INJECTION
50
51 #define ERRI_RX_SEQ_NUMBER 1
52 #define ERRI_ACK_MSG 2
53 #define ERRI_CRC_HEADER 3
54 #define ERRI_CRC_MSG 4
55 #define ERRI_SEND_CTL_STACK 5
56 #define ERRI_SEND_CTL_START 6
57
58 #define ERRI_CTL_RX_SEQ_NUMBER 7
59 #define ERRI_CTL_CRC_HEADER 8
60
61 int erri_test_number = 0;
62 int erri_test_intrvl = 0;
63 int erri_test_repeat = 0;
64 int erri_test_count = 0;
65
66 int erri_test_simulate_srec_sec(struct rmc_comm_state *, char *, int);
67
68 #endif
69
70
71 /* static functions */
72
73 static void dp_link_setup_tohandler(void *);
74 static void dp_delay_ack_tohandler(void *);
75 static uint8_t *dp_get_buffer(struct rmc_comm_state *, uint8_t);
76 static void dp_release_buffer(struct rmc_comm_state *, uint8_t);
77 static void dp_init_buffers(struct rmc_comm_state *);
78 static void dp_got_full_hdr(struct rmc_comm_state *, dp_packet_t *);
79 static void dp_got_bp_msg(struct rmc_comm_state *, dp_packet_t *);
80 static void dp_got_full_msg(struct rmc_comm_state *, dp_packet_t *);
81 static void dp_tx_handle_ack(struct rmc_comm_state *, uint16_t);
82 static void dp_tx_handle_nak(struct rmc_comm_state *, uint16_t);
83 static void dp_send_packet(struct rmc_comm_state *, uchar_t *);
84 static void dp_enable_data_link(struct rmc_comm_state *);
85 static int dp_get_msglen(struct rmc_comm_state *, uint8_t *);
86 static uint16_t dp_calc_crc16(uint8_t *, int);
87 void dp_wake_up_waiter(struct rmc_comm_state *, uint8_t);
88 void dp_reset(struct rmc_comm_state *, uint8_t, boolean_t, boolean_t);
89
90 /*
91 * utilities...
92 */
93
94 /*
95 * init rx/tx buffer pool
96 */
97 static void
dp_init_buffers(struct rmc_comm_state * rcs)98 dp_init_buffers(struct rmc_comm_state *rcs)
99 {
100 int i;
101 dp_buffer_t *dbuf = rcs->dp_state.dp_buffers;
102
103 for (i = 0; i < DP_BUFFER_COUNT; i++)
104 dbuf[i].in_use = 0;
105 }
106
107 /*
108 * get tx/rx buffer
109 */
110 static uint8_t *
dp_get_buffer(struct rmc_comm_state * rcs,uint8_t type)111 dp_get_buffer(struct rmc_comm_state *rcs, uint8_t type)
112 {
113 dp_buffer_t *dbuf = rcs->dp_state.dp_buffers;
114
115 ASSERT(MUTEX_HELD(rcs->dp_state.dp_mutex));
116
117 if ((type != DP_TX_BUFFER && type != DP_RX_BUFFER) ||
118 dbuf[type].in_use) {
119
120 DPRINTF(rcs, DMEM,
121 (CE_CONT, "get buffer err. type=%d, in_use=%d\n",
122 type, dbuf[type].in_use));
123
124 return (NULL);
125 }
126
127 DPRINTF(rcs, DMEM, (CE_CONT, "get buffer type=%d\n", type));
128
129 dbuf[type].in_use = 1;
130
131 return (dbuf[type].buf);
132 }
133
134 /*
135 * release tx/rx buffer
136 */
137 static void
dp_release_buffer(struct rmc_comm_state * rcs,uint8_t type)138 dp_release_buffer(struct rmc_comm_state *rcs, uint8_t type)
139 {
140 dp_buffer_t *dbuf = rcs->dp_state.dp_buffers;
141
142 ASSERT(MUTEX_HELD(rcs->dp_state.dp_mutex));
143
144 if (type != DP_TX_BUFFER && type != DP_RX_BUFFER) {
145 DPRINTF(rcs, DMEM,
146 (CE_CONT, "free buffer err. type=%d, in_use=%d\n",
147 type, dbuf[type].in_use));
148 return;
149 }
150 DPRINTF(rcs, DMEM, (CE_CONT, "free buffer type=%d\n", type));
151
152 dbuf[type].in_use = 0;
153 }
154
155 /*
156 * setup data link timeout handler
157 * (called without having the dp_mutex)
158 */
159 static void
dp_link_setup_tohandler(void * arg)160 dp_link_setup_tohandler(void *arg)
161 {
162 struct rmc_comm_state *rcs = (struct rmc_comm_state *)arg;
163 rmc_comm_dp_state_t *dps = &rcs->dp_state;
164
165 DPRINTF(rcs, DPRO, (CE_CONT, "t/o setup data link\n"));
166
167 /*
168 * check if timer has actually been cancelled
169 */
170 mutex_enter(dps->dp_mutex);
171 if (dps->timer_link_setup != (timeout_id_t)0) {
172
173 /*
174 * send CTL:start to the remote side to set up the data link
175 */
176 (void) rmc_comm_dp_ctlsend(rcs, DP_CTL_START);
177
178 dps->timer_link_setup = timeout(dp_link_setup_tohandler,
179 (void *) rcs, drv_usectohz(RETRY_DP_SETUP * 1000));
180 }
181 mutex_exit(dps->dp_mutex);
182 }
183
184 /*
185 * delay acknowledgment of a received message timeout handler
186 * (called without having the dp_mutex)
187 */
188 static void
dp_delay_ack_tohandler(void * arg)189 dp_delay_ack_tohandler(void *arg)
190 {
191 struct rmc_comm_state *rcs = (struct rmc_comm_state *)arg;
192 rmc_comm_dp_state_t *dps = &rcs->dp_state;
193
194 #ifdef DEBUG_ERROR_INJECTION
195
196 if (erri_test_number == ERRI_ACK_MSG &&
197 erri_test_repeat >= 0 &&
198 erri_test_count++ > 0 && !(erri_test_count % erri_test_intrvl)) {
199
200 /*
201 * DON'T ACK THE MESSAGE - BE SILENT!
202 */
203
204 if (erri_test_repeat == 0)
205 erri_test_repeat--; /* will not repeat the test */
206
207 dps->timer_delay_ack = (timeout_id_t)0;
208 return;
209 }
210
211 #endif
212
213 /*
214 * check if timer has actually been cancelled
215 */
216 mutex_enter(dps->dp_mutex);
217 if (dps->timer_delay_ack != (timeout_id_t)0) {
218 /*
219 * ACK the message
220 */
221 (void) rmc_comm_dp_ctlsend(rcs, DP_CTL_ACK);
222 dps->timer_delay_ack = (timeout_id_t)0;
223 }
224 mutex_exit(dps->dp_mutex);
225 }
226
227 /*
228 * Enable data link protocol:
229 * stop data link setup timer
230 * set data_link_ok flag
231 * (must already have the dp_mutex)
232 */
233 static void
dp_enable_data_link(struct rmc_comm_state * rcs)234 dp_enable_data_link(struct rmc_comm_state *rcs)
235 {
236 rmc_comm_dp_state_t *dps = &rcs->dp_state;
237 timeout_id_t timer_id;
238
239 ASSERT(MUTEX_HELD(dps->dp_mutex));
240
241 dps->data_link_ok = 1;
242
243 timer_id = dps->timer_link_setup;
244 dps->timer_link_setup = (timeout_id_t)0;
245 if (timer_id != (timeout_id_t)0) {
246
247 mutex_exit(dps->dp_mutex);
248 (void) untimeout(timer_id);
249 mutex_enter(dps->dp_mutex);
250 }
251 }
252
253 /*
254 * CRC calculation routine.
255 */
256 static uint16_t
dp_calc_crc16(uint8_t * buf,int len)257 dp_calc_crc16(uint8_t *buf, int len)
258 {
259 extern uint16_t crctab16[];
260 uint16_t crc;
261
262 crc = 0;
263 while (len--) {
264 crc = (crc >> 8) ^ crctab16[(crc ^ *buf++) & 0xFF];
265 }
266 return (crc);
267 }
268
269 /*
270 * Reset the data protocol
271 * (dp_mutex must be held)
272 */
273 void
dp_reset(struct rmc_comm_state * rcs,uint8_t rx_seqid,boolean_t flush_tx,boolean_t restart_data_link)274 dp_reset(struct rmc_comm_state *rcs, uint8_t rx_seqid,
275 boolean_t flush_tx, boolean_t restart_data_link)
276 {
277 rmc_comm_dp_state_t *dps = &rcs->dp_state;
278
279 ASSERT(MUTEX_HELD(dps->dp_mutex));
280
281 DPRINTF(rcs, DPRO, (CE_CONT,
282 "reset proto: rxsid=%d, flushtx=%d, restartdp=%d\n",
283 rx_seqid, flush_tx, restart_data_link));
284
285 DPRINTF(rcs, DGEN, (CE_CONT,
286 "stats: reset=%d nak=%d start=%d stack=%d retries=%d crcerr=%d\n",
287 dps->reset_cnt, dps->nak_cnt, dps->start_cnt, dps->stack_cnt,
288 dps->retries_cnt, dps->crcerr_cnt));
289
290 dps->last_rx_seqid = rx_seqid;
291 dps->reset_cnt++;
292
293 /*
294 * Flush pending tx message.
295 */
296 if (flush_tx) {
297 dps->last_tx_seqid = INITIAL_SEQID;
298 dps->last_rx_ack = rx_seqid;
299
300 /*
301 * if there is any pending request/response session
302 * then just abort it.
303 */
304 dp_wake_up_waiter(rcs, MSG_ERROR);
305 }
306
307 /*
308 * restart data link, but only if the data link set up timer is
309 * not already running.
310 */
311 if (restart_data_link && dps->timer_link_setup == (timeout_id_t)0) {
312
313 dps->data_link_ok = 0;
314
315 /*
316 * set up the data protocol link
317 */
318 (void) rmc_comm_dp_ctlsend(rcs, DP_CTL_START);
319 dps->timer_link_setup = timeout(dp_link_setup_tohandler,
320 (void *)rcs, drv_usectohz(RETRY_DP_SETUP * 1000));
321 }
322 }
323
324 /*
325 * Handles acknowledgment of a message previously sent OR a heartbeat command
326 * (CTL_RESPOND).
327 */
328 static void
dp_tx_handle_ack(struct rmc_comm_state * rcs,uint16_t rxnum)329 dp_tx_handle_ack(struct rmc_comm_state *rcs, uint16_t rxnum)
330 {
331 rmc_comm_dp_state_t *dps = &rcs->dp_state;
332 dp_req_resp_t *drr = &dps->req_resp;
333
334 ASSERT(MUTEX_HELD(dps->dp_mutex));
335
336 DPRINTF(rcs, DPRO, (CE_CONT, "handle ACK, rxnum=%03d\n", rxnum));
337
338 dps->last_rx_ack = rxnum;
339 if ((drr->flags & MSG_SENT) == 0) {
340 /*
341 * no pending messages, so nothing to do
342 */
343 return;
344 }
345
346 if (rxnum == dps->last_tx_seqid) {
347 /*
348 * message was sent and acknowledged successfully
349 * set flag and signal the waiting task if it is not
350 * expecting a reply back
351 */
352 drr->flags |= MSG_ACKED;
353 if (drr->response.msg_type == DP_NULL_MSG) {
354 dp_wake_up_waiter(rcs, MSG_ACKED);
355 }
356 }
357 }
358
359 /*
360 * Handles NAK
361 */
362 static void
dp_tx_handle_nak(struct rmc_comm_state * rcs,uint16_t rxnum)363 dp_tx_handle_nak(struct rmc_comm_state *rcs, uint16_t rxnum)
364 {
365 rmc_comm_dp_state_t *dps = &rcs->dp_state;
366 dp_req_resp_t *drr = &dps->req_resp;
367
368 ASSERT(MUTEX_HELD(dps->dp_mutex));
369
370 DPRINTF(rcs, DPRO, (CE_CONT, "handle NAK, rxnum=%03d\n", rxnum));
371
372 if ((drr->flags & MSG_SENT) == 0) {
373 /*
374 * no pending messages, so nothing to do
375 */
376 return;
377 }
378
379 /*
380 * since one message per time can be sent, it is assumed that the
381 * message being NAKed is just the one that has been sent.
382 */
383 dps->nak_cnt++;
384
385 dp_wake_up_waiter(rcs, MSG_NAKED);
386 }
387
388 /*
389 * Got a full header. Check header CRC and get the length of the packet
390 */
391 static void
dp_got_full_hdr(struct rmc_comm_state * rcs,dp_packet_t * pkt)392 dp_got_full_hdr(struct rmc_comm_state *rcs, dp_packet_t *pkt)
393 {
394 /*
395 * Got the full header. Call up to the logical layer to see
396 * how big of a buffer I need for this message. If the size
397 * is < sizeof (dp_msg_t), then there is something wrong with
398 * this message - drop it. If the size is equal, then hand it
399 * up right now. If the size is too big - drop it. otherwise we must
400 * receive the body of the message.
401 */
402
403 pkt->full_length = dp_get_msglen(rcs, pkt->buf);
404
405 DPRINTF(rcs, DPKT, (CE_CONT, "got header msglen=%d\n",
406 pkt->full_length));
407
408 if ((pkt->full_length < 0) ||
409 (pkt->full_length < sizeof (dp_header_t)) ||
410 (pkt->full_length > DP_BUFFER_SIZE)) {
411 /*
412 * not a valid message: either message too big or too small
413 */
414 dp_release_buffer(rcs, DP_RX_BUFFER);
415 pkt->buf = NULL;
416
417 pkt->rx_state = WAITING_FOR_SYNC;
418
419 } else if (pkt->full_length == sizeof (dp_header_t)) {
420 /*
421 * process message: it is basically a control message
422 * (no data being carried)
423 */
424 rmc_comm_dp_mrecv(rcs, pkt->buf);
425
426 dp_release_buffer(rcs, DP_RX_BUFFER);
427 pkt->buf = NULL;
428
429 pkt->rx_state = WAITING_FOR_SYNC;
430 } else {
431 pkt->rx_state = RECEIVING_BODY;
432 }
433 }
434
435 /*
436 * Got a BP (boot prom) message. Usually, BP messages are received when
437 * the firmware goes into boot monitor mode (where only BP protocol is used).
438 * This just happens during firmware download. There should not be any other
439 * case where a BP message is received.
440 */
441 static void
dp_got_bp_msg(struct rmc_comm_state * rcs,dp_packet_t * pkt)442 dp_got_bp_msg(struct rmc_comm_state *rcs, dp_packet_t *pkt)
443 {
444 bp_msg_t *msgp = (bp_msg_t *)pkt->buf;
445 rmc_comm_dp_state_t *dps = &rcs->dp_state;
446 dp_req_resp_t *drr = &dps->req_resp;
447 int datalen = sizeof (bp_msg_t);
448
449 ASSERT(MUTEX_HELD(dps->dp_mutex));
450
451 /*
452 * ignore BP message, if it is not expected
453 */
454 if ((drr->flags & MSG_SENT_BP) != 0) {
455
456 DPRINTF(rcs, DPRO, (CE_CONT, "got bp msg: %02x %02x %02x\n",
457 msgp->cmd, msgp->dat1, msgp->dat2));
458
459 /*
460 * A boot prom (BP) msg has been sent. Here is the
461 * 'expected' reply
462 */
463
464 /*
465 * check that the recv buffer is big enough (just in case).
466 */
467 if (datalen <= drr->response.msg_bufsiz) {
468 bcopy(pkt->buf, drr->response.msg_buf, datalen);
469 drr->response.msg_msglen = datalen;
470 dp_wake_up_waiter(rcs, MSG_RXED_BP);
471 } else {
472 drr->response.msg_msglen = -1;
473 dp_wake_up_waiter(rcs, MSG_RXED_BP);
474 }
475 }
476
477 /* Return the buffer to the pool and wait for the next msg. */
478 dp_release_buffer(rcs, DP_RX_BUFFER);
479 pkt->buf = NULL;
480 pkt->rx_state = WAITING_FOR_SYNC;
481 }
482
483 /*
484 * Got a complete message, check CRC and pass it on to the upper layer (message
485 * processing)
486 */
487 static void
dp_got_full_msg(struct rmc_comm_state * rcs,dp_packet_t * pkt)488 dp_got_full_msg(struct rmc_comm_state *rcs, dp_packet_t *pkt)
489 {
490 uint16_t crc;
491 int msglen;
492
493 DPRINTF(rcs, DPKT, (CE_CONT, "got full msg\n"));
494
495 /*
496 * check message CRC
497 */
498
499 msglen = pkt->full_length - sizeof (dp_header_t) - sizeof (crc);
500
501 bcopy(pkt->buf + (pkt->full_length - sizeof (crc)), &crc, sizeof (crc));
502
503 if (crc == dp_calc_crc16(pkt->buf + sizeof (dp_header_t), msglen)) {
504 /*
505 * CRC is ok, process this message
506 */
507 DPRINTF(rcs, DPKT, (CE_CONT, "got 'good' msg\n"));
508
509 rmc_comm_dp_mrecv(rcs, pkt->buf);
510 } else {
511 DPRINTF(rcs, DPKT, (CE_CONT, "CRC error (msg)\n"));
512 rcs->dp_state.crcerr_cnt++;
513 }
514
515 dp_release_buffer(rcs, DP_RX_BUFFER);
516 pkt->buf = NULL;
517
518 pkt->rx_state = WAITING_FOR_SYNC;
519 }
520
521 /*
522 * Check the checksum of the header & return the length field. If the
523 * checksum check fails, then return -1.
524 */
525 static int
dp_get_msglen(struct rmc_comm_state * rcs,uint8_t * buf)526 dp_get_msglen(struct rmc_comm_state *rcs, uint8_t *buf)
527 {
528 dp_header_t *dp_msgp;
529 uint16_t crc;
530
531 dp_msgp = (dp_header_t *)buf;
532
533 crc = dp_calc_crc16(buf + sizeof (dp_msgp->pad), sizeof (dp_header_t) -
534 sizeof (dp_msgp->crc) - sizeof (dp_msgp->pad));
535
536 if (dp_msgp->crc == crc) {
537 return (dp_msgp->length + sizeof (dp_msgp->pad));
538 } else {
539 DPRINTF(rcs, DPKT, (CE_CONT, "CRC error (header)\n"));
540 rcs->dp_state.crcerr_cnt++;
541 return (-1);
542 }
543 }
544
545 /*
546 * to send a protocol packet to the remote side. it handles escaping SYNC
547 * and ESC chars
548 */
549 static void
dp_send_packet(struct rmc_comm_state * rcs,uchar_t * buf)550 dp_send_packet(struct rmc_comm_state *rcs, uchar_t *buf)
551 {
552 char syncbuf[2];
553 dp_header_t *dp_msgp = (dp_header_t *)buf;
554 int total, cur;
555
556 /* First, send out two SYNC characters. */
557 syncbuf[0] = syncbuf[1] = (char)SYNC_CHAR;
558 rmc_comm_serdev_send(rcs, syncbuf, 2);
559
560 total = dp_msgp->length;
561 buf = buf + sizeof (dp_msgp->pad);
562
563 while (total > 0) {
564 cur = 0;
565
566 /* Count up characters that don't need ESC'ing. */
567 while ((cur < total) &&
568 (buf[cur] != ESC_CHAR) &&
569 (buf[cur] != SYNC_CHAR)) {
570 cur++;
571 }
572
573 /* Send characters that don't need escaping, if any. */
574 if (cur > 0) {
575 rmc_comm_serdev_send(rcs, (char *)buf, cur);
576 total -= cur;
577 buf += cur;
578 }
579
580 /*
581 * If total > 0 at this point, we need to send an
582 * ESC'd character. Send as many as there are.
583 */
584 while ((total > 0) &&
585 ((*buf == SYNC_CHAR) || (*buf == ESC_CHAR))) {
586 syncbuf[0] = (char)ESC_CHAR;
587 syncbuf[1] = *buf;
588 rmc_comm_serdev_send(rcs, syncbuf, 2);
589 buf++;
590 total--;
591 }
592 }
593 }
594
595 /*
596 * to wake a thread waiting for a reply/ACK/error status for a request/response
597 * session.
598 */
599 void
dp_wake_up_waiter(struct rmc_comm_state * rcs,uint8_t flags)600 dp_wake_up_waiter(struct rmc_comm_state *rcs, uint8_t flags)
601 {
602 dp_req_resp_t *drr = &rcs->dp_state.req_resp;
603
604 ASSERT(MUTEX_HELD(rcs->dp_state.dp_mutex));
605
606 DPRINTF(rcs, DGEN, (CE_CONT, "wake up? %x, set %x\n",
607 (drr->flags & (MSG_SENT | MSG_SENT_BP)) != 0, flags));
608
609 if ((drr->flags & (MSG_SENT | MSG_SENT_BP)) != 0) {
610 drr->flags |= flags;
611 cv_signal(drr->cv_wait_reply);
612 }
613 }
614
615 /*
616 * initialization of the data protocol (called from the attach routine)
617 */
618 void
rmc_comm_dp_init(struct rmc_comm_state * rcs)619 rmc_comm_dp_init(struct rmc_comm_state *rcs)
620 {
621 rmc_comm_dp_state_t *dps = &rcs->dp_state;
622 dp_packet_t *pkt = &dps->dp_packet;
623
624 DPRINTF(rcs, DGEN, (CE_CONT, "rmc_comm_dp_init\n"));
625
626 /*
627 * initialize data structure:
628 */
629 bzero((void *) dps, sizeof (rmc_comm_dp_state_t));
630
631 /*
632 * initialize packet receive handler state
633 */
634
635 pkt->rx_state = WAITING_FOR_SYNC;
636
637 /*
638 * cv variables initialization
639 * (dp_mutex has been already created during the serial device
640 * initialization)
641 */
642 cv_init(dps->cv_ok_to_send, NULL, CV_DRIVER, NULL);
643 cv_init(dps->req_resp.cv_wait_reply, NULL, CV_DRIVER, NULL);
644
645 mutex_enter(dps->dp_mutex);
646
647 dp_init_buffers(rcs);
648
649 /*
650 * initialize the data protocol (reset sequence numbers, etc.)
651 */
652 dps->last_tx_seqid = INITIAL_SEQID;
653 dps->last_rx_seqid = dps->last_rx_ack = INITIAL_SEQID;
654
655 /*
656 * start timer to 'delay' the set up of the data protocol link
657 */
658 dps->timer_link_setup = timeout(dp_link_setup_tohandler,
659 (void *)rcs, drv_usectohz(DELAY_DP_SETUP * 1000));
660
661 mutex_exit(dps->dp_mutex);
662
663 #ifdef DEBUG_ERROR_INJECTION
664
665 erri_test_number = ddi_prop_get_int(DDI_DEV_T_ANY, rcs->dip,
666 DDI_PROP_DONTPASS, "test-no", 0);
667 erri_test_intrvl = ddi_prop_get_int(DDI_DEV_T_ANY, rcs->dip,
668 DDI_PROP_DONTPASS, "test-interval", 0);
669 erri_test_repeat = ddi_prop_get_int(DDI_DEV_T_ANY, rcs->dip,
670 DDI_PROP_DONTPASS, "test-repeat", 0);
671
672 erri_test_count = 0;
673
674
675 cmn_err(CE_CONT, "error injection test: no=%d, intrvl=%d, rep=%d\n",
676 erri_test_number, erri_test_intrvl, erri_test_repeat);
677 #endif
678
679 }
680
681 /*
682 * termination of the data protocol (called from the detach routine)
683 */
684 void
rmc_comm_dp_fini(struct rmc_comm_state * rcs)685 rmc_comm_dp_fini(struct rmc_comm_state *rcs)
686 {
687 rmc_comm_dp_state_t *dps = &rcs->dp_state;
688 timeout_id_t tid_delay_ack;
689 timeout_id_t tid_link_setup;
690
691 DPRINTF(rcs, DGEN, (CE_CONT,
692 "stats: reset=%d nak=%d start=%d stack=%d retries=%d crcerr=%d\n",
693 dps->reset_cnt, dps->nak_cnt, dps->start_cnt, dps->stack_cnt,
694 dps->retries_cnt, dps->crcerr_cnt));
695
696 /*
697 * if any timer is running, must be terminated here!
698 */
699 mutex_enter(dps->dp_mutex);
700 tid_delay_ack = dps->timer_link_setup;
701 tid_link_setup = dps->timer_delay_ack;
702 dps->timer_link_setup = (timeout_id_t)0;
703 dps->timer_delay_ack = (timeout_id_t)0;
704 mutex_exit(dps->dp_mutex);
705
706 if (tid_delay_ack)
707 (void) untimeout(tid_delay_ack);
708
709 if (tid_link_setup)
710 (void) untimeout(tid_link_setup);
711
712 /*
713 * cv variables termination
714 */
715 cv_destroy(dps->cv_ok_to_send);
716 cv_destroy(dps->req_resp.cv_wait_reply);
717 }
718
719 /*
720 * This is the low-level receiver handler. It's job is to find a complete
721 * message from the incoming data stream, and once it finds one to pass it
722 * on to the upper layer (message processing).
723 * (it must have the dp_mutex)
724 */
725 void
rmc_comm_dp_drecv(struct rmc_comm_state * rcs,uint8_t * buf,int buflen)726 rmc_comm_dp_drecv(struct rmc_comm_state *rcs, uint8_t *buf, int buflen)
727 {
728 rmc_comm_dp_state_t *dps = &rcs->dp_state;
729 dp_packet_t *pkt = &dps->dp_packet;
730 uint8_t quit;
731 int count;
732 int max;
733
734 ASSERT(MUTEX_HELD(dps->dp_mutex));
735
736 pkt->inbuf = buf;
737 pkt->inbuflen = buflen;
738
739 DPRINTF(rcs, DPKT, (CE_CONT, "drecv len=%d\n", buflen));
740
741 while (pkt->inbuflen > 0) {
742 switch (pkt->rx_state) {
743
744 case WAITING_FOR_SYNC:
745 while ((pkt->inbuflen > 0) &&
746 (*pkt->inbuf != SYNC_CHAR) &&
747 (*pkt->inbuf != ESC_CHAR)) {
748
749 DPRINTF(rcs, DPKT,
750 (CE_CONT, "not SYNC: %02x\n",
751 (uchar_t)(*pkt->inbuf)));
752
753 pkt->inbuf++;
754 pkt->inbuflen--;
755 }
756
757 if (pkt->inbuflen > 0) {
758 if (*pkt->inbuf == SYNC_CHAR)
759 pkt->rx_state = WAITING_FOR_HDR;
760 else if (*pkt->inbuf == ESC_CHAR)
761 pkt->rx_state = WAITING_FOR_SYNC_ESC;
762 }
763 break;
764
765 case WAITING_FOR_SYNC_ESC:
766 pkt->inbuf++;
767 pkt->inbuflen--;
768 pkt->rx_state = WAITING_FOR_SYNC;
769 break;
770
771 case WAITING_FOR_HDR:
772 while ((pkt->inbuflen > 0) &&
773 (*pkt->inbuf == SYNC_CHAR)) {
774 pkt->inbuf++;
775 pkt->inbuflen--;
776 }
777
778 if (pkt->inbuflen <= 0)
779 break;
780
781 if (*pkt->inbuf == ESC_CHAR) {
782 /*
783 * ESC as first char of header?
784 * Impossible - start over!
785 */
786 pkt->rx_state = WAITING_FOR_SYNC;
787 pkt->inbuf++;
788 pkt->inbuflen--;
789 break;
790 }
791
792 /* Get a buffer for this message. */
793 pkt->buf = dp_get_buffer(rcs, DP_RX_BUFFER);
794 if (pkt->buf == NULL) {
795 /* Out of buffers - drop this msg. */
796 pkt->rx_state = WAITING_FOR_SYNC;
797 break;
798 }
799 DPRINTF(rcs, DPKT, (CE_CONT, "drecv first char %x\n",
800 (uchar_t)*pkt->inbuf));
801
802 pkt->buf[1] = *pkt->inbuf;
803 pkt->bufpos = 2;
804 pkt->rx_state = RECEIVING_HDR;
805
806 pkt->inbuf++;
807 pkt->inbuflen--;
808 break;
809
810 case RECEIVING_HDR:
811 quit = 0;
812 while ((pkt->inbuflen > 0) &&
813 (*pkt->inbuf != SYNC_CHAR) &&
814 (*pkt->inbuf != ESC_CHAR)) {
815 pkt->buf[pkt->bufpos++] = *pkt->inbuf;
816 pkt->inbuf++;
817 pkt->inbuflen--;
818 if (pkt->bufpos >= sizeof (dp_header_t)) {
819 dp_got_full_hdr(rcs, pkt);
820 quit = 1;
821 break;
822 } else if ((pkt->bufpos >= sizeof (bp_msg_t)) &&
823 (IS_BOOT_MSG(pkt->buf[1]))) {
824 dp_got_bp_msg(rcs, pkt);
825 quit = 1;
826 break;
827 }
828 }
829
830 if (quit)
831 break;
832
833 if (pkt->inbuflen > 0) {
834 /* Must have gotten an ESC_CHAR or SYNC_CHAR. */
835 if (*pkt->inbuf == SYNC_CHAR) {
836
837 DPRINTF(rcs, DPKT,
838 (CE_CONT, "drecv sync in hdr, "
839 "bufpos=%d\n", pkt->bufpos));
840
841 dp_release_buffer(rcs, DP_RX_BUFFER);
842 pkt->buf = NULL;
843 pkt->rx_state = WAITING_FOR_HDR;
844 } else {
845 pkt->rx_state = RECEIVING_HDR_ESC;
846 }
847 pkt->inbuf++;
848 pkt->inbuflen--;
849 }
850 break;
851
852 case RECEIVING_HDR_ESC:
853 pkt->buf[pkt->bufpos++] = *pkt->inbuf;
854 pkt->inbuf++;
855 pkt->inbuflen--;
856 if (pkt->bufpos >= sizeof (dp_header_t)) {
857 dp_got_full_hdr(rcs, pkt);
858 } else if ((pkt->bufpos >= sizeof (bp_msg_t)) &&
859 (IS_BOOT_MSG(pkt->buf[1]))) {
860 dp_got_bp_msg(rcs, pkt);
861 } else {
862 pkt->rx_state = RECEIVING_HDR;
863 }
864 break;
865
866 case RECEIVING_BODY:
867 max = pkt->full_length - pkt->bufpos;
868 if (max > pkt->inbuflen)
869 max = pkt->inbuflen;
870
871 for (count = 0; count < max; count++)
872 if ((pkt->inbuf[count] == SYNC_CHAR) ||
873 (pkt->inbuf[count] == ESC_CHAR))
874 break;
875
876 if (count > 0) {
877 bcopy(pkt->inbuf, pkt->buf + pkt->bufpos,
878 count);
879 pkt->inbuf += count;
880 pkt->inbuflen -= count;
881 pkt->bufpos += count;
882
883 if (pkt->bufpos >= pkt->full_length) {
884 dp_got_full_msg(rcs, pkt);
885 break;
886 }
887 }
888
889 if (count < max) {
890 /* Must have gotten an ESC_CHAR or SYNC_CHAR. */
891 if (*pkt->inbuf == SYNC_CHAR) {
892 dp_release_buffer(rcs, DP_RX_BUFFER);
893 pkt->buf = NULL;
894 pkt->rx_state = WAITING_FOR_HDR;
895 } else {
896 pkt->rx_state = RECEIVING_BODY_ESC;
897 }
898 pkt->inbuf++;
899 pkt->inbuflen--;
900 }
901 break;
902
903 case RECEIVING_BODY_ESC:
904 pkt->buf[pkt->bufpos] = *pkt->inbuf;
905 pkt->inbuf++;
906 pkt->inbuflen--;
907 pkt->bufpos++;
908 if (pkt->bufpos >= pkt->full_length) {
909 dp_got_full_msg(rcs, pkt);
910 } else {
911 pkt->rx_state = RECEIVING_BODY;
912 }
913 break;
914 }
915 }
916 }
917
918 /*
919 * Handle an incoming message. CRCs have been already checked so message
920 * is good. check if sequence numbers are ok.
921 * Handles: control message, asynchronous notification, reply to requests
922 * and notify the leaf driver of those events.
923 * (it must have the dp_mutex)
924 */
925 void
rmc_comm_dp_mrecv(struct rmc_comm_state * rcs,uint8_t * buf)926 rmc_comm_dp_mrecv(struct rmc_comm_state *rcs, uint8_t *buf)
927 {
928 rmc_comm_dp_state_t *dps = &rcs->dp_state;
929 dp_header_t *dp_msgp;
930 uint8_t *datap;
931 int datalen;
932 dp_msg_intr_t *dmi = &dps->msg_intr;
933 dp_req_resp_t *drr = &dps->req_resp;
934
935 ASSERT(MUTEX_HELD(dps->dp_mutex));
936
937 dp_msgp = (dp_header_t *)buf;
938
939 datalen = dp_msgp->length -
940 (sizeof (dp_header_t) - sizeof (dp_msgp->pad));
941
942 if (datalen > 0) {
943 datalen = datalen - sizeof (uint16_t); /* don't count msg CRC */
944 datap = buf + sizeof (dp_header_t);
945 } else {
946 datap = NULL;
947 }
948
949 DPRINTF(rcs, DPRO, (CE_CONT,
950 "[t%03dr%03d] mrecv msgtype: %02x, len=%d\n",
951 dp_msgp->txnum, dp_msgp->rxnum, dp_msgp->type, datalen));
952
953 /*
954 * Handle control messages first
955 */
956 if (IS_UNNUMBERED_MSG(dp_msgp->type)) {
957 switch (dp_msgp->type) {
958 case DP_CTL_START:
959 /*
960 * CTL:start
961 * Re-init protocol processing.
962 * Enable data link
963 * Stop data link setup timer if running
964 */
965 DPRINTF(rcs, DPRO, (CE_CONT, "mrecv data link ok\n"));
966
967 dp_reset(rcs, dp_msgp->txnum, 1, 0);
968
969 dp_wake_up_waiter(rcs, 0);
970
971 /* Send CTL:stack message. */
972 (void) rmc_comm_dp_ctlsend(rcs, DP_CTL_STACK);
973
974 dps->start_cnt++;
975
976 dp_enable_data_link(rcs);
977
978 break;
979
980 case DP_CTL_STACK:
981 /*
982 * CTL:stack
983 * Enable data link
984 * Stop data link setup timer if running
985 */
986 DPRINTF(rcs, DPRO, (CE_CONT, "mrecv data link ok\n"));
987
988 dp_reset(rcs, dp_msgp->txnum, 0, 0);
989
990 dp_wake_up_waiter(rcs, 0);
991
992 dps->stack_cnt++;
993
994 dp_enable_data_link(rcs);
995 break;
996
997 case DP_CTL_RESPOND:
998 /*
999 * CTL:respond (heartbeat)
1000 * Send a CTL:ack.
1001 */
1002 if (dps->data_link_ok) {
1003 (void) rmc_comm_dp_ctlsend(rcs, DP_CTL_ACK);
1004 }
1005 break;
1006
1007 case DP_CTL_ACK:
1008 /*
1009 * CTL:ack
1010 * Call a transmit-side routine to handle it.
1011 */
1012 dp_tx_handle_ack(rcs, dp_msgp->rxnum);
1013 break;
1014
1015 case DP_CTL_NAK:
1016 /*
1017 * CTL:nak
1018 * Call a transmit-side routine to handle it.
1019 */
1020 dp_tx_handle_nak(rcs, dp_msgp->rxnum);
1021 break;
1022
1023 default:
1024 /* Drop message. */
1025 DPRINTF(rcs, DPRO,
1026 (CE_CONT, "mrecv unknown ctrlmsg\n"));
1027 break;
1028 }
1029 return;
1030 }
1031
1032 /*
1033 * Before processing the received message (NUMBERED), check that the
1034 * data link protocol is up. If not, ignore this message
1035 */
1036 if (!dps->data_link_ok) {
1037 DPRINTF(rcs, DPRO, (CE_CONT, "mrecv drop msg: no data link\n"));
1038 return;
1039 }
1040
1041 /*
1042 * we received a message (NUMBERED) and data link is ok.
1043 * First, instead of ACKing this message now, we delay it. The reason
1044 * why is that a message can be sent (from this side) in the meantime
1045 * and it can ACK the received message (it will spare us to send
1046 * the ACK message across the wire).
1047 */
1048
1049 /*
1050 * Handle acknowledgements even if this is a duplicate message.
1051 */
1052 if (dps->timer_delay_ack == (timeout_id_t)0) {
1053 dps->timer_delay_ack = timeout(dp_delay_ack_tohandler,
1054 (void *) rcs, drv_usectohz(TX_RETRY_TIME/2 * 1000));
1055 DPRINTF(rcs, DGEN, (CE_CONT, "mrecv start ack t/o %p\n",
1056 dps->timer_delay_ack));
1057 }
1058 dp_tx_handle_ack(rcs, dp_msgp->rxnum);
1059
1060 if (dp_msgp->txnum != NEXT_SEQID(dps->last_rx_seqid)) {
1061 /* Duplicate message - free it up & return. */
1062 DPRINTF(rcs, DPRO, (CE_CONT, "mrecv dup msg txnum=%03d\n",
1063 dp_msgp->txnum));
1064 return;
1065 }
1066 dps->last_rx_seqid = dp_msgp->txnum;
1067
1068 #ifdef DEBUG_ERROR_INJECTION
1069
1070 if ((erri_test_number == ERRI_SEND_CTL_STACK ||
1071 erri_test_number == ERRI_SEND_CTL_START) &&
1072 erri_test_repeat >= 0 &&
1073 erri_test_count++ > 0 && !(erri_test_count % erri_test_intrvl)) {
1074
1075 if (erri_test_number == ERRI_SEND_CTL_STACK) {
1076 (void) rmc_comm_dp_ctlsend(rcs, DP_CTL_STACK);
1077
1078 } else if (erri_test_number == ERRI_SEND_CTL_START) {
1079 (void) rmc_comm_dp_ctlsend(rcs, DP_CTL_START);
1080
1081 }
1082 if (erri_test_repeat == 0)
1083 erri_test_repeat--; /* will not repeat the test */
1084 }
1085
1086 #endif
1087
1088 /*
1089 * At this point, we know this is a good message. We've
1090 * checked checksums, message types, and sequence id's.
1091 */
1092
1093 /*
1094 * First, check if a driver has register for this message
1095 * Second, check if this message is a reply to a request
1096 * Third, check to see if ALOM is telling us it doesn't
1097 * know about the command code.
1098 */
1099
1100 if (dmi->intr_handler != NULL &&
1101 dmi->intr_msg_type == dp_msgp->type) {
1102
1103 rmc_comm_msg_t *msgi = (rmc_comm_msg_t *)dmi->intr_arg;
1104
1105 DPRINTF(rcs, DPRO, (CE_CONT,
1106 "mrecv process async msg len=%d, max=%d\n",
1107 datalen, msgi->msg_len));
1108 /*
1109 * process asynchronous notification only if the registered
1110 * driver is not currently processing any other notification
1111 */
1112 mutex_enter(dmi->intr_lock);
1113 if (dmi->intr_state == NULL ||
1114 (dmi->intr_state != NULL &&
1115 *(dmi->intr_state) == RMC_COMM_INTR_IDLE)) {
1116 /*
1117 * check that the buffer is big enough. do not want to
1118 * cross boundaries here..
1119 */
1120 if (datalen <= msgi->msg_len) {
1121 bcopy(datap, msgi->msg_buf, datalen);
1122 msgi->msg_bytes = datalen;
1123
1124 } else {
1125 msgi->msg_bytes = -1;
1126 }
1127 /*
1128 * trigger soft intr. in any case.
1129 * if message is too big, at least, the leaf driver
1130 * will be notified (bytes returned will be -1)
1131 */
1132 ddi_trigger_softintr(dmi->intr_id);
1133 }
1134 mutex_exit(dmi->intr_lock);
1135
1136 } else if ((drr->flags & MSG_SENT) != 0 &&
1137 drr->response.msg_type == dp_msgp->type) {
1138
1139 DPRINTF(rcs, DPRO, (CE_CONT,
1140 "mrecv process reply len=%d, max=%d\n",
1141 datalen, drr->response.msg_bufsiz));
1142
1143 /*
1144 * check that the recv buffer is big enough.
1145 */
1146 if (datalen <= drr->response.msg_bufsiz) {
1147 bcopy(datap, drr->response.msg_buf, datalen);
1148 drr->response.msg_msglen = datalen;
1149 dp_wake_up_waiter(rcs, MSG_REPLY_RXED);
1150 } else {
1151 drr->response.msg_msglen = -1;
1152 dp_wake_up_waiter(rcs, MSG_REPLY_RXED);
1153 }
1154 } else if (dp_msgp->type == DP_INVCMD &&
1155 (drr->flags & MSG_SENT) != 0 &&
1156 ((dp_invcmd_t *)datap)->inv_type == drr->request.msg_type) {
1157 drr->error_status = RCEINVCMD;
1158 dp_wake_up_waiter(rcs, MSG_ERROR);
1159 }
1160 }
1161
1162 /*
1163 * to send a control message (unnumbered message)
1164 * (it must have the dp_mutex)
1165 */
1166 int
rmc_comm_dp_ctlsend(struct rmc_comm_state * rcs,uint8_t type)1167 rmc_comm_dp_ctlsend(struct rmc_comm_state *rcs, uint8_t type)
1168 {
1169 dp_message_t ctlmsg;
1170 int err = RCNOERR;
1171
1172 ctlmsg.msg_type = type;
1173 ctlmsg.msg_buf = NULL;
1174 ctlmsg.msg_msglen = 0;
1175
1176 err = rmc_comm_dp_msend(rcs, &ctlmsg);
1177
1178 return (err);
1179 }
1180
1181 /*
1182 * to send data to the remote party.
1183 *
1184 * NUMBERED messages carry payload data of variable size. A buffer is allocated
1185 * dynamically for the trasmission of data. NUMBERED message trasmission
1186 * data status is stored in the dp_state request_response data structure.
1187 * This because: data sent must be acknowledged, trasmission can be re-tried,
1188 * upper layer has to know the state/result of the trasmission. Upper layer has
1189 * to: initialize the data struct, send data (this function), read result,
1190 * clean up the data struct.
1191 *
1192 * UNUMBERED data are just only control command which do not carry any payload
1193 * A local buffer is used (ctlbuf) instead. UNNUMBERED message are transient
1194 * data which is sent once and not re-tried. It does not use the
1195 * request_response data structure
1196 *
1197 * (it must have the dp_mutex)
1198 */
1199 int
rmc_comm_dp_msend(struct rmc_comm_state * rcs,dp_message_t * req)1200 rmc_comm_dp_msend(struct rmc_comm_state *rcs, dp_message_t *req)
1201 {
1202 rmc_comm_dp_state_t *dps = &rcs->dp_state;
1203 dp_req_resp_t *drr = &dps->req_resp;
1204 dp_message_t *pkt;
1205 dp_header_t *dp_msgp;
1206 dp_message_t ctl;
1207 dp_header_t ctlbuf;
1208 uint16_t data_crc;
1209 timeout_id_t timer_delay_ack = 0;
1210 char first_time = 0;
1211
1212 ASSERT(MUTEX_HELD(dps->dp_mutex));
1213
1214 DPRINTF(rcs, DPRO, (CE_CONT, "msend msgtype=%02x\n", req->msg_type));
1215
1216 if (IS_NUMBERED_MSG(req->msg_type)) {
1217 /*
1218 * if there was an error, just return the error.
1219 * Otherwise if the message was already acknowledged
1220 * (NUMBERED message) then, there is no need to (re)send it.
1221 * just wait for an expected reply (hence, do not return an
1222 * error)
1223 */
1224 if ((drr->flags & MSG_ERROR) != 0) {
1225
1226 DPRINTF(rcs, DPRO, (CE_CONT,
1227 "msg send error flag=%02x\n", drr->flags));
1228 return (RCEGENERIC);
1229
1230 } else if ((drr->flags & MSG_ACKED) != 0) {
1231
1232 DPRINTF(rcs, DPRO, (CE_CONT,
1233 "msg already ACKed flag=%02x\n", drr->flags));
1234 return (RCNOERR);
1235
1236 } else if ((drr->flags & MSG_SENT) == 0) {
1237
1238 first_time = 1;
1239 }
1240
1241 /*
1242 * everything is ok. Now check that the data protocol is up
1243 * and running: messages cannot be sent if the link is down.
1244 */
1245 if (!dps->data_link_ok) {
1246 DPRINTF(rcs, DPRO, (CE_CONT,
1247 "msend: can't send msg - no data link\n"));
1248
1249 /*
1250 * do not return error, since it can be retried
1251 * later (hoping that the data link will come
1252 * up, in the meantime)
1253 */
1254 return (RCNOERR);
1255
1256 }
1257 } else {
1258 first_time = 1;
1259 }
1260
1261 /*
1262 * if the message has never been sent (and, hence, it is the first
1263 * time), then prepare the protocol packet: allocate a buffer,
1264 * create the message header, copy the message body into the buffer and
1265 * calculate CRCs
1266 */
1267 if (first_time) {
1268
1269 if (IS_NUMBERED_MSG(req->msg_type)) {
1270
1271 drr->retries_left = TX_RETRIES;
1272
1273 /*
1274 * Check length of the message.
1275 */
1276 if (req->msg_msglen > DP_MAX_MSGLEN) {
1277 DPRINTF(rcs, DPRO,
1278 (CE_CONT, "msend err: msg too big\n"));
1279 return (RCEINVARG);
1280 }
1281
1282 pkt = &drr->request;
1283
1284 /*
1285 * check that the message buffer is not already
1286 * in use (race condition). If so, return error
1287 */
1288 if (pkt->msg_buf != NULL) {
1289 DPRINTF(rcs, DPRO, (CE_CONT,
1290 "msend err: buf already in use\n"));
1291 return (RCENOMEM);
1292 }
1293
1294 /*
1295 * allocate a buffer for the protocol packet
1296 */
1297 if ((pkt->msg_buf = dp_get_buffer(rcs,
1298 DP_TX_BUFFER)) == NULL) {
1299 DPRINTF(rcs, DPRO, (CE_CONT,
1300 "msend err: no mem\n"));
1301 return (RCENOMEM);
1302 }
1303 pkt->msg_bufsiz = DP_BUFFER_SIZE;
1304
1305 /*
1306 * increment tx sequence number if sending a NUMBERED
1307 * message
1308 */
1309 dps->last_tx_seqid = NEXT_SEQID(dps->last_tx_seqid);
1310 } else {
1311 /*
1312 * UNUMBERED messages (or control messages) do not
1313 * carry any data and, hence, have a 'small' fixed size
1314 * (the size of the header). In this case,
1315 * a 'local' buffer (ctlbuf) is used.
1316 */
1317 pkt = &ctl;
1318 pkt->msg_buf = (uint8_t *)&ctlbuf;
1319 pkt->msg_bufsiz = sizeof (dp_header_t);
1320 }
1321
1322 #ifdef DEBUG_ERROR_INJECTION
1323
1324 if (((erri_test_number == ERRI_RX_SEQ_NUMBER &&
1325 IS_NUMBERED_MSG(req->msg_type)) ||
1326 (erri_test_number == ERRI_CTL_RX_SEQ_NUMBER &&
1327 IS_UNNUMBERED_MSG(req->msg_type))) &&
1328 erri_test_repeat >= 0 &&
1329 erri_test_count++ > 0 &&
1330 !(erri_test_count % erri_test_intrvl)) {
1331
1332 dps->last_rx_seqid--;
1333
1334 if (erri_test_repeat == 0)
1335 erri_test_repeat--; /* will not repeat it */
1336 }
1337 #endif
1338
1339 /*
1340 * create the protocol packet
1341 */
1342 pkt->msg_type = req->msg_type;
1343
1344 /*
1345 * length of the packet (including pad bytes)
1346 */
1347 pkt->msg_msglen = req->msg_msglen + sizeof (dp_header_t);
1348
1349 /*
1350 * message header:
1351 * set the message type
1352 * set the length of the message (excluding pad bytes)
1353 * set tx/rx sequence numbers
1354 * calculate CRC
1355 */
1356 dp_msgp = (dp_header_t *)pkt->msg_buf;
1357 dp_msgp->type = pkt->msg_type;
1358
1359 if (req->msg_msglen == 0)
1360 dp_msgp->length = pkt->msg_msglen -
1361 sizeof (dp_msgp->pad);
1362 else
1363 dp_msgp->length = sizeof (data_crc) +
1364 pkt->msg_msglen - sizeof (dp_msgp->pad);
1365
1366 dp_msgp->txnum = dps->last_tx_seqid;
1367 dp_msgp->rxnum = dps->last_rx_seqid;
1368
1369 dp_msgp->crc = dp_calc_crc16(pkt->msg_buf +
1370 sizeof (dp_msgp->pad), sizeof (dp_header_t) -
1371 sizeof (dp_msgp->crc) - sizeof (dp_msgp->pad));
1372
1373 #ifdef DEBUG_ERROR_INJECTION
1374
1375 if (((erri_test_number == ERRI_CRC_HEADER &&
1376 IS_NUMBERED_MSG(pkt->msg_type)) ||
1377 (erri_test_number == ERRI_CTL_CRC_HEADER &&
1378 IS_UNNUMBERED_MSG(pkt->msg_type))) &&
1379 erri_test_repeat >= 0 &&
1380 erri_test_count++ > 0 &&
1381 !(erri_test_count % erri_test_intrvl)) {
1382
1383 dp_msgp->crc = dp_msgp->crc/2;
1384 if (erri_test_repeat == 0)
1385 erri_test_repeat--; /* will not repeat it */
1386 }
1387 #endif
1388
1389 /*
1390 * copy message body (if present) into the buffer
1391 * and calculate message CRC
1392 */
1393 if (req->msg_msglen > 0) {
1394 bcopy(req->msg_buf, pkt->msg_buf + sizeof (dp_header_t),
1395 req->msg_msglen);
1396 data_crc = dp_calc_crc16(pkt->msg_buf +
1397 sizeof (dp_header_t),
1398 req->msg_msglen);
1399
1400 #ifdef DEBUG_ERROR_INJECTION
1401
1402 if (erri_test_number == ERRI_CRC_MSG &&
1403 erri_test_repeat >= 0 &&
1404 erri_test_count++ > 0 &&
1405 !(erri_test_count % erri_test_intrvl)) {
1406
1407 data_crc = data_crc/2;
1408 if (erri_test_repeat == 0)
1409 erri_test_repeat--;
1410 }
1411 #endif
1412 bcopy((void *) &data_crc,
1413 pkt->msg_buf + (sizeof (dp_header_t) +
1414 req->msg_msglen),
1415 sizeof (data_crc));
1416 }
1417 } else {
1418 /*
1419 * message has already been sent (and packetized).
1420 * get the message packet from the request/response
1421 * data structure
1422 */
1423 pkt = &drr->request;
1424 dp_msgp = (dp_header_t *)pkt->msg_buf;
1425 dps->retries_cnt++;
1426 }
1427
1428 /*
1429 * NUMBERED messages
1430 */
1431 if (IS_NUMBERED_MSG(pkt->msg_type)) {
1432
1433 /*
1434 * check that we have not exceeded the maximum number of
1435 * retries
1436 */
1437 if (drr->retries_left-- <= 0) {
1438
1439 drr->flags |= MSG_ERROR; /* set error flag */
1440
1441 /*
1442 * restart the data protocol link
1443 */
1444 dp_reset(rcs, INITIAL_SEQID, 0, 1);
1445
1446 return (RCEMAXRETRIES);
1447 }
1448
1449 if (dps->timer_delay_ack != (timeout_id_t)0) {
1450 /*
1451 * Cancel any pending acknowledgements - we're
1452 * going to send a message which will include
1453 * an acknowledgement.
1454 */
1455 timer_delay_ack = dps->timer_delay_ack;
1456
1457 /*
1458 * the timer is actually removed at the end of this
1459 * function since I need to release the dp_mutex.
1460 * Instead I clear the timer variable so that the
1461 * timeout callback will not do any processing in the
1462 * meantime.
1463 */
1464 dps->timer_delay_ack = 0;
1465 }
1466
1467 drr->flags |= MSG_SENT;
1468 }
1469
1470 /*
1471 * set rx sequence number (as we might have received a message in the
1472 * meantime). tx sequence number to be the same (we can only send one
1473 * message per time)
1474 */
1475 if (dp_msgp->rxnum != dps->last_rx_seqid) {
1476
1477 dp_msgp->rxnum = dps->last_rx_seqid;
1478
1479 /*
1480 * re-calculate CRC (header)
1481 */
1482 dp_msgp->crc = dp_calc_crc16(pkt->msg_buf +
1483 sizeof (dp_msgp->pad), sizeof (dp_header_t) -
1484 sizeof (dp_msgp->crc) - sizeof (dp_msgp->pad));
1485 }
1486
1487 DPRINTF(rcs, DPRO, (CE_CONT, "[t%03dr%03d] msend msgtype=%02x\n",
1488 dp_msgp->txnum, dp_msgp->rxnum, dp_msgp->type));
1489
1490 /*
1491 * send this message
1492 */
1493
1494 dp_send_packet(rcs, pkt->msg_buf);
1495
1496 /*
1497 * remove delay ack timer (if any is running)
1498 * Note that the dp_mutex must be released before calling
1499 * untimeout. Otherwise we may have a deadlock situation.
1500 */
1501 if (timer_delay_ack != 0) {
1502 DPRINTF(rcs, DGEN, (CE_CONT, "msend remove ack timer %p\n",
1503 timer_delay_ack));
1504 mutex_exit(dps->dp_mutex);
1505 (void) untimeout(timer_delay_ack);
1506 mutex_enter(dps->dp_mutex);
1507 }
1508
1509 return (RCNOERR);
1510 }
1511
1512 /*
1513 * to send a boot protocol message
1514 * (this is to support the firmware download feature)
1515 */
1516 void
rmc_comm_bp_msend(struct rmc_comm_state * rcs,bp_msg_t * bp_msg)1517 rmc_comm_bp_msend(struct rmc_comm_state *rcs, bp_msg_t *bp_msg)
1518 {
1519 char syncbuf[2];
1520
1521 ASSERT(MUTEX_HELD(rcs->dp_state.dp_mutex));
1522
1523 DPRINTF(rcs, DPRO, (CE_CONT, "send bp msg: %02x %02x %02x\n",
1524 bp_msg->cmd, bp_msg->dat1, bp_msg->dat2));
1525
1526 rcs->dp_state.req_resp.flags |= MSG_SENT_BP;
1527
1528 /* First, send out two SYNC characters. */
1529 syncbuf[0] = syncbuf[1] = (char)SYNC_CHAR;
1530 rmc_comm_serdev_send(rcs, syncbuf, 2);
1531
1532 /* Next, send the BP message. */
1533 rmc_comm_serdev_send(rcs, (char *)&bp_msg->cmd,
1534 sizeof (bp_msg_t) - sizeof (bp_msg->pad));
1535 }
1536
1537 /*
1538 * to send a fw s-record
1539 * (this is to support the firmware download feature)
1540 */
1541 void
rmc_comm_bp_srecsend(struct rmc_comm_state * rcs,char * buf,int buflen)1542 rmc_comm_bp_srecsend(struct rmc_comm_state *rcs, char *buf, int buflen)
1543 {
1544 ASSERT(MUTEX_HELD(rcs->dp_state.dp_mutex));
1545
1546 rcs->dp_state.req_resp.flags |= MSG_SENT_BP;
1547
1548 rmc_comm_serdev_send(rcs, buf, buflen);
1549 }
1550
1551 /*
1552 * clean up a request/response session
1553 * (it must have the dp_mutex)
1554 */
1555
1556 void
rmc_comm_dp_mcleanup(struct rmc_comm_state * rcs)1557 rmc_comm_dp_mcleanup(struct rmc_comm_state *rcs)
1558 {
1559 rmc_comm_dp_state_t *dps = &rcs->dp_state;
1560 dp_req_resp_t *drr = &dps->req_resp;
1561 dp_message_t *req = &drr->request;
1562 dp_message_t *resp = &drr->response;
1563
1564 ASSERT(MUTEX_HELD(dps->dp_mutex));
1565
1566 DPRINTF(rcs, DGEN, (CE_CONT, "msg cleanup\n"));
1567
1568 /*
1569 * 'release' memory
1570 * memory is only 'dynamically allocated for NUMBERED messages
1571 */
1572 if (req->msg_buf != NULL)
1573 dp_release_buffer(rcs, DP_TX_BUFFER);
1574
1575 drr->flags = 0;
1576 drr->error_status = 0;
1577
1578 req->msg_type = DP_NULL_MSG;
1579 req->msg_buf = NULL;
1580 req->msg_msglen = 0;
1581 req->msg_bufsiz = 0;
1582 resp->msg_type = DP_NULL_MSG;
1583 resp->msg_buf = NULL;
1584 resp->msg_msglen = 0;
1585 resp->msg_bufsiz = 0;
1586 }
1587