]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/cam/scsi/scsi_target.c
Make MAXPHYS tunable. Bump MAXPHYS to 1M.
[FreeBSD/FreeBSD.git] / sys / cam / scsi / scsi_target.c
1 /*-
2  * Generic SCSI Target Kernel Mode Driver
3  *
4  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/conf.h>
39 #include <sys/malloc.h>
40 #include <sys/poll.h>
41 #include <sys/vnode.h>
42 #include <sys/lock.h>
43 #include <sys/mutex.h>
44 #include <sys/devicestat.h>
45 #include <sys/proc.h>
46 /* Includes to support callout */
47 #include <sys/types.h>
48 #include <sys/systm.h>
49
50 #include <cam/cam.h>
51 #include <cam/cam_ccb.h>
52 #include <cam/cam_periph.h>
53 #include <cam/cam_xpt_periph.h>
54 #include <cam/cam_sim.h>
55 #include <cam/scsi/scsi_targetio.h>
56
57 /* Transaction information attached to each CCB sent by the user */
58 struct targ_cmd_descr {
59         struct cam_periph_map_info  mapinfo;
60         TAILQ_ENTRY(targ_cmd_descr) 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_descr      periph_priv.entries[1].ptr
68
69 TAILQ_HEAD(descr_queue, targ_cmd_descr);
70
71 typedef 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 */
78 struct 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
102 static d_open_t         targopen;
103 static d_read_t         targread;
104 static d_write_t        targwrite;
105 static d_ioctl_t        targioctl;
106 static d_poll_t         targpoll;
107 static d_kqfilter_t     targkqfilter;
108 static void             targreadfiltdetach(struct knote *kn);
109 static int              targreadfilt(struct knote *kn, long hint);
110 static struct filterops targread_filtops = {
111         .f_isfd = 1,
112         .f_detach = targreadfiltdetach,
113         .f_event = targreadfilt,
114 };
115
116 static struct cdevsw targ_cdevsw = {
117         .d_version =    D_VERSION,
118         .d_flags =      D_NEEDGIANT,
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
128 static cam_status       targendislun(struct cam_path *path, int enable,
129                                      int grp6_len, int grp7_len);
130 static cam_status       targenable(struct targ_softc *softc,
131                                    struct cam_path *path,
132                                    int grp6_len, int grp7_len);
133 static cam_status       targdisable(struct targ_softc *softc);
134 static periph_ctor_t    targctor;
135 static periph_dtor_t    targdtor;
136 static periph_start_t   targstart;
137 static int              targusermerge(struct targ_softc *softc,
138                                       struct targ_cmd_descr *descr,
139                                       union ccb *ccb);
140 static int              targsendccb(struct targ_softc *softc, union ccb *ccb,
141                                     struct targ_cmd_descr *descr);
142 static void             targdone(struct cam_periph *periph,
143                                  union  ccb *done_ccb);
144 static int              targreturnccb(struct targ_softc *softc,
145                                       union  ccb *ccb);
146 static union ccb *      targgetccb(struct targ_softc *softc, xpt_opcode type,
147                                    int priority);
148 static void             targfreeccb(struct targ_softc *softc, union ccb *ccb);
149 static struct targ_cmd_descr *
150                         targgetdescr(struct targ_softc *softc);
151 static periph_init_t    targinit;
152 static void             targasync(void *callback_arg, u_int32_t code,
153                                   struct cam_path *path, void *arg);
154 static void             abort_all_pending(struct targ_softc *softc);
155 static void             notify_user(struct targ_softc *softc);
156 static int              targcamstatus(cam_status status);
157 static size_t           targccblen(xpt_opcode func_code);
158
159 static struct periph_driver targdriver =
160 {
161         targinit, "targ",
162         TAILQ_HEAD_INITIALIZER(targdriver.units), /* generation */ 0
163 };
164 PERIPHDRIVER_DECLARE(targ, targdriver);
165
166 static MALLOC_DEFINE(M_TARG, "TARG", "TARG data");
167
168 /* Disable LUN if enabled and teardown softc */
169 static void
170 targcdevdtor(void *data)
171 {
172         struct targ_softc *softc;
173         struct cam_periph *periph;
174
175         softc = data;
176         if (softc->periph == NULL) {
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);
189         (void)targdisable(softc);
190         if (softc->periph != NULL) {
191                 cam_periph_invalidate(softc->periph);
192                 softc->periph = NULL;
193         }
194         cam_periph_unlock(periph);
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  */
204 static int
205 targopen(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_WAITOK | M_ZERO);
212         softc->state = TARG_STATE_OPENED;
213         softc->periph = NULL;
214         softc->path = NULL;
215
216         TAILQ_INIT(&softc->pending_ccb_queue);
217         TAILQ_INIT(&softc->work_queue);
218         TAILQ_INIT(&softc->abort_queue);
219         TAILQ_INIT(&softc->user_ccb_queue);
220         knlist_init_mtx(&softc->read_select.si_note, NULL);
221
222         devfs_set_cdevpriv(softc, targcdevdtor);
223         return (0);
224 }
225
226 /* Enable/disable LUNs, set debugging level */
227 static int
228 targioctl(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:
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,
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);
251                 status = targenable(softc, path, new_lun->grp6_len,
252                                     new_lun->grp7_len);
253                 xpt_path_unlock(path);
254                 xpt_free_path(path);
255                 break;
256         }
257         case TARGIOCDISABLE:
258                 if (softc->periph == NULL) {
259                         status = CAM_DEV_NOT_THERE;
260                         break;
261                 }
262                 cam_periph_lock(softc->periph);
263                 status = targdisable(softc);
264                 cam_periph_unlock(softc->periph);
265                 break;
266         case TARGIOCDEBUG:
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);
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 */
296 static int
297 targpoll(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 & (POLLOUT | POLLWRNORM);
306         if ((poll_events & (POLLIN | POLLRDNORM)) != 0) {
307                 /* Poll for read() depends on user and abort queues. */
308                 cam_periph_lock(softc->periph);
309                 if (!TAILQ_EMPTY(&softc->user_ccb_queue) ||
310                     !TAILQ_EMPTY(&softc->abort_queue)) {
311                         revents |= poll_events & (POLLIN | POLLRDNORM);
312                 }
313                 cam_periph_unlock(softc->periph);
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
322 static int
323 targkqfilter(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
334 static void
335 targreadfiltdetach(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 */
344 static int
345 targreadfilt(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);
352         retval = !TAILQ_EMPTY(&softc->user_ccb_queue) ||
353                  !TAILQ_EMPTY(&softc->abort_queue);
354         cam_periph_unlock(softc->periph);
355         return (retval);
356 }
357
358 /* Send the HBA the enable/disable message */
359 static cam_status
360 targendislun(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);
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 */
382 static cam_status
383 targenable(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_path_inq(&cpi, path);
395         status = cpi.ccb_h.status & CAM_STATUS_MASK;
396         if (status != CAM_REQ_CMP) {
397                 printf("pathinq failed, status %#x\n", status);
398                 goto enable_fail;
399         }
400         if ((cpi.target_sprt & PIT_PROCESSOR) == 0) {
401                 printf("controller does not support target mode\n");
402                 status = CAM_FUNC_NOTAVAIL;
403                 goto enable_fail;
404         }
405         if (cpi.maxio == 0)
406                 softc->maxio = DFLTPHYS;        /* traditional default */
407         else if (cpi.maxio > maxphys)
408                 softc->maxio = maxphys;         /* for safety */
409         else
410                 softc->maxio = cpi.maxio;       /* real value */
411
412         /* Destroy any periph on our path if it is disabled */
413         periph = cam_periph_find(path, "targ");
414         if (periph != NULL) {
415                 struct targ_softc *del_softc;
416
417                 del_softc = (struct targ_softc *)periph->softc;
418                 if ((del_softc->state & TARG_STATE_LUN_ENABLED) == 0) {
419                         cam_periph_invalidate(del_softc->periph);
420                         del_softc->periph = NULL;
421                 } else {
422                         printf("Requested path still in use by targ%d\n",
423                                periph->unit_number);
424                         status = CAM_LUN_ALRDY_ENA;
425                         goto enable_fail;
426                 }
427         }
428
429         /* Create a periph instance attached to this path */
430         status = cam_periph_alloc(targctor, NULL, targdtor, targstart,
431                         "targ", CAM_PERIPH_BIO, path, targasync, 0, softc);
432         if (status != CAM_REQ_CMP) {
433                 printf("cam_periph_alloc failed, status %#x\n", status);
434                 goto enable_fail;
435         }
436
437         /* Ensure that the periph now exists. */
438         if (cam_periph_find(path, "targ") == NULL) {
439                 panic("targenable: succeeded but no periph?");
440                 /* NOTREACHED */
441         }
442
443         /* Send the enable lun message */
444         status = targendislun(path, /*enable*/1, grp6_len, grp7_len);
445         if (status != CAM_REQ_CMP) {
446                 printf("enable lun failed, status %#x\n", status);
447                 goto enable_fail;
448         }
449         softc->state |= TARG_STATE_LUN_ENABLED;
450
451 enable_fail:
452         return (status);
453 }
454
455 /* Disable this softc's target instance if enabled */
456 static cam_status
457 targdisable(struct targ_softc *softc)
458 {
459         cam_status status;
460
461         if ((softc->state & TARG_STATE_LUN_ENABLED) == 0)
462                 return (CAM_REQ_CMP);
463
464         CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targdisable\n"));
465
466         /* Abort any ccbs pending on the controller */
467         abort_all_pending(softc);
468
469         /* Disable this lun */
470         status = targendislun(softc->path, /*enable*/0,
471                               /*grp6_len*/0, /*grp7_len*/0);
472         if (status == CAM_REQ_CMP)
473                 softc->state &= ~TARG_STATE_LUN_ENABLED;
474         else
475                 printf("Disable lun failed, status %#x\n", status);
476
477         return (status);
478 }
479
480 /* Initialize a periph (called from cam_periph_alloc) */
481 static cam_status
482 targctor(struct cam_periph *periph, void *arg)
483 {
484         struct targ_softc *softc;
485
486         /* Store pointer to softc for periph-driven routines */
487         softc = (struct targ_softc *)arg;
488         periph->softc = softc;
489         softc->periph = periph;
490         softc->path = periph->path;
491         return (CAM_REQ_CMP);
492 }
493
494 static void
495 targdtor(struct cam_periph *periph)
496 {
497         struct targ_softc     *softc;
498         struct ccb_hdr        *ccb_h;
499         struct targ_cmd_descr *descr;
500
501         softc = (struct targ_softc *)periph->softc;
502
503         /* 
504          * targdisable() aborts CCBs back to the user and leaves them
505          * on user_ccb_queue and abort_queue in case the user is still
506          * interested in them.  We free them now.
507          */
508         while ((ccb_h = TAILQ_FIRST(&softc->user_ccb_queue)) != NULL) {
509                 TAILQ_REMOVE(&softc->user_ccb_queue, ccb_h, periph_links.tqe);
510                 targfreeccb(softc, (union ccb *)ccb_h);
511         }
512         while ((descr = TAILQ_FIRST(&softc->abort_queue)) != NULL) {
513                 TAILQ_REMOVE(&softc->abort_queue, descr, tqe);
514                 free(descr, M_TARG);
515         }
516
517         softc->periph = NULL;
518         softc->path = NULL;
519         periph->softc = NULL;
520 }
521
522 /* Receive CCBs from user mode proc and send them to the HBA */
523 static int
524 targwrite(struct cdev *dev, struct uio *uio, int ioflag)
525 {
526         union ccb *user_ccb;
527         struct targ_softc *softc;
528         struct targ_cmd_descr *descr;
529         int write_len, error;
530         int func_code, priority;
531
532         devfs_get_cdevpriv((void **)&softc);
533         write_len = error = 0;
534         CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
535                   ("write - uio_resid %zd\n", uio->uio_resid));
536         while (uio->uio_resid >= sizeof(user_ccb) && error == 0) {
537                 union ccb *ccb;
538
539                 error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
540                 if (error != 0) {
541                         CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
542                                   ("write - uiomove failed (%d)\n", error));
543                         break;
544                 }
545                 priority = fuword32(&user_ccb->ccb_h.pinfo.priority);
546                 if (priority == CAM_PRIORITY_NONE) {
547                         error = EINVAL;
548                         break;
549                 }
550                 func_code = fuword32(&user_ccb->ccb_h.func_code);
551                 switch (func_code) {
552                 case XPT_ACCEPT_TARGET_IO:
553                 case XPT_IMMED_NOTIFY:
554                 case XPT_IMMEDIATE_NOTIFY:
555                         cam_periph_lock(softc->periph);
556                         ccb = targgetccb(softc, func_code, priority);
557                         descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descr;
558                         descr->user_ccb = user_ccb;
559                         descr->func_code = func_code;
560                         CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
561                                   ("Sent ATIO/INOT (%p)\n", user_ccb));
562                         xpt_action(ccb);
563                         TAILQ_INSERT_TAIL(&softc->pending_ccb_queue,
564                                           &ccb->ccb_h,
565                                           periph_links.tqe);
566                         cam_periph_unlock(softc->periph);
567                         break;
568                 default:
569                         cam_periph_lock(softc->periph);
570                         if ((func_code & XPT_FC_QUEUED) != 0) {
571                                 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
572                                           ("Sending queued ccb %#x (%p)\n",
573                                           func_code, user_ccb));
574                                 descr = targgetdescr(softc);
575                                 descr->user_ccb = user_ccb;
576                                 descr->priority = priority;
577                                 descr->func_code = func_code;
578                                 TAILQ_INSERT_TAIL(&softc->work_queue,
579                                                   descr, tqe);
580                                 xpt_schedule(softc->periph, priority);
581                         } else {
582                                 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
583                                           ("Sending inline ccb %#x (%p)\n",
584                                           func_code, user_ccb));
585                                 ccb = targgetccb(softc, func_code, priority);
586                                 descr = (struct targ_cmd_descr *)
587                                          ccb->ccb_h.targ_descr;
588                                 descr->user_ccb = user_ccb;
589                                 descr->priority = priority;
590                                 descr->func_code = func_code;
591                                 if (targusermerge(softc, descr, ccb) != EFAULT)
592                                         targsendccb(softc, ccb, descr);
593                                 targreturnccb(softc, ccb);
594                         }
595                         cam_periph_unlock(softc->periph);
596                         break;
597                 }
598                 write_len += sizeof(user_ccb);
599         }
600
601         /*
602          * If we've successfully taken in some amount of
603          * data, return success for that data first.  If
604          * an error is persistent, it will be reported
605          * on the next write.
606          */
607         if (error != 0 && write_len == 0)
608                 return (error);
609         if (write_len == 0 && uio->uio_resid != 0)
610                 return (ENOSPC);
611         return (0);
612 }
613
614 /* Process requests (descrs) via the periph-supplied CCBs */
615 static void
616 targstart(struct cam_periph *periph, union ccb *start_ccb)
617 {
618         struct targ_softc *softc;
619         struct targ_cmd_descr *descr, *next_descr;
620         int error;
621
622         softc = (struct targ_softc *)periph->softc;
623         CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targstart %p\n", start_ccb));
624
625         descr = TAILQ_FIRST(&softc->work_queue);
626         if (descr == NULL) {
627                 xpt_release_ccb(start_ccb);
628         } else {
629                 TAILQ_REMOVE(&softc->work_queue, descr, tqe);
630                 next_descr = TAILQ_FIRST(&softc->work_queue);
631
632                 /* Initiate a transaction using the descr and supplied CCB */
633                 error = targusermerge(softc, descr, start_ccb);
634                 if (error == 0)
635                         error = targsendccb(softc, start_ccb, descr);
636                 if (error != 0) {
637                         xpt_print(periph->path,
638                             "targsendccb failed, err %d\n", error);
639                         xpt_release_ccb(start_ccb);
640                         suword(&descr->user_ccb->ccb_h.status,
641                                CAM_REQ_CMP_ERR);
642                         TAILQ_INSERT_TAIL(&softc->abort_queue, descr, tqe);
643                         notify_user(softc);
644                 }
645
646                 /* If we have more work to do, stay scheduled */
647                 if (next_descr != NULL)
648                         xpt_schedule(periph, next_descr->priority);
649         }
650 }
651
652 static int
653 targusermerge(struct targ_softc *softc, struct targ_cmd_descr *descr,
654               union ccb *ccb)
655 {
656         struct ccb_hdr *u_ccbh, *k_ccbh;
657         size_t ccb_len;
658         int error;
659
660         u_ccbh = &descr->user_ccb->ccb_h;
661         k_ccbh = &ccb->ccb_h;
662
663         /*
664          * There are some fields in the CCB header that need to be
665          * preserved, the rest we get from the user ccb. (See xpt_merge_ccb)
666          */
667         xpt_setup_ccb(k_ccbh, softc->path, descr->priority);
668         k_ccbh->retry_count = fuword32(&u_ccbh->retry_count);
669         k_ccbh->func_code = descr->func_code;
670         k_ccbh->flags = fuword32(&u_ccbh->flags);
671         k_ccbh->timeout = fuword32(&u_ccbh->timeout);
672         ccb_len = targccblen(k_ccbh->func_code) - sizeof(struct ccb_hdr);
673         error = copyin(u_ccbh + 1, k_ccbh + 1, ccb_len);
674         if (error != 0) {
675                 k_ccbh->status = CAM_REQ_CMP_ERR;
676                 return (error);
677         }
678
679         /* Translate usermode abort_ccb pointer to its kernel counterpart */
680         if (k_ccbh->func_code == XPT_ABORT) {
681                 struct ccb_abort *cab;
682                 struct ccb_hdr *ccb_h;
683
684                 cab = (struct ccb_abort *)ccb;
685                 TAILQ_FOREACH(ccb_h, &softc->pending_ccb_queue,
686                     periph_links.tqe) {
687                         struct targ_cmd_descr *ab_descr;
688
689                         ab_descr = (struct targ_cmd_descr *)ccb_h->targ_descr;
690                         if (ab_descr->user_ccb == cab->abort_ccb) {
691                                 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
692                                           ("Changing abort for %p to %p\n",
693                                           cab->abort_ccb, ccb_h));
694                                 cab->abort_ccb = (union ccb *)ccb_h;
695                                 break;
696                         }
697                 }
698                 /* CCB not found, set appropriate status */
699                 if (ccb_h == NULL) {
700                         k_ccbh->status = CAM_PATH_INVALID;
701                         error = ESRCH;
702                 }
703         }
704
705         return (error);
706 }
707
708 /* Build and send a kernel CCB formed from descr->user_ccb */
709 static int
710 targsendccb(struct targ_softc *softc, union ccb *ccb,
711             struct targ_cmd_descr *descr)
712 {
713         struct cam_periph_map_info *mapinfo;
714         struct ccb_hdr *ccb_h;
715         int error;
716
717         ccb_h = &ccb->ccb_h;
718         mapinfo = &descr->mapinfo;
719         mapinfo->num_bufs_used = 0;
720
721         /*
722          * There's no way for the user to have a completion
723          * function, so we put our own completion function in here.
724          * We also stash in a reference to our descriptor so targreturnccb()
725          * can find our mapping info.
726          */
727         ccb_h->cbfcnp = targdone;
728         ccb_h->targ_descr = descr;
729
730         if ((ccb_h->func_code == XPT_CONT_TARGET_IO) ||
731             (ccb_h->func_code == XPT_DEV_MATCH)) {
732                 error = cam_periph_mapmem(ccb, mapinfo, softc->maxio);
733
734                 /*
735                  * cam_periph_mapmem returned an error, we can't continue.
736                  * Return the error to the user.
737                  */
738                 if (error) {
739                         ccb_h->status = CAM_REQ_CMP_ERR;
740                         mapinfo->num_bufs_used = 0;
741                         return (error);
742                 }
743         }
744
745         /*
746          * Once queued on the pending CCB list, this CCB will be protected
747          * by our error recovery handler.
748          */
749         CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("sendccb %p\n", ccb));
750         if (XPT_FC_IS_QUEUED(ccb)) {
751                 TAILQ_INSERT_TAIL(&softc->pending_ccb_queue, ccb_h,
752                                   periph_links.tqe);
753         }
754         xpt_action(ccb);
755
756         return (0);
757 }
758
759 /* Completion routine for CCBs (called at splsoftcam) */
760 static void
761 targdone(struct cam_periph *periph, union ccb *done_ccb)
762 {
763         struct targ_softc *softc;
764         cam_status status;
765
766         CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("targdone %p\n", done_ccb));
767         softc = (struct targ_softc *)periph->softc;
768         TAILQ_REMOVE(&softc->pending_ccb_queue, &done_ccb->ccb_h,
769                      periph_links.tqe);
770         status = done_ccb->ccb_h.status & CAM_STATUS_MASK;
771
772         /* If we're no longer enabled, throw away CCB */
773         if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) {
774                 targfreeccb(softc, done_ccb);
775                 return;
776         }
777         /* abort_all_pending() waits for pending queue to be empty */
778         if (TAILQ_EMPTY(&softc->pending_ccb_queue))
779                 wakeup(&softc->pending_ccb_queue);
780
781         switch (done_ccb->ccb_h.func_code) {
782         /* All FC_*_QUEUED CCBs go back to userland */
783         case XPT_IMMED_NOTIFY:
784         case XPT_IMMEDIATE_NOTIFY:
785         case XPT_ACCEPT_TARGET_IO:
786         case XPT_CONT_TARGET_IO:
787                 TAILQ_INSERT_TAIL(&softc->user_ccb_queue, &done_ccb->ccb_h,
788                                   periph_links.tqe);
789                 cam_periph_unlock(softc->periph);
790                 notify_user(softc);
791                 cam_periph_lock(softc->periph);
792                 break;
793         default:
794                 panic("targdone: impossible xpt opcode %#x",
795                       done_ccb->ccb_h.func_code);
796                 /* NOTREACHED */
797         }
798 }
799
800 /* Return CCBs to the user from the user queue and abort queue */
801 static int
802 targread(struct cdev *dev, struct uio *uio, int ioflag)
803 {
804         struct descr_queue      *abort_queue;
805         struct targ_cmd_descr   *user_descr;
806         struct targ_softc       *softc;
807         struct ccb_queue  *user_queue;
808         struct ccb_hdr    *ccb_h;
809         union  ccb        *user_ccb;
810         int                read_len, error;
811
812         error = 0;
813         read_len = 0;
814         devfs_get_cdevpriv((void **)&softc);
815         user_queue = &softc->user_ccb_queue;
816         abort_queue = &softc->abort_queue;
817         CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targread\n"));
818
819         /* If no data is available, wait or return immediately */
820         cam_periph_lock(softc->periph);
821         ccb_h = TAILQ_FIRST(user_queue);
822         user_descr = TAILQ_FIRST(abort_queue);
823         while (ccb_h == NULL && user_descr == NULL) {
824                 if ((ioflag & IO_NDELAY) == 0) {
825                         error = cam_periph_sleep(softc->periph, user_queue,
826                             PRIBIO | PCATCH, "targrd", 0);
827                         ccb_h = TAILQ_FIRST(user_queue);
828                         user_descr = TAILQ_FIRST(abort_queue);
829                         if (error != 0) {
830                                 if (error == ERESTART) {
831                                         continue;
832                                 } else {
833                                         goto read_fail;
834                                 }
835                         }
836                 } else {
837                         cam_periph_unlock(softc->periph);
838                         return (EAGAIN);
839                 }
840         }
841
842         /* Data is available so fill the user's buffer */
843         while (ccb_h != NULL) {
844                 struct targ_cmd_descr *descr;
845
846                 if (uio->uio_resid < sizeof(user_ccb))
847                         break;
848                 TAILQ_REMOVE(user_queue, ccb_h, periph_links.tqe);
849                 descr = (struct targ_cmd_descr *)ccb_h->targ_descr;
850                 user_ccb = descr->user_ccb;
851                 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
852                           ("targread ccb %p (%p)\n", ccb_h, user_ccb));
853                 error = targreturnccb(softc, (union ccb *)ccb_h);
854                 if (error != 0)
855                         goto read_fail;
856                 cam_periph_unlock(softc->periph);
857                 error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
858                 cam_periph_lock(softc->periph);
859                 if (error != 0)
860                         goto read_fail;
861                 read_len += sizeof(user_ccb);
862
863                 ccb_h = TAILQ_FIRST(user_queue);
864         }
865
866         /* Flush out any aborted descriptors */
867         while (user_descr != NULL) {
868                 if (uio->uio_resid < sizeof(user_ccb))
869                         break;
870                 TAILQ_REMOVE(abort_queue, user_descr, tqe);
871                 user_ccb = user_descr->user_ccb;
872                 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
873                           ("targread aborted descr %p (%p)\n",
874                           user_descr, user_ccb));
875                 suword(&user_ccb->ccb_h.status, CAM_REQ_ABORTED);
876                 cam_periph_unlock(softc->periph);
877                 error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
878                 cam_periph_lock(softc->periph);
879                 if (error != 0)
880                         goto read_fail;
881                 read_len += sizeof(user_ccb);
882
883                 user_descr = TAILQ_FIRST(abort_queue);
884         }
885
886         /*
887          * If we've successfully read some amount of data, don't report an
888          * error.  If the error is persistent, it will be reported on the
889          * next read().
890          */
891         if (read_len == 0 && uio->uio_resid != 0)
892                 error = ENOSPC;
893
894 read_fail:
895         cam_periph_unlock(softc->periph);
896         return (error);
897 }
898
899 /* Copy completed ccb back to the user */
900 static int
901 targreturnccb(struct targ_softc *softc, union ccb *ccb)
902 {
903         struct targ_cmd_descr *descr;
904         struct ccb_hdr *u_ccbh;
905         size_t ccb_len;
906         int error;
907
908         CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targreturnccb %p\n", ccb));
909         descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descr;
910         u_ccbh = &descr->user_ccb->ccb_h;
911
912         /* Copy out the central portion of the ccb_hdr */
913         copyout(&ccb->ccb_h.retry_count, &u_ccbh->retry_count,
914                 offsetof(struct ccb_hdr, periph_priv) -
915                 offsetof(struct ccb_hdr, retry_count));
916
917         /* Copy out the rest of the ccb (after the ccb_hdr) */
918         ccb_len = targccblen(ccb->ccb_h.func_code) - sizeof(struct ccb_hdr);
919         if (descr->mapinfo.num_bufs_used != 0)
920                 cam_periph_unmapmem(ccb, &descr->mapinfo);
921         error = copyout(&ccb->ccb_h + 1, u_ccbh + 1, ccb_len);
922         if (error != 0) {
923                 xpt_print(softc->path,
924                     "targreturnccb - CCB copyout failed (%d)\n", error);
925         }
926         /* Free CCB or send back to devq. */
927         targfreeccb(softc, ccb);
928
929         return (error);
930 }
931
932 static union ccb *
933 targgetccb(struct targ_softc *softc, xpt_opcode type, int priority)
934 {
935         union ccb *ccb;
936         int ccb_len;
937
938         ccb_len = targccblen(type);
939         ccb = malloc(ccb_len, M_TARG, M_NOWAIT);
940         CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("getccb %p\n", ccb));
941         if (ccb == NULL) {
942                 return (ccb);
943         }
944         xpt_setup_ccb(&ccb->ccb_h, softc->path, priority);
945         ccb->ccb_h.func_code = type;
946         ccb->ccb_h.cbfcnp = targdone;
947         ccb->ccb_h.targ_descr = targgetdescr(softc);
948         if (ccb->ccb_h.targ_descr == NULL) {
949                 free (ccb, M_TARG);
950                 ccb = NULL;
951         }
952         return (ccb);
953 }
954
955 static void
956 targfreeccb(struct targ_softc *softc, union ccb *ccb)
957 {
958         CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH, ("targfreeccb descr %p and\n",
959                         ccb->ccb_h.targ_descr));
960         free(ccb->ccb_h.targ_descr, M_TARG);
961
962         switch (ccb->ccb_h.func_code) {
963         case XPT_ACCEPT_TARGET_IO:
964         case XPT_IMMED_NOTIFY:
965         case XPT_IMMEDIATE_NOTIFY:
966                 CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH, ("freeing ccb %p\n", ccb));
967                 free(ccb, M_TARG);
968                 break;
969         default:
970                 /* Send back CCB if we got it from the periph */
971                 if (XPT_FC_IS_QUEUED(ccb)) {
972                         CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH,
973                                         ("returning queued ccb %p\n", ccb));
974                         xpt_release_ccb(ccb);
975                 } else {
976                         CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH,
977                                         ("freeing ccb %p\n", ccb));
978                         free(ccb, M_TARG);
979                 }
980                 break;
981         }
982 }
983
984 static struct targ_cmd_descr *
985 targgetdescr(struct targ_softc *softc)
986 {
987         struct targ_cmd_descr *descr;
988
989         descr = malloc(sizeof(*descr), M_TARG,
990                M_NOWAIT);
991         if (descr) {
992                 descr->mapinfo.num_bufs_used = 0;
993         }
994         return (descr);
995 }
996
997 static void
998 targinit(void)
999 {
1000         struct cdev *dev;
1001
1002         /* Add symbolic link to targ0 for compatibility. */
1003         dev = make_dev(&targ_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "targ");
1004         make_dev_alias(dev, "targ0");
1005 }
1006
1007 static void
1008 targasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
1009 {
1010         /* All events are handled in usermode by INOTs */
1011         panic("targasync() called, should be an INOT instead");
1012 }
1013
1014 /* Cancel all pending requests and CCBs awaiting work. */
1015 static void
1016 abort_all_pending(struct targ_softc *softc)
1017 {
1018         struct targ_cmd_descr   *descr;
1019         struct ccb_abort         cab;
1020         struct ccb_hdr          *ccb_h;
1021
1022         CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("abort_all_pending\n"));
1023
1024         /* First abort the descriptors awaiting resources */
1025         while ((descr = TAILQ_FIRST(&softc->work_queue)) != NULL) {
1026                 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
1027                           ("Aborting descr from workq %p\n", descr));
1028                 TAILQ_REMOVE(&softc->work_queue, descr, tqe);
1029                 TAILQ_INSERT_TAIL(&softc->abort_queue, descr, tqe);
1030         }
1031
1032         /* 
1033          * Then abort all pending CCBs.
1034          * targdone() will return the aborted CCB via user_ccb_queue
1035          */
1036         xpt_setup_ccb(&cab.ccb_h, softc->path, CAM_PRIORITY_NORMAL);
1037         cab.ccb_h.func_code = XPT_ABORT;
1038         cab.ccb_h.status = CAM_REQ_CMP_ERR;
1039         TAILQ_FOREACH(ccb_h, &softc->pending_ccb_queue, periph_links.tqe) {
1040                 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
1041                           ("Aborting pending CCB %p\n", ccb_h));
1042                 cab.abort_ccb = (union ccb *)ccb_h;
1043                 xpt_action((union ccb *)&cab);
1044                 if (cab.ccb_h.status != CAM_REQ_CMP) {
1045                         xpt_print(cab.ccb_h.path,
1046                             "Unable to abort CCB, status %#x\n",
1047                             cab.ccb_h.status);
1048                 }
1049         }
1050
1051         /* If we aborted at least one pending CCB ok, wait for it. */
1052         if (cab.ccb_h.status == CAM_REQ_CMP) {
1053                 cam_periph_sleep(softc->periph, &softc->pending_ccb_queue,
1054                        PRIBIO | PCATCH, "tgabrt", 0);
1055         }
1056
1057         /* If we aborted anything from the work queue, wakeup user. */
1058         if (!TAILQ_EMPTY(&softc->user_ccb_queue)
1059          || !TAILQ_EMPTY(&softc->abort_queue)) {
1060                 cam_periph_unlock(softc->periph);
1061                 notify_user(softc);
1062                 cam_periph_lock(softc->periph);
1063         }
1064 }
1065
1066 /* Notify the user that data is ready */
1067 static void
1068 notify_user(struct targ_softc *softc)
1069 {
1070         /*
1071          * Notify users sleeping via poll(), kqueue(), and
1072          * blocking read().
1073          */
1074         selwakeuppri(&softc->read_select, PRIBIO);
1075         KNOTE_UNLOCKED(&softc->read_select.si_note, 0);
1076         wakeup(&softc->user_ccb_queue);
1077 }
1078
1079 /* Convert CAM status to errno values */
1080 static int
1081 targcamstatus(cam_status status)
1082 {
1083         switch (status & CAM_STATUS_MASK) {
1084         case CAM_REQ_CMP:       /* CCB request completed without error */
1085                 return (0);
1086         case CAM_REQ_INPROG:    /* CCB request is in progress */
1087                 return (EINPROGRESS);
1088         case CAM_REQ_CMP_ERR:   /* CCB request completed with an error */
1089                 return (EIO);
1090         case CAM_PROVIDE_FAIL:  /* Unable to provide requested capability */
1091                 return (ENOTTY);
1092         case CAM_FUNC_NOTAVAIL: /* The requested function is not available */
1093                 return (ENOTSUP);
1094         case CAM_LUN_ALRDY_ENA: /* LUN is already enabled for target mode */
1095                 return (EADDRINUSE);
1096         case CAM_PATH_INVALID:  /* Supplied Path ID is invalid */
1097         case CAM_DEV_NOT_THERE: /* SCSI Device Not Installed/there */
1098                 return (ENOENT);
1099         case CAM_REQ_ABORTED:   /* CCB request aborted by the host */
1100                 return (ECANCELED);
1101         case CAM_CMD_TIMEOUT:   /* Command timeout */
1102                 return (ETIMEDOUT);
1103         case CAM_REQUEUE_REQ:   /* Requeue to preserve transaction ordering */
1104                 return (EAGAIN);
1105         case CAM_REQ_INVALID:   /* CCB request was invalid */
1106                 return (EINVAL);
1107         case CAM_RESRC_UNAVAIL: /* Resource Unavailable */
1108                 return (ENOMEM);
1109         case CAM_BUSY:          /* CAM subsystem is busy */
1110         case CAM_UA_ABORT:      /* Unable to abort CCB request */
1111                 return (EBUSY);
1112         default:
1113                 return (ENXIO);
1114         }
1115 }
1116
1117 static size_t
1118 targccblen(xpt_opcode func_code)
1119 {
1120         int len;
1121
1122         /* Codes we expect to see as a target */
1123         switch (func_code) {
1124         case XPT_CONT_TARGET_IO:
1125         case XPT_SCSI_IO:
1126                 len = sizeof(struct ccb_scsiio);
1127                 break;
1128         case XPT_ACCEPT_TARGET_IO:
1129                 len = sizeof(struct ccb_accept_tio);
1130                 break;
1131         case XPT_IMMED_NOTIFY:
1132                 len = sizeof(struct ccb_immed_notify);
1133                 break;
1134         case XPT_IMMEDIATE_NOTIFY:
1135                 len = sizeof(struct ccb_immediate_notify);
1136                 break;
1137         case XPT_REL_SIMQ:
1138                 len = sizeof(struct ccb_relsim);
1139                 break;
1140         case XPT_PATH_INQ:
1141                 len = sizeof(struct ccb_pathinq);
1142                 break;
1143         case XPT_DEBUG:
1144                 len = sizeof(struct ccb_debug);
1145                 break;
1146         case XPT_ABORT:
1147                 len = sizeof(struct ccb_abort);
1148                 break;
1149         case XPT_EN_LUN:
1150                 len = sizeof(struct ccb_en_lun);
1151                 break;
1152         default:
1153                 len = sizeof(union ccb);
1154                 break;
1155         }
1156
1157         return (len);
1158 }