Home | History | Annotate | Line # | Download | only in iscsi
iscsi_utils.c revision 1.4
      1  1.4  mlelstv /*	$NetBSD: iscsi_utils.c,v 1.4 2012/06/25 20:34:26 mlelstv Exp $	*/
      2  1.1      agc 
      3  1.1      agc /*-
      4  1.1      agc  * Copyright (c) 2004,2005,2006,2008 The NetBSD Foundation, Inc.
      5  1.1      agc  * All rights reserved.
      6  1.1      agc  *
      7  1.1      agc  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1      agc  * by Wasabi Systems, Inc.
      9  1.1      agc  *
     10  1.1      agc  * Redistribution and use in source and binary forms, with or without
     11  1.1      agc  * modification, are permitted provided that the following conditions
     12  1.1      agc  * are met:
     13  1.1      agc  * 1. Redistributions of source code must retain the above copyright
     14  1.1      agc  *    notice, this list of conditions and the following disclaimer.
     15  1.1      agc  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1      agc  *    notice, this list of conditions and the following disclaimer in the
     17  1.1      agc  *    documentation and/or other materials provided with the distribution.
     18  1.1      agc  *
     19  1.1      agc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  1.1      agc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  1.1      agc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  1.1      agc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  1.1      agc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  1.1      agc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  1.1      agc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  1.1      agc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  1.1      agc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  1.1      agc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  1.1      agc  * POSSIBILITY OF SUCH DAMAGE.
     30  1.1      agc  */
     31  1.1      agc #include "iscsi_globals.h"
     32  1.1      agc 
     33  1.1      agc #include <sys/systm.h>
     34  1.1      agc #include <sys/buf.h>
     35  1.1      agc #include <sys/socketvar.h>
     36  1.4  mlelstv #include <sys/bswap.h>
     37  1.1      agc 
     38  1.1      agc 
     39  1.1      agc #ifdef ISCSI_DEBUG
     40  1.1      agc 
     41  1.1      agc /* debug helper routine */
     42  1.1      agc void
     43  1.1      agc dump(void *buff, int len)
     44  1.1      agc {
     45  1.1      agc 	uint8_t *bp = (uint8_t *) buff;
     46  1.1      agc 	int i;
     47  1.1      agc 
     48  1.1      agc 	while (len > 0) {
     49  1.1      agc 		for (i = min(16, len); i > 0; i--)
     50  1.1      agc 			printf("%02x ", *bp++);
     51  1.1      agc 		printf("\n");
     52  1.1      agc 		len -= 16;
     53  1.1      agc 	}
     54  1.1      agc }
     55  1.1      agc 
     56  1.1      agc #endif
     57  1.1      agc 
     58  1.1      agc /*****************************************************************************
     59  1.1      agc  * Digest functions
     60  1.1      agc  *****************************************************************************/
     61  1.1      agc 
     62  1.1      agc /*****************************************************************
     63  1.1      agc  *
     64  1.1      agc  * CRC LOOKUP TABLE
     65  1.1      agc  * ================
     66  1.1      agc  * The following CRC lookup table was generated automagically
     67  1.1      agc  * by the Rocksoft^tm Model CRC Algorithm Table Generation
     68  1.1      agc  * Program V1.0 using the following model parameters:
     69  1.1      agc  *
     70  1.1      agc  *    Width   : 4 bytes.
     71  1.1      agc  *    Poly    : 0x1EDC6F41L
     72  1.1      agc  *    Reverse : TRUE.
     73  1.1      agc  *
     74  1.1      agc  * For more information on the Rocksoft^tm Model CRC Algorithm,
     75  1.1      agc  * see the document titled "A Painless Guide to CRC Error
     76  1.1      agc  * Detection Algorithms" by Ross Williams
     77  1.1      agc  * (ross (at) guest.adelaide.edu.au.). This document is likely to be
     78  1.1      agc  * in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft".
     79  1.1      agc  *
     80  1.1      agc  *****************************************************************/
     81  1.1      agc 
     82  1.1      agc STATIC uint32_t crc_table[256] = {
     83  1.1      agc 	0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
     84  1.1      agc 	0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
     85  1.1      agc 	0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
     86  1.1      agc 	0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
     87  1.1      agc 	0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
     88  1.1      agc 	0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
     89  1.1      agc 	0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
     90  1.1      agc 	0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
     91  1.1      agc 	0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
     92  1.1      agc 	0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
     93  1.1      agc 	0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
     94  1.1      agc 	0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
     95  1.1      agc 	0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
     96  1.1      agc 	0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
     97  1.1      agc 	0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
     98  1.1      agc 	0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
     99  1.1      agc 	0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
    100  1.1      agc 	0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
    101  1.1      agc 	0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
    102  1.1      agc 	0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
    103  1.1      agc 	0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
    104  1.1      agc 	0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
    105  1.1      agc 	0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
    106  1.1      agc 	0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
    107  1.1      agc 	0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
    108  1.1      agc 	0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
    109  1.1      agc 	0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
    110  1.1      agc 	0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
    111  1.1      agc 	0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
    112  1.1      agc 	0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
    113  1.1      agc 	0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
    114  1.1      agc 	0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
    115  1.1      agc 	0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
    116  1.1      agc 	0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
    117  1.1      agc 	0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
    118  1.1      agc 	0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
    119  1.1      agc 	0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
    120  1.1      agc 	0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
    121  1.1      agc 	0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
    122  1.1      agc 	0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
    123  1.1      agc 	0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
    124  1.1      agc 	0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
    125  1.1      agc 	0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
    126  1.1      agc 	0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
    127  1.1      agc 	0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
    128  1.1      agc 	0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
    129  1.1      agc 	0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
    130  1.1      agc 	0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
    131  1.1      agc 	0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
    132  1.1      agc 	0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
    133  1.1      agc 	0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
    134  1.1      agc 	0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
    135  1.1      agc 	0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
    136  1.1      agc 	0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
    137  1.1      agc 	0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
    138  1.1      agc 	0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
    139  1.1      agc 	0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
    140  1.1      agc 	0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
    141  1.1      agc 	0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
    142  1.1      agc 	0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
    143  1.1      agc 	0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
    144  1.1      agc 	0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
    145  1.1      agc 	0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
    146  1.1      agc 	0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
    147  1.1      agc };
    148  1.1      agc 
    149  1.1      agc 
    150  1.1      agc /*
    151  1.1      agc  * gen_digest:
    152  1.1      agc  *    Generate an iSCSI CRC32C digest over the given data.
    153  1.1      agc  *
    154  1.1      agc  *    Parameters:
    155  1.1      agc  *          buff   The data
    156  1.1      agc  *          len   The length of the data in bytes
    157  1.1      agc  *
    158  1.1      agc  *    Returns:    The digest in network byte order
    159  1.1      agc  */
    160  1.1      agc 
    161  1.1      agc uint32_t
    162  1.1      agc gen_digest(void *buff, int len)
    163  1.1      agc {
    164  1.1      agc 	uint8_t *bp = (uint8_t *) buff;
    165  1.1      agc 	uint32_t crc = 0xffffffff;
    166  1.1      agc 
    167  1.1      agc 	while (len--) {
    168  1.1      agc 		crc = ((crc >> 8) & 0x00ffffff) ^ crc_table[(crc ^ *bp++) & 0xff];
    169  1.1      agc 	}
    170  1.4  mlelstv 	return htonl(bswap32(crc ^ 0xffffffff));
    171  1.1      agc }
    172  1.1      agc 
    173  1.1      agc 
    174  1.1      agc /*
    175  1.1      agc  * gen_digest_2:
    176  1.1      agc  *    Generate an iSCSI CRC32C digest over the given data, which is split over
    177  1.1      agc  *    two buffers.
    178  1.1      agc  *
    179  1.1      agc  *    Parameters:
    180  1.1      agc  *          buf1, buf2  The data
    181  1.1      agc  *          len1, len2  The length of the data in bytes
    182  1.1      agc  *
    183  1.1      agc  *    Returns:    The digest in network byte order
    184  1.1      agc  */
    185  1.1      agc 
    186  1.1      agc uint32_t
    187  1.1      agc gen_digest_2(void *buf1, int len1, void *buf2, int len2)
    188  1.1      agc {
    189  1.1      agc 	uint8_t *bp = (uint8_t *) buf1;
    190  1.1      agc 	uint32_t crc = 0xffffffff;
    191  1.1      agc 
    192  1.1      agc 	while (len1--) {
    193  1.1      agc 		crc = ((crc >> 8) & 0x00ffffff) ^ crc_table[(crc ^ *bp++) & 0xff];
    194  1.1      agc 	}
    195  1.1      agc 	bp = (uint8_t *) buf2;
    196  1.1      agc 	while (len2--) {
    197  1.1      agc 		crc = ((crc >> 8) & 0x00ffffff) ^ crc_table[(crc ^ *bp++) & 0xff];
    198  1.1      agc 	}
    199  1.4  mlelstv 	return htonl(bswap32(crc ^ 0xffffffff));
    200  1.1      agc }
    201  1.1      agc 
    202  1.1      agc /*****************************************************************************
    203  1.1      agc  * CCB management functions
    204  1.1      agc  *****************************************************************************/
    205  1.1      agc 
    206  1.1      agc /*
    207  1.1      agc  * get_ccb:
    208  1.1      agc  *    Get a CCB for the SCSI operation, waiting if none is available.
    209  1.1      agc  *
    210  1.1      agc  *    Parameter:
    211  1.1      agc  *       sess     The session containing this CCB
    212  1.1      agc  *       waitok   Whether waiting for a CCB is OK
    213  1.1      agc  *
    214  1.1      agc  *    Returns:    The CCB.
    215  1.1      agc  */
    216  1.1      agc 
    217  1.1      agc ccb_t *
    218  1.1      agc get_ccb(connection_t *conn, bool waitok)
    219  1.1      agc {
    220  1.1      agc 	ccb_t *ccb;
    221  1.1      agc 	session_t *sess = conn->session;
    222  1.1      agc 
    223  1.1      agc 	do {
    224  1.1      agc 		CS_BEGIN;
    225  1.1      agc 		ccb = TAILQ_FIRST(&sess->ccb_pool);
    226  1.1      agc 		if (ccb != NULL) {
    227  1.1      agc 			TAILQ_REMOVE(&sess->ccb_pool, ccb, chain);
    228  1.1      agc 		}
    229  1.1      agc 		CS_END;
    230  1.1      agc 		DEB(100, ("get_ccb: ccb = %p, waitok = %d\n", ccb, waitok));
    231  1.1      agc 		if (ccb == NULL) {
    232  1.1      agc 			if (!waitok || conn->terminating) {
    233  1.1      agc 				return NULL;
    234  1.1      agc 			}
    235  1.1      agc 			PDEBOUT(("Waiting for CCB!\n"));
    236  1.1      agc 			tsleep(&sess->ccb_pool, PWAIT, "get_ccb", 0);
    237  1.1      agc 		}
    238  1.1      agc 	} while (ccb == NULL);
    239  1.1      agc 
    240  1.1      agc 	ccb->flags = 0;
    241  1.1      agc 	ccb->xs = NULL;
    242  1.1      agc 	ccb->temp_data = NULL;
    243  1.1      agc 	ccb->text_data = NULL;
    244  1.1      agc 	ccb->status = ISCSI_STATUS_SUCCESS;
    245  1.1      agc 	ccb->ITT = (ccb->ITT & 0xffffff) | (++sess->itt_id << 24);
    246  1.1      agc 	ccb->disp = CCBDISP_NOWAIT;
    247  1.1      agc 	ccb->connection = conn;
    248  1.2  mlelstv 	conn->usecount++;
    249  1.1      agc 
    250  1.1      agc 	return ccb;
    251  1.1      agc }
    252  1.1      agc 
    253  1.1      agc /*
    254  1.1      agc  * free_ccb:
    255  1.1      agc  *    Put a CCB back onto the free list.
    256  1.1      agc  *
    257  1.1      agc  *    Parameter:  The CCB.
    258  1.1      agc  */
    259  1.1      agc 
    260  1.1      agc void
    261  1.1      agc free_ccb(ccb_t *ccb)
    262  1.1      agc {
    263  1.1      agc 	session_t *sess = ccb->session;
    264  1.1      agc 	pdu_t *pdu;
    265  1.1      agc 
    266  1.2  mlelstv 	ccb->connection->usecount--;
    267  1.2  mlelstv 	ccb->connection = NULL;
    268  1.2  mlelstv 
    269  1.1      agc 	ccb->disp = CCBDISP_UNUSED;
    270  1.1      agc 
    271  1.1      agc 	/* free temporary data */
    272  1.1      agc 	if (ccb->temp_data != NULL) {
    273  1.1      agc 		free(ccb->temp_data, M_TEMP);
    274  1.1      agc 	}
    275  1.1      agc 	if (ccb->text_data != NULL) {
    276  1.1      agc 		free(ccb->text_data, M_TEMP);
    277  1.1      agc 	}
    278  1.1      agc 	/* free PDU waiting for ACK */
    279  1.1      agc 	if ((pdu = ccb->pdu_waiting) != NULL) {
    280  1.1      agc 		ccb->pdu_waiting = NULL;
    281  1.1      agc 		free_pdu(pdu);
    282  1.1      agc 	}
    283  1.1      agc 
    284  1.1      agc 	CS_BEGIN;
    285  1.1      agc 	TAILQ_INSERT_TAIL(&sess->ccb_pool, ccb, chain);
    286  1.1      agc 	CS_END;
    287  1.1      agc 	wakeup(&sess->ccb_pool);
    288  1.1      agc }
    289  1.1      agc 
    290  1.1      agc /*
    291  1.1      agc  *    create_ccbs
    292  1.1      agc  *       "Create" the pool of CCBs. This doesn't actually create the CCBs
    293  1.1      agc  *       (they are allocated with the session structure), but it links them
    294  1.1      agc  *       into the free-list.
    295  1.1      agc  *
    296  1.1      agc  *    Parameter:  The session owning the CCBs.
    297  1.1      agc  */
    298  1.1      agc 
    299  1.1      agc void
    300  1.1      agc create_ccbs(session_t *sess)
    301  1.1      agc {
    302  1.1      agc 	int i;
    303  1.1      agc 	ccb_t *ccb;
    304  1.1      agc 	int sid = sess->id << 8;
    305  1.1      agc 
    306  1.1      agc 	/* Note: CCBs are initialized to 0 with connection structure */
    307  1.1      agc 
    308  1.1      agc 	for (i = 0, ccb = sess->ccb; i < CCBS_PER_SESSION; i++, ccb++) {
    309  1.1      agc 		ccb->ITT = i | sid;
    310  1.1      agc 		ccb->session = sess;
    311  1.1      agc 
    312  1.1      agc 		callout_init(&ccb->timeout, 0);
    313  1.1      agc #if (__NetBSD_Version__ >= 106000000)
    314  1.1      agc 		callout_setfunc(&ccb->timeout, ccb_timeout, ccb);
    315  1.1      agc #endif
    316  1.1      agc 
    317  1.1      agc 		/*DEB (9, ("Create_ccbs: ccb %x itt %x\n", ccb, ccb->ITT)); */
    318  1.1      agc 		TAILQ_INSERT_HEAD(&sess->ccb_pool, ccb, chain);
    319  1.1      agc 	}
    320  1.1      agc }
    321  1.1      agc 
    322  1.1      agc 
    323  1.1      agc /*
    324  1.1      agc  * wake_ccb:
    325  1.1      agc  *    Wake up (or dispose of) a CCB. Depending on the CCB's disposition,
    326  1.1      agc  *    either wake up the requesting thread, signal SCSIPI that we're done,
    327  1.1      agc  *    or just free the CCB for CCBDISP_FREE.
    328  1.1      agc  *
    329  1.1      agc  *    Parameter:  The CCB to handle.
    330  1.1      agc  */
    331  1.1      agc 
    332  1.1      agc void
    333  1.1      agc wake_ccb(ccb_t *ccb)
    334  1.1      agc {
    335  1.1      agc 	ccb_disp_t disp;
    336  1.1      agc 	connection_t *conn;
    337  1.1      agc 	int s;
    338  1.1      agc #ifdef ISCSI_DEBUG
    339  1.1      agc 	static ccb_t *lastccb = NULL;
    340  1.1      agc 	static int lastdisp = -1;
    341  1.1      agc #endif
    342  1.1      agc 
    343  1.1      agc 	/* Just in case */
    344  1.1      agc 	if (ccb == NULL)
    345  1.1      agc 		return;
    346  1.1      agc 
    347  1.1      agc 	conn = ccb->connection;
    348  1.1      agc 
    349  1.1      agc #ifdef ISCSI_DEBUG
    350  1.1      agc 	if (ccb != lastccb || ccb->disp != lastdisp) {
    351  1.1      agc 		DEBC(conn, 9, ("Wake CCB, ccb = %p, disp = %d\n",
    352  1.1      agc 			ccb, (ccb) ? ccb->disp : 0));
    353  1.1      agc 		lastccb = ccb;
    354  1.1      agc 		lastdisp = (ccb) ? ccb->disp : 0;
    355  1.1      agc 	}
    356  1.1      agc #endif
    357  1.1      agc 
    358  1.1      agc 	callout_stop(&ccb->timeout);
    359  1.1      agc 
    360  1.1      agc 	s = splbio();
    361  1.1      agc 	disp = ccb->disp;
    362  1.1      agc 	if (disp <= CCBDISP_NOWAIT ||
    363  1.1      agc 		(disp == CCBDISP_DEFER && conn->state <= ST_WINDING_DOWN)) {
    364  1.1      agc 		splx(s);
    365  1.1      agc 		return;
    366  1.1      agc 	}
    367  1.1      agc 
    368  1.1      agc 	TAILQ_REMOVE(&conn->ccbs_waiting, ccb, chain);
    369  1.1      agc 
    370  1.1      agc 	/* change the disposition so nobody tries this again */
    371  1.1      agc 	ccb->disp = CCBDISP_BUSY;
    372  1.1      agc 	splx(s);
    373  1.1      agc 
    374  1.1      agc 	PERF_END(ccb);
    375  1.1      agc 
    376  1.1      agc 	switch (disp) {
    377  1.1      agc 	case CCBDISP_WAIT:
    378  1.1      agc 		wakeup(ccb);
    379  1.1      agc 		break;
    380  1.1      agc 
    381  1.1      agc 	case CCBDISP_SCSIPI:
    382  1.1      agc 		iscsi_done(ccb);
    383  1.1      agc 		break;
    384  1.1      agc 
    385  1.1      agc 	case CCBDISP_DEFER:
    386  1.1      agc 		break;
    387  1.1      agc 
    388  1.1      agc 	default:
    389  1.1      agc 		free_ccb(ccb);
    390  1.1      agc 		break;
    391  1.1      agc 	}
    392  1.1      agc }
    393  1.1      agc 
    394  1.1      agc 
    395  1.1      agc /*
    396  1.1      agc  * complete_ccb:
    397  1.1      agc  *    Same as wake_ccb, but the CCB is not assumed to be in the waiting list.
    398  1.1      agc  *
    399  1.1      agc  *    Parameter:  The CCB to handle.
    400  1.1      agc  */
    401  1.1      agc 
    402  1.1      agc void
    403  1.1      agc complete_ccb(ccb_t *ccb)
    404  1.1      agc {
    405  1.1      agc 	ccb_disp_t disp;
    406  1.1      agc 	int s;
    407  1.1      agc 
    408  1.1      agc 	/* Just in case */
    409  1.1      agc 	if (ccb == NULL)
    410  1.1      agc 		return;
    411  1.1      agc 
    412  1.1      agc 	callout_stop(&ccb->timeout);
    413  1.1      agc 
    414  1.1      agc 	s = splbio();
    415  1.1      agc 	disp = ccb->disp;
    416  1.1      agc 	if (disp <= CCBDISP_NOWAIT || disp == CCBDISP_DEFER) {
    417  1.1      agc 		splx(s);
    418  1.1      agc 		return;
    419  1.1      agc 	}
    420  1.1      agc 	/* change the disposition so nobody tries this again */
    421  1.1      agc 	ccb->disp = CCBDISP_BUSY;
    422  1.1      agc 	splx(s);
    423  1.1      agc 
    424  1.1      agc 	PERF_END(ccb);
    425  1.1      agc 
    426  1.1      agc 	switch (disp) {
    427  1.1      agc 	case CCBDISP_WAIT:
    428  1.1      agc 		wakeup(ccb);
    429  1.1      agc 		break;
    430  1.1      agc 
    431  1.1      agc 	case CCBDISP_SCSIPI:
    432  1.1      agc 		iscsi_done(ccb);
    433  1.1      agc 		break;
    434  1.1      agc 
    435  1.1      agc 	default:
    436  1.1      agc 		free_ccb(ccb);
    437  1.1      agc 		break;
    438  1.1      agc 	}
    439  1.1      agc }
    440  1.1      agc 
    441  1.1      agc 
    442  1.1      agc /*****************************************************************************
    443  1.1      agc  * PDU management functions
    444  1.1      agc  *****************************************************************************/
    445  1.1      agc 
    446  1.1      agc /*
    447  1.1      agc  * get_pdu_c:
    448  1.1      agc  *    Get a PDU for the SCSI operation.
    449  1.1      agc  *
    450  1.1      agc  *    Parameter:
    451  1.1      agc  *          conn     The connection this PDU should be associated with
    452  1.1      agc  *          waitok   OK to wait for PDU if TRUE
    453  1.1      agc  *
    454  1.1      agc  *    Returns:    The PDU or NULL if none is available and waitok is FALSE.
    455  1.1      agc  */
    456  1.1      agc 
    457  1.1      agc pdu_t *
    458  1.1      agc get_pdu_c(connection_t *conn, bool waitok)
    459  1.1      agc {
    460  1.1      agc 	pdu_t *pdu;
    461  1.1      agc 
    462  1.1      agc 	do {
    463  1.1      agc 		CS_BEGIN;
    464  1.1      agc 		pdu = TAILQ_FIRST(&conn->pdu_pool);
    465  1.1      agc 		if (pdu != NULL) {
    466  1.1      agc 			TAILQ_REMOVE(&conn->pdu_pool, pdu, chain);
    467  1.1      agc 		}
    468  1.1      agc 		CS_END;
    469  1.1      agc 		DEB(100, ("get_pdu_c: pdu = %p, waitok = %d\n", pdu, waitok));
    470  1.1      agc 		if (pdu == NULL) {
    471  1.1      agc 			if (!waitok || conn->terminating)
    472  1.1      agc 				return NULL;
    473  1.1      agc 			PDEBOUT(("Waiting for PDU!\n"));
    474  1.1      agc 			tsleep(&conn->pdu_pool, PWAIT, "get_pdu_c", 0);
    475  1.1      agc 		}
    476  1.1      agc 	} while (pdu == NULL);
    477  1.1      agc 
    478  1.1      agc 	memset(pdu, 0, sizeof(pdu_t));
    479  1.1      agc 	pdu->connection = conn;
    480  1.1      agc 	pdu->disp = PDUDISP_FREE;
    481  1.1      agc 
    482  1.1      agc 	return pdu;
    483  1.1      agc }
    484  1.1      agc 
    485  1.1      agc /*
    486  1.1      agc  * get_pdu:
    487  1.1      agc  *    Get a PDU for the SCSI operation, waits if none is available.
    488  1.1      agc  *    Same as get_pdu_c, but with wait always OK.
    489  1.1      agc  *    Duplicated code because this is the more common case.
    490  1.1      agc  *
    491  1.1      agc  *    Parameter:  The connection this PDU should be associated with.
    492  1.1      agc  *
    493  1.1      agc  *    Returns:    The PDU.
    494  1.1      agc  */
    495  1.1      agc 
    496  1.1      agc pdu_t *
    497  1.1      agc get_pdu(connection_t *conn)
    498  1.1      agc {
    499  1.1      agc 	pdu_t *pdu;
    500  1.1      agc 
    501  1.1      agc 	do {
    502  1.1      agc 		CS_BEGIN;
    503  1.1      agc 		pdu = TAILQ_FIRST(&conn->pdu_pool);
    504  1.1      agc 		if (pdu != NULL) {
    505  1.1      agc 			TAILQ_REMOVE(&conn->pdu_pool, pdu, chain);
    506  1.1      agc 		}
    507  1.1      agc 		CS_END;
    508  1.1      agc 		DEB(100, ("get_pdu: pdu = %p\n", pdu));
    509  1.1      agc 		if (pdu == NULL) {
    510  1.1      agc 			if (conn->terminating)
    511  1.1      agc 				return NULL;
    512  1.1      agc 
    513  1.1      agc 			PDEBOUT(("Waiting for PDU!\n"));
    514  1.1      agc 			tsleep(&conn->pdu_pool, PWAIT, "get_pdu", 0);
    515  1.1      agc 		}
    516  1.1      agc 	} while (pdu == NULL);
    517  1.1      agc 
    518  1.1      agc 	memset(pdu, 0, sizeof(pdu_t));
    519  1.1      agc 	pdu->connection = conn;
    520  1.1      agc 	pdu->disp = PDUDISP_FREE;
    521  1.1      agc 
    522  1.1      agc 	return pdu;
    523  1.1      agc }
    524  1.1      agc 
    525  1.1      agc /*
    526  1.1      agc  * free_pdu:
    527  1.1      agc  *    Put a PDU back onto the free list.
    528  1.1      agc  *
    529  1.1      agc  *    Parameter:  The PDU.
    530  1.1      agc  */
    531  1.1      agc 
    532  1.1      agc void
    533  1.1      agc free_pdu(pdu_t *pdu)
    534  1.1      agc {
    535  1.1      agc 	connection_t *conn = pdu->connection;
    536  1.1      agc 	pdu_disp_t pdisp;
    537  1.1      agc 
    538  1.1      agc 	if (PDUDISP_UNUSED == (pdisp = pdu->disp))
    539  1.1      agc 		return;
    540  1.1      agc 	pdu->disp = PDUDISP_UNUSED;
    541  1.1      agc 
    542  1.1      agc 	if (pdu->flags & PDUF_INQUEUE) {
    543  1.1      agc 		TAILQ_REMOVE(&conn->pdus_to_send, pdu, send_chain);
    544  1.1      agc 		pdu->flags &= ~PDUF_INQUEUE;
    545  1.1      agc 	}
    546  1.1      agc 
    547  1.1      agc 	if (pdisp == PDUDISP_SIGNAL)
    548  1.1      agc 		wakeup(pdu);
    549  1.1      agc 
    550  1.1      agc 	/* free temporary data in this PDU */
    551  1.1      agc 	if (pdu->temp_data)
    552  1.1      agc 		free(pdu->temp_data, M_TEMP);
    553  1.1      agc 
    554  1.1      agc 	CS_BEGIN;
    555  1.1      agc 	TAILQ_INSERT_TAIL(&conn->pdu_pool, pdu, chain);
    556  1.1      agc 	CS_END;
    557  1.1      agc 	wakeup(&conn->pdu_pool);
    558  1.1      agc }
    559  1.1      agc 
    560  1.1      agc /*
    561  1.1      agc  *    create_pdus
    562  1.1      agc  *       "Create" the pool of PDUs. This doesn't actually create the PDUs
    563  1.1      agc  *       (they are allocated with the connection structure), but it links them
    564  1.1      agc  *       into the free-list.
    565  1.1      agc  *
    566  1.1      agc  *    Parameter:  The connection owning the PDUs.
    567  1.1      agc  */
    568  1.1      agc 
    569  1.1      agc void
    570  1.1      agc create_pdus(connection_t *conn)
    571  1.1      agc {
    572  1.1      agc 	int i;
    573  1.1      agc 	pdu_t *pdu;
    574  1.1      agc 
    575  1.1      agc 	/* Note: PDUs are initialized to 0 with connection structure */
    576  1.1      agc 
    577  1.1      agc 	for (i = 0, pdu = conn->pdu; i < PDUS_PER_CONNECTION; i++, pdu++) {
    578  1.1      agc 		TAILQ_INSERT_HEAD(&conn->pdu_pool, pdu, chain);
    579  1.1      agc 	}
    580  1.1      agc }
    581  1.1      agc 
    582  1.1      agc 
    583  1.1      agc /*****************************************************************************
    584  1.1      agc  * Serial Number management functions
    585  1.1      agc  *****************************************************************************/
    586  1.1      agc 
    587  1.1      agc /*
    588  1.1      agc  * init_sernum:
    589  1.1      agc  *    Initialize serial number buffer variables.
    590  1.1      agc  *
    591  1.1      agc  *    Parameter:
    592  1.1      agc  *          buff   The serial number buffer.
    593  1.1      agc  */
    594  1.1      agc 
    595  1.1      agc void
    596  1.1      agc init_sernum(sernum_buffer_t *buff)
    597  1.1      agc {
    598  1.1      agc 
    599  1.1      agc 	buff->bottom = 0;
    600  1.1      agc 	buff->top = 0;
    601  1.1      agc 	buff->next_sn = 0;
    602  1.1      agc 	buff->ExpSN = 0;
    603  1.1      agc }
    604  1.1      agc 
    605  1.1      agc 
    606  1.1      agc /*
    607  1.1      agc  * add_sernum:
    608  1.1      agc  *    Add a received serial number to the buffer.
    609  1.1      agc  *    If the serial number is smaller than the expected one, it is ignored.
    610  1.1      agc  *    If it is larger, all missing serial numbers are added as well.
    611  1.1      agc  *
    612  1.1      agc  *    Parameter:
    613  1.1      agc  *          buff   The serial number buffer.
    614  1.1      agc  *          num   The received serial number
    615  1.1      agc  *
    616  1.1      agc  *    Returns:
    617  1.1      agc  *          0     if the received block is a duplicate
    618  1.1      agc  *          1     if the number is the expected one
    619  1.1      agc  *          >1    if the numer is > the expected value, in this case the
    620  1.1      agc  *                return value is the number of unacknowledged blocks
    621  1.1      agc  *          <0    if the buffer is full (i.e. an excessive number of blocks
    622  1.1      agc  *                is unacknowledged)
    623  1.1      agc  */
    624  1.1      agc 
    625  1.1      agc int
    626  1.1      agc add_sernum(sernum_buffer_t *buff, uint32_t num)
    627  1.1      agc {
    628  1.3  mlelstv 	int i, t, b;
    629  1.3  mlelstv 	uint32_t n;
    630  1.3  mlelstv 	int32_t diff;
    631  1.1      agc 
    632  1.1      agc 	/*
    633  1.1      agc 	 * next_sn is the next expected SN, so normally diff should be 1.
    634  1.1      agc 	 */
    635  1.1      agc 	n = buff->next_sn;
    636  1.1      agc 	diff = (num - n) + 1;
    637  1.1      agc 
    638  1.1      agc 	if (diff <= 0) {
    639  1.3  mlelstv 		PDEB(1, ("Rx Duplicate Block: SN %u < Next SN %u\n", num, n));
    640  1.1      agc 		return 0;				/* ignore if SN is smaller than expected (dup or retransmit) */
    641  1.1      agc 	}
    642  1.1      agc 
    643  1.1      agc 	buff->next_sn = num + 1;
    644  1.1      agc 	t = buff->top;
    645  1.1      agc 	b = buff->bottom;
    646  1.1      agc 
    647  1.1      agc 	for (i = 0; i < diff; i++) {
    648  1.1      agc 		buff->sernum[t] = n++;
    649  1.1      agc 		buff->ack[t] = 0;
    650  1.1      agc 		t = (t + 1) % SERNUM_BUFFER_LENGTH;
    651  1.1      agc 		if (t == b) {
    652  1.1      agc 			DEB(1, ("AddSernum: Buffer Full! num %d, diff %d\n", num, diff));
    653  1.1      agc 			return -1;
    654  1.1      agc 		}
    655  1.1      agc 	}
    656  1.1      agc 
    657  1.1      agc 	buff->top = t;
    658  1.3  mlelstv 	DEB(10, ("AddSernum bottom %d [%d], top %d, num %u, diff %d\n",
    659  1.1      agc 			 b, buff->sernum[b], buff->top, num, diff));
    660  1.1      agc 
    661  1.1      agc 	return diff;
    662  1.1      agc }
    663  1.1      agc 
    664  1.1      agc 
    665  1.1      agc /*
    666  1.1      agc  * ack_sernum:
    667  1.1      agc  *    Mark a received serial number as acknowledged. This does not necessarily
    668  1.1      agc  *    change the associated ExpSN if there are lower serial numbers in the
    669  1.1      agc  *    buffer.
    670  1.1      agc  *
    671  1.1      agc  *    Parameter:
    672  1.1      agc  *          buff   The serial number buffer.
    673  1.1      agc  *          num   The serial number to acknowledge.
    674  1.1      agc  *
    675  1.1      agc  *    Returns:    The value of ExpSN.
    676  1.1      agc  */
    677  1.1      agc 
    678  1.1      agc uint32_t
    679  1.1      agc ack_sernum(sernum_buffer_t *buff, uint32_t num)
    680  1.1      agc {
    681  1.1      agc 	int b = buff->bottom;
    682  1.1      agc 	int t = buff->top;
    683  1.1      agc 
    684  1.1      agc 	/* shortcut for most likely case */
    685  1.1      agc 	if (t == (b + 1) && num == buff->sernum[b]) {
    686  1.1      agc 		/* buffer is now empty, reset top */
    687  1.1      agc 		buff->top = b;
    688  1.1      agc 	} else if (b != t) {
    689  1.1      agc 		for (; b != t; b = (b + 1) % SERNUM_BUFFER_LENGTH) {
    690  1.1      agc 			if (!sn_a_lt_b(buff->sernum[b], num))
    691  1.1      agc 				break;
    692  1.1      agc 		}
    693  1.1      agc 		if (num == buff->sernum[b]) {
    694  1.1      agc 			if (b == buff->bottom)
    695  1.1      agc 				buff->bottom = (b + 1) % SERNUM_BUFFER_LENGTH;
    696  1.1      agc 			else
    697  1.1      agc 				buff->ack[b] = 1;
    698  1.1      agc 		}
    699  1.1      agc 
    700  1.1      agc 		for (b = buff->bottom, num = buff->sernum[b] - 1;
    701  1.1      agc 			 b != t && buff->ack[b]; b = (b + 1) % SERNUM_BUFFER_LENGTH) {
    702  1.1      agc 			num = buff->sernum[b];
    703  1.1      agc 		}
    704  1.1      agc 	}
    705  1.1      agc 
    706  1.1      agc 	if (!sn_a_lt_b(num, buff->ExpSN))
    707  1.1      agc 		buff->ExpSN = num + 1;
    708  1.1      agc 
    709  1.1      agc 	DEB(10, ("AckSernum bottom %d, top %d, num %d ExpSN %d\n",
    710  1.1      agc 			 buff->bottom, buff->top, num, buff->ExpSN));
    711  1.1      agc 
    712  1.1      agc 	return buff->ExpSN;
    713  1.1      agc }
    714