Home | History | Annotate | Line # | Download | only in iscsi
iscsi_send.c revision 1.29
      1 /*	$NetBSD: iscsi_send.c,v 1.29 2016/06/05 09:12:48 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 
    295 	sess = conn->session;
    296 	/* so cleanup thread knows there's someone left */
    297 	iscsi_num_send_threads++;
    298 
    299 	do {
    300 		mutex_enter(&conn->lock);
    301 		while (!conn->terminating) {
    302 			while (!conn->terminating &&
    303 				(pdu = TAILQ_FIRST(&conn->pdus_to_send)) != NULL) {
    304 				TAILQ_REMOVE(&conn->pdus_to_send, pdu, send_chain);
    305 				mutex_exit(&conn->lock);
    306 
    307 				/* update ExpStatSN here to avoid discontinuities */
    308 				/* and delays in updating target */
    309 				pdu->pdu.p.command.ExpStatSN = htonl(conn->StatSN_buf.ExpSN);
    310 
    311 				if (conn->HeaderDigest)
    312 					pdu->pdu.HeaderDigest = gen_digest(&pdu->pdu, BHS_SIZE);
    313 				DEBC(conn, 99, ("Transmitting PDU CmdSN = %u\n",
    314 				                ntohl(pdu->pdu.p.command.CmdSN)));
    315 				my_soo_write(conn, &pdu->uio);
    316 
    317 				mutex_enter(&conn->lock);
    318 				pdu->flags &= ~PDUF_INQUEUE;
    319 				if (pdu->disp > PDUDISP_FREE)
    320 					pdu->flags &= ~PDUF_BUSY;
    321 				mutex_exit(&conn->lock);
    322 
    323 				if (pdu->disp <= PDUDISP_FREE)
    324 					free_pdu(pdu);
    325 
    326 				mutex_enter(&conn->lock);
    327 			}
    328 
    329 			if (!conn->terminating)
    330 				cv_wait(&conn->conn_cv, &conn->lock);
    331 		}
    332 		mutex_exit(&conn->lock);
    333 
    334 		/* ------------------------------------------------------------------------
    335 		 *    Here this thread takes over cleanup of the terminating connection.
    336 		 * ------------------------------------------------------------------------
    337 		 */
    338 		connection_timeout_stop(conn);
    339 		conn->idle_timeout_val = CONNECTION_IDLE_TIMEOUT;
    340 
    341 		fp = conn->sock;
    342 
    343 		/*
    344 		 * We shutdown the socket here to force the receive
    345 		 * thread to wake up
    346 		 */
    347 		DEBC(conn, 1, ("Closing Socket %p\n", conn->sock));
    348 		solock(fp->f_socket);
    349 		soshutdown(fp->f_socket, SHUT_RDWR);
    350 		sounlock(fp->f_socket);
    351 
    352 		/* wake up any non-reassignable waiting CCBs */
    353 		TAILQ_FOREACH_SAFE(ccb, &conn->ccbs_waiting, chain, nccb) {
    354 			if (!(ccb->flags & CCBF_REASSIGN) || ccb->pdu_waiting == NULL) {
    355 				DEBC(conn, 1, ("Terminating CCB %p (t=%p)\n",
    356 					ccb,&ccb->timeout));
    357 				wake_ccb(ccb, conn->terminating);
    358 			} else {
    359 				ccb_timeout_stop(ccb);
    360 				ccb->num_timeouts = 0;
    361 			}
    362 		}
    363 
    364 		/* clean out anything left in send queue */
    365 		mutex_enter(&conn->lock);
    366 		while ((pdu = TAILQ_FIRST(&conn->pdus_to_send)) != NULL) {
    367 			TAILQ_REMOVE(&conn->pdus_to_send, pdu, send_chain);
    368 			pdu->flags &= ~(PDUF_INQUEUE | PDUF_BUSY);
    369 			mutex_exit(&conn->lock);
    370 			/* if it's not attached to a waiting CCB, free it */
    371 			if (pdu->owner == NULL ||
    372 			    pdu->owner->pdu_waiting != pdu) {
    373 				free_pdu(pdu);
    374 			}
    375 			mutex_enter(&conn->lock);
    376 		}
    377 		mutex_exit(&conn->lock);
    378 
    379 		/* If there's another connection available, transfer pending tasks */
    380 		if (sess->active_connections &&
    381 			TAILQ_FIRST(&conn->ccbs_waiting) != NULL) {
    382 
    383 			reassign_tasks(conn);
    384 		} else if (!conn->destroy && conn->Time2Wait) {
    385 			DEBC(conn, 1, ("Time2Wait\n"));
    386 			kpause("Time2Wait", false, conn->Time2Wait * hz, NULL);
    387 			DEBC(conn, 1, ("Time2Wait\n"));
    388 		}
    389 		/* notify event handlers of connection shutdown */
    390 		DEBC(conn, 1, ("%s\n", (conn->destroy) ? "TERMINATED" : "RECOVER"));
    391 		add_event((conn->destroy) ? ISCSI_CONNECTION_TERMINATED
    392 								  : ISCSI_RECOVER_CONNECTION,
    393 				  sess->id, conn->id, conn->terminating);
    394 
    395 		DEBC(conn, 1, ("Waiting for conn_idle\n"));
    396 		mutex_enter(&conn->lock);
    397 		if (!conn->destroy)
    398 			cv_timedwait(&conn->idle_cv, &conn->lock, CONNECTION_IDLE_TIMEOUT);
    399 		mutex_exit(&conn->lock);
    400 		DEBC(conn, 1, ("Waited for conn_idle, destroy = %d\n", conn->destroy));
    401 
    402 	} while (!conn->destroy);
    403 
    404 	/* wake up anyone waiting for a PDU */
    405 	cv_broadcast(&conn->conn_cv);
    406 
    407 	/* wake up any waiting CCBs */
    408 	while ((ccb = TAILQ_FIRST(&conn->ccbs_waiting)) != NULL) {
    409 		KASSERT(ccb->disp >= CCBDISP_NOWAIT);
    410 		wake_ccb(ccb, conn->terminating);
    411 		/* NOTE: wake_ccb will remove the CCB from the queue */
    412 	}
    413 
    414 	if (conn->in_session) {
    415 		conn->in_session = FALSE;
    416 		TAILQ_REMOVE(&sess->conn_list, conn, connections);
    417 		sess->mru_connection = TAILQ_FIRST(&sess->conn_list);
    418 	}
    419 
    420 	add_connection_cleanup(conn);
    421 
    422 	conn->sendproc = NULL;
    423 	DEBC(conn, 1, ("Send thread exits\n"));
    424 	iscsi_num_send_threads--;
    425 	kthread_exit(0);
    426 }
    427 
    428 
    429 /*
    430  * send_pdu:
    431  *    Enqueue a PDU to be sent, and handle its disposition as well as
    432  *    the disposition of its associated CCB.
    433  *
    434  *    Parameter:
    435  *          ccb      The associated CCB. May be NULL if cdisp is CCBDISP_NOWAIT
    436  *                   and pdisp is not PDUDISP_WAIT
    437  *          cdisp    The CCB's disposition
    438  *          pdu      The PDU
    439  *          pdisp    The PDU's disposition
    440  */
    441 
    442 STATIC void
    443 send_pdu(ccb_t *ccb, pdu_t *pdu, ccb_disp_t cdisp, pdu_disp_t pdisp)
    444 {
    445 	connection_t *conn = pdu->connection;
    446 	ccb_disp_t prev_cdisp = 0;
    447 
    448 	if (ccb != NULL) {
    449 		prev_cdisp = ccb->disp;
    450 		pdu->pdu.InitiatorTaskTag = ccb->ITT;
    451 		pdu->owner = ccb;
    452 		if (cdisp != CCBDISP_NOWAIT)
    453 			ccb->disp = cdisp;
    454 	}
    455 
    456 	pdu->disp = pdisp;
    457 
    458 	DEBC(conn, 10, ("Send_pdu: ccb=%p, pcd=%d, cdsp=%d, pdu=%p, pdsp=%d\n",
    459 			ccb, prev_cdisp, cdisp, pdu, pdisp));
    460 
    461 	mutex_enter(&conn->lock);
    462 	if (pdisp == PDUDISP_WAIT) {
    463 		ccb->pdu_waiting = pdu;
    464 
    465 		/* save UIO and IOVEC for retransmit */
    466 		pdu->save_uio = pdu->uio;
    467 		memcpy(pdu->save_iovec, pdu->io_vec, sizeof(pdu->save_iovec));
    468 
    469 		pdu->flags |= PDUF_BUSY;
    470 	}
    471 	/* Enqueue for sending */
    472 	pdu->flags |= PDUF_INQUEUE;
    473 
    474 	if (pdu->flags & PDUF_PRIORITY)
    475 		TAILQ_INSERT_HEAD(&conn->pdus_to_send, pdu, send_chain);
    476 	else
    477 		TAILQ_INSERT_TAIL(&conn->pdus_to_send, pdu, send_chain);
    478 	mutex_exit(&conn->lock);
    479 
    480 	cv_broadcast(&conn->conn_cv);
    481 
    482 	if (cdisp != CCBDISP_NOWAIT) {
    483 		ccb_timeout_start(ccb, COMMAND_TIMEOUT);
    484 
    485 		if (prev_cdisp <= CCBDISP_NOWAIT)
    486 			suspend_ccb(ccb, TRUE);
    487 
    488 		mutex_enter(&conn->lock);
    489 		while (ccb->disp == CCBDISP_WAIT) {
    490 			DEBC(conn, 15, ("Send_pdu: ccb=%p cdisp=%d waiting\n",
    491 				ccb, ccb->disp));
    492 			cv_wait(&conn->ccb_cv, &conn->lock);
    493 			DEBC(conn, 15, ("Send_pdu: ccb=%p cdisp=%d returned\n",
    494 				ccb, ccb->disp));
    495 		}
    496 		mutex_exit(&conn->lock);
    497 	}
    498 }
    499 
    500 
    501 /*
    502  * resend_pdu:
    503  *    Re-Enqueue a PDU that has apparently gotten lost.
    504  *
    505  *    Parameter:
    506  *          ccb      The associated CCB.
    507  */
    508 
    509 void
    510 resend_pdu(ccb_t *ccb)
    511 {
    512 	connection_t *conn = ccb->connection;
    513 	pdu_t *pdu = ccb->pdu_waiting;
    514 
    515 	mutex_enter(&conn->lock);
    516 	if (pdu == NULL || (pdu->flags & PDUF_BUSY)) {
    517 		mutex_exit(&conn->lock);
    518 		return;
    519 	}
    520 	pdu->flags |= PDUF_BUSY;
    521 	mutex_exit(&conn->lock);
    522 
    523 	/* restore UIO and IOVEC */
    524 	pdu->uio = pdu->save_uio;
    525 	memcpy(pdu->io_vec, pdu->save_iovec, sizeof(pdu->io_vec));
    526 
    527 	DEBC(conn, 8, ("ReSend_pdu ccb=%p, pdu=%p\n", ccb, pdu));
    528 
    529 	mutex_enter(&conn->lock);
    530 	/* Enqueue for sending */
    531 	pdu->flags |= PDUF_INQUEUE;
    532 
    533 	if (pdu->flags & PDUF_PRIORITY) {
    534 		TAILQ_INSERT_HEAD(&conn->pdus_to_send, pdu, send_chain);
    535 	} else {
    536 		TAILQ_INSERT_TAIL(&conn->pdus_to_send, pdu, send_chain);
    537 	}
    538 	ccb_timeout_start(ccb, COMMAND_TIMEOUT);
    539 	mutex_exit(&conn->lock);
    540 
    541 	cv_broadcast(&conn->conn_cv);
    542 }
    543 
    544 
    545 /*
    546  * setup_tx_uio:
    547  *    Initialize the uio structure for sending, including header,
    548  *    data (if present), padding, and Data Digest.
    549  *    Header Digest is generated in send thread.
    550  *
    551  *    Parameter:
    552  *          pdu      The PDU
    553  *          dsl      The Data Segment Length
    554  *          data     The data pointer
    555  *          read     TRUE if this is a read operation
    556  */
    557 
    558 STATIC void
    559 setup_tx_uio(pdu_t *pdu, uint32_t dsl, void *data, bool read)
    560 {
    561 	static uint8_t pad_bytes[4] = { 0 };
    562 	struct uio *uio;
    563 	int i, pad, hlen;
    564 	connection_t *conn = pdu->connection;
    565 
    566 	DEB(99, ("SetupTxUio: dlen = %d, dptr: %p, read: %d\n",
    567 			 dsl, data, read));
    568 
    569 	if (!read && dsl) {
    570 		hton3(dsl, pdu->pdu.DataSegmentLength);
    571 	}
    572 	hlen = (conn->HeaderDigest) ? BHS_SIZE + 4 : BHS_SIZE;
    573 
    574 	pdu->io_vec[0].iov_base = &pdu->pdu;
    575 	pdu->io_vec[0].iov_len = hlen;
    576 
    577 	uio = &pdu->uio;
    578 
    579 	uio->uio_iov = pdu->io_vec;
    580 	uio->uio_iovcnt = 1;
    581 	uio->uio_rw = UIO_WRITE;
    582 	uio->uio_resid = hlen;
    583 	UIO_SETUP_SYSSPACE(uio);
    584 
    585 	if (!read && dsl) {
    586 		uio->uio_iovcnt++;
    587 		pdu->io_vec[1].iov_base = data;
    588 		pdu->io_vec[1].iov_len = dsl;
    589 		uio->uio_resid += dsl;
    590 
    591 		/* Pad to next multiple of 4 */
    592 		pad = uio->uio_resid & 0x03;
    593 		if (pad) {
    594 			i = uio->uio_iovcnt++;
    595 			pad = 4 - pad;
    596 			pdu->io_vec[i].iov_base = pad_bytes;
    597 			pdu->io_vec[i].iov_len = pad;
    598 			uio->uio_resid += pad;
    599 		}
    600 
    601 		if (conn->DataDigest) {
    602 			pdu->data_digest = gen_digest_2(data, dsl, pad_bytes, pad);
    603 			i = uio->uio_iovcnt++;
    604 			pdu->io_vec[i].iov_base = &pdu->data_digest;
    605 			pdu->io_vec[i].iov_len = 4;
    606 			uio->uio_resid += 4;
    607 		}
    608 	}
    609 }
    610 
    611 /*
    612  * init_login_pdu:
    613  *    Initialize the login PDU.
    614  *
    615  *    Parameter:
    616  *          conn     The connection
    617  *          ccb      The CCB
    618  *          pdu      The PDU
    619  */
    620 
    621 STATIC void
    622 init_login_pdu(connection_t *conn, ccb_t *ccb, pdu_t *ppdu, bool next)
    623 {
    624 	pdu_header_t *pdu = &ppdu->pdu;
    625 	login_isid_t *isid = (login_isid_t *) & pdu->LUN;
    626 	uint8_t c_phase;
    627 
    628 	pdu->Opcode = IOP_Login_Request | OP_IMMEDIATE;
    629 
    630 	mutex_enter(&conn->session->lock);
    631 	ccb->CmdSN = get_sernum(conn->session, false);
    632 	mutex_exit(&conn->session->lock);
    633 
    634 	if (next) {
    635 		c_phase = (pdu->Flags >> CSG_SHIFT) & SG_MASK;
    636 		pdu->Flags = FLAG_TRANSIT | (c_phase << CSG_SHIFT) |
    637 					 NEXT_PHASE(c_phase);
    638 	}
    639 
    640 	memcpy(isid, &iscsi_InitiatorISID, 6);
    641 	isid->TSIH = conn->session->TSIH;
    642 
    643 	pdu->p.login_req.CID = htons(conn->id);
    644 	pdu->p.login_req.CmdSN = htonl(ccb->CmdSN);
    645 }
    646 
    647 
    648 /*
    649  * negotiate_login:
    650  *    Control login negotiation.
    651  *
    652  *    Parameter:
    653  *          conn     The connection
    654  *          rx_pdu   The received login response PDU
    655  *          tx_ccb   The originally sent login CCB
    656  */
    657 
    658 void
    659 negotiate_login(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb)
    660 {
    661 	int rc;
    662 	bool next = TRUE;
    663 	pdu_t *tx_pdu;
    664 	uint8_t c_phase;
    665 
    666 	if (rx_pdu->pdu.Flags & FLAG_TRANSIT)
    667 		c_phase = rx_pdu->pdu.Flags & SG_MASK;
    668 	else
    669 		c_phase = (rx_pdu->pdu.Flags >> CSG_SHIFT) & SG_MASK;
    670 
    671 	DEB(99, ("NegotiateLogin: Flags=%x Phase=%x\n",
    672 			 rx_pdu->pdu.Flags, c_phase));
    673 
    674 	if (c_phase == SG_FULL_FEATURE_PHASE) {
    675 		session_t *sess = conn->session;
    676 
    677 		if (!sess->TSIH)
    678 			sess->TSIH = ((login_isid_t *) &rx_pdu->pdu.LUN)->TSIH;
    679 
    680 		if (rx_pdu->temp_data != NULL)
    681 			assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, NULL);
    682 
    683 		/* negotiated values are now valid */
    684 		set_negotiated_parameters(tx_ccb);
    685 
    686 		DEBC(conn, 5, ("Login Successful!\n"));
    687 		wake_ccb(tx_ccb, ISCSI_STATUS_SUCCESS);
    688 		return;
    689 	}
    690 
    691 	tx_pdu = get_pdu(conn, TRUE);
    692 	if (tx_pdu == NULL)
    693 		return;
    694 
    695 	tx_pdu->pdu.Flags = c_phase << CSG_SHIFT;
    696 
    697 	switch (c_phase) {
    698 	case SG_SECURITY_NEGOTIATION:
    699 		rc = assemble_security_parameters(conn, tx_ccb, rx_pdu, tx_pdu);
    700 		if (rc < 0)
    701 			next = FALSE;
    702 		break;
    703 
    704 	case SG_LOGIN_OPERATIONAL_NEGOTIATION:
    705 		rc = assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, tx_pdu);
    706 		break;
    707 
    708 	default:
    709 		DEBOUT(("Invalid phase %x in negotiate_login\n", c_phase));
    710 		rc = ISCSI_STATUS_TARGET_ERROR;
    711 		break;
    712 	}
    713 
    714 	if (rc > 0) {
    715 		wake_ccb(tx_ccb, rc);
    716 		free_pdu(tx_pdu);
    717 	} else {
    718 		init_login_pdu(conn, tx_ccb, tx_pdu, next);
    719 		setup_tx_uio(tx_pdu, tx_pdu->temp_data_len, tx_pdu->temp_data, FALSE);
    720 		send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE);
    721 	}
    722 }
    723 
    724 
    725 /*
    726  * init_text_pdu:
    727  *    Initialize the text PDU.
    728  *
    729  *    Parameter:
    730  *          conn     The connection
    731  *          ccb      The transmit CCB
    732  *          ppdu     The transmit PDU
    733  *          rx_pdu   The received PDU if this is an unsolicited negotiation
    734  */
    735 
    736 STATIC void
    737 init_text_pdu(connection_t *conn, ccb_t *ccb, pdu_t *ppdu, pdu_t *rx_pdu)
    738 {
    739 	pdu_header_t *pdu = &ppdu->pdu;
    740 
    741 	pdu->Opcode = IOP_Text_Request | OP_IMMEDIATE;
    742 	pdu->Flags = FLAG_FINAL;
    743 
    744 	mutex_enter(&conn->session->lock);
    745 	ccb->CmdSN = get_sernum(conn->session, false);
    746 	mutex_exit(&conn->session->lock);
    747 
    748 	if (rx_pdu != NULL) {
    749 		pdu->p.text_req.TargetTransferTag =
    750 			rx_pdu->pdu.p.text_rsp.TargetTransferTag;
    751 		pdu->LUN = rx_pdu->pdu.LUN;
    752 	} else
    753 		pdu->p.text_req.TargetTransferTag = 0xffffffff;
    754 
    755 	pdu->p.text_req.CmdSN = htonl(ccb->CmdSN);
    756 }
    757 
    758 
    759 /*
    760  * acknowledge_text:
    761  *    Acknowledge a continued login or text response.
    762  *
    763  *    Parameter:
    764  *          conn     The connection
    765  *          rx_pdu   The received login/text response PDU
    766  *          tx_ccb   The originally sent login/text request CCB
    767  */
    768 
    769 void
    770 acknowledge_text(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb)
    771 {
    772 	pdu_t *tx_pdu;
    773 
    774 	tx_pdu = get_pdu(conn, TRUE);
    775 	if (tx_pdu == NULL)
    776 		return;
    777 
    778 	if (rx_pdu != NULL &&
    779 		(rx_pdu->pdu.Opcode & OPCODE_MASK) == IOP_Login_Request)
    780 		init_login_pdu(conn, tx_ccb, tx_pdu, FALSE);
    781 	else
    782 		init_text_pdu(conn, tx_ccb, tx_pdu, rx_pdu);
    783 
    784 	setup_tx_uio(tx_pdu, 0, NULL, FALSE);
    785 	send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE);
    786 }
    787 
    788 
    789 /*
    790  * start_text_negotiation:
    791  *    Handle target request to negotiate (via asynch event)
    792  *
    793  *    Parameter:
    794  *          conn     The connection
    795  */
    796 
    797 void
    798 start_text_negotiation(connection_t *conn)
    799 {
    800 	pdu_t *pdu;
    801 	ccb_t *ccb;
    802 
    803 	ccb = get_ccb(conn, TRUE);
    804 	if (ccb == NULL)
    805 		return;
    806 	pdu = get_pdu(conn, TRUE);
    807 	if (pdu == NULL) {
    808 		free_ccb(ccb);
    809 		return;
    810 	}
    811 
    812 	if (init_text_parameters(conn, ccb)) {
    813 		free_ccb(ccb);
    814 		free_pdu(pdu);
    815 		return;
    816 	}
    817 
    818 	init_text_pdu(conn, ccb, pdu, NULL);
    819 	setup_tx_uio(pdu, 0, NULL, FALSE);
    820 	send_pdu(ccb, pdu, CCBDISP_FREE, PDUDISP_WAIT);
    821 }
    822 
    823 
    824 /*
    825  * negotiate_text:
    826  *    Handle received text negotiation.
    827  *
    828  *    Parameter:
    829  *          conn     The connection
    830  *          rx_pdu   The received text response PDU
    831  *          tx_ccb   The original CCB
    832  */
    833 
    834 void
    835 negotiate_text(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb)
    836 {
    837 	int rc;
    838 	pdu_t *tx_pdu;
    839 
    840 	if (tx_ccb->flags & CCBF_SENDTARGET) {
    841 		if (!(rx_pdu->pdu.Flags & FLAG_FINAL)) {
    842 			handle_connection_error(conn, ISCSI_STATUS_PROTOCOL_ERROR,
    843 									LOGOUT_CONNECTION);
    844 			return;
    845 		}
    846 		/* transfer ownership of text to CCB */
    847 		tx_ccb->text_data = rx_pdu->temp_data;
    848 		tx_ccb->text_len = rx_pdu->temp_data_len;
    849 		rx_pdu->temp_data = NULL;
    850 		wake_ccb(tx_ccb, ISCSI_STATUS_SUCCESS);
    851 	} else {
    852 		if (!(rx_pdu->pdu.Flags & FLAG_FINAL))
    853 			tx_pdu = get_pdu(conn, TRUE);
    854 		else
    855 			tx_pdu = NULL;
    856 
    857 		rc = assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, tx_pdu);
    858 		if (rc) {
    859 			if (tx_pdu != NULL)
    860 				free_pdu(tx_pdu);
    861 
    862 			handle_connection_error(conn, rc, LOGOUT_CONNECTION);
    863 		} else if (tx_pdu != NULL) {
    864 			init_text_pdu(conn, tx_ccb, tx_pdu, rx_pdu);
    865 			setup_tx_uio(tx_pdu, tx_pdu->temp_data_len, tx_pdu->temp_data,
    866 						 FALSE);
    867 			send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE);
    868 		} else {
    869 			set_negotiated_parameters(tx_ccb);
    870 			wake_ccb(tx_ccb, ISCSI_STATUS_SUCCESS);
    871 		}
    872 	}
    873 }
    874 
    875 
    876 /*
    877  * send_send_targets:
    878  *    Send out a SendTargets text request.
    879  *    The result is stored in the fields in the session structure.
    880  *
    881  *    Parameter:
    882  *          session  The session
    883  *          key      The text key to use
    884  *
    885  *    Returns:    0 on success, else an error code.
    886  */
    887 
    888 int
    889 send_send_targets(session_t *session, uint8_t *key)
    890 {
    891 	ccb_t *ccb;
    892 	pdu_t *pdu;
    893 	int rc = 0;
    894 	connection_t *conn;
    895 
    896 	DEB(9, ("Send_send_targets\n"));
    897 
    898 	conn = assign_connection(session, TRUE);
    899 	if (conn == NULL || conn->terminating || conn->state != ST_FULL_FEATURE)
    900 		return (conn != NULL && conn->terminating) ? conn->terminating
    901 			: ISCSI_STATUS_CONNECTION_FAILED;
    902 
    903 	ccb = get_ccb(conn, TRUE);
    904 	if (ccb == NULL)
    905 		return conn->terminating;
    906 	pdu = get_pdu(conn, TRUE);
    907 	if (pdu == NULL) {
    908 		free_ccb(ccb);
    909 		return conn->terminating;
    910 	}
    911 
    912 	ccb->flags |= CCBF_SENDTARGET;
    913 
    914 	if ((rc = assemble_send_targets(pdu, key)) != 0) {
    915 		free_ccb(ccb);
    916 		free_pdu(pdu);
    917 		return rc;
    918 	}
    919 
    920 	init_text_pdu(conn, ccb, pdu, NULL);
    921 
    922 	setup_tx_uio(pdu, pdu->temp_data_len, pdu->temp_data, FALSE);
    923 	send_pdu(ccb, pdu, CCBDISP_WAIT, PDUDISP_WAIT);
    924 
    925 	rc = ccb->status;
    926 	if (!rc) {
    927 		/* transfer ownership of data */
    928 		session->target_list = ccb->text_data;
    929 		session->target_list_len = ccb->text_len;
    930 		ccb->text_data = NULL;
    931 	}
    932 	free_ccb(ccb);
    933 	return rc;
    934 }
    935 
    936 
    937 /*
    938  * send_nop_out:
    939  *    Send nop out request.
    940  *
    941  *    Parameter:
    942  *          conn     The connection
    943  *          rx_pdu   The received Nop-In PDU
    944  *
    945  *    Returns:    0 on success, else an error code.
    946  */
    947 
    948 int
    949 send_nop_out(connection_t *conn, pdu_t *rx_pdu)
    950 {
    951 	ccb_t *ccb;
    952 	pdu_t *ppdu;
    953 	pdu_header_t *pdu;
    954 
    955 	DEBC(conn, 10, ("Send NOP_Out rx_pdu=%p\n", rx_pdu));
    956 
    957 	if (rx_pdu != NULL) {
    958 		ccb = NULL;
    959 		ppdu = get_pdu(conn, TRUE);
    960 		if (ppdu == NULL)
    961 			return 1;
    962 	} else {
    963 		ccb = get_ccb(conn, FALSE);
    964 		if (ccb == NULL) {
    965 			DEBOUT(("Can't get CCB in send_nop_out\n"));
    966 			return 1;
    967 		}
    968 		ppdu = get_pdu(conn, FALSE);
    969 		if (ppdu == NULL) {
    970 			free_ccb(ccb);
    971 			DEBOUT(("Can't get PDU in send_nop_out\n"));
    972 			return 1;
    973 		}
    974 	}
    975 
    976 	pdu = &ppdu->pdu;
    977 	pdu->Flags = FLAG_FINAL;
    978 	pdu->Opcode = IOP_NOP_Out | OP_IMMEDIATE;
    979 
    980 	if (rx_pdu != NULL) {
    981 		pdu->p.nop_out.TargetTransferTag =
    982 			rx_pdu->pdu.p.nop_in.TargetTransferTag;
    983 		pdu->InitiatorTaskTag = rx_pdu->pdu.InitiatorTaskTag;
    984 		pdu->p.nop_out.CmdSN = htonl(conn->session->CmdSN);
    985 		pdu->LUN = rx_pdu->pdu.LUN;
    986 	} else {
    987 		pdu->p.nop_out.TargetTransferTag = 0xffffffff;
    988 		ccb->CmdSN = ccb->session->CmdSN;
    989 		pdu->p.nop_out.CmdSN = htonl(ccb->CmdSN);
    990 	}
    991 
    992 	setup_tx_uio(ppdu, 0, NULL, FALSE);
    993 	send_pdu(ccb, ppdu, (rx_pdu != NULL) ? CCBDISP_NOWAIT : CCBDISP_FREE,
    994 			 PDUDISP_FREE);
    995 	return 0;
    996 }
    997 
    998 
    999 /*
   1000  * snack_missing:
   1001  *    Send SNACK request for missing data.
   1002  *
   1003  *    Parameter:
   1004  *          conn     The connection
   1005  *          ccb      The task's CCB (for Data NAK only)
   1006  *          type     The SNACK type
   1007  *          BegRun   The BegRun field
   1008  *          RunLength   The RunLength field
   1009  */
   1010 
   1011 void
   1012 snack_missing(connection_t *conn, ccb_t *ccb, uint8_t type,
   1013 			  uint32_t BegRun, uint32_t RunLength)
   1014 {
   1015 	pdu_t *ppdu;
   1016 	pdu_header_t *pdu;
   1017 
   1018 	ppdu = get_pdu(conn, TRUE);
   1019 	if (ppdu == NULL)
   1020 		return;
   1021 	pdu = &ppdu->pdu;
   1022 	pdu->Opcode = IOP_SNACK_Request;
   1023 	pdu->Flags = FLAG_FINAL | type;
   1024 
   1025 	pdu->InitiatorTaskTag = (type == SNACK_DATA_NAK) ? ccb->ITT : 0xffffffff;
   1026 	pdu->p.snack.TargetTransferTag = 0xffffffff;
   1027 	pdu->p.snack.BegRun = htonl(BegRun);
   1028 	pdu->p.snack.RunLength = htonl(RunLength);
   1029 
   1030 	ppdu->flags = PDUF_PRIORITY;
   1031 
   1032 	setup_tx_uio(ppdu, 0, NULL, FALSE);
   1033 	send_pdu(NULL, ppdu, CCBDISP_NOWAIT, PDUDISP_FREE);
   1034 }
   1035 
   1036 
   1037 /*
   1038  * send_snack:
   1039  *    Send SNACK request.
   1040  *
   1041  *    Parameter:
   1042  *          conn     The connection
   1043  *          rx_pdu   The received data in PDU
   1044  *          tx_ccb   The original command CCB (required for Data ACK only)
   1045  *          type     The SNACK type
   1046  *
   1047  *    Returns:    0 on success, else an error code.
   1048  */
   1049 
   1050 void
   1051 send_snack(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb, uint8_t type)
   1052 {
   1053 	pdu_t *ppdu;
   1054 	pdu_header_t *pdu;
   1055 
   1056 	ppdu = get_pdu(conn, TRUE);
   1057 	if (ppdu == NULL)
   1058 		return;
   1059 	pdu = &ppdu->pdu;
   1060 	pdu->Opcode = IOP_SNACK_Request;
   1061 	pdu->Flags = FLAG_FINAL | type;
   1062 
   1063 	switch (type) {
   1064 	case SNACK_DATA_NAK:
   1065 		pdu->InitiatorTaskTag = rx_pdu->pdu.InitiatorTaskTag;
   1066 		pdu->p.snack.TargetTransferTag = 0xffffffff;
   1067 		pdu->p.snack.BegRun = rx_pdu->pdu.p.data_in.DataSN;
   1068 		pdu->p.snack.RunLength = htonl(1);
   1069 		break;
   1070 
   1071 	case SNACK_STATUS_NAK:
   1072 		pdu->InitiatorTaskTag = 0xffffffff;
   1073 		pdu->p.snack.TargetTransferTag = 0xffffffff;
   1074 		pdu->p.snack.BegRun = rx_pdu->pdu.p.response.StatSN;
   1075 		pdu->p.snack.RunLength = htonl(1);
   1076 		break;
   1077 
   1078 	case SNACK_DATA_ACK:
   1079 		pdu->InitiatorTaskTag = 0xffffffff;
   1080 		pdu->p.snack.TargetTransferTag =
   1081 			rx_pdu->pdu.p.data_in.TargetTransferTag;
   1082 		pdu->p.snack.BegRun = tx_ccb->DataSN_buf.ExpSN;
   1083 		pdu->p.snack.RunLength = 0;
   1084 		break;
   1085 
   1086 	default:
   1087 		DEBOUT(("Invalid type %d in send_snack\n", type));
   1088 		return;
   1089 	}
   1090 
   1091 	pdu->LUN = rx_pdu->pdu.LUN;
   1092 
   1093 	ppdu->flags = PDUF_PRIORITY;
   1094 
   1095 	setup_tx_uio(ppdu, 0, NULL, FALSE);
   1096 	send_pdu(NULL, ppdu, CCBDISP_NOWAIT, PDUDISP_FREE);
   1097 }
   1098 
   1099 
   1100 /*
   1101  * send_login:
   1102  *    Send login request.
   1103  *
   1104  *    Parameter:
   1105  *          conn     The connection
   1106  *          par      The login parameters (for negotiation)
   1107  *
   1108  *    Returns:       0 on success, else an error code.
   1109  */
   1110 
   1111 int
   1112 send_login(connection_t *conn)
   1113 {
   1114 	ccb_t *ccb;
   1115 	pdu_t *pdu;
   1116 	int rc;
   1117 
   1118 	DEBC(conn, 9, ("Send_login\n"));
   1119 	ccb = get_ccb(conn, TRUE);
   1120 	/* only if terminating (which couldn't possibly happen here, but...) */
   1121 	if (ccb == NULL)
   1122 		return conn->terminating;
   1123 	pdu = get_pdu(conn, TRUE);
   1124 	if (pdu == NULL) {
   1125 		free_ccb(ccb);
   1126 		return conn->terminating;
   1127 	}
   1128 
   1129 	if ((rc = assemble_login_parameters(conn, ccb, pdu)) <= 0) {
   1130 		init_login_pdu(conn, ccb, pdu, !rc);
   1131 		setup_tx_uio(pdu, pdu->temp_data_len, pdu->temp_data, FALSE);
   1132 		send_pdu(ccb, pdu, CCBDISP_WAIT, PDUDISP_FREE);
   1133 		rc = ccb->status;
   1134 	} else {
   1135 		free_pdu(pdu);
   1136 	}
   1137 	free_ccb(ccb);
   1138 	return rc;
   1139 }
   1140 
   1141 
   1142 /*
   1143  * send_logout:
   1144  *    Send logout request.
   1145  *	  NOTE: This function does not wait for the logout to complete.
   1146  *
   1147  *    Parameter:
   1148  *          conn	The connection
   1149  *			refconn	The referenced connection
   1150  *			reason	The reason code
   1151  *			wait	Wait for completion if TRUE
   1152  *
   1153  *    Returns:       0 on success (logout sent), else an error code.
   1154  */
   1155 
   1156 int
   1157 send_logout(connection_t *conn, connection_t *refconn, int reason,
   1158 			bool wait)
   1159 {
   1160 	ccb_t *ccb;
   1161 	pdu_t *ppdu;
   1162 	pdu_header_t *pdu;
   1163 
   1164 	DEBC(conn, 5, ("Send_logout\n"));
   1165 	ccb = get_ccb(conn, TRUE);
   1166 	/* can only happen if terminating... */
   1167 	if (ccb == NULL)
   1168 		return conn->terminating;
   1169 	ppdu = get_pdu(conn, TRUE);
   1170 	if (ppdu == NULL) {
   1171 		free_ccb(ccb);
   1172 		return conn->terminating;
   1173 	}
   1174 
   1175 	pdu = &ppdu->pdu;
   1176 	pdu->Opcode = IOP_Logout_Request | OP_IMMEDIATE;
   1177 
   1178 	pdu->Flags = FLAG_FINAL | reason;
   1179 	ccb->CmdSN = conn->session->CmdSN;
   1180 	pdu->p.logout_req.CmdSN = htonl(ccb->CmdSN);
   1181 	if (reason > 0)
   1182 		pdu->p.logout_req.CID = htons(refconn->id);
   1183 
   1184 	ccb->par = refconn;
   1185 	if (refconn != conn) {
   1186 		ccb->flags |= CCBF_OTHERCONN;
   1187 	} else {
   1188 		conn->state = ST_LOGOUT_SENT;
   1189 		conn->loggedout = LOGOUT_SENT;
   1190 	}
   1191 
   1192 	setup_tx_uio(ppdu, 0, NULL, FALSE);
   1193 
   1194 	send_pdu(ccb, ppdu, (wait) ? CCBDISP_WAIT : CCBDISP_FREE, PDUDISP_FREE);
   1195 
   1196 	if (wait) {
   1197 		int rc = ccb->status;
   1198 		free_ccb (ccb);
   1199 		return rc;
   1200 	}
   1201 	return 0;
   1202 }
   1203 
   1204 
   1205 /*
   1206  * send_task_management:
   1207  *    Send task management request.
   1208  *
   1209  *    Parameter:
   1210  *          conn     The connection
   1211  *          ref_ccb  The referenced command (NULL if none)
   1212  *          xs       The scsipi command structure (NULL if not a scsipi request)
   1213  *          function The function code
   1214  *
   1215  *    Returns:       0 on success, else an error code.
   1216  */
   1217 
   1218 int
   1219 send_task_management(connection_t *conn, ccb_t *ref_ccb, struct scsipi_xfer *xs,
   1220 					 int function)
   1221 {
   1222 	ccb_t *ccb;
   1223 	pdu_t *ppdu;
   1224 	pdu_header_t *pdu;
   1225 
   1226 	DEBC(conn, 5, ("Send_task_management, ref_ccb=%p, func = %d\n",
   1227 			ref_ccb, function));
   1228 
   1229 	if (function == TASK_REASSIGN && conn->session->ErrorRecoveryLevel < 2)
   1230 		return ISCSI_STATUS_CANT_REASSIGN;
   1231 
   1232 	ccb = get_ccb(conn, xs == NULL);
   1233 	/* can only happen if terminating... */
   1234 	if (ccb == NULL)
   1235 		return conn->terminating;
   1236 	ppdu = get_pdu(conn, xs == NULL);
   1237 	if (ppdu == NULL) {
   1238 		free_ccb(ccb);
   1239 		return conn->terminating;
   1240 	}
   1241 
   1242 	ccb->xs = xs;
   1243 
   1244 	pdu = &ppdu->pdu;
   1245 	pdu->Opcode = IOP_SCSI_Task_Management | OP_IMMEDIATE;
   1246 	pdu->Flags = FLAG_FINAL | function;
   1247 
   1248 	ccb->CmdSN = conn->session->CmdSN;
   1249 	pdu->p.task_req.CmdSN = htonl(ccb->CmdSN);
   1250 
   1251 	if (ref_ccb != NULL) {
   1252 		pdu->p.task_req.ReferencedTaskTag = ref_ccb->ITT;
   1253 		pdu->p.task_req.RefCmdSN = htonl(ref_ccb->CmdSN);
   1254 		pdu->p.task_req.ExpDataSN = htonl(ref_ccb->DataSN_buf.ExpSN);
   1255 	} else
   1256 		pdu->p.task_req.ReferencedTaskTag = 0xffffffff;
   1257 
   1258 	ppdu->flags |= PDUF_PRIORITY;
   1259 
   1260 	setup_tx_uio(ppdu, 0, NULL, FALSE);
   1261 	send_pdu(ccb, ppdu, (xs) ? CCBDISP_SCSIPI : CCBDISP_WAIT, PDUDISP_FREE);
   1262 
   1263 	if (xs == NULL) {
   1264 		int rc = ccb->status;
   1265 		free_ccb(ccb);
   1266 		return rc;
   1267 	}
   1268 	return 0;
   1269 }
   1270 
   1271 
   1272 /*
   1273  * send_data_out:
   1274  *    Send data to target in response to an R2T or as unsolicited data.
   1275  *
   1276  *    Parameter:
   1277  *          conn     The connection
   1278  *          rx_pdu   The received R2T PDU (NULL if unsolicited)
   1279  *          tx_ccb   The originally sent command CCB
   1280  *          waitok   Whether it's OK to wait for an available PDU or not
   1281  */
   1282 
   1283 int
   1284 send_data_out(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb,
   1285 			  ccb_disp_t disp, bool waitok)
   1286 {
   1287 	pdu_header_t *pdu;
   1288 	uint32_t totlen, len, offs, sn;
   1289 	pdu_t *tx_pdu;
   1290 
   1291 	KASSERT(conn->max_transfer != 0);
   1292 
   1293 	if (rx_pdu) {
   1294 		offs = ntohl(rx_pdu->pdu.p.r2t.BufferOffset);
   1295 		totlen = ntohl(rx_pdu->pdu.p.r2t.DesiredDataTransferLength);
   1296 	} else {
   1297 		offs = conn->max_firstimmed;
   1298 		totlen = min(conn->max_firstdata - offs, tx_ccb->data_len - offs);
   1299 	}
   1300 	sn = 0;
   1301 
   1302 	while (totlen) {
   1303 		len = min(totlen, conn->max_transfer);
   1304 
   1305 		tx_pdu = get_pdu(conn, waitok);
   1306 		if (tx_pdu == NULL) {
   1307 			DEBC(conn, 5, ("No PDU in send_data_out\n"));
   1308 
   1309 			tx_ccb->disp = disp;
   1310 			tx_ccb->status = ISCSI_STATUS_NO_RESOURCES;
   1311 			handle_connection_error(conn, ISCSI_STATUS_NO_RESOURCES, NO_LOGOUT);
   1312 
   1313 			return ISCSI_STATUS_NO_RESOURCES;
   1314 		}
   1315 
   1316 		totlen -= len;
   1317 		pdu = &tx_pdu->pdu;
   1318 		pdu->Opcode = IOP_SCSI_Data_out;
   1319 		if (!totlen)
   1320 			pdu->Flags = FLAG_FINAL;
   1321 
   1322 		if (rx_pdu != NULL)
   1323 			pdu->p.data_out.TargetTransferTag =
   1324 				rx_pdu->pdu.p.r2t.TargetTransferTag;
   1325 		else
   1326 			pdu->p.data_out.TargetTransferTag = 0xffffffff;
   1327 		pdu->p.data_out.BufferOffset = htonl(offs);
   1328 		pdu->p.data_out.DataSN = htonl(sn);
   1329 
   1330 		DEBC(conn, 10, ("Send DataOut: DataSN %d, len %d offs %x totlen %d\n",
   1331 				sn, len, offs, totlen));
   1332 
   1333 		setup_tx_uio(tx_pdu, len, tx_ccb->data_ptr + offs, FALSE);
   1334 
   1335 		send_pdu(tx_ccb, tx_pdu, (totlen) ? CCBDISP_NOWAIT : disp, PDUDISP_FREE);
   1336 
   1337 		sn++;
   1338 		offs += len;
   1339 	}
   1340 	return 0;
   1341 }
   1342 
   1343 
   1344 /*
   1345  * send_command:
   1346  *    Send a SCSI command request.
   1347  *
   1348  *    Parameter:
   1349  *          CCB      The CCB
   1350  *          disp     The CCB disposition
   1351  */
   1352 
   1353 void
   1354 send_command(ccb_t *ccb, ccb_disp_t disp, bool waitok, bool immed)
   1355 {
   1356 	uint32_t totlen, len;
   1357 	connection_t *conn = ccb->connection;
   1358 	session_t *sess = ccb->session;
   1359 	pdu_t *ppdu;
   1360 	pdu_header_t *pdu;
   1361 
   1362 	mutex_enter(&sess->lock);
   1363 	while (/*CONSTCOND*/ISCSI_THROTTLING_ENABLED &&
   1364 	    /*CONSTCOND*/!ISCSI_SERVER_TRUSTED &&
   1365 	    !sernum_in_window(sess)) {
   1366 
   1367 		ccb->disp = disp;
   1368 		if (waitok)
   1369 			ccb->flags |= CCBF_WAITING;
   1370 		throttle_ccb(ccb, TRUE);
   1371 
   1372 		if (!waitok) {
   1373 			mutex_exit(&sess->lock);
   1374 			DEBC(conn, 10, ("Throttling send_command, ccb = %p\n",ccb));
   1375 			return;
   1376 		}
   1377 
   1378 		DEBC(conn, 15, ("Wait send_command, ccb = %p\n",ccb));
   1379 		cv_wait(&sess->ccb_cv, &sess->lock);
   1380 		DEBC(conn, 15, ("Resuming send_command, ccb = %p\n",ccb));
   1381 
   1382 		throttle_ccb(ccb, FALSE);
   1383 		ccb->flags &= ~CCBF_WAITING;
   1384 	}
   1385 	mutex_exit(&sess->lock);
   1386 
   1387 	ppdu = get_pdu(conn, waitok);
   1388 	if (ppdu == NULL) {
   1389 		DEBOUT(("No PDU for send_command, ccb = %p\n",ccb));
   1390 		ccb->disp = disp;
   1391 		wake_ccb(ccb, ISCSI_STATUS_NO_RESOURCES);
   1392 		return;
   1393 	}
   1394 
   1395 	totlen = len = ccb->data_len;
   1396 
   1397 	pdu = &ppdu->pdu;
   1398 	pdu->LUN = htonq(ccb->lun);
   1399 	memcpy(pdu->p.command.SCSI_CDB, ccb->cmd, ccb->cmdlen);
   1400 	pdu->Opcode = IOP_SCSI_Command;
   1401 	if (immed)
   1402 		pdu->Opcode |= OP_IMMEDIATE;
   1403 	pdu->p.command.ExpectedDataTransferLength = htonl(totlen);
   1404 
   1405 	if (totlen) {
   1406 		if (ccb->data_in) {
   1407 			pdu->Flags = FLAG_READ;
   1408 			totlen = 0;
   1409 		} else {
   1410 			pdu->Flags = FLAG_WRITE;
   1411 			/* immediate data we can send */
   1412 			len = min(totlen, conn->max_firstimmed);
   1413 
   1414 			/* can we send more unsolicited data ? */
   1415 			totlen = conn->max_firstdata ? totlen - len : 0;
   1416 		}
   1417 	}
   1418 	if (!totlen)
   1419 		pdu->Flags |= FLAG_FINAL;
   1420 	pdu->Flags |= ccb->tag;
   1421 
   1422 	if (ccb->data_in)
   1423 		init_sernum(&ccb->DataSN_buf);
   1424 
   1425 	ccb->sense_len_got = 0;
   1426 	ccb->xfer_len = 0;
   1427 	ccb->residual = 0;
   1428 	ccb->flags |= CCBF_REASSIGN;
   1429 
   1430 	mutex_enter(&sess->lock);
   1431 	ccb->CmdSN = get_sernum(sess, !immed);
   1432 	mutex_exit(&sess->lock);
   1433 
   1434 	pdu->p.command.CmdSN = htonl(ccb->CmdSN);
   1435 
   1436 	DEBC(conn, 10, ("Send Command: CmdSN %d (%d), data_in %d, len %d, totlen %d\n",
   1437 			ccb->CmdSN, sess->MaxCmdSN, ccb->data_in, len, totlen));
   1438 
   1439 	setup_tx_uio(ppdu, len, ccb->data_ptr, ccb->data_in);
   1440 	send_pdu(ccb, ppdu, (totlen) ? CCBDISP_DEFER : disp, PDUDISP_WAIT);
   1441 
   1442 	if (totlen)
   1443 		send_data_out(conn, NULL, ccb, disp, waitok);
   1444 }
   1445 
   1446 
   1447 /*
   1448  * send_run_xfer:
   1449  *    Handle a SCSI command transfer request from scsipi.
   1450  *
   1451  *    Parameter:
   1452  *          session  The session
   1453  *          xs       The transfer parameters
   1454  */
   1455 
   1456 void
   1457 send_run_xfer(session_t *session, struct scsipi_xfer *xs)
   1458 {
   1459 	ccb_t *ccb;
   1460 	connection_t *conn;
   1461 	bool waitok;
   1462 
   1463 	waitok = !(xs->xs_control & XS_CTL_NOSLEEP);
   1464 
   1465 	DEB(10, ("RunXfer: flags=%x, data=%p, datalen=%d, resid=%d, cmdlen=%d, "
   1466 			"waitok=%d\n", xs->xs_control, xs->data, xs->datalen,
   1467 			xs->resid, xs->cmdlen, waitok));
   1468 
   1469 	conn = assign_connection(session, waitok);
   1470 
   1471 	if (conn == NULL || conn->terminating || conn->state != ST_FULL_FEATURE) {
   1472 		xs->error = XS_SELTIMEOUT;
   1473 		DEBC(conn, 10, ("run_xfer on dead connection\n"));
   1474 		scsipi_done(xs);
   1475 		return;
   1476 	}
   1477 
   1478 	if (xs->xs_control & XS_CTL_RESET) {
   1479 		if (send_task_management(conn, NULL, xs, TARGET_WARM_RESET)) {
   1480 			xs->error = XS_SELTIMEOUT;
   1481 			scsipi_done(xs);
   1482 		}
   1483 		return;
   1484 	}
   1485 
   1486 	ccb = get_ccb(conn, waitok);
   1487 	if (ccb == NULL) {
   1488 		xs->error = XS_BUSY;
   1489 		DEBC(conn, 5, ("No CCB in run_xfer, %d in use.\n", conn->usecount));
   1490 		scsipi_done(xs);
   1491 		return;
   1492 	}
   1493 	/* copy parameters into CCB for easier access */
   1494 	ccb->xs = xs;
   1495 
   1496 	ccb->data_in = (xs->xs_control & XS_CTL_DATA_IN) != 0;
   1497 	ccb->data_len = (uint32_t) xs->datalen;
   1498 	ccb->data_ptr = xs->data;
   1499 
   1500 	ccb->sense_len_req = sizeof(xs->sense.scsi_sense);
   1501 	ccb->sense_ptr = &xs->sense;
   1502 
   1503 	ccb->lun = ((uint64_t) (uint8_t) xs->xs_periph->periph_lun) << 48;
   1504 	ccb->cmd = (uint8_t *) xs->cmd;
   1505 	ccb->cmdlen = xs->cmdlen;
   1506 	DEB(10, ("RunXfer: Periph_lun = %d, cmd[1] = %x, cmdlen = %d\n",
   1507 			xs->xs_periph->periph_lun, ccb->cmd[1], xs->cmdlen));
   1508 
   1509 	ccb->ITT |= xs->xs_tag_id << 24;
   1510 	switch (xs->xs_tag_type) {
   1511 	case MSG_ORDERED_Q_TAG:
   1512 		ccb->tag = ATTR_ORDERED;
   1513 		break;
   1514 	case MSG_SIMPLE_Q_TAG:
   1515 		ccb->tag = ATTR_SIMPLE;
   1516 		break;
   1517 	case MSG_HEAD_OF_Q_TAG:
   1518 		ccb->tag = ATTR_HEAD_OF_QUEUE;
   1519 		break;
   1520 	default:
   1521 		ccb->tag = 0;
   1522 		break;
   1523 	}
   1524 
   1525 #ifdef LUN_1
   1526 	ccb->lun += 0x1000000000000LL;
   1527 	ccb->cmd[1] += 0x10;
   1528 #endif
   1529 	send_command(ccb, CCBDISP_SCSIPI, waitok, FALSE);
   1530 }
   1531 
   1532 
   1533 #ifndef ISCSI_MINIMAL
   1534 /*
   1535  * send_io_command:
   1536  *    Handle a SCSI io command request from user space.
   1537  *
   1538  *    Parameter:
   1539  *          session 	The session
   1540  *          lun		    The LUN to use
   1541  *          req			The SCSI request block
   1542  *			immed		Immediate command if TRUE
   1543  *			conn_id		Assign to this connection ID if nonzero
   1544  */
   1545 
   1546 int
   1547 send_io_command(session_t *session, uint64_t lun, scsireq_t *req,
   1548 				bool immed, uint32_t conn_id)
   1549 {
   1550 	ccb_t *ccb;
   1551 	connection_t *conn;
   1552 	int rc;
   1553 
   1554 	DEB(9, ("IoCommand: lun=%x, datalen=%d, cmdlen=%d, immed=%d, cid=%d\n",
   1555 			(int) lun, (int) req->datalen, (int) req->cmdlen, immed, conn_id));
   1556 
   1557 	conn = (conn_id) ? find_connection(session, conn_id)
   1558 					 : assign_connection(session, TRUE);
   1559 
   1560 	if (conn == NULL || conn->terminating || conn->state != ST_FULL_FEATURE) {
   1561 		DEBOUT(("io_command on dead connection (state = %d)\n",
   1562 				(conn != NULL) ? conn->state : -1));
   1563 		return ISCSI_STATUS_INVALID_CONNECTION_ID;
   1564 	}
   1565 
   1566 	ccb = get_ccb(conn, TRUE);
   1567 	if (ccb == NULL) {
   1568 		DEBOUT(("No CCB in io_command\n"));
   1569 		return ISCSI_STATUS_NO_RESOURCES;
   1570 	}
   1571 
   1572 	ccb->data_in = (req->flags & SCCMD_READ) != 0;
   1573 	ccb->data_len = (uint32_t) req->datalen;
   1574 	ccb->data_ptr = req->databuf;
   1575 
   1576 	ccb->sense_len_req = req->senselen;
   1577 	ccb->sense_ptr = &req->sense;
   1578 
   1579 	ccb->lun = lun;
   1580 	ccb->cmd = (uint8_t *) req->cmd;
   1581 	ccb->cmdlen = req->cmdlen;
   1582 	DEBC(conn, 10, ("IoCommand: cmd[1] = %x, cmdlen = %d\n",
   1583 			 ccb->cmd[1], ccb->cmdlen));
   1584 
   1585 	send_command(ccb, CCBDISP_WAIT, TRUE, immed);
   1586 
   1587 	rc = ccb->status;
   1588 
   1589 	req->senselen_used = ccb->sense_len_got;
   1590 	req->datalen_used = req->datalen - ccb->residual;
   1591 
   1592 	free_ccb(ccb);
   1593 
   1594 	return rc;
   1595 }
   1596 #endif
   1597 
   1598 
   1599 /*****************************************************************************
   1600  * Timeout handlers
   1601  *****************************************************************************/
   1602 /*
   1603  * connection_timeout:
   1604  *    Handle prolonged silence on a connection by checking whether
   1605  *    it's still alive.
   1606  *    This has the side effect of discovering missing status or lost commands
   1607  *    before those time out.
   1608  *
   1609  *    Parameter:
   1610  *          conn     The connection
   1611  */
   1612 
   1613 void
   1614 connection_timeout(connection_t *conn)
   1615 {
   1616 
   1617 	if (++conn->num_timeouts > MAX_CONN_TIMEOUTS)
   1618 		handle_connection_error(conn, ISCSI_STATUS_TIMEOUT, NO_LOGOUT);
   1619 	else {
   1620 		if (conn->state == ST_FULL_FEATURE)
   1621 			send_nop_out(conn, NULL);
   1622 
   1623 		connection_timeout_start(conn, CONNECTION_TIMEOUT);
   1624 	}
   1625 }
   1626 
   1627 /*
   1628  * ccb_timeout:
   1629  *    Handle timeout of a sent command.
   1630  *
   1631  *    Parameter:
   1632  *          ccb      The CCB
   1633  */
   1634 
   1635 void
   1636 ccb_timeout(ccb_t *ccb)
   1637 {
   1638 	connection_t *conn = ccb->connection;
   1639 
   1640 	ccb->total_tries++;
   1641 
   1642 	DEBC(conn, 0, ("ccb_timeout: num=%d total=%d disp=%d\n",
   1643 		ccb->num_timeouts+1, ccb->total_tries, ccb->disp));
   1644 
   1645 	if (++ccb->num_timeouts > MAX_CCB_TIMEOUTS ||
   1646 		ccb->total_tries > MAX_CCB_TRIES ||
   1647 		ccb->disp <= CCBDISP_FREE ||
   1648 		!ccb->session->ErrorRecoveryLevel) {
   1649 
   1650 		wake_ccb(ccb, ISCSI_STATUS_TIMEOUT);
   1651 		handle_connection_error(conn, ISCSI_STATUS_TIMEOUT, RECOVER_CONNECTION);
   1652 	} else {
   1653 		if (ccb->data_in && ccb->xfer_len < ccb->data_len) {
   1654 			/* request resend of all missing data */
   1655 			snack_missing(conn, ccb, SNACK_DATA_NAK, 0, 0);
   1656 		} else {
   1657 			/* request resend of all missing status */
   1658 			snack_missing(conn, NULL, SNACK_STATUS_NAK, 0, 0);
   1659 		}
   1660 		ccb_timeout_start(ccb, COMMAND_TIMEOUT);
   1661 	}
   1662 }
   1663 
   1664