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