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

📄 phy.c

📁 Airgo agn1000系列 无线网卡驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * Airgo MIMO wireless driver * * Copyright (c) 2007-2008 Li YanBo <dreamfly281@gmail.com> * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer  * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin  * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as  * published by the Free Software Foundation. */#include <linux/init.h>#include <linux/etherdevice.h>#include <linux/pci.h>#include <linux/delay.h>#include "agnx.h"#include "debug.h"#include "phy.h"#include "table.h"#include "sta.h"#include "xmit.h"u8 read_from_eeprom(struct agnx_priv *priv, u16 address){	void __iomem *ctl = priv->ctl;	struct agnx_eeprom cmd;	u32 reg;	memset(&cmd, 0, sizeof(cmd)); 	cmd.cmd = EEPROM_CMD_READ << AGNX_EEPROM_COMMAND_SHIFT;	cmd.address = address;	/* Verify that the Status bit is clear */	/* Read Command and Address are written to the Serial Interface */	iowrite32(*(__le32 *)&cmd, ctl + AGNX_CIR_SERIALITF);	/* Wait for the Status bit to clear again */	eeprom_delay();	/* Read from Data */	reg = ioread32(ctl + AGNX_CIR_SERIALITF);	cmd = *(struct agnx_eeprom *)&reg;	return cmd.data;}static int card_full_reset(struct agnx_priv *priv){	void __iomem *ctl = priv->ctl;	u32 reg;	AGNX_TRACE;	reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);	agnx_write32(ctl, AGNX_CIR_BLKCTL, 0x80);	reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);	return 0;}inline void enable_power_saving(struct agnx_priv *priv){	void __iomem *ctl = priv->ctl;	u32 reg;	reg = agnx_read32(ctl, AGNX_PM_PMCTL);	reg &= ~0x8;	agnx_write32(ctl, AGNX_PM_PMCTL, reg);}inline void disable_power_saving(struct agnx_priv *priv){	void __iomem *ctl = priv->ctl;	u32 reg;	reg = agnx_read32(ctl, AGNX_PM_PMCTL);	reg |= 0x8;	agnx_write32(ctl, AGNX_PM_PMCTL, reg);}void disable_receiver(struct agnx_priv *priv){	void __iomem *ctl = priv->ctl;	AGNX_TRACE;	/* FIXME Disable the receiver */	agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x0);	/* Set gain control reset */	agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);	/* Reset gain control reset */	agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);}/* Fixme this shoule be disable RX, above is enable RX */void enable_receiver(struct agnx_priv *priv){	void __iomem *ctl = priv->ctl;	AGNX_TRACE;	/* Set adaptive gain control discovery mode */	agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);	/* Set gain control reset */	agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);	/* Clear gain control reset */	agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);}static void mac_address_set(struct agnx_priv *priv){	void __iomem *ctl = priv->ctl;	u8 *mac_addr = priv->mac_addr;	u32 reg;	/* FIXME */	reg = (mac_addr[0] << 24) | (mac_addr[1] << 16) | mac_addr[2] << 8 | mac_addr[3];	iowrite32(reg, ctl + AGNX_RXM_MACHI); 	reg = (mac_addr[4] << 8) | mac_addr[5];	iowrite32(reg, ctl + AGNX_RXM_MACLO);}static void receiver_bssid_set(struct agnx_priv *priv, u8 *bssid){	void __iomem *ctl = priv->ctl;	u32 reg;	disable_receiver(priv);	/* FIXME */	reg = bssid[0] << 24 | (bssid[1] << 16) | (bssid[2] << 8) | bssid[3];	iowrite32(reg, ctl + AGNX_RXM_BSSIDHI); 	reg = (bssid[4] << 8) | bssid[5];	iowrite32(reg, ctl + AGNX_RXM_BSSIDLO);	/* Enable the receiver */	enable_receiver(priv);	/* Clear the TSF *//* 	agnx_write32(ctl, AGNX_TXM_TSFLO, 0x0); *//* 	agnx_write32(ctl, AGNX_TXM_TSFHI, 0x0); */	/* Clear the TBTT */	agnx_write32(ctl, AGNX_TXM_TBTTLO, 0x0);	agnx_write32(ctl, AGNX_TXM_TBTTHI, 0x0);	disable_receiver(priv);} /* receiver_bssid_set */static void band_management_init(struct agnx_priv *priv){	void __iomem *ctl = priv->ctl;	void __iomem *data = priv->data;	u32 reg;	int i;	AGNX_TRACE;	agnx_write32(ctl, AGNX_BM_TXWADDR, AGNX_PDU_TX_WQ);	agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x0);	memset_io(data + AGNX_PDUPOOL, 0x0, AGNX_PDUPOOL_SIZE);	agnx_write32(ctl, AGNX_BM_BMCTL, 0x200);	agnx_write32(ctl, AGNX_BM_CIPDUWCNT, 0x40);	agnx_write32(ctl, AGNX_BM_SPPDUWCNT, 0x2);	agnx_write32(ctl, AGNX_BM_RFPPDUWCNT, 0x0);	agnx_write32(ctl, AGNX_BM_RHPPDUWCNT, 0x22);	/* FIXME Initialize the Free Pool Linked List */	/*    1. Write the Address of the Next Node ((0x41800 + node*size)/size) 	      to the first word of each node.  */	for (i = 0; i < PDU_FREE_CNT; i++) {		iowrite32((AGNX_PDU_FREE + (i+1)*PDU_SIZE)/PDU_SIZE, 			  data + AGNX_PDU_FREE + (PDU_SIZE * i));		/* The last node should be set to 0x0 */		if ((i + 1) == PDU_FREE_CNT)			memset_io(data + AGNX_PDU_FREE + (PDU_SIZE * i), 				  0x0, PDU_SIZE);	}	/* Head is First Pool address (0x41800) / size (0x80) */	agnx_write32(ctl, AGNX_BM_FPLHP, AGNX_PDU_FREE/PDU_SIZE);	/* Tail is Last Pool Address (0x47f80) / size (0x80) */	agnx_write32(ctl, AGNX_BM_FPLTP, 0x47f80/PDU_SIZE);	/* Count is Number of Nodes in the Pool (0xd0) */	agnx_write32(ctl, AGNX_BM_FPCNT, PDU_FREE_CNT);	/* Start all workqueue */	agnx_write32(ctl, AGNX_BM_CIWQCTL, 0x80000);	agnx_write32(ctl, AGNX_BM_CPULWCTL, 0x80000);	agnx_write32(ctl, AGNX_BM_CPUHWCTL, 0x80000);	agnx_write32(ctl, AGNX_BM_CPUTXWCTL, 0x80000);	agnx_write32(ctl, AGNX_BM_CPURXWCTL, 0x80000);	agnx_write32(ctl, AGNX_BM_SPRXWCTL, 0x80000);	agnx_write32(ctl, AGNX_BM_SPTXWCTL, 0x80000);	agnx_write32(ctl, AGNX_BM_RFPWCTL, 0x80000);	/* Enable the Band Management */	reg = agnx_read32(ctl, AGNX_BM_BMCTL);	reg |= 0x1; 	agnx_write32(ctl, AGNX_BM_BMCTL, reg);} /* band_managment_init */static void system_itf_init(struct agnx_priv *priv){	void __iomem *ctl = priv->ctl;	u32 reg;	AGNX_TRACE;	agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x0);	agnx_write32(ctl, AGNX_PM_TESTPHY, 0x11e143a);	if (priv->revid == 0) {		reg = agnx_read32(ctl, AGNX_SYSITF_SYSMODE);		reg |= 0x11;		agnx_write32(ctl, AGNX_SYSITF_SYSMODE, reg);	}	/* ??? What is that means? it should difference for differice type 	 of cards */	agnx_write32(ctl, AGNX_CIR_SERIALITF, 0xfff81006);	agnx_write32(ctl, AGNX_SYSITF_GPIOIN, 0x1f0000);	agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x5);	reg = agnx_read32(ctl, AGNX_SYSITF_GPIOIN);}static void encryption_init(struct agnx_priv *priv){	void __iomem *ctl = priv->ctl;	AGNX_TRACE;	agnx_write32(ctl, AGNX_ENCRY_WEPKEY0, 0x0);	agnx_write32(ctl, AGNX_ENCRY_WEPKEY1, 0x0);	agnx_write32(ctl, AGNX_ENCRY_WEPKEY2, 0x0);	agnx_write32(ctl, AGNX_ENCRY_WEPKEY3, 0x0);	agnx_write32(ctl, AGNX_ENCRY_CCMRECTL, 0x8);}static void tx_management_init(struct agnx_priv *priv){	void __iomem *ctl = priv->ctl;	void __iomem *data = priv->data;	u32 reg;	AGNX_TRACE;	/* Fill out the ComputationalEngineLookupTable	 * starting at memory #2 offset 0x800 	 */	tx_engine_lookup_tbl_init(priv);	memset_io(data + 0x1000, 0, 0xfe0);	/* Enable Transmission Management Functions */	agnx_write32(ctl, AGNX_TXM_ETMF, 0x3ff);	/* Write 0x3f to Transmission Template */	agnx_write32(ctl, AGNX_TXM_TXTEMP, 0x3f);	if (priv->revid >= 2) 		agnx_write32(ctl, AGNX_TXM_SIFSPIFS, 0x1e140a0b);	else 		agnx_write32(ctl, AGNX_TXM_SIFSPIFS, 0x1e190a0b);		reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);	reg &= 0xff00;	reg |= 0xb;	agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);      	reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);	reg &= 0xffff00ff;	reg |= 0xa00;	agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);	/* Enable TIFS */	agnx_write32(ctl, AGNX_TXM_CTL, 0x40000);	reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);	reg &= 0xff00ffff;	reg |= 0x510000;	agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);	reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY);	reg &= 0xff00ffff;	agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg);	reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);	reg &= 0x00ffffff;	reg |= 0x1c000000;	agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);	reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY);	reg &= 0x00ffffff;	reg |= 0x01000000;	agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg);	/* # Set DIF 0-1,2-3,4-5,6-7 to defaults */	agnx_write32(ctl, AGNX_TXM_DIF01, 0x321d321d);	agnx_write32(ctl, AGNX_TXM_DIF23, 0x321d321d);	agnx_write32(ctl, AGNX_TXM_DIF45, 0x321d321d);	agnx_write32(ctl, AGNX_TXM_DIF67, 0x321d321d);	/* Max Ack timeout limit */	agnx_write32(ctl, AGNX_TXM_MAXACKTIM, 0x1e19);	/* Max RX Data Timeout count, */	reg = agnx_read32(ctl, AGNX_TXM_MAXRXTIME);	reg &= 0xffff0000;	reg |= 0xff;	agnx_write32(ctl, AGNX_TXM_MAXRXTIME, reg);	/* CF poll RX Timeout count */	reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM);	reg &= 0xffff;	reg |= 0xff0000;	agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg);	/* Max Timeout Exceeded count, */	reg = agnx_read32(ctl, AGNX_TXM_MAXTIMOUT);	reg &= 0xff00ffff;	reg |= 0x190000;	agnx_write32(ctl, AGNX_TXM_MAXTIMOUT, reg);	/* CF ack timeout limit for 11b */	reg = agnx_read32(ctl, AGNX_TXM_CFACKT11B);	reg &= 0xff00;	reg |= 0x1e;	agnx_write32(ctl, AGNX_TXM_CFACKT11B, reg);	/* Max CF Poll Timeout Count */	reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM);	reg &= 0xffff0000;	reg |= 0x19;	agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg);	/* CF Poll RX Timeout Count */	reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM);	reg &= 0xffff0000;	reg |= 0x1e;	agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg);	/* # write default to */	/*    1. Schedule Empty Count */	agnx_write32(ctl, AGNX_TXM_SCHEMPCNT, 0x5);	/*    2. CFP Period Count */	agnx_write32(ctl, AGNX_TXM_CFPERCNT, 0x1);	/*    3. CFP MDV  */	agnx_write32(ctl, AGNX_TXM_CFPMDV, 0x10000);	/* Probe Delay */	reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY);	reg &= 0xffff0000;	reg |= 0x400;	agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg);	/* Max CCA count Slot */	reg = agnx_read32(ctl, AGNX_TXM_MAXCCACNTSLOT);	reg &= 0xffff00ff;	reg |= 0x900;	agnx_write32(ctl, AGNX_TXM_MAXCCACNTSLOT, reg);	/* Slot limit/1 msec Limit */	reg = agnx_read32(ctl, AGNX_TXM_SLOTLIMIT);	reg &= 0xff00ffff;	reg |= 0x140077;	agnx_write32(ctl, AGNX_TXM_SLOTLIMIT, reg);	/* # Set CW #(0-7) to default */	agnx_write32(ctl, AGNX_TXM_CW0, 0xff0007);	agnx_write32(ctl, AGNX_TXM_CW1, 0xff0007);	agnx_write32(ctl, AGNX_TXM_CW2, 0xff0007);	agnx_write32(ctl, AGNX_TXM_CW3, 0xff0007);	agnx_write32(ctl, AGNX_TXM_CW4, 0xff0007);	agnx_write32(ctl, AGNX_TXM_CW5, 0xff0007);	agnx_write32(ctl, AGNX_TXM_CW6, 0xff0007);	agnx_write32(ctl, AGNX_TXM_CW7, 0xff0007);	/* # Set Short/Long limit #(0-7) to default */	agnx_write32(ctl, AGNX_TXM_SLBEALIM0,  0xa000a);	agnx_write32(ctl, AGNX_TXM_SLBEALIM1,  0xa000a);	agnx_write32(ctl, AGNX_TXM_SLBEALIM2,  0xa000a);	agnx_write32(ctl, AGNX_TXM_SLBEALIM3,  0xa000a);	agnx_write32(ctl, AGNX_TXM_SLBEALIM4,  0xa000a);	agnx_write32(ctl, AGNX_TXM_SLBEALIM5,  0xa000a);	agnx_write32(ctl, AGNX_TXM_SLBEALIM6,  0xa000a);	agnx_write32(ctl, AGNX_TXM_SLBEALIM7,  0xa000a);	reg = agnx_read32(ctl, AGNX_TXM_CTL);	reg |= 0x1400;	agnx_write32(ctl, AGNX_TXM_CTL, reg);	/* Wait for bit 0 in Control Reg to clear  */	udelay(80);	reg = agnx_read32(ctl, AGNX_TXM_CTL);	/* Or 0x18000 to Control reg */	reg = agnx_read32(ctl, AGNX_TXM_CTL);	reg |= 0x18000;	agnx_write32(ctl, AGNX_TXM_CTL, reg);	/* Wait for bit 0 in Control Reg to clear */	udelay(80);	reg = agnx_read32(ctl, AGNX_TXM_CTL);	/* Set Listen Interval Count to default */	agnx_write32(ctl, AGNX_TXM_LISINTERCNT, 0x1);	/* Set DTIM period count to default */	agnx_write32(ctl, AGNX_TXM_DTIMPERICNT, 0x2000);} /* tx_management_init */static void rx_management_init(struct agnx_priv *priv){	void __iomem *ctl = priv->ctl;	AGNX_TRACE;	/* Initialize the Routing Table */	routing_table_init(priv);	if (priv->revid >= 3) {		agnx_write32(ctl, 0x2074, 0x1f171710);		agnx_write32(ctl, 0x2078, 0x10100d0d);		agnx_write32(ctl, 0x207c, 0x11111010);	}		else		agnx_write32(ctl, AGNX_RXM_DELAY11, 0x0);	agnx_write32(ctl, AGNX_RXM_REQRATE, 0x8195e00);}static void agnx_timer_init(struct agnx_priv *priv){	void __iomem *ctl = priv->ctl;	AGNX_TRACE;/* 	/\* Write 0x249f00 (tick duration?) to Timer 1 *\/ *//* 	agnx_write32(ctl, AGNX_TIMCTL_TIMER1, 0x249f00); *//* 	/\* Write 0xe2 to Timer 1 Control *\/ *//* 	agnx_write32(ctl, AGNX_TIMCTL_TIM1CTL, 0xe2); */	/* Write 0x249f00 (tick duration?) to Timer 1 */	agnx_write32(ctl, AGNX_TIMCTL_TIMER1, 0x0);	/* Write 0xe2 to Timer 1 Control */	agnx_write32(ctl, AGNX_TIMCTL_TIM1CTL, 0x0);	iowrite32(0xFFFFFFFF, priv->ctl + AGNX_TXM_BEACON_CTL);}static void power_manage_init(struct agnx_priv *priv){	void __iomem *ctl = priv->ctl;	u32 reg;	AGNX_TRACE;	agnx_write32(ctl, AGNX_PM_MACMSW, 0x1f);	agnx_write32(ctl, AGNX_PM_RFCTL, 0x1f);	reg = agnx_read32(ctl, AGNX_PM_PMCTL);	reg &= 0xf00f;	reg |= 0xa0;		agnx_write32(ctl, AGNX_PM_PMCTL, reg);	if (priv->revid >= 3) {		reg = agnx_read32(ctl, AGNX_PM_SOFTRST);		reg |= 0x18;			agnx_write32(ctl, AGNX_PM_SOFTRST, reg);	}} /* power_manage_init */static void gain_ctlcnt_init(struct agnx_priv *priv){	void __iomem *ctl = priv->ctl;	u32 reg;	AGNX_TRACE;	agnx_write32(ctl, AGNX_GCR_TRACNT5, 0x119);	agnx_write32(ctl, AGNX_GCR_TRACNT6, 0x118);	agnx_write32(ctl, AGNX_GCR_TRACNT7, 0x117);	reg = agnx_read32(ctl, AGNX_PM_PMCTL);	reg |= 0x8;	agnx_write32(ctl, AGNX_PM_PMCTL, reg);	reg = agnx_read32(ctl, AGNX_PM_PMCTL);	reg &= ~0x8;	agnx_write32(ctl, AGNX_PM_PMCTL, reg);	agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x0);	/* FIXME Write the initial Station Descriptor for the card */	sta_init(priv, LOCAL_STAID);	sta_init(priv, BSSID_STAID);	/* Enable staion 0 and 1 can do TX */	/* It seemed if we set other bit to 1 the bit 0 will 	   be auto change to 0 */	agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x2 | 0x1);//	agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x1);} /* gain_ctlcnt_init */

⌨️ 快捷键说明

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