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

📄 prism2_cs.c

📁 uClinux2.6上兼容PRISM2.0芯片组的USB设备驱动程序.
💻 C
📖 第 1 页 / 共 3 页
字号:
		*linkp = link->next;		if ( link->priv != NULL ) {			wlandev = (wlandevice_t*)link->priv;			p80211netdev_hwremoved(wlandev);			if (link->dev != NULL) {				unregister_wlandev(wlandev);			}			wlan_unsetup(wlandev);			if (wlandev->priv) {				hw = wlandev->priv;				wlandev->priv = NULL;				if (hw) {					hfa384x_destroy(hw);					kfree(hw);				}			}			link->priv = NULL;			kfree(wlandev);		}		kfree(link);	}	DBFEXIT;	return;}/*----------------------------------------------------------------* prism2sta_config** Half of the config/release pair.  Usually called in response to* a card insertion event.  At this point, we _know_ there's some* physical device present.  That means we can start poking around* at the CIS and at any device specific config data we want.** Note the gotos and the macros.  I recoded this once without* them, and it got incredibly ugly.  It's actually simpler with* them.** Arguments:*	link	the dev_link_t structure created in attach that *		represents this device instance.** Returns: *	nothing** Side effects:*	Resources (irq, io, mem) are allocated*	The pcmcia dev_link->node->name is set*	(For netcards) The device structure is finished and,*	  most importantly, registered.  This means that there*	  is now a _named_ device that can be configured from*	  userland.** Call context:*	May be called from a timer.  Don't block!----------------------------------------------------------------*/#define CS_CHECK(fn, ret) \do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)#define CFG_CHECK(fn, retf) \do { int ret = (retf); \if (ret != 0) { \        WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \        cs_error(link->handle, fn, ret); \        goto next_entry; \} \} while (0)void prism2sta_config(dev_link_t *link){	client_handle_t		handle;	wlandevice_t		*wlandev;	hfa384x_t               *hw;	int			last_fn;	int			last_ret;	tuple_t			tuple;	cisparse_t		parse;	config_info_t		socketconf;	UINT8			buf[64];	int			minVcc = 0;	int			maxVcc = 0;	cistpl_cftable_entry_t	dflt = { 0 };	DBFENTER;	handle = link->handle;	wlandev = (wlandevice_t*)link->priv;	hw = wlandev->priv;	/* Collect the config register info */	tuple.DesiredTuple = CISTPL_CONFIG;	tuple.Attributes = 0;	tuple.TupleData = buf;	tuple.TupleDataMax = sizeof(buf);	tuple.TupleOffset = 0;	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));	link->conf.ConfigBase = parse.config.base;	link->conf.Present = parse.config.rmask[0];		/* Configure card */	link->state |= DEV_CONFIG;	/* Acquire the current socket config (need Vcc setting) */	CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &socketconf));	/* Loop through the config table entries until we find one that works */	/* Assumes a complete and valid CIS */	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));	while (1) {		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);		CFG_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));		CFG_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));		if (cfg->index == 0) goto next_entry;		link->conf.ConfigIndex = cfg->index;		/* Lets print out the Vcc that the controller+pcmcia-cs set		 * for us, cause that's what we're going to use.		 */		WLAN_LOG_DEBUG(1,"Initial Vcc=%d/10v\n", socketconf.Vcc);		if (prism2_ignorevcc) {			link->conf.Vcc = socketconf.Vcc;			goto skipvcc;		}		/* Use power settings for Vcc and Vpp if present */		/* Note that the CIS values need to be rescaled */		if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {			WLAN_LOG_DEBUG(1, "Vcc obtained from curtupl.VNOM\n");			minVcc = maxVcc = 				cfg->vcc.param[CISTPL_POWER_VNOM]/10000;		} else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {			WLAN_LOG_DEBUG(1, "Vcc set from dflt.VNOM\n");			minVcc = maxVcc = 				dflt.vcc.param[CISTPL_POWER_VNOM]/10000;		} else if ((cfg->vcc.present & (1<<CISTPL_POWER_VMAX)) &&			   (cfg->vcc.present & (1<<CISTPL_POWER_VMIN)) ) {			WLAN_LOG_DEBUG(1, "Vcc set from curtupl(VMIN,VMAX)\n");			minVcc = cfg->vcc.param[CISTPL_POWER_VMIN]/10000;			maxVcc = cfg->vcc.param[CISTPL_POWER_VMAX]/10000;		} else if ((dflt.vcc.present & (1<<CISTPL_POWER_VMAX)) &&			   (dflt.vcc.present & (1<<CISTPL_POWER_VMIN)) ) {			WLAN_LOG_DEBUG(1, "Vcc set from dflt(VMIN,VMAX)\n");			minVcc = dflt.vcc.param[CISTPL_POWER_VMIN]/10000;			maxVcc = dflt.vcc.param[CISTPL_POWER_VMAX]/10000;		}		if ( socketconf.Vcc >= minVcc && socketconf.Vcc <= maxVcc) {			link->conf.Vcc = socketconf.Vcc;		} else {			/* [MSM]: Note that I've given up trying to change 			 * the Vcc if a change is indicated.  It seems the			 * system&socketcontroller&card vendors can't seem			 * to get it right, so I'm tired of trying to hack			 * my way around it.  pcmcia-cs does its best using 			 * the voltage sense pins but sometimes the controller			 * lies.  Then, even if we have a good read on the VS 			 * pins, some system designs will silently ignore our			 * requests to set the voltage.  Additionally, some 			 * vendors have 3.3v indicated on their sense pins, 			 * but 5v specified in the CIS or vice-versa.  I've			 * had it.  My only recommendation is "let the buyer			 * beware".  Your system might supply 5v to a 3v card			 * (possibly causing damage) or a 3v capable system 			 * might supply 5v to a 3v capable card (wasting 			 * precious battery life).			 * My only recommendation (if you care) is to get 			 * yourself an extender card (I don't know where, I 			 * have only one myself) and a meter and test it for			 * yourself.			 */			goto next_entry;		}skipvcc:					WLAN_LOG_DEBUG(1, "link->conf.Vcc=%d\n", link->conf.Vcc);		/* Do we need to allocate an interrupt? */		/* HACK: due to a bad CIS....we ALWAYS need an interrupt */		/* if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) */			link->conf.Attributes |= CONF_ENABLE_IRQ;		/* IO window settings */		link->io.NumPorts1 = link->io.NumPorts2 = 0;		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;			if (!(io->flags & CISTPL_IO_8BIT))				link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;			if (!(io->flags & CISTPL_IO_16BIT))				link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;			link->io.BasePort1 = io->win[0].base;			if  ( link->io.BasePort1 != 0 ) {				WLAN_LOG_WARNING(				"Brain damaged CIS: hard coded iobase="				"0x%x, try letting pcmcia_cs decide...\n",				link->io.BasePort1 );				link->io.BasePort1 = 0;			}			link->io.NumPorts1 = io->win[0].len;			if (io->nwin > 1) {				link->io.Attributes2 = link->io.Attributes1;				link->io.BasePort2 = io->win[1].base;				link->io.NumPorts2 = io->win[1].len;			}		}		/* This reserves IO space but doesn't actually enable it */		CFG_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));		/* If we got this far, we're cool! */		break;next_entry:		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)			dflt = *cfg;		CS_CHECK(GetNextTuple,                         pcmcia_get_next_tuple(handle, &tuple));	}	/* Allocate an interrupt line.  Note that this does not assign a */	/* handler to the interrupt, unless the 'Handler' member of the */	/* irq structure is initialized. */	if (link->conf.Attributes & CONF_ENABLE_IRQ)	{#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) )		int			i;		link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;		if (irq_list[0] == -1)			link->irq.IRQInfo2 = irq_mask;		else			for (i=0; i<4; i++)				link->irq.IRQInfo2 |= 1 << irq_list[i];#else		link->irq.IRQInfo1 = IRQ_LEVEL_ID;#endif		link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;		link->irq.Handler = hfa384x_interrupt;		link->irq.Instance = wlandev;		CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));	}	/* This actually configures the PCMCIA socket -- setting up */	/* the I/O windows and the interrupt mapping, and putting the */	/* card and host interface into "Memory and IO" mode. */	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));	/* Fill the netdevice with this info */	wlandev->netdev->irq = link->irq.AssignedIRQ;	wlandev->netdev->base_addr = link->io.BasePort1;	/* Report what we've done */	WLAN_LOG_INFO("%s: index 0x%02x: Vcc %d.%d", 		dev_info, link->conf.ConfigIndex, 		link->conf.Vcc/10, link->conf.Vcc%10);	if (link->conf.Vpp1)		printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);	if (link->conf.Attributes & CONF_ENABLE_IRQ)		printk(", irq %d", link->irq.AssignedIRQ);	if (link->io.NumPorts1)		printk(", io 0x%04x-0x%04x", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1-1);	if (link->io.NumPorts2)		printk(" & 0x%04x-0x%04x", link->io.BasePort2, link->io.BasePort2+link->io.NumPorts2-1);	printk("\n");	link->state &= ~DEV_CONFIG_PENDING;	/* Let pcmcia know the device name */	link->dev = &hw->node;	/* Register the network device and get assigned a name */	SET_MODULE_OWNER(wlandev->netdev);#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) )	SET_NETDEV_DEV(wlandev->netdev,  &handle_to_dev(link->handle));#endif	if (register_wlandev(wlandev) != 0) {		WLAN_LOG_NOTICE("prism2sta_cs: register_wlandev() failed.\n");		goto failed;	}	strcpy(hw->node.dev_name, wlandev->name);	/* Any device custom config/query stuff should be done here */	/* For a netdevice, we should at least grab the mac address */	return;cs_failed:	cs_error(link->handle, last_fn, last_ret);	WLAN_LOG_ERROR("NextTuple failure? It's probably a Vcc mismatch.\n");failed:	prism2sta_release((u_long)link);	return;}/*----------------------------------------------------------------* prism2sta_release** Half of the config/release pair.  Usually called in response to * a card ejection event.  Checks to make sure no higher layers* are still (or think they are) using the card via the link->open* field.  ** NOTE: Don't forget to increment the link->open variable in the *  device_open method, and decrement it in the device_close *  method.** Arguments:*	arg	a generic 32 bit variable.  It's the value that*		we assigned to link->release.data in sta_attach().** Returns: *	nothing** Side effects:*	All resources should be released after this function*	executes and finds the device !open.** Call context:*	Possibly in a timer context.  Don't do anything that'll*	block.----------------------------------------------------------------*/void prism2sta_release(u_long arg){        dev_link_t	*link = (dev_link_t *)arg;

⌨️ 快捷键说明

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