Exemple #1
0
static int
mmcsetpage10(Drive *drive, int page, void *v)
{
	uint8_t cmd[10], *p, *pagedata;
	int len, n;

	/* allocate parameter list, copy in mode page, fill in header */
	pagedata = v;
	assert(pagedata[0] == page);
	len = Mode10parmhdrlen + Modepaghdrlen + pagedata[1];
	p = emalloc(len);
	memmove(p + Mode10parmhdrlen, pagedata, pagedata[1]);
	/* parameter list header */
	p[0] = 0;
	p[1] = len - 2;

	/* set up CDB */
	initcdb(cmd, sizeof cmd, ScmdMselect10);
	cmd[1] = 0x10;			/* format not vendor-specific */
	cmd[8] = len;

	n = scsi(&drive->scsi, cmd, sizeof(cmd), p, len, Swrite);

	free(p);
	if(n < len)
		return -1;
	return 0;
}
Exemple #2
0
/*
 * `read cd' only works for CDs; for everybody else,
 * we'll try plain `read (12)'.  only use read cd if it's
 * a cd drive with a cd in it and we're not reading data
 * (e.g., reading audio).
 */
static int
fillread12cdb(Drive *drive, uint8_t *cmd, int32_t nblock, uint32_t off,
	      int bs)
{
	if (drive->type == TypeCD && drive->mmctype == Mmccd && bs != BScdrom) {
		initcdb(cmd, 12, ScmdReadcd);
		cmd[6] = nblock>>16;
		cmd[7] = nblock>>8;
		cmd[8] = nblock>>0;
		cmd[9] = 0x10;
		switch(bs){
		case BScdda:
			cmd[1] = 0x04;
			break;
		case BScdrom:
			cmd[1] = 0x08;
			break;
		case BScdxa:
			cmd[1] = 0x0C;
			break;
		default:
			werrstr("unknown bs %d", bs);
			return -1;
		}
	} else {				/* e.g., TypeDA */
Exemple #3
0
int
mmcstatus(Drive *drive)
{
	uchar cmd[12];

	initcdb(cmd, sizeof cmd, ScmdCDstatus);		/* mechanism status */
	return scsi(drive, cmd, sizeof(cmd), nil, 0, Sread);
}
Exemple #4
0
static int
start(Drive *drive, int code)
{
	uchar cmd[6];

	initcdb(cmd, sizeof cmd, ScmdStart);
	cmd[4] = code;
	return scsi(drive, cmd, sizeof(cmd), cmd, 0, Snone);
}
Exemple #5
0
static int
start(Drive *drive, int code)
{
	uint8_t cmd[6];

	initcdb(cmd, sizeof cmd, ScmdStart);
	cmd[4] = code;
	return scsi(&drive->scsi, cmd, sizeof(cmd), cmd, 0, Snone);
}
Exemple #6
0
/* t is a track number on disc, i is an index into drive->track[] for result */
static int
mmctrackinfo(Drive *drive, int t, int i)
{
	int n, type, bs;
	uint32_t beg, size;
	uint8_t tmode;
	uint8_t cmd[10], resp[255];
	Track *track;

	initcdb(cmd, sizeof cmd, ScmdRtrackinfo);
	cmd[1] = 1;			/* address below is logical track # */
	cmd[2] = t>>24;
	cmd[3] = t>>16;
	cmd[4] = t>>8;
	cmd[5] = t;
	cmd[7] = sizeof(resp)>>8;
	cmd[8] = sizeof(resp);
	n = scsi(&drive->scsi, cmd, sizeof(cmd), resp, sizeof(resp), Sread);
	if(n < 28) {
		if(vflag)
			print("trackinfo %d fails n=%d: %r\n", t, n);
		return -1;
	}

	tmode = resp[5] & 0x0D;
//	dmode = resp[6] & 0x0F;

	gettypebs(tmode, t, i, &type, &bs);

	beg  = bige(&resp[8]);
	size = bige(&resp[24]);

	track = &drive->track[i];
	track->mtime = drive->changetime;
	track->beg = beg;
	track->end = beg + size;
	track->type = type;
	track->bs = bs;
	track->size = (int64_t)(size-2) * bs;	/* -2: skip lead out */

	if(resp[6] & (1<<6)) {			/* blank? */
		track->type = TypeBlank;
		drive->writeok = Yes;
	}

	if(vflag)
		print(" start %lu end %lu", beg, beg + size - 1);
	gettracknwa(drive, t, beg, resp);
	if (vflag)
		print("\n");
	return 0;
}
Exemple #7
0
static int
getdevtype(Drive *drive)
{
	int n;
	uchar cmd[6], resp[Pagesz];

	initcdb(cmd, sizeof cmd, ScmdInq);
	cmd[3] = sizeof resp >> 8;
	cmd[4] = sizeof resp;
	n = scsi(drive, cmd, sizeof(cmd), resp, sizeof resp, Sread);
	if (n < 8)
		return -1;
	return resp[0] & 037;
}
Exemple #8
0
static int
getbdstruct(Drive *drive)
{
	int n;
	uchar cmd[12], resp[4100];

	initcdb(cmd, sizeof cmd, ScmdReadDVD); /* actually, read disc structure */
	cmd[1] = 1;			/* media type: bd */
	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);
	/*
	 * 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
	 * 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]);
		return -1;
	}
	drive->erasableset = drive->recordableset = 1;
	drive->mmctype = Mmcbd;
	return 0;
}
Exemple #9
0
/* this may fail for blank media */
static int
mmcreadtoc(Drive *drive, int type, int track, void *data, int nbytes)
{
	uint8_t cmd[10];

	initcdb(cmd, sizeof cmd, ScmdRTOC);
	cmd[1] = type;				/* msf bit & reserved */
	cmd[2] = Tocfmttoc;
	cmd[6] = track;				/* track/session */
	cmd[7] = nbytes>>8;
	cmd[8] = nbytes;

	/*
	 * printing iounit(drive->scsi.rawfd) here yields
	 *	iounit(3) = 0;		# for local access
	 *	iounit(3) = 65512;	# for remote access via /mnt/term
	 */
	return scsi(&drive->scsi, cmd, sizeof(cmd), data, nbytes, Sread);
}
Exemple #10
0
static int
getdvdstruct(Drive *drive)
{
	int n, cat;
	uchar cmd[12], resp[Pagesz];

	initcdb(cmd, sizeof cmd, ScmdReadDVD); /* actually, read disc structure */
	cmd[1] = 0;			/* media type: dvd */
	cmd[7] = 0;			/* format code: physical format */
	cmd[8] = sizeof resp >> 8;	/* allocation length */
	cmd[9] = sizeof resp;
	n = scsi(drive, cmd, sizeof(cmd), resp, sizeof resp, Sread);
	if (n < 7)
		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)
		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;
	/*
	 * 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;
	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->mmctype = (cat >= 8? Mmcdvdplus: Mmcdvdminus);
	return 0;
}
Exemple #11
0
static int
getdiscinfo(Drive *drive, uint8_t resp[], int resplen)
{
	int n;
	uint8_t cmd[10];

	initcdb(cmd, sizeof cmd, ScmdRdiscinfo);
	cmd[7] = resplen>>8;
	cmd[8] = resplen;
	n = scsi(&drive->scsi, 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 -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? */
	return n;
}
Exemple #12
0
static int
mmcgetpage6(Drive *drive, int page, void *v)
{
	uint8_t cmd[6], resp[512];
	int n;

	initcdb(cmd, sizeof cmd, ScmdMsense6);
	cmd[2] = page;
	cmd[4] = 255;			/* allocation length */

	n = scsi(&drive->scsi, cmd, sizeof(cmd), resp, sizeof(resp), Sread);
	if(n < Mode6parmhdrlen)
		return -1;

	n -= Mode6parmhdrlen + resp[3];
	if(n < 0)
		return -1;
	if(n > Pagesz)
		n = Pagesz;

	memmove(v, &resp[Mode6parmhdrlen + resp[3]], n);
	return n;
}
Exemple #13
0
static int
getconfcmd(Drive *drive, uint8_t *resp, int respsz)
{
	int n;
	uint32_t datalen;
	uint8_t cmd[10];

	initcdb(cmd, sizeof cmd, Scmdgetconf);
	cmd[3] = 0;			/* start with profile list feature */
	cmd[7] = respsz >> 8;
	cmd[8] = respsz;
	n = scsi(&drive->scsi, cmd, sizeof cmd, resp, respsz, 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;
	return datalen;
}
Exemple #14
0
static int
mmcsetpage6(Drive *drive, int page, void *v)
{
	uint8_t cmd[6], *p, *pagedata;
	int len, n;

	if (vflag)
		print("mmcsetpage6 called!\n");
	pagedata = v;
	assert(pagedata[0] == page);
	len = Mode6parmhdrlen + Modepaghdrlen + pagedata[1];
	p = emalloc(len);
	memmove(p + Mode6parmhdrlen, pagedata, pagedata[1]);

	initcdb(cmd, sizeof cmd, ScmdMselect6);
	cmd[1] = 0x10;			/* format not vendor-specific */
	cmd[4] = len;

	n = scsi(&drive->scsi, cmd, sizeof(cmd), p, len, Swrite);
	free(p);
	if(n < len)
		return -1;
	return 0;
}
Exemple #15
0
static int
mmcgetpage10(Drive *drive, int page, void *v)
{
	uint8_t cmd[10], resp[512];
	int n, r;

	initcdb(cmd, sizeof cmd, ScmdMsense10);
	cmd[2] = page;
	cmd[8] = 255;			/* allocation length: buffer size */
	n = scsi(&drive->scsi, cmd, sizeof(cmd), resp, sizeof(resp), Sread);
	if(n < Mode10parmhdrlen)
		return -1;

	r = (resp[6]<<8) | resp[7];	/* block descriptor length */
	n -= Mode10parmhdrlen + r;

	if(n < 0)
		return -1;
	if(n > Pagesz)
		n = Pagesz;

	memmove(v, &resp[Mode10parmhdrlen + r], n);
	return n;
}
Exemple #16
0
static int
getbdstruct(Drive *drive)
{
	int n;
	uint8_t cmd[12], resp[4+4096];
	uint8_t *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] = (int8_t)sizeof resp;
	n = scsi(&drive->scsi, 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 (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.
	 */
	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;
	}
	/* printed  getbdstruct: di bytes 98 di units/layers 32 */
	// fprint(2, "getbdstruct: di bytes %d di units/layers %d\n", di[6], di[3]);
	drive->mmctype = Mmcbd;
	return 0;
}