Home | History | Annotate | Line # | Download | only in iscsi
iscsi_globals.h revision 1.17
      1 /*	$NetBSD: iscsi_globals.h,v 1.17 2016/06/05 04:48:17 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 /* Timeout state */
    189 
    190 typedef enum {
    191 	TOUT_NONE,		/* Initial */
    192 	TOUT_ARMED,		/* callout is scheduled */
    193 	TOUT_QUEUED,		/* put into timeout queue */
    194 	TOUT_BUSY		/* cleanup thread working */
    195 } tout_state_t;
    196 
    197 typedef struct connection_s connection_t;
    198 typedef struct session_s session_t;
    199 typedef struct ccb_s ccb_t;
    200 typedef struct pdu_s pdu_t;
    201 
    202 /* the serial number management structure (a circular buffer) */
    203 
    204 typedef struct {
    205 	uint32_t	ExpSN;	/* ExpxxSN (Data or Stat) sent to the target */
    206 	uint32_t	next_sn; /* next_sn (== ExpSN if no ack is pending) */
    207 	int		top;	/* top of buffer (newest element) */
    208 	int		bottom;	/* bottom of buffer (oldest element) */
    209 	uint32_t	sernum[SERNUM_BUFFER_LENGTH];	/* the serial numbers */
    210 	bool		ack[SERNUM_BUFFER_LENGTH];	/* acknowledged? */
    211 } sernum_buffer_t;
    212 
    213 
    214 /*
    215    The per-PDU data structure.
    216 */
    217 
    218 struct pdu_s {
    219 	TAILQ_ENTRY(pdu_s)	chain;	/* freelist or wait list (or no list) */
    220 	TAILQ_ENTRY(pdu_s)	send_chain;
    221 				/* chaining PDUs waiting to be sent */
    222 	pdu_disp_t		disp; /* what to do with this pdu */
    223 	uint32_t		flags; 	/* various processing flags */
    224 	pdu_header_t		pdu; /* Buffer for PDU associated with cmd */
    225 	void			*temp_data; /* (free after use) */
    226 	uint32_t		temp_data_len;	/* size of temp data */
    227 
    228 	struct uio		uio; /* UIO structure */
    229 	struct iovec		io_vec[4];
    230 				/* Header + data + data-digest + padding */
    231 
    232 	struct uio		save_uio;
    233 				/* UIO structure save for retransmits */
    234 	struct iovec		save_iovec[4];
    235 				/* Header + data + data-digest + padding */
    236 	uint32_t		data_digest;
    237 				/* holds data digest if enabled */
    238 	ccb_t			*owner;
    239 				/* the ccb this PDU belongs to (if any) */
    240 	connection_t		*connection;
    241 				/* the connection this PDU belongs to */
    242 };
    243 
    244 
    245 /* the PDU list type */
    246 
    247 TAILQ_HEAD(pdu_list_s, pdu_s);
    248 typedef struct pdu_list_s pdu_list_t;
    249 
    250 /*
    251    The per-command data structure. Calling it ccb in correspondence
    252    to other HA drivers.
    253 */
    254 
    255 struct ccb_s {
    256 	TAILQ_ENTRY(ccb_s)	chain;
    257 	/* either freelist or waiting list (or no list) */
    258 
    259 	uint32_t		status; /* Status gets entered here */
    260 	ccb_disp_t		disp;	/* what to do with this ccb */
    261 
    262 	struct callout		timeout; /* To make sure it isn't lost */
    263 	TAILQ_ENTRY(ccb_s)	tchain;
    264 	tout_state_t		timedout;
    265 	int			num_timeouts;
    266 	/* How often we've sent out SNACK without answer */
    267 	int			total_tries;
    268 	/* How often we've tried to recover */
    269 
    270 	uint32_t		ITT;
    271 	/* task tag: ITT counter + sess id + CCB index */
    272 	sernum_buffer_t		DataSN_buf;
    273 	/* Received Data Seq nums (read ops only) */
    274 
    275 	void			*par;
    276 	/* misc. parameter for this request */
    277 	struct scsipi_xfer	*xs;
    278 	/* the scsipi_xfer for this cmd */
    279 
    280 	void			*temp_data;
    281 	/* to hold state (mainly during negotiation) */
    282 	void			*text_data;
    283 	/* holds accumulated text for continued PDUs */
    284 	uint32_t		text_len;
    285 	/* length of text data so far */
    286 
    287 	uint64_t		lun; /* LUN */
    288 	uint8_t			*cmd; /* SCSI command block */
    289 	uint16_t		cmdlen; /* SCSI command block length */
    290 	bool			data_in; /* if this is a read request */
    291 	uint8_t			*data_ptr; /* data pointer for read/write */
    292 	uint32_t		data_len; /* total data length */
    293 	uint32_t		xfer_len; /* data transferred on read */
    294 	uint32_t		residual; /* residual data size */
    295 
    296 	void			*sense_ptr; /* sense data pointer */
    297 	int			sense_len_req; /* requested sense data length */
    298 	int			sense_len_got; /* actual sense data length */
    299 
    300 	pdu_t			*pdu_waiting; /* PDU waiting to be ack'ed */
    301 	volatile uint32_t	CmdSN; /* CmdSN associated with waiting PDU */
    302 
    303 	int			flags;
    304 	connection_t		*connection; /* connection for CCB */
    305 	session_t		*session; /* session for CCB */
    306 };
    307 
    308 
    309 /* the CCB list type */
    310 
    311 TAILQ_HEAD(ccb_list_s, ccb_s);
    312 typedef struct ccb_list_s ccb_list_t;
    313 
    314 
    315 /*
    316    Per connection data: the connection structure
    317 */
    318 struct connection_s {
    319 	TAILQ_ENTRY(connection_s)	connections;
    320 
    321 	kmutex_t			lock;
    322 	kcondvar_t			conn_cv;
    323 	kcondvar_t			ccb_cv;
    324 	kcondvar_t			idle_cv;
    325 
    326 	pdu_list_t			pdu_pool; /* the free PDU pool */
    327 
    328 	ccb_list_t			ccbs_waiting;
    329 					/* CCBs waiting for completion */
    330 
    331 	pdu_list_t			pdus_to_send;
    332 					/* the PDUs waiting to be sent */
    333 
    334 	sernum_buffer_t			StatSN_buf;
    335 					/* to keep track of received StatSNs */
    336 
    337 	uint32_t			max_transfer;
    338 		/* min(MaxRecvDataSegmentLength, MaxBurstLength) */
    339 	uint32_t			max_firstimmed;
    340 		/* 0 if InitialR2T=Yes, else
    341 		   min of (MaxRecvDataSegmentLength, FirstBurstLength) */
    342 	uint32_t			max_firstdata;
    343 		/* 0 if ImmediateData=No, else min of */
    344 		/* (MaxRecvDataSegmentLength, FirstBurstLength) */
    345 
    346 	uint32_t			MaxRecvDataSegmentLength;
    347 					/* Target's value */
    348 	uint32_t			Our_MaxRecvDataSegmentLength;
    349 					/* Our own value */
    350 	bool				HeaderDigest;	/* TRUE if doing CRC */
    351 	bool				DataDigest;	/* TRUE if doing CRC */
    352 	uint32_t			Time2Wait;
    353 					/* Negotiated default or logout value */
    354 	uint32_t			Time2Retain;
    355 					/* Negotiated default or logout value */
    356 
    357 	uint16_t			id;
    358 		/* connection ID (unique within session) */
    359 
    360 	conn_state_t			state; /* State of connection */
    361 
    362 	struct lwp			*threadobj;
    363 		/* proc/thread pointer of socket owner */
    364 	struct file			*sock;	/* the connection's socket */
    365 	session_t			*session;
    366 					/* back pointer to the owning session */
    367 
    368 	struct lwp			*rcvproc; /* receive thread */
    369 	struct lwp			*sendproc; /* send thread */
    370 
    371 	uint32_t			terminating;
    372 					/* if closing down: status */
    373 	int				recover; /* recovery count */
    374 		/* (reset on first successful data transfer) */
    375 	volatile unsigned		usecount; /* number of active CCBs */
    376 
    377 	bool				destroy; /* conn will be destroyed */
    378 	bool				in_session;
    379 		/* if it's linked into the session list */
    380 	logout_state_t			loggedout;
    381 		/* status of logout (for recovery) */
    382 	struct callout			timeout;
    383 		/* Timeout for checking if connection is dead */
    384 	TAILQ_ENTRY(connection_s)	tchain;
    385 	tout_state_t			timedout;
    386 	int				num_timeouts;
    387 		/* How often we've sent out a NOP without answer */
    388 	uint32_t			idle_timeout_val;
    389 		/* Connection timeout value when idle */
    390 
    391 	iscsi_login_parameters_t	*login_par;
    392 					/* only valid during login */
    393 
    394 	pdu_t				pdu[PDUS_PER_CONNECTION]; /* PDUs */
    395 };
    396 
    397 /* the connection list type */
    398 
    399 TAILQ_HEAD(connection_list_s, connection_s);
    400 typedef struct connection_list_s connection_list_t;
    401 
    402 
    403 /*
    404    Per session data: the session structure
    405 */
    406 
    407 struct session_s {
    408 	/* Interface to child drivers.
    409 	   NOTE: sc_adapter MUST be the first field in this structure so we can
    410 	   easily get from adapter to session.
    411 	 */
    412 	struct scsipi_adapter	sc_adapter;
    413 	struct scsipi_channel	sc_channel;
    414 
    415 	device_t		child_dev;
    416 	/* the child we're associated with - (NULL if not mapped) */
    417 
    418 	/* local stuff */
    419 	TAILQ_ENTRY(session_s)	sessions;	/* the list of sessions */
    420 
    421 	kmutex_t		lock;
    422 	kcondvar_t		sess_cv;
    423 	kcondvar_t		ccb_cv;
    424 
    425 	ccb_list_t		ccb_pool;	/* The free CCB pool */
    426 	ccb_list_t		ccbs_throttled;
    427 				/* CCBs waiting for MaxCmdSN to increase */
    428 
    429 	uint16_t		id;	/* session ID (unique within driver) */
    430 	uint16_t		TSIH;	/* Target assigned session ID */
    431 
    432 	uint32_t		CmdSN;	 /* Current CmdSN */
    433 	uint32_t		ExpCmdSN; /* Current max ExpCmdSN received */
    434 	uint32_t		MaxCmdSN; /* Current MaxCmdSN */
    435 
    436 	/* negotiated values */
    437 	uint32_t		ErrorRecoveryLevel;
    438 	uint32_t		FirstBurstLength;
    439 	uint32_t		MaxBurstLength;
    440 	bool			ImmediateData;
    441 	bool			InitialR2T;
    442 	uint32_t		MaxOutstandingR2T;
    443 	uint32_t		MaxConnections;
    444 	uint32_t		DefaultTime2Wait;
    445 	uint32_t		DefaultTime2Retain;
    446 
    447 	iscsi_login_session_type_t login_type;	/* session type */
    448 
    449 	/* for send_targets requests */
    450 	uint8_t			*target_list;
    451 	uint32_t		target_list_len;
    452 
    453 	uint32_t		conn_id;	/* connection ID counter */
    454 
    455 	uint32_t		terminating;	/* if closing down: status */
    456 
    457 	uint32_t		active_connections;
    458 				/* currently active connections */
    459 	uint32_t		total_connections;
    460 	/* connections associated with this session (active or winding down) */
    461 	connection_list_t	conn_list;	/* the list of connections */
    462 	connection_t		*mru_connection;
    463 				/* the most recently used connection */
    464 
    465 	uint8_t			itt_id; 	/* counter for use in ITT */
    466 
    467 	ccb_t			ccb[CCBS_PER_SESSION];		/* CCBs */
    468 
    469 	char			tgtname[ISCSI_STRING_LENGTH + 1];
    470 				/* iSCSI target name */
    471 };
    472 
    473 /* the session list type */
    474 
    475 TAILQ_HEAD(session_list_s, session_s);
    476 typedef struct session_list_s session_list_t;
    477 
    478 
    479 /*
    480    Event notification structures
    481 */
    482 
    483 typedef struct event_s {
    484 	TAILQ_ENTRY(event_s)	link;		/* next event in queue */
    485 	iscsi_event_t		event_kind;	/* which event */
    486 	uint32_t		session_id;	/* affected session ID */
    487 	uint32_t		connection_id;	/* affected connection ID */
    488 	uint32_t		reason;		/* event reason */
    489 } event_t;
    490 
    491 /* the event list entry type */
    492 
    493 TAILQ_HEAD(event_list_s, event_s);
    494 typedef struct event_list_s event_list_t;
    495 
    496 
    497 typedef struct event_handler_s {
    498 	TAILQ_ENTRY(event_handler_s)	link;	/* next handler */
    499 	uint32_t			id;	/* unique ID */
    500 	event_list_t			events;	/* list of events pending */
    501 	iscsi_wait_event_parameters_t	*waiter; /* waiting parameter */
    502 	/* following to detect dead handlers */
    503 	event_t				*first_in_list;
    504 } event_handler_t;
    505 
    506 /* the event list entry type */
    507 
    508 TAILQ_HEAD(event_handler_list_s, event_handler_s);
    509 typedef struct event_handler_list_s event_handler_list_t;
    510 
    511 /* /dev/iscsi0 state */
    512 struct iscsifd {
    513 	TAILQ_ENTRY(iscsifd)		link;
    514 	device_t	dev;
    515 	int		unit;
    516 };
    517 
    518 /* -------------------------  Global Variables  ----------------------------- */
    519 
    520 /* In iscsi_main.c */
    521 
    522 extern struct cfattach iscsi_ca;		/* the device attach structure */
    523 
    524 extern session_list_t iscsi_sessions;		/* the list of sessions */
    525 extern bool iscsi_detaching;			/* signal to cleanup thread it should exit */
    526 extern uint32_t iscsi_num_send_threads;		/* the number of active send threads */
    527 
    528 extern uint8_t iscsi_InitiatorName[ISCSI_STRING_LENGTH];
    529 extern uint8_t iscsi_InitiatorAlias[ISCSI_STRING_LENGTH];
    530 extern login_isid_t iscsi_InitiatorISID;
    531 
    532 /* Debugging stuff */
    533 
    534 #ifndef DDB
    535 #define Debugger() panic("should call debugger here (iscsi.c)")
    536 #endif /* ! DDB */
    537 
    538 #ifdef ISCSI_DEBUG
    539 
    540 extern int iscsi_debug_level;	/* How much debug info to display */
    541 
    542 #define DEBOUT(x) printf x
    543 #define DEB(lev,x) { if (iscsi_debug_level >= lev) printf x ;}
    544 #define DEBC(conn,lev,x) { if (iscsi_debug_level >= lev) { printf("S%dC%d: ", \
    545 				conn ? conn->session->id : -1, \
    546 				conn ? conn->id : -1); printf x ;}}
    547 void iscsi_hexdump(void *buf, int len);
    548 
    549 #define STATIC static
    550 
    551 #else
    552 
    553 #define DEBOUT(x)
    554 #define DEB(lev,x)
    555 #define DEBC(conn,lev,x)
    556 #define iscsi_hexdump(a,b)
    557 
    558 #define STATIC static
    559 
    560 #endif
    561 
    562 /* Critical section macros */
    563 
    564 /* misc stuff */
    565 #define min(a, b) ((a) < (b)) ? (a) : (b)
    566 #define max(a, b) ((a) < (b)) ? (b) : (a)
    567 
    568 
    569 /*
    570    Convert unsigned int to 3-byte value (for DataSegmentLength field in PDU)
    571 */
    572 
    573 static __inline void
    574 hton3(uint32_t val, uint8_t *bytes)
    575 {
    576 	bytes[0] = (uint8_t) (val >> 16);
    577 	bytes[1] = (uint8_t) (val >> 8);
    578 	bytes[2] = (uint8_t) val;
    579 }
    580 
    581 /*
    582    Convert 3-byte value to unsigned int (for DataSegmentLength field in PDU)
    583 */
    584 
    585 static __inline uint32_t
    586 ntoh3(uint8_t *bytes)
    587 {
    588 	return (bytes[0] << 16) | (bytes[1] << 8) | bytes[2];
    589 }
    590 
    591 
    592 /*
    593  * Convert uint64 to network byte order (for LUN field in PDU)
    594 */
    595 static __inline uint64_t
    596 htonq(uint64_t x)
    597 {
    598 #if BYTE_ORDER == LITTLE_ENDIAN
    599 	uint8_t *s = (uint8_t *) & x;
    600 	return (uint64_t) ((uint64_t) s[0] << 56 | (uint64_t) s[1] << 48 |
    601 			(uint64_t) s[2] << 40 | (uint64_t) s[3] << 32 |
    602 			(uint64_t) s[4] << 24 | (uint64_t) s[5] << 16 |
    603 			(uint64_t) s[6] <<  8 | (uint64_t) s[7]);
    604 #else
    605 	return x;
    606 #endif
    607 }
    608 
    609 #define ntohq(x) htonq(x)
    610 
    611 /*
    612  * Serial number buffer empty?
    613 */
    614 
    615 static __inline bool
    616 sn_empty(sernum_buffer_t *buf)
    617 {
    618 	return buf->top == buf->bottom;
    619 }
    620 
    621 
    622 /*
    623  * Serial number compare
    624 */
    625 
    626 static __inline bool
    627 sn_a_lt_b(uint32_t a, uint32_t b)
    628 {
    629 	return (a < b && !((b - a) & 0x80000000)) ||
    630 	       (a > b && ((a - b) & 0x80000000));
    631 }
    632 
    633 static __inline bool
    634 sn_a_le_b(uint32_t a, uint32_t b)
    635 {
    636 	return (a <= b && !((b - a) & 0x80000000)) ||
    637 	       (a >= b && ((a - b) & 0x80000000));
    638 }
    639 
    640 /* in iscsi_ioctl.c */
    641 
    642 void iscsi_init_cleanup(void);
    643 void iscsi_destroy_cleanup(void);
    644 void iscsi_notify_cleanup(void);
    645 
    646 
    647 /* Parameter for logout is reason code in logout PDU, -1 for don't send logout */
    648 #define NO_LOGOUT          -1
    649 #define LOGOUT_SESSION     0
    650 #define LOGOUT_CONNECTION  1
    651 #define RECOVER_CONNECTION 2
    652 
    653 void add_event(iscsi_event_t, uint32_t, uint32_t, uint32_t);
    654 
    655 void kill_connection(connection_t *, uint32_t, int, bool);
    656 void kill_session(session_t *, uint32_t, int, bool);
    657 void kill_all_sessions(void);
    658 void handle_connection_error(connection_t *, uint32_t, int);
    659 void add_connection_cleanup(connection_t *);
    660 
    661 #ifndef ISCSI_MINIMAL
    662 uint32_t map_databuf(struct proc *, void **, uint32_t);
    663 void unmap_databuf(struct proc *, void *, uint32_t);
    664 #endif
    665 int iscsiioctl(struct file *, u_long, void *);
    666 
    667 session_t *find_session(uint32_t);
    668 connection_t *find_connection(session_t *, uint32_t);
    669 
    670 
    671 /* in iscsi_main.c */
    672 
    673 /*void iscsiattach(void *); */
    674 int iscsidetach(device_t, int);
    675 
    676 void iscsi_done(ccb_t *);
    677 int map_session(session_t *, device_t);
    678 int unmap_session(session_t *);
    679 
    680 /* in iscsi_send.c */
    681 
    682 void iscsi_send_thread(void *);
    683 
    684 connection_t *assign_connection(session_t *session, bool waitok);
    685 void resend_pdu(ccb_t *);
    686 int send_login(connection_t *);
    687 int send_logout(connection_t *, connection_t *, int, bool);
    688 int send_data_out(connection_t *, pdu_t *, ccb_t *, ccb_disp_t, bool);
    689 void send_run_xfer(session_t *, struct scsipi_xfer *);
    690 int send_send_targets(session_t *, uint8_t *);
    691 int send_task_management(connection_t *, ccb_t *, struct scsipi_xfer *, int);
    692 
    693 void negotiate_login(connection_t *, pdu_t *, ccb_t *);
    694 void acknowledge_text(connection_t *, pdu_t *, ccb_t *);
    695 void start_text_negotiation(connection_t *);
    696 void negotiate_text(connection_t *, pdu_t *, ccb_t *);
    697 int send_nop_out(connection_t *, pdu_t *);
    698 void snack_missing(connection_t *, ccb_t *, uint8_t, uint32_t, uint32_t);
    699 void send_snack(connection_t *, pdu_t *, ccb_t *, uint8_t);
    700 int send_send_targets(session_t *, uint8_t *);
    701 
    702 void send_command(ccb_t *, ccb_disp_t, bool, bool);
    703 #ifndef ISCSI_MINIMAL
    704 int send_io_command(session_t *, uint64_t, scsireq_t *, bool, uint32_t);
    705 #endif
    706 
    707 void connection_timeout_co(void *);
    708 void ccb_timeout_co(void *);
    709 
    710 void connection_timeout(connection_t *);
    711 void connection_timeout_start(connection_t *, int);
    712 void connection_timeout_stop(connection_t *);
    713 void ccb_timeout(ccb_t *);
    714 void ccb_timeout_start(ccb_t *, int);
    715 void ccb_timeout_stop(ccb_t *);
    716 
    717 /* in iscsi_rcv.c */
    718 
    719 void iscsi_rcv_thread(void *);
    720 
    721 /* in iscsi_utils.c */
    722 
    723 uint32_t gen_digest(void *, int);
    724 uint32_t gen_digest_2(void *, int, void *, int);
    725 
    726 void create_ccbs(session_t *);
    727 ccb_t *get_ccb(connection_t *, bool);
    728 void free_ccb(ccb_t *);
    729 void suspend_ccb(ccb_t *, bool);
    730 void throttle_ccb(ccb_t *, bool);
    731 void wake_ccb(ccb_t *, uint32_t);
    732 
    733 void create_pdus(connection_t *);
    734 pdu_t *get_pdu(connection_t *, bool);
    735 void free_pdu(pdu_t *);
    736 
    737 void init_sernum(sernum_buffer_t *);
    738 int add_sernum(sernum_buffer_t *, uint32_t);
    739 uint32_t ack_sernum(sernum_buffer_t *, uint32_t);
    740 
    741 uint32_t get_sernum(session_t *, bool);
    742 int sernum_in_window(session_t *);
    743 
    744 /* in iscsi_text.c */
    745 
    746 int assemble_login_parameters(connection_t *, ccb_t *, pdu_t *);
    747 int assemble_security_parameters(connection_t *, ccb_t *, pdu_t *, pdu_t *);
    748 int assemble_negotiation_parameters(connection_t *, ccb_t *, pdu_t *, pdu_t *);
    749 int init_text_parameters(connection_t *, ccb_t *);
    750 int assemble_send_targets(pdu_t *, uint8_t *);
    751 void set_negotiated_parameters(ccb_t *);
    752 
    753 #endif /* !_ISCSI_GLOBALS_H */
    754