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