Example #1
0
/*
 * Builds track information database for track trackno. If trackno is
 * -1, builds the database for next blank track.
 */
int
build_track_info(cd_device *dev, int trackno, struct track_info *t_info)
{
	uchar_t *ti;
	uchar_t toc[20];		/* 2 entries + 4 byte header */
	int ret;

	(void) memset(t_info, 0, sizeof (*t_info));
	/* 1st try READ TRACK INFORMATION */
	ti = (uchar_t *)my_zalloc(TRACK_INFO_SIZE);
	t_info->ti_track_no = trackno;

	/* Gererate faked information for writing to DVD */
	if (device_type != CD_RW) {
		uint_t bsize;

		t_info->ti_flags = 0x3000;
		t_info->ti_track_no = 1;
		t_info->ti_session_no = 1;
		t_info->ti_track_mode = 0x4;
		t_info->ti_data_mode = 1;
		t_info->ti_start_address = 0;

		/* only 1 track on DVD make it max size */
		t_info->ti_track_size = read_format_capacity(target->d_fd,
		    &bsize);
		if (t_info->ti_track_size < MAX_CD_BLKS) {
			t_info->ti_track_size = MAX_DVD_BLKS;
		}

		t_info->ti_nwa = 0;
		t_info->ti_lra = 0;
		t_info->ti_packet_size = 0x10;
		t_info->ti_free_blocks = 0;
	}

	if (read_track_info(dev->d_fd, trackno, ti)) {

		if (debug)
			(void) printf("using read_track_info for TOC \n");

		t_info->ti_track_no = ti[2];
		t_info->ti_session_no = ti[3];
		t_info->ti_flags = (ti[6] >> 4) & 0xf;
		t_info->ti_flags |= (uint32_t)(ti[5] & 0xf0);
		t_info->ti_flags |= (uint32_t)(ti[7]) << 8;
		t_info->ti_flags |= TI_SESSION_NO_VALID | TI_FREE_BLOCKS_VALID;
		t_info->ti_track_mode = ti[5] & 0xf;
		if ((ti[6] & 0xf) == 0xf)
			t_info->ti_data_mode = 0xff;
		else
			t_info->ti_data_mode = ti[6] & 0xf;
		t_info->ti_start_address = read_scsi32(&ti[8]);
		t_info->ti_nwa = read_scsi32(&ti[12]);
		t_info->ti_free_blocks = read_scsi32(&ti[16]);
		t_info->ti_packet_size = read_scsi32(&ti[20]);
		t_info->ti_track_size = read_scsi32(&ti[24]);
		t_info->ti_lra = read_scsi32(&ti[28]);
		free(ti);
		return (1);
	}
	/* READ TRACK INFORMATION not supported, try other options */
	free(ti);
	/*
	 * We can get info for next blank track if READ TRACK INFO is not
	 * supported.
	 */
	if (trackno == -1)
		return (0);

	if (debug)
		(void) printf("using READ_TOC for TOC\n");

	/* Try Read TOC */
	if (!read_toc(dev->d_fd, 0, trackno, 20, toc)) {
		return (0);
	}
	t_info->ti_start_address = read_scsi32(&toc[8]);
	t_info->ti_track_mode = toc[5] & 0xf;
	t_info->ti_track_size = read_scsi32(&toc[16]) - read_scsi32(&toc[8]);
	t_info->ti_data_mode = get_data_mode(dev->d_fd, read_scsi32(&toc[8]));

	/* Numbers for audio tracks are always in 2K chunks */
	if ((dev->d_blksize == 512) && ((t_info->ti_track_mode & 4) == 0)) {
		t_info->ti_start_address /= 4;
		t_info->ti_track_size /= 4;
	}

	/* Now find out the session thing */
	ret = read_toc(dev->d_fd, 1, trackno, 12, toc);

	/*
	 * Make sure that the call succeeds and returns the requested
	 * TOC size correctly.
	 */

	if ((ret == 0) || (toc[1] != 0x0a)) {

		/* For ATAPI drives or old Toshiba drives */
		ret = read_toc_as_per_8020(dev->d_fd, 1, trackno, 12, toc);
	}
	/* If this goes through well TOC length will always be 0x0a */
	if (ret && (toc[1] == 0x0a)) {
		if (trackno >= toc[6]) {
			t_info->ti_session_no = toc[3];
			t_info->ti_flags |= TI_SESSION_NO_VALID;
		}
		/*
		 * This might be the last track of this session. If so,
		 * exclude the leadout and next lead in.
		 */
		if (trackno == (toc[6] - 1)) {
			/*
			 * 1.5 Min leadout + 1 min. leadin + 2 sec. pre-gap.
			 * For 2nd+ leadout it will be 0.5 min. But currently
			 * there is no direct way. And it will not happen
			 * for any normal case.
			 *
			 * 75 frames/sec, 60 sec/min, so leadin gap is
			 * ((1.5 +1)*60 + 2)*75 = 11400 frames (blocks)
			 */
			t_info->ti_track_size -= 11400;
		}
	}
	return (1);
}
Example #2
0
void
info(void)
{
	uchar_t *toc, *p, *conf;
	int ret, toc_size;
	uint_t bsize;
	size_t cap = 0;
	char *msg;
	struct track_info *ti;

	msg = gettext("Cannot read Table of contents\n");

	get_media_type(target->d_fd);

	(void) printf(gettext("\nDevice : %.8s %.16s\n"),
	    &target->d_inq[8], &target->d_inq[16]);
	(void) printf(gettext("Firmware : Rev. %.4s (%.12s)\n"),
	    &target->d_inq[32], &target->d_inq[36]);

	if (check_device(target, CHECK_DEVICE_NOT_READY)) {
		(void) check_device(target, CHECK_NO_MEDIA |
		    EXIT_IF_CHECK_FAILED);
		(void) check_device(target, CHECK_DEVICE_NOT_READY |
		    EXIT_IF_CHECK_FAILED);
	}

	if (verbose != 0) {
		/*
		 * Determine the media type by reading the active profile
		 * from the profile list.
		 */
		(void) printf(gettext("Media Type : "));

		conf = (uchar_t *)my_zalloc(MMC_FTR_HDR_LEN);

		if (get_configuration(target->d_fd, MMC_FTR_PRFL_LIST,
		    MMC_FTR_HDR_LEN, conf))
			print_profile_name(read_scsi16(&conf[6]), 0, 1);
		else
			(void) printf(gettext("UNKNOWN\n"));

		free(conf);

		/*
		 * Get the start address of the last possible lead out.
		 */
		cap = get_last_possible_lba(target);

		/*
		 * The start address of the last possible leadout will only
		 * be zero if the disc is full or this drive does not support
		 * this method of determining capacity.
		 */
		if (cap == 0)
			cap = read_format_capacity(target->d_fd, &bsize);

		/*
		 * Since both methods of determining the capacity of the
		 * media count the correct number of blocks, just multiply
		 * the capacity by the block size.
		 */
		cap *= target->d_blksize;

		if (device_type == CD_RW) {
			(void) printf(gettext("Media Capacity : %.2f MB "),
			    ((double)cap/ONE_MB_BASE2));
		} else {
			/*
			 * For DVD's make sure we print out "Formatted Media
			 * Capacity". Don't do this for CD-RWs as only
			 * DVDs are formatted.
			 */
			(void) printf(gettext("Formatted Media Capacity : "
			    "%.2f GB "), ((double)cap/ONE_GB_BASE10));
		}

		cap /= target->d_blksize;
		(void) printf(gettext("(%u blocks)\n"), (uint_t)cap);
	}

	if (!check_device(target, CHECK_MEDIA_IS_NOT_BLANK)) {
		(void) printf(gettext("Media is blank\n"));
		exit(0);
	}

	/*  Find out the number of entries in the toc */
	toc = (uchar_t *)my_zalloc(12);
	if (!read_toc(target->d_fd, 0, 1, 4, toc)) {
		err_msg(msg);
	} else {
		toc_size = 256*toc[0] + toc[1] + 2;
		free(toc);

		/* allocate enough space for each track entry */
		toc = (uchar_t *)my_zalloc(toc_size);

		if (!read_toc(target->d_fd, 0, 1, toc_size, toc)) {
			err_msg(msg);
			exit(1);
		}
		(void) printf("\n");

		/* l10n_NOTE : Preserve column numbers of '|' character */
		(void) printf(gettext("Track No. |Type    |Start address\n"));
		(void) printf("----------+--------+-------------\n");


		/* look at each track and display it's type. */

		for (p = &toc[4]; p < (toc + toc_size); p += 8) {
			if (p[2] != 0xAA)
				(void) printf(" %-3d      |", p[2]);
			else
				(void) printf("Leadout   |");
			(void) printf("%s   |", (p[1] & 4) ? gettext("Data ") :
			    gettext("Audio"));
			(void) printf("%u\n", read_scsi32(&p[4]));
		}
	}
	(void) printf("\n");
	ret = read_toc(target->d_fd, 1, 0, 12, toc);
	if ((ret == 0) || (toc[1] != 0x0a))
		/* For ATAPI drives or old Toshiba drives */
		ret = read_toc_as_per_8020(target->d_fd, 1, 0, 12, toc);

	if (ret && (toc[1] == 0x0a)) {
		(void) printf(gettext("Last session start address: %u\n"),
		    read_scsi32(&toc[8]));
	}
	free(toc);
	ti = (struct track_info *)my_zalloc(sizeof (struct track_info));

	if (build_track_info(target, -1, ti) && (ti->ti_flags & TI_NWA_VALID)) {
		(void) printf(gettext("Next writable address: %u\n"),
		    ti->ti_nwa);
	}
	free(ti);
	exit(0);
}