📄 growisofs_mmc.cpp
字号:
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 + -