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