diff --git a/driver/openofdm_tx/openofdm_tx.c b/driver/openofdm_tx/openofdm_tx.c index 8cb33ce..d9b5f1f 100644 --- a/driver/openofdm_tx/openofdm_tx.c +++ b/driver/openofdm_tx/openofdm_tx.c @@ -85,7 +85,7 @@ static inline u32 hw_init(enum openofdm_tx_mode mode){ for (i=0;i<8;i++) openofdm_tx_api->OPENOFDM_TX_REG_MULTI_RST_write(0); - openofdm_tx_api->OPENOFDM_TX_REG_INIT_PILOT_STATE_write(0x7E); + openofdm_tx_api->OPENOFDM_TX_REG_INIT_PILOT_STATE_write(0x7F); openofdm_tx_api->OPENOFDM_TX_REG_INIT_DATA_STATE_write(0x7F); printk("%s hw_init err %d\n", openofdm_tx_compatible_str, err); diff --git a/driver/sdr.c b/driver/sdr.c index f791045..2410677 100644 --- a/driver/sdr.c +++ b/driver/sdr.c @@ -313,7 +313,7 @@ static irqreturn_t openwifi_rx_interrupt(int irq, void *dev_id) struct ieee80211_rx_status rx_status = {0}; struct sk_buff *skb; struct ieee80211_hdr *hdr; - u32 addr1_low32=0, addr2_low32=0, addr3_low32=0, len, rate_idx, tsft_low, tsft_high, loop_count=0, ht_flag;//;//, fc_di; + u32 addr1_low32=0, addr2_low32=0, addr3_low32=0, len, rate_idx, tsft_low, tsft_high, loop_count=0, ht_flag, short_gi;//, fc_di; // u32 dma_driver_buf_idx_mod; u8 *pdata_tmp, fcs_ok, target_buf_idx;//, phy_rx_sn_hw; s8 signal; @@ -337,6 +337,8 @@ static irqreturn_t openwifi_rx_interrupt(int irq, void *dev_id) len_overflow = (len>(RX_BD_BUF_SIZE-16)?true:false); rate_idx = (*((u16*)(pdata_tmp+14))); + short_gi = ((rate_idx&0x20)!=0); + rate_idx = (rate_idx&0xDF); fcs_ok = ( len_overflow?0:(*(( u8*)(pdata_tmp+16+len-1))) ); @@ -345,9 +347,8 @@ static irqreturn_t openwifi_rx_interrupt(int irq, void *dev_id) // dma_driver_buf_idx_mod = (state.residue&0x7f); fcs_ok = ((fcs_ok&0x80)!=0); ht_flag = ((rate_idx&0x10)!=0); - rate_idx = (rate_idx&0xF); - if ( (len>=14 && (!len_overflow)) && (rate_idx>=8 && rate_idx<=15)) { + if ( (len>=14 && (!len_overflow)) && (rate_idx>=8 && rate_idx<=23)) { // if ( phy_rx_sn_hw!=dma_driver_buf_idx_mod) { // printk("%s openwifi_rx_interrupt: WARNING sn %d next buf_idx %d!\n", sdr_compatible_str,phy_rx_sn_hw,dma_driver_buf_idx_mod); // } @@ -386,7 +387,7 @@ static irqreturn_t openwifi_rx_interrupt(int irq, void *dev_id) sc = hdr->seq_ctrl; if ( addr1_low32!=0xffffffff || addr1_high16!=0xffff ) - printk("%s openwifi_rx_interrupt:%4dbytes ht%d %2dM FC%04x DI%04x addr1/2/3:%04x%08x/%04x%08x/%04x%08x SC%04x fcs%d buf_idx%d %ddBm\n", sdr_compatible_str, + printk("%s openwifi_rx_interrupt:%4dbytes ht%d %3dM FC%04x DI%04x addr1/2/3:%04x%08x/%04x%08x/%04x%08x SC%04x fcs%d buf_idx%d %ddBm\n", sdr_compatible_str, len, ht_flag, wifi_rate_table[rate_idx], hdr->frame_control, hdr->duration_id, reverse16(addr1_high16), reverse32(addr1_low32), reverse16(addr2_high16), reverse32(addr2_low32), reverse16(addr3_high16), reverse32(addr3_low32), sc, fcs_ok, target_buf_idx_old, signal); @@ -408,8 +409,13 @@ static irqreturn_t openwifi_rx_interrupt(int irq, void *dev_id) rx_status.flag |= RX_FLAG_MACTIME_START; if (!fcs_ok) rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; - rx_status.encoding = RX_ENC_LEGACY; + if (rate_idx <= 15) + rx_status.encoding = RX_ENC_LEGACY; + else + rx_status.encoding = RX_ENC_HT; rx_status.bw = RATE_INFO_BW_20; + if (short_gi) + rx_status.enc_flags |= RX_ENC_FLAG_SHORT_GI; memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); // put rx_status into skb->cb, from now on skb->cb is not dma_dsts any more. ieee80211_rx_irqsafe(dev, skb); // call mac80211 function @@ -469,7 +475,7 @@ static irqreturn_t openwifi_tx_interrupt(int irq, void *dev_id) } } - if ( ((*(u32*)(&(skb->data[0])))&0xFF000000) || (*(u32*)(&(skb->data[12]))) || (*(u32*)(&(skb->data[8]))) || (*(u32*)(&(skb->data[4]))) ) { + if ( (*(u32*)(&(skb->data[4]))) || ((*(u32*)(&(skb->data[12])))&0xFFFF0000) ) { printk("%s openwifi_tx_interrupt: WARNING %08x %08x %08x %08x\n", sdr_compatible_str, *(u32*)(&(skb->data[12])), *(u32*)(&(skb->data[8])), *(u32*)(&(skb->data[4])), *(u32*)(&(skb->data[0]))); continue; } @@ -522,18 +528,56 @@ u32 gen_parity(u32 v){ return (v >> 28) & 1; } -u32 calc_phy_header(u8 rate_hw_value, u32 len, u8 *bytes){ +u8 gen_ht_sig_crc(u64 m) +{ + u8 i, temp, c[8] = {1, 1, 1, 1, 1, 1, 1, 1}, ht_sig_crc; + + for (i = 0; i < 34; i++) + { + temp = c[7] ^ ((m >> i) & 0x01); + + c[7] = c[6]; + c[6] = c[5]; + c[5] = c[4]; + c[4] = c[3]; + c[3] = c[2]; + c[2] = c[1] ^ temp; + c[1] = c[0] ^ temp; + c[0] = temp; + } + ht_sig_crc = ((~c[7] & 0x01) << 0) | ((~c[6] & 0x01) << 1) | ((~c[5] & 0x01) << 2) | ((~c[4] & 0x01) << 3) | ((~c[3] & 0x01) << 4) | ((~c[2] & 0x01) << 5) | ((~c[1] & 0x01) << 6) | ((~c[0] & 0x01) << 7); + + return ht_sig_crc; +} + +u32 calc_phy_header(u8 rate_hw_value, bool use_ht_rate, bool use_short_gi, u32 len, u8 *bytes){ //u32 signal_word = 0 ; - u8 SIG_RATE = 0 ; + u8 SIG_RATE = 0, HT_SIG_RATE; u8 len_2to0, len_10to3, len_msb,b0,b1,b2, header_parity ; + u32 l_len, ht_len, ht_sig1, ht_sig2; - // rate_hw_value = (rate_hw_value<=4?0:(rate_hw_value-4)); - // SIG_RATE = wifi_mcs_table_phy_tx[rate_hw_value]; - SIG_RATE = wifi_mcs_table_11b_force_up[rate_hw_value]; + // printk("rate_hw_value=%u\tuse_ht_rate=%u\tuse_short_gi=%u\tlen=%u\n", rate_hw_value, use_ht_rate, use_short_gi, len); - len_2to0 = len & 0x07 ; - len_10to3 = (len >> 3 ) & 0xFF ; - len_msb = (len >> 11) & 0x01 ; + // HT-mixed mode ht signal + + if(use_ht_rate) + { + SIG_RATE = wifi_mcs_table_11b_force_up[4]; + HT_SIG_RATE = rate_hw_value; + l_len = 24 * len / wifi_n_dbps_ht_table[rate_hw_value]; + ht_len = len; + } + else + { + // rate_hw_value = (rate_hw_value<=4?0:(rate_hw_value-4)); + // SIG_RATE = wifi_mcs_table_phy_tx[rate_hw_value]; + SIG_RATE = wifi_mcs_table_11b_force_up[rate_hw_value]; + l_len = len; + } + + len_2to0 = l_len & 0x07 ; + len_10to3 = (l_len >> 3 ) & 0xFF ; + len_msb = (l_len >> 11) & 0x01 ; b0=SIG_RATE | (len_2to0 << 5) ; b1 = len_10to3 ; @@ -544,9 +588,30 @@ u32 calc_phy_header(u8 rate_hw_value, u32 len, u8 *bytes){ bytes[0] = b0 ; bytes[1] = b1 ; bytes[2] = b2; - //signal_word = b0+(b1<<8)+(b2<<16) ; - //return signal_word; - return(SIG_RATE); + + // HT-mixed mode signal + if(use_ht_rate) + { + ht_sig1 = (HT_SIG_RATE & 0x7F) | ((ht_len << 8) & 0xFFFF00); + ht_sig2 = 0x04 | (use_short_gi << 7); + ht_sig2 = ht_sig2 | (gen_ht_sig_crc(ht_sig1 | ht_sig2 << 24) << 10); + + bytes[3] = 1; + bytes[8] = (ht_sig1 & 0xFF); + bytes[9] = (ht_sig1 >> 8) & 0xFF; + bytes[10] = (ht_sig1 >> 16) & 0xFF; + bytes[11] = (ht_sig2 & 0xFF); + bytes[12] = (ht_sig2 >> 8) & 0xFF; + bytes[13] = (ht_sig2 >> 16) & 0xFF; + + return(HT_SIG_RATE); + } + else + { + //signal_word = b0+(b1<<8)+(b2<<16) ; + //return signal_word; + return(SIG_RATE); + } } static inline struct gpio_led_data * //please align with the implementation in leds-gpio.c @@ -571,7 +636,7 @@ static void openwifi_tx(struct ieee80211_hw *dev, u32 pkt_need_ack, addr1_low32=0, addr2_low32=0, addr3_low32=0, queue_idx=2, dma_reg, cts_reg;//, openofdm_state_history; u16 addr1_high16=0, addr2_high16=0, addr3_high16=0, sc=0, cts_duration=0, cts_rate_hw_value = 0, cts_rate_signal_value=0, sifs, ack_duration=0, traffic_pkt_duration; u8 fc_flag,fc_type,fc_subtype,retry_limit_raw,*dma_buf,retry_limit_hw_value,rc_flags; - bool use_rts_cts, use_cts_protect, addr_flag, cts_use_traffic_rate=false, force_use_cts_protect=false; + bool use_rts_cts, use_cts_protect, use_ht_rate=false, use_short_gi, addr_flag, cts_use_traffic_rate=false, force_use_cts_protect=false; __le16 frame_control,duration_id; u32 dma_fifo_no_room_flag, hw_queue_len; enum dma_status status; @@ -670,6 +735,8 @@ static void openwifi_tx(struct ieee80211_hw *dev, rc_flags = info->control.rates[0].flags; use_rts_cts = ((rc_flags&IEEE80211_TX_RC_USE_RTS_CTS)!=0); use_cts_protect = ((rc_flags&IEEE80211_TX_RC_USE_CTS_PROTECT)!=0); + use_ht_rate = ((rc_flags&IEEE80211_TX_RC_MCS)!=0); + use_short_gi = ((rc_flags&IEEE80211_TX_RC_SHORT_GI)!=0); if (use_rts_cts) printk("%s openwifi_tx: WARNING sn %d use_rts_cts is not supported!\n", sdr_compatible_str, ring->bd_wr_idx); @@ -701,8 +768,8 @@ static void openwifi_tx(struct ieee80211_hw *dev, } if ( (!addr_flag) && (priv->drv_tx_reg_val[DRV_TX_REG_IDX_PRINT_CFG]&2) ) - printk("%s openwifi_tx: %4dbytes %2dM FC%04x DI%04x addr1/2/3:%04x%08x/%04x%08x/%04x%08x SC%04x flag%08x retr%d ack%d prio%d q%d wr%d rd%d\n", sdr_compatible_str, - len_mac_pdu, wifi_rate_all[rate_hw_value],frame_control,duration_id, + printk("%s openwifi_tx: %4dbytes ht%d %3dM FC%04x DI%04x addr1/2/3:%04x%08x/%04x%08x/%04x%08x SC%04x flag%08x retr%d ack%d prio%d q%d wr%d rd%d\n", sdr_compatible_str, + len_mac_pdu, (use_ht_rate == false ? 0 : 1), (use_ht_rate == false ? wifi_rate_all[rate_hw_value] : wifi_rate_all[rate_hw_value + 12]),frame_control,duration_id, reverse16(addr1_high16), reverse32(addr1_low32), reverse16(addr2_high16), reverse32(addr2_low32), reverse16(addr3_high16), reverse32(addr3_low32), sc, info->flags, retry_limit_raw, pkt_need_ack, prio, queue_idx, // use_rts_cts,use_cts_protect|force_use_cts_protect,wifi_rate_all[cts_rate_hw_value],cts_duration, @@ -747,7 +814,8 @@ static void openwifi_tx(struct ieee80211_hw *dev, } skb_push( skb, LEN_PHY_HEADER ); - rate_signal_value = calc_phy_header(rate_hw_value, len_mac_pdu+LEN_PHY_CRC, skb->data); //fill the phy header + rate_signal_value = calc_phy_header(rate_hw_value, use_ht_rate, use_short_gi, len_mac_pdu+LEN_PHY_CRC, skb->data); //fill the phy header + //make sure dma length is integer times of DDC_NUM_BYTE_PER_DMA_SYMBOL if (skb_tailroom(skb)data[0])))&0xFF000000) || (*(u32*)(&(skb->data[12]))) || (*(u32*)(&(skb->data[8]))) || (*(u32*)(&(skb->data[4]))) ) { + if ( (*(u32*)(&(skb->data[4]))) || ((*(u32*)(&(skb->data[12])))&0xFFFF0000) ) { printk("%s openwifi_tx: WARNING 1 %d %08x %08x %08x %08x\n", sdr_compatible_str, num_byte_pad, *(u32*)(&(skb->data[12])), *(u32*)(&(skb->data[8])), *(u32*)(&(skb->data[4])), *(u32*)(&(skb->data[0]))); goto openwifi_tx_early_out_after_lock; } @@ -837,7 +905,7 @@ static void openwifi_tx(struct ieee80211_hw *dev, dma_async_issue_pending(priv->tx_chan); - if ( ((*(u32*)(&(skb->data[0])))&0xFF000000) || (*(u32*)(&(skb->data[12]))) || (*(u32*)(&(skb->data[8]))) || (*(u32*)(&(skb->data[4]))) ) + if ( (*(u32*)(&(skb->data[4]))) || ((*(u32*)(&(skb->data[12])))&0xFFFF0000) ) printk("%s openwifi_tx: WARNING 2 %08x %08x %08x %08x\n", sdr_compatible_str, *(u32*)(&(skb->data[12])), *(u32*)(&(skb->data[8])), *(u32*)(&(skb->data[4])), *(u32*)(&(skb->data[0]))); spin_unlock_irqrestore(&priv->lock, flags); @@ -1983,6 +2051,11 @@ static int openwifi_dev_probe(struct platform_device *pdev) priv->band_2GHz.n_channels = ARRAY_SIZE(priv->channels_2GHz); priv->band_2GHz.bitrates = priv->rates_2GHz; priv->band_2GHz.n_bitrates = ARRAY_SIZE(priv->rates_2GHz); + priv->band_2GHz.ht_cap.ht_supported = true; + priv->band_2GHz.ht_cap.cap = IEEE80211_HT_CAP_SGI_20; + memset(&priv->band_2GHz.ht_cap.mcs, 0, sizeof(priv->band_2GHz.ht_cap.mcs)); + priv->band_2GHz.ht_cap.mcs.rx_mask[0] = 0xff; + priv->band_2GHz.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; dev->wiphy->bands[NL80211_BAND_2GHZ] = &(priv->band_2GHz); priv->band_5GHz.band = NL80211_BAND_5GHZ; @@ -1990,6 +2063,11 @@ static int openwifi_dev_probe(struct platform_device *pdev) priv->band_5GHz.n_channels = ARRAY_SIZE(priv->channels_5GHz); priv->band_5GHz.bitrates = priv->rates_5GHz; priv->band_5GHz.n_bitrates = ARRAY_SIZE(priv->rates_5GHz); + priv->band_5GHz.ht_cap.ht_supported = true; + priv->band_5GHz.ht_cap.cap = IEEE80211_HT_CAP_SGI_20; + memset(&priv->band_5GHz.ht_cap.mcs, 0, sizeof(priv->band_5GHz.ht_cap.mcs)); + priv->band_5GHz.ht_cap.mcs.rx_mask[0] = 0xff; + priv->band_5GHz.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; dev->wiphy->bands[NL80211_BAND_5GHZ] = &(priv->band_5GHz); printk("%s openwifi_dev_probe: band_2GHz.n_channels %d n_bitrates %d band_5GHz.n_channels %d n_bitrates %d\n",sdr_compatible_str, diff --git a/driver/sdr.h b/driver/sdr.h index 3e0840c..925958f 100644 --- a/driver/sdr.h +++ b/driver/sdr.h @@ -260,11 +260,12 @@ static const struct ieee80211_iface_combination openwifi_if_comb = { BIT(NL80211_CHAN_WIDTH_80), }; -static const u8 wifi_rate_table_mapping[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 10, 8, 6, 4, 11, 9, 7, 5}; -static const u8 wifi_rate_table[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 48, 24, 12, 6, 54, 36, 18, 9}; -static const u8 wifi_rate_all[16] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 0, 0, 0, 0}; -static const u8 wifi_mcs_table_11b_force_up[16] = {11, 11, 11, 11, 11, 15, 10, 14, 9, 13, 8, 12, 0, 0, 0, 0}; -static const u16 wifi_n_dbps_table[16] = {24, 24, 24, 24, 24, 36, 48, 72, 96, 144, 192, 216, 0, 0, 0, 0}; +static const u8 wifi_rate_table_mapping[24] = { 0, 0, 0, 0, 0, 0, 0, 0, 10, 8, 6, 4, 11, 9, 7, 5, 0, 1, 2, 3, 4, 5, 6, 7}; +static const u16 wifi_rate_table[24] = { 0, 0, 0, 0, 0, 0, 0, 0, 480, 240, 120, 60, 540, 360, 180, 90, 65, 130, 195, 260, 390, 520, 585, 650}; +static const u16 wifi_rate_all[20] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540, 65, 130, 195, 260, 390, 520, 585, 650}; +static const u8 wifi_mcs_table_11b_force_up[16] = {11, 11, 11, 11, 11, 15, 10, 14, 9, 13, 8, 12, 0, 0, 0, 0}; +static const u16 wifi_n_dbps_table[16] = {24, 24, 24, 24, 24, 36, 48, 72, 96, 144, 192, 216, 0, 0, 0, 0}; +static const u16 wifi_n_dbps_ht_table[16] = {26, 26, 26, 26, 26, 52, 78, 104, 156, 208, 234, 260, 0, 0, 0, 0}; // static const u8 wifi_mcs_table[8] = {6,9,12,18,24,36,48,54}; // static const u8 wifi_mcs_table_phy_tx[8] = {11,15,10,14,9,13,8,12};