sr_vendor.c (9010B)
1// SPDX-License-Identifier: GPL-2.0 2/* -*-linux-c-*- 3 4 * vendor-specific code for SCSI CD-ROM's goes here. 5 * 6 * This is needed becauce most of the new features (multisession and 7 * the like) are too new to be included into the SCSI-II standard (to 8 * be exact: there is'nt anything in my draft copy). 9 * 10 * Aug 1997: Ha! Got a SCSI-3 cdrom spec across my fingers. SCSI-3 does 11 * multisession using the READ TOC command (like SONY). 12 * 13 * Rearranged stuff here: SCSI-3 is included allways, support 14 * for NEC/TOSHIBA/HP commands is optional. 15 * 16 * Gerd Knorr <kraxel@cs.tu-berlin.de> 17 * 18 * -------------------------------------------------------------------------- 19 * 20 * support for XA/multisession-CD's 21 * 22 * - NEC: Detection and support of multisession CD's. 23 * 24 * - TOSHIBA: Detection and support of multisession CD's. 25 * Some XA-Sector tweaking, required for older drives. 26 * 27 * - SONY: Detection and support of multisession CD's. 28 * added by Thomas Quinot <thomas@cuivre.freenix.fr> 29 * 30 * - PIONEER, HITACHI, PLEXTOR, MATSHITA, TEAC, PHILIPS: known to 31 * work with SONY (SCSI3 now) code. 32 * 33 * - HP: Much like SONY, but a little different... (Thomas) 34 * HP-Writers only ??? Maybe other CD-Writers work with this too ? 35 * HP 6020 writers now supported. 36 */ 37 38#include <linux/cdrom.h> 39#include <linux/errno.h> 40#include <linux/string.h> 41#include <linux/bcd.h> 42#include <linux/blkdev.h> 43#include <linux/slab.h> 44 45#include <scsi/scsi.h> 46#include <scsi/scsi_cmnd.h> 47#include <scsi/scsi_device.h> 48#include <scsi/scsi_host.h> 49#include <scsi/scsi_ioctl.h> 50 51#include "sr.h" 52 53#if 0 54#define DEBUG 55#endif 56 57/* here are some constants to sort the vendors into groups */ 58 59#define VENDOR_SCSI3 1 /* default: scsi-3 mmc */ 60 61#define VENDOR_NEC 2 62#define VENDOR_TOSHIBA 3 63#define VENDOR_WRITER 4 /* pre-scsi3 writers */ 64#define VENDOR_CYGNAL_85ED 5 /* CD-on-a-chip */ 65 66#define VENDOR_TIMEOUT 30*HZ 67 68void sr_vendor_init(Scsi_CD *cd) 69{ 70 const char *vendor = cd->device->vendor; 71 const char *model = cd->device->model; 72 73 /* default */ 74 cd->vendor = VENDOR_SCSI3; 75 if (cd->readcd_known) 76 /* this is true for scsi3/mmc drives - no more checks */ 77 return; 78 79 if (cd->device->type == TYPE_WORM) { 80 cd->vendor = VENDOR_WRITER; 81 82 } else if (!strncmp(vendor, "NEC", 3)) { 83 cd->vendor = VENDOR_NEC; 84 if (!strncmp(model, "CD-ROM DRIVE:25", 15) || 85 !strncmp(model, "CD-ROM DRIVE:36", 15) || 86 !strncmp(model, "CD-ROM DRIVE:83", 15) || 87 !strncmp(model, "CD-ROM DRIVE:84 ", 16) 88#if 0 89 /* my NEC 3x returns the read-raw data if a read-raw 90 is followed by a read for the same sector - aeb */ 91 || !strncmp(model, "CD-ROM DRIVE:500", 16) 92#endif 93 ) 94 /* these can't handle multisession, may hang */ 95 cd->cdi.mask |= CDC_MULTI_SESSION; 96 97 } else if (!strncmp(vendor, "TOSHIBA", 7)) { 98 cd->vendor = VENDOR_TOSHIBA; 99 100 } else if (!strncmp(vendor, "Beurer", 6) && 101 !strncmp(model, "Gluco Memory", 12)) { 102 /* The Beurer GL50 evo uses a Cygnal-manufactured CD-on-a-chip 103 that only accepts a subset of SCSI commands. Most of the 104 not-implemented commands are fine to fail, but a few, 105 particularly around the MMC or Audio commands, will put the 106 device into an unrecoverable state, so they need to be 107 avoided at all costs. 108 */ 109 cd->vendor = VENDOR_CYGNAL_85ED; 110 cd->cdi.mask |= ( 111 CDC_MULTI_SESSION | 112 CDC_CLOSE_TRAY | CDC_OPEN_TRAY | 113 CDC_LOCK | 114 CDC_GENERIC_PACKET | 115 CDC_PLAY_AUDIO 116 ); 117 } 118} 119 120 121/* small handy function for switching block length using MODE SELECT, 122 * used by sr_read_sector() */ 123 124int sr_set_blocklength(Scsi_CD *cd, int blocklength) 125{ 126 unsigned char *buffer; /* the buffer for the ioctl */ 127 struct packet_command cgc; 128 struct ccs_modesel_head *modesel; 129 int rc, density = 0; 130 131 if (cd->vendor == VENDOR_TOSHIBA) 132 density = (blocklength > 2048) ? 0x81 : 0x83; 133 134 buffer = kmalloc(512, GFP_KERNEL); 135 if (!buffer) 136 return -ENOMEM; 137 138#ifdef DEBUG 139 sr_printk(KERN_INFO, cd, "MODE SELECT 0x%x/%d\n", density, blocklength); 140#endif 141 memset(&cgc, 0, sizeof(struct packet_command)); 142 cgc.cmd[0] = MODE_SELECT; 143 cgc.cmd[1] = (1 << 4); 144 cgc.cmd[4] = 12; 145 modesel = (struct ccs_modesel_head *) buffer; 146 memset(modesel, 0, sizeof(*modesel)); 147 modesel->block_desc_length = 0x08; 148 modesel->density = density; 149 modesel->block_length_med = (blocklength >> 8) & 0xff; 150 modesel->block_length_lo = blocklength & 0xff; 151 cgc.buffer = buffer; 152 cgc.buflen = sizeof(*modesel); 153 cgc.data_direction = DMA_TO_DEVICE; 154 cgc.timeout = VENDOR_TIMEOUT; 155 if (0 == (rc = sr_do_ioctl(cd, &cgc))) { 156 cd->device->sector_size = blocklength; 157 } 158#ifdef DEBUG 159 else 160 sr_printk(KERN_INFO, cd, 161 "switching blocklength to %d bytes failed\n", 162 blocklength); 163#endif 164 kfree(buffer); 165 return rc; 166} 167 168/* This function gets called after a media change. Checks if the CD is 169 multisession, asks for offset etc. */ 170 171int sr_cd_check(struct cdrom_device_info *cdi) 172{ 173 Scsi_CD *cd = cdi->handle; 174 unsigned long sector; 175 unsigned char *buffer; /* the buffer for the ioctl */ 176 struct packet_command cgc; 177 int rc, no_multi; 178 179 if (cd->cdi.mask & CDC_MULTI_SESSION) 180 return 0; 181 182 buffer = kmalloc(512, GFP_KERNEL); 183 if (!buffer) 184 return -ENOMEM; 185 186 sector = 0; /* the multisession sector offset goes here */ 187 no_multi = 0; /* flag: the drive can't handle multisession */ 188 rc = 0; 189 190 memset(&cgc, 0, sizeof(struct packet_command)); 191 192 switch (cd->vendor) { 193 194 case VENDOR_SCSI3: 195 cgc.cmd[0] = READ_TOC; 196 cgc.cmd[8] = 12; 197 cgc.cmd[9] = 0x40; 198 cgc.buffer = buffer; 199 cgc.buflen = 12; 200 cgc.quiet = 1; 201 cgc.data_direction = DMA_FROM_DEVICE; 202 cgc.timeout = VENDOR_TIMEOUT; 203 rc = sr_do_ioctl(cd, &cgc); 204 if (rc != 0) 205 break; 206 if ((buffer[0] << 8) + buffer[1] < 0x0a) { 207 sr_printk(KERN_INFO, cd, "Hmm, seems the drive " 208 "doesn't support multisession CD's\n"); 209 no_multi = 1; 210 break; 211 } 212 sector = buffer[11] + (buffer[10] << 8) + 213 (buffer[9] << 16) + (buffer[8] << 24); 214 if (buffer[6] <= 1) { 215 /* ignore sector offsets from first track */ 216 sector = 0; 217 } 218 break; 219 220 case VENDOR_NEC:{ 221 unsigned long min, sec, frame; 222 cgc.cmd[0] = 0xde; 223 cgc.cmd[1] = 0x03; 224 cgc.cmd[2] = 0xb0; 225 cgc.buffer = buffer; 226 cgc.buflen = 0x16; 227 cgc.quiet = 1; 228 cgc.data_direction = DMA_FROM_DEVICE; 229 cgc.timeout = VENDOR_TIMEOUT; 230 rc = sr_do_ioctl(cd, &cgc); 231 if (rc != 0) 232 break; 233 if (buffer[14] != 0 && buffer[14] != 0xb0) { 234 sr_printk(KERN_INFO, cd, "Hmm, seems the cdrom " 235 "doesn't support multisession CD's\n"); 236 237 no_multi = 1; 238 break; 239 } 240 min = bcd2bin(buffer[15]); 241 sec = bcd2bin(buffer[16]); 242 frame = bcd2bin(buffer[17]); 243 sector = min * CD_SECS * CD_FRAMES + sec * CD_FRAMES + frame; 244 break; 245 } 246 247 case VENDOR_TOSHIBA:{ 248 unsigned long min, sec, frame; 249 250 /* we request some disc information (is it a XA-CD ?, 251 * where starts the last session ?) */ 252 cgc.cmd[0] = 0xc7; 253 cgc.cmd[1] = 0x03; 254 cgc.buffer = buffer; 255 cgc.buflen = 4; 256 cgc.quiet = 1; 257 cgc.data_direction = DMA_FROM_DEVICE; 258 cgc.timeout = VENDOR_TIMEOUT; 259 rc = sr_do_ioctl(cd, &cgc); 260 if (rc == -EINVAL) { 261 sr_printk(KERN_INFO, cd, "Hmm, seems the drive " 262 "doesn't support multisession CD's\n"); 263 no_multi = 1; 264 break; 265 } 266 if (rc != 0) 267 break; 268 min = bcd2bin(buffer[1]); 269 sec = bcd2bin(buffer[2]); 270 frame = bcd2bin(buffer[3]); 271 sector = min * CD_SECS * CD_FRAMES + sec * CD_FRAMES + frame; 272 if (sector) 273 sector -= CD_MSF_OFFSET; 274 sr_set_blocklength(cd, 2048); 275 break; 276 } 277 278 case VENDOR_WRITER: 279 cgc.cmd[0] = READ_TOC; 280 cgc.cmd[8] = 0x04; 281 cgc.cmd[9] = 0x40; 282 cgc.buffer = buffer; 283 cgc.buflen = 0x04; 284 cgc.quiet = 1; 285 cgc.data_direction = DMA_FROM_DEVICE; 286 cgc.timeout = VENDOR_TIMEOUT; 287 rc = sr_do_ioctl(cd, &cgc); 288 if (rc != 0) { 289 break; 290 } 291 if ((rc = buffer[2]) == 0) { 292 sr_printk(KERN_WARNING, cd, 293 "No finished session\n"); 294 break; 295 } 296 cgc.cmd[0] = READ_TOC; /* Read TOC */ 297 cgc.cmd[6] = rc & 0x7f; /* number of last session */ 298 cgc.cmd[8] = 0x0c; 299 cgc.cmd[9] = 0x40; 300 cgc.buffer = buffer; 301 cgc.buflen = 12; 302 cgc.quiet = 1; 303 cgc.data_direction = DMA_FROM_DEVICE; 304 cgc.timeout = VENDOR_TIMEOUT; 305 rc = sr_do_ioctl(cd, &cgc); 306 if (rc != 0) { 307 break; 308 } 309 sector = buffer[11] + (buffer[10] << 8) + 310 (buffer[9] << 16) + (buffer[8] << 24); 311 break; 312 313 default: 314 /* should not happen */ 315 sr_printk(KERN_WARNING, cd, 316 "unknown vendor code (%i), not initialized ?\n", 317 cd->vendor); 318 sector = 0; 319 no_multi = 1; 320 break; 321 } 322 cd->ms_offset = sector; 323 cd->xa_flag = 0; 324 if (CDS_AUDIO != sr_disk_status(cdi) && 1 == sr_is_xa(cd)) 325 cd->xa_flag = 1; 326 327 if (2048 != cd->device->sector_size) { 328 sr_set_blocklength(cd, 2048); 329 } 330 if (no_multi) 331 cdi->mask |= CDC_MULTI_SESSION; 332 333#ifdef DEBUG 334 if (sector) 335 sr_printk(KERN_DEBUG, cd, "multisession offset=%lu\n", 336 sector); 337#endif 338 kfree(buffer); 339 return rc; 340}