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