示例#1
0
/*
 * ---------------------------------------------------------------------------
 *  unifi_fw_read_start
 *
 *      Returns a structure to be passed in unifi_fw_read().
 *      This structure is an OS specific description of the f/w file.
 *      In the linux implementation it is a buffer with the f/w and its' length.
 *      The HIP driver calls this functions to request for the loader or
 *      the firmware file.
 *      The structure pointer can be freed when unifi_fw_read_stop() is called.
 *
 *  Arguments:
 *      ospriv          Pointer to driver context.
 *      is_fw           Flag to indicate whether it is the f/w or the loader
 *      info            Versions information. Can be used to determine
 *                      the appropriate f/w file to load.
 *
 *  Returns:
 *      O on success, non-zero otherwise.
 *
 * ---------------------------------------------------------------------------
 */
void*
unifi_fw_read_start(void *ospriv, CsrInt8 is_fw, const card_info_t *info)
{
    unifi_priv_t *priv = (unifi_priv_t*)ospriv;
    CSR_UNUSED(info);

    func_enter();
#ifdef ANDROID_BUILD
    /* Copy content of info to the priv struct to make it available in the reguest_firmware_files() function */
    priv->card_info = *info;
    printk("Unifi: Firmware build %d\n", (int) info->fw_build);
#endif
    if (is_fw == UNIFI_FW_LOADER) {
        /* F/w may have been released after a previous successful download */
        if (priv->fw_loader.dl_data == NULL) {
            unifi_trace(priv, UDBG2, "Attempt reload of loader f/w\n");    
            uf_request_firmware_files(priv, UNIFI_FW_LOADER);
        }        
        /* Set up callback struct for readfunc() */        
        if (priv->fw_loader.dl_data != NULL) {
            func_exit();
            return &priv->fw_loader;
        }       

    } else if (is_fw == UNIFI_FW_STA) {
        /* F/w may have been released after a previous successful download. */
        if (priv->fw_sta.dl_data == NULL) {
            unifi_trace(priv, UDBG2, "Attempt reload of sta f/w\n");    
            uf_request_firmware_files(priv, UNIFI_FW_STA);
        }                
        /* Set up callback struct for readfunc() */
        if (priv->fw_sta.dl_data != NULL) {
            func_exit();
            return &priv->fw_sta;
        }

    } else {
        unifi_error(priv, "downloading firmware... unknown request: %d\n", is_fw);
    }

    func_exit();
    return NULL;
} /* unifi_fw_read_start() */
int sme_mgt_wifi_on(unifi_priv_t *priv)
{
    int r,i;
    s32 csrResult;

    if (priv == NULL) {
        return -EINVAL;
    }
    /* Initialize the interface mode to None */
    for (i=0; i<CSR_WIFI_NUM_INTERFACES; i++) {
        priv->interfacePriv[i]->interfaceMode = 0;
    }

    /* Set up interface mode so that get_packet_priority() can
     * select the right QOS priority when WMM is enabled.
     */
    priv->interfacePriv[0]->interfaceMode = CSR_WIFI_ROUTER_CTRL_MODE_STA;

    r = uf_request_firmware_files(priv, UNIFI_FW_STA);
    if (r) {
        unifi_error(priv, "sme_mgt_wifi_on: Failed to get f/w\n");
        return r;
    }

    /*
     * The request to initialise UniFi might come while UniFi is running.
     * We need to block all I/O activity until the reset completes, otherwise
     * an SDIO error might occur resulting an indication to the SME which
     * makes it think that the initialisation has failed.
     */
    priv->bh_thread.block_thread = 1;

    /* Power on UniFi */
    CsrSdioClaim(priv->sdio);
    csrResult = CsrSdioPowerOn(priv->sdio);
    CsrSdioRelease(priv->sdio);
    if(csrResult != CSR_RESULT_SUCCESS && csrResult != CSR_SDIO_RESULT_NOT_RESET) {
        return -EIO;
    }

    if (csrResult == CSR_RESULT_SUCCESS) {
        /* Initialise UniFi hardware */
        r = uf_init_hw(priv);
        if (r) {
            return r;
        }
    }

    /* Re-enable the I/O thread */
    priv->bh_thread.block_thread = 0;

    /* Disable deep sleep signalling during the firmware initialisation, to
     * prevent the wakeup mechanism raising the SDIO clock beyond INIT before
     * the first MLME-RESET.ind. It gets re-enabled at the CONNECTED.ind,
     * immediately after the MLME-RESET.ind
     */
    csrResult = unifi_configure_low_power_mode(priv->card,
                                           UNIFI_LOW_POWER_DISABLED,
                                           UNIFI_PERIODIC_WAKE_HOST_DISABLED);
    if (csrResult != CSR_RESULT_SUCCESS) {
        unifi_warning(priv,
                      "sme_mgt_wifi_on: unifi_configure_low_power_mode() returned an error\n");
    }


    /* Start the I/O thread */
    CsrSdioClaim(priv->sdio);
    r = uf_init_bh(priv);
    if (r) {
        CsrSdioPowerOff(priv->sdio);
        CsrSdioRelease(priv->sdio);
        return r;
    }
    CsrSdioRelease(priv->sdio);

    priv->init_progress = UNIFI_INIT_FW_DOWNLOADED;

    return 0;
}