xref: /netbsd-src/sys/dev/iscsi/iscsi_send.c (revision a24efa7dea9f1f56c3bdb15a927d3516792ace1c)
1 /*	$NetBSD: iscsi_send.c,v 1.30 2016/06/05 13:54:28 mlelstv Exp $	*/
2 
3 /*-
4  * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Wasabi Systems, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 #include "iscsi_globals.h"
32 
33 #include <sys/file.h>
34 #include <sys/filedesc.h>
35 #include <sys/socket.h>
36 #include <sys/socketvar.h>
37 #include <sys/atomic.h>
38 
39 /*#define LUN_1  1 */
40 
41 /*****************************************************************************/
42 
43 /*
44  * my_soo_write:
45  *    Replacement for soo_write with flag handling.
46  *
47  *    Parameter:
48  *          conn     The connection
49  *          u        The uio descriptor
50  *
51  *    Returns:    0 on success, else EIO.
52  */
53 
54 STATIC int
55 my_soo_write(connection_t *conn, struct uio *u)
56 {
57 	struct socket *so = conn->sock->f_socket;
58 	int ret;
59 #ifdef ISCSI_DEBUG
60 	size_t resid = u->uio_resid;
61 #endif
62 
63 	KASSERT(u->uio_resid != 0);
64 
65 	ret = (*so->so_send)(so, NULL, u, NULL, NULL, 0, conn->threadobj);
66 
67 	DEB(99, ("soo_write done: len = %zu\n", u->uio_resid));
68 
69 	if (ret != 0 || u->uio_resid) {
70 		DEBC(conn, 0, ("Write failed sock %p (ret: %d, req: %zu, resid: %zu)\n",
71 			conn->sock, ret, resid, u->uio_resid));
72 		handle_connection_error(conn, ISCSI_STATUS_SOCKET_ERROR, NO_LOGOUT);
73 		return EIO;
74 	}
75 	return 0;
76 }
77 
78 /*****************************************************************************/
79 
80 /*
81  * assign_connection:
82  *    This function returns the connection to use for the next transaction.
83  *
84  *    Parameter:  The session
85  *
86  *    Returns:    The connection
87  */
88 
89 connection_t *
90 assign_connection(session_t *session, bool waitok)
91 {
92 	connection_t *conn, *next;
93 
94 	mutex_enter(&session->lock);
95 	do {
96 		if ((conn = session->mru_connection) == NULL) {
97 			mutex_exit(&session->lock);
98 			return NULL;
99 		}
100 		next = conn;
101 		do {
102 			next = TAILQ_NEXT(next, connections);
103 			if (next == NULL) {
104 				next = TAILQ_FIRST(&session->conn_list);
105 			}
106 		} while (next != NULL && next != conn &&
107 				 next->state != ST_FULL_FEATURE);
108 
109 		if (next->state != ST_FULL_FEATURE) {
110 			if (waitok) {
111 				cv_wait(&session->sess_cv, &session->lock);
112 				next = TAILQ_FIRST(&session->conn_list);
113 			} else {
114 				mutex_exit(&session->lock);
115 				return NULL;
116 			}
117 		} else {
118 			session->mru_connection = next;
119 		}
120 	} while (next != NULL && next->state != ST_FULL_FEATURE);
121 	mutex_exit(&session->lock);
122 
123 	return next;
124 }
125 
126 
127 /*
128  * reassign_tasks:
129  *    Reassign pending commands to one of the still existing connections
130  *    of a session.
131  *
132  *    Parameter:
133  *          oldconn		The terminating connection
134  */
135 
136 STATIC void
137 reassign_tasks(connection_t *oldconn)
138 {
139 	session_t *sess = oldconn->session;
140 	connection_t *conn;
141 	ccb_t *ccb;
142 	pdu_t *pdu = NULL;
143 	pdu_t *opdu;
144 	int no_tm = 1;
145 	int rc = 1;
146 	uint32_t sn;
147 
148 	if ((conn = assign_connection(sess, FALSE)) == NULL) {
149 		DEB(1, ("Reassign_tasks of Session %d, connection %d failed, "
150 			    "no active connection\n",
151 			    sess->id, oldconn->id));
152 		/* XXX here we need to abort the waiting CCBs */
153 		return;
154 	}
155 
156 	if (sess->ErrorRecoveryLevel >= 2) {
157 		if (oldconn->loggedout == NOT_LOGGED_OUT) {
158 			oldconn->loggedout = LOGOUT_SENT;
159 			no_tm = send_logout(conn, oldconn, RECOVER_CONNECTION, TRUE);
160 			oldconn->loggedout = (rc) ? LOGOUT_FAILED : LOGOUT_SUCCESS;
161 			if (!oldconn->Time2Retain) {
162 				DEBC(conn, 1, ("Time2Retain is zero, setting no_tm\n"));
163 				no_tm = 1;
164 			}
165 		} else if (oldconn->loggedout == LOGOUT_SUCCESS) {
166 			no_tm = 0;
167 		}
168 		if (!no_tm && oldconn->Time2Wait) {
169 			DEBC(conn, 1, ("Time2Wait=%d, hz=%d, waiting...\n",
170 						   oldconn->Time2Wait, hz));
171 			kpause("Time2Wait", false, oldconn->Time2Wait * hz, NULL);
172 		}
173 	}
174 
175 	DEBC(conn, 1, ("Reassign_tasks: Session %d, conn %d -> conn %d, no_tm=%d\n",
176 		sess->id, oldconn->id, conn->id, no_tm));
177 
178 
179 	/* XXX reassign waiting CCBs to new connection */
180 
181 	while ((ccb = TAILQ_FIRST(&oldconn->ccbs_waiting)) != NULL) {
182 		/* Copy PDU contents (PDUs are bound to connection) */
183 		if ((pdu = get_pdu(conn, TRUE)) == NULL) {
184 			break;
185 		}
186 
187 		/* adjust CCB and clone PDU for new connection */
188 		TAILQ_REMOVE(&oldconn->ccbs_waiting, ccb, chain);
189 
190 		opdu = ccb->pdu_waiting;
191 		KASSERT((opdu->flags & PDUF_INQUEUE) == 0);
192 
193 		*pdu = *opdu;
194 
195 		/* restore overwritten back ptr */
196 		pdu->connection = conn;
197 
198 		/* fixup saved UIO and IOVEC (regular one will be overwritten anyway) */
199 		pdu->save_uio.uio_iov = pdu->io_vec;
200 		pdu->save_iovec [0].iov_base = &pdu->pdu;
201 
202 		if (conn->DataDigest && pdu->save_uio.uio_iovcnt > 1) {
203 			if (pdu->save_iovec [2].iov_base == NULL) {
204 				pdu->save_iovec [2].iov_base = &pdu->data_digest;
205 				pdu->save_uio.uio_iovcnt = 3;
206 			} else {
207 				pdu->save_iovec [3].iov_base = &pdu->data_digest;
208 				pdu->save_uio.uio_iovcnt = 4;
209 			}
210 		}
211 		pdu->save_iovec [0].iov_len =
212 			(conn->HeaderDigest) ? BHS_SIZE + 4 : BHS_SIZE;
213 
214 		/* link new PDU into old CCB */
215 		ccb->pdu_waiting = pdu;
216 		/* link new CCB into new connection */
217 		ccb->connection = conn;
218 		/* reset timeouts */
219 		ccb->num_timeouts = 0;
220 
221 		/* fixup reference counts */
222 		oldconn->usecount--;
223 		atomic_inc_uint(&conn->usecount);
224 
225 		DEBC(conn, 1, ("CCB %p: Copied PDU %p to %p\n",
226 					   ccb, opdu, pdu));
227 
228 		/* kill temp pointer that is now referenced by the new PDU */
229 		opdu->temp_data = NULL;
230 
231 		/* and free the old PDU */
232 		free_pdu(opdu);
233 
234 		/* put ready CCB into waiting list of new connection */
235 		suspend_ccb(ccb, TRUE);
236 	}
237 
238 	if (pdu == NULL) {
239 		DEBC(conn, 1, ("Error while copying PDUs in reassign_tasks!\n"));
240 		/* give up recovering, the other connection is screwed up as well... */
241 		while ((ccb = TAILQ_FIRST(&oldconn->ccbs_waiting)) != NULL) {
242 			wake_ccb(ccb, oldconn->terminating);
243 		}
244 		/* XXX some CCBs might have been moved to new connection, but how is the
245 		 * new connection handled or killed ? */
246 		return;
247 	}
248 
249 	TAILQ_FOREACH(ccb, &conn->ccbs_waiting, chain) {
250 		if (!no_tm) {
251 			rc = send_task_management(conn, ccb, NULL, TASK_REASSIGN);
252 		}
253 		/* if we get an error on reassign, restart the original request */
254 		if (no_tm || rc) {
255 			mutex_enter(&sess->lock);
256 			if (ccb->CmdSN < sess->ExpCmdSN) {
257 				pdu = ccb->pdu_waiting;
258 				sn = get_sernum(sess, !(pdu->pdu.Opcode & OP_IMMEDIATE));
259 
260 				/* update CmdSN */
261 				DEBC(conn, 1, ("Resend Updating CmdSN - old %d, new %d\n",
262 					   ccb->CmdSN, sn));
263 				ccb->CmdSN = sn;
264 				pdu->pdu.p.command.CmdSN = htonl(ccb->CmdSN);
265 			}
266 			mutex_exit(&sess->lock);
267 			resend_pdu(ccb);
268 		} else {
269 			ccb_timeout_start(ccb, COMMAND_TIMEOUT);
270 		}
271 		DEBC(conn, 1, ("Reassign ccb %p, no_tm=%d, rc=%d\n",
272 					   ccb, no_tm, rc));
273 	}
274 }
275 
276 
277 /*
278  * iscsi_send_thread:
279  *    This thread services the send queue, writing the PDUs to the socket.
280  *    It also handles the cleanup when the connection is terminated.
281  *
282  *    Parameter:
283  *          par		The connection this thread services
284  */
285 
286 void
287 iscsi_send_thread(void *par)
288 {
289 	connection_t *conn = (connection_t *) par;
290 	session_t *sess;
291 	ccb_t *ccb, *nccb;
292 	pdu_t *pdu;
293 	struct file *fp;
294 	pdu_disp_t pdisp;
295 
296 	sess = conn->session;
297 	/* so cleanup thread knows there's someone left */
298 	iscsi_num_send_threads++;
299 
300 	do {
301 		mutex_enter(&conn->lock);
302 		while (!conn->terminating) {
303 			while (!conn->terminating &&
304 				(pdu = TAILQ_FIRST(&conn->pdus_to_send)) != NULL) {
305 				TAILQ_REMOVE(&conn->pdus_to_send, pdu, send_chain);
306 				pdu->flags &= ~PDUF_INQUEUE;
307 				mutex_exit(&conn->lock);
308 
309 				/* update ExpStatSN here to avoid discontinuities */
310 				/* and delays in updating target */
311 				pdu->pdu.p.command.ExpStatSN = htonl(conn->StatSN_buf.ExpSN);
312 
313 				if (conn->HeaderDigest)
314 					pdu->pdu.HeaderDigest = gen_digest(&pdu->pdu, BHS_SIZE);
315 				DEBC(conn, 99, ("Transmitting PDU CmdSN = %u\n",
316 				                ntohl(pdu->pdu.p.command.CmdSN)));
317 				my_soo_write(conn, &pdu->uio);
318 
319 				mutex_enter(&conn->lock);
320 				pdisp = pdu->disp;
321 				if (pdisp <= PDUDISP_FREE)
322 					pdu->disp = PDUDISP_UNUSED;
323 				else
324 					pdu->flags &= ~PDUF_BUSY;
325 				mutex_exit(&conn->lock);
326 
327 				if (pdisp <= PDUDISP_FREE)
328 					free_pdu(pdu);
329 
330 				mutex_enter(&conn->lock);
331 			}
332 
333 			if (!conn->terminating)
334 				cv_wait(&conn->conn_cv, &conn->lock);
335 		}
336 		mutex_exit(&conn->lock);
337 
338 		/* ------------------------------------------------------------------------
339 		 *    Here this thread takes over cleanup of the terminating connection.
340 		 * ------------------------------------------------------------------------
341 		 */
342 		connection_timeout_stop(conn);
343 		conn->idle_timeout_val = CONNECTION_IDLE_TIMEOUT;
344 
345 		fp = conn->sock;
346 
347 		/*
348 		 * We shutdown the socket here to force the receive
349 		 * thread to wake up
350 		 */
351 		DEBC(conn, 1, ("Closing Socket %p\n", conn->sock));
352 		solock(fp->f_socket);
353 		soshutdown(fp->f_socket, SHUT_RDWR);
354 		sounlock(fp->f_socket);
355 
356 		/* wake up any non-reassignable waiting CCBs */
357 		TAILQ_FOREACH_SAFE(ccb, &conn->ccbs_waiting, chain, nccb) {
358 			if (!(ccb->flags & CCBF_REASSIGN) || ccb->pdu_waiting == NULL) {
359 				DEBC(conn, 1, ("Terminating CCB %p (t=%p)\n",
360 					ccb,&ccb->timeout));
361 				wake_ccb(ccb, conn->terminating);
362 			} else {
363 				ccb_timeout_stop(ccb);
364 				ccb->num_timeouts = 0;
365 			}
366 		}
367 
368 		/* clean out anything left in send queue */
369 		mutex_enter(&conn->lock);
370 		while ((pdu = TAILQ_FIRST(&conn->pdus_to_send)) != NULL) {
371 			TAILQ_REMOVE(&conn->pdus_to_send, pdu, send_chain);
372 			pdu->flags &= ~(PDUF_INQUEUE | PDUF_BUSY);
373 			mutex_exit(&conn->lock);
374 			/* if it's not attached to a waiting CCB, free it */
375 			if (pdu->owner == NULL ||
376 			    pdu->owner->pdu_waiting != pdu) {
377 				free_pdu(pdu);
378 			}
379 			mutex_enter(&conn->lock);
380 		}
381 		mutex_exit(&conn->lock);
382 
383 		/* If there's another connection available, transfer pending tasks */
384 		if (sess->active_connections &&
385 			TAILQ_FIRST(&conn->ccbs_waiting) != NULL) {
386 
387 			reassign_tasks(conn);
388 		} else if (!conn->destroy && conn->Time2Wait) {
389 			DEBC(conn, 1, ("Time2Wait\n"));
390 			kpause("Time2Wait", false, conn->Time2Wait * hz, NULL);
391 			DEBC(conn, 1, ("Time2Wait\n"));
392 		}
393 		/* notify event handlers of connection shutdown */
394 		DEBC(conn, 1, ("%s\n", (conn->destroy) ? "TERMINATED" : "RECOVER"));
395 		add_event((conn->destroy) ? ISCSI_CONNECTION_TERMINATED
396 								  : ISCSI_RECOVER_CONNECTION,
397 				  sess->id, conn->id, conn->terminating);
398 
399 		DEBC(conn, 1, ("Waiting for conn_idle\n"));
400 		mutex_enter(&conn->lock);
401 		if (!conn->destroy)
402 			cv_timedwait(&conn->idle_cv, &conn->lock, CONNECTION_IDLE_TIMEOUT);
403 		mutex_exit(&conn->lock);
404 		DEBC(conn, 1, ("Waited for conn_idle, destroy = %d\n", conn->destroy));
405 
406 	} while (!conn->destroy);
407 
408 	/* wake up anyone waiting for a PDU */
409 	cv_broadcast(&conn->conn_cv);
410 
411 	/* wake up any waiting CCBs */
412 	while ((ccb = TAILQ_FIRST(&conn->ccbs_waiting)) != NULL) {
413 		KASSERT(ccb->disp >= CCBDISP_NOWAIT);
414 		wake_ccb(ccb, conn->terminating);
415 		/* NOTE: wake_ccb will remove the CCB from the queue */
416 	}
417 
418 	if (conn->in_session) {
419 		conn->in_session = FALSE;
420 		TAILQ_REMOVE(&sess->conn_list, conn, connections);
421 		sess->mru_connection = TAILQ_FIRST(&sess->conn_list);
422 	}
423 
424 	add_connection_cleanup(conn);
425 
426 	conn->sendproc = NULL;
427 	DEBC(conn, 1, ("Send thread exits\n"));
428 	iscsi_num_send_threads--;
429 	kthread_exit(0);
430 }
431 
432 
433 /*
434  * send_pdu:
435  *    Enqueue a PDU to be sent, and handle its disposition as well as
436  *    the disposition of its associated CCB.
437  *
438  *    Parameter:
439  *          ccb      The associated CCB. May be NULL if cdisp is CCBDISP_NOWAIT
440  *                   and pdisp is not PDUDISP_WAIT
441  *          cdisp    The CCB's disposition
442  *          pdu      The PDU
443  *          pdisp    The PDU's disposition
444  */
445 
446 STATIC void
447 send_pdu(ccb_t *ccb, pdu_t *pdu, ccb_disp_t cdisp, pdu_disp_t pdisp)
448 {
449 	connection_t *conn = pdu->connection;
450 	ccb_disp_t prev_cdisp = 0;
451 
452 	if (ccb != NULL) {
453 		prev_cdisp = ccb->disp;
454 		pdu->pdu.InitiatorTaskTag = ccb->ITT;
455 		pdu->owner = ccb;
456 		if (cdisp != CCBDISP_NOWAIT)
457 			ccb->disp = cdisp;
458 	}
459 
460 	pdu->disp = pdisp;
461 
462 	DEBC(conn, 10, ("Send_pdu: ccb=%p, pcd=%d, cdsp=%d, pdu=%p, pdsp=%d\n",
463 			ccb, prev_cdisp, cdisp, pdu, pdisp));
464 
465 	mutex_enter(&conn->lock);
466 	if (pdisp == PDUDISP_WAIT) {
467 		ccb->pdu_waiting = pdu;
468 
469 		/* save UIO and IOVEC for retransmit */
470 		pdu->save_uio = pdu->uio;
471 		memcpy(pdu->save_iovec, pdu->io_vec, sizeof(pdu->save_iovec));
472 
473 		pdu->flags |= PDUF_BUSY;
474 	}
475 	/* Enqueue for sending */
476 	pdu->flags |= PDUF_INQUEUE;
477 
478 	if (pdu->flags & PDUF_PRIORITY)
479 		TAILQ_INSERT_HEAD(&conn->pdus_to_send, pdu, send_chain);
480 	else
481 		TAILQ_INSERT_TAIL(&conn->pdus_to_send, pdu, send_chain);
482 	mutex_exit(&conn->lock);
483 
484 	cv_broadcast(&conn->conn_cv);
485 
486 	if (cdisp != CCBDISP_NOWAIT) {
487 		ccb_timeout_start(ccb, COMMAND_TIMEOUT);
488 
489 		if (prev_cdisp <= CCBDISP_NOWAIT)
490 			suspend_ccb(ccb, TRUE);
491 
492 		mutex_enter(&conn->lock);
493 		while (ccb->disp == CCBDISP_WAIT) {
494 			DEBC(conn, 15, ("Send_pdu: ccb=%p cdisp=%d waiting\n",
495 				ccb, ccb->disp));
496 			cv_wait(&conn->ccb_cv, &conn->lock);
497 			DEBC(conn, 15, ("Send_pdu: ccb=%p cdisp=%d returned\n",
498 				ccb, ccb->disp));
499 		}
500 		mutex_exit(&conn->lock);
501 	}
502 }
503 
504 
505 /*
506  * resend_pdu:
507  *    Re-Enqueue a PDU that has apparently gotten lost.
508  *
509  *    Parameter:
510  *          ccb      The associated CCB.
511  */
512 
513 void
514 resend_pdu(ccb_t *ccb)
515 {
516 	connection_t *conn = ccb->connection;
517 	pdu_t *pdu = ccb->pdu_waiting;
518 
519 	mutex_enter(&conn->lock);
520 	if (pdu == NULL || (pdu->flags & PDUF_BUSY)) {
521 		mutex_exit(&conn->lock);
522 		return;
523 	}
524 	pdu->flags |= PDUF_BUSY;
525 	mutex_exit(&conn->lock);
526 
527 	/* restore UIO and IOVEC */
528 	pdu->uio = pdu->save_uio;
529 	memcpy(pdu->io_vec, pdu->save_iovec, sizeof(pdu->io_vec));
530 
531 	DEBC(conn, 8, ("ReSend_pdu ccb=%p, pdu=%p\n", ccb, pdu));
532 
533 	mutex_enter(&conn->lock);
534 	/* Enqueue for sending */
535 	pdu->flags |= PDUF_INQUEUE;
536 
537 	if (pdu->flags & PDUF_PRIORITY) {
538 		TAILQ_INSERT_HEAD(&conn->pdus_to_send, pdu, send_chain);
539 	} else {
540 		TAILQ_INSERT_TAIL(&conn->pdus_to_send, pdu, send_chain);
541 	}
542 	ccb_timeout_start(ccb, COMMAND_TIMEOUT);
543 	mutex_exit(&conn->lock);
544 
545 	cv_broadcast(&conn->conn_cv);
546 }
547 
548 
549 /*
550  * setup_tx_uio:
551  *    Initialize the uio structure for sending, including header,
552  *    data (if present), padding, and Data Digest.
553  *    Header Digest is generated in send thread.
554  *
555  *    Parameter:
556  *          pdu      The PDU
557  *          dsl      The Data Segment Length
558  *          data     The data pointer
559  *          read     TRUE if this is a read operation
560  */
561 
562 STATIC void
563 setup_tx_uio(pdu_t *pdu, uint32_t dsl, void *data, bool read)
564 {
565 	static uint8_t pad_bytes[4] = { 0 };
566 	struct uio *uio;
567 	int i, pad, hlen;
568 	connection_t *conn = pdu->connection;
569 
570 	DEB(99, ("SetupTxUio: dlen = %d, dptr: %p, read: %d\n",
571 			 dsl, data, read));
572 
573 	if (!read && dsl) {
574 		hton3(dsl, pdu->pdu.DataSegmentLength);
575 	}
576 	hlen = (conn->HeaderDigest) ? BHS_SIZE + 4 : BHS_SIZE;
577 
578 	pdu->io_vec[0].iov_base = &pdu->pdu;
579 	pdu->io_vec[0].iov_len = hlen;
580 
581 	uio = &pdu->uio;
582 
583 	uio->uio_iov = pdu->io_vec;
584 	uio->uio_iovcnt = 1;
585 	uio->uio_rw = UIO_WRITE;
586 	uio->uio_resid = hlen;
587 	UIO_SETUP_SYSSPACE(uio);
588 
589 	if (!read && dsl) {
590 		uio->uio_iovcnt++;
591 		pdu->io_vec[1].iov_base = data;
592 		pdu->io_vec[1].iov_len = dsl;
593 		uio->uio_resid += dsl;
594 
595 		/* Pad to next multiple of 4 */
596 		pad = uio->uio_resid & 0x03;
597 		if (pad) {
598 			i = uio->uio_iovcnt++;
599 			pad = 4 - pad;
600 			pdu->io_vec[i].iov_base = pad_bytes;
601 			pdu->io_vec[i].iov_len = pad;
602 			uio->uio_resid += pad;
603 		}
604 
605 		if (conn->DataDigest) {
606 			pdu->data_digest = gen_digest_2(data, dsl, pad_bytes, pad);
607 			i = uio->uio_iovcnt++;
608 			pdu->io_vec[i].iov_base = &pdu->data_digest;
609 			pdu->io_vec[i].iov_len = 4;
610 			uio->uio_resid += 4;
611 		}
612 	}
613 }
614 
615 /*
616  * init_login_pdu:
617  *    Initialize the login PDU.
618  *
619  *    Parameter:
620  *          conn     The connection
621  *          ccb      The CCB
622  *          pdu      The PDU
623  */
624 
625 STATIC void
626 init_login_pdu(connection_t *conn, ccb_t *ccb, pdu_t *ppdu, bool next)
627 {
628 	pdu_header_t *pdu = &ppdu->pdu;
629 	login_isid_t *isid = (login_isid_t *) & pdu->LUN;
630 	uint8_t c_phase;
631 
632 	pdu->Opcode = IOP_Login_Request | OP_IMMEDIATE;
633 
634 	mutex_enter(&conn->session->lock);
635 	ccb->CmdSN = get_sernum(conn->session, false);
636 	mutex_exit(&conn->session->lock);
637 
638 	if (next) {
639 		c_phase = (pdu->Flags >> CSG_SHIFT) & SG_MASK;
640 		pdu->Flags = FLAG_TRANSIT | (c_phase << CSG_SHIFT) |
641 					 NEXT_PHASE(c_phase);
642 	}
643 
644 	memcpy(isid, &iscsi_InitiatorISID, 6);
645 	isid->TSIH = conn->session->TSIH;
646 
647 	pdu->p.login_req.CID = htons(conn->id);
648 	pdu->p.login_req.CmdSN = htonl(ccb->CmdSN);
649 }
650 
651 
652 /*
653  * negotiate_login:
654  *    Control login negotiation.
655  *
656  *    Parameter:
657  *          conn     The connection
658  *          rx_pdu   The received login response PDU
659  *          tx_ccb   The originally sent login CCB
660  */
661 
662 void
663 negotiate_login(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb)
664 {
665 	int rc;
666 	bool next = TRUE;
667 	pdu_t *tx_pdu;
668 	uint8_t c_phase;
669 
670 	if (rx_pdu->pdu.Flags & FLAG_TRANSIT)
671 		c_phase = rx_pdu->pdu.Flags & SG_MASK;
672 	else
673 		c_phase = (rx_pdu->pdu.Flags >> CSG_SHIFT) & SG_MASK;
674 
675 	DEB(99, ("NegotiateLogin: Flags=%x Phase=%x\n",
676 			 rx_pdu->pdu.Flags, c_phase));
677 
678 	if (c_phase == SG_FULL_FEATURE_PHASE) {
679 		session_t *sess = conn->session;
680 
681 		if (!sess->TSIH)
682 			sess->TSIH = ((login_isid_t *) &rx_pdu->pdu.LUN)->TSIH;
683 
684 		if (rx_pdu->temp_data != NULL)
685 			assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, NULL);
686 
687 		/* negotiated values are now valid */
688 		set_negotiated_parameters(tx_ccb);
689 
690 		DEBC(conn, 5, ("Login Successful!\n"));
691 		wake_ccb(tx_ccb, ISCSI_STATUS_SUCCESS);
692 		return;
693 	}
694 
695 	tx_pdu = get_pdu(conn, TRUE);
696 	if (tx_pdu == NULL)
697 		return;
698 
699 	tx_pdu->pdu.Flags = c_phase << CSG_SHIFT;
700 
701 	switch (c_phase) {
702 	case SG_SECURITY_NEGOTIATION:
703 		rc = assemble_security_parameters(conn, tx_ccb, rx_pdu, tx_pdu);
704 		if (rc < 0)
705 			next = FALSE;
706 		break;
707 
708 	case SG_LOGIN_OPERATIONAL_NEGOTIATION:
709 		rc = assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, tx_pdu);
710 		break;
711 
712 	default:
713 		DEBOUT(("Invalid phase %x in negotiate_login\n", c_phase));
714 		rc = ISCSI_STATUS_TARGET_ERROR;
715 		break;
716 	}
717 
718 	if (rc > 0) {
719 		wake_ccb(tx_ccb, rc);
720 		free_pdu(tx_pdu);
721 	} else {
722 		init_login_pdu(conn, tx_ccb, tx_pdu, next);
723 		setup_tx_uio(tx_pdu, tx_pdu->temp_data_len, tx_pdu->temp_data, FALSE);
724 		send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE);
725 	}
726 }
727 
728 
729 /*
730  * init_text_pdu:
731  *    Initialize the text PDU.
732  *
733  *    Parameter:
734  *          conn     The connection
735  *          ccb      The transmit CCB
736  *          ppdu     The transmit PDU
737  *          rx_pdu   The received PDU if this is an unsolicited negotiation
738  */
739 
740 STATIC void
741 init_text_pdu(connection_t *conn, ccb_t *ccb, pdu_t *ppdu, pdu_t *rx_pdu)
742 {
743 	pdu_header_t *pdu = &ppdu->pdu;
744 
745 	pdu->Opcode = IOP_Text_Request | OP_IMMEDIATE;
746 	pdu->Flags = FLAG_FINAL;
747 
748 	mutex_enter(&conn->session->lock);
749 	ccb->CmdSN = get_sernum(conn->session, false);
750 	mutex_exit(&conn->session->lock);
751 
752 	if (rx_pdu != NULL) {
753 		pdu->p.text_req.TargetTransferTag =
754 			rx_pdu->pdu.p.text_rsp.TargetTransferTag;
755 		pdu->LUN = rx_pdu->pdu.LUN;
756 	} else
757 		pdu->p.text_req.TargetTransferTag = 0xffffffff;
758 
759 	pdu->p.text_req.CmdSN = htonl(ccb->CmdSN);
760 }
761 
762 
763 /*
764  * acknowledge_text:
765  *    Acknowledge a continued login or text response.
766  *
767  *    Parameter:
768  *          conn     The connection
769  *          rx_pdu   The received login/text response PDU
770  *          tx_ccb   The originally sent login/text request CCB
771  */
772 
773 void
774 acknowledge_text(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb)
775 {
776 	pdu_t *tx_pdu;
777 
778 	tx_pdu = get_pdu(conn, TRUE);
779 	if (tx_pdu == NULL)
780 		return;
781 
782 	if (rx_pdu != NULL &&
783 		(rx_pdu->pdu.Opcode & OPCODE_MASK) == IOP_Login_Request)
784 		init_login_pdu(conn, tx_ccb, tx_pdu, FALSE);
785 	else
786 		init_text_pdu(conn, tx_ccb, tx_pdu, rx_pdu);
787 
788 	setup_tx_uio(tx_pdu, 0, NULL, FALSE);
789 	send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE);
790 }
791 
792 
793 /*
794  * start_text_negotiation:
795  *    Handle target request to negotiate (via asynch event)
796  *
797  *    Parameter:
798  *          conn     The connection
799  */
800 
801 void
802 start_text_negotiation(connection_t *conn)
803 {
804 	pdu_t *pdu;
805 	ccb_t *ccb;
806 
807 	ccb = get_ccb(conn, TRUE);
808 	if (ccb == NULL)
809 		return;
810 	pdu = get_pdu(conn, TRUE);
811 	if (pdu == NULL) {
812 		free_ccb(ccb);
813 		return;
814 	}
815 
816 	if (init_text_parameters(conn, ccb)) {
817 		free_ccb(ccb);
818 		free_pdu(pdu);
819 		return;
820 	}
821 
822 	init_text_pdu(conn, ccb, pdu, NULL);
823 	setup_tx_uio(pdu, 0, NULL, FALSE);
824 	send_pdu(ccb, pdu, CCBDISP_FREE, PDUDISP_WAIT);
825 }
826 
827 
828 /*
829  * negotiate_text:
830  *    Handle received text negotiation.
831  *
832  *    Parameter:
833  *          conn     The connection
834  *          rx_pdu   The received text response PDU
835  *          tx_ccb   The original CCB
836  */
837 
838 void
839 negotiate_text(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb)
840 {
841 	int rc;
842 	pdu_t *tx_pdu;
843 
844 	if (tx_ccb->flags & CCBF_SENDTARGET) {
845 		if (!(rx_pdu->pdu.Flags & FLAG_FINAL)) {
846 			handle_connection_error(conn, ISCSI_STATUS_PROTOCOL_ERROR,
847 									LOGOUT_CONNECTION);
848 			return;
849 		}
850 		/* transfer ownership of text to CCB */
851 		tx_ccb->text_data = rx_pdu->temp_data;
852 		tx_ccb->text_len = rx_pdu->temp_data_len;
853 		rx_pdu->temp_data = NULL;
854 		wake_ccb(tx_ccb, ISCSI_STATUS_SUCCESS);
855 	} else {
856 		if (!(rx_pdu->pdu.Flags & FLAG_FINAL))
857 			tx_pdu = get_pdu(conn, TRUE);
858 		else
859 			tx_pdu = NULL;
860 
861 		rc = assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, tx_pdu);
862 		if (rc) {
863 			if (tx_pdu != NULL)
864 				free_pdu(tx_pdu);
865 
866 			handle_connection_error(conn, rc, LOGOUT_CONNECTION);
867 		} else if (tx_pdu != NULL) {
868 			init_text_pdu(conn, tx_ccb, tx_pdu, rx_pdu);
869 			setup_tx_uio(tx_pdu, tx_pdu->temp_data_len, tx_pdu->temp_data,
870 						 FALSE);
871 			send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE);
872 		} else {
873 			set_negotiated_parameters(tx_ccb);
874 			wake_ccb(tx_ccb, ISCSI_STATUS_SUCCESS);
875 		}
876 	}
877 }
878 
879 
880 /*
881  * send_send_targets:
882  *    Send out a SendTargets text request.
883  *    The result is stored in the fields in the session structure.
884  *
885  *    Parameter:
886  *          session  The session
887  *          key      The text key to use
888  *
889  *    Returns:    0 on success, else an error code.
890  */
891 
892 int
893 send_send_targets(session_t *session, uint8_t *key)
894 {
895 	ccb_t *ccb;
896 	pdu_t *pdu;
897 	int rc = 0;
898 	connection_t *conn;
899 
900 	DEB(9, ("Send_send_targets\n"));
901 
902 	conn = assign_connection(session, TRUE);
903 	if (conn == NULL || conn->terminating || conn->state != ST_FULL_FEATURE)
904 		return (conn != NULL && conn->terminating) ? conn->terminating
905 			: ISCSI_STATUS_CONNECTION_FAILED;
906 
907 	ccb = get_ccb(conn, TRUE);
908 	if (ccb == NULL)
909 		return conn->terminating;
910 	pdu = get_pdu(conn, TRUE);
911 	if (pdu == NULL) {
912 		free_ccb(ccb);
913 		return conn->terminating;
914 	}
915 
916 	ccb->flags |= CCBF_SENDTARGET;
917 
918 	if ((rc = assemble_send_targets(pdu, key)) != 0) {
919 		free_ccb(ccb);
920 		free_pdu(pdu);
921 		return rc;
922 	}
923 
924 	init_text_pdu(conn, ccb, pdu, NULL);
925 
926 	setup_tx_uio(pdu, pdu->temp_data_len, pdu->temp_data, FALSE);
927 	send_pdu(ccb, pdu, CCBDISP_WAIT, PDUDISP_WAIT);
928 
929 	rc = ccb->status;
930 	if (!rc) {
931 		/* transfer ownership of data */
932 		session->target_list = ccb->text_data;
933 		session->target_list_len = ccb->text_len;
934 		ccb->text_data = NULL;
935 	}
936 	free_ccb(ccb);
937 	return rc;
938 }
939 
940 
941 /*
942  * send_nop_out:
943  *    Send nop out request.
944  *
945  *    Parameter:
946  *          conn     The connection
947  *          rx_pdu   The received Nop-In PDU
948  *
949  *    Returns:    0 on success, else an error code.
950  */
951 
952 int
953 send_nop_out(connection_t *conn, pdu_t *rx_pdu)
954 {
955 	ccb_t *ccb;
956 	pdu_t *ppdu;
957 	pdu_header_t *pdu;
958 
959 	DEBC(conn, 10, ("Send NOP_Out rx_pdu=%p\n", rx_pdu));
960 
961 	if (rx_pdu != NULL) {
962 		ccb = NULL;
963 		ppdu = get_pdu(conn, TRUE);
964 		if (ppdu == NULL)
965 			return 1;
966 	} else {
967 		ccb = get_ccb(conn, FALSE);
968 		if (ccb == NULL) {
969 			DEBOUT(("Can't get CCB in send_nop_out\n"));
970 			return 1;
971 		}
972 		ppdu = get_pdu(conn, FALSE);
973 		if (ppdu == NULL) {
974 			free_ccb(ccb);
975 			DEBOUT(("Can't get PDU in send_nop_out\n"));
976 			return 1;
977 		}
978 	}
979 
980 	pdu = &ppdu->pdu;
981 	pdu->Flags = FLAG_FINAL;
982 	pdu->Opcode = IOP_NOP_Out | OP_IMMEDIATE;
983 
984 	if (rx_pdu != NULL) {
985 		pdu->p.nop_out.TargetTransferTag =
986 			rx_pdu->pdu.p.nop_in.TargetTransferTag;
987 		pdu->InitiatorTaskTag = rx_pdu->pdu.InitiatorTaskTag;
988 		pdu->p.nop_out.CmdSN = htonl(conn->session->CmdSN);
989 		pdu->LUN = rx_pdu->pdu.LUN;
990 	} else {
991 		pdu->p.nop_out.TargetTransferTag = 0xffffffff;
992 		ccb->CmdSN = ccb->session->CmdSN;
993 		pdu->p.nop_out.CmdSN = htonl(ccb->CmdSN);
994 	}
995 
996 	setup_tx_uio(ppdu, 0, NULL, FALSE);
997 	send_pdu(ccb, ppdu, (rx_pdu != NULL) ? CCBDISP_NOWAIT : CCBDISP_FREE,
998 			 PDUDISP_FREE);
999 	return 0;
1000 }
1001 
1002 
1003 /*
1004  * snack_missing:
1005  *    Send SNACK request for missing data.
1006  *
1007  *    Parameter:
1008  *          conn     The connection
1009  *          ccb      The task's CCB (for Data NAK only)
1010  *          type     The SNACK type
1011  *          BegRun   The BegRun field
1012  *          RunLength   The RunLength field
1013  */
1014 
1015 void
1016 snack_missing(connection_t *conn, ccb_t *ccb, uint8_t type,
1017 			  uint32_t BegRun, uint32_t RunLength)
1018 {
1019 	pdu_t *ppdu;
1020 	pdu_header_t *pdu;
1021 
1022 	ppdu = get_pdu(conn, TRUE);
1023 	if (ppdu == NULL)
1024 		return;
1025 	pdu = &ppdu->pdu;
1026 	pdu->Opcode = IOP_SNACK_Request;
1027 	pdu->Flags = FLAG_FINAL | type;
1028 
1029 	pdu->InitiatorTaskTag = (type == SNACK_DATA_NAK) ? ccb->ITT : 0xffffffff;
1030 	pdu->p.snack.TargetTransferTag = 0xffffffff;
1031 	pdu->p.snack.BegRun = htonl(BegRun);
1032 	pdu->p.snack.RunLength = htonl(RunLength);
1033 
1034 	ppdu->flags = PDUF_PRIORITY;
1035 
1036 	setup_tx_uio(ppdu, 0, NULL, FALSE);
1037 	send_pdu(NULL, ppdu, CCBDISP_NOWAIT, PDUDISP_FREE);
1038 }
1039 
1040 
1041 /*
1042  * send_snack:
1043  *    Send SNACK request.
1044  *
1045  *    Parameter:
1046  *          conn     The connection
1047  *          rx_pdu   The received data in PDU
1048  *          tx_ccb   The original command CCB (required for Data ACK only)
1049  *          type     The SNACK type
1050  *
1051  *    Returns:    0 on success, else an error code.
1052  */
1053 
1054 void
1055 send_snack(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb, uint8_t type)
1056 {
1057 	pdu_t *ppdu;
1058 	pdu_header_t *pdu;
1059 
1060 	ppdu = get_pdu(conn, TRUE);
1061 	if (ppdu == NULL)
1062 		return;
1063 	pdu = &ppdu->pdu;
1064 	pdu->Opcode = IOP_SNACK_Request;
1065 	pdu->Flags = FLAG_FINAL | type;
1066 
1067 	switch (type) {
1068 	case SNACK_DATA_NAK:
1069 		pdu->InitiatorTaskTag = rx_pdu->pdu.InitiatorTaskTag;
1070 		pdu->p.snack.TargetTransferTag = 0xffffffff;
1071 		pdu->p.snack.BegRun = rx_pdu->pdu.p.data_in.DataSN;
1072 		pdu->p.snack.RunLength = htonl(1);
1073 		break;
1074 
1075 	case SNACK_STATUS_NAK:
1076 		pdu->InitiatorTaskTag = 0xffffffff;
1077 		pdu->p.snack.TargetTransferTag = 0xffffffff;
1078 		pdu->p.snack.BegRun = rx_pdu->pdu.p.response.StatSN;
1079 		pdu->p.snack.RunLength = htonl(1);
1080 		break;
1081 
1082 	case SNACK_DATA_ACK:
1083 		pdu->InitiatorTaskTag = 0xffffffff;
1084 		pdu->p.snack.TargetTransferTag =
1085 			rx_pdu->pdu.p.data_in.TargetTransferTag;
1086 		pdu->p.snack.BegRun = tx_ccb->DataSN_buf.ExpSN;
1087 		pdu->p.snack.RunLength = 0;
1088 		break;
1089 
1090 	default:
1091 		DEBOUT(("Invalid type %d in send_snack\n", type));
1092 		return;
1093 	}
1094 
1095 	pdu->LUN = rx_pdu->pdu.LUN;
1096 
1097 	ppdu->flags = PDUF_PRIORITY;
1098 
1099 	setup_tx_uio(ppdu, 0, NULL, FALSE);
1100 	send_pdu(NULL, ppdu, CCBDISP_NOWAIT, PDUDISP_FREE);
1101 }
1102 
1103 
1104 /*
1105  * send_login:
1106  *    Send login request.
1107  *
1108  *    Parameter:
1109  *          conn     The connection
1110  *          par      The login parameters (for negotiation)
1111  *
1112  *    Returns:       0 on success, else an error code.
1113  */
1114 
1115 int
1116 send_login(connection_t *conn)
1117 {
1118 	ccb_t *ccb;
1119 	pdu_t *pdu;
1120 	int rc;
1121 
1122 	DEBC(conn, 9, ("Send_login\n"));
1123 	ccb = get_ccb(conn, TRUE);
1124 	/* only if terminating (which couldn't possibly happen here, but...) */
1125 	if (ccb == NULL)
1126 		return conn->terminating;
1127 	pdu = get_pdu(conn, TRUE);
1128 	if (pdu == NULL) {
1129 		free_ccb(ccb);
1130 		return conn->terminating;
1131 	}
1132 
1133 	if ((rc = assemble_login_parameters(conn, ccb, pdu)) <= 0) {
1134 		init_login_pdu(conn, ccb, pdu, !rc);
1135 		setup_tx_uio(pdu, pdu->temp_data_len, pdu->temp_data, FALSE);
1136 		send_pdu(ccb, pdu, CCBDISP_WAIT, PDUDISP_FREE);
1137 		rc = ccb->status;
1138 	} else {
1139 		free_pdu(pdu);
1140 	}
1141 	free_ccb(ccb);
1142 	return rc;
1143 }
1144 
1145 
1146 /*
1147  * send_logout:
1148  *    Send logout request.
1149  *	  NOTE: This function does not wait for the logout to complete.
1150  *
1151  *    Parameter:
1152  *          conn	The connection
1153  *			refconn	The referenced connection
1154  *			reason	The reason code
1155  *			wait	Wait for completion if TRUE
1156  *
1157  *    Returns:       0 on success (logout sent), else an error code.
1158  */
1159 
1160 int
1161 send_logout(connection_t *conn, connection_t *refconn, int reason,
1162 			bool wait)
1163 {
1164 	ccb_t *ccb;
1165 	pdu_t *ppdu;
1166 	pdu_header_t *pdu;
1167 
1168 	DEBC(conn, 5, ("Send_logout\n"));
1169 	ccb = get_ccb(conn, TRUE);
1170 	/* can only happen if terminating... */
1171 	if (ccb == NULL)
1172 		return conn->terminating;
1173 	ppdu = get_pdu(conn, TRUE);
1174 	if (ppdu == NULL) {
1175 		free_ccb(ccb);
1176 		return conn->terminating;
1177 	}
1178 
1179 	pdu = &ppdu->pdu;
1180 	pdu->Opcode = IOP_Logout_Request | OP_IMMEDIATE;
1181 
1182 	pdu->Flags = FLAG_FINAL | reason;
1183 	ccb->CmdSN = conn->session->CmdSN;
1184 	pdu->p.logout_req.CmdSN = htonl(ccb->CmdSN);
1185 	if (reason > 0)
1186 		pdu->p.logout_req.CID = htons(refconn->id);
1187 
1188 	ccb->par = refconn;
1189 	if (refconn != conn) {
1190 		ccb->flags |= CCBF_OTHERCONN;
1191 	} else {
1192 		conn->state = ST_LOGOUT_SENT;
1193 		conn->loggedout = LOGOUT_SENT;
1194 	}
1195 
1196 	setup_tx_uio(ppdu, 0, NULL, FALSE);
1197 
1198 	send_pdu(ccb, ppdu, (wait) ? CCBDISP_WAIT : CCBDISP_FREE, PDUDISP_FREE);
1199 
1200 	if (wait) {
1201 		int rc = ccb->status;
1202 		free_ccb (ccb);
1203 		return rc;
1204 	}
1205 	return 0;
1206 }
1207 
1208 
1209 /*
1210  * send_task_management:
1211  *    Send task management request.
1212  *
1213  *    Parameter:
1214  *          conn     The connection
1215  *          ref_ccb  The referenced command (NULL if none)
1216  *          xs       The scsipi command structure (NULL if not a scsipi request)
1217  *          function The function code
1218  *
1219  *    Returns:       0 on success, else an error code.
1220  */
1221 
1222 int
1223 send_task_management(connection_t *conn, ccb_t *ref_ccb, struct scsipi_xfer *xs,
1224 					 int function)
1225 {
1226 	ccb_t *ccb;
1227 	pdu_t *ppdu;
1228 	pdu_header_t *pdu;
1229 
1230 	DEBC(conn, 5, ("Send_task_management, ref_ccb=%p, func = %d\n",
1231 			ref_ccb, function));
1232 
1233 	if (function == TASK_REASSIGN && conn->session->ErrorRecoveryLevel < 2)
1234 		return ISCSI_STATUS_CANT_REASSIGN;
1235 
1236 	ccb = get_ccb(conn, xs == NULL);
1237 	/* can only happen if terminating... */
1238 	if (ccb == NULL)
1239 		return conn->terminating;
1240 	ppdu = get_pdu(conn, xs == NULL);
1241 	if (ppdu == NULL) {
1242 		free_ccb(ccb);
1243 		return conn->terminating;
1244 	}
1245 
1246 	ccb->xs = xs;
1247 
1248 	pdu = &ppdu->pdu;
1249 	pdu->Opcode = IOP_SCSI_Task_Management | OP_IMMEDIATE;
1250 	pdu->Flags = FLAG_FINAL | function;
1251 
1252 	ccb->CmdSN = conn->session->CmdSN;
1253 	pdu->p.task_req.CmdSN = htonl(ccb->CmdSN);
1254 
1255 	if (ref_ccb != NULL) {
1256 		pdu->p.task_req.ReferencedTaskTag = ref_ccb->ITT;
1257 		pdu->p.task_req.RefCmdSN = htonl(ref_ccb->CmdSN);
1258 		pdu->p.task_req.ExpDataSN = htonl(ref_ccb->DataSN_buf.ExpSN);
1259 	} else
1260 		pdu->p.task_req.ReferencedTaskTag = 0xffffffff;
1261 
1262 	ppdu->flags |= PDUF_PRIORITY;
1263 
1264 	setup_tx_uio(ppdu, 0, NULL, FALSE);
1265 	send_pdu(ccb, ppdu, (xs) ? CCBDISP_SCSIPI : CCBDISP_WAIT, PDUDISP_FREE);
1266 
1267 	if (xs == NULL) {
1268 		int rc = ccb->status;
1269 		free_ccb(ccb);
1270 		return rc;
1271 	}
1272 	return 0;
1273 }
1274 
1275 
1276 /*
1277  * send_data_out:
1278  *    Send data to target in response to an R2T or as unsolicited data.
1279  *
1280  *    Parameter:
1281  *          conn     The connection
1282  *          rx_pdu   The received R2T PDU (NULL if unsolicited)
1283  *          tx_ccb   The originally sent command CCB
1284  *          waitok   Whether it's OK to wait for an available PDU or not
1285  */
1286 
1287 int
1288 send_data_out(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb,
1289 			  ccb_disp_t disp, bool waitok)
1290 {
1291 	pdu_header_t *pdu;
1292 	uint32_t totlen, len, offs, sn;
1293 	pdu_t *tx_pdu;
1294 
1295 	KASSERT(conn->max_transfer != 0);
1296 
1297 	if (rx_pdu) {
1298 		offs = ntohl(rx_pdu->pdu.p.r2t.BufferOffset);
1299 		totlen = ntohl(rx_pdu->pdu.p.r2t.DesiredDataTransferLength);
1300 	} else {
1301 		offs = conn->max_firstimmed;
1302 		totlen = min(conn->max_firstdata - offs, tx_ccb->data_len - offs);
1303 	}
1304 	sn = 0;
1305 
1306 	while (totlen) {
1307 		len = min(totlen, conn->max_transfer);
1308 
1309 		tx_pdu = get_pdu(conn, waitok);
1310 		if (tx_pdu == NULL) {
1311 			DEBC(conn, 5, ("No PDU in send_data_out\n"));
1312 
1313 			tx_ccb->disp = disp;
1314 			tx_ccb->status = ISCSI_STATUS_NO_RESOURCES;
1315 			handle_connection_error(conn, ISCSI_STATUS_NO_RESOURCES, NO_LOGOUT);
1316 
1317 			return ISCSI_STATUS_NO_RESOURCES;
1318 		}
1319 
1320 		totlen -= len;
1321 		pdu = &tx_pdu->pdu;
1322 		pdu->Opcode = IOP_SCSI_Data_out;
1323 		if (!totlen)
1324 			pdu->Flags = FLAG_FINAL;
1325 
1326 		if (rx_pdu != NULL)
1327 			pdu->p.data_out.TargetTransferTag =
1328 				rx_pdu->pdu.p.r2t.TargetTransferTag;
1329 		else
1330 			pdu->p.data_out.TargetTransferTag = 0xffffffff;
1331 		pdu->p.data_out.BufferOffset = htonl(offs);
1332 		pdu->p.data_out.DataSN = htonl(sn);
1333 
1334 		DEBC(conn, 10, ("Send DataOut: DataSN %d, len %d offs %x totlen %d\n",
1335 				sn, len, offs, totlen));
1336 
1337 		setup_tx_uio(tx_pdu, len, tx_ccb->data_ptr + offs, FALSE);
1338 
1339 		send_pdu(tx_ccb, tx_pdu, (totlen) ? CCBDISP_NOWAIT : disp, PDUDISP_FREE);
1340 
1341 		sn++;
1342 		offs += len;
1343 	}
1344 	return 0;
1345 }
1346 
1347 
1348 /*
1349  * send_command:
1350  *    Send a SCSI command request.
1351  *
1352  *    Parameter:
1353  *          CCB      The CCB
1354  *          disp     The CCB disposition
1355  */
1356 
1357 void
1358 send_command(ccb_t *ccb, ccb_disp_t disp, bool waitok, bool immed)
1359 {
1360 	uint32_t totlen, len;
1361 	connection_t *conn = ccb->connection;
1362 	session_t *sess = ccb->session;
1363 	pdu_t *ppdu;
1364 	pdu_header_t *pdu;
1365 
1366 	mutex_enter(&sess->lock);
1367 	while (/*CONSTCOND*/ISCSI_THROTTLING_ENABLED &&
1368 	    /*CONSTCOND*/!ISCSI_SERVER_TRUSTED &&
1369 	    !sernum_in_window(sess)) {
1370 
1371 		ccb->disp = disp;
1372 		if (waitok)
1373 			ccb->flags |= CCBF_WAITING;
1374 		throttle_ccb(ccb, TRUE);
1375 
1376 		if (!waitok) {
1377 			mutex_exit(&sess->lock);
1378 			DEBC(conn, 10, ("Throttling send_command, ccb = %p\n",ccb));
1379 			return;
1380 		}
1381 
1382 		DEBC(conn, 15, ("Wait send_command, ccb = %p\n",ccb));
1383 		cv_wait(&sess->ccb_cv, &sess->lock);
1384 		DEBC(conn, 15, ("Resuming send_command, ccb = %p\n",ccb));
1385 
1386 		throttle_ccb(ccb, FALSE);
1387 		ccb->flags &= ~CCBF_WAITING;
1388 	}
1389 	mutex_exit(&sess->lock);
1390 
1391 	ppdu = get_pdu(conn, waitok);
1392 	if (ppdu == NULL) {
1393 		DEBOUT(("No PDU for send_command, ccb = %p\n",ccb));
1394 		ccb->disp = disp;
1395 		wake_ccb(ccb, ISCSI_STATUS_NO_RESOURCES);
1396 		return;
1397 	}
1398 
1399 	totlen = len = ccb->data_len;
1400 
1401 	pdu = &ppdu->pdu;
1402 	pdu->LUN = htonq(ccb->lun);
1403 	memcpy(pdu->p.command.SCSI_CDB, ccb->cmd, ccb->cmdlen);
1404 	pdu->Opcode = IOP_SCSI_Command;
1405 	if (immed)
1406 		pdu->Opcode |= OP_IMMEDIATE;
1407 	pdu->p.command.ExpectedDataTransferLength = htonl(totlen);
1408 
1409 	if (totlen) {
1410 		if (ccb->data_in) {
1411 			pdu->Flags = FLAG_READ;
1412 			totlen = 0;
1413 		} else {
1414 			pdu->Flags = FLAG_WRITE;
1415 			/* immediate data we can send */
1416 			len = min(totlen, conn->max_firstimmed);
1417 
1418 			/* can we send more unsolicited data ? */
1419 			totlen = conn->max_firstdata ? totlen - len : 0;
1420 		}
1421 	}
1422 	if (!totlen)
1423 		pdu->Flags |= FLAG_FINAL;
1424 	pdu->Flags |= ccb->tag;
1425 
1426 	if (ccb->data_in)
1427 		init_sernum(&ccb->DataSN_buf);
1428 
1429 	ccb->sense_len_got = 0;
1430 	ccb->xfer_len = 0;
1431 	ccb->residual = 0;
1432 	ccb->flags |= CCBF_REASSIGN;
1433 
1434 	mutex_enter(&sess->lock);
1435 	ccb->CmdSN = get_sernum(sess, !immed);
1436 	mutex_exit(&sess->lock);
1437 
1438 	pdu->p.command.CmdSN = htonl(ccb->CmdSN);
1439 
1440 	DEBC(conn, 10, ("Send Command: CmdSN %d (%d), data_in %d, len %d, totlen %d\n",
1441 			ccb->CmdSN, sess->MaxCmdSN, ccb->data_in, len, totlen));
1442 
1443 	setup_tx_uio(ppdu, len, ccb->data_ptr, ccb->data_in);
1444 	send_pdu(ccb, ppdu, (totlen) ? CCBDISP_DEFER : disp, PDUDISP_WAIT);
1445 
1446 	if (totlen)
1447 		send_data_out(conn, NULL, ccb, disp, waitok);
1448 }
1449 
1450 
1451 /*
1452  * send_run_xfer:
1453  *    Handle a SCSI command transfer request from scsipi.
1454  *
1455  *    Parameter:
1456  *          session  The session
1457  *          xs       The transfer parameters
1458  */
1459 
1460 void
1461 send_run_xfer(session_t *session, struct scsipi_xfer *xs)
1462 {
1463 	ccb_t *ccb;
1464 	connection_t *conn;
1465 	bool waitok;
1466 
1467 	waitok = !(xs->xs_control & XS_CTL_NOSLEEP);
1468 
1469 	DEB(10, ("RunXfer: flags=%x, data=%p, datalen=%d, resid=%d, cmdlen=%d, "
1470 			"waitok=%d\n", xs->xs_control, xs->data, xs->datalen,
1471 			xs->resid, xs->cmdlen, waitok));
1472 
1473 	conn = assign_connection(session, waitok);
1474 
1475 	if (conn == NULL || conn->terminating || conn->state != ST_FULL_FEATURE) {
1476 		xs->error = XS_SELTIMEOUT;
1477 		DEBC(conn, 10, ("run_xfer on dead connection\n"));
1478 		scsipi_done(xs);
1479 		return;
1480 	}
1481 
1482 	if (xs->xs_control & XS_CTL_RESET) {
1483 		if (send_task_management(conn, NULL, xs, TARGET_WARM_RESET)) {
1484 			xs->error = XS_SELTIMEOUT;
1485 			scsipi_done(xs);
1486 		}
1487 		return;
1488 	}
1489 
1490 	ccb = get_ccb(conn, waitok);
1491 	if (ccb == NULL) {
1492 		xs->error = XS_BUSY;
1493 		DEBC(conn, 5, ("No CCB in run_xfer, %d in use.\n", conn->usecount));
1494 		scsipi_done(xs);
1495 		return;
1496 	}
1497 	/* copy parameters into CCB for easier access */
1498 	ccb->xs = xs;
1499 
1500 	ccb->data_in = (xs->xs_control & XS_CTL_DATA_IN) != 0;
1501 	ccb->data_len = (uint32_t) xs->datalen;
1502 	ccb->data_ptr = xs->data;
1503 
1504 	ccb->sense_len_req = sizeof(xs->sense.scsi_sense);
1505 	ccb->sense_ptr = &xs->sense;
1506 
1507 	ccb->lun = ((uint64_t) (uint8_t) xs->xs_periph->periph_lun) << 48;
1508 	ccb->cmd = (uint8_t *) xs->cmd;
1509 	ccb->cmdlen = xs->cmdlen;
1510 	DEB(10, ("RunXfer: Periph_lun = %d, cmd[1] = %x, cmdlen = %d\n",
1511 			xs->xs_periph->periph_lun, ccb->cmd[1], xs->cmdlen));
1512 
1513 	ccb->ITT |= xs->xs_tag_id << 24;
1514 	switch (xs->xs_tag_type) {
1515 	case MSG_ORDERED_Q_TAG:
1516 		ccb->tag = ATTR_ORDERED;
1517 		break;
1518 	case MSG_SIMPLE_Q_TAG:
1519 		ccb->tag = ATTR_SIMPLE;
1520 		break;
1521 	case MSG_HEAD_OF_Q_TAG:
1522 		ccb->tag = ATTR_HEAD_OF_QUEUE;
1523 		break;
1524 	default:
1525 		ccb->tag = 0;
1526 		break;
1527 	}
1528 
1529 #ifdef LUN_1
1530 	ccb->lun += 0x1000000000000LL;
1531 	ccb->cmd[1] += 0x10;
1532 #endif
1533 	send_command(ccb, CCBDISP_SCSIPI, waitok, FALSE);
1534 }
1535 
1536 
1537 #ifndef ISCSI_MINIMAL
1538 /*
1539  * send_io_command:
1540  *    Handle a SCSI io command request from user space.
1541  *
1542  *    Parameter:
1543  *          session 	The session
1544  *          lun		    The LUN to use
1545  *          req			The SCSI request block
1546  *			immed		Immediate command if TRUE
1547  *			conn_id		Assign to this connection ID if nonzero
1548  */
1549 
1550 int
1551 send_io_command(session_t *session, uint64_t lun, scsireq_t *req,
1552 				bool immed, uint32_t conn_id)
1553 {
1554 	ccb_t *ccb;
1555 	connection_t *conn;
1556 	int rc;
1557 
1558 	DEB(9, ("IoCommand: lun=%x, datalen=%d, cmdlen=%d, immed=%d, cid=%d\n",
1559 			(int) lun, (int) req->datalen, (int) req->cmdlen, immed, conn_id));
1560 
1561 	conn = (conn_id) ? find_connection(session, conn_id)
1562 					 : assign_connection(session, TRUE);
1563 
1564 	if (conn == NULL || conn->terminating || conn->state != ST_FULL_FEATURE) {
1565 		DEBOUT(("io_command on dead connection (state = %d)\n",
1566 				(conn != NULL) ? conn->state : -1));
1567 		return ISCSI_STATUS_INVALID_CONNECTION_ID;
1568 	}
1569 
1570 	ccb = get_ccb(conn, TRUE);
1571 	if (ccb == NULL) {
1572 		DEBOUT(("No CCB in io_command\n"));
1573 		return ISCSI_STATUS_NO_RESOURCES;
1574 	}
1575 
1576 	ccb->data_in = (req->flags & SCCMD_READ) != 0;
1577 	ccb->data_len = (uint32_t) req->datalen;
1578 	ccb->data_ptr = req->databuf;
1579 
1580 	ccb->sense_len_req = req->senselen;
1581 	ccb->sense_ptr = &req->sense;
1582 
1583 	ccb->lun = lun;
1584 	ccb->cmd = (uint8_t *) req->cmd;
1585 	ccb->cmdlen = req->cmdlen;
1586 	DEBC(conn, 10, ("IoCommand: cmd[1] = %x, cmdlen = %d\n",
1587 			 ccb->cmd[1], ccb->cmdlen));
1588 
1589 	send_command(ccb, CCBDISP_WAIT, TRUE, immed);
1590 
1591 	rc = ccb->status;
1592 
1593 	req->senselen_used = ccb->sense_len_got;
1594 	req->datalen_used = req->datalen - ccb->residual;
1595 
1596 	free_ccb(ccb);
1597 
1598 	return rc;
1599 }
1600 #endif
1601 
1602 
1603 /*****************************************************************************
1604  * Timeout handlers
1605  *****************************************************************************/
1606 /*
1607  * connection_timeout:
1608  *    Handle prolonged silence on a connection by checking whether
1609  *    it's still alive.
1610  *    This has the side effect of discovering missing status or lost commands
1611  *    before those time out.
1612  *
1613  *    Parameter:
1614  *          conn     The connection
1615  */
1616 
1617 void
1618 connection_timeout(connection_t *conn)
1619 {
1620 
1621 	if (++conn->num_timeouts > MAX_CONN_TIMEOUTS)
1622 		handle_connection_error(conn, ISCSI_STATUS_TIMEOUT, NO_LOGOUT);
1623 	else {
1624 		if (conn->state == ST_FULL_FEATURE)
1625 			send_nop_out(conn, NULL);
1626 
1627 		connection_timeout_start(conn, CONNECTION_TIMEOUT);
1628 	}
1629 }
1630 
1631 /*
1632  * ccb_timeout:
1633  *    Handle timeout of a sent command.
1634  *
1635  *    Parameter:
1636  *          ccb      The CCB
1637  */
1638 
1639 void
1640 ccb_timeout(ccb_t *ccb)
1641 {
1642 	connection_t *conn = ccb->connection;
1643 
1644 	ccb->total_tries++;
1645 
1646 	DEBC(conn, 0, ("ccb_timeout: num=%d total=%d disp=%d\n",
1647 		ccb->num_timeouts+1, ccb->total_tries, ccb->disp));
1648 
1649 	if (++ccb->num_timeouts > MAX_CCB_TIMEOUTS ||
1650 		ccb->total_tries > MAX_CCB_TRIES ||
1651 		ccb->disp <= CCBDISP_FREE ||
1652 		!ccb->session->ErrorRecoveryLevel) {
1653 
1654 		wake_ccb(ccb, ISCSI_STATUS_TIMEOUT);
1655 		handle_connection_error(conn, ISCSI_STATUS_TIMEOUT, RECOVER_CONNECTION);
1656 	} else {
1657 		if (ccb->data_in && ccb->xfer_len < ccb->data_len) {
1658 			/* request resend of all missing data */
1659 			snack_missing(conn, ccb, SNACK_DATA_NAK, 0, 0);
1660 		} else {
1661 			/* request resend of all missing status */
1662 			snack_missing(conn, NULL, SNACK_STATUS_NAK, 0, 0);
1663 		}
1664 		ccb_timeout_start(ccb, COMMAND_TIMEOUT);
1665 	}
1666 }
1667 
1668