Add DVD+RW support to the ATA driver and burncd. This also closes
PR40430 by "Peter Haight <peterh@sapros.com>" that has semilar patches included and which I merged with my own work. HW sponsored by: FreeBSD Foundation & FreeBSD Mall Inc Enjoy!
This commit is contained in:
parent
6933e3c12b
commit
b2e73852e5
@ -102,6 +102,8 @@ static int acd_mode_sense(struct acd_softc *, int, caddr_t, int);
|
||||
static int acd_mode_select(struct acd_softc *, caddr_t, int);
|
||||
static int acd_set_speed(struct acd_softc *, int, int);
|
||||
static void acd_get_cap(struct acd_softc *);
|
||||
static int acd_read_format_caps(struct acd_softc *, struct cdr_format_capacities *);
|
||||
static int acd_format(struct acd_softc *, struct cdr_format_params *);
|
||||
|
||||
/* internal vars */
|
||||
static u_int32_t acd_lun_map = 0;
|
||||
@ -1029,6 +1031,14 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
|
||||
error = acd_send_cue(cdp, (struct cdr_cuesheet *)addr);
|
||||
break;
|
||||
|
||||
case CDRIOCREADFORMATCAPS:
|
||||
error = acd_read_format_caps(cdp, (struct cdr_format_capacities *)addr);
|
||||
break;
|
||||
|
||||
case CDRIOCFORMAT:
|
||||
error = acd_format(cdp, (struct cdr_format_params *)addr);
|
||||
break;
|
||||
|
||||
case DVDIOCREPORTKEY:
|
||||
if (!cdp->cap.read_dvdrom)
|
||||
error = EINVAL;
|
||||
@ -1184,7 +1194,7 @@ acd_start(struct ata_device *atadev)
|
||||
ccb[9] = 0x10;
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
ccb[0] = ATAPI_WRITE_BIG;
|
||||
|
||||
ccb[1] = 0;
|
||||
@ -1563,21 +1573,23 @@ acd_read_track_info(struct acd_softc *cdp,
|
||||
static int
|
||||
acd_get_progress(struct acd_softc *cdp, int *finished)
|
||||
{
|
||||
int8_t ccb[16] = { ATAPI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0,
|
||||
int8_t ccb[16] = { ATAPI_REQUEST_SENSE, 0, 0, 0,
|
||||
sizeof(struct atapi_reqsense), 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
struct atapi_reqsense *sense = cdp->device->result;
|
||||
char tmp[8];
|
||||
struct atapi_reqsense sense;
|
||||
int error;
|
||||
|
||||
if (atapi_test_ready(cdp->device) != EBUSY) {
|
||||
if (atapi_queue_cmd(cdp->device, ccb, tmp, sizeof(tmp),
|
||||
ATPR_F_READ, 30, NULL, NULL) != EBUSY) {
|
||||
error = atapi_queue_cmd(cdp->device, ccb,
|
||||
(caddr_t)&sense, sizeof(struct atapi_reqsense),
|
||||
ATPR_F_READ, 30, NULL, NULL);
|
||||
|
||||
if (error) {
|
||||
if (error != EBUSY)
|
||||
*finished = 100;
|
||||
return 0;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
if (sense->sksv)
|
||||
*finished =
|
||||
((sense->sk_specific2 | (sense->sk_specific1 << 8)) * 100) / 65535;
|
||||
if (sense.sksv)
|
||||
*finished = ((sense.sk_specific2|(sense.sk_specific1<<8))*100)/65535;
|
||||
else
|
||||
*finished = 0;
|
||||
return 0;
|
||||
@ -2000,3 +2012,29 @@ acd_get_cap(struct acd_softc *cdp)
|
||||
cdp->cap.max_vol_levels = ntohs(cdp->cap.max_vol_levels);
|
||||
cdp->cap.buf_size = ntohs(cdp->cap.buf_size);
|
||||
}
|
||||
|
||||
static int
|
||||
acd_read_format_caps(struct acd_softc *cdp, struct cdr_format_capacities *caps)
|
||||
{
|
||||
int8_t ccb[16] = { ATAPI_READ_FORMAT_CAPACITIES, 0, 0, 0, 0, 0, 0,
|
||||
(sizeof(struct cdr_format_capacities) >> 8) & 0xff,
|
||||
sizeof(struct cdr_format_capacities) & 0xff,
|
||||
0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
return atapi_queue_cmd(cdp->device, ccb, (caddr_t)caps,
|
||||
sizeof(struct cdr_format_capacities),
|
||||
ATPR_F_READ, 30, NULL, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
acd_format(struct acd_softc *cdp, struct cdr_format_params* params)
|
||||
{
|
||||
int error;
|
||||
int8_t ccb[16] = { ATAPI_FORMAT, 0x11, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0 };
|
||||
|
||||
error = atapi_queue_cmd(cdp->device, ccb, (u_int8_t *)params,
|
||||
sizeof(struct cdr_format_params), 0, 30, NULL,NULL);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ struct write_param {
|
||||
#define CDR_WTYPE_RAW 0x03
|
||||
|
||||
u_int8_t test_write :1; /* test write enable */
|
||||
u_int8_t reserved2_5 :1;
|
||||
u_int8_t link_size_valid :1;
|
||||
u_int8_t burnproof :1; /* BurnProof enable */
|
||||
u_int8_t reserved2_7 :1;
|
||||
u_int8_t track_mode :4; /* track mode */
|
||||
@ -319,7 +319,7 @@ struct write_param {
|
||||
|
||||
u_int8_t datablock_type :4; /* data type code (see cdrio.h) */
|
||||
u_int8_t reserved4_4567 :4;
|
||||
u_int8_t reserved5;
|
||||
u_int8_t link_size;
|
||||
u_int8_t reserved6;
|
||||
u_int8_t host_app_code :6; /* host application code */
|
||||
u_int8_t reserved7_67 :2;
|
||||
|
@ -85,6 +85,37 @@ struct cdr_cuesheet {
|
||||
int test_write;
|
||||
};
|
||||
|
||||
struct cdr_format_capacity {
|
||||
u_int32_t blocks;
|
||||
u_int32_t reserved:2;
|
||||
u_int32_t type:6;
|
||||
u_int32_t param:24;
|
||||
};
|
||||
|
||||
struct cdr_format_capacities {
|
||||
u_int8_t reserved1[3];
|
||||
u_int8_t length;
|
||||
u_int32_t blocks;
|
||||
u_int32_t type:2;
|
||||
u_int32_t reserved2:6;
|
||||
u_int32_t block_size:24;
|
||||
struct cdr_format_capacity format[32];
|
||||
};
|
||||
|
||||
struct cdr_format_params {
|
||||
u_int8_t reserved;
|
||||
u_int8_t vs:1;
|
||||
u_int8_t immed:1;
|
||||
u_int8_t try_out:1;
|
||||
u_int8_t ip:1;
|
||||
u_int8_t stpf:1;
|
||||
u_int8_t dcrt:1;
|
||||
u_int8_t dpry:1;
|
||||
u_int8_t fov:1;
|
||||
u_int16_t length;
|
||||
struct cdr_format_capacity format;
|
||||
};
|
||||
|
||||
#define CDRIOCBLANK _IOW('c', 100, int)
|
||||
#define CDR_B_ALL 0x0
|
||||
#define CDR_B_MIN 0x1
|
||||
@ -101,5 +132,7 @@ struct cdr_cuesheet {
|
||||
#define CDRIOCGETBLOCKSIZE _IOR('c', 109, int)
|
||||
#define CDRIOCSETBLOCKSIZE _IOW('c', 110, int)
|
||||
#define CDRIOCGETPROGRESS _IOR('c', 111, int)
|
||||
#define CDRIOCREADFORMATCAPS _IOR('c', 112, struct cdr_format_capacities)
|
||||
#define CDRIOCFORMAT _IOW('c', 113, struct cdr_format_params)
|
||||
|
||||
#endif /* !_SYS_CDRIO_H_ */
|
||||
|
@ -54,6 +54,8 @@ burn the CD-R/RW in DAO (disk at once) mode.
|
||||
eject the media when done.
|
||||
.It Fl f Ar device
|
||||
set the device to use for the burning process.
|
||||
.It Fl F
|
||||
force operation regardless of warnings.
|
||||
.It Fl l
|
||||
read a list of image files from filename.
|
||||
.It Fl m
|
||||
@ -91,6 +93,10 @@ only those areas that make the media appear blank for further usage are erased.
|
||||
Erase a CD-RW medium.
|
||||
This erases the entire media.
|
||||
Can take up to 1 hour to finish.
|
||||
.It Cm format dwd+rw
|
||||
Formats a DVD+RW media to the default max size and 2048byte blocks. This
|
||||
operation can take a long time to finish. Progress reporting is done
|
||||
during the process.
|
||||
.It Cm fixate
|
||||
Fixate the medium so that the TOC is generated and the media can be used
|
||||
in an ordinary CD drive.
|
||||
@ -129,6 +135,9 @@ and
|
||||
.Dq "no gaps"
|
||||
.Pq Fl n
|
||||
modes.
|
||||
.It Cm dvdrw
|
||||
Set the write mode to write a DVD+RW from the follwing image. DVD's only
|
||||
have one track.
|
||||
.It Ar file
|
||||
All other arguments are treated as filenames of images to write to the media,
|
||||
or in case the
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/cdio.h>
|
||||
#include <sys/cdrio.h>
|
||||
#include <sys/dvdio.h>
|
||||
#include <sys/param.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
@ -48,7 +49,7 @@
|
||||
struct track_info {
|
||||
int file;
|
||||
char *file_name;
|
||||
u_int file_size;
|
||||
off_t file_size;
|
||||
int block_size;
|
||||
int block_type;
|
||||
int pregap;
|
||||
@ -59,7 +60,8 @@ static int fd, quiet, verbose, saved_block_size, notracks;
|
||||
|
||||
void add_track(char *, int, int, int);
|
||||
void do_DAO(int, int);
|
||||
void do_TAO(int, int);
|
||||
void do_TAO(int, int, int);
|
||||
void do_format(int, int, char *);
|
||||
int write_file(struct track_info *);
|
||||
int roundup_blocks(struct track_info *);
|
||||
void cue_ent(struct cdr_cue_entry *, int, int, int, int, int, int, int);
|
||||
@ -71,11 +73,11 @@ main(int argc, char **argv)
|
||||
{
|
||||
int ch, arg, addr;
|
||||
int dao = 0, eject = 0, fixate = 0, list = 0, multi = 0, preemp = 0;
|
||||
int nogap = 0, speed = 4, test_write = 0;
|
||||
int block_size = 0, block_type = 0, cdopen = 0;
|
||||
int nogap = 0, speed = 4, test_write = 0, force = 0;
|
||||
int block_size = 0, block_type = 0, cdopen = 0, dvdrw = 0;
|
||||
const char *dev = "/dev/acd0c";
|
||||
|
||||
while ((ch = getopt(argc, argv, "def:lmnpqs:tv")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "def:Flmnpqs:tv")) != -1) {
|
||||
switch (ch) {
|
||||
case 'd':
|
||||
dao = 1;
|
||||
@ -88,6 +90,10 @@ main(int argc, char **argv)
|
||||
case 'f':
|
||||
dev = optarg;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
force = 1;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
list = 1;
|
||||
@ -167,8 +173,9 @@ main(int argc, char **argv)
|
||||
|
||||
break;
|
||||
}
|
||||
if (!strcasecmp(argv[arg], "erase") || !strcasecmp(argv[arg], "blank")){
|
||||
int error, blank, percent;
|
||||
if ((!strcasecmp(argv[arg], "erase") ||
|
||||
!strcasecmp(argv[arg], "blank")) && !test_write) {
|
||||
int error, blank, percent, last = 0;
|
||||
|
||||
if (!strcasecmp(argv[arg], "erase"))
|
||||
blank = CDR_B_ALL;
|
||||
@ -188,13 +195,25 @@ main(int argc, char **argv)
|
||||
"%sing CD - %d %% done \r",
|
||||
blank == CDR_B_ALL ?
|
||||
"eras" : "blank", percent);
|
||||
if (error || percent == 100)
|
||||
if (error || percent == 100 ||
|
||||
(percent == 0 && last == 99))
|
||||
break;
|
||||
last = percent;
|
||||
}
|
||||
if (!quiet)
|
||||
printf("\n");
|
||||
continue;
|
||||
}
|
||||
if (!strcasecmp(argv[arg], "format") && !test_write) {
|
||||
if (arg + 1 < argc &&
|
||||
(!strcasecmp(argv[arg + 1], "dvd+rw") ||
|
||||
!strcasecmp(argv[arg + 1], "dvd-rw")))
|
||||
do_format(fd, force, argv[arg + 1]);
|
||||
else
|
||||
err(EX_NOINPUT, "format media type invalid");
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (!strcasecmp(argv[arg], "audio") || !strcasecmp(argv[arg], "raw")) {
|
||||
block_type = CDR_DB_RAW;
|
||||
block_size = 2352;
|
||||
@ -227,6 +246,13 @@ main(int argc, char **argv)
|
||||
nogap = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcasecmp(argv[arg], "dvdrw")) {
|
||||
block_type = CDR_DB_ROM_MODE1;
|
||||
block_size = 2048;
|
||||
dvdrw = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!block_size)
|
||||
err(EX_NOINPUT, "no data format selected");
|
||||
if (list) {
|
||||
@ -252,6 +278,8 @@ main(int argc, char **argv)
|
||||
add_track(argv[arg], block_size, block_type, nogap);
|
||||
}
|
||||
if (notracks) {
|
||||
if (dvdrw && notracks > 1)
|
||||
err(EX_USAGE, "DVD's only have 1 track");
|
||||
if (ioctl(fd, CDIOCSTART, 0) < 0)
|
||||
err(EX_IOERR, "ioctl(CDIOCSTART)");
|
||||
if (!cdopen) {
|
||||
@ -262,7 +290,7 @@ main(int argc, char **argv)
|
||||
if (dao)
|
||||
do_DAO(test_write, multi);
|
||||
else
|
||||
do_TAO(test_write, preemp);
|
||||
do_TAO(test_write, preemp, dvdrw);
|
||||
}
|
||||
if (fixate && !dao) {
|
||||
if (!quiet)
|
||||
@ -436,7 +464,7 @@ do_DAO(int test_write, int multi)
|
||||
}
|
||||
|
||||
void
|
||||
do_TAO(int test_write, int preemp)
|
||||
do_TAO(int test_write, int preemp, int dvdrw)
|
||||
{
|
||||
struct cdr_track track;
|
||||
int i;
|
||||
@ -448,8 +476,13 @@ do_TAO(int test_write, int preemp)
|
||||
if (ioctl(fd, CDRIOCINITTRACK, &track) < 0)
|
||||
err(EX_IOERR, "ioctl(CDRIOCINITTRACK)");
|
||||
|
||||
if (ioctl(fd, CDRIOCNEXTWRITEABLEADDR, &tracks[i].addr) < 0)
|
||||
err(EX_IOERR, "ioctl(CDRIOCNEXTWRITEABLEADDR)");
|
||||
if (dvdrw)
|
||||
tracks[i].addr = 0;
|
||||
else
|
||||
if (ioctl(fd, CDRIOCNEXTWRITEABLEADDR,
|
||||
&tracks[i].addr) < 0)
|
||||
err(EX_IOERR, "ioctl(CDRIOCNEXTWRITEABLEADDR)");
|
||||
|
||||
if (!quiet)
|
||||
fprintf(stderr, "next writeable LBA %d\n",
|
||||
tracks[i].addr);
|
||||
@ -460,12 +493,91 @@ do_TAO(int test_write, int preemp)
|
||||
}
|
||||
}
|
||||
|
||||
#define NTOH3B(x) ((x&0x0000ff)<<16) | (x&0x00ff00) | ((x&0xff0000)>>16)
|
||||
|
||||
void
|
||||
do_format(int fd, int force, char *type)
|
||||
{
|
||||
struct cdr_format_capacities capacities;
|
||||
struct cdr_format_params format_params;
|
||||
int count, i, percent, last = 0;
|
||||
|
||||
if (ioctl(fd, CDRIOCREADFORMATCAPS, &capacities) == -1)
|
||||
err(EX_IOERR, "ioctl(CDRIOCREADFORMATCAPS)");
|
||||
|
||||
if (verbose) {
|
||||
fprintf(stderr, "format list entries=%d\n",
|
||||
capacities.length / sizeof(struct cdr_format_capacity));
|
||||
fprintf(stderr, "current format: blocks=%u type=0x%x block_size=%u\n",
|
||||
ntohl(capacities.blocks), capacities.type,
|
||||
NTOH3B(capacities.block_size));
|
||||
}
|
||||
|
||||
count = capacities.length / sizeof(struct cdr_format_capacity);
|
||||
if (verbose) {
|
||||
for (i = 0; i < count; ++i)
|
||||
fprintf(stderr,
|
||||
"format %d: blocks=%u type=0x%x param=%u\n",
|
||||
i, ntohl(capacities.format[i].blocks),
|
||||
capacities.format[i].type,
|
||||
NTOH3B(capacities.format[i].param));
|
||||
}
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
if (!strcasecmp(type, "dvd+rw")) {
|
||||
if (capacities.format[i].type == 0x26) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(type, "dvd-rw")) {
|
||||
if (capacities.format[i].type == 0x0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i == count)
|
||||
err(EX_IOERR, "could not find a valid format capacity");
|
||||
|
||||
if (!quiet)
|
||||
fprintf(stderr,"formatting with blocks=%u type=0x%x param=%u\n",
|
||||
ntohl(capacities.format[i].blocks),
|
||||
capacities.format[i].type,
|
||||
NTOH3B(capacities.format[i].param));
|
||||
|
||||
if (!force && capacities.type == 2)
|
||||
err(EX_IOERR, "media already formatted (use -F to override)");
|
||||
|
||||
memset(&format_params, 0, sizeof(struct cdr_format_params));
|
||||
format_params.fov = 1;
|
||||
format_params.immed = 1;
|
||||
format_params.length = ntohs(sizeof(struct cdr_format_capacity));
|
||||
memcpy(&format_params.format, &capacities.format[i],
|
||||
sizeof(struct cdr_format_capacity));
|
||||
|
||||
if(ioctl(fd, CDRIOCFORMAT, &format_params) == -1)
|
||||
err(EX_IOERR, "ioctl(CDRIOCFORMAT)");
|
||||
|
||||
while (1) {
|
||||
sleep(1);
|
||||
if (ioctl(fd, CDRIOCGETPROGRESS, &percent) == -1)
|
||||
err(EX_IOERR, "ioctl(CDRIOGETPROGRESS)");
|
||||
if (percent > 0 && !quiet)
|
||||
fprintf(stderr, "formatting DVD - %d %% done \r",
|
||||
percent);
|
||||
if (percent == 100 || (percent == 0 && last == 99))
|
||||
break;
|
||||
last = percent;
|
||||
}
|
||||
if (!quiet)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
int
|
||||
write_file(struct track_info *track_info)
|
||||
{
|
||||
int size, count, filesize;
|
||||
off_t size, count, filesize;
|
||||
char buf[2352*BLOCKS];
|
||||
static int tot_size = 0;
|
||||
static off_t tot_size = 0;
|
||||
|
||||
filesize = track_info->file_size / 1024;
|
||||
|
||||
@ -476,7 +588,7 @@ write_file(struct track_info *track_info)
|
||||
lseek(fd, track_info->addr * track_info->block_size, SEEK_SET);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "addr = %d size = %d blocks = %d\n",
|
||||
fprintf(stderr, "addr = %d size = %qd blocks = %d\n",
|
||||
track_info->addr, track_info->file_size,
|
||||
roundup_blocks(track_info));
|
||||
|
||||
@ -485,7 +597,7 @@ write_file(struct track_info *track_info)
|
||||
fprintf(stderr, "writing from stdin\n");
|
||||
else
|
||||
fprintf(stderr,
|
||||
"writing from file %s size %d KB\n",
|
||||
"writing from file %s size %qd KB\n",
|
||||
track_info->file_name, filesize);
|
||||
}
|
||||
size = 0;
|
||||
@ -503,7 +615,7 @@ write_file(struct track_info *track_info)
|
||||
track_info->block_size;
|
||||
}
|
||||
if ((res = write(fd, buf, count)) != count) {
|
||||
fprintf(stderr, "\nonly wrote %d of %d bytes err=%d\n",
|
||||
fprintf(stderr, "\nonly wrote %d of %qd bytes err=%d\n",
|
||||
res, count, errno);
|
||||
break;
|
||||
}
|
||||
@ -512,12 +624,12 @@ write_file(struct track_info *track_info)
|
||||
if (!quiet) {
|
||||
int pct;
|
||||
|
||||
fprintf(stderr, "written this track %d KB", size/1024);
|
||||
fprintf(stderr, "written this track %qd KB", size/1024);
|
||||
if (track_info->file != STDIN_FILENO && filesize) {
|
||||
pct = (size / 1024) * 100 / filesize;
|
||||
fprintf(stderr, " (%d%%)", pct);
|
||||
}
|
||||
fprintf(stderr, " total %d KB\r", tot_size/1024);
|
||||
fprintf(stderr, " total %qd KB\r", tot_size/1024);
|
||||
}
|
||||
if (size >= track_info->file_size)
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user