Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mode_sense.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2015, Emulex
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  * may be used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 
33 /**
34  * @file
35  * Mode sense SCSI command processing
36  */
37 
38 
39 #include "ocs.h"
40 #include "ocs_ramd.h"
41 
42 
43 
44 /* Mode Sense page parameter data */
45 
46 /* Mode Sense Declarations */
47 
48 
49 /**
50  * @brief Defines the mode sense 6 parameter header.
51  */
53  unsigned mode_data_length:8;
54  unsigned medium_type:8;
57  };
58 
59 /**
60  * @brief Defines the mode sense 10 parameter header.
61  */
63  unsigned mode_data_length:16;
64  unsigned medium_type:8;
66  unsigned longlba:1;
67  unsigned _1_:7;
68  unsigned _2_:8;
70  };
71 
72 /**
73  * @brief Defines the mode sense parameter block descriptor.
74  */
76  unsigned number_of_blocks:32;
77  unsigned _1_:8;
78  unsigned block_length:24;
79  };
80 
81 /**
82  * @brief Defines the mode sense long parameter block descriptor.
83  */
85  uint64_t number_of_blocks;
86  unsigned _1_:32;
87  unsigned block_length:32;
88  };
89 
90 #define MODE_SENSE_ALL_PAGES 0x3f
91 #define MODE_SENSE_PC_CURRENT 0x0
92 #define MODE_SENSE_PC_CHANGEABLE 0x1
93 #define MODE_SENSE_PC_DEFAULT 0x2
94 #define MODE_SENSE_PC_SAVED 0x3
95 
96 /* (error recovery) pcd */
97 static uint8_t mode_parameter_page_01[] = {
98  0x01, 0x0a, 0x0c, 0x4b,
99  0x30, 0x00, 0x00, 0x00,
100  0x29, 0x00, 0xff, 0xff, };
101 
102 /* (disconnect-reconnect) pcd */
103 static uint8_t mode_parameter_page_02[] = {
104  0x02, 0x0e, 0x80, 0x80, /* Buffer ratios */
105  0x00, 0x00, 0x00, 0x00, /* Bus inactivity limit/Disconnect time limit */
106  0x00, 0x00, 0x02, 0x84, /* Connect Time Limit/Max burst size */
107  0x00, 0x00, 0x00, 0x04, }; /* first burst = 2048 bytes */
108 
109 /* (format device) pcd */
110 static uint8_t mode_parameter_page_03[] = {
111  0x03, 0x16, 0x00, 0x01,
112  0x00, 0x00, 0x00, 0x00,
113  0x00, 0x00, 0x00, 0x40,
114  0x00, 0x00, 0x00, 0x00,
115  0x00, 0x00, 0x00, 0x00,
116  0x00, 0x00, 0x00, 0x00, };
117 
118 /* (rigid disk geometry) pcd */
119 static uint8_t mode_parameter_page_04[] = {
120  0x04, 0x16, 0x00, 0x01,
121  0x01, 0x00, 0x00, 0x00,
122  0x00, 0x00, 0x00, 0x00,
123  0x00, 0x00, 0x00, 0x00,
124  0x00, 0x00, 0x00, 0x00,
125  0x1c, 0x20, 0x00, 0x00, };
126 
127 /* (verify error recovery) pcd */
128 static uint8_t mode_parameter_page_07[] = {
129  0x07, 0x0a, 0x00, 0x4b,
130  0x30, 0x00, 0x00, 0x00,
131  0x00, 0x00, 0xff, 0xff, };
132 
133 /* (caching) pcd */
134 static uint8_t mode_parameter_page_08[] = {
135  0x08, 0x12, 0x10, 0x00,
136  0xff, 0xff, 0x00, 0x00,
137  0xff, 0xff, 0xff, 0xff,
138  0x80, 0x03, 0x00, 0x00,
139  0x00, 0x00, 0x00, 0x00, };
140 
141 /* (control) pcd */
142 static uint8_t mode_parameter_page_0a[] = {
143  0x0a, 0x0a, 0x02, 0x00,
144  0x00, 0x80, 0x00, 0x00,
145  0x00, 0x00, 0x00, 0x00, };
146 
147 /* Protocol Specific Logical Unit */
148 static uint8_t mode_parameter_page_18[] = {
149  0x18, 0x06, 0x00, 0x00,
150  0x00, 0x00, 0x00, 0x00, };
151 
152 /* (info exceptions control) pcd */
153 static uint8_t mode_parameter_page_1c[] = {
154  0x1c, 0x0a, 0x00, 0x00,
155  0xff, 0xff, 0xff, 0xff,
156  0x00, 0x00, 0x00, 0x00, };
157 
158 /* (vendor-specific) pcd */
159 static uint8_t mode_parameter_page_00[] = {
160  0x00, 0x02, 0x00, 0x00, };
161 
162 /**
163  * @brief internal structure for mode sense parameter data pages.
164  */
166  uint8_t page;
167  uint8_t *parameter_data;
169  };
170 
182 
183 static ocs_ramd_hndlr_rtn_e ocs_ramd_mode_sense(ocs_io_t *io, uint32_t hdrsize, uint8_t cdb[]);
184 
186 {
187  struct mode_parameter_data_s *param;
188 
189  uint32_t mode_parameter_data_count = (sizeof(mode_parameter_data) /
190  sizeof(mode_parameter_data[0]));
191  uint32_t i;
192 
193  for (i = 0, param = mode_parameter_data; i < mode_parameter_data_count;
194  i++, param++)
195  if (param->page == page)
196  return 1;
197  return 0;
198 }
199 
200 static uint32_t ocs_htobe24(uint32_t value)
201 {
202  return ((value >> 16) & 0xff) |
203  ((value) & 0xff00) |
204  ((value << 16) & 0xff0000);
205 }
206 
207 static int tm_build_mode_parameter(ocs_io_t *io, int page, int dbd, int llbaa, int hdrsize,
208  uint8_t *buffer, uint32_t buffer_length)
209 {
210  uint32_t lun = io->tgt_io.lun;
211  int shortdesc = !dbd && !llbaa;
212  int longdesc = !dbd && llbaa;
213  struct mode_parameter_data_s *param;
214  uint32_t i;
215  uint32_t mode_parameter_data_count = (sizeof(mode_parameter_data) /
216  sizeof(mode_parameter_data[0]));
217  struct mode_parameter_header6_s *hdr6 = NULL;
218  struct mode_parameter_header10_s *hdr10 = NULL;
219  struct mode_parameter_block_descriptor_s *desc = NULL;
220  struct mode_parameter_long_block_descriptor_s *ldesc = NULL;
221  uint8_t *parameter_data = NULL;
222  uint32_t length = 0;
223  uint32_t block_size;
224  uint32_t payload_length = 0;
225  uint8_t *local_buffer;
226  uint8_t *local_ptr;
227  ocs_ramdisc_t *ramdisc;
228  ocs_t *ocs = io->ocs;
229 
230  ramdisc = ocs_ramd_lookup(io, lun);
231 
232  ocs_memset(buffer, 0, buffer_length);
233 
234  length += (hdrsize == 6) ? sizeof(struct mode_parameter_header6_s) :
235  sizeof(struct mode_parameter_header10_s);
236  if (shortdesc)
237  length += sizeof(struct mode_parameter_block_descriptor_s);
238  if (longdesc)
239  length += sizeof(struct mode_parameter_long_block_descriptor_s);
240  for (i = 0, param = mode_parameter_data; i < mode_parameter_data_count;
241  i++, param++)
242  if ((page == MODE_SENSE_ALL_PAGES) || (param->page == page))
243  length += param->parameter_data_length;
244 
245  /* allocate a local buffer */
246  local_buffer = ocs_malloc(ocs, length, OCS_M_NOWAIT);
247  if (!local_buffer)
248  return -1;
249 
250  ocs_memset(local_buffer, 0, length);
251 
252  /* assign header, descriptor block and parameter data pointers */
253  local_ptr = local_buffer;
254  if (hdrsize == 6) {
255  hdr6 = (struct mode_parameter_header6_s *) local_ptr;
256  local_ptr += sizeof(struct mode_parameter_header6_s);
257  } else {
258  hdr10 = (struct mode_parameter_header10_s *) local_ptr;
259  local_ptr += sizeof(struct mode_parameter_header10_s);
260  }
261 
262  /* assign descriptor block */
263  if (longdesc) {
264  ldesc =
265  (struct mode_parameter_long_block_descriptor_s *)local_ptr;
266  local_ptr +=
268  }
269  if (shortdesc) {
270  desc = (struct mode_parameter_block_descriptor_s *)local_ptr;
271  local_ptr += sizeof(struct mode_parameter_block_descriptor_s);
272  }
273  /* assign pointer to parameter data */
274  parameter_data = local_ptr;
275 
276  /* fill in header */
277  if (hdr6) {
278  hdr6->mode_data_length = length - 1;
279  hdr6->medium_type = 0;
280  hdr6->device_specific_parameter = 0x10;
281  if (shortdesc)
283  sizeof(struct mode_parameter_block_descriptor_s);
284  }
285  if (hdr10) {
286  hdr10->mode_data_length = ocs_htobe16(length - 2);
287  hdr10->medium_type = 0;
288  hdr10->device_specific_parameter = 0x10;
289  hdr10->longlba = llbaa;
290  if (shortdesc)
291  hdr10->block_descriptor_length =
292  ocs_htobe16(sizeof(
294  if (longdesc)
295  hdr10->block_descriptor_length =
296  ocs_htobe16(sizeof(
298  }
299 
300  /* fill in block descriptor (if defined)
301  * If the ramdisc has protection enabled then the logical block size, which report here,
302  * is actually 8 bytes shorter than the formatted block size because we report the size
303  * of the user data area with the DIF data
304  */
305  block_size = ramdisc->data_block_size;
306 
307  if (shortdesc) {
308  desc->number_of_blocks = ocs_htobe32(ramdisc->block_count);
309  desc->block_length = ocs_htobe24(block_size);
310  }
311 
312  if (longdesc) {
313  ldesc->number_of_blocks =
314  ocs_htobe64(ramdisc->block_count);
315  ldesc->block_length = ocs_htobe32(block_size);
316  }
317 
318  /* fill in page data */
319  local_ptr = parameter_data;
320  for (i = 0, param = mode_parameter_data; i < mode_parameter_data_count;
321  i++, param++)
322  if ((page == MODE_SENSE_ALL_PAGES) || (param->page == page)) {
323 
324  /* Check for ATO in control page (0xa) */
325 #define tm_prot_luns (0)
326 /* Values for tm_prot_mode */
327 #define TM_PROT_MODE_DEFAULT 0x0
328 #define TM_PROT_MODE_END2END 0x1
329 #define TM_PROT_MODE_WIRE_ONLY 0x2
330 #define TM_PROT_MODE_HOST_ONLY 0x3
331 #define tm_prot_mode TM_PROT_MODE_DEFAULT
332 
333  if (param->page == 0xa) {
334  if (tm_prot_luns &&
336  param->parameter_data[5] |= 0x80;
337  else
338  param->parameter_data[5] &= ~0x80;
339  } else if (param->page == 2) {
340  /*
341  * Update the first burst size is the
342  * disconnect/reconnect mode page.
343  */
344  ocs_t *ocs = io->ocs;
345  uint32_t fburst = ocs_scsi_get_property(ocs, OCS_SCSI_MAX_FIRST_BURST) / 512;
346  param->parameter_data[14] = (fburst >> 8) & 0xff;
347  param->parameter_data[15] = fburst & 0xff;
348  }
349 
350  ocs_memcpy(local_ptr, param->parameter_data,
351  param->parameter_data_length);
352  local_ptr += param->parameter_data_length;
353  }
354 
355  /* copy to buffer */
356  payload_length = (buffer_length < length) ? buffer_length : length;
357  ocs_memcpy(buffer, local_buffer, payload_length);
358 
359  /* free local buffer */
360  ocs_free(ocs, local_buffer, length);
361 
362  /* return length of payload */
363  return payload_length;
364 }
365 
366 /**
367  * @ingroup scsi_cmd
368  * @brief Process SCSI Mode Sense 6 command
369  *
370  * The SCSI Mode Sense 6 command is processed
371  *
372  * @param io pointer to IO context
373  * @param cdb pointer to SCSI cdb
374  *
375  * @return returns the handler status for the command. SCSI_HANDLER_NOT_STARTED
376  * and SCSI_CMD_NOT_SUPPORTED are errors and the IO should be freed.
377  */
378 
379 ocs_ramd_hndlr_rtn_e ocs_ramd_mode_sense6(ocs_io_t *io, uint8_t cdb[]) {
380  return ocs_ramd_mode_sense(io, 6, cdb);
381 }
382 
383 /**
384  * @ingroup scsi_cmd
385  * @brief Process SCSI Mode Sense 10 command
386  *
387  * The SCSI Mode Sense 10 command is processed
388  *
389  * @param io pointer to IO context
390  * @param cdb pointer to SCSI cdb
391  *
392  * @return returns the handler status for the command. SCSI_HANDLER_NOT_STARTED
393  * and SCSI_CMD_NOT_SUPPORTED are errors and the IO should be freed.
394  */
395 
396 ocs_ramd_hndlr_rtn_e ocs_ramd_mode_sense10(ocs_io_t *io, uint8_t cdb[]) {
397  return ocs_ramd_mode_sense(io, 10, cdb);
398 }
399 
400 static ocs_ramd_hndlr_rtn_e ocs_ramd_mode_sense(ocs_io_t *io, uint32_t hdrsize, uint8_t cdb[]) {
401  uint32_t allocation_len;
402  uint8_t page;
403  //uint8_t subpage;
404  uint8_t dbd;
405  uint8_t pc;
406  uint32_t mode_sense_len;
407  uint8_t llbaa = 0;
409  ocs_scsi_sgl_t sgl[1];
410 
411  dbd = (cdb[1] & 0x08) != 0;
412  page = cdb[2] & 0x3f;
413  pc = (cdb[2] >> 6) & 0x03;
414  //subpage = cdb[3];
415 //aka pf
416  llbaa = (cdb[1] & 0x10) != 0;
417 
418  if (hdrsize == 6)
419  allocation_len = cdb[4];
420  else
421  allocation_len = (cdb[7] << 8) | (cdb[8] << 0);
422 
423  /* As per SPC-4 an allocation length of 0 means no data transfer
424  * so Just return good status now.
425  */
426  if (allocation_len == 0) {
427  return(ocs_ramd_good_status(io));
428  }
429 
430  /* Page control CHANGEABLE, not supported, return illegal request
431  * invalid field in cdb (SPC-4, 6.11.3)
432  */
433  if (pc == MODE_SENSE_PC_CHANGEABLE) {
434  ocs_log_info(NULL, "Mode Sense changeable not supported for LUN %d\n", io->tgt_io.lun);
435 
437  }
438 
439  /* Page control SAVED, not supported, return illegal request
440  * saving parameters not supported (SPC-4, 6.11.5)
441  */
442  if (pc == MODE_SENSE_PC_SAVED) {
443  ocs_log_info(NULL, "Mode Sense saving parameters not supported for LUN %d\n", io->tgt_io.lun);
445  }
446 
447  if ((page != MODE_SENSE_ALL_PAGES) && !tm_mode_page_supported(page)) {
448  ocs_log_info(NULL, "Mode Sense (6) unsupported page code 0x%02x for LUN %d\n", page, io->tgt_io.lun);
449 
451  }
452 
453  if (ocs_dma_alloc(io->ocs, &io->tgt_io.payload, 256, 16)) {
454  ocs_log_err(NULL, "ocs_scsi_dma_alloc failed\n");
456  }
457  ocs_assert(io->tgt_io.payload.virt, -1);
458 
459  /* build response data */
460  mode_sense_len = tm_build_mode_parameter(io, page, dbd, llbaa, hdrsize, io->tgt_io.payload.virt, allocation_len);
461 
462  sgl[0].addr = io->tgt_io.payload.phys;
463  sgl[0].len = mode_sense_len;
464 
465  io->tgt_io.is_read = TRUE;
466 
467  /* Send read data */
468  if (ocs_scsi_send_rd_data(io, OCS_SCSI_LAST_DATAPHASE, NULL, sgl, 1, sgl[0].len, scsi_dataphase_cb, NULL) == 0) {
470  } else {
472  }
473  return rc;
474 }
static uint8_t mode_parameter_page_02[]
Definition: mode_sense.c:103
#define tm_prot_luns
static uint8_t mode_parameter_page_00[]
Definition: mode_sense.c:159
uint32_t data_block_size
Definition: ocs_ramdisc.h:90
Defines the mode sense long parameter block descriptor.
Definition: mode_sense.c:84
internal structure for mode sense parameter data pages.
Definition: mode_sense.c:165
#define MODE_SENSE_PC_SAVED
Definition: mode_sense.c:94
uintptr_t addr
Definition: ocs_scsi.h:219
static uint8_t mode_parameter_page_1c[]
Definition: mode_sense.c:153
static uint8_t mode_parameter_page_01[]
Definition: mode_sense.c:97
static int tm_mode_page_supported(int page)
Definition: mode_sense.c:185
static uint8_t mode_parameter_page_0a[]
Definition: mode_sense.c:142
static uint8_t mode_parameter_page_08[]
Definition: mode_sense.c:134
unsigned block_descriptor_length
Definition: mode_sense.c:56
Defines the mode sense 10 parameter header.
Definition: mode_sense.c:62
uint64_t block_count
Definition: ocs_ramdisc.h:95
static uint8_t mode_parameter_page_03[]
Definition: mode_sense.c:110
generic scatter-gather list structure
Definition: ocs_scsi.h:218
static uint8_t mode_parameter_page_07[]
Definition: mode_sense.c:128
ramdisc instance structure
Definition: ocs_ramdisc.h:88
static uint32_t ocs_htobe24(uint32_t value)
Definition: mode_sense.c:200
#define SNSCODE_SAVE_NOT_SUPPORTED
Definition: ocs_ramd.h:62
unsigned device_specific_parameter
Definition: mode_sense.c:55
#define tm_prot_mode
ocs_ramd_hndlr_rtn_e ocs_ramd_mode_sense10(ocs_io_t *io, uint8_t cdb[])
Process SCSI Mode Sense 10 command.
Definition: mode_sense.c:396
uint8_t * parameter_data
Definition: mode_sense.c:167
int32_t ocs_scsi_send_rd_data(ocs_io_t *io, uint32_t flags, ocs_scsi_dif_info_t *dif_info, ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint64_t wire_len, ocs_scsi_io_cb_t cb, void *arg)
Definition: ocs_scsi.c:1629
ocs_ramd_hndlr_rtn_e ocs_ramd_mode_sense6(ocs_io_t *io, uint8_t cdb[])
Process SCSI Mode Sense 6 command.
Definition: mode_sense.c:379
static int tm_build_mode_parameter(ocs_io_t *io, int page, int dbd, int llbaa, int hdrsize, uint8_t *buffer, uint32_t buffer_length)
Definition: mode_sense.c:207
#define OCS_SCSI_LAST_DATAPHASE
Definition: ocs_scsi.h:58
Defines the mode sense 6 parameter header.
Definition: mode_sense.c:52
ocs_ramd_hndlr_rtn_e
Definition: ocs_ramd.h:71
static struct mode_parameter_data_s mode_parameter_data[]
Definition: mode_sense.c:171
ocs_ramdisc_t * ocs_ramd_lookup(ocs_io_t *io, uint32_t lun)
Given an IO and a LUN number, return the ramdisc to which the IO is directed.
Definition: ocs_ramd.c:471
unsigned block_descriptor_length
Definition: mode_sense.c:69
#define MODE_SENSE_ALL_PAGES
Definition: mode_sense.c:90
ocs_ramd_hndlr_rtn_e ocs_ramd_check_cond(ocs_io_t *io, uint8_t sense_key, uint8_t asc, uint8_t ascq)
Send a SCSI check condition.
Definition: ocs_ramd.c:2551
static uint8_t mode_parameter_page_04[]
Definition: mode_sense.c:119
size_t len
Definition: ocs_scsi.h:221
Defines the mode sense parameter block descriptor.
Definition: mode_sense.c:75
uint32_t parameter_data_length
Definition: mode_sense.c:168
#define ocs_assert(cond,...)
Definition: ocs_debug.h:176
#define MODE_SENSE_PC_CHANGEABLE
Definition: mode_sense.c:92
#define SNS_ILLEGAL_REQ
Definition: ocs_ramd.h:49
static uint8_t mode_parameter_page_18[]
Definition: mode_sense.c:148
static ocs_ramd_hndlr_rtn_e ocs_ramd_mode_sense(ocs_io_t *io, uint32_t hdrsize, uint8_t cdb[])
Definition: mode_sense.c:400
#define SNSCODE_INV_CDB
Definition: ocs_ramd.h:58
int32_t scsi_dataphase_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, uint32_t flags, void *arg)
ocs_ramd_hndlr_rtn_e ocs_ramd_good_status(ocs_io_t *io)
Send a good SCSI status.
Definition: ocs_ramd.c:2519
uint32_t ocs_scsi_get_property(ocs_t *ocs, ocs_scsi_property_e prop)
Return SCSI API integer valued property.
Definition: ocs_scsi.c:2799
#define TM_PROT_MODE_HOST_ONLY
unsigned device_specific_parameter
Definition: mode_sense.c:65