Home | History | Annotate | Line # | Download | only in iscsi
iscsi_globals.h revision 1.19
      1 /*	$NetBSD: iscsi_globals.h,v 1.19 2016/06/05 05:36:57 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/scsi_message.h>
     52 #include <dev/scsipi/scsipi_all.h>
     53 #include <dev/scsipi/scsiconf.h>
     54 #include <dev/scsipi/scsipiconf.h>
     55 
     56 #include "iscsi.h"
     57 #include "iscsi_pdu.h"
     58 #include "iscsi_ioctl.h"
     59 
     60 /* ------------------------ Code selection constants ------------------------ */
     61 
     62 #define ISCSI_DEBUG      0
     63 
     64 /* -------------------------  Global Constants  ----------------------------- */
     65 
     66 /* Version information */
     67 
     68 #define INTERFACE_VERSION	2
     69 #define VERSION_MAJOR		3
     70 #define VERSION_MINOR		1
     71 #define VERSION_STRING		"NetBSD iSCSI Software Initiator 20110407"
     72 
     73 /*
     74 Various checks are made that the expected cmd Serial Number is less than
     75 the actual command serial number. The extremely paranoid amongst us
     76 believe that a malicious iSCSI server could set this artificially low
     77 and effectively DoS a naive initiator. For this (possibly ludicrous)
     78 reason, I have added the two definitions below (agc, 2011/04/09). The
     79 throttling definition enables a check that the CmdSN is less than the
     80 ExpCmdSN in iscsi_send.c, and is enabled by default. The second definition
     81 effectively says "don't bother testing these values", and is used right
     82 now only in iscsi_send.c.
     83  */
     84 #define ISCSI_THROTTLING_ENABLED	1
     85 #define ISCSI_SERVER_TRUSTED		0
     86 
     87 /*
     88    NOTE: CCBS_PER_SESSION must not exceed 256 due to the way the ITT
     89    is constructed (it has the CCB index in its lower 8 bits). If it should ever
     90    be necessary to increase the number beyond that (which isn't expected),
     91    the corresponding ITT generation and extraction code must be rewritten.
     92 */
     93 #define CCBS_PER_SESSION      64	/* ToDo: Reasonable number?? */
     94 /*
     95    NOTE: PDUS_PER_CONNECTION is a number that could potentially impact
     96    performance if set too low, as a single command may use up a lot of PDUs for
     97    high values of First/MaxBurstLength and small values of
     98    MaxRecvDataSegmentLength of the target.
     99 */
    100 #define PDUS_PER_CONNECTION   128	/* ToDo: Reasonable number?? */
    101 
    102 /* max outstanding serial nums before we give up on the connection */
    103 #define SERNUM_BUFFER_LENGTH  (CCBS_PER_SESSION / 2)	/* ToDo: Reasonable?? */
    104 
    105 /* The RecvDataSegmentLength for Target->Initiator */
    106 #define DEFAULT_MaxRecvDataSegmentLength     (64*1024)
    107 
    108 /* Command timeout (reset on received PDU associated with the command's CCB) */
    109 #define COMMAND_TIMEOUT		(7 * hz) /* ToDo: Reasonable? (7 seconds) */
    110 #define MAX_CCB_TIMEOUTS	3		/* Max number of tries to resend or SNACK */
    111 #define MAX_CCB_TRIES		9      	/* Max number of total tries to recover */
    112 
    113 /* Connectionn timeout (reset on every valid received PDU) */
    114 #define CONNECTION_TIMEOUT       (2 * hz)	/* ToDo: Reasonable? (2 seconds) */
    115 #define CONNECTION_IDLE_TIMEOUT  (30 * hz)	/* Adjusted to Time2Retain/2 later */
    116 #define MAX_CONN_TIMEOUTS        4	/* Max number of tries to ping a target */
    117 
    118 /* Maximum attempts to recover connection */
    119 #define MAX_RECOVERY_ATTEMPTS	2	/* If two attempts don't work, something */
    120 									/* probably is seriously broken */
    121 
    122 /* PDU flags */
    123 
    124 #define PDUF_BUSY	0x01	/* PDU is being sent, don't re-send */
    125 #define PDUF_INQUEUE	0x02	/* PDU is in send queue */
    126 #define PDUF_PRIORITY	0x04	/* Insert PDU at head of queue */
    127 #define PDUF_NOUPDATE	0x10	/* Do not update PDU header/digest (test mode) */
    128 
    129 /* CCB Flags */
    130 
    131 #define CCBF_COMPLETE   0x0001	/* received status */
    132 #define CCBF_RESENT     0x0002	/* ccb was resent */
    133 #define CCBF_SENDTARGET 0x0004	/* SendTargets text request, not negotiation */
    134 #define CCBF_WAITING    0x0008	/* CCB is waiting for MaxCmdSN, wake it up */
    135 #define CCBF_GOT_RSP    0x0010	/* Got at least one response to this request */
    136 #define CCBF_REASSIGN   0x0020	/* Command can be reassigned */
    137 #define CCBF_OTHERCONN  0x0040	/* a logout for a different connection */
    138 #define CCBF_WAITQUEUE  0x0080	/* CCB is on waiting queue */
    139 #define CCBF_THROTTLING 0x0100	/* CCB is on throttling queue */
    140 
    141 /* ---------------------------  Global Types  ------------------------------- */
    142 
    143 /* Connection state */
    144 
    145 typedef enum {
    146 	/* first three correspond to CSG/NSG coding */
    147 	ST_SEC_NEG	= 0,	/* security negotiation phase */
    148 	ST_OP_NEG	= 1,	/* operational negotiation phase */
    149 	ST_FULL_FEATURE	= 3,	/* full feature phase */
    150 	/* rest is internal */
    151 	ST_WINDING_DOWN	= 4,	/* connection termination initiated, logging out */
    152 	ST_LOGOUT_SENT	= 5,	/* logout has been sent */
    153 	ST_SETTLING	= 6,	/* waiting for things to settle down */
    154 	ST_IDLE		= 7	/* connection is idle (ready to delete) */
    155 } conn_state_t;
    156 
    157 
    158 /* Logout state */
    159 
    160 typedef enum {
    161 	NOT_LOGGED_OUT,				/* Not logged out */
    162 	LOGOUT_SENT,				/* Logout was sent */
    163 	LOGOUT_SUCCESS,				/* Logout succeeded */
    164 	LOGOUT_FAILED				/* Logout failed */
    165 } logout_state_t;
    166 
    167 
    168 /* CCB Disposition */
    169 
    170 typedef enum {
    171 	CCBDISP_UNUSED,	/* 0 = In free pool */
    172 	CCBDISP_BUSY,	/* This CCB is busy, don't allow rx ops */
    173 	CCBDISP_NOWAIT,	/* Not waiting for anything */
    174 	CCBDISP_FREE,	/* Free this CCB when done */
    175 	CCBDISP_WAIT,	/* Calling thread is waiting for completion */
    176 	CCBDISP_SCSIPI,	/* Call scsipi_done when operation completes */
    177 	CCBDISP_DEFER	/* Defer waiting until all PDUs have been queued */
    178 } ccb_disp_t;
    179 
    180 
    181 /* PDU Disposition */
    182 
    183 typedef enum {
    184 	PDUDISP_UNUSED,		/* 0 = In free pool */
    185 	PDUDISP_FREE,		/* Free this PDU when done */
    186 	PDUDISP_WAIT		/* Waiting for acknowledge */
    187 } pdu_disp_t;
    188 
    189 /* Timeout state */
    190 
    191 typedef enum {
    192 	TOUT_NONE,		/* Initial */
    193 	TOUT_ARMED,		/* callout is scheduled */
    194 	TOUT_QUEUED,		/* put into timeout queue */
    195 	TOUT_BUSY		/* cleanup thread working */
    196 } tout_state_t;
    197 
    198 typedef struct connection_s connection_t;
    199 typedef struct session_s session_t;
    200 typedef struct ccb_s ccb_t;
    201 typedef struct pdu_s pdu_t;
    202 
    203 /* the serial number management structure (a circular buffer) */
    204 
    205 typedef struct {
    206 	uint32_t	ExpSN;	/* ExpxxSN (Data or Stat) sent to the target */
    207 	uint32_t	next_sn; /* next_sn (== ExpSN if no ack is pending) */
    208 	int		top;	/* top of buffer (newest element) */
    209 	int		bottom;	/* bottom of buffer (oldest element) */
    210 	uint32_t	sernum[SERNUM_BUFFER_LENGTH];	/* the serial numbers */
    211 	bool		ack[SERNUM_BUFFER_LENGTH];	/* acknowledged? */
    212 } sernum_buffer_t;
    213 
    214 
    215 /*
    216    The per-PDU data structure.
    217 */
    218 
    219 struct pdu_s {
    220 	TAILQ_ENTRY(pdu_s)	chain;	/* freelist or wait list (or no list) */
    221 	TAILQ_ENTRY(pdu_s)	send_chain;
    222 				/* chaining PDUs waiting to be sent */
    223 	pdu_disp_t		disp; /* what to do with this pdu */
    224 	uint32_t		flags; 	/* various processing flags */
    225 	pdu_header_t		pdu; /* Buffer for PDU associated with cmd */
    226 	void			*temp_data; /* (free after use) */
    227 	uint32_t		temp_data_len;	/* size of temp data */
    228 
    229 	struct uio		uio; /* UIO structure */
    230 	struct iovec		io_vec[4];
    231 				/* Header + data + data-digest + padding */
    232 
    233 	struct uio		save_uio;
    234 				/* UIO structure save for retransmits */
    235 	struct iovec		save_iovec[4];
    236 				/* Header + data + data-digest + padding */
    237 	uint32_t		data_digest;
    238 				/* holds data digest if enabled */
    239 	ccb_t			*owner;
    240 				/* the ccb this PDU belongs to (if any) */
    241 	connection_t		*connection;
    242 				/* the connection this PDU belongs to */
    243 };
    244 
    245 
    246 /* the PDU list type */
    247 
    248 TAILQ_HEAD(pdu_list_s, pdu_s);
    249 typedef struct pdu_list_s pdu_list_t;
    250 
    251 /*
    252    The per-command data structure. Calling it ccb in correspondence
    253    to other HA drivers.
    254 */
    255 
    256 struct ccb_s {
    257 	TAILQ_ENTRY(ccb_s)	chain;
    258 	/* either freelist or waiting list (or no list) */
    259 
    260 	uint32_t		status; /* Status gets entered here */
    261 	ccb_disp_t		disp;	/* what to do with this ccb */
    262 
    263 	struct callout		timeout; /* To make sure it isn't lost */
    264 	TAILQ_ENTRY(ccb_s)	tchain;
    265 	tout_state_t		timedout;
    266 	int			num_timeouts;
    267 	/* How often we've sent out SNACK without answer */
    268 	int			total_tries;
    269 	/* How often we've tried to recover */
    270 
    271 	uint32_t		ITT;
    272 	/* task tag: ITT counter + sess id + CCB index */
    273 	sernum_buffer_t		DataSN_buf;
    274 	/* Received Data Seq nums (read ops only) */
    275 
    276 	void			*par;
    277 	/* misc. parameter for this request */
    278 	struct scsipi_xfer	*xs;
    279 	/* the scsipi_xfer for this cmd */
    280 
    281 	void			*temp_data;
    282 	/* to hold state (mainly during negotiation) */
    283 	void			*text_data;
    284 	/* holds accumulated text for continued PDUs */
    285 	uint32_t		text_len;
    286 	/* length of text data so far */
    287 
    288 	uint64_t		lun; /* LUN */
    289 	uint32_t		tag; /* Command tag */
    290 	uint8_t			*cmd; /* SCSI command block */
    291 	uint16_t		cmdlen; /* SCSI command block length */
    292 	bool			data_in; /* if this is a read request */
    293 	uint8_t			*data_ptr; /* data pointer for read/write */
    294 	uint32_t		data_len; /* total data length */
    295 	uint32_t		xfer_len; /* data transferred on read */
    296 	uint32_t		residual; /* residual data size */
    297 
    298 	void			*sense_ptr; /* sense data pointer */
    299 	int			sense_len_req; /* requested sense data length */
    300 	int			sense_len_got; /* actual sense data length */
    301 
    302 	pdu_t			*pdu_waiting; /* PDU waiting to be ack'ed */
    303 	volatile uint32_t	CmdSN; /* CmdSN associated with waiting PDU */
    304 
    305 	int			flags;
    306 	connection_t		*connection; /* connection for CCB */
    307 	session_t		*session; /* session for CCB */
    308 };
    309 
    310 
    311 /* the CCB list type */
    312 
    313 TAILQ_HEAD(ccb_list_s, ccb_s);
    314 typedef struct ccb_list_s ccb_list_t;
    315 
    316 
    317 /*
    318    Per connection data: the connection structure
    319 */
    320 struct connection_s {
    321 	TAILQ_ENTRY(connection_s)	connections;
    322 
    323 	kmutex_t			lock;
    324 	kcondvar_t			conn_cv;
    325 	kcondvar_t			ccb_cv;
    326 	kcondvar_t			idle_cv;
    327 
    328 	pdu_list_t			pdu_pool; /* the free PDU pool */
    329 
    330 	ccb_list_t			ccbs_waiting;
    331 					/* CCBs waiting for completion */
    332 
    333 	pdu_list_t			pdus_to_send;
    334 					/* the PDUs waiting to be sent */
    335 
    336 	sernum_buffer_t			StatSN_buf;
    337 					/* to keep track of received StatSNs */
    338 
    339 	uint32_t			max_transfer;
    340 		/* min(MaxRecvDataSegmentLength, MaxBurstLength) */
    341 	uint32_t			max_firstimmed;
    342 		/* 0 if InitialR2T=Yes, else
    343 		   min of (MaxRecvDataSegmentLength, FirstBurstLength) */
    344 	uint32_t			max_firstdata;
    345 		/* 0 if ImmediateData=No, else min of */
    346 		/* (MaxRecvDataSegmentLength, FirstBurstLength) */
    347 
    348 	uint32_t			MaxRecvDataSegmentLength;
    349 					/* Target's value */
    350 	uint32_t			Our_MaxRecvDataSegmentLength;
    351 					/* Our own value */
    352 	bool				HeaderDigest;	/* TRUE if doing CRC */
    353 	bool				DataDigest;	/* TRUE if doing CRC */
    354 	uint32_t			Time2Wait;
    355 					/* Negotiated default or logout value */
    356 	uint32_t			Time2Retain;
    357 					/* Negotiated default or logout value */
    358 
    359 	uint16_t			id;
    360 		/* connection ID (unique within session) */
    361 
    362 	conn_state_t			state; /* State of connection */
    363 
    364 	struct lwp			*threadobj;
    365 		/* proc/thread pointer of socket owner */
    366 	struct file			*sock;	/* the connection's socket */
    367 	session_t			*session;
    368 					/* back pointer to the owning session */
    369 
    370 	struct lwp			*rcvproc; /* receive thread */
    371 	struct lwp			*sendproc; /* send thread */
    372 
    373 	uint32_t			terminating;
    374 					/* if closing down: status */
    375 	int				recover; /* recovery count */
    376 		/* (reset on first successful data transfer) */
    377 	volatile unsigned		usecount; /* number of active CCBs */
    378 
    379 	bool				destroy; /* conn will be destroyed */
    380 	bool				in_session;
    381 		/* if it's linked into the session list */
    382 	logout_state_t			loggedout;
    383 		/* status of logout (for recovery) */
    384 	struct callout			timeout;
    385 		/* Timeout for checking if connection is dead */
    386 	TAILQ_ENTRY(connection_s)	tchain;
    387 	tout_state_t			timedout;
    388 	int				num_timeouts;
    389 		/* How often we've sent out a NOP without answer */
    390 	uint32_t			idle_timeout_val;
    391 		/* Connection timeout value when idle */
    392 
    393 	iscsi_login_parameters_t	*login_par;
    394 					/* only valid during login */
    395 
    396 	pdu_t				pdu[PDUS_PER_CONNECTION]; /* PDUs */
    397 };
    398 
    399 /* the connection list type */
    400 
    401 TAILQ_HEAD(connection_list_s, connection_s);
    402 typedef struct connection_list_s connection_list_t;
    403 
    404 
    405 /*
    406    Per session data: the session structure
    407 */
    408 
    409 struct session_s {
    410 	/* Interface to child drivers.
    411 	   NOTE: sc_adapter MUST be the first field in this structure so we can
    412 	   easily get from adapter to session.
    413 	 */
    414 	struct scsipi_adapter	sc_adapter;
    415 	struct scsipi_channel	sc_channel;
    416 
    417 	device_t		child_dev;
    418 	/* the child we're associated with - (NULL if not mapped) */
    419 
    420 	/* local stuff */
    421 	TAILQ_ENTRY(session_s)	sessions;	/* the list of sessions */
    422 
    423 	kmutex_t		lock;
    424 	kcondvar_t		sess_cv;
    425 	kcondvar_t		ccb_cv;
    426 
    427 	ccb_list_t		ccb_pool;	/* The free CCB pool */
    428 	ccb_list_t		ccbs_throttled;
    429 				/* CCBs waiting for MaxCmdSN to increase */
    430 
    431 	uint16_t		id;	/* session ID (unique within driver) */
    432 	uint16_t		TSIH;	/* Target assigned session ID */
    433 
    434 	uint32_t		CmdSN;	 /* Current CmdSN */
    435 	uint32_t		ExpCmdSN; /* Current max ExpCmdSN received */
    436 	uint32_t		MaxCmdSN; /* Current MaxCmdSN */
    437 
    438 	/* negotiated values */
    439 	uint32_t		ErrorRecoveryLevel;
    440 	uint32_t		FirstBurstLength;
    441 	uint32_t		MaxBurstLength;
    442 	bool			ImmediateData;
    443 	bool			InitialR2T;
    444 	uint32_t		MaxOutstandingR2T;
    445 	uint32_t		MaxConnections;
    446 	uint32_t		DefaultTime2Wait;
    447 	uint32_t		DefaultTime2Retain;
    448 
    449 	iscsi_login_session_type_t login_type;	/* session type */
    450 
    451 	/* for send_targets requests */
    452 	uint8_t			*target_list;
    453 	uint32_t		target_list_len;
    454 
    455 	uint32_t		conn_id;	/* connection ID counter */
    456 
    457 	uint32_t		terminating;	/* if closing down: status */
    458 
    459 	uint32_t		active_connections;
    460 				/* currently active connections */
    461 	uint32_t		total_connections;
    462 	/* connections associated with this session (active or winding down) */
    463 	connection_list_t	conn_list;	/* the list of connections */
    464 	connection_t		*mru_connection;
    465 				/* the most recently used connection */
    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