diff options
Diffstat (limited to 'drivers/net/wireless/hostap/hostap_cs.c')
| -rw-r--r-- | drivers/net/wireless/hostap/hostap_cs.c | 227 | 
1 files changed, 108 insertions, 119 deletions
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 3b4e55cf33c..3d914dde5de 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -532,145 +532,134 @@ static void prism2_detach(struct pcmcia_device *link)  #define CS_CHECK(fn, ret) \  do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -#define CFG_CHECK2(fn, retf) \ -do { int _ret = (retf); \ -if (_ret != 0) { \ -	PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", _ret); \ -	cs_error(link, fn, _ret); \ -	goto next_entry; \ -} \ -} while (0) -  /* run after a CARD_INSERTION event is received to configure the PCMCIA   * socket and make the device available to the system */ + +struct prism2_config_data { +	cistpl_cftable_entry_t dflt; +	config_info_t conf; +}; + +static int prism2_config_check(struct pcmcia_device *p_dev, +			       cistpl_cftable_entry_t *cfg, +			       void *priv_data) +{ +	struct prism2_config_data *cfg_mem = priv_data; + +	if (cfg->flags & CISTPL_CFTABLE_DEFAULT) +		cfg_mem->dflt = *cfg; +	if (cfg->index == 0) +		return -ENODEV; + +	p_dev->conf.ConfigIndex = cfg->index; +	PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X " +	       "(default 0x%02X)\n", cfg->index, cfg_mem->dflt.index); + +	/* Does this card need audio output? */ +	if (cfg->flags & CISTPL_CFTABLE_AUDIO) { +		p_dev->conf.Attributes |= CONF_ENABLE_SPKR; +		p_dev->conf.Status = CCSR_AUDIO_ENA; +	} + +	/* 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)) { +		if (cfg_mem->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / +		    10000 && !ignore_cis_vcc) { +			PDEBUG(DEBUG_EXTRA, "  Vcc mismatch - skipping" +			       " this entry\n"); +			return -ENODEV; +		} +	} else if (cfg_mem->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { +		if (cfg_mem->conf.Vcc != cfg_mem->dflt.vcc.param[CISTPL_POWER_VNOM] / +		    10000 && !ignore_cis_vcc) { +			PDEBUG(DEBUG_EXTRA, "  Vcc (default) mismatch " +			       "- skipping this entry\n"); +			return -ENODEV; +		} +	} + +	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) +		p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; +	else if (cfg_mem->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) +		p_dev->conf.Vpp = cfg_mem->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; + +	/* Do we need to allocate an interrupt? */ +	if (cfg->irq.IRQInfo1 || cfg_mem->dflt.irq.IRQInfo1) +		p_dev->conf.Attributes |= CONF_ENABLE_IRQ; +	else if (!(p_dev->conf.Attributes & CONF_ENABLE_IRQ)) { +		/* At least Compaq WL200 does not have IRQInfo1 set, +		 * but it does not work without interrupts.. */ +		printk(KERN_WARNING "Config has no IRQ info, but trying to " +		       "enable IRQ anyway..\n"); +		p_dev->conf.Attributes |= CONF_ENABLE_IRQ; +	} + +	/* IO window settings */ +	PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d " +	       "cfg_mem->dflt.io.nwin=%d\n", +	       cfg->io.nwin, cfg_mem->dflt.io.nwin); +	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; +	if ((cfg->io.nwin > 0) || (cfg_mem->dflt.io.nwin > 0)) { +		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &cfg_mem->dflt.io; +		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; +		PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, " +		       "io.base=0x%04x, len=%d\n", io->flags, +		       io->win[0].base, io->win[0].len); +		if (!(io->flags & CISTPL_IO_8BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; +		if (!(io->flags & CISTPL_IO_16BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; +		p_dev->io.IOAddrLines = io->flags & +			CISTPL_IO_LINES_MASK; +		p_dev->io.BasePort1 = io->win[0].base; +		p_dev->io.NumPorts1 = io->win[0].len; +		if (io->nwin > 1) { +			p_dev->io.Attributes2 = p_dev->io.Attributes1; +			p_dev->io.BasePort2 = io->win[1].base; +			p_dev->io.NumPorts2 = io->win[1].len; +		} +	} + +	/* This reserves IO space but doesn't actually enable it */ +	return pcmcia_request_io(p_dev, &p_dev->io); +} +  static int prism2_config(struct pcmcia_device *link)  {  	struct net_device *dev;  	struct hostap_interface *iface; +	struct prism2_config_data *cfg_mem;  	local_info_t *local;  	int ret = 1; -	tuple_t tuple; -	cisparse_t *parse;  	int last_fn, last_ret; -	u_char buf[64]; -	config_info_t conf; -	cistpl_cftable_entry_t dflt = { 0 };  	struct hostap_cs_priv *hw_priv;  	PDEBUG(DEBUG_FLOW, "prism2_config()\n"); -	parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); +	cfg_mem = kzalloc(sizeof(struct prism2_config_data), GFP_KERNEL); +	if (!cfg_mem) +		return -ENOMEM; +  	hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); -	if (parse == NULL || hw_priv == NULL) { +	if (hw_priv == NULL) {  		ret = -ENOMEM;  		goto failed;  	} -	tuple.Attributes = 0; -	tuple.TupleData = buf; -	tuple.TupleDataMax = sizeof(buf); -	tuple.TupleOffset = 0; -  	CS_CHECK(GetConfigurationInfo, -		 pcmcia_get_configuration_info(link, &conf)); +		 pcmcia_get_configuration_info(link, &cfg_mem->conf));  	/* Look for an appropriate configuration table entry in the CIS */ -	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; -	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); -	for (;;) { -		cistpl_cftable_entry_t *cfg = &(parse->cftable_entry); -		CFG_CHECK2(GetTupleData, -			   pcmcia_get_tuple_data(link, &tuple)); -		CFG_CHECK2(ParseTuple, -			   pcmcia_parse_tuple(link, &tuple, parse)); - -		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) -			dflt = *cfg; -		if (cfg->index == 0) -			goto next_entry; -		link->conf.ConfigIndex = cfg->index; -		PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X " -		       "(default 0x%02X)\n", cfg->index, dflt.index); - -		/* Does this card need audio output? */ -		if (cfg->flags & CISTPL_CFTABLE_AUDIO) { -			link->conf.Attributes |= CONF_ENABLE_SPKR; -			link->conf.Status = CCSR_AUDIO_ENA; -		} - -		/* 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)) { -			if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / -			    10000 && !ignore_cis_vcc) { -				PDEBUG(DEBUG_EXTRA, "  Vcc mismatch - skipping" -				       " this entry\n"); -				goto next_entry; -			} -		} else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { -			if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / -			    10000 && !ignore_cis_vcc) { -				PDEBUG(DEBUG_EXTRA, "  Vcc (default) mismatch " -				       "- skipping this entry\n"); -				goto next_entry; -			} -		} - -		if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) -			link->conf.Vpp = -				cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; -		else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) -			link->conf.Vpp = -				dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; - -		/* Do we need to allocate an interrupt? */ -		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) -			link->conf.Attributes |= CONF_ENABLE_IRQ; -		else if (!(link->conf.Attributes & CONF_ENABLE_IRQ)) { -			/* At least Compaq WL200 does not have IRQInfo1 set, -			 * but it does not work without interrupts.. */ -			printk("Config has no IRQ info, but trying to enable " -			       "IRQ anyway..\n"); -			link->conf.Attributes |= CONF_ENABLE_IRQ; -		} - -		/* IO window settings */ -		PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d " -		       "dflt.io.nwin=%d\n", -		       cfg->io.nwin, dflt.io.nwin); -		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; -			PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, " -			       "io.base=0x%04x, len=%d\n", io->flags, -			       io->win[0].base, io->win[0].len); -			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.IOAddrLines = io->flags & -				CISTPL_IO_LINES_MASK; -			link->io.BasePort1 = io->win[0].base; -			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_CHECK2(RequestIO, -			   pcmcia_request_io(link, &link->io)); - -		/* This configuration table entry is OK */ -		break; - -	next_entry: -		CS_CHECK(GetNextTuple, -			 pcmcia_get_next_tuple(link, &tuple)); +	last_ret = pcmcia_loop_config(link, prism2_config_check, cfg_mem); +	if (last_ret) { +		if (!ignore_cis_vcc) +			printk(KERN_ERR "GetNextTuple(): No matching " +			       "CIS configuration.  Maybe you need the " +			       "ignore_cis_vcc=1 parameter.\n"); +		cs_error(link, RequestIO, last_ret); +		goto failed;  	}  	/* Need to allocate net_device before requesting IRQ handler */ @@ -738,15 +727,15 @@ static int prism2_config(struct pcmcia_device *link)  		if (ret == 0 && local->ddev)  			strcpy(hw_priv->node.dev_name, local->ddev->name);  	} -	kfree(parse); +	kfree(cfg_mem);  	return ret;   cs_failed:  	cs_error(link, last_fn, last_ret);   failed: -	kfree(parse);  	kfree(hw_priv); +	kfree(cfg_mem);  	prism2_release((u_long)link);  	return ret;  }  |