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

📄 growisofs_mmc.cpp

📁 linux平台下的dvd刻录软件
💻 CPP
📖 第 1 页 / 共 4 页
字号:
			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;	    }	    if (retries > (dao_toggle?192:96))		fprintf (stderr,":-? the LUN appears to be stuck "				"writing LBA=%xh, retry in %dms\n",				lba,msecs),		retries=0, msecs--;	    if (msecs>=0)	    {	poll (NULL,0,msecs);		continue;	    }	    lba |= 0x80000000;		// signal insane bfree...	}	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:	    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 (SIG_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;}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));    next_track = disc_info[5]|disc_info[10]<<8;    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;    if ((err=cmd.transport (READ,buf,sizeof(buf))))    {	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 0    if (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	fprintf (stderr,":-( Next Writable Address is invalid\n"),	exit(FATAL_START(EMEDIUMTYPE));#else    next_session  = buf[8]<<24;	// Track Start Address    next_session |= buf[9]<<16;    next_session |= buf[10]<<8;    next_session |= buf[11];#endif    //    // 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.    //    cmd[0] = 0x43;		// READ TOC    cmd[2] = 1;			// "Session info"    cmd[8] = 12;    cmd[9] = 0;    if ((err=cmd.transport (READ,buf,12)))	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 dvddash,			  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;    }    perf = (unsigned char *)malloc(len+=8);    if (perf == NULL)	fprintf (stderr,":-( memory exhausted\n"),	exit(FATAL_START(ENOMEM));    if (len == sizeof(d))	memcpy (perf,d,sizeof(d));    else    { unsigned int n=(len-8)/16;	cmd[0]=0xAC;		// GET PERFORMANCE	cmd[8]=n>>8;	cmd[9]=n;		// real number of descriptors	cmd[10]=0x3;		// ask for "Write Speed Descriptor"	cmd[11]=0;	if ((err=cmd.transport(READ,perf,len)))	    sperror ("GET PERFORMANCE",err),	    exit (FATAL_START(errno));    }    int targetv=0,errp=0;    do {	memset (d,0,sizeof(d));	cmd[0]=0xAC;		// GET PERFORMANCE	cmd[1]=4;		// ask for "Overall Write performance"	cmd[9]=1;	cmd[10]=0;		// ask for descriptor in effect	cmd[11]=0;	if (errp || (errp=cmd.transport(READ,d,sizeof(d))))#if 0	    sperror ("GET CURRENT PERFORMANCE",errp),	    exit (FATAL_START(errno));	// well, if it passed above, we					// expect it to pass this too...#else	// Pioneer doesn't report current speed through GET PERFORMANCE:-(	{   emulated_err:	    if (page2A == NULL)	return -1;	    unsigned int  plen,hlen;	    plen = (page2A[0]<<8|page2A[1]) + 2;	    hlen = 8 + (page2A[6]<<8|page2A[7]);	    unsigned char * const p = page2A + hlen;	    if (plen<(hlen+32) || p[1]<(32-2))		return -1;	// well, SET CD SPEED wouldn't work...	    velocity = p[28]<<8|p[29];	}

⌨️ 快捷键说明

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