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