Home | History | Annotate | Line # | Download | only in iscsi
iscsi_globals.h revision 1.27
      1  1.27   mlelstv /*	$NetBSD: iscsi_globals.h,v 1.27 2022/09/13 13:09:16 mlelstv 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.27   mlelstv #include <sys/mutex.h>
     41  1.27   mlelstv #include <sys/rwlock.h>
     42   1.1       agc #include <sys/proc.h>
     43   1.1       agc #include <sys/conf.h>
     44   1.1       agc #include <sys/errno.h>
     45   1.1       agc #include <sys/malloc.h>
     46   1.1       agc #include <sys/scsiio.h>
     47   1.1       agc #include <sys/kernel.h>
     48   1.1       agc #include <sys/kthread.h>
     49   1.1       agc #include <sys/systm.h>
     50   1.1       agc #include <sys/device.h>
     51   1.1       agc 
     52   1.1       agc #include <dev/scsipi/scsi_all.h>
     53  1.19   mlelstv #include <dev/scsipi/scsi_message.h>
     54   1.1       agc #include <dev/scsipi/scsipi_all.h>
     55   1.1       agc #include <dev/scsipi/scsiconf.h>
     56   1.1       agc #include <dev/scsipi/scsipiconf.h>
     57   1.1       agc 
     58   1.1       agc #include "iscsi.h"
     59   1.1       agc #include "iscsi_pdu.h"
     60   1.1       agc #include "iscsi_ioctl.h"
     61   1.1       agc 
     62   1.1       agc /* ------------------------ Code selection constants ------------------------ */
     63   1.1       agc 
     64  1.14   mlelstv #define ISCSI_DEBUG      0
     65   1.1       agc 
     66   1.1       agc /* -------------------------  Global Constants  ----------------------------- */
     67   1.1       agc 
     68   1.1       agc /* Version information */
     69   1.1       agc 
     70   1.1       agc #define INTERFACE_VERSION	2
     71   1.1       agc #define VERSION_MAJOR		3
     72   1.1       agc #define VERSION_MINOR		1
     73   1.1       agc #define VERSION_STRING		"NetBSD iSCSI Software Initiator 20110407"
     74   1.1       agc 
     75   1.1       agc /*
     76   1.1       agc    NOTE: CCBS_PER_SESSION must not exceed 256 due to the way the ITT
     77   1.1       agc    is constructed (it has the CCB index in its lower 8 bits). If it should ever
     78   1.1       agc    be necessary to increase the number beyond that (which isn't expected),
     79   1.1       agc    the corresponding ITT generation and extraction code must be rewritten.
     80   1.1       agc */
     81  1.21   mlelstv #define CCBS_PER_SESSION      32	/* ToDo: Reasonable number?? */
     82  1.21   mlelstv /*
     83  1.21   mlelstv    NOTE: CCBS_FOR_SCSPI limits the number of outstanding commands for
     84  1.21   mlelstv    SCSI commands, leaving some CCBs for keepalive and logout attempts,
     85  1.21   mlelstv    which are needed for each connection.
     86  1.21   mlelstv */
     87  1.21   mlelstv #define CCBS_FOR_SCSIPI       16	/* ToDo: Reasonable number?? */
     88   1.1       agc /*
     89   1.1       agc    NOTE: PDUS_PER_CONNECTION is a number that could potentially impact
     90   1.1       agc    performance if set too low, as a single command may use up a lot of PDUs for
     91   1.1       agc    high values of First/MaxBurstLength and small values of
     92   1.1       agc    MaxRecvDataSegmentLength of the target.
     93   1.1       agc */
     94  1.21   mlelstv #define PDUS_PER_CONNECTION   64	/* ToDo: Reasonable number?? */
     95   1.1       agc 
     96   1.1       agc /* max outstanding serial nums before we give up on the connection */
     97   1.1       agc #define SERNUM_BUFFER_LENGTH  (CCBS_PER_SESSION / 2)	/* ToDo: Reasonable?? */
     98   1.1       agc 
     99   1.1       agc /* The RecvDataSegmentLength for Target->Initiator */
    100   1.1       agc #define DEFAULT_MaxRecvDataSegmentLength     (64*1024)
    101   1.1       agc 
    102   1.1       agc /* Command timeout (reset on received PDU associated with the command's CCB) */
    103  1.21   mlelstv #define COMMAND_TIMEOUT		(60 * hz) /* ToDo: Reasonable? (60 seconds) */
    104   1.1       agc #define MAX_CCB_TIMEOUTS	3		/* Max number of tries to resend or SNACK */
    105   1.1       agc #define MAX_CCB_TRIES		9      	/* Max number of total tries to recover */
    106   1.1       agc 
    107   1.1       agc /* Connectionn timeout (reset on every valid received PDU) */
    108   1.1       agc #define CONNECTION_TIMEOUT       (2 * hz)	/* ToDo: Reasonable? (2 seconds) */
    109   1.1       agc #define CONNECTION_IDLE_TIMEOUT  (30 * hz)	/* Adjusted to Time2Retain/2 later */
    110   1.1       agc #define MAX_CONN_TIMEOUTS        4	/* Max number of tries to ping a target */
    111   1.1       agc 
    112   1.1       agc /* Maximum attempts to recover connection */
    113   1.1       agc #define MAX_RECOVERY_ATTEMPTS	2	/* If two attempts don't work, something */
    114   1.1       agc 									/* probably is seriously broken */
    115   1.1       agc 
    116   1.1       agc /* PDU flags */
    117   1.1       agc 
    118   1.1       agc #define PDUF_BUSY	0x01	/* PDU is being sent, don't re-send */
    119   1.1       agc #define PDUF_INQUEUE	0x02	/* PDU is in send queue */
    120   1.1       agc #define PDUF_PRIORITY	0x04	/* Insert PDU at head of queue */
    121   1.1       agc #define PDUF_NOUPDATE	0x10	/* Do not update PDU header/digest (test mode) */
    122   1.1       agc 
    123   1.1       agc /* CCB Flags */
    124   1.1       agc 
    125   1.6   mlelstv #define CCBF_COMPLETE   0x0001	/* received status */
    126   1.6   mlelstv #define CCBF_RESENT     0x0002	/* ccb was resent */
    127   1.6   mlelstv #define CCBF_SENDTARGET 0x0004	/* SendTargets text request, not negotiation */
    128   1.6   mlelstv #define CCBF_GOT_RSP    0x0010	/* Got at least one response to this request */
    129   1.6   mlelstv #define CCBF_REASSIGN   0x0020	/* Command can be reassigned */
    130   1.6   mlelstv #define CCBF_OTHERCONN  0x0040	/* a logout for a different connection */
    131   1.6   mlelstv #define CCBF_WAITQUEUE  0x0080	/* CCB is on waiting queue */
    132   1.1       agc 
    133   1.1       agc /* ---------------------------  Global Types  ------------------------------- */
    134   1.1       agc 
    135   1.1       agc /* Connection state */
    136   1.1       agc 
    137   1.1       agc typedef enum {
    138   1.1       agc 	/* first three correspond to CSG/NSG coding */
    139   1.1       agc 	ST_SEC_NEG	= 0,	/* security negotiation phase */
    140   1.1       agc 	ST_OP_NEG	= 1,	/* operational negotiation phase */
    141   1.1       agc 	ST_FULL_FEATURE	= 3,	/* full feature phase */
    142   1.1       agc 	/* rest is internal */
    143   1.1       agc 	ST_WINDING_DOWN	= 4,	/* connection termination initiated, logging out */
    144   1.1       agc 	ST_LOGOUT_SENT	= 5,	/* logout has been sent */
    145   1.1       agc 	ST_SETTLING	= 6,	/* waiting for things to settle down */
    146   1.1       agc 	ST_IDLE		= 7	/* connection is idle (ready to delete) */
    147   1.1       agc } conn_state_t;
    148   1.1       agc 
    149   1.1       agc 
    150   1.1       agc /* Logout state */
    151   1.1       agc 
    152   1.1       agc typedef enum {
    153   1.1       agc 	NOT_LOGGED_OUT,				/* Not logged out */
    154   1.1       agc 	LOGOUT_SENT,				/* Logout was sent */
    155   1.1       agc 	LOGOUT_SUCCESS,				/* Logout succeeded */
    156   1.1       agc 	LOGOUT_FAILED				/* Logout failed */
    157   1.1       agc } logout_state_t;
    158   1.1       agc 
    159   1.1       agc 
    160   1.1       agc /* CCB Disposition */
    161   1.1       agc 
    162   1.1       agc typedef enum {
    163   1.1       agc 	CCBDISP_UNUSED,	/* 0 = In free pool */
    164   1.1       agc 	CCBDISP_BUSY,	/* This CCB is busy, don't allow rx ops */
    165   1.1       agc 	CCBDISP_NOWAIT,	/* Not waiting for anything */
    166   1.1       agc 	CCBDISP_FREE,	/* Free this CCB when done */
    167   1.1       agc 	CCBDISP_WAIT,	/* Calling thread is waiting for completion */
    168   1.1       agc 	CCBDISP_SCSIPI,	/* Call scsipi_done when operation completes */
    169   1.1       agc 	CCBDISP_DEFER	/* Defer waiting until all PDUs have been queued */
    170   1.1       agc } ccb_disp_t;
    171   1.1       agc 
    172   1.1       agc 
    173   1.1       agc /* PDU Disposition */
    174   1.1       agc 
    175   1.1       agc typedef enum {
    176   1.1       agc 	PDUDISP_UNUSED,		/* 0 = In free pool */
    177   1.1       agc 	PDUDISP_FREE,		/* Free this PDU when done */
    178   1.1       agc 	PDUDISP_WAIT		/* Waiting for acknowledge */
    179   1.1       agc } pdu_disp_t;
    180   1.1       agc 
    181  1.17   mlelstv /* Timeout state */
    182  1.17   mlelstv 
    183  1.17   mlelstv typedef enum {
    184  1.17   mlelstv 	TOUT_NONE,		/* Initial */
    185  1.17   mlelstv 	TOUT_ARMED,		/* callout is scheduled */
    186  1.17   mlelstv 	TOUT_QUEUED,		/* put into timeout queue */
    187  1.17   mlelstv 	TOUT_BUSY		/* cleanup thread working */
    188  1.17   mlelstv } tout_state_t;
    189   1.1       agc 
    190   1.1       agc typedef struct connection_s connection_t;
    191   1.1       agc typedef struct session_s session_t;
    192   1.1       agc typedef struct ccb_s ccb_t;
    193   1.1       agc typedef struct pdu_s pdu_t;
    194   1.1       agc 
    195   1.1       agc /* the serial number management structure (a circular buffer) */
    196   1.1       agc 
    197   1.1       agc typedef struct {
    198   1.1       agc 	uint32_t	ExpSN;	/* ExpxxSN (Data or Stat) sent to the target */
    199   1.1       agc 	uint32_t	next_sn; /* next_sn (== ExpSN if no ack is pending) */
    200   1.1       agc 	int		top;	/* top of buffer (newest element) */
    201   1.1       agc 	int		bottom;	/* bottom of buffer (oldest element) */
    202   1.1       agc 	uint32_t	sernum[SERNUM_BUFFER_LENGTH];	/* the serial numbers */
    203  1.12     joerg 	bool		ack[SERNUM_BUFFER_LENGTH];	/* acknowledged? */
    204   1.1       agc } sernum_buffer_t;
    205   1.1       agc 
    206   1.1       agc 
    207   1.1       agc /*
    208   1.1       agc    The per-PDU data structure.
    209   1.1       agc */
    210   1.1       agc 
    211   1.1       agc struct pdu_s {
    212  1.23  christos 	TAILQ_ENTRY(pdu_s)	pdu_chain;	/* freelist or wait list (or no list) */
    213  1.23  christos 	TAILQ_ENTRY(pdu_s)	pdu_send_chain;
    214   1.1       agc 				/* chaining PDUs waiting to be sent */
    215  1.23  christos 	pdu_disp_t		pdu_disp; /* what to do with this pdu */
    216  1.23  christos 	uint32_t		pdu_flags; 	/* various processing flags */
    217  1.23  christos 	pdu_header_t		pdu_hdr; /* Buffer for PDU associated with cmd */
    218  1.23  christos 	void			*pdu_temp_data; /* (free after use) */
    219  1.23  christos 	uint32_t		pdu_temp_data_len;	/* size of temp data */
    220   1.1       agc 
    221  1.23  christos 	struct uio		pdu_uio; /* UIO structure */
    222  1.23  christos 	struct iovec		pdu_io_vec[4];
    223   1.1       agc 				/* Header + data + data-digest + padding */
    224   1.1       agc 
    225  1.23  christos 	struct uio		pdu_save_uio;
    226   1.1       agc 				/* UIO structure save for retransmits */
    227  1.23  christos 	struct iovec		pdu_save_iovec[4];
    228   1.1       agc 				/* Header + data + data-digest + padding */
    229  1.23  christos 	uint32_t		pdu_data_digest;
    230   1.1       agc 				/* holds data digest if enabled */
    231  1.23  christos 	ccb_t			*pdu_owner;
    232   1.1       agc 				/* the ccb this PDU belongs to (if any) */
    233  1.23  christos 	connection_t		*pdu_connection;
    234   1.1       agc 				/* the connection this PDU belongs to */
    235   1.1       agc };
    236   1.1       agc 
    237   1.1       agc 
    238   1.1       agc /* the PDU list type */
    239   1.1       agc 
    240   1.1       agc TAILQ_HEAD(pdu_list_s, pdu_s);
    241   1.1       agc typedef struct pdu_list_s pdu_list_t;
    242   1.1       agc 
    243   1.1       agc /*
    244   1.1       agc    The per-command data structure. Calling it ccb in correspondence
    245   1.1       agc    to other HA drivers.
    246   1.1       agc */
    247   1.1       agc 
    248   1.1       agc struct ccb_s {
    249  1.23  christos 	TAILQ_ENTRY(ccb_s)	ccb_chain;
    250   1.1       agc 	/* either freelist or waiting list (or no list) */
    251   1.1       agc 
    252  1.23  christos 	uint32_t		ccb_status; /* Status gets entered here */
    253  1.23  christos 	ccb_disp_t		ccb_disp;	/* what to do with this ccb */
    254   1.1       agc 
    255  1.23  christos 	struct callout		ccb_timeout; /* To make sure it isn't lost */
    256  1.23  christos 	TAILQ_ENTRY(ccb_s)	ccb_tchain;
    257  1.23  christos 	tout_state_t		ccb_timedout;
    258  1.23  christos 	int			ccb_num_timeouts;
    259   1.1       agc 	/* How often we've sent out SNACK without answer */
    260  1.23  christos 	int			ccb_total_tries;
    261   1.1       agc 	/* How often we've tried to recover */
    262   1.1       agc 
    263  1.23  christos 	uint32_t		ccb_ITT;
    264   1.1       agc 	/* task tag: ITT counter + sess id + CCB index */
    265  1.23  christos 	sernum_buffer_t		ccb_DataSN_buf;
    266   1.1       agc 	/* Received Data Seq nums (read ops only) */
    267   1.1       agc 
    268  1.23  christos 	void			*ccb_par;
    269   1.1       agc 	/* misc. parameter for this request */
    270  1.23  christos 	struct scsipi_xfer	*ccb_xs;
    271   1.1       agc 	/* the scsipi_xfer for this cmd */
    272   1.1       agc 
    273  1.23  christos 	void			*ccb_temp_data;
    274   1.1       agc 	/* to hold state (mainly during negotiation) */
    275  1.23  christos 	void			*ccb_text_data;
    276   1.1       agc 	/* holds accumulated text for continued PDUs */
    277  1.23  christos 	uint32_t		ccb_text_len;
    278   1.1       agc 	/* length of text data so far */
    279   1.1       agc 
    280  1.23  christos 	uint64_t		ccb_lun; /* LUN */
    281  1.23  christos 	uint32_t		ccb_tag; /* Command tag */
    282  1.23  christos 	uint8_t			*ccb_cmd; /* SCSI command block */
    283  1.23  christos 	uint16_t		ccb_cmdlen; /* SCSI command block length */
    284  1.23  christos 	bool			ccb_data_in; /* if this is a read request */
    285  1.23  christos 	uint8_t			*ccb_data_ptr; /* data pointer for read/write */
    286  1.23  christos 	uint32_t		ccb_data_len; /* total data length */
    287  1.23  christos 	uint32_t		ccb_xfer_len; /* data transferred on read */
    288  1.23  christos 	uint32_t		ccb_residual; /* residual data size */
    289  1.23  christos 
    290  1.23  christos 	void			*ccb_sense_ptr; /* sense data pointer */
    291  1.23  christos 	int			ccb_sense_len_req; /* requested sense data length */
    292  1.23  christos 	int			ccb_sense_len_got; /* actual sense data length */
    293  1.23  christos 
    294  1.23  christos 	pdu_t			*ccb_pdu_waiting; /* PDU waiting to be ack'ed */
    295  1.23  christos 	volatile uint32_t	ccb_CmdSN; /* CmdSN associated with waiting PDU */
    296  1.23  christos 
    297  1.23  christos 	int			ccb_flags;
    298  1.23  christos 	connection_t		*ccb_connection; /* connection for CCB */
    299  1.23  christos 	session_t		*ccb_session; /* session for CCB */
    300   1.1       agc };
    301   1.1       agc 
    302   1.1       agc 
    303   1.1       agc /* the CCB list type */
    304   1.1       agc 
    305   1.1       agc TAILQ_HEAD(ccb_list_s, ccb_s);
    306   1.1       agc typedef struct ccb_list_s ccb_list_t;
    307   1.1       agc 
    308   1.1       agc 
    309   1.1       agc /*
    310   1.1       agc    Per connection data: the connection structure
    311   1.1       agc */
    312   1.1       agc struct connection_s {
    313  1.23  christos 	TAILQ_ENTRY(connection_s)	c_connections;
    314   1.1       agc 
    315  1.23  christos 	kmutex_t			c_lock;
    316  1.23  christos 	kcondvar_t			c_conn_cv;
    317  1.23  christos 	kcondvar_t			c_pdu_cv;
    318  1.23  christos 	kcondvar_t			c_ccb_cv;
    319  1.23  christos 	kcondvar_t			c_idle_cv;
    320  1.14   mlelstv 
    321  1.23  christos 	pdu_list_t			c_pdu_pool; /* the free PDU pool */
    322   1.1       agc 
    323  1.23  christos 	ccb_list_t			c_ccbs_waiting;
    324   1.1       agc 					/* CCBs waiting for completion */
    325   1.1       agc 
    326  1.23  christos 	pdu_list_t			c_pdus_to_send;
    327   1.1       agc 					/* the PDUs waiting to be sent */
    328   1.1       agc 
    329  1.23  christos 	sernum_buffer_t			c_StatSN_buf;
    330   1.1       agc 					/* to keep track of received StatSNs */
    331   1.1       agc 
    332  1.23  christos 	uint32_t			c_max_transfer;
    333   1.1       agc 		/* min(MaxRecvDataSegmentLength, MaxBurstLength) */
    334  1.23  christos 	uint32_t			c_max_firstimmed;
    335   1.1       agc 		/* 0 if InitialR2T=Yes, else
    336   1.1       agc 		   min of (MaxRecvDataSegmentLength, FirstBurstLength) */
    337  1.23  christos 	uint32_t			c_max_firstdata;
    338   1.1       agc 		/* 0 if ImmediateData=No, else min of */
    339   1.1       agc 		/* (MaxRecvDataSegmentLength, FirstBurstLength) */
    340   1.1       agc 
    341  1.23  christos 	uint32_t			c_MaxRecvDataSegmentLength;
    342   1.1       agc 					/* Target's value */
    343  1.23  christos 	uint32_t			c_Our_MaxRecvDataSegmentLength;
    344   1.1       agc 					/* Our own value */
    345  1.23  christos 	bool				c_HeaderDigest;	/* TRUE if doing CRC */
    346  1.23  christos 	bool				c_DataDigest;	/* TRUE if doing CRC */
    347  1.23  christos 	uint32_t			c_Time2Wait;
    348   1.1       agc 					/* Negotiated default or logout value */
    349  1.23  christos 	uint32_t			c_Time2Retain;
    350   1.1       agc 					/* Negotiated default or logout value */
    351   1.1       agc 
    352  1.23  christos 	uint16_t			c_id;
    353   1.1       agc 		/* connection ID (unique within session) */
    354   1.1       agc 
    355  1.23  christos 	conn_state_t			c_state; /* State of connection */
    356   1.1       agc 
    357  1.23  christos 	struct lwp			*c_threadobj;
    358   1.1       agc 		/* proc/thread pointer of socket owner */
    359  1.27   mlelstv 
    360  1.27   mlelstv 	krwlock_t			c_sock_rw;
    361  1.23  christos 	struct file			*c_sock;	/* the connection's socket */
    362  1.23  christos 	session_t			*c_session;
    363   1.1       agc 					/* back pointer to the owning session */
    364   1.1       agc 
    365  1.23  christos 	struct lwp			*c_rcvproc; /* receive thread */
    366  1.23  christos 	struct lwp			*c_sendproc; /* send thread */
    367   1.1       agc 
    368  1.23  christos 	uint32_t			c_terminating;
    369   1.1       agc 					/* if closing down: status */
    370  1.23  christos 	int				c_recover; /* recovery count */
    371   1.1       agc 		/* (reset on first successful data transfer) */
    372  1.23  christos 	volatile unsigned		c_usecount; /* number of active CCBs */
    373  1.27   mlelstv 	unsigned			c_pducount; /* number of active PDUs */
    374   1.1       agc 
    375  1.23  christos 	bool				c_destroy; /* conn will be destroyed */
    376  1.23  christos 	bool				c_in_session;
    377   1.1       agc 		/* if it's linked into the session list */
    378  1.23  christos 	logout_state_t			c_loggedout;
    379   1.1       agc 		/* status of logout (for recovery) */
    380  1.23  christos 	struct callout			c_timeout;
    381   1.1       agc 		/* Timeout for checking if connection is dead */
    382  1.23  christos 	TAILQ_ENTRY(connection_s)	c_tchain;
    383  1.23  christos 	tout_state_t			c_timedout;
    384  1.23  christos 	int				c_num_timeouts;
    385   1.1       agc 		/* How often we've sent out a NOP without answer */
    386  1.23  christos 	uint32_t			c_idle_timeout_val;
    387   1.1       agc 		/* Connection timeout value when idle */
    388   1.1       agc 
    389  1.23  christos 	iscsi_login_parameters_t	*c_login_par;
    390   1.1       agc 					/* only valid during login */
    391   1.1       agc 
    392  1.23  christos 	pdu_t				c_pdu[PDUS_PER_CONNECTION]; /* PDUs */
    393   1.1       agc };
    394   1.1       agc 
    395   1.1       agc /* the connection list type */
    396   1.1       agc 
    397   1.1       agc TAILQ_HEAD(connection_list_s, connection_s);
    398   1.1       agc typedef struct connection_list_s connection_list_t;
    399   1.1       agc 
    400   1.1       agc 
    401   1.1       agc /*
    402   1.1       agc    Per session data: the session structure
    403   1.1       agc */
    404   1.1       agc 
    405   1.1       agc struct session_s {
    406   1.1       agc 	/* Interface to child drivers.
    407   1.1       agc 	   NOTE: sc_adapter MUST be the first field in this structure so we can
    408   1.1       agc 	   easily get from adapter to session.
    409   1.1       agc 	 */
    410  1.23  christos 	struct scsipi_adapter	s_sc_adapter;
    411  1.23  christos 	struct scsipi_channel	s_sc_channel;
    412   1.1       agc 
    413  1.23  christos 	device_t		s_child_dev;
    414   1.1       agc 	/* the child we're associated with - (NULL if not mapped) */
    415   1.1       agc 
    416  1.23  christos 	int			s_refcount;	/* session in use by scsipi */
    417  1.21   mlelstv 
    418   1.1       agc 	/* local stuff */
    419  1.23  christos 	TAILQ_ENTRY(session_s)	s_sessions;	/* the list of sessions */
    420   1.1       agc 
    421  1.23  christos 	kmutex_t		s_lock;
    422  1.23  christos 	kcondvar_t		s_sess_cv;
    423  1.23  christos 	kcondvar_t		s_ccb_cv;
    424  1.14   mlelstv 
    425  1.23  christos 	ccb_list_t		s_ccb_pool;	/* The free CCB pool */
    426  1.21   mlelstv 
    427  1.23  christos 	int			s_send_window;
    428   1.1       agc 
    429  1.23  christos 	uint16_t		s_id;	/* session ID (unique within driver) */
    430  1.23  christos 	uint16_t		s_TSIH;	/* Target assigned session ID */
    431   1.1       agc 
    432  1.23  christos 	uint32_t		s_CmdSN;	 /* Current CmdSN */
    433  1.23  christos 	uint32_t		s_ExpCmdSN; /* Current max ExpCmdSN received */
    434  1.23  christos 	uint32_t		s_MaxCmdSN; /* Current MaxCmdSN */
    435   1.1       agc 
    436   1.1       agc 	/* negotiated values */
    437  1.23  christos 	uint32_t		s_ErrorRecoveryLevel;
    438  1.23  christos 	uint32_t		s_FirstBurstLength;
    439  1.23  christos 	uint32_t		s_MaxBurstLength;
    440  1.23  christos 	bool			s_ImmediateData;
    441  1.23  christos 	bool			s_InitialR2T;
    442  1.23  christos 	uint32_t		s_MaxOutstandingR2T;
    443  1.23  christos 	uint32_t		s_MaxConnections;
    444  1.23  christos 	uint32_t		s_DefaultTime2Wait;
    445  1.23  christos 	uint32_t		s_DefaultTime2Retain;
    446   1.1       agc 
    447  1.23  christos 	iscsi_login_session_type_t s_login_type;	/* session type */
    448   1.1       agc 
    449   1.1       agc 	/* for send_targets requests */
    450  1.23  christos 	uint8_t			*s_target_list;
    451  1.23  christos 	uint32_t		s_target_list_len;
    452   1.1       agc 
    453  1.23  christos 	uint32_t		s_conn_id;	/* connection ID counter */
    454   1.1       agc 
    455  1.23  christos 	uint32_t		s_terminating;	/* if closing down: status */
    456   1.1       agc 
    457  1.23  christos 	uint32_t		s_active_connections;
    458   1.1       agc 				/* currently active connections */
    459  1.23  christos 	uint32_t		s_total_connections;
    460   1.1       agc 	/* connections associated with this session (active or winding down) */
    461  1.23  christos 	connection_list_t	s_conn_list;	/* the list of connections */
    462  1.23  christos 	connection_t		*s_mru_connection;
    463   1.1       agc 				/* the most recently used connection */
    464   1.1       agc 
    465  1.23  christos 	ccb_t			s_ccb[CCBS_PER_SESSION];	/* CCBs */
    466   1.1       agc 
    467  1.23  christos 	char			s_tgtname[ISCSI_STRING_LENGTH + 1];
    468   1.1       agc 				/* iSCSI target name */
    469   1.1       agc };
    470   1.1       agc 
    471   1.1       agc /* the session list type */
    472   1.1       agc 
    473   1.1       agc TAILQ_HEAD(session_list_s, session_s);
    474   1.1       agc typedef struct session_list_s session_list_t;
    475   1.1       agc 
    476   1.1       agc 
    477   1.1       agc /*
    478   1.1       agc    Event notification structures
    479   1.1       agc */
    480   1.1       agc 
    481   1.1       agc typedef struct event_s {
    482  1.23  christos 	TAILQ_ENTRY(event_s)	ev_link;	/* next event in queue */
    483  1.23  christos 	iscsi_event_t		ev_event_kind;	/* which event */
    484  1.23  christos 	uint32_t		ev_session_id;	/* affected session ID */
    485  1.23  christos 	uint32_t		ev_connection_id;/* affected connection ID */
    486  1.23  christos 	uint32_t		ev_reason;		/* event reason */
    487   1.1       agc } event_t;
    488   1.1       agc 
    489   1.1       agc /* the event list entry type */
    490   1.1       agc 
    491   1.1       agc TAILQ_HEAD(event_list_s, event_s);
    492   1.1       agc typedef struct event_list_s event_list_t;
    493   1.1       agc 
    494   1.1       agc 
    495   1.1       agc typedef struct event_handler_s {
    496  1.23  christos 	TAILQ_ENTRY(event_handler_s)	evh_link;	/* next handler */
    497  1.23  christos 	uint32_t			evh_id;	/* unique ID */
    498  1.23  christos 	event_list_t			evh_events;	/* list of events pending */
    499  1.23  christos 	iscsi_wait_event_parameters_t	*evh_waiter; /* waiting parameter */
    500   1.1       agc 	/* following to detect dead handlers */
    501  1.23  christos 	event_t				*evh_first_in_list;
    502   1.1       agc } event_handler_t;
    503   1.1       agc 
    504   1.1       agc /* the event list entry type */
    505   1.1       agc 
    506   1.1       agc TAILQ_HEAD(event_handler_list_s, event_handler_s);
    507   1.1       agc typedef struct event_handler_list_s event_handler_list_t;
    508   1.1       agc 
    509  1.13     joerg /* /dev/iscsi0 state */
    510  1.13     joerg struct iscsifd {
    511  1.23  christos 	TAILQ_ENTRY(iscsifd)		fd_link;
    512  1.23  christos 	device_t	fd_dev;
    513  1.23  christos 	int		fd_unit;
    514  1.13     joerg };
    515   1.1       agc 
    516   1.1       agc /* -------------------------  Global Variables  ----------------------------- */
    517   1.1       agc 
    518   1.1       agc /* In iscsi_main.c */
    519   1.1       agc 
    520   1.5   mlelstv extern struct cfattach iscsi_ca;		/* the device attach structure */
    521   1.1       agc 
    522   1.5   mlelstv extern session_list_t iscsi_sessions;		/* the list of sessions */
    523   1.5   mlelstv extern bool iscsi_detaching;			/* signal to cleanup thread it should exit */
    524   1.5   mlelstv extern uint32_t iscsi_num_send_threads;		/* the number of active send threads */
    525   1.1       agc 
    526   1.5   mlelstv extern uint8_t iscsi_InitiatorName[ISCSI_STRING_LENGTH];
    527   1.5   mlelstv extern uint8_t iscsi_InitiatorAlias[ISCSI_STRING_LENGTH];
    528   1.5   mlelstv extern login_isid_t iscsi_InitiatorISID;
    529   1.1       agc 
    530  1.10     joerg /* Debugging stuff */
    531   1.1       agc 
    532   1.1       agc #ifndef DDB
    533   1.1       agc #define Debugger() panic("should call debugger here (iscsi.c)")
    534   1.1       agc #endif /* ! DDB */
    535   1.1       agc 
    536   1.1       agc #ifdef ISCSI_DEBUG
    537   1.1       agc 
    538   1.5   mlelstv extern int iscsi_debug_level;	/* How much debug info to display */
    539  1.25      maya extern bool iscsi_hex_bignums;	/* Whether to encode parameters in hex or base64 */
    540   1.1       agc 
    541   1.1       agc #define DEBOUT(x) printf x
    542   1.3   mlelstv #define DEB(lev,x) { if (iscsi_debug_level >= lev) printf x ;}
    543   1.3   mlelstv #define DEBC(conn,lev,x) { if (iscsi_debug_level >= lev) { printf("S%dC%d: ", \
    544  1.27   mlelstv 			conn && conn->c_session ? conn->c_session->s_id : -1, \
    545  1.27   mlelstv 			conn ? conn->c_id : -1); printf x ;}}
    546   1.1       agc 
    547   1.1       agc #define STATIC static
    548   1.1       agc 
    549   1.1       agc #else
    550   1.1       agc 
    551   1.1       agc #define DEBOUT(x)
    552   1.1       agc #define DEB(lev,x)
    553   1.1       agc #define DEBC(conn,lev,x)
    554   1.1       agc 
    555   1.1       agc #define STATIC static
    556   1.1       agc 
    557   1.1       agc #endif
    558   1.1       agc 
    559   1.1       agc /* Critical section macros */
    560   1.1       agc 
    561   1.1       agc /* misc stuff */
    562   1.1       agc #define min(a, b) ((a) < (b)) ? (a) : (b)
    563   1.1       agc #define max(a, b) ((a) < (b)) ? (b) : (a)
    564   1.1       agc 
    565   1.1       agc 
    566   1.1       agc /*
    567   1.1       agc    Convert unsigned int to 3-byte value (for DataSegmentLength field in PDU)
    568   1.1       agc */
    569   1.1       agc 
    570   1.1       agc static __inline void
    571   1.1       agc hton3(uint32_t val, uint8_t *bytes)
    572   1.1       agc {
    573   1.1       agc 	bytes[0] = (uint8_t) (val >> 16);
    574   1.1       agc 	bytes[1] = (uint8_t) (val >> 8);
    575   1.1       agc 	bytes[2] = (uint8_t) val;
    576   1.1       agc }
    577   1.1       agc 
    578   1.1       agc /*
    579   1.1       agc    Convert 3-byte value to unsigned int (for DataSegmentLength field in PDU)
    580   1.1       agc */
    581   1.1       agc 
    582   1.1       agc static __inline uint32_t
    583   1.1       agc ntoh3(uint8_t *bytes)
    584   1.1       agc {
    585   1.1       agc 	return (bytes[0] << 16) | (bytes[1] << 8) | bytes[2];
    586   1.1       agc }
    587   1.1       agc 
    588   1.1       agc 
    589   1.1       agc /*
    590   1.1       agc  * Convert uint64 to network byte order (for LUN field in PDU)
    591   1.1       agc */
    592   1.1       agc static __inline uint64_t
    593   1.1       agc htonq(uint64_t x)
    594   1.1       agc {
    595   1.1       agc #if BYTE_ORDER == LITTLE_ENDIAN
    596   1.1       agc 	uint8_t *s = (uint8_t *) & x;
    597   1.1       agc 	return (uint64_t) ((uint64_t) s[0] << 56 | (uint64_t) s[1] << 48 |
    598   1.1       agc 			(uint64_t) s[2] << 40 | (uint64_t) s[3] << 32 |
    599   1.1       agc 			(uint64_t) s[4] << 24 | (uint64_t) s[5] << 16 |
    600   1.1       agc 			(uint64_t) s[6] <<  8 | (uint64_t) s[7]);
    601   1.1       agc #else
    602   1.1       agc 	return x;
    603   1.1       agc #endif
    604   1.1       agc }
    605   1.1       agc 
    606   1.1       agc #define ntohq(x) htonq(x)
    607   1.1       agc 
    608   1.1       agc /*
    609   1.1       agc  * Serial number buffer empty?
    610   1.1       agc */
    611   1.1       agc 
    612   1.1       agc static __inline bool
    613   1.1       agc sn_empty(sernum_buffer_t *buf)
    614   1.1       agc {
    615   1.1       agc 	return buf->top == buf->bottom;
    616   1.1       agc }
    617   1.1       agc 
    618   1.1       agc 
    619   1.1       agc /*
    620   1.1       agc  * Serial number compare
    621   1.1       agc */
    622   1.1       agc 
    623   1.1       agc static __inline bool
    624   1.1       agc sn_a_lt_b(uint32_t a, uint32_t b)
    625   1.1       agc {
    626   1.1       agc 	return (a < b && !((b - a) & 0x80000000)) ||
    627   1.1       agc 	       (a > b && ((a - b) & 0x80000000));
    628   1.1       agc }
    629   1.1       agc 
    630   1.1       agc static __inline bool
    631   1.1       agc sn_a_le_b(uint32_t a, uint32_t b)
    632   1.1       agc {
    633   1.1       agc 	return (a <= b && !((b - a) & 0x80000000)) ||
    634   1.1       agc 	       (a >= b && ((a - b) & 0x80000000));
    635   1.1       agc }
    636   1.1       agc 
    637   1.1       agc /* in iscsi_ioctl.c */
    638   1.1       agc 
    639  1.14   mlelstv void iscsi_init_cleanup(void);
    640  1.21   mlelstv int iscsi_destroy_cleanup(void);
    641  1.14   mlelstv void iscsi_notify_cleanup(void);
    642  1.14   mlelstv 
    643  1.14   mlelstv 
    644   1.1       agc /* Parameter for logout is reason code in logout PDU, -1 for don't send logout */
    645   1.1       agc #define NO_LOGOUT          -1
    646   1.1       agc #define LOGOUT_SESSION     0
    647   1.1       agc #define LOGOUT_CONNECTION  1
    648   1.1       agc #define RECOVER_CONNECTION 2
    649   1.1       agc 
    650   1.1       agc void add_event(iscsi_event_t, uint32_t, uint32_t, uint32_t);
    651   1.1       agc 
    652   1.1       agc void kill_connection(connection_t *, uint32_t, int, bool);
    653  1.27   mlelstv void kill_session(uint32_t, uint32_t, int, bool);
    654  1.21   mlelstv int kill_all_sessions(void);
    655   1.1       agc void handle_connection_error(connection_t *, uint32_t, int);
    656  1.14   mlelstv void add_connection_cleanup(connection_t *);
    657   1.1       agc 
    658  1.13     joerg int iscsiioctl(struct file *, u_long, void *);
    659   1.1       agc 
    660   1.1       agc session_t *find_session(uint32_t);
    661   1.1       agc connection_t *find_connection(session_t *, uint32_t);
    662  1.21   mlelstv int ref_session(session_t *);
    663  1.21   mlelstv void unref_session(session_t *);
    664   1.1       agc 
    665   1.1       agc /* in iscsi_main.c */
    666   1.1       agc 
    667   1.1       agc /*void iscsiattach(void *); */
    668   1.1       agc int iscsidetach(device_t, int);
    669   1.1       agc 
    670   1.1       agc void iscsi_done(ccb_t *);
    671  1.14   mlelstv int map_session(session_t *, device_t);
    672   1.6   mlelstv int unmap_session(session_t *);
    673   1.1       agc 
    674   1.1       agc /* in iscsi_send.c */
    675   1.1       agc 
    676   1.1       agc void iscsi_send_thread(void *);
    677   1.1       agc 
    678   1.1       agc connection_t *assign_connection(session_t *session, bool waitok);
    679   1.1       agc void resend_pdu(ccb_t *);
    680   1.1       agc int send_login(connection_t *);
    681   1.1       agc int send_logout(connection_t *, connection_t *, int, bool);
    682   1.1       agc int send_data_out(connection_t *, pdu_t *, ccb_t *, ccb_disp_t, bool);
    683   1.1       agc void send_run_xfer(session_t *, struct scsipi_xfer *);
    684   1.1       agc int send_send_targets(session_t *, uint8_t *);
    685   1.1       agc int send_task_management(connection_t *, ccb_t *, struct scsipi_xfer *, int);
    686   1.1       agc 
    687   1.1       agc void negotiate_login(connection_t *, pdu_t *, ccb_t *);
    688   1.1       agc void acknowledge_text(connection_t *, pdu_t *, ccb_t *);
    689   1.1       agc void start_text_negotiation(connection_t *);
    690   1.1       agc void negotiate_text(connection_t *, pdu_t *, ccb_t *);
    691   1.1       agc int send_nop_out(connection_t *, pdu_t *);
    692   1.1       agc void snack_missing(connection_t *, ccb_t *, uint8_t, uint32_t, uint32_t);
    693   1.1       agc void send_snack(connection_t *, pdu_t *, ccb_t *, uint8_t);
    694   1.1       agc int send_send_targets(session_t *, uint8_t *);
    695   1.1       agc 
    696   1.1       agc void send_command(ccb_t *, ccb_disp_t, bool, bool);
    697   1.1       agc #ifndef ISCSI_MINIMAL
    698   1.1       agc int send_io_command(session_t *, uint64_t, scsireq_t *, bool, uint32_t);
    699   1.1       agc #endif
    700   1.1       agc 
    701  1.14   mlelstv void connection_timeout_co(void *);
    702  1.14   mlelstv void ccb_timeout_co(void *);
    703  1.14   mlelstv 
    704  1.14   mlelstv void connection_timeout(connection_t *);
    705  1.16   mlelstv void connection_timeout_start(connection_t *, int);
    706  1.16   mlelstv void connection_timeout_stop(connection_t *);
    707  1.14   mlelstv void ccb_timeout(ccb_t *);
    708  1.16   mlelstv void ccb_timeout_start(ccb_t *, int);
    709  1.16   mlelstv void ccb_timeout_stop(ccb_t *);
    710   1.1       agc 
    711   1.1       agc /* in iscsi_rcv.c */
    712   1.1       agc 
    713   1.1       agc void iscsi_rcv_thread(void *);
    714   1.1       agc 
    715   1.1       agc /* in iscsi_utils.c */
    716   1.1       agc 
    717  1.23  christos uint32_t gen_digest(const void *, size_t);
    718  1.23  christos uint32_t gen_digest_2(const void *, size_t, const void *, size_t);
    719   1.1       agc 
    720   1.1       agc void create_ccbs(session_t *);
    721  1.22   mlelstv void destroy_ccbs(session_t *);
    722   1.1       agc ccb_t *get_ccb(connection_t *, bool);
    723   1.1       agc void free_ccb(ccb_t *);
    724   1.6   mlelstv void suspend_ccb(ccb_t *, bool);
    725   1.6   mlelstv void wake_ccb(ccb_t *, uint32_t);
    726   1.1       agc 
    727   1.1       agc void create_pdus(connection_t *);
    728   1.6   mlelstv pdu_t *get_pdu(connection_t *, bool);
    729   1.1       agc void free_pdu(pdu_t *);
    730   1.1       agc 
    731   1.1       agc void init_sernum(sernum_buffer_t *);
    732   1.1       agc int add_sernum(sernum_buffer_t *, uint32_t);
    733   1.1       agc uint32_t ack_sernum(sernum_buffer_t *, uint32_t);
    734   1.1       agc 
    735  1.21   mlelstv uint32_t get_sernum(session_t *, pdu_t *);
    736  1.15   mlelstv int sernum_in_window(session_t *);
    737  1.21   mlelstv int window_size(session_t *, int);
    738  1.15   mlelstv 
    739   1.1       agc /* in iscsi_text.c */
    740   1.1       agc 
    741   1.1       agc int assemble_login_parameters(connection_t *, ccb_t *, pdu_t *);
    742   1.1       agc int assemble_security_parameters(connection_t *, ccb_t *, pdu_t *, pdu_t *);
    743   1.1       agc int assemble_negotiation_parameters(connection_t *, ccb_t *, pdu_t *, pdu_t *);
    744   1.1       agc int init_text_parameters(connection_t *, ccb_t *);
    745   1.1       agc int assemble_send_targets(pdu_t *, uint8_t *);
    746   1.1       agc void set_negotiated_parameters(ccb_t *);
    747   1.1       agc 
    748   1.1       agc #endif /* !_ISCSI_GLOBALS_H */
    749