Exemple #1
0
/*
 * infer endings from the beginnings of other tracks.
 */
static int
mmcinfertracks(Drive *drive, int first, int last)
{
	int i;
	uint8_t resp[1024];
	uint32_t tot;
	Track *t;

	if (vflag)
		fprint(2, "inferring tracks from toc\n");
	for(i = first; i <= last; i++) {
		memset(resp, 0, sizeof(resp));
		if(mmcreadtoc(drive, 0, i, resp, sizeof(resp)) < 0) {
			last = i - 1;
			if (last < 1)
				last = 1;
			break;
		}
		t = &drive->track[i-first];
		t->mtime = drive->changetime;
		t->type = TypeData;
		t->bs = BScdrom;
		t->beg = bige(resp+8);
		if(!(resp[5] & 4)) {
			t->type = TypeAudio;
			t->bs = BScdda;
		}
	}

	if((int32_t)drive->track[0].beg < 0)  /* i've seen negative track 0's */
		drive->track[0].beg = 0;

	tot = 0;
	memset(resp, 0, sizeof(resp));
	/* 0xAA is lead-out */
	if(mmcreadtoc(drive, 0, 0xAA, resp, sizeof(resp)) < 0)
		print("bad mmcreadtoc\n");
	if(resp[6])
		tot = bige(resp+8);

	t = nil;
	for(i=last; i>=first; i--) {
		t = &drive->track[i-first];
		t->end = tot;
		tot = t->beg;
		if(t->end <= t->beg)
			t->beg = t->end = 0;
		/* -2: skip lead out */
		t->size = (t->end - t->beg - 2) * (int64_t)t->bs;
	}
	fprint(2, "infertracks: nwa should be %,lld; tot = %,ld\n", t->size, tot);
	return last;
}
Exemple #2
0
/*
 * infer endings from the beginnings of other tracks.
 */
static void
mmcinfertracks(Drive *drive, int first, int last)
{
	int i;
	uchar resp[1024];
	ulong tot;
	Track *t;

	if (vflag)
		fprint(2, "inferring tracks\n");
	for(i = first; i <= last; i++) {
		memset(resp, 0, sizeof(resp));
		if(mmcreadtoc(drive, 0, i, resp, sizeof(resp)) < 0)
			break;
		t = &drive->track[i-first];
		t->mtime = drive->changetime;
		t->type = TypeData;
		t->bs = BScdrom;
		t->beg = bige(resp+8);
		if(!(resp[5] & 4)) {
			t->type = TypeAudio;
			t->bs = BScdda;
		}
	}

	if((long)drive->track[0].beg < 0)  /* i've seen negative track 0's */
		drive->track[0].beg = 0;

	tot = 0;
	memset(resp, 0, sizeof(resp));
	/* 0xAA is lead-out */
	if(mmcreadtoc(drive, 0, 0xAA, resp, sizeof(resp)) < 0)
		print("bad\n");
	if(resp[6])
		tot = bige(resp+8);

	for(i=last; i>=first; i--) {
		t = &drive->track[i-first];
		t->end = tot;
		tot = t->beg;
		if(t->end <= t->beg)
			t->beg = t->end = 0;
		/* -2: skip lead out */
		t->size = (t->end - t->beg - 2) * (vlong)t->bs;
	}
}
Exemple #3
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;
}
Exemple #4
0
/* this gets called a lot from main.c's 9P routines */
static int
mmcgettoc(Drive *drive)
{
	int first, last;
	uint8_t resp[1024];

	/*
	 * 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 &&
	    !drive->relearn)
		return 0;
	drive->relearn = 0;

	/*
	 * the disc in the drive may have just been changed,
	 * so rescan it and relearn all about it.
	 */
	if (vflag &&
	    (drive->nchange != drive->scsi.nchange || drive->changetime == 0))
		fprint(2, "\nnew disc in drive\n");
	initdrive(drive);

	if (findntracks(drive, &first, &last) < 0)
		return -1;
	/*
	 * we would like to call findtracks before finddisctype so that
	 * we can format bd-rs at the right capacity with explicit spares
	 * ratio given, but findtracks needs the disc type to be already set.
	 * format is called from getconf from finddisctype before getbdstruct.
	 * luckily, FORMAT UNIT (thus format()) doesn't seem to care when we
	 * don't provide an explicit spares ratio.
	 */
	/* calls getdvdstruct, getconf and getbdstruct, in that order */
	finddisctype(drive, first, last);	/* formats bds at first use */
	return findtracks(drive, first, last);
}
Exemple #5
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;
}