/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * Copyright (c) 2002-2006 Neterion, Inc. */ #include "xgehal-mgmt.h" #include "xgehal-driver.h" #include "xgehal-device.h" /** * xge_hal_mgmt_about - Retrieve about info. * @devh: HAL device handle. * @about_info: Filled in by HAL. See xge_hal_mgmt_about_info_t{}. * @size: Size of the @about_info buffer. HAL will return error if the * size is smaller than sizeof(xge_hal_mgmt_about_info_t). * * Retrieve information such as PCI device and vendor IDs, board * revision number, HAL version number, etc. * * Returns: XGE_HAL_OK - success; * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. * XGE_HAL_FAIL - Failed to retrieve the information. * * See also: xge_hal_mgmt_about_info_t{}. */ xge_hal_status_e xge_hal_mgmt_about(xge_hal_device_h devh, xge_hal_mgmt_about_info_t *about_info, int size) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { return XGE_HAL_ERR_INVALID_DEVICE; } if (size != sizeof(xge_hal_mgmt_about_info_t)) { return XGE_HAL_ERR_VERSION_CONFLICT; } xge_os_pci_read16(hldev->pdev, hldev->cfgh, xge_offsetof(xge_hal_pci_config_le_t, vendor_id), &about_info->vendor); xge_os_pci_read16(hldev->pdev, hldev->cfgh, xge_offsetof(xge_hal_pci_config_le_t, device_id), &about_info->device); xge_os_pci_read16(hldev->pdev, hldev->cfgh, xge_offsetof(xge_hal_pci_config_le_t, subsystem_vendor_id), &about_info->subsys_vendor); xge_os_pci_read16(hldev->pdev, hldev->cfgh, xge_offsetof(xge_hal_pci_config_le_t, subsystem_id), &about_info->subsys_device); xge_os_pci_read8(hldev->pdev, hldev->cfgh, xge_offsetof(xge_hal_pci_config_le_t, revision), &about_info->board_rev); xge_os_strlcpy(about_info->vendor_name, XGE_DRIVER_VENDOR, sizeof(about_info->vendor_name)); xge_os_strlcpy(about_info->chip_name, XGE_CHIP_FAMILY, sizeof(about_info->chip_name)); xge_os_strlcpy(about_info->media, XGE_SUPPORTED_MEDIA_0, sizeof(about_info->media)); xge_os_strlcpy(about_info->hal_major, XGE_HAL_VERSION_MAJOR, sizeof(about_info->hal_major)); xge_os_strlcpy(about_info->hal_minor, XGE_HAL_VERSION_MINOR, sizeof(about_info->hal_minor)); xge_os_strlcpy(about_info->hal_fix, XGE_HAL_VERSION_FIX, sizeof(about_info->hal_fix)); xge_os_strlcpy(about_info->hal_build, XGE_HAL_VERSION_BUILD, sizeof(about_info->hal_build)); xge_os_strlcpy(about_info->ll_major, XGELL_VERSION_MAJOR, sizeof(about_info->ll_major)); xge_os_strlcpy(about_info->ll_minor, XGELL_VERSION_MINOR, sizeof(about_info->ll_minor)); xge_os_strlcpy(about_info->ll_fix, XGELL_VERSION_FIX, sizeof(about_info->ll_fix)); xge_os_strlcpy(about_info->ll_build, XGELL_VERSION_BUILD, sizeof(about_info->ll_build)); about_info->transponder_temperature = xge_hal_read_xfp_current_temp(devh); return XGE_HAL_OK; } /** * xge_hal_mgmt_reg_read - Read Xframe register. * @devh: HAL device handle. * @bar_id: 0 - for BAR0, 1- for BAR1. * @offset: Register offset in the Base Address Register (BAR) space. * @value: Register value. Returned by HAL. * Read Xframe register. * * Returns: XGE_HAL_OK - success. * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. * XGE_HAL_ERR_INVALID_OFFSET - Register offset in the BAR space is not * valid. * XGE_HAL_ERR_INVALID_BAR_ID - BAR id is not valid. * * See also: xge_hal_aux_bar0_read(), xge_hal_aux_bar1_read(). */ xge_hal_status_e xge_hal_mgmt_reg_read(xge_hal_device_h devh, int bar_id, unsigned int offset, u64 *value) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { return XGE_HAL_ERR_INVALID_DEVICE; } if (bar_id == 0) { if (offset > sizeof(xge_hal_pci_bar0_t)-8) { return XGE_HAL_ERR_INVALID_OFFSET; } *value = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, (void *)(hldev->bar0 + offset)); } else if (bar_id == 1 && (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA || xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)) { int i; for (i=0; ipdev, hldev->regh1, (void *)(hldev->bar1 + offset)); } else if (bar_id == 1) { /* FIXME: check TITAN BAR1 offsets */ return XGE_HAL_ERR_INVALID_DEVICE; } else { return XGE_HAL_ERR_INVALID_BAR_ID; } return XGE_HAL_OK; } /** * xge_hal_mgmt_reg_write - Write Xframe register. * @devh: HAL device handle. * @bar_id: 0 - for BAR0, 1- for BAR1. * @offset: Register offset in the Base Address Register (BAR) space. * @value: Register value. * * Write Xframe register. * * Returns: XGE_HAL_OK - success. * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. * XGE_HAL_ERR_INVALID_OFFSET - Register offset in the BAR space is not * valid. * XGE_HAL_ERR_INVALID_BAR_ID - BAR id is not valid. * * See also: xge_hal_aux_bar0_write(). */ xge_hal_status_e xge_hal_mgmt_reg_write(xge_hal_device_h devh, int bar_id, unsigned int offset, u64 value) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { return XGE_HAL_ERR_INVALID_DEVICE; } if (bar_id == 0) { if (offset > sizeof(xge_hal_pci_bar0_t)-8) { return XGE_HAL_ERR_INVALID_OFFSET; } xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, value, (void *)(hldev->bar0 + offset)); } else if (bar_id == 1 && (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA || xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC)) { int i; for (i=0; ipdev, hldev->regh1, value, (void *)(hldev->bar1 + offset)); } else if (bar_id == 1) { /* FIXME: check TITAN BAR1 offsets */ return XGE_HAL_ERR_INVALID_DEVICE; } else { return XGE_HAL_ERR_INVALID_BAR_ID; } return XGE_HAL_OK; } /** * xge_hal_mgmt_hw_stats - Get Xframe hardware statistics. * @devh: HAL device handle. * @hw_stats: Hardware statistics. Returned by HAL. * See xge_hal_stats_hw_info_t{}. * @size: Size of the @hw_stats buffer. HAL will return an error * if the size is smaller than sizeof(xge_hal_stats_hw_info_t). * Get Xframe hardware statistics. * * Returns: XGE_HAL_OK - success. * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. * * See also: xge_hal_mgmt_sw_stats(). */ xge_hal_status_e xge_hal_mgmt_hw_stats(xge_hal_device_h devh, xge_hal_mgmt_hw_stats_t *hw_stats, int size) { xge_hal_status_e status; xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_stats_hw_info_t *hw_info; xge_assert(xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN); if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { return XGE_HAL_ERR_INVALID_DEVICE; } if (size != sizeof(xge_hal_stats_hw_info_t)) { return XGE_HAL_ERR_VERSION_CONFLICT; } if ((status = xge_hal_stats_hw (devh, &hw_info)) != XGE_HAL_OK) { return status; } xge_os_memcpy(hw_stats, hw_info, sizeof(xge_hal_stats_hw_info_t)); return XGE_HAL_OK; } /** * xge_hal_mgmt_hw_stats_off - TBD. * @devh: HAL device handle. * @off: TBD * @size: TBD * @out: TBD * * Returns: XGE_HAL_OK - success. * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. * * See also: xge_hal_mgmt_sw_stats(). */ xge_hal_status_e xge_hal_mgmt_hw_stats_off(xge_hal_device_h devh, int off, int size, char *out) { xge_hal_status_e status; xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_stats_hw_info_t *hw_info; xge_assert(xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN); if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { return XGE_HAL_ERR_INVALID_DEVICE; } if (off > sizeof(xge_hal_stats_hw_info_t)-4 || size > 8) { return XGE_HAL_ERR_INVALID_OFFSET; } if ((status = xge_hal_stats_hw (devh, &hw_info)) != XGE_HAL_OK) { return status; } xge_os_memcpy(out, (char*)hw_info + off, size); return XGE_HAL_OK; } /** * xge_hal_mgmt_pcim_stats - Get Titan hardware statistics. * @devh: HAL device handle. * @pcim_stats: PCIM statistics. Returned by HAL. * See xge_hal_stats_hw_info_t{}. * @size: Size of the @hw_stats buffer. HAL will return an error * if the size is smaller than sizeof(xge_hal_stats_hw_info_t). * Get Xframe hardware statistics. * * Returns: XGE_HAL_OK - success. * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. * * See also: xge_hal_mgmt_sw_stats(). */ xge_hal_status_e xge_hal_mgmt_pcim_stats(xge_hal_device_h devh, xge_hal_mgmt_pcim_stats_t *pcim_stats, int size) { xge_hal_status_e status; xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_stats_pcim_info_t *pcim_info; xge_assert(xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN); if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { return XGE_HAL_ERR_INVALID_DEVICE; } if (size != sizeof(xge_hal_stats_pcim_info_t)) { return XGE_HAL_ERR_VERSION_CONFLICT; } if ((status = xge_hal_stats_pcim (devh, &pcim_info)) != XGE_HAL_OK) { return status; } xge_os_memcpy(pcim_stats, pcim_info, sizeof(xge_hal_stats_pcim_info_t)); return XGE_HAL_OK; } /** * xge_hal_mgmt_pcim_stats_off - TBD. * @devh: HAL device handle. * @off: TBD * @size: TBD * @out: TBD * * Returns: XGE_HAL_OK - success. * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. * * See also: xge_hal_mgmt_sw_stats(). */ xge_hal_status_e xge_hal_mgmt_pcim_stats_off(xge_hal_device_h devh, int off, int size, char *out) { xge_hal_status_e status; xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_stats_pcim_info_t *pcim_info; xge_assert(xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN); if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { return XGE_HAL_ERR_INVALID_DEVICE; } if (off > sizeof(xge_hal_stats_pcim_info_t)-8 || size > 8) { return XGE_HAL_ERR_INVALID_OFFSET; } if ((status = xge_hal_stats_pcim (devh, &pcim_info)) != XGE_HAL_OK) { return status; } xge_os_memcpy(out, (char*)pcim_info + off, size); return XGE_HAL_OK; } /** * xge_hal_mgmt_sw_stats - Get per-device software statistics. * @devh: HAL device handle. * @sw_stats: Hardware statistics. Returned by HAL. * See xge_hal_stats_sw_err_t{}. * @size: Size of the @sw_stats buffer. HAL will return an error * if the size is smaller than sizeof(xge_hal_stats_sw_err_t). * Get device software statistics, including ECC and Parity error * counters, etc. * * Returns: XGE_HAL_OK - success. * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. * * See also: xge_hal_stats_sw_err_t{}, xge_hal_mgmt_hw_stats(). */ xge_hal_status_e xge_hal_mgmt_sw_stats(xge_hal_device_h devh, xge_hal_mgmt_sw_stats_t *sw_stats, int size) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { return XGE_HAL_ERR_INVALID_DEVICE; } if (size != sizeof(xge_hal_stats_sw_err_t)) { return XGE_HAL_ERR_VERSION_CONFLICT; } if (!hldev->stats.is_initialized || !hldev->stats.is_enabled) { return XGE_HAL_INF_STATS_IS_NOT_READY; } /* Updating xpak stats value */ __hal_updt_stats_xpak(hldev); xge_os_memcpy(sw_stats, &hldev->stats.sw_dev_err_stats, sizeof(xge_hal_stats_sw_err_t)); return XGE_HAL_OK; } /** * xge_hal_mgmt_device_stats - Get HAL device statistics. * @devh: HAL device handle. * @device_stats: HAL device "soft" statistics. Maintained by HAL itself. * (as opposed to xge_hal_mgmt_hw_stats() - those are * maintained by the Xframe hardware). * Returned by HAL. * See xge_hal_stats_device_info_t{}. * @size: Size of the @device_stats buffer. HAL will return an error * if the size is smaller than sizeof(xge_hal_stats_device_info_t). * * Get HAL (layer) statistic counters. * Returns: XGE_HAL_OK - success. * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not * currently available. * */ xge_hal_status_e xge_hal_mgmt_device_stats(xge_hal_device_h devh, xge_hal_mgmt_device_stats_t *device_stats, int size) { xge_hal_status_e status; xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_stats_device_info_t *device_info; if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { return XGE_HAL_ERR_INVALID_DEVICE; } if (size != sizeof(xge_hal_stats_device_info_t)) { return XGE_HAL_ERR_VERSION_CONFLICT; } if ((status = xge_hal_stats_device (devh, &device_info)) != XGE_HAL_OK) { return status; } xge_os_memcpy(device_stats, device_info, sizeof(xge_hal_stats_device_info_t)); return XGE_HAL_OK; } /* * __hal_update_ring_bump - Update the ring bump counter for the * particular channel. * @hldev: HAL device handle. * @queue: the queue who's data is to be collected. * @chinfo: pointer to the statistics structure of the given channel. * Usage: See xge_hal_aux_stats_hal_read{} */ static void __hal_update_ring_bump(xge_hal_device_t *hldev, int queue, xge_hal_stats_channel_info_t *chinfo) { xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; u64 rbc = 0; int reg = (queue / 4); void * addr; addr = (reg == 1)? (&bar0->ring_bump_counter2) : (&bar0->ring_bump_counter1); rbc = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, addr); chinfo->ring_bump_cnt = XGE_HAL_RING_BUMP_CNT(queue, rbc); } /** * xge_hal_mgmt_channel_stats - Get HAL channel statistics. * @channelh: HAL channel handle. * @channel_stats: HAL channel statistics. Maintained by HAL itself * (as opposed to xge_hal_mgmt_hw_stats() - those are * maintained by the Xframe hardware). * Returned by HAL. * See xge_hal_stats_channel_info_t{}. * @size: Size of the @channel_stats buffer. HAL will return an error * if the size is smaller than sizeof(xge_hal_mgmt_channel_stats_t). * * Get HAL per-channel statistic counters. * * Returns: XGE_HAL_OK - success. * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not * currently available. * */ xge_hal_status_e xge_hal_mgmt_channel_stats(xge_hal_channel_h channelh, xge_hal_mgmt_channel_stats_t *channel_stats, int size) { xge_hal_status_e status; xge_hal_stats_channel_info_t *channel_info; xge_hal_channel_t *channel = (xge_hal_channel_t* ) channelh; if (size != sizeof(xge_hal_stats_channel_info_t)) { return XGE_HAL_ERR_VERSION_CONFLICT; } if ((status = xge_hal_stats_channel (channelh, &channel_info)) != XGE_HAL_OK) { return status; } if (xge_hal_device_check_id(channel->devh) == XGE_HAL_CARD_HERC) { __hal_update_ring_bump( (xge_hal_device_t *) channel->devh, channel->post_qid, channel_info); } xge_os_memcpy(channel_stats, channel_info, sizeof(xge_hal_stats_channel_info_t)); return XGE_HAL_OK; } /** * xge_hal_mgmt_pcireg_read - Read PCI configuration at a specified * offset. * @devh: HAL device handle. * @offset: Offset in the 256 byte PCI configuration space. * @value_bits: 8, 16, or 32 (bits) to read. * @value: Value returned by HAL. * * Read PCI configuration, given device and offset in the PCI space. * * Returns: XGE_HAL_OK - success. * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. * XGE_HAL_ERR_INVALID_OFFSET - Register offset in the BAR space is not * valid. * XGE_HAL_ERR_INVALID_VALUE_BIT_SIZE - Invalid bits size. Valid * values(8/16/32). * */ xge_hal_status_e xge_hal_mgmt_pcireg_read(xge_hal_device_h devh, unsigned int offset, int value_bits, u32 *value) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { return XGE_HAL_ERR_INVALID_DEVICE; } if (offset > sizeof(xge_hal_pci_config_t)-value_bits/8) { return XGE_HAL_ERR_INVALID_OFFSET; } if (value_bits == 8) { xge_os_pci_read8(hldev->pdev, hldev->cfgh, offset, (u8*)value); } else if (value_bits == 16) { xge_os_pci_read16(hldev->pdev, hldev->cfgh, offset, (u16*)value); } else if (value_bits == 32) { xge_os_pci_read32(hldev->pdev, hldev->cfgh, offset, value); } else { return XGE_HAL_ERR_INVALID_VALUE_BIT_SIZE; } return XGE_HAL_OK; } /** * xge_hal_mgmt_device_config - Retrieve device configuration. * @devh: HAL device handle. * @dev_config: Device configuration, see xge_hal_device_config_t{}. * @size: Size of the @dev_config buffer. HAL will return an error * if the size is smaller than sizeof(xge_hal_mgmt_device_config_t). * * Get device configuration. Permits to retrieve at run-time configuration * values that were used to initialize and configure the device. * * Returns: XGE_HAL_OK - success. * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. * * See also: xge_hal_device_config_t{}, xge_hal_mgmt_driver_config(). */ xge_hal_status_e xge_hal_mgmt_device_config(xge_hal_device_h devh, xge_hal_mgmt_device_config_t *dev_config, int size) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { return XGE_HAL_ERR_INVALID_DEVICE; } if (size != sizeof(xge_hal_mgmt_device_config_t)) { return XGE_HAL_ERR_VERSION_CONFLICT; } xge_os_memcpy(dev_config, &hldev->config, sizeof(xge_hal_device_config_t)); return XGE_HAL_OK; } /** * xge_hal_mgmt_driver_config - Retrieve driver configuration. * @drv_config: Device configuration, see xge_hal_driver_config_t{}. * @size: Size of the @dev_config buffer. HAL will return an error * if the size is smaller than sizeof(xge_hal_mgmt_driver_config_t). * * Get driver configuration. Permits to retrieve at run-time configuration * values that were used to configure the device at load-time. * * Returns: XGE_HAL_OK - success. * XGE_HAL_ERR_DRIVER_NOT_INITIALIZED - HAL is not initialized. * XGE_HAL_ERR_VERSION_CONFLICT - Version is not maching. * * See also: xge_hal_driver_config_t{}, xge_hal_mgmt_device_config(). */ xge_hal_status_e xge_hal_mgmt_driver_config(xge_hal_mgmt_driver_config_t *drv_config, int size) { if (g_xge_hal_driver == NULL) { return XGE_HAL_ERR_DRIVER_NOT_INITIALIZED; } if (size != sizeof(xge_hal_mgmt_driver_config_t)) { return XGE_HAL_ERR_VERSION_CONFLICT; } xge_os_memcpy(drv_config, &g_xge_hal_driver->config, sizeof(xge_hal_mgmt_driver_config_t)); return XGE_HAL_OK; } /** * xge_hal_mgmt_pci_config - Retrieve PCI configuration. * @devh: HAL device handle. * @pci_config: 256 byte long buffer for PCI configuration space. * @size: Size of the @ buffer. HAL will return an error * if the size is smaller than sizeof(xge_hal_mgmt_pci_config_t). * * Get PCI configuration. Permits to retrieve at run-time configuration * values that were used to configure the device at load-time. * * Returns: XGE_HAL_OK - success. * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid. * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching. * */ xge_hal_status_e xge_hal_mgmt_pci_config(xge_hal_device_h devh, xge_hal_mgmt_pci_config_t *pci_config, int size) { int i; xge_hal_device_t *hldev = (xge_hal_device_t*)devh; if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) { return XGE_HAL_ERR_INVALID_DEVICE; } if (size != sizeof(xge_hal_mgmt_pci_config_t)) { return XGE_HAL_ERR_VERSION_CONFLICT; } /* refresh PCI config space */ for (i = 0; i < 0x68/4+1; i++) { xge_os_pci_read32(hldev->pdev, hldev->cfgh, i*4, (u32*)&hldev->pci_config_space + i); } xge_os_memcpy(pci_config, &hldev->pci_config_space, sizeof(xge_hal_mgmt_pci_config_t)); return XGE_HAL_OK; } #ifdef XGE_TRACE_INTO_CIRCULAR_ARR /** * xge_hal_mgmt_trace_read - Read trace buffer contents. * @buffer: Buffer to store the trace buffer contents. * @buf_size: Size of the buffer. * @offset: Offset in the internal trace buffer to read data. * @read_length: Size of the valid data in the buffer. * * Read HAL trace buffer contents starting from the offset * upto the size of the buffer or till EOF is reached. * * Returns: XGE_HAL_OK - success. * XGE_HAL_EOF_TRACE_BUF - No more data in the trace buffer. * */ xge_hal_status_e xge_hal_mgmt_trace_read (char *buffer, unsigned buf_size, unsigned *offset, unsigned *read_length) { int data_offset; int start_offset; if ((g_xge_os_tracebuf == NULL) || (g_xge_os_tracebuf->offset == g_xge_os_tracebuf->size - 2)) { return XGE_HAL_EOF_TRACE_BUF; } data_offset = g_xge_os_tracebuf->offset + 1; if (*offset >= (unsigned)xge_os_strlen(g_xge_os_tracebuf->data + data_offset)) { return XGE_HAL_EOF_TRACE_BUF; } xge_os_memzero(buffer, buf_size); start_offset = data_offset + *offset; *read_length = xge_os_strlen(g_xge_os_tracebuf->data + start_offset); if (*read_length >= buf_size) { *read_length = buf_size - 1; } xge_os_memcpy(buffer, g_xge_os_tracebuf->data + start_offset, *read_length); *offset += *read_length; (*read_length) ++; return XGE_HAL_OK; } #endif /** * xge_hal_restore_link_led - Restore link LED to its original state. * @devh: HAL device handle. */ void xge_hal_restore_link_led(xge_hal_device_h devh) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; u64 val64; /* * If the current link state is UP, switch on LED else make it * off. */ /* * For Xena 3 and lower revision cards, adapter control needs to be * used for making LED ON/OFF. */ if ((xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) && (xge_hal_device_rev(hldev) <= 3)) { val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->adapter_control); if (hldev->link_state == XGE_HAL_LINK_UP) { val64 |= XGE_HAL_ADAPTER_LED_ON; } else { val64 &= ~XGE_HAL_ADAPTER_LED_ON; } xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->adapter_control); return; } /* * Use beacon control register to control the LED. * LED link output corresponds to bit 8 of the beacon control * register. Note that, in the case of Xena, beacon control register * represents the gpio control register. In the case of Herc, LED * handling is done by beacon control register as opposed to gpio * control register in Xena. Beacon control is used only to toggle * and the value written into it does not depend on the link state. * It is upto the ULD to toggle the LED even number of times which * brings the LED to it's original state. */ val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->beacon_control); val64 |= 0x0000800000000000ULL; xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->beacon_control); } /** * xge_hal_flick_link_led - Flick (blink) link LED. * @devh: HAL device handle. * * Depending on the card revision flicker the link LED by using the * beacon control or the adapter_control register. */ void xge_hal_flick_link_led(xge_hal_device_h devh) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; u64 val64 = 0; /* * For Xena 3 and lower revision cards, adapter control needs to be * used for making LED ON/OFF. */ if ((xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) && (xge_hal_device_rev(hldev) <= 3)) { val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->adapter_control); val64 ^= XGE_HAL_ADAPTER_LED_ON; xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->adapter_control); return; } /* * Use beacon control register to control the Link LED. * Note that, in the case of Xena, beacon control register represents * the gpio control register. In the case of Herc, LED handling is * done by beacon control register as opposed to gpio control register * in Xena. */ val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->beacon_control); val64 ^= XGE_HAL_GPIO_CTRL_GPIO_0; xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->beacon_control); } /** * xge_hal_read_eeprom - Read 4 bytes of data from user given offset. * @devh: HAL device handle. * @off: offset at which the data must be written * @data: output parameter where the data is stored. * * Read 4 bytes of data from the user given offset and return the * read data. * Note: will allow to read only part of the EEPROM visible through the * I2C bus. * Returns: -1 on failure, 0 on success. */ xge_hal_status_e xge_hal_read_eeprom(xge_hal_device_h devh, int off, u32* data) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_status_e ret = XGE_HAL_FAIL; u32 exit_cnt = 0; u64 val64; xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; val64 = XGE_HAL_I2C_CONTROL_DEV_ID(XGE_DEV_ID) | XGE_HAL_I2C_CONTROL_ADDR(off) | XGE_HAL_I2C_CONTROL_BYTE_CNT(0x3) | XGE_HAL_I2C_CONTROL_READ | XGE_HAL_I2C_CONTROL_CNTL_START; __hal_serial_mem_write64(hldev, val64, &bar0->i2c_control); while (exit_cnt < 5) { val64 = __hal_serial_mem_read64(hldev, &bar0->i2c_control); if (XGE_HAL_I2C_CONTROL_CNTL_END(val64)) { *data = XGE_HAL_I2C_CONTROL_GET_DATA(val64); ret = XGE_HAL_OK; break; } exit_cnt++; } return ret; } /* * xge_hal_write_eeprom - actually writes the relevant part of the data value. * @devh: HAL device handle. * @off: offset at which the data must be written * @data : The data that is to be written * @cnt : Number of bytes of the data that are actually to be written into * the Eeprom. (max of 3) * * Actually writes the relevant part of the data value into the Eeprom * through the I2C bus. * Return value: * 0 on success, -1 on failure. */ xge_hal_status_e xge_hal_write_eeprom(xge_hal_device_h devh, int off, u32 data, int cnt) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_status_e ret = XGE_HAL_FAIL; u32 exit_cnt = 0; u64 val64; xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; val64 = XGE_HAL_I2C_CONTROL_DEV_ID(XGE_DEV_ID) | XGE_HAL_I2C_CONTROL_ADDR(off) | XGE_HAL_I2C_CONTROL_BYTE_CNT(cnt) | XGE_HAL_I2C_CONTROL_SET_DATA(data) | XGE_HAL_I2C_CONTROL_CNTL_START; __hal_serial_mem_write64(hldev, val64, &bar0->i2c_control); while (exit_cnt < 5) { val64 = __hal_serial_mem_read64(hldev, &bar0->i2c_control); if (XGE_HAL_I2C_CONTROL_CNTL_END(val64)) { if (!(val64 & XGE_HAL_I2C_CONTROL_NACK)) ret = XGE_HAL_OK; break; } exit_cnt++; } return ret; } /* * xge_hal_register_test - reads and writes into all clock domains. * @hldev : private member of the device structure. * xge_nic structure. * @data : variable that returns the result of each of the test conducted b * by the driver. * * Read and write into all clock domains. The NIC has 3 clock domains, * see that registers in all the three regions are accessible. * Return value: * 0 on success. */ xge_hal_status_e xge_hal_register_test(xge_hal_device_h devh, u64 *data) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; u64 val64 = 0; int fail = 0; val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->pif_rd_swapper_fb); if (val64 != 0x123456789abcdefULL) { fail = 1; xge_debug_osdep(XGE_TRACE, "Read Test level 1 fails"); } val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->rmac_pause_cfg); if (val64 != 0xc000ffff00000000ULL) { fail = 1; xge_debug_osdep(XGE_TRACE, "Read Test level 2 fails"); } val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->rx_queue_cfg); if (val64 != 0x0808080808080808ULL) { fail = 1; xge_debug_osdep(XGE_TRACE, "Read Test level 3 fails"); } val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->xgxs_efifo_cfg); if (val64 != 0x000000001923141EULL) { fail = 1; xge_debug_osdep(XGE_TRACE, "Read Test level 4 fails"); } val64 = 0x5A5A5A5A5A5A5A5AULL; xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->xmsi_data); val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->xmsi_data); if (val64 != 0x5A5A5A5A5A5A5A5AULL) { fail = 1; xge_debug_osdep(XGE_ERR, "Write Test level 1 fails"); } val64 = 0xA5A5A5A5A5A5A5A5ULL; xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->xmsi_data); val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->xmsi_data); if (val64 != 0xA5A5A5A5A5A5A5A5ULL) { fail = 1; xge_debug_osdep(XGE_ERR, "Write Test level 2 fails"); } *data = fail; return XGE_HAL_OK; } /* * xge_hal_rldram_test - offline test for access to the RldRam chip on the NIC * @devh: HAL device handle. * @data: variable that returns the result of each of the test * conducted by the driver. * * This is one of the offline test that tests the read and write * access to the RldRam chip on the NIC. * Return value: * 0 on success. */ xge_hal_status_e xge_hal_rldram_test(xge_hal_device_h devh, u64 *data) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; u64 val64; int cnt, iteration = 0, test_pass = 0; val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->adapter_control); val64 &= ~XGE_HAL_ADAPTER_ECC_EN; xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->adapter_control); val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->mc_rldram_test_ctrl); val64 |= XGE_HAL_MC_RLDRAM_TEST_MODE; xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->mc_rldram_test_ctrl); val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->mc_rldram_mrs); val64 |= XGE_HAL_MC_RLDRAM_QUEUE_SIZE_ENABLE; __hal_serial_mem_write64(hldev, val64, &bar0->i2c_control); val64 |= XGE_HAL_MC_RLDRAM_MRS_ENABLE; __hal_serial_mem_write64(hldev, val64, &bar0->i2c_control); while (iteration < 2) { val64 = 0x55555555aaaa0000ULL; if (iteration == 1) { val64 ^= 0xFFFFFFFFFFFF0000ULL; } xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->mc_rldram_test_d0); val64 = 0xaaaa5a5555550000ULL; if (iteration == 1) { val64 ^= 0xFFFFFFFFFFFF0000ULL; } xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->mc_rldram_test_d1); val64 = 0x55aaaaaaaa5a0000ULL; if (iteration == 1) { val64 ^= 0xFFFFFFFFFFFF0000ULL; } xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->mc_rldram_test_d2); val64 = (u64) (0x0000003fffff0000ULL); xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->mc_rldram_test_add); val64 = XGE_HAL_MC_RLDRAM_TEST_MODE; xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->mc_rldram_test_ctrl); val64 |= XGE_HAL_MC_RLDRAM_TEST_MODE | XGE_HAL_MC_RLDRAM_TEST_WRITE | XGE_HAL_MC_RLDRAM_TEST_GO; xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->mc_rldram_test_ctrl); for (cnt = 0; cnt < 5; cnt++) { val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->mc_rldram_test_ctrl); if (val64 & XGE_HAL_MC_RLDRAM_TEST_DONE) break; xge_os_mdelay(200); } if (cnt == 5) break; val64 = XGE_HAL_MC_RLDRAM_TEST_MODE; xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->mc_rldram_test_ctrl); val64 |= XGE_HAL_MC_RLDRAM_TEST_MODE | XGE_HAL_MC_RLDRAM_TEST_GO; xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->mc_rldram_test_ctrl); for (cnt = 0; cnt < 5; cnt++) { val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->mc_rldram_test_ctrl); if (val64 & XGE_HAL_MC_RLDRAM_TEST_DONE) break; xge_os_mdelay(500); } if (cnt == 5) break; val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->mc_rldram_test_ctrl); if (val64 & XGE_HAL_MC_RLDRAM_TEST_PASS) test_pass = 1; iteration++; } if (!test_pass) *data = 1; else *data = 0; return XGE_HAL_OK; } /* * xge_hal_pma_loopback - Enable or disable PMA loopback * @devh: HAL device handle. * @enable:Boolean set to 1 to enable and 0 to disable. * * Enable or disable PMA loopback. * Return value: * 0 on success. */ xge_hal_status_e xge_hal_pma_loopback( xge_hal_device_h devh, int enable ) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; u64 val64; u16 data; /* * This code if for MAC loopbak * Should be enabled through another parameter */ #if 0 val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->mac_cfg); if ( enable ) { val64 |= ( XGE_HAL_MAC_CFG_TMAC_LOOPBACK | XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE ); } __hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0, (u32)(val64 >> 32), (char*)&bar0->mac_cfg); xge_os_mdelay(1); #endif val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(0) | XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(1) | XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | XGE_HAL_MDIO_CONTROL_MMD_CTRL(0) | XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_ADDRESS); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(0) | XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(1) | XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | XGE_HAL_MDIO_CONTROL_MMD_CTRL(0) | XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_READ); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); val64 = __hal_serial_mem_read64(hldev, &bar0->mdio_control); data = (u16)XGE_HAL_MDIO_CONTROL_MMD_DATA_GET(val64); #define _HAL_LOOPBK_PMA 1 if( enable ) data |= 1; else data &= 0xfe; val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(0) | XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(1) | XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | XGE_HAL_MDIO_CONTROL_MMD_CTRL(0) | XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_ADDRESS); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(0) | XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(1) | XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | XGE_HAL_MDIO_CONTROL_MMD_DATA(data) | XGE_HAL_MDIO_CONTROL_MMD_CTRL(0x0) | XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_WRITE); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(0) | XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(1) | XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | XGE_HAL_MDIO_CONTROL_MMD_CTRL(0x0) | XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_READ); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); return XGE_HAL_OK; } u16 xge_hal_mdio_read( xge_hal_device_h devh, u32 mmd_type, u64 addr ) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; u64 val64 = 0x0; u16 rval16 = 0x0; u8 i = 0; /* address transaction */ val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(addr) | XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(mmd_type) | XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_ADDRESS); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); do { val64 = __hal_serial_mem_read64(hldev, &bar0->mdio_control); if (i++ > 10) { break; } }while((val64 & XGE_HAL_MDIO_CONTROL_MMD_CTRL(0xF)) != XGE_HAL_MDIO_CONTROL_MMD_CTRL(1)); /* Data transaction */ val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(addr) | XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(mmd_type) | XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_READ); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); i = 0; do { val64 = __hal_serial_mem_read64(hldev, &bar0->mdio_control); if (i++ > 10) { break; } }while((val64 & XGE_HAL_MDIO_CONTROL_MMD_CTRL(0xF)) != XGE_HAL_MDIO_CONTROL_MMD_CTRL(1)); rval16 = (u16)XGE_HAL_MDIO_CONTROL_MMD_DATA_GET(val64); return rval16; } xge_hal_status_e xge_hal_mdio_write( xge_hal_device_h devh, u32 mmd_type, u64 addr, u32 value ) { u64 val64 = 0x0; xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; u8 i = 0; /* address transaction */ val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(addr) | XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(mmd_type) | XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_ADDRESS); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); do { val64 = __hal_serial_mem_read64(hldev, &bar0->mdio_control); if (i++ > 10) { break; } } while((val64 & XGE_HAL_MDIO_CONTROL_MMD_CTRL(0xF)) != XGE_HAL_MDIO_CONTROL_MMD_CTRL(1)); /* Data transaction */ val64 = 0x0; val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(addr) | XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(mmd_type) | XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0) | XGE_HAL_MDIO_CONTROL_MMD_DATA(value) | XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_WRITE); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START); __hal_serial_mem_write64(hldev, val64, &bar0->mdio_control); i = 0; do { val64 = __hal_serial_mem_read64(hldev, &bar0->mdio_control); if (i++ > 10) { break; } }while((val64 & XGE_HAL_MDIO_CONTROL_MMD_CTRL(0xF)) != XGE_HAL_MDIO_CONTROL_MMD_CTRL(1)); return XGE_HAL_OK; } /* * xge_hal_eeprom_test - to verify that EEprom in the xena can be programmed. * @devh: HAL device handle. * @data:variable that returns the result of each of the test conducted by * the driver. * * Verify that EEPROM in the xena can be programmed using I2C_CONTROL * register. * Return value: * 0 on success. */ xge_hal_status_e xge_hal_eeprom_test(xge_hal_device_h devh, u64 *data) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; int fail = 0; u32 ret_data = 0; /* Test Write Error at offset 0 */ if (!xge_hal_write_eeprom(hldev, 0, 0, 3)) fail = 1; /* Test Write at offset 4f0 */ if (xge_hal_write_eeprom(hldev, 0x4F0, 0x01234567, 3)) fail = 1; if (xge_hal_read_eeprom(hldev, 0x4F0, &ret_data)) fail = 1; if (ret_data != 0x01234567) fail = 1; /* Reset the EEPROM data go FFFF */ (void) xge_hal_write_eeprom(hldev, 0x4F0, 0xFFFFFFFF, 3); /* Test Write Request Error at offset 0x7c */ if (!xge_hal_write_eeprom(hldev, 0x07C, 0, 3)) fail = 1; /* Test Write Request at offset 0x7fc */ if (xge_hal_write_eeprom(hldev, 0x7FC, 0x01234567, 3)) fail = 1; if (xge_hal_read_eeprom(hldev, 0x7FC, &ret_data)) fail = 1; if (ret_data != 0x01234567) fail = 1; /* Reset the EEPROM data go FFFF */ (void) xge_hal_write_eeprom(hldev, 0x7FC, 0xFFFFFFFF, 3); /* Test Write Error at offset 0x80 */ if (!xge_hal_write_eeprom(hldev, 0x080, 0, 3)) fail = 1; /* Test Write Error at offset 0xfc */ if (!xge_hal_write_eeprom(hldev, 0x0FC, 0, 3)) fail = 1; /* Test Write Error at offset 0x100 */ if (!xge_hal_write_eeprom(hldev, 0x100, 0, 3)) fail = 1; /* Test Write Error at offset 4ec */ if (!xge_hal_write_eeprom(hldev, 0x4EC, 0, 3)) fail = 1; *data = fail; return XGE_HAL_OK; } /* * xge_hal_bist_test - invokes the MemBist test of the card . * @devh: HAL device handle. * xge_nic structure. * @data:variable that returns the result of each of the test conducted by * the driver. * * This invokes the MemBist test of the card. We give around * 2 secs time for the Test to complete. If it's still not complete * within this peiod, we consider that the test failed. * Return value: * 0 on success and -1 on failure. */ xge_hal_status_e xge_hal_bist_test(xge_hal_device_h devh, u64 *data) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; u8 bist = 0; int cnt = 0; xge_hal_status_e ret = XGE_HAL_FAIL; xge_os_pci_read8(hldev->pdev, hldev->cfgh, 0x0f, &bist); bist |= 0x40; xge_os_pci_write8(hldev->pdev, hldev->cfgh, 0x0f, bist); while (cnt < 20) { xge_os_pci_read8(hldev->pdev, hldev->cfgh, 0x0f, &bist); if (!(bist & 0x40)) { *data = (bist & 0x0f); ret = XGE_HAL_OK; break; } xge_os_mdelay(100); cnt++; } return ret; } /* * xge_hal_link_test - verifies the link state of the nic * @devh: HAL device handle. * @data: variable that returns the result of each of the test conducted by * the driver. * * Verify the link state of the NIC and updates the input * argument 'data' appropriately. * Return value: * 0 on success. */ xge_hal_status_e xge_hal_link_test(xge_hal_device_h devh, u64 *data) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; u64 val64; val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->adapter_status); if (val64 & XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT) *data = 1; return XGE_HAL_OK; } /** * xge_hal_getpause_data -Pause frame frame generation and reception. * @devh: HAL device handle. * @tx : A field to return the pause generation capability of the NIC. * @rx : A field to return the pause reception capability of the NIC. * * Returns the Pause frame generation and reception capability of the NIC. * Return value: * void */ void xge_hal_getpause_data(xge_hal_device_h devh, int *tx, int *rx) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; u64 val64; val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->rmac_pause_cfg); if (val64 & XGE_HAL_RMAC_PAUSE_GEN_EN) *tx = 1; if (val64 & XGE_HAL_RMAC_PAUSE_RCV_EN) *rx = 1; } /** * xge_hal_setpause_data - set/reset pause frame generation. * @devh: HAL device handle. * @tx: A field that indicates the pause generation capability to be * set on the NIC. * @rx: A field that indicates the pause reception capability to be * set on the NIC. * * It can be used to set or reset Pause frame generation or reception * support of the NIC. * Return value: * int, returns 0 on Success */ int xge_hal_setpause_data(xge_hal_device_h devh, int tx, int rx) { xge_hal_device_t *hldev = (xge_hal_device_t*)devh; xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0; u64 val64; val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, &bar0->rmac_pause_cfg); if (tx) val64 |= XGE_HAL_RMAC_PAUSE_GEN_EN; else val64 &= ~XGE_HAL_RMAC_PAUSE_GEN_EN; if (rx) val64 |= XGE_HAL_RMAC_PAUSE_RCV_EN; else val64 &= ~XGE_HAL_RMAC_PAUSE_RCV_EN; xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64, &bar0->rmac_pause_cfg); return 0; } /** * xge_hal_read_xfp_current_temp - * @hldev: HAL device handle. * * This routine only gets the temperature for XFP modules. Also, updating of the * NVRAM can sometimes fail and so the reading we might get may not be uptodate. */ u32 xge_hal_read_xfp_current_temp(xge_hal_device_h hldev) { u16 val_1, val_2, i = 0; u32 actual; /* First update the NVRAM table of XFP. */ (void) xge_hal_mdio_write(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, 0x8000, 0x3); /* Now wait for the transfer to complete */ do { xge_os_mdelay( 50 ); // wait 50 milliseonds val_1 = xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, 0x8000); if ( i++ > 10 ) { // waited 500 ms which should be plenty of time. break; } }while (( val_1 & 0x000C ) != 0x0004); /* Now NVRAM table of XFP should be updated, so read the temp */ val_1 = (u8) xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, 0x8067); val_2 = (u8) xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, 0x8068); actual = ((val_1 << 8) | val_2); if (actual >= 32768) actual = actual- 65536; actual = actual/256; return actual; } /** * __hal_chk_xpak_counter - check the Xpak error count and log the msg. * @hldev: pointer to xge_hal_device_t structure * @type: xpak stats error type * @value: xpak stats value * * It is used to log the error message based on the xpak stats value * Return value: * None */ void __hal_chk_xpak_counter(xge_hal_device_t *hldev, int type, u32 value) { /* * If the value is high for three consecutive cylce, * log a error message */ if(value == 3) { switch(type) { case 1: hldev->stats.sw_dev_err_stats.xpak_counter. excess_temp = 0; /* * Notify the ULD on Excess Xpak temperature alarm msg */ if (g_xge_hal_driver->uld_callbacks.xpak_alarm_log) { g_xge_hal_driver->uld_callbacks.xpak_alarm_log( hldev->upper_layer_info, XGE_HAL_XPAK_ALARM_EXCESS_TEMP); } break; case 2: hldev->stats.sw_dev_err_stats.xpak_counter. excess_bias_current = 0; /* * Notify the ULD on Excess xpak bias current alarm msg */ if (g_xge_hal_driver->uld_callbacks.xpak_alarm_log) { g_xge_hal_driver->uld_callbacks.xpak_alarm_log( hldev->upper_layer_info, XGE_HAL_XPAK_ALARM_EXCESS_BIAS_CURRENT); } break; case 3: hldev->stats.sw_dev_err_stats.xpak_counter. excess_laser_output = 0; /* * Notify the ULD on Excess Xpak Laser o/p power * alarm msg */ if (g_xge_hal_driver->uld_callbacks.xpak_alarm_log) { g_xge_hal_driver->uld_callbacks.xpak_alarm_log( hldev->upper_layer_info, XGE_HAL_XPAK_ALARM_EXCESS_LASER_OUTPUT); } break; default: xge_debug_osdep(XGE_TRACE, "Incorrect XPAK Alarm " "type "); } } } /** * __hal_updt_stats_xpak - update the Xpak error count. * @hldev: pointer to xge_hal_device_t structure * * It is used to update the xpak stats value * Return value: * None */ void __hal_updt_stats_xpak(xge_hal_device_t *hldev) { u16 val_1; u64 addr; /* Check the communication with the MDIO slave */ addr = 0x0000; val_1 = 0x0; val_1 = xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, addr); if((val_1 == 0xFFFF) || (val_1 == 0x0000)) { xge_debug_osdep(XGE_TRACE, "ERR: MDIO slave access failed - " "Returned %x", val_1); return; } /* Check for the expected value of 2040 at PMA address 0x0000 */ if(val_1 != 0x2040) { xge_debug_osdep(XGE_TRACE, "Incorrect value at PMA address 0x0000 - "); xge_debug_osdep(XGE_TRACE, "Returned: %llx- Expected: 0x2040", (unsigned long long)(unsigned long)val_1); return; } /* Loading the DOM register to MDIO register */ addr = 0xA100; (void) xge_hal_mdio_write(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, addr, 0x0); val_1 = xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, addr); /* * Reading the Alarm flags */ addr = 0xA070; val_1 = 0x0; val_1 = xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, addr); if(CHECKBIT(val_1, 0x7)) { hldev->stats.sw_dev_err_stats.stats_xpak. alarm_transceiver_temp_high++; hldev->stats.sw_dev_err_stats.xpak_counter.excess_temp++; __hal_chk_xpak_counter(hldev, 0x1, hldev->stats.sw_dev_err_stats.xpak_counter.excess_temp); } else { hldev->stats.sw_dev_err_stats.xpak_counter.excess_temp = 0; } if(CHECKBIT(val_1, 0x6)) hldev->stats.sw_dev_err_stats.stats_xpak. alarm_transceiver_temp_low++; if(CHECKBIT(val_1, 0x3)) { hldev->stats.sw_dev_err_stats.stats_xpak. alarm_laser_bias_current_high++; hldev->stats.sw_dev_err_stats.xpak_counter. excess_bias_current++; __hal_chk_xpak_counter(hldev, 0x2, hldev->stats.sw_dev_err_stats.xpak_counter. excess_bias_current); } else { hldev->stats.sw_dev_err_stats.xpak_counter. excess_bias_current = 0; } if(CHECKBIT(val_1, 0x2)) hldev->stats.sw_dev_err_stats.stats_xpak. alarm_laser_bias_current_low++; if(CHECKBIT(val_1, 0x1)) { hldev->stats.sw_dev_err_stats.stats_xpak. alarm_laser_output_power_high++; hldev->stats.sw_dev_err_stats.xpak_counter. excess_laser_output++; __hal_chk_xpak_counter(hldev, 0x3, hldev->stats.sw_dev_err_stats.xpak_counter. excess_laser_output); } else { hldev->stats.sw_dev_err_stats.xpak_counter. excess_laser_output = 0; } if(CHECKBIT(val_1, 0x0)) hldev->stats.sw_dev_err_stats.stats_xpak. alarm_laser_output_power_low++; /* * Reading the warning flags */ addr = 0xA074; val_1 = 0x0; val_1 = xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, addr); if(CHECKBIT(val_1, 0x7)) hldev->stats.sw_dev_err_stats.stats_xpak. warn_transceiver_temp_high++; if(CHECKBIT(val_1, 0x6)) hldev->stats.sw_dev_err_stats.stats_xpak. warn_transceiver_temp_low++; if(CHECKBIT(val_1, 0x3)) hldev->stats.sw_dev_err_stats.stats_xpak. warn_laser_bias_current_high++; if(CHECKBIT(val_1, 0x2)) hldev->stats.sw_dev_err_stats.stats_xpak. warn_laser_bias_current_low++; if(CHECKBIT(val_1, 0x1)) hldev->stats.sw_dev_err_stats.stats_xpak. warn_laser_output_power_high++; if(CHECKBIT(val_1, 0x0)) hldev->stats.sw_dev_err_stats.stats_xpak. warn_laser_output_power_low++; }