drivers/ata/libata-scsi.c

Source file repositories/reference/linux-study-clean/drivers/ata/libata-scsi.c

File Facts

System
Linux kernel
Corpus path
drivers/ata/libata-scsi.c
Extension
.c
Size
128445 bytes
Lines
5072
Domain
Driver Families
Bucket
drivers/ata
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (dev->flags & ATA_DFLAG_NO_UNLOAD) {
			rc = -EOPNOTSUPP;
			goto unlock;
		}

		dev->unpark_deadline = ata_deadline(jiffies, input);
		dev->link->eh_info.dev_action[dev->devno] |= ATA_EH_PARK;
		ata_port_schedule_eh(ap);
		complete(&ap->park_req_pending);
	} else {
		switch (input) {
		case -1:
			dev->flags &= ~ATA_DFLAG_NO_UNLOAD;
			break;
		case -2:
			dev->flags |= ATA_DFLAG_NO_UNLOAD;
			break;
		}
	}
unlock:
	spin_unlock_irqrestore(ap->lock, flags);

	return rc ? rc : len;
}
DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR,
	    ata_scsi_park_show, ata_scsi_park_store);
EXPORT_SYMBOL_GPL(dev_attr_unload_heads);

bool ata_scsi_sense_is_valid(u8 sk, u8 asc, u8 ascq)
{
	/*
	 * If sk == NO_SENSE, and asc + ascq == NO ADDITIONAL SENSE INFORMATION,
	 * then there is no sense data to add.
	 */
	if (sk == 0 && asc == 0 && ascq == 0)
		return false;

	/* If sk > COMPLETED, sense data is bogus. */
	if (sk > COMPLETED)
		return false;

	return true;
}

void ata_scsi_set_sense(struct ata_device *dev, struct scsi_cmnd *cmd,
			u8 sk, u8 asc, u8 ascq)
{
	bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE);

	scsi_build_sense(cmd, d_sense, sk, asc, ascq);
}

static void ata_scsi_set_sense_information(struct ata_queued_cmd *qc)
{
	u64 information;

	if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {
		ata_dev_dbg(qc->dev,
			    "missing result TF: can't set INFORMATION sense field\n");
		return;
	}

	information = ata_tf_read_block(&qc->result_tf, qc->dev);
	if (information == U64_MAX)
		return;

	scsi_set_sense_information(qc->scsicmd->sense_buffer,
				   SCSI_SENSE_BUFFERSIZE, information);
}

/**
 *	ata_scsi_set_passthru_sense_fields - Set ATA fields in sense buffer
 *	@qc: ATA PASS-THROUGH command.
 *
 *	Populates "ATA Status Return sense data descriptor" / "Fixed format
 *	sense data" with ATA taskfile fields.
 *
 *	LOCKING:
 *	None.
 */
static void ata_scsi_set_passthru_sense_fields(struct ata_queued_cmd *qc)
{
	struct ata_device *dev = qc->dev;
	struct scsi_cmnd *cmd = qc->scsicmd;
	struct ata_taskfile *tf = &qc->result_tf;
	unsigned char *sb = cmd->sense_buffer;

	if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {
		ata_dev_dbg(dev,
			    "missing result TF: can't set ATA PT sense fields\n");

Annotation

Implementation Notes