1*44704f69SBart Van Assche /*
2*44704f69SBart Van Assche * Utility program for the Linux OS SCSI generic ("sg") device driver.
3*44704f69SBart Van Assche * Copyright (C) 2000-2017 D. Gilbert
4*44704f69SBart Van Assche * This program is free software; you can redistribute it and/or modify
5*44704f69SBart Van Assche * it under the terms of the GNU General Public License as published by
6*44704f69SBart Van Assche * the Free Software Foundation; either version 2, or (at your option)
7*44704f69SBart Van Assche * any later version.
8*44704f69SBart Van Assche *
9*44704f69SBart Van Assche * SPDX-License-Identifier: GPL-2.0-or-later
10*44704f69SBart Van Assche
11*44704f69SBart Van Assche This shows the mapping from "sg" devices to other scsi devices
12*44704f69SBart Van Assche (i.e. sd, scd or st) if any.
13*44704f69SBart Van Assche
14*44704f69SBart Van Assche Note: This program requires sg version 2 or better.
15*44704f69SBart Van Assche
16*44704f69SBart Van Assche Version 0.19 20041203
17*44704f69SBart Van Assche
18*44704f69SBart Van Assche Version 1.02 20050511
19*44704f69SBart Van Assche - allow for sparse disk name with up to 3 letter SCSI
20*44704f69SBart Van Assche disk device node names (e.g. /dev/sdaaa)
21*44704f69SBart Van Assche [Nate Dailey < Nate dot Dailey at stratus dot com >]
22*44704f69SBart Van Assche */
23*44704f69SBart Van Assche
24*44704f69SBart Van Assche #ifndef _GNU_SOURCE
25*44704f69SBart Van Assche #define _GNU_SOURCE 1
26*44704f69SBart Van Assche #endif
27*44704f69SBart Van Assche
28*44704f69SBart Van Assche #include <unistd.h>
29*44704f69SBart Van Assche #include <fcntl.h>
30*44704f69SBart Van Assche #include <stdio.h>
31*44704f69SBart Van Assche #include <stdlib.h>
32*44704f69SBart Van Assche #include <stdarg.h>
33*44704f69SBart Van Assche #include <stdbool.h>
34*44704f69SBart Van Assche #include <string.h>
35*44704f69SBart Van Assche #include <errno.h>
36*44704f69SBart Van Assche #include <dirent.h>
37*44704f69SBart Van Assche #include <libgen.h>
38*44704f69SBart Van Assche #include <sys/ioctl.h>
39*44704f69SBart Van Assche #include <sys/types.h>
40*44704f69SBart Van Assche #include <sys/stat.h>
41*44704f69SBart Van Assche
42*44704f69SBart Van Assche #ifdef HAVE_CONFIG_H
43*44704f69SBart Van Assche #include "config.h"
44*44704f69SBart Van Assche #endif
45*44704f69SBart Van Assche #include "sg_lib.h"
46*44704f69SBart Van Assche #include "sg_cmds_basic.h"
47*44704f69SBart Van Assche #include "sg_io_linux.h"
48*44704f69SBart Van Assche
49*44704f69SBart Van Assche
50*44704f69SBart Van Assche static const char * version_str = "1.12 20171010";
51*44704f69SBart Van Assche
52*44704f69SBart Van Assche static const char * devfs_id = "/dev/.devfsd";
53*44704f69SBart Van Assche
54*44704f69SBart Van Assche #define NUMERIC_SCAN_DEF true /* set to false to make alpha scan default */
55*44704f69SBart Van Assche
56*44704f69SBart Van Assche #define INQUIRY_RESP_INITIAL_LEN 36
57*44704f69SBart Van Assche #define MAX_SG_DEVS 4096
58*44704f69SBart Van Assche #define PRESENT_ARRAY_SIZE MAX_SG_DEVS
59*44704f69SBart Van Assche
60*44704f69SBart Van Assche static const char * sysfs_sg_dir = "/sys/class/scsi_generic";
61*44704f69SBart Van Assche static char gen_index_arr[PRESENT_ARRAY_SIZE];
62*44704f69SBart Van Assche static int has_sysfs_sg = 0;
63*44704f69SBart Van Assche
64*44704f69SBart Van Assche
65*44704f69SBart Van Assche typedef struct my_map_info
66*44704f69SBart Van Assche {
67*44704f69SBart Van Assche int active;
68*44704f69SBart Van Assche int lin_dev_type;
69*44704f69SBart Van Assche int oth_dev_num;
70*44704f69SBart Van Assche struct sg_scsi_id sg_dat;
71*44704f69SBart Van Assche char vendor[8];
72*44704f69SBart Van Assche char product[16];
73*44704f69SBart Van Assche char revision[4];
74*44704f69SBart Van Assche } my_map_info_t;
75*44704f69SBart Van Assche
76*44704f69SBart Van Assche
77*44704f69SBart Van Assche #define MAX_SD_DEVS (26 + 26*26 + 26*26*26) /* sdX, sdXX, sdXXX */
78*44704f69SBart Van Assche /* (26 + 676 + 17576) = 18278 */
79*44704f69SBart Van Assche #define MAX_SR_DEVS 128
80*44704f69SBart Van Assche #define MAX_ST_DEVS 128
81*44704f69SBart Van Assche #define MAX_OSST_DEVS 128
82*44704f69SBart Van Assche #define MAX_ERRORS 5
83*44704f69SBart Van Assche
84*44704f69SBart Van Assche static my_map_info_t map_arr[MAX_SG_DEVS];
85*44704f69SBart Van Assche
86*44704f69SBart Van Assche #define LIN_DEV_TYPE_UNKNOWN 0
87*44704f69SBart Van Assche #define LIN_DEV_TYPE_SD 1
88*44704f69SBart Van Assche #define LIN_DEV_TYPE_SR 2
89*44704f69SBart Van Assche #define LIN_DEV_TYPE_ST 3
90*44704f69SBart Van Assche #define LIN_DEV_TYPE_SCD 4
91*44704f69SBart Van Assche #define LIN_DEV_TYPE_OSST 5
92*44704f69SBart Van Assche
93*44704f69SBart Van Assche
94*44704f69SBart Van Assche typedef struct my_scsi_idlun {
95*44704f69SBart Van Assche /* why can't userland see this structure ??? */
96*44704f69SBart Van Assche int dev_id;
97*44704f69SBart Van Assche int host_unique_id;
98*44704f69SBart Van Assche } My_scsi_idlun;
99*44704f69SBart Van Assche
100*44704f69SBart Van Assche
101*44704f69SBart Van Assche #define EBUFF_SZ 256
102*44704f69SBart Van Assche static char ebuff[EBUFF_SZ];
103*44704f69SBart Van Assche
104*44704f69SBart Van Assche static void scan_dev_type(const char * leadin, int max_dev, bool do_numeric,
105*44704f69SBart Van Assche int lin_dev_type, int last_sg_ind);
106*44704f69SBart Van Assche
usage()107*44704f69SBart Van Assche static void usage()
108*44704f69SBart Van Assche {
109*44704f69SBart Van Assche printf("Usage: sg_map [-a] [-h] [-i] [-n] [-sd] [-scd or -sr] [-st] "
110*44704f69SBart Van Assche "[-V] [-x]\n");
111*44704f69SBart Van Assche printf(" where:\n");
112*44704f69SBart Van Assche printf(" -a do alphabetic scan (ie sga, sgb, sgc)\n");
113*44704f69SBart Van Assche printf(" -h or -? show this usage message then exit\n");
114*44704f69SBart Van Assche printf(" -i also show device INQUIRY strings\n");
115*44704f69SBart Van Assche printf(" -n do numeric scan (i.e. sg0, sg1, sg2) "
116*44704f69SBart Van Assche "(default)\n");
117*44704f69SBart Van Assche printf(" -sd show mapping to disks\n");
118*44704f69SBart Van Assche printf(" -scd show mapping to cdroms (look for /dev/scd<n>\n");
119*44704f69SBart Van Assche printf(" -sr show mapping to cdroms (look for /dev/sr<n>\n");
120*44704f69SBart Van Assche printf(" -st show mapping to tapes (st and osst devices)\n");
121*44704f69SBart Van Assche printf(" -V print version string then exit\n");
122*44704f69SBart Van Assche printf(" -x also show bus,chan,id,lun and type\n\n");
123*44704f69SBart Van Assche printf("If no '-s*' arguments given then show all mappings. This "
124*44704f69SBart Van Assche "utility\nis DEPRECATED, do not use in Linux 2.6 series or "
125*44704f69SBart Van Assche "later.\n");
126*44704f69SBart Van Assche }
127*44704f69SBart Van Assche
scandir_select(const struct dirent * s)128*44704f69SBart Van Assche static int scandir_select(const struct dirent * s)
129*44704f69SBart Van Assche {
130*44704f69SBart Van Assche int k;
131*44704f69SBart Van Assche
132*44704f69SBart Van Assche if (1 == sscanf(s->d_name, "sg%d", &k)) {
133*44704f69SBart Van Assche if ((k >= 0) && (k < PRESENT_ARRAY_SIZE)) {
134*44704f69SBart Van Assche gen_index_arr[k] = 1;
135*44704f69SBart Van Assche return 1;
136*44704f69SBart Van Assche }
137*44704f69SBart Van Assche }
138*44704f69SBart Van Assche return 0;
139*44704f69SBart Van Assche }
140*44704f69SBart Van Assche
sysfs_sg_scan(const char * dir_name)141*44704f69SBart Van Assche static int sysfs_sg_scan(const char * dir_name)
142*44704f69SBart Van Assche {
143*44704f69SBart Van Assche struct dirent ** namelist;
144*44704f69SBart Van Assche int num, k;
145*44704f69SBart Van Assche
146*44704f69SBart Van Assche num = scandir(dir_name, &namelist, scandir_select, NULL);
147*44704f69SBart Van Assche if (num < 0)
148*44704f69SBart Van Assche return -errno;
149*44704f69SBart Van Assche for (k = 0; k < num; ++k)
150*44704f69SBart Van Assche free(namelist[k]);
151*44704f69SBart Van Assche free(namelist);
152*44704f69SBart Van Assche return num;
153*44704f69SBart Van Assche }
154*44704f69SBart Van Assche
make_dev_name(char * fname,const char * leadin,int k,bool do_numeric)155*44704f69SBart Van Assche static void make_dev_name(char * fname, const char * leadin, int k,
156*44704f69SBart Van Assche bool do_numeric)
157*44704f69SBart Van Assche {
158*44704f69SBart Van Assche char buff[64];
159*44704f69SBart Van Assche int ones,tens,hundreds; /* for lack of a better name */
160*44704f69SBart Van Assche int buff_idx;
161*44704f69SBart Van Assche
162*44704f69SBart Van Assche strcpy(fname, leadin ? leadin : "/dev/sg");
163*44704f69SBart Van Assche if (do_numeric) {
164*44704f69SBart Van Assche sprintf(buff, "%d", k);
165*44704f69SBart Van Assche strcat(fname, buff);
166*44704f69SBart Van Assche }
167*44704f69SBart Van Assche else if (k >= (26 + 26*26 + 26*26*26)) {
168*44704f69SBart Van Assche strcat(fname, "xxxx");
169*44704f69SBart Van Assche }
170*44704f69SBart Van Assche else {
171*44704f69SBart Van Assche ones = k % 26;
172*44704f69SBart Van Assche
173*44704f69SBart Van Assche if ((k - 26) >= 0)
174*44704f69SBart Van Assche tens = ((k-26)/26) % 26;
175*44704f69SBart Van Assche else tens = -1;
176*44704f69SBart Van Assche
177*44704f69SBart Van Assche if ((k - (26 + 26*26)) >= 0)
178*44704f69SBart Van Assche hundreds = ((k - (26 + 26*26))/(26*26)) % 26;
179*44704f69SBart Van Assche else hundreds = -1;
180*44704f69SBart Van Assche
181*44704f69SBart Van Assche buff_idx = 0;
182*44704f69SBart Van Assche if (hundreds >= 0) buff[buff_idx++] = 'a' + (char)hundreds;
183*44704f69SBart Van Assche if (tens >= 0) buff[buff_idx++] = 'a' + (char)tens;
184*44704f69SBart Van Assche buff[buff_idx++] = 'a' + (char)ones;
185*44704f69SBart Van Assche buff[buff_idx] = '\0';
186*44704f69SBart Van Assche strcat(fname, buff);
187*44704f69SBart Van Assche }
188*44704f69SBart Van Assche }
189*44704f69SBart Van Assche
190*44704f69SBart Van Assche
main(int argc,char * argv[])191*44704f69SBart Van Assche int main(int argc, char * argv[])
192*44704f69SBart Van Assche {
193*44704f69SBart Van Assche bool do_all_s = true;
194*44704f69SBart Van Assche bool do_extra = false;
195*44704f69SBart Van Assche bool do_inquiry = false;
196*44704f69SBart Van Assche bool do_numeric = NUMERIC_SCAN_DEF;
197*44704f69SBart Van Assche bool do_osst = false;
198*44704f69SBart Van Assche bool do_scd = false;
199*44704f69SBart Van Assche bool do_sd = false;
200*44704f69SBart Van Assche bool do_sr = false;
201*44704f69SBart Van Assche bool do_st = false;
202*44704f69SBart Van Assche bool eacces_err = false;
203*44704f69SBart Van Assche int sg_fd, res, k;
204*44704f69SBart Van Assche int num_errors = 0;
205*44704f69SBart Van Assche int num_silent = 0;
206*44704f69SBart Van Assche int last_sg_ind = -1;
207*44704f69SBart Van Assche char fname[64];
208*44704f69SBart Van Assche struct stat a_stat;
209*44704f69SBart Van Assche
210*44704f69SBart Van Assche for (k = 1; k < argc; ++k) {
211*44704f69SBart Van Assche if (0 == strcmp("-n", argv[k]))
212*44704f69SBart Van Assche do_numeric = true;
213*44704f69SBart Van Assche else if (0 == strcmp("-a", argv[k]))
214*44704f69SBart Van Assche do_numeric = false;
215*44704f69SBart Van Assche else if (0 == strcmp("-x", argv[k]))
216*44704f69SBart Van Assche do_extra = true;
217*44704f69SBart Van Assche else if (0 == strcmp("-i", argv[k]))
218*44704f69SBart Van Assche do_inquiry = true;
219*44704f69SBart Van Assche else if (0 == strcmp("-sd", argv[k])) {
220*44704f69SBart Van Assche do_sd = true;
221*44704f69SBart Van Assche do_all_s = false;
222*44704f69SBart Van Assche } else if (0 == strcmp("-st", argv[k])) {
223*44704f69SBart Van Assche do_st = true;
224*44704f69SBart Van Assche do_osst = true;
225*44704f69SBart Van Assche do_all_s = false;
226*44704f69SBart Van Assche } else if (0 == strcmp("-sr", argv[k])) {
227*44704f69SBart Van Assche do_sr = true;
228*44704f69SBart Van Assche do_all_s = false;
229*44704f69SBart Van Assche } else if (0 == strcmp("-scd", argv[k])) {
230*44704f69SBart Van Assche do_scd = true;
231*44704f69SBart Van Assche do_all_s = false;
232*44704f69SBart Van Assche } else if (0 == strcmp("-V", argv[k])) {
233*44704f69SBart Van Assche fprintf(stderr, "Version string: %s\n", version_str);
234*44704f69SBart Van Assche exit(0);
235*44704f69SBart Van Assche } else if ((0 == strcmp("-?", argv[k])) ||
236*44704f69SBart Van Assche (0 == strncmp("-h", argv[k], 2))) {
237*44704f69SBart Van Assche printf(
238*44704f69SBart Van Assche "Show mapping from sg devices to other scsi device names\n\n");
239*44704f69SBart Van Assche usage();
240*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
241*44704f69SBart Van Assche } else if (*argv[k] == '-') {
242*44704f69SBart Van Assche printf("Unknown switch: %s\n", argv[k]);
243*44704f69SBart Van Assche usage();
244*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
245*44704f69SBart Van Assche } else if (*argv[k] != '-') {
246*44704f69SBart Van Assche printf("Unknown argument\n");
247*44704f69SBart Van Assche usage();
248*44704f69SBart Van Assche return SG_LIB_SYNTAX_ERROR;
249*44704f69SBart Van Assche }
250*44704f69SBart Van Assche }
251*44704f69SBart Van Assche
252*44704f69SBart Van Assche if ((stat(sysfs_sg_dir, &a_stat) >= 0) && (S_ISDIR(a_stat.st_mode)))
253*44704f69SBart Van Assche has_sysfs_sg = sysfs_sg_scan(sysfs_sg_dir);
254*44704f69SBart Van Assche
255*44704f69SBart Van Assche if (stat(devfs_id, &a_stat) == 0)
256*44704f69SBart Van Assche printf("# Note: the devfs pseudo file system is present\n");
257*44704f69SBart Van Assche
258*44704f69SBart Van Assche for (k = 0, res = 0; (k < MAX_SG_DEVS) && (num_errors < MAX_ERRORS);
259*44704f69SBart Van Assche ++k, res = (sg_fd >= 0) ? close(sg_fd) : 0) {
260*44704f69SBart Van Assche if (res < 0) {
261*44704f69SBart Van Assche snprintf(ebuff, EBUFF_SZ, "Error closing %s ", fname);
262*44704f69SBart Van Assche perror("sg_map: close error");
263*44704f69SBart Van Assche return SG_LIB_FILE_ERROR;
264*44704f69SBart Van Assche }
265*44704f69SBart Van Assche if (has_sysfs_sg) {
266*44704f69SBart Van Assche if (0 == gen_index_arr[k]) {
267*44704f69SBart Van Assche sg_fd = -1;
268*44704f69SBart Van Assche continue;
269*44704f69SBart Van Assche }
270*44704f69SBart Van Assche make_dev_name(fname, "/dev/sg", k, true);
271*44704f69SBart Van Assche } else
272*44704f69SBart Van Assche make_dev_name(fname, "/dev/sg", k, do_numeric);
273*44704f69SBart Van Assche
274*44704f69SBart Van Assche sg_fd = open(fname, O_RDONLY | O_NONBLOCK);
275*44704f69SBart Van Assche if (sg_fd < 0) {
276*44704f69SBart Van Assche if (EBUSY == errno) {
277*44704f69SBart Van Assche map_arr[k].active = -2;
278*44704f69SBart Van Assche continue;
279*44704f69SBart Van Assche }
280*44704f69SBart Van Assche else if ((ENODEV == errno) || (ENOENT == errno) ||
281*44704f69SBart Van Assche (ENXIO == errno)) {
282*44704f69SBart Van Assche ++num_errors;
283*44704f69SBart Van Assche ++num_silent;
284*44704f69SBart Van Assche map_arr[k].active = -1;
285*44704f69SBart Van Assche continue;
286*44704f69SBart Van Assche }
287*44704f69SBart Van Assche else {
288*44704f69SBart Van Assche if (EACCES == errno)
289*44704f69SBart Van Assche eacces_err = true;
290*44704f69SBart Van Assche snprintf(ebuff, EBUFF_SZ, "Error opening %s ", fname);
291*44704f69SBart Van Assche perror(ebuff);
292*44704f69SBart Van Assche ++num_errors;
293*44704f69SBart Van Assche continue;
294*44704f69SBart Van Assche }
295*44704f69SBart Van Assche }
296*44704f69SBart Van Assche res = ioctl(sg_fd, SG_GET_SCSI_ID, &map_arr[k].sg_dat);
297*44704f69SBart Van Assche if (res < 0) {
298*44704f69SBart Van Assche snprintf(ebuff, EBUFF_SZ,
299*44704f69SBart Van Assche "device %s failed on sg ioctl, skip", fname);
300*44704f69SBart Van Assche perror(ebuff);
301*44704f69SBart Van Assche ++num_errors;
302*44704f69SBart Van Assche continue;
303*44704f69SBart Van Assche }
304*44704f69SBart Van Assche if (do_inquiry) {
305*44704f69SBart Van Assche char buff[INQUIRY_RESP_INITIAL_LEN];
306*44704f69SBart Van Assche
307*44704f69SBart Van Assche if (0 == sg_ll_inquiry(sg_fd, false, false, 0, buff, sizeof(buff),
308*44704f69SBart Van Assche true, 0)) {
309*44704f69SBart Van Assche memcpy(map_arr[k].vendor, &buff[8], 8);
310*44704f69SBart Van Assche memcpy(map_arr[k].product, &buff[16], 16);
311*44704f69SBart Van Assche memcpy(map_arr[k].revision, &buff[32], 4);
312*44704f69SBart Van Assche }
313*44704f69SBart Van Assche }
314*44704f69SBart Van Assche map_arr[k].active = 1;
315*44704f69SBart Van Assche map_arr[k].oth_dev_num = -1;
316*44704f69SBart Van Assche last_sg_ind = k;
317*44704f69SBart Van Assche }
318*44704f69SBart Van Assche if ((num_errors >= MAX_ERRORS) && (num_silent < num_errors)) {
319*44704f69SBart Van Assche printf("Stopping because there are too many error\n");
320*44704f69SBart Van Assche if (eacces_err)
321*44704f69SBart Van Assche printf(" root access may be required\n");
322*44704f69SBart Van Assche return SG_LIB_FILE_ERROR;
323*44704f69SBart Van Assche }
324*44704f69SBart Van Assche if (last_sg_ind < 0) {
325*44704f69SBart Van Assche printf("Stopping because no sg devices found\n");
326*44704f69SBart Van Assche }
327*44704f69SBart Van Assche
328*44704f69SBart Van Assche if (do_all_s || do_sd)
329*44704f69SBart Van Assche scan_dev_type("/dev/sd", MAX_SD_DEVS, 0, LIN_DEV_TYPE_SD, last_sg_ind);
330*44704f69SBart Van Assche if (do_all_s || do_sr)
331*44704f69SBart Van Assche scan_dev_type("/dev/sr", MAX_SR_DEVS, 1, LIN_DEV_TYPE_SR, last_sg_ind);
332*44704f69SBart Van Assche if (do_all_s || do_scd)
333*44704f69SBart Van Assche scan_dev_type("/dev/scd", MAX_SR_DEVS, 1, LIN_DEV_TYPE_SCD,
334*44704f69SBart Van Assche last_sg_ind);
335*44704f69SBart Van Assche if (do_all_s || do_st)
336*44704f69SBart Van Assche scan_dev_type("/dev/nst", MAX_ST_DEVS, 1, LIN_DEV_TYPE_ST,
337*44704f69SBart Van Assche last_sg_ind);
338*44704f69SBart Van Assche if (do_all_s || do_osst)
339*44704f69SBart Van Assche scan_dev_type("/dev/osst", MAX_OSST_DEVS, 1, LIN_DEV_TYPE_OSST,
340*44704f69SBart Van Assche last_sg_ind);
341*44704f69SBart Van Assche
342*44704f69SBart Van Assche for (k = 0; k <= last_sg_ind; ++k) {
343*44704f69SBart Van Assche if (has_sysfs_sg) {
344*44704f69SBart Van Assche if (0 == gen_index_arr[k]) {
345*44704f69SBart Van Assche continue;
346*44704f69SBart Van Assche }
347*44704f69SBart Van Assche make_dev_name(fname, "/dev/sg", k, true);
348*44704f69SBart Van Assche } else
349*44704f69SBart Van Assche make_dev_name(fname, "/dev/sg", k, do_numeric);
350*44704f69SBart Van Assche printf("%s", fname);
351*44704f69SBart Van Assche switch (map_arr[k].active)
352*44704f69SBart Van Assche {
353*44704f69SBart Van Assche case -2:
354*44704f69SBart Van Assche printf(do_extra ? " -2 -2 -2 -2 -2" : " busy");
355*44704f69SBart Van Assche break;
356*44704f69SBart Van Assche case -1:
357*44704f69SBart Van Assche printf(do_extra ? " -1 -1 -1 -1 -1" : " not present");
358*44704f69SBart Van Assche break;
359*44704f69SBart Van Assche case 0:
360*44704f69SBart Van Assche printf(do_extra ? " -3 -3 -3 -3 -3" : " some error");
361*44704f69SBart Van Assche break;
362*44704f69SBart Van Assche case 1:
363*44704f69SBart Van Assche if (do_extra)
364*44704f69SBart Van Assche printf(" %d %d %d %d %d", map_arr[k].sg_dat.host_no,
365*44704f69SBart Van Assche map_arr[k].sg_dat.channel, map_arr[k].sg_dat.scsi_id,
366*44704f69SBart Van Assche map_arr[k].sg_dat.lun, map_arr[k].sg_dat.scsi_type);
367*44704f69SBart Van Assche switch (map_arr[k].lin_dev_type)
368*44704f69SBart Van Assche {
369*44704f69SBart Van Assche case LIN_DEV_TYPE_SD:
370*44704f69SBart Van Assche make_dev_name(fname, "/dev/sd" , map_arr[k].oth_dev_num, 0);
371*44704f69SBart Van Assche printf(" %s", fname);
372*44704f69SBart Van Assche break;
373*44704f69SBart Van Assche case LIN_DEV_TYPE_ST:
374*44704f69SBart Van Assche make_dev_name(fname, "/dev/nst" , map_arr[k].oth_dev_num, 1);
375*44704f69SBart Van Assche printf(" %s", fname);
376*44704f69SBart Van Assche break;
377*44704f69SBart Van Assche case LIN_DEV_TYPE_OSST:
378*44704f69SBart Van Assche make_dev_name(fname, "/dev/osst" , map_arr[k].oth_dev_num, 1);
379*44704f69SBart Van Assche printf(" %s", fname);
380*44704f69SBart Van Assche break;
381*44704f69SBart Van Assche case LIN_DEV_TYPE_SR:
382*44704f69SBart Van Assche make_dev_name(fname, "/dev/sr" , map_arr[k].oth_dev_num, 1);
383*44704f69SBart Van Assche printf(" %s", fname);
384*44704f69SBart Van Assche break;
385*44704f69SBart Van Assche case LIN_DEV_TYPE_SCD:
386*44704f69SBart Van Assche make_dev_name(fname, "/dev/scd" , map_arr[k].oth_dev_num, 1);
387*44704f69SBart Van Assche printf(" %s", fname);
388*44704f69SBart Van Assche break;
389*44704f69SBart Van Assche default:
390*44704f69SBart Van Assche break;
391*44704f69SBart Van Assche }
392*44704f69SBart Van Assche if (do_inquiry)
393*44704f69SBart Van Assche printf(" %.8s %.16s %.4s", map_arr[k].vendor,
394*44704f69SBart Van Assche map_arr[k].product, map_arr[k].revision);
395*44704f69SBart Van Assche break;
396*44704f69SBart Van Assche default:
397*44704f69SBart Van Assche printf(" bad logic\n");
398*44704f69SBart Van Assche break;
399*44704f69SBart Van Assche }
400*44704f69SBart Van Assche printf("\n");
401*44704f69SBart Van Assche }
402*44704f69SBart Van Assche return 0;
403*44704f69SBart Van Assche }
404*44704f69SBart Van Assche
find_dev_in_sg_arr(My_scsi_idlun * my_idlun,int host_no,int last_sg_ind)405*44704f69SBart Van Assche static int find_dev_in_sg_arr(My_scsi_idlun * my_idlun, int host_no,
406*44704f69SBart Van Assche int last_sg_ind)
407*44704f69SBart Van Assche {
408*44704f69SBart Van Assche int k;
409*44704f69SBart Van Assche struct sg_scsi_id * sidp;
410*44704f69SBart Van Assche
411*44704f69SBart Van Assche for (k = 0; k <= last_sg_ind; ++k) {
412*44704f69SBart Van Assche sidp = &(map_arr[k].sg_dat);
413*44704f69SBart Van Assche if ((host_no == sidp->host_no) &&
414*44704f69SBart Van Assche ((my_idlun->dev_id & 0xff) == sidp->scsi_id) &&
415*44704f69SBart Van Assche (((my_idlun->dev_id >> 8) & 0xff) == sidp->lun) &&
416*44704f69SBart Van Assche (((my_idlun->dev_id >> 16) & 0xff) == sidp->channel))
417*44704f69SBart Van Assche return k;
418*44704f69SBart Van Assche }
419*44704f69SBart Van Assche return -1;
420*44704f69SBart Van Assche }
421*44704f69SBart Van Assche
scan_dev_type(const char * leadin,int max_dev,bool do_numeric,int lin_dev_type,int last_sg_ind)422*44704f69SBart Van Assche static void scan_dev_type(const char * leadin, int max_dev, bool do_numeric,
423*44704f69SBart Van Assche int lin_dev_type, int last_sg_ind)
424*44704f69SBart Van Assche {
425*44704f69SBart Van Assche int k, res, ind, sg_fd = 0;
426*44704f69SBart Van Assche int num_errors = 0;
427*44704f69SBart Van Assche int num_silent = 0;
428*44704f69SBart Van Assche int host_no = -1;
429*44704f69SBart Van Assche My_scsi_idlun my_idlun;
430*44704f69SBart Van Assche char fname[64];
431*44704f69SBart Van Assche
432*44704f69SBart Van Assche for (k = 0, res = 0; (k < max_dev) && (num_errors < MAX_ERRORS);
433*44704f69SBart Van Assche ++k, res = (sg_fd >= 0) ? close(sg_fd) : 0) {
434*44704f69SBart Van Assche
435*44704f69SBart Van Assche /* ignore close() errors */
436*44704f69SBart Van Assche #if 0
437*44704f69SBart Van Assche if (res < 0) {
438*44704f69SBart Van Assche snprintf(ebuff, EBUFF_SZ, "Error closing %s ", fname);
439*44704f69SBart Van Assche perror("sg_map: close error");
440*44704f69SBart Van Assche #ifndef IGN_CLOSE_ERR
441*44704f69SBart Van Assche return;
442*44704f69SBart Van Assche #else
443*44704f69SBart Van Assche ++num_errors;
444*44704f69SBart Van Assche sg_fd = 0;
445*44704f69SBart Van Assche #endif
446*44704f69SBart Van Assche }
447*44704f69SBart Van Assche #endif
448*44704f69SBart Van Assche make_dev_name(fname, leadin, k, do_numeric);
449*44704f69SBart Van Assche #ifdef DEBUG
450*44704f69SBart Van Assche printf ("Trying %s: ", fname);
451*44704f69SBart Van Assche #endif
452*44704f69SBart Van Assche
453*44704f69SBart Van Assche sg_fd = open(fname, O_RDONLY | O_NONBLOCK);
454*44704f69SBart Van Assche if (sg_fd < 0) {
455*44704f69SBart Van Assche #ifdef DEBUG
456*44704f69SBart Van Assche printf ("ERROR %i\n", errno);
457*44704f69SBart Van Assche #endif
458*44704f69SBart Van Assche if (EBUSY == errno) {
459*44704f69SBart Van Assche printf("Device %s is busy\n", fname);
460*44704f69SBart Van Assche ++num_errors;
461*44704f69SBart Van Assche } else if ((ENODEV == errno) || (ENXIO == errno)) {
462*44704f69SBart Van Assche ++num_errors;
463*44704f69SBart Van Assche ++num_silent;
464*44704f69SBart Van Assche } else if (ENOENT != errno) { /* ignore ENOENT for sparse names */
465*44704f69SBart Van Assche snprintf(ebuff, EBUFF_SZ, "Error opening %s ", fname);
466*44704f69SBart Van Assche perror(ebuff);
467*44704f69SBart Van Assche ++num_errors;
468*44704f69SBart Van Assche }
469*44704f69SBart Van Assche continue;
470*44704f69SBart Van Assche }
471*44704f69SBart Van Assche
472*44704f69SBart Van Assche res = ioctl(sg_fd, SCSI_IOCTL_GET_IDLUN, &my_idlun);
473*44704f69SBart Van Assche if (res < 0) {
474*44704f69SBart Van Assche snprintf(ebuff, EBUFF_SZ,
475*44704f69SBart Van Assche "device %s failed on scsi ioctl(idlun), skip", fname);
476*44704f69SBart Van Assche perror(ebuff);
477*44704f69SBart Van Assche ++num_errors;
478*44704f69SBart Van Assche #ifdef DEBUG
479*44704f69SBart Van Assche printf ("Couldn't get IDLUN!\n");
480*44704f69SBart Van Assche #endif
481*44704f69SBart Van Assche continue;
482*44704f69SBart Van Assche }
483*44704f69SBart Van Assche res = ioctl(sg_fd, SCSI_IOCTL_GET_BUS_NUMBER, &host_no);
484*44704f69SBart Van Assche if (res < 0) {
485*44704f69SBart Van Assche snprintf(ebuff, EBUFF_SZ,
486*44704f69SBart Van Assche "device %s failed on scsi ioctl(bus_number), skip", fname);
487*44704f69SBart Van Assche perror(ebuff);
488*44704f69SBart Van Assche ++num_errors;
489*44704f69SBart Van Assche #ifdef DEBUG
490*44704f69SBart Van Assche printf ("Couldn't get BUS!\n");
491*44704f69SBart Van Assche #endif
492*44704f69SBart Van Assche continue;
493*44704f69SBart Van Assche }
494*44704f69SBart Van Assche #ifdef DEBUG
495*44704f69SBart Van Assche printf ("%i(%x) %i %i %i %i\n", host_no, my_idlun.host_unique_id,
496*44704f69SBart Van Assche (my_idlun.dev_id>>24)&0xff, (my_idlun.dev_id>>16)&0xff,
497*44704f69SBart Van Assche (my_idlun.dev_id>>8)&0xff, my_idlun.dev_id&0xff);
498*44704f69SBart Van Assche #endif
499*44704f69SBart Van Assche ind = find_dev_in_sg_arr(&my_idlun, host_no, last_sg_ind);
500*44704f69SBart Van Assche if (ind >= 0) {
501*44704f69SBart Van Assche map_arr[ind].oth_dev_num = k;
502*44704f69SBart Van Assche map_arr[ind].lin_dev_type = lin_dev_type;
503*44704f69SBart Van Assche }
504*44704f69SBart Van Assche else
505*44704f69SBart Van Assche printf("Strange, could not find device %s mapped to sg device??\n",
506*44704f69SBart Van Assche fname);
507*44704f69SBart Van Assche }
508*44704f69SBart Van Assche }
509