⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 growisofs_mmc.cpp

📁 最新的linux下dvd刻录软件,支持DVD+RW、DVD-RW光盘刻录。
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	    {	if (track[7]&1)	// NWA_V		{   next_wr_addr  = track[12]<<24;		    next_wr_addr |= track[13]<<16;		    next_wr_addr |= track[14]<<8;		    next_wr_addr |= track[15];		    if (lba<next_wr_addr && (lba+nbl)>next_wr_addr)		    {	nbl  -= next_wr_addr-lba,			size -= (next_wr_addr-lba)<<11,			buff += (next_wr_addr-lba)<<11,			lba   = next_wr_addr;			continue;		    }		}	    }	}#endif	if (errcode==0x20408)		// "LONG WRITE IN PROGRESS"	{   // Apparently only Pioneer units do this...	    if (velocity == 0)	    {	if (handle_events(cmd) & (1<<6))		    continue;		goto sync_cache;	    }	    cmd[0] = 0x5C;		// READ BUFFER CAPACITY	    cmd[8] = sizeof(bcap);	    cmd[9] = 0;	    if (cmd.transport (READ,bcap,sizeof(bcap)))		bfree=0, bsize=buf_size;	    else	    {	bsize = bcap[4]<<24|bcap[5]<<16|bcap[6]<<8|bcap[7];		bfree = bcap[8]<<24|bcap[9]<<16|bcap[10]<<8|bcap[11];		bsize /= 1024, bfree /= 1024;	// xlate to KB	    }	    // check for sanity and drain 1/2 of the buffer	    if (bsize < buf_size/2)	bsize = buf_size/2;	    else			bsize /= 2;	    if (bfree > bsize)		bfree = bsize;	    int msecs=0;	    if ((msecs=(bsize-bfree)*1000) > velocity)	    {	msecs /= velocity;		retries++;		if (dao_toggle) dao_toggle=-1;	    }	    else	// lots of free buffer reported?	    {	if (dao_toggle)		{   dao_toggle=-1;		    if ((handle_events(cmd) & (1<<6)))			continue;		    msecs = bsize*1000;		    msecs /= velocity;		}		else if (!retries++)	continue;		// Pioneer units seem to return bogus values at high		// velocities now and then... I reserve for 4 ECC		// blocks, which is ~6 ms at 16x. But note that some		// OSes, Linux 2.4 among then, will nap for 10 or 20.		msecs = (4*32*1000)/velocity;	    }	    // Retry values were increased because high-speed units	    // start recordings at only portion of velocity and it	    // takes more retries to write lead-in... Another common	    // reason for stucks are recalibrations at zone edges...	    if (retries > (dao_toggle?768:192))		fprintf (stderr,":-? the LUN appears to be stuck "				"writing LBA=%xh, keep retrying in %dms\n",				lba,msecs),		retries=1;	    if (msecs>=0)	    {	poll (NULL,0,msecs);		continue;	    }	    lba |= 0x80000000;		// signal insane bfree...	}	else if (lba==0 && errcode==0x20401)	// "IN PROCESS OF BECOMING READY"	{   if ((handle_events(cmd) & (1<<6)))		continue;	    if (++retries > 3)	    {	fprintf (stderr,":-! the LUN is still in process of becoming ready, "		    		    "retrying in 5 secs...\n"),		retries=0;		sigs_mask (SIGS_UNBLOCK);		poll (NULL,0,5000);	    }	    else	    	sigs_mask (SIGS_UNBLOCK),		poll (NULL,0,stdnap);	    continue;	}	else if (errcode==0x20404 ||	// "FORMAT IN PROGRESS"		 errcode==0x20407 ||	// "OPERATION IN PROGRESS"		 errcode==0x52C00)	// "COMMAND SEQUENCE ERROR"	{   // Happens under automounter control? In general I recommend	    // to disable it! This code is a tribute to users who disregard	    // the instructions...	sync_cache:	    // should I check if lba+nbl is multiple of 64K in BD case?	    cmd[0] = 0x35;	// SYNC CACHE	    cmd[9] = 0;	    if (!cmd.transport())	    {	if (++retries > 1)	    	{   fprintf (stderr,":-! the LUN appears to be stuck at %xh, "		    		    "retrying in 5 secs...\n",lba),		    retries=0;		    sigs_mask (SIGS_UNBLOCK);		    poll (NULL,0,5000);		}		else if (errcode==0x52C00)		    fprintf (stderr,":-! \"COMMAND SEQUENCE ERROR\"@LBA=%xh. "				    "Is media being read?\n",lba);		continue;	    }	    lba |= 0x40000000;	// signal "can't SYNC CACHE"	}	{ char cmdname[64];	    sprintf (cmdname,"WRITE@LBA=%xh",lba),	    sperror (cmdname,errcode);	}	if (lba==0)	{   if (ASC(errcode)==0x30)		fprintf (stderr,":-( media is not formatted or unsupported.\n");	    else if ((mmc_profile&0xFFFF)==0x14 /*&& ASC(errcode)==0x64*/)		fprintf (stderr,":-( attempt to re-run with "				"-dvd-compat -dvd-compat to engage DAO or "				"apply full blanking procedure\n");	}#if 1	// safety net: leave DL sessions open and resumable...	if ((mmc_profile&0xFFFF)==0x2B && errcode!=0x52100) media_written=0;#endif	return -1;    }    next_wr_addr = lba+nbl;    media_written = 1;    if (dao_toggle<0) dao_toggle=0;  return size;}// spare == -1	"format without spare"// spare == 0	"format with minimal spare"// spare >  0	"format with default descriptor"static void bd_r_format (Scsi_Command &cmd){ int err,i,len;  unsigned char descr[12],*f;    if (spare < 0)	return;	// no format -> no spare area:-)    len = formats[3];    if (spare == 0)	// locate descriptor with maximum capacity    { unsigned int max,cap;      int j;	i = 0;	for (max=0,j=8;j<len;j+=8)	{   f = formats+4+j;	    if ((f[4]>>2) == 0x32)	    {	cap = f[0]<<24|f[1]<<16|f[2]<<8|f[3];		if (max < cap) max=cap,i=j;	    }	}	if (i==0)	    fprintf (stderr,":-( can't locate format 0x32 descriptor\n"),	    exit (FATAL_START(errno=EMEDIUMTYPE));    }    else	i = 8;	// grab default descriptor    memset (descr,0,sizeof(descr));    descr[1]=0x02;	// "IMMED" flag    descr[3]=0x08;	// "Descriptor Lenght" (LSB)    memcpy (descr+4,formats+4+i,5);    descr[4+4]&=~3;	// ensure "Format Subtype" is set to SRM+POW     f = descr+4;    fprintf (stderr,"%s: pre-formatting blank BD-R for %.1fGB...\n",		    ioctl_device,(f[0]<<24|f[1]<<16|f[2]<<8|f[3])*2048.0/1e9);    cmd[0] = 0x04;	// FORMAT UNIT    cmd[1] = 0x11;	// "FmtData" and "Format Code"    cmd[5] = 0;    if ((err=cmd.transport(WRITE,descr,sizeof(descr))))	sperror ("FORMAT UNIT",err),	exit (FATAL_START(errno));    wait_for_unit (cmd);    cmd[0] = 0x35;	// FLUSH CACHE    cmd[9] = 0;    cmd.transport();}static void bd_re_format (Scsi_Command &cmd){ int err,i,len;  unsigned char descr[12],*f;    len = formats[3];    if (spare == 0)	// locate descriptor with maximum capacity    { unsigned int max,cap;      int j;	i = 0;	for (max=0,j=8;j<len;j+=8)	{   f = formats+4+j;	    if ((f[4]>>2) == 0x30)	    {	cap = f[0]<<24|f[1]<<16|f[2]<<8|f[3];		if (max < cap) max=cap,i=j;	    }	}	if (i==0)	    fprintf (stderr,":-( can't locate format 0x30 descriptor\n"),	    exit (FATAL_START(errno=EMEDIUMTYPE));    }    else if (spare < 0)	// locate descriptor 0x31    {	for (i=8;i<len;i+=8)	    if ((formats[4+i+4]>>2) == 0x31) break;	if (i==len)	    fprintf (stderr,":-( can't locate format 0x31 descriptor\n"),	    exit (FATAL_START(errno=EMEDIUMTYPE));    }    else	i = 8;	// grab default descriptor    memset (descr,0,sizeof(descr));    descr[1]=0x02;	// "IMMED" flag    descr[3]=0x08;	// "Descriptor Lenght" (LSB)    memcpy (descr+4,formats+4+i,5);    f = descr+4;    fprintf (stderr,"%s: pre-formatting blank BD-RE for %.1fGB...\n",		    ioctl_device,(f[0]<<24|f[1]<<16|f[2]<<8|f[3])*2048.0/1e9);    cmd[0] = 0x04;	// FORMAT UNIT    cmd[1] = 0x11;	// "FmtData" and "Format Code"    cmd[5] = 0;    if ((err=cmd.transport(WRITE,descr,sizeof(descr))))	sperror ("FORMAT UNIT",err),	exit(FATAL_START(errno));    wait_for_unit (cmd);    cmd[0] = 0x35;	// FLUSH CACHE    cmd[9] = 0;    cmd.transport();}static void plus_rw_format (Scsi_Command &cmd){ int err,i,len;  unsigned char descr[12];    if ((formats[4+4]&3) == 1)	// Unformatted media    {	fprintf (stderr,"%s: pre-formatting blank DVD+RW...\n",ioctl_device);	for (i=8,len=formats[3];i<len;i+=8)	    if ((formats [4+i+4]>>2) == 0x26) break;	if (i==len)	    fprintf (stderr,":-( can't locate DVD+RW format descriptor\n"),	    exit(FATAL_START(EMEDIUMTYPE));	memset (descr,0,sizeof(descr));	descr[1]=0x02;		// "IMMED" flag	descr[3]=0x08;		// "Descriptor Length" (LSB)	memcpy (descr+4,formats+4+i,4);	descr[8]=0x26<<2;	// "Format type" 0x26	cmd[0] = 0x04;		// FORMAT UNIT	cmd[1] = 0x11;		// "FmtData" and "Format Code"	cmd[5] = 0;	if ((err=cmd.transport(WRITE,descr,sizeof(descr))))	    sperror ("FORMAT UNIT",err),	    exit(FATAL_START(errno));	wait_for_unit (cmd);	cmd[0] = 0x35;		// FLUSH CACHE	cmd[9] = 0;	if ((err=cmd.transport()))	    sperror ("FLUSH CACHE",err),	    exit(FATAL_START(errno));    }}static int plus_rw_restart_format (Scsi_Command &cmd, off64_t size){ unsigned char descr[12];  unsigned int lead_out,blocks;  int err,i,len;    if (!dvd_compat && size!=0)    {	blocks = size/2048;	blocks += 15, blocks &= ~15;	lead_out = 0;	lead_out |= formats[4+0], lead_out <<= 8;	lead_out |= formats[4+1], lead_out <<= 8;	lead_out |= formats[4+2], lead_out <<= 8;	lead_out |= formats[4+3];	if (blocks<=lead_out)   // no need to resume format...	    return 0;    }    fprintf (stderr,"%s: restarting DVD+RW format...\n",ioctl_device);    for (i=8,len=formats[3];i<len;i+=8)	if ((formats [4+i+4]>>2) == 0x26) break;    if (i==len)	fprintf (stderr,":-( can't locate DVD+RW format descriptor\n"),	exit(FATAL_START(EMEDIUMTYPE));    memset (descr,0,sizeof(descr));    descr[1]=0x02;		// "IMMED" flag    descr[3]=0x08;		// "Descriptor Length" (LSB)#if 1    memcpy (descr+4,formats+4+i,4);#else    memset (descr+4,-1,4);#endif    descr[8]=0x26<<2;		// "Format type" 0x26    descr[11]=1;		// "Restart Format"    cmd[0] = 0x04;		// FORMAT UNIT    cmd[1] = 0x11;		// "FmtData" and "Format Code"    cmd[5] = 0;    if ((err=cmd.transport(WRITE,descr,sizeof(descr))))    {	sperror ("RESTART FORMAT",err);	return 1;    }    wait_for_unit(cmd);  return 0;}extern "C"int plusminus_r_C_parm (void *fd,char *C_parm){ unsigned int next_session, prev_session,err;  Scsi_Command cmd(fd);  unsigned char buf[36];    if ((disc_info[2]&3) != 1)	fprintf (stderr,":-( media is not appendable\n"),	exit(FATAL_START(EMEDIUMTYPE));    // allow to resume even --v-- incomplete sessions //    if (((disc_info[2]>>2)&3) > 1)	fprintf (stderr,":-( last session is not empty\n"),	exit(FATAL_START(EMEDIUMTYPE));    if (mmc_profile==0x41 && bdr_plus_pow)	next_track = disc_info[6]|disc_info[11]<<8;    else	next_track = disc_info[5]|disc_info[10]<<8;#if defined(__APPLE__) && defined(__MACH__)    err = MMCIO(fd,ReadTrackInformation,1,next_track,buf,sizeof(buf));#else    cmd[0] = 0x52;		// READ TRACK INFORMATION    cmd[1] = 1;    cmd[4] = next_track>>8;    cmd[5] = next_track;	// ask for last track    cmd[8] = sizeof(buf);    cmd[9] = 0;    err = cmd.transport (READ,buf,sizeof(buf));#endif    if (err)    {	sperror ("READ TRACK INFORMATION",err);	if (ASC(err)==0x24) // hp dvd200i returns 24 if media is full	    fprintf (stderr,":-( media must be full already\n");	exit (FATAL_START(errno));    }    if (mmc_profile==0x41 && bdr_plus_pow && buf[7]&1)		// NWA_V    {	next_session  = buf[12]<<24;	next_session |= buf[13]<<16;	next_session |= buf[14]<<8;	next_session |= buf[15];    }    else    {	next_session  = buf[8]<<24;	// Track Start Address	next_session |= buf[9]<<16;	next_session |= buf[10]<<8;	next_session |= buf[11];    }    if (mmc_profile==0x41 && bdr_plus_pow)	prev_session=0;    else    {	//	// All manuals say the data is fabricated, presumably implying	// that one should use another command. But we stick to this one	// because kernel uses this very command to mount multi-session	// discs.	//#if defined(__APPLE__) && defined(__MACH__)	err = MMCIO(fd,ReadTableOfContents,0,1,0,buf,12);#else	cmd[0] = 0x43;		// READ TOC	cmd[2] = 1;		// "Session info"	cmd[8] = 12;	cmd[9] = 0;	err = cmd.transport (READ,buf,12);#endif	if (err)	    sperror ("READ SESSION INFO",err),	    exit (FATAL_START(errno));	prev_session  = buf[8]<<24;	prev_session |= buf[9]<<16;	prev_session |= buf[10]<<8;	prev_session |= buf[11];    }    sprintf (C_parm,"%d,%d",prev_session+16,next_session);  return next_session;}static unsigned char *pull_page2A (Scsi_Command &cmd){ unsigned char *page2A,header[12];  unsigned int   len,bdlen;  int            err;    cmd[0] = 0x5A;		// MODE SENSE    cmd[1] = 0x08;		// "Disable Block Descriptors"    cmd[2] = 0x2A;		// "Capabilities and Mechanical Status"    cmd[8] = sizeof(header);	// header only to start with    cmd[9] = 0;    if ((err=cmd.transport(READ,header,sizeof(header))))	sperror ("MODE SENSE#2A",err), exit(FATAL_START(errno));    len   = (header[0]<<8|header[1])+2;    bdlen = header[6]<<8|header[7];    if (bdlen)	// should never happen as we set "DBD" above    {	if (len < (8+bdlen+30))	    fprintf (stderr,":-( LUN is impossible to bear with...\n"),	    exit(FATAL_START(EINVAL));    }    else if (len < (8+2+(unsigned int)header[9]))// SANYO does this.	len = 8+2+header[9];    page2A = (unsigned char *)malloc(len);    if (page2A == NULL)	fprintf (stderr,":-( memory exhausted\n"), exit(FATAL_START(ENOMEM));    cmd[0] = 0x5A;		// MODE SENSE    cmd[1] = 0x08;		// "Disable Block Descriptors"    cmd[2] = 0x2A;		// "Capabilities and Mechanical Status"    cmd[7] = len>>8;    cmd[8] = len;		// real length this time    cmd[9] = 0;    if ((err=cmd.transport(READ,page2A,len)))	sperror ("MODE SENSE#2A",err),	exit(FATAL_START(errno));    len -= 2;    if (len < ((unsigned int)page2A[0]<<8|page2A[1]))	// paranoia:-)	page2A[0] = len>>8, page2A[1] = len;  return page2A;}static int pull_velocity (Scsi_Command &cmd,unsigned char *d){ unsigned int len;  int v,err;  class autofree perf;#if 0	// 8x AccessTek derivatives, such as OptoRite DD0405    if ((d[4]&2) == 0)	return -1;#endif    len = (d[0]<<24|d[1]<<16|d[2]<<8|d[3])-4;    if (len%16)		return -1;    if (len==0)		return -1;	// LG GCA-4040N:-(    len += 8;    if (len == (8+16))    {	velocity = d[8+ 4]<<24|d[8+ 5]<<16|d[8+ 6]<<8|d[8+ 7];	v =        d[8+12]<<24|d[8+13]<<16|d[8+14]<<8|d[8+15];	if (v>velocity) velocity=v;	// CAV?    }    else	// ZCLV    { unsigned int n = (len-8)/16;      unsigned char *p;	perf = (unsigned char *)malloc (len);	if (perf == NULL)	    fprintf (stderr,":-( memory exhausted\n"),	    exit(FATAL_START(ENOMEM));	cmd[0]=0xAC;	// GET PERFORMANCE	cmd[1]=4;	// ask for "Overall Write Performance"	cmd[8]=n>>8;	cmd[9]=n;	// real number of descriptors	cmd[10]=0;	// ask for descriptor in effect	cmd[11]=0;	if ((err=cmd.transport(READ,perf,len)))	    sperror ("GET CURRENT PERFORMANCE",err),	    exit (FATAL_START(errno));	// Pick the highest speed...	for (p=perf+8,len-=8;len;p+=16,len-=16)	{   v=p[ 4]<<24|p[ 5]<<16|p[ 6]<<8|p[ 7];	    if (v > velocity) velocity = v;	    v=p[12]<<24|p[13]<<16|p[14]<<8|p[15];	    if (v > velocity) velocity = v;	// ZCAV?	}    }  return 0;}static int set_speed_B6h (Scsi_Command &cmd,unsigned int dvdplus,			  unsigned char *page2A){ unsigned int len;  int err;  unsigned char d[8+16];  class autofree perf;    cmd[0]=0xAC;		// GET PERFORMACE    cmd[9]=1;			// start with one descriptor    cmd[10]=0x3;		// ask for "Write Speed Descriptor"    cmd[11]=0;    if ((err=cmd.transport(READ,d,sizeof(d))))    {	sperror ("GET PERFORMANCE",err);	fprintf (stderr,":-( falling down to SET CD SPEED\n");	return -1;    }    len = (d[0]<<24|d[1]<<16|d[2]<<8|d[3])-4;    if (len%16)			// insane length    {	fprintf (stderr,":-( GET PERFORMANCE: insane Performance Data Length\n");	return -1;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -