]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - share/examples/scsi_target/scsi_target.c
Implement pci_enable_msi() and pci_disable_msi() in the LinuxKPI.
[FreeBSD/FreeBSD.git] / share / examples / scsi_target / scsi_target.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * SCSI Disk Emulator
5  *
6  * Copyright (c) 2002 Nate Lawson.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions, and the following disclaimer,
14  *    without modification, immediately at the beginning of the file.
15  * 2. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
22  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32
33 #include <sys/types.h>
34 #include <ctype.h>
35 #include <errno.h>
36 #include <err.h>
37 #include <fcntl.h>
38 #include <signal.h>
39 #include <stddef.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sysexits.h>
44 #include <unistd.h>
45 #include <aio.h>
46 #include <assert.h>
47 #include <sys/stat.h>
48 #include <sys/queue.h>
49 #include <sys/event.h>
50 #include <sys/param.h>
51 #include <sys/disk.h>
52 #include <cam/cam_queue.h>
53 #include <cam/scsi/scsi_all.h>
54 #include <cam/scsi/scsi_targetio.h>
55 #include <cam/scsi/scsi_message.h>
56 #include "scsi_target.h"
57
58 /* Maximum amount to transfer per CTIO */
59 #define MAX_XFER        MAXPHYS
60 /* Maximum number of allocated CTIOs */
61 #define MAX_CTIOS       64
62 /* Maximum sector size for emulated volume */
63 #define MAX_SECTOR      32768
64
65 /* Global variables */
66 int             debug;
67 int             notaio = 0;
68 off_t           volume_size;
69 u_int           sector_size;
70 size_t          buf_size;
71
72 /* Local variables */
73 static int    targ_fd;
74 static int    kq_fd;
75 static int    file_fd;
76 static int    num_ctios;
77 static struct ccb_queue         pending_queue;
78 static struct ccb_queue         work_queue;
79 static struct ioc_enable_lun    ioc_enlun = {
80         CAM_BUS_WILDCARD,
81         CAM_TARGET_WILDCARD,
82         CAM_LUN_WILDCARD
83 };
84
85 /* Local functions */
86 static void             cleanup(void);
87 static int              init_ccbs(void);
88 static void             request_loop(void);
89 static void             handle_read(void);
90 /* static int           work_atio(struct ccb_accept_tio *); */
91 static void             queue_io(struct ccb_scsiio *);
92 static int              run_queue(struct ccb_accept_tio *);
93 static int              work_inot(struct ccb_immediate_notify *);
94 static struct ccb_scsiio *
95                         get_ctio(void);
96 /* static void          free_ccb(union ccb *); */
97 static cam_status       get_sim_flags(u_int16_t *);
98 static void             rel_simq(void);
99 static void             abort_all_pending(void);
100 static void             usage(void);
101
102 int
103 main(int argc, char *argv[])
104 {
105         int ch;
106         char *file_name;
107         u_int16_t req_flags, sim_flags;
108         off_t user_size;
109
110         /* Initialize */
111         debug = 0;
112         req_flags = sim_flags = 0;
113         user_size = 0;
114         targ_fd = file_fd = kq_fd = -1;
115         num_ctios = 0;
116         sector_size = SECTOR_SIZE;
117         buf_size = DFLTPHYS;
118
119         /* Prepare resource pools */
120         TAILQ_INIT(&pending_queue);
121         TAILQ_INIT(&work_queue);
122
123         while ((ch = getopt(argc, argv, "AdSTYb:c:s:W:")) != -1) {
124                 switch(ch) {
125                 case 'A':
126                         req_flags |= SID_Addr16;
127                         break;
128                 case 'd':
129                         debug = 1;
130                         break;
131                 case 'S':
132                         req_flags |= SID_Sync;
133                         break;
134                 case 'T':
135                         req_flags |= SID_CmdQue;
136                         break;
137                 case 'b':
138                         buf_size = atoi(optarg);
139                         if (buf_size < 256 || buf_size > MAX_XFER)
140                                 errx(1, "Unreasonable buf size: %s", optarg);
141                         break;
142                 case 'c':
143                         sector_size = atoi(optarg);
144                         if (sector_size < 512 || sector_size > MAX_SECTOR)
145                                 errx(1, "Unreasonable sector size: %s", optarg);
146                         break;
147                 case 's':
148                 {
149                         int last, shift = 0;
150
151                         last = strlen(optarg) - 1;
152                         if (last > 0) {
153                                 switch (tolower(optarg[last])) {
154                                 case 'e':
155                                         shift += 10;
156                                         /* FALLTHROUGH */
157                                 case 'p':
158                                         shift += 10;
159                                         /* FALLTHROUGH */
160                                 case 't':
161                                         shift += 10;
162                                         /* FALLTHROUGH */
163                                 case 'g':
164                                         shift += 10;
165                                         /* FALLTHROUGH */
166                                 case 'm':
167                                         shift += 10;
168                                         /* FALLTHROUGH */
169                                 case 'k':
170                                         shift += 10;
171                                         optarg[last] = 0;
172                                         break;
173                                 }
174                         }
175                         user_size = strtoll(optarg, (char **)NULL, /*base*/10);
176                         user_size <<= shift;
177                         if (user_size < 0)
178                                 errx(1, "Unreasonable volume size: %s", optarg);
179                         break;
180                 }
181                 case 'W':
182                         req_flags &= ~(SID_WBus16 | SID_WBus32);
183                         switch (atoi(optarg)) {
184                         case 8:
185                                 /* Leave req_flags zeroed */
186                                 break;
187                         case 16:
188                                 req_flags |= SID_WBus16;
189                                 break;
190                         case 32:
191                                 req_flags |= SID_WBus32;
192                                 break;
193                         default:
194                                 warnx("Width %s not supported", optarg);
195                                 usage();
196                                 /* NOTREACHED */
197                         }
198                         break;
199                 case 'Y':
200                         notaio = 1;
201                         break;
202                 default:
203                         usage();
204                         /* NOTREACHED */
205                 }
206         }
207         argc -= optind;
208         argv += optind;
209         
210         if (argc != 2)
211                 usage();
212
213         sscanf(argv[0], "%u:%u:%u", &ioc_enlun.path_id, &ioc_enlun.target_id,
214                &ioc_enlun.lun_id);
215         file_name = argv[1];
216
217         if (ioc_enlun.path_id == CAM_BUS_WILDCARD ||
218             ioc_enlun.target_id == CAM_TARGET_WILDCARD ||
219             ioc_enlun.lun_id == CAM_LUN_WILDCARD) {
220                 warnx("Incomplete target path specified");
221                 usage();
222                 /* NOTREACHED */
223         }
224         /* We don't support any vendor-specific commands */
225         ioc_enlun.grp6_len = 0;
226         ioc_enlun.grp7_len = 0;
227
228         /* Open backing store for IO */
229         file_fd = open(file_name, O_RDWR);
230         if (file_fd < 0)
231                 errx(EX_NOINPUT, "open backing store file");
232
233         /* Check backing store size or use the size user gave us */
234         if (user_size == 0) {
235                 struct stat st;
236
237                 if (fstat(file_fd, &st) < 0)
238                         err(1, "fstat file");
239 #if __FreeBSD_version >= 500000
240                 if ((st.st_mode & S_IFCHR) != 0) {
241                         /* raw device */
242                         off_t mediasize;
243                         if (ioctl(file_fd, DIOCGMEDIASIZE, &mediasize) < 0)
244                                 err(1, "DIOCGMEDIASIZE"); 
245
246                         /* XXX get sector size by ioctl()?? */
247                         volume_size = mediasize / sector_size;
248                 } else
249 #endif
250                         volume_size = st.st_size / sector_size;
251         } else {
252                 volume_size = user_size / sector_size;
253         }
254         if (debug)
255                 warnx("volume_size: %d bytes x " OFF_FMT " sectors",
256                     sector_size, volume_size);
257
258         if (volume_size <= 0)
259                 errx(1, "volume must be larger than %d", sector_size);
260
261         if (notaio == 0) {
262                 struct aiocb aio, *aiop;
263                 
264                 /* See if we have we have working AIO support */
265                 memset(&aio, 0, sizeof(aio));
266                 aio.aio_buf = malloc(sector_size);
267                 if (aio.aio_buf == NULL)
268                         err(1, "malloc");
269                 aio.aio_fildes = file_fd;
270                 aio.aio_offset = 0;
271                 aio.aio_nbytes = sector_size;
272                 signal(SIGSYS, SIG_IGN);
273                 if (aio_read(&aio) != 0) {
274                         printf("AIO support is not available- switchin to"
275                                " single-threaded mode.\n");
276                         notaio = 1;
277                 } else {
278                         if (aio_waitcomplete(&aiop, NULL) != sector_size)
279                                 err(1, "aio_waitcomplete");
280                         assert(aiop == &aio);
281                         signal(SIGSYS, SIG_DFL);
282                 }
283                 free((void *)aio.aio_buf);
284                 if (debug && notaio == 0)
285                         warnx("aio support tested ok");
286         }
287
288         targ_fd = open("/dev/targ", O_RDWR);
289         if (targ_fd < 0)
290             err(1, "/dev/targ");
291         else
292             warnx("opened /dev/targ");
293
294         /* The first three are handled by kevent() later */
295         signal(SIGHUP, SIG_IGN);
296         signal(SIGINT, SIG_IGN);
297         signal(SIGTERM, SIG_IGN);
298         signal(SIGPROF, SIG_IGN);
299         signal(SIGALRM, SIG_IGN);
300         signal(SIGSTOP, SIG_IGN);
301         signal(SIGTSTP, SIG_IGN);
302
303         /* Register a cleanup handler to run when exiting */
304         atexit(cleanup);
305
306         /* Enable listening on the specified LUN */
307         if (ioctl(targ_fd, TARGIOCENABLE, &ioc_enlun) != 0)
308                 err(1, "TARGIOCENABLE");
309
310         /* Enable debugging if requested */
311         if (debug) {
312                 if (ioctl(targ_fd, TARGIOCDEBUG, &debug) != 0)
313                         warnx("TARGIOCDEBUG");
314         }
315
316         /* Set up inquiry data according to what SIM supports */
317         if (get_sim_flags(&sim_flags) != CAM_REQ_CMP)
318                 errx(1, "get_sim_flags");
319
320         if (tcmd_init(req_flags, sim_flags) != 0)
321                 errx(1, "Initializing tcmd subsystem failed");
322
323         /* Queue ATIOs and INOTs on descriptor */
324         if (init_ccbs() != 0)
325                 errx(1, "init_ccbs failed");
326
327         if (debug)
328                 warnx("main loop beginning");
329
330         request_loop();
331
332         exit(0);
333 }
334
335 static void
336 cleanup()
337 {
338         struct ccb_hdr *ccb_h;
339
340         if (debug) {
341                 warnx("cleanup called");
342                 debug = 0;
343                 ioctl(targ_fd, TARGIOCDEBUG, &debug);
344         }
345         ioctl(targ_fd, TARGIOCDISABLE, NULL);
346         close(targ_fd);
347
348         while ((ccb_h = TAILQ_FIRST(&pending_queue)) != NULL) {
349                 TAILQ_REMOVE(&pending_queue, ccb_h, periph_links.tqe);
350                 free_ccb((union ccb *)ccb_h);
351         }
352         while ((ccb_h = TAILQ_FIRST(&work_queue)) != NULL) {
353                 TAILQ_REMOVE(&work_queue, ccb_h, periph_links.tqe);
354                 free_ccb((union ccb *)ccb_h);
355         }
356
357         if (kq_fd != -1)
358                 close(kq_fd);
359 }
360
361 /* Allocate ATIOs/INOTs and queue on HBA */
362 static int
363 init_ccbs()
364 {
365         int i;
366
367         for (i = 0; i < MAX_INITIATORS; i++) {
368                 struct ccb_accept_tio *atio;
369                 struct atio_descr *a_descr;
370                 struct ccb_immediate_notify *inot;
371
372                 atio = (struct ccb_accept_tio *)malloc(sizeof(*atio));
373                 if (atio == NULL) {
374                         warn("malloc ATIO");
375                         return (-1);
376                 }
377                 a_descr = (struct atio_descr *)malloc(sizeof(*a_descr));
378                 if (a_descr == NULL) {
379                         free(atio);
380                         warn("malloc atio_descr");
381                         return (-1);
382                 }
383                 atio->ccb_h.func_code = XPT_ACCEPT_TARGET_IO;
384                 atio->ccb_h.targ_descr = a_descr;
385                 send_ccb((union ccb *)atio, /*priority*/1);
386
387                 inot = (struct ccb_immediate_notify *)malloc(sizeof(*inot));
388                 if (inot == NULL) {
389                         warn("malloc INOT");
390                         return (-1);
391                 }
392                 inot->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
393                 send_ccb((union ccb *)inot, /*priority*/1);
394         }
395
396         return (0);
397 }
398
399 static void
400 request_loop()
401 {
402         struct kevent events[MAX_EVENTS];
403         struct timespec ts, *tptr;
404         int quit;
405
406         /* Register kqueue for event notification */
407         if ((kq_fd = kqueue()) < 0)
408                 err(1, "init kqueue");
409
410         /* Set up some default events */
411         EV_SET(&events[0], SIGHUP, EVFILT_SIGNAL, EV_ADD|EV_ENABLE, 0, 0, 0);
412         EV_SET(&events[1], SIGINT, EVFILT_SIGNAL, EV_ADD|EV_ENABLE, 0, 0, 0);
413         EV_SET(&events[2], SIGTERM, EVFILT_SIGNAL, EV_ADD|EV_ENABLE, 0, 0, 0);
414         EV_SET(&events[3], targ_fd, EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, 0);
415         if (kevent(kq_fd, events, 4, NULL, 0, NULL) < 0)
416                 err(1, "kevent signal registration");
417
418         ts.tv_sec = 0;
419         ts.tv_nsec = 0;
420         tptr = NULL;
421         quit = 0;
422
423         /* Loop until user signal */
424         while (quit == 0) {
425                 int retval, i, oo;
426                 struct ccb_hdr *ccb_h;
427
428                 /* Check for the next signal, read ready, or AIO completion */
429                 retval = kevent(kq_fd, NULL, 0, events, MAX_EVENTS, tptr);
430                 if (retval < 0) {
431                         if (errno == EINTR) {
432                                 if (debug)
433                                         warnx("EINTR, looping");
434                                 continue;
435                         }
436                         else {
437                                 err(1, "kevent failed");
438                         }
439                 } else if (retval > MAX_EVENTS) {
440                         errx(1, "kevent returned more events than allocated?");
441                 }
442
443                 /* Process all received events. */
444                 for (oo = i = 0; i < retval; i++) {
445                         if ((events[i].flags & EV_ERROR) != 0)
446                                 errx(1, "kevent registration failed");
447
448                         switch (events[i].filter) {
449                         case EVFILT_READ:
450                                 if (debug)
451                                         warnx("read ready");
452                                 handle_read();
453                                 break;
454                         case EVFILT_AIO:
455                         {
456                                 struct ccb_scsiio *ctio;
457                                 struct ctio_descr *c_descr;
458                                 if (debug)
459                                         warnx("aio ready");
460
461                                 ctio = (struct ccb_scsiio *)events[i].udata;
462                                 c_descr = (struct ctio_descr *)
463                                           ctio->ccb_h.targ_descr;
464                                 c_descr->event = AIO_DONE;
465                                 /* Queue on the appropriate ATIO */
466                                 queue_io(ctio);
467                                 /* Process any queued completions. */
468                                 oo += run_queue(c_descr->atio);
469                                 break;
470                         }
471                         case EVFILT_SIGNAL:
472                                 if (debug)
473                                         warnx("signal ready, setting quit");
474                                 quit = 1;
475                                 break;
476                         default:
477                                 warnx("unknown event %d", events[i].filter);
478                                 break;
479                         }
480
481                         if (debug)
482                                 warnx("event %d done", events[i].filter);
483                 }
484
485                 if (oo) {
486                         tptr = &ts;
487                         continue;
488                 }
489
490                 /* Grab the first CCB and perform one work unit. */
491                 if ((ccb_h = TAILQ_FIRST(&work_queue)) != NULL) {
492                         union ccb *ccb;
493
494                         ccb = (union ccb *)ccb_h;
495                         switch (ccb_h->func_code) {
496                         case XPT_ACCEPT_TARGET_IO:
497                                 /* Start one more transfer. */
498                                 retval = work_atio(&ccb->atio);
499                                 break;
500                         case XPT_IMMEDIATE_NOTIFY:
501                                 retval = work_inot(&ccb->cin1);
502                                 break;
503                         default:
504                                 warnx("Unhandled ccb type %#x on workq",
505                                       ccb_h->func_code);
506                                 abort();
507                                 /* NOTREACHED */
508                         }
509
510                         /* Assume work function handled the exception */
511                         if ((ccb_h->status & CAM_DEV_QFRZN) != 0) {
512                                 if (debug) {
513                                         warnx("Queue frozen receiving CCB, "
514                                               "releasing");
515                                 }
516                                 rel_simq();
517                         }
518
519                         /* No more work needed for this command. */
520                         if (retval == 0) {
521                                 TAILQ_REMOVE(&work_queue, ccb_h,
522                                              periph_links.tqe);
523                         }
524                 }
525
526                 /*
527                  * Poll for new events (i.e. completions) while we
528                  * are processing CCBs on the work_queue. Once it's
529                  * empty, use an infinite wait.
530                  */
531                 if (!TAILQ_EMPTY(&work_queue))
532                         tptr = &ts;
533                 else
534                         tptr = NULL;
535         }
536 }
537
538 /* CCBs are ready from the kernel */
539 static void
540 handle_read()
541 {
542         union ccb *ccb_array[MAX_INITIATORS], *ccb;
543         int ccb_count, i, oo;
544
545         ccb_count = read(targ_fd, ccb_array, sizeof(ccb_array));
546         if (ccb_count <= 0) {
547                 warn("read ccb ptrs");
548                 return;
549         }
550         ccb_count /= sizeof(union ccb *);
551         if (ccb_count < 1) {
552                 warnx("truncated read ccb ptr?");
553                 return;
554         }
555
556         for (i = 0; i < ccb_count; i++) {
557                 ccb = ccb_array[i];
558                 TAILQ_REMOVE(&pending_queue, &ccb->ccb_h, periph_links.tqe);
559
560                 switch (ccb->ccb_h.func_code) {
561                 case XPT_ACCEPT_TARGET_IO:
562                 {
563                         struct ccb_accept_tio *atio;
564                         struct atio_descr *a_descr;
565
566                         /* Initialize ATIO descr for this transaction */
567                         atio = &ccb->atio;
568                         a_descr = (struct atio_descr *)atio->ccb_h.targ_descr;
569                         bzero(a_descr, sizeof(*a_descr));
570                         TAILQ_INIT(&a_descr->cmplt_io);
571                         a_descr->flags = atio->ccb_h.flags &
572                                 (CAM_DIS_DISCONNECT | CAM_TAG_ACTION_VALID);
573                         /* XXX add a_descr->priority */
574                         if ((atio->ccb_h.flags & CAM_CDB_POINTER) == 0)
575                                 a_descr->cdb = atio->cdb_io.cdb_bytes;
576                         else
577                                 a_descr->cdb = atio->cdb_io.cdb_ptr;
578
579                         /* ATIOs are processed in FIFO order */
580                         TAILQ_INSERT_TAIL(&work_queue, &ccb->ccb_h,
581                                           periph_links.tqe);
582                         break;
583                 }
584                 case XPT_CONT_TARGET_IO:
585                 {
586                         struct ccb_scsiio *ctio;
587                         struct ctio_descr *c_descr;
588
589                         ctio = &ccb->ctio;
590                         c_descr = (struct ctio_descr *)ctio->ccb_h.targ_descr;
591                         c_descr->event = CTIO_DONE;
592                         /* Queue on the appropriate ATIO */
593                         queue_io(ctio);
594                         /* Process any queued completions. */
595                         oo += run_queue(c_descr->atio);
596                         break;
597                 }
598                 case XPT_IMMEDIATE_NOTIFY:
599                         /* INOTs are handled with priority */
600                         TAILQ_INSERT_HEAD(&work_queue, &ccb->ccb_h,
601                                           periph_links.tqe);
602                         break;
603                 default:
604                         warnx("Unhandled ccb type %#x in handle_read",
605                               ccb->ccb_h.func_code);
606                         break;
607                 }
608         }
609 }
610
611 /* Process an ATIO CCB from the kernel */
612 int
613 work_atio(struct ccb_accept_tio *atio)
614 {
615         struct ccb_scsiio *ctio;
616         struct atio_descr *a_descr;
617         struct ctio_descr *c_descr;
618         cam_status status;
619         int ret;
620
621         if (debug)
622                 warnx("Working on ATIO %p", atio);
623
624         a_descr = (struct atio_descr *)atio->ccb_h.targ_descr;
625
626         /* Get a CTIO and initialize it according to our known parameters */
627         ctio = get_ctio();
628         if (ctio == NULL) {
629                 return (1);
630         }
631         ret = 0;
632         ctio->ccb_h.flags = a_descr->flags;
633         ctio->tag_id = atio->tag_id;
634         ctio->init_id = atio->init_id;
635         /* XXX priority needs to be added to a_descr */
636         c_descr = (struct ctio_descr *)ctio->ccb_h.targ_descr;
637         c_descr->atio = atio;
638         if ((a_descr->flags & CAM_DIR_IN) != 0)
639                 c_descr->offset = a_descr->base_off + a_descr->targ_req;
640         else if ((a_descr->flags & CAM_DIR_MASK) == CAM_DIR_OUT)
641                 c_descr->offset = a_descr->base_off + a_descr->init_req;
642         else
643                 c_descr->offset = a_descr->base_off;
644
645         /* 
646          * Return a check condition if there was an error while
647          * receiving this ATIO.
648          */
649         if (atio->sense_len != 0) {
650                 struct scsi_sense_data_fixed *sense;
651
652                 if (debug) {
653                         warnx("ATIO with %u bytes sense received",
654                               atio->sense_len);
655                 }
656                 sense = (struct scsi_sense_data_fixed *)&atio->sense_data;
657                 tcmd_sense(ctio->init_id, ctio, sense->flags,
658                            sense->add_sense_code, sense->add_sense_code_qual);
659                 send_ccb((union ccb *)ctio, /*priority*/1);
660                 return (0);
661         }
662
663         status = atio->ccb_h.status & CAM_STATUS_MASK;
664         switch (status) {
665         case CAM_CDB_RECVD:
666                 ret = tcmd_handle(atio, ctio, ATIO_WORK);
667                 break;
668         case CAM_REQ_ABORTED:
669                 warn("ATIO %p aborted", a_descr);
670                 /* Requeue on HBA */
671                 TAILQ_REMOVE(&work_queue, &atio->ccb_h, periph_links.tqe);
672                 send_ccb((union ccb *)atio, /*priority*/1);
673                 ret = 1;
674                 break;
675         default:
676                 warnx("ATIO completed with unhandled status %#x", status);
677                 abort();
678                 /* NOTREACHED */
679                 break;
680         }
681
682         return (ret);
683 }
684
685 static void
686 queue_io(struct ccb_scsiio *ctio)
687 {
688         struct ccb_hdr *ccb_h;
689         struct io_queue *ioq;
690         struct ctio_descr *c_descr;
691         
692         c_descr = (struct ctio_descr *)ctio->ccb_h.targ_descr;
693         if (c_descr->atio == NULL) {
694                 errx(1, "CTIO %p has NULL ATIO", ctio);
695         }
696         ioq = &((struct atio_descr *)c_descr->atio->ccb_h.targ_descr)->cmplt_io;
697
698         if (TAILQ_EMPTY(ioq)) {
699                 TAILQ_INSERT_HEAD(ioq, &ctio->ccb_h, periph_links.tqe);
700                 return;
701         }
702
703         TAILQ_FOREACH_REVERSE(ccb_h, ioq, io_queue, periph_links.tqe) {
704                 struct ctio_descr *curr_descr = 
705                     (struct ctio_descr *)ccb_h->targ_descr;
706                 if (curr_descr->offset <= c_descr->offset) {
707                         break;
708                 }
709         }
710
711         if (ccb_h) {
712                 TAILQ_INSERT_AFTER(ioq, ccb_h, &ctio->ccb_h, periph_links.tqe);
713         } else {
714                 TAILQ_INSERT_HEAD(ioq, &ctio->ccb_h, periph_links.tqe);
715         }
716 }
717
718 /*
719  * Go through all completed AIO/CTIOs for a given ATIO and advance data
720  * counts, start continuation IO, etc.
721  */
722 static int
723 run_queue(struct ccb_accept_tio *atio)
724 {
725         struct atio_descr *a_descr;
726         struct ccb_hdr *ccb_h;
727         int sent_status, event;
728
729         if (atio == NULL)
730                 return (0);
731
732         a_descr = (struct atio_descr *)atio->ccb_h.targ_descr;
733
734         while ((ccb_h = TAILQ_FIRST(&a_descr->cmplt_io)) != NULL) {
735                 struct ccb_scsiio *ctio;
736                 struct ctio_descr *c_descr;
737
738                 ctio = (struct ccb_scsiio *)ccb_h;
739                 c_descr = (struct ctio_descr *)ctio->ccb_h.targ_descr;
740
741                 if (ctio->ccb_h.status == CAM_REQ_ABORTED) {
742                         TAILQ_REMOVE(&a_descr->cmplt_io, ccb_h,
743                                      periph_links.tqe);
744                         free_ccb((union ccb *)ctio);
745                         send_ccb((union ccb *)atio, /*priority*/1);
746                         continue;
747                 }
748
749                 /* If completed item is in range, call handler */
750                 if ((c_descr->event == AIO_DONE &&
751                     c_descr->offset == a_descr->base_off + a_descr->targ_ack)
752                  || (c_descr->event == CTIO_DONE &&
753                     c_descr->offset == a_descr->base_off + a_descr->init_ack)) {
754                         sent_status = (ccb_h->flags & CAM_SEND_STATUS) != 0;
755                         event = c_descr->event;
756
757                         TAILQ_REMOVE(&a_descr->cmplt_io, ccb_h,
758                                      periph_links.tqe);
759                         tcmd_handle(atio, ctio, c_descr->event);
760
761                         /* If entire transfer complete, send back ATIO */
762                         if (sent_status != 0 && event == CTIO_DONE)
763                                 send_ccb((union ccb *)atio, /*priority*/1);
764                 } else {
765                         /* Gap in offsets so wait until later callback */
766                         if (/* debug */ 1)
767                                 warnx("IO %p:%p out of order %s",  ccb_h,
768                                     a_descr, c_descr->event == AIO_DONE?
769                                     "aio" : "ctio");
770                         return (1);
771                 }
772         }
773         return (0);
774 }
775
776 static int
777 work_inot(struct ccb_immediate_notify *inot)
778 {
779         cam_status status;
780
781         if (debug)
782                 warnx("Working on INOT %p", inot);
783
784         status = inot->ccb_h.status;
785         status &= CAM_STATUS_MASK;
786
787         switch (status) {
788         case CAM_SCSI_BUS_RESET:
789                 tcmd_ua(CAM_TARGET_WILDCARD, UA_BUS_RESET);
790                 abort_all_pending();
791                 break;
792         case CAM_BDR_SENT:
793                 tcmd_ua(CAM_TARGET_WILDCARD, UA_BDR);
794                 abort_all_pending();
795                 break;
796         case CAM_MESSAGE_RECV:
797                 switch (inot->arg) {
798                 case MSG_TASK_COMPLETE:
799                 case MSG_INITIATOR_DET_ERR:
800                 case MSG_ABORT_TASK_SET:
801                 case MSG_MESSAGE_REJECT:
802                 case MSG_NOOP:
803                 case MSG_PARITY_ERROR:
804                 case MSG_TARGET_RESET:
805                 case MSG_ABORT_TASK:
806                 case MSG_CLEAR_TASK_SET:
807                 default:
808                         warnx("INOT message %#x", inot->arg);
809                         break;
810                 }
811                 break;
812         case CAM_REQ_ABORTED:
813                 warnx("INOT %p aborted", inot);
814                 break;
815         default:
816                 warnx("Unhandled INOT status %#x", status);
817                 break;
818         }
819
820         /* Requeue on SIM */
821         TAILQ_REMOVE(&work_queue, &inot->ccb_h, periph_links.tqe);
822         send_ccb((union ccb *)inot, /*priority*/1);
823
824         return (1);
825 }
826
827 void
828 send_ccb(union ccb *ccb, int priority)
829 {
830         if (debug)
831                 warnx("sending ccb (%#x)", ccb->ccb_h.func_code);
832         ccb->ccb_h.pinfo.priority = priority;
833         if (XPT_FC_IS_QUEUED(ccb)) {
834                 TAILQ_INSERT_TAIL(&pending_queue, &ccb->ccb_h,
835                                   periph_links.tqe);
836         }
837         if (write(targ_fd, &ccb, sizeof(ccb)) != sizeof(ccb)) {
838                 warn("write ccb");
839                 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
840         }
841 }
842
843 /* Return a CTIO/descr/buf combo from the freelist or malloc one */
844 static struct ccb_scsiio *
845 get_ctio()
846 {
847         struct ccb_scsiio *ctio;
848         struct ctio_descr *c_descr;
849         struct sigevent *se;
850
851         if (num_ctios == MAX_CTIOS) {
852                 warnx("at CTIO max");
853                 return (NULL);
854         }
855
856         ctio = (struct ccb_scsiio *)malloc(sizeof(*ctio));
857         if (ctio == NULL) {
858                 warn("malloc CTIO");
859                 return (NULL);
860         }
861         c_descr = (struct ctio_descr *)malloc(sizeof(*c_descr));
862         if (c_descr == NULL) {
863                 free(ctio);
864                 warn("malloc ctio_descr");
865                 return (NULL);
866         }
867         c_descr->buf = malloc(buf_size);
868         if (c_descr->buf == NULL) {
869                 free(c_descr);
870                 free(ctio);
871                 warn("malloc backing store");
872                 return (NULL);
873         }
874         num_ctios++;
875
876         /* Initialize CTIO, CTIO descr, and AIO */
877         ctio->ccb_h.func_code = XPT_CONT_TARGET_IO;
878         ctio->ccb_h.retry_count = 2;
879         ctio->ccb_h.timeout = CAM_TIME_INFINITY;
880         ctio->data_ptr = c_descr->buf;
881         ctio->ccb_h.targ_descr = c_descr;
882         c_descr->aiocb.aio_buf = c_descr->buf;
883         c_descr->aiocb.aio_fildes = file_fd;
884         se = &c_descr->aiocb.aio_sigevent;
885         se->sigev_notify = SIGEV_KEVENT;
886         se->sigev_notify_kqueue = kq_fd;
887         se->sigev_value.sival_ptr = ctio;
888
889         return (ctio);
890 }
891
892 void
893 free_ccb(union ccb *ccb)
894 {
895         switch (ccb->ccb_h.func_code) {
896         case XPT_CONT_TARGET_IO:
897         {
898                 struct ctio_descr *c_descr;
899
900                 c_descr = (struct ctio_descr *)ccb->ccb_h.targ_descr;
901                 free(c_descr->buf);
902                 num_ctios--;
903                 /* FALLTHROUGH */
904         }
905         case XPT_ACCEPT_TARGET_IO:
906                 free(ccb->ccb_h.targ_descr);
907                 /* FALLTHROUGH */
908         case XPT_IMMEDIATE_NOTIFY:
909         default:
910                 free(ccb);
911                 break;
912         }
913 }
914
915 static cam_status
916 get_sim_flags(u_int16_t *flags)
917 {
918         struct ccb_pathinq cpi;
919         cam_status status;
920
921         /* Find SIM capabilities */
922         bzero(&cpi, sizeof(cpi));
923         cpi.ccb_h.func_code = XPT_PATH_INQ;
924         send_ccb((union ccb *)&cpi, /*priority*/1);
925         status = cpi.ccb_h.status & CAM_STATUS_MASK;
926         if (status != CAM_REQ_CMP) {
927                 fprintf(stderr, "CPI failed, status %#x\n", status);
928                 return (status);
929         }
930
931         /* Can only enable on controllers that support target mode */
932         if ((cpi.target_sprt & PIT_PROCESSOR) == 0) {
933                 fprintf(stderr, "HBA does not support target mode\n");
934                 status = CAM_PATH_INVALID;
935                 return (status);
936         }
937
938         *flags = cpi.hba_inquiry;
939         return (status);
940 }
941
942 static void
943 rel_simq()
944 {
945         struct ccb_relsim crs;
946
947         bzero(&crs, sizeof(crs));
948         crs.ccb_h.func_code = XPT_REL_SIMQ;
949         crs.release_flags = RELSIM_RELEASE_AFTER_QEMPTY;
950         crs.openings = 0;
951         crs.release_timeout = 0;
952         crs.qfrozen_cnt = 0;
953         send_ccb((union ccb *)&crs, /*priority*/0);
954 }
955
956 /* Cancel all pending CCBs. */
957 static void
958 abort_all_pending()
959 {
960         struct ccb_abort         cab;
961         struct ccb_hdr          *ccb_h;
962
963         if (debug)
964                   warnx("abort_all_pending");
965
966         bzero(&cab, sizeof(cab));
967         cab.ccb_h.func_code = XPT_ABORT;
968         TAILQ_FOREACH(ccb_h, &pending_queue, periph_links.tqe) {
969                 if (debug)
970                           warnx("Aborting pending CCB %p\n", ccb_h);
971                 cab.abort_ccb = (union ccb *)ccb_h;
972                 send_ccb((union ccb *)&cab, /*priority*/1);
973                 if (cab.ccb_h.status != CAM_REQ_CMP) {
974                         warnx("Unable to abort CCB, status %#x\n",
975                                cab.ccb_h.status);
976                 }
977         }
978 }
979
980 static void
981 usage()
982 {
983         fprintf(stderr,
984                 "Usage: scsi_target [-AdSTY] [-b bufsize] [-c sectorsize]\n"
985                 "\t\t[-r numbufs] [-s volsize] [-W 8,16,32]\n"
986                 "\t\tbus:target:lun filename\n");
987         exit(1);
988 }