Ejemplo n.º 1
0
/*
 * Find out media capacity.
 */
uint32_t
get_last_possible_lba(cd_device *dev)
{
	uchar_t *di;
	uint32_t cap;

	di = (uchar_t *)my_zalloc(DISC_INFO_BLOCK_SIZE);
	if (!read_disc_info(dev->d_fd, di)) {
		free(di);
		return (0);
	}

	/*
	 * If we have a DVD+R this field is an LBA. If the media is
	 * a CD-R/W the field is MSF formatted. Otherwise this field
	 * is not valid and will be zero.
	 */
	if (device_type == DVD_PLUS) {
		if (read_scsi32(&di[20]) != 0xffffffff) {
			cap = read_scsi32(&di[20]);
		} else {
			cap = 0;
		}
	} else {
		if ((di[21] != 0) && (di[21] != 0xff)) {
			cap = MSF2LBA(di[21], di[22], di[23]);
		} else {
			cap = 0;
		}
	}

	free(di);
	return (cap);
}
Ejemplo n.º 2
0
/*
 * Find out media capacity.
 */
int
get_last_possible_lba(cd_device *dev)
{
	uchar_t *di;
	int cap;

	di = (uchar_t *)my_zalloc(DISC_INFO_BLOCK_SIZE);
	if (!read_disc_info(dev->d_fd, di)) {
		free(di);
		return (0);
	}
	if ((di[21] != 0) && (di[21] != 0xff)) {
		cap = ((di[21] * 60) + di[22]) * 75;
	} else {
		cap = 0;
	}

	free(di);
	return (cap);
}
Ejemplo n.º 3
0
/*
 * Close session. This will write TOC.
 */
int
finalize(cd_device *dev)
{
	uchar_t *di;
	int count, ret, err;
	int immediate;
	int finalize_max;

	/*
	 * For ATAPI devices we will use the immediate mode and will
	 * poll the command for completion so that this command may
	 * not hog the channel. But for SCSI, we will use the treditional
	 * way of issuing the command with a large enough timeout. This
	 * is done because immediate mode was designed for ATAPI and some
	 * SCSI RW drives might not be even tested with it.
	 */
	if ((dev->d_inq[2] & 7) != 0) {
		/* SCSI device */
		immediate = 0;
	} else {
		/* non-SCSI (e.g ATAPI) device */
		immediate = 1;
	}

	/* We need to close track before close session */
	if (device_type == DVD_PLUS) {
		if (!close_track(dev->d_fd, 0, 0, immediate))
			return (0);
	}

	if (!close_track(dev->d_fd, 0, 1, immediate)) {
		/*
		 * For DAO mode which we use for DVD-RW, the latest MMC
		 * specification does not mention close_track. Some
		 * newer drives will return an ILLEGAL INSTRUCTION
		 * which we will ignore. We have also found a Panasonic
		 * drive which will return a MEDIA ERROR. It is safe
		 * to ignore both errors as this is not needed for
		 * these drives.
		 * This is kept for older drives which had needed
		 * us to issue close_track to flush the cache fully.
		 * once we are certain these drives have cleared the
		 * market, this can be removed.
		 */
		if (device_type == DVD_MINUS) {
			return (0);
		}
	} else {
		if (!immediate)
			return (1);
	}
	if (immediate) {
		(void) sleep(10);

		di = (uchar_t *)my_zalloc(DISC_INFO_BLOCK_SIZE);
		err = 0;

		if (device_type == CD_RW) {
			/* Finalization should not take more than 6 minutes */
			finalize_max = FINALIZE_TIMEOUT;
		} else {
			/* some DVD-RW drives take longer than 6 minutes */
			finalize_max = FINALIZE_TIMEOUT*2;
		}

		for (count = 0; count < finalize_max; count++) {
			ret = read_disc_info(dev->d_fd, di);
			if (ret != 0)
				break;
			if (uscsi_status != 2)
				err = 1;
			if (SENSE_KEY(rqbuf) == 2) {
				/* not ready but not becoming ready */
				if (ASC(rqbuf) != 4)
					err = 1;
			} else if (SENSE_KEY(rqbuf) == 5) {
				/* illegal mode for this track */
				if (ASC(rqbuf) != 0x64)
					err = 1;
			} else {
				err = 1;
			}
			if (err == 1) {
				if (debug) {
					(void) printf("Finalization failed\n");
					(void) printf("%x %x %x %x\n",
					    uscsi_status, SENSE_KEY(rqbuf),
					    ASC(rqbuf), ASCQ(rqbuf));
				}
				free(di);
				return (0);
			}
			if (uscsi_status == 2) {
				int i;
				/* illegal field in command packet */
				if (ASC(rqbuf) == 0x24) {
					/* print it out! */
					(void) printf("\n");
					for (i = 0; i < 18; i++)
						(void) printf("%x ",
						    (unsigned)(rqbuf[i]));
					(void) printf("\n");
				}
			}
			(void) sleep(5);
		}
		free(di);
	}
	return (ret);
}