xref: /illumos-gate/usr/src/uts/sun4u/io/rmc_comm_dp.c (revision 7ae111d47a973fff4c6e231cc31f271dd9cef473)
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 2005 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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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] = SYNC_CHAR;
558 	rmc_comm_serdev_send(rcs, (char *)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] = ESC_CHAR;
587 			syncbuf[1] = *buf;
588 			rmc_comm_serdev_send(rcs, (char *)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
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
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
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
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
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
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
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 (RCEGENERIC);
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
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] = SYNC_CHAR;
1530 	rmc_comm_serdev_send(rcs, (char *)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
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
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