/** 
 *  @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;
}
예제 #2
0
/**
 *  @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;
}
예제 #3
0
/* 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;
}