| /* |
| * Copyright (c) 2000-2005 ZyDAS Technology Corporation |
| * Copyright (c) 2007-2008 Atheros Communications Inc. |
| * |
| * Permission to use, copy, modify, and/or distribute this software for any |
| * purpose with or without fee is hereby granted, provided that the above |
| * copyright notice and this permission notice appear in all copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| */ |
| /* */ |
| /* Module Name : ud.c */ |
| /* */ |
| /* Abstract */ |
| /* This module contains USB descriptor functions. */ |
| /* */ |
| /* NOTES */ |
| /* None */ |
| /* */ |
| /************************************************************************/ |
| #include "../80211core/cprecomp.h" |
| #include "hpani.h" |
| #include "hpusb.h" |
| |
| extern void zfwUsbCmd(zdev_t* dev, u8_t endpt, u32_t* cmd, u16_t cmdLen); |
| |
| extern void zfIdlRsp(zdev_t* dev, u32_t* rsp, u16_t rspLen); |
| extern u16_t zfDelayWriteInternalReg(zdev_t* dev, u32_t addr, u32_t val); |
| extern u16_t zfFlushDelayWrite(zdev_t* dev); |
| |
| |
| #define USB_ENDPOINT_TX_INDEX 1 |
| #define USB_ENDPOINT_RX_INDEX 2 |
| #define USB_ENDPOINT_INT_INDEX 3 |
| #define USB_ENDPOINT_CMD_INDEX 4 |
| |
| void zfIdlCmd(zdev_t* dev, u32_t* cmd, u16_t cmdLen) |
| { |
| #if ZM_SW_LOOP_BACK != 1 |
| zfwUsbCmd(dev, USB_ENDPOINT_CMD_INDEX, cmd, cmdLen); |
| #endif |
| |
| return; |
| } |
| |
| |
| /* zfAdjustCtrlSetting: fit OUTS format */ |
| /* convert MIMO2 to OUTS */ |
| void zfAdjustCtrlSetting(zdev_t* dev, u16_t* header, zbuf_t* buf) |
| { |
| /* MIMO2 => OUTS FB-50 */ |
| /* length not change, only modify format */ |
| |
| u32_t oldMT; |
| u32_t oldMCS; |
| |
| u32_t phyCtrl; |
| u32_t oldPhyCtrl; |
| |
| u16_t tpc = 0; |
| struct zsHpPriv* hpPriv; |
| |
| zmw_get_wlan_dev(dev); |
| hpPriv=wd->hpPrivate; |
| |
| /* mm */ |
| if (header == NULL) |
| { |
| oldPhyCtrl = zmw_buf_readh(dev, buf, 4) | ((u32_t)zmw_buf_readh(dev, buf, 6) << 16); |
| } |
| else |
| { |
| oldPhyCtrl = header[2] | ((u32_t)header[3] <<16); |
| } |
| |
| phyCtrl = 0; |
| |
| |
| /* MT : Bit[1~0] */ |
| oldMT = oldPhyCtrl&0x3; |
| phyCtrl |= oldMT; |
| if ( oldMT == 0x3 ) /* DL-OFDM (Duplicate Legacy OFDM) */ |
| phyCtrl |= 0x1; |
| |
| |
| /* PT : Bit[2] HT PT: 0 Mixed mode 1 Green field */ |
| phyCtrl |= (oldPhyCtrl&0x4); |
| |
| /* Bandwidth control : Bit[4~3] */ |
| if ( oldPhyCtrl&0x800000 ) /* Bit23 : 40M */ |
| { |
| #if 0 |
| if (oldMT == 0x3) /* DL-OFDM */ |
| phyCtrl |= (0x3<<3); /* 40M duplicate */ |
| else |
| phyCtrl |= (0x2<<3); /* 40M shared */ |
| #else |
| if (oldMT == 0x2 && ((struct zsHpPriv*)wd->hpPrivate)->hwBw40) |
| { |
| phyCtrl |= (0x2<<3); /* 40M shared */ |
| } |
| #endif |
| } |
| else { |
| oldPhyCtrl &= ~0x80000000; |
| } |
| |
| /* MCS : Bit[24~18] */ |
| oldMCS = (oldPhyCtrl&0x7f0000)>>16; /* Bit[22~16] */ |
| phyCtrl |= (oldMCS<<18); |
| |
| /* Short GI : Bit[31]*/ |
| phyCtrl |= (oldPhyCtrl&0x80000000); |
| |
| /* AM : Antenna mask */ |
| //if ((oldMT == 2) && (oldMCS > 7)) |
| if (hpPriv->halCapability & ZM_HP_CAP_11N_ONE_TX_STREAM) |
| { |
| phyCtrl |= (0x1<<15); |
| } |
| else |
| { |
| /* HT Tx 2 chain */ |
| /* OFDM 6M/9M/12M/18M/24M Tx 2 chain */ |
| /* OFDM 36M/48M/54M/ Tx 1 chain */ |
| /* CCK Tx 2 chain */ |
| if ((oldMT == 2) || (oldMT == 3)) |
| { |
| phyCtrl |= (0x5<<15); |
| } |
| else if (oldMT == 1) |
| { |
| if ((oldMCS == 0xb) || (oldMCS == 0xf) || |
| (oldMCS == 0xa) || (oldMCS == 0xe) || |
| (oldMCS == 0x9)) //6M/9M/12M/18M/24M |
| { |
| phyCtrl |= (0x5<<15); |
| } |
| else |
| { |
| phyCtrl |= (0x1<<15); |
| } |
| } |
| else //(oldMT==0) |
| { |
| phyCtrl |= (0x5<<15); |
| } |
| } |
| //else |
| // phyCtrl |= (0x1<<15); |
| |
| /* TPC */ |
| /* TODO : accelerating these code */ |
| if (hpPriv->hwFrequency < 3000) |
| { |
| if (oldMT == 0) |
| { |
| /* CCK */ |
| tpc = (hpPriv->tPow2xCck[oldMCS]&0x3f); |
| } |
| else if (oldMT == 1) |
| { |
| /* OFDM */ |
| if (oldMCS == 0xc) |
| { |
| tpc = (hpPriv->tPow2x2g[3]&0x3f); |
| } |
| else if (oldMCS == 0x8) |
| { |
| tpc = (hpPriv->tPow2x2g[2]&0x3f); |
| } |
| else if (oldMCS == 0xd) |
| { |
| tpc = (hpPriv->tPow2x2g[1]&0x3f); |
| } |
| else if (oldMCS == 0x9) |
| { |
| tpc = ((hpPriv->tPow2x2g[0]-hpPriv->tPow2x2g24HeavyClipOffset)&0x3f); |
| } |
| else |
| { |
| tpc = (hpPriv->tPow2x2g[0]&0x3f); |
| } |
| } |
| else if (oldMT == 2) |
| { |
| if ( oldPhyCtrl&0x800000 ) /* Bit23 : 40M */ |
| { |
| /* HT 40 */ |
| tpc = (hpPriv->tPow2x2gHt40[oldMCS&0x7]&0x3f); |
| } |
| else |
| { |
| /* HT 20 */ |
| tpc = (hpPriv->tPow2x2gHt20[oldMCS&0x7]&0x3f); |
| } |
| } |
| } |
| else //5GHz |
| { |
| if (oldMT == 1) |
| { |
| /* OFDM */ |
| if (oldMCS == 0xc) |
| { |
| tpc = (hpPriv->tPow2x5g[3]&0x3f); |
| } |
| else if (oldMCS == 0x8) |
| { |
| tpc = (hpPriv->tPow2x5g[2]&0x3f); |
| } |
| else if (oldMCS == 0xd) |
| { |
| tpc = (hpPriv->tPow2x5g[1]&0x3f); |
| } |
| else |
| { |
| tpc = (hpPriv->tPow2x5g[0]&0x3f); |
| } |
| } |
| else if (oldMT == 2) |
| { |
| if ( oldPhyCtrl&0x800000 ) /* Bit23 : 40M */ |
| { |
| /* HT 40 */ |
| tpc = (hpPriv->tPow2x5gHt40[oldMCS&0x7]&0x3f); |
| } |
| else |
| { |
| /* HT 20 */ |
| tpc = (hpPriv->tPow2x5gHt20[oldMCS&0x7]&0x3f); |
| } |
| } |
| } |
| |
| /* Tx power adjust for HT40 */ |
| /* HT40 +1dBm */ |
| if ((oldMT==2) && (oldPhyCtrl&0x800000) ) |
| { |
| tpc += 2; |
| } |
| tpc &= 0x3f; |
| |
| /* Evl force tx TPC */ |
| if(wd->forceTxTPC) |
| { |
| tpc = (u16_t)(wd->forceTxTPC & 0x3f); |
| } |
| |
| if (hpPriv->hwFrequency < 3000) { |
| wd->maxTxPower2 &= 0x3f; |
| tpc = (tpc > wd->maxTxPower2)? wd->maxTxPower2 : tpc; |
| } else { |
| wd->maxTxPower5 &= 0x3f; |
| tpc = (tpc > wd->maxTxPower5)? wd->maxTxPower5 : tpc; |
| } |
| |
| |
| #define ZM_MIN_TPC 5 |
| #define ZM_TPC_OFFSET 5 |
| #define ZM_SIGNAL_THRESHOLD 56 |
| if ((wd->sta.bScheduleScan == FALSE) && (wd->sta.bChannelScan == FALSE)) |
| { |
| if (( wd->wlanMode == ZM_MODE_INFRASTRUCTURE ) |
| && (zfStaIsConnected(dev)) |
| && (wd->SignalStrength > ZM_SIGNAL_THRESHOLD)) |
| { |
| if (tpc > ((ZM_MIN_TPC+ZM_TPC_OFFSET)*2)) |
| { |
| tpc -= (ZM_TPC_OFFSET*2); |
| } |
| else if (tpc > (ZM_MIN_TPC*2)) |
| { |
| tpc = (ZM_MIN_TPC*2); |
| } |
| } |
| } |
| #undef ZM_MIN_TPC |
| #undef ZM_TPC_OFFSET |
| #undef ZM_SIGNAL_THRESHOLD |
| |
| #ifndef ZM_OTUS_LINUX_PHASE_2 |
| phyCtrl |= (tpc & 0x3f) << 9; |
| #endif |
| |
| /* Set bits[8:6]BF-MCS for heavy clip */ |
| if ((phyCtrl&0x3) == 2) |
| { |
| phyCtrl |= ((phyCtrl >> 12) & 0x1c0); |
| } |
| |
| /* PHY control */ |
| if (header == NULL) |
| { |
| zmw_buf_writeh(dev, buf, 4, (u16_t) (phyCtrl&0xffff)); |
| zmw_buf_writeh(dev, buf, 6, (u16_t) (phyCtrl>>16)); |
| } |
| else |
| { |
| //PHY control L |
| header[2] = (u16_t) (phyCtrl&0xffff); |
| //PHY control H |
| header[3] = (u16_t) (phyCtrl>>16); |
| } |
| |
| zm_msg2_tx(ZM_LV_2, "old phy ctrl = ", oldPhyCtrl); |
| zm_msg2_tx(ZM_LV_2, "new phy ctrl = ", phyCtrl); |
| //DbgPrint("old phy ctrl =%08x \n", oldPhyCtrl); |
| //DbgPrint("new phy ctrl =%08x \n", phyCtrl); |
| } |
| |
| |
| #define EXTRA_INFO_LEN 24 //RSSI(7) + EVM(12) + PHY(1) + MACStatus(4) |
| u16_t zfHpSend(zdev_t* dev, u16_t* header, u16_t headerLen, |
| u16_t* snap, u16_t snapLen, |
| u16_t* tail, u16_t tailLen, zbuf_t* buf, u16_t offset, |
| u16_t bufType, u8_t ac, u8_t keyIdx) |
| { |
| #if ZM_SW_LOOP_BACK == 1 |
| zbuf_t *rxbuf; |
| u8_t *puRxBuf; |
| u8_t *pHdr; |
| u8_t *psnap; |
| u16_t plcplen = 12; |
| u16_t i; |
| u16_t swlpOffset; |
| #endif /* #if ZM_SW_LOOP_BACK == 1 */ |
| struct zsHpPriv* hpPriv; |
| |
| zmw_get_wlan_dev(dev); |
| hpPriv=wd->hpPrivate; |
| |
| zm_msg1_tx(ZM_LV_1, "zfHpSend(), len = ", 12 + headerLen-8 + snapLen + zfwBufGetSize(dev, buf) + 4 + 8); |
| |
| /* Adjust ctrl setting : 6N14 yjsung */ |
| zfAdjustCtrlSetting(dev, header, buf); |
| |
| #if ZM_SW_LOOP_BACK != 1 |
| hpPriv->usbSendBytes += zfwBufGetSize(dev, buf); |
| hpPriv->usbAcSendBytes[ac&0x3] += zfwBufGetSize(dev, buf); |
| |
| /* Submit USB Out Urb */ |
| zfwUsbSend(dev, USB_ENDPOINT_TX_INDEX, (u8_t *)header, headerLen, |
| (u8_t *)snap, snapLen, (u8_t *)tail, tailLen, buf, offset); |
| #endif |
| |
| #if ZM_SW_LOOP_BACK == 1 |
| |
| rxbuf = zfwBufAllocate(dev, plcplen + headerLen-8 + snapLen + (zfwBufGetSize(dev, buf)-offset) + 4 + EXTRA_INFO_LEN); |
| pHdr = (u8_t *) header+8; |
| psnap = (u8_t *) snap; |
| |
| zmw_enter_critical_section(dev); |
| /* software loop back */ |
| /* Copy WLAN header and packet buffer */ |
| swlpOffset = plcplen; |
| |
| for(i = 0; i < headerLen-8; i++) |
| { |
| zmw_rx_buf_writeb(dev, rxbuf, swlpOffset+i, pHdr[i]); |
| } |
| |
| swlpOffset += headerLen-8; |
| |
| /* Copy SNAP header */ |
| for(i = 0; i < snapLen; i++) |
| { |
| zmw_rx_buf_writeb(dev, rxbuf, swlpOffset+i, psnap[i]); |
| } |
| |
| swlpOffset += snapLen; |
| |
| /* Copy body from tx buf to rxbuf */ |
| for(i = 0; i < (zfwBufGetSize(dev, buf)-offset); i++) |
| { |
| u8_t value = zmw_rx_buf_readb(dev, buf, i+offset); |
| zmw_rx_buf_writeb(dev, rxbuf, swlpOffset+i, value); |
| } |
| |
| /* total length = PLCP + MacHeader + Payload + FCS + RXstatus */ |
| /* 12 + headerLen-8 + snapLen + buf length + 4 + 8 */ |
| zfwSetBufSetSize(dev, rxbuf, swlpOffset + (zfwBufGetSize(dev, buf)-offset) + 4 + EXTRA_INFO_LEN ); |
| |
| zmw_leave_critical_section(dev); |
| |
| zfwBufFree(dev, buf, 0); |
| |
| //zfwDumpBuf(dev, rxbuf); |
| //------------------------------------------------- |
| |
| //zfCoreRecv(dev, rxbuf); |
| |
| #endif /* #if ZM_SW_LOOP_BACK */ |
| |
| return ZM_SUCCESS; |
| } |
| |
| /* Report moniter Hal rx information about rssi, evm, bandwidth, SG etc */ |
| void zfHpQueryMonHalRxInfo(zdev_t* dev, u8_t *monHalRxInfo) |
| { |
| zmw_get_wlan_dev(dev); |
| zfMemoryCopy(monHalRxInfo, |
| (u8_t*)&(((struct zsHpPriv*)wd->hpPrivate)->halRxInfo), |
| sizeof(struct zsHalRxInfo)); |
| } |
| |
| |
| u8_t zfIsDataFrame(zdev_t* dev, zbuf_t* buf) |
| { |
| u8_t frameType; |
| u8_t mpduInd; |
| |
| mpduInd = zmw_rx_buf_readb(dev, buf, zfwBufGetSize(dev, buf)-1); |
| |
| /* sinlge or First */ |
| if ((mpduInd & 0x30) == 0x00 || (mpduInd & 0x30) == 0x20) |
| { |
| frameType = zmw_rx_buf_readb(dev, buf, 12); |
| } |
| else |
| { |
| frameType = zmw_rx_buf_readb(dev, buf, 0); |
| } |
| |
| if((frameType & 0xf) == ZM_WLAN_DATA_FRAME) |
| return 1; |
| else |
| return 0; |
| } |
| |
| u32_t zfcConvertRateOFDM(zdev_t* dev, zbuf_t* buf) |
| { |
| // What's the default value?? |
| u32_t MCS = 0; |
| |
| switch(zmw_rx_buf_readb(dev, buf, 0)& 0xf) |
| { |
| case 0xb: |
| MCS = 0x4; |
| break; |
| case 0xf: |
| MCS = 0x5; |
| break; |
| case 0xa: |
| MCS = 0x6; |
| break; |
| case 0xe: |
| MCS = 0x7; |
| break; |
| case 0x9: |
| MCS = 0x8; |
| break; |
| case 0xd: |
| MCS = 0x9; |
| break; |
| case 0x8: |
| MCS = 0xa; |
| break; |
| case 0xc: |
| MCS = 0xb; |
| break; |
| } |
| return MCS; |
| } |
| |
| u16_t zfHpGetPayloadLen(zdev_t* dev, |
| zbuf_t* buf, |
| u16_t len, |
| u16_t plcpHdrLen, |
| u32_t *rxMT, |
| u32_t *rxMCS, |
| u32_t *rxBW, |
| u32_t *rxSG |
| ) |
| { |
| u8_t modulation,mpduInd; |
| u16_t low, high, msb; |
| s16_t payloadLen = 0; |
| |
| zmw_get_wlan_dev(dev); |
| |
| mpduInd = zmw_rx_buf_readb(dev, buf, len-1); |
| modulation = zmw_rx_buf_readb(dev, buf, (len-1)) & 0x3; |
| *rxMT = modulation; |
| |
| //zm_debug_msg1(" modulation= ", modulation); |
| switch (modulation) { |
| case 0: /* CCK Mode */ |
| low = zmw_rx_buf_readb(dev, buf, 2); |
| high = zmw_rx_buf_readb(dev, buf, 3); |
| payloadLen = (low | high << 8) - 4; |
| if (wd->enableHALDbgInfo) |
| { |
| *rxMCS = zmw_rx_buf_readb(dev, buf, 0); |
| *rxBW = 0; |
| *rxSG = 0; |
| } |
| break; |
| case 1: /* Legacy-OFDM mode */ |
| low = zmw_rx_buf_readb(dev, buf, 0) >> 5; |
| high = zmw_rx_buf_readb(dev, buf, 1); |
| msb = zmw_rx_buf_readb(dev, buf, 2) & 0x1; |
| payloadLen = (low | (high << 3) | (msb << 11)) - 4; |
| if (wd->enableHALDbgInfo) |
| { |
| *rxMCS = zfcConvertRateOFDM(dev, buf); |
| *rxBW = 0; |
| *rxSG = 0; |
| } |
| break; |
| case 2: /* HT OFDM mode */ |
| //zm_debug_msg1("aggregation= ", (zmw_rx_buf_readb(dev, buf, 6) >> 3) &0x1 ); |
| if ((mpduInd & 0x30) == 0x00 || (mpduInd & 0x30) == 0x10) //single or last mpdu |
| payloadLen = len - 24 - 4 - plcpHdrLen; // - rxStatus - fcs |
| else { |
| payloadLen = len - 4 - 4 - plcpHdrLen; // - rxStatus - fcs |
| //zm_debug_msg1("first or middle mpdu, plcpHdrLen= ", plcpHdrLen); |
| } |
| if (wd->enableHALDbgInfo) |
| { |
| *rxMCS = zmw_rx_buf_readb(dev, buf, 3) & 0x7f; |
| *rxBW = (zmw_rx_buf_readb(dev, buf, 3) >> 7) & 0x1; |
| *rxSG = (zmw_rx_buf_readb(dev, buf, 6) >> 7) & 0x1; |
| } |
| break; |
| default: |
| break; |
| |
| } |
| /* return the payload length - FCS */ |
| if (payloadLen < 0) payloadLen = 0; |
| return payloadLen; |
| } |
| |
| /************************************************************************/ |
| /* */ |
| /* FUNCTION DESCRIPTION zfiUsbRecv */ |
| /* Callback function for USB IN Transfer. */ |
| /* */ |
| /* INPUTS */ |
| /* dev: device pointer */ |
| /* */ |
| /* OUTPUTS */ |
| /* None */ |
| /* */ |
| /* AUTHOR */ |
| /* Yuan-Gu Wei ZyDAS Technology Corporation 2005.10 */ |
| /* */ |
| /************************************************************************/ |
| #define ZM_INT_USE_EP2 1 |
| #define ZM_INT_USE_EP2_HEADER_SIZE 12 |
| |
| #if ZM_INT_USE_EP2 == 1 |
| void zfiUsbRegIn(zdev_t* dev, u32_t* rsp, u16_t rspLen); |
| #endif |
| |
| #ifdef ZM_OTUS_RX_STREAM_MODE |
| void zfiUsbRecvPerPkt(zdev_t *dev, zbuf_t *buf) |
| #else |
| void zfiUsbRecv(zdev_t *dev, zbuf_t *buf) |
| #endif |
| { |
| |
| |
| #if ZM_FW_LOOP_BACK != 1 |
| u8_t mpduInd; |
| u16_t plcpHdrLen; |
| u16_t crcPlusRxStatusLen; |
| u16_t len, payloadLen=0; |
| u16_t i; //CWYang(+) |
| struct zsAdditionInfo addInfo; |
| u32_t rxMT; |
| u32_t rxMCS; |
| u32_t rxBW; |
| u32_t rxSG; |
| struct zsHpPriv* hpPriv; |
| |
| zmw_get_wlan_dev(dev); |
| hpPriv=wd->hpPrivate; |
| |
| //zm_msg0_rx(ZM_LV_0, "zfiUsbRecv()"); |
| |
| #if ZM_INT_USE_EP2 == 1 |
| |
| for (i=0; i<(ZM_INT_USE_EP2_HEADER_SIZE>>1); i++) |
| { |
| if (zmw_rx_buf_readh(dev, buf, i*2) != 0xffff) |
| break; |
| } |
| |
| if (i==(ZM_INT_USE_EP2_HEADER_SIZE>>1)) |
| { |
| u32_t rsp[ZM_USB_MAX_EPINT_BUFFER/4]; |
| u16_t rspLen; |
| u32_t rspi; |
| u8_t* pdst = (u8_t*)rsp; |
| |
| /* Interrupt Rsp */ |
| rspLen = (u16_t) zfwBufGetSize(dev, buf)-ZM_INT_USE_EP2_HEADER_SIZE; |
| |
| if (rspLen > 60) |
| { |
| zm_debug_msg1("Get error len by EP2 = \n", rspLen); |
| /* free USB buf */ |
| zfwBufFree(dev, buf, 0); |
| return; |
| } |
| |
| for (rspi=0; rspi<rspLen; rspi++) |
| { |
| *pdst = zmw_rx_buf_readb(dev, buf, rspi+ZM_INT_USE_EP2_HEADER_SIZE); |
| pdst++; |
| } |
| |
| //if (adapter->zfcbUsbRegIn) |
| // adapter->zfcbUsbRegIn(adapter, rsp, rspLen); |
| zfiUsbRegIn(dev, rsp, rspLen); |
| |
| /* free USB buf */ |
| zfwBufFree(dev, buf, 0); |
| return; |
| } |
| #endif /* end of #if ZM_INT_USE_EP2 == 1 */ |
| |
| ZM_PERFORMANCE_RX_MPDU(dev, buf); |
| |
| if (wd->swSniffer) |
| { |
| /* airopeek: Report everything up */ |
| if (wd->zfcbRecv80211 != NULL) |
| { |
| wd->zfcbRecv80211(dev, buf, NULL); |
| } |
| } |
| |
| /* Read the last byte */ |
| len = zfwBufGetSize(dev, buf); |
| mpduInd = zmw_rx_buf_readb(dev, buf, len-1); |
| |
| /* First MPDU */ |
| if((mpduInd & 0x30) == 0x20) |
| { |
| u16_t duration; |
| if (zmw_rx_buf_readb(dev, buf, 36) == 0) //AC = BE |
| { |
| duration = zmw_rx_buf_readh(dev, buf, 14); |
| if (duration > hpPriv->aggMaxDurationBE) |
| { |
| hpPriv->aggMaxDurationBE = duration; |
| } |
| else |
| { |
| if (hpPriv->aggMaxDurationBE > 10) |
| { |
| hpPriv->aggMaxDurationBE--; |
| } |
| } |
| //DbgPrint("aggMaxDurationBE=%d", hpPriv->aggMaxDurationBE); |
| } |
| } |
| |
| #if 1 |
| /* First MPDU or Single MPDU */ |
| if(((mpduInd & 0x30) == 0x00) || ((mpduInd & 0x30) == 0x20)) |
| //if ((mpduInd & 0x10) == 0x00) |
| { |
| plcpHdrLen = 12; // PLCP header length |
| } |
| else |
| { |
| if (zmw_rx_buf_readh(dev, buf, 4) == wd->macAddr[0] && |
| zmw_rx_buf_readh(dev, buf, 6) == wd->macAddr[1] && |
| zmw_rx_buf_readh(dev, buf, 8) == wd->macAddr[2]) { |
| plcpHdrLen = 0; |
| } |
| else if (zmw_rx_buf_readh(dev, buf, 16) == wd->macAddr[0] && |
| zmw_rx_buf_readh(dev, buf, 18) == wd->macAddr[1] && |
| zmw_rx_buf_readh(dev, buf, 20) == wd->macAddr[2]){ |
| plcpHdrLen = 12; |
| } |
| else { |
| plcpHdrLen = 0; |
| } |
| } |
| |
| /* Last MPDU or Single MPDU */ |
| if ((mpduInd & 0x30) == 0x00 || (mpduInd & 0x30) == 0x10) |
| { |
| crcPlusRxStatusLen = EXTRA_INFO_LEN + 4; // Extra bytes + FCS |
| } |
| else |
| { |
| crcPlusRxStatusLen = 4 + 4; // Extra 4 bytes + FCS |
| } |
| #else |
| plcpHdrLen = 12; |
| crcPlusRxStatusLen = EXTRA_INFO_LEN + 4; // Extra bytes + FCS |
| #endif |
| |
| if (len < (plcpHdrLen+10+crcPlusRxStatusLen)) |
| { |
| zm_msg1_rx(ZM_LV_0, "Invalid Rx length=", len); |
| //zfwDumpBuf(dev, buf); |
| |
| zfwBufFree(dev, buf, 0); |
| return; |
| } |
| |
| /* display RSSI combined */ |
| /* |
| * ¢z¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢{ |
| * ¢x PLCP Header ¢x MPDU ¢x RSSI ¢x EVM ¢x PHY Err ¢x MAC Status ¢x |
| * ¢u¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢t |
| * ¢x 12 ¢x n ¢x 7 ¢x 12 ¢x 1 ¢x 4 ¢x |
| * ¢|¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢} |
| * RSSI filed (From BB and MAC just pass them to host) |
| * Byte1: RSSI for antenna 0. |
| * Byte2: RSSI for antenna 1. |
| * Byte3: RSSI for antenna 2. |
| * Byte4: RSSI for antenna 0 extension. |
| * Byte5: RSSI for antenna 1 extension. |
| * Byte6: RSSI for antenna 2 extension. |
| * Byte7: RSSI for antenna combined. |
| */ |
| |
| //zm_debug_msg1(" recv RSSI = ", zmw_rx_buf_readb(dev, buf, (len-1)-17)); |
| |
| payloadLen = zfHpGetPayloadLen(dev, buf, len, plcpHdrLen, &rxMT, &rxMCS, &rxBW, &rxSG); |
| |
| /* Hal Rx info */ |
| /* First MPDU or Single MPDU */ |
| if(((mpduInd & 0x30) == 0x00) || ((mpduInd & 0x30) == 0x20)) |
| { |
| if (wd->enableHALDbgInfo && zfIsDataFrame(dev, buf)) |
| { |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxDataMT = rxMT; |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxDataMCS = rxMCS; |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxDataBW = rxBW; |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxDataSG = rxSG; |
| } |
| } |
| |
| if ((plcpHdrLen + payloadLen) > len) { |
| zm_msg1_rx(ZM_LV_0, "Invalid payload length=", payloadLen); |
| zfwBufFree(dev, buf, 0); |
| return; |
| } |
| |
| //Store Rx Tail Infomation before Remove--CWYang(+) |
| |
| #if 0 |
| for (i = 0; i < crcPlusRxStatusLen-4; i++) |
| { |
| addInfo.Tail.Byte[i] = |
| zmw_rx_buf_readb(dev, buf, len - crcPlusRxStatusLen + 4 + i); |
| } |
| #else |
| /* |
| * Brief format of OUTS chip |
| * ¢z¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢{ |
| * ¢x PLCP Header ¢x MPDU ¢x RSSI ¢x EVM ¢x PHY Err ¢x MAC Status ¢x |
| * ¢u¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢t |
| * ¢x 12 ¢x n ¢x 7 ¢x 12 ¢x 1 ¢x 4 ¢x |
| * ¢|¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢} |
| * RSSI: |
| * Byte 1 antenna 0 |
| * Byte 2 antenna 1 |
| * Byte 3 antenna 2 |
| * Byte 4 antenna 0 extension |
| * Byte 5 antenna 1 extension |
| * Byte 6 antenna 2 extension |
| * Byte 7 antenna combined |
| * EVM: |
| * Byte 1 Stream 0 pilot 0 |
| * Byte 2 Stream 0 pilot 1 |
| * Byte 3 Stream 0 pilot 2 |
| * Byte 4 Stream 0 pilot 3 |
| * Byte 5 Stream 0 pilot 4 |
| * Byte 6 Stream 0 pilot 5 |
| * Byte 7 Stream 1 pilot 0 |
| * Byte 8 Stream 1 pilot 1 |
| * Byte 9 Stream 1 pilot 2 |
| * Byte 10 Stream 1 pilot 3 |
| * Byte 11 Stream 1 pilot 4 |
| * Byte 12 Stream 1 pilot 5 |
| */ |
| |
| /* Fill the Tail information */ |
| /* Last MPDU or Single MPDU */ |
| if ((mpduInd & 0x30) == 0x00 || (mpduInd & 0x30) == 0x10) |
| { |
| #define ZM_RX_RSSI_COMPENSATION 27 |
| u8_t zm_rx_rssi_compensation = ZM_RX_RSSI_COMPENSATION; |
| |
| /* RSSI information */ |
| addInfo.Tail.Data.SignalStrength1 = zmw_rx_buf_readb(dev, buf, |
| (len-1) - 17) + ((hpPriv->rxStrongRSSI == 1)?zm_rx_rssi_compensation:0); |
| #undef ZM_RX_RSSI_COMPENSATION |
| |
| /* EVM */ |
| |
| /* TODO: for RD/BB debug message */ |
| /* save current rx hw infomration, report to DrvCore/Application */ |
| if (wd->enableHALDbgInfo && zfIsDataFrame(dev, buf)) |
| { |
| u8_t trssi; |
| for (i=0; i<7; i++) |
| { |
| trssi = zmw_rx_buf_readb(dev, buf, (len-1) - 23 + i); |
| if (trssi&0x80) |
| { |
| trssi = ((~((u8_t)trssi) & 0x7f) + 1) & 0x7f; |
| } |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[i] = trssi; |
| |
| } |
| if (rxMT==2) |
| { |
| //if (rxBW) |
| //{ |
| for (i=0; i<12; i++) |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[i] = |
| zmw_rx_buf_readb(dev, buf, (len-1) - 16 + i); |
| //} |
| //else |
| //{ |
| // for (i=0; i<4; i++) |
| // ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[i] = |
| // zmw_rx_buf_readb(dev, buf, (len-1) - 16 + i); |
| //} |
| } |
| |
| #if 0 |
| /* print */ |
| zm_dbg(("MT(%d) MCS(%d) BW(%d) SG(%d) RSSI:%d,%d,%d,%d,%d,%d,%d EVM:(%d,%d,%d,%d,%d,%d)(%d,%d,%d,%d,%d,%d)\n", |
| rxMT, |
| rxMCS, |
| rxBW, |
| rxSG, |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[0], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[1], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[2], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[3], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[4], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[5], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[6], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[0], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[1], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[2], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[3], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[4], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[5], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[6], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[7], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[8], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[9], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[10], |
| ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[11] |
| )); |
| #endif |
| } /* if (wd->enableHALDbgInfo && zfIsDataFrame(dev, buf)) */ |
| |
| } |
| else |
| { |
| /* Mid or First aggregate frame without phy rx information */ |
| addInfo.Tail.Data.SignalStrength1 = 0; |
| } |
| |
| addInfo.Tail.Data.SignalStrength2 = 0; |
| addInfo.Tail.Data.SignalStrength3 = 0; |
| addInfo.Tail.Data.SignalQuality = 0; |
| |
| addInfo.Tail.Data.SAIndex = zmw_rx_buf_readb(dev, buf, len - 4); |
| addInfo.Tail.Data.DAIndex = zmw_rx_buf_readb(dev, buf, len - 3); |
| addInfo.Tail.Data.ErrorIndication = zmw_rx_buf_readb(dev, buf, len - 2); |
| addInfo.Tail.Data.RxMacStatus = zmw_rx_buf_readb(dev, buf, len - 1); |
| |
| #endif |
| /* Remove CRC and Rx Status */ |
| zfwBufSetSize(dev, buf, (len-crcPlusRxStatusLen)); |
| //zfwBufSetSize(dev, buf, payloadLen + plcpHdrLen); /* payloadLen + PLCP 12 - FCS 4*/ |
| |
| //Store PLCP Header Infomation before Remove--CWYang(+) |
| if (plcpHdrLen != 0) |
| { |
| for (i = 0; i < plcpHdrLen; i++) |
| { |
| addInfo.PlcpHeader[i] = zmw_rx_buf_readb(dev, buf, i); |
| } |
| } |
| else |
| { |
| addInfo.PlcpHeader[0] = 0; |
| } |
| /* Remove PLCP header */ |
| zfwBufRemoveHead(dev, buf, plcpHdrLen); |
| |
| /* handle 802.11 frame */ |
| zfCoreRecv(dev, buf, &addInfo); |
| |
| #else |
| /* Firmware loopback: Rx frame = Tx frame */ |
| /* convert Rx frame to fit receive frame format */ |
| zbuf_t *new_buf; |
| u8_t ctrl_offset = 8; |
| u8_t PLCP_Len = 12; |
| u8_t data; |
| u8_t i; |
| |
| |
| /* Tx: | ctrl_setting | Mac hdr | data | */ |
| /* 8 24 x */ |
| |
| /* Rx: | PLCP | Mac hdr | data | FCS | Rxstatus | */ |
| /* 12 24 x 4 8 */ |
| |
| /* new allocate a rx format size buf */ |
| new_buf = zfwBufAllocate(dev, zfwBufGetSize(dev, buf)-8+12+4+EXTRA_INFO_LEN); |
| |
| for (i=0; i<zfwBufGetSize(dev, buf)-ctrl_offset; i++) |
| { |
| data = zmw_rx_buf_readb(dev, buf, ctrl_offset+i); |
| zmw_rx_buf_writeb(dev, new_buf, PLCP_Len+i, data); |
| } |
| |
| zfwBufSetSize(dev, new_buf, zfwBufGetSize(dev, buf)-8+12+4+EXTRA_INFO_LEN); |
| |
| zfwBufFree(dev, buf, 0); |
| |
| /* receive the new_buf */ |
| //zfCoreRecv(dev, new_buf); |
| |
| #endif |
| |
| } |
| |
| #ifdef ZM_OTUS_RX_STREAM_MODE |
| void zfiUsbRecv(zdev_t *dev, zbuf_t *buf) |
| { |
| u16_t index = 0; |
| u16_t chkIdx; |
| u32_t status = 0; |
| u16_t ii; |
| zbuf_t *newBuf; |
| zbuf_t *rxBufPool[8]; |
| u16_t rxBufPoolIndex = 0; |
| struct zsHpPriv *halPriv; |
| u8_t *srcBufPtr; |
| u32_t bufferLength; |
| u16_t usbRxRemainLen; |
| u16_t usbRxPktLen; |
| |
| zmw_get_wlan_dev(dev); |
| |
| halPriv = (struct zsHpPriv*)wd->hpPrivate; |
| srcBufPtr = zmw_buf_get_buffer(dev, buf); |
| |
| bufferLength = zfwBufGetSize(dev, buf); |
| |
| /* Zero Length Transfer */ |
| if (!bufferLength) |
| { |
| zfwBufFree(dev, buf, 0); |
| return; |
| } |
| |
| usbRxRemainLen = halPriv->usbRxRemainLen; |
| usbRxPktLen = halPriv->usbRxTransferLen; |
| |
| /* Check whether there is any data in the last transfer */ |
| if (usbRxRemainLen != 0 ) |
| { |
| zbuf_t *remainBufPtr = halPriv->remainBuf; |
| u8_t* BufPtr = NULL; |
| |
| if ( remainBufPtr != NULL ) |
| { |
| BufPtr = zmw_buf_get_buffer(dev, remainBufPtr); |
| } |
| |
| index = usbRxRemainLen; |
| usbRxRemainLen -= halPriv->usbRxPadLen; |
| |
| /* Copy data */ |
| if ( BufPtr != NULL ) |
| { |
| zfwMemoryCopy(&(BufPtr[usbRxPktLen]), srcBufPtr, usbRxRemainLen); |
| } |
| |
| usbRxPktLen += usbRxRemainLen; |
| halPriv->usbRxRemainLen = 0; |
| |
| if ( remainBufPtr != NULL ) |
| { |
| zfwBufSetSize(dev, remainBufPtr, usbRxPktLen); |
| rxBufPool[rxBufPoolIndex++] = remainBufPtr; |
| } |
| halPriv->remainBuf = NULL; |
| } |
| |
| //zm_debug_msg1("length: %d\n", (int)pUsbRxTransfer->pRxUrb->UrbBulkOrInterruptTransfer.TransferBufferLength); |
| |
| bufferLength = zfwBufGetSize(dev, buf); |
| //printk("bufferLength %d\n", bufferLength); |
| while(index < bufferLength) |
| { |
| u16_t pktLen; |
| u16_t pktTag; |
| //u8_t *ptr = (u8_t*)((struct zsBuffer*)pUsbRxTransfer->buf)->data; |
| u8_t *ptr = srcBufPtr; |
| |
| /* Retrieve packet length and tag */ |
| pktLen = ptr[index] + (ptr[index+1] << 8); |
| pktTag = ptr[index+2] + (ptr[index+3] << 8); |
| |
| if (pktTag == ZM_USB_STREAM_MODE_TAG) |
| { |
| u16_t padLen; |
| |
| zm_assert(pktLen < ZM_WLAN_MAX_RX_SIZE); |
| |
| //printk("Get a packet, pktLen: 0x%04x\n", pktLen); |
| #if 0 |
| /* Dump data */ |
| for (ii = index; ii < pkt_len+4;) |
| { |
| DbgPrint("0x%02x ", |
| (zmw_rx_buf_readb(adapter, pUsbRxTransfer->buf, ii) & 0xff)); |
| |
| if ((++ii % 16) == 0) |
| DbgPrint("\n"); |
| } |
| |
| DbgPrint("\n"); |
| #endif |
| |
| /* Calcuate the padding length, in the current design, |
| the length should be padded to 4 byte boundray. */ |
| padLen = ZM_USB_STREAM_MODE_TAG_LEN - (pktLen & 0x3); |
| |
| if(padLen == ZM_USB_STREAM_MODE_TAG_LEN) |
| padLen = 0; |
| |
| chkIdx = index; |
| index = index + ZM_USB_STREAM_MODE_TAG_LEN + pktLen + padLen; |
| |
| if (chkIdx > ZM_MAX_USB_IN_TRANSFER_SIZE) |
| { |
| zm_debug_msg1("chkIdx is too large, chkIdx: %d\n", chkIdx); |
| zm_assert(0); |
| status = 1; |
| break; |
| } |
| |
| if (index > ZM_MAX_USB_IN_TRANSFER_SIZE) |
| { |
| //struct zsBuffer* BufPtr; |
| //struct zsBuffer* UsbBufPtr; |
| u8_t *BufPtr; |
| u8_t *UsbBufPtr; |
| |
| halPriv->usbRxRemainLen = index - ZM_MAX_USB_IN_TRANSFER_SIZE; // - padLen; |
| halPriv->usbRxTransferLen = ZM_MAX_USB_IN_TRANSFER_SIZE - |
| chkIdx - ZM_USB_STREAM_MODE_TAG_LEN; |
| halPriv->usbRxPadLen = padLen; |
| //check_index = index; |
| |
| if (halPriv->usbRxTransferLen > ZM_WLAN_MAX_RX_SIZE) |
| { |
| zm_debug_msg1("check_len is too large, chk_len: %d\n", |
| halPriv->usbRxTransferLen); |
| status = 1; |
| break; |
| } |
| |
| /* Allocate a skb buffer */ |
| newBuf = zfwBufAllocate(dev, ZM_WLAN_MAX_RX_SIZE); |
| |
| if ( newBuf != NULL ) |
| { |
| BufPtr = zmw_buf_get_buffer(dev, newBuf); |
| UsbBufPtr = srcBufPtr; |
| |
| /* Copy the buffer */ |
| zfwMemoryCopy(BufPtr, &(UsbBufPtr[chkIdx+ZM_USB_STREAM_MODE_TAG_LEN]), halPriv->usbRxTransferLen); |
| |
| /* Record the buffer pointer */ |
| halPriv->remainBuf = newBuf; |
| } |
| } |
| else |
| { |
| u8_t* BufPtr; |
| u8_t* UsbBufPtr; |
| |
| /* Allocate a skb buffer */ |
| newBuf = zfwBufAllocate(dev, ZM_WLAN_MAX_RX_SIZE); |
| if ( newBuf != NULL ) |
| { |
| BufPtr = zmw_buf_get_buffer(dev, newBuf); |
| UsbBufPtr = srcBufPtr; |
| |
| /* Copy the buffer */ |
| zfwMemoryCopy(BufPtr, &(UsbBufPtr[chkIdx+ZM_USB_STREAM_MODE_TAG_LEN]), pktLen); |
| |
| zfwBufSetSize(dev, newBuf, pktLen); |
| rxBufPool[rxBufPoolIndex++] = newBuf; |
| } |
| } |
| } |
| else |
| { |
| u16_t i; |
| |
| DbgPrint("Can't find tag, pkt_len: 0x%04x, tag: 0x%04x\n", |
| pktLen, pktTag); |
| |
| #if 0 |
| for(i = 0; i < 32; i++) |
| { |
| DbgPrint("%02x ", buf->data[index-16+i]); |
| |
| if ((i & 0xf) == 0xf) |
| DbgPrint("\n"); |
| } |
| #endif |
| |
| break; |
| } |
| } |
| |
| /* Free buffer */ |
| //zfwBufFree(adapter, pUsbRxTransfer->buf, 0); |
| zfwBufFree(dev, buf, 0); |
| |
| for(ii = 0; ii < rxBufPoolIndex; ii++) |
| { |
| zfiUsbRecvPerPkt(dev, rxBufPool[ii]); |
| } |
| } |
| #endif |
| |
| /************************************************************************/ |
| /* */ |
| /* FUNCTION DESCRIPTION zfUsbInit */ |
| /* Initialize USB resource. */ |
| /* */ |
| /* INPUTS */ |
| /* dev : device pointer */ |
| /* */ |
| /* OUTPUTS */ |
| /* None */ |
| /* */ |
| /* AUTHOR */ |
| /* Stephen Chen ZyDAS Technology Corporation 2005.12 */ |
| /* */ |
| /************************************************************************/ |
| void zfUsbInit(zdev_t* dev) |
| { |
| /* Initialize Rx & INT endpoint for receiving data & interrupt */ |
| zfwUsbEnableRxEpt(dev, USB_ENDPOINT_RX_INDEX); |
| zfwUsbEnableIntEpt(dev, USB_ENDPOINT_INT_INDEX); |
| |
| return; |
| } |
| |
| |
| /************************************************************************/ |
| /* */ |
| /* FUNCTION DESCRIPTION zfUsbFree */ |
| /* Free PCI resource. */ |
| /* */ |
| /* INPUTS */ |
| /* dev : device pointer */ |
| /* */ |
| /* OUTPUTS */ |
| /* None */ |
| /* */ |
| /* AUTHOR */ |
| /* Stephen Chen ZyDAS Technology Corporation 2005.12 */ |
| /* */ |
| /************************************************************************/ |
| void zfUsbFree(zdev_t* dev) |
| { |
| struct zsHpPriv *halPriv; |
| |
| zmw_get_wlan_dev(dev); |
| |
| halPriv = (struct zsHpPriv*)wd->hpPrivate; |
| |
| #ifdef ZM_OTUS_RX_STREAM_MODE |
| if ( halPriv->remainBuf != NULL ) |
| { |
| zfwBufFree(dev, halPriv->remainBuf, 0); |
| } |
| #endif |
| |
| return; |
| } |
| |
| void zfHpSendBeacon(zdev_t* dev, zbuf_t* buf, u16_t len) |
| { |
| u32_t hw, lw; |
| u16_t i; |
| zmw_get_wlan_dev(dev); |
| |
| /* Write to beacon buffer (ZM_BEACON_BUFFER_ADDRESS) */ |
| for (i = 0; i<len; i+=4) |
| { |
| lw = zmw_tx_buf_readh(dev, buf, i); |
| hw = zmw_tx_buf_readh(dev, buf, i+2); |
| |
| zfDelayWriteInternalReg(dev, ZM_BEACON_BUFFER_ADDRESS+i, (hw<<16)+lw); |
| } |
| |
| /* Beacon PCLP header */ |
| if (((struct zsHpPriv*)wd->hpPrivate)->hwFrequency < 3000) |
| { |
| zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_PLCP, ((len+4)<<(3+16))+0x0400); |
| } |
| else |
| { |
| zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_PLCP, ((len+4)<<(16))+0x001b); |
| } |
| |
| /* Beacon length (include CRC32) */ |
| zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_LENGTH, len+4); |
| |
| /* Beacon Ready */ |
| zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_CTRL, 1); |
| zfFlushDelayWrite(dev); |
| |
| /* Free beacon buf */ |
| zfwBufFree(dev, buf, 0); |
| |
| return; |
| } |
| |
| |
| #define ZM_STATUS_TX_COMP 0x00 |
| #define ZM_STATUS_RETRY_COMP 0x01 |
| #define ZM_STATUS_TX_FAILED 0x02 |
| void zfiUsbRegIn(zdev_t* dev, u32_t* rsp, u16_t rspLen) |
| { |
| //u8_t len, type, i; |
| u8_t type; |
| u8_t *u8rsp; |
| u16_t status; |
| u32_t bitmap; |
| zmw_get_wlan_dev(dev); |
| |
| zm_msg0_mm(ZM_LV_3, "zfiUsbRegIn()"); |
| |
| u8rsp = (u8_t *)rsp; |
| |
| //len = *u8rsp; |
| type = *(u8rsp+1); |
| u8rsp = u8rsp+4; |
| |
| |
| /* Interrupt event */ |
| if ((type & 0xC0) == 0xC0) |
| { |
| if (type == 0xC0) |
| { |
| zfCoreEvent(dev, 0, u8rsp); |
| |
| } |
| else if (type == 0xC1) |
| { |
| #if 0 |
| { |
| u16_t i; |
| DbgPrint("rspLen=%d\n", rspLen); |
| for (i=0; i<(rspLen/4); i++) |
| { |
| DbgPrint("rsp[%d]=0x%lx\n", i, rsp[i]); |
| } |
| } |
| #endif |
| status = (u16_t)(rsp[3] >> 16); |
| |
| ////6789 |
| rsp[8] = rsp[8] >> 2 | (rsp[9] & 0x1) << 6; |
| switch (status) |
| { |
| case ZM_STATUS_RETRY_COMP : |
| zfCoreEvent(dev, 1, u8rsp); |
| break; |
| case ZM_STATUS_TX_FAILED : |
| zfCoreEvent(dev, 2, u8rsp); |
| break; |
| case ZM_STATUS_TX_COMP : |
| zfCoreEvent(dev, 3, u8rsp); |
| break; |
| } |
| } |
| else if (type == 0xC2) |
| { |
| zfBeaconCfgInterrupt(dev, u8rsp); |
| } |
| else if (type == 0xC3) |
| { |
| zfEndOfAtimWindowInterrupt(dev); |
| } |
| else if (type == 0xC4) |
| { |
| #if 0 |
| { |
| u16_t i; |
| DbgPrint("0xC2:rspLen=%d\n", rspLen); |
| for (i=0; i<(rspLen/4); i++) |
| { |
| DbgPrint("0xC2:rsp[%d]=0x%lx\n", i, rsp[i]); |
| } |
| } |
| #endif |
| bitmap = (rsp[1] >> 16) + ((rsp[2] & 0xFFFF) << 16 ); |
| //zfBawCore(dev, (u16_t)rsp[1] & 0xFFFF, bitmap, (u16_t)(rsp[2] >> 16) & 0xFF); |
| } |
| else if (type == 0xC5) |
| { |
| u16_t i; |
| #if 0 |
| |
| for (i=0; i<(rspLen/4); i++) { |
| DbgPrint("0xC5:rsp[%d]=0x%lx\n", i, rsp[i]); |
| } |
| #endif |
| for (i=1; i<(rspLen/4); i++) { |
| u8rsp = (u8_t *)(rsp+i); |
| //DbgPrint("0xC5:rsp[%d]=0x%lx\n", i, ((u32_t*)u8rsp)[0]); |
| zfCoreEvent(dev, 4, u8rsp); |
| } |
| } |
| else if (type == 0xC6) |
| { |
| zm_debug_msg0("\n\n WatchDog interrupt!!! : 0xC6 \n\n"); |
| if (wd->zfcbHwWatchDogNotify != NULL) |
| { |
| wd->zfcbHwWatchDogNotify(dev); |
| } |
| } |
| else if (type == 0xC8) |
| { |
| //PZSW_ADAPTER adapter; |
| |
| // for SPI flash program chk Flag |
| zfwDbgProgrameFlashChkDone(dev); |
| } |
| else if (type == 0xC9) |
| { |
| struct zsHpPriv* hpPriv=wd->hpPrivate; |
| |
| zm_debug_msg0("##### Tx retransmission 5 times event #####"); |
| |
| /* correct tx retransmission issue */ |
| hpPriv->retransmissionEvent = 1; |
| } |
| } |
| else |
| { |
| zfIdlRsp(dev, rsp, rspLen); |
| } |
| } |
| |
| |
| #define ZM_PROGRAM_RAM_ADDR 0x200000 //0x1000 //0x700000 |
| #define FIRMWARE_DOWNLOAD 0x30 |
| #define FIRMWARE_DOWNLOAD_COMP 0x31 |
| #define FIRMWARE_CONFIRM 0x32 |
| |
| u16_t zfFirmwareDownload(zdev_t* dev, u32_t* fw, u32_t len, u32_t offset) |
| { |
| u16_t ret = ZM_SUCCESS; |
| u32_t uCodeOfst = offset; |
| u8_t *image, *ptr; |
| u32_t result; |
| |
| image = (u8_t*) fw; |
| ptr = image; |
| |
| while (len > 0) |
| { |
| u32_t translen = (len > 4096) ? 4096 : len; |
| |
| result = zfwUsbSubmitControl(dev, FIRMWARE_DOWNLOAD, |
| (u16_t) (uCodeOfst >> 8), |
| 0, image, translen); |
| |
| if (result != ZM_SUCCESS) |
| { |
| zm_msg0_init(ZM_LV_0, "FIRMWARE_DOWNLOAD failed"); |
| ret = 1; |
| goto exit; |
| } |
| |
| len -= translen; |
| image += translen; |
| uCodeOfst += translen; // in Word (16 bit) |
| |
| result = 0; |
| } |
| |
| /* If download firmware success, issue a command to firmware */ |
| if (ret == 0) |
| { |
| result = zfwUsbSubmitControl(dev, FIRMWARE_DOWNLOAD_COMP, |
| 0, 0, NULL, 0); |
| |
| if (result != ZM_SUCCESS) |
| { |
| zm_msg0_init(ZM_LV_0, "FIRMWARE_DOWNLOAD_COMP failed"); |
| ret = 1; |
| goto exit; |
| } |
| } |
| |
| #if 0 |
| /* PCI code */ |
| /* Wait for firmware ready */ |
| result = zfwUsbSubmitControl(dev, FIRMWARE_CONFIRM, USB_DIR_IN | 0x40, |
| 0, 0, &ret_value, sizeof(ret_value), HZ); |
| |
| if (result != 0) |
| { |
| zm_msg0_init(ZM_LV_0, "Can't receive firmware ready: ", result); |
| ret = 1; |
| } |
| #endif |
| |
| exit: |
| |
| return ret; |
| |
| } |
| |
| u16_t zfFirmwareDownloadNotJump(zdev_t* dev, u32_t* fw, u32_t len, u32_t offset) |
| { |
| u16_t ret = ZM_SUCCESS; |
| u32_t uCodeOfst = offset; |
| u8_t *image, *ptr; |
| u32_t result; |
| |
| image = (u8_t*) fw; |
| ptr = image; |
| |
| while (len > 0) |
| { |
| u32_t translen = (len > 4096) ? 4096 : len; |
| |
| result = zfwUsbSubmitControl(dev, FIRMWARE_DOWNLOAD, |
| (u16_t) (uCodeOfst >> 8), |
| 0, image, translen); |
| |
| if (result != ZM_SUCCESS) |
| { |
| zm_msg0_init(ZM_LV_0, "FIRMWARE_DOWNLOAD failed"); |
| ret = 1; |
| goto exit; |
| } |
| |
| len -= translen; |
| image += translen; |
| uCodeOfst += translen; // in Word (16 bit) |
| |
| result = 0; |
| } |
| |
| exit: |
| |
| return ret; |
| |
| } |
| |
| /************************************************************************/ |
| /* */ |
| /* FUNCTION DESCRIPTION zfIdlGetFreeTxdCount */ |
| /* Get free PCI PCI TxD count. */ |
| /* */ |
| /* INPUTS */ |
| /* dev : device pointer */ |
| /* */ |
| /* OUTPUTS */ |
| /* None */ |
| /* */ |
| /* AUTHOR */ |
| /* Stephen ZyDAS Technology Corporation 2006.6 */ |
| /* */ |
| /************************************************************************/ |
| u32_t zfHpGetFreeTxdCount(zdev_t* dev) |
| { |
| return zfwUsbGetFreeTxQSize(dev); |
| } |
| |
| u32_t zfHpGetMaxTxdCount(zdev_t* dev) |
| { |
| //return 8; |
| return zfwUsbGetMaxTxQSize(dev); |
| } |
| |
| void zfiUsbRegOutComplete(zdev_t* dev) |
| { |
| return; |
| } |
| |
| extern void zfPushVtxq(zdev_t* dev); |
| |
| void zfiUsbOutComplete(zdev_t* dev, zbuf_t *buf, u8_t status, u8_t *hdr) { |
| #ifndef ZM_ENABLE_AGGREGATION |
| if (buf) { |
| zfwBufFree(dev, buf, 0); |
| } |
| #else |
| #ifdef ZM_BYPASS_AGGR_SCHEDULING |
| //Simply free the buf since BA retransmission is done in the firmware |
| if (buf) |
| { |
| zfwBufFree(dev, buf, 0); |
| } |
| zfPushVtxq(dev); |
| #else |
| zmw_get_wlan_dev(dev); |
| |
| #ifdef ZM_ENABLE_FW_BA_RETRANSMISSION |
| //Simply free the buf since BA retransmission is done in the firmware |
| if (buf) |
| { |
| zfwBufFree(dev, buf, 0); |
| } |
| #else |
| u8_t agg; |
| u16_t frameType; |
| |
| if(!hdr && buf) { |
| zfwBufFree(dev, buf, 0); |
| //zm_debug_msg0("buf Free due to hdr == NULL"); |
| return; |
| } |
| |
| if(hdr && buf) { |
| frameType = hdr[8] & 0xf; |
| agg = (u8_t)(hdr[2] >> 5 ) & 0x1; |
| //zm_debug_msg1("AGG=", agg); |
| |
| if (!status) { |
| if (agg) { |
| //delete buf in ba fail queue?? |
| //not ganna happen? |
| } |
| else { |
| zfwBufFree(dev, buf, 0); |
| } |
| } |
| else { |
| if (agg) { |
| //don't do anything |
| //zfwBufFree(dev, buf, 0); |
| } |
| else { |
| zfwBufFree(dev, buf, 0); |
| } |
| } |
| } |
| #endif |
| |
| if (wd->state != ZM_WLAN_STATE_ENABLED) { |
| return; |
| } |
| |
| if( (wd->wlanMode == ZM_MODE_AP) || |
| (wd->wlanMode == ZM_MODE_INFRASTRUCTURE && wd->sta.EnableHT) || |
| (wd->wlanMode == ZM_MODE_PSEUDO) ) { |
| zfAggTxScheduler(dev, 0); |
| } |
| #endif |
| #endif |
| |
| return; |
| |
| } |
| |