/* The sr_is_xa() seems to trigger firmware bugs with some drives :-(
* It is off by default and can be turned on with this module parameter */ staticint xa_test = 0;
/* ATAPI drives don't have a SCMD_PLAYAUDIO_TI command. When these drives are emulating a SCSI device via the idescsi module, they need to have
CDROMPLAYTRKIND commands translated into CDROMPLAYMSF commands for them */
result = sr_do_ioctl(cd, &cgc); if (result == -EDRIVE_CANT_DO_THIS)
result = sr_fake_playtrkind(cdi, ti);
return result;
}
/* We do our own retries because we want to know what the specific error code is. Normally the UNIT_ATTENTION code will automatically
clear after one error */
int sr_drive_status(struct cdrom_device_info *cdi, int slot)
{ struct scsi_cd *cd = cdi->handle; struct scsi_sense_hdr sshdr; struct media_event_desc med;
if (CDSL_CURRENT != slot) { /* we have no changer support */ return -EINVAL;
} if (!scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr)) return CDS_DISC_OK;
/* SK/ASC/ASCQ of 2/4/1 means "unit is becoming ready" */ if (scsi_sense_valid(&sshdr) && sshdr.sense_key == NOT_READY
&& sshdr.asc == 0x04 && sshdr.ascq == 0x01) return CDS_DRIVE_NOT_READY;
if (!cdrom_get_media_event(cdi, &med)) { if (med.media_present) return CDS_DISC_OK; elseif (med.door_open) return CDS_TRAY_OPEN; else return CDS_NO_DISC;
}
/* * SK/ASC/ASCQ of 2/4/2 means "initialization required" * Using CD_TRAY_OPEN results in an START_STOP_UNIT to close * the tray, which resolves the initialization requirement.
*/ if (scsi_sense_valid(&sshdr) && sshdr.sense_key == NOT_READY
&& sshdr.asc == 0x04 && sshdr.ascq == 0x02) return CDS_TRAY_OPEN;
/* * 0x04 is format in progress .. but there must be a disc present!
*/ if (sshdr.sense_key == NOT_READY && sshdr.asc == 0x04) return CDS_DISC_OK;
/* * If not using Mt Fuji extended media tray reports, * just return TRAY_OPEN since ATAPI doesn't provide * any other way to detect this...
*/ if (scsi_sense_valid(&sshdr) && /* 0x3a is medium not present */
sshdr.asc == 0x3a) return CDS_NO_DISC; else return CDS_TRAY_OPEN;
return CDS_DRIVE_NOT_READY;
}
int sr_disk_status(struct cdrom_device_info *cdi)
{
Scsi_CD *cd = cdi->handle; struct cdrom_tochdr toc_h; struct cdrom_tocentry toc_e; int i, rc, have_datatracks = 0;
/* look for data tracks */
rc = sr_read_tochdr(cdi, &toc_h); if (rc) return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO;
for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) {
toc_e.cdte_track = i;
toc_e.cdte_format = CDROM_LBA; if (sr_read_tocentry(cdi, &toc_e)) return CDS_NO_INFO; if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) {
have_datatracks = 1; break;
}
} if (!have_datatracks) return CDS_AUDIO;
if (cd->xa_flag) return CDS_XA_2_1; else return CDS_DATA_1;
}
memset(&cgc, 0, sizeof(struct packet_command));
cgc.cmd[0] = GPCMD_READ_SUBCHANNEL;
cgc.cmd[2] = 0x40; /* I do want the subchannel info */
cgc.cmd[3] = 0x02; /* Give me medium catalog number info */
cgc.cmd[8] = 24;
cgc.buffer = buffer;
cgc.buflen = 24;
cgc.data_direction = DMA_FROM_DEVICE;
cgc.timeout = IOCTL_TIMEOUT;
result = sr_do_ioctl(cd, &cgc); if (result) goto err;
/* avoid exceeding the max speed or overflowing integer bounds */
speed = clamp(speed, 0, 0xffff / 177);
if (speed == 0)
speed = 0xffff; /* set to max */ else
speed *= 177; /* Nx to kbyte/s */
memset(&cgc, 0, sizeof(struct packet_command));
cgc.cmd[0] = GPCMD_SET_SPEED; /* SET CD SPEED */
cgc.cmd[2] = (speed >> 8) & 0xff; /* MSB for speed (in kbytes/sec) */
cgc.cmd[3] = speed & 0xff; /* LSB */
cgc.data_direction = DMA_NONE;
cgc.timeout = IOCTL_TIMEOUT;
if (sr_do_ioctl(cd, &cgc)) return -EIO; return 0;
}
/* ----------------------------------------------------------------------- */ /* this is called by the generic cdrom driver. arg is a _kernel_ pointer, */ /* because the generic cdrom driver does the user access stuff for us. */ /* only cdromreadtochdr and cdromreadtocentry are left - for use with the */ /* sr_disk_status interface for the generic cdrom driver. */
int sr_audio_ioctl(struct cdrom_device_info *cdi, unsignedint cmd, void *arg)
{ switch (cmd) { case CDROMREADTOCHDR: return sr_read_tochdr(cdi, arg); case CDROMREADTOCENTRY: return sr_read_tocentry(cdi, arg); case CDROMPLAYTRKIND: return sr_play_trkind(cdi, arg); default: return -EINVAL;
}
}
/* ----------------------------------------------------------------------- * a function to read all sorts of funny cdrom sectors using the READ_CD * scsi-3 mmc command * * lba: linear block address * format: 0 = data (anything) * 1 = audio * 2 = data (mode 1) * 3 = data (mode 2) * 4 = data (mode 2 form1) * 5 = data (mode 2 form2) * blksize: 2048 | 2336 | 2340 | 2352
*/
staticint sr_read_cd(Scsi_CD *cd, unsignedchar *dest, int lba, int format, int blksize)
{ struct packet_command cgc;
/* * read sectors with blocksizes other than 2048
*/
staticint sr_read_sector(Scsi_CD *cd, int lba, int blksize, unsignedchar *dest)
{ struct packet_command cgc; int rc;
/* we try the READ CD command first... */ if (cd->readcd_known) {
rc = sr_read_cd(cd, dest, lba, 0, blksize); if (-EDRIVE_CANT_DO_THIS != rc) return rc;
cd->readcd_known = 0;
sr_printk(KERN_INFO, cd, "CDROM doesn't support READ CD (0xbe) command\n"); /* fall & retry the other way */
} /* ... if this fails, we switch the blocksize using MODE SELECT */ if (blksize != cd->device->sector_size) { if (0 != (rc = sr_set_blocklength(cd, blksize))) return rc;
} #ifdef DEBUG
sr_printk(KERN_INFO, cd, "sr_read_sector lba=%d blksize=%d\n",
lba, blksize); #endif
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.