📄 growisofs_mmc.cpp
字号:
dvd_20[10] = blocks>>8; dvd_20[11] = blocks; cmd[0] = 0xBF; // SEND DVD STRUCTURE cmd[7] = 0x20; // "DVD+R Double Layer Recording Information" cmd[9] = sizeof(dvd_20); cmd[11] = 0; cmd.timeout(180); // Lite-on seems to fire off calibration here if ((err=cmd.transport(WRITE,dvd_20,sizeof(dvd_20)))) sperror ("SEND DVD+R DOUBLE LAYER RECORDING INFORMATION",err), exit (FATAL_START(errno));}static int flush_cache (Scsi_Command &cmd, int even_sync=1){ int err; cmd[0] = 0x35; // FLUSH CACHE cmd[1] = 0x02; // "IMMED" cmd[9] = 0; if (!(err=cmd.transport())) wait_for_unit (cmd); else sperror ("FLUSH CACHE",err); if (even_sync) // Pioneer apparently needs this, { // non-IMMED FLUSH that is... cmd[0] = 0x35; // FLUSH CACHE cmd[9] = 0; if (is_dao) cmd.timeout (15*60); if ((err=cmd.transport())) { sperror ("SYNCHRONOUS FLUSH CACHE",err); return err; } } return 0;}//// atexit/signal handlers//extern "C"void no_r_finalize (){ while (media_written) { Scsi_Command cmd(ioctl_handle); fprintf (stderr,"%s: flushing cache\n",ioctl_device); if (flush_cache (cmd)) break; pioneer_stop (cmd); media_written = 0; errno = 0; } _exit (errno);}extern "C"void plus_rw_finalize (){ sigs_mask(SIGS_BLOCK); while (media_written) { Scsi_Command cmd(ioctl_handle); int err; fprintf (stderr,"%s: flushing cache\n",ioctl_device); if (flush_cache (cmd)) break; if (!dvd_compat) { fprintf (stderr,"%s: stopping de-icing\n",ioctl_device); cmd[0] = 0x5B; // CLOSE TRACK/SESSION cmd[1] = 0x01; // "IMMED" cmd[2] = 0; // "Stop De-Icing" cmd[9] = 0; if ((err=cmd.transport())) sperror ("STOP DE-ICING",err); if (wait_for_unit (cmd)) break; } fprintf (stderr,"%s: writing lead-out\n",ioctl_device); cmd[0] = 0x5B; // CLOSE TRACK/SESSION cmd[1] = 0x01; // "IMMED" cmd[2] = 0x02; // "Close session" cmd[9] = 0; if ((err=cmd.transport())) sperror ("CLOSE SESSION",err); if (wait_for_unit (cmd)) break; media_written = 0; next_wr_addr = 0; errno = 0; if (do_reload && media_reload()) perror (":-( unable to reload tray");// not actually reached } _exit (errno);}extern "C"void bd_re_finalize (){ sigs_mask(SIGS_BLOCK); while (media_written) { Scsi_Command cmd(ioctl_handle); fprintf (stderr,"%s: flushing cache\n",ioctl_device); if (flush_cache (cmd)) break; media_written = 0; next_wr_addr = 0; errno = 0; if (do_reload && media_reload()) perror (":-( unable to reload tray");// not actually reached } _exit (errno);}extern "C"void plus_r_finalize (){ sigs_mask(SIGS_BLOCK); while (media_written) { Scsi_Command cmd(ioctl_handle); int mode,err; fprintf (stderr,"%s: flushing cache\n",ioctl_device); if (flush_cache(cmd)) break; fprintf (stderr,"%s: closing track\n",ioctl_device); cmd[0] = 0x5B; // CLOSE TRACK/SESSION cmd[1] = 0x01; // "IMMED" cmd[2] = 0x01; // "Close Track" cmd[4] = next_track>>8; cmd[5] = next_track; cmd[9] = 0; if ((err=cmd.transport())) sperror ("CLOSE TRACK",err); if (wait_for_unit (cmd)) break; if (dvd_compat) // HP dvd520n insists on "finalize with minimum radius" // with DVD+R DL ---------------vv mode = ((mmc_profile&0xFFFF)==0x2B)?0x05:0x06, fprintf (stderr,"%s: closing disc\n",ioctl_device); else mode = 0x02, fprintf (stderr,"%s: closing session\n",ioctl_device); while (1) // Pioneer DVR-K04RA { cmd[0] = 0x5B; // CLOSE TRACK/SESSION cmd[1] = 0x01; // "IMMED" cmd[2] = mode; // "Close session" cmd[9] = 0; err = cmd.transport(); if (err == 0x20407) // "OP IN PROGRESS" { poll (NULL,0,stdnap); continue; } else if (err) sperror (dvd_compat?"CLOSE DISC":"CLOSE SESSION",err); break; } if (wait_for_unit (cmd)) break; media_written = 0; errno = 0; if (do_reload && media_reload()) perror (":-( unable to reload tray");// not actually reached } _exit (errno);}extern "C"void minus_rw_finalize (){ sigs_mask(SIGS_BLOCK); while (media_written) { Scsi_Command cmd(ioctl_handle); int err; fprintf (stderr,"%s: flushing cache\n",ioctl_device); if (flush_cache(cmd)) break; if (quickgrown) { fprintf (stderr,"%s: writing lead-out\n",ioctl_device); cmd[0] = 0x5B; // CLOSE TRACK/SESSION cmd[1] = 0x01; // "IMMED" cmd[2] = 0x02; // "Close Session" cmd[9] = 0; if ((err=cmd.transport())) sperror ("CLOSE SESSION",err); if (wait_for_unit (cmd)) break; quickgrown=0; } media_written = 0; next_wr_addr = 0; errno = 0; if (do_reload) { if (media_reload()) perror (":-( unable to reload tray");// not actually reached } else return; // Restricted Overwrite is just ugly! } _exit (errno);}extern "C"void minus_r_finalize (){ sigs_mask(SIGS_BLOCK); while (media_written) { Scsi_Command cmd(ioctl_handle); int err; fprintf (stderr,"%s: flushing cache\n",ioctl_device); if (flush_cache(cmd,!is_dao)) break; if (!is_dao) { fprintf (stderr,"%s: updating RMA\n",ioctl_device); cmd[0] = 0x5B; // CLOSE TRACK/SESSION cmd[1] = 0x01; // "IMMED" cmd[2] = 0x01; // "Close Track" cmd[4] = next_track>>8; cmd[5] = next_track; cmd[9] = 0; if ((err=cmd.transport())) sperror ("CLOSE TRACK",err); if (wait_for_unit (cmd)) break; fprintf (stderr,"%s: closing %s\n",ioctl_device, dvd_compat?"disc":"session"); while (1) // Pioneer DVR-K04RA { cmd[0] = 0x5B; // CLOSE TRACK/SESSION cmd[1] = 0x01; // "IMMED" cmd[2] = 0x02; // "Close Session" cmd[9] = 0; err = cmd.transport(); if (err == 0x20407) // "OP IN PROGRESS" { poll (NULL,0,stdnap); continue; } else if (err) sperror (dvd_compat?"CLOSE DISC":"CLOSE SESSION",err); break; } if (wait_for_unit (cmd)) break; } media_written = 0; errno = 0; if (do_reload && media_reload()) perror (":-( unable to reload tray");// not actually reached } _exit (errno);}extern "C"void bd_r_finalize (){ sigs_mask(SIGS_BLOCK); while (media_written) { Scsi_Command cmd(ioctl_handle); int err; fprintf (stderr,"%s: flushing cache\n",ioctl_device); if (flush_cache(cmd)) break; fprintf (stderr,"%s: closing track\n",ioctl_device); cmd[0] = 0x5B; // CLOSE TRACK/SESSION cmd[1] = 0x01; // "IMMED" cmd[2] = 0x01; // "Close Track" cmd[4] = next_track>>8; cmd[5] = next_track; cmd[9] = 0; if ((err=cmd.transport())) sperror ("CLOSE TRACK",err); if (wait_for_unit (cmd)) break; if (!bdr_plus_pow) { fprintf (stderr,"%s: closing session\n",ioctl_device); while (1) // Pioneer DVR-K04RA { cmd[0] = 0x5B; // CLOSE TRACK/SESSION cmd[1] = 0x01; // "IMMED" cmd[2] = 0x02; // "Close session" cmd[9] = 0; err = cmd.transport(); if (err == 0x20407) // "OP IN PROGRESS" { poll (NULL,0,stdnap); continue; } else if (err) sperror ("CLOSE SESSION",err); break; } if (wait_for_unit (cmd)) break; } media_written = 0; errno = 0; if (do_reload && media_reload()) perror (":-( unable to reload tray");// not actually reached } _exit (errno);}extern "C"void ram_reload (){ sigs_mask(SIGS_BLOCK); if (media_written && do_reload) media_reload(); _exit (errno);}//// poor_mans_setup takes care of a lot of things.// It's invoked right before first write and if necessary/applicable// prepares Page 05, reserves track, sets up atexit and signal handlers.//typedef ssize_t (*pwrite64_t)(int,const void *,size_t,off64_t);extern "C"pwrite64_t poor_mans_setup (void *fd,off64_t leadout){ Scsi_Command cmd(ioctl_handle=fd); int err,profile=mmc_profile&0xFFFF; // We might have loaded media ourselves, in which case we // should lock the door... cmd[0] = 0x1E; // PREVENT/ALLOW MEDIA REMOVAL cmd[4] = 1; // "Prevent" cmd[5] = 0; if ((err=cmd.transport ())) sperror ("PREVENT MEDIA REMOVAL",err), exit (FATAL_START(errno)); handle_events(cmd); // This actually belongs in get_mmc_profile, but the trouble // is that Mac OS X does not implement ReadCapacity method and // therefore we have to do it here, after we went exclusive... if (!(mmc_profile&0x10000)) // non-blank media { unsigned char c[8]; cmd[0] = 0x25; // READ CAPACITY cmd[9] = 0; if (!cmd.transport (READ,c,sizeof(c))) cap2kstart = c[0]<<24|c[1]<<16|c[2]<<8|c[3]; } switch (profile) { case 0x1A: // DVD+RW switch (disc_info[7]&3) // Background formatting { case 0: // blank plus_rw_format (cmd); break; case 1: // suspended plus_rw_restart_format (cmd,leadout); break; case 2: // in progress case 3: // complete break; } plusminus_pages_setup (cmd,profile); atexit (plus_rw_finalize); atsignals (plus_rw_finalize); break; case 0x1B: // DVD+R case 0x2B: // DVD+R Double Layer plusminus_pages_setup(cmd,profile); if (profile==0x2B && next_track==1 && dvd_compat && leadout) plus_r_dl_split (cmd,leadout); atexit (plus_r_finalize); if (next_wr_addr) { atsignals (no_r_finalize); next_wr_addr=(unsigned int)-1; } else atsignals (plus_r_finalize); break; case 0x13: // DVD-RW Restricted Overwrite plusminus_pages_setup (cmd,profile); // // A side note. Quick Grow can't be performed earlier, // as then reading is not possible. // minus_rw_quickgrow (cmd,leadout); atexit (minus_rw_finalize); atsignals (minus_rw_finalize); break; case 0x11: // DVD-R Sequential case 0x14: // DVD-RW Sequential case 0x15: // DVD-R Dual Layer Sequential plusminus_pages_setup (cmd,profile); if ((profile==0x15) && leadout) { unsigned char dvd_10[4+16]; unsigned int layer_size,data_size=leadout/2048; cmd[0] = 0xAD; // READ DVD STRUCTURE cmd[7] = 0x10; cmd[9] = sizeof(dvd_10); cmd[11] = 0; if ((err=cmd.transport(READ,dvd_10,sizeof(dvd_10)))) sperror("READ DVD STRUCTURE #10h",err), exit(FATAL_START(errno)); layer_size = dvd_10[4+13]<<16, layer_size |= dvd_10[4+14]<<8, layer_size |= dvd_10[4+15]; if (data_size <= layer_size) fprintf (stderr,":-( more than 50%% of space will be *wasted*!\n" " use single layer media for this recording\n"), exit(FATAL_START(EMEDIUMTYPE)); } if (is_dao && leadout) minus_r_reserve_track(cmd,leadout); atexit (minus_r_finalize); if (next_wr_addr) { atsignals (no_r_finalize); next_wr_addr=(unsigned int)-1; } else atsignals (minus_r_finalize); break; case 0x12: // DVD-RAM // exclusively for speed settings... plusminus_pages_setup (cmd,profile); atexit (ram_reload); atsignals (ram_reload); break; case 0x41: // BD-R SRM if ((disc_info[2]&3) == 0) // blank bd_r_format (cmd); // exclusively for speed settings... plusminus_pages_setup (cmd,profile); atexit (bd_r_finalize); if (next_wr_addr) { atsignals (no_r_finalize); next_wr_addr=(unsigned int)-1; } else atsignals (bd_r_finalize); break; case 0x43: // BR-RE if ((disc_info[2]&3) == 0) // blank bd_re_format (cmd); // exclusively for speed settings... plusminus_pages_setup (cmd,profile); atexit(bd_re_finalize); atsignals(bd_re_finalize); break; case 0x42: // BD-R RRM is not supported yet... case 0x16: // DVD-R Dual Layer Jump not supported for reasons // discussed at web-page... default: fprintf (stderr,":-( mounted media[%X] is not supported\n",profile), exit(FATAL_START(EMEDIUMTYPE)); break; } if (velocity) fprintf (stderr,"%s: \"Current Write Speed\" is %.1fx%dKBps.\n", ioctl_device,velocity/(double)_1x,_1x); if (next_wr_addr==(unsigned int)-1) do { unsigned char track[32]; next_wr_addr = 0; cmd[0] = 0x52; // READ TRACK INFORMATION cmd[1] = 1; cmd[4] = next_track>>8; cmd[5] = next_track&0xFF; // last track, set up earlier cmd[8] = sizeof(track); cmd[9] = 0; if (cmd.transport (READ,track,sizeof(track))) break; 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 (next_wr_addr != // track start (unsigned int)(track[8]<<24|track[9]<<16|track[10]<<8|track[11])) fprintf (stderr,":-? resuming track#%d from LBA#%d\n", next_track,next_wr_addr); } while (0); else next_wr_addr = 0; return poor_mans_pwrite64;}extern "C"int poor_man_rewritable (void *fd, void *buf){ Scsi_Command cmd(fd); int err,profile=mmc_profile&0xFFFF; if (profile!=0x13 && // not DVD-RW Restricted Overwrite profile!=0x12 && // nor DVD-RAM profile!=0x1A && // nor DVD+RW profile!=0x2A && // nor DVD+RW Double Layer !(profile==0x41 && bdr_plus_pow) && // nor BD-R SRM+POW profile!=0x42 && // nor BD-R RRM profile!=0x43) // nor BD-RE return 0; if (profile==0x13) // DVD-RW Restricted Overwrite { // Yet another restriction of Restricted Overwrite mode? // Pioneer DVR-x05 can't read a bit otherwise... do_reload=0; minus_rw_finalize (); // with do_reload==0! do_reload=1; } else if (profile==0x1A || // DVD+RW profile==0x2A || // DVD+RW Double Layer (profile&=0xF0)==0x40) // BD-R[E] { fprintf (stderr,"%s: flushing cache\n",ioctl_device); if (flush_cache(cmd)) exit (errno); } cmd[0] = 0x28; // READ(10) cmd[5] = 16; // LBA#16, volume descriptor set cmd[8] = 16; // 32KB cmd[9] = 0; if ((err=cmd.transport (READ,buf,16*2048))) sperror ("READ@LBA=10h",err), exit(errno); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -