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