Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / wodim / drv_sony.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_sony.c       1.72 05/05/16 Copyright 1997-2005 J. Schilling */
14 /*
15  *      CDR device implementation for
16  *      Sony
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
35 /*#define       SONY_DEBUG*/
36
37 #include <mconfig.h>
38
39 #include <stdio.h>
40 #include <stdxlib.h>
41 #include <unixstd.h>    /* Include sys/types.h to make off_t available */
42 #include <standard.h>
43 #include <fctldefs.h>
44 #include <errno.h>
45 #include <strdefs.h>
46 #include <timedefs.h>
47
48 #include <utypes.h>
49 #include <btorder.h>
50 #include <intcvt.h>
51 #include <schily.h>
52
53 #include <usal/usalcmd.h>
54 #include <usal/scsidefs.h>
55 #include <usal/scsireg.h>
56 #include <usal/scsitransp.h>
57
58 #include "wodim.h"
59
60 #ifdef  SONY_DEBUG
61 #       define          inc_verbose()   usalp->verbose++
62 #       define          dec_verbose()   usalp->verbose--
63 #else
64 #       define          inc_verbose()
65 #       define          dec_verbose()
66 #endif
67
68 extern  int     debug;
69 extern  int     lverbose;
70
71 #if defined(_BIT_FIELDS_LTOH)   /* Intel byteorder */
72
73 struct sony_924_mode_page_20 {  /* mastering information */
74                 MP_P_CODE;              /* parsave & pagecode */
75         Uchar   p_len;                  /* 0x06 = 6 Bytes */
76         Uchar   subcode_header_off;
77         Ucbit   res3_0          : 1;
78         Ucbit   speudo          : 1;
79         Ucbit   res3_2          : 1;
80         Ucbit   c2po            : 1;
81         Ucbit   subcode_ecc     : 1;
82         Ucbit   res3_567        : 3;
83         Uchar   res_4;
84         Uchar   cue_sheet_opt;
85         Uchar   res[2];
86 };
87
88 #else                           /* Motorola byteorder */
89
90 struct sony_924_mode_page_20 {  /* mastering information */
91                 MP_P_CODE;              /* parsave & pagecode */
92         Uchar   p_len;                  /* 0x06 = 6 Bytes */
93         Uchar   subcode_header_off;
94         Ucbit   res3_567        : 3;
95         Ucbit   subcode_ecc     : 1;
96         Ucbit   c2po            : 1;
97         Ucbit   res3_2          : 1;
98         Ucbit   speudo          : 1;
99         Ucbit   res3_0          : 1;
100         Uchar   res_4;
101         Uchar   cue_sheet_opt;
102         Uchar   res[2];
103 };
104 #endif
105
106 struct sony_924_mode_page_22 {  /* disk information */
107                 MP_P_CODE;              /* parsave & pagecode */
108         Uchar   p_len;                  /* 0x1E = 30 Bytes */
109         Uchar   disk_style;
110         Uchar   disk_type;
111         Uchar   first_track;
112         Uchar   last_track;
113         Uchar   numsess;
114         Uchar   res_7;
115         Uchar   disk_appl_code[4];
116         Uchar   last_start_time[4];
117         Uchar   disk_status;
118         Uchar   num_valid_nra;
119         Uchar   track_info_track;
120         Uchar   post_gap;
121         Uchar   disk_id_code[4];
122         Uchar   lead_in_start[4];
123         Uchar   res[4];
124 };
125
126 struct sony_924_mode_page_23 {  /* track information */
127                 MP_P_CODE;              /* parsave & pagecode */
128         Uchar   p_len;                  /* 0x22 = 34 Bytes */
129         Uchar   res_2;
130         Uchar   track_num;
131         Uchar   data_form;
132         Uchar   write_method;
133         Uchar   session;
134         Uchar   track_status;
135         Uchar   start_lba[4];
136         Uchar   next_recordable_addr[4];
137         Uchar   blank_area_cap[4];
138         Uchar   fixed_packet_size[4];
139         Uchar   res_24;
140         Uchar   starting_msf[3];
141         Uchar   res_28;
142         Uchar   ending_msf[3];
143         Uchar   res_32;
144         Uchar   next_rec_time[3];
145 };
146
147 struct sony_924_mode_page_31 {  /* drive speed */
148                 MP_P_CODE;              /* parsave & pagecode */
149         Uchar   p_len;                  /* 0x02 = 2 Bytes */
150         Uchar   speed;
151         Uchar   res;
152 };
153
154 struct cdd_52x_mode_data {
155         struct scsi_mode_header header;
156         union cdd_pagex {
157                 struct sony_924_mode_page_20    page_s20;
158                 struct sony_924_mode_page_22    page_s22;
159                 struct sony_924_mode_page_23    page_s23;
160                 struct sony_924_mode_page_31    page_s31;
161         } pagex;
162 };
163
164 struct sony_write_parameter {
165         Uchar   res0;                   /* Reserved (must be zero)      */
166         Uchar   len;                    /* Parameter length 0x32 == 52  */
167         Uchar   res2;                   /* Reserved (must be zero)      */
168 #if defined(_BIT_FIELDS_LTOH)   /* Intel byteorder */
169         Ucbit   res3_05         : 6;    /* Reserved                     */
170         Ucbit   ms              : 2;    /* Multi session mode           */
171 #else                           /* Motorola byteorder */
172         Ucbit   ms              : 2;    /* Multi session mode           */
173         Ucbit   res3_05         : 6;    /* Reserved                     */
174 #endif
175         Uchar   resx[12];
176 #if defined(_BIT_FIELDS_LTOH)   /* Intel byteorder */
177         Ucbit   res16_06        : 7;    /* Reserved                     */
178         Ucbit   mcval           : 1;    /* MCN valid                    */
179 #else                           /* Motorola byteorder */
180         Ucbit   mcval           : 1;    /* MCN valid                    */
181         Ucbit   res16_06        : 7;    /* Reserved                     */
182 #endif
183         Uchar   mcn[15];
184 #if defined(_BIT_FIELDS_LTOH)   /* Intel byteorder */
185         Ucbit   res32_06        : 7;    /* Reserved                     */
186         Ucbit   icval           : 1;    /* ISRC valid                   */
187 #else                           /* Motorola byteorder */
188         Ucbit   icval           : 1;    /* ISRC valid                   */
189         Ucbit   res32_06        : 7;    /* Reserved                     */
190 #endif
191         Uchar   isrc[15];
192         Uchar   subheader[4];
193 };
194
195 struct sony_cue {
196         Uchar   cs_ctladr;              /* CTL/ADR for this track       */
197         Uchar   cs_tno;                 /* This track number            */
198         Uchar   cs_index;               /* Index within this track      */
199         Uchar   cs_dataform;            /* Data form                    */
200                                         /* Bit 0..5 Main channel Format */
201                                         /* Bit 6..7 SubChannel format   */
202         Uchar   cs_zero;                /* Reserved or MCN/ISRC         */
203         Uchar   cs_min;                 /* Absolute time minutes        */
204         Uchar   cs_sec;                 /* Absolute time seconds        */
205         Uchar   cs_frame;               /* Absolute time frames         */
206 };
207
208
209 #define strbeg(s1, s2)  (strstr((s2), (s1)) == (s2))
210
211 static  int     write_start_sony(SCSI *usalp, caddr_t bp, int size);
212 static  int     write_continue_sony(SCSI *usalp, caddr_t bp, long sectaddr, 
213                                                                                           long size, int blocks, BOOL islast);
214 static  int     discontinue_sony(SCSI *usalp);
215 static  int     write_track_sony(SCSI *usalp, long track, int sectype);
216 static  int     close_track_sony(SCSI *usalp, cdr_t *dp, track_t *trackp);
217 static  int     flush_sony(SCSI *usalp, int track);
218 static  int     finalize_sony(SCSI *usalp, cdr_t *dp, track_t *trackp);
219 static  int     recover_sony(SCSI *usalp, cdr_t *dp, int track);
220 static  int     set_wr_parameter_sony(SCSI *usalp, caddr_t bp, int size);
221 static  int     next_wr_addr_sony(SCSI *usalp, track_t *trackp, long *ap);
222 static  int     reserve_track_sony(SCSI *usalp, unsigned long len);
223 static  int     init_sony(SCSI *usalp, cdr_t *dp);
224 static  int     getdisktype_sony(SCSI *usalp, cdr_t *dp);
225 static  void    di_to_dstat_sony(struct sony_924_mode_page_22 *dip, 
226                                                                                   dstat_t *dsp);
227 static  int     speed_select_sony(SCSI *usalp, cdr_t *dp, int *speedp);
228 static  int     next_writable_address_sony(SCSI *usalp, long *ap, int track, 
229                                                                                                                 int sectype, int tracktype);
230 static  int     new_track_sony(SCSI *usalp, int track, int sectype, 
231                                                                                 int tracktype);
232 static  int     open_track_sony(SCSI *usalp, cdr_t *dp, track_t *trackp);
233 static  int     open_session_sony(SCSI *usalp, cdr_t *dp, track_t *trackp);
234 static  int     abort_session_sony(SCSI *usalp, cdr_t *dp);
235 static  int     get_page22_sony(SCSI *usalp, char *mode);
236 static  int     gen_cue_sony(track_t *trackp, void *vcuep, BOOL needgap);
237 static  void    fillcue(struct sony_cue *cp, int ca, int tno, int idx, int dataform, int scms, msf_t *mp);
238 static  int     send_cue_sony(SCSI *usalp, cdr_t *dp, track_t *trackp);
239 static  int     write_leadin_sony(SCSI *usalp, cdr_t *dp, track_t *trackp);
240 static  int     sony_attach(SCSI *usalp, cdr_t *dp);
241 #ifdef  SONY_DEBUG
242 static  void    print_sony_mp22(struct sony_924_mode_page_22 *xp, int len);
243 static  void    print_sony_mp23(struct sony_924_mode_page_23 *xp, int len);
244 #endif
245 static  int     buf_cap_sony(SCSI *usalp, long *, long *);
246
247 cdr_t   cdr_sony_cdu924 = {
248         0, 0,
249         CDR_TAO|CDR_SAO|CDR_CADDYLOAD|CDR_SWABAUDIO,
250         CDR_CDRW_NONE,
251         2, 4,
252         "sony_cdu924",
253         "driver for Sony CDU-924 / CDU-948",
254         0,
255         (dstat_t *)0,
256         drive_identify,
257         sony_attach,
258         init_sony,
259         getdisktype_sony,
260         scsi_load,
261         scsi_unload,
262         buf_cap_sony,
263         cmd_dummy,                                      /* recovery_needed */
264         recover_sony,
265         speed_select_sony,
266         select_secsize,
267         next_wr_addr_sony,
268         reserve_track_sony,
269         write_continue_sony,
270         gen_cue_sony,
271         send_cue_sony,
272         write_leadin_sony,
273         open_track_sony,
274         close_track_sony,
275         open_session_sony,
276         cmd_dummy,
277         abort_session_sony,
278         read_session_offset_philips,
279         finalize_sony,
280         cmd_dummy,                                      /* stats        */
281         blank_dummy,
282         format_dummy,
283         (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
284         cmd_dummy,                                      /* opt1         */
285         cmd_dummy,                                      /* opt2         */
286 };
287
288 static int
289 write_start_sony(SCSI *usalp, caddr_t bp, int size)
290 {
291         register struct usal_cmd        *scmd = usalp->scmd;
292
293         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
294         scmd->addr = bp;
295         scmd->size = size;
296         scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
297         scmd->cdb_len = SC_G1_CDBLEN;
298         scmd->sense_len = CCS_SENSE_LEN;
299         scmd->sense_len = 26;
300         scmd->cdb.g1_cdb.cmd = 0xE0;
301         scmd->cdb.g1_cdb.lun = usal_lun(usalp);
302         g0_cdbaddr(&scmd->cdb.g0_cdb, size); /* Hack, but Sony is silly */
303
304         usalp->cmdname = "write_start";
305
306         if (usal_cmd(usalp) < 0)
307                 return (-1);
308         return (0);
309 }
310
311 static int
312 write_continue_sony(SCSI *usalp, 
313                     caddr_t bp      /* address of buffer */, 
314                     long sectaddr   /* disk address (sector) to put */, 
315                     long size       /* number of bytes to transfer */, 
316                     int blocks      /* sector count */, 
317                     BOOL islast     /* last write for track */)
318 {
319         register struct usal_cmd        *scmd = usalp->scmd;
320
321         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
322         scmd->addr = bp;
323         scmd->size = size;
324         scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
325         scmd->cdb_len = SC_G1_CDBLEN;
326         scmd->sense_len = CCS_SENSE_LEN;
327         scmd->cdb.g1_cdb.cmd = 0xE1;
328         scmd->cdb.g1_cdb.lun = usal_lun(usalp);
329         g0_cdbaddr(&scmd->cdb.g0_cdb, size); /* Hack, but Sony is silly */
330
331         usalp->cmdname = "write_continue";
332
333         if (usal_cmd(usalp) < 0) {
334                 /*
335                  * XXX This seems to happen only sometimes.
336                  */
337                 if (usal_sense_code(usalp) != 0x80)
338                         return (-1);
339         }
340         return (size - usal_getresid(usalp));
341 }
342
343 static int
344 discontinue_sony(SCSI *usalp)
345 {
346         register struct usal_cmd        *scmd = usalp->scmd;
347
348         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
349         scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
350         scmd->cdb_len = SC_G1_CDBLEN;
351         scmd->sense_len = CCS_SENSE_LEN;
352         scmd->cdb.g1_cdb.cmd = 0xE2;
353         scmd->cdb.g1_cdb.lun = usal_lun(usalp);
354
355         usalp->cmdname = "discontinue";
356
357         if (usal_cmd(usalp) < 0)
358                 return (-1);
359         return (0);
360 }
361
362 static int
363 write_track_sony(SCSI *usalp, 
364                  long track     /* track number 0 == new track */, 
365                  int sectype    /* no sectype for Sony write track */)
366 {
367         register struct usal_cmd        *scmd = usalp->scmd;
368
369         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
370         scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
371         scmd->cdb_len = SC_G1_CDBLEN;
372         scmd->sense_len = CCS_SENSE_LEN;
373         scmd->cdb.g1_cdb.cmd = 0xF5;
374         scmd->cdb.g1_cdb.lun = usal_lun(usalp);
375         g1_cdbaddr(&scmd->cdb.g1_cdb, track);
376
377         usalp->cmdname = "write_track";
378
379         if (usal_cmd(usalp) < 0)
380                 return (-1);
381         return (0);
382 }
383
384 /* XXX NOCH NICHT FERTIG */
385 static int
386 close_track_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
387 {
388         register struct usal_cmd        *scmd = usalp->scmd;
389         int     track = 0;
390
391         if (!is_tao(trackp) && !is_packet(trackp))
392                 return (0);
393
394         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
395         scmd->flags = SCG_DISRE_ENA;
396         scmd->cdb_len = SC_G1_CDBLEN;
397         scmd->sense_len = CCS_SENSE_LEN;
398         scmd->cdb.g1_cdb.cmd = 0xF0;
399         scmd->cdb.g1_cdb.lun = usal_lun(usalp);
400         g1_cdbaddr(&scmd->cdb.g1_cdb, track);
401 /* XXX Padding ??? (bit 0 in addr[0] / CDB[2]) */
402
403         usalp->cmdname = "close_track";
404
405         if (usal_cmd(usalp) < 0)
406                 return (-1);
407
408         /*
409          * Clear the silly "error situation" from Sony´ dummy write end
410          * but notify if real errors occurred.
411          */
412         usalp->silent++;
413         if (test_unit_ready(usalp) < 0 && usal_sense_code(usalp) != 0xD4) {
414                 usalp->cmdname = "close_track/test_unit_ready";
415                 usal_printerr(usalp);
416         }
417         usalp->silent--;
418
419         return (0);
420 }
421
422 static int
423 finalize_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
424 {
425         register struct usal_cmd        *scmd = usalp->scmd;
426         int     dummy = track_base(trackp)->tracktype & TOCF_DUMMY;
427
428         if (!is_tao(trackp) && !is_packet(trackp)) {
429                 wait_unit_ready(usalp, 240);
430                 return (0);
431         }
432         if (dummy) {
433                 printf("Fixating is not possible in dummy write mode.\n");
434                 return (0);
435         }
436         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
437         scmd->flags = SCG_DISRE_ENA;
438         scmd->cdb_len = SC_G1_CDBLEN;
439         scmd->sense_len = CCS_SENSE_LEN;
440         scmd->timeout = 8 * 60;         /* Needs up to 4 minutes */
441         scmd->cdb.g1_cdb.cmd = 0xF1;
442         scmd->cdb.g1_cdb.lun = usal_lun(usalp);
443         scmd->cdb.g1_cdb.count[1] = ((track_base(trackp)->tracktype & TOCF_MULTI) ? 1 : 0);
444 /* XXX Padding ??? (bit 0 in addr[0] / CDB[2]) */
445
446         usalp->cmdname = "finalize";
447
448         if (usal_cmd(usalp) < 0)
449                 return (-1);
450         return (0);
451 }
452
453 static int
454 flush_sony(SCSI *usalp, int track)
455 {
456         register struct usal_cmd        *scmd = usalp->scmd;
457
458         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
459         scmd->flags = SCG_DISRE_ENA;
460         scmd->cdb_len = SC_G1_CDBLEN;
461         scmd->sense_len = CCS_SENSE_LEN;
462         scmd->timeout = 8 * 60;         /* Needs up to 4 minutes */
463         scmd->cdb.g1_cdb.cmd = 0xF2;
464         scmd->cdb.g1_cdb.lun = usal_lun(usalp);
465         scmd->cdb.cmd_cdb[5] = track;
466 /* XXX POE ???     (bit 1 in addr[0] / CDB[2]) */
467 /* XXX Padding ??? (bit 0 in addr[0] / CDB[2]) */
468 /* XXX Partial flush ??? (CDB[3]) */
469
470         usalp->cmdname = "flush";
471
472         if (usal_cmd(usalp) < 0)
473                 return (-1);
474         return (0);
475 }
476
477 static int
478 recover_sony(SCSI *usalp, cdr_t *dp, int track)
479 {
480         register struct usal_cmd        *scmd = usalp->scmd;
481
482         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
483         scmd->flags = SCG_DISRE_ENA;
484         scmd->cdb_len = SC_G1_CDBLEN;
485         scmd->sense_len = CCS_SENSE_LEN;
486         scmd->cdb.g1_cdb.cmd = 0xF6;
487         scmd->cdb.g1_cdb.lun = usal_lun(usalp);
488         scmd->cdb.g1_cdb.addr[3] = track;
489
490         usalp->cmdname = "recover";
491
492         if (usal_cmd(usalp) < 0)
493                 return (-1);
494         return (0);
495 }
496
497 static int
498 set_wr_parameter_sony(SCSI *usalp, caddr_t bp, int size)
499 {
500         register struct usal_cmd        *scmd = usalp->scmd;
501
502         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
503         scmd->addr = bp;
504         scmd->size = size;
505         scmd->flags = SCG_DISRE_ENA;
506         scmd->cdb_len = SC_G1_CDBLEN;
507         scmd->sense_len = CCS_SENSE_LEN;
508         scmd->cdb.g1_cdb.cmd = 0xF8;
509         scmd->cdb.g1_cdb.lun = usal_lun(usalp);
510         g1_cdblen(&scmd->cdb.g1_cdb, size);
511
512         usalp->cmdname = "set_write_parameter";
513
514         if (usal_cmd(usalp) < 0)
515                 return (-1);
516         return (0);
517 }
518
519 static int
520 next_wr_addr_sony(SCSI *usalp, track_t *trackp, long *ap)
521 {
522         if (next_writable_address_sony(usalp, ap, 0, 0, 0) < 0)
523                 return (-1);
524         return (0);
525 }
526
527 static int
528 reserve_track_sony(SCSI *usalp, unsigned long len)
529 {
530         register struct usal_cmd        *scmd = usalp->scmd;
531
532         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
533         scmd->flags = SCG_DISRE_ENA;
534         scmd->cdb_len = SC_G1_CDBLEN;
535         scmd->sense_len = CCS_SENSE_LEN;
536         scmd->cdb.g1_cdb.cmd = 0xF3;
537         scmd->cdb.g1_cdb.lun = usal_lun(usalp);
538         i_to_4_byte(&scmd->cdb.g1_cdb.addr[3], len);
539
540         usalp->cmdname = "reserve_track";
541
542         if (usal_cmd(usalp) < 0)
543                 return (-1);
544         return (0);
545 }
546
547 static int
548 init_sony(SCSI *usalp, cdr_t *dp)
549 {
550         return (speed_select_sony(usalp, dp, NULL));
551 }
552
553
554 #define IS(what, flag)  printf("  Is %s%s\n", flag?"":"not ", what);
555
556 static int
557 getdisktype_sony(SCSI *usalp, cdr_t *dp)
558 {
559         dstat_t *dsp = dp->cdr_dstat;
560         long    dummy;
561         long    lst;
562         msf_t   msf;
563
564         char                    mode[256];
565         struct scsi_mode_page_header    *mp;
566         struct sony_924_mode_page_22    *xp;
567
568         dummy = get_page22_sony(usalp, mode);
569         if (dummy >= 0) {
570                 mp = (struct scsi_mode_page_header *)
571                         (mode + sizeof (struct scsi_mode_header) +
572                         ((struct scsi_mode_header *)mode)->blockdesc_len);
573
574                 xp = (struct sony_924_mode_page_22 *)mp;
575
576                 if (xp->disk_appl_code[0] == 0xFF)
577                         dummy = -1;
578         } else {
579                 return (drive_getdisktype(usalp, dp));
580         }
581
582         if ((dp->cdr_dstat->ds_cdrflags & RF_PRATIP) != 0 && dummy >= 0) {
583
584                 printf("ATIP info from disk:\n");
585                 printf("  Indicated writing power: %d\n",
586                                 (unsigned)(xp->disk_appl_code[1] & 0x70) >> 4);
587                 IS("unrestricted", xp->disk_appl_code[2] & 0x40);
588                 printf("  Disk application code: %d\n", xp->disk_appl_code[2] & 0x3F);
589                 msf.msf_min = xp->lead_in_start[1];
590                 msf.msf_sec = xp->lead_in_start[2];
591                 msf.msf_frame = xp->lead_in_start[3];
592                 lst = msf_to_lba(msf.msf_min, msf.msf_sec, msf.msf_frame, FALSE);
593                 if (lst  < -150) {
594                         /*
595                          * The Sony CDU 920 seems to deliver 00:00/00 for
596                          * lead-in start time, dont use it.
597                          */
598                         printf("  ATIP start of lead in:  %ld (%02d:%02d/%02d)\n",
599                                 msf_to_lba(msf.msf_min, msf.msf_sec, msf.msf_frame, FALSE),
600                                 msf.msf_min, msf.msf_sec, msf.msf_frame);
601                 }
602                 msf.msf_min = xp->last_start_time[1];
603                 msf.msf_sec = xp->last_start_time[2];
604                 msf.msf_frame = xp->last_start_time[3];
605                 printf("  ATIP start of lead out: %ld (%02d:%02d/%02d)\n",
606                         msf_to_lba(msf.msf_min, msf.msf_sec, msf.msf_frame, TRUE),
607                         msf.msf_min, msf.msf_sec, msf.msf_frame);
608                 if (lst  < -150) {
609                         /*
610                          * The Sony CDU 920 seems to deliver 00:00/00 for
611                          * lead-in start time, dont use it.
612                          */
613                         msf.msf_min = xp->lead_in_start[1];
614                         msf.msf_sec = xp->lead_in_start[2];
615                         msf.msf_frame = xp->lead_in_start[3];
616                         pr_manufacturer(&msf,
617                                         FALSE,  /* Always not erasable */
618                                         (xp->disk_appl_code[2] & 0x40) != 0);
619                 }
620         }
621         if (dummy >= 0)
622                 di_to_dstat_sony(xp, dsp);
623         return (drive_getdisktype(usalp, dp));
624 }
625
626 static void
627 di_to_dstat_sony(struct sony_924_mode_page_22 *dip, dstat_t *dsp)
628 {
629         msf_t   msf;
630
631         dsp->ds_diskid = a_to_u_4_byte(dip->disk_id_code);
632 #ifdef  PROTOTYPES
633         if (dsp->ds_diskid != 0xFFFFFFFFUL)
634 #else
635         if (dsp->ds_diskid != (Ulong)0xFFFFFFFF)
636 #endif
637                 dsp->ds_flags |= DSF_DID_V;
638         dsp->ds_diskstat = (dip->disk_status >> 6) & 0x03;
639 #ifdef  XXX
640         /*
641          * There seems to be no MMC equivalent...
642          */
643         dsp->ds_sessstat = dip->sess_status;
644 #endif
645
646         dsp->ds_maxblocks = msf_to_lba(dip->last_start_time[1],
647                                         dip->last_start_time[2],
648                                         dip->last_start_time[3], TRUE);
649         /*
650          * Check for 0xFF:0xFF/0xFF which is an indicator for a complete disk
651          */
652         if (dsp->ds_maxblocks == 716730)
653                 dsp->ds_maxblocks = -1L;
654
655         if (dsp->ds_first_leadin == 0) {
656                 dsp->ds_first_leadin = msf_to_lba(dip->lead_in_start[1],
657                                                 dip->lead_in_start[2],
658                                                 dip->lead_in_start[3], FALSE);
659                 /*
660                  * Check for illegal values (> 0)
661                  * or for empty field (-150) with CDU-920.
662                  */
663                 if (dsp->ds_first_leadin > 0 || dsp->ds_first_leadin == -150)
664                         dsp->ds_first_leadin = 0;
665         }
666
667         if (dsp->ds_last_leadout == 0 && dsp->ds_maxblocks >= 0)
668                 dsp->ds_last_leadout = dsp->ds_maxblocks;
669
670         msf.msf_min = dip->lead_in_start[1];
671         msf.msf_sec = dip->lead_in_start[2];
672         msf.msf_frame = dip->lead_in_start[3];
673         dsp->ds_maxrblocks = disk_rcap(&msf, dsp->ds_maxblocks,
674                                         FALSE,  /* Always not erasable */
675                                         (dip->disk_appl_code[2] & 0x40) != 0);
676 }
677
678
679 int     sony_speeds[] = {
680                 -1,             /* Speed null is not allowed */
681                 0,              /* Single speed */
682                 1,              /* Double speed */
683                 -1,             /* Three times */
684                 3,              /* Quad speed */
685 };
686
687 static int
688 speed_select_sony(SCSI *usalp, cdr_t *dp, int *speedp)
689 {
690         struct cdd_52x_mode_data md;
691         int     count;
692         int     err;
693         int     speed = 1;
694         BOOL    dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
695
696         if (speedp) {
697                 speed = *speedp;
698                 if (speed < 1 || speed > 4 || sony_speeds[speed] < 0)
699                         return (-1);
700         }
701
702         fillbytes((caddr_t)&md, sizeof (md), '\0');
703
704         count  = sizeof (struct scsi_mode_header) +
705                 sizeof (struct sony_924_mode_page_20);
706
707         md.pagex.page_s20.p_code = 0x20;
708         md.pagex.page_s20.p_len =  0x06;
709         md.pagex.page_s20.speudo = dummy?1:0;
710
711         /*
712          * Set Cue sheet option. This is documented for the 924 and
713          * seems to be supported for the 948 too.
714          */
715         md.pagex.page_s20.cue_sheet_opt = 0x03;
716
717         err = mode_select(usalp, (Uchar *)&md, count, 0, 1);
718         if (err < 0)
719                 return (err);
720
721         if (speedp == 0)
722                 return (0);
723
724         fillbytes((caddr_t)&md, sizeof (md), '\0');
725
726         count  = sizeof (struct scsi_mode_header) +
727                 sizeof (struct sony_924_mode_page_31);
728
729         md.pagex.page_s31.p_code = 0x31;
730         md.pagex.page_s31.p_len =  0x02;
731         md.pagex.page_s31.speed = sony_speeds[speed];
732
733         return (mode_select(usalp, (Uchar *)&md, count, 0, 1));
734 }
735
736 static int
737 next_writable_address_sony(SCSI *usalp, long *ap, int track, int sectype, 
738                            int tracktype)
739 {
740         struct  scsi_mode_page_header *mp;
741         char                    mode[256];
742         int                     len = 0x30;
743         int                     page = 0x23;
744         struct sony_924_mode_page_23    *xp;
745
746         fillbytes((caddr_t)mode, sizeof (mode), '\0');
747
748         inc_verbose();
749         if (!get_mode_params(usalp, page, "CD track information",
750                         (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
751                 dec_verbose();
752                 return (-1);
753         }
754         dec_verbose();
755         if (len == 0)
756                 return (-1);
757
758         mp = (struct scsi_mode_page_header *)
759                 (mode + sizeof (struct scsi_mode_header) +
760                 ((struct scsi_mode_header *)mode)->blockdesc_len);
761
762
763         xp = (struct sony_924_mode_page_23 *)mp;
764
765 #ifdef  SONY_DEBUG
766         print_sony_mp23(xp, len);
767 #endif
768         if (ap)
769                 *ap = a_to_4_byte(xp->next_recordable_addr);
770         return (0);
771 }
772
773
774 static int
775 new_track_sony(SCSI *usalp, int track, int sectype, int tracktype)
776 {
777         struct  scsi_mode_page_header *mp;
778         char                    mode[256];
779         int                     len = 0x30;
780         int                     page = 0x23;
781         struct sony_924_mode_page_23    *xp;
782         int     i;
783
784         fillbytes((caddr_t)mode, sizeof (mode), '\0');
785         get_page22_sony(usalp, mode);
786
787         fillbytes((caddr_t)mode, sizeof (mode), '\0');
788
789         inc_verbose();
790         if (!get_mode_params(usalp, page, "CD track information",
791                         (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
792                 dec_verbose();
793                 return (-1);
794         }
795         dec_verbose();
796         if (len == 0)
797                 return (-1);
798
799         mp = (struct scsi_mode_page_header *)
800                 (mode + sizeof (struct scsi_mode_header) +
801                 ((struct scsi_mode_header *)mode)->blockdesc_len);
802
803
804         xp = (struct sony_924_mode_page_23 *)mp;
805
806 #ifdef  SONY_DEBUG
807         print_sony_mp23(xp, len);
808 #endif
809
810         xp->write_method = 0;   /* Track at one recording */
811
812         if (sectype & ST_AUDIOMASK) {
813                 xp->data_form = (sectype & ST_MASK) == ST_AUDIO_PRE ? 0x02 : 0x00;
814         } else {
815                 if (tracktype == TOC_ROM) {
816                         xp->data_form = (sectype & ST_MASK) == ST_ROM_MODE1 ? 0x10 : 0x11;
817                 } else if (tracktype == TOC_XA1) {
818                         xp->data_form = 0x12;
819                 } else if (tracktype == TOC_XA2) {
820                         xp->data_form = 0x12;
821                 } else if (tracktype == TOC_CDI) {
822                         xp->data_form = 0x12;
823                 }
824         }
825
826         ((struct scsi_modesel_header *)mode)->sense_data_len    = 0;
827         ((struct scsi_modesel_header *)mode)->res2              = 0;
828
829         i = ((struct scsi_mode_header *)mode)->blockdesc_len;
830         if (i > 0) {
831                 i_to_3_byte(
832                         ((struct scsi_mode_data *)mode)->blockdesc.nlblock,
833                                                                 0);
834         }
835
836         if (mode_select(usalp, (Uchar *)mode, len, 0, usalp->inq->data_format >= 2) < 0) {
837                 return (-1);
838         }
839
840         return (0);
841 }
842
843 static int
844 open_track_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
845 {
846         if (!is_tao(trackp) && !is_packet(trackp)) {
847                 if (trackp->pregapsize > 0 && (trackp->flags & TI_PREGAP) == 0) {
848                         if (lverbose) {
849                                 printf("Writing pregap for track %d at %ld\n",
850                                         (int)trackp->trackno,
851                                         trackp->trackstart-trackp->pregapsize);
852                         }
853                         /*
854                          * XXX Do we need to check isecsize too?
855                          */
856                         pad_track(usalp, dp, trackp,
857                                 trackp->trackstart-trackp->pregapsize,
858                                 (Llong)trackp->pregapsize*trackp->secsize,
859                                         FALSE, 0);
860                 }
861                 return (0);
862         }
863
864         if (select_secsize(usalp, trackp->secsize) < 0)
865                 return (-1);
866
867         if (new_track_sony(usalp, trackp->trackno, trackp->sectype, trackp->tracktype & TOC_MASK) < 0)
868                 return (-1);
869
870         if (write_track_sony(usalp, 0L, trackp->sectype) < 0)
871                 return (-1);
872
873         return (0);
874 }
875
876 static int
877 open_session_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
878 {
879         struct  scsi_mode_page_header *mp;
880         char                    mode[256];
881         int     i;
882         int     len = 0x30;
883         struct sony_924_mode_page_22    *xp;
884
885         fillbytes((caddr_t)mode, sizeof (mode), '\0');
886
887         if ((len = get_page22_sony(usalp, mode)) < 0)
888                 return (-1);
889
890         mp = (struct scsi_mode_page_header *)
891                 (mode + sizeof (struct scsi_mode_header) +
892                 ((struct scsi_mode_header *)mode)->blockdesc_len);
893
894         xp = (struct sony_924_mode_page_22 *)mp;
895
896         xp->disk_type = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
897
898         if (is_tao(track_base(trackp))) {
899 #ifdef  __needed__
900                 if ((track_base(trackp)->tracktype & TOC_MASK) == TOC_DA)
901                         xp->disk_style = 0x80;
902                 else
903                         xp->disk_style = 0xC0;
904 #endif
905         } else if (is_sao(track_base(trackp))) {
906                 /*
907                  * We may only change this value if the disk is empty.
908                  * i.e. when disk_status & 0xC0 == 0x00
909                  */
910                 if ((xp->disk_status & 0xC0) != 0) {
911                         if (xp->disk_style != 0x00)
912                                 errmsgno(EX_BAD, "Cannot change disk stile for recorded disk.\n");
913                 }
914                 xp->disk_style = 0x00;
915         }
916
917         ((struct scsi_modesel_header *)mode)->sense_data_len    = 0;
918         ((struct scsi_modesel_header *)mode)->res2              = 0;
919
920         i = ((struct scsi_mode_header *)mode)->blockdesc_len;
921         if (i > 0) {
922                 i_to_3_byte(
923                         ((struct scsi_mode_data *)mode)->blockdesc.nlblock,
924                                                                 0);
925         }
926
927         if (mode_select(usalp, (Uchar *)mode, len, 0, usalp->inq->data_format >= 2) < 0) {
928                 return (-1);
929         }
930 /*
931  * XXX set write parameter für SAO mit Multi Session (948 only?)
932  * XXX set_wr_parameter_sony(usalp, bp, size);
933  */
934         return (0);
935 }
936
937 static int
938 abort_session_sony(SCSI *usalp, cdr_t *dp)
939 {
940         return (discontinue_sony(usalp));
941 }
942
943 static int
944 get_page22_sony(SCSI *usalp, char *mode)
945 {
946         struct  scsi_mode_page_header *mp;
947         int     len = 0x30;
948         int     page = 0x22;
949         struct sony_924_mode_page_22    *xp;
950
951         fillbytes((caddr_t)mode, sizeof (mode), '\0');
952
953         inc_verbose();
954         if (!get_mode_params(usalp, page, "CD disk information",
955                         (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
956                 dec_verbose();
957                 return (-1);
958         }
959         dec_verbose();
960         if (len == 0)
961                 return (-1);
962
963         mp = (struct scsi_mode_page_header *)
964                 (mode + sizeof (struct scsi_mode_header) +
965                 ((struct scsi_mode_header *)mode)->blockdesc_len);
966
967         xp = (struct sony_924_mode_page_22 *)mp;
968
969 #ifdef  SONY_DEBUG
970         print_sony_mp22(xp, len);
971 #endif
972         return (len);
973 }
974
975 /*--------------------------------------------------------------------------*/
976
977 static Uchar    db2df[] = {
978         0x01,                   /*  0 2352 bytes of raw data                    */
979         0xFF,                   /*  1 2368 bytes (raw data + P/Q Subchannel)    */
980         0xFF,                   /*  2 2448 bytes (raw data + P-W Subchannel)    */
981         0xFF,                   /*  3 2448 bytes (raw data + P-W raw Subchannel)*/
982         0xFF,                   /*  4 -    Reserved                             */
983         0xFF,                   /*  5 -    Reserved                             */
984         0xFF,                   /*  6 -    Reserved                             */
985         0xFF,                   /*  7 -    Vendor specific                      */
986         0x11,                   /*  8 2048 bytes Mode 1 (ISO/IEC 10149)         */
987         0xFF,                   /*  9 2336 bytes Mode 2 (ISO/IEC 10149)         */
988         0xFF,                   /* 10 2048 bytes Mode 2! (CD-ROM XA form 1)     */
989         0xFF,                   /* 11 2056 bytes Mode 2 (CD-ROM XA form 1)      */
990         0xFF,                   /* 12 2324 bytes Mode 2 (CD-ROM XA form 2)      */
991         0xFF,                   /* 13 2332 bytes Mode 2 (CD-ROM XA 1/2+subhdr)  */
992         0xFF,                   /* 14 -    Reserved                             */
993         0xFF,                   /* 15 -    Vendor specific                      */
994 };
995
996 static int
997 gen_cue_sony(track_t *trackp, void *vcuep, BOOL needgap)
998 {
999         int     tracks = trackp->tracks;
1000         int     i;
1001         struct sony_cue **cuep = vcuep;
1002         struct sony_cue *cue;
1003         struct sony_cue *cp;
1004         int     ncue = 0;
1005         int     icue = 0;
1006         int     pgsize;
1007         msf_t   m;
1008         int     ctl;
1009         int     df;
1010         int     scms;
1011
1012         cue = malloc(1);
1013
1014         for (i = 0; i <= tracks; i++) {
1015                 ctl = (st2mode[trackp[i].sectype & ST_MASK]) << 4;
1016                 if (is_copy(&trackp[i]))
1017                         ctl |= TM_ALLOW_COPY << 4;
1018                 df = db2df[trackp[i].dbtype & 0x0F];
1019
1020 #ifdef  __supported__
1021                 if (trackp[i].isrc) {   /* MCN or ISRC */
1022                         ncue += 2;
1023                         cue = realloc(cue, ncue * sizeof (*cue));
1024                         cp = &cue[icue++];
1025                         if (i == 0) {
1026                                 cp->cs_ctladr = 0x02;
1027                                 movebytes(&trackp[i].isrc[0], &cp->cs_tno, 7);
1028                                 cp = &cue[icue++];
1029                                 cp->cs_ctladr = 0x02;
1030                                 movebytes(&trackp[i].isrc[7], &cp->cs_tno, 7);
1031                         } else {
1032                                 cp->cs_ctladr = 0x03;
1033                                 cp->cs_tno = i;
1034                                 movebytes(&trackp[i].isrc[0], &cp->cs_index, 6);
1035                                 cp = &cue[icue++];
1036                                 cp->cs_ctladr = 0x03;
1037                                 cp->cs_tno = i;
1038                                 movebytes(&trackp[i].isrc[6], &cp->cs_index, 6);
1039                         }
1040                 }
1041 #endif
1042                 if (i == 0) {   /* Lead in */
1043                         df &= ~7;
1044                         if (trackp[0].flags & TI_TEXT)  /* CD-Text in Lead-in*/
1045                                 df |= 0xC0;
1046                         lba_to_msf(-150, &m);
1047                         cue = realloc(cue, ++ncue * sizeof (*cue));
1048                         cp = &cue[icue++];
1049                         fillcue(cp, ctl|0x01, i, 0, df, 0, &m);
1050                 } else {
1051                         scms = 0;
1052
1053                         if (is_scms(&trackp[i]))
1054                                 scms = 0x80;
1055                         pgsize = trackp[i].pregapsize;
1056                         if (pgsize == 0 && needgap)
1057                                 pgsize++;
1058                         lba_to_msf(trackp[i].trackstart-pgsize, &m);
1059                         cue = realloc(cue, ++ncue * sizeof (*cue));
1060                         cp = &cue[icue++];
1061                         fillcue(cp, ctl|0x01, i, 0, df, scms, &m);
1062
1063                         if (trackp[i].nindex == 1) {
1064                                 lba_to_msf(trackp[i].trackstart, &m);
1065                                 cue = realloc(cue, ++ncue * sizeof (*cue));
1066                                 cp = &cue[icue++];
1067                                 fillcue(cp, ctl|0x01, i, 1, df, scms, &m);
1068                         } else {
1069                                 int     idx;
1070                                 long    *idxlist;
1071
1072                                 ncue += trackp[i].nindex;
1073                                 idxlist = trackp[i].tindex;
1074                                 cue = realloc(cue, ncue * sizeof (*cue));
1075
1076                                 for (idx = 1; idx <= trackp[i].nindex; idx++) {
1077                                         lba_to_msf(trackp[i].trackstart + idxlist[idx], &m);
1078                                         cp = &cue[icue++];
1079                                         fillcue(cp, ctl|0x01, i, idx, df, scms, &m);
1080                                 }
1081                         }
1082                 }
1083         }
1084         /* Lead out */
1085         ctl = (st2mode[trackp[tracks+1].sectype & ST_MASK]) << 4;
1086         df = db2df[trackp[tracks+1].dbtype & 0x0F];
1087         df &= ~7;
1088         lba_to_msf(trackp[tracks+1].trackstart, &m);
1089         cue = realloc(cue, ++ncue * sizeof (*cue));
1090         cp = &cue[icue++];
1091         fillcue(cp, ctl|0x01, 0xAA, 1, df, 0, &m);
1092
1093         if (lverbose > 1) {
1094                 for (i = 0; i < ncue; i++) {
1095                         usal_prbytes("", (Uchar *)&cue[i], 8);
1096                 }
1097         }
1098         if (cuep)
1099                 *cuep = cue;
1100         else
1101                 free(cue);
1102         return (ncue);
1103 }
1104
1105
1106 static void
1107 fillcue(struct sony_cue *cp     /* The target cue entry */, 
1108         int ca                  /* Control/adr for this entry */, 
1109         int tno                 /* Track number for this entry */, 
1110         int idx                 /* Index for this entry */, 
1111         int dataform            /* Data format for this entry */, 
1112         int scms                /* Serial copy management */, 
1113         msf_t *mp               /* MSF value for this entry */)
1114 {
1115         cp->cs_ctladr = ca;
1116         if (tno <= 99)
1117                 cp->cs_tno = to_bcd(tno);
1118         else
1119                 cp->cs_tno = tno;
1120         cp->cs_index = to_bcd(idx);
1121         cp->cs_dataform = dataform;
1122         cp->cs_zero = scms;
1123         cp->cs_min = to_bcd(mp->msf_min);
1124         cp->cs_sec = to_bcd(mp->msf_sec);
1125         cp->cs_frame = to_bcd(mp->msf_frame);
1126 }
1127
1128 static int
1129 send_cue_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
1130 {
1131         struct sony_cue *cp;
1132         int             ncue;
1133         int             ret;
1134         Uint            i;
1135         struct timeval starttime;
1136         struct timeval stoptime;
1137         int             disktype;
1138
1139         disktype = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
1140
1141         for (i = 1; i <= trackp->tracks; i++) {
1142                 if (trackp[i].tracksize < (tsize_t)0) {
1143                         errmsgno(EX_BAD, "Track %d has unknown length.\n", i);
1144                         return (-1);
1145                 }
1146         }
1147         ncue = (*dp->cdr_gen_cue)(trackp, &cp, FALSE);
1148
1149         starttime.tv_sec = 0;
1150         starttime.tv_usec = 0;
1151         stoptime = starttime;
1152         gettimeofday(&starttime, (struct timezone *)0);
1153
1154         usalp->silent++;
1155         ret  = write_start_sony(usalp, (caddr_t)cp, ncue*8);
1156         usalp->silent--;
1157         free(cp);
1158         if (ret < 0) {
1159                 errmsgno(EX_BAD, "CUE sheet not accepted. Retrying with minimum pregapsize = 1.\n");
1160                 ncue = (*dp->cdr_gen_cue)(trackp, &cp, TRUE);
1161                 ret  = write_start_sony(usalp, (caddr_t)cp, ncue*8);
1162                 free(cp);
1163         }
1164         if (ret >= 0 && lverbose) {
1165                 gettimeofday(&stoptime, (struct timezone *)0);
1166                 prtimediff("Write Lead-in time: ", &starttime, &stoptime);
1167         }
1168         return (ret);
1169 }
1170
1171 static int
1172 write_leadin_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
1173 {
1174         Uint    i;
1175         long    startsec = 0L;
1176
1177 /*      if (flags & F_SAO) {*/
1178         if (wm_base(dp->cdr_dstat->ds_wrmode) == WM_SAO) {
1179                 if (debug || lverbose) {
1180                         printf("Sending CUE sheet...\n");
1181                         flush();
1182                 }
1183                 if (trackp[0].flags & TI_TEXT) {
1184                         if (dp->cdr_speeddef != 4) {
1185                                 errmsgno(EX_BAD,
1186                                 "The CDU-924 does not support CD-Text, disabling.\n");
1187
1188                                 trackp[0].flags &= ~TI_TEXT;
1189                         }
1190                 }
1191                 if ((*dp->cdr_send_cue)(usalp, dp, trackp) < 0) {
1192                         errmsgno(EX_BAD, "Cannot send CUE sheet.\n");
1193                         return (-1);
1194                 }
1195
1196                 if (trackp[0].flags & TI_TEXT) {
1197                         startsec = dp->cdr_dstat->ds_first_leadin;
1198                         printf("SAO startsec: %ld\n", startsec);
1199                 } else {
1200                         startsec = -150;
1201                 }
1202                 if (debug)
1203                         printf("SAO startsec: %ld\n", startsec);
1204
1205                 if (trackp[0].flags & TI_TEXT) {
1206                         if (startsec > 0) {
1207                                 errmsgno(EX_BAD, "CD-Text must be in first session.\n");
1208                                 return (-1);
1209                         }
1210                         if (debug || lverbose)
1211                                 printf("Writing lead-in...\n");
1212                         if (write_cdtext(usalp, dp, startsec) < 0)
1213                                 return (-1);
1214
1215                         dp->cdr_dstat->ds_cdrflags |= RF_LEADIN;
1216                 } else for (i = 1; i <= trackp->tracks; i++) {
1217                         trackp[i].trackstart += startsec +150;
1218                 }
1219         }
1220         return (0);
1221 }
1222
1223 /*--------------------------------------------------------------------------*/
1224
1225 static const char *sd_cdu_924_error_str[] = {
1226
1227         "\200\000write complete",                               /* 80 00 */
1228         "\201\000logical unit is reserved",                     /* 81 00 */
1229         "\205\000audio address not valid",                      /* 85 00 */
1230         "\210\000illegal cue sheet",                            /* 88 00 */
1231         "\211\000inappropriate command",                        /* 89 00 */
1232
1233         "\266\000media load mechanism failed",                  /* B6 00 */
1234         "\271\000audio play operation aborted",                 /* B9 00 */
1235         "\277\000buffer overflow for read all subcodes command", /* BF 00 */
1236         "\300\000unrecordable disk",                            /* C0 00 */
1237         "\301\000illegal track status",                         /* C1 00 */
1238         "\302\000reserved track present",                       /* C2 00 */
1239         "\303\000buffer data size error",                       /* C3 00 */
1240         "\304\001illegal data form for reserve track command",  /* C4 01 */
1241         "\304\002unable to reserve track, because track mode has been changed", /* C4 02 */
1242         "\305\000buffer error during at once recording",        /* C5 00 */
1243         "\306\001unwritten area encountered",                   /* C6 01 */
1244         "\306\002link blocks encountered",                      /* C6 02 */
1245         "\306\003nonexistent block encountered",                /* C6 03 */
1246         "\307\000disk style mismatch",                          /* C7 00 */
1247         "\310\000no table of contents",                         /* C8 00 */
1248         "\311\000illegal block length for write command",       /* C9 00 */
1249         "\312\000power calibration error",                      /* CA 00 */
1250         "\313\000write error",                                  /* CB 00 */
1251         "\313\001write error track recovered",                  /* CB 01 */
1252         "\314\000not enough space",                             /* CC 00 */
1253         "\315\000no track present to finalize",                 /* CD 00 */
1254         "\316\000unrecoverable track descriptor encountered",   /* CE 00 */
1255         "\317\000damaged track present",                        /* CF 00 */
1256         "\320\000pma area full",                                /* D0 00 */
1257         "\321\000pca area full",                                /* D1 00 */
1258         "\322\000unrecoverable damaged track cause too small writing area",     /* D2 00 */
1259         "\323\000no bar code",                                  /* D3 00 */
1260         "\323\001not enough bar code margin",                   /* D3 01 */
1261         "\323\002no bar code start pattern",                    /* D3 02 */
1262         "\323\003illegal bar code length",                      /* D3 03 */
1263         "\323\004illegal bar code format",                      /* D3 04 */
1264         "\324\000exit from pseudo track at once recording",     /* D4 00 */
1265         NULL
1266 };
1267
1268 static int
1269 sony_attach(SCSI *usalp, cdr_t *dp)
1270 {
1271         if (usalp->inq != NULL) {
1272                 if (strbeg("CD-R   CDU94", usalp->inq->prod_ident)) {
1273                         dp->cdr_speeddef = 4;
1274                 }
1275         }
1276         usal_setnonstderrs(usalp, sd_cdu_924_error_str);
1277         return (0);
1278 }
1279
1280 #ifdef  SONY_DEBUG
1281 static void
1282 print_sony_mp22(struct sony_924_mode_page_22 *xp, int len)
1283 {
1284         printf("disk style: %X\n", xp->disk_style);
1285         printf("disk type: %X\n", xp->disk_type);
1286         printf("first track: %X\n", xp->first_track);
1287         printf("last track: %X\n", xp->last_track);
1288         printf("numsess:    %X\n", xp->numsess);
1289         printf("disk appl code: %lX\n", a_to_u_4_byte(xp->disk_appl_code));
1290         printf("last start time: %lX\n", a_to_u_4_byte(xp->last_start_time));
1291         printf("disk status: %X\n", xp->disk_status);
1292         printf("num valid nra: %X\n", xp->num_valid_nra);
1293         printf("track info track: %X\n", xp->track_info_track);
1294         printf("post gap: %X\n", xp->post_gap);
1295         printf("disk id code: %lX\n", a_to_u_4_byte(xp->disk_id_code));
1296         printf("lead in start: %lX\n", a_to_u_4_byte(xp->lead_in_start));
1297 }
1298
1299 static void
1300 print_sony_mp23(struct sony_924_mode_page_23 *xp, int len)
1301 {
1302         printf("len: %d\n", len);
1303
1304         printf("track num: %X\n", xp->track_num);
1305         printf("data form: %X\n", xp->data_form);
1306         printf("write method: %X\n", xp->write_method);
1307         printf("session: %X\n", xp->session);
1308         printf("track status: %X\n", xp->track_status);
1309
1310 /*
1311  * XXX Check for signed/unsigned a_to_*() conversion.
1312  */
1313         printf("start lba: %lX\n", a_to_4_byte(xp->start_lba));
1314         printf("next recordable addr: %lX\n", a_to_4_byte(xp->next_recordable_addr));
1315         printf("blank area cap: %lX\n", a_to_u_4_byte(xp->blank_area_cap));
1316         printf("fixed packet size: %lX\n", a_to_u_4_byte(xp->fixed_packet_size));
1317         printf("starting msf: %lX\n", a_to_u_4_byte(xp->starting_msf));
1318         printf("ending msf: %lX\n", a_to_u_4_byte(xp->ending_msf));
1319         printf("next rec time: %lX\n", a_to_u_4_byte(xp->next_rec_time));
1320 }
1321 #endif
1322
1323 static int
1324 buf_cap_sony(SCSI *usalp, long *sp, long *fp)
1325 {
1326         char    resp[8];
1327         Ulong   freespace;
1328         Ulong   bufsize;
1329         int     per;
1330         register struct usal_cmd        *scmd = usalp->scmd;
1331
1332         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1333         scmd->addr = (caddr_t)resp;
1334         scmd->size = sizeof (resp);
1335         scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1336         scmd->cdb_len = SC_G1_CDBLEN;
1337         scmd->sense_len = CCS_SENSE_LEN;
1338         scmd->cdb.g1_cdb.cmd = 0xEC;            /* Read buffer cap */
1339         scmd->cdb.g1_cdb.lun = usal_lun(usalp);
1340
1341         usalp->cmdname = "read buffer cap sony";
1342
1343         if (usal_cmd(usalp) < 0)
1344                 return (-1);
1345
1346         bufsize   = a_to_u_3_byte(&resp[1]);
1347         freespace = a_to_u_3_byte(&resp[5]);
1348         if (sp)
1349                 *sp = bufsize;
1350         if (fp)
1351                 *fp = freespace;
1352
1353         if (usalp->verbose || (sp == 0 && fp == 0))
1354                 printf("BFree: %ld K BSize: %ld K\n", freespace >> 10, bufsize >> 10);
1355
1356         if (bufsize == 0)
1357                 return (0);
1358         per = (100 * (bufsize - freespace)) / bufsize;
1359         if (per < 0)
1360                 return (0);
1361         if (per > 100)
1362                 return (100);
1363         return (per);
1364 }