1809 lines · 45.9 KB · C
RawDownload
/* * ATAPI CD-ROM driver. * * Copyright (C) 1994-1996   Scott Snyder <snyder@fnald0.fnal.gov> * Copyright (C) 1996-1998   Erik Andersen <andersee@debian.org> * Copyright (C) 1998-2000   Jens Axboe <axboe@suse.de> * Copyright (C) 2005, 2007-2009  Bartlomiej Zolnierkiewicz * * May be copied or modified under the terms of the GNU General Public * License.  See linux/COPYING for more information. * * See Documentation/cdrom/ide-cd for usage information. * * Suggestions are welcome. Patches that work are more welcome though. ;-) * * Documentation: *	Mt. Fuji (SFF8090 version 4) and ATAPI (SFF-8020i rev 2.6) standards. * * For historical changelog please see: *	Documentation/ide/ChangeLog.ide-cd.1994-2004 */ #define DRV_NAME "ide-cd"#define PFX DRV_NAME ": " #define IDECD_VERSION "5.00" #include <linux/module.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/timer.h>#include <linux/seq_file.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/errno.h>#include <linux/cdrom.h>#include <linux/ide.h>#include <linux/completion.h>#include <linux/mutex.h>#include <linux/bcd.h> /* For SCSI -> ATAPI command conversion */#include <scsi/scsi.h> #include <linux/io.h>#include <asm/byteorder.h>#include <linux/uaccess.h>#include <asm/unaligned.h> #include "ide-cd.h" static DEFINE_MUTEX(ide_cd_mutex);static DEFINE_MUTEX(idecd_ref_mutex); static void ide_cd_release(struct device *); static struct cdrom_info *ide_cd_get(struct gendisk *disk){	struct cdrom_info *cd = NULL; 	mutex_lock(&idecd_ref_mutex);	cd = ide_drv_g(disk, cdrom_info);	if (cd) {		if (ide_device_get(cd->drive))			cd = NULL;		else			get_device(&cd->dev); 	}	mutex_unlock(&idecd_ref_mutex);	return cd;} static void ide_cd_put(struct cdrom_info *cd){	ide_drive_t *drive = cd->drive; 	mutex_lock(&idecd_ref_mutex);	put_device(&cd->dev);	ide_device_put(drive);	mutex_unlock(&idecd_ref_mutex);} /* * Generic packet command support and error handling routines. */ /* Mark that we've seen a media change and invalidate our internal buffers. */static void cdrom_saw_media_change(ide_drive_t *drive){	drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;	drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID;} static int cdrom_log_sense(ide_drive_t *drive, struct request *rq){	struct request_sense *sense = &drive->sense_data;	int log = 0; 	if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))		return 0; 	ide_debug_log(IDE_DBG_SENSE, "sense_key: 0x%x", sense->sense_key); 	switch (sense->sense_key) {	case NO_SENSE:	case RECOVERED_ERROR:		break;	case NOT_READY:		/*		 * don't care about tray state messages for e.g. capacity		 * commands or in-progress or becoming ready		 */		if (sense->asc == 0x3a || sense->asc == 0x04)			break;		log = 1;		break;	case ILLEGAL_REQUEST:		/*		 * don't log START_STOP unit with LoEj set, since we cannot		 * reliably check if drive can auto-close		 */		if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)			break;		log = 1;		break;	case UNIT_ATTENTION:		/*		 * Make good and sure we've seen this potential media change.		 * Some drives (i.e. Creative) fail to present the correct sense		 * key in the error register.		 */		cdrom_saw_media_change(drive);		break;	default:		log = 1;		break;	}	return log;} static void cdrom_analyze_sense_data(ide_drive_t *drive,				     struct request *failed_command){	struct request_sense *sense = &drive->sense_data;	struct cdrom_info *info = drive->driver_data;	unsigned long sector;	unsigned long bio_sectors; 	ide_debug_log(IDE_DBG_SENSE, "error_code: 0x%x, sense_key: 0x%x",				     sense->error_code, sense->sense_key); 	if (failed_command)		ide_debug_log(IDE_DBG_SENSE, "failed cmd: 0x%x",					     failed_command->cmd[0]); 	if (!cdrom_log_sense(drive, failed_command))		return; 	/*	 * If a read toc is executed for a CD-R or CD-RW medium where the first	 * toc has not been recorded yet, it will fail with 05/24/00 (which is a	 * confusing error)	 */	if (failed_command && failed_command->cmd[0] == GPCMD_READ_TOC_PMA_ATIP)		if (sense->sense_key == 0x05 && sense->asc == 0x24)			return; 	/* current error */	if (sense->error_code == 0x70) {		switch (sense->sense_key) {		case MEDIUM_ERROR:		case VOLUME_OVERFLOW:		case ILLEGAL_REQUEST:			if (!sense->valid)				break;			if (failed_command == NULL ||			    failed_command->cmd_type != REQ_TYPE_FS)				break;			sector = (sense->information[0] << 24) |				 (sense->information[1] << 16) |				 (sense->information[2] <<  8) |				 (sense->information[3]); 			if (queue_logical_block_size(drive->queue) == 2048)				/* device sector size is 2K */				sector <<= 2; 			bio_sectors = max(bio_sectors(failed_command->bio), 4U);			sector &= ~(bio_sectors - 1); 			/*			 * The SCSI specification allows for the value			 * returned by READ CAPACITY to be up to 75 2K			 * sectors past the last readable block.			 * Therefore, if we hit a medium error within the			 * last 75 2K sectors, we decrease the saved size			 * value.			 */			if (sector < get_capacity(info->disk) &&			    drive->probed_capacity - sector < 4 * 75)				set_capacity(info->disk, sector);		}	} 	ide_cd_log_error(drive->name, failed_command, sense);} static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq){	/*	 * For REQ_TYPE_SENSE, "rq->special" points to the original	 * failed request.  Also, the sense data should be read	 * directly from rq which might be different from the original	 * sense buffer if it got copied during mapping.	 */	struct request *failed = (struct request *)rq->special;	void *sense = bio_data(rq->bio); 	if (failed) {		if (failed->sense) {			/*			 * Sense is always read into drive->sense_data.			 * Copy back if the failed request has its			 * sense pointer set.			 */			memcpy(failed->sense, sense, 18);			failed->sense_len = rq->sense_len;		}		cdrom_analyze_sense_data(drive, failed); 		if (ide_end_rq(drive, failed, -EIO, blk_rq_bytes(failed)))			BUG();	} else		cdrom_analyze_sense_data(drive, NULL);}  /* * Allow the drive 5 seconds to recover; some devices will return NOT_READY * while flushing data from cache. * * returns: 0 failed (write timeout expired) *	    1 success */static int ide_cd_breathe(ide_drive_t *drive, struct request *rq){ 	struct cdrom_info *info = drive->driver_data; 	if (!rq->errors)		info->write_timeout = jiffies +	ATAPI_WAIT_WRITE_BUSY; 	rq->errors = 1; 	if (time_after(jiffies, info->write_timeout))		return 0;	else {		/*		 * take a breather		 */		blk_delay_queue(drive->queue, 1);		return 1;	}} /** * Returns: * 0: if the request should be continued. * 1: if the request will be going through error recovery. * 2: if the request should be ended. */static int cdrom_decode_status(ide_drive_t *drive, u8 stat){	ide_hwif_t *hwif = drive->hwif;	struct request *rq = hwif->rq;	int err, sense_key, do_end_request = 0; 	/* get the IDE error register */	err = ide_read_error(drive);	sense_key = err >> 4; 	ide_debug_log(IDE_DBG_RQ, "cmd: 0x%x, rq->cmd_type: 0x%x, err: 0x%x, "				  "stat 0x%x",				  rq->cmd[0], rq->cmd_type, err, stat); 	if (rq->cmd_type == REQ_TYPE_SENSE) {		/*		 * We got an error trying to get sense info from the drive		 * (probably while trying to recover from a former error).		 * Just give up.		 */		rq->cmd_flags |= REQ_FAILED;		return 2;	} 	/* if we have an error, pass CHECK_CONDITION as the SCSI status byte */	if (rq->cmd_type == REQ_TYPE_BLOCK_PC && !rq->errors)		rq->errors = SAM_STAT_CHECK_CONDITION; 	if (blk_noretry_request(rq))		do_end_request = 1; 	switch (sense_key) {	case NOT_READY:		if (rq->cmd_type == REQ_TYPE_FS && rq_data_dir(rq) == WRITE) {			if (ide_cd_breathe(drive, rq))				return 1;		} else {			cdrom_saw_media_change(drive); 			if (rq->cmd_type == REQ_TYPE_FS &&			    !(rq->cmd_flags & REQ_QUIET))				printk(KERN_ERR PFX "%s: tray open\n",					drive->name);		}		do_end_request = 1;		break;	case UNIT_ATTENTION:		cdrom_saw_media_change(drive); 		if (rq->cmd_type != REQ_TYPE_FS)			return 0; 		/*		 * Arrange to retry the request but be sure to give up if we've		 * retried too many times.		 */		if (++rq->errors > ERROR_MAX)			do_end_request = 1;		break;	case ILLEGAL_REQUEST:		/*		 * Don't print error message for this condition -- SFF8090i		 * indicates that 5/24/00 is the correct response to a request		 * to close the tray if the drive doesn't have that capability.		 *		 * cdrom_log_sense() knows this!		 */		if (rq->cmd[0] == GPCMD_START_STOP_UNIT)			break;		/* fall-through */	case DATA_PROTECT:		/*		 * No point in retrying after an illegal request or data		 * protect error.		 */		if (!(rq->cmd_flags & REQ_QUIET))			ide_dump_status(drive, "command error", stat);		do_end_request = 1;		break;	case MEDIUM_ERROR:		/*		 * No point in re-trying a zillion times on a bad sector.		 * If we got here the error is not correctable.		 */		if (!(rq->cmd_flags & REQ_QUIET))			ide_dump_status(drive, "media error "					"(bad sector)", stat);		do_end_request = 1;		break;	case BLANK_CHECK:		/* disk appears blank? */		if (!(rq->cmd_flags & REQ_QUIET))			ide_dump_status(drive, "media error (blank)",					stat);		do_end_request = 1;		break;	default:		if (rq->cmd_type != REQ_TYPE_FS)			break;		if (err & ~ATA_ABORTED) {			/* go to the default handler for other errors */			ide_error(drive, "cdrom_decode_status", stat);			return 1;		} else if (++rq->errors > ERROR_MAX)			/* we've racked up too many retries, abort */			do_end_request = 1;	} 	if (rq->cmd_type != REQ_TYPE_FS) {		rq->cmd_flags |= REQ_FAILED;		do_end_request = 1;	} 	/*	 * End a request through request sense analysis when we have sense data.	 * We need this in order to perform end of media processing.	 */	if (do_end_request)		goto end_request; 	/* if we got a CHECK_CONDITION status, queue a request sense command */	if (stat & ATA_ERR)		return ide_queue_sense_rq(drive, NULL) ? 2 : 1;	return 1; end_request:	if (stat & ATA_ERR) {		hwif->rq = NULL;		return ide_queue_sense_rq(drive, rq) ? 2 : 1;	} else		return 2;} static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd){	struct request *rq = cmd->rq; 	ide_debug_log(IDE_DBG_FUNC, "rq->cmd[0]: 0x%x", rq->cmd[0]); 	/*	 * Some of the trailing request sense fields are optional,	 * and some drives don't send them.  Sigh.	 */	if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&	    cmd->nleft > 0 && cmd->nleft <= 5)		cmd->nleft = 0;} int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,		    int write, void *buffer, unsigned *bufflen,		    struct request_sense *sense, int timeout,		    unsigned int cmd_flags){	struct cdrom_info *info = drive->driver_data;	struct request_sense local_sense;	int retries = 10;	unsigned int flags = 0; 	if (!sense)		sense = &local_sense; 	ide_debug_log(IDE_DBG_PC, "cmd[0]: 0x%x, write: 0x%x, timeout: %d, "				  "cmd_flags: 0x%x",				  cmd[0], write, timeout, cmd_flags); 	/* start of retry loop */	do {		struct request *rq;		int error; 		rq = blk_get_request(drive->queue, write, __GFP_WAIT); 		memcpy(rq->cmd, cmd, BLK_MAX_CDB);		rq->cmd_type = REQ_TYPE_ATA_PC;		rq->sense = sense;		rq->cmd_flags |= cmd_flags;		rq->timeout = timeout;		if (buffer) {			error = blk_rq_map_kern(drive->queue, rq, buffer,						*bufflen, GFP_NOIO);			if (error) {				blk_put_request(rq);				return error;			}		} 		error = blk_execute_rq(drive->queue, info->disk, rq, 0); 		if (buffer)			*bufflen = rq->resid_len; 		flags = rq->cmd_flags;		blk_put_request(rq); 		/*		 * FIXME: we should probably abort/retry or something in case of		 * failure.		 */		if (flags & REQ_FAILED) {			/*			 * The request failed.  Retry if it was due to a unit			 * attention status (usually means media was changed).			 */			struct request_sense *reqbuf = sense; 			if (reqbuf->sense_key == UNIT_ATTENTION)				cdrom_saw_media_change(drive);			else if (reqbuf->sense_key == NOT_READY &&				 reqbuf->asc == 4 && reqbuf->ascq != 4) {				/*				 * The drive is in the process of loading				 * a disk.  Retry, but wait a little to give				 * the drive time to complete the load.				 */				ssleep(2);			} else {				/* otherwise, don't retry */				retries = 0;			}			--retries;		} 		/* end of retry loop */	} while ((flags & REQ_FAILED) && retries >= 0); 	/* return an error if the command failed */	return (flags & REQ_FAILED) ? -EIO : 0;

Lines 1–500 of 1809.