1 /* $NetBSD: iscsi_globals.h,v 1.27 2022/09/13 13:09:16 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/mutex.h> 41 #include <sys/rwlock.h> 42 #include <sys/proc.h> 43 #include <sys/conf.h> 44 #include <sys/errno.h> 45 #include <sys/malloc.h> 46 #include <sys/scsiio.h> 47 #include <sys/kernel.h> 48 #include <sys/kthread.h> 49 #include <sys/systm.h> 50 #include <sys/device.h> 51 52 #include <dev/scsipi/scsi_all.h> 53 #include <dev/scsipi/scsi_message.h> 54 #include <dev/scsipi/scsipi_all.h> 55 #include <dev/scsipi/scsiconf.h> 56 #include <dev/scsipi/scsipiconf.h> 57 58 #include "iscsi.h" 59 #include "iscsi_pdu.h" 60 #include "iscsi_ioctl.h" 61 62 /* ------------------------ Code selection constants ------------------------ */ 63 64 #define ISCSI_DEBUG 0 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 NOTE: CCBS_PER_SESSION must not exceed 256 due to the way the ITT 77 is constructed (it has the CCB index in its lower 8 bits). If it should ever 78 be necessary to increase the number beyond that (which isn't expected), 79 the corresponding ITT generation and extraction code must be rewritten. 80 */ 81 #define CCBS_PER_SESSION 32 /* ToDo: Reasonable number?? */ 82 /* 83 NOTE: CCBS_FOR_SCSPI limits the number of outstanding commands for 84 SCSI commands, leaving some CCBs for keepalive and logout attempts, 85 which are needed for each connection. 86 */ 87 #define CCBS_FOR_SCSIPI 16 /* ToDo: Reasonable number?? */ 88 /* 89 NOTE: PDUS_PER_CONNECTION is a number that could potentially impact 90 performance if set too low, as a single command may use up a lot of PDUs for 91 high values of First/MaxBurstLength and small values of 92 MaxRecvDataSegmentLength of the target. 93 */ 94 #define PDUS_PER_CONNECTION 64 /* ToDo: Reasonable number?? */ 95 96 /* max outstanding serial nums before we give up on the connection */ 97 #define SERNUM_BUFFER_LENGTH (CCBS_PER_SESSION / 2) /* ToDo: Reasonable?? */ 98 99 /* The RecvDataSegmentLength for Target->Initiator */ 100 #define DEFAULT_MaxRecvDataSegmentLength (64*1024) 101 102 /* Command timeout (reset on received PDU associated with the command's CCB) */ 103 #define COMMAND_TIMEOUT (60 * hz) /* ToDo: Reasonable? (60 seconds) */ 104 #define MAX_CCB_TIMEOUTS 3 /* Max number of tries to resend or SNACK */ 105 #define MAX_CCB_TRIES 9 /* Max number of total tries to recover */ 106 107 /* Connectionn timeout (reset on every valid received PDU) */ 108 #define CONNECTION_TIMEOUT (2 * hz) /* ToDo: Reasonable? (2 seconds) */ 109 #define CONNECTION_IDLE_TIMEOUT (30 * hz) /* Adjusted to Time2Retain/2 later */ 110 #define MAX_CONN_TIMEOUTS 4 /* Max number of tries to ping a target */ 111 112 /* Maximum attempts to recover connection */ 113 #define MAX_RECOVERY_ATTEMPTS 2 /* If two attempts don't work, something */ 114 /* probably is seriously broken */ 115 116 /* PDU flags */ 117 118 #define PDUF_BUSY 0x01 /* PDU is being sent, don't re-send */ 119 #define PDUF_INQUEUE 0x02 /* PDU is in send queue */ 120 #define PDUF_PRIORITY 0x04 /* Insert PDU at head of queue */ 121 #define PDUF_NOUPDATE 0x10 /* Do not update PDU header/digest (test mode) */ 122 123 /* CCB Flags */ 124 125 #define CCBF_COMPLETE 0x0001 /* received status */ 126 #define CCBF_RESENT 0x0002 /* ccb was resent */ 127 #define CCBF_SENDTARGET 0x0004 /* SendTargets text request, not negotiation */ 128 #define CCBF_GOT_RSP 0x0010 /* Got at least one response to this request */ 129 #define CCBF_REASSIGN 0x0020 /* Command can be reassigned */ 130 #define CCBF_OTHERCONN 0x0040 /* a logout for a different connection */ 131 #define CCBF_WAITQUEUE 0x0080 /* CCB is on waiting queue */ 132 133 /* --------------------------- Global Types ------------------------------- */ 134 135 /* Connection state */ 136 137 typedef enum { 138 /* first three correspond to CSG/NSG coding */ 139 ST_SEC_NEG = 0, /* security negotiation phase */ 140 ST_OP_NEG = 1, /* operational negotiation phase */ 141 ST_FULL_FEATURE = 3, /* full feature phase */ 142 /* rest is internal */ 143 ST_WINDING_DOWN = 4, /* connection termination initiated, logging out */ 144 ST_LOGOUT_SENT = 5, /* logout has been sent */ 145 ST_SETTLING = 6, /* waiting for things to settle down */ 146 ST_IDLE = 7 /* connection is idle (ready to delete) */ 147 } conn_state_t; 148 149 150 /* Logout state */ 151 152 typedef enum { 153 NOT_LOGGED_OUT, /* Not logged out */ 154 LOGOUT_SENT, /* Logout was sent */ 155 LOGOUT_SUCCESS, /* Logout succeeded */ 156 LOGOUT_FAILED /* Logout failed */ 157 } logout_state_t; 158 159 160 /* CCB Disposition */ 161 162 typedef enum { 163 CCBDISP_UNUSED, /* 0 = In free pool */ 164 CCBDISP_BUSY, /* This CCB is busy, don't allow rx ops */ 165 CCBDISP_NOWAIT, /* Not waiting for anything */ 166 CCBDISP_FREE, /* Free this CCB when done */ 167 CCBDISP_WAIT, /* Calling thread is waiting for completion */ 168 CCBDISP_SCSIPI, /* Call scsipi_done when operation completes */ 169 CCBDISP_DEFER /* Defer waiting until all PDUs have been queued */ 170 } ccb_disp_t; 171 172 173 /* PDU Disposition */ 174 175 typedef enum { 176 PDUDISP_UNUSED, /* 0 = In free pool */ 177 PDUDISP_FREE, /* Free this PDU when done */ 178 PDUDISP_WAIT /* Waiting for acknowledge */ 179 } pdu_disp_t; 180 181 /* Timeout state */ 182 183 typedef enum { 184 TOUT_NONE, /* Initial */ 185 TOUT_ARMED, /* callout is scheduled */ 186 TOUT_QUEUED, /* put into timeout queue */ 187 TOUT_BUSY /* cleanup thread working */ 188 } tout_state_t; 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) pdu_chain; /* freelist or wait list (or no list) */ 213 TAILQ_ENTRY(pdu_s) pdu_send_chain; 214 /* chaining PDUs waiting to be sent */ 215 pdu_disp_t pdu_disp; /* what to do with this pdu */ 216 uint32_t pdu_flags; /* various processing flags */ 217 pdu_header_t pdu_hdr; /* Buffer for PDU associated with cmd */ 218 void *pdu_temp_data; /* (free after use) */ 219 uint32_t pdu_temp_data_len; /* size of temp data */ 220 221 struct uio pdu_uio; /* UIO structure */ 222 struct iovec pdu_io_vec[4]; 223 /* Header + data + data-digest + padding */ 224 225 struct uio pdu_save_uio; 226 /* UIO structure save for retransmits */ 227 struct iovec pdu_save_iovec[4]; 228 /* Header + data + data-digest + padding */ 229 uint32_t pdu_data_digest; 230 /* holds data digest if enabled */ 231 ccb_t *pdu_owner; 232 /* the ccb this PDU belongs to (if any) */ 233 connection_t *pdu_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) ccb_chain; 250 /* either freelist or waiting list (or no list) */ 251 252 uint32_t ccb_status; /* Status gets entered here */ 253 ccb_disp_t ccb_disp; /* what to do with this ccb */ 254 255 struct callout ccb_timeout; /* To make sure it isn't lost */ 256 TAILQ_ENTRY(ccb_s) ccb_tchain; 257 tout_state_t ccb_timedout; 258 int ccb_num_timeouts; 259 /* How often we've sent out SNACK without answer */ 260 int ccb_total_tries; 261 /* How often we've tried to recover */ 262 263 uint32_t ccb_ITT; 264 /* task tag: ITT counter + sess id + CCB index */ 265 sernum_buffer_t ccb_DataSN_buf; 266 /* Received Data Seq nums (read ops only) */ 267 268 void *ccb_par; 269 /* misc. parameter for this request */ 270 struct scsipi_xfer *ccb_xs; 271 /* the scsipi_xfer for this cmd */ 272 273 void *ccb_temp_data; 274 /* to hold state (mainly during negotiation) */ 275 void *ccb_text_data; 276 /* holds accumulated text for continued PDUs */ 277 uint32_t ccb_text_len; 278 /* length of text data so far */ 279 280 uint64_t ccb_lun; /* LUN */ 281 uint32_t ccb_tag; /* Command tag */ 282 uint8_t *ccb_cmd; /* SCSI command block */ 283 uint16_t ccb_cmdlen; /* SCSI command block length */ 284 bool ccb_data_in; /* if this is a read request */ 285 uint8_t *ccb_data_ptr; /* data pointer for read/write */ 286 uint32_t ccb_data_len; /* total data length */ 287 uint32_t ccb_xfer_len; /* data transferred on read */ 288 uint32_t ccb_residual; /* residual data size */ 289 290 void *ccb_sense_ptr; /* sense data pointer */ 291 int ccb_sense_len_req; /* requested sense data length */ 292 int ccb_sense_len_got; /* actual sense data length */ 293 294 pdu_t *ccb_pdu_waiting; /* PDU waiting to be ack'ed */ 295 volatile uint32_t ccb_CmdSN; /* CmdSN associated with waiting PDU */ 296 297 int ccb_flags; 298 connection_t *ccb_connection; /* connection for CCB */ 299 session_t *ccb_session; /* session for CCB */ 300 }; 301 302 303 /* the CCB list type */ 304 305 TAILQ_HEAD(ccb_list_s, ccb_s); 306 typedef struct ccb_list_s ccb_list_t; 307 308 309 /* 310 Per connection data: the connection structure 311 */ 312 struct connection_s { 313 TAILQ_ENTRY(connection_s) c_connections; 314 315 kmutex_t c_lock; 316 kcondvar_t c_conn_cv; 317 kcondvar_t c_pdu_cv; 318 kcondvar_t c_ccb_cv; 319 kcondvar_t c_idle_cv; 320 321 pdu_list_t c_pdu_pool; /* the free PDU pool */ 322 323 ccb_list_t c_ccbs_waiting; 324 /* CCBs waiting for completion */ 325 326 pdu_list_t c_pdus_to_send; 327 /* the PDUs waiting to be sent */ 328 329 sernum_buffer_t c_StatSN_buf; 330 /* to keep track of received StatSNs */ 331 332 uint32_t c_max_transfer; 333 /* min(MaxRecvDataSegmentLength, MaxBurstLength) */ 334 uint32_t c_max_firstimmed; 335 /* 0 if InitialR2T=Yes, else 336 min of (MaxRecvDataSegmentLength, FirstBurstLength) */ 337 uint32_t c_max_firstdata; 338 /* 0 if ImmediateData=No, else min of */ 339 /* (MaxRecvDataSegmentLength, FirstBurstLength) */ 340 341 uint32_t c_MaxRecvDataSegmentLength; 342 /* Target's value */ 343 uint32_t c_Our_MaxRecvDataSegmentLength; 344 /* Our own value */ 345 bool c_HeaderDigest; /* TRUE if doing CRC */ 346 bool c_DataDigest; /* TRUE if doing CRC */ 347 uint32_t c_Time2Wait; 348 /* Negotiated default or logout value */ 349 uint32_t c_Time2Retain; 350 /* Negotiated default or logout value */ 351 352 uint16_t c_id; 353 /* connection ID (unique within session) */ 354 355 conn_state_t c_state; /* State of connection */ 356 357 struct lwp *c_threadobj; 358 /* proc/thread pointer of socket owner */ 359 360 krwlock_t c_sock_rw; 361 struct file *c_sock; /* the connection's socket */ 362 session_t *c_session; 363 /* back pointer to the owning session */ 364 365 struct lwp *c_rcvproc; /* receive thread */ 366 struct lwp *c_sendproc; /* send thread */ 367 368 uint32_t c_terminating; 369 /* if closing down: status */ 370 int c_recover; /* recovery count */ 371 /* (reset on first successful data transfer) */ 372 volatile unsigned c_usecount; /* number of active CCBs */ 373 unsigned c_pducount; /* number of active PDUs */ 374 375 bool c_destroy; /* conn will be destroyed */ 376 bool c_in_session; 377 /* if it's linked into the session list */ 378 logout_state_t c_loggedout; 379 /* status of logout (for recovery) */ 380 struct callout c_timeout; 381 /* Timeout for checking if connection is dead */ 382 TAILQ_ENTRY(connection_s) c_tchain; 383 tout_state_t c_timedout; 384 int c_num_timeouts; 385 /* How often we've sent out a NOP without answer */ 386 uint32_t c_idle_timeout_val; 387 /* Connection timeout value when idle */ 388 389 iscsi_login_parameters_t *c_login_par; 390 /* only valid during login */ 391 392 pdu_t c_pdu[PDUS_PER_CONNECTION]; /* PDUs */ 393 }; 394 395 /* the connection list type */ 396 397 TAILQ_HEAD(connection_list_s, connection_s); 398 typedef struct connection_list_s connection_list_t; 399 400 401 /* 402 Per session data: the session structure 403 */ 404 405 struct session_s { 406 /* Interface to child drivers. 407 NOTE: sc_adapter MUST be the first field in this structure so we can 408 easily get from adapter to session. 409 */ 410 struct scsipi_adapter s_sc_adapter; 411 struct scsipi_channel s_sc_channel; 412 413 device_t s_child_dev; 414 /* the child we're associated with - (NULL if not mapped) */ 415 416 int s_refcount; /* session in use by scsipi */ 417 418 /* local stuff */ 419 TAILQ_ENTRY(session_s) s_sessions; /* the list of sessions */ 420 421 kmutex_t s_lock; 422 kcondvar_t s_sess_cv; 423 kcondvar_t s_ccb_cv; 424 425 ccb_list_t s_ccb_pool; /* The free CCB pool */ 426 427 int s_send_window; 428 429 uint16_t s_id; /* session ID (unique within driver) */ 430 uint16_t s_TSIH; /* Target assigned session ID */ 431 432 uint32_t s_CmdSN; /* Current CmdSN */ 433 uint32_t s_ExpCmdSN; /* Current max ExpCmdSN received */ 434 uint32_t s_MaxCmdSN; /* Current MaxCmdSN */ 435 436 /* negotiated values */ 437 uint32_t s_ErrorRecoveryLevel; 438 uint32_t s_FirstBurstLength; 439 uint32_t s_MaxBurstLength; 440 bool s_ImmediateData; 441 bool s_InitialR2T; 442 uint32_t s_MaxOutstandingR2T; 443 uint32_t s_MaxConnections; 444 uint32_t s_DefaultTime2Wait; 445 uint32_t s_DefaultTime2Retain; 446 447 iscsi_login_session_type_t s_login_type; /* session type */ 448 449 /* for send_targets requests */ 450 uint8_t *s_target_list; 451 uint32_t s_target_list_len; 452 453 uint32_t s_conn_id; /* connection ID counter */ 454 455 uint32_t s_terminating; /* if closing down: status */ 456 457 uint32_t s_active_connections; 458 /* currently active connections */ 459 uint32_t s_total_connections; 460 /* connections associated with this session (active or winding down) */ 461 connection_list_t s_conn_list; /* the list of connections */ 462 connection_t *s_mru_connection; 463 /* the most recently used connection */ 464 465 ccb_t s_ccb[CCBS_PER_SESSION]; /* CCBs */ 466 467 char s_tgtname[ISCSI_STRING_LENGTH + 1]; 468 /* iSCSI target name */ 469 }; 470 471 /* the session list type */ 472 473 TAILQ_HEAD(session_list_s, session_s); 474 typedef struct session_list_s session_list_t; 475 476 477 /* 478 Event notification structures 479 */ 480 481 typedef struct event_s { 482 TAILQ_ENTRY(event_s) ev_link; /* next event in queue */ 483 iscsi_event_t ev_event_kind; /* which event */ 484 uint32_t ev_session_id; /* affected session ID */ 485 uint32_t ev_connection_id;/* affected connection ID */ 486 uint32_t ev_reason; /* event reason */ 487 } event_t; 488 489 /* the event list entry type */ 490 491 TAILQ_HEAD(event_list_s, event_s); 492 typedef struct event_list_s event_list_t; 493 494 495 typedef struct event_handler_s { 496 TAILQ_ENTRY(event_handler_s) evh_link; /* next handler */ 497 uint32_t evh_id; /* unique ID */ 498 event_list_t evh_events; /* list of events pending */ 499 iscsi_wait_event_parameters_t *evh_waiter; /* waiting parameter */ 500 /* following to detect dead handlers */ 501 event_t *evh_first_in_list; 502 } event_handler_t; 503 504 /* the event list entry type */ 505 506 TAILQ_HEAD(event_handler_list_s, event_handler_s); 507 typedef struct event_handler_list_s event_handler_list_t; 508 509 /* /dev/iscsi0 state */ 510 struct iscsifd { 511 TAILQ_ENTRY(iscsifd) fd_link; 512 device_t fd_dev; 513 int fd_unit; 514 }; 515 516 /* ------------------------- Global Variables ----------------------------- */ 517 518 /* In iscsi_main.c */ 519 520 extern struct cfattach iscsi_ca; /* the device attach structure */ 521 522 extern session_list_t iscsi_sessions; /* the list of sessions */ 523 extern bool iscsi_detaching; /* signal to cleanup thread it should exit */ 524 extern uint32_t iscsi_num_send_threads; /* the number of active send threads */ 525 526 extern uint8_t iscsi_InitiatorName[ISCSI_STRING_LENGTH]; 527 extern uint8_t iscsi_InitiatorAlias[ISCSI_STRING_LENGTH]; 528 extern login_isid_t iscsi_InitiatorISID; 529 530 /* Debugging stuff */ 531 532 #ifndef DDB 533 #define Debugger() panic("should call debugger here (iscsi.c)") 534 #endif /* ! DDB */ 535 536 #ifdef ISCSI_DEBUG 537 538 extern int iscsi_debug_level; /* How much debug info to display */ 539 extern bool iscsi_hex_bignums; /* Whether to encode parameters in hex or base64 */ 540 541 #define DEBOUT(x) printf x 542 #define DEB(lev,x) { if (iscsi_debug_level >= lev) printf x ;} 543 #define DEBC(conn,lev,x) { if (iscsi_debug_level >= lev) { printf("S%dC%d: ", \ 544 conn && conn->c_session ? conn->c_session->s_id : -1, \ 545 conn ? conn->c_id : -1); printf x ;}} 546 547 #define STATIC static 548 549 #else 550 551 #define DEBOUT(x) 552 #define DEB(lev,x) 553 #define DEBC(conn,lev,x) 554 555 #define STATIC static 556 557 #endif 558 559 /* Critical section macros */ 560 561 /* misc stuff */ 562 #define min(a, b) ((a) < (b)) ? (a) : (b) 563 #define max(a, b) ((a) < (b)) ? (b) : (a) 564 565 566 /* 567 Convert unsigned int to 3-byte value (for DataSegmentLength field in PDU) 568 */ 569 570 static __inline void 571 hton3(uint32_t val, uint8_t *bytes) 572 { 573 bytes[0] = (uint8_t) (val >> 16); 574 bytes[1] = (uint8_t) (val >> 8); 575 bytes[2] = (uint8_t) val; 576 } 577 578 /* 579 Convert 3-byte value to unsigned int (for DataSegmentLength field in PDU) 580 */ 581 582 static __inline uint32_t 583 ntoh3(uint8_t *bytes) 584 { 585 return (bytes[0] << 16) | (bytes[1] << 8) | bytes[2]; 586 } 587 588 589 /* 590 * Convert uint64 to network byte order (for LUN field in PDU) 591 */ 592 static __inline uint64_t 593 htonq(uint64_t x) 594 { 595 #if BYTE_ORDER == LITTLE_ENDIAN 596 uint8_t *s = (uint8_t *) & x; 597 return (uint64_t) ((uint64_t) s[0] << 56 | (uint64_t) s[1] << 48 | 598 (uint64_t) s[2] << 40 | (uint64_t) s[3] << 32 | 599 (uint64_t) s[4] << 24 | (uint64_t) s[5] << 16 | 600 (uint64_t) s[6] << 8 | (uint64_t) s[7]); 601 #else 602 return x; 603 #endif 604 } 605 606 #define ntohq(x) htonq(x) 607 608 /* 609 * Serial number buffer empty? 610 */ 611 612 static __inline bool 613 sn_empty(sernum_buffer_t *buf) 614 { 615 return buf->top == buf->bottom; 616 } 617 618 619 /* 620 * Serial number compare 621 */ 622 623 static __inline bool 624 sn_a_lt_b(uint32_t a, uint32_t b) 625 { 626 return (a < b && !((b - a) & 0x80000000)) || 627 (a > b && ((a - b) & 0x80000000)); 628 } 629 630 static __inline bool 631 sn_a_le_b(uint32_t a, uint32_t b) 632 { 633 return (a <= b && !((b - a) & 0x80000000)) || 634 (a >= b && ((a - b) & 0x80000000)); 635 } 636 637 /* in iscsi_ioctl.c */ 638 639 void iscsi_init_cleanup(void); 640 int iscsi_destroy_cleanup(void); 641 void iscsi_notify_cleanup(void); 642 643 644 /* Parameter for logout is reason code in logout PDU, -1 for don't send logout */ 645 #define NO_LOGOUT -1 646 #define LOGOUT_SESSION 0 647 #define LOGOUT_CONNECTION 1 648 #define RECOVER_CONNECTION 2 649 650 void add_event(iscsi_event_t, uint32_t, uint32_t, uint32_t); 651 652 void kill_connection(connection_t *, uint32_t, int, bool); 653 void kill_session(uint32_t, uint32_t, int, bool); 654 int kill_all_sessions(void); 655 void handle_connection_error(connection_t *, uint32_t, int); 656 void add_connection_cleanup(connection_t *); 657 658 int iscsiioctl(struct file *, u_long, void *); 659 660 session_t *find_session(uint32_t); 661 connection_t *find_connection(session_t *, uint32_t); 662 int ref_session(session_t *); 663 void unref_session(session_t *); 664 665 /* in iscsi_main.c */ 666 667 /*void iscsiattach(void *); */ 668 int iscsidetach(device_t, int); 669 670 void iscsi_done(ccb_t *); 671 int map_session(session_t *, device_t); 672 int unmap_session(session_t *); 673 674 /* in iscsi_send.c */ 675 676 void iscsi_send_thread(void *); 677 678 connection_t *assign_connection(session_t *session, bool waitok); 679 void resend_pdu(ccb_t *); 680 int send_login(connection_t *); 681 int send_logout(connection_t *, connection_t *, int, bool); 682 int send_data_out(connection_t *, pdu_t *, ccb_t *, ccb_disp_t, bool); 683 void send_run_xfer(session_t *, struct scsipi_xfer *); 684 int send_send_targets(session_t *, uint8_t *); 685 int send_task_management(connection_t *, ccb_t *, struct scsipi_xfer *, int); 686 687 void negotiate_login(connection_t *, pdu_t *, ccb_t *); 688 void acknowledge_text(connection_t *, pdu_t *, ccb_t *); 689 void start_text_negotiation(connection_t *); 690 void negotiate_text(connection_t *, pdu_t *, ccb_t *); 691 int send_nop_out(connection_t *, pdu_t *); 692 void snack_missing(connection_t *, ccb_t *, uint8_t, uint32_t, uint32_t); 693 void send_snack(connection_t *, pdu_t *, ccb_t *, uint8_t); 694 int send_send_targets(session_t *, uint8_t *); 695 696 void send_command(ccb_t *, ccb_disp_t, bool, bool); 697 #ifndef ISCSI_MINIMAL 698 int send_io_command(session_t *, uint64_t, scsireq_t *, bool, uint32_t); 699 #endif 700 701 void connection_timeout_co(void *); 702 void ccb_timeout_co(void *); 703 704 void connection_timeout(connection_t *); 705 void connection_timeout_start(connection_t *, int); 706 void connection_timeout_stop(connection_t *); 707 void ccb_timeout(ccb_t *); 708 void ccb_timeout_start(ccb_t *, int); 709 void ccb_timeout_stop(ccb_t *); 710 711 /* in iscsi_rcv.c */ 712 713 void iscsi_rcv_thread(void *); 714 715 /* in iscsi_utils.c */ 716 717 uint32_t gen_digest(const void *, size_t); 718 uint32_t gen_digest_2(const void *, size_t, const void *, size_t); 719 720 void create_ccbs(session_t *); 721 void destroy_ccbs(session_t *); 722 ccb_t *get_ccb(connection_t *, bool); 723 void free_ccb(ccb_t *); 724 void suspend_ccb(ccb_t *, bool); 725 void wake_ccb(ccb_t *, uint32_t); 726 727 void create_pdus(connection_t *); 728 pdu_t *get_pdu(connection_t *, bool); 729 void free_pdu(pdu_t *); 730 731 void init_sernum(sernum_buffer_t *); 732 int add_sernum(sernum_buffer_t *, uint32_t); 733 uint32_t ack_sernum(sernum_buffer_t *, uint32_t); 734 735 uint32_t get_sernum(session_t *, pdu_t *); 736 int sernum_in_window(session_t *); 737 int window_size(session_t *, int); 738 739 /* in iscsi_text.c */ 740 741 int assemble_login_parameters(connection_t *, ccb_t *, pdu_t *); 742 int assemble_security_parameters(connection_t *, ccb_t *, pdu_t *, pdu_t *); 743 int assemble_negotiation_parameters(connection_t *, ccb_t *, pdu_t *, pdu_t *); 744 int init_text_parameters(connection_t *, ccb_t *); 745 int assemble_send_targets(pdu_t *, uint8_t *); 746 void set_negotiated_parameters(ccb_t *); 747 748 #endif /* !_ISCSI_GLOBALS_H */ 749