| 1 | // SPDX-License-Identifier: GPL-2.0 | 
|---|
| 2 | #include <linux/kernel.h> | 
|---|
| 3 | #include <linux/mm.h> | 
|---|
| 4 | #include <linux/fs.h> | 
|---|
| 5 | #include <linux/errno.h> | 
|---|
| 6 | #include <linux/string.h> | 
|---|
| 7 | #include <linux/blkdev.h> | 
|---|
| 8 | #include <linux/module.h> | 
|---|
| 9 | #include <linux/blkpg.h> | 
|---|
| 10 | #include <linux/cdrom.h> | 
|---|
| 11 | #include <linux/delay.h> | 
|---|
| 12 | #include <linux/slab.h> | 
|---|
| 13 | #include <asm/io.h> | 
|---|
| 14 | #include <linux/uaccess.h> | 
|---|
| 15 |  | 
|---|
| 16 | #include <scsi/scsi.h> | 
|---|
| 17 | #include <scsi/scsi_dbg.h> | 
|---|
| 18 | #include <scsi/scsi_device.h> | 
|---|
| 19 | #include <scsi/scsi_eh.h> | 
|---|
| 20 | #include <scsi/scsi_host.h> | 
|---|
| 21 | #include <scsi/scsi_ioctl.h> | 
|---|
| 22 | #include <scsi/scsi_cmnd.h> | 
|---|
| 23 |  | 
|---|
| 24 | #include "sr.h" | 
|---|
| 25 |  | 
|---|
| 26 | #if 0 | 
|---|
| 27 | #define DEBUG | 
|---|
| 28 | #endif | 
|---|
| 29 |  | 
|---|
| 30 | /* The sr_is_xa() seems to trigger firmware bugs with some drives :-( | 
|---|
| 31 | * It is off by default and can be turned on with this module parameter */ | 
|---|
| 32 | static int xa_test = 0; | 
|---|
| 33 |  | 
|---|
| 34 | module_param(xa_test, int, S_IRUGO | S_IWUSR); | 
|---|
| 35 |  | 
|---|
| 36 | static int sr_read_tochdr(struct cdrom_device_info *cdi, | 
|---|
| 37 | struct cdrom_tochdr *tochdr) | 
|---|
| 38 | { | 
|---|
| 39 | struct scsi_cd *cd = cdi->handle; | 
|---|
| 40 | struct packet_command cgc; | 
|---|
| 41 | int result; | 
|---|
| 42 | unsigned char *buffer; | 
|---|
| 43 |  | 
|---|
| 44 | buffer = kzalloc(32, GFP_KERNEL); | 
|---|
| 45 | if (!buffer) | 
|---|
| 46 | return -ENOMEM; | 
|---|
| 47 |  | 
|---|
| 48 | memset(s: &cgc, c: 0, n: sizeof(struct packet_command)); | 
|---|
| 49 | cgc.timeout = IOCTL_TIMEOUT; | 
|---|
| 50 | cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; | 
|---|
| 51 | cgc.cmd[8] = 12;		/* LSB of length */ | 
|---|
| 52 | cgc.buffer = buffer; | 
|---|
| 53 | cgc.buflen = 12; | 
|---|
| 54 | cgc.quiet = 1; | 
|---|
| 55 | cgc.data_direction = DMA_FROM_DEVICE; | 
|---|
| 56 |  | 
|---|
| 57 | result = sr_do_ioctl(cd, &cgc); | 
|---|
| 58 | if (result) | 
|---|
| 59 | goto err; | 
|---|
| 60 |  | 
|---|
| 61 | tochdr->cdth_trk0 = buffer[2]; | 
|---|
| 62 | tochdr->cdth_trk1 = buffer[3]; | 
|---|
| 63 |  | 
|---|
| 64 | err: | 
|---|
| 65 | kfree(objp: buffer); | 
|---|
| 66 | return result; | 
|---|
| 67 | } | 
|---|
| 68 |  | 
|---|
| 69 | static int sr_read_tocentry(struct cdrom_device_info *cdi, | 
|---|
| 70 | struct cdrom_tocentry *tocentry) | 
|---|
| 71 | { | 
|---|
| 72 | struct scsi_cd *cd = cdi->handle; | 
|---|
| 73 | struct packet_command cgc; | 
|---|
| 74 | int result; | 
|---|
| 75 | unsigned char *buffer; | 
|---|
| 76 |  | 
|---|
| 77 | buffer = kzalloc(32, GFP_KERNEL); | 
|---|
| 78 | if (!buffer) | 
|---|
| 79 | return -ENOMEM; | 
|---|
| 80 |  | 
|---|
| 81 | memset(s: &cgc, c: 0, n: sizeof(struct packet_command)); | 
|---|
| 82 | cgc.timeout = IOCTL_TIMEOUT; | 
|---|
| 83 | cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP; | 
|---|
| 84 | cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0; | 
|---|
| 85 | cgc.cmd[6] = tocentry->cdte_track; | 
|---|
| 86 | cgc.cmd[8] = 12;		/* LSB of length */ | 
|---|
| 87 | cgc.buffer = buffer; | 
|---|
| 88 | cgc.buflen = 12; | 
|---|
| 89 | cgc.data_direction = DMA_FROM_DEVICE; | 
|---|
| 90 |  | 
|---|
| 91 | result = sr_do_ioctl(cd, &cgc); | 
|---|
| 92 | if (result) | 
|---|
| 93 | goto err; | 
|---|
| 94 |  | 
|---|
| 95 | tocentry->cdte_ctrl = buffer[5] & 0xf; | 
|---|
| 96 | tocentry->cdte_adr = buffer[5] >> 4; | 
|---|
| 97 | tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0; | 
|---|
| 98 | if (tocentry->cdte_format == CDROM_MSF) { | 
|---|
| 99 | tocentry->cdte_addr.msf.minute = buffer[9]; | 
|---|
| 100 | tocentry->cdte_addr.msf.second = buffer[10]; | 
|---|
| 101 | tocentry->cdte_addr.msf.frame = buffer[11]; | 
|---|
| 102 | } else | 
|---|
| 103 | tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8) | 
|---|
| 104 | + buffer[10]) << 8) + buffer[11]; | 
|---|
| 105 |  | 
|---|
| 106 | err: | 
|---|
| 107 | kfree(objp: buffer); | 
|---|
| 108 | return result; | 
|---|
| 109 | } | 
|---|
| 110 |  | 
|---|
| 111 | #define IOCTL_RETRIES 3 | 
|---|
| 112 |  | 
|---|
| 113 | /* ATAPI drives don't have a SCMD_PLAYAUDIO_TI command.  When these drives | 
|---|
| 114 | are emulating a SCSI device via the idescsi module, they need to have | 
|---|
| 115 | CDROMPLAYTRKIND commands translated into CDROMPLAYMSF commands for them */ | 
|---|
| 116 |  | 
|---|
| 117 | static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti) | 
|---|
| 118 | { | 
|---|
| 119 | struct cdrom_tocentry trk0_te, trk1_te; | 
|---|
| 120 | struct cdrom_tochdr tochdr; | 
|---|
| 121 | struct packet_command cgc; | 
|---|
| 122 | int ntracks, ret; | 
|---|
| 123 |  | 
|---|
| 124 | ret = sr_read_tochdr(cdi, tochdr: &tochdr); | 
|---|
| 125 | if (ret) | 
|---|
| 126 | return ret; | 
|---|
| 127 |  | 
|---|
| 128 | ntracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1; | 
|---|
| 129 |  | 
|---|
| 130 | if (ti->cdti_trk1 == ntracks) | 
|---|
| 131 | ti->cdti_trk1 = CDROM_LEADOUT; | 
|---|
| 132 | else if (ti->cdti_trk1 != CDROM_LEADOUT) | 
|---|
| 133 | ti->cdti_trk1 ++; | 
|---|
| 134 |  | 
|---|
| 135 | trk0_te.cdte_track = ti->cdti_trk0; | 
|---|
| 136 | trk0_te.cdte_format = CDROM_MSF; | 
|---|
| 137 | trk1_te.cdte_track = ti->cdti_trk1; | 
|---|
| 138 | trk1_te.cdte_format = CDROM_MSF; | 
|---|
| 139 |  | 
|---|
| 140 | ret = sr_read_tocentry(cdi, tocentry: &trk0_te); | 
|---|
| 141 | if (ret) | 
|---|
| 142 | return ret; | 
|---|
| 143 | ret = sr_read_tocentry(cdi, tocentry: &trk1_te); | 
|---|
| 144 | if (ret) | 
|---|
| 145 | return ret; | 
|---|
| 146 |  | 
|---|
| 147 | memset(s: &cgc, c: 0, n: sizeof(struct packet_command)); | 
|---|
| 148 | cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF; | 
|---|
| 149 | cgc.cmd[3] = trk0_te.cdte_addr.msf.minute; | 
|---|
| 150 | cgc.cmd[4] = trk0_te.cdte_addr.msf.second; | 
|---|
| 151 | cgc.cmd[5] = trk0_te.cdte_addr.msf.frame; | 
|---|
| 152 | cgc.cmd[6] = trk1_te.cdte_addr.msf.minute; | 
|---|
| 153 | cgc.cmd[7] = trk1_te.cdte_addr.msf.second; | 
|---|
| 154 | cgc.cmd[8] = trk1_te.cdte_addr.msf.frame; | 
|---|
| 155 | cgc.data_direction = DMA_NONE; | 
|---|
| 156 | cgc.timeout = IOCTL_TIMEOUT; | 
|---|
| 157 | return sr_do_ioctl(cdi->handle, &cgc); | 
|---|
| 158 | } | 
|---|
| 159 |  | 
|---|
| 160 | static int sr_play_trkind(struct cdrom_device_info *cdi, | 
|---|
| 161 | struct cdrom_ti *ti) | 
|---|
| 162 |  | 
|---|
| 163 | { | 
|---|
| 164 | struct scsi_cd *cd = cdi->handle; | 
|---|
| 165 | struct packet_command cgc; | 
|---|
| 166 | int result; | 
|---|
| 167 |  | 
|---|
| 168 | memset(s: &cgc, c: 0, n: sizeof(struct packet_command)); | 
|---|
| 169 | cgc.timeout = IOCTL_TIMEOUT; | 
|---|
| 170 | cgc.cmd[0] = GPCMD_PLAYAUDIO_TI; | 
|---|
| 171 | cgc.cmd[4] = ti->cdti_trk0; | 
|---|
| 172 | cgc.cmd[5] = ti->cdti_ind0; | 
|---|
| 173 | cgc.cmd[7] = ti->cdti_trk1; | 
|---|
| 174 | cgc.cmd[8] = ti->cdti_ind1; | 
|---|
| 175 | cgc.data_direction = DMA_NONE; | 
|---|
| 176 |  | 
|---|
| 177 | result = sr_do_ioctl(cd, &cgc); | 
|---|
| 178 | if (result == -EDRIVE_CANT_DO_THIS) | 
|---|
| 179 | result = sr_fake_playtrkind(cdi, ti); | 
|---|
| 180 |  | 
|---|
| 181 | return result; | 
|---|
| 182 | } | 
|---|
| 183 |  | 
|---|
| 184 | /* We do our own retries because we want to know what the specific | 
|---|
| 185 | error code is.  Normally the UNIT_ATTENTION code will automatically | 
|---|
| 186 | clear after one error */ | 
|---|
| 187 |  | 
|---|
| 188 | int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) | 
|---|
| 189 | { | 
|---|
| 190 | struct scsi_device *SDev; | 
|---|
| 191 | struct scsi_sense_hdr local_sshdr, *sshdr; | 
|---|
| 192 | int result, err = 0, retries = 0; | 
|---|
| 193 | const struct scsi_exec_args exec_args = { | 
|---|
| 194 | .sshdr = cgc->sshdr ? : &local_sshdr, | 
|---|
| 195 | }; | 
|---|
| 196 |  | 
|---|
| 197 | SDev = cd->device; | 
|---|
| 198 |  | 
|---|
| 199 | sshdr = exec_args.sshdr; | 
|---|
| 200 |  | 
|---|
| 201 | retry: | 
|---|
| 202 | if (!scsi_block_when_processing_errors(SDev)) { | 
|---|
| 203 | err = -ENODEV; | 
|---|
| 204 | goto out; | 
|---|
| 205 | } | 
|---|
| 206 |  | 
|---|
| 207 | result = scsi_execute_cmd(sdev: SDev, cmd: cgc->cmd, | 
|---|
| 208 | opf: cgc->data_direction == DMA_TO_DEVICE ? | 
|---|
| 209 | REQ_OP_DRV_OUT : REQ_OP_DRV_IN, buffer: cgc->buffer, | 
|---|
| 210 | bufflen: cgc->buflen, timeout: cgc->timeout, IOCTL_RETRIES, | 
|---|
| 211 | args: &exec_args); | 
|---|
| 212 | /* Minimal error checking.  Ignore cases we know about, and report the rest. */ | 
|---|
| 213 | if (result < 0) { | 
|---|
| 214 | err = result; | 
|---|
| 215 | goto out; | 
|---|
| 216 | } | 
|---|
| 217 | if (scsi_status_is_check_condition(status: result)) { | 
|---|
| 218 | switch (sshdr->sense_key) { | 
|---|
| 219 | case UNIT_ATTENTION: | 
|---|
| 220 | SDev->changed = 1; | 
|---|
| 221 | if (!cgc->quiet) | 
|---|
| 222 | sr_printk(KERN_INFO, cd, | 
|---|
| 223 | "disc change detected.\n"); | 
|---|
| 224 | if (retries++ < 10) | 
|---|
| 225 | goto retry; | 
|---|
| 226 | err = -ENOMEDIUM; | 
|---|
| 227 | break; | 
|---|
| 228 | case NOT_READY:	/* This happens if there is no disc in drive */ | 
|---|
| 229 | if (sshdr->asc == 0x04 && | 
|---|
| 230 | sshdr->ascq == 0x01) { | 
|---|
| 231 | /* sense: Logical unit is in process of becoming ready */ | 
|---|
| 232 | if (!cgc->quiet) | 
|---|
| 233 | sr_printk(KERN_INFO, cd, | 
|---|
| 234 | "CDROM not ready yet.\n"); | 
|---|
| 235 | if (retries++ < 10) { | 
|---|
| 236 | /* sleep 2 sec and try again */ | 
|---|
| 237 | ssleep(seconds: 2); | 
|---|
| 238 | goto retry; | 
|---|
| 239 | } else { | 
|---|
| 240 | /* 20 secs are enough? */ | 
|---|
| 241 | err = -ENOMEDIUM; | 
|---|
| 242 | break; | 
|---|
| 243 | } | 
|---|
| 244 | } | 
|---|
| 245 | if (!cgc->quiet) | 
|---|
| 246 | sr_printk(KERN_INFO, cd, | 
|---|
| 247 | "CDROM not ready.  Make sure there " | 
|---|
| 248 | "is a disc in the drive.\n"); | 
|---|
| 249 | err = -ENOMEDIUM; | 
|---|
| 250 | break; | 
|---|
| 251 | case ILLEGAL_REQUEST: | 
|---|
| 252 | err = -EIO; | 
|---|
| 253 | if (sshdr->asc == 0x20 && | 
|---|
| 254 | sshdr->ascq == 0x00) | 
|---|
| 255 | /* sense: Invalid command operation code */ | 
|---|
| 256 | err = -EDRIVE_CANT_DO_THIS; | 
|---|
| 257 | break; | 
|---|
| 258 | default: | 
|---|
| 259 | err = -EIO; | 
|---|
| 260 | } | 
|---|
| 261 | } | 
|---|
| 262 |  | 
|---|
| 263 | /* Wake up a process waiting for device */ | 
|---|
| 264 | out: | 
|---|
| 265 | cgc->stat = err; | 
|---|
| 266 | return err; | 
|---|
| 267 | } | 
|---|
| 268 |  | 
|---|
| 269 | /* ---------------------------------------------------------------------- */ | 
|---|
| 270 | /* interface to cdrom.c                                                   */ | 
|---|
| 271 |  | 
|---|
| 272 | int sr_tray_move(struct cdrom_device_info *cdi, int pos) | 
|---|
| 273 | { | 
|---|
| 274 | Scsi_CD *cd = cdi->handle; | 
|---|
| 275 | struct packet_command cgc; | 
|---|
| 276 |  | 
|---|
| 277 | memset(s: &cgc, c: 0, n: sizeof(struct packet_command)); | 
|---|
| 278 | cgc.cmd[0] = GPCMD_START_STOP_UNIT; | 
|---|
| 279 | cgc.cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */ ; | 
|---|
| 280 | cgc.data_direction = DMA_NONE; | 
|---|
| 281 | cgc.timeout = IOCTL_TIMEOUT; | 
|---|
| 282 | return sr_do_ioctl(cd, cgc: &cgc); | 
|---|
| 283 | } | 
|---|
| 284 |  | 
|---|
| 285 | int sr_lock_door(struct cdrom_device_info *cdi, int lock) | 
|---|
| 286 | { | 
|---|
| 287 | Scsi_CD *cd = cdi->handle; | 
|---|
| 288 |  | 
|---|
| 289 | return scsi_set_medium_removal(cd->device, lock ? | 
|---|
| 290 | SCSI_REMOVAL_PREVENT : SCSI_REMOVAL_ALLOW); | 
|---|
| 291 | } | 
|---|
| 292 |  | 
|---|
| 293 | int sr_drive_status(struct cdrom_device_info *cdi, int slot) | 
|---|
| 294 | { | 
|---|
| 295 | struct scsi_cd *cd = cdi->handle; | 
|---|
| 296 | struct scsi_sense_hdr sshdr; | 
|---|
| 297 | struct media_event_desc med; | 
|---|
| 298 |  | 
|---|
| 299 | if (CDSL_CURRENT != slot) { | 
|---|
| 300 | /* we have no changer support */ | 
|---|
| 301 | return -EINVAL; | 
|---|
| 302 | } | 
|---|
| 303 | if (!scsi_test_unit_ready(sdev: cd->device, SR_TIMEOUT, MAX_RETRIES, sshdr: &sshdr)) | 
|---|
| 304 | return CDS_DISC_OK; | 
|---|
| 305 |  | 
|---|
| 306 | /* SK/ASC/ASCQ of 2/4/1 means "unit is becoming ready" */ | 
|---|
| 307 | if (scsi_sense_valid(sshdr: &sshdr) && sshdr.sense_key == NOT_READY | 
|---|
| 308 | && sshdr.asc == 0x04 && sshdr.ascq == 0x01) | 
|---|
| 309 | return CDS_DRIVE_NOT_READY; | 
|---|
| 310 |  | 
|---|
| 311 | if (!cdrom_get_media_event(cdi, med: &med)) { | 
|---|
| 312 | if (med.media_present) | 
|---|
| 313 | return CDS_DISC_OK; | 
|---|
| 314 | else if (med.door_open) | 
|---|
| 315 | return CDS_TRAY_OPEN; | 
|---|
| 316 | else | 
|---|
| 317 | return CDS_NO_DISC; | 
|---|
| 318 | } | 
|---|
| 319 |  | 
|---|
| 320 | /* | 
|---|
| 321 | * SK/ASC/ASCQ of 2/4/2 means "initialization required" | 
|---|
| 322 | * Using CD_TRAY_OPEN results in an START_STOP_UNIT to close | 
|---|
| 323 | * the tray, which resolves the initialization requirement. | 
|---|
| 324 | */ | 
|---|
| 325 | if (scsi_sense_valid(sshdr: &sshdr) && sshdr.sense_key == NOT_READY | 
|---|
| 326 | && sshdr.asc == 0x04 && sshdr.ascq == 0x02) | 
|---|
| 327 | return CDS_TRAY_OPEN; | 
|---|
| 328 |  | 
|---|
| 329 | /* | 
|---|
| 330 | * 0x04 is format in progress .. but there must be a disc present! | 
|---|
| 331 | */ | 
|---|
| 332 | if (sshdr.sense_key == NOT_READY && sshdr.asc == 0x04) | 
|---|
| 333 | return CDS_DISC_OK; | 
|---|
| 334 |  | 
|---|
| 335 | /* | 
|---|
| 336 | * If not using Mt Fuji extended media tray reports, | 
|---|
| 337 | * just return TRAY_OPEN since ATAPI doesn't provide | 
|---|
| 338 | * any other way to detect this... | 
|---|
| 339 | */ | 
|---|
| 340 | if (scsi_sense_valid(sshdr: &sshdr) && | 
|---|
| 341 | /* 0x3a is medium not present */ | 
|---|
| 342 | sshdr.asc == 0x3a) | 
|---|
| 343 | return CDS_NO_DISC; | 
|---|
| 344 | else | 
|---|
| 345 | return CDS_TRAY_OPEN; | 
|---|
| 346 |  | 
|---|
| 347 | return CDS_DRIVE_NOT_READY; | 
|---|
| 348 | } | 
|---|
| 349 |  | 
|---|
| 350 | int sr_disk_status(struct cdrom_device_info *cdi) | 
|---|
| 351 | { | 
|---|
| 352 | Scsi_CD *cd = cdi->handle; | 
|---|
| 353 | struct cdrom_tochdr toc_h; | 
|---|
| 354 | struct cdrom_tocentry toc_e; | 
|---|
| 355 | int i, rc, have_datatracks = 0; | 
|---|
| 356 |  | 
|---|
| 357 | /* look for data tracks */ | 
|---|
| 358 | rc = sr_read_tochdr(cdi, tochdr: &toc_h); | 
|---|
| 359 | if (rc) | 
|---|
| 360 | return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO; | 
|---|
| 361 |  | 
|---|
| 362 | for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) { | 
|---|
| 363 | toc_e.cdte_track = i; | 
|---|
| 364 | toc_e.cdte_format = CDROM_LBA; | 
|---|
| 365 | if (sr_read_tocentry(cdi, tocentry: &toc_e)) | 
|---|
| 366 | return CDS_NO_INFO; | 
|---|
| 367 | if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) { | 
|---|
| 368 | have_datatracks = 1; | 
|---|
| 369 | break; | 
|---|
| 370 | } | 
|---|
| 371 | } | 
|---|
| 372 | if (!have_datatracks) | 
|---|
| 373 | return CDS_AUDIO; | 
|---|
| 374 |  | 
|---|
| 375 | if (cd->xa_flag) | 
|---|
| 376 | return CDS_XA_2_1; | 
|---|
| 377 | else | 
|---|
| 378 | return CDS_DATA_1; | 
|---|
| 379 | } | 
|---|
| 380 |  | 
|---|
| 381 | int sr_get_last_session(struct cdrom_device_info *cdi, | 
|---|
| 382 | struct cdrom_multisession *ms_info) | 
|---|
| 383 | { | 
|---|
| 384 | Scsi_CD *cd = cdi->handle; | 
|---|
| 385 |  | 
|---|
| 386 | ms_info->addr.lba = cd->ms_offset; | 
|---|
| 387 | ms_info->xa_flag = cd->xa_flag || cd->ms_offset > 0; | 
|---|
| 388 |  | 
|---|
| 389 | return 0; | 
|---|
| 390 | } | 
|---|
| 391 |  | 
|---|
| 392 | int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) | 
|---|
| 393 | { | 
|---|
| 394 | Scsi_CD *cd = cdi->handle; | 
|---|
| 395 | struct packet_command cgc; | 
|---|
| 396 | char *buffer = kzalloc(32, GFP_KERNEL); | 
|---|
| 397 | int result; | 
|---|
| 398 |  | 
|---|
| 399 | if (!buffer) | 
|---|
| 400 | return -ENOMEM; | 
|---|
| 401 |  | 
|---|
| 402 | memset(s: &cgc, c: 0, n: sizeof(struct packet_command)); | 
|---|
| 403 | cgc.cmd[0] = GPCMD_READ_SUBCHANNEL; | 
|---|
| 404 | cgc.cmd[2] = 0x40;	/* I do want the subchannel info */ | 
|---|
| 405 | cgc.cmd[3] = 0x02;	/* Give me medium catalog number info */ | 
|---|
| 406 | cgc.cmd[8] = 24; | 
|---|
| 407 | cgc.buffer = buffer; | 
|---|
| 408 | cgc.buflen = 24; | 
|---|
| 409 | cgc.data_direction = DMA_FROM_DEVICE; | 
|---|
| 410 | cgc.timeout = IOCTL_TIMEOUT; | 
|---|
| 411 | result = sr_do_ioctl(cd, cgc: &cgc); | 
|---|
| 412 | if (result) | 
|---|
| 413 | goto err; | 
|---|
| 414 |  | 
|---|
| 415 | memcpy(to: mcn->medium_catalog_number, from: buffer + 9, len: 13); | 
|---|
| 416 | mcn->medium_catalog_number[13] = 0; | 
|---|
| 417 |  | 
|---|
| 418 | err: | 
|---|
| 419 | kfree(objp: buffer); | 
|---|
| 420 | return result; | 
|---|
| 421 | } | 
|---|
| 422 |  | 
|---|
| 423 | int sr_reset(struct cdrom_device_info *cdi) | 
|---|
| 424 | { | 
|---|
| 425 | return 0; | 
|---|
| 426 | } | 
|---|
| 427 |  | 
|---|
| 428 | int sr_select_speed(struct cdrom_device_info *cdi, unsigned long speed) | 
|---|
| 429 | { | 
|---|
| 430 | Scsi_CD *cd = cdi->handle; | 
|---|
| 431 | struct packet_command cgc; | 
|---|
| 432 |  | 
|---|
| 433 | /* avoid exceeding the max speed or overflowing integer bounds */ | 
|---|
| 434 | speed = clamp(speed, 0, 0xffff / 177); | 
|---|
| 435 |  | 
|---|
| 436 | if (speed == 0) | 
|---|
| 437 | speed = 0xffff;	/* set to max */ | 
|---|
| 438 | else | 
|---|
| 439 | speed *= 177;	/* Nx to kbyte/s */ | 
|---|
| 440 |  | 
|---|
| 441 | memset(s: &cgc, c: 0, n: sizeof(struct packet_command)); | 
|---|
| 442 | cgc.cmd[0] = GPCMD_SET_SPEED;	/* SET CD SPEED */ | 
|---|
| 443 | cgc.cmd[2] = (speed >> 8) & 0xff;	/* MSB for speed (in kbytes/sec) */ | 
|---|
| 444 | cgc.cmd[3] = speed & 0xff;	/* LSB */ | 
|---|
| 445 | cgc.data_direction = DMA_NONE; | 
|---|
| 446 | cgc.timeout = IOCTL_TIMEOUT; | 
|---|
| 447 |  | 
|---|
| 448 | if (sr_do_ioctl(cd, cgc: &cgc)) | 
|---|
| 449 | return -EIO; | 
|---|
| 450 | return 0; | 
|---|
| 451 | } | 
|---|
| 452 |  | 
|---|
| 453 | /* ----------------------------------------------------------------------- */ | 
|---|
| 454 | /* this is called by the generic cdrom driver. arg is a _kernel_ pointer,  */ | 
|---|
| 455 | /* because the generic cdrom driver does the user access stuff for us.     */ | 
|---|
| 456 | /* only cdromreadtochdr and cdromreadtocentry are left - for use with the  */ | 
|---|
| 457 | /* sr_disk_status interface for the generic cdrom driver.                  */ | 
|---|
| 458 |  | 
|---|
| 459 | int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) | 
|---|
| 460 | { | 
|---|
| 461 | switch (cmd) { | 
|---|
| 462 | case CDROMREADTOCHDR: | 
|---|
| 463 | return sr_read_tochdr(cdi, tochdr: arg); | 
|---|
| 464 | case CDROMREADTOCENTRY: | 
|---|
| 465 | return sr_read_tocentry(cdi, tocentry: arg); | 
|---|
| 466 | case CDROMPLAYTRKIND: | 
|---|
| 467 | return sr_play_trkind(cdi, ti: arg); | 
|---|
| 468 | default: | 
|---|
| 469 | return -EINVAL; | 
|---|
| 470 | } | 
|---|
| 471 | } | 
|---|
| 472 |  | 
|---|
| 473 | /* ----------------------------------------------------------------------- | 
|---|
| 474 | * a function to read all sorts of funny cdrom sectors using the READ_CD | 
|---|
| 475 | * scsi-3 mmc command | 
|---|
| 476 | * | 
|---|
| 477 | * lba:     linear block address | 
|---|
| 478 | * format:  0 = data (anything) | 
|---|
| 479 | *          1 = audio | 
|---|
| 480 | *          2 = data (mode 1) | 
|---|
| 481 | *          3 = data (mode 2) | 
|---|
| 482 | *          4 = data (mode 2 form1) | 
|---|
| 483 | *          5 = data (mode 2 form2) | 
|---|
| 484 | * blksize: 2048 | 2336 | 2340 | 2352 | 
|---|
| 485 | */ | 
|---|
| 486 |  | 
|---|
| 487 | static int sr_read_cd(Scsi_CD *cd, unsigned char *dest, int lba, int format, int blksize) | 
|---|
| 488 | { | 
|---|
| 489 | struct packet_command cgc; | 
|---|
| 490 |  | 
|---|
| 491 | #ifdef DEBUG | 
|---|
| 492 | sr_printk(KERN_INFO, cd, "sr_read_cd lba=%d format=%d blksize=%d\n", | 
|---|
| 493 | lba, format, blksize); | 
|---|
| 494 | #endif | 
|---|
| 495 |  | 
|---|
| 496 | memset(s: &cgc, c: 0, n: sizeof(struct packet_command)); | 
|---|
| 497 | cgc.cmd[0] = GPCMD_READ_CD;	/* READ_CD */ | 
|---|
| 498 | cgc.cmd[1] = ((format & 7) << 2); | 
|---|
| 499 | cgc.cmd[2] = (unsigned char) (lba >> 24) & 0xff; | 
|---|
| 500 | cgc.cmd[3] = (unsigned char) (lba >> 16) & 0xff; | 
|---|
| 501 | cgc.cmd[4] = (unsigned char) (lba >> 8) & 0xff; | 
|---|
| 502 | cgc.cmd[5] = (unsigned char) lba & 0xff; | 
|---|
| 503 | cgc.cmd[8] = 1; | 
|---|
| 504 | switch (blksize) { | 
|---|
| 505 | case 2336: | 
|---|
| 506 | cgc.cmd[9] = 0x58; | 
|---|
| 507 | break; | 
|---|
| 508 | case 2340: | 
|---|
| 509 | cgc.cmd[9] = 0x78; | 
|---|
| 510 | break; | 
|---|
| 511 | case 2352: | 
|---|
| 512 | cgc.cmd[9] = 0xf8; | 
|---|
| 513 | break; | 
|---|
| 514 | default: | 
|---|
| 515 | cgc.cmd[9] = 0x10; | 
|---|
| 516 | break; | 
|---|
| 517 | } | 
|---|
| 518 | cgc.buffer = dest; | 
|---|
| 519 | cgc.buflen = blksize; | 
|---|
| 520 | cgc.data_direction = DMA_FROM_DEVICE; | 
|---|
| 521 | cgc.timeout = IOCTL_TIMEOUT; | 
|---|
| 522 | return sr_do_ioctl(cd, cgc: &cgc); | 
|---|
| 523 | } | 
|---|
| 524 |  | 
|---|
| 525 | /* | 
|---|
| 526 | * read sectors with blocksizes other than 2048 | 
|---|
| 527 | */ | 
|---|
| 528 |  | 
|---|
| 529 | static int sr_read_sector(Scsi_CD *cd, int lba, int blksize, unsigned char *dest) | 
|---|
| 530 | { | 
|---|
| 531 | struct packet_command cgc; | 
|---|
| 532 | int rc; | 
|---|
| 533 |  | 
|---|
| 534 | /* we try the READ CD command first... */ | 
|---|
| 535 | if (cd->readcd_known) { | 
|---|
| 536 | rc = sr_read_cd(cd, dest, lba, format: 0, blksize); | 
|---|
| 537 | if (-EDRIVE_CANT_DO_THIS != rc) | 
|---|
| 538 | return rc; | 
|---|
| 539 | cd->readcd_known = 0; | 
|---|
| 540 | sr_printk(KERN_INFO, cd, | 
|---|
| 541 | "CDROM doesn't support READ CD (0xbe) command\n"); | 
|---|
| 542 | /* fall & retry the other way */ | 
|---|
| 543 | } | 
|---|
| 544 | /* ... if this fails, we switch the blocksize using MODE SELECT */ | 
|---|
| 545 | if (blksize != cd->device->sector_size) { | 
|---|
| 546 | if (0 != (rc = sr_set_blocklength(cd, blocklength: blksize))) | 
|---|
| 547 | return rc; | 
|---|
| 548 | } | 
|---|
| 549 | #ifdef DEBUG | 
|---|
| 550 | sr_printk(KERN_INFO, cd, "sr_read_sector lba=%d blksize=%d\n", | 
|---|
| 551 | lba, blksize); | 
|---|
| 552 | #endif | 
|---|
| 553 |  | 
|---|
| 554 | memset(s: &cgc, c: 0, n: sizeof(struct packet_command)); | 
|---|
| 555 | cgc.cmd[0] = GPCMD_READ_10; | 
|---|
| 556 | cgc.cmd[2] = (unsigned char) (lba >> 24) & 0xff; | 
|---|
| 557 | cgc.cmd[3] = (unsigned char) (lba >> 16) & 0xff; | 
|---|
| 558 | cgc.cmd[4] = (unsigned char) (lba >> 8) & 0xff; | 
|---|
| 559 | cgc.cmd[5] = (unsigned char) lba & 0xff; | 
|---|
| 560 | cgc.cmd[8] = 1; | 
|---|
| 561 | cgc.buffer = dest; | 
|---|
| 562 | cgc.buflen = blksize; | 
|---|
| 563 | cgc.data_direction = DMA_FROM_DEVICE; | 
|---|
| 564 | cgc.timeout = IOCTL_TIMEOUT; | 
|---|
| 565 | rc = sr_do_ioctl(cd, cgc: &cgc); | 
|---|
| 566 |  | 
|---|
| 567 | if (blksize != CD_FRAMESIZE) | 
|---|
| 568 | rc |= sr_set_blocklength(cd, CD_FRAMESIZE); | 
|---|
| 569 | return rc; | 
|---|
| 570 | } | 
|---|
| 571 |  | 
|---|
| 572 | /* | 
|---|
| 573 | * read a sector in raw mode to check the sector format | 
|---|
| 574 | * ret: 1 == mode2 (XA), 0 == mode1, <0 == error | 
|---|
| 575 | */ | 
|---|
| 576 |  | 
|---|
| 577 | int sr_is_xa(Scsi_CD *cd) | 
|---|
| 578 | { | 
|---|
| 579 | unsigned char *raw_sector; | 
|---|
| 580 | int is_xa; | 
|---|
| 581 |  | 
|---|
| 582 | if (!xa_test) | 
|---|
| 583 | return 0; | 
|---|
| 584 |  | 
|---|
| 585 | raw_sector = kmalloc(2048, GFP_KERNEL); | 
|---|
| 586 | if (!raw_sector) | 
|---|
| 587 | return -ENOMEM; | 
|---|
| 588 | if (0 == sr_read_sector(cd, lba: cd->ms_offset + 16, | 
|---|
| 589 | CD_FRAMESIZE_RAW1, dest: raw_sector)) { | 
|---|
| 590 | is_xa = (raw_sector[3] == 0x02) ? 1 : 0; | 
|---|
| 591 | } else { | 
|---|
| 592 | /* read a raw sector failed for some reason. */ | 
|---|
| 593 | is_xa = -1; | 
|---|
| 594 | } | 
|---|
| 595 | kfree(objp: raw_sector); | 
|---|
| 596 | #ifdef DEBUG | 
|---|
| 597 | sr_printk(KERN_INFO, cd, "sr_is_xa: %d\n", is_xa); | 
|---|
| 598 | #endif | 
|---|
| 599 | return is_xa; | 
|---|
| 600 | } | 
|---|
| 601 |  | 
|---|