19875eecfSJustin T. Gibbs /* 29875eecfSJustin T. Gibbs * Sample program to attach to the "targ" processor target, target mode 39875eecfSJustin T. Gibbs * peripheral driver and push or receive data. 49875eecfSJustin T. Gibbs * 59875eecfSJustin T. Gibbs * Copyright (c) 1998 Justin T. Gibbs. 69875eecfSJustin T. Gibbs * All rights reserved. 79875eecfSJustin T. Gibbs * 89875eecfSJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 99875eecfSJustin T. Gibbs * modification, are permitted provided that the following conditions 109875eecfSJustin T. Gibbs * are met: 119875eecfSJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 129875eecfSJustin T. Gibbs * notice, this list of conditions, and the following disclaimer, 139875eecfSJustin T. Gibbs * without modification, immediately at the beginning of the file. 149875eecfSJustin T. Gibbs * 2. The name of the author may not be used to endorse or promote products 159875eecfSJustin T. Gibbs * derived from this software without specific prior written permission. 169875eecfSJustin T. Gibbs * 179875eecfSJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 189875eecfSJustin T. Gibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 199875eecfSJustin T. Gibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 209875eecfSJustin T. Gibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 219875eecfSJustin T. Gibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 229875eecfSJustin T. Gibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 239875eecfSJustin T. Gibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 249875eecfSJustin T. Gibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 259875eecfSJustin T. Gibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 269875eecfSJustin T. Gibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 279875eecfSJustin T. Gibbs * SUCH DAMAGE. 289875eecfSJustin T. Gibbs * 297f3dea24SPeter Wemm * $FreeBSD$ 309875eecfSJustin T. Gibbs */ 319875eecfSJustin T. Gibbs 329875eecfSJustin T. Gibbs #include <sys/types.h> 339875eecfSJustin T. Gibbs 34b3fae35cSJustin T. Gibbs #include <errno.h> 359875eecfSJustin T. Gibbs #include <fcntl.h> 369875eecfSJustin T. Gibbs #include <poll.h> 37b3fae35cSJustin T. Gibbs #include <signal.h> 389875eecfSJustin T. Gibbs #include <stddef.h> 399875eecfSJustin T. Gibbs #include <stdio.h> 409875eecfSJustin T. Gibbs #include <stdlib.h> 419875eecfSJustin T. Gibbs #include <sysexits.h> 429875eecfSJustin T. Gibbs #include <unistd.h> 439875eecfSJustin T. Gibbs 449875eecfSJustin T. Gibbs #include <cam/scsi/scsi_all.h> 459875eecfSJustin T. Gibbs #include <cam/scsi/scsi_message.h> 469875eecfSJustin T. Gibbs #include <cam/scsi/scsi_targetio.h> 479875eecfSJustin T. Gibbs 489875eecfSJustin T. Gibbs char *appname; 499875eecfSJustin T. Gibbs int ifd; 509875eecfSJustin T. Gibbs char *ifilename; 519875eecfSJustin T. Gibbs int ofd; 529875eecfSJustin T. Gibbs char *ofilename; 539875eecfSJustin T. Gibbs size_t bufsize = 64 * 1024; 549875eecfSJustin T. Gibbs void *buf; 55b3fae35cSJustin T. Gibbs char targdevname[80]; 56b3fae35cSJustin T. Gibbs int targctlfd; 579875eecfSJustin T. Gibbs int targfd; 58b3fae35cSJustin T. Gibbs int quit; 5997188b54SMatt Jacob int debug = 0; 60b3fae35cSJustin T. Gibbs struct ioc_alloc_unit alloc_unit = { 61b3fae35cSJustin T. Gibbs CAM_BUS_WILDCARD, 62b3fae35cSJustin T. Gibbs CAM_TARGET_WILDCARD, 63b3fae35cSJustin T. Gibbs CAM_LUN_WILDCARD 64b3fae35cSJustin T. Gibbs }; 659875eecfSJustin T. Gibbs 669875eecfSJustin T. Gibbs static void pump_events(); 6787609397SJustin T. Gibbs static void cleanup(); 689875eecfSJustin T. Gibbs static void handle_exception(); 69b3fae35cSJustin T. Gibbs static void quit_handler(); 709875eecfSJustin T. Gibbs static void usage(); 719875eecfSJustin T. Gibbs 729875eecfSJustin T. Gibbs int 739875eecfSJustin T. Gibbs main(int argc, char *argv[]) 749875eecfSJustin T. Gibbs { 759875eecfSJustin T. Gibbs int ch; 769875eecfSJustin T. Gibbs 779875eecfSJustin T. Gibbs appname = *argv; 7897188b54SMatt Jacob while ((ch = getopt(argc, argv, "i:o:p:t:l:d")) != -1) { 799875eecfSJustin T. Gibbs switch(ch) { 809875eecfSJustin T. Gibbs case 'i': 819875eecfSJustin T. Gibbs if ((ifd = open(optarg, O_RDONLY)) == -1) { 829875eecfSJustin T. Gibbs perror(optarg); 839875eecfSJustin T. Gibbs exit(EX_NOINPUT); 849875eecfSJustin T. Gibbs } 859875eecfSJustin T. Gibbs ifilename = optarg; 869875eecfSJustin T. Gibbs break; 879875eecfSJustin T. Gibbs case 'o': 889875eecfSJustin T. Gibbs if ((ofd = open(optarg, 899875eecfSJustin T. Gibbs O_WRONLY|O_CREAT), 0600) == -1) { 909875eecfSJustin T. Gibbs perror(optarg); 919875eecfSJustin T. Gibbs exit(EX_CANTCREAT); 929875eecfSJustin T. Gibbs } 939875eecfSJustin T. Gibbs ofilename = optarg; 949875eecfSJustin T. Gibbs break; 95b3fae35cSJustin T. Gibbs case 'p': 96b3fae35cSJustin T. Gibbs alloc_unit.path_id = atoi(optarg); 97b3fae35cSJustin T. Gibbs break; 98b3fae35cSJustin T. Gibbs case 't': 99b3fae35cSJustin T. Gibbs alloc_unit.target_id = atoi(optarg); 100b3fae35cSJustin T. Gibbs break; 101b3fae35cSJustin T. Gibbs case 'l': 102b3fae35cSJustin T. Gibbs alloc_unit.lun_id = atoi(optarg); 103b3fae35cSJustin T. Gibbs break; 10497188b54SMatt Jacob case 'd': 10597188b54SMatt Jacob debug++; 10697188b54SMatt Jacob break; 1079875eecfSJustin T. Gibbs case '?': 1089875eecfSJustin T. Gibbs default: 1099875eecfSJustin T. Gibbs usage(); 1109875eecfSJustin T. Gibbs /* NOTREACHED */ 1119875eecfSJustin T. Gibbs } 1129875eecfSJustin T. Gibbs } 1139875eecfSJustin T. Gibbs argc -= optind; 1149875eecfSJustin T. Gibbs argv += optind; 1159875eecfSJustin T. Gibbs 116b3fae35cSJustin T. Gibbs if (alloc_unit.path_id == CAM_BUS_WILDCARD 117b3fae35cSJustin T. Gibbs || alloc_unit.target_id == CAM_TARGET_WILDCARD 118b3fae35cSJustin T. Gibbs || alloc_unit.lun_id == CAM_LUN_WILDCARD) { 119b3fae35cSJustin T. Gibbs fprintf(stderr, "%s: Incomplete device path specifiled\n", 120b3fae35cSJustin T. Gibbs appname); 1219875eecfSJustin T. Gibbs usage(); 1229875eecfSJustin T. Gibbs /* NOTREACHED */ 1239875eecfSJustin T. Gibbs } 1249875eecfSJustin T. Gibbs 125b3fae35cSJustin T. Gibbs if (argc != 0) { 126b3fae35cSJustin T. Gibbs fprintf(stderr, "%s: Too many arguments\n", appname); 127b3fae35cSJustin T. Gibbs usage(); 128b3fae35cSJustin T. Gibbs /* NOTREACHED */ 129b3fae35cSJustin T. Gibbs } 130b3fae35cSJustin T. Gibbs 131b3fae35cSJustin T. Gibbs /* Allocate a new instance */ 132b3fae35cSJustin T. Gibbs if ((targctlfd = open("/dev/targ.ctl", O_RDWR)) == -1) { 133b3fae35cSJustin T. Gibbs perror("/dev/targ.ctl"); 134b3fae35cSJustin T. Gibbs exit(EX_UNAVAILABLE); 135b3fae35cSJustin T. Gibbs } 136b3fae35cSJustin T. Gibbs 137b3fae35cSJustin T. Gibbs if (ioctl(targctlfd, TARGCTLIOALLOCUNIT, &alloc_unit) == -1) { 138b3fae35cSJustin T. Gibbs perror("TARGCTLIOALLOCUNIT"); 139b3fae35cSJustin T. Gibbs exit(EX_SOFTWARE); 140b3fae35cSJustin T. Gibbs } 141b3fae35cSJustin T. Gibbs 142b3fae35cSJustin T. Gibbs snprintf(targdevname, sizeof(targdevname), "/dev/targ%d", 143b3fae35cSJustin T. Gibbs alloc_unit.unit); 144b3fae35cSJustin T. Gibbs 1459875eecfSJustin T. Gibbs if ((targfd = open(targdevname, O_RDWR)) == -1) { 1469875eecfSJustin T. Gibbs perror(targdevname); 147b3fae35cSJustin T. Gibbs ioctl(targctlfd, TARGCTLIOFREEUNIT, &alloc_unit); 1489875eecfSJustin T. Gibbs exit(EX_NOINPUT); 1499875eecfSJustin T. Gibbs } 1509875eecfSJustin T. Gibbs 15197188b54SMatt Jacob if (ioctl(targfd, TARGIODEBUG, &debug) == -1) { 15297188b54SMatt Jacob perror("TARGIODEBUG"); 15397188b54SMatt Jacob exit(EX_SOFTWARE); 15497188b54SMatt Jacob } 15597188b54SMatt Jacob 1569875eecfSJustin T. Gibbs buf = malloc(bufsize); 1579875eecfSJustin T. Gibbs 1589875eecfSJustin T. Gibbs if (buf == NULL) { 1599875eecfSJustin T. Gibbs fprintf(stderr, "%s: Could not malloc I/O buffer", appname); 1609875eecfSJustin T. Gibbs exit(EX_OSERR); 1619875eecfSJustin T. Gibbs } 1629875eecfSJustin T. Gibbs 163b3fae35cSJustin T. Gibbs signal(SIGHUP, quit_handler); 164b3fae35cSJustin T. Gibbs signal(SIGINT, quit_handler); 165b3fae35cSJustin T. Gibbs signal(SIGTERM, quit_handler); 166b3fae35cSJustin T. Gibbs 16787609397SJustin T. Gibbs atexit(cleanup); 16887609397SJustin T. Gibbs 1699875eecfSJustin T. Gibbs pump_events(); 1709875eecfSJustin T. Gibbs 17187609397SJustin T. Gibbs return (0); 17287609397SJustin T. Gibbs } 17387609397SJustin T. Gibbs 17487609397SJustin T. Gibbs static void 17587609397SJustin T. Gibbs cleanup() 17687609397SJustin T. Gibbs { 177b3fae35cSJustin T. Gibbs close(targfd); 178b3fae35cSJustin T. Gibbs 179b3fae35cSJustin T. Gibbs if (ioctl(targctlfd, TARGCTLIOFREEUNIT, &alloc_unit) == -1) { 180b3fae35cSJustin T. Gibbs perror("TARGCTLIOFREEUNIT"); 181b3fae35cSJustin T. Gibbs exit(EX_SOFTWARE); 182b3fae35cSJustin T. Gibbs } 183b3fae35cSJustin T. Gibbs 184b3fae35cSJustin T. Gibbs close(targctlfd); 1859875eecfSJustin T. Gibbs } 1869875eecfSJustin T. Gibbs 1879875eecfSJustin T. Gibbs static void 1889875eecfSJustin T. Gibbs pump_events() 1899875eecfSJustin T. Gibbs { 1909875eecfSJustin T. Gibbs struct pollfd targpoll; 1919875eecfSJustin T. Gibbs 1929875eecfSJustin T. Gibbs targpoll.fd = targfd; 1939875eecfSJustin T. Gibbs targpoll.events = POLLRDNORM|POLLWRNORM; 1949875eecfSJustin T. Gibbs 195b3fae35cSJustin T. Gibbs while (quit == 0) { 1969875eecfSJustin T. Gibbs int retval; 1979875eecfSJustin T. Gibbs 1989875eecfSJustin T. Gibbs retval = poll(&targpoll, 1, INFTIM); 1999875eecfSJustin T. Gibbs 2009875eecfSJustin T. Gibbs if (retval == -1) { 201b3fae35cSJustin T. Gibbs if (errno == EINTR) 202b3fae35cSJustin T. Gibbs continue; 2039875eecfSJustin T. Gibbs perror("Poll Failed"); 2049875eecfSJustin T. Gibbs exit(EX_SOFTWARE); 2059875eecfSJustin T. Gibbs } 2069875eecfSJustin T. Gibbs 2079875eecfSJustin T. Gibbs if (retval == 0) { 2089875eecfSJustin T. Gibbs perror("Poll returned 0 although timeout infinite???"); 2099875eecfSJustin T. Gibbs exit(EX_SOFTWARE); 2109875eecfSJustin T. Gibbs } 2119875eecfSJustin T. Gibbs 2129875eecfSJustin T. Gibbs if (retval > 1) { 2139875eecfSJustin T. Gibbs perror("Poll returned more fds ready than allocated"); 2149875eecfSJustin T. Gibbs exit(EX_SOFTWARE); 2159875eecfSJustin T. Gibbs } 2169875eecfSJustin T. Gibbs 2179875eecfSJustin T. Gibbs /* Process events */ 2189875eecfSJustin T. Gibbs if ((targpoll.revents & POLLERR) != 0) { 2199875eecfSJustin T. Gibbs handle_exception(); 2209875eecfSJustin T. Gibbs } 2219875eecfSJustin T. Gibbs 2229875eecfSJustin T. Gibbs if ((targpoll.revents & POLLRDNORM) != 0) { 2239875eecfSJustin T. Gibbs retval = read(targfd, buf, bufsize); 2249875eecfSJustin T. Gibbs 2259875eecfSJustin T. Gibbs if (retval == -1) { 2269875eecfSJustin T. Gibbs perror("Read from targ failed"); 22787609397SJustin T. Gibbs /* Go look for exceptions */ 22887609397SJustin T. Gibbs continue; 2299875eecfSJustin T. Gibbs } else { 2309875eecfSJustin T. Gibbs retval = write(ofd, buf, retval); 2319875eecfSJustin T. Gibbs if (retval == -1) { 2329875eecfSJustin T. Gibbs perror("Write to file failed"); 2339875eecfSJustin T. Gibbs } 2349875eecfSJustin T. Gibbs } 2359875eecfSJustin T. Gibbs } 2369875eecfSJustin T. Gibbs 2379875eecfSJustin T. Gibbs if ((targpoll.revents & POLLWRNORM) != 0) { 2389875eecfSJustin T. Gibbs int amount_read; 2399875eecfSJustin T. Gibbs 2409875eecfSJustin T. Gibbs retval = read(ifd, buf, bufsize); 2419875eecfSJustin T. Gibbs if (retval == -1) { 2429875eecfSJustin T. Gibbs perror("Read from file failed"); 2439875eecfSJustin T. Gibbs exit(EX_SOFTWARE); 2449875eecfSJustin T. Gibbs } 2459875eecfSJustin T. Gibbs 2469875eecfSJustin T. Gibbs amount_read = retval; 2479875eecfSJustin T. Gibbs retval = write(targfd, buf, retval); 2489875eecfSJustin T. Gibbs if (retval == -1) { 2499875eecfSJustin T. Gibbs perror("Write to targ failed"); 2509875eecfSJustin T. Gibbs retval = 0; 2519875eecfSJustin T. Gibbs } 2529875eecfSJustin T. Gibbs 2539875eecfSJustin T. Gibbs /* Backup in our input stream on short writes */ 2549875eecfSJustin T. Gibbs if (retval != amount_read) 2559875eecfSJustin T. Gibbs lseek(ifd, retval - amount_read, SEEK_CUR); 2569875eecfSJustin T. Gibbs } 2579875eecfSJustin T. Gibbs } 2589875eecfSJustin T. Gibbs } 2599875eecfSJustin T. Gibbs 2609875eecfSJustin T. Gibbs static void 2619875eecfSJustin T. Gibbs handle_exception() 2629875eecfSJustin T. Gibbs { 2639875eecfSJustin T. Gibbs targ_exception exceptions; 2649875eecfSJustin T. Gibbs 2659875eecfSJustin T. Gibbs if (ioctl(targfd, TARGIOCFETCHEXCEPTION, &exceptions) == -1) { 2669875eecfSJustin T. Gibbs perror("TARGIOCFETCHEXCEPTION"); 2679875eecfSJustin T. Gibbs exit(EX_SOFTWARE); 2689875eecfSJustin T. Gibbs } 2699875eecfSJustin T. Gibbs 27087609397SJustin T. Gibbs printf("Saw exceptions %x\n", exceptions); 2719875eecfSJustin T. Gibbs if ((exceptions & TARG_EXCEPT_DEVICE_INVALID) != 0) { 2729875eecfSJustin T. Gibbs /* Device went away. Nothing more to do. */ 27387609397SJustin T. Gibbs printf("Device went away\n"); 2749875eecfSJustin T. Gibbs exit(0); 2759875eecfSJustin T. Gibbs } 2769875eecfSJustin T. Gibbs 2779875eecfSJustin T. Gibbs if ((exceptions & TARG_EXCEPT_UNKNOWN_ATIO) != 0) { 2789875eecfSJustin T. Gibbs struct ccb_accept_tio atio; 2799875eecfSJustin T. Gibbs struct ioc_initiator_state ioc_istate; 2809875eecfSJustin T. Gibbs struct scsi_sense_data *sense; 2819875eecfSJustin T. Gibbs union ccb ccb; 2829875eecfSJustin T. Gibbs 2839875eecfSJustin T. Gibbs if (ioctl(targfd, TARGIOCFETCHATIO, &atio) == -1) { 2849875eecfSJustin T. Gibbs perror("TARGIOCFETCHATIO"); 2859875eecfSJustin T. Gibbs exit(EX_SOFTWARE); 2869875eecfSJustin T. Gibbs } 2879875eecfSJustin T. Gibbs 2889875eecfSJustin T. Gibbs printf("Ignoring unhandled command 0x%x for Id %d\n", 2899875eecfSJustin T. Gibbs atio.cdb_io.cdb_bytes[0], atio.init_id); 2909875eecfSJustin T. Gibbs 2919875eecfSJustin T. Gibbs ioc_istate.initiator_id = atio.init_id; 2929875eecfSJustin T. Gibbs if (ioctl(targfd, TARGIOCGETISTATE, &ioc_istate) == -1) { 2939875eecfSJustin T. Gibbs perror("TARGIOCGETISTATE"); 2949875eecfSJustin T. Gibbs exit(EX_SOFTWARE); 2959875eecfSJustin T. Gibbs } 2969875eecfSJustin T. Gibbs 2979875eecfSJustin T. Gibbs /* Send back Illegal Command code status */ 2989875eecfSJustin T. Gibbs ioc_istate.istate.pending_ca |= CA_CMD_SENSE; 2999875eecfSJustin T. Gibbs sense = &ioc_istate.istate.sense_data; 3009875eecfSJustin T. Gibbs bzero(sense, sizeof(*sense)); 3019875eecfSJustin T. Gibbs sense->error_code = SSD_CURRENT_ERROR; 3029875eecfSJustin T. Gibbs sense->flags = SSD_KEY_ILLEGAL_REQUEST; 3039875eecfSJustin T. Gibbs sense->add_sense_code = 0x20; 3049875eecfSJustin T. Gibbs sense->add_sense_code_qual = 0x00; 3059875eecfSJustin T. Gibbs sense->extra_len = offsetof(struct scsi_sense_data, fru) 3069875eecfSJustin T. Gibbs - offsetof(struct scsi_sense_data, extra_len); 3079875eecfSJustin T. Gibbs 3089875eecfSJustin T. Gibbs if (ioctl(targfd, TARGIOCSETISTATE, &ioc_istate) == -1) { 3099875eecfSJustin T. Gibbs perror("TARGIOCSETISTATE"); 3109875eecfSJustin T. Gibbs exit(EX_SOFTWARE); 3119875eecfSJustin T. Gibbs } 3129875eecfSJustin T. Gibbs 31397188b54SMatt Jacob /* Clear the exception so the kernel will take our response */ 31497188b54SMatt Jacob if (ioctl(targfd, TARGIOCCLEAREXCEPTION, &exceptions) == -1) { 31597188b54SMatt Jacob perror("TARGIOCCLEAREXCEPTION"); 31697188b54SMatt Jacob exit(EX_SOFTWARE); 31797188b54SMatt Jacob } 31897188b54SMatt Jacob 3199875eecfSJustin T. Gibbs bzero(&ccb, sizeof(ccb)); 3209875eecfSJustin T. Gibbs cam_fill_ctio(&ccb.csio, /*retries*/2, 3219875eecfSJustin T. Gibbs /*cbfcnp*/NULL, 3229875eecfSJustin T. Gibbs /*flags*/CAM_DIR_NONE 3239875eecfSJustin T. Gibbs | (atio.ccb_h.flags & CAM_TAG_ACTION_VALID) 3249875eecfSJustin T. Gibbs | CAM_SEND_STATUS, 3259875eecfSJustin T. Gibbs /*tag_action*/MSG_SIMPLE_Q_TAG, 3269875eecfSJustin T. Gibbs atio.tag_id, 3279875eecfSJustin T. Gibbs atio.init_id, 3289875eecfSJustin T. Gibbs SCSI_STATUS_CHECK_COND, 3299875eecfSJustin T. Gibbs /*data_ptr*/NULL, 3309875eecfSJustin T. Gibbs /*dxfer_len*/0, 3319875eecfSJustin T. Gibbs /*timeout*/5 * 1000); 33297188b54SMatt Jacob 3339875eecfSJustin T. Gibbs if (ioctl(targfd, TARGIOCCOMMAND, &ccb) == -1) { 3349875eecfSJustin T. Gibbs perror("TARGIOCCOMMAND"); 3359875eecfSJustin T. Gibbs exit(EX_SOFTWARE); 3369875eecfSJustin T. Gibbs } 3379875eecfSJustin T. Gibbs 33897188b54SMatt Jacob } else { 3399875eecfSJustin T. Gibbs if (ioctl(targfd, TARGIOCCLEAREXCEPTION, &exceptions) == -1) { 3409875eecfSJustin T. Gibbs perror("TARGIOCCLEAREXCEPTION"); 3419875eecfSJustin T. Gibbs exit(EX_SOFTWARE); 3429875eecfSJustin T. Gibbs } 3439875eecfSJustin T. Gibbs } 3449875eecfSJustin T. Gibbs 34597188b54SMatt Jacob } 34697188b54SMatt Jacob 3479875eecfSJustin T. Gibbs static void 348b3fae35cSJustin T. Gibbs quit_handler(int signum) 349b3fae35cSJustin T. Gibbs { 350b3fae35cSJustin T. Gibbs quit = 1; 351b3fae35cSJustin T. Gibbs } 352b3fae35cSJustin T. Gibbs 353b3fae35cSJustin T. Gibbs static void 3549875eecfSJustin T. Gibbs usage() 3559875eecfSJustin T. Gibbs { 3569875eecfSJustin T. Gibbs 3579875eecfSJustin T. Gibbs (void)fprintf(stderr, 35897188b54SMatt Jacob "usage: %-16s [ -d ] [-o output_file] [-i input_file] -p path -t target -l lun\n", 359b3fae35cSJustin T. Gibbs appname); 3609875eecfSJustin T. Gibbs 3619875eecfSJustin T. Gibbs exit(EX_USAGE); 3629875eecfSJustin T. Gibbs } 3639875eecfSJustin T. Gibbs 364