int PSSendOps(void *arg) { int i; int ps_index; int status = 0; PSCmdPacket *HciCmdList; /* List storing the commands */ const struct firmware* firmware; A_UINT32 numCmds; A_UINT8 *event; A_UINT8 *bufferToFree; struct hci_dev *device; A_UCHAR *buffer; A_UINT32 len; A_UINT32 DevType; A_UCHAR *PsFileName; A_UCHAR *patchFileName; A_UCHAR patch_loc[40]; A_UCHAR *path = NULL; A_UCHAR *config_path = NULL; A_UCHAR config_bdaddr[MAX_BDADDR_FORMAT_LENGTH]; AR3K_CONFIG_INFO *hdev = (AR3K_CONFIG_INFO*)arg; struct device *firmwareDev = NULL; A_UINT8 cFlags = 0; A_UINT8 bit7 = 0; status = 0; HciCmdList = NULL; #ifdef HCI_TRANSPORT_SDIO device = hdev->pBtStackHCIDev; firmwareDev = device->parent; #else device = hdev; firmwareDev = &device->dev; AthEnableSyncCommandOp(TRUE); #endif /* HCI_TRANSPORT_SDIO */ /* First verify if the controller is an FPGA or ASIC, so depending on the device type the PS file to be written will be different. */ path =(A_UCHAR *)A_MALLOC(MAX_FW_PATH_LEN); if(path == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for path\n", MAX_FW_PATH_LEN)); goto complete; } config_path = (A_UCHAR *) A_MALLOC(MAX_FW_PATH_LEN); if(config_path == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for config_path\n", MAX_FW_PATH_LEN)); goto complete; } if(A_ERROR == getDeviceType(hdev,&DevType)) { status = 1; goto complete; } if(A_ERROR == ReadVersionInfo(hdev)) { status = 1; goto complete; } patchFileName = PATCH_FILE; snprintf(path, MAX_FW_PATH_LEN, "%s/%xcoex/",CONFIG_PATH,Rom_Version); if(DevType){ if(DevType == 0xdeadc0de){ PsFileName = PS_ASIC_FILE; } else{ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" FPGA Test Image : %x %x \n",Rom_Version,Build_Version)); if((Rom_Version == 0x99999999) && (Build_Version == 1)){ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("FPGA Test Image : Skipping Patch File load\n")); patchFileName = NULL; } PsFileName = PS_FPGA_FILE; } } else{ PsFileName = PS_ASIC_FILE; } snprintf(config_path, MAX_FW_PATH_LEN, "%s%s",path,PsFileName); AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%x: FPGA/ASIC PS File Name %s\n", DevType,config_path)); /* Read the PS file to a dynamically allocated buffer */ if(A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ )); status = 1; goto complete; } if(NULL == firmware || firmware->size == 0) { status = 1; goto complete; } buffer = (A_UCHAR *)A_MALLOC(firmware->size); if(buffer != NULL) { /* Copy the read file to a local Dynamic buffer */ memcpy(buffer,firmware->data,firmware->size); len = firmware->size; A_RELEASE_FIRMWARE(firmware); /* Parse the PS buffer to a global variable */ status = AthDoParsePS(buffer,len); A_FREE(buffer); } else { A_RELEASE_FIRMWARE(firmware); } /* Read the patch file to a dynamically allocated buffer */ if(patchFileName != NULL) snprintf(config_path, MAX_FW_PATH_LEN, "%s%s",path,patchFileName); else { status = 0; } AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch File Name %s\n", config_path)); if((patchFileName == NULL) || (A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ )); /* * It is not necessary that Patch file be available, continue with PS Operations if. * failed. */ status = 0; } else { if(NULL == firmware || firmware->size == 0) { status = 0; } else { buffer = (A_UCHAR *)A_MALLOC(firmware->size); if(buffer != NULL) { /* Copy the read file to a local Dynamic buffer */ memcpy(buffer,firmware->data,firmware->size); len = firmware->size; A_RELEASE_FIRMWARE(firmware); /* parse and store the Patch file contents to a global variables */ patch_loc[0] = '\0'; status = AthDoParsePatch(buffer,len, patch_loc); A_FREE(buffer); } else { A_RELEASE_FIRMWARE(firmware); } } } /* Create an HCI command list from the parsed PS and patch information */ AthCreateCommandList(&HciCmdList,&numCmds); #define CONFIG_PLATFORM 0x21 #define CONFIG_TLPM 0x23 #define PLATFORM_CONFIG_BIT 0x01 #define TLPM_CONFIG_BIT 0x02 #define IDLE_TIMEOUT_OFFSET 12 #define WAKEUP_TIMEOUT_OFFSET 8 #define IDLE_TIMEOUT_DEFAULT_VAL 1000 #define WAKEUP_TIMEOUT_DEFAULT_VAL 10 hdev->IdleTimeout = IDLE_TIMEOUT_DEFAULT_VAL; hdev->WakeupTimeout = WAKEUP_TIMEOUT_DEFAULT_VAL; hdev->PwrMgmtEnabled = 0; ps_index = 2; /* CRC + PS Reset */ if (Patch_Count) ps_index += Patch_Count + 1; /* Patches + Enable patch Cmd */ for(i = ps_index; i <numCmds; i++) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Check PS ID %x\n", HciCmdList[i].Hcipacket[4])); /* search for Platform config and TLPM tags */ if((HciCmdList[i].Hcipacket[4] == CONFIG_PLATFORM) && (HciCmdList[i].Hcipacket[5] == 0)) { cFlags |= PLATFORM_CONFIG_BIT; bit7 = (HciCmdList[i].Hcipacket[7]) & (1<<7); if(bit7) { hdev->PwrMgmtEnabled = 1; AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("CONFIG PLATFORM present and Pwr Manage %x\n", hdev->PwrMgmtEnabled)); } } else if((HciCmdList[i].Hcipacket[4] == CONFIG_TLPM) && (HciCmdList[i].Hcipacket[5] == 0)) { cFlags |= TLPM_CONFIG_BIT; hdev->IdleTimeout = *((A_UINT32 *)&HciCmdList[i].Hcipacket[IDLE_TIMEOUT_OFFSET + 7]); hdev->WakeupTimeout = *((A_UINT16 *)&HciCmdList[i].Hcipacket[WAKEUP_TIMEOUT_OFFSET + 7]); AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("hdev->idletimeout %d hdev->WakeupTimeout %d",hdev->IdleTimeout, hdev->WakeupTimeout)); } } /* Form the parameter for PSSendOps() API */ /* * First Send the CRC packet, * We have to continue with the PS operations only if the CRC packet has been replied with * a Command complete event with status Error. */ if(SendHCICommandWaitCommandComplete (hdev, HciCmdList[0].Hcipacket, HciCmdList[0].packetLen, &event, &bufferToFree) == A_OK) { if(ReadPSEvent(event) == A_OK) { /* Exit if the status is success */ if(bufferToFree != NULL) { A_FREE(bufferToFree); } #ifndef HCI_TRANSPORT_SDIO if(bdaddr && bdaddr[0] !='\0') { write_bdaddr(hdev,bdaddr,BDADDR_TYPE_STRING); } #endif status = 1; goto complete; } if(bufferToFree != NULL) { A_FREE(bufferToFree); } } else { status = 0; goto complete; } /* Set Patch location */ if(patch_loc[0] != '\0') { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Setting Patch Location %s\n", patch_loc)); set_patch_ram(hdev,patch_loc,sizeof(patch_loc)); } for(i = 1; i <numCmds; i++) { Hci_log("PS/Patch Write -->",HciCmdList[i].Hcipacket,HciCmdList[i].packetLen); if(SendHCICommandWaitCommandComplete (hdev, HciCmdList[i].Hcipacket, HciCmdList[i].packetLen, &event, &bufferToFree) == A_OK) { if(ReadPSEvent(event) != A_OK) { /* Exit if the status is success */ if(bufferToFree != NULL) { A_FREE(bufferToFree); } status = 1; goto complete; } if(bufferToFree != NULL) { A_FREE(bufferToFree); } } else { status = 0; goto complete; } } #ifdef HCI_TRANSPORT_SDIO if(BDADDR == FALSE) if(hdev->bdaddr[0] !=0x00 || hdev->bdaddr[1] !=0x00 || hdev->bdaddr[2] !=0x00 || hdev->bdaddr[3] !=0x00 || hdev->bdaddr[4] !=0x00 || hdev->bdaddr[5] !=0x00) write_bdaddr(hdev,hdev->bdaddr,BDADDR_TYPE_HEX); /* if Platform config is present and TLPM is not available * write HCI command for TLPM with default timeout values */ if(bit7 && !(cFlags & TLPM_CONFIG_BIT)) { A_UCHAR TLPMHciCmd[] = {0x0b, 0xfc, 0x1c, 0x01, 0x23, 0x00, 0x18, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0xe8, 0x03, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00 }; int CmdLen = sizeof(TLPMHciCmd); *((A_UINT32 *)&TLPMHciCmd[IDLE_TIMEOUT_OFFSET + 7]) = hdev->IdleTimeout; *((A_UINT16 *)&TLPMHciCmd[WAKEUP_TIMEOUT_OFFSET + 7]) = hdev->WakeupTimeout; if(SendHCICommandWaitCommandComplete (hdev, TLPMHciCmd, CmdLen, &event, &bufferToFree) == A_OK) { if(ReadPSEvent(event) != A_OK) { /* Exit if the status is success */ if(bufferToFree != NULL) { A_FREE(bufferToFree); } status = 1; goto complete; } if(bufferToFree != NULL) { A_FREE(bufferToFree); } } else { status = 0; goto complete; } } #ifndef HCI_TRANSPORT_SDIO if(bdaddr && bdaddr[0] != '\0') { write_bdaddr(hdev,bdaddr,BDADDR_TYPE_STRING); } else #endif /* HCI_TRANSPORT_SDIO */ /* Write BDADDR Read from OTP here */ #endif { /* Read Contents of BDADDR file if user has not provided any option */ snprintf(config_path,MAX_FW_PATH_LEN, "%s%s",path,BDADDR_FILE); AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BDADDR File Name %s\n", config_path)); if(A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ )); goto complete; } if(NULL == firmware || firmware->size == 0) { goto complete; } len = (firmware->size > MAX_BDADDR_FORMAT_LENGTH)? MAX_BDADDR_FORMAT_LENGTH: firmware->size; memcpy(config_bdaddr, firmware->data,len); config_bdaddr[len] = '\0'; write_bdaddr(hdev,config_bdaddr,BDADDR_TYPE_STRING); A_RELEASE_FIRMWARE(firmware); } complete: #ifndef HCI_TRANSPORT_SDIO AthEnableSyncCommandOp(FALSE); PSTagMode = FALSE; wake_up_interruptible(&PsCompleteEvent); #endif /* HCI_TRANSPORT_SDIO */ if(NULL != HciCmdList) { AthFreeCommandList(&HciCmdList,numCmds); } if(path) { A_FREE(path); } if(config_path) { A_FREE(config_path); } return status; }
int PSSendOps(void *arg) { int i; int status = 0; struct ps_cmd_packet *HciCmdList; /* List storing the commands */ const struct firmware* firmware; u32 numCmds; u8 *event; u8 *bufferToFree; struct hci_dev *device; u8 *buffer; u32 len; u32 DevType; u8 *PsFileName; u8 *patchFileName; u8 *path = NULL; u8 *config_path = NULL; u8 config_bdaddr[MAX_BDADDR_FORMAT_LENGTH]; struct ar3k_config_info *hdev = (struct ar3k_config_info*)arg; struct device *firmwareDev = NULL; status = 0; HciCmdList = NULL; #ifdef HCI_TRANSPORT_SDIO device = hdev->pBtStackHCIDev; firmwareDev = device->parent; #else device = hdev; firmwareDev = &device->dev; AthEnableSyncCommandOp(true); #endif /* HCI_TRANSPORT_SDIO */ /* First verify if the controller is an FPGA or ASIC, so depending on the device type the PS file to be written will be different. */ path =(u8 *)A_MALLOC(MAX_FW_PATH_LEN); if(path == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for path\n", MAX_FW_PATH_LEN)); goto complete; } config_path = (u8 *) A_MALLOC(MAX_FW_PATH_LEN); if(config_path == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for config_path\n", MAX_FW_PATH_LEN)); goto complete; } if(A_ERROR == getDeviceType(hdev,&DevType)) { status = 1; goto complete; } if(A_ERROR == ReadVersionInfo(hdev)) { status = 1; goto complete; } patchFileName = PATCH_FILE; snprintf(path, MAX_FW_PATH_LEN, "%s/%xcoex/",CONFIG_PATH,Rom_Version); if(DevType){ if(DevType == 0xdeadc0de){ PsFileName = PS_ASIC_FILE; } else{ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" FPGA Test Image : %x %x \n",Rom_Version,Build_Version)); if((Rom_Version == 0x99999999) && (Build_Version == 1)){ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("FPGA Test Image : Skipping Patch File load\n")); patchFileName = NULL; } PsFileName = PS_FPGA_FILE; } } else{ PsFileName = PS_ASIC_FILE; } snprintf(config_path, MAX_FW_PATH_LEN, "%s%s",path,PsFileName); AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%x: FPGA/ASIC PS File Name %s\n", DevType,config_path)); /* Read the PS file to a dynamically allocated buffer */ if(A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ )); status = 1; goto complete; } if(NULL == firmware || firmware->size == 0) { status = 1; goto complete; } buffer = (u8 *)A_MALLOC(firmware->size); if(buffer != NULL) { /* Copy the read file to a local Dynamic buffer */ memcpy(buffer,firmware->data,firmware->size); len = firmware->size; A_RELEASE_FIRMWARE(firmware); /* Parse the PS buffer to a global variable */ status = AthDoParsePS(buffer,len); kfree(buffer); } else { A_RELEASE_FIRMWARE(firmware); } /* Read the patch file to a dynamically allocated buffer */ if(patchFileName != NULL) snprintf(config_path, MAX_FW_PATH_LEN, "%s%s",path,patchFileName); else { status = 0; } AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch File Name %s\n", config_path)); if((patchFileName == NULL) || (A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ )); /* * It is not necessary that Patch file be available, continue with PS Operations if. * failed. */ status = 0; } else { if(NULL == firmware || firmware->size == 0) { status = 0; } else { buffer = (u8 *)A_MALLOC(firmware->size); if(buffer != NULL) { /* Copy the read file to a local Dynamic buffer */ memcpy(buffer,firmware->data,firmware->size); len = firmware->size; A_RELEASE_FIRMWARE(firmware); /* parse and store the Patch file contents to a global variables */ status = AthDoParsePatch(buffer,len); kfree(buffer); } else { A_RELEASE_FIRMWARE(firmware); } } } /* Create an HCI command list from the parsed PS and patch information */ AthCreateCommandList(&HciCmdList,&numCmds); /* Form the parameter for PSSendOps() API */ /* * First Send the CRC packet, * We have to continue with the PS operations only if the CRC packet has been replied with * a Command complete event with status Error. */ if(SendHCICommandWaitCommandComplete (hdev, HciCmdList[0].Hcipacket, HciCmdList[0].packetLen, &event, &bufferToFree) == 0) { if(ReadPSEvent(event) == 0) { /* Exit if the status is success */ if(bufferToFree != NULL) { kfree(bufferToFree); } #ifndef HCI_TRANSPORT_SDIO if(bdaddr && bdaddr[0] !='\0') { write_bdaddr(hdev,bdaddr,BDADDR_TYPE_STRING); } #endif status = 1; goto complete; } if(bufferToFree != NULL) { kfree(bufferToFree); } } else { status = 0; goto complete; } for(i = 1; i <numCmds; i++) { if(SendHCICommandWaitCommandComplete (hdev, HciCmdList[i].Hcipacket, HciCmdList[i].packetLen, &event, &bufferToFree) == 0) { if(ReadPSEvent(event) != 0) { /* Exit if the status is success */ if(bufferToFree != NULL) { kfree(bufferToFree); } status = 1; goto complete; } if(bufferToFree != NULL) { kfree(bufferToFree); } } else { status = 0; goto complete; } } #ifdef HCI_TRANSPORT_SDIO if(BDADDR == false) if(hdev->bdaddr[0] !=0x00 || hdev->bdaddr[1] !=0x00 || hdev->bdaddr[2] !=0x00 || hdev->bdaddr[3] !=0x00 || hdev->bdaddr[4] !=0x00 || hdev->bdaddr[5] !=0x00) write_bdaddr(hdev,hdev->bdaddr,BDADDR_TYPE_HEX); #ifndef HCI_TRANSPORT_SDIO if(bdaddr && bdaddr[0] != '\0') { write_bdaddr(hdev,bdaddr,BDADDR_TYPE_STRING); } else #endif /* HCI_TRANSPORT_SDIO */ /* Write BDADDR Read from OTP here */ #endif { /* Read Contents of BDADDR file if user has not provided any option */ snprintf(config_path,MAX_FW_PATH_LEN, "%s%s",path,BDADDR_FILE); AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch File Name %s\n", config_path)); if(A_REQUEST_FIRMWARE(&firmware,config_path,firmwareDev) < 0) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ )); status = 1; goto complete; } if(NULL == firmware || firmware->size == 0) { status = 1; goto complete; } len = min_t(size_t, firmware->size, MAX_BDADDR_FORMAT_LENGTH - 1); memcpy(config_bdaddr, firmware->data, len); config_bdaddr[len] = '\0'; write_bdaddr(hdev,config_bdaddr,BDADDR_TYPE_STRING); A_RELEASE_FIRMWARE(firmware); } complete: #ifndef HCI_TRANSPORT_SDIO AthEnableSyncCommandOp(false); PSTagMode = false; wake_up_interruptible(&PsCompleteEvent); #endif /* HCI_TRANSPORT_SDIO */ if(NULL != HciCmdList) { AthFreeCommandList(&HciCmdList,numCmds); } if(path) { kfree(path); } if(config_path) { kfree(config_path); } return status; }