1 /* @(#)scsi-linux-ata.c	1.16 13/05/28 Copyright 2002-2013 J. Schilling */
2 #ifndef lint
3 static	char ata_sccsid[] =
4 	"@(#)scsi-linux-ata.c	1.16 13/05/28 Copyright 2002-2013 J. Schilling";
5 #endif
6 /*
7  *	Interface for Linux generic SCSI implementation (sg).
8  *
9  *	This inteface is ised with dev=ATAPI:b,t,l
10  *
11  *	This is the interface for the broken Linux SCSI generic driver.
12  *	This is a hack, that tries to emulate the functionality
13  *	of the scg driver.
14  *
15  *	Warning: you may change this source, but if you do that
16  *	you need to change the _scg_version and _scg_auth* string below.
17  *	You may not return "schily" for an SCG_AUTHOR request anymore.
18  *	Choose your name instead of "schily" and make clear that the version
19  *	string is related to a modified source.
20  *
21  *	Copyright (c) 2002-2013 J. Schilling
22  *
23  *	Thanks to Alexander Kern <alex.kern@gmx.de> for the idea and first
24  *	code fragments for supporting the CDROM_SEND_PACKET ioctl() from
25  *	the cdrom.c kernel driver. Please note that this interface in priciple
26  *	is completely unneeded but the Linux kernel is just a cluster of
27  *	code and does not support planned orthogonal interface systems.
28  *	For this reason we need CDROM_SEND_PACKET in order to work around a
29  *	bug in the linux kernel that prevents to use PCATA drives because
30  *	the kernel panics if you try to put ide-scsi on top of the PCATA
31  *	driver.
32  */
33 /*
34  * The contents of this file are subject to the terms of the
35  * Common Development and Distribution License, Version 1.0 only
36  * (the "License").  You may not use this file except in compliance
37  * with the License.
38  *
39  * See the file CDDL.Schily.txt in this distribution for details.
40  * A copy of the CDDL is also available via the Internet at
41  * http://www.opensource.org/licenses/cddl1.txt
42  *
43  * The following exceptions apply:
44  * CDDL �3.6 needs to be replaced by: "You may create a Larger Work by
45  * combining Covered Software with other code if all other code is governed by
46  * the terms of a license that is OSI approved (see www.opensource.org) and
47  * you may distribute the Larger Work as a single product. In such a case,
48  * You must make sure the requirements of this License are fulfilled for
49  * the Covered Software."
50  *
51  * When distributing Covered Code, include this CDDL HEADER in each
52  * file and include the License file CDDL.Schily.txt from this distribution.
53  */
54 
55 #ifdef	USE_ATAPI
56 
57 LOCAL	char	_scg_atrans_version[] = "scsi-linux-ata.c-1.16";	/* The version for ATAPI transport*/
58 
59 LOCAL	char *	scgo_aversion	__PR((SCSI *scgp, int what));
60 LOCAL	int	scgo_ahelp	__PR((SCSI *scgp, FILE *f));
61 LOCAL	int	scgo_aopen	__PR((SCSI *scgp, char *device));
62 LOCAL	int	scgo_aclose	__PR((SCSI *scgp));
63 LOCAL	long	scgo_amaxdma	__PR((SCSI *scgp, long amt));
64 LOCAL	int	scgo_anumbus	__PR((SCSI *scgp));
65 LOCAL	BOOL	scgo_ahavebus	__PR((SCSI *scgp, int));
66 LOCAL	int	scgo_afileno	__PR((SCSI *scgp, int, int, int));
67 LOCAL	int	scgo_ainitiator_id __PR((SCSI *scgp));
68 LOCAL	int	scgo_aisatapi	__PR((SCSI *scgp));
69 LOCAL	int	scgo_areset	__PR((SCSI *scgp, int what));
70 LOCAL	int	scgo_asend	__PR((SCSI *scgp));
71 
72 LOCAL scg_ops_t atapi_ops = {
73 	scgo_asend,
74 	scgo_aversion,
75 	scgo_ahelp,
76 	scgo_aopen,
77 	scgo_aclose,
78 	scgo_amaxdma,
79 	scgo_getbuf,		/* Shared with SG driver */
80 	scgo_freebuf,		/* Shared with SG driver */
81 	scgo_anumbus,
82 	scgo_ahavebus,
83 	scgo_afileno,
84 	scgo_ainitiator_id,
85 	scgo_aisatapi,
86 	scgo_areset,
87 };
88 
89 #define	HOST_EMPTY	0xF
90 #define	HOST_SCSI	0x0
91 #define	HOST_IDE	0x1
92 #define	HOST_USB	0x2
93 #define	HOST_IEEE1389	0x3
94 #define	HOST_PARALLEL	0x4
95 #define	HOST_OTHER	0xE
96 
97 
98 #define	typlocal(p, atapibus)		scglocal(p)->bc[atapibus].typ
99 #define	buslocal(p, atapibus)		scglocal(p)->bc[atapibus].bus
100 #define	hostlocal(p, atapibus)		scglocal(p)->bc[atapibus].host
101 
102 #define	MAX_DMA_ATA (131072-1)	/* EINVAL (hart) ENOMEM (weich) bei mehr ... */
103 				/* Bei fehlerhaftem Sense Pointer kommt EFAULT */
104 
105 LOCAL int scgo_send		__PR((SCSI * scgp));
106 LOCAL BOOL sg_amapdev		__PR((SCSI * scgp, int f, char *device, int *bus,
107 					int *target, int *lun));
108 LOCAL BOOL sg_amapdev_scsi	__PR((SCSI * scgp, int f, int *busp, int *tgtp,
109 					int *lunp, int *chanp, int *inop));
110 LOCAL int scgo_aget_first_free_atapibus __PR((SCSI * scgp, int subsystem,
111 					int host, int bus));
112 LOCAL int scgo_amerge		__PR((char *path, char *readedlink,
113 					char *buffer, int buflen));
114 
115 /*
116  * uncomment this when you will get a debug file #define DEBUG
117  */
118 #ifdef DEBUG
119 #define	LOGFILE "scsi-linux-ata.log"
120 #define	log(a)	sglog a
121 
122 LOCAL	void	sglog		__PR((const char *fmt, ...));
123 
124 #include <schily/varargs.h>
125 
126 /* VARARGS1 */
127 #ifdef	PROTOTYPES
128 LOCAL void
sglog(const char * fmt,...)129 sglog(const char *fmt, ...)
130 #else
131 LOCAL void
132 error(fmt, va_alist)
133 	char	*fmt;
134 	va_dcl
135 #endif
136 {
137 	va_list	args;
138 	FILE	*f	 = fopen(LOGFILE, "a");
139 
140 	if (f == NULL)
141 		return;
142 
143 #ifdef	PROTOTYPES
144 	va_start(args, fmt);
145 #else
146 	va_start(args);
147 #endif
148 	js_fprintf(f, "%r", fmt, args);
149 	va_end(args);
150 	fclose(f);
151 }
152 #else
153 #define	log(a)
154 #endif	/* DEBUG */
155 
156 LOCAL	int	scan_internal __PR((SCSI * scgp, int *fatal));
157 
158 /*
159  * Return version information for the low level SCSI transport code.
160  * This has been introduced to make it easier to trace down problems
161  * in applications.
162  */
163 LOCAL char *
scgo_aversion(scgp,what)164 scgo_aversion(scgp, what)
165 	SCSI	*scgp;
166 	int	what;
167 {
168 	if (scgp != (SCSI *)0) {
169 		switch (what) {
170 
171 		case SCG_VERSION:
172 			return (_scg_atrans_version);
173 		/*
174 		 * If you changed this source, you are not allowed to
175 		 * return "schily" for the SCG_AUTHOR request.
176 		 */
177 		case SCG_AUTHOR:
178 			return (_scg_auth_schily);
179 		case SCG_SCCS_ID:
180 			return (ata_sccsid);
181 		}
182 	}
183 	return ((char *)0);
184 }
185 
186 LOCAL int
scgo_ahelp(scgp,f)187 scgo_ahelp(scgp, f)
188 	SCSI	*scgp;
189 	FILE	*f;
190 {
191 	__scg_help(f, "ATA", "ATA Packet specific SCSI transport",
192 		"ATAPI:", "bus,target,lun", "ATAPI:1,2,0", TRUE, FALSE);
193 	return (0);
194 }
195 
196 LOCAL int
scgo_aopen(scgp,device)197 scgo_aopen(scgp, device)
198 	SCSI	*scgp;
199 	char	*device;
200 {
201 	int	bus = scg_scsibus(scgp);
202 	int	target = scg_target(scgp);
203 	int	lun = scg_lun(scgp);
204 
205 	register int	f;
206 	register int	b;
207 	register int	t;
208 	register int	l;
209 		int	nopen = 0;
210 
211 	if (scgp->overbose) {
212 		error("Warning: dev=ATA: is preferred over dev=ATAPI:.\n");
213 		error("Warning: Using ATA Packet interface.\n");
214 	}
215 	if (scgp->overbose) {
216 		error("Warning: The related Linux kernel interface code seems to be unmaintained.\n");
217 		error("Warning: There is absolutely NO DMA, operations thus are slow.\n");
218 	}
219 
220 	log(("\n<<<<<<<<<<<<<<<<  LOGGING ON >>>>>>>>>>>>>>>>>\n"));
221 	if (bus >= MAX_ATAPI_HOSTS || target >= MAX_TGT || lun >= MAX_LUN) {
222 		errno = EINVAL;
223 		if (scgp->errstr)
224 			js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
225 				"Illegal value for bus, target or lun '%d,%d,%d'",
226 				bus, target, lun);
227 
228 		return (-1);
229 	}
230 
231 	if (scgp->local == NULL) {
232 		scgp->local = malloc(sizeof (struct scg_local));
233 		if (scgp->local == NULL) {
234 			return (0);
235 		}
236 
237 		scglocal(scgp)->scgfile = -1;
238 		scglocal(scgp)->pgbus = -2;
239 		scglocal(scgp)->SCSIbuf = (char *)-1;
240 		scglocal(scgp)->pack_id = 5;
241 		scglocal(scgp)->drvers = -1;
242 		scglocal(scgp)->isold = -1;
243 		scglocal(scgp)->xbufsize = 0L;
244 		scglocal(scgp)->xbuf = NULL;
245 
246 
247 		for (b = 0; b < MAX_ATAPI_HOSTS; b++) {
248 			typlocal(scgp, b) = HOST_EMPTY;
249 			for (t = 0; t < MAX_TGT; t++) {
250 				for (l = 0; l < MAX_LUN; l++)
251 					scglocal(scgp)->scgfiles[b][t][l] = (short) -1;
252 			}
253 		}
254 	}
255 
256 	if (device != NULL && strcmp(device, "ATAPI") == 0)
257 		goto atascan;
258 
259 	/* if not scanning */
260 	if ((device != NULL && *device != '\0') || (bus == -2 && target == -2))
261 		goto openbydev;
262 
263 atascan:
264 	if (scan_internal(scgp, &nopen)) {
265 		if (scgp->errstr)
266 			js_printf(scgp->errstr, "INFO: scan_internal(...) failed");
267 		return (-1);
268 	}
269 	return (nopen);
270 
271 openbydev:
272 	if (device != NULL && strncmp(device, "ATAPI:", 6) == 0)
273 		device += 6;
274 	if (scgp->debug > 3) {
275 		js_fprintf((FILE *) scgp->errfile, "INFO: do scgo_open openbydev");
276 	}
277 	if (device != NULL && *device != '\0') {
278 		int	atapi_bus,
279 			starget,
280 			slun;
281 
282 		f = open(device, O_RDONLY | O_NONBLOCK);
283 
284 		if (f < 0) {
285 			if (scgp->errstr)
286 				js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
287 					"Cannot open '%s'", device);
288 			return (0);
289 		}
290 		if (sg_amapdev(scgp, f, device, &atapi_bus, &starget, &slun)) {
291 			scg_settarget(scgp, atapi_bus, starget, slun);
292 			return (++nopen);
293 		}
294 	}
295 	return (nopen);
296 }
297 
298 LOCAL int
scan_internal(scgp,nopen)299 scan_internal(scgp, nopen)
300 	SCSI	*scgp;
301 	int	*nopen;
302 {
303 	int	i,
304 		f;
305 	int	atapi_bus,
306 		target,
307 		lun;
308 	char	device[128];
309 	/*
310 	 * try always with devfs
311 	 * unfortunatelly the solution with test of existing
312 	 * of '/dev/.devfsd' don't work, because it root.root 700
313 	 * and i don't like run suid root
314 	 */
315 	BOOL	DEVFS = TRUE;
316 
317 	if (DEVFS) {
318 		for (i = 0; ; i++) {
319 			sprintf(device, "/dev/cdroms/cdrom%i", i);
320 			if ((f = open(device, O_RDONLY | O_NONBLOCK)) < 0) {
321 				if (errno != ENOENT && errno != ENXIO && errno != ENODEV && errno != EACCES) {
322 					if (scgp->debug > 4) {
323 						js_fprintf((FILE *) scgp->errfile,
324 						"try open(%s) return %i, errno %i, cancel\n", device, f, errno);
325 					}
326 					return (-2);
327 				} else if (errno == ENOENT || errno == ENODEV) {
328 					if (scgp->debug > 4) {
329 						js_fprintf((FILE *) scgp->errfile,
330 						"try open(%s) return %i, errno %i\n", device, f, errno);
331 					}
332 					if (0 == i) {
333 						DEVFS = FALSE;
334 						if (scgp->debug > 4) {
335 							js_fprintf((FILE *) scgp->errfile,
336 							"DEVFS not detected, continuing with old dev\n");
337 						}
338 					}
339 					break;
340 				}
341 				if (scgp->debug > 4) {
342 					if (errno == EACCES) {
343 						js_fprintf((FILE *) scgp->errfile,
344 						"errno (EACCESS), you don't have the needed rights for %s\n",
345 						device);
346 					}
347 					js_fprintf((FILE *) scgp->errfile,
348 					"try open(%s) return %i, errno %i, trying next cdrom\n",
349 					device, f, errno);
350 				}
351 			} else {
352 				if (scgp->debug > 4) {
353 					js_fprintf((FILE *) scgp->errfile,
354 					"try open(%s) return %i errno %i calling sg_mapdev(...)\n",
355 					device, f, errno);
356 				}
357 				if (sg_amapdev(scgp, f, device, &atapi_bus, &target, &lun)) {
358 					(++(*nopen));
359 				} else {
360 					close(f);
361 				}
362 			}
363 		}
364 	}
365 	if (!DEVFS) {
366 		/* for /dev/sr0 - /dev/sr? */
367 		for (i = 0; ; i++) {
368 			sprintf(device, "/dev/sr%i", i);
369 			if ((f = open(device, O_RDONLY | O_NONBLOCK)) < 0) {
370 				if (errno != ENOENT && errno != ENXIO && errno != ENODEV && errno != EACCES) {
371 					if (scgp->debug > 4) {
372 						js_fprintf((FILE *) scgp->errfile,
373 						"try open(%s) return %i, errno %i, cancel\n",
374 						device, f, errno);
375 					}
376 					return (-2);
377 				} else if (errno == ENOENT || errno == ENODEV) {
378 					break;
379 				}
380 			} else {
381 				if (sg_amapdev(scgp, f, device, &atapi_bus, &target, &lun)) {
382 					(++(*nopen));
383 				} else {
384 					close(f);
385 				}
386 			}
387 		}
388 
389 		/* for /dev/hda - /dev/hdz */
390 		for (i = 'a'; i <= 'z'; i++) {
391 			sprintf(device, "/dev/hd%c", i);
392 			if ((f = open(device, O_RDONLY | O_NONBLOCK)) < 0) {
393 				if (errno != ENOENT && errno != ENXIO && errno != EACCES) {
394 					if (scgp->debug > 4) {
395 						js_fprintf((FILE *) scgp->errfile,
396 						"try open(%s) return %i, errno %i, cancel\n",
397 						device, f, errno);
398 					}
399 					return (-2);
400 				} else if (errno == ENOENT || errno == ENODEV) {
401 					break;
402 				}
403 			} else {
404 				/* ugly hack, make better, when you can. Alex */
405 				if (0 > ioctl(f, CDROM_DRIVE_STATUS, CDSL_CURRENT)) {
406 					if (scgp->debug > 4) {
407 						js_fprintf((FILE *) scgp->errfile,
408 						"%s is not a cdrom, skipping\n",
409 						device);
410 					}
411 					close(f);
412 				} else if (sg_amapdev(scgp, f, device, &atapi_bus, &target, &lun)) {
413 					(++(*nopen));
414 				} else {
415 					close(f);
416 				}
417 			}
418 		}
419 	}
420 	return (0);
421 }
422 
423 LOCAL int
scgo_aclose(scgp)424 scgo_aclose(scgp)
425 	SCSI	*scgp;
426 {
427 	register int	f;
428 	register int	h;
429 	register int	t;
430 	register int	l;
431 
432 	if (scgp->local == NULL)
433 		return (-1);
434 
435 	for (h = 0; h < MAX_ATAPI_HOSTS; h++) {
436 		typlocal(scgp, h) = (HOST_EMPTY);
437 		for (t = 0; t < MAX_TGT; t++) {
438 			for (l = 0; l < MAX_LUN; l++) {
439 				f = scglocal(scgp)->scgfiles[h][t][l];
440 				if (f >= 0)
441 					close(f);
442 				scglocal(scgp)->scgfiles[h][t][l] = (short) -1;
443 			}
444 		}
445 	}
446 
447 	if (scglocal(scgp)->xbuf != NULL) {
448 		free(scglocal(scgp)->xbuf);
449 		scglocal(scgp)->xbufsize = 0L;
450 		scglocal(scgp)->xbuf = NULL;
451 	}
452 	log(("<<<<<<<<<<<<<<<<  LOGGING OFF >>>>>>>>>>>>>>>>>\n\n"));
453 	return (0);
454 }
455 
456 LOCAL int
scgo_aget_first_free_atapibus(scgp,subsystem,host,bus)457 scgo_aget_first_free_atapibus(scgp, subsystem, host, bus)
458 	SCSI	*scgp;
459 	int	subsystem;
460 	int	host;
461 	int	bus;
462 {
463 	int	first_free_atapi_bus;
464 
465 	for (first_free_atapi_bus = 0;
466 			first_free_atapi_bus < MAX_ATAPI_HOSTS;
467 						first_free_atapi_bus++) {
468 
469 		if (typlocal(scgp, first_free_atapi_bus) == HOST_EMPTY ||
470 		    (typlocal(scgp, first_free_atapi_bus) == subsystem &&
471 		    hostlocal(scgp, first_free_atapi_bus) == host &&
472 		    buslocal(scgp, first_free_atapi_bus) == bus))
473 			break;
474 	}
475 
476 	if (first_free_atapi_bus >= MAX_ATAPI_HOSTS) {
477 		errmsgno(EX_BAD, "ERROR: in scgo_get_first_free_atapibus(...). Too many CDROMs, more than %i",
478 			MAX_ATAPI_HOSTS);
479 		errmsgno(EX_BAD, "Increase MAX_ATAPI_HOSTS in scsi-linux-ata.c and recompile!");
480 		return (-1);
481 	}
482 	return (first_free_atapi_bus);
483 }
484 
485 LOCAL int
scgo_amerge(path,readedlink,buffer,buflen)486 scgo_amerge(path, readedlink, buffer, buflen)
487 	char	*path;
488 	char	*readedlink;
489 	char	*buffer;
490 	int	buflen;
491 {
492 	char	*aa;
493 
494 #define	TOKEN_ARRAY		20
495 #define	LAST_CHAR(x)		(x)[strlen((x))-1]
496 #define	ONE_CHAR_BACK(x)	(x)[strlen((x))-1] = '\0'
497 	char	*ppa[TOKEN_ARRAY];
498 	char	*pa;
499 
500 	int	i;
501 	int	len;
502 	char	seps[] = "/";
503 	char	*last_slash;
504 
505 	if (!path || !readedlink || !buffer)
506 		return (-EINVAL);
507 
508 	if ('/' == readedlink[0]) {
509 		aa = (char *) malloc(strlen(readedlink) + 1);
510 		if (!aa)
511 			return (-ENOMEM);
512 
513 		strcpy(aa, readedlink);
514 	} else {
515 		aa = (char *) malloc(strlen(path) + strlen(readedlink) + 1);
516 		if (!aa)
517 			return (-ENOMEM);
518 
519 		strcpy(aa, path);
520 		if (LAST_CHAR(aa) == '/') {
521 			ONE_CHAR_BACK(aa);
522 		}
523 		last_slash = strrchr(aa, '/');
524 		if (last_slash == NULL)
525 			strcpy(aa, "/");
526 		else
527 			*(++last_slash) = '\0';
528 		strcat(aa, readedlink);
529 	}
530 	memset(ppa, 0x00, sizeof (ppa));
531 
532 	for (i = 0, pa = strtok(aa, seps);
533 		i < TOKEN_ARRAY && pa != NULL;
534 		++i, pa = strtok(NULL, seps)) {
535 		ppa[i] = pa;
536 	}
537 
538 	if (i == TOKEN_ARRAY) {
539 		free(aa);
540 		return (-ENOMEM);
541 	}
542 	for (i = 0; i < TOKEN_ARRAY && ppa[i]; i++) {
543 		if (strcmp(ppa[i], "..") == 0) {
544 			ppa[i] = NULL;
545 			if (i > 1)
546 				ppa[i - 1] = NULL;
547 		}
548 	}
549 
550 	/* dry run */
551 	len = 0;
552 	for (i = 0; i < TOKEN_ARRAY; i++) {
553 		if (ppa[i]) {
554 			len += 1;
555 			len += strlen(ppa[i]);
556 		}
557 	}
558 	if (0 == len)
559 		len = 1;
560 
561 	if (len + 1 <= buflen) {
562 		strcpy(buffer, "");
563 		for (i = 0; i < TOKEN_ARRAY; i++) {
564 			if (ppa[i]) {
565 				strcat(buffer, "/");
566 				strcat(buffer, ppa[i]);
567 			}
568 		}
569 
570 		if (strlen(buffer) == 0)
571 			strcpy(buffer, "/");
572 	}
573 	free(aa);
574 
575 	return (len + 1);
576 }
577 
578 /*
579  *	/dev/cdroms/cdrom0	first CD-ROM
580  *	/dev/cdroms/cdrom1	second CD-ROM
581  *
582  *
583  *	SCSI Devices
584  *
585  *	To uniquely identify any SCSI device requires the following information:
586  *
587  *	controller	(host adapter)
588  *	bus		(SCSI channel)
589  *	target		(SCSI ID)
590  *	unit		(Logical Unit Number)
591  *
592  *	All SCSI devices are placed under /dev/scsi (assuming devfs is mounted on /dev).
593  *	Hence, a SCSI device with the following parameters:
594  *		c=1,b=2,t=3,u=4 would appear as:
595  *
596  *		/dev/scsi/host1/bus2/target3/lun4	device directory
597  *
598  *	Inside this directory, a number of device entries may be created,
599  *	depending on which SCSI device-type drivers were installed.
600  *
601  *	See the section on the disc naming scheme to see what entries
602  *	the SCSI disc driver creates.
603  *
604  *	See the section on the tape naming scheme to see what entries
605  *	the SCSI tape driver creates.
606  *
607  *	The SCSI CD-ROM driver creates:  cd
608  *	The SCSI generic driver creates: generic
609  *
610  *	IDE Devices
611  *
612  *	To uniquely identify any IDE device requires the following information:
613  *
614  *	controller
615  *	bus		(0/1 aka. primary/secondary)
616  *	target		(0/1 aka. master/slave)
617  *	unit
618  *
619  *	All IDE devices are placed under /dev/ide, and uses a similar
620  *	naming scheme to the SCSI subsystem.
621  *
622  *
623  *	Example /dev/cdroms/cdrom0 ->  /dev/scsi/host1/bus2/target3/lun4/cd
624  *	Example /dev/cdroms/cdrom1 ->  /dev/ide/host1/bus0/target1/lun4/cd
625  *
626  */
627 LOCAL BOOL
sg_amapdev(scgp,f,device,atapibus,target,lun)628 sg_amapdev(scgp, f, device, atapibus, target, lun)
629 	SCSI	*scgp;
630 	int	f;
631 	char	*device;
632 	int	*atapibus;
633 	int	*target;
634 	int	*lun;
635 {
636 	struct host {
637 		char	host[4];
638 		char	host_no;
639 	};
640 	struct bus {
641 		char	bus[3];
642 		char	bus_no;
643 	};
644 	struct target {
645 		char	target[6];
646 		char	target_no;
647 	};
648 	struct lun {
649 		char	lun[3];
650 		char	lun_no;
651 	};
652 
653 	int	h,
654 		b,
655 		t,
656 		l;
657 
658 #define	TOKEN_DEV		"dev"
659 #define	TOKEN_SUBSYSTEM_SCSI	"scsi"
660 #define	TOKEN_SUBSYSTEM_IDE	"ide"
661 #define	TOKEN_HOST		"host"
662 #define	TOKEN_BUS		"bus"
663 #define	TOKEN_TARGET		"target"
664 #define	TOKEN_LUN		"lun"
665 #define	TOKEN_CD		"cd"
666 
667 #define	ID_TOKEN_DEV		0
668 #define	ID_TOKEN_SUBSYSTEM	1
669 #define	ID_TOKEN_HOST		2
670 #define	ID_TOKEN_BUS		3
671 #define	ID_TOKEN_TARGET		4
672 #define	ID_TOKEN_LUN		5
673 #define	ID_TOKEN_CD		6
674 #define	ID_TOKEN_LAST		ID_TOKEN_CD
675 #define	ID_TOKEN_MAX		ID_TOKEN_LAST + 2
676 #define	CHARTOINT(x)		(abs(atoi(&x)))
677 
678 	char		*token[ID_TOKEN_MAX],
679 			*seps = "/";
680 	int		i,
681 			result;
682 	struct stat	buf;
683 
684 #ifndef MAX_PATH
685 #define	MAX_PATH 260
686 #endif
687 #define	LOCAL_MAX_PATH MAX_PATH
688 	char		tmp[LOCAL_MAX_PATH],
689 			tmp1[LOCAL_MAX_PATH];
690 	int		first_free_atapi_bus;
691 	int		subsystem = HOST_EMPTY;
692 
693 	/* old DEV */
694 	typedef struct {
695 		char		prefix[2];
696 		char		device;
697 	} old_dev;
698 	/* strtok need char* instead of const char* */
699 	result = stat(device, &buf);
700 	if (result || !S_ISBLK(buf.st_mode))
701 		return (FALSE);
702 
703 	result = lstat(device, &buf);
704 	if (!result && S_ISLNK(buf.st_mode)) {
705 		result = readlink(device, tmp, LOCAL_MAX_PATH);
706 		if (result > 0 && result < LOCAL_MAX_PATH) {
707 			tmp[result] = '\0';
708 
709 			result = scgo_amerge(device, tmp, tmp1, LOCAL_MAX_PATH);
710 			if (result > 0 && result < LOCAL_MAX_PATH) {
711 				tmp1[result] = '\0';
712 				strcpy(tmp, tmp1);
713 			} else {
714 				errmsgno(EX_BAD,
715 				"ERROR: with link merging! base %s link %s, result of merging %i\n",
716 					device, tmp, result);
717 				return (FALSE);
718 			}
719 		} else {
720 			errmsgno(EX_BAD,
721 			"ERROR: with link reading! link %s, result of readlink %i\n",
722 				device, result);
723 			return (FALSE);
724 		}
725 	} else {
726 		strncpy(tmp, device, sizeof (tmp));
727 	}
728 	if (scgp->debug > 3) {
729 		js_fprintf((FILE *) scgp->errfile, "INFO: %s -> %s\n", device, tmp);
730 	}
731 	memset(token, 0x00, sizeof (token));
732 	i = 0;
733 	token[i] = strtok(tmp, seps);
734 	while (token[i] != NULL && (++i) && i < ID_TOKEN_MAX) {
735 		token[i] = strtok(NULL, seps);
736 	}
737 
738 	if (i == ID_TOKEN_MAX ||
739 		!(token[ID_TOKEN_DEV]) ||
740 		strcmp(token[ID_TOKEN_DEV], TOKEN_DEV)) {
741 
742 		errmsgno(EX_BAD, "ERROR: unknow format\n");
743 		errmsgno(EX_BAD, "EXAMPLE: /dev/scsi/host1/bus2/target3/lun4/cd\n");
744 		errmsgno(EX_BAD, "EXAMPLE: /dev/ide/host0/bus0/target1/lun0/cd\n");
745 		errmsgno(EX_BAD, "EXAMPLE: /dev/hda or /dev/sr0\n");
746 		return (FALSE);
747 	}
748 	if (!(strcmp(token[ID_TOKEN_SUBSYSTEM], TOKEN_SUBSYSTEM_SCSI)) ||
749 	    !(strcmp(token[ID_TOKEN_SUBSYSTEM], TOKEN_SUBSYSTEM_IDE))) {
750 		h = CHARTOINT(((struct host *) token[ID_TOKEN_HOST])->host_no);
751 		b = CHARTOINT(((struct bus *) token[ID_TOKEN_BUS])->bus_no);
752 		t = CHARTOINT(((struct target *) token[ID_TOKEN_TARGET])->target_no);
753 		l = CHARTOINT(((struct lun *) token[ID_TOKEN_LUN])->lun_no);
754 #ifdef PARANOID
755 		if (strncmp(token[ID_TOKEN_HOST], TOKEN_HOST, strlen(TOKEN_HOST))) {
756 			log(("ERROR: invalid host specified\n"));
757 			return (FALSE);
758 		}
759 		if (strncmp(token[ID_TOKEN_BUS], TOKEN_BUS, strlen(TOKEN_BUS))) {
760 			log(("ERROR: invalid bus specified\n"));
761 			return (FALSE);
762 		}
763 		if (strncmp(token[ID_TOKEN_TARGET], TOKEN_TARGET, strlen(TOKEN_TARGET))) {
764 			log(("ERROR: invalid target specified\n"));
765 			return (FALSE);
766 		}
767 		if (strncmp(token[ID_TOKEN_LUN], TOKEN_LUN, strlen(TOKEN_LUN))) {
768 			log(("ERROR: invalid lun specified\n"));
769 			return (FALSE);
770 		}
771 		if (!(strcmp(token[ID_TOKEN_SUBSYSTEM], TOKEN_SUBSYSTEM_IDE))) {
772 			if (b > 1 || t > 1) {
773 				log(("ERROR: invalid bus or target for IDE specified\n"));
774 				return (FALSE);
775 			}
776 		}
777 #endif	/* PARANOID */
778 
779 		if (!(strcmp(token[ID_TOKEN_SUBSYSTEM], TOKEN_SUBSYSTEM_IDE))) {
780 			subsystem = HOST_IDE;
781 		} else if (!(strcmp(token[ID_TOKEN_SUBSYSTEM], TOKEN_SUBSYSTEM_SCSI))) {
782 			subsystem = HOST_SCSI;
783 		} else {
784 			subsystem = HOST_OTHER;
785 		}
786 	} else if (!token[ID_TOKEN_HOST] &&
787 		strlen(token[ID_TOKEN_SUBSYSTEM]) == sizeof (old_dev)) {
788 		char	j;
789 
790 		old_dev	*pDev = (old_dev *) token[ID_TOKEN_SUBSYSTEM];
791 
792 		if (strncmp(pDev->prefix, "hd", 2) == 0) {
793 			j = pDev->device - ('a');
794 
795 			subsystem = HOST_IDE;
796 			h = j / 4;
797 			b = (j % 4) / 2;
798 			t = (j % 4) % 2;
799 			l = 0;
800 		} else if (strncmp(pDev->prefix, "sr", 2) == 0) {
801 #ifdef	nonono
802 			if (pDev->device >= '0' && pDev->device <= '9')
803 				j = pDev->device - ('0');
804 			else
805 				j = pDev->device - ('a');
806 
807 
808 			h = j / 4;
809 			b = (j % 4) / 2;
810 			t = (j % 4) % 2;
811 			l = 0;
812 #endif	/* nonono */
813 			/* other solution, with ioctl */
814 			int	Chan	= -1,
815 				Ino	= -1,
816 				Bus	= -1,
817 				Target	= -1,
818 				Lun	= -1;
819 
820 			subsystem = HOST_SCSI;
821 			sg_amapdev_scsi(scgp, f, &Bus, &Target, &Lun, &Chan, &Ino);
822 
823 			/* For old kernels try to make the best guess. */
824 #ifdef	nonono
825 				int	n;
826 				Ino |= Chan << 8;
827 				n = sg_mapbus(scgp, Bus, Ino);
828 				if (Bus == -1) {
829 					Bus = n;
830 					if (scgp->debug > 0) {
831 						js_fprintf((FILE *)scgp->errfile,
832 							"SCSI Bus: %d (mapped from %d)\n",
833 							Bus, Ino);
834 					}
835 				}
836 /*				It is me too high ;-()*/
837 #endif	/* nonono */
838 			h = Ino;
839 			b = Chan;
840 			t = Target;
841 			l = Lun;
842 		} else {
843 			errmsgno(EX_BAD, "ERROR: unknow subsystem (%s) in (%s)\n",
844 				token[ID_TOKEN_SUBSYSTEM], device);
845 			return (FALSE);
846 		}
847 	} else {
848 		errmsgno(EX_BAD, "ERROR: unknow subsystem (%s) in (%s)\n",
849 			token[ID_TOKEN_SUBSYSTEM], device);
850 		return (FALSE);
851 	}
852 
853 	if (scgp->verbose)
854 		js_printf(scgp->errstr, "INFO: subsystem %s: h %i, b %i, t %i, l %i",
855 			token[ID_TOKEN_SUBSYSTEM], h, b, t, l);
856 
857 	first_free_atapi_bus = scgo_aget_first_free_atapibus(scgp, subsystem, h, b);
858 	if (-1 == first_free_atapi_bus) {
859 		return (FALSE);
860 	}
861 	if (scglocal(scgp)->scgfiles[first_free_atapi_bus][t][l] != (-1)) {
862 		errmsgno(EX_BAD, "ERROR: this cdrom is already mapped %s(%d,%d,%d)\n",
863 			device, first_free_atapi_bus, t, l);
864 		return (FALSE);
865 	} else {
866 		scglocal(scgp)->scgfiles[first_free_atapi_bus][t][l] = f;
867 		typlocal(scgp, first_free_atapi_bus) = subsystem;
868 		hostlocal(scgp, first_free_atapi_bus) = h;
869 		buslocal(scgp, first_free_atapi_bus) = b;
870 		*atapibus = first_free_atapi_bus;
871 		*target = t;
872 		*lun = l;
873 
874 		if (scgp->debug > 1) {
875 			js_fprintf((FILE *) scgp->errfile,
876 				"INFO: /dev/%s, (host%d/bus%d/target%d/lun%d) will be mapped on the atapi bus No %d (%d,%d,%d)\n",
877 				token[ID_TOKEN_SUBSYSTEM], h, b, t, l,
878 				first_free_atapi_bus, first_free_atapi_bus, t, l);
879 		}
880 	}
881 	return (TRUE);
882 }
883 
884 LOCAL BOOL
sg_amapdev_scsi(scgp,f,busp,tgtp,lunp,chanp,inop)885 sg_amapdev_scsi(scgp, f, busp, tgtp, lunp, chanp, inop)
886 	SCSI	*scgp;
887 	int	f;
888 	int	*busp;
889 	int	*tgtp;
890 	int	*lunp;
891 	int	*chanp;
892 	int	*inop;
893 {
894 	struct sg_id {
895 		long	l1;	/* target | lun << 8 | channel << 16 | low_ino << 24 */
896 		long	l2;	/* Unique id */
897 	} sg_id;
898 	int	Chan;
899 	int	Ino;
900 	int	Bus;
901 	int	Target;
902 	int	Lun;
903 
904 	if (ioctl(f, SCSI_IOCTL_GET_IDLUN, &sg_id))
905 		return (FALSE);
906 
907 	if (scgp->debug > 0) {
908 		js_fprintf((FILE *) scgp->errfile,
909 			"INFO: l1: 0x%lX l2: 0x%lX\n", sg_id.l1, sg_id.l2);
910 	}
911 	if (ioctl(f, SCSI_IOCTL_GET_BUS_NUMBER, &Bus) < 0) {
912 		Bus = -1;
913 	}
914 	Target = sg_id.l1 & 0xFF;
915 	Lun = (sg_id.l1 >> 8) & 0xFF;
916 	Chan = (sg_id.l1 >> 16) & 0xFF;
917 	Ino = (sg_id.l1 >> 24) & 0xFF;
918 	if (scgp->debug > 0) {
919 		js_fprintf((FILE *) scgp->errfile,
920 			"INFO: Bus: %d Target: %d Lun: %d Chan: %d Ino: %d\n",
921 			Bus, Target, Lun, Chan, Ino);
922 	}
923 	*busp = Bus;
924 	*tgtp = Target;
925 	*lunp = Lun;
926 	if (chanp)
927 		*chanp = Chan;
928 	if (inop)
929 		*inop = Ino;
930 	return (TRUE);
931 }
932 
933 LOCAL long
scgo_amaxdma(scgp,amt)934 scgo_amaxdma(scgp, amt)
935 	SCSI	*scgp;
936 	long	amt;
937 {
938 	/*
939 	 * EINVAL (hart) ENOMEM (weich) bei mehr ...
940 	 * Bei fehlerhaftem Sense Pointer kommt EFAULT
941 	 */
942 	return (MAX_DMA_ATA);
943 }
944 
945 LOCAL int
scgo_anumbus(scgp)946 scgo_anumbus(scgp)
947 	SCSI	*scgp;
948 {
949 	return (MAX_ATAPI_HOSTS);
950 }
951 
952 LOCAL BOOL
scgo_ahavebus(scgp,busno)953 scgo_ahavebus(scgp, busno)
954 	SCSI	*scgp;
955 	int	busno;
956 {
957 	register int	t;
958 	register int	l;
959 
960 	if (busno < 0 || busno >= MAX_ATAPI_HOSTS)
961 		return (FALSE);
962 
963 	if (scgp->local == NULL)
964 		return (FALSE);
965 
966 	for (t = 0; t < MAX_TGT; t++) {
967 		for (l = 0; l < MAX_LUN; l++)
968 			if (scglocal(scgp)->scgfiles[busno][t][l] >= 0)
969 				return (TRUE);
970 	}
971 	return (FALSE);
972 }
973 
974 LOCAL int
scgo_afileno(scgp,busno,tgt,tlun)975 scgo_afileno(scgp, busno, tgt, tlun)
976 	SCSI	*scgp;
977 	int	busno;
978 	int	tgt;
979 	int	tlun;
980 {
981 	if (busno < 0 || busno >= MAX_ATAPI_HOSTS ||
982 		tgt < 0 || tgt >= MAX_TGT ||
983 		tlun < 0 || tlun >= MAX_LUN)
984 		return (-1);
985 
986 	if (scgp->local == NULL)
987 		return (-1);
988 
989 	return ((int) scglocal(scgp)->scgfiles[busno][tgt][tlun]);
990 }
991 
992 LOCAL int
scgo_ainitiator_id(scgp)993 scgo_ainitiator_id(scgp)
994 	SCSI	*scgp;
995 {
996 	js_printf(scgp->errstr, "NOT IMPELEMENTED: scgo_initiator_id");
997 	return (-1);
998 }
999 
1000 LOCAL int
scgo_aisatapi(scgp)1001 scgo_aisatapi(scgp)
1002 	SCSI	*scgp;
1003 {
1004 	int atapibus = scgp->addr.scsibus;
1005 	int typ = typlocal(scgp, atapibus);
1006 	if (typ == HOST_EMPTY)
1007 		return (-1);
1008 	if (typ != HOST_SCSI)
1009 		return (1);
1010 	else
1011 		return (0);
1012 }
1013 
1014 LOCAL int
scgo_areset(scgp,what)1015 scgo_areset(scgp, what)
1016 	SCSI	*scgp;
1017 	int	what;
1018 {
1019 	if (what == SCG_RESET_NOP)
1020 		return (0);
1021 
1022 	if (what == SCG_RESET_TGT || what == SCG_RESET_BUS)
1023 		return (ioctl(what, CDROMRESET));
1024 
1025 	return (-1);
1026 }
1027 
1028 LOCAL int
scgo_asend(scgp)1029 scgo_asend(scgp)
1030 	SCSI	*scgp;
1031 {
1032 	struct scg_cmd	*sp = scgp->scmd;
1033 	int		ret,
1034 			i;
1035 	struct cdrom_generic_command sg_cgc;
1036 	struct request_sense sense_cgc;
1037 static	uid_t		cureuid = 0;	/* XXX Hack until we have uid management */
1038 
1039 #ifdef DEBUG
1040 	char		tmp_send[340],
1041 			tmp_read[340],
1042 			tmp_sense[340],
1043 			tmp1[30];
1044 	int		j;
1045 	char		*p;
1046 #endif
1047 
1048 	if (scgp->fd < 0) {
1049 		sp->error = SCG_FATAL;
1050 		sp->ux_errno = EIO;
1051 		return (0);
1052 	}
1053 	if (sp->cdb_len > CDROM_PACKET_SIZE) {
1054 		sp->error = SCG_FATAL;
1055 		sp->ux_errno = EIO;
1056 		return (0);
1057 	}
1058 	/* initialize */
1059 	fillbytes((caddr_t) & sg_cgc, sizeof (sg_cgc), '\0');
1060 	fillbytes((caddr_t) & sense_cgc, sizeof (sense_cgc), '\0');
1061 
1062 	if (sp->flags & SCG_RECV_DATA) {
1063 		sg_cgc.data_direction = CGC_DATA_READ;
1064 	} else if (sp->size > 0) {
1065 		sg_cgc.data_direction = CGC_DATA_WRITE;
1066 	} else {
1067 		sg_cgc.data_direction = CGC_DATA_NONE;
1068 	}
1069 #if LINUX_VERSION_CODE >= 0x020403
1070 	if (sp->flags & SCG_SILENT) {
1071 		sg_cgc.quiet = 1;
1072 	}
1073 #endif
1074 	for (i = 0; i < sp->cdb_len; i++) {
1075 		sg_cgc.cmd[i] = sp->cdb.cmd_cdb[i];
1076 	}
1077 
1078 	sg_cgc.buflen = sp->size;
1079 	sg_cgc.buffer = (void *)sp->addr; /* Workaround silly type in sg_cgc */
1080 
1081 	if (sp->sense_len > sizeof (sense_cgc))
1082 		sense_cgc.add_sense_len = sizeof (sense_cgc) - 8;
1083 	else
1084 		sense_cgc.add_sense_len = sp->sense_len - 8;
1085 
1086 	sg_cgc.sense = &sense_cgc;
1087 #if LINUX_VERSION_CODE >= 0x020403
1088 	sg_cgc.timeout = sp->timeout * 1000;
1089 #endif
1090 #ifdef DEBUG
1091 	strcpy(tmp_send, "send cmd:\n");
1092 	for (j = 0; j < sp->cdb_len; j++) {
1093 		sprintf(tmp1, " %02X", sp->cdb.cmd_cdb[j]);
1094 		strcat(tmp_send, tmp1);
1095 	}
1096 	strcat(tmp_send, "\n");
1097 
1098 	if (sg_cgc.data_direction == CGC_DATA_WRITE) {
1099 		int	z;
1100 
1101 		sprintf(tmp1, "data_write: %i bytes\n", sp->size);
1102 		strcat(tmp_send, tmp1);
1103 		for (j = 0, z = 1; j < 80 && j < sp->size; j++, z++) {
1104 			if (z > 16) {
1105 				z = 1;
1106 				strcat(tmp_send, "\n");
1107 			}
1108 			sprintf(tmp1, " %02X", (unsigned char) (sp->addr[j]));
1109 			strcat(tmp_send, tmp1);
1110 		}
1111 		strcat(tmp_send, "\n");
1112 
1113 		if (sp->size > 80) {
1114 			strcat(tmp_send, "...\n");
1115 		}
1116 	}
1117 #endif	/* DEBUG */
1118 
1119 	if (cureuid != 0)
1120 		seteuid(0);
1121 again:
1122 	errno = 0;
1123 	if ((ret = ioctl(scgp->fd, CDROM_SEND_PACKET, &sg_cgc)) < 0)
1124 		sp->ux_errno = geterrno();
1125 	if (ret < 0 && geterrno() == EPERM) {	/* XXX Hack until we have uid management */
1126 		cureuid = geteuid();
1127 		if (seteuid(0) >= 0)
1128 			goto again;
1129 	}
1130 	if (cureuid != 0)
1131 		seteuid(cureuid);
1132 
1133 	if (ret < 0 && scgp->debug > 4) {
1134 		js_fprintf((FILE *) scgp->errfile,
1135 			"ioctl(CDROM_SEND_PACKET) ret: %d\n", ret);
1136 	}
1137 	/*
1138 	 * copy scsi data back
1139 	 */
1140 	if (sp->flags & SCG_RECV_DATA && ((void *) sp->addr != (void *) sg_cgc.buffer)) {
1141 		memcpy(sp->addr, sg_cgc.buffer, (sp->size < sg_cgc.buflen) ? sp->size : sg_cgc.buflen);
1142 		if (sg_cgc.buflen > sp->size)
1143 			sp->resid = sg_cgc.buflen - sp->size;
1144 	}
1145 	sp->error = SCG_NO_ERROR;
1146 #ifdef DEBUG
1147 	if (ret < 0) {
1148 		switch (sp->ux_errno) {
1149 		case ENOTTY:
1150 			p = "ENOTTY";
1151 			break;
1152 		case EINVAL:
1153 			p = "EINVAL";
1154 			break;
1155 		case ENXIO:
1156 			p = "ENXIO";
1157 			break;
1158 		case EPERM:
1159 			p = "EPERM";
1160 			break;
1161 		case EACCES:
1162 			p = "EACCES";
1163 			break;
1164 		case EIO:
1165 			p = "EIO";
1166 			break;
1167 		case ENOMEDIUM:
1168 			p = "ENOMEDIUM";
1169 			break;
1170 		case EDRIVE_CANT_DO_THIS:
1171 			p = "EDRIVE_CANT_DO_THIS";
1172 			break;
1173 		default:
1174 			p = "UNKNOW";
1175 		};
1176 		log(("%s", tmp_send));
1177 		log(("ERROR: returns %i errno %i(%s)\n", ret, sp->ux_errno, p));
1178 	}
1179 #endif	/* DEBUG */
1180 	if (ret < 0) {
1181 		/*
1182 		 * Check if SCSI command could not be send at all.
1183 		 * Linux usually returns EINVAL for an unknown ioctl.
1184 		 * In case somebody from the Linux kernel team learns that the
1185 		 * corect errno would be ENOTTY, we check for this errno too.
1186 		 */
1187 		if (sp->ux_errno == EINVAL) {
1188 			/*
1189 			 * Try to work around broken Linux kernel design...
1190 			 * If SCSI Sense Key is 0x05 (Illegal request), Linux
1191 			 * returns a useless EINVAL making it close to
1192 			 * impossible distinct from "Illegal ioctl()" or
1193 			 * "Invalid parameter".
1194 			 */
1195 			if ((((Uchar *)sg_cgc.sense)[0] != 0) ||
1196 			    (((Uchar *)sg_cgc.sense)[2] != 0))
1197 				sp->ux_errno = EIO;
1198 
1199 		} else if ((sp->ux_errno == ENOTTY || sp->ux_errno == EINVAL)) {
1200 			/*
1201 			 * May be "Illegal ioctl()".
1202 			 */
1203 			return (-1);
1204 		}
1205 		if (sp->ux_errno == ENXIO ||
1206 		    sp->ux_errno == EPERM ||
1207 		    sp->ux_errno == EACCES) {
1208 			return (-1);
1209 		}
1210 	} else if (ret == 0) {
1211 #ifdef DEBUG
1212 		if (sg_cgc.data_direction == CGC_DATA_READ) {
1213 			int	z;
1214 
1215 			sprintf(tmp_read, "data_read: %i bytes\n", sp->size);
1216 			for (j = 0, z = 1; j < 80 && j < sp->size; j++, z++) {
1217 				if (z > 16) {
1218 					z = 1;
1219 					strcat(tmp_read, "\n");
1220 				}
1221 				sprintf(tmp1, " %02X", (unsigned char) (sp->addr[j]));
1222 				strcat(tmp_read, tmp1);
1223 			}
1224 			strcat(tmp_read, "\n");
1225 			if (sp->size > 80) {
1226 				strcat(tmp_read, "...\n");
1227 			}
1228 		}
1229 #endif	/* DEBUG */
1230 	}
1231 	/*
1232 	 * copy sense back
1233 	 */
1234 	if (ret < 0 && sg_cgc.sense->error_code) {
1235 		sp->sense_count = sense_cgc.add_sense_len + 8;
1236 #ifdef DEBUG
1237 		sprintf(tmp_sense, "sense_data: length %i\n", sp->sense_count);
1238 		for (j = 0; j < sp->sense_count; j++) {
1239 			sprintf(tmp1, " %02X", (((unsigned char *) (&sense_cgc))[j]));
1240 			strcat(tmp_sense, tmp1);
1241 		}
1242 		log(("%s\n", tmp_sense));
1243 
1244 		sprintf(tmp_sense, "sense_data: error code 0x%02X, sense key 0x%02X,"
1245 			" additional length %i, ASC 0x%02X, ASCQ 0x%02X\n",
1246 			sg_cgc.sense->error_code, sg_cgc.sense->sense_key,
1247 			sg_cgc.sense->add_sense_len, sg_cgc.sense->asc,
1248 			sg_cgc.sense->ascq);
1249 
1250 		log(("%s\n", tmp_sense));
1251 #endif	/* DEBUG */
1252 		memcpy(sp->u_sense.cmd_sense, /* (caddr_t) */ &sense_cgc, SCG_MAX_SENSE);
1253 		sp->u_scb.cmd_scb[0] = ST_CHK_COND;
1254 
1255 		switch (sg_cgc.sense->sense_key) {
1256 		case SC_UNIT_ATTENTION:
1257 		case SC_NOT_READY:
1258 			sp->error = SCG_RETRYABLE;	/* may be BUS_BUSY */
1259 			sp->u_scb.cmd_scb[0] |= ST_BUSY;
1260 			break;
1261 		case SC_ILLEGAL_REQUEST:
1262 			break;
1263 		default:
1264 			break;
1265 		}
1266 	} else {
1267 		sp->u_scb.cmd_scb[0] = 0x00;
1268 	}
1269 
1270 	sp->resid = 0;
1271 	return (0);
1272 }
1273 #endif	/* USE_ATAPI */
1274