/* * Copyright (c) 2008, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU Lesser General Public License, * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * */ #ifndef _FC_SCSI_H_ #define _FC_SCSI_H_ /* * SCSI definitions. * From T10 SBC-3. */ /* * Block size. */ #define SCSI_BSIZE 512 /* * Operation codes. */ enum scsi_op { SCSI_OP_TEST_UNIT_READY = 0, /* test unit ready */ SCSI_OP_REQ_SENSE = 0x03, /* request sense */ SCSI_OP_INQUIRY = 0x12, /* inquiry */ SCSI_OP_START_STOP = 0x1b, /* start/stop unit command */ SCSI_OP_READ_CAP10 = 0x25, /* read capacity (32-bit blk address) */ SCSI_OP_READ10 = 0x28, /* read (32-bit block address) */ SCSI_OP_WRITE10 = 0x2a, /* write (32-bit block address) */ SCSI_OP_READ16 = 0x88, /* read (64-bit block address) */ SCSI_OP_SA_IN_16 = 0x9e, /* serivice action in (16) */ SCSI_OP_SA_OUT_16 = 0x9f, /* serivice action out (16) */ SCSI_OP_REPORT_LUNS = 0xa0, /* report LUNs */ }; /* * Name table initializer for SCSI opcodes. * Please keep this in sync with the enum above. */ #define SCSI_OP_NAME_INIT { \ [SCSI_OP_TEST_UNIT_READY] = "test unit ready", \ [SCSI_OP_REQ_SENSE] = "request sense", \ [SCSI_OP_INQUIRY] = "inquiry", \ [SCSI_OP_START_STOP] = "start/stop unit", \ [SCSI_OP_READ_CAP10] = "read_cap(10)", \ [SCSI_OP_READ10] = "read(10)", \ [SCSI_OP_WRITE10] = "write(10)", \ [SCSI_OP_READ16] = "read(16)", \ [SCSI_OP_SA_IN_16] = "sa_in(16)", \ [SCSI_OP_SA_OUT_16] = "sa_out(16)", \ [SCSI_OP_REPORT_LUNS] = "report LUNs", \ } /* * Service action codes. * Codes for SCSI_OP_SA_IN_16 and SCSI_OP_SA_OUT_16. */ enum scsi_sa_in_16 { SCSI_SA_READ_CAP16 = 0x10, /* read capacity (16) (IN only) */ SCSI_SA_RW_LONG = 0x11, /* read/write long (16) */ }; /* * Status codes. */ enum scsi_status { SCSI_ST_GOOD = 0x00, /* good */ SCSI_ST_CHECK = 0x02, /* check condition */ SCSI_ST_COND_MET = 0x04, /* condition met */ SCSI_ST_BUSY = 0x08, /* busy */ SCSI_ST_INTMED = 0x10, /* intermediate */ SCSI_ST_INTMED_MET = 0x14, /* intermediate, condition met */ SCSI_ST_RESERVED = 0x18, /* reservation conflict */ SCSI_ST_TS_FULL = 0x28, /* task set full */ SCSI_ST_ACA_ACTV = 0x30, /* ACA active */ SCSI_ST_ABORTED = 0x40, /* task aborted */ }; /* * Control byte. */ #define SCSI_CTL_LINK (1 << 0) /* Task is linked accross multiple commands */ #define SCSI_CTL_NACA (1 << 2) /* Normal auto contingent allegiance (ACA) */ /* * Test Unit Ready command. */ struct scsi_test_unit_ready { net8_t tr_op; /* opcode (0) */ net8_t _tr_resvd[4]; /* reserved */ net8_t tr_control; /* control bits */ }; /* * Request Sense command. */ struct scsi_req_sense { net8_t rs_op; /* opcode (0x88) */ net8_t rs_flags; /* LSB is descriptor sense bit */ net8_t _rs_resvd[2]; net8_t rs_alloc_len; /* allocated reply length */ net8_t rs_control; /* control bits */ }; #define SCSI_REQ_SENSE_LEN 6 /* expected length of struct */ #define SCSI_SENSE_LEN_MAX 252 /* maximum rs_alloc_len */ /* * Start / stop command. */ struct scsi_start { net8_t ss_op; /* opcode (0x88) */ net8_t ss_immed; /* LSB is respond-immediately bit */ net8_t _ss_resvd[2]; net8_t ss_flags; /* power condition, flags */ net8_t ss_control; /* control bits */ }; #define SCSI_START_LEN 6 /* expected length of struct */ /* * ss_flags: */ #define SCSI_SSF_START 0x01 /* start */ #define SCSI_SSF_LOEJ 0x02 /* load or eject depending on start */ #define SCSI_SSF_ACTIVE 0x10 /* set active power condition */ #define SCSI_SSF_IDLE 0x20 /* set idle power condition */ #define SCSI_SSF_STANDBY 0x30 /* set idle power condition */ #define SCSI_SSF_LU_CONTROL 0x70 /* set local control of power */ #define SCSI_SSF_IDLE_0 0xa0 /* force idle timer to zero */ #define SCSI_SSF_STDBY_0 0xb0 /* force standby timer to zero */ /* * Read Capacity (10) command. */ struct scsi_rcap10 { net8_t rc_op; /* opcode */ net8_t _rc_resvd; ua_net32_t rc_lba; /* logical block address */ net8_t _rc_resvd1[2]; net8_t rc_flags; /* flags (see below) */ net8_t rc_control; /* control */ }; #define SCSI_RCAP10_LEN 10 /* expected length of struct */ #define SCSI_RCAPF_PMI (1 << 0) /* rc_flags: partial medium indicator */ struct scsi_rcap10_resp { net32_t rc_lba; /* logical block address (size) */ net32_t rc_block_len; /* block length in bytes */ }; /* * Read Capacity (16) command. */ struct scsi_rcap16 { net8_t rc_op; /* opcode (0x9e) */ net8_t rc_sa; /* serivce action sub-opcode (0x10) */ ua_net64_t rc_lba; /* logical block address */ ua_net32_t rc_alloc_len; /* allocation length */ net8_t rc_flags; /* flags (see scsi_rcap10 rc_flags) */ net8_t rc_control; /* control */ }; #define SCSI_RCAP16_LEN 16 /* expected length of struct */ struct scsi_rcap16_resp { net64_t rc_lba; /* logical block address (size) */ net32_t rc_block_len; /* block length in bytes */ }; /* * Read(10) or write(10) command. */ struct scsi_rw10 { net8_t rd_op; /* opcode */ net8_t rd_flags; ua_net32_t rd_lba; /* logical block address */ net8_t rd_group; /* group number */ ua_net16_t rd_len; /* transfer length */ net8_t rd_control; /* control */ }; #define SCSI_RW10_LEN 10 /* expected length of struct */ /* * Read(16) or write(16) command. */ struct scsi_rw16 { net8_t rd_op; /* opcode */ net8_t rd_flags; ua_net64_t rd_lba; /* logical block address */ ua_net32_t rd_len; /* transfer length */ net8_t rd_group; /* group number */ net8_t rd_control; /* control */ }; #define SCSI_RW16_LEN 16 /* expected length of struct */ /* * Flags: */ #define RDF_RWPROT_BIT 5 /* shift for RD/WRPROTECT field */ #define RDF_DPO 0x10 /* disable page out - cache advisory */ #define RDF_FUA 0x08 /* force unit access */ #define RDF_FUA_NV 0x02 /* force unit access non-volatile */ /* * REPORT LUNS. */ struct scsi_report_luns { net8_t rl_op; /* opcode (0x88) */ net8_t _rl_resvd1; net8_t rl_sel_report; /* select report field */ net8_t _rl_resvd2[3]; ua_net32_t rl_alloc_len; /* allocated length for reply */ net8_t _rl_resvd3; net8_t rl_control; /* control */ }; #define SCSI_REPORT_LUNS_LEN 12 /* expected length of struct */ /* * rl_sel_report. */ #define SCSI_RLS_WKL 1 /* req. well known LUNs only */ #define SCSI_RLS_ITL 2 /* req. LUNs accessible to I_T nexus */ /* * REPORT LUNS repsonse. */ struct scsi_report_luns_resp { net32_t rl_len; /* list length in bytes */ net8_t _rl_resvd[4]; net64_t rl_lun[1]; /* list of LUNs */ }; /* * Inquiry. */ struct scsi_inquiry { net8_t in_op; /* opcode (0x12) */ net8_t in_flags; /* LSB is EVPD */ net8_t in_page_code; /* page code */ /* * Note that the in_alloc_len field was widened to 16-bits between * SPC-2 and SPC-3, but some devices will ignore the upper 8 bits. * It makes sense to use lengths less than 256 where possible. */ ua_net16_t in_alloc_len; /* allocated length for reply */ net8_t in_control; /* control */ }; #define SCSI_INQUIRY_LEN 6 /* expected length of struct */ /* * Inquiry in_flags. */ #define SCSI_INQF_EVPD (1 << 0) /* request vital product data (VPD) page */ /* * SCSI Inquiry VPD Page Codes. */ enum scsi_inq_page { SCSI_INQP_SUPP_VPD = 0, /* supported VPD list */ SCSI_INQP_UNIT_SN = 0x80, /* Unit serial number */ SCSI_INQP_DEV_ID = 0x83, /* Device Identification */ SCSI_INQP_SW_IF_ID = 0x84, /* Software Interface Identification */ SCSI_INQP_MGMT_ADDR = 0x85, /* management network addresses */ SCSI_INQP_EXT_DATA = 0x86, /* Extended Inquiry Data */ SCSI_INQP_MD_PAGE_POL = 0x87, /* Mode Page Policy */ SCSI_INQP_SCSI_PORTS = 0x88, /* SCSI Ports */ }; /* * Inquiry - standard data format. */ struct scsi_inquiry_std { net8_t is_periph; /* peripheral qualifier and type */ net8_t is_flags1; /* flags (see below) */ net8_t is_version; net8_t is_flags2; /* flags / response data format */ net8_t is_addl_len; /* additional length */ net8_t is_flags3; /* flags (see below) */ net8_t is_flags4; net8_t is_flags5; char is_vendor_id[8]; /* ASCII T10 vendor identification */ char is_product[16]; /* ASCII product identification */ char is_rev_level[4]; /* ASCII revision level */ char is_vendor_spec[56 - 36]; /* vendor specific data */ net8_t is_clock_flags; /* clocking, QAS, IUS flags */ net8_t is_resvd; net16_t is_vers_desc[8]; /* version descriptors */ /* followed by vendor-specific fields */ }; #define SCSI_INQUIRY_STD_LEN 74 /* expected length of structure */ /* * Peripheral qualifier in is_periph field. */ #define SCSI_INQ_PQUAL_MASK 0xe0 /* mask for peripheral qualifier */ #define SCSI_INQ_PTYPE_MASK 0x1f /* mask for peripheral type */ enum scsi_inq_pqual { SCSI_PQUAL_ATT = 0, /* peripheral attached */ SCSI_PQUAL_DET = (1 << 5), /* peripheral detached */ SCSI_PQUAL_NC = (3 << 5), /* not capable of attachment */ }; enum scsi_inq_ptype { SCSI_PTYPE_DIR = 0x00, /* direct acccess block device */ SCSI_PTYPE_SEQ = 0x01, /* sequential acccess block device */ SCSI_PTYPE_PRINT = 0x02, /* printer device (obsolete) */ SCSI_PTYPE_PROC = 0x03, /* processor device */ SCSI_PTYPE_WORM = 0x04, /* write-once device */ SCSI_PTYPE_CDDVD = 0x05, /* CD/DVD device */ SCSI_PTYPE_SCANNER = 0x06, /* scanner device (obsolete) */ SCSI_PTYPE_OPTMEM = 0x07, /* optical memory device */ SCSI_PTYPE_CHANGER = 0x08, /* medium changer device */ SCSI_PTYPE_RAID = 0x0c, /* storage array controoler (RAID) */ SCSI_PTYPE_SES = 0x0d, /* enclosure services device */ SCSI_PTYPE_SDIR = 0x0e, /* simplified direct acccess */ SCSI_PTYPE_OCRW = 0x0f, /* optical card reader/writer */ SCSI_PTYPE_BCC = 0x10, /* bridge controller commands */ SCSI_PTYPE_OSD = 0x11, /* object-based storage device */ SCSI_PTYPE_ADC = 0x12, /* automation/drive interface */ SCSI_PTYPE_UNK = 0x1f, /* unknown or no device type */ }; /* * is_flags[1-5] in the standard inquiry response. */ #define SCSI_INQF1_RMB (1 << 7) /* removable medium */ #define SCSI_INQF2_NACA (1 << 5) /* normal ACA */ #define SCSI_INQF2_HISUP (1 << 4) /* hierarchical LUN support */ #define SCSI_INQF2_RDF_MASK 0xf /* response data format mask */ #define SCSI_INQF2_RDF 2 /* this response data format */ #define SCSI_INQF3_PROTECT (1 << 0) /* supports protection information */ #define SCSI_INQF3_3PC (1 << 3) /* supports third-party copy */ #define SCSI_INQF3_TPGS_IMPL (1 << 4) /* supports REPORT TARGET PORT GRPS */ #define SCSI_INQF3_TPGS_EXPL (1 << 5) /* supports SET TARGET PORT GROUPS */ #define SCSI_INQF3_ACC (1 << 6) /* access controls coordinator */ #define SCSI_INQF3_SCCS (1 << 7) /* SCC supported (see SCC-2) */ #define SCSI_INQF4_ADDR16 (1 << 0) /* parallel-SCSI only */ #define SCSI_INQF4_MULTIP (1 << 4) /* multiport compliant */ #define SCSI_INQF4_ENCSERV (1 << 6) /* embedded enclosure services */ #define SCSI_INQF4_BQUE (1 << 7) /* basic task management model */ #define SCSI_INQF5_CMDQUE (1 << 1) /* full task management model */ #define SCSI_INQF5_LINKED (1 << 3) /* linked commands supported */ #define SCSI_INQF5_SYNC (1 << 4) /* parallel-SCSI only */ #define SCSI_INQF5_WBUS16 (1 << 5) /* parallel-SCSI only */ /* * Inquiry - page 0 - supported VPD pages. */ struct scsi_inquiry_supp_vpd { net8_t is_periph; /* peripheral qualifier and type */ net8_t is_page_code; /* page code (0x00) */ net8_t _is_resvd; /* reserved */ net8_t is_list_len; /* length of page list */ net8_t is_page_list[1]; /* supported page list - var. length */ }; /* * Inquiry - page 0x80 - unit serial number VPD page. */ struct scsi_inquiry_unit_sn { net8_t is_periph; /* peripheral qualifier and type */ net8_t is_page_code; /* page code (0x80) */ net8_t _is_resvd; /* reserved */ net8_t is_page_len; /* length of serial number */ net8_t is_serial[1]; /* ASCII serial number - var. length */ }; /* * Inquiry - page 0x83 - device identification. */ struct scsi_inquiry_dev_id { net8_t is_periph; /* peripheral qualifier and type */ net8_t is_page_code; /* page code (0x83) */ net16_t is_page_len; /* len of designation descriptor list */ /* descriptor list follows */ }; /* * Inquiry - page 0x83 designation descriptor list entry. */ struct scsi_inquiry_desc { net8_t id_proto_code; /* protocol identifier and code set */ net8_t id_type_flags; /* designator type and flags */ net8_t _id_resvd; /* reserved */ net8_t id_designator_len; /* designator length */ net8_t id_designator[1]; /* designator - variable length */ }; /* * id_proto_code field. */ #define SCSI_INQ_CODE_MASK 0xf /* mask for code set in id_proto_code */ enum scsi_inq_code_set { SCSI_CS_BIN = 1, /* designator contains binary values */ SCSI_CS_ASCII = 2, /* designator contains printable ASCII */ SCSI_CS_UTF8 = 3, /* designator contains UTF-8 codes */ }; /* * id_type_flags field. */ #define SCSI_INQT_PIV (1 << 7) /* protocol identifier field valid */ #define SCSI_INQT_ASSOC_BIT 4 /* shift count for association */ #define SCSI_INQT_ASSOC_MASK 0x3 /* mask for association */ #define SCSI_INQT_TYPE_MASK 0xf /* mask for designator type */ enum scsi_inq_assoc { SCSI_ASSOC_LUN = 0, /* designator is for the LUN */ SCSI_ASSOC_PORT = 1, /* designator is for the target port */ SCSI_ASSOC_TARG = 2, /* designator is for the target dev */ }; /* * Designator type field values. */ enum scsi_inq_dtype { SCSI_DTYPE_VENDOR = 0, /* vendor specific */ SCSI_DTYPE_T10_VENDOR = 1, /* T10 vendor-ID based */ SCSI_DTYPE_EUI_64 = 2, /* EUI-64 based */ SCSI_DTYPE_NAA = 3, /* network address authority (WWN) */ SCSI_DTYPE_RTPI = 4, /* relative target port id */ SCSI_DTYPE_TPORTG = 5, /* target port group */ SCSI_DTYPE_LPORTG = 6, /* logical port group */ SCSI_DTYPE_MD5_LUN = 7, /* MD5 LU identifier */ SCSI_DTYPE_SCSI_NAME = 8, /* SCSI name string */ }; #endif /* _FC_SCSI_H_ */