11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 288455ec4SChristoph Hellwig /* 388455ec4SChristoph Hellwig * SCSI Primary Commands (SPC) parsing and emulation. 488455ec4SChristoph Hellwig * 54c76251eSNicholas Bellinger * (c) Copyright 2002-2013 Datera, Inc. 688455ec4SChristoph Hellwig * 788455ec4SChristoph Hellwig * Nicholas A. Bellinger <nab@kernel.org> 888455ec4SChristoph Hellwig */ 988455ec4SChristoph Hellwig 1088455ec4SChristoph Hellwig #include <linux/kernel.h> 1188455ec4SChristoph Hellwig #include <linux/module.h> 1288455ec4SChristoph Hellwig #include <asm/unaligned.h> 1388455ec4SChristoph Hellwig 14ba929992SBart Van Assche #include <scsi/scsi_proto.h> 15ba929992SBart Van Assche #include <scsi/scsi_common.h> 1688455ec4SChristoph Hellwig #include <scsi/scsi_tcq.h> 1788455ec4SChristoph Hellwig 1888455ec4SChristoph Hellwig #include <target/target_core_base.h> 1988455ec4SChristoph Hellwig #include <target/target_core_backend.h> 2088455ec4SChristoph Hellwig #include <target/target_core_fabric.h> 2188455ec4SChristoph Hellwig 2288455ec4SChristoph Hellwig #include "target_core_internal.h" 23eba2ca45SNicholas Bellinger #include "target_core_alua.h" 2488455ec4SChristoph Hellwig #include "target_core_pr.h" 2588455ec4SChristoph Hellwig #include "target_core_ua.h" 2604b1b795SNicholas Bellinger #include "target_core_xcopy.h" 2788455ec4SChristoph Hellwig 28adf653f9SChristoph Hellwig static void spc_fill_alua_data(struct se_lun *lun, unsigned char *buf) 291fd032eeSChristoph Hellwig { 301fd032eeSChristoph Hellwig struct t10_alua_tg_pt_gp *tg_pt_gp; 311fd032eeSChristoph Hellwig 321fd032eeSChristoph Hellwig /* 331fd032eeSChristoph Hellwig * Set SCCS for MAINTENANCE_IN + REPORT_TARGET_PORT_GROUPS. 341fd032eeSChristoph Hellwig */ 351fd032eeSChristoph Hellwig buf[5] = 0x80; 361fd032eeSChristoph Hellwig 371fd032eeSChristoph Hellwig /* 38125d0119SHannes Reinecke * Set TPGS field for explicit and/or implicit ALUA access type 391fd032eeSChristoph Hellwig * and opteration. 401fd032eeSChristoph Hellwig * 411fd032eeSChristoph Hellwig * See spc4r17 section 6.4.2 Table 135 421fd032eeSChristoph Hellwig */ 43e2a49a95SMike Christie rcu_read_lock(); 44e2a49a95SMike Christie tg_pt_gp = rcu_dereference(lun->lun_tg_pt_gp); 451fd032eeSChristoph Hellwig if (tg_pt_gp) 461fd032eeSChristoph Hellwig buf[5] |= tg_pt_gp->tg_pt_gp_alua_access_type; 47e2a49a95SMike Christie rcu_read_unlock(); 481fd032eeSChristoph Hellwig } 491fd032eeSChristoph Hellwig 50b790a56dSKonstantin Shelekhin static u16 51b790a56dSKonstantin Shelekhin spc_find_scsi_transport_vd(int proto_id) 52b790a56dSKonstantin Shelekhin { 53b790a56dSKonstantin Shelekhin switch (proto_id) { 54b790a56dSKonstantin Shelekhin case SCSI_PROTOCOL_FCP: 55b790a56dSKonstantin Shelekhin return SCSI_VERSION_DESCRIPTOR_FCP4; 56b790a56dSKonstantin Shelekhin case SCSI_PROTOCOL_ISCSI: 57b790a56dSKonstantin Shelekhin return SCSI_VERSION_DESCRIPTOR_ISCSI; 58b790a56dSKonstantin Shelekhin case SCSI_PROTOCOL_SAS: 59b790a56dSKonstantin Shelekhin return SCSI_VERSION_DESCRIPTOR_SAS3; 60b790a56dSKonstantin Shelekhin case SCSI_PROTOCOL_SBP: 61b790a56dSKonstantin Shelekhin return SCSI_VERSION_DESCRIPTOR_SBP3; 62b790a56dSKonstantin Shelekhin case SCSI_PROTOCOL_SRP: 63b790a56dSKonstantin Shelekhin return SCSI_VERSION_DESCRIPTOR_SRP; 64b790a56dSKonstantin Shelekhin default: 65b790a56dSKonstantin Shelekhin pr_warn("Cannot find VERSION DESCRIPTOR value for unknown SCSI" 66b790a56dSKonstantin Shelekhin " transport PROTOCOL IDENTIFIER %#x\n", proto_id); 67b790a56dSKonstantin Shelekhin return 0; 68b790a56dSKonstantin Shelekhin } 69b790a56dSKonstantin Shelekhin } 70b790a56dSKonstantin Shelekhin 710dfa1c5dSHannes Reinecke sense_reason_t 720dfa1c5dSHannes Reinecke spc_emulate_inquiry_std(struct se_cmd *cmd, unsigned char *buf) 731fd032eeSChristoph Hellwig { 741fd032eeSChristoph Hellwig struct se_lun *lun = cmd->se_lun; 75b790a56dSKonstantin Shelekhin struct se_portal_group *tpg = lun->lun_tpg; 761fd032eeSChristoph Hellwig struct se_device *dev = cmd->se_dev; 77d2c5304cSNicholas Bellinger struct se_session *sess = cmd->se_sess; 781fd032eeSChristoph Hellwig 791fd032eeSChristoph Hellwig /* Set RMB (removable media) for tape devices */ 801fd032eeSChristoph Hellwig if (dev->transport->get_device_type(dev) == TYPE_TAPE) 811fd032eeSChristoph Hellwig buf[1] = 0x80; 821fd032eeSChristoph Hellwig 8364ae33efSKonstantin Shelekhin buf[2] = 0x06; /* SPC-4 */ 841fd032eeSChristoph Hellwig 851fd032eeSChristoph Hellwig /* 861fd032eeSChristoph Hellwig * NORMACA and HISUP = 0, RESPONSE DATA FORMAT = 2 871fd032eeSChristoph Hellwig * 881fd032eeSChristoph Hellwig * SPC4 says: 891fd032eeSChristoph Hellwig * A RESPONSE DATA FORMAT field set to 2h indicates that the 901fd032eeSChristoph Hellwig * standard INQUIRY data is in the format defined in this 911fd032eeSChristoph Hellwig * standard. Response data format values less than 2h are 921fd032eeSChristoph Hellwig * obsolete. Response data format values greater than 2h are 931fd032eeSChristoph Hellwig * reserved. 941fd032eeSChristoph Hellwig */ 951fd032eeSChristoph Hellwig buf[3] = 2; 961fd032eeSChristoph Hellwig 971fd032eeSChristoph Hellwig /* 981fd032eeSChristoph Hellwig * Enable SCCS and TPGS fields for Emulated ALUA 991fd032eeSChristoph Hellwig */ 100adf653f9SChristoph Hellwig spc_fill_alua_data(lun, buf); 1011fd032eeSChristoph Hellwig 102d397a445SNicholas Bellinger /* 103d397a445SNicholas Bellinger * Set Third-Party Copy (3PC) bit to indicate support for EXTENDED_COPY 104d397a445SNicholas Bellinger */ 105d397a445SNicholas Bellinger if (dev->dev_attrib.emulate_3pc) 106d397a445SNicholas Bellinger buf[5] |= 0x8; 107bdbad2bdSNicholas Bellinger /* 108d2c5304cSNicholas Bellinger * Set Protection (PROTECT) bit when DIF has been enabled on the 1099ef5466eSNicholas Bellinger * device, and the fabric supports VERIFY + PASS. Also report 1109ef5466eSNicholas Bellinger * PROTECT=1 if sess_prot_type has been configured to allow T10-PI 1119ef5466eSNicholas Bellinger * to unprotected devices. 112bdbad2bdSNicholas Bellinger */ 113d2c5304cSNicholas Bellinger if (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) { 1149ef5466eSNicholas Bellinger if (dev->dev_attrib.pi_prot_type || cmd->se_sess->sess_prot_type) 115bdbad2bdSNicholas Bellinger buf[5] |= 0x1; 116d2c5304cSNicholas Bellinger } 117d397a445SNicholas Bellinger 1185bdd4a8eSDmitry Bogdanov /* 1195bdd4a8eSDmitry Bogdanov * Set MULTIP bit to indicate presence of multiple SCSI target ports 1205bdd4a8eSDmitry Bogdanov */ 1215bdd4a8eSDmitry Bogdanov if (dev->export_count > 1) 1225bdd4a8eSDmitry Bogdanov buf[6] |= 0x10; 1235bdd4a8eSDmitry Bogdanov 1241fd032eeSChristoph Hellwig buf[7] = 0x2; /* CmdQue=1 */ 1251fd032eeSChristoph Hellwig 1260de26357SDavid Disseldorp /* 1270de26357SDavid Disseldorp * ASCII data fields described as being left-aligned shall have any 1280de26357SDavid Disseldorp * unused bytes at the end of the field (i.e., highest offset) and the 1290de26357SDavid Disseldorp * unused bytes shall be filled with ASCII space characters (20h). 1300de26357SDavid Disseldorp */ 131b2da4abfSDavid Disseldorp memset(&buf[8], 0x20, 132b2da4abfSDavid Disseldorp INQUIRY_VENDOR_LEN + INQUIRY_MODEL_LEN + INQUIRY_REVISION_LEN); 1332d882847SDavid Disseldorp memcpy(&buf[8], dev->t10_wwn.vendor, 1342d882847SDavid Disseldorp strnlen(dev->t10_wwn.vendor, INQUIRY_VENDOR_LEN)); 135ee60bddbSNicholas Bellinger memcpy(&buf[16], dev->t10_wwn.model, 136b2da4abfSDavid Disseldorp strnlen(dev->t10_wwn.model, INQUIRY_MODEL_LEN)); 137ee60bddbSNicholas Bellinger memcpy(&buf[32], dev->t10_wwn.revision, 138b2da4abfSDavid Disseldorp strnlen(dev->t10_wwn.revision, INQUIRY_REVISION_LEN)); 139b790a56dSKonstantin Shelekhin 140b790a56dSKonstantin Shelekhin /* 141b790a56dSKonstantin Shelekhin * Set the VERSION DESCRIPTOR fields 142b790a56dSKonstantin Shelekhin */ 143b790a56dSKonstantin Shelekhin put_unaligned_be16(SCSI_VERSION_DESCRIPTOR_SAM5, &buf[58]); 144b790a56dSKonstantin Shelekhin put_unaligned_be16(spc_find_scsi_transport_vd(tpg->proto_id), &buf[60]); 145b790a56dSKonstantin Shelekhin put_unaligned_be16(SCSI_VERSION_DESCRIPTOR_SPC4, &buf[62]); 146b790a56dSKonstantin Shelekhin if (cmd->se_dev->transport->get_device_type(dev) == TYPE_DISK) 147b790a56dSKonstantin Shelekhin put_unaligned_be16(SCSI_VERSION_DESCRIPTOR_SBC3, &buf[64]); 148b790a56dSKonstantin Shelekhin 149b790a56dSKonstantin Shelekhin buf[4] = 91; /* Set additional length to 91 */ 1501fd032eeSChristoph Hellwig 1511fd032eeSChristoph Hellwig return 0; 1521fd032eeSChristoph Hellwig } 1530dfa1c5dSHannes Reinecke EXPORT_SYMBOL(spc_emulate_inquiry_std); 1541fd032eeSChristoph Hellwig 1551fd032eeSChristoph Hellwig /* unit serial number */ 156de103c93SChristoph Hellwig static sense_reason_t 157de103c93SChristoph Hellwig spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) 1581fd032eeSChristoph Hellwig { 1591fd032eeSChristoph Hellwig struct se_device *dev = cmd->se_dev; 1609aff64e1SChristophe Vu-Brugier u16 len; 1611fd032eeSChristoph Hellwig 1620fd97ccfSChristoph Hellwig if (dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) { 1639aff64e1SChristophe Vu-Brugier len = sprintf(&buf[4], "%s", dev->t10_wwn.unit_serial); 1641fd032eeSChristoph Hellwig len++; /* Extra Byte for NULL Terminator */ 1651fd032eeSChristoph Hellwig buf[3] = len; 1661fd032eeSChristoph Hellwig } 1671fd032eeSChristoph Hellwig return 0; 1681fd032eeSChristoph Hellwig } 1691fd032eeSChristoph Hellwig 17017f947b8SSergey Samoylenko /* 17117f947b8SSergey Samoylenko * Generate NAA IEEE Registered Extended designator 17217f947b8SSergey Samoylenko */ 17317f947b8SSergey Samoylenko void spc_gen_naa_6h_vendor_specific(struct se_device *dev, 1741fd032eeSChristoph Hellwig unsigned char *buf) 1751fd032eeSChristoph Hellwig { 1760fd97ccfSChristoph Hellwig unsigned char *p = &dev->t10_wwn.unit_serial[0]; 1772469f1e0SSergey Samoylenko u32 company_id = dev->t10_wwn.company_id; 17817f947b8SSergey Samoylenko int cnt, off = 0; 1791fd032eeSChristoph Hellwig bool next = true; 1801fd032eeSChristoph Hellwig 1811fd032eeSChristoph Hellwig /* 18217f947b8SSergey Samoylenko * Start NAA IEEE Registered Extended Identifier/Designator 18317f947b8SSergey Samoylenko */ 1842469f1e0SSergey Samoylenko buf[off] = 0x6 << 4; 18517f947b8SSergey Samoylenko 1862469f1e0SSergey Samoylenko /* IEEE COMPANY_ID */ 1872469f1e0SSergey Samoylenko buf[off++] |= (company_id >> 20) & 0xf; 1882469f1e0SSergey Samoylenko buf[off++] = (company_id >> 12) & 0xff; 1892469f1e0SSergey Samoylenko buf[off++] = (company_id >> 4) & 0xff; 1902469f1e0SSergey Samoylenko buf[off] = (company_id & 0xf) << 4; 19117f947b8SSergey Samoylenko 19217f947b8SSergey Samoylenko /* 1931fd032eeSChristoph Hellwig * Generate up to 36 bits of VENDOR SPECIFIC IDENTIFIER starting on 1941fd032eeSChristoph Hellwig * byte 3 bit 3-0 for NAA IEEE Registered Extended DESIGNATOR field 1951fd032eeSChristoph Hellwig * format, followed by 64 bits of VENDOR SPECIFIC IDENTIFIER EXTENSION 1961fd032eeSChristoph Hellwig * to complete the payload. These are based from VPD=0x80 PRODUCT SERIAL 1971fd032eeSChristoph Hellwig * NUMBER set via vpd_unit_serial in target_core_configfs.c to ensure 1981fd032eeSChristoph Hellwig * per device uniqeness. 1991fd032eeSChristoph Hellwig */ 20017f947b8SSergey Samoylenko for (cnt = off + 13; *p && off < cnt; p++) { 2011fd032eeSChristoph Hellwig int val = hex_to_bin(*p); 2021fd032eeSChristoph Hellwig 2031fd032eeSChristoph Hellwig if (val < 0) 2041fd032eeSChristoph Hellwig continue; 2051fd032eeSChristoph Hellwig 2061fd032eeSChristoph Hellwig if (next) { 2071fd032eeSChristoph Hellwig next = false; 20817f947b8SSergey Samoylenko buf[off++] |= val; 2091fd032eeSChristoph Hellwig } else { 2101fd032eeSChristoph Hellwig next = true; 21117f947b8SSergey Samoylenko buf[off] = val << 4; 2121fd032eeSChristoph Hellwig } 2131fd032eeSChristoph Hellwig } 2141fd032eeSChristoph Hellwig } 2151fd032eeSChristoph Hellwig 2161fd032eeSChristoph Hellwig /* 2171fd032eeSChristoph Hellwig * Device identification VPD, for a complete list of 2181fd032eeSChristoph Hellwig * DESIGNATOR TYPEs see spc4r17 Table 459. 2191fd032eeSChristoph Hellwig */ 2200dfa1c5dSHannes Reinecke sense_reason_t 221de103c93SChristoph Hellwig spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) 2221fd032eeSChristoph Hellwig { 2231fd032eeSChristoph Hellwig struct se_device *dev = cmd->se_dev; 2241fd032eeSChristoph Hellwig struct se_lun *lun = cmd->se_lun; 2251fd032eeSChristoph Hellwig struct se_portal_group *tpg = NULL; 2261fd032eeSChristoph Hellwig struct t10_alua_lu_gp_member *lu_gp_mem; 2271fd032eeSChristoph Hellwig struct t10_alua_tg_pt_gp *tg_pt_gp; 2280fd97ccfSChristoph Hellwig unsigned char *prod = &dev->t10_wwn.model[0]; 2291fd032eeSChristoph Hellwig u32 prod_len; 2301fd032eeSChristoph Hellwig u32 unit_serial_len, off = 0; 2311fd032eeSChristoph Hellwig u16 len = 0, id_len; 2321fd032eeSChristoph Hellwig 2331fd032eeSChristoph Hellwig off = 4; 2341fd032eeSChristoph Hellwig 2351fd032eeSChristoph Hellwig /* 2361fd032eeSChristoph Hellwig * NAA IEEE Registered Extended Assigned designator format, see 2371fd032eeSChristoph Hellwig * spc4r17 section 7.7.3.6.5 2381fd032eeSChristoph Hellwig * 2391fd032eeSChristoph Hellwig * We depend upon a target_core_mod/ConfigFS provided 2401fd032eeSChristoph Hellwig * /sys/kernel/config/target/core/$HBA/$DEV/wwn/vpd_unit_serial 2411fd032eeSChristoph Hellwig * value in order to return the NAA id. 2421fd032eeSChristoph Hellwig */ 2430fd97ccfSChristoph Hellwig if (!(dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL)) 2441fd032eeSChristoph Hellwig goto check_t10_vend_desc; 2451fd032eeSChristoph Hellwig 2461fd032eeSChristoph Hellwig /* CODE SET == Binary */ 2471fd032eeSChristoph Hellwig buf[off++] = 0x1; 2481fd032eeSChristoph Hellwig 2491fd032eeSChristoph Hellwig /* Set ASSOCIATION == addressed logical unit: 0)b */ 2501fd032eeSChristoph Hellwig buf[off] = 0x00; 2511fd032eeSChristoph Hellwig 2521fd032eeSChristoph Hellwig /* Identifier/Designator type == NAA identifier */ 2531fd032eeSChristoph Hellwig buf[off++] |= 0x3; 2541fd032eeSChristoph Hellwig off++; 2551fd032eeSChristoph Hellwig 2561fd032eeSChristoph Hellwig /* Identifier/Designator length */ 2571fd032eeSChristoph Hellwig buf[off++] = 0x10; 2581fd032eeSChristoph Hellwig 25917f947b8SSergey Samoylenko /* NAA IEEE Registered Extended designator */ 26017f947b8SSergey Samoylenko spc_gen_naa_6h_vendor_specific(dev, &buf[off]); 2611fd032eeSChristoph Hellwig 2621fd032eeSChristoph Hellwig len = 20; 2631fd032eeSChristoph Hellwig off = (len + 4); 2641fd032eeSChristoph Hellwig 2651fd032eeSChristoph Hellwig check_t10_vend_desc: 2661fd032eeSChristoph Hellwig /* 2671fd032eeSChristoph Hellwig * T10 Vendor Identifier Page, see spc4r17 section 7.7.3.4 2681fd032eeSChristoph Hellwig */ 2691fd032eeSChristoph Hellwig id_len = 8; /* For Vendor field */ 2701fd032eeSChristoph Hellwig prod_len = 4; /* For VPD Header */ 2711fd032eeSChristoph Hellwig prod_len += 8; /* For Vendor field */ 2721fd032eeSChristoph Hellwig prod_len += strlen(prod); 2731fd032eeSChristoph Hellwig prod_len++; /* For : */ 2741fd032eeSChristoph Hellwig 2750fd97ccfSChristoph Hellwig if (dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) { 2760fd97ccfSChristoph Hellwig unit_serial_len = strlen(&dev->t10_wwn.unit_serial[0]); 2771fd032eeSChristoph Hellwig unit_serial_len++; /* For NULL Terminator */ 2781fd032eeSChristoph Hellwig 2791fd032eeSChristoph Hellwig id_len += sprintf(&buf[off+12], "%s:%s", prod, 2800fd97ccfSChristoph Hellwig &dev->t10_wwn.unit_serial[0]); 2811fd032eeSChristoph Hellwig } 2821fd032eeSChristoph Hellwig buf[off] = 0x2; /* ASCII */ 2831fd032eeSChristoph Hellwig buf[off+1] = 0x1; /* T10 Vendor ID */ 2841fd032eeSChristoph Hellwig buf[off+2] = 0x0; 2850de26357SDavid Disseldorp /* left align Vendor ID and pad with spaces */ 2862d882847SDavid Disseldorp memset(&buf[off+4], 0x20, INQUIRY_VENDOR_LEN); 2872d882847SDavid Disseldorp memcpy(&buf[off+4], dev->t10_wwn.vendor, 2882d882847SDavid Disseldorp strnlen(dev->t10_wwn.vendor, INQUIRY_VENDOR_LEN)); 2891fd032eeSChristoph Hellwig /* Extra Byte for NULL Terminator */ 2901fd032eeSChristoph Hellwig id_len++; 2911fd032eeSChristoph Hellwig /* Identifier Length */ 2921fd032eeSChristoph Hellwig buf[off+3] = id_len; 2931fd032eeSChristoph Hellwig /* Header size for Designation descriptor */ 2941fd032eeSChristoph Hellwig len += (id_len + 4); 2951fd032eeSChristoph Hellwig off += (id_len + 4); 296adf653f9SChristoph Hellwig 297adf653f9SChristoph Hellwig if (1) { 2981fd032eeSChristoph Hellwig struct t10_alua_lu_gp *lu_gp; 299fbfe858fSHannes Reinecke u32 padding, scsi_name_len, scsi_target_len; 3001fd032eeSChristoph Hellwig u16 lu_gp_id = 0; 3011fd032eeSChristoph Hellwig u16 tg_pt_gp_id = 0; 3021fd032eeSChristoph Hellwig u16 tpgt; 3031fd032eeSChristoph Hellwig 304adf653f9SChristoph Hellwig tpg = lun->lun_tpg; 3051fd032eeSChristoph Hellwig /* 3061fd032eeSChristoph Hellwig * Relative target port identifer, see spc4r17 3071fd032eeSChristoph Hellwig * section 7.7.3.7 3081fd032eeSChristoph Hellwig * 3091fd032eeSChristoph Hellwig * Get the PROTOCOL IDENTIFIER as defined by spc4r17 3101fd032eeSChristoph Hellwig * section 7.5.1 Table 362 3111fd032eeSChristoph Hellwig */ 3122aeeafaeSChristoph Hellwig buf[off] = tpg->proto_id << 4; 3131fd032eeSChristoph Hellwig buf[off++] |= 0x1; /* CODE SET == Binary */ 3141fd032eeSChristoph Hellwig buf[off] = 0x80; /* Set PIV=1 */ 3151fd032eeSChristoph Hellwig /* Set ASSOCIATION == target port: 01b */ 3161fd032eeSChristoph Hellwig buf[off] |= 0x10; 3171fd032eeSChristoph Hellwig /* DESIGNATOR TYPE == Relative target port identifer */ 3181fd032eeSChristoph Hellwig buf[off++] |= 0x4; 3191fd032eeSChristoph Hellwig off++; /* Skip over Reserved */ 3201fd032eeSChristoph Hellwig buf[off++] = 4; /* DESIGNATOR LENGTH */ 3211fd032eeSChristoph Hellwig /* Skip over Obsolete field in RTPI payload 3221fd032eeSChristoph Hellwig * in Table 472 */ 3231fd032eeSChristoph Hellwig off += 2; 324a85d667eSBart Van Assche put_unaligned_be16(lun->lun_rtpi, &buf[off]); 325a85d667eSBart Van Assche off += 2; 3261fd032eeSChristoph Hellwig len += 8; /* Header size + Designation descriptor */ 3271fd032eeSChristoph Hellwig /* 3281fd032eeSChristoph Hellwig * Target port group identifier, see spc4r17 3291fd032eeSChristoph Hellwig * section 7.7.3.8 3301fd032eeSChristoph Hellwig * 3311fd032eeSChristoph Hellwig * Get the PROTOCOL IDENTIFIER as defined by spc4r17 3321fd032eeSChristoph Hellwig * section 7.5.1 Table 362 3331fd032eeSChristoph Hellwig */ 334e2a49a95SMike Christie rcu_read_lock(); 335e2a49a95SMike Christie tg_pt_gp = rcu_dereference(lun->lun_tg_pt_gp); 3361fd032eeSChristoph Hellwig if (!tg_pt_gp) { 337e2a49a95SMike Christie rcu_read_unlock(); 3381fd032eeSChristoph Hellwig goto check_lu_gp; 3391fd032eeSChristoph Hellwig } 3401fd032eeSChristoph Hellwig tg_pt_gp_id = tg_pt_gp->tg_pt_gp_id; 341e2a49a95SMike Christie rcu_read_unlock(); 3421fd032eeSChristoph Hellwig 3432aeeafaeSChristoph Hellwig buf[off] = tpg->proto_id << 4; 3441fd032eeSChristoph Hellwig buf[off++] |= 0x1; /* CODE SET == Binary */ 3451fd032eeSChristoph Hellwig buf[off] = 0x80; /* Set PIV=1 */ 3461fd032eeSChristoph Hellwig /* Set ASSOCIATION == target port: 01b */ 3471fd032eeSChristoph Hellwig buf[off] |= 0x10; 3481fd032eeSChristoph Hellwig /* DESIGNATOR TYPE == Target port group identifier */ 3491fd032eeSChristoph Hellwig buf[off++] |= 0x5; 3501fd032eeSChristoph Hellwig off++; /* Skip over Reserved */ 3511fd032eeSChristoph Hellwig buf[off++] = 4; /* DESIGNATOR LENGTH */ 3521fd032eeSChristoph Hellwig off += 2; /* Skip over Reserved Field */ 353a85d667eSBart Van Assche put_unaligned_be16(tg_pt_gp_id, &buf[off]); 354a85d667eSBart Van Assche off += 2; 3551fd032eeSChristoph Hellwig len += 8; /* Header size + Designation descriptor */ 3561fd032eeSChristoph Hellwig /* 3571fd032eeSChristoph Hellwig * Logical Unit Group identifier, see spc4r17 3581fd032eeSChristoph Hellwig * section 7.7.3.8 3591fd032eeSChristoph Hellwig */ 3601fd032eeSChristoph Hellwig check_lu_gp: 3611fd032eeSChristoph Hellwig lu_gp_mem = dev->dev_alua_lu_gp_mem; 3621fd032eeSChristoph Hellwig if (!lu_gp_mem) 3631fd032eeSChristoph Hellwig goto check_scsi_name; 3641fd032eeSChristoph Hellwig 3651fd032eeSChristoph Hellwig spin_lock(&lu_gp_mem->lu_gp_mem_lock); 3661fd032eeSChristoph Hellwig lu_gp = lu_gp_mem->lu_gp; 3671fd032eeSChristoph Hellwig if (!lu_gp) { 3681fd032eeSChristoph Hellwig spin_unlock(&lu_gp_mem->lu_gp_mem_lock); 3691fd032eeSChristoph Hellwig goto check_scsi_name; 3701fd032eeSChristoph Hellwig } 3711fd032eeSChristoph Hellwig lu_gp_id = lu_gp->lu_gp_id; 3721fd032eeSChristoph Hellwig spin_unlock(&lu_gp_mem->lu_gp_mem_lock); 3731fd032eeSChristoph Hellwig 3741fd032eeSChristoph Hellwig buf[off++] |= 0x1; /* CODE SET == Binary */ 3751fd032eeSChristoph Hellwig /* DESIGNATOR TYPE == Logical Unit Group identifier */ 3761fd032eeSChristoph Hellwig buf[off++] |= 0x6; 3771fd032eeSChristoph Hellwig off++; /* Skip over Reserved */ 3781fd032eeSChristoph Hellwig buf[off++] = 4; /* DESIGNATOR LENGTH */ 3791fd032eeSChristoph Hellwig off += 2; /* Skip over Reserved Field */ 380a85d667eSBart Van Assche put_unaligned_be16(lu_gp_id, &buf[off]); 381a85d667eSBart Van Assche off += 2; 3821fd032eeSChristoph Hellwig len += 8; /* Header size + Designation descriptor */ 3831fd032eeSChristoph Hellwig /* 3841fd032eeSChristoph Hellwig * SCSI name string designator, see spc4r17 3851fd032eeSChristoph Hellwig * section 7.7.3.11 3861fd032eeSChristoph Hellwig * 3871fd032eeSChristoph Hellwig * Get the PROTOCOL IDENTIFIER as defined by spc4r17 3881fd032eeSChristoph Hellwig * section 7.5.1 Table 362 3891fd032eeSChristoph Hellwig */ 3901fd032eeSChristoph Hellwig check_scsi_name: 3912aeeafaeSChristoph Hellwig buf[off] = tpg->proto_id << 4; 3921fd032eeSChristoph Hellwig buf[off++] |= 0x3; /* CODE SET == UTF-8 */ 3931fd032eeSChristoph Hellwig buf[off] = 0x80; /* Set PIV=1 */ 3941fd032eeSChristoph Hellwig /* Set ASSOCIATION == target port: 01b */ 3951fd032eeSChristoph Hellwig buf[off] |= 0x10; 3961fd032eeSChristoph Hellwig /* DESIGNATOR TYPE == SCSI name string */ 3971fd032eeSChristoph Hellwig buf[off++] |= 0x8; 3981fd032eeSChristoph Hellwig off += 2; /* Skip over Reserved and length */ 3991fd032eeSChristoph Hellwig /* 4001fd032eeSChristoph Hellwig * SCSI name string identifer containing, $FABRIC_MOD 4011fd032eeSChristoph Hellwig * dependent information. For LIO-Target and iSCSI 4021fd032eeSChristoph Hellwig * Target Port, this means "<iSCSI name>,t,0x<TPGT> in 4031fd032eeSChristoph Hellwig * UTF-8 encoding. 4041fd032eeSChristoph Hellwig */ 4051fd032eeSChristoph Hellwig tpgt = tpg->se_tpg_tfo->tpg_get_tag(tpg); 4061fd032eeSChristoph Hellwig scsi_name_len = sprintf(&buf[off], "%s,t,0x%04x", 4071fd032eeSChristoph Hellwig tpg->se_tpg_tfo->tpg_get_wwn(tpg), tpgt); 4081fd032eeSChristoph Hellwig scsi_name_len += 1 /* Include NULL terminator */; 4091fd032eeSChristoph Hellwig /* 4101fd032eeSChristoph Hellwig * The null-terminated, null-padded (see 4.4.2) SCSI 4111fd032eeSChristoph Hellwig * NAME STRING field contains a UTF-8 format string. 4121fd032eeSChristoph Hellwig * The number of bytes in the SCSI NAME STRING field 4131fd032eeSChristoph Hellwig * (i.e., the value in the DESIGNATOR LENGTH field) 4141fd032eeSChristoph Hellwig * shall be no larger than 256 and shall be a multiple 4151fd032eeSChristoph Hellwig * of four. 4161fd032eeSChristoph Hellwig */ 41703ba84caSHannes Reinecke padding = ((-scsi_name_len) & 3); 4181fd032eeSChristoph Hellwig if (padding) 4191fd032eeSChristoph Hellwig scsi_name_len += padding; 42003ba84caSHannes Reinecke if (scsi_name_len > 256) 42103ba84caSHannes Reinecke scsi_name_len = 256; 4221fd032eeSChristoph Hellwig 4231fd032eeSChristoph Hellwig buf[off-1] = scsi_name_len; 4241fd032eeSChristoph Hellwig off += scsi_name_len; 4251fd032eeSChristoph Hellwig /* Header size + Designation descriptor */ 4261fd032eeSChristoph Hellwig len += (scsi_name_len + 4); 427fbfe858fSHannes Reinecke 428fbfe858fSHannes Reinecke /* 429fbfe858fSHannes Reinecke * Target device designator 430fbfe858fSHannes Reinecke */ 4312aeeafaeSChristoph Hellwig buf[off] = tpg->proto_id << 4; 432fbfe858fSHannes Reinecke buf[off++] |= 0x3; /* CODE SET == UTF-8 */ 433fbfe858fSHannes Reinecke buf[off] = 0x80; /* Set PIV=1 */ 434fbfe858fSHannes Reinecke /* Set ASSOCIATION == target device: 10b */ 435fbfe858fSHannes Reinecke buf[off] |= 0x20; 436fbfe858fSHannes Reinecke /* DESIGNATOR TYPE == SCSI name string */ 437fbfe858fSHannes Reinecke buf[off++] |= 0x8; 438fbfe858fSHannes Reinecke off += 2; /* Skip over Reserved and length */ 439fbfe858fSHannes Reinecke /* 440fbfe858fSHannes Reinecke * SCSI name string identifer containing, $FABRIC_MOD 441fbfe858fSHannes Reinecke * dependent information. For LIO-Target and iSCSI 442fbfe858fSHannes Reinecke * Target Port, this means "<iSCSI name>" in 443fbfe858fSHannes Reinecke * UTF-8 encoding. 444fbfe858fSHannes Reinecke */ 445fbfe858fSHannes Reinecke scsi_target_len = sprintf(&buf[off], "%s", 446fbfe858fSHannes Reinecke tpg->se_tpg_tfo->tpg_get_wwn(tpg)); 447fbfe858fSHannes Reinecke scsi_target_len += 1 /* Include NULL terminator */; 448fbfe858fSHannes Reinecke /* 449fbfe858fSHannes Reinecke * The null-terminated, null-padded (see 4.4.2) SCSI 450fbfe858fSHannes Reinecke * NAME STRING field contains a UTF-8 format string. 451fbfe858fSHannes Reinecke * The number of bytes in the SCSI NAME STRING field 452fbfe858fSHannes Reinecke * (i.e., the value in the DESIGNATOR LENGTH field) 453fbfe858fSHannes Reinecke * shall be no larger than 256 and shall be a multiple 454fbfe858fSHannes Reinecke * of four. 455fbfe858fSHannes Reinecke */ 456fbfe858fSHannes Reinecke padding = ((-scsi_target_len) & 3); 457fbfe858fSHannes Reinecke if (padding) 458fbfe858fSHannes Reinecke scsi_target_len += padding; 4596a16d7beSRoland Dreier if (scsi_target_len > 256) 4606a16d7beSRoland Dreier scsi_target_len = 256; 461fbfe858fSHannes Reinecke 462fbfe858fSHannes Reinecke buf[off-1] = scsi_target_len; 463fbfe858fSHannes Reinecke off += scsi_target_len; 464fbfe858fSHannes Reinecke 465fbfe858fSHannes Reinecke /* Header size + Designation descriptor */ 466fbfe858fSHannes Reinecke len += (scsi_target_len + 4); 4671fd032eeSChristoph Hellwig } 468a85d667eSBart Van Assche put_unaligned_be16(len, &buf[2]); /* Page Length for VPD 0x83 */ 4691fd032eeSChristoph Hellwig return 0; 4701fd032eeSChristoph Hellwig } 4710dfa1c5dSHannes Reinecke EXPORT_SYMBOL(spc_emulate_evpd_83); 4721fd032eeSChristoph Hellwig 4731fd032eeSChristoph Hellwig /* Extended INQUIRY Data VPD Page */ 474de103c93SChristoph Hellwig static sense_reason_t 475de103c93SChristoph Hellwig spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) 4761fd032eeSChristoph Hellwig { 477d0c8b259SNicholas Bellinger struct se_device *dev = cmd->se_dev; 478d2c5304cSNicholas Bellinger struct se_session *sess = cmd->se_sess; 479d0c8b259SNicholas Bellinger 4801fd032eeSChristoph Hellwig buf[3] = 0x3c; 48143bb95c7SNicholas Bellinger /* 48243bb95c7SNicholas Bellinger * Set GRD_CHK + REF_CHK for TYPE1 protection, or GRD_CHK 48343bb95c7SNicholas Bellinger * only for TYPE3 protection. 48443bb95c7SNicholas Bellinger */ 485d2c5304cSNicholas Bellinger if (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) { 4869ef5466eSNicholas Bellinger if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE1_PROT || 4879ef5466eSNicholas Bellinger cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE1_PROT) 48843bb95c7SNicholas Bellinger buf[4] = 0x5; 4899ef5466eSNicholas Bellinger else if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE3_PROT || 4909ef5466eSNicholas Bellinger cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE3_PROT) 49143bb95c7SNicholas Bellinger buf[4] = 0x4; 492d2c5304cSNicholas Bellinger } 49343bb95c7SNicholas Bellinger 49427e6772bSSagi Grimberg /* logical unit supports type 1 and type 3 protection */ 4953aa3c67bSNicholas Bellinger if ((dev->transport->get_device_type(dev) == TYPE_DISK) && 4963aa3c67bSNicholas Bellinger (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) && 4973aa3c67bSNicholas Bellinger (dev->dev_attrib.pi_prot_type || cmd->se_sess->sess_prot_type)) { 49827e6772bSSagi Grimberg buf[4] |= (0x3 << 3); 4993aa3c67bSNicholas Bellinger } 50027e6772bSSagi Grimberg 5011fd032eeSChristoph Hellwig /* Set HEADSUP, ORDSUP, SIMPSUP */ 5021fd032eeSChristoph Hellwig buf[5] = 0x07; 5031fd032eeSChristoph Hellwig 5041fd032eeSChristoph Hellwig /* If WriteCache emulation is enabled, set V_SUP */ 505814e5b45SChristoph Hellwig if (target_check_wce(dev)) 5061fd032eeSChristoph Hellwig buf[6] = 0x01; 507c66094bfSHannes Reinecke /* If an LBA map is present set R_SUP */ 508c66094bfSHannes Reinecke spin_lock(&cmd->se_dev->t10_alua.lba_map_lock); 509c66094bfSHannes Reinecke if (!list_empty(&dev->t10_alua.lba_map_list)) 510c66094bfSHannes Reinecke buf[8] = 0x10; 511c66094bfSHannes Reinecke spin_unlock(&cmd->se_dev->t10_alua.lba_map_lock); 5121fd032eeSChristoph Hellwig return 0; 5131fd032eeSChristoph Hellwig } 5141fd032eeSChristoph Hellwig 5151fd032eeSChristoph Hellwig /* Block Limits VPD page */ 516de103c93SChristoph Hellwig static sense_reason_t 517de103c93SChristoph Hellwig spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) 5181fd032eeSChristoph Hellwig { 5191fd032eeSChristoph Hellwig struct se_device *dev = cmd->se_dev; 5208f9b5654SNicholas Bellinger u32 mtl = 0; 5218f9b5654SNicholas Bellinger int have_tp = 0, opt, min; 5221fd032eeSChristoph Hellwig 5231fd032eeSChristoph Hellwig /* 5241fd032eeSChristoph Hellwig * Following spc3r22 section 6.5.3 Block Limits VPD page, when 5251fd032eeSChristoph Hellwig * emulate_tpu=1 or emulate_tpws=1 we will be expect a 5261fd032eeSChristoph Hellwig * different page length for Thin Provisioning. 5271fd032eeSChristoph Hellwig */ 5280fd97ccfSChristoph Hellwig if (dev->dev_attrib.emulate_tpu || dev->dev_attrib.emulate_tpws) 5291fd032eeSChristoph Hellwig have_tp = 1; 5301fd032eeSChristoph Hellwig 5311fd032eeSChristoph Hellwig buf[0] = dev->transport->get_device_type(dev); 5321fd032eeSChristoph Hellwig buf[3] = have_tp ? 0x3c : 0x10; 5331fd032eeSChristoph Hellwig 5341fd032eeSChristoph Hellwig /* Set WSNZ to 1 */ 5351fd032eeSChristoph Hellwig buf[4] = 0x01; 5360123a9ecSNicholas Bellinger /* 5370123a9ecSNicholas Bellinger * Set MAXIMUM COMPARE AND WRITE LENGTH 5380123a9ecSNicholas Bellinger */ 5390123a9ecSNicholas Bellinger if (dev->dev_attrib.emulate_caw) 5400123a9ecSNicholas Bellinger buf[5] = 0x01; 5411fd032eeSChristoph Hellwig 5421fd032eeSChristoph Hellwig /* 5431fd032eeSChristoph Hellwig * Set OPTIMAL TRANSFER LENGTH GRANULARITY 5441fd032eeSChristoph Hellwig */ 5457f7caf6aSAndy Grover if (dev->transport->get_io_min && (min = dev->transport->get_io_min(dev))) 5467f7caf6aSAndy Grover put_unaligned_be16(min / dev->dev_attrib.block_size, &buf[6]); 5477f7caf6aSAndy Grover else 5481fd032eeSChristoph Hellwig put_unaligned_be16(1, &buf[6]); 5491fd032eeSChristoph Hellwig 5501fd032eeSChristoph Hellwig /* 5511fd032eeSChristoph Hellwig * Set MAXIMUM TRANSFER LENGTH 5528f9b5654SNicholas Bellinger * 5538f9b5654SNicholas Bellinger * XXX: Currently assumes single PAGE_SIZE per scatterlist for fabrics 5548f9b5654SNicholas Bellinger * enforcing maximum HW scatter-gather-list entry limit 5551fd032eeSChristoph Hellwig */ 5568f9b5654SNicholas Bellinger if (cmd->se_tfo->max_data_sg_nents) { 5578f9b5654SNicholas Bellinger mtl = (cmd->se_tfo->max_data_sg_nents * PAGE_SIZE) / 5588f9b5654SNicholas Bellinger dev->dev_attrib.block_size; 5598f9b5654SNicholas Bellinger } 5608f9b5654SNicholas Bellinger put_unaligned_be32(min_not_zero(mtl, dev->dev_attrib.hw_max_sectors), &buf[8]); 5611fd032eeSChristoph Hellwig 5621fd032eeSChristoph Hellwig /* 5631fd032eeSChristoph Hellwig * Set OPTIMAL TRANSFER LENGTH 5641fd032eeSChristoph Hellwig */ 5657f7caf6aSAndy Grover if (dev->transport->get_io_opt && (opt = dev->transport->get_io_opt(dev))) 5667f7caf6aSAndy Grover put_unaligned_be32(opt / dev->dev_attrib.block_size, &buf[12]); 5677f7caf6aSAndy Grover else 5680fd97ccfSChristoph Hellwig put_unaligned_be32(dev->dev_attrib.optimal_sectors, &buf[12]); 5691fd032eeSChristoph Hellwig 5701fd032eeSChristoph Hellwig /* 5711fd032eeSChristoph Hellwig * Exit now if we don't support TP. 5721fd032eeSChristoph Hellwig */ 5731fd032eeSChristoph Hellwig if (!have_tp) 574773cbaf7SNicholas Bellinger goto max_write_same; 5751fd032eeSChristoph Hellwig 5761fd032eeSChristoph Hellwig /* 5771fd032eeSChristoph Hellwig * Set MAXIMUM UNMAP LBA COUNT 5781fd032eeSChristoph Hellwig */ 5790fd97ccfSChristoph Hellwig put_unaligned_be32(dev->dev_attrib.max_unmap_lba_count, &buf[20]); 5801fd032eeSChristoph Hellwig 5811fd032eeSChristoph Hellwig /* 5821fd032eeSChristoph Hellwig * Set MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT 5831fd032eeSChristoph Hellwig */ 5840fd97ccfSChristoph Hellwig put_unaligned_be32(dev->dev_attrib.max_unmap_block_desc_count, 5851fd032eeSChristoph Hellwig &buf[24]); 5861fd032eeSChristoph Hellwig 5871fd032eeSChristoph Hellwig /* 5881fd032eeSChristoph Hellwig * Set OPTIMAL UNMAP GRANULARITY 5891fd032eeSChristoph Hellwig */ 5900fd97ccfSChristoph Hellwig put_unaligned_be32(dev->dev_attrib.unmap_granularity, &buf[28]); 5911fd032eeSChristoph Hellwig 5921fd032eeSChristoph Hellwig /* 5931fd032eeSChristoph Hellwig * UNMAP GRANULARITY ALIGNMENT 5941fd032eeSChristoph Hellwig */ 5950fd97ccfSChristoph Hellwig put_unaligned_be32(dev->dev_attrib.unmap_granularity_alignment, 5961fd032eeSChristoph Hellwig &buf[32]); 5970fd97ccfSChristoph Hellwig if (dev->dev_attrib.unmap_granularity_alignment != 0) 5981fd032eeSChristoph Hellwig buf[32] |= 0x80; /* Set the UGAVALID bit */ 5991fd032eeSChristoph Hellwig 600773cbaf7SNicholas Bellinger /* 601773cbaf7SNicholas Bellinger * MAXIMUM WRITE SAME LENGTH 602773cbaf7SNicholas Bellinger */ 603773cbaf7SNicholas Bellinger max_write_same: 604773cbaf7SNicholas Bellinger put_unaligned_be64(dev->dev_attrib.max_write_same_len, &buf[36]); 605773cbaf7SNicholas Bellinger 6061fd032eeSChristoph Hellwig return 0; 6071fd032eeSChristoph Hellwig } 6081fd032eeSChristoph Hellwig 6091fd032eeSChristoph Hellwig /* Block Device Characteristics VPD page */ 610de103c93SChristoph Hellwig static sense_reason_t 611de103c93SChristoph Hellwig spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf) 6121fd032eeSChristoph Hellwig { 6131fd032eeSChristoph Hellwig struct se_device *dev = cmd->se_dev; 6141fd032eeSChristoph Hellwig 6151fd032eeSChristoph Hellwig buf[0] = dev->transport->get_device_type(dev); 6161fd032eeSChristoph Hellwig buf[3] = 0x3c; 6170fd97ccfSChristoph Hellwig buf[5] = dev->dev_attrib.is_nonrot ? 1 : 0; 6181fd032eeSChristoph Hellwig 6191fd032eeSChristoph Hellwig return 0; 6201fd032eeSChristoph Hellwig } 6211fd032eeSChristoph Hellwig 6221fd032eeSChristoph Hellwig /* Thin Provisioning VPD */ 623de103c93SChristoph Hellwig static sense_reason_t 624de103c93SChristoph Hellwig spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) 6251fd032eeSChristoph Hellwig { 6261fd032eeSChristoph Hellwig struct se_device *dev = cmd->se_dev; 6271fd032eeSChristoph Hellwig 6281fd032eeSChristoph Hellwig /* 6291fd032eeSChristoph Hellwig * From spc3r22 section 6.5.4 Thin Provisioning VPD page: 6301fd032eeSChristoph Hellwig * 6311fd032eeSChristoph Hellwig * The PAGE LENGTH field is defined in SPC-4. If the DP bit is set to 6321fd032eeSChristoph Hellwig * zero, then the page length shall be set to 0004h. If the DP bit 6331fd032eeSChristoph Hellwig * is set to one, then the page length shall be set to the value 6341fd032eeSChristoph Hellwig * defined in table 162. 6351fd032eeSChristoph Hellwig */ 6361fd032eeSChristoph Hellwig buf[0] = dev->transport->get_device_type(dev); 6371fd032eeSChristoph Hellwig 6381fd032eeSChristoph Hellwig /* 6391fd032eeSChristoph Hellwig * Set Hardcoded length mentioned above for DP=0 6401fd032eeSChristoph Hellwig */ 6411fd032eeSChristoph Hellwig put_unaligned_be16(0x0004, &buf[2]); 6421fd032eeSChristoph Hellwig 6431fd032eeSChristoph Hellwig /* 6441fd032eeSChristoph Hellwig * The THRESHOLD EXPONENT field indicates the threshold set size in 6451fd032eeSChristoph Hellwig * LBAs as a power of 2 (i.e., the threshold set size is equal to 6461fd032eeSChristoph Hellwig * 2(threshold exponent)). 6471fd032eeSChristoph Hellwig * 6481fd032eeSChristoph Hellwig * Note that this is currently set to 0x00 as mkp says it will be 6491fd032eeSChristoph Hellwig * changing again. We can enable this once it has settled in T10 6501fd032eeSChristoph Hellwig * and is actually used by Linux/SCSI ML code. 6511fd032eeSChristoph Hellwig */ 6521fd032eeSChristoph Hellwig buf[4] = 0x00; 6531fd032eeSChristoph Hellwig 6541fd032eeSChristoph Hellwig /* 6551fd032eeSChristoph Hellwig * A TPU bit set to one indicates that the device server supports 6561fd032eeSChristoph Hellwig * the UNMAP command (see 5.25). A TPU bit set to zero indicates 6571fd032eeSChristoph Hellwig * that the device server does not support the UNMAP command. 6581fd032eeSChristoph Hellwig */ 6590fd97ccfSChristoph Hellwig if (dev->dev_attrib.emulate_tpu != 0) 6601fd032eeSChristoph Hellwig buf[5] = 0x80; 6611fd032eeSChristoph Hellwig 6621fd032eeSChristoph Hellwig /* 6631fd032eeSChristoph Hellwig * A TPWS bit set to one indicates that the device server supports 6641fd032eeSChristoph Hellwig * the use of the WRITE SAME (16) command (see 5.42) to unmap LBAs. 6651fd032eeSChristoph Hellwig * A TPWS bit set to zero indicates that the device server does not 6661fd032eeSChristoph Hellwig * support the use of the WRITE SAME (16) command to unmap LBAs. 6671fd032eeSChristoph Hellwig */ 6680fd97ccfSChristoph Hellwig if (dev->dev_attrib.emulate_tpws != 0) 669aa04dae4SNicholas Bellinger buf[5] |= 0x40 | 0x20; 6701fd032eeSChristoph Hellwig 671e6f41633SJamie Pocas /* 672e6f41633SJamie Pocas * The unmap_zeroes_data set means that the underlying device supports 6739305455aSBart Van Assche * REQ_OP_DISCARD and has the discard_zeroes_data bit set. This 6749305455aSBart Van Assche * satisfies the SBC requirements for LBPRZ, meaning that a subsequent 6759305455aSBart Van Assche * read will return zeroes after an UNMAP or WRITE SAME (16) to an LBA 676e6f41633SJamie Pocas * See sbc4r36 6.6.4. 677e6f41633SJamie Pocas */ 678e6f41633SJamie Pocas if (((dev->dev_attrib.emulate_tpu != 0) || 679e6f41633SJamie Pocas (dev->dev_attrib.emulate_tpws != 0)) && 680e6f41633SJamie Pocas (dev->dev_attrib.unmap_zeroes_data != 0)) 681e6f41633SJamie Pocas buf[5] |= 0x04; 682e6f41633SJamie Pocas 6831fd032eeSChristoph Hellwig return 0; 6841fd032eeSChristoph Hellwig } 6851fd032eeSChristoph Hellwig 686c66094bfSHannes Reinecke /* Referrals VPD page */ 687c66094bfSHannes Reinecke static sense_reason_t 688c66094bfSHannes Reinecke spc_emulate_evpd_b3(struct se_cmd *cmd, unsigned char *buf) 689c66094bfSHannes Reinecke { 690c66094bfSHannes Reinecke struct se_device *dev = cmd->se_dev; 691c66094bfSHannes Reinecke 692c66094bfSHannes Reinecke buf[0] = dev->transport->get_device_type(dev); 693c66094bfSHannes Reinecke buf[3] = 0x0c; 694c66094bfSHannes Reinecke put_unaligned_be32(dev->t10_alua.lba_map_segment_size, &buf[8]); 695096b4995SSebastian Herbszt put_unaligned_be32(dev->t10_alua.lba_map_segment_multiplier, &buf[12]); 696c66094bfSHannes Reinecke 697c66094bfSHannes Reinecke return 0; 698c66094bfSHannes Reinecke } 699c66094bfSHannes Reinecke 700de103c93SChristoph Hellwig static sense_reason_t 701de103c93SChristoph Hellwig spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf); 7021fd032eeSChristoph Hellwig 7031fd032eeSChristoph Hellwig static struct { 7041fd032eeSChristoph Hellwig uint8_t page; 705de103c93SChristoph Hellwig sense_reason_t (*emulate)(struct se_cmd *, unsigned char *); 7061fd032eeSChristoph Hellwig } evpd_handlers[] = { 7071fd032eeSChristoph Hellwig { .page = 0x00, .emulate = spc_emulate_evpd_00 }, 7081fd032eeSChristoph Hellwig { .page = 0x80, .emulate = spc_emulate_evpd_80 }, 7091fd032eeSChristoph Hellwig { .page = 0x83, .emulate = spc_emulate_evpd_83 }, 7101fd032eeSChristoph Hellwig { .page = 0x86, .emulate = spc_emulate_evpd_86 }, 7111fd032eeSChristoph Hellwig { .page = 0xb0, .emulate = spc_emulate_evpd_b0 }, 7121fd032eeSChristoph Hellwig { .page = 0xb1, .emulate = spc_emulate_evpd_b1 }, 7131fd032eeSChristoph Hellwig { .page = 0xb2, .emulate = spc_emulate_evpd_b2 }, 714c66094bfSHannes Reinecke { .page = 0xb3, .emulate = spc_emulate_evpd_b3 }, 7151fd032eeSChristoph Hellwig }; 7161fd032eeSChristoph Hellwig 7171fd032eeSChristoph Hellwig /* supported vital product data pages */ 718de103c93SChristoph Hellwig static sense_reason_t 719de103c93SChristoph Hellwig spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) 7201fd032eeSChristoph Hellwig { 7211fd032eeSChristoph Hellwig int p; 7221fd032eeSChristoph Hellwig 7231fd032eeSChristoph Hellwig /* 7241fd032eeSChristoph Hellwig * Only report the INQUIRY EVPD=1 pages after a valid NAA 7251fd032eeSChristoph Hellwig * Registered Extended LUN WWN has been set via ConfigFS 7261fd032eeSChristoph Hellwig * during device creation/restart. 7271fd032eeSChristoph Hellwig */ 7280fd97ccfSChristoph Hellwig if (cmd->se_dev->dev_flags & DF_EMULATED_VPD_UNIT_SERIAL) { 7291fd032eeSChristoph Hellwig buf[3] = ARRAY_SIZE(evpd_handlers); 7301fd032eeSChristoph Hellwig for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p) 7311fd032eeSChristoph Hellwig buf[p + 4] = evpd_handlers[p].page; 7321fd032eeSChristoph Hellwig } 7331fd032eeSChristoph Hellwig 7341fd032eeSChristoph Hellwig return 0; 7351fd032eeSChristoph Hellwig } 7361fd032eeSChristoph Hellwig 737de103c93SChristoph Hellwig static sense_reason_t 738de103c93SChristoph Hellwig spc_emulate_inquiry(struct se_cmd *cmd) 7391fd032eeSChristoph Hellwig { 7401fd032eeSChristoph Hellwig struct se_device *dev = cmd->se_dev; 741ffe7b0e9SPaolo Bonzini unsigned char *rbuf; 7421fd032eeSChristoph Hellwig unsigned char *cdb = cmd->t_task_cdb; 743f82f320eSNicholas Bellinger unsigned char *buf; 744de103c93SChristoph Hellwig sense_reason_t ret; 745de103c93SChristoph Hellwig int p; 7462426bd45SRoland Dreier int len = 0; 7471fd032eeSChristoph Hellwig 748f82f320eSNicholas Bellinger buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL); 749f82f320eSNicholas Bellinger if (!buf) { 750f82f320eSNicholas Bellinger pr_err("Unable to allocate response buffer for INQUIRY\n"); 751f82f320eSNicholas Bellinger return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 752f82f320eSNicholas Bellinger } 753dea5f099SNicholas Bellinger 7541fd032eeSChristoph Hellwig buf[0] = dev->transport->get_device_type(dev); 7551fd032eeSChristoph Hellwig 7561fd032eeSChristoph Hellwig if (!(cdb[1] & 0x1)) { 7571fd032eeSChristoph Hellwig if (cdb[2]) { 7581fd032eeSChristoph Hellwig pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n", 7591fd032eeSChristoph Hellwig cdb[2]); 760de103c93SChristoph Hellwig ret = TCM_INVALID_CDB_FIELD; 7611fd032eeSChristoph Hellwig goto out; 7621fd032eeSChristoph Hellwig } 7631fd032eeSChristoph Hellwig 7641fd032eeSChristoph Hellwig ret = spc_emulate_inquiry_std(cmd, buf); 7652426bd45SRoland Dreier len = buf[4] + 5; 7661fd032eeSChristoph Hellwig goto out; 7671fd032eeSChristoph Hellwig } 7681fd032eeSChristoph Hellwig 7691fd032eeSChristoph Hellwig for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p) { 7701fd032eeSChristoph Hellwig if (cdb[2] == evpd_handlers[p].page) { 7711fd032eeSChristoph Hellwig buf[1] = cdb[2]; 7721fd032eeSChristoph Hellwig ret = evpd_handlers[p].emulate(cmd, buf); 7732426bd45SRoland Dreier len = get_unaligned_be16(&buf[2]) + 4; 7741fd032eeSChristoph Hellwig goto out; 7751fd032eeSChristoph Hellwig } 7761fd032eeSChristoph Hellwig } 7771fd032eeSChristoph Hellwig 77895af09faSKonstantin Shelekhin pr_debug("Unknown VPD Code: 0x%02x\n", cdb[2]); 779de103c93SChristoph Hellwig ret = TCM_INVALID_CDB_FIELD; 7801fd032eeSChristoph Hellwig 7811fd032eeSChristoph Hellwig out: 782ffe7b0e9SPaolo Bonzini rbuf = transport_kmap_data_sg(cmd); 78349df9fc9SNicholas Bellinger if (rbuf) { 784f82f320eSNicholas Bellinger memcpy(rbuf, buf, min_t(u32, SE_INQUIRY_BUF, cmd->data_length)); 7851fd032eeSChristoph Hellwig transport_kunmap_data_sg(cmd); 78649df9fc9SNicholas Bellinger } 787f82f320eSNicholas Bellinger kfree(buf); 7881fd032eeSChristoph Hellwig 7891fd032eeSChristoph Hellwig if (!ret) 79014b40c1eSHannes Reinecke target_complete_cmd_with_length(cmd, SAM_STAT_GOOD, len); 7911fd032eeSChristoph Hellwig return ret; 7921fd032eeSChristoph Hellwig } 7931fd032eeSChristoph Hellwig 794d45aca42SNicholas Bellinger static int spc_modesense_rwrecovery(struct se_cmd *cmd, u8 pc, u8 *p) 7951fd032eeSChristoph Hellwig { 7961fd032eeSChristoph Hellwig p[0] = 0x01; 7971fd032eeSChristoph Hellwig p[1] = 0x0a; 7981fd032eeSChristoph Hellwig 799d4b2b867SRoland Dreier /* No changeable values for now */ 800d4b2b867SRoland Dreier if (pc == 1) 801d4b2b867SRoland Dreier goto out; 802d4b2b867SRoland Dreier 803d4b2b867SRoland Dreier out: 8041fd032eeSChristoph Hellwig return 12; 8051fd032eeSChristoph Hellwig } 8061fd032eeSChristoph Hellwig 807d45aca42SNicholas Bellinger static int spc_modesense_control(struct se_cmd *cmd, u8 pc, u8 *p) 8081fd032eeSChristoph Hellwig { 809d45aca42SNicholas Bellinger struct se_device *dev = cmd->se_dev; 810d45aca42SNicholas Bellinger struct se_session *sess = cmd->se_sess; 811d45aca42SNicholas Bellinger 8121fd032eeSChristoph Hellwig p[0] = 0x0a; 8131fd032eeSChristoph Hellwig p[1] = 0x0a; 814d4b2b867SRoland Dreier 815d4b2b867SRoland Dreier /* No changeable values for now */ 816d4b2b867SRoland Dreier if (pc == 1) 817d4b2b867SRoland Dreier goto out; 818d4b2b867SRoland Dreier 8194e4937e8SSagi Grimberg /* GLTSD: No implicit save of log parameters */ 8204e4937e8SSagi Grimberg p[2] = (1 << 1); 8214e4937e8SSagi Grimberg if (target_sense_desc_format(dev)) 8224e4937e8SSagi Grimberg /* D_SENSE: Descriptor format sense data for 64bit sectors */ 8234e4937e8SSagi Grimberg p[2] |= (1 << 2); 8244e4937e8SSagi Grimberg 8251fd032eeSChristoph Hellwig /* 8261fd032eeSChristoph Hellwig * From spc4r23, 7.4.7 Control mode page 8271fd032eeSChristoph Hellwig * 8281fd032eeSChristoph Hellwig * The QUEUE ALGORITHM MODIFIER field (see table 368) specifies 8291fd032eeSChristoph Hellwig * restrictions on the algorithm used for reordering commands 8301fd032eeSChristoph Hellwig * having the SIMPLE task attribute (see SAM-4). 8311fd032eeSChristoph Hellwig * 8321fd032eeSChristoph Hellwig * Table 368 -- QUEUE ALGORITHM MODIFIER field 8331fd032eeSChristoph Hellwig * Code Description 8341fd032eeSChristoph Hellwig * 0h Restricted reordering 8351fd032eeSChristoph Hellwig * 1h Unrestricted reordering allowed 8361fd032eeSChristoph Hellwig * 2h to 7h Reserved 8371fd032eeSChristoph Hellwig * 8h to Fh Vendor specific 8381fd032eeSChristoph Hellwig * 8391fd032eeSChristoph Hellwig * A value of zero in the QUEUE ALGORITHM MODIFIER field specifies that 8401fd032eeSChristoph Hellwig * the device server shall order the processing sequence of commands 8411fd032eeSChristoph Hellwig * having the SIMPLE task attribute such that data integrity is maintained 8421fd032eeSChristoph Hellwig * for that I_T nexus (i.e., if the transmission of new SCSI transport protocol 8431fd032eeSChristoph Hellwig * requests is halted at any time, the final value of all data observable 8441fd032eeSChristoph Hellwig * on the medium shall be the same as if all the commands had been processed 8451fd032eeSChristoph Hellwig * with the ORDERED task attribute). 8461fd032eeSChristoph Hellwig * 8471fd032eeSChristoph Hellwig * A value of one in the QUEUE ALGORITHM MODIFIER field specifies that the 8481fd032eeSChristoph Hellwig * device server may reorder the processing sequence of commands having the 8491fd032eeSChristoph Hellwig * SIMPLE task attribute in any manner. Any data integrity exposures related to 8501fd032eeSChristoph Hellwig * command sequence order shall be explicitly handled by the application client 8511fd032eeSChristoph Hellwig * through the selection of appropriate ommands and task attributes. 8521fd032eeSChristoph Hellwig */ 8530fd97ccfSChristoph Hellwig p[3] = (dev->dev_attrib.emulate_rest_reord == 1) ? 0x00 : 0x10; 8541fd032eeSChristoph Hellwig /* 8551fd032eeSChristoph Hellwig * From spc4r17, section 7.4.6 Control mode Page 8561fd032eeSChristoph Hellwig * 8571fd032eeSChristoph Hellwig * Unit Attention interlocks control (UN_INTLCK_CTRL) to code 00b 8581fd032eeSChristoph Hellwig * 8591fd032eeSChristoph Hellwig * 00b: The logical unit shall clear any unit attention condition 8601fd032eeSChristoph Hellwig * reported in the same I_T_L_Q nexus transaction as a CHECK CONDITION 8611fd032eeSChristoph Hellwig * status and shall not establish a unit attention condition when a com- 8621fd032eeSChristoph Hellwig * mand is completed with BUSY, TASK SET FULL, or RESERVATION CONFLICT 8631fd032eeSChristoph Hellwig * status. 8641fd032eeSChristoph Hellwig * 8651fd032eeSChristoph Hellwig * 10b: The logical unit shall not clear any unit attention condition 8661fd032eeSChristoph Hellwig * reported in the same I_T_L_Q nexus transaction as a CHECK CONDITION 8671fd032eeSChristoph Hellwig * status and shall not establish a unit attention condition when 8681fd032eeSChristoph Hellwig * a command is completed with BUSY, TASK SET FULL, or RESERVATION 8691fd032eeSChristoph Hellwig * CONFLICT status. 8701fd032eeSChristoph Hellwig * 8711fd032eeSChristoph Hellwig * 11b a The logical unit shall not clear any unit attention condition 8721fd032eeSChristoph Hellwig * reported in the same I_T_L_Q nexus transaction as a CHECK CONDITION 8731fd032eeSChristoph Hellwig * status and shall establish a unit attention condition for the 8741fd032eeSChristoph Hellwig * initiator port associated with the I_T nexus on which the BUSY, 8751fd032eeSChristoph Hellwig * TASK SET FULL, or RESERVATION CONFLICT status is being returned. 8761fd032eeSChristoph Hellwig * Depending on the status, the additional sense code shall be set to 8771fd032eeSChristoph Hellwig * PREVIOUS BUSY STATUS, PREVIOUS TASK SET FULL STATUS, or PREVIOUS 8781fd032eeSChristoph Hellwig * RESERVATION CONFLICT STATUS. Until it is cleared by a REQUEST SENSE 8791fd032eeSChristoph Hellwig * command, a unit attention condition shall be established only once 8801fd032eeSChristoph Hellwig * for a BUSY, TASK SET FULL, or RESERVATION CONFLICT status regardless 8811fd032eeSChristoph Hellwig * to the number of commands completed with one of those status codes. 8821fd032eeSChristoph Hellwig */ 8831bf630fdSDavid Disseldorp switch (dev->dev_attrib.emulate_ua_intlck_ctrl) { 8841bf630fdSDavid Disseldorp case TARGET_UA_INTLCK_CTRL_ESTABLISH_UA: 8851bf630fdSDavid Disseldorp p[4] = 0x30; 8861bf630fdSDavid Disseldorp break; 8871bf630fdSDavid Disseldorp case TARGET_UA_INTLCK_CTRL_NO_CLEAR: 8881bf630fdSDavid Disseldorp p[4] = 0x20; 8891bf630fdSDavid Disseldorp break; 8901bf630fdSDavid Disseldorp default: /* TARGET_UA_INTLCK_CTRL_CLEAR */ 8911bf630fdSDavid Disseldorp p[4] = 0x00; 8921bf630fdSDavid Disseldorp break; 8931bf630fdSDavid Disseldorp } 8941fd032eeSChristoph Hellwig /* 8951fd032eeSChristoph Hellwig * From spc4r17, section 7.4.6 Control mode Page 8961fd032eeSChristoph Hellwig * 8971fd032eeSChristoph Hellwig * Task Aborted Status (TAS) bit set to zero. 8981fd032eeSChristoph Hellwig * 8991fd032eeSChristoph Hellwig * A task aborted status (TAS) bit set to zero specifies that aborted 9001fd032eeSChristoph Hellwig * tasks shall be terminated by the device server without any response 9011fd032eeSChristoph Hellwig * to the application client. A TAS bit set to one specifies that tasks 9021fd032eeSChristoph Hellwig * aborted by the actions of an I_T nexus other than the I_T nexus on 9031fd032eeSChristoph Hellwig * which the command was received shall be completed with TASK ABORTED 9041fd032eeSChristoph Hellwig * status (see SAM-4). 9051fd032eeSChristoph Hellwig */ 9060fd97ccfSChristoph Hellwig p[5] = (dev->dev_attrib.emulate_tas) ? 0x40 : 0x00; 9070c30f421SNicholas Bellinger /* 9080c30f421SNicholas Bellinger * From spc4r30, section 7.5.7 Control mode page 9090c30f421SNicholas Bellinger * 9100c30f421SNicholas Bellinger * Application Tag Owner (ATO) bit set to one. 9110c30f421SNicholas Bellinger * 9120c30f421SNicholas Bellinger * If the ATO bit is set to one the device server shall not modify the 9130c30f421SNicholas Bellinger * LOGICAL BLOCK APPLICATION TAG field and, depending on the protection 9140c30f421SNicholas Bellinger * type, shall not modify the contents of the LOGICAL BLOCK REFERENCE 9150c30f421SNicholas Bellinger * TAG field. 9160c30f421SNicholas Bellinger */ 917d45aca42SNicholas Bellinger if (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) { 9189ef5466eSNicholas Bellinger if (dev->dev_attrib.pi_prot_type || sess->sess_prot_type) 9190c30f421SNicholas Bellinger p[5] |= 0x80; 920d45aca42SNicholas Bellinger } 9210c30f421SNicholas Bellinger 9221fd032eeSChristoph Hellwig p[8] = 0xff; 9231fd032eeSChristoph Hellwig p[9] = 0xff; 9241fd032eeSChristoph Hellwig p[11] = 30; 9251fd032eeSChristoph Hellwig 926d4b2b867SRoland Dreier out: 9271fd032eeSChristoph Hellwig return 12; 9281fd032eeSChristoph Hellwig } 9291fd032eeSChristoph Hellwig 930d45aca42SNicholas Bellinger static int spc_modesense_caching(struct se_cmd *cmd, u8 pc, u8 *p) 9311fd032eeSChristoph Hellwig { 932d45aca42SNicholas Bellinger struct se_device *dev = cmd->se_dev; 933d45aca42SNicholas Bellinger 9341fd032eeSChristoph Hellwig p[0] = 0x08; 9351fd032eeSChristoph Hellwig p[1] = 0x12; 936d4b2b867SRoland Dreier 937d4b2b867SRoland Dreier /* No changeable values for now */ 938d4b2b867SRoland Dreier if (pc == 1) 939d4b2b867SRoland Dreier goto out; 940d4b2b867SRoland Dreier 941814e5b45SChristoph Hellwig if (target_check_wce(dev)) 9421fd032eeSChristoph Hellwig p[2] = 0x04; /* Write Cache Enable */ 9431fd032eeSChristoph Hellwig p[12] = 0x20; /* Disabled Read Ahead */ 9441fd032eeSChristoph Hellwig 945d4b2b867SRoland Dreier out: 9461fd032eeSChristoph Hellwig return 20; 9471fd032eeSChristoph Hellwig } 9481fd032eeSChristoph Hellwig 949d45aca42SNicholas Bellinger static int spc_modesense_informational_exceptions(struct se_cmd *cmd, u8 pc, unsigned char *p) 9500f6d64ceSRoland Dreier { 9510f6d64ceSRoland Dreier p[0] = 0x1c; 9520f6d64ceSRoland Dreier p[1] = 0x0a; 9530f6d64ceSRoland Dreier 9540f6d64ceSRoland Dreier /* No changeable values for now */ 9550f6d64ceSRoland Dreier if (pc == 1) 9560f6d64ceSRoland Dreier goto out; 9570f6d64ceSRoland Dreier 9580f6d64ceSRoland Dreier out: 9590f6d64ceSRoland Dreier return 12; 9600f6d64ceSRoland Dreier } 9610f6d64ceSRoland Dreier 962d4b2b867SRoland Dreier static struct { 963d4b2b867SRoland Dreier uint8_t page; 964d4b2b867SRoland Dreier uint8_t subpage; 965d45aca42SNicholas Bellinger int (*emulate)(struct se_cmd *, u8, unsigned char *); 966d4b2b867SRoland Dreier } modesense_handlers[] = { 967d4b2b867SRoland Dreier { .page = 0x01, .subpage = 0x00, .emulate = spc_modesense_rwrecovery }, 968d4b2b867SRoland Dreier { .page = 0x08, .subpage = 0x00, .emulate = spc_modesense_caching }, 969d4b2b867SRoland Dreier { .page = 0x0a, .subpage = 0x00, .emulate = spc_modesense_control }, 9700f6d64ceSRoland Dreier { .page = 0x1c, .subpage = 0x00, .emulate = spc_modesense_informational_exceptions }, 971d4b2b867SRoland Dreier }; 972d4b2b867SRoland Dreier 9731fd032eeSChristoph Hellwig static void spc_modesense_write_protect(unsigned char *buf, int type) 9741fd032eeSChristoph Hellwig { 9751fd032eeSChristoph Hellwig /* 9761fd032eeSChristoph Hellwig * I believe that the WP bit (bit 7) in the mode header is the same for 9771fd032eeSChristoph Hellwig * all device types.. 9781fd032eeSChristoph Hellwig */ 9791fd032eeSChristoph Hellwig switch (type) { 9801fd032eeSChristoph Hellwig case TYPE_DISK: 9811fd032eeSChristoph Hellwig case TYPE_TAPE: 9821fd032eeSChristoph Hellwig default: 9831fd032eeSChristoph Hellwig buf[0] |= 0x80; /* WP bit */ 9841fd032eeSChristoph Hellwig break; 9851fd032eeSChristoph Hellwig } 9861fd032eeSChristoph Hellwig } 9871fd032eeSChristoph Hellwig 9881fd032eeSChristoph Hellwig static void spc_modesense_dpofua(unsigned char *buf, int type) 9891fd032eeSChristoph Hellwig { 9901fd032eeSChristoph Hellwig switch (type) { 9911fd032eeSChristoph Hellwig case TYPE_DISK: 9921fd032eeSChristoph Hellwig buf[0] |= 0x10; /* DPOFUA bit */ 9931fd032eeSChristoph Hellwig break; 9941fd032eeSChristoph Hellwig default: 9951fd032eeSChristoph Hellwig break; 9961fd032eeSChristoph Hellwig } 9971fd032eeSChristoph Hellwig } 9981fd032eeSChristoph Hellwig 999d4b2b867SRoland Dreier static int spc_modesense_blockdesc(unsigned char *buf, u64 blocks, u32 block_size) 1000d4b2b867SRoland Dreier { 1001d4b2b867SRoland Dreier *buf++ = 8; 1002d4b2b867SRoland Dreier put_unaligned_be32(min(blocks, 0xffffffffull), buf); 1003d4b2b867SRoland Dreier buf += 4; 1004d4b2b867SRoland Dreier put_unaligned_be32(block_size, buf); 1005d4b2b867SRoland Dreier return 9; 1006d4b2b867SRoland Dreier } 1007d4b2b867SRoland Dreier 1008d4b2b867SRoland Dreier static int spc_modesense_long_blockdesc(unsigned char *buf, u64 blocks, u32 block_size) 1009d4b2b867SRoland Dreier { 1010d4b2b867SRoland Dreier if (blocks <= 0xffffffff) 1011d4b2b867SRoland Dreier return spc_modesense_blockdesc(buf + 3, blocks, block_size) + 3; 1012d4b2b867SRoland Dreier 1013d4b2b867SRoland Dreier *buf++ = 1; /* LONGLBA */ 1014d4b2b867SRoland Dreier buf += 2; 1015d4b2b867SRoland Dreier *buf++ = 16; 1016d4b2b867SRoland Dreier put_unaligned_be64(blocks, buf); 1017d4b2b867SRoland Dreier buf += 12; 1018d4b2b867SRoland Dreier put_unaligned_be32(block_size, buf); 1019d4b2b867SRoland Dreier 1020d4b2b867SRoland Dreier return 17; 1021d4b2b867SRoland Dreier } 1022d4b2b867SRoland Dreier 1023de103c93SChristoph Hellwig static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) 10241fd032eeSChristoph Hellwig { 10251fd032eeSChristoph Hellwig struct se_device *dev = cmd->se_dev; 10261fd032eeSChristoph Hellwig char *cdb = cmd->t_task_cdb; 1027cab9609bSNicholas Bellinger unsigned char buf[SE_MODE_PAGE_BUF], *rbuf; 10281fd032eeSChristoph Hellwig int type = dev->transport->get_device_type(dev); 10291fd032eeSChristoph Hellwig int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10); 1030d4b2b867SRoland Dreier bool dbd = !!(cdb[1] & 0x08); 1031d4b2b867SRoland Dreier bool llba = ten ? !!(cdb[1] & 0x10) : false; 1032d4b2b867SRoland Dreier u8 pc = cdb[2] >> 6; 1033d4b2b867SRoland Dreier u8 page = cdb[2] & 0x3f; 1034d4b2b867SRoland Dreier u8 subpage = cdb[3]; 10351fd032eeSChristoph Hellwig int length = 0; 1036d4b2b867SRoland Dreier int ret; 1037d4b2b867SRoland Dreier int i; 10381fd032eeSChristoph Hellwig 1039cab9609bSNicholas Bellinger memset(buf, 0, SE_MODE_PAGE_BUF); 1040cab9609bSNicholas Bellinger 1041fecae40aSNicholas Bellinger /* 1042fecae40aSNicholas Bellinger * Skip over MODE DATA LENGTH + MEDIUM TYPE fields to byte 3 for 1043fecae40aSNicholas Bellinger * MODE_SENSE_10 and byte 2 for MODE_SENSE (6). 1044fecae40aSNicholas Bellinger */ 1045fecae40aSNicholas Bellinger length = ten ? 3 : 2; 1046d4b2b867SRoland Dreier 1047d4b2b867SRoland Dreier /* DEVICE-SPECIFIC PARAMETER */ 104803a68b44SAndy Grover if (cmd->se_lun->lun_access_ro || target_lun_is_rdonly(cmd)) 1049d4b2b867SRoland Dreier spc_modesense_write_protect(&buf[length], type); 1050d4b2b867SRoland Dreier 1051814e5b45SChristoph Hellwig /* 1052814e5b45SChristoph Hellwig * SBC only allows us to enable FUA and DPO together. Fortunately 1053814e5b45SChristoph Hellwig * DPO is explicitly specified as a hint, so a noop is a perfectly 1054814e5b45SChristoph Hellwig * valid implementation. 1055814e5b45SChristoph Hellwig */ 1056814e5b45SChristoph Hellwig if (target_check_fua(dev)) 1057d4b2b867SRoland Dreier spc_modesense_dpofua(&buf[length], type); 1058d4b2b867SRoland Dreier 1059d4b2b867SRoland Dreier ++length; 1060d4b2b867SRoland Dreier 1061d4b2b867SRoland Dreier /* BLOCK DESCRIPTOR */ 1062d4b2b867SRoland Dreier 1063d4b2b867SRoland Dreier /* 1064d4b2b867SRoland Dreier * For now we only include a block descriptor for disk (SBC) 1065d4b2b867SRoland Dreier * devices; other command sets use a slightly different format. 1066d4b2b867SRoland Dreier */ 1067d4b2b867SRoland Dreier if (!dbd && type == TYPE_DISK) { 1068d4b2b867SRoland Dreier u64 blocks = dev->transport->get_blocks(dev); 1069d4b2b867SRoland Dreier u32 block_size = dev->dev_attrib.block_size; 10701fd032eeSChristoph Hellwig 10711fd032eeSChristoph Hellwig if (ten) { 1072d4b2b867SRoland Dreier if (llba) { 1073d4b2b867SRoland Dreier length += spc_modesense_long_blockdesc(&buf[length], 1074d4b2b867SRoland Dreier blocks, block_size); 10751fd032eeSChristoph Hellwig } else { 1076d4b2b867SRoland Dreier length += 3; 1077d4b2b867SRoland Dreier length += spc_modesense_blockdesc(&buf[length], 1078d4b2b867SRoland Dreier blocks, block_size); 1079d4b2b867SRoland Dreier } 1080d4b2b867SRoland Dreier } else { 1081d4b2b867SRoland Dreier length += spc_modesense_blockdesc(&buf[length], blocks, 1082d4b2b867SRoland Dreier block_size); 1083d4b2b867SRoland Dreier } 1084d4b2b867SRoland Dreier } else { 1085d4b2b867SRoland Dreier if (ten) 1086d4b2b867SRoland Dreier length += 4; 1087d4b2b867SRoland Dreier else 1088d4b2b867SRoland Dreier length += 1; 10891fd032eeSChristoph Hellwig } 10901fd032eeSChristoph Hellwig 1091d4b2b867SRoland Dreier if (page == 0x3f) { 1092d4b2b867SRoland Dreier if (subpage != 0x00 && subpage != 0xff) { 1093de103c93SChristoph Hellwig pr_warn("MODE_SENSE: Invalid subpage code: 0x%02x\n", subpage); 1094de103c93SChristoph Hellwig return TCM_INVALID_CDB_FIELD; 1095d4b2b867SRoland Dreier } 1096d4b2b867SRoland Dreier 1097d4b2b867SRoland Dreier for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i) { 1098d4b2b867SRoland Dreier /* 1099d4b2b867SRoland Dreier * Tricky way to say all subpage 00h for 1100d4b2b867SRoland Dreier * subpage==0, all subpages for subpage==0xff 1101d4b2b867SRoland Dreier * (and we just checked above that those are 1102d4b2b867SRoland Dreier * the only two possibilities). 1103d4b2b867SRoland Dreier */ 1104d4b2b867SRoland Dreier if ((modesense_handlers[i].subpage & ~subpage) == 0) { 1105d45aca42SNicholas Bellinger ret = modesense_handlers[i].emulate(cmd, pc, &buf[length]); 1106d4b2b867SRoland Dreier if (!ten && length + ret >= 255) 1107d4b2b867SRoland Dreier break; 1108d4b2b867SRoland Dreier length += ret; 1109d4b2b867SRoland Dreier } 1110d4b2b867SRoland Dreier } 1111d4b2b867SRoland Dreier 1112d4b2b867SRoland Dreier goto set_length; 1113d4b2b867SRoland Dreier } 1114d4b2b867SRoland Dreier 1115d4b2b867SRoland Dreier for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i) 1116d4b2b867SRoland Dreier if (modesense_handlers[i].page == page && 1117d4b2b867SRoland Dreier modesense_handlers[i].subpage == subpage) { 1118d45aca42SNicholas Bellinger length += modesense_handlers[i].emulate(cmd, pc, &buf[length]); 1119d4b2b867SRoland Dreier goto set_length; 1120d4b2b867SRoland Dreier } 1121d4b2b867SRoland Dreier 1122d4b2b867SRoland Dreier /* 1123d4b2b867SRoland Dreier * We don't intend to implement: 1124d4b2b867SRoland Dreier * - obsolete page 03h "format parameters" (checked by Solaris) 1125d4b2b867SRoland Dreier */ 1126d4b2b867SRoland Dreier if (page != 0x03) 1127d4b2b867SRoland Dreier pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n", 1128d4b2b867SRoland Dreier page, subpage); 1129d4b2b867SRoland Dreier 1130de103c93SChristoph Hellwig return TCM_UNKNOWN_MODE_PAGE; 1131d4b2b867SRoland Dreier 1132d4b2b867SRoland Dreier set_length: 1133d4b2b867SRoland Dreier if (ten) 1134d4b2b867SRoland Dreier put_unaligned_be16(length - 2, buf); 1135d4b2b867SRoland Dreier else 1136d4b2b867SRoland Dreier buf[0] = length - 1; 1137d4b2b867SRoland Dreier 1138cab9609bSNicholas Bellinger rbuf = transport_kmap_data_sg(cmd); 1139cab9609bSNicholas Bellinger if (rbuf) { 1140cab9609bSNicholas Bellinger memcpy(rbuf, buf, min_t(u32, SE_MODE_PAGE_BUF, cmd->data_length)); 1141cab9609bSNicholas Bellinger transport_kunmap_data_sg(cmd); 1142d4b2b867SRoland Dreier } 1143d4b2b867SRoland Dreier 114414b40c1eSHannes Reinecke target_complete_cmd_with_length(cmd, SAM_STAT_GOOD, length); 11451fd032eeSChristoph Hellwig return 0; 11461fd032eeSChristoph Hellwig } 11471fd032eeSChristoph Hellwig 1148de103c93SChristoph Hellwig static sense_reason_t spc_emulate_modeselect(struct se_cmd *cmd) 11493a3c5e4aSRoland Dreier { 11503a3c5e4aSRoland Dreier char *cdb = cmd->t_task_cdb; 11513a3c5e4aSRoland Dreier bool ten = cdb[0] == MODE_SELECT_10; 11523a3c5e4aSRoland Dreier int off = ten ? 8 : 4; 11533a3c5e4aSRoland Dreier bool pf = !!(cdb[1] & 0x10); 11543a3c5e4aSRoland Dreier u8 page, subpage; 11553a3c5e4aSRoland Dreier unsigned char *buf; 11563a3c5e4aSRoland Dreier unsigned char tbuf[SE_MODE_PAGE_BUF]; 11573a3c5e4aSRoland Dreier int length; 11583abff1e5SChristoph Hellwig sense_reason_t ret = 0; 11593a3c5e4aSRoland Dreier int i; 11603a3c5e4aSRoland Dreier 116171f41fe1SRoland Dreier if (!cmd->data_length) { 116214b40c1eSHannes Reinecke target_complete_cmd(cmd, SAM_STAT_GOOD); 116371f41fe1SRoland Dreier return 0; 116471f41fe1SRoland Dreier } 116571f41fe1SRoland Dreier 116671f41fe1SRoland Dreier if (cmd->data_length < off + 2) 116771f41fe1SRoland Dreier return TCM_PARAMETER_LIST_LENGTH_ERROR; 116871f41fe1SRoland Dreier 11693a3c5e4aSRoland Dreier buf = transport_kmap_data_sg(cmd); 1170de103c93SChristoph Hellwig if (!buf) 1171de103c93SChristoph Hellwig return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 11723a3c5e4aSRoland Dreier 11733a3c5e4aSRoland Dreier if (!pf) { 1174de103c93SChristoph Hellwig ret = TCM_INVALID_CDB_FIELD; 11753a3c5e4aSRoland Dreier goto out; 11763a3c5e4aSRoland Dreier } 11773a3c5e4aSRoland Dreier 11783a3c5e4aSRoland Dreier page = buf[off] & 0x3f; 11793a3c5e4aSRoland Dreier subpage = buf[off] & 0x40 ? buf[off + 1] : 0; 11803a3c5e4aSRoland Dreier 11813a3c5e4aSRoland Dreier for (i = 0; i < ARRAY_SIZE(modesense_handlers); ++i) 11823a3c5e4aSRoland Dreier if (modesense_handlers[i].page == page && 11833a3c5e4aSRoland Dreier modesense_handlers[i].subpage == subpage) { 11843a3c5e4aSRoland Dreier memset(tbuf, 0, SE_MODE_PAGE_BUF); 1185d45aca42SNicholas Bellinger length = modesense_handlers[i].emulate(cmd, 0, tbuf); 11863a3c5e4aSRoland Dreier goto check_contents; 11873a3c5e4aSRoland Dreier } 11883a3c5e4aSRoland Dreier 1189de103c93SChristoph Hellwig ret = TCM_UNKNOWN_MODE_PAGE; 11903a3c5e4aSRoland Dreier goto out; 11913a3c5e4aSRoland Dreier 11923a3c5e4aSRoland Dreier check_contents: 119371f41fe1SRoland Dreier if (cmd->data_length < off + length) { 119471f41fe1SRoland Dreier ret = TCM_PARAMETER_LIST_LENGTH_ERROR; 119571f41fe1SRoland Dreier goto out; 119671f41fe1SRoland Dreier } 119771f41fe1SRoland Dreier 1198de103c93SChristoph Hellwig if (memcmp(buf + off, tbuf, length)) 1199de103c93SChristoph Hellwig ret = TCM_INVALID_PARAMETER_LIST; 12003a3c5e4aSRoland Dreier 12013a3c5e4aSRoland Dreier out: 12023a3c5e4aSRoland Dreier transport_kunmap_data_sg(cmd); 12033a3c5e4aSRoland Dreier 12043a3c5e4aSRoland Dreier if (!ret) 120514b40c1eSHannes Reinecke target_complete_cmd(cmd, SAM_STAT_GOOD); 12063a3c5e4aSRoland Dreier return ret; 12073a3c5e4aSRoland Dreier } 12083a3c5e4aSRoland Dreier 1209de103c93SChristoph Hellwig static sense_reason_t spc_emulate_request_sense(struct se_cmd *cmd) 12101fd032eeSChristoph Hellwig { 12111fd032eeSChristoph Hellwig unsigned char *cdb = cmd->t_task_cdb; 121232a8811fSPaolo Bonzini unsigned char *rbuf; 12131fd032eeSChristoph Hellwig u8 ua_asc = 0, ua_ascq = 0; 121432a8811fSPaolo Bonzini unsigned char buf[SE_SENSE_BUF]; 12154e4937e8SSagi Grimberg bool desc_format = target_sense_desc_format(cmd->se_dev); 121632a8811fSPaolo Bonzini 121732a8811fSPaolo Bonzini memset(buf, 0, SE_SENSE_BUF); 12181fd032eeSChristoph Hellwig 12191fd032eeSChristoph Hellwig if (cdb[1] & 0x01) { 12201fd032eeSChristoph Hellwig pr_err("REQUEST_SENSE description emulation not" 12211fd032eeSChristoph Hellwig " supported\n"); 1222de103c93SChristoph Hellwig return TCM_INVALID_CDB_FIELD; 12231fd032eeSChristoph Hellwig } 12241fd032eeSChristoph Hellwig 122532a8811fSPaolo Bonzini rbuf = transport_kmap_data_sg(cmd); 1226de103c93SChristoph Hellwig if (!rbuf) 1227de103c93SChristoph Hellwig return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 1228de103c93SChristoph Hellwig 12299ec1e1ceSSagi Grimberg if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) 12304e4937e8SSagi Grimberg scsi_build_sense_buffer(desc_format, buf, UNIT_ATTENTION, 12319ec1e1ceSSagi Grimberg ua_asc, ua_ascq); 12329ec1e1ceSSagi Grimberg else 12334e4937e8SSagi Grimberg scsi_build_sense_buffer(desc_format, buf, NO_SENSE, 0x0, 0x0); 12341fd032eeSChristoph Hellwig 123532a8811fSPaolo Bonzini memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); 12361fd032eeSChristoph Hellwig transport_kunmap_data_sg(cmd); 123732a8811fSPaolo Bonzini 123814b40c1eSHannes Reinecke target_complete_cmd(cmd, SAM_STAT_GOOD); 12391fd032eeSChristoph Hellwig return 0; 12401fd032eeSChristoph Hellwig } 12411fd032eeSChristoph Hellwig 1242de103c93SChristoph Hellwig sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd) 1243d1b1f805SChristoph Hellwig { 1244d1b1f805SChristoph Hellwig struct se_dev_entry *deve; 1245d1b1f805SChristoph Hellwig struct se_session *sess = cmd->se_sess; 124629a05deeSNicholas Bellinger struct se_node_acl *nacl; 12470f69a387SRoland Dreier struct scsi_lun slun; 1248d1b1f805SChristoph Hellwig unsigned char *buf; 124929a05deeSNicholas Bellinger u32 lun_count = 0, offset = 8; 12500f69a387SRoland Dreier __be32 len; 1251d1b1f805SChristoph Hellwig 1252d1b1f805SChristoph Hellwig buf = transport_kmap_data_sg(cmd); 12530f69a387SRoland Dreier if (cmd->data_length && !buf) 1254de103c93SChristoph Hellwig return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 1255d1b1f805SChristoph Hellwig 1256d1b1f805SChristoph Hellwig /* 1257d1b1f805SChristoph Hellwig * If no struct se_session pointer is present, this struct se_cmd is 1258d1b1f805SChristoph Hellwig * coming via a target_core_mod PASSTHROUGH op, and not through 1259d1b1f805SChristoph Hellwig * a $FABRIC_MOD. In that case, report LUN=0 only. 1260d1b1f805SChristoph Hellwig */ 12619c395170SRoland Dreier if (!sess) 1262d1b1f805SChristoph Hellwig goto done; 12639c395170SRoland Dreier 126429a05deeSNicholas Bellinger nacl = sess->se_node_acl; 1265d1b1f805SChristoph Hellwig 126629a05deeSNicholas Bellinger rcu_read_lock(); 126729a05deeSNicholas Bellinger hlist_for_each_entry_rcu(deve, &nacl->lun_entry_hlist, link) { 1268d1b1f805SChristoph Hellwig /* 1269d1b1f805SChristoph Hellwig * We determine the correct LUN LIST LENGTH even once we 1270d1b1f805SChristoph Hellwig * have reached the initial allocation length. 1271d1b1f805SChristoph Hellwig * See SPC2-R20 7.19. 1272d1b1f805SChristoph Hellwig */ 1273d1b1f805SChristoph Hellwig lun_count++; 12740f69a387SRoland Dreier if (offset >= cmd->data_length) 1275d1b1f805SChristoph Hellwig continue; 1276d1b1f805SChristoph Hellwig 12770f69a387SRoland Dreier int_to_scsilun(deve->mapped_lun, &slun); 12780f69a387SRoland Dreier memcpy(buf + offset, &slun, 12790f69a387SRoland Dreier min(8u, cmd->data_length - offset)); 1280d1b1f805SChristoph Hellwig offset += 8; 1281d1b1f805SChristoph Hellwig } 128229a05deeSNicholas Bellinger rcu_read_unlock(); 1283d1b1f805SChristoph Hellwig 1284d1b1f805SChristoph Hellwig /* 1285d1b1f805SChristoph Hellwig * See SPC3 r07, page 159. 1286d1b1f805SChristoph Hellwig */ 1287d1b1f805SChristoph Hellwig done: 12889c395170SRoland Dreier /* 12899c395170SRoland Dreier * If no LUNs are accessible, report virtual LUN 0. 12909c395170SRoland Dreier */ 12919c395170SRoland Dreier if (lun_count == 0) { 12920f69a387SRoland Dreier int_to_scsilun(0, &slun); 12930f69a387SRoland Dreier if (cmd->data_length > 8) 12940f69a387SRoland Dreier memcpy(buf + offset, &slun, 12950f69a387SRoland Dreier min(8u, cmd->data_length - offset)); 12969c395170SRoland Dreier lun_count = 1; 12979c395170SRoland Dreier } 12989c395170SRoland Dreier 12990f69a387SRoland Dreier if (buf) { 13000f69a387SRoland Dreier len = cpu_to_be32(lun_count * 8); 13010f69a387SRoland Dreier memcpy(buf, &len, min_t(int, sizeof len, cmd->data_length)); 1302d1b1f805SChristoph Hellwig transport_kunmap_data_sg(cmd); 13030f69a387SRoland Dreier } 1304d1b1f805SChristoph Hellwig 130514b40c1eSHannes Reinecke target_complete_cmd_with_length(cmd, SAM_STAT_GOOD, 8 + lun_count * 8); 1306d1b1f805SChristoph Hellwig return 0; 1307d1b1f805SChristoph Hellwig } 13088de530a5SChristoph Hellwig EXPORT_SYMBOL(spc_emulate_report_luns); 1309d1b1f805SChristoph Hellwig 1310de103c93SChristoph Hellwig static sense_reason_t 1311de103c93SChristoph Hellwig spc_emulate_testunitready(struct se_cmd *cmd) 13121fd032eeSChristoph Hellwig { 131314b40c1eSHannes Reinecke target_complete_cmd(cmd, SAM_STAT_GOOD); 13141fd032eeSChristoph Hellwig return 0; 13151fd032eeSChristoph Hellwig } 13161fd032eeSChristoph Hellwig 1317*b9b8782fSDmitry Bogdanov 1318*b9b8782fSDmitry Bogdanov static struct target_opcode_descriptor *tcm_supported_opcodes[] = { 1319*b9b8782fSDmitry Bogdanov }; 1320*b9b8782fSDmitry Bogdanov 1321*b9b8782fSDmitry Bogdanov static int 1322*b9b8782fSDmitry Bogdanov spc_rsoc_encode_command_timeouts_descriptor(unsigned char *buf, u8 ctdp, 1323*b9b8782fSDmitry Bogdanov struct target_opcode_descriptor *descr) 1324*b9b8782fSDmitry Bogdanov { 1325*b9b8782fSDmitry Bogdanov if (!ctdp) 1326*b9b8782fSDmitry Bogdanov return 0; 1327*b9b8782fSDmitry Bogdanov 1328*b9b8782fSDmitry Bogdanov put_unaligned_be16(0xa, buf); 1329*b9b8782fSDmitry Bogdanov buf[3] = descr->specific_timeout; 1330*b9b8782fSDmitry Bogdanov put_unaligned_be32(descr->nominal_timeout, &buf[4]); 1331*b9b8782fSDmitry Bogdanov put_unaligned_be32(descr->recommended_timeout, &buf[8]); 1332*b9b8782fSDmitry Bogdanov 1333*b9b8782fSDmitry Bogdanov return 12; 1334*b9b8782fSDmitry Bogdanov } 1335*b9b8782fSDmitry Bogdanov 1336*b9b8782fSDmitry Bogdanov static int 1337*b9b8782fSDmitry Bogdanov spc_rsoc_encode_command_descriptor(unsigned char *buf, u8 ctdp, 1338*b9b8782fSDmitry Bogdanov struct target_opcode_descriptor *descr) 1339*b9b8782fSDmitry Bogdanov { 1340*b9b8782fSDmitry Bogdanov int td_size = 0; 1341*b9b8782fSDmitry Bogdanov 1342*b9b8782fSDmitry Bogdanov buf[0] = descr->opcode; 1343*b9b8782fSDmitry Bogdanov 1344*b9b8782fSDmitry Bogdanov put_unaligned_be16(descr->service_action, &buf[2]); 1345*b9b8782fSDmitry Bogdanov 1346*b9b8782fSDmitry Bogdanov buf[5] = (ctdp << 1) | descr->serv_action_valid; 1347*b9b8782fSDmitry Bogdanov put_unaligned_be16(descr->cdb_size, &buf[6]); 1348*b9b8782fSDmitry Bogdanov 1349*b9b8782fSDmitry Bogdanov td_size = spc_rsoc_encode_command_timeouts_descriptor(&buf[8], ctdp, 1350*b9b8782fSDmitry Bogdanov descr); 1351*b9b8782fSDmitry Bogdanov 1352*b9b8782fSDmitry Bogdanov return 8 + td_size; 1353*b9b8782fSDmitry Bogdanov } 1354*b9b8782fSDmitry Bogdanov 1355*b9b8782fSDmitry Bogdanov static int 1356*b9b8782fSDmitry Bogdanov spc_rsoc_encode_one_command_descriptor(unsigned char *buf, u8 ctdp, 1357*b9b8782fSDmitry Bogdanov struct target_opcode_descriptor *descr) 1358*b9b8782fSDmitry Bogdanov { 1359*b9b8782fSDmitry Bogdanov int td_size = 0; 1360*b9b8782fSDmitry Bogdanov 1361*b9b8782fSDmitry Bogdanov if (!descr) { 1362*b9b8782fSDmitry Bogdanov buf[1] = (ctdp << 7) | SCSI_SUPPORT_NOT_SUPPORTED; 1363*b9b8782fSDmitry Bogdanov return 2; 1364*b9b8782fSDmitry Bogdanov } 1365*b9b8782fSDmitry Bogdanov 1366*b9b8782fSDmitry Bogdanov buf[1] = (ctdp << 7) | SCSI_SUPPORT_FULL; 1367*b9b8782fSDmitry Bogdanov put_unaligned_be16(descr->cdb_size, &buf[2]); 1368*b9b8782fSDmitry Bogdanov memcpy(&buf[4], descr->usage_bits, descr->cdb_size); 1369*b9b8782fSDmitry Bogdanov 1370*b9b8782fSDmitry Bogdanov td_size = spc_rsoc_encode_command_timeouts_descriptor( 1371*b9b8782fSDmitry Bogdanov &buf[4 + descr->cdb_size], ctdp, descr); 1372*b9b8782fSDmitry Bogdanov 1373*b9b8782fSDmitry Bogdanov return 4 + descr->cdb_size + td_size; 1374*b9b8782fSDmitry Bogdanov } 1375*b9b8782fSDmitry Bogdanov 1376*b9b8782fSDmitry Bogdanov static sense_reason_t 1377*b9b8782fSDmitry Bogdanov spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) 1378*b9b8782fSDmitry Bogdanov { 1379*b9b8782fSDmitry Bogdanov struct target_opcode_descriptor *descr; 1380*b9b8782fSDmitry Bogdanov struct se_session *sess = cmd->se_sess; 1381*b9b8782fSDmitry Bogdanov unsigned char *cdb = cmd->t_task_cdb; 1382*b9b8782fSDmitry Bogdanov u8 opts = cdb[2] & 0x3; 1383*b9b8782fSDmitry Bogdanov u8 requested_opcode; 1384*b9b8782fSDmitry Bogdanov u16 requested_sa; 1385*b9b8782fSDmitry Bogdanov int i; 1386*b9b8782fSDmitry Bogdanov 1387*b9b8782fSDmitry Bogdanov requested_opcode = cdb[3]; 1388*b9b8782fSDmitry Bogdanov requested_sa = ((u16)cdb[4]) << 8 | cdb[5]; 1389*b9b8782fSDmitry Bogdanov *opcode = NULL; 1390*b9b8782fSDmitry Bogdanov 1391*b9b8782fSDmitry Bogdanov if (opts > 3) { 1392*b9b8782fSDmitry Bogdanov pr_debug("TARGET_CORE[%s]: Invalid REPORT SUPPORTED OPERATION CODES" 1393*b9b8782fSDmitry Bogdanov " with unsupported REPORTING OPTIONS %#x for 0x%08llx from %s\n", 1394*b9b8782fSDmitry Bogdanov cmd->se_tfo->fabric_name, opts, 1395*b9b8782fSDmitry Bogdanov cmd->se_lun->unpacked_lun, 1396*b9b8782fSDmitry Bogdanov sess->se_node_acl->initiatorname); 1397*b9b8782fSDmitry Bogdanov return TCM_INVALID_CDB_FIELD; 1398*b9b8782fSDmitry Bogdanov } 1399*b9b8782fSDmitry Bogdanov 1400*b9b8782fSDmitry Bogdanov for (i = 0; i < ARRAY_SIZE(tcm_supported_opcodes); i++) { 1401*b9b8782fSDmitry Bogdanov descr = tcm_supported_opcodes[i]; 1402*b9b8782fSDmitry Bogdanov if (descr->opcode != requested_opcode) 1403*b9b8782fSDmitry Bogdanov continue; 1404*b9b8782fSDmitry Bogdanov 1405*b9b8782fSDmitry Bogdanov switch (opts) { 1406*b9b8782fSDmitry Bogdanov case 0x1: 1407*b9b8782fSDmitry Bogdanov /* 1408*b9b8782fSDmitry Bogdanov * If the REQUESTED OPERATION CODE field specifies an 1409*b9b8782fSDmitry Bogdanov * operation code for which the device server implements 1410*b9b8782fSDmitry Bogdanov * service actions, then the device server shall 1411*b9b8782fSDmitry Bogdanov * terminate the command with CHECK CONDITION status, 1412*b9b8782fSDmitry Bogdanov * with the sense key set to ILLEGAL REQUEST, and the 1413*b9b8782fSDmitry Bogdanov * additional sense code set to INVALID FIELD IN CDB 1414*b9b8782fSDmitry Bogdanov */ 1415*b9b8782fSDmitry Bogdanov if (descr->serv_action_valid) 1416*b9b8782fSDmitry Bogdanov return TCM_INVALID_CDB_FIELD; 1417*b9b8782fSDmitry Bogdanov *opcode = descr; 1418*b9b8782fSDmitry Bogdanov break; 1419*b9b8782fSDmitry Bogdanov case 0x2: 1420*b9b8782fSDmitry Bogdanov /* 1421*b9b8782fSDmitry Bogdanov * If the REQUESTED OPERATION CODE field specifies an 1422*b9b8782fSDmitry Bogdanov * operation code for which the device server does not 1423*b9b8782fSDmitry Bogdanov * implement service actions, then the device server 1424*b9b8782fSDmitry Bogdanov * shall terminate the command with CHECK CONDITION 1425*b9b8782fSDmitry Bogdanov * status, with the sense key set to ILLEGAL REQUEST, 1426*b9b8782fSDmitry Bogdanov * and the additional sense code set to INVALID FIELD IN CDB. 1427*b9b8782fSDmitry Bogdanov */ 1428*b9b8782fSDmitry Bogdanov if (descr->serv_action_valid && 1429*b9b8782fSDmitry Bogdanov descr->service_action == requested_sa) 1430*b9b8782fSDmitry Bogdanov *opcode = descr; 1431*b9b8782fSDmitry Bogdanov else if (!descr->serv_action_valid) 1432*b9b8782fSDmitry Bogdanov return TCM_INVALID_CDB_FIELD; 1433*b9b8782fSDmitry Bogdanov break; 1434*b9b8782fSDmitry Bogdanov case 0x3: 1435*b9b8782fSDmitry Bogdanov /* 1436*b9b8782fSDmitry Bogdanov * The command support data for the operation code and 1437*b9b8782fSDmitry Bogdanov * service action a specified in the REQUESTED OPERATION 1438*b9b8782fSDmitry Bogdanov * CODE field and REQUESTED SERVICE ACTION field shall 1439*b9b8782fSDmitry Bogdanov * be returned in the one_command parameter data format. 1440*b9b8782fSDmitry Bogdanov */ 1441*b9b8782fSDmitry Bogdanov if (descr->service_action == requested_sa) 1442*b9b8782fSDmitry Bogdanov *opcode = descr; 1443*b9b8782fSDmitry Bogdanov break; 1444*b9b8782fSDmitry Bogdanov } 1445*b9b8782fSDmitry Bogdanov } 1446*b9b8782fSDmitry Bogdanov return 0; 1447*b9b8782fSDmitry Bogdanov } 1448*b9b8782fSDmitry Bogdanov 1449*b9b8782fSDmitry Bogdanov static sense_reason_t 1450*b9b8782fSDmitry Bogdanov spc_emulate_report_supp_op_codes(struct se_cmd *cmd) 1451*b9b8782fSDmitry Bogdanov { 1452*b9b8782fSDmitry Bogdanov int descr_num = ARRAY_SIZE(tcm_supported_opcodes); 1453*b9b8782fSDmitry Bogdanov struct target_opcode_descriptor *descr = NULL; 1454*b9b8782fSDmitry Bogdanov unsigned char *cdb = cmd->t_task_cdb; 1455*b9b8782fSDmitry Bogdanov u8 rctd = (cdb[2] >> 7) & 0x1; 1456*b9b8782fSDmitry Bogdanov unsigned char *buf = NULL; 1457*b9b8782fSDmitry Bogdanov int response_length = 0; 1458*b9b8782fSDmitry Bogdanov u8 opts = cdb[2] & 0x3; 1459*b9b8782fSDmitry Bogdanov unsigned char *rbuf; 1460*b9b8782fSDmitry Bogdanov sense_reason_t ret = 0; 1461*b9b8782fSDmitry Bogdanov int i; 1462*b9b8782fSDmitry Bogdanov 1463*b9b8782fSDmitry Bogdanov rbuf = transport_kmap_data_sg(cmd); 1464*b9b8782fSDmitry Bogdanov if (cmd->data_length && !rbuf) { 1465*b9b8782fSDmitry Bogdanov ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 1466*b9b8782fSDmitry Bogdanov goto out; 1467*b9b8782fSDmitry Bogdanov } 1468*b9b8782fSDmitry Bogdanov 1469*b9b8782fSDmitry Bogdanov if (opts == 0) 1470*b9b8782fSDmitry Bogdanov response_length = 4 + (8 + rctd * 12) * descr_num; 1471*b9b8782fSDmitry Bogdanov else { 1472*b9b8782fSDmitry Bogdanov ret = spc_rsoc_get_descr(cmd, &descr); 1473*b9b8782fSDmitry Bogdanov if (ret) 1474*b9b8782fSDmitry Bogdanov goto out; 1475*b9b8782fSDmitry Bogdanov 1476*b9b8782fSDmitry Bogdanov if (descr) 1477*b9b8782fSDmitry Bogdanov response_length = 4 + descr->cdb_size + rctd * 12; 1478*b9b8782fSDmitry Bogdanov else 1479*b9b8782fSDmitry Bogdanov response_length = 2; 1480*b9b8782fSDmitry Bogdanov } 1481*b9b8782fSDmitry Bogdanov 1482*b9b8782fSDmitry Bogdanov buf = kzalloc(response_length, GFP_KERNEL); 1483*b9b8782fSDmitry Bogdanov if (!buf) { 1484*b9b8782fSDmitry Bogdanov ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 1485*b9b8782fSDmitry Bogdanov goto out; 1486*b9b8782fSDmitry Bogdanov } 1487*b9b8782fSDmitry Bogdanov response_length = 0; 1488*b9b8782fSDmitry Bogdanov 1489*b9b8782fSDmitry Bogdanov if (opts == 0) { 1490*b9b8782fSDmitry Bogdanov response_length += 4; 1491*b9b8782fSDmitry Bogdanov 1492*b9b8782fSDmitry Bogdanov for (i = 0; i < ARRAY_SIZE(tcm_supported_opcodes); i++) { 1493*b9b8782fSDmitry Bogdanov descr = tcm_supported_opcodes[i]; 1494*b9b8782fSDmitry Bogdanov response_length += spc_rsoc_encode_command_descriptor( 1495*b9b8782fSDmitry Bogdanov &buf[response_length], rctd, descr); 1496*b9b8782fSDmitry Bogdanov } 1497*b9b8782fSDmitry Bogdanov put_unaligned_be32(response_length - 3, buf); 1498*b9b8782fSDmitry Bogdanov } else { 1499*b9b8782fSDmitry Bogdanov response_length = spc_rsoc_encode_one_command_descriptor( 1500*b9b8782fSDmitry Bogdanov &buf[response_length], rctd, descr); 1501*b9b8782fSDmitry Bogdanov } 1502*b9b8782fSDmitry Bogdanov 1503*b9b8782fSDmitry Bogdanov memcpy(rbuf, buf, min_t(u32, response_length, cmd->data_length)); 1504*b9b8782fSDmitry Bogdanov out: 1505*b9b8782fSDmitry Bogdanov kfree(buf); 1506*b9b8782fSDmitry Bogdanov transport_kunmap_data_sg(cmd); 1507*b9b8782fSDmitry Bogdanov 1508*b9b8782fSDmitry Bogdanov if (!ret) 1509*b9b8782fSDmitry Bogdanov target_complete_cmd_with_length(cmd, SAM_STAT_GOOD, response_length); 1510*b9b8782fSDmitry Bogdanov return ret; 1511*b9b8782fSDmitry Bogdanov } 1512*b9b8782fSDmitry Bogdanov 1513de103c93SChristoph Hellwig sense_reason_t 1514de103c93SChristoph Hellwig spc_parse_cdb(struct se_cmd *cmd, unsigned int *size) 151588455ec4SChristoph Hellwig { 1516eba2ca45SNicholas Bellinger struct se_device *dev = cmd->se_dev; 151788455ec4SChristoph Hellwig unsigned char *cdb = cmd->t_task_cdb; 151888455ec4SChristoph Hellwig 1519b49d6f78SDavid Disseldorp if (!dev->dev_attrib.emulate_pr && 1520b49d6f78SDavid Disseldorp ((cdb[0] == PERSISTENT_RESERVE_IN) || 1521b49d6f78SDavid Disseldorp (cdb[0] == PERSISTENT_RESERVE_OUT) || 1522b49d6f78SDavid Disseldorp (cdb[0] == RELEASE || cdb[0] == RELEASE_10) || 1523b49d6f78SDavid Disseldorp (cdb[0] == RESERVE || cdb[0] == RESERVE_10))) { 1524b49d6f78SDavid Disseldorp return TCM_UNSUPPORTED_SCSI_OPCODE; 1525b49d6f78SDavid Disseldorp } 1526b49d6f78SDavid Disseldorp 152788455ec4SChristoph Hellwig switch (cdb[0]) { 152888455ec4SChristoph Hellwig case MODE_SELECT: 152988455ec4SChristoph Hellwig *size = cdb[4]; 15303a3c5e4aSRoland Dreier cmd->execute_cmd = spc_emulate_modeselect; 153188455ec4SChristoph Hellwig break; 153288455ec4SChristoph Hellwig case MODE_SELECT_10: 1533a85d667eSBart Van Assche *size = get_unaligned_be16(&cdb[7]); 15343a3c5e4aSRoland Dreier cmd->execute_cmd = spc_emulate_modeselect; 153588455ec4SChristoph Hellwig break; 153688455ec4SChristoph Hellwig case MODE_SENSE: 153788455ec4SChristoph Hellwig *size = cdb[4]; 15381fd032eeSChristoph Hellwig cmd->execute_cmd = spc_emulate_modesense; 153988455ec4SChristoph Hellwig break; 154088455ec4SChristoph Hellwig case MODE_SENSE_10: 1541a85d667eSBart Van Assche *size = get_unaligned_be16(&cdb[7]); 15421fd032eeSChristoph Hellwig cmd->execute_cmd = spc_emulate_modesense; 154388455ec4SChristoph Hellwig break; 154488455ec4SChristoph Hellwig case LOG_SELECT: 154588455ec4SChristoph Hellwig case LOG_SENSE: 1546a85d667eSBart Van Assche *size = get_unaligned_be16(&cdb[7]); 154788455ec4SChristoph Hellwig break; 154888455ec4SChristoph Hellwig case PERSISTENT_RESERVE_IN: 1549a85d667eSBart Van Assche *size = get_unaligned_be16(&cdb[7]); 1550d977f437SChristoph Hellwig cmd->execute_cmd = target_scsi3_emulate_pr_in; 155188455ec4SChristoph Hellwig break; 155288455ec4SChristoph Hellwig case PERSISTENT_RESERVE_OUT: 1553388fe699STang Wenji *size = get_unaligned_be32(&cdb[5]); 1554d977f437SChristoph Hellwig cmd->execute_cmd = target_scsi3_emulate_pr_out; 155588455ec4SChristoph Hellwig break; 155688455ec4SChristoph Hellwig case RELEASE: 155788455ec4SChristoph Hellwig case RELEASE_10: 155888455ec4SChristoph Hellwig if (cdb[0] == RELEASE_10) 1559a85d667eSBart Van Assche *size = get_unaligned_be16(&cdb[7]); 156088455ec4SChristoph Hellwig else 156188455ec4SChristoph Hellwig *size = cmd->data_length; 156288455ec4SChristoph Hellwig 156388455ec4SChristoph Hellwig cmd->execute_cmd = target_scsi2_reservation_release; 156488455ec4SChristoph Hellwig break; 156588455ec4SChristoph Hellwig case RESERVE: 156688455ec4SChristoph Hellwig case RESERVE_10: 156788455ec4SChristoph Hellwig /* 156888455ec4SChristoph Hellwig * The SPC-2 RESERVE does not contain a size in the SCSI CDB. 156988455ec4SChristoph Hellwig * Assume the passthrough or $FABRIC_MOD will tell us about it. 157088455ec4SChristoph Hellwig */ 157188455ec4SChristoph Hellwig if (cdb[0] == RESERVE_10) 1572a85d667eSBart Van Assche *size = get_unaligned_be16(&cdb[7]); 157388455ec4SChristoph Hellwig else 157488455ec4SChristoph Hellwig *size = cmd->data_length; 157588455ec4SChristoph Hellwig 157688455ec4SChristoph Hellwig cmd->execute_cmd = target_scsi2_reservation_reserve; 157788455ec4SChristoph Hellwig break; 157888455ec4SChristoph Hellwig case REQUEST_SENSE: 157988455ec4SChristoph Hellwig *size = cdb[4]; 15801fd032eeSChristoph Hellwig cmd->execute_cmd = spc_emulate_request_sense; 158188455ec4SChristoph Hellwig break; 158288455ec4SChristoph Hellwig case INQUIRY: 1583a85d667eSBart Van Assche *size = get_unaligned_be16(&cdb[3]); 158488455ec4SChristoph Hellwig 158588455ec4SChristoph Hellwig /* 1586125d0119SHannes Reinecke * Do implicit HEAD_OF_QUEUE processing for INQUIRY. 158788455ec4SChristoph Hellwig * See spc4r17 section 5.3 158888455ec4SChristoph Hellwig */ 158968d81f40SChristoph Hellwig cmd->sam_task_attr = TCM_HEAD_TAG; 15901fd032eeSChristoph Hellwig cmd->execute_cmd = spc_emulate_inquiry; 159188455ec4SChristoph Hellwig break; 159288455ec4SChristoph Hellwig case SECURITY_PROTOCOL_IN: 159388455ec4SChristoph Hellwig case SECURITY_PROTOCOL_OUT: 1594a85d667eSBart Van Assche *size = get_unaligned_be32(&cdb[6]); 159588455ec4SChristoph Hellwig break; 159688455ec4SChristoph Hellwig case EXTENDED_COPY: 159704b1b795SNicholas Bellinger *size = get_unaligned_be32(&cdb[10]); 159804b1b795SNicholas Bellinger cmd->execute_cmd = target_do_xcopy; 159904b1b795SNicholas Bellinger break; 160088455ec4SChristoph Hellwig case RECEIVE_COPY_RESULTS: 160104b1b795SNicholas Bellinger *size = get_unaligned_be32(&cdb[10]); 160204b1b795SNicholas Bellinger cmd->execute_cmd = target_do_receive_copy_results; 160304b1b795SNicholas Bellinger break; 160404b1b795SNicholas Bellinger case READ_ATTRIBUTE: 160588455ec4SChristoph Hellwig case WRITE_ATTRIBUTE: 1606a85d667eSBart Van Assche *size = get_unaligned_be32(&cdb[10]); 160788455ec4SChristoph Hellwig break; 160888455ec4SChristoph Hellwig case RECEIVE_DIAGNOSTIC: 160988455ec4SChristoph Hellwig case SEND_DIAGNOSTIC: 1610a85d667eSBart Van Assche *size = get_unaligned_be16(&cdb[3]); 161188455ec4SChristoph Hellwig break; 161288455ec4SChristoph Hellwig case WRITE_BUFFER: 1613a85d667eSBart Van Assche *size = get_unaligned_be24(&cdb[6]); 161488455ec4SChristoph Hellwig break; 161588455ec4SChristoph Hellwig case REPORT_LUNS: 1616d1b1f805SChristoph Hellwig cmd->execute_cmd = spc_emulate_report_luns; 1617a85d667eSBart Van Assche *size = get_unaligned_be32(&cdb[6]); 161888455ec4SChristoph Hellwig /* 1619125d0119SHannes Reinecke * Do implicit HEAD_OF_QUEUE processing for REPORT_LUNS 162088455ec4SChristoph Hellwig * See spc4r17 section 5.3 162188455ec4SChristoph Hellwig */ 162268d81f40SChristoph Hellwig cmd->sam_task_attr = TCM_HEAD_TAG; 162388455ec4SChristoph Hellwig break; 162488455ec4SChristoph Hellwig case TEST_UNIT_READY: 16251fd032eeSChristoph Hellwig cmd->execute_cmd = spc_emulate_testunitready; 1626d6e0175cSChristoph Hellwig *size = 0; 162788455ec4SChristoph Hellwig break; 1628eba2ca45SNicholas Bellinger case MAINTENANCE_IN: 1629eba2ca45SNicholas Bellinger if (dev->transport->get_device_type(dev) != TYPE_ROM) { 1630eba2ca45SNicholas Bellinger /* 1631eba2ca45SNicholas Bellinger * MAINTENANCE_IN from SCC-2 1632eba2ca45SNicholas Bellinger * Check for emulated MI_REPORT_TARGET_PGS 1633eba2ca45SNicholas Bellinger */ 1634c87fbd56SChristoph Hellwig if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS) { 1635eba2ca45SNicholas Bellinger cmd->execute_cmd = 1636eba2ca45SNicholas Bellinger target_emulate_report_target_port_groups; 1637eba2ca45SNicholas Bellinger } 1638*b9b8782fSDmitry Bogdanov if ((cdb[1] & 0x1f) == 1639*b9b8782fSDmitry Bogdanov MI_REPORT_SUPPORTED_OPERATION_CODES) 1640*b9b8782fSDmitry Bogdanov cmd->execute_cmd = 1641*b9b8782fSDmitry Bogdanov spc_emulate_report_supp_op_codes; 1642eba2ca45SNicholas Bellinger *size = get_unaligned_be32(&cdb[6]); 1643eba2ca45SNicholas Bellinger } else { 1644eba2ca45SNicholas Bellinger /* 1645eba2ca45SNicholas Bellinger * GPCMD_SEND_KEY from multi media commands 1646eba2ca45SNicholas Bellinger */ 1647eba2ca45SNicholas Bellinger *size = get_unaligned_be16(&cdb[8]); 1648eba2ca45SNicholas Bellinger } 1649eba2ca45SNicholas Bellinger break; 1650eba2ca45SNicholas Bellinger case MAINTENANCE_OUT: 1651eba2ca45SNicholas Bellinger if (dev->transport->get_device_type(dev) != TYPE_ROM) { 1652eba2ca45SNicholas Bellinger /* 1653eba2ca45SNicholas Bellinger * MAINTENANCE_OUT from SCC-2 1654eba2ca45SNicholas Bellinger * Check for emulated MO_SET_TARGET_PGS. 1655eba2ca45SNicholas Bellinger */ 1656c87fbd56SChristoph Hellwig if (cdb[1] == MO_SET_TARGET_PGS) { 1657eba2ca45SNicholas Bellinger cmd->execute_cmd = 1658eba2ca45SNicholas Bellinger target_emulate_set_target_port_groups; 1659eba2ca45SNicholas Bellinger } 1660eba2ca45SNicholas Bellinger *size = get_unaligned_be32(&cdb[6]); 1661eba2ca45SNicholas Bellinger } else { 1662eba2ca45SNicholas Bellinger /* 1663eba2ca45SNicholas Bellinger * GPCMD_SEND_KEY from multi media commands 1664eba2ca45SNicholas Bellinger */ 1665eba2ca45SNicholas Bellinger *size = get_unaligned_be16(&cdb[8]); 1666eba2ca45SNicholas Bellinger } 1667eba2ca45SNicholas Bellinger break; 166888455ec4SChristoph Hellwig default: 1669de103c93SChristoph Hellwig return TCM_UNSUPPORTED_SCSI_OPCODE; 167088455ec4SChristoph Hellwig } 167188455ec4SChristoph Hellwig 167288455ec4SChristoph Hellwig return 0; 167388455ec4SChristoph Hellwig } 167488455ec4SChristoph Hellwig EXPORT_SYMBOL(spc_parse_cdb); 1675