alua: Handle LBA_DEPENDENT state
[multipath-tools/.git] / libmultipath / prioritizers / alua_spc3.h
1 /*
2  * (C) Copyright IBM Corp. 2004, 2005   All Rights Reserved.
3  *
4  * spc3.h
5  *
6  * Tool to make use of a SCSI-feature called Asymmetric Logical Unit Access.
7  * It determines the ALUA state of a device and prints a priority value to
8  * stdout.
9  *
10  * Author(s): Jan Kunigk
11  *            S. Bader <shbader@de.ibm.com>
12  * 
13  * This file is released under the GPL.
14  */
15 #ifndef __SPC3_H__
16 #define __SPC3_H__
17 /*=============================================================================
18  * Some helper functions for getting and setting 16 and 32 bit values.
19  *=============================================================================
20  */
21 static inline unsigned short
22 get_uint16(unsigned char *p)
23 {
24         return (p[0] << 8) + p[1];
25 }
26
27 static inline void
28 set_uint16(unsigned char *p, unsigned short v)
29 {
30         p[0] = (v >> 8) & 0xff;
31         p[1] = v & 0xff;
32 }
33
34 static inline unsigned int
35 get_uint32(unsigned char *p)
36 {
37         return (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3];
38 }
39
40 static inline void
41 set_uint32(unsigned char *p, unsigned int v)
42 {
43         p[0] = (v >> 24) & 0xff;
44         p[1] = (v >> 16) & 0xff;
45         p[2] = (v >>  8) & 0xff;
46         p[3] = v & 0xff;
47 }
48
49 /*=============================================================================
50  * Definitions to support the standard inquiry command as defined in SPC-3.
51  * If the evpd (enable vital product data) bit is set the data that will be
52  * returned is selected by the page field. This field must be 0 if the evpd
53  * bit is not set.
54  *=============================================================================
55  */
56 #define OPERATION_CODE_INQUIRY          0x12
57
58 struct inquiry_command {
59         unsigned char   op;
60         unsigned char   b1;             /* xxxxxx.. = reserved               */
61                                         /* ......x. = obsolete               */
62                                         /* .......x = evpd                   */
63         unsigned char   page;
64         unsigned char   length[2];
65         unsigned char   control;
66 } __attribute__((packed));
67
68 static inline void
69 inquiry_command_set_evpd(struct inquiry_command *ic)
70 {
71         ic->b1 |= 1;
72 }
73
74 /*-----------------------------------------------------------------------------
75  * Data returned by the standard inquiry command.
76  *-----------------------------------------------------------------------------
77  *
78  * Peripheral qualifier codes.
79  */
80 #define PQ_CONNECTED                                    0x0
81 #define PQ_DISCONNECTED                                 0x1
82 #define PQ_UNSUPPORTED                                  0x3
83
84 /* Defined peripheral device types. */
85 #define PDT_DIRECT_ACCESS                               0x00
86 #define PDT_SEQUENTIAL_ACCESS                           0x01
87 #define PDT_PRINTER                                     0x02
88 #define PDT_PROCESSOR                                   0x03
89 #define PDT_WRITE_ONCE                                  0x04
90 #define PDT_CD_DVD                                      0x05
91 #define PDT_SCANNER                                     0x06
92 #define PDT_OPTICAL_MEMORY                              0x07
93 #define PDT_MEDIUM_CHANGER                              0x08
94 #define PDT_COMMUNICATIONS                              0x09
95 #define PDT_STORAGE_ARRAY_CONTROLLER                    0x0c
96 #define PDT_ENCLOSURE_SERVICES                          0x0d
97 #define PDT_SIMPLIFIED_DIRECT_ACCESS                    0x0e
98 #define PDT_OPTICAL_CARD_READER_WRITER                  0x0f
99 #define PDT_BRIDGE_CONTROLLER                           0x10
100 #define PDT_OBJECT_BASED                                0x11
101 #define PDT_AUTOMATION_INTERFACE                        0x12
102 #define PDT_LUN                                         0x1e
103 #define PDT_UNKNOWN                                     0x1f
104
105 /* Defined version codes. */
106 #define VERSION_NONE                                    0x00
107 #define VERSION_SPC                                     0x03
108 #define VERSION_SPC2                                    0x04
109 #define VERSION_SPC3                                    0x05
110
111 /* Defined TPGS field values. */
112 #define TPGS_NONE                                       0x0
113 #define TPGS_IMPLICIT                                   0x1
114 #define TPGS_EXPLICIT                                   0x2
115 #define TPGS_BOTH                                       0x3
116
117 struct inquiry_data {
118         unsigned char   b0;             /* xxx..... = peripheral_qualifier   */
119                                         /* ...xxxxx = peripheral_device_type */
120         unsigned char   b1;             /* x....... = removable medium       */
121                                         /* .xxxxxxx = reserverd              */
122         unsigned char   version;
123         unsigned char   b3;             /* xx...... = obsolete               */
124                                         /* ..x..... = normal aca supported   */
125                                         /* ...x.... = hirarchichal lun supp. */
126                                         /* ....xxxx = response format        */
127                                         /*            2 is spc-3 format      */
128         unsigned char   length;
129         unsigned char   b5;             /* x....... = storage controller     */
130                                         /*            component supported    */
131                                         /* .x...... = access controls coord. */
132                                         /* ..xx.... = target port group supp.*/
133                                         /* ....x... = third party copy supp. */
134                                         /* .....xx. = reserved               */
135                                         /* .......x = protection info supp.  */
136         unsigned char   b6;             /* x....... = bque                   */
137                                         /* .x...... = enclosure services sup.*/
138                                         /* ..x..... = vs1                    */
139                                         /* ...x.... = multiport support      */
140                                         /* ....x... = medium changer         */
141                                         /* .....xx. = obsolete               */
142                                         /* .......x = add16                  */
143         unsigned char   b7;             /* xx...... = obsolete               */
144                                         /* ..x..... = wbus16                 */
145                                         /* ...x.... = sync                   */
146                                         /* ....x... = linked commands supp.  */
147                                         /* .....x.. = obsolete               */
148                                         /* ......x. = command queue support  */
149                                         /* .......x = vs2                    */
150         unsigned char   vendor_identification[8];
151         unsigned char   product_identification[16];
152         unsigned char   product_revision[4];
153         unsigned char   vendor_specific[20];
154         unsigned char   b56;            /* xxxx.... = reserved               */
155                                         /* ....xx.. = clocking               */
156                                         /* ......x. = qas                    */
157                                         /* .......x = ius                    */
158         unsigned char   reserved4;
159         unsigned char   version_descriptor[8][2];
160         unsigned char   reserved5[22];
161         unsigned char   vendor_parameters[0];
162 } __attribute__((packed));
163
164 static inline int
165 inquiry_data_get_tpgs(struct inquiry_data *id)
166 {
167         return (id->b5 >> 4) & 3;
168 }
169
170 /*-----------------------------------------------------------------------------
171  * Inquiry data returned when requesting vital product data page 0x83.
172  *-----------------------------------------------------------------------------
173  */
174 #define CODESET_BINARY                  0x1
175 #define CODESET_ACSII                   0x2
176 #define CODESET_UTF8                    0x3
177
178 #define ASSOCIATION_UNIT                0x0
179 #define ASSOCIATION_PORT                0x1
180 #define ASSOCIATION_DEVICE              0x2
181
182 #define IDTYPE_VENDOR_SPECIFIC          0x0
183 #define IDTYPE_T10_VENDOR_ID            0x1
184 #define IDTYPE_EUI64                    0x2
185 #define IDTYPE_NAA                      0x3
186 #define IDTYPE_RELATIVE_TPG_ID          0x4
187 #define IDTYPE_TARGET_PORT_GROUP        0x5
188 #define IDTYPE_LUN_GROUP                0x6
189 #define IDTYPE_MD5_LUN_ID               0x7
190 #define IDTYPE_SCSI_NAME_STRING         0x8
191
192 struct vpd83_tpg_dscr {
193         unsigned char           reserved1[2];
194         unsigned char           tpg[2];
195 } __attribute__((packed));
196
197 struct vpd83_dscr {
198         unsigned char           b0;     /* xxxx.... = protocol id            */
199                                         /* ....xxxx = codeset                */
200         unsigned char           b1;     /* x....... = protocol id valid      */
201                                         /* .x...... = reserved               */
202                                         /* ..xx.... = association            */
203                                         /* ....xxxx = id type                */
204         unsigned char           reserved2;
205         unsigned char           length;                         /* size-4    */
206         unsigned char           data[0];
207 } __attribute__((packed));
208
209 static inline int
210 vpd83_dscr_istype(struct vpd83_dscr *d, unsigned char type)
211 {
212         return ((d->b1 & 7) == type);
213 }
214
215 struct vpd83_data {
216         unsigned char           b0;     /* xxx..... = peripheral_qualifier   */
217                                         /* ...xxxxx = peripheral_device_type */
218         unsigned char           page_code;                      /* 0x83      */
219         unsigned char           length[2];                      /* size-4    */
220         struct vpd83_dscr       data[0];
221 } __attribute__((packed));
222
223 /*-----------------------------------------------------------------------------
224  * This macro should be used to walk through all identification descriptors
225  * defined in the code page 0x83.
226  * The argument p is a pointer to the code page 0x83 data and d is used to
227  * point to the current descriptor.
228  *-----------------------------------------------------------------------------
229  */
230 #define FOR_EACH_VPD83_DSCR(p, d) \
231                 for( \
232                         d = p->data; \
233                         (((char *) d) - ((char *) p)) < \
234                         get_uint16(p->length); \
235                         d = (struct vpd83_dscr *) \
236                                 ((char *) d + d->length + 4) \
237                 )
238
239 /*=============================================================================
240  * The following stuctures and macros are used to call the report target port
241  * groups command defined in SPC-3.
242  * This command is used to get information about the target port groups (which
243  * states are supported, which ports belong to this group, and so on) and the
244  * current state of each target port group.
245  *=============================================================================
246  */
247 #define OPERATION_CODE_RTPG             0xa3
248 #define SERVICE_ACTION_RTPG             0x0a
249
250 struct rtpg_command {
251         unsigned char           op;     /* 0xa3                              */
252         unsigned char           b1;     /* xxx..... = reserved               */
253                                         /* ...xxxxx = service action (0x0a)  */
254         unsigned char                   reserved2[4];
255         unsigned char                   length[4];
256         unsigned char                   reserved3;
257         unsigned char                   control;
258 } __attribute__((packed));
259
260 static inline void
261 rtpg_command_set_service_action(struct rtpg_command *cmd)
262 {
263         cmd->b1 = (cmd->b1 & 0xe0) | SERVICE_ACTION_RTPG;
264 }
265
266 struct rtpg_tp_dscr {
267         unsigned char                   obsolete1[2];
268         /* The Relative Target Port Identifier of a target port. */
269         unsigned char                   rtpi[2];
270 } __attribute__((packed));
271
272 #define AAS_OPTIMIZED                   0x0
273 #define AAS_NON_OPTIMIZED               0x1
274 #define AAS_STANDBY                     0x2
275 #define AAS_UNAVAILABLE                 0x3
276 #define AAS_LBA_DEPENDENT               0x4
277 #define AAS_RESERVED                    0x5
278 #define AAS_OFFLINE                     0xe
279 #define AAS_TRANSITIONING               0xf
280
281 #define TPG_STATUS_NONE                 0x0
282 #define TPG_STATUS_SET                  0x1
283 #define TPG_STATUS_IMPLICIT_CHANGE      0x2
284
285 struct rtpg_tpg_dscr {
286         unsigned char   b0;             /* x....... = pref(ered) port        */
287                                         /* .xxx.... = reserved               */
288                                         /* ....xxxx = asymetric access state */
289         unsigned char   b1;             /* xxx..... = reserved               */
290                                         /* ...x.... = LBA dependent support  */
291                                         /* ....x... = unavailable support    */
292                                         /* .....x.. = standby support        */
293                                         /* ......x. = non-optimized support  */
294                                         /* .......x = optimized support      */
295         unsigned char                   tpg[2];
296         unsigned char                   reserved3;
297         unsigned char                   status;
298         unsigned char                   vendor_unique;
299         unsigned char                   port_count;
300         struct rtpg_tp_dscr             data[0];
301 } __attribute__((packed));
302
303 static inline int
304 rtpg_tpg_dscr_get_aas(struct rtpg_tpg_dscr *d)
305 {
306         return (d->b0 & 0x8f);
307 }
308
309 struct rtpg_data {
310         unsigned char                   length[4];              /* size-4 */
311         struct rtpg_tpg_dscr            data[0];
312 } __attribute__((packed));
313
314 #define RTPG_FOR_EACH_PORT_GROUP(p, g) \
315                 for( \
316                         g = &(p->data[0]); \
317                         (((char *) g) - ((char *) p)) < get_uint32(p->length); \
318                         g = (struct rtpg_tpg_dscr *) ( \
319                                 ((char *) g) + \
320                                 sizeof(struct rtpg_tpg_dscr) + \
321                                 g->port_count * sizeof(struct rtpg_tp_dscr) \
322                         ) \
323                 )
324
325 #endif /* __SPC3_H__ */
326