Exemplo n.º 1
0
Arquivo: mmc.c Projeto: Requaos/harvey
/* needs drive->mmctype to be already set */
static int
alltrackinfo(Drive *drive, int first, int last)
{
	int i;
	int32_t nwa;
	int64_t cap;
	char *osfx;
	Mmcaux *aux;
	Track *track;

	for(i = first; i <= last; i++)
		if (mmctrackinfo(drive, i, i - first) < 0) {
			last = i - 1;
			if (last < 1)
				last = 1;
			break;
		}
	track = &drive->track[last - first];
	drive->end = track->end;
	if (drive->mmctype == Mmcbd) {
		/* allow for lower apparent capacity due to reserved spares */
		cap = (int64_t)track->end * track->bs;
		osfx = drive->laysfx;
		if (cap >= (int64_t)101*GB)
			drive->laysfx = "-ql";		/* 128GB nominal */
		else if (cap >= (int64_t)51*GB)
			drive->laysfx = "-tl";		/* 100GB nominal */
		else if (cap >= (int64_t)26*GB)
			drive->laysfx = "-dl";		/* 50GB nominal */
		else
			drive->laysfx = "";		/* 25GB nominal */
		if (vflag)
			fprint(2, "capacity %,lu sectors (%,lld bytes); bd%s\n",
				track->end, cap, drive->laysfx);
		if (osfx == nil || strcmp(osfx, drive->laysfx) != 0)
			drive->relearn = 1;
	}
	if (drive->mmctype == Mmcnone)
		return last;				/* no disc */
	nwa = computenwa(drive, first, last);
	aux = drive->aux;
	if (vflag)
		fprint(2, "nwa from drive %,ld; computed nwa %,ld\n",
			aux->mmcnwa, nwa);
	if (aux->mmcnwa == -1 && nwa == 0)
		return last;			/* probably a blank disc */
	if (aux->mmcnwa == -1)
		fprint(2, "%s: disc is full\n", argv0);
	/* reconcile differing nwas */
	if (aux->mmcnwa != nwa) {
		fprint(2, "%s: nwa from drive %,ld != computed nwa %,ld\n",
			argv0, aux->mmcnwa, nwa);
		fprint(2, "\tbe careful!  assuming computed nwa\n");
		/* the invisible track may still start at the old nwa. */
		// aux->mmcnwa = nwa;
	}
	return last;
}
Exemplo n.º 2
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;
}