int PIPEnsControlOut(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_WRITES) return STATUS_FAILURE; if (pDevice->Flags & fMP_CONTROL_READS) return STATUS_FAILURE; MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES); 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); MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES); return STATUS_FAILURE; } 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; }
VOID Sta11ResetStep4( __in PSTATION pStation, __in MP_RESET_TYPE ResetType ) { MP_CLEAR_FLAG(pStation, STA_RESET_IN_PROGRESS); // // Start scanning // StaStartPeriodicScan(pStation); if (ResetType == MP_RESET_TYPE_NDIS_RESET) { // // Restart beaconing. NDIS Reset should stop beacons & probes only temporarily // // Hw11StartBSSAdvertisment(pStation->pNic); // // Here we could reestablish the connection. However, // to reduce state to be maintained, we indicated // disconnect and let the OS reestablish the connection // } }
/** * et131x_close - Close the device * @netdev: device to be closed * * Returns 0 on success, errno on failure (as defined in errno.h) */ int et131x_close(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); DBG_ENTER(et131x_dbginfo); /* First thing is to stop the queue */ netif_stop_queue(netdev); /* Stop the Tx and Rx DMA engines */ et131x_rx_dma_disable(adapter); et131x_tx_dma_disable(adapter); /* Disable device interrupts */ et131x_disable_interrupts(adapter); /* Deregistering ISR */ MP_CLEAR_FLAG(adapter, fMP_ADAPTER_INTERRUPT_IN_USE); DBG_TRACE(et131x_dbginfo, "Deregistering ISR...\n"); free_irq(netdev->irq, netdev); /* Stop the error timer */ del_timer_sync(&adapter->ErrorTimer); DBG_LEAVE(et131x_dbginfo); return 0; }
int PIPEnsControlIn( 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_READS) return STATUS_FAILURE; 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); }else { MP_SET_FLAG(pDevice, fMP_CONTROL_READS); } 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; }
IOReturn AgereET131x::disable(IONetworkInterface * netif) { //IOLog("AgereET131x::disable()\n"); if(!enabledForNetif) return kIOReturnSuccess; enabledForNetif = false; /************************************************************************** First thing is to stop the queue *************************************************************************/ workLoop->disableAllInterrupts(); if (transmitQueue) { transmitQueue->stop(); transmitQueue->flush(); } //stop watchdog timer watchdogSource->cancelTimeout(); // Stop the timer event source. /************************************************************************** Stop the Tx and Rx DMA engines *************************************************************************/ rx_dma_disable(); tx_dma_disable(); /************************************************************************** Disable device interrupts *************************************************************************/ disable_interrupts( ); /************************************************************************** Deregistering ISR *************************************************************************/ MP_CLEAR_FLAG( &adapter, fMP_ADAPTER_INTERRUPT_IN_USE ); setLinkStatus( kIONetworkLinkValid ); // Valid sans kIONetworkLinkActive /************************************************************************** Stop the error timer *************************************************************************/ //del_timer_sync( &adapter->ErrorTimer ); pciDevice->close(this); return kIOReturnSuccess; }
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; } }
/** * DisablePhyComa - Disable the Phy Coma Mode * @pAdapter: pointer to our adapter structure */ void DisablePhyComa(struct et131x_adapter *pAdapter) { PM_CSR_t GlobalPmCSR; DBG_ENTER(et131x_dbginfo); GlobalPmCSR.value = readl(&pAdapter->CSRAddress->global.pm_csr.value); /* Disable phy_sw_coma register and re-enable JAGCore clocks */ GlobalPmCSR.bits.pm_sysclk_gate = 1; GlobalPmCSR.bits.pm_txclk_gate = 1; GlobalPmCSR.bits.pm_rxclk_gate = 1; GlobalPmCSR.bits.pm_phy_sw_coma = 0; writel(GlobalPmCSR.value, &pAdapter->CSRAddress->global.pm_csr.value); /* Restore the GbE PHY speed and duplex modes; * Reset JAGCore; re-configure and initialize JAGCore and gigE PHY */ pAdapter->AiForceSpeed = pAdapter->PoMgmt.PowerDownSpeed; pAdapter->AiForceDpx = pAdapter->PoMgmt.PowerDownDuplex; /* Re-initialize the send structures */ et131x_init_send(pAdapter); /* Reset the RFD list and re-start RU */ et131x_reset_recv(pAdapter); /* Bring the device back to the state it was during init prior to * autonegotiation being complete. This way, when we get the auto-neg * complete interrupt, we can complete init by calling ConfigMacREGS2. */ et131x_soft_reset(pAdapter); /* setup et1310 as per the documentation ?? */ et131x_adapter_setup(pAdapter); /* Allow Tx to restart */ MP_CLEAR_FLAG(pAdapter, fMP_ADAPTER_LOWER_POWER); /* Need to re-enable Rx. */ et131x_rx_dma_enable(pAdapter); DBG_LEAVE(et131x_dbginfo); }
static void s_nsControlInUsbIoCompleteRead(struct urb *urb) { struct vnt_private *pDevice = (struct vnt_private *)urb->context; switch (urb->status) { case 0: break; case -EINPROGRESS: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status EINPROGRESS%d\n", urb->status); break; case -ENOENT: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status = ENOENT %d\n", urb->status); break; default: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status %d\n", urb->status); } MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS); }
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; }
static void s_nsControlInUsbIoCompleteWrite( struct urb *urb ) { PSDevice pDevice; pDevice = urb->context; switch (urb->status) { case 0: break; case -EINPROGRESS: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status EINPROGRESS%d\n", urb->status); break; case -ENOENT: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status ENOENT %d\n", urb->status); break; default: DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status %d\n", urb->status); } MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES); }
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"); }
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; }
NTSTATUS NICLinkDetection( PFDO_DATA FdoData ) /*++ Routine Description: Timer function for postponed link negotiation. Called from the NICWatchDogEvtTimerFunc. After the link detection is over we will complete any pending ioctl or send IRPs. Arguments: FdoData Pointer to our FdoData Return Value: NT status --*/ { NTSTATUS status = STATUS_SUCCESS; MEDIA_STATE CurrMediaState; PNDISPROT_QUERY_OID pQuery = NULL; PNDISPROT_SET_OID pSet = NULL; PVOID DataBuffer; ULONG BytesWritten; NDIS_OID Oid; PVOID InformationBuffer; size_t bufSize; WDFREQUEST request; // // Handle the link negotiation. // if (FdoData->bLinkDetectionWait) { status = ScanAndSetupPhy(FdoData); } else { status = PhyDetect(FdoData); } if (status == STATUS_PENDING) { return status; } // // Reset some variables for link detection // FdoData->bLinkDetectionWait = FALSE; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_DPC, "NICLinkDetection - negotiation done\n"); WdfSpinLockAcquire(FdoData->Lock); MP_CLEAR_FLAG(FdoData, fMP_ADAPTER_LINK_DETECTION); WdfSpinLockRelease(FdoData->Lock); // // Any OID query request pending? // status = NICGetIoctlRequest(FdoData->PendingIoctlQueue, IOCTL_NDISPROT_QUERY_OID_VALUE, &request); if(NT_SUCCESS(status)) { status = WdfRequestRetrieveOutputBuffer(request, sizeof(NDISPROT_QUERY_OID), &DataBuffer, &bufSize); if(NT_SUCCESS(status)) { pQuery = (PNDISPROT_QUERY_OID)DataBuffer; Oid = pQuery->Oid; InformationBuffer = &pQuery->Data[0]; switch(Oid) { case OID_GEN_LINK_SPEED: *((PULONG)InformationBuffer) = FdoData->usLinkSpeed * 10000; BytesWritten = sizeof(ULONG); break; case OID_GEN_MEDIA_CONNECT_STATUS: default: ASSERT(Oid == OID_GEN_MEDIA_CONNECT_STATUS); CurrMediaState = NICIndicateMediaState(FdoData); RtlMoveMemory(InformationBuffer, &CurrMediaState, sizeof(NDIS_MEDIA_STATE)); BytesWritten = sizeof(NDIS_MEDIA_STATE); } WdfRequestCompleteWithInformation(request, status, BytesWritten); } } // // Any OID set request pending? // status = NICGetIoctlRequest(FdoData->PendingIoctlQueue, IOCTL_NDISPROT_SET_OID_VALUE, &request); if(NT_SUCCESS(status)) { ULONG PacketFilter; status = WdfRequestRetrieveOutputBuffer(request, sizeof(NDISPROT_SET_OID), &DataBuffer, &bufSize); if(NT_SUCCESS(status)) { pSet = (PNDISPROT_SET_OID)DataBuffer; Oid = pSet->Oid; InformationBuffer = &pSet->Data[0]; if (Oid == OID_GEN_CURRENT_PACKET_FILTER) { RtlMoveMemory(&PacketFilter, InformationBuffer, sizeof(ULONG)); WdfSpinLockAcquire(FdoData->Lock); status = NICSetPacketFilter( FdoData, PacketFilter); WdfSpinLockRelease(FdoData->Lock); if (status == STATUS_SUCCESS) { FdoData->PacketFilter = PacketFilter; } WdfRequestCompleteWithInformation(request, status, 0); } } } // // Any read pending? // WdfSpinLockAcquire(FdoData->RcvLock); // // Start the NIC receive unit // status = NICStartRecv(FdoData); if (status != STATUS_SUCCESS) { MP_SET_HARDWARE_ERROR(FdoData); } WdfSpinLockRelease(FdoData->RcvLock); // // Send packets which have been queued while link detection was going on. // NICCheckForQueuedSends(FdoData); return status; }
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 NICServiceReadIrps( PFDO_DATA FdoData, PMP_RFD *PacketArray, ULONG PacketArrayCount ) /*++ Routine Description: Copy the data from the recv buffers to pending read IRP buffers and complete the IRP. When used as network driver, copy operation can be avoided by devising a private interface between us and the NDIS-WDM filter and have the NDIS-WDM edge to indicate our buffers directly to NDIS. Called at DISPATCH_LEVEL. Take advantage of that fact while acquiring spinlocks. Arguments: FdoData Pointer to our FdoData Return Value: None --*/ { PMP_RFD pMpRfd = NULL; ULONG index; NTSTATUS status; PVOID buffer; WDFREQUEST request; size_t bufLength=0; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "--> NICServiceReadIrps\n"); for(index=0; index < PacketArrayCount; index++) { pMpRfd = PacketArray[index]; ASSERT(pMpRfd); status = WdfIoQueueRetrieveNextRequest( FdoData->PendingReadQueue, &request ); if(NT_SUCCESS(status)){ WDF_REQUEST_PARAMETERS params; ULONG length = 0; WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters( request, ¶ms ); ASSERT(status == STATUS_SUCCESS); bufLength = params.Parameters.Read.Length; status = WdfRequestRetrieveOutputBuffer(request, bufLength, &buffer, &bufLength); if(NT_SUCCESS(status) ) { length = min((ULONG)bufLength, pMpRfd->PacketSize); RtlCopyMemory(buffer, pMpRfd->Buffer, length); Hexdump((TRACE_LEVEL_VERBOSE, DBG_READ, "Received Packet Data: %!HEXDUMP!\n", log_xstr(buffer, (USHORT)length))); FdoData->BytesReceived += length; } WdfRequestCompleteWithInformation(request, status, length); }else { ASSERTMSG("WdfIoQueueRetrieveNextRequest failed", (status == STATUS_NO_MORE_ENTRIES || status == STATUS_WDF_PAUSED)); } WdfSpinLockAcquire(FdoData->RcvLock); ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_RECV_PEND)); MP_CLEAR_FLAG(pMpRfd, fMP_RFD_RECV_PEND); if (FdoData->RfdShrinkCount < NIC_RFD_SHRINK_THRESHOLD) { NICReturnRFD(FdoData, pMpRfd); } else { ASSERT(FdoData->CurrNumRfd > FdoData->NumRfd); status = PciDrvQueuePassiveLevelCallback(FdoData, NICFreeRfdWorkItem, (PVOID)pMpRfd, NULL); if(NT_SUCCESS(status)){ FdoData->RfdShrinkCount = 0; FdoData->CurrNumRfd--; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "Shrink... CurrNumRfd = %d\n", FdoData->CurrNumRfd); } else { // // We couldn't queue a workitem to free memory, so let us // put that back in the main pool and try again next time. // NICReturnRFD(FdoData, pMpRfd); } } WdfSpinLockRelease(FdoData->RcvLock); }// end of loop TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<-- NICServiceReadIrps\n"); return; }
NTSTATUS InterruptPipeCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) /*++ Routine Description: Completion routine for the read request. This routine indicates the received packet from the WDM driver to NDIS. This routine also handles the case where another thread has canceled the read request. Arguments: DeviceObject - not used. Should be NULL Irp - Pointer to our read IRP Context - pointer to our adapter context structure Return Value: STATUS_MORE_PROCESSING_REQUIRED - because this is an asynchronouse IRP and we want to reuse it. --*/ { PNOTICB pNotiCB = (PNOTICB)Context; PMP_ADAPTER Adapter = pNotiCB->Adapter; ULONG bytesRead = 0; UNREFERENCED_PARAMETER(DeviceObject); DEBUGP(MP_TRACE, ("--> InterruptPipeCompletion\n")); if(!NT_SUCCESS(Irp->IoStatus.Status)) { Adapter->nReadsCompletedWithError++; DEBUGP (MP_LOUD, ("Read request failed %x\n", Irp->IoStatus.Status)); // // Clear the flag to prevent any more reads from being // posted to the target device. // MP_CLEAR_FLAG(Adapter, fMP_POST_INTERRUPT); } else { bytesRead = (ULONG)pNotiCB->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength; DEBUGP (MP_VERY_LOUD, ("Read %d bytes\n", bytesRead)); pNotiCB->ulSize=bytesRead; } if (InterlockedExchange((PVOID)&pNotiCB->IrpLock, IRPLOCK_COMPLETED) == IRPLOCK_CANCEL_STARTED) { // // NICFreeBusyRecvPackets has got the control of the IRP. It will // now take the responsibility of freeing the IRP. // Therefore... return STATUS_MORE_PROCESSING_REQUIRED; } if (NT_SUCCESS(Irp->IoStatus.Status)) { cdc_ncm_status(Adapter,pNotiCB->pData,pNotiCB->ulSize); } if(NdisInterlockedDecrement(&pNotiCB->Ref) == 0) { NICFreeNotify(pNotiCB); } DEBUGP(MP_TRACE, ("<-- InterruptPipeCompletion\n")); return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS NICReadRequestCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) /*++ Routine Description: Completion routine for the read request. This routine indicates the received packet from the WDM driver to NDIS. This routine also handles the case where another thread has canceled the read request. Arguments: DeviceObject - not used. Should be NULL Irp - Pointer to our read IRP Context - pointer to our adapter context structure Return Value: STATUS_MORE_PROCESSING_REQUIRED - because this is an asynchronouse IRP and we want to reuse it. --*/ { PRCB pRCB = (PRCB)Context; PMP_ADAPTER Adapter = pRCB->Adapter; ULONG bytesRead = 0; BOOLEAN bIndicateReceive = FALSE; BOOLEAN datagramsover=TRUE; UNREFERENCED_PARAMETER(DeviceObject); DEBUGP(MP_TRACE, ("--> NICReadRequestCompletion\n")); if(!NT_SUCCESS(Irp->IoStatus.Status)) { Adapter->nReadsCompletedWithError++; DEBUGP (MP_LOUD, ("Read request failed %x\n", Irp->IoStatus.Status)); // // Clear the flag to prevent any more reads from being // posted to the target device. // MP_CLEAR_FLAG(Adapter, fMP_POST_READS); } else { bytesRead = (ULONG)pRCB->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength; DEBUGP (MP_VERY_LOUD, ("Read %d bytes\n", bytesRead)); Adapter->nBytesRead += bytesRead; pRCB->ulSize=bytesRead; pRCB->nextndeoffset=pRCB->nextndpoffset=0; pRCB->bIsOver=FALSE; bIndicateReceive = TRUE; } if (InterlockedExchange((PVOID)&pRCB->IrpLock, IRPLOCK_COMPLETED) == IRPLOCK_CANCEL_STARTED) { // // NICFreeBusyRecvPackets has got the control of the IRP. It will // now take the responsibility of freeing the IRP. // Therefore... return STATUS_MORE_PROCESSING_REQUIRED; } ncmdivi: if(bIndicateReceive) { datagramsover=cdc_ncm_rx_fixup(Adapter,pRCB); } if(NdisInterlockedDecrement(&pRCB->Ref) == 0) { if(FALSE==datagramsover) { pRCB->Ref=1; goto ncmdivi; } NICFreeRCB(pRCB); } return STATUS_MORE_PROCESSING_REQUIRED; }
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; }
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"); }