b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * CDDL HEADER START
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * The contents of this file are subject to the terms of the
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Common Development and Distribution License, Version 1.0 only
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * (the "License"). You may not use this file except in compliance
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * with the License.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * or http://www.opensolaris.org/os/licensing.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * See the License for the specific language governing permissions
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * and limitations under the License.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * When distributing Covered Code, include this CDDL HEADER in each
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * If applicable, add the following below this CDDL HEADER, with the
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * fields enclosed by brackets "[]" replaced with your own identifying
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * information: Portions Copyright [yyyy] [name of copyright owner]
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * CDDL HEADER END
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Use is subject to license terms.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#pragma ident "%Z%%M% %I% %E% SMI"
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth/*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * This program provides a command line interface to the
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * three new ioctls for the emul64 driver - EMUL64_WRITE_OFF,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * EMUL64_WRITE_ON and EMUL64_ZERO_RANGE. All three of these
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * ioctls require the range of blocks to be specified. The
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * range is specified by starting block number and block count
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * both of which are 64 bit.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Returns 0 on success, >0 on failure.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <stdio.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <fcntl.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <unistd.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <stropts.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <string.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <stdlib.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <errno.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <sys/types.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#include <sys/emul64.h>
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define DEBUG 1
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define ADMIN_DIR "/dev/cfg/"
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthchar *Pname;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int get_disk_addr(char *path, emul64_tgt_range_t *tr, char **admin);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic void
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthusage(void)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) fprintf(stderr, "Usage: emul64ioctl -s start_block "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "-b block_count -c write_off | write_on | zero emul64_dev\n");
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth exit(1);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthint
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthmain(int argc, char **argv)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth extern char *optarg;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth extern int optind;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth char *admin;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int count_seen = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int fd, retval;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int cmd = -1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int do_usage = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth char *slice;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int sb_seen = 0;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth emul64_tgt_range_t tr;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth Pname = strrchr(argv[0], '/');
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (Pname == NULL)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth Pname = argv[0];
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth else
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth Pname++;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth while ((retval = getopt(argc, argv, "s:b:c:")) != -1) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth switch (retval) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case 's':
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth sb_seen = 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth tr.emul64_blkrange.emul64_sb = atoll(optarg);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case 'b':
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth count_seen = 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth tr.emul64_blkrange.emul64_blkcnt = atoll(optarg);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth case 'c':
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (strncmp(optarg, "write_off",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth strlen("write_off")) == 0) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmd = EMUL64_WRITE_OFF;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth } else if (strncmp(optarg, "write_on",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth strlen("write_on")) == 0) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmd = EMUL64_WRITE_ON;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth } else if (strncmp(optarg, "zero",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth strlen("zero")) == 0) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth cmd = EMUL64_ZERO_RANGE;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth } else {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth do_usage = 1;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth default:
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth break;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (do_usage || (optind != argc - 1)) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth usage();
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if ((sb_seen == 0) || (count_seen == 0) || (cmd == -1))
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth usage();
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth slice = argv[optind];
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * Get admin device, target and lun
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (get_disk_addr(slice, &tr, &admin) != 0)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth exit(1);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /*
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth * open the specified emul64_dev.
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if ((fd = open(admin, O_RDONLY, 0444)) != -1) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth retval = ioctl(fd, cmd, &tr);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) close(fd);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (retval != -1) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth free(admin);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) printf("emul64ioctl: %s: ioctl %s\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth admin, strerror(errno));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth } else {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) printf("emul64ioctl: %s: open %s\n",
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth admin, strerror(errno));
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth free(admin);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (1);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth#define TOK_CHECK(s) if (token == NULL) {\
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth bogus = (s);\
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth goto err_out;\
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthstatic int
b1dd958f54f8bfa984d306bb8ca8264855761d7bcthget_disk_addr(char *path, emul64_tgt_range_t *tr, char **admin)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth{
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth size_t admin_size;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int ctlr_num;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth int conversions;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth char *ctds;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *admin = NULL;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth ctds = strrchr(path, '/');
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (ctds == NULL)
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth ctds = path;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth else
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth ctds++;
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth conversions = sscanf(ctds, "c%dt%hud%hu", &ctlr_num,
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth &tr->emul64_target, &tr->emul64_lun);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (conversions != 3) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) fprintf(stderr, "%s: \"%s\" is invalid disk name. "
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth "%d conversions\n", Pname, ctds, conversions);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (-1);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth /* Build controller name */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth admin_size = strlen(ADMIN_DIR) +
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth 10 + /* enough digits for an int */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth 1 + /* c */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth 1; /* Null terminator */
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth *admin = malloc(admin_size);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth if (*admin == NULL) {
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) fprintf(stderr, "%s: out of memory\n", Pname);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (-1);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth }
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth (void) snprintf(*admin, admin_size, "%sc%d", ADMIN_DIR, ctlr_num);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth return (0);
b1dd958f54f8bfa984d306bb8ca8264855761d7bcth}