1 /** @(#)drv_jvc.c	1.95 10/12/19 Copyright 1997-2010 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)drv_jvc.c	1.95 10/12/19 Copyright 1997-2010 J. Schilling";
6 #endif
7 /*
8  *	CDR device implementation for
9  *	JVC/TEAC
10  *
11  *	Copyright (c) 1997-2010 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 /*#define	XXDEBUG*/
27 /*#define	XXBUFFER*/
28 
29 #include <schily/mconfig.h>
30 
31 #include <schily/stdio.h>
32 #include <schily/standard.h>
33 #include <schily/fcntl.h>
34 #include <schily/errno.h>
35 #include <schily/string.h>
36 #include <schily/unistd.h>
37 #ifdef	XXDEBUG
38 #include <schily/stdlib.h>
39 #endif
40 
41 #include <schily/utypes.h>
42 #include <schily/btorder.h>
43 #include <schily/intcvt.h>
44 #include <schily/schily.h>
45 #include <schily/nlsdefs.h>
46 
47 #include <scg/scgcmd.h>
48 #include <scg/scsidefs.h>
49 #include <scg/scsireg.h>
50 #include <scg/scsitransp.h>
51 
52 #include "cdrecord.h"
53 
54 /* just a hack */
55 long	lba_addr;
56 BOOL	last_done;
57 
58 /*
59  * macros for building MSF values from LBA
60  */
61 #define	LBA_MIN(x)	((x)/(60*75))
62 #define	LBA_SEC(x)	(((x)%(60*75))/75)
63 #define	LBA_FRM(x)	((x)%75)
64 #define	MSF_CONV(a)	((((a)%(unsigned)100)/10)*16 + ((a)%(unsigned)10))
65 
66 extern	int	lverbose;
67 
68 #if defined(_BIT_FIELDS_LTOH)	/* Intel byteorder */
69 struct teac_mode_page_21 {		/* teac dummy selection */
70 		MP_P_CODE;		/* parsave & pagecode */
71 	Uchar	p_len;			/* 0x01 = 1 Byte */
72 	Ucbit	dummy		: 2;
73 	Ucbit	res		: 6;
74 };
75 #else
76 struct teac_mode_page_21 {		/* teac dummy selection */
77 		MP_P_CODE;		/* parsave & pagecode */
78 	Uchar	p_len;			/* 0x01 = 1 Byte */
79 	Ucbit	res		: 6;
80 	Ucbit	dummy		: 2;
81 };
82 #endif
83 
84 struct teac_mode_page_31 {		/* teac speed selection */
85 		MP_P_CODE;		/* parsave & pagecode */
86 	Uchar	p_len;			/* 0x02 = 2 Byte */
87 	Uchar	speed;
88 	Uchar	res;
89 };
90 
91 struct cdd_52x_mode_data {
92 	struct scsi_mode_header	header;
93 	union cdd_pagex	{
94 		struct teac_mode_page_21	teac_page21;
95 		struct teac_mode_page_31	teac_page31;
96 	} pagex;
97 };
98 
99 #if defined(_BIT_FIELDS_LTOH)	/* Intel byteorder */
100 
101 struct pgm_subcode {		/* subcode for progam area */
102 	Uchar	subcode;
103 	Ucbit	addr		: 4;
104 	Ucbit	control		: 4;
105 	Uchar	track;
106 	Uchar	index;
107 };
108 
109 #else
110 
111 struct pgm_subcode {		/* subcode for progam area */
112 	Uchar	subcode;
113 	Ucbit	control		: 4;
114 	Ucbit	addr		: 4;
115 	Uchar	track;
116 	Uchar	index;
117 };
118 
119 #endif
120 
121 #define	set_pgm_subcode(sp, t, c, a, tr, idx)		(\
122 			(sp)->subcode = (t),		 \
123 			(sp)->control = (c),		 \
124 			(sp)->addr = (a),		 \
125 			(sp)->track = MSF_CONV(tr),	 \
126 			(sp)->index = (idx))
127 
128 #define	SC_P		1	/* Subcode defines pre-gap (Pause)	*/
129 #define	SC_TR		0	/* Subcode defines track data		*/
130 
131 #if defined(_BIT_FIELDS_LTOH)	/* Intel byteorder */
132 
133 typedef struct lin_subcode {	/* subcode for lead in area */
134 	Ucbit	addr		: 4;
135 	Ucbit	control		: 4;
136 	Uchar	track;
137 	Uchar	msf[3];
138 } lsc_t;
139 
140 #else
141 
142 typedef struct lin_subcode {	/* subcode for lead in area */
143 	Ucbit	control		: 4;
144 	Ucbit	addr		: 4;
145 	Uchar	track;
146 	Uchar	msf[3];
147 } lsc_t;
148 
149 #endif
150 
151 #define	set_toc_subcode(sp, c, a, tr, bno)				(\
152 			((lsc_t *)sp)->control = (c),			 \
153 			((lsc_t *)sp)->addr = (a),			 \
154 			((lsc_t *)sp)->track = MSF_CONV(tr),		 \
155 			((lsc_t *)sp)->msf[0] = MSF_CONV(LBA_MIN(bno)),	 \
156 			((lsc_t *)sp)->msf[1] = MSF_CONV(LBA_SEC(bno)),	 \
157 			((lsc_t *)sp)->msf[2] = MSF_CONV(LBA_FRM(bno)),	 \
158 			&((lsc_t *)sp)->msf[3])
159 
160 #define	set_lin_subcode(sp, c, a, pt, min, sec, frm)			(\
161 			((lsc_t *)sp)->control = (c),			 \
162 			((lsc_t *)sp)->addr = (a),			 \
163 			((lsc_t *)sp)->track = (pt),			 \
164 			((lsc_t *)sp)->msf[0] = (min),			 \
165 			((lsc_t *)sp)->msf[1] = (sec),			 \
166 			((lsc_t *)sp)->msf[2] = (frm),			 \
167 			&((lsc_t *)sp)->msf[3])
168 
169 #if defined(_BIT_FIELDS_LTOH)	/* Intel byteorder */
170 
171 struct upc_subcode {		/* subcode for upc/bar code */
172 	Uchar	res;
173 	Ucbit	addr		: 4;
174 	Ucbit	control		: 4;
175 	Uchar	upc[13];
176 };
177 
178 #else
179 
180 struct upc_subcode {		/* subcode for upc/bar code */
181 	Uchar	res;
182 	Ucbit	control		: 4;
183 	Ucbit	addr		: 4;
184 	Uchar	upc[13];
185 };
186 
187 #endif
188 
189 #if defined(_BIT_FIELDS_LTOH)	/* Intel byteorder */
190 
191 struct isrc_subcode {		/* subcode for ISRC code */
192 	Uchar	res;
193 	Ucbit	addr		: 4;
194 	Ucbit	control		: 4;
195 	Uchar	isrc[12];
196 	Uchar	res14;
197 };
198 
199 #else
200 
201 struct isrc_subcode {		/* subcode for ISRC code */
202 	Uchar	res;
203 	Ucbit	control		: 4;
204 	Ucbit	addr		: 4;
205 	Uchar	isrc[12];
206 	Uchar	res14;
207 };
208 
209 #endif
210 
211 
212 LOCAL	int	teac_attach		__PR((SCSI *scgp, cdr_t *dp));
213 LOCAL	int	teac_init		__PR((SCSI *scgp, cdr_t *dp));
214 LOCAL	int	teac_getdisktype	__PR((SCSI *scgp, cdr_t *dp));
215 LOCAL	int	speed_select_teac	__PR((SCSI *scgp, cdr_t *dp, int *speedp));
216 LOCAL	int	select_secsize_teac	__PR((SCSI *scgp, track_t *trackp));
217 LOCAL	int	next_wr_addr_jvc	__PR((SCSI *scgp, track_t *, long *ap));
218 LOCAL	int	write_teac_xg1		__PR((SCSI *scgp, caddr_t, long, long, int, BOOL));
219 LOCAL	int	cdr_write_teac		__PR((SCSI *scgp, caddr_t bp, long sectaddr, long size, int blocks, BOOL islast));
220 LOCAL	int	open_track_jvc		__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
221 LOCAL	int	teac_fixation		__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
222 LOCAL	int	close_track_teac	__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
223 LOCAL	int	teac_open_session	__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
224 LOCAL	int	initsub_teac		__PR((SCSI *scgp, int toctype, int multi));
225 LOCAL	int	teac_doopc		__PR((SCSI *scgp));
226 LOCAL	int	teac_opc		__PR((SCSI *scgp, caddr_t, int cnt, int doopc));
227 LOCAL	int	opt_power_judge		__PR((SCSI *scgp, int judge));
228 LOCAL	int	clear_subcode		__PR((SCSI *scgp));
229 LOCAL	int	set_limits		__PR((SCSI *scgp, long lba, long length));
230 LOCAL	int	set_subcode		__PR((SCSI *scgp, Uchar *subcode_data, int length));
231 #ifdef	XDI
232 LOCAL	int	read_disk_info_teac	__PR((SCSI *scgp, Uchar *data, int length, int type));
233 #endif
234 LOCAL	int	teac_freeze		__PR((SCSI *scgp, int bp_flag));
235 LOCAL	int	teac_wr_pma		__PR((SCSI *scgp));
236 LOCAL	int	teac_rd_pma		__PR((SCSI *scgp));
237 LOCAL	int	next_wr_addr_teac	__PR((SCSI *scgp, long start_lba, long last_lba));
238 LOCAL	int	blank_jvc		__PR((SCSI *scgp, cdr_t *dp, long addr, int blanktype));
239 LOCAL	int	buf_cap_teac		__PR((SCSI *scgp, long *sp, long *fp));
240 LOCAL	long	read_peak_buffer_cap_teac __PR((SCSI *scgp));
241 #ifdef	XXBUFFER
242 LOCAL	int	buffer_inquiry_teac	__PR((SCSI *scgp, int fmt));
243 LOCAL	void	check_buffer_teac	__PR((SCSI *scgp));
244 #endif
245 #ifdef	XXDEBUG
246 LOCAL	void	xxtest_teac		__PR((SCSI *scgp));
247 #endif
248 
249 
250 cdr_t	cdr_teac_cdr50 = {
251 	0, 0, 0,
252 /*	CDR_TAO|CDR_SAO|CDR_SWABAUDIO|CDR_NO_LOLIMIT,*/
253 	CDR_TAO|CDR_SWABAUDIO|CDR_NO_LOLIMIT,
254 	0,
255 	CDR_CDRW_ALL,
256 	WM_TAO,
257 	2, 4,
258 	"teac_cdr50",
259 	"driver for Teac CD-R50S, Teac CD-R55S, JVC XR-W2010, Pinnacle RCD-5020",
260 	0,
261 	(dstat_t *)0,
262 	drive_identify,
263 	teac_attach,
264 	teac_init,
265 	teac_getdisktype,
266 	no_diskstatus,
267 	scsi_load,
268 	scsi_unload,
269 	buf_cap_teac,
270 	cmd_dummy,					/* recovery_needed */
271 	(int(*)__PR((SCSI *, cdr_t *, int)))cmd_dummy,	/* recover	*/
272 	speed_select_teac,
273 	select_secsize,
274 	next_wr_addr_jvc,
275 	(int(*)__PR((SCSI *, Ulong)))cmd_ill,	/* reserve_track	*/
276 	cdr_write_teac,
277 	(int(*)__PR((track_t *, void *, BOOL)))cmd_dummy,	/* gen_cue */
278 	no_sendcue,
279 	(int(*)__PR((SCSI *, cdr_t *, track_t *)))cmd_dummy, /* leadin */
280 	open_track_jvc,
281 	close_track_teac,
282 	teac_open_session,
283 	cmd_dummy,
284 	cmd_dummy,					/* abort	*/
285 	read_session_offset_philips,
286 	teac_fixation,
287 	cmd_dummy,					/* stats	*/
288 /*	blank_dummy,*/
289 	blank_jvc,
290 	format_dummy,
291 	teac_opc,
292 	cmd_dummy,					/* opt1		*/
293 	cmd_dummy,					/* opt2		*/
294 };
295 
296 LOCAL int
teac_init(scgp,dp)297 teac_init(scgp, dp)
298 	SCSI	*scgp;
299 	cdr_t	*dp;
300 {
301 	return (speed_select_teac(scgp, dp, NULL));
302 }
303 
304 LOCAL int
teac_getdisktype(scgp,dp)305 teac_getdisktype(scgp, dp)
306 	SCSI	*scgp;
307 	cdr_t	*dp;
308 {
309 	dstat_t	*dsp = dp->cdr_dstat;
310 	struct scsi_mode_data md;
311 	int	count = sizeof (struct scsi_mode_header) +
312 			sizeof (struct scsi_mode_blockdesc);
313 	int	len;
314 	int	page = 0;
315 	long	l;
316 
317 	fillbytes((caddr_t)&md, sizeof (md), '\0');
318 
319 	(void) test_unit_ready(scgp);
320 	if (mode_sense(scgp, (Uchar *)&md, count, page, 0) < 0) {	/* Page n current */
321 		return (-1);
322 	} else {
323 		len = ((struct scsi_mode_header *)&md)->sense_data_len + 1;
324 	}
325 	if (((struct scsi_mode_header *)&md)->blockdesc_len < 8)
326 		return (-1);
327 
328 	l = a_to_u_3_byte(md.blockdesc.nlblock);
329 	dsp->ds_maxblocks = l;
330 	return (drive_getdisktype(scgp, dp));
331 }
332 
333 LOCAL int
speed_select_teac(scgp,dp,speedp)334 speed_select_teac(scgp, dp, speedp)
335 	SCSI	*scgp;
336 	cdr_t	*dp;
337 	int	*speedp;
338 {
339 	struct cdd_52x_mode_data md;
340 	int	count;
341 	int	status;
342 	int	speed = 1;
343 	BOOL	dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
344 
345 	if (speedp)
346 		speed = *speedp;
347 
348 	fillbytes((caddr_t)&md, sizeof (md), '\0');
349 
350 	count  = sizeof (struct scsi_mode_header) +
351 		sizeof (struct teac_mode_page_21);
352 
353 	md.pagex.teac_page21.p_code = 0x21;
354 	md.pagex.teac_page21.p_len =  0x01;
355 	md.pagex.teac_page21.dummy = dummy?3:0;
356 
357 	status = mode_select(scgp, (Uchar *)&md, count, 0, scgp->inq->data_format >= 2);
358 	if (status < 0)
359 		return (status);
360 
361 	if (speedp == 0)
362 		return (0);
363 
364 	fillbytes((caddr_t)&md, sizeof (md), '\0');
365 
366 	count  = sizeof (struct scsi_mode_header) +
367 		sizeof (struct teac_mode_page_31);
368 
369 	speed >>= 1;
370 	md.pagex.teac_page31.p_code = 0x31;
371 	md.pagex.teac_page31.p_len =  0x02;
372 	md.pagex.teac_page31.speed = speed;
373 
374 	return (mode_select(scgp, (Uchar *)&md, count, 0, scgp->inq->data_format >= 2));
375 }
376 
377 LOCAL int
select_secsize_teac(scgp,trackp)378 select_secsize_teac(scgp, trackp)
379 	SCSI	*scgp;
380 	track_t	*trackp;
381 {
382 	struct scsi_mode_data md;
383 	int	count = sizeof (struct scsi_mode_header) +
384 			sizeof (struct scsi_mode_blockdesc);
385 	int	len;
386 	int	page = 0;
387 
388 	fillbytes((caddr_t)&md, sizeof (md), '\0');
389 
390 	(void) test_unit_ready(scgp);
391 	if (mode_sense(scgp, (Uchar *)&md, count, page, 0) < 0) {	/* Page n current */
392 		return (-1);
393 	} else {
394 		len = ((struct scsi_mode_header *)&md)->sense_data_len + 1;
395 	}
396 	if (((struct scsi_mode_header *)&md)->blockdesc_len < 8)
397 		return (-1);
398 
399 	md.header.sense_data_len = 0;
400 	md.header.blockdesc_len = 8;
401 
402 	md.blockdesc.density = 1;
403 	if (trackp->secsize == 2352)
404 		md.blockdesc.density = 4;
405 	i_to_3_byte(md.blockdesc.lblen, trackp->secsize);
406 
407 	return (mode_select(scgp, (Uchar *)&md, count, 0, scgp->inq->data_format >= 2));
408 }
409 
410 LOCAL int
next_wr_addr_jvc(scgp,trackp,ap)411 next_wr_addr_jvc(scgp, trackp, ap)
412 	SCSI	*scgp;
413 	track_t	*trackp;
414 	long	*ap;
415 {
416 	if (trackp != 0 && trackp->track > 0) {
417 		*ap = lba_addr;
418 	} else {
419 		long	nwa;
420 
421 		if (read_B0(scgp, TRUE, &nwa, NULL) < 0)
422 			return (-1);
423 
424 		*ap = nwa + 150;
425 	}
426 	return (0);
427 }
428 
429 LOCAL int
write_teac_xg1(scgp,bp,sectaddr,size,blocks,extwr)430 write_teac_xg1(scgp, bp, sectaddr, size, blocks, extwr)
431 	SCSI	*scgp;
432 	caddr_t	bp;		/* address of buffer */
433 	long	sectaddr;	/* disk address (sector) to put */
434 	long	size;		/* number of bytes to transfer */
435 	int	blocks;		/* sector count */
436 	BOOL	extwr;		/* is an extended write */
437 {
438 	register struct	scg_cmd	*scmd = scgp->scmd;
439 
440 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
441 	scmd->addr = bp;
442 	scmd->size = size;
443 	scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
444 /*	scmd->flags = SCG_DISRE_ENA;*/
445 	scmd->cdb_len = SC_G1_CDBLEN;
446 	scmd->sense_len = CCS_SENSE_LEN;
447 	scmd->cdb.g1_cdb.cmd = SC_EWRITE;
448 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
449 	g1_cdbaddr(&scmd->cdb.g1_cdb, sectaddr);
450 	g1_cdblen(&scmd->cdb.g1_cdb, blocks);
451 	scmd->cdb.g1_cdb.vu_97 = extwr;
452 
453 	scgp->cmdname = "write_teac_g1";
454 
455 	if (scg_cmd(scgp) < 0)
456 		return (-1);
457 	return (size - scg_getresid(scgp));
458 }
459 
460 LOCAL int
cdr_write_teac(scgp,bp,sectaddr,size,blocks,islast)461 cdr_write_teac(scgp, bp, sectaddr, size, blocks, islast)
462 	SCSI	*scgp;
463 	caddr_t	bp;		/* address of buffer */
464 	long	sectaddr;	/* disk address (sector) to put */
465 	long	size;		/* number of bytes to transfer */
466 	int	blocks;		/* sector count */
467 	BOOL	islast;		/* last write for track */
468 {
469 	int	ret;
470 
471 	if (islast)
472 		last_done = TRUE;
473 
474 	ret = write_teac_xg1(scgp, bp, sectaddr, size, blocks, !islast);
475 	if (ret < 0)
476 		return (ret);
477 
478 	lba_addr = sectaddr + blocks;
479 #ifdef	XXBUFFER
480 	check_buffer_teac(scgp);
481 #endif
482 	return (ret);
483 }
484 
485 LOCAL int
open_track_jvc(scgp,dp,trackp)486 open_track_jvc(scgp, dp, trackp)
487 	SCSI	*scgp;
488 	cdr_t	*dp;
489 	track_t	*trackp;
490 {
491 	int	status;
492 	long	blocks;
493 	long	pregapsize;
494 	struct	pgm_subcode	sc;
495 
496 	last_done = FALSE;
497 
498 	if (select_secsize_teac(scgp, trackp) < 0)
499 		return (-1);
500 
501 	status = clear_subcode(scgp);
502 /*next_wr_addr_teac(scgp);*/
503 	if (status < 0)
504 		return (status);
505 
506 if (trackp->pregapsize != 0) {
507 	if (lverbose > 1) {
508 		printf(_("set_limits(%ld, %ld)-> %ld\n"),
509 		lba_addr, trackp->pregapsize, lba_addr + trackp->pregapsize);
510 	}
511 
512 	status = set_limits(scgp, lba_addr, trackp->pregapsize);
513 	if (status < 0)
514 		return (status);
515 
516 	/*
517 	 * Set pre-gap (pause - index 0)
518 	 */
519 	set_pgm_subcode(&sc, SC_P,
520 			st2mode[trackp->sectype&ST_MASK], ADR_POS, trackp->trackno, 0);
521 
522 	if (lverbose > 1)
523 		scg_prbytes(_("Subcode:"), (Uchar *)&sc, sizeof (sc));
524 
525 	status = set_subcode(scgp, (Uchar *)&sc, sizeof (sc));
526 	if (status < 0)
527 		return (status);
528 
529 	pregapsize = trackp->pregapsize;
530 	if (!is_audio(trackp)) {
531 		lba_addr += 5;	/* link & run in blocks */
532 		pregapsize -= 5;
533 	}
534 	if (lverbose > 1) {
535 		printf(_("pad_track(%ld, %ld)-> %ld\n"),
536 			lba_addr, pregapsize, lba_addr + pregapsize);
537 	}
538 	/*
539 	 * XXX Do we need to check isecsize too?
540 	 */
541 	if (pad_track(scgp, dp, trackp,
542 			lba_addr, (Llong)pregapsize*trackp->secsize,
543 			FALSE, (Llong *)0) < 0)
544 		return (-1);
545 }
546 
547 	blocks = trackp->tracksize/trackp->secsize +
548 		    (trackp->tracksize%trackp->secsize?1:0);
549 	blocks += trackp->padsecs;
550 	if (blocks < 300)
551 		blocks = 300;
552 	if (!is_audio(trackp))
553 		blocks += 2;
554 if (!is_last(trackp) && trackp[1].pregapsize == 0)
555 		blocks -= 150;
556 
557 	/*
558 	 * set the limits for the new subcode - seems to apply to all
559 	 * of the data track.
560 	 * Unknown tracksize is handled in open_session.
561 	 * We definitely need to know the tracksize in this driver.
562 	 */
563 	if (lverbose > 1) {
564 		printf(_("set_limits(%ld, %ld)-> %ld\n"),
565 			lba_addr, blocks, lba_addr + blocks);
566 	}
567 	status = set_limits(scgp, lba_addr, blocks);
568 	if (status < 0)
569 		return (status);
570 
571 	/*
572 	 * Set track start (index 1)
573 	 */
574 	set_pgm_subcode(&sc, SC_TR,
575 			st2mode[trackp->sectype&ST_MASK], ADR_POS, trackp->trackno, 1);
576 
577 	if (lverbose > 1)
578 		scg_prbytes(_("Subcode:"), (Uchar *)&sc, sizeof (sc));
579 
580 	status = set_subcode(scgp, (Uchar *)&sc, sizeof (sc));
581 	if (status < 0)
582 		return (status);
583 
584 if (!is_last(trackp) && trackp[1].pregapsize == 0) {
585 	blocks += lba_addr;
586 	pregapsize = 150;
587 
588 	if (lverbose > 1) {
589 		printf(_("set_limits(%ld, %ld)-> %ld\n"),
590 		blocks, pregapsize, blocks + pregapsize);
591 	}
592 
593 	status = set_limits(scgp, blocks, pregapsize);
594 	if (status < 0)
595 		return (status);
596 
597 	/*
598 	 * Set pre-gap (pause - index 0)
599 	 */
600 	trackp++;
601 	set_pgm_subcode(&sc, SC_P,
602 			st2mode[trackp->sectype&ST_MASK], ADR_POS, trackp->trackno, 0);
603 
604 	if (lverbose > 1)
605 		scg_prbytes(_("Subcode:"), (Uchar *)&sc, sizeof (sc));
606 
607 	status = set_subcode(scgp, (Uchar *)&sc, sizeof (sc));
608 	if (status < 0)
609 		return (status);
610 }
611 	return (status);
612 }
613 
614 LOCAL	char	sector[3000];
615 
616 LOCAL int
close_track_teac(scgp,dp,trackp)617 close_track_teac(scgp, dp, trackp)
618 	SCSI	*scgp;
619 	cdr_t	*dp;
620 	track_t	*trackp;
621 {
622 	int	ret = 0;
623 
624 	if (!last_done) {
625 		printf(_("WARNING: adding dummy block to close track.\n"));
626 		/*
627 		 * need read sector size
628 		 * XXX do we really need this ?
629 		 * XXX if we need this can we set blocks to 0 ?
630 		 */
631 		ret =  write_teac_xg1(scgp, sector, lba_addr, 2352, 1, FALSE);
632 		lba_addr++;
633 	}
634 	if (!is_audio(trackp))
635 		lba_addr += 2;
636 	teac_wr_pma(scgp);
637 	return (ret);
638 }
639 
640 
641 
642 static const char *sd_teac50_error_str[] = {
643 	"\100\200diagnostic failure on component parts",	/* 40 80 */
644 	"\100\201diagnostic failure on memories",		/* 40 81 */
645 	"\100\202diagnostic failure on cd-rom ecc circuit",	/* 40 82 */
646 	"\100\203diagnostic failure on gate array",		/* 40 83 */
647 	"\100\204diagnostic failure on internal SCSI controller",	/* 40 84 */
648 	"\100\205diagnostic failure on servo processor",	/* 40 85 */
649 	"\100\206diagnostic failure on program rom",		/* 40 86 */
650 	"\100\220thermal sensor failure",			/* 40 90 */
651 	"\200\000controller prom error",			/* 80 00 */	/* JVC */
652 	"\201\000no disk present - couldn't get focus",		/* 81 00 */	/* JVC */
653 	"\202\000no cartridge present",				/* 82 00 */	/* JVC */
654 	"\203\000unable to spin up",				/* 83 00 */	/* JVC */
655 	"\204\000addr exceeded the last valid block addr",	/* 84 00 */	/* JVC */
656 	"\205\000sync error",					/* 85 00 */	/* JVC */
657 	"\206\000address can't find or not data track",		/* 86 00 */	/* JVC */
658 	"\207\000missing track",				/* 87 00 */	/* JVC */
659 	"\213\000cartridge could not be ejected",		/* 8B 00 */	/* JVC */
660 	"\215\000audio not playing",				/* 8D 00 */	/* JVC */
661 	"\216\000read toc error",				/* 8E 00 */	/* JVC */
662 	"\217\000a blank disk is detected by read toc",		/* 8F 00 */
663 	"\220\000pma less disk - not a recordable disk",	/* 90 00 */
664 	"\223\000mount error",					/* 93 00 */	/* JVC */
665 	"\224\000toc less disk",				/* 94 00 */
666 	"\225\000disc information less disk",			/* 95 00 */	/* JVC */
667 	"\226\000disc information read error",			/* 96 00 */	/* JVC */
668 	"\227\000linear velocity measurement error",		/* 97 00 */	/* JVC */
669 	"\230\000drive sequence stop",				/* 98 00 */	/* JVC */
670 	"\231\000actuator velocity control error",		/* 99 00 */	/* JVC */
671 	"\232\000slider velocity control error",		/* 9A 00 */	/* JVC */
672 	"\233\000opc initialize error",				/* 9B 00 */
673 	"\233\001power calibration not executed",		/* 9B 01 */
674 	"\234\000opc execution eror",				/* 9C 00 */
675 	"\234\001alpc error - opc execution",			/* 9C 01 */
676 	"\234\002opc execution timeout",			/* 9C 02 */
677 	"\245\000disk application code does not match host application code",	/* A5 00 */
678 	"\255\000completed preview write",			/* AD 00 */
679 	"\256\000invalid B0 value",				/* AE 00 */	/* JVC */
680 	"\257\000pca area full",				/* AF 00 */
681 	"\260\000efm isn't detected",				/* B0 00 */	/* JVC */
682 	"\263\000no logical sector",				/* B3 00 */	/* JVC */
683 	"\264\000full pma area",				/* B4 00 */
684 	"\265\000read address is atip area - blank",		/* B5 00 */
685 	"\266\000write address is efm area - aleady written",	/* B6 00 */
686 	"\271\000abnormal spinning - servo irq",		/* B9 00 */	/* JVC */
687 	"\272\000no write data - buffer empty",			/* BA 00 */
688 	"\273\000write emergency occurred",			/* BB 00 */
689 	"\274\000read timeout",					/* BC 00 */	/* JVC */
690 	"\277\000abnormal spin - nmi",				/* BF 00 */	/* JVC */
691 	"\301\0004th run-in block detected",			/* C1 00 */
692 	"\302\0003rd run-in block detected",			/* C2 00 */
693 	"\303\0002nd run-in block detected",			/* C3 00 */
694 	"\304\0001st run-in block detected",			/* C4 00 */
695 	"\305\000link block detected",				/* C5 00 */
696 	"\306\0001st run-out block detected",			/* C6 00 */
697 	"\307\0002nd run-out block detected",			/* C7 00 */
698 	"\314\000write request means mixed data mode",		/* CC 00 */
699 	"\315\000unable to ensure reliable writing with the inserted disk - unsupported disk",	 /* CD 00 */
700 	"\316\000unable to ensure reliable writing as the inserted disk does not support speed", /* CE 00 */
701 	"\317\000unable to ensure reliable writing as the inserted disk has no char id code",	 /* CF 00 */
702 	NULL
703 };
704 
705 LOCAL int
teac_attach(scgp,dp)706 teac_attach(scgp, dp)
707 	SCSI	*scgp;
708 	cdr_t	*dp;
709 {
710 	scg_setnonstderrs(scgp, sd_teac50_error_str);
711 #ifdef	XXDEBUG
712 	xxtest_teac(scgp);
713 	exit(0);
714 #endif
715 	return (0);
716 }
717 
718 LOCAL int
teac_fixation(scgp,dp,trackp)719 teac_fixation(scgp, dp, trackp)
720 	SCSI	*scgp;
721 	cdr_t	*dp;
722 	track_t	*trackp;
723 {
724 	long	lba;
725 	int	status;
726 	Uchar	*sp;
727 	Uint	i;
728 extern	char	*buf;
729 
730 	if (trackp->tracks < 1) {
731 		/*
732 		 * We come here if cdrecord isonly called with the -fix option.
733 		 * As long as we cannot read and interpret the PMA, we must
734 		 * abort here.
735 		 */
736 		teac_rd_pma(scgp);
737 /*		errmsgno(EX_BAD, "Cannot fixate zero track disk.\n");*/
738 		errmsgno(EX_BAD, _("Cannot fixate without track list (not yet implemented).\n"));
739 		return (-1);
740 	}
741 	sp = (Uchar *)buf;
742 
743 	sleep(1);
744 
745 	status = clear_subcode(scgp);
746 	sleep(1);
747 	if (status < 0)
748 		return (status);
749 
750 	sp[0] = 0;		/* reserved */
751 	sp[1] = 0;		/* reserved */
752 	sp[2] = 0;		/* Q TNO */
753 
754 	sp = &sp[3];		/* point past header */
755 
756 	/*
757 	 * Set up TOC entries for all tracks
758 	 */
759 	for (i = 1; i <= trackp->tracks; i++) {
760 		lba = trackp[i].trackstart+150;	/* MSF=00:02:00 is LBA=0 */
761 
762 		sp = set_toc_subcode(sp,
763 				/* ctrl/adr for this track */
764 				st2mode[trackp[i].sectype&ST_MASK], ADR_POS,
765 					trackp[i].trackno, lba);
766 	}
767 
768 	/*
769 	 * Set first track on disk
770 	 *
771 	 * XXX We set the track type for the lead-in to the track type
772 	 * XXX of the first track. The TEAC manual states that we should use
773 	 * XXX audio if the disk contains both, audio and data tracks.
774 	 */
775 	sp = set_lin_subcode(sp,
776 		/* ctrl/adr for first track */
777 		st2mode[trackp[1].sectype&ST_MASK], ADR_POS,
778 		0xA0,				/* Point A0 */
779 		trackp[1].trackno,		/* first track # */
780 		toc2sess[track_base(trackp)->tracktype & TOC_MASK],	/* disk type */
781 		0);				/* reserved */
782 
783 	/*
784 	 * Set last track on disk
785 	 */
786 	sp = set_lin_subcode(sp,
787 		/* ctrl/adr for first track */
788 		st2mode[trackp[1].sectype&ST_MASK], ADR_POS,
789 		0xA1,				/* Point A1 */
790 		MSF_CONV(trackp[trackp->tracks].trackno), /* last track # */
791 		0,				/* reserved */
792 		0);				/* reserved */
793 
794 	/*
795 	 * Set start of lead out area in MSF
796 	 * MSF=00:02:00 is LBA=0
797 	 */
798 	lba = lba_addr + 150;
799 	if (lverbose > 1)
800 	printf(_("lba: %ld lba_addr: %ld\n"), lba, lba_addr);
801 
802 	if (lverbose > 1)
803 	printf(_("Lead out start: (%02d:%02d/%02d)\n"),
804 			minutes(lba*2352),
805 			seconds(lba*2352),
806 			frames(lba*2352));
807 
808 	sp = set_lin_subcode(sp,
809 		/* ctrl/adr for first track */
810 		st2mode[trackp[1].sectype&ST_MASK], ADR_POS,
811 		0xA2,				/* Point A2 */
812 		MSF_CONV(LBA_MIN(lba)),
813 		MSF_CONV(LBA_SEC(lba)),
814 		MSF_CONV(LBA_FRM(lba)));
815 
816 	status = sp - ((Uchar *)buf);
817 	if (lverbose > 1) {
818 		printf(_("Subcode len: %d\n"), status);
819 		scg_prbytes(_("Subcode:"), (Uchar *)buf, status);
820 	}
821 	status = set_subcode(scgp, (Uchar *)buf, status);
822 	sleep(1);
823 	if (status < 0)
824 		return (status);
825 
826 	/*
827 	 * now write the toc
828 	 */
829 	status = teac_freeze(scgp, (track_base(trackp)->tracktype & TOCF_MULTI) == 0);
830 	return (status);
831 
832 }
833 
834 LOCAL int
teac_open_session(scgp,dp,trackp)835 teac_open_session(scgp, dp, trackp)
836 	SCSI	*scgp;
837 	cdr_t	*dp;
838 	track_t	*trackp;
839 {
840 	Uint	i;
841 
842 	for (i = 1; i <= trackp->tracks; i++) {
843 		if (trackp[i].tracksize < (tsize_t)0) {
844 			/*
845 			 * XXX How about setting the subcode range to infinity.
846 			 * XXX and correct it in clode track before writing
847 			 * XXX the PMA?
848 			 */
849 			errmsgno(EX_BAD, _("Track %d has unknown length.\n"), i);
850 			return (-1);
851 		}
852 	}
853 	return (initsub_teac(scgp, track_base(trackp)->tracktype & TOC_MASK,
854 				track_base(trackp)->tracktype & TOCF_MULTI));
855 }
856 
857 LOCAL int
initsub_teac(scgp,toctype,multi)858 initsub_teac(scgp, toctype, multi)
859 	SCSI	*scgp;
860 	int	toctype;
861 	int	multi;
862 {
863 	int	status;
864 
865 	scgp->silent++;
866 	if (read_B0(scgp, TRUE, &lba_addr, NULL) < 0)
867 		lba_addr = -150;
868 	scgp->silent--;
869 
870 	status = clear_subcode(scgp);
871 	if (status < 0)
872 		return (status);
873 
874 	return (0);
875 }
876 
877 LOCAL int
teac_doopc(scgp)878 teac_doopc(scgp)
879 	SCSI	*scgp;
880 {
881 	int	status;
882 
883 	if (lverbose) {
884 		fprintf(stdout, _("Judging disk..."));
885 		flush();
886 	}
887 	status = opt_power_judge(scgp, 1);
888 	if (status < 0) {
889 		printf("\n");
890 		return (status);
891 	}
892 	if (lverbose) {
893 		fprintf(stdout, _("done.\nCalibrating laser..."));
894 		flush();
895 	}
896 
897 	status = opt_power_judge(scgp, 0);
898 	if (lverbose) {
899 		fprintf(stdout, _("done.\n"));
900 	}
901 	/*
902 	 * Check for error codes 0xCD ... 0xCF
903 	 */
904 	scgp->silent++;
905 	if (next_wr_addr_teac(scgp, -1, -1) < 0) {
906 		if (scgp->verbose == 0 && scg_sense_key(scgp) != SC_ILLEGAL_REQUEST)
907 			scg_printerr(scgp);
908 	}
909 	scgp->silent--;
910 	return (status);
911 }
912 
913 LOCAL int
teac_opc(scgp,bp,cnt,doopc)914 teac_opc(scgp, bp, cnt, doopc)
915 	SCSI	*scgp;
916 	caddr_t	bp;
917 	int	cnt;
918 	int	doopc;
919 {
920 	int	status;
921 	int	count = 0;
922 
923 	do {
924 		status = teac_doopc(scgp);
925 	} while (++count <= 1 && status < 0);
926 
927 	return (status);
928 }
929 
930 /*--------------------------------------------------------------------------*/
931 #define	SC_SET_LIMITS		0xb3		/* teac 12 byte command */
932 #define	SC_SET_SUBCODE		0xc2		/* teac 10 byte command */
933 #define	SC_READ_PMA		0xc4		/* teac 10 byte command */
934 #define	SC_READ_DISK_INFO	0xc7		/* teac 10 byte command */
935 #define	SC_BUFFER_INQUIRY	0xe0		/* teac 12 byte command */
936 
937 #define	SC_WRITE_PMA		0xe1		/* teac 12 byte command */
938 #define	SC_FREEZE		0xe3		/* teac 12 byte command */
939 #define	SC_OPC_EXECUTE		0xec		/* teac 12 byte command */
940 #define	SC_CLEAR_SUBCODE	0xe4		/* teac 12 byte command */
941 #define	SC_NEXT_WR_ADDRESS	0xe6		/* teac 12 byte command */
942 
943 #define	SC_READ_PEAK_BUF_CAP	0xef		/* teac 12 byte command */
944 
945 /*
946  * Optimum power calibration for Teac Drives.
947  */
948 LOCAL int
opt_power_judge(scgp,judge)949 opt_power_judge(scgp, judge)
950 	SCSI	*scgp;
951 	int	judge;
952 {
953 	register struct	scg_cmd	*scmd = scgp->scmd;
954 
955 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
956 	scmd->addr = (caddr_t)0;
957 	scmd->size = 0;
958 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
959 	scmd->cdb_len = SC_G5_CDBLEN;
960 	scmd->sense_len = CCS_SENSE_LEN;
961 	scmd->timeout = 60;
962 
963 	scmd->cdb.g5_cdb.cmd = SC_OPC_EXECUTE;
964 	scmd->cdb.g5_cdb.lun = scg_lun(scgp);
965 	scmd->cdb.g5_cdb.reladr = judge; /* Judge the Disc */
966 
967 	scgp->cmdname = "opt_power_judge";
968 
969 	return (scg_cmd(scgp));
970 }
971 
972 /*
973  * Clear subcodes for Teac Drives.
974  */
975 LOCAL int
clear_subcode(scgp)976 clear_subcode(scgp)
977 	SCSI	*scgp;
978 {
979 	register struct	scg_cmd	*scmd = scgp->scmd;
980 
981 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
982 	scmd->addr = (caddr_t)0;
983 	scmd->size = 0;
984 	scmd->flags = SCG_DISRE_ENA;
985 	scmd->cdb_len = SC_G5_CDBLEN;
986 	scmd->sense_len = CCS_SENSE_LEN;
987 
988 	scmd->cdb.g5_cdb.cmd = SC_CLEAR_SUBCODE;
989 	scmd->cdb.g5_cdb.lun = scg_lun(scgp);
990 	scmd->cdb.g5_cdb.addr[3] = 0x80;
991 
992 	scgp->cmdname = "clear subcode";
993 
994 	return (scg_cmd(scgp));
995 }
996 
997 /*
998  * Set limits for command linking for Teac Drives.
999  */
1000 LOCAL int
set_limits(scgp,lba,length)1001 set_limits(scgp, lba, length)
1002 	SCSI	*scgp;
1003 	long	lba;
1004 	long	length;
1005 {
1006 	register struct	scg_cmd	*scmd = scgp->scmd;
1007 
1008 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1009 	scmd->addr = (caddr_t)0;
1010 	scmd->size = 0;
1011 	scmd->flags = SCG_DISRE_ENA;
1012 	scmd->cdb_len = SC_G5_CDBLEN;
1013 	scmd->sense_len = CCS_SENSE_LEN;
1014 
1015 	scmd->cdb.g5_cdb.cmd = SC_SET_LIMITS;
1016 	scmd->cdb.g5_cdb.lun = scg_lun(scgp);
1017 	i_to_4_byte(&scmd->cdb.g5_cdb.addr[0], lba);
1018 	i_to_4_byte(&scmd->cdb.g5_cdb.count[0], length);
1019 
1020 	scgp->cmdname = "set limits";
1021 
1022 	return (scg_cmd(scgp));
1023 }
1024 
1025 /*
1026  * Set subcode for Teac Drives.
1027  */
1028 LOCAL int
set_subcode(scgp,subcode_data,length)1029 set_subcode(scgp, subcode_data, length)
1030 	SCSI	*scgp;
1031 	Uchar	*subcode_data;
1032 	int	length;
1033 {
1034 	register struct	scg_cmd	*scmd = scgp->scmd;
1035 
1036 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1037 	scmd->addr = (caddr_t)subcode_data;
1038 	scmd->size = length;
1039 	scmd->flags = SCG_DISRE_ENA;
1040 	scmd->cdb_len = SC_G1_CDBLEN;
1041 	scmd->sense_len = CCS_SENSE_LEN;
1042 
1043 	scmd->cdb.g1_cdb.cmd = SC_SET_SUBCODE;
1044 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1045 	g1_cdblen(&scmd->cdb.g1_cdb, length);
1046 
1047 	scgp->cmdname = "set subcode";
1048 
1049 	return (scg_cmd(scgp));
1050 }
1051 
1052 #ifdef	XDI
1053 LOCAL int
read_disk_info_teac(scgp,data,length,type)1054 read_disk_info_teac(scgp, data, length, type)
1055 	SCSI	*scgp;
1056 	Uchar	*data;
1057 	int	length;
1058 	int	type;
1059 {
1060 	register struct	scg_cmd	*scmd = scgp->scmd;
1061 
1062 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1063 	scmd->addr = (caddr_t)data;
1064 	scmd->size = length;
1065 	scmd->flags = SCG_RECV_DATA |SCG_DISRE_ENA;
1066 	scmd->cdb_len = SC_G1_CDBLEN;
1067 	scmd->sense_len = CCS_SENSE_LEN;
1068 
1069 	scmd->cdb.g1_cdb.cmd = SC_READ_DISK_INFO;
1070 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1071 
1072 	scmd->cdb.g1_cdb.reladr = type & 1;
1073 	scmd->cdb.g1_cdb.res    = (type & 2) >> 1;
1074 
1075 	scgp->cmdname = "read disk info teac";
1076 
1077 	return (scg_cmd(scgp));
1078 }
1079 #endif
1080 
1081 /*
1082  * Perform the freeze command for Teac Drives.
1083  */
1084 LOCAL int
teac_freeze(scgp,bp_flag)1085 teac_freeze(scgp, bp_flag)
1086 	SCSI	*scgp;
1087 	int	bp_flag;
1088 {
1089 	register struct	scg_cmd	*scmd = scgp->scmd;
1090 
1091 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1092 	scmd->addr = (caddr_t)0;
1093 	scmd->size = 0;
1094 	scmd->flags = SCG_DISRE_ENA;
1095 	scmd->cdb_len = SC_G5_CDBLEN;
1096 	scmd->sense_len = CCS_SENSE_LEN;
1097 	scmd->timeout = 8 * 60;		/* Needs up to 4 minutes */
1098 
1099 	scmd->cdb.g5_cdb.cmd = SC_FREEZE;
1100 	scmd->cdb.g5_cdb.lun = scg_lun(scgp);
1101 	scmd->cdb.g5_cdb.addr[3] = bp_flag ? 0x80 : 0;
1102 
1103 	scgp->cmdname = "teac_freeze";
1104 
1105 	return (scg_cmd(scgp));
1106 }
1107 
1108 LOCAL int
teac_wr_pma(scgp)1109 teac_wr_pma(scgp)
1110 	SCSI	*scgp;
1111 {
1112 	register struct	scg_cmd	*scmd = scgp->scmd;
1113 
1114 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1115 	scmd->addr = (caddr_t)0;
1116 	scmd->size = 0;
1117 	scmd->flags = SCG_DISRE_ENA;
1118 	scmd->cdb_len = SC_G5_CDBLEN;
1119 	scmd->sense_len = CCS_SENSE_LEN;
1120 
1121 	scmd->cdb.g5_cdb.cmd = SC_WRITE_PMA;
1122 	scmd->cdb.g5_cdb.lun = scg_lun(scgp);
1123 
1124 	scgp->cmdname = "teac_write_pma";
1125 
1126 	return (scg_cmd(scgp));
1127 }
1128 
1129 /*
1130  * Read PMA for Teac Drives.
1131  */
1132 LOCAL int
teac_rd_pma(scgp)1133 teac_rd_pma(scgp)
1134 	SCSI	*scgp;
1135 {
1136 	unsigned char	xx[256];
1137 	register struct	scg_cmd	*scmd = scgp->scmd;
1138 
1139 	fillbytes((caddr_t)xx, sizeof (xx), '\0');
1140 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1141 	scmd->addr = (caddr_t)xx;
1142 	scmd->size = sizeof (xx);
1143 	scmd->flags = SCG_RECV_DATA |SCG_DISRE_ENA;
1144 	scmd->cdb_len = SC_G1_CDBLEN;
1145 	scmd->sense_len = CCS_SENSE_LEN;
1146 
1147 	scmd->cdb.g1_cdb.cmd = SC_READ_PMA;
1148 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1149 
1150 	g1_cdblen(&scmd->cdb.g1_cdb, sizeof (xx));
1151 
1152 	scgp->cmdname = "teac_read_pma";
1153 
1154 /*	return (scg_cmd(scgp));*/
1155 	if (scg_cmd(scgp) < 0)
1156 		return (-1);
1157 
1158 	if (scgp->verbose) {
1159 		scg_prbytes(_("PMA Data"), xx, sizeof (xx) - scg_getresid(scgp));
1160 	}
1161 	if (lverbose) {
1162 		unsigned i;
1163 		Uchar	*p;
1164 
1165 		scg_prbytes(_("PMA Header: "), xx, 4);
1166 		i = xx[2];
1167 		p = &xx[4];
1168 		for (; i <= xx[3]; i++) {
1169 			scg_prbytes("PMA: ", p, 10);
1170 			p += 10;
1171 		}
1172 	}
1173 	return (0);
1174 }
1175 
1176 /*
1177  * Next writable address for Teac Drives.
1178  */
1179 LOCAL int
next_wr_addr_teac(scgp,start_lba,last_lba)1180 next_wr_addr_teac(scgp, start_lba, last_lba)
1181 	SCSI	*scgp;
1182 	long	start_lba;
1183 	long	last_lba;
1184 {
1185 	unsigned char	xx[256];
1186 	register struct	scg_cmd	*scmd = scgp->scmd;
1187 
1188 	fillbytes((caddr_t)xx, sizeof (xx), '\0');
1189 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1190 	scmd->addr = (caddr_t)xx;
1191 	scmd->size = sizeof (xx);
1192 	scmd->flags = SCG_RECV_DATA |SCG_DISRE_ENA;
1193 	scmd->cdb_len = SC_G5_CDBLEN;
1194 	scmd->sense_len = CCS_SENSE_LEN;
1195 
1196 	scmd->cdb.g5_cdb.cmd = SC_NEXT_WR_ADDRESS;
1197 	scmd->cdb.g5_cdb.lun = scg_lun(scgp);
1198 
1199 	i_to_4_byte(&scmd->cdb.g5_cdb.addr[0], start_lba);
1200 	i_to_4_byte(&scmd->cdb.g5_cdb.count[0], last_lba);
1201 
1202 	if (scgp->verbose)
1203 		printf(_("start lba: %ld last lba: %ld\n"),
1204 					start_lba, last_lba);
1205 
1206 	scgp->cmdname = "next writable address";
1207 
1208 /*	return (scg_cmd(scgp));*/
1209 	if (scg_cmd(scgp) < 0)
1210 		return (-1);
1211 
1212 	if (scgp->verbose) {
1213 		scg_prbytes(_("WRa Data"), xx, sizeof (xx) - scg_getresid(scgp));
1214 		printf(_("NWA: %ld\n"), a_to_4_byte(xx));
1215 	}
1216 	return (0);
1217 }
1218 
1219 LOCAL int
blank_jvc(scgp,dp,addr,blanktype)1220 blank_jvc(scgp, dp, addr, blanktype)
1221 	SCSI	*scgp;
1222 	cdr_t	*dp;
1223 	long	addr;
1224 	int	blanktype;
1225 {
1226 	extern	char	*blank_types[];
1227 
1228 	if (lverbose) {
1229 		printf(_("Blanking %s\n"), blank_types[blanktype & 0x07]);
1230 		flush();
1231 	}
1232 
1233 	return (scsi_blank(scgp, addr, blanktype, FALSE));
1234 }
1235 
1236 LOCAL int
buf_cap_teac(scgp,sp,fp)1237 buf_cap_teac(scgp, sp, fp)
1238 	SCSI	*scgp;
1239 	long	*sp;	/* Size pointer */
1240 	long	*fp;	/* Free pointer */
1241 {
1242 	Ulong	freespace;
1243 	Ulong	bufsize;
1244 	long	ret;
1245 	int	per;
1246 
1247 	ret = read_peak_buffer_cap_teac(scgp);
1248 	if (ret < 0)
1249 		return (-1);
1250 	bufsize = ret;
1251 	freespace = 0;
1252 	if (sp)
1253 		*sp = bufsize;
1254 	if (fp)
1255 		*fp = freespace;
1256 
1257 	if (scgp->verbose || (sp == 0 && fp == 0))
1258 		printf(_("BFree: %ld K BSize: %ld K\n"), freespace >> 10, bufsize >> 10);
1259 
1260 	if (bufsize == 0)
1261 		return (0);
1262 	per = (100 * (bufsize - freespace)) / bufsize;
1263 	if (per < 0)
1264 		return (0);
1265 	if (per > 100)
1266 		return (100);
1267 	return (per);
1268 }
1269 
1270 LOCAL long
read_peak_buffer_cap_teac(scgp)1271 read_peak_buffer_cap_teac(scgp)
1272 	SCSI	*scgp;
1273 {
1274 	Uchar	xx[4];
1275 	register struct	scg_cmd	*scmd = scgp->scmd;
1276 
1277 	fillbytes((caddr_t)xx, sizeof (xx), '\0');
1278 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1279 	scmd->addr = (caddr_t)xx;
1280 	scmd->size = sizeof (xx);
1281 	scmd->flags = SCG_RECV_DATA |SCG_DISRE_ENA;
1282 	scmd->cdb_len = SC_G5_CDBLEN;
1283 	scmd->sense_len = CCS_SENSE_LEN;
1284 
1285 	scmd->cdb.g5_cdb.cmd = SC_READ_PEAK_BUF_CAP;
1286 	scmd->cdb.g5_cdb.lun = scg_lun(scgp);
1287 
1288 	scgp->cmdname = "read peak buffer capacity";
1289 
1290 #define	BDEBUG
1291 #ifndef	BDEBUG
1292 	return (scg_cmd(scgp));
1293 #else
1294 	if (scg_cmd(scgp) < 0)
1295 		return (-1);
1296 
1297 	if (scgp->verbose) {
1298 		scg_prbytes(_("WRa Data"), xx, sizeof (xx) - scg_getresid(scgp));
1299 		printf(_("Buffer cap: %ld\n"), a_to_u_3_byte(&xx[1]));
1300 	}
1301 	return (a_to_u_3_byte(&xx[1]));
1302 /*	return (0);*/
1303 #endif
1304 }
1305 
1306 #define	BI_ONE_BYTE	0xC0
1307 #define	BI_448_BYTE	0x40
1308 #define	BI_APP_CODE	0x10
1309 
1310 #ifdef	XXBUFFER
1311 LOCAL int
buffer_inquiry_teac(scgp,fmt)1312 buffer_inquiry_teac(scgp, fmt)
1313 	SCSI	*scgp;
1314 	int	fmt;
1315 {
1316 	Uchar	xx[448];
1317 	register struct	scg_cmd	*scmd = scgp->scmd;
1318 
1319 	fillbytes((caddr_t)xx, sizeof (xx), '\0');
1320 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1321 	scmd->addr = (caddr_t)xx;
1322 	scmd->size = sizeof (xx);
1323 	scmd->size = 448;
1324 	scmd->flags = SCG_RECV_DATA |SCG_DISRE_ENA;
1325 	scmd->cdb_len = SC_G5_CDBLEN;
1326 	scmd->sense_len = CCS_SENSE_LEN;
1327 
1328 	scmd->cdb.g5_cdb.cmd = SC_BUFFER_INQUIRY;
1329 	scmd->cdb.g5_cdb.lun = scg_lun(scgp);
1330 
1331 	if (fmt > 0) {
1332 		scmd->cdb.g5_cdb.addr[3] = fmt;
1333 		if (fmt == BI_ONE_BYTE)
1334 			scmd->size = 1;
1335 	} else {
1336 		scmd->cdb.g5_cdb.addr[3] = BI_448_BYTE;
1337 /*		scmd->cdb.g5_cdb.addr[3] = BI_APP_CODE;*/
1338 	}
1339 
1340 	scgp->cmdname = "buffer inquiry";
1341 
1342 #define	BDEBUG
1343 #ifndef	BDEBUG
1344 	return (scg_cmd(scgp));
1345 #else
1346 	if (scg_cmd(scgp) < 0)
1347 		return (-1);
1348 
1349 	if (scgp->verbose) {
1350 /*		scg_prbytes("WRa Data", xx, sizeof (xx) - scg_getresid(scgp));*/
1351 /*		scg_prbytes("WRa Data", xx, 1);*/
1352 
1353 		if (fmt > 0) printf("fmt: %X ", fmt);
1354 		scg_prbytes(_("WRa Data"), xx, 9);
1355 		printf("%d\n", xx[8] - xx[1]);
1356 /*		printf("Buffer cap: %ld\n", a_to_u_3_byte(&xx[1]));*/
1357 	}
1358 	return (0);
1359 #endif
1360 }
1361 
1362 LOCAL void
check_buffer_teac(scgp)1363 check_buffer_teac(scgp)
1364 	SCSI	*scgp;
1365 {
1366 	printf("-------\n");
1367 	buffer_inquiry_teac(scgp, 0);
1368 #ifdef	SL
1369 	usleep(40000);
1370 	buffer_inquiry_teac(scgp, 0);
1371 #endif
1372 	read_peak_buffer_cap_teac(scgp);
1373 }
1374 #endif
1375 /*--------------------------------------------------------------------------*/
1376 #ifdef	XXDEBUG
1377 #include "scsimmc.h"
1378 
1379 LOCAL	int	g7_teac			__PR((SCSI *scgp));
1380 LOCAL	int	g6_teac			__PR((SCSI *scgp));
1381 
1382 LOCAL int
g7_teac(scgp)1383 g7_teac(scgp)
1384 	SCSI	*scgp;
1385 {
1386 	Uchar	xx[2048];
1387 	register struct	scg_cmd	*scmd = scgp->scmd;
1388 
1389 	fillbytes((caddr_t)xx, sizeof (xx), '\0');
1390 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1391 	scmd->addr = (caddr_t)xx;
1392 	scmd->size = sizeof (xx);
1393 	scmd->flags = SCG_RECV_DATA |SCG_DISRE_ENA;
1394 	scmd->cdb_len = SC_G5_CDBLEN;
1395 	scmd->sense_len = CCS_SENSE_LEN;
1396 
1397 	scmd->cdb.g5_cdb.cmd = 0xDF;
1398 /*	scmd->cdb.g5_cdb.cmd = 0xE5;*/
1399 	scmd->cdb.g5_cdb.lun = scg_lun(scgp);
1400 
1401 /*	scmd->cdb.g5_cdb.addr[3] = BI_ONE_BYTE;*/
1402 /*	scmd->size = 1;*/
1403 
1404 /*	scmd->cdb.g5_cdb.addr[3] = BI_448_BYTE;*/
1405 /*	scmd->cdb.g5_cdb.addr[3] = BI_APP_CODE;*/
1406 
1407 	scgp->cmdname = "g7 teac";
1408 
1409 /*	return (scg_cmd(scgp));*/
1410 	if (scg_cmd(scgp) < 0)
1411 		return (-1);
1412 
1413 /*	if (scgp->verbose) {*/
1414 		scg_prbytes(_("WRa Data"), xx, sizeof (xx) - scg_getresid(scgp));
1415 /*		scg_prbytes("WRa Data", xx, 1);*/
1416 /*		scg_prbytes("WRa Data", xx, 9);*/
1417 /*printf("%d\n", xx[8] - xx[1]);*/
1418 /*		printf("Buffer cap: %ld\n", a_to_u_3_byte(&xx[1]));*/
1419 /*	}*/
1420 	return (0);
1421 }
1422 
1423 LOCAL int
g6_teac(scgp)1424 g6_teac(scgp)
1425 	SCSI	*scgp;
1426 {
1427 	Uchar	xx[2048];
1428 	register struct	scg_cmd	*scmd = scgp->scmd;
1429 
1430 	fillbytes((caddr_t)xx, sizeof (xx), '\0');
1431 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1432 	scmd->addr = (caddr_t)xx;
1433 	scmd->size = sizeof (xx);
1434 	scmd->flags = SCG_RECV_DATA |SCG_DISRE_ENA;
1435 	scmd->cdb_len = SC_G1_CDBLEN;
1436 	scmd->sense_len = CCS_SENSE_LEN;
1437 
1438 	scmd->cdb.g1_cdb.cmd = 0xC1;
1439 	scmd->cdb.g1_cdb.cmd = 0xC3;
1440 	scmd->cdb.g1_cdb.cmd = 0xC6;
1441 	scmd->cdb.g1_cdb.cmd = 0xC7;	/* Read TOC */
1442 	scmd->cdb.g1_cdb.cmd = 0xCE;
1443 	scmd->cdb.g1_cdb.cmd = 0xCF;
1444 	scmd->cdb.g1_cdb.cmd = 0xC7;	/* Read TOC */
1445 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1446 
1447 	scgp->cmdname = "g6 teac";
1448 
1449 /*	return (scg_cmd(scgp));*/
1450 	if (scg_cmd(scgp) < 0)
1451 		return (-1);
1452 
1453 /*	if (scgp->verbose) {*/
1454 		scg_prbytes(_("WRa Data"), xx, sizeof (xx) - scg_getresid(scgp));
1455 /*		scg_prbytes("WRa Data", xx, 1);*/
1456 /*		scg_prbytes("WRa Data", xx, 9);*/
1457 /*printf("%d\n", xx[8] - xx[1]);*/
1458 /*		printf("Buffer cap: %ld\n", a_to_u_3_byte(&xx[1]));*/
1459 /*	}*/
1460 	return (0);
1461 }
1462 
1463 LOCAL void
xxtest_teac(scgp)1464 xxtest_teac(scgp)
1465 	SCSI	*scgp;
1466 {
1467 	read_peak_buffer_cap_teac(scgp);
1468 
1469 /*#define	XDI*/
1470 #ifdef	XDI
1471 	{
1472 		Uchar cbuf[512];
1473 
1474 /*		read_disk_info_teac(scgp, data, length, type)*/
1475 /*		read_disk_info_teac(scgp, cbuf, 512, 2);*/
1476 /*		read_disk_info_teac(scgp, cbuf, 512, 2);*/
1477 		read_disk_info_teac(scgp, cbuf, 512, 3);
1478 		scg_prbytes(_("DI Data"), cbuf, sizeof (cbuf) - scg_getresid(scgp));
1479 	}
1480 #endif	/* XDI */
1481 
1482 	buffer_inquiry_teac(scgp, -1);
1483 
1484 /*#define	XBU*/
1485 #ifdef	XBU
1486 	{
1487 		int i;
1488 
1489 		for (i = 0; i < 63; i++) {
1490 			scgp->silent++;
1491 			buffer_inquiry_teac(scgp, i<<2);
1492 			scgp->silent--;
1493 		}
1494 	}
1495 #endif	/* XBU */
1496 
1497 /*	printf("LLLL\n");*/
1498 /*	g7_teac(scgp);*/
1499 /*	g6_teac(scgp);*/
1500 }
1501 #endif	/* XXDEBUG */
1502