/** * @brief Use index to get the data rate * * @param pmadapter A pointer to mlan_adapter structure * @param index The index of data rate * @param ht_info HT info * * @return Data rate or 0 */ t_u32 wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index, t_u8 ht_info) { #define MCS_NUM_SUPP 8 t_u16 mcs_num_supp = MCS_NUM_SUPP; t_u16 mcs_rate[4][MCS_NUM_SUPP] = { {0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e} , /* LG 40M */ {0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c} , /* SG 40M */ {0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82} , /* LG 20M */ {0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90} }; /* SG 20M */ t_u32 rate = 0; ENTER(); if (ht_info & MBIT(0)) { if (index == MLAN_RATE_BITMAP_MCS0) { if (ht_info & MBIT(2)) rate = 0x0D; /* MCS 32 SGI rate */ else rate = 0x0C; /* MCS 32 LGI rate */ } else if (index < mcs_num_supp) { if (ht_info & MBIT(1)) { if (ht_info & MBIT(2)) rate = mcs_rate[1][index]; /* SGI, 40M */ else rate = mcs_rate[0][index]; /* LGI, 40M */ } else { if (ht_info & MBIT(2)) rate = mcs_rate[3][index]; /* SGI, 20M */ else rate = mcs_rate[2][index]; /* LGI, 20M */ } } else rate = WlanDataRates[0]; } else { /* 11n non HT rates */ if (index >= WLAN_SUPPORTED_RATES_EXT) index = 0; rate = WlanDataRates[index]; } LEAVE(); return rate; }
/** * @brief Check the STA is 40 MHz intolerant or not * @param intol Flag: TRUE when the STA is 40 MHz intolerant, otherwise FALSE * @return MLAN_STATUS_SUCCESS--success, otherwise--fail */ int is_intolerant_sta(int *intol) { struct iwreq iwr; int ret = MLAN_STATUS_SUCCESS; int ioctl_val, subioctl_val, htcap_info; *intol = FALSE; if (get_priv_ioctl("htcapinfo", &ioctl_val, &subioctl_val) == MLAN_STATUS_FAILURE) { return -EOPNOTSUPP; } memset(&iwr, 0, sizeof(iwr)); strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); iwr.u.data.pointer = &htcap_info; iwr.u.data.length = 0; iwr.u.data.flags = subioctl_val; if (ioctl(sockfd, ioctl_val, &iwr)) { fprintf(stderr, "mlan2040coex: private command 'htcapinfo' is not supported by %s\n", dev_name); ret = MLAN_STATUS_FAILURE; } if (htcap_info & MBIT(8)) *intol = TRUE; return ret; }
//-------------------------------------------------------------------------------------------------------------------------- MDIN_ERROR_t MDIN3xx_EnableDeintCCS(PMDIN_VIDEO_INFO pINFO, BOOL OnOff) { PMDIN_DEINTCTL_INFO pIPC = (PMDIN_DEINTCTL_INFO)&pINFO->stIPC_m; BOOL pal = (pIPC->attb&MDIN_DEINT_PAL_CCS)? 1 : 0; if (OnOff) pIPC->fine |= MDIN_DEINT_CCS_ON; else pIPC->fine &= ~MDIN_DEINT_CCS_ON; // if progressive input, ccs_en = off if ((pIPC->attb&MDIN_DEINT_IPC_PROC)==0) OnOff = OFF; // if 1080i input, ccs_en = off if (pIPC->attb&MDIN_DEINT_HD_1080i) OnOff = OFF; if (MDINHIF_RegField(MDIN_LOCAL_ID, 0x248, 14, 1, MBIT(OnOff,1))) return MDIN_I2C_ERROR; if (MDINHIF_RegField(MDIN_LOCAL_ID, 0x205, 5, 1, MBIT(OnOff,pal))) return MDIN_I2C_ERROR; return MDIN_NO_ERROR; }
//-------------------------------------------------------------------------------------------------------------------------- MDIN_ERROR_t MDIN3xx_EnableDeintCUE(PMDIN_VIDEO_INFO pINFO, BOOL OnOff) { PMDIN_DEINTCTL_INFO pIPC = (PMDIN_DEINTCTL_INFO)&pINFO->stIPC_m; WORD rVal; if (OnOff) pIPC->fine |= MDIN_DEINT_CUE_ON; else pIPC->fine &= ~MDIN_DEINT_CUE_ON; // if ycbcr444_en==1 and progressive input, cue_en = off if ((pIPC->attb&MDIN_DEINT_444_PROC)&&(pIPC->attb&MDIN_DEINT_IPC_PROC)==0) OnOff = OFF; // if pal_ccs_en==1, cue_en = off if (MDINHIF_RegRead(MDIN_LOCAL_ID, 0x205, &rVal)) return MDIN_I2C_ERROR; if (rVal&0x0020) OnOff = OFF; if (MDINHIF_RegField(MDIN_LOCAL_ID, 0x208, 5, 1, MBIT(OnOff,1))) return MDIN_I2C_ERROR; return MDIN_NO_ERROR; }
//-------------------------------------------------------------------------------------------------------------------------- MDIN_ERROR_t MDIN3xx_EnableDeint3DNR(PMDIN_VIDEO_INFO pINFO, BOOL OnOff) { PMDIN_DEINTCTL_INFO pIPC = (PMDIN_DEINTCTL_INFO)&pINFO->stIPC_m; PMDIN_SRCVIDEO_INFO pSRC = (PMDIN_SRCVIDEO_INFO)&pINFO->stSRC_m; // added on 16Aug2012 PMDIN_OUTVIDEO_INFO pOUT = (PMDIN_OUTVIDEO_INFO)&pINFO->stOUT_m; // added on 20Mar2012 // PMDIN_MFCSCALE_INFO pMFC = (PMDIN_MFCSCALE_INFO)&pINFO->stMFC_m; // BYTE mode = (pIPC->fine&MDIN_DEINT_FRC_DOWN)? 1 : 0; BYTE mode = ((pIPC->attb&MDIN_DEINT_IPC_PROC)&&(pIPC->fine&MDIN_DEINT_FRC_DOWN))? 1 : 0; // modified on 05Apr2012 if (OnOff) pIPC->fine |= MDIN_DEINT_3DNR_ON; else pIPC->fine &= ~MDIN_DEINT_3DNR_ON; // if ycbcr444_en==1 and progressive input, 3dnr_en = off if ((pIPC->attb&MDIN_DEINT_444_PROC)&&(pIPC->attb&MDIN_DEINT_IPC_PROC)==0) OnOff = OFF; // if 1080p input and dual output, 3dnr_en = off if (pIPC->attb&MDIN_DEINT_HD_1080p&&pINFO->dacPATH==DAC_PATH_AUX_OUT) OnOff = OFF; // for 2-HD input mode if (pINFO->dacPATH==DAC_PATH_AUX_2HD) OnOff = OFF; // if vertical scale ratio<0.5, 3dnr_en = off if (pIPC->attb&MDIN_DEINT_p5_SCALE) OnOff = OFF; // if revision=0 and vertical scale ratio<1.0 and progressive input, 3dnr_en = off if ((mdinREV==0)&& (pIPC->attb&MDIN_DEINT_DN_SCALE)&&(pIPC->attb&MDIN_DEINT_IPC_PROC)==0) OnOff = OFF; if (pIPC->attb&MDIN_DEINT_HD_1080i&& (pOUT->frmt==VIDOUT_1920x1080i59||pOUT->frmt==VIDOUT_1920x1080i60)) OnOff = OFF; // added on 20Mar2012 if (pIPC->attb&MDIN_DEINT_HD_1080p&& (pOUT->frmt==VIDOUT_1920x1080i50||pOUT->frmt==VIDOUT_1920x1080i59||pOUT->frmt==VIDOUT_1920x1080i60)) OnOff = OFF; // added on 20Mar2012 // prepare for timing problem when 10bit process use (refer to MDIN3xx_Set10BITProcess()) // if ((pIPC->attb&MDIN_DEINT_IPC_PROC)==0&&pMFC->stMEM.h==1080&&pMFC->stDST.h==576) OnOff = OFF; // prepare for timing problem when 10bit process use (refer to MDIN3xx_Set10BITProcess()) // if ((pIPC->attb&MDIN_DEINT_HD_1080i)&&(pSRC->stATTB.attb==MDIN_PRECISION_10)) OnOff = OFF; // added on 16Aug2012 // if 1080p input, 3dnr_en = off #if !defined(SYSTEM_USE_MCLK202) if (pIPC->attb&MDIN_DEINT_HD_1080p) OnOff = OFF; #endif if (pSRC->frmt==VIDSRC_1920x1200p60) OnOff = OFF; // added on 26Nov2012 // common_mode_at_IPC - nr_t_en if (MDINHIF_RegField(MDIN_LOCAL_ID, 0x205, 0, 1, (OnOff)? mode : 0)) return MDIN_I2C_ERROR; // nr_mode_reg - nr_en, nr_write_en if (MDINHIF_RegField(MDIN_LOCAL_ID, 0x260, 10, 1, MBIT(OnOff,1))) return MDIN_I2C_ERROR; if (MDINHIF_RegField(MDIN_LOCAL_ID, 0x260, 12, 1, MBIT(OnOff,1))) return MDIN_I2C_ERROR; // nr_motion_set_reg - nr_mo_sel, nr_all_use_mo if (MDINHIF_RegField(MDIN_LOCAL_ID, 0x261, 6, 2, (OnOff)? 2 : 3)) return MDIN_I2C_ERROR; if (MDINHIF_RegField(MDIN_LOCAL_ID, 0x261, 0, 1, MBIT(OnOff,1))) return MDIN_I2C_ERROR; // nr_motion_offset_reg - cu_motion_use, n_motion_use, slow_motion_use, still_motion_use if (MDINHIF_RegField(MDIN_LOCAL_ID, 0x262, 15, 1, MBIT(OnOff,1))) return MDIN_I2C_ERROR; if (MDINHIF_RegField(MDIN_LOCAL_ID, 0x262, 14, 1, MBIT(OnOff,1))) return MDIN_I2C_ERROR; if (MDINHIF_RegField(MDIN_LOCAL_ID, 0x262, 13, 1, MBIT(OnOff,1))) return MDIN_I2C_ERROR; if (MDINHIF_RegField(MDIN_LOCAL_ID, 0x262, 12, 1, MBIT(OnOff,1))) return MDIN_I2C_ERROR; // mo_history_for_nr_condition - nr_mo_his_update_use_en if (MDINHIF_RegField(MDIN_LOCAL_ID, 0x266, 11, 1, MBIT(OnOff,1))) return MDIN_I2C_ERROR; // border_ctrl_reg1 - no_his_border_adp_en if (MDINHIF_RegField(MDIN_LOCAL_ID, 0x240, 13, 1, MBIT(OnOff,1))) return MDIN_I2C_ERROR; // set progressive NR scale down if (MDIN3xx_ScaleDownProgNR(pINFO, OnOff)) return MDIN_NO_ERROR; // if 3dnr_en=off & progressive input, mfc_prepend_load = OFF OnOff = ((OnOff==OFF)&&((pIPC->attb&MDIN_DEINT_IPC_PROC)==0))? OFF : ON; if (MDINHIF_RegField(MDIN_LOCAL_ID, 0x100, 6, 1, MBIT(OnOff,1))) return MDIN_I2C_ERROR; // set ultraNR => if 3dnr_en=on & 3dnr_gain>50, ultraNR = ON return MDIN3xx_SetDeintUltraNR((pIPC->gain>50)? ON : OFF); }
/** * @brief Register the device with cfg80211 * * @param dev A pointer to net_device structure * @param bss_type BSS type * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status woal_register_uap_cfg80211(struct net_device * dev, t_u8 bss_type) { mlan_status ret = MLAN_STATUS_SUCCESS; moal_private *priv = (moal_private *) netdev_priv(dev); void *wdev_priv = NULL; struct wireless_dev *wdev = NULL; mlan_fw_info fw_info; ENTER(); /* Allocate wireless device */ wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); if (!wdev) { PRINTM(MERROR, "Could not allocate wireless device\n"); ret = MLAN_STATUS_FAILURE; goto err_wdev; } /* Allocate wiphy */ wdev->wiphy = wiphy_new(&woal_cfg80211_uap_ops, sizeof(moal_private *)); if (!wdev->wiphy) { PRINTM(MERROR, "Could not allocate wiphy device\n"); ret = MLAN_STATUS_FAILURE; goto err_wdev; } if (bss_type == MLAN_BSS_TYPE_UAP) { dev_set_name(&wdev->wiphy->dev, dev->name); wdev->iftype = NL80211_IFTYPE_AP; wdev->wiphy->interface_modes = MBIT(NL80211_IFTYPE_AP) | MBIT(NL80211_IFTYPE_STATION) | 0; wdev->wiphy->max_scan_ssids = 10; } /* Make this wiphy known to this driver only */ wdev->wiphy->privid = mrvl_wiphy_privid; /* Supported bands */ wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &cfg80211_band_2ghz; if (MLAN_STATUS_SUCCESS == woal_request_get_fw_info(priv, MOAL_CMD_WAIT, &fw_info)) { if (fw_info.fw_bands & BAND_A) wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &cfg80211_band_5ghz; } /* Initialize cipher suits */ wdev->wiphy->cipher_suites = cfg80211_cipher_suites; wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cfg80211_cipher_suites); wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; /* We are using custom domains */ wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; wdev->wiphy->reg_notifier = NULL; // TODO: woal_cfg80211_reg_notifier; /* Set moal_private pointer in wiphy_priv */ wdev_priv = wiphy_priv(wdev->wiphy); *(unsigned long *) wdev_priv = (unsigned long) priv; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) || defined(COMPAT_WIRELESS) set_wiphy_dev(wdev->wiphy, (struct device *) priv->phandle->hotplug_device); #endif if (wiphy_register(wdev->wiphy) < 0) { PRINTM(MERROR, "Wiphy device registration failed!\n"); ret = MLAN_STATUS_FAILURE; goto err_wdev; } dev_net_set(dev, wiphy_net(wdev->wiphy)); dev->ieee80211_ptr = wdev; SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); priv->wdev = wdev; if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Wiphy device registration failed!\n"); } else { PRINTM(MINFO, "Successfully registered wiphy device\n"); LEAVE(); return ret; } wiphy_unregister(wdev->wiphy); err_wdev: dev->ieee80211_ptr = NULL; if (wdev && wdev->wiphy) wiphy_free(wdev->wiphy); kfree(wdev); LEAVE(); return ret; }
/** * @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; t_u32 firmwarelen = pmfw->fw_len; t_u32 offset = 0; t_u32 base0, base1; t_void *tmpfwbuf = MNULL; t_u32 tmpfwbufsz; t_u8 *fwbuf; mlan_buffer mbuf; t_u16 len = 0; t_u32 txlen = 0, tx_blocks = 0, tries = 0; t_u32 i = 0; t_u8 crc_buffer = 0; t_u8 *header_crc_fw; t_u8 header_crc_fw_len = 0; header_crc_fw = fw_crc_header_rb; header_crc_fw_len = FW_CRC_HEADER_RB; ENTER(); if (!firmware && !pcb->moal_get_fw_data) { PRINTM(MMSG, "No firmware image found! Terminating download\n"); LEAVE(); return MLAN_STATUS_FAILURE; } PRINTM(MINFO, "WLAN: Downloading FW image (%d bytes)\n", firmwarelen); tmpfwbufsz = ALIGN_SZ(WLAN_UPLD_SIZE, DMA_ALIGNMENT); ret = pcb->moal_malloc(pmadapter->pmoal_handle, tmpfwbufsz, MLAN_MEM_DEF | MLAN_MEM_DMA, (t_u8 **) & tmpfwbuf); if ((ret != MLAN_STATUS_SUCCESS) || !tmpfwbuf) { PRINTM(MERROR, "Unable to allocate buffer for firmware. Terminating download\n"); ret = MLAN_STATUS_FAILURE; goto done; } memset(pmadapter, tmpfwbuf, 0, tmpfwbufsz); /* Ensure 8-byte aligned firmware buffer */ fwbuf = (t_u8 *) ALIGN_ADDR(tmpfwbuf, DMA_ALIGNMENT); if (!pmadapter->init_para.fw_crc_check) { /* CRC check not required, use custom header first */ firmware = header_crc_fw; firmwarelen = header_crc_fw_len; crc_buffer = 1; } /* Perform firmware data transfer */ do { /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */ ret = wlan_sdio_poll_card_status(pmadapter, CARD_IO_READY | DN_LD_CARD_RDY); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MFATAL, "WLAN: FW download with helper poll status timeout @ %d\n", offset); goto done; } if (!crc_buffer) /* More data? */ if (firmwarelen && offset >= firmwarelen) break; for (tries = 0; tries < MAX_POLL_TRIES; tries++) { ret = pcb->moal_read_reg(pmadapter->pmoal_handle, READ_BASE_0_REG, &base0); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Dev BASE0 register read failed:" " base0=0x%04X(%d). Terminating download\n", base0, base0); goto done; } ret = pcb->moal_read_reg(pmadapter->pmoal_handle, READ_BASE_1_REG, &base1); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Dev BASE1 register read failed:" " base1=0x%04X(%d). Terminating download\n", base1, base1); goto done; } len = (t_u16) (((base1 & 0xff) << 8) | (base0 & 0xff)); if (len) break; wlan_udelay(pmadapter, 10); } if (!len) break; else if (len > WLAN_UPLD_SIZE) { PRINTM(MFATAL, "WLAN: FW download failure @ %d, invalid length %d\n", offset, len); ret = MLAN_STATUS_FAILURE; goto done; } txlen = len; if (len & MBIT(0)) { i++; if (i > MAX_WRITE_IOMEM_RETRY) { PRINTM(MFATAL, "WLAN: FW download failure @ %d, over max retry count\n", offset); ret = MLAN_STATUS_FAILURE; goto done; } PRINTM(MERROR, "WLAN: FW CRC error indicated by the helper:" " len = 0x%04X, txlen = %d\n", len, txlen); len &= ~MBIT(0); PRINTM(MERROR, "WLAN: retry: %d, offset %d\n", i, offset); DBG_HEXDUMP(MERROR, "WLAN: FW block:", mbuf.pbuf, len); /* Setting this to 0 to resend from same offset */ txlen = 0; } else { i = 0; /* Set blocksize to transfer - checking for last block */ if (firmwarelen && firmwarelen - offset < txlen) { txlen = firmwarelen - offset; } PRINTM(MINFO, "."); tx_blocks = (txlen + MLAN_SDIO_BLOCK_SIZE_FW_DNLD - 1) / MLAN_SDIO_BLOCK_SIZE_FW_DNLD; /* Copy payload to buffer */ if (firmware) memmove(pmadapter, fwbuf, &firmware[offset], txlen); else pcb->moal_get_fw_data(pmadapter->pmoal_handle, offset, txlen, fwbuf); } /* Send data */ memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer)); mbuf.pbuf = (t_u8 *) fwbuf; mbuf.data_len = tx_blocks * MLAN_SDIO_BLOCK_SIZE_FW_DNLD; ret = pcb->moal_write_data_sync(pmadapter->pmoal_handle, &mbuf, pmadapter->ioport, 0); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "WLAN: FW download, write iomem (%d) failed @ %d\n", i, offset); if (pcb-> moal_write_reg(pmadapter->pmoal_handle, HOST_TO_CARD_EVENT_REG, HOST_TERM_CMD53) != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "write CFG reg failed\n"); } ret = MLAN_STATUS_FAILURE; goto done; } offset += txlen; if (crc_buffer && offset >= header_crc_fw_len) { /* Custom header download complete, restore original FW */ offset = 0; firmware = pmfw->pfw_buf; firmwarelen = pmfw->fw_len; crc_buffer = 0; } } while (MTRUE); PRINTM(MMSG, "Wlan: FW download over, firmwarelen=%d downloaded %d\n", firmwarelen, offset); ret = MLAN_STATUS_SUCCESS; done: if (tmpfwbuf) pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) tmpfwbuf); LEAVE(); return ret; }