/* * Copyright (c) 2011-2018, 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** * @brief test write permissions for given file * * @param filename File for which write test is performed * */ static int elxu_test_file_write(const char *filename) { FILE *out; out = fopen(filename, "wb"); if (out == NULL) { printf("Error: can't create file: %s\n", filename); return -1; } else fclose(out); return 0; } /** * @brief FAT data upload functionality * * * @param device_p The pointer to the HBA descriptor structure. * @param fname_p The pointer to the file name string. */ static int fat_upload (elxu_device_t *device_p, char const *fname_p) { int fd; uint8_t *buf_p; int retval = 0; int fatLength; /* * Validate arguments */ if (device_p == NULL) { printf("Null pointer\n"); return -1; } if (fname_p == NULL) { fname_p = DEFAULT_OUTPUT_FILE_NAME; } /* test to make sure we can write to outfile before continuing */ if (elxu_test_file_write(fname_p)) { printf ("Failed to open file for writing, file: %s\n", fname_p); return -1; } // Fetch the length of the FAT if ((fatLength = fat_info(device_p)) < 0) { printf ("Fetch FAT info failure \n"); return -1; } if (fatLength == 0) { printf ("FAT fetch - nothing to retrieve\n"); return 0; } printf ("Fat length is %d bytes\n", fatLength); /* * Allocate space to retrieve the file headers. */ if ((buf_p = zmalloc(fatLength)) == NULL) { printf("Malloc failure - (%s)\n", strerror(errno)); return MALLOC_FAILED; } // Read FAT if ((retval = fat_read(device_p, buf_p, fatLength)) < 0) { printf ("FAT read Failed with error code: %d\n", retval); } else { /* * Open file */ if ((fd = open(fname_p, O_CREAT | O_WRONLY, 0644)) < 0) { zfree(buf_p); return -1; } if (write(fd, buf_p, fatLength) < 0) { printf("write file failure, (%s)\n", strerror(errno)); retval = -1; } close(fd); } zfree(buf_p); return retval; } void elxu_driver_dump(elxu_device_t *device, int bufsize, ocs_ioctl_ddump_arg_t *args) { char *buf; ocs_ioctl_ddump_t req; int rval; if (bufsize <= 0) { fprintf(stderr, "Invalid bufsize: %d\n", bufsize); return; } buf = malloc(bufsize+1); if (buf == NULL) { fprintf(stderr, "Unable to allocate buffer of %d KBytes\n", bufsize/1024); return; } memset(&req, 0, sizeof(req)); req.args = *args; req.user_buffer = (uint8_t *)buf; req.user_buffer_len = bufsize; rval = elxu_ioctl_device(device, OCS_IOCTL_CMD_GET_DDUMP, &req); if (rval < 0) { perror("ioctl"); } else { switch (args->action) { case OCS_IOCTL_DDUMP_GET: case OCS_IOCTL_DDUMP_GET_SAVED: if (req.bytes_written) { buf[req.bytes_written] = '\0'; printf("%s\n", buf); } else { printf("No driver-dump data returned\n"); } break; case OCS_IOCTL_DDUMP_CLR_SAVED: break; } } free(buf); } /** * @brief FAT data upload functionality * * * @param device_p The pointer to the HBA descriptor structure. * @param fname_p The pointer to the file name string. */ int ext_fat_read_string_table_upld (elxu_device_t *device_p, char const *fname_p) { uint32_t tbl_info_len; mbox_ext_fat_read_string_params_t *tblinfo; uint32_t remaining_bytes = 0; uint32_t read_bytes = 0; uint32_t tbl_data_block_size = 2*1024; int fd; int fd1; const char *filename = "efdstr.data"; tbl_info_len = sizeof (mbox_ext_fat_read_string_params_t) + tbl_data_block_size; if ((tblinfo = malloc (tbl_info_len)) == NULL) { printf("Malloc failure - (%s)\n", strerror(errno)); return MALLOC_FAILED; } if (fname_p == NULL) { fname_p = filename; } printf ("Filename :%s \n", fname_p); /* * Open file */ if ((fd = open(fname_p, O_CREAT | O_WRONLY, 0644)) < 0) { printf("open file failure, (%s)\n", strerror(errno)); zfree(tblinfo); return -1; } /* * Open file */ if ((fd1 = open("strTbl", O_CREAT | O_WRONLY, 0644)) < 0) { printf("open file failure, (%s)\n", strerror(errno)); goto error_Cleanup; } do { memset (tblinfo, 0, tbl_info_len); if (ext_fat_read_string_table (device_p, tblinfo, tbl_info_len, tbl_data_block_size, read_bytes) < 0) { printf ("Reading string table failed\n"); goto error_Cleanup_fd1; } if (write(fd, tblinfo->table_data, tblinfo->num_returned_bytes) < 0) { printf("write file failure, (%s)\n", strerror(errno)); goto error_Cleanup_fd1; } if (write(fd1, tblinfo->table_data, tblinfo->num_returned_bytes) < 0) { printf("write file failure, (%s)\n", strerror(errno)); goto error_Cleanup_fd1; } read_bytes+= tblinfo->num_returned_bytes; remaining_bytes = tblinfo->num_remaining_bytes; } while (remaining_bytes); printf ("String table was read successfully : %d Bytes \n", read_bytes); zfree(tblinfo); close (fd); close (fd1); return 0; error_Cleanup_fd1: close(fd1); error_Cleanup: close(fd); zfree(tblinfo); return -1; } /** * @brief Displays EXT FAT capabilities * * @param device_p The pointer to the HBA descriptor structure. */ int ext_fat_capabilities_upld (elxu_device_t *device_p) { uint32_t bufferLength = 3*1024+256; ext_fat_config_params_t *config; int rval, i, j; if ((config = zmalloc(bufferLength)) == NULL) { printf("Malloc failure - (%s)\n", strerror(errno)); return MALLOC_FAILED; } rval = get_ext_fat_capabilities(device_p, EXT_FAT_PARAM_TYPE_DEFAULT, config, bufferLength); if (rval) { printf ("Error: rval %d\n", rval); zfree(config); return -1; } else { ext_fat_module_t *module; ext_fat_mode_t *mode; printf("max_log_entries %d\n", config->max_log_entries); printf("log_entry_size %d\n", config->log_entry_size); printf("logging_type %d\n", config->logging_type); printf("max_logging_functions %d\n", config->max_logging_functions); printf("max logging port %d\n", config->max_logging_ports); printf("supported_modes %s%s%s%s\n", config->supported_modes & LOG_MODE_UART_MASK ? "uart " : "", config->supported_modes & LOG_MODE_RAM_MASK ? "ram " : "", config->supported_modes & LOG_MODE_NVRAM_MASK ? "nvram " : "", config->supported_modes & LOG_MODE_NWTK_MASK ? "nwtk " : ""); printf("num_modules %d\n", config->num_modules); module = config->debug_module; for (i = 0; i < config->num_modules; i ++) { printf("[%d]\t%-16s\tmodule_id %d\tnum_modes %d\n", i, module->module_str, module->module_id, module->num_modes); mode = module->mode_trace_level; if (module->num_modes > 16) { printf("Error: suspected invalid num_modes - terminating dump\n"); break; } for (j = 0; j < module->num_modes; j ++, mode ++) { printf (" [%d] mode %d port_mask %04X trace_level %08X function_mask %016llX\n", j, mode->mode, mode->port_mask, mode->trace_level, (long long unsigned int) mode->function_mask); } module = (ext_fat_module_t*)mode; } } zfree(config); return 0; } /** * @brief EXT FAT data upload functionality * * * @param device_p The pointer to the HBA descriptor structure. * @param fname_p The pointer to the file name string. */ static int ext_fat_snapshot_upload (elxu_device_t *device_p, char const *fname_p) { int len; uint8_t *buf_p; if ((len = ext_fat_config_snapshot(device_p)) < 0) { printf ("Error executing EFD config snapshot mailbox cmd.\n"); } else { printf ("EFD Snapshot size is %d logs\n", len); if ((buf_p = (uint8_t *) malloc (len*sizeof(arm_trace_record_t))) == NULL) { printf("Malloc failure - (%s)\n", strerror(errno)); return -1; } printf ("Retrieve EFD snapshot \n"); if (ext_fat_retrieve_snapshot (device_p, buf_p, len*sizeof(arm_trace_record_t), len) < 0) { printf ("Retrieve failed\n"); } else { int fd; const char *filename = "efd.data"; if (fname_p == NULL) { fname_p = filename; } /* * Open file */ if ((fd = open(fname_p, O_WRONLY| O_APPEND |O_CREAT, 0644)) < 0) { printf("open file failure, (%s)\n", strerror(errno)); zfree(buf_p); return -1; } if (write(fd, buf_p, (len*sizeof(arm_trace_record_t))) < 0) \ { printf("write file failure, (%s)\n", strerror(errno)); } printf ("EFD snapshot was retrieved successfully \n"); close(fd); } zfree (buf_p); } return 0; } /** * @brief EXT FAT data upload functionality * * * @param device_p The pointer to the HBA descriptor structure. * @param fname_p The pointer to the file name string. */ static int ext_fat_generate_efd_file (elxu_device_t *device_p, char const *fname_p) { const char *filename = "data.efd"; if (fname_p == NULL) { printf ("Using generic file name - %s\n", filename); fname_p = filename; } /* test to make sure we can write to outfile before continuing */ if (elxu_test_file_write(fname_p)) { printf ("Failed to open file for writing, file: %s\n", fname_p); return -1; } if (ext_fat_read_string_table_upld (device_p,fname_p) < 0) { printf ("EFD String table retrieval failed \n"); return (-1); } if (ext_fat_snapshot_upload (device_p, fname_p) < 0) { printf ("EFD Snapshot retrieval failed \n"); return -1; } return 0; } /** * @brief Lancer dump data upload functionality * * * @param device_p The pointer to the HBA descriptor structure. * @param fname_p The pointer to the file name string. */ static int lancer_hba_dump_upload(elxu_device_t *device_p, char const *fname_p) { const char *ofname = "dump.bin"; const char *objectName = "/dbg/dump.bin"; int rval = -1; FILE *out; if (fname_p != NULL) { ofname = fname_p; } /* test to make sure we can write to outfile before continuing */ if (elxu_test_file_write(ofname)) { printf ("Failed to open file for writing, file: %s\n", ofname); return -1; } rval = sli4_object_length(device_p, objectName); if (rval < 0) { printf("Error: sli4_object_length(%s) returned %d\n", objectName, rval); return -1; } uint32_t objectLength = rval; printf ("Length of object %s is %d\n", objectName, objectLength); if (objectLength == 0) { printf("Length of object %s is zero, nothing to read\n", objectName); return 0; } void *buffer = malloc(objectLength); if (!buffer) { printf("Malloc failure - (%s)\n", strerror(errno)); return MALLOC_FAILED; } rval = sli4_object_read(device_p, objectName, buffer, objectLength); if (rval < 0) { printf("Error: sli4_object_read(%s) failed: %d\n", objectName, rval); return -1; } out = fopen(ofname, "wb"); if (out) { size_t written = 0; written = fwrite(buffer, objectLength, 1, out); fclose(out); printf ("File %s created\n", ofname); if (written) { // only delete file if write was successful if (sli4_object_delete (device_p, objectName) < 0) { printf ("Failed to delete object %s from SLI device\n", objectName); rval = -1; } else { printf ("Object %s was deleted from SLI device\n", objectName); rval = 0; } } else { printf("Failed to write to file: %s\n", ofname); rval = -1; } } else { printf("Failed to write to file: %s\n", ofname); rval = -1; } zfree (buffer); return (rval); } int hba_data_object_upload (elxu_device_t *device_p, char const *objname_p, char const *fname_p) { const char *ofname = "object.bin"; const char *objectName = objname_p; int rval = -1; FILE *out; if (fname_p != NULL) { ofname = fname_p; } /* test to make sure we can write to outfile before continuing */ if (elxu_test_file_write(ofname)) { printf ("Failed to open file for writing, file: %s\n", ofname); return -1; } printf ("object name : %s \n", objname_p); rval = sli4_object_length(device_p, objectName); if (rval < 0) { printf("Error: sli4_object_length(%s) returned %d\n", objectName, rval); return -1; } uint32_t objectLength = rval; printf ("Length of object is %d\n", objectLength); void *buffer = malloc(objectLength); if (!buffer) { printf("Malloc failure - (%s)\n", strerror(errno)); return MALLOC_FAILED; } rval = sli4_object_read(device_p, objectName, buffer, objectLength); if (rval < 0) { printf("Error: sli4_object_read(%s) failed: %d\n", objectName, rval); zfree (buffer); return -1; } printf("rval %d\n", rval); out = fopen(ofname, "wb"); if (out) { fwrite(buffer, objectLength, 1, out); fclose(out); printf ("File %s created\n", ofname); } zfree (buffer); return (rval); } /** * @brief Trigger dump generation on Lancer * * The functionality to generate a dump on Lancer. * * @param device_p The pointer to the HBA descriptor structure. */ int lancer_gen_dump(elxu_device_t *device_p, int fdb_dump) { int rc; printf("Generating dump..\n"); if (fdb_dump) { rc = elxu_device_exec(device_p, "/ocs/driver/fdb_gendump", NULL, 0, NULL, 0); } else { rc = elxu_device_exec(device_p, "/ocs/driver/gendump", NULL, 0, NULL, 0); } if (rc == 0) { printf("Dump successfully generated and can now be read from SLI device\n"); } else { printf("Dump generation failed.\n"); } return rc; } /** * @brief Trigger dump-to-host on Lancer * * This function uses Lancer's dump-to-host capability to cause * a dump to be generated and to transfer that dump into host * memory. The transfered dump is stored in a file. * * @param device_p The pointer to the HBA descriptor structure. */ int lancer_dump_to_host(elxu_device_t *device_p, const char *fname, int fdb_dump) { int rc; uint8_t *dump_buffer; const char *ofname = "dump.bin"; FILE *out; uint32_t actual_size; uint8_t *response_bytes; uint32_t max_dump_size = 0; if (fname != NULL) { ofname = fname; } /* test to make sure we can write to outfile before continuing */ if (elxu_test_file_write(ofname)) { printf ("Failed to open file for writing, file: %s\n", ofname); return -1; } max_dump_size = strtoul(elxu_device_get_value(device_p, "/ocs/fw_dump_max_size"), NULL, 0); if (!max_dump_size) { printf("Unable to determine the size of dump \n"); return -1; } dump_buffer = malloc(max_dump_size); if (dump_buffer == NULL) { perror("malloc"); return -1; } printf("Starting dump...\n"); if (fdb_dump) { rc = elxu_device_exec(device_p, "/ocs/driver/fdb_dump_to_host", NULL, 0, dump_buffer, max_dump_size); } else { rc = elxu_device_exec(device_p, "/ocs/driver/dump_to_host", NULL, 0, dump_buffer, max_dump_size); } if (rc != 0) { perror("ioctl"); printf("Dump generation failed.\n"); free(dump_buffer); return -1; } /* The first 32 bits of the dump contain the actual length but we need to change the endianess */ response_bytes = dump_buffer; actual_size = (response_bytes[0] << 24) | (response_bytes[1] << 16) | (response_bytes[2] << 8) | (response_bytes[3]); if (actual_size > max_dump_size) { printf("Reported dump size is higher than max allowed dump size (%d). Dump may have been truncated\n", max_dump_size); actual_size = max_dump_size; } out = fopen(ofname, "wb"); if (out) { size_t written = 0; written = fwrite(dump_buffer, actual_size, 1, out); fclose(out); printf ("File %s created\n", ofname); if (dump_buffer == NULL) printf("Dump buffer is NULL\n"); if (!written) { printf("Failed to write to file: %s\n", ofname); } else { printf("Dump written to file %s\n", ofname); } } zfree (dump_buffer); return rc; } static size_t ocs_write_buffer_to_file(const char *ofname, void *src_buffer, size_t byte_count) { FILE *fp; size_t written = 0; fp = fopen(ofname, "wb"); if (fp) { written = fwrite(src_buffer, byte_count, 1, fp); fclose(fp); } return written; } /** * @brief gather firmware diagnostic logs * * The functionality to extract firmware diagnostic logs to a file * * @param device_p Pointer to HBA descriptor structure. * @param fname Output file name. */ int elxu_get_fw_diagnostic_log(elxu_device_t *device_p, char const *fname) { #define OCS_FW_DIAG_LOG_SIZE_MAX (1*1024*1024) // 1MB #define MAX_FW_LOG_BUFFER_SIZE (16*1024*1024) // 16MB uint8_t *diag_log_buffer; size_t buffer_size; uint32_t bytes_copied = 0; int rc = 0; /* Account for 32-bit header to get notified of the exact number of bytes * copied by driver to application buffer. */ buffer_size = MAX_FW_LOG_BUFFER_SIZE + sizeof(uint32_t); /* test to make sure we can write to outfile before continuing */ if (elxu_test_file_write(fname)) { printf ("Failed to open file, %s for writing\n", fname); return -1; } diag_log_buffer = malloc(buffer_size); if (diag_log_buffer == NULL) { perror("malloc : fw diagnostic log buffer"); return -1; } rc = elxu_device_exec(device_p, "/ocs/driver/fw_diag_log", NULL, 0, diag_log_buffer, buffer_size); if (rc < 0) { printf("FW diagnostic logs copy failed, rc %d.\n", rc); goto release_buffer; } bytes_copied = *((uint32_t *)diag_log_buffer); if (bytes_copied) { /* Copy only driver signals it copied non-zero bytes of data from * fw registered buffer to application buffer. */ ocs_write_buffer_to_file(fname, diag_log_buffer + sizeof(uint32_t), bytes_copied); printf("Wrote %d bytes of firmware diagnostic log to %s\n", bytes_copied, fname); } release_buffer: zfree(diag_log_buffer); return rc; } /** * @brief FAT data upload functionality * * The functionality which is handling the request to retrieve the FAT data * from Skyhawk. * * @param device_p The pointer to the HBA descriptor structure. * @param fname_p The pointer to the file name string. * @param req The request data type. */ int hba_data_upload(elxu_device_t *device_p, char const *fname_p, data_type_req_t req) { int retval = -1; if (is_lancer(device_p) || is_prism(device_p)) { return (lancer_hba_dump_upload (device_p, fname_p)); } else if (is_skyhawk(device_p)) { if (req == FAT_DATA) { retval = fat_upload(device_p, fname_p); } if (req == EFD_DATA) { retval = ext_fat_generate_efd_file (device_p, fname_p); } return retval; } else { printf ("Unknown HBA \n"); return -1; } return 0; } /** * @brief Core Dump functionality * * Handle the request to retrieve the core dump from Skyhawk. * * @param device_p The pointer to the HBA descriptor structure. * @param fname_p file name of file to to which dump is written * */ int elxu_core_dump( elxu_device_t *device_p, char *fname_p, int test_dump) { int rc; uint8_t *buffer; uint32_t bufferLength = ECD_MIN_BUFFER_SIZE; char *sky_template_ecdargs[] = {"dead", "skytemplate"}; char *test_template_ecdargs[] = {"dead", "testtemplate"}; char **ecdargs; uint32_t ecdargs_count = ARRAY_SIZE(sky_template_ecdargs); struct utsname utsname; ecd_fwState_t fwState = ECD_FW_STATE_UE; ecd_get_params_t params; int major; int minor; int release; if (fname_p == NULL) { fname_p = "dump.core"; } /* test to make sure we can write to outfile before continuing */ if (elxu_test_file_write(fname_p)) { printf ("Failed to open file for writing, file: %s\n", fname_p); return -1; } /* Build parameters */ memset(¶ms, 0, sizeof(params)); params.instance = device_p->deviceIndex; if (test_dump) { ecdargs = test_template_ecdargs; ecdargs_count = ARRAY_SIZE(test_template_ecdargs); } else if (is_skyhawk(device_p)) { ecdargs = sky_template_ecdargs; ecdargs_count = ARRAY_SIZE(sky_template_ecdargs); } else { return -1; } /* Using uname() system call fetch required parameter information */ rc = uname(&utsname); if (rc != 0) { strncpy(params.system_name, "unknown", sizeof(params.system_name)); strncpy(params.os_name, "unknown", sizeof(params.os_name)); } else { strncpy(params.os_name, utsname.release, sizeof(params.os_name)); strncpy(params.system_name, utsname.nodename, sizeof(params.system_name)); } params.ioctl_high_version = 1; params.ioctl_low_version = 0; /* Parse out the linux version, pass in 2.6.32 as 26.32 */ sscanf(utsname.release, "%d.%d.%d", &major, &minor, &release); params.os_major = major*10 + minor; params.os_minor = release; /* set SLI_INTF from device structure */ params.sli_intf = elxu_get_sliintf(device_p); params.asic_id = elxu_get_asic_id(device_p); buffer = malloc(bufferLength); if (buffer == NULL) { printf("Error: coredump malloc (%d) failed\n", bufferLength); return -1; } rc = ecd_GetCoreDumpData(device_p, fwState, ¶ms, buffer, bufferLength, ecdargs_count, ecdargs); printf("ecd_GetCoreDumpData returned %d\n", rc); /* A return value >= 0 means that there is data in the buffer */ if ((rc > 0) && (fname_p != NULL)) { FILE *out; uint32_t len = rc; out = fopen(fname_p, "wb"); if (out == NULL) printf("Error: can't create %s\n", fname_p); else { rc = fwrite(buffer, 1, len, out); if (rc != len) printf("Error: fwrite failed: %d\n", rc); fclose(out); } } free(buffer); return 0; } /**************************************************************************************************** * Helper functions for Core Dump * * These helper functions implement an interface to the Emulex OCS driver using the ioctl() interface. * * The customer implementation would replace these with functions that interface to their particular * driver. */ static int enable_helper_trace = 0; #define helper_trace(fmt, ...) \ do { \ if (enable_helper_trace) \ printf(fmt, ##__VA_ARGS__); \ } while(0) void ecd_log(char *fmt, ...) { va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); } void os_assert(char *message, uint32_t Line, char *File) { ecd_log("%s(%d) %s\n", File, Line, message); exit(0); } void os_stall(void *ctx, uint32_t usecTime) { usleep(usecTime); } void os_cfg_read8 (void *ctx, uint32_t offset, uint32_t *pdata) { int32_t rc; elxu_device_t *device = (elxu_device_t *)ctx; if (device->driver == DEVICE_DRIVER_OCS) { ocs_ioctl_ecd_helper_t cmd; helper_trace("%-16s: offset x%x\n", __func__, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = OCS_ECD_HELPER_CFG_READ8; cmd.offset = offset; rc = elxu_ioctl_device(device, OCS_IOCTL_CMD_ECD_HELPER, &cmd); if (rc == 0) *pdata = cmd.data; } else if (device->driver == DEVICE_DRIVER_PT) { elx_pt_ioctl_ecd_helper_t cmd; helper_trace("%-16s: offset x%x\n", __func__, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = ELX_PT_ECD_HELPER_CFG_READ8; cmd.offset = offset; rc = elxu_ioctl_device(device, IOCTL_CMD_ELX_PT_ECD_HELPER, &cmd); if (rc == 0) *pdata = cmd.data; } } void os_cfg_read16(void *ctx, uint32_t offset, uint32_t *pdata) { int32_t rc; elxu_device_t *device = (elxu_device_t *)ctx; if (device->driver == DEVICE_DRIVER_OCS) { ocs_ioctl_ecd_helper_t cmd; helper_trace("%-16s: offset x%x\n", __func__, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = OCS_ECD_HELPER_CFG_READ16; cmd.offset = offset; rc = elxu_ioctl_device(device, OCS_IOCTL_CMD_ECD_HELPER, &cmd); if (rc == 0) *pdata = cmd.data; } else if (device->driver == DEVICE_DRIVER_PT) { elx_pt_ioctl_ecd_helper_t cmd; helper_trace("%-16s: offset x%x\n", __func__, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = ELX_PT_ECD_HELPER_CFG_READ16; cmd.offset = offset; rc = elxu_ioctl_device(device, IOCTL_CMD_ELX_PT_ECD_HELPER, &cmd); if (rc == 0) *pdata = cmd.data; } } void os_cfg_read32(void *ctx, uint32_t offset, uint32_t *pdata) { int32_t rc; elxu_device_t *device = (elxu_device_t *)ctx; if (device->driver == DEVICE_DRIVER_OCS) { ocs_ioctl_ecd_helper_t cmd; helper_trace("%-16s: offset x%x\n", __func__, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = OCS_ECD_HELPER_CFG_READ32; cmd.offset = offset; rc = elxu_ioctl_device(device, OCS_IOCTL_CMD_ECD_HELPER, &cmd); if (rc == 0) { *pdata = cmd.data; } } else if (device->driver == DEVICE_DRIVER_PT) { elx_pt_ioctl_ecd_helper_t cmd; memset(&cmd, 0, sizeof(cmd)); cmd.cmd = ELX_PT_ECD_HELPER_CFG_READ32; cmd.offset = offset; rc = elxu_ioctl_device(device, IOCTL_CMD_ELX_PT_ECD_HELPER, &cmd); if (rc == 0) { *pdata = cmd.data; } } } void os_cfg_write8 (void *ctx, uint32_t offset, uint32_t data) { elxu_device_t *device = (elxu_device_t *)ctx; if (device->driver == DEVICE_DRIVER_OCS) { ocs_ioctl_ecd_helper_t cmd; helper_trace("%-16s: offset x%x\n", __func__, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = OCS_ECD_HELPER_CFG_WRITE8; cmd.offset = offset; cmd.data = data; elxu_ioctl_device(device, OCS_IOCTL_CMD_ECD_HELPER, &cmd); } else if (device->driver == DEVICE_DRIVER_PT) { elx_pt_ioctl_ecd_helper_t cmd; helper_trace("%-16s: offset x%x\n", __func__, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = ELX_PT_ECD_HELPER_CFG_WRITE8; cmd.offset = offset; cmd.data = data; elxu_ioctl_device(device, IOCTL_CMD_ELX_PT_ECD_HELPER, &cmd); } } void os_cfg_write16(void *ctx, uint32_t offset, uint32_t data) { elxu_device_t *device = (elxu_device_t *)ctx; if (device->driver == DEVICE_DRIVER_OCS) { ocs_ioctl_ecd_helper_t cmd; helper_trace("%-16s: offset x%x\n", __func__, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = OCS_ECD_HELPER_CFG_WRITE16; cmd.offset = offset; cmd.data = data; elxu_ioctl_device(device, OCS_IOCTL_CMD_ECD_HELPER, &cmd); } else if (device->driver == DEVICE_DRIVER_PT) { elx_pt_ioctl_ecd_helper_t cmd; helper_trace("%-16s: offset x%x\n", __func__, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = ELX_PT_ECD_HELPER_CFG_WRITE16; cmd.offset = offset; cmd.data = data; elxu_ioctl_device(device, IOCTL_CMD_ELX_PT_ECD_HELPER, &cmd); } } void os_cfg_write32(void *ctx, uint32_t offset, uint32_t data) { elxu_device_t *device = (elxu_device_t *)ctx; if (device->driver == DEVICE_DRIVER_OCS) { ocs_ioctl_ecd_helper_t cmd; helper_trace("%-16s: offset x%x\n", __func__, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = OCS_ECD_HELPER_CFG_WRITE16; cmd.offset = offset; cmd.data = data; elxu_ioctl_device(device, OCS_IOCTL_CMD_ECD_HELPER, &cmd); } else { elx_pt_ioctl_ecd_helper_t cmd; helper_trace("%-16s: offset x%x\n", __func__, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = ELX_PT_ECD_HELPER_CFG_WRITE16; cmd.offset = offset; cmd.data = data; elxu_ioctl_device(device, IOCTL_CMD_ELX_PT_ECD_HELPER, &cmd); } } void os_bar_read8 (void *ctx, uint32_t bar, uint32_t offset, uint32_t *pdata) { int32_t rc; elxu_device_t *device = (elxu_device_t *)ctx; if (device->driver == DEVICE_DRIVER_OCS) { ocs_ioctl_ecd_helper_t cmd; helper_trace("%-16s: bar %d offset x%x\n", __func__, bar, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = OCS_ECD_HELPER_BAR_READ8; cmd.bar = bar; cmd.offset = offset; rc = elxu_ioctl_device(device, OCS_IOCTL_CMD_ECD_HELPER, &cmd); if (rc == 0) *pdata = cmd.data; } else if (device->driver == DEVICE_DRIVER_PT) { elx_pt_ioctl_ecd_helper_t cmd; helper_trace("%-16s: bar %d offset x%x\n", __func__, bar, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = ELX_PT_ECD_HELPER_BAR_READ8; cmd.bar = bar; cmd.offset = offset; rc = elxu_ioctl_device(device, IOCTL_CMD_ELX_PT_ECD_HELPER, &cmd); if (rc == 0) *pdata = cmd.data; } } void os_bar_read16(void *ctx, uint32_t bar, uint32_t offset, uint32_t *pdata) { int32_t rc; elxu_device_t *device = (elxu_device_t *)ctx; if (device->driver == DEVICE_DRIVER_OCS) { ocs_ioctl_ecd_helper_t cmd; helper_trace("%-16s: bar %d offset x%x\n", __func__, bar, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = OCS_ECD_HELPER_BAR_READ16; cmd.bar = bar; cmd.offset = offset; rc = elxu_ioctl_device(device, OCS_IOCTL_CMD_ECD_HELPER, &cmd); if (rc == 0) *pdata = cmd.data; } else if (device->driver == DEVICE_DRIVER_PT) { elx_pt_ioctl_ecd_helper_t cmd; helper_trace("%-16s: bar %d offset x%x\n", __func__, bar, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = ELX_PT_ECD_HELPER_BAR_READ16; cmd.bar = bar; cmd.offset = offset; rc = elxu_ioctl_device(device, IOCTL_CMD_ELX_PT_ECD_HELPER, &cmd); if (rc == 0) *pdata = cmd.data; } } void os_bar_read32(void *ctx, uint32_t bar, uint32_t offset, uint32_t *pdata) { int32_t rc; elxu_device_t *device = (elxu_device_t *)ctx; if (device->driver == DEVICE_DRIVER_OCS) { ocs_ioctl_ecd_helper_t cmd; helper_trace("%-16s: bar %d offset x%x\n", __func__, bar, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = OCS_ECD_HELPER_BAR_READ32; cmd.bar = bar; cmd.offset = offset; rc = elxu_ioctl_device(device, OCS_IOCTL_CMD_ECD_HELPER, &cmd); if (rc == 0) *pdata = cmd.data; } else if (device->driver == DEVICE_DRIVER_PT) { elx_pt_ioctl_ecd_helper_t cmd; helper_trace("%-16s: bar %d offset x%x\n", __func__, bar, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = ELX_PT_ECD_HELPER_BAR_READ32; cmd.bar = bar; cmd.offset = offset; rc = elxu_ioctl_device(device, IOCTL_CMD_ELX_PT_ECD_HELPER, &cmd); if (rc == 0) *pdata = cmd.data; } } void os_bar_write8 (void *ctx, uint32_t bar, uint32_t offset, uint32_t data) { elxu_device_t *device = (elxu_device_t *)ctx; if (device->driver == DEVICE_DRIVER_OCS) { ocs_ioctl_ecd_helper_t cmd; helper_trace("%-16s: bar %d offset x%x\n", __func__, bar, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = OCS_ECD_HELPER_BAR_WRITE8; cmd.bar = bar; cmd.offset = offset; cmd.data = data; elxu_ioctl_device(device, OCS_IOCTL_CMD_ECD_HELPER, &cmd); } else if (device->driver == DEVICE_DRIVER_PT) { elx_pt_ioctl_ecd_helper_t cmd; helper_trace("%-16s: bar %d offset x%x\n", __func__, bar, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = ELX_PT_ECD_HELPER_BAR_WRITE8; cmd.bar = bar; cmd.offset = offset; cmd.data = data; elxu_ioctl_device(device, IOCTL_CMD_ELX_PT_ECD_HELPER, &cmd); } } void os_bar_write16(void *ctx, uint32_t bar, uint32_t offset, uint32_t data) { elxu_device_t *device = (elxu_device_t *)ctx; if (device->driver == DEVICE_DRIVER_OCS) { ocs_ioctl_ecd_helper_t cmd; helper_trace("%-16s: bar %d offset x%x\n", __func__, bar, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = OCS_ECD_HELPER_BAR_WRITE16; cmd.bar = bar; cmd.offset = offset; cmd.data = data; elxu_ioctl_device(device, OCS_IOCTL_CMD_ECD_HELPER, &cmd); } else if (device->driver == DEVICE_DRIVER_PT) { elx_pt_ioctl_ecd_helper_t cmd; helper_trace("%-16s: bar %d offset x%x\n", __func__, bar, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = ELX_PT_ECD_HELPER_BAR_WRITE16; cmd.bar = bar; cmd.offset = offset; cmd.data = data; elxu_ioctl_device(device, IOCTL_CMD_ELX_PT_ECD_HELPER, &cmd); } } void os_bar_write32(void *ctx, uint32_t bar, uint32_t offset, uint32_t data) { elxu_device_t *device = (elxu_device_t *)ctx; if (device->driver == DEVICE_DRIVER_OCS) { ocs_ioctl_ecd_helper_t cmd; helper_trace("%-16s: bar %d offset x%x\n", __func__, bar, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = OCS_ECD_HELPER_BAR_WRITE32; cmd.bar = bar; cmd.offset = offset; cmd.data = data; elxu_ioctl_device(device, OCS_IOCTL_CMD_ECD_HELPER, &cmd); helper_trace("%-16s: done\n", __func__); } else { elx_pt_ioctl_ecd_helper_t cmd; helper_trace("%-16s: bar %d offset x%x\n", __func__, bar, offset); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = ELX_PT_ECD_HELPER_BAR_WRITE32; cmd.bar = bar; cmd.offset = offset; cmd.data = data; elxu_ioctl_device(device, IOCTL_CMD_ELX_PT_ECD_HELPER, &cmd); } } void *os_malloc(void *ctx, uint32_t size) { return malloc(size); } void os_free(void *ctx, void *ptr) { return free(ptr); }