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