2 * This file has been modified for the cdrkit suite.
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).
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.
13 /* @(#)drv_sony.c 1.72 05/05/16 Copyright 1997-2005 J. Schilling */
15 * CDR device implementation for
18 * Copyright (c) 1997-2005 J. Schilling
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.
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.
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.
35 /*#define SONY_DEBUG*/
41 #include <unixstd.h> /* Include sys/types.h to make off_t available */
53 #include <usal/usalcmd.h>
54 #include <usal/scsidefs.h>
55 #include <usal/scsireg.h>
56 #include <usal/scsitransp.h>
61 # define inc_verbose() usalp->verbose++
62 # define dec_verbose() usalp->verbose--
64 # define inc_verbose()
65 # define dec_verbose()
71 #if defined(_BIT_FIELDS_LTOH) /* Intel byteorder */
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;
81 Ucbit subcode_ecc : 1;
88 #else /* Motorola byteorder */
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;
95 Ucbit subcode_ecc : 1;
106 struct sony_924_mode_page_22 { /* disk information */
107 MP_P_CODE; /* parsave & pagecode */
108 Uchar p_len; /* 0x1E = 30 Bytes */
115 Uchar disk_appl_code[4];
116 Uchar last_start_time[4];
119 Uchar track_info_track;
121 Uchar disk_id_code[4];
122 Uchar lead_in_start[4];
126 struct sony_924_mode_page_23 { /* track information */
127 MP_P_CODE; /* parsave & pagecode */
128 Uchar p_len; /* 0x22 = 34 Bytes */
136 Uchar next_recordable_addr[4];
137 Uchar blank_area_cap[4];
138 Uchar fixed_packet_size[4];
140 Uchar starting_msf[3];
144 Uchar next_rec_time[3];
147 struct sony_924_mode_page_31 { /* drive speed */
148 MP_P_CODE; /* parsave & pagecode */
149 Uchar p_len; /* 0x02 = 2 Bytes */
154 struct cdd_52x_mode_data {
155 struct scsi_mode_header header;
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;
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 */
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 */
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 */
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 */
209 #define strbeg(s1, s2) (strstr((s2), (s1)) == (s2))
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,
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,
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);
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);
245 static int buf_cap_sony(SCSI *usalp, long *, long *);
247 cdr_t cdr_sony_cdu924 = {
249 CDR_TAO|CDR_SAO|CDR_CADDYLOAD|CDR_SWABAUDIO,
253 "driver for Sony CDU-924 / CDU-948",
263 cmd_dummy, /* recovery_needed */
278 read_session_offset_philips,
280 cmd_dummy, /* stats */
283 (int(*)(SCSI *, caddr_t, int, int))NULL, /* no OPC */
284 cmd_dummy, /* opt1 */
285 cmd_dummy, /* opt2 */
289 write_start_sony(SCSI *usalp, caddr_t bp, int size)
291 register struct usal_cmd *scmd = usalp->scmd;
293 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
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 */
304 usalp->cmdname = "write_start";
306 if (usal_cmd(usalp) < 0)
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 */)
319 register struct usal_cmd *scmd = usalp->scmd;
321 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
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 */
331 usalp->cmdname = "write_continue";
333 if (usal_cmd(usalp) < 0) {
335 * XXX This seems to happen only sometimes.
337 if (usal_sense_code(usalp) != 0x80)
340 return (size - usal_getresid(usalp));
344 discontinue_sony(SCSI *usalp)
346 register struct usal_cmd *scmd = usalp->scmd;
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);
355 usalp->cmdname = "discontinue";
357 if (usal_cmd(usalp) < 0)
363 write_track_sony(SCSI *usalp,
364 long track /* track number 0 == new track */,
365 int sectype /* no sectype for Sony write track */)
367 register struct usal_cmd *scmd = usalp->scmd;
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);
377 usalp->cmdname = "write_track";
379 if (usal_cmd(usalp) < 0)
384 /* XXX NOCH NICHT FERTIG */
386 close_track_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
388 register struct usal_cmd *scmd = usalp->scmd;
391 if (!is_tao(trackp) && !is_packet(trackp))
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]) */
403 usalp->cmdname = "close_track";
405 if (usal_cmd(usalp) < 0)
409 * Clear the silly "error situation" from Sony´ dummy write end
410 * but notify if real errors occurred.
413 if (test_unit_ready(usalp) < 0 && usal_sense_code(usalp) != 0xD4) {
414 usalp->cmdname = "close_track/test_unit_ready";
415 usal_printerr(usalp);
423 finalize_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
425 register struct usal_cmd *scmd = usalp->scmd;
426 int dummy = track_base(trackp)->tracktype & TOCF_DUMMY;
428 if (!is_tao(trackp) && !is_packet(trackp)) {
429 wait_unit_ready(usalp, 240);
433 printf("Fixating is not possible in dummy write mode.\n");
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]) */
446 usalp->cmdname = "finalize";
448 if (usal_cmd(usalp) < 0)
454 flush_sony(SCSI *usalp, int track)
456 register struct usal_cmd *scmd = usalp->scmd;
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]) */
470 usalp->cmdname = "flush";
472 if (usal_cmd(usalp) < 0)
478 recover_sony(SCSI *usalp, cdr_t *dp, int track)
480 register struct usal_cmd *scmd = usalp->scmd;
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;
490 usalp->cmdname = "recover";
492 if (usal_cmd(usalp) < 0)
498 set_wr_parameter_sony(SCSI *usalp, caddr_t bp, int size)
500 register struct usal_cmd *scmd = usalp->scmd;
502 fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
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);
512 usalp->cmdname = "set_write_parameter";
514 if (usal_cmd(usalp) < 0)
520 next_wr_addr_sony(SCSI *usalp, track_t *trackp, long *ap)
522 if (next_writable_address_sony(usalp, ap, 0, 0, 0) < 0)
528 reserve_track_sony(SCSI *usalp, unsigned long len)
530 register struct usal_cmd *scmd = usalp->scmd;
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);
540 usalp->cmdname = "reserve_track";
542 if (usal_cmd(usalp) < 0)
548 init_sony(SCSI *usalp, cdr_t *dp)
550 return (speed_select_sony(usalp, dp, NULL));
554 #define IS(what, flag) printf(" Is %s%s\n", flag?"":"not ", what);
557 getdisktype_sony(SCSI *usalp, cdr_t *dp)
559 dstat_t *dsp = dp->cdr_dstat;
565 struct scsi_mode_page_header *mp;
566 struct sony_924_mode_page_22 *xp;
568 dummy = get_page22_sony(usalp, mode);
570 mp = (struct scsi_mode_page_header *)
571 (mode + sizeof (struct scsi_mode_header) +
572 ((struct scsi_mode_header *)mode)->blockdesc_len);
574 xp = (struct sony_924_mode_page_22 *)mp;
576 if (xp->disk_appl_code[0] == 0xFF)
579 return (drive_getdisktype(usalp, dp));
582 if ((dp->cdr_dstat->ds_cdrflags & RF_PRATIP) != 0 && dummy >= 0) {
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);
595 * The Sony CDU 920 seems to deliver 00:00/00 for
596 * lead-in start time, dont use it.
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);
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);
610 * The Sony CDU 920 seems to deliver 00:00/00 for
611 * lead-in start time, dont use it.
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);
622 di_to_dstat_sony(xp, dsp);
623 return (drive_getdisktype(usalp, dp));
627 di_to_dstat_sony(struct sony_924_mode_page_22 *dip, dstat_t *dsp)
631 dsp->ds_diskid = a_to_u_4_byte(dip->disk_id_code);
633 if (dsp->ds_diskid != 0xFFFFFFFFUL)
635 if (dsp->ds_diskid != (Ulong)0xFFFFFFFF)
637 dsp->ds_flags |= DSF_DID_V;
638 dsp->ds_diskstat = (dip->disk_status >> 6) & 0x03;
641 * There seems to be no MMC equivalent...
643 dsp->ds_sessstat = dip->sess_status;
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);
650 * Check for 0xFF:0xFF/0xFF which is an indicator for a complete disk
652 if (dsp->ds_maxblocks == 716730)
653 dsp->ds_maxblocks = -1L;
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);
660 * Check for illegal values (> 0)
661 * or for empty field (-150) with CDU-920.
663 if (dsp->ds_first_leadin > 0 || dsp->ds_first_leadin == -150)
664 dsp->ds_first_leadin = 0;
667 if (dsp->ds_last_leadout == 0 && dsp->ds_maxblocks >= 0)
668 dsp->ds_last_leadout = dsp->ds_maxblocks;
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);
679 int sony_speeds[] = {
680 -1, /* Speed null is not allowed */
681 0, /* Single speed */
682 1, /* Double speed */
683 -1, /* Three times */
688 speed_select_sony(SCSI *usalp, cdr_t *dp, int *speedp)
690 struct cdd_52x_mode_data md;
694 BOOL dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
698 if (speed < 1 || speed > 4 || sony_speeds[speed] < 0)
702 fillbytes((caddr_t)&md, sizeof (md), '\0');
704 count = sizeof (struct scsi_mode_header) +
705 sizeof (struct sony_924_mode_page_20);
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;
712 * Set Cue sheet option. This is documented for the 924 and
713 * seems to be supported for the 948 too.
715 md.pagex.page_s20.cue_sheet_opt = 0x03;
717 err = mode_select(usalp, (Uchar *)&md, count, 0, 1);
724 fillbytes((caddr_t)&md, sizeof (md), '\0');
726 count = sizeof (struct scsi_mode_header) +
727 sizeof (struct sony_924_mode_page_31);
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];
733 return (mode_select(usalp, (Uchar *)&md, count, 0, 1));
737 next_writable_address_sony(SCSI *usalp, long *ap, int track, int sectype,
740 struct scsi_mode_page_header *mp;
744 struct sony_924_mode_page_23 *xp;
746 fillbytes((caddr_t)mode, sizeof (mode), '\0');
749 if (!get_mode_params(usalp, page, "CD track information",
750 (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
758 mp = (struct scsi_mode_page_header *)
759 (mode + sizeof (struct scsi_mode_header) +
760 ((struct scsi_mode_header *)mode)->blockdesc_len);
763 xp = (struct sony_924_mode_page_23 *)mp;
766 print_sony_mp23(xp, len);
769 *ap = a_to_4_byte(xp->next_recordable_addr);
775 new_track_sony(SCSI *usalp, int track, int sectype, int tracktype)
777 struct scsi_mode_page_header *mp;
781 struct sony_924_mode_page_23 *xp;
784 fillbytes((caddr_t)mode, sizeof (mode), '\0');
785 get_page22_sony(usalp, mode);
787 fillbytes((caddr_t)mode, sizeof (mode), '\0');
790 if (!get_mode_params(usalp, page, "CD track information",
791 (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
799 mp = (struct scsi_mode_page_header *)
800 (mode + sizeof (struct scsi_mode_header) +
801 ((struct scsi_mode_header *)mode)->blockdesc_len);
804 xp = (struct sony_924_mode_page_23 *)mp;
807 print_sony_mp23(xp, len);
810 xp->write_method = 0; /* Track at one recording */
812 if (sectype & ST_AUDIOMASK) {
813 xp->data_form = (sectype & ST_MASK) == ST_AUDIO_PRE ? 0x02 : 0x00;
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;
826 ((struct scsi_modesel_header *)mode)->sense_data_len = 0;
827 ((struct scsi_modesel_header *)mode)->res2 = 0;
829 i = ((struct scsi_mode_header *)mode)->blockdesc_len;
832 ((struct scsi_mode_data *)mode)->blockdesc.nlblock,
836 if (mode_select(usalp, (Uchar *)mode, len, 0, usalp->inq->data_format >= 2) < 0) {
844 open_track_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
846 if (!is_tao(trackp) && !is_packet(trackp)) {
847 if (trackp->pregapsize > 0 && (trackp->flags & TI_PREGAP) == 0) {
849 printf("Writing pregap for track %d at %ld\n",
850 (int)trackp->trackno,
851 trackp->trackstart-trackp->pregapsize);
854 * XXX Do we need to check isecsize too?
856 pad_track(usalp, dp, trackp,
857 trackp->trackstart-trackp->pregapsize,
858 (Llong)trackp->pregapsize*trackp->secsize,
864 if (select_secsize(usalp, trackp->secsize) < 0)
867 if (new_track_sony(usalp, trackp->trackno, trackp->sectype, trackp->tracktype & TOC_MASK) < 0)
870 if (write_track_sony(usalp, 0L, trackp->sectype) < 0)
877 open_session_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
879 struct scsi_mode_page_header *mp;
883 struct sony_924_mode_page_22 *xp;
885 fillbytes((caddr_t)mode, sizeof (mode), '\0');
887 if ((len = get_page22_sony(usalp, mode)) < 0)
890 mp = (struct scsi_mode_page_header *)
891 (mode + sizeof (struct scsi_mode_header) +
892 ((struct scsi_mode_header *)mode)->blockdesc_len);
894 xp = (struct sony_924_mode_page_22 *)mp;
896 xp->disk_type = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
898 if (is_tao(track_base(trackp))) {
900 if ((track_base(trackp)->tracktype & TOC_MASK) == TOC_DA)
901 xp->disk_style = 0x80;
903 xp->disk_style = 0xC0;
905 } else if (is_sao(track_base(trackp))) {
907 * We may only change this value if the disk is empty.
908 * i.e. when disk_status & 0xC0 == 0x00
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");
914 xp->disk_style = 0x00;
917 ((struct scsi_modesel_header *)mode)->sense_data_len = 0;
918 ((struct scsi_modesel_header *)mode)->res2 = 0;
920 i = ((struct scsi_mode_header *)mode)->blockdesc_len;
923 ((struct scsi_mode_data *)mode)->blockdesc.nlblock,
927 if (mode_select(usalp, (Uchar *)mode, len, 0, usalp->inq->data_format >= 2) < 0) {
931 * XXX set write parameter für SAO mit Multi Session (948 only?)
932 * XXX set_wr_parameter_sony(usalp, bp, size);
938 abort_session_sony(SCSI *usalp, cdr_t *dp)
940 return (discontinue_sony(usalp));
944 get_page22_sony(SCSI *usalp, char *mode)
946 struct scsi_mode_page_header *mp;
949 struct sony_924_mode_page_22 *xp;
951 fillbytes((caddr_t)mode, sizeof (mode), '\0');
954 if (!get_mode_params(usalp, page, "CD disk information",
955 (Uchar *)mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
963 mp = (struct scsi_mode_page_header *)
964 (mode + sizeof (struct scsi_mode_header) +
965 ((struct scsi_mode_header *)mode)->blockdesc_len);
967 xp = (struct sony_924_mode_page_22 *)mp;
970 print_sony_mp22(xp, len);
975 /*--------------------------------------------------------------------------*/
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 */
997 gen_cue_sony(track_t *trackp, void *vcuep, BOOL needgap)
999 int tracks = trackp->tracks;
1001 struct sony_cue **cuep = vcuep;
1002 struct sony_cue *cue;
1003 struct sony_cue *cp;
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];
1020 #ifdef __supported__
1021 if (trackp[i].isrc) { /* MCN or ISRC */
1023 cue = realloc(cue, ncue * sizeof (*cue));
1026 cp->cs_ctladr = 0x02;
1027 movebytes(&trackp[i].isrc[0], &cp->cs_tno, 7);
1029 cp->cs_ctladr = 0x02;
1030 movebytes(&trackp[i].isrc[7], &cp->cs_tno, 7);
1032 cp->cs_ctladr = 0x03;
1034 movebytes(&trackp[i].isrc[0], &cp->cs_index, 6);
1036 cp->cs_ctladr = 0x03;
1038 movebytes(&trackp[i].isrc[6], &cp->cs_index, 6);
1042 if (i == 0) { /* Lead in */
1044 if (trackp[0].flags & TI_TEXT) /* CD-Text in Lead-in*/
1046 lba_to_msf(-150, &m);
1047 cue = realloc(cue, ++ncue * sizeof (*cue));
1049 fillcue(cp, ctl|0x01, i, 0, df, 0, &m);
1053 if (is_scms(&trackp[i]))
1055 pgsize = trackp[i].pregapsize;
1056 if (pgsize == 0 && needgap)
1058 lba_to_msf(trackp[i].trackstart-pgsize, &m);
1059 cue = realloc(cue, ++ncue * sizeof (*cue));
1061 fillcue(cp, ctl|0x01, i, 0, df, scms, &m);
1063 if (trackp[i].nindex == 1) {
1064 lba_to_msf(trackp[i].trackstart, &m);
1065 cue = realloc(cue, ++ncue * sizeof (*cue));
1067 fillcue(cp, ctl|0x01, i, 1, df, scms, &m);
1072 ncue += trackp[i].nindex;
1073 idxlist = trackp[i].tindex;
1074 cue = realloc(cue, ncue * sizeof (*cue));
1076 for (idx = 1; idx <= trackp[i].nindex; idx++) {
1077 lba_to_msf(trackp[i].trackstart + idxlist[idx], &m);
1079 fillcue(cp, ctl|0x01, i, idx, df, scms, &m);
1085 ctl = (st2mode[trackp[tracks+1].sectype & ST_MASK]) << 4;
1086 df = db2df[trackp[tracks+1].dbtype & 0x0F];
1088 lba_to_msf(trackp[tracks+1].trackstart, &m);
1089 cue = realloc(cue, ++ncue * sizeof (*cue));
1091 fillcue(cp, ctl|0x01, 0xAA, 1, df, 0, &m);
1094 for (i = 0; i < ncue; i++) {
1095 usal_prbytes("", (Uchar *)&cue[i], 8);
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 */)
1117 cp->cs_tno = to_bcd(tno);
1120 cp->cs_index = to_bcd(idx);
1121 cp->cs_dataform = dataform;
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);
1129 send_cue_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
1131 struct sony_cue *cp;
1135 struct timeval starttime;
1136 struct timeval stoptime;
1139 disktype = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
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);
1147 ncue = (*dp->cdr_gen_cue)(trackp, &cp, FALSE);
1149 starttime.tv_sec = 0;
1150 starttime.tv_usec = 0;
1151 stoptime = starttime;
1152 gettimeofday(&starttime, (struct timezone *)0);
1155 ret = write_start_sony(usalp, (caddr_t)cp, ncue*8);
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);
1164 if (ret >= 0 && lverbose) {
1165 gettimeofday(&stoptime, (struct timezone *)0);
1166 prtimediff("Write Lead-in time: ", &starttime, &stoptime);
1172 write_leadin_sony(SCSI *usalp, cdr_t *dp, track_t *trackp)
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");
1183 if (trackp[0].flags & TI_TEXT) {
1184 if (dp->cdr_speeddef != 4) {
1186 "The CDU-924 does not support CD-Text, disabling.\n");
1188 trackp[0].flags &= ~TI_TEXT;
1191 if ((*dp->cdr_send_cue)(usalp, dp, trackp) < 0) {
1192 errmsgno(EX_BAD, "Cannot send CUE sheet.\n");
1196 if (trackp[0].flags & TI_TEXT) {
1197 startsec = dp->cdr_dstat->ds_first_leadin;
1198 printf("SAO startsec: %ld\n", startsec);
1203 printf("SAO startsec: %ld\n", startsec);
1205 if (trackp[0].flags & TI_TEXT) {
1207 errmsgno(EX_BAD, "CD-Text must be in first session.\n");
1210 if (debug || lverbose)
1211 printf("Writing lead-in...\n");
1212 if (write_cdtext(usalp, dp, startsec) < 0)
1215 dp->cdr_dstat->ds_cdrflags |= RF_LEADIN;
1216 } else for (i = 1; i <= trackp->tracks; i++) {
1217 trackp[i].trackstart += startsec +150;
1223 /*--------------------------------------------------------------------------*/
1225 static const char *sd_cdu_924_error_str[] = {
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 */
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 */
1269 sony_attach(SCSI *usalp, cdr_t *dp)
1271 if (usalp->inq != NULL) {
1272 if (strbeg("CD-R CDU94", usalp->inq->prod_ident)) {
1273 dp->cdr_speeddef = 4;
1276 usal_setnonstderrs(usalp, sd_cdu_924_error_str);
1282 print_sony_mp22(struct sony_924_mode_page_22 *xp, int len)
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));
1300 print_sony_mp23(struct sony_924_mode_page_23 *xp, int len)
1302 printf("len: %d\n", len);
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);
1311 * XXX Check for signed/unsigned a_to_*() conversion.
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));
1324 buf_cap_sony(SCSI *usalp, long *sp, long *fp)
1330 register struct usal_cmd *scmd = usalp->scmd;
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);
1341 usalp->cmdname = "read buffer cap sony";
1343 if (usal_cmd(usalp) < 0)
1346 bufsize = a_to_u_3_byte(&resp[1]);
1347 freespace = a_to_u_3_byte(&resp[5]);
1353 if (usalp->verbose || (sp == 0 && fp == 0))
1354 printf("BFree: %ld K BSize: %ld K\n", freespace >> 10, bufsize >> 10);
1358 per = (100 * (bufsize - freespace)) / bufsize;