]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - sys/cam/scsi/scsi_target.c
- Copy stable/10@296371 to releng/10.3 in preparation for 10.3-RC1
[FreeBSD/releng/10.3.git] / sys / cam / scsi / scsi_target.c
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$");
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 */
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_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL);
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;        /* traditional default */
409         else if (cpi.maxio > MAXPHYS)
410                 softc->maxio = MAXPHYS;         /* 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) {
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;
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, 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) {
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
453 enable_fail:
454         return (status);
455 }
456
457 /* Disable this softc's target instance if enabled */
458 static cam_status
459 targdisable(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"));
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) */
483 static cam_status
484 targctor(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
496 static void
497 targdtor(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)) != NULL) {
511                 TAILQ_REMOVE(&softc->user_ccb_queue, ccb_h, periph_links.tqe);
512                 targfreeccb(softc, (union ccb *)ccb_h);
513         }
514         while ((descr = TAILQ_FIRST(&softc->abort_queue)) != NULL) {
515                 TAILQ_REMOVE(&softc->abort_queue, descr, tqe);
516                 free(descr, M_TARG);
517         }
518
519         softc->periph = NULL;
520         softc->path = NULL;
521         periph->softc = NULL;
522 }
523
524 /* Receive CCBs from user mode proc and send them to the HBA */
525 static int
526 targwrite(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,
537                   ("write - uio_resid %zd\n", uio->uio_resid));
538         while (uio->uio_resid >= sizeof(user_ccb) && error == 0) {
539                 union ccb *ccb;
540
541                 error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
542                 if (error != 0) {
543                         CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
544                                   ("write - uiomove failed (%d)\n", error));
545                         break;
546                 }
547                 priority = fuword32(&user_ccb->ccb_h.pinfo.priority);
548                 if (priority == CAM_PRIORITY_NONE) {
549                         error = EINVAL;
550                         break;
551                 }
552                 func_code = fuword32(&user_ccb->ccb_h.func_code);
553                 switch (func_code) {
554                 case XPT_ACCEPT_TARGET_IO:
555                 case XPT_IMMED_NOTIFY:
556                 case XPT_IMMEDIATE_NOTIFY:
557                         cam_periph_lock(softc->periph);
558                         ccb = targgetccb(softc, func_code, priority);
559                         descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descr;
560                         descr->user_ccb = user_ccb;
561                         descr->func_code = func_code;
562                         CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
563                                   ("Sent ATIO/INOT (%p)\n", user_ccb));
564                         xpt_action(ccb);
565                         TAILQ_INSERT_TAIL(&softc->pending_ccb_queue,
566                                           &ccb->ccb_h,
567                                           periph_links.tqe);
568                         cam_periph_unlock(softc->periph);
569                         break;
570                 default:
571                         cam_periph_lock(softc->periph);
572                         if ((func_code & XPT_FC_QUEUED) != 0) {
573                                 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
574                                           ("Sending queued ccb %#x (%p)\n",
575                                           func_code, user_ccb));
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,
581                                                   descr, tqe);
582                                 xpt_schedule(softc->periph, priority);
583                         } else {
584                                 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
585                                           ("Sending inline ccb %#x (%p)\n",
586                                           func_code, user_ccb));
587                                 ccb = targgetccb(softc, func_code, priority);
588                                 descr = (struct targ_cmd_descr *)
589                                          ccb->ccb_h.targ_descr;
590                                 descr->user_ccb = user_ccb;
591                                 descr->priority = priority;
592                                 descr->func_code = func_code;
593                                 if (targusermerge(softc, descr, ccb) != EFAULT)
594                                         targsendccb(softc, ccb, descr);
595                                 targreturnccb(softc, ccb);
596                         }
597                         cam_periph_unlock(softc->periph);
598                         break;
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 (ENOSPC);
613         return (0);
614 }
615
616 /* Process requests (descrs) via the periph-supplied CCBs */
617 static void
618 targstart(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));
626
627         descr = TAILQ_FIRST(&softc->work_queue);
628         if (descr == NULL) {
629                 xpt_release_ccb(start_ccb);
630         } else {
631                 TAILQ_REMOVE(&softc->work_queue, descr, tqe);
632                 next_descr = TAILQ_FIRST(&softc->work_queue);
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);
645                         notify_user(softc);
646                 }
647
648                 /* If we have more work to do, stay scheduled */
649                 if (next_descr != NULL)
650                         xpt_schedule(periph, next_descr->priority);
651         }
652 }
653
654 static int
655 targusermerge(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,
688                     periph_links.tqe) {
689                         struct targ_cmd_descr *ab_descr;
690
691                         ab_descr = (struct targ_cmd_descr *)ccb_h->targ_descr;
692                         if (ab_descr->user_ccb == cab->abort_ccb) {
693                                 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
694                                           ("Changing abort for %p to %p\n",
695                                           cab->abort_ccb, ccb_h));
696                                 cab->abort_ccb = (union ccb *)ccb_h;
697                                 break;
698                         }
699                 }
700                 /* CCB not found, set appropriate status */
701                 if (ccb_h == NULL) {
702                         k_ccbh->status = CAM_PATH_INVALID;
703                         error = ESRCH;
704                 }
705         }
706
707         return (error);
708 }
709
710 /* Build and send a kernel CCB formed from descr->user_ccb */
711 static int
712 targsendccb(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_descr = 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));
753         if (XPT_FC_IS_QUEUED(ccb)) {
754                 TAILQ_INSERT_TAIL(&softc->pending_ccb_queue, ccb_h,
755                                   periph_links.tqe);
756         }
757         xpt_action(ccb);
758
759         return (0);
760 }
761
762 /* Completion routine for CCBs (called at splsoftcam) */
763 static void
764 targdone(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));
770         softc = (struct targ_softc *)periph->softc;
771         TAILQ_REMOVE(&softc->pending_ccb_queue, &done_ccb->ccb_h,
772                      periph_links.tqe);
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))
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,
791                                   periph_links.tqe);
792                 cam_periph_unlock(softc->periph);
793                 notify_user(softc);
794                 cam_periph_lock(softc->periph);
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 */
804 static int
805 targread(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"));
821
822         /* If no data is available, wait or return immediately */
823         cam_periph_lock(softc->periph);
824         ccb_h = TAILQ_FIRST(user_queue);
825         user_descr = TAILQ_FIRST(abort_queue);
826         while (ccb_h == NULL && user_descr == NULL) {
827                 if ((ioflag & IO_NDELAY) == 0) {
828                         error = cam_periph_sleep(softc->periph, user_queue,
829                             PRIBIO | PCATCH, "targrd", 0);
830                         ccb_h = TAILQ_FIRST(user_queue);
831                         user_descr = TAILQ_FIRST(abort_queue);
832                         if (error != 0) {
833                                 if (error == ERESTART) {
834                                         continue;
835                                 } else {
836                                         goto read_fail;
837                                 }
838                         }
839                 } else {
840                         cam_periph_unlock(softc->periph);
841                         return (EAGAIN);
842                 }
843         }
844
845         /* Data is available so fill the user's buffer */
846         while (ccb_h != NULL) {
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);
852                 descr = (struct targ_cmd_descr *)ccb_h->targ_descr;
853                 user_ccb = descr->user_ccb;
854                 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
855                           ("targread ccb %p (%p)\n", ccb_h, user_ccb));
856                 error = targreturnccb(softc, (union ccb *)ccb_h);
857                 if (error != 0)
858                         goto read_fail;
859                 cam_periph_unlock(softc->periph);
860                 error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
861                 cam_periph_lock(softc->periph);
862                 if (error != 0)
863                         goto read_fail;
864                 read_len += sizeof(user_ccb);
865
866                 ccb_h = TAILQ_FIRST(user_queue);
867         }
868
869         /* Flush out any aborted descriptors */
870         while (user_descr != NULL) {
871                 if (uio->uio_resid < sizeof(user_ccb))
872                         break;
873                 TAILQ_REMOVE(abort_queue, user_descr, tqe);
874                 user_ccb = user_descr->user_ccb;
875                 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
876                           ("targread aborted descr %p (%p)\n",
877                           user_descr, user_ccb));
878                 suword(&user_ccb->ccb_h.status, CAM_REQ_ABORTED);
879                 cam_periph_unlock(softc->periph);
880                 error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
881                 cam_periph_lock(softc->periph);
882                 if (error != 0)
883                         goto read_fail;
884                 read_len += sizeof(user_ccb);
885
886                 user_descr = TAILQ_FIRST(abort_queue);
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 = ENOSPC;
896
897 read_fail:
898         cam_periph_unlock(softc->periph);
899         return (error);
900 }
901
902 /* Copy completed ccb back to the user */
903 static int
904 targreturnccb(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));
912         descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descr;
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) -
918                 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)
923                 cam_periph_unmapmem(ccb, &descr->mapinfo);
924         error = copyout(&ccb->ccb_h + 1, u_ccbh + 1, ccb_len);
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
935 static union ccb *
936 targgetccb(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_NOWAIT);
943         CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("getccb %p\n", ccb));
944         if (ccb == NULL) {
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_descr = targgetdescr(softc);
951         if (ccb->ccb_h.targ_descr == NULL) {
952                 free (ccb, M_TARG);
953                 ccb = NULL;
954         }
955         return (ccb);
956 }
957
958 static void
959 targfreeccb(struct targ_softc *softc, union ccb *ccb)
960 {
961         CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH, ("targfreeccb descr %p and\n",
962                         ccb->ccb_h.targ_descr));
963         free(ccb->ccb_h.targ_descr, 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));
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)) {
975                         CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH,
976                                         ("returning queued ccb %p\n", ccb));
977                         xpt_release_ccb(ccb);
978                 } else {
979                         CAM_DEBUG_PRINT(CAM_DEBUG_PERIPH,
980                                         ("freeing ccb %p\n", ccb));
981                         free(ccb, M_TARG);
982                 }
983                 break;
984         }
985 }
986
987 static struct targ_cmd_descr *
988 targgetdescr(struct targ_softc *softc)
989 {
990         struct targ_cmd_descr *descr;
991
992         descr = malloc(sizeof(*descr), M_TARG,
993                M_NOWAIT);
994         if (descr) {
995                 descr->mapinfo.num_bufs_used = 0;
996         }
997         return (descr);
998 }
999
1000 static void
1001 targinit(void)
1002 {
1003         struct cdev *dev;
1004
1005         /* Add symbolic link to targ0 for compatibility. */
1006         dev = make_dev(&targ_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "targ");
1007         make_dev_alias(dev, "targ0");
1008 }
1009
1010 static void
1011 targasync(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. */
1018 static void
1019 abort_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"));
1026
1027         /* First abort the descriptors awaiting resources */
1028         while ((descr = TAILQ_FIRST(&softc->work_queue)) != NULL) {
1029                 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
1030                           ("Aborting descr from workq %p\n", descr));
1031                 TAILQ_REMOVE(&softc->work_queue, descr, tqe);
1032                 TAILQ_INSERT_TAIL(&softc->abort_queue, descr, tqe);
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);
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) {
1043                 CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
1044                           ("Aborting pending CCB %p\n", ccb_h));
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,
1057                        PRIBIO | PCATCH, "tgabrt", 0);
1058         }
1059
1060         /* If we aborted anything from the work queue, wakeup user. */
1061         if (!TAILQ_EMPTY(&softc->user_ccb_queue)
1062          || !TAILQ_EMPTY(&softc->abort_queue)) {
1063                 cam_periph_unlock(softc->periph);
1064                 notify_user(softc);
1065                 cam_periph_lock(softc->periph);
1066         }
1067 }
1068
1069 /* Notify the user that data is ready */
1070 static void
1071 notify_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);
1078         KNOTE_UNLOCKED(&softc->read_select.si_note, 0);
1079         wakeup(&softc->user_ccb_queue);
1080 }
1081
1082 /* Convert CAM status to errno values */
1083 static int
1084 targcamstatus(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 (EINPROGRESS);
1091         case CAM_REQ_CMP_ERR:   /* CCB request completed with an error */
1092                 return (EIO);
1093         case CAM_PROVIDE_FAIL:  /* Unable to provide requested capability */
1094                 return (ENOTTY);
1095         case CAM_FUNC_NOTAVAIL: /* The requested function is not available */
1096                 return (ENOTSUP);
1097         case CAM_LUN_ALRDY_ENA: /* LUN is already enabled for target mode */
1098                 return (EADDRINUSE);
1099         case CAM_PATH_INVALID:  /* Supplied Path ID is invalid */
1100         case CAM_DEV_NOT_THERE: /* SCSI Device Not Installed/there */
1101                 return (ENOENT);
1102         case CAM_REQ_ABORTED:   /* CCB request aborted by the host */
1103                 return (ECANCELED);
1104         case CAM_CMD_TIMEOUT:   /* Command timeout */
1105                 return (ETIMEDOUT);
1106         case CAM_REQUEUE_REQ:   /* Requeue to preserve transaction ordering */
1107                 return (EAGAIN);
1108         case CAM_REQ_INVALID:   /* CCB request was invalid */
1109                 return (EINVAL);
1110         case CAM_RESRC_UNAVAIL: /* Resource Unavailable */
1111                 return (ENOMEM);
1112         case CAM_BUSY:          /* CAM subsystem is busy */
1113         case CAM_UA_ABORT:      /* Unable to abort CCB request */
1114                 return (EBUSY);
1115         default:
1116                 return (ENXIO);
1117         }
1118 }
1119
1120 static size_t
1121 targccblen(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 }