/* * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * * File: int.c * * Purpose: Handle USB interrupt endpoint * * Author: Jerry Chen * * Date: Apr. 2, 2004 * * Functions: * * Revision History: * 04-02-2004 Jerry Chen: Initial release * */ #include "int.h" #include "tmacro.h" #include "mac.h" #include "power.h" #include "bssdb.h" #include "usbpipe.h" static int msglevel = MSG_LEVEL_INFO; /* MSG_LEVEL_DEBUG */ /*+ * * Function: InterruptPollingThread * * Synopsis: Thread running at IRQL PASSIVE_LEVEL. * * Arguments: Device Extension * * Returns: * * Algorithm: Call USBD for input data; * * History: dd-mm-yyyy Author Comment * * * Notes: * * USB reads are by nature 'Blocking', and when in a read, the device looks * like it's in a 'stall' condition, so we deliberately time out every second * if we've gotten no data * -*/ void INTvWorkItem(struct vnt_private *pDevice) { unsigned long flags; int ntStatus; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Interrupt Polling Thread\n"); spin_lock_irqsave(&pDevice->lock, flags); ntStatus = PIPEnsInterruptRead(pDevice); spin_unlock_irqrestore(&pDevice->lock, flags); } void INTnsProcessData(struct vnt_private *priv) { struct vnt_interrupt_data *int_data; struct vnt_manager *mgmt = &priv->vnt_mgmt; struct net_device_stats *stats = &priv->stats; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsInterruptProcessData\n"); int_data = (struct vnt_interrupt_data *)priv->int_buf.data_buf; if (int_data->tsr0 & TSR_VALID) { if (int_data->tsr0 & (TSR_TMO | TSR_RETRYTMO)) priv->wstats.discard.retries++; else stats->tx_packets++; BSSvUpdateNodeTxCounter(priv, int_data->tsr0, int_data->pkt0); } if (int_data->tsr1 & TSR_VALID) { if (int_data->tsr1 & (TSR_TMO | TSR_RETRYTMO)) priv->wstats.discard.retries++; else stats->tx_packets++; BSSvUpdateNodeTxCounter(priv, int_data->tsr1, int_data->pkt1); } if (int_data->tsr2 & TSR_VALID) { if (int_data->tsr2 & (TSR_TMO | TSR_RETRYTMO)) priv->wstats.discard.retries++; else stats->tx_packets++; BSSvUpdateNodeTxCounter(priv, int_data->tsr2, int_data->pkt2); } if (int_data->tsr3 & TSR_VALID) { if (int_data->tsr3 & (TSR_TMO | TSR_RETRYTMO)) priv->wstats.discard.retries++; else stats->tx_packets++; BSSvUpdateNodeTxCounter(priv, int_data->tsr3, int_data->pkt3); } if (int_data->isr0 != 0) { if (int_data->isr0 & ISR_BNTX) { if (priv->op_mode == NL80211_IFTYPE_AP) { if (mgmt->byDTIMCount > 0) { mgmt->byDTIMCount--; mgmt->sNodeDBTable[0].bRxPSPoll = false; } else if (mgmt->byDTIMCount == 0) { /* check if multicast tx buffering */ mgmt->byDTIMCount = mgmt->byDTIMPeriod-1; mgmt->sNodeDBTable[0].bRxPSPoll = true; if (mgmt->sNodeDBTable[0].bPSEnable) bScheduleCommand((void *) priv, WLAN_CMD_RX_PSPOLL, NULL); } bScheduleCommand((void *) priv, WLAN_CMD_BECON_SEND, NULL); } priv->bBeaconSent = true; } else { priv->bBeaconSent = false; } if (int_data->isr0 & ISR_TBTT) { if (priv->bEnablePSMode) bScheduleCommand((void *) priv, WLAN_CMD_TBTT_WAKEUP, NULL); if (priv->bChannelSwitch) { priv->byChannelSwitchCount--; if (priv->byChannelSwitchCount == 0) bScheduleCommand((void *) priv, WLAN_CMD_11H_CHSW, NULL); } } priv->qwCurrTSF = le64_to_cpu(int_data->tsf); } if (int_data->isr1 != 0) if (int_data->isr1 & ISR_GPIO3) bScheduleCommand((void *) priv, WLAN_CMD_RADIO, NULL); priv->int_buf.in_use = false; stats->tx_errors = priv->wstats.discard.retries; stats->tx_dropped = priv->wstats.discard.retries; }