VOID NICStartWatchDogTimer( IN PFDO_DATA FdoData ) { LARGE_INTEGER dueTime; if(!FdoData->CheckForHang){ // // Set the link detection flag to indicate that NICWatchDogEvtTimerFunc // is first doing link-detection. // MP_SET_FLAG(FdoData, fMP_ADAPTER_LINK_DETECTION); FdoData->CheckForHang = FALSE; FdoData->bLinkDetectionWait = FALSE; FdoData->bLookForLink = FALSE; dueTime.QuadPart = NIC_LINK_DETECTION_DELAY; } else { dueTime.QuadPart = NIC_CHECK_FOR_HANG_DELAY; } WdfTimerStart(FdoData->WatchDogTimer, dueTime.QuadPart ); }
int PIPEnsControlOut( PSDevice pDevice, BYTE byRequest, WORD wValue, WORD wIndex, WORD wLength, PBYTE pbyBuffer ) { int ntStatus = 0; int ii; if (pDevice->Flags & fMP_DISCONNECTED) return STATUS_FAILURE; if (pDevice->Flags & fMP_CONTROL_WRITES) return STATUS_FAILURE; pDevice->sUsbCtlRequest.bRequestType = 0x40; pDevice->sUsbCtlRequest.bRequest = byRequest; pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue); pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex); pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength); pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK; pDevice->pControlURB->actual_length = 0; // Notice, pbyBuffer limited point to variable buffer, can't be constant. usb_fill_control_urb(pDevice->pControlURB, pDevice->usb, usb_sndctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest, pbyBuffer, wLength, s_nsControlInUsbIoCompleteWrite, pDevice); ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC); if (ntStatus != 0) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control send request submission failed: %d\n", ntStatus); return STATUS_FAILURE; } else { MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES); } spin_unlock_irq(&pDevice->lock); for (ii = 0; ii <= USB_CTL_WAIT; ii ++) { if (pDevice->Flags & fMP_CONTROL_WRITES) mdelay(1); else break; if (ii >= USB_CTL_WAIT) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "control send request submission timeout\n"); spin_lock_irq(&pDevice->lock); MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES); return STATUS_FAILURE; } } spin_lock_irq(&pDevice->lock); return STATUS_SUCCESS; }
int PIPEnsControlIn(struct vnt_private *pDevice, u8 byRequest, u16 wValue, u16 wIndex, u16 wLength, u8 *pbyBuffer) { int ntStatus = 0; int ii; if (pDevice->Flags & fMP_DISCONNECTED) return STATUS_FAILURE; if (pDevice->Flags & fMP_CONTROL_READS) return STATUS_FAILURE; if (pDevice->Flags & fMP_CONTROL_WRITES) return STATUS_FAILURE; MP_SET_FLAG(pDevice, fMP_CONTROL_READS); pDevice->sUsbCtlRequest.bRequestType = 0xC0; pDevice->sUsbCtlRequest.bRequest = byRequest; pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue); pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex); pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength); pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK; pDevice->pControlURB->actual_length = 0; usb_fill_control_urb(pDevice->pControlURB, pDevice->usb, usb_rcvctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest, pbyBuffer, wLength, s_nsControlInUsbIoCompleteRead, pDevice); ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC); if (ntStatus != 0) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "control request submission failed: %d\n", ntStatus); MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS); return STATUS_FAILURE; } spin_unlock_irq(&pDevice->lock); for (ii = 0; ii <= USB_CTL_WAIT; ii ++) { if (pDevice->Flags & fMP_CONTROL_READS) mdelay(1); else break; if (ii >= USB_CTL_WAIT) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "control rcv request submission timeout\n"); spin_lock_irq(&pDevice->lock); MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS); return STATUS_FAILURE; } } spin_lock_irq(&pDevice->lock); return ntStatus; }
NTSTATUS NICWritePacket( IN PFDO_DATA FdoData, IN WDFDMATRANSACTION DmaTransaction, IN PSCATTER_GATHER_LIST SGList ) /*++ Routine Description: Do the work to send a packet Assumption: This function is called with the Send SPINLOCK held. Arguments: FdoData Pointer to our FdoData Return Value: --*/ { PMP_TCB pMpTcb = NULL; NTSTATUS status; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "--> NICWritePacket: SGList %p\n", SGList); // // Initialize the Transfer Control Block. // pMpTcb = FdoData->CurrSendTail; ASSERT(!MP_TEST_FLAG(pMpTcb, fMP_TCB_IN_USE)); pMpTcb->DmaTransaction = DmaTransaction; MP_SET_FLAG(pMpTcb, fMP_TCB_IN_USE); // // Call the send handler, it only needs to deal with the ScatterGather list // status = NICSendPacket(FdoData, pMpTcb, SGList); if(!NT_SUCCESS(status)){ MP_CLEAR_FLAG(pMpTcb, fMP_TCB_IN_USE); return status; } FdoData->nBusySend++; ASSERT(FdoData->nBusySend <= FdoData->NumTcb); FdoData->CurrSendTail = FdoData->CurrSendTail->Next; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- NICWritePacket\n"); return status; }
void cdc_ncm_status(PMP_ADAPTER Adapter, PVOID buffer,NCMDWORD length) { PUSB_CDC_NOTIFICATION event; PMP_USBPIPE usbpipe=Adapter->UsbPipeForNIC; if (length< sizeof(USB_CDC_NOTIFICATION)) return; event =(PUSB_CDC_NOTIFICATION)buffer; switch (event->bNotificationType) { case USB_CDC_NOTIFY_NETWORK_CONNECTION: /* * According to the CDC NCM specification ch.7.1 * USB_CDC_NOTIFY_NETWORK_CONNECTION notification shall be * sent by device after USB_CDC_NOTIFY_SPEED_CHANGE. */ usbpipe->connected = le16_to_cpu(event->wValue); DEBUGP(MP_INFO,("network connection: %sconnected\n",usbpipe->connected ? "" : "dis")); if(usbpipe->connected) { MP_CLEAR_FLAG(Adapter,fMP_DISCONNECTED); }else { MP_SET_FLAG(Adapter,fMP_DISCONNECTED); } break; case USB_CDC_NOTIFY_SPEED_CHANGE: if (length>=(sizeof(USB_CDC_NOTIFICATION) +sizeof(USB_CDC_SPEED_CHANGE))) { cdc_ncm_speed_change(Adapter, ( PUSB_CDC_SPEED_CHANGE)(event+sizeof(USB_CDC_SPEED_CHANGE))); }else { DEBUGP(MP_INFO,("USB_CDC_NOTIFY_SPEED_CHANGE notify length is short:%d\n",length)); } break; default: DEBUGP(MP_ERROR,("NCM: unexpected notification 0x%02x!\n", event->bNotificationType) ); break; } }
VOID Sta11ResetStep1( __in PSTATION pStation, __in MP_RESET_TYPE ResetType ) { UNREFERENCED_PARAMETER(ResetType); MP_SET_FLAG(pStation, STA_RESET_IN_PROGRESS); // // Pause the beaconing // Hw11StopAdHoc(pStation->pNic); // Stop periodic scan (must call before stopping the // connection, since a periodic scan can start // off the association process) StaStopPeriodicScan(pStation); // Cleanup connection context StaResetConnection(pStation, TRUE); // Reset the state we had maintained about for roaming StaResetRoamState(pStation); // Reset the AdHoc station Info but do not clear AdHoc station list. StaResetAdHocStaInfo(pStation, FALSE); // Reset configuration (including resetting cipher and key on hardware) StaResetStationConfig(pStation); // We dont clear the BSS list on a reset // Clears PMKID cache pStation->PMKIDCache.CheckingTime = 0; pStation->PMKIDCache.Count = 0; pStation->Statistics.ullMcastWEPExcludedCount = 0; pStation->Statistics.ullUcastWEPExcludedCount = 0; }
MEDIA_STATE NICIndicateMediaState( __in PFDO_DATA FdoData ) { MEDIA_STATE CurrMediaState; KIRQL oldIrql; KeAcquireSpinLock(&FdoData->Lock, &oldIrql); CurrMediaState = GetMediaState(FdoData); if (CurrMediaState != FdoData->MediaState) { DebugPrint(WARNING, DBG_IOCTLS, "Media state changed to %s\n", ((CurrMediaState == Connected)? "Connected": "Disconnected")); FdoData->MediaState = CurrMediaState; if (CurrMediaState == Connected) { MP_CLEAR_FLAG(FdoData, fMP_ADAPTER_NO_CABLE); } else { MP_SET_FLAG(FdoData, fMP_ADAPTER_NO_CABLE); } KeReleaseSpinLock(&FdoData->Lock, oldIrql); // Indicate the media event NICServiceIndicateStatusIrp(FdoData); } else { KeReleaseSpinLock(&FdoData->Lock, oldIrql); } return CurrMediaState; }
/** * EnablePhyComa - called when network cable is unplugged * @pAdapter: pointer to our adapter structure * * driver receive an phy status change interrupt while in D0 and check that * phy_status is down. * * -- gate off JAGCore; * -- set gigE PHY in Coma mode * -- wake on phy_interrupt; Perform software reset JAGCore, * re-initialize jagcore and gigE PHY * * Add D0-ASPM-PhyLinkDown Support: * -- while in D0, when there is a phy_interrupt indicating phy link * down status, call the MPSetPhyComa routine to enter this active * state power saving mode * -- while in D0-ASPM-PhyLinkDown mode, when there is a phy_interrupt * indicating linkup status, call the MPDisablePhyComa routine to * restore JAGCore and gigE PHY */ void EnablePhyComa(struct et131x_adapter *pAdapter) { unsigned long lockflags; PM_CSR_t GlobalPmCSR; int32_t LoopCounter = 10; DBG_ENTER(et131x_dbginfo); GlobalPmCSR.value = readl(&pAdapter->CSRAddress->global.pm_csr.value); /* Save the GbE PHY speed and duplex modes. Need to restore this * when cable is plugged back in */ pAdapter->PoMgmt.PowerDownSpeed = pAdapter->AiForceSpeed; pAdapter->PoMgmt.PowerDownDuplex = pAdapter->AiForceDpx; /* Stop sending packets. */ spin_lock_irqsave(&pAdapter->SendHWLock, lockflags); MP_SET_FLAG(pAdapter, fMP_ADAPTER_LOWER_POWER); spin_unlock_irqrestore(&pAdapter->SendHWLock, lockflags); /* Wait for outstanding Receive packets */ while ((MP_GET_RCV_REF(pAdapter) != 0) && (LoopCounter-- > 0)) { mdelay(2); } /* Gate off JAGCore 3 clock domains */ GlobalPmCSR.bits.pm_sysclk_gate = 0; GlobalPmCSR.bits.pm_txclk_gate = 0; GlobalPmCSR.bits.pm_rxclk_gate = 0; writel(GlobalPmCSR.value, &pAdapter->CSRAddress->global.pm_csr.value); /* Program gigE PHY in to Coma mode */ GlobalPmCSR.bits.pm_phy_sw_coma = 1; writel(GlobalPmCSR.value, &pAdapter->CSRAddress->global.pm_csr.value); DBG_LEAVE(et131x_dbginfo); }
/** * et131x_open - Open the device for use. * @netdev: device to be opened * * Returns 0 on success, errno on failure (as defined in errno.h) */ int et131x_open(struct net_device *netdev) { int result = 0; struct et131x_adapter *adapter = netdev_priv(netdev); DBG_ENTER(et131x_dbginfo); /* Start the timer to track NIC errors */ add_timer(&adapter->ErrorTimer); /* Register our ISR */ DBG_TRACE(et131x_dbginfo, "Registering ISR...\n"); result = request_irq(netdev->irq, et131x_isr, IRQF_SHARED, netdev->name, netdev); if (result) { DBG_ERROR(et131x_dbginfo, "Could not register ISR\n"); DBG_LEAVE(et131x_dbginfo); return result; } /* Enable the Tx and Rx DMA engines (if not already enabled) */ et131x_rx_dma_enable(adapter); et131x_tx_dma_enable(adapter); /* Enable device interrupts */ et131x_enable_interrupts(adapter); MP_SET_FLAG(adapter, fMP_ADAPTER_INTERRUPT_IN_USE); /* We're ready to move some data, so start the queue */ netif_start_queue(netdev); DBG_LEAVE(et131x_dbginfo); return result; }
VOID NICReturnRFD( IN PFDO_DATA FdoData, IN PMP_RFD pMpRfd ) /*++ Routine Description: Recycle a RFD and put it back onto the receive list Assumption: This function is called with the Rcv SPINLOCK held. Arguments: FdoData Pointer to our FdoData pMpRfd Pointer to the RFD Return Value: None --*/ { PMP_RFD pLastMpRfd; PULONG pHwRfd = pMpRfd->HwRfd; ASSERT(pMpRfd->Flags == 0); MP_SET_FLAG(pMpRfd, fMP_RFD_RECV_READY); // // The processing on this RFD is done, so put it back on the tail of // our list // InsertTailList(&FdoData->RecvList, (PLIST_ENTRY)pMpRfd); FdoData->nReadyRecv++; ASSERT(FdoData->nReadyRecv <= FdoData->CurrNumRfd); }
IOReturn AgereET131x::enable(IONetworkInterface * netif) { //IOLog("AgereET131x::enable()\n"); if (pciDevice->open(this) == false) return kIOReturnError; /************************************************************************** Enable the Tx and Rx DMA engines (if not already enabled) *************************************************************************/ rx_dma_enable( ); tx_dma_enable(); /************************************************************************** Enable device interrupts *************************************************************************/ enable_interrupts(); MP_SET_FLAG( &adapter, fMP_ADAPTER_INTERRUPT_IN_USE ); /************************************************************************** We're ready to move some data, so start the queue *************************************************************************/ selectMedium(getSelectedMedium()); watchdogSource->setTimeoutMS(1000); transmitQueue->start(); workLoop->enableAllInterrupts(); enabledForNetif = true; return kIOReturnSuccess; }
static int device_open(struct net_device *dev) { struct vnt_private *pDevice = netdev_priv(dev); pDevice->fWPA_Authened = false; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " device_open...\n"); pDevice->rx_buf_sz = MAX_TOTAL_SIZE_WITH_ALL_HEADERS; if (device_alloc_bufs(pDevice) == false) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " device_alloc_bufs fail... \n"); return -ENOMEM; } if (device_init_defrag_cb(pDevice)== false) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Initial defragment cb fail \n"); goto free_rx_tx; } MP_CLEAR_FLAG(pDevice, fMP_DISCONNECTED); MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS); MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES); MP_SET_FLAG(pDevice, fMP_POST_READS); MP_SET_FLAG(pDevice, fMP_POST_WRITES); /* read config file */ Read_config_file(pDevice); if (device_init_registers(pDevice) == false) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " init register fail\n"); goto free_all; } device_set_multi(pDevice->dev); /* init for key management */ KeyvInitTable(pDevice,&pDevice->sKey); memcpy(pDevice->vnt_mgmt.abyMACAddr, pDevice->abyCurrentNetAddr, ETH_ALEN); memcpy(pDevice->dev->dev_addr, pDevice->abyCurrentNetAddr, ETH_ALEN); pDevice->bStopTx0Pkt = false; pDevice->bStopDataPkt = false; pDevice->bRoaming = false; pDevice->bIsRoaming = false; pDevice->bEnableRoaming = false; if (pDevice->bDiversityRegCtlON) { device_init_diversity_timer(pDevice); } vMgrObjectInit(pDevice); tasklet_init(&pDevice->EventWorkItem, (void *)INTvWorkItem, (unsigned long)pDevice); schedule_delayed_work(&pDevice->second_callback_work, HZ); pDevice->int_interval = 100; /* max 100 microframes */ pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; pDevice->bIsRxWorkItemQueued = true; pDevice->fKillEventPollingThread = false; pDevice->bEventAvailable = false; pDevice->bWPADEVUp = false; pDevice->bwextstep0 = false; pDevice->bwextstep1 = false; pDevice->bwextstep2 = false; pDevice->bwextstep3 = false; pDevice->bWPASuppWextEnabled = false; pDevice->byReAssocCount = 0; schedule_work(&pDevice->read_work_item); INTvWorkItem(pDevice); /* if WEP key already set by iwconfig but device not yet open */ if ((pDevice->bEncryptionEnable == true) && (pDevice->bTransmitKey == true)) { spin_lock_irq(&pDevice->lock); KeybSetDefaultKey( pDevice, &(pDevice->sKey), pDevice->byKeyIndex | (1 << 31), pDevice->uKeyLength, NULL, pDevice->abyKey, KEY_CTL_WEP ); spin_unlock_irq(&pDevice->lock); pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; } if (pDevice->vnt_mgmt.eConfigMode == WMAC_CONFIG_AP) bScheduleCommand((void *) pDevice, WLAN_CMD_RUN_AP, NULL); else bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL); netif_stop_queue(pDevice->dev); pDevice->flags |= DEVICE_FLAGS_OPENED; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open success..\n"); return 0; free_all: device_free_frag_bufs(pDevice); free_rx_tx: device_free_rx_bufs(pDevice); device_free_tx_bufs(pDevice); device_free_int_bufs(pDevice); usb_kill_urb(pDevice->pInterruptURB); usb_free_urb(pDevice->pInterruptURB); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open fail.. \n"); return -ENOMEM; }
static int device_close(struct net_device *dev) { struct vnt_private *pDevice = netdev_priv(dev); struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; int uu; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_close1\n"); if (pDevice == NULL) return -ENODEV; if (pDevice->bLinkPass) { bScheduleCommand((void *) pDevice, WLAN_CMD_DISASSOCIATE, NULL); mdelay(30); } memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); pMgmt->bShareKeyAlgorithm = false; pDevice->bEncryptionEnable = false; pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; spin_lock_irq(&pDevice->lock); for (uu = 0; uu < MAX_KEY_TABLE; uu++) MACvDisableKeyEntry(pDevice,uu); spin_unlock_irq(&pDevice->lock); if ((pDevice->flags & DEVICE_FLAGS_UNPLUG) == false) { MACbShutdown(pDevice); } netif_stop_queue(pDevice->dev); MP_SET_FLAG(pDevice, fMP_DISCONNECTED); MP_CLEAR_FLAG(pDevice, fMP_POST_WRITES); MP_CLEAR_FLAG(pDevice, fMP_POST_READS); pDevice->fKillEventPollingThread = true; cancel_delayed_work_sync(&pDevice->run_command_work); cancel_delayed_work_sync(&pDevice->second_callback_work); if (pDevice->bDiversityRegCtlON) { del_timer(&pDevice->TimerSQ3Tmax1); del_timer(&pDevice->TimerSQ3Tmax2); del_timer(&pDevice->TimerSQ3Tmax3); } cancel_work_sync(&pDevice->rx_mng_work_item); cancel_work_sync(&pDevice->read_work_item); tasklet_kill(&pDevice->EventWorkItem); pDevice->bRoaming = false; pDevice->bIsRoaming = false; pDevice->bEnableRoaming = false; pDevice->bCmdRunning = false; pDevice->bLinkPass = false; memset(pMgmt->abyCurrBSSID, 0, 6); pMgmt->eCurrState = WMAC_STATE_IDLE; pDevice->flags &= ~DEVICE_FLAGS_OPENED; device_free_tx_bufs(pDevice); device_free_rx_bufs(pDevice); device_free_int_bufs(pDevice); device_free_frag_bufs(pDevice); usb_kill_urb(pDevice->pInterruptURB); usb_free_urb(pDevice->pInterruptURB); BSSvClearNodeDBTable(pDevice, 0); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_close2 \n"); return 0; }
VOID NICReturnRFD( IN PFDO_DATA FdoData, IN PMP_RFD pMpRfd ) /*++ Routine Description: Recycle a RFD and put it back onto the receive list Assumption: This function is called with the Rcv SPINLOCK held. Arguments: FdoData Pointer to our FdoData pMpRfd Pointer to the RFD Return Value: None --*/ { PMP_RFD pLastMpRfd; PHW_RFD pHwRfd = pMpRfd->HwRfd; ASSERT(pMpRfd->Flags == 0); MP_SET_FLAG(pMpRfd, fMP_RFD_RECV_READY); // // HW_SPECIFIC_START // pHwRfd->RfdCbHeader.CbStatus = 0; pHwRfd->RfdActualCount = 0; pHwRfd->RfdCbHeader.CbCommand = (RFD_EL_BIT); pHwRfd->RfdCbHeader.CbLinkPointer = DRIVER_NULL; // // Append this RFD to the RFD chain if (!IsListEmpty(&FdoData->RecvList)) { pLastMpRfd = (PMP_RFD)GetListTailEntry(&FdoData->RecvList); // Link it onto the end of the chain dynamically pHwRfd = pLastMpRfd->HwRfd; pHwRfd->RfdCbHeader.CbLinkPointer = pMpRfd->HwRfdPhys; pHwRfd->RfdCbHeader.CbCommand = 0; } // // HW_SPECIFIC_END // // // The processing on this RFD is done, so put it back on the tail of // our list // InsertTailList(&FdoData->RecvList, (PLIST_ENTRY)pMpRfd); FdoData->nReadyRecv++; ASSERT(FdoData->nReadyRecv <= FdoData->CurrNumRfd); }
VOID NICHandleRecvInterrupt( IN PFDO_DATA FdoData ) /*++ Routine Description: Interrupt handler for receive processing. Put the received packets into an array and call NICServiceReadIrps. If we run low on RFDs, allocate another one. Assumption: This function is called with the Rcv SPINLOCK held. Arguments: FdoData Pointer to our FdoData Return Value: None --*/ { PMP_RFD pMpRfd = NULL; PHW_RFD pHwRfd = NULL; PMP_RFD PacketArray[NIC_DEF_RFDS]; PMP_RFD PacketFreeArray[NIC_DEF_RFDS]; UINT PacketArrayCount; UINT PacketFreeCount; UINT Index; UINT LoopIndex = 0; UINT LoopCount = NIC_MAX_RFDS / NIC_DEF_RFDS + 1; // avoid staying here too long BOOLEAN bContinue = TRUE; BOOLEAN bAllocNewRfd = FALSE; USHORT PacketStatus; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "---> NICHandleRecvInterrupt\n"); ASSERT(FdoData->nReadyRecv >= NIC_MIN_RFDS); while (LoopIndex++ < LoopCount && bContinue) { PacketArrayCount = 0; PacketFreeCount = 0; // // Process up to the array size RFD's // while (PacketArrayCount < NIC_DEF_RFDS) { if (IsListEmpty(&FdoData->RecvList)) { ASSERT(FdoData->nReadyRecv == 0); bContinue = FALSE; break; } // // Get the next MP_RFD to process // pMpRfd = (PMP_RFD)GetListHeadEntry(&FdoData->RecvList); // // Get the associated HW_RFD // pHwRfd = pMpRfd->HwRfd; // // Is this packet completed? // PacketStatus = NIC_RFD_GET_STATUS(pHwRfd); if (!NIC_RFD_STATUS_COMPLETED(PacketStatus)) { bContinue = FALSE; break; } // // HW specific - check if actual count field has been updated // if (!NIC_RFD_VALID_ACTUALCOUNT(pHwRfd)) { bContinue = FALSE; break; } // // Remove the RFD from the head of the List // RemoveEntryList((PLIST_ENTRY)pMpRfd); FdoData->nReadyRecv--; ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_RECV_READY)); MP_CLEAR_FLAG(pMpRfd, fMP_RFD_RECV_READY); // // A good packet? drop it if not. // if (!NIC_RFD_STATUS_SUCCESS(PacketStatus)) { TraceEvents(TRACE_LEVEL_WARNING, DBG_READ, "Receive failure = %x\n", PacketStatus); NICReturnRFD(FdoData, pMpRfd); continue; } // // Do not receive any packets until a filter has been set // if (!FdoData->PacketFilter) { NICReturnRFD(FdoData, pMpRfd); continue; } // // Do not receive any packets until we are at D0 // if (FdoData->DevicePowerState != PowerDeviceD0) { NICReturnRFD(FdoData, pMpRfd); continue; } pMpRfd->PacketSize = NIC_RFD_GET_PACKET_SIZE(pHwRfd); KeFlushIoBuffers(pMpRfd->Mdl, TRUE, TRUE); // // set the status on the packet, either resources or success // if (FdoData->nReadyRecv >= MIN_NUM_RFD) { MP_SET_FLAG(pMpRfd, fMP_RFD_RECV_PEND); } else { MP_SET_FLAG(pMpRfd, fMP_RFD_RESOURCES); _Analysis_assume_(PacketFreeCount <= PacketArrayCount); PacketFreeArray[PacketFreeCount] = pMpRfd; PacketFreeCount++; // // Reset the RFD shrink count - don't attempt to shrink RFD // FdoData->RfdShrinkCount = 0; // // Remember to allocate a new RFD later // bAllocNewRfd = TRUE; } PacketArray[PacketArrayCount] = pMpRfd; PacketArrayCount++; } // // if we didn't process any receives, just return from here // if (PacketArrayCount == 0) { break; } WdfSpinLockRelease(FdoData->RcvLock); WdfSpinLockAcquire(FdoData->Lock); // // if we have a Recv interrupt and have reported a media disconnect status // time to indicate the new status // if (Disconnected == FdoData->MediaState) { TraceEvents(TRACE_LEVEL_WARNING, DBG_READ, "Media state changed to Connected\n"); MP_CLEAR_FLAG(FdoData, fMP_ADAPTER_NO_CABLE); FdoData->MediaState = Connected; WdfSpinLockRelease(FdoData->Lock); // // Indicate the media event // NICServiceIndicateStatusIrp(FdoData); } else { WdfSpinLockRelease(FdoData->Lock); } NICServiceReadIrps( FdoData, PacketArray, PacketArrayCount); WdfSpinLockAcquire(FdoData->RcvLock); // // Return all the RFDs to the pool. // for (Index = 0; Index < PacketFreeCount; Index++) { // // Get the MP_RFD saved in this packet, in NICAllocRfd // pMpRfd = PacketFreeArray[Index]; ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_RESOURCES)); MP_CLEAR_FLAG(pMpRfd, fMP_RFD_RESOURCES); NICReturnRFD(FdoData, pMpRfd); } } // // If we ran low on RFD's, we need to allocate a new RFD // if (bAllocNewRfd) { // // Allocate one more RFD only if it doesn't exceed the max RFD limit // if (FdoData->CurrNumRfd < FdoData->MaxNumRfd && !FdoData->AllocNewRfd) { NTSTATUS status; FdoData->AllocNewRfd = TRUE; // // Since we are running at DISPATCH_LEVEL, we will queue a workitem // to allocate RFD memory at PASSIVE_LEVEL. Note that // AllocateCommonBuffer and FreeCommonBuffer can be called only at // PASSIVE_LEVEL. // status = PciDrvQueuePassiveLevelCallback(FdoData, NICAllocRfdWorkItem, NULL, NULL); if(!NT_SUCCESS(status)){ FdoData->AllocNewRfd = FALSE; } } } ASSERT(FdoData->nReadyRecv >= NIC_MIN_RFDS); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<--- NICHandleRecvInterrupt\n"); }
NTSTATUS NICReset( IN PFDO_DATA FdoData ) /*++ Routine Description: Function to reset the device. Arguments: FdoData Pointer to our adapter Return Value: NT Status code. Note: NICReset is called at DPC. Take advantage of this fact when acquiring or releasing spinlocks --*/ { NTSTATUS status; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_DPC, "---> MPReset\n"); WdfSpinLockAcquire(FdoData->Lock); WdfSpinLockAcquire(FdoData->SendLock); WdfSpinLockAcquire(FdoData->RcvLock); do { // // Is this adapter already doing a reset? // if (MP_TEST_FLAG(FdoData, fMP_ADAPTER_RESET_IN_PROGRESS)) { status = STATUS_SUCCESS; goto exit; } MP_SET_FLAG(FdoData, fMP_ADAPTER_RESET_IN_PROGRESS); // // Is this adapter doing link detection? // if (MP_TEST_FLAG(FdoData, fMP_ADAPTER_LINK_DETECTION)) { TraceEvents(TRACE_LEVEL_WARNING, DBG_DPC, "Reset is pended...\n"); status = STATUS_SUCCESS; goto exit; } // // Is this adapter going to be removed // if (MP_TEST_FLAG(FdoData, fMP_ADAPTER_NON_RECOVER_ERROR)) { status = STATUS_DEVICE_DATA_ERROR; if (MP_TEST_FLAG(FdoData, fMP_ADAPTER_REMOVE_IN_PROGRESS)) { goto exit; } // This is an unrecoverable hardware failure. // We need to tell NDIS to remove this miniport MP_SET_FLAG(FdoData, fMP_ADAPTER_REMOVE_IN_PROGRESS); MP_CLEAR_FLAG(FdoData, fMP_ADAPTER_RESET_IN_PROGRESS); WdfSpinLockRelease(FdoData->RcvLock); WdfSpinLockRelease(FdoData->SendLock); WdfSpinLockRelease(FdoData->Lock); // TODO: Log an entry into the eventlog WdfDeviceSetFailed(FdoData->WdfDevice, WdfDeviceFailedAttemptRestart); TraceEvents(TRACE_LEVEL_FATAL, DBG_DPC, "<--- MPReset, status=%x\n", status); return status; } // // Disable the interrupt and issue a reset to the NIC // NICDisableInterrupt(FdoData); NICIssueSelectiveReset(FdoData); // // Release all the locks and then acquire back the send lock // we are going to clean up the send queues // which may involve calling Ndis APIs // release all the locks before grabbing the send lock to // avoid deadlocks // WdfSpinLockRelease(FdoData->RcvLock); WdfSpinLockRelease(FdoData->SendLock); WdfSpinLockRelease(FdoData->Lock); WdfSpinLockAcquire(FdoData->SendLock); // // Free the packets on SendQueueList // NICFreeQueuedSendPackets(FdoData); // // Free the packets being actively sent & stopped // NICFreeBusySendPackets(FdoData); RtlZeroMemory(FdoData->MpTcbMem, FdoData->MpTcbMemSize); // // Re-initialize the send structures // NICInitSendBuffers(FdoData); WdfSpinLockRelease(FdoData->SendLock); // // get all the locks again in the right order // WdfSpinLockAcquire(FdoData->Lock); WdfSpinLockAcquire(FdoData->SendLock); WdfSpinLockAcquire(FdoData->RcvLock); // // Reset the RFD list and re-start RU // NICResetRecv(FdoData); status = NICStartRecv(FdoData); if (status != STATUS_SUCCESS) { // Are we having failures in a few consecutive resets? if (FdoData->HwErrCount < NIC_HARDWARE_ERROR_THRESHOLD) { // It's not over the threshold yet, let it to continue FdoData->HwErrCount++; } else { // This is an unrecoverable hardware failure. // We need to tell NDIS to remove this miniport MP_SET_FLAG(FdoData, fMP_ADAPTER_REMOVE_IN_PROGRESS); MP_CLEAR_FLAG(FdoData, fMP_ADAPTER_RESET_IN_PROGRESS); WdfSpinLockRelease(FdoData->RcvLock); WdfSpinLockRelease(FdoData->SendLock); WdfSpinLockRelease(FdoData->Lock); // TODO: Log an entry into the eventlog // // Tell the system that the device has failed. // WdfDeviceSetFailed(FdoData->WdfDevice, WdfDeviceFailedAttemptRestart); TraceEvents(TRACE_LEVEL_ERROR, DBG_DPC, "<--- MPReset, status=%x\n", status); return(status); } break; } FdoData->HwErrCount = 0; MP_CLEAR_FLAG(FdoData, fMP_ADAPTER_HARDWARE_ERROR); NICEnableInterrupt(FdoData->WdfInterrupt, FdoData); } WHILE (FALSE); MP_CLEAR_FLAG(FdoData, fMP_ADAPTER_RESET_IN_PROGRESS); exit: WdfSpinLockRelease(FdoData->RcvLock); WdfSpinLockRelease(FdoData->SendLock); WdfSpinLockRelease(FdoData->Lock); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_DPC, "<--- MPReset, status=%x\n", status); return(status); }
VOID NICWritePacket( __in PFDO_DATA FdoData, __in PIRP Irp, __in BOOLEAN bFromQueue ) /*++ Routine Description: Do the work to send a packet Assumption: Send spinlock has been acquired Arguments: FdoData Pointer to our FdoData Packet The packet bFromQueue TRUE if it's taken from the send wait queue Return Value: --*/ { PMP_TCB pMpTcb = NULL; ULONG packetLength; PVOID virtualAddress; DebugPrint(TRACE, DBG_WRITE, "--> NICWritePacket, Irp= %p\n", Irp); // // Get the next free TCB and initialize it to represent the // request buffer. // pMpTcb = FdoData->CurrSendTail; ASSERT(!MP_TEST_FLAG(pMpTcb, fMP_TCB_IN_USE)); // // If the adapter is not ready, fail the request. // if(MP_IS_NOT_READY(FdoData)) { MP_FREE_SEND_PACKET(FdoData, pMpTcb, STATUS_DEVICE_NOT_READY); return; } pMpTcb->FirstBuffer = Irp->MdlAddress; virtualAddress = MmGetMdlVirtualAddress(Irp->MdlAddress); pMpTcb->BufferCount = 1; pMpTcb->PacketLength = packetLength = MmGetMdlByteCount(Irp->MdlAddress); pMpTcb->PhysBufCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(virtualAddress, packetLength); pMpTcb->Irp = Irp; MP_SET_FLAG(pMpTcb, fMP_TCB_IN_USE); // // Call the send handler, it only needs to deal with the frag list // NICSendPacket(FdoData, pMpTcb, Irp->Tail.Overlay.DriverContext[3]); FdoData->nBusySend++; ASSERT(FdoData->nBusySend <= FdoData->NumTcb); FdoData->CurrSendTail = FdoData->CurrSendTail->Next; DebugPrint(TRACE, DBG_WRITE, "<-- NICWritePacket\n"); return; }
VOID NICHandleRecvInterrupt( IN PFDO_DATA FdoData ) /*++ Routine Description: Interrupt handler for receive processing. Put the received packets into an array and call NICServiceReadIrps. If we run low on RFDs, allocate another one. Assumption: This function is called with the Rcv SPINLOCK held. Arguments: FdoData Pointer to our FdoData Return Value: None --*/ { PMP_RFD pMpRfd = NULL; PULONG pHwRfd = NULL; PMP_RFD PacketArray[NIC_DEF_RFDS]; PMP_RFD PacketFreeArray[NIC_DEF_RFDS]; UINT PacketArrayCount; UINT PacketFreeCount; UINT Index; UINT LoopIndex = 0; UINT LoopCount = NIC_MAX_RFDS / NIC_DEF_RFDS + 1; // avoid staying here too long BOOLEAN bContinue = TRUE; BOOLEAN bAllocNewRfd = FALSE; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "---> NICHandleRecvInterrupt\n"); ASSERT(FdoData->nReadyRecv >= NIC_MIN_RFDS); while (LoopIndex++ < LoopCount && bContinue) { PacketArrayCount = 0; PacketFreeCount = 0; // // Process up to the array size RFD's // while (PacketArrayCount < NIC_DEF_RFDS) { if (IsListEmpty(&FdoData->RecvList)) { ASSERT(FdoData->nReadyRecv == 0); bContinue = FALSE; break; } // // Get the next MP_RFD to process // pMpRfd = (PMP_RFD)GetListHeadEntry(&FdoData->RecvList); // // Get the associated HW_RFD // pHwRfd = pMpRfd->HwRfd; // // Remove the RFD from the head of the List // RemoveEntryList((PLIST_ENTRY)pMpRfd); FdoData->nReadyRecv--; ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_RECV_READY)); MP_CLEAR_FLAG(pMpRfd, fMP_RFD_RECV_READY); pMpRfd->PacketSize = 4; KeFlushIoBuffers(pMpRfd->Mdl, TRUE, TRUE); MP_SET_FLAG(pMpRfd, fMP_RFD_RECV_PEND); PacketArray[PacketArrayCount] = pMpRfd; PacketArrayCount++; } // // if we didn't process any receives, just return from here // if (PacketArrayCount == 0) { break; } WdfSpinLockRelease(FdoData->RcvLock); NICServiceReadIrps( FdoData, PacketArray, PacketArrayCount); WdfSpinLockAcquire(FdoData->RcvLock); // // Return all the RFDs to the pool. // for (Index = 0; Index < PacketFreeCount; Index++) { // // Get the MP_RFD saved in this packet, in NICAllocRfd // pMpRfd = PacketFreeArray[Index]; ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_RESOURCES)); MP_CLEAR_FLAG(pMpRfd, fMP_RFD_RESOURCES); NICReturnRFD(FdoData, pMpRfd); } } ASSERT(FdoData->nReadyRecv >= NIC_MIN_RFDS); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<--- NICHandleRecvInterrupt\n"); }