2 * Copyright (c) 2005-2007 Daniel Braniss <danny@cs.huji.ac.il>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 | $Id: iscsivar.h,v 1.30 2007/04/22 10:12:11 danny Exp danny $
31 #ifndef ISCSI_INITIATOR_DEBUG
32 #define ISCSI_INITIATOR_DEBUG 1
35 #ifdef ISCSI_INITIATOR_DEBUG
36 extern int iscsi_debug;
37 #define debug(level, fmt, args...) do {if(level <= iscsi_debug)\
38 printf("%s: " fmt "\n", __func__ , ##args);} while(0)
39 #define sdebug(level, fmt, args...) do {if(level <= iscsi_debug)\
40 printf("%d] %s: " fmt "\n", sp->sid, __func__ , ##args);} while(0)
41 #define debug_called(level) do {if(level <= iscsi_debug)\
42 printf("%s: called\n", __func__);} while(0)
44 #define debug(level, fmt, args...)
45 #define debug_called(level)
46 #define sdebug(level, fmt, args...)
47 #endif /* ISCSI_INITIATOR_DEBUG */
49 #define xdebug(fmt, args...) printf("%s: " fmt "\n", __func__ , ##args)
51 #define MAX_SESSIONS ISCSI_MAX_TARGETS
53 typedef uint32_t digest_t(const void *, int len, uint32_t ocrc);
55 MALLOC_DECLARE(M_ISCSI);
56 MALLOC_DECLARE(M_PDU);
59 #define BIT(n) (1 <<(n))
62 #define ISC_SM_RUN BIT(0)
63 #define ISC_SM_RUNNING BIT(1)
64 #define ISC_SM_HOLD BIT(2)
66 #define ISC_CON_RUN BIT(3)
67 #define ISC_CON_RUNNING BIT(4)
68 #define ISC_KILL BIT(5)
69 #define ISC_IWAITING BIT(6)
70 //#define ISC_OWAITING BIT(7)
71 #define ISC_FFPHASE BIT(8)
72 #define ISC_FFPWAIT BIT(9)
74 #define ISC_MEMWAIT BIT(10)
75 #define ISC_SIGNALED BIT(11)
76 #define ISC_FROZEN BIT(12)
77 #define ISC_STALLED BIT(13)
79 #define ISC_SHUTDOWN BIT(31)
85 int npdu; // number of pdus malloc'ed.
86 int nrecv; // unprocessed received pdus
87 int nsent; // sent pdus
96 struct bintime t_sent;
97 struct bintime t_recv;
103 typedef struct isc_session {
104 TAILQ_ENTRY(isc_session) sp_link;
111 struct proc *proc; // the userland process
114 struct proc *soc_proc;
116 struct proc *stp; // the sm thread
118 struct isc_softc *isc;
120 digest_t *hdrDigest; // the digest alg. if any
121 digest_t *dataDigest; // the digest alg. if any
123 int sid; // Session ID
125 // int cid; // Connection ID
126 // int tsih; // target session identifier handle
127 sn_t sn; // sequence number stuff;
128 int cws; // current window size
130 int target_nluns; // this and target_lun are
131 // hopefully temporal till I
132 // figure out a better way.
133 lun_id_t target_lun[ISCSI_MAX_LUNS];
141 TAILQ_HEAD(,pduq) rsp;
142 TAILQ_HEAD(,pduq) rsv;
143 TAILQ_HEAD(,pduq) csnd;
144 TAILQ_HEAD(,pduq) isnd;
145 TAILQ_HEAD(,pduq) wsnd;
146 TAILQ_HEAD(,pduq) hld;
152 struct i_stats stats;
153 struct cam_path *cam_path;
160 struct sysctl_ctx_list clist;
161 struct sysctl_oid *oid;
164 typedef struct pduq {
165 TAILQ_ENTRY(pduq) pq_link;
168 u_int len; // the total length of the pdu
173 struct iovec iov[5]; // XXX: careful ...
182 char isid[6]; // Initiator Session ID (48 bits)
186 TAILQ_HEAD(,isc_session) isc_sess;
187 isc_session_t *sessions[MAX_SESSIONS];
190 #ifdef ISCSI_INITIATOR_DEBUG
191 int npdu_alloc, npdu_max; // for instrumentation
193 #define MAX_PDUS 256 // XXX: at the moment this is arbitrary
194 uma_zone_t pdu_zone; // pool of free pdu's
198 struct cam_sim *cam_sim;
199 struct cam_path *cam_path;
204 struct sysctl_ctx_list clist;
205 struct sysctl_oid *oid;
208 #ifdef ISCSI_INITIATOR_DEBUG
209 extern struct mtx iscsi_dbg_mtx;
212 void isc_start_receiver(isc_session_t *sp);
213 void isc_stop_receiver(isc_session_t *sp);
215 int isc_sendPDU(isc_session_t *sp, pduq_t *pq);
216 int isc_qout(isc_session_t *sp, pduq_t *pq);
217 int i_prepPDU(isc_session_t *sp, pduq_t *pq);
219 int ism_fullfeature(struct cdev *dev, int flag);
221 int i_pdu_flush(isc_session_t *sc);
222 int i_setopt(isc_session_t *sp, isc_opt_t *opt);
223 void i_freeopt(isc_opt_t *opt);
225 int ic_init(struct isc_softc *sc);
226 void ic_destroy(struct isc_softc *sc);
227 int ic_fullfeature(struct cdev *dev);
228 void ic_lost_target(isc_session_t *sp, int target);
229 int ic_getCamVals(isc_session_t *sp, iscsi_cam_t *cp);
231 void ism_recv(isc_session_t *sp, pduq_t *pq);
232 int ism_start(isc_session_t *sp);
233 void ism_stop(isc_session_t *sp);
235 int scsi_encap(struct cam_sim *sim, union ccb *ccb);
236 int scsi_decap(isc_session_t *sp, pduq_t *opq, pduq_t *pq);
237 void iscsi_r2t(isc_session_t *sp, pduq_t *opq, pduq_t *pq);
238 void iscsi_done(isc_session_t *sp, pduq_t *opq, pduq_t *pq);
239 void iscsi_reject(isc_session_t *sp, pduq_t *opq, pduq_t *pq);
240 void iscsi_async(isc_session_t *sp, pduq_t *pq);
241 void iscsi_cleanup(isc_session_t *sp);
242 int iscsi_requeue(isc_session_t *sp);
244 void ic_freeze(isc_session_t *sp);
245 void ic_release(isc_session_t *sp);
247 // Serial Number Arithmetic
248 #define _MAXINCR 0x7FFFFFFF // 2 ^ 31 - 1
249 #define SNA_GT(i1, i2) ((i1 != i2) && (\
250 (i1 < i2 && i2 - i1 > _MAXINCR) ||\
251 (i1 > i2 && i1 - i2 < _MAXINCR))?1: 0)
256 #ifdef _CAM_CAM_XPT_SIM_H
258 #if __FreeBSD_version < 600000
259 #define CAM_LOCK(arg)
260 #define CAM_ULOCK(arg)
263 XPT_DONE(struct isc_softc *isp, union ccb *ccb)
269 #elif __FreeBSD_version >= 700000
270 #define CAM_LOCK(arg) mtx_lock(&arg->cam_mtx)
271 #define CAM_UNLOCK(arg) mtx_unlock(&arg->cam_mtx)
274 XPT_DONE(struct isc_softc *isp, union ccb *ccb)
281 //__FreeBSD_version >= 600000
282 #define CAM_LOCK(arg)
283 #define CAM_UNLOCK(arg)
284 #define XPT_DONE(ignore, arg) xpt_done(arg)
287 #endif /* _CAM_CAM_XPT_SIM_H */
289 static __inline pduq_t *
290 pdu_alloc(struct isc_softc *isc, int wait)
294 pq = (pduq_t *)uma_zalloc(isc->pdu_zone, wait? M_WAITOK: M_NOWAIT);
296 // will not happend if M_WAITOK ...
297 mtx_unlock(&isc->pdu_mtx);
298 debug(1, "out of mem");
301 #ifdef ISCSI_INITIATOR_DEBUG
302 mtx_lock(&isc->pdu_mtx);
304 if(isc->npdu_alloc > isc->npdu_max)
305 isc->npdu_max = isc->npdu_alloc;
306 mtx_unlock(&isc->pdu_mtx);
308 memset(pq, 0, sizeof(pduq_t));
314 pdu_free(struct isc_softc *isc, pduq_t *pq)
319 free(pq->buf, M_ISCSI);
320 mtx_lock(&isc->pdu_mtx);
321 uma_zfree(isc->pdu_zone, pq);
322 #ifdef ISCSI_INITIATOR_DEBUG
325 mtx_unlock(&isc->pdu_mtx);
329 i_nqueue_rsp(isc_session_t *sp, pduq_t *pq)
331 mtx_lock(&sp->rsp_mtx);
332 if(++sp->stats.nrsp > sp->stats.max_rsp)
333 sp->stats.max_rsp = sp->stats.nrsp;
334 TAILQ_INSERT_TAIL(&sp->rsp, pq, pq_link);
335 mtx_unlock(&sp->rsp_mtx);
338 static __inline pduq_t *
339 i_dqueue_rsp(isc_session_t *sp)
343 mtx_lock(&sp->rsp_mtx);
344 if((pq = TAILQ_FIRST(&sp->rsp)) != NULL) {
346 TAILQ_REMOVE(&sp->rsp, pq, pq_link);
348 mtx_unlock(&sp->rsp_mtx);
354 i_nqueue_rsv(isc_session_t *sp, pduq_t *pq)
356 mtx_lock(&sp->rsv_mtx);
357 if(++sp->stats.nrsv > sp->stats.max_rsv)
358 sp->stats.max_rsv = sp->stats.nrsv;
359 TAILQ_INSERT_TAIL(&sp->rsv, pq, pq_link);
360 mtx_unlock(&sp->rsv_mtx);
363 static __inline pduq_t *
364 i_dqueue_rsv(isc_session_t *sp)
368 mtx_lock(&sp->rsv_mtx);
369 if((pq = TAILQ_FIRST(&sp->rsv)) != NULL) {
371 TAILQ_REMOVE(&sp->rsv, pq, pq_link);
373 mtx_unlock(&sp->rsv_mtx);
379 i_nqueue_csnd(isc_session_t *sp, pduq_t *pq)
381 mtx_lock(&sp->snd_mtx);
382 if(++sp->stats.ncsnd > sp->stats.max_csnd)
383 sp->stats.max_csnd = sp->stats.ncsnd;
384 TAILQ_INSERT_TAIL(&sp->csnd, pq, pq_link);
385 mtx_unlock(&sp->snd_mtx);
388 static __inline pduq_t *
389 i_dqueue_csnd(isc_session_t *sp)
393 mtx_lock(&sp->snd_mtx);
394 if((pq = TAILQ_FIRST(&sp->csnd)) != NULL) {
396 TAILQ_REMOVE(&sp->csnd, pq, pq_link);
398 mtx_unlock(&sp->snd_mtx);
404 i_nqueue_isnd(isc_session_t *sp, pduq_t *pq)
406 mtx_lock(&sp->snd_mtx);
407 if(++sp->stats.nisnd > sp->stats.max_isnd)
408 sp->stats.max_isnd = sp->stats.nisnd;
409 TAILQ_INSERT_TAIL(&sp->isnd, pq, pq_link);
410 mtx_unlock(&sp->snd_mtx);
413 static __inline pduq_t *
414 i_dqueue_isnd(isc_session_t *sp)
418 mtx_lock(&sp->snd_mtx);
419 if((pq = TAILQ_FIRST(&sp->isnd)) != NULL) {
421 TAILQ_REMOVE(&sp->isnd, pq, pq_link);
423 mtx_unlock(&sp->snd_mtx);
429 i_nqueue_wsnd(isc_session_t *sp, pduq_t *pq)
431 mtx_lock(&sp->snd_mtx);
432 if(++sp->stats.nwsnd > sp->stats.max_wsnd)
433 sp->stats.max_wsnd = sp->stats.nwsnd;
434 TAILQ_INSERT_TAIL(&sp->wsnd, pq, pq_link);
435 mtx_unlock(&sp->snd_mtx);
438 static __inline pduq_t *
439 i_dqueue_wsnd(isc_session_t *sp)
443 mtx_lock(&sp->snd_mtx);
444 if((pq = TAILQ_FIRST(&sp->wsnd)) != NULL) {
446 TAILQ_REMOVE(&sp->wsnd, pq, pq_link);
448 mtx_unlock(&sp->snd_mtx);
453 static __inline pduq_t *
454 i_dqueue_snd(isc_session_t *sp, int which)
459 mtx_lock(&sp->snd_mtx);
460 if((which & BIT(0)) && (pq = TAILQ_FIRST(&sp->isnd)) != NULL) {
462 TAILQ_REMOVE(&sp->isnd, pq, pq_link);
464 if((which & BIT(1)) && (pq = TAILQ_FIRST(&sp->wsnd)) != NULL) {
466 TAILQ_REMOVE(&sp->wsnd, pq, pq_link);
468 if((which & BIT(2)) && (pq = TAILQ_FIRST(&sp->csnd)) != NULL) {
470 TAILQ_REMOVE(&sp->csnd, pq, pq_link);
472 mtx_unlock(&sp->snd_mtx);
478 | Waiting for ACK (or something :-)
481 i_nqueue_hld(isc_session_t *sp, pduq_t *pq)
484 mtx_lock(&sp->hld_mtx);
485 if(++sp->stats.nhld > sp->stats.max_hld)
486 sp->stats.max_hld = sp->stats.nhld;
487 TAILQ_INSERT_TAIL(&sp->hld, pq, pq_link);
488 mtx_unlock(&sp->hld_mtx);
493 i_remove_hld(isc_session_t *sp, pduq_t *pq)
495 mtx_lock(&sp->hld_mtx);
497 TAILQ_REMOVE(&sp->hld, pq, pq_link);
498 mtx_unlock(&sp->hld_mtx);
501 static __inline pduq_t *
502 i_dqueue_hld(isc_session_t *sp)
506 mtx_lock(&sp->hld_mtx);
507 if((pq = TAILQ_FIRST(&sp->hld)) != NULL) {
509 TAILQ_REMOVE(&sp->hld, pq, pq_link);
511 mtx_unlock(&sp->hld_mtx);
516 static __inline pduq_t *
517 i_search_hld(isc_session_t *sp, int itt, int keep)
523 mtx_lock(&sp->hld_mtx);
524 TAILQ_FOREACH_SAFE(pq, &sp->hld, pq_link, tmp) {
525 if(pq->pdu.ipdu.bhs.itt == itt) {
528 TAILQ_REMOVE(&sp->hld, pq, pq_link);
533 mtx_unlock(&sp->hld_mtx);
539 i_mbufcopy(struct mbuf *mp, caddr_t dp, int len)
544 for(m = mp; m != NULL; m = m->m_next) {
545 bp = mtod(m, caddr_t);
547 | the pdu is word (4 octed) aligned
550 memcpy(dp, bp, MIN(len, m->m_len));