1 /* @(#)scsi_scan.c	1.38 17/08/06 Copyright 1997-2017 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)scsi_scan.c	1.38 17/08/06 Copyright 1997-2017 J. Schilling";
6 #endif
7 /*
8  *	Scan SCSI Bus.
9  *	Stolen from sformat. Need a more general form to
10  *	re-use it in sformat too.
11  *
12  *	Copyright (c) 1997-2017 J. Schilling
13  */
14 /*
15  * The contents of this file are subject to the terms of the
16  * Common Development and Distribution License, Version 1.0 only
17  * (the "License").  You may not use this file except in compliance
18  * with the License.
19  *
20  * See the file CDDL.Schily.txt in this distribution for details.
21  * A copy of the CDDL is also available via the Internet at
22  * http://www.opensource.org/licenses/cddl1.txt
23  *
24  * When distributing Covered Code, include this CDDL HEADER in each
25  * file and include the License file CDDL.Schily.txt from this distribution.
26  */
27 
28 #include <schily/mconfig.h>
29 #include <schily/stdio.h>
30 #include <schily/stdlib.h>
31 #include <schily/standard.h>
32 #include <schily/btorder.h>
33 #include <schily/errno.h>
34 #include <schily/schily.h>
35 #include <schily/nlsdefs.h>
36 
37 #include <scg/scgcmd.h>
38 #include <scg/scsidefs.h>
39 #include <scg/scsireg.h>
40 #include <scg/scsitransp.h>
41 
42 #include "scsi_scan.h"
43 #include "cdrecord.h"
44 
45 LOCAL	void	print_product		__PR((FILE *f, struct scsi_inquiry *ip));
46 EXPORT	int	select_target		__PR((SCSI *scgp, FILE *f));
47 EXPORT	int	find_target		__PR((SCSI *scgp, int type, int idx));
48 LOCAL	int	_select_target		__PR((SCSI *scgp, FILE *f, int type, int idx));
49 #ifdef	__ready__
50 LOCAL	int	select_unit		__PR((SCSI *scgp, FILE *f));
51 #endif
52 
53 LOCAL void
print_product(f,ip)54 print_product(f, ip)
55 	FILE			*f;
56 	struct	scsi_inquiry	*ip;
57 {
58 	fprintf(f, "'%.8s' ", ip->inq_vendor_info);
59 	fprintf(f, "'%.16s' ", ip->inq_prod_ident);
60 	fprintf(f, "'%.4s' ", ip->inq_prod_revision);
61 	if (ip->add_len < 31) {
62 		fprintf(f, "NON CCS ");
63 	}
64 	scg_fprintdev(f, ip);
65 }
66 
67 EXPORT int
select_target(scgp,f)68 select_target(scgp, f)
69 	SCSI	*scgp;
70 	FILE	*f;
71 {
72 	return (_select_target(scgp, f, -1, -1));
73 }
74 
75 EXPORT int
find_target(scgp,type,idx)76 find_target(scgp, type, idx)
77 	SCSI	*scgp;
78 	int	type;
79 	int	idx;
80 {
81 	return (_select_target(scgp, (FILE *)NULL, type, idx));
82 }
83 
84 LOCAL int
_select_target(scgp,f,type,idx)85 _select_target(scgp, f, type, idx)
86 	SCSI	*scgp;
87 	FILE	*f;
88 	int	type;
89 	int	idx;
90 {
91 	int	initiator;
92 	int	cscsibus = scg_scsibus(scgp);
93 	int	ctarget  = scg_target(scgp);
94 	int	clun	 = scg_lun(scgp);
95 	int	numbus	 = scg_numbus(scgp);
96 	int	n;
97 	int	low	= -1;
98 	int	high	= -1;
99 	int	amt	= -1;
100 	int	bus;
101 	int	tgt;
102 	int	lun = 0;
103 	int	err;
104 	BOOL	have_tgt;
105 
106 	if (numbus < 0)
107 		numbus = 1024;
108 	scgp->silent++;
109 
110 	for (bus = 0; bus < numbus; bus++) {
111 		scg_settarget(scgp, bus, 0, 0);
112 
113 		if (!scg_havebus(scgp, bus))
114 			continue;
115 
116 		initiator = scg_initiator_id(scgp);
117 		if (f)
118 			fprintf(f, "scsibus%d:\n", bus);
119 
120 		for (tgt = 0; tgt < 16; tgt++) {
121 			n = bus*100 + tgt;
122 
123 			scg_settarget(scgp, bus, tgt, lun);
124 			seterrno(0);
125 			have_tgt = unit_ready(scgp) || scgp->scmd->error != SCG_FATAL;
126 			err = geterrno();
127 			if (err == EPERM || err == EACCES)
128 				return (-1);
129 
130 			if (!have_tgt && tgt > 7) {
131 				if (scgp->scmd->ux_errno == EINVAL)
132 					break;
133 				continue;
134 			}
135 			if (f) {
136 #ifdef	FMT
137 				if (print_disknames(bus, tgt, -1) < 8)
138 					fprintf(f, "\t");
139 				else
140 					fprintf(f, " ");
141 #else
142 				fprintf(f, "\t");
143 #endif
144 				if (fprintf(f, "%d,%d,%d", bus, tgt, lun) < 8)
145 					fprintf(f, "\t");
146 				else
147 					fprintf(f, " ");
148 				fprintf(f, "%3d) ", n);
149 			}
150 			if (tgt == initiator) {
151 				if (f)
152 					fprintf(f, "HOST ADAPTOR\n");
153 				continue;
154 			}
155 			if (!have_tgt) {
156 				/*
157 				 * Hack: fd -> -2 means no access
158 				 */
159 				if (f) {
160 					fprintf(f, "%c\n",
161 						scgp->fd == -2 ? '?':'*');
162 				}
163 				continue;
164 			}
165 			if (low < 0)
166 				low = n;
167 			high = n;
168 
169 			getdev(scgp, FALSE);
170 			if (f)
171 				print_product(f, scgp->inq);
172 			if (type >= 0 && scgp->inq->type == type) {
173 				amt++;
174 				if (amt == 0)	/* amt starts at -1 */
175 					amt++;
176 				if (amt == idx) {
177 					scgp->silent--;
178 					return (amt);
179 				}
180 			} else if (type < 0) {
181 				amt++;
182 			}
183 			if (amt == 0)	/* amt starts at -1 */
184 				amt++;
185 		}
186 	}
187 	scgp->silent--;
188 
189 	if (low < 0) {
190 		errmsgno(EX_BAD, _("No target found.\n"));
191 		return (0);
192 	}
193 	n = -1;
194 #ifdef	FMT
195 	getint(_("Select target"), &n, low, high);
196 	bus = n/100;
197 	tgt = n%100;
198 	scg_settarget(scgp, bus, tgt, lun);
199 	return (select_unit(scgp));
200 #else
201 	scg_settarget(scgp, cscsibus, ctarget, clun);
202 	return (amt);
203 #endif
204 }
205 
206 #ifdef	__ready__
207 LOCAL int
select_unit(scgp,f)208 select_unit(scgp, f)
209 	SCSI	*scgp;
210 	FILE	*f;
211 {
212 	int	initiator;
213 	int	clun	= scg_lun(scgp);
214 	int	low	= -1;
215 	int	high	= -1;
216 	int	lun;
217 
218 	scgp->silent++;
219 
220 	fprintf(f, _("scsibus%d target %d:\n"), scg_scsibus(scgp), scg_target(scgp));
221 
222 	initiator = scg_initiator_id(scgp);
223 	for (lun = 0; lun < 8; lun++) {
224 
225 #ifdef	FMT
226 		if (print_disknames(scg_scsibus(scgp), scg_target(scgp), lun) < 8)
227 			fprintf(f, "\t");
228 		else
229 			fprintf(f, " ");
230 #else
231 		fprintf(f, "\t");
232 #endif
233 		if (fprintf(f, "%d,%d,%d", scg_scsibus(scgp), scg_target(scgp), lun) < 8)
234 			fprintf(f, "\t");
235 		else
236 			fprintf(f, " ");
237 		fprintf(f, "%3d) ", lun);
238 		if (scg_target(scgp) == initiator) {
239 			fprintf(f, "HOST ADAPTOR\n");
240 			continue;
241 		}
242 		scg_settarget(scgp, scg_scsibus(scgp), scg_target(scgp), lun);
243 		if (!unit_ready(scgp) && scgp->scmd->error == SCG_FATAL) {
244 			fprintf(f, "*\n");
245 			continue;
246 		}
247 		if (unit_ready(scgp)) {
248 			/* non extended sense illegal lun */
249 			if (scgp->scmd->sense.code == 0x25) {
250 				fprintf(f, "BAD UNIT\n");
251 				continue;
252 			}
253 		}
254 		if (low < 0)
255 			low = lun;
256 		high = lun;
257 
258 		getdev(scgp, FALSE);
259 		print_product(f, scgp->inq);
260 	}
261 	scgp->silent--;
262 
263 	if (low < 0) {
264 		errmsgno(EX_BAD, _("No lun found.\n"));
265 		return (0);
266 	}
267 	lun = -1;
268 #ifdef	FMT
269 	getint(_("Select lun"), &lun, low, high);
270 	scg_settarget(scgp, scg_scsibus(scgp), scg_target(scgp), lun);
271 	format_one(scgp);
272 	return (1);
273 #else
274 	scg_settarget(scgp, scg_scsibus(scgp), scg_target(scgp), clun);
275 	return (1);
276 #endif
277 }
278 #endif	/* __ready__ */
279