Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
elxu_lancer.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 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <elxu_sli4.h>
37 #include <elxu_lancer.h>
38 #include <elxu_device.h>
39 #include <elxu_mbox.h>
40 #include <elxu_common.h>
41 #include <assert.h>
42 
43 static sli4_object_t *sli4_object_scan_directory(elxu_device_t *device, const char *directory);
44 const char *oft2string(uint32_t oft);
45 
46 /**
47  * @brief Create a list of all SLI4 objects
48  *
49  * The SLI4 HBA referred to by 'device' is scanned returning a list of all objects
50  *
51  * @param device pointer to device
52  */
54 {
55  return sli4_object_scan_directory (device, "/");
56 }
57 
58 /**
59  * @brief Scan an SLI4 object directory returning a list of all objects
60  *
61  * The SLI4 object directory 'directory' is scanned recursively. A list of
62  * all objects is returned
63  *
64  * @param device pointer to device
65  * @param directory name of directory
66  */
67 static sli4_object_t *sli4_object_scan_directory(elxu_device_t *device, const char *directory)
68 {
69  mbox_command_t mqe;
70  mbox_sli_config_t *sli_config;
73  int rval;
74  uint32_t offset = 0;
75  sli4_object_t *obj;
76  sli4_object_t *head = NULL;
77  sli4_object_t *tail = NULL;
78  int object_count;
79 
80  memset(&mqe, 0, 256);
81  sli_config = (mbox_sli_config_t*)&mqe;
82  mbox = (mbox_common_read_object_list_t*)&(sli_config[1]);
84 
85  sli_config->command = MBOX_SLI_CONFIG;
86  sli_config->emb = 1;
87  sli_config->pcmd_count = 0;
88  sli_config->payload_length = sizeof (*mbox);
89 
92  mbox->timeout = 0;
93  mbox->request_length = sizeof (*mbox) - 4*sizeof (uint32_t);
94  mbox->version = 0;
95 
96  mbox->descriptor_count = 0;
97  mbox->descriptor_offset = 0;
98 
99  /*
100  * Send a request with descriptor_count and descriptor_offset == 0. This will return
101  * a count of the objects in the directory.
102  */
103  strncpy((char*)mbox->object_directory_name, directory, (sizeof(mbox->object_directory_name) - 1));
104  rval = mbox_common(device, &mqe, sli_config->payload_length, NULL, 0, NULL, 0);
105  if (rval)
106  {
107  printf ("Error: rval %d\n", rval);
108  return NULL;
109  }
110  if (rsp->status)
111  {
112  return NULL;
113  }
114 
115  /*
116  * Iterate over the objects in this directory
117  */
118 
119  object_count = rsp->actual_descriptor_count;
120 
121  for (offset = 0; offset < object_count; offset ++)
122  {
123  // Fetch one
124  memset(&mqe, 0, 256);
125 
126  sli_config->command = MBOX_SLI_CONFIG;
127  sli_config->emb = 1;
128  sli_config->pcmd_count = 0;
129  sli_config->payload_length = sizeof (*mbox) + sizeof (mbox_hbd_t);
130 
133  mbox->timeout = 0;
134 
135  mbox->version = 0;
136 
137  mbox->descriptor_count = 1;
138  mbox->descriptor_offset = offset;
139 
142 
143  mbox->request_length = sizeof (*mbox) - 4*sizeof (uint32_t) +
145 
147 
148  strncpy((char*)mbox->object_directory_name, directory, (sizeof(mbox->object_directory_name) - 1));
149 
150  rval = mbox_common(device, &mqe, 256, NULL, 0,
151  (uint8_t*)&desc, sizeof(desc));
152 
153  if (rval)
154  {
155  printf ("Error: rval %d\n", rval);
156  break;
157  }
158 
159  if (rsp->actual_descriptor_count == 0 || rsp->actual_response_length == 0)
160  break;
161 
162  char fullPath[128];
163 
164  snprintf(fullPath, sizeof(fullPath), "%s%s%s", directory,
165  directory[strlen(directory)-1] == '/' ? "" : "/",
166  (char*)desc.object_base_name);
167 
168  obj = sli4_object_new(fullPath, desc.oft, desc.object_info);
169 
170  if (!obj) {
171  break;
172  }
173 
174  if (tail)
175  {
176  tail->next = obj;
177  tail = obj;
178  }
179  else
180  head = tail = obj;
181 
182  if (desc.oft == OFT_DIRECTORY_OBJECT)
183  {
184  if ((strcmp ((char*)desc.object_base_name, ".") == 0) ||
185  (strcmp ((char*)desc.object_base_name, "..") == 0)) {
186  continue;
187  }
188 
189  obj = sli4_object_scan_directory(device, fullPath);
190  if (obj)
191  {
192  if (tail)
193  {
194  tail->next = obj;
195  for (tail = obj; tail->next; tail = tail->next)
196  ;
197  }
198  }
199  }
200  }
201 
202  return head;
203 }
204 
205 
206 /**
207  * @brief Deletes an SLI4 object
208  *
209  * Deletes the SLI4 object.
210  *
211  * @param device pointer to device
212  * @param objectName name of object
213  */
214 int sli4_object_delete (elxu_device_t *device, const char *objectName)
215 {
216  void *mqe = zmalloc(256);
217  mbox_sli_config_t *sli_config;
220  int rval;
221 
222  if (!mqe)
223  return MALLOC_FAILED;
224 
225  sli_config = mqe;
226  mbox = (mbox_common_delete_object_t*)(&sli_config[1]);
227  rsp = (mbox_common_delete_object_rsp_t*)mbox;
228 
229  sli_config->command = MBOX_SLI_CONFIG;
230  sli_config->emb = 1;
231  sli_config->pcmd_count = 0;
232  sli_config->payload_length = sizeof (*mbox) + sizeof (mbox_hbd_t);
233 
236  mbox->timeout = 0;
237  mbox->request_length = sizeof (*mbox) - 4*sizeof (uint32_t);
238  mbox->version = 0;
239 
240  strncpy((char*)mbox->object_name, objectName, (sizeof(mbox->object_name) - 1));
241 
242 
243  rval = mbox_common(device, mqe, sli_config->payload_length, mbox, sizeof(*mbox), rsp, sizeof(*rsp));
244 
245  if (rval)
246  {
247  printf ("Error: rval %d\n", rval);
248  free(mqe);
249  return -1;
250  }
251 
252  if (rsp->status)
253  {
254  free(mqe);
255  return -rsp->status;
256  }
257  free(mqe);
258  return 0;
259 }
260 
261 
262 /**
263  * @brief Return an SLI4 object's length in bytes
264  *
265  * Returns the length of an SLI4 normal object, or the number of elements in
266  * an SLI4 directory object
267  *
268  * @param device pointer to device
269  * @param objectName name of object
270  */
271 int sli4_object_length(elxu_device_t *device, const char *objectName)
272 {
273  void *mqe = zmalloc(256);
274  mbox_sli_config_t *sli_config;
277  int rval;
278  uint32_t length = 0;
279 
280  if (!mqe)
281  return MALLOC_FAILED;
282 
283  sli_config = mqe;
284  mbox = (mbox_common_read_object_t*)(&sli_config[1]);
285  rsp = (mbox_common_read_object_rsp_t*)mbox;
286 
287  sli_config->command = MBOX_SLI_CONFIG;
288  sli_config->emb = 1;
289  sli_config->pcmd_count = 0;
290  sli_config->payload_length = sizeof (*mbox) + sizeof (mbox_hbd_t);
291 
294  mbox->timeout = 0;
295  mbox->request_length = sizeof (*mbox) - 4*sizeof (uint32_t);
296  mbox->version = 0;
297  mbox->desired_read_length = 0;
298  mbox->read_offset = 0;
299  strncpy((char*)mbox->object_name, objectName, sizeof(mbox->object_name));
301 
302  rval = mbox_common(device, mqe, sli_config->payload_length, mbox, sizeof(*mbox), rsp, sizeof(*rsp));
303  if (rval)
304  {
305  printf ("Error: rval %d\n", rval);
306  free(mqe);
307  return -1;
308  }
309  if (rsp->status)
310  {
311  free(mqe);
312  return -rsp->status;
313  }
314 
315  length = rsp->actual_read_length;
316  free(mqe);
317 
318  return length;
319 }
320 
321 /**
322  * @brief Read data from an object
323  *
324  * The data of an SLI4 data object is read.
325  *
326  * @param device pointer to device
327  * @param objectName name of object to read
328  * @param buffer pointer to data buffer
329  * @param bufferLength byte length of data buffer
330  *
331  * returns the number of bytes read, or a negative value
332  */
333 int sli4_object_read(elxu_device_t *device, const char *objectName, void *buffer, uint32_t bufferLength)
334 {
335  int rval;
336  uint32_t objectLength;
337  uint32_t offset = 0;
338  uint32_t n;
339  void *mqe = NULL;
340  mbox_sli_config_t *sli_config = NULL;
341  mbox_common_read_object_t *mbox = NULL;
342  mbox_common_read_object_rsp_t *rsp = NULL;
343 
344  mqe = zmalloc(MBOX_ENTRY_LENGTH);
345  if (!mqe)
346  return MALLOC_FAILED;
347 
348  sli_config = mqe;
349  mbox = (mbox_common_read_object_t*)(&sli_config[1]);
350  rsp = (mbox_common_read_object_rsp_t*)mbox;
351 
352  rval = sli4_object_length(device, objectName);
353  if (rval < 0)
354  {
355  zfree (mqe);
356  return rval;
357  }
358 
359  objectLength = (uint32_t) rval;
360  if (bufferLength > objectLength)
361  {
362  bufferLength = objectLength;
363  }
364 
365  while (bufferLength > 0)
366  {
367  n = bufferLength;
368 #define MAX_OBJECT_READ 3840
369  if (n > MAX_OBJECT_READ)
370  n = MAX_OBJECT_READ;
371 
372  memset(mqe, 0, MBOX_ENTRY_LENGTH);
373 
374  sli_config->command = MBOX_SLI_CONFIG;
375  sli_config->emb = 1; // Embedded, Mbox Cmd data is placed in the 256 MQE
376  sli_config->pcmd_count = 0;
377  sli_config->payload_length = sizeof (*mbox) + sizeof (mbox_hbd_t);
378 
381  mbox->timeout = 0;
382  mbox->request_length = sizeof (*mbox) - 4*sizeof (uint32_t) + sizeof(mbox_hbd_t);
383  mbox->version = 0;
384  mbox->desired_read_length = n;
385  mbox->read_offset = offset;
386  strncpy((char*)mbox->object_name, objectName, (sizeof(mbox->object_name) - 1));
389 
390  rval = mbox_common(device, mqe, MBOX_ENTRY_LENGTH, buffer, n, buffer, n);
391 
392  if (rval)
393  {
394  printf ("Error: rval %d\n", rval);
395  zfree(mqe);
396  return -1;
397  }
398  if (rsp->status)
399  {
400  zfree(mqe);
401  return -rsp->status;
402  }
403 
404  offset += n;
405  bufferLength -= n;
406 
407  buffer = (((uint8_t*)buffer) + n);
408  }
409 
410  zfree(mqe);
411  // return amount read
412  return offset;
413 }
414 
415 
416 
417 /**
418  * @brief Write data into an object
419  *
420  * Write the data into an SLI4 data object.
421  *
422  * @param device pointer to device
423  * @param objectName name of object to write
424  * @param buffer pointer to data buffer
425  * @param bufferLength byte length of data buffer
426  *
427  * returns the number of bytes written, or a negative value
428  */
429 int sli4_object_write (elxu_device_t *device, const char *objectName, int buffer_offset, void *buffer, uint32_t bufferLength, int eofl)
430 {
431  int rval;
432  uint32_t offset = buffer_offset;
433  uint32_t n;
434  void *mqe = NULL;
435  mbox_sli_config_t *sli_config = NULL;
436  mbox_common_write_object_t *mbox = NULL;
437  mbox_common_write_object_rsp_t *rsp = NULL;
438 
439  mqe = zmalloc(MBOX_ENTRY_LENGTH);
440  if (!mqe)
441  return MALLOC_FAILED;
442 
443  sli_config = mqe;
444  mbox = (mbox_common_write_object_t*)(&sli_config[1]);
445  rsp = (mbox_common_write_object_rsp_t*)mbox;
446  while (bufferLength > 0)
447  {
448  n = bufferLength;
449 #define MAX_OBJECT_WRITE 3840
450  if (n > MAX_OBJECT_WRITE)
451  n = MAX_OBJECT_WRITE;
452 
453  memset(mqe, 0, MBOX_ENTRY_LENGTH);
454 
455  sli_config->command = MBOX_SLI_CONFIG;
456  sli_config->emb = 1; // Embedded, Mbox Cmd data is placed in the 256 MQE
457  sli_config->pcmd_count = 0;
458  sli_config->payload_length = sizeof (*mbox) + sizeof (mbox_hbd_t);
459 
462  mbox->timeout = 0;
463  mbox->request_length = sizeof (*mbox) - 4*sizeof (uint32_t) + sizeof(mbox_hbd_t);
464  mbox->version = 0;
465  mbox->desired_write_length = n;
466  if ((bufferLength <= MAX_OBJECT_WRITE) && eofl)
467  mbox->eof = 1;
468 
469  mbox->write_offset = offset;
470  strncpy((char*)mbox->object_name, objectName, (sizeof(mbox->object_name) - 1));
473 
474  printf ("."); fflush (stdout);
475  rval = mbox_common(device, mqe, MBOX_ENTRY_LENGTH, buffer, n, buffer, n);
476  if (rval)
477  {
478  printf ("Error: rval %d\n", rval);
479  zfree(mqe);
480  return -1;
481  }
482 
483  if (rsp->status)
484  {
485  printf ("\nStatus 0x%X Additional Status 0x%X \n", rsp->status, rsp->additional_status);
486  zfree(mqe);
487  return -rsp->status;
488  }
489  n = rsp->actual_write_length;
490  assert(rsp->actual_write_length - offset >= 0);
491  offset += n;
492  bufferLength -= n;
493 
494  buffer = (((uint8_t*)buffer) + n);
495  }
496 
497  zfree(mqe);
498  // return written ammount
499  return offset;
500 }
501 
502 
503 
504 
505 
506 /**
507  * @brief Return a string associated with an object type
508  *
509  * Returns a string associated with an object type
510  *
511  * @param oft Object type
512  */
513 const char *oft2string(uint32_t oft)
514 {
515  switch (oft)
516  {
517  case OFT_NORMAL_OBJECT: return "normal";
518  case OFT_DIRECTORY_OBJECT: return "directory";
519  case OFT_LINKED_OBJECT: return "link";
520  }
521  return "unknown";
522 }
523 
524 /**
525  * @brief Instantiate a new sli4_object_t
526  *
527  * An sli4_object_t is allocated and populated with name, type and length;
528  *
529  * @param name Name of object
530  * @param type Type of object
531  * @param length Length of object
532  */
533 sli4_object_t *sli4_object_new(const char *name, uint32_t type, uint32_t length)
534 {
535  sli4_object_t *new = zmalloc(sizeof(*new));
536  if (new)
537  {
538  new->next = NULL;
539  new->name = strdup (name);
540  new->type = type;
541  new->length = length;
542  }
543  return new;
544 }
545 
546 /**
547  * @brief Free and sli4_object_t
548  *
549  * The object given by 'obj' if free'd
550  *
551  * @param obj Object to free
552  */
554 {
555  if (obj)
556  {
557  if (obj->name)
558  free (obj->name);
559  free(obj);
560  }
561 }
562 
563 /**
564  * @brief Free a list of sli4_object_t's
565  *
566  * The elements of list given by 'head' are freed
567  *
568  * @param head head of list
569  */
571 {
572  sli4_object_t *next;
573 
574  for (; head; head = next)
575  {
576  next = head->next;
577  sli4_object_free(head);
578  }
579 }
580 
581 /**
582 * @page elxsdkutil_lpe1600x.html LPe1600x Adapter APIs
583 *
584 * @section lpe1600x_obj_mgmt Data Object Management API
585 *
586 * The LPe16000/LPe16002 data object management API consists of the functions shown
587 * in the following table.
588 *
589 * <table class="dashboard">
590 * <tr><th>Function Name</th><th>Description</th></tr>
591 * <tr><td>sli4_object_enumerate()</td><td>Create a list of all SLI-4 objects.</td></tr>
592 * <tr><td>sli4_object_length()</td><td>Return an SLI-4 object's length in bytes.</td></tr>
593 * <tr><td>sli4_object_read()</td><td>Read data object.</td></tr>
594 * <tr><td>sli4_object_write()</td><td>Write data object.</td></tr>
595 * </table>
596 *
597 *
598 * @section lpe1600x_obj_groups Data Object Groups
599 *
600 * Within the flash file system of an LPe16000/LPe16002 HBA, directory names are used
601 * to identify the type of object and file names are used to specify the instance of the
602 * object. The object groups (directories) shown in the following table are supported by
603 * LPe16000/LPe16002 HBAs..
604 *
605 * <table class="dashboard">
606 * <tr><th>Group</th><th>Description</th></tr>
607 * <tr><td>/</td><td>The root directory for all object groups.</td></tr>
608 * <tr><td>/cfg</td><td>Objects in this group correspond to configuration objects.</td></tr>
609 * <tr><td>/dbg</td><td>Objects in this group correspond to device debug and
610 * postmortem diagnosis. When a diagnostic dump (dump.bin) file is
611 * retrieved, it is retrieved from the /dbg directory.</td></tr>
612 * <tr><td>/prg</td><td>Objects in this group correspond to firmware program images.
613 * When an LPe16000/LPe16002 HBA firmware file (.grp) is
614 * downloaded, it is sent to the /prg directory.</td></tr>
615 * <tr><td>/vpd</td><td>Objects in this group correspond to different VPD images for the
616 * different protocols and function types.</td></tr>
617 * <tr><td>/xrom</td><td>Objects in this group correspond to the expansion ROM images
618 * for the different protocols.</td></tr>
619 * </table>
620 *
621 */
622 
sli4_object_t * sli4_object_new(const char *name, uint32_t type, uint32_t length)
Instantiate a new sli4_object_t.
Definition: elxu_lancer.c:533
uint32_t payload_length
Definition: elxu_sli4.h:168
uint32_t object_name[OBJECT_NAME_LENGTH]
Definition: elxu_sli4.h:596
uint32_t object_name[OBJECT_NAME_LENGTH]
Definition: elxu_sli4.h:551
#define OFT_NORMAL_OBJECT
Definition: elxu_sli4.h:703
void sli4_object_free(sli4_object_t *obj)
Free and sli4_object_t.
Definition: elxu_lancer.c:553
unsigned buffer_length
Definition: elxu_sli4.h:135
int sli4_object_read(elxu_device_t *device, const char *objectName, void *buffer, uint32_t bufferLength)
Read data from an object.
Definition: elxu_lancer.c:333
#define OPCODE_COMMON_DELETE_OBJECT
Definition: elxu_sli4.h:103
int sli4_object_write(elxu_device_t *device, const char *objectName, int buffer_offset, void *buffer, uint32_t bufferLength, int eofl)
Write data into an object.
Definition: elxu_lancer.c:429
int mbox_common(elxu_device_t *device, mbox_command_t *mboxcmd, uint32_t mboxcmdLength, void *inbuf, uint32_t inbufLength, void *outbuf, uint32_t outbufLength)
Send a mailbox command.
Definition: elxu_mbox.c:2418
uint32_t device_buffer_descriptor_count
Definition: elxu_sli4.h:598
const char * oft2string(uint32_t oft)
Return a string associated with an object type.
Definition: elxu_lancer.c:513
void * zmalloc(uint32_t len)
Allocates and zeroes memory to be used.
Definition: elxu_common.c:63
#define OFT_DIRECTORY_OBJECT
Definition: elxu_sli4.h:704
#define MAX_OBJECT_READ
void zfree(void *p)
Frees memory that has been allocated.
Definition: elxu_common.c:80
#define MBOX_SLI_CONFIG
Definition: elxu_sli4.h:62
static sli4_object_t * sli4_object_scan_directory(elxu_device_t *device, const char *directory)
Scan an SLI4 object directory returning a list of all objects.
Definition: elxu_lancer.c:67
#define OFT_LINKED_OBJECT
Definition: elxu_sli4.h:705
#define MBOX_ENTRY_LENGTH
Definition: elxu_sli4.h:123
int sli4_object_delete(elxu_device_t *device, const char *objectName)
Deletes an SLI4 object.
Definition: elxu_lancer.c:214
mbox_hbd_t device_buffer_descriptor[1]
Definition: elxu_sli4.h:600
int sli4_object_length(elxu_device_t *device, const char *objectName)
Return an SLI4 object&#39;s length in bytes.
Definition: elxu_lancer.c:271
#define MBOX_SUBSYSTEM_COMMON
Definition: elxu_sli4.h:76
mbox_hbd_t device_buffer_descriptor[0]
Definition: elxu_sli4.h:555
#define OPCODE_COMMON_READ_OBJECT
Definition: elxu_sli4.h:100
#define OPCODE_COMMON_WRITE_OBJECT
Definition: elxu_sli4.h:101
uint32_t device_buffer_descriptor_count
Definition: elxu_sli4.h:553
mbox_hbd_t device_buffer_descriptor[0]
Definition: elxu_sli4.h:679
uint32_t object_directory_name[OBJECT_NAME_LENGTH]
Definition: elxu_sli4.h:675
unsigned command
Definition: elxu_sli4.h:160
#define MALLOC_FAILED
Definition: elxu.h:42
unsigned pcmd_count
Definition: elxu_sli4.h:165
sli4_object_t * sli4_object_enumerate(elxu_device_t *device)
Create a list of all SLI4 objects.
Definition: elxu_lancer.c:53
uint32_t object_base_name[OBJECT_BASE_NAME_LENGTH]
Definition: elxu_sli4.h:710
uint32_t object_name[OBJECT_NAME_LENGTH]
Definition: elxu_sli4.h:730
#define MAX_OBJECT_WRITE
#define OPCODE_COMMON_READ_OBJECT_LIST
Definition: elxu_sli4.h:102
struct sli4_object_s * next
Definition: elxu_lancer.h:39
void sli4_object_free_list(sli4_object_t *head)
Free a list of sli4_object_t&#39;s.
Definition: elxu_lancer.c:570