18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * libata-scsi.c - helper library for ATA 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2003-2004 Red Hat, Inc. All rights reserved. 68c2ecf20Sopenharmony_ci * Copyright 2003-2004 Jeff Garzik 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * libata documentation is available via 'make {ps|pdf}docs', 98c2ecf20Sopenharmony_ci * as Documentation/driver-api/libata.rst 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Hardware documentation available from 128c2ecf20Sopenharmony_ci * - http://www.t10.org/ 138c2ecf20Sopenharmony_ci * - http://www.t13.org/ 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/compat.h> 178c2ecf20Sopenharmony_ci#include <linux/slab.h> 188c2ecf20Sopenharmony_ci#include <linux/kernel.h> 198c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 208c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 218c2ecf20Sopenharmony_ci#include <linux/export.h> 228c2ecf20Sopenharmony_ci#include <scsi/scsi.h> 238c2ecf20Sopenharmony_ci#include <scsi/scsi_host.h> 248c2ecf20Sopenharmony_ci#include <scsi/scsi_cmnd.h> 258c2ecf20Sopenharmony_ci#include <scsi/scsi_eh.h> 268c2ecf20Sopenharmony_ci#include <scsi/scsi_device.h> 278c2ecf20Sopenharmony_ci#include <scsi/scsi_tcq.h> 288c2ecf20Sopenharmony_ci#include <scsi/scsi_transport.h> 298c2ecf20Sopenharmony_ci#include <linux/libata.h> 308c2ecf20Sopenharmony_ci#include <linux/hdreg.h> 318c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 328c2ecf20Sopenharmony_ci#include <linux/suspend.h> 338c2ecf20Sopenharmony_ci#include <asm/unaligned.h> 348c2ecf20Sopenharmony_ci#include <linux/ioprio.h> 358c2ecf20Sopenharmony_ci#include <linux/of.h> 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include "libata.h" 388c2ecf20Sopenharmony_ci#include "libata-transport.h" 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define ATA_SCSI_RBUF_SIZE 576 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(ata_scsi_rbuf_lock); 438c2ecf20Sopenharmony_cistatic u8 ata_scsi_rbuf[ATA_SCSI_RBUF_SIZE]; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_citypedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic struct ata_device *__ata_scsi_find_dev(struct ata_port *ap, 488c2ecf20Sopenharmony_ci const struct scsi_device *scsidev); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#define RW_RECOVERY_MPAGE 0x1 518c2ecf20Sopenharmony_ci#define RW_RECOVERY_MPAGE_LEN 12 528c2ecf20Sopenharmony_ci#define CACHE_MPAGE 0x8 538c2ecf20Sopenharmony_ci#define CACHE_MPAGE_LEN 20 548c2ecf20Sopenharmony_ci#define CONTROL_MPAGE 0xa 558c2ecf20Sopenharmony_ci#define CONTROL_MPAGE_LEN 12 568c2ecf20Sopenharmony_ci#define ALL_MPAGES 0x3f 578c2ecf20Sopenharmony_ci#define ALL_SUB_MPAGES 0xff 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic const u8 def_rw_recovery_mpage[RW_RECOVERY_MPAGE_LEN] = { 618c2ecf20Sopenharmony_ci RW_RECOVERY_MPAGE, 628c2ecf20Sopenharmony_ci RW_RECOVERY_MPAGE_LEN - 2, 638c2ecf20Sopenharmony_ci (1 << 7), /* AWRE */ 648c2ecf20Sopenharmony_ci 0, /* read retry count */ 658c2ecf20Sopenharmony_ci 0, 0, 0, 0, 668c2ecf20Sopenharmony_ci 0, /* write retry count */ 678c2ecf20Sopenharmony_ci 0, 0, 0 688c2ecf20Sopenharmony_ci}; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic const u8 def_cache_mpage[CACHE_MPAGE_LEN] = { 718c2ecf20Sopenharmony_ci CACHE_MPAGE, 728c2ecf20Sopenharmony_ci CACHE_MPAGE_LEN - 2, 738c2ecf20Sopenharmony_ci 0, /* contains WCE, needs to be 0 for logic */ 748c2ecf20Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 758c2ecf20Sopenharmony_ci 0, /* contains DRA, needs to be 0 for logic */ 768c2ecf20Sopenharmony_ci 0, 0, 0, 0, 0, 0, 0 778c2ecf20Sopenharmony_ci}; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic const u8 def_control_mpage[CONTROL_MPAGE_LEN] = { 808c2ecf20Sopenharmony_ci CONTROL_MPAGE, 818c2ecf20Sopenharmony_ci CONTROL_MPAGE_LEN - 2, 828c2ecf20Sopenharmony_ci 2, /* DSENSE=0, GLTSD=1 */ 838c2ecf20Sopenharmony_ci 0, /* [QAM+QERR may be 1, see 05-359r1] */ 848c2ecf20Sopenharmony_ci 0, 0, 0, 0, 0xff, 0xff, 858c2ecf20Sopenharmony_ci 0, 30 /* extended self test time, see 05-359r1 */ 868c2ecf20Sopenharmony_ci}; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cistatic ssize_t ata_scsi_park_show(struct device *device, 898c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci struct scsi_device *sdev = to_scsi_device(device); 928c2ecf20Sopenharmony_ci struct ata_port *ap; 938c2ecf20Sopenharmony_ci struct ata_link *link; 948c2ecf20Sopenharmony_ci struct ata_device *dev; 958c2ecf20Sopenharmony_ci unsigned long now; 968c2ecf20Sopenharmony_ci unsigned int msecs; 978c2ecf20Sopenharmony_ci int rc = 0; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci ap = ata_shost_to_port(sdev->host); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci spin_lock_irq(ap->lock); 1028c2ecf20Sopenharmony_ci dev = ata_scsi_find_dev(ap, sdev); 1038c2ecf20Sopenharmony_ci if (!dev) { 1048c2ecf20Sopenharmony_ci rc = -ENODEV; 1058c2ecf20Sopenharmony_ci goto unlock; 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci if (dev->flags & ATA_DFLAG_NO_UNLOAD) { 1088c2ecf20Sopenharmony_ci rc = -EOPNOTSUPP; 1098c2ecf20Sopenharmony_ci goto unlock; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci link = dev->link; 1138c2ecf20Sopenharmony_ci now = jiffies; 1148c2ecf20Sopenharmony_ci if (ap->pflags & ATA_PFLAG_EH_IN_PROGRESS && 1158c2ecf20Sopenharmony_ci link->eh_context.unloaded_mask & (1 << dev->devno) && 1168c2ecf20Sopenharmony_ci time_after(dev->unpark_deadline, now)) 1178c2ecf20Sopenharmony_ci msecs = jiffies_to_msecs(dev->unpark_deadline - now); 1188c2ecf20Sopenharmony_ci else 1198c2ecf20Sopenharmony_ci msecs = 0; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ciunlock: 1228c2ecf20Sopenharmony_ci spin_unlock_irq(ap->lock); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci return rc ? rc : snprintf(buf, 20, "%u\n", msecs); 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic ssize_t ata_scsi_park_store(struct device *device, 1288c2ecf20Sopenharmony_ci struct device_attribute *attr, 1298c2ecf20Sopenharmony_ci const char *buf, size_t len) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci struct scsi_device *sdev = to_scsi_device(device); 1328c2ecf20Sopenharmony_ci struct ata_port *ap; 1338c2ecf20Sopenharmony_ci struct ata_device *dev; 1348c2ecf20Sopenharmony_ci long int input; 1358c2ecf20Sopenharmony_ci unsigned long flags; 1368c2ecf20Sopenharmony_ci int rc; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci rc = kstrtol(buf, 10, &input); 1398c2ecf20Sopenharmony_ci if (rc) 1408c2ecf20Sopenharmony_ci return rc; 1418c2ecf20Sopenharmony_ci if (input < -2) 1428c2ecf20Sopenharmony_ci return -EINVAL; 1438c2ecf20Sopenharmony_ci if (input > ATA_TMOUT_MAX_PARK) { 1448c2ecf20Sopenharmony_ci rc = -EOVERFLOW; 1458c2ecf20Sopenharmony_ci input = ATA_TMOUT_MAX_PARK; 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci ap = ata_shost_to_port(sdev->host); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci spin_lock_irqsave(ap->lock, flags); 1518c2ecf20Sopenharmony_ci dev = ata_scsi_find_dev(ap, sdev); 1528c2ecf20Sopenharmony_ci if (unlikely(!dev)) { 1538c2ecf20Sopenharmony_ci rc = -ENODEV; 1548c2ecf20Sopenharmony_ci goto unlock; 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci if (dev->class != ATA_DEV_ATA && 1578c2ecf20Sopenharmony_ci dev->class != ATA_DEV_ZAC) { 1588c2ecf20Sopenharmony_ci rc = -EOPNOTSUPP; 1598c2ecf20Sopenharmony_ci goto unlock; 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (input >= 0) { 1638c2ecf20Sopenharmony_ci if (dev->flags & ATA_DFLAG_NO_UNLOAD) { 1648c2ecf20Sopenharmony_ci rc = -EOPNOTSUPP; 1658c2ecf20Sopenharmony_ci goto unlock; 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci dev->unpark_deadline = ata_deadline(jiffies, input); 1698c2ecf20Sopenharmony_ci dev->link->eh_info.dev_action[dev->devno] |= ATA_EH_PARK; 1708c2ecf20Sopenharmony_ci ata_port_schedule_eh(ap); 1718c2ecf20Sopenharmony_ci complete(&ap->park_req_pending); 1728c2ecf20Sopenharmony_ci } else { 1738c2ecf20Sopenharmony_ci switch (input) { 1748c2ecf20Sopenharmony_ci case -1: 1758c2ecf20Sopenharmony_ci dev->flags &= ~ATA_DFLAG_NO_UNLOAD; 1768c2ecf20Sopenharmony_ci break; 1778c2ecf20Sopenharmony_ci case -2: 1788c2ecf20Sopenharmony_ci dev->flags |= ATA_DFLAG_NO_UNLOAD; 1798c2ecf20Sopenharmony_ci break; 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ciunlock: 1838c2ecf20Sopenharmony_ci spin_unlock_irqrestore(ap->lock, flags); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci return rc ? rc : len; 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ciDEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR, 1888c2ecf20Sopenharmony_ci ata_scsi_park_show, ata_scsi_park_store); 1898c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dev_attr_unload_heads); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_civoid ata_scsi_set_sense(struct ata_device *dev, struct scsi_cmnd *cmd, 1928c2ecf20Sopenharmony_ci u8 sk, u8 asc, u8 ascq) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci if (!cmd) 1978c2ecf20Sopenharmony_ci return; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci scsi_build_sense_buffer(d_sense, cmd->sense_buffer, sk, asc, ascq); 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_civoid ata_scsi_set_sense_information(struct ata_device *dev, 2058c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd, 2068c2ecf20Sopenharmony_ci const struct ata_taskfile *tf) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci u64 information; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci if (!cmd) 2118c2ecf20Sopenharmony_ci return; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci information = ata_tf_read_block(tf, dev); 2148c2ecf20Sopenharmony_ci if (information == U64_MAX) 2158c2ecf20Sopenharmony_ci return; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci scsi_set_sense_information(cmd->sense_buffer, 2188c2ecf20Sopenharmony_ci SCSI_SENSE_BUFFERSIZE, information); 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic void ata_scsi_set_invalid_field(struct ata_device *dev, 2228c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd, u16 field, u8 bit) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x24, 0x0); 2258c2ecf20Sopenharmony_ci /* "Invalid field in CDB" */ 2268c2ecf20Sopenharmony_ci scsi_set_sense_field_pointer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, 2278c2ecf20Sopenharmony_ci field, bit, 1); 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic void ata_scsi_set_invalid_parameter(struct ata_device *dev, 2318c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd, u16 field) 2328c2ecf20Sopenharmony_ci{ 2338c2ecf20Sopenharmony_ci /* "Invalid field in parameter list" */ 2348c2ecf20Sopenharmony_ci ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x26, 0x0); 2358c2ecf20Sopenharmony_ci scsi_set_sense_field_pointer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, 2368c2ecf20Sopenharmony_ci field, 0xff, 0); 2378c2ecf20Sopenharmony_ci} 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_cistruct device_attribute *ata_common_sdev_attrs[] = { 2408c2ecf20Sopenharmony_ci &dev_attr_unload_heads, 2418c2ecf20Sopenharmony_ci NULL 2428c2ecf20Sopenharmony_ci}; 2438c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_common_sdev_attrs); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci/** 2468c2ecf20Sopenharmony_ci * ata_std_bios_param - generic bios head/sector/cylinder calculator used by sd. 2478c2ecf20Sopenharmony_ci * @sdev: SCSI device for which BIOS geometry is to be determined 2488c2ecf20Sopenharmony_ci * @bdev: block device associated with @sdev 2498c2ecf20Sopenharmony_ci * @capacity: capacity of SCSI device 2508c2ecf20Sopenharmony_ci * @geom: location to which geometry will be output 2518c2ecf20Sopenharmony_ci * 2528c2ecf20Sopenharmony_ci * Generic bios head/sector/cylinder calculator 2538c2ecf20Sopenharmony_ci * used by sd. Most BIOSes nowadays expect a XXX/255/16 (CHS) 2548c2ecf20Sopenharmony_ci * mapping. Some situations may arise where the disk is not 2558c2ecf20Sopenharmony_ci * bootable if this is not used. 2568c2ecf20Sopenharmony_ci * 2578c2ecf20Sopenharmony_ci * LOCKING: 2588c2ecf20Sopenharmony_ci * Defined by the SCSI layer. We don't really care. 2598c2ecf20Sopenharmony_ci * 2608c2ecf20Sopenharmony_ci * RETURNS: 2618c2ecf20Sopenharmony_ci * Zero. 2628c2ecf20Sopenharmony_ci */ 2638c2ecf20Sopenharmony_ciint ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, 2648c2ecf20Sopenharmony_ci sector_t capacity, int geom[]) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci geom[0] = 255; 2678c2ecf20Sopenharmony_ci geom[1] = 63; 2688c2ecf20Sopenharmony_ci sector_div(capacity, 255*63); 2698c2ecf20Sopenharmony_ci geom[2] = capacity; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci return 0; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_std_bios_param); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci/** 2768c2ecf20Sopenharmony_ci * ata_scsi_unlock_native_capacity - unlock native capacity 2778c2ecf20Sopenharmony_ci * @sdev: SCSI device to adjust device capacity for 2788c2ecf20Sopenharmony_ci * 2798c2ecf20Sopenharmony_ci * This function is called if a partition on @sdev extends beyond 2808c2ecf20Sopenharmony_ci * the end of the device. It requests EH to unlock HPA. 2818c2ecf20Sopenharmony_ci * 2828c2ecf20Sopenharmony_ci * LOCKING: 2838c2ecf20Sopenharmony_ci * Defined by the SCSI layer. Might sleep. 2848c2ecf20Sopenharmony_ci */ 2858c2ecf20Sopenharmony_civoid ata_scsi_unlock_native_capacity(struct scsi_device *sdev) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci struct ata_port *ap = ata_shost_to_port(sdev->host); 2888c2ecf20Sopenharmony_ci struct ata_device *dev; 2898c2ecf20Sopenharmony_ci unsigned long flags; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci spin_lock_irqsave(ap->lock, flags); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci dev = ata_scsi_find_dev(ap, sdev); 2948c2ecf20Sopenharmony_ci if (dev && dev->n_sectors < dev->n_native_sectors) { 2958c2ecf20Sopenharmony_ci dev->flags |= ATA_DFLAG_UNLOCK_HPA; 2968c2ecf20Sopenharmony_ci dev->link->eh_info.action |= ATA_EH_RESET; 2978c2ecf20Sopenharmony_ci ata_port_schedule_eh(ap); 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci spin_unlock_irqrestore(ap->lock, flags); 3018c2ecf20Sopenharmony_ci ata_port_wait_eh(ap); 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_scsi_unlock_native_capacity); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci/** 3068c2ecf20Sopenharmony_ci * ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl 3078c2ecf20Sopenharmony_ci * @ap: target port 3088c2ecf20Sopenharmony_ci * @sdev: SCSI device to get identify data for 3098c2ecf20Sopenharmony_ci * @arg: User buffer area for identify data 3108c2ecf20Sopenharmony_ci * 3118c2ecf20Sopenharmony_ci * LOCKING: 3128c2ecf20Sopenharmony_ci * Defined by the SCSI layer. We don't really care. 3138c2ecf20Sopenharmony_ci * 3148c2ecf20Sopenharmony_ci * RETURNS: 3158c2ecf20Sopenharmony_ci * Zero on success, negative errno on error. 3168c2ecf20Sopenharmony_ci */ 3178c2ecf20Sopenharmony_cistatic int ata_get_identity(struct ata_port *ap, struct scsi_device *sdev, 3188c2ecf20Sopenharmony_ci void __user *arg) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci struct ata_device *dev = ata_scsi_find_dev(ap, sdev); 3218c2ecf20Sopenharmony_ci u16 __user *dst = arg; 3228c2ecf20Sopenharmony_ci char buf[40]; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci if (!dev) 3258c2ecf20Sopenharmony_ci return -ENOMSG; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci if (copy_to_user(dst, dev->id, ATA_ID_WORDS * sizeof(u16))) 3288c2ecf20Sopenharmony_ci return -EFAULT; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci ata_id_string(dev->id, buf, ATA_ID_PROD, ATA_ID_PROD_LEN); 3318c2ecf20Sopenharmony_ci if (copy_to_user(dst + ATA_ID_PROD, buf, ATA_ID_PROD_LEN)) 3328c2ecf20Sopenharmony_ci return -EFAULT; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci ata_id_string(dev->id, buf, ATA_ID_FW_REV, ATA_ID_FW_REV_LEN); 3358c2ecf20Sopenharmony_ci if (copy_to_user(dst + ATA_ID_FW_REV, buf, ATA_ID_FW_REV_LEN)) 3368c2ecf20Sopenharmony_ci return -EFAULT; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci ata_id_string(dev->id, buf, ATA_ID_SERNO, ATA_ID_SERNO_LEN); 3398c2ecf20Sopenharmony_ci if (copy_to_user(dst + ATA_ID_SERNO, buf, ATA_ID_SERNO_LEN)) 3408c2ecf20Sopenharmony_ci return -EFAULT; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci return 0; 3438c2ecf20Sopenharmony_ci} 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci/** 3468c2ecf20Sopenharmony_ci * ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl 3478c2ecf20Sopenharmony_ci * @scsidev: Device to which we are issuing command 3488c2ecf20Sopenharmony_ci * @arg: User provided data for issuing command 3498c2ecf20Sopenharmony_ci * 3508c2ecf20Sopenharmony_ci * LOCKING: 3518c2ecf20Sopenharmony_ci * Defined by the SCSI layer. We don't really care. 3528c2ecf20Sopenharmony_ci * 3538c2ecf20Sopenharmony_ci * RETURNS: 3548c2ecf20Sopenharmony_ci * Zero on success, negative errno on error. 3558c2ecf20Sopenharmony_ci */ 3568c2ecf20Sopenharmony_ciint ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) 3578c2ecf20Sopenharmony_ci{ 3588c2ecf20Sopenharmony_ci int rc = 0; 3598c2ecf20Sopenharmony_ci u8 sensebuf[SCSI_SENSE_BUFFERSIZE]; 3608c2ecf20Sopenharmony_ci u8 scsi_cmd[MAX_COMMAND_SIZE]; 3618c2ecf20Sopenharmony_ci u8 args[4], *argbuf = NULL; 3628c2ecf20Sopenharmony_ci int argsize = 0; 3638c2ecf20Sopenharmony_ci enum dma_data_direction data_dir; 3648c2ecf20Sopenharmony_ci struct scsi_sense_hdr sshdr; 3658c2ecf20Sopenharmony_ci int cmd_result; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci if (arg == NULL) 3688c2ecf20Sopenharmony_ci return -EINVAL; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci if (copy_from_user(args, arg, sizeof(args))) 3718c2ecf20Sopenharmony_ci return -EFAULT; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci memset(sensebuf, 0, sizeof(sensebuf)); 3748c2ecf20Sopenharmony_ci memset(scsi_cmd, 0, sizeof(scsi_cmd)); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci if (args[3]) { 3778c2ecf20Sopenharmony_ci argsize = ATA_SECT_SIZE * args[3]; 3788c2ecf20Sopenharmony_ci argbuf = kmalloc(argsize, GFP_KERNEL); 3798c2ecf20Sopenharmony_ci if (argbuf == NULL) { 3808c2ecf20Sopenharmony_ci rc = -ENOMEM; 3818c2ecf20Sopenharmony_ci goto error; 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci scsi_cmd[1] = (4 << 1); /* PIO Data-in */ 3858c2ecf20Sopenharmony_ci scsi_cmd[2] = 0x0e; /* no off.line or cc, read from dev, 3868c2ecf20Sopenharmony_ci block count in sector count field */ 3878c2ecf20Sopenharmony_ci data_dir = DMA_FROM_DEVICE; 3888c2ecf20Sopenharmony_ci } else { 3898c2ecf20Sopenharmony_ci scsi_cmd[1] = (3 << 1); /* Non-data */ 3908c2ecf20Sopenharmony_ci scsi_cmd[2] = 0x20; /* cc but no off.line or data xfer */ 3918c2ecf20Sopenharmony_ci data_dir = DMA_NONE; 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci scsi_cmd[0] = ATA_16; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci scsi_cmd[4] = args[2]; 3978c2ecf20Sopenharmony_ci if (args[0] == ATA_CMD_SMART) { /* hack -- ide driver does this too */ 3988c2ecf20Sopenharmony_ci scsi_cmd[6] = args[3]; 3998c2ecf20Sopenharmony_ci scsi_cmd[8] = args[1]; 4008c2ecf20Sopenharmony_ci scsi_cmd[10] = ATA_SMART_LBAM_PASS; 4018c2ecf20Sopenharmony_ci scsi_cmd[12] = ATA_SMART_LBAH_PASS; 4028c2ecf20Sopenharmony_ci } else { 4038c2ecf20Sopenharmony_ci scsi_cmd[6] = args[1]; 4048c2ecf20Sopenharmony_ci } 4058c2ecf20Sopenharmony_ci scsi_cmd[14] = args[0]; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci /* Good values for timeout and retries? Values below 4088c2ecf20Sopenharmony_ci from scsi_ioctl_send_command() for default case... */ 4098c2ecf20Sopenharmony_ci cmd_result = scsi_execute(scsidev, scsi_cmd, data_dir, argbuf, argsize, 4108c2ecf20Sopenharmony_ci sensebuf, &sshdr, (10*HZ), 5, 0, 0, NULL); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */ 4138c2ecf20Sopenharmony_ci u8 *desc = sensebuf + 8; 4148c2ecf20Sopenharmony_ci cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */ 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci /* If we set cc then ATA pass-through will cause a 4178c2ecf20Sopenharmony_ci * check condition even if no error. Filter that. */ 4188c2ecf20Sopenharmony_ci if (cmd_result & SAM_STAT_CHECK_CONDITION) { 4198c2ecf20Sopenharmony_ci if (sshdr.sense_key == RECOVERED_ERROR && 4208c2ecf20Sopenharmony_ci sshdr.asc == 0 && sshdr.ascq == 0x1d) 4218c2ecf20Sopenharmony_ci cmd_result &= ~SAM_STAT_CHECK_CONDITION; 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci /* Send userspace a few ATA registers (same as drivers/ide) */ 4258c2ecf20Sopenharmony_ci if (sensebuf[0] == 0x72 && /* format is "descriptor" */ 4268c2ecf20Sopenharmony_ci desc[0] == 0x09) { /* code is "ATA Descriptor" */ 4278c2ecf20Sopenharmony_ci args[0] = desc[13]; /* status */ 4288c2ecf20Sopenharmony_ci args[1] = desc[3]; /* error */ 4298c2ecf20Sopenharmony_ci args[2] = desc[5]; /* sector count (0:7) */ 4308c2ecf20Sopenharmony_ci if (copy_to_user(arg, args, sizeof(args))) 4318c2ecf20Sopenharmony_ci rc = -EFAULT; 4328c2ecf20Sopenharmony_ci } 4338c2ecf20Sopenharmony_ci } 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci if (cmd_result) { 4378c2ecf20Sopenharmony_ci rc = -EIO; 4388c2ecf20Sopenharmony_ci goto error; 4398c2ecf20Sopenharmony_ci } 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci if ((argbuf) 4428c2ecf20Sopenharmony_ci && copy_to_user(arg + sizeof(args), argbuf, argsize)) 4438c2ecf20Sopenharmony_ci rc = -EFAULT; 4448c2ecf20Sopenharmony_cierror: 4458c2ecf20Sopenharmony_ci kfree(argbuf); 4468c2ecf20Sopenharmony_ci return rc; 4478c2ecf20Sopenharmony_ci} 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci/** 4508c2ecf20Sopenharmony_ci * ata_task_ioctl - Handler for HDIO_DRIVE_TASK ioctl 4518c2ecf20Sopenharmony_ci * @scsidev: Device to which we are issuing command 4528c2ecf20Sopenharmony_ci * @arg: User provided data for issuing command 4538c2ecf20Sopenharmony_ci * 4548c2ecf20Sopenharmony_ci * LOCKING: 4558c2ecf20Sopenharmony_ci * Defined by the SCSI layer. We don't really care. 4568c2ecf20Sopenharmony_ci * 4578c2ecf20Sopenharmony_ci * RETURNS: 4588c2ecf20Sopenharmony_ci * Zero on success, negative errno on error. 4598c2ecf20Sopenharmony_ci */ 4608c2ecf20Sopenharmony_ciint ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) 4618c2ecf20Sopenharmony_ci{ 4628c2ecf20Sopenharmony_ci int rc = 0; 4638c2ecf20Sopenharmony_ci u8 sensebuf[SCSI_SENSE_BUFFERSIZE]; 4648c2ecf20Sopenharmony_ci u8 scsi_cmd[MAX_COMMAND_SIZE]; 4658c2ecf20Sopenharmony_ci u8 args[7]; 4668c2ecf20Sopenharmony_ci struct scsi_sense_hdr sshdr; 4678c2ecf20Sopenharmony_ci int cmd_result; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci if (arg == NULL) 4708c2ecf20Sopenharmony_ci return -EINVAL; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci if (copy_from_user(args, arg, sizeof(args))) 4738c2ecf20Sopenharmony_ci return -EFAULT; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci memset(sensebuf, 0, sizeof(sensebuf)); 4768c2ecf20Sopenharmony_ci memset(scsi_cmd, 0, sizeof(scsi_cmd)); 4778c2ecf20Sopenharmony_ci scsi_cmd[0] = ATA_16; 4788c2ecf20Sopenharmony_ci scsi_cmd[1] = (3 << 1); /* Non-data */ 4798c2ecf20Sopenharmony_ci scsi_cmd[2] = 0x20; /* cc but no off.line or data xfer */ 4808c2ecf20Sopenharmony_ci scsi_cmd[4] = args[1]; 4818c2ecf20Sopenharmony_ci scsi_cmd[6] = args[2]; 4828c2ecf20Sopenharmony_ci scsi_cmd[8] = args[3]; 4838c2ecf20Sopenharmony_ci scsi_cmd[10] = args[4]; 4848c2ecf20Sopenharmony_ci scsi_cmd[12] = args[5]; 4858c2ecf20Sopenharmony_ci scsi_cmd[13] = args[6] & 0x4f; 4868c2ecf20Sopenharmony_ci scsi_cmd[14] = args[0]; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci /* Good values for timeout and retries? Values below 4898c2ecf20Sopenharmony_ci from scsi_ioctl_send_command() for default case... */ 4908c2ecf20Sopenharmony_ci cmd_result = scsi_execute(scsidev, scsi_cmd, DMA_NONE, NULL, 0, 4918c2ecf20Sopenharmony_ci sensebuf, &sshdr, (10*HZ), 5, 0, 0, NULL); 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */ 4948c2ecf20Sopenharmony_ci u8 *desc = sensebuf + 8; 4958c2ecf20Sopenharmony_ci cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */ 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci /* If we set cc then ATA pass-through will cause a 4988c2ecf20Sopenharmony_ci * check condition even if no error. Filter that. */ 4998c2ecf20Sopenharmony_ci if (cmd_result & SAM_STAT_CHECK_CONDITION) { 5008c2ecf20Sopenharmony_ci if (sshdr.sense_key == RECOVERED_ERROR && 5018c2ecf20Sopenharmony_ci sshdr.asc == 0 && sshdr.ascq == 0x1d) 5028c2ecf20Sopenharmony_ci cmd_result &= ~SAM_STAT_CHECK_CONDITION; 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci /* Send userspace ATA registers */ 5068c2ecf20Sopenharmony_ci if (sensebuf[0] == 0x72 && /* format is "descriptor" */ 5078c2ecf20Sopenharmony_ci desc[0] == 0x09) {/* code is "ATA Descriptor" */ 5088c2ecf20Sopenharmony_ci args[0] = desc[13]; /* status */ 5098c2ecf20Sopenharmony_ci args[1] = desc[3]; /* error */ 5108c2ecf20Sopenharmony_ci args[2] = desc[5]; /* sector count (0:7) */ 5118c2ecf20Sopenharmony_ci args[3] = desc[7]; /* lbal */ 5128c2ecf20Sopenharmony_ci args[4] = desc[9]; /* lbam */ 5138c2ecf20Sopenharmony_ci args[5] = desc[11]; /* lbah */ 5148c2ecf20Sopenharmony_ci args[6] = desc[12]; /* select */ 5158c2ecf20Sopenharmony_ci if (copy_to_user(arg, args, sizeof(args))) 5168c2ecf20Sopenharmony_ci rc = -EFAULT; 5178c2ecf20Sopenharmony_ci } 5188c2ecf20Sopenharmony_ci } 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci if (cmd_result) { 5218c2ecf20Sopenharmony_ci rc = -EIO; 5228c2ecf20Sopenharmony_ci goto error; 5238c2ecf20Sopenharmony_ci } 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci error: 5268c2ecf20Sopenharmony_ci return rc; 5278c2ecf20Sopenharmony_ci} 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_cistatic int ata_ioc32(struct ata_port *ap) 5308c2ecf20Sopenharmony_ci{ 5318c2ecf20Sopenharmony_ci if (ap->flags & ATA_FLAG_PIO_DMA) 5328c2ecf20Sopenharmony_ci return 1; 5338c2ecf20Sopenharmony_ci if (ap->pflags & ATA_PFLAG_PIO32) 5348c2ecf20Sopenharmony_ci return 1; 5358c2ecf20Sopenharmony_ci return 0; 5368c2ecf20Sopenharmony_ci} 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci/* 5398c2ecf20Sopenharmony_ci * This handles both native and compat commands, so anything added 5408c2ecf20Sopenharmony_ci * here must have a compatible argument, or check in_compat_syscall() 5418c2ecf20Sopenharmony_ci */ 5428c2ecf20Sopenharmony_ciint ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev, 5438c2ecf20Sopenharmony_ci unsigned int cmd, void __user *arg) 5448c2ecf20Sopenharmony_ci{ 5458c2ecf20Sopenharmony_ci unsigned long val; 5468c2ecf20Sopenharmony_ci int rc = -EINVAL; 5478c2ecf20Sopenharmony_ci unsigned long flags; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci switch (cmd) { 5508c2ecf20Sopenharmony_ci case HDIO_GET_32BIT: 5518c2ecf20Sopenharmony_ci spin_lock_irqsave(ap->lock, flags); 5528c2ecf20Sopenharmony_ci val = ata_ioc32(ap); 5538c2ecf20Sopenharmony_ci spin_unlock_irqrestore(ap->lock, flags); 5548c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT 5558c2ecf20Sopenharmony_ci if (in_compat_syscall()) 5568c2ecf20Sopenharmony_ci return put_user(val, (compat_ulong_t __user *)arg); 5578c2ecf20Sopenharmony_ci#endif 5588c2ecf20Sopenharmony_ci return put_user(val, (unsigned long __user *)arg); 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci case HDIO_SET_32BIT: 5618c2ecf20Sopenharmony_ci val = (unsigned long) arg; 5628c2ecf20Sopenharmony_ci rc = 0; 5638c2ecf20Sopenharmony_ci spin_lock_irqsave(ap->lock, flags); 5648c2ecf20Sopenharmony_ci if (ap->pflags & ATA_PFLAG_PIO32CHANGE) { 5658c2ecf20Sopenharmony_ci if (val) 5668c2ecf20Sopenharmony_ci ap->pflags |= ATA_PFLAG_PIO32; 5678c2ecf20Sopenharmony_ci else 5688c2ecf20Sopenharmony_ci ap->pflags &= ~ATA_PFLAG_PIO32; 5698c2ecf20Sopenharmony_ci } else { 5708c2ecf20Sopenharmony_ci if (val != ata_ioc32(ap)) 5718c2ecf20Sopenharmony_ci rc = -EINVAL; 5728c2ecf20Sopenharmony_ci } 5738c2ecf20Sopenharmony_ci spin_unlock_irqrestore(ap->lock, flags); 5748c2ecf20Sopenharmony_ci return rc; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci case HDIO_GET_IDENTITY: 5778c2ecf20Sopenharmony_ci return ata_get_identity(ap, scsidev, arg); 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci case HDIO_DRIVE_CMD: 5808c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) 5818c2ecf20Sopenharmony_ci return -EACCES; 5828c2ecf20Sopenharmony_ci return ata_cmd_ioctl(scsidev, arg); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci case HDIO_DRIVE_TASK: 5858c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) 5868c2ecf20Sopenharmony_ci return -EACCES; 5878c2ecf20Sopenharmony_ci return ata_task_ioctl(scsidev, arg); 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci default: 5908c2ecf20Sopenharmony_ci rc = -ENOTTY; 5918c2ecf20Sopenharmony_ci break; 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci return rc; 5958c2ecf20Sopenharmony_ci} 5968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_sas_scsi_ioctl); 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ciint ata_scsi_ioctl(struct scsi_device *scsidev, unsigned int cmd, 5998c2ecf20Sopenharmony_ci void __user *arg) 6008c2ecf20Sopenharmony_ci{ 6018c2ecf20Sopenharmony_ci return ata_sas_scsi_ioctl(ata_shost_to_port(scsidev->host), 6028c2ecf20Sopenharmony_ci scsidev, cmd, arg); 6038c2ecf20Sopenharmony_ci} 6048c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_scsi_ioctl); 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci/** 6078c2ecf20Sopenharmony_ci * ata_scsi_qc_new - acquire new ata_queued_cmd reference 6088c2ecf20Sopenharmony_ci * @dev: ATA device to which the new command is attached 6098c2ecf20Sopenharmony_ci * @cmd: SCSI command that originated this ATA command 6108c2ecf20Sopenharmony_ci * 6118c2ecf20Sopenharmony_ci * Obtain a reference to an unused ata_queued_cmd structure, 6128c2ecf20Sopenharmony_ci * which is the basic libata structure representing a single 6138c2ecf20Sopenharmony_ci * ATA command sent to the hardware. 6148c2ecf20Sopenharmony_ci * 6158c2ecf20Sopenharmony_ci * If a command was available, fill in the SCSI-specific 6168c2ecf20Sopenharmony_ci * portions of the structure with information on the 6178c2ecf20Sopenharmony_ci * current command. 6188c2ecf20Sopenharmony_ci * 6198c2ecf20Sopenharmony_ci * LOCKING: 6208c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 6218c2ecf20Sopenharmony_ci * 6228c2ecf20Sopenharmony_ci * RETURNS: 6238c2ecf20Sopenharmony_ci * Command allocated, or %NULL if none available. 6248c2ecf20Sopenharmony_ci */ 6258c2ecf20Sopenharmony_cistatic struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, 6268c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd) 6278c2ecf20Sopenharmony_ci{ 6288c2ecf20Sopenharmony_ci struct ata_queued_cmd *qc; 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci qc = ata_qc_new_init(dev, cmd->request->tag); 6318c2ecf20Sopenharmony_ci if (qc) { 6328c2ecf20Sopenharmony_ci qc->scsicmd = cmd; 6338c2ecf20Sopenharmony_ci qc->scsidone = cmd->scsi_done; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci qc->sg = scsi_sglist(cmd); 6368c2ecf20Sopenharmony_ci qc->n_elem = scsi_sg_count(cmd); 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci if (cmd->request->rq_flags & RQF_QUIET) 6398c2ecf20Sopenharmony_ci qc->flags |= ATA_QCFLAG_QUIET; 6408c2ecf20Sopenharmony_ci } else { 6418c2ecf20Sopenharmony_ci cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1); 6428c2ecf20Sopenharmony_ci cmd->scsi_done(cmd); 6438c2ecf20Sopenharmony_ci } 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci return qc; 6468c2ecf20Sopenharmony_ci} 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_cistatic void ata_qc_set_pc_nbytes(struct ata_queued_cmd *qc) 6498c2ecf20Sopenharmony_ci{ 6508c2ecf20Sopenharmony_ci struct scsi_cmnd *scmd = qc->scsicmd; 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci qc->extrabytes = scmd->extra_len; 6538c2ecf20Sopenharmony_ci qc->nbytes = scsi_bufflen(scmd) + qc->extrabytes; 6548c2ecf20Sopenharmony_ci} 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci/** 6578c2ecf20Sopenharmony_ci * ata_dump_status - user friendly display of error info 6588c2ecf20Sopenharmony_ci * @id: id of the port in question 6598c2ecf20Sopenharmony_ci * @tf: ptr to filled out taskfile 6608c2ecf20Sopenharmony_ci * 6618c2ecf20Sopenharmony_ci * Decode and dump the ATA error/status registers for the user so 6628c2ecf20Sopenharmony_ci * that they have some idea what really happened at the non 6638c2ecf20Sopenharmony_ci * make-believe layer. 6648c2ecf20Sopenharmony_ci * 6658c2ecf20Sopenharmony_ci * LOCKING: 6668c2ecf20Sopenharmony_ci * inherited from caller 6678c2ecf20Sopenharmony_ci */ 6688c2ecf20Sopenharmony_cistatic void ata_dump_status(unsigned id, struct ata_taskfile *tf) 6698c2ecf20Sopenharmony_ci{ 6708c2ecf20Sopenharmony_ci u8 stat = tf->command, err = tf->feature; 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci pr_warn("ata%u: status=0x%02x { ", id, stat); 6738c2ecf20Sopenharmony_ci if (stat & ATA_BUSY) { 6748c2ecf20Sopenharmony_ci pr_cont("Busy }\n"); /* Data is not valid in this case */ 6758c2ecf20Sopenharmony_ci } else { 6768c2ecf20Sopenharmony_ci if (stat & ATA_DRDY) pr_cont("DriveReady "); 6778c2ecf20Sopenharmony_ci if (stat & ATA_DF) pr_cont("DeviceFault "); 6788c2ecf20Sopenharmony_ci if (stat & ATA_DSC) pr_cont("SeekComplete "); 6798c2ecf20Sopenharmony_ci if (stat & ATA_DRQ) pr_cont("DataRequest "); 6808c2ecf20Sopenharmony_ci if (stat & ATA_CORR) pr_cont("CorrectedError "); 6818c2ecf20Sopenharmony_ci if (stat & ATA_SENSE) pr_cont("Sense "); 6828c2ecf20Sopenharmony_ci if (stat & ATA_ERR) pr_cont("Error "); 6838c2ecf20Sopenharmony_ci pr_cont("}\n"); 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci if (err) { 6868c2ecf20Sopenharmony_ci pr_warn("ata%u: error=0x%02x { ", id, err); 6878c2ecf20Sopenharmony_ci if (err & ATA_ABORTED) pr_cont("DriveStatusError "); 6888c2ecf20Sopenharmony_ci if (err & ATA_ICRC) { 6898c2ecf20Sopenharmony_ci if (err & ATA_ABORTED) 6908c2ecf20Sopenharmony_ci pr_cont("BadCRC "); 6918c2ecf20Sopenharmony_ci else pr_cont("Sector "); 6928c2ecf20Sopenharmony_ci } 6938c2ecf20Sopenharmony_ci if (err & ATA_UNC) pr_cont("UncorrectableError "); 6948c2ecf20Sopenharmony_ci if (err & ATA_IDNF) pr_cont("SectorIdNotFound "); 6958c2ecf20Sopenharmony_ci if (err & ATA_TRK0NF) pr_cont("TrackZeroNotFound "); 6968c2ecf20Sopenharmony_ci if (err & ATA_AMNF) pr_cont("AddrMarkNotFound "); 6978c2ecf20Sopenharmony_ci pr_cont("}\n"); 6988c2ecf20Sopenharmony_ci } 6998c2ecf20Sopenharmony_ci } 7008c2ecf20Sopenharmony_ci} 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci/** 7038c2ecf20Sopenharmony_ci * ata_to_sense_error - convert ATA error to SCSI error 7048c2ecf20Sopenharmony_ci * @id: ATA device number 7058c2ecf20Sopenharmony_ci * @drv_stat: value contained in ATA status register 7068c2ecf20Sopenharmony_ci * @drv_err: value contained in ATA error register 7078c2ecf20Sopenharmony_ci * @sk: the sense key we'll fill out 7088c2ecf20Sopenharmony_ci * @asc: the additional sense code we'll fill out 7098c2ecf20Sopenharmony_ci * @ascq: the additional sense code qualifier we'll fill out 7108c2ecf20Sopenharmony_ci * @verbose: be verbose 7118c2ecf20Sopenharmony_ci * 7128c2ecf20Sopenharmony_ci * Converts an ATA error into a SCSI error. Fill out pointers to 7138c2ecf20Sopenharmony_ci * SK, ASC, and ASCQ bytes for later use in fixed or descriptor 7148c2ecf20Sopenharmony_ci * format sense blocks. 7158c2ecf20Sopenharmony_ci * 7168c2ecf20Sopenharmony_ci * LOCKING: 7178c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 7188c2ecf20Sopenharmony_ci */ 7198c2ecf20Sopenharmony_cistatic void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, 7208c2ecf20Sopenharmony_ci u8 *asc, u8 *ascq, int verbose) 7218c2ecf20Sopenharmony_ci{ 7228c2ecf20Sopenharmony_ci int i; 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci /* Based on the 3ware driver translation table */ 7258c2ecf20Sopenharmony_ci static const unsigned char sense_table[][4] = { 7268c2ecf20Sopenharmony_ci /* BBD|ECC|ID|MAR */ 7278c2ecf20Sopenharmony_ci {0xd1, ABORTED_COMMAND, 0x00, 0x00}, 7288c2ecf20Sopenharmony_ci // Device busy Aborted command 7298c2ecf20Sopenharmony_ci /* BBD|ECC|ID */ 7308c2ecf20Sopenharmony_ci {0xd0, ABORTED_COMMAND, 0x00, 0x00}, 7318c2ecf20Sopenharmony_ci // Device busy Aborted command 7328c2ecf20Sopenharmony_ci /* ECC|MC|MARK */ 7338c2ecf20Sopenharmony_ci {0x61, HARDWARE_ERROR, 0x00, 0x00}, 7348c2ecf20Sopenharmony_ci // Device fault Hardware error 7358c2ecf20Sopenharmony_ci /* ICRC|ABRT */ /* NB: ICRC & !ABRT is BBD */ 7368c2ecf20Sopenharmony_ci {0x84, ABORTED_COMMAND, 0x47, 0x00}, 7378c2ecf20Sopenharmony_ci // Data CRC error SCSI parity error 7388c2ecf20Sopenharmony_ci /* MC|ID|ABRT|TRK0|MARK */ 7398c2ecf20Sopenharmony_ci {0x37, NOT_READY, 0x04, 0x00}, 7408c2ecf20Sopenharmony_ci // Unit offline Not ready 7418c2ecf20Sopenharmony_ci /* MCR|MARK */ 7428c2ecf20Sopenharmony_ci {0x09, NOT_READY, 0x04, 0x00}, 7438c2ecf20Sopenharmony_ci // Unrecovered disk error Not ready 7448c2ecf20Sopenharmony_ci /* Bad address mark */ 7458c2ecf20Sopenharmony_ci {0x01, MEDIUM_ERROR, 0x13, 0x00}, 7468c2ecf20Sopenharmony_ci // Address mark not found for data field 7478c2ecf20Sopenharmony_ci /* TRK0 - Track 0 not found */ 7488c2ecf20Sopenharmony_ci {0x02, HARDWARE_ERROR, 0x00, 0x00}, 7498c2ecf20Sopenharmony_ci // Hardware error 7508c2ecf20Sopenharmony_ci /* Abort: 0x04 is not translated here, see below */ 7518c2ecf20Sopenharmony_ci /* Media change request */ 7528c2ecf20Sopenharmony_ci {0x08, NOT_READY, 0x04, 0x00}, 7538c2ecf20Sopenharmony_ci // FIXME: faking offline 7548c2ecf20Sopenharmony_ci /* SRV/IDNF - ID not found */ 7558c2ecf20Sopenharmony_ci {0x10, ILLEGAL_REQUEST, 0x21, 0x00}, 7568c2ecf20Sopenharmony_ci // Logical address out of range 7578c2ecf20Sopenharmony_ci /* MC - Media Changed */ 7588c2ecf20Sopenharmony_ci {0x20, UNIT_ATTENTION, 0x28, 0x00}, 7598c2ecf20Sopenharmony_ci // Not ready to ready change, medium may have changed 7608c2ecf20Sopenharmony_ci /* ECC - Uncorrectable ECC error */ 7618c2ecf20Sopenharmony_ci {0x40, MEDIUM_ERROR, 0x11, 0x04}, 7628c2ecf20Sopenharmony_ci // Unrecovered read error 7638c2ecf20Sopenharmony_ci /* BBD - block marked bad */ 7648c2ecf20Sopenharmony_ci {0x80, MEDIUM_ERROR, 0x11, 0x04}, 7658c2ecf20Sopenharmony_ci // Block marked bad Medium error, unrecovered read error 7668c2ecf20Sopenharmony_ci {0xFF, 0xFF, 0xFF, 0xFF}, // END mark 7678c2ecf20Sopenharmony_ci }; 7688c2ecf20Sopenharmony_ci static const unsigned char stat_table[][4] = { 7698c2ecf20Sopenharmony_ci /* Must be first because BUSY means no other bits valid */ 7708c2ecf20Sopenharmony_ci {0x80, ABORTED_COMMAND, 0x47, 0x00}, 7718c2ecf20Sopenharmony_ci // Busy, fake parity for now 7728c2ecf20Sopenharmony_ci {0x40, ILLEGAL_REQUEST, 0x21, 0x04}, 7738c2ecf20Sopenharmony_ci // Device ready, unaligned write command 7748c2ecf20Sopenharmony_ci {0x20, HARDWARE_ERROR, 0x44, 0x00}, 7758c2ecf20Sopenharmony_ci // Device fault, internal target failure 7768c2ecf20Sopenharmony_ci {0x08, ABORTED_COMMAND, 0x47, 0x00}, 7778c2ecf20Sopenharmony_ci // Timed out in xfer, fake parity for now 7788c2ecf20Sopenharmony_ci {0x04, RECOVERED_ERROR, 0x11, 0x00}, 7798c2ecf20Sopenharmony_ci // Recovered ECC error Medium error, recovered 7808c2ecf20Sopenharmony_ci {0xFF, 0xFF, 0xFF, 0xFF}, // END mark 7818c2ecf20Sopenharmony_ci }; 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci /* 7848c2ecf20Sopenharmony_ci * Is this an error we can process/parse 7858c2ecf20Sopenharmony_ci */ 7868c2ecf20Sopenharmony_ci if (drv_stat & ATA_BUSY) { 7878c2ecf20Sopenharmony_ci drv_err = 0; /* Ignore the err bits, they're invalid */ 7888c2ecf20Sopenharmony_ci } 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci if (drv_err) { 7918c2ecf20Sopenharmony_ci /* Look for drv_err */ 7928c2ecf20Sopenharmony_ci for (i = 0; sense_table[i][0] != 0xFF; i++) { 7938c2ecf20Sopenharmony_ci /* Look for best matches first */ 7948c2ecf20Sopenharmony_ci if ((sense_table[i][0] & drv_err) == 7958c2ecf20Sopenharmony_ci sense_table[i][0]) { 7968c2ecf20Sopenharmony_ci *sk = sense_table[i][1]; 7978c2ecf20Sopenharmony_ci *asc = sense_table[i][2]; 7988c2ecf20Sopenharmony_ci *ascq = sense_table[i][3]; 7998c2ecf20Sopenharmony_ci goto translate_done; 8008c2ecf20Sopenharmony_ci } 8018c2ecf20Sopenharmony_ci } 8028c2ecf20Sopenharmony_ci } 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci /* 8058c2ecf20Sopenharmony_ci * Fall back to interpreting status bits. Note that if the drv_err 8068c2ecf20Sopenharmony_ci * has only the ABRT bit set, we decode drv_stat. ABRT by itself 8078c2ecf20Sopenharmony_ci * is not descriptive enough. 8088c2ecf20Sopenharmony_ci */ 8098c2ecf20Sopenharmony_ci for (i = 0; stat_table[i][0] != 0xFF; i++) { 8108c2ecf20Sopenharmony_ci if (stat_table[i][0] & drv_stat) { 8118c2ecf20Sopenharmony_ci *sk = stat_table[i][1]; 8128c2ecf20Sopenharmony_ci *asc = stat_table[i][2]; 8138c2ecf20Sopenharmony_ci *ascq = stat_table[i][3]; 8148c2ecf20Sopenharmony_ci goto translate_done; 8158c2ecf20Sopenharmony_ci } 8168c2ecf20Sopenharmony_ci } 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci /* 8198c2ecf20Sopenharmony_ci * We need a sensible error return here, which is tricky, and one 8208c2ecf20Sopenharmony_ci * that won't cause people to do things like return a disk wrongly. 8218c2ecf20Sopenharmony_ci */ 8228c2ecf20Sopenharmony_ci *sk = ABORTED_COMMAND; 8238c2ecf20Sopenharmony_ci *asc = 0x00; 8248c2ecf20Sopenharmony_ci *ascq = 0x00; 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci translate_done: 8278c2ecf20Sopenharmony_ci if (verbose) 8288c2ecf20Sopenharmony_ci pr_err("ata%u: translated ATA stat/err 0x%02x/%02x to SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", 8298c2ecf20Sopenharmony_ci id, drv_stat, drv_err, *sk, *asc, *ascq); 8308c2ecf20Sopenharmony_ci return; 8318c2ecf20Sopenharmony_ci} 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci/* 8348c2ecf20Sopenharmony_ci * ata_gen_passthru_sense - Generate check condition sense block. 8358c2ecf20Sopenharmony_ci * @qc: Command that completed. 8368c2ecf20Sopenharmony_ci * 8378c2ecf20Sopenharmony_ci * This function is specific to the ATA descriptor format sense 8388c2ecf20Sopenharmony_ci * block specified for the ATA pass through commands. Regardless 8398c2ecf20Sopenharmony_ci * of whether the command errored or not, return a sense 8408c2ecf20Sopenharmony_ci * block. Copy all controller registers into the sense 8418c2ecf20Sopenharmony_ci * block. If there was no error, we get the request from an ATA 8428c2ecf20Sopenharmony_ci * passthrough command, so we use the following sense data: 8438c2ecf20Sopenharmony_ci * sk = RECOVERED ERROR 8448c2ecf20Sopenharmony_ci * asc,ascq = ATA PASS-THROUGH INFORMATION AVAILABLE 8458c2ecf20Sopenharmony_ci * 8468c2ecf20Sopenharmony_ci * 8478c2ecf20Sopenharmony_ci * LOCKING: 8488c2ecf20Sopenharmony_ci * None. 8498c2ecf20Sopenharmony_ci */ 8508c2ecf20Sopenharmony_cistatic void ata_gen_passthru_sense(struct ata_queued_cmd *qc) 8518c2ecf20Sopenharmony_ci{ 8528c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = qc->scsicmd; 8538c2ecf20Sopenharmony_ci struct ata_taskfile *tf = &qc->result_tf; 8548c2ecf20Sopenharmony_ci unsigned char *sb = cmd->sense_buffer; 8558c2ecf20Sopenharmony_ci unsigned char *desc = sb + 8; 8568c2ecf20Sopenharmony_ci int verbose = qc->ap->ops->error_handler == NULL; 8578c2ecf20Sopenharmony_ci u8 sense_key, asc, ascq; 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci memset(sb, 0, SCSI_SENSE_BUFFERSIZE); 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci /* 8648c2ecf20Sopenharmony_ci * Use ata_to_sense_error() to map status register bits 8658c2ecf20Sopenharmony_ci * onto sense key, asc & ascq. 8668c2ecf20Sopenharmony_ci */ 8678c2ecf20Sopenharmony_ci if (qc->err_mask || 8688c2ecf20Sopenharmony_ci tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { 8698c2ecf20Sopenharmony_ci ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature, 8708c2ecf20Sopenharmony_ci &sense_key, &asc, &ascq, verbose); 8718c2ecf20Sopenharmony_ci ata_scsi_set_sense(qc->dev, cmd, sense_key, asc, ascq); 8728c2ecf20Sopenharmony_ci } else { 8738c2ecf20Sopenharmony_ci /* 8748c2ecf20Sopenharmony_ci * ATA PASS-THROUGH INFORMATION AVAILABLE 8758c2ecf20Sopenharmony_ci * Always in descriptor format sense. 8768c2ecf20Sopenharmony_ci */ 8778c2ecf20Sopenharmony_ci scsi_build_sense_buffer(1, cmd->sense_buffer, 8788c2ecf20Sopenharmony_ci RECOVERED_ERROR, 0, 0x1D); 8798c2ecf20Sopenharmony_ci } 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci if ((cmd->sense_buffer[0] & 0x7f) >= 0x72) { 8828c2ecf20Sopenharmony_ci u8 len; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci /* descriptor format */ 8858c2ecf20Sopenharmony_ci len = sb[7]; 8868c2ecf20Sopenharmony_ci desc = (char *)scsi_sense_desc_find(sb, len + 8, 9); 8878c2ecf20Sopenharmony_ci if (!desc) { 8888c2ecf20Sopenharmony_ci if (SCSI_SENSE_BUFFERSIZE < len + 14) 8898c2ecf20Sopenharmony_ci return; 8908c2ecf20Sopenharmony_ci sb[7] = len + 14; 8918c2ecf20Sopenharmony_ci desc = sb + 8 + len; 8928c2ecf20Sopenharmony_ci } 8938c2ecf20Sopenharmony_ci desc[0] = 9; 8948c2ecf20Sopenharmony_ci desc[1] = 12; 8958c2ecf20Sopenharmony_ci /* 8968c2ecf20Sopenharmony_ci * Copy registers into sense buffer. 8978c2ecf20Sopenharmony_ci */ 8988c2ecf20Sopenharmony_ci desc[2] = 0x00; 8998c2ecf20Sopenharmony_ci desc[3] = tf->feature; /* == error reg */ 9008c2ecf20Sopenharmony_ci desc[5] = tf->nsect; 9018c2ecf20Sopenharmony_ci desc[7] = tf->lbal; 9028c2ecf20Sopenharmony_ci desc[9] = tf->lbam; 9038c2ecf20Sopenharmony_ci desc[11] = tf->lbah; 9048c2ecf20Sopenharmony_ci desc[12] = tf->device; 9058c2ecf20Sopenharmony_ci desc[13] = tf->command; /* == status reg */ 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci /* 9088c2ecf20Sopenharmony_ci * Fill in Extend bit, and the high order bytes 9098c2ecf20Sopenharmony_ci * if applicable. 9108c2ecf20Sopenharmony_ci */ 9118c2ecf20Sopenharmony_ci if (tf->flags & ATA_TFLAG_LBA48) { 9128c2ecf20Sopenharmony_ci desc[2] |= 0x01; 9138c2ecf20Sopenharmony_ci desc[4] = tf->hob_nsect; 9148c2ecf20Sopenharmony_ci desc[6] = tf->hob_lbal; 9158c2ecf20Sopenharmony_ci desc[8] = tf->hob_lbam; 9168c2ecf20Sopenharmony_ci desc[10] = tf->hob_lbah; 9178c2ecf20Sopenharmony_ci } 9188c2ecf20Sopenharmony_ci } else { 9198c2ecf20Sopenharmony_ci /* Fixed sense format */ 9208c2ecf20Sopenharmony_ci desc[0] = tf->feature; 9218c2ecf20Sopenharmony_ci desc[1] = tf->command; /* status */ 9228c2ecf20Sopenharmony_ci desc[2] = tf->device; 9238c2ecf20Sopenharmony_ci desc[3] = tf->nsect; 9248c2ecf20Sopenharmony_ci desc[7] = 0; 9258c2ecf20Sopenharmony_ci if (tf->flags & ATA_TFLAG_LBA48) { 9268c2ecf20Sopenharmony_ci desc[8] |= 0x80; 9278c2ecf20Sopenharmony_ci if (tf->hob_nsect) 9288c2ecf20Sopenharmony_ci desc[8] |= 0x40; 9298c2ecf20Sopenharmony_ci if (tf->hob_lbal || tf->hob_lbam || tf->hob_lbah) 9308c2ecf20Sopenharmony_ci desc[8] |= 0x20; 9318c2ecf20Sopenharmony_ci } 9328c2ecf20Sopenharmony_ci desc[9] = tf->lbal; 9338c2ecf20Sopenharmony_ci desc[10] = tf->lbam; 9348c2ecf20Sopenharmony_ci desc[11] = tf->lbah; 9358c2ecf20Sopenharmony_ci } 9368c2ecf20Sopenharmony_ci} 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci/** 9398c2ecf20Sopenharmony_ci * ata_gen_ata_sense - generate a SCSI fixed sense block 9408c2ecf20Sopenharmony_ci * @qc: Command that we are erroring out 9418c2ecf20Sopenharmony_ci * 9428c2ecf20Sopenharmony_ci * Generate sense block for a failed ATA command @qc. Descriptor 9438c2ecf20Sopenharmony_ci * format is used to accommodate LBA48 block address. 9448c2ecf20Sopenharmony_ci * 9458c2ecf20Sopenharmony_ci * LOCKING: 9468c2ecf20Sopenharmony_ci * None. 9478c2ecf20Sopenharmony_ci */ 9488c2ecf20Sopenharmony_cistatic void ata_gen_ata_sense(struct ata_queued_cmd *qc) 9498c2ecf20Sopenharmony_ci{ 9508c2ecf20Sopenharmony_ci struct ata_device *dev = qc->dev; 9518c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = qc->scsicmd; 9528c2ecf20Sopenharmony_ci struct ata_taskfile *tf = &qc->result_tf; 9538c2ecf20Sopenharmony_ci unsigned char *sb = cmd->sense_buffer; 9548c2ecf20Sopenharmony_ci int verbose = qc->ap->ops->error_handler == NULL; 9558c2ecf20Sopenharmony_ci u64 block; 9568c2ecf20Sopenharmony_ci u8 sense_key, asc, ascq; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci memset(sb, 0, SCSI_SENSE_BUFFERSIZE); 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci if (ata_dev_disabled(dev)) { 9638c2ecf20Sopenharmony_ci /* Device disabled after error recovery */ 9648c2ecf20Sopenharmony_ci /* LOGICAL UNIT NOT READY, HARD RESET REQUIRED */ 9658c2ecf20Sopenharmony_ci ata_scsi_set_sense(dev, cmd, NOT_READY, 0x04, 0x21); 9668c2ecf20Sopenharmony_ci return; 9678c2ecf20Sopenharmony_ci } 9688c2ecf20Sopenharmony_ci /* Use ata_to_sense_error() to map status register bits 9698c2ecf20Sopenharmony_ci * onto sense key, asc & ascq. 9708c2ecf20Sopenharmony_ci */ 9718c2ecf20Sopenharmony_ci if (qc->err_mask || 9728c2ecf20Sopenharmony_ci tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { 9738c2ecf20Sopenharmony_ci ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature, 9748c2ecf20Sopenharmony_ci &sense_key, &asc, &ascq, verbose); 9758c2ecf20Sopenharmony_ci ata_scsi_set_sense(dev, cmd, sense_key, asc, ascq); 9768c2ecf20Sopenharmony_ci } else { 9778c2ecf20Sopenharmony_ci /* Could not decode error */ 9788c2ecf20Sopenharmony_ci ata_dev_warn(dev, "could not decode error status 0x%x err_mask 0x%x\n", 9798c2ecf20Sopenharmony_ci tf->command, qc->err_mask); 9808c2ecf20Sopenharmony_ci ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0); 9818c2ecf20Sopenharmony_ci return; 9828c2ecf20Sopenharmony_ci } 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci block = ata_tf_read_block(&qc->result_tf, dev); 9858c2ecf20Sopenharmony_ci if (block == U64_MAX) 9868c2ecf20Sopenharmony_ci return; 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci scsi_set_sense_information(sb, SCSI_SENSE_BUFFERSIZE, block); 9898c2ecf20Sopenharmony_ci} 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_civoid ata_scsi_sdev_config(struct scsi_device *sdev) 9928c2ecf20Sopenharmony_ci{ 9938c2ecf20Sopenharmony_ci sdev->use_10_for_rw = 1; 9948c2ecf20Sopenharmony_ci sdev->use_10_for_ms = 1; 9958c2ecf20Sopenharmony_ci sdev->no_write_same = 1; 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci /* Schedule policy is determined by ->qc_defer() callback and 9988c2ecf20Sopenharmony_ci * it needs to see every deferred qc. Set dev_blocked to 1 to 9998c2ecf20Sopenharmony_ci * prevent SCSI midlayer from automatically deferring 10008c2ecf20Sopenharmony_ci * requests. 10018c2ecf20Sopenharmony_ci */ 10028c2ecf20Sopenharmony_ci sdev->max_device_blocked = 1; 10038c2ecf20Sopenharmony_ci} 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci/** 10068c2ecf20Sopenharmony_ci * ata_scsi_dma_need_drain - Check whether data transfer may overflow 10078c2ecf20Sopenharmony_ci * @rq: request to be checked 10088c2ecf20Sopenharmony_ci * 10098c2ecf20Sopenharmony_ci * ATAPI commands which transfer variable length data to host 10108c2ecf20Sopenharmony_ci * might overflow due to application error or hardware bug. This 10118c2ecf20Sopenharmony_ci * function checks whether overflow should be drained and ignored 10128c2ecf20Sopenharmony_ci * for @request. 10138c2ecf20Sopenharmony_ci * 10148c2ecf20Sopenharmony_ci * LOCKING: 10158c2ecf20Sopenharmony_ci * None. 10168c2ecf20Sopenharmony_ci * 10178c2ecf20Sopenharmony_ci * RETURNS: 10188c2ecf20Sopenharmony_ci * 1 if ; otherwise, 0. 10198c2ecf20Sopenharmony_ci */ 10208c2ecf20Sopenharmony_cibool ata_scsi_dma_need_drain(struct request *rq) 10218c2ecf20Sopenharmony_ci{ 10228c2ecf20Sopenharmony_ci return atapi_cmd_type(scsi_req(rq)->cmd[0]) == ATAPI_MISC; 10238c2ecf20Sopenharmony_ci} 10248c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_scsi_dma_need_drain); 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ciint ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev) 10278c2ecf20Sopenharmony_ci{ 10288c2ecf20Sopenharmony_ci struct request_queue *q = sdev->request_queue; 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci if (!ata_id_has_unload(dev->id)) 10318c2ecf20Sopenharmony_ci dev->flags |= ATA_DFLAG_NO_UNLOAD; 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci /* configure max sectors */ 10348c2ecf20Sopenharmony_ci blk_queue_max_hw_sectors(q, dev->max_sectors); 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci if (dev->class == ATA_DEV_ATAPI) { 10378c2ecf20Sopenharmony_ci sdev->sector_size = ATA_SECT_SIZE; 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci /* set DMA padding */ 10408c2ecf20Sopenharmony_ci blk_queue_update_dma_pad(q, ATA_DMA_PAD_SZ - 1); 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci /* make room for appending the drain */ 10438c2ecf20Sopenharmony_ci blk_queue_max_segments(q, queue_max_segments(q) - 1); 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci sdev->dma_drain_len = ATAPI_MAX_DRAIN; 10468c2ecf20Sopenharmony_ci sdev->dma_drain_buf = kmalloc(sdev->dma_drain_len, 10478c2ecf20Sopenharmony_ci q->bounce_gfp | GFP_KERNEL); 10488c2ecf20Sopenharmony_ci if (!sdev->dma_drain_buf) { 10498c2ecf20Sopenharmony_ci ata_dev_err(dev, "drain buffer allocation failed\n"); 10508c2ecf20Sopenharmony_ci return -ENOMEM; 10518c2ecf20Sopenharmony_ci } 10528c2ecf20Sopenharmony_ci } else { 10538c2ecf20Sopenharmony_ci sdev->sector_size = ata_id_logical_sector_size(dev->id); 10548c2ecf20Sopenharmony_ci sdev->manage_start_stop = 1; 10558c2ecf20Sopenharmony_ci } 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_ci /* 10588c2ecf20Sopenharmony_ci * ata_pio_sectors() expects buffer for each sector to not cross 10598c2ecf20Sopenharmony_ci * page boundary. Enforce it by requiring buffers to be sector 10608c2ecf20Sopenharmony_ci * aligned, which works iff sector_size is not larger than 10618c2ecf20Sopenharmony_ci * PAGE_SIZE. ATAPI devices also need the alignment as 10628c2ecf20Sopenharmony_ci * IDENTIFY_PACKET is executed as ATA_PROT_PIO. 10638c2ecf20Sopenharmony_ci */ 10648c2ecf20Sopenharmony_ci if (sdev->sector_size > PAGE_SIZE) 10658c2ecf20Sopenharmony_ci ata_dev_warn(dev, 10668c2ecf20Sopenharmony_ci "sector_size=%u > PAGE_SIZE, PIO may malfunction\n", 10678c2ecf20Sopenharmony_ci sdev->sector_size); 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci blk_queue_update_dma_alignment(q, sdev->sector_size - 1); 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci if (dev->flags & ATA_DFLAG_AN) 10728c2ecf20Sopenharmony_ci set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events); 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci if (dev->flags & ATA_DFLAG_NCQ) { 10758c2ecf20Sopenharmony_ci int depth; 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id)); 10788c2ecf20Sopenharmony_ci depth = min(ATA_MAX_QUEUE, depth); 10798c2ecf20Sopenharmony_ci scsi_change_queue_depth(sdev, depth); 10808c2ecf20Sopenharmony_ci } 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci if (dev->flags & ATA_DFLAG_TRUSTED) 10838c2ecf20Sopenharmony_ci sdev->security_supported = 1; 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci dev->sdev = sdev; 10868c2ecf20Sopenharmony_ci return 0; 10878c2ecf20Sopenharmony_ci} 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci/** 10908c2ecf20Sopenharmony_ci * ata_scsi_slave_config - Set SCSI device attributes 10918c2ecf20Sopenharmony_ci * @sdev: SCSI device to examine 10928c2ecf20Sopenharmony_ci * 10938c2ecf20Sopenharmony_ci * This is called before we actually start reading 10948c2ecf20Sopenharmony_ci * and writing to the device, to configure certain 10958c2ecf20Sopenharmony_ci * SCSI mid-layer behaviors. 10968c2ecf20Sopenharmony_ci * 10978c2ecf20Sopenharmony_ci * LOCKING: 10988c2ecf20Sopenharmony_ci * Defined by SCSI layer. We don't really care. 10998c2ecf20Sopenharmony_ci */ 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ciint ata_scsi_slave_config(struct scsi_device *sdev) 11028c2ecf20Sopenharmony_ci{ 11038c2ecf20Sopenharmony_ci struct ata_port *ap = ata_shost_to_port(sdev->host); 11048c2ecf20Sopenharmony_ci struct ata_device *dev = __ata_scsi_find_dev(ap, sdev); 11058c2ecf20Sopenharmony_ci int rc = 0; 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci ata_scsi_sdev_config(sdev); 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci if (dev) 11108c2ecf20Sopenharmony_ci rc = ata_scsi_dev_config(sdev, dev); 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci return rc; 11138c2ecf20Sopenharmony_ci} 11148c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_scsi_slave_config); 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci/** 11178c2ecf20Sopenharmony_ci * ata_scsi_slave_destroy - SCSI device is about to be destroyed 11188c2ecf20Sopenharmony_ci * @sdev: SCSI device to be destroyed 11198c2ecf20Sopenharmony_ci * 11208c2ecf20Sopenharmony_ci * @sdev is about to be destroyed for hot/warm unplugging. If 11218c2ecf20Sopenharmony_ci * this unplugging was initiated by libata as indicated by NULL 11228c2ecf20Sopenharmony_ci * dev->sdev, this function doesn't have to do anything. 11238c2ecf20Sopenharmony_ci * Otherwise, SCSI layer initiated warm-unplug is in progress. 11248c2ecf20Sopenharmony_ci * Clear dev->sdev, schedule the device for ATA detach and invoke 11258c2ecf20Sopenharmony_ci * EH. 11268c2ecf20Sopenharmony_ci * 11278c2ecf20Sopenharmony_ci * LOCKING: 11288c2ecf20Sopenharmony_ci * Defined by SCSI layer. We don't really care. 11298c2ecf20Sopenharmony_ci */ 11308c2ecf20Sopenharmony_civoid ata_scsi_slave_destroy(struct scsi_device *sdev) 11318c2ecf20Sopenharmony_ci{ 11328c2ecf20Sopenharmony_ci struct ata_port *ap = ata_shost_to_port(sdev->host); 11338c2ecf20Sopenharmony_ci unsigned long flags; 11348c2ecf20Sopenharmony_ci struct ata_device *dev; 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci if (!ap->ops->error_handler) 11378c2ecf20Sopenharmony_ci return; 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci spin_lock_irqsave(ap->lock, flags); 11408c2ecf20Sopenharmony_ci dev = __ata_scsi_find_dev(ap, sdev); 11418c2ecf20Sopenharmony_ci if (dev && dev->sdev) { 11428c2ecf20Sopenharmony_ci /* SCSI device already in CANCEL state, no need to offline it */ 11438c2ecf20Sopenharmony_ci dev->sdev = NULL; 11448c2ecf20Sopenharmony_ci dev->flags |= ATA_DFLAG_DETACH; 11458c2ecf20Sopenharmony_ci ata_port_schedule_eh(ap); 11468c2ecf20Sopenharmony_ci } 11478c2ecf20Sopenharmony_ci spin_unlock_irqrestore(ap->lock, flags); 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci kfree(sdev->dma_drain_buf); 11508c2ecf20Sopenharmony_ci} 11518c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_scsi_slave_destroy); 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci/** 11548c2ecf20Sopenharmony_ci * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command 11558c2ecf20Sopenharmony_ci * @qc: Storage for translated ATA taskfile 11568c2ecf20Sopenharmony_ci * 11578c2ecf20Sopenharmony_ci * Sets up an ATA taskfile to issue STANDBY (to stop) or READ VERIFY 11588c2ecf20Sopenharmony_ci * (to start). Perhaps these commands should be preceded by 11598c2ecf20Sopenharmony_ci * CHECK POWER MODE to see what power mode the device is already in. 11608c2ecf20Sopenharmony_ci * [See SAT revision 5 at www.t10.org] 11618c2ecf20Sopenharmony_ci * 11628c2ecf20Sopenharmony_ci * LOCKING: 11638c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 11648c2ecf20Sopenharmony_ci * 11658c2ecf20Sopenharmony_ci * RETURNS: 11668c2ecf20Sopenharmony_ci * Zero on success, non-zero on error. 11678c2ecf20Sopenharmony_ci */ 11688c2ecf20Sopenharmony_cistatic unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) 11698c2ecf20Sopenharmony_ci{ 11708c2ecf20Sopenharmony_ci struct scsi_cmnd *scmd = qc->scsicmd; 11718c2ecf20Sopenharmony_ci struct ata_taskfile *tf = &qc->tf; 11728c2ecf20Sopenharmony_ci const u8 *cdb = scmd->cmnd; 11738c2ecf20Sopenharmony_ci u16 fp; 11748c2ecf20Sopenharmony_ci u8 bp = 0xff; 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci if (scmd->cmd_len < 5) { 11778c2ecf20Sopenharmony_ci fp = 4; 11788c2ecf20Sopenharmony_ci goto invalid_fld; 11798c2ecf20Sopenharmony_ci } 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; 11828c2ecf20Sopenharmony_ci tf->protocol = ATA_PROT_NODATA; 11838c2ecf20Sopenharmony_ci if (cdb[1] & 0x1) { 11848c2ecf20Sopenharmony_ci ; /* ignore IMMED bit, violates sat-r05 */ 11858c2ecf20Sopenharmony_ci } 11868c2ecf20Sopenharmony_ci if (cdb[4] & 0x2) { 11878c2ecf20Sopenharmony_ci fp = 4; 11888c2ecf20Sopenharmony_ci bp = 1; 11898c2ecf20Sopenharmony_ci goto invalid_fld; /* LOEJ bit set not supported */ 11908c2ecf20Sopenharmony_ci } 11918c2ecf20Sopenharmony_ci if (((cdb[4] >> 4) & 0xf) != 0) { 11928c2ecf20Sopenharmony_ci fp = 4; 11938c2ecf20Sopenharmony_ci bp = 3; 11948c2ecf20Sopenharmony_ci goto invalid_fld; /* power conditions not supported */ 11958c2ecf20Sopenharmony_ci } 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci if (cdb[4] & 0x1) { 11988c2ecf20Sopenharmony_ci tf->nsect = 1; /* 1 sector, lba=0 */ 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci if (qc->dev->flags & ATA_DFLAG_LBA) { 12018c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_LBA; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci tf->lbah = 0x0; 12048c2ecf20Sopenharmony_ci tf->lbam = 0x0; 12058c2ecf20Sopenharmony_ci tf->lbal = 0x0; 12068c2ecf20Sopenharmony_ci tf->device |= ATA_LBA; 12078c2ecf20Sopenharmony_ci } else { 12088c2ecf20Sopenharmony_ci /* CHS */ 12098c2ecf20Sopenharmony_ci tf->lbal = 0x1; /* sect */ 12108c2ecf20Sopenharmony_ci tf->lbam = 0x0; /* cyl low */ 12118c2ecf20Sopenharmony_ci tf->lbah = 0x0; /* cyl high */ 12128c2ecf20Sopenharmony_ci } 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci tf->command = ATA_CMD_VERIFY; /* READ VERIFY */ 12158c2ecf20Sopenharmony_ci } else { 12168c2ecf20Sopenharmony_ci /* Some odd clown BIOSen issue spindown on power off (ACPI S4 12178c2ecf20Sopenharmony_ci * or S5) causing some drives to spin up and down again. 12188c2ecf20Sopenharmony_ci */ 12198c2ecf20Sopenharmony_ci if ((qc->ap->flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) && 12208c2ecf20Sopenharmony_ci system_state == SYSTEM_POWER_OFF) 12218c2ecf20Sopenharmony_ci goto skip; 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci if ((qc->ap->flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) && 12248c2ecf20Sopenharmony_ci system_entering_hibernation()) 12258c2ecf20Sopenharmony_ci goto skip; 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci /* Issue ATA STANDBY IMMEDIATE command */ 12288c2ecf20Sopenharmony_ci tf->command = ATA_CMD_STANDBYNOW1; 12298c2ecf20Sopenharmony_ci } 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci /* 12328c2ecf20Sopenharmony_ci * Standby and Idle condition timers could be implemented but that 12338c2ecf20Sopenharmony_ci * would require libata to implement the Power condition mode page 12348c2ecf20Sopenharmony_ci * and allow the user to change it. Changing mode pages requires 12358c2ecf20Sopenharmony_ci * MODE SELECT to be implemented. 12368c2ecf20Sopenharmony_ci */ 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci return 0; 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci invalid_fld: 12418c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(qc->dev, scmd, fp, bp); 12428c2ecf20Sopenharmony_ci return 1; 12438c2ecf20Sopenharmony_ci skip: 12448c2ecf20Sopenharmony_ci scmd->result = SAM_STAT_GOOD; 12458c2ecf20Sopenharmony_ci return 1; 12468c2ecf20Sopenharmony_ci} 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci/** 12508c2ecf20Sopenharmony_ci * ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command 12518c2ecf20Sopenharmony_ci * @qc: Storage for translated ATA taskfile 12528c2ecf20Sopenharmony_ci * 12538c2ecf20Sopenharmony_ci * Sets up an ATA taskfile to issue FLUSH CACHE or 12548c2ecf20Sopenharmony_ci * FLUSH CACHE EXT. 12558c2ecf20Sopenharmony_ci * 12568c2ecf20Sopenharmony_ci * LOCKING: 12578c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 12588c2ecf20Sopenharmony_ci * 12598c2ecf20Sopenharmony_ci * RETURNS: 12608c2ecf20Sopenharmony_ci * Zero on success, non-zero on error. 12618c2ecf20Sopenharmony_ci */ 12628c2ecf20Sopenharmony_cistatic unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc) 12638c2ecf20Sopenharmony_ci{ 12648c2ecf20Sopenharmony_ci struct ata_taskfile *tf = &qc->tf; 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_DEVICE; 12678c2ecf20Sopenharmony_ci tf->protocol = ATA_PROT_NODATA; 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci if (qc->dev->flags & ATA_DFLAG_FLUSH_EXT) 12708c2ecf20Sopenharmony_ci tf->command = ATA_CMD_FLUSH_EXT; 12718c2ecf20Sopenharmony_ci else 12728c2ecf20Sopenharmony_ci tf->command = ATA_CMD_FLUSH; 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci /* flush is critical for IO integrity, consider it an IO command */ 12758c2ecf20Sopenharmony_ci qc->flags |= ATA_QCFLAG_IO; 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci return 0; 12788c2ecf20Sopenharmony_ci} 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci/** 12818c2ecf20Sopenharmony_ci * scsi_6_lba_len - Get LBA and transfer length 12828c2ecf20Sopenharmony_ci * @cdb: SCSI command to translate 12838c2ecf20Sopenharmony_ci * 12848c2ecf20Sopenharmony_ci * Calculate LBA and transfer length for 6-byte commands. 12858c2ecf20Sopenharmony_ci * 12868c2ecf20Sopenharmony_ci * RETURNS: 12878c2ecf20Sopenharmony_ci * @plba: the LBA 12888c2ecf20Sopenharmony_ci * @plen: the transfer length 12898c2ecf20Sopenharmony_ci */ 12908c2ecf20Sopenharmony_cistatic void scsi_6_lba_len(const u8 *cdb, u64 *plba, u32 *plen) 12918c2ecf20Sopenharmony_ci{ 12928c2ecf20Sopenharmony_ci u64 lba = 0; 12938c2ecf20Sopenharmony_ci u32 len; 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci VPRINTK("six-byte command\n"); 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci lba |= ((u64)(cdb[1] & 0x1f)) << 16; 12988c2ecf20Sopenharmony_ci lba |= ((u64)cdb[2]) << 8; 12998c2ecf20Sopenharmony_ci lba |= ((u64)cdb[3]); 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci len = cdb[4]; 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ci *plba = lba; 13048c2ecf20Sopenharmony_ci *plen = len; 13058c2ecf20Sopenharmony_ci} 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci/** 13088c2ecf20Sopenharmony_ci * scsi_10_lba_len - Get LBA and transfer length 13098c2ecf20Sopenharmony_ci * @cdb: SCSI command to translate 13108c2ecf20Sopenharmony_ci * 13118c2ecf20Sopenharmony_ci * Calculate LBA and transfer length for 10-byte commands. 13128c2ecf20Sopenharmony_ci * 13138c2ecf20Sopenharmony_ci * RETURNS: 13148c2ecf20Sopenharmony_ci * @plba: the LBA 13158c2ecf20Sopenharmony_ci * @plen: the transfer length 13168c2ecf20Sopenharmony_ci */ 13178c2ecf20Sopenharmony_cistatic void scsi_10_lba_len(const u8 *cdb, u64 *plba, u32 *plen) 13188c2ecf20Sopenharmony_ci{ 13198c2ecf20Sopenharmony_ci u64 lba = 0; 13208c2ecf20Sopenharmony_ci u32 len = 0; 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci VPRINTK("ten-byte command\n"); 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci lba |= ((u64)cdb[2]) << 24; 13258c2ecf20Sopenharmony_ci lba |= ((u64)cdb[3]) << 16; 13268c2ecf20Sopenharmony_ci lba |= ((u64)cdb[4]) << 8; 13278c2ecf20Sopenharmony_ci lba |= ((u64)cdb[5]); 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_ci len |= ((u32)cdb[7]) << 8; 13308c2ecf20Sopenharmony_ci len |= ((u32)cdb[8]); 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci *plba = lba; 13338c2ecf20Sopenharmony_ci *plen = len; 13348c2ecf20Sopenharmony_ci} 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci/** 13378c2ecf20Sopenharmony_ci * scsi_16_lba_len - Get LBA and transfer length 13388c2ecf20Sopenharmony_ci * @cdb: SCSI command to translate 13398c2ecf20Sopenharmony_ci * 13408c2ecf20Sopenharmony_ci * Calculate LBA and transfer length for 16-byte commands. 13418c2ecf20Sopenharmony_ci * 13428c2ecf20Sopenharmony_ci * RETURNS: 13438c2ecf20Sopenharmony_ci * @plba: the LBA 13448c2ecf20Sopenharmony_ci * @plen: the transfer length 13458c2ecf20Sopenharmony_ci */ 13468c2ecf20Sopenharmony_cistatic void scsi_16_lba_len(const u8 *cdb, u64 *plba, u32 *plen) 13478c2ecf20Sopenharmony_ci{ 13488c2ecf20Sopenharmony_ci u64 lba = 0; 13498c2ecf20Sopenharmony_ci u32 len = 0; 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci VPRINTK("sixteen-byte command\n"); 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci lba |= ((u64)cdb[2]) << 56; 13548c2ecf20Sopenharmony_ci lba |= ((u64)cdb[3]) << 48; 13558c2ecf20Sopenharmony_ci lba |= ((u64)cdb[4]) << 40; 13568c2ecf20Sopenharmony_ci lba |= ((u64)cdb[5]) << 32; 13578c2ecf20Sopenharmony_ci lba |= ((u64)cdb[6]) << 24; 13588c2ecf20Sopenharmony_ci lba |= ((u64)cdb[7]) << 16; 13598c2ecf20Sopenharmony_ci lba |= ((u64)cdb[8]) << 8; 13608c2ecf20Sopenharmony_ci lba |= ((u64)cdb[9]); 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci len |= ((u32)cdb[10]) << 24; 13638c2ecf20Sopenharmony_ci len |= ((u32)cdb[11]) << 16; 13648c2ecf20Sopenharmony_ci len |= ((u32)cdb[12]) << 8; 13658c2ecf20Sopenharmony_ci len |= ((u32)cdb[13]); 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci *plba = lba; 13688c2ecf20Sopenharmony_ci *plen = len; 13698c2ecf20Sopenharmony_ci} 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci/** 13728c2ecf20Sopenharmony_ci * ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one 13738c2ecf20Sopenharmony_ci * @qc: Storage for translated ATA taskfile 13748c2ecf20Sopenharmony_ci * 13758c2ecf20Sopenharmony_ci * Converts SCSI VERIFY command to an ATA READ VERIFY command. 13768c2ecf20Sopenharmony_ci * 13778c2ecf20Sopenharmony_ci * LOCKING: 13788c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 13798c2ecf20Sopenharmony_ci * 13808c2ecf20Sopenharmony_ci * RETURNS: 13818c2ecf20Sopenharmony_ci * Zero on success, non-zero on error. 13828c2ecf20Sopenharmony_ci */ 13838c2ecf20Sopenharmony_cistatic unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc) 13848c2ecf20Sopenharmony_ci{ 13858c2ecf20Sopenharmony_ci struct scsi_cmnd *scmd = qc->scsicmd; 13868c2ecf20Sopenharmony_ci struct ata_taskfile *tf = &qc->tf; 13878c2ecf20Sopenharmony_ci struct ata_device *dev = qc->dev; 13888c2ecf20Sopenharmony_ci u64 dev_sectors = qc->dev->n_sectors; 13898c2ecf20Sopenharmony_ci const u8 *cdb = scmd->cmnd; 13908c2ecf20Sopenharmony_ci u64 block; 13918c2ecf20Sopenharmony_ci u32 n_block; 13928c2ecf20Sopenharmony_ci u16 fp; 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; 13958c2ecf20Sopenharmony_ci tf->protocol = ATA_PROT_NODATA; 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci if (cdb[0] == VERIFY) { 13988c2ecf20Sopenharmony_ci if (scmd->cmd_len < 10) { 13998c2ecf20Sopenharmony_ci fp = 9; 14008c2ecf20Sopenharmony_ci goto invalid_fld; 14018c2ecf20Sopenharmony_ci } 14028c2ecf20Sopenharmony_ci scsi_10_lba_len(cdb, &block, &n_block); 14038c2ecf20Sopenharmony_ci } else if (cdb[0] == VERIFY_16) { 14048c2ecf20Sopenharmony_ci if (scmd->cmd_len < 16) { 14058c2ecf20Sopenharmony_ci fp = 15; 14068c2ecf20Sopenharmony_ci goto invalid_fld; 14078c2ecf20Sopenharmony_ci } 14088c2ecf20Sopenharmony_ci scsi_16_lba_len(cdb, &block, &n_block); 14098c2ecf20Sopenharmony_ci } else { 14108c2ecf20Sopenharmony_ci fp = 0; 14118c2ecf20Sopenharmony_ci goto invalid_fld; 14128c2ecf20Sopenharmony_ci } 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci if (!n_block) 14158c2ecf20Sopenharmony_ci goto nothing_to_do; 14168c2ecf20Sopenharmony_ci if (block >= dev_sectors) 14178c2ecf20Sopenharmony_ci goto out_of_range; 14188c2ecf20Sopenharmony_ci if ((block + n_block) > dev_sectors) 14198c2ecf20Sopenharmony_ci goto out_of_range; 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci if (dev->flags & ATA_DFLAG_LBA) { 14228c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_LBA; 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_ci if (lba_28_ok(block, n_block)) { 14258c2ecf20Sopenharmony_ci /* use LBA28 */ 14268c2ecf20Sopenharmony_ci tf->command = ATA_CMD_VERIFY; 14278c2ecf20Sopenharmony_ci tf->device |= (block >> 24) & 0xf; 14288c2ecf20Sopenharmony_ci } else if (lba_48_ok(block, n_block)) { 14298c2ecf20Sopenharmony_ci if (!(dev->flags & ATA_DFLAG_LBA48)) 14308c2ecf20Sopenharmony_ci goto out_of_range; 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_ci /* use LBA48 */ 14338c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_LBA48; 14348c2ecf20Sopenharmony_ci tf->command = ATA_CMD_VERIFY_EXT; 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci tf->hob_nsect = (n_block >> 8) & 0xff; 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci tf->hob_lbah = (block >> 40) & 0xff; 14398c2ecf20Sopenharmony_ci tf->hob_lbam = (block >> 32) & 0xff; 14408c2ecf20Sopenharmony_ci tf->hob_lbal = (block >> 24) & 0xff; 14418c2ecf20Sopenharmony_ci } else 14428c2ecf20Sopenharmony_ci /* request too large even for LBA48 */ 14438c2ecf20Sopenharmony_ci goto out_of_range; 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci tf->nsect = n_block & 0xff; 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci tf->lbah = (block >> 16) & 0xff; 14488c2ecf20Sopenharmony_ci tf->lbam = (block >> 8) & 0xff; 14498c2ecf20Sopenharmony_ci tf->lbal = block & 0xff; 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci tf->device |= ATA_LBA; 14528c2ecf20Sopenharmony_ci } else { 14538c2ecf20Sopenharmony_ci /* CHS */ 14548c2ecf20Sopenharmony_ci u32 sect, head, cyl, track; 14558c2ecf20Sopenharmony_ci 14568c2ecf20Sopenharmony_ci if (!lba_28_ok(block, n_block)) 14578c2ecf20Sopenharmony_ci goto out_of_range; 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci /* Convert LBA to CHS */ 14608c2ecf20Sopenharmony_ci track = (u32)block / dev->sectors; 14618c2ecf20Sopenharmony_ci cyl = track / dev->heads; 14628c2ecf20Sopenharmony_ci head = track % dev->heads; 14638c2ecf20Sopenharmony_ci sect = (u32)block % dev->sectors + 1; 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_ci DPRINTK("block %u track %u cyl %u head %u sect %u\n", 14668c2ecf20Sopenharmony_ci (u32)block, track, cyl, head, sect); 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci /* Check whether the converted CHS can fit. 14698c2ecf20Sopenharmony_ci Cylinder: 0-65535 14708c2ecf20Sopenharmony_ci Head: 0-15 14718c2ecf20Sopenharmony_ci Sector: 1-255*/ 14728c2ecf20Sopenharmony_ci if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) 14738c2ecf20Sopenharmony_ci goto out_of_range; 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci tf->command = ATA_CMD_VERIFY; 14768c2ecf20Sopenharmony_ci tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */ 14778c2ecf20Sopenharmony_ci tf->lbal = sect; 14788c2ecf20Sopenharmony_ci tf->lbam = cyl; 14798c2ecf20Sopenharmony_ci tf->lbah = cyl >> 8; 14808c2ecf20Sopenharmony_ci tf->device |= head; 14818c2ecf20Sopenharmony_ci } 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci return 0; 14848c2ecf20Sopenharmony_ci 14858c2ecf20Sopenharmony_ciinvalid_fld: 14868c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(qc->dev, scmd, fp, 0xff); 14878c2ecf20Sopenharmony_ci return 1; 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ciout_of_range: 14908c2ecf20Sopenharmony_ci ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x21, 0x0); 14918c2ecf20Sopenharmony_ci /* "Logical Block Address out of range" */ 14928c2ecf20Sopenharmony_ci return 1; 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_cinothing_to_do: 14958c2ecf20Sopenharmony_ci scmd->result = SAM_STAT_GOOD; 14968c2ecf20Sopenharmony_ci return 1; 14978c2ecf20Sopenharmony_ci} 14988c2ecf20Sopenharmony_ci 14998c2ecf20Sopenharmony_cistatic bool ata_check_nblocks(struct scsi_cmnd *scmd, u32 n_blocks) 15008c2ecf20Sopenharmony_ci{ 15018c2ecf20Sopenharmony_ci struct request *rq = scmd->request; 15028c2ecf20Sopenharmony_ci u32 req_blocks; 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci if (!blk_rq_is_passthrough(rq)) 15058c2ecf20Sopenharmony_ci return true; 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci req_blocks = blk_rq_bytes(rq) / scmd->device->sector_size; 15088c2ecf20Sopenharmony_ci if (n_blocks > req_blocks) 15098c2ecf20Sopenharmony_ci return false; 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_ci return true; 15128c2ecf20Sopenharmony_ci} 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci/** 15158c2ecf20Sopenharmony_ci * ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one 15168c2ecf20Sopenharmony_ci * @qc: Storage for translated ATA taskfile 15178c2ecf20Sopenharmony_ci * 15188c2ecf20Sopenharmony_ci * Converts any of six SCSI read/write commands into the 15198c2ecf20Sopenharmony_ci * ATA counterpart, including starting sector (LBA), 15208c2ecf20Sopenharmony_ci * sector count, and taking into account the device's LBA48 15218c2ecf20Sopenharmony_ci * support. 15228c2ecf20Sopenharmony_ci * 15238c2ecf20Sopenharmony_ci * Commands %READ_6, %READ_10, %READ_16, %WRITE_6, %WRITE_10, and 15248c2ecf20Sopenharmony_ci * %WRITE_16 are currently supported. 15258c2ecf20Sopenharmony_ci * 15268c2ecf20Sopenharmony_ci * LOCKING: 15278c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 15288c2ecf20Sopenharmony_ci * 15298c2ecf20Sopenharmony_ci * RETURNS: 15308c2ecf20Sopenharmony_ci * Zero on success, non-zero on error. 15318c2ecf20Sopenharmony_ci */ 15328c2ecf20Sopenharmony_cistatic unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) 15338c2ecf20Sopenharmony_ci{ 15348c2ecf20Sopenharmony_ci struct scsi_cmnd *scmd = qc->scsicmd; 15358c2ecf20Sopenharmony_ci const u8 *cdb = scmd->cmnd; 15368c2ecf20Sopenharmony_ci struct request *rq = scmd->request; 15378c2ecf20Sopenharmony_ci int class = IOPRIO_PRIO_CLASS(req_get_ioprio(rq)); 15388c2ecf20Sopenharmony_ci unsigned int tf_flags = 0; 15398c2ecf20Sopenharmony_ci u64 block; 15408c2ecf20Sopenharmony_ci u32 n_block; 15418c2ecf20Sopenharmony_ci int rc; 15428c2ecf20Sopenharmony_ci u16 fp = 0; 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci if (cdb[0] == WRITE_10 || cdb[0] == WRITE_6 || cdb[0] == WRITE_16) 15458c2ecf20Sopenharmony_ci tf_flags |= ATA_TFLAG_WRITE; 15468c2ecf20Sopenharmony_ci 15478c2ecf20Sopenharmony_ci /* Calculate the SCSI LBA, transfer length and FUA. */ 15488c2ecf20Sopenharmony_ci switch (cdb[0]) { 15498c2ecf20Sopenharmony_ci case READ_10: 15508c2ecf20Sopenharmony_ci case WRITE_10: 15518c2ecf20Sopenharmony_ci if (unlikely(scmd->cmd_len < 10)) { 15528c2ecf20Sopenharmony_ci fp = 9; 15538c2ecf20Sopenharmony_ci goto invalid_fld; 15548c2ecf20Sopenharmony_ci } 15558c2ecf20Sopenharmony_ci scsi_10_lba_len(cdb, &block, &n_block); 15568c2ecf20Sopenharmony_ci if (cdb[1] & (1 << 3)) 15578c2ecf20Sopenharmony_ci tf_flags |= ATA_TFLAG_FUA; 15588c2ecf20Sopenharmony_ci if (!ata_check_nblocks(scmd, n_block)) 15598c2ecf20Sopenharmony_ci goto invalid_fld; 15608c2ecf20Sopenharmony_ci break; 15618c2ecf20Sopenharmony_ci case READ_6: 15628c2ecf20Sopenharmony_ci case WRITE_6: 15638c2ecf20Sopenharmony_ci if (unlikely(scmd->cmd_len < 6)) { 15648c2ecf20Sopenharmony_ci fp = 5; 15658c2ecf20Sopenharmony_ci goto invalid_fld; 15668c2ecf20Sopenharmony_ci } 15678c2ecf20Sopenharmony_ci scsi_6_lba_len(cdb, &block, &n_block); 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci /* for 6-byte r/w commands, transfer length 0 15708c2ecf20Sopenharmony_ci * means 256 blocks of data, not 0 block. 15718c2ecf20Sopenharmony_ci */ 15728c2ecf20Sopenharmony_ci if (!n_block) 15738c2ecf20Sopenharmony_ci n_block = 256; 15748c2ecf20Sopenharmony_ci if (!ata_check_nblocks(scmd, n_block)) 15758c2ecf20Sopenharmony_ci goto invalid_fld; 15768c2ecf20Sopenharmony_ci break; 15778c2ecf20Sopenharmony_ci case READ_16: 15788c2ecf20Sopenharmony_ci case WRITE_16: 15798c2ecf20Sopenharmony_ci if (unlikely(scmd->cmd_len < 16)) { 15808c2ecf20Sopenharmony_ci fp = 15; 15818c2ecf20Sopenharmony_ci goto invalid_fld; 15828c2ecf20Sopenharmony_ci } 15838c2ecf20Sopenharmony_ci scsi_16_lba_len(cdb, &block, &n_block); 15848c2ecf20Sopenharmony_ci if (cdb[1] & (1 << 3)) 15858c2ecf20Sopenharmony_ci tf_flags |= ATA_TFLAG_FUA; 15868c2ecf20Sopenharmony_ci if (!ata_check_nblocks(scmd, n_block)) 15878c2ecf20Sopenharmony_ci goto invalid_fld; 15888c2ecf20Sopenharmony_ci break; 15898c2ecf20Sopenharmony_ci default: 15908c2ecf20Sopenharmony_ci DPRINTK("no-byte command\n"); 15918c2ecf20Sopenharmony_ci fp = 0; 15928c2ecf20Sopenharmony_ci goto invalid_fld; 15938c2ecf20Sopenharmony_ci } 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_ci /* Check and compose ATA command */ 15968c2ecf20Sopenharmony_ci if (!n_block) 15978c2ecf20Sopenharmony_ci /* For 10-byte and 16-byte SCSI R/W commands, transfer 15988c2ecf20Sopenharmony_ci * length 0 means transfer 0 block of data. 15998c2ecf20Sopenharmony_ci * However, for ATA R/W commands, sector count 0 means 16008c2ecf20Sopenharmony_ci * 256 or 65536 sectors, not 0 sectors as in SCSI. 16018c2ecf20Sopenharmony_ci * 16028c2ecf20Sopenharmony_ci * WARNING: one or two older ATA drives treat 0 as 0... 16038c2ecf20Sopenharmony_ci */ 16048c2ecf20Sopenharmony_ci goto nothing_to_do; 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_ci qc->flags |= ATA_QCFLAG_IO; 16078c2ecf20Sopenharmony_ci qc->nbytes = n_block * scmd->device->sector_size; 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags, 16108c2ecf20Sopenharmony_ci qc->hw_tag, class); 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci if (likely(rc == 0)) 16138c2ecf20Sopenharmony_ci return 0; 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci if (rc == -ERANGE) 16168c2ecf20Sopenharmony_ci goto out_of_range; 16178c2ecf20Sopenharmony_ci /* treat all other errors as -EINVAL, fall through */ 16188c2ecf20Sopenharmony_ciinvalid_fld: 16198c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(qc->dev, scmd, fp, 0xff); 16208c2ecf20Sopenharmony_ci return 1; 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ciout_of_range: 16238c2ecf20Sopenharmony_ci ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x21, 0x0); 16248c2ecf20Sopenharmony_ci /* "Logical Block Address out of range" */ 16258c2ecf20Sopenharmony_ci return 1; 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_cinothing_to_do: 16288c2ecf20Sopenharmony_ci scmd->result = SAM_STAT_GOOD; 16298c2ecf20Sopenharmony_ci return 1; 16308c2ecf20Sopenharmony_ci} 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_cistatic void ata_qc_done(struct ata_queued_cmd *qc) 16338c2ecf20Sopenharmony_ci{ 16348c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = qc->scsicmd; 16358c2ecf20Sopenharmony_ci void (*done)(struct scsi_cmnd *) = qc->scsidone; 16368c2ecf20Sopenharmony_ci 16378c2ecf20Sopenharmony_ci ata_qc_free(qc); 16388c2ecf20Sopenharmony_ci done(cmd); 16398c2ecf20Sopenharmony_ci} 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_cistatic void ata_scsi_qc_complete(struct ata_queued_cmd *qc) 16428c2ecf20Sopenharmony_ci{ 16438c2ecf20Sopenharmony_ci struct ata_port *ap = qc->ap; 16448c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = qc->scsicmd; 16458c2ecf20Sopenharmony_ci u8 *cdb = cmd->cmnd; 16468c2ecf20Sopenharmony_ci int need_sense = (qc->err_mask != 0); 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_ci /* For ATA pass thru (SAT) commands, generate a sense block if 16498c2ecf20Sopenharmony_ci * user mandated it or if there's an error. Note that if we 16508c2ecf20Sopenharmony_ci * generate because the user forced us to [CK_COND =1], a check 16518c2ecf20Sopenharmony_ci * condition is generated and the ATA register values are returned 16528c2ecf20Sopenharmony_ci * whether the command completed successfully or not. If there 16538c2ecf20Sopenharmony_ci * was no error, we use the following sense data: 16548c2ecf20Sopenharmony_ci * sk = RECOVERED ERROR 16558c2ecf20Sopenharmony_ci * asc,ascq = ATA PASS-THROUGH INFORMATION AVAILABLE 16568c2ecf20Sopenharmony_ci */ 16578c2ecf20Sopenharmony_ci if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) && 16588c2ecf20Sopenharmony_ci ((cdb[2] & 0x20) || need_sense)) 16598c2ecf20Sopenharmony_ci ata_gen_passthru_sense(qc); 16608c2ecf20Sopenharmony_ci else if (qc->flags & ATA_QCFLAG_SENSE_VALID) 16618c2ecf20Sopenharmony_ci cmd->result = SAM_STAT_CHECK_CONDITION; 16628c2ecf20Sopenharmony_ci else if (need_sense) 16638c2ecf20Sopenharmony_ci ata_gen_ata_sense(qc); 16648c2ecf20Sopenharmony_ci else 16658c2ecf20Sopenharmony_ci cmd->result = SAM_STAT_GOOD; 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci if (need_sense && !ap->ops->error_handler) 16688c2ecf20Sopenharmony_ci ata_dump_status(ap->print_id, &qc->result_tf); 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci ata_qc_done(qc); 16718c2ecf20Sopenharmony_ci} 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_ci/** 16748c2ecf20Sopenharmony_ci * ata_scsi_translate - Translate then issue SCSI command to ATA device 16758c2ecf20Sopenharmony_ci * @dev: ATA device to which the command is addressed 16768c2ecf20Sopenharmony_ci * @cmd: SCSI command to execute 16778c2ecf20Sopenharmony_ci * @xlat_func: Actor which translates @cmd to an ATA taskfile 16788c2ecf20Sopenharmony_ci * 16798c2ecf20Sopenharmony_ci * Our ->queuecommand() function has decided that the SCSI 16808c2ecf20Sopenharmony_ci * command issued can be directly translated into an ATA 16818c2ecf20Sopenharmony_ci * command, rather than handled internally. 16828c2ecf20Sopenharmony_ci * 16838c2ecf20Sopenharmony_ci * This function sets up an ata_queued_cmd structure for the 16848c2ecf20Sopenharmony_ci * SCSI command, and sends that ata_queued_cmd to the hardware. 16858c2ecf20Sopenharmony_ci * 16868c2ecf20Sopenharmony_ci * The xlat_func argument (actor) returns 0 if ready to execute 16878c2ecf20Sopenharmony_ci * ATA command, else 1 to finish translation. If 1 is returned 16888c2ecf20Sopenharmony_ci * then cmd->result (and possibly cmd->sense_buffer) are assumed 16898c2ecf20Sopenharmony_ci * to be set reflecting an error condition or clean (early) 16908c2ecf20Sopenharmony_ci * termination. 16918c2ecf20Sopenharmony_ci * 16928c2ecf20Sopenharmony_ci * LOCKING: 16938c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 16948c2ecf20Sopenharmony_ci * 16958c2ecf20Sopenharmony_ci * RETURNS: 16968c2ecf20Sopenharmony_ci * 0 on success, SCSI_ML_QUEUE_DEVICE_BUSY if the command 16978c2ecf20Sopenharmony_ci * needs to be deferred. 16988c2ecf20Sopenharmony_ci */ 16998c2ecf20Sopenharmony_cistatic int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, 17008c2ecf20Sopenharmony_ci ata_xlat_func_t xlat_func) 17018c2ecf20Sopenharmony_ci{ 17028c2ecf20Sopenharmony_ci struct ata_port *ap = dev->link->ap; 17038c2ecf20Sopenharmony_ci struct ata_queued_cmd *qc; 17048c2ecf20Sopenharmony_ci int rc; 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_ci VPRINTK("ENTER\n"); 17078c2ecf20Sopenharmony_ci 17088c2ecf20Sopenharmony_ci qc = ata_scsi_qc_new(dev, cmd); 17098c2ecf20Sopenharmony_ci if (!qc) 17108c2ecf20Sopenharmony_ci goto err_mem; 17118c2ecf20Sopenharmony_ci 17128c2ecf20Sopenharmony_ci /* data is present; dma-map it */ 17138c2ecf20Sopenharmony_ci if (cmd->sc_data_direction == DMA_FROM_DEVICE || 17148c2ecf20Sopenharmony_ci cmd->sc_data_direction == DMA_TO_DEVICE) { 17158c2ecf20Sopenharmony_ci if (unlikely(scsi_bufflen(cmd) < 1)) { 17168c2ecf20Sopenharmony_ci ata_dev_warn(dev, "WARNING: zero len r/w req\n"); 17178c2ecf20Sopenharmony_ci goto err_did; 17188c2ecf20Sopenharmony_ci } 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci ata_sg_init(qc, scsi_sglist(cmd), scsi_sg_count(cmd)); 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci qc->dma_dir = cmd->sc_data_direction; 17238c2ecf20Sopenharmony_ci } 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci qc->complete_fn = ata_scsi_qc_complete; 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_ci if (xlat_func(qc)) 17288c2ecf20Sopenharmony_ci goto early_finish; 17298c2ecf20Sopenharmony_ci 17308c2ecf20Sopenharmony_ci if (ap->ops->qc_defer) { 17318c2ecf20Sopenharmony_ci if ((rc = ap->ops->qc_defer(qc))) 17328c2ecf20Sopenharmony_ci goto defer; 17338c2ecf20Sopenharmony_ci } 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci /* select device, send command to hardware */ 17368c2ecf20Sopenharmony_ci ata_qc_issue(qc); 17378c2ecf20Sopenharmony_ci 17388c2ecf20Sopenharmony_ci VPRINTK("EXIT\n"); 17398c2ecf20Sopenharmony_ci return 0; 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ciearly_finish: 17428c2ecf20Sopenharmony_ci ata_qc_free(qc); 17438c2ecf20Sopenharmony_ci cmd->scsi_done(cmd); 17448c2ecf20Sopenharmony_ci DPRINTK("EXIT - early finish (good or error)\n"); 17458c2ecf20Sopenharmony_ci return 0; 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_cierr_did: 17488c2ecf20Sopenharmony_ci ata_qc_free(qc); 17498c2ecf20Sopenharmony_ci cmd->result = (DID_ERROR << 16); 17508c2ecf20Sopenharmony_ci cmd->scsi_done(cmd); 17518c2ecf20Sopenharmony_cierr_mem: 17528c2ecf20Sopenharmony_ci DPRINTK("EXIT - internal\n"); 17538c2ecf20Sopenharmony_ci return 0; 17548c2ecf20Sopenharmony_ci 17558c2ecf20Sopenharmony_cidefer: 17568c2ecf20Sopenharmony_ci ata_qc_free(qc); 17578c2ecf20Sopenharmony_ci DPRINTK("EXIT - defer\n"); 17588c2ecf20Sopenharmony_ci if (rc == ATA_DEFER_LINK) 17598c2ecf20Sopenharmony_ci return SCSI_MLQUEUE_DEVICE_BUSY; 17608c2ecf20Sopenharmony_ci else 17618c2ecf20Sopenharmony_ci return SCSI_MLQUEUE_HOST_BUSY; 17628c2ecf20Sopenharmony_ci} 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_cistruct ata_scsi_args { 17658c2ecf20Sopenharmony_ci struct ata_device *dev; 17668c2ecf20Sopenharmony_ci u16 *id; 17678c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd; 17688c2ecf20Sopenharmony_ci}; 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci/** 17718c2ecf20Sopenharmony_ci * ata_scsi_rbuf_get - Map response buffer. 17728c2ecf20Sopenharmony_ci * @cmd: SCSI command containing buffer to be mapped. 17738c2ecf20Sopenharmony_ci * @flags: unsigned long variable to store irq enable status 17748c2ecf20Sopenharmony_ci * @copy_in: copy in from user buffer 17758c2ecf20Sopenharmony_ci * 17768c2ecf20Sopenharmony_ci * Prepare buffer for simulated SCSI commands. 17778c2ecf20Sopenharmony_ci * 17788c2ecf20Sopenharmony_ci * LOCKING: 17798c2ecf20Sopenharmony_ci * spin_lock_irqsave(ata_scsi_rbuf_lock) on success 17808c2ecf20Sopenharmony_ci * 17818c2ecf20Sopenharmony_ci * RETURNS: 17828c2ecf20Sopenharmony_ci * Pointer to response buffer. 17838c2ecf20Sopenharmony_ci */ 17848c2ecf20Sopenharmony_cistatic void *ata_scsi_rbuf_get(struct scsi_cmnd *cmd, bool copy_in, 17858c2ecf20Sopenharmony_ci unsigned long *flags) 17868c2ecf20Sopenharmony_ci{ 17878c2ecf20Sopenharmony_ci spin_lock_irqsave(&ata_scsi_rbuf_lock, *flags); 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_ci memset(ata_scsi_rbuf, 0, ATA_SCSI_RBUF_SIZE); 17908c2ecf20Sopenharmony_ci if (copy_in) 17918c2ecf20Sopenharmony_ci sg_copy_to_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), 17928c2ecf20Sopenharmony_ci ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE); 17938c2ecf20Sopenharmony_ci return ata_scsi_rbuf; 17948c2ecf20Sopenharmony_ci} 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_ci/** 17978c2ecf20Sopenharmony_ci * ata_scsi_rbuf_put - Unmap response buffer. 17988c2ecf20Sopenharmony_ci * @cmd: SCSI command containing buffer to be unmapped. 17998c2ecf20Sopenharmony_ci * @copy_out: copy out result 18008c2ecf20Sopenharmony_ci * @flags: @flags passed to ata_scsi_rbuf_get() 18018c2ecf20Sopenharmony_ci * 18028c2ecf20Sopenharmony_ci * Returns rbuf buffer. The result is copied to @cmd's buffer if 18038c2ecf20Sopenharmony_ci * @copy_back is true. 18048c2ecf20Sopenharmony_ci * 18058c2ecf20Sopenharmony_ci * LOCKING: 18068c2ecf20Sopenharmony_ci * Unlocks ata_scsi_rbuf_lock. 18078c2ecf20Sopenharmony_ci */ 18088c2ecf20Sopenharmony_cistatic inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, bool copy_out, 18098c2ecf20Sopenharmony_ci unsigned long *flags) 18108c2ecf20Sopenharmony_ci{ 18118c2ecf20Sopenharmony_ci if (copy_out) 18128c2ecf20Sopenharmony_ci sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), 18138c2ecf20Sopenharmony_ci ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE); 18148c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ata_scsi_rbuf_lock, *flags); 18158c2ecf20Sopenharmony_ci} 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci/** 18188c2ecf20Sopenharmony_ci * ata_scsi_rbuf_fill - wrapper for SCSI command simulators 18198c2ecf20Sopenharmony_ci * @args: device IDENTIFY data / SCSI command of interest. 18208c2ecf20Sopenharmony_ci * @actor: Callback hook for desired SCSI command simulator 18218c2ecf20Sopenharmony_ci * 18228c2ecf20Sopenharmony_ci * Takes care of the hard work of simulating a SCSI command... 18238c2ecf20Sopenharmony_ci * Mapping the response buffer, calling the command's handler, 18248c2ecf20Sopenharmony_ci * and handling the handler's return value. This return value 18258c2ecf20Sopenharmony_ci * indicates whether the handler wishes the SCSI command to be 18268c2ecf20Sopenharmony_ci * completed successfully (0), or not (in which case cmd->result 18278c2ecf20Sopenharmony_ci * and sense buffer are assumed to be set). 18288c2ecf20Sopenharmony_ci * 18298c2ecf20Sopenharmony_ci * LOCKING: 18308c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 18318c2ecf20Sopenharmony_ci */ 18328c2ecf20Sopenharmony_cistatic void ata_scsi_rbuf_fill(struct ata_scsi_args *args, 18338c2ecf20Sopenharmony_ci unsigned int (*actor)(struct ata_scsi_args *args, u8 *rbuf)) 18348c2ecf20Sopenharmony_ci{ 18358c2ecf20Sopenharmony_ci u8 *rbuf; 18368c2ecf20Sopenharmony_ci unsigned int rc; 18378c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = args->cmd; 18388c2ecf20Sopenharmony_ci unsigned long flags; 18398c2ecf20Sopenharmony_ci 18408c2ecf20Sopenharmony_ci rbuf = ata_scsi_rbuf_get(cmd, false, &flags); 18418c2ecf20Sopenharmony_ci rc = actor(args, rbuf); 18428c2ecf20Sopenharmony_ci ata_scsi_rbuf_put(cmd, rc == 0, &flags); 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci if (rc == 0) 18458c2ecf20Sopenharmony_ci cmd->result = SAM_STAT_GOOD; 18468c2ecf20Sopenharmony_ci} 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_ci/** 18498c2ecf20Sopenharmony_ci * ata_scsiop_inq_std - Simulate INQUIRY command 18508c2ecf20Sopenharmony_ci * @args: device IDENTIFY data / SCSI command of interest. 18518c2ecf20Sopenharmony_ci * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. 18528c2ecf20Sopenharmony_ci * 18538c2ecf20Sopenharmony_ci * Returns standard device identification data associated 18548c2ecf20Sopenharmony_ci * with non-VPD INQUIRY command output. 18558c2ecf20Sopenharmony_ci * 18568c2ecf20Sopenharmony_ci * LOCKING: 18578c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 18588c2ecf20Sopenharmony_ci */ 18598c2ecf20Sopenharmony_cistatic unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf) 18608c2ecf20Sopenharmony_ci{ 18618c2ecf20Sopenharmony_ci static const u8 versions[] = { 18628c2ecf20Sopenharmony_ci 0x00, 18638c2ecf20Sopenharmony_ci 0x60, /* SAM-3 (no version claimed) */ 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_ci 0x03, 18668c2ecf20Sopenharmony_ci 0x20, /* SBC-2 (no version claimed) */ 18678c2ecf20Sopenharmony_ci 18688c2ecf20Sopenharmony_ci 0x03, 18698c2ecf20Sopenharmony_ci 0x00 /* SPC-3 (no version claimed) */ 18708c2ecf20Sopenharmony_ci }; 18718c2ecf20Sopenharmony_ci static const u8 versions_zbc[] = { 18728c2ecf20Sopenharmony_ci 0x00, 18738c2ecf20Sopenharmony_ci 0xA0, /* SAM-5 (no version claimed) */ 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_ci 0x06, 18768c2ecf20Sopenharmony_ci 0x00, /* SBC-4 (no version claimed) */ 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_ci 0x05, 18798c2ecf20Sopenharmony_ci 0xC0, /* SPC-5 (no version claimed) */ 18808c2ecf20Sopenharmony_ci 18818c2ecf20Sopenharmony_ci 0x60, 18828c2ecf20Sopenharmony_ci 0x24, /* ZBC r05 */ 18838c2ecf20Sopenharmony_ci }; 18848c2ecf20Sopenharmony_ci 18858c2ecf20Sopenharmony_ci u8 hdr[] = { 18868c2ecf20Sopenharmony_ci TYPE_DISK, 18878c2ecf20Sopenharmony_ci 0, 18888c2ecf20Sopenharmony_ci 0x5, /* claim SPC-3 version compatibility */ 18898c2ecf20Sopenharmony_ci 2, 18908c2ecf20Sopenharmony_ci 95 - 4, 18918c2ecf20Sopenharmony_ci 0, 18928c2ecf20Sopenharmony_ci 0, 18938c2ecf20Sopenharmony_ci 2 18948c2ecf20Sopenharmony_ci }; 18958c2ecf20Sopenharmony_ci 18968c2ecf20Sopenharmony_ci VPRINTK("ENTER\n"); 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_ci /* set scsi removable (RMB) bit per ata bit, or if the 18998c2ecf20Sopenharmony_ci * AHCI port says it's external (Hotplug-capable, eSATA). 19008c2ecf20Sopenharmony_ci */ 19018c2ecf20Sopenharmony_ci if (ata_id_removable(args->id) || 19028c2ecf20Sopenharmony_ci (args->dev->link->ap->pflags & ATA_PFLAG_EXTERNAL)) 19038c2ecf20Sopenharmony_ci hdr[1] |= (1 << 7); 19048c2ecf20Sopenharmony_ci 19058c2ecf20Sopenharmony_ci if (args->dev->class == ATA_DEV_ZAC) { 19068c2ecf20Sopenharmony_ci hdr[0] = TYPE_ZBC; 19078c2ecf20Sopenharmony_ci hdr[2] = 0x7; /* claim SPC-5 version compatibility */ 19088c2ecf20Sopenharmony_ci } 19098c2ecf20Sopenharmony_ci 19108c2ecf20Sopenharmony_ci memcpy(rbuf, hdr, sizeof(hdr)); 19118c2ecf20Sopenharmony_ci memcpy(&rbuf[8], "ATA ", 8); 19128c2ecf20Sopenharmony_ci ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16); 19138c2ecf20Sopenharmony_ci 19148c2ecf20Sopenharmony_ci /* From SAT, use last 2 words from fw rev unless they are spaces */ 19158c2ecf20Sopenharmony_ci ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV + 2, 4); 19168c2ecf20Sopenharmony_ci if (strncmp(&rbuf[32], " ", 4) == 0) 19178c2ecf20Sopenharmony_ci ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4); 19188c2ecf20Sopenharmony_ci 19198c2ecf20Sopenharmony_ci if (rbuf[32] == 0 || rbuf[32] == ' ') 19208c2ecf20Sopenharmony_ci memcpy(&rbuf[32], "n/a ", 4); 19218c2ecf20Sopenharmony_ci 19228c2ecf20Sopenharmony_ci if (ata_id_zoned_cap(args->id) || args->dev->class == ATA_DEV_ZAC) 19238c2ecf20Sopenharmony_ci memcpy(rbuf + 58, versions_zbc, sizeof(versions_zbc)); 19248c2ecf20Sopenharmony_ci else 19258c2ecf20Sopenharmony_ci memcpy(rbuf + 58, versions, sizeof(versions)); 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci return 0; 19288c2ecf20Sopenharmony_ci} 19298c2ecf20Sopenharmony_ci 19308c2ecf20Sopenharmony_ci/** 19318c2ecf20Sopenharmony_ci * ata_scsiop_inq_00 - Simulate INQUIRY VPD page 0, list of pages 19328c2ecf20Sopenharmony_ci * @args: device IDENTIFY data / SCSI command of interest. 19338c2ecf20Sopenharmony_ci * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. 19348c2ecf20Sopenharmony_ci * 19358c2ecf20Sopenharmony_ci * Returns list of inquiry VPD pages available. 19368c2ecf20Sopenharmony_ci * 19378c2ecf20Sopenharmony_ci * LOCKING: 19388c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 19398c2ecf20Sopenharmony_ci */ 19408c2ecf20Sopenharmony_cistatic unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf) 19418c2ecf20Sopenharmony_ci{ 19428c2ecf20Sopenharmony_ci int num_pages; 19438c2ecf20Sopenharmony_ci static const u8 pages[] = { 19448c2ecf20Sopenharmony_ci 0x00, /* page 0x00, this page */ 19458c2ecf20Sopenharmony_ci 0x80, /* page 0x80, unit serial no page */ 19468c2ecf20Sopenharmony_ci 0x83, /* page 0x83, device ident page */ 19478c2ecf20Sopenharmony_ci 0x89, /* page 0x89, ata info page */ 19488c2ecf20Sopenharmony_ci 0xb0, /* page 0xb0, block limits page */ 19498c2ecf20Sopenharmony_ci 0xb1, /* page 0xb1, block device characteristics page */ 19508c2ecf20Sopenharmony_ci 0xb2, /* page 0xb2, thin provisioning page */ 19518c2ecf20Sopenharmony_ci 0xb6, /* page 0xb6, zoned block device characteristics */ 19528c2ecf20Sopenharmony_ci }; 19538c2ecf20Sopenharmony_ci 19548c2ecf20Sopenharmony_ci num_pages = sizeof(pages); 19558c2ecf20Sopenharmony_ci if (!(args->dev->flags & ATA_DFLAG_ZAC)) 19568c2ecf20Sopenharmony_ci num_pages--; 19578c2ecf20Sopenharmony_ci rbuf[3] = num_pages; /* number of supported VPD pages */ 19588c2ecf20Sopenharmony_ci memcpy(rbuf + 4, pages, num_pages); 19598c2ecf20Sopenharmony_ci return 0; 19608c2ecf20Sopenharmony_ci} 19618c2ecf20Sopenharmony_ci 19628c2ecf20Sopenharmony_ci/** 19638c2ecf20Sopenharmony_ci * ata_scsiop_inq_80 - Simulate INQUIRY VPD page 80, device serial number 19648c2ecf20Sopenharmony_ci * @args: device IDENTIFY data / SCSI command of interest. 19658c2ecf20Sopenharmony_ci * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. 19668c2ecf20Sopenharmony_ci * 19678c2ecf20Sopenharmony_ci * Returns ATA device serial number. 19688c2ecf20Sopenharmony_ci * 19698c2ecf20Sopenharmony_ci * LOCKING: 19708c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 19718c2ecf20Sopenharmony_ci */ 19728c2ecf20Sopenharmony_cistatic unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf) 19738c2ecf20Sopenharmony_ci{ 19748c2ecf20Sopenharmony_ci static const u8 hdr[] = { 19758c2ecf20Sopenharmony_ci 0, 19768c2ecf20Sopenharmony_ci 0x80, /* this page code */ 19778c2ecf20Sopenharmony_ci 0, 19788c2ecf20Sopenharmony_ci ATA_ID_SERNO_LEN, /* page len */ 19798c2ecf20Sopenharmony_ci }; 19808c2ecf20Sopenharmony_ci 19818c2ecf20Sopenharmony_ci memcpy(rbuf, hdr, sizeof(hdr)); 19828c2ecf20Sopenharmony_ci ata_id_string(args->id, (unsigned char *) &rbuf[4], 19838c2ecf20Sopenharmony_ci ATA_ID_SERNO, ATA_ID_SERNO_LEN); 19848c2ecf20Sopenharmony_ci return 0; 19858c2ecf20Sopenharmony_ci} 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_ci/** 19888c2ecf20Sopenharmony_ci * ata_scsiop_inq_83 - Simulate INQUIRY VPD page 83, device identity 19898c2ecf20Sopenharmony_ci * @args: device IDENTIFY data / SCSI command of interest. 19908c2ecf20Sopenharmony_ci * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. 19918c2ecf20Sopenharmony_ci * 19928c2ecf20Sopenharmony_ci * Yields two logical unit device identification designators: 19938c2ecf20Sopenharmony_ci * - vendor specific ASCII containing the ATA serial number 19948c2ecf20Sopenharmony_ci * - SAT defined "t10 vendor id based" containing ASCII vendor 19958c2ecf20Sopenharmony_ci * name ("ATA "), model and serial numbers. 19968c2ecf20Sopenharmony_ci * 19978c2ecf20Sopenharmony_ci * LOCKING: 19988c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 19998c2ecf20Sopenharmony_ci */ 20008c2ecf20Sopenharmony_cistatic unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf) 20018c2ecf20Sopenharmony_ci{ 20028c2ecf20Sopenharmony_ci const int sat_model_serial_desc_len = 68; 20038c2ecf20Sopenharmony_ci int num; 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_ci rbuf[1] = 0x83; /* this page code */ 20068c2ecf20Sopenharmony_ci num = 4; 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_ci /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */ 20098c2ecf20Sopenharmony_ci rbuf[num + 0] = 2; 20108c2ecf20Sopenharmony_ci rbuf[num + 3] = ATA_ID_SERNO_LEN; 20118c2ecf20Sopenharmony_ci num += 4; 20128c2ecf20Sopenharmony_ci ata_id_string(args->id, (unsigned char *) rbuf + num, 20138c2ecf20Sopenharmony_ci ATA_ID_SERNO, ATA_ID_SERNO_LEN); 20148c2ecf20Sopenharmony_ci num += ATA_ID_SERNO_LEN; 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_ci /* SAT defined lu model and serial numbers descriptor */ 20178c2ecf20Sopenharmony_ci /* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */ 20188c2ecf20Sopenharmony_ci rbuf[num + 0] = 2; 20198c2ecf20Sopenharmony_ci rbuf[num + 1] = 1; 20208c2ecf20Sopenharmony_ci rbuf[num + 3] = sat_model_serial_desc_len; 20218c2ecf20Sopenharmony_ci num += 4; 20228c2ecf20Sopenharmony_ci memcpy(rbuf + num, "ATA ", 8); 20238c2ecf20Sopenharmony_ci num += 8; 20248c2ecf20Sopenharmony_ci ata_id_string(args->id, (unsigned char *) rbuf + num, ATA_ID_PROD, 20258c2ecf20Sopenharmony_ci ATA_ID_PROD_LEN); 20268c2ecf20Sopenharmony_ci num += ATA_ID_PROD_LEN; 20278c2ecf20Sopenharmony_ci ata_id_string(args->id, (unsigned char *) rbuf + num, ATA_ID_SERNO, 20288c2ecf20Sopenharmony_ci ATA_ID_SERNO_LEN); 20298c2ecf20Sopenharmony_ci num += ATA_ID_SERNO_LEN; 20308c2ecf20Sopenharmony_ci 20318c2ecf20Sopenharmony_ci if (ata_id_has_wwn(args->id)) { 20328c2ecf20Sopenharmony_ci /* SAT defined lu world wide name */ 20338c2ecf20Sopenharmony_ci /* piv=0, assoc=lu, code_set=binary, designator=NAA */ 20348c2ecf20Sopenharmony_ci rbuf[num + 0] = 1; 20358c2ecf20Sopenharmony_ci rbuf[num + 1] = 3; 20368c2ecf20Sopenharmony_ci rbuf[num + 3] = ATA_ID_WWN_LEN; 20378c2ecf20Sopenharmony_ci num += 4; 20388c2ecf20Sopenharmony_ci ata_id_string(args->id, (unsigned char *) rbuf + num, 20398c2ecf20Sopenharmony_ci ATA_ID_WWN, ATA_ID_WWN_LEN); 20408c2ecf20Sopenharmony_ci num += ATA_ID_WWN_LEN; 20418c2ecf20Sopenharmony_ci } 20428c2ecf20Sopenharmony_ci rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */ 20438c2ecf20Sopenharmony_ci return 0; 20448c2ecf20Sopenharmony_ci} 20458c2ecf20Sopenharmony_ci 20468c2ecf20Sopenharmony_ci/** 20478c2ecf20Sopenharmony_ci * ata_scsiop_inq_89 - Simulate INQUIRY VPD page 89, ATA info 20488c2ecf20Sopenharmony_ci * @args: device IDENTIFY data / SCSI command of interest. 20498c2ecf20Sopenharmony_ci * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. 20508c2ecf20Sopenharmony_ci * 20518c2ecf20Sopenharmony_ci * Yields SAT-specified ATA VPD page. 20528c2ecf20Sopenharmony_ci * 20538c2ecf20Sopenharmony_ci * LOCKING: 20548c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 20558c2ecf20Sopenharmony_ci */ 20568c2ecf20Sopenharmony_cistatic unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf) 20578c2ecf20Sopenharmony_ci{ 20588c2ecf20Sopenharmony_ci rbuf[1] = 0x89; /* our page code */ 20598c2ecf20Sopenharmony_ci rbuf[2] = (0x238 >> 8); /* page size fixed at 238h */ 20608c2ecf20Sopenharmony_ci rbuf[3] = (0x238 & 0xff); 20618c2ecf20Sopenharmony_ci 20628c2ecf20Sopenharmony_ci memcpy(&rbuf[8], "linux ", 8); 20638c2ecf20Sopenharmony_ci memcpy(&rbuf[16], "libata ", 16); 20648c2ecf20Sopenharmony_ci memcpy(&rbuf[32], DRV_VERSION, 4); 20658c2ecf20Sopenharmony_ci 20668c2ecf20Sopenharmony_ci rbuf[36] = 0x34; /* force D2H Reg FIS (34h) */ 20678c2ecf20Sopenharmony_ci rbuf[37] = (1 << 7); /* bit 7 indicates Command FIS */ 20688c2ecf20Sopenharmony_ci /* TODO: PMP? */ 20698c2ecf20Sopenharmony_ci 20708c2ecf20Sopenharmony_ci /* we don't store the ATA device signature, so we fake it */ 20718c2ecf20Sopenharmony_ci rbuf[38] = ATA_DRDY; /* really, this is Status reg */ 20728c2ecf20Sopenharmony_ci rbuf[40] = 0x1; 20738c2ecf20Sopenharmony_ci rbuf[48] = 0x1; 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_ci rbuf[56] = ATA_CMD_ID_ATA; 20768c2ecf20Sopenharmony_ci 20778c2ecf20Sopenharmony_ci memcpy(&rbuf[60], &args->id[0], 512); 20788c2ecf20Sopenharmony_ci return 0; 20798c2ecf20Sopenharmony_ci} 20808c2ecf20Sopenharmony_ci 20818c2ecf20Sopenharmony_cistatic unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf) 20828c2ecf20Sopenharmony_ci{ 20838c2ecf20Sopenharmony_ci struct ata_device *dev = args->dev; 20848c2ecf20Sopenharmony_ci u16 min_io_sectors; 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci rbuf[1] = 0xb0; 20878c2ecf20Sopenharmony_ci rbuf[3] = 0x3c; /* required VPD size with unmap support */ 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_ci /* 20908c2ecf20Sopenharmony_ci * Optimal transfer length granularity. 20918c2ecf20Sopenharmony_ci * 20928c2ecf20Sopenharmony_ci * This is always one physical block, but for disks with a smaller 20938c2ecf20Sopenharmony_ci * logical than physical sector size we need to figure out what the 20948c2ecf20Sopenharmony_ci * latter is. 20958c2ecf20Sopenharmony_ci */ 20968c2ecf20Sopenharmony_ci min_io_sectors = 1 << ata_id_log2_per_physical_sector(args->id); 20978c2ecf20Sopenharmony_ci put_unaligned_be16(min_io_sectors, &rbuf[6]); 20988c2ecf20Sopenharmony_ci 20998c2ecf20Sopenharmony_ci /* 21008c2ecf20Sopenharmony_ci * Optimal unmap granularity. 21018c2ecf20Sopenharmony_ci * 21028c2ecf20Sopenharmony_ci * The ATA spec doesn't even know about a granularity or alignment 21038c2ecf20Sopenharmony_ci * for the TRIM command. We can leave away most of the unmap related 21048c2ecf20Sopenharmony_ci * VPD page entries, but we have specifify a granularity to signal 21058c2ecf20Sopenharmony_ci * that we support some form of unmap - in thise case via WRITE SAME 21068c2ecf20Sopenharmony_ci * with the unmap bit set. 21078c2ecf20Sopenharmony_ci */ 21088c2ecf20Sopenharmony_ci if (ata_id_has_trim(args->id)) { 21098c2ecf20Sopenharmony_ci u64 max_blocks = 65535 * ATA_MAX_TRIM_RNUM; 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci if (dev->horkage & ATA_HORKAGE_MAX_TRIM_128M) 21128c2ecf20Sopenharmony_ci max_blocks = 128 << (20 - SECTOR_SHIFT); 21138c2ecf20Sopenharmony_ci 21148c2ecf20Sopenharmony_ci put_unaligned_be64(max_blocks, &rbuf[36]); 21158c2ecf20Sopenharmony_ci put_unaligned_be32(1, &rbuf[28]); 21168c2ecf20Sopenharmony_ci } 21178c2ecf20Sopenharmony_ci 21188c2ecf20Sopenharmony_ci return 0; 21198c2ecf20Sopenharmony_ci} 21208c2ecf20Sopenharmony_ci 21218c2ecf20Sopenharmony_cistatic unsigned int ata_scsiop_inq_b1(struct ata_scsi_args *args, u8 *rbuf) 21228c2ecf20Sopenharmony_ci{ 21238c2ecf20Sopenharmony_ci int form_factor = ata_id_form_factor(args->id); 21248c2ecf20Sopenharmony_ci int media_rotation_rate = ata_id_rotation_rate(args->id); 21258c2ecf20Sopenharmony_ci u8 zoned = ata_id_zoned_cap(args->id); 21268c2ecf20Sopenharmony_ci 21278c2ecf20Sopenharmony_ci rbuf[1] = 0xb1; 21288c2ecf20Sopenharmony_ci rbuf[3] = 0x3c; 21298c2ecf20Sopenharmony_ci rbuf[4] = media_rotation_rate >> 8; 21308c2ecf20Sopenharmony_ci rbuf[5] = media_rotation_rate; 21318c2ecf20Sopenharmony_ci rbuf[7] = form_factor; 21328c2ecf20Sopenharmony_ci if (zoned) 21338c2ecf20Sopenharmony_ci rbuf[8] = (zoned << 4); 21348c2ecf20Sopenharmony_ci 21358c2ecf20Sopenharmony_ci return 0; 21368c2ecf20Sopenharmony_ci} 21378c2ecf20Sopenharmony_ci 21388c2ecf20Sopenharmony_cistatic unsigned int ata_scsiop_inq_b2(struct ata_scsi_args *args, u8 *rbuf) 21398c2ecf20Sopenharmony_ci{ 21408c2ecf20Sopenharmony_ci /* SCSI Thin Provisioning VPD page: SBC-3 rev 22 or later */ 21418c2ecf20Sopenharmony_ci rbuf[1] = 0xb2; 21428c2ecf20Sopenharmony_ci rbuf[3] = 0x4; 21438c2ecf20Sopenharmony_ci rbuf[5] = 1 << 6; /* TPWS */ 21448c2ecf20Sopenharmony_ci 21458c2ecf20Sopenharmony_ci return 0; 21468c2ecf20Sopenharmony_ci} 21478c2ecf20Sopenharmony_ci 21488c2ecf20Sopenharmony_cistatic unsigned int ata_scsiop_inq_b6(struct ata_scsi_args *args, u8 *rbuf) 21498c2ecf20Sopenharmony_ci{ 21508c2ecf20Sopenharmony_ci /* 21518c2ecf20Sopenharmony_ci * zbc-r05 SCSI Zoned Block device characteristics VPD page 21528c2ecf20Sopenharmony_ci */ 21538c2ecf20Sopenharmony_ci rbuf[1] = 0xb6; 21548c2ecf20Sopenharmony_ci rbuf[3] = 0x3C; 21558c2ecf20Sopenharmony_ci 21568c2ecf20Sopenharmony_ci /* 21578c2ecf20Sopenharmony_ci * URSWRZ bit is only meaningful for host-managed ZAC drives 21588c2ecf20Sopenharmony_ci */ 21598c2ecf20Sopenharmony_ci if (args->dev->zac_zoned_cap & 1) 21608c2ecf20Sopenharmony_ci rbuf[4] |= 1; 21618c2ecf20Sopenharmony_ci put_unaligned_be32(args->dev->zac_zones_optimal_open, &rbuf[8]); 21628c2ecf20Sopenharmony_ci put_unaligned_be32(args->dev->zac_zones_optimal_nonseq, &rbuf[12]); 21638c2ecf20Sopenharmony_ci put_unaligned_be32(args->dev->zac_zones_max_open, &rbuf[16]); 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_ci return 0; 21668c2ecf20Sopenharmony_ci} 21678c2ecf20Sopenharmony_ci 21688c2ecf20Sopenharmony_ci/** 21698c2ecf20Sopenharmony_ci * modecpy - Prepare response for MODE SENSE 21708c2ecf20Sopenharmony_ci * @dest: output buffer 21718c2ecf20Sopenharmony_ci * @src: data being copied 21728c2ecf20Sopenharmony_ci * @n: length of mode page 21738c2ecf20Sopenharmony_ci * @changeable: whether changeable parameters are requested 21748c2ecf20Sopenharmony_ci * 21758c2ecf20Sopenharmony_ci * Generate a generic MODE SENSE page for either current or changeable 21768c2ecf20Sopenharmony_ci * parameters. 21778c2ecf20Sopenharmony_ci * 21788c2ecf20Sopenharmony_ci * LOCKING: 21798c2ecf20Sopenharmony_ci * None. 21808c2ecf20Sopenharmony_ci */ 21818c2ecf20Sopenharmony_cistatic void modecpy(u8 *dest, const u8 *src, int n, bool changeable) 21828c2ecf20Sopenharmony_ci{ 21838c2ecf20Sopenharmony_ci if (changeable) { 21848c2ecf20Sopenharmony_ci memcpy(dest, src, 2); 21858c2ecf20Sopenharmony_ci memset(dest + 2, 0, n - 2); 21868c2ecf20Sopenharmony_ci } else { 21878c2ecf20Sopenharmony_ci memcpy(dest, src, n); 21888c2ecf20Sopenharmony_ci } 21898c2ecf20Sopenharmony_ci} 21908c2ecf20Sopenharmony_ci 21918c2ecf20Sopenharmony_ci/** 21928c2ecf20Sopenharmony_ci * ata_msense_caching - Simulate MODE SENSE caching info page 21938c2ecf20Sopenharmony_ci * @id: device IDENTIFY data 21948c2ecf20Sopenharmony_ci * @buf: output buffer 21958c2ecf20Sopenharmony_ci * @changeable: whether changeable parameters are requested 21968c2ecf20Sopenharmony_ci * 21978c2ecf20Sopenharmony_ci * Generate a caching info page, which conditionally indicates 21988c2ecf20Sopenharmony_ci * write caching to the SCSI layer, depending on device 21998c2ecf20Sopenharmony_ci * capabilities. 22008c2ecf20Sopenharmony_ci * 22018c2ecf20Sopenharmony_ci * LOCKING: 22028c2ecf20Sopenharmony_ci * None. 22038c2ecf20Sopenharmony_ci */ 22048c2ecf20Sopenharmony_cistatic unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable) 22058c2ecf20Sopenharmony_ci{ 22068c2ecf20Sopenharmony_ci modecpy(buf, def_cache_mpage, sizeof(def_cache_mpage), changeable); 22078c2ecf20Sopenharmony_ci if (changeable) { 22088c2ecf20Sopenharmony_ci buf[2] |= (1 << 2); /* ata_mselect_caching() */ 22098c2ecf20Sopenharmony_ci } else { 22108c2ecf20Sopenharmony_ci buf[2] |= (ata_id_wcache_enabled(id) << 2); /* write cache enable */ 22118c2ecf20Sopenharmony_ci buf[12] |= (!ata_id_rahead_enabled(id) << 5); /* disable read ahead */ 22128c2ecf20Sopenharmony_ci } 22138c2ecf20Sopenharmony_ci return sizeof(def_cache_mpage); 22148c2ecf20Sopenharmony_ci} 22158c2ecf20Sopenharmony_ci 22168c2ecf20Sopenharmony_ci/** 22178c2ecf20Sopenharmony_ci * ata_msense_control - Simulate MODE SENSE control mode page 22188c2ecf20Sopenharmony_ci * @dev: ATA device of interest 22198c2ecf20Sopenharmony_ci * @buf: output buffer 22208c2ecf20Sopenharmony_ci * @changeable: whether changeable parameters are requested 22218c2ecf20Sopenharmony_ci * 22228c2ecf20Sopenharmony_ci * Generate a generic MODE SENSE control mode page. 22238c2ecf20Sopenharmony_ci * 22248c2ecf20Sopenharmony_ci * LOCKING: 22258c2ecf20Sopenharmony_ci * None. 22268c2ecf20Sopenharmony_ci */ 22278c2ecf20Sopenharmony_cistatic unsigned int ata_msense_control(struct ata_device *dev, u8 *buf, 22288c2ecf20Sopenharmony_ci bool changeable) 22298c2ecf20Sopenharmony_ci{ 22308c2ecf20Sopenharmony_ci modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable); 22318c2ecf20Sopenharmony_ci if (changeable) { 22328c2ecf20Sopenharmony_ci buf[2] |= (1 << 2); /* ata_mselect_control() */ 22338c2ecf20Sopenharmony_ci } else { 22348c2ecf20Sopenharmony_ci bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE); 22358c2ecf20Sopenharmony_ci 22368c2ecf20Sopenharmony_ci buf[2] |= (d_sense << 2); /* descriptor format sense data */ 22378c2ecf20Sopenharmony_ci } 22388c2ecf20Sopenharmony_ci return sizeof(def_control_mpage); 22398c2ecf20Sopenharmony_ci} 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_ci/** 22428c2ecf20Sopenharmony_ci * ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page 22438c2ecf20Sopenharmony_ci * @buf: output buffer 22448c2ecf20Sopenharmony_ci * @changeable: whether changeable parameters are requested 22458c2ecf20Sopenharmony_ci * 22468c2ecf20Sopenharmony_ci * Generate a generic MODE SENSE r/w error recovery page. 22478c2ecf20Sopenharmony_ci * 22488c2ecf20Sopenharmony_ci * LOCKING: 22498c2ecf20Sopenharmony_ci * None. 22508c2ecf20Sopenharmony_ci */ 22518c2ecf20Sopenharmony_cistatic unsigned int ata_msense_rw_recovery(u8 *buf, bool changeable) 22528c2ecf20Sopenharmony_ci{ 22538c2ecf20Sopenharmony_ci modecpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage), 22548c2ecf20Sopenharmony_ci changeable); 22558c2ecf20Sopenharmony_ci return sizeof(def_rw_recovery_mpage); 22568c2ecf20Sopenharmony_ci} 22578c2ecf20Sopenharmony_ci 22588c2ecf20Sopenharmony_ci/* 22598c2ecf20Sopenharmony_ci * We can turn this into a real blacklist if it's needed, for now just 22608c2ecf20Sopenharmony_ci * blacklist any Maxtor BANC1G10 revision firmware 22618c2ecf20Sopenharmony_ci */ 22628c2ecf20Sopenharmony_cistatic int ata_dev_supports_fua(u16 *id) 22638c2ecf20Sopenharmony_ci{ 22648c2ecf20Sopenharmony_ci unsigned char model[ATA_ID_PROD_LEN + 1], fw[ATA_ID_FW_REV_LEN + 1]; 22658c2ecf20Sopenharmony_ci 22668c2ecf20Sopenharmony_ci if (!libata_fua) 22678c2ecf20Sopenharmony_ci return 0; 22688c2ecf20Sopenharmony_ci if (!ata_id_has_fua(id)) 22698c2ecf20Sopenharmony_ci return 0; 22708c2ecf20Sopenharmony_ci 22718c2ecf20Sopenharmony_ci ata_id_c_string(id, model, ATA_ID_PROD, sizeof(model)); 22728c2ecf20Sopenharmony_ci ata_id_c_string(id, fw, ATA_ID_FW_REV, sizeof(fw)); 22738c2ecf20Sopenharmony_ci 22748c2ecf20Sopenharmony_ci if (strcmp(model, "Maxtor")) 22758c2ecf20Sopenharmony_ci return 1; 22768c2ecf20Sopenharmony_ci if (strcmp(fw, "BANC1G10")) 22778c2ecf20Sopenharmony_ci return 1; 22788c2ecf20Sopenharmony_ci 22798c2ecf20Sopenharmony_ci return 0; /* blacklisted */ 22808c2ecf20Sopenharmony_ci} 22818c2ecf20Sopenharmony_ci 22828c2ecf20Sopenharmony_ci/** 22838c2ecf20Sopenharmony_ci * ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands 22848c2ecf20Sopenharmony_ci * @args: device IDENTIFY data / SCSI command of interest. 22858c2ecf20Sopenharmony_ci * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. 22868c2ecf20Sopenharmony_ci * 22878c2ecf20Sopenharmony_ci * Simulate MODE SENSE commands. Assume this is invoked for direct 22888c2ecf20Sopenharmony_ci * access devices (e.g. disks) only. There should be no block 22898c2ecf20Sopenharmony_ci * descriptor for other device types. 22908c2ecf20Sopenharmony_ci * 22918c2ecf20Sopenharmony_ci * LOCKING: 22928c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 22938c2ecf20Sopenharmony_ci */ 22948c2ecf20Sopenharmony_cistatic unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) 22958c2ecf20Sopenharmony_ci{ 22968c2ecf20Sopenharmony_ci struct ata_device *dev = args->dev; 22978c2ecf20Sopenharmony_ci u8 *scsicmd = args->cmd->cmnd, *p = rbuf; 22988c2ecf20Sopenharmony_ci static const u8 sat_blk_desc[] = { 22998c2ecf20Sopenharmony_ci 0, 0, 0, 0, /* number of blocks: sat unspecified */ 23008c2ecf20Sopenharmony_ci 0, 23018c2ecf20Sopenharmony_ci 0, 0x2, 0x0 /* block length: 512 bytes */ 23028c2ecf20Sopenharmony_ci }; 23038c2ecf20Sopenharmony_ci u8 pg, spg; 23048c2ecf20Sopenharmony_ci unsigned int ebd, page_control, six_byte; 23058c2ecf20Sopenharmony_ci u8 dpofua, bp = 0xff; 23068c2ecf20Sopenharmony_ci u16 fp; 23078c2ecf20Sopenharmony_ci 23088c2ecf20Sopenharmony_ci VPRINTK("ENTER\n"); 23098c2ecf20Sopenharmony_ci 23108c2ecf20Sopenharmony_ci six_byte = (scsicmd[0] == MODE_SENSE); 23118c2ecf20Sopenharmony_ci ebd = !(scsicmd[1] & 0x8); /* dbd bit inverted == edb */ 23128c2ecf20Sopenharmony_ci /* 23138c2ecf20Sopenharmony_ci * LLBA bit in msense(10) ignored (compliant) 23148c2ecf20Sopenharmony_ci */ 23158c2ecf20Sopenharmony_ci 23168c2ecf20Sopenharmony_ci page_control = scsicmd[2] >> 6; 23178c2ecf20Sopenharmony_ci switch (page_control) { 23188c2ecf20Sopenharmony_ci case 0: /* current */ 23198c2ecf20Sopenharmony_ci case 1: /* changeable */ 23208c2ecf20Sopenharmony_ci case 2: /* defaults */ 23218c2ecf20Sopenharmony_ci break; /* supported */ 23228c2ecf20Sopenharmony_ci case 3: /* saved */ 23238c2ecf20Sopenharmony_ci goto saving_not_supp; 23248c2ecf20Sopenharmony_ci default: 23258c2ecf20Sopenharmony_ci fp = 2; 23268c2ecf20Sopenharmony_ci bp = 6; 23278c2ecf20Sopenharmony_ci goto invalid_fld; 23288c2ecf20Sopenharmony_ci } 23298c2ecf20Sopenharmony_ci 23308c2ecf20Sopenharmony_ci if (six_byte) 23318c2ecf20Sopenharmony_ci p += 4 + (ebd ? 8 : 0); 23328c2ecf20Sopenharmony_ci else 23338c2ecf20Sopenharmony_ci p += 8 + (ebd ? 8 : 0); 23348c2ecf20Sopenharmony_ci 23358c2ecf20Sopenharmony_ci pg = scsicmd[2] & 0x3f; 23368c2ecf20Sopenharmony_ci spg = scsicmd[3]; 23378c2ecf20Sopenharmony_ci /* 23388c2ecf20Sopenharmony_ci * No mode subpages supported (yet) but asking for _all_ 23398c2ecf20Sopenharmony_ci * subpages may be valid 23408c2ecf20Sopenharmony_ci */ 23418c2ecf20Sopenharmony_ci if (spg && (spg != ALL_SUB_MPAGES)) { 23428c2ecf20Sopenharmony_ci fp = 3; 23438c2ecf20Sopenharmony_ci goto invalid_fld; 23448c2ecf20Sopenharmony_ci } 23458c2ecf20Sopenharmony_ci 23468c2ecf20Sopenharmony_ci switch(pg) { 23478c2ecf20Sopenharmony_ci case RW_RECOVERY_MPAGE: 23488c2ecf20Sopenharmony_ci p += ata_msense_rw_recovery(p, page_control == 1); 23498c2ecf20Sopenharmony_ci break; 23508c2ecf20Sopenharmony_ci 23518c2ecf20Sopenharmony_ci case CACHE_MPAGE: 23528c2ecf20Sopenharmony_ci p += ata_msense_caching(args->id, p, page_control == 1); 23538c2ecf20Sopenharmony_ci break; 23548c2ecf20Sopenharmony_ci 23558c2ecf20Sopenharmony_ci case CONTROL_MPAGE: 23568c2ecf20Sopenharmony_ci p += ata_msense_control(args->dev, p, page_control == 1); 23578c2ecf20Sopenharmony_ci break; 23588c2ecf20Sopenharmony_ci 23598c2ecf20Sopenharmony_ci case ALL_MPAGES: 23608c2ecf20Sopenharmony_ci p += ata_msense_rw_recovery(p, page_control == 1); 23618c2ecf20Sopenharmony_ci p += ata_msense_caching(args->id, p, page_control == 1); 23628c2ecf20Sopenharmony_ci p += ata_msense_control(args->dev, p, page_control == 1); 23638c2ecf20Sopenharmony_ci break; 23648c2ecf20Sopenharmony_ci 23658c2ecf20Sopenharmony_ci default: /* invalid page code */ 23668c2ecf20Sopenharmony_ci fp = 2; 23678c2ecf20Sopenharmony_ci goto invalid_fld; 23688c2ecf20Sopenharmony_ci } 23698c2ecf20Sopenharmony_ci 23708c2ecf20Sopenharmony_ci dpofua = 0; 23718c2ecf20Sopenharmony_ci if (ata_dev_supports_fua(args->id) && (dev->flags & ATA_DFLAG_LBA48) && 23728c2ecf20Sopenharmony_ci (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count)) 23738c2ecf20Sopenharmony_ci dpofua = 1 << 4; 23748c2ecf20Sopenharmony_ci 23758c2ecf20Sopenharmony_ci if (six_byte) { 23768c2ecf20Sopenharmony_ci rbuf[0] = p - rbuf - 1; 23778c2ecf20Sopenharmony_ci rbuf[2] |= dpofua; 23788c2ecf20Sopenharmony_ci if (ebd) { 23798c2ecf20Sopenharmony_ci rbuf[3] = sizeof(sat_blk_desc); 23808c2ecf20Sopenharmony_ci memcpy(rbuf + 4, sat_blk_desc, sizeof(sat_blk_desc)); 23818c2ecf20Sopenharmony_ci } 23828c2ecf20Sopenharmony_ci } else { 23838c2ecf20Sopenharmony_ci unsigned int output_len = p - rbuf - 2; 23848c2ecf20Sopenharmony_ci 23858c2ecf20Sopenharmony_ci rbuf[0] = output_len >> 8; 23868c2ecf20Sopenharmony_ci rbuf[1] = output_len; 23878c2ecf20Sopenharmony_ci rbuf[3] |= dpofua; 23888c2ecf20Sopenharmony_ci if (ebd) { 23898c2ecf20Sopenharmony_ci rbuf[7] = sizeof(sat_blk_desc); 23908c2ecf20Sopenharmony_ci memcpy(rbuf + 8, sat_blk_desc, sizeof(sat_blk_desc)); 23918c2ecf20Sopenharmony_ci } 23928c2ecf20Sopenharmony_ci } 23938c2ecf20Sopenharmony_ci return 0; 23948c2ecf20Sopenharmony_ci 23958c2ecf20Sopenharmony_ciinvalid_fld: 23968c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(dev, args->cmd, fp, bp); 23978c2ecf20Sopenharmony_ci return 1; 23988c2ecf20Sopenharmony_ci 23998c2ecf20Sopenharmony_cisaving_not_supp: 24008c2ecf20Sopenharmony_ci ata_scsi_set_sense(dev, args->cmd, ILLEGAL_REQUEST, 0x39, 0x0); 24018c2ecf20Sopenharmony_ci /* "Saving parameters not supported" */ 24028c2ecf20Sopenharmony_ci return 1; 24038c2ecf20Sopenharmony_ci} 24048c2ecf20Sopenharmony_ci 24058c2ecf20Sopenharmony_ci/** 24068c2ecf20Sopenharmony_ci * ata_scsiop_read_cap - Simulate READ CAPACITY[ 16] commands 24078c2ecf20Sopenharmony_ci * @args: device IDENTIFY data / SCSI command of interest. 24088c2ecf20Sopenharmony_ci * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. 24098c2ecf20Sopenharmony_ci * 24108c2ecf20Sopenharmony_ci * Simulate READ CAPACITY commands. 24118c2ecf20Sopenharmony_ci * 24128c2ecf20Sopenharmony_ci * LOCKING: 24138c2ecf20Sopenharmony_ci * None. 24148c2ecf20Sopenharmony_ci */ 24158c2ecf20Sopenharmony_cistatic unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf) 24168c2ecf20Sopenharmony_ci{ 24178c2ecf20Sopenharmony_ci struct ata_device *dev = args->dev; 24188c2ecf20Sopenharmony_ci u64 last_lba = dev->n_sectors - 1; /* LBA of the last block */ 24198c2ecf20Sopenharmony_ci u32 sector_size; /* physical sector size in bytes */ 24208c2ecf20Sopenharmony_ci u8 log2_per_phys; 24218c2ecf20Sopenharmony_ci u16 lowest_aligned; 24228c2ecf20Sopenharmony_ci 24238c2ecf20Sopenharmony_ci sector_size = ata_id_logical_sector_size(dev->id); 24248c2ecf20Sopenharmony_ci log2_per_phys = ata_id_log2_per_physical_sector(dev->id); 24258c2ecf20Sopenharmony_ci lowest_aligned = ata_id_logical_sector_offset(dev->id, log2_per_phys); 24268c2ecf20Sopenharmony_ci 24278c2ecf20Sopenharmony_ci VPRINTK("ENTER\n"); 24288c2ecf20Sopenharmony_ci 24298c2ecf20Sopenharmony_ci if (args->cmd->cmnd[0] == READ_CAPACITY) { 24308c2ecf20Sopenharmony_ci if (last_lba >= 0xffffffffULL) 24318c2ecf20Sopenharmony_ci last_lba = 0xffffffff; 24328c2ecf20Sopenharmony_ci 24338c2ecf20Sopenharmony_ci /* sector count, 32-bit */ 24348c2ecf20Sopenharmony_ci rbuf[0] = last_lba >> (8 * 3); 24358c2ecf20Sopenharmony_ci rbuf[1] = last_lba >> (8 * 2); 24368c2ecf20Sopenharmony_ci rbuf[2] = last_lba >> (8 * 1); 24378c2ecf20Sopenharmony_ci rbuf[3] = last_lba; 24388c2ecf20Sopenharmony_ci 24398c2ecf20Sopenharmony_ci /* sector size */ 24408c2ecf20Sopenharmony_ci rbuf[4] = sector_size >> (8 * 3); 24418c2ecf20Sopenharmony_ci rbuf[5] = sector_size >> (8 * 2); 24428c2ecf20Sopenharmony_ci rbuf[6] = sector_size >> (8 * 1); 24438c2ecf20Sopenharmony_ci rbuf[7] = sector_size; 24448c2ecf20Sopenharmony_ci } else { 24458c2ecf20Sopenharmony_ci /* sector count, 64-bit */ 24468c2ecf20Sopenharmony_ci rbuf[0] = last_lba >> (8 * 7); 24478c2ecf20Sopenharmony_ci rbuf[1] = last_lba >> (8 * 6); 24488c2ecf20Sopenharmony_ci rbuf[2] = last_lba >> (8 * 5); 24498c2ecf20Sopenharmony_ci rbuf[3] = last_lba >> (8 * 4); 24508c2ecf20Sopenharmony_ci rbuf[4] = last_lba >> (8 * 3); 24518c2ecf20Sopenharmony_ci rbuf[5] = last_lba >> (8 * 2); 24528c2ecf20Sopenharmony_ci rbuf[6] = last_lba >> (8 * 1); 24538c2ecf20Sopenharmony_ci rbuf[7] = last_lba; 24548c2ecf20Sopenharmony_ci 24558c2ecf20Sopenharmony_ci /* sector size */ 24568c2ecf20Sopenharmony_ci rbuf[ 8] = sector_size >> (8 * 3); 24578c2ecf20Sopenharmony_ci rbuf[ 9] = sector_size >> (8 * 2); 24588c2ecf20Sopenharmony_ci rbuf[10] = sector_size >> (8 * 1); 24598c2ecf20Sopenharmony_ci rbuf[11] = sector_size; 24608c2ecf20Sopenharmony_ci 24618c2ecf20Sopenharmony_ci rbuf[12] = 0; 24628c2ecf20Sopenharmony_ci rbuf[13] = log2_per_phys; 24638c2ecf20Sopenharmony_ci rbuf[14] = (lowest_aligned >> 8) & 0x3f; 24648c2ecf20Sopenharmony_ci rbuf[15] = lowest_aligned; 24658c2ecf20Sopenharmony_ci 24668c2ecf20Sopenharmony_ci if (ata_id_has_trim(args->id) && 24678c2ecf20Sopenharmony_ci !(dev->horkage & ATA_HORKAGE_NOTRIM)) { 24688c2ecf20Sopenharmony_ci rbuf[14] |= 0x80; /* LBPME */ 24698c2ecf20Sopenharmony_ci 24708c2ecf20Sopenharmony_ci if (ata_id_has_zero_after_trim(args->id) && 24718c2ecf20Sopenharmony_ci dev->horkage & ATA_HORKAGE_ZERO_AFTER_TRIM) { 24728c2ecf20Sopenharmony_ci ata_dev_info(dev, "Enabling discard_zeroes_data\n"); 24738c2ecf20Sopenharmony_ci rbuf[14] |= 0x40; /* LBPRZ */ 24748c2ecf20Sopenharmony_ci } 24758c2ecf20Sopenharmony_ci } 24768c2ecf20Sopenharmony_ci if (ata_id_zoned_cap(args->id) || 24778c2ecf20Sopenharmony_ci args->dev->class == ATA_DEV_ZAC) 24788c2ecf20Sopenharmony_ci rbuf[12] = (1 << 4); /* RC_BASIS */ 24798c2ecf20Sopenharmony_ci } 24808c2ecf20Sopenharmony_ci return 0; 24818c2ecf20Sopenharmony_ci} 24828c2ecf20Sopenharmony_ci 24838c2ecf20Sopenharmony_ci/** 24848c2ecf20Sopenharmony_ci * ata_scsiop_report_luns - Simulate REPORT LUNS command 24858c2ecf20Sopenharmony_ci * @args: device IDENTIFY data / SCSI command of interest. 24868c2ecf20Sopenharmony_ci * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. 24878c2ecf20Sopenharmony_ci * 24888c2ecf20Sopenharmony_ci * Simulate REPORT LUNS command. 24898c2ecf20Sopenharmony_ci * 24908c2ecf20Sopenharmony_ci * LOCKING: 24918c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 24928c2ecf20Sopenharmony_ci */ 24938c2ecf20Sopenharmony_cistatic unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf) 24948c2ecf20Sopenharmony_ci{ 24958c2ecf20Sopenharmony_ci VPRINTK("ENTER\n"); 24968c2ecf20Sopenharmony_ci rbuf[3] = 8; /* just one lun, LUN 0, size 8 bytes */ 24978c2ecf20Sopenharmony_ci 24988c2ecf20Sopenharmony_ci return 0; 24998c2ecf20Sopenharmony_ci} 25008c2ecf20Sopenharmony_ci 25018c2ecf20Sopenharmony_cistatic void atapi_sense_complete(struct ata_queued_cmd *qc) 25028c2ecf20Sopenharmony_ci{ 25038c2ecf20Sopenharmony_ci if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) { 25048c2ecf20Sopenharmony_ci /* FIXME: not quite right; we don't want the 25058c2ecf20Sopenharmony_ci * translation of taskfile registers into 25068c2ecf20Sopenharmony_ci * a sense descriptors, since that's only 25078c2ecf20Sopenharmony_ci * correct for ATA, not ATAPI 25088c2ecf20Sopenharmony_ci */ 25098c2ecf20Sopenharmony_ci ata_gen_passthru_sense(qc); 25108c2ecf20Sopenharmony_ci } 25118c2ecf20Sopenharmony_ci 25128c2ecf20Sopenharmony_ci ata_qc_done(qc); 25138c2ecf20Sopenharmony_ci} 25148c2ecf20Sopenharmony_ci 25158c2ecf20Sopenharmony_ci/* is it pointless to prefer PIO for "safety reasons"? */ 25168c2ecf20Sopenharmony_cistatic inline int ata_pio_use_silly(struct ata_port *ap) 25178c2ecf20Sopenharmony_ci{ 25188c2ecf20Sopenharmony_ci return (ap->flags & ATA_FLAG_PIO_DMA); 25198c2ecf20Sopenharmony_ci} 25208c2ecf20Sopenharmony_ci 25218c2ecf20Sopenharmony_cistatic void atapi_request_sense(struct ata_queued_cmd *qc) 25228c2ecf20Sopenharmony_ci{ 25238c2ecf20Sopenharmony_ci struct ata_port *ap = qc->ap; 25248c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = qc->scsicmd; 25258c2ecf20Sopenharmony_ci 25268c2ecf20Sopenharmony_ci DPRINTK("ATAPI request sense\n"); 25278c2ecf20Sopenharmony_ci 25288c2ecf20Sopenharmony_ci memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); 25298c2ecf20Sopenharmony_ci 25308c2ecf20Sopenharmony_ci#ifdef CONFIG_ATA_SFF 25318c2ecf20Sopenharmony_ci if (ap->ops->sff_tf_read) 25328c2ecf20Sopenharmony_ci ap->ops->sff_tf_read(ap, &qc->tf); 25338c2ecf20Sopenharmony_ci#endif 25348c2ecf20Sopenharmony_ci 25358c2ecf20Sopenharmony_ci /* fill these in, for the case where they are -not- overwritten */ 25368c2ecf20Sopenharmony_ci cmd->sense_buffer[0] = 0x70; 25378c2ecf20Sopenharmony_ci cmd->sense_buffer[2] = qc->tf.feature >> 4; 25388c2ecf20Sopenharmony_ci 25398c2ecf20Sopenharmony_ci ata_qc_reinit(qc); 25408c2ecf20Sopenharmony_ci 25418c2ecf20Sopenharmony_ci /* setup sg table and init transfer direction */ 25428c2ecf20Sopenharmony_ci sg_init_one(&qc->sgent, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE); 25438c2ecf20Sopenharmony_ci ata_sg_init(qc, &qc->sgent, 1); 25448c2ecf20Sopenharmony_ci qc->dma_dir = DMA_FROM_DEVICE; 25458c2ecf20Sopenharmony_ci 25468c2ecf20Sopenharmony_ci memset(&qc->cdb, 0, qc->dev->cdb_len); 25478c2ecf20Sopenharmony_ci qc->cdb[0] = REQUEST_SENSE; 25488c2ecf20Sopenharmony_ci qc->cdb[4] = SCSI_SENSE_BUFFERSIZE; 25498c2ecf20Sopenharmony_ci 25508c2ecf20Sopenharmony_ci qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; 25518c2ecf20Sopenharmony_ci qc->tf.command = ATA_CMD_PACKET; 25528c2ecf20Sopenharmony_ci 25538c2ecf20Sopenharmony_ci if (ata_pio_use_silly(ap)) { 25548c2ecf20Sopenharmony_ci qc->tf.protocol = ATAPI_PROT_DMA; 25558c2ecf20Sopenharmony_ci qc->tf.feature |= ATAPI_PKT_DMA; 25568c2ecf20Sopenharmony_ci } else { 25578c2ecf20Sopenharmony_ci qc->tf.protocol = ATAPI_PROT_PIO; 25588c2ecf20Sopenharmony_ci qc->tf.lbam = SCSI_SENSE_BUFFERSIZE; 25598c2ecf20Sopenharmony_ci qc->tf.lbah = 0; 25608c2ecf20Sopenharmony_ci } 25618c2ecf20Sopenharmony_ci qc->nbytes = SCSI_SENSE_BUFFERSIZE; 25628c2ecf20Sopenharmony_ci 25638c2ecf20Sopenharmony_ci qc->complete_fn = atapi_sense_complete; 25648c2ecf20Sopenharmony_ci 25658c2ecf20Sopenharmony_ci ata_qc_issue(qc); 25668c2ecf20Sopenharmony_ci 25678c2ecf20Sopenharmony_ci DPRINTK("EXIT\n"); 25688c2ecf20Sopenharmony_ci} 25698c2ecf20Sopenharmony_ci 25708c2ecf20Sopenharmony_ci/* 25718c2ecf20Sopenharmony_ci * ATAPI devices typically report zero for their SCSI version, and sometimes 25728c2ecf20Sopenharmony_ci * deviate from the spec WRT response data format. If SCSI version is 25738c2ecf20Sopenharmony_ci * reported as zero like normal, then we make the following fixups: 25748c2ecf20Sopenharmony_ci * 1) Fake MMC-5 version, to indicate to the Linux scsi midlayer this is a 25758c2ecf20Sopenharmony_ci * modern device. 25768c2ecf20Sopenharmony_ci * 2) Ensure response data format / ATAPI information are always correct. 25778c2ecf20Sopenharmony_ci */ 25788c2ecf20Sopenharmony_cistatic void atapi_fixup_inquiry(struct scsi_cmnd *cmd) 25798c2ecf20Sopenharmony_ci{ 25808c2ecf20Sopenharmony_ci u8 buf[4]; 25818c2ecf20Sopenharmony_ci 25828c2ecf20Sopenharmony_ci sg_copy_to_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf, 4); 25838c2ecf20Sopenharmony_ci if (buf[2] == 0) { 25848c2ecf20Sopenharmony_ci buf[2] = 0x5; 25858c2ecf20Sopenharmony_ci buf[3] = 0x32; 25868c2ecf20Sopenharmony_ci } 25878c2ecf20Sopenharmony_ci sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf, 4); 25888c2ecf20Sopenharmony_ci} 25898c2ecf20Sopenharmony_ci 25908c2ecf20Sopenharmony_cistatic void atapi_qc_complete(struct ata_queued_cmd *qc) 25918c2ecf20Sopenharmony_ci{ 25928c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = qc->scsicmd; 25938c2ecf20Sopenharmony_ci unsigned int err_mask = qc->err_mask; 25948c2ecf20Sopenharmony_ci 25958c2ecf20Sopenharmony_ci VPRINTK("ENTER, err_mask 0x%X\n", err_mask); 25968c2ecf20Sopenharmony_ci 25978c2ecf20Sopenharmony_ci /* handle completion from new EH */ 25988c2ecf20Sopenharmony_ci if (unlikely(qc->ap->ops->error_handler && 25998c2ecf20Sopenharmony_ci (err_mask || qc->flags & ATA_QCFLAG_SENSE_VALID))) { 26008c2ecf20Sopenharmony_ci 26018c2ecf20Sopenharmony_ci if (!(qc->flags & ATA_QCFLAG_SENSE_VALID)) { 26028c2ecf20Sopenharmony_ci /* FIXME: not quite right; we don't want the 26038c2ecf20Sopenharmony_ci * translation of taskfile registers into a 26048c2ecf20Sopenharmony_ci * sense descriptors, since that's only 26058c2ecf20Sopenharmony_ci * correct for ATA, not ATAPI 26068c2ecf20Sopenharmony_ci */ 26078c2ecf20Sopenharmony_ci ata_gen_passthru_sense(qc); 26088c2ecf20Sopenharmony_ci } 26098c2ecf20Sopenharmony_ci 26108c2ecf20Sopenharmony_ci /* SCSI EH automatically locks door if sdev->locked is 26118c2ecf20Sopenharmony_ci * set. Sometimes door lock request continues to 26128c2ecf20Sopenharmony_ci * fail, for example, when no media is present. This 26138c2ecf20Sopenharmony_ci * creates a loop - SCSI EH issues door lock which 26148c2ecf20Sopenharmony_ci * fails and gets invoked again to acquire sense data 26158c2ecf20Sopenharmony_ci * for the failed command. 26168c2ecf20Sopenharmony_ci * 26178c2ecf20Sopenharmony_ci * If door lock fails, always clear sdev->locked to 26188c2ecf20Sopenharmony_ci * avoid this infinite loop. 26198c2ecf20Sopenharmony_ci * 26208c2ecf20Sopenharmony_ci * This may happen before SCSI scan is complete. Make 26218c2ecf20Sopenharmony_ci * sure qc->dev->sdev isn't NULL before dereferencing. 26228c2ecf20Sopenharmony_ci */ 26238c2ecf20Sopenharmony_ci if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL && qc->dev->sdev) 26248c2ecf20Sopenharmony_ci qc->dev->sdev->locked = 0; 26258c2ecf20Sopenharmony_ci 26268c2ecf20Sopenharmony_ci qc->scsicmd->result = SAM_STAT_CHECK_CONDITION; 26278c2ecf20Sopenharmony_ci ata_qc_done(qc); 26288c2ecf20Sopenharmony_ci return; 26298c2ecf20Sopenharmony_ci } 26308c2ecf20Sopenharmony_ci 26318c2ecf20Sopenharmony_ci /* successful completion or old EH failure path */ 26328c2ecf20Sopenharmony_ci if (unlikely(err_mask & AC_ERR_DEV)) { 26338c2ecf20Sopenharmony_ci cmd->result = SAM_STAT_CHECK_CONDITION; 26348c2ecf20Sopenharmony_ci atapi_request_sense(qc); 26358c2ecf20Sopenharmony_ci return; 26368c2ecf20Sopenharmony_ci } else if (unlikely(err_mask)) { 26378c2ecf20Sopenharmony_ci /* FIXME: not quite right; we don't want the 26388c2ecf20Sopenharmony_ci * translation of taskfile registers into 26398c2ecf20Sopenharmony_ci * a sense descriptors, since that's only 26408c2ecf20Sopenharmony_ci * correct for ATA, not ATAPI 26418c2ecf20Sopenharmony_ci */ 26428c2ecf20Sopenharmony_ci ata_gen_passthru_sense(qc); 26438c2ecf20Sopenharmony_ci } else { 26448c2ecf20Sopenharmony_ci if (cmd->cmnd[0] == INQUIRY && (cmd->cmnd[1] & 0x03) == 0) 26458c2ecf20Sopenharmony_ci atapi_fixup_inquiry(cmd); 26468c2ecf20Sopenharmony_ci cmd->result = SAM_STAT_GOOD; 26478c2ecf20Sopenharmony_ci } 26488c2ecf20Sopenharmony_ci 26498c2ecf20Sopenharmony_ci ata_qc_done(qc); 26508c2ecf20Sopenharmony_ci} 26518c2ecf20Sopenharmony_ci/** 26528c2ecf20Sopenharmony_ci * atapi_xlat - Initialize PACKET taskfile 26538c2ecf20Sopenharmony_ci * @qc: command structure to be initialized 26548c2ecf20Sopenharmony_ci * 26558c2ecf20Sopenharmony_ci * LOCKING: 26568c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 26578c2ecf20Sopenharmony_ci * 26588c2ecf20Sopenharmony_ci * RETURNS: 26598c2ecf20Sopenharmony_ci * Zero on success, non-zero on failure. 26608c2ecf20Sopenharmony_ci */ 26618c2ecf20Sopenharmony_cistatic unsigned int atapi_xlat(struct ata_queued_cmd *qc) 26628c2ecf20Sopenharmony_ci{ 26638c2ecf20Sopenharmony_ci struct scsi_cmnd *scmd = qc->scsicmd; 26648c2ecf20Sopenharmony_ci struct ata_device *dev = qc->dev; 26658c2ecf20Sopenharmony_ci int nodata = (scmd->sc_data_direction == DMA_NONE); 26668c2ecf20Sopenharmony_ci int using_pio = !nodata && (dev->flags & ATA_DFLAG_PIO); 26678c2ecf20Sopenharmony_ci unsigned int nbytes; 26688c2ecf20Sopenharmony_ci 26698c2ecf20Sopenharmony_ci memset(qc->cdb, 0, dev->cdb_len); 26708c2ecf20Sopenharmony_ci memcpy(qc->cdb, scmd->cmnd, scmd->cmd_len); 26718c2ecf20Sopenharmony_ci 26728c2ecf20Sopenharmony_ci qc->complete_fn = atapi_qc_complete; 26738c2ecf20Sopenharmony_ci 26748c2ecf20Sopenharmony_ci qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; 26758c2ecf20Sopenharmony_ci if (scmd->sc_data_direction == DMA_TO_DEVICE) { 26768c2ecf20Sopenharmony_ci qc->tf.flags |= ATA_TFLAG_WRITE; 26778c2ecf20Sopenharmony_ci DPRINTK("direction: write\n"); 26788c2ecf20Sopenharmony_ci } 26798c2ecf20Sopenharmony_ci 26808c2ecf20Sopenharmony_ci qc->tf.command = ATA_CMD_PACKET; 26818c2ecf20Sopenharmony_ci ata_qc_set_pc_nbytes(qc); 26828c2ecf20Sopenharmony_ci 26838c2ecf20Sopenharmony_ci /* check whether ATAPI DMA is safe */ 26848c2ecf20Sopenharmony_ci if (!nodata && !using_pio && atapi_check_dma(qc)) 26858c2ecf20Sopenharmony_ci using_pio = 1; 26868c2ecf20Sopenharmony_ci 26878c2ecf20Sopenharmony_ci /* Some controller variants snoop this value for Packet 26888c2ecf20Sopenharmony_ci * transfers to do state machine and FIFO management. Thus we 26898c2ecf20Sopenharmony_ci * want to set it properly, and for DMA where it is 26908c2ecf20Sopenharmony_ci * effectively meaningless. 26918c2ecf20Sopenharmony_ci */ 26928c2ecf20Sopenharmony_ci nbytes = min(ata_qc_raw_nbytes(qc), (unsigned int)63 * 1024); 26938c2ecf20Sopenharmony_ci 26948c2ecf20Sopenharmony_ci /* Most ATAPI devices which honor transfer chunk size don't 26958c2ecf20Sopenharmony_ci * behave according to the spec when odd chunk size which 26968c2ecf20Sopenharmony_ci * matches the transfer length is specified. If the number of 26978c2ecf20Sopenharmony_ci * bytes to transfer is 2n+1. According to the spec, what 26988c2ecf20Sopenharmony_ci * should happen is to indicate that 2n+1 is going to be 26998c2ecf20Sopenharmony_ci * transferred and transfer 2n+2 bytes where the last byte is 27008c2ecf20Sopenharmony_ci * padding. 27018c2ecf20Sopenharmony_ci * 27028c2ecf20Sopenharmony_ci * In practice, this doesn't happen. ATAPI devices first 27038c2ecf20Sopenharmony_ci * indicate and transfer 2n bytes and then indicate and 27048c2ecf20Sopenharmony_ci * transfer 2 bytes where the last byte is padding. 27058c2ecf20Sopenharmony_ci * 27068c2ecf20Sopenharmony_ci * This inconsistency confuses several controllers which 27078c2ecf20Sopenharmony_ci * perform PIO using DMA such as Intel AHCIs and sil3124/32. 27088c2ecf20Sopenharmony_ci * These controllers use actual number of transferred bytes to 27098c2ecf20Sopenharmony_ci * update DMA pointer and transfer of 4n+2 bytes make those 27108c2ecf20Sopenharmony_ci * controller push DMA pointer by 4n+4 bytes because SATA data 27118c2ecf20Sopenharmony_ci * FISes are aligned to 4 bytes. This causes data corruption 27128c2ecf20Sopenharmony_ci * and buffer overrun. 27138c2ecf20Sopenharmony_ci * 27148c2ecf20Sopenharmony_ci * Always setting nbytes to even number solves this problem 27158c2ecf20Sopenharmony_ci * because then ATAPI devices don't have to split data at 2n 27168c2ecf20Sopenharmony_ci * boundaries. 27178c2ecf20Sopenharmony_ci */ 27188c2ecf20Sopenharmony_ci if (nbytes & 0x1) 27198c2ecf20Sopenharmony_ci nbytes++; 27208c2ecf20Sopenharmony_ci 27218c2ecf20Sopenharmony_ci qc->tf.lbam = (nbytes & 0xFF); 27228c2ecf20Sopenharmony_ci qc->tf.lbah = (nbytes >> 8); 27238c2ecf20Sopenharmony_ci 27248c2ecf20Sopenharmony_ci if (nodata) 27258c2ecf20Sopenharmony_ci qc->tf.protocol = ATAPI_PROT_NODATA; 27268c2ecf20Sopenharmony_ci else if (using_pio) 27278c2ecf20Sopenharmony_ci qc->tf.protocol = ATAPI_PROT_PIO; 27288c2ecf20Sopenharmony_ci else { 27298c2ecf20Sopenharmony_ci /* DMA data xfer */ 27308c2ecf20Sopenharmony_ci qc->tf.protocol = ATAPI_PROT_DMA; 27318c2ecf20Sopenharmony_ci qc->tf.feature |= ATAPI_PKT_DMA; 27328c2ecf20Sopenharmony_ci 27338c2ecf20Sopenharmony_ci if ((dev->flags & ATA_DFLAG_DMADIR) && 27348c2ecf20Sopenharmony_ci (scmd->sc_data_direction != DMA_TO_DEVICE)) 27358c2ecf20Sopenharmony_ci /* some SATA bridges need us to indicate data xfer direction */ 27368c2ecf20Sopenharmony_ci qc->tf.feature |= ATAPI_DMADIR; 27378c2ecf20Sopenharmony_ci } 27388c2ecf20Sopenharmony_ci 27398c2ecf20Sopenharmony_ci 27408c2ecf20Sopenharmony_ci /* FIXME: We need to translate 0x05 READ_BLOCK_LIMITS to a MODE_SENSE 27418c2ecf20Sopenharmony_ci as ATAPI tape drives don't get this right otherwise */ 27428c2ecf20Sopenharmony_ci return 0; 27438c2ecf20Sopenharmony_ci} 27448c2ecf20Sopenharmony_ci 27458c2ecf20Sopenharmony_cistatic struct ata_device *ata_find_dev(struct ata_port *ap, unsigned int devno) 27468c2ecf20Sopenharmony_ci{ 27478c2ecf20Sopenharmony_ci /* 27488c2ecf20Sopenharmony_ci * For the non-PMP case, ata_link_max_devices() returns 1 (SATA case), 27498c2ecf20Sopenharmony_ci * or 2 (IDE master + slave case). However, the former case includes 27508c2ecf20Sopenharmony_ci * libsas hosted devices which are numbered per scsi host, leading 27518c2ecf20Sopenharmony_ci * to devno potentially being larger than 0 but with each struct 27528c2ecf20Sopenharmony_ci * ata_device having its own struct ata_port and struct ata_link. 27538c2ecf20Sopenharmony_ci * To accommodate these, ignore devno and always use device number 0. 27548c2ecf20Sopenharmony_ci */ 27558c2ecf20Sopenharmony_ci if (likely(!sata_pmp_attached(ap))) { 27568c2ecf20Sopenharmony_ci int link_max_devices = ata_link_max_devices(&ap->link); 27578c2ecf20Sopenharmony_ci 27588c2ecf20Sopenharmony_ci if (link_max_devices == 1) 27598c2ecf20Sopenharmony_ci return &ap->link.device[0]; 27608c2ecf20Sopenharmony_ci 27618c2ecf20Sopenharmony_ci if (devno < link_max_devices) 27628c2ecf20Sopenharmony_ci return &ap->link.device[devno]; 27638c2ecf20Sopenharmony_ci 27648c2ecf20Sopenharmony_ci return NULL; 27658c2ecf20Sopenharmony_ci } 27668c2ecf20Sopenharmony_ci 27678c2ecf20Sopenharmony_ci /* 27688c2ecf20Sopenharmony_ci * For PMP-attached devices, the device number corresponds to C 27698c2ecf20Sopenharmony_ci * (channel) of SCSI [H:C:I:L], indicating the port pmp link 27708c2ecf20Sopenharmony_ci * for the device. 27718c2ecf20Sopenharmony_ci */ 27728c2ecf20Sopenharmony_ci if (devno < ap->nr_pmp_links) 27738c2ecf20Sopenharmony_ci return &ap->pmp_link[devno].device[0]; 27748c2ecf20Sopenharmony_ci 27758c2ecf20Sopenharmony_ci return NULL; 27768c2ecf20Sopenharmony_ci} 27778c2ecf20Sopenharmony_ci 27788c2ecf20Sopenharmony_cistatic struct ata_device *__ata_scsi_find_dev(struct ata_port *ap, 27798c2ecf20Sopenharmony_ci const struct scsi_device *scsidev) 27808c2ecf20Sopenharmony_ci{ 27818c2ecf20Sopenharmony_ci int devno; 27828c2ecf20Sopenharmony_ci 27838c2ecf20Sopenharmony_ci /* skip commands not addressed to targets we simulate */ 27848c2ecf20Sopenharmony_ci if (!sata_pmp_attached(ap)) { 27858c2ecf20Sopenharmony_ci if (unlikely(scsidev->channel || scsidev->lun)) 27868c2ecf20Sopenharmony_ci return NULL; 27878c2ecf20Sopenharmony_ci devno = scsidev->id; 27888c2ecf20Sopenharmony_ci } else { 27898c2ecf20Sopenharmony_ci if (unlikely(scsidev->id || scsidev->lun)) 27908c2ecf20Sopenharmony_ci return NULL; 27918c2ecf20Sopenharmony_ci devno = scsidev->channel; 27928c2ecf20Sopenharmony_ci } 27938c2ecf20Sopenharmony_ci 27948c2ecf20Sopenharmony_ci return ata_find_dev(ap, devno); 27958c2ecf20Sopenharmony_ci} 27968c2ecf20Sopenharmony_ci 27978c2ecf20Sopenharmony_ci/** 27988c2ecf20Sopenharmony_ci * ata_scsi_find_dev - lookup ata_device from scsi_cmnd 27998c2ecf20Sopenharmony_ci * @ap: ATA port to which the device is attached 28008c2ecf20Sopenharmony_ci * @scsidev: SCSI device from which we derive the ATA device 28018c2ecf20Sopenharmony_ci * 28028c2ecf20Sopenharmony_ci * Given various information provided in struct scsi_cmnd, 28038c2ecf20Sopenharmony_ci * map that onto an ATA bus, and using that mapping 28048c2ecf20Sopenharmony_ci * determine which ata_device is associated with the 28058c2ecf20Sopenharmony_ci * SCSI command to be sent. 28068c2ecf20Sopenharmony_ci * 28078c2ecf20Sopenharmony_ci * LOCKING: 28088c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 28098c2ecf20Sopenharmony_ci * 28108c2ecf20Sopenharmony_ci * RETURNS: 28118c2ecf20Sopenharmony_ci * Associated ATA device, or %NULL if not found. 28128c2ecf20Sopenharmony_ci */ 28138c2ecf20Sopenharmony_cistruct ata_device * 28148c2ecf20Sopenharmony_ciata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev) 28158c2ecf20Sopenharmony_ci{ 28168c2ecf20Sopenharmony_ci struct ata_device *dev = __ata_scsi_find_dev(ap, scsidev); 28178c2ecf20Sopenharmony_ci 28188c2ecf20Sopenharmony_ci if (unlikely(!dev || !ata_dev_enabled(dev))) 28198c2ecf20Sopenharmony_ci return NULL; 28208c2ecf20Sopenharmony_ci 28218c2ecf20Sopenharmony_ci return dev; 28228c2ecf20Sopenharmony_ci} 28238c2ecf20Sopenharmony_ci 28248c2ecf20Sopenharmony_ci/* 28258c2ecf20Sopenharmony_ci * ata_scsi_map_proto - Map pass-thru protocol value to taskfile value. 28268c2ecf20Sopenharmony_ci * @byte1: Byte 1 from pass-thru CDB. 28278c2ecf20Sopenharmony_ci * 28288c2ecf20Sopenharmony_ci * RETURNS: 28298c2ecf20Sopenharmony_ci * ATA_PROT_UNKNOWN if mapping failed/unimplemented, protocol otherwise. 28308c2ecf20Sopenharmony_ci */ 28318c2ecf20Sopenharmony_cistatic u8 28328c2ecf20Sopenharmony_ciata_scsi_map_proto(u8 byte1) 28338c2ecf20Sopenharmony_ci{ 28348c2ecf20Sopenharmony_ci switch((byte1 & 0x1e) >> 1) { 28358c2ecf20Sopenharmony_ci case 3: /* Non-data */ 28368c2ecf20Sopenharmony_ci return ATA_PROT_NODATA; 28378c2ecf20Sopenharmony_ci 28388c2ecf20Sopenharmony_ci case 6: /* DMA */ 28398c2ecf20Sopenharmony_ci case 10: /* UDMA Data-in */ 28408c2ecf20Sopenharmony_ci case 11: /* UDMA Data-Out */ 28418c2ecf20Sopenharmony_ci return ATA_PROT_DMA; 28428c2ecf20Sopenharmony_ci 28438c2ecf20Sopenharmony_ci case 4: /* PIO Data-in */ 28448c2ecf20Sopenharmony_ci case 5: /* PIO Data-out */ 28458c2ecf20Sopenharmony_ci return ATA_PROT_PIO; 28468c2ecf20Sopenharmony_ci 28478c2ecf20Sopenharmony_ci case 12: /* FPDMA */ 28488c2ecf20Sopenharmony_ci return ATA_PROT_NCQ; 28498c2ecf20Sopenharmony_ci 28508c2ecf20Sopenharmony_ci case 0: /* Hard Reset */ 28518c2ecf20Sopenharmony_ci case 1: /* SRST */ 28528c2ecf20Sopenharmony_ci case 8: /* Device Diagnostic */ 28538c2ecf20Sopenharmony_ci case 9: /* Device Reset */ 28548c2ecf20Sopenharmony_ci case 7: /* DMA Queued */ 28558c2ecf20Sopenharmony_ci case 15: /* Return Response Info */ 28568c2ecf20Sopenharmony_ci default: /* Reserved */ 28578c2ecf20Sopenharmony_ci break; 28588c2ecf20Sopenharmony_ci } 28598c2ecf20Sopenharmony_ci 28608c2ecf20Sopenharmony_ci return ATA_PROT_UNKNOWN; 28618c2ecf20Sopenharmony_ci} 28628c2ecf20Sopenharmony_ci 28638c2ecf20Sopenharmony_ci/** 28648c2ecf20Sopenharmony_ci * ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile 28658c2ecf20Sopenharmony_ci * @qc: command structure to be initialized 28668c2ecf20Sopenharmony_ci * 28678c2ecf20Sopenharmony_ci * Handles either 12, 16, or 32-byte versions of the CDB. 28688c2ecf20Sopenharmony_ci * 28698c2ecf20Sopenharmony_ci * RETURNS: 28708c2ecf20Sopenharmony_ci * Zero on success, non-zero on failure. 28718c2ecf20Sopenharmony_ci */ 28728c2ecf20Sopenharmony_cistatic unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) 28738c2ecf20Sopenharmony_ci{ 28748c2ecf20Sopenharmony_ci struct ata_taskfile *tf = &(qc->tf); 28758c2ecf20Sopenharmony_ci struct scsi_cmnd *scmd = qc->scsicmd; 28768c2ecf20Sopenharmony_ci struct ata_device *dev = qc->dev; 28778c2ecf20Sopenharmony_ci const u8 *cdb = scmd->cmnd; 28788c2ecf20Sopenharmony_ci u16 fp; 28798c2ecf20Sopenharmony_ci u16 cdb_offset = 0; 28808c2ecf20Sopenharmony_ci 28818c2ecf20Sopenharmony_ci /* 7Fh variable length cmd means a ata pass-thru(32) */ 28828c2ecf20Sopenharmony_ci if (cdb[0] == VARIABLE_LENGTH_CMD) 28838c2ecf20Sopenharmony_ci cdb_offset = 9; 28848c2ecf20Sopenharmony_ci 28858c2ecf20Sopenharmony_ci tf->protocol = ata_scsi_map_proto(cdb[1 + cdb_offset]); 28868c2ecf20Sopenharmony_ci if (tf->protocol == ATA_PROT_UNKNOWN) { 28878c2ecf20Sopenharmony_ci fp = 1; 28888c2ecf20Sopenharmony_ci goto invalid_fld; 28898c2ecf20Sopenharmony_ci } 28908c2ecf20Sopenharmony_ci 28918c2ecf20Sopenharmony_ci if ((cdb[2 + cdb_offset] & 0x3) == 0) { 28928c2ecf20Sopenharmony_ci /* 28938c2ecf20Sopenharmony_ci * When T_LENGTH is zero (No data is transferred), dir should 28948c2ecf20Sopenharmony_ci * be DMA_NONE. 28958c2ecf20Sopenharmony_ci */ 28968c2ecf20Sopenharmony_ci if (scmd->sc_data_direction != DMA_NONE) { 28978c2ecf20Sopenharmony_ci fp = 2 + cdb_offset; 28988c2ecf20Sopenharmony_ci goto invalid_fld; 28998c2ecf20Sopenharmony_ci } 29008c2ecf20Sopenharmony_ci 29018c2ecf20Sopenharmony_ci if (ata_is_ncq(tf->protocol)) 29028c2ecf20Sopenharmony_ci tf->protocol = ATA_PROT_NCQ_NODATA; 29038c2ecf20Sopenharmony_ci } 29048c2ecf20Sopenharmony_ci 29058c2ecf20Sopenharmony_ci /* enable LBA */ 29068c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_LBA; 29078c2ecf20Sopenharmony_ci 29088c2ecf20Sopenharmony_ci /* 29098c2ecf20Sopenharmony_ci * 12 and 16 byte CDBs use different offsets to 29108c2ecf20Sopenharmony_ci * provide the various register values. 29118c2ecf20Sopenharmony_ci */ 29128c2ecf20Sopenharmony_ci if (cdb[0] == ATA_16) { 29138c2ecf20Sopenharmony_ci /* 29148c2ecf20Sopenharmony_ci * 16-byte CDB - may contain extended commands. 29158c2ecf20Sopenharmony_ci * 29168c2ecf20Sopenharmony_ci * If that is the case, copy the upper byte register values. 29178c2ecf20Sopenharmony_ci */ 29188c2ecf20Sopenharmony_ci if (cdb[1] & 0x01) { 29198c2ecf20Sopenharmony_ci tf->hob_feature = cdb[3]; 29208c2ecf20Sopenharmony_ci tf->hob_nsect = cdb[5]; 29218c2ecf20Sopenharmony_ci tf->hob_lbal = cdb[7]; 29228c2ecf20Sopenharmony_ci tf->hob_lbam = cdb[9]; 29238c2ecf20Sopenharmony_ci tf->hob_lbah = cdb[11]; 29248c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_LBA48; 29258c2ecf20Sopenharmony_ci } else 29268c2ecf20Sopenharmony_ci tf->flags &= ~ATA_TFLAG_LBA48; 29278c2ecf20Sopenharmony_ci 29288c2ecf20Sopenharmony_ci /* 29298c2ecf20Sopenharmony_ci * Always copy low byte, device and command registers. 29308c2ecf20Sopenharmony_ci */ 29318c2ecf20Sopenharmony_ci tf->feature = cdb[4]; 29328c2ecf20Sopenharmony_ci tf->nsect = cdb[6]; 29338c2ecf20Sopenharmony_ci tf->lbal = cdb[8]; 29348c2ecf20Sopenharmony_ci tf->lbam = cdb[10]; 29358c2ecf20Sopenharmony_ci tf->lbah = cdb[12]; 29368c2ecf20Sopenharmony_ci tf->device = cdb[13]; 29378c2ecf20Sopenharmony_ci tf->command = cdb[14]; 29388c2ecf20Sopenharmony_ci } else if (cdb[0] == ATA_12) { 29398c2ecf20Sopenharmony_ci /* 29408c2ecf20Sopenharmony_ci * 12-byte CDB - incapable of extended commands. 29418c2ecf20Sopenharmony_ci */ 29428c2ecf20Sopenharmony_ci tf->flags &= ~ATA_TFLAG_LBA48; 29438c2ecf20Sopenharmony_ci 29448c2ecf20Sopenharmony_ci tf->feature = cdb[3]; 29458c2ecf20Sopenharmony_ci tf->nsect = cdb[4]; 29468c2ecf20Sopenharmony_ci tf->lbal = cdb[5]; 29478c2ecf20Sopenharmony_ci tf->lbam = cdb[6]; 29488c2ecf20Sopenharmony_ci tf->lbah = cdb[7]; 29498c2ecf20Sopenharmony_ci tf->device = cdb[8]; 29508c2ecf20Sopenharmony_ci tf->command = cdb[9]; 29518c2ecf20Sopenharmony_ci } else { 29528c2ecf20Sopenharmony_ci /* 29538c2ecf20Sopenharmony_ci * 32-byte CDB - may contain extended command fields. 29548c2ecf20Sopenharmony_ci * 29558c2ecf20Sopenharmony_ci * If that is the case, copy the upper byte register values. 29568c2ecf20Sopenharmony_ci */ 29578c2ecf20Sopenharmony_ci if (cdb[10] & 0x01) { 29588c2ecf20Sopenharmony_ci tf->hob_feature = cdb[20]; 29598c2ecf20Sopenharmony_ci tf->hob_nsect = cdb[22]; 29608c2ecf20Sopenharmony_ci tf->hob_lbal = cdb[16]; 29618c2ecf20Sopenharmony_ci tf->hob_lbam = cdb[15]; 29628c2ecf20Sopenharmony_ci tf->hob_lbah = cdb[14]; 29638c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_LBA48; 29648c2ecf20Sopenharmony_ci } else 29658c2ecf20Sopenharmony_ci tf->flags &= ~ATA_TFLAG_LBA48; 29668c2ecf20Sopenharmony_ci 29678c2ecf20Sopenharmony_ci tf->feature = cdb[21]; 29688c2ecf20Sopenharmony_ci tf->nsect = cdb[23]; 29698c2ecf20Sopenharmony_ci tf->lbal = cdb[19]; 29708c2ecf20Sopenharmony_ci tf->lbam = cdb[18]; 29718c2ecf20Sopenharmony_ci tf->lbah = cdb[17]; 29728c2ecf20Sopenharmony_ci tf->device = cdb[24]; 29738c2ecf20Sopenharmony_ci tf->command = cdb[25]; 29748c2ecf20Sopenharmony_ci tf->auxiliary = get_unaligned_be32(&cdb[28]); 29758c2ecf20Sopenharmony_ci } 29768c2ecf20Sopenharmony_ci 29778c2ecf20Sopenharmony_ci /* For NCQ commands copy the tag value */ 29788c2ecf20Sopenharmony_ci if (ata_is_ncq(tf->protocol)) 29798c2ecf20Sopenharmony_ci tf->nsect = qc->hw_tag << 3; 29808c2ecf20Sopenharmony_ci 29818c2ecf20Sopenharmony_ci /* enforce correct master/slave bit */ 29828c2ecf20Sopenharmony_ci tf->device = dev->devno ? 29838c2ecf20Sopenharmony_ci tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1; 29848c2ecf20Sopenharmony_ci 29858c2ecf20Sopenharmony_ci switch (tf->command) { 29868c2ecf20Sopenharmony_ci /* READ/WRITE LONG use a non-standard sect_size */ 29878c2ecf20Sopenharmony_ci case ATA_CMD_READ_LONG: 29888c2ecf20Sopenharmony_ci case ATA_CMD_READ_LONG_ONCE: 29898c2ecf20Sopenharmony_ci case ATA_CMD_WRITE_LONG: 29908c2ecf20Sopenharmony_ci case ATA_CMD_WRITE_LONG_ONCE: 29918c2ecf20Sopenharmony_ci if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1) { 29928c2ecf20Sopenharmony_ci fp = 1; 29938c2ecf20Sopenharmony_ci goto invalid_fld; 29948c2ecf20Sopenharmony_ci } 29958c2ecf20Sopenharmony_ci qc->sect_size = scsi_bufflen(scmd); 29968c2ecf20Sopenharmony_ci break; 29978c2ecf20Sopenharmony_ci 29988c2ecf20Sopenharmony_ci /* commands using reported Logical Block size (e.g. 512 or 4K) */ 29998c2ecf20Sopenharmony_ci case ATA_CMD_CFA_WRITE_NE: 30008c2ecf20Sopenharmony_ci case ATA_CMD_CFA_TRANS_SECT: 30018c2ecf20Sopenharmony_ci case ATA_CMD_CFA_WRITE_MULT_NE: 30028c2ecf20Sopenharmony_ci /* XXX: case ATA_CMD_CFA_WRITE_SECTORS_WITHOUT_ERASE: */ 30038c2ecf20Sopenharmony_ci case ATA_CMD_READ: 30048c2ecf20Sopenharmony_ci case ATA_CMD_READ_EXT: 30058c2ecf20Sopenharmony_ci case ATA_CMD_READ_QUEUED: 30068c2ecf20Sopenharmony_ci /* XXX: case ATA_CMD_READ_QUEUED_EXT: */ 30078c2ecf20Sopenharmony_ci case ATA_CMD_FPDMA_READ: 30088c2ecf20Sopenharmony_ci case ATA_CMD_READ_MULTI: 30098c2ecf20Sopenharmony_ci case ATA_CMD_READ_MULTI_EXT: 30108c2ecf20Sopenharmony_ci case ATA_CMD_PIO_READ: 30118c2ecf20Sopenharmony_ci case ATA_CMD_PIO_READ_EXT: 30128c2ecf20Sopenharmony_ci case ATA_CMD_READ_STREAM_DMA_EXT: 30138c2ecf20Sopenharmony_ci case ATA_CMD_READ_STREAM_EXT: 30148c2ecf20Sopenharmony_ci case ATA_CMD_VERIFY: 30158c2ecf20Sopenharmony_ci case ATA_CMD_VERIFY_EXT: 30168c2ecf20Sopenharmony_ci case ATA_CMD_WRITE: 30178c2ecf20Sopenharmony_ci case ATA_CMD_WRITE_EXT: 30188c2ecf20Sopenharmony_ci case ATA_CMD_WRITE_FUA_EXT: 30198c2ecf20Sopenharmony_ci case ATA_CMD_WRITE_QUEUED: 30208c2ecf20Sopenharmony_ci case ATA_CMD_WRITE_QUEUED_FUA_EXT: 30218c2ecf20Sopenharmony_ci case ATA_CMD_FPDMA_WRITE: 30228c2ecf20Sopenharmony_ci case ATA_CMD_WRITE_MULTI: 30238c2ecf20Sopenharmony_ci case ATA_CMD_WRITE_MULTI_EXT: 30248c2ecf20Sopenharmony_ci case ATA_CMD_WRITE_MULTI_FUA_EXT: 30258c2ecf20Sopenharmony_ci case ATA_CMD_PIO_WRITE: 30268c2ecf20Sopenharmony_ci case ATA_CMD_PIO_WRITE_EXT: 30278c2ecf20Sopenharmony_ci case ATA_CMD_WRITE_STREAM_DMA_EXT: 30288c2ecf20Sopenharmony_ci case ATA_CMD_WRITE_STREAM_EXT: 30298c2ecf20Sopenharmony_ci qc->sect_size = scmd->device->sector_size; 30308c2ecf20Sopenharmony_ci break; 30318c2ecf20Sopenharmony_ci 30328c2ecf20Sopenharmony_ci /* Everything else uses 512 byte "sectors" */ 30338c2ecf20Sopenharmony_ci default: 30348c2ecf20Sopenharmony_ci qc->sect_size = ATA_SECT_SIZE; 30358c2ecf20Sopenharmony_ci } 30368c2ecf20Sopenharmony_ci 30378c2ecf20Sopenharmony_ci /* 30388c2ecf20Sopenharmony_ci * Set flags so that all registers will be written, pass on 30398c2ecf20Sopenharmony_ci * write indication (used for PIO/DMA setup), result TF is 30408c2ecf20Sopenharmony_ci * copied back and we don't whine too much about its failure. 30418c2ecf20Sopenharmony_ci */ 30428c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; 30438c2ecf20Sopenharmony_ci if (scmd->sc_data_direction == DMA_TO_DEVICE) 30448c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_WRITE; 30458c2ecf20Sopenharmony_ci 30468c2ecf20Sopenharmony_ci qc->flags |= ATA_QCFLAG_RESULT_TF | ATA_QCFLAG_QUIET; 30478c2ecf20Sopenharmony_ci 30488c2ecf20Sopenharmony_ci /* 30498c2ecf20Sopenharmony_ci * Set transfer length. 30508c2ecf20Sopenharmony_ci * 30518c2ecf20Sopenharmony_ci * TODO: find out if we need to do more here to 30528c2ecf20Sopenharmony_ci * cover scatter/gather case. 30538c2ecf20Sopenharmony_ci */ 30548c2ecf20Sopenharmony_ci ata_qc_set_pc_nbytes(qc); 30558c2ecf20Sopenharmony_ci 30568c2ecf20Sopenharmony_ci /* We may not issue DMA commands if no DMA mode is set */ 30578c2ecf20Sopenharmony_ci if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0) { 30588c2ecf20Sopenharmony_ci fp = 1; 30598c2ecf20Sopenharmony_ci goto invalid_fld; 30608c2ecf20Sopenharmony_ci } 30618c2ecf20Sopenharmony_ci 30628c2ecf20Sopenharmony_ci /* We may not issue NCQ commands to devices not supporting NCQ */ 30638c2ecf20Sopenharmony_ci if (ata_is_ncq(tf->protocol) && !ata_ncq_enabled(dev)) { 30648c2ecf20Sopenharmony_ci fp = 1; 30658c2ecf20Sopenharmony_ci goto invalid_fld; 30668c2ecf20Sopenharmony_ci } 30678c2ecf20Sopenharmony_ci 30688c2ecf20Sopenharmony_ci /* sanity check for pio multi commands */ 30698c2ecf20Sopenharmony_ci if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf)) { 30708c2ecf20Sopenharmony_ci fp = 1; 30718c2ecf20Sopenharmony_ci goto invalid_fld; 30728c2ecf20Sopenharmony_ci } 30738c2ecf20Sopenharmony_ci 30748c2ecf20Sopenharmony_ci if (is_multi_taskfile(tf)) { 30758c2ecf20Sopenharmony_ci unsigned int multi_count = 1 << (cdb[1] >> 5); 30768c2ecf20Sopenharmony_ci 30778c2ecf20Sopenharmony_ci /* compare the passed through multi_count 30788c2ecf20Sopenharmony_ci * with the cached multi_count of libata 30798c2ecf20Sopenharmony_ci */ 30808c2ecf20Sopenharmony_ci if (multi_count != dev->multi_count) 30818c2ecf20Sopenharmony_ci ata_dev_warn(dev, "invalid multi_count %u ignored\n", 30828c2ecf20Sopenharmony_ci multi_count); 30838c2ecf20Sopenharmony_ci } 30848c2ecf20Sopenharmony_ci 30858c2ecf20Sopenharmony_ci /* 30868c2ecf20Sopenharmony_ci * Filter SET_FEATURES - XFER MODE command -- otherwise, 30878c2ecf20Sopenharmony_ci * SET_FEATURES - XFER MODE must be preceded/succeeded 30888c2ecf20Sopenharmony_ci * by an update to hardware-specific registers for each 30898c2ecf20Sopenharmony_ci * controller (i.e. the reason for ->set_piomode(), 30908c2ecf20Sopenharmony_ci * ->set_dmamode(), and ->post_set_mode() hooks). 30918c2ecf20Sopenharmony_ci */ 30928c2ecf20Sopenharmony_ci if (tf->command == ATA_CMD_SET_FEATURES && 30938c2ecf20Sopenharmony_ci tf->feature == SETFEATURES_XFER) { 30948c2ecf20Sopenharmony_ci fp = (cdb[0] == ATA_16) ? 4 : 3; 30958c2ecf20Sopenharmony_ci goto invalid_fld; 30968c2ecf20Sopenharmony_ci } 30978c2ecf20Sopenharmony_ci 30988c2ecf20Sopenharmony_ci /* 30998c2ecf20Sopenharmony_ci * Filter TPM commands by default. These provide an 31008c2ecf20Sopenharmony_ci * essentially uncontrolled encrypted "back door" between 31018c2ecf20Sopenharmony_ci * applications and the disk. Set libata.allow_tpm=1 if you 31028c2ecf20Sopenharmony_ci * have a real reason for wanting to use them. This ensures 31038c2ecf20Sopenharmony_ci * that installed software cannot easily mess stuff up without 31048c2ecf20Sopenharmony_ci * user intent. DVR type users will probably ship with this enabled 31058c2ecf20Sopenharmony_ci * for movie content management. 31068c2ecf20Sopenharmony_ci * 31078c2ecf20Sopenharmony_ci * Note that for ATA8 we can issue a DCS change and DCS freeze lock 31088c2ecf20Sopenharmony_ci * for this and should do in future but that it is not sufficient as 31098c2ecf20Sopenharmony_ci * DCS is an optional feature set. Thus we also do the software filter 31108c2ecf20Sopenharmony_ci * so that we comply with the TC consortium stated goal that the user 31118c2ecf20Sopenharmony_ci * can turn off TC features of their system. 31128c2ecf20Sopenharmony_ci */ 31138c2ecf20Sopenharmony_ci if (tf->command >= 0x5C && tf->command <= 0x5F && !libata_allow_tpm) { 31148c2ecf20Sopenharmony_ci fp = (cdb[0] == ATA_16) ? 14 : 9; 31158c2ecf20Sopenharmony_ci goto invalid_fld; 31168c2ecf20Sopenharmony_ci } 31178c2ecf20Sopenharmony_ci 31188c2ecf20Sopenharmony_ci return 0; 31198c2ecf20Sopenharmony_ci 31208c2ecf20Sopenharmony_ci invalid_fld: 31218c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(dev, scmd, fp, 0xff); 31228c2ecf20Sopenharmony_ci return 1; 31238c2ecf20Sopenharmony_ci} 31248c2ecf20Sopenharmony_ci 31258c2ecf20Sopenharmony_ci/** 31268c2ecf20Sopenharmony_ci * ata_format_dsm_trim_descr() - SATL Write Same to DSM Trim 31278c2ecf20Sopenharmony_ci * @cmd: SCSI command being translated 31288c2ecf20Sopenharmony_ci * @trmax: Maximum number of entries that will fit in sector_size bytes. 31298c2ecf20Sopenharmony_ci * @sector: Starting sector 31308c2ecf20Sopenharmony_ci * @count: Total Range of request in logical sectors 31318c2ecf20Sopenharmony_ci * 31328c2ecf20Sopenharmony_ci * Rewrite the WRITE SAME descriptor to be a DSM TRIM little-endian formatted 31338c2ecf20Sopenharmony_ci * descriptor. 31348c2ecf20Sopenharmony_ci * 31358c2ecf20Sopenharmony_ci * Upto 64 entries of the format: 31368c2ecf20Sopenharmony_ci * 63:48 Range Length 31378c2ecf20Sopenharmony_ci * 47:0 LBA 31388c2ecf20Sopenharmony_ci * 31398c2ecf20Sopenharmony_ci * Range Length of 0 is ignored. 31408c2ecf20Sopenharmony_ci * LBA's should be sorted order and not overlap. 31418c2ecf20Sopenharmony_ci * 31428c2ecf20Sopenharmony_ci * NOTE: this is the same format as ADD LBA(S) TO NV CACHE PINNED SET 31438c2ecf20Sopenharmony_ci * 31448c2ecf20Sopenharmony_ci * Return: Number of bytes copied into sglist. 31458c2ecf20Sopenharmony_ci */ 31468c2ecf20Sopenharmony_cistatic size_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 trmax, 31478c2ecf20Sopenharmony_ci u64 sector, u32 count) 31488c2ecf20Sopenharmony_ci{ 31498c2ecf20Sopenharmony_ci struct scsi_device *sdp = cmd->device; 31508c2ecf20Sopenharmony_ci size_t len = sdp->sector_size; 31518c2ecf20Sopenharmony_ci size_t r; 31528c2ecf20Sopenharmony_ci __le64 *buf; 31538c2ecf20Sopenharmony_ci u32 i = 0; 31548c2ecf20Sopenharmony_ci unsigned long flags; 31558c2ecf20Sopenharmony_ci 31568c2ecf20Sopenharmony_ci WARN_ON(len > ATA_SCSI_RBUF_SIZE); 31578c2ecf20Sopenharmony_ci 31588c2ecf20Sopenharmony_ci if (len > ATA_SCSI_RBUF_SIZE) 31598c2ecf20Sopenharmony_ci len = ATA_SCSI_RBUF_SIZE; 31608c2ecf20Sopenharmony_ci 31618c2ecf20Sopenharmony_ci spin_lock_irqsave(&ata_scsi_rbuf_lock, flags); 31628c2ecf20Sopenharmony_ci buf = ((void *)ata_scsi_rbuf); 31638c2ecf20Sopenharmony_ci memset(buf, 0, len); 31648c2ecf20Sopenharmony_ci while (i < trmax) { 31658c2ecf20Sopenharmony_ci u64 entry = sector | 31668c2ecf20Sopenharmony_ci ((u64)(count > 0xffff ? 0xffff : count) << 48); 31678c2ecf20Sopenharmony_ci buf[i++] = __cpu_to_le64(entry); 31688c2ecf20Sopenharmony_ci if (count <= 0xffff) 31698c2ecf20Sopenharmony_ci break; 31708c2ecf20Sopenharmony_ci count -= 0xffff; 31718c2ecf20Sopenharmony_ci sector += 0xffff; 31728c2ecf20Sopenharmony_ci } 31738c2ecf20Sopenharmony_ci r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf, len); 31748c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags); 31758c2ecf20Sopenharmony_ci 31768c2ecf20Sopenharmony_ci return r; 31778c2ecf20Sopenharmony_ci} 31788c2ecf20Sopenharmony_ci 31798c2ecf20Sopenharmony_ci/** 31808c2ecf20Sopenharmony_ci * ata_scsi_write_same_xlat() - SATL Write Same to ATA SCT Write Same 31818c2ecf20Sopenharmony_ci * @qc: Command to be translated 31828c2ecf20Sopenharmony_ci * 31838c2ecf20Sopenharmony_ci * Translate a SCSI WRITE SAME command to be either a DSM TRIM command or 31848c2ecf20Sopenharmony_ci * an SCT Write Same command. 31858c2ecf20Sopenharmony_ci * Based on WRITE SAME has the UNMAP flag: 31868c2ecf20Sopenharmony_ci * 31878c2ecf20Sopenharmony_ci * - When set translate to DSM TRIM 31888c2ecf20Sopenharmony_ci * - When clear translate to SCT Write Same 31898c2ecf20Sopenharmony_ci */ 31908c2ecf20Sopenharmony_cistatic unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) 31918c2ecf20Sopenharmony_ci{ 31928c2ecf20Sopenharmony_ci struct ata_taskfile *tf = &qc->tf; 31938c2ecf20Sopenharmony_ci struct scsi_cmnd *scmd = qc->scsicmd; 31948c2ecf20Sopenharmony_ci struct scsi_device *sdp = scmd->device; 31958c2ecf20Sopenharmony_ci size_t len = sdp->sector_size; 31968c2ecf20Sopenharmony_ci struct ata_device *dev = qc->dev; 31978c2ecf20Sopenharmony_ci const u8 *cdb = scmd->cmnd; 31988c2ecf20Sopenharmony_ci u64 block; 31998c2ecf20Sopenharmony_ci u32 n_block; 32008c2ecf20Sopenharmony_ci const u32 trmax = len >> 3; 32018c2ecf20Sopenharmony_ci u32 size; 32028c2ecf20Sopenharmony_ci u16 fp; 32038c2ecf20Sopenharmony_ci u8 bp = 0xff; 32048c2ecf20Sopenharmony_ci u8 unmap = cdb[1] & 0x8; 32058c2ecf20Sopenharmony_ci 32068c2ecf20Sopenharmony_ci /* we may not issue DMA commands if no DMA mode is set */ 32078c2ecf20Sopenharmony_ci if (unlikely(!dev->dma_mode)) 32088c2ecf20Sopenharmony_ci goto invalid_opcode; 32098c2ecf20Sopenharmony_ci 32108c2ecf20Sopenharmony_ci /* 32118c2ecf20Sopenharmony_ci * We only allow sending this command through the block layer, 32128c2ecf20Sopenharmony_ci * as it modifies the DATA OUT buffer, which would corrupt user 32138c2ecf20Sopenharmony_ci * memory for SG_IO commands. 32148c2ecf20Sopenharmony_ci */ 32158c2ecf20Sopenharmony_ci if (unlikely(blk_rq_is_passthrough(scmd->request))) 32168c2ecf20Sopenharmony_ci goto invalid_opcode; 32178c2ecf20Sopenharmony_ci 32188c2ecf20Sopenharmony_ci if (unlikely(scmd->cmd_len < 16)) { 32198c2ecf20Sopenharmony_ci fp = 15; 32208c2ecf20Sopenharmony_ci goto invalid_fld; 32218c2ecf20Sopenharmony_ci } 32228c2ecf20Sopenharmony_ci scsi_16_lba_len(cdb, &block, &n_block); 32238c2ecf20Sopenharmony_ci 32248c2ecf20Sopenharmony_ci if (!unmap || 32258c2ecf20Sopenharmony_ci (dev->horkage & ATA_HORKAGE_NOTRIM) || 32268c2ecf20Sopenharmony_ci !ata_id_has_trim(dev->id)) { 32278c2ecf20Sopenharmony_ci fp = 1; 32288c2ecf20Sopenharmony_ci bp = 3; 32298c2ecf20Sopenharmony_ci goto invalid_fld; 32308c2ecf20Sopenharmony_ci } 32318c2ecf20Sopenharmony_ci /* If the request is too large the cmd is invalid */ 32328c2ecf20Sopenharmony_ci if (n_block > 0xffff * trmax) { 32338c2ecf20Sopenharmony_ci fp = 2; 32348c2ecf20Sopenharmony_ci goto invalid_fld; 32358c2ecf20Sopenharmony_ci } 32368c2ecf20Sopenharmony_ci 32378c2ecf20Sopenharmony_ci /* 32388c2ecf20Sopenharmony_ci * WRITE SAME always has a sector sized buffer as payload, this 32398c2ecf20Sopenharmony_ci * should never be a multiple entry S/G list. 32408c2ecf20Sopenharmony_ci */ 32418c2ecf20Sopenharmony_ci if (!scsi_sg_count(scmd)) 32428c2ecf20Sopenharmony_ci goto invalid_param_len; 32438c2ecf20Sopenharmony_ci 32448c2ecf20Sopenharmony_ci /* 32458c2ecf20Sopenharmony_ci * size must match sector size in bytes 32468c2ecf20Sopenharmony_ci * For DATA SET MANAGEMENT TRIM in ACS-2 nsect (aka count) 32478c2ecf20Sopenharmony_ci * is defined as number of 512 byte blocks to be transferred. 32488c2ecf20Sopenharmony_ci */ 32498c2ecf20Sopenharmony_ci 32508c2ecf20Sopenharmony_ci size = ata_format_dsm_trim_descr(scmd, trmax, block, n_block); 32518c2ecf20Sopenharmony_ci if (size != len) 32528c2ecf20Sopenharmony_ci goto invalid_param_len; 32538c2ecf20Sopenharmony_ci 32548c2ecf20Sopenharmony_ci if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) { 32558c2ecf20Sopenharmony_ci /* Newer devices support queued TRIM commands */ 32568c2ecf20Sopenharmony_ci tf->protocol = ATA_PROT_NCQ; 32578c2ecf20Sopenharmony_ci tf->command = ATA_CMD_FPDMA_SEND; 32588c2ecf20Sopenharmony_ci tf->hob_nsect = ATA_SUBCMD_FPDMA_SEND_DSM & 0x1f; 32598c2ecf20Sopenharmony_ci tf->nsect = qc->hw_tag << 3; 32608c2ecf20Sopenharmony_ci tf->hob_feature = (size / 512) >> 8; 32618c2ecf20Sopenharmony_ci tf->feature = size / 512; 32628c2ecf20Sopenharmony_ci 32638c2ecf20Sopenharmony_ci tf->auxiliary = 1; 32648c2ecf20Sopenharmony_ci } else { 32658c2ecf20Sopenharmony_ci tf->protocol = ATA_PROT_DMA; 32668c2ecf20Sopenharmony_ci tf->hob_feature = 0; 32678c2ecf20Sopenharmony_ci tf->feature = ATA_DSM_TRIM; 32688c2ecf20Sopenharmony_ci tf->hob_nsect = (size / 512) >> 8; 32698c2ecf20Sopenharmony_ci tf->nsect = size / 512; 32708c2ecf20Sopenharmony_ci tf->command = ATA_CMD_DSM; 32718c2ecf20Sopenharmony_ci } 32728c2ecf20Sopenharmony_ci 32738c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48 | 32748c2ecf20Sopenharmony_ci ATA_TFLAG_WRITE; 32758c2ecf20Sopenharmony_ci 32768c2ecf20Sopenharmony_ci ata_qc_set_pc_nbytes(qc); 32778c2ecf20Sopenharmony_ci 32788c2ecf20Sopenharmony_ci return 0; 32798c2ecf20Sopenharmony_ci 32808c2ecf20Sopenharmony_ciinvalid_fld: 32818c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(dev, scmd, fp, bp); 32828c2ecf20Sopenharmony_ci return 1; 32838c2ecf20Sopenharmony_ciinvalid_param_len: 32848c2ecf20Sopenharmony_ci /* "Parameter list length error" */ 32858c2ecf20Sopenharmony_ci ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0); 32868c2ecf20Sopenharmony_ci return 1; 32878c2ecf20Sopenharmony_ciinvalid_opcode: 32888c2ecf20Sopenharmony_ci /* "Invalid command operation code" */ 32898c2ecf20Sopenharmony_ci ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x20, 0x0); 32908c2ecf20Sopenharmony_ci return 1; 32918c2ecf20Sopenharmony_ci} 32928c2ecf20Sopenharmony_ci 32938c2ecf20Sopenharmony_ci/** 32948c2ecf20Sopenharmony_ci * ata_scsiop_maint_in - Simulate a subset of MAINTENANCE_IN 32958c2ecf20Sopenharmony_ci * @args: device MAINTENANCE_IN data / SCSI command of interest. 32968c2ecf20Sopenharmony_ci * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. 32978c2ecf20Sopenharmony_ci * 32988c2ecf20Sopenharmony_ci * Yields a subset to satisfy scsi_report_opcode() 32998c2ecf20Sopenharmony_ci * 33008c2ecf20Sopenharmony_ci * LOCKING: 33018c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 33028c2ecf20Sopenharmony_ci */ 33038c2ecf20Sopenharmony_cistatic unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) 33048c2ecf20Sopenharmony_ci{ 33058c2ecf20Sopenharmony_ci struct ata_device *dev = args->dev; 33068c2ecf20Sopenharmony_ci u8 *cdb = args->cmd->cmnd; 33078c2ecf20Sopenharmony_ci u8 supported = 0; 33088c2ecf20Sopenharmony_ci unsigned int err = 0; 33098c2ecf20Sopenharmony_ci 33108c2ecf20Sopenharmony_ci if (cdb[2] != 1) { 33118c2ecf20Sopenharmony_ci ata_dev_warn(dev, "invalid command format %d\n", cdb[2]); 33128c2ecf20Sopenharmony_ci err = 2; 33138c2ecf20Sopenharmony_ci goto out; 33148c2ecf20Sopenharmony_ci } 33158c2ecf20Sopenharmony_ci switch (cdb[3]) { 33168c2ecf20Sopenharmony_ci case INQUIRY: 33178c2ecf20Sopenharmony_ci case MODE_SENSE: 33188c2ecf20Sopenharmony_ci case MODE_SENSE_10: 33198c2ecf20Sopenharmony_ci case READ_CAPACITY: 33208c2ecf20Sopenharmony_ci case SERVICE_ACTION_IN_16: 33218c2ecf20Sopenharmony_ci case REPORT_LUNS: 33228c2ecf20Sopenharmony_ci case REQUEST_SENSE: 33238c2ecf20Sopenharmony_ci case SYNCHRONIZE_CACHE: 33248c2ecf20Sopenharmony_ci case SYNCHRONIZE_CACHE_16: 33258c2ecf20Sopenharmony_ci case REZERO_UNIT: 33268c2ecf20Sopenharmony_ci case SEEK_6: 33278c2ecf20Sopenharmony_ci case SEEK_10: 33288c2ecf20Sopenharmony_ci case TEST_UNIT_READY: 33298c2ecf20Sopenharmony_ci case SEND_DIAGNOSTIC: 33308c2ecf20Sopenharmony_ci case MAINTENANCE_IN: 33318c2ecf20Sopenharmony_ci case READ_6: 33328c2ecf20Sopenharmony_ci case READ_10: 33338c2ecf20Sopenharmony_ci case READ_16: 33348c2ecf20Sopenharmony_ci case WRITE_6: 33358c2ecf20Sopenharmony_ci case WRITE_10: 33368c2ecf20Sopenharmony_ci case WRITE_16: 33378c2ecf20Sopenharmony_ci case ATA_12: 33388c2ecf20Sopenharmony_ci case ATA_16: 33398c2ecf20Sopenharmony_ci case VERIFY: 33408c2ecf20Sopenharmony_ci case VERIFY_16: 33418c2ecf20Sopenharmony_ci case MODE_SELECT: 33428c2ecf20Sopenharmony_ci case MODE_SELECT_10: 33438c2ecf20Sopenharmony_ci case START_STOP: 33448c2ecf20Sopenharmony_ci supported = 3; 33458c2ecf20Sopenharmony_ci break; 33468c2ecf20Sopenharmony_ci case ZBC_IN: 33478c2ecf20Sopenharmony_ci case ZBC_OUT: 33488c2ecf20Sopenharmony_ci if (ata_id_zoned_cap(dev->id) || 33498c2ecf20Sopenharmony_ci dev->class == ATA_DEV_ZAC) 33508c2ecf20Sopenharmony_ci supported = 3; 33518c2ecf20Sopenharmony_ci break; 33528c2ecf20Sopenharmony_ci case SECURITY_PROTOCOL_IN: 33538c2ecf20Sopenharmony_ci case SECURITY_PROTOCOL_OUT: 33548c2ecf20Sopenharmony_ci if (dev->flags & ATA_DFLAG_TRUSTED) 33558c2ecf20Sopenharmony_ci supported = 3; 33568c2ecf20Sopenharmony_ci break; 33578c2ecf20Sopenharmony_ci default: 33588c2ecf20Sopenharmony_ci break; 33598c2ecf20Sopenharmony_ci } 33608c2ecf20Sopenharmony_ciout: 33618c2ecf20Sopenharmony_ci rbuf[1] = supported; /* supported */ 33628c2ecf20Sopenharmony_ci return err; 33638c2ecf20Sopenharmony_ci} 33648c2ecf20Sopenharmony_ci 33658c2ecf20Sopenharmony_ci/** 33668c2ecf20Sopenharmony_ci * ata_scsi_report_zones_complete - convert ATA output 33678c2ecf20Sopenharmony_ci * @qc: command structure returning the data 33688c2ecf20Sopenharmony_ci * 33698c2ecf20Sopenharmony_ci * Convert T-13 little-endian field representation into 33708c2ecf20Sopenharmony_ci * T-10 big-endian field representation. 33718c2ecf20Sopenharmony_ci * What a mess. 33728c2ecf20Sopenharmony_ci */ 33738c2ecf20Sopenharmony_cistatic void ata_scsi_report_zones_complete(struct ata_queued_cmd *qc) 33748c2ecf20Sopenharmony_ci{ 33758c2ecf20Sopenharmony_ci struct scsi_cmnd *scmd = qc->scsicmd; 33768c2ecf20Sopenharmony_ci struct sg_mapping_iter miter; 33778c2ecf20Sopenharmony_ci unsigned long flags; 33788c2ecf20Sopenharmony_ci unsigned int bytes = 0; 33798c2ecf20Sopenharmony_ci 33808c2ecf20Sopenharmony_ci sg_miter_start(&miter, scsi_sglist(scmd), scsi_sg_count(scmd), 33818c2ecf20Sopenharmony_ci SG_MITER_TO_SG | SG_MITER_ATOMIC); 33828c2ecf20Sopenharmony_ci 33838c2ecf20Sopenharmony_ci local_irq_save(flags); 33848c2ecf20Sopenharmony_ci while (sg_miter_next(&miter)) { 33858c2ecf20Sopenharmony_ci unsigned int offset = 0; 33868c2ecf20Sopenharmony_ci 33878c2ecf20Sopenharmony_ci if (bytes == 0) { 33888c2ecf20Sopenharmony_ci char *hdr; 33898c2ecf20Sopenharmony_ci u32 list_length; 33908c2ecf20Sopenharmony_ci u64 max_lba, opt_lba; 33918c2ecf20Sopenharmony_ci u16 same; 33928c2ecf20Sopenharmony_ci 33938c2ecf20Sopenharmony_ci /* Swizzle header */ 33948c2ecf20Sopenharmony_ci hdr = miter.addr; 33958c2ecf20Sopenharmony_ci list_length = get_unaligned_le32(&hdr[0]); 33968c2ecf20Sopenharmony_ci same = get_unaligned_le16(&hdr[4]); 33978c2ecf20Sopenharmony_ci max_lba = get_unaligned_le64(&hdr[8]); 33988c2ecf20Sopenharmony_ci opt_lba = get_unaligned_le64(&hdr[16]); 33998c2ecf20Sopenharmony_ci put_unaligned_be32(list_length, &hdr[0]); 34008c2ecf20Sopenharmony_ci hdr[4] = same & 0xf; 34018c2ecf20Sopenharmony_ci put_unaligned_be64(max_lba, &hdr[8]); 34028c2ecf20Sopenharmony_ci put_unaligned_be64(opt_lba, &hdr[16]); 34038c2ecf20Sopenharmony_ci offset += 64; 34048c2ecf20Sopenharmony_ci bytes += 64; 34058c2ecf20Sopenharmony_ci } 34068c2ecf20Sopenharmony_ci while (offset < miter.length) { 34078c2ecf20Sopenharmony_ci char *rec; 34088c2ecf20Sopenharmony_ci u8 cond, type, non_seq, reset; 34098c2ecf20Sopenharmony_ci u64 size, start, wp; 34108c2ecf20Sopenharmony_ci 34118c2ecf20Sopenharmony_ci /* Swizzle zone descriptor */ 34128c2ecf20Sopenharmony_ci rec = miter.addr + offset; 34138c2ecf20Sopenharmony_ci type = rec[0] & 0xf; 34148c2ecf20Sopenharmony_ci cond = (rec[1] >> 4) & 0xf; 34158c2ecf20Sopenharmony_ci non_seq = (rec[1] & 2); 34168c2ecf20Sopenharmony_ci reset = (rec[1] & 1); 34178c2ecf20Sopenharmony_ci size = get_unaligned_le64(&rec[8]); 34188c2ecf20Sopenharmony_ci start = get_unaligned_le64(&rec[16]); 34198c2ecf20Sopenharmony_ci wp = get_unaligned_le64(&rec[24]); 34208c2ecf20Sopenharmony_ci rec[0] = type; 34218c2ecf20Sopenharmony_ci rec[1] = (cond << 4) | non_seq | reset; 34228c2ecf20Sopenharmony_ci put_unaligned_be64(size, &rec[8]); 34238c2ecf20Sopenharmony_ci put_unaligned_be64(start, &rec[16]); 34248c2ecf20Sopenharmony_ci put_unaligned_be64(wp, &rec[24]); 34258c2ecf20Sopenharmony_ci WARN_ON(offset + 64 > miter.length); 34268c2ecf20Sopenharmony_ci offset += 64; 34278c2ecf20Sopenharmony_ci bytes += 64; 34288c2ecf20Sopenharmony_ci } 34298c2ecf20Sopenharmony_ci } 34308c2ecf20Sopenharmony_ci sg_miter_stop(&miter); 34318c2ecf20Sopenharmony_ci local_irq_restore(flags); 34328c2ecf20Sopenharmony_ci 34338c2ecf20Sopenharmony_ci ata_scsi_qc_complete(qc); 34348c2ecf20Sopenharmony_ci} 34358c2ecf20Sopenharmony_ci 34368c2ecf20Sopenharmony_cistatic unsigned int ata_scsi_zbc_in_xlat(struct ata_queued_cmd *qc) 34378c2ecf20Sopenharmony_ci{ 34388c2ecf20Sopenharmony_ci struct ata_taskfile *tf = &qc->tf; 34398c2ecf20Sopenharmony_ci struct scsi_cmnd *scmd = qc->scsicmd; 34408c2ecf20Sopenharmony_ci const u8 *cdb = scmd->cmnd; 34418c2ecf20Sopenharmony_ci u16 sect, fp = (u16)-1; 34428c2ecf20Sopenharmony_ci u8 sa, options, bp = 0xff; 34438c2ecf20Sopenharmony_ci u64 block; 34448c2ecf20Sopenharmony_ci u32 n_block; 34458c2ecf20Sopenharmony_ci 34468c2ecf20Sopenharmony_ci if (unlikely(scmd->cmd_len < 16)) { 34478c2ecf20Sopenharmony_ci ata_dev_warn(qc->dev, "invalid cdb length %d\n", 34488c2ecf20Sopenharmony_ci scmd->cmd_len); 34498c2ecf20Sopenharmony_ci fp = 15; 34508c2ecf20Sopenharmony_ci goto invalid_fld; 34518c2ecf20Sopenharmony_ci } 34528c2ecf20Sopenharmony_ci scsi_16_lba_len(cdb, &block, &n_block); 34538c2ecf20Sopenharmony_ci if (n_block != scsi_bufflen(scmd)) { 34548c2ecf20Sopenharmony_ci ata_dev_warn(qc->dev, "non-matching transfer count (%d/%d)\n", 34558c2ecf20Sopenharmony_ci n_block, scsi_bufflen(scmd)); 34568c2ecf20Sopenharmony_ci goto invalid_param_len; 34578c2ecf20Sopenharmony_ci } 34588c2ecf20Sopenharmony_ci sa = cdb[1] & 0x1f; 34598c2ecf20Sopenharmony_ci if (sa != ZI_REPORT_ZONES) { 34608c2ecf20Sopenharmony_ci ata_dev_warn(qc->dev, "invalid service action %d\n", sa); 34618c2ecf20Sopenharmony_ci fp = 1; 34628c2ecf20Sopenharmony_ci goto invalid_fld; 34638c2ecf20Sopenharmony_ci } 34648c2ecf20Sopenharmony_ci /* 34658c2ecf20Sopenharmony_ci * ZAC allows only for transfers in 512 byte blocks, 34668c2ecf20Sopenharmony_ci * and uses a 16 bit value for the transfer count. 34678c2ecf20Sopenharmony_ci */ 34688c2ecf20Sopenharmony_ci if ((n_block / 512) > 0xffff || n_block < 512 || (n_block % 512)) { 34698c2ecf20Sopenharmony_ci ata_dev_warn(qc->dev, "invalid transfer count %d\n", n_block); 34708c2ecf20Sopenharmony_ci goto invalid_param_len; 34718c2ecf20Sopenharmony_ci } 34728c2ecf20Sopenharmony_ci sect = n_block / 512; 34738c2ecf20Sopenharmony_ci options = cdb[14] & 0xbf; 34748c2ecf20Sopenharmony_ci 34758c2ecf20Sopenharmony_ci if (ata_ncq_enabled(qc->dev) && 34768c2ecf20Sopenharmony_ci ata_fpdma_zac_mgmt_in_supported(qc->dev)) { 34778c2ecf20Sopenharmony_ci tf->protocol = ATA_PROT_NCQ; 34788c2ecf20Sopenharmony_ci tf->command = ATA_CMD_FPDMA_RECV; 34798c2ecf20Sopenharmony_ci tf->hob_nsect = ATA_SUBCMD_FPDMA_RECV_ZAC_MGMT_IN & 0x1f; 34808c2ecf20Sopenharmony_ci tf->nsect = qc->hw_tag << 3; 34818c2ecf20Sopenharmony_ci tf->feature = sect & 0xff; 34828c2ecf20Sopenharmony_ci tf->hob_feature = (sect >> 8) & 0xff; 34838c2ecf20Sopenharmony_ci tf->auxiliary = ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES | (options << 8); 34848c2ecf20Sopenharmony_ci } else { 34858c2ecf20Sopenharmony_ci tf->command = ATA_CMD_ZAC_MGMT_IN; 34868c2ecf20Sopenharmony_ci tf->feature = ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES; 34878c2ecf20Sopenharmony_ci tf->protocol = ATA_PROT_DMA; 34888c2ecf20Sopenharmony_ci tf->hob_feature = options; 34898c2ecf20Sopenharmony_ci tf->hob_nsect = (sect >> 8) & 0xff; 34908c2ecf20Sopenharmony_ci tf->nsect = sect & 0xff; 34918c2ecf20Sopenharmony_ci } 34928c2ecf20Sopenharmony_ci tf->device = ATA_LBA; 34938c2ecf20Sopenharmony_ci tf->lbah = (block >> 16) & 0xff; 34948c2ecf20Sopenharmony_ci tf->lbam = (block >> 8) & 0xff; 34958c2ecf20Sopenharmony_ci tf->lbal = block & 0xff; 34968c2ecf20Sopenharmony_ci tf->hob_lbah = (block >> 40) & 0xff; 34978c2ecf20Sopenharmony_ci tf->hob_lbam = (block >> 32) & 0xff; 34988c2ecf20Sopenharmony_ci tf->hob_lbal = (block >> 24) & 0xff; 34998c2ecf20Sopenharmony_ci 35008c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48; 35018c2ecf20Sopenharmony_ci qc->flags |= ATA_QCFLAG_RESULT_TF; 35028c2ecf20Sopenharmony_ci 35038c2ecf20Sopenharmony_ci ata_qc_set_pc_nbytes(qc); 35048c2ecf20Sopenharmony_ci 35058c2ecf20Sopenharmony_ci qc->complete_fn = ata_scsi_report_zones_complete; 35068c2ecf20Sopenharmony_ci 35078c2ecf20Sopenharmony_ci return 0; 35088c2ecf20Sopenharmony_ci 35098c2ecf20Sopenharmony_ciinvalid_fld: 35108c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(qc->dev, scmd, fp, bp); 35118c2ecf20Sopenharmony_ci return 1; 35128c2ecf20Sopenharmony_ci 35138c2ecf20Sopenharmony_ciinvalid_param_len: 35148c2ecf20Sopenharmony_ci /* "Parameter list length error" */ 35158c2ecf20Sopenharmony_ci ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0); 35168c2ecf20Sopenharmony_ci return 1; 35178c2ecf20Sopenharmony_ci} 35188c2ecf20Sopenharmony_ci 35198c2ecf20Sopenharmony_cistatic unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc) 35208c2ecf20Sopenharmony_ci{ 35218c2ecf20Sopenharmony_ci struct ata_taskfile *tf = &qc->tf; 35228c2ecf20Sopenharmony_ci struct scsi_cmnd *scmd = qc->scsicmd; 35238c2ecf20Sopenharmony_ci struct ata_device *dev = qc->dev; 35248c2ecf20Sopenharmony_ci const u8 *cdb = scmd->cmnd; 35258c2ecf20Sopenharmony_ci u8 all, sa; 35268c2ecf20Sopenharmony_ci u64 block; 35278c2ecf20Sopenharmony_ci u32 n_block; 35288c2ecf20Sopenharmony_ci u16 fp = (u16)-1; 35298c2ecf20Sopenharmony_ci 35308c2ecf20Sopenharmony_ci if (unlikely(scmd->cmd_len < 16)) { 35318c2ecf20Sopenharmony_ci fp = 15; 35328c2ecf20Sopenharmony_ci goto invalid_fld; 35338c2ecf20Sopenharmony_ci } 35348c2ecf20Sopenharmony_ci 35358c2ecf20Sopenharmony_ci sa = cdb[1] & 0x1f; 35368c2ecf20Sopenharmony_ci if ((sa != ZO_CLOSE_ZONE) && (sa != ZO_FINISH_ZONE) && 35378c2ecf20Sopenharmony_ci (sa != ZO_OPEN_ZONE) && (sa != ZO_RESET_WRITE_POINTER)) { 35388c2ecf20Sopenharmony_ci fp = 1; 35398c2ecf20Sopenharmony_ci goto invalid_fld; 35408c2ecf20Sopenharmony_ci } 35418c2ecf20Sopenharmony_ci 35428c2ecf20Sopenharmony_ci scsi_16_lba_len(cdb, &block, &n_block); 35438c2ecf20Sopenharmony_ci if (n_block) { 35448c2ecf20Sopenharmony_ci /* 35458c2ecf20Sopenharmony_ci * ZAC MANAGEMENT OUT doesn't define any length 35468c2ecf20Sopenharmony_ci */ 35478c2ecf20Sopenharmony_ci goto invalid_param_len; 35488c2ecf20Sopenharmony_ci } 35498c2ecf20Sopenharmony_ci 35508c2ecf20Sopenharmony_ci all = cdb[14] & 0x1; 35518c2ecf20Sopenharmony_ci if (all) { 35528c2ecf20Sopenharmony_ci /* 35538c2ecf20Sopenharmony_ci * Ignore the block address (zone ID) as defined by ZBC. 35548c2ecf20Sopenharmony_ci */ 35558c2ecf20Sopenharmony_ci block = 0; 35568c2ecf20Sopenharmony_ci } else if (block >= dev->n_sectors) { 35578c2ecf20Sopenharmony_ci /* 35588c2ecf20Sopenharmony_ci * Block must be a valid zone ID (a zone start LBA). 35598c2ecf20Sopenharmony_ci */ 35608c2ecf20Sopenharmony_ci fp = 2; 35618c2ecf20Sopenharmony_ci goto invalid_fld; 35628c2ecf20Sopenharmony_ci } 35638c2ecf20Sopenharmony_ci 35648c2ecf20Sopenharmony_ci if (ata_ncq_enabled(qc->dev) && 35658c2ecf20Sopenharmony_ci ata_fpdma_zac_mgmt_out_supported(qc->dev)) { 35668c2ecf20Sopenharmony_ci tf->protocol = ATA_PROT_NCQ_NODATA; 35678c2ecf20Sopenharmony_ci tf->command = ATA_CMD_NCQ_NON_DATA; 35688c2ecf20Sopenharmony_ci tf->feature = ATA_SUBCMD_NCQ_NON_DATA_ZAC_MGMT_OUT; 35698c2ecf20Sopenharmony_ci tf->nsect = qc->hw_tag << 3; 35708c2ecf20Sopenharmony_ci tf->auxiliary = sa | ((u16)all << 8); 35718c2ecf20Sopenharmony_ci } else { 35728c2ecf20Sopenharmony_ci tf->protocol = ATA_PROT_NODATA; 35738c2ecf20Sopenharmony_ci tf->command = ATA_CMD_ZAC_MGMT_OUT; 35748c2ecf20Sopenharmony_ci tf->feature = sa; 35758c2ecf20Sopenharmony_ci tf->hob_feature = all; 35768c2ecf20Sopenharmony_ci } 35778c2ecf20Sopenharmony_ci tf->lbah = (block >> 16) & 0xff; 35788c2ecf20Sopenharmony_ci tf->lbam = (block >> 8) & 0xff; 35798c2ecf20Sopenharmony_ci tf->lbal = block & 0xff; 35808c2ecf20Sopenharmony_ci tf->hob_lbah = (block >> 40) & 0xff; 35818c2ecf20Sopenharmony_ci tf->hob_lbam = (block >> 32) & 0xff; 35828c2ecf20Sopenharmony_ci tf->hob_lbal = (block >> 24) & 0xff; 35838c2ecf20Sopenharmony_ci tf->device = ATA_LBA; 35848c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48; 35858c2ecf20Sopenharmony_ci 35868c2ecf20Sopenharmony_ci return 0; 35878c2ecf20Sopenharmony_ci 35888c2ecf20Sopenharmony_ci invalid_fld: 35898c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(qc->dev, scmd, fp, 0xff); 35908c2ecf20Sopenharmony_ci return 1; 35918c2ecf20Sopenharmony_ciinvalid_param_len: 35928c2ecf20Sopenharmony_ci /* "Parameter list length error" */ 35938c2ecf20Sopenharmony_ci ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0); 35948c2ecf20Sopenharmony_ci return 1; 35958c2ecf20Sopenharmony_ci} 35968c2ecf20Sopenharmony_ci 35978c2ecf20Sopenharmony_ci/** 35988c2ecf20Sopenharmony_ci * ata_mselect_caching - Simulate MODE SELECT for caching info page 35998c2ecf20Sopenharmony_ci * @qc: Storage for translated ATA taskfile 36008c2ecf20Sopenharmony_ci * @buf: input buffer 36018c2ecf20Sopenharmony_ci * @len: number of valid bytes in the input buffer 36028c2ecf20Sopenharmony_ci * @fp: out parameter for the failed field on error 36038c2ecf20Sopenharmony_ci * 36048c2ecf20Sopenharmony_ci * Prepare a taskfile to modify caching information for the device. 36058c2ecf20Sopenharmony_ci * 36068c2ecf20Sopenharmony_ci * LOCKING: 36078c2ecf20Sopenharmony_ci * None. 36088c2ecf20Sopenharmony_ci */ 36098c2ecf20Sopenharmony_cistatic int ata_mselect_caching(struct ata_queued_cmd *qc, 36108c2ecf20Sopenharmony_ci const u8 *buf, int len, u16 *fp) 36118c2ecf20Sopenharmony_ci{ 36128c2ecf20Sopenharmony_ci struct ata_taskfile *tf = &qc->tf; 36138c2ecf20Sopenharmony_ci struct ata_device *dev = qc->dev; 36148c2ecf20Sopenharmony_ci u8 mpage[CACHE_MPAGE_LEN]; 36158c2ecf20Sopenharmony_ci u8 wce; 36168c2ecf20Sopenharmony_ci int i; 36178c2ecf20Sopenharmony_ci 36188c2ecf20Sopenharmony_ci /* 36198c2ecf20Sopenharmony_ci * The first two bytes of def_cache_mpage are a header, so offsets 36208c2ecf20Sopenharmony_ci * in mpage are off by 2 compared to buf. Same for len. 36218c2ecf20Sopenharmony_ci */ 36228c2ecf20Sopenharmony_ci 36238c2ecf20Sopenharmony_ci if (len != CACHE_MPAGE_LEN - 2) { 36248c2ecf20Sopenharmony_ci if (len < CACHE_MPAGE_LEN - 2) 36258c2ecf20Sopenharmony_ci *fp = len; 36268c2ecf20Sopenharmony_ci else 36278c2ecf20Sopenharmony_ci *fp = CACHE_MPAGE_LEN - 2; 36288c2ecf20Sopenharmony_ci return -EINVAL; 36298c2ecf20Sopenharmony_ci } 36308c2ecf20Sopenharmony_ci 36318c2ecf20Sopenharmony_ci wce = buf[0] & (1 << 2); 36328c2ecf20Sopenharmony_ci 36338c2ecf20Sopenharmony_ci /* 36348c2ecf20Sopenharmony_ci * Check that read-only bits are not modified. 36358c2ecf20Sopenharmony_ci */ 36368c2ecf20Sopenharmony_ci ata_msense_caching(dev->id, mpage, false); 36378c2ecf20Sopenharmony_ci for (i = 0; i < CACHE_MPAGE_LEN - 2; i++) { 36388c2ecf20Sopenharmony_ci if (i == 0) 36398c2ecf20Sopenharmony_ci continue; 36408c2ecf20Sopenharmony_ci if (mpage[i + 2] != buf[i]) { 36418c2ecf20Sopenharmony_ci *fp = i; 36428c2ecf20Sopenharmony_ci return -EINVAL; 36438c2ecf20Sopenharmony_ci } 36448c2ecf20Sopenharmony_ci } 36458c2ecf20Sopenharmony_ci 36468c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; 36478c2ecf20Sopenharmony_ci tf->protocol = ATA_PROT_NODATA; 36488c2ecf20Sopenharmony_ci tf->nsect = 0; 36498c2ecf20Sopenharmony_ci tf->command = ATA_CMD_SET_FEATURES; 36508c2ecf20Sopenharmony_ci tf->feature = wce ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF; 36518c2ecf20Sopenharmony_ci return 0; 36528c2ecf20Sopenharmony_ci} 36538c2ecf20Sopenharmony_ci 36548c2ecf20Sopenharmony_ci/** 36558c2ecf20Sopenharmony_ci * ata_mselect_control - Simulate MODE SELECT for control page 36568c2ecf20Sopenharmony_ci * @qc: Storage for translated ATA taskfile 36578c2ecf20Sopenharmony_ci * @buf: input buffer 36588c2ecf20Sopenharmony_ci * @len: number of valid bytes in the input buffer 36598c2ecf20Sopenharmony_ci * @fp: out parameter for the failed field on error 36608c2ecf20Sopenharmony_ci * 36618c2ecf20Sopenharmony_ci * Prepare a taskfile to modify caching information for the device. 36628c2ecf20Sopenharmony_ci * 36638c2ecf20Sopenharmony_ci * LOCKING: 36648c2ecf20Sopenharmony_ci * None. 36658c2ecf20Sopenharmony_ci */ 36668c2ecf20Sopenharmony_cistatic int ata_mselect_control(struct ata_queued_cmd *qc, 36678c2ecf20Sopenharmony_ci const u8 *buf, int len, u16 *fp) 36688c2ecf20Sopenharmony_ci{ 36698c2ecf20Sopenharmony_ci struct ata_device *dev = qc->dev; 36708c2ecf20Sopenharmony_ci u8 mpage[CONTROL_MPAGE_LEN]; 36718c2ecf20Sopenharmony_ci u8 d_sense; 36728c2ecf20Sopenharmony_ci int i; 36738c2ecf20Sopenharmony_ci 36748c2ecf20Sopenharmony_ci /* 36758c2ecf20Sopenharmony_ci * The first two bytes of def_control_mpage are a header, so offsets 36768c2ecf20Sopenharmony_ci * in mpage are off by 2 compared to buf. Same for len. 36778c2ecf20Sopenharmony_ci */ 36788c2ecf20Sopenharmony_ci 36798c2ecf20Sopenharmony_ci if (len != CONTROL_MPAGE_LEN - 2) { 36808c2ecf20Sopenharmony_ci if (len < CONTROL_MPAGE_LEN - 2) 36818c2ecf20Sopenharmony_ci *fp = len; 36828c2ecf20Sopenharmony_ci else 36838c2ecf20Sopenharmony_ci *fp = CONTROL_MPAGE_LEN - 2; 36848c2ecf20Sopenharmony_ci return -EINVAL; 36858c2ecf20Sopenharmony_ci } 36868c2ecf20Sopenharmony_ci 36878c2ecf20Sopenharmony_ci d_sense = buf[0] & (1 << 2); 36888c2ecf20Sopenharmony_ci 36898c2ecf20Sopenharmony_ci /* 36908c2ecf20Sopenharmony_ci * Check that read-only bits are not modified. 36918c2ecf20Sopenharmony_ci */ 36928c2ecf20Sopenharmony_ci ata_msense_control(dev, mpage, false); 36938c2ecf20Sopenharmony_ci for (i = 0; i < CONTROL_MPAGE_LEN - 2; i++) { 36948c2ecf20Sopenharmony_ci if (i == 0) 36958c2ecf20Sopenharmony_ci continue; 36968c2ecf20Sopenharmony_ci if (mpage[2 + i] != buf[i]) { 36978c2ecf20Sopenharmony_ci *fp = i; 36988c2ecf20Sopenharmony_ci return -EINVAL; 36998c2ecf20Sopenharmony_ci } 37008c2ecf20Sopenharmony_ci } 37018c2ecf20Sopenharmony_ci if (d_sense & (1 << 2)) 37028c2ecf20Sopenharmony_ci dev->flags |= ATA_DFLAG_D_SENSE; 37038c2ecf20Sopenharmony_ci else 37048c2ecf20Sopenharmony_ci dev->flags &= ~ATA_DFLAG_D_SENSE; 37058c2ecf20Sopenharmony_ci return 0; 37068c2ecf20Sopenharmony_ci} 37078c2ecf20Sopenharmony_ci 37088c2ecf20Sopenharmony_ci/** 37098c2ecf20Sopenharmony_ci * ata_scsi_mode_select_xlat - Simulate MODE SELECT 6, 10 commands 37108c2ecf20Sopenharmony_ci * @qc: Storage for translated ATA taskfile 37118c2ecf20Sopenharmony_ci * 37128c2ecf20Sopenharmony_ci * Converts a MODE SELECT command to an ATA SET FEATURES taskfile. 37138c2ecf20Sopenharmony_ci * Assume this is invoked for direct access devices (e.g. disks) only. 37148c2ecf20Sopenharmony_ci * There should be no block descriptor for other device types. 37158c2ecf20Sopenharmony_ci * 37168c2ecf20Sopenharmony_ci * LOCKING: 37178c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 37188c2ecf20Sopenharmony_ci */ 37198c2ecf20Sopenharmony_cistatic unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) 37208c2ecf20Sopenharmony_ci{ 37218c2ecf20Sopenharmony_ci struct scsi_cmnd *scmd = qc->scsicmd; 37228c2ecf20Sopenharmony_ci const u8 *cdb = scmd->cmnd; 37238c2ecf20Sopenharmony_ci u8 pg, spg; 37248c2ecf20Sopenharmony_ci unsigned six_byte, pg_len, hdr_len, bd_len; 37258c2ecf20Sopenharmony_ci int len; 37268c2ecf20Sopenharmony_ci u16 fp = (u16)-1; 37278c2ecf20Sopenharmony_ci u8 bp = 0xff; 37288c2ecf20Sopenharmony_ci u8 buffer[64]; 37298c2ecf20Sopenharmony_ci const u8 *p = buffer; 37308c2ecf20Sopenharmony_ci 37318c2ecf20Sopenharmony_ci VPRINTK("ENTER\n"); 37328c2ecf20Sopenharmony_ci 37338c2ecf20Sopenharmony_ci six_byte = (cdb[0] == MODE_SELECT); 37348c2ecf20Sopenharmony_ci if (six_byte) { 37358c2ecf20Sopenharmony_ci if (scmd->cmd_len < 5) { 37368c2ecf20Sopenharmony_ci fp = 4; 37378c2ecf20Sopenharmony_ci goto invalid_fld; 37388c2ecf20Sopenharmony_ci } 37398c2ecf20Sopenharmony_ci 37408c2ecf20Sopenharmony_ci len = cdb[4]; 37418c2ecf20Sopenharmony_ci hdr_len = 4; 37428c2ecf20Sopenharmony_ci } else { 37438c2ecf20Sopenharmony_ci if (scmd->cmd_len < 9) { 37448c2ecf20Sopenharmony_ci fp = 8; 37458c2ecf20Sopenharmony_ci goto invalid_fld; 37468c2ecf20Sopenharmony_ci } 37478c2ecf20Sopenharmony_ci 37488c2ecf20Sopenharmony_ci len = (cdb[7] << 8) + cdb[8]; 37498c2ecf20Sopenharmony_ci hdr_len = 8; 37508c2ecf20Sopenharmony_ci } 37518c2ecf20Sopenharmony_ci 37528c2ecf20Sopenharmony_ci /* We only support PF=1, SP=0. */ 37538c2ecf20Sopenharmony_ci if ((cdb[1] & 0x11) != 0x10) { 37548c2ecf20Sopenharmony_ci fp = 1; 37558c2ecf20Sopenharmony_ci bp = (cdb[1] & 0x01) ? 1 : 5; 37568c2ecf20Sopenharmony_ci goto invalid_fld; 37578c2ecf20Sopenharmony_ci } 37588c2ecf20Sopenharmony_ci 37598c2ecf20Sopenharmony_ci /* Test early for possible overrun. */ 37608c2ecf20Sopenharmony_ci if (!scsi_sg_count(scmd) || scsi_sglist(scmd)->length < len) 37618c2ecf20Sopenharmony_ci goto invalid_param_len; 37628c2ecf20Sopenharmony_ci 37638c2ecf20Sopenharmony_ci /* Move past header and block descriptors. */ 37648c2ecf20Sopenharmony_ci if (len < hdr_len) 37658c2ecf20Sopenharmony_ci goto invalid_param_len; 37668c2ecf20Sopenharmony_ci 37678c2ecf20Sopenharmony_ci if (!sg_copy_to_buffer(scsi_sglist(scmd), scsi_sg_count(scmd), 37688c2ecf20Sopenharmony_ci buffer, sizeof(buffer))) 37698c2ecf20Sopenharmony_ci goto invalid_param_len; 37708c2ecf20Sopenharmony_ci 37718c2ecf20Sopenharmony_ci if (six_byte) 37728c2ecf20Sopenharmony_ci bd_len = p[3]; 37738c2ecf20Sopenharmony_ci else 37748c2ecf20Sopenharmony_ci bd_len = (p[6] << 8) + p[7]; 37758c2ecf20Sopenharmony_ci 37768c2ecf20Sopenharmony_ci len -= hdr_len; 37778c2ecf20Sopenharmony_ci p += hdr_len; 37788c2ecf20Sopenharmony_ci if (len < bd_len) 37798c2ecf20Sopenharmony_ci goto invalid_param_len; 37808c2ecf20Sopenharmony_ci if (bd_len != 0 && bd_len != 8) { 37818c2ecf20Sopenharmony_ci fp = (six_byte) ? 3 : 6; 37828c2ecf20Sopenharmony_ci fp += bd_len + hdr_len; 37838c2ecf20Sopenharmony_ci goto invalid_param; 37848c2ecf20Sopenharmony_ci } 37858c2ecf20Sopenharmony_ci 37868c2ecf20Sopenharmony_ci len -= bd_len; 37878c2ecf20Sopenharmony_ci p += bd_len; 37888c2ecf20Sopenharmony_ci if (len == 0) 37898c2ecf20Sopenharmony_ci goto skip; 37908c2ecf20Sopenharmony_ci 37918c2ecf20Sopenharmony_ci /* Parse both possible formats for the mode page headers. */ 37928c2ecf20Sopenharmony_ci pg = p[0] & 0x3f; 37938c2ecf20Sopenharmony_ci if (p[0] & 0x40) { 37948c2ecf20Sopenharmony_ci if (len < 4) 37958c2ecf20Sopenharmony_ci goto invalid_param_len; 37968c2ecf20Sopenharmony_ci 37978c2ecf20Sopenharmony_ci spg = p[1]; 37988c2ecf20Sopenharmony_ci pg_len = (p[2] << 8) | p[3]; 37998c2ecf20Sopenharmony_ci p += 4; 38008c2ecf20Sopenharmony_ci len -= 4; 38018c2ecf20Sopenharmony_ci } else { 38028c2ecf20Sopenharmony_ci if (len < 2) 38038c2ecf20Sopenharmony_ci goto invalid_param_len; 38048c2ecf20Sopenharmony_ci 38058c2ecf20Sopenharmony_ci spg = 0; 38068c2ecf20Sopenharmony_ci pg_len = p[1]; 38078c2ecf20Sopenharmony_ci p += 2; 38088c2ecf20Sopenharmony_ci len -= 2; 38098c2ecf20Sopenharmony_ci } 38108c2ecf20Sopenharmony_ci 38118c2ecf20Sopenharmony_ci /* 38128c2ecf20Sopenharmony_ci * No mode subpages supported (yet) but asking for _all_ 38138c2ecf20Sopenharmony_ci * subpages may be valid 38148c2ecf20Sopenharmony_ci */ 38158c2ecf20Sopenharmony_ci if (spg && (spg != ALL_SUB_MPAGES)) { 38168c2ecf20Sopenharmony_ci fp = (p[0] & 0x40) ? 1 : 0; 38178c2ecf20Sopenharmony_ci fp += hdr_len + bd_len; 38188c2ecf20Sopenharmony_ci goto invalid_param; 38198c2ecf20Sopenharmony_ci } 38208c2ecf20Sopenharmony_ci if (pg_len > len) 38218c2ecf20Sopenharmony_ci goto invalid_param_len; 38228c2ecf20Sopenharmony_ci 38238c2ecf20Sopenharmony_ci switch (pg) { 38248c2ecf20Sopenharmony_ci case CACHE_MPAGE: 38258c2ecf20Sopenharmony_ci if (ata_mselect_caching(qc, p, pg_len, &fp) < 0) { 38268c2ecf20Sopenharmony_ci fp += hdr_len + bd_len; 38278c2ecf20Sopenharmony_ci goto invalid_param; 38288c2ecf20Sopenharmony_ci } 38298c2ecf20Sopenharmony_ci break; 38308c2ecf20Sopenharmony_ci case CONTROL_MPAGE: 38318c2ecf20Sopenharmony_ci if (ata_mselect_control(qc, p, pg_len, &fp) < 0) { 38328c2ecf20Sopenharmony_ci fp += hdr_len + bd_len; 38338c2ecf20Sopenharmony_ci goto invalid_param; 38348c2ecf20Sopenharmony_ci } else { 38358c2ecf20Sopenharmony_ci goto skip; /* No ATA command to send */ 38368c2ecf20Sopenharmony_ci } 38378c2ecf20Sopenharmony_ci break; 38388c2ecf20Sopenharmony_ci default: /* invalid page code */ 38398c2ecf20Sopenharmony_ci fp = bd_len + hdr_len; 38408c2ecf20Sopenharmony_ci goto invalid_param; 38418c2ecf20Sopenharmony_ci } 38428c2ecf20Sopenharmony_ci 38438c2ecf20Sopenharmony_ci /* 38448c2ecf20Sopenharmony_ci * Only one page has changeable data, so we only support setting one 38458c2ecf20Sopenharmony_ci * page at a time. 38468c2ecf20Sopenharmony_ci */ 38478c2ecf20Sopenharmony_ci if (len > pg_len) 38488c2ecf20Sopenharmony_ci goto invalid_param; 38498c2ecf20Sopenharmony_ci 38508c2ecf20Sopenharmony_ci return 0; 38518c2ecf20Sopenharmony_ci 38528c2ecf20Sopenharmony_ci invalid_fld: 38538c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(qc->dev, scmd, fp, bp); 38548c2ecf20Sopenharmony_ci return 1; 38558c2ecf20Sopenharmony_ci 38568c2ecf20Sopenharmony_ci invalid_param: 38578c2ecf20Sopenharmony_ci ata_scsi_set_invalid_parameter(qc->dev, scmd, fp); 38588c2ecf20Sopenharmony_ci return 1; 38598c2ecf20Sopenharmony_ci 38608c2ecf20Sopenharmony_ci invalid_param_len: 38618c2ecf20Sopenharmony_ci /* "Parameter list length error" */ 38628c2ecf20Sopenharmony_ci ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0); 38638c2ecf20Sopenharmony_ci return 1; 38648c2ecf20Sopenharmony_ci 38658c2ecf20Sopenharmony_ci skip: 38668c2ecf20Sopenharmony_ci scmd->result = SAM_STAT_GOOD; 38678c2ecf20Sopenharmony_ci return 1; 38688c2ecf20Sopenharmony_ci} 38698c2ecf20Sopenharmony_ci 38708c2ecf20Sopenharmony_cistatic u8 ata_scsi_trusted_op(u32 len, bool send, bool dma) 38718c2ecf20Sopenharmony_ci{ 38728c2ecf20Sopenharmony_ci if (len == 0) 38738c2ecf20Sopenharmony_ci return ATA_CMD_TRUSTED_NONDATA; 38748c2ecf20Sopenharmony_ci else if (send) 38758c2ecf20Sopenharmony_ci return dma ? ATA_CMD_TRUSTED_SND_DMA : ATA_CMD_TRUSTED_SND; 38768c2ecf20Sopenharmony_ci else 38778c2ecf20Sopenharmony_ci return dma ? ATA_CMD_TRUSTED_RCV_DMA : ATA_CMD_TRUSTED_RCV; 38788c2ecf20Sopenharmony_ci} 38798c2ecf20Sopenharmony_ci 38808c2ecf20Sopenharmony_cistatic unsigned int ata_scsi_security_inout_xlat(struct ata_queued_cmd *qc) 38818c2ecf20Sopenharmony_ci{ 38828c2ecf20Sopenharmony_ci struct scsi_cmnd *scmd = qc->scsicmd; 38838c2ecf20Sopenharmony_ci const u8 *cdb = scmd->cmnd; 38848c2ecf20Sopenharmony_ci struct ata_taskfile *tf = &qc->tf; 38858c2ecf20Sopenharmony_ci u8 secp = cdb[1]; 38868c2ecf20Sopenharmony_ci bool send = (cdb[0] == SECURITY_PROTOCOL_OUT); 38878c2ecf20Sopenharmony_ci u16 spsp = get_unaligned_be16(&cdb[2]); 38888c2ecf20Sopenharmony_ci u32 len = get_unaligned_be32(&cdb[6]); 38898c2ecf20Sopenharmony_ci bool dma = !(qc->dev->flags & ATA_DFLAG_PIO); 38908c2ecf20Sopenharmony_ci 38918c2ecf20Sopenharmony_ci /* 38928c2ecf20Sopenharmony_ci * We don't support the ATA "security" protocol. 38938c2ecf20Sopenharmony_ci */ 38948c2ecf20Sopenharmony_ci if (secp == 0xef) { 38958c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(qc->dev, scmd, 1, 0); 38968c2ecf20Sopenharmony_ci return 1; 38978c2ecf20Sopenharmony_ci } 38988c2ecf20Sopenharmony_ci 38998c2ecf20Sopenharmony_ci if (cdb[4] & 7) { /* INC_512 */ 39008c2ecf20Sopenharmony_ci if (len > 0xffff) { 39018c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(qc->dev, scmd, 6, 0); 39028c2ecf20Sopenharmony_ci return 1; 39038c2ecf20Sopenharmony_ci } 39048c2ecf20Sopenharmony_ci } else { 39058c2ecf20Sopenharmony_ci if (len > 0x01fffe00) { 39068c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(qc->dev, scmd, 6, 0); 39078c2ecf20Sopenharmony_ci return 1; 39088c2ecf20Sopenharmony_ci } 39098c2ecf20Sopenharmony_ci 39108c2ecf20Sopenharmony_ci /* convert to the sector-based ATA addressing */ 39118c2ecf20Sopenharmony_ci len = (len + 511) / 512; 39128c2ecf20Sopenharmony_ci } 39138c2ecf20Sopenharmony_ci 39148c2ecf20Sopenharmony_ci tf->protocol = dma ? ATA_PROT_DMA : ATA_PROT_PIO; 39158c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR | ATA_TFLAG_LBA; 39168c2ecf20Sopenharmony_ci if (send) 39178c2ecf20Sopenharmony_ci tf->flags |= ATA_TFLAG_WRITE; 39188c2ecf20Sopenharmony_ci tf->command = ata_scsi_trusted_op(len, send, dma); 39198c2ecf20Sopenharmony_ci tf->feature = secp; 39208c2ecf20Sopenharmony_ci tf->lbam = spsp & 0xff; 39218c2ecf20Sopenharmony_ci tf->lbah = spsp >> 8; 39228c2ecf20Sopenharmony_ci 39238c2ecf20Sopenharmony_ci if (len) { 39248c2ecf20Sopenharmony_ci tf->nsect = len & 0xff; 39258c2ecf20Sopenharmony_ci tf->lbal = len >> 8; 39268c2ecf20Sopenharmony_ci } else { 39278c2ecf20Sopenharmony_ci if (!send) 39288c2ecf20Sopenharmony_ci tf->lbah = (1 << 7); 39298c2ecf20Sopenharmony_ci } 39308c2ecf20Sopenharmony_ci 39318c2ecf20Sopenharmony_ci ata_qc_set_pc_nbytes(qc); 39328c2ecf20Sopenharmony_ci return 0; 39338c2ecf20Sopenharmony_ci} 39348c2ecf20Sopenharmony_ci 39358c2ecf20Sopenharmony_ci/** 39368c2ecf20Sopenharmony_ci * ata_scsi_var_len_cdb_xlat - SATL variable length CDB to Handler 39378c2ecf20Sopenharmony_ci * @qc: Command to be translated 39388c2ecf20Sopenharmony_ci * 39398c2ecf20Sopenharmony_ci * Translate a SCSI variable length CDB to specified commands. 39408c2ecf20Sopenharmony_ci * It checks a service action value in CDB to call corresponding handler. 39418c2ecf20Sopenharmony_ci * 39428c2ecf20Sopenharmony_ci * RETURNS: 39438c2ecf20Sopenharmony_ci * Zero on success, non-zero on failure 39448c2ecf20Sopenharmony_ci * 39458c2ecf20Sopenharmony_ci */ 39468c2ecf20Sopenharmony_cistatic unsigned int ata_scsi_var_len_cdb_xlat(struct ata_queued_cmd *qc) 39478c2ecf20Sopenharmony_ci{ 39488c2ecf20Sopenharmony_ci struct scsi_cmnd *scmd = qc->scsicmd; 39498c2ecf20Sopenharmony_ci const u8 *cdb = scmd->cmnd; 39508c2ecf20Sopenharmony_ci const u16 sa = get_unaligned_be16(&cdb[8]); 39518c2ecf20Sopenharmony_ci 39528c2ecf20Sopenharmony_ci /* 39538c2ecf20Sopenharmony_ci * if service action represents a ata pass-thru(32) command, 39548c2ecf20Sopenharmony_ci * then pass it to ata_scsi_pass_thru handler. 39558c2ecf20Sopenharmony_ci */ 39568c2ecf20Sopenharmony_ci if (sa == ATA_32) 39578c2ecf20Sopenharmony_ci return ata_scsi_pass_thru(qc); 39588c2ecf20Sopenharmony_ci 39598c2ecf20Sopenharmony_ci /* unsupported service action */ 39608c2ecf20Sopenharmony_ci return 1; 39618c2ecf20Sopenharmony_ci} 39628c2ecf20Sopenharmony_ci 39638c2ecf20Sopenharmony_ci/** 39648c2ecf20Sopenharmony_ci * ata_get_xlat_func - check if SCSI to ATA translation is possible 39658c2ecf20Sopenharmony_ci * @dev: ATA device 39668c2ecf20Sopenharmony_ci * @cmd: SCSI command opcode to consider 39678c2ecf20Sopenharmony_ci * 39688c2ecf20Sopenharmony_ci * Look up the SCSI command given, and determine whether the 39698c2ecf20Sopenharmony_ci * SCSI command is to be translated or simulated. 39708c2ecf20Sopenharmony_ci * 39718c2ecf20Sopenharmony_ci * RETURNS: 39728c2ecf20Sopenharmony_ci * Pointer to translation function if possible, %NULL if not. 39738c2ecf20Sopenharmony_ci */ 39748c2ecf20Sopenharmony_ci 39758c2ecf20Sopenharmony_cistatic inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd) 39768c2ecf20Sopenharmony_ci{ 39778c2ecf20Sopenharmony_ci switch (cmd) { 39788c2ecf20Sopenharmony_ci case READ_6: 39798c2ecf20Sopenharmony_ci case READ_10: 39808c2ecf20Sopenharmony_ci case READ_16: 39818c2ecf20Sopenharmony_ci 39828c2ecf20Sopenharmony_ci case WRITE_6: 39838c2ecf20Sopenharmony_ci case WRITE_10: 39848c2ecf20Sopenharmony_ci case WRITE_16: 39858c2ecf20Sopenharmony_ci return ata_scsi_rw_xlat; 39868c2ecf20Sopenharmony_ci 39878c2ecf20Sopenharmony_ci case WRITE_SAME_16: 39888c2ecf20Sopenharmony_ci return ata_scsi_write_same_xlat; 39898c2ecf20Sopenharmony_ci 39908c2ecf20Sopenharmony_ci case SYNCHRONIZE_CACHE: 39918c2ecf20Sopenharmony_ci case SYNCHRONIZE_CACHE_16: 39928c2ecf20Sopenharmony_ci if (ata_try_flush_cache(dev)) 39938c2ecf20Sopenharmony_ci return ata_scsi_flush_xlat; 39948c2ecf20Sopenharmony_ci break; 39958c2ecf20Sopenharmony_ci 39968c2ecf20Sopenharmony_ci case VERIFY: 39978c2ecf20Sopenharmony_ci case VERIFY_16: 39988c2ecf20Sopenharmony_ci return ata_scsi_verify_xlat; 39998c2ecf20Sopenharmony_ci 40008c2ecf20Sopenharmony_ci case ATA_12: 40018c2ecf20Sopenharmony_ci case ATA_16: 40028c2ecf20Sopenharmony_ci return ata_scsi_pass_thru; 40038c2ecf20Sopenharmony_ci 40048c2ecf20Sopenharmony_ci case VARIABLE_LENGTH_CMD: 40058c2ecf20Sopenharmony_ci return ata_scsi_var_len_cdb_xlat; 40068c2ecf20Sopenharmony_ci 40078c2ecf20Sopenharmony_ci case MODE_SELECT: 40088c2ecf20Sopenharmony_ci case MODE_SELECT_10: 40098c2ecf20Sopenharmony_ci return ata_scsi_mode_select_xlat; 40108c2ecf20Sopenharmony_ci break; 40118c2ecf20Sopenharmony_ci 40128c2ecf20Sopenharmony_ci case ZBC_IN: 40138c2ecf20Sopenharmony_ci return ata_scsi_zbc_in_xlat; 40148c2ecf20Sopenharmony_ci 40158c2ecf20Sopenharmony_ci case ZBC_OUT: 40168c2ecf20Sopenharmony_ci return ata_scsi_zbc_out_xlat; 40178c2ecf20Sopenharmony_ci 40188c2ecf20Sopenharmony_ci case SECURITY_PROTOCOL_IN: 40198c2ecf20Sopenharmony_ci case SECURITY_PROTOCOL_OUT: 40208c2ecf20Sopenharmony_ci if (!(dev->flags & ATA_DFLAG_TRUSTED)) 40218c2ecf20Sopenharmony_ci break; 40228c2ecf20Sopenharmony_ci return ata_scsi_security_inout_xlat; 40238c2ecf20Sopenharmony_ci 40248c2ecf20Sopenharmony_ci case START_STOP: 40258c2ecf20Sopenharmony_ci return ata_scsi_start_stop_xlat; 40268c2ecf20Sopenharmony_ci } 40278c2ecf20Sopenharmony_ci 40288c2ecf20Sopenharmony_ci return NULL; 40298c2ecf20Sopenharmony_ci} 40308c2ecf20Sopenharmony_ci 40318c2ecf20Sopenharmony_ci/** 40328c2ecf20Sopenharmony_ci * ata_scsi_dump_cdb - dump SCSI command contents to dmesg 40338c2ecf20Sopenharmony_ci * @ap: ATA port to which the command was being sent 40348c2ecf20Sopenharmony_ci * @cmd: SCSI command to dump 40358c2ecf20Sopenharmony_ci * 40368c2ecf20Sopenharmony_ci * Prints the contents of a SCSI command via printk(). 40378c2ecf20Sopenharmony_ci */ 40388c2ecf20Sopenharmony_ci 40398c2ecf20Sopenharmony_civoid ata_scsi_dump_cdb(struct ata_port *ap, struct scsi_cmnd *cmd) 40408c2ecf20Sopenharmony_ci{ 40418c2ecf20Sopenharmony_ci#ifdef ATA_VERBOSE_DEBUG 40428c2ecf20Sopenharmony_ci struct scsi_device *scsidev = cmd->device; 40438c2ecf20Sopenharmony_ci 40448c2ecf20Sopenharmony_ci VPRINTK("CDB (%u:%d,%d,%lld) %9ph\n", 40458c2ecf20Sopenharmony_ci ap->print_id, 40468c2ecf20Sopenharmony_ci scsidev->channel, scsidev->id, scsidev->lun, 40478c2ecf20Sopenharmony_ci cmd->cmnd); 40488c2ecf20Sopenharmony_ci#endif 40498c2ecf20Sopenharmony_ci} 40508c2ecf20Sopenharmony_ci 40518c2ecf20Sopenharmony_ciint __ata_scsi_queuecmd(struct scsi_cmnd *scmd, struct ata_device *dev) 40528c2ecf20Sopenharmony_ci{ 40538c2ecf20Sopenharmony_ci struct ata_port *ap = dev->link->ap; 40548c2ecf20Sopenharmony_ci u8 scsi_op = scmd->cmnd[0]; 40558c2ecf20Sopenharmony_ci ata_xlat_func_t xlat_func; 40568c2ecf20Sopenharmony_ci 40578c2ecf20Sopenharmony_ci /* 40588c2ecf20Sopenharmony_ci * scsi_queue_rq() will defer commands if scsi_host_in_recovery(). 40598c2ecf20Sopenharmony_ci * However, this check is done without holding the ap->lock (a libata 40608c2ecf20Sopenharmony_ci * specific lock), so we can have received an error irq since then, 40618c2ecf20Sopenharmony_ci * therefore we must check if EH is pending, while holding ap->lock. 40628c2ecf20Sopenharmony_ci */ 40638c2ecf20Sopenharmony_ci if (ap->pflags & (ATA_PFLAG_EH_PENDING | ATA_PFLAG_EH_IN_PROGRESS)) 40648c2ecf20Sopenharmony_ci return SCSI_MLQUEUE_DEVICE_BUSY; 40658c2ecf20Sopenharmony_ci 40668c2ecf20Sopenharmony_ci if (unlikely(!scmd->cmd_len)) 40678c2ecf20Sopenharmony_ci goto bad_cdb_len; 40688c2ecf20Sopenharmony_ci 40698c2ecf20Sopenharmony_ci if (dev->class == ATA_DEV_ATA || dev->class == ATA_DEV_ZAC) { 40708c2ecf20Sopenharmony_ci if (unlikely(scmd->cmd_len > dev->cdb_len)) 40718c2ecf20Sopenharmony_ci goto bad_cdb_len; 40728c2ecf20Sopenharmony_ci 40738c2ecf20Sopenharmony_ci xlat_func = ata_get_xlat_func(dev, scsi_op); 40748c2ecf20Sopenharmony_ci } else if (likely((scsi_op != ATA_16) || !atapi_passthru16)) { 40758c2ecf20Sopenharmony_ci /* relay SCSI command to ATAPI device */ 40768c2ecf20Sopenharmony_ci int len = COMMAND_SIZE(scsi_op); 40778c2ecf20Sopenharmony_ci 40788c2ecf20Sopenharmony_ci if (unlikely(len > scmd->cmd_len || 40798c2ecf20Sopenharmony_ci len > dev->cdb_len || 40808c2ecf20Sopenharmony_ci scmd->cmd_len > ATAPI_CDB_LEN)) 40818c2ecf20Sopenharmony_ci goto bad_cdb_len; 40828c2ecf20Sopenharmony_ci 40838c2ecf20Sopenharmony_ci xlat_func = atapi_xlat; 40848c2ecf20Sopenharmony_ci } else { 40858c2ecf20Sopenharmony_ci /* ATA_16 passthru, treat as an ATA command */ 40868c2ecf20Sopenharmony_ci if (unlikely(scmd->cmd_len > 16)) 40878c2ecf20Sopenharmony_ci goto bad_cdb_len; 40888c2ecf20Sopenharmony_ci 40898c2ecf20Sopenharmony_ci xlat_func = ata_get_xlat_func(dev, scsi_op); 40908c2ecf20Sopenharmony_ci } 40918c2ecf20Sopenharmony_ci 40928c2ecf20Sopenharmony_ci if (xlat_func) 40938c2ecf20Sopenharmony_ci return ata_scsi_translate(dev, scmd, xlat_func); 40948c2ecf20Sopenharmony_ci 40958c2ecf20Sopenharmony_ci ata_scsi_simulate(dev, scmd); 40968c2ecf20Sopenharmony_ci 40978c2ecf20Sopenharmony_ci return 0; 40988c2ecf20Sopenharmony_ci 40998c2ecf20Sopenharmony_ci bad_cdb_len: 41008c2ecf20Sopenharmony_ci DPRINTK("bad CDB len=%u, scsi_op=0x%02x, max=%u\n", 41018c2ecf20Sopenharmony_ci scmd->cmd_len, scsi_op, dev->cdb_len); 41028c2ecf20Sopenharmony_ci scmd->result = DID_ERROR << 16; 41038c2ecf20Sopenharmony_ci scmd->scsi_done(scmd); 41048c2ecf20Sopenharmony_ci return 0; 41058c2ecf20Sopenharmony_ci} 41068c2ecf20Sopenharmony_ci 41078c2ecf20Sopenharmony_ci/** 41088c2ecf20Sopenharmony_ci * ata_scsi_queuecmd - Issue SCSI cdb to libata-managed device 41098c2ecf20Sopenharmony_ci * @shost: SCSI host of command to be sent 41108c2ecf20Sopenharmony_ci * @cmd: SCSI command to be sent 41118c2ecf20Sopenharmony_ci * 41128c2ecf20Sopenharmony_ci * In some cases, this function translates SCSI commands into 41138c2ecf20Sopenharmony_ci * ATA taskfiles, and queues the taskfiles to be sent to 41148c2ecf20Sopenharmony_ci * hardware. In other cases, this function simulates a 41158c2ecf20Sopenharmony_ci * SCSI device by evaluating and responding to certain 41168c2ecf20Sopenharmony_ci * SCSI commands. This creates the overall effect of 41178c2ecf20Sopenharmony_ci * ATA and ATAPI devices appearing as SCSI devices. 41188c2ecf20Sopenharmony_ci * 41198c2ecf20Sopenharmony_ci * LOCKING: 41208c2ecf20Sopenharmony_ci * ATA host lock 41218c2ecf20Sopenharmony_ci * 41228c2ecf20Sopenharmony_ci * RETURNS: 41238c2ecf20Sopenharmony_ci * Return value from __ata_scsi_queuecmd() if @cmd can be queued, 41248c2ecf20Sopenharmony_ci * 0 otherwise. 41258c2ecf20Sopenharmony_ci */ 41268c2ecf20Sopenharmony_ciint ata_scsi_queuecmd(struct Scsi_Host *shost, struct scsi_cmnd *cmd) 41278c2ecf20Sopenharmony_ci{ 41288c2ecf20Sopenharmony_ci struct ata_port *ap; 41298c2ecf20Sopenharmony_ci struct ata_device *dev; 41308c2ecf20Sopenharmony_ci struct scsi_device *scsidev = cmd->device; 41318c2ecf20Sopenharmony_ci int rc = 0; 41328c2ecf20Sopenharmony_ci unsigned long irq_flags; 41338c2ecf20Sopenharmony_ci 41348c2ecf20Sopenharmony_ci ap = ata_shost_to_port(shost); 41358c2ecf20Sopenharmony_ci 41368c2ecf20Sopenharmony_ci spin_lock_irqsave(ap->lock, irq_flags); 41378c2ecf20Sopenharmony_ci 41388c2ecf20Sopenharmony_ci ata_scsi_dump_cdb(ap, cmd); 41398c2ecf20Sopenharmony_ci 41408c2ecf20Sopenharmony_ci dev = ata_scsi_find_dev(ap, scsidev); 41418c2ecf20Sopenharmony_ci if (likely(dev)) 41428c2ecf20Sopenharmony_ci rc = __ata_scsi_queuecmd(cmd, dev); 41438c2ecf20Sopenharmony_ci else { 41448c2ecf20Sopenharmony_ci cmd->result = (DID_BAD_TARGET << 16); 41458c2ecf20Sopenharmony_ci cmd->scsi_done(cmd); 41468c2ecf20Sopenharmony_ci } 41478c2ecf20Sopenharmony_ci 41488c2ecf20Sopenharmony_ci spin_unlock_irqrestore(ap->lock, irq_flags); 41498c2ecf20Sopenharmony_ci 41508c2ecf20Sopenharmony_ci return rc; 41518c2ecf20Sopenharmony_ci} 41528c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ata_scsi_queuecmd); 41538c2ecf20Sopenharmony_ci 41548c2ecf20Sopenharmony_ci/** 41558c2ecf20Sopenharmony_ci * ata_scsi_simulate - simulate SCSI command on ATA device 41568c2ecf20Sopenharmony_ci * @dev: the target device 41578c2ecf20Sopenharmony_ci * @cmd: SCSI command being sent to device. 41588c2ecf20Sopenharmony_ci * 41598c2ecf20Sopenharmony_ci * Interprets and directly executes a select list of SCSI commands 41608c2ecf20Sopenharmony_ci * that can be handled internally. 41618c2ecf20Sopenharmony_ci * 41628c2ecf20Sopenharmony_ci * LOCKING: 41638c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 41648c2ecf20Sopenharmony_ci */ 41658c2ecf20Sopenharmony_ci 41668c2ecf20Sopenharmony_civoid ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) 41678c2ecf20Sopenharmony_ci{ 41688c2ecf20Sopenharmony_ci struct ata_scsi_args args; 41698c2ecf20Sopenharmony_ci const u8 *scsicmd = cmd->cmnd; 41708c2ecf20Sopenharmony_ci u8 tmp8; 41718c2ecf20Sopenharmony_ci 41728c2ecf20Sopenharmony_ci args.dev = dev; 41738c2ecf20Sopenharmony_ci args.id = dev->id; 41748c2ecf20Sopenharmony_ci args.cmd = cmd; 41758c2ecf20Sopenharmony_ci 41768c2ecf20Sopenharmony_ci switch(scsicmd[0]) { 41778c2ecf20Sopenharmony_ci case INQUIRY: 41788c2ecf20Sopenharmony_ci if (scsicmd[1] & 2) /* is CmdDt set? */ 41798c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(dev, cmd, 1, 0xff); 41808c2ecf20Sopenharmony_ci else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */ 41818c2ecf20Sopenharmony_ci ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std); 41828c2ecf20Sopenharmony_ci else switch (scsicmd[2]) { 41838c2ecf20Sopenharmony_ci case 0x00: 41848c2ecf20Sopenharmony_ci ata_scsi_rbuf_fill(&args, ata_scsiop_inq_00); 41858c2ecf20Sopenharmony_ci break; 41868c2ecf20Sopenharmony_ci case 0x80: 41878c2ecf20Sopenharmony_ci ata_scsi_rbuf_fill(&args, ata_scsiop_inq_80); 41888c2ecf20Sopenharmony_ci break; 41898c2ecf20Sopenharmony_ci case 0x83: 41908c2ecf20Sopenharmony_ci ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83); 41918c2ecf20Sopenharmony_ci break; 41928c2ecf20Sopenharmony_ci case 0x89: 41938c2ecf20Sopenharmony_ci ata_scsi_rbuf_fill(&args, ata_scsiop_inq_89); 41948c2ecf20Sopenharmony_ci break; 41958c2ecf20Sopenharmony_ci case 0xb0: 41968c2ecf20Sopenharmony_ci ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b0); 41978c2ecf20Sopenharmony_ci break; 41988c2ecf20Sopenharmony_ci case 0xb1: 41998c2ecf20Sopenharmony_ci ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b1); 42008c2ecf20Sopenharmony_ci break; 42018c2ecf20Sopenharmony_ci case 0xb2: 42028c2ecf20Sopenharmony_ci ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2); 42038c2ecf20Sopenharmony_ci break; 42048c2ecf20Sopenharmony_ci case 0xb6: 42058c2ecf20Sopenharmony_ci if (dev->flags & ATA_DFLAG_ZAC) { 42068c2ecf20Sopenharmony_ci ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b6); 42078c2ecf20Sopenharmony_ci break; 42088c2ecf20Sopenharmony_ci } 42098c2ecf20Sopenharmony_ci fallthrough; 42108c2ecf20Sopenharmony_ci default: 42118c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(dev, cmd, 2, 0xff); 42128c2ecf20Sopenharmony_ci break; 42138c2ecf20Sopenharmony_ci } 42148c2ecf20Sopenharmony_ci break; 42158c2ecf20Sopenharmony_ci 42168c2ecf20Sopenharmony_ci case MODE_SENSE: 42178c2ecf20Sopenharmony_ci case MODE_SENSE_10: 42188c2ecf20Sopenharmony_ci ata_scsi_rbuf_fill(&args, ata_scsiop_mode_sense); 42198c2ecf20Sopenharmony_ci break; 42208c2ecf20Sopenharmony_ci 42218c2ecf20Sopenharmony_ci case READ_CAPACITY: 42228c2ecf20Sopenharmony_ci ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap); 42238c2ecf20Sopenharmony_ci break; 42248c2ecf20Sopenharmony_ci 42258c2ecf20Sopenharmony_ci case SERVICE_ACTION_IN_16: 42268c2ecf20Sopenharmony_ci if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16) 42278c2ecf20Sopenharmony_ci ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap); 42288c2ecf20Sopenharmony_ci else 42298c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(dev, cmd, 1, 0xff); 42308c2ecf20Sopenharmony_ci break; 42318c2ecf20Sopenharmony_ci 42328c2ecf20Sopenharmony_ci case REPORT_LUNS: 42338c2ecf20Sopenharmony_ci ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns); 42348c2ecf20Sopenharmony_ci break; 42358c2ecf20Sopenharmony_ci 42368c2ecf20Sopenharmony_ci case REQUEST_SENSE: 42378c2ecf20Sopenharmony_ci ata_scsi_set_sense(dev, cmd, 0, 0, 0); 42388c2ecf20Sopenharmony_ci cmd->result = (DRIVER_SENSE << 24); 42398c2ecf20Sopenharmony_ci break; 42408c2ecf20Sopenharmony_ci 42418c2ecf20Sopenharmony_ci /* if we reach this, then writeback caching is disabled, 42428c2ecf20Sopenharmony_ci * turning this into a no-op. 42438c2ecf20Sopenharmony_ci */ 42448c2ecf20Sopenharmony_ci case SYNCHRONIZE_CACHE: 42458c2ecf20Sopenharmony_ci case SYNCHRONIZE_CACHE_16: 42468c2ecf20Sopenharmony_ci fallthrough; 42478c2ecf20Sopenharmony_ci 42488c2ecf20Sopenharmony_ci /* no-op's, complete with success */ 42498c2ecf20Sopenharmony_ci case REZERO_UNIT: 42508c2ecf20Sopenharmony_ci case SEEK_6: 42518c2ecf20Sopenharmony_ci case SEEK_10: 42528c2ecf20Sopenharmony_ci case TEST_UNIT_READY: 42538c2ecf20Sopenharmony_ci break; 42548c2ecf20Sopenharmony_ci 42558c2ecf20Sopenharmony_ci case SEND_DIAGNOSTIC: 42568c2ecf20Sopenharmony_ci tmp8 = scsicmd[1] & ~(1 << 3); 42578c2ecf20Sopenharmony_ci if (tmp8 != 0x4 || scsicmd[3] || scsicmd[4]) 42588c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(dev, cmd, 1, 0xff); 42598c2ecf20Sopenharmony_ci break; 42608c2ecf20Sopenharmony_ci 42618c2ecf20Sopenharmony_ci case MAINTENANCE_IN: 42628c2ecf20Sopenharmony_ci if ((scsicmd[1] & 0x1f) == MI_REPORT_SUPPORTED_OPERATION_CODES) 42638c2ecf20Sopenharmony_ci ata_scsi_rbuf_fill(&args, ata_scsiop_maint_in); 42648c2ecf20Sopenharmony_ci else 42658c2ecf20Sopenharmony_ci ata_scsi_set_invalid_field(dev, cmd, 1, 0xff); 42668c2ecf20Sopenharmony_ci break; 42678c2ecf20Sopenharmony_ci 42688c2ecf20Sopenharmony_ci /* all other commands */ 42698c2ecf20Sopenharmony_ci default: 42708c2ecf20Sopenharmony_ci ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x20, 0x0); 42718c2ecf20Sopenharmony_ci /* "Invalid command operation code" */ 42728c2ecf20Sopenharmony_ci break; 42738c2ecf20Sopenharmony_ci } 42748c2ecf20Sopenharmony_ci 42758c2ecf20Sopenharmony_ci cmd->scsi_done(cmd); 42768c2ecf20Sopenharmony_ci} 42778c2ecf20Sopenharmony_ci 42788c2ecf20Sopenharmony_ciint ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht) 42798c2ecf20Sopenharmony_ci{ 42808c2ecf20Sopenharmony_ci int i, rc; 42818c2ecf20Sopenharmony_ci 42828c2ecf20Sopenharmony_ci for (i = 0; i < host->n_ports; i++) { 42838c2ecf20Sopenharmony_ci struct ata_port *ap = host->ports[i]; 42848c2ecf20Sopenharmony_ci struct Scsi_Host *shost; 42858c2ecf20Sopenharmony_ci 42868c2ecf20Sopenharmony_ci rc = -ENOMEM; 42878c2ecf20Sopenharmony_ci shost = scsi_host_alloc(sht, sizeof(struct ata_port *)); 42888c2ecf20Sopenharmony_ci if (!shost) 42898c2ecf20Sopenharmony_ci goto err_alloc; 42908c2ecf20Sopenharmony_ci 42918c2ecf20Sopenharmony_ci shost->eh_noresume = 1; 42928c2ecf20Sopenharmony_ci *(struct ata_port **)&shost->hostdata[0] = ap; 42938c2ecf20Sopenharmony_ci ap->scsi_host = shost; 42948c2ecf20Sopenharmony_ci 42958c2ecf20Sopenharmony_ci shost->transportt = ata_scsi_transport_template; 42968c2ecf20Sopenharmony_ci shost->unique_id = ap->print_id; 42978c2ecf20Sopenharmony_ci shost->max_id = 16; 42988c2ecf20Sopenharmony_ci shost->max_lun = 1; 42998c2ecf20Sopenharmony_ci shost->max_channel = 1; 43008c2ecf20Sopenharmony_ci shost->max_cmd_len = 32; 43018c2ecf20Sopenharmony_ci 43028c2ecf20Sopenharmony_ci /* Schedule policy is determined by ->qc_defer() 43038c2ecf20Sopenharmony_ci * callback and it needs to see every deferred qc. 43048c2ecf20Sopenharmony_ci * Set host_blocked to 1 to prevent SCSI midlayer from 43058c2ecf20Sopenharmony_ci * automatically deferring requests. 43068c2ecf20Sopenharmony_ci */ 43078c2ecf20Sopenharmony_ci shost->max_host_blocked = 1; 43088c2ecf20Sopenharmony_ci 43098c2ecf20Sopenharmony_ci rc = scsi_add_host_with_dma(shost, &ap->tdev, ap->host->dev); 43108c2ecf20Sopenharmony_ci if (rc) 43118c2ecf20Sopenharmony_ci goto err_alloc; 43128c2ecf20Sopenharmony_ci } 43138c2ecf20Sopenharmony_ci 43148c2ecf20Sopenharmony_ci return 0; 43158c2ecf20Sopenharmony_ci 43168c2ecf20Sopenharmony_ci err_alloc: 43178c2ecf20Sopenharmony_ci while (--i >= 0) { 43188c2ecf20Sopenharmony_ci struct Scsi_Host *shost = host->ports[i]->scsi_host; 43198c2ecf20Sopenharmony_ci 43208c2ecf20Sopenharmony_ci /* scsi_host_put() is in ata_devres_release() */ 43218c2ecf20Sopenharmony_ci scsi_remove_host(shost); 43228c2ecf20Sopenharmony_ci } 43238c2ecf20Sopenharmony_ci return rc; 43248c2ecf20Sopenharmony_ci} 43258c2ecf20Sopenharmony_ci 43268c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 43278c2ecf20Sopenharmony_cistatic void ata_scsi_assign_ofnode(struct ata_device *dev, struct ata_port *ap) 43288c2ecf20Sopenharmony_ci{ 43298c2ecf20Sopenharmony_ci struct scsi_device *sdev = dev->sdev; 43308c2ecf20Sopenharmony_ci struct device *d = ap->host->dev; 43318c2ecf20Sopenharmony_ci struct device_node *np = d->of_node; 43328c2ecf20Sopenharmony_ci struct device_node *child; 43338c2ecf20Sopenharmony_ci 43348c2ecf20Sopenharmony_ci for_each_available_child_of_node(np, child) { 43358c2ecf20Sopenharmony_ci int ret; 43368c2ecf20Sopenharmony_ci u32 val; 43378c2ecf20Sopenharmony_ci 43388c2ecf20Sopenharmony_ci ret = of_property_read_u32(child, "reg", &val); 43398c2ecf20Sopenharmony_ci if (ret) 43408c2ecf20Sopenharmony_ci continue; 43418c2ecf20Sopenharmony_ci if (val == dev->devno) { 43428c2ecf20Sopenharmony_ci dev_dbg(d, "found matching device node\n"); 43438c2ecf20Sopenharmony_ci sdev->sdev_gendev.of_node = child; 43448c2ecf20Sopenharmony_ci return; 43458c2ecf20Sopenharmony_ci } 43468c2ecf20Sopenharmony_ci } 43478c2ecf20Sopenharmony_ci} 43488c2ecf20Sopenharmony_ci#else 43498c2ecf20Sopenharmony_cistatic void ata_scsi_assign_ofnode(struct ata_device *dev, struct ata_port *ap) 43508c2ecf20Sopenharmony_ci{ 43518c2ecf20Sopenharmony_ci} 43528c2ecf20Sopenharmony_ci#endif 43538c2ecf20Sopenharmony_ci 43548c2ecf20Sopenharmony_civoid ata_scsi_scan_host(struct ata_port *ap, int sync) 43558c2ecf20Sopenharmony_ci{ 43568c2ecf20Sopenharmony_ci int tries = 5; 43578c2ecf20Sopenharmony_ci struct ata_device *last_failed_dev = NULL; 43588c2ecf20Sopenharmony_ci struct ata_link *link; 43598c2ecf20Sopenharmony_ci struct ata_device *dev; 43608c2ecf20Sopenharmony_ci 43618c2ecf20Sopenharmony_ci repeat: 43628c2ecf20Sopenharmony_ci ata_for_each_link(link, ap, EDGE) { 43638c2ecf20Sopenharmony_ci ata_for_each_dev(dev, link, ENABLED) { 43648c2ecf20Sopenharmony_ci struct scsi_device *sdev; 43658c2ecf20Sopenharmony_ci int channel = 0, id = 0; 43668c2ecf20Sopenharmony_ci 43678c2ecf20Sopenharmony_ci if (dev->sdev) 43688c2ecf20Sopenharmony_ci continue; 43698c2ecf20Sopenharmony_ci 43708c2ecf20Sopenharmony_ci if (ata_is_host_link(link)) 43718c2ecf20Sopenharmony_ci id = dev->devno; 43728c2ecf20Sopenharmony_ci else 43738c2ecf20Sopenharmony_ci channel = link->pmp; 43748c2ecf20Sopenharmony_ci 43758c2ecf20Sopenharmony_ci sdev = __scsi_add_device(ap->scsi_host, channel, id, 0, 43768c2ecf20Sopenharmony_ci NULL); 43778c2ecf20Sopenharmony_ci if (!IS_ERR(sdev)) { 43788c2ecf20Sopenharmony_ci dev->sdev = sdev; 43798c2ecf20Sopenharmony_ci ata_scsi_assign_ofnode(dev, ap); 43808c2ecf20Sopenharmony_ci scsi_device_put(sdev); 43818c2ecf20Sopenharmony_ci } else { 43828c2ecf20Sopenharmony_ci dev->sdev = NULL; 43838c2ecf20Sopenharmony_ci } 43848c2ecf20Sopenharmony_ci } 43858c2ecf20Sopenharmony_ci } 43868c2ecf20Sopenharmony_ci 43878c2ecf20Sopenharmony_ci /* If we scanned while EH was in progress or allocation 43888c2ecf20Sopenharmony_ci * failure occurred, scan would have failed silently. Check 43898c2ecf20Sopenharmony_ci * whether all devices are attached. 43908c2ecf20Sopenharmony_ci */ 43918c2ecf20Sopenharmony_ci ata_for_each_link(link, ap, EDGE) { 43928c2ecf20Sopenharmony_ci ata_for_each_dev(dev, link, ENABLED) { 43938c2ecf20Sopenharmony_ci if (!dev->sdev) 43948c2ecf20Sopenharmony_ci goto exit_loop; 43958c2ecf20Sopenharmony_ci } 43968c2ecf20Sopenharmony_ci } 43978c2ecf20Sopenharmony_ci exit_loop: 43988c2ecf20Sopenharmony_ci if (!link) 43998c2ecf20Sopenharmony_ci return; 44008c2ecf20Sopenharmony_ci 44018c2ecf20Sopenharmony_ci /* we're missing some SCSI devices */ 44028c2ecf20Sopenharmony_ci if (sync) { 44038c2ecf20Sopenharmony_ci /* If caller requested synchrnous scan && we've made 44048c2ecf20Sopenharmony_ci * any progress, sleep briefly and repeat. 44058c2ecf20Sopenharmony_ci */ 44068c2ecf20Sopenharmony_ci if (dev != last_failed_dev) { 44078c2ecf20Sopenharmony_ci msleep(100); 44088c2ecf20Sopenharmony_ci last_failed_dev = dev; 44098c2ecf20Sopenharmony_ci goto repeat; 44108c2ecf20Sopenharmony_ci } 44118c2ecf20Sopenharmony_ci 44128c2ecf20Sopenharmony_ci /* We might be failing to detect boot device, give it 44138c2ecf20Sopenharmony_ci * a few more chances. 44148c2ecf20Sopenharmony_ci */ 44158c2ecf20Sopenharmony_ci if (--tries) { 44168c2ecf20Sopenharmony_ci msleep(100); 44178c2ecf20Sopenharmony_ci goto repeat; 44188c2ecf20Sopenharmony_ci } 44198c2ecf20Sopenharmony_ci 44208c2ecf20Sopenharmony_ci ata_port_err(ap, 44218c2ecf20Sopenharmony_ci "WARNING: synchronous SCSI scan failed without making any progress, switching to async\n"); 44228c2ecf20Sopenharmony_ci } 44238c2ecf20Sopenharmony_ci 44248c2ecf20Sopenharmony_ci queue_delayed_work(system_long_wq, &ap->hotplug_task, 44258c2ecf20Sopenharmony_ci round_jiffies_relative(HZ)); 44268c2ecf20Sopenharmony_ci} 44278c2ecf20Sopenharmony_ci 44288c2ecf20Sopenharmony_ci/** 44298c2ecf20Sopenharmony_ci * ata_scsi_offline_dev - offline attached SCSI device 44308c2ecf20Sopenharmony_ci * @dev: ATA device to offline attached SCSI device for 44318c2ecf20Sopenharmony_ci * 44328c2ecf20Sopenharmony_ci * This function is called from ata_eh_hotplug() and responsible 44338c2ecf20Sopenharmony_ci * for taking the SCSI device attached to @dev offline. This 44348c2ecf20Sopenharmony_ci * function is called with host lock which protects dev->sdev 44358c2ecf20Sopenharmony_ci * against clearing. 44368c2ecf20Sopenharmony_ci * 44378c2ecf20Sopenharmony_ci * LOCKING: 44388c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 44398c2ecf20Sopenharmony_ci * 44408c2ecf20Sopenharmony_ci * RETURNS: 44418c2ecf20Sopenharmony_ci * 1 if attached SCSI device exists, 0 otherwise. 44428c2ecf20Sopenharmony_ci */ 44438c2ecf20Sopenharmony_ciint ata_scsi_offline_dev(struct ata_device *dev) 44448c2ecf20Sopenharmony_ci{ 44458c2ecf20Sopenharmony_ci if (dev->sdev) { 44468c2ecf20Sopenharmony_ci scsi_device_set_state(dev->sdev, SDEV_OFFLINE); 44478c2ecf20Sopenharmony_ci return 1; 44488c2ecf20Sopenharmony_ci } 44498c2ecf20Sopenharmony_ci return 0; 44508c2ecf20Sopenharmony_ci} 44518c2ecf20Sopenharmony_ci 44528c2ecf20Sopenharmony_ci/** 44538c2ecf20Sopenharmony_ci * ata_scsi_remove_dev - remove attached SCSI device 44548c2ecf20Sopenharmony_ci * @dev: ATA device to remove attached SCSI device for 44558c2ecf20Sopenharmony_ci * 44568c2ecf20Sopenharmony_ci * This function is called from ata_eh_scsi_hotplug() and 44578c2ecf20Sopenharmony_ci * responsible for removing the SCSI device attached to @dev. 44588c2ecf20Sopenharmony_ci * 44598c2ecf20Sopenharmony_ci * LOCKING: 44608c2ecf20Sopenharmony_ci * Kernel thread context (may sleep). 44618c2ecf20Sopenharmony_ci */ 44628c2ecf20Sopenharmony_cistatic void ata_scsi_remove_dev(struct ata_device *dev) 44638c2ecf20Sopenharmony_ci{ 44648c2ecf20Sopenharmony_ci struct ata_port *ap = dev->link->ap; 44658c2ecf20Sopenharmony_ci struct scsi_device *sdev; 44668c2ecf20Sopenharmony_ci unsigned long flags; 44678c2ecf20Sopenharmony_ci 44688c2ecf20Sopenharmony_ci /* Alas, we need to grab scan_mutex to ensure SCSI device 44698c2ecf20Sopenharmony_ci * state doesn't change underneath us and thus 44708c2ecf20Sopenharmony_ci * scsi_device_get() always succeeds. The mutex locking can 44718c2ecf20Sopenharmony_ci * be removed if there is __scsi_device_get() interface which 44728c2ecf20Sopenharmony_ci * increments reference counts regardless of device state. 44738c2ecf20Sopenharmony_ci */ 44748c2ecf20Sopenharmony_ci mutex_lock(&ap->scsi_host->scan_mutex); 44758c2ecf20Sopenharmony_ci spin_lock_irqsave(ap->lock, flags); 44768c2ecf20Sopenharmony_ci 44778c2ecf20Sopenharmony_ci /* clearing dev->sdev is protected by host lock */ 44788c2ecf20Sopenharmony_ci sdev = dev->sdev; 44798c2ecf20Sopenharmony_ci dev->sdev = NULL; 44808c2ecf20Sopenharmony_ci 44818c2ecf20Sopenharmony_ci if (sdev) { 44828c2ecf20Sopenharmony_ci /* If user initiated unplug races with us, sdev can go 44838c2ecf20Sopenharmony_ci * away underneath us after the host lock and 44848c2ecf20Sopenharmony_ci * scan_mutex are released. Hold onto it. 44858c2ecf20Sopenharmony_ci */ 44868c2ecf20Sopenharmony_ci if (scsi_device_get(sdev) == 0) { 44878c2ecf20Sopenharmony_ci /* The following ensures the attached sdev is 44888c2ecf20Sopenharmony_ci * offline on return from ata_scsi_offline_dev() 44898c2ecf20Sopenharmony_ci * regardless it wins or loses the race 44908c2ecf20Sopenharmony_ci * against this function. 44918c2ecf20Sopenharmony_ci */ 44928c2ecf20Sopenharmony_ci scsi_device_set_state(sdev, SDEV_OFFLINE); 44938c2ecf20Sopenharmony_ci } else { 44948c2ecf20Sopenharmony_ci WARN_ON(1); 44958c2ecf20Sopenharmony_ci sdev = NULL; 44968c2ecf20Sopenharmony_ci } 44978c2ecf20Sopenharmony_ci } 44988c2ecf20Sopenharmony_ci 44998c2ecf20Sopenharmony_ci spin_unlock_irqrestore(ap->lock, flags); 45008c2ecf20Sopenharmony_ci mutex_unlock(&ap->scsi_host->scan_mutex); 45018c2ecf20Sopenharmony_ci 45028c2ecf20Sopenharmony_ci if (sdev) { 45038c2ecf20Sopenharmony_ci ata_dev_info(dev, "detaching (SCSI %s)\n", 45048c2ecf20Sopenharmony_ci dev_name(&sdev->sdev_gendev)); 45058c2ecf20Sopenharmony_ci 45068c2ecf20Sopenharmony_ci scsi_remove_device(sdev); 45078c2ecf20Sopenharmony_ci scsi_device_put(sdev); 45088c2ecf20Sopenharmony_ci } 45098c2ecf20Sopenharmony_ci} 45108c2ecf20Sopenharmony_ci 45118c2ecf20Sopenharmony_cistatic void ata_scsi_handle_link_detach(struct ata_link *link) 45128c2ecf20Sopenharmony_ci{ 45138c2ecf20Sopenharmony_ci struct ata_port *ap = link->ap; 45148c2ecf20Sopenharmony_ci struct ata_device *dev; 45158c2ecf20Sopenharmony_ci 45168c2ecf20Sopenharmony_ci ata_for_each_dev(dev, link, ALL) { 45178c2ecf20Sopenharmony_ci unsigned long flags; 45188c2ecf20Sopenharmony_ci 45198c2ecf20Sopenharmony_ci if (!(dev->flags & ATA_DFLAG_DETACHED)) 45208c2ecf20Sopenharmony_ci continue; 45218c2ecf20Sopenharmony_ci 45228c2ecf20Sopenharmony_ci spin_lock_irqsave(ap->lock, flags); 45238c2ecf20Sopenharmony_ci dev->flags &= ~ATA_DFLAG_DETACHED; 45248c2ecf20Sopenharmony_ci spin_unlock_irqrestore(ap->lock, flags); 45258c2ecf20Sopenharmony_ci 45268c2ecf20Sopenharmony_ci if (zpodd_dev_enabled(dev)) 45278c2ecf20Sopenharmony_ci zpodd_exit(dev); 45288c2ecf20Sopenharmony_ci 45298c2ecf20Sopenharmony_ci ata_scsi_remove_dev(dev); 45308c2ecf20Sopenharmony_ci } 45318c2ecf20Sopenharmony_ci} 45328c2ecf20Sopenharmony_ci 45338c2ecf20Sopenharmony_ci/** 45348c2ecf20Sopenharmony_ci * ata_scsi_media_change_notify - send media change event 45358c2ecf20Sopenharmony_ci * @dev: Pointer to the disk device with media change event 45368c2ecf20Sopenharmony_ci * 45378c2ecf20Sopenharmony_ci * Tell the block layer to send a media change notification 45388c2ecf20Sopenharmony_ci * event. 45398c2ecf20Sopenharmony_ci * 45408c2ecf20Sopenharmony_ci * LOCKING: 45418c2ecf20Sopenharmony_ci * spin_lock_irqsave(host lock) 45428c2ecf20Sopenharmony_ci */ 45438c2ecf20Sopenharmony_civoid ata_scsi_media_change_notify(struct ata_device *dev) 45448c2ecf20Sopenharmony_ci{ 45458c2ecf20Sopenharmony_ci if (dev->sdev) 45468c2ecf20Sopenharmony_ci sdev_evt_send_simple(dev->sdev, SDEV_EVT_MEDIA_CHANGE, 45478c2ecf20Sopenharmony_ci GFP_ATOMIC); 45488c2ecf20Sopenharmony_ci} 45498c2ecf20Sopenharmony_ci 45508c2ecf20Sopenharmony_ci/** 45518c2ecf20Sopenharmony_ci * ata_scsi_hotplug - SCSI part of hotplug 45528c2ecf20Sopenharmony_ci * @work: Pointer to ATA port to perform SCSI hotplug on 45538c2ecf20Sopenharmony_ci * 45548c2ecf20Sopenharmony_ci * Perform SCSI part of hotplug. It's executed from a separate 45558c2ecf20Sopenharmony_ci * workqueue after EH completes. This is necessary because SCSI 45568c2ecf20Sopenharmony_ci * hot plugging requires working EH and hot unplugging is 45578c2ecf20Sopenharmony_ci * synchronized with hot plugging with a mutex. 45588c2ecf20Sopenharmony_ci * 45598c2ecf20Sopenharmony_ci * LOCKING: 45608c2ecf20Sopenharmony_ci * Kernel thread context (may sleep). 45618c2ecf20Sopenharmony_ci */ 45628c2ecf20Sopenharmony_civoid ata_scsi_hotplug(struct work_struct *work) 45638c2ecf20Sopenharmony_ci{ 45648c2ecf20Sopenharmony_ci struct ata_port *ap = 45658c2ecf20Sopenharmony_ci container_of(work, struct ata_port, hotplug_task.work); 45668c2ecf20Sopenharmony_ci int i; 45678c2ecf20Sopenharmony_ci 45688c2ecf20Sopenharmony_ci if (ap->pflags & ATA_PFLAG_UNLOADING) { 45698c2ecf20Sopenharmony_ci DPRINTK("ENTER/EXIT - unloading\n"); 45708c2ecf20Sopenharmony_ci return; 45718c2ecf20Sopenharmony_ci } 45728c2ecf20Sopenharmony_ci 45738c2ecf20Sopenharmony_ci DPRINTK("ENTER\n"); 45748c2ecf20Sopenharmony_ci mutex_lock(&ap->scsi_scan_mutex); 45758c2ecf20Sopenharmony_ci 45768c2ecf20Sopenharmony_ci /* Unplug detached devices. We cannot use link iterator here 45778c2ecf20Sopenharmony_ci * because PMP links have to be scanned even if PMP is 45788c2ecf20Sopenharmony_ci * currently not attached. Iterate manually. 45798c2ecf20Sopenharmony_ci */ 45808c2ecf20Sopenharmony_ci ata_scsi_handle_link_detach(&ap->link); 45818c2ecf20Sopenharmony_ci if (ap->pmp_link) 45828c2ecf20Sopenharmony_ci for (i = 0; i < SATA_PMP_MAX_PORTS; i++) 45838c2ecf20Sopenharmony_ci ata_scsi_handle_link_detach(&ap->pmp_link[i]); 45848c2ecf20Sopenharmony_ci 45858c2ecf20Sopenharmony_ci /* scan for new ones */ 45868c2ecf20Sopenharmony_ci ata_scsi_scan_host(ap, 0); 45878c2ecf20Sopenharmony_ci 45888c2ecf20Sopenharmony_ci mutex_unlock(&ap->scsi_scan_mutex); 45898c2ecf20Sopenharmony_ci DPRINTK("EXIT\n"); 45908c2ecf20Sopenharmony_ci} 45918c2ecf20Sopenharmony_ci 45928c2ecf20Sopenharmony_ci/** 45938c2ecf20Sopenharmony_ci * ata_scsi_user_scan - indication for user-initiated bus scan 45948c2ecf20Sopenharmony_ci * @shost: SCSI host to scan 45958c2ecf20Sopenharmony_ci * @channel: Channel to scan 45968c2ecf20Sopenharmony_ci * @id: ID to scan 45978c2ecf20Sopenharmony_ci * @lun: LUN to scan 45988c2ecf20Sopenharmony_ci * 45998c2ecf20Sopenharmony_ci * This function is called when user explicitly requests bus 46008c2ecf20Sopenharmony_ci * scan. Set probe pending flag and invoke EH. 46018c2ecf20Sopenharmony_ci * 46028c2ecf20Sopenharmony_ci * LOCKING: 46038c2ecf20Sopenharmony_ci * SCSI layer (we don't care) 46048c2ecf20Sopenharmony_ci * 46058c2ecf20Sopenharmony_ci * RETURNS: 46068c2ecf20Sopenharmony_ci * Zero. 46078c2ecf20Sopenharmony_ci */ 46088c2ecf20Sopenharmony_ciint ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, 46098c2ecf20Sopenharmony_ci unsigned int id, u64 lun) 46108c2ecf20Sopenharmony_ci{ 46118c2ecf20Sopenharmony_ci struct ata_port *ap = ata_shost_to_port(shost); 46128c2ecf20Sopenharmony_ci unsigned long flags; 46138c2ecf20Sopenharmony_ci int devno, rc = 0; 46148c2ecf20Sopenharmony_ci 46158c2ecf20Sopenharmony_ci if (!ap->ops->error_handler) 46168c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 46178c2ecf20Sopenharmony_ci 46188c2ecf20Sopenharmony_ci if (lun != SCAN_WILD_CARD && lun) 46198c2ecf20Sopenharmony_ci return -EINVAL; 46208c2ecf20Sopenharmony_ci 46218c2ecf20Sopenharmony_ci if (!sata_pmp_attached(ap)) { 46228c2ecf20Sopenharmony_ci if (channel != SCAN_WILD_CARD && channel) 46238c2ecf20Sopenharmony_ci return -EINVAL; 46248c2ecf20Sopenharmony_ci devno = id; 46258c2ecf20Sopenharmony_ci } else { 46268c2ecf20Sopenharmony_ci if (id != SCAN_WILD_CARD && id) 46278c2ecf20Sopenharmony_ci return -EINVAL; 46288c2ecf20Sopenharmony_ci devno = channel; 46298c2ecf20Sopenharmony_ci } 46308c2ecf20Sopenharmony_ci 46318c2ecf20Sopenharmony_ci spin_lock_irqsave(ap->lock, flags); 46328c2ecf20Sopenharmony_ci 46338c2ecf20Sopenharmony_ci if (devno == SCAN_WILD_CARD) { 46348c2ecf20Sopenharmony_ci struct ata_link *link; 46358c2ecf20Sopenharmony_ci 46368c2ecf20Sopenharmony_ci ata_for_each_link(link, ap, EDGE) { 46378c2ecf20Sopenharmony_ci struct ata_eh_info *ehi = &link->eh_info; 46388c2ecf20Sopenharmony_ci ehi->probe_mask |= ATA_ALL_DEVICES; 46398c2ecf20Sopenharmony_ci ehi->action |= ATA_EH_RESET; 46408c2ecf20Sopenharmony_ci } 46418c2ecf20Sopenharmony_ci } else { 46428c2ecf20Sopenharmony_ci struct ata_device *dev = ata_find_dev(ap, devno); 46438c2ecf20Sopenharmony_ci 46448c2ecf20Sopenharmony_ci if (dev) { 46458c2ecf20Sopenharmony_ci struct ata_eh_info *ehi = &dev->link->eh_info; 46468c2ecf20Sopenharmony_ci ehi->probe_mask |= 1 << dev->devno; 46478c2ecf20Sopenharmony_ci ehi->action |= ATA_EH_RESET; 46488c2ecf20Sopenharmony_ci } else 46498c2ecf20Sopenharmony_ci rc = -EINVAL; 46508c2ecf20Sopenharmony_ci } 46518c2ecf20Sopenharmony_ci 46528c2ecf20Sopenharmony_ci if (rc == 0) { 46538c2ecf20Sopenharmony_ci ata_port_schedule_eh(ap); 46548c2ecf20Sopenharmony_ci spin_unlock_irqrestore(ap->lock, flags); 46558c2ecf20Sopenharmony_ci ata_port_wait_eh(ap); 46568c2ecf20Sopenharmony_ci } else 46578c2ecf20Sopenharmony_ci spin_unlock_irqrestore(ap->lock, flags); 46588c2ecf20Sopenharmony_ci 46598c2ecf20Sopenharmony_ci return rc; 46608c2ecf20Sopenharmony_ci} 46618c2ecf20Sopenharmony_ci 46628c2ecf20Sopenharmony_ci/** 46638c2ecf20Sopenharmony_ci * ata_scsi_dev_rescan - initiate scsi_rescan_device() 46648c2ecf20Sopenharmony_ci * @work: Pointer to ATA port to perform scsi_rescan_device() 46658c2ecf20Sopenharmony_ci * 46668c2ecf20Sopenharmony_ci * After ATA pass thru (SAT) commands are executed successfully, 46678c2ecf20Sopenharmony_ci * libata need to propagate the changes to SCSI layer. 46688c2ecf20Sopenharmony_ci * 46698c2ecf20Sopenharmony_ci * LOCKING: 46708c2ecf20Sopenharmony_ci * Kernel thread context (may sleep). 46718c2ecf20Sopenharmony_ci */ 46728c2ecf20Sopenharmony_civoid ata_scsi_dev_rescan(struct work_struct *work) 46738c2ecf20Sopenharmony_ci{ 46748c2ecf20Sopenharmony_ci struct ata_port *ap = 46758c2ecf20Sopenharmony_ci container_of(work, struct ata_port, scsi_rescan_task); 46768c2ecf20Sopenharmony_ci struct ata_link *link; 46778c2ecf20Sopenharmony_ci struct ata_device *dev; 46788c2ecf20Sopenharmony_ci unsigned long flags; 46798c2ecf20Sopenharmony_ci 46808c2ecf20Sopenharmony_ci mutex_lock(&ap->scsi_scan_mutex); 46818c2ecf20Sopenharmony_ci spin_lock_irqsave(ap->lock, flags); 46828c2ecf20Sopenharmony_ci 46838c2ecf20Sopenharmony_ci ata_for_each_link(link, ap, EDGE) { 46848c2ecf20Sopenharmony_ci ata_for_each_dev(dev, link, ENABLED) { 46858c2ecf20Sopenharmony_ci struct scsi_device *sdev = dev->sdev; 46868c2ecf20Sopenharmony_ci 46878c2ecf20Sopenharmony_ci if (!sdev) 46888c2ecf20Sopenharmony_ci continue; 46898c2ecf20Sopenharmony_ci if (scsi_device_get(sdev)) 46908c2ecf20Sopenharmony_ci continue; 46918c2ecf20Sopenharmony_ci 46928c2ecf20Sopenharmony_ci spin_unlock_irqrestore(ap->lock, flags); 46938c2ecf20Sopenharmony_ci scsi_rescan_device(&(sdev->sdev_gendev)); 46948c2ecf20Sopenharmony_ci scsi_device_put(sdev); 46958c2ecf20Sopenharmony_ci spin_lock_irqsave(ap->lock, flags); 46968c2ecf20Sopenharmony_ci } 46978c2ecf20Sopenharmony_ci } 46988c2ecf20Sopenharmony_ci 46998c2ecf20Sopenharmony_ci spin_unlock_irqrestore(ap->lock, flags); 47008c2ecf20Sopenharmony_ci mutex_unlock(&ap->scsi_scan_mutex); 47018c2ecf20Sopenharmony_ci} 4702