int write_bdaddr(struct ar3k_config_info *pConfig,u8 *bdaddr,int type) { u8 bdaddr_cmd[] = { 0x0B, 0xFC, 0x0A, 0x01, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; u8 *event; u8 *bufferToFree = NULL; int result = A_ERROR; int inc,outc; if (type == BDADDR_TYPE_STRING) str2ba(bdaddr,&bdaddr_cmd[7]); else { /* Bdaddr has to be sent as LAP first */ for(inc = 5 ,outc = 7; inc >=0; inc--, outc++) bdaddr_cmd[outc] = bdaddr[inc]; } if(0 == SendHCICommandWaitCommandComplete(pConfig,bdaddr_cmd, sizeof(bdaddr_cmd), &event,&bufferToFree)) { if(event[4] == 0xFC && event[5] == 0x00){ if(event[3] == 0x0B){ result = 0; } } } if(bufferToFree != NULL) { kfree(bufferToFree); } return result; }
A_STATUS write_bdaddr(AR3K_CONFIG_INFO *pConfig,A_UCHAR *bdaddr) { A_UCHAR bdaddr_cmd[] = { 0x0B, 0xFC, 0x0A, 0x01, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; A_UINT8 *event; A_UINT8 *bufferToFree = NULL; A_STATUS result = A_ERROR; str2ba(bdaddr,&bdaddr_cmd[7]); if(A_OK == SendHCICommandWaitCommandComplete(pConfig,bdaddr_cmd, sizeof(bdaddr_cmd), &event,&bufferToFree)) { if(event[4] == 0xFC && event[5] == 0x00){ if(event[3] == 0x0B){ result = A_OK; } } } if(bufferToFree != NULL) { A_FREE(bufferToFree); } return result; }
A_STATUS write_bdaddr(AR3K_CONFIG_INFO *pConfig,A_UCHAR *bdaddr,int type) { A_UCHAR bdaddr_cmd[] = { 0x0B, 0xFC, 0x0A, 0x01, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; A_UINT8 *event; A_UINT8 *bufferToFree = NULL; A_STATUS result = A_ERROR; int inc,outc; if (type == BDADDR_TYPE_STRING) str2ba(bdaddr,&bdaddr_cmd[7]); else { /* Bdaddr has to be sent as LAP first */ for(inc = 5 ,outc = 7; inc >=0; inc--, outc++) bdaddr_cmd[outc] = bdaddr[inc]; } if(A_OK == SendHCICommandWaitCommandComplete(pConfig,bdaddr_cmd, sizeof(bdaddr_cmd), &event,&bufferToFree)) { if(event[4] == 0xFC && event[5] == 0x00){ if(event[3] == 0x0B){ result = A_OK; } } } if(bufferToFree != NULL) { A_FREE(bufferToFree); } return result; }
static A_STATUS AR3KConfigureHCIBaud(AR3K_CONFIG_INFO *pConfig) { A_STATUS status = A_OK; A_UINT8 hciBaudChangeCommand[] = {0x0c,0xfc,0x2,0,0}; A_UINT16 baudVal; A_UINT8 *pEvent = NULL; A_UINT8 *pBufferToFree = NULL; do { if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR3K_BAUD) { baudVal = (A_UINT16)(pConfig->AR3KBaudRate / 100); hciBaudChangeCommand[3] = (A_UINT8)baudVal; hciBaudChangeCommand[4] = (A_UINT8)(baudVal >> 8); status = SendHCICommandWaitCommandComplete(pConfig, hciBaudChangeCommand, sizeof(hciBaudChangeCommand), &pEvent, &pBufferToFree); if (A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Baud rate change failed! \n")); break; } if (pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET] != 0) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR3K Config: Baud change command event status failed: %d \n", pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET])); status = A_ECOMM; break; } AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("AR3K Config: Baud Changed to %d \n",pConfig->AR3KBaudRate)); } if (pConfig->Flags & AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY) { /* some versions of AR3K do not switch baud immediately, up to 300MS */ A_MDELAY(325); } if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP) { /* Tell target to change UART baud rate for AR6K */ status = HCI_TransportSetBaudRate(pConfig->pHCIDev, pConfig->AR3KBaudRate); if (A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR3K Config: failed to set scale and step values: %d \n", status)); break; } AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("AR3K Config: Baud changed to %d for AR6K\n", pConfig->AR3KBaudRate)); } } while (FALSE);
int ReadVersionInfo(struct ar3k_config_info *pConfig) { u8 hciCommand[] = {0x1E,0xfc,0x00}; u8 *event; u8 *bufferToFree = NULL; int result = A_ERROR; if(0 == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) { result = ReadPSEvent(event); } if(bufferToFree != NULL) { kfree(bufferToFree); } return result; }
A_STATUS ReadVersionInfo(AR3K_CONFIG_INFO *pConfig) { A_UINT8 hciCommand[] = {0x1E,0xfc,0x00}; A_UINT8 *event; A_UINT8 *bufferToFree = NULL; A_STATUS result = A_ERROR; if(A_OK == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) { result = ReadPSEvent(event); } if(bufferToFree != NULL) { A_FREE(bufferToFree); } return result; }
A_STATUS getDeviceType(AR3K_CONFIG_INFO *pConfig, A_UINT32 * code) { A_UINT8 hciCommand[] = {0x05,0xfc,0x05,0x00,0x00,0x00,0x00,0x04}; A_UINT8 *event; A_UINT8 *bufferToFree = NULL; A_UINT32 reg; A_STATUS result = A_ERROR; *code = 0; hciCommand[3] = (A_UINT8)(FPGA_REGISTER & 0xFF); hciCommand[4] = (A_UINT8)((FPGA_REGISTER >> 8) & 0xFF); hciCommand[5] = (A_UINT8)((FPGA_REGISTER >> 16) & 0xFF); hciCommand[6] = (A_UINT8)((FPGA_REGISTER >> 24) & 0xFF); if(A_OK == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) { if(event[4] == 0xFC && event[5] == 0x00){ switch(event[3]){ case 0x05: reg = event[9]; reg = ((reg << 8) |event[8]); reg = ((reg << 8) |event[7]); reg = ((reg << 8) |event[6]); *code = reg; result = A_OK; break; case 0x06: //Sleep(500); break; } } } if(bufferToFree != NULL) { A_FREE(bufferToFree); } return result; }
int getDeviceType(struct ar3k_config_info *pConfig, u32 *code) { u8 hciCommand[] = {0x05,0xfc,0x05,0x00,0x00,0x00,0x00,0x04}; u8 *event; u8 *bufferToFree = NULL; u32 reg; int result = A_ERROR; *code = 0; hciCommand[3] = (u8)(FPGA_REGISTER & 0xFF); hciCommand[4] = (u8)((FPGA_REGISTER >> 8) & 0xFF); hciCommand[5] = (u8)((FPGA_REGISTER >> 16) & 0xFF); hciCommand[6] = (u8)((FPGA_REGISTER >> 24) & 0xFF); if(0 == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) { if(event[4] == 0xFC && event[5] == 0x00){ switch(event[3]){ case 0x05: reg = event[9]; reg = ((reg << 8) |event[8]); reg = ((reg << 8) |event[7]); reg = ((reg << 8) |event[6]); *code = reg; result = 0; break; case 0x06: //Sleep(500); break; } } } if(bufferToFree != NULL) { kfree(bufferToFree); } return result; }
A_STATUS set_patch_ram(AR3K_CONFIG_INFO *pConfig,A_UCHAR *patch_loc,A_UINT8 len) { A_UCHAR cmd[] = { 0x0B, 0xFC, 0x07, 0x0D, 0x00, 0x00, 0x00, /* Loc */0x00, 0x00, 0x00, 0x00 }; A_UCHAR i,j; unsigned char loc_byte[3]; A_UINT8 *event; A_UINT8 *bufferToFree = NULL; A_STATUS result = A_ERROR; A_UCHAR *loc_ptr = &cmd[7]; if(!patch_loc) return result; loc_byte[2] = '\0'; LoadHeader(cmd, 0x0D, 4, 0); for( i = 0,j = 3; i < 4; i++, j--) { loc_byte[0] = patch_loc[0]; loc_byte[1] = patch_loc[1]; loc_ptr[j] = A_STRTOL(loc_byte,NULL,16); patch_loc+=2; } Hci_log("Patch Ram Write -->",cmd, sizeof(cmd)); if(A_OK == SendHCICommandWaitCommandComplete(pConfig,cmd, sizeof(cmd), &event,&bufferToFree)) { result = ReadPSEvent(event); } if(bufferToFree != NULL) { A_FREE(bufferToFree); } return result; }
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; }
int PSSendOps(void *arg) { int i; 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; AR3K_CONFIG_INFO *hdev = (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. */ if(A_ERROR == getDeviceType(hdev,&DevType)) { status = 1; goto complete; } if(A_ERROR == ReadVersionInfo(hdev)) { status = 1; goto complete; } patchFileName = PATCH_FILE; 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; } AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%x: FPGA/ASIC PS File Name %s\n", DevType,PsFileName)); /* Read the PS file to a dynamically allocated buffer */ if(request_firmware(&firmware,PsFileName,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; release_firmware(firmware); /* Parse the PS buffer to a global variable */ status = AthDoParsePS(buffer,len); A_FREE(buffer); } else { release_firmware(firmware); } /* Read the patch file to a dynamically allocated buffer */ if((patchFileName == NULL) || (request_firmware(&firmware,patchFileName,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; release_firmware(firmware); /* parse and store the Patch file contents to a global variables */ status = AthDoParsePatch(buffer,len); A_FREE(buffer); } else { 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) == 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[0] !='\0') { write_bdaddr(hdev,bdaddr); } #endif status = 1; goto complete; } if(bufferToFree != NULL) { A_FREE(bufferToFree); } } else { status = 0; goto complete; } for(i = 1; i <numCmds; i++) { 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; } } #ifndef HCI_TRANSPORT_SDIO if(bdaddr[0] != '\0') { write_bdaddr(hdev,bdaddr); } else #endif /* HCI_TRANSPORT_SDIO */ { /* Read Contents of BDADDR file if user has not provided any option */ if(request_firmware(&firmware,BDADDR_FILE,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; } write_bdaddr(hdev,(A_UCHAR *)firmware->data); 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); } return status; }