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