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