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  * Copyright 2000 by Cisco Systems, Inc.  All rights reserved.
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * iSCSI Pseudo HBA Driver
27  */
28 
29 #include <sys/socket.h>		/* networking stuff */
30 #include <sys/t_kuser.h>	/* networking stuff */
31 #include <sys/tihdr.h>		/* networking stuff */
32 #include <sys/strsubr.h>	/* networking stuff */
33 #include <netinet/tcp.h>	/* TCP_NODELAY */
34 #include <sys/socketvar.h>	/* _ALLOC_SLEEP */
35 #include <sys/strsun.h>		/* DB_TYPE() */
36 
37 #include "iscsi.h"		/* iscsi driver */
38 #include <sys/iscsi_protocol.h>	/* iscsi protocol */
39 
40 /* generic io helpers */
41 static uint32_t n2h24(uchar_t *ptr);
42 static int iscsi_sna_lt(uint32_t n1, uint32_t n2);
43 static void iscsi_update_flow_control(iscsi_sess_t *isp,
44     uint32_t max, uint32_t exp);
45 
46 /* receivers */
47 static iscsi_status_t iscsi_rx_process_hdr(iscsi_conn_t *icp,
48     iscsi_hdr_t *ihp, char *data, int data_size);
49 static iscsi_status_t iscsi_rx_process_nop(iscsi_conn_t *icp,
50     iscsi_hdr_t *ihp, char *data);
51 static iscsi_status_t iscsi_rx_process_data_rsp(iscsi_conn_t *icp,
52     iscsi_hdr_t *ihp);
53 static iscsi_status_t iscsi_rx_process_cmd_rsp(iscsi_conn_t *icp,
54     iscsi_hdr_t *ihp, char *data);
55 static iscsi_status_t iscsi_rx_process_rtt_rsp(iscsi_conn_t *icp,
56     iscsi_hdr_t *ihp, char *data);
57 static iscsi_status_t iscsi_rx_process_reject_rsp(iscsi_conn_t *icp,
58     iscsi_hdr_t *ihp, char *data);
59 static iscsi_status_t iscsi_rx_process_rejected_tsk_mgt(iscsi_conn_t *icp,
60     iscsi_hdr_t *old_ihp);
61 static iscsi_status_t iscsi_rx_process_itt_to_icmdp(iscsi_sess_t *isp,
62     iscsi_hdr_t *ihp, iscsi_cmd_t **icmdp);
63 static iscsi_status_t iscsi_rx_process_task_mgt_rsp(iscsi_conn_t *icp,
64     iscsi_hdr_t *ihp, void *data);
65 static iscsi_status_t iscsi_rx_process_logout_rsp(iscsi_conn_t *icp,
66     iscsi_hdr_t *ihp, char *data);
67 static iscsi_status_t iscsi_rx_process_async_rsp(iscsi_conn_t *icp,
68     iscsi_hdr_t *ihp, char *data);
69 static iscsi_status_t iscsi_rx_process_text_rsp(iscsi_conn_t *icp,
70     iscsi_hdr_t *ihp, char *data);
71 
72 
73 /* senders */
74 static iscsi_status_t iscsi_tx_scsi(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
75 static iscsi_status_t iscsi_tx_r2t(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
76 static iscsi_status_t iscsi_tx_data(iscsi_sess_t *isp, iscsi_conn_t *icp,
77     iscsi_cmd_t *icmdp, uint32_t ttt, size_t datalen, size_t offset);
78 static iscsi_status_t iscsi_tx_nop(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
79 static iscsi_status_t iscsi_tx_abort(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
80 static iscsi_status_t iscsi_tx_reset(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
81 static iscsi_status_t iscsi_tx_logout(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
82 static iscsi_status_t iscsi_tx_text(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
83 
84 
85 /* helpers */
86 static void iscsi_handle_r2t(iscsi_conn_t *icp, iscsi_cmd_t *icmdp,
87     uint32_t offset, uint32_t length, uint32_t ttt);
88 static void iscsi_handle_passthru_callback(struct scsi_pkt *pkt);
89 static void iscsi_handle_nop(iscsi_conn_t *icp, uint32_t itt, uint32_t ttt);
90 
91 static void iscsi_timeout_checks(iscsi_sess_t *isp);
92 static void iscsi_nop_checks(iscsi_sess_t *isp);
93 
94 
95 #define	ISCSI_CONN_TO_NET_DIGEST(icp)					    \
96 	((icp->conn_params.header_digest ? ISCSI_NET_HEADER_DIGEST : 0) |   \
97 	(icp->conn_params.data_digest ? ISCSI_NET_DATA_DIGEST : 0))
98 
99 /*
100  * This file contains the main guts of the iSCSI protocol layer.
101  * It's broken into 5 sections; Basic helper functions, RX IO path,
102  * TX IO path, Completion (IC) IO path, and watchdog (WD) routines.
103  *
104  * The IO flow model is similiar to the below diagram.  The
105  * iscsi session, connection and command state machines are used
106  * to drive IO through this flow diagram.  Reference those files
107  * to get a detailed description of their respective state models
108  * prior to their xxx_state_machine_function().
109  *
110  * tran_start() -> CMD_E1     TX_THREAD                   RX_THREAD
111  *                   |            T                           T
112  *                   V            T                           T
113  *                PENDING_Q  --CMD_E2--> ACTIVE_Q -      --CMD_E3--+
114  *                                T                \ C        T    |
115  *                                T                 \M        T    |
116  *                                                   D        T    |
117  *                                       WD_THREAD TT|TT      T    |
118  *                                                  /E        T    |
119  *                                                 / 6        T    |
120  *                                     ABORTING_Q<-      --CMD_E3--+
121  *                                                            T    |
122  *                                T                           T    |
123  *                                T                                |
124  *               callback()  <--CMD_E#-- COMPLETION_Q <------------+
125  *                                T
126  *                                T
127  *                            IC_THREAD
128  *
129  * External and internal command are ran thru this same state
130  * machine.  All commands enter the state machine by receiving an
131  * ISCSI_CMD_EVENT_E1.  This event places the command into the
132  * PENDING_Q.  Next when resources are available the TX_THREAD
133  * issues a E2 event on the command.  This sends the command
134  * to the TCP stack and places the command on the ACTIVE_Q.  While
135  * on the PENDIING_Q and ACTIVE_Q, the command is monitored via the
136  * WD_THREAD to ensure the pkt_time has not elapsed.  If elapsed the
137  * command is issued an E6(timeout) event which moves either (if pending)
138  * completed the command or (if active) moves the command to the
139  * aborting queue and issues a SCSI TASK MANAGEMENT ABORT command
140  * to cancel the IO request.  If the original command is completed
141  * or the TASK MANAGEMENT command completes the command is moved
142  * to the COMPLETION_Q via a E3 event.  The IC_THREAD then processes
143  * the COMPLETION_Q and issues the scsi_pkt callback.  This
144  * callback can not be processed directly from the RX_THREAD
145  * because the callback might call back into the iscsi driver
146  * causing a deadlock condition.
147  *
148  * For more details on the complete CMD state machine reference
149  * the state machine diagram in iscsi_cmd.c.  The connection state
150  * machine is driven via IO events in this file.  Then session
151  * events are driven by the connection events.  For complete
152  * details on these state machines reference iscsi_sess.c and
153  * iscsi_conn.c
154  */
155 
156 
157 /*
158  * +--------------------------------------------------------------------+
159  * | io helper routines							|
160  * +--------------------------------------------------------------------+
161  */
162 
163 /*
164  * n2h24 - native to host 24 bit integer translation.
165  */
166 static uint32_t
167 n2h24(uchar_t *ptr)
168 {
169 	uint32_t idx;
170 	bcopy(ptr, &idx, 3);
171 	return (ntohl(idx) >> 8);
172 }
173 
174 /*
175  * iscsi_sna_lt - Serial Number Arithmetic, 32 bits, less than, RFC1982
176  */
177 static int
178 iscsi_sna_lt(uint32_t n1, uint32_t n2)
179 {
180 	return ((n1 != n2) &&
181 	    (((n1 < n2) && ((n2 - n1) < ISCSI_SNA32_CHECK)) ||
182 	    ((n1 > n2) && ((n1 - n2) > ISCSI_SNA32_CHECK))));
183 }
184 
185 /*
186  * iscsi_sna_lte - Serial Number Arithmetic, 32 bits, less than or equal,
187  * RFC1982
188  */
189 int
190 iscsi_sna_lte(uint32_t n1, uint32_t n2)
191 {
192 	return ((n1 == n2) ||
193 	    (((n1 < n2) && ((n2 - n1) < ISCSI_SNA32_CHECK)) ||
194 	    ((n1 > n2) && ((n1 - n2) > ISCSI_SNA32_CHECK))));
195 }
196 
197 /*
198  * iscsi_update_flow_control - Update expcmdsn and maxcmdsn iSCSI
199  * flow control information for a session
200  */
201 static void
202 iscsi_update_flow_control(iscsi_sess_t *isp, uint32_t max, uint32_t exp)
203 {
204 	ASSERT(isp != NULL);
205 	ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
206 
207 	if (!iscsi_sna_lt(max, (exp - 1))) {
208 
209 		if (!iscsi_sna_lte(exp, isp->sess_expcmdsn)) {
210 			isp->sess_expcmdsn = exp;
211 		}
212 
213 		if (!iscsi_sna_lte(max, isp->sess_maxcmdsn)) {
214 			isp->sess_maxcmdsn = max;
215 			if (iscsi_sna_lte(isp->sess_cmdsn,
216 			    isp->sess_maxcmdsn)) {
217 				/*
218 				 * the window is open again - schedule
219 				 * to send any held tasks soon
220 				 */
221 				iscsi_sess_redrive_io(isp);
222 			}
223 		}
224 	}
225 }
226 
227 
228 /*
229  * +--------------------------------------------------------------------+
230  * | io receive and processing routines					|
231  * +--------------------------------------------------------------------+
232  */
233 
234 /*
235  * iscsi_rx_thread - The connection creates a thread of this
236  * function during login.  After which point this thread is
237  * used to receive and process all iSCSI PDUs on this connection.
238  * The PDUs received on this connection are used to drive the
239  * commands through their state machine.  This thread will
240  * continue processing while the connection is on a LOGGED_IN
241  * or IN_LOGOUT state.  Once the connection moves out of this
242  * state the thread will die.
243  */
244 void
245 iscsi_rx_thread(iscsi_thread_t *thread, void *arg)
246 {
247 	iscsi_status_t		rval		= ISCSI_STATUS_SUCCESS;
248 	iscsi_conn_t		*icp		= (iscsi_conn_t *)arg;
249 	iscsi_sess_t		*isp		= NULL;
250 	char			*hdr		= NULL;
251 	int			hdr_size	= 0;
252 	char			*data		= NULL;
253 	int			data_size	= 0;
254 	iscsi_hdr_t		*ihp;
255 
256 	ASSERT(icp != NULL);
257 	isp = icp->conn_sess;
258 	ASSERT(isp != NULL);
259 
260 	/* pre-alloc recv header buffer for common actions */
261 	hdr_size = sizeof (iscsi_hdr_t) + 255; /* 255 = one byte hlength */
262 	hdr = (char *)kmem_zalloc(hdr_size, KM_SLEEP);
263 	ihp = (iscsi_hdr_t *)hdr;
264 	ASSERT(ihp != NULL);
265 
266 	/* pre-alloc max_recv_size buffer for common actions */
267 	data_size = icp->conn_params.max_recv_data_seg_len;
268 	data = (char *)kmem_zalloc(data_size, KM_SLEEP);
269 	ASSERT(data != NULL);
270 
271 	do {
272 		/* Wait for the next iSCSI header */
273 		rval = iscsi_net->recvhdr(icp->conn_socket,
274 		    ihp, hdr_size, 0, (icp->conn_params.header_digest ?
275 		    ISCSI_NET_HEADER_DIGEST : 0));
276 		if (ISCSI_SUCCESS(rval)) {
277 			isp->sess_rx_lbolt =
278 			    icp->conn_rx_lbolt =
279 			    ddi_get_lbolt();
280 
281 			/* Perform specific hdr handling */
282 			rval = iscsi_rx_process_hdr(icp, ihp,
283 			    data, data_size);
284 		}
285 
286 		/*
287 		 * handle failures
288 		 */
289 		switch (rval) {
290 		case ISCSI_STATUS_SUCCESS:
291 			/*
292 			 * If we successfully completed a receive
293 			 * and we are in an IN_FLUSH state then
294 			 * check the active queue count to see
295 			 * if its empty.  If its empty then force
296 			 * a disconnect event on the connection.
297 			 * This will move the session from IN_FLUSH
298 			 * to FLUSHED and complete the login
299 			 * parameter update.
300 			 */
301 			if ((isp->sess_state == ISCSI_SESS_STATE_IN_FLUSH) &&
302 			    (icp->conn_queue_active.count == 0)) {
303 				mutex_enter(&icp->conn_state_mutex);
304 				(void) iscsi_conn_state_machine(icp,
305 				    ISCSI_CONN_EVENT_T14);
306 				mutex_exit(&icp->conn_state_mutex);
307 			}
308 			break;
309 		case ISCSI_STATUS_TCP_RX_ERROR:
310 			/* connection had an error */
311 			mutex_enter(&icp->conn_state_mutex);
312 			/*
313 			 * recvmsg may return after the closing of socket
314 			 * with this error
315 			 */
316 			if (ISCSI_CONN_STATE_FULL_FEATURE(icp->conn_state)) {
317 				(void) iscsi_conn_state_machine(icp,
318 				    ISCSI_CONN_EVENT_T15);
319 			}
320 			mutex_exit(&icp->conn_state_mutex);
321 			break;
322 		case ISCSI_STATUS_HEADER_DIGEST_ERROR:
323 			/*
324 			 * If we encounter a digest error we have to restart
325 			 * all the connections on this session. per iSCSI
326 			 * Level 0 Recovery.
327 			 */
328 			KSTAT_INC_CONN_ERR_HEADER_DIGEST(icp);
329 			mutex_enter(&icp->conn_state_mutex);
330 			(void) iscsi_conn_state_machine(icp,
331 			    ISCSI_CONN_EVENT_T14);
332 			mutex_exit(&icp->conn_state_mutex);
333 			break;
334 		case ISCSI_STATUS_DATA_DIGEST_ERROR:
335 			/*
336 			 * We can continue with a data digest error.  The
337 			 * icmdp was flaged as having a crc problem.  It
338 			 * will be aborted when all data is received.  This
339 			 * saves us from restarting the session when we
340 			 * might be able to keep it going.  If the data
341 			 * digest issue was really bad we will hit a
342 			 * status protocol error on the next pdu, which
343 			 * will force a connection retstart.
344 			 */
345 			KSTAT_INC_CONN_ERR_DATA_DIGEST(icp);
346 			break;
347 		case ISCSI_STATUS_PROTOCOL_ERROR:
348 			/*
349 			 * A protocol problem was encountered.  Reset
350 			 * session to try and repair issue.
351 			 */
352 			KSTAT_INC_CONN_ERR_PROTOCOL(icp);
353 			mutex_enter(&icp->conn_state_mutex);
354 			(void) iscsi_conn_state_machine(icp,
355 			    ISCSI_CONN_EVENT_T14);
356 			mutex_exit(&icp->conn_state_mutex);
357 			break;
358 		case ISCSI_STATUS_INTERNAL_ERROR:
359 			/*
360 			 * These should have all been handled before now.
361 			 */
362 			break;
363 		default:
364 			cmn_err(CE_WARN, "iscsi connection(%u) encountered "
365 			    "unknown error(%d) on a receive", icp->conn_oid,
366 			    rval);
367 			ASSERT(B_FALSE);
368 		}
369 
370 	} while ((ISCSI_CONN_STATE_FULL_FEATURE(icp->conn_state)) &&
371 	    (iscsi_thread_wait(thread, 0) != 0));
372 
373 	kmem_free(hdr, hdr_size);
374 	kmem_free(data, data_size);
375 }
376 
377 
378 /*
379  * iscsi_rx_process_hdr - This function collects data for all PDUs
380  * that do not have data that will be mapped to a specific scsi_pkt.
381  * Then for each hdr type fan out the processing.
382  */
383 static iscsi_status_t
384 iscsi_rx_process_hdr(iscsi_conn_t *icp, iscsi_hdr_t *ihp,
385     char *data, int data_size)
386 {
387 	iscsi_status_t	rval	= ISCSI_STATUS_SUCCESS;
388 	iscsi_sess_t	*isp	= NULL;
389 
390 	ASSERT(icp != NULL);
391 	ASSERT(ihp != NULL);
392 	ASSERT(data != NULL);
393 	isp = icp->conn_sess;
394 	ASSERT(isp != NULL);
395 
396 	/* If this is not a SCSI_DATA_RSP we can go ahead and get the data */
397 	if ((ihp->opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_SCSI_DATA_RSP) {
398 		rval = iscsi_net->recvdata(icp->conn_socket, ihp,
399 		    data, data_size, 0, (icp->conn_params.data_digest) ?
400 		    ISCSI_NET_DATA_DIGEST : 0);
401 		if (!ISCSI_SUCCESS(rval)) {
402 			return (rval);
403 		}
404 		isp->sess_rx_lbolt = icp->conn_rx_lbolt = ddi_get_lbolt();
405 	}
406 
407 	/* fan out the hdr processing */
408 	switch (ihp->opcode & ISCSI_OPCODE_MASK) {
409 	case ISCSI_OP_SCSI_DATA_RSP:
410 		rval = iscsi_rx_process_data_rsp(icp, ihp);
411 		break;
412 	case ISCSI_OP_SCSI_RSP:
413 		rval = iscsi_rx_process_cmd_rsp(icp, ihp, data);
414 		break;
415 	case ISCSI_OP_RTT_RSP:
416 		rval = iscsi_rx_process_rtt_rsp(icp, ihp, data);
417 		break;
418 	case ISCSI_OP_NOOP_IN:
419 		rval = iscsi_rx_process_nop(icp, ihp, data);
420 		break;
421 	case ISCSI_OP_REJECT_MSG:
422 		rval = iscsi_rx_process_reject_rsp(icp, ihp, data);
423 		break;
424 	case ISCSI_OP_SCSI_TASK_MGT_RSP:
425 		rval = iscsi_rx_process_task_mgt_rsp(icp, ihp, data);
426 		break;
427 	case ISCSI_OP_LOGOUT_RSP:
428 		rval = iscsi_rx_process_logout_rsp(icp, ihp, data);
429 		break;
430 	case ISCSI_OP_ASYNC_EVENT:
431 		rval = iscsi_rx_process_async_rsp(icp, ihp, data);
432 		break;
433 	case ISCSI_OP_TEXT_RSP:
434 		rval = iscsi_rx_process_text_rsp(icp, ihp, data);
435 		break;
436 	default:
437 		cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
438 		    "received an unsupported opcode 0x%02x",
439 		    icp->conn_oid, ihp->opcode);
440 		rval = ISCSI_STATUS_PROTOCOL_ERROR;
441 	}
442 
443 	return (rval);
444 }
445 
446 
447 /*
448  * iscsi_rx_process_data_rsp - Processed received data header.  Once
449  * header is processed we read data off the connection directly into
450  * the scsi_pkt to avoid duplicate bcopy of a large amount of data.
451  * If this is the final data sequence denoted by the data response
452  * PDU Status bit being set.  We will not receive the SCSI response.
453  * This bit denotes that the PDU is the successful completion of the
454  * command.  In this case complete the command.  If This bit isn't
455  * set we wait for more data or a scsi command response.
456  */
457 static iscsi_status_t
458 iscsi_rx_process_data_rsp(iscsi_conn_t *icp, iscsi_hdr_t *ihp)
459 {
460 	iscsi_status_t		rval		= ISCSI_STATUS_SUCCESS;
461 	iscsi_sess_t		*isp		= NULL;
462 	iscsi_data_rsp_hdr_t	*idrhp		= (iscsi_data_rsp_hdr_t *)ihp;
463 	iscsi_cmd_t		*icmdp		= NULL;
464 	struct scsi_pkt		*pkt		= NULL;
465 	struct buf		*bp		= NULL;
466 	uint32_t		offset		= 0;
467 	uint32_t		dlength		= 0;
468 	char			*bcp		= NULL;
469 
470 	ASSERT(icp != NULL);
471 	ASSERT(ihp != NULL);
472 	isp = icp->conn_sess;
473 	ASSERT(isp != NULL);
474 
475 	if (idrhp->flags & ISCSI_FLAG_DATA_STATUS) {
476 		/* make sure we got status in order */
477 		if (icp->conn_expstatsn == ntohl(idrhp->statsn)) {
478 			icp->conn_expstatsn++;
479 		} else {
480 			cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
481 			    "- received status out of order itt:0x%x "
482 			    "statsn:0x%x expstatsn:0x%x", icp->conn_oid,
483 			    idrhp->itt, ntohl(idrhp->statsn),
484 			    icp->conn_expstatsn);
485 			return (ISCSI_STATUS_PROTOCOL_ERROR);
486 		}
487 	}
488 
489 	/* match itt in the session's command table */
490 	mutex_enter(&icp->conn_queue_active.mutex);
491 	mutex_enter(&isp->sess_cmdsn_mutex);
492 	if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(isp, ihp, &icmdp))) {
493 		mutex_exit(&isp->sess_cmdsn_mutex);
494 		mutex_exit(&icp->conn_queue_active.mutex);
495 		return (ISCSI_STATUS_PROTOCOL_ERROR);
496 	}
497 	/*
498 	 * Holding the pending/active queue locks across the
499 	 * iscsi_rx_data call later in this function may cause
500 	 * deadlock during fault injections.  Instead remove
501 	 * the cmd from the active queue and release the locks.
502 	 * Then before returning or completing the command
503 	 * return the cmd to the active queue and reacquire
504 	 * the locks.
505 	 */
506 	iscsi_dequeue_active_cmd(icp, icmdp);
507 
508 	/* update expcmdsn and maxcmdsn */
509 	iscsi_update_flow_control(isp, ntohl(idrhp->maxcmdsn),
510 	    ntohl(idrhp->expcmdsn));
511 	mutex_exit(&isp->sess_cmdsn_mutex);
512 	mutex_exit(&icp->conn_queue_active.mutex);
513 
514 	/* shorthand some values */
515 	pkt = icmdp->cmd_un.scsi.pkt;
516 	bp = icmdp->cmd_un.scsi.bp;
517 	offset = ntohl(idrhp->offset);
518 	dlength = n2h24(idrhp->dlength);
519 
520 	/*
521 	 * some poorly behaved targets have been observed
522 	 * sending data-in pdu's during a write operation
523 	 */
524 	if (bp != NULL) {
525 		if (!(bp->b_flags & B_READ)) {
526 			cmn_err(CE_WARN,
527 			    "iscsi connection(%u) protocol error - "
528 			    "received data response during write operation "
529 			    "itt:0x%x",
530 			    icp->conn_oid, idrhp->itt);
531 			mutex_enter(&icp->conn_queue_active.mutex);
532 			iscsi_enqueue_active_cmd(icp, icmdp);
533 			mutex_exit(&icp->conn_queue_active.mutex);
534 			return (ISCSI_STATUS_PROTOCOL_ERROR);
535 		}
536 
537 		/*
538 		 * We can't tolerate the target sending too much
539 		 * data for our buffer
540 		 */
541 		if ((dlength >
542 		    (bp->b_bcount - icmdp->cmd_un.scsi.data_transferred)) ||
543 		    (dlength > (bp->b_bcount - offset))) {
544 			cmn_err(CE_WARN,
545 			    "iscsi connection(%u) protocol error - "
546 			    "received too much data itt:0x%x",
547 			    icp->conn_oid, idrhp->itt);
548 			mutex_enter(&icp->conn_queue_active.mutex);
549 			iscsi_enqueue_active_cmd(icp, icmdp);
550 			mutex_exit(&icp->conn_queue_active.mutex);
551 			return (ISCSI_STATUS_PROTOCOL_ERROR);
552 		}
553 
554 		bcp = ((char *)bp->b_un.b_addr) + offset;
555 
556 		/*
557 		 * Get the rest of the data and copy it directly into
558 		 * the scsi_pkt.
559 		 */
560 		rval = iscsi_net->recvdata(icp->conn_socket, ihp,
561 		    bcp, dlength, 0, (icp->conn_params.data_digest ?
562 		    ISCSI_NET_DATA_DIGEST : 0));
563 		if (ISCSI_SUCCESS(rval)) {
564 			KSTAT_ADD_CONN_RX_BYTES(icp, dlength);
565 		} else {
566 			/* If digest error flag icmdp with a crc error */
567 			if (rval == ISCSI_STATUS_DATA_DIGEST_ERROR) {
568 				icmdp->cmd_crc_error_seen = B_TRUE;
569 			}
570 			mutex_enter(&icp->conn_queue_active.mutex);
571 			iscsi_enqueue_active_cmd(icp, icmdp);
572 			mutex_exit(&icp->conn_queue_active.mutex);
573 			return (rval);
574 		}
575 		isp->sess_rx_lbolt = icp->conn_rx_lbolt = ddi_get_lbolt();
576 
577 		/* update icmdp statistics */
578 		icmdp->cmd_un.scsi.data_transferred += dlength;
579 	}
580 
581 	/*
582 	 * We got status. This should only happen if we have
583 	 * received all the data with no errors.  The command
584 	 * must be completed now, since we won't get a command
585 	 * response PDU. The cmd_status and residual_count are
586 	 * not meaningful unless status_present is set.
587 	 */
588 	if (idrhp->flags & ISCSI_FLAG_DATA_STATUS) {
589 		pkt->pkt_resid = 0;
590 		/* Check the residual count */
591 		if (bp &&
592 		    (icmdp->cmd_un.scsi.data_transferred !=
593 		    bp->b_bcount)) {
594 			/*
595 			 * We didn't xfer the expected amount of data -
596 			 * the residual_count in the header is only valid
597 			 * if the underflow flag is set.
598 			 */
599 			if (idrhp->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
600 				pkt->pkt_resid = ntohl(idrhp->residual_count);
601 			} else {
602 				if (bp->b_bcount >
603 				    icmdp->cmd_un.scsi.data_transferred) {
604 					/* Some data fell on the floor somehw */
605 					pkt->pkt_resid =
606 					    bp->b_bcount -
607 					    icmdp->cmd_un.scsi.data_transferred;
608 				}
609 			}
610 		}
611 
612 		pkt->pkt_reason = CMD_CMPLT;
613 		pkt->pkt_state |= (STATE_XFERRED_DATA | STATE_GOT_STATUS);
614 
615 		if (((idrhp->cmd_status & STATUS_MASK) != STATUS_GOOD) &&
616 		    (icmdp->cmd_un.scsi.statuslen >=
617 		    sizeof (struct scsi_arq_status)) && pkt->pkt_scbp) {
618 
619 			/*
620 			 * Not supposed to get exception status here!
621 			 * We have no request sense data so just do the
622 			 * best we can
623 			 */
624 			struct scsi_arq_status *arqstat =
625 			    (struct scsi_arq_status *)pkt->pkt_scbp;
626 
627 
628 			bzero(arqstat, sizeof (struct scsi_arq_status));
629 
630 			*((uchar_t *)&arqstat->sts_status) =
631 			    idrhp->cmd_status;
632 
633 			arqstat->sts_rqpkt_resid =
634 			    sizeof (struct scsi_extended_sense);
635 
636 		} else if (pkt->pkt_scbp) {
637 			/* just pass along the status we got */
638 			pkt->pkt_scbp[0] = idrhp->cmd_status;
639 		}
640 
641 		mutex_enter(&icp->conn_queue_active.mutex);
642 		iscsi_enqueue_active_cmd(icp, icmdp);
643 		iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
644 		mutex_exit(&icp->conn_queue_active.mutex);
645 	} else {
646 		mutex_enter(&icp->conn_queue_active.mutex);
647 		iscsi_enqueue_active_cmd(icp, icmdp);
648 		mutex_exit(&icp->conn_queue_active.mutex);
649 	}
650 
651 	return (ISCSI_STATUS_SUCCESS);
652 }
653 
654 
655 /*
656  * iscsi_rx_process_cmd_rsp - Process received scsi command response.  This
657  * will contain sense data if the command was not successful.  This data needs
658  * to be copied into the scsi_pkt.  Otherwise we just complete the IO.
659  */
660 static iscsi_status_t
661 iscsi_rx_process_cmd_rsp(iscsi_conn_t *icp, iscsi_hdr_t *ihp, char *data)
662 {
663 	iscsi_sess_t		*isp		= icp->conn_sess;
664 	iscsi_scsi_rsp_hdr_t	*issrhp		= (iscsi_scsi_rsp_hdr_t *)ihp;
665 	iscsi_cmd_t		*icmdp		= NULL;
666 	struct scsi_pkt		*pkt		= NULL;
667 	uint32_t		dlength		= 0;
668 	struct scsi_arq_status	*arqstat	= NULL;
669 	size_t			senselen	= 0;
670 	int			statuslen	= 0;
671 
672 	/* make sure we get status in order */
673 	if (icp->conn_expstatsn == ntohl(issrhp->statsn)) {
674 		icp->conn_expstatsn++;
675 	} else {
676 		cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
677 		    "received status out of order itt:0x%x statsn:0x%x "
678 		    "expstatsn:0x%x", icp->conn_oid, issrhp->itt,
679 		    ntohl(issrhp->statsn), icp->conn_expstatsn);
680 		return (ISCSI_STATUS_PROTOCOL_ERROR);
681 	}
682 
683 	mutex_enter(&icp->conn_queue_active.mutex);
684 	mutex_enter(&isp->sess_cmdsn_mutex);
685 	if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(isp, ihp, &icmdp))) {
686 		mutex_exit(&isp->sess_cmdsn_mutex);
687 		mutex_exit(&icp->conn_queue_active.mutex);
688 		return (ISCSI_STATUS_PROTOCOL_ERROR);
689 	}
690 
691 	/* update expcmdsn and maxcmdsn */
692 	iscsi_update_flow_control(isp, ntohl(issrhp->maxcmdsn),
693 	    ntohl(issrhp->expcmdsn));
694 	mutex_exit(&isp->sess_cmdsn_mutex);
695 
696 	pkt = icmdp->cmd_un.scsi.pkt;
697 
698 	if (issrhp->response) {
699 		/* The target failed the command. */
700 		pkt->pkt_reason = CMD_TRAN_ERR;
701 		if (icmdp->cmd_un.scsi.bp) {
702 			pkt->pkt_resid = icmdp->cmd_un.scsi.bp->b_bcount;
703 		} else {
704 			pkt->pkt_resid = 0;
705 		}
706 	} else {
707 		/* success */
708 		pkt->pkt_resid = 0;
709 		/* Check the residual count */
710 		if ((icmdp->cmd_un.scsi.bp) &&
711 		    (icmdp->cmd_un.scsi.data_transferred !=
712 		    icmdp->cmd_un.scsi.bp->b_bcount)) {
713 			/*
714 			 * We didn't xfer the expected amount of data -
715 			 * the residual_count in the header is only
716 			 * valid if the underflow flag is set.
717 			 */
718 			if (issrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
719 				pkt->pkt_resid = ntohl(issrhp->residual_count);
720 			} else {
721 				if (icmdp->cmd_un.scsi.bp->b_bcount >
722 				    icmdp->cmd_un.scsi.data_transferred) {
723 					/*
724 					 * Some data fell on the floor
725 					 * somehow - probably a CRC error
726 					 */
727 					pkt->pkt_resid =
728 					    icmdp->cmd_un.scsi.bp->b_bcount -
729 					    icmdp->cmd_un.scsi.data_transferred;
730 				}
731 			}
732 		}
733 
734 		/* set flags that tell SCSA that the command is complete */
735 		if (icmdp->cmd_crc_error_seen == B_FALSE) {
736 			/* Set successful completion */
737 			pkt->pkt_reason = CMD_CMPLT;
738 			if (icmdp->cmd_un.scsi.bp) {
739 				pkt->pkt_state |= (STATE_XFERRED_DATA |
740 				    STATE_GOT_STATUS);
741 			} else {
742 				pkt->pkt_state |= STATE_GOT_STATUS;
743 			}
744 		} else {
745 			/*
746 			 * Some of the data was found to have an incorrect
747 			 * error at the protocol error.
748 			 */
749 			pkt->pkt_reason = CMD_PER_FAIL;
750 			pkt->pkt_statistics |= STAT_PERR;
751 			if (icmdp->cmd_un.scsi.bp) {
752 				pkt->pkt_resid =
753 				    icmdp->cmd_un.scsi.bp->b_bcount;
754 			} else {
755 				pkt->pkt_resid = 0;
756 			}
757 		}
758 
759 		dlength = n2h24(issrhp->dlength);
760 
761 		/*
762 		 * Process iSCSI Cmd Response Status
763 		 * RFC 3720 Sectionn 10.4.2.
764 		 */
765 		switch (issrhp->cmd_status & STATUS_MASK) {
766 		case STATUS_GOOD:
767 			/* pass SCSI status up stack */
768 			if (pkt->pkt_scbp) {
769 				pkt->pkt_scbp[0] = issrhp->cmd_status;
770 			}
771 			break;
772 		case STATUS_CHECK:
773 			/*
774 			 * Verify we received a sense buffer and
775 			 * that there is the correct amount of
776 			 * request sense space to copy it to.
777 			 */
778 			if ((dlength > 1) &&
779 			    (pkt->pkt_scbp != NULL) &&
780 			    (icmdp->cmd_un.scsi.statuslen >=
781 			    sizeof (struct scsi_arq_status))) {
782 				/*
783 				 * If a bad command status is received we
784 				 * need to reset the pkt_resid to zero.
785 				 * The target driver compares its value
786 				 * before checking other error flags.
787 				 * (ex. check conditions)
788 				 */
789 				pkt->pkt_resid = 0;
790 
791 				/* get sense length from first 2 bytes */
792 				senselen = ((data[0] << 8) | data[1]) &
793 				    (size_t)0xFFFF;
794 
795 				/* Sanity-check on the sense length */
796 				if ((senselen + 2) > dlength) {
797 					senselen = dlength - 2;
798 				}
799 
800 				/*
801 				 * If there was a Data Digest error then
802 				 * the sense data cannot be trusted.
803 				 */
804 				if (icmdp->cmd_crc_error_seen) {
805 					senselen = 0;
806 				}
807 
808 				/* automatic request sense */
809 				arqstat =
810 				    (struct scsi_arq_status *)pkt->pkt_scbp;
811 
812 				/* pass SCSI status up stack */
813 				*((uchar_t *)&arqstat->sts_status) =
814 				    issrhp->cmd_status;
815 
816 				/*
817 				 * Set the status for the automatic
818 				 * request sense command
819 				 */
820 				arqstat->sts_rqpkt_state = (STATE_GOT_BUS |
821 				    STATE_GOT_TARGET | STATE_SENT_CMD |
822 				    STATE_XFERRED_DATA | STATE_GOT_STATUS |
823 				    STATE_ARQ_DONE);
824 
825 				*((uchar_t *)&arqstat->sts_rqpkt_status) =
826 				    STATUS_GOOD;
827 
828 				arqstat->sts_rqpkt_reason = CMD_CMPLT;
829 
830 				statuslen = icmdp->cmd_un.scsi.statuslen;
831 
832 				if (senselen == 0) {
833 					/* auto request sense failed */
834 					arqstat->sts_rqpkt_status.sts_chk = 1;
835 					arqstat->sts_rqpkt_resid =
836 					    statuslen;
837 				} else if (senselen <
838 				    statuslen) {
839 					/* auto request sense short */
840 					arqstat->sts_rqpkt_resid =
841 					    statuslen
842 					    - senselen;
843 				} else {
844 					/* auto request sense complete */
845 					arqstat->sts_rqpkt_resid = 0;
846 				}
847 				arqstat->sts_rqpkt_statistics = 0;
848 				pkt->pkt_state |= STATE_ARQ_DONE;
849 
850 				if (icmdp->cmd_misc_flags &
851 				    ISCSI_CMD_MISCFLAG_XARQ) {
852 					pkt->pkt_state |= STATE_XARQ_DONE;
853 				}
854 
855 				/* copy auto request sense */
856 				dlength = min(senselen,
857 				    statuslen);
858 				if (dlength) {
859 					bcopy(&data[2], (uchar_t *)&arqstat->
860 					    sts_sensedata, dlength);
861 				}
862 				break;
863 			}
864 			/* FALLTHRU */
865 		case STATUS_BUSY:
866 		case STATUS_RESERVATION_CONFLICT:
867 		case STATUS_QFULL:
868 		case STATUS_ACA_ACTIVE:
869 		default:
870 			/*
871 			 * If a bad command status is received we need to
872 			 * reset the pkt_resid to zero.  The target driver
873 			 * compares its value before checking other error
874 			 * flags. (ex. check conditions)
875 			 */
876 			pkt->pkt_resid = 0;
877 			/* pass SCSI status up stack */
878 			if (pkt->pkt_scbp) {
879 				pkt->pkt_scbp[0] = issrhp->cmd_status;
880 			}
881 		}
882 	}
883 
884 	iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
885 	mutex_exit(&icp->conn_queue_active.mutex);
886 
887 	return (ISCSI_STATUS_SUCCESS);
888 }
889 
890 /*
891  * iscsi_rx_process_rtt_rsp - Process received RTT.  This means the target is
892  * requesting data.
893  */
894 /* ARGSUSED */
895 static iscsi_status_t
896 iscsi_rx_process_rtt_rsp(iscsi_conn_t *icp, iscsi_hdr_t *ihp, char *data)
897 {
898 	iscsi_sess_t		*isp = (iscsi_sess_t *)icp->conn_sess;
899 	iscsi_rtt_hdr_t		*irhp		= (iscsi_rtt_hdr_t *)ihp;
900 	iscsi_cmd_t		*icmdp		= NULL;
901 	struct buf		*bp		= NULL;
902 	uint32_t		data_length;
903 	iscsi_status_t		status = ISCSI_STATUS_PROTOCOL_ERROR;
904 
905 
906 	mutex_enter(&isp->sess_queue_pending.mutex);
907 	mutex_enter(&icp->conn_queue_active.mutex);
908 	mutex_enter(&isp->sess_cmdsn_mutex);
909 	if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(isp, ihp, &icmdp))) {
910 		mutex_exit(&isp->sess_cmdsn_mutex);
911 		mutex_exit(&icp->conn_queue_active.mutex);
912 		mutex_exit(&isp->sess_queue_pending.mutex);
913 		return (status);
914 	}
915 
916 	/* update expcmdsn and maxcmdsn */
917 	iscsi_update_flow_control(isp, ntohl(irhp->maxcmdsn),
918 	    ntohl(irhp->expcmdsn));
919 	mutex_enter(&icmdp->cmd_mutex);
920 	mutex_exit(&isp->sess_cmdsn_mutex);
921 
922 	bp = icmdp->cmd_un.scsi.bp;
923 	data_length = ntohl(irhp->data_length);
924 
925 	/*
926 	 * Perform boundary-checks per RFC 3720 (section 10.8.4).
927 	 * The Desired Data Transfer Length must satisfy this relation:
928 	 *
929 	 *	0 < Desired Data Transfer Length <= MaxBurstLength
930 	 */
931 	if ((bp == NULL) || (data_length == 0)) {
932 		cmn_err(CE_WARN, "iscsi connection(%u) received r2t but pkt "
933 		    "has no data itt:0x%x - protocol error", icp->conn_oid,
934 		    irhp->itt);
935 	} else if (data_length > icp->conn_params.max_burst_length) {
936 		cmn_err(CE_WARN, "iscsi connection(%u) received r2t but pkt "
937 		    "is larger than MaxBurstLength itt:0x%x len:0x%x - "
938 		    "protocol error",
939 		    icp->conn_oid, irhp->itt, data_length);
940 	} else {
941 		iscsi_handle_r2t(icp, icmdp, ntohl(irhp->data_offset),
942 		    data_length, irhp->ttt);
943 		status = ISCSI_STATUS_SUCCESS;
944 	}
945 
946 	mutex_exit(&icmdp->cmd_mutex);
947 	mutex_exit(&icp->conn_queue_active.mutex);
948 	mutex_exit(&isp->sess_queue_pending.mutex);
949 
950 	return (status);
951 }
952 
953 
954 /*
955  * iscsi_rx_process_nop - Process a received nop.  If nop is in response
956  * to a ping we sent update stats.  If initiated by the target we need
957  * to response back to the target with a nop.  Schedule the response.
958  */
959 /* ARGSUSED */
960 static iscsi_status_t
961 iscsi_rx_process_nop(iscsi_conn_t *icp, iscsi_hdr_t *ihp, char *data)
962 {
963 	iscsi_status_t		rval	= ISCSI_STATUS_SUCCESS;
964 	iscsi_sess_t		*isp	= NULL;
965 	iscsi_nop_in_hdr_t	*inihp	= (iscsi_nop_in_hdr_t *)ihp;
966 	iscsi_cmd_t		*icmdp	= NULL;
967 
968 	ASSERT(icp != NULL);
969 	ASSERT(ihp != NULL);
970 	/* ASSERT(data != NULL) data is allowed to be NULL */
971 	isp = icp->conn_sess;
972 	ASSERT(isp != NULL);
973 
974 	if (icp->conn_expstatsn != ntohl(inihp->statsn)) {
975 		cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
976 		    "received status out of order itt:0x%x statsn:0x%x "
977 		    "expstatsn:0x%x", icp->conn_oid, inihp->itt,
978 		    ntohl(inihp->statsn), icp->conn_expstatsn);
979 		return (ISCSI_STATUS_PROTOCOL_ERROR);
980 	}
981 
982 	mutex_enter(&isp->sess_queue_pending.mutex);
983 	mutex_enter(&icp->conn_queue_active.mutex);
984 	mutex_enter(&isp->sess_cmdsn_mutex);
985 	if (inihp->itt != ISCSI_RSVD_TASK_TAG) {
986 		if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
987 		    isp, ihp, &icmdp))) {
988 			mutex_exit(&isp->sess_cmdsn_mutex);
989 			mutex_exit(&icp->conn_queue_active.mutex);
990 			mutex_exit(&isp->sess_queue_pending.mutex);
991 			return (ISCSI_STATUS_PROTOCOL_ERROR);
992 		}
993 	}
994 
995 	/* update expcmdsn and maxcmdsn */
996 	iscsi_update_flow_control(isp, ntohl(inihp->maxcmdsn),
997 	    ntohl(inihp->expcmdsn));
998 	mutex_exit(&isp->sess_cmdsn_mutex);
999 
1000 	if ((inihp->itt != ISCSI_RSVD_TASK_TAG) &&
1001 	    (inihp->ttt == ISCSI_RSVD_TASK_TAG)) {
1002 		/* This is the only type of nop that incs. the expstatsn */
1003 		icp->conn_expstatsn++;
1004 
1005 		/*
1006 		 * This is a targets response to our nop
1007 		 */
1008 		iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
1009 	} else if (inihp->ttt != ISCSI_RSVD_TASK_TAG) {
1010 		/*
1011 		 * Target requested a nop.  Send one.
1012 		 */
1013 		iscsi_handle_nop(icp, ISCSI_RSVD_TASK_TAG, inihp->ttt);
1014 	} else {
1015 		/*
1016 		 * This is a target-initiated ping that doesn't expect
1017 		 * a response; nothing to do except update our flow control
1018 		 * (which we do in all cases above).
1019 		 */
1020 		/* EMPTY */
1021 	}
1022 	mutex_exit(&icp->conn_queue_active.mutex);
1023 	mutex_exit(&isp->sess_queue_pending.mutex);
1024 
1025 	return (rval);
1026 }
1027 
1028 
1029 /*
1030  * iscsi_rx_process_reject_rsp - The server rejected a PDU
1031  */
1032 static iscsi_status_t
1033 iscsi_rx_process_reject_rsp(iscsi_conn_t *icp,
1034     iscsi_hdr_t *ihp, char *data)
1035 {
1036 	iscsi_reject_rsp_hdr_t		*irrhp = (iscsi_reject_rsp_hdr_t *)ihp;
1037 	iscsi_sess_t			*isp		= NULL;
1038 	uint32_t			dlength		= 0;
1039 	iscsi_hdr_t			*old_ihp	= NULL;
1040 
1041 	ASSERT(icp != NULL);
1042 	isp = icp->conn_sess;
1043 	ASSERT(ihp != NULL);
1044 	ASSERT(data != NULL);
1045 
1046 	/* make sure we only Ack Status numbers that we've actually received. */
1047 	if (icp->conn_expstatsn == ntohl(irrhp->statsn)) {
1048 		icp->conn_expstatsn++;
1049 	} else {
1050 		cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1051 		    "received status out of order itt:0x%x statsn:0x%x "
1052 		    "expstatsn:0x%x", icp->conn_oid, ihp->itt,
1053 		    ntohl(irrhp->statsn), icp->conn_expstatsn);
1054 		return (ISCSI_STATUS_PROTOCOL_ERROR);
1055 	}
1056 
1057 	/* update expcmdsn and maxcmdsn */
1058 	mutex_enter(&isp->sess_cmdsn_mutex);
1059 	iscsi_update_flow_control(isp, ntohl(irrhp->maxcmdsn),
1060 	    ntohl(irrhp->expcmdsn));
1061 	mutex_exit(&isp->sess_cmdsn_mutex);
1062 
1063 	/* If we don't have the rejected header we can't do anything */
1064 	dlength = n2h24(irrhp->dlength);
1065 	if (dlength < sizeof (iscsi_hdr_t)) {
1066 		return (ISCSI_STATUS_PROTOCOL_ERROR);
1067 	}
1068 
1069 	/* map old ihp */
1070 	old_ihp = (iscsi_hdr_t *)data;
1071 
1072 	switch (irrhp->reason) {
1073 	/*
1074 	 * ISCSI_REJECT_IMM_CMD_REJECT - Immediate Command Reject
1075 	 * too many immediate commands (original cmd can be resent)
1076 	 */
1077 	case ISCSI_REJECT_IMM_CMD_REJECT:
1078 		/*
1079 		 * We have exceeded the server's capacity for outstanding
1080 		 * immediate commands.   This must be a task management
1081 		 * command so try to find it in the abortingqueue and
1082 		 * complete it.
1083 		 */
1084 		if (!(old_ihp->opcode & ISCSI_OP_IMMEDIATE)) {
1085 			/* Rejecting IMM but old old_hdr wasn't IMM */
1086 			return (ISCSI_STATUS_PROTOCOL_ERROR);
1087 		}
1088 
1089 		/*
1090 		 * We only send NOP and TASK_MGT as IMM.  All other
1091 		 * cases should be considered as a protocol error.
1092 		 */
1093 		switch (old_ihp->opcode & ISCSI_OPCODE_MASK) {
1094 		case ISCSI_OP_NOOP_OUT:
1095 			/*
1096 			 * A ping was rejected - treat this like
1097 			 * ping response.  The down side is we
1098 			 * didn't get an updated MaxCmdSn.
1099 			 */
1100 			break;
1101 		case ISCSI_OP_SCSI_TASK_MGT_MSG:
1102 			(void) iscsi_rx_process_rejected_tsk_mgt(icp,
1103 			    old_ihp);
1104 			break;
1105 		default:
1106 			cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
1107 			    "- received a reject for a command(0x%02x) not "
1108 			    "sent as an immediate", icp->conn_oid,
1109 			    old_ihp->opcode);
1110 			return (ISCSI_STATUS_PROTOCOL_ERROR);
1111 		}
1112 		break;
1113 
1114 	/*
1115 	 * For the rest of the reject cases just use the general
1116 	 * hammer of dis/reconnecting.  This will resolve all
1117 	 * noted issues although could be more graceful.
1118 	 */
1119 	case ISCSI_REJECT_DATA_DIGEST_ERROR:
1120 	case ISCSI_REJECT_CMD_BEFORE_LOGIN:
1121 	case ISCSI_REJECT_SNACK_REJECT:
1122 	case ISCSI_REJECT_PROTOCOL_ERROR:
1123 	case ISCSI_REJECT_CMD_NOT_SUPPORTED:
1124 	case ISCSI_REJECT_TASK_IN_PROGRESS:
1125 	case ISCSI_REJECT_INVALID_DATA_ACK:
1126 	case ISCSI_REJECT_INVALID_PDU_FIELD:
1127 	case ISCSI_REJECT_LONG_OPERATION_REJECT:
1128 	case ISCSI_REJECT_NEGOTIATION_RESET:
1129 	default:
1130 		cmn_err(CE_WARN, "iscsi connection(%u) closing connection - "
1131 		    "target requested itt:0x%x reason:0x%x",
1132 		    icp->conn_oid, ihp->itt, irrhp->reason);
1133 		return (ISCSI_STATUS_PROTOCOL_ERROR);
1134 	}
1135 
1136 	return (ISCSI_STATUS_SUCCESS);
1137 }
1138 
1139 
1140 /*
1141  * iscsi_rx_process_rejected_tsk_mgt -
1142  */
1143 static iscsi_status_t
1144 iscsi_rx_process_rejected_tsk_mgt(iscsi_conn_t *icp,
1145     iscsi_hdr_t *old_ihp)
1146 {
1147 	iscsi_sess_t			*isp	= NULL;
1148 	iscsi_cmd_t			*icmdp	= NULL;
1149 
1150 	ASSERT(icp != NULL);
1151 	isp = icp->conn_sess;
1152 	ASSERT(old_ihp != NULL);
1153 	ASSERT(icp->conn_sess != NULL);
1154 
1155 	mutex_enter(&icp->conn_queue_active.mutex);
1156 	mutex_enter(&isp->sess_cmdsn_mutex);
1157 	if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
1158 	    isp, old_ihp, &icmdp))) {
1159 		mutex_exit(&isp->sess_cmdsn_mutex);
1160 		mutex_exit(&icp->conn_queue_active.mutex);
1161 		return (ISCSI_STATUS_PROTOCOL_ERROR);
1162 	}
1163 	mutex_exit(&isp->sess_cmdsn_mutex);
1164 
1165 	switch (icmdp->cmd_type) {
1166 	case ISCSI_CMD_TYPE_ABORT:
1167 	case ISCSI_CMD_TYPE_RESET:
1168 		iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E4,
1169 		    icp->conn_sess);
1170 		break;
1171 	/* We don't send any other task mgr types */
1172 	default:
1173 		ASSERT(B_FALSE);
1174 		break;
1175 	}
1176 	mutex_exit(&icp->conn_queue_active.mutex);
1177 
1178 	return (ISCSI_STATUS_SUCCESS);
1179 }
1180 
1181 
1182 /*
1183  * iscsi_rx_process_task_mgt_rsp -
1184  */
1185 /* ARGSUSED */
1186 static iscsi_status_t
1187 iscsi_rx_process_task_mgt_rsp(iscsi_conn_t *icp,
1188     iscsi_hdr_t *ihp, void *data)
1189 {
1190 	iscsi_sess_t			*isp		= NULL;
1191 	iscsi_scsi_task_mgt_rsp_hdr_t	*istmrhp	= NULL;
1192 	iscsi_cmd_t			*icmdp		= NULL;
1193 
1194 	ASSERT(ihp != NULL);
1195 	ASSERT(icp != NULL);
1196 	isp = icp->conn_sess;
1197 	ASSERT(isp != NULL);
1198 	istmrhp = (iscsi_scsi_task_mgt_rsp_hdr_t *)ihp;
1199 
1200 	if (icp->conn_expstatsn == ntohl(istmrhp->statsn)) {
1201 		icp->conn_expstatsn++;
1202 	} else {
1203 		cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1204 		    "received status out of order itt:0x%x statsn:0x%x "
1205 		    "expstatsn:0x%x", icp->conn_oid, istmrhp->itt,
1206 		    ntohl(istmrhp->statsn), icp->conn_expstatsn);
1207 		return (ISCSI_STATUS_PROTOCOL_ERROR);
1208 	}
1209 
1210 	/* make sure we only Ack Status numbers that we've actually received. */
1211 	mutex_enter(&icp->conn_queue_active.mutex);
1212 	mutex_enter(&isp->sess_cmdsn_mutex);
1213 	if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(isp, ihp, &icmdp))) {
1214 		mutex_exit(&isp->sess_cmdsn_mutex);
1215 		mutex_exit(&icp->conn_queue_active.mutex);
1216 		return (ISCSI_STATUS_PROTOCOL_ERROR);
1217 	}
1218 
1219 	/* update expcmdsn and maxcmdn */
1220 	iscsi_update_flow_control(isp, ntohl(istmrhp->maxcmdsn),
1221 	    ntohl(istmrhp->expcmdsn));
1222 	mutex_exit(&isp->sess_cmdsn_mutex);
1223 
1224 	switch (icmdp->cmd_type) {
1225 	case ISCSI_CMD_TYPE_ABORT:
1226 	case ISCSI_CMD_TYPE_RESET:
1227 		switch (istmrhp->response) {
1228 		case SCSI_TCP_TM_RESP_COMPLETE:
1229 			/* success */
1230 			iscsi_cmd_state_machine(icmdp,
1231 			    ISCSI_CMD_EVENT_E3, isp);
1232 			break;
1233 		case SCSI_TCP_TM_RESP_NO_TASK:
1234 			/*
1235 			 * If the array no longer knows about
1236 			 * an ABORT RTT and we no longer have
1237 			 * a parent SCSI command it was just
1238 			 * completed, free this ABORT resource.
1239 			 * Otherwise FALLTHRU this will flag a
1240 			 * protocol problem.
1241 			 */
1242 			if ((icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT) &&
1243 			    (icmdp->cmd_un.abort.icmdp == NULL)) {
1244 				iscsi_cmd_state_machine(icmdp,
1245 				    ISCSI_CMD_EVENT_E4, isp);
1246 				break;
1247 			}
1248 			/* FALLTHRU */
1249 		case SCSI_TCP_TM_RESP_NO_LUN:
1250 		case SCSI_TCP_TM_RESP_TASK_ALLEGIANT:
1251 		case SCSI_TCP_TM_RESP_NO_FAILOVER:
1252 		case SCSI_TCP_TM_RESP_IN_PRGRESS:
1253 		case SCSI_TCP_TM_RESP_REJECTED:
1254 		default:
1255 			/*
1256 			 * Something is out of sync.  Flush
1257 			 * active queues and resync the
1258 			 * the connection to try and recover
1259 			 * to a known state.
1260 			 */
1261 			mutex_exit(&icp->conn_queue_active.mutex);
1262 			return (ISCSI_STATUS_PROTOCOL_ERROR);
1263 		}
1264 		break;
1265 
1266 	default:
1267 		cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1268 		    "received a task mgt response for a non-task mgt "
1269 		    "cmd itt:0x%x type:%d", icp->conn_oid, istmrhp->itt,
1270 		    icmdp->cmd_type);
1271 		mutex_exit(&icp->conn_queue_active.mutex);
1272 		return (ISCSI_STATUS_PROTOCOL_ERROR);
1273 	}
1274 
1275 	mutex_exit(&icp->conn_queue_active.mutex);
1276 	return (ISCSI_STATUS_SUCCESS);
1277 }
1278 
1279 
1280 /*
1281  * iscsi_rx_process_logout -
1282  *
1283  */
1284 /* ARGSUSED */
1285 static iscsi_status_t
1286 iscsi_rx_process_logout_rsp(iscsi_conn_t *icp, iscsi_hdr_t *ihp, char *data)
1287 {
1288 	iscsi_status_t		rval	= ISCSI_STATUS_SUCCESS;
1289 	iscsi_sess_t		*isp	= icp->conn_sess;
1290 	iscsi_logout_rsp_hdr_t	*ilrhp	= (iscsi_logout_rsp_hdr_t *)ihp;
1291 	iscsi_cmd_t		*icmdp	= NULL;
1292 
1293 	ASSERT(icp != NULL);
1294 	ASSERT(ihp != NULL);
1295 	isp = icp->conn_sess;
1296 	ASSERT(isp != NULL);
1297 
1298 	if (icp->conn_expstatsn != ntohl(ilrhp->statsn)) {
1299 		cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1300 		    "received status out of order itt:0x%x statsn:0x%x "
1301 		    "expstatsn:0x%x", icp->conn_oid, ilrhp->itt,
1302 		    ntohl(ilrhp->statsn), icp->conn_expstatsn);
1303 		return (ISCSI_STATUS_PROTOCOL_ERROR);
1304 	}
1305 
1306 	mutex_enter(&icp->conn_queue_active.mutex);
1307 	mutex_enter(&isp->sess_cmdsn_mutex);
1308 	if (ilrhp->itt != ISCSI_RSVD_TASK_TAG) {
1309 		if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
1310 		    isp, ihp, &icmdp))) {
1311 			mutex_exit(&isp->sess_cmdsn_mutex);
1312 			mutex_exit(&icp->conn_queue_active.mutex);
1313 			return (ISCSI_STATUS_PROTOCOL_ERROR);
1314 		}
1315 	}
1316 
1317 	/* update expcmdsn and maxcmdsn */
1318 	iscsi_update_flow_control(isp, ntohl(ilrhp->maxcmdsn),
1319 	    ntohl(ilrhp->expcmdsn));
1320 	mutex_exit(&isp->sess_cmdsn_mutex);
1321 
1322 	switch (ilrhp->response) {
1323 	case ISCSI_LOGOUT_CID_NOT_FOUND:
1324 		/*
1325 		 * If the target doesn't know about our connection
1326 		 * then we can consider our self disconnected.
1327 		 */
1328 		/* FALLTHRU */
1329 	case ISCSI_LOGOUT_RECOVERY_UNSUPPORTED:
1330 		/*
1331 		 * We don't support ErrorRecovery levels above 0
1332 		 * currently so consider this success.
1333 		 */
1334 		/* FALLTHRU */
1335 	case ISCSI_LOGOUT_CLEANUP_FAILED:
1336 		/*
1337 		 * per spec. "cleanup failed for various reasons."
1338 		 * Although those various reasons are undefined.
1339 		 * Not sure what to do here.  So fake success,
1340 		 * which will disconnect the connection.
1341 		 */
1342 		/* FALLTHRU */
1343 	case ISCSI_LOGOUT_SUCCESS:
1344 		iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
1345 		mutex_exit(&icp->conn_queue_active.mutex);
1346 		/* logout completed successfully notify the conn */
1347 		mutex_enter(&icp->conn_state_mutex);
1348 		(void) iscsi_conn_state_machine(icp, ISCSI_CONN_EVENT_T17);
1349 		mutex_exit(&icp->conn_state_mutex);
1350 		break;
1351 	default:
1352 		mutex_exit(&icp->conn_queue_active.mutex);
1353 		rval = ISCSI_STATUS_PROTOCOL_ERROR;
1354 	}
1355 
1356 	return (rval);
1357 }
1358 
1359 
1360 /*
1361  * iscsi_rx_process_logout -
1362  *
1363  */
1364 /* ARGSUSED */
1365 static iscsi_status_t
1366 iscsi_rx_process_async_rsp(iscsi_conn_t *icp, iscsi_hdr_t *ihp, char *data)
1367 {
1368 	iscsi_status_t		rval	= ISCSI_STATUS_SUCCESS;
1369 	iscsi_async_evt_hdr_t	*iaehp	= (iscsi_async_evt_hdr_t *)ihp;
1370 
1371 	ASSERT(icp != NULL);
1372 	ASSERT(ihp != NULL);
1373 	ASSERT(icp->conn_sess != NULL);
1374 
1375 	if (icp->conn_expstatsn != ntohl(iaehp->statsn)) {
1376 		cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1377 		    "received status out of order itt:0x%x statsn:0x%x "
1378 		    "expstatsn:0x%x", icp->conn_oid, ihp->itt,
1379 		    ntohl(iaehp->statsn), icp->conn_expstatsn);
1380 		return (ISCSI_STATUS_PROTOCOL_ERROR);
1381 	}
1382 
1383 	switch (iaehp->async_event) {
1384 	case ISCSI_ASYNC_EVENT_SCSI_EVENT:
1385 		/*
1386 		 * SCSI asynchronous event is reported in
1387 		 * the sense data.  Sense data that accompanies
1388 		 * the report in the data segment identifies the
1389 		 * condition.  If the target supports SCSI
1390 		 * asynchronous events reporting (see [SAM2])
1391 		 * as indicated in the stardard INQUIRY data
1392 		 * (see [SPC3]), its use may be enabled by
1393 		 * parameters in the SCSI control mode page
1394 		 * (see [SPC3]).
1395 		 *
1396 		 * T-10 has removed SCSI asunchronous events
1397 		 * from the standard.  Although we have seen
1398 		 * a couple targets still spending these requests.
1399 		 * Those targets were specifically sending them
1400 		 * for notification of a LUN/Volume change
1401 		 * (ex. LUN addition/removal).  Take a general
1402 		 * action to these events of dis/reconnecting.
1403 		 * Once reconnected we perform a reenumeration.
1404 		 */
1405 		mutex_enter(&icp->conn_state_mutex);
1406 		(void) iscsi_conn_state_machine(icp, ISCSI_CONN_EVENT_T14);
1407 		mutex_exit(&icp->conn_state_mutex);
1408 		break;
1409 
1410 	case ISCSI_ASYNC_EVENT_REQUEST_LOGOUT:
1411 		/* Target has requested this connection to logout. */
1412 		mutex_enter(&icp->conn_state_mutex);
1413 		(void) iscsi_conn_state_machine(icp, ISCSI_CONN_EVENT_T14);
1414 		mutex_exit(&icp->conn_state_mutex);
1415 		break;
1416 
1417 	case ISCSI_ASYNC_EVENT_DROPPING_CONNECTION:
1418 		/*
1419 		 * Target is going to drop our connection.
1420 		 *	param1 - CID which will be dropped.
1421 		 *	param2 - Min time to reconnect.
1422 		 *	param3 - Max time to reconnect.
1423 		 *
1424 		 * For now just let fail as another disconnect.
1425 		 *
1426 		 * MC/S Once we support > 1 connections then
1427 		 * we need to check the CID and drop that
1428 		 * specific connection.
1429 		 */
1430 		iscsi_conn_set_login_min_max(icp, iaehp->param2, iaehp->param3);
1431 		mutex_enter(&icp->conn_state_mutex);
1432 		(void) iscsi_conn_state_machine(icp, ISCSI_CONN_EVENT_T14);
1433 		mutex_exit(&icp->conn_state_mutex);
1434 		break;
1435 
1436 	case ISCSI_ASYNC_EVENT_DROPPING_ALL_CONNECTIONS:
1437 		/*
1438 		 * Target is going to drop ALL connections.
1439 		 *	param2 - Min time to reconnect.
1440 		 *	param3 - Max time to reconnect.
1441 		 *
1442 		 * For now just let fail as anyother disconnect.
1443 		 *
1444 		 * MC/S Once we support more than > 1 connections
1445 		 * then we need to drop all connections on the
1446 		 * session.
1447 		 */
1448 		iscsi_conn_set_login_min_max(icp, iaehp->param2, iaehp->param3);
1449 		mutex_enter(&icp->conn_state_mutex);
1450 		(void) iscsi_conn_state_machine(icp, ISCSI_CONN_EVENT_T14);
1451 		mutex_exit(&icp->conn_state_mutex);
1452 		break;
1453 
1454 	case ISCSI_ASYNC_EVENT_PARAM_NEGOTIATION:
1455 		/*
1456 		 * Target requests parameter negotiation
1457 		 * on this connection.
1458 		 *
1459 		 * The initiator must honor this request.  For
1460 		 * now we will request a logout.  We can't
1461 		 * just ignore this or it might force corruption?
1462 		 */
1463 		mutex_enter(&icp->conn_state_mutex);
1464 		(void) iscsi_conn_state_machine(icp, ISCSI_CONN_EVENT_T14);
1465 		mutex_exit(&icp->conn_state_mutex);
1466 		break;
1467 
1468 	case ISCSI_ASYNC_EVENT_VENDOR_SPECIFIC:
1469 		/*
1470 		 * We currently don't handle any vendor
1471 		 * specific async events.  So just ignore
1472 		 * the request.
1473 		 */
1474 		mutex_enter(&icp->conn_state_mutex);
1475 		(void) iscsi_conn_state_machine(icp, ISCSI_CONN_EVENT_T14);
1476 		mutex_exit(&icp->conn_state_mutex);
1477 		break;
1478 	default:
1479 		rval = ISCSI_STATUS_PROTOCOL_ERROR;
1480 	}
1481 
1482 	return (rval);
1483 }
1484 
1485 /*
1486  * iscsi_rx_process_text_rsp - processes iSCSI text response.  It sets
1487  * the cmd_result field of the command data structure with the actual
1488  * status value instead of returning the status value.  The return value
1489  * is SUCCESS in order to let iscsi_handle_text control the operation of
1490  * a text request.
1491  * Test requests are a handled a little different than other types of
1492  * iSCSI commands because the initiator sends additional empty text requests
1493  * in order to obtain the remaining responses required to complete the
1494  * request.  iscsi_handle_text controls the operation of text request, while
1495  * iscsi_rx_process_text_rsp just process the current response.
1496  */
1497 static iscsi_status_t
1498 iscsi_rx_process_text_rsp(iscsi_conn_t *icp, iscsi_hdr_t *ihp, char *data)
1499 {
1500 	iscsi_sess_t		*isp	= NULL;
1501 	iscsi_text_rsp_hdr_t	*ithp	= (iscsi_text_rsp_hdr_t *)ihp;
1502 	iscsi_cmd_t		*icmdp	= NULL;
1503 	boolean_t		final	= B_FALSE;
1504 	uint32_t		data_len;
1505 
1506 	ASSERT(icp != NULL);
1507 	ASSERT(ihp != NULL);
1508 	ASSERT(data != NULL);
1509 
1510 	isp = icp->conn_sess;
1511 	ASSERT(isp != NULL);
1512 
1513 	if (icp->conn_expstatsn == ntohl(ithp->statsn)) {
1514 		icp->conn_expstatsn++;
1515 	} else {
1516 		cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1517 		    "received status out of order itt:0x%x statsn:0x%x "
1518 		    "expstatsn:0x%x", icp->conn_oid, ithp->itt,
1519 		    ntohl(ithp->statsn), icp->conn_expstatsn);
1520 		return (ISCSI_STATUS_PROTOCOL_ERROR);
1521 	}
1522 
1523 	mutex_enter(&icp->conn_queue_active.mutex);
1524 	mutex_enter(&isp->sess_cmdsn_mutex);
1525 	if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(isp, ihp, &icmdp))) {
1526 		mutex_exit(&isp->sess_cmdsn_mutex);
1527 		mutex_exit(&icp->conn_queue_active.mutex);
1528 		return (ISCSI_STATUS_PROTOCOL_ERROR);
1529 	}
1530 
1531 	/* update expcmdsn and maxcmdsn */
1532 	iscsi_update_flow_control(isp, ntohl(ithp->maxcmdsn),
1533 	    ntohl(ithp->expcmdsn));
1534 	mutex_exit(&isp->sess_cmdsn_mutex);
1535 
1536 	/* update local final response flag */
1537 	if (ithp->flags & ISCSI_FLAG_FINAL) {
1538 		final = B_TRUE;
1539 	}
1540 
1541 	/*
1542 	 * validate received TTT value.  RFC3720 specifies the following:
1543 	 * - F bit set to 1 MUST have a reserved TTT value 0xffffffff
1544 	 * - F bit set to 0 MUST have a non-reserved TTT value !0xffffffff
1545 	 * In addition, the received TTT value must not change between
1546 	 * responses of a long text response
1547 	 */
1548 	if (((final == B_TRUE) && (ithp->ttt != ISCSI_RSVD_TASK_TAG)) ||
1549 	    ((final == B_FALSE) && (ithp->ttt == ISCSI_RSVD_TASK_TAG))) {
1550 		icmdp->cmd_result = ISCSI_STATUS_PROTOCOL_ERROR;
1551 		icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1552 		mutex_exit(&icp->conn_queue_active.mutex);
1553 		cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1554 		    "received text response with invalid flags:0x%x or "
1555 		    "ttt:0x%x", icp->conn_oid, ithp->flags, ithp->itt);
1556 		return (ISCSI_STATUS_PROTOCOL_ERROR);
1557 	}
1558 
1559 	if ((icmdp->cmd_un.text.stage == ISCSI_CMD_TEXT_INITIAL_REQ) &&
1560 	    (ithp->ttt == ISCSI_RSVD_TASK_TAG) &&
1561 	    (final == B_FALSE)) {
1562 		/* TTT should have matched reserved value */
1563 		icmdp->cmd_result = ISCSI_STATUS_PROTOCOL_ERROR;
1564 		icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1565 		mutex_exit(&icp->conn_queue_active.mutex);
1566 		cmn_err(CE_WARN, "iscsi connection(%u) protocol "
1567 		    "error - received text response with invalid "
1568 		    "ttt:0x%x", icp->conn_oid, ithp->ttt);
1569 		return (ISCSI_STATUS_PROTOCOL_ERROR);
1570 	}
1571 
1572 	/*
1573 	 * If this is first response, save away TTT value for later use
1574 	 * in a long text request/response sequence
1575 	 */
1576 	if (icmdp->cmd_un.text.stage == ISCSI_CMD_TEXT_INITIAL_REQ) {
1577 		icmdp->cmd_un.text.ttt = ithp->ttt;
1578 	}
1579 
1580 	data_len = ntoh24(ithp->dlength);
1581 
1582 	/* check whether enough buffer available to copy data */
1583 	if ((icmdp->cmd_un.text.total_rx_len + data_len) >
1584 	    icmdp->cmd_un.text.buf_len) {
1585 		icmdp->cmd_un.text.total_rx_len += data_len;
1586 		icmdp->cmd_result = ISCSI_STATUS_DATA_OVERFLOW;
1587 		/*
1588 		 * DATA_OVERFLOW will result in a SUCCESS return so that
1589 		 * iscsi_handle_text can continue to obtain the remaining
1590 		 * text response if needed.
1591 		 */
1592 	} else {
1593 		char *buf_data = (icmdp->cmd_un.text.buf +
1594 		    icmdp->cmd_un.text.offset);
1595 
1596 		bcopy(data, buf_data, data_len);
1597 		icmdp->cmd_un.text.offset += data_len;
1598 		icmdp->cmd_un.text.total_rx_len += data_len;
1599 		icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
1600 		bcopy(ithp->rsvd4, icmdp->cmd_un.text.lun,
1601 		    sizeof (icmdp->cmd_un.text.lun));
1602 	}
1603 
1604 	/* update stage  */
1605 	if (final == B_TRUE) {
1606 		icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1607 	} else {
1608 		icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_CONTINUATION;
1609 	}
1610 
1611 	iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
1612 	mutex_exit(&icp->conn_queue_active.mutex);
1613 	return (ISCSI_STATUS_SUCCESS);
1614 }
1615 
1616 /*
1617  * iscsi_rx_process_itt_to_icmdp - Lookup itt in the session's
1618  * cmd table to find matching icmdp.  Verify itt in hdr and
1619  * icmdp are the same.
1620  */
1621 static iscsi_status_t
1622 iscsi_rx_process_itt_to_icmdp(iscsi_sess_t *isp, iscsi_hdr_t *ihp,
1623     iscsi_cmd_t **icmdp)
1624 {
1625 	int cmd_table_idx = 0;
1626 
1627 	ASSERT(isp != NULL);
1628 	ASSERT(ihp != NULL);
1629 	ASSERT(icmdp != NULL);
1630 	ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
1631 
1632 	/* try to find an associated iscsi_pkt */
1633 	cmd_table_idx = ihp->itt % ISCSI_CMD_TABLE_SIZE;
1634 	if (isp->sess_cmd_table[cmd_table_idx] == NULL) {
1635 		cmn_err(CE_WARN, "iscsi session(%u) protocol error - "
1636 		    "received unknown itt:0x%x - protocol error",
1637 		    isp->sess_oid, ihp->itt);
1638 		return (ISCSI_STATUS_INTERNAL_ERROR);
1639 	}
1640 
1641 	/* verify itt */
1642 	if (isp->sess_cmd_table[cmd_table_idx]->cmd_itt != ihp->itt) {
1643 		cmn_err(CE_WARN, "iscsi session(%u) received itt:0x%x "
1644 		    " which is out of sync with itt:0x%x", isp->sess_oid,
1645 		    ihp->itt, isp->sess_cmd_table[cmd_table_idx]->cmd_itt);
1646 		return (ISCSI_STATUS_INTERNAL_ERROR);
1647 	}
1648 
1649 	/* ensure that icmdp is still in Active state */
1650 	if (isp->sess_cmd_table[cmd_table_idx]->cmd_state !=
1651 	    ISCSI_CMD_STATE_ACTIVE) {
1652 		cmn_err(CE_WARN, "iscsi session(%u) received itt:0x%x "
1653 		    "but icmdp (%p) is not in active state",
1654 		    isp->sess_oid, ihp->itt,
1655 		    (void *)isp->sess_cmd_table[cmd_table_idx]);
1656 		return (ISCSI_STATUS_INTERNAL_ERROR);
1657 	}
1658 
1659 	/* make sure this is a SCSI cmd */
1660 	*icmdp = isp->sess_cmd_table[cmd_table_idx];
1661 
1662 	return (ISCSI_STATUS_SUCCESS);
1663 }
1664 
1665 
1666 /*
1667  * +--------------------------------------------------------------------+
1668  * | End of protocol receive routines					|
1669  * +--------------------------------------------------------------------+
1670  */
1671 
1672 /*
1673  * +--------------------------------------------------------------------+
1674  * | Beginning of protocol send routines				|
1675  * +--------------------------------------------------------------------+
1676  */
1677 
1678 
1679 /*
1680  * iscsi_tx_thread - This thread is the driving point for all
1681  * iSCSI PDUs after login.  No PDUs should call sendpdu()
1682  * directly they should be funneled through iscsi_tx_thread.
1683  */
1684 void
1685 iscsi_tx_thread(iscsi_thread_t *thread, void *arg)
1686 {
1687 	iscsi_conn_t	*icp	= (iscsi_conn_t *)arg;
1688 	iscsi_sess_t	*isp	= NULL;
1689 	iscsi_cmd_t	*icmdp	= NULL;
1690 	clock_t		tout;
1691 	int		ret	= 1;
1692 
1693 	ASSERT(icp != NULL);
1694 	isp = icp->conn_sess;
1695 	ASSERT(isp != NULL);
1696 	ASSERT(thread != NULL);
1697 	ASSERT(thread->signature == SIG_ISCSI_THREAD);
1698 
1699 	tout = SEC_TO_TICK(1);
1700 	/*
1701 	 * Transfer icmdps until shutdown by owning session.
1702 	 */
1703 	while (ret != 0) {
1704 
1705 		isp->sess_window_open = B_TRUE;
1706 
1707 		/*
1708 		 * While the window is open, there are commands available
1709 		 * to send and the session state allows those commands to
1710 		 * be sent try to transfer them.
1711 		 */
1712 		mutex_enter(&isp->sess_queue_pending.mutex);
1713 		while ((isp->sess_window_open == B_TRUE) &&
1714 		    ((icmdp = isp->sess_queue_pending.head) != NULL) &&
1715 		    (((icmdp->cmd_type != ISCSI_CMD_TYPE_SCSI) &&
1716 		    (ISCSI_CONN_STATE_FULL_FEATURE(icp->conn_state))) ||
1717 		    (icp->conn_state == ISCSI_CONN_STATE_LOGGED_IN))) {
1718 
1719 			/* update command with this connection info */
1720 			icmdp->cmd_conn = icp;
1721 			/* attempt to send this command */
1722 			iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E2, isp);
1723 
1724 			ASSERT(!mutex_owned(&isp->sess_queue_pending.mutex));
1725 			mutex_enter(&isp->sess_queue_pending.mutex);
1726 		}
1727 		mutex_exit(&isp->sess_queue_pending.mutex);
1728 
1729 		/*
1730 		 * Go to sleep until there is something new
1731 		 * to process (awoken via cv_boardcast).
1732 		 * Or the timer goes off.
1733 		 */
1734 		ret = iscsi_thread_wait(thread, tout);
1735 	}
1736 
1737 }
1738 
1739 
1740 /*
1741  * iscsi_tx_cmd - transfers icmdp across wire as iscsi pdu
1742  *
1743  * Just prior to sending the command to the networking layer the
1744  * pending queue lock will be dropped.  At this point only local
1745  * resources will be used, not the icmdp.  Holding the queue lock
1746  * across the networking call can lead to a hang.  (This is due
1747  * to the the target driver and networking layers competing use
1748  * of the timeout() resources and the queue lock being held for
1749  * both sides.)  Upon the completion of this command the lock
1750  * will have been re-acquired.
1751  */
1752 iscsi_status_t
1753 iscsi_tx_cmd(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
1754 {
1755 	iscsi_status_t	rval = ISCSI_STATUS_INTERNAL_ERROR;
1756 
1757 	ASSERT(isp != NULL);
1758 	ASSERT(icmdp != NULL);
1759 
1760 	/* transfer specific command type */
1761 	switch (icmdp->cmd_type) {
1762 	case ISCSI_CMD_TYPE_SCSI:
1763 		rval = iscsi_tx_scsi(isp, icmdp);
1764 		break;
1765 	case ISCSI_CMD_TYPE_R2T:
1766 		rval = iscsi_tx_r2t(isp, icmdp);
1767 		break;
1768 	case ISCSI_CMD_TYPE_NOP:
1769 		rval = iscsi_tx_nop(isp, icmdp);
1770 		break;
1771 	case ISCSI_CMD_TYPE_ABORT:
1772 		rval = iscsi_tx_abort(isp, icmdp);
1773 		break;
1774 	case ISCSI_CMD_TYPE_RESET:
1775 		rval = iscsi_tx_reset(isp, icmdp);
1776 		break;
1777 	case ISCSI_CMD_TYPE_LOGOUT:
1778 		rval = iscsi_tx_logout(isp, icmdp);
1779 		break;
1780 	case ISCSI_CMD_TYPE_TEXT:
1781 		rval = iscsi_tx_text(isp, icmdp);
1782 		break;
1783 	default:
1784 		ASSERT(FALSE);
1785 	}
1786 
1787 	ASSERT(!mutex_owned(&isp->sess_queue_pending.mutex));
1788 	return (rval);
1789 }
1790 
1791 /*
1792  * a variable length cdb can be up to 16K, but we obviously don't want
1793  * to put that on the stack; go with 200 bytes; if we get something
1794  * bigger than that we will kmem_alloc a buffer
1795  */
1796 #define	DEF_CDB_LEN	200
1797 
1798 /*
1799  * given the size of the cdb, return how many bytes the header takes,
1800  * which is the sizeof addl_hdr_t + the CDB size, minus the 16 bytes
1801  * stored in the basic header, minus sizeof (ahs_extscb)
1802  */
1803 #define	ADDLHDRSZ(x)		(sizeof (iscsi_addl_hdr_t) + (x) - \
1804 					16 - 4)
1805 
1806 /*
1807  * iscsi_tx_scsi -
1808  *
1809  */
1810 static iscsi_status_t
1811 iscsi_tx_scsi(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
1812 {
1813 	iscsi_status_t		rval		= ISCSI_STATUS_SUCCESS;
1814 	iscsi_conn_t		*icp		= NULL;
1815 	struct scsi_pkt		*pkt		= NULL;
1816 	struct buf		*bp		= NULL;
1817 	union {
1818 		iscsi_scsi_cmd_hdr_t	isch;
1819 		iscsi_addl_hdr_t	iah;
1820 		uchar_t			arr[ADDLHDRSZ(DEF_CDB_LEN)];
1821 	} hdr_un;
1822 	iscsi_scsi_cmd_hdr_t	*ihp		=
1823 	    (iscsi_scsi_cmd_hdr_t *)&hdr_un.isch;
1824 	int			cdblen		= 0;
1825 	size_t			buflen		= 0;
1826 	uint32_t		imdata		= 0;
1827 	uint32_t		first_burst_length = 0;
1828 
1829 	ASSERT(isp != NULL);
1830 	ASSERT(icmdp != NULL);
1831 	pkt = icmdp->cmd_un.scsi.pkt;
1832 	ASSERT(pkt != NULL);
1833 	bp = icmdp->cmd_un.scsi.bp;
1834 	icp = icmdp->cmd_conn;
1835 	ASSERT(icp != NULL);
1836 
1837 	/* Reset counts in case we are on a retry */
1838 	icmdp->cmd_un.scsi.data_transferred = 0;
1839 
1840 	if (icmdp->cmd_un.scsi.cmdlen > DEF_CDB_LEN) {
1841 		cdblen = icmdp->cmd_un.scsi.cmdlen;
1842 		ihp = kmem_zalloc(ADDLHDRSZ(cdblen), KM_SLEEP);
1843 	} else {
1844 		/*
1845 		 * only bzero the basic header; the additional header
1846 		 * will be set up correctly later, if needed
1847 		 */
1848 		bzero(ihp, sizeof (iscsi_scsi_cmd_hdr_t));
1849 	}
1850 	ihp->opcode		= ISCSI_OP_SCSI_CMD;
1851 	ihp->itt		= icmdp->cmd_itt;
1852 	mutex_enter(&isp->sess_cmdsn_mutex);
1853 	ihp->cmdsn		= htonl(isp->sess_cmdsn);
1854 	isp->sess_cmdsn++;
1855 	mutex_exit(&isp->sess_cmdsn_mutex);
1856 	ihp->expstatsn		= htonl(icp->conn_expstatsn);
1857 	icp->conn_laststatsn = icp->conn_expstatsn;
1858 
1859 	pkt->pkt_state = (STATE_GOT_BUS | STATE_GOT_TARGET);
1860 	pkt->pkt_reason = CMD_INCOMPLETE;
1861 
1862 	/*
1863 	 * Sestion 12.11 of the iSCSI specification has a good table
1864 	 * describing when uncolicited data and/or immediate data
1865 	 * should be sent.
1866 	 */
1867 	bp = icmdp->cmd_un.scsi.bp;
1868 	if ((bp != NULL) && bp->b_bcount) {
1869 		buflen = bp->b_bcount;
1870 		first_burst_length = icp->conn_params.first_burst_length;
1871 
1872 		if (bp->b_flags & B_READ) {
1873 			ihp->flags = ISCSI_FLAG_FINAL;
1874 			/*
1875 			 * fix problem where OS sends bp (B_READ &
1876 			 * b_bcount!=0) for a TUR or START_STOP.
1877 			 * (comment came from cisco code.)
1878 			 */
1879 			if ((pkt->pkt_cdbp[0] != SCMD_TEST_UNIT_READY) &&
1880 			    (pkt->pkt_cdbp[0] != SCMD_START_STOP)) {
1881 				ihp->flags |= ISCSI_FLAG_CMD_READ;
1882 				ihp->data_length = htonl(buflen);
1883 			}
1884 		} else {
1885 			ihp->flags = ISCSI_FLAG_CMD_WRITE;
1886 			/*
1887 			 * FinalBit on the the iSCSI PDU denotes this
1888 			 * is the last PDU in the sequence.
1889 			 *
1890 			 * initial_r2t = true means R2T is required
1891 			 * for additional PDU, so there will be no more
1892 			 * unsolicited PDUs following
1893 			 */
1894 			if (icp->conn_params.initial_r2t) {
1895 				ihp->flags |= ISCSI_FLAG_FINAL;
1896 			}
1897 
1898 			/* Check if we should send ImmediateData */
1899 			if (icp->conn_params.immediate_data) {
1900 				imdata = MIN(MIN(buflen,
1901 				    first_burst_length),
1902 				    icmdp->cmd_conn->conn_params.
1903 				    max_xmit_data_seg_len);
1904 
1905 				/*
1906 				 * if everything fits immediate, or
1907 				 * we can send all burst data immediate
1908 				 * (not unsol), set F
1909 				 */
1910 				if ((imdata == buflen) ||
1911 				    (imdata == first_burst_length)) {
1912 					ihp->flags |= ISCSI_FLAG_FINAL;
1913 				}
1914 
1915 				hton24(ihp->dlength, imdata);
1916 			}
1917 
1918 			/* total data transfer length */
1919 			ihp->data_length = htonl(buflen);
1920 		}
1921 	} else {
1922 		ihp->flags = ISCSI_FLAG_FINAL;
1923 		buflen = 0;
1924 	}
1925 
1926 	/* tagged queuing */
1927 	if (pkt->pkt_flags & FLAG_HTAG) {
1928 		ihp->flags |= ISCSI_ATTR_HEAD_OF_QUEUE;
1929 	} else if (pkt->pkt_flags & FLAG_OTAG) {
1930 		ihp->flags |= ISCSI_ATTR_ORDERED;
1931 	} else if (pkt->pkt_flags & FLAG_STAG) {
1932 		ihp->flags |= ISCSI_ATTR_SIMPLE;
1933 	} else {
1934 		/* ihp->flags |= ISCSI_ATTR_UNTAGGED; */
1935 		/* EMPTY */
1936 	}
1937 
1938 	/* iscsi states lun is based on spc.2 */
1939 	ISCSI_LUN_BYTE_COPY(ihp->lun, icmdp->cmd_un.scsi.lun);
1940 
1941 	if (icmdp->cmd_un.scsi.cmdlen <= 16) {
1942 		/* copy the SCSI Command Block into the PDU */
1943 		bcopy(pkt->pkt_cdbp, ihp->scb,
1944 		    icmdp->cmd_un.scsi.cmdlen);
1945 	} else {
1946 		iscsi_addl_hdr_t *iahp;
1947 
1948 		iahp = (iscsi_addl_hdr_t *)ihp;
1949 
1950 		ihp->hlength = (ADDLHDRSZ(icmdp->cmd_un.scsi.cmdlen) -
1951 		    sizeof (iscsi_scsi_cmd_hdr_t) + 3) / 4;
1952 		iahp->ahs_hlen_hi = 0;
1953 		iahp->ahs_hlen_lo = (icmdp->cmd_un.scsi.cmdlen - 15);
1954 		iahp->ahs_key = 0x01;
1955 		iahp->ahs_resv = 0;
1956 		bcopy(pkt->pkt_cdbp, ihp->scb, 16);
1957 		bcopy(((char *)pkt->pkt_cdbp) + 16, &iahp->ahs_extscb[0],
1958 		    icmdp->cmd_un.scsi.cmdlen);
1959 	}
1960 
1961 	/*
1962 	 * Update all values before transfering.
1963 	 * We should never touch the icmdp after
1964 	 * transfering if there is no more data
1965 	 * to send.  The only case the sendpdu()
1966 	 * will fail is a on a connection disconnect
1967 	 * in that case the command will be flushed.
1968 	 */
1969 	pkt->pkt_state |= STATE_SENT_CMD;
1970 
1971 	icmdp->cmd_un.scsi.data_transferred += imdata;
1972 
1973 	/*
1974 	 * Check if there is additional data to transfer beyond what
1975 	 * will be sent as part of the initial command.  If InitialR2T
1976 	 * is disabled then we should fake up a R2T so all the data,
1977 	 * up to first burst length, is sent in an unsolicited
1978 	 * fashion.  We have already sent as much immediate data
1979 	 * as possible.
1980 	 */
1981 	if ((buflen > 0) &&
1982 	    ((bp->b_flags & B_READ) == 0) &&
1983 	    (icp->conn_params.initial_r2t == 0) &&
1984 	    (MIN(first_burst_length, buflen) - imdata > 0)) {
1985 
1986 		uint32_t xfer_len = MIN(first_burst_length, buflen) - imdata;
1987 		/* data will be chunked at tx */
1988 		iscsi_handle_r2t(icp, icmdp, imdata,
1989 		    xfer_len, ISCSI_RSVD_TASK_TAG);
1990 	}
1991 
1992 	/* release pending queue mutex across the network call */
1993 	mutex_exit(&isp->sess_queue_pending.mutex);
1994 
1995 	/* Transfer Cmd PDU */
1996 	if (imdata) {
1997 		rval = iscsi_net->sendpdu(icp->conn_socket,
1998 		    (iscsi_hdr_t *)ihp, icmdp->cmd_un.scsi.bp->b_un.b_addr,
1999 		    ISCSI_CONN_TO_NET_DIGEST(icp));
2000 		if (ISCSI_SUCCESS(rval)) {
2001 			KSTAT_ADD_CONN_TX_BYTES(icp, imdata);
2002 		}
2003 	} else {
2004 		rval = iscsi_net->sendpdu(icp->conn_socket,
2005 		    (iscsi_hdr_t *)ihp, NULL,
2006 		    ISCSI_CONN_TO_NET_DIGEST(icp));
2007 	}
2008 	if (cdblen) {
2009 		kmem_free(ihp, ADDLHDRSZ(cdblen));
2010 	}
2011 
2012 	return (rval);
2013 }
2014 
2015 
2016 /*
2017  * iscsi_tx_r2t -
2018  *
2019  */
2020 static iscsi_status_t
2021 iscsi_tx_r2t(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2022 {
2023 	iscsi_status_t	rval		= ISCSI_STATUS_SUCCESS;
2024 	iscsi_conn_t	*icp		= NULL;
2025 	iscsi_cmd_t	*orig_icmdp	= NULL;
2026 
2027 	ASSERT(isp != NULL);
2028 	ASSERT(icmdp != NULL);
2029 	icp = icmdp->cmd_conn;
2030 	ASSERT(icp);
2031 	orig_icmdp = icmdp->cmd_un.r2t.icmdp;
2032 	ASSERT(orig_icmdp);
2033 
2034 	/* validate the offset and length against the buffer size */
2035 	if ((icmdp->cmd_un.r2t.offset + icmdp->cmd_un.r2t.length) >
2036 	    orig_icmdp->cmd_un.scsi.bp->b_bcount) {
2037 		cmn_err(CE_WARN, "iscsi session(%u) ignoring invalid r2t "
2038 		    "for icmd itt:0x%x offset:0x%x length:0x%x bufsize:0x%lx",
2039 		    isp->sess_oid, icmdp->cmd_itt, icmdp->cmd_un.r2t.offset,
2040 		    icmdp->cmd_un.r2t.length, orig_icmdp->cmd_un.scsi.bp->
2041 		    b_bcount);
2042 		mutex_exit(&isp->sess_queue_pending.mutex);
2043 		return (ISCSI_STATUS_INTERNAL_ERROR);
2044 	}
2045 	ASSERT(orig_icmdp->cmd_un.scsi.r2t_icmdp);
2046 
2047 	rval = iscsi_tx_data(isp, icp, orig_icmdp, icmdp->cmd_ttt,
2048 	    icmdp->cmd_un.r2t.length, icmdp->cmd_un.r2t.offset);
2049 
2050 	mutex_enter(&orig_icmdp->cmd_mutex);
2051 	orig_icmdp->cmd_un.scsi.r2t_icmdp = NULL;
2052 	icmdp->cmd_un.r2t.icmdp = NULL;
2053 	/*
2054 	 * we're finished with this r2t; there could be another r2t
2055 	 * waiting on us to finish, so signal it.
2056 	 */
2057 	cv_broadcast(&orig_icmdp->cmd_completion);
2058 	mutex_exit(&orig_icmdp->cmd_mutex);
2059 	/*
2060 	 * the parent command may be waiting for us to finish; if so,
2061 	 * wake the _ic_ thread
2062 	 */
2063 	if ((orig_icmdp->cmd_state == ISCSI_CMD_STATE_COMPLETED) &&
2064 	    (ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) &&
2065 	    (orig_icmdp->cmd_un.scsi.r2t_more == B_FALSE))
2066 		iscsi_thread_send_wakeup(isp->sess_ic_thread);
2067 	ASSERT(!mutex_owned(&isp->sess_queue_pending.mutex));
2068 	return (rval);
2069 }
2070 
2071 
2072 /*
2073  * iscsi_tx_data -
2074  */
2075 static iscsi_status_t
2076 iscsi_tx_data(iscsi_sess_t *isp, iscsi_conn_t *icp, iscsi_cmd_t *icmdp,
2077     uint32_t ttt, size_t datalen, size_t offset)
2078 {
2079 	iscsi_status_t		rval		= ISCSI_STATUS_SUCCESS;
2080 	struct buf		*bp		= NULL;
2081 	size_t			remainder	= 0;
2082 	size_t			chunk		= 0;
2083 	char			*data		= NULL;
2084 	uint32_t		data_sn		= 0;
2085 	iscsi_data_hdr_t	idhp;
2086 	uint32_t		itt;
2087 	uint32_t		lun;
2088 
2089 	ASSERT(isp != NULL);
2090 	ASSERT(icp != NULL);
2091 	ASSERT(icmdp != NULL);
2092 	bp = icmdp->cmd_un.scsi.bp;
2093 
2094 	/* verify there is data to send */
2095 	if (bp == NULL) {
2096 		mutex_exit(&isp->sess_queue_pending.mutex);
2097 		return (ISCSI_STATUS_INTERNAL_ERROR);
2098 	}
2099 
2100 	itt = icmdp->cmd_itt;
2101 	lun = icmdp->cmd_un.scsi.lun;
2102 
2103 	/*
2104 	 * update the LUN with the amount of data we will
2105 	 * transfer.  If there is a failure it's because of
2106 	 * a network fault and the command will get flushed.
2107 	 */
2108 	icmdp->cmd_un.scsi.data_transferred += datalen;
2109 
2110 	/* release pending queue mutex across the network call */
2111 	mutex_exit(&isp->sess_queue_pending.mutex);
2112 
2113 	remainder = datalen;
2114 	while (remainder) {
2115 
2116 		/* Check so see if we need to chunk the data */
2117 		if ((icp->conn_params.max_xmit_data_seg_len > 0) &&
2118 		    (remainder > icp->conn_params.max_xmit_data_seg_len)) {
2119 			chunk = icp->conn_params.max_xmit_data_seg_len;
2120 		} else {
2121 			chunk = remainder;
2122 		}
2123 
2124 		/* setup iscsi data hdr */
2125 		bzero(&idhp, sizeof (iscsi_data_hdr_t));
2126 		idhp.opcode	= ISCSI_OP_SCSI_DATA;
2127 		idhp.itt	= itt;
2128 		idhp.ttt	= ttt;
2129 		ISCSI_LUN_BYTE_COPY(idhp.lun, lun);
2130 		idhp.expstatsn	= htonl(icp->conn_expstatsn);
2131 		icp->conn_laststatsn = icp->conn_expstatsn;
2132 		idhp.datasn	= htonl(data_sn);
2133 		data_sn++;
2134 		idhp.offset	= htonl(offset);
2135 		hton24(idhp.dlength, chunk);
2136 
2137 		if (chunk == remainder) {
2138 			idhp.flags = ISCSI_FLAG_FINAL; /* final chunk */
2139 		}
2140 
2141 		/* setup data */
2142 		data = bp->b_un.b_addr + offset;
2143 
2144 		/*
2145 		 * Keep track of how much data we have
2146 		 * transfer so far and how much is remaining.
2147 		 */
2148 		remainder -= chunk;
2149 		offset += chunk;
2150 
2151 		rval = iscsi_net->sendpdu(icp->conn_socket,
2152 		    (iscsi_hdr_t *)&idhp, data,
2153 		    ISCSI_CONN_TO_NET_DIGEST(icp));
2154 
2155 		if (ISCSI_SUCCESS(rval)) {
2156 			KSTAT_ADD_CONN_TX_BYTES(icp, chunk);
2157 		} else {
2158 			break;
2159 		}
2160 	}
2161 
2162 	return (rval);
2163 }
2164 
2165 
2166 /*
2167  * iscsi_tx_nop -
2168  *
2169  */
2170 static iscsi_status_t
2171 iscsi_tx_nop(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2172 {
2173 	iscsi_status_t		rval	= ISCSI_STATUS_SUCCESS;
2174 	iscsi_conn_t		*icp	= NULL;
2175 	iscsi_nop_out_hdr_t	inohp;
2176 
2177 	ASSERT(isp != NULL);
2178 	ASSERT(icmdp != NULL);
2179 	icp = icmdp->cmd_conn;
2180 	ASSERT(icp != NULL);
2181 
2182 	bzero(&inohp, sizeof (iscsi_nop_out_hdr_t));
2183 	inohp.opcode	= ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
2184 	inohp.flags	= ISCSI_FLAG_FINAL;
2185 	inohp.itt	= icmdp->cmd_itt;
2186 	inohp.ttt	= icmdp->cmd_ttt;
2187 	mutex_enter(&isp->sess_cmdsn_mutex);
2188 	inohp.cmdsn	= htonl(isp->sess_cmdsn);
2189 	mutex_exit(&isp->sess_cmdsn_mutex);
2190 	inohp.expstatsn	= htonl(icp->conn_expstatsn);
2191 	icp->conn_laststatsn = icp->conn_expstatsn;
2192 
2193 	/* release pending queue mutex across the network call */
2194 	mutex_exit(&isp->sess_queue_pending.mutex);
2195 
2196 	rval = iscsi_net->sendpdu(icp->conn_socket,
2197 	    (iscsi_hdr_t *)&inohp, NULL,
2198 	    ISCSI_CONN_TO_NET_DIGEST(icp));
2199 
2200 	return (rval);
2201 }
2202 
2203 
2204 /*
2205  * iscsi_tx_abort -
2206  *
2207  */
2208 static iscsi_status_t
2209 iscsi_tx_abort(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2210 {
2211 	iscsi_status_t			rval	= ISCSI_STATUS_SUCCESS;
2212 	iscsi_conn_t			*icp	= NULL;
2213 	iscsi_scsi_task_mgt_hdr_t	istmh;
2214 
2215 	ASSERT(isp != NULL);
2216 	ASSERT(icmdp != NULL);
2217 	icp = icmdp->cmd_conn;
2218 	ASSERT(icp != NULL);
2219 
2220 	bzero(&istmh, sizeof (iscsi_scsi_task_mgt_hdr_t));
2221 	mutex_enter(&isp->sess_cmdsn_mutex);
2222 	istmh.cmdsn	= htonl(isp->sess_cmdsn);
2223 	mutex_exit(&isp->sess_cmdsn_mutex);
2224 	istmh.expstatsn = htonl(icp->conn_expstatsn);
2225 	icp->conn_laststatsn = icp->conn_expstatsn;
2226 	istmh.itt	= icmdp->cmd_itt;
2227 	istmh.opcode	= ISCSI_OP_SCSI_TASK_MGT_MSG | ISCSI_OP_IMMEDIATE;
2228 	istmh.function	= ISCSI_FLAG_FINAL | ISCSI_TM_FUNC_ABORT_TASK;
2229 	ISCSI_LUN_BYTE_COPY(istmh.lun,
2230 	    icmdp->cmd_un.abort.icmdp->cmd_un.scsi.lun);
2231 	istmh.rtt	= icmdp->cmd_un.abort.icmdp->cmd_itt;
2232 
2233 	/* release pending queue mutex across the network call */
2234 	mutex_exit(&isp->sess_queue_pending.mutex);
2235 
2236 	rval = iscsi_net->sendpdu(icp->conn_socket,
2237 	    (iscsi_hdr_t *)&istmh, NULL,
2238 	    ISCSI_CONN_TO_NET_DIGEST(icp));
2239 
2240 	return (rval);
2241 }
2242 
2243 
2244 /*
2245  * iscsi_tx_reset -
2246  *
2247  */
2248 static iscsi_status_t
2249 iscsi_tx_reset(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2250 {
2251 	iscsi_status_t			rval	= ISCSI_STATUS_SUCCESS;
2252 	iscsi_conn_t			*icp	= NULL;
2253 	iscsi_scsi_task_mgt_hdr_t	istmh;
2254 
2255 	ASSERT(isp != NULL);
2256 	ASSERT(icmdp != NULL);
2257 	icp = icmdp->cmd_conn;
2258 	ASSERT(icp != NULL);
2259 
2260 	bzero(&istmh, sizeof (iscsi_scsi_task_mgt_hdr_t));
2261 	istmh.opcode	= ISCSI_OP_SCSI_TASK_MGT_MSG | ISCSI_OP_IMMEDIATE;
2262 	mutex_enter(&isp->sess_cmdsn_mutex);
2263 	istmh.cmdsn	= htonl(isp->sess_cmdsn);
2264 	mutex_exit(&isp->sess_cmdsn_mutex);
2265 	istmh.expstatsn	= htonl(icp->conn_expstatsn);
2266 	istmh.itt	= icmdp->cmd_itt;
2267 
2268 	switch (icmdp->cmd_un.reset.level) {
2269 	case RESET_LUN:
2270 		istmh.function	= ISCSI_FLAG_FINAL |
2271 		    ISCSI_TM_FUNC_LOGICAL_UNIT_RESET;
2272 		ISCSI_LUN_BYTE_COPY(istmh.lun, icmdp->cmd_lun->lun_num);
2273 		break;
2274 	case RESET_TARGET:
2275 	case RESET_BUS:
2276 		istmh.function	= ISCSI_FLAG_FINAL |
2277 		    ISCSI_TM_FUNC_TARGET_WARM_RESET;
2278 		break;
2279 	default:
2280 		/* unsupported / unknown level */
2281 		ASSERT(FALSE);
2282 		break;
2283 	}
2284 
2285 	/* release pending queue mutex across the network call */
2286 	mutex_exit(&isp->sess_queue_pending.mutex);
2287 
2288 	rval = iscsi_net->sendpdu(icp->conn_socket,
2289 	    (iscsi_hdr_t *)&istmh, NULL,
2290 	    ISCSI_CONN_TO_NET_DIGEST(icp));
2291 
2292 	return (rval);
2293 }
2294 
2295 
2296 /*
2297  * iscsi_tx_logout -
2298  *
2299  */
2300 static iscsi_status_t
2301 iscsi_tx_logout(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2302 {
2303 	iscsi_status_t		rval	= ISCSI_STATUS_SUCCESS;
2304 	iscsi_conn_t		*icp	= NULL;
2305 	iscsi_logout_hdr_t	ilh;
2306 
2307 	ASSERT(isp != NULL);
2308 	ASSERT(icmdp != NULL);
2309 	icp = icmdp->cmd_conn;
2310 	ASSERT(icp != NULL);
2311 
2312 	bzero(&ilh, sizeof (iscsi_logout_hdr_t));
2313 	ilh.opcode	= ISCSI_OP_LOGOUT_CMD | ISCSI_OP_IMMEDIATE;
2314 	ilh.flags	= ISCSI_FLAG_FINAL | ISCSI_LOGOUT_REASON_CLOSE_SESSION;
2315 	ilh.itt		= icmdp->cmd_itt;
2316 	ilh.cid		= icp->conn_cid;
2317 	mutex_enter(&isp->sess_cmdsn_mutex);
2318 	ilh.cmdsn	= htonl(isp->sess_cmdsn);
2319 	mutex_exit(&isp->sess_cmdsn_mutex);
2320 	ilh.expstatsn	= htonl(icp->conn_expstatsn);
2321 
2322 	/* release pending queue mutex across the network call */
2323 	mutex_exit(&isp->sess_queue_pending.mutex);
2324 
2325 	rval = iscsi_net->sendpdu(icp->conn_socket,
2326 	    (iscsi_hdr_t *)&ilh, NULL,
2327 	    ISCSI_CONN_TO_NET_DIGEST(icp));
2328 
2329 	return (rval);
2330 }
2331 
2332 /*
2333  * iscsi_tx_text - setup iSCSI text request header and send PDU with
2334  * data given in the buffer attached to the command.  For a single
2335  * text request, the target may need to send its response in multiple
2336  * text response.  In this case, empty text requests are sent after
2337  * each received response to notify the target the initiator is ready
2338  * for more response.  For the initial request, the data_len field in
2339  * the text specific portion of a command is set to the amount of data
2340  * the initiator wants to send as part of the request. If additional
2341  * empty text requests are required for long responses, the data_len
2342  * field is set to 0 by the iscsi_handle_text function.
2343  */
2344 static iscsi_status_t
2345 iscsi_tx_text(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2346 {
2347 	iscsi_status_t		rval	= ISCSI_STATUS_SUCCESS;
2348 	iscsi_conn_t		*icp	= NULL;
2349 	iscsi_text_hdr_t	ith;
2350 
2351 	ASSERT(isp != NULL);
2352 	ASSERT(icmdp != NULL);
2353 	icp = icmdp->cmd_conn;
2354 	ASSERT(icp != NULL);
2355 
2356 	bzero(&ith, sizeof (iscsi_text_hdr_t));
2357 	ith.opcode	= ISCSI_OP_TEXT_CMD;
2358 	ith.flags	= ISCSI_FLAG_FINAL;
2359 	hton24(ith.dlength, icmdp->cmd_un.text.data_len);
2360 	ith.itt		= icmdp->cmd_itt;
2361 	ith.ttt		= icmdp->cmd_un.text.ttt;
2362 	mutex_enter(&isp->sess_cmdsn_mutex);
2363 	ith.cmdsn	= htonl(isp->sess_cmdsn);
2364 	isp->sess_cmdsn++;
2365 	ith.expstatsn	= htonl(icp->conn_expstatsn);
2366 	mutex_exit(&isp->sess_cmdsn_mutex);
2367 	bcopy(icmdp->cmd_un.text.lun, ith.rsvd4, sizeof (ith.rsvd4));
2368 
2369 	/* release pending queue mutex across the network call */
2370 	mutex_exit(&isp->sess_queue_pending.mutex);
2371 
2372 	rval = iscsi_net->sendpdu(icp->conn_socket,
2373 	    (iscsi_hdr_t *)&ith, icmdp->cmd_un.text.buf,
2374 	    ISCSI_CONN_TO_NET_DIGEST(icp));
2375 
2376 	return (rval);
2377 }
2378 
2379 /*
2380  * +--------------------------------------------------------------------+
2381  * | End of protocol send routines					|
2382  * +--------------------------------------------------------------------+
2383  */
2384 
2385 /*
2386  * iscsi_handle_r2t - Create a R2T and put it into the pending queue.
2387  *
2388  * Since the rx thread can hold the pending mutex, the tx thread or wd
2389  * thread may not have chance to check the commands in the pending queue.
2390  * So if the previous R2T is still there, we will release the related
2391  * mutex and wait for its completion in case of deadlock.
2392  */
2393 static void
2394 iscsi_handle_r2t(iscsi_conn_t *icp, iscsi_cmd_t *icmdp,
2395     uint32_t offset, uint32_t length, uint32_t ttt)
2396 {
2397 	iscsi_sess_t	*isp		= NULL;
2398 	iscsi_cmd_t	*new_icmdp	= NULL;
2399 	int		owned		= 0;
2400 
2401 	ASSERT(icp != NULL);
2402 	isp = icp->conn_sess;
2403 	ASSERT(isp != NULL);
2404 
2405 	if (icmdp->cmd_un.scsi.r2t_icmdp != NULL) {
2406 		/*
2407 		 * Occasionally the tx thread doesn't have a chance to
2408 		 * send commands when we hold the pending mutex.
2409 		 * So we should mark this scsi command with more R2T
2410 		 * and release the mutex. Then wait for completion.
2411 		 */
2412 		icmdp->cmd_un.scsi.r2t_more = B_TRUE;
2413 
2414 		mutex_exit(&icmdp->cmd_mutex);
2415 		owned = mutex_owned(&icp->conn_queue_active.mutex);
2416 		if (owned != 0) {
2417 			mutex_exit(&icp->conn_queue_active.mutex);
2418 		}
2419 		mutex_exit(&isp->sess_queue_pending.mutex);
2420 
2421 		/*
2422 		 * the transmission from a previous r2t can be
2423 		 * slow to return; the array may have sent
2424 		 * another r2t at this point, so wait until
2425 		 * the first one finishes and signals us.
2426 		 */
2427 		mutex_enter(&icmdp->cmd_mutex);
2428 		while (icmdp->cmd_un.scsi.r2t_icmdp != NULL) {
2429 			ASSERT(icmdp->cmd_state != ISCSI_CMD_STATE_COMPLETED);
2430 			cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
2431 		}
2432 		mutex_exit(&icmdp->cmd_mutex);
2433 
2434 		mutex_enter(&isp->sess_queue_pending.mutex);
2435 		if (owned != 0) {
2436 			mutex_enter(&icp->conn_queue_active.mutex);
2437 		}
2438 		mutex_enter(&icmdp->cmd_mutex);
2439 	}
2440 
2441 	/*
2442 	 * try to create an R2T task to send it later.  If we can't,
2443 	 * we're screwed, and the command will eventually time out
2444 	 * and be retried by the SCSI layer.
2445 	 */
2446 	new_icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2447 	new_icmdp->cmd_type		= ISCSI_CMD_TYPE_R2T;
2448 	new_icmdp->cmd_un.r2t.icmdp	= icmdp;
2449 	new_icmdp->cmd_un.r2t.offset	= offset;
2450 	new_icmdp->cmd_un.r2t.length	= length;
2451 	new_icmdp->cmd_ttt		= ttt;
2452 	new_icmdp->cmd_itt		= icmdp->cmd_itt;
2453 	new_icmdp->cmd_lun		= icmdp->cmd_lun;
2454 	icmdp->cmd_un.scsi.r2t_icmdp	= new_icmdp;
2455 	icmdp->cmd_un.scsi.r2t_more	= B_FALSE;
2456 
2457 	/*
2458 	 * pending queue mutex is already held by the
2459 	 * tx_thread or rtt_rsp function.
2460 	 */
2461 	iscsi_cmd_state_machine(new_icmdp, ISCSI_CMD_EVENT_E1, isp);
2462 }
2463 
2464 
2465 /*
2466  * iscsi_handle_abort -
2467  *
2468  */
2469 void
2470 iscsi_handle_abort(void *arg)
2471 {
2472 	iscsi_sess_t	*isp		= NULL;
2473 	iscsi_cmd_t	*icmdp		= (iscsi_cmd_t *)arg;
2474 	iscsi_cmd_t	*new_icmdp;
2475 	iscsi_conn_t	*icp;
2476 
2477 	ASSERT(icmdp != NULL);
2478 	icp = icmdp->cmd_conn;
2479 	ASSERT(icp != NULL);
2480 	isp = icp->conn_sess;
2481 	ASSERT(isp != NULL);
2482 
2483 	/* there should only be one abort */
2484 	ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
2485 
2486 	new_icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2487 	new_icmdp->cmd_type		= ISCSI_CMD_TYPE_ABORT;
2488 	new_icmdp->cmd_lun		= icmdp->cmd_lun;
2489 	new_icmdp->cmd_un.abort.icmdp	= icmdp;
2490 	new_icmdp->cmd_conn		= icmdp->cmd_conn;
2491 	icmdp->cmd_un.scsi.abort_icmdp	= new_icmdp;
2492 
2493 	/* pending queue mutex is already held by timeout_checks */
2494 	iscsi_cmd_state_machine(new_icmdp, ISCSI_CMD_EVENT_E1, isp);
2495 }
2496 
2497 
2498 /*
2499  * iscsi_handle_nop -
2500  *
2501  */
2502 static void
2503 iscsi_handle_nop(iscsi_conn_t *icp, uint32_t itt, uint32_t ttt)
2504 {
2505 	iscsi_sess_t	*isp	= NULL;
2506 	iscsi_cmd_t	*icmdp	= NULL;
2507 
2508 	ASSERT(icp != NULL);
2509 	isp = icp->conn_sess;
2510 	ASSERT(isp != NULL);
2511 
2512 	icmdp = iscsi_cmd_alloc(icp, KM_NOSLEEP);
2513 	if (icmdp == NULL) {
2514 		return;
2515 	}
2516 
2517 	icmdp->cmd_type		= ISCSI_CMD_TYPE_NOP;
2518 	icmdp->cmd_itt		= itt;
2519 	icmdp->cmd_ttt		= ttt;
2520 	icmdp->cmd_lun		= NULL;
2521 	icp->conn_nop_lbolt	= ddi_get_lbolt();
2522 
2523 	iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2524 }
2525 
2526 /*
2527  * iscsi_handle_reset -
2528  *
2529  */
2530 iscsi_status_t
2531 iscsi_handle_reset(iscsi_sess_t *isp, int level, iscsi_lun_t *ilp)
2532 {
2533 	iscsi_status_t	rval	= ISCSI_STATUS_SUCCESS;
2534 	iscsi_conn_t	*icp;
2535 	iscsi_cmd_t	icmd;
2536 
2537 	ASSERT(isp != NULL);
2538 
2539 	bzero(&icmd, sizeof (iscsi_cmd_t));
2540 	icmd.cmd_sig		= ISCSI_SIG_CMD;
2541 	icmd.cmd_state		= ISCSI_CMD_STATE_FREE;
2542 	icmd.cmd_type		= ISCSI_CMD_TYPE_RESET;
2543 	icmd.cmd_lun		= ilp;
2544 	icmd.cmd_un.reset.level	= level;
2545 	icmd.cmd_result		= ISCSI_STATUS_SUCCESS;
2546 	icmd.cmd_completed	= B_FALSE;
2547 	mutex_init(&icmd.cmd_mutex, NULL, MUTEX_DRIVER, NULL);
2548 	cv_init(&icmd.cmd_completion, NULL, CV_DRIVER, NULL);
2549 	/*
2550 	 * If we received an IO and we are not in the
2551 	 * LOGGED_IN state we are in the process of
2552 	 * failing.  Just respond that we are BUSY.
2553 	 */
2554 	mutex_enter(&isp->sess_state_mutex);
2555 	if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
2556 		/* We aren't connected to the target fake success */
2557 		mutex_exit(&isp->sess_state_mutex);
2558 		return (ISCSI_STATUS_SUCCESS);
2559 	}
2560 
2561 	mutex_enter(&isp->sess_queue_pending.mutex);
2562 	iscsi_cmd_state_machine(&icmd, ISCSI_CMD_EVENT_E1, isp);
2563 	mutex_exit(&isp->sess_queue_pending.mutex);
2564 	mutex_exit(&isp->sess_state_mutex);
2565 
2566 	/* stall until completed */
2567 	mutex_enter(&icmd.cmd_mutex);
2568 	while (icmd.cmd_completed == B_FALSE) {
2569 		cv_wait(&icmd.cmd_completion, &icmd.cmd_mutex);
2570 	}
2571 	mutex_exit(&icmd.cmd_mutex);
2572 
2573 	/* copy rval */
2574 	rval = icmd.cmd_result;
2575 
2576 	if (rval == ISCSI_STATUS_SUCCESS) {
2577 		/*
2578 		 * Reset was successful.  We need to flush
2579 		 * all active IOs.
2580 		 */
2581 		rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
2582 		icp = isp->sess_conn_list;
2583 		while (icp != NULL) {
2584 			iscsi_cmd_t *t_icmdp = NULL;
2585 
2586 			mutex_enter(&icp->conn_queue_active.mutex);
2587 			t_icmdp = icp->conn_queue_active.head;
2588 			while (t_icmdp != NULL) {
2589 				iscsi_cmd_state_machine(t_icmdp,
2590 				    ISCSI_CMD_EVENT_E7, isp);
2591 				t_icmdp = icp->conn_queue_active.head;
2592 			}
2593 
2594 			mutex_exit(&icp->conn_queue_active.mutex);
2595 			icp = icp->conn_next;
2596 		}
2597 		rw_exit(&isp->sess_conn_list_rwlock);
2598 	}
2599 
2600 	/* clean up */
2601 	cv_destroy(&icmd.cmd_completion);
2602 	mutex_destroy(&icmd.cmd_mutex);
2603 
2604 	return (rval);
2605 }
2606 
2607 
2608 /*
2609  * iscsi_handle_logout - This function will issue a logout for
2610  * the session from a specific connection.
2611  */
2612 iscsi_status_t
2613 iscsi_handle_logout(iscsi_conn_t *icp)
2614 {
2615 	iscsi_sess_t	*isp;
2616 	iscsi_cmd_t	*icmdp;
2617 	int		rval;
2618 
2619 	ASSERT(icp != NULL);
2620 	isp = icp->conn_sess;
2621 	ASSERT(isp != NULL);
2622 	ASSERT(isp->sess_hba != NULL);
2623 
2624 	icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2625 	ASSERT(icmdp != NULL);
2626 	icmdp->cmd_type		= ISCSI_CMD_TYPE_LOGOUT;
2627 	icmdp->cmd_result	= ISCSI_STATUS_SUCCESS;
2628 	icmdp->cmd_completed	= B_FALSE;
2629 
2630 	mutex_enter(&isp->sess_queue_pending.mutex);
2631 	iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2632 	mutex_exit(&isp->sess_queue_pending.mutex);
2633 
2634 	/*
2635 	 * release connection state mutex to avoid a deadlock.  This
2636 	 * function is called from within the connection state
2637 	 * machine with the lock held.  When the logout response is
2638 	 * received another call to the connection state machine
2639 	 * occurs which causes the deadlock
2640 	 */
2641 	mutex_exit(&icp->conn_state_mutex);
2642 
2643 	/* stall until completed */
2644 	mutex_enter(&icmdp->cmd_mutex);
2645 	while (icmdp->cmd_completed == B_FALSE) {
2646 		cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
2647 	}
2648 	mutex_exit(&icmdp->cmd_mutex);
2649 	mutex_enter(&icp->conn_state_mutex);
2650 
2651 	/* copy rval */
2652 	rval = icmdp->cmd_result;
2653 
2654 	/*
2655 	 * another way to do this would be to send t17 unconditionally,
2656 	 * but then the _rx_ thread would get bumped out with a receive
2657 	 * error, and send another t17.
2658 	 */
2659 	if (rval != ISCSI_STATUS_SUCCESS) {
2660 		(void) iscsi_conn_state_machine(icp, ISCSI_CONN_EVENT_T17);
2661 	}
2662 
2663 	/* clean up */
2664 	iscsi_cmd_free(icmdp);
2665 
2666 	return (rval);
2667 }
2668 
2669 /*
2670  * iscsi_handle_text - main control function for iSCSI text requests.  This
2671  * function handles allocating the command, sending initial text request, and
2672  * handling long response sequence.
2673  * If a data overflow condition occurs, iscsi_handle_text continues to
2674  * receive responses until the all data has been recieved.  This allows
2675  * the full data length to be returned to the caller.
2676  */
2677 iscsi_status_t
2678 iscsi_handle_text(iscsi_conn_t *icp, char *buf, uint32_t buf_len,
2679     uint32_t data_len, uint32_t *rx_data_len)
2680 {
2681 	iscsi_sess_t	*isp;
2682 	iscsi_cmd_t	*icmdp;
2683 	iscsi_status_t	rval	= ISCSI_STATUS_SUCCESS;
2684 
2685 	ASSERT(icp != NULL);
2686 	ASSERT(buf != NULL);
2687 	ASSERT(rx_data_len != NULL);
2688 
2689 	isp = icp->conn_sess;
2690 	ASSERT(isp != NULL);
2691 
2692 	/*
2693 	 * Ensure data for text request command is not greater
2694 	 * than the negotiated maximum receive data seqment length.
2695 	 *
2696 	 * Although iSCSI allows for long text requests (multiple
2697 	 * pdus), this function places a restriction on text
2698 	 * requests to ensure it is handled by a single PDU.
2699 	 */
2700 	if (data_len > icp->conn_params.max_xmit_data_seg_len) {
2701 		return (ISCSI_STATUS_CMD_FAILED);
2702 	}
2703 
2704 	icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2705 	ASSERT(icmdp != NULL);
2706 
2707 	icmdp->cmd_type		= ISCSI_CMD_TYPE_TEXT;
2708 	icmdp->cmd_result	= ISCSI_STATUS_SUCCESS;
2709 	icmdp->cmd_misc_flags	&= ~ISCSI_CMD_MISCFLAG_FREE;
2710 	icmdp->cmd_completed	= B_FALSE;
2711 
2712 	icmdp->cmd_un.text.buf		= buf;
2713 	icmdp->cmd_un.text.buf_len	= buf_len;
2714 	icmdp->cmd_un.text.offset	= 0;
2715 	icmdp->cmd_un.text.data_len	= data_len;
2716 	icmdp->cmd_un.text.total_rx_len	= 0;
2717 	icmdp->cmd_un.text.ttt		= ISCSI_RSVD_TASK_TAG;
2718 	icmdp->cmd_un.text.stage	= ISCSI_CMD_TEXT_INITIAL_REQ;
2719 
2720 long_text_response:
2721 	mutex_enter(&isp->sess_state_mutex);
2722 	if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
2723 		iscsi_cmd_free(icmdp);
2724 		mutex_exit(&isp->sess_state_mutex);
2725 		return (ISCSI_STATUS_NO_CONN_LOGGED_IN);
2726 	}
2727 
2728 	mutex_enter(&isp->sess_queue_pending.mutex);
2729 	iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2730 	mutex_exit(&isp->sess_queue_pending.mutex);
2731 	mutex_exit(&isp->sess_state_mutex);
2732 
2733 	/* stall until completed */
2734 	mutex_enter(&icmdp->cmd_mutex);
2735 	while (icmdp->cmd_completed == B_FALSE) {
2736 		cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
2737 	}
2738 	mutex_exit(&icmdp->cmd_mutex);
2739 
2740 	/*
2741 	 * check if error occured.  If data overflow occured, continue on
2742 	 * to ensure we get all data so that the full data length can be
2743 	 * returned to the user
2744 	 */
2745 	if ((icmdp->cmd_result != ISCSI_STATUS_SUCCESS) &&
2746 	    (icmdp->cmd_result != ISCSI_STATUS_DATA_OVERFLOW)) {
2747 		cmn_err(CE_NOTE, "iscsi: SendTarget discovery failed (%d)",
2748 		    icmdp->cmd_result);
2749 		rval = icmdp->cmd_result;
2750 		iscsi_cmd_free(icmdp);
2751 		return (rval);
2752 	}
2753 
2754 	/* check if this was a partial text PDU  */
2755 	if (icmdp->cmd_un.text.stage != ISCSI_CMD_TEXT_FINAL_RSP) {
2756 		/*
2757 		 * If a paritial text rexponse received, send an empty
2758 		 * text request.  This follows the behaviour specified
2759 		 * in RFC3720 regarding long text responses.
2760 		 */
2761 		icmdp->cmd_misc_flags		&= ~ISCSI_CMD_MISCFLAG_FREE;
2762 		icmdp->cmd_completed		= B_FALSE;
2763 		icmdp->cmd_un.text.data_len	= 0;
2764 		icmdp->cmd_un.text.stage	= ISCSI_CMD_TEXT_CONTINUATION;
2765 		goto long_text_response;
2766 	}
2767 
2768 	/*
2769 	 * set total received data length.  If data overflow this would be
2770 	 * amount of data that would have been received if buffer large
2771 	 * enough.
2772 	 */
2773 	*rx_data_len = icmdp->cmd_un.text.total_rx_len;
2774 
2775 	/* copy rval */
2776 	rval = icmdp->cmd_result;
2777 
2778 	/* clean up  */
2779 	iscsi_cmd_free(icmdp);
2780 
2781 	return (rval);
2782 }
2783 
2784 /*
2785  * iscsi_handle_passthru - This function is used to send a uscsi_cmd
2786  * to a specific target lun.  This routine is used for internal purposes
2787  * during enumeration and via the ISCSI_USCSICMD IOCTL.  We restrict
2788  * the CDBs that can be issued to a target/lun to INQUIRY, REPORT_LUNS,
2789  * and READ_CAPACITY for security purposes.
2790  *
2791  * The logic here is broken into three phases.
2792  * 1) Allocate and initialize a pkt/icmdp
2793  * 2) Send the pkt/icmdp
2794  * 3) cv_wait for completion
2795  */
2796 iscsi_status_t
2797 iscsi_handle_passthru(iscsi_sess_t *isp, uint16_t lun, struct uscsi_cmd *ucmdp)
2798 {
2799 	iscsi_status_t		rval		= ISCSI_STATUS_SUCCESS;
2800 	iscsi_cmd_t		*icmdp		= NULL;
2801 	struct scsi_pkt		*pkt		= NULL;
2802 	struct buf		*bp		= NULL;
2803 	struct scsi_arq_status  *arqstat	= NULL;
2804 	int			rqlen		= SENSE_LENGTH;
2805 
2806 	ASSERT(isp != NULL);
2807 	ASSERT(ucmdp != NULL);
2808 
2809 	/*
2810 	 * If the caller didn't provide a sense buffer we need
2811 	 * to allocation one to get the scsi status.
2812 	 */
2813 	if (ucmdp->uscsi_rqlen > SENSE_LENGTH) {
2814 		rqlen = ucmdp->uscsi_rqlen;
2815 	}
2816 
2817 	/*
2818 	 * Step 1. Setup structs - KM_SLEEP will always succeed
2819 	 */
2820 	bp = kmem_zalloc(sizeof (struct buf), KM_SLEEP);
2821 	ASSERT(bp != NULL);
2822 	pkt = kmem_zalloc(sizeof (struct scsi_pkt), KM_SLEEP);
2823 	ASSERT(pkt != NULL);
2824 	icmdp = iscsi_cmd_alloc(NULL, KM_SLEEP);
2825 	ASSERT(icmdp != NULL);
2826 
2827 	/* setup bp structure */
2828 	bp->b_flags		= B_READ;
2829 	bp->b_bcount		= ucmdp->uscsi_buflen;
2830 	bp->b_un.b_addr		= ucmdp->uscsi_bufaddr;
2831 
2832 	/* setup scsi_pkt structure */
2833 	pkt->pkt_ha_private	= icmdp;
2834 	pkt->pkt_scbp		= kmem_zalloc(rqlen, KM_SLEEP);
2835 	pkt->pkt_cdbp		= kmem_zalloc(ucmdp->uscsi_cdblen, KM_SLEEP);
2836 	/* callback routine for passthru, will wake cv_wait */
2837 	pkt->pkt_comp		= iscsi_handle_passthru_callback;
2838 	pkt->pkt_time		= ucmdp->uscsi_timeout;
2839 
2840 	/* setup iscsi_cmd structure */
2841 	icmdp->cmd_lun			= NULL;
2842 	icmdp->cmd_type			= ISCSI_CMD_TYPE_SCSI;
2843 	icmdp->cmd_un.scsi.lun		= lun;
2844 	icmdp->cmd_un.scsi.pkt		= pkt;
2845 	icmdp->cmd_un.scsi.bp		= bp;
2846 	bcopy(ucmdp->uscsi_cdb, pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
2847 	icmdp->cmd_un.scsi.cmdlen	= ucmdp->uscsi_cdblen;
2848 	icmdp->cmd_un.scsi.statuslen	= rqlen;
2849 	icmdp->cmd_crc_error_seen	= B_FALSE;
2850 	icmdp->cmd_completed		= B_FALSE;
2851 	icmdp->cmd_result		= ISCSI_STATUS_SUCCESS;
2852 
2853 	/*
2854 	 * Step 2. Push IO onto pending queue.  If we aren't in
2855 	 * FULL_FEATURE we need to fail the IO.
2856 	 */
2857 	mutex_enter(&isp->sess_state_mutex);
2858 	if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
2859 		mutex_exit(&isp->sess_state_mutex);
2860 
2861 		iscsi_cmd_free(icmdp);
2862 		kmem_free(pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
2863 		kmem_free(pkt->pkt_scbp, rqlen);
2864 		kmem_free(pkt, sizeof (struct scsi_pkt));
2865 		kmem_free(bp, sizeof (struct buf));
2866 
2867 		return (ISCSI_STATUS_CMD_FAILED);
2868 	}
2869 
2870 	mutex_enter(&isp->sess_queue_pending.mutex);
2871 	iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2872 	mutex_exit(&isp->sess_queue_pending.mutex);
2873 	mutex_exit(&isp->sess_state_mutex);
2874 
2875 	/*
2876 	 * Step 3. Wait on cv_wait for completion routine
2877 	 */
2878 	mutex_enter(&icmdp->cmd_mutex);
2879 	while (icmdp->cmd_completed == B_FALSE) {
2880 		cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
2881 	}
2882 	mutex_exit(&icmdp->cmd_mutex);
2883 
2884 	/* copy rval */
2885 	rval = icmdp->cmd_result;
2886 
2887 	ucmdp->uscsi_resid = pkt->pkt_resid;
2888 
2889 	/* update scsi status */
2890 	arqstat = (struct scsi_arq_status *)pkt->pkt_scbp;
2891 	ucmdp->uscsi_status = ((char *)&arqstat->sts_status)[0];
2892 
2893 	/* copy request sense buffers if caller gave space */
2894 	if ((ucmdp->uscsi_rqlen > 0) &&
2895 	    (ucmdp->uscsi_rqbuf != NULL)) {
2896 		bcopy(arqstat, ucmdp->uscsi_rqbuf,
2897 		    MIN(sizeof (struct scsi_arq_status), rqlen));
2898 	}
2899 
2900 	/* clean up */
2901 	iscsi_cmd_free(icmdp);
2902 	kmem_free(pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
2903 	kmem_free(pkt->pkt_scbp, rqlen);
2904 	kmem_free(pkt, sizeof (struct scsi_pkt));
2905 	kmem_free(bp, sizeof (struct buf));
2906 
2907 	return (rval);
2908 }
2909 
2910 
2911 /*
2912  * iscsi_handle_passthru_callback -
2913  *
2914  */
2915 static void
2916 iscsi_handle_passthru_callback(struct scsi_pkt *pkt)
2917 {
2918 	iscsi_cmd_t		*icmdp  = NULL;
2919 
2920 	ASSERT(pkt != NULL);
2921 	icmdp = (iscsi_cmd_t *)pkt->pkt_ha_private;
2922 	ASSERT(icmdp != NULL);
2923 
2924 	mutex_enter(&icmdp->cmd_mutex);
2925 	icmdp->cmd_completed    = B_TRUE;
2926 	icmdp->cmd_result	= ISCSI_STATUS_SUCCESS;
2927 	cv_broadcast(&icmdp->cmd_completion);
2928 	mutex_exit(&icmdp->cmd_mutex);
2929 
2930 }
2931 
2932 /*
2933  * +--------------------------------------------------------------------+
2934  * | Beginning of completion routines					|
2935  * +--------------------------------------------------------------------+
2936  */
2937 
2938 /*
2939  * iscsi_ic_thread -
2940  */
2941 void
2942 iscsi_ic_thread(iscsi_thread_t *thread, void *arg)
2943 {
2944 	iscsi_sess_t	*isp = (iscsi_sess_t *)arg;
2945 	int		ret;
2946 	iscsi_queue_t	q;
2947 	iscsi_cmd_t	*icmdp;
2948 	iscsi_cmd_t	*next_icmdp;
2949 
2950 	ASSERT(isp != NULL);
2951 	ASSERT(thread != NULL);
2952 	ASSERT(thread->signature == SIG_ISCSI_THREAD);
2953 
2954 	for (;;) {
2955 
2956 		/*
2957 		 * We wait till iodone or somebody else wakes us up.
2958 		 */
2959 		ret = iscsi_thread_wait(thread, -1);
2960 
2961 		/*
2962 		 * The value should never be negative since we never timeout.
2963 		 */
2964 		ASSERT(ret >= 0);
2965 
2966 		q.count = 0;
2967 		q.head  = NULL;
2968 		q.tail  = NULL;
2969 		mutex_enter(&isp->sess_queue_completion.mutex);
2970 		icmdp = isp->sess_queue_completion.head;
2971 		while (icmdp != NULL) {
2972 			next_icmdp = icmdp->cmd_next;
2973 			mutex_enter(&icmdp->cmd_mutex);
2974 			/*
2975 			 * check if the associated r2t/abort has finished
2976 			 * yet, and make sure this command has no R2T
2977 			 * to handle. If not, don't complete this command.
2978 			 */
2979 			if ((icmdp->cmd_un.scsi.r2t_icmdp == NULL) &&
2980 			    (icmdp->cmd_un.scsi.abort_icmdp == NULL) &&
2981 			    (icmdp->cmd_un.scsi.r2t_more == B_FALSE)) {
2982 				mutex_exit(&icmdp->cmd_mutex);
2983 				(void) iscsi_dequeue_cmd(&isp->
2984 				    sess_queue_completion.head,
2985 				    &isp->sess_queue_completion.tail,
2986 				    icmdp);
2987 				--isp->sess_queue_completion.count;
2988 				iscsi_enqueue_cmd_head(&q.head,
2989 				    &q.tail, icmdp);
2990 			} else
2991 				mutex_exit(&icmdp->cmd_mutex);
2992 			icmdp = next_icmdp;
2993 		}
2994 		mutex_exit(&isp->sess_queue_completion.mutex);
2995 		icmdp = q.head;
2996 		while (icmdp != NULL) {
2997 			next_icmdp = icmdp->cmd_next;
2998 			iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E8, isp);
2999 			icmdp = next_icmdp;
3000 		}
3001 
3002 		if (ret > 0)
3003 			/* Somebody woke us up to work */
3004 			continue;
3005 		else
3006 			/*
3007 			 * Somebody woke us up to kill ourselves. We will
3008 			 * make sure, however that the completion queue is
3009 			 * empty before leaving.  After we've done that it
3010 			 * is the originator of the signal that has to make
3011 			 * sure no other SCSI command is posted.
3012 			 */
3013 			break;
3014 	}
3015 
3016 }
3017 
3018 /*
3019  * iscsi_iodone -
3020  *
3021  */
3022 void
3023 iscsi_iodone(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
3024 {
3025 	struct scsi_pkt		*pkt	= NULL;
3026 	struct buf		*bp	= icmdp->cmd_un.scsi.bp;
3027 
3028 	ASSERT(isp != NULL);
3029 	ASSERT(icmdp != NULL);
3030 	pkt = icmdp->cmd_un.scsi.pkt;
3031 	ASSERT(pkt != NULL);
3032 
3033 	ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
3034 	ASSERT(icmdp->cmd_un.scsi.r2t_icmdp == NULL);
3035 	if (pkt->pkt_reason == CMD_CMPLT) {
3036 		if (bp) {
3037 			if (bp->b_flags & B_READ) {
3038 				KSTAT_SESS_RX_IO_DONE(isp, bp->b_bcount);
3039 			} else {
3040 				KSTAT_SESS_TX_IO_DONE(isp, bp->b_bcount);
3041 			}
3042 		}
3043 	}
3044 
3045 	if (pkt->pkt_flags & FLAG_NOINTR) {
3046 		cv_broadcast(&icmdp->cmd_completion);
3047 		mutex_exit(&icmdp->cmd_mutex);
3048 	} else {
3049 		/*
3050 		 * Release mutex.  As soon as callback is
3051 		 * issued the caller may destroy the command.
3052 		 */
3053 		mutex_exit(&icmdp->cmd_mutex);
3054 		/*
3055 		 * We can't just directly call the pk_comp routine.  In
3056 		 * many error cases the target driver will use the calling
3057 		 * thread to re-drive error handling (reset, retries...)
3058 		 * back into the hba driver (iscsi).  If the target redrives
3059 		 * a reset back into the iscsi driver off this thead we have
3060 		 * a chance of deadlocking. So instead use the io completion
3061 		 * thread.
3062 		 */
3063 		(*icmdp->cmd_un.scsi.pkt->pkt_comp)(icmdp->cmd_un.scsi.pkt);
3064 	}
3065 }
3066 
3067 /*
3068  * +--------------------------------------------------------------------+
3069  * | End of completion routines						|
3070  * +--------------------------------------------------------------------+
3071  */
3072 
3073 /*
3074  * +--------------------------------------------------------------------+
3075  * | Beginning of watchdog routines					|
3076  * +--------------------------------------------------------------------+
3077  */
3078 
3079 /*
3080  * iscsi_watchdog_thread -
3081  *
3082  */
3083 void
3084 iscsi_wd_thread(iscsi_thread_t *thread, void *arg)
3085 {
3086 	iscsi_sess_t	*isp = (iscsi_sess_t *)arg;
3087 	int		rc = 1;
3088 
3089 	ASSERT(isp != NULL);
3090 
3091 	while (rc != NULL) {
3092 
3093 		iscsi_timeout_checks(isp);
3094 		iscsi_nop_checks(isp);
3095 
3096 		rc = iscsi_thread_wait(thread, SEC_TO_TICK(1));
3097 	}
3098 }
3099 
3100 /*
3101  * iscsi_timeout_checks -
3102  *
3103  */
3104 static void
3105 iscsi_timeout_checks(iscsi_sess_t *isp)
3106 {
3107 	clock_t		now = ddi_get_lbolt();
3108 	iscsi_cmd_t	*icmdp, *nicmdp;
3109 	iscsi_conn_t	*icp;
3110 
3111 	ASSERT(isp != NULL);
3112 
3113 	/* PENDING */
3114 	mutex_enter(&isp->sess_state_mutex);
3115 	mutex_enter(&isp->sess_queue_pending.mutex);
3116 	for (icmdp = isp->sess_queue_pending.head;
3117 	    icmdp; icmdp = nicmdp) {
3118 		nicmdp = icmdp->cmd_next;
3119 
3120 		/* Skip entries with no timeout */
3121 		if (icmdp->cmd_lbolt_timeout == 0)
3122 			continue;
3123 
3124 		/*
3125 		 * Skip pending queue entries for cmd_type values that depend
3126 		 * on having an open cmdsn window for successfull transition
3127 		 * from pending to the active (i.e. ones that depend on
3128 		 * sess_cmdsn .vs. sess_maxcmdsn). For them, the timer starts
3129 		 * when they are successfully moved to the active queue by
3130 		 * iscsi_cmd_state_pending() code.
3131 		 */
3132 		/*
3133 		 * If the cmd is stuck, at least give it a chance
3134 		 * to timeout
3135 		 */
3136 		if (((icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) ||
3137 		    (icmdp->cmd_type == ISCSI_CMD_TYPE_TEXT)) &&
3138 		    !(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_STUCK))
3139 			continue;
3140 
3141 		/* Skip if timeout still in the future */
3142 		if (now <= icmdp->cmd_lbolt_timeout)
3143 			continue;
3144 
3145 		/* timeout */
3146 		iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E6, isp);
3147 	}
3148 	mutex_exit(&isp->sess_queue_pending.mutex);
3149 	mutex_exit(&isp->sess_state_mutex);
3150 
3151 	rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
3152 	icp = isp->sess_conn_list;
3153 	while (icp != NULL) {
3154 
3155 		/* ACTIVE */
3156 		mutex_enter(&icp->conn_state_mutex);
3157 		mutex_enter(&isp->sess_queue_pending.mutex);
3158 		mutex_enter(&icp->conn_queue_active.mutex);
3159 		for (icmdp = icp->conn_queue_active.head;
3160 		    icmdp; icmdp = nicmdp) {
3161 			nicmdp = icmdp->cmd_next;
3162 
3163 			/* Skip entries with no timeout */
3164 			if (icmdp->cmd_lbolt_timeout == 0)
3165 				continue;
3166 
3167 			/* Skip if command is not active */
3168 			if (icmdp->cmd_state != ISCSI_CMD_STATE_ACTIVE)
3169 				continue;
3170 
3171 			/* Skip if timeout still in the future */
3172 			if (now <= icmdp->cmd_lbolt_timeout)
3173 				continue;
3174 
3175 			/* timeout */
3176 			iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E6, isp);
3177 		}
3178 		mutex_exit(&icp->conn_queue_active.mutex);
3179 		mutex_exit(&isp->sess_queue_pending.mutex);
3180 		mutex_exit(&icp->conn_state_mutex);
3181 
3182 		icp = icp->conn_next;
3183 	}
3184 	rw_exit(&isp->sess_conn_list_rwlock);
3185 }
3186 
3187 /*
3188  * iscsi_nop_checks - sends a NOP on idle connections
3189  *
3190  * This function walks the connections on a session and
3191  * issues NOPs on those connections that are in FULL
3192  * FEATURE mode and have not received data for the
3193  * time period specified by iscsi_nop_delay (global).
3194  */
3195 static void
3196 iscsi_nop_checks(iscsi_sess_t *isp)
3197 {
3198 	iscsi_conn_t	*icp;
3199 
3200 	ASSERT(isp != NULL);
3201 
3202 	if (isp->sess_type == ISCSI_SESS_TYPE_DISCOVERY) {
3203 		return;
3204 	}
3205 
3206 	rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
3207 	icp = isp->sess_conn_act;
3208 	if (icp != NULL) {
3209 
3210 		mutex_enter(&icp->conn_state_mutex);
3211 		if ((ISCSI_CONN_STATE_FULL_FEATURE(icp->conn_state)) &&
3212 		    (ddi_get_lbolt() > isp->sess_conn_act->conn_rx_lbolt +
3213 		    SEC_TO_TICK(iscsi_nop_delay)) && (ddi_get_lbolt() >
3214 		    isp->sess_conn_act->conn_nop_lbolt +
3215 		    SEC_TO_TICK(iscsi_nop_delay))) {
3216 
3217 			/*
3218 			 * We haven't received anything from the
3219 			 * target is a defined period of time,
3220 			 * send NOP to see if the target is alive.
3221 			 */
3222 			mutex_enter(&isp->sess_queue_pending.mutex);
3223 			iscsi_handle_nop(isp->sess_conn_act,
3224 			    0, ISCSI_RSVD_TASK_TAG);
3225 			mutex_exit(&isp->sess_queue_pending.mutex);
3226 		}
3227 		mutex_exit(&icp->conn_state_mutex);
3228 
3229 		icp = icp->conn_next;
3230 	}
3231 	rw_exit(&isp->sess_conn_list_rwlock);
3232 }
3233 
3234 /*
3235  * +--------------------------------------------------------------------+
3236  * | End of wd routines						|
3237  * +--------------------------------------------------------------------+
3238  */
3239