1/* $NetBSD: iscsi_globals.h,v 1.2 2011/11/29 03:50:31 tls 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/* 77Various checks are made that the expected cmd Serial Number is less than 78the actual command serial number. The extremely paranoid amongst us 79believe that a malicious iSCSI server could set this artificially low 80and effectively DoS a naive initiator. For this (possibly ludicrous) 81reason, I have added the two definitions below (agc, 2011/04/09). The 82throttling definition enables a check that the CmdSN is less than the 83ExpCmdSN in iscsi_send.c, and is enabled by default. The second definition 84effectively says "don't bother testing these values", and is used right 85now only in iscsi_send.c. 86 */ 87#define ISCSI_TROTTLING_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 0x01 /* received status */ 135#define CCBF_RESENT 0x02 /* ccb was resent */ 136#define CCBF_SENDTARGET 0x04 /* SendTargets text request, not negotiation */ 137#define CCBF_WAITING 0x08 /* CCB is waiting for MaxCmdSN, wake it up */ 138#define CCBF_GOT_RSP 0x10 /* Got at least one response to this request */ 139#define CCBF_REASSIGN 0x20 /* Command can be reassigned */ 140#define CCBF_OTHERCONN 0x40 /* a logout for a different connection */ 141 142 143/* --------------------------- Global Types ------------------------------- */ 144 145/* Connection state */ 146 147typedef enum { 148 /* first three correspond to CSG/NSG coding */ 149 ST_SEC_NEG = 0, /* security negotiation phase */ 150 ST_OP_NEG = 1, /* operational negotiation phase */ 151 ST_FULL_FEATURE = 3, /* full feature phase */ 152 /* rest is internal */ 153 ST_WINDING_DOWN = 4, /* connection termination initiated, logging out */ 154 ST_LOGOUT_SENT = 5, /* logout has been sent */ 155 ST_SETTLING = 6, /* waiting for things to settle down */ 156 ST_IDLE = 7 /* connection is idle (ready to delete) */ 157} conn_state_t; 158 159 160/* Logout state */ 161 162typedef enum { 163 NOT_LOGGED_OUT, /* Not logged out */ 164 LOGOUT_SENT, /* Logout was sent */ 165 LOGOUT_SUCCESS, /* Logout succeeded */ 166 LOGOUT_FAILED /* Logout failed */ 167} logout_state_t; 168 169 170/* CCB Disposition */ 171 172typedef enum { 173 CCBDISP_UNUSED, /* 0 = In free pool */ 174 CCBDISP_BUSY, /* This CCB is busy, don't allow rx ops */ 175 CCBDISP_NOWAIT, /* Not waiting for anything */ 176 CCBDISP_FREE, /* Free this CCB when done */ 177 CCBDISP_WAIT, /* Calling thread is waiting for completion */ 178 CCBDISP_SCSIPI, /* Call scsipi_done when operation completes */ 179 CCBDISP_DEFER /* Defer waiting until all PDUs have been queued */ 180} ccb_disp_t; 181 182 183/* PDU Disposition */ 184 185typedef enum { 186 PDUDISP_UNUSED, /* 0 = In free pool */ 187 PDUDISP_SIGNAL, /* Free this PDU when done and wakeup(pdu) */ 188 PDUDISP_FREE, /* Free this PDU when done */ 189 PDUDISP_WAIT /* Waiting for acknowledge */ 190} pdu_disp_t; 191 192 193typedef struct connection_s connection_t; 194typedef struct session_s session_t; 195typedef struct ccb_s ccb_t; 196typedef struct pdu_s pdu_t; 197 198 199#include "iscsi_testlocal.h" 200 201 202/* the serial number management structure (a circular buffer) */ 203 204typedef struct { 205 uint32_t ExpSN; /* ExpxxSN (Data or Stat) sent to the target */ 206 uint32_t next_sn; /* next_sn (== ExpSN if no ack is pending) */ 207 int top; /* top of buffer (newest element) */ 208 int bottom; /* bottom of buffer (oldest element) */ 209 uint32_t sernum[SERNUM_BUFFER_LENGTH]; /* the serial numbers */ 210 int ack[SERNUM_BUFFER_LENGTH]; /* acknowledged? */ 211} sernum_buffer_t; 212 213 214/* 215 The per-PDU data structure. 216*/ 217 218struct pdu_s { 219 TAILQ_ENTRY(pdu_s) chain; /* freelist or wait list (or no list) */ 220 TAILQ_ENTRY(pdu_s) send_chain; 221 /* chaining PDUs waiting to be sent */ 222 pdu_disp_t disp; /* what to do with this pdu */ 223 uint32_t flags; /* various processing flags */ 224 pdu_header_t pdu; /* Buffer for PDU associated with cmd */ 225 void *temp_data; /* (free after use) */ 226 uint32_t temp_data_len; /* size of temp data */ 227 228 struct uio uio; /* UIO structure */ 229 struct iovec io_vec[4]; 230 /* Header + data + data-digest + padding */ 231 232 struct uio save_uio; 233 /* UIO structure save for retransmits */ 234 struct iovec save_iovec[4]; 235 /* Header + data + data-digest + padding */ 236 uint32_t data_digest; 237 /* holds data digest if enabled */ 238 ccb_t *owner; 239 /* the ccb this PDU belongs to (if any) */ 240 connection_t *connection; 241 /* the connection this PDU belongs to */ 242 243#ifdef ISCSI_TEST_MODE 244 pdu_header_t mod_pdu; 245 /* Buffer for modified PDU header (test mode) */ 246#endif 247 248#ifdef ISCSI_PERFTEST 249 int perf_index; 250 /* performance counter index */ 251 perfpoint_t perf_which; /* performance point */ 252#endif 253}; 254 255 256/* the PDU list type */ 257 258TAILQ_HEAD(pdu_list_s, pdu_s); 259typedef struct pdu_list_s pdu_list_t; 260 261/* 262 The per-command data structure. Calling it ccb in correspondence 263 to other HA drivers. 264*/ 265 266struct ccb_s { 267 TAILQ_ENTRY(ccb_s) chain; 268 /* either freelist or waiting list (or no list) */ 269 270 uint32_t status; /* Status gets entered here */ 271 ccb_disp_t disp; /* what to do with this ccb */ 272 273 struct callout timeout; /* To make sure it isn't lost */ 274 int num_timeouts; 275 /* How often we've sent out SNACK without answer */ 276 int total_tries; 277 /* How often we've tried to recover */ 278 279 uint32_t ITT; 280 /* task tag: ITT counter + sess id + CCB index */ 281 sernum_buffer_t DataSN_buf; 282 /* Received Data Seq nums (read ops only) */ 283 284 void *par; 285 /* misc. parameter for this request */ 286 struct scsipi_xfer *xs; 287 /* the scsipi_xfer for this cmd */ 288 289 void *temp_data; 290 /* to hold state (mainly during negotiation) */ 291 void *text_data; 292 /* holds accumulated text for continued PDUs */ 293 uint32_t text_len; 294 /* length of text data so far */ 295 296 uint64_t lun; /* LUN */ 297 uint8_t *cmd; /* SCSI command block */ 298 uint16_t cmdlen; /* SCSI command block length */ 299 bool data_in; /* if this is a read request */ 300 uint8_t *data_ptr; /* data pointer for read/write */ 301 uint32_t data_len; /* total data length */ 302 uint32_t xfer_len; /* data transferred on read */ 303 uint32_t residual; /* residual data size */ 304 305 void *sense_ptr; /* sense data pointer */ 306 int sense_len_req; /* requested sense data length */ 307 int sense_len_got; /* actual sense data length */ 308 309 pdu_t *pdu_waiting; /* PDU waiting to be ack'ed */ 310 uint32_t CmdSN; /* CmdSN associated with waiting PDU */ 311 312 int flags; 313 connection_t *connection; /* connection for CCB */ 314 session_t *session; /* session for CCB */ 315 316#ifdef ISCSI_PERFTEST 317 int perf_index; /* performance counter index */ 318#endif 319}; 320 321 322/* the CCB list type */ 323 324TAILQ_HEAD(ccb_list_s, ccb_s); 325typedef struct ccb_list_s ccb_list_t; 326 327 328/* 329 Per connection data: the connection structure 330*/ 331#if (__NetBSD_Version__ >= 399000900) 332typedef struct lwp *PTHREADOBJ; 333#else 334typedef struct proc *PTHREADOBJ; 335#endif 336 337 338struct connection_s { 339 TAILQ_ENTRY(connection_s) connections; 340 341 pdu_list_t pdu_pool; /* the free PDU pool */ 342 343 ccb_list_t ccbs_waiting; 344 /* CCBs waiting for completion */ 345 346 pdu_list_t pdus_to_send; 347 /* the PDUs waiting to be sent */ 348 349 sernum_buffer_t StatSN_buf; 350 /* to keep track of received StatSNs */ 351 352 uint32_t max_transfer; 353 /* min(MaxRecvDataSegmentLength, MaxBurstLength) */ 354 uint32_t max_firstimmed; 355 /* 0 if InitialR2T=Yes, else 356 min of (MaxRecvDataSegmentLength, FirstBurstLength) */ 357 uint32_t max_firstdata; 358 /* 0 if ImmediateData=No, else min of */ 359 /* (MaxRecvDataSegmentLength, FirstBurstLength) */ 360 361 uint32_t MaxRecvDataSegmentLength; 362 /* Target's value */ 363 uint32_t Our_MaxRecvDataSegmentLength; 364 /* Our own value */ 365 bool HeaderDigest; /* TRUE if doing CRC */ 366 bool DataDigest; /* TRUE if doing CRC */ 367 uint32_t Time2Wait; 368 /* Negotiated default or logout value */ 369 uint32_t Time2Retain; 370 /* Negotiated default or logout value */ 371 372 uint16_t id; 373 /* connection ID (unique within session) */ 374 375 conn_state_t state; /* State of connection */ 376 377 PTHREADOBJ threadobj; 378 /* proc/thread pointer of socket owner */ 379 struct file *sock; /* the connection's socket */ 380 session_t *session; 381 /* back pointer to the owning session */ 382 383 struct lwp *rcvproc; /* receive thread */ 384 struct lwp *sendproc; /* send thread */ 385 386 uint32_t terminating; 387 /* if closing down: status */ 388 int recover; /* recovery count */ 389 /* (reset on first successful data transfer) */ 390 int usecount; /* number of active CCBs */ 391 392 bool destroy; /* conn will be destroyed */ 393 bool in_session; 394 /* if it's linked into the session list */ 395 logout_state_t loggedout; 396 /* status of logout (for recovery) */ 397 struct callout timeout; 398 /* Timeout for checking if connection is dead */ 399 int num_timeouts; 400 /* How often we've sent out a NOP without answer */ 401 uint32_t idle_timeout_val; 402 /* Connection timeout value when idle */ 403 404 iscsi_login_parameters_t *login_par; 405 /* only valid during login */ 406 407 pdu_t pdu[PDUS_PER_CONNECTION]; /* PDUs */ 408 409#ifdef ISCSI_TEST_MODE 410 test_pars_t *test_pars; 411 /* connection in test mode if non-NULL */ 412#endif 413}; 414 415/* the connection list type */ 416 417TAILQ_HEAD(connection_list_s, connection_s); 418typedef struct connection_list_s connection_list_t; 419 420 421/* 422 Per session data: the session structure 423*/ 424 425struct session_s { 426 /* Interface to child drivers. 427 NOTE: sc_adapter MUST be the first field in this structure so we can 428 easily get from adapter to session. 429 */ 430 struct scsipi_adapter sc_adapter; 431 struct scsipi_channel sc_channel; 432 433 device_t child_dev; 434 /* the child we're associated with - (NULL if not mapped) */ 435 436 /* local stuff */ 437 TAILQ_ENTRY(session_s) sessions; /* the list of sessions */ 438 439 ccb_list_t ccb_pool; /* The free CCB pool */ 440 ccb_list_t ccbs_throttled; 441 /* CCBs waiting for MaxCmdSN to increase */ 442 443 uint16_t id; /* session ID (unique within driver) */ 444 uint16_t TSIH; /* Target assigned session ID */ 445 446 uint32_t CmdSN; /* Current CmdSN */ 447 uint32_t ExpCmdSN; /* Current max ExpCmdSN received */ 448 uint32_t MaxCmdSN; /* Current MaxCmdSN */ 449 450 /* negotiated values */ 451 uint32_t ErrorRecoveryLevel; 452 uint32_t FirstBurstLength; 453 uint32_t MaxBurstLength; 454 bool ImmediateData; 455 bool InitialR2T; 456 uint32_t MaxOutstandingR2T; 457 uint32_t MaxConnections; 458 uint32_t DefaultTime2Wait; 459 uint32_t DefaultTime2Retain; 460 461 iscsi_login_session_type_t login_type; /* session type */ 462 463 /* for send_targets requests */ 464 uint8_t *target_list; 465 uint32_t target_list_len; 466 467 uint32_t conn_id; /* connection ID counter */ 468 469 uint32_t terminating; /* if closing down: status */ 470 471 uint32_t active_connections; 472 /* currently active connections */ 473 uint32_t total_connections; 474 /* connections associated with this session (active or winding down) */ 475 connection_list_t conn_list; /* the list of connections */ 476 connection_t *mru_connection; 477 /* the most recently used connection */ 478 479 uint8_t itt_id; /* counter for use in ITT */ 480 481 ccb_t ccb[CCBS_PER_SESSION]; /* CCBs */ 482 483 char tgtname[ISCSI_STRING_LENGTH + 1]; 484 /* iSCSI target name */ 485}; 486 487/* the session list type */ 488 489TAILQ_HEAD(session_list_s, session_s); 490typedef struct session_list_s session_list_t; 491 492 493/* 494 The softc structure. This driver doesn't really need one, because there's 495 always just one instance, and for the time being it's only loaded as 496 an LKM (which doesn't create a softc), but we need one to put into the 497 scsipi interface structures, so here it is. 498*/ 499 500typedef struct iscsi_softc { 501 device_t sc_dev; 502} iscsi_softc_t; 503 504 505/* 506 Event notification structures 507*/ 508 509typedef struct event_s { 510 TAILQ_ENTRY(event_s) link; /* next event in queue */ 511 iscsi_event_t event_kind; /* which event */ 512 uint32_t session_id; /* affected session ID */ 513 uint32_t connection_id; /* affected connection ID */ 514 uint32_t reason; /* event reason */ 515} event_t; 516 517/* the event list entry type */ 518 519TAILQ_HEAD(event_list_s, event_s); 520typedef struct event_list_s event_list_t; 521 522 523typedef struct event_handler_s { 524 TAILQ_ENTRY(event_handler_s) link; /* next handler */ 525 uint32_t id; /* unique ID */ 526 event_list_t events; /* list of events pending */ 527 iscsi_wait_event_parameters_t *waiter; /* waiting parameter */ 528 /* following to detect dead handlers */ 529 event_t *first_in_list; 530} event_handler_t; 531 532/* the event list entry type */ 533 534TAILQ_HEAD(event_handler_list_s, event_handler_s); 535typedef struct event_handler_list_s event_handler_list_t; 536 537 538/* ------------------------- Global Variables ----------------------------- */ 539 540/* In iscsi_main.c */ 541 542struct cfattach iscsi_ca; /* the device attach structure */ 543struct cdevsw iscsi_cdevsw; /* the character device descriptor */ 544 545iscsi_softc_t *sc; /* our device pointer */ 546session_list_t sessions; /* the list of sessions */ 547 548connection_list_t cleanup_list; /* connections to clean up */ 549bool detaching; /* signal to cleanup thread it should exit */ 550struct lwp *cleanproc; /* pointer to cleanup proc */ 551 552uint32_t num_send_threads; /* the number of active send threads */ 553 554uint8_t InitiatorName[ISCSI_STRING_LENGTH]; 555uint8_t InitiatorAlias[ISCSI_STRING_LENGTH]; 556login_isid_t 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 568int 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 583int 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 ;}} 590void 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#define CS_BEGIN { int s = splbio (); 608#define CS_END splx (s); } 609 610/* misc stuff */ 611#define min(a, b) ((a) < (b)) ? (a) : (b) 612#define max(a, b) ((a) < (b)) ? (b) : (a) 613 614 615/* 616 Convert unsigned int to 3-byte value (for DataSegmentLength field in PDU) 617*/ 618 619static __inline void 620hton3(uint32_t val, uint8_t *bytes) 621{ 622 bytes[0] = (uint8_t) (val >> 16); 623 bytes[1] = (uint8_t) (val >> 8); 624 bytes[2] = (uint8_t) val; 625} 626 627/* 628 Convert 3-byte value to unsigned int (for DataSegmentLength field in PDU) 629*/ 630 631static __inline uint32_t 632ntoh3(uint8_t *bytes) 633{ 634 return (bytes[0] << 16) | (bytes[1] << 8) | bytes[2]; 635} 636 637 638/* 639 * Convert uint64 to network byte order (for LUN field in PDU) 640*/ 641static __inline uint64_t 642htonq(uint64_t x) 643{ 644#if BYTE_ORDER == LITTLE_ENDIAN 645 uint8_t *s = (uint8_t *) & x; 646 return (uint64_t) ((uint64_t) s[0] << 56 | (uint64_t) s[1] << 48 | 647 (uint64_t) s[2] << 40 | (uint64_t) s[3] << 32 | 648 (uint64_t) s[4] << 24 | (uint64_t) s[5] << 16 | 649 (uint64_t) s[6] << 8 | (uint64_t) s[7]); 650#else 651 return x; 652#endif 653} 654 655#define ntohq(x) htonq(x) 656 657/* 658 * Serial number buffer empty? 659*/ 660 661static __inline bool 662sn_empty(sernum_buffer_t *buf) 663{ 664 return buf->top == buf->bottom; 665} 666 667 668/* 669 * Serial number compare 670*/ 671 672static __inline bool 673sn_a_lt_b(uint32_t a, uint32_t b) 674{ 675 return (a < b && !((b - a) & 0x80000000)) || 676 (a > b && ((a - b) & 0x80000000)); 677} 678 679static __inline bool 680sn_a_le_b(uint32_t a, uint32_t b) 681{ 682 return (a <= b && !((b - a) & 0x80000000)) || 683 (a >= b && ((a - b) & 0x80000000)); 684} 685 686 687/* Version dependencies */ 688 689 690#if (__NetBSD_Version__ >= 399000900) 691#define PROCP(obj) (obj->l_proc) 692#else 693#define PROCP(obj) obj 694#define UIO_SETUP_SYSSPACE(uio) (uio)->uio_segflg = UIO_SYSSPACE 695#endif 696 697#if (__NetBSD_Version__ >= 106000000) 698# ifdef ISCSI_TEST_MODE 699#define SET_CCB_TIMEOUT(conn, ccb, tout) do { \ 700 if (test_ccb_timeout (conn)) { \ 701 callout_schedule(&ccb->timeout, tout); \ 702 } \ 703} while (/*CONSTCOND*/ 0) 704# else 705#define SET_CCB_TIMEOUT(conn, ccb, tout) callout_schedule(&ccb->timeout, tout) 706# endif 707#else 708/* no test mode for 1.5 */ 709#define SET_CCB_TIMEOUT(conn, ccb, tout) \ 710 callout_reset(&ccb->timeout, tout, ccb_timeout, ccb) 711#endif 712 713#if (__NetBSD_Version__ >= 106000000) 714# ifdef ISCSI_TEST_MODE 715#define SET_CONN_TIMEOUT(conn, tout) do { \ 716 if (test_conn_timeout (conn)) { \ 717 callout_schedule(&conn->timeout, tout); \ 718 } \ 719} while (/*CONSTCOND*/0) 720# else 721#define SET_CONN_TIMEOUT(conn, tout) callout_schedule(&conn->timeout, tout) 722# endif 723#else 724/* no test mode for 1.5 */ 725#define SET_CONN_TIMEOUT(conn, tout) \ 726 callout_reset(&conn->timeout, tout, connection_timeout, conn) 727#endif 728 729/* in iscsi_ioctl.c */ 730 731/* Parameter for logout is reason code in logout PDU, -1 for don't send logout */ 732#define NO_LOGOUT -1 733#define LOGOUT_SESSION 0 734#define LOGOUT_CONNECTION 1 735#define RECOVER_CONNECTION 2 736 737void add_event(iscsi_event_t, uint32_t, uint32_t, uint32_t); 738 739void kill_connection(connection_t *, uint32_t, int, bool); 740void kill_session(session_t *, uint32_t, int, bool); 741void kill_all_sessions(void); 742void handle_connection_error(connection_t *, uint32_t, int); 743void iscsi_cleanup_thread(void *); 744 745#ifndef ISCSI_MINIMAL 746uint32_t map_databuf(struct proc *, void **, uint32_t); 747void unmap_databuf(struct proc *, void *, uint32_t); 748#endif 749int iscsiioctl(dev_t, u_long, void *, int, PTHREADOBJ); 750 751session_t *find_session(uint32_t); 752connection_t *find_connection(session_t *, uint32_t); 753 754 755/* in iscsi_main.c */ 756 757/*void iscsiattach(void *); */ 758int iscsidetach(device_t, int); 759 760void iscsi_done(ccb_t *); 761int map_session(session_t *); 762void unmap_session(session_t *); 763 764/* in iscsi_send.c */ 765 766void iscsi_send_thread(void *); 767 768connection_t *assign_connection(session_t *session, bool waitok); 769void resend_pdu(ccb_t *); 770int send_login(connection_t *); 771int send_logout(connection_t *, connection_t *, int, bool); 772int send_data_out(connection_t *, pdu_t *, ccb_t *, ccb_disp_t, bool); 773void send_run_xfer(session_t *, struct scsipi_xfer *); 774int send_send_targets(session_t *, uint8_t *); 775int send_task_management(connection_t *, ccb_t *, struct scsipi_xfer *, int); 776 777void negotiate_login(connection_t *, pdu_t *, ccb_t *); 778void acknowledge_text(connection_t *, pdu_t *, ccb_t *); 779void start_text_negotiation(connection_t *); 780void negotiate_text(connection_t *, pdu_t *, ccb_t *); 781int send_nop_out(connection_t *, pdu_t *); 782void snack_missing(connection_t *, ccb_t *, uint8_t, uint32_t, uint32_t); 783void send_snack(connection_t *, pdu_t *, ccb_t *, uint8_t); 784int send_send_targets(session_t *, uint8_t *); 785 786void send_command(ccb_t *, ccb_disp_t, bool, bool); 787#ifndef ISCSI_MINIMAL 788int send_io_command(session_t *, uint64_t, scsireq_t *, bool, uint32_t); 789#endif 790 791void connection_timeout(void *); 792void ccb_timeout(void *); 793 794/* in iscsi_rcv.c */ 795 796void iscsi_rcv_thread(void *); 797 798/* in iscsi_utils.c */ 799 800uint32_t gen_digest(void *, int); 801uint32_t gen_digest_2(void *, int, void *, int); 802 803void create_ccbs(session_t *); 804ccb_t *get_ccb(connection_t *, bool); 805void free_ccb(ccb_t *); 806void wake_ccb(ccb_t *); 807void complete_ccb(ccb_t *); 808 809void create_pdus(connection_t *); 810pdu_t *get_pdu(connection_t *); 811pdu_t *get_pdu_c(connection_t *, bool); 812void free_pdu(pdu_t *); 813 814void init_sernum(sernum_buffer_t *); 815int add_sernum(sernum_buffer_t *, uint32_t); 816uint32_t ack_sernum(sernum_buffer_t *, uint32_t); 817 818/* in iscsi_text.c */ 819 820int assemble_login_parameters(connection_t *, ccb_t *, pdu_t *); 821int assemble_security_parameters(connection_t *, ccb_t *, pdu_t *, pdu_t *); 822int assemble_negotiation_parameters(connection_t *, ccb_t *, pdu_t *, pdu_t *); 823int init_text_parameters(connection_t *, ccb_t *); 824int assemble_send_targets(pdu_t *, uint8_t *); 825void set_negotiated_parameters(ccb_t *); 826 827#endif /* !_ISCSI_GLOBALS_H */ 828