Beispiel #1
0
Datei: mmc.c Projekt: npe9/harvey
static int
playstatus(Drive *d, Cdstatus *stat)
{
	uchar cmd[12], resp[16];

	memset(cmd, 0, sizeof cmd);
	cmd[0] = 0x42;
	cmd[1] = 0x02;
	cmd[2] = 0x40;
	cmd[3] = 0x01;
	cmd[7] = sizeof(resp)>>8;
	cmd[8] = sizeof(resp);
	if(scsi(d->scsi, cmd, sizeof(cmd), resp, sizeof(resp), Sread) < 0)
		return -1;

	switch(resp[1]){
	case 0x11:
		stat->state = Splaying;
		break;
	case 0x12:
		stat->state = Spaused;
		break;
	case 0x13:
		stat->state = Scompleted;
		break;
	case 0x14:
		stat->state = Serror;
		break;
	case 0x00:	/* not supported */
	case 0x15:	/* no current status to return */
	default:
		stat->state = Sunknown;
		break;
	}

	stat->track = resp[6];
	stat->index = resp[7];
	stat->abs = rdmsf(resp+9);
	stat->rel = rdmsf(resp+13);
	return 0;
}
Beispiel #2
0
static int
findntracks(Drive *drive, int *firstp, int *lastp)
{
	int i, n, first, last;
	uint8_t resp[1024];

	if((n = mmcreadtoc(drive, Msfbit, 0, resp, sizeof(resp))) < 4) {
		/*
		 * 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;
		assert((resp[2] & 0340) == 0);	/* data type 0 */
		if(resp[4] != 1)
			print("multi-session disc %d\n", resp[4]);
		drive->writeok = Yes;

		/*
		 * some drives (e.g., LG's BDs) report only 1 track on an
		 * unfinalized disc, so probe every track.  the nwa reported
		 * by such drives may be wrong (e.g., 0), so compute that too.
		 */
		first = resp[3];
		last = resp[6];
		if(vflag)
			print("rdiscinfo tracks %d-%d (last==1 means TBD)\n",
				first, last);
		if(last == 1)
			last = Maxresptracks;	/* probe the tracks */
	} else {
		first = resp[2];
		last = resp[3];
		if(vflag)
			print("toc tracks %d-%d (last==1 means TBD)\n",
				first, last);
		if(last == 1)
			last = Maxresptracks;	/* probe the tracks */

		if(n >= 4+8*(last-first+2)) {
			/* resp[4 + i*8 + 2] is track # */
			/* <=: track[last-first+1] = end */
			for(i=0; i<=last-first+1; i++)
				drive->track[i].mbeg = rdmsf(resp+4+i*8+5);
			for(i=0; i<last-first+1; i++)
				drive->track[i].mend = drive->track[i+1].mbeg;
		}
	}
	*firstp = first;
	*lastp = last;
	return 0;
}
Beispiel #3
0
/* this gets called a lot from main.c's 9P routines */
static int
mmcgettoc(Drive *drive)
{
	int i, n, first, last;
	uchar resp[1024];
	Mmcaux *aux;

	/*
	 * if someone has swapped the cd,
	 * mmcreadtoc will get ``medium changed'' and the
	 * scsi routines will set nchange and changetime in the
	 * scsi device.
	 */
	mmcreadtoc(drive, 0, 0, resp, sizeof(resp));
	if(drive->Scsi.changetime == 0) {	/* no media present */
		drive->mmctype = Mmcnone;
		drive->ntrack = 0;
		return 0;
	}
	/*
	 * if the disc doesn't appear to be have been changed, and there
	 * is a disc in this drive, there's nothing to do (the common case).
	 */
	if(drive->nchange == drive->Scsi.nchange && drive->changetime != 0)
		return 0;

	/*
	 * the disc in the drive may have just been changed,
	 * so rescan it and relearn all about it.
	 */

	drive->ntrack = 0;
	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;
	aux = drive->aux;
	aux->mmcnwa = 0;
	aux->nropen = aux->nwopen = 0;
	aux->ntotby = aux->ntotbk = 0;

	for(i=0; i<nelem(drive->track); i++){
		memset(&drive->track[i].mbeg, 0, sizeof(Msf));
		memset(&drive->track[i].mend, 0, sizeof(Msf));
	}

	/*
	 * TODO: set read ahead, MMC-6 §6.37, seems to control caching.
	 */

	/*
	 * find number of tracks
	 */
	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.
		 */
		if(getdiscinfo(drive, resp, sizeof(resp)) < 7)
			return -1;
		assert((resp[2] & 0340) == 0);	/* data type 0 */
		if(resp[4] != 1)
			print("multi-session disc %d\n", resp[4]);
		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;
	} else {
		first = resp[2];
		last = resp[3];

		if(n >= 4+8*(last-first+2)) {
			/* resp[4 + i*8 + 2] is track # */
			/* <=: track[last-first+1] = end */
			for(i=0; i<=last-first+1; i++)
				drive->track[i].mbeg = rdmsf(resp+4+i*8+5);
			for(i=0; i<last-first+1; i++)
				drive->track[i].mend = drive->track[i+1].mbeg;
		}
	}

	drive->mmctype = Mmcnone;
	drive->dvdtype = nil;
	getdvdstruct(drive);
	getbdstruct(drive);
	if (drive->mmctype == Mmcnone)
		drive->mmctype = Mmccd;		/* by default */
	if (drive->recordable || drive->erasable)
		drive->writeok = 1;

	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)
			fprint(2, " recordable %d", drive->recordable);
		if (drive->erasableset)
			fprint(2, " erasable %d", drive->erasable);
		fprint(2, "\n");
		print("first %d last %d\n", first, last);
	}

	if(first == 0 && last == 0)
		first = 1;

	if(first <= 0 || first >= Maxtrack) {
		werrstr("first table %d not in range", first);
		return -1;
	}
	if(last <= 0 || last >= Maxtrack) {
		werrstr("last table %d not in range", last);
		return -1;
	}

	if(drive->cap & Cwrite)			/* CDR drives are easy */
		for(i = first; i <= last; i++)
			mmctrackinfo(drive, i, i - first);
	else
		/*
		 * otherwise we need to infer endings from the
		 * beginnings of other tracks.
		 */
		mmcinfertracks(drive, first, last);

	drive->firsttrack = first;
	drive->ntrack = last+1-first;
	return 0;
}
Beispiel #4
0
Datei: mmc.c Projekt: npe9/harvey
/* not a Drive, so that we don't accidentally touch Drive.toc */
int
gettoc(Scsi *s, Toc *t)
{
	int i, n;
	uchar cmd[12];
	uchar resp[1024];

Again:
	memset(t, 0, sizeof(*t));
	memset(cmd, 0, sizeof cmd);
	cmd[0] = 0x43;
	cmd[1] = 0x02;
	cmd[7] = sizeof(resp)>>8;
	cmd[8] = sizeof(resp);

	s->changetime = 1;
	/* scsi sets nchange, changetime */
	if(scsi(s, cmd, sizeof cmd, resp, sizeof(resp), Sread) < 4)
		return -1;

	if(s->changetime == 0) {
		t->ntrack = 0;
		werrstr("no media");
		return -1;
	}

	if(t->nchange == s->nchange && t->changetime != 0)
		return 0;

	t->nchange = s->nchange;
	t->changetime = s->changetime;

	if(t->ntrack > MTRACK)
		t->ntrack = MTRACK;

DPRINT(2, "%d %d\n", resp[3], resp[2]);
	t->ntrack = resp[3]-resp[2]+1;
	t->track0 = resp[2];

	n = ((resp[0]<<8) | resp[1])+2;
	if(n < 4+8*(t->ntrack+1)) {
		werrstr("bad read0 %d %d", n, 4+8*(t->ntrack+1));
		return -1;
	}

	for(i=0; i<=t->ntrack; i++)		/* <=: track[ntrack] = end */
		t->track[i].start = rdmsf(resp+4+i*8+5);

	for(i=0; i<t->ntrack; i++)
		t->track[i].end = t->track[i+1].start;

	memset(cmd, 0, sizeof cmd);
	cmd[0] = 0x43;
	cmd[7] = sizeof(resp)>>8;
	cmd[8] = sizeof(resp);
	if(scsi(s, cmd, sizeof cmd, resp, sizeof(resp), Sread) < 4)
		return -1;

	if(s->changetime != t->changetime || s->nchange != t->nchange) {
		fprint(2, "disk changed underfoot; repeating\n");
		goto Again;
	}

	n = ((resp[0]<<8) | resp[1])+2;
	if(n < 4+8*(t->ntrack+1)) {
		werrstr("bad read");
		return -1;
	}

	for(i=0; i<=t->ntrack; i++)
		t->track[i].bstart = rdlba(resp+4+i*8+5);

	for(i=0; i<t->ntrack; i++)
		t->track[i].bend = t->track[i+1].bstart;

	return 0;
}