ref: 9b5b68a3022a6503aab296986fec1b463f9e6b1e
parent: c7ad44a0489ab779e410b58c0c504b9d8a99aa9c
author: cinap_lenrek <[email protected]>
date: Wed Aug 1 17:34:14 EDT 2012
cdfs: pull updates from sources
--- a/sys/src/cmd/cdfs/dat.h
+++ b/sys/src/cmd/cdfs/dat.h
@@ -30,6 +30,17 @@
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 @@
};
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 @@
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 */
--- a/sys/src/cmd/cdfs/fns.h
+++ b/sys/src/cmd/cdfs/fns.h
@@ -4,6 +4,7 @@
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*);
--- a/sys/src/cmd/cdfs/main.c
+++ b/sys/src/cmd/cdfs/main.c
@@ -192,7 +192,7 @@
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 @@
}
/* 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 @@
}
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 @@
break;
case Qwa:
- if(drive->writeok == 0 ||
+ if(drive->writeok == No ||
drive->mmctype != Mmcnone &&
drive->mmctype != Mmccd)
return 0;
@@ -281,7 +281,7 @@
break;
case Qwd:
- if(drive->writeok == 0)
+ if(drive->writeok == No)
return 0;
d->name = "wd";
d->qid.type = QTDIR;
@@ -340,6 +340,7 @@
readctl(Req *r)
{
int i, isaudio;
+ ulong nwa;
char *p, *e, *ty;
char s[1024];
Msf *m;
@@ -375,9 +376,14 @@
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 @@
if(dev == nil || mtpt == nil || argc > 0)
usage();
+ werrstr("");
if((s = openscsi(dev)) == nil)
sysfatal("openscsi '%s': %r", dev);
if((drive = mmcprobe(s)) == nil)
--- a/sys/src/cmd/cdfs/mmc.c
+++ b/sys/src/cmd/cdfs/mmc.c
@@ -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 @@
int pagecmdsz;
/* disc characteristics */
- ulong mmcnwa;
+ long mmcnwa; /* next writable address (block #) */
int nropen;
int nwopen;
vlong ntotby;
@@ -60,6 +62,8 @@
"type-15-unknown",
};
+static int getinvistrack(Drive *drive);
+
static ulong
bige(void *p)
{
@@ -110,16 +114,6 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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,6 +465,7 @@
mmctrackinfo(Drive *drive, int t, int i)
{
int n, type, bs;
+ long newnwa;
ulong beg, size;
uchar tmode;
uchar cmd[10], resp[255];
@@ -486,8 +472,7 @@
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 @@
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 @@
{
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 @@
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,22 +597,108 @@
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;
+}
+
+static int
getdvdstruct(Drive *drive)
{
int n, cat;
@@ -648,12 +710,12 @@
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 */
if (vflag)
@@ -660,7 +722,7 @@
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,
@@ -667,58 +729,108 @@
* 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')
+ 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\n");
- drive->erasable = drive->recordable = 0;
- switch (resp[4+8+2]) {
- case 'O':
- drive->blank = 0;
- drive->blankset = 1;
+ 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 = 1;
+ drive->recordable = Yes;
break;
case 'W': /* reWritable */
- drive->erasable = 1;
+ drive->erasable = Yes;
break;
default:
- fprint(2, "%s: unknown bd type BD%c\n", argv0, resp[4+8+2]);
+ 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 @@
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 @@
}
/*
- * 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 @@
*/
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 @@
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 @@
}
}
+ /* 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 @@
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 @@
* 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 @@
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 @@
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,12 +1267,13 @@
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;
}
@@ -1166,8 +1280,7 @@
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 @@
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,6 +1360,7 @@
if(vflag)
print("getinvistrack: track #%d session #%d\n",
resp[2], resp[3]);
+ drive->invistrack = resp[2];
return resp[2];
}
@@ -1247,7 +1367,7 @@
static Otrack*
mmccreate(Drive *drive, int type)
{
- int bs, invis;
+ int bs;
Mmcaux *aux;
Track *t;
Otrack *o;
@@ -1271,15 +1391,11 @@
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,10 +1403,10 @@
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;
}
@@ -1297,10 +1413,10 @@
/* 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 @@
{
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 @@
void
mmcsynccache(Drive *drive)
{
- int invis;
uchar cmd[10];
Mmcaux *aux;
@@ -1364,7 +1478,7 @@
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 @@
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 @@
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 @@
* 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 @@
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 @@
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;