/** * @brief This function issues boot command to the Boot2 code * @param iValue 1: Boot from FW by USB-Download * 2: Boot from FW in EEPROM * 3: Update Storage Boot2 * 4: Update Storage FW * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ static int us_usb_issue_boot_command(struct usb_card_rec *cardp, int iValue) { int ret, actual_length; struct BootCMDStr sBootCMD; struct BootCMDRespStr* sBootCMDResp; ENTER(); /* Prepare Command */ memset((void *) &sBootCMD, 0x00, sizeof(sBootCMD)); sBootCMD.u32MagicNumber = wlan_cpu_to_le32(BOOT_CMD_MAGIC_NUMBER); sBootCMD.u8CMD_Tag = iValue; /* Issue Command */ if ((ret = usb_bulk_msg(cardp->udev, usb_sndbulkpipe(cardp->udev, cardp-> bulk_out_endpointAddr), (u8 *) & sBootCMD, sizeof(struct BootCMDStr), &actual_length, USB_BULK_MSG_TIMEOUT))) { PRINTM(ERROR, "usb_bulk_msg send failed, ret %d\n", ret); LEAVE(); return ret; } PRINTM(INFO, "Actual length sent is %d\n", actual_length); //memset((void *) &sBootCMDResp, 0x00, sizeof(sBootCMDResp)); sBootCMDResp = kmalloc(MVUSB_RX_BUF_LEN, GFP_KERNEL); memset((void *) sBootCMDResp, 0x00, MVUSB_RX_BUF_LEN); if ((ret = usb_bulk_msg(cardp->udev, usb_rcvbulkpipe(cardp->udev, cardp-> bulk_in_endpointAddr), (u8 *) sBootCMDResp, MVUSB_RX_BUF_LEN, &actual_length, USB_BULK_MSG_TIMEOUT))) { PRINTM(ERROR, "usb_bulk_msg send failed, ret %d\n", ret); if(sBootCMDResp) kfree(sBootCMDResp); LEAVE(); return ret; } if (wlan_le32_to_cpu(sBootCMDResp->u32MagicNumber) != BOOT_CMD_MAGIC_NUMBER) { PRINTM(FATAL, "Boot command response MAGIC_NUMBER error (0x%x)\n", sBootCMDResp->u32MagicNumber); if(sBootCMDResp) kfree(sBootCMDResp); LEAVE(); return WLAN_STATUS_FAILURE; } if(sBootCMDResp) kfree(sBootCMDResp); PRINTM(INFO, "Boot command response success\n"); LEAVE(); return WLAN_STATUS_SUCCESS; }
/** * @brief This function downloads FW blocks to device * * @param pmadapter A pointer to mlan_adapter * @param pmfw A pointer to firmware image * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ static mlan_status wlan_prog_fw_w_helper(IN pmlan_adapter pmadapter, IN pmlan_fw_image pmfw) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_callbacks pcb = &pmadapter->callbacks; t_u8 *firmware = pmfw->pfw_buf, *RecvBuff; t_u32 retries = MAX_FW_RETRY, DataLength; t_u32 FWSeqNum = 0, TotalBytes = 0, DnldCmd = 0; FWData *fwdata = MNULL; FWSyncHeader SyncFWHeader; ENTER(); if (!firmware && !pcb->moal_get_fw_data) { PRINTM(MMSG, "No firmware image found! Terminating download\n"); ret = MLAN_STATUS_FAILURE; goto fw_exit; } /* Allocate memory for transmit */ ret = pcb->moal_malloc(pmadapter->pmoal_handle, FW_DNLD_TX_BUF_SIZE, MLAN_MEM_DEF | MLAN_MEM_DMA, (t_u8 **) & fwdata); if ((ret != MLAN_STATUS_SUCCESS) || !fwdata) { PRINTM(MERROR, "Could not allocate buffer for FW download\n"); goto fw_exit; } /* Allocate memory for receive */ ret = pcb->moal_malloc(pmadapter->pmoal_handle, FW_DNLD_RX_BUF_SIZE, MLAN_MEM_DEF | MLAN_MEM_DMA, &RecvBuff); if ((ret != MLAN_STATUS_SUCCESS) || !RecvBuff) { PRINTM(MERROR, "Could not allocate buffer for FW download response\n"); goto cleanup; } do { /* Copy the header of the firmware data to get the length */ if (firmware) memcpy(pmadapter, &fwdata->fw_header, &firmware[TotalBytes], sizeof(FWHeader)); else pcb->moal_get_fw_data(pmadapter->pmoal_handle, TotalBytes, sizeof(FWHeader), (t_u8 *) & fwdata->fw_header); DataLength = wlan_le32_to_cpu(fwdata->fw_header.data_length); DnldCmd = wlan_le32_to_cpu(fwdata->fw_header.dnld_cmd); TotalBytes += sizeof(FWHeader); /* Copy the firmware data */ if (firmware) memcpy(pmadapter, fwdata->data, &firmware[TotalBytes], DataLength); else pcb->moal_get_fw_data(pmadapter->pmoal_handle, TotalBytes, DataLength, (t_u8 *) fwdata->data); fwdata->seq_num = wlan_cpu_to_le32(FWSeqNum); TotalBytes += DataLength; /* If the send/receive fails or CRC occurs then retry */ while (retries) { mlan_buffer mbuf; int length = FW_DATA_XMIT_SIZE; retries--; memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer)); mbuf.pbuf = (t_u8 *) fwdata; mbuf.data_len = length; /* Send the firmware block */ if ((ret = pcb->moal_write_data_sync(pmadapter->pmoal_handle, &mbuf, MLAN_USB_EP_CMD_EVENT, MLAN_USB_BULK_MSG_TIMEOUT)) != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "fw_dnld: write_data failed, ret %d\n", ret); continue; } memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer)); mbuf.pbuf = RecvBuff; mbuf.data_len = FW_DNLD_RX_BUF_SIZE; /* Receive the firmware block response */ if ((ret = pcb->moal_read_data_sync(pmadapter->pmoal_handle, &mbuf, MLAN_USB_EP_CMD_EVENT, MLAN_USB_BULK_MSG_TIMEOUT)) != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "fw_dnld: read_data failed, ret %d\n", ret); continue; } memcpy(pmadapter, &SyncFWHeader, RecvBuff, sizeof(FWSyncHeader)); endian_convert_syncfwheader(&SyncFWHeader); /* Check the firmware block response for CRC errors */ if (SyncFWHeader.cmd) { PRINTM(MERROR, "FW received Blk with CRC error 0x%x\n", SyncFWHeader.cmd); ret = MLAN_STATUS_FAILURE; continue; } retries = MAX_FW_RETRY; break; } FWSeqNum++; PRINTM(MINFO, ".\n"); } while ((DnldCmd != FW_HAS_LAST_BLOCK) && retries); cleanup: PRINTM(MINFO, "fw_dnld: %d bytes downloaded\n", TotalBytes); if (RecvBuff) pcb->moal_mfree(pmadapter->pmoal_handle, RecvBuff); if (fwdata) pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) fwdata); if (retries) { ret = MLAN_STATUS_SUCCESS; } fw_exit: LEAVE(); return ret; }
/* borrowed from mlanconfig.c and bg_scan_wifidir.conf. This function is hard * coded for our WIFIDIR set up and may not be suitable for all applications. */ int mlanconfig_bgscan(int mode) { unsigned char *buf; wfdcmdbuf *header = NULL; mrvl_cmd_head_buf *hostcmd; int ret = WPS_STATUS_SUCCESS; mlanconfig_bgscfg_cmd_hdr *hdr; ssid_header_tlv *ssid_tlv; probe_header_tlv *probe_tlv; channel_header_tlv *chan_tlv; snr_header_tlv *snr_tlv; start_later_header_tlv *start_later_tlv; u8 *cmd; buf = (unsigned char *)wps_mem_malloc(MRVDRV_SIZE_OF_CMD_BUFFER); if (buf == NULL) { wmprintf("allocate memory for hostcmd failed\r\n"); return WPS_STATUS_FAIL; } /* prepare the bgscan command */ memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER); hostcmd = (mrvl_cmd_head_buf *) buf; hostcmd->cmd_code = wlan_cpu_to_le16(HostCmd_CMD_BGSCAN_CFG); hostcmd->seq_num = (0x01) << 13; hostcmd->result = 0; hostcmd->size = sizeof(mrvl_cmd_head_buf); /* These are all magic numbers from the bg_scan_wifidir.conf file supplied by Marvell */ hdr = (mlanconfig_bgscfg_cmd_hdr *) (buf + sizeof(mrvl_cmd_head_buf)); hdr->Action = 1; hdr->Enable = mode; hdr->BssType = 3; hdr->ChannelsPerScan = 3; hdr->ScanInterval = wlan_cpu_to_le32(1000); hdr->StoreCondition = wlan_cpu_to_le32(1); hdr->ReportConditions = wlan_cpu_to_le32(1); hostcmd->size += sizeof(mlanconfig_bgscfg_cmd_hdr); ssid_tlv = (ssid_header_tlv *) (buf + hostcmd->size); ssid_tlv->type = MLANCONFIG_SSID_HEADER_TYPE; ssid_tlv->len = wlan_cpu_to_le16(SIZEOF_VALUE(ssid_header_tlv)); ssid_tlv->MaxSSIDLen = wlan_cpu_to_le16(0); memcpy(ssid_tlv->ssid, "DIRECT-", sizeof(ssid_tlv->ssid)); hostcmd->size += sizeof(tlv) + ssid_tlv->len; probe_tlv = (probe_header_tlv *) (buf + hostcmd->size); probe_tlv->type = MLANCONFIG_PROBE_HEADER_TYPE; probe_tlv->len = wlan_cpu_to_le16(SIZEOF_VALUE(probe_header_tlv)); probe_tlv->NumProbes = wlan_cpu_to_le16(2); hostcmd->size += sizeof(tlv) + probe_tlv->len; chan_tlv = (channel_header_tlv *) (buf + hostcmd->size); chan_tlv->type = MLANCONFIG_CHANNEL_HEADER_TYPE; chan_tlv->len = wlan_cpu_to_le16(SIZEOF_VALUE(channel_header_tlv)); chan_tlv->Chan1_RadioType = 0; chan_tlv->Chan1_ChanNumber = 1; chan_tlv->Chan1_ScanType = 2; chan_tlv->Chan1_MinScanTime = wlan_cpu_to_le16(50); chan_tlv->Chan1_ScanTime = wlan_cpu_to_le16(100); chan_tlv->Chan2_RadioType = 0; chan_tlv->Chan2_ChanNumber = 6; chan_tlv->Chan2_ScanType = 2; chan_tlv->Chan2_MinScanTime = wlan_cpu_to_le16(50); chan_tlv->Chan2_ScanTime = wlan_cpu_to_le16(100); chan_tlv->Chan3_RadioType = 0; chan_tlv->Chan3_ChanNumber = 11; chan_tlv->Chan3_ScanType = 2; chan_tlv->Chan3_MinScanTime = wlan_cpu_to_le16(50); chan_tlv->Chan3_ScanTime = wlan_cpu_to_le16(100); hostcmd->size += sizeof(tlv) + chan_tlv->len; snr_tlv = (snr_header_tlv *) (buf + hostcmd->size); snr_tlv->type = MLANCONFIG_SNR_HEADER_TYPE; snr_tlv->len = wlan_cpu_to_le16(SIZEOF_VALUE(snr_header_tlv)); snr_tlv->SNRValue = 40; hostcmd->size += sizeof(tlv) + snr_tlv->len; start_later_tlv = (start_later_header_tlv *) (buf + hostcmd->size); start_later_tlv->type = MLANCONFIG_START_LATER_HEADER_TYPE; start_later_tlv->len = wlan_cpu_to_le16(SIZEOF_VALUE(start_later_header_tlv)); start_later_tlv->StartLaterValue = 0; hostcmd->size += sizeof(tlv) + start_later_tlv->len; hostcmd->size = wlan_cpu_to_le16(hostcmd->size); cmd = (u8 *) buf; *(u32 *) cmd = hostcmd->size - BUF_HEADER_SIZE; header = (wfdcmdbuf *) cmd; header->cmd_head.size = hostcmd->size; header->cmd_head.buf_size = header->cmd_head.size + BUF_HEADER_SIZE; endian_convert_request_header(header->cmd_head); wps_hexdump(DEBUG_WFD_DISCOVERY, "Scan config", (unsigned char *)buf, hostcmd->size); if (wfd_ioctl((u8 *) buf, hostcmd->size) == WPS_STATUS_SUCCESS) { wps_printf(DEBUG_WFD_DISCOVERY, "Scan config command sent.\n"); } else { wps_printf(DEBUG_WFD_DISCOVERY, "Scan config command send failed.\n"); ret = WPS_STATUS_FAIL; } if (buf) wps_mem_free(buf); return ret; }