1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <stdio.h> 28 #include <string.h> 29 #include <stdlib.h> 30 #include <sys/types.h> 31 #include <libintl.h> 32 33 #include "transport.h" 34 #include "toshiba.h" 35 #include "device.h" 36 #include "misc_scsi.h" 37 #include "util.h" 38 #include "main.h" 39 #include "msgs.h" 40 #include "mmc.h" 41 42 static int speed_tbl[4] = { 1, 2, 12, 4 }; 43 static uchar_t rev_speed_tbl[16] = { 0, 0, 1, 0, 3, 0, 0, 0, 0, 44 0, 0, 0, 2, 0, 0, 0 }; 45 46 /* 47 * These are commands for using older Sun Toshiba drives. These 48 * commands are needed for reading CD TOC and audio extraction 49 * and changing speeds (used for audio extraction). 50 */ 51 52 int 53 read_toc_as_per_8020(int fd, int format, int trackno, int buflen, uchar_t *buf) 54 { 55 struct uscsi_cmd *scmd; 56 57 scmd = get_uscsi_cmd(); 58 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 59 scmd->uscsi_timeout = 60; 60 scmd->uscsi_cdb[0] = READ_TOC_CMD; 61 scmd->uscsi_cdb[6] = trackno; 62 scmd->uscsi_cdb[8] = buflen & 0xff; 63 scmd->uscsi_cdb[7] = (buflen >> 8) & 0xff; 64 scmd->uscsi_cdb[9] = (format << 6) & 0xc0; 65 scmd->uscsi_cdblen = 10; 66 scmd->uscsi_bufaddr = (char *)buf; 67 scmd->uscsi_buflen = buflen; 68 if (uscsi(fd, scmd) < 0) 69 return (0); 70 return (1); 71 } 72 73 int 74 toshiba_read_audio(cd_device *target, uint_t start_blk, uint_t nblk, 75 uchar_t *buf) 76 { 77 struct uscsi_cmd *scmd; 78 int ret, retry; 79 80 scmd = get_uscsi_cmd(); 81 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 82 scmd->uscsi_timeout = 60; 83 ((uchar_t *)scmd->uscsi_cdb)[0] = READ_AUDIO_CMD; 84 scmd->uscsi_cdb[5] = start_blk & 0xff; 85 scmd->uscsi_cdb[4] = (start_blk >> 8) & 0xff; 86 scmd->uscsi_cdb[3] = (start_blk >> 16) & 0xff; 87 scmd->uscsi_cdb[2] = (start_blk >> 24) & 0xff; 88 scmd->uscsi_cdb[9] = nblk & 0xff; 89 scmd->uscsi_cdb[8] = (nblk >> 8) & 0xff; 90 scmd->uscsi_cdb[7] = (nblk >> 16) & 0xff; 91 scmd->uscsi_cdb[6] = (nblk >> 24) & 0xff; 92 scmd->uscsi_cdblen = 12; 93 scmd->uscsi_bufaddr = (char *)buf; 94 scmd->uscsi_buflen = nblk*2352; 95 96 for (retry = 0; retry < 3; retry++) { 97 ret = uscsi(target->d_fd, scmd); 98 if (ret >= 0) 99 break; 100 } 101 102 if (ret < 0) 103 return (0); 104 return (1); 105 } 106 107 int 108 toshiba_speed_ctrl(cd_device *dev, int cmd, int speed) 109 { 110 uchar_t *mpage; 111 struct uscsi_cmd *scmd; 112 int ret; 113 114 if ((cmd == GET_WRITE_SPEED) || (cmd == SET_WRITE_SPEED)) { 115 if (debug) { 116 (void) printf("toshiba_speed_ctrl: WRONG CMD %d\n", 117 cmd); 118 } 119 return (0); 120 } 121 122 if (cmd == SET_READ_SPEED) { 123 if (dev->d_cap & DEV_CAP_SETTING_SPEED_NOT_ALLOWED) { 124 if (verbose) 125 err_msg(gettext( 126 "Cannot set speed on this device.\n")); 127 return (0); 128 } 129 if (speed == 32) { 130 if (strncmp("SUN32XCD", 131 (const char *)&dev->d_inq[24], 8) == 0) 132 return (1); 133 } 134 if ((speed != 1) && (speed != 2) && (speed != 4) && 135 (speed != 12)) { 136 if (verbose) 137 err_msg(gettext( 138 "%dx speed is not supported by the device.\n")); 139 return (0); 140 } 141 } 142 143 ret = 0; 144 mpage = (uchar_t *)my_zalloc(16); 145 scmd = get_uscsi_cmd(); 146 scmd->uscsi_flags = USCSI_READ|USCSI_SILENT; 147 scmd->uscsi_timeout = 60; 148 scmd->uscsi_cdblen = 6; 149 scmd->uscsi_bufaddr = (char *)mpage; 150 scmd->uscsi_buflen = 16; 151 /* 6 byte mode sense for older drives */ 152 scmd->uscsi_cdb[0] = MODE_SENSE_6_CMD; 153 scmd->uscsi_cdb[2] = 0x31; 154 scmd->uscsi_cdb[4] = 16; 155 if (uscsi(dev->d_fd, scmd) < 0) 156 goto end_speed_ctrl; 157 if (cmd == GET_READ_SPEED) { 158 ret = speed_tbl[mpage[14] & 0x3]; 159 goto end_speed_ctrl; 160 } 161 if (cmd == SET_READ_SPEED) { 162 (void) memset(mpage, 0, 9); 163 mpage[3] = 8; 164 mpage[12] = 0x31; 165 mpage[13] = 2; 166 mpage[14] = rev_speed_tbl[speed]; 167 scmd = get_uscsi_cmd(); 168 scmd->uscsi_flags = USCSI_WRITE|USCSI_SILENT; 169 scmd->uscsi_timeout = 60; 170 scmd->uscsi_cdblen = 6; 171 scmd->uscsi_bufaddr = (char *)mpage; 172 scmd->uscsi_buflen = 16; 173 /* 6 byte mode sense command for older drives */ 174 scmd->uscsi_cdb[0] = MODE_SELECT_6_CMD; 175 scmd->uscsi_cdb[1] = 0x10; 176 scmd->uscsi_cdb[4] = 16; 177 if (uscsi(dev->d_fd, scmd) < 0) 178 goto end_speed_ctrl; 179 ret = 1; 180 } 181 end_speed_ctrl: 182 free(mpage); 183 return (ret); 184 } 185