xref: /illumos-gate/usr/src/cmd/cdrw/mmc.c (revision bbf21555)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5b36bd5c0Szk  * Common Development and Distribution License (the "License").
6b36bd5c0Szk  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22aefd6f19Szk  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <stdio.h>
297c478bd9Sstevel@tonic-gate #include <string.h>
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include "transport.h"
327c478bd9Sstevel@tonic-gate #include "mmc.h"
337c478bd9Sstevel@tonic-gate #include "util.h"
347c478bd9Sstevel@tonic-gate #include "main.h"
357c478bd9Sstevel@tonic-gate 
363a4671b6SToomas Soome int uscsi_error;
373a4671b6SToomas Soome 
387c478bd9Sstevel@tonic-gate int
test_unit_ready(int fd)397c478bd9Sstevel@tonic-gate test_unit_ready(int fd)
407c478bd9Sstevel@tonic-gate {
417c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
447c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_SILENT;
457c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
467c478bd9Sstevel@tonic-gate 	/* give length of cdb structure */
477c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 6;
487c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
497c478bd9Sstevel@tonic-gate 		return (0);
507c478bd9Sstevel@tonic-gate 	return (1);
517c478bd9Sstevel@tonic-gate }
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate int
inquiry(int fd,uchar_t * inq)547c478bd9Sstevel@tonic-gate inquiry(int fd, uchar_t *inq)
557c478bd9Sstevel@tonic-gate {
567c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
597c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
607c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
617c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = INQUIRY_CMD;
627c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[4] = INQUIRY_DATA_LENGTH;
637c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 6;
647c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)inq;
657c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = INQUIRY_DATA_LENGTH;
667c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
677c478bd9Sstevel@tonic-gate 		return (0);
687c478bd9Sstevel@tonic-gate 	return (1);
697c478bd9Sstevel@tonic-gate }
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate int
read_capacity(int fd,uchar_t * capbuf)727c478bd9Sstevel@tonic-gate read_capacity(int fd, uchar_t *capbuf)
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
777c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
787c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
797c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = READ_CAP_CMD;
807c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 10;
817c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)capbuf;
827c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = 8;
837c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
847c478bd9Sstevel@tonic-gate 		return (0);
857c478bd9Sstevel@tonic-gate 	return (1);
867c478bd9Sstevel@tonic-gate }
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate int
mode_sense(int fd,uchar_t pc,int dbd,int page_len,uchar_t * buffer)897c478bd9Sstevel@tonic-gate mode_sense(int fd, uchar_t pc, int dbd, int page_len, uchar_t *buffer)
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
947c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
957c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = page_len;
967c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)buffer;
977c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
987c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 0xa;
997c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = MODE_SENSE_10_CMD;
1007c478bd9Sstevel@tonic-gate 	if (dbd) {
1017c478bd9Sstevel@tonic-gate 		/* don't return any block descriptors */
1027c478bd9Sstevel@tonic-gate 		scmd->uscsi_cdb[1] = 0x8;
1037c478bd9Sstevel@tonic-gate 	}
1047c478bd9Sstevel@tonic-gate 	/* the page code we want */
1057c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[2] = pc;
1067c478bd9Sstevel@tonic-gate 	/* allocation length */
1077c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[7] = (page_len >> 8) & 0xff;
1087c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[8] = page_len & 0xff;
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
1117c478bd9Sstevel@tonic-gate 		return (0);
1127c478bd9Sstevel@tonic-gate 	return (1);
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate int
mode_select(int fd,int page_len,uchar_t * buffer)1167c478bd9Sstevel@tonic-gate mode_select(int fd, int page_len, uchar_t *buffer)
1177c478bd9Sstevel@tonic-gate {
1187c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
1217c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_WRITE|USCSI_SILENT;
1227c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = page_len;
1237c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)buffer;
1247c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
1257c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 0xa;
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	/* mode select (10) command */
1287c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = MODE_SELECT_10_CMD;
1297c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[1] = 0x10;
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	/* parameter list length */
1327c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[7] = (page_len >> 8) & 0xff;
1337c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[8] = page_len & 0xff;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
1367c478bd9Sstevel@tonic-gate 		return (0);
1377c478bd9Sstevel@tonic-gate 	return (1);
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate int
read_track_info(int fd,int trackno,uchar_t * ti)1417c478bd9Sstevel@tonic-gate read_track_info(int fd, int trackno, uchar_t *ti)
1427c478bd9Sstevel@tonic-gate {
1437c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
1467c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
1477c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
1487c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = READ_TRACK_CMD;
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	/* tell device we are giving it a track number */
1517c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[1] = 1;
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	/* track number to read */
1547c478bd9Sstevel@tonic-gate 	if (trackno == -1)
1557c478bd9Sstevel@tonic-gate 		if (device_type == CD_RW) {
1567c478bd9Sstevel@tonic-gate 			((uchar_t *)scmd->uscsi_cdb)[5] = 0xff;
1577c478bd9Sstevel@tonic-gate 		} else {
1587c478bd9Sstevel@tonic-gate 			/* only 1 track is allowed on DVD media */
1597c478bd9Sstevel@tonic-gate 			scmd->uscsi_cdb[1] = 0;
1607c478bd9Sstevel@tonic-gate 			((uchar_t *)scmd->uscsi_cdb)[5] = 0;
1617c478bd9Sstevel@tonic-gate 		}
1627c478bd9Sstevel@tonic-gate 	else
1637c478bd9Sstevel@tonic-gate 		scmd->uscsi_cdb[5] = (uchar_t)trackno;
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[8] = TRACK_INFO_SIZE;
1667c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 10;
1677c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)ti;
1687c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = TRACK_INFO_SIZE;
1697c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
1707c478bd9Sstevel@tonic-gate 		return (0);
1717c478bd9Sstevel@tonic-gate 	return (1);
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate int
read_toc(int fd,int format,int trackno,int buflen,uchar_t * buf)1757c478bd9Sstevel@tonic-gate read_toc(int fd, int format, int trackno, int buflen, uchar_t *buf)
1767c478bd9Sstevel@tonic-gate {
1777c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
1807c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
1817c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
1827c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = READ_TOC_CMD;
1837c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[2] = format & 0xf;
1847c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[6] = trackno;
1857c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[8] = buflen & 0xff;
1867c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[7] = (buflen >> 8) & 0xff;
1877c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 10;
1887c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)buf;
1897c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = buflen;
1907c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
1917c478bd9Sstevel@tonic-gate 		return (0);
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 	/* Fix for old SONY drives */
1947c478bd9Sstevel@tonic-gate 	if ((format == 0) && (buflen == 4) && (buf[0] == 0) && (buf[1] == 2)) {
1957c478bd9Sstevel@tonic-gate 		uint16_t toc_size;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 		toc_size = (((uint16_t)(buf[3] + 1)) * 8) + 2;
1987c478bd9Sstevel@tonic-gate 		load_scsi16(buf, toc_size);
1997c478bd9Sstevel@tonic-gate 	}
2007c478bd9Sstevel@tonic-gate 	return (1);
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate int
read_header(int fd,uint32_t lba,uchar_t * buf)2047c478bd9Sstevel@tonic-gate read_header(int fd, uint32_t lba, uchar_t *buf)
2057c478bd9Sstevel@tonic-gate {
2067c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
2097c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
2107c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
2117c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = READ_HDR_CMD;
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	/* Logical block address */
2147c478bd9Sstevel@tonic-gate 	load_scsi32(&scmd->uscsi_cdb[2], lba);
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	/* allocation length */
2177c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[8] = 8;
2187c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 10;
2197c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)buf;
2207c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = 8;
2217c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
2227c478bd9Sstevel@tonic-gate 		return (0);
2237c478bd9Sstevel@tonic-gate 	return (1);
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate int
read_disc_info(int fd,uchar_t * di)2277c478bd9Sstevel@tonic-gate read_disc_info(int fd, uchar_t *di)
2287c478bd9Sstevel@tonic-gate {
2297c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
2327c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
2337c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
2347c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = READ_INFO_CMD;
2357c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[8] = DISC_INFO_BLOCK_SIZE;
2367c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 10;
2377c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)di;
2387c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = DISC_INFO_BLOCK_SIZE;
2397c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
2407c478bd9Sstevel@tonic-gate 		return (0);
2417c478bd9Sstevel@tonic-gate 	return (1);
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate 
244dc36087fSec /* Get information about the Logical Unit's capabilities */
2457c478bd9Sstevel@tonic-gate int
get_configuration(int fd,uint16_t feature,int bufsize,uchar_t * buf)2467c478bd9Sstevel@tonic-gate get_configuration(int fd, uint16_t feature, int bufsize, uchar_t *buf)
2477c478bd9Sstevel@tonic-gate {
2487c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
2517c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
2527c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
253dc36087fSec 
254dc36087fSec 	/* Set OPERATION CODE in CDB */
2557c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = GET_CONFIG_CMD;
256dc36087fSec 
257dc36087fSec 	/*
258dc36087fSec 	 * Set RT field in CDB, currently need at most one
259dc36087fSec 	 * Feature Descriptor
260dc36087fSec 	 */
2617c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[1] = 0x2;
262dc36087fSec 
263dc36087fSec 	/* Set Starting Feature Number in CDB */
2647c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[2] = (feature >> 8) & 0xff;
2657c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[3] = feature & 0xff;
266dc36087fSec 
267dc36087fSec 	/* Set Allocation Length in CDB */
2687c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[7] = (bufsize >> 8) & 0xff;
2697c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[8] = bufsize & 0xff;
270dc36087fSec 
2717c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 10;
2727c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)buf;
2737c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = bufsize;
2747c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
2757c478bd9Sstevel@tonic-gate 		return (0);
2767c478bd9Sstevel@tonic-gate 	return (1);
2777c478bd9Sstevel@tonic-gate }
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate int
read10(int fd,uint32_t start_blk,uint16_t nblk,uchar_t * buf,uint32_t bufsize)2807c478bd9Sstevel@tonic-gate read10(int fd, uint32_t start_blk, uint16_t nblk, uchar_t *buf,
2813a4671b6SToomas Soome     uint32_t bufsize)
2827c478bd9Sstevel@tonic-gate {
2837c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
2867c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
2877c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
2887c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = READ_10_CMD;
2897c478bd9Sstevel@tonic-gate 	load_scsi32(&scmd->uscsi_cdb[2], start_blk);
2907c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[8] = nblk & 0xff;
2917c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[7] = (nblk >> 8) & 0xff;
2927c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 10;
2937c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)buf;
2947c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = bufsize;
2957c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
2967c478bd9Sstevel@tonic-gate 		return (0);
2977c478bd9Sstevel@tonic-gate 	return (1);
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate int
write10(int fd,uint32_t start_blk,uint16_t nblk,uchar_t * buf,uint32_t bufsize)3017c478bd9Sstevel@tonic-gate write10(int fd, uint32_t start_blk, uint16_t nblk, uchar_t *buf,
3023a4671b6SToomas Soome     uint32_t bufsize)
3037c478bd9Sstevel@tonic-gate {
3047c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
3077c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_WRITE|USCSI_SILENT;
3087c478bd9Sstevel@tonic-gate 	/*
3097c478bd9Sstevel@tonic-gate 	 * Some DVD drives take longer to write than
3107c478bd9Sstevel@tonic-gate 	 * the standard time, since they tend to generate
3117c478bd9Sstevel@tonic-gate 	 * the media TOC on the fly when the cache is full
3127c478bd9Sstevel@tonic-gate 	 */
3137c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT * 3;
3147c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = WRITE_10_CMD;
3157c478bd9Sstevel@tonic-gate 	load_scsi32(&scmd->uscsi_cdb[2], start_blk);
3167c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[8] = nblk & 0xff;
3177c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[7] = (nblk >> 8) & 0xff;
3187c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 10;
3197c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)buf;
3207c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = bufsize;
3217c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
3227c478bd9Sstevel@tonic-gate 		return (0);
3237c478bd9Sstevel@tonic-gate 	return (1);
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate int
close_track(int fd,int trackno,int close_session,int immediate)3277c478bd9Sstevel@tonic-gate close_track(int fd, int trackno, int close_session, int immediate)
3287c478bd9Sstevel@tonic-gate {
3297c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
3327c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_SILENT;
3337c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = CLOSE_TRACK_CMD;
3347c478bd9Sstevel@tonic-gate 	if (immediate) {
3357c478bd9Sstevel@tonic-gate 		scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
3367c478bd9Sstevel@tonic-gate 		scmd->uscsi_cdb[1] = 1;
3377c478bd9Sstevel@tonic-gate 	} else {
3387c478bd9Sstevel@tonic-gate 		scmd->uscsi_timeout = 240;
3397c478bd9Sstevel@tonic-gate 	}
3407c478bd9Sstevel@tonic-gate 	if ((close_session) || (device_type == DVD_PLUS) ||
3417c478bd9Sstevel@tonic-gate 	    (device_type == DVD_PLUS_W)) {
3427c478bd9Sstevel@tonic-gate 		/* close the session */
3437c478bd9Sstevel@tonic-gate 		scmd->uscsi_cdb[2] = 2;
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	} else {
3467c478bd9Sstevel@tonic-gate 		/* Close the track but leave session open */
3477c478bd9Sstevel@tonic-gate 		scmd->uscsi_cdb[2] = 1;
3487c478bd9Sstevel@tonic-gate 		scmd->uscsi_cdb[5] = trackno & 0xff;
3497c478bd9Sstevel@tonic-gate 	}
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	/*
3527c478bd9Sstevel@tonic-gate 	 * DVD+R media are already formatted, we are using
3537c478bd9Sstevel@tonic-gate 	 * a special case to notify that drive to close
3547c478bd9Sstevel@tonic-gate 	 * track/session and null-fill the remaining space.
3557c478bd9Sstevel@tonic-gate 	 */
3567c478bd9Sstevel@tonic-gate 	if (device_type == DVD_PLUS) {
3577c478bd9Sstevel@tonic-gate 		scmd->uscsi_cdb[5] = 1; /* only 1 track */
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 		if (close_session) {
3607c478bd9Sstevel@tonic-gate 			scmd->uscsi_cdb[2] = 6; /* session */
3617c478bd9Sstevel@tonic-gate 		} else {
3627c478bd9Sstevel@tonic-gate 			scmd->uscsi_cdb[2] = 1; /* track */
3637c478bd9Sstevel@tonic-gate 		}
3647c478bd9Sstevel@tonic-gate 	}
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 10;
3677c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
3687c478bd9Sstevel@tonic-gate 		return (0);
3697c478bd9Sstevel@tonic-gate 	return (1);
3707c478bd9Sstevel@tonic-gate }
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate int
blank_disc(int fd,int type,int immediate)3737c478bd9Sstevel@tonic-gate blank_disc(int fd, int type, int immediate)
3747c478bd9Sstevel@tonic-gate {
3757c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
3787c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_SILENT;
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	if (immediate) {
3817c478bd9Sstevel@tonic-gate 		scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
3827c478bd9Sstevel@tonic-gate 		scmd->uscsi_cdb[1] = 0x10;
3837c478bd9Sstevel@tonic-gate 	} else {
3847c478bd9Sstevel@tonic-gate 		scmd->uscsi_timeout = 0x12c0;
3857c478bd9Sstevel@tonic-gate 	}
3867c478bd9Sstevel@tonic-gate 	((uchar_t *)scmd->uscsi_cdb)[0] = BLANK_CMD;
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	/* tell it to blank the last session or all of the disk */
3897c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[1] |= type & 0x07;
3907c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 12;
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
3937c478bd9Sstevel@tonic-gate 		return (0);
3947c478bd9Sstevel@tonic-gate 	return (1);
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate int
read_cd(int fd,uint32_t start_blk,uint16_t nblk,uchar_t sector_type,uchar_t * buf,uint32_t bufsize)3987c478bd9Sstevel@tonic-gate read_cd(int fd, uint32_t start_blk, uint16_t nblk, uchar_t sector_type,
3993a4671b6SToomas Soome     uchar_t *buf, uint32_t bufsize)
4007c478bd9Sstevel@tonic-gate {
4017c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
4047c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
4057c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
4067c478bd9Sstevel@tonic-gate 	((uchar_t *)scmd->uscsi_cdb)[0] = READ_CD_CMD;
4077c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[1] = (sector_type & 0x7) << 2;
4087c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[5] = start_blk & 0xff;
4097c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[4] = (start_blk >> 8) & 0xff;
4107c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[3] = (start_blk >> 16) & 0xff;
4117c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[2] = (start_blk >> 24) & 0xff;
4127c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[8] = nblk & 0xff;
4137c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[7] = (nblk >> 8) & 0xff;
4147c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[9] = 0x10;
4157c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 12;
4167c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)buf;
4177c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = bufsize;
4187c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
4197c478bd9Sstevel@tonic-gate 		return (0);
4207c478bd9Sstevel@tonic-gate 	return (1);
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate int
load_unload(int fd,int load)4247c478bd9Sstevel@tonic-gate load_unload(int fd, int load)
4257c478bd9Sstevel@tonic-gate {
4267c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
4297c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_SILENT;
4307c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
4317c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = START_STOP_CMD;
4327c478bd9Sstevel@tonic-gate 	if (load == 0) {
4337c478bd9Sstevel@tonic-gate 		/* unload medium */
4347c478bd9Sstevel@tonic-gate 		scmd->uscsi_cdb[4] = 2;
4357c478bd9Sstevel@tonic-gate 	} else {
4367c478bd9Sstevel@tonic-gate 		/* load medium */
4377c478bd9Sstevel@tonic-gate 		scmd->uscsi_cdb[4] = 3;
4387c478bd9Sstevel@tonic-gate 	}
4397c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 6;
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
4427c478bd9Sstevel@tonic-gate 		return (0);
4437c478bd9Sstevel@tonic-gate 	return (1);
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate int
prevent_allow_mr(int fd,int op)4477c478bd9Sstevel@tonic-gate prevent_allow_mr(int fd, int op)
4487c478bd9Sstevel@tonic-gate {
4497c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
4527c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_SILENT;
4537c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
4547c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = PREVENT_ALLOW_CMD;
4557c478bd9Sstevel@tonic-gate 	if (!op) {	/* prevent */
4567c478bd9Sstevel@tonic-gate 		scmd->uscsi_cdb[4] = 1;
4577c478bd9Sstevel@tonic-gate 	}
4587c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 6;
4597c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
4607c478bd9Sstevel@tonic-gate 		return (0);
4617c478bd9Sstevel@tonic-gate 	return (1);
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate int
set_cd_speed(int fd,uint16_t read_speed,uint16_t write_speed)4657c478bd9Sstevel@tonic-gate set_cd_speed(int fd, uint16_t read_speed, uint16_t write_speed)
4667c478bd9Sstevel@tonic-gate {
4677c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
4707c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_SILENT;
4717c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
4727c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 0xc;
4737c478bd9Sstevel@tonic-gate 	((uchar_t *)scmd->uscsi_cdb)[0] = SET_CD_SPEED;
4747c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[2] = (read_speed >> 8) & 0xff;
4757c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[3] = read_speed & 0xff;
4767c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[4] = (write_speed >> 8) & 0xff;
4777c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[5] = write_speed & 0xff;
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
4807c478bd9Sstevel@tonic-gate 		return (0);
4817c478bd9Sstevel@tonic-gate 	return (1);
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate int
get_performance(int fd,int get_write_performance,uchar_t * perf)4857c478bd9Sstevel@tonic-gate get_performance(int fd, int get_write_performance, uchar_t *perf)
4867c478bd9Sstevel@tonic-gate {
4877c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
4907c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
4917c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = GET_PERF_DATA_LEN;
4927c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)perf;
4937c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
4947c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 0xc;
4957c478bd9Sstevel@tonic-gate 	((uchar_t *)scmd->uscsi_cdb)[0] = GET_PERFORMANCE_CMD;
4967c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[1] = 0x10;
4977c478bd9Sstevel@tonic-gate 	if (get_write_performance)
4987c478bd9Sstevel@tonic-gate 		scmd->uscsi_cdb[1] |= 4;
4997c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[9] = 2;
5007c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
5017c478bd9Sstevel@tonic-gate 		return (0);
5027c478bd9Sstevel@tonic-gate 	return (1);
5037c478bd9Sstevel@tonic-gate }
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate int
set_streaming(int fd,uchar_t * buf)5067c478bd9Sstevel@tonic-gate set_streaming(int fd, uchar_t *buf)
5077c478bd9Sstevel@tonic-gate {
5087c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
5117c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_WRITE|USCSI_SILENT;
5127c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = SET_STREAM_DATA_LEN;
5137c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)buf;
5147c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
5157c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 0xc;
5167c478bd9Sstevel@tonic-gate 	((uchar_t *)scmd->uscsi_cdb)[0] = STREAM_CMD;
5177c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[10] = SET_STREAM_DATA_LEN;
5187c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
5197c478bd9Sstevel@tonic-gate 		return (0);
5207c478bd9Sstevel@tonic-gate 	return (1);
5217c478bd9Sstevel@tonic-gate }
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate int
rezero_unit(int fd)5247c478bd9Sstevel@tonic-gate rezero_unit(int fd)
5257c478bd9Sstevel@tonic-gate {
5267c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
5297c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_SILENT;
5307c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
5317c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 0x6;
5327c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = REZERO_UNIT_CMD;
5337c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
5347c478bd9Sstevel@tonic-gate 		return (0);
5357c478bd9Sstevel@tonic-gate 	return (1);
5367c478bd9Sstevel@tonic-gate }
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate int
start_stop(int fd,int start)5397c478bd9Sstevel@tonic-gate start_stop(int fd, int start)
5407c478bd9Sstevel@tonic-gate {
5417c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
5447c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_SILENT;
5457c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
5467c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 0x6;
5477c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = START_STOP_CMD;
5487c478bd9Sstevel@tonic-gate 	if (start) {
5497c478bd9Sstevel@tonic-gate 		scmd->uscsi_cdb[4] = 1;
5507c478bd9Sstevel@tonic-gate 	}
5517c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
5527c478bd9Sstevel@tonic-gate 		return (0);
5537c478bd9Sstevel@tonic-gate 	return (1);
5547c478bd9Sstevel@tonic-gate }
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate int
flush_cache(int fd)5577c478bd9Sstevel@tonic-gate flush_cache(int fd)
5587c478bd9Sstevel@tonic-gate {
5597c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
5627c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_SILENT;
5637c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
5647c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 10;
5657c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = SYNC_CACHE_CMD;
5667c478bd9Sstevel@tonic-gate 	if (device_type != CD_RW) {
5677c478bd9Sstevel@tonic-gate 		scmd->uscsi_cdb[1] = 0x2; /* Immediate */
5687c478bd9Sstevel@tonic-gate 	}
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
5717c478bd9Sstevel@tonic-gate 		return (0);
5727c478bd9Sstevel@tonic-gate 	return (1);
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate /*
5767c478bd9Sstevel@tonic-gate  * used for DVD- to reserve the size we want to write.
5777c478bd9Sstevel@tonic-gate  * This is used by the drive to generate a TOC.
5787c478bd9Sstevel@tonic-gate  */
5797c478bd9Sstevel@tonic-gate int
set_reservation(int fd,ulong_t size)5807c478bd9Sstevel@tonic-gate set_reservation(int fd, ulong_t size)
5817c478bd9Sstevel@tonic-gate {
5827c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
5857c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
5867c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
5877c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = SET_RESERVATION_CMD;
5887c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 10;
5897c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[5] = (uchar_t)(size >> 24);
5907c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[6] = (uchar_t)(size >> 16);
5917c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[7] = (uchar_t)(size >> 8);
5927c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[8] = (uchar_t)size;
5937c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
5947c478bd9Sstevel@tonic-gate 		return (0);
5957c478bd9Sstevel@tonic-gate 	return (1);
5967c478bd9Sstevel@tonic-gate }
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate /*
5997c478bd9Sstevel@tonic-gate  * Used for DVD+RW media to prepare the disk to write.
6007c478bd9Sstevel@tonic-gate  * It will also be used for packet mode writing when
6017c478bd9Sstevel@tonic-gate  * it becomes supported.
6027c478bd9Sstevel@tonic-gate  */
6037c478bd9Sstevel@tonic-gate int
format_media(int fd)6047c478bd9Sstevel@tonic-gate format_media(int fd)
6057c478bd9Sstevel@tonic-gate {
6067c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
6077c478bd9Sstevel@tonic-gate 	uchar_t buf[20];
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 	(void) memset(buf, 0, 20);
6107c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
6117c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
6127c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 12;
6157c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = READ_FORMAT_CAP_CMD;
6167c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[8] = 0x14; /* buffer length */
6177c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = 20;
6187c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = (char *)buf;
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
6217c478bd9Sstevel@tonic-gate 		return (0);
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 	/* RE-use cap structure */
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_WRITE|USCSI_SILENT;
6267c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
6277c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 6;
6287c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = FORMAT_UNIT_CMD;
6297c478bd9Sstevel@tonic-gate 	/* full format */
6307c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[1] = 0x11;
6317c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = 12;
6327c478bd9Sstevel@tonic-gate 	buf[1] = 0x82; /* immediate and FOV */
6337c478bd9Sstevel@tonic-gate 	buf[3] = 8;	/* descriptor length */
6347c478bd9Sstevel@tonic-gate 	buf[8] = 0x98;	/* type = 26 DVD+RW format */
6357c478bd9Sstevel@tonic-gate 	buf[10] = 0;
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
6387c478bd9Sstevel@tonic-gate 		return (0);
6397c478bd9Sstevel@tonic-gate 	return (1);
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate /*
6447c478bd9Sstevel@tonic-gate  * Prefered method of reading the media size. This is
6457c478bd9Sstevel@tonic-gate  * the only supported method on several newer drives.
6467c478bd9Sstevel@tonic-gate  */
6477c478bd9Sstevel@tonic-gate uint32_t
read_format_capacity(int fd,uint_t * bsize)6487c478bd9Sstevel@tonic-gate read_format_capacity(int fd, uint_t *bsize)
6497c478bd9Sstevel@tonic-gate {
6507c478bd9Sstevel@tonic-gate 	struct uscsi_cmd *scmd;
6517c478bd9Sstevel@tonic-gate 	uint32_t filesize;
6527c478bd9Sstevel@tonic-gate 	char buf[20];
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 	scmd = get_uscsi_cmd();
6557c478bd9Sstevel@tonic-gate 	scmd->uscsi_flags = USCSI_READ|USCSI_SILENT;
6567c478bd9Sstevel@tonic-gate 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
6577c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdblen = 12;
6587c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[0] = READ_FORMAT_CAP_CMD;
6597c478bd9Sstevel@tonic-gate 	scmd->uscsi_cdb[8] = 0x14;
6607c478bd9Sstevel@tonic-gate 	scmd->uscsi_buflen = 20;
6617c478bd9Sstevel@tonic-gate 	scmd->uscsi_bufaddr = buf;
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	if ((uscsi_error = uscsi(fd, scmd)) < 0)
6647c478bd9Sstevel@tonic-gate 		return (0);
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 	filesize =  (uint32_t)(((uchar_t)buf[4] << 24) +
6677c478bd9Sstevel@tonic-gate 	    ((uchar_t)buf[5] << 16) + ((uchar_t)buf[6] << 8) + (uchar_t)buf[7]);
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 	*bsize = (uint16_t)(((uchar_t)buf[10] << 8) + (uchar_t)buf[11]);
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 	return (filesize);
6727c478bd9Sstevel@tonic-gate }
673c9be8e69Sec 
674b36bd5c0Szk /*
675*bbf21555SRichard Lowe  * Used to reset the device. Since, sd(4D) requires a
676b36bd5c0Szk  * command to be issued when resetting a device we will
677b36bd5c0Szk  * issue an innocuous command. The command chosen for this
678b36bd5c0Szk  * purpose is the TEST UNIT READY (TUR) command. We also do
679b36bd5c0Szk  * not care about the sucess of the TUR so we will not return
680b36bd5c0Szk  * a value.
681b36bd5c0Szk  */
682b36bd5c0Szk void
reset_dev(int fd)683b36bd5c0Szk reset_dev(int fd)
684b36bd5c0Szk {
685b36bd5c0Szk 	struct uscsi_cmd *scmd;
686b36bd5c0Szk 
687b36bd5c0Szk 	/*
688b36bd5c0Szk 	 * Since a TUR has SCSI operation code of 0, we
689b36bd5c0Szk 	 * can make use of the fact that get_uscsi_cmd()
690b36bd5c0Szk 	 * initializes a CDB to all zeros to generate
691b36bd5c0Szk 	 * the TUR command.
692b36bd5c0Szk 	 */
693b36bd5c0Szk 	scmd = get_uscsi_cmd();
694b36bd5c0Szk 
695*bbf21555SRichard Lowe 	/* Tell sd(4D) to do a silent reset of the device. */
696b36bd5c0Szk 	scmd->uscsi_flags = USCSI_SILENT | USCSI_RESET;
697b36bd5c0Szk 
698b36bd5c0Szk 	scmd->uscsi_timeout = DEFAULT_SCSI_TIMEOUT;
699b36bd5c0Szk 	scmd->uscsi_cdblen = 6;
700b36bd5c0Szk 
701b36bd5c0Szk 	/* Issue the TUR command. */
702b36bd5c0Szk 	uscsi_error = uscsi(fd, scmd);
703b36bd5c0Szk }
704b36bd5c0Szk 
705b36bd5c0Szk 
706c9be8e69Sec /*
707c9be8e69Sec  * Function:    ftr_supported
708c9be8e69Sec  *
709c9be8e69Sec  * Description: Check to see if a device supports a Feature
710c9be8e69Sec  *
711c9be8e69Sec  * Arguments:   fd      - file descriptor
712c9be8e69Sec  *              feature - the MMC Feature for which we'd like to know
713c9be8e69Sec  *                        if there's support
714c9be8e69Sec  *
715c9be8e69Sec  * Return Code: 1       - Feature is supported
716c9be8e69Sec  *		0	- Feature is not supported
717c9be8e69Sec  *
718c9be8e69Sec  */
719c9be8e69Sec int
ftr_supported(int fd,uint16_t feature)720c9be8e69Sec ftr_supported(int fd, uint16_t feature)
721c9be8e69Sec {
722c9be8e69Sec 	size_t response_len;
723c9be8e69Sec 	uchar_t *bufp;
724c9be8e69Sec 	int ret;
725c9be8e69Sec 
726c9be8e69Sec 	response_len = MMC_FTR_HDR_LEN + MMC_FTR_DSCRPTR_BASE_LEN;
727c9be8e69Sec 	bufp = (uchar_t *)my_zalloc(response_len);
728c9be8e69Sec 
729c9be8e69Sec 	/*
730c9be8e69Sec 	 * If a Feature is supported, a device will return a Feature Descriptor
731c9be8e69Sec 	 * for that Feature, and its Current Bit will be set.
732c9be8e69Sec 	 */
733c9be8e69Sec 	if (get_configuration(fd, feature, response_len, bufp) == 1) {
734c9be8e69Sec 		/*
735c9be8e69Sec 		 * To check that a Feature Descriptor was returned, we
736c9be8e69Sec 		 * check to see if the Data Length field of the Feature
737c9be8e69Sec 		 * Header holds a value greater than four.  To check if
738c9be8e69Sec 		 * the Current Bit is set, we check bit 1 of byte 10.
739c9be8e69Sec 		 */
740c9be8e69Sec 		if (read_scsi32(bufp) > 4 && bufp[10] & 1)
741c9be8e69Sec 			ret = 1;
742c9be8e69Sec 		else
743c9be8e69Sec 			ret = 0;
744c9be8e69Sec 	} else {
745c9be8e69Sec 		/* get_configuration failed */
746c9be8e69Sec 		ret = 0;
747c9be8e69Sec 	}
748c9be8e69Sec 	free(bufp);
749c9be8e69Sec 	return (ret);
750c9be8e69Sec }
751c9be8e69Sec 
752c9be8e69Sec /*
753c9be8e69Sec  * Function:    print_profile_name
754c9be8e69Sec  *
755c9be8e69Sec  * Description: Prints a list of the Profiles the device supports
756c9be8e69Sec  *
757c9be8e69Sec  * Parameters:  num     - hexadecimal representation of Profile
758c9be8e69Sec  *              current - 1 if the Profile is Current, otherwise 0
759aefd6f19Szk  *		abbr	- 1 if printing abbreviated name, otherwise 0
760c9be8e69Sec  */
761aefd6f19Szk void
print_profile_name(uint16_t num,uchar_t current,uchar_t abbr)762aefd6f19Szk print_profile_name(uint16_t num, uchar_t current, uchar_t abbr)
763c9be8e69Sec {
764aefd6f19Szk 	if (abbr != 1)
765aefd6f19Szk 		(void) printf(" 0x%04x: ", num);
766aefd6f19Szk 
767c9be8e69Sec 	switch (num) {
768c9be8e69Sec 	case 0x0000:
769c9be8e69Sec 		(void) printf("No Current Profile");
770c9be8e69Sec 		break;
771c9be8e69Sec 	case 0x0001:
772c9be8e69Sec 		(void) printf("Non-Removable Disk");
773c9be8e69Sec 		break;
774c9be8e69Sec 	case 0x0002:
775c9be8e69Sec 		(void) printf("Removable Disk");
776c9be8e69Sec 		break;
777c9be8e69Sec 	case 0x0003:
778c9be8e69Sec 		(void) printf("Magneto-Optical Erasable");
779c9be8e69Sec 		break;
780c9be8e69Sec 	case 0x0004:
781c9be8e69Sec 		(void) printf("Optical Write Once");
782c9be8e69Sec 		break;
783c9be8e69Sec 	case 0x0005:
784c9be8e69Sec 		(void) printf("AS-MO");
785c9be8e69Sec 		break;
786c9be8e69Sec 	case 0x0008:
787c9be8e69Sec 		(void) printf("CD-ROM");
788c9be8e69Sec 		break;
789c9be8e69Sec 	case 0x0009:
790c9be8e69Sec 		(void) printf("CD-R");
791c9be8e69Sec 		break;
792c9be8e69Sec 	case 0x000A:
793c9be8e69Sec 		(void) printf("CD-RW");
794c9be8e69Sec 		break;
795c9be8e69Sec 	case 0x0010:
796c9be8e69Sec 		(void) printf("DVD-ROM");
797c9be8e69Sec 		break;
798c9be8e69Sec 	case 0x0011:
799aefd6f19Szk 		(void) printf("DVD-R");
800aefd6f19Szk 		if (abbr != 1)
801aefd6f19Szk 			(void) printf(" Sequential Recording");
802c9be8e69Sec 		break;
803c9be8e69Sec 	case 0x0012:
804c9be8e69Sec 		(void) printf("DVD-RAM");
805c9be8e69Sec 		break;
806c9be8e69Sec 	case 0x0013:
807aefd6f19Szk 		(void) printf("DVD-RW");
808aefd6f19Szk 		if (abbr != 1)
809aefd6f19Szk 			(void) printf(" Restricted Overwrite");
810c9be8e69Sec 		break;
811c9be8e69Sec 	case 0x0014:
812aefd6f19Szk 		(void) printf("DVD-RW");
813aefd6f19Szk 		if (abbr != 1)
814aefd6f19Szk 			(void) printf(" Sequential Recording");
815aefd6f19Szk 		break;
816aefd6f19Szk 	case 0x0015:
817aefd6f19Szk 		(void) printf("DVD-R");
818aefd6f19Szk 		if (abbr != 1)
819aefd6f19Szk 			(void) printf(" Dual Layer Sequential Recording");
820aefd6f19Szk 		else
821aefd6f19Szk 			(void) printf(" DL");
822aefd6f19Szk 		break;
823aefd6f19Szk 	case 0x0016:
824aefd6f19Szk 		(void) printf("DVD-R");
825aefd6f19Szk 		if (abbr != 1)
826aefd6f19Szk 			(void) printf(" Dual Layer Jump Recording");
827aefd6f19Szk 		else
828aefd6f19Szk 			(void) printf(" DL");
829aefd6f19Szk 		break;
830aefd6f19Szk 	case 0x0017:
831aefd6f19Szk 		(void) printf("DVD-RW");
832aefd6f19Szk 		if (abbr != 1)
833aefd6f19Szk 			(void) printf(" Dual Layer");
834aefd6f19Szk 		else
835aefd6f19Szk 			(void) printf(" DL");
836c9be8e69Sec 		break;
837c9be8e69Sec 	case 0x001A:
838c9be8e69Sec 		(void) printf("DVD+RW");
839c9be8e69Sec 		break;
840c9be8e69Sec 	case 0x001B:
841c9be8e69Sec 		(void) printf("DVD+R");
842c9be8e69Sec 		break;
843c9be8e69Sec 	case 0x0020:
844c9be8e69Sec 		(void) printf("DDCD-ROM");
845c9be8e69Sec 		break;
846c9be8e69Sec 	case 0x0021:
847c9be8e69Sec 		(void) printf("DDCD-R");
848c9be8e69Sec 		break;
849c9be8e69Sec 	case 0x0022:
850c9be8e69Sec 		(void) printf("DDCD-RW");
851c9be8e69Sec 		break;
852aefd6f19Szk 	case 0x002A:
853aefd6f19Szk 		(void) printf("DVD+RW");
854aefd6f19Szk 		if (abbr != 1)
855aefd6f19Szk 			(void) printf(" Dual Layer");
856aefd6f19Szk 		else
857aefd6f19Szk 			(void) printf(" DL");
858aefd6f19Szk 		break;
859c9be8e69Sec 	case 0x002B:
860aefd6f19Szk 		(void) printf("DVD+R");
861aefd6f19Szk 		if (abbr != 1)
862aefd6f19Szk 			(void) printf(" Dual Layer");
863aefd6f19Szk 		else
864aefd6f19Szk 			(void) printf(" DL");
865c9be8e69Sec 		break;
866c9be8e69Sec 	case 0x0040:
867c9be8e69Sec 		(void) printf("BD-ROM");
868c9be8e69Sec 		break;
869c9be8e69Sec 	case 0x0041:
870c9be8e69Sec 		(void) printf("BD-R Sequential Recording (SRM) Profile");
871c9be8e69Sec 		break;
872c9be8e69Sec 	case 0x0042:
873c9be8e69Sec 		(void) printf("BD-R Random Recording (RRM) Profile");
874c9be8e69Sec 		break;
875c9be8e69Sec 	case 0x0043:
876c9be8e69Sec 		(void) printf("BD-RE");
877c9be8e69Sec 		break;
878c9be8e69Sec 	case 0xFFFF:
879c9be8e69Sec 		(void) printf("Nonstandard Profile");
880c9be8e69Sec 		break;
881c9be8e69Sec 	default:
882c9be8e69Sec 		break;
883c9be8e69Sec 	}
884c9be8e69Sec 	if (current == 1)
885c9be8e69Sec 		(void) printf(" (Current Profile)");
886c9be8e69Sec 	(void) printf("\n");
887c9be8e69Sec }
888c9be8e69Sec 
889c9be8e69Sec /*
890c9be8e69Sec  * Function: print_profile_list
891c9be8e69Sec  *
892c9be8e69Sec  * Description: Print a list of Profiles supported by the Logical Unit.
893c9be8e69Sec  *
8943a4671b6SToomas Soome  * Parameters:	fd	- file descriptor for device whose list of
895c9be8e69Sec  *			  profiles we wish to print
896c9be8e69Sec  */
897c9be8e69Sec void
print_profile_list(int fd)898c9be8e69Sec print_profile_list(int fd)
899c9be8e69Sec {
900c9be8e69Sec 	size_t i;
901c9be8e69Sec 	size_t buflen;
902c9be8e69Sec 	uint16_t current;
903c9be8e69Sec 	uint16_t other;
904c9be8e69Sec 	uchar_t *bufp = (uchar_t *)my_zalloc(MMC_FTR_HDR_LEN);
905c9be8e69Sec 
906c9be8e69Sec 	/*
907c9be8e69Sec 	 * First get_configuration call is used to determine amount of memory
908c9be8e69Sec 	 * needed to hold all the Profiles.  The first four bytes of bufp
909c9be8e69Sec 	 * concatenated tell us the number of bytes of memory we need but do
910c9be8e69Sec 	 * not take themselves into account.  Therefore, add four, and
911c9be8e69Sec 	 * allocate that number of bytes.
912c9be8e69Sec 	 */
913c9be8e69Sec 	if (get_configuration(fd, MMC_FTR_PRFL_LIST, MMC_FTR_HDR_LEN,
914c9be8e69Sec 	    bufp)) {
915c9be8e69Sec 		buflen = read_scsi32(bufp) + 4;
916c9be8e69Sec 		free(bufp);
917c9be8e69Sec 		bufp = (uchar_t *)my_zalloc(buflen);
918c9be8e69Sec 
919c9be8e69Sec 		/*
920c9be8e69Sec 		 * Now get all the Profiles
921c9be8e69Sec 		 */
922c9be8e69Sec 		if (get_configuration(fd, MMC_FTR_PRFL_LIST, buflen, bufp)) {
923c9be8e69Sec 			(void) printf("\nProfile List\n");
924c9be8e69Sec 			(void) printf("---------------------------------\n");
925c9be8e69Sec 
926c9be8e69Sec 			/*
927c9be8e69Sec 			 * Find out the Logical Unit's Current Profile
928c9be8e69Sec 			 */
929c9be8e69Sec 			current = read_scsi16(&bufp[6]);
930c9be8e69Sec 
931c9be8e69Sec 			/*
932c9be8e69Sec 			 * Print out the Profile List and indicate which
933c9be8e69Sec 			 * Profile is Current
934c9be8e69Sec 			 */
935c9be8e69Sec 			for (i = MMC_FTR_HDR_LEN + MMC_FTR_DSCRPTR_BASE_LEN;
936c9be8e69Sec 			    i < buflen; i += MMC_PRFL_DSCRPTR_LEN) {
937c9be8e69Sec 				other = read_scsi16(&bufp[i]);
938c9be8e69Sec 				if (other == current)
939aefd6f19Szk 					print_profile_name(other, 1, 0);
940c9be8e69Sec 				else
941aefd6f19Szk 					print_profile_name(other, 0, 0);
942c9be8e69Sec 			}
943c9be8e69Sec 			(void) printf("\n");
944c9be8e69Sec 		}
945c9be8e69Sec 	}
946c9be8e69Sec 	free(bufp);
947c9be8e69Sec }
948