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;
}
Exemple #4
0
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;
	 }
 }
Exemple #6
0
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;
}
Exemple #7
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;
}
Exemple #8
0
/**
 * 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);
}
Exemple #9
0
/**
 * 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;
}
Exemple #10
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;
    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;
}
Exemple #12
0
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;
}
Exemple #13
0
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);
}
Exemple #17
0
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;

}
Exemple #18
0
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");
}