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