⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtmp_main.c

📁 经过修改的在uClinux2.6上正常运行的ralink rt2571芯片组的设备驱动程序.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 ***************************************************************************
 * Ralink Tech Inc.
 * 4F, No. 2 Technology 5th Rd.
 * Science-based Industrial Park
 * Hsin-chu, Taiwan, R.O.C.
 *
 * (c) Copyright 2002-2006, Ralink Technology, Inc.
 *
 * 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.,                                       * 
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             * 
 *                                                                       * 
 ************************************************************************

    Module Name:
    rtmp_main.c

    Abstract:
    main initialization routines

    Revision History:
    Who         When            What
    --------    ----------      ----------------------------------------------
    Name        Date            Modification logs
    Jan Lee		01-10-2005	    modified
*/

#include "rt_config.h"

ULONG	RTDebugLevel = RT_DEBUG_TRACE;


// Following information will be show when you run 'modinfo'
// *** If you have a solution for the bug in current version of driver, please mail to me.
// Otherwise post to forum in ralinktech's web site(www.ralinktech.com) and let all users help you. ***
MODULE_AUTHOR("Paul Lin <paul_lin@ralinktech.com>");
MODULE_DESCRIPTION("RT73 Wireless Lan Linux Driver");

// *** open source release
MODULE_LICENSE("GPL");

/* Kernel thread and vars, which handles packets that are completed. Only
 * packets that have a "complete" function are sent here. This way, the
 * completion is run out of kernel context, and doesn't block the rest of
 * the stack. */
static int mlme_kill;
static int RTUSBCmd_kill;

extern	const struct iw_handler_def rt73_iw_handler_def;


/* module table */
struct usb_device_id    rtusb_usb_id[] = RT73_USB_DEVICES;
INT const               rtusb_usb_id_len = sizeof(rtusb_usb_id) / sizeof(struct usb_device_id);   
MODULE_DEVICE_TABLE(usb, rtusb_usb_id);


#ifndef PF_NOFREEZE
#define PF_NOFREEZE  0
#endif


/**************************************************************************/
/**************************************************************************/
//tested for kernel 2.4 series
/**************************************************************************/
/**************************************************************************/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)


static void usb_rtusb_disconnect(struct usb_device *dev, void *ptr);
static void *usb_rtusb_probe(struct usb_device *dev, UINT interface,
				const struct usb_device_id *id_table);

struct usb_driver rtusb_driver = {
		name:"rt73",
		probe:usb_rtusb_probe,
		disconnect:usb_rtusb_disconnect,
		id_table:rtusb_usb_id,
	};
#else
/**************************************************************************/
/**************************************************************************/
//tested for kernel 2.6series
/**************************************************************************/
/**************************************************************************/
static int usb_rtusb_probe (struct usb_interface *intf,
					  const struct usb_device_id *id);

static void usb_rtusb_disconnect(struct usb_interface *intf);

struct usb_driver rtusb_driver = {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
	.owner = THIS_MODULE,
#endif
	.name="rt73",
	.probe=usb_rtusb_probe,
	.disconnect=usb_rtusb_disconnect,
	.id_table=rtusb_usb_id,
	};


#endif


struct net_device_stats *rt73_get_ether_stats(
    IN  struct net_device *net_dev)
{
	PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) net_dev->priv;

	DBGPRINT(RT_DEBUG_INFO, "rt73_get_ether_stats --->\n");

	pAd->stats.rx_packets = pAd->WlanCounters.ReceivedFragmentCount.vv.LowPart;        // total packets received
	pAd->stats.tx_packets = pAd->WlanCounters.TransmittedFragmentCount.vv.LowPart;     // total packets transmitted

	pAd->stats.rx_bytes= pAd->RalinkCounters.ReceivedByteCount;             // total bytes received
	pAd->stats.tx_bytes = pAd->RalinkCounters.TransmittedByteCount;         // total bytes transmitted

	pAd->stats.rx_errors = pAd->Counters8023.RxErrors;                      // bad packets received
	pAd->stats.tx_errors = pAd->Counters8023.TxErrors;                      // packet transmit problems

	pAd->stats.rx_dropped = pAd->Counters8023.RxNoBuffer;                   // no space in linux buffers
	pAd->stats.tx_dropped = pAd->WlanCounters.FailedCount.vv.LowPart;                  // no space available in linux

	pAd->stats.multicast = pAd->WlanCounters.MulticastReceivedFrameCount.vv.LowPart;   // multicast packets received
	pAd->stats.collisions = pAd->Counters8023.OneCollision + pAd->Counters8023.MoreCollisions;  // Collision packets

	pAd->stats.rx_length_errors = 0;
	pAd->stats.rx_over_errors = pAd->Counters8023.RxNoBuffer;               // receiver ring buff overflow
	pAd->stats.rx_crc_errors = 0;//pAd->WlanCounters.FCSErrorCount;         // recved pkt with crc error
	pAd->stats.rx_frame_errors = pAd->Counters8023.RcvAlignmentErrors;      // recv'd frame alignment error
	pAd->stats.rx_fifo_errors = pAd->Counters8023.RxNoBuffer;               // recv'r fifo overrun
	pAd->stats.rx_missed_errors = 0;                                        // receiver missed packet

	// detailed tx_errors
	pAd->stats.tx_aborted_errors = 0;
	pAd->stats.tx_carrier_errors = 0;
	pAd->stats.tx_fifo_errors = 0;
	pAd->stats.tx_heartbeat_errors = 0;
	pAd->stats.tx_window_errors = 0;

	// for cslip etc
	pAd->stats.rx_compressed = 0;
	pAd->stats.tx_compressed = 0;
   
	return &pAd->stats;
}

#if WIRELESS_EXT >= 12
/*
	========================================================================

	Routine Description:
		get wireless statistics

	Arguments:
		net_dev                     Pointer to net_device

	Return Value:
		struct iw_statistics

	Note:
		This function will be called when query /proc

	========================================================================
*/
long rt_abs(long arg)	{	return (arg<0)? -arg : arg;}
struct iw_statistics *rt73_get_wireless_stats(
	IN  struct net_device *net_dev)
{
	PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) net_dev->priv;

	DBGPRINT(RT_DEBUG_TRACE, "rt73_get_wireless_stats --->\n");

	// TODO: All elements are zero before be implemented

	pAd->iw_stats.status = 0;   // Status - device dependent for now

    pAd->iw_stats.qual.qual = pAd->Mlme.ChannelQuality; // link quality (%retries, SNR, %missed beacons or better...)
#ifdef RTMP_EMBEDDED
    pAd->iw_stats.qual.level = rt_abs(pAd->PortCfg.LastRssi);   // signal level (dBm)
#else
    pAd->iw_stats.qual.level = abs(pAd->PortCfg.LastRssi);      // signal level (dBm)
#endif
	pAd->iw_stats.qual.level += 256 - pAd->BbpRssiToDbmDelta;

    pAd->iw_stats.qual.noise = (pAd->BbpWriteLatch[17] > pAd->BbpTuning.R17UpperBoundG) ? pAd->BbpTuning.R17UpperBoundG : ((ULONG) pAd->BbpWriteLatch[17]); // noise level (dBm)
    pAd->iw_stats.qual.noise += 256 - 143;
	pAd->iw_stats.qual.updated = 1;     // Flags to know if updated

	pAd->iw_stats.discard.nwid = 0;     // Rx : Wrong nwid/essid
	pAd->iw_stats.miss.beacon = 0;      // Missed beacons/superframe

	// pAd->iw_stats.discard.code, discard.fragment, discard.retries, discard.misc has counted in other place

	return &pAd->iw_stats;
}
#endif

VOID RTUSBHalt(
	IN	PRTMP_ADAPTER	pAd, 
	IN  BOOLEAN         IsFree)
{
	MLME_DISASSOC_REQ_STRUCT DisReq;
	MLME_QUEUE_ELEM          MsgElem;
	INT                      i;
	
	DBGPRINT(RT_DEBUG_TRACE, "====> RTUSBHalt\n");

	//
	// before set flag fRTMP_ADAPTER_HALT_IN_PROGRESS, 
	// we should send a disassoc frame to our AP.
	//
	if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
	{
		if (INFRA_ON(pAd)) 
		{
			COPY_MAC_ADDR(DisReq.Addr, pAd->PortCfg.Bssid);
			DisReq.Reason =  REASON_DISASSOC_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));

			MlmeDisassocReqAction(pAd, &MsgElem);
			RTMPusecDelay(1000);
		}

        //
		// Patch to fully turn off BBP, need to send a fake NULL frame.
		//
		RTUSBWriteMACRegister(pAd, MAC_CSR10, 0x0018);
		for (i=0; i<10; i++)
		{
			RTMPSendNullFrame(pAd, RATE_6);
			RTMPusecDelay(1000);
		}
	
		// disable BEACON generation and other BEACON related hardware timers
		AsicDisableSync(pAd);
		RTMPSetLED(pAd, LED_HALT);

	}

	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);

	RTUSBCleanUpMLMEWaitQueue(pAd);
	RTUSBCleanUpMLMEBulkOutQueue(pAd);

    RTMPCancelTimer(&pAd->PortCfg.QuickResponeForRateUpTimer);
	RTMPCancelTimer(&pAd->RxAnt.RxAntDiversityTimer);

	// Free MLME stuff
	MlmeHalt(pAd);

    // Sleep 50 milliseconds so pending io might finish normally
	RTMPusecDelay(50000);

	// We want to wait until all pending receives and sends to the
	// device object. We cancel any
	// irps. Wait until sends and receives have stopped.
	//
	RTUSBCancelPendingIRPs(pAd);

    // Free the entire adapter object
	ReleaseAdapter(pAd, IsFree, FALSE);
  	
	// reset mlme & command thread
    pAd->MLMEThr_pid = -1;
	pAd->RTUSBCmdThr_pid = -1;
	
	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
}

VOID CMDHandler(
    IN PRTMP_ADAPTER pAd) 
{
	PCmdQElmt	cmdqelmt;
	PUCHAR	    pData;
	NDIS_STATUS	NdisStatus = NDIS_STATUS_SUCCESS;
    ULONG       IrqFlags;
    ULONG       Now;
    
	while (pAd->CmdQ.size > 0)
	{
		NdisStatus = NDIS_STATUS_SUCCESS;
		NdisAcquireSpinLock(&pAd->CmdQLock, IrqFlags);
		RTUSBDequeueCmd(&pAd->CmdQ, &cmdqelmt);
		NdisReleaseSpinLock(&pAd->CmdQLock, IrqFlags);
		if (cmdqelmt == NULL)
			break;
		pData = cmdqelmt->buffer;

        //DBGPRINT_RAW(RT_DEBUG_INFO, "Cmd = %x\n", cmdqelmt->command);
		switch (cmdqelmt->command)
		{
			case RT_OID_CHECK_GPIO:
			{
				ULONG data;
				// Read GPIO pin7 as Hardware controlled radio state
				RTUSBReadMACRegister(pAd, MAC_CSR13, &data);
				if (data & 0x80)
				{
					pAd->PortCfg.bHwRadio = TRUE;
				}
				else
				{
					pAd->PortCfg.bHwRadio = FALSE;
				}
				if (pAd->PortCfg.bRadio != (pAd->PortCfg.bHwRadio && pAd->PortCfg.bSwRadio))
				{
					pAd->PortCfg.bRadio = (pAd->PortCfg.bHwRadio && pAd->PortCfg.bSwRadio);
					if (pAd->PortCfg.bRadio == TRUE)
					{
						MlmeRadioOn(pAd);
						// Update extra information
						pAd->ExtraInfo = EXTRA_INFO_CLEAR;
					}
					else
					{
						MlmeRadioOff(pAd);
						// Update extra information
						pAd->ExtraInfo = HW_RADIO_OFF;
					}
				}		
			}
			break;

			case RT_OID_PERIODIC_EXECUT:
			    //STAMlmePeriodicExec(pAd);
			break;

			case OID_802_11_BSSID_LIST_SCAN:
			{
				if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)
				{
					MlmeEnqueue(pAd, 
					            MLME_CNTL_STATE_MACHINE,
					            RT_CMD_RESET_MLME,
					            0,
					            NULL);	

				}

				Now = jiffies;
				pAd->MlmeAux.CurrReqIsFromNdis = FALSE;
				// Reset Missed scan number
				pAd->PortCfg.ScanCnt = 0;
				pAd->PortCfg.LastScanTime = Now;
				MlmeEnqueue(pAd,
							MLME_CNTL_STATE_MACHINE,
							OID_802_11_BSSID_LIST_SCAN,
							0,
							NULL);
				RTUSBMlmeUp(pAd);
			}
			break;
			
			case RT_OID_802_11_BSSID:
			{

				if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)
				{
					MlmeEnqueue(pAd, 
					            MLME_CNTL_STATE_MACHINE,
					            RT_CMD_RESET_MLME,
					            0,
					            NULL);	

				}

				pAd->MlmeAux.CurrReqIsFromNdis = FALSE;

				// Reset allowed scan retries
				pAd->PortCfg.ScanCnt = 0;

				MlmeEnqueue(pAd,
							MLME_CNTL_STATE_MACHINE,
							OID_802_11_BSSID,
							cmdqelmt->bufferlength,
							cmdqelmt->buffer);
				RTUSBMlmeUp(pAd);
			}
			break;
			
			case OID_802_11_SSID:
			{
				if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)
				{				
					MlmeEnqueue(pAd, 
					            MLME_CNTL_STATE_MACHINE,
					            RT_CMD_RESET_MLME,
					            0,
					            NULL);	

				}

				pAd->MlmeAux.CurrReqIsFromNdis = FALSE;

				// Reset allowed scan retries
				pAd->PortCfg.ScanCnt = 0;
				pAd->bConfigChanged = TRUE;

				MlmeEnqueue(pAd,
							MLME_CNTL_STATE_MACHINE,
							OID_802_11_SSID,
							cmdqelmt->bufferlength, 
							pData);
				RTUSBMlmeUp(pAd);
			}
			break;

			case OID_802_11_DISASSOCIATE:
			{
				if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)
				{
					MlmeEnqueue(pAd, 
					            MLME_CNTL_STATE_MACHINE,
					            RT_CMD_RESET_MLME,
					            0,
					            NULL);	

				}

				// Set to immediately send the media disconnect event
				pAd->MlmeAux.CurrReqIsFromNdis = TRUE;

				MlmeEnqueue(pAd,
							MLME_CNTL_STATE_MACHINE,
							OID_802_11_DISASSOCIATE,
							0,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -