1 /* @(#)scsi_cdr.c	1.160 12/03/16 Copyright 1995-2012 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)scsi_cdr.c	1.160 12/03/16 Copyright 1995-2012 J. Schilling";
6 #endif
7 /*
8  *	SCSI command functions for cdrecord
9  *	covering pre-MMC standard functions up to MMC-2
10  *
11  *	Copyright (c) 1995-2012 J. Schilling
12  */
13 /*
14  * The contents of this file are subject to the terms of the
15  * Common Development and Distribution License, Version 1.0 only
16  * (the "License").  You may not use this file except in compliance
17  * with the License.
18  *
19  * See the file CDDL.Schily.txt in this distribution for details.
20  * A copy of the CDDL is also available via the Internet at
21  * http://www.opensource.org/licenses/cddl1.txt
22  *
23  * When distributing Covered Code, include this CDDL HEADER in each
24  * file and include the License file CDDL.Schily.txt from this distribution.
25  */
26 
27 /*
28  * NOTICE:	The Philips CDD 521 has several firmware bugs.
29  *		One of them is not to respond to a SCSI selection
30  *		within 200ms if the general load on the
31  *		SCSI bus is high. To deal with this problem
32  *		most of the SCSI commands are send with the
33  *		SCG_CMD_RETRY flag enabled.
34  */
35 #include <schily/mconfig.h>
36 
37 #include <schily/stdio.h>
38 #include <schily/standard.h>
39 #include <schily/stdlib.h>
40 #include <schily/unistd.h>
41 #include <schily/fcntl.h>
42 #include <schily/errno.h>
43 #include <schily/string.h>
44 #include <schily/time.h>
45 
46 #include <schily/utypes.h>
47 #include <schily/btorder.h>
48 #include <schily/intcvt.h>
49 #include <schily/schily.h>
50 #include <schily/nlsdefs.h>
51 
52 #include <scg/scgcmd.h>
53 #include <scg/scsidefs.h>
54 #include <scg/scsireg.h>
55 #include <scg/scsitransp.h>
56 
57 #include "scsimmc.h"
58 #include "cdrecord.h"
59 
60 #define	strbeg(s1, s2)	(strstr((s2), (s1)) == (s2))
61 
62 EXPORT	BOOL	unit_ready	__PR((SCSI *scgp));
63 EXPORT	BOOL	wait_unit_ready	__PR((SCSI *scgp, int secs));
64 EXPORT	BOOL	scsi_in_progress __PR((SCSI *scgp));
65 EXPORT	BOOL	cdr_underrun	__PR((SCSI *scgp));
66 EXPORT	int	test_unit_ready	__PR((SCSI *scgp));
67 EXPORT	int	rezero_unit	__PR((SCSI *scgp));
68 EXPORT	int	request_sense	__PR((SCSI *scgp));
69 EXPORT	int	request_sense_b	__PR((SCSI *scgp, caddr_t bp, int cnt));
70 EXPORT	int	inquiry		__PR((SCSI *scgp, caddr_t, int));
71 EXPORT	int	read_capacity	__PR((SCSI *scgp));
72 EXPORT	void	print_capacity	__PR((SCSI *scgp, FILE *f));
73 EXPORT	int	scsi_load_unload __PR((SCSI *scgp, int));
74 EXPORT	int	scsi_prevent_removal __PR((SCSI *scgp, int));
75 EXPORT	int	scsi_start_stop_unit __PR((SCSI *scgp, int, int, BOOL immed));
76 EXPORT	int	scsi_set_speed	__PR((SCSI *scgp, int readspeed, int writespeed, int rotctl));
77 EXPORT	int	scsi_get_speed	__PR((SCSI *scgp, int *readspeedp, int *writespeedp));
78 EXPORT	int	qic02		__PR((SCSI *scgp, int));
79 EXPORT	int	write_xscsi	__PR((SCSI *scgp, caddr_t, long, long, int));
80 EXPORT	int	write_xg0	__PR((SCSI *scgp, caddr_t, long, long, int));
81 EXPORT	int	write_xg1	__PR((SCSI *scgp, caddr_t, long, long, int));
82 EXPORT	int	write_xg5	__PR((SCSI *scgp, caddr_t, long, long, int));
83 EXPORT	int	seek_scsi	__PR((SCSI *scgp, long addr));
84 EXPORT	int	seek_g0		__PR((SCSI *scgp, long addr));
85 EXPORT	int	seek_g1		__PR((SCSI *scgp, long addr));
86 EXPORT	int	scsi_flush_cache __PR((SCSI *scgp, BOOL immed));
87 EXPORT	int	read_buffer	__PR((SCSI *scgp, caddr_t bp, int cnt, int mode));
88 EXPORT	int	write_buffer	__PR((SCSI *scgp, char *buffer, long length, int mode, int bufferid, long offset));
89 EXPORT	int	read_subchannel	__PR((SCSI *scgp, caddr_t bp, int track,
90 					int cnt, int msf, int subq, int fmt));
91 EXPORT	int	read_toc	__PR((SCSI *scgp, caddr_t, int, int, int, int));
92 EXPORT	int	read_toc_philips __PR((SCSI *scgp, caddr_t, int, int, int, int));
93 EXPORT	int	read_header	__PR((SCSI *scgp, caddr_t, long, int, int));
94 EXPORT	int	read_disk_info	__PR((SCSI *scgp, caddr_t, int));
95 EXPORT	int	read_track_info	__PR((SCSI *scgp, caddr_t, int type, int addr, int cnt));
96 EXPORT	int	get_trackinfo	__PR((SCSI *scgp, caddr_t, int type, int addr, int cnt));
97 EXPORT	int	read_rzone_info	__PR((SCSI *scgp, caddr_t bp, int cnt));
98 EXPORT	int	reserve_tr_rzone __PR((SCSI *scgp, long size));
99 EXPORT	int	read_dvd_structure __PR((SCSI *scgp, caddr_t bp, int cnt, int mt, int addr, int layer, int fmt));
100 EXPORT	int	send_dvd_structure __PR((SCSI *scgp, caddr_t bp, int cnt, int fmt));
101 EXPORT	int	send_opc	__PR((SCSI *scgp, caddr_t, int cnt, int doopc));
102 EXPORT	int	read_track_info_philips	__PR((SCSI *scgp, caddr_t, int, int));
103 EXPORT	int	scsi_close_tr_session __PR((SCSI *scgp, int type, int track, BOOL immed));
104 EXPORT	int	read_master_cue	__PR((SCSI *scgp, caddr_t bp, int sheet, int cnt));
105 EXPORT	int	send_cue_sheet	__PR((SCSI *scgp, caddr_t bp, long size));
106 EXPORT	int	read_buff_cap	__PR((SCSI *scgp, long *, long *));
107 EXPORT	int	scsi_blank	__PR((SCSI *scgp, long addr, int blanktype, BOOL immed));
108 EXPORT	BOOL	allow_atapi	__PR((SCSI *scgp, BOOL new));
109 EXPORT	int	mode_select	__PR((SCSI *scgp, Uchar *, int, int, int));
110 EXPORT	int	mode_sense	__PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
111 EXPORT	int	mode_select_sg0	__PR((SCSI *scgp, Uchar *, int, int, int));
112 EXPORT	int	mode_sense_sg0	__PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
113 EXPORT	int	mode_select_g0	__PR((SCSI *scgp, Uchar *, int, int, int));
114 EXPORT	int	mode_select_g1	__PR((SCSI *scgp, Uchar *, int, int, int));
115 EXPORT	int	mode_sense_g0	__PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
116 EXPORT	int	mode_sense_g1	__PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
117 EXPORT	int	read_tochdr	__PR((SCSI *scgp, cdr_t *, int *, int *));
118 EXPORT	int	read_cdtext	__PR((SCSI *scgp));
119 EXPORT	int	read_trackinfo	__PR((SCSI *scgp, int, long *, struct msf *, int *, int *, int *));
120 EXPORT	int	read_B0		__PR((SCSI *scgp, BOOL isbcd, long *b0p, long *lop));
121 EXPORT	int	read_session_offset __PR((SCSI *scgp, long *));
122 EXPORT	int	read_session_offset_philips __PR((SCSI *scgp, long *));
123 EXPORT	int	sense_secsize	__PR((SCSI *scgp, int current));
124 EXPORT	int	select_secsize	__PR((SCSI *scgp, int));
125 EXPORT	BOOL	is_cddrive	__PR((SCSI *scgp));
126 EXPORT	BOOL	is_unknown_dev	__PR((SCSI *scgp));
127 EXPORT	int	read_scsi	__PR((SCSI *scgp, caddr_t, long, int));
128 EXPORT	int	read_g0		__PR((SCSI *scgp, caddr_t, long, int));
129 EXPORT	int	read_g1		__PR((SCSI *scgp, caddr_t, long, int));
130 EXPORT	BOOL	getdev		__PR((SCSI *scgp, BOOL));
131 EXPORT	void	printinq	__PR((SCSI *scgp, FILE *f));
132 EXPORT	void	printdev	__PR((SCSI *scgp));
133 EXPORT	BOOL	do_inquiry	__PR((SCSI *scgp, BOOL));
134 EXPORT	BOOL	recovery_needed	__PR((SCSI *scgp, cdr_t *));
135 EXPORT	int	scsi_load	__PR((SCSI *scgp, cdr_t *));
136 EXPORT	int	scsi_unload	__PR((SCSI *scgp, cdr_t *));
137 EXPORT	int	scsi_cdr_write	__PR((SCSI *scgp, caddr_t bp, long sectaddr, long size, int blocks, BOOL islast));
138 EXPORT	struct cd_mode_page_2A * mmc_cap __PR((SCSI *scgp, Uchar *modep));
139 EXPORT	void	mmc_getval	__PR((struct cd_mode_page_2A *mp,
140 					BOOL *cdrrp, BOOL *cdwrp,
141 					BOOL *cdrrwp, BOOL *cdwrwp,
142 					BOOL *dvdp, BOOL *dvdwp));
143 EXPORT	BOOL	is_mmc		__PR((SCSI *scgp, BOOL *cdwp, BOOL *dvdwp));
144 EXPORT	BOOL	mmc_check	__PR((SCSI *scgp, BOOL *cdrrp, BOOL *cdwrp,
145 					BOOL *cdrrwp, BOOL *cdwrwp,
146 					BOOL *dvdp, BOOL *dvdwp));
147 LOCAL	void	print_speed	__PR((char *fmt, int val));
148 EXPORT	void	print_capabilities __PR((SCSI *scgp));
149 extern	int	verify		__PR((SCSI *scgp, long start, int count, long *bad_block));
150 
151 EXPORT BOOL
unit_ready(scgp)152 unit_ready(scgp)
153 	SCSI	*scgp;
154 {
155 	register struct	scg_cmd	*scmd = scgp->scmd;
156 
157 	if (test_unit_ready(scgp) >= 0)		/* alles OK */
158 		return (TRUE);
159 	else if (scmd->error >= SCG_FATAL)	/* nicht selektierbar */
160 		return (FALSE);
161 
162 	if (scg_sense_key(scgp) == SC_UNIT_ATTENTION) {
163 		if (test_unit_ready(scgp) >= 0)	/* alles OK */
164 			return (TRUE);
165 	}
166 	if ((scg_cmd_status(scgp) & ST_BUSY) != 0) {
167 		/*
168 		 * Busy/reservation_conflict
169 		 */
170 		usleep(500000);
171 		if (test_unit_ready(scgp) >= 0)	/* alles OK */
172 			return (TRUE);
173 	}
174 	if (scg_sense_key(scgp) == -1) {	/* non extended Sense */
175 		if (scg_sense_code(scgp) == 4)	/* NOT_READY */
176 			return (FALSE);
177 		return (TRUE);
178 	}
179 						/* FALSE wenn NOT_READY */
180 	return (scg_sense_key(scgp) != SC_NOT_READY);
181 }
182 
183 EXPORT BOOL
wait_unit_ready(scgp,secs)184 wait_unit_ready(scgp, secs)
185 	SCSI	*scgp;
186 	int	secs;
187 {
188 	int	i;
189 	int	c;
190 	int	k;
191 	int	ret;
192 	int	err;
193 
194 	seterrno(0);
195 	scgp->silent++;
196 	ret = test_unit_ready(scgp);		/* eat up unit attention */
197 	if (ret < 0) {
198 		err = geterrno();
199 
200 		if (err == EPERM || err == EACCES) {
201 			scgp->silent--;
202 			return (FALSE);
203 		}
204 		ret = test_unit_ready(scgp);	/* got power on condition? */
205 	}
206 	scgp->silent--;
207 
208 	if (ret >= 0)				/* success that's enough */
209 		return (TRUE);
210 
211 	scgp->silent++;
212 	for (i = 0; i < secs && (ret = test_unit_ready(scgp)) < 0; i++) {
213 		if (scgp->scmd->scb.busy != 0) {
214 			sleep(1);
215 			continue;
216 		}
217 		c = scg_sense_code(scgp);
218 		k = scg_sense_key(scgp);
219 		/*
220 		 * Abort quickly if it does not make sense to wait.
221 		 * 0x30 == Cannot read medium
222 		 * 0x3A == Medium not present
223 		 */
224 		if ((k == SC_NOT_READY && (c == 0x3A || c == 0x30)) ||
225 		    (k == SC_MEDIUM_ERROR)) {
226 			if (scgp->silent <= 1)
227 				scg_printerr(scgp);
228 			scgp->silent--;
229 			return (FALSE);
230 		}
231 		sleep(1);
232 	}
233 	scgp->silent--;
234 	if (ret < 0)
235 		return (FALSE);
236 	return (TRUE);
237 }
238 
239 EXPORT BOOL
scsi_in_progress(scgp)240 scsi_in_progress(scgp)
241 	SCSI	*scgp;
242 {
243 	if (scg_sense_key(scgp) == SC_NOT_READY &&
244 		/*
245 		 * Logigal unit not ready operation/long_write in progress
246 		 */
247 	    scg_sense_code(scgp) == 0x04 &&
248 	    (scg_sense_qual(scgp) == 0x04 || /* CyberDr. "format in progress"*/
249 	    scg_sense_qual(scgp) == 0x07 || /* "operation in progress"	    */
250 	    scg_sense_qual(scgp) == 0x08)) { /* "long write in progress"    */
251 		return (TRUE);
252 	} else {
253 		if (scgp->silent <= 1)
254 			scg_printerr(scgp);
255 	}
256 	return (FALSE);
257 }
258 
259 EXPORT BOOL
cdr_underrun(scgp)260 cdr_underrun(scgp)
261 	SCSI	*scgp;
262 {
263 	if ((scg_sense_key(scgp) != SC_ILLEGAL_REQUEST &&
264 	    scg_sense_key(scgp) != SC_MEDIUM_ERROR))
265 		return (FALSE);
266 
267 	if ((scg_sense_code(scgp) == 0x21 &&
268 	    (scg_sense_qual(scgp) == 0x00 ||	/* logical block address out of range */
269 	    scg_sense_qual(scgp) == 0x02)) ||	/* invalid address for write */
270 
271 	    (scg_sense_code(scgp) == 0x0C &&
272 	    scg_sense_qual(scgp) == 0x09)) {	/* write error - loss of streaming */
273 		return (TRUE);
274 	}
275 	/*
276 	 * XXX Bei manchen Brennern kommt mach dem der Brennvorgang bereits
277 	 * XXX eine Weile gelaufen ist ein 5/24/0 Invalid field in CDB.
278 	 * XXX Daher sollte man testen ob schon geschrieben wurde...
279 	 */
280 	return (FALSE);
281 }
282 
283 EXPORT int
test_unit_ready(scgp)284 test_unit_ready(scgp)
285 	SCSI	*scgp;
286 {
287 	register struct	scg_cmd	*scmd = scgp->scmd;
288 
289 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
290 	scmd->addr = (caddr_t)0;
291 	scmd->size = 0;
292 	scmd->flags = SCG_DISRE_ENA | (scgp->silent ? SCG_SILENT:0);
293 	scmd->cdb_len = SC_G0_CDBLEN;
294 	scmd->sense_len = CCS_SENSE_LEN;
295 	scmd->cdb.g0_cdb.cmd = SC_TEST_UNIT_READY;
296 	scmd->cdb.g0_cdb.lun = scg_lun(scgp);
297 
298 	scgp->cmdname = "test unit ready";
299 
300 	return (scg_cmd(scgp));
301 }
302 
303 EXPORT int
rezero_unit(scgp)304 rezero_unit(scgp)
305 	SCSI	*scgp;
306 {
307 	register struct	scg_cmd	*scmd = scgp->scmd;
308 
309 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
310 	scmd->addr = (caddr_t)0;
311 	scmd->size = 0;
312 	scmd->flags = SCG_DISRE_ENA;
313 	scmd->cdb_len = SC_G0_CDBLEN;
314 	scmd->sense_len = CCS_SENSE_LEN;
315 	scmd->cdb.g0_cdb.cmd = SC_REZERO_UNIT;
316 	scmd->cdb.g0_cdb.lun = scg_lun(scgp);
317 
318 	scgp->cmdname = "rezero unit";
319 
320 	return (scg_cmd(scgp));
321 }
322 
323 EXPORT int
request_sense(scgp)324 request_sense(scgp)
325 	SCSI	*scgp;
326 {
327 		char	sensebuf[CCS_SENSE_LEN];
328 		char	*cmdsave;
329 
330 	cmdsave = scgp->cmdname;
331 
332 	if (request_sense_b(scgp, sensebuf, sizeof (sensebuf)) < 0)
333 		return (-1);
334 	scgp->cmdname = cmdsave;
335 	scg_prsense((Uchar *)sensebuf, CCS_SENSE_LEN - scg_getresid(scgp));
336 	return (0);
337 }
338 
339 EXPORT int
request_sense_b(scgp,bp,cnt)340 request_sense_b(scgp, bp, cnt)
341 	SCSI	*scgp;
342 	caddr_t	bp;
343 	int	cnt;
344 {
345 	register struct	scg_cmd	*scmd = scgp->scmd;
346 
347 
348 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
349 	scmd->addr = bp;
350 	scmd->size = cnt;
351 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
352 	scmd->cdb_len = SC_G0_CDBLEN;
353 	scmd->sense_len = CCS_SENSE_LEN;
354 	scmd->cdb.g0_cdb.cmd = SC_REQUEST_SENSE;
355 	scmd->cdb.g0_cdb.lun = scg_lun(scgp);
356 	scmd->cdb.g0_cdb.count = cnt;
357 
358 	scgp->cmdname = "request_sense";
359 
360 	if (scg_cmd(scgp) < 0)
361 		return (-1);
362 	return (0);
363 }
364 
365 EXPORT int
inquiry(scgp,bp,cnt)366 inquiry(scgp, bp, cnt)
367 	SCSI	*scgp;
368 	caddr_t	bp;
369 	int	cnt;
370 {
371 	register struct	scg_cmd	*scmd = scgp->scmd;
372 
373 	fillbytes(bp, cnt, '\0');
374 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
375 	scmd->addr = bp;
376 	scmd->size = cnt;
377 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
378 	scmd->cdb_len = SC_G0_CDBLEN;
379 	scmd->sense_len = CCS_SENSE_LEN;
380 	scmd->cdb.g0_cdb.cmd = SC_INQUIRY;
381 	scmd->cdb.g0_cdb.lun = scg_lun(scgp);
382 	scmd->cdb.g0_cdb.count = cnt;
383 
384 	scgp->cmdname = "inquiry";
385 
386 	if (scg_cmd(scgp) < 0)
387 		return (-1);
388 	if (scgp->verbose)
389 		scg_prbytes(_("Inquiry Data   :"), (Uchar *)bp, cnt - scg_getresid(scgp));
390 	return (0);
391 }
392 
393 EXPORT int
read_capacity(scgp)394 read_capacity(scgp)
395 	SCSI	*scgp;
396 {
397 	register struct	scg_cmd	*scmd = scgp->scmd;
398 
399 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
400 	scmd->addr = (caddr_t)scgp->cap;
401 	scmd->size = sizeof (struct scsi_capacity);
402 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
403 	scmd->cdb_len = SC_G1_CDBLEN;
404 	scmd->sense_len = CCS_SENSE_LEN;
405 	scmd->cdb.g1_cdb.cmd = 0x25;	/* Read Capacity */
406 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
407 	g1_cdblen(&scmd->cdb.g1_cdb, 0); /* Full Media */
408 
409 	scgp->cmdname = "read capacity";
410 
411 	if (scg_cmd(scgp) < 0) {
412 		return (-1);
413 	} else {
414 		long	cbsize;
415 		long	cbaddr;
416 
417 		/*
418 		 * c_bsize & c_baddr are signed Int32_t
419 		 * so we use signed int conversion here.
420 		 */
421 		cbsize = a_to_4_byte(&scgp->cap->c_bsize);
422 		cbaddr = a_to_4_byte(&scgp->cap->c_baddr);
423 		scgp->cap->c_bsize = cbsize;
424 		scgp->cap->c_baddr = cbaddr;
425 	}
426 	return (0);
427 }
428 
429 EXPORT void
print_capacity(scgp,f)430 print_capacity(scgp, f)
431 	SCSI	*scgp;
432 	FILE	*f;
433 {
434 	long	kb;
435 	long	mb;
436 	long	prmb;
437 	double	dkb;
438 
439 	dkb =  (scgp->cap->c_baddr+1.0) * (scgp->cap->c_bsize/1024.0);
440 	kb = dkb;
441 	mb = dkb / 1024.0;
442 	prmb = dkb / 1000.0 * 1.024;
443 	fprintf(f, _("Capacity: %ld Blocks = %ld kBytes = %ld MBytes = %ld prMB\n"),
444 		(long)scgp->cap->c_baddr+1, kb, mb, prmb);
445 	fprintf(f, _("Sectorsize: %ld Bytes\n"), (long)scgp->cap->c_bsize);
446 }
447 
448 EXPORT int
scsi_load_unload(scgp,load)449 scsi_load_unload(scgp, load)
450 	SCSI	*scgp;
451 	int	load;
452 {
453 	register struct	scg_cmd	*scmd = scgp->scmd;
454 
455 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
456 	scmd->flags = SCG_DISRE_ENA;
457 	scmd->cdb_len = SC_G5_CDBLEN;
458 	scmd->sense_len = CCS_SENSE_LEN;
459 	scmd->cdb.g5_cdb.cmd = 0xA6;
460 	scmd->cdb.g5_cdb.lun = scg_lun(scgp);
461 	scmd->cdb.g5_cdb.addr[1] = load?3:2;
462 	scmd->cdb.g5_cdb.count[2] = 0; /* slot # */
463 
464 	scgp->cmdname = "medium load/unload";
465 
466 	if (scg_cmd(scgp) < 0)
467 		return (-1);
468 	return (0);
469 }
470 
471 EXPORT int
scsi_prevent_removal(scgp,prevent)472 scsi_prevent_removal(scgp, prevent)
473 	SCSI	*scgp;
474 	int	prevent;
475 {
476 	register struct	scg_cmd	*scmd = scgp->scmd;
477 
478 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
479 	scmd->flags = SCG_DISRE_ENA;
480 	scmd->cdb_len = SC_G0_CDBLEN;
481 	scmd->sense_len = CCS_SENSE_LEN;
482 	scmd->cdb.g0_cdb.cmd = 0x1E;
483 	scmd->cdb.g0_cdb.lun = scg_lun(scgp);
484 	scmd->cdb.g0_cdb.count = prevent & 1;
485 
486 	scgp->cmdname = "prevent/allow medium removal";
487 
488 	if (scg_cmd(scgp) < 0)
489 		return (-1);
490 	return (0);
491 }
492 
493 
494 EXPORT int
scsi_start_stop_unit(scgp,flg,loej,immed)495 scsi_start_stop_unit(scgp, flg, loej, immed)
496 	SCSI	*scgp;
497 	int	flg;
498 	int	loej;
499 	BOOL	immed;
500 {
501 	register struct	scg_cmd	*scmd = scgp->scmd;
502 
503 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
504 	scmd->flags = SCG_DISRE_ENA;
505 	scmd->cdb_len = SC_G0_CDBLEN;
506 	scmd->sense_len = CCS_SENSE_LEN;
507 	scmd->cdb.g0_cdb.cmd = 0x1B;	/* Start Stop Unit */
508 	scmd->cdb.g0_cdb.lun = scg_lun(scgp);
509 	scmd->cdb.g0_cdb.count = (flg ? 1:0) | (loej ? 2:0);
510 
511 	if (immed)
512 		scmd->cdb.cmd_cdb[1] |= 0x01;
513 
514 	scgp->cmdname = "start/stop unit";
515 
516 	return (scg_cmd(scgp));
517 }
518 
519 EXPORT int
scsi_set_speed(scgp,readspeed,writespeed,rotctl)520 scsi_set_speed(scgp, readspeed, writespeed, rotctl)
521 	SCSI	*scgp;
522 	int	readspeed;
523 	int	writespeed;
524 	int	rotctl;
525 {
526 	register struct	scg_cmd	*scmd = scgp->scmd;
527 
528 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
529 	scmd->flags = SCG_DISRE_ENA;
530 	scmd->cdb_len = SC_G5_CDBLEN;
531 	scmd->sense_len = CCS_SENSE_LEN;
532 	scmd->cdb.g5_cdb.cmd = 0xBB;
533 	scmd->cdb.g5_cdb.lun = scg_lun(scgp);
534 
535 	if (readspeed < 0)
536 		i_to_2_byte(&scmd->cdb.g5_cdb.addr[0], 0xFFFF);
537 	else
538 		i_to_2_byte(&scmd->cdb.g5_cdb.addr[0], readspeed);
539 	if (writespeed < 0)
540 		i_to_2_byte(&scmd->cdb.g5_cdb.addr[2], 0xFFFF);
541 	else
542 		i_to_2_byte(&scmd->cdb.g5_cdb.addr[2], writespeed);
543 
544 	scmd->cdb.cmd_cdb[1] |= rotctl & 0x03;
545 
546 	scgp->cmdname = "set cd speed";
547 
548 	if (scg_cmd(scgp) < 0)
549 		return (-1);
550 	return (0);
551 }
552 
553 EXPORT int
scsi_get_speed(scgp,readspeedp,writespeedp)554 scsi_get_speed(scgp, readspeedp, writespeedp)
555 	SCSI	*scgp;
556 	int	*readspeedp;
557 	int	*writespeedp;
558 {
559 	struct	cd_mode_page_2A *mp;
560 	Uchar	m[256];
561 	int	val;
562 
563 	scgp->silent++;
564 	mp = mmc_cap(scgp, m); /* Get MMC capabilities in allocated mp */
565 	scgp->silent--;
566 	if (mp == NULL)
567 		return (-1);	/* Pre SCSI-3/mmc drive		*/
568 
569 	val = a_to_u_2_byte(mp->cur_read_speed);
570 	if (readspeedp)
571 		*readspeedp = val;
572 
573 	if (mp->p_len >= 28)
574 		val = a_to_u_2_byte(mp->v3_cur_write_speed);
575 	else
576 		val = a_to_u_2_byte(mp->cur_write_speed);
577 	if (writespeedp)
578 		*writespeedp = val;
579 
580 	return (0);
581 }
582 
583 
584 EXPORT int
qic02(scgp,cmd)585 qic02(scgp, cmd)
586 	SCSI	*scgp;
587 	int	cmd;
588 {
589 	register struct	scg_cmd	*scmd = scgp->scmd;
590 
591 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
592 	scmd->addr = (caddr_t)0;
593 	scmd->size = 0;
594 	scmd->flags = SCG_DISRE_ENA;
595 	scmd->cdb_len = SC_G0_CDBLEN;
596 	scmd->sense_len = DEF_SENSE_LEN;
597 	scmd->cdb.g0_cdb.cmd = 0x0D;	/* qic02 Sysgen SC4000 */
598 	scmd->cdb.g0_cdb.lun = scg_lun(scgp);
599 	scmd->cdb.g0_cdb.mid_addr = cmd;
600 
601 	scgp->cmdname = "qic 02";
602 	return (scg_cmd(scgp));
603 }
604 
605 #define	G0_MAXADDR	0x1FFFFFL
606 
607 EXPORT int
write_xscsi(scgp,bp,addr,size,cnt)608 write_xscsi(scgp, bp, addr, size, cnt)
609 	SCSI	*scgp;
610 	caddr_t	bp;		/* address of buffer */
611 	long	addr;		/* disk address (sector) to put */
612 	long	size;		/* number of bytes to transfer */
613 	int	cnt;		/* sectorcount */
614 {
615 	if (addr <= G0_MAXADDR)
616 		return (write_xg0(scgp, bp, addr, size, cnt));
617 	else
618 		return (write_xg1(scgp, bp, addr, size, cnt));
619 }
620 
621 EXPORT int
write_xg0(scgp,bp,addr,size,cnt)622 write_xg0(scgp, bp, addr, size, cnt)
623 	SCSI	*scgp;
624 	caddr_t	bp;		/* address of buffer */
625 	long	addr;		/* disk address (sector) to put */
626 	long	size;		/* number of bytes to transfer */
627 	int	cnt;		/* sectorcount */
628 {
629 	register struct	scg_cmd	*scmd = scgp->scmd;
630 
631 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
632 	scmd->addr = bp;
633 	scmd->size = size;
634 	scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
635 /*	scmd->flags = SCG_DISRE_ENA;*/
636 	scmd->cdb_len = SC_G0_CDBLEN;
637 	scmd->sense_len = CCS_SENSE_LEN;
638 	scmd->cdb.g0_cdb.cmd = SC_WRITE;
639 	scmd->cdb.g0_cdb.lun = scg_lun(scgp);
640 	g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
641 	scmd->cdb.g0_cdb.count = cnt;
642 
643 	scgp->cmdname = "write_g0";
644 
645 	if (scg_cmd(scgp) < 0)
646 		return (-1);
647 	return (size - scg_getresid(scgp));
648 }
649 
650 EXPORT int
write_xg1(scgp,bp,addr,size,cnt)651 write_xg1(scgp, bp, addr, size, cnt)
652 	SCSI	*scgp;
653 	caddr_t	bp;		/* address of buffer */
654 	long	addr;		/* disk address (sector) to put */
655 	long	size;		/* number of bytes to transfer */
656 	int	cnt;		/* sectorcount */
657 {
658 	register struct	scg_cmd	*scmd = scgp->scmd;
659 
660 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
661 	scmd->addr = bp;
662 	scmd->size = size;
663 	scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
664 /*	scmd->flags = SCG_DISRE_ENA;*/
665 	scmd->cdb_len = SC_G1_CDBLEN;
666 	scmd->sense_len = CCS_SENSE_LEN;
667 	scmd->cdb.g1_cdb.cmd = SC_EWRITE;
668 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
669 	g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
670 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
671 
672 	scgp->cmdname = "write_g1";
673 
674 	if (scg_cmd(scgp) < 0)
675 		return (-1);
676 	return (size - scg_getresid(scgp));
677 }
678 
679 EXPORT int
write_xg5(scgp,bp,addr,size,cnt)680 write_xg5(scgp, bp, addr, size, cnt)
681 	SCSI	*scgp;
682 	caddr_t	bp;		/* address of buffer */
683 	long	addr;		/* disk address (sector) to put */
684 	long	size;		/* number of bytes to transfer */
685 	int	cnt;		/* sectorcount */
686 {
687 	register struct	scg_cmd	*scmd = scgp->scmd;
688 
689 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
690 	scmd->addr = bp;
691 	scmd->size = size;
692 	scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
693 /*	scmd->flags = SCG_DISRE_ENA;*/
694 	scmd->cdb_len = SC_G5_CDBLEN;
695 	scmd->sense_len = CCS_SENSE_LEN;
696 	scmd->cdb.g5_cdb.cmd = 0xAA;
697 	scmd->cdb.g5_cdb.lun = scg_lun(scgp);
698 	g5_cdbaddr(&scmd->cdb.g5_cdb, addr);
699 	g5_cdblen(&scmd->cdb.g5_cdb, cnt);
700 
701 	scgp->cmdname = "write_g5";
702 
703 	if (scg_cmd(scgp) < 0)
704 		return (-1);
705 	return (size - scg_getresid(scgp));
706 }
707 
708 EXPORT int
seek_scsi(scgp,addr)709 seek_scsi(scgp, addr)
710 	SCSI	*scgp;
711 	long	addr;
712 {
713 	if (addr <= G0_MAXADDR)
714 		return (seek_g0(scgp, addr));
715 	else
716 		return (seek_g1(scgp, addr));
717 }
718 
719 EXPORT int
seek_g0(scgp,addr)720 seek_g0(scgp, addr)
721 	SCSI	*scgp;
722 	long	addr;
723 {
724 	register struct	scg_cmd	*scmd = scgp->scmd;
725 
726 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
727 	scmd->flags = SCG_DISRE_ENA;
728 	scmd->cdb_len = SC_G0_CDBLEN;
729 	scmd->sense_len = CCS_SENSE_LEN;
730 	scmd->cdb.g0_cdb.cmd = 0x0B;	/* Seek */
731 	scmd->cdb.g0_cdb.lun = scg_lun(scgp);
732 	g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
733 
734 	scgp->cmdname = "seek_g0";
735 
736 	return (scg_cmd(scgp));
737 }
738 
739 EXPORT int
seek_g1(scgp,addr)740 seek_g1(scgp, addr)
741 	SCSI	*scgp;
742 	long	addr;
743 {
744 	register struct	scg_cmd	*scmd = scgp->scmd;
745 
746 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
747 	scmd->flags = SCG_DISRE_ENA;
748 	scmd->cdb_len = SC_G1_CDBLEN;
749 	scmd->sense_len = CCS_SENSE_LEN;
750 	scmd->cdb.g1_cdb.cmd = 0x2B;	/* Seek G1 */
751 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
752 	g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
753 
754 	scgp->cmdname = "seek_g1";
755 
756 	return (scg_cmd(scgp));
757 }
758 
759 EXPORT int
scsi_flush_cache(scgp,immed)760 scsi_flush_cache(scgp, immed)
761 	SCSI	*scgp;
762 	BOOL	immed;
763 {
764 	register struct	scg_cmd	*scmd = scgp->scmd;
765 
766 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
767 	scmd->flags = SCG_DISRE_ENA;
768 	scmd->cdb_len = SC_G1_CDBLEN;
769 	scmd->sense_len = CCS_SENSE_LEN;
770 	scmd->timeout = 2 * 60;		/* Max: sizeof (CDR-cache)/150KB/s */
771 	scmd->cdb.g1_cdb.cmd = 0x35;
772 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
773 
774 	if (immed)
775 		scmd->cdb.cmd_cdb[1] |= 0x02;
776 
777 	scgp->cmdname = "flush cache";
778 
779 	if (scg_cmd(scgp) < 0)
780 		return (-1);
781 	return (0);
782 }
783 
784 EXPORT int
read_buffer(scgp,bp,cnt,mode)785 read_buffer(scgp, bp, cnt, mode)
786 	SCSI	*scgp;
787 	caddr_t	bp;
788 	int	cnt;
789 	int	mode;
790 {
791 	register struct	scg_cmd	*scmd = scgp->scmd;
792 
793 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
794 	scmd->addr = bp;
795 	scmd->size = cnt;
796 	scmd->dma_read = 1;
797 	scmd->cdb_len = SC_G1_CDBLEN;
798 	scmd->sense_len = CCS_SENSE_LEN;
799 	scmd->cdb.g1_cdb.cmd = 0x3C;	/* Read Buffer */
800 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
801 	scmd->cdb.cmd_cdb[1] |= (mode & 7);
802 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
803 
804 	scgp->cmdname = "read buffer";
805 
806 	return (scg_cmd(scgp));
807 }
808 
809 EXPORT int
write_buffer(scgp,buffer,length,mode,bufferid,offset)810 write_buffer(scgp, buffer, length, mode, bufferid, offset)
811 	SCSI	*scgp;
812 	char	*buffer;
813 	long	length;
814 	int	mode;
815 	int	bufferid;
816 	long	offset;
817 {
818 	register struct	scg_cmd	*scmd = scgp->scmd;
819 	char			*cdb;
820 
821 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
822 	scmd->addr = buffer;
823 	scmd->size = length;
824 	scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
825 	scmd->cdb_len = SC_G1_CDBLEN;
826 	scmd->sense_len = CCS_SENSE_LEN;
827 
828 	cdb = (char *)scmd->cdb.cmd_cdb;
829 
830 	cdb[0] = 0x3B;
831 	cdb[1] = mode & 7;
832 	cdb[2] = bufferid;
833 	cdb[3] = offset >> 16;
834 	cdb[4] = (offset >> 8) & 0xff;
835 	cdb[5] = offset & 0xff;
836 	cdb[6] = length >> 16;
837 	cdb[7] = (length >> 8) & 0xff;
838 	cdb[8] = length & 0xff;
839 
840 	scgp->cmdname = "write_buffer";
841 
842 	if (scg_cmd(scgp) >= 0)
843 		return (1);
844 	return (0);
845 }
846 
847 EXPORT int
read_subchannel(scgp,bp,track,cnt,msf,subq,fmt)848 read_subchannel(scgp, bp, track, cnt, msf, subq, fmt)
849 	SCSI	*scgp;
850 	caddr_t	bp;
851 	int	track;
852 	int	cnt;
853 	int	msf;
854 	int	subq;
855 	int	fmt;
856 
857 {
858 	register struct	scg_cmd	*scmd = scgp->scmd;
859 
860 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
861 	scmd->addr = bp;
862 	scmd->size = cnt;
863 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
864 	scmd->cdb_len = SC_G1_CDBLEN;
865 	scmd->sense_len = CCS_SENSE_LEN;
866 	scmd->cdb.g1_cdb.cmd = 0x42;
867 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
868 	if (msf)
869 		scmd->cdb.g1_cdb.res = 1;
870 	if (subq)
871 		scmd->cdb.g1_cdb.addr[0] = 0x40;
872 	scmd->cdb.g1_cdb.addr[1] = fmt;
873 	scmd->cdb.g1_cdb.res6 = track;
874 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
875 
876 	scgp->cmdname = "read subchannel";
877 
878 	if (scg_cmd(scgp) < 0)
879 		return (-1);
880 	return (0);
881 }
882 
883 EXPORT int
read_toc(scgp,bp,track,cnt,msf,fmt)884 read_toc(scgp, bp, track, cnt, msf, fmt)
885 	SCSI	*scgp;
886 	caddr_t	bp;
887 	int	track;
888 	int	cnt;
889 	int	msf;
890 	int	fmt;
891 
892 {
893 	register struct	scg_cmd	*scmd = scgp->scmd;
894 
895 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
896 	scmd->addr = bp;
897 	scmd->size = cnt;
898 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
899 	scmd->cdb_len = SC_G1_CDBLEN;
900 	scmd->sense_len = CCS_SENSE_LEN;
901 	scmd->cdb.g1_cdb.cmd = 0x43;
902 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
903 	if (msf)
904 		scmd->cdb.g1_cdb.res = 1;
905 	scmd->cdb.g1_cdb.addr[0] = fmt & 0x0F;
906 	scmd->cdb.g1_cdb.res6 = track;
907 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
908 
909 	scgp->cmdname = "read toc";
910 
911 	if (scg_cmd(scgp) < 0)
912 		return (-1);
913 	return (0);
914 }
915 
916 EXPORT int
read_toc_philips(scgp,bp,track,cnt,msf,fmt)917 read_toc_philips(scgp, bp, track, cnt, msf, fmt)
918 	SCSI	*scgp;
919 	caddr_t	bp;
920 	int	track;
921 	int	cnt;
922 	int	msf;
923 	int	fmt;
924 
925 {
926 	register struct	scg_cmd	*scmd = scgp->scmd;
927 
928 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
929 	scmd->addr = bp;
930 	scmd->size = cnt;
931 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
932 	scmd->cdb_len = SC_G1_CDBLEN;
933 	scmd->sense_len = CCS_SENSE_LEN;
934 	scmd->timeout = 4 * 60;		/* May last  174s on a TEAC CD-R55S */
935 	scmd->cdb.g1_cdb.cmd = 0x43;
936 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
937 	if (msf)
938 		scmd->cdb.g1_cdb.res = 1;
939 	scmd->cdb.g1_cdb.res6 = track;
940 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
941 
942 	if (fmt & 1)
943 		scmd->cdb.g1_cdb.vu_96 = 1;
944 	if (fmt & 2)
945 		scmd->cdb.g1_cdb.vu_97 = 1;
946 
947 	scgp->cmdname = "read toc";
948 
949 	if (scg_cmd(scgp) < 0)
950 		return (-1);
951 	return (0);
952 }
953 
954 EXPORT int
read_header(scgp,bp,addr,cnt,msf)955 read_header(scgp, bp, addr, cnt, msf)
956 	SCSI	*scgp;
957 	caddr_t	bp;
958 	long	addr;
959 	int	cnt;
960 	int	msf;
961 {
962 	register struct	scg_cmd	*scmd = scgp->scmd;
963 
964 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
965 	scmd->addr = bp;
966 	scmd->size = cnt;
967 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
968 	scmd->cdb_len = SC_G1_CDBLEN;
969 	scmd->sense_len = CCS_SENSE_LEN;
970 	scmd->cdb.g1_cdb.cmd = 0x44;
971 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
972 	if (msf)
973 		scmd->cdb.g1_cdb.res = 1;
974 	g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
975 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
976 
977 	scgp->cmdname = "read header";
978 
979 	if (scg_cmd(scgp) < 0)
980 		return (-1);
981 	return (0);
982 }
983 
984 EXPORT int
read_disk_info(scgp,bp,cnt)985 read_disk_info(scgp, bp, cnt)
986 	SCSI	*scgp;
987 	caddr_t	bp;
988 	int	cnt;
989 
990 {
991 	register struct	scg_cmd	*scmd = scgp->scmd;
992 
993 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
994 	scmd->addr = bp;
995 	scmd->size = cnt;
996 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
997 	scmd->cdb_len = SC_G1_CDBLEN;
998 	scmd->sense_len = CCS_SENSE_LEN;
999 	scmd->timeout = 4 * 60;		/* Needs up to 2 minutes */
1000 	scmd->cdb.g1_cdb.cmd = 0x51;
1001 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1002 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1003 
1004 	scgp->cmdname = "read disk info";
1005 
1006 	if (scg_cmd(scgp) < 0)
1007 		return (-1);
1008 	return (0);
1009 }
1010 
1011 EXPORT int
read_track_info(scgp,bp,type,addr,cnt)1012 read_track_info(scgp, bp, type, addr, cnt)
1013 	SCSI	*scgp;
1014 	caddr_t	bp;
1015 	int	type;
1016 	int	addr;
1017 	int	cnt;
1018 
1019 {
1020 	register struct	scg_cmd	*scmd = scgp->scmd;
1021 
1022 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1023 	scmd->addr = bp;
1024 	scmd->size = cnt;
1025 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1026 	scmd->cdb_len = SC_G1_CDBLEN;
1027 	scmd->sense_len = CCS_SENSE_LEN;
1028 	scmd->timeout = 4 * 60;		/* Needs up to 2 minutes */
1029 	scmd->cdb.g1_cdb.cmd = 0x52;
1030 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1031 /*	scmd->cdb.cmd_cdb[1] = type & 0x03;*/
1032 	scmd->cdb.cmd_cdb[1] = type;
1033 	g1_cdbaddr(&scmd->cdb.g1_cdb, addr);	/* LBA/Track/Session */
1034 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1035 
1036 	scgp->cmdname = "read track info";
1037 
1038 	if (scg_cmd(scgp) < 0)
1039 		return (-1);
1040 	return (0);
1041 }
1042 
1043 EXPORT int
get_trackinfo(scgp,bp,type,addr,cnt)1044 get_trackinfo(scgp, bp, type, addr, cnt)
1045 	SCSI	*scgp;
1046 	caddr_t	bp;
1047 	int	type;
1048 	int	addr;
1049 	int	cnt;
1050 {
1051 	int	len;
1052 	int	ret;
1053 
1054 	fillbytes(bp, cnt, '\0');
1055 
1056 	/*
1057 	 * Used to be 2 instead of 4 (now). But some Y2k ATAPI drives as used
1058 	 * by IOMEGA create a DMA overrun if we try to transfer only 2 bytes.
1059 	 */
1060 	if (read_track_info(scgp, bp, type, addr, 4) < 0)
1061 		return (-1);
1062 
1063 	len = a_to_u_2_byte(bp);
1064 	len += 2;
1065 	if (len > cnt)
1066 		len = cnt;
1067 	ret = read_track_info(scgp, bp, type, addr, len);
1068 
1069 #ifdef	DEBUG
1070 	if (lverbose > 1)
1071 		scg_prbytes(_("Track info:"), (Uchar *)bp,
1072 				len-scg_getresid(scgp));
1073 #endif
1074 	return (ret);
1075 }
1076 
1077 EXPORT int
read_rzone_info(scgp,bp,cnt)1078 read_rzone_info(scgp, bp, cnt)
1079 	SCSI	*scgp;
1080 	caddr_t	bp;
1081 	int	cnt;
1082 {
1083 	return (get_trackinfo(scgp, bp, TI_TYPE_LBA, 0, cnt));
1084 }
1085 
1086 EXPORT int
reserve_tr_rzone(scgp,size)1087 reserve_tr_rzone(scgp, size)
1088 	SCSI	*scgp;
1089 	long	size;		/* number of blocks */
1090 {
1091 	register struct	scg_cmd	*scmd = scgp->scmd;
1092 
1093 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1094 	scmd->addr = (caddr_t)0;
1095 	scmd->size = 0;
1096 	scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
1097 	scmd->cdb_len = SC_G1_CDBLEN;
1098 	scmd->sense_len = CCS_SENSE_LEN;
1099 	scmd->cdb.g1_cdb.cmd = 0x53;
1100 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1101 
1102 	i_to_4_byte(&scmd->cdb.cmd_cdb[5], size);
1103 
1104 	scgp->cmdname = "reserve_track_rzone";
1105 
1106 	if (scg_cmd(scgp) < 0)
1107 		return (-1);
1108 	return (0);
1109 }
1110 
1111 EXPORT int
read_dvd_structure(scgp,bp,cnt,mt,addr,layer,fmt)1112 read_dvd_structure(scgp, bp, cnt, mt, addr, layer, fmt)
1113 	SCSI	*scgp;
1114 	caddr_t	bp;
1115 	int	cnt;
1116 	int	mt;
1117 	int	addr;
1118 	int	layer;
1119 	int	fmt;
1120 {
1121 	register struct	scg_cmd	*scmd = scgp->scmd;
1122 
1123 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1124 	scmd->addr = bp;
1125 	scmd->size = cnt;
1126 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1127 	scmd->cdb_len = SC_G5_CDBLEN;
1128 	scmd->sense_len = CCS_SENSE_LEN;
1129 	scmd->timeout = 4 * 60;		/* Needs up to 2 minutes ??? */
1130 	scmd->cdb.g5_cdb.cmd = 0xAD;
1131 	scmd->cdb.g5_cdb.lun = scg_lun(scgp);
1132 	scmd->cdb.cmd_cdb[1] |= (mt & 0x0F);	/* Media Type */
1133 	g5_cdbaddr(&scmd->cdb.g5_cdb, addr);
1134 	g5_cdblen(&scmd->cdb.g5_cdb, cnt);
1135 	scmd->cdb.g5_cdb.count[0] = layer;
1136 	scmd->cdb.g5_cdb.count[1] = fmt;
1137 
1138 	scgp->cmdname = "read dvd structure";
1139 
1140 	if (scg_cmd(scgp) < 0)
1141 		return (-1);
1142 	return (0);
1143 }
1144 
1145 EXPORT int
send_dvd_structure(scgp,bp,cnt,fmt)1146 send_dvd_structure(scgp, bp, cnt, fmt)
1147 	SCSI	*scgp;
1148 	caddr_t	bp;
1149 	int	cnt;
1150 	int	fmt;
1151 {
1152 	register struct	scg_cmd	*scmd = scgp->scmd;
1153 
1154 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1155 	scmd->addr = bp;
1156 	scmd->size = cnt;
1157 	scmd->flags = SCG_DISRE_ENA;
1158 	scmd->cdb_len = SC_G5_CDBLEN;
1159 	scmd->sense_len = CCS_SENSE_LEN;
1160 	scmd->timeout = 4 * 60;		/* Needs up to 2 minutes ??? */
1161 	scmd->cdb.g5_cdb.cmd = 0xBF;
1162 	scmd->cdb.g5_cdb.lun = scg_lun(scgp);
1163 	g5_cdblen(&scmd->cdb.g5_cdb, cnt);
1164 	scmd->cdb.g5_cdb.count[0] = 0;
1165 	scmd->cdb.g5_cdb.count[1] = fmt;
1166 
1167 	scgp->cmdname = "send dvd structure";
1168 
1169 	if (scg_cmd(scgp) < 0)
1170 		return (-1);
1171 	return (0);
1172 }
1173 
1174 EXPORT int
send_opc(scgp,bp,cnt,doopc)1175 send_opc(scgp, bp, cnt, doopc)
1176 	SCSI	*scgp;
1177 	caddr_t	bp;
1178 	int	cnt;
1179 	int	doopc;
1180 {
1181 	register struct	scg_cmd	*scmd = scgp->scmd;
1182 
1183 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1184 	scmd->addr = bp;
1185 	scmd->size = cnt;
1186 	scmd->flags = SCG_DISRE_ENA;
1187 	scmd->cdb_len = SC_G1_CDBLEN;
1188 	scmd->sense_len = CCS_SENSE_LEN;
1189 	scmd->timeout = 60;
1190 	scmd->cdb.g1_cdb.cmd = 0x54;
1191 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1192 	scmd->cdb.g1_cdb.reladr = doopc?1:0;
1193 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1194 
1195 	scgp->cmdname = "send opc";
1196 
1197 	if (scg_cmd(scgp) < 0)
1198 		return (-1);
1199 	return (0);
1200 }
1201 
1202 EXPORT int
read_track_info_philips(scgp,bp,track,cnt)1203 read_track_info_philips(scgp, bp, track, cnt)
1204 	SCSI	*scgp;
1205 	caddr_t	bp;
1206 	int	track;
1207 	int	cnt;
1208 
1209 {
1210 	register struct	scg_cmd	*scmd = scgp->scmd;
1211 
1212 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1213 	scmd->addr = bp;
1214 	scmd->size = cnt;
1215 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1216 	scmd->cdb_len = SC_G1_CDBLEN;
1217 	scmd->sense_len = CCS_SENSE_LEN;
1218 	scmd->cdb.g1_cdb.cmd = 0xE5;
1219 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1220 	g1_cdbaddr(&scmd->cdb.g1_cdb, track);
1221 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1222 
1223 	scgp->cmdname = "read track info";
1224 
1225 	if (scg_cmd(scgp) < 0)
1226 		return (-1);
1227 	return (0);
1228 }
1229 
1230 EXPORT int
scsi_close_tr_session(scgp,type,track,immed)1231 scsi_close_tr_session(scgp, type, track, immed)
1232 	SCSI	*scgp;
1233 	int	type;
1234 	int	track;
1235 	BOOL	immed;
1236 {
1237 	register struct	scg_cmd	*scmd = scgp->scmd;
1238 
1239 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1240 	scmd->flags = SCG_DISRE_ENA;
1241 	scmd->cdb_len = SC_G1_CDBLEN;
1242 	scmd->sense_len = CCS_SENSE_LEN;
1243 	scmd->timeout = 8 * 60;		/* Needs up to 4 minutes */
1244 	scmd->cdb.g1_cdb.cmd = 0x5B;
1245 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1246 	scmd->cdb.g1_cdb.addr[0] = type;
1247 	scmd->cdb.g1_cdb.addr[3] = track;
1248 
1249 	if (immed)
1250 		scmd->cdb.g1_cdb.reladr = 1;
1251 /*		scmd->cdb.cmd_cdb[1] |= 0x01;*/
1252 #ifdef	nono
1253 	scmd->cdb.g1_cdb.reladr = 1;	/* IMM hack to test Mitsumi behaviour*/
1254 #endif
1255 
1256 	scgp->cmdname = "close track/session";
1257 
1258 	if (scg_cmd(scgp) < 0)
1259 		return (-1);
1260 	return (0);
1261 }
1262 
1263 EXPORT int
read_master_cue(scgp,bp,sheet,cnt)1264 read_master_cue(scgp, bp, sheet, cnt)
1265 	SCSI	*scgp;
1266 	caddr_t	bp;		/* address of master cue sheet	*/
1267 	int	sheet;		/* Sheet number			*/
1268 	int	cnt;		/* Transfer count		*/
1269 {
1270 	register struct	scg_cmd	*scmd = scgp->scmd;
1271 
1272 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1273 	scmd->addr = bp;
1274 	scmd->size = cnt;
1275 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1276 	scmd->cdb_len = SC_G1_CDBLEN;
1277 	scmd->sense_len = CCS_SENSE_LEN;
1278 	scmd->cdb.g1_cdb.cmd = 0x59;		/* Read master cue */
1279 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1280 	scmd->cdb.g1_cdb.addr[2] = sheet;
1281 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1282 
1283 	scgp->cmdname = "read master cue";
1284 
1285 	if (scg_cmd(scgp) < 0)
1286 		return (-1);
1287 	return (0);
1288 }
1289 
1290 EXPORT int
send_cue_sheet(scgp,bp,size)1291 send_cue_sheet(scgp, bp, size)
1292 	SCSI	*scgp;
1293 	caddr_t	bp;		/* address of cue sheet buffer */
1294 	long	size;		/* number of bytes to transfer */
1295 {
1296 	register struct	scg_cmd	*scmd = scgp->scmd;
1297 
1298 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1299 	scmd->addr = bp;
1300 	scmd->size = size;
1301 	scmd->flags = SCG_DISRE_ENA;
1302 	scmd->cdb_len = SC_G1_CDBLEN;
1303 	scmd->sense_len = CCS_SENSE_LEN;
1304 	scmd->cdb.g1_cdb.cmd = 0x5D;	/* Send CUE sheet */
1305 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1306 	g1_cdblen(&scmd->cdb.g1_cdb, size);
1307 
1308 	scgp->cmdname = "send_cue_sheet";
1309 
1310 	if (scg_cmd(scgp) < 0)
1311 		return (-1);
1312 	return (size - scmd->resid);
1313 }
1314 
1315 EXPORT int
read_buff_cap(scgp,sp,fp)1316 read_buff_cap(scgp, sp, fp)
1317 	SCSI	*scgp;
1318 	long	*sp;	/* Size pointer */
1319 	long	*fp;	/* Free pointer */
1320 {
1321 	char	resp[12];
1322 	Ulong	freespace;
1323 	Ulong	bufsize;
1324 	int	per;
1325 	register struct	scg_cmd	*scmd = scgp->scmd;
1326 
1327 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1328 	scmd->addr = (caddr_t)resp;
1329 	scmd->size = sizeof (resp);
1330 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1331 	scmd->cdb_len = SC_G1_CDBLEN;
1332 	scmd->sense_len = CCS_SENSE_LEN;
1333 	scmd->cdb.g1_cdb.cmd = 0x5C;		/* Read buffer cap */
1334 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1335 	g1_cdblen(&scmd->cdb.g1_cdb, sizeof (resp));
1336 
1337 	scgp->cmdname = "read buffer cap";
1338 
1339 	if (scg_cmd(scgp) < 0)
1340 		return (-1);
1341 
1342 	bufsize   = a_to_u_4_byte(&resp[4]);
1343 	freespace = a_to_u_4_byte(&resp[8]);
1344 	if (sp)
1345 		*sp = bufsize;
1346 	if (fp)
1347 		*fp = freespace;
1348 
1349 	if (scgp->verbose || (sp == 0 && fp == 0))
1350 		printf(_("BFree: %ld K BSize: %ld K\n"), freespace >> 10, bufsize >> 10);
1351 
1352 	if (bufsize == 0)
1353 		return (0);
1354 	per = (100 * (bufsize - freespace)) / bufsize;
1355 	if (per < 0)
1356 		return (0);
1357 	if (per > 100)
1358 		return (100);
1359 	return (per);
1360 }
1361 
1362 EXPORT int
scsi_blank(scgp,addr,blanktype,immed)1363 scsi_blank(scgp, addr, blanktype, immed)
1364 	SCSI	*scgp;
1365 	long	addr;
1366 	int	blanktype;
1367 	BOOL	immed;
1368 {
1369 	register struct	scg_cmd	*scmd = scgp->scmd;
1370 
1371 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1372 	scmd->flags = SCG_DISRE_ENA;
1373 	scmd->cdb_len = SC_G5_CDBLEN;
1374 	scmd->sense_len = CCS_SENSE_LEN;
1375 	scmd->timeout = 160 * 60; /* full blank at 1x could take 80 minutes */
1376 	scmd->cdb.g5_cdb.cmd = 0xA1;	/* Blank */
1377 	scmd->cdb.g0_cdb.high_addr = blanktype;
1378 	g1_cdbaddr(&scmd->cdb.g5_cdb, addr);
1379 
1380 	if (immed)
1381 		scmd->cdb.g5_cdb.res |= 8;
1382 /*		scmd->cdb.cmd_cdb[1] |= 0x10;*/
1383 
1384 	scgp->cmdname = "blank unit";
1385 
1386 	return (scg_cmd(scgp));
1387 }
1388 
1389 /*
1390  * XXX First try to handle ATAPI:
1391  * XXX ATAPI cannot handle SCSI 6 byte commands.
1392  * XXX We try to simulate 6 byte mode sense/select.
1393  */
1394 LOCAL BOOL	is_atapi;
1395 
1396 EXPORT BOOL
allow_atapi(scgp,new)1397 allow_atapi(scgp, new)
1398 	SCSI	*scgp;
1399 	BOOL	new;
1400 {
1401 	BOOL	old = is_atapi;
1402 	Uchar	mode[256];
1403 
1404 	if (new == old)
1405 		return (old);
1406 
1407 	scgp->silent++;
1408 	/*
1409 	 * If a bad drive has been reset before, we may need to fire up two
1410 	 * test unit ready commands to clear status.
1411 	 */
1412 	(void) unit_ready(scgp);
1413 	if (new &&
1414 	    mode_sense_g1(scgp, mode, 8, 0x3F, 0) < 0) {	/* All pages current */
1415 		new = FALSE;
1416 	}
1417 	scgp->silent--;
1418 
1419 	is_atapi = new;
1420 	return (old);
1421 }
1422 
1423 EXPORT int
mode_select(scgp,dp,cnt,smp,pf)1424 mode_select(scgp, dp, cnt, smp, pf)
1425 	SCSI	*scgp;
1426 	Uchar	*dp;
1427 	int	cnt;
1428 	int	smp;
1429 	int	pf;
1430 {
1431 	if (is_atapi)
1432 		return (mode_select_sg0(scgp, dp, cnt, smp, pf));
1433 	return (mode_select_g0(scgp, dp, cnt, smp, pf));
1434 }
1435 
1436 EXPORT int
mode_sense(scgp,dp,cnt,page,pcf)1437 mode_sense(scgp, dp, cnt, page, pcf)
1438 	SCSI	*scgp;
1439 	Uchar	*dp;
1440 	int	cnt;
1441 	int	page;
1442 	int	pcf;
1443 {
1444 	if (is_atapi)
1445 		return (mode_sense_sg0(scgp, dp, cnt, page, pcf));
1446 	return (mode_sense_g0(scgp, dp, cnt, page, pcf));
1447 }
1448 
1449 /*
1450  * Simulate mode select g0 with mode select g1.
1451  */
1452 EXPORT int
mode_select_sg0(scgp,dp,cnt,smp,pf)1453 mode_select_sg0(scgp, dp, cnt, smp, pf)
1454 	SCSI	*scgp;
1455 	Uchar	*dp;
1456 	int	cnt;
1457 	int	smp;
1458 	int	pf;
1459 {
1460 	Uchar	xmode[256+4];
1461 	int	amt = cnt;
1462 
1463 	if (amt < 1 || amt > 255) {
1464 		/* XXX clear SCSI error codes ??? */
1465 		return (-1);
1466 	}
1467 
1468 	if (amt < 4) {		/* Data length. medium type & VU */
1469 		amt += 1;
1470 	} else {
1471 		amt += 4;
1472 		movebytes(&dp[4], &xmode[8], cnt-4);
1473 	}
1474 	xmode[0] = 0;
1475 	xmode[1] = 0;
1476 	xmode[2] = dp[1];
1477 	xmode[3] = dp[2];
1478 	xmode[4] = 0;
1479 	xmode[5] = 0;
1480 	i_to_2_byte(&xmode[6], (unsigned int)dp[3]);
1481 
1482 	if (scgp->verbose) scg_prbytes(_("Mode Parameters (un-converted)"), dp, cnt);
1483 
1484 	return (mode_select_g1(scgp, xmode, amt, smp, pf));
1485 }
1486 
1487 /*
1488  * Simulate mode sense g0 with mode sense g1.
1489  */
1490 EXPORT int
mode_sense_sg0(scgp,dp,cnt,page,pcf)1491 mode_sense_sg0(scgp, dp, cnt, page, pcf)
1492 	SCSI	*scgp;
1493 	Uchar	*dp;
1494 	int	cnt;
1495 	int	page;
1496 	int	pcf;
1497 {
1498 	Uchar	xmode[256+4];
1499 	int	amt = cnt;
1500 	int	len;
1501 
1502 	if (amt < 1 || amt > 255) {
1503 		/* XXX clear SCSI error codes ??? */
1504 		return (-1);
1505 	}
1506 
1507 	fillbytes((caddr_t)xmode, sizeof (xmode), '\0');
1508 	if (amt < 4) {		/* Data length. medium type & VU */
1509 		amt += 1;
1510 	} else {
1511 		amt += 4;
1512 	}
1513 	if (mode_sense_g1(scgp, xmode, amt, page, pcf) < 0)
1514 		return (-1);
1515 
1516 	amt = cnt - scg_getresid(scgp);
1517 /*
1518  * For tests: Solaris 8 & LG CD-ROM always returns resid == amt
1519  */
1520 /*	amt = cnt;*/
1521 	if (amt > 4)
1522 		movebytes(&xmode[8], &dp[4], amt-4);
1523 	len = a_to_u_2_byte(xmode);
1524 	if (len == 0) {
1525 		dp[0] = 0;
1526 	} else if (len < 6) {
1527 		if (len > 2)
1528 			len = 2;
1529 		dp[0] = len;
1530 	} else {
1531 		dp[0] = len - 3;
1532 	}
1533 	dp[1] = xmode[2];
1534 	dp[2] = xmode[3];
1535 	len = a_to_u_2_byte(&xmode[6]);
1536 	dp[3] = len;
1537 
1538 	if (scgp->verbose) scg_prbytes(_("Mode Sense Data (converted)"), dp, amt);
1539 	return (0);
1540 }
1541 
1542 EXPORT int
mode_select_g0(scgp,dp,cnt,smp,pf)1543 mode_select_g0(scgp, dp, cnt, smp, pf)
1544 	SCSI	*scgp;
1545 	Uchar	*dp;
1546 	int	cnt;
1547 	int	smp;
1548 	int	pf;
1549 {
1550 	register struct	scg_cmd	*scmd = scgp->scmd;
1551 
1552 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1553 	scmd->addr = (caddr_t)dp;
1554 	scmd->size = cnt;
1555 	scmd->flags = SCG_DISRE_ENA;
1556 	scmd->cdb_len = SC_G0_CDBLEN;
1557 	scmd->sense_len = CCS_SENSE_LEN;
1558 	scmd->cdb.g0_cdb.cmd = SC_MODE_SELECT;
1559 	scmd->cdb.g0_cdb.lun = scg_lun(scgp);
1560 	scmd->cdb.g0_cdb.high_addr = smp ? 1 : 0 | pf ? 0x10 : 0;
1561 	scmd->cdb.g0_cdb.count = cnt;
1562 
1563 	if (scgp->verbose) {
1564 		error("%s ", smp?_("Save"):_("Set "));
1565 		scg_prbytes(_("Mode Parameters"), dp, cnt);
1566 	}
1567 
1568 	scgp->cmdname = "mode select g0";
1569 
1570 	return (scg_cmd(scgp));
1571 }
1572 
1573 EXPORT int
mode_select_g1(scgp,dp,cnt,smp,pf)1574 mode_select_g1(scgp, dp, cnt, smp, pf)
1575 	SCSI	*scgp;
1576 	Uchar	*dp;
1577 	int	cnt;
1578 	int	smp;
1579 	int	pf;
1580 {
1581 	register struct	scg_cmd	*scmd = scgp->scmd;
1582 
1583 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1584 	scmd->addr = (caddr_t)dp;
1585 	scmd->size = cnt;
1586 	scmd->flags = SCG_DISRE_ENA;
1587 	scmd->cdb_len = SC_G1_CDBLEN;
1588 	scmd->sense_len = CCS_SENSE_LEN;
1589 	scmd->cdb.g1_cdb.cmd = 0x55;
1590 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1591 	scmd->cdb.g0_cdb.high_addr = smp ? 1 : 0 | pf ? 0x10 : 0;
1592 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1593 
1594 	if (scgp->verbose) {
1595 		printf("%s ", smp?_("Save"):_("Set "));
1596 		scg_prbytes(_("Mode Parameters"), dp, cnt);
1597 	}
1598 
1599 	scgp->cmdname = "mode select g1";
1600 
1601 	return (scg_cmd(scgp));
1602 }
1603 
1604 EXPORT int
mode_sense_g0(scgp,dp,cnt,page,pcf)1605 mode_sense_g0(scgp, dp, cnt, page, pcf)
1606 	SCSI	*scgp;
1607 	Uchar	*dp;
1608 	int	cnt;
1609 	int	page;
1610 	int	pcf;
1611 {
1612 	register struct	scg_cmd	*scmd = scgp->scmd;
1613 
1614 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1615 	scmd->addr = (caddr_t)dp;
1616 	scmd->size = 0xFF;
1617 	scmd->size = cnt;
1618 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1619 	scmd->cdb_len = SC_G0_CDBLEN;
1620 	scmd->sense_len = CCS_SENSE_LEN;
1621 	scmd->cdb.g0_cdb.cmd = SC_MODE_SENSE;
1622 	scmd->cdb.g0_cdb.lun = scg_lun(scgp);
1623 #ifdef	nonono
1624 	scmd->cdb.g0_cdb.high_addr = 1<<4;	/* DBD Disable Block desc. */
1625 #endif
1626 	scmd->cdb.g0_cdb.mid_addr = (page&0x3F) | ((pcf<<6)&0xC0);
1627 	scmd->cdb.g0_cdb.count = page ? 0xFF : 24;
1628 	scmd->cdb.g0_cdb.count = cnt;
1629 
1630 	scgp->cmdname = "mode sense g0";
1631 
1632 	if (scg_cmd(scgp) < 0)
1633 		return (-1);
1634 	if (scgp->verbose) scg_prbytes(_("Mode Sense Data"), dp, cnt - scg_getresid(scgp));
1635 	return (0);
1636 }
1637 
1638 EXPORT int
mode_sense_g1(scgp,dp,cnt,page,pcf)1639 mode_sense_g1(scgp, dp, cnt, page, pcf)
1640 	SCSI	*scgp;
1641 	Uchar	*dp;
1642 	int	cnt;
1643 	int	page;
1644 	int	pcf;
1645 {
1646 	register struct	scg_cmd	*scmd = scgp->scmd;
1647 
1648 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1649 	scmd->addr = (caddr_t)dp;
1650 	scmd->size = cnt;
1651 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1652 	scmd->cdb_len = SC_G1_CDBLEN;
1653 	scmd->sense_len = CCS_SENSE_LEN;
1654 	scmd->cdb.g1_cdb.cmd = 0x5A;
1655 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1656 #ifdef	nonono
1657 	scmd->cdb.g0_cdb.high_addr = 1<<4;	/* DBD Disable Block desc. */
1658 #endif
1659 	scmd->cdb.g1_cdb.addr[0] = (page&0x3F) | ((pcf<<6)&0xC0);
1660 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1661 
1662 	scgp->cmdname = "mode sense g1";
1663 
1664 	if (scg_cmd(scgp) < 0)
1665 		return (-1);
1666 	if (scgp->verbose) scg_prbytes(_("Mode Sense Data"), dp, cnt - scg_getresid(scgp));
1667 	return (0);
1668 }
1669 
1670 struct trackdesc {
1671 	Uchar	res0;
1672 
1673 #if defined(_BIT_FIELDS_LTOH)		/* Intel byteorder */
1674 	Ucbit	control		: 4;
1675 	Ucbit	adr		: 4;
1676 #else					/* Motorola byteorder */
1677 	Ucbit	adr		: 4;
1678 	Ucbit	control		: 4;
1679 #endif
1680 
1681 	Uchar	track;
1682 	Uchar	res3;
1683 	Uchar	addr[4];
1684 };
1685 
1686 struct diskinfo {
1687 	struct tocheader	hd;
1688 	struct trackdesc	desc[1];
1689 };
1690 
1691 struct siheader {
1692 	Uchar	len[2];
1693 	Uchar	finished;
1694 	Uchar	unfinished;
1695 };
1696 
1697 struct sidesc {
1698 	Uchar	sess_number;
1699 	Uchar	res1;
1700 	Uchar	track;
1701 	Uchar	res3;
1702 	Uchar	addr[4];
1703 };
1704 
1705 struct sinfo {
1706 	struct siheader	hd;
1707 	struct sidesc	desc[1];
1708 };
1709 
1710 struct trackheader {
1711 	Uchar	mode;
1712 	Uchar	res[3];
1713 	Uchar	addr[4];
1714 };
1715 #define	TRM_ZERO	0
1716 #define	TRM_USER_ECC	1	/* 2048 bytes user data + 288 Bytes ECC/EDC */
1717 #define	TRM_USER	2	/* All user data (2336 bytes) */
1718 
1719 
1720 EXPORT	int
read_tochdr(scgp,dp,fp,lp)1721 read_tochdr(scgp, dp, fp, lp)
1722 	SCSI	*scgp;
1723 	cdr_t	*dp;
1724 	int	*fp;
1725 	int	*lp;
1726 {
1727 	struct	tocheader *tp;
1728 	char	xb[256];
1729 	int	len;
1730 
1731 	tp = (struct tocheader *)xb;
1732 
1733 	fillbytes((caddr_t)xb, sizeof (xb), '\0');
1734 	if (read_toc(scgp, xb, 0, sizeof (struct tocheader), 0, FMT_TOC) < 0) {
1735 		if (scgp->silent == 0)
1736 			errmsgno(EX_BAD, _("Cannot read TOC header\n"));
1737 		return (-1);
1738 	}
1739 	len = a_to_u_2_byte(tp->len) + sizeof (struct tocheader)-2;
1740 	if (len >= 4) {
1741 		if (fp)
1742 			*fp = tp->first;
1743 		if (lp)
1744 			*lp = tp->last;
1745 		return (0);
1746 	}
1747 	return (-1);
1748 }
1749 
1750 EXPORT	int
read_cdtext(scgp)1751 read_cdtext(scgp)
1752 	SCSI	*scgp;
1753 {
1754 	struct	tocheader *tp;
1755 	char	xb[256];
1756 	int	len;
1757 	char	xxb[10000];
1758 
1759 	tp = (struct tocheader *)xb;
1760 
1761 	fillbytes((caddr_t)xb, sizeof (xb), '\0');
1762 	if (read_toc(scgp, xb, 0, sizeof (struct tocheader), 0, FMT_CDTEXT) < 0) {
1763 		if (scgp->silent == 0 || scgp->verbose > 0)
1764 			errmsgno(EX_BAD, _("Cannot read CD-Text header\n"));
1765 		return (-1);
1766 	}
1767 	len = a_to_u_2_byte(tp->len) + sizeof (struct tocheader)-2;
1768 	printf(_("CD-Text len: %d\n"), len);
1769 
1770 	if (read_toc(scgp, xxb, 0, len, 0, FMT_CDTEXT) < 0) {
1771 		if (scgp->silent == 0)
1772 			errmsgno(EX_BAD, _("Cannot read CD-Text\n"));
1773 		return (-1);
1774 	}
1775 	{
1776 		FILE	*f = fileopen("cdtext.dat", "wctb");
1777 		filewrite(f, xxb, len);
1778 	}
1779 	return (0);
1780 }
1781 
1782 EXPORT	int
read_trackinfo(scgp,track,offp,msfp,adrp,controlp,modep)1783 read_trackinfo(scgp, track, offp, msfp, adrp, controlp, modep)
1784 	SCSI	*scgp;
1785 	int	track;
1786 	long	*offp;
1787 	struct msf *msfp;
1788 	int	*adrp;
1789 	int	*controlp;
1790 	int	*modep;
1791 {
1792 	struct	diskinfo *dp;
1793 	char	xb[256];
1794 	int	len;
1795 	long	off;
1796 
1797 	dp = (struct diskinfo *)xb;
1798 
1799 	fillbytes((caddr_t)xb, sizeof (xb), '\0');
1800 	if (read_toc(scgp, xb, track, sizeof (struct diskinfo), 0, FMT_TOC) < 0) {
1801 		if (scgp->silent <= 0)
1802 			errmsgno(EX_BAD, _("Cannot read TOC\n"));
1803 		return (-1);
1804 	}
1805 	len = a_to_u_2_byte(dp->hd.len) + sizeof (struct tocheader)-2;
1806 	if (len <  (int)sizeof (struct diskinfo))
1807 		return (-1);
1808 
1809 	off = a_to_4_byte(dp->desc[0].addr);
1810 	if (offp)
1811 		*offp = off;
1812 	if (adrp)
1813 		*adrp = dp->desc[0].adr;
1814 	if (controlp)
1815 		*controlp = dp->desc[0].control;
1816 
1817 	if (msfp) {
1818 		scgp->silent++;
1819 		if (read_toc(scgp, xb, track, sizeof (struct diskinfo), 1, FMT_TOC)
1820 									>= 0) {
1821 			msfp->msf_min = dp->desc[0].addr[1];
1822 			msfp->msf_sec = dp->desc[0].addr[2];
1823 			msfp->msf_frame = dp->desc[0].addr[3];
1824 		} else if (read_toc(scgp, xb, track, sizeof (struct diskinfo), 0, FMT_TOC)
1825 									>= 0) {
1826 			/*
1827 			 * Some drives (e.g. the Philips CDD-522) don't support
1828 			 * to read the TOC in MSF mode.
1829 			 */
1830 			long moff = a_to_4_byte(dp->desc[0].addr);
1831 
1832 			lba_to_msf(moff, msfp);
1833 		} else {
1834 			msfp->msf_min = 0;
1835 			msfp->msf_sec = 0;
1836 			msfp->msf_frame = 0;
1837 		}
1838 		scgp->silent--;
1839 	}
1840 
1841 	if (modep == NULL)
1842 		return (0);
1843 
1844 	if (track == 0xAA) {
1845 		*modep = -1;
1846 		return (0);
1847 	}
1848 
1849 	fillbytes((caddr_t)xb, sizeof (xb), '\0');
1850 
1851 	scgp->silent++;
1852 	if (read_header(scgp, xb, off, 8, 0) >= 0) {
1853 		*modep = xb[0];
1854 	} else if (read_track_info_philips(scgp, xb, track, 14) >= 0) {
1855 		*modep = xb[0xb] & 0xF;
1856 	} else {
1857 		*modep = -1;
1858 	}
1859 	scgp->silent--;
1860 	return (0);
1861 }
1862 
1863 EXPORT	int
read_B0(scgp,isbcd,b0p,lop)1864 read_B0(scgp, isbcd, b0p, lop)
1865 	SCSI	*scgp;
1866 	BOOL	isbcd;
1867 	long	*b0p;
1868 	long	*lop;
1869 {
1870 	struct	fdiskinfo *dp;
1871 	struct	ftrackdesc *tp;
1872 	char	xb[8192];
1873 	char	*pe;
1874 	int	len;
1875 	long	l;
1876 
1877 	dp = (struct fdiskinfo *)xb;
1878 
1879 	fillbytes((caddr_t)xb, sizeof (xb), '\0');
1880 	if (read_toc_philips(scgp, xb, 1, sizeof (struct tocheader), 0, FMT_FULLTOC) < 0) {
1881 		return (-1);
1882 	}
1883 	len = a_to_u_2_byte(dp->hd.len) + sizeof (struct tocheader)-2;
1884 	if (len <  (int)sizeof (struct fdiskinfo))
1885 		return (-1);
1886 	if (read_toc_philips(scgp, xb, 1, len, 0, FMT_FULLTOC) < 0) {
1887 		return (-1);
1888 	}
1889 	if (scgp->verbose) {
1890 		scg_prbytes(_("TOC data: "), (Uchar *)xb,
1891 			len > (int)sizeof (xb) - scg_getresid(scgp) ?
1892 				sizeof (xb) - scg_getresid(scgp) : len);
1893 
1894 		tp = &dp->desc[0];
1895 		pe = &xb[len];
1896 
1897 		while ((char *)tp < pe) {
1898 			scg_prbytes(_("ENT: "), (Uchar *)tp, 11);
1899 			tp++;
1900 		}
1901 	}
1902 	tp = &dp->desc[0];
1903 	pe = &xb[len];
1904 
1905 	for (; (char *)tp < pe; tp++) {
1906 		if (tp->sess_number != dp->hd.last)
1907 			continue;
1908 		if (tp->point != 0xB0)
1909 			continue;
1910 		if (scgp->verbose)
1911 			scg_prbytes("B0: ", (Uchar *)tp, 11);
1912 		if (isbcd) {
1913 			l = msf_to_lba(from_bcd(tp->amin),
1914 				from_bcd(tp->asec),
1915 				from_bcd(tp->aframe), TRUE);
1916 		} else {
1917 			l = msf_to_lba(tp->amin,
1918 				tp->asec,
1919 				tp->aframe, TRUE);
1920 		}
1921 		if (b0p)
1922 			*b0p = l;
1923 
1924 		if (scgp->verbose)
1925 			printf(_("B0 start: %ld\n"), l);
1926 
1927 		if (isbcd) {
1928 			l = msf_to_lba(from_bcd(tp->pmin),
1929 				from_bcd(tp->psec),
1930 				from_bcd(tp->pframe), TRUE);
1931 		} else {
1932 			l = msf_to_lba(tp->pmin,
1933 				tp->psec,
1934 				tp->pframe, TRUE);
1935 		}
1936 
1937 		if (scgp->verbose)
1938 			printf(("B0 lout: %ld\n"), l);
1939 		if (lop)
1940 			*lop = l;
1941 		return (0);
1942 	}
1943 	return (-1);
1944 }
1945 
1946 
1947 /*
1948  * Return address of first track in last session (SCSI-3/mmc version).
1949  */
1950 EXPORT int
read_session_offset(scgp,offp)1951 read_session_offset(scgp, offp)
1952 	SCSI	*scgp;
1953 	long	*offp;
1954 {
1955 	struct	diskinfo *dp;
1956 	char	xb[256];
1957 	int	len;
1958 
1959 	dp = (struct diskinfo *)xb;
1960 
1961 	fillbytes((caddr_t)xb, sizeof (xb), '\0');
1962 	if (read_toc(scgp, (caddr_t)xb, 0, sizeof (struct tocheader), 0, FMT_SINFO) < 0)
1963 		return (-1);
1964 
1965 	if (scgp->verbose)
1966 		scg_prbytes(_("tocheader: "),
1967 		(Uchar *)xb, sizeof (struct tocheader) - scg_getresid(scgp));
1968 
1969 	len = a_to_u_2_byte(dp->hd.len) + sizeof (struct tocheader)-2;
1970 	if (len > (int)sizeof (xb)) {
1971 		errmsgno(EX_BAD, _("Session info too big.\n"));
1972 		return (-1);
1973 	}
1974 	if (read_toc(scgp, (caddr_t)xb, 0, len, 0, FMT_SINFO) < 0)
1975 		return (-1);
1976 
1977 	if (scgp->verbose)
1978 		scg_prbytes(_("tocheader: "),
1979 			(Uchar *)xb, len - scg_getresid(scgp));
1980 
1981 	dp = (struct diskinfo *)xb;
1982 	if (offp)
1983 		*offp = a_to_u_4_byte(dp->desc[0].addr);
1984 	return (0);
1985 }
1986 
1987 /*
1988  * Return address of first track in last session (pre SCSI-3 version).
1989  */
1990 EXPORT int
read_session_offset_philips(scgp,offp)1991 read_session_offset_philips(scgp, offp)
1992 	SCSI	*scgp;
1993 	long	*offp;
1994 {
1995 	struct	sinfo *sp;
1996 	char	xb[256];
1997 	int	len;
1998 
1999 	sp = (struct sinfo *)xb;
2000 
2001 	fillbytes((caddr_t)xb, sizeof (xb), '\0');
2002 	if (read_toc_philips(scgp, (caddr_t)xb, 0, sizeof (struct siheader), 0, FMT_SINFO) < 0)
2003 		return (-1);
2004 	len = a_to_u_2_byte(sp->hd.len) + sizeof (struct siheader)-2;
2005 	if (len > (int)sizeof (xb)) {
2006 		errmsgno(EX_BAD, _("Session info too big.\n"));
2007 		return (-1);
2008 	}
2009 	if (read_toc_philips(scgp, (caddr_t)xb, 0, len, 0, FMT_SINFO) < 0)
2010 		return (-1);
2011 	/*
2012 	 * Old drives return the number of finished sessions in first/finished
2013 	 * a descriptor is returned for each session.
2014 	 * New drives return the number of the first and last session
2015 	 * one descriptor for the last finished session is returned
2016 	 * as in SCSI-3
2017 	 * In all cases the lowest session number is set to 1.
2018 	 */
2019 	sp = (struct sinfo *)xb;
2020 	if (offp)
2021 		*offp = a_to_u_4_byte(sp->desc[sp->hd.finished-1].addr);
2022 	return (0);
2023 }
2024 
2025 EXPORT int
sense_secsize(scgp,current)2026 sense_secsize(scgp, current)
2027 	SCSI	*scgp;
2028 	int	current;
2029 {
2030 	Uchar	mode[0x100];
2031 	Uchar	*p;
2032 	Uchar	*ep;
2033 	int	len;
2034 	int	secsize = -1;
2035 
2036 	scgp->silent++;
2037 	(void) unit_ready(scgp);
2038 	scgp->silent--;
2039 
2040 	/* XXX Quick and dirty, musz verallgemeinert werden !!! */
2041 
2042 	fillbytes(mode, sizeof (mode), '\0');
2043 	scgp->silent++;
2044 
2045 	len =	sizeof (struct scsi_mode_header) +
2046 		sizeof (struct scsi_mode_blockdesc);
2047 	/*
2048 	 * Wenn wir hier get_mode_params() nehmen bekommen wir die Warnung:
2049 	 * Warning: controller returns wrong page 1 for All pages page (3F).
2050 	 */
2051 	if (mode_sense(scgp, mode, len, 0x3F, current?0:2) < 0) {
2052 		fillbytes(mode, sizeof (mode), '\0');
2053 		if (mode_sense(scgp, mode, len, 0, current?0:2) < 0)	{ /* VU (block desc) */
2054 			scgp->silent--;
2055 			return (-1);
2056 		}
2057 	}
2058 	if (mode[3] == 8) {
2059 		if (scgp->debug) {
2060 			printf(_("Density: 0x%X\n"), mode[4]);
2061 			printf(_("Blocks:  %ld\n"), a_to_u_3_byte(&mode[5]));
2062 			printf(_("Blocklen:%ld\n"), a_to_u_3_byte(&mode[9]));
2063 		}
2064 		secsize = a_to_u_3_byte(&mode[9]);
2065 	}
2066 	fillbytes(mode, sizeof (mode), '\0');
2067 	/*
2068 	 * The ACARD TECH AEC-7720 ATAPI<->SCSI adaptor
2069 	 * chokes if we try to transfer more than 0x40 bytes with
2070 	 * mode_sense of all pages. So try to avoid to run this
2071 	 * command if possible.
2072 	 */
2073 	if (scgp->debug &&
2074 	    mode_sense(scgp, mode, 0xFE, 0x3F, current?0:2) >= 0) {	/* All Pages */
2075 
2076 		ep = mode+mode[0];	/* Points to last byte of data */
2077 		p = &mode[4];
2078 		p += mode[3];
2079 		printf(_("Pages: "));
2080 		while (p < ep) {
2081 			printf("0x%X ", *p&0x3F);
2082 			p += p[1]+2;
2083 		}
2084 		printf("\n");
2085 	}
2086 	scgp->silent--;
2087 
2088 	return (secsize);
2089 }
2090 
2091 EXPORT int
select_secsize(scgp,secsize)2092 select_secsize(scgp, secsize)
2093 	SCSI	*scgp;
2094 	int	secsize;
2095 {
2096 	struct scsi_mode_data md;
2097 	int	count = sizeof (struct scsi_mode_header) +
2098 			sizeof (struct scsi_mode_blockdesc);
2099 
2100 	(void) test_unit_ready(scgp);	/* clear any error situation */
2101 
2102 	fillbytes((caddr_t)&md, sizeof (md), '\0');
2103 	md.header.blockdesc_len = 8;
2104 	i_to_3_byte(md.blockdesc.lblen, secsize);
2105 
2106 	return (mode_select(scgp, (Uchar *)&md, count, 0, scgp->inq->data_format >= 2));
2107 }
2108 
2109 EXPORT BOOL
is_cddrive(scgp)2110 is_cddrive(scgp)
2111 	SCSI	*scgp;
2112 {
2113 	return (scgp->inq->type == INQ_ROMD || scgp->inq->type == INQ_WORM);
2114 }
2115 
2116 EXPORT BOOL
is_unknown_dev(scgp)2117 is_unknown_dev(scgp)
2118 	SCSI	*scgp;
2119 {
2120 	return (scgp->dev == DEV_UNKNOWN);
2121 }
2122 
2123 #ifndef	DEBUG
2124 #define	DEBUG
2125 #endif
2126 #ifdef	DEBUG
2127 
2128 EXPORT int
read_scsi(scgp,bp,addr,cnt)2129 read_scsi(scgp, bp, addr, cnt)
2130 	SCSI	*scgp;
2131 	caddr_t	bp;
2132 	long	addr;
2133 	int	cnt;
2134 {
2135 	if (addr <= G0_MAXADDR && cnt < 256 && !is_atapi)
2136 		return (read_g0(scgp, bp, addr, cnt));
2137 	else
2138 		return (read_g1(scgp, bp, addr, cnt));
2139 }
2140 
2141 EXPORT int
read_g0(scgp,bp,addr,cnt)2142 read_g0(scgp, bp, addr, cnt)
2143 	SCSI	*scgp;
2144 	caddr_t	bp;
2145 	long	addr;
2146 	int	cnt;
2147 {
2148 	register struct	scg_cmd	*scmd = scgp->scmd;
2149 
2150 	if (scgp->cap->c_bsize <= 0)
2151 		raisecond("capacity_not_set", 0L);
2152 
2153 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
2154 	scmd->addr = bp;
2155 	scmd->size = cnt*scgp->cap->c_bsize;
2156 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
2157 	scmd->cdb_len = SC_G0_CDBLEN;
2158 	scmd->sense_len = CCS_SENSE_LEN;
2159 	scmd->cdb.g0_cdb.cmd = SC_READ;
2160 	scmd->cdb.g0_cdb.lun = scg_lun(scgp);
2161 	g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
2162 	scmd->cdb.g0_cdb.count = cnt;
2163 /*	scmd->cdb.g0_cdb.vu_56 = 1;*/
2164 
2165 	scgp->cmdname = "read_g0";
2166 
2167 	return (scg_cmd(scgp));
2168 }
2169 
2170 EXPORT int
read_g1(scgp,bp,addr,cnt)2171 read_g1(scgp, bp, addr, cnt)
2172 	SCSI	*scgp;
2173 	caddr_t	bp;
2174 	long	addr;
2175 	int	cnt;
2176 {
2177 	register struct	scg_cmd	*scmd = scgp->scmd;
2178 
2179 	if (scgp->cap->c_bsize <= 0)
2180 		raisecond("capacity_not_set", 0L);
2181 
2182 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
2183 	scmd->addr = bp;
2184 	scmd->size = cnt*scgp->cap->c_bsize;
2185 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
2186 	scmd->cdb_len = SC_G1_CDBLEN;
2187 	scmd->sense_len = CCS_SENSE_LEN;
2188 	scmd->cdb.g1_cdb.cmd = SC_EREAD;
2189 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
2190 	g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
2191 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
2192 
2193 	scgp->cmdname = "read_g1";
2194 
2195 	return (scg_cmd(scgp));
2196 }
2197 #endif	/* DEBUG */
2198 
2199 EXPORT BOOL
getdev(scgp,print)2200 getdev(scgp, print)
2201 	SCSI	*scgp;
2202 	BOOL	print;
2203 {
2204 		BOOL	got_inquiry = TRUE;
2205 		char	vendor_info[8+1];
2206 		char	prod_ident[16+1];
2207 		char	prod_revision[4+1];
2208 		int	inq_len = 0;
2209 	register struct	scg_cmd	*scmd = scgp->scmd;
2210 	register struct scsi_inquiry *inq = scgp->inq;
2211 
2212 
2213 	fillbytes((caddr_t)inq, sizeof (*inq), '\0');
2214 	scgp->dev = DEV_UNKNOWN;
2215 	scgp->silent++;
2216 	(void) unit_ready(scgp);
2217 	if (scmd->error >= SCG_FATAL &&
2218 				!(scmd->scb.chk && scmd->sense_count > 0)) {
2219 		scgp->silent--;
2220 		return (FALSE);
2221 	}
2222 
2223 
2224 /*	if (scmd->error < SCG_FATAL || scmd->scb.chk && scmd->sense_count > 0){*/
2225 
2226 	if (inquiry(scgp, (caddr_t)inq, sizeof (*inq)) < 0) {
2227 		got_inquiry = FALSE;
2228 	} else {
2229 		inq_len = sizeof (*inq) - scg_getresid(scgp);
2230 	}
2231 	if (!got_inquiry) {
2232 		if (scgp->verbose) {
2233 			printf(
2234 		_("error: %d scb.chk: %d sense_count: %d sense.code: 0x%x\n"),
2235 				scmd->error, scmd->scb.chk,
2236 				scmd->sense_count, scmd->sense.code);
2237 		}
2238 			/*
2239 			 * Folgende Kontroller kennen das Kommando
2240 			 * INQUIRY nicht:
2241 			 *
2242 			 * ADAPTEC	ACB-4000, ACB-4010, ACB 4070
2243 			 * SYSGEN	SC4000
2244 			 *
2245 			 * Leider reagieren ACB40X0 und ACB5500 identisch
2246 			 * wenn drive not ready (code == not ready),
2247 			 * sie sind dann nicht zu unterscheiden.
2248 			 */
2249 
2250 		if (scmd->scb.chk && scmd->sense_count == 4) {
2251 			/* Test auf SYSGEN				 */
2252 			(void) qic02(scgp, 0x12);	/* soft lock on  */
2253 			if (qic02(scgp, 1) < 0) {	/* soft lock off */
2254 				scgp->dev = DEV_ACB40X0;
2255 /*				scgp->dev = acbdev();*/
2256 			} else {
2257 				scgp->dev = DEV_SC4000;
2258 				inq->type = INQ_SEQD;
2259 				inq->removable = 1;
2260 			}
2261 		}
2262 	} else if (scgp->verbose) {
2263 		int	i;
2264 		int	len = inq->add_len + 5;
2265 		Uchar	ibuf[256+5];
2266 		Uchar	*ip = (Uchar *)inq;
2267 		Uchar	c;
2268 
2269 		if (len > (int)sizeof (*inq) &&
2270 				inquiry(scgp, (caddr_t)ibuf, inq->add_len+5) >= 0) {
2271 			len = inq->add_len+5 - scg_getresid(scgp);
2272 			ip = ibuf;
2273 		} else {
2274 			len = sizeof (*inq);
2275 		}
2276 		printf(_("Inquiry Data   : "));
2277 		for (i = 0; i < len; i++) {
2278 			c = ip[i];
2279 			if (c >= ' ' && c < 0177)
2280 				printf("%c", c);
2281 			else
2282 				printf(".");
2283 		}
2284 		printf("\n");
2285 	}
2286 
2287 	strncpy(vendor_info, inq->inq_vendor_info, sizeof (inq->inq_vendor_info));
2288 	strncpy(prod_ident, inq->inq_prod_ident, sizeof (inq->inq_prod_ident));
2289 	strncpy(prod_revision, inq->inq_prod_revision, sizeof (inq->inq_prod_revision));
2290 
2291 	vendor_info[sizeof (inq->inq_vendor_info)] = '\0';
2292 	prod_ident[sizeof (inq->inq_prod_ident)] = '\0';
2293 	prod_revision[sizeof (inq->inq_prod_revision)] = '\0';
2294 
2295 	switch (inq->type) {
2296 
2297 	case INQ_DASD:
2298 		if (inq->add_len == 0 && inq->inq_vendor_info[0] != '\0') {
2299 			Uchar	*p;
2300 			/*
2301 			 * NT-4.0 creates fake inquiry data for IDE disks.
2302 			 * Unfortunately, it does not set add_len wo we
2303 			 * check if vendor_info, prod_ident and prod_revision
2304 			 * contains valid chars for a CCS inquiry.
2305 			 */
2306 			if (inq_len >= 36)
2307 				inq->add_len = 31;
2308 
2309 			for (p = (Uchar *)&inq->inq_vendor_info[0];
2310 					p < (Uchar *)&inq->inq_prod_revision[4];
2311 									p++) {
2312 				if (*p < 0x20 || *p > 0x7E) {
2313 					inq->add_len = 0;
2314 					break;
2315 				}
2316 			}
2317 		}
2318 		if (inq->add_len == 0) {
2319 			if (scgp->dev == DEV_UNKNOWN && got_inquiry) {
2320 				scgp->dev = DEV_ACB5500;
2321 				strncpy(inq->inq_info_space,
2322 					"ADAPTEC ACB-5500        FAKE",
2323 					sizeof (inq->inq_info_space));
2324 
2325 			} else switch (scgp->dev) {
2326 
2327 			case DEV_ACB40X0:
2328 				strncpy(inq->inq_info_space,
2329 					"ADAPTEC ACB-40X0        FAKE",
2330 					sizeof (inq->inq_info_space));
2331 				break;
2332 			case DEV_ACB4000:
2333 				strncpy(inq->inq_info_space,
2334 					"ADAPTEC ACB-4000        FAKE",
2335 					sizeof (inq->inq_info_space));
2336 				break;
2337 			case DEV_ACB4010:
2338 				strncpy(inq->inq_info_space,
2339 					"ADAPTEC ACB-4010        FAKE",
2340 					sizeof (inq->inq_info_space));
2341 				break;
2342 			case DEV_ACB4070:
2343 				strncpy(inq->inq_info_space,
2344 					"ADAPTEC ACB-4070        FAKE",
2345 					sizeof (inq->inq_info_space));
2346 				break;
2347 			}
2348 		} else if (inq->add_len < 31) {
2349 			scgp->dev = DEV_NON_CCS_DSK;
2350 
2351 		} else if (strbeg("EMULEX", vendor_info)) {
2352 			if (strbeg("MD21", prod_ident))
2353 				scgp->dev = DEV_MD21;
2354 			if (strbeg("MD23", prod_ident))
2355 				scgp->dev = DEV_MD23;
2356 			else
2357 				scgp->dev = DEV_CCS_GENDISK;
2358 		} else if (strbeg("ADAPTEC", vendor_info)) {
2359 			if (strbeg("ACB-4520", prod_ident))
2360 				scgp->dev = DEV_ACB4520A;
2361 			if (strbeg("ACB-4525", prod_ident))
2362 				scgp->dev = DEV_ACB4525;
2363 			else
2364 				scgp->dev = DEV_CCS_GENDISK;
2365 		} else if (strbeg("SONY", vendor_info) &&
2366 					strbeg("SMO-C501", prod_ident)) {
2367 			scgp->dev = DEV_SONY_SMO;
2368 		} else {
2369 			scgp->dev = DEV_CCS_GENDISK;
2370 		}
2371 		break;
2372 
2373 	case INQ_SEQD:
2374 		if (scgp->dev == DEV_SC4000) {
2375 			strncpy(inq->inq_info_space,
2376 				"SYSGEN  SC4000          FAKE",
2377 					sizeof (inq->inq_info_space));
2378 		} else if (inq->add_len == 0 &&
2379 					inq->removable &&
2380 						inq->ansi_version == 1) {
2381 			scgp->dev = DEV_MT02;
2382 			strncpy(inq->inq_info_space,
2383 				"EMULEX  MT02            FAKE",
2384 					sizeof (inq->inq_info_space));
2385 		}
2386 		break;
2387 
2388 /*	case INQ_OPTD:*/
2389 	case INQ_ROMD:
2390 	case INQ_WORM:
2391 		if (strbeg("RXT-800S", prod_ident))
2392 			scgp->dev = DEV_RXT800S;
2393 
2394 		/*
2395 		 * Start of CD-Recorders:
2396 		 */
2397 		if (strbeg("ACER", vendor_info)) {
2398 			if (strbeg("CR-4020C", prod_ident))
2399 				scgp->dev = DEV_RICOH_RO_1420C;
2400 
2401 		} else if (strbeg("CREATIVE", vendor_info)) {
2402 			if (strbeg("CDR2000", prod_ident))
2403 				scgp->dev = DEV_RICOH_RO_1060C;
2404 
2405 		} else if (strbeg("GRUNDIG", vendor_info)) {
2406 			if (strbeg("CDR100IPW", prod_ident))
2407 				scgp->dev = DEV_CDD_2000;
2408 
2409 		} else if (strbeg("JVC", vendor_info)) {
2410 			if (strbeg("XR-W2001", prod_ident))
2411 				scgp->dev = DEV_TEAC_CD_R50S;
2412 			else if (strbeg("XR-W2010", prod_ident))
2413 				scgp->dev = DEV_TEAC_CD_R50S;
2414 			else if (strbeg("R2626", prod_ident))
2415 				scgp->dev = DEV_TEAC_CD_R50S;
2416 
2417 		} else if (strbeg("MITSBISH", vendor_info)) {
2418 
2419 #ifdef	XXXX_REALLY
2420 			/* It's MMC compliant */
2421 			if (strbeg("CDRW226", prod_ident))
2422 				scgp->dev = DEV_MMC_CDRW;
2423 #else
2424 			/* EMPTY */
2425 #endif
2426 
2427 		} else if (strbeg("MITSUMI", vendor_info)) {
2428 			/* Don't know any product string */
2429 			scgp->dev = DEV_CDD_522;
2430 
2431 		} else if (strbeg("OPTIMA", vendor_info)) {
2432 			if (strbeg("CD-R 650", prod_ident))
2433 				scgp->dev = DEV_SONY_CDU_924;
2434 
2435 		} else if (strbeg("PHILIPS", vendor_info) ||
2436 				strbeg("IMS", vendor_info) ||
2437 				strbeg("KODAK", vendor_info) ||
2438 				strbeg("HP", vendor_info)) {
2439 
2440 			if (strbeg("CDD521/00", prod_ident))
2441 				scgp->dev = DEV_CDD_521_OLD;
2442 			else if (strbeg("CDD521/02", prod_ident))
2443 				scgp->dev = DEV_CDD_521_OLD;		/* PCD 200R? */
2444 			else if (strbeg("CDD521", prod_ident))
2445 				scgp->dev = DEV_CDD_521;
2446 
2447 			if (strbeg("CDD522", prod_ident))
2448 				scgp->dev = DEV_CDD_522;
2449 			if (strbeg("PCD225", prod_ident))
2450 				scgp->dev = DEV_CDD_522;
2451 			if (strbeg("KHSW/OB", prod_ident))	/* PCD600 */
2452 				scgp->dev = DEV_PCD_600;
2453 			if (strbeg("CDR-240", prod_ident))
2454 				scgp->dev = DEV_CDD_2000;
2455 
2456 			if (strbeg("CDD20", prod_ident))
2457 				scgp->dev = DEV_CDD_2000;
2458 			if (strbeg("CDD26", prod_ident))
2459 				scgp->dev = DEV_CDD_2600;
2460 
2461 			if (strbeg("C4324/C4325", prod_ident))
2462 				scgp->dev = DEV_CDD_2000;
2463 			if (strbeg("CD-Writer 6020", prod_ident))
2464 				scgp->dev = DEV_CDD_2600;
2465 
2466 		} else if (strbeg("PINNACLE", vendor_info)) {
2467 			if (strbeg("RCD-1000", prod_ident))
2468 				scgp->dev = DEV_TEAC_CD_R50S;
2469 			if (strbeg("RCD5020", prod_ident))
2470 				scgp->dev = DEV_TEAC_CD_R50S;
2471 			if (strbeg("RCD5040", prod_ident))
2472 				scgp->dev = DEV_TEAC_CD_R50S;
2473 			if (strbeg("RCD 4X4", prod_ident))
2474 				scgp->dev = DEV_TEAC_CD_R50S;
2475 
2476 		} else if (strbeg("PIONEER", vendor_info)) {
2477 			if (strbeg("CD-WO DW-S114X", prod_ident))
2478 				scgp->dev = DEV_PIONEER_DW_S114X;
2479 			else if (strbeg("CD-WO DR-R504X", prod_ident))	/* Reoprt from philip@merge.com */
2480 				scgp->dev = DEV_PIONEER_DW_S114X;
2481 			else if (strbeg("DVD-R DVR-S101", prod_ident))
2482 				scgp->dev = DEV_PIONEER_DVDR_S101;
2483 
2484 		} else if (strbeg("PLASMON", vendor_info)) {
2485 			if (strbeg("RF4100", prod_ident))
2486 				scgp->dev = DEV_PLASMON_RF_4100;
2487 			else if (strbeg("CDR4220", prod_ident))
2488 				scgp->dev = DEV_CDD_2000;
2489 
2490 		} else if (strbeg("PLEXTOR", vendor_info)) {
2491 			if (strbeg("CD-R   PX-R24CS", prod_ident))
2492 				scgp->dev = DEV_RICOH_RO_1420C;
2493 
2494 		} else if (strbeg("RICOH", vendor_info)) {
2495 			if (strbeg("RO-1420C", prod_ident))
2496 				scgp->dev = DEV_RICOH_RO_1420C;
2497 			if (strbeg("RO1060C", prod_ident))
2498 				scgp->dev = DEV_RICOH_RO_1060C;
2499 
2500 		} else if (strbeg("SAF", vendor_info)) {	/* Smart & Friendly */
2501 			if (strbeg("CD-R2004", prod_ident) ||
2502 			    strbeg("CD-R2006 ", prod_ident))
2503 				scgp->dev = DEV_SONY_CDU_924;
2504 			else if (strbeg("CD-R2006PLUS", prod_ident))
2505 				scgp->dev = DEV_TEAC_CD_R50S;
2506 			else if (strbeg("CD-RW226", prod_ident))
2507 				scgp->dev = DEV_TEAC_CD_R50S;
2508 			else if (strbeg("CD-R4012", prod_ident))
2509 				scgp->dev = DEV_TEAC_CD_R50S;
2510 
2511 		} else if (strbeg("SANYO", vendor_info)) {
2512 			if (strbeg("CD-WO CRD-R24S", prod_ident))
2513 				scgp->dev = DEV_CDD_521;
2514 
2515 		} else if (strbeg("SONY", vendor_info)) {
2516 			if (strbeg("CD-R   CDU92", prod_ident) ||
2517 			    strbeg("CD-R   CDU94", prod_ident))
2518 				scgp->dev = DEV_SONY_CDU_924;
2519 
2520 		} else if (strbeg("TEAC", vendor_info)) {
2521 			if (strbeg("CD-R50S", prod_ident) ||
2522 			    strbeg("CD-R55S", prod_ident))
2523 				scgp->dev = DEV_TEAC_CD_R50S;
2524 
2525 		} else if (strbeg("TRAXDATA", vendor_info) ||
2526 				strbeg("Traxdata", vendor_info)) {
2527 			if (strbeg("CDR4120", prod_ident))
2528 				scgp->dev = DEV_TEAC_CD_R50S;
2529 
2530 		} else if (strbeg("T.YUDEN", vendor_info)) {
2531 			if (strbeg("CD-WO EW-50", prod_ident))
2532 				scgp->dev = DEV_TYUDEN_EW50;
2533 
2534 		} else if (strbeg("WPI", vendor_info)) {	/* Wearnes */
2535 			if (strbeg("CDR-632P", prod_ident))
2536 				scgp->dev = DEV_CDD_2600;
2537 
2538 		} else if (strbeg("YAMAHA", vendor_info)) {
2539 			if (strbeg("CDR10", prod_ident))
2540 				scgp->dev = DEV_YAMAHA_CDR_100;
2541 			if (strbeg("CDR200", prod_ident))
2542 				scgp->dev = DEV_YAMAHA_CDR_400;
2543 			if (strbeg("CDR400", prod_ident))
2544 				scgp->dev = DEV_YAMAHA_CDR_400;
2545 
2546 		} else if (strbeg("MATSHITA", vendor_info)) {
2547 			if (strbeg("CD-R   CW-7501", prod_ident))
2548 				scgp->dev = DEV_MATSUSHITA_7501;
2549 			if (strbeg("CD-R   CW-7502", prod_ident))
2550 				scgp->dev = DEV_MATSUSHITA_7502;
2551 		}
2552 		if (scgp->dev == DEV_UNKNOWN) {
2553 			/*
2554 			 * We do not have Manufacturer strings for
2555 			 * the following drives.
2556 			 */
2557 			if (strbeg("CDS615E", prod_ident))	/* Olympus */
2558 				scgp->dev = DEV_SONY_CDU_924;
2559 		}
2560 		if (scgp->dev == DEV_UNKNOWN && inq->type == INQ_ROMD) {
2561 			BOOL	cdrr	 = FALSE;
2562 			BOOL	cdwr	 = FALSE;
2563 			BOOL	cdrrw	 = FALSE;
2564 			BOOL	cdwrw	 = FALSE;
2565 			BOOL	dvd	 = FALSE;
2566 			BOOL	dvdwr	 = FALSE;
2567 
2568 			scgp->dev = DEV_CDROM;
2569 
2570 			if (mmc_check(scgp, &cdrr, &cdwr, &cdrrw, &cdwrw,
2571 								&dvd, &dvdwr))
2572 				scgp->dev = DEV_MMC_CDROM;
2573 			if (cdwr)
2574 				scgp->dev = DEV_MMC_CDR;
2575 			if (cdwrw)
2576 				scgp->dev = DEV_MMC_CDRW;
2577 			if (dvd)
2578 				scgp->dev = DEV_MMC_DVD;
2579 			if (dvdwr)
2580 				scgp->dev = DEV_MMC_DVD_WR;
2581 		}
2582 		break;
2583 
2584 	case INQ_PROCD:
2585 		if (strbeg("BERTHOLD", vendor_info)) {
2586 			if (strbeg("", prod_ident))
2587 				scgp->dev = DEV_HRSCAN;
2588 		}
2589 		break;
2590 
2591 	case INQ_SCAN:
2592 		scgp->dev = DEV_MS300A;
2593 		break;
2594 	}
2595 	scgp->silent--;
2596 	if (!print)
2597 		return (TRUE);
2598 
2599 	if (scgp->dev == DEV_UNKNOWN && !got_inquiry) {
2600 #ifdef	PRINT_INQ_ERR
2601 		scg_printerr(scgp);
2602 #endif
2603 		return (FALSE);
2604 	}
2605 
2606 	printinq(scgp, stdout);
2607 	return (TRUE);
2608 }
2609 
2610 EXPORT void
printinq(scgp,f)2611 printinq(scgp, f)
2612 	SCSI	*scgp;
2613 	FILE	*f;
2614 {
2615 	register struct scsi_inquiry *inq = scgp->inq;
2616 
2617 	fprintf(f, _("Device type    : "));
2618 	scg_fprintdev(f, inq);
2619 	fprintf(f, ("Version        : %d\n"), inq->ansi_version);
2620 	fprintf(f, _("Response Format: %d\n"), inq->data_format);
2621 	if (inq->data_format >= 2) {
2622 		fprintf(f, _("Capabilities   : "));
2623 		if (inq->aenc)		fprintf(f, "AENC ");
2624 		if (inq->termiop)	fprintf(f, "TERMIOP ");
2625 		if (inq->reladr)	fprintf(f, "RELADR ");
2626 		if (inq->wbus32)	fprintf(f, "WBUS32 ");
2627 		if (inq->wbus16)	fprintf(f, "WBUS16 ");
2628 		if (inq->sync)		fprintf(f, "SYNC ");
2629 		if (inq->linked)	fprintf(f, "LINKED ");
2630 		if (inq->cmdque)	fprintf(f, "CMDQUE ");
2631 		if (inq->softreset)	fprintf(f, "SOFTRESET ");
2632 		fprintf(f, "\n");
2633 	}
2634 	if (inq->add_len >= 31 ||
2635 			inq->inq_vendor_info[0] ||
2636 			inq->inq_prod_ident[0] ||
2637 			inq->inq_prod_revision[0]) {
2638 		fprintf(f, _("Vendor_info    : '%.8s'\n"), inq->inq_vendor_info);
2639 		fprintf(f, _("Identifikation : '%.16s'\n"), inq->inq_prod_ident);
2640 		fprintf(f, _("Revision       : '%.4s'\n"), inq->inq_prod_revision);
2641 	}
2642 }
2643 
2644 EXPORT void
printdev(scgp)2645 printdev(scgp)
2646 	SCSI	*scgp;
2647 {
2648 	printf(_("Device seems to be: "));
2649 
2650 	switch (scgp->dev) {
2651 
2652 	case DEV_UNKNOWN:	printf(_("unknown"));		break;
2653 	case DEV_ACB40X0:	printf("Adaptec 4000/4010/4070"); break;
2654 	case DEV_ACB4000:	printf("Adaptec 4000");		break;
2655 	case DEV_ACB4010:	printf("Adaptec 4010");		break;
2656 	case DEV_ACB4070:	printf("Adaptec 4070");		break;
2657 	case DEV_ACB5500:	printf("Adaptec 5500");		break;
2658 	case DEV_ACB4520A:	printf("Adaptec 4520A");	break;
2659 	case DEV_ACB4525:	printf("Adaptec 4525");		break;
2660 	case DEV_MD21:		printf("Emulex MD21");		break;
2661 	case DEV_MD23:		printf("Emulex MD23");		break;
2662 	case DEV_NON_CCS_DSK:	printf("Generic NON CCS Disk");	break;
2663 	case DEV_CCS_GENDISK:	printf("Generic CCS Disk");	break;
2664 	case DEV_SONY_SMO:	printf("Sony SMO-C501");	break;
2665 	case DEV_MT02:		printf("Emulex MT02");		break;
2666 	case DEV_SC4000:	printf("Sysgen SC4000");	break;
2667 	case DEV_RXT800S:	printf("Maxtor RXT800S");	break;
2668 	case DEV_HRSCAN:	printf("Berthold HR-Scanner");	break;
2669 	case DEV_MS300A:	printf("Microtek MS300A");	break;
2670 
2671 	case DEV_CDROM:		printf("Generic CD-ROM");	break;
2672 	case DEV_MMC_CDROM:	printf("Generic mmc CD-ROM");	break;
2673 	case DEV_MMC_CDR:	printf("Generic mmc CD-R");	break;
2674 	case DEV_MMC_CDRW:	printf("Generic mmc CD-RW");	break;
2675 	case DEV_MMC_DVD:	printf("Generic mmc2 DVD-ROM");	break;
2676 	case DEV_MMC_DVD_WR:	printf("Generic mmc2 DVD-R/DVD-RW/DVD-RAM"); break;
2677 	case DEV_CDD_521_OLD:	printf("Philips old CDD-521");	break;
2678 	case DEV_CDD_521:	printf("Philips CDD-521");	break;
2679 	case DEV_CDD_522:	printf("Philips CDD-522");	break;
2680 	case DEV_PCD_600:	printf("Kodak PCD-600");	break;
2681 	case DEV_CDD_2000:	printf("Philips CDD-2000");	break;
2682 	case DEV_CDD_2600:	printf("Philips CDD-2600");	break;
2683 	case DEV_YAMAHA_CDR_100:printf("Yamaha CDR-100");	break;
2684 	case DEV_YAMAHA_CDR_400:printf("Yamaha CDR-400");	break;
2685 	case DEV_PLASMON_RF_4100:printf("Plasmon RF-4100");	break;
2686 	case DEV_SONY_CDU_924:	printf("Sony CDU-924S");	break;
2687 	case DEV_RICOH_RO_1060C:printf("Ricoh RO-1060C");	break;
2688 	case DEV_RICOH_RO_1420C:printf("Ricoh RO-1420C");	break;
2689 	case DEV_TEAC_CD_R50S:	printf("Teac CD-R50S");		break;
2690 	case DEV_MATSUSHITA_7501:printf("Matsushita CW-7501");	break;
2691 	case DEV_MATSUSHITA_7502:printf("Matsushita CW-7502");	break;
2692 
2693 	case DEV_PIONEER_DW_S114X: printf("Pioneer DW-S114X");	break;
2694 	case DEV_PIONEER_DVDR_S101:printf("Pioneer DVD-R S101"); break;
2695 
2696 	default:		printf(_("Missing Entry for dev %d"),
2697 						scgp->dev);	break;
2698 
2699 	}
2700 	printf(".\n");
2701 
2702 }
2703 
2704 EXPORT BOOL
do_inquiry(scgp,print)2705 do_inquiry(scgp, print)
2706 	SCSI	*scgp;
2707 	int	print;
2708 {
2709 	if (getdev(scgp, print)) {
2710 		if (print)
2711 			printdev(scgp);
2712 		return (TRUE);
2713 	} else {
2714 		return (FALSE);
2715 	}
2716 }
2717 
2718 EXPORT BOOL
recovery_needed(scgp,dp)2719 recovery_needed(scgp, dp)
2720 	SCSI	*scgp;
2721 	cdr_t	*dp;
2722 {
2723 		int err;
2724 	register struct	scg_cmd	*scmd = scgp->scmd;
2725 
2726 	scgp->silent++;
2727 	err = test_unit_ready(scgp);
2728 	scgp->silent--;
2729 
2730 	if (err >= 0)
2731 		return (FALSE);
2732 	else if (scmd->error >= SCG_FATAL)	/* nicht selektierbar */
2733 		return (FALSE);
2734 
2735 	if (scmd->sense.code < 0x70)		/* non extended Sense */
2736 		return (FALSE);
2737 
2738 						/* XXX Old Philips code */
2739 	return (((struct scsi_ext_sense *)&scmd->sense)->sense_code == 0xD0);
2740 }
2741 
2742 EXPORT int
scsi_load(scgp,dp)2743 scsi_load(scgp, dp)
2744 	SCSI	*scgp;
2745 	cdr_t	*dp;
2746 {
2747 	int	key;
2748 	int	code;
2749 
2750 	if (dp && (dp->cdr_flags & CDR_CADDYLOAD) == 0) {
2751 		if (scsi_start_stop_unit(scgp, 1, 1, dp->cdr_cmdflags&F_IMMED) >= 0)
2752 			return (0);
2753 	}
2754 
2755 	if (wait_unit_ready(scgp, 60))
2756 		return (0);
2757 
2758 	key = scg_sense_key(scgp);
2759 	code = scg_sense_code(scgp);
2760 
2761 	if (key == SC_NOT_READY && (code == 0x3A || code == 0x30)) {
2762 		errmsgno(EX_BAD, _("Cannot load media with %s drive!\n"),
2763 			dp && (dp->cdr_flags & CDR_CADDYLOAD) ? _("caddy") : _("this"));
2764 		errmsgno(EX_BAD, _("Try to load media by hand.\n"));
2765 	}
2766 	return (-1);
2767 }
2768 
2769 EXPORT int
scsi_unload(scgp,dp)2770 scsi_unload(scgp, dp)
2771 	SCSI	*scgp;
2772 	cdr_t	*dp;
2773 {
2774 	return (scsi_start_stop_unit(scgp, 0, 1, dp && (dp->cdr_cmdflags&F_IMMED)));
2775 }
2776 
2777 EXPORT int
scsi_cdr_write(scgp,bp,sectaddr,size,blocks,islast)2778 scsi_cdr_write(scgp, bp, sectaddr, size, blocks, islast)
2779 	SCSI	*scgp;
2780 	caddr_t	bp;		/* address of buffer */
2781 	long	sectaddr;	/* disk address (sector) to put */
2782 	long	size;		/* number of bytes to transfer */
2783 	int	blocks;		/* sector count */
2784 	BOOL	islast;		/* last write for track */
2785 {
2786 	return (write_xg1(scgp, bp, sectaddr, size, blocks));
2787 }
2788 
2789 EXPORT struct cd_mode_page_2A *
mmc_cap(scgp,modep)2790 mmc_cap(scgp, modep)
2791 	SCSI	*scgp;
2792 	Uchar	*modep;
2793 {
2794 	int	len;
2795 	int	val;
2796 	Uchar	mode[0x100];
2797 	struct	cd_mode_page_2A *mp;
2798 	struct	cd_mode_page_2A *mp2;
2799 
2800 
2801 retry:
2802 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
2803 
2804 	if (!get_mode_params(scgp, 0x2A, _("CD capabilities"),
2805 			mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
2806 
2807 		if (scg_sense_key(scgp) == SC_NOT_READY) {
2808 			if (wait_unit_ready(scgp, 60))
2809 				goto retry;
2810 		}
2811 		return (NULL);		/* Pre SCSI-3/mmc drive		*/
2812 	}
2813 
2814 	if (len == 0)			/* Pre SCSI-3/mmc drive		*/
2815 		return (NULL);
2816 
2817 	mp = (struct cd_mode_page_2A *)
2818 		(mode + sizeof (struct scsi_mode_header) +
2819 		((struct scsi_mode_header *)mode)->blockdesc_len);
2820 
2821 	/*
2822 	 * Do some heuristics against pre SCSI-3/mmc VU page 2A
2823 	 * We should test for a minimum p_len of 0x14, but some
2824 	 * buggy CD-ROM readers ommit the write speed values.
2825 	 */
2826 	if (mp->p_len < 0x10)
2827 		return (NULL);
2828 
2829 	val = a_to_u_2_byte(mp->max_read_speed);
2830 	if (val != 0 && val < 176)
2831 		return (NULL);
2832 
2833 	val = a_to_u_2_byte(mp->cur_read_speed);
2834 	if (val != 0 && val < 176)
2835 		return (NULL);
2836 
2837 	len -= sizeof (struct scsi_mode_header) +
2838 		((struct scsi_mode_header *)mode)->blockdesc_len;
2839 	if (modep)
2840 		mp2 = (struct cd_mode_page_2A *)modep;
2841 	else
2842 		mp2 = malloc(len);
2843 	if (mp2)
2844 		movebytes(mp, mp2, len);
2845 
2846 	return (mp2);
2847 }
2848 
2849 EXPORT void
mmc_getval(mp,cdrrp,cdwrp,cdrrwp,cdwrwp,dvdp,dvdwp)2850 mmc_getval(mp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp, dvdwp)
2851 	struct	cd_mode_page_2A *mp;
2852 	BOOL	*cdrrp;				/* CD ROM		*/
2853 	BOOL	*cdwrp;				/* CD-R writer		*/
2854 	BOOL	*cdrrwp;			/* CD-RW reader		*/
2855 	BOOL	*cdwrwp;			/* CD-RW writer		*/
2856 	BOOL	*dvdp;				/* DVD reader		*/
2857 	BOOL	*dvdwp;				/* DVD writer		*/
2858 {
2859 	BOOL	isdvd;				/* Any DVD reader	*/
2860 	BOOL	isdvd_wr;			/* DVD writer (R / RAM)	*/
2861 	BOOL	iscd_wr;			/* CD  writer		*/
2862 
2863 	iscd_wr = (mp->cd_r_write != 0) ||	/* SCSI-3/mmc CD-R	*/
2864 		    (mp->cd_rw_write != 0);	/* SCSI-3/mmc CD-RW	*/
2865 
2866 	if (cdrrp)
2867 		*cdrrp = (mp->cd_r_read != 0);	/* SCSI-3/mmc CD	*/
2868 	if (cdwrp)
2869 		*cdwrp = (mp->cd_r_write != 0);	/* SCSI-3/mmc CD-R	*/
2870 
2871 	if (cdrrwp)
2872 		*cdrrwp = (mp->cd_rw_read != 0); /* SCSI-3/mmc CD	*/
2873 	if (cdwrwp)
2874 		*cdwrwp = (mp->cd_rw_write != 0); /* SCSI-3/mmc CD-RW	*/
2875 
2876 	isdvd =					/* SCSI-3/mmc2 DVD 	*/
2877 		(mp->dvd_ram_read + mp->dvd_r_read  +
2878 		    mp->dvd_rom_read) != 0;
2879 
2880 	isdvd_wr =				/* SCSI-3/mmc2 DVD writer*/
2881 		(mp->dvd_ram_write + mp->dvd_r_write) != 0;
2882 
2883 	if (dvdp)
2884 		*dvdp = isdvd;
2885 	if (dvdwp)
2886 		*dvdwp = isdvd_wr;
2887 }
2888 
2889 EXPORT BOOL
is_mmc(scgp,cdwp,dvdwp)2890 is_mmc(scgp, cdwp, dvdwp)
2891 	SCSI	*scgp;
2892 	BOOL	*cdwp;				/* CD  writer		*/
2893 	BOOL	*dvdwp;				/* DVD writer		*/
2894 {
2895 	BOOL	cdwr	= FALSE;
2896 	BOOL	cdwrw	= FALSE;
2897 
2898 	if (cdwp)
2899 		*cdwp = FALSE;
2900 	if (dvdwp)
2901 		*dvdwp = FALSE;
2902 
2903 	if (!mmc_check(scgp, NULL, &cdwr, NULL, &cdwrw, NULL, dvdwp))
2904 		return (FALSE);
2905 
2906 	if (cdwp)
2907 		*cdwp = cdwr | cdwrw;
2908 
2909 	return (TRUE);
2910 }
2911 
2912 EXPORT BOOL
mmc_check(scgp,cdrrp,cdwrp,cdrrwp,cdwrwp,dvdp,dvdwp)2913 mmc_check(scgp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp, dvdwp)
2914 	SCSI	*scgp;
2915 	BOOL	*cdrrp;				/* CD ROM		*/
2916 	BOOL	*cdwrp;				/* CD-R writer		*/
2917 	BOOL	*cdrrwp;			/* CD-RW reader		*/
2918 	BOOL	*cdwrwp;			/* CD-RW writer		*/
2919 	BOOL	*dvdp;				/* DVD reader		*/
2920 	BOOL	*dvdwp;				/* DVD writer		*/
2921 {
2922 	Uchar	mode[0x100];
2923 	BOOL	was_atapi;
2924 	struct	cd_mode_page_2A *mp;
2925 
2926 	if (scgp->inq->type != INQ_ROMD)
2927 		return (FALSE);
2928 
2929 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
2930 
2931 	was_atapi = allow_atapi(scgp, TRUE);
2932 	scgp->silent++;
2933 	mp = mmc_cap(scgp, mode);
2934 	scgp->silent--;
2935 	allow_atapi(scgp, was_atapi);
2936 	if (mp == NULL)
2937 		return (FALSE);
2938 
2939 	mmc_getval(mp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp, dvdwp);
2940 
2941 	return (TRUE);			/* Generic SCSI-3/mmc CD	*/
2942 }
2943 
2944 LOCAL void
print_speed(fmt,val)2945 print_speed(fmt, val)
2946 	char	*fmt;
2947 	int	val;
2948 {
2949 	printf("  %s: %5d kB/s", fmt, val);
2950 	printf(" (CD %3ux,", val/176);
2951 	printf(" DVD %2ux,", val/1385);
2952 	printf(" BD %2ux)\n", val/4495);
2953 }
2954 
2955 #define	DOES(what, flag)	printf(_("  Does %s%s\n"), flag?"":_("not "), what)
2956 #define	IS(what, flag)		printf(_("  Is %s%s\n"), flag?"":_("not "), what)
2957 #define	VAL(what, val)		printf(_("  %s: %d\n"), what, val[0]*256 + val[1])
2958 #define	SVAL(what, val)		printf(_("  %s: %s\n"), what, val)
2959 
2960 EXPORT void
print_capabilities(scgp)2961 print_capabilities(scgp)
2962 	SCSI	*scgp;
2963 {
2964 	BOOL	was_atapi;
2965 	Uchar	mode[0x100];
2966 	struct	cd_mode_page_2A *mp;
2967 static	const	char	*bclk[4] = {"32", "16", "24", "24 (I2S)"};
2968 static	const	char	*load[8] = {"caddy", "tray", "pop-up", "reserved(3)",
2969 				"disc changer", "cartridge changer",
2970 				"reserved(6)", "reserved(7)" };
2971 static	const	char	*rotctl[4] = {"CLV/PCAV", "CAV", "reserved(2)", "reserved(3)"};
2972 
2973 
2974 	if (scgp->inq->type != INQ_ROMD)
2975 		return;
2976 
2977 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
2978 
2979 	was_atapi = allow_atapi(scgp, TRUE);	/* Try to switch to 10 byte mode cmds */
2980 	scgp->silent++;
2981 	mp = mmc_cap(scgp, mode);
2982 	scgp->silent--;
2983 	allow_atapi(scgp, was_atapi);
2984 	if (mp == NULL)
2985 		return;
2986 
2987 	printf(_("\nDrive capabilities, per"));
2988 	if (mp->p_len >= 28)
2989 		printf(" MMC-3");
2990 	else if (mp->p_len >= 24)
2991 		printf(" MMC-2");
2992 	else
2993 		printf(" MMC");
2994 	printf(_(" page 2A:\n\n"));
2995 
2996 	DOES(_("read CD-R media"), mp->cd_r_read);
2997 	DOES(_("write CD-R media"), mp->cd_r_write);
2998 	DOES(_("read CD-RW media"), mp->cd_rw_read);
2999 	DOES(_("write CD-RW media"), mp->cd_rw_write);
3000 	DOES(_("read DVD-ROM media"), mp->dvd_rom_read);
3001 	DOES(_("read DVD-R media"), mp->dvd_r_read);
3002 	DOES(_("write DVD-R media"), mp->dvd_r_write);
3003 	DOES(_("read DVD-RAM media"), mp->dvd_ram_read);
3004 	DOES(_("write DVD-RAM media"), mp->dvd_ram_write);
3005 	DOES(_("support test writing"), mp->test_write);
3006 	printf("\n");
3007 	DOES(_("read Mode 2 Form 1 blocks"), mp->mode_2_form_1);
3008 	DOES(_("read Mode 2 Form 2 blocks"), mp->mode_2_form_2);
3009 	DOES(_("read digital audio blocks"), mp->cd_da_supported);
3010 	if (mp->cd_da_supported)
3011 		DOES(_("restart non-streamed digital audio reads accurately"), mp->cd_da_accurate);
3012 	DOES(_("support Buffer-Underrun-Free recording"), mp->BUF);
3013 	DOES(_("read multi-session CDs"), mp->multi_session);
3014 	DOES(_("read fixed-packet CD media using Method 2"), mp->method2);
3015 	DOES(_("read CD bar code"), mp->read_bar_code);
3016 	DOES(_("read R-W subcode information"), mp->rw_supported);
3017 	if (mp->rw_supported)
3018 		DOES(_("return R-W subcode de-interleaved and error-corrected"), mp->rw_deint_corr);
3019 	DOES(_("read raw P-W subcode data from lead in"), mp->pw_in_lead_in);
3020 	DOES(_("return CD media catalog number"), mp->UPC);
3021 	DOES(_("return CD ISRC information"), mp->ISRC);
3022 	DOES(_("support C2 error pointers"), mp->c2_pointers);
3023 	DOES(_("deliver composite A/V data"), mp->composite);
3024 	printf("\n");
3025 	DOES(_("play audio CDs"), mp->audio_play);
3026 	if (mp->audio_play) {
3027 		VAL(_("Number of volume control levels"), mp->num_vol_levels);
3028 		DOES(_("support individual volume control setting for each channel"), mp->sep_chan_vol);
3029 		DOES(_("support independent mute setting for each channel"), mp->sep_chan_mute);
3030 		DOES(_("support digital output on port 1"), mp->digital_port_1);
3031 		DOES(_("support digital output on port 2"), mp->digital_port_2);
3032 		if (mp->digital_port_1 || mp->digital_port_2) {
3033 			DOES(_("send digital data LSB-first"), mp->LSBF);
3034 			DOES(_("set LRCK high for left-channel data"), mp->RCK);
3035 			DOES(_("have valid data on falling edge of clock"), mp->BCK);
3036 			SVAL(_("Length of data in BCLKs"), bclk[mp->length]);
3037 		}
3038 	}
3039 	printf("\n");
3040 	SVAL(_("Loading mechanism type"), load[mp->loading_type]);
3041 	DOES(_("support ejection of CD via START/STOP command"), mp->eject);
3042 	DOES(_("lock media on power up via prevent jumper"), mp->prevent_jumper);
3043 	DOES(_("allow media to be locked in the drive via PREVENT/ALLOW command"), mp->lock);
3044 	IS(_("currently in a media-locked state"), mp->lock_state);
3045 	DOES(_("support changing side of disk"), mp->side_change);
3046 	DOES(_("have load-empty-slot-in-changer feature"), mp->sw_slot_sel);
3047 	DOES(_("support Individual Disk Present feature"), mp->disk_present_rep);
3048 	printf("\n");
3049 	print_speed(_("Maximum read  speed"), a_to_u_2_byte(mp->max_read_speed));
3050 	print_speed(_("Current read  speed"), a_to_u_2_byte(mp->cur_read_speed));
3051 	print_speed(_("Maximum write speed"), a_to_u_2_byte(mp->max_write_speed));
3052 	if (mp->p_len >= 28)
3053 		print_speed(_("Current write speed"), a_to_u_2_byte(mp->v3_cur_write_speed));
3054 	else
3055 		print_speed(_("Current write speed"), a_to_u_2_byte(mp->cur_write_speed));
3056 	if (mp->p_len >= 28) {
3057 		SVAL(_("Rotational control selected"), rotctl[mp->rot_ctl_sel]);
3058 	}
3059 	VAL(_("Buffer size in KB"), mp->buffer_size);
3060 
3061 	if (mp->p_len >= 24) {
3062 		VAL(_("Copy management revision supported"), mp->copy_man_rev);
3063 	}
3064 
3065 	if (mp->p_len >= 28) {
3066 		struct cd_wr_speed_performance *pp;
3067 		Uint	ndesc;
3068 		Uint	i;
3069 		Uint	n;
3070 
3071 		ndesc = a_to_u_2_byte(mp->num_wr_speed_des);
3072 		pp = mp->wr_speed_des;
3073 		printf(_("  Number of supported write speeds: %d\n"), ndesc);
3074 		for (i = 0; i < ndesc; i++, pp++) {
3075 			printf(_("  Write speed # %d:"), i);
3076 			n = a_to_u_2_byte(pp->wr_speed_supp);
3077 			printf(" %5d kB/s", n);
3078 			printf(" %s", rotctl[pp->rot_ctl_sel]);
3079 			printf(" (CD %3ux,", n/176);
3080 			printf(" DVD %2ux,", n/1385);
3081 			printf(" BD %2ux)\n", n/4495);
3082 		}
3083 	}
3084 
3085 	/* Generic SCSI-3/mmc CD	*/
3086 }
3087 
3088 EXPORT int
verify(scgp,start,count,bad_block)3089 verify(scgp, start, count, bad_block)
3090 	SCSI	*scgp;
3091 	long	start;
3092 	int	count;
3093 	long	*bad_block;
3094 {
3095 	register struct	scg_cmd	*scmd = scgp->scmd;
3096 
3097 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
3098 	scmd->addr = (caddr_t)0;
3099 	scmd->size = 0;
3100 	scmd->flags = SCG_DISRE_ENA;
3101 	scmd->cdb_len = SC_G1_CDBLEN;
3102 	scmd->sense_len = CCS_SENSE_LEN;
3103 	scmd->cdb.g1_cdb.cmd = 0x2F;	/* Verify */
3104 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
3105 	g1_cdbaddr(&scmd->cdb.g1_cdb, start);
3106 	g1_cdblen(&scmd->cdb.g1_cdb, count);
3107 
3108 	scgp->cmdname = "verify";
3109 
3110 	if (scg_cmd(scgp) < 0) {
3111 		if (scmd->sense.code >= 0x70) {	/* extended Sense */
3112 			*bad_block =
3113 				a_to_4_byte(&((struct scsi_ext_sense *)
3114 							&scmd->sense)->info_1);
3115 		} else {
3116 			*bad_block = a_to_u_3_byte(&scmd->sense.high_addr);
3117 		}
3118 		return (-1);
3119 	}
3120 	return (0);
3121 }
3122