cdfs: pull updates from sources

This commit is contained in:
cinap_lenrek 2012-08-01 21:34:14 +02:00
parent c7ad44a048
commit 9b5b68a302
4 changed files with 308 additions and 177 deletions

View file

@ -30,6 +30,17 @@ enum {
TypeDisk,
TypeBlank,
/* disc writability classes */
Readonly = 0, /* -ROM */
Write1, /* -R: write once only */
Erasewrite, /* -R[WE]: erase then write */
Ram, /* -RAM: read & write unrestricted */
/* tri-state flags */
Unset = -1,
No,
Yes,
/* offsets in Pagcapmechsts mode page; see MMC-3 §5.5.10 */
Capread = 2,
Capwrite = 3,
@ -129,11 +140,12 @@ enum {
};
typedef struct Buf Buf;
typedef struct Drive Drive;
typedef struct Track Track;
typedef struct Otrack Otrack;
typedef struct Dev Dev;
typedef struct Drive Drive;
typedef struct Msf Msf; /* minute, second, frame */
typedef struct Otrack Otrack;
typedef struct Track Track;
typedef schar Tristate;
struct Msf {
int m;
@ -196,23 +208,24 @@ struct Drive
QLock;
Scsi;
int type; /* scsi peripheral device type */
int type; /* scsi peripheral device type: Type?? */
/* disc characteristics */
int mmctype;
char *dvdtype;
int mmctype; /* cd, dvd, or bd */
char *dvdtype; /* name of dvd flavour */
int firsttrack;
int invistrack;
int ntrack;
int nchange; /* compare with the members in Scsi */
ulong changetime; /* " */
int nameok;
int writeok;
int blank; /* (not used for anything yet) */
int blankset;
int recordable; /* writable by burning? */
int recordableset;
int erasable; /* rewritable? */
int erasableset;
int writeok; /* writable disc? */
/*
* we could combine these attributes into a single variable except
* that we discover them separately sometimes.
*/
Tristate recordable; /* writable by burning? */
Tristate erasable; /* writable after erasing? */
Track track[Ntrack];
ulong cap; /* drive capabilities */

View file

@ -4,6 +4,7 @@ void bterm(Buf*);
long bufread(Otrack*, void*, long, vlong);
long bufwrite(Otrack*, void*, long);
long bwrite(Buf*, void*, long);
char* disctype(Drive *drive);
void *emalloc(ulong);
char* geterrstr(void);
Drive* mmcprobe(Scsi*);

View file

@ -192,7 +192,7 @@ fsremove(Req *r)
case Qwd:
if(drive->fixate(drive) < 0)
respond(r, geterrstr());
// let us see if it can figure this out: drive->writeok = 0;
// let us see if it can figure this out: drive->writeok = No;
else
respond(r, nil);
checktoc(drive);
@ -204,7 +204,7 @@ fsremove(Req *r)
}
/* result is one word, so it can be used as a uid in Dir structs */
static char *
char *
disctype(Drive *drive)
{
char *type, *rw;
@ -229,9 +229,9 @@ disctype(Drive *drive)
}
rw = "";
if (drive->mmctype != Mmcnone && drive->dvdtype == nil)
if (drive->erasable)
if (drive->erasable == Yes)
rw = drive->mmctype == Mmcbd? "re": "rw";
else if (drive->recordable)
else if (drive->recordable == Yes)
rw = "r";
else
rw = "rom";
@ -271,7 +271,7 @@ fillstat(ulong qid, Dir *d)
break;
case Qwa:
if(drive->writeok == 0 ||
if(drive->writeok == No ||
drive->mmctype != Mmcnone &&
drive->mmctype != Mmccd)
return 0;
@ -281,7 +281,7 @@ fillstat(ulong qid, Dir *d)
break;
case Qwd:
if(drive->writeok == 0)
if(drive->writeok == No)
return 0;
d->name = "wd";
d->qid.type = QTDIR;
@ -340,6 +340,7 @@ static void
readctl(Req *r)
{
int i, isaudio;
ulong nwa;
char *p, *e, *ty;
char s[1024];
Msf *m;
@ -375,9 +376,14 @@ readctl(Req *r)
ty = disctype(drive);
p = seprint(p, e, "%s", ty);
free(ty);
if (drive->mmctype != Mmcnone)
p = seprint(p, e, " next writable sector %lud",
getnwa(drive));
if (drive->mmctype != Mmcnone) {
nwa = getnwa(drive);
p = seprint(p, e, " next writable sector ");
if (nwa == ~0ul)
p = seprint(p, e, "none; disc full");
else
p = seprint(p, e, "%lud", nwa);
}
seprint(p, e, "\n");
}
readstr(r, s);
@ -718,6 +724,7 @@ main(int argc, char **argv)
if(dev == nil || mtpt == nil || argc > 0)
usage();
werrstr("");
if((s = openscsi(dev)) == nil)
sysfatal("openscsi '%s': %r", dev);
if((drive = mmcprobe(s)) == nil)

View file

@ -14,6 +14,8 @@
enum
{
Desperate = 0, /* non-zero grubs around in inquiry string */
Pagesz = 255,
Pagwrparams = 5, /* (cd|dvd)-r(w) device write parameters */
@ -33,7 +35,7 @@ struct Mmcaux {
int pagecmdsz;
/* disc characteristics */
ulong mmcnwa;
long mmcnwa; /* next writable address (block #) */
int nropen;
int nwopen;
vlong ntotby;
@ -60,6 +62,8 @@ static char *dvdtype[] = {
"type-15-unknown",
};
static int getinvistrack(Drive *drive);
static ulong
bige(void *p)
{
@ -110,16 +114,6 @@ initcdb(uchar *cdb, int len, int cmd)
cdb[0] = cmd;
}
//static uchar *
//newcdb(int len, int cmd)
//{
// uchar *cdb;
//
// cdb = emalloc(len);
// cdb[0] = cmd;
// return cdb;
//}
/*
* SCSI CDBs (cmd arrays) are 6, 10, 12, 16 or 32 bytes long.
* The mode sense/select commands implicitly refer to
@ -162,14 +156,9 @@ mmcgetpage10(Drive *drive, int page, void *v)
uchar cmd[10], resp[512];
int n, r;
memset(cmd, 0, sizeof(cmd));
cmd[0] = ScmdMsense10;
initcdb(cmd, sizeof cmd, ScmdMsense10);
cmd[2] = page;
cmd[8] = 255; /* allocation length: buffer size */
// print("get: sending cmd\n");
// hexdump(cmd, 10);
n = scsi(drive, cmd, sizeof(cmd), resp, sizeof(resp), Sread);
if(n < Mode10parmhdrlen)
return -1;
@ -183,12 +172,6 @@ mmcgetpage10(Drive *drive, int page, void *v)
n = Pagesz;
memmove(v, &resp[Mode10parmhdrlen + r], n);
// print("get: got cmd\n");
// hexdump(cmd, 10);
// print("page\n");
// hexdump(v, n);
return n;
}
@ -198,8 +181,7 @@ mmcgetpage6(Drive *drive, int page, void *v)
uchar cmd[6], resp[512];
int n;
memset(cmd, 0, sizeof(cmd));
cmd[0] = ScmdMsense6;
initcdb(cmd, sizeof cmd, ScmdMsense6);
cmd[2] = page;
cmd[4] = 255; /* allocation length */
@ -234,8 +216,7 @@ mmcsetpage10(Drive *drive, int page, void *v)
p[1] = len - 2;
/* set up CDB */
memset(cmd, 0, sizeof(cmd));
cmd[0] = ScmdMselect10;
initcdb(cmd, sizeof cmd, ScmdMselect10);
cmd[1] = 0x10; /* format not vendor-specific */
cmd[8] = len;
@ -271,8 +252,7 @@ mmcsetpage6(Drive *drive, int page, void *v)
p = emalloc(len);
memmove(p + Mode6parmhdrlen, pagedata, pagedata[1]);
memset(cmd, 0, sizeof(cmd));
cmd[0] = ScmdMselect6;
initcdb(cmd, sizeof cmd, ScmdMselect6);
cmd[1] = 0x10; /* format not vendor-specific */
cmd[4] = len;
@ -388,11 +368,16 @@ mmcprobe(Scsi *scsi)
if (vflag)
print("mmcprobe: inquiry: %s\n", scsi->inquire);
drive = emalloc(sizeof(Drive));
drive->Scsi = *scsi;
drive->Dev = mmcdev;
drive->invistrack = -1;
getinvistrack(drive);
aux = emalloc(sizeof(Mmcaux));
drive->aux = aux;
scsiready(drive);
drive->type = getdevtype(drive);
if (drive->type != TypeCD) {
@ -480,14 +465,14 @@ static int
mmctrackinfo(Drive *drive, int t, int i)
{
int n, type, bs;
long newnwa;
ulong beg, size;
uchar tmode;
uchar cmd[10], resp[255];
Mmcaux *aux;
aux = drive->aux;
memset(cmd, 0, sizeof(cmd));
cmd[0] = ScmdRtrackinfo;
initcdb(cmd, sizeof cmd, ScmdRtrackinfo);
cmd[1] = 1; /* address below is logical track # */
cmd[2] = t>>24;
cmd[3] = t>>16;
@ -545,20 +530,32 @@ mmctrackinfo(Drive *drive, int t, int i)
if(resp[6] & (1<<6)) { /* blank? */
drive->track[i].type = TypeBlank;
drive->writeok = 1;
drive->writeok = Yes;
}
/*
* figure out the first writable block, if we can
*/
if(vflag)
print(" start %lud end %lud", beg, beg + size - 1);
/* resp[6] & (1<<7) of zero: invisible track */
/* t == getinvistrack(): invisible track */
if(t == Invistrack || resp[7] & 1) { /* invis or nwa valid? */
aux->mmcnwa = bige(&resp[12]);
if ((long)aux->mmcnwa < 0) /* implausible? */
aux->mmcnwa = 0;
if (vflag)
print(" nwa %lud", aux->mmcnwa);
if(resp[7] & 1) { /* nwa valid? */
newnwa = bige(&resp[12]);
if (newnwa >= 0)
if (aux->mmcnwa < 0)
aux->mmcnwa = newnwa;
else if (aux->mmcnwa != newnwa)
fprint(2, "nwa is %ld but invis track starts blk %ld\n",
newnwa, aux->mmcnwa);
}
/* resp[6] & (1<<7) of zero: invisible track */
if(t == Invistrack || t == drive->invistrack)
if (aux->mmcnwa < 0)
aux->mmcnwa = beg;
else if (aux->mmcnwa != beg)
fprint(2, "invis track starts blk %ld but nwa is %ld\n",
beg, aux->mmcnwa);
if (vflag && aux->mmcnwa >= 0)
print(" nwa %lud", aux->mmcnwa);
if (vflag)
print("\n");
return 0;
@ -570,8 +567,7 @@ mmcreadtoc(Drive *drive, int type, int track, void *data, int nbytes)
{
uchar cmd[10];
memset(cmd, 0, sizeof(cmd));
cmd[0] = ScmdRTOC;
initcdb(cmd, sizeof cmd, ScmdRTOC);
cmd[1] = type; /* msf bit & reserved */
cmd[2] = Tocfmttoc;
cmd[6] = track; /* track/session */
@ -586,26 +582,6 @@ mmcreadtoc(Drive *drive, int type, int track, void *data, int nbytes)
return scsi(drive, cmd, sizeof(cmd), data, nbytes, Sread);
}
static int
mmcreaddiscinfo(Drive *drive, void *data, int nbytes)
{
uchar cmd[10];
int n;
memset(cmd, 0, sizeof(cmd));
cmd[0] = ScmdRdiscinfo;
cmd[7] = nbytes>>8;
cmd[8] = nbytes;
n = scsi(drive, cmd, sizeof(cmd), data, nbytes, Sread);
if(n < 24) {
if(n >= 0)
werrstr("rdiscinfo returns %d", n);
return -1;
}
return n;
}
static Msf
rdmsf(uchar *p)
{
@ -621,18 +597,104 @@ static int
getdiscinfo(Drive *drive, uchar resp[], int resplen)
{
int n;
uchar cmd[10];
n = mmcreaddiscinfo(drive, resp, resplen);
if(n < 3) {
if (vflag)
initcdb(cmd, sizeof cmd, ScmdRdiscinfo);
cmd[7] = resplen>>8;
cmd[8] = resplen;
n = scsi(drive, cmd, sizeof(cmd), resp, resplen, Sread);
if(n < 24) {
if(n >= 0)
werrstr("rdiscinfo returns %d", n);
else if (vflag)
fprint(2, "read disc info failed\n");
return n;
return -1;
}
if (vflag)
fprint(2, "read disc info succeeded\n");
assert((resp[2] & 0340) == 0); /* data type 0 */
drive->erasable = ((resp[2] & 0x10) != 0); /* -RW? */
drive->erasableset = 1;
return n;
}
static int
getconf(Drive *drive)
{
int n;
ushort prof;
ulong datalen;
uchar cmd[10];
uchar resp[2*1024]; /* 64k-8 ok, 2k often enough, 400 typical */
initcdb(cmd, sizeof cmd, Scmdgetconf);
cmd[3] = 1; /* start with core feature */
cmd[7] = sizeof resp >> 8;
cmd[8] = sizeof resp;
n = scsi(drive, cmd, sizeof(cmd), resp, sizeof resp, Sread);
if (n < 0) {
if(vflag)
fprint(2, "get config cmd failed\n");
return -1;
}
if (n < 4)
return -1;
datalen = GETBELONG(resp+0);
if (datalen < 8)
return -1;
/*
* features start with an 8-byte header:
* ulong datalen, ushort reserved, ushort current profile.
* profile codes (table 92) are: 0 reserved, 1-7 legacy, 8-0xf cd,
* 0x10-0x1f 0x2a-0x2b dvd*, 0x40-0x4f bd, 0x50-0x5f hd dvd,
* 0xffff whacko.
*
* this is followed by multiple feature descriptors:
* ushort code, uchar bits, uchar addnl_len, addnl_len bytes.
*/
prof = resp[6]<<8 | resp[7];
if(prof == 0 || prof == 0xffff) /* none or whacko? */
return n;
if(drive->mmctype != Mmcnone)
return n;
switch (prof >> 4) {
case 0:
drive->mmctype = Mmccd;
break;
case 1:
if (prof == 0x1a || prof == 0x1b)
drive->mmctype = Mmcdvdplus;
else
drive->mmctype = Mmcdvdminus;
break;
case 2:
drive->mmctype = Mmcdvdplus; /* dual layer */
break;
case 4:
drive->mmctype = Mmcbd;
/*
* further decode prof to set writability flags.
* mostly for Pioneer BDR-206M. there may be unnecessary
* future profiles for dual, triple and quad layer;
* let's hope not.
*/
switch (prof) {
case 0x40:
drive->erasable = drive->recordable = No;
case 0x41:
case 0x42:
drive->erasable = No;
drive->recordable = Yes;
break;
case 0x43:
drive->erasable = Yes;
drive->recordable = No;
break;
}
break;
case 5:
drive->mmctype = Mmcdvdminus; /* hd dvd, obs. */
break;
}
return n;
}
@ -648,11 +710,11 @@ getdvdstruct(Drive *drive)
cmd[8] = sizeof resp >> 8; /* allocation length */
cmd[9] = sizeof resp;
n = scsi(drive, cmd, sizeof(cmd), resp, sizeof resp, Sread);
if (n < 7)
if (n < 7) {
if(vflag)
fprint(2, "read disc structure (dvd) cmd failed\n");
return -1;
// print("dvd structure:\n");
// hexdump(resp, n);
}
/* resp[0..1] is resp length */
cat = (resp[4] & 0xf0) >> 4; /* disk category, MMC-6 §6.22.3.2.1 */
@ -660,65 +722,115 @@ getdvdstruct(Drive *drive)
fprint(2, "dvd type is %s\n", dvdtype[cat]);
drive->dvdtype = dvdtype[cat];
/* write parameters mode page may suffice to compute writeok for dvd */
drive->erasable = drive->recordable = 0;
drive->erasable = drive->recordable = No;
/*
* the layer-type field is a *bit array*,
* though an enumeration of types would make more sense,
* since the types are exclusive, not orthogonal.
*/
if (resp[6] & (1<<2)) /* rewritable? */
drive->erasable = 1;
drive->erasable = Yes;
else if (resp[6] & (1<<1)) /* recordable once? */
drive->recordable = 1;
else { /* factory-pressed disk */
drive->blank = 0;
drive->blankset = 1;
}
drive->erasableset = drive->recordableset = 1;
drive->recordable = Yes;
/* else it's a factory-pressed disk */
drive->mmctype = (cat >= 8? Mmcdvdplus: Mmcdvdminus);
return 0;
}
/*
* ugly hack to divine device type from inquiry string as last resort.
* mostly for Pioneer BDR-206M.
*/
static int
bdguess(Drive *drive)
{
if (drive->mmctype == Mmcnone) {
if (strstr(drive->Scsi.inquire, "BD") == nil)
return -1;
if (vflag)
fprint(2, "drive probably a BD (from inquiry string)\n");
drive->mmctype = Mmcbd;
} else if (drive->mmctype == Mmcbd) {
if (drive->erasable != Unset && drive->recordable != Unset)
return 0;
} else
return -1;
drive->recordable = drive->writeok = No;
if (strstr(drive->Scsi.inquire, "RW") != nil) {
if (vflag)
fprint(2, "drive probably a burner (from inquiry string)\n");
drive->recordable = drive->writeok = Yes;
if (drive->erasable == Unset) { /* set by getdiscinfo perhaps */
drive->erasable = No; /* no way to tell, alas */
if (vflag)
fprint(2, "\tassuming -r not -rw\n");
}
} else {
if (drive->erasable == Unset)
drive->erasable = No;
}
if (drive->erasable == Yes)
drive->recordable = No; /* mutually exclusive */
return 0;
}
static int
getbdstruct(Drive *drive)
{
int n;
uchar cmd[12], resp[4100];
uchar cmd[12], resp[4+4096];
uchar *di, *body;
initcdb(cmd, sizeof cmd, ScmdReadDVD); /* actually, read disc structure */
cmd[1] = 1; /* media type: bd */
/* cmd[6] is layer #, 0 is first */
cmd[7] = 0; /* format code: disc info */
cmd[8] = sizeof resp >> 8; /* allocation length */
cmd[9] = sizeof resp;
n = scsi(drive, cmd, sizeof(cmd), resp, sizeof resp, Sread);
if(n < 0) {
if(vflag)
fprint(2, "read disc structure (bd) cmd failed\n");
return -1;
}
/*
* resp[0..1] is resp length.
* resp[4+8..4+8+2] is bd type (disc type identifier):
* BDO|BDW|BDR, MMC-6 §6.22.3.3.1. The above command should
* resp[0..1] is resp length (4100); 2 & 3 are reserved.
* there may be multiple disc info structs of 112 bytes each.
* disc info (di) starts at 4. di[0..7] are header, followed by body.
* body[0..2] is bd type (disc type identifier):
* BDO|BDW|BDR, MMC-6 §6.22.3.3.1. The above scsi command should
* fail on DVD drives, but some seem to ignore media type
* and return successfully, so verify that it's a BD drive.
*/
if (n < 4+8+3 || resp[4+8] != 'B' || resp[4+8+1] != 'D')
return -1;
if (vflag)
fprint(2, "read disc structure (bd) succeeded\n");
drive->erasable = drive->recordable = 0;
switch (resp[4+8+2]) {
case 'O':
drive->blank = 0;
drive->blankset = 1;
break;
case 'R': /* Recordable */
drive->recordable = 1;
break;
case 'W': /* reWritable */
drive->erasable = 1;
break;
default:
fprint(2, "%s: unknown bd type BD%c\n", argv0, resp[4+8+2]);
di = resp + 4;
body = di + 8;
n -= 4 + 8;
if (n < 3 || di[0] != 'D' || di[1] != 'I' ||
body[0] != 'B' || body[1] != 'D') {
if(vflag)
fprint(2, "it's not a bd\n");
return -1;
}
if (vflag)
fprint(2, "read disc structure (bd) succeeded; di format %d\n",
di[2]);
drive->erasable = drive->recordable = No;
switch (body[2]) {
case 'O': /* read-Only */
break;
case 'R': /* Recordable */
drive->recordable = Yes;
break;
case 'W': /* reWritable */
drive->erasable = Yes;
break;
default:
fprint(2, "%s: unknown bd type BD%c\n", argv0, body[2]);
return -1;
}
drive->erasableset = drive->recordableset = 1;
drive->mmctype = Mmcbd;
return 0;
}
@ -809,10 +921,11 @@ mmcgettoc(Drive *drive)
drive->nameok = 0;
drive->nchange = drive->Scsi.nchange;
drive->changetime = drive->Scsi.changetime;
drive->writeok = drive->erasable = drive->recordable = drive->blank = 0;
drive->erasableset = drive->recordableset = drive->blankset = 0;
drive->writeok = No;
drive->erasable = drive->recordable = Unset;
getinvistrack(drive);
aux = drive->aux;
aux->mmcnwa = 0;
aux->mmcnwa = -1;
aux->nropen = aux->nwopen = 0;
aux->ntotby = aux->ntotbk = 0;
@ -822,7 +935,7 @@ mmcgettoc(Drive *drive)
}
/*
* TODO: set read ahead, MMC-6 §6.37, seems to control caching.
* should set read ahead, MMC-6 §6.37, seems to control caching.
*/
/*
@ -830,8 +943,8 @@ mmcgettoc(Drive *drive)
*/
if((n = mmcreadtoc(drive, Msfbit, 0, resp, sizeof(resp))) < 4) {
/*
* on a blank disc in a cd-rw, use readdiscinfo
* to find the track info.
* it could be a blank disc. in case it's a blank disc in a
* cd-rw drive, use readdiscinfo to try to find the track info.
*/
if(getdiscinfo(drive, resp, sizeof(resp)) < 7)
return -1;
@ -841,9 +954,8 @@ mmcgettoc(Drive *drive)
first = resp[3];
last = resp[6];
if(vflag)
print("blank disc %d %d\n", first, last);
/* the assumption of blankness may be unwarranted */
drive->writeok = drive->blank = drive->blankset = 1;
print("tracks %d-%d\n", first, last);
drive->writeok = Yes;
} else {
first = resp[2];
last = resp[3];
@ -858,26 +970,28 @@ mmcgettoc(Drive *drive)
}
}
/* deduce disc type */
drive->mmctype = Mmcnone;
drive->dvdtype = nil;
getdvdstruct(drive);
getconf(drive);
getbdstruct(drive);
if (Desperate)
bdguess(drive);
if (drive->mmctype == Mmcnone)
drive->mmctype = Mmccd; /* by default */
if (drive->recordable || drive->erasable)
drive->writeok = 1;
if (drive->recordable == Yes || drive->erasable == Yes)
drive->writeok = Yes;
if (vflag) {
fprint(2, "writeok %d", drive->writeok);
/* drive->blank is never used and hard to figure out */
// if (drive->blankset)
// fprint(2, " blank %d", drive->blank);
if (drive->recordableset)
if (drive->recordable != Unset)
fprint(2, " recordable %d", drive->recordable);
if (drive->erasableset)
if (drive->erasable != Unset)
fprint(2, " erasable %d", drive->erasable);
fprint(2, "\n");
print("first %d last %d\n", first, last);
fprint(2, "first %d last %d\n", first, last);
fprint(2, "it's a %s disc.\n\n", disctype(drive)); /* leak */
}
if(first == 0 && last == 0)
@ -954,7 +1068,7 @@ mmcsetbs(Drive *drive, int bs)
switch(bs){
case BScdda:
/* 2 audio channels without pre-emphasis */
settrkmode(p, Tmcdda); /* TODO: should be Tm2audio? */
settrkmode(p, Tmcdda); /* should be Tm2audio? */
p[Wpdatblktype] = Dbraw;
break;
case BScdrom:
@ -1023,9 +1137,8 @@ mmcread(Buf *buf, void *v, long nblock, ulong off)
* a cd drive with a cd in it and we're not reading data
* (e.g., reading audio).
*/
memset(cmd, 0, sizeof(cmd));
if (drive->type == TypeCD && drive->mmctype == Mmccd && bs != BScdrom) {
cmd[0] = ScmdReadcd;
initcdb(cmd, sizeof cmd, ScmdReadcd);
cmd[2] = off>>24;
cmd[3] = off>>16;
cmd[4] = off>>8;
@ -1049,7 +1162,7 @@ mmcread(Buf *buf, void *v, long nblock, ulong off)
return -1;
}
} else { /* e.g., TypeDA */
cmd[0] = ScmdRead12;
initcdb(cmd, sizeof cmd, ScmdRead12);
cmd[2] = off>>24;
cmd[3] = off>>16;
cmd[4] = off>>8;
@ -1111,7 +1224,7 @@ format(Drive *drive)
uchar *fmtdesc;
uchar cmd[6], parms[4+8];
if (drive->recordable && drive->mmctype != Mmcbd) {
if (drive->recordable == Yes && drive->mmctype != Mmcbd) {
werrstr("don't format write-once cd or dvd media");
return -1;
}
@ -1154,20 +1267,20 @@ format(Drive *drive)
static long
mmcxwrite(Otrack *o, void *v, long nblk)
{
int r;
uchar cmd[10];
Mmcaux *aux;
assert(o->omode == OWRITE);
aux = o->drive->aux;
if (aux->mmcnwa == 0 && scsiready(o->drive) < 0) {
if (aux->mmcnwa == -1 && scsiready(o->drive) < 0) {
werrstr("device not ready to write");
return -1;
}
aux->ntotby += nblk*o->track->bs;
aux->ntotbk += nblk;
memset(cmd, 0, sizeof(cmd));
cmd[0] = ScmdExtwrite; /* write (10) */
initcdb(cmd, sizeof cmd, ScmdExtwrite); /* write (10) */
cmd[2] = aux->mmcnwa>>24;
cmd[3] = aux->mmcnwa>>16;
cmd[4] = aux->mmcnwa>>8;
@ -1177,8 +1290,14 @@ mmcxwrite(Otrack *o, void *v, long nblk)
if(vflag)
print("%lld ns: write %ld at 0x%lux\n",
nsec(), nblk, aux->mmcnwa);
r = scsi(o->drive, cmd, sizeof(cmd), v, nblk*o->track->bs, Swrite);
if (r < 0)
fprint(2, "%s: write error at blk offset %,ld = "
"offset %,lld / bs %ld: %r\n",
argv0, aux->mmcnwa, (vlong)aux->mmcnwa * o->track->bs,
o->track->bs);
aux->mmcnwa += nblk;
return scsi(o->drive, cmd, sizeof(cmd), v, nblk*o->track->bs, Swrite);
return r;
}
static long
@ -1241,13 +1360,14 @@ getinvistrack(Drive *drive)
if(vflag)
print("getinvistrack: track #%d session #%d\n",
resp[2], resp[3]);
drive->invistrack = resp[2];
return resp[2];
}
static Otrack*
mmccreate(Drive *drive, int type)
{
int bs, invis;
int bs;
Mmcaux *aux;
Track *t;
Otrack *o;
@ -1271,15 +1391,11 @@ mmccreate(Drive *drive, int type)
return nil;
}
invis = getinvistrack(drive);
if (invis < 0)
invis = Invistrack;
/* comment out the returns for now; it should be no big deal - geoff */
if(mmctrackinfo(drive, invis, Maxtrack)) {
if(mmctrackinfo(drive, drive->invistrack, Maxtrack)) {
if (vflag)
fprint(2, "mmccreate: mmctrackinfo for invis track %d"
" failed: %r\n", invis);
" failed: %r\n", drive->invistrack);
werrstr("disc not writable");
// return nil;
}
@ -1287,20 +1403,20 @@ mmccreate(Drive *drive, int type)
werrstr("cannot set bs mode");
// return nil;
}
if(mmctrackinfo(drive, invis, Maxtrack)) {
if(mmctrackinfo(drive, drive->invistrack, Maxtrack)) {
if (vflag)
fprint(2, "mmccreate: mmctrackinfo for invis track %d"
" (2) failed: %r\n", invis);
" (2) failed: %r\n", drive->invistrack);
werrstr("disc not writable 2");
// return nil;
}
/* special hack for dvd-r: reserve the invisible track */
if (drive->mmctype == Mmcdvdminus && drive->writeok &&
drive->recordable && reserve(drive, invis) < 0) {
drive->recordable == Yes && reserve(drive, drive->invistrack) < 0) {
if (vflag)
fprint(2, "mmcreate: reserving track %d for dvd-r "
"failed: %r\n", invis);
"failed: %r\n", drive->invistrack);
return nil;
}
@ -1339,8 +1455,7 @@ mmcxclose(Drive *drive, int clf, int trackno)
{
uchar cmd[10];
memset(cmd, 0, sizeof(cmd));
cmd[0] = ScmdClosetracksess;
initcdb(cmd, sizeof cmd, ScmdClosetracksess);
/* cmd[1] & 1 is the immediate bit */
cmd[2] = clf; /* close function */
if(clf == Closetrack)
@ -1352,7 +1467,6 @@ mmcxclose(Drive *drive, int clf, int trackno)
void
mmcsynccache(Drive *drive)
{
int invis;
uchar cmd[10];
Mmcaux *aux;
@ -1364,7 +1478,7 @@ mmcsynccache(Drive *drive)
if (vflag) {
fprint(2, "syncing cache");
if (drive->mmctype == Mmcdvdminus && drive->writeok &&
drive->recordable)
drive->recordable == Yes)
fprint(2, "; dvd-r burning rest of track reservation, "
"will be slow");
fprint(2, "\n");
@ -1376,21 +1490,19 @@ mmcsynccache(Drive *drive)
aux->ntotby, aux->ntotbk, aux->mmcnwa);
}
invis = getinvistrack(drive);
if (invis < 0)
invis = Invistrack;
/*
* rsc: seems not to work on some drives.
* so ignore return code & don't issue on dvd+rw.
*/
if(drive->mmctype != Mmcdvdplus || !drive->erasable) {
if(drive->mmctype != Mmcdvdplus || drive->erasable == No) {
if (vflag)
fprint(2, "closing invisible track %d (not dvd+rw)...\n",
invis);
mmcxclose(drive, Closetrack, invis);
drive->invistrack);
mmcxclose(drive, Closetrack, drive->invistrack);
if (vflag)
fprint(2, "... done.\n");
}
getinvistrack(drive); /* track # has probably changed */
}
/*
@ -1445,7 +1557,7 @@ mmcfixate(Drive *drive)
setonesess(drive);
/* skip explicit close session on bd-r */
if (drive->mmctype != Mmcbd || drive->erasable) {
if (drive->mmctype != Mmcbd || drive->erasable == Yes) {
if (vflag)
fprint(2, "closing session and maybe finalizing...\n");
r = mmcxclose(drive, Closesessfinal, 0);
@ -1459,7 +1571,7 @@ mmcfixate(Drive *drive)
* Closedvdrbdfinal closes & finalizes dvd+r and bd-r.
*/
if ((drive->mmctype == Mmcdvdplus || drive->mmctype == Mmcbd) &&
!drive->erasable) {
drive->erasable == No) {
if (vflag)
fprint(2, "finalizing dvd+r or bd-r... "
"(won't print `done').\n");
@ -1475,8 +1587,7 @@ mmcblank(Drive *drive, int quick)
drive->nchange = -1; /* force reread toc */
memset(cmd, 0, sizeof(cmd));
cmd[0] = ScmdBlank; /* blank cd-rw media */
initcdb(cmd, sizeof cmd, ScmdBlank); /* blank cd-rw media */
/* immediate bit is 0x10 */
/* cmd[1] = 0 means blank the whole disc; = 1 just the header */
cmd[1] = quick ? 0x01 : 0x00;
@ -1519,8 +1630,7 @@ mmcsetspeed(Drive *drive, int r, int w)
char *rv;
uchar cmd[12];
memset(cmd, 0, sizeof(cmd));
cmd[0] = ScmdSetcdspeed;
initcdb(cmd, sizeof cmd, ScmdSetcdspeed);
cmd[2] = r>>8;
cmd[3] = r;
cmd[4] = w>>8;