/*************************************************************************** Routine Description: This is the defered processing routine for interrupts. It reads from the Interrupt Status Register any outstanding interrupts and handles them. Arguments: MiniportAdapterContext - a handle to the adapter block. Return Value: NONE. *****************************************************************************/ void R6040HandleInterrupt(IN NDIS_HANDLE MiniportAdapterContext) { // The adapter to process PR6040_ADAPTER Adapter = ((PR6040_ADAPTER)MiniportAdapterContext); NdisDprAcquireSpinLock(&Adapter->Lock); // Handle the interrupts if (Adapter->InterruptStatus & MISR_TXEND) { NdisAcquireSpinLock(&Adapter->SendLock); // Handle the transmit R6040XmitDpc(Adapter); NdisReleaseSpinLock(&Adapter->SendLock); } if (Adapter->InterruptStatus & MISR_RXEND) { NdisDprAcquireSpinLock(&Adapter->RcvLock); // For receives, call this to handle the receive R6040RcvDpc(Adapter); NdisDprReleaseSpinLock(&Adapter->RcvLock); } NdisDprReleaseSpinLock(&Adapter->Lock); }
STATIC VOID LtIndicateReceiveComplete( IN PLOOP_ADAPTER Adapter ) { PLOOP_OPEN Open; PLIST_ENTRY CurrentLink = Adapter->OpenBindings.Flink; while(CurrentLink != &Adapter->OpenBindings) { Open = CONTAINING_RECORD( CurrentLink, LOOP_OPEN, OpenList); if (Open->Flags & BINDING_RECEIVED_PACKET) { NdisIndicateReceiveComplete(Open->NdisBindingContext); NdisDprAcquireSpinLock(&Adapter->Lock); Open->Flags &= ~BINDING_RECEIVED_PACKET; NdisDprReleaseSpinLock(&Adapter->Lock); } CurrentLink = CurrentLink->Flink; } }
VOID filterAcquireSpinLock( IN PFILTER_LOCK pLock, IN ULONG FileNumber, IN ULONG LineNumber, IN BOOLEAN DispatchLevel ) { if (DispatchLevel) { NdisDprAcquireSpinLock(&(filterdLockLock)); } else { NdisAcquireSpinLock(&(filterdLockLock)); } if (pLock->Signature != FILT_LOCK_SIG) { DbgPrint("Trying to acquire uninited lock 0x%x, File %c%c%c%c, Line %d\n", pLock, (CHAR)(FileNumber & 0xff), (CHAR)((FileNumber >> 8) & 0xff), (CHAR)((FileNumber >> 16) & 0xff), (CHAR)((FileNumber >> 24) & 0xff), LineNumber); DbgBreakPoint(); }
VOID LoopTimerProc( IN PVOID SystemSpecific1, IN PVOID Context, IN PVOID SystemSpecific2, IN PVOID SystemSpecific3 ) { PLOOP_ADAPTER Adapter = (PLOOP_ADAPTER)Context; DBGPRINT(DBG_COMP_DPC, DBG_LEVEL_INFO, (" --> LoopTimerProc\n")); NdisDprAcquireSpinLock(&Adapter->Lock); Adapter->References++; Adapter->TimerSet = FALSE; if ((Adapter->Loopback != NULL) && !Adapter->InTimerProc) { Adapter->InTimerProc = TRUE; LoopProcessLoopback(Adapter); Adapter->InTimerProc = FALSE; } Adapter->References--; NdisDprReleaseSpinLock(&Adapter->Lock); }
VOID ndisprotAcquireSpinLock( IN PNPROT_LOCK pLock, IN BOOLEAN DispatchLevel, IN ULONG FileNumber, IN ULONG LineNumber ) { PKTHREAD pThread; pThread = KeGetCurrentThread(); if (DispatchLevel == TRUE) { NdisDprAcquireSpinLock(&(ndisprotdLockLock)); } else { NdisAcquireSpinLock(&(ndisprotdLockLock)); } if (pLock->Signature != NPROTL_SIG) { DbgPrint("Trying to acquire uninited lock 0x%x, File %c%c%c%c, Line %d\n", pLock, (CHAR)(FileNumber & 0xff), (CHAR)((FileNumber >> 8) & 0xff), (CHAR)((FileNumber >> 16) & 0xff), (CHAR)((FileNumber >> 24) & 0xff), LineNumber); DbgBreakPoint(); }
VOID tapAdapterAcquireLock(__in PTAP_ADAPTER_CONTEXT Adapter, __in BOOLEAN DispatchLevel) { ASSERT(!DispatchLevel || (DISPATCH_LEVEL == KeGetCurrentIrql())); if (DispatchLevel) { NdisDprAcquireSpinLock(&Adapter->AdapterLock); } else { NdisAcquireSpinLock(&Adapter->AdapterLock); } }
VOID ParaNdis6_RSSAnalyzeReceivedPacket( PARANDIS_RSS_PARAMS *RSSParameters, PVOID dataBuffer, PNET_PACKET_INFO packetInfo) { NdisDprAcquireSpinLock(&RSSParameters->RSSSettingsLock); if(RSSParameters->RSSMode != PARANDIS_RSS_DISABLED) { RSSCalcHash(RSSParameters, dataBuffer, packetInfo); } NdisDprReleaseSpinLock(&RSSParameters->RSSSettingsLock); }
// 过滤向外发送的数据,从MPSendPackets或者MPSend函数调用 // 如果从MPSendPackets调用就运行在IRQL <= DISPATCH_LEVEL级别 // 如果从MPSend调用,就运行在IRQL == DISPATCH_LEVEL级别 BOOLEAN FltFilterSendPacket( IN PADAPT pAdapt, IN PNDIS_PACKET pSendPacket, IN BOOLEAN bDispatchLevel // TRUE -> IRQL == DISPATCH_LEVEL ) { BOOLEAN bPass = TRUE; PADAPT_FILTER_RSVD pFilterContext = (PADAPT_FILTER_RSVD)&pAdapt->FilterReserved; UCHAR buffer[MAX_PACKET_HEADER_LEN]; ULONG nReadBytes; // 当使用过滤数据时,要获取旋转锁 if(bDispatchLevel) { NdisDprAcquireSpinLock(&pAdapt->Lock); } else { NdisAcquireSpinLock(&pAdapt->Lock); } // 设置统计数字 pFilterContext->Statistics.nMPSendPktsCt ++; // 如果没有设置过滤规则,则放行所有封包 if(pFilterContext->pFilterList == NULL) goto ExitTheFilter; //////////////////////////////////////////////////// // 读取封包中的数据,这里仅读取封包头即可 FltReadPacketData(pSendPacket, buffer, MAX_PACKET_HEADER_LEN, &nReadBytes); // 检查过滤规则,看看是否允许这个封包通过 bPass = FltCheckFilterRules(pFilterContext->pFilterList, buffer, nReadBytes, TRUE); if(!bPass) { // 拒绝了一个封包 pFilterContext->Statistics.nMPSendPktsDropped ++; } ExitTheFilter: // 过滤之后要释放旋转锁 if(bDispatchLevel) NdisDprReleaseSpinLock(&pAdapt->Lock); else NdisReleaseSpinLock(&pAdapt->Lock); return bPass; }
void _rtw_spinlock_ex(_lock *plock) { #ifdef PLATFORM_LINUX spin_lock(plock); #endif #ifdef PLATFORM_WINDOWS NdisDprAcquireSpinLock(plock); #endif }
VOID natpQueueReceivedPacket( IN PFILTER_ADAPTER pAdapt, IN PNDIS_PACKET Packet, IN BOOLEAN DoIndicate ) { PNDIS_PACKET PacketArray[MAX_RCV_PKT_ARR_SZ]; ULONG NumberOfPackets = 0, i; NdisDprAcquireSpinLock(&pAdapt->Lock); ASSERT(pAdapt->ReceivedPacketCount < MAX_RCV_PKT_ARR_SZ); pAdapt->ReceivedPackets[pAdapt->ReceivedPacketCount] = Packet; pAdapt->ReceivedPacketCount++; if ((pAdapt->ReceivedPacketCount == MAX_RCV_PKT_ARR_SZ) || DoIndicate){ NdisMoveMemory(PacketArray, pAdapt->ReceivedPackets, pAdapt->ReceivedPacketCount * sizeof(PNDIS_PACKET)); NumberOfPackets = pAdapt->ReceivedPacketCount; pAdapt->ReceivedPacketCount = 0; NdisDprReleaseSpinLock(&pAdapt->Lock); if ((pAdapt->MiniportHandle != NULL) && (pAdapt->natmDeviceState == NdisDeviceStateD0)){ NdisMIndicateReceivePacket(pAdapt->MiniportHandle, PacketArray, NumberOfPackets); }else{ if (DoIndicate) NumberOfPackets -= 1; for (i = 0; i < NumberOfPackets; i++) natmReturnPacket(pAdapt, PacketArray[i]); } }else NdisDprReleaseSpinLock(&pAdapt->Lock); }
void _spinlock_ex(_lock *plock) { #ifdef PLATFORM_LINUX //eason 20100210 spin_lock(plock); cyg_mutex_t * mut_t = plock; cyg_mutex_lock(mut_t); #endif #ifdef PLATFORM_WINDOWS NdisDprAcquireSpinLock(plock); #endif }
STATIC VOID LtIndicateReceive( IN PLOOP_ADAPTER Adapter, IN UINT PacketType, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookaheadBuffer, IN UINT LookaheadBufferSize, IN UINT PacketSize ) { PLOOP_OPEN Open; PLIST_ENTRY CurrentLink = Adapter->OpenBindings.Flink; NDIS_STATUS Status; while(CurrentLink != &Adapter->OpenBindings) { Open = CONTAINING_RECORD( CurrentLink, LOOP_OPEN, OpenList); if (PacketType & Open->CurrentPacketFilter) { NdisIndicateReceive( &Status, Open->NdisBindingContext, NULL, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize, PacketSize); NdisDprAcquireSpinLock(&Adapter->Lock); Open->Flags |= BINDING_RECEIVED_PACKET; NdisDprReleaseSpinLock(&Adapter->Lock); } CurrentLink = CurrentLink->Flink; } }
VOID natpFlushReceiveQueue( IN PFILTER_ADAPTER pAdapt ) { PNDIS_PACKET PacketArray[MAX_RCV_PKT_ARR_SZ]; ULONG NumberOfPackets = 0, i; __try{ NdisDprAcquireSpinLock(&pAdapt->Lock); if (pAdapt->ReceivedPacketCount > 0){ NdisMoveMemory(PacketArray, pAdapt->ReceivedPackets, pAdapt->ReceivedPacketCount * sizeof(PNDIS_PACKET)); NumberOfPackets = pAdapt->ReceivedPacketCount; pAdapt->ReceivedPacketCount = 0; NdisDprReleaseSpinLock(&pAdapt->Lock); if ((pAdapt->MiniportHandle) && (pAdapt->natmDeviceState == NdisDeviceStateD0)){ NdisMIndicateReceivePacket(pAdapt->MiniportHandle, PacketArray, NumberOfPackets); __leave; } for (i = 0; i < NumberOfPackets; i ++) natmReturnPacket(pAdapt, PacketArray[i]); __leave; } NdisDprReleaseSpinLock(&pAdapt->Lock); }__finally{} }
CCHAR ParaNdis6_RSSGetCurrentCpuReceiveQueue(PARANDIS_RSS_PARAMS *RSSParameters) { CCHAR res; NdisDprAcquireSpinLock(&RSSParameters->RSSSettingsLock); if(RSSParameters->RSSMode != PARANDIS_RSS_FULL) { res = PARANDIS_RECEIVE_QUEUE_UNCLASSIFIED; } else { res = FindReceiveQueueForCurrentCpu(&RSSParameters->ActiveRSSScalingSettings); } NdisDprReleaseSpinLock(&RSSParameters->RSSSettingsLock); return res; }
// 过滤接收到的数据,从PtReceivePacket函数调用,运行在DISPATCH_LEVEL IRQL级别 BOOLEAN FltFilterReceivePacket( IN PADAPT pAdapt, IN PNDIS_PACKET pReceivedPacket ) { BOOLEAN bPass = TRUE; PADAPT_FILTER_RSVD pFilterContext = (PADAPT_FILTER_RSVD)&pAdapt->FilterReserved; UCHAR buffer[MAX_PACKET_HEADER_LEN]; ULONG nReadBytes; // 当使用过滤数据时,要获取旋转锁 NdisDprAcquireSpinLock(&pAdapt->Lock); // 设置统计数字 pFilterContext->Statistics.nPTRcvPktCt ++; // 如果没有设置过滤规则,则放行所有封包 if(pFilterContext->pFilterList == NULL) goto ExitTheFilter; //////////////////////////////////////////////////// // 读取封包中的数据,这里仅读取封包头即可 FltReadPacketData(pReceivedPacket, buffer, MAX_PACKET_HEADER_LEN, &nReadBytes); if(nReadBytes != MAX_PACKET_HEADER_LEN) { DBGPRINT((" FltFilterReceivePacket: nReadBytes != MAX_PACKET_HEADER_LEN")); } // 检查过滤规则,看看是否允许这个封包通过 bPass = FltCheckFilterRules(pFilterContext->pFilterList,buffer, nReadBytes, TRUE); if(!bPass) { // 拒绝了一个封包 pFilterContext->Statistics.nPTRcvPktDropped ++; } ExitTheFilter: // 过滤之后要释放旋转锁 NdisDprReleaseSpinLock(&pAdapt->Lock); return bPass; }
// 过滤接收到的数据,从PtReceivePacket函数调用,运行在DISPATCH_LEVEL IRQL级别 BOOLEAN FltFilterReceive( IN PADAPT pAdapt, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookAheadBufferSize, IN UINT PacketSize ) { BOOLEAN bPass = TRUE; PADAPT_FILTER_RSVD pFilterContext = (PADAPT_FILTER_RSVD)&pAdapt->FilterReserved; PETHeader pEtherHdr = (PETHeader)HeaderBuffer; // 当使用过滤数据时,要获取旋转锁 NdisDprAcquireSpinLock(&pAdapt->Lock); // 设置统计数字 pFilterContext->Statistics.nPTRcvCt ++; // 如果没有设置过滤规则,则放行所有封包 if(pFilterContext->pFilterList == NULL) goto ExitTheFilter; // 如果不是IP协议,则放行 if(pEtherHdr->type != 0x8) goto ExitTheFilter; // 检查过滤规则,看看是否允许这个封包通过 bPass = FltCheckFilterRules(pFilterContext->pFilterList,LookAheadBuffer, LookAheadBufferSize, FALSE); if(!bPass) { // 拒绝了一个封包 pFilterContext->Statistics.nPTRcvDropped ++; } ExitTheFilter: // 过滤之后要释放旋转锁 NdisDprReleaseSpinLock(&pAdapt->Lock); return bPass; }
CCHAR ParaNdis6_RSSGetScalingDataForPacket( PARANDIS_RSS_PARAMS *RSSParameters, PNET_PACKET_INFO packetInfo, PPROCESSOR_NUMBER targetProcessor) { CCHAR targetQueue; NdisDprAcquireSpinLock(&RSSParameters->RSSSettingsLock); if((RSSParameters->RSSMode != PARANDIS_RSS_FULL) || (packetInfo->RSSHash.Type == 0)) { targetQueue = PARANDIS_RECEIVE_QUEUE_UNCLASSIFIED; } else { ULONG indirectionIndex = packetInfo->RSSHash.Value & RSSParameters->ActiveRSSScalingSettings.RSSHashMask; *targetProcessor = RSSParameters->ActiveRSSScalingSettings.IndirectionTable[indirectionIndex]; targetQueue = RSSParameters->ActiveRSSScalingSettings.QueueIndirectionTable[indirectionIndex]; } NdisDprReleaseSpinLock(&RSSParameters->RSSSettingsLock); return targetQueue; }
int divert_filter( IN PADAPT pAdapt, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookAheadBufferSize, IN UINT PacketSize ) { #define MAC_SIZE 14 USHORT EtherType; ULONG NumberOfBytesRead; struct ether_header *pEthHdr; // See ../B2Winet/ethernet.h struct ip *pIPHeader; struct tcphdr *tcp; int rc = 0; struct divert_packet *dp, *cur; NDISPROT_ETH_HEADER UNALIGNED *pEthHeader; NdisDprAcquireSpinLock(&pAdapt->Lock); pEthHdr = (struct ether_header * )HeaderBuffer; pEthHeader = pEthHdr; if (ntohs( pEthHdr->ether_type ) != ETHERTYPE_IP) goto Out; if (get_pa(pEthHeader->SrcAddr)) goto Out; pIPHeader = (struct ip * )LookAheadBuffer; if (LookAheadBufferSize < 40) goto Out; if (pIPHeader->ip_p != IPPROTO_TCP) goto Out; tcp = (struct tcphr*) (pIPHeader + 1); #if 0 if (ntohs(tcp->th_dport) == 666) rc = 1; #endif lock(); if (!_open) goto Outl; dp = get_packet(); if (!dp) { DbgPrint("Out of queue - shit\n"); goto Outl; } if (LookAheadBufferSize != PacketSize) { NDIS_STATUS status; PNDIS_PACKET pkt; PNDIS_BUFFER buf; int len; if ((PacketSize + MAC_SIZE) > sizeof(dp->dp_packet)) { DbgPrint("cAZZOOOOOOOOOOOOOOOOOOOOOOOOOOo\n"); goto Fanculo; } NdisAllocatePacket(&status, &pkt, _packet_pool); NdisAllocateBuffer(&status, &buf, _buf_pool, dp->dp_packet + MAC_SIZE, sizeof(dp->dp_packet) - MAC_SIZE); NdisChainBufferAtFront(pkt, buf); NdisTransferData(&status, pAdapt->BindingHandle, MacReceiveContext, 0, PacketSize, pkt, &len); NdisFreeBuffer(buf); NdisFreePacket(pkt); } else { NdisCopyLookaheadData(dp->dp_packet + MAC_SIZE, LookAheadBuffer, LookAheadBufferSize, 0); } Fanculo: rc = 1; memcpy(dp->dp_packet, pEthHdr, MAC_SIZE); dp->dp_len = PacketSize + MAC_SIZE; dp->dp_flags = 1; kick_pending(); Outl: unlock(); Out: NdisDprReleaseSpinLock(&pAdapt->Lock); return rc; #undef MAC_SIZE }
VOID StaReceiveDisassociation( __in PSTATION pStation, __in PNIC_RX_FRAGMENT pNicFragment, __in ULONG TotalLength ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PUCHAR pPacketBuffer; PDOT11_DISASSOC_FRAME pDot11DisassocFrame = NULL; PDOT11_MGMT_HEADER pMgmtHeader; PSTA_BSS_ENTRY pAPEntry; BOOLEAN bDisassociate = TRUE; if (TotalLength < (sizeof(DOT11_MGMT_HEADER) + sizeof(DOT11_DISASSOC_FRAME))) { MpTrace(COMP_ASSOC, DBG_LOUD, ("Disassociation packet too short\n")); return ; } pPacketBuffer = Hw11GetFragmentDataStart(pNicFragment); // // Ref to make sure reset/halt does not leave while we are still working // STA_INCREMENT_REF(pStation->ConnectContext.AsyncFuncCount); // // Proceed only if we have received association packet // NdisDprAcquireSpinLock(&(pStation->ConnectContext.Lock)); if ((pStation->ConnectContext.ConnectState >= CONN_STATE_READY_TO_CONNECT) && (pStation->ConnectContext.AssociateState > ASSOC_STATE_WAITING_FOR_ASSOCIATE)) { pAPEntry = pStation->ConnectContext.ActiveAP; pMgmtHeader = (PDOT11_MGMT_HEADER)pPacketBuffer; // // Check that is a packet from the AP we are interested in // if (!MP_COMPARE_MAC_ADDRESS(pMgmtHeader->SA, pAPEntry->MacAddress) || !MP_COMPARE_MAC_ADDRESS(pMgmtHeader->BSSID, pAPEntry->Dot11BSSID) || !MP_COMPARE_MAC_ADDRESS(pMgmtHeader->DA, Hw11GetMACAddress(pStation->pNic))) { NdisDprReleaseSpinLock(&(pStation->ConnectContext.Lock)); MpTrace(COMP_ASSOC, DBG_LOUD, ("Disassociate packet not for me\n")); ndisStatus = NDIS_STATUS_NOT_ACCEPTED; } else { pDot11DisassocFrame = (PDOT11_DISASSOC_FRAME)(pPacketBuffer + sizeof(DOT11_MGMT_HEADER)); MpTrace(COMP_ASSOC, DBG_NORMAL, ("Received disassociation, reason %d - ", pDot11DisassocFrame->usReasonCode)); // // On a Disassociated, we would just send the deauthenticate // packet to the access point & move ourselves to ready state // if (pStation->ConnectContext.AssociateState == ASSOC_STATE_ASSOCIATED) { MpTrace(COMP_ASSOC, DBG_LOUD, ("After we were associated\n")); // // We were associated, cleanup state and indicate disassociation // pStation->ConnectContext.ActiveAP = NULL; bDisassociate = TRUE; pAPEntry->AssocState = dot11_assoc_state_unauth_unassoc; // Moving to unauthenticated pStation->ConnectContext.AssociateState = ASSOC_STATE_NOT_ASSOCIATED; } else { MpTrace(COMP_ASSOC, DBG_LOUD, ("While we were associating\n")); // // Receive disassociate while still attempting to associate. Set associate failed // so appropriate routine knows to fail the association attempt // pStation->ConnectContext.AssociateState = ASSOC_STATE_REMOTELY_DISASSOCIATED; bDisassociate = FALSE; } NdisDprReleaseSpinLock(&(pStation->ConnectContext.Lock)); if (bDisassociate) { // // Send deauthenticate (ignoring status) // StaSendDeauthentication( pStation, pAPEntry, DOT11_MGMT_REASON_UPSPEC_REASON ); // Indicate disassociation StaIndicateDisassociation( pStation, pAPEntry, DOT11_ASSOC_STATUS_PEER_DISASSOCIATED_START | pDot11DisassocFrame->usReasonCode ); NdisDprAcquireSpinLock(&(pStation->ConnectContext.Lock)); if (pStation->ConnectContext.ConnectState >= CONN_STATE_READY_TO_CONNECT) { // // We got disassociated, but we can still connect. We will // queue the periodic scan routine to attempt association // StaForceInternalScan(pStation, TRUE); } NdisDprReleaseSpinLock(&(pStation->ConnectContext.Lock)); } // // Raise cost and remove connection ref from the AP entry and raise cost // pAPEntry->AssocCost += STA_ASSOC_COST_REMOTE_DISCONNECT; STA_DECREMENT_REF(pAPEntry->RefCount); } } else { NdisDprReleaseSpinLock(&(pStation->ConnectContext.Lock)); } // Done STA_DECREMENT_REF(pStation->ConnectContext.AsyncFuncCount); }
NDIS_STATUS StaAssociate( __in PSTATION pStation, __in PSTA_BSS_ENTRY pAPEntry, __in ULONG AssociateTimeout ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PUCHAR pAssocPacket = NULL; USHORT AssocPacketLength; ULONG StatusCode = 0; MpEntry; do { // // Create the associate packet // ndisStatus = StaCreateAssociateRequestPacket( pStation, pAPEntry, &pAssocPacket, &AssocPacketLength ); if (ndisStatus != NDIS_STATUS_SUCCESS) { // // Complete the association process // StatusCode = ndisStatus; NdisAcquireSpinLock(&(pStation->ConnectContext.Lock)); if (pStation->ConnectContext.AssociateState == ASSOC_STATE_RECEIVED_AUTHENTICATE) { // // Reset ourselves to ready to original state // pStation->ConnectContext.AssociateState = ASSOC_STATE_STARTED_ASSOCIATION; } NdisReleaseSpinLock(&(pStation->ConnectContext.Lock)); break; } NdisAcquireSpinLock(&(pStation->ConnectContext.Lock)); if ((pStation->ConnectContext.ConnectState >= CONN_STATE_READY_TO_CONNECT) && (pStation->ConnectContext.AssociateState == ASSOC_STATE_RECEIVED_AUTHENTICATE)) { // // Packet will be sent means we will be waiting for packet response // pStation->ConnectContext.AssociateState = ASSOC_STATE_WAITING_FOR_ASSOCIATE; // // Save association request packet inside the AP entry. This will be freed // on association completion indication // NdisDprAcquireSpinLock(&(pAPEntry->Lock)); pAPEntry->pAssocRequest = pAssocPacket; pAPEntry->AssocRequestLength = AssocPacketLength; NdisDprReleaseSpinLock(&(pAPEntry->Lock)); NdisReleaseSpinLock(&(pStation->ConnectContext.Lock)); } else { // // Reset, disconnect, deauthenticated by AP after authentication succeeded // NdisReleaseSpinLock(&(pStation->ConnectContext.Lock)); MpTrace(COMP_ASSOC, DBG_LOUD, ("Reset/Disconnect/Deauth while starting association\n")); // // Assoc packet pointer isnt saved, free it // StaFreeAssociateRequestPacket( pStation, pAPEntry, pAssocPacket, AssocPacketLength ); // // Abort association // StatusCode = (ULONG)STATUS_CANCELLED; break; } // // Send the association request packet // ndisStatus = Hw11SendMgmtPacket( pStation->pNic, pAPEntry, pAssocPacket, AssocPacketLength ); if (ndisStatus != NDIS_STATUS_SUCCESS) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to send Association Request packet\n")); StatusCode = ndisStatus; NdisAcquireSpinLock(&(pStation->ConnectContext.Lock)); if (pStation->ConnectContext.AssociateState == ASSOC_STATE_WAITING_FOR_AUTHENTICATE) { // // Reset ourselves to ready to original state // pStation->ConnectContext.AssociateState = ASSOC_STATE_STARTED_ASSOCIATION; } NdisReleaseSpinLock(&(pStation->ConnectContext.Lock)); break; } else { // Add an extra refcount for the association timer STA_INCREMENT_REF(pStation->ConnectContext.AsyncFuncCount); // // Set the timeout timer for associate failure case. // //NdisMSetTimer(&(pStation->ConnectContext.Timer_AssociateTimeout), AssociateTimeout); WdfTimerStart(pStation->ConnectContext.Timer_AssociateTimeout, WDF_REL_TIMEOUT_IN_MS(AssociateTimeout)); } // // We dont let the hardware pend the request since we will be // freeing the packet // MPVERIFY(ndisStatus != NDIS_STATUS_PENDING); }while (FALSE); // // Fail the association if we failed inline, etc // if (StatusCode != 0) { StaAssociateComplete(pStation, DOT11_ASSOC_STATUS_SYSTEM_ERROR); } return ndisStatus; }
/*************************************************************************** Routine Description: This is the real interrupt handler for receive/overflow interrupt. Called when a receive interrupt is received. It first indicates all packets on the card and finally indicates ReceiveComplete(). Arguments: Adapter - Pointer to the adapter block. Return Value: TRUE if done with all receives, else FALSE. *****************************************************************************/ BOOLEAN R6040RcvDpc(IN PR6040_ADAPTER Adapter) { // Status of a received packet. INDICATE_STATUS IndicateStatus = INDICATE_OK; // Guess at where the packet is located PUCHAR PacketLoc; // Flag to tell when the receive process is complete BOOLEAN Done = TRUE; PUCHAR rxd; USHORT rxstatus; int total_len; do { // Code to fix a loop we got into where the card had been removed, // Now, the NDIS unbind routine calls our shutdown // handler which sets a flag if (Adapter->ShuttingDown) { RETAILMSG(R6040DBG, (TEXT("R6040RcvDpc(): Shutdown detected\r\n"))); break; } // Default to not indicating NdisMEthIndicateReceiveComplete Adapter->IndicateReceiveDone = FALSE; // A packet was found on the card, indicate it. Adapter->ReceivePacketCount++; rxd = Adapter->Rx_ring[Adapter->Rx_desc_add].VirtualAddr; READMEM16(rxd + DS_STATUS, rxstatus); READMEM16(rxd + DS_LEN, total_len); total_len -= 4; /* Skip CRC 4 byte */ /* OWN bit=1, no packet coming */ if (rxstatus & 0x8000) { IndicateStatus = SKIPPED; //RETAILMSG(R6040DBG, (TEXT("R6040RcvDpc(): no packet coming \r\n"))); break; } //RETAILMSG(R6040DBG, (TEXT("R6040RcvDpc(): total_len = %d\r\n"), total_len)); Adapter->Rx_desc_add++; // Adapter->Rx_free_cnt++; // Copy the data to the network stack PacketLoc = rxd + BUF_START; Adapter->PacketHeaderLoc = PacketLoc; // Indicate the packet to the wrapper IndicateStatus = R6040IndicatePacket(Adapter , total_len); if (IndicateStatus != CARD_BAD) { Adapter->FramesRcvGood++; } // Handle when the card is unable to indicate good packets if (IndicateStatus == CARD_BAD) { RETAILMSG(R6040DBG, (TEXT("R6040RcvDpc(): CARD_BAD: R: <%x %x %x %x> \r\n"), Adapter->PacketHeader[0], Adapter->PacketHeader[1], Adapter->PacketHeader[2], Adapter->PacketHeader[3])); // Start off with receive interrupts disabled. Adapter->NicInterruptMask = MIER_RXENDE | MIER_TXENDE; // Reset the adapter CardReset(Adapter); // Since the adapter was just reset, stop indicating packets. break; } /* Rx data already copy to the upper buffer, now can reuse RX descriptor */ WRITEMEM16(rxd + DS_STATUS, 0x8000); /* Reuse RX descriptor */ /* Signal RX ready */ // NdisRawWritePortUshort( Adapter->IoPAddr + NIC_CONTROL0,Adapter->MacControl); /* Move to next RX descriptor */ if (Adapter->Rx_desc_add >= MAX_RX_DESCRIPTORS) { Adapter->Rx_desc_add = 0; Done = FALSE; Adapter->ReceivePacketCount = 0; // break; } // Finally, indicate ReceiveComplete to all protocols which received packets if (Adapter->IndicateReceiveDone) { NdisDprReleaseSpinLock(&Adapter->RcvLock); NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle); NdisDprAcquireSpinLock(&Adapter->RcvLock); Adapter->IndicateReceiveDone = FALSE; } }while (TRUE); return (Done); }
VOID NTAPI MiniportHandleInterrupt ( IN NDIS_HANDLE MiniportAdapterContext ) { PRTL_ADAPTER adapter = (PRTL_ADAPTER)MiniportAdapterContext; ULONG txStatus; UCHAR command; PPACKET_HEADER nicHeader; PETH_HEADER ethHeader; NdisDprAcquireSpinLock(&adapter->Lock); NDIS_DbgPrint(MAX_TRACE, ("Interrupts pending: 0x%x\n", adapter->InterruptPending)); // // Handle a link change // if (adapter->LinkChange) { NdisDprReleaseSpinLock(&adapter->Lock); NdisMIndicateStatus(adapter->MiniportAdapterHandle, adapter->MediaState == NdisMediaStateConnected ? NDIS_STATUS_MEDIA_CONNECT : NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0); NdisMIndicateStatusComplete(adapter->MiniportAdapterHandle); NdisDprAcquireSpinLock(&adapter->Lock); adapter->LinkChange = FALSE; } // // Handle a TX interrupt // if (adapter->InterruptPending & (R_I_TXOK | R_I_TXERR)) { while (adapter->TxFull || adapter->DirtyTxDesc != adapter->CurrentTxDesc) { NdisRawReadPortUlong(adapter->IoBase + R_TXSTS0 + (adapter->DirtyTxDesc * sizeof(ULONG)), &txStatus); if (!(txStatus & (R_TXS_STATOK | R_TXS_UNDERRUN | R_TXS_ABORTED))) { // // Not sent yet // break; } NDIS_DbgPrint(MAX_TRACE, ("Transmission for desc %d complete: 0x%x\n", adapter->DirtyTxDesc, txStatus)); if (txStatus & R_TXS_STATOK) { adapter->TransmitOk++; } else { adapter->TransmitError++; } adapter->DirtyTxDesc++; adapter->DirtyTxDesc %= TX_DESC_COUNT; adapter->InterruptPending &= ~(R_I_TXOK | R_I_TXERR); adapter->TxFull = FALSE; } } // // Handle a good RX interrupt // if (adapter->InterruptPending & (R_I_RXOK | R_I_RXERR)) { for (;;) { NdisRawReadPortUchar(adapter->IoBase + R_CMD, &command); if (command & R_CMD_RXEMPTY) { // // The buffer is empty // adapter->InterruptPending &= ~(R_I_RXOK | R_I_RXERR); break; } adapter->ReceiveOffset %= RECEIVE_BUFFER_SIZE; NDIS_DbgPrint(MAX_TRACE, ("Looking for a packet at offset 0x%x\n", adapter->ReceiveOffset)); nicHeader = (PPACKET_HEADER)(adapter->ReceiveBuffer + adapter->ReceiveOffset); if (!(nicHeader->Status & RSR_ROK)) { // // Receive failed // NDIS_DbgPrint(MIN_TRACE, ("Receive failed: 0x%x\n", nicHeader->Status)); if (nicHeader->Status & RSR_FAE) { adapter->ReceiveAlignmentError++; } else if (nicHeader->Status & RSR_CRC) { adapter->ReceiveCrcError++; } adapter->ReceiveError++; goto NextPacket; } NDIS_DbgPrint(MAX_TRACE, ("Indicating %d byte packet to NDIS\n", nicHeader->PacketLength - RECV_CRC_LENGTH)); ethHeader = (PETH_HEADER)(nicHeader + 1); NdisMEthIndicateReceive(adapter->MiniportAdapterHandle, NULL, (PVOID)(ethHeader), sizeof(ETH_HEADER), (PVOID)(ethHeader + 1), nicHeader->PacketLength - sizeof(ETH_HEADER) - RECV_CRC_LENGTH, nicHeader->PacketLength - sizeof(ETH_HEADER) - RECV_CRC_LENGTH); adapter->ReceiveOk++; NextPacket: adapter->ReceiveOffset += nicHeader->PacketLength + sizeof(PACKET_HEADER); adapter->ReceiveOffset = (adapter->ReceiveOffset + 3) & ~3; NdisRawWritePortUshort(adapter->IoBase + R_CAPR, adapter->ReceiveOffset - 0x10); if (adapter->InterruptPending & (R_I_RXOVRFLW | R_I_FIFOOVR)) { // // We can only clear these interrupts once CAPR has been reset // NdisRawWritePortUshort(adapter->IoBase + R_IS, R_I_RXOVRFLW | R_I_FIFOOVR); adapter->InterruptPending &= ~(R_I_RXOVRFLW | R_I_FIFOOVR); } } NdisMEthIndicateReceiveComplete(adapter->MiniportAdapterHandle); } NdisDprReleaseSpinLock(&adapter->Lock); }
INDICATE_STATUS R6040IndicatePacket( IN PR6040_ADAPTER Adapter, IN INT Len ) /*++ Routine Description: Indicates the first packet on the card to the protocols. NOTE: For MP, non-x86 architectures, this assumes that the packet has been read from the card and into Adapter->PacketHeader and Adapter->Lookahead. NOTE: For UP x86 systems this assumes that the packet header has been read into Adapter->PacketHeader and the minimal lookahead stored in Adapter->Lookahead Arguments: Adapter - pointer to the adapter block. Return Value: CARD_BAD if the card should be reset; INDICATE_OK otherwise. --*/ { // Length of the packet UINT PacketLen = Len; // Length of the lookahead buffer UINT IndicateLen; if (PacketLen > 1514) { RETAILMSG(R6040DBG, (TEXT("R6040:IndicatePacket Third CARD_BAD check failed\r\n"))); return(SKIPPED); } // Lookahead amount to indicate IndicateLen = (PacketLen > (Adapter->MaxLookAhead + R6040_HEADER_SIZE )) ? (Adapter->MaxLookAhead + R6040_HEADER_SIZE ) : PacketLen; // Indicate packet Adapter->PacketLen = PacketLen; if (IndicateLen < R6040_HEADER_SIZE) { // Runt Packet NdisDprReleaseSpinLock(&Adapter->RcvLock); NdisMEthIndicateReceive( Adapter->MiniportAdapterHandle, (NDIS_HANDLE)Adapter, (PCHAR)(Adapter->PacketHeaderLoc), IndicateLen, NULL, 0, 0 ); NdisDprAcquireSpinLock(&Adapter->RcvLock); } else { NdisDprReleaseSpinLock(&Adapter->RcvLock); NdisMEthIndicateReceive( Adapter->MiniportAdapterHandle, (NDIS_HANDLE)Adapter, (PCHAR)(Adapter->PacketHeaderLoc), R6040_HEADER_SIZE, (PCHAR)(Adapter->PacketHeaderLoc) + R6040_HEADER_SIZE, IndicateLen - R6040_HEADER_SIZE, PacketLen - R6040_HEADER_SIZE ); NdisDprAcquireSpinLock(&Adapter->RcvLock); } Adapter->IndicateReceiveDone = TRUE; return INDICATE_OK; }
STATIC VOID LoopProcessLoopback( PLOOP_ADAPTER Adapter ) { PNDIS_PACKET LoopPacket; PLOOP_PACKET_RESERVED Reserved; PLOOP_OPEN Open; UINT BufferLength; UINT IndicateLen; UINT AddressType; UCHAR DestAddress[FDDI_LENGTH_OF_LONG_ADDRESS]; DBGPRINT(DBG_COMP_DPC, DBG_LEVEL_INFO, (" --> LoopProcessLoopback\n")); while ((Adapter->Loopback != NULL) && !Adapter->ResetInProgress) { // dequeue the packet at the head of the loopback queue LoopPacket = Adapter->Loopback; Adapter->CurrentLoopback = LoopPacket; Reserved = PLOOP_RESERVED_FROM_PACKET(LoopPacket); Adapter->Loopback = Reserved->Next; if (Adapter->Loopback == NULL) Adapter->LastLoopback = NULL; DBGPRINT(DBG_COMP_DPC, DBG_LEVEL_INFO, ("Dequeued packet %lx\n",LoopPacket)); IndicateLen = (Reserved->PacketLength > Adapter->MaxLookAhead) ? Adapter->MaxLookAhead : Reserved->PacketLength; Adapter->GeneralMandatory[GM_RECEIVE_GOOD]++; NdisDprReleaseSpinLock(&Adapter->Lock); LoopCopyFromPacketToBuffer( LoopPacket, 0, IndicateLen, Adapter->LoopBuffer, &BufferLength ); // indicate the packet as appropriate switch (Adapter->Medium) { case NdisMedium802_3: case NdisMediumDix: EthFilterIndicateReceive( Adapter->Filter.Eth, (NDIS_HANDLE)NULL, (PCHAR)Adapter->LoopBuffer, Adapter->LoopBuffer, Reserved->HeaderLength, (Adapter->LoopBuffer)+(Reserved->HeaderLength), IndicateLen-(Reserved->HeaderLength), (Reserved->PacketLength)-(Reserved->HeaderLength) ); break; case NdisMedium802_5: TrFilterIndicateReceive( Adapter->Filter.Tr, (NDIS_HANDLE)NULL, Adapter->LoopBuffer, Reserved->HeaderLength, (Adapter->LoopBuffer)+(Reserved->HeaderLength), IndicateLen-(Reserved->HeaderLength), (Reserved->PacketLength)-(Reserved->HeaderLength) ); break; case NdisMediumFddi: // just copy over the long address size, even though it may // be a short address NdisMoveMemory( DestAddress, Adapter->LoopBuffer+1, FDDI_LENGTH_OF_LONG_ADDRESS ); FddiFilterIndicateReceive( Adapter->Filter.Fddi, (NDIS_HANDLE)NULL, (PCHAR)DestAddress, ((*(Adapter->LoopBuffer) & 0x40) ? FDDI_LENGTH_OF_LONG_ADDRESS : FDDI_LENGTH_OF_SHORT_ADDRESS), Adapter->LoopBuffer, Reserved->HeaderLength, (Adapter->LoopBuffer)+(Reserved->HeaderLength), IndicateLen-(Reserved->HeaderLength), (Reserved->PacketLength)-(Reserved->HeaderLength) ); break; case NdisMediumLocalTalk: if (LOOP_LT_IS_BROADCAST(Adapter->LoopBuffer[0])) AddressType = NDIS_PACKET_TYPE_BROADCAST; else AddressType = NDIS_PACKET_TYPE_DIRECTED; LtIndicateReceive( Adapter, AddressType, Adapter->LoopBuffer, Reserved->HeaderLength, (Adapter->LoopBuffer)+(Reserved->HeaderLength), IndicateLen-(Reserved->HeaderLength), (Reserved->PacketLength)-(Reserved->HeaderLength) ); break; case NdisMediumArcnet878_2: if (LOOP_ARC_IS_BROADCAST(Adapter->LoopBuffer[1])) AddressType = NDIS_PACKET_TYPE_BROADCAST; else AddressType = NDIS_PACKET_TYPE_DIRECTED; LtIndicateReceive( Adapter, AddressType, Adapter->LoopBuffer, Reserved->HeaderLength, (Adapter->LoopBuffer)+(Reserved->HeaderLength), IndicateLen-(Reserved->HeaderLength), (Reserved->PacketLength)-(Reserved->HeaderLength) ); break; default: ASSERT(FALSE); // should never get here break; } // complete the send Open = PLOOP_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle); DBGPRINT(DBG_COMP_DPC, DBG_LEVEL_INFO, ("Completing Send for binding %lx\n",Open)); NdisCompleteSend( Open->NdisBindingContext, LoopPacket, NDIS_STATUS_SUCCESS ); NdisDprAcquireSpinLock(&Adapter->Lock); Adapter->GeneralMandatory[GM_TRANSMIT_GOOD]++; // remove reference for send just completed Open->References--; } // rearm timer if there are still packets to loop back and the timer is // not already ticking away if (Adapter->Loopback != NULL && !Adapter->TimerSet) { DBGPRINT(DBG_COMP_DPC, DBG_LEVEL_INFO, ("More packets to loopback\n")); Adapter->TimerSet = TRUE; NdisDprReleaseSpinLock(&Adapter->Lock); NdisSetTimer( &Adapter->LoopTimer, 25 ); NdisDprAcquireSpinLock(&Adapter->Lock); } // issue indicate receive completes as necessary switch (Adapter->Medium) { case NdisMedium802_3: case NdisMediumDix: NdisDprReleaseSpinLock(&Adapter->Lock); EthFilterIndicateReceiveComplete(Adapter->Filter.Eth); NdisDprAcquireSpinLock(&Adapter->Lock); break; case NdisMedium802_5: NdisDprReleaseSpinLock(&Adapter->Lock); TrFilterIndicateReceiveComplete(Adapter->Filter.Tr); NdisDprAcquireSpinLock(&Adapter->Lock); break; case NdisMediumFddi: NdisDprReleaseSpinLock(&Adapter->Lock); FddiFilterIndicateReceiveComplete(Adapter->Filter.Fddi); NdisDprAcquireSpinLock(&Adapter->Lock); break; case NdisMediumLocalTalk: case NdisMediumArcnet878_2: NdisDprReleaseSpinLock(&Adapter->Lock); LtIndicateReceiveComplete(Adapter); NdisDprAcquireSpinLock(&Adapter->Lock); break; default: ASSERT(FALSE); break; } }
VOID StaReceiveAssociationResponse( __in PSTATION pStation, __in PNIC_RX_FRAGMENT pNicFragment, __in ULONG TotalLength ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PUCHAR pPacketBuffer; PDOT11_MGMT_HEADER pMgmtHeader; PDOT11_ASSOC_RESPONSE_FRAME pDot11AssocFrame; USHORT StatusCode; USHORT AID = 0; PSTA_BSS_ENTRY pAPEntry = pStation->ConnectContext.ActiveAP; BOOLEAN bTimerCancelled, bSetTxDataRate = FALSE; DOT11_RATE_SET rateSet; pPacketBuffer = Hw11GetFragmentDataStart(pNicFragment); // // Ref to make sure reset/halt does not leave while we are still working // STA_INCREMENT_REF(pStation->ConnectContext.AsyncFuncCount); NdisDprAcquireSpinLock(&(pStation->ConnectContext.Lock)); if (pStation->ConnectContext.AssociateState == ASSOC_STATE_WAITING_FOR_ASSOCIATE) { if (pStation->ConnectContext.ConnectState < CONN_STATE_READY_TO_CONNECT) { MpTrace(COMP_ASSOC, DBG_LOUD, ("Reset/Disconnect before association completed\n")); // // Reset/disconnect, etc. We dont process this associate packet. Eventually, timeout // will happen and cleanup // NdisDprReleaseSpinLock(&(pStation->ConnectContext.Lock)); STA_DECREMENT_REF(pStation->ConnectContext.AsyncFuncCount); return; } do { if (TotalLength < (sizeof(DOT11_MGMT_HEADER) + sizeof(DOT11_ASSOC_RESPONSE_FRAME))) { ndisStatus = NDIS_STATUS_NOT_ACCEPTED; MpTrace(COMP_ASSOC, DBG_LOUD, ("Association response packet too short\n")); break; } pMgmtHeader = (PDOT11_MGMT_HEADER)pPacketBuffer; // // Check that is a packet from the AP we are interested in // if (!MP_COMPARE_MAC_ADDRESS(pMgmtHeader->SA, pAPEntry->MacAddress) || !MP_COMPARE_MAC_ADDRESS(pMgmtHeader->BSSID, pAPEntry->Dot11BSSID) || !MP_COMPARE_MAC_ADDRESS(pMgmtHeader->DA, Hw11GetMACAddress(pStation->pNic))) { ndisStatus = NDIS_STATUS_NOT_ACCEPTED; MpTrace(COMP_ASSOC, DBG_LOUD, ("Association response packet not for me\n")); break; } } while (FALSE); if (ndisStatus != NDIS_STATUS_NOT_ACCEPTED) { // // This was a valid response to our association request // Complete the association with appropriate status // pDot11AssocFrame = (PDOT11_ASSOC_RESPONSE_FRAME)(pPacketBuffer + sizeof(DOT11_MGMT_HEADER)); // // Get association status code from the packet // StatusCode = pDot11AssocFrame->usStatusCode; if (StatusCode == DOT11_FRAME_STATUS_SUCCESSFUL) { // // Association attempt succeeded // ndisStatus = NDIS_STATUS_SUCCESS; MpTrace(COMP_ASSOC, DBG_NORMAL, ("Association response status SUCCESS\n")); // // Validate AID // AID = pDot11AssocFrame->usAID; if ((AID & 0xc000) != 0xc000) { // Invalid AID. pStation->Config.ValidAID = FALSE; // Connecting to a non-conformant AP. Continue with association instead of bailing out. MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Association response contains invalid AID %d\n", AID)); } else { pStation->Config.ValidAID = TRUE; } AID &= ~(0xc000); if (AID > 2007) { // AID too big ndisStatus = NDIS_STATUS_FAILURE; MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Association response contains invalid AID %d\n", AID)); } if (ndisStatus == NDIS_STATUS_SUCCESS) { // // Get data rate // ndisStatus = StaGetRateSetFromInfoEle( Add2Ptr(pDot11AssocFrame, sizeof(DOT11_ASSOC_RESPONSE_FRAME)), TotalLength - sizeof(DOT11_MGMT_HEADER) - sizeof(DOT11_ASSOC_RESPONSE_FRAME), FALSE, &rateSet); } if (ndisStatus == NDIS_STATUS_SUCCESS) { // Association has succeeded MpTrace(COMP_ASSOC, DBG_NORMAL, ("Association ID %d\n", AID)); pStation->ConnectContext.AssociateState = ASSOC_STATE_RECEIVED_ASSOCIATE; pStation->Config.AID = AID; // // Clear non-static WEP keys. // Hw11DeleteNonPersistentKey(pStation->pNic); bSetTxDataRate = TRUE; // // Set active PhyId // pStation->Config.ActivePhyId = pAPEntry->PhyId; // // Set multicast cipher algorithm if the exact algorithm was not selected. // if (pStation->Config.MulticastCipherAlgorithmCount > 1) { Hw11SetEncryption(pStation->pNic, FALSE, pStation->Config.MulticastCipherAlgorithm); } } else { pStation->ConnectContext.AssociateState = ASSOC_STATE_STARTED_ASSOCIATION; StatusCode = DOT11_FRAME_STATUS_FAILURE; // Unspecified failure } } else { // The association attempt failed MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Association failed by the access point with status %d\n", StatusCode)); pStation->ConnectContext.AssociateState = ASSOC_STATE_STARTED_ASSOCIATION; } // // Copy the association response buffer into the AP Entry for completion indication // NdisDprAcquireSpinLock(&(pAPEntry->Lock)); pAPEntry->AssocResponseLength = (USHORT)TotalLength; MP_ALLOCATE_MEMORY(pStation->MiniportAdapterHandle, &(pAPEntry->pAssocResponse), TotalLength, STA11_MEMORY_TAG); if (pAPEntry->pAssocResponse == NULL) { MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to save association request packet\n")); // // We still maintain the association // pAPEntry->AssocResponseLength = 0; } else { // // Copy the association response into the packet // NdisMoveMemory(pAPEntry->pAssocResponse, pPacketBuffer, TotalLength); } // Save association ID, time, etc pAPEntry->AssocID = AID; NdisGetCurrentSystemTime(&(pAPEntry->AssociationUpTime)); pAPEntry->AssocState = dot11_assoc_state_auth_assoc; NdisDprReleaseSpinLock(&(pAPEntry->Lock)); NdisDprReleaseSpinLock(&(pStation->ConnectContext.Lock)); if (bSetTxDataRate == TRUE) { // // Set data TX rate // Hw11SetTXDataRate(pStation->pNic, &rateSet, Hw11GetCalibratedRSSI(pStation->pNic, pNicFragment) ); } // // Attempt to cancel the timer // /*NdisMCancelTimer(&(pStation->ConnectContext.Timer_AssociateTimeout), &bTimerCancelled); */ bTimerCancelled = WdfTimerStop(pStation->ConnectContext.Timer_AssociateTimeout, FALSE); if (bTimerCancelled) { STA_DECREMENT_REF(pStation->ConnectContext.AsyncFuncCount); } if (StatusCode) { StaAssociateComplete(pStation, StatusCode | DOT11_ASSOC_STATUS_ASSOCIATION_RESPONSE_START); } else { StaAssociateComplete(pStation, DOT11_ASSOC_STATUS_SUCCESS); } } else { NdisDprReleaseSpinLock(&(pStation->ConnectContext.Lock)); } } else { NdisDprReleaseSpinLock(&(pStation->ConnectContext.Lock)); MpTrace(COMP_ASSOC, DBG_LOUD, ("Association already timed out\n")); } STA_DECREMENT_REF(pStation->ConnectContext.AsyncFuncCount); }
/*************************************************************************** Routine Description: A protocol calls the R6040TransferData request (indirectly via NdisTransferData) from within its Receive event handler to instruct the driver to copy the contents of the received packet a specified packet buffer. Arguments: MiniportAdapterContext - Context registered with the wrapper, really a pointer to the adapter. MiniportReceiveContext - The context value passed by the driver on its call to NdisMEthIndicateReceive. The driver can use this value to determine which packet, on which adapter, is being received. ByteOffset - An unsigned integer specifying the offset within the received packet at which the copy is to begin. If the entire packet is to be copied, ByteOffset must be zero. BytesToTransfer - An unsigned integer specifying the number of bytes to copy. It is legal to transfer zero bytes; this has no effect. If the sum of ByteOffset and BytesToTransfer is greater than the size of the received packet, then the remainder of the packet (starting from ByteOffset) is transferred, and the trailing portion of the receive buffer is not modified. Packet - A pointer to a descriptor for the packet storage into which the MAC is to copy the received packet. BytesTransfered - A pointer to an unsigned integer. The MAC writes the actual number of bytes transferred into this location. This value is not valid if the return status is STATUS_PENDING. Notes: - The MacReceiveContext will be a pointer to the open block for the packet. *****************************************************************************/ NDIS_STATUS R6040TransferData( OUT PNDIS_PACKET InPacket, OUT PUINT BytesTransferred, IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_HANDLE MiniportReceiveContext, IN UINT ByteOffset, IN UINT BytesToTransfer) { // Variables for the number of bytes to copy, how much can be // copied at this moment, and the total number of bytes to copy. UINT BytesLeft, BytesNow, BytesWanted; // Current NDIS_BUFFER to copy into PNDIS_BUFFER CurBuffer; PUCHAR BufStart; // Address on the adapter to copy from const UCHAR *CurCardLoc; // Length and offset into the buffer. UINT BufLen, BufOff; // The adapter to transfer from. PR6040_ADAPTER Adapter = ((PR6040_ADAPTER)MiniportReceiveContext); //RETAILMSG(R6040DBG, (TEXT("R6040TransferData()\r\n"))); NdisDprAcquireSpinLock(&Adapter->RcvLock); // Add the packet header onto the offset. ByteOffset+= R6040_HEADER_SIZE; // See how much data there is to transfer. if (ByteOffset+BytesToTransfer > Adapter->PacketLen) { if (Adapter->PacketLen < ByteOffset) { *BytesTransferred = 0; return(NDIS_STATUS_FAILURE); } BytesWanted = Adapter->PacketLen - ByteOffset; } else { BytesWanted = BytesToTransfer; } // Set the number of bytes left to transfer BytesLeft = BytesWanted; { // Copy data from the card -- it is not completely stored in the // adapter structure. // Determine where the copying should start. CurCardLoc = Adapter->PacketHeaderLoc + ByteOffset; // Get location to copy into NdisQueryPacket(InPacket, NULL, NULL, &CurBuffer, NULL); NdisQueryBuffer(CurBuffer, (PVOID *)&BufStart, &BufLen); BufOff = 0; // Loop, filling each buffer in the packet until there // are no more buffers or the data has all been copied. while (CurBuffer && BytesLeft > 0) { // See how much data to read into this buffer. if ((BufLen-BufOff) > BytesLeft) { BytesNow = BytesLeft; } else { BytesNow = (BufLen - BufOff); } // Copy up the data. NdisMoveMemory(BufStart+BufOff,CurCardLoc,BytesNow); // Update offsets and counts CurCardLoc += BytesNow; BytesLeft -= BytesNow; // Is the transfer done now? if (BytesLeft == 0) { break; } // Was the end of this packet buffer reached? BufOff += BytesNow; if (BufOff == BufLen) { NdisGetNextBuffer(CurBuffer, &CurBuffer); if (CurBuffer == (PNDIS_BUFFER)NULL) { break; } NdisQueryBuffer(CurBuffer, (PVOID *)&BufStart, &BufLen); BufOff = 0; } } *BytesTransferred = BytesWanted - BytesLeft; NdisDprReleaseSpinLock(&Adapter->RcvLock); return(NDIS_STATUS_SUCCESS); } NdisDprReleaseSpinLock(&Adapter->RcvLock); return(NDIS_STATUS_SUCCESS); }
VOID ReceiverHandleNotification( IN PRECEIVER Receiver ) /*++ Routine Description: Interrupt handler for receive processing Put the received packets into an array and call NdisMIndicateReceivePacket If we run low on RFDs, allocate another one Arguments: Adapter Pointer to our adapter Return Value: None --*/ { PADAPTER Adapter = Receiver->Common.Adapter; RING_IDX prod; int more_work; PNDIS_PACKET PacketArray[XENNET_DEF_RFDS]; NDIS_STATUS PacketStatus[XENNET_DEF_RFDS]; UINT PacketCount; if (!RING_HAS_UNCONSUMED_RESPONSES(&Receiver->Common.Ring)) return; NdisDprAcquireSpinLock(&Receiver->Common.Lock); if (Receiver->Common.Adapter->media_disconnect) { NdisDprReleaseSpinLock(&Receiver->Common.Lock); return; } if (__RING_IDX_DIFFERENCE(Receiver->Common.Ring.req_prod_pvt, Receiver->Common.Ring.sring->rsp_prod) > NET_RX_RING_SIZE) TraceWarning(("Strange: rsp_prod ahead of req_prod (%d vs %d (s %d))\n", Receiver->Common.Ring.sring->rsp_prod, Receiver->Common.Ring.req_prod_pvt, Receiver->Common.Ring.sring->req_prod)); PacketCount = 0; top: prod = Receiver->Common.Ring.sring->rsp_prod; XsMemoryBarrier(); while (!RING_IDXS_EQ(Receiver->Common.Ring.rsp_cons, prod)) { PNDIS_PACKET packet; ULONG totFrags; NDIS_STATUS status; status = ReceiverReceivePacket(Receiver, &packet, &totFrags); if (status != NDIS_STATUS_SUCCESS) continue; TraceProfile(("%s(%s, %p)\n", __FUNCTION__, Adapter->XenbusPrefix, packet)); // See http://msdn.microsoft.com/en-us/library/ms797610.aspx if (Receiver->LowResources == 2 || (Receiver->LowResources == 1 && totFrags > 1)) { status = NDIS_STATUS_RESOURCES; NDIS_SET_PACKET_STATUS(packet, status); } PacketArray[PacketCount] = packet; PacketStatus[PacketCount] = status; PacketCount++; if (PacketCount == XENNET_DEF_RFDS) { ULONG Index; Receiver->Common.Frames += PacketCount; Receiver->nRxInNdis += PacketCount; if (Receiver->nRxInNdis >= Receiver->nRxInNdisMax) Receiver->nRxInNdisMax = Receiver->nRxInNdis; NdisDprReleaseSpinLock(&Receiver->Common.Lock); NdisMIndicateReceivePacket( Receiver->Common.Adapter->AdapterHandle, PacketArray, PacketCount); NdisDprAcquireSpinLock(&Receiver->Common.Lock); for (Index = 0; Index < PacketCount; Index++) { if (PacketStatus[Index] == NDIS_STATUS_RESOURCES) { ReceiverReleasePacket(Receiver, PacketArray[Index]); Receiver->nRxInNdis--; } else { XM_ASSERT(PacketStatus[Index] == NDIS_STATUS_SUCCESS); } } PacketCount = 0; ReceiverSwizzle(Receiver); } } RING_FINAL_CHECK_FOR_RESPONSES(&Receiver->Common.Ring, more_work); if (more_work) goto top; if (PacketCount != 0) { ULONG Index; Receiver->Common.Frames += PacketCount; Receiver->nRxInNdis += PacketCount; if (Receiver->nRxInNdis >= Receiver->nRxInNdisMax) Receiver->nRxInNdisMax = Receiver->nRxInNdis; NdisDprReleaseSpinLock(&Receiver->Common.Lock); NdisMIndicateReceivePacket( Receiver->Common.Adapter->AdapterHandle, PacketArray, PacketCount); NdisDprAcquireSpinLock(&Receiver->Common.Lock); for (Index = 0; Index < PacketCount; Index++) { if (PacketStatus[Index] == NDIS_STATUS_RESOURCES) { ReceiverReleasePacket(Receiver, PacketArray[Index]); Receiver->nRxInNdis--; } else { XM_ASSERT(PacketStatus[Index] == NDIS_STATUS_SUCCESS); } } PacketCount = 0; } // Swizzle unconditionally to make sure we replenish the ring even if // nothing was passed to NDIS. ReceiverSwizzle(Receiver); NdisDprReleaseSpinLock(&Receiver->Common.Lock); /* XXX Should maybe adjust size of packet pool from here. */ }
// BSS list lock acquired & called at Dispatch NDIS_STATUS HelperPortUpdateBSSEntry( __in PMP_HELPER_PORT HelperPort, __in PMP_BSS_ENTRY pBSSEntry, __in PMP_RX_MPDU pFragment, __in PDOT11_BEACON_FRAME pDot11BeaconPRFrame, __in ULONG BeaconPRDataLength ) { NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; PDOT11_MGMT_HEADER pMgmtPktHeader; ULONGLONG ullHostTimeStamp; PVOID pSavedBeaconPRBuffer = NULL; ULONG uOffsetOfInfoElemBlob = FIELD_OFFSET(DOT11_BEACON_FRAME, InfoElements); UCHAR channel; DOT11_PHY_TYPE PhyType; pMgmtPktHeader = (PDOT11_MGMT_HEADER)MP_RX_MPDU_DATA(pFragment); NdisGetCurrentSystemTime((PLARGE_INTEGER)&ullHostTimeStamp); do { // // Modifying data in the AP entry // NdisDprAcquireSpinLock(&(pBSSEntry->Lock)); if (pDot11BeaconPRFrame->Capability.IBSS) { pBSSEntry->Dot11BSSType = dot11_BSS_type_independent; } else { pBSSEntry->Dot11BSSType = dot11_BSS_type_infrastructure; } // // Adhoc station can leave adhoc cell and create a new cell. SoftAPs // can move. This means the BSSID can change // NdisMoveMemory( pBSSEntry->Dot11BSSID, pMgmtPktHeader->BSSID, sizeof(DOT11_MAC_ADDRESS) ); pBSSEntry->HostTimestamp = ullHostTimeStamp; pBSSEntry->BeaconTimestamp = pDot11BeaconPRFrame->Timestamp; pBSSEntry->BeaconInterval = pDot11BeaconPRFrame->BeaconInterval; pBSSEntry->Dot11Capability = pDot11BeaconPRFrame->Capability; pBSSEntry->RSSI = pFragment->Msdu->RecvContext.lRSSI; pBSSEntry->LinkQuality = pFragment->Msdu->LinkQuality; pBSSEntry->ChannelCenterFrequency = pFragment->Msdu->RecvContext.uChCenterFrequency; // // If signal strength was below our threshold, catch that // if (pBSSEntry->LinkQuality < HelperPort->RegInfo->RSSILinkQualityThreshold) { pBSSEntry->LowQualityCount++; } else { pBSSEntry->LowQualityCount = 0; } #if 0 if (pBSSEntry->AssocState == dot11_assoc_state_auth_assoc) { MpTrace(COMP_ASSOC, DBG_LOUD, ("Received beacon from associated AP: %02X-%02X-%02X-%02X-%02X-%02X\n", pMgmtPktHeader->SA[0], pMgmtPktHeader->SA[1], pMgmtPktHeader->SA[2], pMgmtPktHeader->SA[3], pMgmtPktHeader->SA[4], pMgmtPktHeader->SA[5])); } #endif // // Get channel number at which the frame was received. // if (Dot11GetChannelForDSPhy(Add2Ptr(pDot11BeaconPRFrame, uOffsetOfInfoElemBlob), BeaconPRDataLength - uOffsetOfInfoElemBlob, &channel) != NDIS_STATUS_SUCCESS) { channel = pFragment->Msdu->Channel; } if (channel != 0) { pBSSEntry->Channel = channel; } // // Get PhyType and PhyId // PhyType = VNic11DeterminePHYType(HELPPORT_GET_VNIC(HelperPort), pBSSEntry->Dot11Capability, pBSSEntry->Channel); if (pBSSEntry->Dot11PhyType != PhyType) { pBSSEntry->Dot11PhyType = PhyType; pBSSEntry->PhyId = BasePortGetPhyIdFromType(HELPPORT_GET_MP_PORT(HelperPort), PhyType); } if (pMgmtPktHeader->FrameControl.Subtype == DOT11_MGMT_SUBTYPE_BEACON) { // // Increase the beacon frame size if necessary // if (pBSSEntry->MaxBeaconFrameSize < BeaconPRDataLength) { MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, &pSavedBeaconPRBuffer, BeaconPRDataLength, PORT_MEMORY_TAG ); if (pSavedBeaconPRBuffer == NULL) { // // Unable to allocate memory for information elements. // If this is a new AP entry, we wont be adding it to the list. // For existing entries, we end up ignoring the new IE blob // ndisStatus = NDIS_STATUS_RESOURCES; NdisDprReleaseSpinLock(&(pBSSEntry->Lock)); break; } // // Delete any old blob buffer // if (pBSSEntry->pDot11BeaconFrame != NULL) { MP_FREE_MEMORY(pBSSEntry->pDot11BeaconFrame); } pBSSEntry->pDot11BeaconFrame = pSavedBeaconPRBuffer; pBSSEntry->MaxBeaconFrameSize = BeaconPRDataLength; } // Update the beacon pBSSEntry->BeaconFrameSize = BeaconPRDataLength; // Also save this as the IE blob pointer pBSSEntry->InfoElemBlobSize = BeaconPRDataLength - uOffsetOfInfoElemBlob; pBSSEntry->pDot11InfoElemBlob = (PUCHAR)pBSSEntry->pDot11BeaconFrame + uOffsetOfInfoElemBlob; // // Update/Save the beacon information element block // NdisMoveMemory( pBSSEntry->pDot11BeaconFrame, pDot11BeaconPRFrame, BeaconPRDataLength ); } if (pMgmtPktHeader->FrameControl.Subtype == DOT11_MGMT_SUBTYPE_PROBE_RESPONSE) { // // Increase the probe response frame size if necessary // if (pBSSEntry->MaxProbeFrameSize < BeaconPRDataLength) { MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, &pSavedBeaconPRBuffer, BeaconPRDataLength, PORT_MEMORY_TAG ); if (pSavedBeaconPRBuffer == NULL) { // // Unable to allocate memory for information elements. // If this is a new AP entry, we wont be adding it to the list. // For existing entries, we end up ignoring the new IE blob // ndisStatus = NDIS_STATUS_RESOURCES; NdisDprReleaseSpinLock(&(pBSSEntry->Lock)); break; } // // Delete any old blob buffer // if (pBSSEntry->pDot11ProbeFrame != NULL) { MP_FREE_MEMORY(pBSSEntry->pDot11ProbeFrame); } pBSSEntry->pDot11ProbeFrame = pSavedBeaconPRBuffer; pBSSEntry->MaxProbeFrameSize = BeaconPRDataLength; } pBSSEntry->ProbeFrameSize = BeaconPRDataLength; // Also save this as the IE blob pointer pBSSEntry->InfoElemBlobSize = BeaconPRDataLength - uOffsetOfInfoElemBlob; pBSSEntry->pDot11InfoElemBlob = (PUCHAR)pBSSEntry->pDot11ProbeFrame + uOffsetOfInfoElemBlob; // // Update/Save the beacon information element block // NdisMoveMemory( pBSSEntry->pDot11ProbeFrame, pDot11BeaconPRFrame, BeaconPRDataLength ); } #if 0 if (pBSSEntry->AssocState == dot11_assoc_state_auth_assoc) { MpTrace(COMP_SCAN, DBG_LOUD, ("Received %d for AP %02X-%02X-%02X-%02X-%02X-%02X \n", pMgmtPktHeader->FrameControl.Subtype, pBSSEntry->Dot11BSSID[0], pBSSEntry->Dot11BSSID[1], pBSSEntry->Dot11BSSID[2], pBSSEntry->Dot11BSSID[3], pBSSEntry->Dot11BSSID[4], pBSSEntry->Dot11BSSID[5])); } #endif // // Done with our modification of the AP entry // NdisDprReleaseSpinLock(&(pBSSEntry->Lock)); } while (FALSE); return ndisStatus;