1255570Strasz/* 2255570Strasz * Copyright (c) 1997-2007 Kenneth D. Merry 3255570Strasz * Copyright (c) 2012 The FreeBSD Foundation 4255570Strasz * All rights reserved. 5255570Strasz * 6255570Strasz * Portions of this software were developed by Edward Tomasz Napierala 7255570Strasz * under sponsorship from the FreeBSD Foundation. 8255570Strasz * 9255570Strasz * Redistribution and use in source and binary forms, with or without 10255570Strasz * modification, are permitted provided that the following conditions 11255570Strasz * are met: 12255570Strasz * 1. Redistributions of source code must retain the above copyright 13255570Strasz * notice, this list of conditions and the following disclaimer. 14255570Strasz * 2. Redistributions in binary form must reproduce the above copyright 15255570Strasz * notice, this list of conditions and the following disclaimer in the 16255570Strasz * documentation and/or other materials provided with the distribution. 17255570Strasz * 3. The name of the author may not be used to endorse or promote products 18255570Strasz * derived from this software without specific prior written permission. 19255570Strasz * 20255570Strasz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21255570Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22255570Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23255570Strasz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24255570Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25255570Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26255570Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27255570Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28255570Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29255570Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30255570Strasz * SUCH DAMAGE. 31255570Strasz */ 32255570Strasz 33255570Strasz#include <sys/cdefs.h> 34255570Strasz__FBSDID("$FreeBSD$"); 35255570Strasz 36255570Strasz#include <sys/ioctl.h> 37255570Strasz#include <sys/stdint.h> 38255570Strasz#include <sys/types.h> 39255570Strasz#include <sys/endian.h> 40255570Strasz#include <sys/sbuf.h> 41255570Strasz 42255570Strasz#include <stdio.h> 43255570Strasz#include <stdlib.h> 44255570Strasz#include <string.h> 45255570Strasz#include <unistd.h> 46255570Strasz#include <inttypes.h> 47255570Strasz#include <limits.h> 48255570Strasz#include <fcntl.h> 49255570Strasz#include <err.h> 50255570Strasz 51255570Strasz#include <cam/cam.h> 52255570Strasz#include <cam/cam_debug.h> 53255570Strasz#include <cam/cam_ccb.h> 54255570Strasz#include <cam/scsi/scsi_all.h> 55255570Strasz#include <cam/scsi/scsi_da.h> 56255570Strasz#include <cam/scsi/scsi_pass.h> 57255570Strasz#include <cam/scsi/scsi_message.h> 58255570Strasz#include <cam/scsi/smp_all.h> 59255570Strasz#include <cam/ata/ata_all.h> 60255570Strasz#include <camlib.h> 61255570Strasz 62255570Strasz#include "iscsictl.h" 63255570Strasz 64255570Straszvoid 65255570Straszprint_periphs(int session_id) 66255570Strasz{ 67255570Strasz union ccb ccb; 68255570Strasz int bufsize, fd; 69255570Strasz unsigned int i; 70255570Strasz int skip_bus, skip_device; 71255570Strasz 72255570Strasz if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) { 73255570Strasz warn("couldn't open %s", XPT_DEVICE); 74255570Strasz return; 75255570Strasz } 76255570Strasz 77255570Strasz /* 78255570Strasz * First, iterate over the whole list to find the bus. 79255570Strasz */ 80255570Strasz 81255570Strasz bzero(&ccb, sizeof(union ccb)); 82255570Strasz 83255570Strasz ccb.ccb_h.path_id = CAM_XPT_PATH_ID; 84255570Strasz ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; 85255570Strasz ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; 86255570Strasz 87255570Strasz ccb.ccb_h.func_code = XPT_DEV_MATCH; 88255570Strasz bufsize = sizeof(struct dev_match_result) * 100; 89255570Strasz ccb.cdm.match_buf_len = bufsize; 90255570Strasz ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize); 91255570Strasz if (ccb.cdm.matches == NULL) { 92255570Strasz warnx("can't malloc memory for matches"); 93255570Strasz close(fd); 94255570Strasz return; 95255570Strasz } 96255570Strasz ccb.cdm.num_matches = 0; 97255570Strasz 98255570Strasz /* 99255570Strasz * We fetch all nodes, since we display most of them in the default 100255570Strasz * case, and all in the verbose case. 101255570Strasz */ 102255570Strasz ccb.cdm.num_patterns = 0; 103255570Strasz ccb.cdm.pattern_buf_len = 0; 104255570Strasz 105265532Strasz skip_bus = 1; 106265532Strasz skip_device = 1; 107265532Strasz 108255570Strasz /* 109255570Strasz * We do the ioctl multiple times if necessary, in case there are 110255570Strasz * more than 100 nodes in the EDT. 111255570Strasz */ 112255570Strasz do { 113255570Strasz if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) { 114255570Strasz warn("error sending CAMIOCOMMAND ioctl"); 115255570Strasz break; 116255570Strasz } 117255570Strasz 118255570Strasz if ((ccb.ccb_h.status != CAM_REQ_CMP) 119255570Strasz || ((ccb.cdm.status != CAM_DEV_MATCH_LAST) 120255570Strasz && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) { 121255570Strasz warnx("got CAM error %#x, CDM error %d\n", 122255570Strasz ccb.ccb_h.status, ccb.cdm.status); 123255570Strasz break; 124255570Strasz } 125255570Strasz 126255570Strasz for (i = 0; i < ccb.cdm.num_matches; i++) { 127255570Strasz switch (ccb.cdm.matches[i].type) { 128255570Strasz case DEV_MATCH_BUS: { 129255570Strasz struct bus_match_result *bus_result; 130255570Strasz 131255570Strasz bus_result = &ccb.cdm.matches[i].result.bus_result; 132255570Strasz 133255570Strasz skip_bus = 1; 134255570Strasz 135255570Strasz if (strcmp(bus_result->dev_name, "iscsi") != 0) { 136255570Strasz //printf("not iscsi\n"); 137255570Strasz continue; 138255570Strasz } 139255570Strasz 140255570Strasz if ((int)bus_result->unit_number != session_id) { 141255570Strasz //printf("wrong unit, %d != %d\n", bus_result->unit_number, session_id); 142255570Strasz continue; 143255570Strasz } 144255570Strasz 145255570Strasz skip_bus = 0; 146255570Strasz } 147255570Strasz case DEV_MATCH_DEVICE: { 148255570Strasz skip_device = 1; 149255570Strasz 150255570Strasz if (skip_bus != 0) 151255570Strasz continue; 152255570Strasz 153255570Strasz skip_device = 0; 154255570Strasz 155255570Strasz break; 156255570Strasz } 157255570Strasz case DEV_MATCH_PERIPH: { 158255570Strasz struct periph_match_result *periph_result; 159255570Strasz 160255570Strasz periph_result = 161255570Strasz &ccb.cdm.matches[i].result.periph_result; 162255570Strasz 163255570Strasz if (skip_device != 0) 164255570Strasz continue; 165255570Strasz 166255570Strasz if (strcmp(periph_result->periph_name, "pass") == 0) 167255570Strasz continue; 168255570Strasz 169255570Strasz fprintf(stdout, "%s%d ", 170255570Strasz periph_result->periph_name, 171255570Strasz periph_result->unit_number); 172255570Strasz 173255570Strasz break; 174255570Strasz } 175255570Strasz default: 176255570Strasz fprintf(stdout, "unknown match type\n"); 177255570Strasz break; 178255570Strasz } 179255570Strasz } 180255570Strasz 181255570Strasz } while ((ccb.ccb_h.status == CAM_REQ_CMP) 182255570Strasz && (ccb.cdm.status == CAM_DEV_MATCH_MORE)); 183255570Strasz 184255570Strasz close(fd); 185255570Strasz} 186255570Strasz 187