Beispiel #1
0
/*
 * will get the mode page only i.e. will strip off the header.
 */
int
get_mode_page(int fd, int page_no, int pc, int buf_len, uchar_t *buffer)
{
	int ret;
	uchar_t byte2, *buf;
	uint_t header_len, page_len, copy_cnt;

	byte2 = (uchar_t)(((pc << 6) & 0xC0) | (page_no & 0x3f));
	buf = (uchar_t *)my_zalloc(256);

	/* Ask 254 bytes only to make our IDE driver happy */
	ret = mode_sense(fd, byte2, 1, 254, buf);
	if (ret == 0) {
		free(buf);
		return (0);
	}

	header_len = 8 + read_scsi16(&buf[6]);
	page_len = buf[header_len + 1] + 2;

	copy_cnt = (page_len > buf_len) ? buf_len : page_len;
	(void) memcpy(buffer, &buf[header_len], copy_cnt);
	free(buf);

	return (1);
}
Beispiel #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);
}
Beispiel #3
0
/*
 * Get current Read or Write Speed from Mode Page 0x2a.
 *
 * Use the size of the Page to determine which Multimedia Command
 * set (MMC) is present.  Based on the MMC version, get the
 * specified Read/Write Speed.
 *
 * Note that some MMC versions do not necessarily support a
 * (current) Read or Write Speed.  As a result, this function
 * _can_ return a value of zero.
 *
 * The newer standards (reserve and) mark the field(s) as Obsolete,
 * yet many vendors populate the Obsolete fields with valid values
 * (assumedly for backward compatibility).  This is important, as
 * a command like GET PERFORMANCE cannot return _the_ speed; it can
 * only return a Logical-Block-Address-dependent (LBA) speed.  Such
 * values can vary widely between the innermost and outermost Track.
 * Mode Page 0x2a is the best solution identifying "the current
 * (nominal) speed".
 */
static uint16_t
cd_speed_get(cd_device *dev, int cmd)
{
	uchar_t		*mp2a;
	uint16_t	rate = 0;
	int		offset;
	uint_t		buflen = 254;

	/*
	 * Allocate a buffer acceptably larger than any nominal
	 * Page for Page Code 0x2A.
	 */
	mp2a = (uchar_t *)my_zalloc(buflen);
	if (get_mode_page(dev->d_fd, 0x2A, 0, buflen, mp2a) == 0)
		goto end;

	/* Determine MMC version based on 'Page Length' field */
	switch (mp2a[1]) {
	case 0x14:  /* MMC-1 */
		if (debug)
			(void) printf("Mode Page 2A: MMC-1\n");

		offset = (cmd == GET_READ_SPEED) ? 14 : 20;
		rate = read_scsi16(&mp2a[offset]);
		break;


	case 0x18: /* MMC-2 */
		if (debug)
			(void) printf("Mode Page 2A: MMC-2;"
			    " Read and Write Speeds are "
			    "obsolete\n");

		/* see if "Obsolete" values are valid: */
		offset = (cmd == GET_READ_SPEED) ? 14 : 20;
		rate = read_scsi16(&mp2a[offset]);
		break;

	default: /* MMC-3 or newer */
		if (debug)
			(void) printf("Mode Page 2A: MMC-3 or"
			    " newer; Read Speed is obsolete.\n");

		if (cmd == GET_READ_SPEED) {
			/* this is Obsolete, but try it */
			offset = 14;
			rate = read_scsi16(&mp2a[offset]);
		} else {
			/* Write Speed is not obsolete */
			offset = 28;
			rate = read_scsi16(&mp2a[offset]);

			if (rate == 0) {
				/*
				 * then try an Obsolete field
				 * (but this shouldn't happen!)
				 */
				offset = 20;
				rate = read_scsi16(&mp2a[offset]);
			}
		}
		break;
	}
end:
	free(mp2a);

	if (debug)
		(void) printf("cd_speed_get: %s Speed is "
		    "%uX\n", (cmd == GET_READ_SPEED) ?
		    "Read" : "Write", cdrw_bandwidth_to_x(rate));
	return (rate);
}
Beispiel #4
0
/*
 * The size of the last track in one of the first N - 1 sessions of an
 * N-session (N > 1) disc is reported incorrectly by some drives and calculated
 * incorrectly for others, because a pre-gap/lead-out/lead-in section that ends
 * a session is erroneously considered part of that track. This function checks
 * for this corner case, and adjusts the track size if necessary.
 */
static int
check_track_size(cd_device *dev, int trk_num, struct track_info *tip)
{
	size_t raw_toc_len;
	uchar_t *raw_toc;
	rtoc_hdr_t hdr;
	uint32_t sess_leadout_lba;
	int sess_last_trk_num;
	int trk_sess_num;
	uint32_t trk_size;

	/* Request Raw TOC Header for session count. */
	if (read_toc(dev->d_fd, FORMAT_RAW_TOC, 1,
	    sizeof (rtoc_hdr_t), (uchar_t *)&hdr) != 1)
		return (0);

	/* Is this a multi-session medium? */
	if (hdr.rh_last_sess_num > hdr.rh_first_sess_num) {
		/* Yes; request entire Raw TOC. */
		raw_toc_len = read_scsi16(&hdr.rh_data_len1) + RTOC_DATA_LEN_SZ;
		raw_toc = (uchar_t *)my_zalloc(raw_toc_len);

		if (read_toc(dev->d_fd, FORMAT_RAW_TOC, 1, raw_toc_len, raw_toc)
		    != 1)
			goto fail;

		if (rtoc_get_trk_sess_num(raw_toc, raw_toc_len, trk_num,
		    &trk_sess_num) != 1)
			goto fail;

		tip->ti_session_no = trk_sess_num;
		tip->ti_flags |= TI_SESSION_NO_VALID;

		/* Is the track in one of the first N - 1 sessions? */
		if (trk_sess_num < hdr.rh_last_sess_num) {
			if (rtoc_get_sess_last_trk_num(raw_toc, raw_toc_len,
			    trk_sess_num, &sess_last_trk_num) != 1)
				goto fail;

			/* Is the track the last track in the session? */
			if (trk_num == sess_last_trk_num) {
				if (rtoc_get_sess_leadout_lba(raw_toc,
				    raw_toc_len, trk_sess_num,
				    &sess_leadout_lba) != 1)
					goto fail;

				trk_size = sess_leadout_lba -
				    tip->ti_start_address;

				/* Fix track size if it was too big. */
				if (tip->ti_track_size > trk_size)
					tip->ti_track_size = trk_size;
			}
		}
		free(raw_toc);
	}
	return (1);

fail:
	free(raw_toc);
	return (0);
}