Bug Summary

File:modules/cam/../../cam/scsi/scsi_target.c
Warning:line 924, column 10
Copies out a struct with a union element with different sizes

Annotated Source Code

1/*-
2 * Generic SCSI Target Kernel Mode Driver
3 *
4 * Copyright (c) 2002 Nate Lawson.
5 * Copyright (c) 1998, 1999, 2001, 2002 Justin T. Gibbs.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions, and the following disclaimer,
13 * without modification, immediately at the beginning of the file.
14 * 2. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: releng/11.0/sys/cam/scsi/scsi_target.c 288420 2015-09-30 13:31:37Z mav $")__asm__(".ident\t\"" "$FreeBSD: releng/11.0/sys/cam/scsi/scsi_target.c 288420 2015-09-30 13:31:37Z mav $"
"\"")
;
32
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/kernel.h>
37#include <sys/conf.h>
38#include <sys/malloc.h>
39#include <sys/poll.h>
40#include <sys/vnode.h>
41#include <sys/lock.h>
42#include <sys/mutex.h>
43#include <sys/devicestat.h>
44#include <sys/proc.h>
45/* Includes to support callout */
46#include <sys/types.h>
47#include <sys/systm.h>
48
49#include <cam/cam.h>
50#include <cam/cam_ccb.h>
51#include <cam/cam_periph.h>
52#include <cam/cam_xpt_periph.h>
53#include <cam/cam_sim.h>
54#include <cam/scsi/scsi_targetio.h>
55
56
57/* Transaction information attached to each CCB sent by the user */
58struct targ_cmd_descr {
59 struct cam_periph_map_info mapinfo;
60 TAILQ_ENTRY(targ_cmd_descr)struct { struct targ_cmd_descr *tqe_next; struct targ_cmd_descr
**tqe_prev; }
tqe;
61 union ccb *user_ccb;
62 int priority;
63 int func_code;
64};
65
66/* Offset into the private CCB area for storing our descriptor */
67#define targ_descrperiph_priv.entries[1].ptr periph_priv.entries[1].ptr
68
69TAILQ_HEAD(descr_queue, targ_cmd_descr)struct descr_queue { struct targ_cmd_descr *tqh_first; struct
targ_cmd_descr **tqh_last; }
;
70
71typedef enum {
72 TARG_STATE_RESV = 0x00, /* Invalid state */
73 TARG_STATE_OPENED = 0x01, /* Device opened, softc initialized */
74 TARG_STATE_LUN_ENABLED = 0x02 /* Device enabled for a path */
75} targ_state;
76
77/* Per-instance device software context */
78struct targ_softc {
79 /* CCBs (CTIOs, ATIOs, INOTs) pending on the controller */
80 struct ccb_queue pending_ccb_queue;
81
82 /* Command descriptors awaiting CTIO resources from the XPT */
83 struct descr_queue work_queue;
84
85 /* Command descriptors that have been aborted back to the user. */
86 struct descr_queue abort_queue;
87
88 /*
89 * Queue of CCBs that have been copied out to userland, but our
90 * userland daemon has not yet seen.
91 */
92 struct ccb_queue user_ccb_queue;
93
94 struct cam_periph *periph;
95 struct cam_path *path;
96 targ_state state;
97 u_int maxio;
98 struct selinfo read_select;
99 struct devstat device_stats;
100};
101
102static d_open_t targopen;
103static d_read_t targread;
104static d_write_t targwrite;
105static d_ioctl_t targioctl;
106static d_poll_t targpoll;
107static d_kqfilter_t targkqfilter;
108static void targreadfiltdetach(struct knote *kn);
109static int targreadfilt(struct knote *kn, long hint);
110static struct filterops targread_filtops = {
111 .f_isfd = 1,
112 .f_detach = targreadfiltdetach,
113 .f_event = targreadfilt,
114};
115
116static struct cdevsw targ_cdevsw = {
117 .d_version = D_VERSION0x17122009,
118 .d_flags = D_NEEDGIANT0x00400000,
119 .d_open = targopen,
120 .d_read = targread,
121 .d_write = targwrite,
122 .d_ioctl = targioctl,
123 .d_poll = targpoll,
124 .d_name = "targ",
125 .d_kqfilter = targkqfilter
126};
127
128static cam_status targendislun(struct cam_path *path, int enable,
129 int grp6_len, int grp7_len);
130static cam_status targenable(struct targ_softc *softc,
131 struct cam_path *path,
132 int grp6_len, int grp7_len);
133static cam_status targdisable(struct targ_softc *softc);
134static periph_ctor_t targctor;
135static periph_dtor_t targdtor;
136static periph_start_t targstart;
137static int targusermerge(struct targ_softc *softc,
138 struct targ_cmd_descr *descr,
139 union ccb *ccb);
140static int targsendccb(struct targ_softc *softc, union ccb *ccb,
141 struct targ_cmd_descr *descr);
142static void targdone(struct cam_periph *periph,
143 union ccb *done_ccb);
144static int targreturnccb(struct targ_softc *softc,
145 union ccb *ccb);
146static union ccb * targgetccb(struct targ_softc *softc, xpt_opcode type,
147 int priority);
148static void targfreeccb(struct targ_softc *softc, union ccb *ccb);
149static struct targ_cmd_descr *
150 targgetdescr(struct targ_softc *softc);
151static periph_init_t targinit;
152static void targasync(void *callback_arg, u_int32_t code,
153 struct cam_path *path, void *arg);
154static void abort_all_pending(struct targ_softc *softc);
155static void notify_user(struct targ_softc *softc);
156static int targcamstatus(cam_status status);
157static size_t targccblen(xpt_opcode func_code);
158
159static struct periph_driver targdriver =
160{
161 targinit, "targ",
162 TAILQ_HEAD_INITIALIZER(targdriver.units){ ((void *)0), &(targdriver.units).tqh_first, }, /* generation */ 0
163};
164PERIPHDRIVER_DECLARE(targ, targdriver)static int targ_modevent(module_t mod, int type, void *data) {
switch (type) { case MOD_LOAD: periphdriver_register(data); break
; case MOD_UNLOAD: printf("targ" " module unload - not possible for this module type\n"
); return 22; default: return 45; } return 0; } static moduledata_t
targ_mod = { "targ", targ_modevent, (void *)&targdriver }
; static struct mod_depend _targ_depend_on_kernel __attribute__
((__section__(".data"))) = { 1100122, 1100122, (((((1100122)+
((100000)-1))/(100000))*(100000)) - 1) }; static struct mod_metadata
_mod_metadata_md_targ_on_kernel = { 1, 1, &_targ_depend_on_kernel
, "kernel" }; __asm__(".globl " "__start_set_modmetadata_set"
); __asm__(".globl " "__stop_set_modmetadata_set"); static void
const * const __set_modmetadata_set_sym__mod_metadata_md_targ_on_kernel
__attribute__((__section__("set_" "modmetadata_set"))) __attribute__
((__used__)) = &(_mod_metadata_md_targ_on_kernel); static
struct mod_metadata _mod_metadata_md_targ = { 1, 2, &targ_mod
, "targ" }; __asm__(".globl " "__start_set_modmetadata_set");
__asm__(".globl " "__stop_set_modmetadata_set"); static void
const * const __set_modmetadata_set_sym__mod_metadata_md_targ
__attribute__((__section__("set_" "modmetadata_set"))) __attribute__
((__used__)) = &(_mod_metadata_md_targ); static struct sysinit
targmodule_sys_init = { SI_SUB_DRIVERS, SI_ORDER_ANY, (sysinit_cfunc_t
)(sysinit_nfunc_t)module_register_init, ((void *)(&targ_mod
)) }; __asm__(".globl " "__start_set_sysinit_set"); __asm__(".globl "
"__stop_set_sysinit_set"); static void const * const __set_sysinit_set_sym_targmodule_sys_init
__attribute__((__section__("set_" "sysinit_set"))) __attribute__
((__used__)) = &(targmodule_sys_init); struct __hack; static
struct mod_depend _targ_depend_on_cam __attribute__((__section__
(".data"))) = { 1, 1, 1 }; static struct mod_metadata _mod_metadata_md_targ_on_cam
= { 1, 1, &_targ_depend_on_cam, "cam" }; __asm__(".globl "
"__start_set_modmetadata_set"); __asm__(".globl " "__stop_set_modmetadata_set"
); static void const * const __set_modmetadata_set_sym__mod_metadata_md_targ_on_cam
__attribute__((__section__("set_" "modmetadata_set"))) __attribute__
((__used__)) = &(_mod_metadata_md_targ_on_cam)
;
165
166static MALLOC_DEFINE(M_TARG, "TARG", "TARG data")struct malloc_type M_TARG[1] = { { ((void *)0), 877983977, "TARG"
, ((void *)0) } }; static struct sysinit M_TARG_init_sys_init
= { SI_SUB_KMEM, SI_ORDER_THIRD, (sysinit_cfunc_t)(sysinit_nfunc_t
)malloc_init, ((void *)(M_TARG)) }; __asm__(".globl " "__start_set_sysinit_set"
); __asm__(".globl " "__stop_set_sysinit_set"); static void const
* const __set_sysinit_set_sym_M_TARG_init_sys_init __attribute__
((__section__("set_" "sysinit_set"))) __attribute__((__used__
)) = &(M_TARG_init_sys_init); static struct sysinit M_TARG_uninit_sys_uninit
= { SI_SUB_KMEM, SI_ORDER_ANY, (sysinit_cfunc_t)(sysinit_nfunc_t
)malloc_uninit, ((void *)(M_TARG)) }; __asm__(".globl " "__start_set_sysuninit_set"
); __asm__(".globl " "__stop_set_sysuninit_set"); static void
const * const __set_sysuninit_set_sym_M_TARG_uninit_sys_uninit
__attribute__((__section__("set_" "sysuninit_set"))) __attribute__
((__used__)) = &(M_TARG_uninit_sys_uninit)
;
167
168/* Disable LUN if enabled and teardown softc */
169static void
170targcdevdtor(void *data)
171{
172 struct targ_softc *softc;
173 struct cam_periph *periph;
174
175 softc = data;
176 if (softc->periph == NULL((void *)0)) {
177 printf("%s: destroying non-enabled target\n", __func__);
178 free(softc, M_TARG);
179 return;
180 }
181
182 /*
183 * Acquire a hold on the periph so that it doesn't go away before
184 * we are ready at the end of the function.
185 */
186 periph = softc->periph;
187 cam_periph_acquire(periph);
188 cam_periph_lock(periph)__mtx_lock_flags(&((((xpt_path_mtx((periph)->path)))))
->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (188))
;
189 (void)targdisable(softc);
190 if (softc->periph != NULL((void *)0)) {
191 cam_periph_invalidate(softc->periph);
192 softc->periph = NULL((void *)0);
193 }
194 cam_periph_unlock(periph)__mtx_unlock_flags(&((((xpt_path_mtx((periph)->path)))
))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (194))
;
195 cam_periph_release(periph);
196 free(softc, M_TARG);
197}
198
199/*
200 * Create softc and initialize it. There is no locking here because a
201 * periph doesn't get created until an ioctl is issued to do so, and
202 * that can't happen until this method returns.
203 */
204static int
205targopen(struct cdev *dev, int flags, int fmt, struct thread *td)
206{
207 struct targ_softc *softc;
208
209 /* Allocate its softc, initialize it */
210 softc = malloc(sizeof(*softc), M_TARG,
211 M_WAITOK0x0002 | M_ZERO0x0100);
212 softc->state = TARG_STATE_OPENED;
213 softc->periph = NULL((void *)0);
214 softc->path = NULL((void *)0);
215
216 TAILQ_INIT(&softc->pending_ccb_queue)do { (((&softc->pending_ccb_queue))->tqh_first) = (
(void *)0); (&softc->pending_ccb_queue)->tqh_last =
&(((&softc->pending_ccb_queue))->tqh_first); ;
} while (0)
;
217 TAILQ_INIT(&softc->work_queue)do { (((&softc->work_queue))->tqh_first) = ((void *
)0); (&softc->work_queue)->tqh_last = &(((&
softc->work_queue))->tqh_first); ; } while (0)
;
218 TAILQ_INIT(&softc->abort_queue)do { (((&softc->abort_queue))->tqh_first) = ((void *
)0); (&softc->abort_queue)->tqh_last = &(((&
softc->abort_queue))->tqh_first); ; } while (0)
;
219 TAILQ_INIT(&softc->user_ccb_queue)do { (((&softc->user_ccb_queue))->tqh_first) = ((void
*)0); (&softc->user_ccb_queue)->tqh_last = &((
(&softc->user_ccb_queue))->tqh_first); ; } while (0
)
;
220 knlist_init_mtx(&softc->read_select.si_note, NULL((void *)0));
221
222 devfs_set_cdevpriv(softc, targcdevdtor);
223 return (0);
224}
225
226/* Enable/disable LUNs, set debugging level */
227static int
228targioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
229{
230 struct targ_softc *softc;
231 cam_status status;
232
233 devfs_get_cdevpriv((void **)&softc);
234
235 switch (cmd) {
236 case TARGIOCENABLE((unsigned long) ((0x80000000) | (((sizeof(struct ioc_enable_lun
)) & ((1 << 13) - 1)) << 16) | ((('C')) <<
8) | ((5))))
:
237 {
238 struct ioc_enable_lun *new_lun;
239 struct cam_path *path;
240
241 new_lun = (struct ioc_enable_lun *)addr;
242 status = xpt_create_path(&path, /*periph*/NULL((void *)0),
243 new_lun->path_id,
244 new_lun->target_id,
245 new_lun->lun_id);
246 if (status != CAM_REQ_CMP) {
247 printf("Couldn't create path, status %#x\n", status);
248 break;
249 }
250 xpt_path_lock(path)__mtx_lock_flags(&((((xpt_path_mtx(path)))))->mtx_lock
, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (250))
;
251 status = targenable(softc, path, new_lun->grp6_len,
252 new_lun->grp7_len);
253 xpt_path_unlock(path)__mtx_unlock_flags(&((((xpt_path_mtx(path)))))->mtx_lock
, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (253))
;
254 xpt_free_path(path);
255 break;
256 }
257 case TARGIOCDISABLE((unsigned long) ((0x20000000) | (((0) & ((1 << 13)
- 1)) << 16) | ((('C')) << 8) | ((6))))
:
258 if (softc->periph == NULL((void *)0)) {
259 status = CAM_DEV_NOT_THERE;
260 break;
261 }
262 cam_periph_lock(softc->periph)__mtx_lock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (262))
;
263 status = targdisable(softc);
264 cam_periph_unlock(softc->periph)__mtx_unlock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (264))
;
265 break;
266 case TARGIOCDEBUG((unsigned long) ((0x80000000) | (((sizeof(int)) & ((1 <<
13) - 1)) << 16) | ((('C')) << 8) | ((7))))
:
267 {
268 struct ccb_debug cdbg;
269
270 /* If no periph available, disallow debugging changes */
271 if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) {
272 status = CAM_DEV_NOT_THERE;
273 break;
274 }
275 bzero(&cdbg, sizeof cdbg);
276 if (*((int *)addr) != 0)
277 cdbg.flags = CAM_DEBUG_PERIPH;
278 else
279 cdbg.flags = CAM_DEBUG_NONE;
280 xpt_setup_ccb(&cdbg.ccb_h, softc->path, CAM_PRIORITY_NORMAL((CAM_RL_NORMAL << 8) + 0x80));
281 cdbg.ccb_h.func_code = XPT_DEBUG;
282 cdbg.ccb_h.cbfcnp = targdone;
283 xpt_action((union ccb *)&cdbg);
284 status = cdbg.ccb_h.status & CAM_STATUS_MASK;
285 break;
286 }
287 default:
288 status = CAM_PROVIDE_FAIL;
289 break;
290 }
291
292 return (targcamstatus(status));
293}
294
295/* Writes are always ready, reads wait for user_ccb_queue or abort_queue */
296static int
297targpoll(struct cdev *dev, int poll_events, struct thread *td)
298{
299 struct targ_softc *softc;
300 int revents;
301
302 devfs_get_cdevpriv((void **)&softc);
303
304 /* Poll for write() is always ok. */
305 revents = poll_events & (POLLOUT0x0004 | POLLWRNORM0x0004);
306 if ((poll_events & (POLLIN0x0001 | POLLRDNORM0x0040)) != 0) {
307 /* Poll for read() depends on user and abort queues. */
308 cam_periph_lock(softc->periph)__mtx_lock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (308))
;
309 if (!TAILQ_EMPTY(&softc->user_ccb_queue)((&softc->user_ccb_queue)->tqh_first == ((void *)0)
)
||
310 !TAILQ_EMPTY(&softc->abort_queue)((&softc->abort_queue)->tqh_first == ((void *)0))) {
311 revents |= poll_events & (POLLIN0x0001 | POLLRDNORM0x0040);
312 }
313 cam_periph_unlock(softc->periph)__mtx_unlock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (313))
;
314 /* Only sleep if the user didn't poll for write. */
315 if (revents == 0)
316 selrecord(td, &softc->read_select);
317 }
318
319 return (revents);
320}
321
322static int
323targkqfilter(struct cdev *dev, struct knote *kn)
324{
325 struct targ_softc *softc;
326
327 devfs_get_cdevpriv((void **)&softc);
328 kn->kn_hook = (caddr_t)softc;
329 kn->kn_fop = &targread_filtops;
330 knlist_add(&softc->read_select.si_note, kn, 0);
331 return (0);
332}
333
334static void
335targreadfiltdetach(struct knote *kn)
336{
337 struct targ_softc *softc;
338
339 softc = (struct targ_softc *)kn->kn_hook;
340 knlist_remove(&softc->read_select.si_note, kn, 0);
341}
342
343/* Notify the user's kqueue when the user queue or abort queue gets a CCB */
344static int
345targreadfilt(struct knote *kn, long hint)
346{
347 struct targ_softc *softc;
348 int retval;
349
350 softc = (struct targ_softc *)kn->kn_hook;
351 cam_periph_lock(softc->periph)__mtx_lock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (351))
;
352 retval = !TAILQ_EMPTY(&softc->user_ccb_queue)((&softc->user_ccb_queue)->tqh_first == ((void *)0)
)
||
353 !TAILQ_EMPTY(&softc->abort_queue)((&softc->abort_queue)->tqh_first == ((void *)0));
354 cam_periph_unlock(softc->periph)__mtx_unlock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (354))
;
355 return (retval);
356}
357
358/* Send the HBA the enable/disable message */
359static cam_status
360targendislun(struct cam_path *path, int enable, int grp6_len, int grp7_len)
361{
362 struct ccb_en_lun en_ccb;
363 cam_status status;
364
365 /* Tell the lun to begin answering selects */
366 xpt_setup_ccb(&en_ccb.ccb_h, path, CAM_PRIORITY_NORMAL((CAM_RL_NORMAL << 8) + 0x80));
367 en_ccb.ccb_h.func_code = XPT_EN_LUN;
368 /* Don't need support for any vendor specific commands */
369 en_ccb.grp6_len = grp6_len;
370 en_ccb.grp7_len = grp7_len;
371 en_ccb.enable = enable ? 1 : 0;
372 xpt_action((union ccb *)&en_ccb);
373 status = en_ccb.ccb_h.status & CAM_STATUS_MASK;
374 if (status != CAM_REQ_CMP) {
375 xpt_print(path, "%sable lun CCB rejected, status %#x\n",
376 enable ? "en" : "dis", status);
377 }
378 return (status);
379}
380
381/* Enable target mode on a LUN, given its path */
382static cam_status
383targenable(struct targ_softc *softc, struct cam_path *path, int grp6_len,
384 int grp7_len)
385{
386 struct cam_periph *periph;
387 struct ccb_pathinq cpi;
388 cam_status status;
389
390 if ((softc->state & TARG_STATE_LUN_ENABLED) != 0)
391 return (CAM_LUN_ALRDY_ENA);
392
393 /* Make sure SIM supports target mode */
394 xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL((CAM_RL_NORMAL << 8) + 0x80));
395 cpi.ccb_h.func_code = XPT_PATH_INQ;
396 xpt_action((union ccb *)&cpi);
397 status = cpi.ccb_h.status & CAM_STATUS_MASK;
398 if (status != CAM_REQ_CMP) {
399 printf("pathinq failed, status %#x\n", status);
400 goto enable_fail;
401 }
402 if ((cpi.target_sprt & PIT_PROCESSOR) == 0) {
403 printf("controller does not support target mode\n");
404 status = CAM_FUNC_NOTAVAIL;
405 goto enable_fail;
406 }
407 if (cpi.maxio == 0)
408 softc->maxio = DFLTPHYS(64 * 1024); /* traditional default */
409 else if (cpi.maxio > MAXPHYS(128 * 1024))
410 softc->maxio = MAXPHYS(128 * 1024); /* for safety */
411 else
412 softc->maxio = cpi.maxio; /* real value */
413
414 /* Destroy any periph on our path if it is disabled */
415 periph = cam_periph_find(path, "targ");
416 if (periph != NULL((void *)0)) {
417 struct targ_softc *del_softc;
418
419 del_softc = (struct targ_softc *)periph->softc;
420 if ((del_softc->state & TARG_STATE_LUN_ENABLED) == 0) {
421 cam_periph_invalidate(del_softc->periph);
422 del_softc->periph = NULL((void *)0);
423 } else {
424 printf("Requested path still in use by targ%d\n",
425 periph->unit_number);
426 status = CAM_LUN_ALRDY_ENA;
427 goto enable_fail;
428 }
429 }
430
431 /* Create a periph instance attached to this path */
432 status = cam_periph_alloc(targctor, NULL((void *)0), targdtor, targstart,
433 "targ", CAM_PERIPH_BIO, path, targasync, 0, softc);
434 if (status != CAM_REQ_CMP) {
435 printf("cam_periph_alloc failed, status %#x\n", status);
436 goto enable_fail;
437 }
438
439 /* Ensure that the periph now exists. */
440 if (cam_periph_find(path, "targ") == NULL((void *)0)) {
441 panic("targenable: succeeded but no periph?");
442 /* NOTREACHED */
443 }
444
445 /* Send the enable lun message */
446 status = targendislun(path, /*enable*/1, grp6_len, grp7_len);
447 if (status != CAM_REQ_CMP) {
448 printf("enable lun failed, status %#x\n", status);
449 goto enable_fail;
450 }
451 softc->state |= TARG_STATE_LUN_ENABLED;
452
453enable_fail:
454 return (status);
455}
456
457/* Disable this softc's target instance if enabled */
458static cam_status
459targdisable(struct targ_softc *softc)
460{
461 cam_status status;
462
463 if ((softc->state & TARG_STATE_LUN_ENABLED) == 0)
464 return (CAM_REQ_CMP);
465
466 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targdisable\n"))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("targdisable\n"); if (cam_debug_delay
!= 0) DELAY(cam_debug_delay); }
;
467
468 /* Abort any ccbs pending on the controller */
469 abort_all_pending(softc);
470
471 /* Disable this lun */
472 status = targendislun(softc->path, /*enable*/0,
473 /*grp6_len*/0, /*grp7_len*/0);
474 if (status == CAM_REQ_CMP)
475 softc->state &= ~TARG_STATE_LUN_ENABLED;
476 else
477 printf("Disable lun failed, status %#x\n", status);
478
479 return (status);
480}
481
482/* Initialize a periph (called from cam_periph_alloc) */
483static cam_status
484targctor(struct cam_periph *periph, void *arg)
485{
486 struct targ_softc *softc;
487
488 /* Store pointer to softc for periph-driven routines */
489 softc = (struct targ_softc *)arg;
490 periph->softc = softc;
491 softc->periph = periph;
492 softc->path = periph->path;
493 return (CAM_REQ_CMP);
494}
495
496static void
497targdtor(struct cam_periph *periph)
498{
499 struct targ_softc *softc;
500 struct ccb_hdr *ccb_h;
501 struct targ_cmd_descr *descr;
502
503 softc = (struct targ_softc *)periph->softc;
504
505 /*
506 * targdisable() aborts CCBs back to the user and leaves them
507 * on user_ccb_queue and abort_queue in case the user is still
508 * interested in them. We free them now.
509 */
510 while ((ccb_h = TAILQ_FIRST(&softc->user_ccb_queue)((&softc->user_ccb_queue)->tqh_first)) != NULL((void *)0)) {
511 TAILQ_REMOVE(&softc->user_ccb_queue, ccb_h, periph_links.tqe)do { ; ; ; ; if (((((ccb_h))->periph_links.tqe.tqe_next)) !=
((void *)0)) (((ccb_h))->periph_links.tqe.tqe_next)->periph_links
.tqe.tqe_prev = (ccb_h)->periph_links.tqe.tqe_prev; else {
(&softc->user_ccb_queue)->tqh_last = (ccb_h)->periph_links
.tqe.tqe_prev; ; } *(ccb_h)->periph_links.tqe.tqe_prev = (
((ccb_h))->periph_links.tqe.tqe_next); ; ; ; } while (0)
;
512 targfreeccb(softc, (union ccb *)ccb_h);
513 }
514 while ((descr = TAILQ_FIRST(&softc->abort_queue)((&softc->abort_queue)->tqh_first)) != NULL((void *)0)) {
515 TAILQ_REMOVE(&softc->abort_queue, descr, tqe)do { ; ; ; ; if (((((descr))->tqe.tqe_next)) != ((void *)0
)) (((descr))->tqe.tqe_next)->tqe.tqe_prev = (descr)->
tqe.tqe_prev; else { (&softc->abort_queue)->tqh_last
= (descr)->tqe.tqe_prev; ; } *(descr)->tqe.tqe_prev = (
((descr))->tqe.tqe_next); ; ; ; } while (0)
;
516 free(descr, M_TARG);
517 }
518
519 softc->periph = NULL((void *)0);
520 softc->path = NULL((void *)0);
521 periph->softc = NULL((void *)0);
522}
523
524/* Receive CCBs from user mode proc and send them to the HBA */
525static int
526targwrite(struct cdev *dev, struct uio *uio, int ioflag)
527{
528 union ccb *user_ccb;
529 struct targ_softc *softc;
530 struct targ_cmd_descr *descr;
531 int write_len, error;
532 int func_code, priority;
533
534 devfs_get_cdevpriv((void **)&softc);
535 write_len = error = 0;
536 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("write - uio_resid %zd\n", uio->
uio_resid); if (cam_debug_delay != 0) DELAY(cam_debug_delay);
}
537 ("write - uio_resid %zd\n", uio->uio_resid))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("write - uio_resid %zd\n", uio->
uio_resid); if (cam_debug_delay != 0) DELAY(cam_debug_delay);
}
;
538 while (uio->uio_resid >= sizeof(user_ccb) && error == 0) {
1
Loop condition is true. Entering loop body
9
Loop condition is true. Entering loop body
17
Loop condition is true. Entering loop body
25
Loop condition is true. Entering loop body
539 union ccb *ccb;
540
541 error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
542 if (error != 0) {
2
Assuming 'error' is equal to 0
3
Taking false branch
10
Assuming 'error' is equal to 0
11
Taking false branch
18
Assuming 'error' is equal to 0
19
Taking false branch
26
Assuming 'error' is equal to 0
27
Taking false branch
543 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("write - uiomove failed (%d)\n", error
); if (cam_debug_delay != 0) DELAY(cam_debug_delay); }
544 ("write - uiomove failed (%d)\n", error))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("write - uiomove failed (%d)\n", error
); if (cam_debug_delay != 0) DELAY(cam_debug_delay); }
;
545 break;
546 }
547 priority = fuword32(&user_ccb->ccb_h.pinfo.priority);
548 if (priority == CAM_PRIORITY_NONE(u_int32_t)-1) {
4
Taking false branch
12
Taking false branch
20
Taking false branch
28
Taking false branch
549 error = EINVAL22;
550 break;
551 }
552 func_code = fuword32(&user_ccb->ccb_h.func_code);
553 switch (func_code) {
5
Control jumps to the 'default' case at line 570
13
Control jumps to the 'default' case at line 570
21
Control jumps to the 'default' case at line 570
29
Control jumps to the 'default' case at line 570
554 case XPT_ACCEPT_TARGET_IO:
555 case XPT_IMMED_NOTIFY:
556 case XPT_IMMEDIATE_NOTIFY:
557 cam_periph_lock(softc->periph)__mtx_lock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (557))
;
558 ccb = targgetccb(softc, func_code, priority);
559 descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descrperiph_priv.entries[1].ptr;
560 descr->user_ccb = user_ccb;
561 descr->func_code = func_code;
562 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("Sent ATIO/INOT (%p)\n", user_ccb);
if (cam_debug_delay != 0) DELAY(cam_debug_delay); }
563 ("Sent ATIO/INOT (%p)\n", user_ccb))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("Sent ATIO/INOT (%p)\n", user_ccb);
if (cam_debug_delay != 0) DELAY(cam_debug_delay); }
;
564 xpt_action(ccb);
565 TAILQ_INSERT_TAIL(&softc->pending_ccb_queue,do { ; (((&ccb->ccb_h))->periph_links.tqe.tqe_next)
= ((void *)0); (&ccb->ccb_h)->periph_links.tqe.tqe_prev
= (&softc->pending_ccb_queue)->tqh_last; *(&softc
->pending_ccb_queue)->tqh_last = (&ccb->ccb_h); (
&softc->pending_ccb_queue)->tqh_last = &(((&
ccb->ccb_h))->periph_links.tqe.tqe_next); ; ; } while (
0)
566 &ccb->ccb_h,do { ; (((&ccb->ccb_h))->periph_links.tqe.tqe_next)
= ((void *)0); (&ccb->ccb_h)->periph_links.tqe.tqe_prev
= (&softc->pending_ccb_queue)->tqh_last; *(&softc
->pending_ccb_queue)->tqh_last = (&ccb->ccb_h); (
&softc->pending_ccb_queue)->tqh_last = &(((&
ccb->ccb_h))->periph_links.tqe.tqe_next); ; ; } while (
0)
567 periph_links.tqe)do { ; (((&ccb->ccb_h))->periph_links.tqe.tqe_next)
= ((void *)0); (&ccb->ccb_h)->periph_links.tqe.tqe_prev
= (&softc->pending_ccb_queue)->tqh_last; *(&softc
->pending_ccb_queue)->tqh_last = (&ccb->ccb_h); (
&softc->pending_ccb_queue)->tqh_last = &(((&
ccb->ccb_h))->periph_links.tqe.tqe_next); ; ; } while (
0)
;
568 cam_periph_unlock(softc->periph)__mtx_unlock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (568))
;
569 break;
570 default:
571 cam_periph_lock(softc->periph)__mtx_lock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (571))
;
572 if ((func_code & XPT_FC_QUEUED) != 0) {
6
Taking false branch
14
Taking false branch
22
Taking false branch
30
Taking false branch
573 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("Sending queued ccb %#x (%p)\n", func_code
, user_ccb); if (cam_debug_delay != 0) DELAY(cam_debug_delay)
; }
574 ("Sending queued ccb %#x (%p)\n",if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("Sending queued ccb %#x (%p)\n", func_code
, user_ccb); if (cam_debug_delay != 0) DELAY(cam_debug_delay)
; }
575 func_code, user_ccb))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("Sending queued ccb %#x (%p)\n", func_code
, user_ccb); if (cam_debug_delay != 0) DELAY(cam_debug_delay)
; }
;
576 descr = targgetdescr(softc);
577 descr->user_ccb = user_ccb;
578 descr->priority = priority;
579 descr->func_code = func_code;
580 TAILQ_INSERT_TAIL(&softc->work_queue,do { ; (((descr))->tqe.tqe_next) = ((void *)0); (descr)->
tqe.tqe_prev = (&softc->work_queue)->tqh_last; *(&
softc->work_queue)->tqh_last = (descr); (&softc->
work_queue)->tqh_last = &(((descr))->tqe.tqe_next);
; ; } while (0)
581 descr, tqe)do { ; (((descr))->tqe.tqe_next) = ((void *)0); (descr)->
tqe.tqe_prev = (&softc->work_queue)->tqh_last; *(&
softc->work_queue)->tqh_last = (descr); (&softc->
work_queue)->tqh_last = &(((descr))->tqe.tqe_next);
; ; } while (0)
;
582 xpt_schedule(softc->periph, priority);
583 } else {
584 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("Sending inline ccb %#x (%p)\n", func_code
, user_ccb); if (cam_debug_delay != 0) DELAY(cam_debug_delay)
; }
585 ("Sending inline ccb %#x (%p)\n",if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("Sending inline ccb %#x (%p)\n", func_code
, user_ccb); if (cam_debug_delay != 0) DELAY(cam_debug_delay)
; }
586 func_code, user_ccb))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("Sending inline ccb %#x (%p)\n", func_code
, user_ccb); if (cam_debug_delay != 0) DELAY(cam_debug_delay)
; }
;
587 ccb = targgetccb(softc, func_code, priority);
588 descr = (struct targ_cmd_descr *)
589 ccb->ccb_h.targ_descrperiph_priv.entries[1].ptr;
590 descr->user_ccb = user_ccb;
591 descr->priority = priority;
592 descr->func_code = func_code;
593 if (targusermerge(softc, descr, ccb) != EFAULT14)
7
Taking false branch
15
Taking false branch
23
Taking false branch
31
Taking false branch
594 targsendccb(softc, ccb, descr);
595 targreturnccb(softc, ccb);
32
Calling 'targreturnccb'
596 }
597 cam_periph_unlock(softc->periph)__mtx_unlock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (597))
;
598 break;
8
Execution continues on line 600
16
Execution continues on line 600
24
Execution continues on line 600
599 }
600 write_len += sizeof(user_ccb);
601 }
602
603 /*
604 * If we've successfully taken in some amount of
605 * data, return success for that data first. If
606 * an error is persistent, it will be reported
607 * on the next write.
608 */
609 if (error != 0 && write_len == 0)
610 return (error);
611 if (write_len == 0 && uio->uio_resid != 0)
612 return (ENOSPC28);
613 return (0);
614}
615
616/* Process requests (descrs) via the periph-supplied CCBs */
617static void
618targstart(struct cam_periph *periph, union ccb *start_ccb)
619{
620 struct targ_softc *softc;
621 struct targ_cmd_descr *descr, *next_descr;
622 int error;
623
624 softc = (struct targ_softc *)periph->softc;
625 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targstart %p\n", start_ccb))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("targstart %p\n", start_ccb); if (cam_debug_delay
!= 0) DELAY(cam_debug_delay); }
;
626
627 descr = TAILQ_FIRST(&softc->work_queue)((&softc->work_queue)->tqh_first);
628 if (descr == NULL((void *)0)) {
629 xpt_release_ccb(start_ccb);
630 } else {
631 TAILQ_REMOVE(&softc->work_queue, descr, tqe)do { ; ; ; ; if (((((descr))->tqe.tqe_next)) != ((void *)0
)) (((descr))->tqe.tqe_next)->tqe.tqe_prev = (descr)->
tqe.tqe_prev; else { (&softc->work_queue)->tqh_last
= (descr)->tqe.tqe_prev; ; } *(descr)->tqe.tqe_prev = (
((descr))->tqe.tqe_next); ; ; ; } while (0)
;
632 next_descr = TAILQ_FIRST(&softc->work_queue)((&softc->work_queue)->tqh_first);
633
634 /* Initiate a transaction using the descr and supplied CCB */
635 error = targusermerge(softc, descr, start_ccb);
636 if (error == 0)
637 error = targsendccb(softc, start_ccb, descr);
638 if (error != 0) {
639 xpt_print(periph->path,
640 "targsendccb failed, err %d\n", error);
641 xpt_release_ccb(start_ccb);
642 suword(&descr->user_ccb->ccb_h.status,
643 CAM_REQ_CMP_ERR);
644 TAILQ_INSERT_TAIL(&softc->abort_queue, descr, tqe)do { ; (((descr))->tqe.tqe_next) = ((void *)0); (descr)->
tqe.tqe_prev = (&softc->abort_queue)->tqh_last; *(&
softc->abort_queue)->tqh_last = (descr); (&softc->
abort_queue)->tqh_last = &(((descr))->tqe.tqe_next)
; ; ; } while (0)
;
645 notify_user(softc);
646 }
647
648 /* If we have more work to do, stay scheduled */
649 if (next_descr != NULL((void *)0))
650 xpt_schedule(periph, next_descr->priority);
651 }
652}
653
654static int
655targusermerge(struct targ_softc *softc, struct targ_cmd_descr *descr,
656 union ccb *ccb)
657{
658 struct ccb_hdr *u_ccbh, *k_ccbh;
659 size_t ccb_len;
660 int error;
661
662 u_ccbh = &descr->user_ccb->ccb_h;
663 k_ccbh = &ccb->ccb_h;
664
665 /*
666 * There are some fields in the CCB header that need to be
667 * preserved, the rest we get from the user ccb. (See xpt_merge_ccb)
668 */
669 xpt_setup_ccb(k_ccbh, softc->path, descr->priority);
670 k_ccbh->retry_count = fuword32(&u_ccbh->retry_count);
671 k_ccbh->func_code = descr->func_code;
672 k_ccbh->flags = fuword32(&u_ccbh->flags);
673 k_ccbh->timeout = fuword32(&u_ccbh->timeout);
674 ccb_len = targccblen(k_ccbh->func_code) - sizeof(struct ccb_hdr);
675 error = copyin(u_ccbh + 1, k_ccbh + 1, ccb_len);
676 if (error != 0) {
677 k_ccbh->status = CAM_REQ_CMP_ERR;
678 return (error);
679 }
680
681 /* Translate usermode abort_ccb pointer to its kernel counterpart */
682 if (k_ccbh->func_code == XPT_ABORT) {
683 struct ccb_abort *cab;
684 struct ccb_hdr *ccb_h;
685
686 cab = (struct ccb_abort *)ccb;
687 TAILQ_FOREACH(ccb_h, &softc->pending_ccb_queue,for ((ccb_h) = (((&softc->pending_ccb_queue))->tqh_first
); (ccb_h); (ccb_h) = (((ccb_h))->periph_links.tqe.tqe_next
))
688 periph_links.tqe)for ((ccb_h) = (((&softc->pending_ccb_queue))->tqh_first
); (ccb_h); (ccb_h) = (((ccb_h))->periph_links.tqe.tqe_next
))
{
689 struct targ_cmd_descr *ab_descr;
690
691 ab_descr = (struct targ_cmd_descr *)ccb_h->targ_descrperiph_priv.entries[1].ptr;
692 if (ab_descr->user_ccb == cab->abort_ccb) {
693 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("Changing abort for %p to %p\n", cab
->abort_ccb, ccb_h); if (cam_debug_delay != 0) DELAY(cam_debug_delay
); }
694 ("Changing abort for %p to %p\n",if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("Changing abort for %p to %p\n", cab
->abort_ccb, ccb_h); if (cam_debug_delay != 0) DELAY(cam_debug_delay
); }
695 cab->abort_ccb, ccb_h))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("Changing abort for %p to %p\n", cab
->abort_ccb, ccb_h); if (cam_debug_delay != 0) DELAY(cam_debug_delay
); }
;
696 cab->abort_ccb = (union ccb *)ccb_h;
697 break;
698 }
699 }
700 /* CCB not found, set appropriate status */
701 if (ccb_h == NULL((void *)0)) {
702 k_ccbh->status = CAM_PATH_INVALID;
703 error = ESRCH3;
704 }
705 }
706
707 return (error);
708}
709
710/* Build and send a kernel CCB formed from descr->user_ccb */
711static int
712targsendccb(struct targ_softc *softc, union ccb *ccb,
713 struct targ_cmd_descr *descr)
714{
715 struct cam_periph_map_info *mapinfo;
716 struct ccb_hdr *ccb_h;
717 int error;
718
719 ccb_h = &ccb->ccb_h;
720 mapinfo = &descr->mapinfo;
721 mapinfo->num_bufs_used = 0;
722
723 /*
724 * There's no way for the user to have a completion
725 * function, so we put our own completion function in here.
726 * We also stash in a reference to our descriptor so targreturnccb()
727 * can find our mapping info.
728 */
729 ccb_h->cbfcnp = targdone;
730 ccb_h->targ_descrperiph_priv.entries[1].ptr = descr;
731
732 if ((ccb_h->func_code == XPT_CONT_TARGET_IO) ||
733 (ccb_h->func_code == XPT_DEV_MATCH)) {
734
735 error = cam_periph_mapmem(ccb, mapinfo, softc->maxio);
736
737 /*
738 * cam_periph_mapmem returned an error, we can't continue.
739 * Return the error to the user.
740 */
741 if (error) {
742 ccb_h->status = CAM_REQ_CMP_ERR;
743 mapinfo->num_bufs_used = 0;
744 return (error);
745 }
746 }
747
748 /*
749 * Once queued on the pending CCB list, this CCB will be protected
750 * by our error recovery handler.
751 */
752 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("sendccb %p\n", ccb))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("sendccb %p\n", ccb); if (cam_debug_delay
!= 0) DELAY(cam_debug_delay); }
;
753 if (XPT_FC_IS_QUEUED(ccb)(((ccb)->ccb_h.func_code & XPT_FC_QUEUED) != 0)) {
754 TAILQ_INSERT_TAIL(&softc->pending_ccb_queue, ccb_h,do { ; (((ccb_h))->periph_links.tqe.tqe_next) = ((void *)0
); (ccb_h)->periph_links.tqe.tqe_prev = (&softc->pending_ccb_queue
)->tqh_last; *(&softc->pending_ccb_queue)->tqh_last
= (ccb_h); (&softc->pending_ccb_queue)->tqh_last =
&(((ccb_h))->periph_links.tqe.tqe_next); ; ; } while (
0)
755 periph_links.tqe)do { ; (((ccb_h))->periph_links.tqe.tqe_next) = ((void *)0
); (ccb_h)->periph_links.tqe.tqe_prev = (&softc->pending_ccb_queue
)->tqh_last; *(&softc->pending_ccb_queue)->tqh_last
= (ccb_h); (&softc->pending_ccb_queue)->tqh_last =
&(((ccb_h))->periph_links.tqe.tqe_next); ; ; } while (
0)
;
756 }
757 xpt_action(ccb);
758
759 return (0);
760}
761
762/* Completion routine for CCBs (called at splsoftcam) */
763static void
764targdone(struct cam_periph *periph, union ccb *done_ccb)
765{
766 struct targ_softc *softc;
767 cam_status status;
768
769 CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("targdone %p\n", done_ccb))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, periph->path) >= 0) &&
(xpt_path_comp(cam_dpath, periph->path) < 2)) { xpt_print_path
(periph->path); printf ("targdone %p\n", done_ccb); if (cam_debug_delay
!= 0) DELAY(cam_debug_delay); }
;
770 softc = (struct targ_softc *)periph->softc;
771 TAILQ_REMOVE(&softc->pending_ccb_queue, &done_ccb->ccb_h,do { ; ; ; ; if (((((&done_ccb->ccb_h))->periph_links
.tqe.tqe_next)) != ((void *)0)) (((&done_ccb->ccb_h))->
periph_links.tqe.tqe_next)->periph_links.tqe.tqe_prev = (&
done_ccb->ccb_h)->periph_links.tqe.tqe_prev; else { (&
softc->pending_ccb_queue)->tqh_last = (&done_ccb->
ccb_h)->periph_links.tqe.tqe_prev; ; } *(&done_ccb->
ccb_h)->periph_links.tqe.tqe_prev = (((&done_ccb->ccb_h
))->periph_links.tqe.tqe_next); ; ; ; } while (0)
772 periph_links.tqe)do { ; ; ; ; if (((((&done_ccb->ccb_h))->periph_links
.tqe.tqe_next)) != ((void *)0)) (((&done_ccb->ccb_h))->
periph_links.tqe.tqe_next)->periph_links.tqe.tqe_prev = (&
done_ccb->ccb_h)->periph_links.tqe.tqe_prev; else { (&
softc->pending_ccb_queue)->tqh_last = (&done_ccb->
ccb_h)->periph_links.tqe.tqe_prev; ; } *(&done_ccb->
ccb_h)->periph_links.tqe.tqe_prev = (((&done_ccb->ccb_h
))->periph_links.tqe.tqe_next); ; ; ; } while (0)
;
773 status = done_ccb->ccb_h.status & CAM_STATUS_MASK;
774
775 /* If we're no longer enabled, throw away CCB */
776 if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) {
777 targfreeccb(softc, done_ccb);
778 return;
779 }
780 /* abort_all_pending() waits for pending queue to be empty */
781 if (TAILQ_EMPTY(&softc->pending_ccb_queue)((&softc->pending_ccb_queue)->tqh_first == ((void *
)0))
)
782 wakeup(&softc->pending_ccb_queue);
783
784 switch (done_ccb->ccb_h.func_code) {
785 /* All FC_*_QUEUED CCBs go back to userland */
786 case XPT_IMMED_NOTIFY:
787 case XPT_IMMEDIATE_NOTIFY:
788 case XPT_ACCEPT_TARGET_IO:
789 case XPT_CONT_TARGET_IO:
790 TAILQ_INSERT_TAIL(&softc->user_ccb_queue, &done_ccb->ccb_h,do { ; (((&done_ccb->ccb_h))->periph_links.tqe.tqe_next
) = ((void *)0); (&done_ccb->ccb_h)->periph_links.tqe
.tqe_prev = (&softc->user_ccb_queue)->tqh_last; *(&
softc->user_ccb_queue)->tqh_last = (&done_ccb->ccb_h
); (&softc->user_ccb_queue)->tqh_last = &(((&
done_ccb->ccb_h))->periph_links.tqe.tqe_next); ; ; } while
(0)
791 periph_links.tqe)do { ; (((&done_ccb->ccb_h))->periph_links.tqe.tqe_next
) = ((void *)0); (&done_ccb->ccb_h)->periph_links.tqe
.tqe_prev = (&softc->user_ccb_queue)->tqh_last; *(&
softc->user_ccb_queue)->tqh_last = (&done_ccb->ccb_h
); (&softc->user_ccb_queue)->tqh_last = &(((&
done_ccb->ccb_h))->periph_links.tqe.tqe_next); ; ; } while
(0)
;
792 cam_periph_unlock(softc->periph)__mtx_unlock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (792))
;
793 notify_user(softc);
794 cam_periph_lock(softc->periph)__mtx_lock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (794))
;
795 break;
796 default:
797 panic("targdone: impossible xpt opcode %#x",
798 done_ccb->ccb_h.func_code);
799 /* NOTREACHED */
800 }
801}
802
803/* Return CCBs to the user from the user queue and abort queue */
804static int
805targread(struct cdev *dev, struct uio *uio, int ioflag)
806{
807 struct descr_queue *abort_queue;
808 struct targ_cmd_descr *user_descr;
809 struct targ_softc *softc;
810 struct ccb_queue *user_queue;
811 struct ccb_hdr *ccb_h;
812 union ccb *user_ccb;
813 int read_len, error;
814
815 error = 0;
816 read_len = 0;
817 devfs_get_cdevpriv((void **)&softc);
818 user_queue = &softc->user_ccb_queue;
819 abort_queue = &softc->abort_queue;
820 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targread\n"))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("targread\n"); if (cam_debug_delay !=
0) DELAY(cam_debug_delay); }
;
821
822 /* If no data is available, wait or return immediately */
823 cam_periph_lock(softc->periph)__mtx_lock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (823))
;
824 ccb_h = TAILQ_FIRST(user_queue)((user_queue)->tqh_first);
825 user_descr = TAILQ_FIRST(abort_queue)((abort_queue)->tqh_first);
826 while (ccb_h == NULL((void *)0) && user_descr == NULL((void *)0)) {
827 if ((ioflag & IO_NDELAY0x0004) == 0) {
828 error = cam_periph_sleep(softc->periph, user_queue,_sleep((((user_queue))), &(xpt_path_mtx((softc->periph
)->path))->lock_object, (((((80) + 12) | 0x100))), ((("targrd"
))), tick_sbt * (((0))), 0, 0x0100)
829 PRIBIO | PCATCH, "targrd", 0)_sleep((((user_queue))), &(xpt_path_mtx((softc->periph
)->path))->lock_object, (((((80) + 12) | 0x100))), ((("targrd"
))), tick_sbt * (((0))), 0, 0x0100)
;
830 ccb_h = TAILQ_FIRST(user_queue)((user_queue)->tqh_first);
831 user_descr = TAILQ_FIRST(abort_queue)((abort_queue)->tqh_first);
832 if (error != 0) {
833 if (error == ERESTART(-1)) {
834 continue;
835 } else {
836 goto read_fail;
837 }
838 }
839 } else {
840 cam_periph_unlock(softc->periph)__mtx_unlock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (840))
;
841 return (EAGAIN35);
842 }
843 }
844
845 /* Data is available so fill the user's buffer */
846 while (ccb_h != NULL((void *)0)) {
847 struct targ_cmd_descr *descr;
848
849 if (uio->uio_resid < sizeof(user_ccb))
850 break;
851 TAILQ_REMOVE(user_queue, ccb_h, periph_links.tqe)do { ; ; ; ; if (((((ccb_h))->periph_links.tqe.tqe_next)) !=
((void *)0)) (((ccb_h))->periph_links.tqe.tqe_next)->periph_links
.tqe.tqe_prev = (ccb_h)->periph_links.tqe.tqe_prev; else {
(user_queue)->tqh_last = (ccb_h)->periph_links.tqe.tqe_prev
; ; } *(ccb_h)->periph_links.tqe.tqe_prev = (((ccb_h))->
periph_links.tqe.tqe_next); ; ; ; } while (0)
;
852 descr = (struct targ_cmd_descr *)ccb_h->targ_descrperiph_priv.entries[1].ptr;
853 user_ccb = descr->user_ccb;
854 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("targread ccb %p (%p)\n", ccb_h, user_ccb
); if (cam_debug_delay != 0) DELAY(cam_debug_delay); }
855 ("targread ccb %p (%p)\n", ccb_h, user_ccb))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("targread ccb %p (%p)\n", ccb_h, user_ccb
); if (cam_debug_delay != 0) DELAY(cam_debug_delay); }
;
856 error = targreturnccb(softc, (union ccb *)ccb_h);
857 if (error != 0)
858 goto read_fail;
859 cam_periph_unlock(softc->periph)__mtx_unlock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (859))
;
860 error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
861 cam_periph_lock(softc->periph)__mtx_lock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (861))
;
862 if (error != 0)
863 goto read_fail;
864 read_len += sizeof(user_ccb);
865
866 ccb_h = TAILQ_FIRST(user_queue)((user_queue)->tqh_first);
867 }
868
869 /* Flush out any aborted descriptors */
870 while (user_descr != NULL((void *)0)) {
871 if (uio->uio_resid < sizeof(user_ccb))
872 break;
873 TAILQ_REMOVE(abort_queue, user_descr, tqe)do { ; ; ; ; if (((((user_descr))->tqe.tqe_next)) != ((void
*)0)) (((user_descr))->tqe.tqe_next)->tqe.tqe_prev = (
user_descr)->tqe.tqe_prev; else { (abort_queue)->tqh_last
= (user_descr)->tqe.tqe_prev; ; } *(user_descr)->tqe.tqe_prev
= (((user_descr))->tqe.tqe_next); ; ; ; } while (0)
;
874 user_ccb = user_descr->user_ccb;
875 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("targread aborted descr %p (%p)\n",
user_descr, user_ccb); if (cam_debug_delay != 0) DELAY(cam_debug_delay
); }
876 ("targread aborted descr %p (%p)\n",if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("targread aborted descr %p (%p)\n",
user_descr, user_ccb); if (cam_debug_delay != 0) DELAY(cam_debug_delay
); }
877 user_descr, user_ccb))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("targread aborted descr %p (%p)\n",
user_descr, user_ccb); if (cam_debug_delay != 0) DELAY(cam_debug_delay
); }
;
878 suword(&user_ccb->ccb_h.status, CAM_REQ_ABORTED);
879 cam_periph_unlock(softc->periph)__mtx_unlock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (879))
;
880 error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
881 cam_periph_lock(softc->periph)__mtx_lock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (881))
;
882 if (error != 0)
883 goto read_fail;
884 read_len += sizeof(user_ccb);
885
886 user_descr = TAILQ_FIRST(abort_queue)((abort_queue)->tqh_first);
887 }
888
889 /*
890 * If we've successfully read some amount of data, don't report an
891 * error. If the error is persistent, it will be reported on the
892 * next read().
893 */
894 if (read_len == 0 && uio->uio_resid != 0)
895 error = ENOSPC28;
896
897read_fail:
898 cam_periph_unlock(softc->periph)__mtx_unlock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (898))
;
899 return (error);
900}
901
902/* Copy completed ccb back to the user */
903static int
904targreturnccb(struct targ_softc *softc, union ccb *ccb)
905{
906 struct targ_cmd_descr *descr;
907 struct ccb_hdr *u_ccbh;
908 size_t ccb_len;
909 int error;
910
911 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targreturnccb %p\n", ccb))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("targreturnccb %p\n", ccb); if (cam_debug_delay
!= 0) DELAY(cam_debug_delay); }
;
912 descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descrperiph_priv.entries[1].ptr;
913 u_ccbh = &descr->user_ccb->ccb_h;
914
915 /* Copy out the central portion of the ccb_hdr */
916 copyout(&ccb->ccb_h.retry_count, &u_ccbh->retry_count,
917 offsetof(struct ccb_hdr, periph_priv)__builtin_offsetof(struct ccb_hdr, periph_priv) -
918 offsetof(struct ccb_hdr, retry_count)__builtin_offsetof(struct ccb_hdr, retry_count));
919
920 /* Copy out the rest of the ccb (after the ccb_hdr) */
921 ccb_len = targccblen(ccb->ccb_h.func_code) - sizeof(struct ccb_hdr);
922 if (descr->mapinfo.num_bufs_used != 0)
33
Taking false branch
923 cam_periph_unmapmem(ccb, &descr->mapinfo);
924 error = copyout(&ccb->ccb_h + 1, u_ccbh + 1, ccb_len);
34
Copies out a struct with a union element with different sizes
925 if (error != 0) {
926 xpt_print(softc->path,
927 "targreturnccb - CCB copyout failed (%d)\n", error);
928 }
929 /* Free CCB or send back to devq. */
930 targfreeccb(softc, ccb);
931
932 return (error);
933}
934
935static union ccb *
936targgetccb(struct targ_softc *softc, xpt_opcode type, int priority)
937{
938 union ccb *ccb;
939 int ccb_len;
940
941 ccb_len = targccblen(type);
942 ccb = malloc(ccb_len, M_TARG, M_NOWAIT0x0001);
943 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("getccb %p\n", ccb))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("getccb %p\n", ccb); if (cam_debug_delay
!= 0) DELAY(cam_debug_delay); }
;
944 if (ccb == NULL((void *)0)) {
945 return (ccb);
946 }
947 xpt_setup_ccb(&ccb->ccb_h, softc->path, priority);
948 ccb->ccb_h.func_code = type;
949 ccb->ccb_h.cbfcnp = targdone;
950 ccb->ccb_h.targ_descrperiph_priv.entries[1].ptr = targgetdescr(softc);
951 if (ccb->ccb_h.targ_descrperiph_priv.entries[1].ptr == NULL((void *)0)) {
952 free (ccb, M_TARG);
953 ccb = NULL((void *)0);
954 }
955 return (ccb);
956}
957
958static void
959targfreeccb(struct targ_softc *softc, union ccb *ccb)
960{
961 CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH, ("targfreeccb descr %p and\n",if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags)) { printf("cam_debug: "); printf ("targfreeccb descr %p and\n"
, ccb->ccb_h.periph_priv.entries[1].ptr); if (cam_debug_delay
!= 0) DELAY(cam_debug_delay); }
962 ccb->ccb_h.targ_descr))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags)) { printf("cam_debug: "); printf ("targfreeccb descr %p and\n"
, ccb->ccb_h.periph_priv.entries[1].ptr); if (cam_debug_delay
!= 0) DELAY(cam_debug_delay); }
;
963 free(ccb->ccb_h.targ_descrperiph_priv.entries[1].ptr, M_TARG);
964
965 switch (ccb->ccb_h.func_code) {
966 case XPT_ACCEPT_TARGET_IO:
967 case XPT_IMMED_NOTIFY:
968 case XPT_IMMEDIATE_NOTIFY:
969 CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH, ("freeing ccb %p\n", ccb))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags)) { printf("cam_debug: "); printf ("freeing ccb %p\n"
, ccb); if (cam_debug_delay != 0) DELAY(cam_debug_delay); }
;
970 free(ccb, M_TARG);
971 break;
972 default:
973 /* Send back CCB if we got it from the periph */
974 if (XPT_FC_IS_QUEUED(ccb)(((ccb)->ccb_h.func_code & XPT_FC_QUEUED) != 0)) {
975 CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH,if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags)) { printf("cam_debug: "); printf ("returning queued ccb %p\n"
, ccb); if (cam_debug_delay != 0) DELAY(cam_debug_delay); }
976 ("returning queued ccb %p\n", ccb))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags)) { printf("cam_debug: "); printf ("returning queued ccb %p\n"
, ccb); if (cam_debug_delay != 0) DELAY(cam_debug_delay); }
;
977 xpt_release_ccb(ccb);
978 } else {
979 CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH,if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags)) { printf("cam_debug: "); printf ("freeing ccb %p\n"
, ccb); if (cam_debug_delay != 0) DELAY(cam_debug_delay); }
980 ("freeing ccb %p\n", ccb))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags)) { printf("cam_debug: "); printf ("freeing ccb %p\n"
, ccb); if (cam_debug_delay != 0) DELAY(cam_debug_delay); }
;
981 free(ccb, M_TARG);
982 }
983 break;
984 }
985}
986
987static struct targ_cmd_descr *
988targgetdescr(struct targ_softc *softc)
989{
990 struct targ_cmd_descr *descr;
991
992 descr = malloc(sizeof(*descr), M_TARG,
993 M_NOWAIT0x0001);
994 if (descr) {
995 descr->mapinfo.num_bufs_used = 0;
996 }
997 return (descr);
998}
999
1000static void
1001targinit(void)
1002{
1003 struct cdev *dev;
1004
1005 /* Add symbolic link to targ0 for compatibility. */
1006 dev = make_dev(&targ_cdevsw, 0, UID_ROOT0, GID_WHEEL0, 0600, "targ");
1007 make_dev_alias(dev, "targ0");
1008}
1009
1010static void
1011targasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
1012{
1013 /* All events are handled in usermode by INOTs */
1014 panic("targasync() called, should be an INOT instead");
1015}
1016
1017/* Cancel all pending requests and CCBs awaiting work. */
1018static void
1019abort_all_pending(struct targ_softc *softc)
1020{
1021 struct targ_cmd_descr *descr;
1022 struct ccb_abort cab;
1023 struct ccb_hdr *ccb_h;
1024
1025 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("abort_all_pending\n"))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("abort_all_pending\n"); if (cam_debug_delay
!= 0) DELAY(cam_debug_delay); }
;
1026
1027 /* First abort the descriptors awaiting resources */
1028 while ((descr = TAILQ_FIRST(&softc->work_queue)((&softc->work_queue)->tqh_first)) != NULL((void *)0)) {
1029 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("Aborting descr from workq %p\n", descr
); if (cam_debug_delay != 0) DELAY(cam_debug_delay); }
1030 ("Aborting descr from workq %p\n", descr))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("Aborting descr from workq %p\n", descr
); if (cam_debug_delay != 0) DELAY(cam_debug_delay); }
;
1031 TAILQ_REMOVE(&softc->work_queue, descr, tqe)do { ; ; ; ; if (((((descr))->tqe.tqe_next)) != ((void *)0
)) (((descr))->tqe.tqe_next)->tqe.tqe_prev = (descr)->
tqe.tqe_prev; else { (&softc->work_queue)->tqh_last
= (descr)->tqe.tqe_prev; ; } *(descr)->tqe.tqe_prev = (
((descr))->tqe.tqe_next); ; ; ; } while (0)
;
1032 TAILQ_INSERT_TAIL(&softc->abort_queue, descr, tqe)do { ; (((descr))->tqe.tqe_next) = ((void *)0); (descr)->
tqe.tqe_prev = (&softc->abort_queue)->tqh_last; *(&
softc->abort_queue)->tqh_last = (descr); (&softc->
abort_queue)->tqh_last = &(((descr))->tqe.tqe_next)
; ; ; } while (0)
;
1033 }
1034
1035 /*
1036 * Then abort all pending CCBs.
1037 * targdone() will return the aborted CCB via user_ccb_queue
1038 */
1039 xpt_setup_ccb(&cab.ccb_h, softc->path, CAM_PRIORITY_NORMAL((CAM_RL_NORMAL << 8) + 0x80));
1040 cab.ccb_h.func_code = XPT_ABORT;
1041 cab.ccb_h.status = CAM_REQ_CMP_ERR;
1042 TAILQ_FOREACH(ccb_h, &softc->pending_ccb_queue, periph_links.tqe)for ((ccb_h) = (((&softc->pending_ccb_queue))->tqh_first
); (ccb_h); (ccb_h) = (((ccb_h))->periph_links.tqe.tqe_next
))
{
1043 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("Aborting pending CCB %p\n", ccb_h)
; if (cam_debug_delay != 0) DELAY(cam_debug_delay); }
1044 ("Aborting pending CCB %p\n", ccb_h))if (((CAM_DEBUG_PERIPH) & ((CAM_DEBUG_INFO | CAM_DEBUG_CDB
| CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | CAM_DEBUG_NONE)) &
cam_dflags) && (cam_dpath != ((void *)0)) &&
(xpt_path_comp(cam_dpath, softc->path) >= 0) &&
(xpt_path_comp(cam_dpath, softc->path) < 2)) { xpt_print_path
(softc->path); printf ("Aborting pending CCB %p\n", ccb_h)
; if (cam_debug_delay != 0) DELAY(cam_debug_delay); }
;
1045 cab.abort_ccb = (union ccb *)ccb_h;
1046 xpt_action((union ccb *)&cab);
1047 if (cab.ccb_h.status != CAM_REQ_CMP) {
1048 xpt_print(cab.ccb_h.path,
1049 "Unable to abort CCB, status %#x\n",
1050 cab.ccb_h.status);
1051 }
1052 }
1053
1054 /* If we aborted at least one pending CCB ok, wait for it. */
1055 if (cab.ccb_h.status == CAM_REQ_CMP) {
1056 cam_periph_sleep(softc->periph, &softc->pending_ccb_queue,_sleep((((&softc->pending_ccb_queue))), &(xpt_path_mtx
((softc->periph)->path))->lock_object, (((((80) + 12
) | 0x100))), ((("tgabrt"))), tick_sbt * (((0))), 0, 0x0100)
1057 PRIBIO | PCATCH, "tgabrt", 0)_sleep((((&softc->pending_ccb_queue))), &(xpt_path_mtx
((softc->periph)->path))->lock_object, (((((80) + 12
) | 0x100))), ((("tgabrt"))), tick_sbt * (((0))), 0, 0x0100)
;
1058 }
1059
1060 /* If we aborted anything from the work queue, wakeup user. */
1061 if (!TAILQ_EMPTY(&softc->user_ccb_queue)((&softc->user_ccb_queue)->tqh_first == ((void *)0)
)
1062 || !TAILQ_EMPTY(&softc->abort_queue)((&softc->abort_queue)->tqh_first == ((void *)0))) {
1063 cam_periph_unlock(softc->periph)__mtx_unlock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (1063))
;
1064 notify_user(softc);
1065 cam_periph_lock(softc->periph)__mtx_lock_flags(&((((xpt_path_mtx((softc->periph)->
path)))))->mtx_lock, ((0)), ("/usr/src/sys/modules/cam/../../cam/scsi/scsi_target.c"
), (1065))
;
1066 }
1067}
1068
1069/* Notify the user that data is ready */
1070static void
1071notify_user(struct targ_softc *softc)
1072{
1073 /*
1074 * Notify users sleeping via poll(), kqueue(), and
1075 * blocking read().
1076 */
1077 selwakeuppri(&softc->read_select, PRIBIO((80) + 12));
1078 KNOTE_UNLOCKED(&softc->read_select.si_note, 0)knote(&softc->read_select.si_note, 0, 0);
1079 wakeup(&softc->user_ccb_queue);
1080}
1081
1082/* Convert CAM status to errno values */
1083static int
1084targcamstatus(cam_status status)
1085{
1086 switch (status & CAM_STATUS_MASK) {
1087 case CAM_REQ_CMP: /* CCB request completed without error */
1088 return (0);
1089 case CAM_REQ_INPROG: /* CCB request is in progress */
1090 return (EINPROGRESS36);
1091 case CAM_REQ_CMP_ERR: /* CCB request completed with an error */
1092 return (EIO5);
1093 case CAM_PROVIDE_FAIL: /* Unable to provide requested capability */
1094 return (ENOTTY25);
1095 case CAM_FUNC_NOTAVAIL: /* The requested function is not available */
1096 return (ENOTSUP45);
1097 case CAM_LUN_ALRDY_ENA: /* LUN is already enabled for target mode */
1098 return (EADDRINUSE48);
1099 case CAM_PATH_INVALID: /* Supplied Path ID is invalid */
1100 case CAM_DEV_NOT_THERE: /* SCSI Device Not Installed/there */
1101 return (ENOENT2);
1102 case CAM_REQ_ABORTED: /* CCB request aborted by the host */
1103 return (ECANCELED85);
1104 case CAM_CMD_TIMEOUT: /* Command timeout */
1105 return (ETIMEDOUT60);
1106 case CAM_REQUEUE_REQ: /* Requeue to preserve transaction ordering */
1107 return (EAGAIN35);
1108 case CAM_REQ_INVALID: /* CCB request was invalid */
1109 return (EINVAL22);
1110 case CAM_RESRC_UNAVAIL: /* Resource Unavailable */
1111 return (ENOMEM12);
1112 case CAM_BUSY: /* CAM subsystem is busy */
1113 case CAM_UA_ABORT: /* Unable to abort CCB request */
1114 return (EBUSY16);
1115 default:
1116 return (ENXIO6);
1117 }
1118}
1119
1120static size_t
1121targccblen(xpt_opcode func_code)
1122{
1123 int len;
1124
1125 /* Codes we expect to see as a target */
1126 switch (func_code) {
1127 case XPT_CONT_TARGET_IO:
1128 case XPT_SCSI_IO:
1129 len = sizeof(struct ccb_scsiio);
1130 break;
1131 case XPT_ACCEPT_TARGET_IO:
1132 len = sizeof(struct ccb_accept_tio);
1133 break;
1134 case XPT_IMMED_NOTIFY:
1135 len = sizeof(struct ccb_immed_notify);
1136 break;
1137 case XPT_IMMEDIATE_NOTIFY:
1138 len = sizeof(struct ccb_immediate_notify);
1139 break;
1140 case XPT_REL_SIMQ:
1141 len = sizeof(struct ccb_relsim);
1142 break;
1143 case XPT_PATH_INQ:
1144 len = sizeof(struct ccb_pathinq);
1145 break;
1146 case XPT_DEBUG:
1147 len = sizeof(struct ccb_debug);
1148 break;
1149 case XPT_ABORT:
1150 len = sizeof(struct ccb_abort);
1151 break;
1152 case XPT_EN_LUN:
1153 len = sizeof(struct ccb_en_lun);
1154 break;
1155 default:
1156 len = sizeof(union ccb);
1157 break;
1158 }
1159
1160 return (len);
1161}