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
61int	erri_test_number = 0;
62int	erri_test_intrvl = 0;
63int	erri_test_repeat = 0;
64int	erri_test_count = 0;
65
66int erri_test_simulate_srec_sec(struct rmc_comm_state *, char *, int);
67
68#endif
69
70
71/* static functions */
72
73static void dp_link_setup_tohandler(void *);
74static void dp_delay_ack_tohandler(void *);
75static uint8_t *dp_get_buffer(struct rmc_comm_state *, uint8_t);
76static void dp_release_buffer(struct rmc_comm_state *, uint8_t);
77static void dp_init_buffers(struct rmc_comm_state *);
78static void dp_got_full_hdr(struct rmc_comm_state *, dp_packet_t *);
79static void dp_got_bp_msg(struct rmc_comm_state *, dp_packet_t *);
80static void dp_got_full_msg(struct rmc_comm_state *, dp_packet_t *);
81static void dp_tx_handle_ack(struct rmc_comm_state *, uint16_t);
82static void dp_tx_handle_nak(struct rmc_comm_state *, uint16_t);
83static void dp_send_packet(struct rmc_comm_state *, uchar_t *);
84static void dp_enable_data_link(struct rmc_comm_state *);
85static int dp_get_msglen(struct rmc_comm_state *, uint8_t *);
86static uint16_t dp_calc_crc16(uint8_t *, int);
87void dp_wake_up_waiter(struct rmc_comm_state *, uint8_t);
88void 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 */
97static void
98dp_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 */
110static uint8_t *
111dp_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 */
137static void
138dp_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 */
159static void
160dp_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 */
188static void
189dp_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 */
233static void
234dp_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 */
256static uint16_t
257dp_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 */
273void
274dp_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 */
328static void
329dp_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 */
362static void
363dp_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 */
391static void
392dp_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 */
441static void
442dp_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 */
487static void
488dp_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 */
525static int
526dp_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 */
549static void
550dp_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 */
599void
600dp_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 */
618void
619rmc_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 */
684void
685rmc_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 */
725void
726rmc_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 */
925void
926rmc_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 */
1166int
1167rmc_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 */
1199int
1200rmc_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 */
1516void
1517rmc_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 */
1541void
1542rmc_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
1556void
1557rmc_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