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