1 /* @(#)drv_7501.c	1.30 10/12/19 Copyright 2003-2010 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)drv_7501.c	1.30 10/12/19 Copyright 2003-2010 J. Schilling";
6 #endif
7 /*
8  *	Device driver for the Masushita CW-7501
9  *
10  *	Copyright (c) 2003-2010 J. Schilling
11  *
12  * Mode Pages:
13  *	0x01	error recovery		Seite 100
14  *	0x02	disconnect/reconnect	Seite 107
15  *	0x0D	CD-ROM device parameter	Seite 110
16  *	0x0E	CD-ROM Audio control	Seite 112
17  *	0x20	Speed & Tray position	Seite 115
18  *	0x21	Media catalog number	Seite 124
19  *	0x22	ISRC			Seite 125
20  *	0x23	Dummy/Write Information	Seite 126
21  *	0x24	CD-R disk information	Seite 127
22  */
23 /*
24  * The contents of this file are subject to the terms of the
25  * Common Development and Distribution License, Version 1.0 only
26  * (the "License").  You may not use this file except in compliance
27  * with the License.
28  *
29  * See the file CDDL.Schily.txt in this distribution for details.
30  * A copy of the CDDL is also available via the Internet at
31  * http://www.opensource.org/licenses/cddl1.txt
32  *
33  * When distributing Covered Code, include this CDDL HEADER in each
34  * file and include the License file CDDL.Schily.txt from this distribution.
35  */
36 
37 #ifndef	DEBUG
38 #define	DEBUG
39 #endif
40 #include <schily/mconfig.h>
41 
42 #include <schily/stdio.h>
43 #include <schily/standard.h>
44 #include <schily/stdlib.h>
45 #include <schily/unistd.h>
46 #include <schily/errno.h>
47 #include <schily/string.h>
48 #include <schily/time.h>
49 
50 #include <schily/utypes.h>
51 #include <schily/btorder.h>
52 #include <schily/intcvt.h>
53 #include <schily/schily.h>
54 #include <schily/nlsdefs.h>
55 
56 #include <scg/scgcmd.h>
57 #include <scg/scsidefs.h>
58 #include <scg/scsireg.h>
59 #include <scg/scsitransp.h>
60 
61 #include <schily/libport.h>
62 
63 #include "cdrecord.h"
64 
65 extern	int	silent;
66 extern	int	debug;
67 extern	int	verbose;
68 extern	int	lverbose;
69 extern	int	xdebug;
70 
71 #if defined(_BIT_FIELDS_LTOH)	/* Intel byteorder */
72 
73 struct cw7501_mode_page_20 {	/* Speed control */
74 		MP_P_CODE;		/* parsave & pagecode */
75 	Uchar	p_len;			/* 0x02 = 2 Bytes */
76 	Uchar	speed;
77 	Ucbit	res		: 7;
78 	Ucbit	traypos		: 1;
79 };
80 
81 #else				/* Motorola byteorder */
82 
83 struct cw7501_mode_page_20 {	/* Speed control */
84 		MP_P_CODE;		/* parsave & pagecode */
85 	Uchar	p_len;			/* 0x02 = 2 Bytes */
86 	Uchar	speed;
87 	Ucbit	traypos		: 1;
88 	Ucbit	res		: 7;
89 };
90 #endif
91 
92 #if defined(_BIT_FIELDS_LTOH)	/* Intel byteorder */
93 
94 struct cw7501_mode_page_21 {	/* MCN */
95 		MP_P_CODE;		/* parsave & pagecode */
96 	Uchar	p_len;			/* 0x12 = 20 Bytes */
97 	Ucbit	control		: 4;
98 	Ucbit	addr		: 4;
99 	Uchar	res_3;
100 	Uchar	res_4;
101 	Uchar	mcn[15];
102 };
103 
104 #else				/* Motorola byteorder */
105 
106 struct cw7501_mode_page_21 {	/* MCN */
107 		MP_P_CODE;		/* parsave & pagecode */
108 	Uchar	p_len;			/* 0x12 = 20 Bytes */
109 	Ucbit	addr		: 4;
110 	Ucbit	control		: 4;
111 	Uchar	res_3;
112 	Uchar	res_4;
113 	Uchar	mcn[15];
114 };
115 #endif
116 
117 
118 #if defined(_BIT_FIELDS_LTOH)	/* Intel byteorder */
119 
120 struct cw7501_mode_page_22 {	/* ISRC */
121 		MP_P_CODE;		/* parsave & pagecode */
122 	Uchar	p_len;			/* 0x12 = 20 Bytes */
123 	Ucbit	control		: 4;
124 	Ucbit	addr		: 4;
125 	Uchar	trackno;
126 	Uchar	res_4;
127 	Uchar	isrc[15];
128 };
129 
130 #else				/* Motorola byteorder */
131 
132 struct cw7501_mode_page_22 {	/* ISRC */
133 		MP_P_CODE;		/* parsave & pagecode */
134 	Uchar	p_len;			/* 0x12 = 20 Bytes */
135 	Ucbit	addr		: 4;
136 	Ucbit	control		: 4;
137 	Uchar	trackno;
138 	Uchar	res_4;
139 	Uchar	isrc[15];
140 };
141 #endif
142 
143 #if defined(_BIT_FIELDS_LTOH)	/* Intel byteorder */
144 
145 struct cw7501_mode_page_23 {	/* Dummy / Write information */
146 		MP_P_CODE;		/* parsave & pagecode */
147 	Uchar	p_len;			/* 0x02 = 2 Bytes */
148 	Uchar	res;
149 	Ucbit	autopg		: 1;
150 	Ucbit	dummy		: 1;
151 	Ucbit	res3_72		: 6;
152 };
153 
154 #else				/* Motorola byteorder */
155 
156 struct cw7501_mode_page_23 {	/* Dummy / Write information */
157 		MP_P_CODE;		/* parsave & pagecode */
158 	Uchar	p_len;			/* 0x02 = 2 Bytes */
159 	Uchar	res;
160 	Ucbit	res3_72		: 6;
161 	Ucbit	dummy		: 1;
162 	Ucbit	autopg		: 1;
163 };
164 #endif
165 
166 struct cw7501_mode_page_24 {	/* CD-R Disk information */
167 		MP_P_CODE;		/* parsave & pagecode */
168 	Uchar	p_len;			/* 0x0A = 12 Bytes */
169 	Uchar	disktype;
170 	Uchar	res;
171 	Uchar	appl_code[4];
172 	Uchar	disk_id[4];
173 };
174 
175 struct cw7501_mode_data {
176 	struct scsi_mode_header	header;
177 	union cdd_pagex	{
178 		struct cw7501_mode_page_20	page20;
179 		struct cw7501_mode_page_21	page21;
180 		struct cw7501_mode_page_22	page22;
181 		struct cw7501_mode_page_23	page23;
182 		struct cw7501_mode_page_24	page24;
183 	} pagex;
184 };
185 
186 /*
187  * Mode for read track information
188  */
189 #define	TI_TRACKINFO_R	0
190 #define	TI_NWA		1
191 #define	TI_PMA		2
192 #define	TI_TRACKINFO	3
193 
194 struct cw7501_nwa {
195 	Uchar	nwa_length[2];
196 	Uchar	nwa_res;
197 	Uchar	nwa_trackno;
198 	Uchar	nwa_nwa[4];
199 	Uchar	nwa_freeblocks[4];
200 };
201 
202 struct cw7501_cue {
203 	Uchar	cs_ctladr;		/* CTL/ADR for this track	*/
204 	Uchar	cs_tno;			/* This track number		*/
205 	Uchar	cs_index;		/* Index within this track	*/
206 	Uchar	cs_dataform;		/* Data form 			*/
207 					/* Bit 0..3 Physical Format	*/
208 					/* Bit 4 Alt Copy (SCMS)	*/
209 					/* Bit 5 SubC Audio + RAW96 sub */
210 	Uchar	cs_extension;		/* Reserved or MCN/ISRC		*/
211 	Uchar	cs_min;			/* Absolute time minutes	*/
212 	Uchar	cs_sec;			/* Absolute time seconds	*/
213 	Uchar	cs_frame;		/* Absolute time frames		*/
214 };
215 
216 
217 LOCAL	int	cw7501_attach		__PR((SCSI *scgp, cdr_t *dp));
218 LOCAL	int	cw7501_init		__PR((SCSI *scgp, cdr_t *dp));
219 LOCAL	int	cw7501_getdisktype	__PR((SCSI *scgp, cdr_t *dp));
220 LOCAL	int	cw7501_speed_select	__PR((SCSI *scgp, cdr_t *dp, int *speedp));
221 LOCAL	int	cw7501_next_wr_addr	__PR((SCSI *scgp, track_t *trackp, long *ap));
222 LOCAL	int	cw7501_write		__PR((SCSI *scgp, caddr_t bp, long sectaddr, long size, int blocks, BOOL islast));
223 LOCAL	int	cw7501_write_leadin	__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
224 LOCAL	int	cw7501_open_track	__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
225 LOCAL	int	cw7501_close_track	__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
226 LOCAL	int	cw7501_open_session	__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
227 LOCAL	int	cw7501_gen_cue		__PR((track_t *trackp, void *vcuep, BOOL needgap));
228 LOCAL	void	fillcue			__PR((struct cw7501_cue *cp, int ca, int tno, int idx, int dataform, int scms, msf_t *mp));
229 LOCAL	int	cw7501_send_cue		__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
230 LOCAL	int	cw7501_fixate		__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
231 LOCAL	int	cw7501_rezero		__PR((SCSI *scgp, int reset, int dwreset));
232 LOCAL	int	cw7501_read_trackinfo	__PR((SCSI *scgp, Uchar *bp, int count, int track, int mode));
233 LOCAL	int	cw7501_write_dao	__PR((SCSI *scgp, Uchar *bp, int len, int disktype));
234 LOCAL	int	cw7501_reserve_track	__PR((SCSI *scgp, unsigned long));
235 LOCAL	int	cw7501_set_mode		__PR((SCSI *scgp, int phys_form, int control,
236 						int subc, int alt, int trackno, int tindex,
237 						int packet_size, int write_mode));
238 LOCAL	int	cw7501_finalize		__PR((SCSI *scgp, int pad, int fixed));
239 
240 
241 cdr_t	cdr_cw7501 = {
242 	0, 0, 0,
243 	/*
244 	 * Prinzipiell geht auch: CDR_PACKET & CDR_SRAW96R
245 	 */
246 	CDR_TAO|CDR_SAO|CDR_TRAYLOAD,
247 	0,
248 	CDR_CDRW_NONE,
249 	WM_SAO,
250 	2, 2,
251 	"cw_7501",
252 	"driver for Matsushita/Panasonic CW-7501",
253 	0,
254 	(dstat_t *)0,
255 	drive_identify,
256 	cw7501_attach,
257 	cw7501_init,
258 	cw7501_getdisktype,
259 	no_diskstatus,
260 	scsi_load,
261 	scsi_unload,
262 	buf_dummy,				/* RD buffer cap not supp. */
263 	cmd_dummy,					/* recovery_needed */
264 	(int(*)__PR((SCSI *, cdr_t *, int)))cmd_dummy,	/* recover	*/
265 	cw7501_speed_select,
266 	select_secsize,
267 	cw7501_next_wr_addr,
268 	cw7501_reserve_track,
269 	cw7501_write,
270 	cw7501_gen_cue,
271 	cw7501_send_cue,
272 	cw7501_write_leadin,
273 	cw7501_open_track,
274 	cw7501_close_track,
275 	cw7501_open_session,
276 	cmd_dummy,				/* close seession	*/
277 	cmd_dummy,					/* abort	*/
278 	read_session_offset,
279 	cw7501_fixate,
280 	cmd_dummy,					/* stats	*/
281 	blank_dummy,
282 	format_dummy,
283 	(int(*)__PR((SCSI *, caddr_t, int, int)))NULL,	/* no OPC	*/
284 	cmd_dummy,					/* opt1		*/
285 	cmd_dummy,					/* opt2		*/
286 };
287 
288 static const char *sd_cw7501_error_str[] = {
289 	"\100\201diagnostic failure on ROM",			/* 40 81 */
290 	"\100\202diagnostic failure on CPU internal RAM",	/* 40 82 */
291 	"\100\203diagnostic failure on BUFFER RAM",		/* 40 83 */
292 	"\100\204diagnostic failure on internal SCSI controller",	/* 40 84 */
293 	"\100\205diagnostic failure on system mechanism",	/* 40 85 */
294 
295 	"\210\000Illegal Que Sheet (DAO parameter)",		/* 88 00 */
296 	"\211\000Inappropriate command",			/* 89 00 */
297 
298 	"\250\000Audio Play operation Not in Progress",		/* A8 00 */
299 	"\251\000Buffer Overrun",				/* A9 00 */
300 
301 	"\300\000Unrecordable Disk",				/* C0 00 */
302 	"\301\000Illegal Track Status",				/* C1 00 */
303 	"\302\000Reserved track Status",			/* C2 00 */
304 	"\304\000Illegal Reserve Length for Reserve Track Command",	/* C4 00 */
305 	"\304\001Illegal Data Form for Reserve Track Command",	/* C4 01 */
306 	"\304\002Unable to Reserve Track, Because Track Mode has been Changed",	/* C4 02 */
307 
308 	"\305\000Buffer error during recording",		/* C5 00 */
309 	"\307\000Disk Style mismatch",				/* C7 00 */
310 	"\312\000Power Calibration error",			/* CA 00 */
311 	"\313\000Write error (Fatal Error/Time out)",		/* CB 00 */
312 	"\314\000Not enough space (Leadin/Leadout space)",	/* CC 00 */
313 	"\315\000No track present to finalize",			/* CD 00 */
314 	"\317\000Unable to recover damaged disk",		/* CF 00 */
315 
316 	"\320\000PMA area full (1000 blocks)",			/* D0 00 */
317 	"\321\000PCA area full (100 counts)",			/* D1 00 */
318 	"\322\000Recovery failed",				/* D2 00 */
319 	"\323\000Recovery needed",				/* D3 00 */
320 	NULL
321 };
322 
323 LOCAL int
cw7501_attach(scgp,dp)324 cw7501_attach(scgp, dp)
325 	SCSI	*scgp;
326 	cdr_t	*dp;
327 {
328 	scg_setnonstderrs(scgp, sd_cw7501_error_str);
329 	return (0);
330 }
331 
332 LOCAL int
cw7501_init(scgp,dp)333 cw7501_init(scgp, dp)
334 	SCSI	*scgp;
335 	cdr_t	*dp;
336 {
337 	return (cw7501_speed_select(scgp, dp, NULL));
338 }
339 
340 LOCAL int
cw7501_getdisktype(scgp,dp)341 cw7501_getdisktype(scgp, dp)
342 	SCSI	*scgp;
343 	cdr_t	*dp;
344 {
345 	Ulong	maxb = 0;
346 	Uchar	buf[256];
347 	int	ret;
348 	dstat_t	*dsp = dp->cdr_dstat;
349 
350 	if (xdebug > 0) {
351 		scgp->silent++;
352 		fillbytes((caddr_t)buf, sizeof (buf), '\0');
353 		ret = cw7501_read_trackinfo(scgp, buf, 32, 0, 0);
354 		if (ret >= 0)
355 		scg_prbytes("TI EXIST-R   (0): ", buf, 32 -scg_getresid(scgp));
356 
357 		fillbytes((caddr_t)buf, sizeof (buf), '\0');
358 		ret = cw7501_read_trackinfo(scgp, buf, 32, 0, 1);
359 		if (ret >= 0)
360 		scg_prbytes("TI NWA       (1): ", buf, 32 -scg_getresid(scgp));
361 
362 		fillbytes((caddr_t)buf, sizeof (buf), '\0');
363 		ret = cw7501_read_trackinfo(scgp, buf, 32, 0, 2);
364 		if (ret >= 0)
365 		scg_prbytes("TI PMA       (2): ", buf, 32 -scg_getresid(scgp));
366 
367 		fillbytes((caddr_t)buf, sizeof (buf), '\0');
368 		ret = cw7501_read_trackinfo(scgp, buf, 32, 0, 3);
369 		if (ret >= 0)
370 		scg_prbytes("TI EXIST-ROM (3): ", buf, 32 -scg_getresid(scgp));
371 		scgp->silent--;
372 	}
373 
374 	fillbytes((caddr_t)buf, sizeof (buf), '\0');
375 
376 	scgp->silent++;
377 	ret = cw7501_read_trackinfo(scgp, buf, 12, 0, TI_NWA);
378 	if (ret < 0 &&
379 			(dsp->ds_cdrflags & (RF_WRITE|RF_BLANK)) == RF_WRITE) {
380 
381 		/*
382 		 * Try to clear the dummy bit to reset the virtual
383 		 * drive status. Not all drives support it even though
384 		 * it is mentioned in the MMC standard.
385 		 */
386 		if (lverbose)
387 			printf(_("Trying to clear drive status.\n"));
388 		cw7501_rezero(scgp, 0, 1);
389 		wait_unit_ready(scgp, 60);
390 		ret = cw7501_read_trackinfo(scgp, buf, 12, 0, TI_NWA);
391 	}
392 	scgp->silent--;
393 
394 	if (ret >= 0) {
395 		maxb = a_to_u_4_byte(&buf[8]);
396 		if (maxb != 0)
397 			maxb -= 150;
398 	}
399 	dsp->ds_maxblocks = maxb;
400 
401 	return (drive_getdisktype(scgp, dp));
402 }
403 
404 
405 LOCAL int
cw7501_speed_select(scgp,dp,speedp)406 cw7501_speed_select(scgp, dp, speedp)
407 	SCSI	*scgp;
408 	cdr_t	*dp;
409 	int	*speedp;
410 {
411 	struct	scsi_mode_page_header	*mp;
412 	char				mode[256];
413 	int				len = 20;
414 	int				page = 0x20;
415 	struct cw7501_mode_page_20	*xp20;
416 	struct cw7501_mode_data		md;
417 	int				count;
418 	int				speed = 1;
419 	BOOL				dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
420 
421 	if (speedp) {
422 		speed = *speedp;
423 	} else {
424 		fillbytes((caddr_t)mode, sizeof (mode), '\0');
425 
426 		if (!get_mode_params(scgp, page, _("Speed information"),
427 			(Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
428 			return (-1);
429 		}
430 		if (len == 0)
431 			return (-1);
432 
433 		mp = (struct scsi_mode_page_header *)
434 			(mode + sizeof (struct scsi_mode_header) +
435 			((struct scsi_mode_header *)mode)->blockdesc_len);
436 
437 		xp20  = (struct cw7501_mode_page_20 *)mp;
438 		speed = xp20->speed;
439 	}
440 
441 	fillbytes((caddr_t)&md, sizeof (md), '\0');
442 
443 	count  = sizeof (struct scsi_mode_header) +
444 		sizeof (struct cw7501_mode_page_20);
445 
446 	md.pagex.page20.p_code = 0x20;
447 	md.pagex.page20.p_len =  0x02;
448 	md.pagex.page20.speed = speed;
449 
450 	if (mode_select(scgp, (Uchar *)&md, count, 0, scgp->inq->data_format >= 2) < 0)
451 		return (-1);
452 
453 	fillbytes((caddr_t)&md, sizeof (md), '\0');
454 
455 	count  = sizeof (struct scsi_mode_header) +
456 		sizeof (struct cw7501_mode_page_23);
457 
458 	md.pagex.page23.p_code = 0x23;
459 	md.pagex.page23.p_len =  0x02;
460 	md.pagex.page23.dummy = dummy?1:0;
461 
462 	return (mode_select(scgp, (Uchar *)&md, count, 0, scgp->inq->data_format >= 2));
463 }
464 
465 LOCAL int
cw7501_next_wr_addr(scgp,trackp,ap)466 cw7501_next_wr_addr(scgp, trackp, ap)
467 	SCSI	*scgp;
468 	track_t	*trackp;
469 	long	*ap;
470 {
471 	struct cw7501_nwa	*nwa;
472 	Uchar	buf[256];
473 	long	next_addr;
474 	int	result = -1;
475 
476 
477 	/*
478 	 * Reading info for current track may require doing the read_track_info
479 	 * with either the track number (if the track is currently being written)
480 	 * or with 0 (if the track hasn't been started yet and is invisible
481 	 */
482 	nwa = (struct cw7501_nwa *)buf;
483 
484 	if (trackp != 0 && trackp->track > 0 && is_packet(trackp)) {
485 		fillbytes((caddr_t)buf, sizeof (buf), '\0');
486 
487 		scgp->silent++;
488 		result = cw7501_read_trackinfo(scgp, buf, sizeof (*nwa),
489 							trackp->trackno,
490 							TI_NWA);
491 		scgp->silent--;
492 	}
493 
494 	if (result < 0) {
495 		if (cw7501_read_trackinfo(scgp, buf, sizeof (*nwa),
496 							0, TI_NWA) < 0)
497 			return (-1);
498 	}
499 	if (scgp->verbose)
500 		scg_prbytes(_("track info:"), buf,
501 				12-scg_getresid(scgp));
502 	next_addr = a_to_4_byte(nwa->nwa_nwa);
503 	/*
504 	 * XXX F�r TAO definitiv notwendig.
505 	 * XXX ABh�ngig von Auto-Pregap?
506 	 */
507 	/* XXX */ next_addr += 150;
508 	if (ap)
509 		*ap = next_addr;
510 	return (0);
511 }
512 
513 LOCAL int
cw7501_write(scgp,bp,sectaddr,size,blocks,islast)514 cw7501_write(scgp, bp, sectaddr, size, blocks, islast)
515 	SCSI	*scgp;
516 	caddr_t	bp;		/* address of buffer */
517 	long	sectaddr;	/* disk address (sector) to put */
518 	long	size;		/* number of bytes to transfer */
519 	int	blocks;		/* sector count */
520 	BOOL	islast;		/* last write for track */
521 {
522 	if (lverbose > 1 && islast)
523 		printf(_("\nWriting last record for this track.\n"));
524 
525 	return (write_xg0(scgp, bp, 0, size, blocks));
526 }
527 
528 LOCAL int
cw7501_write_leadin(scgp,dp,trackp)529 cw7501_write_leadin(scgp, dp, trackp)
530 	SCSI	*scgp;
531 	cdr_t	*dp;
532 	track_t *trackp;
533 {
534 	Uint	i;
535 	long	startsec = 0L;
536 
537 	if (wm_base(dp->cdr_dstat->ds_wrmode) == WM_SAO) {
538 		if (debug || lverbose) {
539 			printf(_("Sending CUE sheet...\n"));
540 			flush();
541 		}
542 		if ((*dp->cdr_send_cue)(scgp, dp, trackp) < 0) {
543 			errmsgno(EX_BAD, _("Cannot send CUE sheet.\n"));
544 			return (-1);
545 		}
546 
547 		/*
548 		 * Next writable address function does not work in DAO
549 		 * mode for this writer, so we just assume -150.
550 		 */
551 		startsec = -150;
552 		if (debug)
553 			printf(_("SAO startsec: %ld\n"), startsec);
554 
555 		if (trackp[0].flags & TI_TEXT) {
556 			errmsgno(EX_BAD, _("CD-Text unsupported in CW-7501 - ignoring.\n"));
557 		} else for (i = 1; i <= trackp->tracks; i++) {
558 			trackp[i].trackstart += startsec +150;
559 		}
560 	}
561 	return (0);
562 }
563 
564 LOCAL Uchar	db2phys[] = {
565 	0x00,			/*  0 2352 bytes of raw data			*/
566 	0xFF,			/*  1 2368 bytes (raw data + P/Q Subchannel)	*/
567 	0xFF,			/*  2 2448 bytes (raw data + P-W Subchannel)	*/
568 	0xFF,			/*  3 2448 bytes (raw data + P-W raw Subchannel)*/
569 	0xFF,			/*  4 -    Reserved				*/
570 	0xFF,			/*  5 -    Reserved				*/
571 	0xFF,			/*  6 -    Reserved				*/
572 	0xFF,			/*  7 -    Vendor specific			*/
573 	0x02,			/*  8 2048 bytes Mode 1 (ISO/IEC 10149)		*/
574 	0x03,			/*  9 2336 bytes Mode 2 (ISO/IEC 10149)		*/
575 	0xFF,			/* 10 2048 bytes Mode 2 (CD-ROM XA form 1)	*/
576 	0x04,			/* 11 2056 bytes Mode 2 (CD-ROM XA form 1)	*/
577 	0xFF,			/* 12 2324 bytes Mode 2 (CD-ROM XA form 2)	*/
578 	0x08,			/* 13 2332 bytes Mode 2 (CD-ROM XA 1/2+subhdr)	*/
579 	0xFF,			/* 14 -    Reserved				*/
580 	0xFF,			/* 15 -    Vendor specific			*/
581 };
582 
583 LOCAL int
cw7501_open_track(scgp,dp,trackp)584 cw7501_open_track(scgp, dp, trackp)
585 	SCSI	*scgp;
586 	cdr_t	*dp;
587 	track_t *trackp;
588 {
589 	struct	scsi_mode_page_header	*mp;
590 	Uchar				mode[256];
591 	int				len = 0;
592 	int				page = 0x23;
593 	struct cw7501_mode_page_23	*xp23;
594 
595 	if (!is_tao(trackp) && !is_packet(trackp)) {
596 		if (trackp->pregapsize > 0 && (trackp->flags & TI_PREGAP) == 0) {
597 			if (lverbose) {
598 				printf(_("Writing pregap for track %d at %ld\n"),
599 					(int)trackp->trackno,
600 					trackp->trackstart-trackp->pregapsize);
601 			}
602 			if (trackp->track == 1 && is_hidden(trackp)) {
603 				pad_track(scgp, dp, trackp,
604 					trackp->trackstart-trackp->pregapsize,
605 					(Llong)(trackp->pregapsize-trackp->trackstart)*trackp->secsize,
606 					FALSE, 0);
607 				if (write_track_data(scgp, dp, track_base(trackp)) < 0)
608 					return (-1);
609 			} else {
610 				/*
611 				 * XXX Do we need to check isecsize too?
612 				 */
613 				pad_track(scgp, dp, trackp,
614 					trackp->trackstart-trackp->pregapsize,
615 					(Llong)trackp->pregapsize*trackp->secsize,
616 					FALSE, 0);
617 			}
618 		}
619 		return (0);
620 	}
621 
622 	if (select_secsize(scgp, trackp->secsize) < 0)
623 		return (-1);
624 
625 	if (!get_mode_params(scgp, page, _("Dummy/autopg information"),
626 			(Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
627 		return (-1);
628 	}
629 	if (len == 0)
630 		return (-1);
631 
632 	mp = (struct scsi_mode_page_header *)
633 		(mode + sizeof (struct scsi_mode_header) +
634 		((struct scsi_mode_header *)mode)->blockdesc_len);
635 
636 	xp23  = (struct cw7501_mode_page_23 *)mp;
637 	xp23->autopg = 1;
638 	if (!set_mode_params(scgp, _("Dummy/autopg page"), mode, len, 0, trackp->secsize))
639 		return (-1);
640 
641 	/*
642 	 * Set write modes for next track.
643 	 */
644 	if (cw7501_set_mode(scgp, db2phys[trackp->dbtype & 0x0F],
645 			st2mode[trackp->sectype&ST_MASK] | (is_copy(trackp) ? TM_ALLOW_COPY : 0),
646 			0, is_scms(trackp) ? 1 : 0,
647 			trackp->trackno, 1, 0,
648 			/* write mode TAO */ 0x01) < 0)
649 		return (-1);
650 
651 	return (0);
652 }
653 
654 
655 LOCAL int
cw7501_close_track(scgp,dp,trackp)656 cw7501_close_track(scgp, dp, trackp)
657 	SCSI	*scgp;
658 	cdr_t	*dp;
659 	track_t	*trackp;
660 {
661 	if (!is_tao(trackp) && !is_packet(trackp)) {
662 		return (0);
663 	}
664 	return (scsi_flush_cache(scgp, FALSE));
665 }
666 
667 LOCAL int
cw7501_open_session(scgp,dp,trackp)668 cw7501_open_session(scgp, dp, trackp)
669 	SCSI	*scgp;
670 	cdr_t	*dp;
671 	track_t	*trackp;
672 {
673 	struct cw7501_mode_data		md;
674 	int				count;
675 
676 	if (select_secsize(scgp, 2048) < 0)
677 		return (-1);
678 
679 	/*
680 	 * Disable Auto Pregap when writing in SAO mode.
681 	 */
682 	if (!is_tao(trackp) && !is_packet(trackp)) {
683 		struct	scsi_mode_page_header	*mp;
684 		Uchar				mode[256];
685 		int				len = 0;
686 		int				page = 0x23;
687 		struct cw7501_mode_page_23	*xp23;
688 
689 		if (!get_mode_params(scgp, page, _("Dummy/autopg information"),
690 				(Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
691 			return (-1);
692 		}
693 		if (len == 0)
694 			return (-1);
695 
696 		mp = (struct scsi_mode_page_header *)
697 			(mode + sizeof (struct scsi_mode_header) +
698 			((struct scsi_mode_header *)mode)->blockdesc_len);
699 
700 		xp23  = (struct cw7501_mode_page_23 *)mp;
701 		xp23->autopg = 0;
702 		if (!set_mode_params(scgp, _("Dummy/autopg page"), mode, len, 0, trackp->secsize))
703 			return (-1);
704 
705 		return (0);
706 	}
707 
708 	/*
709 	 * Set Disk Type and Disk ID.
710 	 */
711 	fillbytes((caddr_t)&md, sizeof (md), '\0');
712 
713 	count  = sizeof (struct scsi_mode_header) +
714 		sizeof (struct cw7501_mode_page_24);
715 
716 	md.pagex.page24.p_code = 0x24;
717 	md.pagex.page24.p_len =  0x0A;
718 	md.pagex.page24.disktype = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
719 	i_to_4_byte(md.pagex.page24.disk_id, 0x12345);
720 
721 	return (mode_select(scgp, (Uchar *)&md, count, 0, scgp->inq->data_format >= 2));
722 }
723 
724 LOCAL int
cw7501_fixate(scgp,dp,trackp)725 cw7501_fixate(scgp, dp, trackp)
726 	SCSI	*scgp;
727 	cdr_t	*dp;
728 	track_t	*trackp;
729 {
730 	if (!is_tao(trackp) && !is_packet(trackp)) {
731 		return (scsi_flush_cache(scgp, FALSE));
732 	}
733 	/*
734 	 * 0x00	Finalize Disk (not appendable)
735 	 * 0x01	Finalize Session (allow next session)
736 	 * 0x10	Finalize track (variable packet writing) - Must fluch cache before
737 	 */
738 	return (cw7501_finalize(scgp, 0, (track_base(trackp)->tracktype & TOCF_MULTI) ? 0x01 : 0x00));
739 }
740 
741 /*--------------------------------------------------------------------------*/
742 
743 LOCAL int
cw7501_gen_cue(trackp,vcuep,needgap)744 cw7501_gen_cue(trackp, vcuep, needgap)
745 	track_t	*trackp;
746 	void	*vcuep;
747 	BOOL	needgap;
748 {
749 	int	tracks = trackp->tracks;
750 	int	i;
751 	struct cw7501_cue	**cuep = vcuep;
752 	struct cw7501_cue	*cue;
753 	struct cw7501_cue	*cp;
754 	int	ncue = 0;
755 	int	icue = 0;
756 	int	pgsize;
757 	msf_t	m;
758 	int	ctl;
759 	int	df;
760 	int	scms;
761 
762 	cue = malloc(1);
763 
764 	for (i = 0; i <= tracks; i++) {
765 		ctl = (st2mode[trackp[i].sectype & ST_MASK]) << 4;
766 		if (is_copy(&trackp[i]))
767 			ctl |= TM_ALLOW_COPY << 4;
768 		df = db2phys[trackp[i].dbtype & 0x0F];
769 
770 		if (trackp[i].isrc) {	/* MCN or ISRC */
771 			ncue += 2;
772 			cue = realloc(cue, ncue * sizeof (*cue));
773 			cp = &cue[icue++];
774 			if (i == 0) {
775 				cp->cs_ctladr = 0x02;
776 				movebytes(&trackp[i].isrc[0], &cp->cs_tno, 7);
777 				cp = &cue[icue++];
778 				cp->cs_ctladr = 0x02;
779 				movebytes(&trackp[i].isrc[7], &cp->cs_tno, 7);
780 			} else {
781 				cp->cs_ctladr = 0x03;
782 				cp->cs_tno = i;
783 				movebytes(&trackp[i].isrc[0], &cp->cs_index, 6);
784 				cp = &cue[icue++];
785 				cp->cs_ctladr = 0x03;
786 				cp->cs_tno = i;
787 				movebytes(&trackp[i].isrc[6], &cp->cs_index, 6);
788 			}
789 		}
790 		if (i == 0) {	/* Lead in */
791 			lba_to_msf(-150, &m);
792 			cue = realloc(cue, ++ncue * sizeof (*cue));
793 			cp = &cue[icue++];
794 			fillcue(cp, ctl|0x01, i, 0, df, 0, &m);
795 		} else {
796 			scms = 0;
797 
798 			if (is_scms(&trackp[i]))
799 				scms = 0x80;
800 			pgsize = trackp[i].pregapsize;
801 			if (pgsize == 0 && needgap)
802 				pgsize++;
803 			lba_to_msf(trackp[i].trackstart-pgsize, &m);
804 			cue = realloc(cue, ++ncue * sizeof (*cue));
805 			cp = &cue[icue++];
806 			fillcue(cp, ctl|0x01, i, 0, df, scms, &m);
807 
808 			if (trackp[i].nindex == 1) {
809 				lba_to_msf(trackp[i].trackstart, &m);
810 				cue = realloc(cue, ++ncue * sizeof (*cue));
811 				cp = &cue[icue++];
812 				fillcue(cp, ctl|0x01, i, 1, df, scms, &m);
813 			} else {
814 				int	idx;
815 				long	*idxlist;
816 
817 				ncue += trackp[i].nindex;
818 				idxlist = trackp[i].tindex;
819 				cue = realloc(cue, ncue * sizeof (*cue));
820 
821 				for (idx = 1; idx <= trackp[i].nindex; idx++) {
822 					lba_to_msf(trackp[i].trackstart + idxlist[idx], &m);
823 					cp = &cue[icue++];
824 					fillcue(cp, ctl|0x01, i, idx, df, scms, &m);
825 				}
826 			}
827 		}
828 	}
829 	/* Lead out */
830 	ctl = (st2mode[trackp[tracks+1].sectype & ST_MASK]) << 4;
831 	df = db2phys[trackp[tracks+1].dbtype & 0x0F];
832 	lba_to_msf(trackp[tracks+1].trackstart, &m);
833 	cue = realloc(cue, ++ncue * sizeof (*cue));
834 	cp = &cue[icue++];
835 	fillcue(cp, ctl|0x01, 0xAA, 1, df, 0, &m);
836 
837 	if (lverbose > 1) {
838 		for (i = 0; i < ncue; i++) {
839 			scg_prbytes("", (Uchar *)&cue[i], 8);
840 		}
841 	}
842 	if (cuep)
843 		*cuep = cue;
844 	else
845 		free(cue);
846 	return (ncue);
847 }
848 
849 LOCAL void
fillcue(cp,ca,tno,idx,dataform,scms,mp)850 fillcue(cp, ca, tno, idx, dataform, scms, mp)
851 	struct cw7501_cue *cp;	/* The target cue entry		*/
852 	int	ca;		/* Control/adr for this entry	*/
853 	int	tno;		/* Track number for this entry	*/
854 	int	idx;		/* Index for this entry		*/
855 	int	dataform;	/* Data format for this entry	*/
856 	int	scms;		/* Serial copy management	*/
857 	msf_t	*mp;		/* MSF value for this entry	*/
858 {
859 	cp->cs_ctladr = ca;
860 	if (tno <= 99)
861 		cp->cs_tno = to_bcd(tno);
862 	else
863 		cp->cs_tno = tno;
864 	cp->cs_index = to_bcd(idx);
865 	if (scms != 0)
866 		dataform |= 0x10;
867 	cp->cs_dataform = dataform;
868 	cp->cs_extension = 0;
869 	cp->cs_min = to_bcd(mp->msf_min);
870 	cp->cs_sec = to_bcd(mp->msf_sec);
871 	cp->cs_frame = to_bcd(mp->msf_frame);
872 }
873 
874 LOCAL int
cw7501_send_cue(scgp,dp,trackp)875 cw7501_send_cue(scgp, dp, trackp)
876 	SCSI	*scgp;
877 	cdr_t	*dp;
878 	track_t	*trackp;
879 {
880 	struct cw7501_cue *cp;
881 	int		ncue;
882 	int		ret;
883 	Uint		i;
884 	struct timeval starttime;
885 	struct timeval stoptime;
886 	int		disktype;
887 
888 	disktype = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
889 
890 	for (i = 1; i <= trackp->tracks; i++) {
891 		if (trackp[i].tracksize < (tsize_t)0) {
892 			errmsgno(EX_BAD, _("Track %d has unknown length.\n"), i);
893 			return (-1);
894 		}
895 	}
896 	ncue = (*dp->cdr_gen_cue)(trackp, &cp, FALSE);
897 
898 	starttime.tv_sec = 0;
899 	starttime.tv_usec = 0;
900 	stoptime = starttime;
901 	gettimeofday(&starttime, (struct timezone *)0);
902 
903 	scgp->silent++;
904 	ret = cw7501_write_dao(scgp, (Uchar *)cp, ncue*8, disktype);
905 	scgp->silent--;
906 	free(cp);
907 	if (ret < 0) {
908 		errmsgno(EX_BAD, _("CUE sheet not accepted. Retrying with minimum pregapsize = 1.\n"));
909 		ncue = (*dp->cdr_gen_cue)(trackp, &cp, TRUE);
910 		ret  = cw7501_write_dao(scgp, (Uchar *)cp, ncue*8, disktype);
911 		free(cp);
912 	}
913 	if (ret >= 0 && lverbose) {
914 		gettimeofday(&stoptime, (struct timezone *)0);
915 		prtimediff(_("Write Lead-in time: "), &starttime, &stoptime);
916 	}
917 	return (ret);
918 }
919 
920 /*--------------------------------------------------------------------------*/
921 LOCAL int
cw7501_rezero(scgp,reset,dwreset)922 cw7501_rezero(scgp, reset, dwreset)
923 	SCSI	*scgp;
924 	int	reset;
925 	int	dwreset;
926 {
927 	register struct	scg_cmd	*scmd = scgp->scmd;
928 
929 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
930 	scmd->addr = (caddr_t)0;
931 	scmd->size = 0;
932 	scmd->flags = SCG_DISRE_ENA;
933 	scmd->cdb_len = SC_G0_CDBLEN;
934 	scmd->sense_len = CCS_SENSE_LEN;
935 	scmd->cdb.g0_cdb.cmd = SC_REZERO_UNIT;
936 	scmd->cdb.g0_cdb.lun = scg_lun(scgp);
937 	scmd->cdb.cmd_cdb[5] |= reset ? 0x80 : 0;
938 	scmd->cdb.cmd_cdb[5] |= dwreset ? 0x40 : 0;
939 
940 	scgp->cmdname = "cw7501 rezero";
941 
942 	return (scg_cmd(scgp));
943 }
944 
945 
946 LOCAL int
cw7501_read_trackinfo(scgp,bp,count,track,mode)947 cw7501_read_trackinfo(scgp, bp, count, track, mode)
948 	SCSI	*scgp;
949 	Uchar	*bp;
950 	int	count;
951 	int	track;
952 	int	mode;
953 {
954 	register struct	scg_cmd	*scmd = scgp->scmd;
955 
956 	fillbytes((caddr_t) scmd, sizeof (*scmd), '\0');
957 	scmd->addr = (caddr_t)bp;
958 	scmd->size = count;
959 	scmd->flags = SCG_RECV_DATA | SCG_DISRE_ENA;
960 	scmd->cdb_len = SC_G1_CDBLEN;
961 	scmd->sense_len = CCS_SENSE_LEN;
962 	scmd->cdb.g1_cdb.cmd = 0xE9;
963 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
964 	scmd->cdb.cmd_cdb[6] = track;
965 	g1_cdblen(&scmd->cdb.g1_cdb, count);
966 	scmd->cdb.cmd_cdb[9] = (mode & 3) << 6;
967 
968 	scgp->cmdname = "cw7501 read_track_information";
969 
970 	if (scg_cmd(scgp) < 0)
971 		return (-1);
972 
973 	return (0);
974 }
975 
976 LOCAL int
cw7501_write_dao(scgp,bp,len,disktype)977 cw7501_write_dao(scgp, bp, len, disktype)
978 	SCSI	*scgp;
979 	Uchar	*bp;
980 	int	len;
981 	int	disktype;
982 {
983 	register struct	scg_cmd	*scmd = scgp->scmd;
984 
985 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
986 	scmd->addr = (caddr_t)bp;
987 	scmd->size = len;
988 	scmd->flags = SCG_DISRE_ENA;
989 	scmd->cdb_len = SC_G1_CDBLEN;
990 	scmd->sense_len = CCS_SENSE_LEN;
991 	scmd->cdb.g1_cdb.cmd = 0xE6;
992 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
993 	scmd->cdb.cmd_cdb[2] = disktype;
994 	g1_cdblen(&scmd->cdb.g1_cdb, len);
995 
996 	scgp->cmdname = "cw7501 write_dao";
997 
998 	if (scg_cmd(scgp) < 0)
999 		return (-1);
1000 	return (0);
1001 }
1002 
1003 /*
1004  * XXX CW-7501 also needs "control", so we need to make a different
1005  * XXX driver interface.
1006  */
1007 LOCAL int
cw7501_reserve_track(scgp,len)1008 cw7501_reserve_track(scgp, len)
1009 	SCSI	*scgp;
1010 	unsigned long len;
1011 {
1012 	register struct	scg_cmd	*scmd = scgp->scmd;
1013 
1014 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1015 	scmd->flags = SCG_DISRE_ENA;
1016 	scmd->cdb_len = SC_G1_CDBLEN;
1017 	scmd->sense_len = CCS_SENSE_LEN;
1018 	scmd->cdb.g1_cdb.cmd = 0xE7;
1019 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1020 /*	scmd->cdb.cmd_cdb[2] = control & 0x0F;*/
1021 	i_to_4_byte(&scmd->cdb.cmd_cdb[5], len);
1022 
1023 	scgp->cmdname = "cw7501 reserve_track";
1024 
1025 	comerrno(EX_BAD, _("Control (as in set mode) missing.\n"));
1026 
1027 	if (scg_cmd(scgp) < 0)
1028 		return (-1);
1029 	return (0);
1030 }
1031 
1032 LOCAL int
cw7501_set_mode(scgp,phys_form,control,subc,alt,trackno,tindex,packet_size,write_mode)1033 cw7501_set_mode(scgp, phys_form, control, subc, alt, trackno, tindex, packet_size, write_mode)
1034 	SCSI	*scgp;
1035 	int	phys_form;
1036 	int	control;
1037 	int	subc;
1038 	int	alt;
1039 	int	trackno;
1040 	int	tindex;
1041 	int	packet_size;
1042 	int	write_mode;
1043 {
1044 	register struct	scg_cmd	*scmd = scgp->scmd;
1045 
1046 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1047 	scmd->flags = SCG_DISRE_ENA;
1048 	scmd->cdb_len = SC_G1_CDBLEN;
1049 	scmd->sense_len = CCS_SENSE_LEN;
1050 	scmd->cdb.g1_cdb.cmd = 0xE2;
1051 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1052 	scmd->cdb.cmd_cdb[2] = phys_form & 0x0F;
1053 	scmd->cdb.cmd_cdb[3] = (control & 0x0F) << 4;
1054 	scmd->cdb.cmd_cdb[3] |= subc ? 2 : 0;
1055 	scmd->cdb.cmd_cdb[3] |= alt ? 1 : 0;
1056 	scmd->cdb.cmd_cdb[4] = trackno;
1057 	scmd->cdb.cmd_cdb[5] = tindex;
1058 	i_to_3_byte(&scmd->cdb.cmd_cdb[6], packet_size);
1059 	scmd->cdb.cmd_cdb[9] = (write_mode & 0x03) << 6;
1060 
1061 	scgp->cmdname = "cw7501 set_mode";
1062 
1063 	if (scg_cmd(scgp) < 0)
1064 		return (-1);
1065 	return (0);
1066 }
1067 
1068 LOCAL int
cw7501_finalize(scgp,pad,fixed)1069 cw7501_finalize(scgp, pad, fixed)
1070 	SCSI	*scgp;
1071 	int	pad;
1072 	int	fixed;
1073 {
1074 	register struct	scg_cmd	*scmd = scgp->scmd;
1075 
1076 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1077 	scmd->flags = SCG_DISRE_ENA;
1078 	scmd->cdb_len = SC_G1_CDBLEN;
1079 	scmd->sense_len = CCS_SENSE_LEN;
1080 	scmd->timeout = 8 * 60;		/* Needs up to 4 minutes */
1081 	scmd->cdb.g1_cdb.cmd = 0xE3;
1082 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1083 	scmd->cdb.cmd_cdb[1] = pad ? 1 : 0;
1084 	scmd->cdb.cmd_cdb[8] = fixed & 0x03;
1085 
1086 	scgp->cmdname = "cw7501 finalize";
1087 
1088 	if (scg_cmd(scgp) < 0)
1089 		return (-1);
1090 	return (0);
1091 }
1092