Home | History | Annotate | Line # | Download | only in iscsi
iscsi_globals.h revision 1.14
      1 /*	$NetBSD: iscsi_globals.h,v 1.14 2016/05/29 13:51:16 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 #ifndef _ISCSI_GLOBALS_H
     32 #define _ISCSI_GLOBALS_H
     33 
     34 /*#include "opt_ddb.h" */
     35 #define DDB 1
     36 
     37 /* Includes we need in all files */
     38 
     39 #include <sys/param.h>
     40 #include <sys/proc.h>
     41 #include <sys/conf.h>
     42 #include <sys/errno.h>
     43 #include <sys/malloc.h>
     44 #include <sys/scsiio.h>
     45 #include <sys/kernel.h>
     46 #include <sys/kthread.h>
     47 #include <sys/systm.h>
     48 #include <sys/device.h>
     49 
     50 #include <dev/scsipi/scsi_all.h>
     51 #include <dev/scsipi/scsipi_all.h>
     52 #include <dev/scsipi/scsiconf.h>
     53 #include <dev/scsipi/scsipiconf.h>
     54 
     55 #include "iscsi.h"
     56 #include "iscsi_pdu.h"
     57 #include "iscsi_ioctl.h"
     58 
     59 /* ------------------------ Code selection constants ------------------------ */
     60 
     61 #define ISCSI_DEBUG      0
     62 
     63 /* -------------------------  Global Constants  ----------------------------- */
     64 
     65 /* Version information */
     66 
     67 #define INTERFACE_VERSION	2
     68 #define VERSION_MAJOR		3
     69 #define VERSION_MINOR		1
     70 #define VERSION_STRING		"NetBSD iSCSI Software Initiator 20110407"
     71 
     72 /*
     73 Various checks are made that the expected cmd Serial Number is less than
     74 the actual command serial number. The extremely paranoid amongst us
     75 believe that a malicious iSCSI server could set this artificially low
     76 and effectively DoS a naive initiator. For this (possibly ludicrous)
     77 reason, I have added the two definitions below (agc, 2011/04/09). The
     78 throttling definition enables a check that the CmdSN is less than the
     79 ExpCmdSN in iscsi_send.c, and is enabled by default. The second definition
     80 effectively says "don't bother testing these values", and is used right
     81 now only in iscsi_send.c.
     82  */
     83 #define ISCSI_THROTTLING_ENABLED	1
     84 #define ISCSI_SERVER_TRUSTED	1
     85 
     86 /*
     87    NOTE: CCBS_PER_SESSION must not exceed 256 due to the way the ITT
     88    is constructed (it has the CCB index in its lower 8 bits). If it should ever
     89    be necessary to increase the number beyond that (which isn't expected),
     90    the corresponding ITT generation and extraction code must be rewritten.
     91 */
     92 #define CCBS_PER_SESSION      64	/* ToDo: Reasonable number?? */
     93 /*
     94    NOTE: PDUS_PER_CONNECTION is a number that could potentially impact
     95    performance if set too low, as a single command may use up a lot of PDUs for
     96    high values of First/MaxBurstLength and small values of
     97    MaxRecvDataSegmentLength of the target.
     98 */
     99 #define PDUS_PER_CONNECTION   128	/* ToDo: Reasonable number?? */
    100 
    101 /* max outstanding serial nums before we give up on the connection */
    102 #define SERNUM_BUFFER_LENGTH  (CCBS_PER_SESSION / 2)	/* ToDo: Reasonable?? */
    103 
    104 /* The RecvDataSegmentLength for Target->Initiator */
    105 #define DEFAULT_MaxRecvDataSegmentLength     (64*1024)
    106 
    107 /* Command timeout (reset on received PDU associated with the command's CCB) */
    108 #define COMMAND_TIMEOUT		(7 * hz) /* ToDo: Reasonable? (7 seconds) */
    109 #define MAX_CCB_TIMEOUTS	3		/* Max number of tries to resend or SNACK */
    110 #define MAX_CCB_TRIES		9      	/* Max number of total tries to recover */
    111 
    112 /* Connectionn timeout (reset on every valid received PDU) */
    113 #define CONNECTION_TIMEOUT       (2 * hz)	/* ToDo: Reasonable? (2 seconds) */
    114 #define CONNECTION_IDLE_TIMEOUT  (30 * hz)	/* Adjusted to Time2Retain/2 later */
    115 #define MAX_CONN_TIMEOUTS        4	/* Max number of tries to ping a target */
    116 
    117 /* Maximum attempts to recover connection */
    118 #define MAX_RECOVERY_ATTEMPTS	2	/* If two attempts don't work, something */
    119 									/* probably is seriously broken */
    120 
    121 /* PDU flags */
    122 
    123 #define PDUF_BUSY	0x01	/* PDU is being sent, don't re-send */
    124 #define PDUF_INQUEUE	0x02	/* PDU is in send queue */
    125 #define PDUF_PRIORITY	0x04	/* Insert PDU at head of queue */
    126 #define PDUF_NOUPDATE	0x10	/* Do not update PDU header/digest (test mode) */
    127 
    128 /* CCB Flags */
    129 
    130 #define CCBF_COMPLETE   0x0001	/* received status */
    131 #define CCBF_RESENT     0x0002	/* ccb was resent */
    132 #define CCBF_SENDTARGET 0x0004	/* SendTargets text request, not negotiation */
    133 #define CCBF_WAITING    0x0008	/* CCB is waiting for MaxCmdSN, wake it up */
    134 #define CCBF_GOT_RSP    0x0010	/* Got at least one response to this request */
    135 #define CCBF_REASSIGN   0x0020	/* Command can be reassigned */
    136 #define CCBF_OTHERCONN  0x0040	/* a logout for a different connection */
    137 #define CCBF_WAITQUEUE  0x0080	/* CCB is on waiting queue */
    138 #define CCBF_THROTTLING 0x0100	/* CCB is on throttling queue */
    139 
    140 /* ---------------------------  Global Types  ------------------------------- */
    141 
    142 /* Connection state */
    143 
    144 typedef enum {
    145 	/* first three correspond to CSG/NSG coding */
    146 	ST_SEC_NEG	= 0,	/* security negotiation phase */
    147 	ST_OP_NEG	= 1,	/* operational negotiation phase */
    148 	ST_FULL_FEATURE	= 3,	/* full feature phase */
    149 	/* rest is internal */
    150 	ST_WINDING_DOWN	= 4,	/* connection termination initiated, logging out */
    151 	ST_LOGOUT_SENT	= 5,	/* logout has been sent */
    152 	ST_SETTLING	= 6,	/* waiting for things to settle down */
    153 	ST_IDLE		= 7	/* connection is idle (ready to delete) */
    154 } conn_state_t;
    155 
    156 
    157 /* Logout state */
    158 
    159 typedef enum {
    160 	NOT_LOGGED_OUT,				/* Not logged out */
    161 	LOGOUT_SENT,				/* Logout was sent */
    162 	LOGOUT_SUCCESS,				/* Logout succeeded */
    163 	LOGOUT_FAILED				/* Logout failed */
    164 } logout_state_t;
    165 
    166 
    167 /* CCB Disposition */
    168 
    169 typedef enum {
    170 	CCBDISP_UNUSED,	/* 0 = In free pool */
    171 	CCBDISP_BUSY,	/* This CCB is busy, don't allow rx ops */
    172 	CCBDISP_NOWAIT,	/* Not waiting for anything */
    173 	CCBDISP_FREE,	/* Free this CCB when done */
    174 	CCBDISP_WAIT,	/* Calling thread is waiting for completion */
    175 	CCBDISP_SCSIPI,	/* Call scsipi_done when operation completes */
    176 	CCBDISP_DEFER	/* Defer waiting until all PDUs have been queued */
    177 } ccb_disp_t;
    178 
    179 
    180 /* PDU Disposition */
    181 
    182 typedef enum {
    183 	PDUDISP_UNUSED,		/* 0 = In free pool */
    184 	PDUDISP_FREE,		/* Free this PDU when done */
    185 	PDUDISP_WAIT		/* Waiting for acknowledge */
    186 } pdu_disp_t;
    187 
    188 
    189 typedef struct connection_s connection_t;
    190 typedef struct session_s session_t;
    191 typedef struct ccb_s ccb_t;
    192 typedef struct pdu_s pdu_t;
    193 
    194 /* the serial number management structure (a circular buffer) */
    195 
    196 typedef struct {
    197 	uint32_t	ExpSN;	/* ExpxxSN (Data or Stat) sent to the target */
    198 	uint32_t	next_sn; /* next_sn (== ExpSN if no ack is pending) */
    199 	int		top;	/* top of buffer (newest element) */
    200 	int		bottom;	/* bottom of buffer (oldest element) */
    201 	uint32_t	sernum[SERNUM_BUFFER_LENGTH];	/* the serial numbers */
    202 	bool		ack[SERNUM_BUFFER_LENGTH];	/* acknowledged? */
    203 } sernum_buffer_t;
    204 
    205 
    206 /*
    207    The per-PDU data structure.
    208 */
    209 
    210 struct pdu_s {
    211 	TAILQ_ENTRY(pdu_s)	chain;	/* freelist or wait list (or no list) */
    212 	TAILQ_ENTRY(pdu_s)	send_chain;
    213 				/* chaining PDUs waiting to be sent */
    214 	pdu_disp_t		disp; /* what to do with this pdu */
    215 	uint32_t		flags; 	/* various processing flags */
    216 	pdu_header_t		pdu; /* Buffer for PDU associated with cmd */
    217 	void			*temp_data; /* (free after use) */
    218 	uint32_t		temp_data_len;	/* size of temp data */
    219 
    220 	struct uio		uio; /* UIO structure */
    221 	struct iovec		io_vec[4];
    222 				/* Header + data + data-digest + padding */
    223 
    224 	struct uio		save_uio;
    225 				/* UIO structure save for retransmits */
    226 	struct iovec		save_iovec[4];
    227 				/* Header + data + data-digest + padding */
    228 	uint32_t		data_digest;
    229 				/* holds data digest if enabled */
    230 	ccb_t			*owner;
    231 				/* the ccb this PDU belongs to (if any) */
    232 	connection_t		*connection;
    233 				/* the connection this PDU belongs to */
    234 };
    235 
    236 
    237 /* the PDU list type */
    238 
    239 TAILQ_HEAD(pdu_list_s, pdu_s);
    240 typedef struct pdu_list_s pdu_list_t;
    241 
    242 /*
    243    The per-command data structure. Calling it ccb in correspondence
    244    to other HA drivers.
    245 */
    246 
    247 struct ccb_s {
    248 	TAILQ_ENTRY(ccb_s)	chain;
    249 	/* either freelist or waiting list (or no list) */
    250 
    251 	uint32_t		status; /* Status gets entered here */
    252 	ccb_disp_t		disp;	/* what to do with this ccb */
    253 
    254 	struct callout		timeout; /* To make sure it isn't lost */
    255 	TAILQ_ENTRY(ccb_s)	tchain;
    256 	int			num_timeouts;
    257 	/* How often we've sent out SNACK without answer */
    258 	int			total_tries;
    259 	/* How often we've tried to recover */
    260 
    261 	uint32_t		ITT;
    262 	/* task tag: ITT counter + sess id + CCB index */
    263 	sernum_buffer_t		DataSN_buf;
    264 	/* Received Data Seq nums (read ops only) */
    265 
    266 	void			*par;
    267 	/* misc. parameter for this request */
    268 	struct scsipi_xfer	*xs;
    269 	/* the scsipi_xfer for this cmd */
    270 
    271 	void			*temp_data;
    272 	/* to hold state (mainly during negotiation) */
    273 	void			*text_data;
    274 	/* holds accumulated text for continued PDUs */
    275 	uint32_t		text_len;
    276 	/* length of text data so far */
    277 
    278 	uint64_t		lun; /* LUN */
    279 	uint8_t			*cmd; /* SCSI command block */
    280 	uint16_t		cmdlen; /* SCSI command block length */
    281 	bool			data_in; /* if this is a read request */
    282 	uint8_t			*data_ptr; /* data pointer for read/write */
    283 	uint32_t		data_len; /* total data length */
    284 	uint32_t		xfer_len; /* data transferred on read */
    285 	uint32_t		residual; /* residual data size */
    286 
    287 	void			*sense_ptr; /* sense data pointer */
    288 	int			sense_len_req; /* requested sense data length */
    289 	int			sense_len_got; /* actual sense data length */
    290 
    291 	pdu_t			*pdu_waiting; /* PDU waiting to be ack'ed */
    292 	uint32_t		CmdSN; /* CmdSN associated with waiting PDU */
    293 
    294 	int			flags;
    295 	connection_t		*connection; /* connection for CCB */
    296 	session_t		*session; /* session for CCB */
    297 };
    298 
    299 
    300 /* the CCB list type */
    301 
    302 TAILQ_HEAD(ccb_list_s, ccb_s);
    303 typedef struct ccb_list_s ccb_list_t;
    304 
    305 
    306 /*
    307    Per connection data: the connection structure
    308 */
    309 struct connection_s {
    310 	TAILQ_ENTRY(connection_s)	connections;
    311 
    312 	kmutex_t			lock;
    313 	kcondvar_t			conn_cv;
    314 	kcondvar_t			ccb_cv;
    315 	kcondvar_t			idle_cv;
    316 
    317 	pdu_list_t			pdu_pool; /* the free PDU pool */
    318 
    319 	ccb_list_t			ccbs_waiting;
    320 					/* CCBs waiting for completion */
    321 
    322 	pdu_list_t			pdus_to_send;
    323 					/* the PDUs waiting to be sent */
    324 
    325 	sernum_buffer_t			StatSN_buf;
    326 					/* to keep track of received StatSNs */
    327 
    328 	uint32_t			max_transfer;
    329 		/* min(MaxRecvDataSegmentLength, MaxBurstLength) */
    330 	uint32_t			max_firstimmed;
    331 		/* 0 if InitialR2T=Yes, else
    332 		   min of (MaxRecvDataSegmentLength, FirstBurstLength) */
    333 	uint32_t			max_firstdata;
    334 		/* 0 if ImmediateData=No, else min of */
    335 		/* (MaxRecvDataSegmentLength, FirstBurstLength) */
    336 
    337 	uint32_t			MaxRecvDataSegmentLength;
    338 					/* Target's value */
    339 	uint32_t			Our_MaxRecvDataSegmentLength;
    340 					/* Our own value */
    341 	bool				HeaderDigest;	/* TRUE if doing CRC */
    342 	bool				DataDigest;	/* TRUE if doing CRC */
    343 	uint32_t			Time2Wait;
    344 					/* Negotiated default or logout value */
    345 	uint32_t			Time2Retain;
    346 					/* Negotiated default or logout value */
    347 
    348 	uint16_t			id;
    349 		/* connection ID (unique within session) */
    350 
    351 	conn_state_t			state; /* State of connection */
    352 
    353 	struct lwp			*threadobj;
    354 		/* proc/thread pointer of socket owner */
    355 	struct file			*sock;	/* the connection's socket */
    356 	session_t			*session;
    357 					/* back pointer to the owning session */
    358 
    359 	struct lwp			*rcvproc; /* receive thread */
    360 	struct lwp			*sendproc; /* send thread */
    361 
    362 	uint32_t			terminating;
    363 					/* if closing down: status */
    364 	int				recover; /* recovery count */
    365 		/* (reset on first successful data transfer) */
    366 	unsigned			usecount; /* number of active CCBs */
    367 
    368 	bool				destroy; /* conn will be destroyed */
    369 	bool				in_session;
    370 		/* if it's linked into the session list */
    371 	logout_state_t			loggedout;
    372 		/* status of logout (for recovery) */
    373 	struct callout			timeout;
    374 		/* Timeout for checking if connection is dead */
    375 	TAILQ_ENTRY(connection_s)	tchain;
    376 	int				num_timeouts;
    377 		/* How often we've sent out a NOP without answer */
    378 	uint32_t			idle_timeout_val;
    379 		/* Connection timeout value when idle */
    380 
    381 	iscsi_login_parameters_t	*login_par;
    382 					/* only valid during login */
    383 
    384 	pdu_t				pdu[PDUS_PER_CONNECTION]; /* PDUs */
    385 };
    386 
    387 /* the connection list type */
    388 
    389 TAILQ_HEAD(connection_list_s, connection_s);
    390 typedef struct connection_list_s connection_list_t;
    391 
    392 
    393 /*
    394    Per session data: the session structure
    395 */
    396 
    397 struct session_s {
    398 	/* Interface to child drivers.
    399 	   NOTE: sc_adapter MUST be the first field in this structure so we can
    400 	   easily get from adapter to session.
    401 	 */
    402 	struct scsipi_adapter	sc_adapter;
    403 	struct scsipi_channel	sc_channel;
    404 
    405 	device_t		child_dev;
    406 	/* the child we're associated with - (NULL if not mapped) */
    407 
    408 	/* local stuff */
    409 	TAILQ_ENTRY(session_s)	sessions;	/* the list of sessions */
    410 
    411 	kmutex_t		lock;
    412 	kcondvar_t		sess_cv;
    413 	kcondvar_t		ccb_cv;
    414 
    415 	ccb_list_t		ccb_pool;	/* The free CCB pool */
    416 	ccb_list_t		ccbs_throttled;
    417 				/* CCBs waiting for MaxCmdSN to increase */
    418 
    419 	uint16_t		id;	/* session ID (unique within driver) */
    420 	uint16_t		TSIH;	/* Target assigned session ID */
    421 
    422 	uint32_t		CmdSN;	 /* Current CmdSN */
    423 	uint32_t		ExpCmdSN; /* Current max ExpCmdSN received */
    424 	uint32_t		MaxCmdSN; /* Current MaxCmdSN */
    425 
    426 	/* negotiated values */
    427 	uint32_t		ErrorRecoveryLevel;
    428 	uint32_t		FirstBurstLength;
    429 	uint32_t		MaxBurstLength;
    430 	bool			ImmediateData;
    431 	bool			InitialR2T;
    432 	uint32_t		MaxOutstandingR2T;
    433 	uint32_t		MaxConnections;
    434 	uint32_t		DefaultTime2Wait;
    435 	uint32_t		DefaultTime2Retain;
    436 
    437 	iscsi_login_session_type_t login_type;	/* session type */
    438 
    439 	/* for send_targets requests */
    440 	uint8_t			*target_list;
    441 	uint32_t		target_list_len;
    442 
    443 	uint32_t		conn_id;	/* connection ID counter */
    444 
    445 	uint32_t		terminating;	/* if closing down: status */
    446 
    447 	uint32_t		active_connections;
    448 				/* currently active connections */
    449 	uint32_t		total_connections;
    450 	/* connections associated with this session (active or winding down) */
    451 	connection_list_t	conn_list;	/* the list of connections */
    452 	connection_t		*mru_connection;
    453 				/* the most recently used connection */
    454 
    455 	uint8_t			itt_id; 	/* counter for use in ITT */
    456 
    457 	ccb_t			ccb[CCBS_PER_SESSION];		/* CCBs */
    458 
    459 	char			tgtname[ISCSI_STRING_LENGTH + 1];
    460 				/* iSCSI target name */
    461 };
    462 
    463 /* the session list type */
    464 
    465 TAILQ_HEAD(session_list_s, session_s);
    466 typedef struct session_list_s session_list_t;
    467 
    468 
    469 /*
    470    Event notification structures
    471 */
    472 
    473 typedef struct event_s {
    474 	TAILQ_ENTRY(event_s)	link;		/* next event in queue */
    475 	iscsi_event_t		event_kind;	/* which event */
    476 	uint32_t		session_id;	/* affected session ID */
    477 	uint32_t		connection_id;	/* affected connection ID */
    478 	uint32_t		reason;		/* event reason */
    479 } event_t;
    480 
    481 /* the event list entry type */
    482 
    483 TAILQ_HEAD(event_list_s, event_s);
    484 typedef struct event_list_s event_list_t;
    485 
    486 
    487 typedef struct event_handler_s {
    488 	TAILQ_ENTRY(event_handler_s)	link;	/* next handler */
    489 	uint32_t			id;	/* unique ID */
    490 	event_list_t			events;	/* list of events pending */
    491 	iscsi_wait_event_parameters_t	*waiter; /* waiting parameter */
    492 	/* following to detect dead handlers */
    493 	event_t				*first_in_list;
    494 } event_handler_t;
    495 
    496 /* the event list entry type */
    497 
    498 TAILQ_HEAD(event_handler_list_s, event_handler_s);
    499 typedef struct event_handler_list_s event_handler_list_t;
    500 
    501 /* /dev/iscsi0 state */
    502 struct iscsifd {
    503 	TAILQ_ENTRY(iscsifd)		link;
    504 	device_t	dev;
    505 	int		unit;
    506 };
    507 
    508 /* -------------------------  Global Variables  ----------------------------- */
    509 
    510 /* In iscsi_main.c */
    511 
    512 extern struct cfattach iscsi_ca;		/* the device attach structure */
    513 
    514 extern session_list_t iscsi_sessions;		/* the list of sessions */
    515 extern bool iscsi_detaching;			/* signal to cleanup thread it should exit */
    516 extern uint32_t iscsi_num_send_threads;		/* the number of active send threads */
    517 
    518 extern uint8_t iscsi_InitiatorName[ISCSI_STRING_LENGTH];
    519 extern uint8_t iscsi_InitiatorAlias[ISCSI_STRING_LENGTH];
    520 extern login_isid_t iscsi_InitiatorISID;
    521 
    522 /* Debugging stuff */
    523 
    524 #ifndef DDB
    525 #define Debugger() panic("should call debugger here (iscsi.c)")
    526 #endif /* ! DDB */
    527 
    528 #ifdef ISCSI_DEBUG
    529 
    530 extern int iscsi_debug_level;	/* How much debug info to display */
    531 
    532 #define DEBOUT(x) printf x
    533 #define DEB(lev,x) { if (iscsi_debug_level >= lev) printf x ;}
    534 #define DEBC(conn,lev,x) { if (iscsi_debug_level >= lev) { printf("S%dC%d: ", \
    535 				conn ? conn->session->id : -1, \
    536 				conn ? conn->id : -1); printf x ;}}
    537 void iscsi_hexdump(void *buf, int len);
    538 
    539 #define STATIC static
    540 
    541 #else
    542 
    543 #define DEBOUT(x)
    544 #define DEB(lev,x)
    545 #define DEBC(conn,lev,x)
    546 #define iscsi_hexdump(a,b)
    547 
    548 #define STATIC static
    549 
    550 #endif
    551 
    552 /* Critical section macros */
    553 
    554 /* misc stuff */
    555 #define min(a, b) ((a) < (b)) ? (a) : (b)
    556 #define max(a, b) ((a) < (b)) ? (b) : (a)
    557 
    558 
    559 /*
    560    Convert unsigned int to 3-byte value (for DataSegmentLength field in PDU)
    561 */
    562 
    563 static __inline void
    564 hton3(uint32_t val, uint8_t *bytes)
    565 {
    566 	bytes[0] = (uint8_t) (val >> 16);
    567 	bytes[1] = (uint8_t) (val >> 8);
    568 	bytes[2] = (uint8_t) val;
    569 }
    570 
    571 /*
    572    Convert 3-byte value to unsigned int (for DataSegmentLength field in PDU)
    573 */
    574 
    575 static __inline uint32_t
    576 ntoh3(uint8_t *bytes)
    577 {
    578 	return (bytes[0] << 16) | (bytes[1] << 8) | bytes[2];
    579 }
    580 
    581 
    582 /*
    583  * Convert uint64 to network byte order (for LUN field in PDU)
    584 */
    585 static __inline uint64_t
    586 htonq(uint64_t x)
    587 {
    588 #if BYTE_ORDER == LITTLE_ENDIAN
    589 	uint8_t *s = (uint8_t *) & x;
    590 	return (uint64_t) ((uint64_t) s[0] << 56 | (uint64_t) s[1] << 48 |
    591 			(uint64_t) s[2] << 40 | (uint64_t) s[3] << 32 |
    592 			(uint64_t) s[4] << 24 | (uint64_t) s[5] << 16 |
    593 			(uint64_t) s[6] <<  8 | (uint64_t) s[7]);
    594 #else
    595 	return x;
    596 #endif
    597 }
    598 
    599 #define ntohq(x) htonq(x)
    600 
    601 /*
    602  * Serial number buffer empty?
    603 */
    604 
    605 static __inline bool
    606 sn_empty(sernum_buffer_t *buf)
    607 {
    608 	return buf->top == buf->bottom;
    609 }
    610 
    611 
    612 /*
    613  * Serial number compare
    614 */
    615 
    616 static __inline bool
    617 sn_a_lt_b(uint32_t a, uint32_t b)
    618 {
    619 	return (a < b && !((b - a) & 0x80000000)) ||
    620 	       (a > b && ((a - b) & 0x80000000));
    621 }
    622 
    623 static __inline bool
    624 sn_a_le_b(uint32_t a, uint32_t b)
    625 {
    626 	return (a <= b && !((b - a) & 0x80000000)) ||
    627 	       (a >= b && ((a - b) & 0x80000000));
    628 }
    629 
    630 /* in iscsi_ioctl.c */
    631 
    632 void iscsi_init_cleanup(void);
    633 void iscsi_destroy_cleanup(void);
    634 void iscsi_notify_cleanup(void);
    635 
    636 
    637 /* Parameter for logout is reason code in logout PDU, -1 for don't send logout */
    638 #define NO_LOGOUT          -1
    639 #define LOGOUT_SESSION     0
    640 #define LOGOUT_CONNECTION  1
    641 #define RECOVER_CONNECTION 2
    642 
    643 void add_event(iscsi_event_t, uint32_t, uint32_t, uint32_t);
    644 
    645 void kill_connection(connection_t *, uint32_t, int, bool);
    646 void kill_session(session_t *, uint32_t, int, bool);
    647 void kill_all_sessions(void);
    648 void handle_connection_error(connection_t *, uint32_t, int);
    649 void add_connection_cleanup(connection_t *);
    650 
    651 #ifndef ISCSI_MINIMAL
    652 uint32_t map_databuf(struct proc *, void **, uint32_t);
    653 void unmap_databuf(struct proc *, void *, uint32_t);
    654 #endif
    655 int iscsiioctl(struct file *, u_long, void *);
    656 
    657 session_t *find_session(uint32_t);
    658 connection_t *find_connection(session_t *, uint32_t);
    659 
    660 
    661 /* in iscsi_main.c */
    662 
    663 /*void iscsiattach(void *); */
    664 int iscsidetach(device_t, int);
    665 
    666 void iscsi_done(ccb_t *);
    667 int map_session(session_t *, device_t);
    668 int unmap_session(session_t *);
    669 
    670 /* in iscsi_send.c */
    671 
    672 void iscsi_send_thread(void *);
    673 
    674 connection_t *assign_connection(session_t *session, bool waitok);
    675 void resend_pdu(ccb_t *);
    676 int send_login(connection_t *);
    677 int send_logout(connection_t *, connection_t *, int, bool);
    678 int send_data_out(connection_t *, pdu_t *, ccb_t *, ccb_disp_t, bool);
    679 void send_run_xfer(session_t *, struct scsipi_xfer *);
    680 int send_send_targets(session_t *, uint8_t *);
    681 int send_task_management(connection_t *, ccb_t *, struct scsipi_xfer *, int);
    682 
    683 void negotiate_login(connection_t *, pdu_t *, ccb_t *);
    684 void acknowledge_text(connection_t *, pdu_t *, ccb_t *);
    685 void start_text_negotiation(connection_t *);
    686 void negotiate_text(connection_t *, pdu_t *, ccb_t *);
    687 int send_nop_out(connection_t *, pdu_t *);
    688 void snack_missing(connection_t *, ccb_t *, uint8_t, uint32_t, uint32_t);
    689 void send_snack(connection_t *, pdu_t *, ccb_t *, uint8_t);
    690 int send_send_targets(session_t *, uint8_t *);
    691 
    692 void send_command(ccb_t *, ccb_disp_t, bool, bool);
    693 #ifndef ISCSI_MINIMAL
    694 int send_io_command(session_t *, uint64_t, scsireq_t *, bool, uint32_t);
    695 #endif
    696 
    697 void connection_timeout_co(void *);
    698 void ccb_timeout_co(void *);
    699 
    700 void connection_timeout(connection_t *);
    701 void ccb_timeout(ccb_t *);
    702 
    703 /* in iscsi_rcv.c */
    704 
    705 void iscsi_rcv_thread(void *);
    706 
    707 /* in iscsi_utils.c */
    708 
    709 uint32_t gen_digest(void *, int);
    710 uint32_t gen_digest_2(void *, int, void *, int);
    711 
    712 void create_ccbs(session_t *);
    713 ccb_t *get_ccb(connection_t *, bool);
    714 void free_ccb(ccb_t *);
    715 void suspend_ccb(ccb_t *, bool);
    716 void throttle_ccb(ccb_t *, bool);
    717 void wake_ccb(ccb_t *, uint32_t);
    718 
    719 void create_pdus(connection_t *);
    720 pdu_t *get_pdu(connection_t *, bool);
    721 void free_pdu(pdu_t *);
    722 
    723 void init_sernum(sernum_buffer_t *);
    724 int add_sernum(sernum_buffer_t *, uint32_t);
    725 uint32_t ack_sernum(sernum_buffer_t *, uint32_t);
    726 
    727 /* in iscsi_text.c */
    728 
    729 int assemble_login_parameters(connection_t *, ccb_t *, pdu_t *);
    730 int assemble_security_parameters(connection_t *, ccb_t *, pdu_t *, pdu_t *);
    731 int assemble_negotiation_parameters(connection_t *, ccb_t *, pdu_t *, pdu_t *);
    732 int init_text_parameters(connection_t *, ccb_t *);
    733 int assemble_send_targets(pdu_t *, uint8_t *);
    734 void set_negotiated_parameters(ccb_t *);
    735 
    736 #endif /* !_ISCSI_GLOBALS_H */
    737