BOOLEAN NICEvtInterruptIsr( IN WDFINTERRUPT Interrupt, IN ULONG MessageID ) /*++ Routine Description: Interrupt handler for the device. Arguments: Interupt - Address of the framework interrupt object MessageID - Return Value: TRUE if our device is interrupting, FALSE otherwise. --*/ { BOOLEAN InterruptRecognized = FALSE; PFDO_DATA FdoData = NULL; USHORT IntStatus; UNREFERENCED_PARAMETER( MessageID ); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INTERRUPT, "--> NICEvtInterruptIsr\n"); FdoData = FdoGetData(WdfInterruptGetDevice(Interrupt)); // // We process the interrupt if it's not disabled and it's active // if (!NIC_INTERRUPT_DISABLED(FdoData) && NIC_INTERRUPT_ACTIVE(FdoData)) { InterruptRecognized = TRUE; // // Disable the interrupt (will be re-enabled in NICEvtInterruptDpc // NICDisableInterrupt(FdoData); // // Acknowledge the interrupt(s) and get the interrupt status // NIC_ACK_INTERRUPT(FdoData, IntStatus); WdfInterruptQueueDpcForIsr( Interrupt ); } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INTERRUPT, "<-- NICEvtInterruptIsr\n"); return InterruptRecognized; }
NTSTATUS NICEvtInterruptDisable( IN WDFINTERRUPT Interrupt, IN WDFDEVICE AssociatedDevice ) /*++ Routine Description: This event is called before the Framework moves the device to D1, D2 or D3 and before EvtDeviceD0Exit. The driver should disable its interrupt here. This function will be called at the device's assigned interrupt IRQL (DIRQL.) Arguments: Interrupt - Handle to a Framework interrupt object. AssociatedDevice - Handle to a Framework device object. Return Value: STATUS_SUCCESS - indicates success. --*/ { PFDO_DATA fdoData; UNREFERENCED_PARAMETER(Interrupt); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_PNP, "--> NICEvtInterruptDisable\n"); fdoData = FdoGetData(AssociatedDevice); NICDisableInterrupt(fdoData); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_PNP, "<-- NICEvtInterruptDisable\n"); return STATUS_SUCCESS; }
int rt28xx_close(IN PNET_DEV dev) { struct net_device * net_dev = (struct net_device *)dev; RTMP_ADAPTER *pAd = net_dev->ml_priv; BOOLEAN Cancelled = FALSE; UINT32 i = 0; #ifdef RT2870 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(unlink_wakeup); DECLARE_WAITQUEUE(wait, current); #endif DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n")); if (pAd == NULL) return 0; { #ifdef RT2860 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) || RTMP_SET_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) #endif #ifdef RT2870 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) #endif { #ifdef RT2860 AsicForceWakeup(pAd, RTMP_HALT); #endif #ifdef RT2870 AsicForceWakeup(pAd, TRUE); #endif } if (INFRA_ON(pAd) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { MLME_DISASSOC_REQ_STRUCT DisReq; MLME_QUEUE_ELEM *MsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); COPY_MAC_ADDR(DisReq.Addr, pAd->CommonCfg.Bssid); DisReq.Reason = REASON_DEAUTH_STA_LEAVING; MsgElem->Machine = ASSOC_STATE_MACHINE; MsgElem->MsgType = MT2_MLME_DISASSOC_REQ; MsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); NdisMoveMemory(MsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); pAd->MlmeAux.AutoReconnectSsidLen= 32; NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; MlmeDisassocReqAction(pAd, MsgElem); kfree(MsgElem); RTMPusecDelay(1000); } #ifdef RT2870 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS); #endif #ifdef CCX_SUPPORT RTMPCancelTimer(&pAd->StaCfg.LeapAuthTimer, &Cancelled); #endif RTMPCancelTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, &Cancelled); RTMPCancelTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, &Cancelled); MlmeRadioOff(pAd); #ifdef RT2860 pAd->bPCIclkOff = FALSE; #endif } RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); for (i = 0 ; i < NUM_OF_TX_RING; i++) { while (pAd->DeQueueRunning[i] == TRUE) { printk("Waiting for TxQueue[%d] done..........\n", i); RTMPusecDelay(1000); } } #ifdef RT2870 add_wait_queue (&unlink_wakeup, &wait); pAd->wait = &unlink_wakeup; i = 0; while(i < 25) { unsigned long IrqFlags; RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); if (pAd->PendingRx == 0) { RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); break; } RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); msleep(UNLINK_TIMEOUT_MS); i++; } pAd->wait = NULL; remove_wait_queue (&unlink_wakeup, &wait); #endif #ifdef RT2870 RT2870_TimerQ_Exit(pAd); RT28xxThreadTerminate(pAd); #endif MlmeHalt(pAd); kill_thread_task(pAd); MacTableReset(pAd); MeasureReqTabExit(pAd); TpcReqTabExit(pAd); #ifdef RT2860 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) { NICDisableInterrupt(pAd); } NICIssueReset(pAd); if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { RT28XX_IRQ_RELEASE(net_dev) RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); } #endif RTMPFreeTxRxRingMemory(pAd); RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); ba_reordering_resource_release(pAd); RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP); return 0; }
static int rt28xx_init(IN struct net_device *net_dev) { #ifdef RT2860 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)net_dev->ml_priv; #endif #ifdef RT2870 PRTMP_ADAPTER pAd = net_dev->ml_priv; #endif UINT index; UCHAR TmpPhy; NDIS_STATUS Status; UINT32 MacCsr0 = 0; ba_reordering_resource_init(pAd, MAX_REORDERING_MPDU_NUM); index = 0; do { RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); pAd->MACVersion = MacCsr0; if ((pAd->MACVersion != 0x00) && (pAd->MACVersion != 0xFFFFFFFF)) break; RTMPusecDelay(10); } while (index++ < 100); DBGPRINT(RT_DEBUG_TRACE, ("MAC_CSR0 [ Ver:Rev=0x%08x]\n", pAd->MACVersion)); RT28XXDMADisable(pAd); Status = NICLoadFirmware(pAd); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT_ERR(("NICLoadFirmware failed, Status[=0x%08x]\n", Status)); goto err1; } NICLoadRateSwitchingParams(pAd); #ifdef RT2860 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) { NICDisableInterrupt(pAd); } #endif Status = RTMPAllocTxRxRingMemory(pAd); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT_ERR(("RTMPAllocDMAMemory failed, Status[=0x%08x]\n", Status)); goto err1; } RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); Status = MlmeInit(pAd); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT_ERR(("MlmeInit failed, Status[=0x%08x]\n", Status)); goto err2; } UserCfgInit(pAd); #ifdef RT2870 RT2870_TimerQ_Init(pAd); #endif RT28XX_TASK_THREAD_INIT(pAd, Status); if (Status != NDIS_STATUS_SUCCESS) goto err1; CfgInitHook(pAd); NdisAllocateSpinLock(&pAd->MacTabLock); MeasureReqTabInit(pAd); TpcReqTabInit(pAd); Status = NICInitializeAdapter(pAd, TRUE); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT_ERR(("NICInitializeAdapter failed, Status[=0x%08x]\n", Status)); if (Status != NDIS_STATUS_SUCCESS) goto err3; } Status = RTMPReadParametersHook(pAd); printk("1. Phy Mode = %d\n", pAd->CommonCfg.PhyMode); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT_ERR(("NICReadRegParameters failed, Status[=0x%08x]\n",Status)); goto err4; } #ifdef RT2870 pAd->CommonCfg.bMultipleIRP = FALSE; if (pAd->CommonCfg.bMultipleIRP) pAd->CommonCfg.NumOfBulkInIRP = RX_RING_SIZE; else pAd->CommonCfg.NumOfBulkInIRP = 1; #endif pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable; pAd->CommonCfg.DesiredHtPhy.AmsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; pAd->CommonCfg.DesiredHtPhy.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; printk("2. Phy Mode = %d\n", pAd->CommonCfg.PhyMode); NICReadEEPROMParameters(pAd, mac); printk("3. Phy Mode = %d\n", pAd->CommonCfg.PhyMode); NICInitAsicFromEEPROM(pAd); TmpPhy = pAd->CommonCfg.PhyMode; pAd->CommonCfg.PhyMode = 0xff; RTMPSetPhyMode(pAd, TmpPhy); SetCommonHT(pAd); if (pAd->ChannelListNum == 0) { printk("Wrong configuration. No valid channel found. Check \"ContryCode\" and \"ChannelGeography\" setting.\n"); goto err4; } printk("MCS Set = %02x %02x %02x %02x %02x\n", pAd->CommonCfg.HtCapability.MCSSet[0], pAd->CommonCfg.HtCapability.MCSSet[1], pAd->CommonCfg.HtCapability.MCSSet[2], pAd->CommonCfg.HtCapability.MCSSet[3], pAd->CommonCfg.HtCapability.MCSSet[4]); #ifdef RT2870 NICInitRT30xxRFRegisters(pAd); #endif AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.Channel); #ifndef RT2870 AsicSendCommandToMcu(pAd, 0x72, 0xFF, 0x00, 0x00); #endif if (pAd && (Status != NDIS_STATUS_SUCCESS)) { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); } } else if (pAd) { OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE); DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event B!\n")); #ifdef RT2870 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS); RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS); for(index=0; index<pAd->CommonCfg.NumOfBulkInIRP; index++) { RTUSBBulkReceive(pAd); DBGPRINT(RT_DEBUG_TRACE, ("RTUSBBulkReceive!\n" )); } #endif } DBGPRINT_S(Status, ("<==== RTMPInitialize, Status=%x\n", Status)); return TRUE; err4: err3: MlmeHalt(pAd); err2: RTMPFreeTxRxRingMemory(pAd); err1: os_free_mem(pAd, pAd->mpdu_blk_pool.mem); RT28XX_IRQ_RELEASE(net_dev); printk("!!! %s Initialized fail !!!\n", RT28xx_CHIP_NAME); return FALSE; }
BOOLEAN MPSetPowerLowPrivate( PVOID Context ) /*++ Routine Description: The section follows the steps mentioned in Section C.2.6.2 of the Reference Manual. Arguments: Adapter Pointer to our adapter Return Value: --*/ { CSR_FILTER_STRUC Filter; USHORT IntStatus; MP_PMCSR PMCSR = {0}; ULONG ulResult; PFDO_DATA FdoData = Context; DebugPrint(TRACE, DBG_POWER, "-->MPSetPowerLowPrivate\n"); RtlZeroMemory (&Filter, sizeof (Filter)); do { // // Before issue the command to low power state, we should disable the // interrup and ack all the pending interrupts, then set the adapter's power to // low state. // NICDisableInterrupt(FdoData); NIC_ACK_INTERRUPT(FdoData, IntStatus); // // If the driver should wake up the machine // if (FdoData->AllowWakeArming) { // // Send the WakeUp Patter to the nic MPIssueScbPoMgmtCommand(FdoData, &Filter, TRUE); // // Section C.2.6.2 - The driver needs to wait for the CU to idle // The above function already waits for the CU to idle // ASSERT ((FdoData->CSRAddress->ScbStatus & SCB_CUS_MASK) == SCB_CUS_IDLE); } else { ulResult = FdoData->BusInterface.GetBusData( FdoData->BusInterface.Context, PCI_WHICHSPACE_CONFIG, (PVOID)&PMCSR, FIELD_OFFSET(MP_PM_PCI_SPACE, PMCSR), sizeof(PMCSR)); if(ulResult != sizeof(PMCSR)){ ASSERT(ulResult == sizeof(PMCSR)); DebugPrint(ERROR, DBG_POWER, "GetBusData for PMCSR failed\n"); return FALSE; } if (PMCSR.PME_En == 1) { // // PME is enabled. Clear the PME_En bit. // So that it is not asserted // MpClearPME_En (FdoData,PMCSR); } // // Set the driver to lower power state by OS // } } while (FALSE); DebugPrint(TRACE, DBG_POWER, "<--MPSetPowerLowPrivate\n"); return TRUE; }
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); }