Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / wodim / drv_jvc.c
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 
301 teac_init(SCSI *usalp, cdr_t *dp)
302 {
303         return (speed_select_teac(usalp, dp, NULL));
304 }
305
306 static int 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 */