/* * Copyright (c) 2011-2015, Emulex * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include static sli4_object_t *sli4_object_scan_directory(elxu_device_t *device, const char *directory); const char *oft2string(uint32_t oft); /** * @brief Create a list of all SLI4 objects * * The SLI4 HBA referred to by 'device' is scanned returning a list of all objects * * @param device pointer to device */ sli4_object_t *sli4_object_enumerate(elxu_device_t *device) { return sli4_object_scan_directory (device, "/"); } /** * @brief Scan an SLI4 object directory returning a list of all objects * * The SLI4 object directory 'directory' is scanned recursively. A list of * all objects is returned * * @param device pointer to device * @param directory name of directory */ static sli4_object_t *sli4_object_scan_directory(elxu_device_t *device, const char *directory) { mbox_command_t mqe; mbox_sli_config_t *sli_config; mbox_common_read_object_list_t *mbox; mbox_common_read_object_list_rsp_t *rsp; int rval; uint32_t offset = 0; sli4_object_t *obj; sli4_object_t *head = NULL; sli4_object_t *tail = NULL; int object_count; memset(&mqe, 0, 256); sli_config = (mbox_sli_config_t*)&mqe; mbox = (mbox_common_read_object_list_t*)&(sli_config[1]); rsp = (mbox_common_read_object_list_rsp_t*)mbox; sli_config->command = MBOX_SLI_CONFIG; sli_config->emb = 1; sli_config->pcmd_count = 0; sli_config->payload_length = sizeof (*mbox); mbox->opcode = OPCODE_COMMON_READ_OBJECT_LIST; mbox->sybsystem = MBOX_SUBSYSTEM_COMMON; mbox->timeout = 0; mbox->request_length = sizeof (*mbox) - 4*sizeof (uint32_t); mbox->version = 0; mbox->descriptor_count = 0; mbox->descriptor_offset = 0; /* * Send a request with descriptor_count and descriptor_offset == 0. This will return * a count of the objects in the directory. */ strncpy((char*)mbox->object_directory_name, directory, (sizeof(mbox->object_directory_name) - 1)); rval = mbox_common(device, &mqe, sli_config->payload_length, NULL, 0, NULL, 0); if (rval) { printf ("Error: rval %d\n", rval); return NULL; } if (rsp->status) { return NULL; } /* * Iterate over the objects in this directory */ object_count = rsp->actual_descriptor_count; for (offset = 0; offset < object_count; offset ++) { // Fetch one memset(&mqe, 0, 256); sli_config->command = MBOX_SLI_CONFIG; sli_config->emb = 1; sli_config->pcmd_count = 0; sli_config->payload_length = sizeof (*mbox) + sizeof (mbox_hbd_t); mbox->opcode = OPCODE_COMMON_READ_OBJECT_LIST; mbox->sybsystem = MBOX_SUBSYSTEM_COMMON; mbox->timeout = 0; mbox->version = 0; mbox->descriptor_count = 1; mbox->descriptor_offset = offset; mbox->device_buffer_descriptor_count = 1; mbox->device_buffer_descriptor[0].buffer_length = sizeof (mbox_common_read_object_list_desc_t); mbox->request_length = sizeof (*mbox) - 4*sizeof (uint32_t) + (mbox->device_buffer_descriptor_count*sizeof (mbox_hbd_t)); mbox_common_read_object_list_desc_t desc; strncpy((char*)mbox->object_directory_name, directory, (sizeof(mbox->object_directory_name) - 1)); rval = mbox_common(device, &mqe, 256, NULL, 0, (uint8_t*)&desc, sizeof(desc)); if (rval) { printf ("Error: rval %d\n", rval); break; } if (rsp->actual_descriptor_count == 0 || rsp->actual_response_length == 0) break; char fullPath[128]; snprintf(fullPath, sizeof(fullPath), "%s%s%s", directory, directory[strlen(directory)-1] == '/' ? "" : "/", (char*)desc.object_base_name); obj = sli4_object_new(fullPath, desc.oft, desc.object_info); if (!obj) { break; } if (tail) { tail->next = obj; tail = obj; } else head = tail = obj; if (desc.oft == OFT_DIRECTORY_OBJECT) { if ((strcmp ((char*)desc.object_base_name, ".") == 0) || (strcmp ((char*)desc.object_base_name, "..") == 0)) { continue; } obj = sli4_object_scan_directory(device, fullPath); if (obj) { if (tail) { tail->next = obj; for (tail = obj; tail->next; tail = tail->next) ; } } } } return head; } /** * @brief Deletes an SLI4 object * * Deletes the SLI4 object. * * @param device pointer to device * @param objectName name of object */ int sli4_object_delete (elxu_device_t *device, const char *objectName) { void *mqe = zmalloc(256); mbox_sli_config_t *sli_config; mbox_common_delete_object_t *mbox; mbox_common_delete_object_rsp_t *rsp; int rval; if (!mqe) return MALLOC_FAILED; sli_config = mqe; mbox = (mbox_common_delete_object_t*)(&sli_config[1]); rsp = (mbox_common_delete_object_rsp_t*)mbox; sli_config->command = MBOX_SLI_CONFIG; sli_config->emb = 1; sli_config->pcmd_count = 0; sli_config->payload_length = sizeof (*mbox) + sizeof (mbox_hbd_t); mbox->opcode = OPCODE_COMMON_DELETE_OBJECT; mbox->sybsystem = MBOX_SUBSYSTEM_COMMON; mbox->timeout = 0; mbox->request_length = sizeof (*mbox) - 4*sizeof (uint32_t); mbox->version = 0; strncpy((char*)mbox->object_name, objectName, (sizeof(mbox->object_name) - 1)); rval = mbox_common(device, mqe, sli_config->payload_length, mbox, sizeof(*mbox), rsp, sizeof(*rsp)); if (rval) { printf ("Error: rval %d\n", rval); free(mqe); return -1; } if (rsp->status) { free(mqe); return -rsp->status; } free(mqe); return 0; } /** * @brief Return an SLI4 object's length in bytes * * Returns the length of an SLI4 normal object, or the number of elements in * an SLI4 directory object * * @param device pointer to device * @param objectName name of object */ int sli4_object_length(elxu_device_t *device, const char *objectName) { void *mqe = zmalloc(256); mbox_sli_config_t *sli_config; mbox_common_read_object_t *mbox; mbox_common_read_object_rsp_t *rsp; int rval; uint32_t length = 0; if (!mqe) return MALLOC_FAILED; sli_config = mqe; mbox = (mbox_common_read_object_t*)(&sli_config[1]); rsp = (mbox_common_read_object_rsp_t*)mbox; sli_config->command = MBOX_SLI_CONFIG; sli_config->emb = 1; sli_config->pcmd_count = 0; sli_config->payload_length = sizeof (*mbox) + sizeof (mbox_hbd_t); mbox->opcode = OPCODE_COMMON_READ_OBJECT; mbox->sybsystem = MBOX_SUBSYSTEM_COMMON; mbox->timeout = 0; mbox->request_length = sizeof (*mbox) - 4*sizeof (uint32_t); mbox->version = 0; mbox->desired_read_length = 0; mbox->read_offset = 0; strncpy((char*)mbox->object_name, objectName, sizeof(mbox->object_name)); mbox->device_buffer_descriptor_count = 0; rval = mbox_common(device, mqe, sli_config->payload_length, mbox, sizeof(*mbox), rsp, sizeof(*rsp)); if (rval) { printf ("Error: rval %d\n", rval); free(mqe); return -1; } if (rsp->status) { free(mqe); return -rsp->status; } length = rsp->actual_read_length; free(mqe); return length; } /** * @brief Read data from an object * * The data of an SLI4 data object is read. * * @param device pointer to device * @param objectName name of object to read * @param buffer pointer to data buffer * @param bufferLength byte length of data buffer * * returns the number of bytes read, or a negative value */ int sli4_object_read(elxu_device_t *device, const char *objectName, void *buffer, uint32_t bufferLength) { int rval; uint32_t objectLength; uint32_t offset = 0; uint32_t n; void *mqe = NULL; mbox_sli_config_t *sli_config = NULL; mbox_common_read_object_t *mbox = NULL; mbox_common_read_object_rsp_t *rsp = NULL; mqe = zmalloc(MBOX_ENTRY_LENGTH); if (!mqe) return MALLOC_FAILED; sli_config = mqe; mbox = (mbox_common_read_object_t*)(&sli_config[1]); rsp = (mbox_common_read_object_rsp_t*)mbox; rval = sli4_object_length(device, objectName); if (rval < 0) { zfree (mqe); return rval; } objectLength = (uint32_t) rval; if (bufferLength > objectLength) { bufferLength = objectLength; } while (bufferLength > 0) { n = bufferLength; #define MAX_OBJECT_READ 3840 if (n > MAX_OBJECT_READ) n = MAX_OBJECT_READ; memset(mqe, 0, MBOX_ENTRY_LENGTH); sli_config->command = MBOX_SLI_CONFIG; sli_config->emb = 1; // Embedded, Mbox Cmd data is placed in the 256 MQE sli_config->pcmd_count = 0; sli_config->payload_length = sizeof (*mbox) + sizeof (mbox_hbd_t); mbox->opcode = OPCODE_COMMON_READ_OBJECT; mbox->sybsystem = MBOX_SUBSYSTEM_COMMON; mbox->timeout = 0; mbox->request_length = sizeof (*mbox) - 4*sizeof (uint32_t) + sizeof(mbox_hbd_t); mbox->version = 0; mbox->desired_read_length = n; mbox->read_offset = offset; strncpy((char*)mbox->object_name, objectName, (sizeof(mbox->object_name) - 1)); mbox->device_buffer_descriptor_count = 1; mbox->device_buffer_descriptor[0].buffer_length = n; rval = mbox_common(device, mqe, MBOX_ENTRY_LENGTH, buffer, n, buffer, n); if (rval) { printf ("Error: rval %d\n", rval); zfree(mqe); return -1; } if (rsp->status) { zfree(mqe); return -rsp->status; } offset += n; bufferLength -= n; buffer = (((uint8_t*)buffer) + n); } zfree(mqe); // return amount read return offset; } /** * @brief Write data into an object * * Write the data into an SLI4 data object. * * @param device pointer to device * @param objectName name of object to write * @param buffer pointer to data buffer * @param bufferLength byte length of data buffer * * returns the number of bytes written, or a negative value */ int sli4_object_write (elxu_device_t *device, const char *objectName, int buffer_offset, void *buffer, uint32_t bufferLength, int eofl) { int rval; uint32_t offset = buffer_offset; uint32_t n; void *mqe = NULL; mbox_sli_config_t *sli_config = NULL; mbox_common_write_object_t *mbox = NULL; mbox_common_write_object_rsp_t *rsp = NULL; mqe = zmalloc(MBOX_ENTRY_LENGTH); if (!mqe) return MALLOC_FAILED; sli_config = mqe; mbox = (mbox_common_write_object_t*)(&sli_config[1]); rsp = (mbox_common_write_object_rsp_t*)mbox; while (bufferLength > 0) { n = bufferLength; #define MAX_OBJECT_WRITE 3840 if (n > MAX_OBJECT_WRITE) n = MAX_OBJECT_WRITE; memset(mqe, 0, MBOX_ENTRY_LENGTH); sli_config->command = MBOX_SLI_CONFIG; sli_config->emb = 1; // Embedded, Mbox Cmd data is placed in the 256 MQE sli_config->pcmd_count = 0; sli_config->payload_length = sizeof (*mbox) + sizeof (mbox_hbd_t); mbox->opcode = OPCODE_COMMON_WRITE_OBJECT; mbox->subsystem = MBOX_SUBSYSTEM_COMMON; mbox->timeout = 0; mbox->request_length = sizeof (*mbox) - 4*sizeof (uint32_t) + sizeof(mbox_hbd_t); mbox->version = 0; mbox->desired_write_length = n; if ((bufferLength <= MAX_OBJECT_WRITE) && eofl) mbox->eof = 1; mbox->write_offset = offset; strncpy((char*)mbox->object_name, objectName, (sizeof(mbox->object_name) - 1)); mbox->device_buffer_descriptor_count = 1; mbox->device_buffer_descriptor[0].buffer_length = n; printf ("."); fflush (stdout); rval = mbox_common(device, mqe, MBOX_ENTRY_LENGTH, buffer, n, buffer, n); if (rval) { printf ("Error: rval %d\n", rval); zfree(mqe); return -1; } if (rsp->status) { printf ("\nStatus 0x%X Additional Status 0x%X \n", rsp->status, rsp->additional_status); zfree(mqe); return -rsp->status; } n = rsp->actual_write_length; assert(rsp->actual_write_length - offset >= 0); offset += n; bufferLength -= n; buffer = (((uint8_t*)buffer) + n); } zfree(mqe); // return written ammount return offset; } /** * @brief Return a string associated with an object type * * Returns a string associated with an object type * * @param oft Object type */ const char *oft2string(uint32_t oft) { switch (oft) { case OFT_NORMAL_OBJECT: return "normal"; case OFT_DIRECTORY_OBJECT: return "directory"; case OFT_LINKED_OBJECT: return "link"; } return "unknown"; } /** * @brief Instantiate a new sli4_object_t * * An sli4_object_t is allocated and populated with name, type and length; * * @param name Name of object * @param type Type of object * @param length Length of object */ sli4_object_t *sli4_object_new(const char *name, uint32_t type, uint32_t length) { sli4_object_t *new = zmalloc(sizeof(*new)); if (new) { new->next = NULL; new->name = strdup (name); new->type = type; new->length = length; } return new; } /** * @brief Free and sli4_object_t * * The object given by 'obj' if free'd * * @param obj Object to free */ void sli4_object_free(sli4_object_t *obj) { if (obj) { if (obj->name) free (obj->name); free(obj); } } /** * @brief Free a list of sli4_object_t's * * The elements of list given by 'head' are freed * * @param head head of list */ void sli4_object_free_list(sli4_object_t *head) { sli4_object_t *next; for (; head; head = next) { next = head->next; sli4_object_free(head); } } /** * @page elxsdkutil_lpe1600x.html LPe1600x Adapter APIs * * @section lpe1600x_obj_mgmt Data Object Management API * * The LPe16000/LPe16002 data object management API consists of the functions shown * in the following table. * * * * * * * *
Function NameDescription
sli4_object_enumerate()Create a list of all SLI-4 objects.
sli4_object_length()Return an SLI-4 object's length in bytes.
sli4_object_read()Read data object.
sli4_object_write()Write data object.
* * * @section lpe1600x_obj_groups Data Object Groups * * Within the flash file system of an LPe16000/LPe16002 HBA, directory names are used * to identify the type of object and file names are used to specify the instance of the * object. The object groups (directories) shown in the following table are supported by * LPe16000/LPe16002 HBAs.. * * * * * * * * * *
GroupDescription
/The root directory for all object groups.
/cfgObjects in this group correspond to configuration objects.
/dbgObjects in this group correspond to device debug and * postmortem diagnosis. When a diagnostic dump (dump.bin) file is * retrieved, it is retrieved from the /dbg directory.
/prgObjects in this group correspond to firmware program images. * When an LPe16000/LPe16002 HBA firmware file (.grp) is * downloaded, it is sent to the /prg directory.
/vpdObjects in this group correspond to different VPD images for the * different protocols and function types.
/xromObjects in this group correspond to the expansion ROM images * for the different protocols.
* */