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