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

📄 prism2_plx.c

📁 uClinux2.6上兼容PRISM2.0芯片组的USB设备驱动程序.
💻 C
字号:
#define WLAN_HOSTIF WLAN_PLX#include "hfa384x.c"#include "prism2mgmt.c"#include "prism2mib.c"#include "prism2sta.c"#define PLX_ATTR_SIZE	0x1000	/* Attribute memory size - 4K bytes */#define COR_OFFSET	0x3e0	/* COR attribute offset of Prism2 PC card */#define COR_VALUE	0x41	/* Enable PC card with irq in level trigger */#define PLX_INTCSR	0x4c	/* Interrupt Control and Status Register */#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */#define PLX_MIN_ATTR_LEN 512    /* at least 2 x 256 is needed for CIS *//* 3Com 3CRW777A (PLX) board ID */#define PCIVENDOR_3COM       0x10B7#define PCIDEVICE_AIRCONNECT 0x7770/* Eumitcom PCI WL11000 PCI Adapter (PLX) board device+vendor ID */#define PCIVENDOR_EUMITCOM	0x1638UL#define PCIDEVICE_WL11000	0x1100UL/* Global Sun Tech GL24110P PCI Adapter (PLX) board device+vendor ID */#define PCIVENDOR_GLOBALSUN	0x16abUL#define PCIDEVICE_GL24110P	0x1101UL#define PCIDEVICE_GL24110P_ALT	0x1102UL/* Netgear MA301 PCI Adapter (PLX) board device+vendor ID */#define PCIVENDOR_NETGEAR	0x1385UL#define PCIDEVICE_MA301		0x4100UL/* US Robotics USR2410 PCI Adapter (PLX) board device+vendor ID */#define	PCIVENDOR_USROBOTICS    0x16ecUL#define PCIDEVICE_USR2410       0x3685UL/* Linksys WPC11 card with the WDT11 adapter (PLX) board device+vendor ID */#define	PCIVENDOR_Linksys       0x16abUL#define PCIDEVICE_Wpc11Wdt11    0x1102UL/* National Datacomm Corp SOHOware Netblaster II PCI */#define PCIVENDOR_NDC	        0x15e8UL#define PCIDEVICE_NCP130_PLX 	0x0130UL#define PCIDEVICE_NCP130_ASIC	0x0131UL/* NDC NCP130_PLX is also sold by Corega. Their name is CGWLPCIA11 */#define PCIVENDOR_COREGA       PCIVENDOR_NDC#define PCIDEVICE_CGWLPCIA11   PCIDEVICE_NCP130_PLX/* PCI Class & Sub-Class code, Network-'Other controller' */#define PCI_CLASS_NETWORK_OTHERS 0x280/*----------------------------------------------------------------* prism2sta_probe_plx** Probe routine called when a PCI device w/ matching ID is found. * This PLX implementation uses the following map:*   BAR0: Unused*   BAR1: ????*   BAR2: PCMCIA attribute memory*   BAR3: PCMCIA i/o space * Here's the sequence:*   - Allocate the PCI resources.  *   - Read the PCMCIA attribute memory to make sure we have a WLAN card*   - Reset the MAC using the PCMCIA COR*   - Initialize the netdev and wlan data*   - Initialize the MAC** Arguments:*	pdev		ptr to pci device structure containing info about *			pci configuration.*	id		ptr to the device id entry that matched this device.** Returns: *	zero		- success*	negative	- failed** Side effects:*	** Call context:*	process thread*	----------------------------------------------------------------*/static int __devinitprism2sta_probe_plx(	struct pci_dev			*pdev, 	const struct pci_device_id	*id){	int		result;        phys_t	pccard_ioaddr;	phys_t  pccard_attr_mem;        unsigned int    pccard_attr_len;	UINT8 *attr_mem = NULL;	UINT32		plx_addr;         wlandevice_t    *wlandev = NULL;	hfa384x_t	*hw = NULL;	int		reg;        u32		regic;	if (pci_enable_device(pdev))		return -EIO;	/* TMC7160 boards are special */	if ((pdev->vendor == PCIVENDOR_NDC) && 	    (pdev->device == PCIDEVICE_NCP130_ASIC)) {		unsigned long delay;		pccard_attr_mem = 0;		pccard_ioaddr = pci_resource_start(pdev, 1);		outb(0x45, pccard_ioaddr);		delay = jiffies + 1*HZ;		while (time_before(jiffies, delay));		if (inb(pccard_ioaddr) != 0x45) {			WLAN_LOG_ERROR("Initialize the TMC7160 failed. (0x%x)\n", inb(pccard_ioaddr));			return -EIO;		}				pccard_ioaddr = pci_resource_start(pdev, 2);		prism2_doreset = 0;		WLAN_LOG_INFO("NDC NCP130 with TMC716(ASIC) PCI interface device found at io:0x%x, irq:%d\n", pccard_ioaddr, pdev->irq);		goto init;	}	/* Collect the resource requirements */	pccard_attr_mem = pci_resource_start(pdev, 2);	pccard_attr_len = pci_resource_len(pdev, 2);        if (pccard_attr_len < PLX_MIN_ATTR_LEN)		return -EIO;	pccard_ioaddr = pci_resource_start(pdev, 3);	/* bjoern: We need to tell the card to enable interrupts, in	 * case the serial eprom didn't do this already. See the	 * PLX9052 data book, p8-1 and 8-24 for reference.	 * [MSM]: This bit of code came from the orinoco_cs driver.	 */	plx_addr = pci_resource_start(pdev, 1);	regic = 0;	regic = inl(plx_addr+PLX_INTCSR);	if(regic & PLX_INTCSR_INTEN) {		WLAN_LOG_DEBUG(1,			"%s: Local Interrupt already enabled\n", dev_info);	} else {		regic |= PLX_INTCSR_INTEN;		outl(regic, plx_addr+PLX_INTCSR);		regic = inl(plx_addr+PLX_INTCSR);		if(!(regic & PLX_INTCSR_INTEN)) {			WLAN_LOG_ERROR(				"%s: Couldn't enable Local Interrupts\n",				dev_info);			return -EIO;		}	}	/* These assignments are here in case of future mappings for	 * io space and irq that might be similar to ioremap 	 */        if (!request_mem_region(pccard_attr_mem, pci_resource_len(pdev, 2), "Prism2")) {		WLAN_LOG_ERROR("%s: Couldn't reserve PCI memory region\n", dev_info);		return -EIO;        }	attr_mem = ioremap(pccard_attr_mem, pccard_attr_len);	WLAN_LOG_INFO("A PLX PCI/PCMCIA interface device found, "		"phymem:0x%llx, phyio=0x%x, irq:%d, "		"mem: 0x%lx\n", 		(unsigned long long)pccard_attr_mem, pccard_ioaddr, pdev->irq,		(long)attr_mem);	/* Verify whether PC card is present. 	 * [MSM] This needs improvement, the right thing to do is	 * probably to walk the CIS looking for the vendor and product	 * IDs.  It would be nice if this could be tied in with the	 * etc/pcmcia/wlan-ng.conf file.  Any volunteers?  ;-)	 */	if (	attr_mem[0] != 0x01 || attr_mem[2] != 0x03 ||	attr_mem[4] != 0x00 || attr_mem[6] != 0x00 ||	attr_mem[8] != 0xFF || attr_mem[10] != 0x17 ||	attr_mem[12] != 0x04 || attr_mem[14] != 0x67) {		WLAN_LOG_ERROR("Prism2 PC card CIS is invalid.\n");		return -EIO;        }        WLAN_LOG_INFO("A PCMCIA WLAN adapter was found.\n");        /* Write COR to enable PC card */	attr_mem[COR_OFFSET] = COR_VALUE; reg = attr_mem[COR_OFFSET];	 init:	/*	 * Now do everything the same as a PCI device	 * [MSM] TODO: We could probably factor this out of pcmcia/pci/plx	 * and perhaps usb.  Perhaps a task for another day.......	 */	if ((wlandev = create_wlan()) == NULL) {		WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);		result = -EIO;		goto failed;	}	hw = wlandev->priv;	if ( wlan_setup(wlandev) != 0 ) {		WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info);		result = -EIO;		goto failed;	}	/* Setup netdevice's ability to report resources 	 * Note: the netdevice was allocated by wlan_setup()	 */        wlandev->netdev->irq = pdev->irq;        wlandev->netdev->base_addr = pccard_ioaddr;        wlandev->netdev->mem_start = (unsigned long)attr_mem;        wlandev->netdev->mem_end = (unsigned long)attr_mem + pci_resource_len(pdev, 0);	/* Initialize the hw data */        hfa384x_create(hw, wlandev->netdev->irq, pccard_ioaddr, attr_mem);	hw->wlandev = wlandev;	/* Register the wlandev, this gets us a name and registers the	 * linux netdevice.	 */	SET_MODULE_OWNER(wlandev->netdev);#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))       SET_NETDEV_DEV(wlandev->netdev, &(pdev->dev));#endif        if ( register_wlandev(wlandev) != 0 ) {		WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info);		result = -EIO;		goto failed;        }#if 0	/* TODO: Move this and an irq test into an hfa384x_testif() routine.	 */	outw(PRISM2STA_MAGIC, HFA384x_SWSUPPORT(wlandev->netdev->base_addr));	reg=inw( HFA384x_SWSUPPORT(wlandev->netdev->base_addr));	if ( reg != PRISM2STA_MAGIC ) {		WLAN_LOG_ERROR("MAC register access test failed!\n"); 		result = -EIO;		goto failed;	}		#endif	/* Do a chip-level reset on the MAC */	if (prism2_doreset) {		result = hfa384x_corereset(hw, 				prism2_reset_holdtime, 				prism2_reset_settletime, 0);		if (result != 0) {			unregister_wlandev(wlandev);			hfa384x_destroy(hw);			WLAN_LOG_ERROR(				"%s: hfa384x_corereset() failed.\n", 				dev_info);			result = -EIO;			goto failed;		}	}	pci_set_drvdata(pdev, wlandev);	/* Shouldn't actually hook up the IRQ until we 	 * _know_ things are alright.  A test routine would help.	 */       	request_irq(wlandev->netdev->irq, hfa384x_interrupt, 		SA_SHIRQ, wlandev->name, wlandev);	wlandev->msdstate = WLAN_MSD_HWPRESENT;	result = 0;	goto done;	 failed:	pci_set_drvdata(pdev, NULL);	if (wlandev)	kfree(wlandev);	if (hw)		kfree(hw);        if (attr_mem)        iounmap((void *) attr_mem);	pci_release_regions(pdev);        pci_disable_device(pdev); done:	DBFEXIT;        return result;}static void __devexit prism2sta_remove_plx(struct pci_dev *pdev){       	wlandevice_t		*wlandev;	hfa384x_t               *hw;	wlandev = (wlandevice_t *) pci_get_drvdata(pdev);	hw = wlandev->priv;	p80211netdev_hwremoved(wlandev);	/* reset hardware */	prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);        if (pdev->irq)		free_irq(pdev->irq, wlandev);	unregister_wlandev(wlandev);	/* free local stuff */	if (hw) {		hfa384x_destroy(hw);		kfree(hw);	}	iounmap((void*)wlandev->netdev->mem_start);	wlan_unsetup(wlandev);	pci_release_regions(pdev);        pci_disable_device(pdev);	pci_set_drvdata(pdev, NULL);	kfree(wlandev);}static struct pci_device_id plx_id_tbl[] = {	{		PCIVENDOR_EUMITCOM, PCIDEVICE_WL11000,		PCI_ANY_ID, PCI_ANY_ID,		0, 0,		/* Driver data, we just put the name here */		(unsigned long)"Eumitcom WL11000 PCI(PLX) card"		},	{		PCIVENDOR_GLOBALSUN, PCIDEVICE_GL24110P,		PCI_ANY_ID, PCI_ANY_ID,		0, 0, 		/* Driver data, we just put the name here */		(unsigned long)"Global Sun Tech GL24110P PCI(PLX) card"	},	{		PCIVENDOR_GLOBALSUN, PCIDEVICE_GL24110P_ALT,		PCI_ANY_ID, PCI_ANY_ID,		0, 0, 		/* Driver data, we just put the name here */		(unsigned long)"Global Sun Tech GL24110P PCI(PLX) card"	},	{		PCIVENDOR_NETGEAR, PCIDEVICE_MA301,		PCI_ANY_ID, PCI_ANY_ID,		0, 0, 		/* Driver data, we just put the name here */		(unsigned long)"Global Sun Tech GL24110P PCI(PLX) card"	},	{		PCIVENDOR_USROBOTICS, PCIDEVICE_USR2410,		PCI_ANY_ID, PCI_ANY_ID,		0, 0,		/* Driver data, we just put the name here */		(unsigned long)"US Robotics USR2410 PCI(PLX) card"		},	{		PCIVENDOR_Linksys, PCIDEVICE_Wpc11Wdt11,		PCI_ANY_ID, PCI_ANY_ID,		0, 0,		/* Driver data, we just put the name here */		(unsigned long)"Linksys WPC11 with WDT11 PCI(PLX) adapter"		},	{	        PCIVENDOR_NDC, PCIDEVICE_NCP130_PLX,		PCI_ANY_ID, PCI_ANY_ID,		0, 0, 		/* Driver data, we just put the name here */		(unsigned long)"NDC Netblaster II PCI(PLX)"	},	{	        PCIVENDOR_NDC, PCIDEVICE_NCP130_ASIC,		PCI_ANY_ID, PCI_ANY_ID,		0, 0, 		/* Driver data, we just put the name here */		(unsigned long)"NDC Netblaster II PCI(TMC7160)"	},	{		PCIVENDOR_3COM, PCIDEVICE_AIRCONNECT,			PCI_ANY_ID, PCI_ANY_ID,		0, 0, 		/* Driver data, we just put the name here */		(unsigned long)"3Com AirConnect PCI 802.11b 11Mb/s WLAN Controller"	},	{		0, 0, 0, 0, 0, 0, 0	}};MODULE_DEVICE_TABLE(pci, plx_id_tbl);/* Function declared here because of ptr reference below */static int __devinit prism2sta_probe_plx(struct pci_dev *pdev, 					 const struct pci_device_id *);static void __devexit prism2sta_remove_plx(struct pci_dev *pdev);struct pci_driver prism2_plx_drv_id = {        .name = "prism2_plx",        .id_table = plx_id_tbl,        .probe = prism2sta_probe_plx,        .remove = prism2sta_remove_plx,#ifdef CONFIG_PM        .suspend = prism2sta_suspend_pci,        .resume = prism2sta_resume_pci,#endif};#ifdef MODULEstatic int __init prism2plx_init(void){        WLAN_LOG_NOTICE("%s Loaded\n", version);	return pci_module_init(&prism2_plx_drv_id);};static void __exit prism2plx_cleanup(void){	pci_unregister_driver(&prism2_plx_drv_id);};module_init(prism2plx_init);module_exit(prism2plx_cleanup);#endif // MODULEint hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis){	int		result = 0;#define COR_OFFSET	0x3e0	/* COR attribute offset of Prism2 PC card */#define COR_VALUE	0x41	/* Enable PC card with irq in level trigger */#define HCR_OFFSET	0x3e2	/* HCR attribute offset of Prism2 PC card */	UINT8		corsave;	DBFENTER;	WLAN_LOG_DEBUG(3, "Doing reset via direct COR access.\n");	/* Collect COR */	corsave = ((UINT8*)hw->membase)[COR_OFFSET];	/* Write reset bit (BIT7) */	((UINT8*)hw->membase)[COR_OFFSET] = corsave | BIT7;	/* Hold for holdtime */	mdelay(holdtime);	if (genesis) {		((UINT8*)hw->membase)[HCR_OFFSET] = genesis; 		/* Hold for holdtime */		mdelay(holdtime);	}	/* Clear reset bit */	((UINT8*)hw->membase)[COR_OFFSET] = corsave & ~BIT7;	/* Wait for settletime */	mdelay(settletime);	/* Set non-reset bits back what they were */	((UINT8*)hw->membase)[COR_OFFSET] = corsave;	DBFEXIT;	return result;}

⌨️ 快捷键说明

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