⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libata-scsi.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct scsi_cmnd *scmd = qc->scsicmd;	struct ata_taskfile *tf = &qc->tf;	const u8 *cdb = scmd->cmnd;	if (scmd->cmd_len < 5)		goto invalid_fld;	tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;	tf->protocol = ATA_PROT_NODATA;	if (cdb[1] & 0x1) {		;	/* ignore IMMED bit, violates sat-r05 */	}	if (cdb[4] & 0x2)		goto invalid_fld;       /* LOEJ bit set not supported */	if (((cdb[4] >> 4) & 0xf) != 0)		goto invalid_fld;       /* power conditions not supported */	if (qc->dev->horkage & ATA_HORKAGE_SKIP_PM) {		/* the device lacks PM support, finish without doing anything */		scmd->result = SAM_STAT_GOOD;		return 1;	}	if (cdb[4] & 0x1) {		tf->nsect = 1;	/* 1 sector, lba=0 */		if (qc->dev->flags & ATA_DFLAG_LBA) {			tf->flags |= ATA_TFLAG_LBA;			tf->lbah = 0x0;			tf->lbam = 0x0;			tf->lbal = 0x0;			tf->device |= ATA_LBA;		} else {			/* CHS */			tf->lbal = 0x1; /* sect */			tf->lbam = 0x0; /* cyl low */			tf->lbah = 0x0; /* cyl high */		}		tf->command = ATA_CMD_VERIFY;	/* READ VERIFY */	} else {		/* XXX: This is for backward compatibility, will be		 * removed.  Read Documentation/feature-removal-schedule.txt		 * for more info.		 */		if ((qc->dev->flags & ATA_DFLAG_SPUNDOWN) &&		    (system_state == SYSTEM_HALT ||		     system_state == SYSTEM_POWER_OFF)) {			static unsigned long warned;			if (!test_and_set_bit(0, &warned)) {				ata_dev_printk(qc->dev, KERN_WARNING,					"DISK MIGHT NOT BE SPUN DOWN PROPERLY. "					"UPDATE SHUTDOWN UTILITY\n");				ata_dev_printk(qc->dev, KERN_WARNING,					"For more info, visit "					"http://linux-ata.org/shutdown.html\n");				/* ->scsi_done is not used, use it for				 * delayed completion.				 */				scmd->scsi_done = qc->scsidone;				qc->scsidone = ata_delayed_done;			}			scmd->result = SAM_STAT_GOOD;			return 1;		}		/* Issue ATA STANDBY IMMEDIATE command */		tf->command = ATA_CMD_STANDBYNOW1;	}	/*	 * Standby and Idle condition timers could be implemented but that	 * would require libata to implement the Power condition mode page	 * and allow the user to change it. Changing mode pages requires	 * MODE SELECT to be implemented.	 */	return 0;invalid_fld:	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);	/* "Invalid field in cbd" */	return 1;}/** *	ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command *	@qc: Storage for translated ATA taskfile * *	Sets up an ATA taskfile to issue FLUSH CACHE or *	FLUSH CACHE EXT. * *	LOCKING: *	spin_lock_irqsave(host lock) * *	RETURNS: *	Zero on success, non-zero on error. */static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc){	struct ata_taskfile *tf = &qc->tf;	tf->flags |= ATA_TFLAG_DEVICE;	tf->protocol = ATA_PROT_NODATA;	if (qc->dev->flags & ATA_DFLAG_FLUSH_EXT)		tf->command = ATA_CMD_FLUSH_EXT;	else		tf->command = ATA_CMD_FLUSH;	/* flush is critical for IO integrity, consider it an IO command */	qc->flags |= ATA_QCFLAG_IO;	return 0;}/** *	scsi_6_lba_len - Get LBA and transfer length *	@cdb: SCSI command to translate * *	Calculate LBA and transfer length for 6-byte commands. * *	RETURNS: *	@plba: the LBA *	@plen: the transfer length */static void scsi_6_lba_len(const u8 *cdb, u64 *plba, u32 *plen){	u64 lba = 0;	u32 len;	VPRINTK("six-byte command\n");	lba |= ((u64)(cdb[1] & 0x1f)) << 16;	lba |= ((u64)cdb[2]) << 8;	lba |= ((u64)cdb[3]);	len = cdb[4];	*plba = lba;	*plen = len;}/** *	scsi_10_lba_len - Get LBA and transfer length *	@cdb: SCSI command to translate * *	Calculate LBA and transfer length for 10-byte commands. * *	RETURNS: *	@plba: the LBA *	@plen: the transfer length */static void scsi_10_lba_len(const u8 *cdb, u64 *plba, u32 *plen){	u64 lba = 0;	u32 len = 0;	VPRINTK("ten-byte command\n");	lba |= ((u64)cdb[2]) << 24;	lba |= ((u64)cdb[3]) << 16;	lba |= ((u64)cdb[4]) << 8;	lba |= ((u64)cdb[5]);	len |= ((u32)cdb[7]) << 8;	len |= ((u32)cdb[8]);	*plba = lba;	*plen = len;}/** *	scsi_16_lba_len - Get LBA and transfer length *	@cdb: SCSI command to translate * *	Calculate LBA and transfer length for 16-byte commands. * *	RETURNS: *	@plba: the LBA *	@plen: the transfer length */static void scsi_16_lba_len(const u8 *cdb, u64 *plba, u32 *plen){	u64 lba = 0;	u32 len = 0;	VPRINTK("sixteen-byte command\n");	lba |= ((u64)cdb[2]) << 56;	lba |= ((u64)cdb[3]) << 48;	lba |= ((u64)cdb[4]) << 40;	lba |= ((u64)cdb[5]) << 32;	lba |= ((u64)cdb[6]) << 24;	lba |= ((u64)cdb[7]) << 16;	lba |= ((u64)cdb[8]) << 8;	lba |= ((u64)cdb[9]);	len |= ((u32)cdb[10]) << 24;	len |= ((u32)cdb[11]) << 16;	len |= ((u32)cdb[12]) << 8;	len |= ((u32)cdb[13]);	*plba = lba;	*plen = len;}/** *	ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one *	@qc: Storage for translated ATA taskfile * *	Converts SCSI VERIFY command to an ATA READ VERIFY command. * *	LOCKING: *	spin_lock_irqsave(host lock) * *	RETURNS: *	Zero on success, non-zero on error. */static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc){	struct scsi_cmnd *scmd = qc->scsicmd;	struct ata_taskfile *tf = &qc->tf;	struct ata_device *dev = qc->dev;	u64 dev_sectors = qc->dev->n_sectors;	const u8 *cdb = scmd->cmnd;	u64 block;	u32 n_block;	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;	tf->protocol = ATA_PROT_NODATA;	if (cdb[0] == VERIFY) {		if (scmd->cmd_len < 10)			goto invalid_fld;		scsi_10_lba_len(cdb, &block, &n_block);	} else if (cdb[0] == VERIFY_16) {		if (scmd->cmd_len < 16)			goto invalid_fld;		scsi_16_lba_len(cdb, &block, &n_block);	} else		goto invalid_fld;	if (!n_block)		goto nothing_to_do;	if (block >= dev_sectors)		goto out_of_range;	if ((block + n_block) > dev_sectors)		goto out_of_range;	if (dev->flags & ATA_DFLAG_LBA) {		tf->flags |= ATA_TFLAG_LBA;		if (lba_28_ok(block, n_block)) {			/* use LBA28 */			tf->command = ATA_CMD_VERIFY;			tf->device |= (block >> 24) & 0xf;		} else if (lba_48_ok(block, n_block)) {			if (!(dev->flags & ATA_DFLAG_LBA48))				goto out_of_range;			/* use LBA48 */			tf->flags |= ATA_TFLAG_LBA48;			tf->command = ATA_CMD_VERIFY_EXT;			tf->hob_nsect = (n_block >> 8) & 0xff;			tf->hob_lbah = (block >> 40) & 0xff;			tf->hob_lbam = (block >> 32) & 0xff;			tf->hob_lbal = (block >> 24) & 0xff;		} else			/* request too large even for LBA48 */			goto out_of_range;		tf->nsect = n_block & 0xff;		tf->lbah = (block >> 16) & 0xff;		tf->lbam = (block >> 8) & 0xff;		tf->lbal = block & 0xff;		tf->device |= ATA_LBA;	} else {		/* CHS */		u32 sect, head, cyl, track;		if (!lba_28_ok(block, n_block))			goto out_of_range;		/* Convert LBA to CHS */		track = (u32)block / dev->sectors;		cyl   = track / dev->heads;		head  = track % dev->heads;		sect  = (u32)block % dev->sectors + 1;		DPRINTK("block %u track %u cyl %u head %u sect %u\n",			(u32)block, track, cyl, head, sect);		/* Check whether the converted CHS can fit.		   Cylinder: 0-65535		   Head: 0-15		   Sector: 1-255*/		if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))			goto out_of_range;		tf->command = ATA_CMD_VERIFY;		tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */		tf->lbal = sect;		tf->lbam = cyl;		tf->lbah = cyl >> 8;		tf->device |= head;	}	return 0;invalid_fld:	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);	/* "Invalid field in cbd" */	return 1;out_of_range:	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x21, 0x0);	/* "Logical Block Address out of range" */	return 1;nothing_to_do:	scmd->result = SAM_STAT_GOOD;	return 1;}/** *	ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one *	@qc: Storage for translated ATA taskfile * *	Converts any of six SCSI read/write commands into the *	ATA counterpart, including starting sector (LBA), *	sector count, and taking into account the device's LBA48 *	support. * *	Commands %READ_6, %READ_10, %READ_16, %WRITE_6, %WRITE_10, and *	%WRITE_16 are currently supported. * *	LOCKING: *	spin_lock_irqsave(host lock) * *	RETURNS: *	Zero on success, non-zero on error. */static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc){	struct scsi_cmnd *scmd = qc->scsicmd;	const u8 *cdb = scmd->cmnd;	unsigned int tf_flags = 0;	u64 block;	u32 n_block;	int rc;	if (cdb[0] == WRITE_10 || cdb[0] == WRITE_6 || cdb[0] == WRITE_16)		tf_flags |= ATA_TFLAG_WRITE;	/* Calculate the SCSI LBA, transfer length and FUA. */	switch (cdb[0]) {	case READ_10:	case WRITE_10:		if (unlikely(scmd->cmd_len < 10))			goto invalid_fld;		scsi_10_lba_len(cdb, &block, &n_block);		if (unlikely(cdb[1] & (1 << 3)))			tf_flags |= ATA_TFLAG_FUA;		break;	case READ_6:	case WRITE_6:		if (unlikely(scmd->cmd_len < 6))			goto invalid_fld;		scsi_6_lba_len(cdb, &block, &n_block);		/* for 6-byte r/w commands, transfer length 0		 * means 256 blocks of data, not 0 block.		 */		if (!n_block)			n_block = 256;		break;	case READ_16:	case WRITE_16:		if (unlikely(scmd->cmd_len < 16))			goto invalid_fld;		scsi_16_lba_len(cdb, &block, &n_block);		if (unlikely(cdb[1] & (1 << 3)))			tf_flags |= ATA_TFLAG_FUA;		break;	default:		DPRINTK("no-byte command\n");		goto invalid_fld;	}	/* Check and compose ATA command */	if (!n_block)		/* For 10-byte and 16-byte SCSI R/W commands, transfer		 * length 0 means transfer 0 block of data.		 * However, for ATA R/W commands, sector count 0 means		 * 256 or 65536 sectors, not 0 sectors as in SCSI.		 *		 * WARNING: one or two older ATA drives treat 0 as 0...		 */		goto nothing_to_do;	qc->flags |= ATA_QCFLAG_IO;	qc->nbytes = n_block * ATA_SECT_SIZE;	rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags,			     qc->tag);	if (likely(rc == 0))		return 0;	if (rc == -ERANGE)		goto out_of_range;	/* treat all other errors as -EINVAL, fall through */invalid_fld:	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);	/* "Invalid field in cbd" */	return 1;out_of_range:	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x21, 0x0);	/* "Logical Block Address out of range" */	return 1;nothing_to_do:	scmd->result = SAM_STAT_GOOD;	return 1;}static void ata_scsi_qc_complete(struct ata_queued_cmd *qc){	struct ata_port *ap = qc->ap;	struct scsi_cmnd *cmd = qc->scsicmd;	u8 *cdb = cmd->cmnd;	int need_sense = (qc->err_mask != 0);	/* For ATA pass thru (SAT) commands, generate a sense block if	 * user mandated it or if there's an error.  Note that if we	 * generate because the user forced us to, a check condition	 * is generated and the ATA register values are returned	 * whether the command completed successfully or not. If there	 * was no error, SK, ASC and ASCQ will all be zero.	 */	if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&	    ((cdb[2] & 0x20) || need_sense)) {		ata_gen_passthru_sense(qc);	} else {		if (!need_sense) {			cmd->result = SAM_STAT_GOOD;		} else {			/* TODO: decide which descriptor format to use			 * for 48b LBA devices and call that here			 * instead of the fixed desc, which is only			 * good for smaller LBA (and maybe CHS?)			 * devices.			 */			ata_gen_ata_sense(qc);		}	}	/* XXX: track spindown state for spindown skipping and warning */	if (unlikely(qc->tf.command == ATA_CMD_STANDBY ||		     qc->tf.command == ATA_CMD_STANDBYNOW1))		qc->dev->flags |= ATA_DFLAG_SPUNDOWN;	else if (likely(system_state != SYSTEM_HALT &&			system_state != SYSTEM_POWER_OFF))		qc->dev->flags &= ~ATA_DFLAG_SPUNDOWN;	if (need_sense && !ap->ops->error_handler)		ata_dump_status(ap->print_id, &qc->result_tf);	qc->scsidone(cmd);	ata_qc_free(qc);}/** *	ata_scsi_translate - Translate then issue SCSI command to ATA device *	@dev: ATA device to which the command is addressed *	@cmd: SCSI command to execute *	@done: SCSI command completion function *	@xlat_func: Actor which translates @cmd to an ATA taskfile * *	Our ->queuecommand() function has decided that the SCSI *	command issued can be directly translated into an ATA *	command, rather than handled internally. * *	This function sets up an ata_queued_cmd structure for the *	SCSI command, and sends that ata_queued_cmd to the hardware. * *	The xlat_func argument (actor) returns 0 if ready to execute *	ATA command, else 1 to finish translation. If 1 is returned *	then cmd->result (and possibly cmd->sense_buffer) are assumed *	to be set reflecting an error condition or clean (early)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -