/**
 *  @brief This function registers MOAL to MLAN module.
 *
 *  @param pmdevice        A pointer to a mlan_device structure
 *                         allocated in MOAL
 *  @param ppmlan_adapter  A pointer to a t_void pointer to store
 *                         mlan_adapter structure pointer as the context
 *
 *  @return                MLAN_STATUS_SUCCESS
 *                             The registration succeeded.
 *                         MLAN_STATUS_FAILURE
 *                             The registration failed.
 *
 * mlan_status mlan_register (
 *   IN pmlan_device     pmdevice,
 *   OUT t_void          **ppmlan_adapter
 * );
 *
 * Comments
 *   MOAL constructs mlan_device data structure to pass moal_handle and
 *   mlan_callback table to MLAN. MLAN returns mlan_adapter pointer to
 *   the ppmlan_adapter buffer provided by MOAL.
 * Headers:
 *   declared in mlan_decl.h
 * See Also
 *   mlan_unregister
 */
mlan_status
mlan_register(IN pmlan_device pmdevice, OUT t_void ** ppmlan_adapter)
{
    mlan_status ret = MLAN_STATUS_SUCCESS;
    pmlan_adapter pmadapter = MNULL;
    pmlan_callbacks pcb = MNULL;
    t_u8 i = 0;
    t_u32 j = 0;

    MASSERT(pmdevice);
    MASSERT(ppmlan_adapter);
    MASSERT(pmdevice->callbacks.moal_print);
#ifdef DEBUG_LEVEL1
    print_callback = pmdevice->callbacks.moal_print;
    get_sys_time_callback = pmdevice->callbacks.moal_get_system_time;
#endif
    assert_callback = pmdevice->callbacks.moal_assert;

    ENTER();

    MASSERT(pmdevice->callbacks.moal_malloc);
    MASSERT(pmdevice->callbacks.moal_memset);
    MASSERT(pmdevice->callbacks.moal_memmove);

    /* Allocate memory for adapter structure */
    if (pmdevice->callbacks.moal_vmalloc && pmdevice->callbacks.moal_vfree)
        ret = pmdevice->callbacks.moal_vmalloc(pmdevice->pmoal_handle,
                                               sizeof(mlan_adapter),
                                               (t_u8 **) & pmadapter);
    else
        ret = pmdevice->callbacks.moal_malloc(pmdevice->pmoal_handle,
                                              sizeof(mlan_adapter),
                                              MLAN_MEM_DEF,
                                              (t_u8 **) & pmadapter);
    if ((ret != MLAN_STATUS_SUCCESS) || !pmadapter) {
        ret = MLAN_STATUS_FAILURE;
        goto exit_register;
    }

    pmdevice->callbacks.moal_memset(pmdevice->pmoal_handle, pmadapter,
                                    0, sizeof(mlan_adapter));

    pcb = &pmadapter->callbacks;

    /* Save callback functions */
    pmdevice->callbacks.moal_memmove(pmadapter->pmoal_handle, pcb,
                                     &pmdevice->callbacks,
                                     sizeof(mlan_callbacks));

    /* Assertion for all callback functions */
    MASSERT(pcb->moal_init_fw_complete);
    MASSERT(pcb->moal_shutdown_fw_complete);
    MASSERT(pcb->moal_send_packet_complete);
    MASSERT(pcb->moal_recv_packet);
    MASSERT(pcb->moal_recv_event);
    MASSERT(pcb->moal_ioctl_complete);

    MASSERT(pcb->moal_write_reg);
    MASSERT(pcb->moal_read_reg);
    MASSERT(pcb->moal_alloc_mlan_buffer);
    MASSERT(pcb->moal_free_mlan_buffer);
    MASSERT(pcb->moal_write_data_sync);
    MASSERT(pcb->moal_read_data_sync);
    MASSERT(pcb->moal_mfree);
    MASSERT(pcb->moal_memcpy);
    MASSERT(pcb->moal_memcmp);
    MASSERT(pcb->moal_get_system_time);
    MASSERT(pcb->moal_init_timer);
    MASSERT(pcb->moal_free_timer);
    MASSERT(pcb->moal_start_timer);
    MASSERT(pcb->moal_stop_timer);
    MASSERT(pcb->moal_init_lock);
    MASSERT(pcb->moal_free_lock);
    MASSERT(pcb->moal_spin_lock);
    MASSERT(pcb->moal_spin_unlock);
    MASSERT(pcb->moal_tcp_ack_tx_ind);

    /* Save pmoal_handle */
    pmadapter->pmoal_handle = pmdevice->pmoal_handle;

    if ((pmdevice->int_mode == INT_MODE_GPIO) && (pmdevice->gpio_pin == 0)) {
        PRINTM(MERROR, "SDIO_GPIO_INT_CONFIG: Invalid GPIO Pin\n");
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
    pmadapter->init_para.int_mode = pmdevice->int_mode;
    pmadapter->init_para.gpio_pin = pmdevice->gpio_pin;
    /* card specific probing has been deferred until now .. */
    ret = wlan_sdio_probe(pmadapter);
    if (MLAN_STATUS_SUCCESS != ret) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
#ifdef DEBUG_LEVEL1
    mlan_drvdbg = pmdevice->drvdbg;
#endif

#ifdef MFG_CMD_SUPPORT
    pmadapter->init_para.mfg_mode = pmdevice->mfg_mode;
#endif

#ifdef SDIO_MULTI_PORT_TX_AGGR
    pmadapter->init_para.mpa_tx_cfg = pmdevice->mpa_tx_cfg;
#endif
#ifdef SDIO_MULTI_PORT_RX_AGGR
    pmadapter->init_para.mpa_rx_cfg = pmdevice->mpa_rx_cfg;
#endif
    pmadapter->init_para.auto_ds = pmdevice->auto_ds;
    pmadapter->init_para.ps_mode = pmdevice->ps_mode;
    if (pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_2K ||
            pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_4K ||
            pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_8K)
        pmadapter->init_para.max_tx_buf = pmdevice->max_tx_buf;
#ifdef STA_SUPPORT
    pmadapter->init_para.cfg_11d = pmdevice->cfg_11d;
#else
    pmadapter->init_para.cfg_11d = 0;
#endif
    pmadapter->init_para.dfs_master_radar_det_en =
        DFS_MASTER_RADAR_DETECT_EN;
    pmadapter->init_para.dfs_slave_radar_det_en = DFS_SLAVE_RADAR_DETECT_EN;
    pmadapter->init_para.fw_crc_check = pmdevice->fw_crc_check;
    pmadapter->rx_work_flag = pmdevice->rx_work;

    pmadapter->priv_num = 0;
    for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
        pmadapter->priv[i] = MNULL;
        if (pmdevice->bss_attr[i].active == MTRUE) {
            /* For valid bss_attr, allocate memory for private
               structure */
            if (pcb->moal_vmalloc && pcb->moal_vfree)
                ret = pcb->moal_vmalloc(pmadapter->pmoal_handle,
                                        sizeof(mlan_private),
                                        (t_u8 **) & pmadapter->
                                        priv[i]);
            else
                ret = pcb->moal_malloc(pmadapter->pmoal_handle,
                                       sizeof(mlan_private),
                                       MLAN_MEM_DEF,
                                       (t_u8 **) & pmadapter->
                                       priv[i]);
            if (ret != MLAN_STATUS_SUCCESS || !pmadapter->priv[i]) {
                ret = MLAN_STATUS_FAILURE;
                goto error;
            }

            pmadapter->priv_num++;
            memset(pmadapter, pmadapter->priv[i], 0,
                   sizeof(mlan_private));

            pmadapter->priv[i]->adapter = pmadapter;

            /* Save bss_type, frame_type & bss_priority */
            pmadapter->priv[i]->bss_type =
                (t_u8) pmdevice->bss_attr[i].bss_type;
            pmadapter->priv[i]->frame_type =
                (t_u8) pmdevice->bss_attr[i].frame_type;
            pmadapter->priv[i]->bss_priority =
                (t_u8) pmdevice->bss_attr[i].bss_priority;
            if (pmdevice->bss_attr[i].bss_type == MLAN_BSS_TYPE_STA)
                pmadapter->priv[i]->bss_role =
                    MLAN_BSS_ROLE_STA;
            else if (pmdevice->bss_attr[i].bss_type ==
                     MLAN_BSS_TYPE_UAP)
                pmadapter->priv[i]->bss_role =
                    MLAN_BSS_ROLE_UAP;
#ifdef WIFI_DIRECT_SUPPORT
            else if (pmdevice->bss_attr[i].bss_type ==
                     MLAN_BSS_TYPE_WIFIDIRECT) {
                pmadapter->priv[i]->bss_role =
                    MLAN_BSS_ROLE_STA;
                if (pmdevice->bss_attr[i].bss_virtual)
                    pmadapter->priv[i]->bss_virtual = MTRUE;
            }
#endif
            /* Save bss_index and bss_num */
            pmadapter->priv[i]->bss_index = i;
            pmadapter->priv[i]->bss_num =
                (t_u8) pmdevice->bss_attr[i].bss_num;

            /* init function table */
            for (j = 0; mlan_ops[j]; j++) {
                if (mlan_ops[j]->bss_role ==
                        GET_BSS_ROLE(pmadapter->priv[i])) {
                    memcpy(pmadapter,
                           &pmadapter->priv[i]->ops,
                           mlan_ops[j],
                           sizeof(mlan_operations));
                }
            }
        }
    }

    /* Initialize lock variables */
    if (wlan_init_lock_list(pmadapter) != MLAN_STATUS_SUCCESS) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }

    /* Allocate memory for member of adapter structure */
    if (wlan_allocate_adapter(pmadapter)) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }

    /* Initialize timers */
    if (wlan_init_timer(pmadapter) != MLAN_STATUS_SUCCESS) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
    /* Return pointer of mlan_adapter to MOAL */
    *ppmlan_adapter = pmadapter;

    goto exit_register;

error:
    PRINTM(MINFO, "Leave mlan_register with error\n");
    /* Free timers */
    wlan_free_timer(pmadapter);
    /* Free adapter structure */
    wlan_free_adapter(pmadapter);
    /* Free lock variables */
    wlan_free_lock_list(pmadapter);
    for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
        if (pmadapter->priv[i]) {
            if (pcb->moal_vmalloc && pcb->moal_vfree)
                pcb->moal_vfree(pmadapter->pmoal_handle,
                                (t_u8 *) pmadapter->priv[i]);
            else
                pcb->moal_mfree(pmadapter->pmoal_handle,
                                (t_u8 *) pmadapter->priv[i]);
        }
    }
    if (pcb->moal_vmalloc && pcb->moal_vfree)
        pcb->moal_vfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter);
    else
        pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter);

exit_register:
    LEAVE();
    return ret;
}
/**
 *  @brief This function downloads the firmware
 *
 *  @param pmlan_adapter   A pointer to a t_void pointer to store
 *                         mlan_adapter structure pointer
 *  @param pmfw            A pointer to firmware image
 *
 *  @return                MLAN_STATUS_SUCCESS
 *                             The firmware download succeeded.
 *                         MLAN_STATUS_FAILURE
 *                             The firmware download failed.
 */
mlan_status
mlan_dnld_fw(IN t_void * pmlan_adapter, IN pmlan_fw_image pmfw)
{
    mlan_status ret = MLAN_STATUS_SUCCESS;
    mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter;
    t_u32 poll_num = 1;
    t_u32 winner = 0;

    ENTER();
    MASSERT(pmlan_adapter);

    /* Card specific probing */
    ret = wlan_sdio_probe(pmadapter);
    if (ret == MLAN_STATUS_FAILURE) {
        PRINTM(MERROR, "WLAN SDIO probe failed\n", ret);
        LEAVE();
        return ret;
    }

    /* Check if firmware is already running */
    ret = wlan_check_fw_status(pmadapter, poll_num);
    if (ret == MLAN_STATUS_SUCCESS) {
        PRINTM(MMSG, "WLAN FW already running! Skip FW download\n");
        goto done;
    }
    poll_num = MAX_FIRMWARE_POLL_TRIES;

    /* Check if other interface is downloading */
    ret = wlan_check_winner_status(pmadapter, &winner);
    if (ret == MLAN_STATUS_FAILURE) {
        PRINTM(MFATAL, "WLAN read winner status failed!\n");
        goto done;
    }
    if (winner) {
        PRINTM(MMSG,
               "WLAN is not the winner (0x%x). Skip FW download\n",
               winner);
        poll_num = MAX_MULTI_INTERFACE_POLL_TRIES;
        goto poll_fw;
    }

    if (pmfw) {
        /* Download helper/firmware */
        ret = wlan_dnld_fw(pmadapter, pmfw);
        if (ret != MLAN_STATUS_SUCCESS) {
            PRINTM(MERROR, "wlan_dnld_fw fail ret=0x%x\n", ret);
            LEAVE();
            return ret;
        }
    }

poll_fw:
    /* Check if the firmware is downloaded successfully or not */
    ret = wlan_check_fw_status(pmadapter, poll_num);
    if (ret != MLAN_STATUS_SUCCESS) {
        PRINTM(MFATAL, "FW failed to be active in time!\n");
        ret = MLAN_STATUS_FAILURE;
        LEAVE();
        return ret;
    }
done:

    /* re-enable host interrupt for mlan after fw dnld is successful */
    wlan_enable_host_int(pmadapter);

    LEAVE();
    return ret;
}
Exemple #3
0
/**
 *  @brief This function registers MOAL to MLAN module.
 *  
 *  @param pmdevice        A pointer to a mlan_device structure
 *                         allocated in MOAL
 *  @param ppmlan_adapter  A pointer to a t_void pointer to store
 *                         mlan_adapter structure pointer as the context
 *
 *  @return                MLAN_STATUS_SUCCESS
 *                             The registration succeeded.
 *                         MLAN_STATUS_FAILURE
 *                             The registration failed.
 *
 * mlan_status mlan_register (
 *   IN pmlan_device     pmdevice,
 *   OUT t_void          **ppmlan_adapter
 * );
 *
 * Comments
 *   MOAL constructs mlan_device data structure to pass moal_handle and
 *   mlan_callback table to MLAN. MLAN returns mlan_adapter pointer to
 *   the ppmlan_adapter buffer provided by MOAL.
 * Headers:
 *   declared in mlan_decl.h
 * See Also
 *   mlan_unregister
 */
mlan_status
mlan_register(IN pmlan_device pmdevice, OUT t_void ** ppmlan_adapter)
{
    mlan_status ret = MLAN_STATUS_SUCCESS;
    pmlan_adapter pmadapter = MNULL;
    pmlan_callbacks pcb = MNULL;
    t_u8 i = 0;
    t_u32 j = 0;

    MASSERT(pmdevice);
    MASSERT(ppmlan_adapter);
    MASSERT(pmdevice->callbacks.moal_print);
#ifdef DEBUG_LEVEL1
    print_callback = pmdevice->callbacks.moal_print;
#endif
    assert_callback = pmdevice->callbacks.moal_assert;

    ENTER();

    MASSERT(pmdevice->callbacks.moal_malloc);
    MASSERT(pmdevice->callbacks.moal_memset);
    MASSERT(pmdevice->callbacks.moal_memmove);

    /* Allocate memory for adapter structure */
    if ((pmdevice->callbacks.
         moal_malloc(pmdevice->pmoal_handle, sizeof(mlan_adapter), MLAN_MEM_DEF,
                     (t_u8 **) & pmadapter) != MLAN_STATUS_SUCCESS)
        || !pmadapter) {
        ret = MLAN_STATUS_FAILURE;
        goto exit_register;
    }

    pmdevice->callbacks.moal_memset(pmadapter, pmadapter,
                                    0, sizeof(mlan_adapter));

    pcb = &pmadapter->callbacks;

    /* Save callback functions */
    pmdevice->callbacks.moal_memmove(pmadapter->pmoal_handle, pcb,
                                     &pmdevice->callbacks,
                                     sizeof(mlan_callbacks));

    /* Assertion for all callback functions */
    MASSERT(pcb->moal_init_fw_complete);
    MASSERT(pcb->moal_shutdown_fw_complete);
    MASSERT(pcb->moal_send_packet_complete);
    MASSERT(pcb->moal_recv_packet);
    MASSERT(pcb->moal_recv_event);
    MASSERT(pcb->moal_ioctl_complete);
    MASSERT(pcb->moal_write_reg);
    MASSERT(pcb->moal_read_reg);
    MASSERT(pcb->moal_alloc_mlan_buffer);
    MASSERT(pcb->moal_free_mlan_buffer);
    MASSERT(pcb->moal_write_data_sync);
    MASSERT(pcb->moal_read_data_sync);
    MASSERT(pcb->moal_mfree);
    MASSERT(pcb->moal_memcpy);
    MASSERT(pcb->moal_memcmp);
    MASSERT(pcb->moal_get_system_time);
    MASSERT(pcb->moal_init_timer);
    MASSERT(pcb->moal_free_timer);
    MASSERT(pcb->moal_start_timer);
    MASSERT(pcb->moal_stop_timer);
    MASSERT(pcb->moal_init_lock);
    MASSERT(pcb->moal_free_lock);
    MASSERT(pcb->moal_spin_lock);
    MASSERT(pcb->moal_spin_unlock);

    /* Save pmoal_handle */
    pmadapter->pmoal_handle = pmdevice->pmoal_handle;
    if ((pmdevice->int_mode == INT_MODE_GPIO) && (pmdevice->gpio_pin == 0)) {
        PRINTM(MERROR, "SDIO_GPIO_INT_CONFIG: Invalid GPIO Pin\n");
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
    pmadapter->init_para.int_mode = pmdevice->int_mode;
    pmadapter->init_para.gpio_pin = pmdevice->gpio_pin;
    /* card specific probing has been deferred until now .. */
    if (MLAN_STATUS_SUCCESS != (ret = wlan_sdio_probe(pmadapter))) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
#ifdef MFG_CMD_SUPPORT
    pmadapter->init_para.mfg_mode = pmdevice->mfg_mode;
#endif
#ifdef SDIO_MULTI_PORT_TX_AGGR
    pmadapter->init_para.mpa_tx_cfg = pmdevice->mpa_tx_cfg;
#endif
#ifdef SDIO_MULTI_PORT_RX_AGGR
    pmadapter->init_para.mpa_rx_cfg = pmdevice->mpa_rx_cfg;
#endif
    pmadapter->init_para.auto_ds = pmdevice->auto_ds;
    pmadapter->init_para.ps_mode = pmdevice->ps_mode;
    if (pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_2K ||
        pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_4K ||
        pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_8K)
        pmadapter->init_para.max_tx_buf = pmdevice->max_tx_buf;

    for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
        pmadapter->priv[i] = MNULL;
        if (pmdevice->bss_attr[i].active == MTRUE) {
            /* For valid bss_attr, allocate memory for private structure */
            if ((pcb->
                 moal_malloc(pmadapter->pmoal_handle, sizeof(mlan_private),
                             MLAN_MEM_DEF,
                             (t_u8 **) & pmadapter->priv[i]) !=
                 MLAN_STATUS_SUCCESS)
                || !pmadapter->priv[i]) {
                ret = MLAN_STATUS_FAILURE;
                goto error;
            }

            memset(pmadapter, pmadapter->priv[i], 0, sizeof(mlan_private));

            pmadapter->priv[i]->adapter = pmadapter;

            /* Save bss_type, frame_type & bss_priority */
            pmadapter->priv[i]->bss_type =
                (t_u8) pmdevice->bss_attr[i].bss_type;
            pmadapter->priv[i]->frame_type =
                (t_u8) pmdevice->bss_attr[i].frame_type;
            pmadapter->priv[i]->bss_priority =
                (t_u8) pmdevice->bss_attr[i].bss_priority;

            /* Save bss_index and bss_num */
            pmadapter->priv[i]->bss_index = i;
            pmadapter->priv[i]->bss_num = (t_u8) pmdevice->bss_attr[i].bss_num;

            /* init function table */
            for (j = 0; j < (sizeof(ops) / sizeof(ops[0])); j++) {
                if (ops[j].bss_type == pmadapter->priv[i]->bss_type) {
                    memcpy(pmadapter, &pmadapter->priv[i]->ops, &ops[j],
                           sizeof(mlan_operations));
                }
            }
        }
    }

    /* Initialize locks */
    if (pcb->moal_init_lock(pmadapter->pmoal_handle, &pmadapter->pmlan_lock)
        != MLAN_STATUS_SUCCESS) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
    if (pcb->moal_init_lock(pmadapter->pmoal_handle, &pmadapter->pint_lock)
        != MLAN_STATUS_SUCCESS) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
    if (pcb->
        moal_init_lock(pmadapter->pmoal_handle, &pmadapter->pmain_proc_lock)
        != MLAN_STATUS_SUCCESS) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
    if (pcb->moal_init_lock(pmadapter->pmoal_handle, &pmadapter->pmlan_cmd_lock)
        != MLAN_STATUS_SUCCESS) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }

    if (pcb->
        moal_init_timer(pmadapter->pmoal_handle, &pmadapter->pmlan_cmd_timer,
                        wlan_cmd_timeout_func, pmadapter)
        != MLAN_STATUS_SUCCESS) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
    /* Return pointer of mlan_adapter to MOAL */
    *ppmlan_adapter = pmadapter;

    goto exit_register;

  error:
    PRINTM(MINFO, "Leave mlan_register with error\n");
    /* Free resources */
    if (pmadapter->pmlan_cmd_timer)
        pcb->moal_free_timer(pmadapter->pmoal_handle,
                             pmadapter->pmlan_cmd_timer);
    if (pmadapter->pmlan_cmd_lock)
        pcb->moal_free_lock(pmadapter->pmoal_handle, pmadapter->pmlan_cmd_lock);
    if (pmadapter->pmain_proc_lock)
        pcb->moal_free_lock(pmadapter->pmoal_handle,
                            pmadapter->pmain_proc_lock);
    if (pmadapter->pint_lock)
        pcb->moal_free_lock(pmadapter->pmoal_handle, pmadapter->pint_lock);
    if (pmadapter->pmlan_lock)
        pcb->moal_free_lock(pmadapter->pmoal_handle, pmadapter->pmlan_lock);
    for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
        if (pmadapter->priv[i])
            pcb->moal_mfree(pmadapter->pmoal_handle,
                            (t_u8 *) pmadapter->priv[i]);
    }
    pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter);

  exit_register:
    LEAVE();
    return ret;
}