--- cdrtools-2.01.01/libscg/scsi-linux-sg.c.dvd 2005-11-22 23:09:39.000000000 +0100 +++ cdrtools-2.01.01/libscg/scsi-linux-sg.c 2006-01-26 14:32:51.000000000 +0100 @@ -372,7 +372,7 @@ * own belly button. */ js_fprintf((FILE *)scgp->errfile, - "Warning: Using badly designed ATAPI via /dev/hd* interface.\n"); + "#########################################################################################\n#\n# Warning: Using ATAPI via /dev/hd* interface. Use dev=ATA:X,Y,Z or dev=/dev/hdX\n\#\n#########################################################################################\n"); } } } --- cdrtools-2.01.01/libscg/scsitransp.c.dvd 2004-06-17 22:20:27.000000000 +0200 +++ cdrtools-2.01.01/libscg/scsitransp.c 2006-01-26 14:32:51.000000000 +0100 @@ -107,6 +107,7 @@ EXPORT int scg_sense_key __PR((SCSI *scgp)); EXPORT int scg_sense_code __PR((SCSI *scgp)); EXPORT int scg_sense_qual __PR((SCSI *scgp)); +EXPORT unsigned char *scg_sense_table __PR((SCSI *scgp)); EXPORT void scg_fprintdev __PR((FILE *, struct scsi_inquiry *)); EXPORT void scg_printdev __PR((struct scsi_inquiry *)); EXPORT int scg_printf __PR((SCSI *scgp, const char *form, ...)); @@ -1239,6 +1240,23 @@ } /* + * Return all the SCSI sense table last command. + */ +EXPORT unsigned char * +scg_sense_table(scgp) + SCSI *scgp; +{ + register struct scg_cmd *cp = scgp->scmd; + + if(!scg_cmd_err(scgp)) + return (0); + + if (cp->sense.code >= 0x70) + return &(cp->sense); +} + + +/* * Return the SCSI sense code for last command. */ EXPORT int --- cdrtools-2.01.01/cdrecord/cdr_drv.c.dvd 2004-03-02 02:06:26.000000000 +0100 +++ cdrtools-2.01.01/cdrecord/cdr_drv.c 2006-01-26 14:32:51.000000000 +0100 @@ -41,6 +41,7 @@ extern cdr_t cdr_oldcd; extern cdr_t cdr_cd; extern cdr_t cdr_mmc; +extern cdr_t cdr_mdvd; extern cdr_t cdr_mmc_sony; extern cdr_t cdr_cd_dvd; extern cdr_t cdr_philips_cdd521O; @@ -79,6 +80,7 @@ cdr_t *drivers[] = { &cdr_cd_dvd, &cdr_mmc, + &cdr_mdvd, &cdr_mmc_sony, &cdr_cd, &cdr_oldcd, --- cdrtools-2.01.01/cdrecord/cdrecord.c.dvd 2006-01-26 14:31:31.000000000 +0100 +++ cdrtools-2.01.01/cdrecord/cdrecord.c 2006-01-26 14:32:51.000000000 +0100 @@ -179,6 +179,7 @@ LOCAL void susage __PR((int)); LOCAL void usage __PR((int)); LOCAL void blusage __PR((int)); +LOCAL void formattypeusage __PR((int)); LOCAL void intr __PR((int sig)); LOCAL void catchsig __PR((int sig)); LOCAL int scsi_cb __PR((void *arg)); @@ -215,9 +216,9 @@ LOCAL BOOL checkdsize __PR((SCSI *scgp, cdr_t *dp, long tsize, int flags)); LOCAL void raise_fdlim __PR((void)); -LOCAL void gargs __PR((int, char **, int *, track_t *, char **, +LOCAL int gargs __PR((int, char **, int *, track_t *, char **, int *, cdr_t **, - int *, long *, int *)); + int *, long *, int *, int *)); LOCAL void set_trsizes __PR((cdr_t *, int, track_t *)); EXPORT void load_media __PR((SCSI *scgp, cdr_t *, BOOL)); EXPORT void unload_media __PR((SCSI *scgp, cdr_t *, int)); @@ -237,6 +238,7 @@ LOCAL void wait_input __PR((void)); LOCAL void checkgui __PR((void)); LOCAL int getbltype __PR((char *optstr, long *typep)); +LOCAL int getformattype __PR((char *optstr, long *typep)); LOCAL void print_drflags __PR((cdr_t *dp)); LOCAL void print_wrmodes __PR((cdr_t *dp)); LOCAL BOOL check_wrmode __PR((cdr_t *dp, int wmode, int tflags)); @@ -261,6 +263,7 @@ int speed = -1; long flags = 0L; int blanktype = 0; + int formattype = 0; int i; int tracks = 0; int trackno; @@ -272,6 +275,9 @@ SCSI *scgp = NULL; char errstr[80]; BOOL gracedone = FALSE; + int ispacket; + BOOL is_cdwr = FALSE; + BOOL is_dvdwr = FALSE; #ifdef __EMX__ /* This gives wildcard expansion with Non-Posix shells with EMX */ @@ -280,14 +286,13 @@ save_args(ac, av); oeuid = geteuid(); /* Remember saved set uid */ - fillbytes(track, sizeof (track), '\0'); for (i = 0; i < MAX_TRACK+2; i++) track[i].track = track[i].trackno = i; track[0].tracktype = TOC_MASK; raise_fdlim(); - gargs(ac, av, &tracks, track, &dev, &timeout, &dp, &speed, &flags, - &blanktype); + ispacket = gargs(ac, av, &tracks, track, &dev, &timeout, &dp, &speed, &flags, + &blanktype, &formattype); if ((track[0].tracktype & TOC_MASK) == TOC_MASK) comerrno(EX_BAD, "Internal error: Bad TOC type.\n"); @@ -464,7 +469,6 @@ wait_input(); } - /* * Call scg_remote() to force loading the remote SCSI transport library * code that is located in librscg instead of the dummy remote routines @@ -482,12 +486,18 @@ */ if ((scgp = scg_open(dev, errstr, sizeof (errstr), debug, (flags & F_MSINFO) == 0 || lverbose)) == (SCSI *)0) { + if (dev != NULL || (flags & F_SCANBUS) == 0 || (scgp = scg_open("ATA", errstr, sizeof (errstr), + debug, (flags & F_MSINFO) == 0 || lverbose)) == (SCSI *)0) { errmsg("%s%sCannot open SCSI driver.\n", errstr, errstr[0]?". ":""); errmsgno(EX_BAD, "For possible targets try 'cdrecord -scanbus'.%s\n", geteuid() ? " Make sure you are root.":""); errmsgno(EX_BAD, "For possible transport specifiers try 'cdrecord dev=help'.\n"); exit(EX_BAD); + } else { + dev = "ATA"; + } } + /* * XXX Below this point we do not need root privilleges anymore. */ @@ -504,6 +514,7 @@ #endif comerr("Panic cannot set back effective uid.\n"); } + /* * WARNING: We now are no more able to do any privilleged operation * unless we have been called by root. @@ -579,6 +590,7 @@ comerr("Cannot reset target.\n"); exit(0); } + /* * First try to check which type of SCSI device we * have. @@ -619,6 +631,46 @@ } else if (!is_unknown_dev(scgp) && dp != get_cdrcmds(scgp)) { errmsgno(EX_BAD, "WARNING: Trying to use other driver on known device.\n"); } + is_mmc(scgp, &is_cdwr, &is_dvdwr); + if (ispacket) { + if (is_dvdwr) { + track[0].flags |= TI_PACKET; + /*XXX put here to only affect DVD writing, should be in gargs. + * however if set in args for all mode, packet writing is then + * broken for all disc as cdrecord assume that PACKET imply TAO which + * is not true at all???? */ + track[0].flags &= ~TI_TAO; + } + } + /* DVD does not support TAO */ + if (dp->is_dvd) { + printf("Using Session At Once (SAO) for DVD mode.\n"); + dp->cdr_flags |= F_SAO; + for (i = 0; i <= MAX_TRACK; i++) { + track[i].flags &= ~TI_TAO; + track[i].flags |= TI_SAO; + } + } + is_mmc(scgp, &is_cdwr, &is_dvdwr); + if (ispacket) { + if (is_dvdwr) { + track[0].flags |= TI_PACKET; + /*XXX put here to only affect DVD writing, should be in gargs. + * however if set in args for all mode, packet writing is then + * broken for all disc as cdrecord assume that PACKET imply TAO which + * is not true at all???? */ + track[0].flags &= ~TI_TAO; + } + } + /* DVD does not support TAO */ + if (dp->is_dvd) { + printf("Using Session At Once (SAO) for DVD mode.\n"); + dp->cdr_flags |= F_SAO; + for (i = 0; i <= MAX_TRACK; i++) { + track[i].flags &= ~TI_TAO; + track[i].flags |= TI_SAO; + } + } if (!is_cddrive(scgp)) comerrno(EX_BAD, "Sorry, no CD/DVD-Drive found on this target.\n"); @@ -644,13 +696,31 @@ dsp->ds_minbuf = 0xFFFF; dp->cdr_dstat = dsp; } + is_mmc(scgp, &is_cdwr, &is_dvdwr); + if (ispacket) { + if (is_dvdwr) { + track[0].flags |= TI_PACKET; + /*XXX put here to only affect DVD writing, should be in gargs. + * however if set in args for all mode, packet writing is then + * broken for all disc as cdrecord assume that PACKET imply TAO which + * is not true at all???? */ + track[0].flags &= ~TI_TAO; + } + } + /* DVD does not support TAO */ + if (dp->is_dvd) { + printf("Using Session At Once (SAO) for DVD mode.\n"); + dp->cdr_flags |= F_SAO; + for (i = 0; i <= MAX_TRACK; i++) { + track[i].flags &= ~TI_TAO; + track[i].flags |= TI_SAO; + } + } if ((flags & (F_MSINFO|F_TOC|F_LOAD|F_DLCK|F_EJECT)) == 0 || tracks > 0 || cuefilename != NULL) { - BOOL is_cdwr = FALSE; - BOOL is_dvdwr = FALSE; if ((dp->cdr_flags & CDR_ISREADER) != 0) { errmsgno(EX_BAD, @@ -660,7 +730,7 @@ if (!is_mmc(scgp, &is_cdwr, &is_dvdwr)) is_cdwr = TRUE; /* If it is not MMC, it must be a CD writer */ - if (is_dvdwr && !set_cdrcmds("mmc_dvd", (cdr_t **)NULL)) { + if (is_dvdwr && !set_cdrcmds("mmc_mdvd", (cdr_t **)NULL)) { errmsgno(EX_BAD, "This version of cdrecord does not include DVD-R/DVD-RW support code.\n"); errmsgno(EX_BAD, @@ -965,11 +1035,6 @@ print_toc(scgp, dp); comexit(0); } - if ((flags & F_FORMAT) != 0) { - errmsgno(EX_BAD, "Format option not implemented in this version.\n"); - comexit(EX_BAD); - } - #ifdef XXX if ((*dp->cdr_check_session)() < 0) { comexit(EX_BAD); @@ -1013,6 +1078,7 @@ if (setreuid(-1, oeuid) < 0) errmsg("Could set back effective uid.\n"); } + #endif /* * fork() here to start the extra process needed for @@ -1032,6 +1098,7 @@ if (setreuid(-1, getuid()) < 0) comerr("Panic cannot set back effective uid.\n"); } + #endif } if ((*dp->cdr_set_speed_dummy)(scgp, dp, &speed) < 0) { @@ -1173,6 +1240,15 @@ errs++; goto restore_it; } + + if (dp->profile == 0x2B && flags & F_SAO && tsize > 0) { + printf("Preparing middle zone location for this DVD+R dual layer disc\n"); + if (!dp->cdr_layer_split(scgp, dp, tsize)) { + errmsgno(EX_BAD, "Cannot send structure for middle zone location.\n"); + comexit(EX_BAD); + } + } + if (tracks > 0 && fs > 0l) { /* * Wait for the read-buffer to become full. @@ -1194,7 +1270,39 @@ if (gettimeofday(&starttime, (struct timezone *)0) < 0) errmsg("Cannot get start time\n"); - /* + if (flags & F_FORMAT) { + printf("cdrecord: media format asked\n"); + /* + * Do not abort if OPC failes. Just give it a chance + * for better laser power calibration than without OPC. + * + * Ricoh drives return with a vendor unique sense code. + * This is most likely because they refuse to do OPC + * on a non blank media. + */ + scgp->silent++; + do_opc(scgp, dp, flags); + scgp->silent--; + wait_unit_ready(scgp, 120); + if (gettimeofday(&starttime, (struct timezone *)0) < 0) + errmsg("Cannot get start time\n"); + + if ((*dp->cdr_format)(scgp, dp, formattype) < 0) { + errmsgno(EX_BAD, "Cannot format disk, aborting.\n"); + comexit(EX_BAD); + } + if (gettimeofday(&fixtime, (struct timezone *)0) < 0) + errmsg("Cannot get format time\n"); + if (lverbose) + prtimediff("Formatting time: ", &starttime, &fixtime); + + if (!wait_unit_ready(scgp, 240) || tracks == 0) { + comexit(0); + } + if (gettimeofday(&starttime, (struct timezone *)0) < 0) + errmsg("Cannot get start time\n"); + } + /* * Blank the media if we were requested to do so */ if (flags & F_BLANK) { @@ -1251,6 +1359,14 @@ trackno = 0; } scgp->silent--; + + /* If it is DVD, the information in TOC is fabricated :) + The real information is from read disk info command*/ + if((dp->cdr_dstat->ds_disktype&DT_DVD) && (dp->cdr_dstat->ds_trlast>0)){ + trackno=dp->cdr_dstat->ds_trlast-1; + printf("trackno=%d\n",trackno); + } + if ((tracks + trackno) > MAX_TRACK) { /* * XXX How many tracks are allowed on a DVD? @@ -1435,8 +1551,8 @@ if (gracetime > 999) gracetime = 999; - printf("Starting to write CD/DVD at speed %d in %s%s %s mode for %s session.\n", - (int)dp->cdr_dstat->ds_wspeed, + printf("Starting to write CD/DVD at speed %5.1f in %s%s %s mode for %s session.\n", + (float)dp->cdr_dstat->ds_wspeed, (dp->cdr_cmdflags & F_DUMMY) ? "dummy" : "real", (dp->cdr_cmdflags & F_FORCE) ? " force" : "", wm2name[dp->cdr_dstat->ds_wrmode], @@ -1552,6 +1668,7 @@ (tlast.tv_sec * 1.0 + tlast.tv_usec * 0.000001); if (fspeed > 999.0) fspeed = 999.0; + if (dp->is_dvd) fspeed /= 9; printf("Average write speed %5.1fx.\n", fspeed); } @@ -1606,7 +1723,7 @@ error("\t-checkdrive check if a driver for the drive is present\n"); error("\t-prcap print drive capabilities for MMC compliant drives\n"); error("\t-inq do an inquiry for the drive and exit\n"); - error("\t-scanbus scan the SCSI bus and exit\n"); + error("\t-scanbus scan the SCSI and IDE buses and exit\n"); error("\t-reset reset the SCSI bus with the cdrecorder (if possible)\n"); error("\t-abort send an abort sequence to the drive (may help if hung)\n"); error("\t-overburn allow to write more than the official size of a medium\n"); @@ -1614,7 +1731,8 @@ error("\t-useinfo use *.inf files to overwrite audio options.\n"); error("\tspeed=# set speed of drive\n"); error("\tblank=type blank a CD-RW disc (see blank=help)\n"); - error("\t-format format a CD-RW/DVD-RW/DVD+RW disc\n"); + error("\tformat format a CD-RW/DVD-RW/DVD+RW disc\n"); + error("\tformattype=# select the format method for DVD+RW disc\n"); #ifdef FIFO error("\tfs=# Set fifo size to # (0 to disable, default is %ld MB)\n", DEFAULT_FIFOSIZE/(1024L*1024L)); @@ -1700,6 +1818,18 @@ /* NOTREACHED */ } +LOCAL void +formattypeusage(ret) + int ret; +{ + error("Formating options:\n"); + error("\tfull\t\tstandard formating\n"); + error("\tbackground\t\tbackground formating\n"); + error("\tforce\t\tforce reformat\n"); + + exit(ret); + /* NOTREACHED */ +} /* ARGSUSED */ LOCAL void intr(sig) @@ -2169,6 +2299,7 @@ usleep(wt*1000); } #endif + if (dp->is_dvd) fspeed /= 9; printf(" %5.1fx", fspeed); printf("."); savbytes = (bytes >> 20) << 20; @@ -2186,6 +2317,7 @@ oper = per; flush(); } + #endif } while (tracksize < 0 || bytes_read < tracksize); @@ -2882,6 +3014,7 @@ long startsec = 0L; long endsec = 0L; dstat_t *dsp = dp->cdr_dstat; + int profile; scgp->silent++; (*dp->cdr_next_wr_address)(scgp, (track_t *)0, &startsec); @@ -2982,13 +3115,23 @@ /* * dsp->ds_maxblocks == 0 (disk capacity is unknown). */ - if (endsec >= (405000-300)) { /*<90 min disk*/ + profile = dp->profile; + if (endsec >= (4200000)) { + errmsgno(EX_BAD, + "ERROR: Could not manage to find medium size, and more than 8.0 GB of data.\n"); + goto toolarge; + } else if (profile != 0x2B) { + if (endsec >= (2300000)) { errmsgno(EX_BAD, - "Data will not fit on any disk.\n"); + "ERROR: Could not manage to find medium size, and more than 4.3 GB of data for a non dual layer disc.\n"); goto toolarge; - } else if (endsec >= (333000-150)) { /* 74 min disk*/ + } else if (endsec >= (405000-300)) { /*<90 min disk or DVD*/ + errmsgno(EX_BAD, + "WARNING: Could not manage to find medium size, and more than 90 mins of data.\n"); + } else if (endsec >= (333000-150)) { /* 74 min disk*/ errmsgno(EX_BAD, - "WARNING: Data may not fit on standard 74min disk.\n"); + "WARNING: Data may not fit on standard 74min disk.\n"); + } } } if (dsp->ds_maxblocks <= 0 || endsec <= dsp->ds_maxblocks) @@ -3059,7 +3202,7 @@ } char *opts = -"help,version,checkdrive,prcap,inq,scanbus,reset,abort,overburn,ignsize,useinfo,dev*,timeout#,driver*,driveropts*,setdropts,tsize&,padsize&,pregap&,defpregap&,speed#,load,lock,eject,dummy,msinfo,toc,atip,multi,fix,nofix,waiti,immed,debug#,d+,kdebug#,kd#,verbose+,v+,Verbose+,V+,x+,xd#,silent,s,audio,data,mode2,xa,xa1,xa2,xamix,cdi,isosize,nopreemp,preemp,nocopy,copy,nopad,pad,swab,fs&,ts&,blank&,format,pktsize#,packet,noclose,force,tao,dao,sao,raw,raw96r,raw96p,raw16,clone,scms,isrc*,mcn*,index*,cuefile*,textfile*,text,shorttrack,noshorttrack,gracetime#,minbuf#"; +"help,version,checkdrive,prcap,inq,scanbus,reset,abort,overburn,ignsize,useinfo,dev*,timeout#,driver*,driveropts*,setdropts,tsize&,padsize&,pregap&,defpregap&,speed#,load,lock,eject,dummy,msinfo,toc,atip,multi,fix,nofix,waiti,immed,debug#,d+,kdebug#,kd#,verbose+,v+,Verbose+,V+,x+,xd#,silent,s,audio,data,mode2,xa,xa1,xa2,xamix,cdi,isosize,nopreemp,preemp,nocopy,copy,nopad,pad,swab,fs&,ts&,blank&,format,formattype&,pktsize#,packet,noclose,force,tao,dao,sao,raw,raw96r,raw96p,raw16,clone,scms,isrc*,mcn*,index*,cuefile*,textfile*,text,shorttrack,noshorttrack,gracetime#,minbuf#"; /* * Defines used to find whether a write mode has been specified. @@ -3069,8 +3212,8 @@ #define M_RAW 4 /* Raw mode */ #define M_PACKET 8 /* Packed mode */ -LOCAL void -gargs(ac, av, tracksp, trackp, devp, timeoutp, dpp, speedp, flagsp, blankp) +LOCAL int +gargs(ac, av, tracksp, trackp, devp, timeoutp, dpp, speedp, flagsp, blankp, formatp) int ac; char **av; int *tracksp; @@ -3081,6 +3224,7 @@ int *speedp; long *flagsp; int *blankp; + int *formatp; { int cac; char * const*cav; @@ -3093,6 +3237,7 @@ char *textfile = NULL; long bltype = -1; int doformat = 0; + int formattype = -1; Llong tracksize; Llong padsize; long pregapsize; @@ -3208,7 +3353,7 @@ &nopreemp, &preemp, &nocopy, ©, &nopad, &pad, &bswab, getnum, &fs, getnum, &bufsize, - getbltype, &bltype, &doformat, &pktsize, + getbltype, &bltype, &doformat, getformattype, &formattype, &pktsize, &ispacket, &noclose, &force, &tao, &dao, &dao, &raw, &raw96r, &raw96p, &raw16, &clone, @@ -3289,8 +3434,14 @@ *flagsp |= F_BLANK; *blankp = bltype; } - if (doformat) - *flagsp |= F_FORMAT; + if (doformat > 0) { + *flagsp |= F_FORMAT; + *formatp |= FULL_FORMAT; + } + if (formattype >= 0) { + *flagsp |= F_FORMAT; + *formatp |= formattype; + } if (ispacket) wm |= M_PACKET; if (tao) @@ -3595,8 +3746,6 @@ errmsgno(EX_BAD, "No write mode specified.\n"); errmsgno(EX_BAD, "Asuming -tao mode.\n"); errmsgno(EX_BAD, "Future versions of cdrecord may have different drive dependent defaults.\n"); - errmsgno(EX_BAD, "Continuing in 5 seconds...\n"); - sleep(5); tao = 1; } tracks++; @@ -3737,14 +3886,14 @@ ((strncmp(*devp, "HELP", 4) == 0) || (strncmp(*devp, "help", 4) == 0))) { *flagsp |= F_CHECKDRIVE; /* Set this for not calling mlockall() */ - return; + return ispacket; } if (*flagsp & (F_LOAD|F_DLCK|F_SETDROPTS|F_MSINFO|F_TOC|F_PRATIP|F_FIX|F_VERSION|F_CHECKDRIVE|F_PRCAP|F_INQUIRY|F_SCANBUS|F_RESET|F_ABORT)) { if (tracks != 0) { errmsgno(EX_BAD, "No tracks allowed with this option\n"); susage(EX_BAD); } - return; + return ispacket; } *tracksp = tracks; if (*flagsp & F_SAO) { @@ -3773,12 +3922,13 @@ susage(EX_BAD); } cuefilename = cuefile; - return; + return ispacket; } if (tracks == 0 && (*flagsp & (F_LOAD|F_DLCK|F_EJECT|F_BLANK|F_FORMAT)) == 0) { errmsgno(EX_BAD, "No tracks specified. Need at least one.\n"); susage(EX_BAD); } + return ispacket; } LOCAL void @@ -4451,6 +4601,26 @@ return (TRUE); } +LOCAL int +getformattype(optstr, typep) + char *optstr; + long *typep; +{ + if (streql(optstr, "full")) { + *typep = FULL_FORMAT; + } else if (streql(optstr, "background")) { + *typep = BACKGROUND_FORMAT; + } else if (streql(optstr, "force")) { + *typep = FORCE_FORMAT; + } else if (streql(optstr, "help")) { + formattypeusage(0); + } else { + error("Illegal blanking type '%s'.\n", optstr); + formattypeusage(EX_BAD); + return (-1); + } + return (TRUE); +} LOCAL void print_drflags(dp) cdr_t *dp; @@ -4618,6 +4788,7 @@ int tflags; { dstat_t *dsp = dp->cdr_dstat; + int profile; if ((tflags & TI_PACKET) != 0) { dsp->ds_wrmode = WM_PACKET; @@ -4740,3 +4911,4 @@ } #endif } + --- cdrtools-2.01.01/cdrecord/cdrecord.h.dvd 2005-06-11 14:16:14.000000000 +0200 +++ cdrtools-2.01.01/cdrecord/cdrecord.h 2006-01-26 14:32:51.000000000 +0100 @@ -100,7 +100,7 @@ * start writing. */ #ifndef MIN_GRACE_TIME -#define MIN_GRACE_TIME 3 /* 3 seconds */ +#define MIN_GRACE_TIME 0 /* 3 seconds */ #endif #ifndef GRACE_TIME #define GRACE_TIME 9 /* 9 seconds */ @@ -464,6 +464,20 @@ #define BLANK_SESSION 0x06 /* Erase the last session */ /* + * Defines for formating DVD (custom values) + */ +#define FULL_FORMAT 0x00 /* Interactive format */ +#define BACKGROUND_FORMAT 0x01 /* Background format */ +#define FORCE_FORMAT 0x02 /* Force reformat */ + +/* + * Defines for formating DVD (custom values) + */ +#define FULL_FORMAT 0x00 /* Interactive format */ +#define BACKGROUND_FORMAT 0x01 /* Background format */ +#define FORCE_FORMAT 0x02 /* Force reformat */ + +/* * Useful definitions for audio tracks */ #define msample (44100 * 2) /* one 16bit audio sample */ @@ -578,6 +592,18 @@ #define DSF_NEED_FORMAT 0x0800 /* Disk needs to be formatted */ /* + * Definitions for disktype flags + */ +#define DT_CD 0x001 /*is a CD */ +#define DT_DVD 0x002 /*is a DVD */ + +/* + * Definitions for disktype flags + */ +#define DT_CD 0x001 /*is a CD */ +#define DT_DVD 0x002 /*is a DVD */ + +/* * Definitions for disk_status disk type * used in "ds_type". */ @@ -719,6 +745,9 @@ int (*cdr_opc) __PR((SCSI *scgp, caddr_t bp, int cnt, int doopc)); /* Do OPC */ int (*cdr_opt1) __PR((SCSI *scgp, cdr_t *)); /* do early option processing*/ int (*cdr_opt2) __PR((SCSI *scgp, cdr_t *)); /* do late option processing */ + int (*cdr_layer_split) __PR((SCSI *scgp, cdr_t *, long tsize)); /* calculate optimale split */ + int profile; + BOOL is_dvd; }; #endif @@ -913,12 +942,16 @@ extern int read_rzone_info __PR((SCSI *scgp, caddr_t bp, int cnt)); extern int reserve_tr_rzone __PR((SCSI *scgp, long size)); extern int read_dvd_structure __PR((SCSI *scgp, caddr_t bp, int cnt, int addr, int layer, int fmt)); +extern int send_dvd_structure __PR((SCSI *scgp, caddr_t bp, int cnt, int layer, int fmt)); extern int send_opc __PR((SCSI *scgp, caddr_t, int cnt, int doopc)); #define CL_TYPE_STOP_DEICE 0 /* Stop De-icing a DVD+RW Media */ #define CL_TYPE_TRACK 1 /* Close Track # */ #define CL_TYPE_SESSION 2 /* Close Session/Border / Stop backgrnd. format */ #define CL_TYPE_INTER_BORDER 3 /* Close intermediate Border */ +#define CL_TYPE_OPEN_SESSION 4 /* Close the Open Session and Record an Extended lead-out */ +#define CL_TYPE_FINALISE_MINRAD 5 /* Finalize the Disc with a Minimum Recorded Radius */ +#define CL_TYPE_FINALISE 6 /* Finalize the disc */ extern int scsi_close_tr_session __PR((SCSI *scgp, int type, int track, BOOL immed)); extern int read_master_cue __PR((SCSI *scgp, caddr_t bp, int sheet, int cnt)); extern int send_cue_sheet __PR((SCSI *scgp, caddr_t bp, long size)); --- cdrtools-2.01.01/cdrecord/drv_mmc.c.dvd 2006-01-12 00:07:26.000000000 +0100 +++ cdrtools-2.01.01/cdrecord/drv_mmc.c 2006-01-26 14:32:51.000000000 +0100 @@ -83,8 +83,11 @@ EXPORT char *hasdrvopt __PR((char *optstr, char *optname)); LOCAL cdr_t *identify_mmc __PR((SCSI *scgp, cdr_t *, struct scsi_inquiry *)); LOCAL int attach_mmc __PR((SCSI *scgp, cdr_t *)); +LOCAL int attach_mdvd __PR((SCSI *scgp, cdr_t *)); EXPORT int check_writemodes_mmc __PR((SCSI *scgp, cdr_t *dp)); +EXPORT int check_writemodes_mdvd __PR((SCSI *scgp, cdr_t *dp)); LOCAL int deflt_writemodes_mmc __PR((SCSI *scgp, BOOL reset_dummy)); +LOCAL int deflt_writemodes_mdvd __PR((SCSI *scgp, BOOL reset_dummy)); LOCAL int get_diskinfo __PR((SCSI *scgp, struct disk_info *dip)); LOCAL void di_to_dstat __PR((struct disk_info *dip, dstat_t *dsp)); LOCAL int get_atip __PR((SCSI *scgp, struct atipinfo *atp)); @@ -93,18 +96,27 @@ #endif LOCAL int init_mmc __PR((SCSI *scgp, cdr_t *dp)); LOCAL int getdisktype_mmc __PR((SCSI *scgp, cdr_t *dp)); +LOCAL int getdisktype_mdvd __PR((SCSI *scgp, cdr_t *dp)); LOCAL int speed_select_mmc __PR((SCSI *scgp, cdr_t *dp, int *speedp)); +LOCAL int speed_select_mdvd __PR((SCSI *scgp, cdr_t *dp, int *speedp)); LOCAL int mmc_set_speed __PR((SCSI *scgp, int readspeed, int writespeed, int rotctl)); LOCAL int next_wr_addr_mmc __PR((SCSI *scgp, track_t *trackp, long *ap)); +LOCAL int next_wr_addr_mdvd __PR((SCSI *scgp, track_t *trackp, long *ap)); LOCAL int write_leadin_mmc __PR((SCSI *scgp, cdr_t *dp, track_t *trackp)); LOCAL int open_track_mmc __PR((SCSI *scgp, cdr_t *dp, track_t *trackp)); +LOCAL int open_track_mdvd __PR((SCSI *scgp, cdr_t *dp, track_t *trackp)); LOCAL int close_track_mmc __PR((SCSI *scgp, cdr_t *dp, track_t *trackp)); +LOCAL int close_track_mdvd __PR((SCSI *scgp, cdr_t *dp, track_t *trackp)); LOCAL int open_session_mmc __PR((SCSI *scgp, cdr_t *dp, track_t *trackp)); +LOCAL int open_session_mdvd __PR((SCSI *scgp, cdr_t *dp, track_t *trackp)); LOCAL int waitfix_mmc __PR((SCSI *scgp, int secs)); LOCAL int fixate_mmc __PR((SCSI *scgp, cdr_t *dp, track_t *trackp)); +LOCAL int fixate_mdvd __PR((SCSI *scgp, cdr_t *dp, track_t *trackp)); LOCAL int blank_mmc __PR((SCSI *scgp, cdr_t *dp, long addr, int blanktype)); +LOCAL int format_mdvd __PR((SCSI *scgp, cdr_t *dp, int formattype)); LOCAL int send_opc_mmc __PR((SCSI *scgp, caddr_t, int cnt, int doopc)); LOCAL int opt1_mmc __PR((SCSI *scgp, cdr_t *dp)); +LOCAL int opt1_mdvd __PR((SCSI *scgp, cdr_t *dp)); LOCAL int opt2_mmc __PR((SCSI *scgp, cdr_t *dp)); LOCAL int scsi_sony_write __PR((SCSI *scgp, caddr_t bp, long sectaddr, long size, int blocks, BOOL islast)); LOCAL int gen_cue_mmc __PR((track_t *trackp, void *vcuep, BOOL needgap)); @@ -138,6 +150,7 @@ LOCAL int do_tattoo_yamaha __PR((SCSI *scgp, FILE *f)); LOCAL int yamaha_write_buffer __PR((SCSI *scgp, int mode, int bufferid, long offset, long parlen, void *buffer, long buflen)); +LOCAL int dvd_dual_layer_split __PR((SCSI *scgp, cdr_t *dp, long tsize)); #ifdef __needed__ LOCAL int @@ -201,6 +214,48 @@ opt2_mmc, }; +cdr_t cdr_mdvd = { + 0, 0, + CDR_SWABAUDIO, + CDR_CDRW_ALL, + 370,370, + "mmc_mdvd", + "generic SCSI-3/mmc DVD-R(W) driver", + 0, + (dstat_t *)0, + identify_mmc, + attach_mdvd, + init_mmc, + getdisktype_mdvd, + scsi_load, + scsi_unload, + read_buff_cap, + cmd_dummy, /* recovery_needed */ + (int(*)__PR((SCSI *, int)))cmd_dummy, /* recover */ + speed_select_mdvd, + select_secsize, + next_wr_addr_mdvd, + (int(*)__PR((SCSI *, Ulong)))cmd_ill, /* reserve_track */ + scsi_cdr_write, + (int(*)__PR((SCSI *scgp, int, track_t *)))cmd_dummy, /* gen_cue */ + (int(*)__PR((SCSI *scgp, cdr_t *, track_t *)))cmd_dummy, /* send_cue */ + write_leadin_mmc, + open_track_mdvd, + close_track_mdvd, + open_session_mdvd, + cmd_dummy, + cmd_dummy, /* abort */ + read_session_offset, + fixate_mdvd, + stats_mmc, + blank_mmc, + format_mdvd, + send_opc_mmc, + opt1_mdvd, + opt2_mmc, + dvd_dual_layer_split, +}; + /* * Sony MMC CD-writer */ @@ -568,7 +623,22 @@ if (profile >= 0) { if (lverbose) print_profiles(scgp); - if (profile == 0 || profile == 0x12 || profile > 0x19) { + if (profile == 0 || profile >= 0x10 && profile <= 0x15 || profile > 0x19) { + /* + * 10h DVD-ROM + * 11h DVD-R + * 12h DVD-RAM + * 13h DVD-RW (Restricted overwrite) + * 14h DVD-RW (Sequential recording) + * 1Ah DVD+RW + * 1Bh DVD+R + * 2Bh DVD+R DL + * + */ + if (profile == 0x11 || profile == 0x13 || profile == 0x14 || profile == 0x1A || profile == 0x1B || profile == 0x2B) { + is_dvd = TRUE; + dp = &cdr_mdvd; + } else { is_dvd = FALSE; dp = &cdr_cd; @@ -590,23 +660,8 @@ errmsgno(EX_BAD, "Found unsupported DVD-RAM media.\n"); return (dp); - } else { /* DVD+RW DVD+R */ - errmsgno(EX_BAD, - "Found DVD+ media but DVD+R/DVD+RW support code is missing.\n"); - errmsgno(EX_BAD, - "If you need DVD+R/DVD+RW support, ask the Author for cdrecord-ProDVD.\n"); - errmsgno(EX_BAD, - "Free test versions and free keys for personal use are at ftp://ftp.berlios.de/pub/cdrecord/ProDVD/\n"); - return (dp); } - } else if (profile >= 0x10 && profile < 0x18) { - errmsgno(EX_BAD, - "Found DVD media but DVD-R/DVD-RW support code is missing.\n"); - errmsgno(EX_BAD, - "If you need DVD-R/DVD-RW support, ask the Author for cdrecord-ProDVD.\n"); - errmsgno(EX_BAD, - "Free test versions and free keys for personal use are at ftp://ftp.berlios.de/pub/cdrecord/ProDVD/\n"); - return (dp); + } } } else { if (xdebug) @@ -673,13 +728,12 @@ #endif } if (is_dvd) { - errmsgno(EX_BAD, - "Found DVD media but DVD-R/DVD-RW support code is missing.\n"); - errmsgno(EX_BAD, - "If you need DVD-R/DVD-RW support, ask the Author for cdrecord-ProDVD.\n"); - errmsgno(EX_BAD, - "Free test versions and free keys for personal use are at ftp://ftp.berlios.de/pub/cdrecord/ProDVD/\n"); + errmsgno(EX_BAD, + "Found DVD media: using cdr_mdvd.\n"); + dp = &cdr_mdvd; } + dp->profile = profile; + dp->is_dvd = is_dvd; return (dp); } @@ -885,6 +939,42 @@ return (0); } +LOCAL int +attach_mdvd(scgp, dp) + SCSI *scgp; + cdr_t *dp; +{ + struct cd_mode_page_2A *mp; + + + allow_atapi(scgp, TRUE);/* Try to switch to 10 byte mode cmds */ + + scgp->silent++; + mp = mmc_cap(scgp, NULL);/* Get MMC capabilities in allocated mp */ + scgp->silent--; + if (mp == NULL) + return (-1); /* Pre SCSI-3/mmc drive */ + + dp->cdr_cdcap = mp; /* Store MMC cap pointer */ + + if (mp->loading_type == LT_TRAY) + dp->cdr_flags |= CDR_TRAYLOAD; + else if (mp->loading_type == LT_CADDY) + dp->cdr_flags |= CDR_CADDYLOAD; + + if (mp->BUF != 0) + dp->cdr_flags |= CDR_BURNFREE; + + check_writemodes_mdvd(scgp, dp); + + if (driveropts != NULL) { + if (strcmp(driveropts, "help") == 0) { + mmc_opthelp(dp, 0); + } + } + + return (0); +} EXPORT int check_writemodes_mmc(scgp, dp) @@ -956,8 +1046,6 @@ mp->fp = 0; i_to_4_byte(mp->packet_size, 0); mp->track_mode = TM_DATA; - - mp->write_type = WT_SAO; if (set_mode_params(scgp, "CD write parameter", mode, len, 0, -1)) { @@ -1035,6 +1123,77 @@ return (0); } +EXPORT int +check_writemodes_mdvd(scgp, dp) + SCSI *scgp; + cdr_t *dp; +{ + Uchar mode[0x100]; + int len; + struct cd_mode_page_05 *mp; + + if (xdebug) + printf("Checking possible write modes: "); + + deflt_writemodes_mdvd(scgp, FALSE); + + fillbytes((caddr_t)mode, sizeof(mode), '\0'); + + scgp->silent++; + if (!get_mode_params(scgp, 0x05, "DVD write parameter", + mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) { + scgp->silent--; + return (-1); + } + if (len == 0) { + scgp->silent--; + return (-1); + } + + mp = (struct cd_mode_page_05 *) + (mode + sizeof(struct scsi_mode_header) + + ((struct scsi_mode_header *)mode)->blockdesc_len); + + mp->test_write = 0; + + /*We only check for PACKET and SAO since these are the only supported modes for DVD */ + /*XXX these checks are irrelevant because they are not medium sensitive. ie the device returns + error only when it does not support a given mode for ALL mediums. It should check using + GET CONFIGURATION command.*/ + + mp->write_type = WT_PACKET; + mp->fp = 0; + i_to_4_byte(mp->packet_size, 0); + + if (set_mode_params(scgp, "DVD write parameter", mode, len, 0, -1)) { + dp->cdr_flags |= CDR_PACKET; + if (xdebug) + printf("PACKET "); + } else + dp->cdr_flags &= ~CDR_PACKET; + mp->fp = 0; + i_to_4_byte(mp->packet_size, 0); + mp->track_mode = TM_DATA; + + + mp->write_type = WT_SAO; + + if (set_mode_params(scgp, "CD write parameter", mode, len, 0, -1)) { + dp->cdr_flags |= CDR_SAO; + if (xdebug) + printf("SAO "); + } else + dp->cdr_flags &= ~CDR_SAO; + + + if (xdebug) + printf("\n"); + + deflt_writemodes_mdvd(scgp, TRUE); + scgp->silent--; + return (0); +} + LOCAL int deflt_writemodes_mmc(scgp, reset_dummy) SCSI *scgp; @@ -1109,6 +1268,61 @@ return (0); } +LOCAL int +deflt_writemodes_mdvd(scgp, reset_dummy) + SCSI *scgp; + BOOL reset_dummy; +{ + Uchar mode[0x100]; + int len; + struct cd_mode_page_05 *mp; + + fillbytes((caddr_t)mode, sizeof(mode), '\0'); + + scgp->silent++; + if (!get_mode_params(scgp, 0x05, "DVD write parameter", + mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) { + scgp->silent--; + return (-1); + } + if (len == 0) { + scgp->silent--; + return (-1); + } + + mp = (struct cd_mode_page_05 *) + (mode + sizeof(struct scsi_mode_header) + + ((struct scsi_mode_header *)mode)->blockdesc_len); + + mp->test_write = 0; + /* + * This is the only place where we reset mp->test_write (-dummy) + */ + if (reset_dummy) + mp->test_write = 0; + + + /* + * Set default values: + * Write type = 02 (session at once) + * + * XXX Note: the same code appears in check_writemodes_mmc() and + * XXX in speed_select_mmc(). + */ + mp->write_type = WT_SAO; + mp->track_mode = TM_DATA; + mp->dbtype = DB_ROM_MODE1; + mp->session_format = SES_DA_ROM; + + + if (set_mode_params(scgp, "DVD write parameter", mode, len, 0, -1) < 0) { + scgp->silent--; + return (-1); + } + scgp->silent--; + return (0); +} + #ifdef PRINT_ATIP LOCAL void print_di __PR((struct disk_info *dip)); LOCAL void atip_printspeed __PR((char *fmt, int speedindex, char speedtab[])); @@ -1178,6 +1392,9 @@ if (dsp->ds_last_leadout == 0 && dsp->ds_maxblocks >= 0) dsp->ds_last_leadout = dsp->ds_maxblocks; + dsp->ds_trfirst=dip->first_track; + dsp->ds_trlast=dip->last_track_ls; + dsp->ds_trfirst_ls=dip->first_track_ls; } LOCAL int @@ -1288,6 +1505,30 @@ } LOCAL int +getdisktype_mdvd(scgp, dp) + SCSI *scgp; + cdr_t *dp; +{ + int ret = 0; + dstat_t *dsp = dp->cdr_dstat; + + struct track_info track_info; + if(getdisktype_mmc(scgp, dp)<0) + return -1; + + /* read rzone info to get the space left on disk */ + /*ds_trlast is the last rzone on disk, can be invisible */ + if(read_rzone_info(scgp, (caddr_t)&track_info, sizeof(track_info))>=0) + dsp->ds_maxblocks=a_to_u_4_byte(track_info.free_blocks)+a_to_4_byte(track_info.next_writable_addr); + + dsp->ds_disktype&= ~DT_CD; + dsp->ds_disktype|= DT_DVD; + + return (ret); + +} + +LOCAL int getdisktype_mmc(scgp, dp) SCSI *scgp; cdr_t *dp; @@ -1299,6 +1540,7 @@ msf_t msf; BOOL did_atip = FALSE; BOOL did_dummy = FALSE; + int rplus; msf.msf_min = msf.msf_sec = msf.msf_frame = 0; @@ -1366,8 +1608,13 @@ /* * Check for non writable disk first. */ + + /* DVD+RW does not need to be blanked */ + rplus = dsp->ds_cdrflags; + if (dp->profile == 0x1A) rplus = RF_BLANK; + if (dip->disk_status == DS_COMPLETE && - (dsp->ds_cdrflags & (RF_WRITE|RF_BLANK)) == RF_WRITE) { + (rplus & dsp->ds_cdrflags & (RF_WRITE|RF_BLANK)) == RF_WRITE) { if (!did_dummy) { int xspeed = 0xFFFF; int oflags = dp->cdr_cmdflags; @@ -1731,6 +1978,7 @@ if (scsi_get_speed(scgp, 0, &val) >= 0) { if (val > 0) { + printf("Speed set to %d KB/s\n", val); curspeed = val / 176; *speedp = curspeed; } @@ -1793,6 +2041,68 @@ } LOCAL int +speed_select_mdvd(scgp, dp, speedp) + SCSI *scgp; + cdr_t *dp; + int *speedp; +{ + int retcode; + unsigned char perf_desc[28]; + int write_speed = *speedp * 1385; + int val = 0, val2 = 0; + int i; + + /* For the moment we just divide the CD speed by 7*/ + + if(speedp!=NULL) + (*speedp)=(*speedp)*8; + + memset(perf_desc, 0, sizeof(perf_desc)); + + /* Write Rotation Control = ROTCTL_CLV + * | Restore Logical Unit Defaults = 0 + * | Exact = 0 + * | Random Access = 0) + */ + perf_desc[0]= ROTCTL_CLV << 3 | 0 << 2 | 0 << 1 | 0; + /* Start LBA to 0 */ + perf_desc[4] = 0; + perf_desc[5] = 0; + perf_desc[6] = 0; + perf_desc[7] = 0; + /* End LBA set to 0 (setting to 0xffffffff failed on my LG burner + */ + perf_desc[8] = 0; + perf_desc[9] = 0; + perf_desc[10] = 0; + perf_desc[11] = 0; + /* Read Speed = 0xFFFF */ + perf_desc[12] = 0; + perf_desc[13] = 0; + perf_desc[14] = 0xFF; + perf_desc[15] = 0xFF; + /* Read Time = 1s */ + perf_desc[18] = 1000 >> 8; + perf_desc[19] = 1000 & 0xFF; + /* Write Speed */ + perf_desc[20] = write_speed >> 24; + perf_desc[21] = write_speed >> 16 & 0xFF; + perf_desc[22] = write_speed >> 8 & 0xFF; + perf_desc[23] = write_speed & 0xFF; + /* Write Time = 1s */ + perf_desc[26] = 1000 >> 8; + perf_desc[27] = 1000 & 0xFF; + + //retcode = scsi_set_streaming(scgp, NULL, 0); + retcode = scsi_set_streaming(scgp, &perf_desc, sizeof(perf_desc)); + if (retcode == -1) return retcode; + retcode = speed_select_mmc(scgp, dp, speedp); + if(speedp!=NULL) + (*speedp)=(*speedp)/7; + return retcode; +} + +LOCAL int next_wr_addr_mmc(scgp, trackp, ap) SCSI *scgp; track_t *trackp; @@ -1929,6 +2239,49 @@ }; LOCAL int +next_wr_addr_mdvd(scgp, trackp, ap) + SCSI *scgp; + track_t *trackp; + long *ap; +{ + int track=0; + struct track_info track_info; + long next_addr; + int result = -1; + struct disk_info disk_info; + if (trackp){ + track = trackp->trackno; + } + + if (trackp != 0 && track > 0 && is_packet(trackp)) { + scgp->silent++; + result = read_track_info(scgp, (caddr_t)&track_info, TI_TYPE_SESS, track, sizeof(track_info)); + scgp->silent--; + if (scsi_in_progress(scgp)){ + return -1; + } + + } + + if (result < 0) { + /* Get the last rzone*/ + if(read_disk_info(scgp,(caddr_t)&disk_info,8)<0) + return (-1); + + /* if (read_track_info(scgp, (caddr_t)&track_info, TI_TYPE_SESS, 0xFF, sizeof(track_info)) < 0) */ + if (read_rzone_info(scgp, (caddr_t)&track_info, sizeof(track_info)) < 0) + return (-1); + } + if (scgp->verbose) + scg_prbytes("track info:", (Uchar *)&track_info, + sizeof(track_info)-scg_getresid(scgp)); + next_addr = a_to_4_byte(track_info.next_writable_addr); + if (ap) + *ap = next_addr; + return (0); +} + +LOCAL int open_track_mmc(scgp, dp, trackp) SCSI *scgp; cdr_t *dp; @@ -2009,6 +2362,45 @@ } LOCAL int +open_track_mdvd(scgp, dp, trackp) + SCSI *scgp; + cdr_t *dp; + track_t *trackp; +{ + Uchar mode[0x100]; + int len; + struct cd_mode_page_05 *mp; + + if (is_packet(trackp)) { + fillbytes((caddr_t)mode, sizeof(mode), '\0'); + + if (!get_mode_params(scgp, 0x05, "DVD write parameter", + mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) + return (-1); + if (len == 0) + return (-1); + + mp = (struct cd_mode_page_05 *) + (mode + sizeof(struct scsi_mode_header) + + ((struct scsi_mode_header *)mode)->blockdesc_len); + + mp->write_type = WT_PACKET; + mp->LS_V = 1; + /*For now we set the link size to 0x10(32k) because Pioneer-A03 only support this */ + mp->link_size=0x10; + mp->fp = 1; + i_to_4_byte(mp->packet_size, trackp->pktsize); + } else { + return 0; + } + + if (!set_mode_params(scgp, "CD write parameter", mode, len, 0, trackp->secsize)) + return (-1); + + return (0); +} + +LOCAL int close_track_mmc(scgp, dp, trackp) SCSI *scgp; cdr_t *dp; @@ -2034,6 +2426,30 @@ return (0); } +LOCAL int +close_track_mdvd(scgp, dp, trackp) + SCSI *scgp; + cdr_t *dp; + track_t *trackp; +{ + int ret; + if (!is_packet(trackp)) + return (0); + + if (scsi_flush_cache(scgp, (dp->cdr_cmdflags&F_IMMED) != 0) < 0) { + printf("Trouble flushing the cache\n"); + return -1; + } + wait_unit_ready(scgp, 300); /* XXX Wait for ATAPI */ + if (is_packet(trackp) && !is_noclose(trackp)) { + /* close the incomplete track */ + ret = scsi_close_tr_session(scgp, 1, 0xFF, (dp->cdr_cmdflags&F_IMMED) != 0); + wait_unit_ready(scgp, 300); /* XXX Wait for ATAPI */ + return (ret); + } + return (0); +} + int toc2sess[] = { SES_DA_ROM, /* CD-DA */ SES_DA_ROM, /* CD-ROM */ @@ -2117,6 +2533,84 @@ } LOCAL int +open_session_mdvd(scgp, dp, trackp) + SCSI *scgp; + cdr_t *dp; + track_t *trackp; +{ + Uchar mode[0x100]; + int tracks = trackp->tracks; + + int len; + struct cd_mode_page_05 *mp; + Ulong totalsize; + int i; + struct track_info track_info; + int profile; + + fillbytes((caddr_t)mode, sizeof(mode), '\0'); + + if (!get_mode_params(scgp, 0x05, "DVD write parameter", + mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) + return (-1); + if (len == 0) + return (-1); + + mp = (struct cd_mode_page_05 *) + (mode + sizeof(struct scsi_mode_header) + + ((struct scsi_mode_header *)mode)->blockdesc_len); + if(is_packet(trackp)){ + mp->write_type=WT_PACKET; + mp->fp=0; + mp->BUFE=1; + mp->track_mode=1; + }else{ + mp->write_type = WT_SAO; + } + + mp->multi_session = (track_base(trackp)->tracktype & TOCF_MULTI) ? + MS_MULTI : MS_NONE; + mp->session_format = toc2sess[track_base(trackp)->tracktype & TOC_MASK]; + + if (lverbose && dp->cdr_cdcap->BUF != 0) + printf("BURN-Free is %s.\n", mp->BUFE?"ON":"OFF"); + if (driveropts != NULL) { + if ((strcmp(driveropts, "burnproof") == 0 || + strcmp(driveropts, "burnfree") == 0) && dp->cdr_cdcap->BUF != 0) { + errmsgno(EX_BAD, "Turning BURN-Free on\n"); + mp->BUFE = 1; + } else if ((strcmp(driveropts, "noburnproof") == 0 || + strcmp(driveropts, "noburnfree") == 0)) { + errmsgno(EX_BAD, "Turning BURN-Free off\n"); + mp->BUFE = 0; + } else if (strcmp(driveropts, "help") == 0) { + mmc_opthelp(dp, 0); + } else { + errmsgno(EX_BAD, "Bad driver opts '%s'.\n", driveropts); + mmc_opthelp(dp, EX_BAD); + } + } + + + if (!set_mode_params(scgp, "DVD write parameter", mode, len, 0, -1)) + return (-1); + + + totalsize=0; + for(i=1;i<=tracks;i++) { + totalsize+=trackp[i].tracksecs; + } + + profile = get_curprofile(scgp); + if(!is_packet(trackp) && profile != 0x1A){ + /* in DAO mode we need to reserve space for the track*/ + if(reserve_track(scgp, totalsize)<0) + return (-1); + } + return (0); +} + +LOCAL int waitfix_mmc(scgp, secs) SCSI *scgp; int secs; @@ -2155,6 +2649,7 @@ struct timeval stoptime; int dummy = (track_base(trackp)->tracktype & TOCF_DUMMY) != 0; + printf("fixate_mmc\n"); starttime.tv_sec = 0; starttime.tv_usec = 0; stoptime = starttime; @@ -2164,6 +2659,7 @@ printf("WARNING: Some drives don't like fixation in dummy mode.\n"); scgp->silent++; + printf("is_tao: %d,is_packet: %d\n", is_tao(trackp), is_packet(trackp)); if (is_tao(trackp) || is_packet(trackp)) { ret = scsi_close_tr_session(scgp, CL_TYPE_SESSION, 0, (dp->cdr_cmdflags&F_IMMED) != 0); @@ -2246,6 +2742,30 @@ return (ret); } +LOCAL int +fixate_mdvd(scgp, dp, trackp) + SCSI *scgp; + cdr_t *dp; + track_t *trackp; +{ + /*set a really BIG timeout and call fixate_mmc + The BIG timeout is needed in case there was a very short rzone to write at the + beginning of the disk, because lead-out needs to be at some distance. + */ + printf("fixate_mdvd\n"); + scg_settimeout(scgp, 1000); + if(is_packet(trackp) || dp->profile == 0x1B){ + scsi_close_tr_session(scgp, CL_TYPE_SESSION, 0, FALSE); + } + fixate_mmc(scgp, dp, trackp); + if (dp->profile == 0x2B) { + scsi_close_tr_session(scgp, CL_TYPE_OPEN_SESSION, 0, FALSE); + scsi_close_tr_session(scgp, CL_TYPE_FINALISE_MINRAD, 0, FALSE); + } + scg_settimeout(scgp, 200); + +} + char *blank_types[] = { "entire disk", "PMA, TOC, pregap", @@ -2257,6 +2777,12 @@ "reserved blanking type", }; +char *format_types[] = { + "full format", + "background format", + "forced format", +}; + LOCAL int blank_mmc(scgp, dp, addr, blanktype) SCSI *scgp; @@ -2269,11 +2795,16 @@ BOOL cdrrw = FALSE; /* Read CD-RW */ BOOL cdwrw = FALSE; /* Write CD-RW */ int ret; + int profile; mmc_check(scgp, &cdrr, &cdwr, &cdrrw, &cdwrw, NULL, NULL); if (!cdwrw) return (blank_dummy(scgp, dp, addr, blanktype)); + if (dp->profile == 0x1A) { + printf("Error: this media does not support blanking, ignoring.\n"); + return (blank_dummy(scgp, dp, addr, blanktype)); + } if (lverbose) { printf("Blanking %s\n", blank_types[blanktype & 0x07]); flush(); @@ -2289,6 +2820,80 @@ } LOCAL int +format_mdvd(scgp, dp, formattype) + SCSI *scgp; + cdr_t *dp; + int formattype; +{ +extern char *buf; + BOOL dvdwr = FALSE; /* Write DVD */ + int ret; + int profile; + char addr[12]; + struct disk_info *dip; + + printf("format_mdvd\n"); + mmc_check(scgp, NULL, NULL, NULL, NULL, NULL, &dvdwr); + if (!dvdwr) + return (format_dummy(scgp, dp, formattype)); + + printf("format_mdvd: drive is a dvd burner.\n"); + profile = get_curprofile(scgp); + if (profile != 0x1A) { + printf("Error: only support DVD+RW formating, ignoring.\n"); + return (format_dummy(scgp, dp, formattype)); + } + printf("format_mdvd: media is a DVD+RW.\n"); + dip = (struct disk_info *)buf; + if (get_diskinfo(scgp, dip) < 0) + return ret; + + if (dip->disk_status & 3 && formattype != FORCE_FORMAT) { + printf("Error: disk already formated, ignoring.\n"); + return ret; + } + addr[0] = 0; // "Reserved" + addr[1] = 2; // "IMMED" flag + addr[2] = 0; // "Descriptor Length" (MSB) + addr[3] = 8; // "Descriptor Length" (LSB) + addr[4+0] = 0xff; + addr[4+1] = 0xff; + addr[4+2] = 0xff; + addr[4+3] = 0xff; + addr[4+4] = 0x26<<2; + addr[4+5] = 0; + addr[4+6] = 0; + addr[4+7] = 0; + if (formattype == FORCE_FORMAT) { + printf("format_mdvd: forcing reformat.\n"); + formattype = FULL_FORMAT; + addr[4+0] = 0; + addr[4+1] = 0; + addr[4+2] = 0; + addr[4+3] = 0; + addr[4+7] = 1; + } else { + printf("format_mdvd: media is unformated.\n"); + } + + if (lverbose) { + printf("Formating %s\n", format_types[formattype & 0x07]); + flush(); + } + if (formattype == FULL_FORMAT) { + ret = scsi_format(scgp, &addr, sizeof(addr), FALSE); + } else { + ret = scsi_format(scgp, &addr, sizeof(addr), TRUE); + } + if (ret < 0) + return (ret); + + wait_unit_ready(scgp, 90*60/curspeed); /* XXX Wait for ATAPI */ + waitfix_mmc(scgp, 90*60/curspeed); /* XXX Wait for ATAPI */ + return (ret); +} + +LOCAL int send_opc_mmc(scgp, bp, cnt, doopc) SCSI *scgp; caddr_t bp; @@ -2518,6 +3123,43 @@ } LOCAL int +opt1_mdvd(scgp, dp) + SCSI *scgp; + cdr_t *dp; +{ + int oflags = dp->cdr_dstat->ds_cdrflags; + + if ((dp->cdr_dstat->ds_cdrflags & RF_AUDIOMASTER) != 0) { + printf("Turning Audio Master Q. R. on\n"); + if (set_audiomaster_yamaha(scgp, dp, TRUE) < 0) + return (-1); + if (!debug && lverbose <= 1) + dp->cdr_dstat->ds_cdrflags &= ~RF_PRATIP; + if (getdisktype_mdvd(scgp, dp) < 0) { + dp->cdr_dstat->ds_cdrflags = oflags; + return (-1); + } + dp->cdr_dstat->ds_cdrflags = oflags; + if (oflags & RF_PRATIP) { + msf_t msf; + lba_to_msf(dp->cdr_dstat->ds_first_leadin, &msf); + printf("New start of lead in: %ld (%02d:%02d/%02d)\n", + (long)dp->cdr_dstat->ds_first_leadin, + msf.msf_min, + msf.msf_sec, + msf.msf_frame); + lba_to_msf(dp->cdr_dstat->ds_maxblocks, &msf); + printf("New start of lead out: %ld (%02d:%02d/%02d)\n", + (long)dp->cdr_dstat->ds_maxblocks, + msf.msf_min, + msf.msf_sec, + msf.msf_frame); + } + } + return (0); +} + +LOCAL int scsi_sony_write(scgp, bp, sectaddr, size, blocks, islast) SCSI *scgp; caddr_t bp; /* address of buffer */ @@ -3780,3 +4422,48 @@ return (1); return (0); } + +LOCAL int +dvd_dual_layer_split(scgp, dp, tsize) + SCSI *scgp; + cdr_t *dp; + long tsize; +{ + unsigned char xb[12]; + int i; + long l0_size; + + /* Get the Layer 0 defined data zone*/ + if (read_dvd_structure(scgp, (caddr_t)xb, 12, 0, 0, 0x20) >= 0) { + if ((xb[1] | xb[0] << 8) < 13) { + error("dvd_dual_layer_split: read_dvd_structure returns invalid data\n"); + return 1; + } + if (xb[4] & 0x80) { + printf("L0 zone size already set\n"); + return 1; + } + l0_size = xb[11] | xb[10] << 8 | xb[9] << 16 | xb[8] << 24; + if (tsize < l0_size) { + error("track size smaller than one layer, use --force to force burning."); + return 0; + } + printf("L0 size: %l (track size %l)\n", l0_size, tsize); + l0_size = tsize / 2; + l0_size = l0_size - 1 + 16 - (l0_size - 1) % 16; + printf("New L0 size: %l\n", l0_size); + + memset (xb, 0, sizeof(xb)); + xb[1] = sizeof(xb) - 2; + xb[8] = l0_size >> 24; + xb[9] = l0_size >> 16; + xb[10] = l0_size >> 8; + xb[11] = l0_size; + if (send_dvd_structure(scgp, (caddr_t)xb, 12, 0, 0x20)) { + error("dvd_dual_layer_split: send_dvd_structure failed, could not set middle zone location.\n"); + return 0; + } + } + return 1; +} + --- cdrtools-2.01.01/cdrecord/scsi_cdr.c.dvd 2004-05-25 00:36:01.000000000 +0200 +++ cdrtools-2.01.01/cdrecord/scsi_cdr.c 2006-01-26 14:32:51.000000000 +0100 @@ -99,6 +99,7 @@ EXPORT int read_rzone_info __PR((SCSI *scgp, caddr_t bp, int cnt)); EXPORT int reserve_tr_rzone __PR((SCSI *scgp, long size)); EXPORT int read_dvd_structure __PR((SCSI *scgp, caddr_t bp, int cnt, int addr, int layer, int fmt)); +EXPORT int send_dvd_structure __PR((SCSI *scgp, caddr_t bp, int cnt, int layer, int fmt)); EXPORT int send_opc __PR((SCSI *scgp, caddr_t, int cnt, int doopc)); EXPORT int read_track_info_philips __PR((SCSI *scgp, caddr_t, int, int)); EXPORT int scsi_close_tr_session __PR((SCSI *scgp, int type, int track, BOOL immed)); @@ -106,6 +107,8 @@ EXPORT int send_cue_sheet __PR((SCSI *scgp, caddr_t bp, long size)); EXPORT int read_buff_cap __PR((SCSI *scgp, long *, long *)); EXPORT int scsi_blank __PR((SCSI *scgp, long addr, int blanktype, BOOL immed)); +EXPORT int scsi_format __PR((SCSI *scgp, caddr_t addr, int size, BOOL background)); +EXPORT int scsi_set_streaming __PR((SCSI *scgp, caddr_t addr, int size)); EXPORT BOOL allow_atapi __PR((SCSI *scgp, BOOL new)); EXPORT int mode_select __PR((SCSI *scgp, Uchar *, int, int, int)); EXPORT int mode_sense __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf)); @@ -518,6 +521,32 @@ } EXPORT int +scsi_set_streaming(scgp, perf_desc, size) + SCSI *scgp; + caddr_t perf_desc; + int size; +{ + register struct scg_cmd *scmd = scgp->scmd; + + fillbytes((caddr_t)scmd, sizeof (*scmd), '\0'); + scmd->addr = perf_desc; + scmd->size = size; + scmd->flags = SCG_DISRE_ENA; + scmd->cdb_len = SC_G5_CDBLEN; + scmd->sense_len = CCS_SENSE_LEN; + scmd->cdb.g5_cdb.cmd = 0xB6; + scmd->cdb.cmd_cdb[11] = 0; + scmd->cdb.cmd_cdb[10] = size; + + scgp->cmdname = "set streaming"; + + printf("scsi_set_streaming\n"); + if (scg_cmd(scgp) < 0) + return (-1); + return (0); +} + +EXPORT int scsi_set_speed(scgp, readspeed, writespeed, rotctl) SCSI *scgp; int readspeed; @@ -1042,6 +1071,31 @@ } EXPORT int +reserve_track(scgp, size) + SCSI *scgp; + Ulong size; + +{ + register struct scg_cmd *scmd = scgp->scmd; + + fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); + scmd->flags = SCG_DISRE_ENA; + scmd->cdb_len = SC_G1_CDBLEN; + scmd->sense_len = CCS_SENSE_LEN; + scmd->cdb.g1_cdb.cmd = 0x53; + scmd->cdb.g1_cdb.lun = scg_lun(scgp); + i_to_4_byte(&scmd->cdb.g1_cdb.addr[3], size); + + scgp->cmdname = "reserve track"; + + if (scg_cmd(scgp) < 0) + return (-1); + + return (0); + +} + +EXPORT int read_rzone_info(scgp, bp, cnt) SCSI *scgp; caddr_t bp; @@ -1108,6 +1162,36 @@ } EXPORT int +send_dvd_structure(scgp, bp, cnt, layer, fmt) + SCSI *scgp; + caddr_t bp; + int cnt; + int layer; + int fmt; +{ + register struct scg_cmd *scmd = scgp->scmd; + + fillbytes((caddr_t)scmd, sizeof (*scmd), '\0'); + scmd->addr = bp; + scmd->size = cnt; + scmd->flags = SCG_DISRE_ENA; + scmd->cdb_len = SC_G5_CDBLEN; + scmd->sense_len = CCS_SENSE_LEN; + scmd->timeout = 4 * 60; /* Needs up to 2 minutes ??? */ + scmd->cdb.g5_cdb.cmd = 0xBF; + scmd->cdb.g5_cdb.lun = scg_lun(scgp); + g5_cdblen(&scmd->cdb.g5_cdb, cnt); + + scmd->cdb.cmd_cdb[7] = fmt; + + scgp->cmdname = "send dvd structure"; + + if (scg_cmd(scgp) < 0) + return (-1); + return (0); +} + +EXPORT int send_opc(scgp, bp, cnt, doopc) SCSI *scgp; caddr_t bp; @@ -1322,6 +1406,71 @@ return (scg_cmd(scgp)); } +EXPORT int +scsi_format(scgp, addr, size, background) + SCSI *scgp; + caddr_t addr; + int size; + BOOL background; +{ + register struct scg_cmd *scmd = scgp->scmd; + int progress=0, ret=-1, pid=-1; + unsigned char sense_table[18]; + int i; + + printf("scsi_format: preparing\n"); + + fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); + scmd->addr = addr; + scmd->size = size; + scmd->flags = SCG_DISRE_ENA; + scmd->cdb_len = SC_G5_CDBLEN; + scmd->sense_len = CCS_SENSE_LEN; + scmd->timeout = 160 * 60; /* Do not know what to set */ + scmd->cdb.g5_cdb.cmd = 0x04; /* Format Unit */ + scmd->cdb.cmd_cdb[1] = 0x11; /* "FmtData" and "Format Code" */ + scmd->cdb.cmd_cdb[5] = 0; + + scgp->cmdname = "format unit"; + + printf("scsi_format: running\n"); + ret = (scg_cmd(scgp)); + printf("scsi_format: post processing %d\n", ret); + if (ret == -1) return ret; + if (background) { + if ((pid=fork()) == (pid_t)-1) + perror ("- [unable to fork()]"); + else { + if (!pid) { + while (1) { + if (test_unit_ready(scgp) >= 0) + break; + sleep(1); + } + return ret; + } + } + } + printf("Formating in progress: 0.00 %% done."); + sleep(20); + i = 0; + while (progress < 0xfff0 && !(progress == 0 && i > 50)) { + test_unit_ready(scgp); + request_sense_b(scgp, (caddr_t)sense_table, 18); + progress = sense_table[16]<<8|sense_table[17]; + printf("\rFormating in progress: %.2f %% done [%d]. ", (float)(progress*100)/0x10000,progress); + usleep(100000); + i++; + /*for (i=0; i < 18; i++) { + printf("%d ", sense_table[i]); + }*/ + } + sleep(10); + printf("\rFormating in progress: 100.00 %% done. \n"); + if (pid) exit (0); + return ret; +} + /* * XXX First try to handle ATAPI: * XXX ATAPI cannot handle SCSI 6 byte commands.