// SPDX-License-Identifier: GPL-2.0+ /* * Support for emulating SAT (ata pass through) on devices based * on the Cypress USB/ATA bridge supporting ATACB. * * Copyright (c) 2008 Matthieu Castet (castet.matthieu@free.fr)
*/
MODULE_DESCRIPTION("SAT support for Cypress USB/ATA bridges with ATACB");
MODULE_AUTHOR("Matthieu Castet ");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS("USB_STORAGE");
/* * ATACB is a protocol used on cypress usb<->ata bridge to * send raw ATA command over mass storage * There is a ATACB2 protocol that support LBA48 on newer chip. * More info that be found on cy7c68310_8.pdf and cy7c68300c_8.pdf * datasheet from cypress.com.
*/ staticvoid cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
{ unsignedchar save_cmnd[MAX_COMMAND_SIZE];
/* check if we support the command */ if (save_cmnd[1] >> 5) /* MULTIPLE_COUNT */ goto invalid_fld; /* check protocol */ switch ((save_cmnd[1] >> 1) & 0xf) { case 3: /*no DATA */ case 4: /* PIO in */ case 5: /* PIO out */ break; default: goto invalid_fld;
}
/* first build the ATACB command */
srb->cmd_len = 16;
srb->cmnd[0] = 0x24; /* * bVSCBSignature : vendor-specific command * this value can change, but most(all ?) manufacturers * keep the cypress default : 0x24
*/
srb->cmnd[1] = 0x24; /* bVSCBSubCommand : 0x24 for ATACB */
if (srb->cmnd[12] == ATA_CMD_ID_ATA || srb->cmnd[12] == ATA_CMD_ID_ATAPI)
srb->cmnd[2] |= (1<<7); /* set IdentifyPacketDevice for these cmds */
usb_stor_transparent_scsi_command(srb, us);
/* if the device doesn't support ATACB */ if (srb->result == SAM_STAT_CHECK_CONDITION &&
memcmp(srb->sense_buffer, usb_stor_sense_invalidCDB, sizeof(usb_stor_sense_invalidCDB)) == 0) {
usb_stor_dbg(us, "cypress atacb not supported ???\n"); goto end;
}
/* * if ck_cond flags is set, and there wasn't critical error, * build the special sense
*/ if ((srb->result != (DID_ERROR << 16) &&
srb->result != (DID_ABORT << 16)) &&
save_cmnd[2] & 0x20) { struct scsi_eh_save ses; unsignedchar regs[8]; unsignedchar *sb = srb->sense_buffer; unsignedchar *desc = sb + 8; int tmp_result;
/* build the command for reading the ATA registers */
scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sizeof(regs));
/* * we use the same command as before, but we set * the read taskfile bit, for not executing atacb command, * but reading register selected in srb->cmnd[4]
*/
srb->cmd_len = 16;
srb->cmnd[2] = 1;
usb_stor_transparent_scsi_command(srb, us);
memcpy(regs, srb->sense_buffer, sizeof(regs));
tmp_result = srb->result;
scsi_eh_restore_cmnd(srb, &ses); /* we fail to get registers, report invalid command */ if (tmp_result != SAM_STAT_GOOD) goto invalid_fld;
/* build the sense */
memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
/* set sk, asc for a good command */
sb[1] = RECOVERED_ERROR;
sb[2] = 0; /* ATA PASS THROUGH INFORMATION AVAILABLE */
sb[3] = 0x1D;
/* * XXX we should generate sk, asc, ascq from status and error * regs * (see 11.1 Error translation ATA device error to SCSI error * map, and ata_to_sense_error from libata.)
*/
/* Sense data is current and format is descriptor. */
sb[0] = 0x72;
desc[0] = 0x09; /* ATA_RETURN_DESCRIPTOR */
/* set length of additional sense data */
sb[7] = 14;
desc[1] = 12;
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.