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