diff options
Diffstat (limited to 'drivers/staging/bcm/InterfaceDld.c')
| -rw-r--r-- | drivers/staging/bcm/InterfaceDld.c | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/drivers/staging/bcm/InterfaceDld.c b/drivers/staging/bcm/InterfaceDld.c new file mode 100644 index 00000000..348ad75b --- /dev/null +++ b/drivers/staging/bcm/InterfaceDld.c @@ -0,0 +1,332 @@ +#include "headers.h" + +int InterfaceFileDownload(PVOID arg, struct file *flp, unsigned int on_chip_loc) +{ + /* unsigned int reg = 0; */ + mm_segment_t oldfs = {0}; + int errno = 0, len = 0; /* ,is_config_file = 0 */ + loff_t pos = 0; + struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)arg; + /* struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter; */ + char *buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL); + + if (!buff) + return -ENOMEM; + + while (1) { + oldfs = get_fs(); + set_fs(get_ds()); + len = vfs_read(flp, (void __force __user *)buff, + MAX_TRANSFER_CTRL_BYTE_USB, &pos); + set_fs(oldfs); + if (len <= 0) { + if (len < 0) { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, + DBG_TYPE_INITEXIT, MP_INIT, + DBG_LVL_ALL, "len < 0"); + errno = len; + } else { + errno = 0; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, + DBG_TYPE_INITEXIT, MP_INIT, + DBG_LVL_ALL, + "Got end of file!"); + } + break; + } + /* BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT, + * DBG_LVL_ALL, buff, + * MAX_TRANSFER_CTRL_BYTE_USB); + */ + errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len); + if (errno) { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, + DBG_TYPE_PRINTK, 0, 0, + "WRM Failed! status: %d", errno); + break; + } + on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB; + } + + kfree(buff); + return errno; +} + +int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_chip_loc) +{ + char *buff, *buff_readback; + unsigned int reg = 0; + mm_segment_t oldfs = {0}; + int errno = 0, len = 0, is_config_file = 0; + loff_t pos = 0; + static int fw_down; + INT Status = STATUS_SUCCESS; + struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)arg; + int bytes; + + buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA); + buff_readback = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA); + if (!buff || !buff_readback) { + kfree(buff); + kfree(buff_readback); + + return -ENOMEM; + } + + is_config_file = (on_chip_loc == CONFIG_BEGIN_ADDR) ? 1 : 0; + + memset(buff_readback, 0, MAX_TRANSFER_CTRL_BYTE_USB); + memset(buff, 0, MAX_TRANSFER_CTRL_BYTE_USB); + while (1) { + oldfs = get_fs(); + set_fs(get_ds()); + len = vfs_read(flp, (void __force __user *)buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos); + set_fs(oldfs); + fw_down++; + + if (len <= 0) { + if (len < 0) { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0"); + errno = len; + } else { + errno = 0; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!"); + } + break; + } + + bytes = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len); + if (bytes < 0) { + Status = bytes; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "RDM of len %d Failed! %d", len, reg); + goto exit; + } + reg++; + if ((len-sizeof(unsigned int)) < 4) { + if (memcmp(buff_readback, buff, len)) { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Length is: %d", len); + Status = -EIO; + goto exit; + } + } else { + len -= 4; + + while (len) { + if (*(unsigned int *)&buff_readback[len] != *(unsigned int *)&buff[len]) { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&buff_readback[len]); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len); + Status = -EIO; + goto exit; + } + len -= 4; + } + } + on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB; + } /* End of while(1) */ + +exit: + kfree(buff); + kfree(buff_readback); + return Status; +} + +static int bcm_download_config_file(struct bcm_mini_adapter *Adapter, struct bcm_firmware_info *psFwInfo) +{ + int retval = STATUS_SUCCESS; + B_UINT32 value = 0; + + if (Adapter->pstargetparams == NULL) { + Adapter->pstargetparams = kmalloc(sizeof(struct bcm_target_params), GFP_KERNEL); + if (Adapter->pstargetparams == NULL) + return -ENOMEM; + } + + if (psFwInfo->u32FirmwareLength != sizeof(struct bcm_target_params)) + return -EIO; + + retval = copy_from_user(Adapter->pstargetparams, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength); + if (retval) { + kfree(Adapter->pstargetparams); + Adapter->pstargetparams = NULL; + return -EFAULT; + } + + /* Parse the structure and then Download the Firmware */ + beceem_parse_target_struct(Adapter); + + /* Initializing the NVM. */ + BcmInitNVM(Adapter); + retval = InitLedSettings(Adapter); + + if (retval) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "INIT LED Failed\n"); + return retval; + } + + if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { + Adapter->LEDInfo.bLedInitDone = FALSE; + Adapter->DriverState = DRIVER_INIT; + wake_up(&Adapter->LEDInfo.notify_led_event); + } + + if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { + Adapter->DriverState = FW_DOWNLOAD; + wake_up(&Adapter->LEDInfo.notify_led_event); + } + + /* Initialize the DDR Controller */ + retval = ddr_init(Adapter); + if (retval) { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "DDR Init Failed\n"); + return retval; + } + + value = 0; + wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value)); + wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value)); + + if (Adapter->eNVMType == NVM_FLASH) { + retval = PropagateCalParamsFromFlashToMemory(Adapter); + if (retval) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "propagaion of cal param failed with status :%d", retval); + return retval; + } + } + + retval = buffDnldVerify(Adapter, (PUCHAR)Adapter->pstargetparams, sizeof(struct bcm_target_params), CONFIG_BEGIN_ADDR); + + if (retval) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "configuration file not downloaded properly"); + else + Adapter->bCfgDownloaded = TRUE; + + return retval; +} + +int bcm_ioctl_fw_download(struct bcm_mini_adapter *Adapter, struct bcm_firmware_info *psFwInfo) +{ + int retval = STATUS_SUCCESS; + PUCHAR buff = NULL; + + /* Config File is needed for the Driver to download the Config file and + * Firmware. Check for the Config file to be first to be sent from the + * Application + */ + atomic_set(&Adapter->uiMBupdate, FALSE); + if (!Adapter->bCfgDownloaded && psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR) { + /* Can't Download Firmware. */ + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Download the config File first\n"); + return -EINVAL; + } + + /* If Config File, Finish the DDR Settings and then Download CFG File */ + if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) { + retval = bcm_download_config_file(Adapter, psFwInfo); + } else { + buff = kzalloc(psFwInfo->u32FirmwareLength, GFP_KERNEL); + if (buff == NULL) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed in allocation memory"); + return -ENOMEM; + } + + retval = copy_from_user(buff, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength); + if (retval != STATUS_SUCCESS) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copying buffer from user space failed"); + retval = -EFAULT; + goto error; + } + + retval = buffDnldVerify(Adapter, + buff, + psFwInfo->u32FirmwareLength, + psFwInfo->u32StartingAddress); + + if (retval != STATUS_SUCCESS) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "f/w download failed status :%d", retval); + goto error; + } + } + +error: + kfree(buff); + return retval; +} + +static INT buffDnld(struct bcm_mini_adapter *Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress) +{ + unsigned int len = 0; + int retval = STATUS_SUCCESS; + len = u32FirmwareLength; + + while (u32FirmwareLength) { + len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB); + retval = wrm(Adapter, u32StartingAddress, mappedbuffer, len); + + if (retval) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "wrm failed with status :%d", retval); + break; + } + u32StartingAddress += len; + u32FirmwareLength -= len; + mappedbuffer += len; + } + return retval; +} + +static INT buffRdbkVerify(struct bcm_mini_adapter *Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress) +{ + UINT len = u32FirmwareLength; + INT retval = STATUS_SUCCESS; + PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL); + int bytes; + + if (NULL == readbackbuff) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "MEMORY ALLOCATION FAILED"); + return -ENOMEM; + } + + while (u32FirmwareLength && !retval) { + len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB); + bytes = rdm(Adapter, u32StartingAddress, readbackbuff, len); + + if (bytes < 0) { + retval = bytes; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed with status %d", retval); + break; + } + + if (memcmp(readbackbuff, mappedbuffer, len) != 0) { + pr_err("%s() failed. The firmware doesn't match what was written", + __func__); + retval = -EIO; + } + + u32StartingAddress += len; + u32FirmwareLength -= len; + mappedbuffer += len; + + } /* end of while (u32FirmwareLength && !retval) */ + kfree(readbackbuff); + return retval; +} + +INT buffDnldVerify(struct bcm_mini_adapter *Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength, unsigned long u32StartingAddress) +{ + INT status = STATUS_SUCCESS; + + status = buffDnld(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress); + if (status != STATUS_SUCCESS) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer download failed"); + goto error; + } + + status = buffRdbkVerify(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress); + if (status != STATUS_SUCCESS) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer readback verifier failed"); + goto error; + } +error: + return status; +} |
