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