void LinkRxSetup(unsigned char *bssid, unsigned char *macaddr) { DeviceReceiveDisable(); // // cleanup descriptors created last time // LinkRxLoopDestroy(0); /* * create a few descriptors linked in a loop */ LinkRxLoopCreate(MQUEUE); #ifdef UNUSED this should always be turned on ar5kInitData[pLibDev->ar5kInitIndex].pMacAPI->setPPM(0, enablePPM); pLibDev->rx.rxEnable = 1; #endif DeviceStationIdSet(macaddr); DeviceBssIdSet(bssid); DeviceReceiveDeafMode(0); return; }
void LinkRxComplete(int timeout, int ndump, unsigned char *dataPattern, int dataPatternLength, int (*done)()) { unsigned int startTime, endTime, ctime; int it; int notdone; int stop; int behind; int scount; unsigned int mDescriptor; // address of descriptor in shared memory #ifdef MEMORYREAD unsigned int descriptor[MDESCRIPTOR+30]; // private copy of current descriptor #else unsigned int *descriptor; #endif int pass; int dsize; int isdone; pass=0; dataPatternLength=0; dataPattern=0; scount=0; dsize=RxDescriptorSize(); // // Loop timeout condition. // This number can be large since it is only used for // catastrophic failure of cart. The normal terminating // condition is a message from cart saying STOP. // startTime=TimeMillisecond(); ctime=startTime; // if(timeout<=0) // { // timeout=60*60*1000; // one hour // } endTime=startTime+timeout; // // set pointer to first descriptor // // mDescriptor = LinkRxLoopFirst(0); // // keep track of how many times we look and the descriptor is not done // this is used to control the sleep interval // notdone=0; stop=0; behind=0; // // loop looking for descriptors with received packets. // for(it = 0; ; it++) { mDescriptor=LinkRxLoopDescriptor[it%LinkRxLoopMany]; #ifdef MEMORYREAD // // read the next descriptor // MyMemoryRead(mDescriptor, descriptor, dsize); #else descriptor=(unsigned int *)MyMemoryPtr(mDescriptor); #endif // // descriptor is ready, we have a new packet // if(RxDescriptorDone(descriptor)) { #ifdef MEMORYREAD // // read the next descriptor // MyMemoryRead(mDescriptor, descriptor, dsize); #endif notdone=0; behind++; scount=0; #ifdef FASTER if((it%100)==0) { UserPrint(" %d",it); } #endif // // dump packet contents // if(ndump>0) { UserPrint("\n"); LinkRxDump(descriptor, ndump, it%LinkRxLoopMany); } // // extract stats // LinkRxStatExtract(descriptor,it); // // reset the descriptor so that we can use it again // RxDescriptorReset(descriptor); #ifdef MEMORYREAD // // copy it back to the shared memory // MyMemoryWrite(mDescriptor,descriptor,dsize); #endif // // need to queue the descriptor with the hardware // if(LinkRxDescriptorFifo) { DeviceReceiveDescriptorPointer(mDescriptor); } } // // descriptor not ready // else { if(stop) { scount++; if(scount>200) { break; } } it--; // // sleep every other time, need to keep up with fast rates // if(notdone>100) { UserPrint("."); // MyDelay(1); notdone=0; } else { notdone=1; // this makes sure we never sleep } } // // check for message from cart telling us to stop // this is the normal terminating condition // pass++; if(pass>100) { if(done!=0) { isdone=(*done)(); if(isdone!=0) { UserPrint(" %d Stop",it); if(stop==0) { stop=1; scount=0; behind=0; } // // immediate stop // if(isdone==2) { break; } // break; } } pass=0; // // check for timeout // rare terminating condition when cart crashes or disconnects // ctime=TimeMillisecond(); if(timeout>0 && ((endTime>startTime && (ctime>endTime || ctime<startTime)) || (endTime<startTime && ctime>endTime && ctime<startTime))) { UserPrint("%d Timeout",it); break; } } } // // cleanup // DeviceReceiveDisable(); LinkRxLoopDestroy(0); // // do data verify if requested // UserPrint(" %d\n",it); LinkRxStatFinish(); return; }
int DescriptorLinkTxSetup(int *rate, int nrate, int ir, unsigned char *bssid, unsigned char *source, unsigned char *destination, int numDescPerRate, int dataBodyLength, int retries, int antenna, int broadcast, int ifs, int shortGi, unsigned int txchain, int naggregate, unsigned char *pattern, int npattern) { int it; unsigned int antMode = 0; int queueIndex; int dcuIndex; int wepEnable; static unsigned char bcast[]={0xff,0xff,0xff,0xff,0xff,0xff}; unsigned char *duse; unsigned char *ptr; DescriptorLinkRxOptions(); DescriptorLinkTxOptions(); TxStatusCheck(); DeviceTransmitDisable(0xffff); DeviceReceiveDisable(); TxStatusCheck(); // // do we still need these? // wepEnable=0; queueIndex=0; dcuIndex=0; // // Cleanup any descriptors and memory used in previous iteration // Make sure you do these first, since they actually destroy everything. // LinkTxLoopDestroy(); DescriptorLinkRxLoopDestroy(); // // remember some parameters for later use when we queue packets // TxChain=txchain; ShortGi=shortGi; Broadcast=broadcast; Retry=retries; PacketMany= numDescPerRate; // // adjust aggregate parameters to the range [1,MAGGREGATE] // if(naggregate<=1) { AggregateMany=1; AggregateBar=0; } else { AggregateMany=naggregate; if(AggregateMany>MAGGREGATE) { AggregateMany=MAGGREGATE; } // // determine if we should do special block acknowledgement request (BAR) packet // if(Broadcast) { AggregateBar=0; } else { AggregateBar=0; // never do this } // // treat the incoming number of packets as the total // but we treat it internally as the number of aggregate groups, so divide // if(PacketMany>0) { PacketMany/=AggregateMany; if(PacketMany<=0) { PacketMany=1; } } // // enforce maximun aggregate size of 64K // if(AggregateMany*dataBodyLength>65535) { AggregateMany=65535/dataBodyLength; UserPrint("reducing AggregateMany from %d to %d=65535/%d\n",naggregate,AggregateMany,dataBodyLength); } } // // Count rates and make the internal rate arrays. // RateMany = nrate; for(it=0; it<RateMany; it++) { Rate[it]=rate[it]; } //RateCount(rateMask, rateMaskMcs20, rateMaskMcs40, Rate); // // Remember other parameters, for descriptor queueing. // if(PacketMany>0) { InterleaveRate=ir; } else { InterleaveRate=1; } // // If the user asked for an infinite number of packets, set to a million // and force interleave rates on. // if(PacketMany<=0) { // PacketMany=1000000; LinkTxMany= -1; InterleaveRate=1; } // // if in tx100 mode, we only do one packet at the first rate // if(ifs==0) { // // tx100 // RateMany=1; PacketMany=1; Tx100Packet = 1; Broadcast=1; } else if(ifs>0) { // // tx99 // Tx100Packet = 0; Broadcast=1; } else { // // regular // Tx100Packet = 0; } // // If broadcast use the special broadcast address. otherwise, use the specified receiver // if(Broadcast) { duse=bcast; } else { duse=destination; } if(!Broadcast && !DeafMode) { // // Make rx descriptor // DescriptorLinkRxLoopCreate(MQUEUE); } // // calculate the total number of packets we expect to send. // and then figure out how many we should do in each batch. // if the number of packets is small, we may be able to do them in one batch. // if(PacketMany>0) { LinkTxMany=PacketMany*RateMany*(AggregateMany+AggregateBar); if(PacketMany>0 && LinkTxMany<=MQUEUE) { LinkTxBatchMany=LinkTxMany; // do in one batch LinkTxDescriptorMany=LinkTxMany; } else { LinkTxBatchMany=MQUEUE/2; // do in two or more batches LinkTxBatchMany/=(AggregateMany+AggregateBar); // force complete Aggregate into a batch LinkTxBatchMany*=(AggregateMany+AggregateBar); LinkTxDescriptorMany=2*LinkTxBatchMany; } } else { LinkTxBatchMany=MQUEUE/2; // do in two or more batches LinkTxBatchMany/=(AggregateMany+AggregateBar); // force complete Aggregate into a batch LinkTxBatchMany*=(AggregateMany+AggregateBar); LinkTxDescriptorMany=2*LinkTxBatchMany; } // // now calculate the number of tx responses we expect // // Merlin and before return a response for every queued descriptor but only // the terminating descriptor for an aggregate has the done bit set. Skip the others in LinkTxComplete(). // // Osprey only returns status for the terminating packet of aggregates, so there are // fewer status descriptors than control descriptors. // if(LinkTxAggregateStatus || AggregateMany<=1 || PacketMany<=0) { LinkTxStatusMany=LinkTxMany; } else { LinkTxStatusMany=0; for(it=0; it<RateMany; it++) { if(IS_LEGACY_RATE_INDEX(Rate[it])) { // // legacy rates don't support aggrgegates // LinkTxStatusMany+=(PacketMany*(AggregateMany+AggregateBar)); } else { // // only 1 status message is returned for aggregates // LinkTxStatusMany+=(PacketMany*(1+AggregateBar)); } } } UserPrint("TxMany=%d TxStatusMany=%d TxBatchMany=%d TxDescriptorMany=%d\n",LinkTxMany,LinkTxStatusMany,LinkTxBatchMany,LinkTxDescriptorMany); // // create the required number of descriptors // LinkTxLoopDescriptor[0] = MemoryLayout(LinkTxDescriptorMany * TxDescriptorSize()); if(LinkTxLoopDescriptor[0]==0) { UserPrint("txDataSetup: unable to allocate client memory for %d control descriptors\n",LinkTxDescriptorMany); return -1; } for(it=0; it<LinkTxDescriptorMany; it++) { LinkTxLoopDescriptor[it]=LinkTxLoopDescriptor[0]+it*TxDescriptorSize(); } // // make status descriptors // // for pre-Osprey chips, these pointers point to the regular tx descriptor // if(LinkTxStatusLoopCreate(LinkTxDescriptorMany)) { return -1; } // // use PN9 data if no pattern is specified // UserPrint("npattern=%d pattern=%x\n",npattern,pattern); if(npattern<=0) { pattern=PN9Data; npattern=sizeof(PN9Data); } UserPrint("npattern=%d pattern=%x\n",npattern,pattern); ptr=(unsigned char *)pattern; if(ptr!=0) { UserPrint("pattern: "); for(it=0; it<npattern; it++) { UserPrint("%2x ",ptr[it]); } UserPrint("\n"); } // // setup the transmit packets // if(AggregateMany>1) { for(it=0; it<AggregateMany; it++) { LinkTxAggregatePacketCreate(dataBodyLength, pattern, npattern, bssid, source, duse, Tx100Packet, wepEnable, it, AggregateBar); if(LinkTxLoopBuffer(it)==0) { UserPrint("txDataSetup: unable to allocate memory for packet %d\n",it); return -1; } } // // setup the BAR packet // if(AggregateBar>0) { LinkTxBarCreate(source, duse); if(LinkTxBarBuffer==0) { UserPrint("txDataSetup: unable to allocate memory for bar packet\n"); return -1; } } } else { LinkTxPacketCreate(dataBodyLength,pattern,npattern, bssid, source, duse, Tx100Packet,wepEnable); if(LinkTxLoopBuffer(0)==0) { UserPrint("txDataSetup: unable to allocate memory for packet\n"); return -1; } } DeviceTransmitRetryLimit(dcuIndex,retries); // // regular mode // if(ifs<0) { DeviceTransmitRegularData(); DeafMode=0; } // // tx99 mode // else if(ifs>0) { DeviceTransmitFrameData(ifs); DeafMode=1; } // // tx100 mode // else { DeviceTransmitContinuousData(); DeafMode=1; } //#ifdef BADBADBAD // i don't think this works DeviceReceiveDeafMode(DeafMode); //#endif DeviceBssIdSet(bssid); DeviceStationIdSet(source); // // make the first batch of transmit control descriptors, but don't queue them yet // LinkTxBatchNext(0,0); LinkTxBatchNext(LinkTxBatchMany,0); return 0; }
// Added VSG sync detection void LinkRxComplete_vsgSync(int timeout, int ndump, unsigned char *dataPattern, int dataPatternLength, int (*done)(), int chainMask) { unsigned int startTime, endTime, ctime; int it, ii; int notdone; int stop; int behind; int scount; unsigned int mDescriptor; // address of descriptor in shared memory #ifdef MEMORYREAD unsigned int descriptor[MDESCRIPTOR+30]; // private copy of current descriptor #else unsigned int *descriptor; #endif int pass; int dsize; int isdone; int ss; int rssic[MCHAIN], rssie[MCHAIN], rssi; #define MSPECTRUM 1024 int nspectrum,spectrum[MSPECTRUM]; int ndata; unsigned char data[MBUFFER]; int sscount=0; unsigned int vsgSync = 0; pass=0; dataPatternLength=0; dataPattern=0; scount=0; dsize=RxDescriptorSize(); // // Loop timeout condition. // This number can be large since it is only used for // catastrophic failure of cart. The normal terminating // condition is a message from cart saying STOP. // startTime=TimeMillisecond(); ctime=startTime; if(timeout<=0) { timeout=2*60*1000; // 2 mins } endTime=startTime+timeout; // // set pointer to first descriptor // // mDescriptor = LinkRxLoopFirst(0); // // keep track of how many times we look and the descriptor is not done // this is used to control the sleep interval // notdone=0; stop=0; behind=0; // // loop looking for descriptors with received packets. // for(it = 0; ; it++) { mDescriptor=LinkRxLoopDescriptor[it%LinkRxLoopMany]; #ifdef MEMORYREAD // // read the next descriptor // MyMemoryRead(mDescriptor, descriptor, dsize); #else descriptor=(unsigned int *)MyMemoryPtr(mDescriptor); #endif // // descriptor is ready, we have a new packet // if(RxDescriptorDone(descriptor)) { #ifdef MEMORYREAD // // read the next descriptor // MyMemoryRead(mDescriptor, descriptor, dsize); #endif notdone=0; behind++; scount=0; #ifdef FASTER if((it%SASAMPLINGS)==0) { UserPrint(" %d",it); } #endif if(_LinkRxSpectralScan) { ss=Ar9300RxDescriptorSpectralScan(descriptor); if(ss) { // // extract rssi and evm measurements. we need these for both good and bad packets // rssi=RxDescriptorRssiCombined(descriptor); if(rssi&0x80) { rssi|=0xffffff00; } rssic[0]=RxDescriptorRssiAnt00(descriptor); rssic[1]=RxDescriptorRssiAnt01(descriptor); rssic[2]=RxDescriptorRssiAnt02(descriptor); rssie[0]=RxDescriptorRssiAnt10(descriptor); rssie[1]=RxDescriptorRssiAnt11(descriptor); rssie[2]=RxDescriptorRssiAnt12(descriptor); for(ii=0; ii<3; ii++) { if(rssic[ii]&0x80) { rssic[ii]|=0xffffff00; } if(rssie[ii]&0x80) { rssie[ii]|=0xffffff00; } } ndata=RxDescriptorDataLen(descriptor); MyMemoryRead(LinkRxLoopBuffer[it%LinkRxLoopMany], (unsigned int *)data, ndata); nspectrum=Ar9300SpectralScanProcess(data,ndata,spectrum,MSPECTRUM); if(_LinkRxSpectralScanFunction!=0) { (*_LinkRxSpectralScanFunction)(rssi,rssic,rssie,MCHAIN,spectrum,nspectrum); } // // extract stats if (!vsgSync) { vsgSync = ((rssic[0] >= ISSM80DBM_THRESHOLD) && (chainMask & (1 << 0)) || (rssic[1] >= ISSM80DBM_THRESHOLD) && (chainMask & (1 << 1)) || (rssic[2] >= ISSM80DBM_THRESHOLD) && (chainMask & (1 << 2)) ); } else { LinkRxStatSpectralScanExtract(descriptor,it); sscount++; //UserPrint("ss_cnt:rssic:mask %d, %d, %d, %d\n",sscount, rssic[0], rssic[1], chainMask); } if(sscount >= SASAMPLINGS) { break; } } } else { // dump packet contents // if(ndump>0) { UserPrint("\n"); LinkRxDump(descriptor, ndump, it%LinkRxLoopMany); } // // extract stats // LinkRxStatExtract(descriptor,it); } // // reset the descriptor so that we can use it again // RxDescriptorReset(descriptor); #ifdef MEMORYREAD // // copy it back to the shared memory // MyMemoryWrite(mDescriptor,descriptor,dsize); #endif // // need to queue the descriptor with the hardware // if(LinkRxDescriptorFifo) { DeviceReceiveDescriptorPointer(mDescriptor); } } // // descriptor not ready // else { if(stop) { scount++; if(scount>200) { break; } } it--; // // sleep every other time, need to keep up with fast rates // if(notdone>100) { UserPrint("."); // MyDelay(1); notdone=0; } else { notdone=1; // this makes sure we never sleep } } // // check for message from cart telling us to stop // this is the normal terminating condition // pass++; if(pass>100) { if(done!=0) { isdone=(*done)(); if(isdone!=0) { UserPrint(" %d Stop",it); if(stop==0) { stop=1; scount=0; behind=0; } // // immediate stop // if(isdone==2) { break; } // break; } } pass=0; // // check for timeout // rare terminating condition when cart crashes or disconnects // ctime=TimeMillisecond(); #if 1 if( timeout>0 && ((endTime>startTime && (ctime>endTime || ctime<startTime)) || (endTime<startTime && ctime>endTime && ctime<startTime))) { UserPrint("%d Timeout",it); break; } #endif } } // // cleanup // if(_LinkRxSpectralScan) { //DeviceSpectralScanDisable(); Ar9300SpectralScanDisable(); } DeviceReceiveDisable(); LinkRxLoopDestroy(0); // // do data verify if requested // UserPrint(" %d\n",it); LinkRxStatFinish(); return; }
// // run the transmitter // // (*ison)() is called when the transmitter is guaranteed to be on (first descriptor returned done) // // (*done)() is called to check if this function should stop early // int DescriptorLinkTxComplete(int timeout, int (*ison)(), int (*done)(), int chipTemperature, int calibrate) { int it; unsigned int startTime, endTime, ctime, failTime; int failRetry; int notdone; unsigned int mDescriptor; // address of descriptor in shared memory unsigned int descriptor[MDESCRIPTOR]; // private copy of current descriptor int cindex; // index of the corresponding control descriptor unsigned int *cd,cdescriptor[MDESCRIPTOR]; // private copy of current control descriptor int pass; int dsize; // int behind; int batch, lbatch; int temperature; int doTemp; LinkTxStatClear(); lbatch=0; pass=0; doTemp=0; dsize=TxDescriptorSize(); // // Loop timeout condition. // This number can be large since it is only used for // catastrophic failure of cart. The normal terminating // condition is a message from cart saying STOP. // startTime=TimeMillisecond(); ctime=startTime; // if(timeout<=0) // { // timeout=60*60*1000; // one hour // } endTime=startTime+timeout; if(Tx100Packet) { failTime=endTime; } else { failTime=startTime+(5*1000); // 5 seconds } failRetry=0; // // set pointer to first descriptor // mDescriptor = LinkTxLoopFirst(); // // keep track of how many times we look and the descriptor is not done // this is used to control the sleep interval // notdone=0; // tlast=0; // // if this is the first descriptor, announce that the transmitter is really on // if(ison!=0) { (*ison)(); } // // loop looking for descriptors with transmitted packets. // terminate either when we reach a null pointer (Merlin and prior) or // when we've done the specified number of packets (Osprey) // for(it=0; (LinkTxStatusMany<=0 || it<LinkTxStatusMany); it++) { // // read the next descriptor // mDescriptor=LinkTxLoopDescriptorStatus[it%LinkTxDescriptorMany]; DeviceMemoryRead(mDescriptor, descriptor, dsize); // // skip ahead for aggregates. // if(LinkTxAggregateStatus) { if(TxDescriptorAggregate(descriptor) && TxDescriptorMoreAgg(descriptor)) { // UserPrint("A"); continue; } } // // is it done? // if(TxDescriptorDone(descriptor)) { cindex=LinkTxQueued[it%LinkTxDescriptorMany]; batch=cindex/LinkTxBatchMany; // UserPrint("(%d %d %d)",it,cindex,batch); DeviceMemoryRead(mDescriptor, descriptor, dsize); // // get the control descriptor too // if(LinkTxSplitDescriptor) { DeviceMemoryRead(LinkTxLoopDescriptor[cindex%LinkTxDescriptorMany], cdescriptor, TxDescriptorSize()); cd=cdescriptor; } else { cd=descriptor; } #ifdef UNUSED behind=(TxDescriptorPointerGet()-mDescriptor)/dsize; if(behind>10) { UserPrint(" -%d",behind); } #endif notdone=0; if((it%100)==0) { UserPrint(" %d",it); } LinkTxStatExtract(descriptor,cd,AggregateMany,it); // // clear the status packet // if(LinkTxSplitDescriptor) { TxDescriptorStatusSetup(descriptor); DeviceMemoryWrite(LinkTxLoopDescriptorStatus[it%LinkTxDescriptorMany],descriptor,TxDescriptorStatusSize()); } // // Do we need to queue the next batch of descriptors? // if(batch>lbatch) { // UserPrint("\n%d %d %d %d\n",it,cindex,lbatch,batch); LinkTxBatchNext((batch+1)*LinkTxBatchMany,1); lbatch=batch; } } // // descriptor isn't done // else { it--; // // sleep every other time, need to keep up with fast rates // if(notdone>100) { UserPrint("."); // MyDelay(1); notdone=0; } else { notdone++; } } // // check temperature // if(doTemp>10) { temperature=DeviceTemperatureGet(0); // // are we supposed to terminate on reaching a certain chip temperature? // if(chipTemperature>0) { if(temperature<=chipTemperature) { UserPrint(" %d Temperature %d <= %d",it,temperature,chipTemperature); break; } } doTemp=0; } doTemp++; // // check for message from cart telling us to stop // this is the normal terminating condition // pass++; if(pass>100) { if(done!=0) { if((*done)()) { UserPrint(" %d Stop",it); break; } } pass=0; // // check for timeout // rare terminating condition when cart crashes or disconnects // ctime=TimeMillisecond(); if(timeout>0 && ((endTime>startTime && (ctime>endTime || ctime<startTime)) || (endTime<startTime && ctime>endTime && ctime<startTime))) { UserPrint(" %d Timeout",it); break; } // // check for failure to start // if(it<=0) { if((failTime>startTime && (ctime>failTime || ctime<startTime)) || (failTime<startTime && ctime>failTime && ctime<startTime)) { UserPrint("Failed to start transmit.\n"); if(failRetry==0) { UserPrint("Trying to restart.\n"); DescriptorLinkTxStart(); failTime=startTime+(5*1000); // 5 seconds failRetry++; // // set pointer to first descriptor // mDescriptor = LinkTxLoopFirst(); } else { ResetForce(); break; } } } } } TxStatusCheck(); DeviceTransmitDisable(0xffff); DeviceReceiveDisable(); LinkTxLoopDestroy(); DescriptorLinkRxLoopDestroy(); // // finish throughput calculation // LinkTxStatFinish(); TxStatusCheck(); UserPrint(" %d Done\n",it); return 0; }