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