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